From e063984d172daa35c7c49a53540ca5b1ddd052ef Mon Sep 17 00:00:00 2001 From: Hideki Miyazaki Date: Thu, 15 Apr 2021 14:56:07 +0900 Subject: [PATCH 1/3] added EVP_PKEY_param_check --- src/ssl.c | 12 ---- tests/api.c | 54 ++++++++++++++++++ wolfcrypt/src/evp.c | 132 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 186 insertions(+), 12 deletions(-) diff --git a/src/ssl.c b/src/ssl.c index 7f0d835c7..b3a4f96ef 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -55368,18 +55368,6 @@ int wolfSSL_CTX_get_security_level(const WOLFSSL_CTX* ctx) #ifndef NO_WOLFSSL_STUB -/** - * validate the algorithm parameters of the key-pair - * @param ctx a pointer to WOLFSSL_EVP_PKEY_CTX structure - * @return WOLFSSL_FAILURE for now - */ -int wolfSSL_EVP_PKEY_param_check(WOLFSSL_EVP_PKEY_CTX* ctx) -{ - WOLFSSL_STUB("wolfSSL_EVP_PKEY_param_check"); - (void)ctx; - return WOLFSSL_FAILURE; -} - /** * set call back function for psk session use * @param ssl a pointer to WOLFSSL structure diff --git a/tests/api.c b/tests/api.c index 8af9d0bb1..28176612c 100644 --- a/tests/api.c +++ b/tests/api.c @@ -36790,6 +36790,60 @@ static void test_wolfSSL_QT_EVP_PKEY_CTX_free(void) printf(resultFmt, passed); #endif } +static void test_wolfSSL_EVP_PKEY_param_check(void) +{ +#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) +#if !defined(NO_DH) && !defined(NO_FILESYSTEM) +#if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) \ + && (HAVE_FIPS_VERSION>2)) + DH *dh = NULL; + DH *setDh = NULL; + EVP_PKEY *pkey = NULL; + EVP_PKEY_CTX* ctx = NULL; + + FILE* f = NULL; + unsigned char buf[4096]; + const unsigned char* pt = buf; + const char* dh2048 = "./certs/dh2048.der"; + long len = 0; + int code = -1; + + printf(testingFmt, "test_wolfSSL_EVP_PKEY_param_check"); + + XMEMSET(buf, 0, sizeof(buf)); + + f = XFOPEN(dh2048, "rb"); + AssertTrue(f != XBADFILE); + len = (long)XFREAD(buf, 1, sizeof(buf), f); + XFCLOSE(f); + + /* Load dh2048.der into DH with internal format */ + AssertNotNull(setDh = d2i_DHparams(NULL, &pt, len)); + AssertIntEQ(DH_check(setDh, &code), WOLFSSL_SUCCESS); + AssertIntEQ(code, 0); + code = -1; + + pkey = wolfSSL_EVP_PKEY_new(); + /* Set DH into PKEY */ + AssertIntEQ(EVP_PKEY_set1_DH(pkey, setDh), WOLFSSL_SUCCESS); + /* create ctx from pkey */ + AssertNotNull(ctx = EVP_PKEY_CTX_new(pkey, NULL)); + AssertIntEQ(EVP_PKEY_param_check(ctx), 1/* valid */); + + /* */ + /* TO DO invlaid case */ + /* */ + + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(pkey); + DH_free(setDh); + DH_free(dh); + + printf(resultFmt, passed); +#endif +#endif +#endif +} static void test_wolfSSL_EVP_BytesToKey(void) { #if defined(OPENSSL_ALL) && !defined(NO_DES3) diff --git a/wolfcrypt/src/evp.c b/wolfcrypt/src/evp.c index 3f849f1b1..1feed5c11 100644 --- a/wolfcrypt/src/evp.c +++ b/wolfcrypt/src/evp.c @@ -2113,6 +2113,138 @@ WOLFSSL_API int wolfSSL_EVP_PKEY_cmp(const WOLFSSL_EVP_PKEY *a, const WOLFSSL_EV return ret; } +/** + * validate DH algorithm parameters + * @param dh_key a pointer to WOLFSSL_EVP_PKEY_CTX structure + * @return WOLFSSL_SUCCESS on success, otherwise failure + */ +static int DH_param_check(WOLFSSL_DH* dh_key) +{ + int ret = WOLFSSL_SUCCESS; + WOLFSSL_BN_CTX* ctx = NULL; + WOLFSSL_BIGNUM *num1 = NULL; + WOLFSSL_BIGNUM *num2 = NULL; + + WOLFSSL_ENTER("DH_param_check"); + + ctx = wolfSSL_BN_CTX_new(); + if (ctx == NULL) { + WOLFSSL_MSG("failed to allocate memory"); + return WOLFSSL_FAILURE; + } + + num1 = wolfSSL_BN_new(); + num2 = wolfSSL_BN_new(); + if (num1 == NULL || num2 == NULL) { + WOLFSSL_MSG("failed to assign big number"); + ret = WOLFSSL_FAILURE; + } + + /* prime check */ + if (ret == WOLFSSL_SUCCESS && + wolfSSL_BN_is_odd(dh_key->p) == 0){ + WOLFSSL_MSG("dh_key->p is not prime"); + ret = WOLFSSL_FAILURE; + } /* TO DO safe prime check. need BN_rshift1 */ + + /* generator check */ + if (ret == WOLFSSL_SUCCESS && + (wolfSSL_BN_is_one(dh_key->g) || + wolfSSL_BN_is_negative(dh_key->g) || + wolfSSL_BN_is_zero(dh_key->g))) { + WOLFSSL_MSG("dh_key->g is not suitable generator"); + ret = WOLFSSL_FAILURE; + } + + if (ret == WOLFSSL_SUCCESS && + wolfSSL_BN_cmp(dh_key->p, dh_key->g) <= 0) { + WOLFSSL_MSG("dh_key->g is not suitable generator"); + ret = WOLFSSL_FAILURE; + } + + if (ret == WOLFSSL_SUCCESS && + dh_key->q != NULL) + { + if (ret == WOLFSSL_SUCCESS && + wolfSSL_BN_mod_exp(num1, dh_key->g, dh_key->q, dh_key->p, ctx) == + WOLFSSL_FAILURE) { + WOLFSSL_MSG("BN_mod_exp failed"); + ret = WOLFSSL_FAILURE; + } + else + if (ret == WOLFSSL_SUCCESS && + wolfSSL_BN_is_one(num1) == WOLFSSL_FAILURE) { + WOLFSSL_MSG("dh_key->g is not suitable generator"); + ret = WOLFSSL_FAILURE; + } + + /* test if the number q is prime. */ + if (ret == WOLFSSL_SUCCESS && + (wolfSSL_BN_is_prime_ex(dh_key->q, 64, ctx, NULL) <= 0)) { + WOLFSSL_MSG("dh_key->q is not prime or error during check."); + ret = WOLFSSL_FAILURE; + } /* else TO DO check q div q - 1. need BN_div */ + } + + /* clean up */ + wolfSSL_BN_CTX_free(ctx); + wolfSSL_BN_free(num1); + wolfSSL_BN_free(num2); + + WOLFSSL_LEAVE("DH_param_check", WOLFSSL_SUCCESS); + return ret; +} +/** + * validate the algorithm parameters + * @param ctx a pointer to WOLFSSL_EVP_PKEY_CTX structure + * @return WOLFSSL_SUCCESS on success, otherwise failure + */ +int wolfSSL_EVP_PKEY_param_check(WOLFSSL_EVP_PKEY_CTX* ctx) +{ + int type; + int ret; + + /* sanity check */ + if (ctx == NULL) { + return WOLFSSL_FAILURE; + } + + type = wolfSSL_EVP_PKEY_type(wolfSSL_EVP_PKEY_base_id(ctx->pkey)); + + switch(type) { + #if !defined(NO_RSA) + case EVP_PKEY_RSA: + WOLFSSL_MSG("not yet implemented"); + return WOLFSSL_FAILURE; + #endif + #if defined(HAVE_ECC) + case EVP_PKEY_EC: + WOLFSSL_MSG("not yet implemented"); + return WOLFSSL_FAILURE; + #endif + #if !defined(NO_DSA) + case EVP_PKEY_DSA: + WOLFSSL_MSG("not yet implemented"); + return WOLFSSL_FAILURE; + #endif + #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) + #if !defined(NO_DH) && !defined(NO_FILESYSTEM) + #if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) \ + && (HAVE_FIPS_VERSION>2)) + case EVP_PKEY_DH: + ret = DH_param_check(wolfSSL_EVP_PKEY_get1_DH(ctx->pkey)); + return ret; + #endif + #endif + #endif + default: + WOLFSSL_MSG("Unknown PEKY type"); + return WOLFSSL_FAILURE; + } + (void)ret; + (void)DH_param_check; +} + /* Initialize structure for signing * * ctx WOLFSSL_EVP_MD_CTX structure to initialize From 2f5b280d6c76c6a5ae0a17dd3679df14ea2a7607 Mon Sep 17 00:00:00 2001 From: Hideki Miyazaki Date: Sun, 18 Apr 2021 14:41:54 +0900 Subject: [PATCH 2/3] fixed jenkins failure part1 --- wolfcrypt/src/evp.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/wolfcrypt/src/evp.c b/wolfcrypt/src/evp.c index 1feed5c11..61c85fe4d 100644 --- a/wolfcrypt/src/evp.c +++ b/wolfcrypt/src/evp.c @@ -2177,13 +2177,14 @@ static int DH_param_check(WOLFSSL_DH* dh_key) WOLFSSL_MSG("dh_key->g is not suitable generator"); ret = WOLFSSL_FAILURE; } - +#ifdef WOLFSSL_KEY_GEN /* test if the number q is prime. */ if (ret == WOLFSSL_SUCCESS && (wolfSSL_BN_is_prime_ex(dh_key->q, 64, ctx, NULL) <= 0)) { WOLFSSL_MSG("dh_key->q is not prime or error during check."); ret = WOLFSSL_FAILURE; } /* else TO DO check q div q - 1. need BN_div */ +#endif } /* clean up */ @@ -2203,6 +2204,9 @@ int wolfSSL_EVP_PKEY_param_check(WOLFSSL_EVP_PKEY_CTX* ctx) { int type; int ret; + WOLFSSL_DH* dh_key = NULL; + + (void)dh_key; /* sanity check */ if (ctx == NULL) { @@ -2232,7 +2236,13 @@ int wolfSSL_EVP_PKEY_param_check(WOLFSSL_EVP_PKEY_CTX* ctx) #if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) \ && (HAVE_FIPS_VERSION>2)) case EVP_PKEY_DH: - ret = DH_param_check(wolfSSL_EVP_PKEY_get1_DH(ctx->pkey)); + dh_key = wolfSSL_EVP_PKEY_get1_DH(ctx->pkey); + if (dh_key != NULL) { + ret = DH_param_check(dh_key); + wolfSSL_DH_free(dh_key); + } + else + ret = WOLFSSL_FAILURE; return ret; #endif #endif From d3b41a2fedfd3fa27603cb2e09183c304fe07a46 Mon Sep 17 00:00:00 2001 From: Hideki Miyazaki Date: Wed, 21 Apr 2021 09:10:32 +0900 Subject: [PATCH 3/3] addressed review comments p1 --- tests/api.c | 22 +--------------------- wolfcrypt/src/evp.c | 40 ++++++++++++++++++++-------------------- 2 files changed, 21 insertions(+), 41 deletions(-) diff --git a/tests/api.c b/tests/api.c index 28176612c..1b4537f48 100644 --- a/tests/api.c +++ b/tests/api.c @@ -36746,26 +36746,6 @@ static void test_wolfSSL_EVP_PKEY_assign_DH(void) #endif } -static void test_wolfSSL_EVP_PKEY_param_check(void) -{ -#if defined(OPENSSL_EXTRA) - EVP_PKEY* pkey; - EVP_PKEY_CTX* ctx; - - printf(testingFmt, "test_wolfSSL_EVP_PKEY_param_check"); - - AssertNotNull(pkey = wolfSSL_EVP_PKEY_new()); - AssertNotNull(ctx = EVP_PKEY_CTX_new(pkey, NULL)); - - /* STUB */ - AssertIntEQ(EVP_PKEY_param_check(ctx), WOLFSSL_FAILURE); - - EVP_PKEY_CTX_free(ctx); - EVP_PKEY_free(pkey); - printf(resultFmt, passed); -#endif -} - static void test_wolfSSL_QT_EVP_PKEY_CTX_free(void) { #if defined(OPENSSL_EXTRA) @@ -36802,7 +36782,7 @@ static void test_wolfSSL_EVP_PKEY_param_check(void) EVP_PKEY_CTX* ctx = NULL; FILE* f = NULL; - unsigned char buf[4096]; + unsigned char buf[512]; const unsigned char* pt = buf; const char* dh2048 = "./certs/dh2048.der"; long len = 0; diff --git a/wolfcrypt/src/evp.c b/wolfcrypt/src/evp.c index 61c85fe4d..19e0bb4e5 100644 --- a/wolfcrypt/src/evp.c +++ b/wolfcrypt/src/evp.c @@ -2145,7 +2145,7 @@ static int DH_param_check(WOLFSSL_DH* dh_key) wolfSSL_BN_is_odd(dh_key->p) == 0){ WOLFSSL_MSG("dh_key->p is not prime"); ret = WOLFSSL_FAILURE; - } /* TO DO safe prime check. need BN_rshift1 */ + } /* TODO safe prime check. need BN_rshift1 */ /* generator check */ if (ret == WOLFSSL_SUCCESS && @@ -2183,7 +2183,7 @@ static int DH_param_check(WOLFSSL_DH* dh_key) (wolfSSL_BN_is_prime_ex(dh_key->q, 64, ctx, NULL) <= 0)) { WOLFSSL_MSG("dh_key->q is not prime or error during check."); ret = WOLFSSL_FAILURE; - } /* else TO DO check q div q - 1. need BN_div */ + } /* else TODO check q div q - 1. need BN_div */ #endif } @@ -2217,38 +2217,38 @@ int wolfSSL_EVP_PKEY_param_check(WOLFSSL_EVP_PKEY_CTX* ctx) switch(type) { #if !defined(NO_RSA) - case EVP_PKEY_RSA: - WOLFSSL_MSG("not yet implemented"); - return WOLFSSL_FAILURE; + case EVP_PKEY_RSA: + WOLFSSL_MSG("EVP_PKEY_RSA not yet implemented"); + return WOLFSSL_FAILURE; #endif #if defined(HAVE_ECC) - case EVP_PKEY_EC: - WOLFSSL_MSG("not yet implemented"); - return WOLFSSL_FAILURE; + case EVP_PKEY_EC: + WOLFSSL_MSG("EVP_PKEY_EC not yet implemented"); + return WOLFSSL_FAILURE; #endif #if !defined(NO_DSA) - case EVP_PKEY_DSA: - WOLFSSL_MSG("not yet implemented"); - return WOLFSSL_FAILURE; + case EVP_PKEY_DSA: + WOLFSSL_MSG("EVP_PKEY_DSA not yet implemented"); + return WOLFSSL_FAILURE; #endif #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) #if !defined(NO_DH) && !defined(NO_FILESYSTEM) #if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) \ && (HAVE_FIPS_VERSION>2)) - case EVP_PKEY_DH: - dh_key = wolfSSL_EVP_PKEY_get1_DH(ctx->pkey); - if (dh_key != NULL) { - ret = DH_param_check(dh_key); - wolfSSL_DH_free(dh_key); - } - else - ret = WOLFSSL_FAILURE; + case EVP_PKEY_DH: + dh_key = wolfSSL_EVP_PKEY_get1_DH(ctx->pkey); + if (dh_key != NULL) { + ret = DH_param_check(dh_key); + wolfSSL_DH_free(dh_key); + } + else + ret = WOLFSSL_FAILURE; return ret; #endif #endif #endif default: - WOLFSSL_MSG("Unknown PEKY type"); + WOLFSSL_MSG("Unknown PKEY type"); return WOLFSSL_FAILURE; } (void)ret;