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(¶ms.type, "skcipher", sizeof("skcipher")); 44 params.key_len = key_len; 45 params.authsize = authsize; 46 __builtin_memcpy(¶ms.algo, cipher, sizeof(cipher)); 47 __builtin_memcpy(¶ms.key, key, sizeof(key)); 48 cctx = bpf_crypto_ctx_create(¶ms, 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