xref: /linux/tools/testing/selftests/bpf/progs/crypto_bench.c (revision e4287bf34f97a88c7d9322f5bde828724c073a6b)
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 
13 const volatile unsigned int len = 16;
14 /*
15  * cipher[] and key[] are 8-byte aligned and 'params' is kept off the stack to
16  * work around an LLVM code generation bug. clang lowers the memcpy() of these
17  * byte-aligned globals into a per-byte load/store sequence staged on the stack,
18  * and additionally materializes the on-stack 'struct bpf_crypto_params' twice.
19  * Both blow the 512-byte BPF stack limit. Aligning the sources lets clang copy
20  * word-wise, and a global 'params' removes the large object from the stack.
21  */
22 char cipher[128] __attribute__((aligned(8))) = {};
23 u32 key_len, authsize;
24 char dst[256] = {};
25 u8 key[256] __attribute__((aligned(8))) = {};
26 static struct bpf_crypto_params params;
27 long hits = 0;
28 int status;
29 
30 SEC("syscall")
31 int crypto_setup(void *args)
32 {
33 	struct bpf_crypto_ctx *cctx;
34 	int err = 0;
35 
36 	status = 0;
37 
38 	if (!cipher[0] || !key_len || key_len > 256) {
39 		status = -EINVAL;
40 		return 0;
41 	}
42 
43 	__builtin_memcpy(&params.type, "skcipher", sizeof("skcipher"));
44 	params.key_len = key_len;
45 	params.authsize = authsize;
46 	__builtin_memcpy(&params.algo, cipher, sizeof(cipher));
47 	__builtin_memcpy(&params.key, key, sizeof(key));
48 	cctx = bpf_crypto_ctx_create(&params, sizeof(params), &err);
49 
50 	if (!cctx) {
51 		status = err;
52 		return 0;
53 	}
54 
55 	err = crypto_ctx_insert(cctx);
56 	if (err && err != -EEXIST)
57 		status = err;
58 
59 	return 0;
60 }
61 
62 SEC("tc")
63 int crypto_encrypt(struct __sk_buff *skb)
64 {
65 	struct __crypto_ctx_value *v;
66 	struct bpf_crypto_ctx *ctx;
67 	struct bpf_dynptr psrc, pdst;
68 
69 	v = crypto_ctx_value_lookup();
70 	if (!v) {
71 		status = -ENOENT;
72 		return 0;
73 	}
74 
75 	ctx = v->ctx;
76 	if (!ctx) {
77 		status = -ENOENT;
78 		return 0;
79 	}
80 
81 	bpf_dynptr_from_skb(skb, 0, &psrc);
82 	bpf_dynptr_from_mem(dst, len, 0, &pdst);
83 
84 	status = bpf_crypto_encrypt(ctx, &psrc, &pdst, NULL);
85 	__sync_add_and_fetch(&hits, 1);
86 
87 	return 0;
88 }
89 
90 SEC("tc")
91 int crypto_decrypt(struct __sk_buff *skb)
92 {
93 	struct bpf_dynptr psrc, pdst;
94 	struct __crypto_ctx_value *v;
95 	struct bpf_crypto_ctx *ctx;
96 
97 	v = crypto_ctx_value_lookup();
98 	if (!v)
99 		return -ENOENT;
100 
101 	ctx = v->ctx;
102 	if (!ctx)
103 		return -ENOENT;
104 
105 	bpf_dynptr_from_skb(skb, 0, &psrc);
106 	bpf_dynptr_from_mem(dst, len, 0, &pdst);
107 
108 	status = bpf_crypto_decrypt(ctx, &psrc, &pdst, NULL);
109 	__sync_add_and_fetch(&hits, 1);
110 
111 	return 0;
112 }
113 
114 char __license[] SEC("license") = "GPL";
115