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