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