From 51d66877f7dcfd090673862bb7288951ab960bb3 Mon Sep 17 00:00:00 2001 From: Hayden Roche Date: Wed, 2 Feb 2022 15:09:22 -0800 Subject: [PATCH] Add wolfSSL_EVP_PKEY_paramgen to the compatibility layer. Currently, it only supports ECC, which is all we need it for for the OpenSplice port we're working on. In the ECC case, all it needs to do is set the group appropriately. The logic is very similar to `wolfSSL_EVP_PKEY_keygen`, minus the final step of actually generating the key. --- tests/api.c | 25 ++++++++++++---- wolfcrypt/src/evp.c | 69 ++++++++++++++++++++++++++++++++++++++++++- wolfssl/openssl/evp.h | 3 ++ 3 files changed, 91 insertions(+), 6 deletions(-) diff --git a/tests/api.c b/tests/api.c index bfeb66441..4dc98b039 100644 --- a/tests/api.c +++ b/tests/api.c @@ -43235,12 +43235,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