File Index
Files and directories
Sign in
FILE

crypto_sanity.c

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/bpf/progs/crypto_sanity.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/* Copyright (c) 2024 Meta Platforms, Inc. and affiliates. */
  3
  4#include "vmlinux.h"
  5#include "bpf_tracing_net.h"
  6#include <bpf/bpf_helpers.h>
  7#include <bpf/bpf_endian.h>
  8#include <bpf/bpf_tracing.h>
  9#include "bpf_misc.h"
 10#include "bpf_kfuncs.h"
 11#include "crypto_common.h"
 12
 13unsigned char key[256] = {};
 14u16 udp_test_port = 7777;
 15u32 authsize, key_len;
 16char algo[128] = {};
 17char dst[16] = {}, dst_bad[8] = {};
 18int status;
 19
 20static int skb_dynptr_validate(struct __sk_buff *skb, struct bpf_dynptr *psrc)
 21{
 22	struct ipv6hdr ip6h;
 23	struct udphdr udph;
 24	u32 offset;
 25
 26	if (skb->protocol != __bpf_constant_htons(ETH_P_IPV6))
 27		return -1;
 28
 29	if (bpf_skb_load_bytes(skb, ETH_HLEN, &ip6h, sizeof(ip6h)))
 30		return -1;
 31
 32	if (ip6h.nexthdr != IPPROTO_UDP)
 33		return -1;
 34
 35	if (bpf_skb_load_bytes(skb, ETH_HLEN + sizeof(ip6h), &udph, sizeof(udph)))
 36		return -1;
 37
 38	if (udph.dest != __bpf_htons(udp_test_port))
 39		return -1;
 40
 41	offset = ETH_HLEN + sizeof(ip6h) + sizeof(udph);
 42	if (skb->len < offset + 16)
 43		return -1;
 44
 45	/* let's make sure that 16 bytes of payload are in the linear part of skb */
 46	bpf_skb_pull_data(skb, offset + 16);
 47	bpf_dynptr_from_skb(skb, 0, psrc);
 48	bpf_dynptr_adjust(psrc, offset, offset + 16);
 49
 50	return 0;
 51}
 52
 53SEC("syscall")
 54int skb_crypto_setup(void *ctx)
 55{
 56	struct bpf_crypto_params params = {
 57		.type = "skcipher",
 58		.key_len = key_len,
 59		.authsize = authsize,
 60	};
 61	struct bpf_crypto_ctx *cctx;
 62	int err;
 63
 64	status = 0;
 65	if (key_len > 256) {
 66		status = -EINVAL;
 67		return 0;
 68	}
 69
 70	__builtin_memcpy(&params.algo, algo, sizeof(algo));
 71	__builtin_memcpy(&params.key, key, sizeof(key));
 72
 73	cctx = bpf_crypto_ctx_create(&params, sizeof(params), &err);
 74	if (!cctx) {
 75		status = err;
 76		return 0;
 77	}
 78
 79	err = crypto_ctx_insert(cctx);
 80	if (err && err != -EEXIST)
 81		status = err;
 82	return 0;
 83}
 84
 85SEC("tc")
 86int decrypt_sanity(struct __sk_buff *skb)
 87{
 88	struct __crypto_ctx_value *v;
 89	struct bpf_crypto_ctx *ctx;
 90	struct bpf_dynptr psrc, pdst;
 91	int err;
 92
 93	status = 0;
 94	err = skb_dynptr_validate(skb, &psrc);
 95	if (err < 0) {
 96		status = err;
 97		return TC_ACT_SHOT;
 98	}
 99
100	v = crypto_ctx_value_lookup();
101	if (!v) {
102		status = -ENOENT;
103		return TC_ACT_SHOT;
104	}
105
106	ctx = v->ctx;
107	if (!ctx) {
108		status = -ENOENT;
109		return TC_ACT_SHOT;
110	}
111
112	/* Check also bad case where the dst buffer is smaller than the
113	 * skb's linear section.
114	 */
115	bpf_dynptr_from_mem(dst_bad, sizeof(dst_bad), 0, &pdst);
116	status = bpf_crypto_decrypt(ctx, &psrc, &pdst, NULL);
117	if (!status)
118		status = -EIO;
119	if (status != -EINVAL)
120		goto err;
121
122	/* dst is a global variable to make testing part easier to check.
123	 * In real production code, a percpu map should be used to store
124	 * the result.
125	 */
126	bpf_dynptr_from_mem(dst, sizeof(dst), 0, &pdst);
127	status = bpf_crypto_decrypt(ctx, &psrc, &pdst, NULL);
128err:
129	return TC_ACT_SHOT;
130}
131
132SEC("tc")
133int encrypt_sanity(struct __sk_buff *skb)
134{
135	struct __crypto_ctx_value *v;
136	struct bpf_crypto_ctx *ctx;
137	struct bpf_dynptr psrc, pdst;
138	int err;
139
140	status = 0;
141	err = skb_dynptr_validate(skb, &psrc);
142	if (err < 0) {
143		status = err;
144		return TC_ACT_SHOT;
145	}
146
147	v = crypto_ctx_value_lookup();
148	if (!v) {
149		status = -ENOENT;
150		return TC_ACT_SHOT;
151	}
152
153	ctx = v->ctx;
154	if (!ctx) {
155		status = -ENOENT;
156		return TC_ACT_SHOT;
157	}
158
159	/* Check also bad case where the dst buffer is smaller than the
160	 * skb's linear section.
161	 */
162	bpf_dynptr_from_mem(dst_bad, sizeof(dst_bad), 0, &pdst);
163	status = bpf_crypto_encrypt(ctx, &psrc, &pdst, NULL);
164	if (!status)
165		status = -EIO;
166	if (status != -EINVAL)
167		goto err;
168
169	/* dst is a global variable to make testing part easier to check.
170	 * In real production code, a percpu map should be used to store
171	 * the result.
172	 */
173	bpf_dynptr_from_mem(dst, sizeof(dst), 0, &pdst);
174	status = bpf_crypto_encrypt(ctx, &psrc, &pdst, NULL);
175err:
176	return TC_ACT_SHOT;
177}
178
179char __license[] SEC("license") = "GPL";
~/ Read-only file preview.