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
It's part of the ASN feature but since it's also used by the RSA
binding this function must also be part of the library when only
the RSA feature is selected.
The definitions for the following functions are not always available
when wolfSSL is configured to only contain a minimum of functionality:
- wc_GetPkcs8TraditionalOffset (only with ASN, which is required for
RSA)
- wc_PemToDer (only when KEYGEN is enabled)
- wc_DerToPemEx (only when KEYGEN is enabled)
This change allows for building the Python wrapper when ASN and RSA
are both disabled.
`defines` was a string instead of a list of strings. This made it
impossible to build a wrapper with a configuration in which AES-CBC
is disabled, because `'#define NO_AES' in defines` matched also
when the header contains `#define NO_AES_CBC`. With `defines` being
a list the code actually does what you think it does.