forked from wolfSSL/wolfssl
56Ar3 Testing Updates
1. Add PCTs for ECC and FFC. 2. Update the public key checks for ECC and FFC.
This commit is contained in:
committed by
Daniel Pouzzner
parent
976402e04b
commit
a967cbcb7b
@ -3356,10 +3356,10 @@ AS_CASE([$FIPS_VERSION],
|
||||
AS_IF([test "x$ENABLED_RSAPSS" != "xyes"],
|
||||
[ENABLED_RSAPSS="yes"; AM_CFLAGS="$AM_CFLAGS -DWC_RSA_PSS"])
|
||||
AS_IF([test "x$ENABLED_ECC" != "xyes"],
|
||||
[ENABLED_ECC="yes"; AM_CFLAGS="$AM_CFLAGS -DHAVE_ECC -DTFM_ECC256 -DWOLFSSL_VALIDATE_ECC_IMPORT"
|
||||
[ENABLED_ECC="yes"; AM_CFLAGS="$AM_CFLAGS -DHAVE_ECC -DTFM_ECC256"
|
||||
AS_IF([test "x$ENABLED_ECC_SHAMIR" = "xyes"],
|
||||
[AM_CFLAGS="$AM_CFLAGS -DECC_SHAMIR"])],
|
||||
[AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_VALIDATE_ECC_IMPORT"])
|
||||
[AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_VALIDATE_ECC_IMPORT -DWOLFSSL_VALIDATE_ECC_KEYGEN"])
|
||||
AS_IF([test "x$ENABLED_AESCTR" != "xyes"],
|
||||
[ENABLED_AESCTR="yes"; AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AES_COUNTER"])
|
||||
AS_IF([test "x$ENABLED_CMAC" != "xyes"],
|
||||
@ -3373,6 +3373,7 @@ AS_CASE([$FIPS_VERSION],
|
||||
AS_IF([test "x$ENABLED_AESGCM" = "xno"],
|
||||
[ENABLED_AESGCM="yes"; AM_CFLAGS="$AM_CFLAGS -DHAVE_AESGCM"])
|
||||
AS_IF([test "x$ENABLED_MD5" = "xyes"],[ENABLED_MD5="no"; ENABLED_OLD_TLS="no"; AM_CFLAGS="$AM_CFLAGS -DNO_MD5 -DNO_OLD_TLS"])
|
||||
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_VALIDATE_ECC_IMPORT -DECC_USER_CURVES -DHAVE_ECC256 -DHAVE_ECC384 -DHAVE_ECC521"
|
||||
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ECDSA_SET_K -DWC_RNG_SEED_CB"
|
||||
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_VALIDATE_FFC_IMPORT -DHAVE_FFDHE_Q"
|
||||
AM_CFLAGS="$AM_CFLAGS -DHAVE_FFDHE_3072 -DHAVE_FFDHE_4096 -DHAVE_FFDHE_6144 -DHAVE_FFDHE_8192 -DFP_MAX_BITS=16384"
|
||||
|
@ -982,7 +982,13 @@ int wc_FreeDhKey(DhKey* key)
|
||||
}
|
||||
|
||||
|
||||
static int _ffc_validate_public_key(DhKey* key, const byte* pub, word32 pubSz,
|
||||
const byte* prime, word32 primeSz, int partial);
|
||||
static int _ffc_pairwise_consistency_test(DhKey* key,
|
||||
const byte* pub, word32 pubSz, const byte* priv, word32 privSz);
|
||||
|
||||
#ifndef WOLFSSL_KCAPI_DH
|
||||
|
||||
#ifndef WC_NO_RNG
|
||||
/* if defined to not use floating point values do not compile in */
|
||||
#ifndef WOLFSSL_DH_CONST
|
||||
@ -1337,7 +1343,16 @@ static int wc_DhGenerateKeyPair_Sync(DhKey* key, WC_RNG* rng,
|
||||
|
||||
ret = GeneratePrivateDh(key, rng, priv, privSz);
|
||||
|
||||
return (ret != 0) ? ret : GeneratePublicDh(key, priv, *privSz, pub, pubSz);
|
||||
if (ret == 0)
|
||||
ret = GeneratePublicDh(key, priv, *privSz, pub, pubSz);
|
||||
if (ret == 0)
|
||||
ret = _ffc_validate_public_key(key, pub, *pubSz, NULL, 0, 0);
|
||||
if (ret == 0) {
|
||||
ret = _ffc_pairwise_consistency_test(key, pub, *pubSz, priv, *privSz);
|
||||
if (ret != 0) ret = DHE_PCT_FIPS_E;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif /* !WOLFSSL_KCAPI_DH */
|
||||
|
||||
@ -1401,20 +1416,132 @@ static int wc_DhGenerateKeyPair_Async(DhKey* key, WC_RNG* rng,
|
||||
#endif /* WOLFSSL_ASYNC_CRYPT && WC_ASYNC_ENABLE_DH */
|
||||
|
||||
|
||||
/* Performs a Pairwise Consistency Test on an FFC key pair. */
|
||||
static int _ffc_pairwise_consistency_test(DhKey* key,
|
||||
const byte* pub, word32 pubSz, const byte* priv, word32 privSz)
|
||||
{
|
||||
#ifdef WOLFSSL_SMALL_STACK
|
||||
mp_int* publicKey = NULL;
|
||||
mp_int* privateKey = NULL;
|
||||
mp_int* checkKey = NULL;
|
||||
#else
|
||||
mp_int publicKey[1];
|
||||
mp_int privateKey[1];
|
||||
mp_int checkKey[1];
|
||||
#endif
|
||||
int ret = 0;
|
||||
|
||||
if (key == NULL || pub == NULL || priv == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
#ifdef WOLFSSL_SMALL_STACK
|
||||
publicKey = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH);
|
||||
if (publicKey == NULL)
|
||||
return MEMORY_E;
|
||||
privateKey = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH);
|
||||
if (privateKey == NULL) {
|
||||
XFREE(publicKey, key->heap, DYNAMIC_TYPE_DH);
|
||||
return MEMORY_E;
|
||||
}
|
||||
checkKey = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH);
|
||||
if (checkKey == NULL) {
|
||||
XFREE(privateKey, key->heap, DYNAMIC_TYPE_DH);
|
||||
XFREE(publicKey, key->heap, DYNAMIC_TYPE_DH);
|
||||
return MEMORY_E;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (mp_init_multi(publicKey, privateKey, checkKey,
|
||||
NULL, NULL, NULL) != MP_OKAY) {
|
||||
|
||||
#ifdef WOLFSSL_SMALL_STACK
|
||||
XFREE(privateKey, key->heap, DYNAMIC_TYPE_DH);
|
||||
XFREE(publicKey, key->heap, DYNAMIC_TYPE_DH);
|
||||
XFREE(checkKey, key->heap, DYNAMIC_TYPE_DH);
|
||||
#endif
|
||||
return MP_INIT_E;
|
||||
}
|
||||
|
||||
/* Load the private and public keys into big integers. */
|
||||
if (mp_read_unsigned_bin(publicKey, pub, pubSz) != MP_OKAY ||
|
||||
mp_read_unsigned_bin(privateKey, priv, privSz) != MP_OKAY) {
|
||||
|
||||
ret = MP_READ_E;
|
||||
}
|
||||
|
||||
/* Calculate checkKey = g^privateKey mod p */
|
||||
if (ret == 0) {
|
||||
#ifdef WOLFSSL_HAVE_SP_DH
|
||||
#ifndef WOLFSSL_SP_NO_2048
|
||||
if (mp_count_bits(&key->p) == 2048) {
|
||||
ret = sp_ModExp_2048(&key->g, privateKey, &key->p, checkKey);
|
||||
if (ret != 0)
|
||||
ret = MP_EXPTMOD_E;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#ifndef WOLFSSL_SP_NO_3072
|
||||
if (mp_count_bits(&key->p) == 3072) {
|
||||
ret = sp_ModExp_3072(&key->g, privateKey, &key->p, checkKey);
|
||||
if (ret != 0)
|
||||
ret = MP_EXPTMOD_E;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#ifdef WOLFSSL_SP_4096
|
||||
if (mp_count_bits(&key->p) == 4096) {
|
||||
ret = sp_ModExp_4096(&key->g, privateKey, &key->p, checkKey);
|
||||
if (ret != 0)
|
||||
ret = MP_EXPTMOD_E;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
#if !defined(WOLFSSL_SP_MATH)
|
||||
if (mp_exptmod(&key->g, privateKey, &key->p, checkKey) != MP_OKAY)
|
||||
ret = MP_EXPTMOD_E;
|
||||
#else
|
||||
ret = WC_KEY_SIZE_E;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Compare the calculated public key to the supplied check value. */
|
||||
if (ret == 0) {
|
||||
if (mp_cmp(checkKey, publicKey) != MP_EQ)
|
||||
ret = MP_CMP_E;
|
||||
}
|
||||
|
||||
mp_forcezero(privateKey);
|
||||
mp_clear(publicKey);
|
||||
mp_clear(checkKey);
|
||||
#ifdef WOLFSSL_SMALL_STACK
|
||||
XFREE(checkKey, key->heap, DYNAMIC_TYPE_DH);
|
||||
XFREE(privateKey, key->heap, DYNAMIC_TYPE_DH);
|
||||
XFREE(publicKey, key->heap, DYNAMIC_TYPE_DH);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* Check DH Public Key for invalid numbers, optionally allowing
|
||||
* the public key to be checked against the large prime (q).
|
||||
* Check per process in SP 800-56Ar3, section 5.6.2.3.1.
|
||||
* If q is NULL, the q value of key is used.
|
||||
* Check per process in SP 800-56Ar3, section 5.6.2.3.1 or 2.
|
||||
*
|
||||
* key DH key group parameters.
|
||||
* pub Public Key.
|
||||
* pubSz Public Key size.
|
||||
* prime Large prime (q), optionally NULL to skip check
|
||||
* primeSz Size of large prime
|
||||
* partial Do the partial test process. (section 5.6.2.3.2)
|
||||
*
|
||||
* returns 0 on success or error code
|
||||
*/
|
||||
int wc_DhCheckPubKey_ex(DhKey* key, const byte* pub, word32 pubSz,
|
||||
const byte* prime, word32 primeSz)
|
||||
static int _ffc_validate_public_key(DhKey* key, const byte* pub, word32 pubSz,
|
||||
const byte* prime, word32 primeSz, int partial)
|
||||
{
|
||||
int ret = 0;
|
||||
#ifdef WOLFSSL_SMALL_STACK
|
||||
@ -1471,7 +1598,7 @@ int wc_DhCheckPubKey_ex(DhKey* key, const byte* pub, word32 pubSz,
|
||||
ret = MP_INIT_E;
|
||||
}
|
||||
|
||||
/* SP 800-56Ar3, section 5.6.2.3.1, process step 1 */
|
||||
/* SP 800-56Ar3, section 5.6.2.3.2 */
|
||||
/* pub (y) should not be 0 or 1 */
|
||||
if (ret == 0 && mp_cmp_d(y, 2) == MP_LT) {
|
||||
ret = MP_CMP_E;
|
||||
@ -1488,55 +1615,57 @@ int wc_DhCheckPubKey_ex(DhKey* key, const byte* pub, word32 pubSz,
|
||||
ret = MP_CMP_E;
|
||||
}
|
||||
|
||||
if (ret == 0 && (prime != NULL || (mp_iszero(&key->q) == MP_NO) )) {
|
||||
if (!partial) {
|
||||
if (ret == 0 && (prime != NULL || (mp_iszero(&key->q) == MP_NO) )) {
|
||||
|
||||
/* restore key->p into p */
|
||||
if (mp_copy(&key->p, p) != MP_OKAY)
|
||||
ret = MP_INIT_E;
|
||||
}
|
||||
/* restore key->p into p */
|
||||
if (mp_copy(&key->p, p) != MP_OKAY)
|
||||
ret = MP_INIT_E;
|
||||
}
|
||||
|
||||
/* SP 800-56Ar3, section 5.6.2.3.1, process step 2 */
|
||||
if (ret == 0 && prime != NULL) {
|
||||
/* SP 800-56Ar3, section 5.6.2.3.1, process step 2 */
|
||||
if (ret == 0 && prime != NULL) {
|
||||
#ifdef WOLFSSL_HAVE_SP_DH
|
||||
#ifndef WOLFSSL_SP_NO_2048
|
||||
if (mp_count_bits(&key->p) == 2048) {
|
||||
ret = sp_ModExp_2048(y, q, p, y);
|
||||
if (ret != 0)
|
||||
ret = MP_EXPTMOD_E;
|
||||
}
|
||||
else
|
||||
if (mp_count_bits(&key->p) == 2048) {
|
||||
ret = sp_ModExp_2048(y, q, p, y);
|
||||
if (ret != 0)
|
||||
ret = MP_EXPTMOD_E;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#ifndef WOLFSSL_SP_NO_3072
|
||||
if (mp_count_bits(&key->p) == 3072) {
|
||||
ret = sp_ModExp_3072(y, q, p, y);
|
||||
if (ret != 0)
|
||||
ret = MP_EXPTMOD_E;
|
||||
}
|
||||
else
|
||||
if (mp_count_bits(&key->p) == 3072) {
|
||||
ret = sp_ModExp_3072(y, q, p, y);
|
||||
if (ret != 0)
|
||||
ret = MP_EXPTMOD_E;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#ifdef WOLFSSL_SP_4096
|
||||
if (mp_count_bits(&key->p) == 4096) {
|
||||
ret = sp_ModExp_4096(y, q, p, y);
|
||||
if (ret != 0)
|
||||
ret = MP_EXPTMOD_E;
|
||||
}
|
||||
else
|
||||
if (mp_count_bits(&key->p) == 4096) {
|
||||
ret = sp_ModExp_4096(y, q, p, y);
|
||||
if (ret != 0)
|
||||
ret = MP_EXPTMOD_E;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#endif
|
||||
|
||||
{
|
||||
{
|
||||
#if !defined(WOLFSSL_SP_MATH)
|
||||
/* calculate (y^q) mod(p), store back into y */
|
||||
if (mp_exptmod(y, q, p, y) != MP_OKAY)
|
||||
ret = MP_EXPTMOD_E;
|
||||
/* calculate (y^q) mod(p), store back into y */
|
||||
if (mp_exptmod(y, q, p, y) != MP_OKAY)
|
||||
ret = MP_EXPTMOD_E;
|
||||
#else
|
||||
ret = WC_KEY_SIZE_E;
|
||||
ret = WC_KEY_SIZE_E;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* verify above == 1 */
|
||||
if (ret == 0 && mp_cmp_d(y, 1) != MP_EQ)
|
||||
ret = MP_CMP_E;
|
||||
/* verify above == 1 */
|
||||
if (ret == 0 && mp_cmp_d(y, 1) != MP_EQ)
|
||||
ret = MP_CMP_E;
|
||||
}
|
||||
}
|
||||
|
||||
mp_clear(y);
|
||||
@ -1552,7 +1681,16 @@ int wc_DhCheckPubKey_ex(DhKey* key, const byte* pub, word32 pubSz,
|
||||
}
|
||||
|
||||
|
||||
/* Check DH Public Key for invalid numbers
|
||||
/* Performs a full public-key validation routine. */
|
||||
int wc_DhCheckPubKey_ex(DhKey* key, const byte* pub, word32 pubSz,
|
||||
const byte* prime, word32 primeSz)
|
||||
{
|
||||
return _ffc_validate_public_key(key, pub, pubSz, prime, primeSz, 0);
|
||||
}
|
||||
|
||||
|
||||
/* Check DH Public Key for invalid numbers. Performs a partial public-key
|
||||
* validation routine.
|
||||
*
|
||||
* key DH key group parameters.
|
||||
* pub Public Key.
|
||||
@ -1562,7 +1700,7 @@ int wc_DhCheckPubKey_ex(DhKey* key, const byte* pub, word32 pubSz,
|
||||
*/
|
||||
int wc_DhCheckPubKey(DhKey* key, const byte* pub, word32 pubSz)
|
||||
{
|
||||
return wc_DhCheckPubKey_ex(key, pub, pubSz, NULL, 0);
|
||||
return _ffc_validate_public_key(key, pub, pubSz, NULL, 0, 1);
|
||||
}
|
||||
|
||||
|
||||
@ -1732,109 +1870,7 @@ int wc_DhCheckPrivKey(DhKey* key, const byte* priv, word32 privSz)
|
||||
int wc_DhCheckKeyPair(DhKey* key, const byte* pub, word32 pubSz,
|
||||
const byte* priv, word32 privSz)
|
||||
{
|
||||
#ifdef WOLFSSL_SMALL_STACK
|
||||
mp_int* publicKey = NULL;
|
||||
mp_int* privateKey = NULL;
|
||||
mp_int* checkKey = NULL;
|
||||
#else
|
||||
mp_int publicKey[1];
|
||||
mp_int privateKey[1];
|
||||
mp_int checkKey[1];
|
||||
#endif
|
||||
int ret = 0;
|
||||
|
||||
if (key == NULL || pub == NULL || priv == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
#ifdef WOLFSSL_SMALL_STACK
|
||||
publicKey = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH);
|
||||
if (publicKey == NULL)
|
||||
return MEMORY_E;
|
||||
privateKey = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH);
|
||||
if (privateKey == NULL) {
|
||||
XFREE(publicKey, key->heap, DYNAMIC_TYPE_DH);
|
||||
return MEMORY_E;
|
||||
}
|
||||
checkKey = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH);
|
||||
if (checkKey == NULL) {
|
||||
XFREE(privateKey, key->heap, DYNAMIC_TYPE_DH);
|
||||
XFREE(publicKey, key->heap, DYNAMIC_TYPE_DH);
|
||||
return MEMORY_E;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (mp_init_multi(publicKey, privateKey, checkKey,
|
||||
NULL, NULL, NULL) != MP_OKAY) {
|
||||
|
||||
#ifdef WOLFSSL_SMALL_STACK
|
||||
XFREE(privateKey, key->heap, DYNAMIC_TYPE_DH);
|
||||
XFREE(publicKey, key->heap, DYNAMIC_TYPE_DH);
|
||||
XFREE(checkKey, key->heap, DYNAMIC_TYPE_DH);
|
||||
#endif
|
||||
return MP_INIT_E;
|
||||
}
|
||||
|
||||
/* Load the private and public keys into big integers. */
|
||||
if (mp_read_unsigned_bin(publicKey, pub, pubSz) != MP_OKAY ||
|
||||
mp_read_unsigned_bin(privateKey, priv, privSz) != MP_OKAY) {
|
||||
|
||||
ret = MP_READ_E;
|
||||
}
|
||||
|
||||
/* Calculate checkKey = g^privateKey mod p */
|
||||
if (ret == 0) {
|
||||
#ifdef WOLFSSL_HAVE_SP_DH
|
||||
#ifndef WOLFSSL_SP_NO_2048
|
||||
if (mp_count_bits(&key->p) == 2048) {
|
||||
ret = sp_ModExp_2048(&key->g, privateKey, &key->p, checkKey);
|
||||
if (ret != 0)
|
||||
ret = MP_EXPTMOD_E;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#ifndef WOLFSSL_SP_NO_3072
|
||||
if (mp_count_bits(&key->p) == 3072) {
|
||||
ret = sp_ModExp_3072(&key->g, privateKey, &key->p, checkKey);
|
||||
if (ret != 0)
|
||||
ret = MP_EXPTMOD_E;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#ifdef WOLFSSL_SP_4096
|
||||
if (mp_count_bits(&key->p) == 4096) {
|
||||
ret = sp_ModExp_4096(&key->g, privateKey, &key->p, checkKey);
|
||||
if (ret != 0)
|
||||
ret = MP_EXPTMOD_E;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
#if !defined(WOLFSSL_SP_MATH)
|
||||
if (mp_exptmod(&key->g, privateKey, &key->p, checkKey) != MP_OKAY)
|
||||
ret = MP_EXPTMOD_E;
|
||||
#else
|
||||
ret = WC_KEY_SIZE_E;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Compare the calculated public key to the supplied check value. */
|
||||
if (ret == 0) {
|
||||
if (mp_cmp(checkKey, publicKey) != MP_EQ)
|
||||
ret = MP_CMP_E;
|
||||
}
|
||||
|
||||
mp_forcezero(privateKey);
|
||||
mp_clear(publicKey);
|
||||
mp_clear(checkKey);
|
||||
#ifdef WOLFSSL_SMALL_STACK
|
||||
XFREE(checkKey, key->heap, DYNAMIC_TYPE_DH);
|
||||
XFREE(privateKey, key->heap, DYNAMIC_TYPE_DH);
|
||||
XFREE(publicKey, key->heap, DYNAMIC_TYPE_DH);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
return _ffc_pairwise_consistency_test(key, pub, pubSz, priv, privSz);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1224,6 +1224,11 @@ static int wc_ecc_export_x963_compressed(ecc_key*, byte* out, word32* outLen);
|
||||
static int ecc_check_pubkey_order(ecc_key* key, ecc_point* pubkey, mp_int* a,
|
||||
mp_int* prime, mp_int* order);
|
||||
#endif
|
||||
static int _ecc_validate_public_key(ecc_key* key, int partial, int priv);
|
||||
#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
|
||||
static int _ecc_pairwise_consistency_test(ecc_key* key);
|
||||
#endif
|
||||
|
||||
|
||||
int mp_jacobi(mp_int* a, mp_int* n, int* c);
|
||||
int mp_sqrtmod_prime(mp_int* n, mp_int* prime, mp_int* ret);
|
||||
@ -4829,8 +4834,16 @@ int wc_ecc_make_key_ex2(WC_RNG* rng, int keysize, ecc_key* key, int curve_id,
|
||||
#endif
|
||||
|
||||
#endif /* WOLFSSL_ATECC508A */
|
||||
if (err == MP_OKAY)
|
||||
err = wc_ecc_check_key(key);
|
||||
|
||||
if (err == MP_OKAY) {
|
||||
err = _ecc_validate_public_key(key, 0, 0);
|
||||
}
|
||||
|
||||
#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
|
||||
if (err == MP_OKAY) {
|
||||
err = _ecc_pairwise_consistency_test(key);
|
||||
}
|
||||
#endif
|
||||
|
||||
return err;
|
||||
}
|
||||
@ -8281,6 +8294,18 @@ static int ecc_check_privkey_gen_helper(ecc_key* key)
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/* Performs a Pairwise Consistency Test on an ECC key pair. */
|
||||
static int _ecc_pairwise_consistency_test(ecc_key* key)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
if (ecc_check_privkey_gen_helper(key) != 0)
|
||||
err = ECC_PCT_FIPS_E;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
#endif /* WOLFSSL_VALIDATE_ECC_IMPORT */
|
||||
|
||||
#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || !defined(WOLFSSL_SP_MATH)
|
||||
@ -8367,8 +8392,14 @@ int wc_ecc_get_generator(ecc_point* ecp, int curve_idx)
|
||||
}
|
||||
#endif /* OPENSSLALL */
|
||||
|
||||
/* perform sanity checks on ecc key validity, 0 on success */
|
||||
int wc_ecc_check_key(ecc_key* key)
|
||||
|
||||
/* Validate the public key per SP 800-56Ar3 section 5.6.2.3.3,
|
||||
* ECC Full Public Key Validation Routine. If the parameter
|
||||
* partial is set, then it follows section 5.6.2.3.4, the ECC
|
||||
* Partial Public Key Validation Routine.
|
||||
* If the parameter priv is set, add in a few extra
|
||||
* checks on the bounds of the private key. */
|
||||
static int _ecc_validate_public_key(ecc_key* key, int partial, int priv)
|
||||
{
|
||||
int err = MP_OKAY;
|
||||
#ifndef WOLFSSL_SP_MATH
|
||||
@ -8449,6 +8480,7 @@ int wc_ecc_check_key(ecc_key* key)
|
||||
#endif
|
||||
|
||||
/* SP 800-56Ar3, section 5.6.2.3.3, process step 1 */
|
||||
/* SP 800-56Ar3, section 5.6.2.3.4, process step 1 */
|
||||
/* pubkey point cannot be at infinity */
|
||||
if (wc_ecc_point_is_at_infinity(&key->pubkey)) {
|
||||
#ifdef WOLFSSL_SMALL_STACK
|
||||
@ -8479,6 +8511,7 @@ int wc_ecc_check_key(ecc_key* key)
|
||||
#endif
|
||||
|
||||
/* SP 800-56Ar3, section 5.6.2.3.3, process step 2 */
|
||||
/* SP 800-56Ar3, section 5.6.2.3.4, process step 2 */
|
||||
/* Qx must be in the range [0, p-1] */
|
||||
if (err == MP_OKAY) {
|
||||
if (mp_cmp(key->pubkey.x, curve->prime) != MP_LT)
|
||||
@ -8491,29 +8524,34 @@ int wc_ecc_check_key(ecc_key* key)
|
||||
err = ECC_OUT_OF_RANGE_E;
|
||||
}
|
||||
|
||||
/* SP 800-56Ar3, section 5.6.2.3.3, process steps 3 */
|
||||
/* SP 800-56Ar3, section 5.6.2.3.3, process step 3 */
|
||||
/* SP 800-56Ar3, section 5.6.2.3.4, process step 3 */
|
||||
/* make sure point is actually on curve */
|
||||
if (err == MP_OKAY)
|
||||
err = wc_ecc_is_point(&key->pubkey, curve->Af, b, curve->prime);
|
||||
|
||||
/* SP 800-56Ar3, section 5.6.2.3.3, process steps 4 */
|
||||
/* pubkey * order must be at infinity */
|
||||
if (err == MP_OKAY)
|
||||
err = ecc_check_pubkey_order(key, &key->pubkey, curve->Af, curve->prime,
|
||||
curve->order);
|
||||
|
||||
/* SP 800-56Ar3, section 5.6.2.1.2 */
|
||||
/* private keys must be in the range [1, n-1] */
|
||||
if ((err == MP_OKAY) && (key->type == ECC_PRIVATEKEY) &&
|
||||
(mp_iszero(&key->k) || mp_isneg(&key->k) ||
|
||||
(mp_cmp(&key->k, curve->order) != MP_LT))) {
|
||||
err = ECC_PRIV_KEY_E;
|
||||
if (!partial) {
|
||||
/* SP 800-56Ar3, section 5.6.2.3.3, process step 4 */
|
||||
/* pubkey * order must be at infinity */
|
||||
if (err == MP_OKAY)
|
||||
err = ecc_check_pubkey_order(key, &key->pubkey, curve->Af,
|
||||
curve->prime, curve->order);
|
||||
}
|
||||
|
||||
/* SP 800-56Ar3, section 5.6.2.1.4, method (b) for ECC */
|
||||
/* private * base generator must equal pubkey */
|
||||
if (err == MP_OKAY && key->type == ECC_PRIVATEKEY)
|
||||
err = ecc_check_privkey_gen(key, curve->Af, curve->prime);
|
||||
if (priv) {
|
||||
/* SP 800-56Ar3, section 5.6.2.1.2 */
|
||||
/* private keys must be in the range [1, n-1] */
|
||||
if ((err == MP_OKAY) && (key->type == ECC_PRIVATEKEY) &&
|
||||
(mp_iszero(&key->k) || mp_isneg(&key->k) ||
|
||||
(mp_cmp(&key->k, curve->order) != MP_LT))) {
|
||||
err = ECC_PRIV_KEY_E;
|
||||
}
|
||||
|
||||
/* SP 800-56Ar3, section 5.6.2.1.4, method (b) for ECC */
|
||||
/* private * base generator must equal pubkey */
|
||||
if (err == MP_OKAY && key->type == ECC_PRIVATEKEY)
|
||||
err = ecc_check_privkey_gen(key, curve->Af, curve->prime);
|
||||
}
|
||||
|
||||
wc_ecc_curve_free(curve);
|
||||
|
||||
@ -8532,6 +8570,14 @@ int wc_ecc_check_key(ecc_key* key)
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/* perform sanity checks on ecc key validity, 0 on success */
|
||||
int wc_ecc_check_key(ecc_key* key)
|
||||
{
|
||||
return _ecc_validate_public_key(key, 0, 1);
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_ECC_KEY_IMPORT
|
||||
/* import public ECC key in ANSI X9.63 format */
|
||||
int wc_ecc_import_x963_ex(const byte* in, word32 inLen, ecc_key* key,
|
||||
|
@ -545,6 +545,12 @@ const char* wc_GetErrorString(int error)
|
||||
case KDF_SSH_KAT_FIPS_E:
|
||||
return "wolfcrypt FIPS SSH KDF Known Answer Test Failure";
|
||||
|
||||
case DHE_PCT_FIPS_E:
|
||||
return "wolfcrypt FIPS DHE Pairwise Consistency Test Failure";
|
||||
|
||||
case ECC_PCT_FIPS_E:
|
||||
return "wolfcrypt FIPS ECDHE Pairwise Consistency Test Failure";
|
||||
|
||||
default:
|
||||
return "unknown error number";
|
||||
|
||||
|
@ -16165,7 +16165,7 @@ static int dh_generate_test(WC_RNG *rng)
|
||||
#else
|
||||
DhKey smallKey[1];
|
||||
#endif
|
||||
byte p[2] = { 0, 5 };
|
||||
byte p[2] = { 1, 7 }; /* 263 in decimal */
|
||||
byte g[2] = { 0, 2 };
|
||||
#if !defined(WOLFSSL_SP_MATH)
|
||||
#ifdef WOLFSSL_DH_CONST
|
||||
|
@ -243,8 +243,10 @@ enum {
|
||||
KDF_TLS12_KAT_FIPS_E = -282, /* TLS12 KDF KAT failure */
|
||||
KDF_TLS13_KAT_FIPS_E = -283, /* TLS13 KDF KAT failure */
|
||||
KDF_SSH_KAT_FIPS_E = -284, /* SSH KDF KAT failure */
|
||||
DHE_PCT_FIPS_E = -285, /* DHE Pairwise Consistency Test failure */
|
||||
ECC_PCT_FIPS_E = -286, /* ECDHE Pairwise Consistency Test failure */
|
||||
|
||||
WC_LAST_E = -284, /* Update this to indicate last error */
|
||||
WC_LAST_E = -286, /* Update this to indicate last error */
|
||||
MIN_CODE_E = -300 /* errors -101 - -299 */
|
||||
|
||||
/* add new companion error id strings for any new error codes
|
||||
|
Reference in New Issue
Block a user