cryptodev.c revision 1.32 1 /* $NetBSD: cryptodev.c,v 1.32 2008/02/02 02:39:00 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.32 2008/02/02 02:39:00 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;
231 break;
232 case CRYPTO_SHA1_HMAC:
233 thash = &auth_hash_hmac_sha1;
234 break;
235 case CRYPTO_MD5_HMAC_96:
236 thash = &auth_hash_hmac_md5_96;
237 break;
238 case CRYPTO_SHA1_HMAC_96:
239 thash = &auth_hash_hmac_sha1_96;
240 break;
241 case CRYPTO_SHA2_HMAC:
242 if (sop->mackeylen == auth_hash_hmac_sha2_256.keysize)
243 thash = &auth_hash_hmac_sha2_256;
244 else if (sop->mackeylen == auth_hash_hmac_sha2_384.keysize)
245 thash = &auth_hash_hmac_sha2_384;
246 else if (sop->mackeylen == auth_hash_hmac_sha2_512.keysize)
247 thash = &auth_hash_hmac_sha2_512;
248 else {
249 DPRINTF(("Invalid mackeylen %d\n",
250 sop->mackeylen));
251 return (EINVAL);
252 }
253 break;
254 case CRYPTO_RIPEMD160_HMAC:
255 thash = &auth_hash_hmac_ripemd_160_96;
256 break;
257 case CRYPTO_MD5:
258 thash = &auth_hash_md5;
259 break;
260 case CRYPTO_SHA1:
261 thash = &auth_hash_sha1;
262 break;
263 case CRYPTO_NULL_HMAC:
264 thash = &auth_hash_null;
265 break;
266 default:
267 DPRINTF(("Invalid mac %d\n", sop->mac));
268 return (EINVAL);
269 }
270
271 bzero(&crie, sizeof(crie));
272 bzero(&cria, sizeof(cria));
273
274 if (txform) {
275 crie.cri_alg = txform->type;
276 crie.cri_klen = sop->keylen * 8;
277 if (sop->keylen > txform->maxkey ||
278 sop->keylen < txform->minkey) {
279 DPRINTF(("keylen %d not in [%d,%d]\n",
280 sop->keylen, txform->minkey,
281 txform->maxkey));
282 error = EINVAL;
283 goto bail;
284 }
285
286 crie.cri_key = malloc(crie.cri_klen / 8, M_XDATA,
287 M_WAITOK);
288 if ((error = copyin(sop->key, crie.cri_key,
289 crie.cri_klen / 8)))
290 goto bail;
291 if (thash)
292 crie.cri_next = &cria;
293 }
294
295 if (thash) {
296 cria.cri_alg = thash->type;
297 cria.cri_klen = sop->mackeylen * 8;
298 if (sop->mackeylen != thash->keysize) {
299 DPRINTF(("mackeylen %d != keysize %d\n",
300 sop->mackeylen, thash->keysize));
301 error = EINVAL;
302 goto bail;
303 }
304
305 if (cria.cri_klen) {
306 cria.cri_key = malloc(cria.cri_klen / 8,
307 M_XDATA, M_WAITOK);
308 if ((error = copyin(sop->mackey, cria.cri_key,
309 cria.cri_klen / 8)))
310 goto bail;
311 }
312 }
313
314 error = crypto_newsession(&sid, (txform ? &crie : &cria),
315 crypto_devallowsoft);
316 if (error) {
317 DPRINTF(("SIOCSESSION violates kernel parameters %d\n",
318 error));
319 goto bail;
320 }
321
322 cse = csecreate(fcr, sid, crie.cri_key, crie.cri_klen,
323 cria.cri_key, cria.cri_klen, sop->cipher, sop->mac, txform,
324 thash);
325
326 if (cse == NULL) {
327 DPRINTF(("csecreate failed\n"));
328 crypto_freesession(sid);
329 error = EINVAL;
330 goto bail;
331 }
332 sop->ses = cse->ses;
333
334 bail:
335 if (error) {
336 if (crie.cri_key)
337 FREE(crie.cri_key, M_XDATA);
338 if (cria.cri_key)
339 FREE(cria.cri_key, M_XDATA);
340 }
341 break;
342 case CIOCFSESSION:
343 ses = *(u_int32_t *)data;
344 cse = csefind(fcr, ses);
345 if (cse == NULL)
346 return (EINVAL);
347 csedelete(fcr, cse);
348 error = csefree(cse);
349 break;
350 case CIOCCRYPT:
351 cop = (struct crypt_op *)data;
352 cse = csefind(fcr, cop->ses);
353 if (cse == NULL) {
354 DPRINTF(("csefind failed\n"));
355 return (EINVAL);
356 }
357 error = cryptodev_op(cse, cop, l);
358 break;
359 case CIOCKEY:
360 error = cryptodev_key((struct crypt_kop *)data);
361 break;
362 case CIOCASYMFEAT:
363 error = crypto_getfeat((int *)data);
364 break;
365 default:
366 DPRINTF(("invalid ioctl cmd %ld\n", cmd));
367 error = EINVAL;
368 }
369 return (error);
370 }
371
372 static int
373 cryptodev_op(struct csession *cse, struct crypt_op *cop, struct lwp *l)
374 {
375 struct cryptop *crp = NULL;
376 struct cryptodesc *crde = NULL, *crda = NULL;
377 int error, s;
378
379 if (cop->len > 256*1024-4)
380 return (E2BIG);
381
382 if (cse->txform) {
383 if (cop->len == 0 || (cop->len % cse->txform->blocksize) != 0)
384 return (EINVAL);
385 }
386
387 bzero(&cse->uio, sizeof(cse->uio));
388 cse->uio.uio_iovcnt = 1;
389 cse->uio.uio_resid = 0;
390 cse->uio.uio_rw = UIO_WRITE;
391 cse->uio.uio_iov = cse->iovec;
392 UIO_SETUP_SYSSPACE(&cse->uio);
393 memset(&cse->iovec, 0, sizeof(cse->iovec));
394 cse->uio.uio_iov[0].iov_len = cop->len;
395 cse->uio.uio_iov[0].iov_base = malloc(cop->len, M_XDATA, M_WAITOK);
396 cse->uio.uio_resid = cse->uio.uio_iov[0].iov_len;
397
398 crp = crypto_getreq((cse->txform != NULL) + (cse->thash != NULL));
399 if (crp == NULL) {
400 error = ENOMEM;
401 goto bail;
402 }
403
404 if (cse->thash) {
405 crda = crp->crp_desc;
406 if (cse->txform)
407 crde = crda->crd_next;
408 } else {
409 if (cse->txform)
410 crde = crp->crp_desc;
411 else {
412 error = EINVAL;
413 goto bail;
414 }
415 }
416
417 if ((error = copyin(cop->src, cse->uio.uio_iov[0].iov_base, cop->len)))
418 goto bail;
419
420 if (crda) {
421 crda->crd_skip = 0;
422 crda->crd_len = cop->len;
423 crda->crd_inject = 0; /* ??? */
424
425 crda->crd_alg = cse->mac;
426 crda->crd_key = cse->mackey;
427 crda->crd_klen = cse->mackeylen * 8;
428 }
429
430 if (crde) {
431 if (cop->op == COP_ENCRYPT)
432 crde->crd_flags |= CRD_F_ENCRYPT;
433 else
434 crde->crd_flags &= ~CRD_F_ENCRYPT;
435 crde->crd_len = cop->len;
436 crde->crd_inject = 0;
437
438 crde->crd_alg = cse->cipher;
439 crde->crd_key = cse->key;
440 crde->crd_klen = cse->keylen * 8;
441 }
442
443 crp->crp_ilen = cop->len;
444 crp->crp_flags = CRYPTO_F_IOV | CRYPTO_F_CBIMM
445 | (cop->flags & COP_F_BATCH);
446 crp->crp_buf = (void *)&cse->uio;
447 crp->crp_callback = (int (*) (struct cryptop *)) cryptodev_cb;
448 crp->crp_sid = cse->sid;
449 crp->crp_opaque = (void *)cse;
450
451 if (cop->iv) {
452 if (crde == NULL) {
453 error = EINVAL;
454 goto bail;
455 }
456 if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */
457 error = EINVAL;
458 goto bail;
459 }
460 if ((error = copyin(cop->iv, cse->tmp_iv, cse->txform->blocksize)))
461 goto bail;
462 bcopy(cse->tmp_iv, crde->crd_iv, cse->txform->blocksize);
463 crde->crd_flags |= CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT;
464 crde->crd_skip = 0;
465 } else if (crde) {
466 if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */
467 crde->crd_skip = 0;
468 } else {
469 crde->crd_flags |= CRD_F_IV_PRESENT;
470 crde->crd_skip = cse->txform->blocksize;
471 crde->crd_len -= cse->txform->blocksize;
472 }
473 }
474
475 if (cop->mac) {
476 if (crda == NULL) {
477 error = EINVAL;
478 goto bail;
479 }
480 crp->crp_mac=cse->tmp_mac;
481 }
482
483 s = splcrypto(); /* NB: only needed with CRYPTO_F_CBIMM */
484 error = crypto_dispatch(crp);
485 if (error == 0 && (crp->crp_flags & CRYPTO_F_DONE) == 0)
486 error = tsleep(crp, PSOCK, "crydev", 0);
487 splx(s);
488 if (error) {
489 goto bail;
490 }
491
492 if (crp->crp_etype != 0) {
493 error = crp->crp_etype;
494 goto bail;
495 }
496
497 if (cse->error) {
498 error = cse->error;
499 goto bail;
500 }
501
502 if (cop->dst &&
503 (error = copyout(cse->uio.uio_iov[0].iov_base, cop->dst, cop->len)))
504 goto bail;
505
506 if (cop->mac &&
507 (error = copyout(crp->crp_mac, cop->mac, cse->thash->authsize)))
508 goto bail;
509
510 bail:
511 if (crp)
512 crypto_freereq(crp);
513 if (cse->uio.uio_iov[0].iov_base)
514 free(cse->uio.uio_iov[0].iov_base, M_XDATA);
515
516 return (error);
517 }
518
519 static int
520 cryptodev_cb(void *op)
521 {
522 struct cryptop *crp = (struct cryptop *) op;
523 struct csession *cse = (struct csession *)crp->crp_opaque;
524
525 cse->error = crp->crp_etype;
526 if (crp->crp_etype == EAGAIN)
527 return crypto_dispatch(crp);
528 wakeup_one(crp);
529 return (0);
530 }
531
532 static int
533 cryptodevkey_cb(void *op)
534 {
535 struct cryptkop *krp = (struct cryptkop *) op;
536
537 wakeup_one(krp);
538 return (0);
539 }
540
541 static int
542 cryptodev_key(struct crypt_kop *kop)
543 {
544 struct cryptkop *krp = NULL;
545 int error = EINVAL;
546 int in, out, size, i;
547
548 if (kop->crk_iparams + kop->crk_oparams > CRK_MAXPARAM) {
549 return (EFBIG);
550 }
551
552 in = kop->crk_iparams;
553 out = kop->crk_oparams;
554 switch (kop->crk_op) {
555 case CRK_MOD_EXP:
556 if (in == 3 && out == 1)
557 break;
558 return (EINVAL);
559 case CRK_MOD_EXP_CRT:
560 if (in == 6 && out == 1)
561 break;
562 return (EINVAL);
563 case CRK_DSA_SIGN:
564 if (in == 5 && out == 2)
565 break;
566 return (EINVAL);
567 case CRK_DSA_VERIFY:
568 if (in == 7 && out == 0)
569 break;
570 return (EINVAL);
571 case CRK_DH_COMPUTE_KEY:
572 if (in == 3 && out == 1)
573 break;
574 return (EINVAL);
575 case CRK_MOD_ADD:
576 if (in == 3 && out == 1)
577 break;
578 return (EINVAL);
579 case CRK_MOD_ADDINV:
580 if (in == 2 && out == 1)
581 break;
582 return (EINVAL);
583 case CRK_MOD_SUB:
584 if (in == 3 && out == 1)
585 break;
586 return (EINVAL);
587 case CRK_MOD_MULT:
588 if (in == 3 && out == 1)
589 break;
590 return (EINVAL);
591 case CRK_MOD_MULTINV:
592 if (in == 2 && out == 1)
593 break;
594 return (EINVAL);
595 case CRK_MOD:
596 if (in == 2 && out == 1)
597 break;
598 return (EINVAL);
599 default:
600 return (EINVAL);
601 }
602
603 krp = (struct cryptkop *)malloc(sizeof *krp, M_XDATA, M_WAITOK);
604 if (!krp)
605 return (ENOMEM);
606 bzero(krp, sizeof *krp);
607 krp->krp_op = kop->crk_op;
608 krp->krp_status = kop->crk_status;
609 krp->krp_iparams = kop->crk_iparams;
610 krp->krp_oparams = kop->crk_oparams;
611 krp->krp_status = 0;
612 krp->krp_callback = (int (*) (struct cryptkop *)) cryptodevkey_cb;
613
614 for (i = 0; i < CRK_MAXPARAM; i++)
615 krp->krp_param[i].crp_nbits = kop->crk_param[i].crp_nbits;
616 for (i = 0; i < krp->krp_iparams + krp->krp_oparams; i++) {
617 size = (krp->krp_param[i].crp_nbits + 7) / 8;
618 if (size == 0)
619 continue;
620 krp->krp_param[i].crp_p = malloc(size, M_XDATA, M_WAITOK);
621 if (i >= krp->krp_iparams)
622 continue;
623 error = copyin(kop->crk_param[i].crp_p, krp->krp_param[i].crp_p, size);
624 if (error)
625 goto fail;
626 }
627
628 error = crypto_kdispatch(krp);
629 if (error == 0)
630 error = tsleep(krp, PSOCK, "crydev", 0);
631 if (error)
632 goto fail;
633
634 if (krp->krp_status != 0) {
635 error = krp->krp_status;
636 goto fail;
637 }
638
639 for (i = krp->krp_iparams; i < krp->krp_iparams + krp->krp_oparams; i++) {
640 size = (krp->krp_param[i].crp_nbits + 7) / 8;
641 if (size == 0)
642 continue;
643 error = copyout(krp->krp_param[i].crp_p, kop->crk_param[i].crp_p, size);
644 if (error)
645 goto fail;
646 }
647
648 fail:
649 if (krp) {
650 kop->crk_status = krp->krp_status;
651 for (i = 0; i < CRK_MAXPARAM; i++) {
652 if (krp->krp_param[i].crp_p)
653 FREE(krp->krp_param[i].crp_p, M_XDATA);
654 }
655 free(krp, M_XDATA);
656 }
657 return (error);
658 }
659
660 /* ARGSUSED */
661 static int
662 cryptof_close(struct file *fp, struct lwp *l)
663 {
664 struct fcrypt *fcr = (struct fcrypt *)fp->f_data;
665 struct csession *cse;
666
667 while ((cse = TAILQ_FIRST(&fcr->csessions))) {
668 TAILQ_REMOVE(&fcr->csessions, cse, next);
669 (void)csefree(cse);
670 }
671 pool_put(&fcrpl, fcr);
672
673 fp->f_data = NULL;
674
675 return 0;
676 }
677
678 static struct csession *
679 csefind(struct fcrypt *fcr, u_int ses)
680 {
681 struct csession *cse;
682
683 TAILQ_FOREACH(cse, &fcr->csessions, next)
684 if (cse->ses == ses)
685 return (cse);
686 return (NULL);
687 }
688
689 static int
690 csedelete(struct fcrypt *fcr, struct csession *cse_del)
691 {
692 struct csession *cse;
693
694 TAILQ_FOREACH(cse, &fcr->csessions, next) {
695 if (cse == cse_del) {
696 TAILQ_REMOVE(&fcr->csessions, cse, next);
697 return (1);
698 }
699 }
700 return (0);
701 }
702
703 static struct csession *
704 cseadd(struct fcrypt *fcr, struct csession *cse)
705 {
706 TAILQ_INSERT_TAIL(&fcr->csessions, cse, next);
707 cse->ses = fcr->sesn++;
708 return (cse);
709 }
710
711 static struct csession *
712 csecreate(struct fcrypt *fcr, u_int64_t sid, void *key, u_int64_t keylen,
713 void *mackey, u_int64_t mackeylen, u_int32_t cipher, u_int32_t mac,
714 struct enc_xform *txform, struct auth_hash *thash)
715 {
716 struct csession *cse;
717
718 /* Don't let the session ID wrap! */
719 if (fcr->sesn + 1 == 0)
720 return NULL;
721
722 cse = pool_get(&csepl, PR_NOWAIT);
723 if (cse == NULL)
724 return NULL;
725 cse->key = key;
726 cse->keylen = keylen/8;
727 cse->mackey = mackey;
728 cse->mackeylen = mackeylen/8;
729 cse->sid = sid;
730 cse->cipher = cipher;
731 cse->mac = mac;
732 cse->txform = txform;
733 cse->thash = thash;
734 if (cseadd(fcr, cse))
735 return (cse);
736 else {
737 FREE(cse, M_XDATA);
738 return NULL;
739 }
740 }
741
742 static int
743 csefree(struct csession *cse)
744 {
745 int error;
746
747 error = crypto_freesession(cse->sid);
748 if (cse->key)
749 FREE(cse->key, M_XDATA);
750 if (cse->mackey)
751 FREE(cse->mackey, M_XDATA);
752 pool_put(&csepl, cse);
753 return (error);
754 }
755
756 static int
757 cryptoopen(dev_t dev, int flag, int mode,
758 struct lwp *l)
759 {
760 struct file *fp;
761 struct fcrypt *fcr;
762 int fd, error;
763
764 if (crypto_usercrypto == 0)
765 return (ENXIO);
766
767 if ((error = falloc(l, &fp, &fd)) != 0)
768 return error;
769
770 fcr = pool_get(&fcrpl, PR_WAITOK);
771 TAILQ_INIT(&fcr->csessions);
772 /*
773 * Don't ever return session 0, to allow detection of
774 * failed creation attempts with multi-create ioctl.
775 */
776 fcr->sesn = 1;
777 return fdclone(l, fp, fd, flag, &cryptofops, fcr);
778 }
779
780 static int
781 cryptoread(dev_t dev, struct uio *uio, int ioflag)
782 {
783 return (EIO);
784 }
785
786 static int
787 cryptowrite(dev_t dev, struct uio *uio, int ioflag)
788 {
789 return (EIO);
790 }
791
792 int
793 cryptoselect(dev_t dev, int rw, struct lwp *l)
794 {
795 return (0);
796 }
797
798 /*static*/
799 struct cdevsw crypto_cdevsw = {
800 /* open */ cryptoopen,
801 /* close */ noclose,
802 /* read */ cryptoread,
803 /* write */ cryptowrite,
804 /* ioctl */ noioctl,
805 /* ttstop?*/ nostop,
806 /* ??*/ notty,
807 /* poll */ cryptoselect /*nopoll*/,
808 /* mmap */ nommap,
809 /* kqfilter */ nokqfilter,
810 /* type */ D_OTHER,
811 };
812
813 /*
814 * Pseudo-device initialization routine for /dev/crypto
815 */
816 void cryptoattach(int);
817
818 void
819 cryptoattach(int num)
820 {
821 pool_init(&fcrpl, sizeof(struct fcrypt), 0, 0, 0, "fcrpl",
822 NULL, IPL_NET); /* XXX IPL_NET ("splcrypto") */
823 pool_init(&csepl, sizeof(struct csession), 0, 0, 0, "csepl",
824 NULL, IPL_NET); /* XXX IPL_NET ("splcrypto") */
825
826 /*
827 * Preallocate space for 64 users, with 5 sessions each.
828 * (consider that a TLS protocol session requires at least
829 * 3DES, MD5, and SHA1 (both hashes are used in the PRF) for
830 * the negotiation, plus HMAC_SHA1 for the actual SSL records,
831 * consuming one session here for each algorithm.
832 */
833 pool_prime(&fcrpl, 64);
834 pool_prime(&csepl, 64 * 5);
835 }
836