The CFFI cdef declared wc_dilithium_verify_ctx_msg with word32 ctxLen while the
sign variants use byte ctxLen. wolfSSL's real API (wc_MlDsaKey_VerifyCtx in
wolfcrypt/wc_mldsa.h, which the wc_dilithium_verify_ctx_msg macro forwards to)
takes byte ctxLen, matching FIPS 204's 255-byte context cap. The mismatched
cdef made CFFI marshal a 4-byte word32 into a 1-byte slot, silently truncating
any ctxLen > 255 to its low byte.
Declare ctxLen as byte to match the sign cdef and the underlying API.
Also detect WOLFSSL_DILITHIUM_FIPS204_DRAFT as implying no-ctx support,
mirroring the logic in dilithium.h. Add ML_DSA_NO_CTX to the default
features dict for consistency with peer flags.
In the newer wolfSSL signing and verifying without context is
not available unless it is explicitly enabled.
This change modifies the Python binding and test suite to
accommodate this.
F-3340: AesGcmStream.final decrypt path passed len(authTag) straight to
wc_AesGcmDecryptFinal, letting a caller truncate the verification window
(forgery probability ~2^-32 instead of 2^-128 for a 4-byte tag against a
16-byte configuration). Reject len(authTag) != self._tag_bytes and pass
self._tag_bytes to wolfSSL, mirroring ChaCha20Poly1305.decrypt. Added
test_decrypt_rejects_wrong_tag_length. Also fixed test_encrypt_short_tag
which was relying on the bug (decrypt side defaulted to tag_bytes=16
against a 12-byte tag).
F-3089: Declare label as const byte* in the wc_RsaPublicEncrypt_ex and
wc_RsaPrivateDecrypt_ex cdefs so CFFI can accept Python bytes without
exposing a writable pointer into immutable memory. wolfSSL does not
modify label.
F-3090: Declare nonce as const byte* in the wc_InitRngNonce and
wc_InitRngNonce_ex cdefs for the same reason.
F-1983, F-1984: Add minimum + upper bounds to requirements/{prod,test,
docs}.txt so a hijacked release of cffi, tox, pytest, types-cffi,
Sphinx, or sphinx_rtd_theme does not get pulled silently on the next
pip install. setup.txt resolves transitively via prod.txt.
wc_ecc_import_unsigned takes no length parameters for qx/qy/d: it
reads exactly curve_size bytes from each pointer based on curve_id,
via mp_read_unsigned_bin in wc_ecc_import_raw_private. The Python
decode_key_raw wrappers handed the user-supplied buffers straight
through without any length check, so a shorter buffer caused the C
library to read past the end of the Python buffer (OOB read of
adjacent memory, potentially leaking it into the imported key or
segfaulting). A longer buffer silently dropped the extra bytes.
Add wc_ecc_get_curve_size_from_id to the CFFI cdef, then in both
decode_key_raw methods t2b the inputs, look up the expected curve
size, and raise ValueError if any of qx/qy/d does not match. Reject
unknown curve_id values with a clear message rather than falling
through to wolfSSL with a bogus size.
Add test_ecc_decode_key_raw_rejects_wrong_length covering short qx,
long qy, short d, unknown curve_id, and the happy path on both
EccPublic and EccPrivate.
F-3088
scripts/build_ffi.py declared qx, qy, and d as `byte*` while the
wolfSSL header (ecc.h) declares all three as `const byte*`. wolfSSL is
const-correct here and does not mutate the inputs, so there is no
observable bug today, but the non-const cdef let CFFI hand a writable
pointer into Python bytes storage on EccPublic.decode_key_raw and
EccPrivate.decode_key_raw calls. Update the cdef to match the header.
F-3087
scripts/build_ffi.py declared wc_ed448_sign_msg and wc_ed448_verify_msg
with two cdef discrepancies vs the wolfSSL header (ed448.h):
- ctx was typed `byte*` instead of `const byte*`. CFFI was therefore
happy to forward a writable pointer into Python bytes storage.
The wolfSSL functions are const-correct and do not mutate ctx, so
this had no runtime impact, but it widened the surface CFFI was
willing to permit.
- ctx_len was typed `word32` instead of `byte`. RFC 8032 caps Ed448
context at 255 bytes, and wolfSSL's prototype reflects that with a
1-byte parameter. The mismatch happens to work on x86_64 SysV
because the low byte is what the callee reads, but it is still a
real ABI discrepancy and would not be guaranteed on other
platforms or calling conventions.
Update the cdef to const byte* / byte to match the header on both
functions. Add a guard in Ed448Public.verify and Ed448Private.sign so
callers passing a ctx longer than 255 bytes get a clear ValueError
rather than relying on CFFI's narrowing behavior.
ML-DSA's wc_dilithium_sign_ctx_msg / wc_dilithium_verify_ctx_msg cdefs
were also reviewed and already match the wolfSSL header.
F-3086
A bare except catches BaseException which includes KeyboardInterrupt,
SystemExit, Exception, and others.
Catching BaseException can make it hard to interrupt the program (e.g., with
Ctrl-C) and can disguise other problems.
It was already used, but not compiled in.
A unit test is added.
As wcGetErrorString() always returns a string the error handling
in class _Hmac has been removed.
Fixing these minor issues helps in adding more checks to fix-up
the code without being bothered by these issues.
Two minor issues are fixed:
- Mark unused variables with a leading underscore
- Use idiomatic boolean expressions