diff options
-rw-r--r-- | docs/development/test-vectors.rst | 3 | ||||
-rw-r--r-- | src/cryptography/hazmat/primitives/ciphers/base.py | 19 | ||||
-rw-r--r-- | src/cryptography/hazmat/primitives/ciphers/modes.py | 2 | ||||
-rw-r--r-- | tests/hazmat/primitives/test_aes.py | 50 | ||||
-rw-r--r-- | vectors/cryptography_vectors/x509/custom/nc_single_ip_netmask.pem | 19 |
5 files changed, 93 insertions, 0 deletions
diff --git a/docs/development/test-vectors.rst b/docs/development/test-vectors.rst index ca07547c..fe64fe1a 100644 --- a/docs/development/test-vectors.rst +++ b/docs/development/test-vectors.rst @@ -215,6 +215,9 @@ Custom X.509 Vectors * ``nc_invalid_ip_netmask.pem`` - An RSA 2048 bit self-signed certificate containing a name constraints extension with a permitted element that has an ``IPv6`` IP and an invalid network mask. +* ``nc_single_ip_netmask.pem`` - An RSA 2048 bit self-signed certificate + containing a name constraints extension with a permitted element that has two + IPs with ``/32`` and ``/128`` network masks. * ``cp_user_notice_with_notice_reference.pem`` - An RSA 2048 bit self-signed certificate containing a certificate policies extension with a notice reference in the user notice. diff --git a/src/cryptography/hazmat/primitives/ciphers/base.py b/src/cryptography/hazmat/primitives/ciphers/base.py index 8f3028fc..dae93655 100644 --- a/src/cryptography/hazmat/primitives/ciphers/base.py +++ b/src/cryptography/hazmat/primitives/ciphers/base.py @@ -149,6 +149,8 @@ class _CipherContext(object): class _AEADCipherContext(object): def __init__(self, ctx): self._ctx = ctx + self._bytes_processed = 0 + self._aad_bytes_processed = 0 self._tag = None self._updated = False @@ -156,6 +158,14 @@ class _AEADCipherContext(object): if self._ctx is None: raise AlreadyFinalized("Context was already finalized.") self._updated = True + self._bytes_processed += len(data) + if self._bytes_processed > self._ctx._mode._MAX_ENCRYPTED_BYTES: + raise ValueError( + "{0} has a maximum encrypted byte limit of {1}".format( + self._ctx._mode.name, self._ctx._mode._MAX_ENCRYPTED_BYTES + ) + ) + return self._ctx.update(data) def finalize(self): @@ -171,6 +181,15 @@ class _AEADCipherContext(object): raise AlreadyFinalized("Context was already finalized.") if self._updated: raise AlreadyUpdated("Update has been called on this context.") + + self._aad_bytes_processed += len(data) + if self._aad_bytes_processed > self._ctx._mode._MAX_AAD_BYTES: + raise ValueError( + "{0} has a maximum AAD byte limit of {0}".format( + self._ctx._mode.name, self._ctx._mode._MAX_AAD_BYTES + ) + ) + self._ctx.authenticate_additional_data(data) diff --git a/src/cryptography/hazmat/primitives/ciphers/modes.py b/src/cryptography/hazmat/primitives/ciphers/modes.py index e31c9060..4284042d 100644 --- a/src/cryptography/hazmat/primitives/ciphers/modes.py +++ b/src/cryptography/hazmat/primitives/ciphers/modes.py @@ -139,6 +139,8 @@ class CTR(object): @utils.register_interface(ModeWithAuthenticationTag) class GCM(object): name = "GCM" + _MAX_ENCRYPTED_BYTES = (2 ** 39 - 256) // 8 + _MAX_AAD_BYTES = (2 ** 64) // 8 def __init__(self, initialization_vector, tag=None, min_tag_length=16): # len(initialization_vector) must in [1, 2 ** 64), but it's impossible diff --git a/tests/hazmat/primitives/test_aes.py b/tests/hazmat/primitives/test_aes.py index 4d48e8ad..2c3e5f90 100644 --- a/tests/hazmat/primitives/test_aes.py +++ b/tests/hazmat/primitives/test_aes.py @@ -253,3 +253,53 @@ class TestAESModeGCM(object): computed_ct = encryptor.update(pt) + encryptor.finalize() assert computed_ct == ct assert encryptor.tag == tag + + def test_gcm_ciphertext_limit(self, backend): + encryptor = base.Cipher( + algorithms.AES(b"\x00" * 16), + modes.GCM(b"\x01" * 16), + backend=backend + ).encryptor() + encryptor._bytes_processed = modes.GCM._MAX_ENCRYPTED_BYTES - 16 + encryptor.update(b"0" * 16) + assert ( + encryptor._bytes_processed == modes.GCM._MAX_ENCRYPTED_BYTES + ) + with pytest.raises(ValueError): + encryptor.update(b"0") + + def test_gcm_aad_limit(self, backend): + encryptor = base.Cipher( + algorithms.AES(b"\x00" * 16), + modes.GCM(b"\x01" * 16), + backend=backend + ).encryptor() + encryptor._aad_bytes_processed = modes.GCM._MAX_AAD_BYTES - 16 + encryptor.authenticate_additional_data(b"0" * 16) + assert encryptor._aad_bytes_processed == modes.GCM._MAX_AAD_BYTES + with pytest.raises(ValueError): + encryptor.authenticate_additional_data(b"0") + + def test_gcm_ciphertext_increments(self, backend): + encryptor = base.Cipher( + algorithms.AES(b"\x00" * 16), + modes.GCM(b"\x01" * 16), + backend=backend + ).encryptor() + encryptor.update(b"0" * 8) + assert encryptor._bytes_processed == 8 + encryptor.update(b"0" * 7) + assert encryptor._bytes_processed == 15 + encryptor.update(b"0" * 18) + assert encryptor._bytes_processed == 33 + + def test_gcm_aad_increments(self, backend): + encryptor = base.Cipher( + algorithms.AES(b"\x00" * 16), + modes.GCM(b"\x01" * 16), + backend=backend + ).encryptor() + encryptor.authenticate_additional_data(b"0" * 8) + assert encryptor._aad_bytes_processed == 8 + encryptor.authenticate_additional_data(b"0" * 18) + assert encryptor._aad_bytes_processed == 26 diff --git a/vectors/cryptography_vectors/x509/custom/nc_single_ip_netmask.pem b/vectors/cryptography_vectors/x509/custom/nc_single_ip_netmask.pem new file mode 100644 index 00000000..2931b6b9 --- /dev/null +++ b/vectors/cryptography_vectors/x509/custom/nc_single_ip_netmask.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIC/TCCAeWgAwIBAgITBnA4pkis5m3OGusBaihd9qH0hzANBgkqhkiG9w0BAQsF +ADAXMRUwEwYDVQQDDAxjcnlwdG9ncmFwaHkwHhcNMTUwNzAxMjAxNDAwWhcNMTYw +NjMwMjAxNDAwWjAXMRUwEwYDVQQDDAxjcnlwdG9ncmFwaHkwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQCYyaGtu90vcm+jN+SoQHXxWMQyplY1neL9KjfE ++TsKKcy8TKJEqlT8qZr6bIL3KVbTIiYO8bCW9fHSMgHWrmtr37LlFoQ3emcLfDbM +kybmOolAxA78im0L2BIW1wT2iSHh1p/ZO5QLdt+e8zP5AkZAnXCZk912RcJYyGUW +7JQzzRfEANSLE9Gmh78NsxWNI1Ipc3dhyuk3+YHwePGCzLCeXCiF4FHGNMg8Drtr +rENNHZjHJCbMLfK9irHV5Xh1FHTK8xlqEq+YecpqboUyqgWVOOvpxUxiKagfp//Z ++iFDC1+GgpuupzFUiHPSVCZGMnE3bHvIBOkoHkNu7kNK7VX3AgMBAAGjQjBAMD4G +A1UdHgEB/wQ0MDKgMDAihyAA/wAAAAAAAAAAAAAAAAAA//////////////////// +/zAKhwjAqAAB/////zANBgkqhkiG9w0BAQsFAAOCAQEAXSDmonnBpivsW/NKE85c +1ho449K98+1cFUD51VeK42oPUd0GRQCU3ETYJ5YyK7OMoQqe4LTtNDx6ZCF+6z/r +tZctfdpwRmqh2ebGn3qDs1FAckkwwSCRtkJTdgznmtO680Ls5GveNFrgYJkYfFjj +OWpzCypse/3j3uVgSakmjBRS4BOsyX4o7trN+k1MmQOrMpWEtLlmrZJpM66sgP0j +WpI95l4paIMpkFarwCCQfJCNBpl7Uol+BD4vJvf/J7f7ZwxQMEWCBPnYk3EKMnKa +aCsmqRMV1W7SzxL07dHMzWnsC/I5oJNj4HdthGcIJf1Jut9A9KFVodOJAxKOziz2 +aQ== +-----END CERTIFICATE----- |