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