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