1 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 From: Eneas U de Queiroz <cote2004-github@yahoo.com>
3 Date: Tue, 6 Nov 2018 10:57:03 -0200
4 Subject: e_devcrypto: make the /dev/crypto engine dynamic
6 Engine has been moved from crypto/engine/eng_devcrypto.c to
9 Signed-off-by: Eneas U de Queiroz <cote2004-github@yahoo.com>
11 --- a/crypto/engine/build.info
12 +++ b/crypto/engine/build.info
13 @@ -6,6 +6,3 @@ SOURCE[../../libcrypto]=\
14 tb_cipher.c tb_digest.c tb_pkmeth.c tb_asnmth.c tb_eckey.c \
15 eng_openssl.c eng_cnf.c eng_dyn.c \
17 -IF[{- !$disabled{devcryptoeng} -}]
18 - SOURCE[../../libcrypto]=eng_devcrypto.c
22 @@ -328,18 +328,6 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_engine_
23 engine_load_openssl_int();
26 -# ifndef OPENSSL_NO_DEVCRYPTOENG
27 -static CRYPTO_ONCE engine_devcrypto = CRYPTO_ONCE_STATIC_INIT;
28 -DEFINE_RUN_ONCE_STATIC(ossl_init_engine_devcrypto)
30 -# ifdef OPENSSL_INIT_DEBUG
31 - fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_devcrypto: "
32 - "engine_load_devcrypto_int()\n");
34 - engine_load_devcrypto_int();
39 # ifndef OPENSSL_NO_RDRAND
40 static CRYPTO_ONCE engine_rdrand = CRYPTO_ONCE_STATIC_INIT;
41 @@ -364,6 +352,18 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_engine_
44 # ifndef OPENSSL_NO_STATIC_ENGINE
45 +# ifndef OPENSSL_NO_DEVCRYPTOENG
46 +static CRYPTO_ONCE engine_devcrypto = CRYPTO_ONCE_STATIC_INIT;
47 +DEFINE_RUN_ONCE_STATIC(ossl_init_engine_devcrypto)
49 +# ifdef OPENSSL_INIT_DEBUG
50 + fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_devcrypto: "
51 + "engine_load_devcrypto_int()\n");
53 + engine_load_devcrypto_int();
57 # if !defined(OPENSSL_NO_HW) && !defined(OPENSSL_NO_HW_PADLOCK)
58 static CRYPTO_ONCE engine_padlock = CRYPTO_ONCE_STATIC_INIT;
59 DEFINE_RUN_ONCE_STATIC(ossl_init_engine_padlock)
60 @@ -704,11 +704,6 @@ int OPENSSL_init_crypto(uint64_t opts, c
61 if ((opts & OPENSSL_INIT_ENGINE_OPENSSL)
62 && !RUN_ONCE(&engine_openssl, ossl_init_engine_openssl))
64 -# if !defined(OPENSSL_NO_HW) && !defined(OPENSSL_NO_DEVCRYPTOENG)
65 - if ((opts & OPENSSL_INIT_ENGINE_CRYPTODEV)
66 - && !RUN_ONCE(&engine_devcrypto, ossl_init_engine_devcrypto))
69 # ifndef OPENSSL_NO_RDRAND
70 if ((opts & OPENSSL_INIT_ENGINE_RDRAND)
71 && !RUN_ONCE(&engine_rdrand, ossl_init_engine_rdrand))
72 @@ -718,6 +713,11 @@ int OPENSSL_init_crypto(uint64_t opts, c
73 && !RUN_ONCE(&engine_dynamic, ossl_init_engine_dynamic))
75 # ifndef OPENSSL_NO_STATIC_ENGINE
76 +# ifndef OPENSSL_NO_DEVCRYPTOENG
77 + if ((opts & OPENSSL_INIT_ENGINE_CRYPTODEV)
78 + && !RUN_ONCE(&engine_devcrypto, ossl_init_engine_devcrypto))
81 # if !defined(OPENSSL_NO_HW) && !defined(OPENSSL_NO_HW_PADLOCK)
82 if ((opts & OPENSSL_INIT_ENGINE_PADLOCK)
83 && !RUN_ONCE(&engine_padlock, ossl_init_engine_padlock))
84 --- a/engines/build.info
85 +++ b/engines/build.info
86 @@ -11,6 +11,9 @@ IF[{- !$disabled{"engine"} -}]
87 IF[{- !$disabled{afalgeng} -}]
88 SOURCE[../libcrypto]=e_afalg.c
90 + IF[{- !$disabled{"devcryptoeng"} -}]
91 + SOURCE[../libcrypto]=e_devcrypto.c
94 IF[{- !$disabled{hw} && !$disabled{'hw-padlock'} -}]
96 @@ -30,6 +33,12 @@ IF[{- !$disabled{"engine"} -}]
97 DEPEND[afalg]=../libcrypto
98 INCLUDE[afalg]= ../include
100 + IF[{- !$disabled{"devcryptoeng"} -}]
102 + SOURCE[devcrypto]=e_devcrypto.c
103 + DEPEND[devcrypto]=../libcrypto
104 + INCLUDE[devcrypto]=../include
107 ENGINES_NO_INST=ossltest dasync
108 SOURCE[dasync]=e_dasync.c
109 --- a/crypto/engine/eng_devcrypto.c
113 - * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
115 - * Licensed under the OpenSSL license (the "License"). You may not use
116 - * this file except in compliance with the License. You can obtain a copy
117 - * in the file LICENSE in the source distribution or at
118 - * https://www.openssl.org/source/license.html
123 -#include <sys/types.h>
124 -#include <sys/stat.h>
126 -#include <sys/ioctl.h>
130 -#include <openssl/conf.h>
131 -#include <openssl/evp.h>
132 -#include <openssl/err.h>
133 -#include <openssl/engine.h>
134 -#include <openssl/objects.h>
135 -#include <crypto/cryptodev.h>
137 -#include "crypto/engine.h"
139 -/* #define ENGINE_DEVCRYPTO_DEBUG */
141 -#if CRYPTO_ALGORITHM_MIN < CRYPTO_ALGORITHM_MAX
142 -# define CHECK_BSD_STYLE_MACROS
146 - * ONE global file descriptor for all sessions. This allows operations
147 - * such as digest session data copying (see digest_copy()), but is also
148 - * saner... why re-open /dev/crypto for every session?
151 -#define DEVCRYPTO_REQUIRE_ACCELERATED 0 /* require confirmation of acceleration */
152 -#define DEVCRYPTO_USE_SOFTWARE 1 /* allow software drivers */
153 -#define DEVCRYPTO_REJECT_SOFTWARE 2 /* only disallow confirmed software drivers */
155 -#define DEVCRYPTO_DEFAULT_USE_SOFDTRIVERS DEVCRYPTO_REJECT_SOFTWARE
156 -static int use_softdrivers = DEVCRYPTO_DEFAULT_USE_SOFDTRIVERS;
159 - * cipher/digest status & acceleration definitions
160 - * Make sure the defaults are set to 0
162 -struct driver_info_st {
163 - enum devcrypto_status_t {
164 - DEVCRYPTO_STATUS_FAILURE = -3, /* unusable for other reason */
165 - DEVCRYPTO_STATUS_NO_CIOCCPHASH = -2, /* hash state copy not supported */
166 - DEVCRYPTO_STATUS_NO_CIOCGSESSION = -1, /* session open failed */
167 - DEVCRYPTO_STATUS_UNKNOWN = 0, /* not tested yet */
168 - DEVCRYPTO_STATUS_USABLE = 1 /* algo can be used */
171 - enum devcrypto_accelerated_t {
172 - DEVCRYPTO_NOT_ACCELERATED = -1, /* software implemented */
173 - DEVCRYPTO_ACCELERATION_UNKNOWN = 0, /* acceleration support unkown */
174 - DEVCRYPTO_ACCELERATED = 1 /* hardware accelerated */
180 -static int clean_devcrypto_session(struct session_op *sess) {
181 - if (ioctl(cfd, CIOCFSESSION, &sess->ses) < 0) {
182 - SYSerr(SYS_F_IOCTL, errno);
185 - memset(sess, 0, sizeof(struct session_op));
189 -/******************************************************************************
193 - * Because they all do the same basic operation, we have only one set of
194 - * method functions for them all to share, and a mapping table between
195 - * NIDs and cryptodev IDs, with all the necessary size data.
200 - struct session_op sess;
201 - int op; /* COP_ENCRYPT or COP_DECRYPT */
202 - unsigned long mode; /* EVP_CIPH_*_MODE */
204 - /* to handle ctr mode being a stream cipher */
205 - unsigned char partial[EVP_MAX_BLOCK_LENGTH];
206 - unsigned int blocksize, num;
209 -static const struct cipher_data_st {
217 -#ifndef OPENSSL_NO_DES
218 - { NID_des_cbc, 8, 8, 8, EVP_CIPH_CBC_MODE, CRYPTO_DES_CBC },
219 - { NID_des_ede3_cbc, 8, 24, 8, EVP_CIPH_CBC_MODE, CRYPTO_3DES_CBC },
221 -#ifndef OPENSSL_NO_BF
222 - { NID_bf_cbc, 8, 16, 8, EVP_CIPH_CBC_MODE, CRYPTO_BLF_CBC },
224 -#ifndef OPENSSL_NO_CAST
225 - { NID_cast5_cbc, 8, 16, 8, EVP_CIPH_CBC_MODE, CRYPTO_CAST_CBC },
227 - { NID_aes_128_cbc, 16, 128 / 8, 16, EVP_CIPH_CBC_MODE, CRYPTO_AES_CBC },
228 - { NID_aes_192_cbc, 16, 192 / 8, 16, EVP_CIPH_CBC_MODE, CRYPTO_AES_CBC },
229 - { NID_aes_256_cbc, 16, 256 / 8, 16, EVP_CIPH_CBC_MODE, CRYPTO_AES_CBC },
230 -#ifndef OPENSSL_NO_RC4
231 - { NID_rc4, 1, 16, 0, EVP_CIPH_STREAM_CIPHER, CRYPTO_ARC4 },
233 -#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_AES_CTR)
234 - { NID_aes_128_ctr, 16, 128 / 8, 16, EVP_CIPH_CTR_MODE, CRYPTO_AES_CTR },
235 - { NID_aes_192_ctr, 16, 192 / 8, 16, EVP_CIPH_CTR_MODE, CRYPTO_AES_CTR },
236 - { NID_aes_256_ctr, 16, 256 / 8, 16, EVP_CIPH_CTR_MODE, CRYPTO_AES_CTR },
238 -#if 0 /* Not yet supported */
239 - { NID_aes_128_xts, 16, 128 / 8 * 2, 16, EVP_CIPH_XTS_MODE, CRYPTO_AES_XTS },
240 - { NID_aes_256_xts, 16, 256 / 8 * 2, 16, EVP_CIPH_XTS_MODE, CRYPTO_AES_XTS },
242 -#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_AES_ECB)
243 - { NID_aes_128_ecb, 16, 128 / 8, 0, EVP_CIPH_ECB_MODE, CRYPTO_AES_ECB },
244 - { NID_aes_192_ecb, 16, 192 / 8, 0, EVP_CIPH_ECB_MODE, CRYPTO_AES_ECB },
245 - { NID_aes_256_ecb, 16, 256 / 8, 0, EVP_CIPH_ECB_MODE, CRYPTO_AES_ECB },
247 -#if 0 /* Not yet supported */
248 - { NID_aes_128_gcm, 16, 128 / 8, 16, EVP_CIPH_GCM_MODE, CRYPTO_AES_GCM },
249 - { NID_aes_192_gcm, 16, 192 / 8, 16, EVP_CIPH_GCM_MODE, CRYPTO_AES_GCM },
250 - { NID_aes_256_gcm, 16, 256 / 8, 16, EVP_CIPH_GCM_MODE, CRYPTO_AES_GCM },
252 -#ifndef OPENSSL_NO_CAMELLIA
253 - { NID_camellia_128_cbc, 16, 128 / 8, 16, EVP_CIPH_CBC_MODE,
254 - CRYPTO_CAMELLIA_CBC },
255 - { NID_camellia_192_cbc, 16, 192 / 8, 16, EVP_CIPH_CBC_MODE,
256 - CRYPTO_CAMELLIA_CBC },
257 - { NID_camellia_256_cbc, 16, 256 / 8, 16, EVP_CIPH_CBC_MODE,
258 - CRYPTO_CAMELLIA_CBC },
262 -static size_t find_cipher_data_index(int nid)
266 - for (i = 0; i < OSSL_NELEM(cipher_data); i++)
267 - if (nid == cipher_data[i].nid)
272 -static size_t get_cipher_data_index(int nid)
274 - size_t i = find_cipher_data_index(nid);
276 - if (i != (size_t)-1)
280 - * Code further down must make sure that only NIDs in the table above
281 - * are used. If any other NID reaches this function, there's a grave
282 - * coding error further down.
284 - assert("Code that never should be reached" == NULL);
288 -static const struct cipher_data_st *get_cipher_data(int nid)
290 - return &cipher_data[get_cipher_data_index(nid)];
294 - * Following are the three necessary functions to map OpenSSL functionality
298 -static int cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
299 - const unsigned char *iv, int enc)
301 - struct cipher_ctx *cipher_ctx =
302 - (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
303 - const struct cipher_data_st *cipher_d =
304 - get_cipher_data(EVP_CIPHER_CTX_nid(ctx));
306 - /* cleanup a previous session */
307 - if (cipher_ctx->sess.ses != 0 &&
308 - clean_devcrypto_session(&cipher_ctx->sess) == 0)
311 - cipher_ctx->sess.cipher = cipher_d->devcryptoid;
312 - cipher_ctx->sess.keylen = cipher_d->keylen;
313 - cipher_ctx->sess.key = (void *)key;
314 - cipher_ctx->op = enc ? COP_ENCRYPT : COP_DECRYPT;
315 - cipher_ctx->mode = cipher_d->flags & EVP_CIPH_MODE;
316 - cipher_ctx->blocksize = cipher_d->blocksize;
317 - if (ioctl(cfd, CIOCGSESSION, &cipher_ctx->sess) < 0) {
318 - SYSerr(SYS_F_IOCTL, errno);
325 -static int cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
326 - const unsigned char *in, size_t inl)
328 - struct cipher_ctx *cipher_ctx =
329 - (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
330 - struct crypt_op cryp;
331 - unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx);
332 -#if !defined(COP_FLAG_WRITE_IV)
333 - unsigned char saved_iv[EVP_MAX_IV_LENGTH];
334 - const unsigned char *ivptr;
335 - size_t nblocks, ivlen;
338 - memset(&cryp, 0, sizeof(cryp));
339 - cryp.ses = cipher_ctx->sess.ses;
341 - cryp.src = (void *)in;
342 - cryp.dst = (void *)out;
343 - cryp.iv = (void *)iv;
344 - cryp.op = cipher_ctx->op;
345 -#if !defined(COP_FLAG_WRITE_IV)
348 - ivlen = EVP_CIPHER_CTX_iv_length(ctx);
350 - switch (cipher_ctx->mode) {
351 - case EVP_CIPH_CBC_MODE:
352 - assert(inl >= ivlen);
353 - if (!EVP_CIPHER_CTX_encrypting(ctx)) {
354 - ivptr = in + inl - ivlen;
355 - memcpy(saved_iv, ivptr, ivlen);
359 - case EVP_CIPH_CTR_MODE:
362 - default: /* should not happen */
366 - cryp.flags = COP_FLAG_WRITE_IV;
369 - if (ioctl(cfd, CIOCCRYPT, &cryp) < 0) {
370 - SYSerr(SYS_F_IOCTL, errno);
374 -#if !defined(COP_FLAG_WRITE_IV)
376 - switch (cipher_ctx->mode) {
377 - case EVP_CIPH_CBC_MODE:
378 - assert(inl >= ivlen);
379 - if (EVP_CIPHER_CTX_encrypting(ctx))
380 - ivptr = out + inl - ivlen;
384 - memcpy(iv, ivptr, ivlen);
387 - case EVP_CIPH_CTR_MODE:
388 - nblocks = (inl + cipher_ctx->blocksize - 1)
389 - / cipher_ctx->blocksize;
392 - nblocks += iv[ivlen];
393 - iv[ivlen] = (uint8_t) nblocks;
398 - default: /* should not happen */
406 -static int ctr_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
407 - const unsigned char *in, size_t inl)
409 - struct cipher_ctx *cipher_ctx =
410 - (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
411 - size_t nblocks, len;
413 - /* initial partial block */
414 - while (cipher_ctx->num && inl) {
415 - (*out++) = *(in++) ^ cipher_ctx->partial[cipher_ctx->num];
417 - cipher_ctx->num = (cipher_ctx->num + 1) % cipher_ctx->blocksize;
421 - if (inl > (unsigned int) cipher_ctx->blocksize) {
422 - nblocks = inl/cipher_ctx->blocksize;
423 - len = nblocks * cipher_ctx->blocksize;
424 - if (cipher_do_cipher(ctx, out, in, len) < 1)
431 - /* final partial block */
433 - memset(cipher_ctx->partial, 0, cipher_ctx->blocksize);
434 - if (cipher_do_cipher(ctx, cipher_ctx->partial, cipher_ctx->partial,
435 - cipher_ctx->blocksize) < 1)
438 - out[cipher_ctx->num] = in[cipher_ctx->num]
439 - ^ cipher_ctx->partial[cipher_ctx->num];
447 -static int cipher_ctrl(EVP_CIPHER_CTX *ctx, int type, int p1, void* p2)
449 - struct cipher_ctx *cipher_ctx =
450 - (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
451 - EVP_CIPHER_CTX *to_ctx = (EVP_CIPHER_CTX *)p2;
452 - struct cipher_ctx *to_cipher_ctx;
455 - case EVP_CTRL_COPY:
456 - if (cipher_ctx == NULL)
458 - /* when copying the context, a new session needs to be initialized */
460 - (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(to_ctx);
461 - memset(&to_cipher_ctx->sess, 0, sizeof(to_cipher_ctx->sess));
462 - return cipher_init(to_ctx, cipher_ctx->sess.key, EVP_CIPHER_CTX_iv(ctx),
463 - (cipher_ctx->op == COP_ENCRYPT));
465 - case EVP_CTRL_INIT:
466 - memset(&cipher_ctx->sess, 0, sizeof(cipher_ctx->sess));
476 -static int cipher_cleanup(EVP_CIPHER_CTX *ctx)
478 - struct cipher_ctx *cipher_ctx =
479 - (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
481 - return clean_devcrypto_session(&cipher_ctx->sess);
485 - * Keep tables of known nids, associated methods, selected ciphers, and driver
487 - * Note that known_cipher_nids[] isn't necessarily indexed the same way as
488 - * cipher_data[] above, which the other tables are.
490 -static int known_cipher_nids[OSSL_NELEM(cipher_data)];
491 -static int known_cipher_nids_amount = -1; /* -1 indicates not yet initialised */
492 -static EVP_CIPHER *known_cipher_methods[OSSL_NELEM(cipher_data)] = { NULL, };
493 -static int selected_ciphers[OSSL_NELEM(cipher_data)];
494 -static struct driver_info_st cipher_driver_info[OSSL_NELEM(cipher_data)];
497 -static int devcrypto_test_cipher(size_t cipher_data_index)
499 - return (cipher_driver_info[cipher_data_index].status == DEVCRYPTO_STATUS_USABLE
500 - && selected_ciphers[cipher_data_index] == 1
501 - && (cipher_driver_info[cipher_data_index].accelerated
502 - == DEVCRYPTO_ACCELERATED
503 - || use_softdrivers == DEVCRYPTO_USE_SOFTWARE
504 - || (cipher_driver_info[cipher_data_index].accelerated
505 - != DEVCRYPTO_NOT_ACCELERATED
506 - && use_softdrivers == DEVCRYPTO_REJECT_SOFTWARE)));
509 -static void prepare_cipher_methods(void)
512 - struct session_op sess;
513 - unsigned long cipher_mode;
514 -#ifdef CIOCGSESSINFO
515 - struct session_info_op siop;
518 - memset(&cipher_driver_info, 0, sizeof(cipher_driver_info));
520 - memset(&sess, 0, sizeof(sess));
521 - sess.key = (void *)"01234567890123456789012345678901234567890123456789";
523 - for (i = 0, known_cipher_nids_amount = 0;
524 - i < OSSL_NELEM(cipher_data); i++) {
526 - selected_ciphers[i] = 1;
528 - * Check that the cipher is usable
530 - sess.cipher = cipher_data[i].devcryptoid;
531 - sess.keylen = cipher_data[i].keylen;
532 - if (ioctl(cfd, CIOCGSESSION, &sess) < 0) {
533 - cipher_driver_info[i].status = DEVCRYPTO_STATUS_NO_CIOCGSESSION;
537 - cipher_mode = cipher_data[i].flags & EVP_CIPH_MODE;
539 - if ((known_cipher_methods[i] =
540 - EVP_CIPHER_meth_new(cipher_data[i].nid,
541 - cipher_mode == EVP_CIPH_CTR_MODE ? 1 :
542 - cipher_data[i].blocksize,
543 - cipher_data[i].keylen)) == NULL
544 - || !EVP_CIPHER_meth_set_iv_length(known_cipher_methods[i],
545 - cipher_data[i].ivlen)
546 - || !EVP_CIPHER_meth_set_flags(known_cipher_methods[i],
547 - cipher_data[i].flags
548 - | EVP_CIPH_CUSTOM_COPY
549 - | EVP_CIPH_CTRL_INIT
550 - | EVP_CIPH_FLAG_DEFAULT_ASN1)
551 - || !EVP_CIPHER_meth_set_init(known_cipher_methods[i], cipher_init)
552 - || !EVP_CIPHER_meth_set_do_cipher(known_cipher_methods[i],
553 - cipher_mode == EVP_CIPH_CTR_MODE ?
556 - || !EVP_CIPHER_meth_set_ctrl(known_cipher_methods[i], cipher_ctrl)
557 - || !EVP_CIPHER_meth_set_cleanup(known_cipher_methods[i],
559 - || !EVP_CIPHER_meth_set_impl_ctx_size(known_cipher_methods[i],
560 - sizeof(struct cipher_ctx))) {
561 - cipher_driver_info[i].status = DEVCRYPTO_STATUS_FAILURE;
562 - EVP_CIPHER_meth_free(known_cipher_methods[i]);
563 - known_cipher_methods[i] = NULL;
565 - cipher_driver_info[i].status = DEVCRYPTO_STATUS_USABLE;
566 -#ifdef CIOCGSESSINFO
567 - siop.ses = sess.ses;
568 - if (ioctl(cfd, CIOCGSESSINFO, &siop) < 0) {
569 - cipher_driver_info[i].accelerated = DEVCRYPTO_ACCELERATION_UNKNOWN;
571 - cipher_driver_info[i].driver_name =
572 - OPENSSL_strndup(siop.cipher_info.cra_driver_name,
573 - CRYPTODEV_MAX_ALG_NAME);
574 - if (!(siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY))
575 - cipher_driver_info[i].accelerated = DEVCRYPTO_NOT_ACCELERATED;
577 - cipher_driver_info[i].accelerated = DEVCRYPTO_ACCELERATED;
579 -#endif /* CIOCGSESSINFO */
581 - ioctl(cfd, CIOCFSESSION, &sess.ses);
582 - if (devcrypto_test_cipher(i)) {
583 - known_cipher_nids[known_cipher_nids_amount++] =
584 - cipher_data[i].nid;
589 -static void rebuild_known_cipher_nids(ENGINE *e)
593 - for (i = 0, known_cipher_nids_amount = 0; i < OSSL_NELEM(cipher_data); i++) {
594 - if (devcrypto_test_cipher(i))
595 - known_cipher_nids[known_cipher_nids_amount++] = cipher_data[i].nid;
597 - ENGINE_unregister_ciphers(e);
598 - ENGINE_register_ciphers(e);
601 -static const EVP_CIPHER *get_cipher_method(int nid)
603 - size_t i = get_cipher_data_index(nid);
605 - if (i == (size_t)-1)
607 - return known_cipher_methods[i];
610 -static int get_cipher_nids(const int **nids)
612 - *nids = known_cipher_nids;
613 - return known_cipher_nids_amount;
616 -static void destroy_cipher_method(int nid)
618 - size_t i = get_cipher_data_index(nid);
620 - EVP_CIPHER_meth_free(known_cipher_methods[i]);
621 - known_cipher_methods[i] = NULL;
624 -static void destroy_all_cipher_methods(void)
628 - for (i = 0; i < OSSL_NELEM(cipher_data); i++) {
629 - destroy_cipher_method(cipher_data[i].nid);
630 - OPENSSL_free(cipher_driver_info[i].driver_name);
631 - cipher_driver_info[i].driver_name = NULL;
635 -static int devcrypto_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
636 - const int **nids, int nid)
638 - if (cipher == NULL)
639 - return get_cipher_nids(nids);
641 - *cipher = get_cipher_method(nid);
643 - return *cipher != NULL;
646 -static void devcrypto_select_all_ciphers(int *cipher_list)
650 - for (i = 0; i < OSSL_NELEM(cipher_data); i++)
651 - cipher_list[i] = 1;
654 -static int cryptodev_select_cipher_cb(const char *str, int len, void *usr)
656 - int *cipher_list = (int *)usr;
658 - const EVP_CIPHER *EVP;
663 - if (usr == NULL || (name = OPENSSL_strndup(str, len)) == NULL)
665 - EVP = EVP_get_cipherbyname(name);
667 - fprintf(stderr, "devcrypto: unknown cipher %s\n", name);
668 - else if ((i = find_cipher_data_index(EVP_CIPHER_nid(EVP))) != (size_t)-1)
669 - cipher_list[i] = 1;
671 - fprintf(stderr, "devcrypto: cipher %s not available\n", name);
672 - OPENSSL_free(name);
676 -static void dump_cipher_info(void)
681 - fprintf (stderr, "Information about ciphers supported by the /dev/crypto"
683 -#ifndef CIOCGSESSINFO
684 - fprintf(stderr, "CIOCGSESSINFO (session info call) unavailable\n");
686 - for (i = 0; i < OSSL_NELEM(cipher_data); i++) {
687 - name = OBJ_nid2sn(cipher_data[i].nid);
688 - fprintf (stderr, "Cipher %s, NID=%d, /dev/crypto info: id=%d, ",
689 - name ? name : "unknown", cipher_data[i].nid,
690 - cipher_data[i].devcryptoid);
691 - if (cipher_driver_info[i].status == DEVCRYPTO_STATUS_NO_CIOCGSESSION ) {
692 - fprintf (stderr, "CIOCGSESSION (session open call) failed\n");
695 - fprintf (stderr, "driver=%s ", cipher_driver_info[i].driver_name ?
696 - cipher_driver_info[i].driver_name : "unknown");
697 - if (cipher_driver_info[i].accelerated == DEVCRYPTO_ACCELERATED)
698 - fprintf(stderr, "(hw accelerated)");
699 - else if (cipher_driver_info[i].accelerated == DEVCRYPTO_NOT_ACCELERATED)
700 - fprintf(stderr, "(software)");
702 - fprintf(stderr, "(acceleration status unknown)");
703 - if (cipher_driver_info[i].status == DEVCRYPTO_STATUS_FAILURE)
704 - fprintf (stderr, ". Cipher setup failed");
705 - fprintf(stderr, "\n");
707 - fprintf(stderr, "\n");
711 - * We only support digests if the cryptodev implementation supports multiple
712 - * data updates and session copying. Otherwise, we would be forced to maintain
713 - * a cache, which is perilous if there's a lot of data coming in (if someone
714 - * wants to checksum an OpenSSL tarball, for example).
716 -#if defined(CIOCCPHASH) && defined(COP_FLAG_UPDATE) && defined(COP_FLAG_FINAL)
717 -#define IMPLEMENT_DIGEST
719 -/******************************************************************************
723 - * Because they all do the same basic operation, we have only one set of
724 - * method functions for them all to share, and a mapping table between
725 - * NIDs and cryptodev IDs, with all the necessary size data.
730 - struct session_op sess;
731 - /* This signals that the init function was called, not that it succeeded. */
733 - unsigned char digest_res[HASH_MAX_LEN];
736 -static const struct digest_data_st {
742 -#ifndef OPENSSL_NO_MD5
743 - { NID_md5, /* MD5_CBLOCK */ 64, 16, CRYPTO_MD5 },
745 - { NID_sha1, SHA_CBLOCK, 20, CRYPTO_SHA1 },
746 -#ifndef OPENSSL_NO_RMD160
747 -# if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_RIPEMD160)
748 - { NID_ripemd160, /* RIPEMD160_CBLOCK */ 64, 20, CRYPTO_RIPEMD160 },
751 -#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_224)
752 - { NID_sha224, SHA256_CBLOCK, 224 / 8, CRYPTO_SHA2_224 },
754 -#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_256)
755 - { NID_sha256, SHA256_CBLOCK, 256 / 8, CRYPTO_SHA2_256 },
757 -#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_384)
758 - { NID_sha384, SHA512_CBLOCK, 384 / 8, CRYPTO_SHA2_384 },
760 -#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_512)
761 - { NID_sha512, SHA512_CBLOCK, 512 / 8, CRYPTO_SHA2_512 },
765 -static size_t find_digest_data_index(int nid)
769 - for (i = 0; i < OSSL_NELEM(digest_data); i++)
770 - if (nid == digest_data[i].nid)
775 -static size_t get_digest_data_index(int nid)
777 - size_t i = find_digest_data_index(nid);
779 - if (i != (size_t)-1)
783 - * Code further down must make sure that only NIDs in the table above
784 - * are used. If any other NID reaches this function, there's a grave
785 - * coding error further down.
787 - assert("Code that never should be reached" == NULL);
791 -static const struct digest_data_st *get_digest_data(int nid)
793 - return &digest_data[get_digest_data_index(nid)];
797 - * Following are the five necessary functions to map OpenSSL functionality
798 - * with cryptodev: init, update, final, cleanup, and copy.
801 -static int digest_init(EVP_MD_CTX *ctx)
803 - struct digest_ctx *digest_ctx =
804 - (struct digest_ctx *)EVP_MD_CTX_md_data(ctx);
805 - const struct digest_data_st *digest_d =
806 - get_digest_data(EVP_MD_CTX_type(ctx));
808 - digest_ctx->init_called = 1;
810 - memset(&digest_ctx->sess, 0, sizeof(digest_ctx->sess));
811 - digest_ctx->sess.mac = digest_d->devcryptoid;
812 - if (ioctl(cfd, CIOCGSESSION, &digest_ctx->sess) < 0) {
813 - SYSerr(SYS_F_IOCTL, errno);
820 -static int digest_op(struct digest_ctx *ctx, const void *src, size_t srclen,
821 - void *res, unsigned int flags)
823 - struct crypt_op cryp;
825 - memset(&cryp, 0, sizeof(cryp));
826 - cryp.ses = ctx->sess.ses;
828 - cryp.src = (void *)src;
831 - cryp.flags = flags;
832 - return ioctl(cfd, CIOCCRYPT, &cryp);
835 -static int digest_update(EVP_MD_CTX *ctx, const void *data, size_t count)
837 - struct digest_ctx *digest_ctx =
838 - (struct digest_ctx *)EVP_MD_CTX_md_data(ctx);
843 - if (digest_ctx == NULL)
846 - if (EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_ONESHOT)) {
847 - if (digest_op(digest_ctx, data, count, digest_ctx->digest_res, 0) >= 0)
849 - } else if (digest_op(digest_ctx, data, count, NULL, COP_FLAG_UPDATE) >= 0) {
853 - SYSerr(SYS_F_IOCTL, errno);
857 -static int digest_final(EVP_MD_CTX *ctx, unsigned char *md)
859 - struct digest_ctx *digest_ctx =
860 - (struct digest_ctx *)EVP_MD_CTX_md_data(ctx);
862 - if (md == NULL || digest_ctx == NULL)
865 - if (EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_ONESHOT)) {
866 - memcpy(md, digest_ctx->digest_res, EVP_MD_CTX_size(ctx));
867 - } else if (digest_op(digest_ctx, NULL, 0, md, COP_FLAG_FINAL) < 0) {
868 - SYSerr(SYS_F_IOCTL, errno);
875 -static int digest_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from)
877 - struct digest_ctx *digest_from =
878 - (struct digest_ctx *)EVP_MD_CTX_md_data(from);
879 - struct digest_ctx *digest_to =
880 - (struct digest_ctx *)EVP_MD_CTX_md_data(to);
881 - struct cphash_op cphash;
883 - if (digest_from == NULL || digest_from->init_called != 1)
886 - if (!digest_init(to)) {
887 - SYSerr(SYS_F_IOCTL, errno);
891 - cphash.src_ses = digest_from->sess.ses;
892 - cphash.dst_ses = digest_to->sess.ses;
893 - if (ioctl(cfd, CIOCCPHASH, &cphash) < 0) {
894 - SYSerr(SYS_F_IOCTL, errno);
900 -static int digest_cleanup(EVP_MD_CTX *ctx)
902 - struct digest_ctx *digest_ctx =
903 - (struct digest_ctx *)EVP_MD_CTX_md_data(ctx);
905 - if (digest_ctx == NULL)
908 - return clean_devcrypto_session(&digest_ctx->sess);
912 - * Keep tables of known nids, associated methods, selected digests, and
914 - * Note that known_digest_nids[] isn't necessarily indexed the same way as
915 - * digest_data[] above, which the other tables are.
917 -static int known_digest_nids[OSSL_NELEM(digest_data)];
918 -static int known_digest_nids_amount = -1; /* -1 indicates not yet initialised */
919 -static EVP_MD *known_digest_methods[OSSL_NELEM(digest_data)] = { NULL, };
920 -static int selected_digests[OSSL_NELEM(digest_data)];
921 -static struct driver_info_st digest_driver_info[OSSL_NELEM(digest_data)];
923 -static int devcrypto_test_digest(size_t digest_data_index)
925 - return (digest_driver_info[digest_data_index].status == DEVCRYPTO_STATUS_USABLE
926 - && selected_digests[digest_data_index] == 1
927 - && (digest_driver_info[digest_data_index].accelerated
928 - == DEVCRYPTO_ACCELERATED
929 - || use_softdrivers == DEVCRYPTO_USE_SOFTWARE
930 - || (digest_driver_info[digest_data_index].accelerated
931 - != DEVCRYPTO_NOT_ACCELERATED
932 - && use_softdrivers == DEVCRYPTO_REJECT_SOFTWARE)));
935 -static void rebuild_known_digest_nids(ENGINE *e)
939 - for (i = 0, known_digest_nids_amount = 0; i < OSSL_NELEM(digest_data); i++) {
940 - if (devcrypto_test_digest(i))
941 - known_digest_nids[known_digest_nids_amount++] = digest_data[i].nid;
943 - ENGINE_unregister_digests(e);
944 - ENGINE_register_digests(e);
947 -static void prepare_digest_methods(void)
950 - struct session_op sess1, sess2;
951 -#ifdef CIOCGSESSINFO
952 - struct session_info_op siop;
954 - struct cphash_op cphash;
956 - memset(&digest_driver_info, 0, sizeof(digest_driver_info));
958 - memset(&sess1, 0, sizeof(sess1));
959 - memset(&sess2, 0, sizeof(sess2));
961 - for (i = 0, known_digest_nids_amount = 0; i < OSSL_NELEM(digest_data);
964 - selected_digests[i] = 1;
967 - * Check that the digest is usable
969 - sess1.mac = digest_data[i].devcryptoid;
971 - if (ioctl(cfd, CIOCGSESSION, &sess1) < 0) {
972 - digest_driver_info[i].status = DEVCRYPTO_STATUS_NO_CIOCGSESSION;
976 -#ifdef CIOCGSESSINFO
977 - /* gather hardware acceleration info from the driver */
978 - siop.ses = sess1.ses;
979 - if (ioctl(cfd, CIOCGSESSINFO, &siop) < 0) {
980 - digest_driver_info[i].accelerated = DEVCRYPTO_ACCELERATION_UNKNOWN;
982 - digest_driver_info[i].driver_name =
983 - OPENSSL_strndup(siop.hash_info.cra_driver_name,
984 - CRYPTODEV_MAX_ALG_NAME);
985 - if (siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY)
986 - digest_driver_info[i].accelerated = DEVCRYPTO_ACCELERATED;
988 - digest_driver_info[i].accelerated = DEVCRYPTO_NOT_ACCELERATED;
992 - /* digest must be capable of hash state copy */
993 - sess2.mac = sess1.mac;
994 - if (ioctl(cfd, CIOCGSESSION, &sess2) < 0) {
995 - digest_driver_info[i].status = DEVCRYPTO_STATUS_FAILURE;
998 - cphash.src_ses = sess1.ses;
999 - cphash.dst_ses = sess2.ses;
1000 - if (ioctl(cfd, CIOCCPHASH, &cphash) < 0) {
1001 - digest_driver_info[i].status = DEVCRYPTO_STATUS_NO_CIOCCPHASH;
1004 - if ((known_digest_methods[i] = EVP_MD_meth_new(digest_data[i].nid,
1005 - NID_undef)) == NULL
1006 - || !EVP_MD_meth_set_input_blocksize(known_digest_methods[i],
1007 - digest_data[i].blocksize)
1008 - || !EVP_MD_meth_set_result_size(known_digest_methods[i],
1009 - digest_data[i].digestlen)
1010 - || !EVP_MD_meth_set_init(known_digest_methods[i], digest_init)
1011 - || !EVP_MD_meth_set_update(known_digest_methods[i], digest_update)
1012 - || !EVP_MD_meth_set_final(known_digest_methods[i], digest_final)
1013 - || !EVP_MD_meth_set_copy(known_digest_methods[i], digest_copy)
1014 - || !EVP_MD_meth_set_cleanup(known_digest_methods[i], digest_cleanup)
1015 - || !EVP_MD_meth_set_app_datasize(known_digest_methods[i],
1016 - sizeof(struct digest_ctx))) {
1017 - digest_driver_info[i].status = DEVCRYPTO_STATUS_FAILURE;
1018 - EVP_MD_meth_free(known_digest_methods[i]);
1019 - known_digest_methods[i] = NULL;
1022 - digest_driver_info[i].status = DEVCRYPTO_STATUS_USABLE;
1024 - ioctl(cfd, CIOCFSESSION, &sess1.ses);
1025 - if (sess2.ses != 0)
1026 - ioctl(cfd, CIOCFSESSION, &sess2.ses);
1027 - if (devcrypto_test_digest(i))
1028 - known_digest_nids[known_digest_nids_amount++] = digest_data[i].nid;
1032 -static const EVP_MD *get_digest_method(int nid)
1034 - size_t i = get_digest_data_index(nid);
1036 - if (i == (size_t)-1)
1038 - return known_digest_methods[i];
1041 -static int get_digest_nids(const int **nids)
1043 - *nids = known_digest_nids;
1044 - return known_digest_nids_amount;
1047 -static void destroy_digest_method(int nid)
1049 - size_t i = get_digest_data_index(nid);
1051 - EVP_MD_meth_free(known_digest_methods[i]);
1052 - known_digest_methods[i] = NULL;
1055 -static void destroy_all_digest_methods(void)
1059 - for (i = 0; i < OSSL_NELEM(digest_data); i++) {
1060 - destroy_digest_method(digest_data[i].nid);
1061 - OPENSSL_free(digest_driver_info[i].driver_name);
1062 - digest_driver_info[i].driver_name = NULL;
1066 -static int devcrypto_digests(ENGINE *e, const EVP_MD **digest,
1067 - const int **nids, int nid)
1069 - if (digest == NULL)
1070 - return get_digest_nids(nids);
1072 - *digest = get_digest_method(nid);
1074 - return *digest != NULL;
1077 -static void devcrypto_select_all_digests(int *digest_list)
1081 - for (i = 0; i < OSSL_NELEM(digest_data); i++)
1082 - digest_list[i] = 1;
1085 -static int cryptodev_select_digest_cb(const char *str, int len, void *usr)
1087 - int *digest_list = (int *)usr;
1089 - const EVP_MD *EVP;
1094 - if (usr == NULL || (name = OPENSSL_strndup(str, len)) == NULL)
1096 - EVP = EVP_get_digestbyname(name);
1098 - fprintf(stderr, "devcrypto: unknown digest %s\n", name);
1099 - else if ((i = find_digest_data_index(EVP_MD_type(EVP))) != (size_t)-1)
1100 - digest_list[i] = 1;
1102 - fprintf(stderr, "devcrypto: digest %s not available\n", name);
1103 - OPENSSL_free(name);
1107 -static void dump_digest_info(void)
1112 - fprintf (stderr, "Information about digests supported by the /dev/crypto"
1114 -#ifndef CIOCGSESSINFO
1115 - fprintf(stderr, "CIOCGSESSINFO (session info call) unavailable\n");
1118 - for (i = 0; i < OSSL_NELEM(digest_data); i++) {
1119 - name = OBJ_nid2sn(digest_data[i].nid);
1120 - fprintf (stderr, "Digest %s, NID=%d, /dev/crypto info: id=%d, driver=%s",
1121 - name ? name : "unknown", digest_data[i].nid,
1122 - digest_data[i].devcryptoid,
1123 - digest_driver_info[i].driver_name ? digest_driver_info[i].driver_name : "unknown");
1124 - if (digest_driver_info[i].status == DEVCRYPTO_STATUS_NO_CIOCGSESSION) {
1125 - fprintf (stderr, ". CIOCGSESSION (session open) failed\n");
1128 - if (digest_driver_info[i].accelerated == DEVCRYPTO_ACCELERATED)
1129 - fprintf(stderr, " (hw accelerated)");
1130 - else if (digest_driver_info[i].accelerated == DEVCRYPTO_NOT_ACCELERATED)
1131 - fprintf(stderr, " (software)");
1133 - fprintf(stderr, " (acceleration status unknown)");
1134 - if (cipher_driver_info[i].status == DEVCRYPTO_STATUS_FAILURE)
1135 - fprintf (stderr, ". Cipher setup failed\n");
1136 - else if (digest_driver_info[i].status == DEVCRYPTO_STATUS_NO_CIOCCPHASH)
1137 - fprintf(stderr, ", CIOCCPHASH failed\n");
1139 - fprintf(stderr, ", CIOCCPHASH capable\n");
1141 - fprintf(stderr, "\n");
1146 -/******************************************************************************
1148 - * CONTROL COMMANDS
1152 -#define DEVCRYPTO_CMD_USE_SOFTDRIVERS ENGINE_CMD_BASE
1153 -#define DEVCRYPTO_CMD_CIPHERS (ENGINE_CMD_BASE + 1)
1154 -#define DEVCRYPTO_CMD_DIGESTS (ENGINE_CMD_BASE + 2)
1155 -#define DEVCRYPTO_CMD_DUMP_INFO (ENGINE_CMD_BASE + 3)
1157 -/* Helper macros for CPP string composition */
1158 -#ifndef OPENSSL_MSTR
1159 -# define OPENSSL_MSTR_HELPER(x) #x
1160 -# define OPENSSL_MSTR(x) OPENSSL_MSTR_HELPER(x)
1163 -static const ENGINE_CMD_DEFN devcrypto_cmds[] = {
1164 -#ifdef CIOCGSESSINFO
1165 - {DEVCRYPTO_CMD_USE_SOFTDRIVERS,
1166 - "USE_SOFTDRIVERS",
1167 - "specifies whether to use software (not accelerated) drivers ("
1168 - OPENSSL_MSTR(DEVCRYPTO_REQUIRE_ACCELERATED) "=use only accelerated drivers, "
1169 - OPENSSL_MSTR(DEVCRYPTO_USE_SOFTWARE) "=allow all drivers, "
1170 - OPENSSL_MSTR(DEVCRYPTO_REJECT_SOFTWARE)
1171 - "=use if acceleration can't be determined) [default="
1172 - OPENSSL_MSTR(DEVCRYPTO_DEFAULT_USE_SOFDTRIVERS) "]",
1173 - ENGINE_CMD_FLAG_NUMERIC},
1176 - {DEVCRYPTO_CMD_CIPHERS,
1178 - "either ALL, NONE, or a comma-separated list of ciphers to enable [default=ALL]",
1179 - ENGINE_CMD_FLAG_STRING},
1181 -#ifdef IMPLEMENT_DIGEST
1182 - {DEVCRYPTO_CMD_DIGESTS,
1184 - "either ALL, NONE, or a comma-separated list of digests to enable [default=ALL]",
1185 - ENGINE_CMD_FLAG_STRING},
1188 - {DEVCRYPTO_CMD_DUMP_INFO,
1190 - "dump info about each algorithm to stderr; use 'openssl engine -pre DUMP_INFO devcrypto'",
1191 - ENGINE_CMD_FLAG_NO_INPUT},
1193 - {0, NULL, NULL, 0}
1196 -static int devcrypto_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void))
1200 -#ifdef CIOCGSESSINFO
1201 - case DEVCRYPTO_CMD_USE_SOFTDRIVERS:
1203 - case DEVCRYPTO_REQUIRE_ACCELERATED:
1204 - case DEVCRYPTO_USE_SOFTWARE:
1205 - case DEVCRYPTO_REJECT_SOFTWARE:
1208 - fprintf(stderr, "devcrypto: invalid value (%ld) for USE_SOFTDRIVERS\n", i);
1211 - if (use_softdrivers == i)
1213 - use_softdrivers = i;
1214 -#ifdef IMPLEMENT_DIGEST
1215 - rebuild_known_digest_nids(e);
1217 - rebuild_known_cipher_nids(e);
1219 -#endif /* CIOCGSESSINFO */
1221 - case DEVCRYPTO_CMD_CIPHERS:
1224 - if (strcasecmp((const char *)p, "ALL") == 0) {
1225 - devcrypto_select_all_ciphers(selected_ciphers);
1226 - } else if (strcasecmp((const char*)p, "NONE") == 0) {
1227 - memset(selected_ciphers, 0, sizeof(selected_ciphers));
1229 - new_list=OPENSSL_zalloc(sizeof(selected_ciphers));
1230 - if (!CONF_parse_list(p, ',', 1, cryptodev_select_cipher_cb, new_list)) {
1231 - OPENSSL_free(new_list);
1234 - memcpy(selected_ciphers, new_list, sizeof(selected_ciphers));
1235 - OPENSSL_free(new_list);
1237 - rebuild_known_cipher_nids(e);
1240 -#ifdef IMPLEMENT_DIGEST
1241 - case DEVCRYPTO_CMD_DIGESTS:
1244 - if (strcasecmp((const char *)p, "ALL") == 0) {
1245 - devcrypto_select_all_digests(selected_digests);
1246 - } else if (strcasecmp((const char*)p, "NONE") == 0) {
1247 - memset(selected_digests, 0, sizeof(selected_digests));
1249 - new_list=OPENSSL_zalloc(sizeof(selected_digests));
1250 - if (!CONF_parse_list(p, ',', 1, cryptodev_select_digest_cb, new_list)) {
1251 - OPENSSL_free(new_list);
1254 - memcpy(selected_digests, new_list, sizeof(selected_digests));
1255 - OPENSSL_free(new_list);
1257 - rebuild_known_digest_nids(e);
1259 -#endif /* IMPLEMENT_DIGEST */
1261 - case DEVCRYPTO_CMD_DUMP_INFO:
1262 - dump_cipher_info();
1263 -#ifdef IMPLEMENT_DIGEST
1264 - dump_digest_info();
1274 -/******************************************************************************
1280 -static int devcrypto_unload(ENGINE *e)
1282 - destroy_all_cipher_methods();
1283 -#ifdef IMPLEMENT_DIGEST
1284 - destroy_all_digest_methods();
1292 - * This engine is always built into libcrypto, so it doesn't offer any
1293 - * ability to be dynamically loadable.
1295 -void engine_load_devcrypto_int()
1300 - if ((fd = open("/dev/crypto", O_RDWR, 0)) < 0) {
1301 -#ifndef ENGINE_DEVCRYPTO_DEBUG
1302 - if (errno != ENOENT)
1304 - fprintf(stderr, "Could not open /dev/crypto: %s\n", strerror(errno));
1309 - if (ioctl(fd, CRIOGET, &cfd) < 0) {
1310 - fprintf(stderr, "Could not create crypto fd: %s\n", strerror(errno));
1320 - if ((e = ENGINE_new()) == NULL
1321 - || !ENGINE_set_destroy_function(e, devcrypto_unload)) {
1324 - * We know that devcrypto_unload() won't be called when one of the
1325 - * above two calls have failed, so we close cfd explicitly here to
1326 - * avoid leaking resources.
1332 - prepare_cipher_methods();
1333 -#ifdef IMPLEMENT_DIGEST
1334 - prepare_digest_methods();
1337 - if (!ENGINE_set_id(e, "devcrypto")
1338 - || !ENGINE_set_name(e, "/dev/crypto engine")
1339 - || !ENGINE_set_cmd_defns(e, devcrypto_cmds)
1340 - || !ENGINE_set_ctrl_function(e, devcrypto_ctrl)
1343 - * Asymmetric ciphers aren't well supported with /dev/crypto. Among the BSD
1344 - * implementations, it seems to only exist in FreeBSD, and regarding the
1345 - * parameters in its crypt_kop, the manual crypto(4) has this to say:
1347 - * The semantics of these arguments are currently undocumented.
1349 - * Reading through the FreeBSD source code doesn't give much more than
1350 - * their CRK_MOD_EXP implementation for ubsec.
1352 - * It doesn't look much better with cryptodev-linux. They have the crypt_kop
1353 - * structure as well as the command (CRK_*) in cryptodev.h, but no support
1354 - * seems to be implemented at all for the moment.
1356 - * At the time of writing, it seems impossible to write proper support for
1357 - * FreeBSD's asym features without some very deep knowledge and access to
1358 - * specific kernel modules.
1360 - * /Richard Levitte, 2017-05-11
1363 -# ifndef OPENSSL_NO_RSA
1364 - || !ENGINE_set_RSA(e, devcrypto_rsa)
1366 -# ifndef OPENSSL_NO_DSA
1367 - || !ENGINE_set_DSA(e, devcrypto_dsa)
1369 -# ifndef OPENSSL_NO_DH
1370 - || !ENGINE_set_DH(e, devcrypto_dh)
1372 -# ifndef OPENSSL_NO_EC
1373 - || !ENGINE_set_EC(e, devcrypto_ec)
1376 - || !ENGINE_set_ciphers(e, devcrypto_ciphers)
1377 -#ifdef IMPLEMENT_DIGEST
1378 - || !ENGINE_set_digests(e, devcrypto_digests)
1386 - ENGINE_free(e); /* Loose our local reference */
1387 - ERR_clear_error();
1390 +++ b/engines/e_devcrypto.c
1393 + * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
1395 + * Licensed under the OpenSSL license (the "License"). You may not use
1396 + * this file except in compliance with the License. You can obtain a copy
1397 + * in the file LICENSE in the source distribution or at
1398 + * https://www.openssl.org/source/license.html
1401 +#include "../e_os.h"
1402 +#include <string.h>
1403 +#include <sys/types.h>
1404 +#include <sys/stat.h>
1406 +#include <sys/ioctl.h>
1407 +#include <unistd.h>
1408 +#include <assert.h>
1410 +#include <openssl/conf.h>
1411 +#include <openssl/evp.h>
1412 +#include <openssl/err.h>
1413 +#include <openssl/engine.h>
1414 +#include <openssl/objects.h>
1415 +#include <crypto/cryptodev.h>
1417 +#include "crypto/engine.h"
1419 +/* #define ENGINE_DEVCRYPTO_DEBUG */
1421 +#if CRYPTO_ALGORITHM_MIN < CRYPTO_ALGORITHM_MAX
1422 +# define CHECK_BSD_STYLE_MACROS
1425 +#define engine_devcrypto_id "devcrypto"
1428 + * ONE global file descriptor for all sessions. This allows operations
1429 + * such as digest session data copying (see digest_copy()), but is also
1430 + * saner... why re-open /dev/crypto for every session?
1432 +static int cfd = -1;
1433 +#define DEVCRYPTO_REQUIRE_ACCELERATED 0 /* require confirmation of acceleration */
1434 +#define DEVCRYPTO_USE_SOFTWARE 1 /* allow software drivers */
1435 +#define DEVCRYPTO_REJECT_SOFTWARE 2 /* only disallow confirmed software drivers */
1437 +#define DEVCRYPTO_DEFAULT_USE_SOFTDRIVERS DEVCRYPTO_REJECT_SOFTWARE
1438 +static int use_softdrivers = DEVCRYPTO_DEFAULT_USE_SOFTDRIVERS;
1441 + * cipher/digest status & acceleration definitions
1442 + * Make sure the defaults are set to 0
1444 +struct driver_info_st {
1445 + enum devcrypto_status_t {
1446 + DEVCRYPTO_STATUS_FAILURE = -3, /* unusable for other reason */
1447 + DEVCRYPTO_STATUS_NO_CIOCCPHASH = -2, /* hash state copy not supported */
1448 + DEVCRYPTO_STATUS_NO_CIOCGSESSION = -1, /* session open failed */
1449 + DEVCRYPTO_STATUS_UNKNOWN = 0, /* not tested yet */
1450 + DEVCRYPTO_STATUS_USABLE = 1 /* algo can be used */
1453 + enum devcrypto_accelerated_t {
1454 + DEVCRYPTO_NOT_ACCELERATED = -1, /* software implemented */
1455 + DEVCRYPTO_ACCELERATION_UNKNOWN = 0, /* acceleration support unkown */
1456 + DEVCRYPTO_ACCELERATED = 1 /* hardware accelerated */
1459 + char *driver_name;
1462 +static int clean_devcrypto_session(struct session_op *sess) {
1463 + if (ioctl(cfd, CIOCFSESSION, &sess->ses) < 0) {
1464 + SYSerr(SYS_F_IOCTL, errno);
1467 + memset(sess, 0, sizeof(struct session_op));
1471 +/******************************************************************************
1475 + * Because they all do the same basic operation, we have only one set of
1476 + * method functions for them all to share, and a mapping table between
1477 + * NIDs and cryptodev IDs, with all the necessary size data.
1481 +struct cipher_ctx {
1482 + struct session_op sess;
1483 + int op; /* COP_ENCRYPT or COP_DECRYPT */
1484 + unsigned long mode; /* EVP_CIPH_*_MODE */
1486 + /* to handle ctr mode being a stream cipher */
1487 + unsigned char partial[EVP_MAX_BLOCK_LENGTH];
1488 + unsigned int blocksize, num;
1491 +static const struct cipher_data_st {
1498 +} cipher_data[] = {
1499 +#ifndef OPENSSL_NO_DES
1500 + { NID_des_cbc, 8, 8, 8, EVP_CIPH_CBC_MODE, CRYPTO_DES_CBC },
1501 + { NID_des_ede3_cbc, 8, 24, 8, EVP_CIPH_CBC_MODE, CRYPTO_3DES_CBC },
1503 +#ifndef OPENSSL_NO_BF
1504 + { NID_bf_cbc, 8, 16, 8, EVP_CIPH_CBC_MODE, CRYPTO_BLF_CBC },
1506 +#ifndef OPENSSL_NO_CAST
1507 + { NID_cast5_cbc, 8, 16, 8, EVP_CIPH_CBC_MODE, CRYPTO_CAST_CBC },
1509 + { NID_aes_128_cbc, 16, 128 / 8, 16, EVP_CIPH_CBC_MODE, CRYPTO_AES_CBC },
1510 + { NID_aes_192_cbc, 16, 192 / 8, 16, EVP_CIPH_CBC_MODE, CRYPTO_AES_CBC },
1511 + { NID_aes_256_cbc, 16, 256 / 8, 16, EVP_CIPH_CBC_MODE, CRYPTO_AES_CBC },
1512 +#ifndef OPENSSL_NO_RC4
1513 + { NID_rc4, 1, 16, 0, EVP_CIPH_STREAM_CIPHER, CRYPTO_ARC4 },
1515 +#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_AES_CTR)
1516 + { NID_aes_128_ctr, 16, 128 / 8, 16, EVP_CIPH_CTR_MODE, CRYPTO_AES_CTR },
1517 + { NID_aes_192_ctr, 16, 192 / 8, 16, EVP_CIPH_CTR_MODE, CRYPTO_AES_CTR },
1518 + { NID_aes_256_ctr, 16, 256 / 8, 16, EVP_CIPH_CTR_MODE, CRYPTO_AES_CTR },
1520 +#if 0 /* Not yet supported */
1521 + { NID_aes_128_xts, 16, 128 / 8 * 2, 16, EVP_CIPH_XTS_MODE, CRYPTO_AES_XTS },
1522 + { NID_aes_256_xts, 16, 256 / 8 * 2, 16, EVP_CIPH_XTS_MODE, CRYPTO_AES_XTS },
1524 +#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_AES_ECB)
1525 + { NID_aes_128_ecb, 16, 128 / 8, 0, EVP_CIPH_ECB_MODE, CRYPTO_AES_ECB },
1526 + { NID_aes_192_ecb, 16, 192 / 8, 0, EVP_CIPH_ECB_MODE, CRYPTO_AES_ECB },
1527 + { NID_aes_256_ecb, 16, 256 / 8, 0, EVP_CIPH_ECB_MODE, CRYPTO_AES_ECB },
1529 +#if 0 /* Not yet supported */
1530 + { NID_aes_128_gcm, 16, 128 / 8, 16, EVP_CIPH_GCM_MODE, CRYPTO_AES_GCM },
1531 + { NID_aes_192_gcm, 16, 192 / 8, 16, EVP_CIPH_GCM_MODE, CRYPTO_AES_GCM },
1532 + { NID_aes_256_gcm, 16, 256 / 8, 16, EVP_CIPH_GCM_MODE, CRYPTO_AES_GCM },
1534 +#ifndef OPENSSL_NO_CAMELLIA
1535 + { NID_camellia_128_cbc, 16, 128 / 8, 16, EVP_CIPH_CBC_MODE,
1536 + CRYPTO_CAMELLIA_CBC },
1537 + { NID_camellia_192_cbc, 16, 192 / 8, 16, EVP_CIPH_CBC_MODE,
1538 + CRYPTO_CAMELLIA_CBC },
1539 + { NID_camellia_256_cbc, 16, 256 / 8, 16, EVP_CIPH_CBC_MODE,
1540 + CRYPTO_CAMELLIA_CBC },
1544 +static size_t find_cipher_data_index(int nid)
1548 + for (i = 0; i < OSSL_NELEM(cipher_data); i++)
1549 + if (nid == cipher_data[i].nid)
1551 + return (size_t)-1;
1554 +static size_t get_cipher_data_index(int nid)
1556 + size_t i = find_cipher_data_index(nid);
1558 + if (i != (size_t)-1)
1562 + * Code further down must make sure that only NIDs in the table above
1563 + * are used. If any other NID reaches this function, there's a grave
1564 + * coding error further down.
1566 + assert("Code that never should be reached" == NULL);
1570 +static const struct cipher_data_st *get_cipher_data(int nid)
1572 + return &cipher_data[get_cipher_data_index(nid)];
1576 + * Following are the three necessary functions to map OpenSSL functionality
1580 +static int cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
1581 + const unsigned char *iv, int enc)
1583 + struct cipher_ctx *cipher_ctx =
1584 + (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
1585 + const struct cipher_data_st *cipher_d =
1586 + get_cipher_data(EVP_CIPHER_CTX_nid(ctx));
1588 + /* cleanup a previous session */
1589 + if (cipher_ctx->sess.ses != 0 &&
1590 + clean_devcrypto_session(&cipher_ctx->sess) == 0)
1593 + cipher_ctx->sess.cipher = cipher_d->devcryptoid;
1594 + cipher_ctx->sess.keylen = cipher_d->keylen;
1595 + cipher_ctx->sess.key = (void *)key;
1596 + cipher_ctx->op = enc ? COP_ENCRYPT : COP_DECRYPT;
1597 + cipher_ctx->mode = cipher_d->flags & EVP_CIPH_MODE;
1598 + cipher_ctx->blocksize = cipher_d->blocksize;
1599 + if (ioctl(cfd, CIOCGSESSION, &cipher_ctx->sess) < 0) {
1600 + SYSerr(SYS_F_IOCTL, errno);
1607 +static int cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
1608 + const unsigned char *in, size_t inl)
1610 + struct cipher_ctx *cipher_ctx =
1611 + (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
1612 + struct crypt_op cryp;
1613 + unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx);
1614 +#if !defined(COP_FLAG_WRITE_IV)
1615 + unsigned char saved_iv[EVP_MAX_IV_LENGTH];
1616 + const unsigned char *ivptr;
1617 + size_t nblocks, ivlen;
1620 + memset(&cryp, 0, sizeof(cryp));
1621 + cryp.ses = cipher_ctx->sess.ses;
1623 + cryp.src = (void *)in;
1624 + cryp.dst = (void *)out;
1625 + cryp.iv = (void *)iv;
1626 + cryp.op = cipher_ctx->op;
1627 +#if !defined(COP_FLAG_WRITE_IV)
1630 + ivlen = EVP_CIPHER_CTX_iv_length(ctx);
1632 + switch (cipher_ctx->mode) {
1633 + case EVP_CIPH_CBC_MODE:
1634 + assert(inl >= ivlen);
1635 + if (!EVP_CIPHER_CTX_encrypting(ctx)) {
1636 + ivptr = in + inl - ivlen;
1637 + memcpy(saved_iv, ivptr, ivlen);
1641 + case EVP_CIPH_CTR_MODE:
1644 + default: /* should not happen */
1648 + cryp.flags = COP_FLAG_WRITE_IV;
1651 + if (ioctl(cfd, CIOCCRYPT, &cryp) < 0) {
1652 + SYSerr(SYS_F_IOCTL, errno);
1656 +#if !defined(COP_FLAG_WRITE_IV)
1658 + switch (cipher_ctx->mode) {
1659 + case EVP_CIPH_CBC_MODE:
1660 + assert(inl >= ivlen);
1661 + if (EVP_CIPHER_CTX_encrypting(ctx))
1662 + ivptr = out + inl - ivlen;
1666 + memcpy(iv, ivptr, ivlen);
1669 + case EVP_CIPH_CTR_MODE:
1670 + nblocks = (inl + cipher_ctx->blocksize - 1)
1671 + / cipher_ctx->blocksize;
1674 + nblocks += iv[ivlen];
1675 + iv[ivlen] = (uint8_t) nblocks;
1680 + default: /* should not happen */
1688 +static int ctr_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
1689 + const unsigned char *in, size_t inl)
1691 + struct cipher_ctx *cipher_ctx =
1692 + (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
1693 + size_t nblocks, len;
1695 + /* initial partial block */
1696 + while (cipher_ctx->num && inl) {
1697 + (*out++) = *(in++) ^ cipher_ctx->partial[cipher_ctx->num];
1699 + cipher_ctx->num = (cipher_ctx->num + 1) % cipher_ctx->blocksize;
1703 + if (inl > (unsigned int) cipher_ctx->blocksize) {
1704 + nblocks = inl/cipher_ctx->blocksize;
1705 + len = nblocks * cipher_ctx->blocksize;
1706 + if (cipher_do_cipher(ctx, out, in, len) < 1)
1713 + /* final partial block */
1715 + memset(cipher_ctx->partial, 0, cipher_ctx->blocksize);
1716 + if (cipher_do_cipher(ctx, cipher_ctx->partial, cipher_ctx->partial,
1717 + cipher_ctx->blocksize) < 1)
1720 + out[cipher_ctx->num] = in[cipher_ctx->num]
1721 + ^ cipher_ctx->partial[cipher_ctx->num];
1722 + cipher_ctx->num++;
1729 +static int cipher_ctrl(EVP_CIPHER_CTX *ctx, int type, int p1, void* p2)
1731 + struct cipher_ctx *cipher_ctx =
1732 + (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
1733 + EVP_CIPHER_CTX *to_ctx = (EVP_CIPHER_CTX *)p2;
1734 + struct cipher_ctx *to_cipher_ctx;
1737 + case EVP_CTRL_COPY:
1738 + if (cipher_ctx == NULL)
1740 + /* when copying the context, a new session needs to be initialized */
1742 + (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(to_ctx);
1743 + memset(&to_cipher_ctx->sess, 0, sizeof(to_cipher_ctx->sess));
1744 + return cipher_init(to_ctx, cipher_ctx->sess.key, EVP_CIPHER_CTX_iv(ctx),
1745 + (cipher_ctx->op == COP_ENCRYPT));
1747 + case EVP_CTRL_INIT:
1748 + memset(&cipher_ctx->sess, 0, sizeof(cipher_ctx->sess));
1758 +static int cipher_cleanup(EVP_CIPHER_CTX *ctx)
1760 + struct cipher_ctx *cipher_ctx =
1761 + (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
1763 + return clean_devcrypto_session(&cipher_ctx->sess);
1767 + * Keep tables of known nids, associated methods, selected ciphers, and driver
1769 + * Note that known_cipher_nids[] isn't necessarily indexed the same way as
1770 + * cipher_data[] above, which the other tables are.
1772 +static int known_cipher_nids[OSSL_NELEM(cipher_data)];
1773 +static int known_cipher_nids_amount = -1; /* -1 indicates not yet initialised */
1774 +static EVP_CIPHER *known_cipher_methods[OSSL_NELEM(cipher_data)] = { NULL, };
1775 +static int selected_ciphers[OSSL_NELEM(cipher_data)];
1776 +static struct driver_info_st cipher_driver_info[OSSL_NELEM(cipher_data)];
1779 +static int devcrypto_test_cipher(size_t cipher_data_index)
1781 + return (cipher_driver_info[cipher_data_index].status == DEVCRYPTO_STATUS_USABLE
1782 + && selected_ciphers[cipher_data_index] == 1
1783 + && (cipher_driver_info[cipher_data_index].accelerated
1784 + == DEVCRYPTO_ACCELERATED
1785 + || use_softdrivers == DEVCRYPTO_USE_SOFTWARE
1786 + || (cipher_driver_info[cipher_data_index].accelerated
1787 + != DEVCRYPTO_NOT_ACCELERATED
1788 + && use_softdrivers == DEVCRYPTO_REJECT_SOFTWARE)));
1791 +static void prepare_cipher_methods(void)
1794 + struct session_op sess;
1795 + unsigned long cipher_mode;
1796 +#ifdef CIOCGSESSINFO
1797 + struct session_info_op siop;
1800 + memset(&cipher_driver_info, 0, sizeof(cipher_driver_info));
1802 + memset(&sess, 0, sizeof(sess));
1803 + sess.key = (void *)"01234567890123456789012345678901234567890123456789";
1805 + for (i = 0, known_cipher_nids_amount = 0;
1806 + i < OSSL_NELEM(cipher_data); i++) {
1808 + selected_ciphers[i] = 1;
1810 + * Check that the cipher is usable
1812 + sess.cipher = cipher_data[i].devcryptoid;
1813 + sess.keylen = cipher_data[i].keylen;
1814 + if (ioctl(cfd, CIOCGSESSION, &sess) < 0) {
1815 + cipher_driver_info[i].status = DEVCRYPTO_STATUS_NO_CIOCGSESSION;
1819 + cipher_mode = cipher_data[i].flags & EVP_CIPH_MODE;
1821 + if ((known_cipher_methods[i] =
1822 + EVP_CIPHER_meth_new(cipher_data[i].nid,
1823 + cipher_mode == EVP_CIPH_CTR_MODE ? 1 :
1824 + cipher_data[i].blocksize,
1825 + cipher_data[i].keylen)) == NULL
1826 + || !EVP_CIPHER_meth_set_iv_length(known_cipher_methods[i],
1827 + cipher_data[i].ivlen)
1828 + || !EVP_CIPHER_meth_set_flags(known_cipher_methods[i],
1829 + cipher_data[i].flags
1830 + | EVP_CIPH_CUSTOM_COPY
1831 + | EVP_CIPH_CTRL_INIT
1832 + | EVP_CIPH_FLAG_DEFAULT_ASN1)
1833 + || !EVP_CIPHER_meth_set_init(known_cipher_methods[i], cipher_init)
1834 + || !EVP_CIPHER_meth_set_do_cipher(known_cipher_methods[i],
1835 + cipher_mode == EVP_CIPH_CTR_MODE ?
1838 + || !EVP_CIPHER_meth_set_ctrl(known_cipher_methods[i], cipher_ctrl)
1839 + || !EVP_CIPHER_meth_set_cleanup(known_cipher_methods[i],
1841 + || !EVP_CIPHER_meth_set_impl_ctx_size(known_cipher_methods[i],
1842 + sizeof(struct cipher_ctx))) {
1843 + cipher_driver_info[i].status = DEVCRYPTO_STATUS_FAILURE;
1844 + EVP_CIPHER_meth_free(known_cipher_methods[i]);
1845 + known_cipher_methods[i] = NULL;
1847 + cipher_driver_info[i].status = DEVCRYPTO_STATUS_USABLE;
1848 +#ifdef CIOCGSESSINFO
1849 + siop.ses = sess.ses;
1850 + if (ioctl(cfd, CIOCGSESSINFO, &siop) < 0) {
1851 + cipher_driver_info[i].accelerated = DEVCRYPTO_ACCELERATION_UNKNOWN;
1853 + cipher_driver_info[i].driver_name =
1854 + OPENSSL_strndup(siop.cipher_info.cra_driver_name,
1855 + CRYPTODEV_MAX_ALG_NAME);
1856 + if (!(siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY))
1857 + cipher_driver_info[i].accelerated = DEVCRYPTO_NOT_ACCELERATED;
1859 + cipher_driver_info[i].accelerated = DEVCRYPTO_ACCELERATED;
1861 +#endif /* CIOCGSESSINFO */
1863 + ioctl(cfd, CIOCFSESSION, &sess.ses);
1864 + if (devcrypto_test_cipher(i)) {
1865 + known_cipher_nids[known_cipher_nids_amount++] =
1866 + cipher_data[i].nid;
1871 +static void rebuild_known_cipher_nids(ENGINE *e)
1875 + for (i = 0, known_cipher_nids_amount = 0; i < OSSL_NELEM(cipher_data); i++) {
1876 + if (devcrypto_test_cipher(i))
1877 + known_cipher_nids[known_cipher_nids_amount++] = cipher_data[i].nid;
1879 + ENGINE_unregister_ciphers(e);
1880 + ENGINE_register_ciphers(e);
1883 +static const EVP_CIPHER *get_cipher_method(int nid)
1885 + size_t i = get_cipher_data_index(nid);
1887 + if (i == (size_t)-1)
1889 + return known_cipher_methods[i];
1892 +static int get_cipher_nids(const int **nids)
1894 + *nids = known_cipher_nids;
1895 + return known_cipher_nids_amount;
1898 +static void destroy_cipher_method(int nid)
1900 + size_t i = get_cipher_data_index(nid);
1902 + EVP_CIPHER_meth_free(known_cipher_methods[i]);
1903 + known_cipher_methods[i] = NULL;
1906 +static void destroy_all_cipher_methods(void)
1910 + for (i = 0; i < OSSL_NELEM(cipher_data); i++) {
1911 + destroy_cipher_method(cipher_data[i].nid);
1912 + OPENSSL_free(cipher_driver_info[i].driver_name);
1913 + cipher_driver_info[i].driver_name = NULL;
1917 +static int devcrypto_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
1918 + const int **nids, int nid)
1920 + if (cipher == NULL)
1921 + return get_cipher_nids(nids);
1923 + *cipher = get_cipher_method(nid);
1925 + return *cipher != NULL;
1928 +static void devcrypto_select_all_ciphers(int *cipher_list)
1932 + for (i = 0; i < OSSL_NELEM(cipher_data); i++)
1933 + cipher_list[i] = 1;
1936 +static int cryptodev_select_cipher_cb(const char *str, int len, void *usr)
1938 + int *cipher_list = (int *)usr;
1940 + const EVP_CIPHER *EVP;
1945 + if (usr == NULL || (name = OPENSSL_strndup(str, len)) == NULL)
1947 + EVP = EVP_get_cipherbyname(name);
1949 + fprintf(stderr, "devcrypto: unknown cipher %s\n", name);
1950 + else if ((i = find_cipher_data_index(EVP_CIPHER_nid(EVP))) != (size_t)-1)
1951 + cipher_list[i] = 1;
1953 + fprintf(stderr, "devcrypto: cipher %s not available\n", name);
1954 + OPENSSL_free(name);
1958 +static void dump_cipher_info(void)
1963 + fprintf (stderr, "Information about ciphers supported by the /dev/crypto"
1965 +#ifndef CIOCGSESSINFO
1966 + fprintf(stderr, "CIOCGSESSINFO (session info call) unavailable\n");
1968 + for (i = 0; i < OSSL_NELEM(cipher_data); i++) {
1969 + name = OBJ_nid2sn(cipher_data[i].nid);
1970 + fprintf (stderr, "Cipher %s, NID=%d, /dev/crypto info: id=%d, ",
1971 + name ? name : "unknown", cipher_data[i].nid,
1972 + cipher_data[i].devcryptoid);
1973 + if (cipher_driver_info[i].status == DEVCRYPTO_STATUS_NO_CIOCGSESSION ) {
1974 + fprintf (stderr, "CIOCGSESSION (session open call) failed\n");
1977 + fprintf (stderr, "driver=%s ", cipher_driver_info[i].driver_name ?
1978 + cipher_driver_info[i].driver_name : "unknown");
1979 + if (cipher_driver_info[i].accelerated == DEVCRYPTO_ACCELERATED)
1980 + fprintf(stderr, "(hw accelerated)");
1981 + else if (cipher_driver_info[i].accelerated == DEVCRYPTO_NOT_ACCELERATED)
1982 + fprintf(stderr, "(software)");
1984 + fprintf(stderr, "(acceleration status unknown)");
1985 + if (cipher_driver_info[i].status == DEVCRYPTO_STATUS_FAILURE)
1986 + fprintf (stderr, ". Cipher setup failed");
1987 + fprintf(stderr, "\n");
1989 + fprintf(stderr, "\n");
1993 + * We only support digests if the cryptodev implementation supports multiple
1994 + * data updates and session copying. Otherwise, we would be forced to maintain
1995 + * a cache, which is perilous if there's a lot of data coming in (if someone
1996 + * wants to checksum an OpenSSL tarball, for example).
1998 +#if defined(CIOCCPHASH) && defined(COP_FLAG_UPDATE) && defined(COP_FLAG_FINAL)
1999 +#define IMPLEMENT_DIGEST
2001 +/******************************************************************************
2005 + * Because they all do the same basic operation, we have only one set of
2006 + * method functions for them all to share, and a mapping table between
2007 + * NIDs and cryptodev IDs, with all the necessary size data.
2011 +struct digest_ctx {
2012 + struct session_op sess;
2013 + /* This signals that the init function was called, not that it succeeded. */
2015 + unsigned char digest_res[HASH_MAX_LEN];
2018 +static const struct digest_data_st {
2023 +} digest_data[] = {
2024 +#ifndef OPENSSL_NO_MD5
2025 + { NID_md5, /* MD5_CBLOCK */ 64, 16, CRYPTO_MD5 },
2027 + { NID_sha1, SHA_CBLOCK, 20, CRYPTO_SHA1 },
2028 +#ifndef OPENSSL_NO_RMD160
2029 +# if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_RIPEMD160)
2030 + { NID_ripemd160, /* RIPEMD160_CBLOCK */ 64, 20, CRYPTO_RIPEMD160 },
2033 +#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_224)
2034 + { NID_sha224, SHA256_CBLOCK, 224 / 8, CRYPTO_SHA2_224 },
2036 +#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_256)
2037 + { NID_sha256, SHA256_CBLOCK, 256 / 8, CRYPTO_SHA2_256 },
2039 +#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_384)
2040 + { NID_sha384, SHA512_CBLOCK, 384 / 8, CRYPTO_SHA2_384 },
2042 +#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_512)
2043 + { NID_sha512, SHA512_CBLOCK, 512 / 8, CRYPTO_SHA2_512 },
2047 +static size_t find_digest_data_index(int nid)
2051 + for (i = 0; i < OSSL_NELEM(digest_data); i++)
2052 + if (nid == digest_data[i].nid)
2054 + return (size_t)-1;
2057 +static size_t get_digest_data_index(int nid)
2059 + size_t i = find_digest_data_index(nid);
2061 + if (i != (size_t)-1)
2065 + * Code further down must make sure that only NIDs in the table above
2066 + * are used. If any other NID reaches this function, there's a grave
2067 + * coding error further down.
2069 + assert("Code that never should be reached" == NULL);
2073 +static const struct digest_data_st *get_digest_data(int nid)
2075 + return &digest_data[get_digest_data_index(nid)];
2079 + * Following are the five necessary functions to map OpenSSL functionality
2080 + * with cryptodev: init, update, final, cleanup, and copy.
2083 +static int digest_init(EVP_MD_CTX *ctx)
2085 + struct digest_ctx *digest_ctx =
2086 + (struct digest_ctx *)EVP_MD_CTX_md_data(ctx);
2087 + const struct digest_data_st *digest_d =
2088 + get_digest_data(EVP_MD_CTX_type(ctx));
2090 + digest_ctx->init_called = 1;
2092 + memset(&digest_ctx->sess, 0, sizeof(digest_ctx->sess));
2093 + digest_ctx->sess.mac = digest_d->devcryptoid;
2094 + if (ioctl(cfd, CIOCGSESSION, &digest_ctx->sess) < 0) {
2095 + SYSerr(SYS_F_IOCTL, errno);
2102 +static int digest_op(struct digest_ctx *ctx, const void *src, size_t srclen,
2103 + void *res, unsigned int flags)
2105 + struct crypt_op cryp;
2107 + memset(&cryp, 0, sizeof(cryp));
2108 + cryp.ses = ctx->sess.ses;
2109 + cryp.len = srclen;
2110 + cryp.src = (void *)src;
2113 + cryp.flags = flags;
2114 + return ioctl(cfd, CIOCCRYPT, &cryp);
2117 +static int digest_update(EVP_MD_CTX *ctx, const void *data, size_t count)
2119 + struct digest_ctx *digest_ctx =
2120 + (struct digest_ctx *)EVP_MD_CTX_md_data(ctx);
2125 + if (digest_ctx == NULL)
2128 + if (EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_ONESHOT)) {
2129 + if (digest_op(digest_ctx, data, count, digest_ctx->digest_res, 0) >= 0)
2131 + } else if (digest_op(digest_ctx, data, count, NULL, COP_FLAG_UPDATE) >= 0) {
2135 + SYSerr(SYS_F_IOCTL, errno);
2139 +static int digest_final(EVP_MD_CTX *ctx, unsigned char *md)
2141 + struct digest_ctx *digest_ctx =
2142 + (struct digest_ctx *)EVP_MD_CTX_md_data(ctx);
2144 + if (md == NULL || digest_ctx == NULL)
2147 + if (EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_ONESHOT)) {
2148 + memcpy(md, digest_ctx->digest_res, EVP_MD_CTX_size(ctx));
2149 + } else if (digest_op(digest_ctx, NULL, 0, md, COP_FLAG_FINAL) < 0) {
2150 + SYSerr(SYS_F_IOCTL, errno);
2157 +static int digest_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from)
2159 + struct digest_ctx *digest_from =
2160 + (struct digest_ctx *)EVP_MD_CTX_md_data(from);
2161 + struct digest_ctx *digest_to =
2162 + (struct digest_ctx *)EVP_MD_CTX_md_data(to);
2163 + struct cphash_op cphash;
2165 + if (digest_from == NULL || digest_from->init_called != 1)
2168 + if (!digest_init(to)) {
2169 + SYSerr(SYS_F_IOCTL, errno);
2173 + cphash.src_ses = digest_from->sess.ses;
2174 + cphash.dst_ses = digest_to->sess.ses;
2175 + if (ioctl(cfd, CIOCCPHASH, &cphash) < 0) {
2176 + SYSerr(SYS_F_IOCTL, errno);
2182 +static int digest_cleanup(EVP_MD_CTX *ctx)
2184 + struct digest_ctx *digest_ctx =
2185 + (struct digest_ctx *)EVP_MD_CTX_md_data(ctx);
2187 + if (digest_ctx == NULL)
2190 + return clean_devcrypto_session(&digest_ctx->sess);
2194 + * Keep tables of known nids, associated methods, selected digests, and
2196 + * Note that known_digest_nids[] isn't necessarily indexed the same way as
2197 + * digest_data[] above, which the other tables are.
2199 +static int known_digest_nids[OSSL_NELEM(digest_data)];
2200 +static int known_digest_nids_amount = -1; /* -1 indicates not yet initialised */
2201 +static EVP_MD *known_digest_methods[OSSL_NELEM(digest_data)] = { NULL, };
2202 +static int selected_digests[OSSL_NELEM(digest_data)];
2203 +static struct driver_info_st digest_driver_info[OSSL_NELEM(digest_data)];
2205 +static int devcrypto_test_digest(size_t digest_data_index)
2207 + return (digest_driver_info[digest_data_index].status == DEVCRYPTO_STATUS_USABLE
2208 + && selected_digests[digest_data_index] == 1
2209 + && (digest_driver_info[digest_data_index].accelerated
2210 + == DEVCRYPTO_ACCELERATED
2211 + || use_softdrivers == DEVCRYPTO_USE_SOFTWARE
2212 + || (digest_driver_info[digest_data_index].accelerated
2213 + != DEVCRYPTO_NOT_ACCELERATED
2214 + && use_softdrivers == DEVCRYPTO_REJECT_SOFTWARE)));
2217 +static void rebuild_known_digest_nids(ENGINE *e)
2221 + for (i = 0, known_digest_nids_amount = 0; i < OSSL_NELEM(digest_data); i++) {
2222 + if (devcrypto_test_digest(i))
2223 + known_digest_nids[known_digest_nids_amount++] = digest_data[i].nid;
2225 + ENGINE_unregister_digests(e);
2226 + ENGINE_register_digests(e);
2229 +static void prepare_digest_methods(void)
2232 + struct session_op sess1, sess2;
2233 +#ifdef CIOCGSESSINFO
2234 + struct session_info_op siop;
2236 + struct cphash_op cphash;
2238 + memset(&digest_driver_info, 0, sizeof(digest_driver_info));
2240 + memset(&sess1, 0, sizeof(sess1));
2241 + memset(&sess2, 0, sizeof(sess2));
2243 + for (i = 0, known_digest_nids_amount = 0; i < OSSL_NELEM(digest_data);
2246 + selected_digests[i] = 1;
2249 + * Check that the digest is usable
2251 + sess1.mac = digest_data[i].devcryptoid;
2253 + if (ioctl(cfd, CIOCGSESSION, &sess1) < 0) {
2254 + digest_driver_info[i].status = DEVCRYPTO_STATUS_NO_CIOCGSESSION;
2258 +#ifdef CIOCGSESSINFO
2259 + /* gather hardware acceleration info from the driver */
2260 + siop.ses = sess1.ses;
2261 + if (ioctl(cfd, CIOCGSESSINFO, &siop) < 0) {
2262 + digest_driver_info[i].accelerated = DEVCRYPTO_ACCELERATION_UNKNOWN;
2264 + digest_driver_info[i].driver_name =
2265 + OPENSSL_strndup(siop.hash_info.cra_driver_name,
2266 + CRYPTODEV_MAX_ALG_NAME);
2267 + if (siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY)
2268 + digest_driver_info[i].accelerated = DEVCRYPTO_ACCELERATED;
2270 + digest_driver_info[i].accelerated = DEVCRYPTO_NOT_ACCELERATED;
2274 + /* digest must be capable of hash state copy */
2275 + sess2.mac = sess1.mac;
2276 + if (ioctl(cfd, CIOCGSESSION, &sess2) < 0) {
2277 + digest_driver_info[i].status = DEVCRYPTO_STATUS_FAILURE;
2280 + cphash.src_ses = sess1.ses;
2281 + cphash.dst_ses = sess2.ses;
2282 + if (ioctl(cfd, CIOCCPHASH, &cphash) < 0) {
2283 + digest_driver_info[i].status = DEVCRYPTO_STATUS_NO_CIOCCPHASH;
2286 + if ((known_digest_methods[i] = EVP_MD_meth_new(digest_data[i].nid,
2287 + NID_undef)) == NULL
2288 + || !EVP_MD_meth_set_input_blocksize(known_digest_methods[i],
2289 + digest_data[i].blocksize)
2290 + || !EVP_MD_meth_set_result_size(known_digest_methods[i],
2291 + digest_data[i].digestlen)
2292 + || !EVP_MD_meth_set_init(known_digest_methods[i], digest_init)
2293 + || !EVP_MD_meth_set_update(known_digest_methods[i], digest_update)
2294 + || !EVP_MD_meth_set_final(known_digest_methods[i], digest_final)
2295 + || !EVP_MD_meth_set_copy(known_digest_methods[i], digest_copy)
2296 + || !EVP_MD_meth_set_cleanup(known_digest_methods[i], digest_cleanup)
2297 + || !EVP_MD_meth_set_app_datasize(known_digest_methods[i],
2298 + sizeof(struct digest_ctx))) {
2299 + digest_driver_info[i].status = DEVCRYPTO_STATUS_FAILURE;
2300 + EVP_MD_meth_free(known_digest_methods[i]);
2301 + known_digest_methods[i] = NULL;
2304 + digest_driver_info[i].status = DEVCRYPTO_STATUS_USABLE;
2306 + ioctl(cfd, CIOCFSESSION, &sess1.ses);
2307 + if (sess2.ses != 0)
2308 + ioctl(cfd, CIOCFSESSION, &sess2.ses);
2309 + if (devcrypto_test_digest(i))
2310 + known_digest_nids[known_digest_nids_amount++] = digest_data[i].nid;
2314 +static const EVP_MD *get_digest_method(int nid)
2316 + size_t i = get_digest_data_index(nid);
2318 + if (i == (size_t)-1)
2320 + return known_digest_methods[i];
2323 +static int get_digest_nids(const int **nids)
2325 + *nids = known_digest_nids;
2326 + return known_digest_nids_amount;
2329 +static void destroy_digest_method(int nid)
2331 + size_t i = get_digest_data_index(nid);
2333 + EVP_MD_meth_free(known_digest_methods[i]);
2334 + known_digest_methods[i] = NULL;
2337 +static void destroy_all_digest_methods(void)
2341 + for (i = 0; i < OSSL_NELEM(digest_data); i++) {
2342 + destroy_digest_method(digest_data[i].nid);
2343 + OPENSSL_free(digest_driver_info[i].driver_name);
2344 + digest_driver_info[i].driver_name = NULL;
2348 +static int devcrypto_digests(ENGINE *e, const EVP_MD **digest,
2349 + const int **nids, int nid)
2351 + if (digest == NULL)
2352 + return get_digest_nids(nids);
2354 + *digest = get_digest_method(nid);
2356 + return *digest != NULL;
2359 +static void devcrypto_select_all_digests(int *digest_list)
2363 + for (i = 0; i < OSSL_NELEM(digest_data); i++)
2364 + digest_list[i] = 1;
2367 +static int cryptodev_select_digest_cb(const char *str, int len, void *usr)
2369 + int *digest_list = (int *)usr;
2371 + const EVP_MD *EVP;
2376 + if (usr == NULL || (name = OPENSSL_strndup(str, len)) == NULL)
2378 + EVP = EVP_get_digestbyname(name);
2380 + fprintf(stderr, "devcrypto: unknown digest %s\n", name);
2381 + else if ((i = find_digest_data_index(EVP_MD_type(EVP))) != (size_t)-1)
2382 + digest_list[i] = 1;
2384 + fprintf(stderr, "devcrypto: digest %s not available\n", name);
2385 + OPENSSL_free(name);
2389 +static void dump_digest_info(void)
2394 + fprintf (stderr, "Information about digests supported by the /dev/crypto"
2396 +#ifndef CIOCGSESSINFO
2397 + fprintf(stderr, "CIOCGSESSINFO (session info call) unavailable\n");
2400 + for (i = 0; i < OSSL_NELEM(digest_data); i++) {
2401 + name = OBJ_nid2sn(digest_data[i].nid);
2402 + fprintf (stderr, "Digest %s, NID=%d, /dev/crypto info: id=%d, driver=%s",
2403 + name ? name : "unknown", digest_data[i].nid,
2404 + digest_data[i].devcryptoid,
2405 + digest_driver_info[i].driver_name ? digest_driver_info[i].driver_name : "unknown");
2406 + if (digest_driver_info[i].status == DEVCRYPTO_STATUS_NO_CIOCGSESSION) {
2407 + fprintf (stderr, ". CIOCGSESSION (session open) failed\n");
2410 + if (digest_driver_info[i].accelerated == DEVCRYPTO_ACCELERATED)
2411 + fprintf(stderr, " (hw accelerated)");
2412 + else if (digest_driver_info[i].accelerated == DEVCRYPTO_NOT_ACCELERATED)
2413 + fprintf(stderr, " (software)");
2415 + fprintf(stderr, " (acceleration status unknown)");
2416 + if (cipher_driver_info[i].status == DEVCRYPTO_STATUS_FAILURE)
2417 + fprintf (stderr, ". Cipher setup failed\n");
2418 + else if (digest_driver_info[i].status == DEVCRYPTO_STATUS_NO_CIOCCPHASH)
2419 + fprintf(stderr, ", CIOCCPHASH failed\n");
2421 + fprintf(stderr, ", CIOCCPHASH capable\n");
2423 + fprintf(stderr, "\n");
2428 +/******************************************************************************
2430 + * CONTROL COMMANDS
2434 +#define DEVCRYPTO_CMD_USE_SOFTDRIVERS ENGINE_CMD_BASE
2435 +#define DEVCRYPTO_CMD_CIPHERS (ENGINE_CMD_BASE + 1)
2436 +#define DEVCRYPTO_CMD_DIGESTS (ENGINE_CMD_BASE + 2)
2437 +#define DEVCRYPTO_CMD_DUMP_INFO (ENGINE_CMD_BASE + 3)
2439 +/* Helper macros for CPP string composition */
2440 +#ifndef OPENSSL_MSTR
2441 +# define OPENSSL_MSTR_HELPER(x) #x
2442 +# define OPENSSL_MSTR(x) OPENSSL_MSTR_HELPER(x)
2445 +static const ENGINE_CMD_DEFN devcrypto_cmds[] = {
2446 +#ifdef CIOCGSESSINFO
2447 + {DEVCRYPTO_CMD_USE_SOFTDRIVERS,
2448 + "USE_SOFTDRIVERS",
2449 + "specifies whether to use software (not accelerated) drivers ("
2450 + OPENSSL_MSTR(DEVCRYPTO_REQUIRE_ACCELERATED) "=use only accelerated drivers, "
2451 + OPENSSL_MSTR(DEVCRYPTO_USE_SOFTWARE) "=allow all drivers, "
2452 + OPENSSL_MSTR(DEVCRYPTO_REJECT_SOFTWARE)
2453 + "=use if acceleration can't be determined) [default="
2454 + OPENSSL_MSTR(DEVCRYPTO_DEFAULT_USE_SOFTDRIVERS) "]",
2455 + ENGINE_CMD_FLAG_NUMERIC},
2458 + {DEVCRYPTO_CMD_CIPHERS,
2460 + "either ALL, NONE, or a comma-separated list of ciphers to enable [default=ALL]",
2461 + ENGINE_CMD_FLAG_STRING},
2463 +#ifdef IMPLEMENT_DIGEST
2464 + {DEVCRYPTO_CMD_DIGESTS,
2466 + "either ALL, NONE, or a comma-separated list of digests to enable [default=ALL]",
2467 + ENGINE_CMD_FLAG_STRING},
2470 + {DEVCRYPTO_CMD_DUMP_INFO,
2472 + "dump info about each algorithm to stderr; use 'openssl engine -pre DUMP_INFO devcrypto'",
2473 + ENGINE_CMD_FLAG_NO_INPUT},
2475 + {0, NULL, NULL, 0}
2478 +static int devcrypto_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void))
2482 +#ifdef CIOCGSESSINFO
2483 + case DEVCRYPTO_CMD_USE_SOFTDRIVERS:
2485 + case DEVCRYPTO_REQUIRE_ACCELERATED:
2486 + case DEVCRYPTO_USE_SOFTWARE:
2487 + case DEVCRYPTO_REJECT_SOFTWARE:
2490 + fprintf(stderr, "devcrypto: invalid value (%ld) for USE_SOFTDRIVERS\n", i);
2493 + if (use_softdrivers == i)
2495 + use_softdrivers = i;
2496 +#ifdef IMPLEMENT_DIGEST
2497 + rebuild_known_digest_nids(e);
2499 + rebuild_known_cipher_nids(e);
2501 +#endif /* CIOCGSESSINFO */
2503 + case DEVCRYPTO_CMD_CIPHERS:
2506 + if (strcasecmp((const char *)p, "ALL") == 0) {
2507 + devcrypto_select_all_ciphers(selected_ciphers);
2508 + } else if (strcasecmp((const char*)p, "NONE") == 0) {
2509 + memset(selected_ciphers, 0, sizeof(selected_ciphers));
2511 + new_list=OPENSSL_zalloc(sizeof(selected_ciphers));
2512 + if (!CONF_parse_list(p, ',', 1, cryptodev_select_cipher_cb, new_list)) {
2513 + OPENSSL_free(new_list);
2516 + memcpy(selected_ciphers, new_list, sizeof(selected_ciphers));
2517 + OPENSSL_free(new_list);
2519 + rebuild_known_cipher_nids(e);
2522 +#ifdef IMPLEMENT_DIGEST
2523 + case DEVCRYPTO_CMD_DIGESTS:
2526 + if (strcasecmp((const char *)p, "ALL") == 0) {
2527 + devcrypto_select_all_digests(selected_digests);
2528 + } else if (strcasecmp((const char*)p, "NONE") == 0) {
2529 + memset(selected_digests, 0, sizeof(selected_digests));
2531 + new_list=OPENSSL_zalloc(sizeof(selected_digests));
2532 + if (!CONF_parse_list(p, ',', 1, cryptodev_select_digest_cb, new_list)) {
2533 + OPENSSL_free(new_list);
2536 + memcpy(selected_digests, new_list, sizeof(selected_digests));
2537 + OPENSSL_free(new_list);
2539 + rebuild_known_digest_nids(e);
2541 +#endif /* IMPLEMENT_DIGEST */
2543 + case DEVCRYPTO_CMD_DUMP_INFO:
2544 + dump_cipher_info();
2545 +#ifdef IMPLEMENT_DIGEST
2546 + dump_digest_info();
2556 +/******************************************************************************
2563 + * Opens /dev/crypto
2565 +static int open_devcrypto(void)
2572 + if ((fd = open("/dev/crypto", O_RDWR, 0)) < 0) {
2573 +#ifndef ENGINE_DEVCRYPTO_DEBUG
2574 + if (errno != ENOENT)
2576 + fprintf(stderr, "Could not open /dev/crypto: %s\n", strerror(errno));
2581 + if (ioctl(fd, CRIOGET, &cfd) < 0) {
2582 + fprintf(stderr, "Could not create crypto fd: %s\n", strerror(errno));
2595 +static int close_devcrypto(void)
2604 + fprintf(stderr, "Error closing /dev/crypto: %s\n", strerror(errno));
2610 +static int devcrypto_unload(ENGINE *e)
2612 + destroy_all_cipher_methods();
2613 +#ifdef IMPLEMENT_DIGEST
2614 + destroy_all_digest_methods();
2617 + close_devcrypto();
2622 +static int bind_devcrypto(ENGINE *e) {
2624 + if (!ENGINE_set_id(e, engine_devcrypto_id)
2625 + || !ENGINE_set_name(e, "/dev/crypto engine")
2626 + || !ENGINE_set_destroy_function(e, devcrypto_unload)
2627 + || !ENGINE_set_cmd_defns(e, devcrypto_cmds)
2628 + || !ENGINE_set_ctrl_function(e, devcrypto_ctrl))
2631 + prepare_cipher_methods();
2632 +#ifdef IMPLEMENT_DIGEST
2633 + prepare_digest_methods();
2636 + return (ENGINE_set_ciphers(e, devcrypto_ciphers)
2637 +#ifdef IMPLEMENT_DIGEST
2638 + && ENGINE_set_digests(e, devcrypto_digests)
2641 + * Asymmetric ciphers aren't well supported with /dev/crypto. Among the BSD
2642 + * implementations, it seems to only exist in FreeBSD, and regarding the
2643 + * parameters in its crypt_kop, the manual crypto(4) has this to say:
2645 + * The semantics of these arguments are currently undocumented.
2647 + * Reading through the FreeBSD source code doesn't give much more than
2648 + * their CRK_MOD_EXP implementation for ubsec.
2650 + * It doesn't look much better with cryptodev-linux. They have the crypt_kop
2651 + * structure as well as the command (CRK_*) in cryptodev.h, but no support
2652 + * seems to be implemented at all for the moment.
2654 + * At the time of writing, it seems impossible to write proper support for
2655 + * FreeBSD's asym features without some very deep knowledge and access to
2656 + * specific kernel modules.
2658 + * /Richard Levitte, 2017-05-11
2661 +# ifndef OPENSSL_NO_RSA
2662 + && ENGINE_set_RSA(e, devcrypto_rsa)
2664 +# ifndef OPENSSL_NO_DSA
2665 + && ENGINE_set_DSA(e, devcrypto_dsa)
2667 +# ifndef OPENSSL_NO_DH
2668 + && ENGINE_set_DH(e, devcrypto_dh)
2670 +# ifndef OPENSSL_NO_EC
2671 + && ENGINE_set_EC(e, devcrypto_ec)
2677 +#ifdef OPENSSL_NO_DYNAMIC_ENGINE
2679 + * In case this engine is built into libcrypto, then it doesn't offer any
2680 + * ability to be dynamically loadable.
2682 +void engine_load_devcrypto_int(void)
2686 + if (!open_devcrypto())
2689 + if ((e = ENGINE_new()) == NULL
2690 + || !bind_devcrypto(e)) {
2691 + close_devcrypto();
2697 + ENGINE_free(e); /* Loose our local reference */
2698 + ERR_clear_error();
2703 +static int bind_helper(ENGINE *e, const char *id)
2705 + if ((id && (strcmp(id, engine_devcrypto_id) != 0))
2706 + || !open_devcrypto())
2708 + if (!bind_devcrypto(e)) {
2709 + close_devcrypto();
2715 +IMPLEMENT_DYNAMIC_CHECK_FN()
2716 +IMPLEMENT_DYNAMIC_BIND_FN(bind_helper)