diff options
Diffstat (limited to 'package/libs/openssl/patches/410-eng_devcrypto-add-configuration-options.patch')
-rw-r--r-- | package/libs/openssl/patches/410-eng_devcrypto-add-configuration-options.patch | 566 |
1 files changed, 566 insertions, 0 deletions
diff --git a/package/libs/openssl/patches/410-eng_devcrypto-add-configuration-options.patch b/package/libs/openssl/patches/410-eng_devcrypto-add-configuration-options.patch new file mode 100644 index 0000000000..18a430e83d --- /dev/null +++ b/package/libs/openssl/patches/410-eng_devcrypto-add-configuration-options.patch @@ -0,0 +1,566 @@ +From 800272d22acf95070f22c870eca15bdba0539a6a 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: [PATCH 2/4] 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) + +--- 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 + } + + /* +- * 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, + 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_ + } + + /* +- * 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 *ct + 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,7 +909,153 @@ static int devcrypto_digests(ENGINE *e, + 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; ++} + + /****************************************************************************** + * +@@ -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 |