1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (c) 2024 Meta Platforms, Inc. and affiliates. */ 3 4 #include <sys/types.h> 5 #include <sys/socket.h> 6 #include <net/if.h> 7 #include <linux/in6.h> 8 #include <linux/if_alg.h> 9 10 #include "test_progs.h" 11 #include "network_helpers.h" 12 #include "crypto_sanity.skel.h" 13 #include "crypto_basic.skel.h" 14 15 #define NS_TEST "crypto_sanity_ns" 16 #define IPV6_IFACE_ADDR "face::1" 17 static const unsigned char crypto_key[] = "testtest12345678"; 18 static const char plain_text[] = "stringtoencrypt0"; 19 static int opfd = -1, tfmfd = -1; 20 static const char algo[] = "ecb(aes)"; 21 static int init_afalg(void) 22 { 23 struct sockaddr_alg sa = { 24 .salg_family = AF_ALG, 25 .salg_type = "skcipher", 26 .salg_name = "ecb(aes)" 27 }; 28 29 tfmfd = socket(AF_ALG, SOCK_SEQPACKET, 0); 30 if (tfmfd == -1) 31 return errno; 32 if (bind(tfmfd, (struct sockaddr *)&sa, sizeof(sa)) == -1) 33 return errno; 34 if (setsockopt(tfmfd, SOL_ALG, ALG_SET_KEY, crypto_key, 16) == -1) 35 return errno; 36 opfd = accept(tfmfd, NULL, 0); 37 if (opfd == -1) 38 return errno; 39 return 0; 40 } 41 42 static void deinit_afalg(void) 43 { 44 if (tfmfd != -1) 45 close(tfmfd); 46 if (opfd != -1) 47 close(opfd); 48 } 49 50 static void do_crypt_afalg(const void *src, void *dst, int size, bool encrypt) 51 { 52 struct msghdr msg = {}; 53 struct cmsghdr *cmsg; 54 char cbuf[CMSG_SPACE(4)] = {0}; 55 struct iovec iov; 56 57 msg.msg_control = cbuf; 58 msg.msg_controllen = sizeof(cbuf); 59 60 cmsg = CMSG_FIRSTHDR(&msg); 61 cmsg->cmsg_level = SOL_ALG; 62 cmsg->cmsg_type = ALG_SET_OP; 63 cmsg->cmsg_len = CMSG_LEN(4); 64 *(__u32 *)CMSG_DATA(cmsg) = encrypt ? ALG_OP_ENCRYPT : ALG_OP_DECRYPT; 65 66 iov.iov_base = (char *)src; 67 iov.iov_len = size; 68 69 msg.msg_iov = &iov; 70 msg.msg_iovlen = 1; 71 72 sendmsg(opfd, &msg, 0); 73 read(opfd, dst, size); 74 } 75 76 void test_crypto_basic(void) 77 { 78 RUN_TESTS(crypto_basic); 79 } 80 81 void test_crypto_sanity(void) 82 { 83 LIBBPF_OPTS(bpf_tc_hook, qdisc_hook, .attach_point = BPF_TC_EGRESS); 84 LIBBPF_OPTS(bpf_tc_opts, tc_attach_enc); 85 LIBBPF_OPTS(bpf_tc_opts, tc_attach_dec); 86 LIBBPF_OPTS(bpf_test_run_opts, opts); 87 struct nstoken *nstoken = NULL; 88 struct crypto_sanity *skel; 89 char afalg_plain[16] = {0}; 90 char afalg_dst[16] = {0}; 91 struct sockaddr_in6 addr; 92 int sockfd, err, pfd; 93 socklen_t addrlen; 94 u16 udp_test_port; 95 96 skel = crypto_sanity__open_and_load(); 97 if (!ASSERT_OK_PTR(skel, "skel open")) 98 return; 99 100 SYS(fail, "ip netns add %s", NS_TEST); 101 SYS(fail, "ip -net %s -6 addr add %s/128 dev lo nodad", NS_TEST, IPV6_IFACE_ADDR); 102 SYS(fail, "ip -net %s link set dev lo up", NS_TEST); 103 104 nstoken = open_netns(NS_TEST); 105 if (!ASSERT_OK_PTR(nstoken, "open_netns")) 106 goto fail; 107 108 err = init_afalg(); 109 if (!ASSERT_OK(err, "AF_ALG init fail")) 110 goto fail; 111 112 qdisc_hook.ifindex = if_nametoindex("lo"); 113 if (!ASSERT_GT(qdisc_hook.ifindex, 0, "if_nametoindex lo")) 114 goto fail; 115 116 skel->bss->key_len = 16; 117 skel->bss->authsize = 0; 118 udp_test_port = skel->data->udp_test_port; 119 memcpy(skel->bss->key, crypto_key, sizeof(crypto_key)); 120 snprintf(skel->bss->algo, 128, "%s", algo); 121 pfd = bpf_program__fd(skel->progs.skb_crypto_setup); 122 if (!ASSERT_GT(pfd, 0, "skb_crypto_setup fd")) 123 goto fail; 124 125 err = bpf_prog_test_run_opts(pfd, &opts); 126 if (!ASSERT_OK(err, "skb_crypto_setup") || 127 !ASSERT_OK(opts.retval, "skb_crypto_setup retval")) 128 goto fail; 129 130 if (!ASSERT_OK(skel->bss->status, "skb_crypto_setup status")) 131 goto fail; 132 133 err = bpf_tc_hook_create(&qdisc_hook); 134 if (!ASSERT_OK(err, "create qdisc hook")) 135 goto fail; 136 137 addrlen = sizeof(addr); 138 err = make_sockaddr(AF_INET6, IPV6_IFACE_ADDR, udp_test_port, 139 (void *)&addr, &addrlen); 140 if (!ASSERT_OK(err, "make_sockaddr")) 141 goto fail; 142 143 tc_attach_enc.prog_fd = bpf_program__fd(skel->progs.encrypt_sanity); 144 err = bpf_tc_attach(&qdisc_hook, &tc_attach_enc); 145 if (!ASSERT_OK(err, "attach encrypt filter")) 146 goto fail; 147 148 sockfd = socket(AF_INET6, SOCK_DGRAM, 0); 149 if (!ASSERT_NEQ(sockfd, -1, "encrypt socket")) 150 goto fail; 151 err = sendto(sockfd, plain_text, sizeof(plain_text), 0, (void *)&addr, addrlen); 152 close(sockfd); 153 if (!ASSERT_EQ(err, sizeof(plain_text), "encrypt send")) 154 goto fail; 155 156 do_crypt_afalg(plain_text, afalg_dst, sizeof(afalg_dst), true); 157 158 if (!ASSERT_OK(skel->bss->status, "encrypt status")) 159 goto fail; 160 if (!ASSERT_STRNEQ(skel->bss->dst, afalg_dst, sizeof(afalg_dst), "encrypt AF_ALG")) 161 goto fail; 162 163 tc_attach_enc.flags = tc_attach_enc.prog_fd = tc_attach_enc.prog_id = 0; 164 err = bpf_tc_detach(&qdisc_hook, &tc_attach_enc); 165 if (!ASSERT_OK(err, "bpf_tc_detach encrypt")) 166 goto fail; 167 168 tc_attach_dec.prog_fd = bpf_program__fd(skel->progs.decrypt_sanity); 169 err = bpf_tc_attach(&qdisc_hook, &tc_attach_dec); 170 if (!ASSERT_OK(err, "attach decrypt filter")) 171 goto fail; 172 173 sockfd = socket(AF_INET6, SOCK_DGRAM, 0); 174 if (!ASSERT_NEQ(sockfd, -1, "decrypt socket")) 175 goto fail; 176 err = sendto(sockfd, afalg_dst, sizeof(afalg_dst), 0, (void *)&addr, addrlen); 177 close(sockfd); 178 if (!ASSERT_EQ(err, sizeof(afalg_dst), "decrypt send")) 179 goto fail; 180 181 do_crypt_afalg(afalg_dst, afalg_plain, sizeof(afalg_plain), false); 182 183 if (!ASSERT_OK(skel->bss->status, "decrypt status")) 184 goto fail; 185 if (!ASSERT_STRNEQ(skel->bss->dst, afalg_plain, sizeof(afalg_plain), "decrypt AF_ALG")) 186 goto fail; 187 188 tc_attach_dec.flags = tc_attach_dec.prog_fd = tc_attach_dec.prog_id = 0; 189 err = bpf_tc_detach(&qdisc_hook, &tc_attach_dec); 190 ASSERT_OK(err, "bpf_tc_detach decrypt"); 191 192 fail: 193 close_netns(nstoken); 194 deinit_afalg(); 195 SYS_NOFAIL("ip netns del " NS_TEST " &> /dev/null"); 196 crypto_sanity__destroy(skel); 197 } 198