diff --git a/wolfcrypt/src/dh.c b/wolfcrypt/src/dh.c index 4d4427652..4bddf485b 100644 --- a/wolfcrypt/src/dh.c +++ b/wolfcrypt/src/dh.c @@ -184,6 +184,57 @@ int wc_DhGenerateKeyPair(DhKey* key, WC_RNG* rng, byte* priv, word32* privSz, return (ret != 0) ? ret : GeneratePublic(key, priv, *privSz, pub, pubSz); } + +/* Check DH Public Key for invalid numbers + * + * key DH key group parameters. + * pub Public Key. + * pubSz Public Key size. + * + * returns 0 on success or error code + */ +int wc_DhCheckPubKey(DhKey* key, const byte* pub, word32 pubSz) +{ + int ret = 0; + + mp_int x; + mp_int y; + + if (key == NULL || pub == NULL) { + return BAD_FUNC_ARG; + } + + if (mp_init_multi(&x, &y, NULL, NULL, NULL, NULL) != MP_OKAY) { + return MP_INIT_E; + } + + if (mp_read_unsigned_bin(&x, pub, pubSz) != MP_OKAY) { + ret = MP_READ_E; + } + + /* pub should not be 0 or 1 */ + if (ret == 0 && mp_cmp_d(&x, 2) == MP_LT) { + ret = MP_CMP_E; + } + + /* pub shouldn't be greater than or equal to p - 1 */ + if (ret == 0 && mp_copy(&key->p, &y) != MP_OKAY) { + ret = MP_INIT_E; + } + if (ret == 0 && mp_sub_d(&y, 2, &y) != MP_OKAY) { + ret = MP_SUB_E; + } + if (ret == 0 && mp_cmp(&x, &y) == MP_GT) { + ret = MP_CMP_E; + } + + mp_clear(&y); + mp_clear(&x); + + return ret; +} + + int wc_DhAgree(DhKey* key, byte* agree, word32* agreeSz, const byte* priv, word32 privSz, const byte* otherPub, word32 pubSz) { @@ -193,6 +244,11 @@ int wc_DhAgree(DhKey* key, byte* agree, word32* agreeSz, const byte* priv, mp_int y; mp_int z; + if (wc_DhCheckPubKey(key, otherPub, pubSz) != 0) { + WOLFSSL_MSG("wc_DhAgree wc_DhCheckPubKey failed"); + return DH_CHECK_PUB_E; + } + if (mp_init_multi(&x, &y, &z, 0, 0, 0) != MP_OKAY) return MP_INIT_E; diff --git a/wolfcrypt/src/error.c b/wolfcrypt/src/error.c index be37b7275..d49734474 100644 --- a/wolfcrypt/src/error.c +++ b/wolfcrypt/src/error.c @@ -416,6 +416,9 @@ const char* wc_GetErrorString(int error) case ECC_CDH_KAT_FIPS_E: return "wolfcrypt FIPS ECC CDH Known Answer Test Failure"; + case DH_CHECK_PUB_E: + return "DH Check Public Key failure"; + default: return "unknown error number"; diff --git a/wolfssl/wolfcrypt/dh.h b/wolfssl/wolfcrypt/dh.h index 332d460f0..2410ab777 100644 --- a/wolfssl/wolfcrypt/dh.h +++ b/wolfssl/wolfcrypt/dh.h @@ -56,6 +56,7 @@ WOLFSSL_API int wc_DhSetKey(DhKey* key, const byte* p, word32 pSz, const byte* g word32 gSz); WOLFSSL_API int wc_DhParamsLoad(const byte* input, word32 inSz, byte* p, word32* pInOutSz, byte* g, word32* gInOutSz); +WOLFSSL_API int wc_DhCheckPubKey(DhKey* key, const byte* pub, word32 pubSz); #ifdef __cplusplus diff --git a/wolfssl/wolfcrypt/error-crypt.h b/wolfssl/wolfcrypt/error-crypt.h index 8a5080d57..8e0c73230 100644 --- a/wolfssl/wolfcrypt/error-crypt.h +++ b/wolfssl/wolfcrypt/error-crypt.h @@ -183,6 +183,7 @@ enum { BAD_KEYWRAP_IV_E = -240, /* Decrypted AES key wrap IV incorrect */ WC_CLEANUP_E = -241, /* wolfcrypt cleanup failed */ ECC_CDH_KAT_FIPS_E = -242, /* ECC CDH Known Answer Test failure */ + DH_CHECK_PUB_E = -243, /* DH Check Pub Key error */ MIN_CODE_E = -300 /* errors -101 - -299 */