]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/opencrypto/cryptodev.c
IFC @r272185
[FreeBSD/FreeBSD.git] / sys / opencrypto / cryptodev.c
1 /*      $OpenBSD: cryptodev.c,v 1.52 2002/06/19 07:22:46 deraadt Exp $  */
2
3 /*-
4  * Copyright (c) 2001 Theo de Raadt
5  * Copyright (c) 2002-2006 Sam Leffler, Errno Consulting
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *   notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *   notice, this list of conditions and the following disclaimer in the
15  *   documentation and/or other materials provided with the distribution.
16  * 3. The name of the author may not be used to endorse or promote products
17  *   derived from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  *
30  * Effort sponsored in part by the Defense Advanced Research Projects
31  * Agency (DARPA) and Air Force Research Laboratory, Air Force
32  * Materiel Command, USAF, under agreement number F30602-01-2-0537.
33  */
34
35 #include <sys/cdefs.h>
36 __FBSDID("$FreeBSD$");
37
38 #include "opt_compat.h"
39
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/malloc.h>
43 #include <sys/mbuf.h>
44 #include <sys/lock.h>
45 #include <sys/mutex.h>
46 #include <sys/sysctl.h>
47 #include <sys/file.h>
48 #include <sys/filedesc.h>
49 #include <sys/errno.h>
50 #include <sys/uio.h>
51 #include <sys/random.h>
52 #include <sys/conf.h>
53 #include <sys/kernel.h>
54 #include <sys/module.h>
55 #include <sys/fcntl.h>
56 #include <sys/bus.h>
57 #include <sys/user.h>
58
59 #include <opencrypto/cryptodev.h>
60 #include <opencrypto/xform.h>
61
62 #ifdef COMPAT_FREEBSD32
63 #include <sys/mount.h>
64 #include <compat/freebsd32/freebsd32.h>
65
66 struct session_op32 {
67         u_int32_t       cipher;
68         u_int32_t       mac;
69         u_int32_t       keylen;
70         u_int32_t       key;
71         int             mackeylen;
72         u_int32_t       mackey;
73         u_int32_t       ses;
74 };
75
76 struct session2_op32 {
77         u_int32_t       cipher;
78         u_int32_t       mac;
79         u_int32_t       keylen;
80         u_int32_t       key;
81         int             mackeylen;
82         u_int32_t       mackey;
83         u_int32_t       ses;
84         int             crid;
85         int             pad[4];
86 };
87
88 struct crypt_op32 {
89         u_int32_t       ses;
90         u_int16_t       op;
91         u_int16_t       flags;
92         u_int           len;
93         u_int32_t       src, dst;
94         u_int32_t       mac;
95         u_int32_t       iv;
96 };
97
98 struct crparam32 {
99         u_int32_t       crp_p;
100         u_int           crp_nbits;
101 };
102
103 struct crypt_kop32 {
104         u_int           crk_op;
105         u_int           crk_status;
106         u_short         crk_iparams;
107         u_short         crk_oparams;
108         u_int           crk_crid;
109         struct crparam32        crk_param[CRK_MAXPARAM];
110 };
111
112 struct cryptotstat32 {
113         struct timespec32       acc;
114         struct timespec32       min;
115         struct timespec32       max;
116         u_int32_t       count;
117 };
118
119 struct cryptostats32 {
120         u_int32_t       cs_ops;
121         u_int32_t       cs_errs;
122         u_int32_t       cs_kops;
123         u_int32_t       cs_kerrs;
124         u_int32_t       cs_intrs;
125         u_int32_t       cs_rets;
126         u_int32_t       cs_blocks;
127         u_int32_t       cs_kblocks;
128         struct cryptotstat32 cs_invoke;
129         struct cryptotstat32 cs_done;
130         struct cryptotstat32 cs_cb;
131         struct cryptotstat32 cs_finis;
132 };
133
134 #define CIOCGSESSION32  _IOWR('c', 101, struct session_op32)
135 #define CIOCCRYPT32     _IOWR('c', 103, struct crypt_op32)
136 #define CIOCKEY32       _IOWR('c', 104, struct crypt_kop32)
137 #define CIOCGSESSION232 _IOWR('c', 106, struct session2_op32)
138 #define CIOCKEY232      _IOWR('c', 107, struct crypt_kop32)
139
140 static void
141 session_op_from_32(const struct session_op32 *from, struct session_op *to)
142 {
143
144         CP(*from, *to, cipher);
145         CP(*from, *to, mac);
146         CP(*from, *to, keylen);
147         PTRIN_CP(*from, *to, key);
148         CP(*from, *to, mackeylen);
149         PTRIN_CP(*from, *to, mackey);
150         CP(*from, *to, ses);
151 }
152
153 static void
154 session2_op_from_32(const struct session2_op32 *from, struct session2_op *to)
155 {
156
157         session_op_from_32((const struct session_op32 *)from,
158             (struct session_op *)to);
159         CP(*from, *to, crid);
160 }
161
162 static void
163 session_op_to_32(const struct session_op *from, struct session_op32 *to)
164 {
165
166         CP(*from, *to, cipher);
167         CP(*from, *to, mac);
168         CP(*from, *to, keylen);
169         PTROUT_CP(*from, *to, key);
170         CP(*from, *to, mackeylen);
171         PTROUT_CP(*from, *to, mackey);
172         CP(*from, *to, ses);
173 }
174
175 static void
176 session2_op_to_32(const struct session2_op *from, struct session2_op32 *to)
177 {
178
179         session_op_to_32((const struct session_op *)from,
180             (struct session_op32 *)to);
181         CP(*from, *to, crid);
182 }
183
184 static void
185 crypt_op_from_32(const struct crypt_op32 *from, struct crypt_op *to)
186 {
187
188         CP(*from, *to, ses);
189         CP(*from, *to, op);
190         CP(*from, *to, flags);
191         CP(*from, *to, len);
192         PTRIN_CP(*from, *to, src);
193         PTRIN_CP(*from, *to, dst);
194         PTRIN_CP(*from, *to, mac);
195         PTRIN_CP(*from, *to, iv);
196 }
197
198 static void
199 crypt_op_to_32(const struct crypt_op *from, struct crypt_op32 *to)
200 {
201
202         CP(*from, *to, ses);
203         CP(*from, *to, op);
204         CP(*from, *to, flags);
205         CP(*from, *to, len);
206         PTROUT_CP(*from, *to, src);
207         PTROUT_CP(*from, *to, dst);
208         PTROUT_CP(*from, *to, mac);
209         PTROUT_CP(*from, *to, iv);
210 }
211
212 static void
213 crparam_from_32(const struct crparam32 *from, struct crparam *to)
214 {
215
216         PTRIN_CP(*from, *to, crp_p);
217         CP(*from, *to, crp_nbits);
218 }
219
220 static void
221 crparam_to_32(const struct crparam *from, struct crparam32 *to)
222 {
223
224         PTROUT_CP(*from, *to, crp_p);
225         CP(*from, *to, crp_nbits);
226 }
227
228 static void
229 crypt_kop_from_32(const struct crypt_kop32 *from, struct crypt_kop *to)
230 {
231         int i;
232
233         CP(*from, *to, crk_op);
234         CP(*from, *to, crk_status);
235         CP(*from, *to, crk_iparams);
236         CP(*from, *to, crk_oparams);
237         CP(*from, *to, crk_crid);
238         for (i = 0; i < CRK_MAXPARAM; i++)
239                 crparam_from_32(&from->crk_param[i], &to->crk_param[i]);
240 }
241
242 static void
243 crypt_kop_to_32(const struct crypt_kop *from, struct crypt_kop32 *to)
244 {
245         int i;
246
247         CP(*from, *to, crk_op);
248         CP(*from, *to, crk_status);
249         CP(*from, *to, crk_iparams);
250         CP(*from, *to, crk_oparams);
251         CP(*from, *to, crk_crid);
252         for (i = 0; i < CRK_MAXPARAM; i++)
253                 crparam_to_32(&from->crk_param[i], &to->crk_param[i]);
254 }
255 #endif
256
257 struct csession {
258         TAILQ_ENTRY(csession) next;
259         u_int64_t       sid;
260         u_int32_t       ses;
261         struct mtx      lock;           /* for op submission */
262
263         u_int32_t       cipher;
264         struct enc_xform *txform;
265         u_int32_t       mac;
266         struct auth_hash *thash;
267
268         caddr_t         key;
269         int             keylen;
270         u_char          tmp_iv[EALG_MAX_BLOCK_LEN];
271
272         caddr_t         mackey;
273         int             mackeylen;
274
275         struct iovec    iovec;
276         struct uio      uio;
277         int             error;
278 };
279
280 struct fcrypt {
281         TAILQ_HEAD(csessionlist, csession) csessions;
282         int             sesn;
283 };
284
285 static  int cryptof_ioctl(struct file *, u_long, void *,
286                     struct ucred *, struct thread *);
287 static  int cryptof_stat(struct file *, struct stat *,
288                     struct ucred *, struct thread *);
289 static  int cryptof_close(struct file *, struct thread *);
290 static  int cryptof_fill_kinfo(struct file *, struct kinfo_file *,
291                     struct filedesc *);
292
293 static struct fileops cryptofops = {
294     .fo_read = invfo_rdwr,
295     .fo_write = invfo_rdwr,
296     .fo_truncate = invfo_truncate,
297     .fo_ioctl = cryptof_ioctl,
298     .fo_poll = invfo_poll,
299     .fo_kqfilter = invfo_kqfilter,
300     .fo_stat = cryptof_stat,
301     .fo_close = cryptof_close,
302     .fo_chmod = invfo_chmod,
303     .fo_chown = invfo_chown,
304     .fo_sendfile = invfo_sendfile,
305     .fo_fill_kinfo = cryptof_fill_kinfo,
306 };
307
308 static struct csession *csefind(struct fcrypt *, u_int);
309 static int csedelete(struct fcrypt *, struct csession *);
310 static struct csession *cseadd(struct fcrypt *, struct csession *);
311 static struct csession *csecreate(struct fcrypt *, u_int64_t, caddr_t,
312     u_int64_t, caddr_t, u_int64_t, u_int32_t, u_int32_t, struct enc_xform *,
313     struct auth_hash *);
314 static int csefree(struct csession *);
315
316 static  int cryptodev_op(struct csession *, struct crypt_op *,
317                         struct ucred *, struct thread *td);
318 static  int cryptodev_key(struct crypt_kop *);
319 static  int cryptodev_find(struct crypt_find_op *);
320
321 /*
322  * Check a crypto identifier to see if it requested
323  * a software device/driver.  This can be done either
324  * by device name/class or through search constraints.
325  */
326 static int
327 checkforsoftware(int crid)
328 {
329
330         if (!crypto_devallowsoft) {
331                 if (crid & CRYPTOCAP_F_SOFTWARE)
332                         return EINVAL;          /* XXX */
333                 if ((crid & CRYPTOCAP_F_HARDWARE) == 0 &&
334                     (crypto_getcaps(crid) & CRYPTOCAP_F_HARDWARE) == 0)
335                         return EINVAL;          /* XXX */
336         }
337         return 0;
338 }
339
340 /* ARGSUSED */
341 static int
342 cryptof_ioctl(
343         struct file *fp,
344         u_long cmd,
345         void *data,
346         struct ucred *active_cred,
347         struct thread *td)
348 {
349 #define SES2(p) ((struct session2_op *)p)
350         struct cryptoini cria, crie;
351         struct fcrypt *fcr = fp->f_data;
352         struct csession *cse;
353         struct session_op *sop;
354         struct crypt_op *cop;
355         struct enc_xform *txform = NULL;
356         struct auth_hash *thash = NULL;
357         struct crypt_kop *kop;
358         u_int64_t sid;
359         u_int32_t ses;
360         int error = 0, crid;
361 #ifdef COMPAT_FREEBSD32
362         struct session2_op sopc;
363         struct crypt_op copc;
364         struct crypt_kop kopc;
365 #endif
366
367         switch (cmd) {
368         case CIOCGSESSION:
369         case CIOCGSESSION2:
370 #ifdef COMPAT_FREEBSD32
371         case CIOCGSESSION32:
372         case CIOCGSESSION232:
373                 if (cmd == CIOCGSESSION32) {
374                         session_op_from_32(data, (struct session_op *)&sopc);
375                         sop = (struct session_op *)&sopc;
376                 } else if (cmd == CIOCGSESSION232) {
377                         session2_op_from_32(data, &sopc);
378                         sop = (struct session_op *)&sopc;
379                 } else
380 #endif
381                         sop = (struct session_op *)data;
382                 switch (sop->cipher) {
383                 case 0:
384                         break;
385                 case CRYPTO_DES_CBC:
386                         txform = &enc_xform_des;
387                         break;
388                 case CRYPTO_3DES_CBC:
389                         txform = &enc_xform_3des;
390                         break;
391                 case CRYPTO_BLF_CBC:
392                         txform = &enc_xform_blf;
393                         break;
394                 case CRYPTO_CAST_CBC:
395                         txform = &enc_xform_cast5;
396                         break;
397                 case CRYPTO_SKIPJACK_CBC:
398                         txform = &enc_xform_skipjack;
399                         break;
400                 case CRYPTO_AES_CBC:
401                         txform = &enc_xform_rijndael128;
402                         break;
403                 case CRYPTO_AES_XTS:
404                         txform = &enc_xform_aes_xts;
405                         break;
406                 case CRYPTO_NULL_CBC:
407                         txform = &enc_xform_null;
408                         break;
409                 case CRYPTO_ARC4:
410                         txform = &enc_xform_arc4;
411                         break;
412                 case CRYPTO_CAMELLIA_CBC:
413                         txform = &enc_xform_camellia;
414                         break;
415                 default:
416                         return (EINVAL);
417                 }
418
419                 switch (sop->mac) {
420                 case 0:
421                         break;
422                 case CRYPTO_MD5_HMAC:
423                         thash = &auth_hash_hmac_md5;
424                         break;
425                 case CRYPTO_SHA1_HMAC:
426                         thash = &auth_hash_hmac_sha1;
427                         break;
428                 case CRYPTO_SHA2_256_HMAC:
429                         thash = &auth_hash_hmac_sha2_256;
430                         break;
431                 case CRYPTO_SHA2_384_HMAC:
432                         thash = &auth_hash_hmac_sha2_384;
433                         break;
434                 case CRYPTO_SHA2_512_HMAC:
435                         thash = &auth_hash_hmac_sha2_512;
436                         break;
437                 case CRYPTO_RIPEMD160_HMAC:
438                         thash = &auth_hash_hmac_ripemd_160;
439                         break;
440 #ifdef notdef
441                 case CRYPTO_MD5:
442                         thash = &auth_hash_md5;
443                         break;
444                 case CRYPTO_SHA1:
445                         thash = &auth_hash_sha1;
446                         break;
447 #endif
448                 case CRYPTO_NULL_HMAC:
449                         thash = &auth_hash_null;
450                         break;
451                 default:
452                         return (EINVAL);
453                 }
454
455                 bzero(&crie, sizeof(crie));
456                 bzero(&cria, sizeof(cria));
457
458                 if (txform) {
459                         crie.cri_alg = txform->type;
460                         crie.cri_klen = sop->keylen * 8;
461                         if (sop->keylen > txform->maxkey ||
462                             sop->keylen < txform->minkey) {
463                                 error = EINVAL;
464                                 goto bail;
465                         }
466
467                         crie.cri_key = malloc(crie.cri_klen / 8,
468                             M_XDATA, M_WAITOK);
469                         if ((error = copyin(sop->key, crie.cri_key,
470                             crie.cri_klen / 8)))
471                                 goto bail;
472                         if (thash)
473                                 crie.cri_next = &cria;
474                 }
475
476                 if (thash) {
477                         cria.cri_alg = thash->type;
478                         cria.cri_klen = sop->mackeylen * 8;
479                         if (sop->mackeylen != thash->keysize) {
480                                 error = EINVAL;
481                                 goto bail;
482                         }
483
484                         if (cria.cri_klen) {
485                                 cria.cri_key = malloc(cria.cri_klen / 8,
486                                     M_XDATA, M_WAITOK);
487                                 if ((error = copyin(sop->mackey, cria.cri_key,
488                                     cria.cri_klen / 8)))
489                                         goto bail;
490                         }
491                 }
492
493                 /* NB: CIOCGSESSION2 has the crid */
494                 if (cmd == CIOCGSESSION2
495 #ifdef COMPAT_FREEBSD32
496                     || cmd == CIOCGSESSION232
497 #endif
498                         ) {
499                         crid = SES2(sop)->crid;
500                         error = checkforsoftware(crid);
501                         if (error)
502                                 goto bail;
503                 } else
504                         crid = CRYPTOCAP_F_HARDWARE;
505                 error = crypto_newsession(&sid, (txform ? &crie : &cria), crid);
506                 if (error)
507                         goto bail;
508
509                 cse = csecreate(fcr, sid, crie.cri_key, crie.cri_klen,
510                     cria.cri_key, cria.cri_klen, sop->cipher, sop->mac, txform,
511                     thash);
512
513                 if (cse == NULL) {
514                         crypto_freesession(sid);
515                         error = EINVAL;
516                         goto bail;
517                 }
518                 sop->ses = cse->ses;
519                 if (cmd == CIOCGSESSION2
520 #ifdef COMPAT_FREEBSD32
521                     || cmd == CIOCGSESSION232
522 #endif
523                     ) {
524                         /* return hardware/driver id */
525                         SES2(sop)->crid = CRYPTO_SESID2HID(cse->sid);
526                 }
527 bail:
528                 if (error) {
529                         if (crie.cri_key)
530                                 free(crie.cri_key, M_XDATA);
531                         if (cria.cri_key)
532                                 free(cria.cri_key, M_XDATA);
533                 }
534 #ifdef COMPAT_FREEBSD32
535                 else {
536                         if (cmd == CIOCGSESSION32)
537                                 session_op_to_32(sop, data);
538                         else if (cmd == CIOCGSESSION232)
539                                 session2_op_to_32((struct session2_op *)sop,
540                                     data);
541                 }
542 #endif
543                 break;
544         case CIOCFSESSION:
545                 ses = *(u_int32_t *)data;
546                 cse = csefind(fcr, ses);
547                 if (cse == NULL)
548                         return (EINVAL);
549                 csedelete(fcr, cse);
550                 error = csefree(cse);
551                 break;
552         case CIOCCRYPT:
553 #ifdef COMPAT_FREEBSD32
554         case CIOCCRYPT32:
555                 if (cmd == CIOCCRYPT32) {
556                         cop = &copc;
557                         crypt_op_from_32(data, cop);
558                 } else
559 #endif
560                         cop = (struct crypt_op *)data;
561                 cse = csefind(fcr, cop->ses);
562                 if (cse == NULL)
563                         return (EINVAL);
564                 error = cryptodev_op(cse, cop, active_cred, td);
565 #ifdef COMPAT_FREEBSD32
566                 if (error == 0 && cmd == CIOCCRYPT32)
567                         crypt_op_to_32(cop, data);
568 #endif
569                 break;
570         case CIOCKEY:
571         case CIOCKEY2:
572 #ifdef COMPAT_FREEBSD32
573         case CIOCKEY32:
574         case CIOCKEY232:
575 #endif
576                 if (!crypto_userasymcrypto)
577                         return (EPERM);         /* XXX compat? */
578 #ifdef COMPAT_FREEBSD32
579                 if (cmd == CIOCKEY32 || cmd == CIOCKEY232) {
580                         kop = &kopc;
581                         crypt_kop_from_32(data, kop);
582                 } else
583 #endif
584                         kop = (struct crypt_kop *)data;
585                 if (cmd == CIOCKEY
586 #ifdef COMPAT_FREEBSD32
587                     || cmd == CIOCKEY32
588 #endif
589                     ) {
590                         /* NB: crypto core enforces s/w driver use */
591                         kop->crk_crid =
592                             CRYPTOCAP_F_HARDWARE | CRYPTOCAP_F_SOFTWARE;
593                 }
594                 mtx_lock(&Giant);
595                 error = cryptodev_key(kop);
596                 mtx_unlock(&Giant);
597 #ifdef COMPAT_FREEBSD32
598                 if (cmd == CIOCKEY32 || cmd == CIOCKEY232)
599                         crypt_kop_to_32(kop, data);
600 #endif
601                 break;
602         case CIOCASYMFEAT:
603                 if (!crypto_userasymcrypto) {
604                         /*
605                          * NB: if user asym crypto operations are
606                          * not permitted return "no algorithms"
607                          * so well-behaved applications will just
608                          * fallback to doing them in software.
609                          */
610                         *(int *)data = 0;
611                 } else
612                         error = crypto_getfeat((int *)data);
613                 break;
614         case CIOCFINDDEV:
615                 error = cryptodev_find((struct crypt_find_op *)data);
616                 break;
617         default:
618                 error = EINVAL;
619                 break;
620         }
621         return (error);
622 #undef SES2
623 }
624
625 static int cryptodev_cb(void *);
626
627
628 static int
629 cryptodev_op(
630         struct csession *cse,
631         struct crypt_op *cop,
632         struct ucred *active_cred,
633         struct thread *td)
634 {
635         struct cryptop *crp = NULL;
636         struct cryptodesc *crde = NULL, *crda = NULL;
637         int error;
638
639         if (cop->len > 256*1024-4)
640                 return (E2BIG);
641
642         if (cse->txform) {
643                 if (cop->len == 0 || (cop->len % cse->txform->blocksize) != 0)
644                         return (EINVAL);
645         }
646
647         cse->uio.uio_iov = &cse->iovec;
648         cse->uio.uio_iovcnt = 1;
649         cse->uio.uio_offset = 0;
650         cse->uio.uio_resid = cop->len;
651         cse->uio.uio_segflg = UIO_SYSSPACE;
652         cse->uio.uio_rw = UIO_WRITE;
653         cse->uio.uio_td = td;
654         cse->uio.uio_iov[0].iov_len = cop->len;
655         if (cse->thash) {
656                 cse->uio.uio_iov[0].iov_len += cse->thash->hashsize;
657                 cse->uio.uio_resid += cse->thash->hashsize;
658         }
659         cse->uio.uio_iov[0].iov_base = malloc(cse->uio.uio_iov[0].iov_len,
660             M_XDATA, M_WAITOK);
661
662         crp = crypto_getreq((cse->txform != NULL) + (cse->thash != NULL));
663         if (crp == NULL) {
664                 error = ENOMEM;
665                 goto bail;
666         }
667
668         if (cse->thash) {
669                 crda = crp->crp_desc;
670                 if (cse->txform)
671                         crde = crda->crd_next;
672         } else {
673                 if (cse->txform)
674                         crde = crp->crp_desc;
675                 else {
676                         error = EINVAL;
677                         goto bail;
678                 }
679         }
680
681         if ((error = copyin(cop->src, cse->uio.uio_iov[0].iov_base, cop->len)))
682                 goto bail;
683
684         if (crda) {
685                 crda->crd_skip = 0;
686                 crda->crd_len = cop->len;
687                 crda->crd_inject = cop->len;
688
689                 crda->crd_alg = cse->mac;
690                 crda->crd_key = cse->mackey;
691                 crda->crd_klen = cse->mackeylen * 8;
692         }
693
694         if (crde) {
695                 if (cop->op == COP_ENCRYPT)
696                         crde->crd_flags |= CRD_F_ENCRYPT;
697                 else
698                         crde->crd_flags &= ~CRD_F_ENCRYPT;
699                 crde->crd_len = cop->len;
700                 crde->crd_inject = 0;
701
702                 crde->crd_alg = cse->cipher;
703                 crde->crd_key = cse->key;
704                 crde->crd_klen = cse->keylen * 8;
705         }
706
707         crp->crp_ilen = cop->len;
708         crp->crp_flags = CRYPTO_F_IOV | CRYPTO_F_CBIMM
709                        | (cop->flags & COP_F_BATCH);
710         crp->crp_buf = (caddr_t)&cse->uio;
711         crp->crp_callback = (int (*) (struct cryptop *)) cryptodev_cb;
712         crp->crp_sid = cse->sid;
713         crp->crp_opaque = (void *)cse;
714
715         if (cop->iv) {
716                 if (crde == NULL) {
717                         error = EINVAL;
718                         goto bail;
719                 }
720                 if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */
721                         error = EINVAL;
722                         goto bail;
723                 }
724                 if ((error = copyin(cop->iv, cse->tmp_iv, cse->txform->blocksize)))
725                         goto bail;
726                 bcopy(cse->tmp_iv, crde->crd_iv, cse->txform->blocksize);
727                 crde->crd_flags |= CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT;
728                 crde->crd_skip = 0;
729         } else if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */
730                 crde->crd_skip = 0;
731         } else if (crde) {
732                 crde->crd_flags |= CRD_F_IV_PRESENT;
733                 crde->crd_skip = cse->txform->blocksize;
734                 crde->crd_len -= cse->txform->blocksize;
735         }
736
737         if (cop->mac && crda == NULL) {
738                 error = EINVAL;
739                 goto bail;
740         }
741
742 again:
743         /*
744          * Let the dispatch run unlocked, then, interlock against the
745          * callback before checking if the operation completed and going
746          * to sleep.  This insures drivers don't inherit our lock which
747          * results in a lock order reversal between crypto_dispatch forced
748          * entry and the crypto_done callback into us.
749          */
750         error = crypto_dispatch(crp);
751         mtx_lock(&cse->lock);
752         if (error == 0 && (crp->crp_flags & CRYPTO_F_DONE) == 0)
753                 error = msleep(crp, &cse->lock, PWAIT, "crydev", 0);
754         mtx_unlock(&cse->lock);
755
756         if (error != 0)
757                 goto bail;
758
759         if (crp->crp_etype == EAGAIN) {
760                 crp->crp_etype = 0;
761                 crp->crp_flags &= ~CRYPTO_F_DONE;
762                 goto again;
763         }
764
765         if (crp->crp_etype != 0) {
766                 error = crp->crp_etype;
767                 goto bail;
768         }
769
770         if (cse->error) {
771                 error = cse->error;
772                 goto bail;
773         }
774
775         if (cop->dst &&
776             (error = copyout(cse->uio.uio_iov[0].iov_base, cop->dst, cop->len)))
777                 goto bail;
778
779         if (cop->mac &&
780             (error = copyout((caddr_t)cse->uio.uio_iov[0].iov_base + cop->len,
781             cop->mac, cse->thash->hashsize)))
782                 goto bail;
783
784 bail:
785         if (crp)
786                 crypto_freereq(crp);
787         if (cse->uio.uio_iov[0].iov_base)
788                 free(cse->uio.uio_iov[0].iov_base, M_XDATA);
789
790         return (error);
791 }
792
793 static int
794 cryptodev_cb(void *op)
795 {
796         struct cryptop *crp = (struct cryptop *) op;
797         struct csession *cse = (struct csession *)crp->crp_opaque;
798
799         mtx_lock(&cse->lock);
800         cse->error = crp->crp_etype;
801         wakeup_one(crp);
802         mtx_unlock(&cse->lock);
803         return (0);
804 }
805
806 static int
807 cryptodevkey_cb(void *op)
808 {
809         struct cryptkop *krp = (struct cryptkop *) op;
810
811         wakeup_one(krp);
812         return (0);
813 }
814
815 static int
816 cryptodev_key(struct crypt_kop *kop)
817 {
818         struct cryptkop *krp = NULL;
819         int error = EINVAL;
820         int in, out, size, i;
821
822         if (kop->crk_iparams + kop->crk_oparams > CRK_MAXPARAM) {
823                 return (EFBIG);
824         }
825
826         in = kop->crk_iparams;
827         out = kop->crk_oparams;
828         switch (kop->crk_op) {
829         case CRK_MOD_EXP:
830                 if (in == 3 && out == 1)
831                         break;
832                 return (EINVAL);
833         case CRK_MOD_EXP_CRT:
834                 if (in == 6 && out == 1)
835                         break;
836                 return (EINVAL);
837         case CRK_DSA_SIGN:
838                 if (in == 5 && out == 2)
839                         break;
840                 return (EINVAL);
841         case CRK_DSA_VERIFY:
842                 if (in == 7 && out == 0)
843                         break;
844                 return (EINVAL);
845         case CRK_DH_COMPUTE_KEY:
846                 if (in == 3 && out == 1)
847                         break;
848                 return (EINVAL);
849         default:
850                 return (EINVAL);
851         }
852
853         krp = (struct cryptkop *)malloc(sizeof *krp, M_XDATA, M_WAITOK|M_ZERO);
854         if (!krp)
855                 return (ENOMEM);
856         krp->krp_op = kop->crk_op;
857         krp->krp_status = kop->crk_status;
858         krp->krp_iparams = kop->crk_iparams;
859         krp->krp_oparams = kop->crk_oparams;
860         krp->krp_crid = kop->crk_crid;
861         krp->krp_status = 0;
862         krp->krp_callback = (int (*) (struct cryptkop *)) cryptodevkey_cb;
863
864         for (i = 0; i < CRK_MAXPARAM; i++) {
865                 if (kop->crk_param[i].crp_nbits > 65536)
866                         /* Limit is the same as in OpenBSD */
867                         goto fail;
868                 krp->krp_param[i].crp_nbits = kop->crk_param[i].crp_nbits;
869         }
870         for (i = 0; i < krp->krp_iparams + krp->krp_oparams; i++) {
871                 size = (krp->krp_param[i].crp_nbits + 7) / 8;
872                 if (size == 0)
873                         continue;
874                 krp->krp_param[i].crp_p = malloc(size, M_XDATA, M_WAITOK);
875                 if (i >= krp->krp_iparams)
876                         continue;
877                 error = copyin(kop->crk_param[i].crp_p, krp->krp_param[i].crp_p, size);
878                 if (error)
879                         goto fail;
880         }
881
882         error = crypto_kdispatch(krp);
883         if (error)
884                 goto fail;
885         error = tsleep(krp, PSOCK, "crydev", 0);
886         if (error) {
887                 /* XXX can this happen?  if so, how do we recover? */
888                 goto fail;
889         }
890         
891         kop->crk_crid = krp->krp_crid;          /* device that did the work */
892         if (krp->krp_status != 0) {
893                 error = krp->krp_status;
894                 goto fail;
895         }
896
897         for (i = krp->krp_iparams; i < krp->krp_iparams + krp->krp_oparams; i++) {
898                 size = (krp->krp_param[i].crp_nbits + 7) / 8;
899                 if (size == 0)
900                         continue;
901                 error = copyout(krp->krp_param[i].crp_p, kop->crk_param[i].crp_p, size);
902                 if (error)
903                         goto fail;
904         }
905
906 fail:
907         if (krp) {
908                 kop->crk_status = krp->krp_status;
909                 for (i = 0; i < CRK_MAXPARAM; i++) {
910                         if (krp->krp_param[i].crp_p)
911                                 free(krp->krp_param[i].crp_p, M_XDATA);
912                 }
913                 free(krp, M_XDATA);
914         }
915         return (error);
916 }
917
918 static int
919 cryptodev_find(struct crypt_find_op *find)
920 {
921         device_t dev;
922
923         if (find->crid != -1) {
924                 dev = crypto_find_device_byhid(find->crid);
925                 if (dev == NULL)
926                         return (ENOENT);
927                 strlcpy(find->name, device_get_nameunit(dev),
928                     sizeof(find->name));
929         } else {
930                 find->crid = crypto_find_driver(find->name);
931                 if (find->crid == -1)
932                         return (ENOENT);
933         }
934         return (0);
935 }
936
937 /* ARGSUSED */
938 static int
939 cryptof_stat(
940         struct file *fp,
941         struct stat *sb,
942         struct ucred *active_cred,
943         struct thread *td)
944 {
945
946         return (EOPNOTSUPP);
947 }
948
949 /* ARGSUSED */
950 static int
951 cryptof_close(struct file *fp, struct thread *td)
952 {
953         struct fcrypt *fcr = fp->f_data;
954         struct csession *cse;
955
956         while ((cse = TAILQ_FIRST(&fcr->csessions))) {
957                 TAILQ_REMOVE(&fcr->csessions, cse, next);
958                 (void)csefree(cse);
959         }
960         free(fcr, M_XDATA);
961         fp->f_data = NULL;
962         return 0;
963 }
964
965 static int
966 cryptof_fill_kinfo(struct file *fp, struct kinfo_file *kif, struct filedesc *fdp)
967 {
968
969         kif->kf_type = KF_TYPE_CRYPTO;
970         return (0);
971 }
972
973 static struct csession *
974 csefind(struct fcrypt *fcr, u_int ses)
975 {
976         struct csession *cse;
977
978         TAILQ_FOREACH(cse, &fcr->csessions, next)
979                 if (cse->ses == ses)
980                         return (cse);
981         return (NULL);
982 }
983
984 static int
985 csedelete(struct fcrypt *fcr, struct csession *cse_del)
986 {
987         struct csession *cse;
988
989         TAILQ_FOREACH(cse, &fcr->csessions, next) {
990                 if (cse == cse_del) {
991                         TAILQ_REMOVE(&fcr->csessions, cse, next);
992                         return (1);
993                 }
994         }
995         return (0);
996 }
997         
998 static struct csession *
999 cseadd(struct fcrypt *fcr, struct csession *cse)
1000 {
1001         TAILQ_INSERT_TAIL(&fcr->csessions, cse, next);
1002         cse->ses = fcr->sesn++;
1003         return (cse);
1004 }
1005
1006 struct csession *
1007 csecreate(struct fcrypt *fcr, u_int64_t sid, caddr_t key, u_int64_t keylen,
1008     caddr_t mackey, u_int64_t mackeylen, u_int32_t cipher, u_int32_t mac,
1009     struct enc_xform *txform, struct auth_hash *thash)
1010 {
1011         struct csession *cse;
1012
1013         cse = malloc(sizeof(struct csession), M_XDATA, M_NOWAIT | M_ZERO);
1014         if (cse == NULL)
1015                 return NULL;
1016         mtx_init(&cse->lock, "cryptodev", "crypto session lock", MTX_DEF);
1017         cse->key = key;
1018         cse->keylen = keylen/8;
1019         cse->mackey = mackey;
1020         cse->mackeylen = mackeylen/8;
1021         cse->sid = sid;
1022         cse->cipher = cipher;
1023         cse->mac = mac;
1024         cse->txform = txform;
1025         cse->thash = thash;
1026         cseadd(fcr, cse);
1027         return (cse);
1028 }
1029
1030 static int
1031 csefree(struct csession *cse)
1032 {
1033         int error;
1034
1035         error = crypto_freesession(cse->sid);
1036         mtx_destroy(&cse->lock);
1037         if (cse->key)
1038                 free(cse->key, M_XDATA);
1039         if (cse->mackey)
1040                 free(cse->mackey, M_XDATA);
1041         free(cse, M_XDATA);
1042         return (error);
1043 }
1044
1045 static int
1046 cryptoopen(struct cdev *dev, int oflags, int devtype, struct thread *td)
1047 {
1048         return (0);
1049 }
1050
1051 static int
1052 cryptoread(struct cdev *dev, struct uio *uio, int ioflag)
1053 {
1054         return (EIO);
1055 }
1056
1057 static int
1058 cryptowrite(struct cdev *dev, struct uio *uio, int ioflag)
1059 {
1060         return (EIO);
1061 }
1062
1063 static int
1064 cryptoioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td)
1065 {
1066         struct file *f;
1067         struct fcrypt *fcr;
1068         int fd, error;
1069
1070         switch (cmd) {
1071         case CRIOGET:
1072                 fcr = malloc(sizeof(struct fcrypt), M_XDATA, M_WAITOK);
1073                 TAILQ_INIT(&fcr->csessions);
1074                 fcr->sesn = 0;
1075
1076                 error = falloc(td, &f, &fd, 0);
1077
1078                 if (error) {
1079                         free(fcr, M_XDATA);
1080                         return (error);
1081                 }
1082                 /* falloc automatically provides an extra reference to 'f'. */
1083                 finit(f, FREAD | FWRITE, DTYPE_CRYPTO, fcr, &cryptofops);
1084                 *(u_int32_t *)data = fd;
1085                 fdrop(f, td);
1086                 break;
1087         case CRIOFINDDEV:
1088                 error = cryptodev_find((struct crypt_find_op *)data);
1089                 break;
1090         case CRIOASYMFEAT:
1091                 error = crypto_getfeat((int *)data);
1092                 break;
1093         default:
1094                 error = EINVAL;
1095                 break;
1096         }
1097         return (error);
1098 }
1099
1100 static struct cdevsw crypto_cdevsw = {
1101         .d_version =    D_VERSION,
1102         .d_flags =      D_NEEDGIANT,
1103         .d_open =       cryptoopen,
1104         .d_read =       cryptoread,
1105         .d_write =      cryptowrite,
1106         .d_ioctl =      cryptoioctl,
1107         .d_name =       "crypto",
1108 };
1109 static struct cdev *crypto_dev;
1110
1111 /*
1112  * Initialization code, both for static and dynamic loading.
1113  */
1114 static int
1115 cryptodev_modevent(module_t mod, int type, void *unused)
1116 {
1117         switch (type) {
1118         case MOD_LOAD:
1119                 if (bootverbose)
1120                         printf("crypto: <crypto device>\n");
1121                 crypto_dev = make_dev(&crypto_cdevsw, 0, 
1122                                       UID_ROOT, GID_WHEEL, 0666,
1123                                       "crypto");
1124                 return 0;
1125         case MOD_UNLOAD:
1126                 /*XXX disallow if active sessions */
1127                 destroy_dev(crypto_dev);
1128                 return 0;
1129         }
1130         return EINVAL;
1131 }
1132
1133 static moduledata_t cryptodev_mod = {
1134         "cryptodev",
1135         cryptodev_modevent,
1136         0
1137 };
1138 MODULE_VERSION(cryptodev, 1);
1139 DECLARE_MODULE(cryptodev, cryptodev_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
1140 MODULE_DEPEND(cryptodev, crypto, 1, 1, 1);
1141 MODULE_DEPEND(cryptodev, zlib, 1, 1, 1);