Fix AesSiv silently mangling associated data
AesSiv._prepare_associated_data only checked for str and bytes when deciding whether the input was a single associated-data block, so bytearray and memoryview fell through to the "list of blocks" branch. Iterating those types yields integers, which t2b() then turned into ASCII decimal byte-strings (b'16', b'17', ...), producing many bogus blocks instead of one. The C SIV computation succeeded over wrong associated data, so encryption/decryption silently produced an incorrect tag rather than raising. This broke interoperability between callers passing the same content as different buffer types. Match the set of types accepted by t2b() by including bytearray and memoryview in the isinstance check. Add a parametrized test that reuses the OpenSSL KAT vectors with bytes, bytearray, and memoryview wrappers; a round-trip test would not have caught this since both sides mangle identically. F-1981pull/118/head
parent
4ec45a6511
commit
6c1c1b76bb
|
|
@ -938,6 +938,35 @@ def test_aessiv_decrypt_kat_openssl():
|
|||
assert plaintext == TEST_VECTOR_PLAINTEXT_OPENSSL
|
||||
|
||||
|
||||
@pytest.mark.skipif(not _lib.AES_SIV_ENABLED, reason="AES-SIV not enabled")
|
||||
@pytest.mark.parametrize("wrap", [bytes, bytearray, memoryview],
|
||||
ids=["bytes", "bytearray", "memoryview"])
|
||||
def test_aessiv_associated_data_accepts_buffer_types(wrap):
|
||||
"""
|
||||
Single-block associated_data passed as bytes, bytearray, or memoryview
|
||||
must all produce the same SIV/ciphertext as the OpenSSL KAT. A previous
|
||||
bug treated bytearray/memoryview as a sequence of int blocks, producing
|
||||
a different (incorrect) tag without raising.
|
||||
"""
|
||||
aessiv = AesSiv(TEST_VECTOR_KEY_OPENSSL)
|
||||
associated_data = wrap(TEST_VECTOR_ASSOCIATED_DATA_OPENSSL)
|
||||
siv, ciphertext = aessiv.encrypt(
|
||||
associated_data,
|
||||
TEST_VECTOR_NONCE_OPENSSL,
|
||||
TEST_VECTOR_PLAINTEXT_OPENSSL
|
||||
)
|
||||
assert siv == TEST_VECTOR_SIV_OPENSSL
|
||||
assert ciphertext == TEST_VECTOR_CIPHERTEXT_OPENSSL
|
||||
|
||||
plaintext = aessiv.decrypt(
|
||||
wrap(TEST_VECTOR_ASSOCIATED_DATA_OPENSSL),
|
||||
TEST_VECTOR_NONCE_OPENSSL,
|
||||
TEST_VECTOR_SIV_OPENSSL,
|
||||
TEST_VECTOR_CIPHERTEXT_OPENSSL
|
||||
)
|
||||
assert plaintext == TEST_VECTOR_PLAINTEXT_OPENSSL
|
||||
|
||||
|
||||
if _lib.DES3_ENABLED:
|
||||
def test_des3_rejects_mode_ctr():
|
||||
key = b"\x01\x23\x45\x67\x89\xab\xcd\xef" * 3
|
||||
|
|
|
|||
|
|
@ -363,7 +363,7 @@ if _lib.AES_SIV_ENABLED:
|
|||
C function has been called, in order to make sure that the memory
|
||||
is not freed by the FFI garbage collector before the data is read.
|
||||
"""
|
||||
if isinstance(associated_data, str) or isinstance(associated_data, bytes):
|
||||
if isinstance(associated_data, (str, bytes, bytearray, memoryview)):
|
||||
# A single block is provided.
|
||||
# Make sure we have bytes.
|
||||
associated_data = t2b(associated_data)
|
||||
|
|
|
|||
Loading…
Reference in New Issue