Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 85 additions & 1 deletion wolfcrypt/src/ecc.c
Original file line number Diff line number Diff line change
Expand Up @@ -4779,6 +4779,30 @@ static void wc_ecc_free_async(ecc_key* key)


#ifdef HAVE_ECC_DHE
#if FIPS_VERSION3_GE(7,0,0)
/* The module's KAS-ECC-SSC validation covers only P-256, P-384 and P-521,
* and FIPS 140-3 IG C.B does not permit an algorithm implementation that
* has not been CAVP tested to be used in an approved mode; SP 800-131A
* Rev. 2 Section 5 (Table 4) additionally disallows EC key agreement
* providing fewer than 112 bits of security strength (len(n) < 224). The
* curve is resolved from key->dp, never from ecc_sets[key->idx], so a
* custom-curve key (idx == ECC_CUSTOM_IDX) cannot index out of range. */
static int ecc_fips_kas_curve_allowed(const ecc_key* key)
{
if (key->dp == NULL) {
return ECC_BAD_ARG_E;
}
switch (key->dp->id) {
case ECC_SECP256R1:
case ECC_SECP384R1:
case ECC_SECP521R1:
return 0;
default:
return ECC_CURVE_OID_E;
}
}
#endif /* FIPS_VERSION3_GE(7,0,0) */

/**
Create an ECC shared secret between two keys
private_key The private ECC key (heap hint based off of private key)
Expand Down Expand Up @@ -4808,7 +4832,27 @@ int wc_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, byte* out,
return BAD_FUNC_ARG;
}

#ifdef WOLF_CRYPTO_CB
#if FIPS_VERSION3_GE(7,0,0)
/* Gate ahead of the crypto callback and the hardware dispatch below so no
* backend computes a shared secret on a curve outside the validated
* KAS-ECC-SSC set (FIPS 140-3 IG C.B). */
err = ecc_fips_kas_curve_allowed(private_key);
if (err == 0) {
err = ecc_fips_kas_curve_allowed(public_key);
}
if (err != 0) {
return err;
}
#endif

#if defined(WOLF_CRYPTO_CB) && !FIPS_VERSION3_GE(7,0,0)
/* The ECDH crypto-callback dispatch is compiled out of v7 FIPS builds:
* the module is validated as a software module, FIPS 140-3 IG C.B bars
* using an algorithm implementation in the approved mode without CAVP
* testing, and an offload to a callback or hardware executes outside
* the validated module. A hybrid software-plus-hardware module
* configuration would reintroduce the dispatch under its own build
* option. */
#ifndef WOLF_CRYPTO_CB_FIND
if (private_key->devId != INVALID_DEVID)
#endif
Expand Down Expand Up @@ -5296,6 +5340,15 @@ int wc_ecc_shared_secret_ex(ecc_key* private_key, ecc_point* point,
return ECC_BAD_ARG_E;
}

#if FIPS_VERSION3_GE(7,0,0)
/* Direct callers of this entry point (and the async path) get the same
* KAS-ECC-SSC validated-curve gate as wc_ecc_shared_secret(). */
err = ecc_fips_kas_curve_allowed(private_key);
if (err != 0) {
return err;
}
#endif

switch (private_key->state) {
case ECC_STATE_NONE:
case ECC_STATE_SHARED_SEC_GEN:
Expand Down Expand Up @@ -6306,6 +6359,26 @@ int wc_ecc_make_key_ex2(WC_RNG* rng, int keysize, ecc_key* key, int curve_id,
{
int err;

#if FIPS_VERSION3_GE(7,0,0)
/* SP 800-131A Rev. 2 Table 2 disallows ECDSA key pair generation
* providing fewer than 112 bits of security strength (len(n) < 224), and
* SP 800-186 Section 3.2.1.1 retains P-192 for legacy use only, so
* refuse to generate on any curve smaller than 224 bits. The bound
* mirrors wc_ecc_set_curve(): an explicit curve_id selects the curve
* directly, otherwise keysize selects the smallest compiled curve that
* fits, so keysize 0 would land on the smallest compiled curve and is
* rejected too. Signature verification with the small curves stays
* available (legacy use per SP 800-131A Rev. 2 Table 2). */
if (curve_id > ECC_CURVE_DEF) {
if (wc_ecc_get_curve_size_from_id(curve_id) < WC_ECC_FIPS_GEN_MIN) {
return ECC_CURVE_OID_E;
}
}
else if (keysize < WC_ECC_FIPS_GEN_MIN) {
return ECC_CURVE_OID_E;
}
#endif

err = _ecc_make_key_ex(rng, keysize, key, curve_id, flags);

#if (FIPS_VERSION_GE(5,0) || defined(WOLFSSL_VALIDATE_ECC_KEYGEN)) && \
Expand Down Expand Up @@ -7670,6 +7743,17 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng,
return ECC_BAD_ARG_E;
}

#if FIPS_VERSION3_GE(7,0,0)
/* SP 800-131A Rev. 2 Table 2: ECDSA digital signature generation with
* len(n) < 224 is disallowed, while signature verification with those
* curves remains legacy use, so only the signing path is gated. The
* curve is resolved from key->dp, never from ecc_sets[key->idx], so a
* custom-curve key (idx == ECC_CUSTOM_IDX) cannot index out of range. */
if (key->dp->size < WC_ECC_FIPS_GEN_MIN) {
return SIG_TYPE_E;
}
#endif

#if defined(WOLFSSL_SP_MATH)
if (key->idx == ECC_CUSTOM_IDX || (1
#ifndef WOLFSSL_SP_NO_256
Expand Down
13 changes: 13 additions & 0 deletions wolfcrypt/src/hmac.c
Original file line number Diff line number Diff line change
Expand Up @@ -622,6 +622,19 @@ int wc_HmacSetKey_ex(Hmac* hmac, int type, const byte* key, word32 length,
WOLFSSL_ERROR_VERBOSE(HMAC_MIN_KEYLEN_E);
return HMAC_MIN_KEYLEN_E;
}
#if FIPS_VERSION3_GE(7,0,0)
/* FIPS 198-1 Section 4 (step 2) sets K0 = H(K) when the key is
* longer than the block size, so any length computes correctly, but
* the module's CAVP HMAC testing covers key lengths only up to
* 1024 bits and FIPS 140-3 IG C.B does not permit an algorithm
* implementation to be used in the approved mode outside its tested
* scope, so reject longer keys unless the caller explicitly opts out
* of the approved-mode limits with allowFlag. */
if (length > HMAC_FIPS_MAX_KEY) {
WOLFSSL_ERROR_VERBOSE(BAD_LENGTH_E);
return BAD_LENGTH_E;
}
#endif
}

#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_SETKEY)
Expand Down
83 changes: 83 additions & 0 deletions wolfcrypt/src/random.c
Original file line number Diff line number Diff line change
Expand Up @@ -695,6 +695,77 @@
* and array_add_one (shared utility) which both must
* remain available to SHA-512-only builds */

#if FIPS_VERSION3_GE(7,0,0)
/* SP 800-90A Rev. 1 Section 9.2 requires the reseed function to obtain its
* entropy input from "a randomness source ... that supports the security
* strength of the DRBG" and lists entropy_input among the information "not
* provided by the consuming application": "it shall not be provided by the
* consuming application as an input parameter during the reseed request"
* (reseed process step 4: Get_entropy_input). Section 9.2 does permit
* additional_input from the consuming application, and its length may be
* zero, so the caller's bytes are mixed as the additional_input argument of
* the Section 10.1.1.3 reseed algorithm while fresh entropy is drawn from
* the module's seed source exactly as the end-of-seedlife reseed in
* PollAndReSeed() draws it. */
static int Rng_ReseedFromSeedSource(WC_RNG* rng, const byte* addIn,

Check failure on line 710 in wolfcrypt/src/random.c

View workflow job for this annotation

GitHub Actions / codespell

addIn ==> adding, add in, add-on
word32 addInSz)
{
int ret;
#ifdef WOLFSSL_SMALL_STACK
byte* newSeed = (byte*)XMALLOC(SEED_SZ + SEED_BLOCK_SZ, rng->heap,
DYNAMIC_TYPE_SEED);
if (newSeed == NULL) {
return MEMORY_E;
}
#else
byte newSeed[SEED_SZ + SEED_BLOCK_SZ];
#endif

#ifdef WC_RNG_SEED_CB
if (seedCb == NULL) {
ret = DRBG_NO_SEED_CB;
}
else {
ret = seedCb(&rng->seed, newSeed, SEED_SZ + SEED_BLOCK_SZ);
if (ret != 0) {
ret = DRBG_FAILURE;
}
}
#else
ret = wc_GenerateSeed(&rng->seed, newSeed, SEED_SZ + SEED_BLOCK_SZ);
if (ret != 0) {
ret = DRBG_FAILURE;
}
#endif
if (ret == DRBG_SUCCESS) {
ret = wc_RNG_TestSeed(newSeed, SEED_SZ + SEED_BLOCK_SZ);
}
if (ret == DRBG_SUCCESS) {
#ifndef NO_SHA256
if (rng->drbgType == WC_DRBG_SHA256) {
ret = Hash_DRBG_Reseed((DRBG_internal *)rng->drbg,
newSeed + SEED_BLOCK_SZ, SEED_SZ,
addIn, addInSz);

Check failure on line 748 in wolfcrypt/src/random.c

View workflow job for this annotation

GitHub Actions / codespell

addIn ==> adding, add in, add-on
}
#endif
#ifdef WOLFSSL_DRBG_SHA512
if (rng->drbgType == WC_DRBG_SHA512) {
ret = Hash512_DRBG_Reseed((DRBG_SHA512_internal *)rng->drbg512,
newSeed + SEED_BLOCK_SZ, SEED_SZ,
addIn, addInSz);

Check failure on line 755 in wolfcrypt/src/random.c

View workflow job for this annotation

GitHub Actions / codespell

addIn ==> adding, add in, add-on
}
#endif
}
/* SP 800-90A Rev. 1 Section 8.6.6: the entropy input is a critical
* security parameter, so it does not outlive the reseed. */
ForceZero(newSeed, SEED_SZ + SEED_BLOCK_SZ);
#ifdef WOLFSSL_SMALL_STACK
XFREE(newSeed, rng->heap, DYNAMIC_TYPE_SEED);
#endif
return ret;
}
#endif /* FIPS_VERSION3_GE(7,0,0) */

/* Returns: DRBG_SUCCESS and DRBG_FAILURE or BAD_FUNC_ARG on fail */
int wc_RNG_DRBG_Reseed(WC_RNG* rng, const byte* seed, word32 seedSz)
{
Expand All @@ -713,8 +784,14 @@
#endif
return BAD_FUNC_ARG;
}
#if FIPS_VERSION3_GE(7,0,0)
/* Caller bytes become additional_input; entropy comes from the
* module's seed source (SP 800-90A Rev. 1 Section 9.2). */
return Rng_ReseedFromSeedSource(rng, seed, seedSz);
Comment on lines +787 to +790
#else
return Hash_DRBG_Reseed((DRBG_internal *)rng->drbg, seed, seedSz,
NULL, 0);
#endif
}
#endif
#ifdef WOLFSSL_DRBG_SHA512
Expand All @@ -728,8 +805,14 @@
#endif
return BAD_FUNC_ARG;
}
#if FIPS_VERSION3_GE(7,0,0)
/* Caller bytes become additional_input; entropy comes from the
* module's seed source (SP 800-90A Rev. 1 Section 9.2). */
return Rng_ReseedFromSeedSource(rng, seed, seedSz);
#else
return Hash512_DRBG_Reseed((DRBG_SHA512_internal *)rng->drbg512,
seed, seedSz, NULL, 0);
#endif
}
#endif

Expand Down
Loading
Loading