From dbb41ce2b7f309d394054a6bd1e33afd578798a5 Mon Sep 17 00:00:00 2001 From: Manuel Bentele Date: Fri, 23 Oct 2020 15:18:01 +0200 Subject: Move the source code of all xloop components to the common 'src' directory --- src/kernel/tests/lib/tst_af_alg.c | 212 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 212 insertions(+) create mode 100644 src/kernel/tests/lib/tst_af_alg.c (limited to 'src/kernel/tests/lib/tst_af_alg.c') diff --git a/src/kernel/tests/lib/tst_af_alg.c b/src/kernel/tests/lib/tst_af_alg.c new file mode 100644 index 0000000..d3895a8 --- /dev/null +++ b/src/kernel/tests/lib/tst_af_alg.c @@ -0,0 +1,212 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright 2019 Google LLC + */ + +#include +#include + +#define TST_NO_DEFAULT_MAIN +#include "tst_test.h" +#include "tst_af_alg.h" +#include "lapi/socket.h" + +int tst_alg_create(void) +{ + TEST(socket(AF_ALG, SOCK_SEQPACKET, 0)); + if (TST_RET >= 0) + return TST_RET; + if (TST_ERR == EAFNOSUPPORT) + tst_brk(TCONF, "kernel doesn't support AF_ALG"); + tst_brk(TBROK | TTERRNO, "unexpected error creating AF_ALG socket"); + return -1; +} + +void tst_alg_bind_addr(int algfd, const struct sockaddr_alg *addr) +{ + TEST(bind(algfd, (const struct sockaddr *)addr, sizeof(*addr))); + if (TST_RET == 0) + return; + if (TST_ERR == ENOENT) { + tst_brk(TCONF, "kernel doesn't support %s algorithm '%s'", + addr->salg_type, addr->salg_name); + } + tst_brk(TBROK | TTERRNO, + "unexpected error binding AF_ALG socket to %s algorithm '%s'", + addr->salg_type, addr->salg_name); +} + +static void init_sockaddr_alg(struct sockaddr_alg *addr, + const char *algtype, const char *algname) +{ + memset(addr, 0, sizeof(*addr)); + + addr->salg_family = AF_ALG; + + strncpy((char *)addr->salg_type, algtype, sizeof(addr->salg_type)); + if (addr->salg_type[sizeof(addr->salg_type) - 1] != '\0') + tst_brk(TBROK, "algorithm type too long: '%s'", algtype); + + strncpy((char *)addr->salg_name, algname, sizeof(addr->salg_name)); + if (addr->salg_name[sizeof(addr->salg_name) - 1] != '\0') + tst_brk(TBROK, "algorithm name too long: '%s'", algname); +} + +void tst_alg_bind(int algfd, const char *algtype, const char *algname) +{ + struct sockaddr_alg addr; + + init_sockaddr_alg(&addr, algtype, algname); + + tst_alg_bind_addr(algfd, &addr); +} + +bool tst_have_alg(const char *algtype, const char *algname) +{ + int algfd; + struct sockaddr_alg addr; + bool have_alg = true; + + algfd = tst_alg_create(); + + init_sockaddr_alg(&addr, algtype, algname); + + TEST(bind(algfd, (const struct sockaddr *)&addr, sizeof(addr))); + if (TST_RET != 0) { + if (TST_ERR != ENOENT) { + tst_brk(TBROK | TTERRNO, + "unexpected error binding AF_ALG socket to %s algorithm '%s'", + algtype, algname); + } + have_alg = false; + } + + close(algfd); + return have_alg; +} + +void tst_require_alg(const char *algtype, const char *algname) +{ + int algfd = tst_alg_create(); + + tst_alg_bind(algfd, algtype, algname); + + close(algfd); +} + +void tst_alg_setkey(int algfd, const uint8_t *key, unsigned int keylen) +{ + uint8_t *keybuf = NULL; + unsigned int i; + + if (key == NULL) { + /* generate a random key */ + keybuf = SAFE_MALLOC(keylen); + for (i = 0; i < keylen; i++) + keybuf[i] = rand(); + key = keybuf; + } + TEST(setsockopt(algfd, SOL_ALG, ALG_SET_KEY, key, keylen)); + if (TST_RET != 0) { + tst_brk(TBROK | TTERRNO, + "unexpected error setting key (len=%u)", keylen); + } + free(keybuf); +} + +int tst_alg_accept(int algfd) +{ + TEST(accept(algfd, NULL, NULL)); + if (TST_RET < 0) { + tst_brk(TBROK | TTERRNO, + "unexpected error accept()ing AF_ALG request socket"); + } + return TST_RET; +} + +int tst_alg_setup(const char *algtype, const char *algname, + const uint8_t *key, unsigned int keylen) +{ + int algfd = tst_alg_create(); + + tst_alg_bind(algfd, algtype, algname); + + if (keylen != 0) + tst_alg_setkey(algfd, key, keylen); + + return algfd; +} + +int tst_alg_setup_reqfd(const char *algtype, const char *algname, + const uint8_t *key, unsigned int keylen) +{ + int algfd = tst_alg_setup(algtype, algname, key, keylen); + int reqfd = tst_alg_accept(algfd); + + close(algfd); + return reqfd; +} + +void tst_alg_sendmsg(int reqfd, const void *data, size_t datalen, + const struct tst_alg_sendmsg_params *params) +{ + struct iovec iov = { + .iov_base = (void *)data, + .iov_len = datalen, + }; + struct msghdr msg = { + .msg_iov = &iov, + .msg_iovlen = 1, + .msg_flags = params->msg_flags, + }; + size_t controllen; + uint8_t *control; + struct cmsghdr *cmsg; + struct af_alg_iv *alg_iv; + + if (params->encrypt && params->decrypt) + tst_brk(TBROK, "Both encrypt and decrypt are specified"); + + controllen = 0; + if (params->encrypt || params->decrypt) + controllen += CMSG_SPACE(sizeof(uint32_t)); + if (params->ivlen) + controllen += CMSG_SPACE(sizeof(struct af_alg_iv) + + params->ivlen); + if (params->assoclen) + controllen += CMSG_SPACE(sizeof(uint32_t)); + + control = SAFE_MALLOC(controllen); + memset(control, 0, controllen); + msg.msg_control = control; + msg.msg_controllen = controllen; + cmsg = CMSG_FIRSTHDR(&msg); + + if (params->encrypt || params->decrypt) { + cmsg->cmsg_level = SOL_ALG; + cmsg->cmsg_type = ALG_SET_OP; + cmsg->cmsg_len = CMSG_LEN(sizeof(uint32_t)); + *(uint32_t *)CMSG_DATA(cmsg) = + params->encrypt ? ALG_OP_ENCRYPT : ALG_OP_DECRYPT; + cmsg = CMSG_NXTHDR(&msg, cmsg); + } + if (params->ivlen) { + cmsg->cmsg_level = SOL_ALG; + cmsg->cmsg_type = ALG_SET_IV; + cmsg->cmsg_len = CMSG_LEN(sizeof(struct af_alg_iv) + + params->ivlen); + alg_iv = (struct af_alg_iv *)CMSG_DATA(cmsg); + alg_iv->ivlen = params->ivlen; + memcpy(alg_iv->iv, params->iv, params->ivlen); + cmsg = CMSG_NXTHDR(&msg, cmsg); + } + if (params->assoclen) { + cmsg->cmsg_level = SOL_ALG; + cmsg->cmsg_type = ALG_SET_AEAD_ASSOCLEN; + cmsg->cmsg_len = CMSG_LEN(sizeof(uint32_t)); + *(uint32_t *)CMSG_DATA(cmsg) = params->assoclen; + cmsg = CMSG_NXTHDR(&msg, cmsg); + } + + SAFE_SENDMSG(datalen, reqfd, &msg, 0); +} -- cgit v1.2.3-55-g7522