From 9849bef358804e65a6d0c8d0cbea24a421fde4ad Mon Sep 17 00:00:00 2001 From: Seb Olney Date: Tue, 12 Sep 2023 09:53:58 +0100 Subject: [PATCH 1/2] Define test for plaintext and nonce too long --- lib/Crypto/SelfTest/Cipher/test_CCM.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lib/Crypto/SelfTest/Cipher/test_CCM.py b/lib/Crypto/SelfTest/Cipher/test_CCM.py index e8ebc0b1e..9d9c21776 100644 --- a/lib/Crypto/SelfTest/Cipher/test_CCM.py +++ b/lib/Crypto/SelfTest/Cipher/test_CCM.py @@ -241,6 +241,19 @@ def test_shorter_ciphertext_than_declared(self): msg_len=DATA_LEN - 1) self.assertRaises(ValueError, cipher.decrypt, ct) + def test_plaintext_too_long_for_nonce(self): + nonce = get_tag_random("nonce", 13) + # The octet length of the binary representation of the octet length + # of the payload. + q = 15 - len(nonce) + + # The plaintext must be shorter than this + # See Appendix A.1 of NIST SP 800-38C + data_len_limit = 2**(8 * q) + data = bytearray(data_len_limit) + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=nonce) + self.assertRaises(OverflowError, cipher.encrypt_and_digest, data) + def test_message_chunks(self): # Validate that both associated data and plaintext/ciphertext # can be broken up in chunks of arbitrary length From 10f21fffd3074e39480a0ac8c7610e0ad0daf8c4 Mon Sep 17 00:00:00 2001 From: Seb Olney Date: Tue, 12 Sep 2023 10:14:18 +0100 Subject: [PATCH 2/2] Check for length overflow --- lib/Crypto/Cipher/_mode_ccm.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/Crypto/Cipher/_mode_ccm.py b/lib/Crypto/Cipher/_mode_ccm.py index 1c1105bcb..7f78fbe5a 100644 --- a/lib/Crypto/Cipher/_mode_ccm.py +++ b/lib/Crypto/Cipher/_mode_ccm.py @@ -189,9 +189,13 @@ def _start_mac(self): # Formatting control information and nonce (A.2.1) q = 15 - len(self.nonce) # length of Q, the encoded message length + # Limit on plaintext length imposed by choice of nonce (A.1) + if self._msg_len >= 2**(8*q): + raise OverflowError("Combined plaintext and nonce too long") flags = (64 * (self._assoc_len > 0) + 8 * ((self._mac_len - 2) // 2) + (q - 1)) b_0 = struct.pack("B", flags) + self.nonce + long_to_bytes(self._msg_len, q) + assert len(b_0) == 16 # Formatting associated data (A.2.2) # Encoded 'a' is concatenated with the associated data 'A'