diff --git a/tests/api.c b/tests/api.c index 31373730f..764d2cea9 100644 --- a/tests/api.c +++ b/tests/api.c @@ -43480,12 +43480,27 @@ static void test_wolfSSL_EVP_PKEY_paramgen(void) printf(testingFmt, "wolfSSL_EVP_PKEY_paramgen"); + /* Test error conditions. */ + AssertIntEQ(EVP_PKEY_paramgen(NULL, &pkey), WOLFSSL_FAILURE); AssertNotNull(ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL)); - AssertIntEQ(EVP_PKEY_paramgen_init(ctx), 1); - AssertIntEQ(EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, NID_X9_62_prime256v1), 1); - AssertIntEQ(EVP_PKEY_CTX_set_ec_param_enc(ctx, OPENSSL_EC_NAMED_CURVE), 1); - AssertIntEQ(EVP_PKEY_keygen_init(ctx), 1); - AssertIntEQ(EVP_PKEY_keygen(ctx, &pkey), 1); + AssertIntEQ(EVP_PKEY_paramgen(ctx, NULL), WOLFSSL_FAILURE); + EVP_PKEY_CTX_free(ctx); +#ifndef NO_RSA + /* Parameter generation for RSA not supported yet. */ + AssertNotNull(ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL)); + AssertIntEQ(EVP_PKEY_paramgen(ctx, &pkey), WOLFSSL_FAILURE); + EVP_PKEY_CTX_free(ctx); +#endif + + AssertNotNull(ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL)); + AssertIntEQ(EVP_PKEY_paramgen_init(ctx), WOLFSSL_SUCCESS); + AssertIntEQ(EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, + NID_X9_62_prime256v1), WOLFSSL_SUCCESS); + AssertIntEQ(EVP_PKEY_paramgen(ctx, &pkey), WOLFSSL_SUCCESS); + AssertIntEQ(EVP_PKEY_CTX_set_ec_param_enc(ctx, OPENSSL_EC_NAMED_CURVE), + WOLFSSL_SUCCESS); + AssertIntEQ(EVP_PKEY_keygen_init(ctx), WOLFSSL_SUCCESS); + AssertIntEQ(EVP_PKEY_keygen(ctx, &pkey), WOLFSSL_SUCCESS); EVP_PKEY_CTX_free(ctx); EVP_PKEY_free(pkey); diff --git a/wolfcrypt/src/evp.c b/wolfcrypt/src/evp.c index 9fa6bd547..7fc0031b7 100644 --- a/wolfcrypt/src/evp.c +++ b/wolfcrypt/src/evp.c @@ -1946,6 +1946,69 @@ int wolfSSL_EVP_PKEY_CTX_set_ec_paramgen_curve_nid(WOLFSSL_EVP_PKEY_CTX *ctx, } } +int wolfSSL_EVP_PKEY_paramgen(WOLFSSL_EVP_PKEY_CTX* ctx, + WOLFSSL_EVP_PKEY** pkey) +{ + int ret = WOLFSSL_SUCCESS; + int ownPkey = 0; + + WOLFSSL_ENTER("wolfSSL_EVP_PKEY_paramgen"); + + if (ctx == NULL || pkey == NULL) { + WOLFSSL_MSG("Bad parameter"); + ret = WOLFSSL_FAILURE; + } + + if (ret == WOLFSSL_SUCCESS && *pkey == NULL) { + /* Only ECC is supported currently. */ + if (ctx->pkey == NULL || ctx->pkey->type != EVP_PKEY_EC) { + WOLFSSL_MSG("Key not set or key type not supported."); + ret = WOLFSSL_FAILURE; + } + else { + *pkey = wolfSSL_EVP_PKEY_new(); + if (*pkey == NULL) { + WOLFSSL_MSG("Failed to create WOLFSSL_EVP_PKEY."); + ret = WOLFSSL_FAILURE; + } + else { + (*pkey)->type = ctx->pkey->type; + ownPkey = 1; + } + } + } + if (ret == WOLFSSL_SUCCESS) { + switch ((*pkey)->type) { + #ifdef HAVE_ECC + /* For ECC parameter generation we just need to set the group, which + * wolfSSL_EC_KEY_new_by_curve_name will do. */ + case EVP_PKEY_EC: + (*pkey)->ecc = wolfSSL_EC_KEY_new_by_curve_name(ctx->curveNID); + if ((*pkey)->ecc == NULL) { + WOLFSSL_MSG("Failed to create WOLFSSL_EC_KEY."); + ret = WOLFSSL_FAILURE; + } + else { + (*pkey)->ownEcc = 1; + } + break; + #endif + default: + ret = WOLFSSL_FAILURE; + break; + } + } + + if (ret != WOLFSSL_SUCCESS && ownPkey) { + wolfSSL_EVP_PKEY_free(*pkey); + *pkey = NULL; + } + + WOLFSSL_LEAVE("wolfSSL_EVP_PKEY_paramgen", ret); + + return ret; +} + /* wolfSSL only supports writing out named curves so no need to store the flag. * In short, it is preferred to write out the name of the curve chosen instead * of the explicit parameters. @@ -2011,7 +2074,11 @@ int wolfSSL_EVP_PKEY_keygen(WOLFSSL_EVP_PKEY_CTX *ctx, #endif #ifdef HAVE_ECC case EVP_PKEY_EC: - pkey->ecc = wolfSSL_EC_KEY_new_by_curve_name(ctx->curveNID); + /* pkey->ecc may not be NULL, if, for example, it was populated by a + * prior call to wolfSSL_EVP_PKEY_paramgen. */ + if (pkey->ecc == NULL) { + pkey->ecc = wolfSSL_EC_KEY_new_by_curve_name(ctx->curveNID); + } if (pkey->ecc) { ret = wolfSSL_EC_KEY_generate_key(pkey->ecc); if (ret == WOLFSSL_SUCCESS) { diff --git a/wolfssl/openssl/evp.h b/wolfssl/openssl/evp.h index bed43f0ec..5b4741e39 100644 --- a/wolfssl/openssl/evp.h +++ b/wolfssl/openssl/evp.h @@ -630,6 +630,8 @@ WOLFSSL_API int wolfSSL_EVP_PKEY_sign(WOLFSSL_EVP_PKEY_CTX *ctx, WOLFSSL_API int wolfSSL_EVP_PKEY_paramgen_init(WOLFSSL_EVP_PKEY_CTX *ctx); WOLFSSL_API int wolfSSL_EVP_PKEY_CTX_set_ec_paramgen_curve_nid(WOLFSSL_EVP_PKEY_CTX *ctx, int nid); +WOLFSSL_API int wolfSSL_EVP_PKEY_paramgen(WOLFSSL_EVP_PKEY_CTX* ctx, + WOLFSSL_EVP_PKEY** pkey); WOLFSSL_API int EVP_PKEY_CTX_set_ec_param_enc(WOLFSSL_EVP_PKEY_CTX *ctx, int flag); WOLFSSL_API int wolfSSL_EVP_PKEY_keygen_init(WOLFSSL_EVP_PKEY_CTX *ctx); @@ -934,6 +936,7 @@ WOLFSSL_API void wolfSSL_EVP_MD_do_all(void (*fn) (const WOLFSSL_EVP_MD *md, #define EVP_PKEY_sign wolfSSL_EVP_PKEY_sign #define EVP_PKEY_paramgen_init wolfSSL_EVP_PKEY_paramgen_init #define EVP_PKEY_CTX_set_ec_paramgen_curve_nid wolfSSL_EVP_PKEY_CTX_set_ec_paramgen_curve_nid +#define EVP_PKEY_paramgen wolfSSL_EVP_PKEY_paramgen #define EVP_PKEY_keygen wolfSSL_EVP_PKEY_keygen #define EVP_PKEY_keygen_init wolfSSL_EVP_PKEY_keygen_init #define EVP_PKEY_bits wolfSSL_EVP_PKEY_bits