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