Initial commit
This commit is contained in:
		| @@ -0,0 +1,569 @@ | ||||
| From 1c2fabcdb34e436286b4a8760cfbfbff11ea551a Mon Sep 17 00:00:00 2001 | ||||
| From: Eneas U de Queiroz <cote2004-github@yahoo.com> | ||||
| Date: Sat, 3 Nov 2018 15:41:10 -0300 | ||||
| Subject: eng_devcrypto: add configuration options | ||||
|  | ||||
| USE_SOFTDRIVERS: whether to use software (not accelerated) drivers | ||||
| CIPHERS: list of ciphers to enable | ||||
| DIGESTS: list of digests to enable | ||||
|  | ||||
| Signed-off-by: Eneas U de Queiroz <cote2004-github@yahoo.com> | ||||
|  | ||||
| Reviewed-by: Matthias St. Pierre <Matthias.St.Pierre@ncp-e.com> | ||||
| Reviewed-by: Richard Levitte <levitte@openssl.org> | ||||
| (Merged from https://github.com/openssl/openssl/pull/7585) | ||||
|  | ||||
| diff --git a/crypto/engine/eng_devcrypto.c b/crypto/engine/eng_devcrypto.c | ||||
| index a2c9a966f7..5ec38ca8f3 100644 | ||||
| --- a/crypto/engine/eng_devcrypto.c | ||||
| +++ b/crypto/engine/eng_devcrypto.c | ||||
| @@ -16,6 +16,7 @@ | ||||
|  #include <unistd.h> | ||||
|  #include <assert.h> | ||||
|   | ||||
| +#include <openssl/conf.h> | ||||
|  #include <openssl/evp.h> | ||||
|  #include <openssl/err.h> | ||||
|  #include <openssl/engine.h> | ||||
| @@ -36,6 +37,30 @@ | ||||
|   * saner...  why re-open /dev/crypto for every session? | ||||
|   */ | ||||
|  static int cfd; | ||||
| +#define DEVCRYPTO_REQUIRE_ACCELERATED 0 /* require confirmation of acceleration */ | ||||
| +#define DEVCRYPTO_USE_SOFTWARE        1 /* allow software drivers */ | ||||
| +#define DEVCRYPTO_REJECT_SOFTWARE     2 /* only disallow confirmed software drivers */ | ||||
| + | ||||
| +#define DEVCRYPTO_DEFAULT_USE_SOFDTRIVERS DEVCRYPTO_REJECT_SOFTWARE | ||||
| +static int use_softdrivers = DEVCRYPTO_DEFAULT_USE_SOFDTRIVERS; | ||||
| + | ||||
| +/* | ||||
| + * cipher/digest status & acceleration definitions | ||||
| + * Make sure the defaults are set to 0 | ||||
| + */ | ||||
| +struct driver_info_st { | ||||
| +    enum devcrypto_status_t { | ||||
| +        DEVCRYPTO_STATUS_UNUSABLE       = -1, /* session open failed */ | ||||
| +        DEVCRYPTO_STATUS_UNKNOWN        =  0, /* not tested yet */ | ||||
| +        DEVCRYPTO_STATUS_USABLE         =  1  /* algo can be used */ | ||||
| +    } status; | ||||
| + | ||||
| +    enum devcrypto_accelerated_t { | ||||
| +        DEVCRYPTO_NOT_ACCELERATED       = -1, /* software implemented */ | ||||
| +        DEVCRYPTO_ACCELERATION_UNKNOWN  =  0, /* acceleration support unkown */ | ||||
| +        DEVCRYPTO_ACCELERATED           =  1  /* hardware accelerated */ | ||||
| +    } accelerated; | ||||
| +}; | ||||
|   | ||||
|  static int clean_devcrypto_session(struct session_op *sess) { | ||||
|      if (ioctl(cfd, CIOCFSESSION, &sess->ses) < 0) { | ||||
| @@ -119,13 +144,22 @@ static const struct cipher_data_st { | ||||
|  #endif | ||||
|  }; | ||||
|   | ||||
| -static size_t get_cipher_data_index(int nid) | ||||
| +static size_t find_cipher_data_index(int nid) | ||||
|  { | ||||
|      size_t i; | ||||
|   | ||||
|      for (i = 0; i < OSSL_NELEM(cipher_data); i++) | ||||
|          if (nid == cipher_data[i].nid) | ||||
|              return i; | ||||
| +    return (size_t)-1; | ||||
| +} | ||||
| + | ||||
| +static size_t get_cipher_data_index(int nid) | ||||
| +{ | ||||
| +    size_t i = find_cipher_data_index(nid); | ||||
| + | ||||
| +    if (i != (size_t)-1) | ||||
| +        return i; | ||||
|   | ||||
|      /* | ||||
|       * Code further down must make sure that only NIDs in the table above | ||||
| @@ -333,19 +367,40 @@ static int cipher_cleanup(EVP_CIPHER_CTX *ctx) | ||||
|  } | ||||
|   | ||||
|  /* | ||||
| - * Keep a table of known nids and associated methods. | ||||
| + * Keep tables of known nids, associated methods, selected ciphers, and driver | ||||
| + * info. | ||||
|   * Note that known_cipher_nids[] isn't necessarily indexed the same way as | ||||
| - * cipher_data[] above, which known_cipher_methods[] is. | ||||
| + * cipher_data[] above, which the other tables are. | ||||
|   */ | ||||
|  static int known_cipher_nids[OSSL_NELEM(cipher_data)]; | ||||
|  static int known_cipher_nids_amount = -1; /* -1 indicates not yet initialised */ | ||||
|  static EVP_CIPHER *known_cipher_methods[OSSL_NELEM(cipher_data)] = { NULL, }; | ||||
| +static int selected_ciphers[OSSL_NELEM(cipher_data)]; | ||||
| +static struct driver_info_st cipher_driver_info[OSSL_NELEM(cipher_data)]; | ||||
| + | ||||
| + | ||||
| +static int devcrypto_test_cipher(size_t cipher_data_index) | ||||
| +{ | ||||
| +    return (cipher_driver_info[cipher_data_index].status == DEVCRYPTO_STATUS_USABLE | ||||
| +            && selected_ciphers[cipher_data_index] == 1 | ||||
| +            && (cipher_driver_info[cipher_data_index].accelerated | ||||
| +                    == DEVCRYPTO_ACCELERATED | ||||
| +                || use_softdrivers == DEVCRYPTO_USE_SOFTWARE | ||||
| +                || (cipher_driver_info[cipher_data_index].accelerated | ||||
| +                        != DEVCRYPTO_NOT_ACCELERATED | ||||
| +                    && use_softdrivers == DEVCRYPTO_REJECT_SOFTWARE))); | ||||
| +} | ||||
|   | ||||
|  static void prepare_cipher_methods(void) | ||||
|  { | ||||
|      size_t i; | ||||
|      struct session_op sess; | ||||
|      unsigned long cipher_mode; | ||||
| +#ifdef CIOCGSESSINFO | ||||
| +    struct session_info_op siop; | ||||
| +#endif | ||||
| + | ||||
| +    memset(&cipher_driver_info, 0, sizeof(cipher_driver_info)); | ||||
|   | ||||
|      memset(&sess, 0, sizeof(sess)); | ||||
|      sess.key = (void *)"01234567890123456789012345678901234567890123456789"; | ||||
| @@ -353,15 +408,16 @@ static void prepare_cipher_methods(void) | ||||
|      for (i = 0, known_cipher_nids_amount = 0; | ||||
|           i < OSSL_NELEM(cipher_data); i++) { | ||||
|   | ||||
| +        selected_ciphers[i] = 1; | ||||
|          /* | ||||
| -         * Check that the algo is really availably by trying to open and close | ||||
| -         * a session. | ||||
| +         * Check that the cipher is usable | ||||
|           */ | ||||
|          sess.cipher = cipher_data[i].devcryptoid; | ||||
|          sess.keylen = cipher_data[i].keylen; | ||||
| -        if (ioctl(cfd, CIOCGSESSION, &sess) < 0 | ||||
| -            || ioctl(cfd, CIOCFSESSION, &sess.ses) < 0) | ||||
| +        if (ioctl(cfd, CIOCGSESSION, &sess) < 0) { | ||||
| +            cipher_driver_info[i].status = DEVCRYPTO_STATUS_UNUSABLE; | ||||
|              continue; | ||||
| +        } | ||||
|   | ||||
|          cipher_mode = cipher_data[i].flags & EVP_CIPH_MODE; | ||||
|   | ||||
| @@ -387,15 +443,41 @@ static void prepare_cipher_methods(void) | ||||
|                                              cipher_cleanup) | ||||
|              || !EVP_CIPHER_meth_set_impl_ctx_size(known_cipher_methods[i], | ||||
|                                                    sizeof(struct cipher_ctx))) { | ||||
| +            cipher_driver_info[i].status = DEVCRYPTO_STATUS_UNUSABLE; | ||||
|              EVP_CIPHER_meth_free(known_cipher_methods[i]); | ||||
|              known_cipher_methods[i] = NULL; | ||||
|          } else { | ||||
| +            cipher_driver_info[i].status = DEVCRYPTO_STATUS_USABLE; | ||||
| +#ifdef CIOCGSESSINFO | ||||
| +            siop.ses = sess.ses; | ||||
| +            if (ioctl(cfd, CIOCGSESSINFO, &siop) < 0) | ||||
| +                cipher_driver_info[i].accelerated = DEVCRYPTO_ACCELERATION_UNKNOWN; | ||||
| +            else if (!(siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY)) | ||||
| +                cipher_driver_info[i].accelerated = DEVCRYPTO_NOT_ACCELERATED; | ||||
| +            else | ||||
| +                cipher_driver_info[i].accelerated = DEVCRYPTO_ACCELERATED; | ||||
| +#endif /* CIOCGSESSINFO */ | ||||
| +        } | ||||
| +        ioctl(cfd, CIOCFSESSION, &sess.ses); | ||||
| +        if (devcrypto_test_cipher(i)) { | ||||
|              known_cipher_nids[known_cipher_nids_amount++] = | ||||
|                  cipher_data[i].nid; | ||||
|          } | ||||
|      } | ||||
|  } | ||||
|   | ||||
| +static void rebuild_known_cipher_nids(ENGINE *e) | ||||
| +{ | ||||
| +    size_t i; | ||||
| + | ||||
| +    for (i = 0, known_cipher_nids_amount = 0; i < OSSL_NELEM(cipher_data); i++) { | ||||
| +        if (devcrypto_test_cipher(i)) | ||||
| +            known_cipher_nids[known_cipher_nids_amount++] = cipher_data[i].nid; | ||||
| +    } | ||||
| +    ENGINE_unregister_ciphers(e); | ||||
| +    ENGINE_register_ciphers(e); | ||||
| +} | ||||
| + | ||||
|  static const EVP_CIPHER *get_cipher_method(int nid) | ||||
|  { | ||||
|      size_t i = get_cipher_data_index(nid); | ||||
| @@ -438,6 +520,36 @@ static int devcrypto_ciphers(ENGINE *e, const EVP_CIPHER **cipher, | ||||
|      return *cipher != NULL; | ||||
|  } | ||||
|   | ||||
| +static void devcrypto_select_all_ciphers(int *cipher_list) | ||||
| +{ | ||||
| +    size_t i; | ||||
| + | ||||
| +    for (i = 0; i < OSSL_NELEM(cipher_data); i++) | ||||
| +        cipher_list[i] = 1; | ||||
| +} | ||||
| + | ||||
| +static int cryptodev_select_cipher_cb(const char *str, int len, void *usr) | ||||
| +{ | ||||
| +    int *cipher_list = (int *)usr; | ||||
| +    char *name; | ||||
| +    const EVP_CIPHER *EVP; | ||||
| +    size_t i; | ||||
| + | ||||
| +    if (len == 0) | ||||
| +        return 1; | ||||
| +    if (usr == NULL || (name = OPENSSL_strndup(str, len)) == NULL) | ||||
| +        return 0; | ||||
| +    EVP = EVP_get_cipherbyname(name); | ||||
| +    if (EVP == NULL) | ||||
| +        fprintf(stderr, "devcrypto: unknown cipher %s\n", name); | ||||
| +    else if ((i = find_cipher_data_index(EVP_CIPHER_nid(EVP))) != (size_t)-1) | ||||
| +        cipher_list[i] = 1; | ||||
| +    else | ||||
| +        fprintf(stderr, "devcrypto: cipher %s not available\n", name); | ||||
| +    OPENSSL_free(name); | ||||
| +    return 1; | ||||
| +} | ||||
| + | ||||
|  /* | ||||
|   * We only support digests if the cryptodev implementation supports multiple | ||||
|   * data updates and session copying.  Otherwise, we would be forced to maintain | ||||
| @@ -493,13 +605,22 @@ static const struct digest_data_st { | ||||
|  #endif | ||||
|  }; | ||||
|   | ||||
| -static size_t get_digest_data_index(int nid) | ||||
| +static size_t find_digest_data_index(int nid) | ||||
|  { | ||||
|      size_t i; | ||||
|   | ||||
|      for (i = 0; i < OSSL_NELEM(digest_data); i++) | ||||
|          if (nid == digest_data[i].nid) | ||||
|              return i; | ||||
| +    return (size_t)-1; | ||||
| +} | ||||
| + | ||||
| +static size_t get_digest_data_index(int nid) | ||||
| +{ | ||||
| +    size_t i = find_digest_data_index(nid); | ||||
| + | ||||
| +    if (i != (size_t)-1) | ||||
| +        return i; | ||||
|   | ||||
|      /* | ||||
|       * Code further down must make sure that only NIDs in the table above | ||||
| @@ -516,8 +637,8 @@ static const struct digest_data_st *get_digest_data(int nid) | ||||
|  } | ||||
|   | ||||
|  /* | ||||
| - * Following are the four necessary functions to map OpenSSL functionality | ||||
| - * with cryptodev. | ||||
| + * Following are the five necessary functions to map OpenSSL functionality | ||||
| + * with cryptodev: init, update, final, cleanup, and copy. | ||||
|   */ | ||||
|   | ||||
|  static int digest_init(EVP_MD_CTX *ctx) | ||||
| @@ -630,52 +751,94 @@ static int digest_cleanup(EVP_MD_CTX *ctx) | ||||
|      return clean_devcrypto_session(&digest_ctx->sess); | ||||
|  } | ||||
|   | ||||
| -static int devcrypto_test_digest(size_t digest_data_index) | ||||
| -{ | ||||
| -    struct session_op sess1, sess2; | ||||
| -    struct cphash_op cphash; | ||||
| -    int ret=0; | ||||
| - | ||||
| -    memset(&sess1, 0, sizeof(sess1)); | ||||
| -    memset(&sess2, 0, sizeof(sess2)); | ||||
| -    sess1.mac = digest_data[digest_data_index].devcryptoid; | ||||
| -    if (ioctl(cfd, CIOCGSESSION, &sess1) < 0) | ||||
| -        return 0; | ||||
| -    /* Make sure the driver is capable of hash state copy */ | ||||
| -    sess2.mac = sess1.mac; | ||||
| -    if (ioctl(cfd, CIOCGSESSION, &sess2) >= 0) { | ||||
| -        cphash.src_ses = sess1.ses; | ||||
| -        cphash.dst_ses = sess2.ses; | ||||
| -        if (ioctl(cfd, CIOCCPHASH, &cphash) >= 0) | ||||
| -            ret = 1; | ||||
| -        ioctl(cfd, CIOCFSESSION, &sess2.ses); | ||||
| -    } | ||||
| -    ioctl(cfd, CIOCFSESSION, &sess1.ses); | ||||
| -    return ret; | ||||
| -} | ||||
| - | ||||
|  /* | ||||
| - * Keep a table of known nids and associated methods. | ||||
| + * Keep tables of known nids, associated methods, selected digests, and | ||||
| + * driver info. | ||||
|   * Note that known_digest_nids[] isn't necessarily indexed the same way as | ||||
| - * digest_data[] above, which known_digest_methods[] is. | ||||
| + * digest_data[] above, which the other tables are. | ||||
|   */ | ||||
|  static int known_digest_nids[OSSL_NELEM(digest_data)]; | ||||
|  static int known_digest_nids_amount = -1; /* -1 indicates not yet initialised */ | ||||
|  static EVP_MD *known_digest_methods[OSSL_NELEM(digest_data)] = { NULL, }; | ||||
| +static int selected_digests[OSSL_NELEM(digest_data)]; | ||||
| +static struct driver_info_st digest_driver_info[OSSL_NELEM(digest_data)]; | ||||
| + | ||||
| +static int devcrypto_test_digest(size_t digest_data_index) | ||||
| +{ | ||||
| +    return (digest_driver_info[digest_data_index].status == DEVCRYPTO_STATUS_USABLE | ||||
| +            && selected_digests[digest_data_index] == 1 | ||||
| +            && (digest_driver_info[digest_data_index].accelerated | ||||
| +                    == DEVCRYPTO_ACCELERATED | ||||
| +                || use_softdrivers == DEVCRYPTO_USE_SOFTWARE | ||||
| +                || (digest_driver_info[digest_data_index].accelerated | ||||
| +                        != DEVCRYPTO_NOT_ACCELERATED | ||||
| +                    && use_softdrivers == DEVCRYPTO_REJECT_SOFTWARE))); | ||||
| +} | ||||
| + | ||||
| +static void rebuild_known_digest_nids(ENGINE *e) | ||||
| +{ | ||||
| +    size_t i; | ||||
| + | ||||
| +    for (i = 0, known_digest_nids_amount = 0; i < OSSL_NELEM(digest_data); i++) { | ||||
| +        if (devcrypto_test_digest(i)) | ||||
| +            known_digest_nids[known_digest_nids_amount++] = digest_data[i].nid; | ||||
| +    } | ||||
| +    ENGINE_unregister_digests(e); | ||||
| +    ENGINE_register_digests(e); | ||||
| +} | ||||
|   | ||||
|  static void prepare_digest_methods(void) | ||||
|  { | ||||
|      size_t i; | ||||
| +    struct session_op sess1, sess2; | ||||
| +#ifdef CIOCGSESSINFO | ||||
| +    struct session_info_op siop; | ||||
| +#endif | ||||
| +    struct cphash_op cphash; | ||||
| + | ||||
| +    memset(&digest_driver_info, 0, sizeof(digest_driver_info)); | ||||
| + | ||||
| +    memset(&sess1, 0, sizeof(sess1)); | ||||
| +    memset(&sess2, 0, sizeof(sess2)); | ||||
|   | ||||
|      for (i = 0, known_digest_nids_amount = 0; i < OSSL_NELEM(digest_data); | ||||
|           i++) { | ||||
|   | ||||
| +        selected_digests[i] = 1; | ||||
| + | ||||
|          /* | ||||
| -         * Check that the algo is usable | ||||
| +         * Check that the digest is usable | ||||
|           */ | ||||
| -        if (!devcrypto_test_digest(i)) | ||||
| -            continue; | ||||
| +        sess1.mac = digest_data[i].devcryptoid; | ||||
| +        sess2.ses = 0; | ||||
| +        if (ioctl(cfd, CIOCGSESSION, &sess1) < 0) { | ||||
| +            digest_driver_info[i].status = DEVCRYPTO_STATUS_UNUSABLE; | ||||
| +            goto finish; | ||||
| +        } | ||||
|   | ||||
| +#ifdef CIOCGSESSINFO | ||||
| +        /* gather hardware acceleration info from the driver */ | ||||
| +        siop.ses = sess1.ses; | ||||
| +        if (ioctl(cfd, CIOCGSESSINFO, &siop) < 0) | ||||
| +            digest_driver_info[i].accelerated = DEVCRYPTO_ACCELERATION_UNKNOWN; | ||||
| +        else if (siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY) | ||||
| +            digest_driver_info[i].accelerated = DEVCRYPTO_ACCELERATED; | ||||
| +        else | ||||
| +            digest_driver_info[i].accelerated = DEVCRYPTO_NOT_ACCELERATED; | ||||
| +#endif | ||||
| + | ||||
| +        /* digest must be capable of hash state copy */ | ||||
| +        sess2.mac = sess1.mac; | ||||
| +        if (ioctl(cfd, CIOCGSESSION, &sess2) < 0) { | ||||
| +            digest_driver_info[i].status = DEVCRYPTO_STATUS_UNUSABLE; | ||||
| +            goto finish; | ||||
| +        } | ||||
| +        cphash.src_ses = sess1.ses; | ||||
| +        cphash.dst_ses = sess2.ses; | ||||
| +        if (ioctl(cfd, CIOCCPHASH, &cphash) < 0) { | ||||
| +            digest_driver_info[i].status = DEVCRYPTO_STATUS_UNUSABLE; | ||||
| +            goto finish; | ||||
| +        } | ||||
|          if ((known_digest_methods[i] = EVP_MD_meth_new(digest_data[i].nid, | ||||
|                                                         NID_undef)) == NULL | ||||
|              || !EVP_MD_meth_set_input_blocksize(known_digest_methods[i], | ||||
| @@ -689,11 +852,18 @@ static void prepare_digest_methods(void) | ||||
|              || !EVP_MD_meth_set_cleanup(known_digest_methods[i], digest_cleanup) | ||||
|              || !EVP_MD_meth_set_app_datasize(known_digest_methods[i], | ||||
|                                               sizeof(struct digest_ctx))) { | ||||
| +            digest_driver_info[i].status = DEVCRYPTO_STATUS_UNUSABLE; | ||||
|              EVP_MD_meth_free(known_digest_methods[i]); | ||||
|              known_digest_methods[i] = NULL; | ||||
| -        } else { | ||||
| -            known_digest_nids[known_digest_nids_amount++] = digest_data[i].nid; | ||||
| +            goto finish; | ||||
|          } | ||||
| +        digest_driver_info[i].status = DEVCRYPTO_STATUS_USABLE; | ||||
| +finish: | ||||
| +        ioctl(cfd, CIOCFSESSION, &sess1.ses); | ||||
| +        if (sess2.ses != 0) | ||||
| +            ioctl(cfd, CIOCFSESSION, &sess2.ses); | ||||
| +        if (devcrypto_test_digest(i)) | ||||
| +            known_digest_nids[known_digest_nids_amount++] = digest_data[i].nid; | ||||
|      } | ||||
|  } | ||||
|   | ||||
| @@ -739,8 +909,154 @@ static int devcrypto_digests(ENGINE *e, const EVP_MD **digest, | ||||
|      return *digest != NULL; | ||||
|  } | ||||
|   | ||||
| +static void devcrypto_select_all_digests(int *digest_list) | ||||
| +{ | ||||
| +    size_t i; | ||||
| + | ||||
| +    for (i = 0; i < OSSL_NELEM(digest_data); i++) | ||||
| +        digest_list[i] = 1; | ||||
| +} | ||||
| + | ||||
| +static int cryptodev_select_digest_cb(const char *str, int len, void *usr) | ||||
| +{ | ||||
| +    int *digest_list = (int *)usr; | ||||
| +    char *name; | ||||
| +    const EVP_MD *EVP; | ||||
| +    size_t i; | ||||
| + | ||||
| +    if (len == 0) | ||||
| +        return 1; | ||||
| +    if (usr == NULL || (name = OPENSSL_strndup(str, len)) == NULL) | ||||
| +        return 0; | ||||
| +    EVP = EVP_get_digestbyname(name); | ||||
| +    if (EVP == NULL) | ||||
| +        fprintf(stderr, "devcrypto: unknown digest %s\n", name); | ||||
| +    else if ((i = find_digest_data_index(EVP_MD_type(EVP))) != (size_t)-1) | ||||
| +        digest_list[i] = 1; | ||||
| +    else | ||||
| +        fprintf(stderr, "devcrypto: digest %s not available\n", name); | ||||
| +    OPENSSL_free(name); | ||||
| +    return 1; | ||||
| +} | ||||
| + | ||||
| +#endif | ||||
| + | ||||
| +/****************************************************************************** | ||||
| + * | ||||
| + * CONTROL COMMANDS | ||||
| + * | ||||
| + *****/ | ||||
| + | ||||
| +#define DEVCRYPTO_CMD_USE_SOFTDRIVERS ENGINE_CMD_BASE | ||||
| +#define DEVCRYPTO_CMD_CIPHERS (ENGINE_CMD_BASE + 1) | ||||
| +#define DEVCRYPTO_CMD_DIGESTS (ENGINE_CMD_BASE + 2) | ||||
| +#define DEVCRYPTO_CMD_DUMP_INFO (ENGINE_CMD_BASE + 3) | ||||
| + | ||||
| +/* Helper macros for CPP string composition */ | ||||
| +#ifndef OPENSSL_MSTR | ||||
| +# define OPENSSL_MSTR_HELPER(x) #x | ||||
| +# define OPENSSL_MSTR(x) OPENSSL_MSTR_HELPER(x) | ||||
| +#endif | ||||
| + | ||||
| +static const ENGINE_CMD_DEFN devcrypto_cmds[] = { | ||||
| +#ifdef CIOCGSESSINFO | ||||
| +   {DEVCRYPTO_CMD_USE_SOFTDRIVERS, | ||||
| +    "USE_SOFTDRIVERS", | ||||
| +    "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_SOFDTRIVERS) "]", | ||||
| +    ENGINE_CMD_FLAG_NUMERIC}, | ||||
| +#endif | ||||
| + | ||||
| +   {DEVCRYPTO_CMD_CIPHERS, | ||||
| +    "CIPHERS", | ||||
| +    "either ALL, NONE, or a comma-separated list of ciphers to enable [default=ALL]", | ||||
| +    ENGINE_CMD_FLAG_STRING}, | ||||
| + | ||||
| +#ifdef IMPLEMENT_DIGEST | ||||
| +   {DEVCRYPTO_CMD_DIGESTS, | ||||
| +    "DIGESTS", | ||||
| +    "either ALL, NONE, or a comma-separated list of digests to enable [default=ALL]", | ||||
| +    ENGINE_CMD_FLAG_STRING}, | ||||
|  #endif | ||||
|   | ||||
| +   {0, NULL, NULL, 0} | ||||
| +}; | ||||
| + | ||||
| +static int devcrypto_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void)) | ||||
| +{ | ||||
| +    int *new_list; | ||||
| +    switch (cmd) { | ||||
| +#ifdef CIOCGSESSINFO | ||||
| +    case DEVCRYPTO_CMD_USE_SOFTDRIVERS: | ||||
| +        switch (i) { | ||||
| +        case DEVCRYPTO_REQUIRE_ACCELERATED: | ||||
| +        case DEVCRYPTO_USE_SOFTWARE: | ||||
| +        case DEVCRYPTO_REJECT_SOFTWARE: | ||||
| +            break; | ||||
| +        default: | ||||
| +            fprintf(stderr, "devcrypto: invalid value (%ld) for USE_SOFTDRIVERS\n", i); | ||||
| +            return 0; | ||||
| +        } | ||||
| +        if (use_softdrivers == i) | ||||
| +            return 1; | ||||
| +        use_softdrivers = i; | ||||
| +#ifdef IMPLEMENT_DIGEST | ||||
| +        rebuild_known_digest_nids(e); | ||||
| +#endif | ||||
| +        rebuild_known_cipher_nids(e); | ||||
| +        return 1; | ||||
| +#endif /* CIOCGSESSINFO */ | ||||
| + | ||||
| +    case DEVCRYPTO_CMD_CIPHERS: | ||||
| +        if (p == NULL) | ||||
| +            return 1; | ||||
| +        if (strcasecmp((const char *)p, "ALL") == 0) { | ||||
| +            devcrypto_select_all_ciphers(selected_ciphers); | ||||
| +        } else if (strcasecmp((const char*)p, "NONE") == 0) { | ||||
| +            memset(selected_ciphers, 0, sizeof(selected_ciphers)); | ||||
| +        } else { | ||||
| +            new_list=OPENSSL_zalloc(sizeof(selected_ciphers)); | ||||
| +            if (!CONF_parse_list(p, ',', 1, cryptodev_select_cipher_cb, new_list)) { | ||||
| +                OPENSSL_free(new_list); | ||||
| +                return 0; | ||||
| +            } | ||||
| +            memcpy(selected_ciphers, new_list, sizeof(selected_ciphers)); | ||||
| +            OPENSSL_free(new_list); | ||||
| +        } | ||||
| +        rebuild_known_cipher_nids(e); | ||||
| +        return 1; | ||||
| + | ||||
| +#ifdef IMPLEMENT_DIGEST | ||||
| +    case DEVCRYPTO_CMD_DIGESTS: | ||||
| +        if (p == NULL) | ||||
| +            return 1; | ||||
| +        if (strcasecmp((const char *)p, "ALL") == 0) { | ||||
| +            devcrypto_select_all_digests(selected_digests); | ||||
| +        } else if (strcasecmp((const char*)p, "NONE") == 0) { | ||||
| +            memset(selected_digests, 0, sizeof(selected_digests)); | ||||
| +        } else { | ||||
| +            new_list=OPENSSL_zalloc(sizeof(selected_digests)); | ||||
| +            if (!CONF_parse_list(p, ',', 1, cryptodev_select_digest_cb, new_list)) { | ||||
| +                OPENSSL_free(new_list); | ||||
| +                return 0; | ||||
| +            } | ||||
| +            memcpy(selected_digests, new_list, sizeof(selected_digests)); | ||||
| +            OPENSSL_free(new_list); | ||||
| +        } | ||||
| +        rebuild_known_digest_nids(e); | ||||
| +        return 1; | ||||
| +#endif /* IMPLEMENT_DIGEST */ | ||||
| + | ||||
| +    default: | ||||
| +        break; | ||||
| +    } | ||||
| +    return 0; | ||||
| +} | ||||
| + | ||||
|  /****************************************************************************** | ||||
|   * | ||||
|   * LOAD / UNLOAD | ||||
| @@ -793,6 +1109,8 @@ void engine_load_devcrypto_int() | ||||
|   | ||||
|      if (!ENGINE_set_id(e, "devcrypto") | ||||
|          || !ENGINE_set_name(e, "/dev/crypto engine") | ||||
| +        || !ENGINE_set_cmd_defns(e, devcrypto_cmds) | ||||
| +        || !ENGINE_set_ctrl_function(e, devcrypto_ctrl) | ||||
|   | ||||
|  /* | ||||
|   * Asymmetric ciphers aren't well supported with /dev/crypto.  Among the BSD | ||||
		Reference in New Issue
	
	Block a user
	 domenico
					domenico