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 unsigned char key[256] = {}; 14 u16 udp_test_port = 7777; 15 u32 authsize, key_len; 16 char algo[128] = {}; 17 char dst[16] = {}, dst_bad[8] = {}; 18 int status; 19 20 static 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 53 SEC("syscall") 54 int 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(¶ms.algo, algo, sizeof(algo)); 71 __builtin_memcpy(¶ms.key, key, sizeof(key)); 72 73 cctx = bpf_crypto_ctx_create(¶ms, 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 85 SEC("tc") 86 int 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); 128 err: 129 return TC_ACT_SHOT; 130 } 131 132 SEC("tc") 133 int 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); 175 err: 176 return TC_ACT_SHOT; 177 } 178 179 char __license[] SEC("license") = "GPL"; 180