1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (c) 2018 Richard Palethorpe <rpalethorpe@suse.com>
4 * Nicolai Stange <nstange@suse.de>
5 */
6
7 #include <errno.h>
8 #include <stdio.h>
9
10 #define TST_NO_DEFAULT_MAIN
11 #include "tst_test.h"
12 #include "tst_crypto.h"
13 #include "tst_netlink.h"
14
tst_crypto_open(struct tst_crypto_session * ses)15 void tst_crypto_open(struct tst_crypto_session *ses)
16 {
17 TEST(socket(AF_NETLINK, SOCK_DGRAM, NETLINK_CRYPTO));
18 if (TST_RET < 0 && TST_ERR == EPROTONOSUPPORT)
19 tst_brk(TCONF | TTERRNO, "NETLINK_CRYPTO is probably disabled");
20
21 if (TST_RET < 0) {
22 tst_brk(TBROK | TTERRNO,
23 "socket(AF_NETLINK, SOCK_DGRAM, NETLINK_CRYPTO)");
24 }
25
26 ses->fd = TST_RET;
27 ses->seq_num = 0;
28 }
29
tst_crypto_close(struct tst_crypto_session * ses)30 void tst_crypto_close(struct tst_crypto_session *ses)
31 {
32 SAFE_CLOSE(ses->fd);
33 }
34
tst_crypto_recv_ack(struct tst_crypto_session * ses)35 static int tst_crypto_recv_ack(struct tst_crypto_session *ses)
36 {
37 uint32_t len;
38 char buf[BUFSIZ];
39 struct nlmsghdr *nh;
40
41 len = SAFE_NETLINK_RECV(ses->fd, buf, sizeof(buf));
42
43 for (nh = (struct nlmsghdr *) buf;
44 NLMSG_OK(nh, len);
45 nh = NLMSG_NEXT(nh, len)) {
46 if (nh->nlmsg_seq != ses->seq_num) {
47 tst_brk(TBROK,
48 "Message out of sequence; type=0%hx, seq_num=%u (not %u)",
49 nh->nlmsg_type, nh->nlmsg_seq, ses->seq_num);
50 }
51
52 /* Acks use the error message type with error number set to
53 * zero. Ofcourse we could also receive an actual error.
54 */
55 if (nh->nlmsg_type == NLMSG_ERROR)
56 return ((struct nlmsgerr *)NLMSG_DATA(nh))->error;
57
58 tst_brk(TBROK, "Unexpected message type; type=0x%hx, seq_num=%u",
59 nh->nlmsg_type, nh->nlmsg_seq);
60 }
61
62 tst_brk(TBROK, "Empty message from netlink socket?");
63
64 return ENODATA;
65 }
66
tst_crypto_add_alg(struct tst_crypto_session * ses,const struct crypto_user_alg * alg)67 int tst_crypto_add_alg(struct tst_crypto_session *ses,
68 const struct crypto_user_alg *alg)
69 {
70 struct nlmsghdr nh = {
71 .nlmsg_len = sizeof(struct nlmsghdr) + sizeof(*alg),
72 .nlmsg_type = CRYPTO_MSG_NEWALG,
73 .nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK,
74 .nlmsg_seq = ++(ses->seq_num),
75 .nlmsg_pid = 0,
76 };
77
78 SAFE_NETLINK_SEND(ses->fd, &nh, alg);
79
80 return tst_crypto_recv_ack(ses);
81 }
82
tst_crypto_del_alg(struct tst_crypto_session * ses,const struct crypto_user_alg * alg)83 int tst_crypto_del_alg(struct tst_crypto_session *ses,
84 const struct crypto_user_alg *alg)
85 {
86 unsigned int i = 0;
87 struct nlmsghdr nh = {
88 .nlmsg_len = sizeof(struct nlmsghdr) + sizeof(*alg),
89 .nlmsg_type = CRYPTO_MSG_DELALG,
90 .nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK,
91 .nlmsg_pid = 0,
92 };
93
94 while (1) {
95 nh.nlmsg_seq = ++(ses->seq_num),
96
97 SAFE_NETLINK_SEND(ses->fd, &nh, alg);
98
99 TEST(tst_crypto_recv_ack(ses));
100 if (TST_RET != -EBUSY || i >= ses->retries)
101 break;
102
103 if (usleep(1) && errno != EINTR)
104 tst_brk(TBROK | TERRNO, "usleep(1)");
105
106 ++i;
107 }
108
109 return TST_RET;
110 }
111