Skip to content
Merged
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
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ classifiers = [
]
dynamic = ["version"]
dependencies = [
"cffi>=1.0.0",
"cffi>=1.0.0,<2",
]

[project.urls]
Expand Down
4 changes: 2 additions & 2 deletions requirements/docs.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
-r prod.txt
Sphinx
sphinx_rtd_theme
Sphinx>=7,<9
sphinx_rtd_theme>=2,<4
2 changes: 1 addition & 1 deletion requirements/prod.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
cffi
cffi>=1.17,<2
Comment thread
LinuxJedi marked this conversation as resolved.
6 changes: 3 additions & 3 deletions requirements/test.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
-r prod.txt
tox
pytest
types-cffi
tox>=4,<5
pytest>=8,<9
types-cffi>=1.16,<2
10 changes: 6 additions & 4 deletions scripts/build_ffi.py
Original file line number Diff line number Diff line change
Expand Up @@ -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*);
Expand Down Expand Up @@ -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*);
"""
Expand Down
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@

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"]}
Expand Down
29 changes: 28 additions & 1 deletion tests/test_aesgcmstream.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def test_encrypt_short_tag():
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")
Expand Down Expand Up @@ -144,6 +144,33 @@ def test_invalid_tag_bytes():
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"
Expand Down
7 changes: 6 additions & 1 deletion wolfcrypt/ciphers.py
Original file line number Diff line number Diff line change
Expand Up @@ -496,7 +496,12 @@ def final(self, authTag=None):
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)

Expand Down
Loading