Skip to content
Merged
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
2 changes: 1 addition & 1 deletion IDE/C2000/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ if (wc_UnpackOctets(sig, (word32)sizeof(sig), sigPacked,
(word32)sizeof(sigPacked), WC_MLDSA_65_SIG_SIZE) == 0) {
ret = wc_MlDsaKey_VerifyCtxHash(key, sig, WC_MLDSA_65_SIG_SIZE,
ctx, ctxLen, hash, hashLen,
WC_HASH_TYPE_SHA256, &res);
WC_HASH_TYPE_SHA512, &res);
}
```

Expand Down
5 changes: 5 additions & 0 deletions doc/dox_comments/header_files/ecc.h
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,9 @@ int wc_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, byte* out,
\ingroup ECC

\brief Create an ECC shared secret between private key and public point.
The point is first given full public key validation on the private key's
curve with wc_ecc_check_key() (SP 800-56Ar3 5.6.2.3.3). A build without
the order check (NO_ECC_CHECK_PUBKEY_ORDER) still checks range and curve.

\return MP_OKAY Indicates success.
\return BAD_FUNC_ARG Error returned when any arguments are null.
Expand All @@ -368,6 +371,8 @@ int wc_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, byte* out,
\return MEMORY_E Error to create a new point.
\return MP_VAL possible when an initialization failure occurs.
\return MP_MEM possible when an initialization failure occurs.
\return IS_POINT_E, ECC_OUT_OF_RANGE_E, ECC_INF_E or MP_VAL when the point
fails validation (not on the curve, out of range, or the identity).

\param private_key The private ECC key.
\param point The point to use (public key).
Expand Down
7 changes: 4 additions & 3 deletions doc/dox_comments/header_files/wc_mldsa.h
Original file line number Diff line number Diff line change
Expand Up @@ -303,8 +303,8 @@ int wc_MlDsaKey_SignCtx(wc_MlDsaKey* key, const byte* ctx, byte ctxLen,

\return 0 on success.
\return BAD_FUNC_ARG if any required pointer is NULL, ctxLen is
invalid, hashAlg is not supported or the key has no private key
set.
invalid, hashAlg is not supported or is weaker than the parameter set
(FIPS 204 sec 5.4), or the key has no private key set.
\return BUFFER_E if the sig buffer is too small.

\param [in,out] key Pointer to a wc_MlDsaKey with the private key.
Expand Down Expand Up @@ -482,7 +482,8 @@ int wc_MlDsaKey_VerifyCtx(wc_MlDsaKey* key, const byte* sig, word32 sigLen,

\return 0 if verification completed (check res for the result).
\return BAD_FUNC_ARG if any required pointer is NULL, ctxLen is
invalid, or hashAlg is unsupported.
invalid, or hashAlg is unsupported or weaker than the parameter set
(FIPS 204 sec 5.4).

\param [in,out] key Pointer to a wc_MlDsaKey with the public key.
\param [in] sig Signature bytes to verify.
Expand Down
113 changes: 108 additions & 5 deletions tests/api/test_ecc.c
Original file line number Diff line number Diff line change
Expand Up @@ -834,6 +834,112 @@ static int ecc_shared_secret_size_bound(WC_RNG* rng, int curveId, int fieldSz)
}
#endif

/* wc_ecc_shared_secret_ex fully validates a raw peer point, SP 800-56Ar3
* 5.6.2.3.3. Rejections run first: a pending async call leaves key state set. */
int test_wc_ecc_shared_secret_ex_peer_point(void)
{
EXPECT_DECLS;
#if defined(HAVE_ECC) && defined(HAVE_ECC_DHE) && \
defined(HAVE_ECC_KEY_IMPORT) && !defined(WC_NO_RNG) && \
!defined(NO_ECC256) && !defined(WOLFSSL_ATECC508A) && \
!defined(WOLFSSL_ATECC608A) && !defined(WOLFSSL_MICROCHIP_TA100) && \
!defined(PLUTON_CRYPTO_ECC) && !defined(WOLFSSL_CRYPTOCELL) && \
!defined(WOLFSSL_KCAPI_ECC) && !defined(WOLF_CRYPTO_CB_ONLY_ECC)
/* P-256 base point G, uncompressed X9.63 encoding. Not const: older
* wc_ecc_import_point_der() takes byte*. */
byte g[] = {
0x04,
0x6B,0x17,0xD1,0xF2,0xE1,0x2C,0x42,0x47,0xF8,0xBC,0xE6,0xE5,
0x63,0xA4,0x40,0xF2,0x77,0x03,0x7D,0x81,0x2D,0xEB,0x33,0xA0,
0xF4,0xA1,0x39,0x45,0xD8,0x98,0xC2,0x96,
0x4F,0xE3,0x42,0xE2,0xFE,0x1A,0x7F,0x9B,0x8E,0xE7,0xEB,0x4A,
0x7C,0x0F,0x9E,0x16,0x2B,0xCE,0x33,0x57,0x6B,0x31,0x5E,0xCE,
0xCB,0xB6,0x40,0x68,0x37,0xBF,0x51,0xF5
};
byte bad[sizeof(g)];
ecc_key key;
ecc_point* peer = NULL;
WC_RNG rng;
byte out[MAX_ECC_BYTES];
word32 outLen;
int idx = wc_ecc_get_curve_idx(ECC_SECP256R1);
int ret;

XMEMSET(&key, 0, sizeof(key));
XMEMSET(&rng, 0, sizeof(rng));
PRIVATE_KEY_UNLOCK();
ExpectIntEQ(wc_InitRng(&rng), 0);
ExpectIntEQ(wc_ecc_init(&key), 0);
ret = wc_ecc_make_key_ex(&rng, 32, &key, ECC_SECP256R1);
#if defined(WOLFSSL_ASYNC_CRYPT)
ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_NONE);
#endif
ExpectIntEQ(ret, 0);
#if defined(ECC_TIMING_RESISTANT) && (!defined(HAVE_FIPS) || \
(!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION != 2))) && \
!defined(HAVE_SELFTEST)
ExpectIntEQ(wc_ecc_set_rng(&key, &rng), 0);
#endif
ExpectNotNull(peer = wc_ecc_new_point());

/* Older FIPS and selftest modules keep an ecc.c without this check, and
* SE050, STM32 PKA and SILABS hardware are not covered here. */
#if (!defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0)) && \
!defined(HAVE_SELFTEST) && !defined(WOLFSSL_SE050) && \
!defined(WOLFSSL_STM32_PKA) && !defined(WOLFSSL_SILABS_SE_ACCEL)
/* G with one bit of y flipped is off the curve. */
XMEMCPY(bad, g, sizeof(g));
bad[sizeof(bad) - 1] ^= 0x01;
ExpectIntEQ(wc_ecc_import_point_der(bad, (word32)sizeof(bad), idx, peer),
0);
outLen = sizeof(out);
ExpectIntNE(wc_ecc_shared_secret_ex(&key, peer, out, &outLen), 0);
#if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)
{
/* A P-384 point is not on P-256. */
ecc_key key2;

XMEMSET(&key2, 0, sizeof(key2));
ExpectIntEQ(wc_ecc_init(&key2), 0);
ret = wc_ecc_make_key_ex(&rng, 48, &key2, ECC_SECP384R1);
#if defined(WOLFSSL_ASYNC_CRYPT)
ret = wc_AsyncWait(ret, &key2.asyncDev, WC_ASYNC_FLAG_NONE);
#endif
ExpectIntEQ(ret, 0);
outLen = sizeof(out);
ExpectIntNE(wc_ecc_shared_secret_ex(&key, &key2.pubkey, out, &outLen),
0);
wc_ecc_free(&key2);
}
#endif
#ifdef WOLFSSL_PUBLIC_MP
/* G with Z = 2: ECDH would use the Jacobian point (x/4, y/8), not the
* affine (x, y) that the checks read. */
ExpectIntEQ(wc_ecc_import_point_der(g, (word32)sizeof(g), idx, peer), 0);
ExpectIntEQ(mp_set(peer->z, 2), MP_OKAY);
outLen = sizeof(out);
ExpectIntNE(wc_ecc_shared_secret_ex(&key, peer, out, &outLen), 0);
#endif
#else
(void)bad;
#endif

ExpectIntEQ(wc_ecc_import_point_der(g, (word32)sizeof(g), idx, peer), 0);
outLen = sizeof(out);
ret = wc_ecc_shared_secret_ex(&key, peer, out, &outLen);
#if defined(WOLFSSL_ASYNC_CRYPT)
ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_NONE);
#endif
ExpectIntEQ(ret, 0);

wc_ecc_del_point(peer);
wc_ecc_free(&key);
DoExpectIntEQ(wc_FreeRng(&rng), 0);
PRIVATE_KEY_LOCK();
#endif
return EXPECT_RESULT();
}

/*
* Testing wc_ecc_shared_secret() output buffer bounds at the field-size edge.
*/
Expand Down Expand Up @@ -3023,11 +3129,8 @@ int test_wc_ecc_shared_secret_ssh(void)
WC_RNG rng;
int ret;
int keySz = KEY32;
#if FIPS_VERSION3_GE(6,0,0)
int key2Sz = KEY28;
#else
int key2Sz = KEY24;
#endif
/* ECDH needs both keys on one curve, SP 800-56A Rev 3 sec 5.7.1.2. */
int key2Sz = KEY32;
byte secret[KEY32];
word32 secretLen = (word32)keySz;

Expand Down
2 changes: 2 additions & 0 deletions tests/api/test_ecc.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ int test_wc_ecc_params(void);
int test_wc_ecc_signVerify_hash(void);
int test_wc_ecc_shared_secret(void);
int test_wc_ecc_shared_secret_at_infinity(void);
int test_wc_ecc_shared_secret_ex_peer_point(void);
int test_wc_ecc_shared_secret_size_bounds(void);
int test_wc_ecc_export_x963(void);
int test_wc_ecc_export_x963_ex(void);
Expand Down Expand Up @@ -91,6 +92,7 @@ int test_wc_EccDecisionCoverage4(void);
TEST_DECL_GROUP("ecc", test_wc_ecc_signVerify_hash), \
TEST_DECL_GROUP("ecc", test_wc_ecc_shared_secret), \
TEST_DECL_GROUP("ecc", test_wc_ecc_shared_secret_at_infinity), \
TEST_DECL_GROUP("ecc", test_wc_ecc_shared_secret_ex_peer_point), \
TEST_DECL_GROUP("ecc", test_wc_ecc_shared_secret_size_bounds), \
TEST_DECL_GROUP("ecc", test_wc_ecc_export_x963), \
TEST_DECL_GROUP("ecc", test_wc_ecc_export_x963_ex), \
Expand Down
117 changes: 117 additions & 0 deletions tests/api/test_mldsa.c
Original file line number Diff line number Diff line change
Expand Up @@ -1351,6 +1351,123 @@ int test_mldsa_sign_vfy(void)
return EXPECT_RESULT();
}

#if defined(WOLFSSL_HAVE_MLDSA) && defined(WC_MLDSA_HAVE_NATIVE) && \
!defined(WOLFSSL_MLDSA_NO_MAKE_KEY) && \
!defined(WOLFSSL_MLDSA_NO_SIGN) && !defined(WOLFSSL_MLDSA_NO_VERIFY)
/* Collision strength in bits of each pre-hash, FIPS 202 Table 4. */
static const struct {
int hash;
int strength;
} mldsa_prehash_strengths[] = {
{ WC_HASH_TYPE_SHA224, 112 },
{ WC_HASH_TYPE_SHA256, 128 },
{ WC_HASH_TYPE_SHA384, 192 },
{ WC_HASH_TYPE_SHA512, 256 },
{ WC_HASH_TYPE_SHA512_224, 112 },
{ WC_HASH_TYPE_SHA512_256, 128 },
{ WC_HASH_TYPE_SHA3_224, 112 },
{ WC_HASH_TYPE_SHA3_256, 128 },
{ WC_HASH_TYPE_SHA3_384, 192 },
{ WC_HASH_TYPE_SHA3_512, 256 },
{ WC_HASH_TYPE_SHAKE128, 128 },
{ WC_HASH_TYPE_SHAKE256, 256 },
};

static int mldsa_prehash_strength_level(byte level, int lambda, WC_RNG* rng)
{
EXPECT_DECLS;
wc_MlDsaKey* key;
byte* sig;
byte* goodSig;
word32 sigLen;
word32 goodSigLen = MLDSA_MAX_SIG_SIZE;
byte digest[WC_MAX_DIGEST_SIZE];
int digestSz;
int hash;
int res = 0;
int i;

key = (wc_MlDsaKey*)XMALLOC(sizeof(*key), NULL, DYNAMIC_TYPE_TMP_BUFFER);
sig = (byte*)XMALLOC(MLDSA_MAX_SIG_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
goodSig = (byte*)XMALLOC(MLDSA_MAX_SIG_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
ExpectNotNull(key);
ExpectNotNull(sig);
ExpectNotNull(goodSig);
if (key != NULL) {
XMEMSET(key, 0, sizeof(*key));
}
XMEMSET(digest, 0x5A, sizeof(digest));

ExpectIntEQ(wc_MlDsaKey_Init(key, NULL, INVALID_DEVID), 0);
ExpectIntEQ(wc_MlDsaKey_SetParams(key, level), 0);
ExpectIntEQ(wc_MlDsaKey_MakeKey(key, rng), 0);
/* SHAKE256 is in every ML-DSA build and allowed at every level: a
* well-formed signature to verify. */
ExpectIntEQ(wc_MlDsaKey_SignCtxHash(key, NULL, 0, goodSig, &goodSigLen,
digest, (word32)wc_HashGetDigestSize(WC_HASH_TYPE_SHAKE256),
WC_HASH_TYPE_SHAKE256, rng), 0);

for (i = 0; i < (int)(sizeof(mldsa_prehash_strengths) /
sizeof(mldsa_prehash_strengths[0])); i++) {
hash = mldsa_prehash_strengths[i].hash;
digestSz = wc_HashGetDigestSize((enum wc_HashType)hash);
if (digestSz <= 0) {
continue; /* hash not compiled in */
}
sigLen = MLDSA_MAX_SIG_SIZE;
if (mldsa_prehash_strengths[i].strength >= lambda) {
ExpectIntEQ(wc_MlDsaKey_SignCtxHash(key, NULL, 0, sig, &sigLen,
digest, (word32)digestSz, hash, rng), 0);
ExpectIntEQ(wc_MlDsaKey_VerifyCtxHash(key, sig, sigLen, NULL, 0,
digest, (word32)digestSz, hash, &res), 0);
ExpectIntEQ(res, 1);
}
else {
ExpectIntEQ(wc_MlDsaKey_SignCtxHash(key, NULL, 0, sig, &sigLen,
digest, (word32)digestSz, hash, rng),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(wc_MlDsaKey_VerifyCtxHash(key, goodSig, goodSigLen,
NULL, 0, digest, (word32)digestSz, hash, &res),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
}
}

wc_MlDsaKey_Free(key);
XFREE(goodSig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(sig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
return EXPECT_RESULT();
}
#endif

/* HashML-DSA rejects a pre-hash weaker than lambda, FIPS 204 sec 5.4. */
int test_mldsa_prehash_strength(void)
{
EXPECT_DECLS;
#if defined(WOLFSSL_HAVE_MLDSA) && defined(WC_MLDSA_HAVE_NATIVE) && \
!defined(WOLFSSL_MLDSA_NO_MAKE_KEY) && \
!defined(WOLFSSL_MLDSA_NO_SIGN) && !defined(WOLFSSL_MLDSA_NO_VERIFY)
WC_RNG rng;

XMEMSET(&rng, 0, sizeof(WC_RNG));
ExpectIntEQ(wc_InitRng(&rng), 0);
#ifndef WOLFSSL_NO_ML_DSA_44
ExpectIntEQ(mldsa_prehash_strength_level(WC_ML_DSA_44, 128, &rng),
TEST_SUCCESS);
#endif
#ifndef WOLFSSL_NO_ML_DSA_65
ExpectIntEQ(mldsa_prehash_strength_level(WC_ML_DSA_65, 192, &rng),
TEST_SUCCESS);
#endif
#ifndef WOLFSSL_NO_ML_DSA_87
ExpectIntEQ(mldsa_prehash_strength_level(WC_ML_DSA_87, 256, &rng),
TEST_SUCCESS);
#endif
DoExpectIntEQ(wc_FreeRng(&rng), 0);
#endif
return EXPECT_RESULT();
}

int test_mldsa_check_key(void)
{
EXPECT_DECLS;
Expand Down
2 changes: 2 additions & 0 deletions tests/api/test_mldsa.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ int test_mldsa_make_key(void);
int test_mldsa_sign(void);
int test_mldsa_verify(void);
int test_mldsa_sign_vfy(void);
int test_mldsa_prehash_strength(void);
int test_mldsa_check_key(void);
int test_mldsa_public_der_decode(void);
int test_mldsa_der(void);
Expand Down Expand Up @@ -79,6 +80,7 @@ int test_wc_MlDsaKey_SetPrecompA(void);
TEST_DECL_GROUP("mldsa", test_mldsa_sign), \
TEST_DECL_GROUP("mldsa", test_mldsa_verify), \
TEST_DECL_GROUP("mldsa", test_mldsa_sign_vfy), \
TEST_DECL_GROUP("mldsa", test_mldsa_prehash_strength), \
TEST_DECL_GROUP("mldsa", test_mldsa_check_key), \
TEST_DECL_GROUP("mldsa", test_mldsa_public_der_decode), \
TEST_DECL_GROUP("mldsa", test_mldsa_der), \
Expand Down
Loading
Loading