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

5-freebsd-12
Last change on this file since 8189ea8 was 8189ea8, checked in by Sebastian Huber <sebastian.huber@…>, on Mar 27, 2018 at 12:42:31 PM

CRYPTO(4): Port to RTEMS

  • Property mode set to 100644
File size: 33.4 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
298#ifndef __rtems__
299static  int cryptof_ioctl(struct file *, u_long, void *,
300                    struct ucred *, struct thread *);
301static  int cryptof_stat(struct file *, struct stat *,
302                    struct ucred *, struct thread *);
303static  int cryptof_close(struct file *, struct thread *);
304static  int cryptof_fill_kinfo(struct file *, struct kinfo_file *,
305                    struct filedesc *);
306
307static struct fileops cryptofops = {
308    .fo_read = invfo_rdwr,
309    .fo_write = invfo_rdwr,
310    .fo_truncate = invfo_truncate,
311    .fo_ioctl = cryptof_ioctl,
312    .fo_poll = invfo_poll,
313    .fo_kqfilter = invfo_kqfilter,
314    .fo_stat = cryptof_stat,
315    .fo_close = cryptof_close,
316    .fo_chmod = invfo_chmod,
317    .fo_chown = invfo_chown,
318    .fo_sendfile = invfo_sendfile,
319    .fo_fill_kinfo = cryptof_fill_kinfo,
320};
321#else /* __rtems__ */
322static const rtems_filesystem_file_handlers_r cryptofops;
323#endif /* __rtems__ */
324
325static struct csession *csefind(struct fcrypt *, u_int);
326static int csedelete(struct fcrypt *, struct csession *);
327static struct csession *cseadd(struct fcrypt *, struct csession *);
328static struct csession *csecreate(struct fcrypt *, u_int64_t, caddr_t,
329    u_int64_t, caddr_t, u_int64_t, u_int32_t, u_int32_t, struct enc_xform *,
330    struct auth_hash *);
331static int csefree(struct csession *);
332
333static  int cryptodev_op(struct csession *, struct crypt_op *,
334                        struct ucred *, struct thread *td);
335static  int cryptodev_aead(struct csession *, struct crypt_aead *,
336                        struct ucred *, struct thread *);
337static  int cryptodev_key(struct crypt_kop *);
338static  int cryptodev_find(struct crypt_find_op *);
339
340/*
341 * Check a crypto identifier to see if it requested
342 * a software device/driver.  This can be done either
343 * by device name/class or through search constraints.
344 */
345static int
346checkforsoftware(int *cridp)
347{
348        int crid;
349
350        crid = *cridp;
351
352        if (!crypto_devallowsoft) {
353                if (crid & CRYPTOCAP_F_SOFTWARE) {
354                        if (crid & CRYPTOCAP_F_HARDWARE) {
355                                *cridp = CRYPTOCAP_F_HARDWARE;
356                                return 0;
357                        }
358                        return EINVAL;
359                }
360                if ((crid & CRYPTOCAP_F_HARDWARE) == 0 &&
361                    (crypto_getcaps(crid) & CRYPTOCAP_F_HARDWARE) == 0)
362                        return EINVAL;
363        }
364        return 0;
365}
366
367/* ARGSUSED */
368static int
369cryptof_ioctl(
370        struct file *fp,
371        u_long cmd,
372        void *data,
373        struct ucred *active_cred,
374        struct thread *td)
375{
376#define SES2(p) ((struct session2_op *)p)
377        struct cryptoini cria, crie;
378        struct fcrypt *fcr = fp->f_data;
379        struct csession *cse;
380        struct session_op *sop;
381        struct crypt_op *cop;
382        struct crypt_aead *caead;
383        struct enc_xform *txform = NULL;
384        struct auth_hash *thash = NULL;
385        struct crypt_kop *kop;
386        u_int64_t sid;
387        u_int32_t ses;
388        int error = 0, crid;
389#ifdef COMPAT_FREEBSD32
390        struct session2_op sopc;
391        struct crypt_op copc;
392        struct crypt_kop kopc;
393#endif
394
395        switch (cmd) {
396        case CIOCGSESSION:
397        case CIOCGSESSION2:
398#ifdef COMPAT_FREEBSD32
399        case CIOCGSESSION32:
400        case CIOCGSESSION232:
401                if (cmd == CIOCGSESSION32) {
402                        session_op_from_32(data, (struct session_op *)&sopc);
403                        sop = (struct session_op *)&sopc;
404                } else if (cmd == CIOCGSESSION232) {
405                        session2_op_from_32(data, &sopc);
406                        sop = (struct session_op *)&sopc;
407                } else
408#endif
409                        sop = (struct session_op *)data;
410                switch (sop->cipher) {
411                case 0:
412                        break;
413                case CRYPTO_DES_CBC:
414                        txform = &enc_xform_des;
415                        break;
416                case CRYPTO_3DES_CBC:
417                        txform = &enc_xform_3des;
418                        break;
419                case CRYPTO_BLF_CBC:
420                        txform = &enc_xform_blf;
421                        break;
422                case CRYPTO_CAST_CBC:
423                        txform = &enc_xform_cast5;
424                        break;
425                case CRYPTO_SKIPJACK_CBC:
426                        txform = &enc_xform_skipjack;
427                        break;
428                case CRYPTO_AES_CBC:
429                        txform = &enc_xform_rijndael128;
430                        break;
431                case CRYPTO_AES_XTS:
432                        txform = &enc_xform_aes_xts;
433                        break;
434                case CRYPTO_NULL_CBC:
435                        txform = &enc_xform_null;
436                        break;
437                case CRYPTO_ARC4:
438                        txform = &enc_xform_arc4;
439                        break;
440                case CRYPTO_CAMELLIA_CBC:
441                        txform = &enc_xform_camellia;
442                        break;
443                case CRYPTO_AES_ICM:
444                        txform = &enc_xform_aes_icm;
445                        break;
446                case CRYPTO_AES_NIST_GCM_16:
447                        txform = &enc_xform_aes_nist_gcm;
448                        break;
449
450                default:
451                        CRYPTDEB("invalid cipher");
452                        return (EINVAL);
453                }
454
455                switch (sop->mac) {
456                case 0:
457                        break;
458                case CRYPTO_MD5_HMAC:
459                        thash = &auth_hash_hmac_md5;
460                        break;
461                case CRYPTO_SHA1_HMAC:
462                        thash = &auth_hash_hmac_sha1;
463                        break;
464                case CRYPTO_SHA2_256_HMAC:
465                        thash = &auth_hash_hmac_sha2_256;
466                        break;
467                case CRYPTO_SHA2_384_HMAC:
468                        thash = &auth_hash_hmac_sha2_384;
469                        break;
470                case CRYPTO_SHA2_512_HMAC:
471                        thash = &auth_hash_hmac_sha2_512;
472                        break;
473                case CRYPTO_RIPEMD160_HMAC:
474                        thash = &auth_hash_hmac_ripemd_160;
475                        break;
476                case CRYPTO_AES_128_NIST_GMAC:
477                        thash = &auth_hash_nist_gmac_aes_128;
478                        break;
479                case CRYPTO_AES_192_NIST_GMAC:
480                        thash = &auth_hash_nist_gmac_aes_192;
481                        break;
482                case CRYPTO_AES_256_NIST_GMAC:
483                        thash = &auth_hash_nist_gmac_aes_256;
484                        break;
485
486#ifdef notdef
487                case CRYPTO_MD5:
488                        thash = &auth_hash_md5;
489                        break;
490                case CRYPTO_SHA1:
491                        thash = &auth_hash_sha1;
492                        break;
493#endif
494                case CRYPTO_NULL_HMAC:
495                        thash = &auth_hash_null;
496                        break;
497                default:
498                        CRYPTDEB("invalid mac");
499                        return (EINVAL);
500                }
501
502                bzero(&crie, sizeof(crie));
503                bzero(&cria, sizeof(cria));
504
505                if (txform) {
506                        crie.cri_alg = txform->type;
507                        crie.cri_klen = sop->keylen * 8;
508                        if (sop->keylen > txform->maxkey ||
509                            sop->keylen < txform->minkey) {
510                                CRYPTDEB("invalid cipher parameters");
511                                error = EINVAL;
512                                goto bail;
513                        }
514
515                        crie.cri_key = malloc(crie.cri_klen / 8,
516                            M_XDATA, M_WAITOK);
517                        if ((error = copyin(sop->key, crie.cri_key,
518                            crie.cri_klen / 8))) {
519                                CRYPTDEB("invalid key");
520                                goto bail;
521                        }
522                        if (thash)
523                                crie.cri_next = &cria;
524                }
525
526                if (thash) {
527                        cria.cri_alg = thash->type;
528                        cria.cri_klen = sop->mackeylen * 8;
529                        if (sop->mackeylen != thash->keysize) {
530                                CRYPTDEB("invalid mac key length");
531                                error = EINVAL;
532                                goto bail;
533                        }
534
535                        if (cria.cri_klen) {
536                                cria.cri_key = malloc(cria.cri_klen / 8,
537                                    M_XDATA, M_WAITOK);
538                                if ((error = copyin(sop->mackey, cria.cri_key,
539                                    cria.cri_klen / 8))) {
540                                        CRYPTDEB("invalid mac key");
541                                        goto bail;
542                                }
543                        }
544                }
545
546                /* NB: CIOCGSESSION2 has the crid */
547                if (cmd == CIOCGSESSION2
548#ifdef COMPAT_FREEBSD32
549                    || cmd == CIOCGSESSION232
550#endif
551                        ) {
552                        crid = SES2(sop)->crid;
553                        error = checkforsoftware(&crid);
554                        if (error) {
555                                CRYPTDEB("checkforsoftware");
556                                goto bail;
557                        }
558                } else
559                        crid = CRYPTOCAP_F_HARDWARE;
560                error = crypto_newsession(&sid, (txform ? &crie : &cria), crid);
561                if (error) {
562                        CRYPTDEB("crypto_newsession");
563                        goto bail;
564                }
565
566                cse = csecreate(fcr, sid, crie.cri_key, crie.cri_klen,
567                    cria.cri_key, cria.cri_klen, sop->cipher, sop->mac, txform,
568                    thash);
569
570                if (cse == NULL) {
571                        crypto_freesession(sid);
572                        error = EINVAL;
573                        CRYPTDEB("csecreate");
574                        goto bail;
575                }
576                sop->ses = cse->ses;
577                if (cmd == CIOCGSESSION2
578#ifdef COMPAT_FREEBSD32
579                    || cmd == CIOCGSESSION232
580#endif
581                    ) {
582                        /* return hardware/driver id */
583                        SES2(sop)->crid = CRYPTO_SESID2HID(cse->sid);
584                }
585bail:
586                if (error) {
587                        if (crie.cri_key)
588                                free(crie.cri_key, M_XDATA);
589                        if (cria.cri_key)
590                                free(cria.cri_key, M_XDATA);
591                }
592#ifdef COMPAT_FREEBSD32
593                else {
594                        if (cmd == CIOCGSESSION32)
595                                session_op_to_32(sop, data);
596                        else if (cmd == CIOCGSESSION232)
597                                session2_op_to_32((struct session2_op *)sop,
598                                    data);
599                }
600#endif
601                break;
602        case CIOCFSESSION:
603                ses = *(u_int32_t *)data;
604                cse = csefind(fcr, ses);
605                if (cse == NULL)
606                        return (EINVAL);
607                csedelete(fcr, cse);
608                error = csefree(cse);
609                break;
610        case CIOCCRYPT:
611#ifdef COMPAT_FREEBSD32
612        case CIOCCRYPT32:
613                if (cmd == CIOCCRYPT32) {
614                        cop = &copc;
615                        crypt_op_from_32(data, cop);
616                } else
617#endif
618                        cop = (struct crypt_op *)data;
619                cse = csefind(fcr, cop->ses);
620                if (cse == NULL) {
621                        SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
622                        return (EINVAL);
623                }
624                error = cryptodev_op(cse, cop, active_cred, td);
625#ifdef COMPAT_FREEBSD32
626                if (error == 0 && cmd == CIOCCRYPT32)
627                        crypt_op_to_32(cop, data);
628#endif
629                break;
630        case CIOCKEY:
631        case CIOCKEY2:
632#ifdef COMPAT_FREEBSD32
633        case CIOCKEY32:
634        case CIOCKEY232:
635#endif
636                if (!crypto_userasymcrypto)
637                        return (EPERM);         /* XXX compat? */
638#ifdef COMPAT_FREEBSD32
639                if (cmd == CIOCKEY32 || cmd == CIOCKEY232) {
640                        kop = &kopc;
641                        crypt_kop_from_32(data, kop);
642                } else
643#endif
644                        kop = (struct crypt_kop *)data;
645                if (cmd == CIOCKEY
646#ifdef COMPAT_FREEBSD32
647                    || cmd == CIOCKEY32
648#endif
649                    ) {
650                        /* NB: crypto core enforces s/w driver use */
651                        kop->crk_crid =
652                            CRYPTOCAP_F_HARDWARE | CRYPTOCAP_F_SOFTWARE;
653                }
654                mtx_lock(&Giant);
655                error = cryptodev_key(kop);
656                mtx_unlock(&Giant);
657#ifdef COMPAT_FREEBSD32
658                if (cmd == CIOCKEY32 || cmd == CIOCKEY232)
659                        crypt_kop_to_32(kop, data);
660#endif
661                break;
662        case CIOCASYMFEAT:
663                if (!crypto_userasymcrypto) {
664                        /*
665                         * NB: if user asym crypto operations are
666                         * not permitted return "no algorithms"
667                         * so well-behaved applications will just
668                         * fallback to doing them in software.
669                         */
670                        *(int *)data = 0;
671                } else
672                        error = crypto_getfeat((int *)data);
673                break;
674        case CIOCFINDDEV:
675                error = cryptodev_find((struct crypt_find_op *)data);
676                break;
677        case CIOCCRYPTAEAD:
678                caead = (struct crypt_aead *)data;
679                cse = csefind(fcr, caead->ses);
680                if (cse == NULL)
681                        return (EINVAL);
682                error = cryptodev_aead(cse, caead, active_cred, td);
683                break;
684        default:
685                error = EINVAL;
686                break;
687        }
688        return (error);
689#undef SES2
690}
691#ifdef __rtems__
692static int
693rtems_bsd_cryptof_ioctl(rtems_libio_t *iop, ioctl_command_t request,
694    void *buffer)
695{
696        struct thread *td;
697        int error;
698
699        td = rtems_bsd_get_curthread_or_null();
700        if (td != NULL) {
701                struct file *fp;
702
703                fp = rtems_bsd_iop_to_fp(iop);
704                error = cryptof_ioctl(fp, request, buffer, NULL, td);
705        } else {
706                error = ENOMEM;
707        }
708
709        return (rtems_bsd_error_to_status_and_errno(error));
710}
711#endif /* __rtems__ */
712
713static int cryptodev_cb(void *);
714
715
716static int
717cryptodev_op(
718        struct csession *cse,
719        struct crypt_op *cop,
720        struct ucred *active_cred,
721        struct thread *td)
722{
723        struct cryptop *crp = NULL;
724        struct cryptodesc *crde = NULL, *crda = NULL;
725        int error;
726
727        if (cop->len > 256*1024-4) {
728                SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
729                return (E2BIG);
730        }
731
732        if (cse->txform) {
733                if (cop->len == 0 || (cop->len % cse->txform->blocksize) != 0) {
734                        SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
735                        return (EINVAL);
736                }
737        }
738
739        cse->uio.uio_iov = &cse->iovec;
740        cse->uio.uio_iovcnt = 1;
741        cse->uio.uio_offset = 0;
742        cse->uio.uio_resid = cop->len;
743        cse->uio.uio_segflg = UIO_SYSSPACE;
744        cse->uio.uio_rw = UIO_WRITE;
745        cse->uio.uio_td = td;
746        cse->uio.uio_iov[0].iov_len = cop->len;
747        if (cse->thash) {
748                cse->uio.uio_iov[0].iov_len += cse->thash->hashsize;
749                cse->uio.uio_resid += cse->thash->hashsize;
750        }
751        cse->uio.uio_iov[0].iov_base = malloc(cse->uio.uio_iov[0].iov_len,
752            M_XDATA, M_WAITOK);
753
754        crp = crypto_getreq((cse->txform != NULL) + (cse->thash != NULL));
755        if (crp == NULL) {
756                SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
757                error = ENOMEM;
758                goto bail;
759        }
760
761        if (cse->thash) {
762                crda = crp->crp_desc;
763                if (cse->txform)
764                        crde = crda->crd_next;
765        } else {
766                if (cse->txform)
767                        crde = crp->crp_desc;
768                else {
769                        SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
770                        error = EINVAL;
771                        goto bail;
772                }
773        }
774
775        if ((error = copyin(cop->src, cse->uio.uio_iov[0].iov_base,
776            cop->len))) {
777                SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
778                goto bail;
779        }
780
781        if (crda) {
782                crda->crd_skip = 0;
783                crda->crd_len = cop->len;
784                crda->crd_inject = cop->len;
785
786                crda->crd_alg = cse->mac;
787                crda->crd_key = cse->mackey;
788                crda->crd_klen = cse->mackeylen * 8;
789        }
790
791        if (crde) {
792                if (cop->op == COP_ENCRYPT)
793                        crde->crd_flags |= CRD_F_ENCRYPT;
794                else
795                        crde->crd_flags &= ~CRD_F_ENCRYPT;
796                crde->crd_len = cop->len;
797                crde->crd_inject = 0;
798
799                crde->crd_alg = cse->cipher;
800                crde->crd_key = cse->key;
801                crde->crd_klen = cse->keylen * 8;
802        }
803
804        crp->crp_ilen = cop->len;
805        crp->crp_flags = CRYPTO_F_IOV | CRYPTO_F_CBIMM
806                       | (cop->flags & COP_F_BATCH);
807        crp->crp_buf = (caddr_t)&cse->uio;
808        crp->crp_callback = (int (*) (struct cryptop *)) cryptodev_cb;
809        crp->crp_sid = cse->sid;
810        crp->crp_opaque = (void *)cse;
811
812        if (cop->iv) {
813                if (crde == NULL) {
814                        SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
815                        error = EINVAL;
816                        goto bail;
817                }
818                if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */
819                        SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
820                        error = EINVAL;
821                        goto bail;
822                }
823                if ((error = copyin(cop->iv, cse->tmp_iv,
824                    cse->txform->blocksize))) {
825                        SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
826                        goto bail;
827                }
828                bcopy(cse->tmp_iv, crde->crd_iv, cse->txform->blocksize);
829                crde->crd_flags |= CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT;
830                crde->crd_skip = 0;
831        } else if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */
832                crde->crd_skip = 0;
833        } else if (crde) {
834                crde->crd_flags |= CRD_F_IV_PRESENT;
835                crde->crd_skip = cse->txform->blocksize;
836                crde->crd_len -= cse->txform->blocksize;
837        }
838
839        if (cop->mac && crda == NULL) {
840                SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
841                error = EINVAL;
842                goto bail;
843        }
844
845again:
846        /*
847         * Let the dispatch run unlocked, then, interlock against the
848         * callback before checking if the operation completed and going
849         * to sleep.  This insures drivers don't inherit our lock which
850         * results in a lock order reversal between crypto_dispatch forced
851         * entry and the crypto_done callback into us.
852         */
853        error = crypto_dispatch(crp);
854        mtx_lock(&cse->lock);
855        if (error == 0 && (crp->crp_flags & CRYPTO_F_DONE) == 0)
856                error = msleep(crp, &cse->lock, PWAIT, "crydev", 0);
857        mtx_unlock(&cse->lock);
858
859        if (error != 0) {
860                SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
861                goto bail;
862        }
863
864        if (crp->crp_etype == EAGAIN) {
865                crp->crp_etype = 0;
866                crp->crp_flags &= ~CRYPTO_F_DONE;
867                goto again;
868        }
869
870        if (crp->crp_etype != 0) {
871                SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
872                error = crp->crp_etype;
873                goto bail;
874        }
875
876        if (cse->error) {
877                SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
878                error = cse->error;
879                goto bail;
880        }
881
882        if (cop->dst &&
883            (error = copyout(cse->uio.uio_iov[0].iov_base, cop->dst,
884            cop->len))) {
885                SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
886                goto bail;
887        }
888
889        if (cop->mac &&
890            (error = copyout((caddr_t)cse->uio.uio_iov[0].iov_base + cop->len,
891            cop->mac, cse->thash->hashsize))) {
892                SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
893                goto bail;
894        }
895
896bail:
897        if (crp)
898                crypto_freereq(crp);
899        if (cse->uio.uio_iov[0].iov_base)
900                free(cse->uio.uio_iov[0].iov_base, M_XDATA);
901
902        return (error);
903}
904
905static int
906cryptodev_aead(
907        struct csession *cse,
908        struct crypt_aead *caead,
909        struct ucred *active_cred,
910        struct thread *td)
911{
912        struct uio *uio;
913        struct cryptop *crp = NULL;
914        struct cryptodesc *crde = NULL, *crda = NULL;
915        int error;
916
917        if (caead->len > 256*1024-4 || caead->aadlen > 256*1024-4)
918                return (E2BIG);
919
920        if (cse->txform == NULL || cse->thash == NULL || caead->tag == NULL ||
921            (caead->len % cse->txform->blocksize) != 0)
922                return (EINVAL);
923
924        uio = &cse->uio;
925        uio->uio_iov = &cse->iovec;
926        uio->uio_iovcnt = 1;
927        uio->uio_offset = 0;
928        uio->uio_resid = caead->len + caead->aadlen + cse->thash->hashsize;
929        uio->uio_segflg = UIO_SYSSPACE;
930        uio->uio_rw = UIO_WRITE;
931        uio->uio_td = td;
932        uio->uio_iov[0].iov_len = uio->uio_resid;
933
934        uio->uio_iov[0].iov_base = malloc(uio->uio_iov[0].iov_len,
935            M_XDATA, M_WAITOK);
936
937        crp = crypto_getreq(2);
938        if (crp == NULL) {
939                error = ENOMEM;
940                goto bail;
941        }
942
943        crda = crp->crp_desc;
944        crde = crda->crd_next;
945
946        if ((error = copyin(caead->src, cse->uio.uio_iov[0].iov_base,
947            caead->len)))
948                goto bail;
949
950        if ((error = copyin(caead->aad, (char *)cse->uio.uio_iov[0].iov_base +
951            caead->len, caead->aadlen)))
952                goto bail;
953
954        crda->crd_skip = caead->len;
955        crda->crd_len = caead->aadlen;
956        crda->crd_inject = caead->len + caead->aadlen;
957
958        crda->crd_alg = cse->mac;
959        crda->crd_key = cse->mackey;
960        crda->crd_klen = cse->mackeylen * 8;
961
962        if (caead->op == COP_ENCRYPT)
963                crde->crd_flags |= CRD_F_ENCRYPT;
964        else
965                crde->crd_flags &= ~CRD_F_ENCRYPT;
966        /* crde->crd_skip set below */
967        crde->crd_len = caead->len;
968        crde->crd_inject = 0;
969
970        crde->crd_alg = cse->cipher;
971        crde->crd_key = cse->key;
972        crde->crd_klen = cse->keylen * 8;
973
974        crp->crp_ilen = caead->len + caead->aadlen;
975        crp->crp_flags = CRYPTO_F_IOV | CRYPTO_F_CBIMM
976                       | (caead->flags & COP_F_BATCH);
977        crp->crp_buf = (caddr_t)&cse->uio.uio_iov;
978        crp->crp_callback = (int (*) (struct cryptop *)) cryptodev_cb;
979        crp->crp_sid = cse->sid;
980        crp->crp_opaque = (void *)cse;
981
982        if (caead->iv) {
983                if (caead->ivlen > sizeof cse->tmp_iv) {
984                        error = EINVAL;
985                        goto bail;
986                }
987
988                if ((error = copyin(caead->iv, cse->tmp_iv, caead->ivlen)))
989                        goto bail;
990                bcopy(cse->tmp_iv, crde->crd_iv, caead->ivlen);
991                crde->crd_flags |= CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT;
992                crde->crd_skip = 0;
993        } else {
994                crde->crd_flags |= CRD_F_IV_PRESENT;
995                crde->crd_skip = cse->txform->blocksize;
996                crde->crd_len -= cse->txform->blocksize;
997        }
998
999        if ((error = copyin(caead->tag, (caddr_t)cse->uio.uio_iov[0].iov_base +
1000            caead->len + caead->aadlen, cse->thash->hashsize)))
1001                goto bail;
1002again:
1003        /*
1004         * Let the dispatch run unlocked, then, interlock against the
1005         * callback before checking if the operation completed and going
1006         * to sleep.  This insures drivers don't inherit our lock which
1007         * results in a lock order reversal between crypto_dispatch forced
1008         * entry and the crypto_done callback into us.
1009         */
1010        error = crypto_dispatch(crp);
1011        mtx_lock(&cse->lock);
1012        if (error == 0 && (crp->crp_flags & CRYPTO_F_DONE) == 0)
1013                error = msleep(crp, &cse->lock, PWAIT, "crydev", 0);
1014        mtx_unlock(&cse->lock);
1015
1016        if (error != 0)
1017                goto bail;
1018
1019        if (crp->crp_etype == EAGAIN) {
1020                crp->crp_etype = 0;
1021                crp->crp_flags &= ~CRYPTO_F_DONE;
1022                goto again;
1023        }
1024
1025        if (crp->crp_etype != 0) {
1026                error = crp->crp_etype;
1027                goto bail;
1028        }
1029
1030        if (cse->error) {
1031                error = cse->error;
1032                goto bail;
1033        }
1034
1035        if (caead->dst && (error = copyout(cse->uio.uio_iov[0].iov_base,
1036            caead->dst, caead->len)))
1037                goto bail;
1038
1039        if ((error = copyout((caddr_t)cse->uio.uio_iov[0].iov_base +
1040            caead->len + caead->aadlen, caead->tag, cse->thash->hashsize)))
1041                goto bail;
1042
1043bail:
1044        crypto_freereq(crp);
1045        free(cse->uio.uio_iov[0].iov_base, M_XDATA);
1046
1047        return (error);
1048}
1049
1050static int
1051cryptodev_cb(void *op)
1052{
1053        struct cryptop *crp = (struct cryptop *) op;
1054        struct csession *cse = (struct csession *)crp->crp_opaque;
1055
1056        mtx_lock(&cse->lock);
1057        cse->error = crp->crp_etype;
1058        wakeup_one(crp);
1059        mtx_unlock(&cse->lock);
1060        return (0);
1061}
1062
1063static int
1064cryptodevkey_cb(void *op)
1065{
1066        struct cryptkop *krp = (struct cryptkop *) op;
1067
1068        wakeup_one(krp);
1069        return (0);
1070}
1071
1072static int
1073cryptodev_key(struct crypt_kop *kop)
1074{
1075        struct cryptkop *krp = NULL;
1076        int error = EINVAL;
1077        int in, out, size, i;
1078
1079        if (kop->crk_iparams + kop->crk_oparams > CRK_MAXPARAM) {
1080                return (EFBIG);
1081        }
1082
1083        in = kop->crk_iparams;
1084        out = kop->crk_oparams;
1085        switch (kop->crk_op) {
1086        case CRK_MOD_EXP:
1087                if (in == 3 && out == 1)
1088                        break;
1089                return (EINVAL);
1090        case CRK_MOD_EXP_CRT:
1091                if (in == 6 && out == 1)
1092                        break;
1093                return (EINVAL);
1094        case CRK_DSA_SIGN:
1095                if (in == 5 && out == 2)
1096                        break;
1097                return (EINVAL);
1098        case CRK_DSA_VERIFY:
1099                if (in == 7 && out == 0)
1100                        break;
1101                return (EINVAL);
1102        case CRK_DH_COMPUTE_KEY:
1103                if (in == 3 && out == 1)
1104                        break;
1105                return (EINVAL);
1106        default:
1107                return (EINVAL);
1108        }
1109
1110        krp = (struct cryptkop *)malloc(sizeof *krp, M_XDATA, M_WAITOK|M_ZERO);
1111        if (!krp)
1112                return (ENOMEM);
1113        krp->krp_op = kop->crk_op;
1114        krp->krp_status = kop->crk_status;
1115        krp->krp_iparams = kop->crk_iparams;
1116        krp->krp_oparams = kop->crk_oparams;
1117        krp->krp_crid = kop->crk_crid;
1118        krp->krp_status = 0;
1119        krp->krp_callback = (int (*) (struct cryptkop *)) cryptodevkey_cb;
1120
1121        for (i = 0; i < CRK_MAXPARAM; i++) {
1122                if (kop->crk_param[i].crp_nbits > 65536)
1123                        /* Limit is the same as in OpenBSD */
1124                        goto fail;
1125                krp->krp_param[i].crp_nbits = kop->crk_param[i].crp_nbits;
1126        }
1127        for (i = 0; i < krp->krp_iparams + krp->krp_oparams; i++) {
1128                size = (krp->krp_param[i].crp_nbits + 7) / 8;
1129                if (size == 0)
1130                        continue;
1131                krp->krp_param[i].crp_p = malloc(size, M_XDATA, M_WAITOK);
1132                if (i >= krp->krp_iparams)
1133                        continue;
1134                error = copyin(kop->crk_param[i].crp_p, krp->krp_param[i].crp_p, size);
1135                if (error)
1136                        goto fail;
1137        }
1138
1139        error = crypto_kdispatch(krp);
1140        if (error)
1141                goto fail;
1142        error = tsleep(krp, PSOCK, "crydev", 0);
1143        if (error) {
1144                /* XXX can this happen?  if so, how do we recover? */
1145                goto fail;
1146        }
1147       
1148        kop->crk_crid = krp->krp_crid;          /* device that did the work */
1149        if (krp->krp_status != 0) {
1150                error = krp->krp_status;
1151                goto fail;
1152        }
1153
1154        for (i = krp->krp_iparams; i < krp->krp_iparams + krp->krp_oparams; i++) {
1155                size = (krp->krp_param[i].crp_nbits + 7) / 8;
1156                if (size == 0)
1157                        continue;
1158                error = copyout(krp->krp_param[i].crp_p, kop->crk_param[i].crp_p, size);
1159                if (error)
1160                        goto fail;
1161        }
1162
1163fail:
1164        if (krp) {
1165                kop->crk_status = krp->krp_status;
1166                for (i = 0; i < CRK_MAXPARAM; i++) {
1167                        if (krp->krp_param[i].crp_p)
1168                                free(krp->krp_param[i].crp_p, M_XDATA);
1169                }
1170                free(krp, M_XDATA);
1171        }
1172        return (error);
1173}
1174
1175static int
1176cryptodev_find(struct crypt_find_op *find)
1177{
1178        device_t dev;
1179        size_t fnlen = sizeof find->name;
1180
1181        if (find->crid != -1) {
1182                dev = crypto_find_device_byhid(find->crid);
1183                if (dev == NULL)
1184                        return (ENOENT);
1185                strncpy(find->name, device_get_nameunit(dev), fnlen);
1186                find->name[fnlen - 1] = '\x0';
1187        } else {
1188                find->name[fnlen - 1] = '\x0';
1189                find->crid = crypto_find_driver(find->name);
1190                if (find->crid == -1)
1191                        return (ENOENT);
1192        }
1193        return (0);
1194}
1195
1196/* ARGSUSED */
1197static int
1198#ifndef __rtems__
1199cryptof_stat(
1200        struct file *fp,
1201        struct stat *sb,
1202        struct ucred *active_cred,
1203        struct thread *td)
1204#else /* __rtems__ */
1205rtems_bsd_cryptof_stat(const rtems_filesystem_location_info_t *loc,
1206    struct stat *buf
1207#endif /* __rtems__ */
1208)
1209{
1210
1211        return (EOPNOTSUPP);
1212}
1213
1214/* ARGSUSED */
1215static int
1216cryptof_close(struct file *fp, struct thread *td)
1217{
1218        struct fcrypt *fcr = fp->f_data;
1219        struct csession *cse;
1220
1221        while ((cse = TAILQ_FIRST(&fcr->csessions))) {
1222                TAILQ_REMOVE(&fcr->csessions, cse, next);
1223                (void)csefree(cse);
1224        }
1225        free(fcr, M_XDATA);
1226        fp->f_data = NULL;
1227        return 0;
1228}
1229#ifdef __rtems__
1230static int
1231rtems_bsd_cryptof_close(rtems_libio_t *iop)
1232{
1233        struct thread *td;
1234        int error;
1235
1236        td = rtems_bsd_get_curthread_or_null();
1237        if (td != NULL) {
1238                struct file *fp;
1239
1240                fp = rtems_bsd_iop_to_fp(iop);
1241                error = cryptof_close(fp, td);
1242        } else {
1243                error = ENOMEM;
1244        }
1245
1246        return (rtems_bsd_error_to_status_and_errno(error));
1247}
1248#endif /* __rtems__ */
1249
1250#ifndef __rtems__
1251static int
1252cryptof_fill_kinfo(struct file *fp, struct kinfo_file *kif, struct filedesc *fdp)
1253{
1254
1255        kif->kf_type = KF_TYPE_CRYPTO;
1256        return (0);
1257}
1258#endif /* __rtems__ */
1259
1260static struct csession *
1261csefind(struct fcrypt *fcr, u_int ses)
1262{
1263        struct csession *cse;
1264
1265        TAILQ_FOREACH(cse, &fcr->csessions, next)
1266                if (cse->ses == ses)
1267                        return (cse);
1268        return (NULL);
1269}
1270
1271static int
1272csedelete(struct fcrypt *fcr, struct csession *cse_del)
1273{
1274        struct csession *cse;
1275
1276        TAILQ_FOREACH(cse, &fcr->csessions, next) {
1277                if (cse == cse_del) {
1278                        TAILQ_REMOVE(&fcr->csessions, cse, next);
1279                        return (1);
1280                }
1281        }
1282        return (0);
1283}
1284       
1285static struct csession *
1286cseadd(struct fcrypt *fcr, struct csession *cse)
1287{
1288        TAILQ_INSERT_TAIL(&fcr->csessions, cse, next);
1289        cse->ses = fcr->sesn++;
1290        return (cse);
1291}
1292
1293struct csession *
1294csecreate(struct fcrypt *fcr, u_int64_t sid, caddr_t key, u_int64_t keylen,
1295    caddr_t mackey, u_int64_t mackeylen, u_int32_t cipher, u_int32_t mac,
1296    struct enc_xform *txform, struct auth_hash *thash)
1297{
1298        struct csession *cse;
1299
1300        cse = malloc(sizeof(struct csession), M_XDATA, M_NOWAIT | M_ZERO);
1301        if (cse == NULL)
1302                return NULL;
1303        mtx_init(&cse->lock, "cryptodev", "crypto session lock", MTX_DEF);
1304        cse->key = key;
1305        cse->keylen = keylen/8;
1306        cse->mackey = mackey;
1307        cse->mackeylen = mackeylen/8;
1308        cse->sid = sid;
1309        cse->cipher = cipher;
1310        cse->mac = mac;
1311        cse->txform = txform;
1312        cse->thash = thash;
1313        cseadd(fcr, cse);
1314        return (cse);
1315}
1316
1317static int
1318csefree(struct csession *cse)
1319{
1320        int error;
1321
1322        error = crypto_freesession(cse->sid);
1323        mtx_destroy(&cse->lock);
1324        if (cse->key)
1325                free(cse->key, M_XDATA);
1326        if (cse->mackey)
1327                free(cse->mackey, M_XDATA);
1328        free(cse, M_XDATA);
1329        return (error);
1330}
1331
1332static int
1333cryptoopen(struct cdev *dev, int oflags, int devtype, struct thread *td)
1334{
1335        return (0);
1336}
1337
1338static int
1339cryptoread(struct cdev *dev, struct uio *uio, int ioflag)
1340{
1341        return (EIO);
1342}
1343
1344static int
1345cryptowrite(struct cdev *dev, struct uio *uio, int ioflag)
1346{
1347        return (EIO);
1348}
1349
1350static int
1351cryptoioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td)
1352{
1353        struct file *f;
1354        struct fcrypt *fcr;
1355        int fd, error;
1356
1357        switch (cmd) {
1358        case CRIOGET:
1359                fcr = malloc(sizeof(struct fcrypt), M_XDATA, M_WAITOK);
1360                TAILQ_INIT(&fcr->csessions);
1361                fcr->sesn = 0;
1362
1363                error = falloc(td, &f, &fd, 0);
1364
1365                if (error) {
1366                        free(fcr, M_XDATA);
1367                        return (error);
1368                }
1369                /* falloc automatically provides an extra reference to 'f'. */
1370                finit(f, FREAD | FWRITE, DTYPE_CRYPTO, fcr, &cryptofops);
1371                *(u_int32_t *)data = fd;
1372#ifndef __rtems__
1373                fdrop(f, td);
1374#endif /* __rtems__ */
1375                break;
1376        case CRIOFINDDEV:
1377                error = cryptodev_find((struct crypt_find_op *)data);
1378                break;
1379        case CRIOASYMFEAT:
1380                error = crypto_getfeat((int *)data);
1381                break;
1382        default:
1383                error = EINVAL;
1384                break;
1385        }
1386        return (error);
1387}
1388
1389static struct cdevsw crypto_cdevsw = {
1390        .d_version =    D_VERSION,
1391        .d_flags =      D_NEEDGIANT,
1392        .d_open =       cryptoopen,
1393        .d_read =       cryptoread,
1394        .d_write =      cryptowrite,
1395        .d_ioctl =      cryptoioctl,
1396        .d_name =       "crypto",
1397};
1398static struct cdev *crypto_dev;
1399
1400/*
1401 * Initialization code, both for static and dynamic loading.
1402 */
1403static int
1404cryptodev_modevent(module_t mod, int type, void *unused)
1405{
1406        switch (type) {
1407        case MOD_LOAD:
1408                if (bootverbose)
1409                        printf("crypto: <crypto device>\n");
1410                crypto_dev = make_dev(&crypto_cdevsw, 0, 
1411                                      UID_ROOT, GID_WHEEL, 0666,
1412                                      "crypto");
1413                return 0;
1414        case MOD_UNLOAD:
1415                /*XXX disallow if active sessions */
1416                destroy_dev(crypto_dev);
1417                return 0;
1418        }
1419        return EINVAL;
1420}
1421
1422static moduledata_t cryptodev_mod = {
1423        "cryptodev",
1424        cryptodev_modevent,
1425        0
1426};
1427MODULE_VERSION(cryptodev, 1);
1428DECLARE_MODULE(cryptodev, cryptodev_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
1429MODULE_DEPEND(cryptodev, crypto, 1, 1, 1);
1430MODULE_DEPEND(cryptodev, zlib, 1, 1, 1);
1431#ifdef __rtems__
1432static const rtems_filesystem_file_handlers_r cryptofops = {
1433        .open_h = rtems_filesystem_default_open,
1434        .close_h = rtems_bsd_cryptof_close,
1435        .read_h = rtems_filesystem_default_read,
1436        .write_h = rtems_filesystem_default_write,
1437        .ioctl_h = rtems_bsd_cryptof_ioctl,
1438        .lseek_h = rtems_filesystem_default_lseek,
1439        .fstat_h = rtems_bsd_cryptof_stat,
1440        .ftruncate_h = rtems_filesystem_default_ftruncate,
1441        .fsync_h = rtems_filesystem_default_fsync_or_fdatasync,
1442        .fdatasync_h = rtems_filesystem_default_fsync_or_fdatasync,
1443        .fcntl_h = rtems_filesystem_default_fcntl,
1444        .poll_h = rtems_filesystem_default_poll,
1445        .kqfilter_h = rtems_filesystem_default_kqfilter,
1446        .readv_h = rtems_filesystem_default_readv,
1447        .writev_h = rtems_filesystem_default_writev,
1448        .mmap_h = rtems_filesystem_default_mmap
1449};
1450#endif /* __rtems__ */
Note: See TracBrowser for help on using the repository browser.