1 /*      $OpenBSD: markus $  */
2 
3 /*
4  * Copyright (c) 2005 Markus Friedl <markus@openbsd.org>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <sys/types.h>
20 #include <sys/param.h>
21 #include <sys/ioctl.h>
22 #include <sys/sysctl.h>
23 #include <crypto/cryptodev.h>
24 #include <err.h>
25 #include <fcntl.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <unistd.h>
30 #include <limits.h>
31 #include <errno.h>
32 
33 int debug = 0;
34 
35 enum { TST_KEY, TST_IV, TST_PLAIN, TST_CIPHER, TST_NUM };
36 
37 /* Test vectors from RFC 3686 */
38 struct {
39 	char *data[TST_NUM];
40 } tests[] = {
41 	/* 128 bit key */
42 	{
43 		"AE 68 52 F8 12 10 67 CC 4B F7 A5 76 55 77 F3 9E "
44 		"00 00 00 30",
45 		"00 00 00 00 00 00 00 00",
46 		"53 69 6E 67 6C 65 20 62 6C 6F 63 6B 20 6D 73 67",
47 		"E4 09 5D 4F B7 A7 B3 79 2D 61 75 A3 26 13 11 B8"
48 	},
49 	{
50 		"7E 24 06 78 17 FA E0 D7 43 D6 CE 1F 32 53 91 63 "
51 		"00 6C B6 DB",
52 		"C0 54 3B 59 DA 48 D9 0B",
53 		"00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F "
54 		"10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F",
55 		"51 04 A1 06 16 8A 72 D9 79 0D 41 EE 8E DA D3 88 "
56 		"EB 2E 1E FC 46 DA 57 C8 FC E6 30 DF 91 41 BE 28"
57 	},
58 	{
59 		"76 91 BE 03 5E 50 20 A8 AC 6E 61 85 29 F9 A0 DC "
60 		"00 E0 01 7B",
61 		"27 77 7F 3F 4A 17 86 F0",
62 		"00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F "
63 		"10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F"
64 		/*"20 21 22 23"*/,
65 		"C1 CF 48 A8 9F 2F FD D9 CF 46 52 E9 EF DB 72 D7 "
66 		"45 40 A4 2B DE 6D 78 36 D5 9A 5C EA AE F3 10 53"
67                 /*"25 B2 07 2F"*/
68 	},
69 	/* 192 bit key */
70 	{
71 		"16 AF 5B 14 5F C9 F5 79 C1 75 F9 3E 3B FB 0E ED "
72 		"86 3D 06 CC FD B7 85 15 "
73 		"00 00 00 48",
74 		"36 73 3C 14 7D 6D 93 CB",
75 		"53 69 6E 67 6C 65 20 62 6C 6F 63 6B 20 6D 73 67",
76 		"4B 55 38 4F E2 59 C9 C8 4E 79 35 A0 03 CB E9 28",
77 	},
78 	{
79 		"7C 5C B2 40 1B 3D C3 3C 19 E7 34 08 19 E0 F6 9C "
80 		"67 8C 3D B8 E6 F6 A9 1A "
81 		"00 96 B0 3B",
82 		"02 0C 6E AD C2 CB 50 0D",
83 		"00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F "
84 		"10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F",
85 		"45 32 43 FC 60 9B 23 32 7E DF AA FA 71 31 CD 9F "
86 		"84 90 70 1C 5A D4 A7 9C FC 1F E0 FF 42 F4 FB 00",
87 	},
88 	{
89 		"02 BF 39 1E E8 EC B1 59 B9 59 61 7B 09 65 27 9B "
90 		"F5 9B 60 A7 86 D3 E0 FE "
91 		"00 07 BD FD",
92 		"5C BD 60 27 8D CC 09 12",
93 		"00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F "
94 		"10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F"
95 		/*"20 21 22 23"*/,
96 		"96 89 3F C5 5E 5C 72 2F 54 0B 7D D1 DD F7 E7 58 "
97 		"D2 88 BC 95 C6 91 65 88 45 36 C8 11 66 2F 21 88"
98 		/*"AB EE 09 35"*/,
99 	},
100 	/* 256 bit key */
101 	{
102 		"77 6B EF F2 85 1D B0 6F 4C 8A 05 42 C8 69 6F 6C "
103 		"6A 81 AF 1E EC 96 B4 D3 7F C1 D6 89 E6 C1 C1 04 "
104 		"00 00 00 60",
105 		"DB 56 72 C9 7A A8 F0 B2",
106 		"53 69 6E 67 6C 65 20 62 6C 6F 63 6B 20 6D 73 67",
107 		"14 5A D0 1D BF 82 4E C7 56 08 63 DC 71 E3 E0 C0"
108 	},
109 	{
110 		"F6 D6 6D 6B D5 2D 59 BB 07 96 36 58 79 EF F8 86 "
111 		"C6 6D D5 1A 5B 6A 99 74 4B 50 59 0C 87 A2 38 84 "
112 		"00 FA AC 24",
113 		"C1 58 5E F1 5A 43 D8 75",
114 		"00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F "
115 		"10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F",
116 		"F0 5E 23 1B 38 94 61 2C 49 EE 00 0B 80 4E B2 A9 "
117 		"B8 30 6B 50 8F 83 9D 6A 55 30 83 1D 93 44 AF 1C",
118 	},
119 	{
120 		"FF 7A 61 7C E6 91 48 E4 F1 72 6E 2F 43 58 1D E2 "
121 		"AA 62 D9 F8 05 53 2E DF F1 EE D6 87 FB 54 15 3D "
122 		"00 1C C5 B7",
123 		"51 A5 1D 70 A1 C1 11 48",
124 		"00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F "
125 		"10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F"
126 		/*"20 21 22 23"*/,
127 		"EB 6C 52 82 1D 0B BB F7 CE 75 94 46 2A CA 4F AA "
128 		"B4 07 DF 86 65 69 FD 07 F4 8C C0 B5 83 D6 07 1F"
129 		/*"1E C0 E6 B8"*/,
130 	},
131 };
132 
133 static int
134 syscrypt(const unsigned char *key, size_t klen, const unsigned char *iv,
135     const unsigned char *in, unsigned char *out, size_t len, int encrypt)
136 {
137 	struct session_op session;
138 	struct crypt_op cryp;
139 	int cryptodev_fd = -1, fd = -1;
140 
141 	if ((cryptodev_fd = open("/dev/crypto", O_RDWR, 0)) < 0) {
142 		warn("/dev/crypto");
143 		goto err;
144 	}
145 	if (ioctl(cryptodev_fd, CRIOGET, &fd) == -1) {
146 		warn("CRIOGET failed");
147 		goto err;
148 	}
149 	memset(&session, 0, sizeof(session));
150 	session.cipher = CRYPTO_AES_CTR;
151 	session.key = (caddr_t) key;
152 	session.keylen = klen;
153 	if (ioctl(fd, CIOCGSESSION, &session) == -1) {
154 		warn("CIOCGSESSION");
155 		goto err;
156 	}
157 	memset(&cryp, 0, sizeof(cryp));
158 	cryp.ses = session.ses;
159 	cryp.op = encrypt ? COP_ENCRYPT : COP_DECRYPT;
160 	cryp.flags = 0;
161 	cryp.len = len;
162 	cryp.src = (caddr_t) in;
163 	cryp.dst = (caddr_t) out;
164 	cryp.iv = (caddr_t) iv;
165 	cryp.mac = 0;
166 	if (ioctl(fd, CIOCCRYPT, &cryp) == -1) {
167 		warn("CIOCCRYPT");
168 		goto err;
169 	}
170 	if (ioctl(fd, CIOCFSESSION, &session.ses) == -1) {
171 		warn("CIOCFSESSION");
172 		goto err;
173 	}
174 	close(fd);
175 	close(cryptodev_fd);
176 	return (0);
177 
178 err:
179 	if (fd != -1)
180 		close(fd);
181 	if (cryptodev_fd != -1)
182 		close(cryptodev_fd);
183 	return (-1);
184 }
185 
186 static int
187 getallowsoft(void)
188 {
189 	int mib[2], old;
190 	size_t olen;
191 
192 	olen = sizeof(old);
193 
194 	if (sysctlbyname("kern.cryptodevallowsoft", &old, &olen, NULL, 0) < 0)
195 		err(1, "sysctl failed");
196 
197 	return old;
198 }
199 
200 static void
201 setallowsoft(int new)
202 {
203 	int mib[2], old;
204 	size_t olen, nlen;
205 
206 	olen = nlen = sizeof(new);
207 
208 	if (sysctlbyname("kern.cryptodevallowsoft", &old, &olen, &new, nlen) < 0)
209 		err(1, "sysctl failed");
210 }
211 
212 static int
213 match(unsigned char *a, unsigned char *b, size_t len)
214 {
215 	int i;
216 
217 	if (memcmp(a, b, len) == 0)
218 		return (1);
219 
220 	warnx("ciphertext mismatch");
221 
222 	for (i = 0; i < len; i++)
223 		printf("%2.2x", a[i]);
224 	printf("\n");
225 	for (i = 0; i < len; i++)
226 		printf("%2.2x", b[i]);
227 	printf("\n");
228 
229 	return (0);
230 }
231 
232 static int
233 run(int num)
234 {
235 	int i, fail = 1, len, j, length[TST_NUM];
236 	u_long val;
237 	char *ep, *from;
238 	u_char *p, *data[TST_NUM];
239 
240 	for (i = 0; i < TST_NUM; i++)
241 		data[i] = NULL;
242 	for (i = 0; i < TST_NUM; i++) {
243 		from = tests[num].data[i];
244 		if (debug)
245 			printf("%s\n", from);
246 		len = strlen(from);
247 		if ((p = malloc(len)) == NULL) {
248 			warn("malloc");
249 			goto done;
250 		}
251 		errno = 0;
252 		for (j = 0; j < len; j++) {
253 			val = strtoul(&from[j*3], &ep, 16);
254 			p[j] = (u_char)val;
255 			if (*ep == '\0' || errno)
256 				break;
257 		}
258 		length[i] = j+1;
259 		data[i] = p;
260 	}
261 	len = length[TST_PLAIN];
262 	if ((p = malloc(len)) == NULL) {
263 		warn("malloc");
264 		return (1);
265 	}
266 	if (syscrypt(data[TST_KEY], length[TST_KEY],
267 	    data[TST_IV], data[TST_PLAIN], p,
268 	    length[TST_PLAIN], 0) < 0) {
269 		warnx("crypt with /dev/crypto failed");
270 		goto done;
271 	}
272 	fail = !match(data[TST_CIPHER], p, len);
273 	printf("%s test vector %d\n", fail ? "FAILED" : "OK", num);
274 done:
275 	for (i = 0; i < TST_NUM; i++)
276 		free(data[i]);
277 	return (fail);
278 }
279 
280 int
281 main(int argc, char **argv)
282 {
283 	int allowed = 0, fail = 0, i;
284 
285 	if (geteuid() == 0) {
286 		allowed = getallowsoft();
287 		if (allowed == 0)
288 			setallowsoft(1);
289 	}
290 	for (i = 0; i < (sizeof(tests) / sizeof(tests[0])); i++)
291 		fail += run(i);
292 	if (geteuid() == 0 && allowed == 0)
293 		setallowsoft(0);
294 	exit((fail > 0) ? 1 : 0);
295 }
296