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
7 changes: 7 additions & 0 deletions doc/dox_comments/header_files/asn_public.h
Original file line number Diff line number Diff line change
Expand Up @@ -2267,6 +2267,13 @@ int wc_DhPrivKeyToDer(DhKey* key, byte* out, word32* outSz);
input, parses the private key, and uses it to generate an ecc_key object,
which it stores in key.

For private-only encoding, public key is derived best-effort; failure
doesn't fail decode. Under ECC_TIMING_RESISTANT the scalar multiply is
blinded with the key's rng when one was set via wc_ecc_set_rng(), and
otherwise with a temporary rng created for the derivation. Define
WOLFSSL_NO_ECC_DERIVE_PUB_ON_DECODE to disable this best-effort
derivation entirely.

\return 0 On successfully decoding the private key and storing the result
in the ecc_key struct
\return ASN_PARSE_E: Returned if there is an error parsing the der file
Expand Down
48 changes: 48 additions & 0 deletions doc/dox_comments/header_files/wc_mldsa.h
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,29 @@ int wc_MlDsaKey_MakeKey(wc_MlDsaKey* key, WC_RNG* rng);
*/
int wc_MlDsaKey_MakeKeyFromSeed(wc_MlDsaKey* key, const byte* seed);

/*!

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 [Low] Doxygen for the new/changed ML-DSA APIs is inconsistent with the implemented return codes
🔧 NIT style

Two small doc mismatches. (1) The new wc_MlDsaKey_MakePublicKey block lists 0 / BAD_FUNC_ARG / MEMORY_E / Other negative but omits PUBLIC_KEY_E, which is the function's most interesting documented failure (t0 or tr mismatch, wc_mldsa.c:11634 and :11650) — and every export function's block in the same file does list it. (2) The wc_MlDsaKey_PrivateKeyDecode addition says the public key is "derived best-effort on demand by export functions", but the export functions now hard-fail with PUBLIC_KEY_E/MEMORY_E when derivation fails (as those same doc blocks state); "best-effort" describes the ECC path, not this one, and reads as a contradiction.

Suggestion:

Suggested change
/*!
\return 0 on success or already set.
\return BAD_FUNC_ARG if invalid args, or the public key is not yet set
and key has a devId set.
\return MEMORY_E on allocation failure.
\return PUBLIC_KEY_E if the derived public key does not match the t0
and tr values stored in the private key.
\return Other negative on error.

Recommendation: Add PUBLIC_KEY_E to the MakePublicKey return list, and reword the PrivateKeyDecode note to "public key left unset; derived on demand by the export functions, which fail if derivation fails."

\ingroup ML_DSA

\brief Derives public key for a wc_MlDsaKey with private key set.
No-op if already set.

Derives in software, so it is not supported on keys with a devId set,
unless the public key is already set - in that case this is a no-op
regardless of devId.

\return 0 on success or already set.
\return BAD_FUNC_ARG if invalid args, or the public key is not yet set
and key has a devId set.
\return MEMORY_E on allocation failure.
\return Other negative on error.

\param [in,out] key Pointer to wc_MlDsaKey.

\sa wc_MlDsaKey_ImportPrivRaw
\sa wc_MlDsaKey_MakeKey
*/
int wc_MlDsaKey_MakePublicKey(wc_MlDsaKey* key);

/*!
\ingroup ML_DSA

Expand Down Expand Up @@ -453,6 +476,7 @@ int wc_MlDsaKey_SignWithSeed(wc_MlDsaKey* key, byte* sig, word32* sigLen,
\return 0 if verification completed (check res for the result).
\return BAD_FUNC_ARG if any required pointer is NULL or ctxLen is
invalid.
\return PUBLIC_KEY_E when the public key is not set.

\param [in,out] key Pointer to a wc_MlDsaKey with the public key.
\param [in] sig Signature bytes to verify.
Expand Down Expand Up @@ -480,6 +504,7 @@ 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.
\return PUBLIC_KEY_E when the public key is not set.

\param [in,out] key Pointer to a wc_MlDsaKey with the public key.
\param [in] sig Signature bytes to verify.
Expand Down Expand Up @@ -508,6 +533,7 @@ int wc_MlDsaKey_VerifyCtxHash(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 or muLen is
not 64.
\return PUBLIC_KEY_E when the public key is not set.

\param [in,out] key Pointer to a wc_MlDsaKey with the public key.
\param [in] sig Signature bytes to verify.
Expand Down Expand Up @@ -756,9 +782,15 @@ int wc_MlDsaKey_ImportKey(wc_MlDsaKey* key, const byte* priv, word32 privSz,
\brief Exports the raw ML-DSA public key. On entry *outLen is the
size of out; on success it is updated to the bytes written.

If only the private key is set, the public key is derived and cached
in key. Don't share key across threads during this call.

\return 0 on success.
\return BAD_FUNC_ARG if any required pointer is NULL.
\return BUFFER_E if *outLen is smaller than the public key size.
\return MEMORY_E if deriving the public key fails to allocate.
\return PUBLIC_KEY_E if deriving the public key fails to verify
against the private key.

\param [in] key Pointer to a wc_MlDsaKey with a public key.
\param [out] out Buffer that receives the public key.
Expand Down Expand Up @@ -818,6 +850,9 @@ int wc_MlDsaKey_ExportKey(wc_MlDsaKey* key, byte* priv, word32 *privSz,

Only available when WOLFSSL_MLDSA_NO_ASN1 is not defined.

For private-only encoding, public key left unset; derived best-effort
on demand by export functions.

\return 0 on success.
\return BAD_FUNC_ARG if any required pointer is NULL.
\return ASN_PARSE_E on malformed encoding.
Expand All @@ -830,6 +865,7 @@ int wc_MlDsaKey_ExportKey(wc_MlDsaKey* key, byte* priv, word32 *privSz,

\sa wc_MlDsaKey_PrivateKeyToDer
\sa wc_MlDsaKey_PublicKeyDecode
\sa wc_MlDsaKey_MakePublicKey
*/
int wc_MlDsaKey_PrivateKeyDecode(wc_MlDsaKey* key, const byte* input,
word32 inSz, word32* inOutIdx);
Expand Down Expand Up @@ -867,11 +903,17 @@ int wc_MlDsaKey_PublicKeyDecode(wc_MlDsaKey* key, const byte* input,

Pass NULL as output to query the required buffer size.

If only the private key is set, the public key is derived and cached
in key. Don't share key across threads during this call.

\return Size of the encoded DER in bytes on success.
\return BAD_FUNC_ARG if key is NULL or no parameter set is
selected.
\return BUFFER_E if output is non-NULL and inLen is smaller than
the required size.
\return MEMORY_E if deriving the public key fails to allocate.
\return PUBLIC_KEY_E if deriving the public key fails to verify
against the private key.

\param [in] key Pointer to a wc_MlDsaKey with a public key.
\param [out] output Buffer that receives the DER encoding, or
Expand All @@ -893,11 +935,17 @@ int wc_MlDsaKey_PublicKeyToDer(wc_MlDsaKey* key, byte* output,
PKCS#8 OneAsymmetricKey structure. Pass NULL as output to query
the required buffer size.

If only the private key is set, the public key is derived and cached
in key. Don't share key across threads during this call.

\return Size of the encoded DER in bytes on success.
\return BAD_FUNC_ARG if key is NULL or no parameter set is
selected.
\return MISSING_KEY if the private key has not been set.
\return BUFFER_E if output is non-NULL and inLen is too small.
\return MEMORY_E if deriving the public key fails to allocate.
\return PUBLIC_KEY_E if deriving the public key fails to verify
against the private key.

\param [in] key Pointer to a wc_MlDsaKey with the private key.
\param [out] output Buffer that receives the DER encoding, or
Expand Down
245 changes: 245 additions & 0 deletions tests/api/test_asn.c
Original file line number Diff line number Diff line change
Expand Up @@ -2781,3 +2781,248 @@ int test_wc_AsnFeatureCoverage(void)
#endif /* !NO_ASN && HAVE_ECC && USE_CERT_BUFFERS_256 && !HAVE_FIPS */
return EXPECT_RESULT();
}

#if defined(USE_WOLFSSL_MEMORY) && !defined(WOLFSSL_NO_MALLOC) && \

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 [Medium] test_wc_EccPrivateKeyDecode_derive_pub guard omits !defined(WC_NO_RNG) and asserts behaviour the code deliberately skips there
💡 SUGGEST test

Two independent failures in a WC_NO_RNG build. (a) wc_InitRng is a macro expanding to NOT_COMPILED_IN under WC_NO_RNG (wolfssl/wolfcrypt/random.h:463), so ExpectIntEQ(wc_InitRng(&rng), 0) fails immediately and short-circuits the whole test to TEST_FAIL rather than skipping it. (b) EccDerivePubBestEffort() deliberately returns without deriving under ECC_TIMING_RESISTANT && WC_NO_RNG (asn.c:33214-33218, the #else arm that emits "no RNG for blinding" and returns), so ExpectIntEQ(privOnlyKey.type, ECC_PRIVATEKEY) asserts the opposite of the implemented behaviour. Every other RNG-using test in tests/api/test_ecc.c carries !defined(WC_NO_RNG), including test_wc_EccPrivateKeyToDer (test_ecc.c:2529), which exercises the same API. Not currently reachable in CI — the only --disable-rng job is rust-wrapper.yml:68, which is --enable-cryptonly and does not build tests/unit.test — but it is a supported downstream config.

Suggestion:

Suggested change
#if defined(USE_WOLFSSL_MEMORY) && !defined(WOLFSSL_NO_MALLOC) && \
#if !defined(NO_ASN) && defined(HAVE_ECC) && !defined(NO_ECC_MAKE_PUB) && \
!defined(WC_NO_RNG) && \
!defined(WOLFSSL_NO_ECC_DERIVE_PUB_ON_DECODE) && \
defined(HAVE_ECC_KEY_EXPORT) && \

Recommendation: Add !defined(WC_NO_RNG) to both the function guard (test_asn.c:2856-2864) and the OOM-helper guard (test_asn.c:2785-2795).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 [Low] ECC OOM guard omits WOLFSSL_MEM_FAIL_COUNT / WOLFSSL_FORCE_MALLOC_FAIL_TEST exclusions the ML-DSA harness has
💡 SUGGEST test

The ML-DSA OOM harness added in the same diff excludes both macros (tests/api/test_mldsa.c:8154-8161 and :8295-8301) because each injects its own allocation failures inside wolfSSL_Mallocwc_MemFailCount_AllocMem() at wolfcrypt/src/memory.c:337-342 runs before the user hook, and the gMemFailCount countdown at memory.c:395-411 runs after it — making both the counting pass and the injection pass non-deterministic. The ECC harness omits them, so in a WOLFSSL_FORCE_MALLOC_FAIL_TEST build the counting decode at test_asn.c:2969 can fail spuriously and the whole test reports failure.

Also raised by the bugs scan (tests/api/test_asn.c:2785-2790, 2943-2944):

The new ECC allocation-failure loop installs its own allocators and calibrates a totalAllocCount by counting the allocations one decode makes, then fails each in turn. Its guard is only:

#if defined(USE_WOLFSSL_MEMORY) && !defined(WOLFSSL_NO_MALLOC) && \
    !defined(WOLFSSL_STATIC_MEMORY)

The parallel ML-DSA test added by the same PR (tests/api/test_mldsa.c) additionally excludes WOLFSSL_MEM_FAIL_COUNT and WOLFSSL_FORCE_MALLOC_FAIL_TEST; the ECC one does not. Both of those macros make wolfSSL_Malloc() fail independently of the test's injector:

  • WOLFSSL_MEM_FAIL_COUNT (wolfcrypt/src/memory.c:337-342) returns NULL from wc_MemFailCount_AllocMem() before the registered malloc callback runs, so those allocations are invisible to ecc_oom_count. totalAllocCount is then under-counted, and a decode can fail from an allocation the test never injected.
  • WOLFSSL_FORCE_MALLOC_FAIL_TEST (memory.c:395-405) frees and nulls a successful allocation once --gMemFailCount hits zero, again after the callback has already been counted.

Either one makes the calibration assertion ExpectIntEQ(wc_EccPrivateKeyDecode(privOnlyDer, &idx, &privOnlyKey, privOnlyDerSz), 0) able to fail, and makes totalAllocCount non-reproducible between the two passes. wolfSSL runs a WOLFSSL_MEM_FAIL_COUNT configuration in CI, so this is a reachable flake rather than a theoretical one.

Suggestion:

Suggested change
#if defined(USE_WOLFSSL_MEMORY) && !defined(WOLFSSL_NO_MALLOC) && \
#if defined(USE_WOLFSSL_MEMORY) && !defined(WOLFSSL_NO_MALLOC) && \
!defined(WOLFSSL_STATIC_MEMORY) && !defined(WOLFSSL_MEM_FAIL_COUNT) && \
!defined(WOLFSSL_FORCE_MALLOC_FAIL_TEST) && !defined(NO_ASN) && \

Recommendation: Add !defined(WOLFSSL_MEM_FAIL_COUNT) && !defined(WOLFSSL_FORCE_MALLOC_FAIL_TEST) to both the helper guard (2785-2795) and the inner allocator block guard (2943-2944), matching the ML-DSA harness.

!defined(WOLFSSL_STATIC_MEMORY) && !defined(NO_ASN) && \
defined(HAVE_ECC) && !defined(NO_ECC_MAKE_PUB) && \
!defined(WOLFSSL_NO_ECC_DERIVE_PUB_ON_DECODE) && \
defined(HAVE_ECC_KEY_EXPORT) && \
defined(USE_CERT_BUFFERS_256) && !defined(HAVE_FIPS) && \
!defined(HAVE_SELFTEST) && !defined(WOLF_CRYPTO_CB_ONLY_ECC) && \
!defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_ATECC608A) && \
!defined(WOLFSSL_MICROCHIP_TA100) && !defined(WOLFSSL_CRYPTOCELL) && \
!defined(WOLFSSL_SILABS_SE_ACCEL) && !defined(WOLFSSL_KCAPI_ECC) && \
!defined(WOLFSSL_QNX_CAAM) && !defined(WOLFSSL_IMXRT1170_CAAM)
/* Fail Nth alloc to target public key derive. */
static int ecc_oom_failed = 0;
static int ecc_oom_inject = 0;
static int ecc_oom_count = 0;
static int ecc_oom_fail_at = 0;

/* Custom malloc for testing OOM. */
#ifdef WOLFSSL_DEBUG_MEMORY
static void* ecc_oom_malloc_cb(size_t size, const char* func,
unsigned int line)
{
(void)func;
(void)line;
#else
static void* ecc_oom_malloc_cb(size_t size)
{
#endif
if (ecc_oom_inject) {
ecc_oom_count++;
if (!ecc_oom_failed &&
(ecc_oom_fail_at != 0) && (ecc_oom_count == ecc_oom_fail_at)) {
ecc_oom_failed = 1;
return NULL;
}
}
return malloc(size);
}

/* Custom free for testing OOM. */
#ifdef WOLFSSL_DEBUG_MEMORY
static void ecc_oom_free_cb(void* ptr, const char* func, unsigned int line)
{
(void)func;
(void)line;
#else
static void ecc_oom_free_cb(void* ptr)
{
#endif
free(ptr);
}

/* Custom realloc for testing OOM. */
#ifdef WOLFSSL_DEBUG_MEMORY
static void* ecc_oom_realloc_cb(void* ptr, size_t size, const char* func,
unsigned int line)
{
(void)func;
(void)line;
#else
static void* ecc_oom_realloc_cb(void* ptr, size_t size)
{
#endif
return realloc(ptr, size);
}
#endif /* USE_WOLFSSL_MEMORY && ... */

/* Decode should best-effort derive omitted SEC1 public point. */
int test_wc_EccPrivateKeyDecode_derive_pub(void)
{
EXPECT_DECLS;
#if !defined(NO_ASN) && defined(HAVE_ECC) && !defined(NO_ECC_MAKE_PUB) && \
Comment thread
Frauschi marked this conversation as resolved.
!defined(WOLFSSL_NO_ECC_DERIVE_PUB_ON_DECODE) && \
defined(HAVE_ECC_KEY_EXPORT) && \
defined(USE_CERT_BUFFERS_256) && !defined(HAVE_FIPS) && \
!defined(HAVE_SELFTEST) && !defined(WOLF_CRYPTO_CB_ONLY_ECC) && \
!defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_ATECC608A) && \
!defined(WOLFSSL_MICROCHIP_TA100) && !defined(WOLFSSL_CRYPTOCELL) && \
!defined(WOLFSSL_SILABS_SE_ACCEL) && !defined(WOLFSSL_KCAPI_ECC) && \
!defined(WOLFSSL_QNX_CAAM) && !defined(WOLFSSL_IMXRT1170_CAAM)
ecc_key fullKey;
ecc_key privOnlyKey;
WC_RNG rng;
word32 idx;
byte privOnlyDer[256];
int privOnlyDerSz = 0;
byte fullPub[256];
word32 fullPubSz = sizeof(fullPub);
byte derivedPub[256];
word32 derivedPubSz = sizeof(derivedPub);

XMEMSET(&fullKey, 0, sizeof(fullKey));
XMEMSET(&privOnlyKey, 0, sizeof(privOnlyKey));
/* wc_FreeRng() below runs unconditionally, so rng must be safe to free
* even if wc_InitRng() fails. */
XMEMSET(&rng, 0, sizeof(rng));

ExpectIntEQ(wc_InitRng(&rng), 0);

ExpectIntEQ(wc_ecc_init(&fullKey), 0);
idx = 0;
ExpectIntEQ(wc_EccPrivateKeyDecode(ecc_clikey_der_256, &idx, &fullKey,
sizeof_ecc_clikey_der_256), 0);
ExpectIntEQ(fullKey.type, ECC_PRIVATEKEY);
PRIVATE_KEY_UNLOCK();
ExpectIntEQ(wc_ecc_export_x963(&fullKey, fullPub, &fullPubSz), 0);
PRIVATE_KEY_LOCK();

/* Re-encode as private-key-only SEC1 DER. */
ExpectIntGT(privOnlyDerSz = wc_EccPrivateKeyToDer(&fullKey, privOnlyDer,
sizeof(privOnlyDer)), 0);

/* No RNG set: derivation still runs, blinding with a temporary RNG when
* ECC_TIMING_RESISTANT is on. */
ExpectIntEQ(wc_ecc_init(&privOnlyKey), 0);
idx = 0;
ExpectIntEQ(wc_EccPrivateKeyDecode(privOnlyDer, &idx, &privOnlyKey,
(word32)privOnlyDerSz), 0);
ExpectIntEQ(privOnlyKey.type, ECC_PRIVATEKEY);
PRIVATE_KEY_UNLOCK();
ExpectIntEQ(wc_ecc_export_x963(&privOnlyKey, derivedPub, &derivedPubSz),
0);
PRIVATE_KEY_LOCK();
ExpectIntEQ(derivedPubSz, fullPubSz);
ExpectBufEQ(derivedPub, fullPub, fullPubSz);
wc_ecc_free(&privOnlyKey);

/* Setting an RNG blinds the scalar mult; same derived point. */
derivedPubSz = sizeof(derivedPub);
ExpectIntEQ(wc_ecc_init(&privOnlyKey), 0);
ExpectIntEQ(wc_ecc_set_rng(&privOnlyKey, &rng), 0);
idx = 0;
ExpectIntEQ(wc_EccPrivateKeyDecode(privOnlyDer, &idx, &privOnlyKey,
(word32)privOnlyDerSz), 0);

/* Public point derived, key fully usable. */
ExpectIntEQ(privOnlyKey.type, ECC_PRIVATEKEY);
PRIVATE_KEY_UNLOCK();
ExpectIntEQ(wc_ecc_export_x963(&privOnlyKey, derivedPub, &derivedPubSz),
0);
PRIVATE_KEY_LOCK();
ExpectIntEQ(derivedPubSz, fullPubSz);
ExpectBufEQ(derivedPub, fullPub, fullPubSz);

wc_ecc_free(&privOnlyKey);
wc_ecc_free(&fullKey);

#if defined(PLUTON_CRYPTO_ECC) || defined(WOLF_CRYPTO_CB)
/* devId key left ECC_PRIVATEKEY_ONLY: device derives it. */
ExpectIntEQ(wc_ecc_init_ex(&privOnlyKey, NULL, 1), 0);
ExpectIntEQ(wc_ecc_set_rng(&privOnlyKey, &rng), 0);
idx = 0;
ExpectIntEQ(wc_EccPrivateKeyDecode(privOnlyDer, &idx, &privOnlyKey,
(word32)privOnlyDerSz), 0);
ExpectIntEQ(privOnlyKey.type, ECC_PRIVATEKEY_ONLY);
wc_ecc_free(&privOnlyKey);
#endif

#if defined(USE_WOLFSSL_MEMORY) && !defined(WOLFSSL_NO_MALLOC) && \
!defined(WOLFSSL_STATIC_MEMORY)
{
wolfSSL_Malloc_cb prevMalloc = NULL;
wolfSSL_Free_cb prevFree = NULL;
wolfSSL_Realloc_cb prevRealloc = NULL;
int allocatorsSet = 0;
int totalAllocCount = 0;
int i;

ExpectIntEQ(wolfSSL_GetAllocators(&prevMalloc, &prevFree, &prevRealloc),
0);
ExpectIntEQ(wolfSSL_SetAllocators(ecc_oom_malloc_cb, ecc_oom_free_cb,
ecc_oom_realloc_cb), 0);
if (EXPECT_SUCCESS()) {
allocatorsSet = 1;
}

/* Count the allocations one decode-with-derive makes. Injection is
* armed only around the decode so wc_ecc_init() is never starved. */
ecc_oom_count = 0;
ecc_oom_fail_at = 0;
ecc_oom_failed = 0;
ExpectIntEQ(wc_ecc_init(&privOnlyKey), 0);
idx = 0;
ecc_oom_inject = 1;
ExpectIntEQ(wc_EccPrivateKeyDecode(privOnlyDer, &idx, &privOnlyKey,
(word32)privOnlyDerSz), 0);
ecc_oom_inject = 0;
totalAllocCount = ecc_oom_count;
wc_ecc_free(&privOnlyKey);

/* Fail each allocation in turn. Whatever fails, decode must never
* report a derived public key it does not have: the key comes back
* either fully derived and correct, or still ECC_PRIVATEKEY_ONLY. */
for (i = 1; EXPECT_SUCCESS() && (i <= totalAllocCount); i++) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 [Low] ECC OOM loop never asserts the injected failure actually fired
💡 SUGGEST test

ecc_oom_failed is reset at the top of each iteration and set by the malloc hook, but never read afterwards. If a failure pass makes fewer allocations than the counting pass (plausible — the counting pass ran with ecc_oom_fail_at = 0, and any early-out changes the allocation profile), nothing is injected and the iteration passes vacuously while looking like it exercised OOM. The ML-DSA harness added in the same PR does check this — ExpectIntEQ(mldsa_oom_failed, 1) at tests/api/test_mldsa.c:8284 — so the two harnesses in one diff are inconsistent.

Suggestion:

Suggested change
for (i = 1; EXPECT_SUCCESS() && (i <= totalAllocCount); i++) {
decodeRet = wc_EccPrivateKeyDecode(privOnlyDer, &idx, &privOnlyKey,
(word32)privOnlyDerSz);
ecc_oom_inject = 0;
ExpectIntEQ(ecc_oom_failed, 1);

Recommendation: Assert ecc_oom_failed == 1 after each injection pass, matching mldsa_oom_derive_fail_level().

int decodeRet;

ecc_oom_count = 0;
ecc_oom_fail_at = i;
ecc_oom_failed = 0;
derivedPubSz = sizeof(derivedPub);

ExpectIntEQ(wc_ecc_init(&privOnlyKey), 0);
idx = 0;
ecc_oom_inject = 1;
decodeRet = wc_EccPrivateKeyDecode(privOnlyDer, &idx, &privOnlyKey,
(word32)privOnlyDerSz);
ecc_oom_inject = 0;

/* A failure inside the decode itself is fine; only the
* best-effort derivation is required to be non-fatal. */
if (decodeRet == 0) {
ExpectIntNE(privOnlyKey.type, ECC_PUBLICKEY);
if (privOnlyKey.type == ECC_PRIVATEKEY) {
PRIVATE_KEY_UNLOCK();
ExpectIntEQ(wc_ecc_export_x963(&privOnlyKey, derivedPub,
&derivedPubSz), 0);
PRIVATE_KEY_LOCK();
ExpectIntEQ(derivedPubSz, fullPubSz);
ExpectBufEQ(derivedPub, fullPub, fullPubSz);
}
else {
ExpectIntEQ(privOnlyKey.type, ECC_PRIVATEKEY_ONLY);
}
}

wc_ecc_free(&privOnlyKey);
}

ecc_oom_inject = 0;
ecc_oom_fail_at = 0;

if (allocatorsSet) {
(void)wolfSSL_SetAllocators(prevMalloc, prevFree, prevRealloc);
}
}
#endif /* USE_WOLFSSL_MEMORY */

wc_FreeRng(&rng);
#endif /* !NO_ASN && HAVE_ECC && !NO_ECC_MAKE_PUB &&
* !WOLFSSL_NO_ECC_DERIVE_PUB_ON_DECODE && HAVE_ECC_KEY_EXPORT &&
* USE_CERT_BUFFERS_256 && !HAVE_FIPS && !HAVE_SELFTEST &&
* !WOLF_CRYPTO_CB_ONLY_ECC */
return EXPECT_RESULT();
}
Loading
Loading