diff --git a/.gitignore b/.gitignore index be7d21a..0d89bbd 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/openssl-ibmca-2.3.1.tar.gz +SOURCES/openssl-ibmca-2.4.0.tar.gz diff --git a/.openssl-ibmca.metadata b/.openssl-ibmca.metadata index aa192b9..888dcd4 100644 --- a/.openssl-ibmca.metadata +++ b/.openssl-ibmca.metadata @@ -1 +1 @@ -5e5ac182d30787788c94b5dcdf9a3a21d209bbaf SOURCES/openssl-ibmca-2.3.1.tar.gz +d1361eec709c4b6d1760171ac077fa0d21f5a698 SOURCES/openssl-ibmca-2.4.0.tar.gz diff --git a/SOURCES/openssl-ibmca-2.3.1-fixes.patch b/SOURCES/openssl-ibmca-2.3.1-fixes.patch deleted file mode 100644 index 5e63b2e..0000000 --- a/SOURCES/openssl-ibmca-2.3.1-fixes.patch +++ /dev/null @@ -1,827 +0,0 @@ -From ec926d577754babce01db22274a582988c5c4e44 Mon Sep 17 00:00:00 2001 -From: Ingo Franzki -Date: Wed, 12 Oct 2022 09:40:27 +0200 -Subject: [PATCH 1/4] provider: Support EC parameter generation with named - curve - -In general the IBMCA provider does not support EC parameter generation, -because libica only supports certain named curves. However, one can -also use EC parameter generation with a named curve, and then use such -parameter key object as template for generating other keys. One example -for this is the openssl speed utility. - -Like for EC key generation, EC parameter generation only supports -parameters 'group', 'point-format', 'encoding', and 'use-cofactor-flag', -where the only accepted value for parameter 'encoding' is 'named_curve', -and the only accepted value for parameter 'use-cofactor-flag' is '0'. - -Signed-off-by: Ingo Franzki ---- - src/provider/ec_keymgmt.c | 10 ++++++++-- - src/provider/p_ibmca.h | 1 + - 2 files changed, 9 insertions(+), 2 deletions(-) - -diff --git a/src/provider/ec_keymgmt.c b/src/provider/ec_keymgmt.c -index d39b1e2..97516f1 100644 ---- a/src/provider/ec_keymgmt.c -+++ b/src/provider/ec_keymgmt.c -@@ -928,9 +928,10 @@ static void *ibmca_keymgmt_ec_gen_init(void *vprovctx, int selection, - for (p = params; p != NULL && p->key != NULL; p++) - ibmca_debug_ctx(provctx, "param: %s", p->key); - -- if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0) { -+ if ((selection & (OSSL_KEYMGMT_SELECT_KEYPAIR | -+ OSSL_KEYMGMT_SELECT_ALL_PARAMETERS)) == 0) { - put_error_ctx(provctx, IBMCA_ERR_INVALID_PARAM, -- "selection is not KEYPAIR"); -+ "selection is not KEYPAIR and/or parameters"); - return NULL; - } - -@@ -943,6 +944,7 @@ static void *ibmca_keymgmt_ec_gen_init(void *vprovctx, int selection, - } - - /* set defaults */ -+ ctx->ec.gen.selection = selection; - ctx->ec.gen.curve_nid = NID_undef; - ctx->ec.gen.format = POINT_CONVERSION_UNCOMPRESSED; - -@@ -1223,6 +1225,9 @@ static void *ibmca_keymgmt_ec_gen(void *vgenctx, OSSL_CALLBACK *osslcb, - - ibmca_debug_op_ctx(genctx, "prime_size: %lu", key->ec.prime_size); - -+ if ((genctx->ec.gen.selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0) -+ goto out; -+ - key->ec.key = ica_ec_key_new(key->ec.curve_nid, &privlen); - if (key->ec.key == NULL || key->ec.prime_size != privlen) { - ibmca_debug_op_ctx(genctx, "ica_ec_key_new failed"); -@@ -1267,6 +1272,7 @@ static void *ibmca_keymgmt_ec_gen(void *vgenctx, OSSL_CALLBACK *osslcb, - return NULL; - } - -+out: - ibmca_debug_op_ctx(genctx, "key: %p", key); - - return key; -diff --git a/src/provider/p_ibmca.h b/src/provider/p_ibmca.h -index fa0e1ee..2b4ff8e 100644 ---- a/src/provider/p_ibmca.h -+++ b/src/provider/p_ibmca.h -@@ -216,6 +216,7 @@ struct ibmca_op_ctx { - } rsa; /* For type EVP_PKEY_RSA and EVP_PKEY_RSA_PSS */ - union { - struct { -+ int selection; - int curve_nid; - point_conversion_form_t format; - } gen; /* For operation EVP_PKEY_OP_KEYGEN */ --- -2.39.0 - - -From a462093d2478b287cb9a7a25131788eba16b7640 Mon Sep 17 00:00:00 2001 -From: Ingo Franzki -Date: Fri, 14 Oct 2022 11:31:16 +0200 -Subject: [PATCH 2/4] engine: EC: Cache ICA key in EC_KEY object - -Creating a new ICA EC key via ica_ec_key_init() is time consuming, because -libica performs EC key checks on the key components. - -Currently every sign, verify or derive operation creates a new ICA key, and -thus suffers from the long taking EC key checks with every operation. - -Change this to create an ICA key on the first usage of an EC key, and attach -the ICA key to the EC_KEY object as ex-data. That way, subsequent operations -using the same key will reuse the attached ICA key and do not have to create -a new ICA key again. - -Signed-off-by: Ingo Franzki ---- - src/engine/e_ibmca.c | 5 + - src/engine/ibmca.h | 1 + - src/engine/ibmca_ec.c | 411 ++++++++++++++++++++++++++++++------------ - 3 files changed, 306 insertions(+), 111 deletions(-) - -diff --git a/src/engine/e_ibmca.c b/src/engine/e_ibmca.c -index d045828..fe21897 100644 ---- a/src/engine/e_ibmca.c -+++ b/src/engine/e_ibmca.c -@@ -833,6 +833,11 @@ static int ibmca_init(ENGINE *e) - goto err; - } - -+#ifndef NO_EC -+ if (!ibmca_ec_init()) -+ goto err; -+#endif -+ - if (!set_supported_meths(e)) - goto err; - -diff --git a/src/engine/ibmca.h b/src/engine/ibmca.h -index 37bdfd8..7281a5b 100644 ---- a/src/engine/ibmca.h -+++ b/src/engine/ibmca.h -@@ -298,6 +298,7 @@ void ibmca_dh_destroy(void); - #define IBMCA_EC_MAX_Z_LEN IBMCA_EC_MAX_D_LEN - - #ifndef OPENSSL_NO_EC -+int ibmca_ec_init(void); - void ibmca_ec_destroy(void); - - int ibmca_ecdh_compute_key(unsigned char **pout, size_t *poutlen, -diff --git a/src/engine/ibmca_ec.c b/src/engine/ibmca_ec.c -index 8bc6cbf..5206ae3 100644 ---- a/src/engine/ibmca_ec.c -+++ b/src/engine/ibmca_ec.c -@@ -16,6 +16,7 @@ - */ - - #include -+#include - #include "ibmca.h" - #include "e_ibmca_err.h" - -@@ -31,6 +32,251 @@ ica_ec_key_get_public_key_t p_ica_ec_key_get_public_key; - ica_ec_key_get_private_key_t p_ica_ec_key_get_private_key; - ica_ec_key_free_t p_ica_ec_key_free; - -+int ec_ex_data_index = -1; -+pthread_mutex_t ec_ex_data_mutex = PTHREAD_MUTEX_INITIALIZER; -+ -+struct ibmca_ec_ex_data { -+ ICA_EC_KEY *ica_key; -+ int nid; -+ unsigned int privlen; -+}; -+ -+void ibmca_ec_ex_data_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad, -+ int idx, long argl, void *argp) -+{ -+ struct ibmca_ec_ex_data *data = ptr; -+ -+ if (data == NULL) -+ return; -+ -+ p_ica_ec_key_free(data->ica_key); -+ OPENSSL_free(data); -+} -+ -+int ibmca_ec_ex_data_dup(CRYPTO_EX_DATA *to, const CRYPTO_EX_DATA *from, -+#ifdef OPENSSL_VERSION_PREREQ -+ void **pptr, int idx, long argl, void *argp) -+#else -+ void *from_d, int idx, long argl, void *argp) -+#endif -+{ -+#ifndef OPENSSL_VERSION_PREREQ -+ void **pptr = (void **)from_d; -+#endif -+ struct ibmca_ec_ex_data *from_data; -+ struct ibmca_ec_ex_data *to_data; -+ unsigned char Q[2 * IBMCA_EC_MAX_D_LEN]; -+ unsigned char D[IBMCA_EC_MAX_D_LEN]; -+ unsigned int len; -+ int rc; -+ -+ if (pptr == NULL) -+ return 0; -+ -+ from_data = (struct ibmca_ec_ex_data *)*pptr; -+ if (from_data == NULL) -+ return 0; -+ -+ to_data = OPENSSL_zalloc(sizeof(*to_data)); -+ if (to_data == NULL) { -+ return 0; -+ } -+ -+ to_data->nid = from_data->nid; -+ to_data->ica_key = p_ica_ec_key_new(to_data->nid, &to_data->privlen); -+ if (to_data->ica_key == NULL) { -+ IBMCAerr(IBMCA_F_ICA_EC_KEY_NEW, IBMCA_R_EC_ICA_EC_KEY_INIT); -+ goto error; -+ } -+ -+ if (p_ica_ec_key_get_private_key(from_data->ica_key, D, &len) == 0) { -+ rc = p_ica_ec_key_init(NULL, NULL, D, to_data->ica_key); -+ if (rc != 0) { -+ IBMCAerr(IBMCA_F_ICA_EC_KEY_INIT, rc); -+ goto error; -+ } -+ } -+ -+ if (p_ica_ec_key_get_public_key(from_data->ica_key, Q, &len) == 0) { -+ rc = p_ica_ec_key_init(Q, Q + to_data->privlen, NULL, to_data->ica_key); -+ if (rc != 0) { -+ IBMCAerr(IBMCA_F_ICA_EC_KEY_INIT, rc); -+ goto error; -+ } -+ } -+ -+ *pptr = to_data; -+ -+ return 1; -+ -+error: -+ if (to_data->ica_key != NULL) -+ p_ica_ec_key_free(to_data->ica_key); -+ OPENSSL_free(to_data); -+ -+ return 0; -+} -+ -+static ICA_EC_KEY *ibmca_ec_make_ica_key(EC_KEY *ec_key, int *nid, -+ unsigned int *privlen) -+{ -+ ICA_EC_KEY *icakey; -+ const EC_GROUP *group; -+ const EC_POINT *q; -+ const BIGNUM *bn_d; -+ BIGNUM *bn_x = NULL, *bn_y = NULL; -+ unsigned char D[IBMCA_EC_MAX_D_LEN]; -+ unsigned char X[IBMCA_EC_MAX_D_LEN]; -+ unsigned char Y[IBMCA_EC_MAX_D_LEN]; -+ int rc, n; -+ -+ /* Get group */ -+ if ((group = EC_KEY_get0_group(ec_key)) == NULL) { -+ IBMCAerr(IBMCA_F_ICA_EC_KEY_NEW, IBMCA_R_EC_INVALID_PARM); -+ return NULL; -+ } -+ -+ /* Get curve nid */ -+ *nid = EC_GROUP_get_curve_name(group); -+ if (*nid <= 0) { -+ IBMCAerr(IBMCA_F_ICA_EC_KEY_NEW, IBMCA_R_EC_UNSUPPORTED_CURVE); -+ return NULL; -+ } -+ -+ /* Create ICA_EC_KEY object */ -+ icakey = p_ica_ec_key_new(*nid, privlen); -+ if (icakey == NULL) { -+ IBMCAerr(IBMCA_F_ICA_EC_KEY_NEW, IBMCA_R_EC_ICA_EC_KEY_INIT); -+ return NULL; -+ } -+ -+ /* Get private (D) value from EC_KEY (if available) */ -+ bn_d = EC_KEY_get0_private_key(ec_key); -+ if (bn_d != NULL) { -+ /* Format (D) as char array, with leading zeros if necessary */ -+ n = *privlen - BN_num_bytes(bn_d); -+ memset(D, 0, n); -+ BN_bn2bin(bn_d, &(D[n])); -+ -+ /* Initialize private ICA_EC_KEY */ -+ rc = p_ica_ec_key_init(NULL, NULL, D, icakey); -+ if (rc != 0) { -+ IBMCAerr(IBMCA_F_ICA_EC_KEY_INIT, rc); -+ goto error; -+ } -+ } -+ -+ /* Get public (X and Y) values from EC_KEY (if available) */ -+ q = EC_KEY_get0_public_key(ec_key); -+ if (q != NULL) { -+ /* Provide public key (X,Y) */ -+ bn_x = BN_new(); -+ bn_y = BN_new(); -+ if (!EC_POINT_get_affine_coordinates_GFp(group, q, bn_x, bn_y, NULL)) { -+ IBMCAerr(IBMCA_F_ICA_EC_KEY_NEW, IBMCA_R_EC_INTERNAL_ERROR); -+ goto error; -+ } -+ -+ /* Format (X) as char array with leading nulls if necessary */ -+ n = *privlen - BN_num_bytes(bn_x); -+ memset(X, 0, n); -+ BN_bn2bin(bn_x, &X[n]); -+ -+ /* Format (Y) as char array with leading nulls if necessary */ -+ n = *privlen - BN_num_bytes(bn_y); -+ memset(Y, 0, n); -+ BN_bn2bin(bn_y, &Y[n]); -+ -+ /* Initialize public ICA_EC_KEY */ -+ rc = p_ica_ec_key_init(X, Y, NULL, icakey); -+ if (rc != 0) { -+ IBMCAerr(IBMCA_F_ICA_EC_KEY_INIT, rc); -+ goto error; -+ } -+ } -+ -+out: -+ BN_clear_free(bn_x); -+ BN_clear_free(bn_y); -+ -+ return icakey; -+ -+error: -+ p_ica_ec_key_free(icakey); -+ icakey = NULL; -+ goto out; -+} -+ -+static ICA_EC_KEY *ibmca_ec_make_and_cache_ica_key(EC_KEY *ec_key, -+ unsigned int *privlen) -+{ -+ struct ibmca_ec_ex_data *data, *data2; -+ -+ data = OPENSSL_zalloc(sizeof(*data)); -+ if (data == NULL) -+ return NULL; -+ -+ data->ica_key = ibmca_ec_make_ica_key(ec_key, &data->nid, &data->privlen); -+ if (data->ica_key == NULL) { -+ OPENSSL_free(data); -+ return NULL; -+ } -+ -+ /* -+ * Note that another thread could have allocated and set the ex_data for -+ * that key after the caller of this function has checked if there is -+ * already ex_data available for the key. So once we have the lock, we -+ * check again, and if there now is ex_data available, we return the -+ * ICA key from the ex_data, and free the one just created. -+ */ -+ if (pthread_mutex_lock(&ec_ex_data_mutex) != 0) { -+ IBMCAerr(IBMCA_F_ICA_EC_KEY_NEW, IBMCA_R_EC_INTERNAL_ERROR); -+ return NULL; -+ } -+ -+ data2 = EC_KEY_get_ex_data(ec_key, ec_ex_data_index); -+ if (data2 != NULL) { -+ pthread_mutex_unlock(&ec_ex_data_mutex); -+ -+ p_ica_ec_key_free(data->ica_key); -+ OPENSSL_free(data); -+ -+ *privlen = data2->privlen; -+ -+ return data2->ica_key; -+ } -+ -+ if (EC_KEY_set_ex_data(ec_key, ec_ex_data_index, data) != 1) { -+ IBMCAerr(IBMCA_F_ICA_EC_KEY_NEW, IBMCA_R_EC_INTERNAL_ERROR); -+ pthread_mutex_unlock(&ec_ex_data_mutex); -+ OPENSSL_free(data); -+ return NULL; -+ } -+ -+ pthread_mutex_unlock(&ec_ex_data_mutex); -+ -+ *privlen = data->privlen; -+ -+ return data->ica_key; -+} -+ -+int ibmca_ec_init(void) -+{ -+#ifdef OLDER_OPENSSL -+ return 0; -+#else -+ ec_ex_data_index = EC_KEY_get_ex_new_index(0, NULL, NULL, -+ ibmca_ec_ex_data_dup, -+ ibmca_ec_ex_data_free); -+ if (ec_ex_data_index < 0) { -+ IBMCAerr(IBMCA_F_IBMCA_INIT, IBMCA_R_EC_INTERNAL_ERROR); -+ return 0; -+ } -+ -+ return 1; -+#endif -+} -+ - void ibmca_ec_destroy(void) - { - #ifdef OLDER_OPENSSL -@@ -39,6 +285,10 @@ void ibmca_ec_destroy(void) - if (ibmca_ecdh) - ECDSA_METHOD_free(ibmca_ecdsa); - #else -+ if (ec_ex_data_index >= 0) { -+ CRYPTO_free_ex_index(CRYPTO_EX_INDEX_EC_KEY, ec_ex_data_index); -+ ec_ex_data_index = -1; -+ } - if (ibmca_ec) - EC_KEY_METHOD_free(ibmca_ec); - #endif -@@ -55,17 +305,17 @@ int ibmca_ecdh_compute_key(unsigned char **pout, size_t *poutlen, - { - ICA_EC_KEY *ica_pubkey = NULL, *ica_privkey = NULL; - const EC_GROUP *group; -- BIGNUM *bn_d, *bn_x, *bn_y; -+ BIGNUM *bn_x = NULL, *bn_y = NULL; - unsigned int n, privlen; - unsigned char X[IBMCA_EC_MAX_D_LEN]; - unsigned char Y[IBMCA_EC_MAX_D_LEN]; -- unsigned char D[IBMCA_EC_MAX_D_LEN]; - unsigned char *z_buf = NULL; - int rc, ret = 0, nid; - #ifndef OLDER_OPENSSL - int (*compute_key_sw)(unsigned char **pout, size_t *poutlen, - const EC_POINT *pub_key, const EC_KEY *ecdh) = NULL; - #endif -+ struct ibmca_ec_ex_data *data = EC_KEY_get_ex_data(ecdh, ec_ex_data_index); - - /* Get group from EC_KEY */ - if ((group = EC_KEY_get0_group(ecdh)) == NULL) { -@@ -76,10 +326,40 @@ int ibmca_ecdh_compute_key(unsigned char **pout, size_t *poutlen, - /* Determine curve nid */ - nid = EC_GROUP_get_curve_name(group); - if (nid <= 0) { -- IBMCAerr(IBMCA_F_IBMCA_ECDH_COMPUTE_KEY, IBMCA_R_EC_INTERNAL_ERROR); -+ IBMCAerr(IBMCA_F_IBMCA_ECDH_COMPUTE_KEY, IBMCA_R_EC_UNSUPPORTED_CURVE); -+ return 0; -+ } -+ -+ if (data != NULL) { -+ ica_privkey = data->ica_key; -+ privlen = data->privlen; -+ goto do_derive; -+ } -+ -+ /* Create ICA_EC_KEY object for private key */ -+ ica_privkey = ibmca_ec_make_and_cache_ica_key((EC_KEY*)ecdh, &privlen); -+ if (ica_privkey == NULL) { -+ /* This curve is not supported by libica. */ -+ #ifdef OLDER_OPENSSL - return 0; -+ #else -+ /* -+ * EC_KEY_METHOD_get_compute_key misses the const-qualifier of the -+ * parameter in some openssl versions. -+ */ -+ EC_KEY_METHOD_get_compute_key((EC_KEY_METHOD *)ossl_ec, -+ &compute_key_sw); -+ if (compute_key_sw == NULL) { -+ IBMCAerr(IBMCA_F_IBMCA_ECDH_COMPUTE_KEY, -+ IBMCA_R_EC_INTERNAL_ERROR); -+ return 0; -+ } -+ -+ return compute_key_sw(pout, poutlen, pub_key, ecdh); -+ #endif - } - -+do_derive: - /* Create ICA_EC_KEY object for public key */ - ica_pubkey = p_ica_ec_key_new(nid, &privlen); - if (ica_pubkey == NULL) { -@@ -128,32 +408,6 @@ int ibmca_ecdh_compute_key(unsigned char **pout, size_t *poutlen, - goto end; - } - -- /* Create ICA_EC_KEY object for private key */ -- ica_privkey = p_ica_ec_key_new(nid, &privlen); -- if (!ica_privkey) { -- IBMCAerr(IBMCA_F_ICA_EC_KEY_NEW, IBMCA_R_EC_INTERNAL_ERROR); -- goto end; -- } -- -- /* Get private (D) value from EC_KEY */ -- bn_d = (BIGNUM*)EC_KEY_get0_private_key((EC_KEY*)ecdh); -- if (bn_d == NULL) { -- IBMCAerr(IBMCA_F_IBMCA_ECDH_COMPUTE_KEY, IBMCA_R_EC_INTERNAL_ERROR); -- goto end; -- } -- -- /* Format (D) as char array, with leading zeros if necessary */ -- n = privlen - BN_num_bytes(bn_d); -- memset(D, 0, n); -- BN_bn2bin(bn_d, &(D[n])); -- -- /* Initialize private ICA_EC_KEY with (D) */ -- rc = p_ica_ec_key_init(NULL, NULL, D, ica_privkey); -- if (rc != 0) { -- IBMCAerr(IBMCA_F_ICA_EC_KEY_INIT, rc); -- goto end; -- } -- - /* Allocate memory for shared secret z, will be freed by caller */ - if ((z_buf = OPENSSL_malloc(privlen)) == NULL) { - IBMCAerr(IBMCA_F_IBMCA_ECDH_COMPUTE_KEY, IBMCA_R_EC_INTERNAL_ERROR); -@@ -193,7 +447,6 @@ int ibmca_ecdh_compute_key(unsigned char **pout, size_t *poutlen, - - end: - p_ica_ec_key_free(ica_pubkey); -- p_ica_ec_key_free(ica_privkey); - BN_clear_free(bn_x); - BN_clear_free(bn_y); - return ret; -@@ -210,12 +463,10 @@ ECDSA_SIG *ibmca_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len, - { - ECDSA_SIG *sig = NULL; - ICA_EC_KEY *icakey = NULL; -- const EC_GROUP *group; - unsigned int privlen; -- BIGNUM *r, *s, *bn_d, *kinv; -- unsigned char D[IBMCA_EC_MAX_D_LEN]; -+ BIGNUM *r, *s, *kinv; - unsigned char sigret[IBMCA_EC_MAX_SIG_LEN]; -- int n, nid, rc; -+ int rc; - #ifndef OLDER_OPENSSL - int (*sign_sw)(int type, const unsigned char *dgst, int dlen, - unsigned char *sig, unsigned int *siglen, -@@ -227,6 +478,7 @@ ECDSA_SIG *ibmca_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len, - const BIGNUM *in_kinv, const BIGNUM *in_r, - EC_KEY *eckey) = NULL; - BN_CTX *ctx; -+ struct ibmca_ec_ex_data *data = EC_KEY_get_ex_data(eckey, ec_ex_data_index); - - /* Check parms: precomputed (k,r) are not supported by ibmca */ - if (in_kinv != NULL || in_r != NULL) { -@@ -234,12 +486,6 @@ ECDSA_SIG *ibmca_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len, - return NULL; - } - -- /* Get group */ -- if ((group = EC_KEY_get0_group(eckey)) == NULL) { -- IBMCAerr(IBMCA_F_IBMCA_ECDSA_SIGN_SIG, IBMCA_R_EC_INVALID_PARM); -- return NULL; -- } -- - /* Check if key usable */ - #ifndef OLDER_OPENSSL - if (!EC_KEY_can_sign(eckey)) { -@@ -249,15 +495,14 @@ ECDSA_SIG *ibmca_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len, - } - #endif - -- /* Get curve nid */ -- nid = EC_GROUP_get_curve_name(group); -- if (nid <= 0) { -- IBMCAerr(IBMCA_F_IBMCA_ECDSA_SIGN_SIG, IBMCA_R_EC_UNSUPPORTED_CURVE); -- return NULL; -+ if (data != NULL) { -+ icakey = data->ica_key; -+ privlen = data->privlen; -+ goto do_sign; - } - - /* Create ICA_EC_KEY object */ -- icakey = p_ica_ec_key_new(nid, &privlen); -+ icakey = ibmca_ec_make_and_cache_ica_key(eckey, &privlen); - if (icakey == NULL) { - /* This curve is not supported by libica. */ - #ifdef OLDER_OPENSSL -@@ -287,25 +532,7 @@ ECDSA_SIG *ibmca_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len, - return sig; - } - -- /* Get private (D) value from EC_KEY */ -- bn_d = (BIGNUM*)EC_KEY_get0_private_key(eckey); -- if (bn_d == NULL) { -- IBMCAerr(IBMCA_F_IBMCA_ECDSA_SIGN_SIG, IBMCA_R_EC_INTERNAL_ERROR); -- goto end; -- } -- -- /* Format (D) as char array, with leading zeros if necessary */ -- n = privlen - BN_num_bytes(bn_d); -- memset(D, 0, n); -- BN_bn2bin(bn_d, &(D[n])); -- -- /* Initialize private ICA_EC_KEY */ -- rc = p_ica_ec_key_init(NULL, NULL, D, icakey); -- if (rc != 0) { -- IBMCAerr(IBMCA_F_ICA_EC_KEY_INIT, rc); -- goto end; -- } -- -+do_sign: - /* Call libica signing routine */ - rc = p_ica_ecdsa_sign(ibmca_handle, icakey, dgst, dgst_len, sigret, - sizeof(sigret)); -@@ -343,7 +570,6 @@ ECDSA_SIG *ibmca_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len, - s = BN_bin2bn(sigret + privlen, privlen, NULL); - sig = ECDSA_SIG_new(); - --end: - #ifndef OLDER_OPENSSL - if (sig) - ECDSA_SIG_set0(sig, r, s); -@@ -357,7 +583,6 @@ end: - #endif - - end2: -- p_ica_ec_key_free(icakey); - return sig; - } - -@@ -372,16 +597,12 @@ end2: - int ibmca_ecdsa_verify_sig(const unsigned char *dgst, int dgst_len, - const ECDSA_SIG *sig, EC_KEY *eckey) - { -- const EC_GROUP *group; -- const EC_POINT *q; -- unsigned char x_array[IBMCA_EC_MAX_D_LEN]; -- unsigned char y_array[IBMCA_EC_MAX_D_LEN]; - unsigned char sig_array[IBMCA_EC_MAX_Q_LEN]; - BIGNUM *bn_x = NULL, *bn_y = NULL; - const BIGNUM *bn_r, *bn_s; - unsigned int privlen; - ICA_EC_KEY *icakey = NULL; -- int rc, n, nid; -+ int rc, n; - int ret = -1; - #ifndef OLDER_OPENSSL - int (*verify_sw)(int type, const unsigned char *dgst, int dgst_len, -@@ -389,6 +610,7 @@ int ibmca_ecdsa_verify_sig(const unsigned char *dgst, int dgst_len, - #endif - int (*verify_sig_sw)(const unsigned char *dgst, int dgst_len, - const ECDSA_SIG *sig, EC_KEY *eckey) = NULL; -+ struct ibmca_ec_ex_data *data = EC_KEY_get_ex_data(eckey, ec_ex_data_index); - - /* Check parms */ - if (eckey == NULL || sig == NULL) { -@@ -404,21 +626,14 @@ int ibmca_ecdsa_verify_sig(const unsigned char *dgst, int dgst_len, - } - #endif - -- /* Get group */ -- if ((group = EC_KEY_get0_group(eckey)) == NULL) { -- IBMCAerr(IBMCA_F_IBMCA_ECDSA_VERIFY_SIG, IBMCA_R_EC_INTERNAL_ERROR); -- return ret; -- } -- -- /* Get curve nid */ -- nid = EC_GROUP_get_curve_name(group); -- if (nid <= 0) { -- IBMCAerr(IBMCA_F_IBMCA_ECDSA_VERIFY_SIG, IBMCA_R_EC_UNSUPPORTED_CURVE); -- return ret; -+ if (data != NULL) { -+ icakey = data->ica_key; -+ privlen = data->privlen; -+ goto do_verify; - } - - /* Create ICA_EC_KEY object */ -- icakey = p_ica_ec_key_new(nid, &privlen); -+ icakey = ibmca_ec_make_and_cache_ica_key(eckey, &privlen); - if (icakey == NULL) { - /* This curve is not supported by libica. */ - #ifdef OLDER_OPENSSL -@@ -440,32 +655,7 @@ int ibmca_ecdsa_verify_sig(const unsigned char *dgst, int dgst_len, - return verify_sig_sw(dgst, dgst_len, sig, eckey); - } - -- /* Provide public key (X,Y) */ -- bn_x = BN_new(); -- bn_y = BN_new(); -- q = EC_KEY_get0_public_key(eckey); -- if (!EC_POINT_get_affine_coordinates_GFp(group, q, bn_x, bn_y, NULL)) { -- IBMCAerr(IBMCA_F_IBMCA_ECDSA_VERIFY_SIG, IBMCA_R_EC_INTERNAL_ERROR); -- goto end; -- } -- -- /* Format (X) as char array with leading nulls if necessary */ -- n = privlen - BN_num_bytes(bn_x); -- memset(x_array, 0, n); -- BN_bn2bin(bn_x, &(x_array[n])); -- -- /* Format (Y) as char array with leading nulls if necessary */ -- n = privlen - BN_num_bytes(bn_y); -- memset(y_array, 0, n); -- BN_bn2bin(bn_y, &(y_array[n])); -- -- /* Initialize ICA_EC_KEY */ -- rc = p_ica_ec_key_init(x_array, y_array, NULL, icakey); -- if (rc != 0) { -- IBMCAerr(IBMCA_F_ICA_EC_KEY_INIT, rc); -- goto end; -- } -- -+do_verify: - /* Get (r,s) from ECDSA_SIG */ - #ifdef OLDER_OPENSSL - bn_r = sig->r; -@@ -517,7 +707,6 @@ int ibmca_ecdsa_verify_sig(const unsigned char *dgst, int dgst_len, - } - - end: -- p_ica_ec_key_free(icakey); - BN_clear_free(bn_x); - BN_clear_free(bn_y); - --- -2.39.0 - - -From 072e32bb199ff772148f1cbe0b2faadf9ab33c12 Mon Sep 17 00:00:00 2001 -From: Juergen Christ -Date: Thu, 27 Oct 2022 16:13:01 +0200 -Subject: [PATCH 3/4] provider: Fix configuration script - -Small typo in the configuration script created an invalid configuration. - -Signed-off-by: Juergen Christ ---- - src/provider/ibmca-provider-opensslconfig | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/provider/ibmca-provider-opensslconfig b/src/provider/ibmca-provider-opensslconfig -index 21ed6f6..d45428e 100755 ---- a/src/provider/ibmca-provider-opensslconfig -+++ b/src/provider/ibmca-provider-opensslconfig -@@ -83,7 +83,7 @@ sub generate() - } - if ($providersect && $line =~ /\[\s*$providersect\s*\]/) { - print $oh "ibmca_provider = ibmca_provider_section\n"; -- print $oh # Make sure that you have configured and activated at least one other provider!\n"; -+ print $oh "# Make sure that you have configured and activated at least one other provider!\n"; - print "WARNING: The IBMCA provider was added to section [$providersect].\n"; - print "Make sure that you have configured and activated at least one other provider, e.g. the default provider!\n"; - } --- -2.39.0 - - -From e90203dbc9bf0d9a4488af470adf11852860991a Mon Sep 17 00:00:00 2001 -From: Juergen Christ -Date: Wed, 2 Nov 2022 14:29:35 +0100 -Subject: [PATCH 4/4] provider: Fix order of providers in configuration - -Since libica requires a provider that supports HMAC to be loaded and -available, fix the order of providers loaded by our sample configuration -generator. The "default" provider has to come first such that libica can do -the file integrity test with a HMAC provided by this provider when being -loaded via the ibmca provider. - -Signed-off-by: Juergen Christ ---- - src/provider/ibmca-provider-opensslconfig | 23 +++++++++++++++-------- - 1 file changed, 15 insertions(+), 8 deletions(-) - -diff --git a/src/provider/ibmca-provider-opensslconfig b/src/provider/ibmca-provider-opensslconfig -index d45428e..d87fa8e 100755 ---- a/src/provider/ibmca-provider-opensslconfig -+++ b/src/provider/ibmca-provider-opensslconfig -@@ -30,7 +30,7 @@ use warnings; - sub generate() - { - my ($osslconfpath); -- my ($ih, $line, $oh, $defaultcnfsect, $indefaultsect, $providersect); -+ my ($ih, $line, $oh, $defaultcnfsect, $indefaultsect, $providersect, $inprovidersect); - my ($inalgsect, $algsection); - - $osslconfpath = `openssl version -d` || die "Please install openssl binary"; -@@ -43,6 +43,7 @@ sub generate() - $defaultcnfsect = undef; - $indefaultsect = 0; - $providersect = undef; -+ $inprovidersect = 0; - while ($line = <$ih>) { - if ($line =~ /openssl_conf\s*=\s*(.*)/) { - $defaultcnfsect = $1; -@@ -67,13 +68,22 @@ sub generate() - } elsif ($inalgsect) { - if ($line =~ /\[\s*\w+\s*\]/) { - print $oh "default_properties = ?provider=ibmca\n"; -+ $inalgsect = 0; - } elsif ($line =~ /^\s*default_properties\s*=\s*(\w+)\s*/) { - print $oh "default_properties = ?provider=ibmca\n"; - print $oh "# The following was commented out by ibmca-provider-opensslconfig script\n"; - print "WARNING: The default_properties in $algsection was modified by this script.\n"; - $line = "# $line"; - } -- } -+ } elsif ($inprovidersect) { -+ if ($line =~ /\[\s*\w+\s*\]/) { -+ $inprovidersect = 0; -+ print $oh "ibmca_provider = ibmca_provider_section\n"; -+ print $oh "# Make sure that you have configured and activated at least one other provider!\n"; -+ print "WARNING: The IBMCA provider was added to section [$providersect].\n"; -+ print "Make sure that you have configured and activated at least one other provider, e.g. the default provider!\n"; -+ } -+ } - print $oh "$line"; - if ($defaultcnfsect && $line =~ /\[\s*$defaultcnfsect\s*\]/) { - $indefaultsect = 1; -@@ -81,11 +91,8 @@ sub generate() - if ($algsection && $line =~ /\[\s*$algsection\s*\]/) { - $inalgsect = 1; - } -- if ($providersect && $line =~ /\[\s*$providersect\s*\]/) { -- print $oh "ibmca_provider = ibmca_provider_section\n"; -- print $oh "# Make sure that you have configured and activated at least one other provider!\n"; -- print "WARNING: The IBMCA provider was added to section [$providersect].\n"; -- print "Make sure that you have configured and activated at least one other provider, e.g. the default provider!\n"; -+ if ($providersect && $line =~ /\[\s*$providersect\s*\]/) { -+ $inprovidersect = 1; - } - } - -@@ -100,8 +107,8 @@ providers = provider_section - if (!$providersect) { - print $oh qq| - [provider_section] --ibmca_provider = ibmca_provider_section - default = default_sect -+ibmca_provider = ibmca_provider_section - - [default_sect] - activate = 1 --- -2.39.0 - diff --git a/SOURCES/openssl-ibmca-2.4.0-engine-defaults.patch b/SOURCES/openssl-ibmca-2.4.0-engine-defaults.patch new file mode 100644 index 0000000..40785b6 --- /dev/null +++ b/SOURCES/openssl-ibmca-2.4.0-engine-defaults.patch @@ -0,0 +1,40 @@ +From 3ea8f4ed58e075e097856437c0732e11771931d0 Mon Sep 17 00:00:00 2001 +From: Ingo Franzki +Date: Wed, 19 Apr 2023 10:07:01 +0200 +Subject: [PATCH] engine: Only register those algos specified with + default_algorithms + +As part of OpenSSL initialization, the engine(s) configured in the OpenSSL +config file are loaded, and its algorithms (methods) are registered according +to the default_algorithms setting. + +However, later during initialization, ENGINE_register_all_complete() is called +which unconditionally registered all algorithms (methods) of the loaded engines +again, unless the engine flag ENGINE_FLAGS_NO_REGISTER_ALL is set. + +Set the ENGINE_FLAGS_NO_REGISTER_ALL flag during IBMCA engine initialization +to avoid unconditional registration of all algorithms. We only want to register +algorithms specified in the default_algorithms configuration setting. + +Note that if the default_algorithms setting is omitted in the OpenSSL config +file, then no algorithms will be registered. + +Signed-off-by: Ingo Franzki +--- + src/engine/e_ibmca.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/src/engine/e_ibmca.c b/src/engine/e_ibmca.c +index fe21897..6cbf745 100644 +--- a/src/engine/e_ibmca.c ++++ b/src/engine/e_ibmca.c +@@ -642,6 +642,9 @@ static int set_supported_meths(ENGINE *e) + if (!ENGINE_set_pkey_meths(e, ibmca_engine_pkey_meths)) + goto out; + ++ if (!ENGINE_set_flags(e, ENGINE_FLAGS_NO_REGISTER_ALL)) ++ goto out; ++ + rc = 1; + out: + free(pmech_list); diff --git a/SOURCES/openssl-ibmca-2.4.0-log-into-tmp.patch b/SOURCES/openssl-ibmca-2.4.0-log-into-tmp.patch new file mode 100644 index 0000000..f81e270 --- /dev/null +++ b/SOURCES/openssl-ibmca-2.4.0-log-into-tmp.patch @@ -0,0 +1,218 @@ +From 2298d3964f1ce32d35bb7585e4fa224c5bf2c8d4 Mon Sep 17 00:00:00 2001 +From: Ingo Franzki +Date: Wed, 26 Jul 2023 15:19:55 +0200 +Subject: [PATCH] provider: Default debug directory to /tmp but make it + configurable + +The IBMCA provider debug logs were written to the /var/log/ibmca/ directory, +but this required that directory to be world-writable, because we don't know +under which user an application runs that uses the provider. +A world-writable directory under /var has security implications and should be +avoided. + +Change the default log directory to /tmp which is world-writable anyway. +Additionally the log directory can now be configured via the 'debug-path' +option in the IBMCA provider section of the OpenSSL config file, or via +environment variable 'IBMCA_DEBUG_PATH'. + +Closes: https://github.com/opencryptoki/openssl-ibmca/issues/107 + +Signed-off-by: Ingo Franzki +--- + configure.ac | 2 +- + src/provider/Makefile.am | 4 --- + src/provider/doc/ibmca-provider.man | 38 +++++++++++++++++++++++------ + src/provider/p_ibmca.c | 25 ++++++++++++++++++- + src/provider/p_ibmca.h | 3 +++ + test/provider/openssl-test.cnf | 1 + + 6 files changed, 59 insertions(+), 14 deletions(-) + +diff --git a/configure.ac b/configure.ac +index cea8ce8f..57b32050 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -10,7 +10,7 @@ AM_INIT_AUTOMAKE([foreign]) + + AC_PATH_PROG([CHMOD], [chmod], [/bin/chmod]) + +-logdir=$localstatedir/log/ibmca ++logdir=/tmp + AC_SUBST(logdir) + + # Cmdline arguments. +diff --git a/src/provider/Makefile.am b/src/provider/Makefile.am +index da45a52e..f2d1d50b 100644 +--- a/src/provider/Makefile.am ++++ b/src/provider/Makefile.am +@@ -25,7 +25,3 @@ ACLOCAL_AMFLAGS = -I m4 + SUBDIRS = doc + + noinst_SCRIPTS = ibmca-provider-opensslconfig +- +-install-data-hook: +- $(MKDIR_P) $(DESTDIR)$(logdir) +- $(CHMOD) 0777 $(DESTDIR)$(logdir) +diff --git a/src/provider/doc/ibmca-provider.man b/src/provider/doc/ibmca-provider.man +index 52350e47..846d6070 100644 +--- a/src/provider/doc/ibmca-provider.man ++++ b/src/provider/doc/ibmca-provider.man +@@ -94,13 +94,25 @@ provider if you are on an IBM z15 or later. This would actually make it slower. + .IP "debug = yes | no | stderr" + .RS + Enables debug output for the IBMCA provider. If this option is not specified, +-no debuging output is produced. If \fBdebug = stderr\fP is specified, ++no debugging output is produced. If \fBdebug = stderr\fP is specified, + debugging messages are printed to stderr. Otherwise the debug output is written +-into a trace file in \fB[/usr/local]/var/log/ibmca/trace-.\fP, +-where is the name of the IBMCA provider from the identity +-option, and is the process ID of the current process. You can also +-enable debugging by setting the environment variable \fBIBMCA_DEBUG\fP to +-\fBon\fP or \fBstderr\fP. ++into a trace file in \fB/trace-.\fP, ++where is the path name of a directory to where the debug files are ++written (default: \fB/tmp\fP), is the name of the IBMCA provider ++from the identity option, and is the process ID of the current process. ++You can also enable debugging by setting the environment variable ++\fBIBMCA_DEBUG\fP to \fBon\fP or \fBstderr\fP. ++.RE ++.PP ++.IP "debug-path = /dir/to/debug/directory" ++.RS ++Sets the directory path to where debug files are written when debug is enabled ++via \fBdebug = yes\fP or via environment variable \fBIBMCA_DEBUG=on\fP. ++You can also set the debug path by setting the environment variable ++\fBIBMCA_DEBUG_PATH\fP to the directory path. It must be ensured that the user ++under which the application that uses the IBMCA provider runs has write access ++to that directory. If this option is not specified, the default debug path is ++\fB/tmp\fP. + .RE + .PP + .IP "fips = yes | no" +@@ -153,8 +165,18 @@ If + .B $IBMCA_DEBUG + is set to \fBstderr\fP debug output to stderr for the IBMCA provider is enabled. + If it is set to \fBon\fP the debug output is written into a trace file in +-\fB[/usr/local]/var/log/ibmca/trace-.\fP, where is +-the process ID of the current process. ++\fB/trace-.\fP, where is the path ++name of a directory to where the debug files are written (default: \fB/tmp\fP), ++ is the name of the IBMCA provider from the identity option, ++and is the process ID of the current process. ++.PP ++.TP ++.BR IBMCA_DEBUG_PATH ++Sets the directory path to where debug files are written when debug is enabled ++via \fBdebug = yes\fP configuration option or via environment variable ++\fBIBMCA_DEBUG=on\fP. It must be ensured that the user under which the ++application that uses the IBMCA provider runs has write access to that ++directory. + .PP + .SH SEE ALSO + .B provider(1) +diff --git a/src/provider/p_ibmca.c b/src/provider/p_ibmca.c +index 80f03685..ffb9b5dd 100644 +--- a/src/provider/p_ibmca.c ++++ b/src/provider/p_ibmca.c +@@ -19,6 +19,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -58,6 +59,8 @@ struct ibmca_config_item { + + static int ibmca_config_debug(struct ibmca_prov_ctx *provctx, + const char *key, const char *value); ++static int ibmca_config_debug_path(struct ibmca_prov_ctx *provctx, ++ const char *key, const char *value); + static int ibmca_config_fips(struct ibmca_prov_ctx *provctx, + const char *key, const char *value); + static int ibmca_config_algorithms(struct ibmca_prov_ctx *provctx, +@@ -70,6 +73,7 @@ static int ibmca_config_openssl_version(struct ibmca_prov_ctx *provctx, + const char *key, const char *value); + + static const struct ibmca_config_item config_items[] = { ++ { IBMCA_CONF_DEBUG_PATH, ibmca_config_debug_path }, + { IBMCA_CONF_DEBUG, ibmca_config_debug }, + { IBMCA_CONF_FIPS, ibmca_config_fips }, + { IBMCA_CONF_ALGORITHMS, ibmca_config_algorithms }, +@@ -881,7 +885,9 @@ static int ibmca_config_debug(struct ibmca_prov_ctx *provctx, + *p = '_'; + + if (snprintf(debug_file, sizeof(debug_file), "%s/trace-%s.%d", +- IBMCA_LOGDIR, prov_name, provctx->debug_pid) ++ provctx->debug_path != NULL ? provctx->debug_path : ++ IBMCA_LOGDIR, ++ prov_name, provctx->debug_pid) + >= (int)sizeof(debug_file)) { + put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, + "IBMCA_LOGDIR too long: '%s'", IBMCA_LOGDIR); +@@ -904,6 +910,20 @@ static int ibmca_config_debug(struct ibmca_prov_ctx *provctx, + return 1; + } + ++static int ibmca_config_debug_path(struct ibmca_prov_ctx *provctx, ++ const char *key, const char *value) ++{ ++ /* ++ * If the debug path is already set (e.g. due to IBMCA_DEBUG_PATH ++ * environment variable) do not override the setting. ++ */ ++ if (provctx->debug_path != NULL) ++ return 1; ++ ++ return ibmca_config_const_string(provctx, key, value, ++ &provctx->debug_path); ++} ++ + static int ibmca_config_fips(struct ibmca_prov_ctx *provctx, + const char *key, const char *value) + { +@@ -1302,6 +1322,9 @@ int OSSL_provider_init(const OSSL_CORE_HANDLE *handle, + ctx->c_free = c_free; + ctx->ica_adapter = DRIVER_NOT_LOADED; + ++ val = secure_getenv(IBMCA_DEBUG_PATH_ENVVAR); ++ if (val != NULL) ++ ibmca_config_debug_path(ctx, IBMCA_CONF_DEBUG_PATH, val); + val = getenv(IBMCA_DEBUG_ENVVAR); + if (val != NULL) + ibmca_config_debug(ctx, IBMCA_CONF_DEBUG, val); +diff --git a/src/provider/p_ibmca.h b/src/provider/p_ibmca.h +index 3b3d4f04..c47a6aa9 100644 +--- a/src/provider/p_ibmca.h ++++ b/src/provider/p_ibmca.h +@@ -27,9 +27,11 @@ + + /* Environment variable name to enable debug */ + #define IBMCA_DEBUG_ENVVAR "IBMCA_DEBUG" ++#define IBMCA_DEBUG_PATH_ENVVAR "IBMCA_DEBUG_PATH" + + /* IBMCA provider configuration key words */ + #define IBMCA_CONF_DEBUG "debug" ++#define IBMCA_CONF_DEBUG_PATH "debug-path" + #define IBMCA_CONF_ALGORITHMS "algorithms" + #define IBMCA_CONF_FIPS "fips" + #define IBMCA_CONF_FALLBACK_PROPS "fallback-properties" +@@ -64,6 +66,7 @@ struct ibmca_prov_ctx { + OSSL_FUNC_CRYPTO_secure_clear_free_fn *c_secure_clear_free; + OSSL_FUNC_OPENSSL_cleanse_fn *c_cleanse; + bool debug; ++ const char *debug_path; + FILE *debug_file; + pid_t debug_pid; + pthread_mutex_t debug_mutex; +diff --git a/test/provider/openssl-test.cnf b/test/provider/openssl-test.cnf +index 7866f4e9..e8132a6b 100644 +--- a/test/provider/openssl-test.cnf ++++ b/test/provider/openssl-test.cnf +@@ -16,6 +16,7 @@ identity = ibmca + module = ibmca-provider.so + activate = 1 + #debug = yes ++#debug-path = /dir/to/debug/directory + #fips=yes + #algorithms = RSA,EC,DH + algorithms = ALL diff --git a/SOURCES/openssl-ibmca-2.4.0-rsa-me.patch b/SOURCES/openssl-ibmca-2.4.0-rsa-me.patch new file mode 100644 index 0000000..1e3bb28 --- /dev/null +++ b/SOURCES/openssl-ibmca-2.4.0-rsa-me.patch @@ -0,0 +1,1118 @@ +From f8a60b6678b1eb3ccadcb31f36bf7961ed8d5a9a Mon Sep 17 00:00:00 2001 +From: Ingo Franzki +Date: Tue, 25 Apr 2023 16:23:52 +0200 +Subject: [PATCH] provider: rsa: Check RSA keys with p < q at key generation + and import + +Since OpenSSL 3.0 the OpenSSL RSA key generation taking place within libica +may generate RSA keys where p < q (privileged form). While such a key is +automatically corrected with the first call to libica's ica_rsa_crt(), such +correction modifies the libica RSA key object and may cause concurrency +problems when the same key object is used by multiple threads. + +Check and correct such keys right after key generation or during import, +so that it is ensured that p > q whenever the key is used afterwards, and +thus no correction is applied by ica_rsa_crt() later on. + +Signed-off-by: Ingo Franzki +--- + src/provider/rsa_keymgmt.c | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +diff --git a/src/provider/rsa_keymgmt.c b/src/provider/rsa_keymgmt.c +index aabf9d2..f83d90a 100644 +--- a/src/provider/rsa_keymgmt.c ++++ b/src/provider/rsa_keymgmt.c +@@ -1203,6 +1203,15 @@ static void *ibmca_keymgmt_rsa_gen(void *vgenctx, OSSL_CALLBACK *osslcb, + } + } + ++ /* If p < q, swap and recalculate now */ ++ rc = ica_rsa_crt_key_check(&key->rsa.private); ++ if (rc > 1) { ++ put_error_op_ctx(genctx, IBMCA_ERR_INTERNAL_ERROR, ++ "ica_rsa_crt_key_check failed"); ++ ibmca_keymgmt_free(key); ++ return NULL; ++ } ++ + p = 3; + n = 0; + if (osslcb != NULL && osslcb(cb_params, cbarg) == 0) { +@@ -1823,6 +1832,15 @@ int ibmca_keymgmt_rsa_import(void *vkey, int selection, + "BN_bn2binpad failed for private qinv"); + goto out; + } ++ ++ /* If p < q, swap and recalculate now */ ++ rc = ica_rsa_crt_key_check(&key->rsa.private); ++ if (rc > 1) { ++ rc = 0; ++ put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, ++ "ica_rsa_crt_key_check failed"); ++ goto out; ++ } + } + + if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0 && +From acba1d936bd84c7090ed7d3849b0bab3c7f18da0 Mon Sep 17 00:00:00 2001 +From: Ingo Franzki +Date: Fri, 7 Jul 2023 14:55:26 +0200 +Subject: [PATCH] provider: Support importing of RSA keys with just ME + components + +RSA private keys may contain just CRT (p, q, dp, dq, qinv) or ME (d) +components, or all of them. If an application imports a private RSA key +from just the ME components (m, e, and private d), then the IBMCA provider +can not use ica_rsa_crt() to perform private key operations. + +Therefore let an RSA key also contain the private key components in ME +format, and use ica_rsa_mod_expo() if only the ME components are available. +RSA keys are still always generated in CRT format, but it now allows to +import an RSA private key in ME format. + +Signed-off-by: Ingo Franzki +--- + src/provider/p_ibmca.h | 11 +- + src/provider/rsa_asym_cipher.c | 2 +- + src/provider/rsa_blinding.c | 31 +- + src/provider/rsa_keymgmt.c | 603 +++++++++++++++++++++------------ + src/provider/rsa_signature.c | 2 +- + 5 files changed, 427 insertions(+), 222 deletions(-) + +diff --git a/src/provider/p_ibmca.h b/src/provider/p_ibmca.h +index 58f150f..3b3d4f0 100644 +--- a/src/provider/p_ibmca.h ++++ b/src/provider/p_ibmca.h +@@ -124,7 +124,9 @@ struct ibmca_key { + union { + struct { + size_t bits; +- ica_rsa_key_crt_t private; ++ size_t keylength; ++ ica_rsa_key_crt_t private_crt; ++ ica_rsa_key_mod_expo_t private_me; + ica_rsa_key_mod_expo_t public; + struct ibmca_pss_params pss; /* For type EVP_PKEY_RSA_PSS only */ + BN_BLINDING *blinding; +@@ -176,6 +178,9 @@ struct ibmca_op_ctx *ibmca_keymgmt_gen_init( + int (*dup_cb) + (const struct ibmca_op_ctx *ctx, + struct ibmca_op_ctx *new_ctx)); ++bool ibmca_keymgmt_rsa_pub_valid(const ica_rsa_key_mod_expo_t *public); ++bool ibmca_keymgmt_rsa_priv_crt_valid(const ica_rsa_key_crt_t *private_crt); ++bool ibmca_keymgmt_rsa_priv_me_valid(const ica_rsa_key_mod_expo_t *private_me); + + OSSL_FUNC_keymgmt_free_fn ibmca_keymgmt_free; + OSSL_FUNC_keymgmt_dup_fn ibmca_keymgmt_dup; +@@ -519,8 +524,8 @@ int ibmca_keymgmt_rsa_derive_kdk(struct ibmca_key *key, + + int ibmca_keymgmt_rsa_pub_as_bn(struct ibmca_key *key, BIGNUM **n, BIGNUM **e); + +-int ibmca_rsa_crt_with_blinding(struct ibmca_key *key, const unsigned char *in, +- unsigned char *out, size_t rsa_size); ++int ibmca_rsa_priv_with_blinding(struct ibmca_key *key, const unsigned char *in, ++ unsigned char *out, size_t rsa_size); + + int ossl_bn_rsa_do_unblind(const unsigned char *intermediate, + const BIGNUM *unblind, +diff --git a/src/provider/rsa_asym_cipher.c b/src/provider/rsa_asym_cipher.c +index 43049ee..624bd60 100644 +--- a/src/provider/rsa_asym_cipher.c ++++ b/src/provider/rsa_asym_cipher.c +@@ -844,7 +844,7 @@ static int ibmca_asym_cipher_rsa_decrypt(void *vctx, + } + + /* Perform private key decrypt */ +- rc = ibmca_rsa_crt_with_blinding(ctx->key, in, dec_data, rsa_size); ++ rc = ibmca_rsa_priv_with_blinding(ctx->key, in, dec_data, rsa_size); + if (rc != 1) { + ibmca_debug_op_ctx(ctx, "ibmca_asym_cipher_rsa_with_blinding failed"); + +diff --git a/src/provider/rsa_blinding.c b/src/provider/rsa_blinding.c +index fc13326..4100065 100644 +--- a/src/provider/rsa_blinding.c ++++ b/src/provider/rsa_blinding.c +@@ -392,8 +392,8 @@ static int ibmca_rsa_blinding_invert(struct ibmca_key *key, + return rc; + } + +-int ibmca_rsa_crt_with_blinding(struct ibmca_key *key, const unsigned char *in, +- unsigned char *out, size_t rsa_size) ++int ibmca_rsa_priv_with_blinding(struct ibmca_key *key, const unsigned char *in, ++ unsigned char *out, size_t rsa_size) + { + BN_BLINDING *blinding; + bool local_blinding = false; +@@ -404,7 +404,7 @@ int ibmca_rsa_crt_with_blinding(struct ibmca_key *key, const unsigned char *in, + + ibmca_debug_key(key, "key: %p rsa_size: %lu", key, rsa_size); + +- if (rsa_size != key->rsa.private.key_length) { ++ if (rsa_size != key->rsa.keylength) { + put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, + "rsa_size is not modulus size"); + goto out; +@@ -445,11 +445,26 @@ int ibmca_rsa_crt_with_blinding(struct ibmca_key *key, const unsigned char *in, + goto out; + } + +- rc = ica_rsa_crt(key->provctx->ica_adapter, buf, +- &key->rsa.private, buf + rsa_size); +- if (rc != 0) { +- ibmca_debug_key(key, "ERROR: ica_rsa_crt failed with: %s", +- strerror(rc)); ++ if (ibmca_keymgmt_rsa_priv_crt_valid(&key->rsa.private_crt)) { ++ rc = ica_rsa_crt(key->provctx->ica_adapter, buf, ++ &key->rsa.private_crt, buf + rsa_size); ++ if (rc != 0) { ++ ibmca_debug_key(key, "ERROR: ica_rsa_crt failed with: %s", ++ strerror(rc)); ++ rc = 0; ++ goto out; ++ } ++ } else if (ibmca_keymgmt_rsa_priv_me_valid(&key->rsa.private_me)) { ++ rc = ica_rsa_mod_expo(key->provctx->ica_adapter, buf, ++ &key->rsa.private_me, buf + rsa_size); ++ if (rc != 0) { ++ ibmca_debug_key(key, "ERROR: ica_rsa_mod_expo failed with: %s", ++ strerror(rc)); ++ rc = 0; ++ goto out; ++ } ++ } else { ++ put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "No private key"); + rc = 0; + goto out; + } +diff --git a/src/provider/rsa_keymgmt.c b/src/provider/rsa_keymgmt.c +index f83d90a..526f2aa 100644 +--- a/src/provider/rsa_keymgmt.c ++++ b/src/provider/rsa_keymgmt.c +@@ -241,25 +241,14 @@ static int ibmca_keymgmt_rsa_pub_key_to_data( + return 1; + } + +-static int ibmca_keymgmt_rsa_priv_key_from_data( ++static int ibmca_keymgmt_rsa_priv_crt_key_from_data( + const struct ibmca_prov_ctx *provctx, +- const OSSL_PARAM params[], +- BIGNUM **d, BIGNUM **p, ++ const OSSL_PARAM params[], BIGNUM **p, + BIGNUM **q, BIGNUM **dp, + BIGNUM **dq, BIGNUM **qinv) + { + int rc; + +- /* OSSL_PKEY_PARAM_RSA_D */ +- *d = BN_secure_new(); +- if (*d == NULL) { +- put_error_ctx(provctx, IBMCA_ERR_MALLOC_FAILED, "BN_secure_new failed"); +- goto error; +- } +- rc = ibmca_param_get_bn(provctx, params, OSSL_PKEY_PARAM_RSA_D, d); +- if (rc <= 0) +- goto error; +- + /* OSSL_PKEY_PARAM_RSA_FACTOR1 */ + *p = BN_secure_new(); + if (*p == NULL) { +@@ -316,8 +305,6 @@ static int ibmca_keymgmt_rsa_priv_key_from_data( + return 1; + + error: +- BN_clear_free(*d); +- *d = NULL; + BN_clear_free(*p); + *p = NULL; + BN_clear_free(*dp); +@@ -330,6 +317,31 @@ static int ibmca_keymgmt_rsa_priv_key_from_data( + return 0; + } + ++static int ibmca_keymgmt_rsa_priv_me_key_from_data( ++ const struct ibmca_prov_ctx *provctx, ++ const OSSL_PARAM params[], BIGNUM **d) ++{ ++ int rc; ++ ++ /* OSSL_PKEY_PARAM_RSA_D */ ++ *d = BN_secure_new(); ++ if (*d == NULL) { ++ put_error_ctx(provctx, IBMCA_ERR_MALLOC_FAILED, "BN_secure_new failed"); ++ goto error; ++ } ++ rc = ibmca_param_get_bn(provctx, params, OSSL_PKEY_PARAM_RSA_D, d); ++ if (rc <= 0) ++ goto error; ++ ++ return 1; ++ ++error: ++ BN_clear_free(*d); ++ *d = NULL; ++ ++ return 0; ++} ++ + static int ibmca_keymgmt_rsa_priv_key_to_data( + const struct ibmca_prov_ctx *provctx, + OSSL_PARAM_BLD *bld, +@@ -451,13 +463,14 @@ static void *ibmca_keymgmt_rsa_pss_new(void *vprovctx) + + static int ibmca_keymgmt_rsa_alloc_pub(struct ibmca_key *key) + { +- key->rsa.public.key_length = (key->rsa.bits + 7) / 8; ++ key->rsa.public.key_length = key->rsa.keylength; + + key->rsa.public.modulus = P_ZALLOC(key->provctx, + key->rsa.public.key_length); + key->rsa.public.exponent = P_ZALLOC(key->provctx, + key->rsa.public.key_length); +- if (key->rsa.public.modulus == NULL || key->rsa.public.exponent == NULL) { ++ ++ if (!ibmca_keymgmt_rsa_pub_valid(&key->rsa.public)) { + put_error_key(key, IBMCA_ERR_MALLOC_FAILED, + "Failed to allocate libica public RSA key"); + return 0; +@@ -466,24 +479,42 @@ static int ibmca_keymgmt_rsa_alloc_pub(struct ibmca_key *key) + return 1; + } + +-static int ibmca_keymgmt_rsa_alloc_priv(struct ibmca_key *key) ++static int ibmca_keymgmt_rsa_alloc_priv_crt(struct ibmca_key *key) + { +- key->rsa.private.key_length = (key->rsa.bits + 7) / 8; +- key->rsa.private.p = P_SECURE_ZALLOC(key->provctx, +- ICA_P_LEN(key->rsa.private.key_length)); +- key->rsa.private.q = P_SECURE_ZALLOC(key->provctx, +- ICA_Q_LEN(key->rsa.private.key_length)); +- key->rsa.private.dp = P_SECURE_ZALLOC(key->provctx, +- ICA_DP_LEN(key->rsa.private.key_length)); +- key->rsa.private.dq = P_SECURE_ZALLOC(key->provctx, +- ICA_DQ_LEN(key->rsa.private.key_length)); +- key->rsa.private.qInverse = P_SECURE_ZALLOC(key->provctx, +- ICA_QINV_LEN(key->rsa.private.key_length)); +- if (key->rsa.private.p == NULL || key->rsa.private.q == NULL || +- key->rsa.private.dp == NULL || key->rsa.private.dq == NULL || +- key->rsa.private.qInverse == NULL ) { ++ key->rsa.private_crt.key_length = key->rsa.keylength; ++ ++ key->rsa.private_crt.p = P_SECURE_ZALLOC(key->provctx, ++ ICA_P_LEN(key->rsa.private_crt.key_length)); ++ key->rsa.private_crt.q = P_SECURE_ZALLOC(key->provctx, ++ ICA_Q_LEN(key->rsa.private_crt.key_length)); ++ key->rsa.private_crt.dp = P_SECURE_ZALLOC(key->provctx, ++ ICA_DP_LEN(key->rsa.private_crt.key_length)); ++ key->rsa.private_crt.dq = P_SECURE_ZALLOC(key->provctx, ++ ICA_DQ_LEN(key->rsa.private_crt.key_length)); ++ key->rsa.private_crt.qInverse = P_SECURE_ZALLOC(key->provctx, ++ ICA_QINV_LEN(key->rsa.private_crt.key_length)); ++ ++ if (!ibmca_keymgmt_rsa_priv_crt_valid(&key->rsa.private_crt)) { + put_error_key(key, IBMCA_ERR_MALLOC_FAILED, +- "Failed to allocate libica private RSA key"); ++ "Failed to allocate libica private RSA CRT key"); ++ return 0; ++ } ++ ++ return 1; ++} ++ ++static int ibmca_keymgmt_rsa_alloc_priv_me(struct ibmca_key *key) ++{ ++ key->rsa.private_me.key_length = key->rsa.keylength; ++ ++ key->rsa.private_me.modulus = P_ZALLOC(key->provctx, ++ key->rsa.private_me.key_length); ++ key->rsa.private_me.exponent = P_ZALLOC(key->provctx, ++ key->rsa.private_me.key_length); ++ ++ if (!ibmca_keymgmt_rsa_priv_me_valid(&key->rsa.private_me)) { ++ put_error_key(key, IBMCA_ERR_MALLOC_FAILED, ++ "Failed to allocate libica private RSA ME key"); + return 0; + } + +@@ -503,29 +534,42 @@ static void ibmca_keymgmt_rsa_free_pub(struct ibmca_key *key) + key->rsa.public.key_length = 0; + } + +-static void ibmca_keymgmt_rsa_free_priv(struct ibmca_key *key) ++static void ibmca_keymgmt_rsa_free_priv_crt(struct ibmca_key *key) ++{ ++ if (key->rsa.private_crt.p != NULL) ++ P_SECURE_CLEAR_FREE(key->provctx, key->rsa.private_crt.p, ++ ICA_P_LEN(key->rsa.private_crt.key_length)); ++ key->rsa.private_crt.p = NULL; ++ if (key->rsa.private_crt.q != NULL) ++ P_SECURE_CLEAR_FREE(key->provctx, key->rsa.private_crt.q, ++ ICA_Q_LEN(key->rsa.private_crt.key_length)); ++ key->rsa.private_crt.q = NULL; ++ if (key->rsa.private_crt.dp != NULL) ++ P_SECURE_CLEAR_FREE(key->provctx, key->rsa.private_crt.dp, ++ ICA_DP_LEN(key->rsa.private_crt.key_length)); ++ key->rsa.private_crt.dp = NULL; ++ if (key->rsa.private_crt.dq != NULL) ++ P_SECURE_CLEAR_FREE(key->provctx, key->rsa.private_crt.dq, ++ ICA_DQ_LEN(key->rsa.private_crt.key_length)); ++ key->rsa.private_crt.dq = NULL; ++ if (key->rsa.private_crt.qInverse != NULL) ++ P_SECURE_CLEAR_FREE(key->provctx, key->rsa.private_crt.qInverse, ++ ICA_QINV_LEN(key->rsa.private_crt.key_length)); ++ key->rsa.private_crt.qInverse = NULL; ++ key->rsa.private_crt.key_length = 0; ++} ++ ++static void ibmca_keymgmt_rsa_free_priv_me(struct ibmca_key *key) + { +- if (key->rsa.private.p != NULL) +- P_SECURE_CLEAR_FREE(key->provctx, key->rsa.private.p, +- ICA_P_LEN(key->rsa.private.key_length)); +- key->rsa.private.p = NULL; +- if (key->rsa.private.q != NULL) +- P_SECURE_CLEAR_FREE(key->provctx, key->rsa.private.q, +- ICA_Q_LEN(key->rsa.private.key_length)); +- key->rsa.private.q = NULL; +- if (key->rsa.private.dp != NULL) +- P_SECURE_CLEAR_FREE(key->provctx, key->rsa.private.dp, +- ICA_DP_LEN(key->rsa.private.key_length)); +- key->rsa.private.dp = NULL; +- if (key->rsa.private.dq != NULL) +- P_SECURE_CLEAR_FREE(key->provctx, key->rsa.private.dq, +- ICA_DQ_LEN(key->rsa.private.key_length)); +- key->rsa.private.dq = NULL; +- if (key->rsa.private.qInverse != NULL) +- P_SECURE_CLEAR_FREE(key->provctx, key->rsa.private.qInverse, +- ICA_QINV_LEN(key->rsa.private.key_length)); +- key->rsa.private.qInverse = NULL; +- key->rsa.private.key_length = 0; ++ if (key->rsa.private_me.modulus != NULL) ++ P_CLEAR_FREE(key->provctx, key->rsa.private_me.modulus, ++ key->rsa.private_me.key_length); ++ key->rsa.private_me.modulus = NULL; ++ if (key->rsa.private_me.exponent != NULL) ++ P_CLEAR_FREE(key->provctx, key->rsa.private_me.exponent, ++ key->rsa.private_me.key_length); ++ key->rsa.private_me.exponent = NULL; ++ key->rsa.private_me.key_length = 0; + } + + static void ibmca_keymgmt_rsa_clean(struct ibmca_key *key) +@@ -535,7 +579,8 @@ static void ibmca_keymgmt_rsa_clean(struct ibmca_key *key) + + ibmca_debug_key(key, "key: %p", key); + +- ibmca_keymgmt_rsa_free_priv(key); ++ ibmca_keymgmt_rsa_free_priv_crt(key); ++ ibmca_keymgmt_rsa_free_priv_me(key); + ibmca_keymgmt_rsa_free_pub(key); + + if (key->type == EVP_PKEY_RSA_PSS) +@@ -572,6 +617,30 @@ static void ibmca_keymgmt_rsa_free_cb(struct ibmca_key *key) + pthread_rwlock_destroy(&key->rsa.blinding_lock); + } + ++bool ibmca_keymgmt_rsa_pub_valid(const ica_rsa_key_mod_expo_t *public) ++{ ++ return public->key_length != 0 && ++ public->modulus != NULL && ++ public->exponent != NULL; ++} ++ ++bool ibmca_keymgmt_rsa_priv_crt_valid(const ica_rsa_key_crt_t *private_crt) ++{ ++ return private_crt->key_length != 0 && ++ private_crt->p != NULL && ++ private_crt->q != NULL && ++ private_crt->dp != NULL && ++ private_crt->dq != NULL && ++ private_crt->qInverse != NULL; ++} ++ ++bool ibmca_keymgmt_rsa_priv_me_valid(const ica_rsa_key_mod_expo_t *private_me) ++{ ++ return private_me->key_length != 0 && ++ private_me->modulus != NULL && ++ private_me->exponent != NULL; ++} ++ + static int ibmca_keymgmt_rsa_dup_pub(const struct ibmca_key *key, + struct ibmca_key *new_key) + { +@@ -583,8 +652,8 @@ static int ibmca_keymgmt_rsa_dup_pub(const struct ibmca_key *key, + new_key->rsa.public.exponent = P_MEMDUP(key->provctx, + key->rsa.public.exponent, + key->rsa.public.key_length); +- if (new_key->rsa.public.modulus == NULL || +- new_key->rsa.public.exponent == NULL) { ++ ++ if (!ibmca_keymgmt_rsa_pub_valid(&new_key->rsa.public)) { + put_error_key(key, IBMCA_ERR_MALLOC_FAILED, + "Failed to allocate libica RSA key"); + return 0; +@@ -593,29 +662,46 @@ static int ibmca_keymgmt_rsa_dup_pub(const struct ibmca_key *key, + return 1; + } + +-static int ibmca_keymgmt_rsa_dup_priv(const struct ibmca_key *key, +- struct ibmca_key *new_key) ++static int ibmca_keymgmt_rsa_dup_priv_crt(const struct ibmca_key *key, ++ struct ibmca_key *new_key) + { +- new_key->rsa.private.key_length = key->rsa.private.key_length; +- +- new_key->rsa.private.p = P_SECURE_MEMDUP(key->provctx, key->rsa.private.p, +- ICA_P_LEN(key->rsa.private.key_length)); +- new_key->rsa.private.q = P_SECURE_MEMDUP(key->provctx, key->rsa.private.q, +- ICA_Q_LEN(key->rsa.private.key_length)); +- new_key->rsa.private.dp = P_SECURE_MEMDUP(key->provctx, key->rsa.private.dp, +- ICA_DP_LEN(key->rsa.private.key_length)); +- new_key->rsa.private.dq = P_SECURE_MEMDUP(key->provctx, key->rsa.private.dq, +- ICA_DQ_LEN(key->rsa.private.key_length)); +- new_key->rsa.private.qInverse = P_SECURE_MEMDUP(key->provctx, +- key->rsa.private.qInverse, ++ new_key->rsa.private_crt.key_length = key->rsa.private_crt.key_length; ++ ++ new_key->rsa.private_crt.p = P_SECURE_MEMDUP(key->provctx, key->rsa.private_crt.p, ++ ICA_P_LEN(key->rsa.private_crt.key_length)); ++ new_key->rsa.private_crt.q = P_SECURE_MEMDUP(key->provctx, key->rsa.private_crt.q, ++ ICA_Q_LEN(key->rsa.private_crt.key_length)); ++ new_key->rsa.private_crt.dp = P_SECURE_MEMDUP(key->provctx, key->rsa.private_crt.dp, ++ ICA_DP_LEN(key->rsa.private_crt.key_length)); ++ new_key->rsa.private_crt.dq = P_SECURE_MEMDUP(key->provctx, key->rsa.private_crt.dq, ++ ICA_DQ_LEN(key->rsa.private_crt.key_length)); ++ new_key->rsa.private_crt.qInverse = P_SECURE_MEMDUP(key->provctx, ++ key->rsa.private_crt.qInverse, + ICA_QINV_LEN( +- key->rsa.private.key_length)); ++ key->rsa.private_crt.key_length)); + +- if (new_key->rsa.private.p == NULL || +- new_key->rsa.private.q == NULL || +- new_key->rsa.private.dp == NULL || +- new_key->rsa.private.dq == NULL || +- new_key->rsa.private.qInverse == NULL) { ++ if (!ibmca_keymgmt_rsa_priv_crt_valid(&new_key->rsa.private_crt)) { ++ put_error_key(key, IBMCA_ERR_MALLOC_FAILED, ++ "Failed to allocate libica RSA key"); ++ return 0; ++ } ++ ++ return 1; ++} ++ ++static int ibmca_keymgmt_rsa_dup_priv_me(const struct ibmca_key *key, ++ struct ibmca_key *new_key) ++{ ++ new_key->rsa.private_me.key_length = key->rsa.private_me.key_length; ++ ++ new_key->rsa.private_me.modulus = P_MEMDUP(key->provctx, ++ key->rsa.private_me.modulus, ++ key->rsa.private_me.key_length); ++ new_key->rsa.private_me.exponent = P_MEMDUP(key->provctx, ++ key->rsa.private_me.exponent, ++ key->rsa.private_me.key_length); ++ ++ if (!ibmca_keymgmt_rsa_priv_me_valid(&new_key->rsa.private_me)) { + put_error_key(key, IBMCA_ERR_MALLOC_FAILED, + "Failed to allocate libica RSA key"); + return 0; +@@ -639,14 +725,20 @@ static int ibmca_keymgmt_rsa_dup_cb(const struct ibmca_key *key, + } + + new_key->rsa.bits = key->rsa.bits; ++ new_key->rsa.keylength = key->rsa.keylength; + +- if (key->rsa.public.key_length != 0) { ++ if (ibmca_keymgmt_rsa_pub_valid(&key->rsa.public)) { + if (ibmca_keymgmt_rsa_dup_pub(key, new_key) == 0) + return 0; + } + +- if (key->rsa.private.key_length != 0) { +- if (ibmca_keymgmt_rsa_dup_priv(key, new_key) == 0) ++ if (ibmca_keymgmt_rsa_priv_crt_valid(&key->rsa.private_crt)) { ++ if (ibmca_keymgmt_rsa_dup_priv_crt(key, new_key) == 0) ++ return 0; ++ } ++ ++ if (ibmca_keymgmt_rsa_priv_me_valid(&key->rsa.private_me)) { ++ if (ibmca_keymgmt_rsa_dup_priv_me(key, new_key) == 0) + return 0; + } + +@@ -667,21 +759,56 @@ static int ibmca_keymgmt_rsa_has(const void *vkey, int selection) + ibmca_debug_key(key, "key: %p selection: 0x%x", key, selection); + + if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) +- ok = ok && (key->rsa.public.key_length != 0 && +- key->rsa.public.modulus != NULL && +- key->rsa.public.exponent != NULL); ++ ok = ok && ibmca_keymgmt_rsa_pub_valid(&key->rsa.public); + if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) +- ok = ok && (key->rsa.private.key_length != 0 && +- key->rsa.private.p != NULL && +- key->rsa.private.q != NULL && +- key->rsa.private.dp != NULL && +- key->rsa.private.dq != NULL && +- key->rsa.private.qInverse != NULL); ++ ok = ok && (ibmca_keymgmt_rsa_priv_crt_valid(&key->rsa.private_crt) || ++ ibmca_keymgmt_rsa_priv_me_valid(&key->rsa.private_me)); + + ibmca_debug_key(key, "ok: %d", ok); + return ok; + } + ++static bool ibmca_keymgmt_rsa_pub_equal(const ica_rsa_key_mod_expo_t *public1, ++ const ica_rsa_key_mod_expo_t *public2) ++{ ++ return public1->key_length > 0 && ++ public1->key_length == public2-> key_length && ++ memcmp(public1->exponent, public2->exponent, ++ public1->key_length) == 0 && ++ memcmp(public1->modulus, public2->modulus, ++ public1->key_length) == 0; ++} ++ ++static bool ibmca_keymgmt_rsa_priv_crt_equal( ++ const ica_rsa_key_crt_t *private_crt1, ++ const ica_rsa_key_crt_t *private_crt2) ++{ ++ return private_crt1->key_length > 0 && ++ private_crt1->key_length == private_crt2->key_length && ++ CRYPTO_memcmp(private_crt1->p, private_crt2->p, ++ ICA_P_LEN(private_crt1->key_length)) == 0 && ++ CRYPTO_memcmp(private_crt1->q, private_crt2->q, ++ ICA_Q_LEN(private_crt1->key_length)) == 0 && ++ CRYPTO_memcmp(private_crt1->dp, private_crt2->dp, ++ ICA_DP_LEN(private_crt1->key_length)) == 0 && ++ CRYPTO_memcmp(private_crt1->dq, private_crt2->dq, ++ ICA_DQ_LEN(private_crt1->key_length)) == 0 && ++ CRYPTO_memcmp(private_crt1->qInverse, private_crt2->qInverse, ++ ICA_QINV_LEN(private_crt1->key_length)) == 0; ++} ++ ++static bool ibmca_keymgmt_rsa_priv_me_equal( ++ const ica_rsa_key_mod_expo_t *private_me1, ++ const ica_rsa_key_mod_expo_t *private_me2) ++{ ++ return private_me1->key_length > 0 && ++ private_me1->key_length == private_me2-> key_length && ++ CRYPTO_memcmp(private_me1->exponent, private_me2->exponent, ++ private_me2->key_length) == 0 && ++ CRYPTO_memcmp(private_me1->modulus, private_me2->modulus, ++ private_me1->key_length) == 0; ++} ++ + static int ibmca_keymgmt_rsa_match(const void *vkey1, const void *vkey2, + int selection) + { +@@ -699,35 +826,16 @@ static int ibmca_keymgmt_rsa_match(const void *vkey1, const void *vkey2, + return 0; + + if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) { +- ok = ok && (key1->rsa.public.key_length == +- key2->rsa.public.key_length && +- memcmp(key1->rsa.public.exponent, +- key2->rsa.public.exponent, +- key1->rsa.public.key_length) == 0 && +- memcmp(key1->rsa.public.modulus, +- key2->rsa.public.modulus, +- key1->rsa.public.key_length) == 0); ++ ok = ok && ibmca_keymgmt_rsa_pub_equal(&key1->rsa.public, ++ &key2->rsa.public); + checked = 1; + } + + if (!checked && (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) +- ok = ok && (key1->rsa.private.key_length == +- key2->rsa.private.key_length && +- CRYPTO_memcmp(key1->rsa.private.p, +- key2->rsa.private.p, +- ICA_P_LEN(key1->rsa.private.key_length)) == 0 && +- CRYPTO_memcmp(key1->rsa.private.q, +- key2->rsa.private.q, +- ICA_Q_LEN(key1->rsa.private.key_length)) == 0 && +- CRYPTO_memcmp(key1->rsa.private.dp, +- key2->rsa.private.dp, +- ICA_DP_LEN(key1->rsa.private.key_length)) == 0 && +- CRYPTO_memcmp(key1->rsa.private.dq, +- key2->rsa.private.dq, +- ICA_DQ_LEN(key1->rsa.private.key_length)) == 0 && +- CRYPTO_memcmp(key1->rsa.private.qInverse, +- key2->rsa.private.qInverse, +- ICA_QINV_LEN(key1->rsa.private.key_length)) == 0); ++ ok = ok && (ibmca_keymgmt_rsa_priv_crt_equal(&key1->rsa.private_crt, ++ &key2->rsa.private_crt) || ++ ibmca_keymgmt_rsa_priv_me_equal(&key1->rsa.private_me, ++ &key2->rsa.private_me)); + + ibmca_debug_key(key1, "ok: %d", ok); + return ok; +@@ -922,7 +1030,7 @@ static int ibmca_keymgmt_rsa_gen_set_template(void *vgenctx, void *vtempl) + ibmca_keymgmt_rsa_gen_free_cb(genctx); + + genctx->rsa.gen.bits = templ->rsa.bits; +- if (templ->rsa.public.exponent != NULL) { ++ if (ibmca_keymgmt_rsa_pub_valid(&templ->rsa.public)) { + genctx->rsa.gen.pub_exp = BN_bin2bn(templ->rsa.public.exponent, + templ->rsa.public.key_length, + NULL); +@@ -1153,6 +1261,7 @@ static void *ibmca_keymgmt_rsa_gen(void *vgenctx, OSSL_CALLBACK *osslcb, + } + + key->rsa.bits = genctx->rsa.gen.bits; ++ key->rsa.keylength = (key->rsa.bits + 7) / 8; + ibmca_debug_op_ctx(genctx, "bits: %lu", key->rsa.bits); + + if (ibmca_keymgmt_rsa_alloc_pub(key) == 0) { +@@ -1160,7 +1269,7 @@ static void *ibmca_keymgmt_rsa_gen(void *vgenctx, OSSL_CALLBACK *osslcb, + return NULL; + } + +- if (ibmca_keymgmt_rsa_alloc_priv(key) == 0) { ++ if (ibmca_keymgmt_rsa_alloc_priv_crt(key) == 0) { + ibmca_keymgmt_free(key); + return NULL; + } +@@ -1189,7 +1298,7 @@ static void *ibmca_keymgmt_rsa_gen(void *vgenctx, OSSL_CALLBACK *osslcb, + } + + rc = ica_rsa_key_generate_crt(genctx->provctx->ica_adapter, key->rsa.bits, +- &key->rsa.public, &key->rsa.private); ++ &key->rsa.public, &key->rsa.private_crt); + if (rc != 0) { + ibmca_debug_op_ctx(genctx, "ica_rsa_key_generate_crt failed with: %s", + strerror(rc)); +@@ -1204,7 +1313,7 @@ static void *ibmca_keymgmt_rsa_gen(void *vgenctx, OSSL_CALLBACK *osslcb, + } + + /* If p < q, swap and recalculate now */ +- rc = ica_rsa_crt_key_check(&key->rsa.private); ++ rc = ica_rsa_crt_key_check(&key->rsa.private_crt); + if (rc > 1) { + put_error_op_ctx(genctx, IBMCA_ERR_INTERNAL_ERROR, + "ica_rsa_crt_key_check failed"); +@@ -1256,7 +1365,7 @@ static int ibmca_keymgmt_rsa_security_bits(size_t bits) + + int ibmca_keymgmt_rsa_pub_as_bn(struct ibmca_key *key, BIGNUM **n, BIGNUM **e) + { +- if (key->rsa.public.modulus == NULL || key->rsa.public.exponent == NULL) ++ if (!ibmca_keymgmt_rsa_pub_valid(&key->rsa.public)) + return 0; + + *n = BN_bin2bn(key->rsa.public.modulus, key->rsa.public.key_length, NULL); +@@ -1277,14 +1386,11 @@ int ibmca_keymgmt_rsa_pub_as_bn(struct ibmca_key *key, BIGNUM **n, BIGNUM **e) + return 0; + } + +- +-static int ibmca_keymgmt_rsa_priv_as_bn(struct ibmca_key *key, BIGNUM **p, +- BIGNUM **q, BIGNUM **dp, BIGNUM **dq, +- BIGNUM **qinv) ++static int ibmca_keymgmt_rsa_priv_crt_as_bn(struct ibmca_key *key, BIGNUM **p, ++ BIGNUM **q, BIGNUM **dp, ++ BIGNUM **dq, BIGNUM **qinv) + { +- if (key->rsa.private.p == NULL || key->rsa.private.q == NULL || +- key->rsa.private.dp == NULL || key->rsa.private.dq == NULL || +- key->rsa.private.qInverse == NULL) ++ if (!ibmca_keymgmt_rsa_priv_crt_valid(&key->rsa.private_crt)) + return 0; + + *p = BN_secure_new(); +@@ -1298,17 +1404,17 @@ static int ibmca_keymgmt_rsa_priv_as_bn(struct ibmca_key *key, BIGNUM **p, + goto error; + } + +- *p = BN_bin2bn(key->rsa.private.p, +- ICA_P_LEN(key->rsa.private.key_length), *p); +- *q = BN_bin2bn(key->rsa.private.q, +- ICA_Q_LEN(key->rsa.private.key_length), *q); +- *dp = BN_bin2bn(key->rsa.private.dp, +- ICA_DP_LEN(key->rsa.private.key_length), ++ *p = BN_bin2bn(key->rsa.private_crt.p, ++ ICA_P_LEN(key->rsa.private_crt.key_length), *p); ++ *q = BN_bin2bn(key->rsa.private_crt.q, ++ ICA_Q_LEN(key->rsa.private_crt.key_length), *q); ++ *dp = BN_bin2bn(key->rsa.private_crt.dp, ++ ICA_DP_LEN(key->rsa.private_crt.key_length), + *dp); +- *dq = BN_bin2bn(key->rsa.private.dq, +- ICA_DQ_LEN(key->rsa.private.key_length), *dq); +- *qinv = BN_bin2bn(key->rsa.private.qInverse, +- ICA_QINV_LEN(key->rsa.private.key_length), *qinv); ++ *dq = BN_bin2bn(key->rsa.private_crt.dq, ++ ICA_DQ_LEN(key->rsa.private_crt.key_length), *dq); ++ *qinv = BN_bin2bn(key->rsa.private_crt.qInverse, ++ ICA_QINV_LEN(key->rsa.private_crt.key_length), *qinv); + if (*p == NULL || *q == NULL || *dp == NULL || + *dq == NULL || *qinv == NULL) { + put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_bin2bn failed"); +@@ -1332,6 +1438,33 @@ static int ibmca_keymgmt_rsa_priv_as_bn(struct ibmca_key *key, BIGNUM **p, + return 0; + } + ++int ibmca_keymgmt_rsa_priv_me_as_bn(struct ibmca_key *key, BIGNUM **d) ++{ ++ if (!ibmca_keymgmt_rsa_priv_me_valid(&key->rsa.private_me)) ++ return 0; ++ ++ *d = BN_secure_new(); ++ if (*d == NULL) { ++ put_error_key(key, IBMCA_ERR_MALLOC_FAILED, "BN_secure_new failed"); ++ goto error; ++ } ++ ++ *d = BN_bin2bn(key->rsa.private_me.exponent, key->rsa.private_me.key_length, ++ *d); ++ if (*d == NULL) { ++ put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_bin2bn failed"); ++ goto error; ++ } ++ ++ return 1; ++ ++error: ++ BN_clear_free(*d); ++ *d = NULL; ++ ++ return 0; ++} ++ + static int ibmca_keymgmt_rsa_calc_priv_d(struct ibmca_key *key, BIGNUM *n, + BIGNUM *e, BIGNUM *p, BIGNUM *q, + BIGNUM **d) +@@ -1379,8 +1512,9 @@ static int ibmca_keymgmt_rsa_get_params(void *vkey, OSSL_PARAM params[]) + for (parm = params; parm != NULL && parm->key != NULL; parm++) + ibmca_debug_key(key, "param: %s", parm->key); + +- empty = (key->rsa.public.key_length == 0 || +- key->rsa.private.key_length == 0); ++ empty = (!ibmca_keymgmt_rsa_pub_valid(&key->rsa.public) || ++ (!ibmca_keymgmt_rsa_priv_crt_valid(&key->rsa.private_crt) && ++ !ibmca_keymgmt_rsa_priv_me_valid(&key->rsa.private_me))); + + if (!empty) { + /* OSSL_PKEY_PARAM_BITS */ +@@ -1439,16 +1573,30 @@ static int ibmca_keymgmt_rsa_get_params(void *vkey, OSSL_PARAM params[]) + } + + /* Private key parts */ +- rc = ibmca_keymgmt_rsa_priv_as_bn(key, &p, &q, &dp, &dq, &qinv); ++ rc = ibmca_keymgmt_rsa_priv_crt_as_bn(key, &p, &q, &dp, &dq, &qinv); + if (rc == 1) { +- rc = ibmca_keymgmt_rsa_calc_priv_d(key, n, e, p, q, &d); +- if (rc == 0) +- goto out; ++ /* CRT format */ ++ rc = ibmca_keymgmt_rsa_priv_me_as_bn(key, &d); ++ if (rc == 0) { ++ rc = ibmca_keymgmt_rsa_calc_priv_d(key, n, e, p, q, &d); ++ if (rc == 0) ++ goto out; ++ } + + rc = ibmca_keymgmt_rsa_priv_key_to_data(key->provctx, NULL, params, d, + p, q, dp, dq, qinv); + if (rc == 0) + goto out; ++ } else { ++ rc = ibmca_keymgmt_rsa_priv_me_as_bn(key, &d); ++ if (rc == 1) { ++ /* ME format */ ++ rc = ibmca_keymgmt_rsa_priv_key_to_data(key->provctx, NULL, params, ++ d, NULL, NULL, NULL, NULL, ++ NULL); ++ if (rc == 0) ++ goto out; ++ } + } + + /* Return RSA-PSS parameters only for restricted RSA-PSS keys */ +@@ -1684,16 +1832,30 @@ int ibmca_keymgmt_rsa_export(void *vkey, int selection, + + if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) { + /* Private key parts */ +- rc = ibmca_keymgmt_rsa_priv_as_bn(key, &p, &q, &dp, &dq, &qinv); ++ rc = ibmca_keymgmt_rsa_priv_crt_as_bn(key, &p, &q, &dp, &dq, &qinv); + if (rc == 1) { +- rc = ibmca_keymgmt_rsa_calc_priv_d(key, n, e, p, q, &d); +- if (rc == 0) +- goto error; ++ /* CRT format */ ++ rc = ibmca_keymgmt_rsa_priv_me_as_bn(key, &d); ++ if (rc == 0) { ++ rc = ibmca_keymgmt_rsa_calc_priv_d(key, n, e, p, q, &d); ++ if (rc == 0) ++ goto error; ++ } + + rc = ibmca_keymgmt_rsa_priv_key_to_data(key->provctx, bld, NULL, d, + p, q, dp, dq, qinv); + if (rc == 0) + goto error; ++ } else { ++ rc = ibmca_keymgmt_rsa_priv_me_as_bn(key, &d); ++ if (rc == 1) { ++ /* ME format */ ++ rc = ibmca_keymgmt_rsa_priv_key_to_data(key->provctx, bld, NULL, ++ d, NULL, NULL, NULL, ++ NULL, NULL); ++ if (rc == 0) ++ goto error; ++ } + } + } + +@@ -1773,6 +1935,7 @@ int ibmca_keymgmt_rsa_import(void *vkey, int selection, + return 0; + + key->rsa.bits = BN_num_bits(n); ++ key->rsa.keylength = (key->rsa.bits + 7) / 8; + ibmca_debug_key(key, "key: %p bits: %u", key, key->rsa.bits); + + if (ibmca_keymgmt_rsa_alloc_pub(key) == 0) +@@ -1794,52 +1957,73 @@ int ibmca_keymgmt_rsa_import(void *vkey, int selection, + + if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) { + /* Import private key parts */ +- if (ibmca_keymgmt_rsa_alloc_priv(key) == 0) +- goto out; +- +- rc = ibmca_keymgmt_rsa_priv_key_from_data(key->provctx, params, &d, +- &p, &q, &dp, &dq, &qinv); +- if (rc == 0) +- goto out; +- +- if (BN_bn2binpad(p, key->rsa.private.p, +- ICA_P_LEN(key->rsa.private.key_length)) <= 0) { +- put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, +- "BN_bn2binpad failed for private p"); +- goto out; +- } +- if (BN_bn2binpad(q, key->rsa.private.q, +- ICA_Q_LEN(key->rsa.private.key_length)) <= 0) { +- put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, +- "BN_bn2binpad failed for private q"); +- goto out; +- } +- if (BN_bn2binpad(dp, key->rsa.private.dp, +- ICA_DP_LEN(key->rsa.private.key_length)) <= 0) { +- put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, +- "BN_bn2binpad failed for private dp"); +- goto out; +- } +- if (BN_bn2binpad(dq, key->rsa.private.dq, +- ICA_DQ_LEN(key->rsa.private.key_length)) <= 0) { +- put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, +- "BN_bn2binpad failed for private dq"); +- goto out; +- } +- if (BN_bn2binpad(qinv, key->rsa.private.qInverse, +- ICA_QINV_LEN(key->rsa.private.key_length)) <= 0) { +- put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, +- "BN_bn2binpad failed for private qinv"); +- goto out; ++ rc = ibmca_keymgmt_rsa_priv_crt_key_from_data(key->provctx, params, ++ &p, &q, &dp, &dq, &qinv); ++ if (rc == 1) { ++ /* CRT components */ ++ if (ibmca_keymgmt_rsa_alloc_priv_crt(key) == 0) ++ goto out; ++ ++ if (BN_bn2binpad(p, key->rsa.private_crt.p, ++ ICA_P_LEN(key->rsa.private_crt.key_length)) <= 0) { ++ put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, ++ "BN_bn2binpad failed for private p"); ++ goto out; ++ } ++ if (BN_bn2binpad(q, key->rsa.private_crt.q, ++ ICA_Q_LEN(key->rsa.private_crt.key_length)) <= 0) { ++ put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, ++ "BN_bn2binpad failed for private q"); ++ goto out; ++ } ++ if (BN_bn2binpad(dp, key->rsa.private_crt.dp, ++ ICA_DP_LEN(key->rsa.private_crt.key_length)) <= 0) { ++ put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, ++ "BN_bn2binpad failed for private dp"); ++ goto out; ++ } ++ if (BN_bn2binpad(dq, key->rsa.private_crt.dq, ++ ICA_DQ_LEN(key->rsa.private_crt.key_length)) <= 0) { ++ put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, ++ "BN_bn2binpad failed for private dq"); ++ goto out; ++ } ++ if (BN_bn2binpad(qinv, key->rsa.private_crt.qInverse, ++ ICA_QINV_LEN(key->rsa.private_crt.key_length)) <= 0) { ++ put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, ++ "BN_bn2binpad failed for private qinv"); ++ goto out; ++ } ++ ++ /* If p < q, swap and recalculate now */ ++ rc = ica_rsa_crt_key_check(&key->rsa.private_crt); ++ if (rc > 1) { ++ rc = 0; ++ put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, ++ "ica_rsa_crt_key_check failed"); ++ goto out; ++ } + } + +- /* If p < q, swap and recalculate now */ +- rc = ica_rsa_crt_key_check(&key->rsa.private); +- if (rc > 1) { +- rc = 0; +- put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, +- "ica_rsa_crt_key_check failed"); +- goto out; ++ rc = ibmca_keymgmt_rsa_priv_me_key_from_data(key->provctx, params, &d); ++ if (rc == 1) { ++ /* ME components */ ++ if (ibmca_keymgmt_rsa_alloc_priv_me(key) == 0) ++ goto out; ++ ++ if (BN_bn2binpad(n, key->rsa.private_me.modulus, ++ key->rsa.private_me.key_length) <= 0) { ++ put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, ++ "BN_bn2binpad failed for modulus"); ++ goto out; ++ } ++ ++ if (BN_bn2binpad(d, key->rsa.private_me.exponent, ++ key->rsa.private_me.key_length) <= 0) { ++ put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, ++ "BN_bn2binpad failed for private d"); ++ goto out; ++ } + } + } + +@@ -1902,19 +2086,22 @@ int ibmca_keymgmt_rsa_derive_kdk(struct ibmca_key *key, + return 0; + } + +- rc = ibmca_keymgmt_rsa_priv_as_bn(key, &p, &q, &dp, &dq, &qinv); +- if (rc == 0) +- goto out; ++ rc = ibmca_keymgmt_rsa_priv_me_as_bn(key, &d); ++ if (rc == 0) { ++ rc = ibmca_keymgmt_rsa_priv_crt_as_bn(key, &p, &q, &dp, &dq, &qinv); ++ if (rc == 0) ++ goto out; + +- rc = ibmca_keymgmt_rsa_pub_as_bn(key, &n, &e); +- if (rc == 0) +- goto out; ++ rc = ibmca_keymgmt_rsa_pub_as_bn(key, &n, &e); ++ if (rc == 0) ++ goto out; + +- rc = ibmca_keymgmt_rsa_calc_priv_d(key, n, e, p, q, &d); +- if (rc == 0) +- goto out; ++ rc = ibmca_keymgmt_rsa_calc_priv_d(key, n, e, p, q, &d); ++ if (rc == 0) ++ goto out; ++ } + +- buf = P_SECURE_ZALLOC(key->provctx, key->rsa.private.key_length); ++ buf = P_SECURE_ZALLOC(key->provctx, key->rsa.keylength); + if (buf == NULL) { + put_error_key(key, IBMCA_ERR_MALLOC_FAILED, + "Failed to allocate buffer for private key"); +@@ -1922,7 +2109,7 @@ int ibmca_keymgmt_rsa_derive_kdk(struct ibmca_key *key, + } + + BN_set_flags(d, BN_FLG_CONSTTIME); +- if (BN_bn2binpad(d, buf, key->rsa.private.key_length) < 0) { ++ if (BN_bn2binpad(d, buf, key->rsa.keylength) < 0) { + put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, + "BN_bn2binpad failed"); + goto out; +@@ -1942,8 +2129,7 @@ int ibmca_keymgmt_rsa_derive_kdk(struct ibmca_key *key, + goto out; + } + +- if (EVP_Digest(buf, key->rsa.private.key_length, d_hash, NULL, md, NULL) +- <= 0) { ++ if (EVP_Digest(buf, key->rsa.keylength, d_hash, NULL, md, NULL) <= 0) { + put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "EVP_Digest failed"); + goto out; + } +@@ -1971,10 +2157,9 @@ int ibmca_keymgmt_rsa_derive_kdk(struct ibmca_key *key, + goto out; + } + +- if (inlen < key->rsa.private.key_length) { +- memset(buf, 0, key->rsa.private.key_length - inlen); +- if (EVP_MAC_update(ctx, buf, key->rsa.private.key_length - inlen) +- != 1) { ++ if (inlen < key->rsa.keylength) { ++ memset(buf, 0, key->rsa.keylength - inlen); ++ if (EVP_MAC_update(ctx, buf, key->rsa.keylength - inlen) != 1) { + put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, + "EVP_MAC_update failed"); + goto out; +@@ -2003,7 +2188,7 @@ int ibmca_keymgmt_rsa_derive_kdk(struct ibmca_key *key, + BN_free(dq); + BN_free(qinv); + if (buf != NULL) +- P_SECURE_CLEAR_FREE(key->provctx, buf, key->rsa.private.key_length); ++ P_SECURE_CLEAR_FREE(key->provctx, buf, key->rsa.keylength); + EVP_MAC_free(hmac); + EVP_MAC_CTX_free(ctx); + EVP_MD_free(md); +diff --git a/src/provider/rsa_signature.c b/src/provider/rsa_signature.c +index cfc10a1..f7a0a91 100644 +--- a/src/provider/rsa_signature.c ++++ b/src/provider/rsa_signature.c +@@ -719,7 +719,7 @@ static int ibmca_signature_rsa_sign(void *vctx, + goto out; + + /* Perform private key encrypt */ +- rc = ibmca_rsa_crt_with_blinding(ctx->key, enc_data, sig, rsa_size); ++ rc = ibmca_rsa_priv_with_blinding(ctx->key, enc_data, sig, rsa_size); + if (rc != 1) { + ibmca_debug_op_ctx(ctx, "ibmca_asym_cipher_rsa_with_blinding failed"); + +From 67efa9ad713e8283cb20111a15629f15a8ea8c86 Mon Sep 17 00:00:00 2001 +From: Ingo Franzki +Date: Tue, 25 Jul 2023 14:52:49 +0200 +Subject: [PATCH] provider: RSA: Fix get_params to retrieve max-size, bits, and + security-bits + +The RSA key management's get_params() function should be able to return the +values for max-size, bits, and security-bits if at least the public key is +available. + +The detection whether the key is 'empty', i.e. has neither the public nor the +private key components was wrong. This leads to the fact that those parameters +were not returned when only the public key was available. + +Signed-off-by: Ingo Franzki +--- + src/provider/rsa_keymgmt.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/src/provider/rsa_keymgmt.c b/src/provider/rsa_keymgmt.c +index 526f2aa..ce49c88 100644 +--- a/src/provider/rsa_keymgmt.c ++++ b/src/provider/rsa_keymgmt.c +@@ -1512,9 +1512,9 @@ static int ibmca_keymgmt_rsa_get_params(void *vkey, OSSL_PARAM params[]) + for (parm = params; parm != NULL && parm->key != NULL; parm++) + ibmca_debug_key(key, "param: %s", parm->key); + +- empty = (!ibmca_keymgmt_rsa_pub_valid(&key->rsa.public) || +- (!ibmca_keymgmt_rsa_priv_crt_valid(&key->rsa.private_crt) && +- !ibmca_keymgmt_rsa_priv_me_valid(&key->rsa.private_me))); ++ empty = (!ibmca_keymgmt_rsa_pub_valid(&key->rsa.public) && ++ !ibmca_keymgmt_rsa_priv_crt_valid(&key->rsa.private_crt) && ++ !ibmca_keymgmt_rsa_priv_me_valid(&key->rsa.private_me)); + + if (!empty) { + /* OSSL_PKEY_PARAM_BITS */ diff --git a/SPECS/openssl-ibmca.spec b/SPECS/openssl-ibmca.spec index e6263a6..0d7e42f 100644 --- a/SPECS/openssl-ibmca.spec +++ b/SPECS/openssl-ibmca.spec @@ -6,17 +6,25 @@ %endif -Summary: A dynamic OpenSSL engine for IBMCA +Summary: OpenSSL engine and provider for IBMCA Name: openssl-ibmca -Version: 2.3.1 -Release: 2%{?dist} +Version: 2.4.0 +Release: 4%{?dist} License: ASL 2.0 URL: https://github.com/opencryptoki Source0: https://github.com/opencryptoki/%{name}/archive/v%{version}/%{name}-%{version}.tar.gz -# post GA fixes -Patch0: %{name}-%{version}-fixes.patch # warn the user about engine being deprecated Patch1: %{name}-2.3.1-engine-warning.patch +# https://bugzilla.redhat.com/show_bug.cgi?id=2221894 +# https://github.com/opencryptoki/openssl-ibmca/commit/3ea8f4ed58e075e097856437c0732e11771931d0 +Patch2: %{name}-2.4.0-engine-defaults.patch +# https://bugzilla.redhat.com/show_bug.cgi?id=2222878 +# https://github.com/opencryptoki/openssl-ibmca/commit/f8a60b6678b1eb3ccadcb31f36bf7961ed8d5a9a +# https://github.com/opencryptoki/openssl-ibmca/commit/acba1d936bd84c7090ed7d3849b0bab3c7f18da0 +# https://github.com/opencryptoki/openssl-ibmca/commit/67efa9ad713e8283cb20111a15629f15a8ea8c86 +Patch3: %{name}-2.4.0-rsa-me.patch +# https://github.com/opencryptoki/openssl-ibmca/commit/2298d3964f1ce32d35bb7585e4fa224c5bf2c8d4 +Patch4: %{name}-2.4.0-log-into-tmp.patch Requires: libica >= 4.0.0 BuildRequires: make BuildRequires: gcc @@ -28,7 +36,8 @@ ExclusiveArch: s390 s390x %description -A dynamic OpenSSL engine for IBMCA crypto hardware on IBM z Systems machines. +A dynamic OpenSSL engine and provider for IBMCA crypto hardware on IBM Z +machines to accelerate cryptographic operations. %prep @@ -78,6 +87,23 @@ make check %changelog +* Thu Jul 27 2023 Dan Horák - 2.4.0-4 +- provider: RSA: Fix get_params to retrieve max-size, bits, and security-bits (#2222878 #2224568) +- provider: Default debug directory to /tmp but make it configurable (#2160084) +- Resolves: #2222878 #2160084 #2224568 + +* Mon Jul 17 2023 Dan Horák - 2.4.0-3 +- provider: Support importing of RSA keys with just ME components (#2222878) +- Resolves: #2222878 + +* Tue Jul 11 2023 Dan Horák - 2.4.0-2 +- engine: Only register those algos specified with default_algorithms (#2221894) +- Resolves: #2221894 + +* Thu Apr 06 2023 Dan Horák - 2.4.0-1 +- updated to 2.4.0 (#2160084) +- Resolves: #2160084 + * Fri Jan 13 2023 Dan Horák - 2.3.1-2 - fix provider configuration script (#2140028) - Resolves: #2140028