Skip to content

Commit

Permalink
provider: Add support for OSSL_PKEY_PARAM_RSA_DERIVE_FROM_PQ on import
Browse files Browse the repository at this point in the history
When importing a private RSA key from params, allow that only private CRT
key components OSSL_PARAM_RSA_FACTOR1, OSSL_PARAM_RSA_FACTOR2, as well as
the public key components OSSL_PARAM_RSA_N and OSSL_PKEY_PARAM_RSA_E are
available in the params, when also OSSL_PKEY_PARAM_RSA_DERIVE_FROM_PQ
with a nonzero value is contained. In this case the other CRT components
are calculated to form a complete CRT key.

OSSL_PKEY_PARAM_RSA_DERIVE_FROM_PQ is available since OpenSSL 3.3.

Signed-off-by: Ingo Franzki <[email protected]>
  • Loading branch information
ifranzki committed Mar 6, 2025
1 parent f90b993 commit acef9b9
Showing 1 changed file with 125 additions and 35 deletions.
160 changes: 125 additions & 35 deletions src/provider/rsa_keymgmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ static OSSL_FUNC_keymgmt_import_types_fn ibmca_keymgmt_rsa_pss_import_types;
static void ibmca_keymgmt_rsa_free_cb(struct ibmca_key *key);
static int ibmca_keymgmt_rsa_dup_cb(const struct ibmca_key *key,
struct ibmca_key *new_key);
static int ibmca_keymgmt_rsa_calc_priv_d(const struct ibmca_prov_ctx *provctx,
BIGNUM *n, BIGNUM *e,
BIGNUM *p, BIGNUM *q,
BIGNUM **d);

static int ibmca_keymgmt_rsa_pss_parms_from_data(
const struct ibmca_prov_ctx *provctx,
Expand Down Expand Up @@ -257,72 +261,155 @@ static int ibmca_keymgmt_rsa_pub_key_to_data(
return 1;
}

static int ibmca_keymgmt_rsa_derive_crt_from_pq(
const struct ibmca_prov_ctx *provctx,
BIGNUM *n, BIGNUM *e, BIGNUM *p,
BIGNUM *q, BIGNUM *dp, BIGNUM *dq,
BIGNUM *qinv)
{
BIGNUM *d = NULL, *p1 = NULL, *q1 = NULL;
BN_CTX *ctx = NULL;
int rc = 0;

ctx = BN_CTX_secure_new();
if (ctx == NULL) {
put_error_ctx(provctx, IBMCA_ERR_MALLOC_FAILED,
"BN_CTX_secure_new failed");
goto out;
}

p1 = BN_CTX_get(ctx);
q1 = BN_CTX_get(ctx);
if (p1 == NULL || q1 == NULL) {
put_error_ctx(provctx, IBMCA_ERR_MALLOC_FAILED, "BN_CTX_get failed");
goto out;
}

BN_set_flags(p1, BN_FLG_CONSTTIME);
BN_set_flags(q1, BN_FLG_CONSTTIME);

if (!BN_sub(p1, p, BN_value_one()) || /* p-1 */
!BN_sub(q1, q, BN_value_one())) { /* q-1 */
put_error_ctx(provctx, IBMCA_ERR_MALLOC_FAILED, "BN_sub failed");
goto out;
}

BN_set_flags(dp, BN_FLG_CONSTTIME);
BN_set_flags(dq, BN_FLG_CONSTTIME);
BN_set_flags(qinv, BN_FLG_CONSTTIME);

rc = ibmca_keymgmt_rsa_calc_priv_d(provctx, n, e, p, q, &d);
if (rc != 1)
goto out;

rc = 0;

/*
* See SP800-56Br1 6.3.1.3 rsakpg1 - crt (Step 5)
*
* (Step 5a) dP = d mod (p-1)
*/
if (!BN_mod(dp, d, p1, ctx)) {
put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "BN_mod failed");
goto out;
}

/* (Step 5b) dQ = d mod (q-1) */
if (!BN_mod(dq, d, q1, ctx)) {
put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "BN_mod failed");
goto out;
}

/* (Step 5c) qInv = (inverse of q) mod p */
if (BN_mod_inverse(qinv, q, p, ctx) == NULL) {
put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR,
"BN_mod_inverse failed");
goto out;
}

rc = 1;

out:
BN_CTX_free(ctx);
BN_free(d);

return rc;
}

static int ibmca_keymgmt_rsa_priv_crt_key_from_data(
const struct ibmca_prov_ctx *provctx,
const OSSL_PARAM params[], BIGNUM **p,
BIGNUM **q, BIGNUM **dp,
BIGNUM **dq, BIGNUM **qinv)
const OSSL_PARAM params[],
BIGNUM *n, BIGNUM *e,
BIGNUM **p, BIGNUM **q,
BIGNUM **dp, BIGNUM **dq, BIGNUM **qinv)
{
int rc;
int rc, derive_from_pq = 0;

/* OSSL_PKEY_PARAM_RSA_FACTOR1 */
*p = BN_secure_new();
if (*p == NULL) {
*q = BN_secure_new();
*dp = BN_secure_new();
*dq = BN_secure_new();
*qinv = BN_secure_new();
if (*p == NULL || *q == NULL || *dp == NULL || *dp == NULL ||
*qinv == NULL) {
put_error_ctx(provctx, IBMCA_ERR_MALLOC_FAILED, "BN_secure_new failed");
goto error;
}

/* OSSL_PKEY_PARAM_RSA_FACTOR1 */
rc = ibmca_param_get_bn(provctx, params, OSSL_PKEY_PARAM_RSA_FACTOR1, p);
if (rc <= 0)
goto error;

/* OSSL_PKEY_PARAM_RSA_FACTOR2 */
*q = BN_secure_new();
if (*q == 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_FACTOR2, q);
if (rc <= 0)
goto error;

/* OSSL_PKEY_PARAM_RSA_EXPONENT1 */
*dp = BN_secure_new();
if (*dp == 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_EXPONENT1,
dp);
if (rc <= 0)
goto error;
goto check_from_pq;

/* OSSL_PKEY_PARAM_RSA_EXPONENT2 */
*dq = BN_secure_new();
if (*dq == 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_EXPONENT2,
dq);
if (rc <= 0)
goto error;
goto check_from_pq;

/* OSSL_PKEY_PARAM_RSA_COEFFICIENT1 */
*qinv = BN_secure_new();
if (*qinv == 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_COEFFICIENT1,
qinv);
if (rc <= 0)
goto error;
goto check_from_pq;

return 1;

check_from_pq:
#ifdef OSSL_PKEY_PARAM_RSA_DERIVE_FROM_PQ
/* OSSL_PKEY_PARAM_RSA_DERIVE_FROM_PQ */
rc = ibmca_param_get_int(provctx, params,
OSSL_PKEY_PARAM_RSA_DERIVE_FROM_PQ,
&derive_from_pq);
if (rc <= 0)
goto error;
#endif

if (derive_from_pq) {
rc = ibmca_keymgmt_rsa_derive_crt_from_pq(provctx, n, e, *p, *q,
*dp, *dq, *qinv);
if (rc != 1)
goto error;

return 1;
}

error:
BN_clear_free(*p);
*p = NULL;
BN_clear_free(*q);
*q = NULL;
BN_clear_free(*dp);
*dp = NULL;
BN_clear_free(*dq);
Expand Down Expand Up @@ -1496,8 +1583,9 @@ int ibmca_keymgmt_rsa_priv_me_as_bn(struct ibmca_key *key, BIGNUM **d)
return 0;
}

static int ibmca_keymgmt_rsa_calc_priv_d(struct ibmca_key *key, BIGNUM *n,
BIGNUM *e, BIGNUM *p, BIGNUM *q,
static int ibmca_keymgmt_rsa_calc_priv_d(const struct ibmca_prov_ctx *provctx,
BIGNUM *n, BIGNUM *e,
BIGNUM *p, BIGNUM *q,
BIGNUM **d)
{
BN_CTX *bn_ctx;
Expand All @@ -1514,7 +1602,7 @@ static int ibmca_keymgmt_rsa_calc_priv_d(struct ibmca_key *key, BIGNUM *n,
BN_sub(*d, *d, q) == 0 ||
BN_add_word(*d, 1) == 0 ||
BN_mod_inverse(*d, e, *d, bn_ctx) == NULL) {
put_error_key(key, IBMCA_ERR_INTERNAL_ERROR,
put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR,
"Failed to calculate private key part d");
BN_CTX_free(bn_ctx);
BN_clear_free(*d);
Expand Down Expand Up @@ -1609,7 +1697,7 @@ static int ibmca_keymgmt_rsa_get_params(void *vkey, OSSL_PARAM params[])
/* 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);
rc = ibmca_keymgmt_rsa_calc_priv_d(key->provctx, n, e, p, q, &d);
if (rc == 0)
goto out;
}
Expand Down Expand Up @@ -1868,7 +1956,8 @@ int ibmca_keymgmt_rsa_export(void *vkey, int selection,
/* 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);
rc = ibmca_keymgmt_rsa_calc_priv_d(key->provctx, n, e, p, q,
&d);
if (rc == 0)
goto error;
}
Expand Down Expand Up @@ -1989,6 +2078,7 @@ int ibmca_keymgmt_rsa_import(void *vkey, int selection,
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
/* Import private key parts */
rc = ibmca_keymgmt_rsa_priv_crt_key_from_data(key->provctx, params,
n, e,
&p, &q, &dp, &dq, &qinv);
if (rc == 1) {
/* CRT components */
Expand Down Expand Up @@ -2127,7 +2217,7 @@ int ibmca_keymgmt_rsa_derive_kdk(struct ibmca_key *key,
if (rc == 0)
goto out;

rc = ibmca_keymgmt_rsa_calc_priv_d(key, n, e, p, q, &d);
rc = ibmca_keymgmt_rsa_calc_priv_d(key->provctx, n, e, p, q, &d);
if (rc == 0)
goto out;
}
Expand Down

0 comments on commit acef9b9

Please sign in to comment.