diff --git a/openssl-ibmca-2.4.0-rsa-me.patch b/openssl-ibmca-2.4.0-rsa-me.patch new file mode 100644 index 0000000..eeaa299 --- /dev/null +++ b/openssl-ibmca-2.4.0-rsa-me.patch @@ -0,0 +1,1082 @@ +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"); + diff --git a/openssl-ibmca.spec b/openssl-ibmca.spec index e635b32..6481823 100644 --- a/openssl-ibmca.spec +++ b/openssl-ibmca.spec @@ -9,17 +9,19 @@ Summary: OpenSSL engine and provider for IBMCA Name: openssl-ibmca Version: 2.4.0 -Release: 2%{?dist} +Release: 3%{?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 +Patch3: %{name}-2.4.0-rsa-me.patch Requires: libica >= 4.0.0 BuildRequires: make BuildRequires: gcc @@ -82,6 +84,10 @@ make check %changelog +* 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