Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.8.
  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] = {};
 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 = 0;
 63
 64	status = 0;
 65
 66	if (key_len > 256) {
 67		status = -EINVAL;
 68		return 0;
 69	}
 70
 71	__builtin_memcpy(&params.algo, algo, sizeof(algo));
 72	__builtin_memcpy(&params.key, key, sizeof(key));
 73	cctx = bpf_crypto_ctx_create(&params, sizeof(params), &err);
 74
 75	if (!cctx) {
 76		status = err;
 77		return 0;
 78	}
 79
 80	err = crypto_ctx_insert(cctx);
 81	if (err && err != -EEXIST)
 82		status = err;
 83
 84	return 0;
 85}
 86
 87SEC("tc")
 88int decrypt_sanity(struct __sk_buff *skb)
 89{
 90	struct __crypto_ctx_value *v;
 91	struct bpf_crypto_ctx *ctx;
 92	struct bpf_dynptr psrc, pdst;
 93	int err;
 94
 95	err = skb_dynptr_validate(skb, &psrc);
 96	if (err < 0) {
 97		status = err;
 98		return TC_ACT_SHOT;
 99	}
100
101	v = crypto_ctx_value_lookup();
102	if (!v) {
103		status = -ENOENT;
104		return TC_ACT_SHOT;
105	}
106
107	ctx = v->ctx;
108	if (!ctx) {
109		status = -ENOENT;
110		return TC_ACT_SHOT;
111	}
112
113	/* dst is a global variable to make testing part easier to check. In real
114	 * production code, a percpu map should be used to store the result.
115	 */
116	bpf_dynptr_from_mem(dst, sizeof(dst), 0, &pdst);
117
118	status = bpf_crypto_decrypt(ctx, &psrc, &pdst, NULL);
119
120	return TC_ACT_SHOT;
121}
122
123SEC("tc")
124int encrypt_sanity(struct __sk_buff *skb)
125{
126	struct __crypto_ctx_value *v;
127	struct bpf_crypto_ctx *ctx;
128	struct bpf_dynptr psrc, pdst;
129	int err;
130
131	status = 0;
132
133	err = skb_dynptr_validate(skb, &psrc);
134	if (err < 0) {
135		status = err;
136		return TC_ACT_SHOT;
137	}
138
139	v = crypto_ctx_value_lookup();
140	if (!v) {
141		status = -ENOENT;
142		return TC_ACT_SHOT;
143	}
144
145	ctx = v->ctx;
146	if (!ctx) {
147		status = -ENOENT;
148		return TC_ACT_SHOT;
149	}
150
151	/* dst is a global variable to make testing part easier to check. In real
152	 * production code, a percpu map should be used to store the result.
153	 */
154	bpf_dynptr_from_mem(dst, sizeof(dst), 0, &pdst);
155
156	status = bpf_crypto_encrypt(ctx, &psrc, &pdst, NULL);
157
158	return TC_ACT_SHOT;
159}
160
161char __license[] SEC("license") = "GPL";