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 const long ret = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_CRYPTO);
18
19 if (ret < 0 && errno == EPROTONOSUPPORT)
20 tst_brk(TCONF | TERRNO, "NETLINK_CRYPTO is probably disabled");
21
22 if (ret < 0) {
23 tst_brk(TBROK | TERRNO,
24 "socket(AF_NETLINK, SOCK_DGRAM, NETLINK_CRYPTO)");
25 }
26
27 ses->fd = ret;
28 ses->seq_num = 0;
29 }
30
tst_crypto_close(struct tst_crypto_session * ses)31 void tst_crypto_close(struct tst_crypto_session *ses)
32 {
33 SAFE_CLOSE(ses->fd);
34 }
35
tst_crypto_recv_ack(struct tst_crypto_session * ses)36 static int tst_crypto_recv_ack(struct tst_crypto_session *ses)
37 {
38 uint32_t len;
39 char buf[BUFSIZ];
40 struct nlmsghdr *nh;
41
42 len = SAFE_NETLINK_RECV(ses->fd, buf, sizeof(buf));
43
44 for (nh = (struct nlmsghdr *) buf;
45 NLMSG_OK(nh, len);
46 nh = NLMSG_NEXT(nh, len)) {
47 if (nh->nlmsg_seq != ses->seq_num) {
48 tst_brk(TBROK,
49 "Message out of sequence; type=0%hx, seq_num=%u (not %u)",
50 nh->nlmsg_type, nh->nlmsg_seq, ses->seq_num);
51 }
52
53 /* Acks use the error message type with error number set to
54 * zero. Ofcourse we could also receive an actual error.
55 */
56 if (nh->nlmsg_type == NLMSG_ERROR)
57 return ((struct nlmsgerr *)NLMSG_DATA(nh))->error;
58
59 tst_brk(TBROK, "Unexpected message type; type=0x%hx, seq_num=%u",
60 nh->nlmsg_type, nh->nlmsg_seq);
61 }
62
63 tst_brk(TBROK, "Empty message from netlink socket?");
64
65 return ENODATA;
66 }
67
tst_crypto_add_alg(struct tst_crypto_session * ses,const struct crypto_user_alg * alg)68 int tst_crypto_add_alg(struct tst_crypto_session *ses,
69 const struct crypto_user_alg *alg)
70 {
71 struct nlmsghdr nh = {
72 .nlmsg_len = sizeof(struct nlmsghdr) + sizeof(*alg),
73 .nlmsg_type = CRYPTO_MSG_NEWALG,
74 .nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK,
75 .nlmsg_seq = ++(ses->seq_num),
76 .nlmsg_pid = 0,
77 };
78
79 SAFE_NETLINK_SEND(ses->fd, &nh, alg);
80
81 return tst_crypto_recv_ack(ses);
82 }
83
tst_crypto_del_alg(struct tst_crypto_session * ses,const struct crypto_user_alg * alg)84 int tst_crypto_del_alg(struct tst_crypto_session *ses,
85 const struct crypto_user_alg *alg)
86 {
87 long ret;
88 unsigned int i = 0;
89 struct nlmsghdr nh = {
90 .nlmsg_len = sizeof(struct nlmsghdr) + sizeof(*alg),
91 .nlmsg_type = CRYPTO_MSG_DELALG,
92 .nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK,
93 .nlmsg_pid = 0,
94 };
95
96 while (1) {
97 nh.nlmsg_seq = ++(ses->seq_num),
98
99 SAFE_NETLINK_SEND(ses->fd, &nh, alg);
100
101 ret = tst_crypto_recv_ack(ses);
102 if (ret != -EBUSY || i >= ses->retries)
103 break;
104
105 if (usleep(1) && errno != EINTR)
106 tst_brk(TBROK | TERRNO, "usleep(1)");
107
108 ++i;
109 }
110
111 return ret;
112 }
113