summaryrefslogtreecommitdiffstats
path: root/src/kernel/tests/lib/tst_crypto.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel/tests/lib/tst_crypto.c')
-rw-r--r--src/kernel/tests/lib/tst_crypto.c110
1 files changed, 110 insertions, 0 deletions
diff --git a/src/kernel/tests/lib/tst_crypto.c b/src/kernel/tests/lib/tst_crypto.c
new file mode 100644
index 0000000..685e087
--- /dev/null
+++ b/src/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;
+}