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