h_ioctl.c revision 1.3 1 1.3 christos /* $NetBSD: h_ioctl.c,v 1.3 2017/06/14 21:43:02 christos Exp $ */
2 1.1 knakahar
3 1.1 knakahar /*-
4 1.1 knakahar * Copyright (c) 2017 Internet Initiative Japan Inc.
5 1.1 knakahar * All rights reserved.
6 1.1 knakahar *
7 1.1 knakahar * Redistribution and use in source and binary forms, with or without
8 1.1 knakahar * modification, are permitted provided that the following conditions
9 1.1 knakahar * are met:
10 1.1 knakahar * 1. Redistributions of source code must retain the above copyright
11 1.1 knakahar * notice, this list of conditions and the following disclaimer.
12 1.1 knakahar * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 knakahar * notice, this list of conditions and the following disclaimer in the
14 1.1 knakahar * documentation and/or other materials provided with the distribution.
15 1.1 knakahar *
16 1.1 knakahar * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 1.1 knakahar * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 1.1 knakahar * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 1.1 knakahar * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 1.1 knakahar * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 1.1 knakahar * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 1.1 knakahar * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 1.1 knakahar * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 1.1 knakahar * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 1.1 knakahar * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 1.1 knakahar * POSSIBILITY OF SUCH DAMAGE.
27 1.1 knakahar */
28 1.1 knakahar
29 1.1 knakahar #include <err.h>
30 1.1 knakahar #include <errno.h>
31 1.1 knakahar #include <fcntl.h>
32 1.1 knakahar #include <stdio.h>
33 1.1 knakahar #include <string.h>
34 1.1 knakahar
35 1.1 knakahar #include <sys/errno.h>
36 1.1 knakahar #include <sys/ioctl.h>
37 1.1 knakahar #include <sys/sysctl.h>
38 1.1 knakahar
39 1.1 knakahar #include <crypto/cryptodev.h>
40 1.1 knakahar
41 1.1 knakahar /* copy from h_aescbc.c */
42 1.1 knakahar #define AES_KEY_LEN 16
43 1.1 knakahar unsigned char aes_key[AES_KEY_LEN] =
44 1.1 knakahar { 0x06, 0xa9, 0x21, 0x40, 0x36, 0xb8, 0xa1, 0x5b,
45 1.1 knakahar 0x51, 0x2e, 0x03, 0xd5, 0x34, 0x12, 0x00, 0x06, };
46 1.1 knakahar
47 1.1 knakahar #define AES_IV_LEN 16
48 1.1 knakahar unsigned char aes_iv[AES_IV_LEN] =
49 1.1 knakahar { 0x3d, 0xaf, 0xba, 0x42, 0x9d, 0x9e, 0xb4, 0x30,
50 1.1 knakahar 0xb4, 0x22, 0xda, 0x80, 0x2c, 0x9f, 0xac, 0x41, };
51 1.1 knakahar
52 1.1 knakahar #define AES_PLAINTX_LEN 64
53 1.1 knakahar unsigned char aes_plaintx[AES_PLAINTX_LEN] = "Single block msg";
54 1.1 knakahar
55 1.1 knakahar #define AES_CIPHER_LEN 64
56 1.1 knakahar unsigned char aes_cipher[AES_CIPHER_LEN] =
57 1.1 knakahar { 0xe3, 0x53, 0x77, 0x9c, 0x10, 0x79, 0xae, 0xb8,
58 1.1 knakahar 0x27, 0x08, 0x94, 0x2d, 0xbe, 0x77, 0x18, 0x1a, };
59 1.1 knakahar
60 1.3 christos #define COUNT 2
61 1.3 christos
62 1.1 knakahar /*
63 1.1 knakahar * CRIOGET is deprecated.
64 1.1 knakahar */
65 1.1 knakahar
66 1.1 knakahar /*
67 1.1 knakahar * CIOCNGSESSION
68 1.1 knakahar * Hmm, who uses? (1)
69 1.1 knakahar */
70 1.1 knakahar static int
71 1.1 knakahar test_ngsession(int fd)
72 1.1 knakahar {
73 1.1 knakahar int ret;
74 1.1 knakahar struct crypt_sgop sg;
75 1.3 christos struct session_n_op css[COUNT];
76 1.1 knakahar
77 1.3 christos for (size_t i = 0; i < COUNT; i++) {
78 1.1 knakahar struct session_n_op *cs = &css[i];
79 1.1 knakahar
80 1.1 knakahar memset(cs, 0, sizeof(*cs));
81 1.1 knakahar cs->cipher = CRYPTO_AES_CBC;
82 1.1 knakahar cs->keylen = AES_KEY_LEN;
83 1.1 knakahar cs->key = __UNCONST(&aes_key);
84 1.1 knakahar }
85 1.1 knakahar memset(&sg, 0, sizeof(sg));
86 1.3 christos sg.count = COUNT;
87 1.1 knakahar sg.sessions = css;
88 1.1 knakahar
89 1.1 knakahar ret = ioctl(fd, CIOCNGSESSION, &sg);
90 1.1 knakahar if (ret < 0)
91 1.1 knakahar fprintf(stderr, "failed: CIOCNGSESSION\n");
92 1.1 knakahar
93 1.1 knakahar return ret;
94 1.1 knakahar }
95 1.1 knakahar
96 1.1 knakahar /*
97 1.1 knakahar * CIOCNFSESSION
98 1.1 knakahar * Hmm, who uses? (2)
99 1.1 knakahar */
100 1.1 knakahar static int
101 1.1 knakahar test_nfsession(int fd)
102 1.1 knakahar {
103 1.1 knakahar int ret;
104 1.1 knakahar struct crypt_sfop sf;
105 1.3 christos u_int32_t sids[COUNT];
106 1.1 knakahar
107 1.1 knakahar memset(sids, 0, sizeof(sids));
108 1.1 knakahar memset(&sf, 0, sizeof(sf));
109 1.3 christos sf.count = COUNT;
110 1.1 knakahar sf.sesid = sids;
111 1.1 knakahar
112 1.1 knakahar ret = ioctl(fd, CIOCNFSESSION, &sf);
113 1.1 knakahar if (ret < 0)
114 1.1 knakahar fprintf(stderr, "failed: CIOCNFSESSION\n");
115 1.1 knakahar
116 1.1 knakahar return ret;
117 1.1 knakahar }
118 1.1 knakahar
119 1.1 knakahar /*
120 1.1 knakahar * CIOCNCRYPTM
121 1.1 knakahar * Hmm, who uses? (3)
122 1.1 knakahar */
123 1.1 knakahar static int
124 1.1 knakahar test_ncryptm(int fd)
125 1.1 knakahar {
126 1.1 knakahar int ret;
127 1.1 knakahar struct crypt_mop mop;
128 1.3 christos struct crypt_n_op css[COUNT];
129 1.1 knakahar
130 1.3 christos for (size_t i = 0; i < COUNT; i++) {
131 1.1 knakahar struct crypt_n_op *cs;
132 1.1 knakahar cs = &css[i];
133 1.1 knakahar
134 1.1 knakahar memset(cs, 0, sizeof(*cs));
135 1.1 knakahar cs->ses = 0; /* session id */
136 1.1 knakahar cs->op = COP_ENCRYPT;
137 1.1 knakahar /* XXX */
138 1.1 knakahar }
139 1.1 knakahar
140 1.1 knakahar memset(&mop, 0, sizeof(mop));
141 1.3 christos mop.count = COUNT;
142 1.1 knakahar mop.reqs = css;
143 1.1 knakahar
144 1.1 knakahar ret = ioctl(fd, CIOCNCRYPTM, &mop);
145 1.1 knakahar if (ret < 0)
146 1.1 knakahar fprintf(stderr, "failed: CIOCNCRYPTM\n");
147 1.1 knakahar
148 1.1 knakahar return ret;
149 1.1 knakahar }
150 1.1 knakahar
151 1.1 knakahar /*
152 1.1 knakahar * CIOCNCRYPTRETM
153 1.1 knakahar * Hmm, who uses? (4)
154 1.1 knakahar */
155 1.1 knakahar static int
156 1.1 knakahar test_ncryptretm(int fd)
157 1.1 knakahar {
158 1.1 knakahar int ret;
159 1.1 knakahar struct session_op cs;
160 1.1 knakahar
161 1.1 knakahar struct crypt_mop mop;
162 1.3 christos struct crypt_n_op cnos[COUNT];
163 1.3 christos unsigned char cno_dst[COUNT][AES_CIPHER_LEN];
164 1.1 knakahar struct cryptret cret;
165 1.3 christos struct crypt_result crs[COUNT];
166 1.1 knakahar
167 1.1 knakahar memset(&cs, 0, sizeof(cs));
168 1.1 knakahar cs.cipher = CRYPTO_AES_CBC;
169 1.1 knakahar cs.keylen = AES_KEY_LEN;
170 1.1 knakahar cs.key = __UNCONST(&aes_key);
171 1.1 knakahar ret = ioctl(fd, CIOCGSESSION, &cs);
172 1.1 knakahar if (ret < 0) {
173 1.1 knakahar fprintf(stderr, "failed: CIOCGSESSION\n");
174 1.1 knakahar return ret;
175 1.1 knakahar }
176 1.1 knakahar
177 1.3 christos for (size_t i = 0; i < COUNT; i++) {
178 1.1 knakahar struct crypt_n_op *cno = &cnos[i];
179 1.1 knakahar
180 1.1 knakahar memset(cno, 0, sizeof(*cno));
181 1.1 knakahar cno->ses = cs.ses;
182 1.1 knakahar cno->op = COP_ENCRYPT;
183 1.1 knakahar cno->len = AES_PLAINTX_LEN;
184 1.1 knakahar cno->src = aes_plaintx;
185 1.1 knakahar cno->dst_len = AES_CIPHER_LEN;
186 1.1 knakahar cno->dst = cno_dst[i];
187 1.1 knakahar }
188 1.1 knakahar
189 1.1 knakahar memset(&mop, 0, sizeof(mop));
190 1.3 christos mop.count = COUNT;
191 1.1 knakahar mop.reqs = cnos;
192 1.1 knakahar ret = ioctl(fd, CIOCNCRYPTM, &mop);
193 1.1 knakahar if (ret < 0)
194 1.1 knakahar fprintf(stderr, "failed: CIOCNCRYPTM\n");
195 1.1 knakahar
196 1.3 christos for (size_t i = 0; i < COUNT; i++) {
197 1.1 knakahar struct crypt_result *cr = &crs[i];
198 1.1 knakahar
199 1.1 knakahar memset(cr, 0, sizeof(*cr));
200 1.1 knakahar cr->reqid = cnos[i].reqid;
201 1.1 knakahar }
202 1.1 knakahar
203 1.1 knakahar memset(&cret, 0, sizeof(cret));
204 1.3 christos cret.count = COUNT;
205 1.1 knakahar cret.results = crs;
206 1.1 knakahar ret = ioctl(fd, CIOCNCRYPTRETM, &cret);
207 1.1 knakahar if (ret < 0)
208 1.1 knakahar fprintf(stderr, "failed: CIOCNCRYPTRETM\n");
209 1.1 knakahar
210 1.1 knakahar return ret;
211 1.1 knakahar }
212 1.1 knakahar
213 1.1 knakahar /*
214 1.1 knakahar * CIOCNCRYPTRET
215 1.1 knakahar * Hmm, who uses? (5)
216 1.1 knakahar */
217 1.1 knakahar /* test when it does not request yet. */
218 1.1 knakahar static int
219 1.1 knakahar test_ncryptret_noent(int fd)
220 1.1 knakahar {
221 1.1 knakahar int ret;
222 1.1 knakahar struct crypt_result cr;
223 1.1 knakahar
224 1.1 knakahar memset(&cr, 0, sizeof(cr));
225 1.1 knakahar
226 1.1 knakahar ret = ioctl(fd, CIOCNCRYPTRET, &cr);
227 1.1 knakahar if (ret == 0) {
228 1.1 knakahar fprintf(stderr,
229 1.1 knakahar "failed: CIOCNCRYPTRET unexpected success when no entry\n");
230 1.1 knakahar ret = -1;
231 1.1 knakahar } else if (errno == EINPROGRESS) {
232 1.1 knakahar /* expected fail */
233 1.1 knakahar ret = 0;
234 1.1 knakahar }
235 1.1 knakahar
236 1.1 knakahar return ret;
237 1.1 knakahar }
238 1.1 knakahar
239 1.1 knakahar static int
240 1.1 knakahar test_ncryptret_ent(int fd)
241 1.1 knakahar {
242 1.1 knakahar int ret;
243 1.1 knakahar struct session_op cs;
244 1.1 knakahar
245 1.1 knakahar struct crypt_mop mop;
246 1.1 knakahar struct crypt_n_op cno;
247 1.1 knakahar unsigned char cno_dst[AES_CIPHER_LEN];
248 1.1 knakahar
249 1.1 knakahar struct crypt_result cr;
250 1.1 knakahar
251 1.1 knakahar memset(&cs, 0, sizeof(cs));
252 1.1 knakahar cs.cipher = CRYPTO_AES_CBC;
253 1.1 knakahar cs.keylen = AES_KEY_LEN;
254 1.1 knakahar cs.key = __UNCONST(&aes_key);
255 1.1 knakahar ret = ioctl(fd, CIOCGSESSION, &cs);
256 1.1 knakahar if (ret < 0) {
257 1.1 knakahar fprintf(stderr, "failed: CIOCGSESSION\n");
258 1.1 knakahar return ret;
259 1.1 knakahar }
260 1.1 knakahar
261 1.1 knakahar memset(&cno, 0, sizeof(cno));
262 1.1 knakahar cno.ses = cs.ses;
263 1.1 knakahar cno.op = COP_ENCRYPT;
264 1.1 knakahar cno.len = AES_PLAINTX_LEN;
265 1.1 knakahar cno.src = aes_plaintx;
266 1.1 knakahar cno.dst_len = AES_CIPHER_LEN;
267 1.1 knakahar cno.dst = cno_dst;
268 1.1 knakahar
269 1.1 knakahar memset(&mop, 0, sizeof(mop));
270 1.1 knakahar mop.count = 1;
271 1.1 knakahar mop.reqs = &cno;
272 1.1 knakahar ret = ioctl(fd, CIOCNCRYPTM, &mop);
273 1.1 knakahar if (ret < 0)
274 1.1 knakahar fprintf(stderr, "failed: CIOCNCRYPTM\n");
275 1.1 knakahar
276 1.1 knakahar memset(&cr, 0, sizeof(cr));
277 1.1 knakahar cr.reqid = cno.reqid;
278 1.1 knakahar
279 1.1 knakahar ret = ioctl(fd, CIOCNCRYPTRET, &cr);
280 1.1 knakahar if (ret < 0)
281 1.1 knakahar fprintf(stderr, "failed: CIOCNCRYPTRET\n");
282 1.1 knakahar
283 1.1 knakahar return ret;
284 1.1 knakahar }
285 1.1 knakahar
286 1.1 knakahar static int
287 1.1 knakahar test_ncryptret(int fd)
288 1.1 knakahar {
289 1.1 knakahar int ret;
290 1.1 knakahar
291 1.1 knakahar ret = test_ncryptret_noent(fd);
292 1.1 knakahar if (ret < 0)
293 1.1 knakahar return ret;
294 1.1 knakahar
295 1.1 knakahar ret = test_ncryptret_ent(fd);
296 1.1 knakahar if (ret < 0)
297 1.1 knakahar return ret;
298 1.1 knakahar
299 1.1 knakahar return ret;
300 1.1 knakahar }
301 1.1 knakahar
302 1.1 knakahar /*
303 1.1 knakahar * CIOCASYMFEAT
304 1.1 knakahar */
305 1.1 knakahar static int
306 1.1 knakahar set_userasymcrypto(int new, int *old)
307 1.1 knakahar {
308 1.1 knakahar int ret;
309 1.1 knakahar
310 1.1 knakahar ret = sysctlbyname("kern.userasymcrypto", NULL, NULL, &new, sizeof(new));
311 1.1 knakahar if (ret < 0) {
312 1.1 knakahar fprintf(stderr, "failed: kern.userasymcrypto=%d", new);
313 1.1 knakahar return ret;
314 1.1 knakahar }
315 1.1 knakahar
316 1.1 knakahar if (old != NULL)
317 1.1 knakahar *old = new;
318 1.1 knakahar
319 1.1 knakahar return ret;
320 1.1 knakahar }
321 1.1 knakahar
322 1.1 knakahar static int
323 1.1 knakahar test_asymfeat_each(int fd, u_int32_t *asymfeat, int userasym)
324 1.1 knakahar {
325 1.1 knakahar int ret;
326 1.1 knakahar
327 1.1 knakahar ret = ioctl(fd, CIOCASYMFEAT, asymfeat);
328 1.1 knakahar if (ret < 0)
329 1.1 knakahar fprintf(stderr, "failed: CIOCASYMFEAT when userasym=%d\n", userasym);
330 1.1 knakahar
331 1.1 knakahar return ret;
332 1.1 knakahar }
333 1.1 knakahar
334 1.1 knakahar static int
335 1.1 knakahar test_asymfeat(int fd)
336 1.1 knakahar {
337 1.1 knakahar int ret, new, orig;
338 1.1 knakahar u_int32_t asymfeat = 0;
339 1.1 knakahar
340 1.1 knakahar /* test for kern.userasymcrypto=1 */
341 1.1 knakahar new = 1;
342 1.1 knakahar ret = set_userasymcrypto(new, &orig);
343 1.1 knakahar if (ret < 0)
344 1.1 knakahar return ret;
345 1.1 knakahar ret = test_asymfeat_each(fd, &asymfeat, new);
346 1.1 knakahar if (ret < 0)
347 1.1 knakahar return ret;
348 1.1 knakahar
349 1.1 knakahar /* test for kern.userasymcrypto=0 */
350 1.1 knakahar new = 0;
351 1.1 knakahar ret = set_userasymcrypto(new, NULL);
352 1.1 knakahar if (ret < 0)
353 1.1 knakahar return ret;
354 1.1 knakahar ret = test_asymfeat_each(fd, &asymfeat, new);
355 1.1 knakahar if (ret < 0)
356 1.1 knakahar return ret;
357 1.1 knakahar
358 1.1 knakahar /* cleanup */
359 1.1 knakahar ret = set_userasymcrypto(orig, NULL);
360 1.1 knakahar if (ret < 0)
361 1.1 knakahar fprintf(stderr, "failed: cleanup kern.userasymcrypto\n");
362 1.1 knakahar
363 1.1 knakahar return ret;
364 1.1 knakahar }
365 1.1 knakahar
366 1.1 knakahar int
367 1.1 knakahar main(void)
368 1.1 knakahar {
369 1.1 knakahar int fd, ret;
370 1.1 knakahar
371 1.1 knakahar fd = open("/dev/crypto", O_RDWR, 0);
372 1.1 knakahar if (fd < 0)
373 1.1 knakahar err(1, "open");
374 1.1 knakahar
375 1.1 knakahar ret = test_ngsession(fd);
376 1.1 knakahar if (ret < 0)
377 1.1 knakahar err(1, "test_ngsession");
378 1.1 knakahar
379 1.1 knakahar ret = test_nfsession(fd);
380 1.1 knakahar if (ret < 0)
381 1.1 knakahar err(1, "test_ngsession");
382 1.1 knakahar
383 1.1 knakahar ret = test_ncryptm(fd);
384 1.1 knakahar if (ret < 0)
385 1.1 knakahar err(1, "test_ncryptm");
386 1.1 knakahar
387 1.1 knakahar test_ncryptretm(fd);
388 1.1 knakahar if (ret < 0)
389 1.1 knakahar err(1, "test_ncryptretm");
390 1.1 knakahar
391 1.1 knakahar ret = test_ncryptret(fd);
392 1.1 knakahar if (ret < 0)
393 1.1 knakahar err(1, "test_ncryptret");
394 1.1 knakahar
395 1.1 knakahar ret = test_asymfeat(fd);
396 1.1 knakahar if (ret < 0)
397 1.1 knakahar err(1, "test_asymfeat");
398 1.1 knakahar
399 1.1 knakahar return 0;
400 1.1 knakahar }
401