b1e87096fdbc2f4b7d6c86b54af8b4320d05e79c
[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, (void *)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 blocksize;
633     int digestlen;
634     int devcryptoid;
635 } digest_data[] = {
636 #ifndef OPENSSL_NO_MD5
637     { NID_md5, /* MD5_CBLOCK */ 64, 16, CRYPTO_MD5 },
638 #endif
639     { NID_sha1, SHA_CBLOCK, 20, CRYPTO_SHA1 },
640 #ifndef OPENSSL_NO_RMD160
641 # if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_RIPEMD160)
642     { NID_ripemd160, /* RIPEMD160_CBLOCK */ 64, 20, CRYPTO_RIPEMD160 },
643 # endif
644 #endif
645 #if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_224)
646     { NID_sha224, SHA256_CBLOCK, 224 / 8, CRYPTO_SHA2_224 },
647 #endif
648 #if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_256)
649     { NID_sha256, SHA256_CBLOCK, 256 / 8, CRYPTO_SHA2_256 },
650 #endif
651 #if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_384)
652     { NID_sha384, SHA512_CBLOCK, 384 / 8, CRYPTO_SHA2_384 },
653 #endif
654 #if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_512)
655     { NID_sha512, SHA512_CBLOCK, 512 / 8, CRYPTO_SHA2_512 },
656 #endif
657 };
658
659 static size_t find_digest_data_index(int nid)
660 {
661     size_t i;
662
663     for (i = 0; i < OSSL_NELEM(digest_data); i++)
664         if (nid == digest_data[i].nid)
665             return i;
666     return (size_t)-1;
667 }
668
669 static size_t get_digest_data_index(int nid)
670 {
671     size_t i = find_digest_data_index(nid);
672
673     if (i != (size_t)-1)
674         return i;
675
676     /*
677      * Code further down must make sure that only NIDs in the table above
678      * are used.  If any other NID reaches this function, there's a grave
679      * coding error further down.
680      */
681     assert("Code that never should be reached" == NULL);
682     return -1;
683 }
684
685 static const struct digest_data_st *get_digest_data(int nid)
686 {
687     return &digest_data[get_digest_data_index(nid)];
688 }
689
690 /*
691  * Following are the five necessary functions to map OpenSSL functionality
692  * with cryptodev: init, update, final, cleanup, and copy.
693  */
694
695 static int digest_init(EVP_MD_CTX *ctx)
696 {
697     struct digest_ctx *digest_ctx =
698         (struct digest_ctx *)EVP_MD_CTX_md_data(ctx);
699     const struct digest_data_st *digest_d =
700         get_digest_data(EVP_MD_CTX_type(ctx));
701
702     digest_ctx->init_called = 1;
703
704     memset(&digest_ctx->sess, 0, sizeof(digest_ctx->sess));
705     digest_ctx->sess.mac = digest_d->devcryptoid;
706     if (ioctl(cfd, CIOCGSESSION, &digest_ctx->sess) < 0) {
707         SYSerr(SYS_F_IOCTL, errno);
708         return 0;
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_input_blocksize(known_digest_methods[i],
900                                                 digest_data[i].blocksize)
901             || !EVP_MD_meth_set_result_size(known_digest_methods[i],
902                                             digest_data[i].digestlen)
903             || !EVP_MD_meth_set_init(known_digest_methods[i], digest_init)
904             || !EVP_MD_meth_set_update(known_digest_methods[i], digest_update)
905             || !EVP_MD_meth_set_final(known_digest_methods[i], digest_final)
906             || !EVP_MD_meth_set_copy(known_digest_methods[i], digest_copy)
907             || !EVP_MD_meth_set_cleanup(known_digest_methods[i], digest_cleanup)
908             || !EVP_MD_meth_set_app_datasize(known_digest_methods[i],
909                                              sizeof(struct digest_ctx))) {
910             digest_driver_info[i].status = DEVCRYPTO_STATUS_FAILURE;
911             EVP_MD_meth_free(known_digest_methods[i]);
912             known_digest_methods[i] = NULL;
913             goto finish;
914         }
915         digest_driver_info[i].status = DEVCRYPTO_STATUS_USABLE;
916 finish:
917         ioctl(cfd, CIOCFSESSION, &sess1.ses);
918         if (sess2.ses != 0)
919             ioctl(cfd, CIOCFSESSION, &sess2.ses);
920         if (devcrypto_test_digest(i))
921             known_digest_nids[known_digest_nids_amount++] = digest_data[i].nid;
922     }
923 }
924
925 static const EVP_MD *get_digest_method(int nid)
926 {
927     size_t i = get_digest_data_index(nid);
928
929     if (i == (size_t)-1)
930         return NULL;
931     return known_digest_methods[i];
932 }
933
934 static int get_digest_nids(const int **nids)
935 {
936     *nids = known_digest_nids;
937     return known_digest_nids_amount;
938 }
939
940 static void destroy_digest_method(int nid)
941 {
942     size_t i = get_digest_data_index(nid);
943
944     EVP_MD_meth_free(known_digest_methods[i]);
945     known_digest_methods[i] = NULL;
946 }
947
948 static void destroy_all_digest_methods(void)
949 {
950     size_t i;
951
952     for (i = 0; i < OSSL_NELEM(digest_data); i++) {
953         destroy_digest_method(digest_data[i].nid);
954         OPENSSL_free(digest_driver_info[i].driver_name);
955         digest_driver_info[i].driver_name = NULL;
956     }
957 }
958
959 static int devcrypto_digests(ENGINE *e, const EVP_MD **digest,
960                              const int **nids, int nid)
961 {
962     if (digest == NULL)
963         return get_digest_nids(nids);
964
965     *digest = get_digest_method(nid);
966
967     return *digest != NULL;
968 }
969
970 static void devcrypto_select_all_digests(int *digest_list)
971 {
972     size_t i;
973
974     for (i = 0; i < OSSL_NELEM(digest_data); i++)
975         digest_list[i] = 1;
976 }
977
978 static int cryptodev_select_digest_cb(const char *str, int len, void *usr)
979 {
980     int *digest_list = (int *)usr;
981     char *name;
982     const EVP_MD *EVP;
983     size_t i;
984
985     if (len == 0)
986         return 1;
987     if (usr == NULL || (name = OPENSSL_strndup(str, len)) == NULL)
988         return 0;
989     EVP = EVP_get_digestbyname(name);
990     if (EVP == NULL)
991         fprintf(stderr, "devcrypto: unknown digest %s\n", name);
992     else if ((i = find_digest_data_index(EVP_MD_type(EVP))) != (size_t)-1)
993         digest_list[i] = 1;
994     else
995         fprintf(stderr, "devcrypto: digest %s not available\n", name);
996     OPENSSL_free(name);
997     return 1;
998 }
999
1000 static void dump_digest_info(void)
1001 {
1002     size_t i;
1003     const char *name;
1004
1005     fprintf (stderr, "Information about digests supported by the /dev/crypto"
1006              " engine:\n");
1007 #ifndef CIOCGSESSINFO
1008     fprintf(stderr, "CIOCGSESSINFO (session info call) unavailable\n");
1009 #endif
1010
1011     for (i = 0; i < OSSL_NELEM(digest_data); i++) {
1012         name = OBJ_nid2sn(digest_data[i].nid);
1013         fprintf (stderr, "Digest %s, NID=%d, /dev/crypto info: id=%d, driver=%s",
1014                  name ? name : "unknown", digest_data[i].nid,
1015                  digest_data[i].devcryptoid,
1016                  digest_driver_info[i].driver_name ? digest_driver_info[i].driver_name : "unknown");
1017         if (digest_driver_info[i].status == DEVCRYPTO_STATUS_NO_CIOCGSESSION) {
1018             fprintf (stderr, ". CIOCGSESSION (session open) failed\n");
1019             continue;
1020         }
1021         if (digest_driver_info[i].accelerated == DEVCRYPTO_ACCELERATED)
1022             fprintf(stderr, " (hw accelerated)");
1023         else if (digest_driver_info[i].accelerated == DEVCRYPTO_NOT_ACCELERATED)
1024             fprintf(stderr, " (software)");
1025         else
1026             fprintf(stderr, " (acceleration status unknown)");
1027         if (cipher_driver_info[i].status == DEVCRYPTO_STATUS_FAILURE)
1028             fprintf (stderr, ". Cipher setup failed\n");
1029         else if (digest_driver_info[i].status == DEVCRYPTO_STATUS_NO_CIOCCPHASH)
1030             fprintf(stderr, ", CIOCCPHASH failed\n");
1031         else
1032             fprintf(stderr, ", CIOCCPHASH capable\n");
1033     }
1034     fprintf(stderr, "\n");
1035 }
1036
1037 #endif
1038
1039 /******************************************************************************
1040  *
1041  * CONTROL COMMANDS
1042  *
1043  *****/
1044
1045 #define DEVCRYPTO_CMD_USE_SOFTDRIVERS ENGINE_CMD_BASE
1046 #define DEVCRYPTO_CMD_CIPHERS (ENGINE_CMD_BASE + 1)
1047 #define DEVCRYPTO_CMD_DIGESTS (ENGINE_CMD_BASE + 2)
1048 #define DEVCRYPTO_CMD_DUMP_INFO (ENGINE_CMD_BASE + 3)
1049
1050 static const ENGINE_CMD_DEFN devcrypto_cmds[] = {
1051 #ifdef CIOCGSESSINFO
1052    {DEVCRYPTO_CMD_USE_SOFTDRIVERS,
1053     "USE_SOFTDRIVERS",
1054     "specifies whether to use software (not accelerated) drivers ("
1055         OPENSSL_MSTR(DEVCRYPTO_REQUIRE_ACCELERATED) "=use only accelerated drivers, "
1056         OPENSSL_MSTR(DEVCRYPTO_USE_SOFTWARE) "=allow all drivers, "
1057         OPENSSL_MSTR(DEVCRYPTO_REJECT_SOFTWARE)
1058         "=use if acceleration can't be determined) [default="
1059         OPENSSL_MSTR(DEVCRYPTO_DEFAULT_USE_SOFTDRIVERS) "]",
1060     ENGINE_CMD_FLAG_NUMERIC},
1061 #endif
1062
1063    {DEVCRYPTO_CMD_CIPHERS,
1064     "CIPHERS",
1065     "either ALL, NONE, or a comma-separated list of ciphers to enable [default=ALL]",
1066     ENGINE_CMD_FLAG_STRING},
1067
1068 #ifdef IMPLEMENT_DIGEST
1069    {DEVCRYPTO_CMD_DIGESTS,
1070     "DIGESTS",
1071     "either ALL, NONE, or a comma-separated list of digests to enable [default=ALL]",
1072     ENGINE_CMD_FLAG_STRING},
1073 #endif
1074
1075    {DEVCRYPTO_CMD_DUMP_INFO,
1076     "DUMP_INFO",
1077     "dump info about each algorithm to stderr; use 'openssl engine -pre DUMP_INFO devcrypto'",
1078     ENGINE_CMD_FLAG_NO_INPUT},
1079
1080    {0, NULL, NULL, 0}
1081 };
1082
1083 static int devcrypto_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void))
1084 {
1085     int *new_list;
1086     switch (cmd) {
1087 #ifdef CIOCGSESSINFO
1088     case DEVCRYPTO_CMD_USE_SOFTDRIVERS:
1089         switch (i) {
1090         case DEVCRYPTO_REQUIRE_ACCELERATED:
1091         case DEVCRYPTO_USE_SOFTWARE:
1092         case DEVCRYPTO_REJECT_SOFTWARE:
1093             break;
1094         default:
1095             fprintf(stderr, "devcrypto: invalid value (%ld) for USE_SOFTDRIVERS\n", i);
1096             return 0;
1097         }
1098         if (use_softdrivers == i)
1099             return 1;
1100         use_softdrivers = i;
1101 #ifdef IMPLEMENT_DIGEST
1102         rebuild_known_digest_nids(e);
1103 #endif
1104         rebuild_known_cipher_nids(e);
1105         return 1;
1106 #endif /* CIOCGSESSINFO */
1107
1108     case DEVCRYPTO_CMD_CIPHERS:
1109         if (p == NULL)
1110             return 1;
1111         if (strcasecmp((const char *)p, "ALL") == 0) {
1112             devcrypto_select_all_ciphers(selected_ciphers);
1113         } else if (strcasecmp((const char*)p, "NONE") == 0) {
1114             memset(selected_ciphers, 0, sizeof(selected_ciphers));
1115         } else {
1116             new_list=OPENSSL_zalloc(sizeof(selected_ciphers));
1117             if (!CONF_parse_list(p, ',', 1, cryptodev_select_cipher_cb, new_list)) {
1118                 OPENSSL_free(new_list);
1119                 return 0;
1120             }
1121             memcpy(selected_ciphers, new_list, sizeof(selected_ciphers));
1122             OPENSSL_free(new_list);
1123         }
1124         rebuild_known_cipher_nids(e);
1125         return 1;
1126
1127 #ifdef IMPLEMENT_DIGEST
1128     case DEVCRYPTO_CMD_DIGESTS:
1129         if (p == NULL)
1130             return 1;
1131         if (strcasecmp((const char *)p, "ALL") == 0) {
1132             devcrypto_select_all_digests(selected_digests);
1133         } else if (strcasecmp((const char*)p, "NONE") == 0) {
1134             memset(selected_digests, 0, sizeof(selected_digests));
1135         } else {
1136             new_list=OPENSSL_zalloc(sizeof(selected_digests));
1137             if (!CONF_parse_list(p, ',', 1, cryptodev_select_digest_cb, new_list)) {
1138                 OPENSSL_free(new_list);
1139                 return 0;
1140             }
1141             memcpy(selected_digests, new_list, sizeof(selected_digests));
1142             OPENSSL_free(new_list);
1143         }
1144         rebuild_known_digest_nids(e);
1145         return 1;
1146 #endif /* IMPLEMENT_DIGEST */
1147
1148     case DEVCRYPTO_CMD_DUMP_INFO:
1149         dump_cipher_info();
1150 #ifdef IMPLEMENT_DIGEST
1151         dump_digest_info();
1152 #endif
1153         return 1;
1154
1155     default:
1156         break;
1157     }
1158     return 0;
1159 }
1160
1161 /******************************************************************************
1162  *
1163  * LOAD / UNLOAD
1164  *
1165  *****/
1166
1167 /*
1168  * Opens /dev/crypto
1169  */
1170 static int open_devcrypto(void)
1171 {
1172     if (cfd >= 0)
1173         return 1;
1174
1175     if ((cfd = open("/dev/crypto", O_RDWR, 0)) < 0) {
1176 #ifndef ENGINE_DEVCRYPTO_DEBUG
1177         if (errno != ENOENT)
1178 #endif
1179             fprintf(stderr, "Could not open /dev/crypto: %s\n", strerror(errno));
1180         return 0;
1181     }
1182
1183     return 1;
1184 }
1185
1186 static int close_devcrypto(void)
1187 {
1188     int ret;
1189
1190     if (cfd < 0)
1191         return 1;
1192     ret = close(cfd);
1193     cfd = -1;
1194     if (ret != 0) {
1195         fprintf(stderr, "Error closing /dev/crypto: %s\n", strerror(errno));
1196         return 0;
1197     }
1198     return 1;
1199 }
1200
1201 static int devcrypto_unload(ENGINE *e)
1202 {
1203     destroy_all_cipher_methods();
1204 #ifdef IMPLEMENT_DIGEST
1205     destroy_all_digest_methods();
1206 #endif
1207
1208     close_devcrypto();
1209
1210     return 1;
1211 }
1212
1213 static int bind_devcrypto(ENGINE *e) {
1214
1215     if (!ENGINE_set_id(e, engine_devcrypto_id)
1216         || !ENGINE_set_name(e, "/dev/crypto engine")
1217         || !ENGINE_set_destroy_function(e, devcrypto_unload)
1218         || !ENGINE_set_cmd_defns(e, devcrypto_cmds)
1219         || !ENGINE_set_ctrl_function(e, devcrypto_ctrl))
1220         return 0;
1221
1222     prepare_cipher_methods();
1223 #ifdef IMPLEMENT_DIGEST
1224     prepare_digest_methods();
1225 #endif
1226
1227     return (ENGINE_set_ciphers(e, devcrypto_ciphers)
1228 #ifdef IMPLEMENT_DIGEST
1229         && ENGINE_set_digests(e, devcrypto_digests)
1230 #endif
1231 /*
1232  * Asymmetric ciphers aren't well supported with /dev/crypto.  Among the BSD
1233  * implementations, it seems to only exist in FreeBSD, and regarding the
1234  * parameters in its crypt_kop, the manual crypto(4) has this to say:
1235  *
1236  *    The semantics of these arguments are currently undocumented.
1237  *
1238  * Reading through the FreeBSD source code doesn't give much more than
1239  * their CRK_MOD_EXP implementation for ubsec.
1240  *
1241  * It doesn't look much better with cryptodev-linux.  They have the crypt_kop
1242  * structure as well as the command (CRK_*) in cryptodev.h, but no support
1243  * seems to be implemented at all for the moment.
1244  *
1245  * At the time of writing, it seems impossible to write proper support for
1246  * FreeBSD's asym features without some very deep knowledge and access to
1247  * specific kernel modules.
1248  *
1249  * /Richard Levitte, 2017-05-11
1250  */
1251 #if 0
1252 # ifndef OPENSSL_NO_RSA
1253         && ENGINE_set_RSA(e, devcrypto_rsa)
1254 # endif
1255 # ifndef OPENSSL_NO_DSA
1256         && ENGINE_set_DSA(e, devcrypto_dsa)
1257 # endif
1258 # ifndef OPENSSL_NO_DH
1259         && ENGINE_set_DH(e, devcrypto_dh)
1260 # endif
1261 # ifndef OPENSSL_NO_EC
1262         && ENGINE_set_EC(e, devcrypto_ec)
1263 # endif
1264 #endif
1265         );
1266 }
1267
1268 #ifdef OPENSSL_NO_DYNAMIC_ENGINE
1269 /*
1270  * In case this engine is built into libcrypto, then it doesn't offer any
1271  * ability to be dynamically loadable.
1272  */
1273 void engine_load_devcrypto_int(void)
1274 {
1275     ENGINE *e = NULL;
1276
1277     if (!open_devcrypto())
1278         return;
1279
1280     if ((e = ENGINE_new()) == NULL
1281         || !bind_devcrypto(e)) {
1282         close_devcrypto();
1283         ENGINE_free(e);
1284         return;
1285     }
1286
1287     ENGINE_add(e);
1288     ENGINE_free(e);          /* Loose our local reference */
1289     ERR_clear_error();
1290 }
1291
1292 #else
1293
1294 static int bind_helper(ENGINE *e, const char *id)
1295 {
1296     if ((id && (strcmp(id, engine_devcrypto_id) != 0))
1297         || !open_devcrypto())
1298         return 0;
1299     if (!bind_devcrypto(e)) {
1300         close_devcrypto();
1301         return 0;
1302     }
1303     return 1;
1304 }
1305
1306 IMPLEMENT_DYNAMIC_CHECK_FN()
1307 IMPLEMENT_DYNAMIC_BIND_FN(bind_helper)
1308
1309 #endif