• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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