Merge pull request #119 from LinuxJedi/f-fixes2

Address Fenrir findings
pull/112/head
David Garske 2026-05-12 09:29:01 -07:00 committed by GitHub
commit 8b3acfc12a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 49 additions and 15 deletions

View File

@ -23,7 +23,7 @@ classifiers = [
]
dynamic = ["version"]
dependencies = [
"cffi>=1.0.0",
"cffi>=1.0.0,<2",
]
[project.urls]

View File

@ -1,3 +1,3 @@
-r prod.txt
Sphinx
sphinx_rtd_theme
Sphinx>=7,<9
sphinx_rtd_theme>=2,<4

View File

@ -1 +1 @@
cffi
cffi>=1.17,<2

View File

@ -1,4 +1,4 @@
-r prod.txt
tox
pytest
types-cffi
tox>=4,<5
pytest>=8,<9
types-cffi>=1.16,<2

View File

@ -545,8 +545,8 @@ def build_ffi(local_wolfssl, features):
typedef struct { ...; } OS_Seed;
int wc_InitRng(WC_RNG*);
int wc_InitRngNonce(WC_RNG*, byte*, word32);
int wc_InitRngNonce_ex(WC_RNG*, byte*, word32, void*, int);
int wc_InitRngNonce(WC_RNG*, const byte*, word32);
int wc_InitRngNonce_ex(WC_RNG*, const byte*, word32, void*, int);
int wc_RNG_GenerateBlock(WC_RNG*, byte*, word32);
int wc_RNG_GenerateByte(WC_RNG*, byte*);
int wc_FreeRng(WC_RNG*);
@ -1039,10 +1039,12 @@ def build_ffi(local_wolfssl, features):
RsaKey*, WC_RNG*);
int wc_RsaPublicEncrypt_ex(const byte* in, word32 inLen, byte* out,
word32 outLen, RsaKey* key, WC_RNG* rng, int type,
enum wc_HashType hash, int mgf, byte* label, word32 labelSz);
enum wc_HashType hash, int mgf, const byte* label,
word32 labelSz);
int wc_RsaPrivateDecrypt_ex(const byte* in, word32 inLen,
byte* out, word32 outLen, RsaKey* key, int type,
enum wc_HashType hash, int mgf, byte* label, word32 labelSz);
enum wc_HashType hash, int mgf, const byte* label,
word32 labelSz);
int wc_RsaSSL_Sign(const byte*, word32, byte*, word32, RsaKey*, WC_RNG*);
int wc_RsaSSL_Verify(const byte*, word32, byte*, word32, RsaKey*);
"""

View File

@ -60,8 +60,8 @@ setup(
packages=find_packages(),
setup_requires=["cffi>=1.0.0"],
install_requires=["cffi>=1.0.0"],
setup_requires=["cffi>=1.0.0,<2"],
install_requires=["cffi>=1.0.0,<2"],
cffi_modules=["./scripts/build_ffi.py:ffibuilder"],
package_data={"wolfcrypt": ["*.dll", "**/*.pyi"]}

View File

@ -50,7 +50,7 @@ if _lib.AESGCM_STREAM_ENABLED:
authTag = gcm.final()
assert b2h(authTag) == bytes('ac8fcee96dc6ef8e5236da19', 'utf-8')
assert b2h(buf) == bytes('5ba7d42e1bf01d7998e932', "utf-8")
gcmdec = AesGcmStream(key, iv)
gcmdec = AesGcmStream(key, iv, 12)
bufdec = gcmdec.decrypt(buf)
gcmdec.final(authTag)
assert bufdec == t2b("hello world")
@ -144,6 +144,33 @@ if _lib.AESGCM_STREAM_ENABLED:
tag = gcm.final()
assert len(tag) == good
def test_decrypt_rejects_wrong_tag_length():
key = "fedcba9876543210"
iv = "0123456789abcdef"
gcm = AesGcmStream(key, iv, tag_bytes=16)
buf = gcm.encrypt("hello world")
authTag = gcm.final()
assert len(authTag) == 16
# Truncated tag: would silently lower the verification window to
# 32-bit forgery probability without this check.
gcmdec = AesGcmStream(key, iv, tag_bytes=16)
gcmdec.decrypt(buf)
with pytest.raises(ValueError, match="authTag must be 16 bytes"):
gcmdec.final(authTag[:4])
# Over-long tag is also rejected.
gcmdec2 = AesGcmStream(key, iv, tag_bytes=16)
gcmdec2.decrypt(buf)
with pytest.raises(ValueError, match="authTag must be 16 bytes"):
gcmdec2.final(authTag + b"\x00")
# Happy path with the configured length still verifies.
gcmdec3 = AesGcmStream(key, iv, tag_bytes=16)
plain = gcmdec3.decrypt(buf)
gcmdec3.final(authTag)
assert plain == t2b("hello world")
def test_repeated_construction_destruction():
import gc
key = "fedcba9876543210"

View File

@ -496,7 +496,12 @@ if _lib.AESGCM_STREAM_ENABLED:
if authTag is None:
raise WolfCryptError("authTag parameter required")
authTag = t2b(authTag)
ret = _lib.wc_AesGcmDecryptFinal(self._native_object, authTag, len(authTag))
if len(authTag) != self._tag_bytes:
raise ValueError(
"authTag must be %d bytes, got %d" %
(self._tag_bytes, len(authTag)))
ret = _lib.wc_AesGcmDecryptFinal(
self._native_object, authTag, self._tag_bytes)
if ret < 0:
raise WolfCryptApiError("Decryption error", ret)