• 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 	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