c57862969ece4d2ad93ba35f34240fca0bbfd48a
[openssl.git] / engines / e_devcrypto.c
1 /*
2  * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License 2.0 (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9
10 #include "../e_os.h"
11 #include <string.h>
12 #include <sys/types.h>
13 #include <sys/stat.h>
14 #include <fcntl.h>
15 #include <sys/ioctl.h>
16 #include <unistd.h>
17 #include <assert.h>
18
19 #include <openssl/conf.h>
20 #include <openssl/evp.h>
21 #include <openssl/err.h>
22 #include <openssl/engine.h>
23 #include <openssl/objects.h>
24 #include <crypto/cryptodev.h>
25
26 /* #define ENGINE_DEVCRYPTO_DEBUG */
27
28 #ifdef CRYPTO_ALGORITHM_MIN
29 # define CHECK_BSD_STYLE_MACROS
30 #endif
31
32 #define engine_devcrypto_id "devcrypto"
33
34 /*
35  * ONE global file descriptor for all sessions.  This allows operations
36  * such as digest session data copying (see digest_copy()), but is also
37  * saner...  why re-open /dev/crypto for every session?
38  */
39 static int cfd = -1;
40 #define DEVCRYPTO_REQUIRE_ACCELERATED 0 /* require confirmation of acceleration */
41 #define DEVCRYPTO_USE_SOFTWARE        1 /* allow software drivers */
42 #define DEVCRYPTO_REJECT_SOFTWARE     2 /* only disallow confirmed software drivers */
43
44 #define DEVCRYPTO_DEFAULT_USE_SOFTDRIVERS DEVCRYPTO_REJECT_SOFTWARE
45 static int use_softdrivers = DEVCRYPTO_DEFAULT_USE_SOFTDRIVERS;
46
47 /*
48  * cipher/digest status & acceleration definitions
49  * Make sure the defaults are set to 0
50  */
51 struct driver_info_st {
52     enum devcrypto_status_t {
53         DEVCRYPTO_STATUS_FAILURE         = -3, /* unusable for other reason */
54         DEVCRYPTO_STATUS_NO_CIOCCPHASH   = -2, /* hash state copy not supported */
55         DEVCRYPTO_STATUS_NO_CIOCGSESSION = -1, /* session open failed */
56         DEVCRYPTO_STATUS_UNKNOWN         =  0, /* not tested yet */
57         DEVCRYPTO_STATUS_USABLE          =  1  /* algo can be used */
58     } status;
59
60     enum devcrypto_accelerated_t {
61         DEVCRYPTO_NOT_ACCELERATED        = -1, /* software implemented */
62         DEVCRYPTO_ACCELERATION_UNKNOWN   =  0, /* acceleration support unkown */
63         DEVCRYPTO_ACCELERATED            =  1  /* hardware accelerated */
64     } accelerated;
65
66     char *driver_name;
67 };
68
69 #ifdef OPENSSL_NO_DYNAMIC_ENGINE
70 void engine_load_devcrypto_int(void);
71 #endif
72
73 static int clean_devcrypto_session(struct session_op *sess) {
74     if (ioctl(cfd, CIOCFSESSION, &sess->ses) < 0) {
75         SYSerr(SYS_F_IOCTL, errno);
76         return 0;
77     }
78     memset(sess, 0, sizeof(struct session_op));
79     return 1;
80 }
81
82 /******************************************************************************
83  *
84  * Ciphers
85  *
86  * Because they all do the same basic operation, we have only one set of
87  * method functions for them all to share, and a mapping table between
88  * NIDs and cryptodev IDs, with all the necessary size data.
89  *
90  *****/
91
92 struct cipher_ctx {
93     struct session_op sess;
94     int op;                      /* COP_ENCRYPT or COP_DECRYPT */
95     unsigned long mode;          /* EVP_CIPH_*_MODE */
96
97     /* to handle ctr mode being a stream cipher */
98     unsigned char partial[EVP_MAX_BLOCK_LENGTH];
99     unsigned int blocksize, num;
100 };
101
102 static const struct cipher_data_st {
103     int nid;
104     int blocksize;
105     int keylen;
106     int ivlen;
107     int flags;
108     int devcryptoid;
109 } cipher_data[] = {
110 #ifndef OPENSSL_NO_DES
111     { NID_des_cbc, 8, 8, 8, EVP_CIPH_CBC_MODE, CRYPTO_DES_CBC },
112     { NID_des_ede3_cbc, 8, 24, 8, EVP_CIPH_CBC_MODE, CRYPTO_3DES_CBC },
113 #endif
114 #ifndef OPENSSL_NO_BF
115     { NID_bf_cbc, 8, 16, 8, EVP_CIPH_CBC_MODE, CRYPTO_BLF_CBC },
116 #endif
117 #ifndef OPENSSL_NO_CAST
118     { NID_cast5_cbc, 8, 16, 8, EVP_CIPH_CBC_MODE, CRYPTO_CAST_CBC },
119 #endif
120     { NID_aes_128_cbc, 16, 128 / 8, 16, EVP_CIPH_CBC_MODE, CRYPTO_AES_CBC },
121     { NID_aes_192_cbc, 16, 192 / 8, 16, EVP_CIPH_CBC_MODE, CRYPTO_AES_CBC },
122     { NID_aes_256_cbc, 16, 256 / 8, 16, EVP_CIPH_CBC_MODE, CRYPTO_AES_CBC },
123 #ifndef OPENSSL_NO_RC4
124     { NID_rc4, 1, 16, 0, EVP_CIPH_STREAM_CIPHER, CRYPTO_ARC4 },
125 #endif
126 #if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_AES_CTR)
127     { NID_aes_128_ctr, 16, 128 / 8, 16, EVP_CIPH_CTR_MODE, CRYPTO_AES_CTR },
128     { NID_aes_192_ctr, 16, 192 / 8, 16, EVP_CIPH_CTR_MODE, CRYPTO_AES_CTR },
129     { NID_aes_256_ctr, 16, 256 / 8, 16, EVP_CIPH_CTR_MODE, CRYPTO_AES_CTR },
130 #endif
131 #if 0                            /* Not yet supported */
132     { NID_aes_128_xts, 16, 128 / 8 * 2, 16, EVP_CIPH_XTS_MODE, CRYPTO_AES_XTS },
133     { NID_aes_256_xts, 16, 256 / 8 * 2, 16, EVP_CIPH_XTS_MODE, CRYPTO_AES_XTS },
134 #endif
135 #if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_AES_ECB)
136     { NID_aes_128_ecb, 16, 128 / 8, 0, EVP_CIPH_ECB_MODE, CRYPTO_AES_ECB },
137     { NID_aes_192_ecb, 16, 192 / 8, 0, EVP_CIPH_ECB_MODE, CRYPTO_AES_ECB },
138     { NID_aes_256_ecb, 16, 256 / 8, 0, EVP_CIPH_ECB_MODE, CRYPTO_AES_ECB },
139 #endif
140 #if 0                            /* Not yet supported */
141     { NID_aes_128_gcm, 16, 128 / 8, 16, EVP_CIPH_GCM_MODE, CRYPTO_AES_GCM },
142     { NID_aes_192_gcm, 16, 192 / 8, 16, EVP_CIPH_GCM_MODE, CRYPTO_AES_GCM },
143     { NID_aes_256_gcm, 16, 256 / 8, 16, EVP_CIPH_GCM_MODE, CRYPTO_AES_GCM },
144 #endif
145 #ifndef OPENSSL_NO_CAMELLIA
146     { NID_camellia_128_cbc, 16, 128 / 8, 16, EVP_CIPH_CBC_MODE,
147       CRYPTO_CAMELLIA_CBC },
148     { NID_camellia_192_cbc, 16, 192 / 8, 16, EVP_CIPH_CBC_MODE,
149       CRYPTO_CAMELLIA_CBC },
150     { NID_camellia_256_cbc, 16, 256 / 8, 16, EVP_CIPH_CBC_MODE,
151       CRYPTO_CAMELLIA_CBC },
152 #endif
153 };
154
155 static size_t find_cipher_data_index(int nid)
156 {
157     size_t i;
158
159     for (i = 0; i < OSSL_NELEM(cipher_data); i++)
160         if (nid == cipher_data[i].nid)
161             return i;
162     return (size_t)-1;
163 }
164
165 static size_t get_cipher_data_index(int nid)
166 {
167     size_t i = find_cipher_data_index(nid);
168
169     if (i != (size_t)-1)
170         return i;
171
172     /*
173      * Code further down must make sure that only NIDs in the table above
174      * are used.  If any other NID reaches this function, there's a grave
175      * coding error further down.
176      */
177     assert("Code that never should be reached" == NULL);
178     return -1;
179 }
180
181 static const struct cipher_data_st *get_cipher_data(int nid)
182 {
183     return &cipher_data[get_cipher_data_index(nid)];
184 }
185
186 /*
187  * Following are the three necessary functions to map OpenSSL functionality
188  * with cryptodev.
189  */
190
191 static int cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
192                        const unsigned char *iv, int enc)
193 {
194     struct cipher_ctx *cipher_ctx =
195         (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
196     const struct cipher_data_st *cipher_d =
197         get_cipher_data(EVP_CIPHER_CTX_nid(ctx));
198
199     /* cleanup a previous session */
200     if (cipher_ctx->sess.ses != 0 &&
201         clean_devcrypto_session(&cipher_ctx->sess) == 0)
202         return 0;
203
204     cipher_ctx->sess.cipher = cipher_d->devcryptoid;
205     cipher_ctx->sess.keylen = cipher_d->keylen;
206     cipher_ctx->sess.key = (void *)key;
207     cipher_ctx->op = enc ? COP_ENCRYPT : COP_DECRYPT;
208     cipher_ctx->mode = cipher_d->flags & EVP_CIPH_MODE;
209     cipher_ctx->blocksize = cipher_d->blocksize;
210     if (ioctl(cfd, CIOCGSESSION, &cipher_ctx->sess) < 0) {
211         SYSerr(SYS_F_IOCTL, errno);
212         return 0;
213     }
214
215     return 1;
216 }
217
218 static int cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
219                             const unsigned char *in, size_t inl)
220 {
221     struct cipher_ctx *cipher_ctx =
222         (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
223     struct crypt_op cryp;
224     unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx);
225 #if !defined(COP_FLAG_WRITE_IV)
226     unsigned char saved_iv[EVP_MAX_IV_LENGTH];
227     const unsigned char *ivptr;
228     size_t nblocks, ivlen;
229 #endif
230
231     memset(&cryp, 0, sizeof(cryp));
232     cryp.ses = cipher_ctx->sess.ses;
233     cryp.len = inl;
234     cryp.src = (void *)in;
235     cryp.dst = (void *)out;
236     cryp.iv = (void *)iv;
237     cryp.op = cipher_ctx->op;
238 #if !defined(COP_FLAG_WRITE_IV)
239     cryp.flags = 0;
240
241     ivlen = EVP_CIPHER_CTX_iv_length(ctx);
242     if (ivlen > 0)
243         switch (cipher_ctx->mode) {
244         case EVP_CIPH_CBC_MODE:
245             assert(inl >= ivlen);
246             if (!EVP_CIPHER_CTX_encrypting(ctx)) {
247                 ivptr = in + inl - ivlen;
248                 memcpy(saved_iv, ivptr, ivlen);
249             }
250             break;
251
252         case EVP_CIPH_CTR_MODE:
253             break;
254
255         default: /* should not happen */
256             return 0;
257         }
258 #else
259     cryp.flags = COP_FLAG_WRITE_IV;
260 #endif
261
262     if (ioctl(cfd, CIOCCRYPT, &cryp) < 0) {
263         SYSerr(SYS_F_IOCTL, errno);
264         return 0;
265     }
266
267 #if !defined(COP_FLAG_WRITE_IV)
268     if (ivlen > 0)
269         switch (cipher_ctx->mode) {
270         case EVP_CIPH_CBC_MODE:
271             assert(inl >= ivlen);
272             if (EVP_CIPHER_CTX_encrypting(ctx))
273                 ivptr = out + inl - ivlen;
274             else
275                 ivptr = saved_iv;
276
277             memcpy(iv, ivptr, ivlen);
278             break;
279
280         case EVP_CIPH_CTR_MODE:
281             nblocks = (inl + cipher_ctx->blocksize - 1)
282                       / cipher_ctx->blocksize;
283             do {
284                 ivlen--;
285                 nblocks += iv[ivlen];
286                 iv[ivlen] = (uint8_t) nblocks;
287                 nblocks >>= 8;
288             } while (ivlen);
289             break;
290
291         default: /* should not happen */
292             return 0;
293         }
294 #endif
295
296     return 1;
297 }
298
299 static int ctr_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
300                          const unsigned char *in, size_t inl)
301 {
302     struct cipher_ctx *cipher_ctx =
303         (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
304     size_t nblocks, len;
305
306     /* initial partial block */
307     while (cipher_ctx->num && inl) {
308         (*out++) = *(in++) ^ cipher_ctx->partial[cipher_ctx->num];
309         --inl;
310         cipher_ctx->num = (cipher_ctx->num + 1) % cipher_ctx->blocksize;
311     }
312
313     /* full blocks */
314     if (inl > (unsigned int) cipher_ctx->blocksize) {
315         nblocks = inl/cipher_ctx->blocksize;
316         len = nblocks * cipher_ctx->blocksize;
317         if (cipher_do_cipher(ctx, out, in, len) < 1)
318             return 0;
319         inl -= len;
320         out += len;
321         in += len;
322     }
323
324     /* final partial block */
325     if (inl) {
326         memset(cipher_ctx->partial, 0, cipher_ctx->blocksize);
327         if (cipher_do_cipher(ctx, cipher_ctx->partial, cipher_ctx->partial,
328             cipher_ctx->blocksize) < 1)
329             return 0;
330         while (inl--) {
331             out[cipher_ctx->num] = in[cipher_ctx->num]
332                                    ^ cipher_ctx->partial[cipher_ctx->num];
333             cipher_ctx->num++;
334         }
335     }
336
337     return 1;
338 }
339
340 static int cipher_ctrl(EVP_CIPHER_CTX *ctx, int type, int p1, void* p2)
341 {
342     struct cipher_ctx *cipher_ctx =
343         (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
344     EVP_CIPHER_CTX *to_ctx = (EVP_CIPHER_CTX *)p2;
345     struct cipher_ctx *to_cipher_ctx;
346
347     switch (type) {
348
349     case EVP_CTRL_COPY:
350         if (cipher_ctx == NULL)
351             return 1;
352         /* when copying the context, a new session needs to be initialized */
353         to_cipher_ctx =
354             (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(to_ctx);
355         memset(&to_cipher_ctx->sess, 0, sizeof(to_cipher_ctx->sess));
356         return cipher_init(to_ctx, cipher_ctx->sess.key, EVP_CIPHER_CTX_iv(ctx),
357                            (cipher_ctx->op == COP_ENCRYPT));
358
359     case EVP_CTRL_INIT:
360         memset(&cipher_ctx->sess, 0, sizeof(cipher_ctx->sess));
361         return 1;
362
363     default:
364         break;
365     }
366
367     return -1;
368 }
369
370 static int cipher_cleanup(EVP_CIPHER_CTX *ctx)
371 {
372     struct cipher_ctx *cipher_ctx =
373         (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
374
375     return clean_devcrypto_session(&cipher_ctx->sess);
376 }
377
378 /*
379  * Keep tables of known nids, associated methods, selected ciphers, and driver
380  * info.
381  * Note that known_cipher_nids[] isn't necessarily indexed the same way as
382  * cipher_data[] above, which the other tables are.
383  */
384 static int known_cipher_nids[OSSL_NELEM(cipher_data)];
385 static int known_cipher_nids_amount = -1; /* -1 indicates not yet initialised */
386 static EVP_CIPHER *known_cipher_methods[OSSL_NELEM(cipher_data)] = { NULL, };
387 static int selected_ciphers[OSSL_NELEM(cipher_data)];
388 static struct driver_info_st cipher_driver_info[OSSL_NELEM(cipher_data)];
389
390
391 static int devcrypto_test_cipher(size_t cipher_data_index)
392 {
393     return (cipher_driver_info[cipher_data_index].status == DEVCRYPTO_STATUS_USABLE
394             && selected_ciphers[cipher_data_index] == 1
395             && (cipher_driver_info[cipher_data_index].accelerated
396                     == DEVCRYPTO_ACCELERATED
397                 || use_softdrivers == DEVCRYPTO_USE_SOFTWARE
398                 || (cipher_driver_info[cipher_data_index].accelerated
399                         != DEVCRYPTO_NOT_ACCELERATED
400                     && use_softdrivers == DEVCRYPTO_REJECT_SOFTWARE)));
401 }
402
403 static void prepare_cipher_methods(void)
404 {
405     size_t i;
406     struct session_op sess;
407     unsigned long cipher_mode;
408 #ifdef CIOCGSESSINFO
409     struct session_info_op siop;
410 #endif
411
412     memset(&cipher_driver_info, 0, sizeof(cipher_driver_info));
413
414     memset(&sess, 0, sizeof(sess));
415     sess.key = (void *)"01234567890123456789012345678901234567890123456789";
416
417     for (i = 0, known_cipher_nids_amount = 0;
418          i < OSSL_NELEM(cipher_data); i++) {
419
420         selected_ciphers[i] = 1;
421         /*
422          * Check that the cipher is usable
423          */
424         sess.cipher = cipher_data[i].devcryptoid;
425         sess.keylen = cipher_data[i].keylen;
426         if (ioctl(cfd, CIOCGSESSION, &sess) < 0) {
427             cipher_driver_info[i].status = DEVCRYPTO_STATUS_NO_CIOCGSESSION;
428             continue;
429         }
430
431         cipher_mode = cipher_data[i].flags & EVP_CIPH_MODE;
432
433         if ((known_cipher_methods[i] =
434                  EVP_CIPHER_meth_new(cipher_data[i].nid,
435                                      cipher_mode == EVP_CIPH_CTR_MODE ? 1 :
436                                                     cipher_data[i].blocksize,
437                                      cipher_data[i].keylen)) == NULL
438             || !EVP_CIPHER_meth_set_iv_length(known_cipher_methods[i],
439                                               cipher_data[i].ivlen)
440             || !EVP_CIPHER_meth_set_flags(known_cipher_methods[i],
441                                           cipher_data[i].flags
442                                           | EVP_CIPH_CUSTOM_COPY
443                                           | EVP_CIPH_CTRL_INIT
444                                           | EVP_CIPH_FLAG_DEFAULT_ASN1)
445             || !EVP_CIPHER_meth_set_init(known_cipher_methods[i], cipher_init)
446             || !EVP_CIPHER_meth_set_do_cipher(known_cipher_methods[i],
447                                      cipher_mode == EVP_CIPH_CTR_MODE ?
448                                               ctr_do_cipher :
449                                               cipher_do_cipher)
450             || !EVP_CIPHER_meth_set_ctrl(known_cipher_methods[i], cipher_ctrl)
451             || !EVP_CIPHER_meth_set_cleanup(known_cipher_methods[i],
452                                             cipher_cleanup)
453             || !EVP_CIPHER_meth_set_impl_ctx_size(known_cipher_methods[i],
454                                                   sizeof(struct cipher_ctx))) {
455             cipher_driver_info[i].status = DEVCRYPTO_STATUS_FAILURE;
456             EVP_CIPHER_meth_free(known_cipher_methods[i]);
457             known_cipher_methods[i] = NULL;
458         } else {
459             cipher_driver_info[i].status = DEVCRYPTO_STATUS_USABLE;
460 #ifdef CIOCGSESSINFO
461             siop.ses = sess.ses;
462             if (ioctl(cfd, CIOCGSESSINFO, &siop) < 0) {
463                 cipher_driver_info[i].accelerated = DEVCRYPTO_ACCELERATION_UNKNOWN;
464             } else {
465                 cipher_driver_info[i].driver_name =
466                     OPENSSL_strndup(siop.cipher_info.cra_driver_name,
467                                     CRYPTODEV_MAX_ALG_NAME);
468                 if (!(siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY))
469                     cipher_driver_info[i].accelerated = DEVCRYPTO_NOT_ACCELERATED;
470                 else
471                     cipher_driver_info[i].accelerated = DEVCRYPTO_ACCELERATED;
472             }
473 #endif /* CIOCGSESSINFO */
474         }
475         ioctl(cfd, CIOCFSESSION, &sess.ses);
476         if (devcrypto_test_cipher(i)) {
477             known_cipher_nids[known_cipher_nids_amount++] =
478                 cipher_data[i].nid;
479         }
480     }
481 }
482
483 static void rebuild_known_cipher_nids(ENGINE *e)
484 {
485     size_t i;
486
487     for (i = 0, known_cipher_nids_amount = 0; i < OSSL_NELEM(cipher_data); i++) {
488         if (devcrypto_test_cipher(i))
489             known_cipher_nids[known_cipher_nids_amount++] = cipher_data[i].nid;
490     }
491     ENGINE_unregister_ciphers(e);
492     ENGINE_register_ciphers(e);
493 }
494
495 static const EVP_CIPHER *get_cipher_method(int nid)
496 {
497     size_t i = get_cipher_data_index(nid);
498
499     if (i == (size_t)-1)
500         return NULL;
501     return known_cipher_methods[i];
502 }
503
504 static int get_cipher_nids(const int **nids)
505 {
506     *nids = known_cipher_nids;
507     return known_cipher_nids_amount;
508 }
509
510 static void destroy_cipher_method(int nid)
511 {
512     size_t i = get_cipher_data_index(nid);
513
514     EVP_CIPHER_meth_free(known_cipher_methods[i]);
515     known_cipher_methods[i] = NULL;
516 }
517
518 static void destroy_all_cipher_methods(void)
519 {
520     size_t i;
521
522     for (i = 0; i < OSSL_NELEM(cipher_data); i++) {
523         destroy_cipher_method(cipher_data[i].nid);
524         OPENSSL_free(cipher_driver_info[i].driver_name);
525         cipher_driver_info[i].driver_name = NULL;
526     }
527 }
528
529 static int devcrypto_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
530                              const int **nids, int nid)
531 {
532     if (cipher == NULL)
533         return get_cipher_nids(nids);
534
535     *cipher = get_cipher_method(nid);
536
537     return *cipher != NULL;
538 }
539
540 static void devcrypto_select_all_ciphers(int *cipher_list)
541 {
542     size_t i;
543
544     for (i = 0; i < OSSL_NELEM(cipher_data); i++)
545         cipher_list[i] = 1;
546 }
547
548 static int cryptodev_select_cipher_cb(const char *str, int len, void *usr)
549 {
550     int *cipher_list = (int *)usr;
551     char *name;
552     const EVP_CIPHER *EVP;
553     size_t i;
554
555     if (len == 0)
556         return 1;
557     if (usr == NULL || (name = OPENSSL_strndup(str, len)) == NULL)
558         return 0;
559     EVP = EVP_get_cipherbyname(name);
560     if (EVP == NULL)
561         fprintf(stderr, "devcrypto: unknown cipher %s\n", name);
562     else if ((i = find_cipher_data_index(EVP_CIPHER_nid(EVP))) != (size_t)-1)
563         cipher_list[i] = 1;
564     else
565         fprintf(stderr, "devcrypto: cipher %s not available\n", name);
566     OPENSSL_free(name);
567     return 1;
568 }
569
570 static void dump_cipher_info(void)
571 {
572     size_t i;
573     const char *name;
574
575     fprintf (stderr, "Information about ciphers supported by the /dev/crypto"
576              " engine:\n");
577 #ifndef CIOCGSESSINFO
578     fprintf(stderr, "CIOCGSESSINFO (session info call) unavailable\n");
579 #endif
580     for (i = 0; i < OSSL_NELEM(cipher_data); i++) {
581         name = OBJ_nid2sn(cipher_data[i].nid);
582         fprintf (stderr, "Cipher %s, NID=%d, /dev/crypto info: id=%d, ",
583                  name ? name : "unknown", cipher_data[i].nid,
584                  cipher_data[i].devcryptoid);
585         if (cipher_driver_info[i].status == DEVCRYPTO_STATUS_NO_CIOCGSESSION ) {
586             fprintf (stderr, "CIOCGSESSION (session open call) failed\n");
587             continue;
588         }
589         fprintf (stderr, "driver=%s ", cipher_driver_info[i].driver_name ?
590                  cipher_driver_info[i].driver_name : "unknown");
591         if (cipher_driver_info[i].accelerated == DEVCRYPTO_ACCELERATED)
592             fprintf(stderr, "(hw accelerated)");
593         else if (cipher_driver_info[i].accelerated == DEVCRYPTO_NOT_ACCELERATED)
594             fprintf(stderr, "(software)");
595         else
596             fprintf(stderr, "(acceleration status unknown)");
597         if (cipher_driver_info[i].status == DEVCRYPTO_STATUS_FAILURE)
598             fprintf (stderr, ". Cipher setup failed");
599         fprintf(stderr, "\n");
600     }
601     fprintf(stderr, "\n");
602 }
603
604 /*
605  * We only support digests if the cryptodev implementation supports multiple
606  * data updates and session copying.  Otherwise, we would be forced to maintain
607  * a cache, which is perilous if there's a lot of data coming in (if someone
608  * wants to checksum an OpenSSL tarball, for example).
609  */
610 #if defined(CIOCCPHASH) && defined(COP_FLAG_UPDATE) && defined(COP_FLAG_FINAL)
611 #define IMPLEMENT_DIGEST
612
613 /******************************************************************************
614  *
615  * Digests
616  *
617  * Because they all do the same basic operation, we have only one set of
618  * method functions for them all to share, and a mapping table between
619  * NIDs and cryptodev IDs, with all the necessary size data.
620  *
621  *****/
622
623 struct digest_ctx {
624     struct session_op sess;
625     /* This signals that the init function was called, not that it succeeded. */
626     int init_called;
627     unsigned char digest_res[HASH_MAX_LEN];
628 };
629
630 static const struct digest_data_st {
631     int nid;
632     int digestlen;
633     int devcryptoid;
634 } digest_data[] = {
635 #ifndef OPENSSL_NO_MD5
636     { NID_md5, 16, CRYPTO_MD5 },
637 #endif
638     { NID_sha1, 20, CRYPTO_SHA1 },
639 #ifndef OPENSSL_NO_RMD160
640 # if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_RIPEMD160)
641     { NID_ripemd160, 20, CRYPTO_RIPEMD160 },
642 # endif
643 #endif
644 #if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_224)
645     { NID_sha224, 224 / 8, CRYPTO_SHA2_224 },
646 #endif
647 #if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_256)
648     { NID_sha256, 256 / 8, CRYPTO_SHA2_256 },
649 #endif
650 #if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_384)
651     { NID_sha384, 384 / 8, CRYPTO_SHA2_384 },
652 #endif
653 #if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_512)
654     { NID_sha512, 512 / 8, CRYPTO_SHA2_512 },
655 #endif
656 };
657
658 static size_t find_digest_data_index(int nid)
659 {
660     size_t i;
661
662     for (i = 0; i < OSSL_NELEM(digest_data); i++)
663         if (nid == digest_data[i].nid)
664             return i;
665     return (size_t)-1;
666 }
667
668 static size_t get_digest_data_index(int nid)
669 {
670     size_t i = find_digest_data_index(nid);
671
672     if (i != (size_t)-1)
673         return i;
674
675     /*
676      * Code further down must make sure that only NIDs in the table above
677      * are used.  If any other NID reaches this function, there's a grave
678      * coding error further down.
679      */
680     assert("Code that never should be reached" == NULL);
681     return -1;
682 }
683
684 static const struct digest_data_st *get_digest_data(int nid)
685 {
686     return &digest_data[get_digest_data_index(nid)];
687 }
688
689 /*
690  * Following are the five necessary functions to map OpenSSL functionality
691  * with cryptodev: init, update, final, cleanup, and copy.
692  */
693
694 static int digest_init(EVP_MD_CTX *ctx)
695 {
696     struct digest_ctx *digest_ctx =
697         (struct digest_ctx *)EVP_MD_CTX_md_data(ctx);
698     const struct digest_data_st *digest_d =
699         get_digest_data(EVP_MD_CTX_type(ctx));
700
701     digest_ctx->init_called = 1;
702
703     memset(&digest_ctx->sess, 0, sizeof(digest_ctx->sess));
704     digest_ctx->sess.mac = digest_d->devcryptoid;
705     if (ioctl(cfd, CIOCGSESSION, &digest_ctx->sess) < 0) {
706         SYSerr(SYS_F_IOCTL, errno);
707         return 0;
708     }
709
710     return 1;
711 }
712
713 static int digest_op(struct digest_ctx *ctx, const void *src, size_t srclen,
714                      void *res, unsigned int flags)
715 {
716     struct crypt_op cryp;
717
718     memset(&cryp, 0, sizeof(cryp));
719     cryp.ses = ctx->sess.ses;
720     cryp.len = srclen;
721     cryp.src = (void *)src;
722     cryp.dst = NULL;
723     cryp.mac = res;
724     cryp.flags = flags;
725     return ioctl(cfd, CIOCCRYPT, &cryp);
726 }
727
728 static int digest_update(EVP_MD_CTX *ctx, const void *data, size_t count)
729 {
730     struct digest_ctx *digest_ctx =
731         (struct digest_ctx *)EVP_MD_CTX_md_data(ctx);
732
733     if (count == 0)
734         return 1;
735
736     if (digest_ctx == NULL)
737         return 0;
738
739     if (EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_ONESHOT)) {
740         if (digest_op(digest_ctx, data, count, digest_ctx->digest_res, 0) >= 0)
741             return 1;
742     } else if (digest_op(digest_ctx, data, count, NULL, COP_FLAG_UPDATE) >= 0) {
743         return 1;
744     }
745
746     SYSerr(SYS_F_IOCTL, errno);
747     return 0;
748 }
749
750 static int digest_final(EVP_MD_CTX *ctx, unsigned char *md)
751 {
752     struct digest_ctx *digest_ctx =
753         (struct digest_ctx *)EVP_MD_CTX_md_data(ctx);
754
755     if (md == NULL || digest_ctx == NULL)
756         return 0;
757
758     if (EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_ONESHOT)) {
759         memcpy(md, digest_ctx->digest_res, EVP_MD_CTX_size(ctx));
760     } else if (digest_op(digest_ctx, NULL, 0, md, COP_FLAG_FINAL) < 0) {
761         SYSerr(SYS_F_IOCTL, errno);
762         return 0;
763     }
764
765     return 1;
766 }
767
768 static int digest_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from)
769 {
770     struct digest_ctx *digest_from =
771         (struct digest_ctx *)EVP_MD_CTX_md_data(from);
772     struct digest_ctx *digest_to =
773         (struct digest_ctx *)EVP_MD_CTX_md_data(to);
774     struct cphash_op cphash;
775
776     if (digest_from == NULL || digest_from->init_called != 1)
777         return 1;
778
779     if (!digest_init(to)) {
780         SYSerr(SYS_F_IOCTL, errno);
781         return 0;
782     }
783
784     cphash.src_ses = digest_from->sess.ses;
785     cphash.dst_ses = digest_to->sess.ses;
786     if (ioctl(cfd, CIOCCPHASH, &cphash) < 0) {
787         SYSerr(SYS_F_IOCTL, errno);
788         return 0;
789     }
790     return 1;
791 }
792
793 static int digest_cleanup(EVP_MD_CTX *ctx)
794 {
795     struct digest_ctx *digest_ctx =
796         (struct digest_ctx *)EVP_MD_CTX_md_data(ctx);
797
798     if (digest_ctx == NULL)
799         return 1;
800
801     return clean_devcrypto_session(&digest_ctx->sess);
802 }
803
804 /*
805  * Keep tables of known nids, associated methods, selected digests, and
806  * driver info.
807  * Note that known_digest_nids[] isn't necessarily indexed the same way as
808  * digest_data[] above, which the other tables are.
809  */
810 static int known_digest_nids[OSSL_NELEM(digest_data)];
811 static int known_digest_nids_amount = -1; /* -1 indicates not yet initialised */
812 static EVP_MD *known_digest_methods[OSSL_NELEM(digest_data)] = { NULL, };
813 static int selected_digests[OSSL_NELEM(digest_data)];
814 static struct driver_info_st digest_driver_info[OSSL_NELEM(digest_data)];
815
816 static int devcrypto_test_digest(size_t digest_data_index)
817 {
818     return (digest_driver_info[digest_data_index].status == DEVCRYPTO_STATUS_USABLE
819             && selected_digests[digest_data_index] == 1
820             && (digest_driver_info[digest_data_index].accelerated
821                     == DEVCRYPTO_ACCELERATED
822                 || use_softdrivers == DEVCRYPTO_USE_SOFTWARE
823                 || (digest_driver_info[digest_data_index].accelerated
824                         != DEVCRYPTO_NOT_ACCELERATED
825                     && use_softdrivers == DEVCRYPTO_REJECT_SOFTWARE)));
826 }
827
828 static void rebuild_known_digest_nids(ENGINE *e)
829 {
830     size_t i;
831
832     for (i = 0, known_digest_nids_amount = 0; i < OSSL_NELEM(digest_data); i++) {
833         if (devcrypto_test_digest(i))
834             known_digest_nids[known_digest_nids_amount++] = digest_data[i].nid;
835     }
836     ENGINE_unregister_digests(e);
837     ENGINE_register_digests(e);
838 }
839
840 static void prepare_digest_methods(void)
841 {
842     size_t i;
843     struct session_op sess1, sess2;
844 #ifdef CIOCGSESSINFO
845     struct session_info_op siop;
846 #endif
847     struct cphash_op cphash;
848
849     memset(&digest_driver_info, 0, sizeof(digest_driver_info));
850
851     memset(&sess1, 0, sizeof(sess1));
852     memset(&sess2, 0, sizeof(sess2));
853
854     for (i = 0, known_digest_nids_amount = 0; i < OSSL_NELEM(digest_data);
855          i++) {
856
857         selected_digests[i] = 1;
858
859         /*
860          * Check that the digest is usable
861          */
862         sess1.mac = digest_data[i].devcryptoid;
863         sess2.ses = 0;
864         if (ioctl(cfd, CIOCGSESSION, &sess1) < 0) {
865             digest_driver_info[i].status = DEVCRYPTO_STATUS_NO_CIOCGSESSION;
866             goto finish;
867         }
868
869 #ifdef CIOCGSESSINFO
870         /* gather hardware acceleration info from the driver */
871         siop.ses = sess1.ses;
872         if (ioctl(cfd, CIOCGSESSINFO, &siop) < 0) {
873             digest_driver_info[i].accelerated = DEVCRYPTO_ACCELERATION_UNKNOWN;
874         } else {
875             digest_driver_info[i].driver_name =
876                 OPENSSL_strndup(siop.hash_info.cra_driver_name,
877                                 CRYPTODEV_MAX_ALG_NAME);
878             if (siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY)
879                 digest_driver_info[i].accelerated = DEVCRYPTO_ACCELERATED;
880             else
881                 digest_driver_info[i].accelerated = DEVCRYPTO_NOT_ACCELERATED;
882         }
883 #endif
884
885         /* digest must be capable of hash state copy */
886         sess2.mac = sess1.mac;
887         if (ioctl(cfd, CIOCGSESSION, &sess2) < 0) {
888             digest_driver_info[i].status = DEVCRYPTO_STATUS_FAILURE;
889             goto finish;
890         }
891         cphash.src_ses = sess1.ses;
892         cphash.dst_ses = sess2.ses;
893         if (ioctl(cfd, CIOCCPHASH, &cphash) < 0) {
894             digest_driver_info[i].status = DEVCRYPTO_STATUS_NO_CIOCCPHASH;
895             goto finish;
896         }
897         if ((known_digest_methods[i] = EVP_MD_meth_new(digest_data[i].nid,
898                                                        NID_undef)) == NULL
899             || !EVP_MD_meth_set_result_size(known_digest_methods[i],
900                                             digest_data[i].digestlen)
901             || !EVP_MD_meth_set_init(known_digest_methods[i], digest_init)
902             || !EVP_MD_meth_set_update(known_digest_methods[i], digest_update)
903             || !EVP_MD_meth_set_final(known_digest_methods[i], digest_final)
904             || !EVP_MD_meth_set_copy(known_digest_methods[i], digest_copy)
905             || !EVP_MD_meth_set_cleanup(known_digest_methods[i], digest_cleanup)
906             || !EVP_MD_meth_set_app_datasize(known_digest_methods[i],
907                                              sizeof(struct digest_ctx))) {
908             digest_driver_info[i].status = DEVCRYPTO_STATUS_FAILURE;
909             EVP_MD_meth_free(known_digest_methods[i]);
910             known_digest_methods[i] = NULL;
911             goto finish;
912         }
913         digest_driver_info[i].status = DEVCRYPTO_STATUS_USABLE;
914 finish:
915         ioctl(cfd, CIOCFSESSION, &sess1.ses);
916         if (sess2.ses != 0)
917             ioctl(cfd, CIOCFSESSION, &sess2.ses);
918         if (devcrypto_test_digest(i))
919             known_digest_nids[known_digest_nids_amount++] = digest_data[i].nid;
920     }
921 }
922
923 static const EVP_MD *get_digest_method(int nid)
924 {
925     size_t i = get_digest_data_index(nid);
926
927     if (i == (size_t)-1)
928         return NULL;
929     return known_digest_methods[i];
930 }
931
932 static int get_digest_nids(const int **nids)
933 {
934     *nids = known_digest_nids;
935     return known_digest_nids_amount;
936 }
937
938 static void destroy_digest_method(int nid)
939 {
940     size_t i = get_digest_data_index(nid);
941
942     EVP_MD_meth_free(known_digest_methods[i]);
943     known_digest_methods[i] = NULL;
944 }
945
946 static void destroy_all_digest_methods(void)
947 {
948     size_t i;
949
950     for (i = 0; i < OSSL_NELEM(digest_data); i++) {
951         destroy_digest_method(digest_data[i].nid);
952         OPENSSL_free(digest_driver_info[i].driver_name);
953         digest_driver_info[i].driver_name = NULL;
954     }
955 }
956
957 static int devcrypto_digests(ENGINE *e, const EVP_MD **digest,
958                              const int **nids, int nid)
959 {
960     if (digest == NULL)
961         return get_digest_nids(nids);
962
963     *digest = get_digest_method(nid);
964
965     return *digest != NULL;
966 }
967
968 static void devcrypto_select_all_digests(int *digest_list)
969 {
970     size_t i;
971
972     for (i = 0; i < OSSL_NELEM(digest_data); i++)
973         digest_list[i] = 1;
974 }
975
976 static int cryptodev_select_digest_cb(const char *str, int len, void *usr)
977 {
978     int *digest_list = (int *)usr;
979     char *name;
980     const EVP_MD *EVP;
981     size_t i;
982
983     if (len == 0)
984         return 1;
985     if (usr == NULL || (name = OPENSSL_strndup(str, len)) == NULL)
986         return 0;
987     EVP = EVP_get_digestbyname(name);
988     if (EVP == NULL)
989         fprintf(stderr, "devcrypto: unknown digest %s\n", name);
990     else if ((i = find_digest_data_index(EVP_MD_type(EVP))) != (size_t)-1)
991         digest_list[i] = 1;
992     else
993         fprintf(stderr, "devcrypto: digest %s not available\n", name);
994     OPENSSL_free(name);
995     return 1;
996 }
997
998 static void dump_digest_info(void)
999 {
1000     size_t i;
1001     const char *name;
1002
1003     fprintf (stderr, "Information about digests supported by the /dev/crypto"
1004              " engine:\n");
1005 #ifndef CIOCGSESSINFO
1006     fprintf(stderr, "CIOCGSESSINFO (session info call) unavailable\n");
1007 #endif
1008
1009     for (i = 0; i < OSSL_NELEM(digest_data); i++) {
1010         name = OBJ_nid2sn(digest_data[i].nid);
1011         fprintf (stderr, "Digest %s, NID=%d, /dev/crypto info: id=%d, driver=%s",
1012                  name ? name : "unknown", digest_data[i].nid,
1013                  digest_data[i].devcryptoid,
1014                  digest_driver_info[i].driver_name ? digest_driver_info[i].driver_name : "unknown");
1015         if (digest_driver_info[i].status == DEVCRYPTO_STATUS_NO_CIOCGSESSION) {
1016             fprintf (stderr, ". CIOCGSESSION (session open) failed\n");
1017             continue;
1018         }
1019         if (digest_driver_info[i].accelerated == DEVCRYPTO_ACCELERATED)
1020             fprintf(stderr, " (hw accelerated)");
1021         else if (digest_driver_info[i].accelerated == DEVCRYPTO_NOT_ACCELERATED)
1022             fprintf(stderr, " (software)");
1023         else
1024             fprintf(stderr, " (acceleration status unknown)");
1025         if (cipher_driver_info[i].status == DEVCRYPTO_STATUS_FAILURE)
1026             fprintf (stderr, ". Cipher setup failed\n");
1027         else if (digest_driver_info[i].status == DEVCRYPTO_STATUS_NO_CIOCCPHASH)
1028             fprintf(stderr, ", CIOCCPHASH failed\n");
1029         else
1030             fprintf(stderr, ", CIOCCPHASH capable\n");
1031     }
1032     fprintf(stderr, "\n");
1033 }
1034
1035 #endif
1036
1037 /******************************************************************************
1038  *
1039  * CONTROL COMMANDS
1040  *
1041  *****/
1042
1043 #define DEVCRYPTO_CMD_USE_SOFTDRIVERS ENGINE_CMD_BASE
1044 #define DEVCRYPTO_CMD_CIPHERS (ENGINE_CMD_BASE + 1)
1045 #define DEVCRYPTO_CMD_DIGESTS (ENGINE_CMD_BASE + 2)
1046 #define DEVCRYPTO_CMD_DUMP_INFO (ENGINE_CMD_BASE + 3)
1047
1048 static const ENGINE_CMD_DEFN devcrypto_cmds[] = {
1049 #ifdef CIOCGSESSINFO
1050    {DEVCRYPTO_CMD_USE_SOFTDRIVERS,
1051     "USE_SOFTDRIVERS",
1052     "specifies whether to use software (not accelerated) drivers ("
1053         OPENSSL_MSTR(DEVCRYPTO_REQUIRE_ACCELERATED) "=use only accelerated drivers, "
1054         OPENSSL_MSTR(DEVCRYPTO_USE_SOFTWARE) "=allow all drivers, "
1055         OPENSSL_MSTR(DEVCRYPTO_REJECT_SOFTWARE)
1056         "=use if acceleration can't be determined) [default="
1057         OPENSSL_MSTR(DEVCRYPTO_DEFAULT_USE_SOFTDRIVERS) "]",
1058     ENGINE_CMD_FLAG_NUMERIC},
1059 #endif
1060
1061    {DEVCRYPTO_CMD_CIPHERS,
1062     "CIPHERS",
1063     "either ALL, NONE, or a comma-separated list of ciphers to enable [default=ALL]",
1064     ENGINE_CMD_FLAG_STRING},
1065
1066 #ifdef IMPLEMENT_DIGEST
1067    {DEVCRYPTO_CMD_DIGESTS,
1068     "DIGESTS",
1069     "either ALL, NONE, or a comma-separated list of digests to enable [default=ALL]",
1070     ENGINE_CMD_FLAG_STRING},
1071 #endif
1072
1073    {DEVCRYPTO_CMD_DUMP_INFO,
1074     "DUMP_INFO",
1075     "dump info about each algorithm to stderr; use 'openssl engine -pre DUMP_INFO devcrypto'",
1076     ENGINE_CMD_FLAG_NO_INPUT},
1077
1078    {0, NULL, NULL, 0}
1079 };
1080
1081 static int devcrypto_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void))
1082 {
1083     int *new_list;
1084     switch (cmd) {
1085 #ifdef CIOCGSESSINFO
1086     case DEVCRYPTO_CMD_USE_SOFTDRIVERS:
1087         switch (i) {
1088         case DEVCRYPTO_REQUIRE_ACCELERATED:
1089         case DEVCRYPTO_USE_SOFTWARE:
1090         case DEVCRYPTO_REJECT_SOFTWARE:
1091             break;
1092         default:
1093             fprintf(stderr, "devcrypto: invalid value (%ld) for USE_SOFTDRIVERS\n", i);
1094             return 0;
1095         }
1096         if (use_softdrivers == i)
1097             return 1;
1098         use_softdrivers = i;
1099 #ifdef IMPLEMENT_DIGEST
1100         rebuild_known_digest_nids(e);
1101 #endif
1102         rebuild_known_cipher_nids(e);
1103         return 1;
1104 #endif /* CIOCGSESSINFO */
1105
1106     case DEVCRYPTO_CMD_CIPHERS:
1107         if (p == NULL)
1108             return 1;
1109         if (strcasecmp((const char *)p, "ALL") == 0) {
1110             devcrypto_select_all_ciphers(selected_ciphers);
1111         } else if (strcasecmp((const char*)p, "NONE") == 0) {
1112             memset(selected_ciphers, 0, sizeof(selected_ciphers));
1113         } else {
1114             new_list=OPENSSL_zalloc(sizeof(selected_ciphers));
1115             if (!CONF_parse_list(p, ',', 1, cryptodev_select_cipher_cb, new_list)) {
1116                 OPENSSL_free(new_list);
1117                 return 0;
1118             }
1119             memcpy(selected_ciphers, new_list, sizeof(selected_ciphers));
1120             OPENSSL_free(new_list);
1121         }
1122         rebuild_known_cipher_nids(e);
1123         return 1;
1124
1125 #ifdef IMPLEMENT_DIGEST
1126     case DEVCRYPTO_CMD_DIGESTS:
1127         if (p == NULL)
1128             return 1;
1129         if (strcasecmp((const char *)p, "ALL") == 0) {
1130             devcrypto_select_all_digests(selected_digests);
1131         } else if (strcasecmp((const char*)p, "NONE") == 0) {
1132             memset(selected_digests, 0, sizeof(selected_digests));
1133         } else {
1134             new_list=OPENSSL_zalloc(sizeof(selected_digests));
1135             if (!CONF_parse_list(p, ',', 1, cryptodev_select_digest_cb, new_list)) {
1136                 OPENSSL_free(new_list);
1137                 return 0;
1138             }
1139             memcpy(selected_digests, new_list, sizeof(selected_digests));
1140             OPENSSL_free(new_list);
1141         }
1142         rebuild_known_digest_nids(e);
1143         return 1;
1144 #endif /* IMPLEMENT_DIGEST */
1145
1146     case DEVCRYPTO_CMD_DUMP_INFO:
1147         dump_cipher_info();
1148 #ifdef IMPLEMENT_DIGEST
1149         dump_digest_info();
1150 #endif
1151         return 1;
1152
1153     default:
1154         break;
1155     }
1156     return 0;
1157 }
1158
1159 /******************************************************************************
1160  *
1161  * LOAD / UNLOAD
1162  *
1163  *****/
1164
1165 /*
1166  * Opens /dev/crypto
1167  */
1168 static int open_devcrypto(void)
1169 {
1170     if (cfd >= 0)
1171         return 1;
1172
1173     if ((cfd = open("/dev/crypto", O_RDWR, 0)) < 0) {
1174 #ifndef ENGINE_DEVCRYPTO_DEBUG
1175         if (errno != ENOENT)
1176 #endif
1177             fprintf(stderr, "Could not open /dev/crypto: %s\n", strerror(errno));
1178         return 0;
1179     }
1180
1181     return 1;
1182 }
1183
1184 static int close_devcrypto(void)
1185 {
1186     int ret;
1187
1188     if (cfd < 0)
1189         return 1;
1190     ret = close(cfd);
1191     cfd = -1;
1192     if (ret != 0) {
1193         fprintf(stderr, "Error closing /dev/crypto: %s\n", strerror(errno));
1194         return 0;
1195     }
1196     return 1;
1197 }
1198
1199 static int devcrypto_unload(ENGINE *e)
1200 {
1201     destroy_all_cipher_methods();
1202 #ifdef IMPLEMENT_DIGEST
1203     destroy_all_digest_methods();
1204 #endif
1205
1206     close_devcrypto();
1207
1208     return 1;
1209 }
1210
1211 static int bind_devcrypto(ENGINE *e) {
1212
1213     if (!ENGINE_set_id(e, engine_devcrypto_id)
1214         || !ENGINE_set_name(e, "/dev/crypto engine")
1215         || !ENGINE_set_destroy_function(e, devcrypto_unload)
1216         || !ENGINE_set_cmd_defns(e, devcrypto_cmds)
1217         || !ENGINE_set_ctrl_function(e, devcrypto_ctrl))
1218         return 0;
1219
1220     prepare_cipher_methods();
1221 #ifdef IMPLEMENT_DIGEST
1222     prepare_digest_methods();
1223 #endif
1224
1225     return (ENGINE_set_ciphers(e, devcrypto_ciphers)
1226 #ifdef IMPLEMENT_DIGEST
1227         && ENGINE_set_digests(e, devcrypto_digests)
1228 #endif
1229 /*
1230  * Asymmetric ciphers aren't well supported with /dev/crypto.  Among the BSD
1231  * implementations, it seems to only exist in FreeBSD, and regarding the
1232  * parameters in its crypt_kop, the manual crypto(4) has this to say:
1233  *
1234  *    The semantics of these arguments are currently undocumented.
1235  *
1236  * Reading through the FreeBSD source code doesn't give much more than
1237  * their CRK_MOD_EXP implementation for ubsec.
1238  *
1239  * It doesn't look much better with cryptodev-linux.  They have the crypt_kop
1240  * structure as well as the command (CRK_*) in cryptodev.h, but no support
1241  * seems to be implemented at all for the moment.
1242  *
1243  * At the time of writing, it seems impossible to write proper support for
1244  * FreeBSD's asym features without some very deep knowledge and access to
1245  * specific kernel modules.
1246  *
1247  * /Richard Levitte, 2017-05-11
1248  */
1249 #if 0
1250 # ifndef OPENSSL_NO_RSA
1251         && ENGINE_set_RSA(e, devcrypto_rsa)
1252 # endif
1253 # ifndef OPENSSL_NO_DSA
1254         && ENGINE_set_DSA(e, devcrypto_dsa)
1255 # endif
1256 # ifndef OPENSSL_NO_DH
1257         && ENGINE_set_DH(e, devcrypto_dh)
1258 # endif
1259 # ifndef OPENSSL_NO_EC
1260         && ENGINE_set_EC(e, devcrypto_ec)
1261 # endif
1262 #endif
1263         );
1264 }
1265
1266 #ifdef OPENSSL_NO_DYNAMIC_ENGINE
1267 /*
1268  * In case this engine is built into libcrypto, then it doesn't offer any
1269  * ability to be dynamically loadable.
1270  */
1271 void engine_load_devcrypto_int(void)
1272 {
1273     ENGINE *e = NULL;
1274
1275     if (!open_devcrypto())
1276         return;
1277
1278     if ((e = ENGINE_new()) == NULL
1279         || !bind_devcrypto(e)) {
1280         close_devcrypto();
1281         ENGINE_free(e);
1282         return;
1283     }
1284
1285     ENGINE_add(e);
1286     ENGINE_free(e);          /* Loose our local reference */
1287     ERR_clear_error();
1288 }
1289
1290 #else
1291
1292 static int bind_helper(ENGINE *e, const char *id)
1293 {
1294     if ((id && (strcmp(id, engine_devcrypto_id) != 0))
1295         || !open_devcrypto())
1296         return 0;
1297     if (!bind_devcrypto(e)) {
1298         close_devcrypto();
1299         return 0;
1300     }
1301     return 1;
1302 }
1303
1304 IMPLEMENT_DYNAMIC_CHECK_FN()
1305 IMPLEMENT_DYNAMIC_BIND_FN(bind_helper)
1306
1307 #endif