cryptodev.c revision 1.31 1 /* $NetBSD: cryptodev.c,v 1.31 2008/02/01 04:52:35 tls 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) 2001 Theo de Raadt
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. The name of the author may not be used to endorse or promote products
18 * derived from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 *
31 * Effort sponsored in part by the Defense Advanced Research Projects
32 * Agency (DARPA) and Air Force Research Laboratory, Air Force
33 * Materiel Command, USAF, under agreement number F30602-01-2-0537.
34 *
35 */
36
37 #include <sys/cdefs.h>
38 __KERNEL_RCSID(0, "$NetBSD: cryptodev.c,v 1.31 2008/02/01 04:52:35 tls Exp $");
39
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/malloc.h>
43 #include <sys/mbuf.h>
44 #include <sys/pool.h>
45 #include <sys/sysctl.h>
46 #include <sys/file.h>
47 #include <sys/filedesc.h>
48 #include <sys/errno.h>
49 #include <sys/md5.h>
50 #include <sys/sha1.h>
51 #include <sys/conf.h>
52 #include <sys/device.h>
53 #include <sys/kauth.h>
54
55 #include <opencrypto/cryptodev.h>
56 #include <opencrypto/xform.h>
57
58 #define splcrypto splnet
59 #ifdef CRYPTO_DEBUG
60 #define DPRINTF(a) uprintf a
61 #else
62 #define DPRINTF(a)
63 #endif
64
65 struct csession {
66 TAILQ_ENTRY(csession) next;
67 u_int64_t sid;
68 u_int32_t ses;
69
70 u_int32_t cipher;
71 struct enc_xform *txform;
72 u_int32_t mac;
73 struct auth_hash *thash;
74
75 void * key;
76 int keylen;
77 u_char tmp_iv[EALG_MAX_BLOCK_LEN];
78
79 void * mackey;
80 int mackeylen;
81 u_char tmp_mac[CRYPTO_MAX_MAC_LEN];
82
83 struct iovec iovec[1]; /* user requests never have more */
84 struct uio uio;
85 int error;
86 };
87
88 struct fcrypt {
89 TAILQ_HEAD(csessionlist, csession) csessions;
90 int sesn;
91 };
92
93 /* For our fixed-size allocations */
94 struct pool fcrpl;
95 struct pool csepl;
96
97 /* Declaration of master device (fd-cloning/ctxt-allocating) entrypoints */
98 static int cryptoopen(dev_t dev, int flag, int mode, struct lwp *l);
99 static int cryptoread(dev_t dev, struct uio *uio, int ioflag);
100 static int cryptowrite(dev_t dev, struct uio *uio, int ioflag);
101 static int cryptoselect(dev_t dev, int rw, struct lwp *l);
102
103 /* Declaration of cloned-device (per-ctxt) entrypoints */
104 static int cryptof_read(struct file *, off_t *, struct uio *, kauth_cred_t, int);
105 static int cryptof_write(struct file *, off_t *, struct uio *, kauth_cred_t, int);
106 static int cryptof_ioctl(struct file *, u_long, void*, struct lwp *l);
107 static int cryptof_close(struct file *, struct lwp *);
108
109 static const struct fileops cryptofops = {
110 cryptof_read,
111 cryptof_write,
112 cryptof_ioctl,
113 fnullop_fcntl,
114 fnullop_poll,
115 fbadop_stat,
116 cryptof_close,
117 fnullop_kqfilter
118 };
119
120 static struct csession *csefind(struct fcrypt *, u_int);
121 static int csedelete(struct fcrypt *, struct csession *);
122 static struct csession *cseadd(struct fcrypt *, struct csession *);
123 static struct csession *csecreate(struct fcrypt *, u_int64_t, void *, u_int64_t,
124 void *, u_int64_t, u_int32_t, u_int32_t, struct enc_xform *,
125 struct auth_hash *);
126 static int csefree(struct csession *);
127
128 static int cryptodev_op(struct csession *, struct crypt_op *, struct lwp *);
129 static int cryptodev_key(struct crypt_kop *);
130 int cryptodev_dokey(struct crypt_kop *kop, struct crparam kvp[]);
131
132 static int cryptodev_cb(void *);
133 static int cryptodevkey_cb(void *);
134
135 /*
136 * sysctl-able control variables for /dev/crypto now defined in crypto.c:
137 * crypto_usercrypto, crypto_userasmcrypto, crypto_devallowsoft.
138 */
139
140 /* ARGSUSED */
141 int
142 cryptof_read(struct file *fp, off_t *poff,
143 struct uio *uio, kauth_cred_t cred, int flags)
144 {
145 return (EIO);
146 }
147
148 /* ARGSUSED */
149 int
150 cryptof_write(struct file *fp, off_t *poff,
151 struct uio *uio, kauth_cred_t cred, int flags)
152 {
153 return (EIO);
154 }
155
156 /* ARGSUSED */
157 int
158 cryptof_ioctl(struct file *fp, u_long cmd, void* data, struct lwp *l)
159 {
160 struct cryptoini cria, crie;
161 struct fcrypt *fcr = (struct fcrypt *)fp->f_data;
162 struct csession *cse;
163 struct session_op *sop;
164 struct crypt_op *cop;
165 struct enc_xform *txform = NULL;
166 struct auth_hash *thash = NULL;
167 u_int64_t sid;
168 u_int32_t ses;
169 int error = 0;
170
171 /* backwards compatibility */
172 struct file *criofp;
173 struct fcrypt *criofcr;
174 int criofd;
175
176 switch (cmd) {
177 case CRIOGET: /* XXX deprecated, remove after 5.0 */
178 if ((error = falloc(l, &criofp, &criofd)) != 0)
179 return error;
180 criofcr = pool_get(&fcrpl, PR_WAITOK);
181 TAILQ_INIT(&criofcr->csessions);
182 /*
183 * Don't ever return session 0, to allow detection of
184 * failed creation attempts with multi-create ioctl.
185 */
186 criofcr->sesn = 1;
187 (void)fdclone(l, criofp, criofd, (FREAD|FWRITE),
188 &cryptofops, criofcr);
189 *(u_int32_t *)data = criofd;
190 return error;
191 break;
192 case CIOCGSESSION:
193 sop = (struct session_op *)data;
194 switch (sop->cipher) {
195 case 0:
196 break;
197 case CRYPTO_DES_CBC:
198 txform = &enc_xform_des;
199 break;
200 case CRYPTO_3DES_CBC:
201 txform = &enc_xform_3des;
202 break;
203 case CRYPTO_BLF_CBC:
204 txform = &enc_xform_blf;
205 break;
206 case CRYPTO_CAST_CBC:
207 txform = &enc_xform_cast5;
208 break;
209 case CRYPTO_SKIPJACK_CBC:
210 txform = &enc_xform_skipjack;
211 break;
212 case CRYPTO_AES_CBC:
213 txform = &enc_xform_rijndael128;
214 break;
215 case CRYPTO_NULL_CBC:
216 txform = &enc_xform_null;
217 break;
218 case CRYPTO_ARC4:
219 txform = &enc_xform_arc4;
220 break;
221 default:
222 DPRINTF(("Invalid cipher %d\n", sop->cipher));
223 return (EINVAL);
224 }
225
226 switch (sop->mac) {
227 case 0:
228 break;
229 case CRYPTO_MD5_HMAC:
230 thash = &auth_hash_hmac_md5_96;
231 break;
232 case CRYPTO_SHA1_HMAC:
233 thash = &auth_hash_hmac_sha1_96;
234 break;
235 case CRYPTO_SHA2_HMAC:
236 if (sop->mackeylen == auth_hash_hmac_sha2_256.keysize)
237 thash = &auth_hash_hmac_sha2_256;
238 else if (sop->mackeylen == auth_hash_hmac_sha2_384.keysize)
239 thash = &auth_hash_hmac_sha2_384;
240 else if (sop->mackeylen == auth_hash_hmac_sha2_512.keysize)
241 thash = &auth_hash_hmac_sha2_512;
242 else {
243 DPRINTF(("Invalid mackeylen %d\n",
244 sop->mackeylen));
245 return (EINVAL);
246 }
247 break;
248 case CRYPTO_RIPEMD160_HMAC:
249 thash = &auth_hash_hmac_ripemd_160_96;
250 break;
251 case CRYPTO_MD5:
252 thash = &auth_hash_md5;
253 break;
254 case CRYPTO_SHA1:
255 thash = &auth_hash_sha1;
256 break;
257 case CRYPTO_NULL_HMAC:
258 thash = &auth_hash_null;
259 break;
260 default:
261 DPRINTF(("Invalid mac %d\n", sop->mac));
262 return (EINVAL);
263 }
264
265 bzero(&crie, sizeof(crie));
266 bzero(&cria, sizeof(cria));
267
268 if (txform) {
269 crie.cri_alg = txform->type;
270 crie.cri_klen = sop->keylen * 8;
271 if (sop->keylen > txform->maxkey ||
272 sop->keylen < txform->minkey) {
273 DPRINTF(("keylen %d not in [%d,%d]\n",
274 sop->keylen, txform->minkey,
275 txform->maxkey));
276 error = EINVAL;
277 goto bail;
278 }
279
280 crie.cri_key = malloc(crie.cri_klen / 8, M_XDATA,
281 M_WAITOK);
282 if ((error = copyin(sop->key, crie.cri_key,
283 crie.cri_klen / 8)))
284 goto bail;
285 if (thash)
286 crie.cri_next = &cria;
287 }
288
289 if (thash) {
290 cria.cri_alg = thash->type;
291 cria.cri_klen = sop->mackeylen * 8;
292 if (sop->mackeylen != thash->keysize) {
293 DPRINTF(("mackeylen %d != keysize %d\n",
294 sop->mackeylen, thash->keysize));
295 error = EINVAL;
296 goto bail;
297 }
298
299 if (cria.cri_klen) {
300 cria.cri_key = malloc(cria.cri_klen / 8,
301 M_XDATA, M_WAITOK);
302 if ((error = copyin(sop->mackey, cria.cri_key,
303 cria.cri_klen / 8)))
304 goto bail;
305 }
306 }
307
308 error = crypto_newsession(&sid, (txform ? &crie : &cria),
309 crypto_devallowsoft);
310 if (error) {
311 DPRINTF(("SIOCSESSION violates kernel parameters %d\n",
312 error));
313 goto bail;
314 }
315
316 cse = csecreate(fcr, sid, crie.cri_key, crie.cri_klen,
317 cria.cri_key, cria.cri_klen, sop->cipher, sop->mac, txform,
318 thash);
319
320 if (cse == NULL) {
321 DPRINTF(("csecreate failed\n"));
322 crypto_freesession(sid);
323 error = EINVAL;
324 goto bail;
325 }
326 sop->ses = cse->ses;
327
328 bail:
329 if (error) {
330 if (crie.cri_key)
331 FREE(crie.cri_key, M_XDATA);
332 if (cria.cri_key)
333 FREE(cria.cri_key, M_XDATA);
334 }
335 break;
336 case CIOCFSESSION:
337 ses = *(u_int32_t *)data;
338 cse = csefind(fcr, ses);
339 if (cse == NULL)
340 return (EINVAL);
341 csedelete(fcr, cse);
342 error = csefree(cse);
343 break;
344 case CIOCCRYPT:
345 cop = (struct crypt_op *)data;
346 cse = csefind(fcr, cop->ses);
347 if (cse == NULL) {
348 DPRINTF(("csefind failed\n"));
349 return (EINVAL);
350 }
351 error = cryptodev_op(cse, cop, l);
352 break;
353 case CIOCKEY:
354 error = cryptodev_key((struct crypt_kop *)data);
355 break;
356 case CIOCASYMFEAT:
357 error = crypto_getfeat((int *)data);
358 break;
359 default:
360 DPRINTF(("invalid ioctl cmd %ld\n", cmd));
361 error = EINVAL;
362 }
363 return (error);
364 }
365
366 static int
367 cryptodev_op(struct csession *cse, struct crypt_op *cop, struct lwp *l)
368 {
369 struct cryptop *crp = NULL;
370 struct cryptodesc *crde = NULL, *crda = NULL;
371 int error, s;
372
373 if (cop->len > 256*1024-4)
374 return (E2BIG);
375
376 if (cse->txform) {
377 if (cop->len == 0 || (cop->len % cse->txform->blocksize) != 0)
378 return (EINVAL);
379 }
380
381 bzero(&cse->uio, sizeof(cse->uio));
382 cse->uio.uio_iovcnt = 1;
383 cse->uio.uio_resid = 0;
384 cse->uio.uio_rw = UIO_WRITE;
385 cse->uio.uio_iov = cse->iovec;
386 UIO_SETUP_SYSSPACE(&cse->uio);
387 memset(&cse->iovec, 0, sizeof(cse->iovec));
388 cse->uio.uio_iov[0].iov_len = cop->len;
389 cse->uio.uio_iov[0].iov_base = malloc(cop->len, M_XDATA, M_WAITOK);
390 cse->uio.uio_resid = cse->uio.uio_iov[0].iov_len;
391
392 crp = crypto_getreq((cse->txform != NULL) + (cse->thash != NULL));
393 if (crp == NULL) {
394 error = ENOMEM;
395 goto bail;
396 }
397
398 if (cse->thash) {
399 crda = crp->crp_desc;
400 if (cse->txform)
401 crde = crda->crd_next;
402 } else {
403 if (cse->txform)
404 crde = crp->crp_desc;
405 else {
406 error = EINVAL;
407 goto bail;
408 }
409 }
410
411 if ((error = copyin(cop->src, cse->uio.uio_iov[0].iov_base, cop->len)))
412 goto bail;
413
414 if (crda) {
415 crda->crd_skip = 0;
416 crda->crd_len = cop->len;
417 crda->crd_inject = 0; /* ??? */
418
419 crda->crd_alg = cse->mac;
420 crda->crd_key = cse->mackey;
421 crda->crd_klen = cse->mackeylen * 8;
422 }
423
424 if (crde) {
425 if (cop->op == COP_ENCRYPT)
426 crde->crd_flags |= CRD_F_ENCRYPT;
427 else
428 crde->crd_flags &= ~CRD_F_ENCRYPT;
429 crde->crd_len = cop->len;
430 crde->crd_inject = 0;
431
432 crde->crd_alg = cse->cipher;
433 crde->crd_key = cse->key;
434 crde->crd_klen = cse->keylen * 8;
435 }
436
437 crp->crp_ilen = cop->len;
438 crp->crp_flags = CRYPTO_F_IOV | CRYPTO_F_CBIMM
439 | (cop->flags & COP_F_BATCH);
440 crp->crp_buf = (void *)&cse->uio;
441 crp->crp_callback = (int (*) (struct cryptop *)) cryptodev_cb;
442 crp->crp_sid = cse->sid;
443 crp->crp_opaque = (void *)cse;
444
445 if (cop->iv) {
446 if (crde == NULL) {
447 error = EINVAL;
448 goto bail;
449 }
450 if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */
451 error = EINVAL;
452 goto bail;
453 }
454 if ((error = copyin(cop->iv, cse->tmp_iv, cse->txform->blocksize)))
455 goto bail;
456 bcopy(cse->tmp_iv, crde->crd_iv, cse->txform->blocksize);
457 crde->crd_flags |= CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT;
458 crde->crd_skip = 0;
459 } else if (crde) {
460 if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */
461 crde->crd_skip = 0;
462 } else {
463 crde->crd_flags |= CRD_F_IV_PRESENT;
464 crde->crd_skip = cse->txform->blocksize;
465 crde->crd_len -= cse->txform->blocksize;
466 }
467 }
468
469 if (cop->mac) {
470 if (crda == NULL) {
471 error = EINVAL;
472 goto bail;
473 }
474 crp->crp_mac=cse->tmp_mac;
475 }
476
477 s = splcrypto(); /* NB: only needed with CRYPTO_F_CBIMM */
478 error = crypto_dispatch(crp);
479 if (error == 0 && (crp->crp_flags & CRYPTO_F_DONE) == 0)
480 error = tsleep(crp, PSOCK, "crydev", 0);
481 splx(s);
482 if (error) {
483 goto bail;
484 }
485
486 if (crp->crp_etype != 0) {
487 error = crp->crp_etype;
488 goto bail;
489 }
490
491 if (cse->error) {
492 error = cse->error;
493 goto bail;
494 }
495
496 if (cop->dst &&
497 (error = copyout(cse->uio.uio_iov[0].iov_base, cop->dst, cop->len)))
498 goto bail;
499
500 if (cop->mac &&
501 (error = copyout(crp->crp_mac, cop->mac, cse->thash->authsize)))
502 goto bail;
503
504 bail:
505 if (crp)
506 crypto_freereq(crp);
507 if (cse->uio.uio_iov[0].iov_base)
508 free(cse->uio.uio_iov[0].iov_base, M_XDATA);
509
510 return (error);
511 }
512
513 static int
514 cryptodev_cb(void *op)
515 {
516 struct cryptop *crp = (struct cryptop *) op;
517 struct csession *cse = (struct csession *)crp->crp_opaque;
518
519 cse->error = crp->crp_etype;
520 if (crp->crp_etype == EAGAIN)
521 return crypto_dispatch(crp);
522 wakeup_one(crp);
523 return (0);
524 }
525
526 static int
527 cryptodevkey_cb(void *op)
528 {
529 struct cryptkop *krp = (struct cryptkop *) op;
530
531 wakeup_one(krp);
532 return (0);
533 }
534
535 static int
536 cryptodev_key(struct crypt_kop *kop)
537 {
538 struct cryptkop *krp = NULL;
539 int error = EINVAL;
540 int in, out, size, i;
541
542 if (kop->crk_iparams + kop->crk_oparams > CRK_MAXPARAM) {
543 return (EFBIG);
544 }
545
546 in = kop->crk_iparams;
547 out = kop->crk_oparams;
548 switch (kop->crk_op) {
549 case CRK_MOD_EXP:
550 if (in == 3 && out == 1)
551 break;
552 return (EINVAL);
553 case CRK_MOD_EXP_CRT:
554 if (in == 6 && out == 1)
555 break;
556 return (EINVAL);
557 case CRK_DSA_SIGN:
558 if (in == 5 && out == 2)
559 break;
560 return (EINVAL);
561 case CRK_DSA_VERIFY:
562 if (in == 7 && out == 0)
563 break;
564 return (EINVAL);
565 case CRK_DH_COMPUTE_KEY:
566 if (in == 3 && out == 1)
567 break;
568 return (EINVAL);
569 case CRK_MOD_ADD:
570 if (in == 3 && out == 1)
571 break;
572 return (EINVAL);
573 case CRK_MOD_ADDINV:
574 if (in == 2 && out == 1)
575 break;
576 return (EINVAL);
577 case CRK_MOD_SUB:
578 if (in == 3 && out == 1)
579 break;
580 return (EINVAL);
581 case CRK_MOD_MULT:
582 if (in == 3 && out == 1)
583 break;
584 return (EINVAL);
585 case CRK_MOD_MULTINV:
586 if (in == 2 && out == 1)
587 break;
588 return (EINVAL);
589 case CRK_MOD:
590 if (in == 2 && out == 1)
591 break;
592 return (EINVAL);
593 default:
594 return (EINVAL);
595 }
596
597 krp = (struct cryptkop *)malloc(sizeof *krp, M_XDATA, M_WAITOK);
598 if (!krp)
599 return (ENOMEM);
600 bzero(krp, sizeof *krp);
601 krp->krp_op = kop->crk_op;
602 krp->krp_status = kop->crk_status;
603 krp->krp_iparams = kop->crk_iparams;
604 krp->krp_oparams = kop->crk_oparams;
605 krp->krp_status = 0;
606 krp->krp_callback = (int (*) (struct cryptkop *)) cryptodevkey_cb;
607
608 for (i = 0; i < CRK_MAXPARAM; i++)
609 krp->krp_param[i].crp_nbits = kop->crk_param[i].crp_nbits;
610 for (i = 0; i < krp->krp_iparams + krp->krp_oparams; i++) {
611 size = (krp->krp_param[i].crp_nbits + 7) / 8;
612 if (size == 0)
613 continue;
614 krp->krp_param[i].crp_p = malloc(size, M_XDATA, M_WAITOK);
615 if (i >= krp->krp_iparams)
616 continue;
617 error = copyin(kop->crk_param[i].crp_p, krp->krp_param[i].crp_p, size);
618 if (error)
619 goto fail;
620 }
621
622 error = crypto_kdispatch(krp);
623 if (error == 0)
624 error = tsleep(krp, PSOCK, "crydev", 0);
625 if (error)
626 goto fail;
627
628 if (krp->krp_status != 0) {
629 error = krp->krp_status;
630 goto fail;
631 }
632
633 for (i = krp->krp_iparams; i < krp->krp_iparams + krp->krp_oparams; i++) {
634 size = (krp->krp_param[i].crp_nbits + 7) / 8;
635 if (size == 0)
636 continue;
637 error = copyout(krp->krp_param[i].crp_p, kop->crk_param[i].crp_p, size);
638 if (error)
639 goto fail;
640 }
641
642 fail:
643 if (krp) {
644 kop->crk_status = krp->krp_status;
645 for (i = 0; i < CRK_MAXPARAM; i++) {
646 if (krp->krp_param[i].crp_p)
647 FREE(krp->krp_param[i].crp_p, M_XDATA);
648 }
649 free(krp, M_XDATA);
650 }
651 return (error);
652 }
653
654 /* ARGSUSED */
655 static int
656 cryptof_close(struct file *fp, struct lwp *l)
657 {
658 struct fcrypt *fcr = (struct fcrypt *)fp->f_data;
659 struct csession *cse;
660
661 while ((cse = TAILQ_FIRST(&fcr->csessions))) {
662 TAILQ_REMOVE(&fcr->csessions, cse, next);
663 (void)csefree(cse);
664 }
665 pool_put(&fcrpl, fcr);
666
667 fp->f_data = NULL;
668
669 return 0;
670 }
671
672 static struct csession *
673 csefind(struct fcrypt *fcr, u_int ses)
674 {
675 struct csession *cse;
676
677 TAILQ_FOREACH(cse, &fcr->csessions, next)
678 if (cse->ses == ses)
679 return (cse);
680 return (NULL);
681 }
682
683 static int
684 csedelete(struct fcrypt *fcr, struct csession *cse_del)
685 {
686 struct csession *cse;
687
688 TAILQ_FOREACH(cse, &fcr->csessions, next) {
689 if (cse == cse_del) {
690 TAILQ_REMOVE(&fcr->csessions, cse, next);
691 return (1);
692 }
693 }
694 return (0);
695 }
696
697 static struct csession *
698 cseadd(struct fcrypt *fcr, struct csession *cse)
699 {
700 TAILQ_INSERT_TAIL(&fcr->csessions, cse, next);
701 cse->ses = fcr->sesn++;
702 return (cse);
703 }
704
705 static struct csession *
706 csecreate(struct fcrypt *fcr, u_int64_t sid, void *key, u_int64_t keylen,
707 void *mackey, u_int64_t mackeylen, u_int32_t cipher, u_int32_t mac,
708 struct enc_xform *txform, struct auth_hash *thash)
709 {
710 struct csession *cse;
711
712 /* Don't let the session ID wrap! */
713 if (fcr->sesn + 1 == 0)
714 return NULL;
715
716 cse = pool_get(&csepl, PR_NOWAIT);
717 if (cse == NULL)
718 return NULL;
719 cse->key = key;
720 cse->keylen = keylen/8;
721 cse->mackey = mackey;
722 cse->mackeylen = mackeylen/8;
723 cse->sid = sid;
724 cse->cipher = cipher;
725 cse->mac = mac;
726 cse->txform = txform;
727 cse->thash = thash;
728 if (cseadd(fcr, cse))
729 return (cse);
730 else {
731 FREE(cse, M_XDATA);
732 return NULL;
733 }
734 }
735
736 static int
737 csefree(struct csession *cse)
738 {
739 int error;
740
741 error = crypto_freesession(cse->sid);
742 if (cse->key)
743 FREE(cse->key, M_XDATA);
744 if (cse->mackey)
745 FREE(cse->mackey, M_XDATA);
746 pool_put(&csepl, cse);
747 return (error);
748 }
749
750 static int
751 cryptoopen(dev_t dev, int flag, int mode,
752 struct lwp *l)
753 {
754 struct file *fp;
755 struct fcrypt *fcr;
756 int fd, error;
757
758 if (crypto_usercrypto == 0)
759 return (ENXIO);
760
761 if ((error = falloc(l, &fp, &fd)) != 0)
762 return error;
763
764 fcr = pool_get(&fcrpl, PR_WAITOK);
765 TAILQ_INIT(&fcr->csessions);
766 /*
767 * Don't ever return session 0, to allow detection of
768 * failed creation attempts with multi-create ioctl.
769 */
770 fcr->sesn = 1;
771 return fdclone(l, fp, fd, flag, &cryptofops, fcr);
772 }
773
774 static int
775 cryptoread(dev_t dev, struct uio *uio, int ioflag)
776 {
777 return (EIO);
778 }
779
780 static int
781 cryptowrite(dev_t dev, struct uio *uio, int ioflag)
782 {
783 return (EIO);
784 }
785
786 int
787 cryptoselect(dev_t dev, int rw, struct lwp *l)
788 {
789 return (0);
790 }
791
792 /*static*/
793 struct cdevsw crypto_cdevsw = {
794 /* open */ cryptoopen,
795 /* close */ noclose,
796 /* read */ cryptoread,
797 /* write */ cryptowrite,
798 /* ioctl */ noioctl,
799 /* ttstop?*/ nostop,
800 /* ??*/ notty,
801 /* poll */ cryptoselect /*nopoll*/,
802 /* mmap */ nommap,
803 /* kqfilter */ nokqfilter,
804 /* type */ D_OTHER,
805 };
806
807 /*
808 * Pseudo-device initialization routine for /dev/crypto
809 */
810 void cryptoattach(int);
811
812 void
813 cryptoattach(int num)
814 {
815 pool_init(&fcrpl, sizeof(struct fcrypt), 0, 0, 0, "fcrpl",
816 NULL, IPL_NET); /* XXX IPL_NET ("splcrypto") */
817 pool_init(&csepl, sizeof(struct csession), 0, 0, 0, "csepl",
818 NULL, IPL_NET); /* XXX IPL_NET ("splcrypto") */
819
820 /*
821 * Preallocate space for 64 users, with 5 sessions each.
822 * (consider that a TLS protocol session requires at least
823 * 3DES, MD5, and SHA1 (both hashes are used in the PRF) for
824 * the negotiation, plus HMAC_SHA1 for the actual SSL records,
825 * consuming one session here for each algorithm.
826 */
827 pool_prime(&fcrpl, 64);
828 pool_prime(&csepl, 64 * 5);
829 }
830