source: rtems-libbsd/freebsd/sys/opencrypto/cryptodev.c @ 6600368

5-freebsd-12
Last change on this file since 6600368 was 6600368, checked in by Sebastian Huber <sebastian.huber@…>, on Mar 27, 2018 at 11:25:16 AM

CRYPTO(4): Import from FreeBSD

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