1 From 37a5c14aad5051201e4bd18faf1a4b25a824cc30 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: [PATCH 4/4] 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 @@ -330,18 +330,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 @@ -366,6 +354,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 @@ -714,11 +714,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 @@ -728,6 +723,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 @@ -10,6 +10,9 @@ IF[{- !$disabled{"engine"} -}]
87 IF[{- !$disabled{afalgeng} -}]
88 SOURCE[../libcrypto]=e_afalg.c
90 + IF[{- !$disabled{"devcryptoeng"} -}]
91 + SOURCE[../libcrypto]=e_devcrypto.c
95 SOURCE[padlock]=e_padlock.c {- $target{padlock_asm_src} -}
96 @@ -27,6 +30,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-2019 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 "internal/engine.h"
139 -/* #define ENGINE_DEVCRYPTO_DEBUG */
141 -#ifdef CRYPTO_ALGORITHM_MIN
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()
1299 - if ((cfd = open("/dev/crypto", O_RDWR, 0)) < 0) {
1300 -#ifndef ENGINE_DEVCRYPTO_DEBUG
1301 - if (errno != ENOENT)
1303 - fprintf(stderr, "Could not open /dev/crypto: %s\n", strerror(errno));
1307 - if ((e = ENGINE_new()) == NULL
1308 - || !ENGINE_set_destroy_function(e, devcrypto_unload)) {
1311 - * We know that devcrypto_unload() won't be called when one of the
1312 - * above two calls have failed, so we close cfd explicitly here to
1313 - * avoid leaking resources.
1319 - prepare_cipher_methods();
1320 -#ifdef IMPLEMENT_DIGEST
1321 - prepare_digest_methods();
1324 - if (!ENGINE_set_id(e, "devcrypto")
1325 - || !ENGINE_set_name(e, "/dev/crypto engine")
1326 - || !ENGINE_set_cmd_defns(e, devcrypto_cmds)
1327 - || !ENGINE_set_ctrl_function(e, devcrypto_ctrl)
1330 - * Asymmetric ciphers aren't well supported with /dev/crypto. Among the BSD
1331 - * implementations, it seems to only exist in FreeBSD, and regarding the
1332 - * parameters in its crypt_kop, the manual crypto(4) has this to say:
1334 - * The semantics of these arguments are currently undocumented.
1336 - * Reading through the FreeBSD source code doesn't give much more than
1337 - * their CRK_MOD_EXP implementation for ubsec.
1339 - * It doesn't look much better with cryptodev-linux. They have the crypt_kop
1340 - * structure as well as the command (CRK_*) in cryptodev.h, but no support
1341 - * seems to be implemented at all for the moment.
1343 - * At the time of writing, it seems impossible to write proper support for
1344 - * FreeBSD's asym features without some very deep knowledge and access to
1345 - * specific kernel modules.
1347 - * /Richard Levitte, 2017-05-11
1350 -# ifndef OPENSSL_NO_RSA
1351 - || !ENGINE_set_RSA(e, devcrypto_rsa)
1353 -# ifndef OPENSSL_NO_DSA
1354 - || !ENGINE_set_DSA(e, devcrypto_dsa)
1356 -# ifndef OPENSSL_NO_DH
1357 - || !ENGINE_set_DH(e, devcrypto_dh)
1359 -# ifndef OPENSSL_NO_EC
1360 - || !ENGINE_set_EC(e, devcrypto_ec)
1363 - || !ENGINE_set_ciphers(e, devcrypto_ciphers)
1364 -#ifdef IMPLEMENT_DIGEST
1365 - || !ENGINE_set_digests(e, devcrypto_digests)
1373 - ENGINE_free(e); /* Loose our local reference */
1374 - ERR_clear_error();
1377 +++ b/engines/e_devcrypto.c
1380 + * Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved.
1382 + * Licensed under the OpenSSL license (the "License"). You may not use
1383 + * this file except in compliance with the License. You can obtain a copy
1384 + * in the file LICENSE in the source distribution or at
1385 + * https://www.openssl.org/source/license.html
1388 +#include "../e_os.h"
1389 +#include <string.h>
1390 +#include <sys/types.h>
1391 +#include <sys/stat.h>
1393 +#include <sys/ioctl.h>
1394 +#include <unistd.h>
1395 +#include <assert.h>
1397 +#include <openssl/conf.h>
1398 +#include <openssl/evp.h>
1399 +#include <openssl/err.h>
1400 +#include <openssl/engine.h>
1401 +#include <openssl/objects.h>
1402 +#include <crypto/cryptodev.h>
1404 +/* #define ENGINE_DEVCRYPTO_DEBUG */
1406 +#ifdef CRYPTO_ALGORITHM_MIN
1407 +# define CHECK_BSD_STYLE_MACROS
1410 +#define engine_devcrypto_id "devcrypto"
1413 + * ONE global file descriptor for all sessions. This allows operations
1414 + * such as digest session data copying (see digest_copy()), but is also
1415 + * saner... why re-open /dev/crypto for every session?
1417 +static int cfd = -1;
1418 +#define DEVCRYPTO_REQUIRE_ACCELERATED 0 /* require confirmation of acceleration */
1419 +#define DEVCRYPTO_USE_SOFTWARE 1 /* allow software drivers */
1420 +#define DEVCRYPTO_REJECT_SOFTWARE 2 /* only disallow confirmed software drivers */
1422 +#define DEVCRYPTO_DEFAULT_USE_SOFTDRIVERS DEVCRYPTO_REJECT_SOFTWARE
1423 +static int use_softdrivers = DEVCRYPTO_DEFAULT_USE_SOFTDRIVERS;
1426 + * cipher/digest status & acceleration definitions
1427 + * Make sure the defaults are set to 0
1429 +struct driver_info_st {
1430 + enum devcrypto_status_t {
1431 + DEVCRYPTO_STATUS_FAILURE = -3, /* unusable for other reason */
1432 + DEVCRYPTO_STATUS_NO_CIOCCPHASH = -2, /* hash state copy not supported */
1433 + DEVCRYPTO_STATUS_NO_CIOCGSESSION = -1, /* session open failed */
1434 + DEVCRYPTO_STATUS_UNKNOWN = 0, /* not tested yet */
1435 + DEVCRYPTO_STATUS_USABLE = 1 /* algo can be used */
1438 + enum devcrypto_accelerated_t {
1439 + DEVCRYPTO_NOT_ACCELERATED = -1, /* software implemented */
1440 + DEVCRYPTO_ACCELERATION_UNKNOWN = 0, /* acceleration support unkown */
1441 + DEVCRYPTO_ACCELERATED = 1 /* hardware accelerated */
1444 + char *driver_name;
1447 +#ifdef OPENSSL_NO_DYNAMIC_ENGINE
1448 +void engine_load_devcrypto_int(void);
1451 +static int clean_devcrypto_session(struct session_op *sess) {
1452 + if (ioctl(cfd, CIOCFSESSION, &sess->ses) < 0) {
1453 + SYSerr(SYS_F_IOCTL, errno);
1456 + memset(sess, 0, sizeof(struct session_op));
1460 +/******************************************************************************
1464 + * Because they all do the same basic operation, we have only one set of
1465 + * method functions for them all to share, and a mapping table between
1466 + * NIDs and cryptodev IDs, with all the necessary size data.
1470 +struct cipher_ctx {
1471 + struct session_op sess;
1472 + int op; /* COP_ENCRYPT or COP_DECRYPT */
1473 + unsigned long mode; /* EVP_CIPH_*_MODE */
1475 + /* to handle ctr mode being a stream cipher */
1476 + unsigned char partial[EVP_MAX_BLOCK_LENGTH];
1477 + unsigned int blocksize, num;
1480 +static const struct cipher_data_st {
1487 +} cipher_data[] = {
1488 +#ifndef OPENSSL_NO_DES
1489 + { NID_des_cbc, 8, 8, 8, EVP_CIPH_CBC_MODE, CRYPTO_DES_CBC },
1490 + { NID_des_ede3_cbc, 8, 24, 8, EVP_CIPH_CBC_MODE, CRYPTO_3DES_CBC },
1492 +#ifndef OPENSSL_NO_BF
1493 + { NID_bf_cbc, 8, 16, 8, EVP_CIPH_CBC_MODE, CRYPTO_BLF_CBC },
1495 +#ifndef OPENSSL_NO_CAST
1496 + { NID_cast5_cbc, 8, 16, 8, EVP_CIPH_CBC_MODE, CRYPTO_CAST_CBC },
1498 + { NID_aes_128_cbc, 16, 128 / 8, 16, EVP_CIPH_CBC_MODE, CRYPTO_AES_CBC },
1499 + { NID_aes_192_cbc, 16, 192 / 8, 16, EVP_CIPH_CBC_MODE, CRYPTO_AES_CBC },
1500 + { NID_aes_256_cbc, 16, 256 / 8, 16, EVP_CIPH_CBC_MODE, CRYPTO_AES_CBC },
1501 +#ifndef OPENSSL_NO_RC4
1502 + { NID_rc4, 1, 16, 0, EVP_CIPH_STREAM_CIPHER, CRYPTO_ARC4 },
1504 +#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_AES_CTR)
1505 + { NID_aes_128_ctr, 16, 128 / 8, 16, EVP_CIPH_CTR_MODE, CRYPTO_AES_CTR },
1506 + { NID_aes_192_ctr, 16, 192 / 8, 16, EVP_CIPH_CTR_MODE, CRYPTO_AES_CTR },
1507 + { NID_aes_256_ctr, 16, 256 / 8, 16, EVP_CIPH_CTR_MODE, CRYPTO_AES_CTR },
1509 +#if 0 /* Not yet supported */
1510 + { NID_aes_128_xts, 16, 128 / 8 * 2, 16, EVP_CIPH_XTS_MODE, CRYPTO_AES_XTS },
1511 + { NID_aes_256_xts, 16, 256 / 8 * 2, 16, EVP_CIPH_XTS_MODE, CRYPTO_AES_XTS },
1513 +#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_AES_ECB)
1514 + { NID_aes_128_ecb, 16, 128 / 8, 0, EVP_CIPH_ECB_MODE, CRYPTO_AES_ECB },
1515 + { NID_aes_192_ecb, 16, 192 / 8, 0, EVP_CIPH_ECB_MODE, CRYPTO_AES_ECB },
1516 + { NID_aes_256_ecb, 16, 256 / 8, 0, EVP_CIPH_ECB_MODE, CRYPTO_AES_ECB },
1518 +#if 0 /* Not yet supported */
1519 + { NID_aes_128_gcm, 16, 128 / 8, 16, EVP_CIPH_GCM_MODE, CRYPTO_AES_GCM },
1520 + { NID_aes_192_gcm, 16, 192 / 8, 16, EVP_CIPH_GCM_MODE, CRYPTO_AES_GCM },
1521 + { NID_aes_256_gcm, 16, 256 / 8, 16, EVP_CIPH_GCM_MODE, CRYPTO_AES_GCM },
1523 +#ifndef OPENSSL_NO_CAMELLIA
1524 + { NID_camellia_128_cbc, 16, 128 / 8, 16, EVP_CIPH_CBC_MODE,
1525 + CRYPTO_CAMELLIA_CBC },
1526 + { NID_camellia_192_cbc, 16, 192 / 8, 16, EVP_CIPH_CBC_MODE,
1527 + CRYPTO_CAMELLIA_CBC },
1528 + { NID_camellia_256_cbc, 16, 256 / 8, 16, EVP_CIPH_CBC_MODE,
1529 + CRYPTO_CAMELLIA_CBC },
1533 +static size_t find_cipher_data_index(int nid)
1537 + for (i = 0; i < OSSL_NELEM(cipher_data); i++)
1538 + if (nid == cipher_data[i].nid)
1540 + return (size_t)-1;
1543 +static size_t get_cipher_data_index(int nid)
1545 + size_t i = find_cipher_data_index(nid);
1547 + if (i != (size_t)-1)
1551 + * Code further down must make sure that only NIDs in the table above
1552 + * are used. If any other NID reaches this function, there's a grave
1553 + * coding error further down.
1555 + assert("Code that never should be reached" == NULL);
1559 +static const struct cipher_data_st *get_cipher_data(int nid)
1561 + return &cipher_data[get_cipher_data_index(nid)];
1565 + * Following are the three necessary functions to map OpenSSL functionality
1569 +static int cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
1570 + const unsigned char *iv, int enc)
1572 + struct cipher_ctx *cipher_ctx =
1573 + (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
1574 + const struct cipher_data_st *cipher_d =
1575 + get_cipher_data(EVP_CIPHER_CTX_nid(ctx));
1577 + /* cleanup a previous session */
1578 + if (cipher_ctx->sess.ses != 0 &&
1579 + clean_devcrypto_session(&cipher_ctx->sess) == 0)
1582 + cipher_ctx->sess.cipher = cipher_d->devcryptoid;
1583 + cipher_ctx->sess.keylen = cipher_d->keylen;
1584 + cipher_ctx->sess.key = (void *)key;
1585 + cipher_ctx->op = enc ? COP_ENCRYPT : COP_DECRYPT;
1586 + cipher_ctx->mode = cipher_d->flags & EVP_CIPH_MODE;
1587 + cipher_ctx->blocksize = cipher_d->blocksize;
1588 + if (ioctl(cfd, CIOCGSESSION, &cipher_ctx->sess) < 0) {
1589 + SYSerr(SYS_F_IOCTL, errno);
1596 +static int cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
1597 + const unsigned char *in, size_t inl)
1599 + struct cipher_ctx *cipher_ctx =
1600 + (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
1601 + struct crypt_op cryp;
1602 + unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx);
1603 +#if !defined(COP_FLAG_WRITE_IV)
1604 + unsigned char saved_iv[EVP_MAX_IV_LENGTH];
1605 + const unsigned char *ivptr;
1606 + size_t nblocks, ivlen;
1609 + memset(&cryp, 0, sizeof(cryp));
1610 + cryp.ses = cipher_ctx->sess.ses;
1612 + cryp.src = (void *)in;
1613 + cryp.dst = (void *)out;
1614 + cryp.iv = (void *)iv;
1615 + cryp.op = cipher_ctx->op;
1616 +#if !defined(COP_FLAG_WRITE_IV)
1619 + ivlen = EVP_CIPHER_CTX_iv_length(ctx);
1621 + switch (cipher_ctx->mode) {
1622 + case EVP_CIPH_CBC_MODE:
1623 + assert(inl >= ivlen);
1624 + if (!EVP_CIPHER_CTX_encrypting(ctx)) {
1625 + ivptr = in + inl - ivlen;
1626 + memcpy(saved_iv, ivptr, ivlen);
1630 + case EVP_CIPH_CTR_MODE:
1633 + default: /* should not happen */
1637 + cryp.flags = COP_FLAG_WRITE_IV;
1640 + if (ioctl(cfd, CIOCCRYPT, &cryp) < 0) {
1641 + SYSerr(SYS_F_IOCTL, errno);
1645 +#if !defined(COP_FLAG_WRITE_IV)
1647 + switch (cipher_ctx->mode) {
1648 + case EVP_CIPH_CBC_MODE:
1649 + assert(inl >= ivlen);
1650 + if (EVP_CIPHER_CTX_encrypting(ctx))
1651 + ivptr = out + inl - ivlen;
1655 + memcpy(iv, ivptr, ivlen);
1658 + case EVP_CIPH_CTR_MODE:
1659 + nblocks = (inl + cipher_ctx->blocksize - 1)
1660 + / cipher_ctx->blocksize;
1663 + nblocks += iv[ivlen];
1664 + iv[ivlen] = (uint8_t) nblocks;
1669 + default: /* should not happen */
1677 +static int ctr_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
1678 + const unsigned char *in, size_t inl)
1680 + struct cipher_ctx *cipher_ctx =
1681 + (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
1682 + size_t nblocks, len;
1684 + /* initial partial block */
1685 + while (cipher_ctx->num && inl) {
1686 + (*out++) = *(in++) ^ cipher_ctx->partial[cipher_ctx->num];
1688 + cipher_ctx->num = (cipher_ctx->num + 1) % cipher_ctx->blocksize;
1692 + if (inl > (unsigned int) cipher_ctx->blocksize) {
1693 + nblocks = inl/cipher_ctx->blocksize;
1694 + len = nblocks * cipher_ctx->blocksize;
1695 + if (cipher_do_cipher(ctx, out, in, len) < 1)
1702 + /* final partial block */
1704 + memset(cipher_ctx->partial, 0, cipher_ctx->blocksize);
1705 + if (cipher_do_cipher(ctx, cipher_ctx->partial, cipher_ctx->partial,
1706 + cipher_ctx->blocksize) < 1)
1709 + out[cipher_ctx->num] = in[cipher_ctx->num]
1710 + ^ cipher_ctx->partial[cipher_ctx->num];
1711 + cipher_ctx->num++;
1718 +static int cipher_ctrl(EVP_CIPHER_CTX *ctx, int type, int p1, void* p2)
1720 + struct cipher_ctx *cipher_ctx =
1721 + (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
1722 + EVP_CIPHER_CTX *to_ctx = (EVP_CIPHER_CTX *)p2;
1723 + struct cipher_ctx *to_cipher_ctx;
1727 + case EVP_CTRL_COPY:
1728 + if (cipher_ctx == NULL)
1730 + /* when copying the context, a new session needs to be initialized */
1732 + (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(to_ctx);
1733 + memset(&to_cipher_ctx->sess, 0, sizeof(to_cipher_ctx->sess));
1734 + return cipher_init(to_ctx, cipher_ctx->sess.key, EVP_CIPHER_CTX_iv(ctx),
1735 + (cipher_ctx->op == COP_ENCRYPT));
1737 + case EVP_CTRL_INIT:
1738 + memset(&cipher_ctx->sess, 0, sizeof(cipher_ctx->sess));
1748 +static int cipher_cleanup(EVP_CIPHER_CTX *ctx)
1750 + struct cipher_ctx *cipher_ctx =
1751 + (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
1753 + return clean_devcrypto_session(&cipher_ctx->sess);
1757 + * Keep tables of known nids, associated methods, selected ciphers, and driver
1759 + * Note that known_cipher_nids[] isn't necessarily indexed the same way as
1760 + * cipher_data[] above, which the other tables are.
1762 +static int known_cipher_nids[OSSL_NELEM(cipher_data)];
1763 +static int known_cipher_nids_amount = -1; /* -1 indicates not yet initialised */
1764 +static EVP_CIPHER *known_cipher_methods[OSSL_NELEM(cipher_data)] = { NULL, };
1765 +static int selected_ciphers[OSSL_NELEM(cipher_data)];
1766 +static struct driver_info_st cipher_driver_info[OSSL_NELEM(cipher_data)];
1769 +static int devcrypto_test_cipher(size_t cipher_data_index)
1771 + return (cipher_driver_info[cipher_data_index].status == DEVCRYPTO_STATUS_USABLE
1772 + && selected_ciphers[cipher_data_index] == 1
1773 + && (cipher_driver_info[cipher_data_index].accelerated
1774 + == DEVCRYPTO_ACCELERATED
1775 + || use_softdrivers == DEVCRYPTO_USE_SOFTWARE
1776 + || (cipher_driver_info[cipher_data_index].accelerated
1777 + != DEVCRYPTO_NOT_ACCELERATED
1778 + && use_softdrivers == DEVCRYPTO_REJECT_SOFTWARE)));
1781 +static void prepare_cipher_methods(void)
1784 + struct session_op sess;
1785 + unsigned long cipher_mode;
1786 +#ifdef CIOCGSESSINFO
1787 + struct session_info_op siop;
1790 + memset(&cipher_driver_info, 0, sizeof(cipher_driver_info));
1792 + memset(&sess, 0, sizeof(sess));
1793 + sess.key = (void *)"01234567890123456789012345678901234567890123456789";
1795 + for (i = 0, known_cipher_nids_amount = 0;
1796 + i < OSSL_NELEM(cipher_data); i++) {
1798 + selected_ciphers[i] = 1;
1800 + * Check that the cipher is usable
1802 + sess.cipher = cipher_data[i].devcryptoid;
1803 + sess.keylen = cipher_data[i].keylen;
1804 + if (ioctl(cfd, CIOCGSESSION, &sess) < 0) {
1805 + cipher_driver_info[i].status = DEVCRYPTO_STATUS_NO_CIOCGSESSION;
1809 + cipher_mode = cipher_data[i].flags & EVP_CIPH_MODE;
1811 + if ((known_cipher_methods[i] =
1812 + EVP_CIPHER_meth_new(cipher_data[i].nid,
1813 + cipher_mode == EVP_CIPH_CTR_MODE ? 1 :
1814 + cipher_data[i].blocksize,
1815 + cipher_data[i].keylen)) == NULL
1816 + || !EVP_CIPHER_meth_set_iv_length(known_cipher_methods[i],
1817 + cipher_data[i].ivlen)
1818 + || !EVP_CIPHER_meth_set_flags(known_cipher_methods[i],
1819 + cipher_data[i].flags
1820 + | EVP_CIPH_CUSTOM_COPY
1821 + | EVP_CIPH_CTRL_INIT
1822 + | EVP_CIPH_FLAG_DEFAULT_ASN1)
1823 + || !EVP_CIPHER_meth_set_init(known_cipher_methods[i], cipher_init)
1824 + || !EVP_CIPHER_meth_set_do_cipher(known_cipher_methods[i],
1825 + cipher_mode == EVP_CIPH_CTR_MODE ?
1828 + || !EVP_CIPHER_meth_set_ctrl(known_cipher_methods[i], cipher_ctrl)
1829 + || !EVP_CIPHER_meth_set_cleanup(known_cipher_methods[i],
1831 + || !EVP_CIPHER_meth_set_impl_ctx_size(known_cipher_methods[i],
1832 + sizeof(struct cipher_ctx))) {
1833 + cipher_driver_info[i].status = DEVCRYPTO_STATUS_FAILURE;
1834 + EVP_CIPHER_meth_free(known_cipher_methods[i]);
1835 + known_cipher_methods[i] = NULL;
1837 + cipher_driver_info[i].status = DEVCRYPTO_STATUS_USABLE;
1838 +#ifdef CIOCGSESSINFO
1839 + siop.ses = sess.ses;
1840 + if (ioctl(cfd, CIOCGSESSINFO, &siop) < 0) {
1841 + cipher_driver_info[i].accelerated = DEVCRYPTO_ACCELERATION_UNKNOWN;
1843 + cipher_driver_info[i].driver_name =
1844 + OPENSSL_strndup(siop.cipher_info.cra_driver_name,
1845 + CRYPTODEV_MAX_ALG_NAME);
1846 + if (!(siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY))
1847 + cipher_driver_info[i].accelerated = DEVCRYPTO_NOT_ACCELERATED;
1849 + cipher_driver_info[i].accelerated = DEVCRYPTO_ACCELERATED;
1851 +#endif /* CIOCGSESSINFO */
1853 + ioctl(cfd, CIOCFSESSION, &sess.ses);
1854 + if (devcrypto_test_cipher(i)) {
1855 + known_cipher_nids[known_cipher_nids_amount++] =
1856 + cipher_data[i].nid;
1861 +static void rebuild_known_cipher_nids(ENGINE *e)
1865 + for (i = 0, known_cipher_nids_amount = 0; i < OSSL_NELEM(cipher_data); i++) {
1866 + if (devcrypto_test_cipher(i))
1867 + known_cipher_nids[known_cipher_nids_amount++] = cipher_data[i].nid;
1869 + ENGINE_unregister_ciphers(e);
1870 + ENGINE_register_ciphers(e);
1873 +static const EVP_CIPHER *get_cipher_method(int nid)
1875 + size_t i = get_cipher_data_index(nid);
1877 + if (i == (size_t)-1)
1879 + return known_cipher_methods[i];
1882 +static int get_cipher_nids(const int **nids)
1884 + *nids = known_cipher_nids;
1885 + return known_cipher_nids_amount;
1888 +static void destroy_cipher_method(int nid)
1890 + size_t i = get_cipher_data_index(nid);
1892 + EVP_CIPHER_meth_free(known_cipher_methods[i]);
1893 + known_cipher_methods[i] = NULL;
1896 +static void destroy_all_cipher_methods(void)
1900 + for (i = 0; i < OSSL_NELEM(cipher_data); i++) {
1901 + destroy_cipher_method(cipher_data[i].nid);
1902 + OPENSSL_free(cipher_driver_info[i].driver_name);
1903 + cipher_driver_info[i].driver_name = NULL;
1907 +static int devcrypto_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
1908 + const int **nids, int nid)
1910 + if (cipher == NULL)
1911 + return get_cipher_nids(nids);
1913 + *cipher = get_cipher_method(nid);
1915 + return *cipher != NULL;
1918 +static void devcrypto_select_all_ciphers(int *cipher_list)
1922 + for (i = 0; i < OSSL_NELEM(cipher_data); i++)
1923 + cipher_list[i] = 1;
1926 +static int cryptodev_select_cipher_cb(const char *str, int len, void *usr)
1928 + int *cipher_list = (int *)usr;
1930 + const EVP_CIPHER *EVP;
1935 + if (usr == NULL || (name = OPENSSL_strndup(str, len)) == NULL)
1937 + EVP = EVP_get_cipherbyname(name);
1939 + fprintf(stderr, "devcrypto: unknown cipher %s\n", name);
1940 + else if ((i = find_cipher_data_index(EVP_CIPHER_nid(EVP))) != (size_t)-1)
1941 + cipher_list[i] = 1;
1943 + fprintf(stderr, "devcrypto: cipher %s not available\n", name);
1944 + OPENSSL_free(name);
1948 +static void dump_cipher_info(void)
1953 + fprintf (stderr, "Information about ciphers supported by the /dev/crypto"
1955 +#ifndef CIOCGSESSINFO
1956 + fprintf(stderr, "CIOCGSESSINFO (session info call) unavailable\n");
1958 + for (i = 0; i < OSSL_NELEM(cipher_data); i++) {
1959 + name = OBJ_nid2sn(cipher_data[i].nid);
1960 + fprintf (stderr, "Cipher %s, NID=%d, /dev/crypto info: id=%d, ",
1961 + name ? name : "unknown", cipher_data[i].nid,
1962 + cipher_data[i].devcryptoid);
1963 + if (cipher_driver_info[i].status == DEVCRYPTO_STATUS_NO_CIOCGSESSION ) {
1964 + fprintf (stderr, "CIOCGSESSION (session open call) failed\n");
1967 + fprintf (stderr, "driver=%s ", cipher_driver_info[i].driver_name ?
1968 + cipher_driver_info[i].driver_name : "unknown");
1969 + if (cipher_driver_info[i].accelerated == DEVCRYPTO_ACCELERATED)
1970 + fprintf(stderr, "(hw accelerated)");
1971 + else if (cipher_driver_info[i].accelerated == DEVCRYPTO_NOT_ACCELERATED)
1972 + fprintf(stderr, "(software)");
1974 + fprintf(stderr, "(acceleration status unknown)");
1975 + if (cipher_driver_info[i].status == DEVCRYPTO_STATUS_FAILURE)
1976 + fprintf (stderr, ". Cipher setup failed");
1977 + fprintf(stderr, "\n");
1979 + fprintf(stderr, "\n");
1983 + * We only support digests if the cryptodev implementation supports multiple
1984 + * data updates and session copying. Otherwise, we would be forced to maintain
1985 + * a cache, which is perilous if there's a lot of data coming in (if someone
1986 + * wants to checksum an OpenSSL tarball, for example).
1988 +#if defined(CIOCCPHASH) && defined(COP_FLAG_UPDATE) && defined(COP_FLAG_FINAL)
1989 +#define IMPLEMENT_DIGEST
1991 +/******************************************************************************
1995 + * Because they all do the same basic operation, we have only one set of
1996 + * method functions for them all to share, and a mapping table between
1997 + * NIDs and cryptodev IDs, with all the necessary size data.
2001 +struct digest_ctx {
2002 + struct session_op sess;
2003 + /* This signals that the init function was called, not that it succeeded. */
2005 + unsigned char digest_res[HASH_MAX_LEN];
2008 +static const struct digest_data_st {
2013 +} digest_data[] = {
2014 +#ifndef OPENSSL_NO_MD5
2015 + { NID_md5, /* MD5_CBLOCK */ 64, 16, CRYPTO_MD5 },
2017 + { NID_sha1, SHA_CBLOCK, 20, CRYPTO_SHA1 },
2018 +#ifndef OPENSSL_NO_RMD160
2019 +# if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_RIPEMD160)
2020 + { NID_ripemd160, /* RIPEMD160_CBLOCK */ 64, 20, CRYPTO_RIPEMD160 },
2023 +#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_224)
2024 + { NID_sha224, SHA256_CBLOCK, 224 / 8, CRYPTO_SHA2_224 },
2026 +#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_256)
2027 + { NID_sha256, SHA256_CBLOCK, 256 / 8, CRYPTO_SHA2_256 },
2029 +#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_384)
2030 + { NID_sha384, SHA512_CBLOCK, 384 / 8, CRYPTO_SHA2_384 },
2032 +#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_512)
2033 + { NID_sha512, SHA512_CBLOCK, 512 / 8, CRYPTO_SHA2_512 },
2037 +static size_t find_digest_data_index(int nid)
2041 + for (i = 0; i < OSSL_NELEM(digest_data); i++)
2042 + if (nid == digest_data[i].nid)
2044 + return (size_t)-1;
2047 +static size_t get_digest_data_index(int nid)
2049 + size_t i = find_digest_data_index(nid);
2051 + if (i != (size_t)-1)
2055 + * Code further down must make sure that only NIDs in the table above
2056 + * are used. If any other NID reaches this function, there's a grave
2057 + * coding error further down.
2059 + assert("Code that never should be reached" == NULL);
2063 +static const struct digest_data_st *get_digest_data(int nid)
2065 + return &digest_data[get_digest_data_index(nid)];
2069 + * Following are the five necessary functions to map OpenSSL functionality
2070 + * with cryptodev: init, update, final, cleanup, and copy.
2073 +static int digest_init(EVP_MD_CTX *ctx)
2075 + struct digest_ctx *digest_ctx =
2076 + (struct digest_ctx *)EVP_MD_CTX_md_data(ctx);
2077 + const struct digest_data_st *digest_d =
2078 + get_digest_data(EVP_MD_CTX_type(ctx));
2080 + digest_ctx->init_called = 1;
2082 + memset(&digest_ctx->sess, 0, sizeof(digest_ctx->sess));
2083 + digest_ctx->sess.mac = digest_d->devcryptoid;
2084 + if (ioctl(cfd, CIOCGSESSION, &digest_ctx->sess) < 0) {
2085 + SYSerr(SYS_F_IOCTL, errno);
2091 +static int digest_op(struct digest_ctx *ctx, const void *src, size_t srclen,
2092 + void *res, unsigned int flags)
2094 + struct crypt_op cryp;
2096 + memset(&cryp, 0, sizeof(cryp));
2097 + cryp.ses = ctx->sess.ses;
2098 + cryp.len = srclen;
2099 + cryp.src = (void *)src;
2102 + cryp.flags = flags;
2103 + return ioctl(cfd, CIOCCRYPT, &cryp);
2106 +static int digest_update(EVP_MD_CTX *ctx, const void *data, size_t count)
2108 + struct digest_ctx *digest_ctx =
2109 + (struct digest_ctx *)EVP_MD_CTX_md_data(ctx);
2114 + if (digest_ctx == NULL)
2117 + if (EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_ONESHOT)) {
2118 + if (digest_op(digest_ctx, data, count, digest_ctx->digest_res, 0) >= 0)
2120 + } else if (digest_op(digest_ctx, data, count, NULL, COP_FLAG_UPDATE) >= 0) {
2124 + SYSerr(SYS_F_IOCTL, errno);
2128 +static int digest_final(EVP_MD_CTX *ctx, unsigned char *md)
2130 + struct digest_ctx *digest_ctx =
2131 + (struct digest_ctx *)EVP_MD_CTX_md_data(ctx);
2133 + if (md == NULL || digest_ctx == NULL)
2136 + if (EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_ONESHOT)) {
2137 + memcpy(md, digest_ctx->digest_res, EVP_MD_CTX_size(ctx));
2138 + } else if (digest_op(digest_ctx, NULL, 0, md, COP_FLAG_FINAL) < 0) {
2139 + SYSerr(SYS_F_IOCTL, errno);
2146 +static int digest_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from)
2148 + struct digest_ctx *digest_from =
2149 + (struct digest_ctx *)EVP_MD_CTX_md_data(from);
2150 + struct digest_ctx *digest_to =
2151 + (struct digest_ctx *)EVP_MD_CTX_md_data(to);
2152 + struct cphash_op cphash;
2154 + if (digest_from == NULL || digest_from->init_called != 1)
2157 + if (!digest_init(to)) {
2158 + SYSerr(SYS_F_IOCTL, errno);
2162 + cphash.src_ses = digest_from->sess.ses;
2163 + cphash.dst_ses = digest_to->sess.ses;
2164 + if (ioctl(cfd, CIOCCPHASH, &cphash) < 0) {
2165 + SYSerr(SYS_F_IOCTL, errno);
2171 +static int digest_cleanup(EVP_MD_CTX *ctx)
2173 + struct digest_ctx *digest_ctx =
2174 + (struct digest_ctx *)EVP_MD_CTX_md_data(ctx);
2176 + if (digest_ctx == NULL)
2179 + return clean_devcrypto_session(&digest_ctx->sess);
2183 + * Keep tables of known nids, associated methods, selected digests, and
2185 + * Note that known_digest_nids[] isn't necessarily indexed the same way as
2186 + * digest_data[] above, which the other tables are.
2188 +static int known_digest_nids[OSSL_NELEM(digest_data)];
2189 +static int known_digest_nids_amount = -1; /* -1 indicates not yet initialised */
2190 +static EVP_MD *known_digest_methods[OSSL_NELEM(digest_data)] = { NULL, };
2191 +static int selected_digests[OSSL_NELEM(digest_data)];
2192 +static struct driver_info_st digest_driver_info[OSSL_NELEM(digest_data)];
2194 +static int devcrypto_test_digest(size_t digest_data_index)
2196 + return (digest_driver_info[digest_data_index].status == DEVCRYPTO_STATUS_USABLE
2197 + && selected_digests[digest_data_index] == 1
2198 + && (digest_driver_info[digest_data_index].accelerated
2199 + == DEVCRYPTO_ACCELERATED
2200 + || use_softdrivers == DEVCRYPTO_USE_SOFTWARE
2201 + || (digest_driver_info[digest_data_index].accelerated
2202 + != DEVCRYPTO_NOT_ACCELERATED
2203 + && use_softdrivers == DEVCRYPTO_REJECT_SOFTWARE)));
2206 +static void rebuild_known_digest_nids(ENGINE *e)
2210 + for (i = 0, known_digest_nids_amount = 0; i < OSSL_NELEM(digest_data); i++) {
2211 + if (devcrypto_test_digest(i))
2212 + known_digest_nids[known_digest_nids_amount++] = digest_data[i].nid;
2214 + ENGINE_unregister_digests(e);
2215 + ENGINE_register_digests(e);
2218 +static void prepare_digest_methods(void)
2221 + struct session_op sess1, sess2;
2222 +#ifdef CIOCGSESSINFO
2223 + struct session_info_op siop;
2225 + struct cphash_op cphash;
2227 + memset(&digest_driver_info, 0, sizeof(digest_driver_info));
2229 + memset(&sess1, 0, sizeof(sess1));
2230 + memset(&sess2, 0, sizeof(sess2));
2232 + for (i = 0, known_digest_nids_amount = 0; i < OSSL_NELEM(digest_data);
2235 + selected_digests[i] = 1;
2238 + * Check that the digest is usable
2240 + sess1.mac = digest_data[i].devcryptoid;
2242 + if (ioctl(cfd, CIOCGSESSION, &sess1) < 0) {
2243 + digest_driver_info[i].status = DEVCRYPTO_STATUS_NO_CIOCGSESSION;
2247 +#ifdef CIOCGSESSINFO
2248 + /* gather hardware acceleration info from the driver */
2249 + siop.ses = sess1.ses;
2250 + if (ioctl(cfd, CIOCGSESSINFO, &siop) < 0) {
2251 + digest_driver_info[i].accelerated = DEVCRYPTO_ACCELERATION_UNKNOWN;
2253 + digest_driver_info[i].driver_name =
2254 + OPENSSL_strndup(siop.hash_info.cra_driver_name,
2255 + CRYPTODEV_MAX_ALG_NAME);
2256 + if (siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY)
2257 + digest_driver_info[i].accelerated = DEVCRYPTO_ACCELERATED;
2259 + digest_driver_info[i].accelerated = DEVCRYPTO_NOT_ACCELERATED;
2263 + /* digest must be capable of hash state copy */
2264 + sess2.mac = sess1.mac;
2265 + if (ioctl(cfd, CIOCGSESSION, &sess2) < 0) {
2266 + digest_driver_info[i].status = DEVCRYPTO_STATUS_FAILURE;
2269 + cphash.src_ses = sess1.ses;
2270 + cphash.dst_ses = sess2.ses;
2271 + if (ioctl(cfd, CIOCCPHASH, &cphash) < 0) {
2272 + digest_driver_info[i].status = DEVCRYPTO_STATUS_NO_CIOCCPHASH;
2275 + if ((known_digest_methods[i] = EVP_MD_meth_new(digest_data[i].nid,
2276 + NID_undef)) == NULL
2277 + || !EVP_MD_meth_set_input_blocksize(known_digest_methods[i],
2278 + digest_data[i].blocksize)
2279 + || !EVP_MD_meth_set_result_size(known_digest_methods[i],
2280 + digest_data[i].digestlen)
2281 + || !EVP_MD_meth_set_init(known_digest_methods[i], digest_init)
2282 + || !EVP_MD_meth_set_update(known_digest_methods[i], digest_update)
2283 + || !EVP_MD_meth_set_final(known_digest_methods[i], digest_final)
2284 + || !EVP_MD_meth_set_copy(known_digest_methods[i], digest_copy)
2285 + || !EVP_MD_meth_set_cleanup(known_digest_methods[i], digest_cleanup)
2286 + || !EVP_MD_meth_set_app_datasize(known_digest_methods[i],
2287 + sizeof(struct digest_ctx))) {
2288 + digest_driver_info[i].status = DEVCRYPTO_STATUS_FAILURE;
2289 + EVP_MD_meth_free(known_digest_methods[i]);
2290 + known_digest_methods[i] = NULL;
2293 + digest_driver_info[i].status = DEVCRYPTO_STATUS_USABLE;
2295 + ioctl(cfd, CIOCFSESSION, &sess1.ses);
2296 + if (sess2.ses != 0)
2297 + ioctl(cfd, CIOCFSESSION, &sess2.ses);
2298 + if (devcrypto_test_digest(i))
2299 + known_digest_nids[known_digest_nids_amount++] = digest_data[i].nid;
2303 +static const EVP_MD *get_digest_method(int nid)
2305 + size_t i = get_digest_data_index(nid);
2307 + if (i == (size_t)-1)
2309 + return known_digest_methods[i];
2312 +static int get_digest_nids(const int **nids)
2314 + *nids = known_digest_nids;
2315 + return known_digest_nids_amount;
2318 +static void destroy_digest_method(int nid)
2320 + size_t i = get_digest_data_index(nid);
2322 + EVP_MD_meth_free(known_digest_methods[i]);
2323 + known_digest_methods[i] = NULL;
2326 +static void destroy_all_digest_methods(void)
2330 + for (i = 0; i < OSSL_NELEM(digest_data); i++) {
2331 + destroy_digest_method(digest_data[i].nid);
2332 + OPENSSL_free(digest_driver_info[i].driver_name);
2333 + digest_driver_info[i].driver_name = NULL;
2337 +static int devcrypto_digests(ENGINE *e, const EVP_MD **digest,
2338 + const int **nids, int nid)
2340 + if (digest == NULL)
2341 + return get_digest_nids(nids);
2343 + *digest = get_digest_method(nid);
2345 + return *digest != NULL;
2348 +static void devcrypto_select_all_digests(int *digest_list)
2352 + for (i = 0; i < OSSL_NELEM(digest_data); i++)
2353 + digest_list[i] = 1;
2356 +static int cryptodev_select_digest_cb(const char *str, int len, void *usr)
2358 + int *digest_list = (int *)usr;
2360 + const EVP_MD *EVP;
2365 + if (usr == NULL || (name = OPENSSL_strndup(str, len)) == NULL)
2367 + EVP = EVP_get_digestbyname(name);
2369 + fprintf(stderr, "devcrypto: unknown digest %s\n", name);
2370 + else if ((i = find_digest_data_index(EVP_MD_type(EVP))) != (size_t)-1)
2371 + digest_list[i] = 1;
2373 + fprintf(stderr, "devcrypto: digest %s not available\n", name);
2374 + OPENSSL_free(name);
2378 +static void dump_digest_info(void)
2383 + fprintf (stderr, "Information about digests supported by the /dev/crypto"
2385 +#ifndef CIOCGSESSINFO
2386 + fprintf(stderr, "CIOCGSESSINFO (session info call) unavailable\n");
2389 + for (i = 0; i < OSSL_NELEM(digest_data); i++) {
2390 + name = OBJ_nid2sn(digest_data[i].nid);
2391 + fprintf (stderr, "Digest %s, NID=%d, /dev/crypto info: id=%d, driver=%s",
2392 + name ? name : "unknown", digest_data[i].nid,
2393 + digest_data[i].devcryptoid,
2394 + digest_driver_info[i].driver_name ? digest_driver_info[i].driver_name : "unknown");
2395 + if (digest_driver_info[i].status == DEVCRYPTO_STATUS_NO_CIOCGSESSION) {
2396 + fprintf (stderr, ". CIOCGSESSION (session open) failed\n");
2399 + if (digest_driver_info[i].accelerated == DEVCRYPTO_ACCELERATED)
2400 + fprintf(stderr, " (hw accelerated)");
2401 + else if (digest_driver_info[i].accelerated == DEVCRYPTO_NOT_ACCELERATED)
2402 + fprintf(stderr, " (software)");
2404 + fprintf(stderr, " (acceleration status unknown)");
2405 + if (cipher_driver_info[i].status == DEVCRYPTO_STATUS_FAILURE)
2406 + fprintf (stderr, ". Cipher setup failed\n");
2407 + else if (digest_driver_info[i].status == DEVCRYPTO_STATUS_NO_CIOCCPHASH)
2408 + fprintf(stderr, ", CIOCCPHASH failed\n");
2410 + fprintf(stderr, ", CIOCCPHASH capable\n");
2412 + fprintf(stderr, "\n");
2417 +/******************************************************************************
2419 + * CONTROL COMMANDS
2423 +#define DEVCRYPTO_CMD_USE_SOFTDRIVERS ENGINE_CMD_BASE
2424 +#define DEVCRYPTO_CMD_CIPHERS (ENGINE_CMD_BASE + 1)
2425 +#define DEVCRYPTO_CMD_DIGESTS (ENGINE_CMD_BASE + 2)
2426 +#define DEVCRYPTO_CMD_DUMP_INFO (ENGINE_CMD_BASE + 3)
2428 +/* Helper macros for CPP string composition */
2429 +#ifndef OPENSSL_MSTR
2430 +# define OPENSSL_MSTR_HELPER(x) #x
2431 +# define OPENSSL_MSTR(x) OPENSSL_MSTR_HELPER(x)
2434 +static const ENGINE_CMD_DEFN devcrypto_cmds[] = {
2435 +#ifdef CIOCGSESSINFO
2436 + {DEVCRYPTO_CMD_USE_SOFTDRIVERS,
2437 + "USE_SOFTDRIVERS",
2438 + "specifies whether to use software (not accelerated) drivers ("
2439 + OPENSSL_MSTR(DEVCRYPTO_REQUIRE_ACCELERATED) "=use only accelerated drivers, "
2440 + OPENSSL_MSTR(DEVCRYPTO_USE_SOFTWARE) "=allow all drivers, "
2441 + OPENSSL_MSTR(DEVCRYPTO_REJECT_SOFTWARE)
2442 + "=use if acceleration can't be determined) [default="
2443 + OPENSSL_MSTR(DEVCRYPTO_DEFAULT_USE_SOFTDRIVERS) "]",
2444 + ENGINE_CMD_FLAG_NUMERIC},
2447 + {DEVCRYPTO_CMD_CIPHERS,
2449 + "either ALL, NONE, or a comma-separated list of ciphers to enable [default=ALL]",
2450 + ENGINE_CMD_FLAG_STRING},
2452 +#ifdef IMPLEMENT_DIGEST
2453 + {DEVCRYPTO_CMD_DIGESTS,
2455 + "either ALL, NONE, or a comma-separated list of digests to enable [default=ALL]",
2456 + ENGINE_CMD_FLAG_STRING},
2459 + {DEVCRYPTO_CMD_DUMP_INFO,
2461 + "dump info about each algorithm to stderr; use 'openssl engine -pre DUMP_INFO devcrypto'",
2462 + ENGINE_CMD_FLAG_NO_INPUT},
2464 + {0, NULL, NULL, 0}
2467 +static int devcrypto_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void))
2471 +#ifdef CIOCGSESSINFO
2472 + case DEVCRYPTO_CMD_USE_SOFTDRIVERS:
2474 + case DEVCRYPTO_REQUIRE_ACCELERATED:
2475 + case DEVCRYPTO_USE_SOFTWARE:
2476 + case DEVCRYPTO_REJECT_SOFTWARE:
2479 + fprintf(stderr, "devcrypto: invalid value (%ld) for USE_SOFTDRIVERS\n", i);
2482 + if (use_softdrivers == i)
2484 + use_softdrivers = i;
2485 +#ifdef IMPLEMENT_DIGEST
2486 + rebuild_known_digest_nids(e);
2488 + rebuild_known_cipher_nids(e);
2490 +#endif /* CIOCGSESSINFO */
2492 + case DEVCRYPTO_CMD_CIPHERS:
2495 + if (strcasecmp((const char *)p, "ALL") == 0) {
2496 + devcrypto_select_all_ciphers(selected_ciphers);
2497 + } else if (strcasecmp((const char*)p, "NONE") == 0) {
2498 + memset(selected_ciphers, 0, sizeof(selected_ciphers));
2500 + new_list=OPENSSL_zalloc(sizeof(selected_ciphers));
2501 + if (!CONF_parse_list(p, ',', 1, cryptodev_select_cipher_cb, new_list)) {
2502 + OPENSSL_free(new_list);
2505 + memcpy(selected_ciphers, new_list, sizeof(selected_ciphers));
2506 + OPENSSL_free(new_list);
2508 + rebuild_known_cipher_nids(e);
2511 +#ifdef IMPLEMENT_DIGEST
2512 + case DEVCRYPTO_CMD_DIGESTS:
2515 + if (strcasecmp((const char *)p, "ALL") == 0) {
2516 + devcrypto_select_all_digests(selected_digests);
2517 + } else if (strcasecmp((const char*)p, "NONE") == 0) {
2518 + memset(selected_digests, 0, sizeof(selected_digests));
2520 + new_list=OPENSSL_zalloc(sizeof(selected_digests));
2521 + if (!CONF_parse_list(p, ',', 1, cryptodev_select_digest_cb, new_list)) {
2522 + OPENSSL_free(new_list);
2525 + memcpy(selected_digests, new_list, sizeof(selected_digests));
2526 + OPENSSL_free(new_list);
2528 + rebuild_known_digest_nids(e);
2530 +#endif /* IMPLEMENT_DIGEST */
2532 + case DEVCRYPTO_CMD_DUMP_INFO:
2533 + dump_cipher_info();
2534 +#ifdef IMPLEMENT_DIGEST
2535 + dump_digest_info();
2545 +/******************************************************************************
2552 + * Opens /dev/crypto
2554 +static int open_devcrypto(void)
2559 + if ((cfd = open("/dev/crypto", O_RDWR, 0)) < 0) {
2560 +#ifndef ENGINE_DEVCRYPTO_DEBUG
2561 + if (errno != ENOENT)
2563 + fprintf(stderr, "Could not open /dev/crypto: %s\n", strerror(errno));
2570 +static int close_devcrypto(void)
2579 + fprintf(stderr, "Error closing /dev/crypto: %s\n", strerror(errno));
2585 +static int devcrypto_unload(ENGINE *e)
2587 + destroy_all_cipher_methods();
2588 +#ifdef IMPLEMENT_DIGEST
2589 + destroy_all_digest_methods();
2592 + close_devcrypto();
2597 +static int bind_devcrypto(ENGINE *e) {
2599 + if (!ENGINE_set_id(e, engine_devcrypto_id)
2600 + || !ENGINE_set_name(e, "/dev/crypto engine")
2601 + || !ENGINE_set_destroy_function(e, devcrypto_unload)
2602 + || !ENGINE_set_cmd_defns(e, devcrypto_cmds)
2603 + || !ENGINE_set_ctrl_function(e, devcrypto_ctrl))
2606 + prepare_cipher_methods();
2607 +#ifdef IMPLEMENT_DIGEST
2608 + prepare_digest_methods();
2611 + return (ENGINE_set_ciphers(e, devcrypto_ciphers)
2612 +#ifdef IMPLEMENT_DIGEST
2613 + && ENGINE_set_digests(e, devcrypto_digests)
2616 + * Asymmetric ciphers aren't well supported with /dev/crypto. Among the BSD
2617 + * implementations, it seems to only exist in FreeBSD, and regarding the
2618 + * parameters in its crypt_kop, the manual crypto(4) has this to say:
2620 + * The semantics of these arguments are currently undocumented.
2622 + * Reading through the FreeBSD source code doesn't give much more than
2623 + * their CRK_MOD_EXP implementation for ubsec.
2625 + * It doesn't look much better with cryptodev-linux. They have the crypt_kop
2626 + * structure as well as the command (CRK_*) in cryptodev.h, but no support
2627 + * seems to be implemented at all for the moment.
2629 + * At the time of writing, it seems impossible to write proper support for
2630 + * FreeBSD's asym features without some very deep knowledge and access to
2631 + * specific kernel modules.
2633 + * /Richard Levitte, 2017-05-11
2636 +# ifndef OPENSSL_NO_RSA
2637 + && ENGINE_set_RSA(e, devcrypto_rsa)
2639 +# ifndef OPENSSL_NO_DSA
2640 + && ENGINE_set_DSA(e, devcrypto_dsa)
2642 +# ifndef OPENSSL_NO_DH
2643 + && ENGINE_set_DH(e, devcrypto_dh)
2645 +# ifndef OPENSSL_NO_EC
2646 + && ENGINE_set_EC(e, devcrypto_ec)
2652 +#ifdef OPENSSL_NO_DYNAMIC_ENGINE
2654 + * In case this engine is built into libcrypto, then it doesn't offer any
2655 + * ability to be dynamically loadable.
2657 +void engine_load_devcrypto_int(void)
2661 + if (!open_devcrypto())
2664 + if ((e = ENGINE_new()) == NULL
2665 + || !bind_devcrypto(e)) {
2666 + close_devcrypto();
2672 + ENGINE_free(e); /* Loose our local reference */
2673 + ERR_clear_error();
2678 +static int bind_helper(ENGINE *e, const char *id)
2680 + if ((id && (strcmp(id, engine_devcrypto_id) != 0))
2681 + || !open_devcrypto())
2683 + if (!bind_devcrypto(e)) {
2684 + close_devcrypto();
2690 +IMPLEMENT_DYNAMIC_CHECK_FN()
2691 +IMPLEMENT_DYNAMIC_BIND_FN(bind_helper)