cryptodev.c revision 1.98.2.10 1 /* $NetBSD: cryptodev.c,v 1.98.2.10 2019/01/18 00:01:02 pgoyette Exp $ */
2 /* $FreeBSD: src/sys/opencrypto/cryptodev.c,v 1.4.2.4 2003/06/03 00:09:02 sam Exp $ */
3 /* $OpenBSD: cryptodev.c,v 1.53 2002/07/10 22:21:30 mickey Exp $ */
4
5 /*-
6 * Copyright (c) 2008 The NetBSD Foundation, Inc.
7 * All rights reserved.
8 *
9 * This code is derived from software contributed to The NetBSD Foundation
10 * by Coyote Point Systems, Inc.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 /*
35 * Copyright (c) 2001 Theo de Raadt
36 *
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
39 * are met:
40 *
41 * 1. Redistributions of source code must retain the above copyright
42 * notice, this list of conditions and the following disclaimer.
43 * 2. Redistributions in binary form must reproduce the above copyright
44 * notice, this list of conditions and the following disclaimer in the
45 * documentation and/or other materials provided with the distribution.
46 * 3. The name of the author may not be used to endorse or promote products
47 * derived from this software without specific prior written permission.
48 *
49 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
50 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
51 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
52 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
53 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
54 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
55 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
56 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
57 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
58 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
59 *
60 * Effort sponsored in part by the Defense Advanced Research Projects
61 * Agency (DARPA) and Air Force Research Laboratory, Air Force
62 * Materiel Command, USAF, under agreement number F30602-01-2-0537.
63 *
64 */
65
66 #include <sys/cdefs.h>
67 __KERNEL_RCSID(0, "$NetBSD: cryptodev.c,v 1.98.2.10 2019/01/18 00:01:02 pgoyette Exp $");
68
69 #include <sys/param.h>
70 #include <sys/systm.h>
71 #include <sys/kmem.h>
72 #include <sys/malloc.h>
73 #include <sys/mbuf.h>
74 #include <sys/pool.h>
75 #include <sys/sysctl.h>
76 #include <sys/file.h>
77 #include <sys/filedesc.h>
78 #include <sys/errno.h>
79 #include <sys/md5.h>
80 #include <sys/sha1.h>
81 #include <sys/conf.h>
82 #include <sys/device.h>
83 #include <sys/kauth.h>
84 #include <sys/select.h>
85 #include <sys/poll.h>
86 #include <sys/atomic.h>
87 #include <sys/stat.h>
88 #include <sys/module.h>
89 #include <sys/compat_stub.h>
90
91 #ifdef _KERNEL_OPT
92 #include "opt_ocf.h"
93 #include "opt_compat_netbsd.h"
94 #endif
95
96 #include <opencrypto/cryptodev.h>
97 #include <opencrypto/ocryptodev.h>
98 #include <opencrypto/cryptodev_internal.h>
99 #include <opencrypto/xform.h>
100
101 #include "ioconf.h"
102
103 kmutex_t cryptodev_mtx;
104
105 struct csession {
106 TAILQ_ENTRY(csession) next;
107 u_int64_t sid;
108 u_int32_t ses;
109
110 u_int32_t cipher; /* note: shares name space in crd_alg */
111 const struct enc_xform *txform;
112 u_int32_t mac; /* note: shares name space in crd_alg */
113 const struct auth_hash *thash;
114 u_int32_t comp_alg; /* note: shares name space in crd_alg */
115 const struct comp_algo *tcomp;
116
117 void * key;
118 int keylen;
119 u_char tmp_iv[EALG_MAX_BLOCK_LEN];
120
121 void * mackey;
122 int mackeylen;
123 u_char tmp_mac[CRYPTO_MAX_MAC_LEN];
124
125 struct iovec iovec[1]; /* user requests never have more */
126 struct uio uio;
127 int error;
128 };
129
130 struct fcrypt {
131 TAILQ_HEAD(csessionlist, csession) csessions;
132 TAILQ_HEAD(crprethead, cryptop) crp_ret_mq;
133 TAILQ_HEAD(krprethead, cryptkop) crp_ret_mkq;
134 int sesn;
135 struct selinfo sinfo;
136 u_int32_t requestid;
137 struct timespec atime;
138 struct timespec mtime;
139 struct timespec btime;
140 };
141
142 /* For our fixed-size allocations */
143 static struct pool fcrpl;
144 static struct pool csepl;
145
146 /* Declaration of master device (fd-cloning/ctxt-allocating) entrypoints */
147 static int cryptoopen(dev_t dev, int flag, int mode, struct lwp *l);
148 static int cryptoread(dev_t dev, struct uio *uio, int ioflag);
149 static int cryptowrite(dev_t dev, struct uio *uio, int ioflag);
150 static int cryptoselect(dev_t dev, int rw, struct lwp *l);
151
152 static int crypto_refcount = 0; /* Prevent detaching while in use */
153
154 /* Declaration of cloned-device (per-ctxt) entrypoints */
155 static int cryptof_read(struct file *, off_t *, struct uio *,
156 kauth_cred_t, int);
157 static int cryptof_write(struct file *, off_t *, struct uio *,
158 kauth_cred_t, int);
159 static int cryptof_ioctl(struct file *, u_long, void *);
160 static int cryptof_close(struct file *);
161 static int cryptof_poll(struct file *, int);
162 static int cryptof_stat(struct file *, struct stat *);
163
164 static const struct fileops cryptofops = {
165 .fo_name = "cryptof",
166 .fo_read = cryptof_read,
167 .fo_write = cryptof_write,
168 .fo_ioctl = cryptof_ioctl,
169 .fo_fcntl = fnullop_fcntl,
170 .fo_poll = cryptof_poll,
171 .fo_stat = cryptof_stat,
172 .fo_close = cryptof_close,
173 .fo_kqfilter = fnullop_kqfilter,
174 .fo_restart = fnullop_restart,
175 };
176
177 struct csession *cryptodev_csefind(struct fcrypt *, u_int);
178 static struct csession *csefind(struct fcrypt *, u_int);
179 static int csedelete(struct fcrypt *, struct csession *);
180 static struct csession *cseadd(struct fcrypt *, struct csession *);
181 static struct csession *csecreate(struct fcrypt *, u_int64_t, void *,
182 u_int64_t, void *, u_int64_t, u_int32_t, u_int32_t, u_int32_t,
183 const struct enc_xform *, const struct auth_hash *,
184 const struct comp_algo *);
185 static int csefree(struct csession *);
186
187 static int cryptodev_key(struct crypt_kop *);
188 static int cryptodev_mkey(struct fcrypt *, struct crypt_n_kop *, int);
189 static int cryptodev_msessionfin(struct fcrypt *, int, u_int32_t *);
190
191 static int cryptodev_cb(void *);
192 static int cryptodevkey_cb(void *);
193
194 static int cryptodev_mcb(void *);
195 static int cryptodevkey_mcb(void *);
196
197 static int cryptodev_getmstatus(struct fcrypt *, struct crypt_result *,
198 int);
199 static int cryptodev_getstatus(struct fcrypt *, struct crypt_result *);
200
201 /*
202 * sysctl-able control variables for /dev/crypto now defined in crypto.c:
203 * crypto_usercrypto, crypto_userasmcrypto, crypto_devallowsoft.
204 */
205
206 /* ARGSUSED */
207 int
208 cryptof_read(file_t *fp, off_t *poff,
209 struct uio *uio, kauth_cred_t cred, int flags)
210 {
211 return EIO;
212 }
213
214 /* ARGSUSED */
215 int
216 cryptof_write(file_t *fp, off_t *poff,
217 struct uio *uio, kauth_cred_t cred, int flags)
218 {
219 return EIO;
220 }
221
222 /*
223 * Hook the ocryptodev 50 compat code
224 *
225 * This is a bit messy because we need to pass local stuff to the
226 * compat routines. The compat routines may be built-in to a
227 * kernel which doesn't contain the local stuff, so the compat
228 * code cannot directly reference them as globals.
229 */
230 MODULE_CALL_HOOK_DECL(ocryptof_50_hook, int,
231 (struct file *fp, u_long cmd, void *data));
232 MODULE_CALL_HOOK(ocryptof_50_hook, int,
233 (struct file *fp, u_long cmd, void *data), (fp, cmd, data), enosys());
234
235 /* ARGSUSED */
236 int
237 cryptof_ioctl(struct file *fp, u_long cmd, void *data)
238 {
239 struct fcrypt *fcr = fp->f_fcrypt;
240 struct csession *cse;
241 struct session_op *sop;
242 struct session_n_op *snop;
243 struct crypt_op *cop;
244 struct crypt_mop *mop;
245 struct crypt_mkop *mkop;
246 struct crypt_n_op *cnop;
247 struct crypt_n_kop *knop;
248 struct crypt_sgop *sgop;
249 struct crypt_sfop *sfop;
250 struct cryptret *crypt_ret;
251 struct crypt_result *crypt_res;
252 u_int32_t ses;
253 u_int32_t *sesid;
254 int error = 0;
255 size_t count;
256
257 /* backwards compatibility */
258 file_t *criofp;
259 struct fcrypt *criofcr;
260 int criofd;
261
262 mutex_enter(&cryptodev_mtx);
263 getnanotime(&fcr->atime);
264 mutex_exit(&cryptodev_mtx);
265
266 switch (cmd) {
267 case CRIOGET: /* XXX deprecated, remove after 5.0 */
268 if ((error = fd_allocfile(&criofp, &criofd)) != 0)
269 return error;
270 criofcr = pool_get(&fcrpl, PR_WAITOK);
271 mutex_enter(&cryptodev_mtx);
272 TAILQ_INIT(&criofcr->csessions);
273 TAILQ_INIT(&criofcr->crp_ret_mq);
274 TAILQ_INIT(&criofcr->crp_ret_mkq);
275 selinit(&criofcr->sinfo);
276
277 /*
278 * Don't ever return session 0, to allow detection of
279 * failed creation attempts with multi-create ioctl.
280 */
281 criofcr->sesn = 1;
282 criofcr->requestid = 1;
283 crypto_refcount++;
284 mutex_exit(&cryptodev_mtx);
285 (void)fd_clone(criofp, criofd, (FREAD|FWRITE),
286 &cryptofops, criofcr);
287 *(u_int32_t *)data = criofd;
288 return error;
289 break;
290 case CIOCGSESSION:
291 sop = (struct session_op *)data;
292 error = cryptodev_session(fcr, sop);
293 break;
294 case CIOCNGSESSION:
295 sgop = (struct crypt_sgop *)data;
296 if (sgop->count <= 0
297 || SIZE_MAX / sizeof(struct session_n_op) <= sgop->count) {
298 error = EINVAL;
299 break;
300 }
301 snop = kmem_alloc((sgop->count *
302 sizeof(struct session_n_op)), KM_SLEEP);
303 error = copyin(sgop->sessions, snop, sgop->count *
304 sizeof(struct session_n_op));
305 if (error) {
306 goto mbail;
307 }
308
309 mutex_enter(&cryptodev_mtx);
310 fcr->mtime = fcr->atime;
311 mutex_exit(&cryptodev_mtx);
312 error = cryptodev_msession(fcr, snop, sgop->count);
313 if (error) {
314 goto mbail;
315 }
316
317 error = copyout(snop, sgop->sessions, sgop->count *
318 sizeof(struct session_n_op));
319 mbail:
320 kmem_free(snop, sgop->count * sizeof(struct session_n_op));
321 break;
322 case CIOCFSESSION:
323 mutex_enter(&cryptodev_mtx);
324 fcr->mtime = fcr->atime;
325 ses = *(u_int32_t *)data;
326 cse = csefind(fcr, ses);
327 if (cse == NULL) {
328 mutex_exit(&cryptodev_mtx);
329 return EINVAL;
330 }
331 csedelete(fcr, cse);
332 mutex_exit(&cryptodev_mtx);
333 error = csefree(cse);
334 break;
335 case CIOCNFSESSION:
336 mutex_enter(&cryptodev_mtx);
337 fcr->mtime = fcr->atime;
338 mutex_exit(&cryptodev_mtx);
339 sfop = (struct crypt_sfop *)data;
340 if (sfop->count <= 0
341 || SIZE_MAX / sizeof(u_int32_t) <= sfop->count) {
342 error = EINVAL;
343 break;
344 }
345 sesid = kmem_alloc((sfop->count * sizeof(u_int32_t)),
346 KM_SLEEP);
347 error = copyin(sfop->sesid, sesid,
348 (sfop->count * sizeof(u_int32_t)));
349 if (!error) {
350 error = cryptodev_msessionfin(fcr, sfop->count, sesid);
351 }
352 kmem_free(sesid, (sfop->count * sizeof(u_int32_t)));
353 break;
354 case CIOCCRYPT:
355 mutex_enter(&cryptodev_mtx);
356 fcr->mtime = fcr->atime;
357 cop = (struct crypt_op *)data;
358 cse = csefind(fcr, cop->ses);
359 mutex_exit(&cryptodev_mtx);
360 if (cse == NULL) {
361 DPRINTF("csefind failed\n");
362 return EINVAL;
363 }
364 error = cryptodev_op(cse, cop, curlwp);
365 DPRINTF("cryptodev_op error = %d\n", error);
366 break;
367 case CIOCNCRYPTM:
368 mutex_enter(&cryptodev_mtx);
369 fcr->mtime = fcr->atime;
370 mutex_exit(&cryptodev_mtx);
371 mop = (struct crypt_mop *)data;
372 if (mop->count <= 0
373 || SIZE_MAX / sizeof(struct crypt_n_op) <= mop->count) {
374 error = EINVAL;
375 break;
376 }
377 cnop = kmem_alloc((mop->count * sizeof(struct crypt_n_op)),
378 KM_SLEEP);
379 error = copyin(mop->reqs, cnop,
380 (mop->count * sizeof(struct crypt_n_op)));
381 if(!error) {
382 error = cryptodev_mop(fcr, cnop, mop->count, curlwp);
383 if (!error) {
384 error = copyout(cnop, mop->reqs,
385 (mop->count * sizeof(struct crypt_n_op)));
386 }
387 }
388 kmem_free(cnop, (mop->count * sizeof(struct crypt_n_op)));
389 break;
390 case CIOCKEY:
391 error = cryptodev_key((struct crypt_kop *)data);
392 DPRINTF("cryptodev_key error = %d\n", error);
393 break;
394 case CIOCNFKEYM:
395 mutex_enter(&cryptodev_mtx);
396 fcr->mtime = fcr->atime;
397 mutex_exit(&cryptodev_mtx);
398 mkop = (struct crypt_mkop *)data;
399 if (mkop->count <= 0
400 || SIZE_MAX / sizeof(struct crypt_n_kop) <= mkop->count) {
401 error = EINVAL;
402 break;
403 }
404 knop = kmem_alloc((mkop->count * sizeof(struct crypt_n_kop)),
405 KM_SLEEP);
406 error = copyin(mkop->reqs, knop,
407 (mkop->count * sizeof(struct crypt_n_kop)));
408 if (!error) {
409 error = cryptodev_mkey(fcr, knop, mkop->count);
410 if (!error)
411 error = copyout(knop, mkop->reqs,
412 (mkop->count * sizeof(struct crypt_n_kop)));
413 }
414 kmem_free(knop, (mkop->count * sizeof(struct crypt_n_kop)));
415 break;
416 case CIOCASYMFEAT:
417 error = crypto_getfeat((int *)data);
418 break;
419 case CIOCNCRYPTRETM:
420 mutex_enter(&cryptodev_mtx);
421 fcr->mtime = fcr->atime;
422 mutex_exit(&cryptodev_mtx);
423 crypt_ret = (struct cryptret *)data;
424 count = crypt_ret->count;
425 if (count <= 0
426 || SIZE_MAX / sizeof(struct crypt_result) <= count) {
427 error = EINVAL;
428 break;
429 }
430 crypt_res = kmem_alloc((count * sizeof(struct crypt_result)),
431 KM_SLEEP);
432 error = copyin(crypt_ret->results, crypt_res,
433 (count * sizeof(struct crypt_result)));
434 if (error)
435 goto reterr;
436 crypt_ret->count = cryptodev_getmstatus(fcr, crypt_res,
437 crypt_ret->count);
438 /* sanity check count */
439 if (crypt_ret->count > count) {
440 printf("%s.%d: error returned count %zd > original "
441 " count %zd\n",
442 __FILE__, __LINE__, crypt_ret->count, count);
443 crypt_ret->count = count;
444
445 }
446 error = copyout(crypt_res, crypt_ret->results,
447 (crypt_ret->count * sizeof(struct crypt_result)));
448 reterr:
449 kmem_free(crypt_res, (count * sizeof(struct crypt_result)));
450 break;
451 case CIOCNCRYPTRET:
452 error = cryptodev_getstatus(fcr, (struct crypt_result *)data);
453 break;
454 default:
455 /* Check for backward compatible commands */
456 error = ocryptof_50_hook_call(fp, cmd, data);
457 if (error == ENOSYS)
458 error = EINVAL;
459 return error;
460 }
461 return error;
462 }
463
464 int
465 cryptodev_op(struct csession *cse, struct crypt_op *cop, struct lwp *l)
466 {
467 struct cryptop *crp = NULL;
468 struct cryptodesc *crde = NULL, *crda = NULL, *crdc = NULL;
469 int error;
470 int iov_len = cop->len;
471 int flags=0;
472 int dst_len; /* copyout size */
473
474 if (cop->len > 256*1024-4)
475 return E2BIG;
476
477 if (cse->txform) {
478 if (cop->len < cse->txform->blocksize
479 + (cop->iv ? 0 : cse->txform->ivsize) ||
480 (cop->len - (cop->iv ? 0 : cse->txform->ivsize))
481 % cse->txform->blocksize != 0)
482 return EINVAL;
483 }
484
485 DPRINTF("cryptodev_op[%u]: iov_len %d\n",
486 CRYPTO_SESID2LID(cse->sid), iov_len);
487 if ((cse->tcomp) && cop->dst_len) {
488 if (iov_len < cop->dst_len) {
489 /* Need larger iov to deal with decompress */
490 iov_len = cop->dst_len;
491 }
492 DPRINTF("cryptodev_op: iov_len -> %d for decompress\n", iov_len);
493 }
494
495 (void)memset(&cse->uio, 0, sizeof(cse->uio));
496 cse->uio.uio_iovcnt = 1;
497 cse->uio.uio_resid = 0;
498 cse->uio.uio_rw = UIO_WRITE;
499 cse->uio.uio_iov = cse->iovec;
500 UIO_SETUP_SYSSPACE(&cse->uio);
501 memset(&cse->iovec, 0, sizeof(cse->iovec));
502
503 /* the iov needs to be big enough to handle the uncompressed
504 * data.... */
505 cse->uio.uio_iov[0].iov_len = iov_len;
506 if (iov_len > 0)
507 cse->uio.uio_iov[0].iov_base = kmem_alloc(iov_len, KM_SLEEP);
508 cse->uio.uio_resid = cse->uio.uio_iov[0].iov_len;
509 DPRINTF("lid[%u]: uio.iov_base %p malloced %d bytes\n",
510 CRYPTO_SESID2LID(cse->sid),
511 cse->uio.uio_iov[0].iov_base, iov_len);
512
513 crp = crypto_getreq((cse->tcomp != NULL) + (cse->txform != NULL) + (cse->thash != NULL));
514 if (crp == NULL) {
515 error = ENOMEM;
516 goto bail;
517 }
518 DPRINTF("lid[%u]: crp %p\n", CRYPTO_SESID2LID(cse->sid), crp);
519
520 /* crds are always ordered tcomp, thash, then txform */
521 /* with optional missing links */
522
523 /* XXX: If we're going to compress then hash or encrypt, we need
524 * to be able to pass on the new size of the data.
525 */
526
527 if (cse->tcomp) {
528 crdc = crp->crp_desc;
529 }
530
531 if (cse->thash) {
532 crda = crdc ? crdc->crd_next : crp->crp_desc;
533 if (cse->txform && crda)
534 crde = crda->crd_next;
535 } else {
536 if (cse->txform) {
537 crde = crdc ? crdc->crd_next : crp->crp_desc;
538 } else if (!cse->tcomp) {
539 error = EINVAL;
540 goto bail;
541 }
542 }
543
544 DPRINTF("ocf[%u]: iov_len %zu, cop->len %u\n",
545 CRYPTO_SESID2LID(cse->sid),
546 cse->uio.uio_iov[0].iov_len,
547 cop->len);
548
549 if ((error = copyin(cop->src, cse->uio.uio_iov[0].iov_base, cop->len)))
550 {
551 printf("copyin failed %s %d \n", (char *)cop->src, error);
552 goto bail;
553 }
554
555 if (crdc) {
556 switch (cop->op) {
557 case COP_COMP:
558 crdc->crd_flags |= CRD_F_COMP;
559 break;
560 case COP_DECOMP:
561 crdc->crd_flags &= ~CRD_F_COMP;
562 break;
563 default:
564 break;
565 }
566 /* more data to follow? */
567 if (cop->flags & COP_F_MORE) {
568 flags |= CRYPTO_F_MORE;
569 }
570 crdc->crd_len = cop->len;
571 crdc->crd_inject = 0;
572
573 crdc->crd_alg = cse->comp_alg;
574 crdc->crd_key = NULL;
575 crdc->crd_klen = 0;
576 DPRINTF("lid[%u]: crdc setup for comp_alg %d.\n",
577 CRYPTO_SESID2LID(cse->sid), crdc->crd_alg);
578 }
579
580 if (crda) {
581 crda->crd_skip = 0;
582 crda->crd_len = cop->len;
583 crda->crd_inject = 0; /* ??? */
584
585 crda->crd_alg = cse->mac;
586 crda->crd_key = cse->mackey;
587 crda->crd_klen = cse->mackeylen * 8;
588 DPRINTF("crda setup for mac %d.\n", crda->crd_alg);
589 }
590
591 if (crde) {
592 switch (cop->op) {
593 case COP_ENCRYPT:
594 crde->crd_flags |= CRD_F_ENCRYPT;
595 break;
596 case COP_DECRYPT:
597 crde->crd_flags &= ~CRD_F_ENCRYPT;
598 break;
599 default:
600 break;
601 }
602 crde->crd_len = cop->len;
603 crde->crd_inject = 0;
604
605 if (cse->cipher == CRYPTO_AES_GCM_16 && crda)
606 crda->crd_len = 0;
607 else if (cse->cipher == CRYPTO_AES_GMAC)
608 crde->crd_len = 0;
609
610 crde->crd_alg = cse->cipher;
611 crde->crd_key = cse->key;
612 crde->crd_klen = cse->keylen * 8;
613 DPRINTF("crde setup for cipher %d.\n", crde->crd_alg);
614 }
615
616
617 crp->crp_ilen = cop->len;
618 /*
619 * The request is flagged as CRYPTO_F_USER as long as it is running
620 * in the user IOCTL thread. However, whether the request completes
621 * immediately or belatedly is depends on the used encryption driver.
622 */
623 crp->crp_flags = CRYPTO_F_IOV | (cop->flags & COP_F_BATCH) | CRYPTO_F_USER |
624 flags;
625 crp->crp_buf = (void *)&cse->uio;
626 crp->crp_callback = (int (*) (struct cryptop *)) cryptodev_cb;
627 crp->crp_sid = cse->sid;
628 crp->crp_opaque = (void *)cse;
629
630 if (cop->iv) {
631 if (crde == NULL) {
632 error = EINVAL;
633 goto bail;
634 }
635 if (cse->txform->ivsize == 0) {
636 error = EINVAL;
637 goto bail;
638 }
639 if ((error = copyin(cop->iv, cse->tmp_iv,
640 cse->txform->ivsize)))
641 goto bail;
642 (void)memcpy(crde->crd_iv, cse->tmp_iv, cse->txform->ivsize);
643 crde->crd_flags |= CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT;
644 crde->crd_skip = 0;
645 } else if (crde) {
646 if (cse->txform->ivsize == 0) {
647 crde->crd_skip = 0;
648 } else {
649 if (!(crde->crd_flags & CRD_F_ENCRYPT))
650 crde->crd_flags |= CRD_F_IV_PRESENT;
651 crde->crd_skip = cse->txform->ivsize;
652 crde->crd_len -= cse->txform->ivsize;
653 }
654 }
655
656 if (cop->mac) {
657 if (crda == NULL) {
658 error = EINVAL;
659 goto bail;
660 }
661 crp->crp_mac=cse->tmp_mac;
662 }
663
664 cv_init(&crp->crp_cv, "crydev");
665
666 /*
667 * XXX there was a comment here which said that we went to
668 * XXX splcrypto() but needed to only if CRYPTO_F_CBIMM,
669 * XXX disabled on NetBSD since 1.6O due to a race condition.
670 * XXX But crypto_dispatch went to splcrypto() itself! (And
671 * XXX now takes the cryptodev_mtx mutex itself). We do, however,
672 * XXX need to hold the mutex across the call to cv_wait().
673 * XXX (should we arrange for crypto_dispatch to return to
674 * XXX us with it held? it seems quite ugly to do so.)
675 */
676 #ifdef notyet
677 eagain:
678 #endif
679 error = crypto_dispatch(crp);
680 mutex_enter(&cryptodev_mtx);
681
682 /*
683 * Don't touch crp before returned by any error or received
684 * cv_signal(&crp->crp_cv). It is required to restructure locks.
685 */
686
687 switch (error) {
688 #ifdef notyet /* don't loop forever -- but EAGAIN not possible here yet */
689 case EAGAIN:
690 mutex_exit(&cryptodev_mtx);
691 goto eagain;
692 break;
693 #endif
694 case 0:
695 break;
696 default:
697 DPRINTF("not waiting, error.\n");
698 mutex_exit(&cryptodev_mtx);
699 cv_destroy(&crp->crp_cv);
700 goto bail;
701 }
702
703 while (!(crp->crp_devflags & CRYPTODEV_F_RET)) {
704 DPRINTF("cse->sid[%d]: sleeping on cv %p for crp %p\n",
705 (uint32_t)cse->sid, &crp->crp_cv, crp);
706 cv_wait(&crp->crp_cv, &cryptodev_mtx); /* XXX cv_wait_sig? */
707 }
708 mutex_exit(&cryptodev_mtx);
709 cv_destroy(&crp->crp_cv);
710
711 if (crp->crp_etype != 0) {
712 DPRINTF("crp_etype %d\n", crp->crp_etype);
713 error = crp->crp_etype;
714 goto bail;
715 }
716
717 if (cse->error) {
718 DPRINTF("cse->error %d\n", cse->error);
719 error = cse->error;
720 goto bail;
721 }
722
723 dst_len = crp->crp_ilen;
724 /* let the user know how much data was returned */
725 if (crp->crp_olen) {
726 if (crp->crp_olen > (cop->dst_len ? cop->dst_len : cop->len)) {
727 error = ENOSPC;
728 goto bail;
729 }
730 dst_len = cop->dst_len = crp->crp_olen;
731 }
732
733 if (cop->dst) {
734 DPRINTF("copyout %d bytes to %p\n", dst_len, cop->dst);
735 }
736 if (cop->dst &&
737 (error = copyout(cse->uio.uio_iov[0].iov_base, cop->dst, dst_len)))
738 {
739 DPRINTF("copyout error %d\n", error);
740 goto bail;
741 }
742
743 if (cop->mac &&
744 (error = copyout(crp->crp_mac, cop->mac, cse->thash->authsize))) {
745 DPRINTF("mac copyout error %d\n", error);
746 goto bail;
747 }
748
749
750 bail:
751 if (crp) {
752 crypto_freereq(crp);
753 }
754 if (cse->uio.uio_iov[0].iov_base) {
755 kmem_free(cse->uio.uio_iov[0].iov_base,iov_len);
756 }
757
758 return error;
759 }
760
761 static int
762 cryptodev_cb(void *op)
763 {
764 struct cryptop *crp = (struct cryptop *) op;
765 struct csession *cse = (struct csession *)crp->crp_opaque;
766 int error = 0;
767
768 mutex_enter(&cryptodev_mtx);
769 cse->error = crp->crp_etype;
770 if (crp->crp_etype == EAGAIN) {
771 /* always drop mutex to call dispatch routine */
772 mutex_exit(&cryptodev_mtx);
773 error = crypto_dispatch(crp);
774 mutex_enter(&cryptodev_mtx);
775 }
776 if (error != 0 || (crp->crp_flags & CRYPTO_F_DONE)) {
777 crp->crp_devflags |= CRYPTODEV_F_RET;
778 cv_signal(&crp->crp_cv);
779 }
780 mutex_exit(&cryptodev_mtx);
781 return 0;
782 }
783
784 static int
785 cryptodev_mcb(void *op)
786 {
787 struct cryptop *crp = (struct cryptop *) op;
788 struct csession *cse = (struct csession *)crp->crp_opaque;
789 int error=0;
790
791 mutex_enter(&cryptodev_mtx);
792 cse->error = crp->crp_etype;
793 if (crp->crp_etype == EAGAIN) {
794 mutex_exit(&cryptodev_mtx);
795 error = crypto_dispatch(crp);
796 mutex_enter(&cryptodev_mtx);
797 }
798 if (error != 0 || (crp->crp_flags & CRYPTO_F_DONE)) {
799 cv_signal(&crp->crp_cv);
800 }
801
802 TAILQ_INSERT_TAIL(&crp->fcrp->crp_ret_mq, crp, crp_next);
803 selnotify(&crp->fcrp->sinfo, 0, 0);
804 mutex_exit(&cryptodev_mtx);
805 return 0;
806 }
807
808 static int
809 cryptodevkey_cb(void *op)
810 {
811 struct cryptkop *krp = op;
812
813 mutex_enter(&cryptodev_mtx);
814 krp->krp_devflags |= CRYPTODEV_F_RET;
815 cv_signal(&krp->krp_cv);
816 mutex_exit(&cryptodev_mtx);
817 return 0;
818 }
819
820 static int
821 cryptodevkey_mcb(void *op)
822 {
823 struct cryptkop *krp = op;
824
825 mutex_enter(&cryptodev_mtx);
826 cv_signal(&krp->krp_cv);
827 TAILQ_INSERT_TAIL(&krp->fcrp->crp_ret_mkq, krp, krp_next);
828 selnotify(&krp->fcrp->sinfo, 0, 0);
829 mutex_exit(&cryptodev_mtx);
830 return 0;
831 }
832
833 static int
834 cryptodev_key(struct crypt_kop *kop)
835 {
836 struct cryptkop *krp = NULL;
837 int error = EINVAL;
838 int in, out, size, i;
839
840 if (kop->crk_iparams + kop->crk_oparams > CRK_MAXPARAM)
841 return EFBIG;
842
843 in = kop->crk_iparams;
844 out = kop->crk_oparams;
845 switch (kop->crk_op) {
846 case CRK_MOD_EXP:
847 if (in == 3 && out == 1)
848 break;
849 return EINVAL;
850 case CRK_MOD_EXP_CRT:
851 if (in == 6 && out == 1)
852 break;
853 return EINVAL;
854 case CRK_DSA_SIGN:
855 if (in == 5 && out == 2)
856 break;
857 return EINVAL;
858 case CRK_DSA_VERIFY:
859 if (in == 7 && out == 0)
860 break;
861 return EINVAL;
862 case CRK_DH_COMPUTE_KEY:
863 if (in == 3 && out == 1)
864 break;
865 return EINVAL;
866 case CRK_MOD_ADD:
867 if (in == 3 && out == 1)
868 break;
869 return EINVAL;
870 case CRK_MOD_ADDINV:
871 if (in == 2 && out == 1)
872 break;
873 return EINVAL;
874 case CRK_MOD_SUB:
875 if (in == 3 && out == 1)
876 break;
877 return EINVAL;
878 case CRK_MOD_MULT:
879 if (in == 3 && out == 1)
880 break;
881 return EINVAL;
882 case CRK_MOD_MULTINV:
883 if (in == 2 && out == 1)
884 break;
885 return EINVAL;
886 case CRK_MOD:
887 if (in == 2 && out == 1)
888 break;
889 return EINVAL;
890 default:
891 return EINVAL;
892 }
893
894 krp = crypto_kgetreq(1, PR_WAITOK);
895 if (krp == NULL) {
896 /* limited by opencrypto.crypto_ret_kq.maxlen */
897 return ENOMEM;
898 }
899 (void)memset(krp, 0, sizeof *krp);
900 cv_init(&krp->krp_cv, "crykdev");
901 krp->krp_op = kop->crk_op;
902 krp->krp_status = kop->crk_status;
903 krp->krp_iparams = kop->crk_iparams;
904 krp->krp_oparams = kop->crk_oparams;
905 krp->krp_status = 0;
906 krp->krp_callback = (int (*) (struct cryptkop *)) cryptodevkey_cb;
907
908 for (i = 0; i < CRK_MAXPARAM; i++)
909 krp->krp_param[i].crp_nbits = kop->crk_param[i].crp_nbits;
910 for (i = 0; i < krp->krp_iparams + krp->krp_oparams; i++) {
911 size = (krp->krp_param[i].crp_nbits + 7) / 8;
912 if (size == 0)
913 continue;
914 krp->krp_param[i].crp_p = kmem_alloc(size, KM_SLEEP);
915 if (i >= krp->krp_iparams)
916 continue;
917 error = copyin(kop->crk_param[i].crp_p,
918 krp->krp_param[i].crp_p, size);
919 if (error)
920 goto fail;
921 }
922
923 error = crypto_kdispatch(krp);
924 if (error != 0) {
925 goto fail;
926 }
927
928 mutex_enter(&cryptodev_mtx);
929 while (!(krp->krp_devflags & CRYPTODEV_F_RET)) {
930 cv_wait(&krp->krp_cv, &cryptodev_mtx); /* XXX cv_wait_sig? */
931 }
932 mutex_exit(&cryptodev_mtx);
933
934 if (krp->krp_status != 0) {
935 DPRINTF("krp->krp_status 0x%08x\n", krp->krp_status);
936 error = krp->krp_status;
937 goto fail;
938 }
939
940 for (i = krp->krp_iparams; i < krp->krp_iparams + krp->krp_oparams;
941 i++) {
942 size = (krp->krp_param[i].crp_nbits + 7) / 8;
943 if (size == 0)
944 continue;
945 error = copyout(krp->krp_param[i].crp_p,
946 kop->crk_param[i].crp_p, size);
947 if (error) {
948 DPRINTF("copyout oparam %d failed, "
949 "error=%d\n", i-krp->krp_iparams, error);
950 goto fail;
951 }
952 }
953
954 fail:
955 kop->crk_status = krp->krp_status;
956 for (i = 0; i < CRK_MAXPARAM; i++) {
957 struct crparam *kp = &(krp->krp_param[i]);
958 if (krp->krp_param[i].crp_p) {
959 size = (kp->crp_nbits + 7) / 8;
960 KASSERT(size > 0);
961 (void)memset(kp->crp_p, 0, size);
962 kmem_free(kp->crp_p, size);
963 }
964 }
965 cv_destroy(&krp->krp_cv);
966 crypto_kfreereq(krp);
967 DPRINTF("error=0x%08x\n", error);
968 return error;
969 }
970
971 /* ARGSUSED */
972 static int
973 cryptof_close(struct file *fp)
974 {
975 struct fcrypt *fcr = fp->f_fcrypt;
976 struct csession *cse;
977
978 mutex_enter(&cryptodev_mtx);
979 while ((cse = TAILQ_FIRST(&fcr->csessions))) {
980 TAILQ_REMOVE(&fcr->csessions, cse, next);
981 mutex_exit(&cryptodev_mtx);
982 (void)csefree(cse);
983 mutex_enter(&cryptodev_mtx);
984 }
985 seldestroy(&fcr->sinfo);
986 fp->f_fcrypt = NULL;
987 crypto_refcount--;
988 mutex_exit(&cryptodev_mtx);
989
990 pool_put(&fcrpl, fcr);
991 return 0;
992 }
993
994 /* needed for compatibility module */
995 struct csession *cryptodev_csefind(struct fcrypt *fcr, u_int ses)
996 {
997 return csefind(fcr, ses);
998 }
999
1000 /* csefind: call with cryptodev_mtx held. */
1001 static struct csession *
1002 csefind(struct fcrypt *fcr, u_int ses)
1003 {
1004 struct csession *cse, *cnext, *ret = NULL;
1005
1006 KASSERT(mutex_owned(&cryptodev_mtx));
1007 TAILQ_FOREACH_SAFE(cse, &fcr->csessions, next, cnext)
1008 if (cse->ses == ses)
1009 ret = cse;
1010
1011 return ret;
1012 }
1013
1014 /* csedelete: call with cryptodev_mtx held. */
1015 static int
1016 csedelete(struct fcrypt *fcr, struct csession *cse_del)
1017 {
1018 struct csession *cse, *cnext;
1019 int ret = 0;
1020
1021 KASSERT(mutex_owned(&cryptodev_mtx));
1022 TAILQ_FOREACH_SAFE(cse, &fcr->csessions, next, cnext) {
1023 if (cse == cse_del) {
1024 TAILQ_REMOVE(&fcr->csessions, cse, next);
1025 ret = 1;
1026 }
1027 }
1028 return ret;
1029 }
1030
1031 static struct csession *
1032 cseadd(struct fcrypt *fcr, struct csession *cse)
1033 {
1034 mutex_enter(&cryptodev_mtx);
1035 /* don't let session ID wrap! */
1036 if (fcr->sesn + 1 == 0) return NULL;
1037 TAILQ_INSERT_TAIL(&fcr->csessions, cse, next);
1038 cse->ses = fcr->sesn++;
1039 mutex_exit(&cryptodev_mtx);
1040 return cse;
1041 }
1042
1043 static struct csession *
1044 csecreate(struct fcrypt *fcr, u_int64_t sid, void *key, u_int64_t keylen,
1045 void *mackey, u_int64_t mackeylen, u_int32_t cipher, u_int32_t mac,
1046 u_int32_t comp_alg, const struct enc_xform *txform,
1047 const struct auth_hash *thash, const struct comp_algo *tcomp)
1048 {
1049 struct csession *cse;
1050
1051 cse = pool_get(&csepl, PR_NOWAIT);
1052 if (cse == NULL)
1053 return NULL;
1054 cse->key = key;
1055 cse->keylen = keylen/8;
1056 cse->mackey = mackey;
1057 cse->mackeylen = mackeylen/8;
1058 cse->sid = sid;
1059 cse->cipher = cipher;
1060 cse->mac = mac;
1061 cse->comp_alg = comp_alg;
1062 cse->txform = txform;
1063 cse->thash = thash;
1064 cse->tcomp = tcomp;
1065 cse->error = 0;
1066 if (cseadd(fcr, cse))
1067 return cse;
1068 else {
1069 pool_put(&csepl, cse);
1070 return NULL;
1071 }
1072 }
1073
1074 /* csefree: call with cryptodev_mtx held. */
1075 static int
1076 csefree(struct csession *cse)
1077 {
1078 int error;
1079
1080 error = crypto_freesession(cse->sid);
1081 if (cse->key)
1082 free(cse->key, M_XDATA);
1083 if (cse->mackey)
1084 free(cse->mackey, M_XDATA);
1085 pool_put(&csepl, cse);
1086 return error;
1087 }
1088
1089 static int
1090 cryptoopen(dev_t dev, int flag, int mode,
1091 struct lwp *l)
1092 {
1093 file_t *fp;
1094 struct fcrypt *fcr;
1095 int fd, error;
1096
1097 if (crypto_usercrypto == 0)
1098 return ENXIO;
1099
1100 if ((error = fd_allocfile(&fp, &fd)) != 0)
1101 return error;
1102
1103 fcr = pool_get(&fcrpl, PR_WAITOK);
1104 getnanotime(&fcr->btime);
1105 fcr->atime = fcr->mtime = fcr->btime;
1106 mutex_enter(&cryptodev_mtx);
1107 TAILQ_INIT(&fcr->csessions);
1108 TAILQ_INIT(&fcr->crp_ret_mq);
1109 TAILQ_INIT(&fcr->crp_ret_mkq);
1110 selinit(&fcr->sinfo);
1111 /*
1112 * Don't ever return session 0, to allow detection of
1113 * failed creation attempts with multi-create ioctl.
1114 */
1115 fcr->sesn = 1;
1116 fcr->requestid = 1;
1117 crypto_refcount++;
1118 mutex_exit(&cryptodev_mtx);
1119 return fd_clone(fp, fd, flag, &cryptofops, fcr);
1120 }
1121
1122 static int
1123 cryptoread(dev_t dev, struct uio *uio, int ioflag)
1124 {
1125 return EIO;
1126 }
1127
1128 static int
1129 cryptowrite(dev_t dev, struct uio *uio, int ioflag)
1130 {
1131 return EIO;
1132 }
1133
1134 int
1135 cryptoselect(dev_t dev, int rw, struct lwp *l)
1136 {
1137 return 0;
1138 }
1139
1140 /*static*/
1141 struct cdevsw crypto_cdevsw = {
1142 .d_open = cryptoopen,
1143 .d_close = noclose,
1144 .d_read = cryptoread,
1145 .d_write = cryptowrite,
1146 .d_ioctl = noioctl,
1147 .d_stop = nostop,
1148 .d_tty = notty,
1149 .d_poll = cryptoselect /*nopoll*/,
1150 .d_mmap = nommap,
1151 .d_kqfilter = nokqfilter,
1152 .d_discard = nodiscard,
1153 .d_flag = D_OTHER
1154 };
1155
1156 int
1157 cryptodev_mop(struct fcrypt *fcr,
1158 struct crypt_n_op * cnop,
1159 int count, struct lwp *l)
1160 {
1161 struct cryptop *crp = NULL;
1162 struct cryptodesc *crde = NULL, *crda = NULL, *crdc = NULL;
1163 int req, error=0;
1164 struct csession *cse;
1165 int flags=0;
1166 int iov_len;
1167
1168 for (req = 0; req < count; req++) {
1169 mutex_enter(&cryptodev_mtx);
1170 cse = csefind(fcr, cnop[req].ses);
1171 if (cse == NULL) {
1172 DPRINTF("csefind failed\n");
1173 cnop[req].status = EINVAL;
1174 mutex_exit(&cryptodev_mtx);
1175 continue;
1176 }
1177 mutex_exit(&cryptodev_mtx);
1178
1179 if (cnop[req].len > 256*1024-4) {
1180 DPRINTF("length failed\n");
1181 cnop[req].status = EINVAL;
1182 continue;
1183 }
1184 if (cse->txform) {
1185 if (cnop[req].len < cse->txform->blocksize -
1186 (cnop[req].iv ? 0 : cse->txform->ivsize) ||
1187 (cnop[req].len -
1188 (cnop[req].iv ? 0 : cse->txform->ivsize))
1189 % cse->txform->blocksize) {
1190 cnop[req].status = EINVAL;
1191 continue;
1192 }
1193 }
1194
1195 /* sanitize */
1196 if (cnop[req].len <= 0) {
1197 cnop[req].status = ENOMEM;
1198 goto bail;
1199 }
1200
1201 crp = crypto_getreq((cse->txform != NULL) +
1202 (cse->thash != NULL) +
1203 (cse->tcomp != NULL));
1204 if (crp == NULL) {
1205 cnop[req].status = ENOMEM;
1206 goto bail;
1207 }
1208
1209 iov_len = cnop[req].len;
1210 /* got a compression/decompression max size? */
1211 if ((cse->tcomp) && cnop[req].dst_len) {
1212 if (iov_len < cnop[req].dst_len) {
1213 /* Need larger iov to deal with decompress */
1214 iov_len = cnop[req].dst_len;
1215 }
1216 DPRINTF("iov_len -> %d for decompress\n", iov_len);
1217 }
1218
1219 (void)memset(&crp->uio, 0, sizeof(crp->uio));
1220 crp->uio.uio_iovcnt = 1;
1221 crp->uio.uio_resid = 0;
1222 crp->uio.uio_rw = UIO_WRITE;
1223 crp->uio.uio_iov = crp->iovec;
1224 UIO_SETUP_SYSSPACE(&crp->uio);
1225 memset(&crp->iovec, 0, sizeof(crp->iovec));
1226 crp->uio.uio_iov[0].iov_len = iov_len;
1227 DPRINTF("kmem_alloc(%d) for iov \n", iov_len);
1228 crp->uio.uio_iov[0].iov_base = kmem_alloc(iov_len, KM_SLEEP);
1229 crp->uio.uio_resid = crp->uio.uio_iov[0].iov_len;
1230
1231 if (cse->tcomp) {
1232 crdc = crp->crp_desc;
1233 }
1234
1235 if (cse->thash) {
1236 crda = crdc ? crdc->crd_next : crp->crp_desc;
1237 if (cse->txform && crda)
1238 crde = crda->crd_next;
1239 } else {
1240 if (cse->txform) {
1241 crde = crdc ? crdc->crd_next : crp->crp_desc;
1242 } else if (!cse->tcomp) {
1243 error = EINVAL;
1244 goto bail;
1245 }
1246 }
1247
1248 if ((copyin(cnop[req].src,
1249 crp->uio.uio_iov[0].iov_base, cnop[req].len))) {
1250 cnop[req].status = EINVAL;
1251 goto bail;
1252 }
1253
1254 if (crdc) {
1255 switch (cnop[req].op) {
1256 case COP_COMP:
1257 crdc->crd_flags |= CRD_F_COMP;
1258 break;
1259 case COP_DECOMP:
1260 crdc->crd_flags &= ~CRD_F_COMP;
1261 break;
1262 default:
1263 break;
1264 }
1265 /* more data to follow? */
1266 if (cnop[req].flags & COP_F_MORE) {
1267 flags |= CRYPTO_F_MORE;
1268 }
1269 crdc->crd_len = cnop[req].len;
1270 crdc->crd_inject = 0;
1271
1272 crdc->crd_alg = cse->comp_alg;
1273 crdc->crd_key = NULL;
1274 crdc->crd_klen = 0;
1275 DPRINTF("cse->sid[%d]: crdc setup for comp_alg %d"
1276 " len %d.\n",
1277 (uint32_t)cse->sid, crdc->crd_alg,
1278 crdc->crd_len);
1279 }
1280
1281 if (crda) {
1282 crda->crd_skip = 0;
1283 crda->crd_len = cnop[req].len;
1284 crda->crd_inject = 0; /* ??? */
1285
1286 crda->crd_alg = cse->mac;
1287 crda->crd_key = cse->mackey;
1288 crda->crd_klen = cse->mackeylen * 8;
1289 }
1290
1291 if (crde) {
1292 if (cnop[req].op == COP_ENCRYPT)
1293 crde->crd_flags |= CRD_F_ENCRYPT;
1294 else
1295 crde->crd_flags &= ~CRD_F_ENCRYPT;
1296 crde->crd_len = cnop[req].len;
1297 crde->crd_inject = 0;
1298
1299 crde->crd_alg = cse->cipher;
1300 #ifdef notyet /* XXX must notify h/w driver new key, drain */
1301 if(cnop[req].key && cnop[req].keylen) {
1302 crde->crd_key = malloc(cnop[req].keylen,
1303 M_XDATA, M_WAITOK);
1304 if((error = copyin(cnop[req].key,
1305 crde->crd_key, cnop[req].keylen))) {
1306 cnop[req].status = EINVAL;
1307 goto bail;
1308 }
1309 crde->crd_klen = cnop[req].keylen * 8;
1310 } else { ... }
1311 #endif
1312 crde->crd_key = cse->key;
1313 crde->crd_klen = cse->keylen * 8;
1314 }
1315
1316 crp->crp_ilen = cnop[req].len;
1317 crp->crp_flags = CRYPTO_F_IOV | CRYPTO_F_CBIMM |
1318 (cnop[req].flags & COP_F_BATCH) | flags;
1319 crp->crp_buf = (void *)&crp->uio;
1320 crp->crp_callback = (int (*) (struct cryptop *)) cryptodev_mcb;
1321 crp->crp_sid = cse->sid;
1322 crp->crp_opaque = (void *)cse;
1323 crp->fcrp = fcr;
1324 crp->dst = cnop[req].dst;
1325 crp->len = cnop[req].len; /* input len, iov may be larger */
1326 crp->mac = cnop[req].mac;
1327 DPRINTF("iov_base %p dst %p len %d mac %p\n",
1328 crp->uio.uio_iov[0].iov_base, crp->dst, crp->len,
1329 crp->mac);
1330
1331 if (cnop[req].iv) {
1332 if (crde == NULL) {
1333 cnop[req].status = EINVAL;
1334 goto bail;
1335 }
1336 if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */
1337 cnop[req].status = EINVAL;
1338 goto bail;
1339 }
1340 if ((error = copyin(cnop[req].iv, crp->tmp_iv,
1341 cse->txform->ivsize))) {
1342 cnop[req].status = EINVAL;
1343 goto bail;
1344 }
1345 (void)memcpy(crde->crd_iv, crp->tmp_iv,
1346 cse->txform->ivsize);
1347 crde->crd_flags |= CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT;
1348 crde->crd_skip = 0;
1349 } else if (crde) {
1350 if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */
1351 crde->crd_skip = 0;
1352 } else {
1353 if (!(crde->crd_flags & CRD_F_ENCRYPT))
1354 crde->crd_flags |= CRD_F_IV_PRESENT;
1355 crde->crd_skip = cse->txform->ivsize;
1356 crde->crd_len -= cse->txform->ivsize;
1357 }
1358 }
1359
1360 if (cnop[req].mac) {
1361 if (crda == NULL) {
1362 cnop[req].status = EINVAL;
1363 goto bail;
1364 }
1365 crp->crp_mac=cse->tmp_mac;
1366 }
1367 cnop[req].reqid = atomic_inc_32_nv(&(fcr->requestid));
1368 crp->crp_reqid = cnop[req].reqid;
1369 crp->crp_usropaque = cnop[req].opaque;
1370 cv_init(&crp->crp_cv, "crydev");
1371 #ifdef notyet
1372 eagain:
1373 #endif
1374 cnop[req].status = crypto_dispatch(crp);
1375 mutex_enter(&cryptodev_mtx); /* XXX why mutex? */
1376
1377 switch (cnop[req].status) {
1378 #ifdef notyet /* don't loop forever -- but EAGAIN not possible here yet */
1379 case EAGAIN:
1380 mutex_exit(&cryptodev_mtx);
1381 goto eagain;
1382 break;
1383 #endif
1384 case 0:
1385 break;
1386 default:
1387 DPRINTF("not waiting, error.\n");
1388 mutex_exit(&cryptodev_mtx);
1389 cv_destroy(&crp->crp_cv);
1390 goto bail;
1391 }
1392
1393 mutex_exit(&cryptodev_mtx);
1394 cv_destroy(&crp->crp_cv);
1395 bail:
1396 if (cnop[req].status) {
1397 if (crp) {
1398 if (crp->uio.uio_iov[0].iov_base) {
1399 kmem_free(crp->uio.uio_iov[0].iov_base,
1400 crp->uio.uio_iov[0].iov_len);
1401 }
1402 crypto_freereq(crp);
1403 }
1404 error = 0;
1405 }
1406 }
1407 return error;
1408 }
1409
1410 static int
1411 cryptodev_mkey(struct fcrypt *fcr, struct crypt_n_kop *kop, int count)
1412 {
1413 struct cryptkop *krp = NULL;
1414 int error = EINVAL;
1415 int in, out, size, i, req;
1416
1417 for (req = 0; req < count; req++) {
1418 if (kop[req].crk_iparams + kop[req].crk_oparams > CRK_MAXPARAM)
1419 return EFBIG;
1420
1421 in = kop[req].crk_iparams;
1422 out = kop[req].crk_oparams;
1423 switch (kop[req].crk_op) {
1424 case CRK_MOD_EXP:
1425 if (in == 3 && out == 1)
1426 break;
1427 kop[req].crk_status = EINVAL;
1428 continue;
1429 case CRK_MOD_EXP_CRT:
1430 if (in == 6 && out == 1)
1431 break;
1432 kop[req].crk_status = EINVAL;
1433 continue;
1434 case CRK_DSA_SIGN:
1435 if (in == 5 && out == 2)
1436 break;
1437 kop[req].crk_status = EINVAL;
1438 continue;
1439 case CRK_DSA_VERIFY:
1440 if (in == 7 && out == 0)
1441 break;
1442 kop[req].crk_status = EINVAL;
1443 continue;
1444 case CRK_DH_COMPUTE_KEY:
1445 if (in == 3 && out == 1)
1446 break;
1447 kop[req].crk_status = EINVAL;
1448 continue;
1449 case CRK_MOD_ADD:
1450 if (in == 3 && out == 1)
1451 break;
1452 kop[req].crk_status = EINVAL;
1453 continue;
1454 case CRK_MOD_ADDINV:
1455 if (in == 2 && out == 1)
1456 break;
1457 kop[req].crk_status = EINVAL;
1458 continue;
1459 case CRK_MOD_SUB:
1460 if (in == 3 && out == 1)
1461 break;
1462 kop[req].crk_status = EINVAL;
1463 continue;
1464 case CRK_MOD_MULT:
1465 if (in == 3 && out == 1)
1466 break;
1467 kop[req].crk_status = EINVAL;
1468 continue;
1469 case CRK_MOD_MULTINV:
1470 if (in == 2 && out == 1)
1471 break;
1472 kop[req].crk_status = EINVAL;
1473 continue;
1474 case CRK_MOD:
1475 if (in == 2 && out == 1)
1476 break;
1477 kop[req].crk_status = EINVAL;
1478 continue;
1479 default:
1480 kop[req].crk_status = EINVAL;
1481 continue;
1482 }
1483
1484 krp = crypto_kgetreq(1, PR_WAITOK);
1485 if (krp == NULL) {
1486 /* limited by opencrypto.crypto_ret_kq.maxlen */
1487 continue;
1488 }
1489 (void)memset(krp, 0, sizeof *krp);
1490 cv_init(&krp->krp_cv, "crykdev");
1491 krp->krp_op = kop[req].crk_op;
1492 krp->krp_status = kop[req].crk_status;
1493 krp->krp_iparams = kop[req].crk_iparams;
1494 krp->krp_oparams = kop[req].crk_oparams;
1495 krp->krp_status = 0;
1496 krp->krp_callback =
1497 (int (*) (struct cryptkop *)) cryptodevkey_mcb;
1498 (void)memcpy(krp->crk_param, kop[req].crk_param,
1499 sizeof(kop[req].crk_param));
1500
1501 krp->krp_flags = CRYPTO_F_CBIMM;
1502
1503 for (i = 0; i < CRK_MAXPARAM; i++)
1504 krp->krp_param[i].crp_nbits =
1505 kop[req].crk_param[i].crp_nbits;
1506 for (i = 0; i < krp->krp_iparams + krp->krp_oparams; i++) {
1507 size = (krp->krp_param[i].crp_nbits + 7) / 8;
1508 if (size == 0)
1509 continue;
1510 krp->krp_param[i].crp_p =
1511 kmem_alloc(size, KM_SLEEP);
1512 if (i >= krp->krp_iparams)
1513 continue;
1514 kop[req].crk_status =
1515 copyin(kop[req].crk_param[i].crp_p,
1516 krp->krp_param[i].crp_p, size);
1517 if (kop[req].crk_status)
1518 goto fail;
1519 }
1520 krp->fcrp = fcr;
1521
1522 kop[req].crk_reqid = atomic_inc_32_nv(&(fcr->requestid));
1523 krp->krp_reqid = kop[req].crk_reqid;
1524 krp->krp_usropaque = kop[req].crk_opaque;
1525
1526 kop[req].crk_status = crypto_kdispatch(krp);
1527 if (kop[req].crk_status != 0) {
1528 goto fail;
1529 }
1530
1531 fail:
1532 if(kop[req].crk_status) {
1533 if (krp) {
1534 kop[req].crk_status = krp->krp_status;
1535 for (i = 0; i < CRK_MAXPARAM; i++) {
1536 struct crparam *kp =
1537 &(krp->krp_param[i]);
1538 if (kp->crp_p) {
1539 size = (kp->crp_nbits + 7) / 8;
1540 KASSERT(size > 0);
1541 memset(kp->crp_p, 0, size);
1542 kmem_free(kp->crp_p, size);
1543 }
1544 }
1545 cv_destroy(&krp->krp_cv);
1546 crypto_kfreereq(krp);
1547 }
1548 }
1549 error = 0;
1550 }
1551 DPRINTF("error=0x%08x\n", error);
1552 return error;
1553 }
1554
1555 int
1556 cryptodev_session(struct fcrypt *fcr, struct session_op *sop)
1557 {
1558 struct cryptoini cria, crie;
1559 struct cryptoini cric; /* compressor */
1560 struct cryptoini *crihead = NULL;
1561 const struct enc_xform *txform = NULL;
1562 const struct auth_hash *thash = NULL;
1563 const struct comp_algo *tcomp = NULL;
1564 struct csession *cse;
1565 u_int64_t sid;
1566 int error = 0;
1567
1568 DPRINTF("cipher=%d, mac=%d\n", sop->cipher, sop->mac);
1569
1570 /* XXX there must be a way to not embed the list of xforms here */
1571 switch (sop->cipher) {
1572 case 0:
1573 break;
1574 case CRYPTO_DES_CBC:
1575 txform = &enc_xform_des;
1576 break;
1577 case CRYPTO_3DES_CBC:
1578 txform = &enc_xform_3des;
1579 break;
1580 case CRYPTO_BLF_CBC:
1581 txform = &enc_xform_blf;
1582 break;
1583 case CRYPTO_CAST_CBC:
1584 txform = &enc_xform_cast5;
1585 break;
1586 case CRYPTO_SKIPJACK_CBC:
1587 txform = &enc_xform_skipjack;
1588 break;
1589 case CRYPTO_AES_CBC:
1590 txform = &enc_xform_rijndael128;
1591 break;
1592 case CRYPTO_CAMELLIA_CBC:
1593 txform = &enc_xform_camellia;
1594 break;
1595 case CRYPTO_AES_CTR:
1596 txform = &enc_xform_aes_ctr;
1597 break;
1598 case CRYPTO_AES_GCM_16:
1599 txform = &enc_xform_aes_gcm;
1600 break;
1601 case CRYPTO_AES_GMAC:
1602 txform = &enc_xform_aes_gmac;
1603 break;
1604 case CRYPTO_NULL_CBC:
1605 txform = &enc_xform_null;
1606 break;
1607 case CRYPTO_ARC4:
1608 txform = &enc_xform_arc4;
1609 break;
1610 default:
1611 DPRINTF("Invalid cipher %d\n", sop->cipher);
1612 return EINVAL;
1613 }
1614
1615 switch (sop->comp_alg) {
1616 case 0:
1617 break;
1618 case CRYPTO_DEFLATE_COMP:
1619 tcomp = &comp_algo_deflate;
1620 break;
1621 case CRYPTO_GZIP_COMP:
1622 tcomp = &comp_algo_gzip;
1623 DPRINTF("tcomp for GZIP\n");
1624 break;
1625 default:
1626 DPRINTF("Invalid compression alg %d\n", sop->comp_alg);
1627 return EINVAL;
1628 }
1629
1630 switch (sop->mac) {
1631 case 0:
1632 break;
1633 case CRYPTO_MD5_HMAC:
1634 thash = &auth_hash_hmac_md5;
1635 break;
1636 case CRYPTO_SHA1_HMAC:
1637 thash = &auth_hash_hmac_sha1;
1638 break;
1639 case CRYPTO_MD5_HMAC_96:
1640 thash = &auth_hash_hmac_md5_96;
1641 break;
1642 case CRYPTO_SHA1_HMAC_96:
1643 thash = &auth_hash_hmac_sha1_96;
1644 break;
1645 case CRYPTO_SHA2_HMAC:
1646 /* XXX switching on key length seems questionable */
1647 if (sop->mackeylen == auth_hash_hmac_sha2_256.keysize) {
1648 thash = &auth_hash_hmac_sha2_256;
1649 } else if (sop->mackeylen == auth_hash_hmac_sha2_384.keysize) {
1650 thash = &auth_hash_hmac_sha2_384;
1651 } else if (sop->mackeylen == auth_hash_hmac_sha2_512.keysize) {
1652 thash = &auth_hash_hmac_sha2_512;
1653 } else {
1654 DPRINTF("Invalid mackeylen %d\n", sop->mackeylen);
1655 return EINVAL;
1656 }
1657 break;
1658 case CRYPTO_RIPEMD160_HMAC:
1659 thash = &auth_hash_hmac_ripemd_160;
1660 break;
1661 case CRYPTO_RIPEMD160_HMAC_96:
1662 thash = &auth_hash_hmac_ripemd_160_96;
1663 break;
1664 case CRYPTO_MD5:
1665 thash = &auth_hash_md5;
1666 break;
1667 case CRYPTO_SHA1:
1668 thash = &auth_hash_sha1;
1669 break;
1670 case CRYPTO_AES_XCBC_MAC_96:
1671 thash = &auth_hash_aes_xcbc_mac_96;
1672 break;
1673 case CRYPTO_AES_128_GMAC:
1674 thash = &auth_hash_gmac_aes_128;
1675 break;
1676 case CRYPTO_AES_192_GMAC:
1677 thash = &auth_hash_gmac_aes_192;
1678 break;
1679 case CRYPTO_AES_256_GMAC:
1680 thash = &auth_hash_gmac_aes_256;
1681 break;
1682 case CRYPTO_NULL_HMAC:
1683 thash = &auth_hash_null;
1684 break;
1685 default:
1686 DPRINTF("Invalid mac %d\n", sop->mac);
1687 return EINVAL;
1688 }
1689
1690 memset(&crie, 0, sizeof(crie));
1691 memset(&cria, 0, sizeof(cria));
1692 memset(&cric, 0, sizeof(cric));
1693
1694 if (tcomp) {
1695 cric.cri_alg = tcomp->type;
1696 cric.cri_klen = 0;
1697 DPRINTF("tcomp->type = %d\n", tcomp->type);
1698
1699 crihead = &cric;
1700 if (txform) {
1701 cric.cri_next = &crie;
1702 } else if (thash) {
1703 cric.cri_next = &cria;
1704 }
1705 }
1706
1707 if (txform) {
1708 crie.cri_alg = txform->type;
1709 crie.cri_klen = sop->keylen * 8;
1710 if (sop->keylen > txform->maxkey ||
1711 sop->keylen < txform->minkey) {
1712 DPRINTF("keylen %d not in [%d,%d]\n",
1713 sop->keylen, txform->minkey, txform->maxkey);
1714 error = EINVAL;
1715 goto bail;
1716 }
1717
1718 crie.cri_key = malloc(crie.cri_klen / 8, M_XDATA, M_WAITOK);
1719 if ((error = copyin(sop->key, crie.cri_key, crie.cri_klen / 8)))
1720 goto bail;
1721 if (!crihead) {
1722 crihead = &crie;
1723 }
1724 if (thash)
1725 crie.cri_next = &cria;
1726 }
1727
1728 if (thash) {
1729 cria.cri_alg = thash->type;
1730 cria.cri_klen = sop->mackeylen * 8;
1731 if (sop->mackeylen != thash->keysize) {
1732 DPRINTF("mackeylen %d != keysize %d\n",
1733 sop->mackeylen, thash->keysize);
1734 error = EINVAL;
1735 goto bail;
1736 }
1737 if (cria.cri_klen) {
1738 cria.cri_key = malloc(cria.cri_klen / 8, M_XDATA,
1739 M_WAITOK);
1740 if ((error = copyin(sop->mackey, cria.cri_key,
1741 cria.cri_klen / 8))) {
1742 goto bail;
1743 }
1744 }
1745 if (!crihead) {
1746 crihead = &cria;
1747 }
1748 }
1749
1750 error = crypto_newsession(&sid, crihead, crypto_devallowsoft);
1751 if (!error) {
1752 DPRINTF("got session %d\n", (uint32_t)sid);
1753 cse = csecreate(fcr, sid, crie.cri_key, crie.cri_klen,
1754 cria.cri_key, cria.cri_klen, (txform ? sop->cipher : 0), sop->mac,
1755 (tcomp ? sop->comp_alg : 0), txform, thash, tcomp);
1756 if (cse != NULL) {
1757 sop->ses = cse->ses;
1758 } else {
1759 DPRINTF("csecreate failed\n");
1760 crypto_freesession(sid);
1761 error = EINVAL;
1762 }
1763 } else {
1764 DPRINTF("SIOCSESSION violates kernel parameters %d\n", error);
1765 }
1766 bail:
1767 if (error) {
1768 if (crie.cri_key) {
1769 memset(crie.cri_key, 0, crie.cri_klen / 8);
1770 free(crie.cri_key, M_XDATA);
1771 }
1772 if (cria.cri_key) {
1773 memset(cria.cri_key, 0, cria.cri_klen / 8);
1774 free(cria.cri_key, M_XDATA);
1775 }
1776 }
1777 return error;
1778 }
1779
1780 int
1781 cryptodev_msession(struct fcrypt *fcr, struct session_n_op *sn_ops,
1782 int count)
1783 {
1784 int i;
1785
1786 for (i = 0; i < count; i++, sn_ops++) {
1787 struct session_op s_op;
1788 s_op.cipher = sn_ops->cipher;
1789 s_op.mac = sn_ops->mac;
1790 s_op.comp_alg = sn_ops->comp_alg;
1791 s_op.keylen = sn_ops->keylen;
1792 s_op.key = sn_ops->key;
1793 s_op.mackeylen = sn_ops->mackeylen;
1794 s_op.mackey = sn_ops->mackey;
1795
1796 sn_ops->status = cryptodev_session(fcr, &s_op);
1797
1798 sn_ops->ses = s_op.ses;
1799 }
1800
1801 return 0;
1802 }
1803
1804 static int
1805 cryptodev_msessionfin(struct fcrypt *fcr, int count, u_int32_t *sesid)
1806 {
1807 struct csession *cse;
1808 int req, error = 0;
1809
1810 mutex_enter(&cryptodev_mtx);
1811 for(req = 0; req < count; req++) {
1812 cse = csefind(fcr, sesid[req]);
1813 if (cse == NULL)
1814 continue;
1815 csedelete(fcr, cse);
1816 mutex_exit(&cryptodev_mtx);
1817 error = csefree(cse);
1818 mutex_enter(&cryptodev_mtx);
1819 }
1820 mutex_exit(&cryptodev_mtx);
1821 return error;
1822 }
1823
1824 /*
1825 * collect as many completed requests as are availble, or count completed
1826 * requests whichever is less.
1827 * return the number of requests.
1828 */
1829 static int
1830 cryptodev_getmstatus(struct fcrypt *fcr, struct crypt_result *crypt_res,
1831 int count)
1832 {
1833 struct cryptop *crp = NULL;
1834 struct cryptkop *krp = NULL;
1835 struct csession *cse;
1836 int i, size, req = 0;
1837 int completed=0;
1838
1839 /* On queue so nobody else can grab them
1840 * and copyout can be delayed-- no locking */
1841 TAILQ_HEAD(, cryptop) crp_delfree_q =
1842 TAILQ_HEAD_INITIALIZER(crp_delfree_q);
1843 TAILQ_HEAD(, cryptkop) krp_delfree_q =
1844 TAILQ_HEAD_INITIALIZER(krp_delfree_q);
1845
1846 /* at this point we do not know which response user is requesting for
1847 * (symmetric or asymmetric) so we copyout one from each i.e if the
1848 * count is 2 then 1 from symmetric and 1 from asymmetric queue and
1849 * if 3 then 2 symmetric and 1 asymmetric and so on */
1850
1851 /* pull off a list of requests while protected from changes */
1852 mutex_enter(&cryptodev_mtx);
1853 while (req < count) {
1854 crp = TAILQ_FIRST(&fcr->crp_ret_mq);
1855 if (crp) {
1856 TAILQ_REMOVE(&fcr->crp_ret_mq, crp, crp_next);
1857 TAILQ_INSERT_TAIL(&crp_delfree_q, crp, crp_next);
1858 cse = (struct csession *)crp->crp_opaque;
1859
1860 /* see if the session is still valid */
1861 cse = csefind(fcr, cse->ses);
1862 if (cse != NULL) {
1863 crypt_res[req].status = 0;
1864 } else {
1865 DPRINTF("csefind failed\n");
1866 crypt_res[req].status = EINVAL;
1867 }
1868 req++;
1869 }
1870 if(req < count) {
1871 crypt_res[req].status = 0;
1872 krp = TAILQ_FIRST(&fcr->crp_ret_mkq);
1873 if (krp) {
1874 TAILQ_REMOVE(&fcr->crp_ret_mkq, krp, krp_next);
1875 TAILQ_INSERT_TAIL(&krp_delfree_q, krp, krp_next);
1876 req++;
1877 }
1878 }
1879 }
1880 mutex_exit(&cryptodev_mtx);
1881
1882 /* now do all the work outside the mutex */
1883 for(req=0; req < count ;) {
1884 crp = TAILQ_FIRST(&crp_delfree_q);
1885 if (crp) {
1886 if (crypt_res[req].status != 0) {
1887 /* csefind failed during collection */
1888 goto bail;
1889 }
1890 cse = (struct csession *)crp->crp_opaque;
1891 crypt_res[req].reqid = crp->crp_reqid;
1892 crypt_res[req].opaque = crp->crp_usropaque;
1893 completed++;
1894
1895 if (crp->crp_etype != 0) {
1896 crypt_res[req].status = crp->crp_etype;
1897 goto bail;
1898 }
1899
1900 if (cse->error) {
1901 crypt_res[req].status = cse->error;
1902 goto bail;
1903 }
1904
1905 if (crp->dst && (crypt_res[req].status =
1906 copyout(crp->uio.uio_iov[0].iov_base, crp->dst,
1907 crp->len)))
1908 goto bail;
1909
1910 if (crp->mac && (crypt_res[req].status =
1911 copyout(crp->crp_mac, crp->mac,
1912 cse->thash->authsize)))
1913 goto bail;
1914
1915 bail:
1916 TAILQ_REMOVE(&crp_delfree_q, crp, crp_next);
1917 kmem_free(crp->uio.uio_iov[0].iov_base,
1918 crp->uio.uio_iov[0].iov_len);
1919 crypto_freereq(crp);
1920 req++;
1921 }
1922
1923 if (req < count) {
1924 krp = TAILQ_FIRST(&krp_delfree_q);
1925 if (krp) {
1926 crypt_res[req].reqid = krp->krp_reqid;
1927 crypt_res[req].opaque = krp->krp_usropaque;
1928 completed++;
1929 if (krp->krp_status != 0) {
1930 DPRINTF("krp->krp_status 0x%08x\n",
1931 krp->krp_status);
1932 crypt_res[req].status = krp->krp_status;
1933 goto fail;
1934 }
1935
1936 for (i = krp->krp_iparams; i < krp->krp_iparams
1937 + krp->krp_oparams; i++) {
1938 size = (krp->krp_param[i].crp_nbits
1939 + 7) / 8;
1940 if (size == 0)
1941 continue;
1942 crypt_res[req].status = copyout
1943 (krp->krp_param[i].crp_p,
1944 krp->crk_param[i].crp_p, size);
1945 if (crypt_res[req].status) {
1946 DPRINTF("copyout oparam %d failed, "
1947 "error=%d\n",
1948 i - krp->krp_iparams,
1949 crypt_res[req].status);
1950 goto fail;
1951 }
1952 }
1953 fail:
1954 TAILQ_REMOVE(&krp_delfree_q, krp, krp_next);
1955 /* not sure what to do for this */
1956 /* kop[req].crk_status = krp->krp_status; */
1957 for (i = 0; i < CRK_MAXPARAM; i++) {
1958 struct crparam *kp = &(krp->krp_param[i]);
1959 if (kp->crp_p) {
1960 size = (kp->crp_nbits + 7) / 8;
1961 KASSERT(size > 0);
1962 (void)memset(kp->crp_p, 0, size);
1963 kmem_free(kp->crp_p, size);
1964 }
1965 }
1966 cv_destroy(&krp->krp_cv);
1967 crypto_kfreereq(krp);
1968 req++;
1969 }
1970 }
1971 }
1972
1973 return completed;
1974 }
1975
1976 static int
1977 cryptodev_getstatus (struct fcrypt *fcr, struct crypt_result *crypt_res)
1978 {
1979 struct cryptop *crp = NULL, *cnext;
1980 struct cryptkop *krp = NULL, *knext;
1981 struct csession *cse;
1982 int i, size, req = 0;
1983
1984 mutex_enter(&cryptodev_mtx);
1985 /* Here we dont know for which request the user is requesting the
1986 * response so checking in both the queues */
1987 TAILQ_FOREACH_SAFE(crp, &fcr->crp_ret_mq, crp_next, cnext) {
1988 if(crp && (crp->crp_reqid == crypt_res->reqid)) {
1989 cse = (struct csession *)crp->crp_opaque;
1990 crypt_res->opaque = crp->crp_usropaque;
1991 cse = csefind(fcr, cse->ses);
1992 if (cse == NULL) {
1993 DPRINTF("csefind failed\n");
1994 crypt_res->status = EINVAL;
1995 goto bail;
1996 }
1997
1998 if (crp->crp_etype != 0) {
1999 crypt_res->status = crp->crp_etype;
2000 goto bail;
2001 }
2002
2003 if (cse->error) {
2004 crypt_res->status = cse->error;
2005 goto bail;
2006 }
2007
2008 if (crp->dst && (crypt_res->status =
2009 copyout(crp->uio.uio_iov[0].iov_base,
2010 crp->dst, crp->len)))
2011 goto bail;
2012
2013 if (crp->mac && (crypt_res->status =
2014 copyout(crp->crp_mac, crp->mac,
2015 cse->thash->authsize)))
2016 goto bail;
2017 bail:
2018 TAILQ_REMOVE(&fcr->crp_ret_mq, crp, crp_next);
2019
2020 mutex_exit(&cryptodev_mtx);
2021 crypto_freereq(crp);
2022 return 0;
2023 }
2024 }
2025
2026 TAILQ_FOREACH_SAFE(krp, &fcr->crp_ret_mkq, krp_next, knext) {
2027 if(krp && (krp->krp_reqid == crypt_res->reqid)) {
2028 crypt_res[req].opaque = krp->krp_usropaque;
2029 if (krp->krp_status != 0) {
2030 DPRINTF("krp->krp_status 0x%08x\n",
2031 krp->krp_status);
2032 crypt_res[req].status = krp->krp_status;
2033 goto fail;
2034 }
2035
2036 for (i = krp->krp_iparams; i < krp->krp_iparams +
2037 krp->krp_oparams; i++) {
2038 size = (krp->krp_param[i].crp_nbits + 7) / 8;
2039 if (size == 0)
2040 continue;
2041 crypt_res[req].status = copyout(
2042 krp->krp_param[i].crp_p,
2043 krp->crk_param[i].crp_p, size);
2044 if (crypt_res[req].status) {
2045 DPRINTF("copyout oparam "
2046 "%d failed, error=%d\n",
2047 i - krp->krp_iparams,
2048 crypt_res[req].status);
2049 goto fail;
2050 }
2051 }
2052 fail:
2053 TAILQ_REMOVE(&fcr->crp_ret_mkq, krp, krp_next);
2054 mutex_exit(&cryptodev_mtx);
2055 /* not sure what to do for this */
2056 /* kop[req].crk_status = krp->krp_status; */
2057 for (i = 0; i < CRK_MAXPARAM; i++) {
2058 struct crparam *kp = &(krp->krp_param[i]);
2059 if (kp->crp_p) {
2060 size = (kp->crp_nbits + 7) / 8;
2061 KASSERT(size > 0);
2062 memset(kp->crp_p, 0, size);
2063 kmem_free(kp->crp_p, size);
2064 }
2065 }
2066 cv_destroy(&krp->krp_cv);
2067 crypto_kfreereq(krp);
2068 return 0;
2069 }
2070 }
2071 mutex_exit(&cryptodev_mtx);
2072 return EINPROGRESS;
2073 }
2074
2075 static int
2076 cryptof_stat(struct file *fp, struct stat *st)
2077 {
2078 struct fcrypt *fcr = fp->f_fcrypt;
2079
2080 (void)memset(st, 0, sizeof(*st));
2081
2082 mutex_enter(&cryptodev_mtx);
2083 st->st_dev = makedev(cdevsw_lookup_major(&crypto_cdevsw), fcr->sesn);
2084 st->st_atimespec = fcr->atime;
2085 st->st_mtimespec = fcr->mtime;
2086 st->st_ctimespec = st->st_birthtimespec = fcr->btime;
2087 st->st_uid = kauth_cred_geteuid(fp->f_cred);
2088 st->st_gid = kauth_cred_getegid(fp->f_cred);
2089 mutex_exit(&cryptodev_mtx);
2090
2091 return 0;
2092 }
2093
2094 static int
2095 cryptof_poll(struct file *fp, int events)
2096 {
2097 struct fcrypt *fcr = fp->f_fcrypt;
2098 int revents = 0;
2099
2100 if (!(events & (POLLIN | POLLRDNORM))) {
2101 /* only support read and POLLIN */
2102 return 0;
2103 }
2104
2105 mutex_enter(&cryptodev_mtx);
2106 if (TAILQ_EMPTY(&fcr->crp_ret_mq) && TAILQ_EMPTY(&fcr->crp_ret_mkq)) {
2107 /* no completed requests pending, save the poll for later */
2108 selrecord(curlwp, &fcr->sinfo);
2109 } else {
2110 /* let the app(s) know that there are completed requests */
2111 revents = events & (POLLIN | POLLRDNORM);
2112 }
2113 mutex_exit(&cryptodev_mtx);
2114
2115 return revents;
2116 }
2117
2118 /*
2119 * Pseudo-device initialization routine for /dev/crypto
2120 */
2121 void
2122 cryptoattach(int num)
2123 {
2124 int error;
2125
2126 crypto_init();
2127
2128 mutex_init(&cryptodev_mtx, MUTEX_DEFAULT, IPL_NONE);
2129
2130 pool_init(&fcrpl, sizeof(struct fcrypt), 0, 0, 0, "fcrpl",
2131 NULL, IPL_NET); /* XXX IPL_NET ("splcrypto") */
2132 pool_init(&csepl, sizeof(struct csession), 0, 0, 0, "csepl",
2133 NULL, IPL_NET); /* XXX IPL_NET ("splcrypto") */
2134
2135 /*
2136 * Preallocate space for 64 users, with 5 sessions each.
2137 * (consider that a TLS protocol session requires at least
2138 * 3DES, MD5, and SHA1 (both hashes are used in the PRF) for
2139 * the negotiation, plus HMAC_SHA1 for the actual SSL records,
2140 * consuming one session here for each algorithm.
2141 */
2142 if ((error = pool_prime(&fcrpl, 64)) != 0 ||
2143 (error = pool_prime(&csepl, 64 * 5)) != 0)
2144 panic("%s: can't prime pool: %d", __func__, error);
2145 }
2146
2147 void crypto_attach(device_t, device_t, void *);
2148
2149 void
2150 crypto_attach(device_t parent, device_t self, void * opaque)
2151 {
2152
2153 cryptoattach(0);
2154 }
2155
2156 int crypto_detach(device_t, int);
2157
2158 int
2159 crypto_detach(device_t self, int num)
2160 {
2161
2162 pool_destroy(&fcrpl);
2163 pool_destroy(&csepl);
2164
2165 mutex_destroy(&cryptodev_mtx);
2166
2167 return 0;
2168 }
2169
2170 int crypto_match(device_t, cfdata_t, void *);
2171
2172 int
2173 crypto_match(device_t parent, cfdata_t data, void *opaque)
2174 {
2175
2176 return 1;
2177 }
2178
2179 MODULE(MODULE_CLASS_DRIVER, crypto, "opencrypto");
2180
2181 CFDRIVER_DECL(crypto, DV_DULL, NULL);
2182
2183 CFATTACH_DECL2_NEW(crypto, 0, crypto_match, crypto_attach, crypto_detach,
2184 NULL, NULL, NULL);
2185
2186 #ifdef _MODULE
2187 static int cryptoloc[] = { -1, -1 };
2188
2189 static struct cfdata crypto_cfdata[] = {
2190 {
2191 .cf_name = "crypto",
2192 .cf_atname = "crypto",
2193 .cf_unit = 0,
2194 .cf_fstate = 0,
2195 .cf_loc = cryptoloc,
2196 .cf_flags = 0,
2197 .cf_pspec = NULL,
2198 },
2199 { NULL, NULL, 0, 0, NULL, 0, NULL }
2200 };
2201 #endif
2202
2203 static int
2204 crypto_modcmd(modcmd_t cmd, void *arg)
2205 {
2206 int error = 0;
2207 #ifdef _MODULE
2208 devmajor_t cmajor = NODEVMAJOR, bmajor = NODEVMAJOR;
2209 #endif
2210
2211 switch (cmd) {
2212 case MODULE_CMD_INIT:
2213 #ifdef _MODULE
2214
2215 error = config_cfdriver_attach(&crypto_cd);
2216 if (error) {
2217 return error;
2218 }
2219
2220 error = config_cfattach_attach(crypto_cd.cd_name, &crypto_ca);
2221 if (error) {
2222 config_cfdriver_detach(&crypto_cd);
2223 aprint_error("%s: unable to register cfattach\n",
2224 crypto_cd.cd_name);
2225
2226 return error;
2227 }
2228
2229 error = config_cfdata_attach(crypto_cfdata, 1);
2230 if (error) {
2231 config_cfattach_detach(crypto_cd.cd_name, &crypto_ca);
2232 config_cfdriver_detach(&crypto_cd);
2233 aprint_error("%s: unable to register cfdata\n",
2234 crypto_cd.cd_name);
2235
2236 return error;
2237 }
2238
2239 error = devsw_attach(crypto_cd.cd_name, NULL, &bmajor,
2240 &crypto_cdevsw, &cmajor);
2241 if (error) {
2242 error = config_cfdata_detach(crypto_cfdata);
2243 if (error) {
2244 return error;
2245 }
2246 config_cfattach_detach(crypto_cd.cd_name, &crypto_ca);
2247 config_cfdriver_detach(&crypto_cd);
2248 aprint_error("%s: unable to register devsw\n",
2249 crypto_cd.cd_name);
2250
2251 return error;
2252 }
2253
2254 (void)config_attach_pseudo(crypto_cfdata);
2255 #endif
2256
2257 return error;
2258 case MODULE_CMD_FINI:
2259 #ifdef _MODULE
2260 error = config_cfdata_detach(crypto_cfdata);
2261 if (error) {
2262 return error;
2263 }
2264
2265 config_cfattach_detach(crypto_cd.cd_name, &crypto_ca);
2266 config_cfdriver_detach(&crypto_cd);
2267 devsw_detach(NULL, &crypto_cdevsw);
2268 #endif
2269
2270 return error;
2271 #ifdef _MODULE
2272 case MODULE_CMD_AUTOUNLOAD:
2273 #if 0 /*
2274 * XXX Completely disable auto-unload for now, since there is still
2275 * XXX a (small) window where in-module ref-counting doesn't help
2276 */
2277 if (crypto_refcount != 0)
2278 #endif
2279 return EBUSY;
2280 /* FALLTHROUGH */
2281 #endif
2282 default:
2283 return ENOTTY;
2284 }
2285 }
2286