1 /*
2 * Copyright (c) 2018 Richard Palethorpe <rpalethorpe@suse.com>
3 * Nicolai Stange <nstange@suse.de>
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include <errno.h>
20 #include <stdio.h>
21
22 #define TST_NO_DEFAULT_MAIN
23 #include "tst_test.h"
24 #include "tst_crypto.h"
25 #include "tst_netlink.h"
26
tst_crypto_open(struct tst_crypto_session * ses)27 void tst_crypto_open(struct tst_crypto_session *ses)
28 {
29 TEST(socket(AF_NETLINK, SOCK_DGRAM, NETLINK_CRYPTO));
30 if (TST_RET < 0 && TST_ERR == EPROTONOSUPPORT)
31 tst_brk(TCONF | TTERRNO, "NETLINK_CRYPTO is probably disabled");
32
33 if (TST_RET < 0) {
34 tst_brk(TBROK | TTERRNO,
35 "socket(AF_NETLINK, SOCK_DGRAM, NETLINK_CRYPTO)");
36 }
37
38 ses->fd = TST_RET;
39 ses->seq_num = 0;
40 }
41
tst_crypto_close(struct tst_crypto_session * ses)42 void tst_crypto_close(struct tst_crypto_session *ses)
43 {
44 SAFE_CLOSE(ses->fd);
45 }
46
tst_crypto_recv_ack(struct tst_crypto_session * ses)47 static int tst_crypto_recv_ack(struct tst_crypto_session *ses)
48 {
49 uint32_t len;
50 char buf[BUFSIZ];
51 struct nlmsghdr *nh;
52
53 len = SAFE_NETLINK_RECV(ses->fd, buf, sizeof(buf));
54
55 for (nh = (struct nlmsghdr *) buf;
56 NLMSG_OK(nh, len);
57 nh = NLMSG_NEXT(nh, len)) {
58 if (nh->nlmsg_seq != ses->seq_num) {
59 tst_brk(TBROK,
60 "Message out of sequence; type=0%hx, seq_num=%u (not %u)",
61 nh->nlmsg_type, nh->nlmsg_seq, ses->seq_num);
62 }
63
64 /* Acks use the error message type with error number set to
65 * zero. Ofcourse we could also receive an actual error.
66 */
67 if (nh->nlmsg_type == NLMSG_ERROR)
68 return ((struct nlmsgerr *)NLMSG_DATA(nh))->error;
69
70 tst_brk(TBROK, "Unexpected message type; type=0x%hx, seq_num=%u",
71 nh->nlmsg_type, nh->nlmsg_seq);
72 }
73
74 tst_brk(TBROK, "Empty message from netlink socket?");
75
76 return ENODATA;
77 }
78
tst_crypto_add_alg(struct tst_crypto_session * ses,const struct crypto_user_alg * alg)79 int tst_crypto_add_alg(struct tst_crypto_session *ses,
80 const struct crypto_user_alg *alg)
81 {
82 struct nlmsghdr nh = {
83 .nlmsg_len = sizeof(struct nlmsghdr) + sizeof(*alg),
84 .nlmsg_type = CRYPTO_MSG_NEWALG,
85 .nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK,
86 .nlmsg_seq = ++(ses->seq_num),
87 .nlmsg_pid = 0,
88 };
89
90 SAFE_NETLINK_SEND(ses->fd, &nh, alg);
91
92 return tst_crypto_recv_ack(ses);
93 }
94
tst_crypto_del_alg(struct tst_crypto_session * ses,const struct crypto_user_alg * alg)95 int tst_crypto_del_alg(struct tst_crypto_session *ses,
96 const struct crypto_user_alg *alg)
97 {
98 unsigned int i = 0;
99 struct nlmsghdr nh = {
100 .nlmsg_len = sizeof(struct nlmsghdr) + sizeof(*alg),
101 .nlmsg_type = CRYPTO_MSG_DELALG,
102 .nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK,
103 .nlmsg_pid = 0,
104 };
105
106 while (1) {
107 nh.nlmsg_seq = ++(ses->seq_num),
108
109 SAFE_NETLINK_SEND(ses->fd, &nh, alg);
110
111 TEST(tst_crypto_recv_ack(ses));
112 if (TST_RET != -EBUSY || i >= ses->retries)
113 break;
114
115 if (usleep(1) && errno != EINTR)
116 tst_brk(TBROK | TERRNO, "usleep(1)");
117
118 ++i;
119 }
120
121 return TST_RET;
122 }
123