diff options
Diffstat (limited to 'kernel/tests/lib/tst_crypto.c')
-rw-r--r-- | kernel/tests/lib/tst_crypto.c | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/kernel/tests/lib/tst_crypto.c b/kernel/tests/lib/tst_crypto.c new file mode 100644 index 0000000..685e087 --- /dev/null +++ b/kernel/tests/lib/tst_crypto.c @@ -0,0 +1,110 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2018 Richard Palethorpe <rpalethorpe@suse.com> + * Nicolai Stange <nstange@suse.de> + */ + +#include <errno.h> +#include <stdio.h> + +#define TST_NO_DEFAULT_MAIN +#include "tst_test.h" +#include "tst_crypto.h" +#include "tst_netlink.h" + +void tst_crypto_open(struct tst_crypto_session *ses) +{ + TEST(socket(AF_NETLINK, SOCK_DGRAM, NETLINK_CRYPTO)); + if (TST_RET < 0 && TST_ERR == EPROTONOSUPPORT) + tst_brk(TCONF | TTERRNO, "NETLINK_CRYPTO is probably disabled"); + + if (TST_RET < 0) { + tst_brk(TBROK | TTERRNO, + "socket(AF_NETLINK, SOCK_DGRAM, NETLINK_CRYPTO)"); + } + + ses->fd = TST_RET; + ses->seq_num = 0; +} + +void tst_crypto_close(struct tst_crypto_session *ses) +{ + SAFE_CLOSE(ses->fd); +} + +static int tst_crypto_recv_ack(struct tst_crypto_session *ses) +{ + uint32_t len; + char buf[BUFSIZ]; + struct nlmsghdr *nh; + + len = SAFE_NETLINK_RECV(ses->fd, buf, sizeof(buf)); + + for (nh = (struct nlmsghdr *) buf; + NLMSG_OK(nh, len); + nh = NLMSG_NEXT(nh, len)) { + if (nh->nlmsg_seq != ses->seq_num) { + tst_brk(TBROK, + "Message out of sequence; type=0%hx, seq_num=%u (not %u)", + nh->nlmsg_type, nh->nlmsg_seq, ses->seq_num); + } + + /* Acks use the error message type with error number set to + * zero. Ofcourse we could also receive an actual error. + */ + if (nh->nlmsg_type == NLMSG_ERROR) + return ((struct nlmsgerr *)NLMSG_DATA(nh))->error; + + tst_brk(TBROK, "Unexpected message type; type=0x%hx, seq_num=%u", + nh->nlmsg_type, nh->nlmsg_seq); + } + + tst_brk(TBROK, "Empty message from netlink socket?"); + + return ENODATA; +} + +int tst_crypto_add_alg(struct tst_crypto_session *ses, + const struct crypto_user_alg *alg) +{ + struct nlmsghdr nh = { + .nlmsg_len = sizeof(struct nlmsghdr) + sizeof(*alg), + .nlmsg_type = CRYPTO_MSG_NEWALG, + .nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK, + .nlmsg_seq = ++(ses->seq_num), + .nlmsg_pid = 0, + }; + + SAFE_NETLINK_SEND(ses->fd, &nh, alg); + + return tst_crypto_recv_ack(ses); +} + +int tst_crypto_del_alg(struct tst_crypto_session *ses, + const struct crypto_user_alg *alg) +{ + unsigned int i = 0; + struct nlmsghdr nh = { + .nlmsg_len = sizeof(struct nlmsghdr) + sizeof(*alg), + .nlmsg_type = CRYPTO_MSG_DELALG, + .nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK, + .nlmsg_pid = 0, + }; + + while (1) { + nh.nlmsg_seq = ++(ses->seq_num), + + SAFE_NETLINK_SEND(ses->fd, &nh, alg); + + TEST(tst_crypto_recv_ack(ses)); + if (TST_RET != -EBUSY || i >= ses->retries) + break; + + if (usleep(1) && errno != EINTR) + tst_brk(TBROK | TERRNO, "usleep(1)"); + + ++i; + } + + return TST_RET; +} |