Merge from vendor branch SENDMAIL:
[dragonfly.git] / sys / opencrypto / cryptodev.c
1 /*      $FreeBSD: src/sys/opencrypto/cryptodev.c,v 1.4.2.4 2003/06/03 00:09:02 sam Exp $        */
2 /*      $DragonFly: src/sys/opencrypto/cryptodev.c,v 1.17 2006/05/26 15:55:13 dillon Exp $      */
3 /*      $OpenBSD: cryptodev.c,v 1.52 2002/06/19 07:22:46 deraadt 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/param.h>
38 #include <sys/systm.h>
39 #include <sys/malloc.h>
40 #include <sys/mbuf.h>
41 #include <sys/sysctl.h>
42 #include <sys/file.h>
43 #include <sys/lock.h>
44 #include <sys/filedesc.h>
45 #include <sys/errno.h>
46 #include <sys/uio.h>
47 #include <sys/random.h>
48 #include <sys/conf.h>
49 #include <sys/kernel.h>
50 #include <sys/fcntl.h>
51 #include <sys/proc.h>
52 #include <sys/file2.h>
53 #include <sys/thread2.h>
54
55 #include <opencrypto/cryptodev.h>
56 #include <opencrypto/xform.h>
57
58 struct csession {
59         TAILQ_ENTRY(csession) next;
60         u_int64_t       sid;
61         u_int32_t       ses;
62
63         u_int32_t       cipher;
64         struct enc_xform *txform;
65         u_int32_t       mac;
66         struct auth_hash *thash;
67
68         caddr_t         key;
69         int             keylen;
70         u_char          tmp_iv[EALG_MAX_BLOCK_LEN];
71
72         caddr_t         mackey;
73         int             mackeylen;
74         u_char          tmp_mac[CRYPTO_MAX_MAC_LEN];
75
76         struct iovec    iovec[UIO_MAXIOV];
77         struct uio      uio;
78         int             error;
79 };
80
81 struct fcrypt {
82         TAILQ_HEAD(csessionlist, csession) csessions;
83         int             sesn;
84 };
85
86 static  int cryptof_rw(struct file *fp, struct uio *uio,
87                     struct ucred *cred, int flags);
88 static  int cryptof_ioctl(struct file *, u_long, caddr_t, struct ucred *);
89 static  int cryptof_poll(struct file *, int, struct ucred *);
90 static  int cryptof_kqfilter(struct file *, struct knote *);
91 static  int cryptof_stat(struct file *, struct stat *, struct ucred *);
92 static  int cryptof_close(struct file *);
93
94 static struct fileops cryptofops = {
95     NULL,       /* port */
96     NULL,       /* clone */
97     cryptof_rw,
98     cryptof_rw,
99     cryptof_ioctl,
100     cryptof_poll,
101     cryptof_kqfilter,
102     cryptof_stat,
103     cryptof_close,
104     nofo_shutdown
105 };
106
107 static struct csession *csefind(struct fcrypt *, u_int);
108 static int csedelete(struct fcrypt *, struct csession *);
109 static struct csession *cseadd(struct fcrypt *, struct csession *);
110 static struct csession *csecreate(struct fcrypt *, u_int64_t, caddr_t,
111     u_int64_t, caddr_t, u_int64_t, u_int32_t, u_int32_t, struct enc_xform *,
112     struct auth_hash *);
113 static int csefree(struct csession *);
114
115 static  int cryptodev_op(struct csession *, struct crypt_op *);
116 static  int cryptodev_key(struct crypt_kop *);
117
118 /*
119  * MPSAFE
120  */
121 static int
122 cryptof_rw(
123         struct file *fp,
124         struct uio *uio,
125         struct ucred *active_cred,
126         int flags)
127 {
128         return (EIO);
129 }
130
131 /*
132  * MPALMOSTSAFE - acquires mplock
133  */
134 static int
135 cryptof_ioctl(
136         struct file *fp,
137         u_long cmd,
138         caddr_t data,
139         struct ucred *cred)
140 {
141         struct cryptoini cria, crie;
142         struct fcrypt *fcr;
143         struct csession *cse;
144         struct session_op *sop;
145         struct crypt_op *cop;
146         struct enc_xform *txform = NULL;
147         struct auth_hash *thash = NULL;
148         u_int64_t sid;
149         u_int32_t ses;
150         int error = 0;
151
152         get_mplock();
153         fcr = (struct fcrypt *)fp->f_data;
154
155         switch (cmd) {
156         case CIOCGSESSION:
157                 sop = (struct session_op *)data;
158                 switch (sop->cipher) {
159                 case 0:
160                         break;
161                 case CRYPTO_DES_CBC:
162                         txform = &enc_xform_des;
163                         break;
164                 case CRYPTO_3DES_CBC:
165                         txform = &enc_xform_3des;
166                         break;
167                 case CRYPTO_BLF_CBC:
168                         txform = &enc_xform_blf;
169                         break;
170                 case CRYPTO_CAST_CBC:
171                         txform = &enc_xform_cast5;
172                         break;
173                 case CRYPTO_SKIPJACK_CBC:
174                         txform = &enc_xform_skipjack;
175                         break;
176                 case CRYPTO_AES_CBC:
177                         txform = &enc_xform_rijndael128;
178                         break;
179                 case CRYPTO_NULL_CBC:
180                         txform = &enc_xform_null;
181                         break;
182                 case CRYPTO_ARC4:
183                         txform = &enc_xform_arc4;
184                         break;
185                 default:
186                         error = EINVAL;
187                         break;
188                 }
189                 if (error)
190                         break;
191
192                 switch (sop->mac) {
193                 case 0:
194                         break;
195                 case CRYPTO_MD5_HMAC:
196                         thash = &auth_hash_hmac_md5_96;
197                         break;
198                 case CRYPTO_SHA1_HMAC:
199                         thash = &auth_hash_hmac_sha1_96;
200                         break;
201                 case CRYPTO_SHA2_HMAC:
202                         if (sop->mackeylen == auth_hash_hmac_sha2_256.keysize)
203                                 thash = &auth_hash_hmac_sha2_256;
204                         else if (sop->mackeylen == auth_hash_hmac_sha2_384.keysize)
205                                 thash = &auth_hash_hmac_sha2_384;
206                         else if (sop->mackeylen == auth_hash_hmac_sha2_512.keysize)
207                                 thash = &auth_hash_hmac_sha2_512;
208                         else {
209                                 error = EINVAL;
210                                 break;
211                         }
212                         break;
213                 case CRYPTO_RIPEMD160_HMAC:
214                         thash = &auth_hash_hmac_ripemd_160_96;
215                         break;
216 #ifdef notdef
217                 case CRYPTO_MD5:
218                         thash = &auth_hash_md5;
219                         break;
220                 case CRYPTO_SHA1:
221                         thash = &auth_hash_sha1;
222                         break;
223 #endif
224                 case CRYPTO_NULL_HMAC:
225                         thash = &auth_hash_null;
226                         break;
227                 default:
228                         error = EINVAL;
229                         break;
230                 }
231                 if (error)
232                         break;
233
234                 bzero(&crie, sizeof(crie));
235                 bzero(&cria, sizeof(cria));
236
237                 if (txform) {
238                         crie.cri_alg = txform->type;
239                         crie.cri_klen = sop->keylen * 8;
240                         if (sop->keylen > txform->maxkey ||
241                             sop->keylen < txform->minkey) {
242                                 error = EINVAL;
243                                 goto bail;
244                         }
245
246                         MALLOC(crie.cri_key, u_int8_t *,
247                             crie.cri_klen / 8, M_XDATA, M_WAITOK);
248                         if ((error = copyin(sop->key, crie.cri_key,
249                             crie.cri_klen / 8)))
250                                 goto bail;
251                         if (thash)
252                                 crie.cri_next = &cria;
253                 }
254
255                 if (thash) {
256                         cria.cri_alg = thash->type;
257                         cria.cri_klen = sop->mackeylen * 8;
258                         if (sop->mackeylen != thash->keysize) {
259                                 error = EINVAL;
260                                 goto bail;
261                         }
262
263                         if (cria.cri_klen) {
264                                 MALLOC(cria.cri_key, u_int8_t *,
265                                     cria.cri_klen / 8, M_XDATA, M_WAITOK);
266                                 if ((error = copyin(sop->mackey, cria.cri_key,
267                                     cria.cri_klen / 8)))
268                                         goto bail;
269                         }
270                 }
271
272                 error = crypto_newsession(&sid, (txform ? &crie : &cria), 1);
273                 if (error)
274                         goto bail;
275
276                 cse = csecreate(fcr, sid, crie.cri_key, crie.cri_klen,
277                     cria.cri_key, cria.cri_klen, sop->cipher, sop->mac, txform,
278                     thash);
279
280                 if (cse == NULL) {
281                         crypto_freesession(sid);
282                         error = EINVAL;
283                         goto bail;
284                 }
285                 sop->ses = cse->ses;
286
287 bail:
288                 if (error) {
289                         if (crie.cri_key)
290                                 FREE(crie.cri_key, M_XDATA);
291                         if (cria.cri_key)
292                                 FREE(cria.cri_key, M_XDATA);
293                 }
294                 break;
295         case CIOCFSESSION:
296                 ses = *(u_int32_t *)data;
297                 cse = csefind(fcr, ses);
298                 if (cse == NULL) {
299                         error = EINVAL;
300                         break;
301                 }
302                 csedelete(fcr, cse);
303                 error = csefree(cse);
304                 break;
305         case CIOCCRYPT:
306                 cop = (struct crypt_op *)data;
307                 cse = csefind(fcr, cop->ses);
308                 if (cse == NULL) {
309                         error = EINVAL;
310                         break;
311                 }
312                 error = cryptodev_op(cse, cop);
313                 break;
314         case CIOCKEY:
315                 error = cryptodev_key((struct crypt_kop *)data);
316                 break;
317         case CIOCASYMFEAT:
318                 error = crypto_getfeat((int *)data);
319                 break;
320         default:
321                 error = EINVAL;
322                 break;
323         }
324         rel_mplock();
325         return (error);
326 }
327
328 static int cryptodev_cb(void *);
329
330
331 static int
332 cryptodev_op(struct csession *cse, struct crypt_op *cop)
333 {
334         struct cryptop *crp = NULL;
335         struct cryptodesc *crde = NULL, *crda = NULL;
336         int i, error;
337
338         if (cop->len > 256*1024-4)
339                 return (E2BIG);
340
341         if (cse->txform && (cop->len % cse->txform->blocksize) != 0)
342                 return (EINVAL);
343
344         bzero(&cse->uio, sizeof(cse->uio));
345         cse->uio.uio_iovcnt = 1;
346         cse->uio.uio_resid = 0;
347         cse->uio.uio_segflg = UIO_SYSSPACE;
348         cse->uio.uio_rw = UIO_WRITE;
349         cse->uio.uio_td = curthread;
350         cse->uio.uio_iov = cse->iovec;
351         bzero(&cse->iovec, sizeof(cse->iovec));
352         cse->uio.uio_iov[0].iov_len = cop->len;
353         cse->uio.uio_iov[0].iov_base = malloc(cop->len, M_XDATA, M_WAITOK);
354         for (i = 0; i < cse->uio.uio_iovcnt; i++)
355                 cse->uio.uio_resid += cse->uio.uio_iov[0].iov_len;
356
357         crp = crypto_getreq((cse->txform != NULL) + (cse->thash != NULL));
358         if (crp == NULL) {
359                 error = ENOMEM;
360                 goto bail;
361         }
362
363         if (cse->thash) {
364                 crda = crp->crp_desc;
365                 if (cse->txform)
366                         crde = crda->crd_next;
367         } else {
368                 if (cse->txform)
369                         crde = crp->crp_desc;
370                 else {
371                         error = EINVAL;
372                         goto bail;
373                 }
374         }
375
376         if ((error = copyin(cop->src, cse->uio.uio_iov[0].iov_base, cop->len)))
377                 goto bail;
378
379         if (crda) {
380                 crda->crd_skip = 0;
381                 crda->crd_len = cop->len;
382                 crda->crd_inject = 0;   /* ??? */
383
384                 crda->crd_alg = cse->mac;
385                 crda->crd_key = cse->mackey;
386                 crda->crd_klen = cse->mackeylen * 8;
387         }
388
389         if (crde) {
390                 if (cop->op == COP_ENCRYPT)
391                         crde->crd_flags |= CRD_F_ENCRYPT;
392                 else
393                         crde->crd_flags &= ~CRD_F_ENCRYPT;
394                 crde->crd_len = cop->len;
395                 crde->crd_inject = 0;
396
397                 crde->crd_alg = cse->cipher;
398                 crde->crd_key = cse->key;
399                 crde->crd_klen = cse->keylen * 8;
400         }
401
402         crp->crp_ilen = cop->len;
403         crp->crp_flags = CRYPTO_F_IOV | CRYPTO_F_CBIMM
404                        | (cop->flags & COP_F_BATCH);
405         crp->crp_buf = (caddr_t)&cse->uio;
406         crp->crp_callback = (int (*) (struct cryptop *)) cryptodev_cb;
407         crp->crp_sid = cse->sid;
408         crp->crp_opaque = (void *)cse;
409
410         if (cop->iv) {
411                 if (crde == NULL) {
412                         error = EINVAL;
413                         goto bail;
414                 }
415                 if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */
416                         error = EINVAL;
417                         goto bail;
418                 }
419                 if ((error = copyin(cop->iv, cse->tmp_iv, cse->txform->blocksize)))
420                         goto bail;
421                 bcopy(cse->tmp_iv, crde->crd_iv, cse->txform->blocksize);
422                 crde->crd_flags |= CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT;
423                 crde->crd_skip = 0;
424         } else if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */
425                 crde->crd_skip = 0;
426         } else if (crde) {
427                 crde->crd_flags |= CRD_F_IV_PRESENT;
428                 crde->crd_skip = cse->txform->blocksize;
429                 crde->crd_len -= cse->txform->blocksize;
430         }
431
432         if (cop->mac) {
433                 if (crda == NULL) {
434                         error = EINVAL;
435                         goto bail;
436                 }
437                 crp->crp_mac=cse->tmp_mac;
438         }
439
440         crit_enter();
441         error = crypto_dispatch(crp);
442         if (error == 0 && (crp->crp_flags & CRYPTO_F_DONE) == 0)
443                 error = tsleep(crp, 0, "crydev", 0);
444         crit_exit();
445         if (error)
446                 goto bail;
447
448         if (crp->crp_etype != 0) {
449                 error = crp->crp_etype;
450                 goto bail;
451         }
452
453         if (cse->error) {
454                 error = cse->error;
455                 goto bail;
456         }
457
458         if (cop->dst &&
459             (error = copyout(cse->uio.uio_iov[0].iov_base, cop->dst, cop->len)))
460                 goto bail;
461
462         if (cop->mac &&
463             (error = copyout(crp->crp_mac, cop->mac, cse->thash->authsize)))
464                 goto bail;
465
466 bail:
467         if (crp)
468                 crypto_freereq(crp);
469         if (cse->uio.uio_iov[0].iov_base)
470                 free(cse->uio.uio_iov[0].iov_base, M_XDATA);
471
472         return (error);
473 }
474
475 static int
476 cryptodev_cb(void *op)
477 {
478         struct cryptop *crp = (struct cryptop *) op;
479         struct csession *cse = (struct csession *)crp->crp_opaque;
480
481         cse->error = crp->crp_etype;
482         if (crp->crp_etype == EAGAIN)
483                 return crypto_dispatch(crp);
484         wakeup_one(crp);
485         return (0);
486 }
487
488 static int
489 cryptodevkey_cb(void *op)
490 {
491         struct cryptkop *krp = (struct cryptkop *) op;
492
493         wakeup_one(krp);
494         return (0);
495 }
496
497 static int
498 cryptodev_key(struct crypt_kop *kop)
499 {
500         struct cryptkop *krp = NULL;
501         int error = EINVAL;
502         int in, out, size, i;
503
504         if (kop->crk_iparams + kop->crk_oparams > CRK_MAXPARAM) {
505                 return (EFBIG);
506         }
507
508         in = kop->crk_iparams;
509         out = kop->crk_oparams;
510         switch (kop->crk_op) {
511         case CRK_MOD_EXP:
512                 if (in == 3 && out == 1)
513                         break;
514                 return (EINVAL);
515         case CRK_MOD_EXP_CRT:
516                 if (in == 6 && out == 1)
517                         break;
518                 return (EINVAL);
519         case CRK_DSA_SIGN:
520                 if (in == 5 && out == 2)
521                         break;
522                 return (EINVAL);
523         case CRK_DSA_VERIFY:
524                 if (in == 7 && out == 0)
525                         break;
526                 return (EINVAL);
527         case CRK_DH_COMPUTE_KEY:
528                 if (in == 3 && out == 1)
529                         break;
530                 return (EINVAL);
531         default:
532                 return (EINVAL);
533         }
534
535         krp = (struct cryptkop *)malloc(sizeof *krp, M_XDATA, M_WAITOK);
536         if (!krp)
537                 return (ENOMEM);
538         bzero(krp, sizeof *krp);
539         krp->krp_op = kop->crk_op;
540         krp->krp_status = kop->crk_status;
541         krp->krp_iparams = kop->crk_iparams;
542         krp->krp_oparams = kop->crk_oparams;
543         krp->krp_status = 0;
544         krp->krp_callback = (int (*) (struct cryptkop *)) cryptodevkey_cb;
545
546         for (i = 0; i < CRK_MAXPARAM; i++)
547                 krp->krp_param[i].crp_nbits = kop->crk_param[i].crp_nbits;
548         for (i = 0; i < krp->krp_iparams + krp->krp_oparams; i++) {
549                 size = (krp->krp_param[i].crp_nbits + 7) / 8;
550                 if (size == 0)
551                         continue;
552                 MALLOC(krp->krp_param[i].crp_p, caddr_t, size, M_XDATA, M_WAITOK);
553                 if (i >= krp->krp_iparams)
554                         continue;
555                 error = copyin(kop->crk_param[i].crp_p, krp->krp_param[i].crp_p, size);
556                 if (error)
557                         goto fail;
558         }
559
560         error = crypto_kdispatch(krp);
561         if (error == 0)
562                 error = tsleep(krp, 0, "crydev", 0);
563         if (error)
564                 goto fail;
565         
566         if (krp->krp_status != 0) {
567                 error = krp->krp_status;
568                 goto fail;
569         }
570
571         for (i = krp->krp_iparams; i < krp->krp_iparams + krp->krp_oparams; i++) {
572                 size = (krp->krp_param[i].crp_nbits + 7) / 8;
573                 if (size == 0)
574                         continue;
575                 error = copyout(krp->krp_param[i].crp_p, kop->crk_param[i].crp_p, size);
576                 if (error)
577                         goto fail;
578         }
579
580 fail:
581         if (krp) {
582                 kop->crk_status = krp->krp_status;
583                 for (i = 0; i < CRK_MAXPARAM; i++) {
584                         if (krp->krp_param[i].crp_p)
585                                 FREE(krp->krp_param[i].crp_p, M_XDATA);
586                 }
587                 free(krp, M_XDATA);
588         }
589         return (error);
590 }
591
592 /*
593  * MPSAFE
594  */
595 static int
596 cryptof_poll(struct file *fp, int events, struct ucred *active_cred)
597 {
598         return (0);
599 }
600
601 /*
602  * MPSAFE
603  */
604 static int
605 cryptof_kqfilter(struct file *fp, struct knote *kn)
606 {
607
608         return (0);
609 }
610
611 /*
612  * MPSAFE
613  */
614 static int
615 cryptof_stat(struct file *fp, struct stat *sb, struct ucred *cred)
616 {
617         return (EOPNOTSUPP);
618 }
619
620 /*
621  * MPALMOSTSAFE - acquires mplock
622  */
623 static int
624 cryptof_close(struct file *fp)
625 {
626         struct fcrypt *fcr;
627         struct csession *cse;
628
629         get_mplock();
630         fcr = (struct fcrypt *)fp->f_data;
631         while ((cse = TAILQ_FIRST(&fcr->csessions))) {
632                 TAILQ_REMOVE(&fcr->csessions, cse, next);
633                 (void)csefree(cse);
634         }
635         fp->f_data = NULL;
636         rel_mplock();
637
638         FREE(fcr, M_XDATA);
639         return (0);
640 }
641
642 static struct csession *
643 csefind(struct fcrypt *fcr, u_int ses)
644 {
645         struct csession *cse;
646
647         TAILQ_FOREACH(cse, &fcr->csessions, next)
648                 if (cse->ses == ses)
649                         return (cse);
650         return (NULL);
651 }
652
653 static int
654 csedelete(struct fcrypt *fcr, struct csession *cse_del)
655 {
656         struct csession *cse;
657
658         TAILQ_FOREACH(cse, &fcr->csessions, next) {
659                 if (cse == cse_del) {
660                         TAILQ_REMOVE(&fcr->csessions, cse, next);
661                         return (1);
662                 }
663         }
664         return (0);
665 }
666         
667 static struct csession *
668 cseadd(struct fcrypt *fcr, struct csession *cse)
669 {
670         TAILQ_INSERT_TAIL(&fcr->csessions, cse, next);
671         cse->ses = fcr->sesn++;
672         return (cse);
673 }
674
675 struct csession *
676 csecreate(struct fcrypt *fcr, u_int64_t sid, caddr_t key, u_int64_t keylen,
677     caddr_t mackey, u_int64_t mackeylen, u_int32_t cipher, u_int32_t mac,
678     struct enc_xform *txform, struct auth_hash *thash)
679 {
680         struct csession *cse;
681
682         MALLOC(cse, struct csession *, sizeof(struct csession),
683             M_XDATA, M_NOWAIT);
684         if (cse == NULL)
685                 return NULL;
686         cse->key = key;
687         cse->keylen = keylen/8;
688         cse->mackey = mackey;
689         cse->mackeylen = mackeylen/8;
690         cse->sid = sid;
691         cse->cipher = cipher;
692         cse->mac = mac;
693         cse->txform = txform;
694         cse->thash = thash;
695         cseadd(fcr, cse);
696         return (cse);
697 }
698
699 static int
700 csefree(struct csession *cse)
701 {
702         int error;
703
704         error = crypto_freesession(cse->sid);
705         if (cse->key)
706                 FREE(cse->key, M_XDATA);
707         if (cse->mackey)
708                 FREE(cse->mackey, M_XDATA);
709         FREE(cse, M_XDATA);
710         return (error);
711 }
712
713 static int
714 cryptoopen(dev_t dev, int oflags, int devtype, struct thread *td)
715 {
716         if (crypto_usercrypto == 0)
717                 return (ENXIO);
718         return (0);
719 }
720
721 static int
722 cryptoread(dev_t dev, struct uio *uio, int ioflag)
723 {
724         return (EIO);
725 }
726
727 static int
728 cryptowrite(dev_t dev, struct uio *uio, int ioflag)
729 {
730         return (EIO);
731 }
732
733 static int
734 cryptoioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td)
735 {
736         struct file *f;
737         struct fcrypt *fcr;
738         int fd, error;
739         switch (cmd) {
740         case CRIOGET:
741                 MALLOC(fcr, struct fcrypt *,
742                     sizeof(struct fcrypt), M_XDATA, M_WAITOK);
743                 TAILQ_INIT(&fcr->csessions);
744                 fcr->sesn = 0;
745
746                 KKASSERT(td->td_proc);
747                 error = falloc(td->td_proc, &f, &fd);
748
749                 if (error) {
750                         FREE(fcr, M_XDATA);
751                         return (error);
752                 }
753                 f->f_type = DTYPE_CRYPTO;
754                 f->f_flag = FREAD | FWRITE;
755                 f->f_ops = &cryptofops;
756                 f->f_data = fcr;
757                 fsetfd(td->td_proc, f, fd);
758                 *(u_int32_t *)data = fd;
759                 fdrop(f);
760                 break;
761         default:
762                 error = EINVAL;
763                 break;
764         }
765         return (error);
766 }
767
768 #define CRYPTO_MAJOR    70              /* from openbsd */
769 static struct cdevsw crypto_cdevsw = {
770         /* dev name */  "crypto",
771         /* dev major */ CRYPTO_MAJOR,
772         /* flags */     0,
773         /* port */      NULL,
774         /* clone */     NULL,
775
776         /* open */      cryptoopen,
777         /* close */     nullclose,
778         /* read */      cryptoread,
779         /* write */     cryptowrite,
780         /* ioctl */     cryptoioctl,
781         /* poll */      nopoll,
782         /* mmap */      nommap,
783         /* strategy */  nostrategy,
784         /* dump */      nodump,
785         /* psize */     nopsize,
786         /* kqfilter */  NULL
787 };
788
789 /*
790  * Initialization code, both for static and dynamic loading.
791  */
792 static int
793 cryptodev_modevent(module_t mod, int type, void *unused)
794 {
795         switch (type) {
796         case MOD_LOAD:
797                 if (bootverbose)
798                         printf("crypto: <crypto device>\n");
799                 cdevsw_add(&crypto_cdevsw, 0, 0);
800                 make_dev(&crypto_cdevsw, 0, UID_ROOT, GID_WHEEL,
801                         0666, "crypto");
802                 return 0;
803         case MOD_UNLOAD:
804                 /*XXX disallow if active sessions */
805                 cdevsw_remove(&crypto_cdevsw, 0, 0);
806                 return 0;
807         }
808         return EINVAL;
809 }
810
811 static moduledata_t cryptodev_mod = {
812         "cryptodev",
813         cryptodev_modevent,
814         0
815 };
816 MODULE_VERSION(cryptodev, 1);
817 DECLARE_MODULE(cryptodev, cryptodev_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
818 #if 0
819 MODULE_DEPEND(cryptodev, crypto, 1, 1, 1);
820 #endif