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