1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Copyright 2019 Google LLC 4 * Copyright (c) Linux Test Project, 2019-2021 5 */ 6 7#include <errno.h> 8#include <stdlib.h> 9 10#define TST_NO_DEFAULT_MAIN 11#include "tst_test.h" 12#include "tst_af_alg.h" 13#include "lapi/socket.h" 14 15int tst_alg_create(void) 16{ 17 const long ret = socket(AF_ALG, SOCK_SEQPACKET, 0); 18 19 if (ret >= 0) 20 return ret; 21 if (errno == EAFNOSUPPORT) 22 tst_brk(TCONF, "kernel doesn't support AF_ALG"); 23 tst_brk(TBROK | TERRNO, "unexpected error creating AF_ALG socket"); 24 return -1; 25} 26 27void tst_alg_bind_addr(int algfd, const struct sockaddr_alg *addr) 28{ 29 const long ret = bind(algfd, (const struct sockaddr *)addr, 30 sizeof(*addr)); 31 32 if (ret == 0) 33 return; 34 35 if (errno == ELIBBAD && tst_fips_enabled()) { 36 tst_brk(TCONF, 37 "FIPS enabled => %s algorithm '%s' disabled", 38 addr->salg_type, addr->salg_name); 39 } 40 41 if (errno == ENOENT) { 42 tst_brk(TCONF, "kernel doesn't support %s algorithm '%s'", 43 addr->salg_type, addr->salg_name); 44 } 45 46 tst_brk(TBROK | TERRNO, 47 "unexpected error binding AF_ALG socket to %s algorithm '%s'", 48 addr->salg_type, addr->salg_name); 49} 50 51static void init_sockaddr_alg(struct sockaddr_alg *addr, 52 const char *algtype, const char *algname) 53{ 54 memset(addr, 0, sizeof(*addr)); 55 56 addr->salg_family = AF_ALG; 57 58 strncpy((char *)addr->salg_type, algtype, sizeof(addr->salg_type)); 59 if (addr->salg_type[sizeof(addr->salg_type) - 1] != '\0') 60 tst_brk(TBROK, "algorithm type too long: '%s'", algtype); 61 62 strncpy((char *)addr->salg_name, algname, sizeof(addr->salg_name)); 63 if (addr->salg_name[sizeof(addr->salg_name) - 1] != '\0') 64 tst_brk(TBROK, "algorithm name too long: '%s'", algname); 65} 66 67void tst_alg_bind(int algfd, const char *algtype, const char *algname) 68{ 69 struct sockaddr_alg addr; 70 71 init_sockaddr_alg(&addr, algtype, algname); 72 73 tst_alg_bind_addr(algfd, &addr); 74} 75 76int tst_try_alg(const char *algtype, const char *algname) 77{ 78 long ret; 79 int retval = 0; 80 int algfd; 81 struct sockaddr_alg addr; 82 83 algfd = tst_alg_create(); 84 85 init_sockaddr_alg(&addr, algtype, algname); 86 87 ret = bind(algfd, (const struct sockaddr *)&addr, sizeof(addr)); 88 89 if (ret != 0) 90 retval = errno; 91 92 close(algfd); 93 return retval; 94} 95 96bool tst_have_alg(const char *algtype, const char *algname) 97{ 98 int ret; 99 100 ret = tst_try_alg(algtype, algname); 101 102 switch (ret) { 103 case 0: 104 return true; 105 case ENOENT: 106 tst_res(TCONF, "kernel doesn't have %s algorithm '%s'", 107 algtype, algname); 108 return false; 109 case ELIBBAD: 110 if (tst_fips_enabled()) { 111 tst_res(TCONF, 112 "FIPS enabled => %s algorithm '%s' disabled", 113 algtype, algname); 114 return false; 115 } 116 /* fallthrough */ 117 default: 118 errno = ret; 119 tst_brk(TBROK | TERRNO, 120 "unexpected error binding AF_ALG socket to %s algorithm '%s'", 121 algtype, algname); 122 return false; 123 } 124} 125 126void tst_require_alg(const char *algtype, const char *algname) 127{ 128 int algfd = tst_alg_create(); 129 130 tst_alg_bind(algfd, algtype, algname); 131 132 close(algfd); 133} 134 135void tst_alg_setkey(int algfd, const uint8_t *key, unsigned int keylen) 136{ 137 long ret; 138 uint8_t *keybuf = NULL; 139 unsigned int i; 140 141 if (key == NULL) { 142 /* generate a random key */ 143 keybuf = SAFE_MALLOC(keylen); 144 for (i = 0; i < keylen; i++) 145 keybuf[i] = rand(); 146 key = keybuf; 147 } 148 ret = setsockopt(algfd, SOL_ALG, ALG_SET_KEY, key, keylen); 149 if (ret != 0) { 150 tst_brk(TBROK | TERRNO, 151 "unexpected error setting key (len=%u)", keylen); 152 } 153 free(keybuf); 154} 155 156int tst_alg_accept(int algfd) 157{ 158 const long ret = accept(algfd, NULL, NULL); 159 160 if (ret < 0) { 161 tst_brk(TBROK | TERRNO, 162 "unexpected error accept()ing AF_ALG request socket"); 163 } 164 return ret; 165} 166 167int tst_alg_setup(const char *algtype, const char *algname, 168 const uint8_t *key, unsigned int keylen) 169{ 170 int algfd = tst_alg_create(); 171 172 tst_alg_bind(algfd, algtype, algname); 173 174 if (keylen != 0) 175 tst_alg_setkey(algfd, key, keylen); 176 177 return algfd; 178} 179 180int tst_alg_setup_reqfd(const char *algtype, const char *algname, 181 const uint8_t *key, unsigned int keylen) 182{ 183 int algfd = tst_alg_setup(algtype, algname, key, keylen); 184 int reqfd = tst_alg_accept(algfd); 185 186 close(algfd); 187 return reqfd; 188} 189 190void tst_alg_sendmsg(int reqfd, const void *data, size_t datalen, 191 const struct tst_alg_sendmsg_params *params) 192{ 193 struct iovec iov = { 194 .iov_base = (void *)data, 195 .iov_len = datalen, 196 }; 197 struct msghdr msg = { 198 .msg_iov = &iov, 199 .msg_iovlen = 1, 200 .msg_flags = params->msg_flags, 201 }; 202 size_t controllen; 203 uint8_t *control; 204 struct cmsghdr *cmsg; 205 struct af_alg_iv *alg_iv; 206 207 if (params->encrypt && params->decrypt) 208 tst_brk(TBROK, "Both encrypt and decrypt are specified"); 209 210 controllen = 0; 211 if (params->encrypt || params->decrypt) 212 controllen += CMSG_SPACE(sizeof(uint32_t)); 213 if (params->ivlen) 214 controllen += CMSG_SPACE(sizeof(struct af_alg_iv) + 215 params->ivlen); 216 if (params->assoclen) 217 controllen += CMSG_SPACE(sizeof(uint32_t)); 218 219 control = SAFE_MALLOC(controllen); 220 memset(control, 0, controllen); 221 msg.msg_control = control; 222 msg.msg_controllen = controllen; 223 cmsg = CMSG_FIRSTHDR(&msg); 224 225 if (params->encrypt || params->decrypt) { 226 cmsg->cmsg_level = SOL_ALG; 227 cmsg->cmsg_type = ALG_SET_OP; 228 cmsg->cmsg_len = CMSG_LEN(sizeof(uint32_t)); 229 *(uint32_t *)CMSG_DATA(cmsg) = 230 params->encrypt ? ALG_OP_ENCRYPT : ALG_OP_DECRYPT; 231 cmsg = CMSG_NXTHDR(&msg, cmsg); 232 } 233 if (params->ivlen) { 234 cmsg->cmsg_level = SOL_ALG; 235 cmsg->cmsg_type = ALG_SET_IV; 236 cmsg->cmsg_len = CMSG_LEN(sizeof(struct af_alg_iv) + 237 params->ivlen); 238 alg_iv = (struct af_alg_iv *)CMSG_DATA(cmsg); 239 alg_iv->ivlen = params->ivlen; 240 memcpy(alg_iv->iv, params->iv, params->ivlen); 241 cmsg = CMSG_NXTHDR(&msg, cmsg); 242 } 243 if (params->assoclen) { 244 cmsg->cmsg_level = SOL_ALG; 245 cmsg->cmsg_type = ALG_SET_AEAD_ASSOCLEN; 246 cmsg->cmsg_len = CMSG_LEN(sizeof(uint32_t)); 247 *(uint32_t *)CMSG_DATA(cmsg) = params->assoclen; 248 cmsg = CMSG_NXTHDR(&msg, cmsg); 249 } 250 251 SAFE_SENDMSG(datalen, reqfd, &msg, 0); 252} 253