Added support for encoding and decoding keys in ASN.1.
Added support for X.509 certificates and CSRs.
Generated certificates and CSRs. Not fo FrodoKEM-640 as is not in the specs.
Under DEBUG_WOLFSSL the hash->type != type check in wc_HashUpdate,
wc_HashFinal and wc_HashFree fired for an uninitialized hash
(hash->type == WC_HASH_TYPE_NONE), returning BAD_FUNC_ARG where a non-debug
build returns HASH_TYPE_E from the type switch, so the returned error code
depended on whether DEBUG_WOLFSSL was defined. Only apply the mismatch check
to initialized hashes; the genuine init-then-wrong-type misuse check is
preserved.
```
==485951== Uninitialised value was created by a stack allocation
==485951== at 0x207D47: des3_key_wrap_test (test.c:12773)
```
and
```
==485951== Uninitialised value was created by a stack allocation
==485951== at 0x3A075E: test_wc_AesGcmArgMcdc (test_aes.c:8968)
```
The RISC-V ASM build provides its own AES-GCM implementation
(wolfcrypt/src/port/riscv/riscv-64-aes.c) rather than AES_GCM_decrypt_C, so
it does not clear the output buffer on authentication failure. Exclude it
from the zero-check, matching the other non-C decrypt paths. Fixes the
riscv64 multi-arch testwolfcrypt failure.
Skoll review of the auth-fail zero-check test in aesgcm_test:
- The guard listed WOLFSSL_ARMASM_NO_HW_CRYPTO and __aarch64__, which are
defined on default x86-64 builds, so the zero-check block was compiled out
and the assertion never actually ran there. They are subsumed by
WOLFSSL_ARMASM (the condition under which AES_GCM_decrypt_C is not the
decrypt path), so use that instead and the check runs on the C path.
- Exclude WC_AES_GCM_DEC_AUTH_EARLY (out is not written on an early-auth
failure) and WOLFSSL_ASYNC_CRYPT (a real async device may offload the
decrypt and not clear the output).
Verified: default make check passes with the zero-check now executing;
testwolfcrypt AES-GCM passes with --enable-aesni and with
-DWC_AES_GCM_DEC_AUTH_EARLY.
Review follow-ups for the constant-time AES-GCM decrypt output clear:
- Guard the output-masking pass with #ifndef WC_AES_GCM_DEC_AUTH_EARLY. In
that configuration the tag is verified before decryption and a mismatch
returns before any output is written, so the masking pass is a guaranteed
no-op; skipping it avoids a wasted O(sz) pass.
- Add a test in aesgcm_test: decrypt with a corrupted tag into a pre-filled
buffer and assert wc_AesGcmDecrypt returns AES_GCM_AUTH_E and, on the
software C path, that the output buffer is cleared to zero. The AES-NI/asm
decrypt paths and the FIPS module do not clear the output on auth failure,
so the zero check forces the C path (use_aesni = 0) and is limited to it
(and skipped under HAVE_FIPS). The AES_GCM_AUTH_E comparison uses
WC_NO_ERR_TRACE().
Verified (gcc 15.2): make check passes on the default (C path) build;
testwolfcrypt AES-GCM passes with --enable-aesni and with
-DWC_AES_GCM_DEC_AUTH_EARLY; ct-valgrind aes_gcm reports 0 errors.
AES_GCM_decrypt_C cleared the output on a tag mismatch with
'if (ret != 0) ForceZero(out, sz)'. That is a conditional branch on the
secret-dependent authentication result, which is not constant time and is
flagged by the ct-valgrind constant-time test (Conditional jump depends on
uninitialised value in AES_GCM_decrypt_C).
Mask the output with 'res' (already computed as all-ones on tag mismatch,
zero on match) instead of branching, matching the constant-time idiom used
for the tag comparison itself. C path only; the AES-NI/ASM paths are
unaffected.
linuxkm/lkcapi_aes_glue.c: zero the ephemeral ivOut in AesGcmCrypt_1().
wolfcrypt/src/port/kcapi/kcapi_aes.c: tighten the test on the return value from kcapi_aead_decrypt().
wc_ShaUpdate, wc_Sha3Update, wc_Shake128_Update and wc_Shake256_Update
guarded inputs as:
if (obj == NULL || (data == NULL && len > 0)) return BAD_FUNC_ARG;
if (data == NULL && len == 0) return 0;
The first guard rejected (data==NULL, len>0) before the second decision,
so that decision's len==0 condition could only ever be observed true --
its MC/DC independence pair was structurally unreachable.
Reorder to the same idiom sha256.c/sha512.c already use:
if (obj == NULL) return BAD_FUNC_ARG;
if (data == NULL && len == 0) return 0; /* (NULL,len>0) now reaches: len==0 false */
if (data == NULL) return BAD_FUNC_ARG;
Behavior is identical for every input; the existing DIGEST_UPDATE_TEST
cases wc_*Update(&dgst, NULL, 1) and (&dgst, NULL, 0) now exercise both
sides of the decision. Closes the four guard-ordering MC/DC residuals in
the sha campaign module (sha.c and sha3.c).