diff --git a/wolfcrypt/src/error.c b/wolfcrypt/src/error.c index f6355dab1..ffc67252e 100644 --- a/wolfcrypt/src/error.c +++ b/wolfcrypt/src/error.c @@ -476,6 +476,9 @@ const char* wc_GetErrorString(int error) case AES_CCM_OVERFLOW_E: return "AES-CCM invocation counter overflow"; + case RSA_KEY_PAIR_E: + return "RSA Key Pair-Wise Consistency check fail"; + default: return "unknown error number"; diff --git a/wolfcrypt/src/rsa.c b/wolfcrypt/src/rsa.c index 8239b4367..28cce9a39 100644 --- a/wolfcrypt/src/rsa.c +++ b/wolfcrypt/src/rsa.c @@ -410,6 +410,48 @@ int wc_FreeRsaKey(RsaKey* key) } +/* Check the pair-wise consistency of the RSA key. + * Verify that k = (k^e)^d, for some k: 1 < k < n-1. */ +int wc_CheckRsaKey(RsaKey* key) +{ + mp_int k, tmp; + int ret = 0; + + if (mp_init_multi(&k, &tmp, NULL, NULL, NULL, NULL) != MP_OKAY) + ret = MP_INIT_E; + + if (ret == 0) { + if (key == NULL) + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + if (mp_set_int(&k, 0x2342) != MP_OKAY) + ret = MP_READ_E; + } + + if (ret == 0) { + if (mp_exptmod(&k, &key->e, &key->n, &tmp) != MP_OKAY) + ret = MP_EXPTMOD_E; + } + + if (ret == 0) { + if (mp_exptmod(&tmp, &key->d, &key->n, &tmp) != MP_OKAY) + ret = MP_EXPTMOD_E; + } + + if (ret == 0) { + if (mp_cmp(&k, &tmp) != MP_EQ) + ret = RSA_KEY_PAIR_E; + } + + mp_forcezero(&tmp); + mp_clear(&tmp); + mp_clear(&k); + return ret; +} + + #if !defined(WC_NO_RSA_OAEP) || defined(WC_RSA_PSS) /* Uses MGF1 standard as a mask generation function hType: hash type used diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 2cbcb7c4a..d04ea9020 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -9825,6 +9825,16 @@ int rsa_test(void) ERROR_OUT(-5551, exit_rsa); } + /* If not using old FIPS, or not using FAST or USER RSA... */ +#if !defined(HAVE_FAST_RSA) && !defined(HAVE_USER_RSA) && \ + (!defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2))) + ret = wc_CheckRsaKey(&genKey); + if (ret != 0) { + ERROR_OUT(-8228, exit_rsa); + } +#endif + der = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); if (der == NULL) { ERROR_OUT(-5552, exit_rsa); diff --git a/wolfssl/wolfcrypt/error-crypt.h b/wolfssl/wolfcrypt/error-crypt.h index 9319838aa..8b013fc4f 100644 --- a/wolfssl/wolfcrypt/error-crypt.h +++ b/wolfssl/wolfcrypt/error-crypt.h @@ -210,8 +210,9 @@ enum { ECDHE_KAT_FIPS_E = -259, /* ECDHE KAT failure */ AES_GCM_OVERFLOW_E = -260, /* AES-GCM invocation counter overflow. */ AES_CCM_OVERFLOW_E = -261, /* AES-CCM invocation counter overflow. */ + RSA_KEY_PAIR_E = -262, /* RSA Key Pair-Wise Consistency check fail. */ - WC_LAST_E = -261, /* Update this to indicate last error */ + WC_LAST_E = -262, /* Update this to indicate last error */ MIN_CODE_E = -300 /* errors -101 - -299 */ /* add new companion error id strings for any new error codes diff --git a/wolfssl/wolfcrypt/rsa.h b/wolfssl/wolfcrypt/rsa.h index 8d2c12798..b8415125c 100644 --- a/wolfssl/wolfcrypt/rsa.h +++ b/wolfssl/wolfcrypt/rsa.h @@ -146,6 +146,7 @@ struct RsaKey { WOLFSSL_API int wc_InitRsaKey(RsaKey* key, void* heap); WOLFSSL_API int wc_InitRsaKey_ex(RsaKey* key, void* heap, int devId); WOLFSSL_API int wc_FreeRsaKey(RsaKey* key); +WOLFSSL_API int wc_CheckRsaKey(RsaKey* key); #ifdef WOLFSSL_XILINX_CRYPT WOLFSSL_LOCAL int wc_InitRsaHw(RsaKey* key); #endif /* WOLFSSL_XILINX_CRYPT */