diff options
author | Paul Kehrer <paul.l.kehrer@gmail.com> | 2019-01-17 09:43:47 -0600 |
---|---|---|
committer | Alex Gaynor <alex.gaynor@gmail.com> | 2019-01-17 10:43:47 -0500 |
commit | 5b4c81e39622fc13895bf5df7d0f4f6bd067e7a0 (patch) | |
tree | 70ae40472a57cad2b25d9fba7044f3a719e7c05f | |
parent | 8d9ea52be9e7de1373641d3afaed9b292cb03f43 (diff) | |
download | cryptography-5b4c81e39622fc13895bf5df7d0f4f6bd067e7a0.tar.gz cryptography-5b4c81e39622fc13895bf5df7d0f4f6bd067e7a0.tar.bz2 cryptography-5b4c81e39622fc13895bf5df7d0f4f6bd067e7a0.zip |
x448 and x25519 should enforce key lengths in backend (#4703)
* x448 and x25519 should enforce key lengths in from_private_bytes
they should also check if the algorithm is supported like the public
bytes class methods do
* oops
* move the checks
-rw-r--r-- | src/cryptography/hazmat/backends/openssl/backend.py | 9 | ||||
-rw-r--r-- | src/cryptography/hazmat/primitives/asymmetric/x25519.py | 9 | ||||
-rw-r--r-- | src/cryptography/hazmat/primitives/asymmetric/x448.py | 6 | ||||
-rw-r--r-- | tests/hazmat/primitives/test_x25519.py | 10 | ||||
-rw-r--r-- | tests/hazmat/primitives/test_x448.py | 12 |
5 files changed, 42 insertions, 4 deletions
diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index fd6057f8..8cec64d6 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -2081,6 +2081,9 @@ class Backend(object): def x25519_load_public_bytes(self, data): # When we drop support for CRYPTOGRAPHY_OPENSSL_LESS_THAN_111 we can # switch this to EVP_PKEY_new_raw_public_key + if len(data) != 32: + raise ValueError("An X25519 public key is 32 bytes long") + evp_pkey = self._create_evp_pkey_gc() res = self._lib.EVP_PKEY_set_type(evp_pkey, self._lib.NID_X25519) backend.openssl_assert(res == 1) @@ -2106,6 +2109,9 @@ class Backend(object): # Of course there's a bit more complexity. In reality OCTET STRING # contains an OCTET STRING of length 32! So the last two bytes here # are \x04\x20, which is an OCTET STRING of length 32. + if len(data) != 32: + raise ValueError("An X25519 private key is 32 bytes long") + pkcs8_prefix = b'0.\x02\x01\x000\x05\x06\x03+en\x04"\x04 ' bio = self._bytes_to_bio(pkcs8_prefix + data) evp_pkey = backend._lib.d2i_PrivateKey_bio(bio.bio, self._ffi.NULL) @@ -2148,6 +2154,9 @@ class Backend(object): return _X448PublicKey(self, evp_pkey) def x448_load_private_bytes(self, data): + if len(data) != 56: + raise ValueError("An X448 private key is 56 bytes long") + data_ptr = self._ffi.from_buffer(data) evp_pkey = self._lib.EVP_PKEY_new_raw_private_key( self._lib.NID_X448, self._ffi.NULL, data_ptr, len(data) diff --git a/src/cryptography/hazmat/primitives/asymmetric/x25519.py b/src/cryptography/hazmat/primitives/asymmetric/x25519.py index 94602261..4e8badf4 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/x25519.py +++ b/src/cryptography/hazmat/primitives/asymmetric/x25519.py @@ -22,9 +22,6 @@ class X25519PublicKey(object): _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM ) - if len(data) != 32: - raise ValueError("An X25519 public key is 32 bytes long") - return backend.x25519_load_public_bytes(data) @abc.abstractmethod @@ -49,6 +46,12 @@ class X25519PrivateKey(object): @classmethod def from_private_bytes(cls, data): from cryptography.hazmat.backends.openssl.backend import backend + if not backend.x25519_supported(): + raise UnsupportedAlgorithm( + "X25519 is not supported by this version of OpenSSL.", + _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM + ) + return backend.x25519_load_private_bytes(data) @abc.abstractmethod diff --git a/src/cryptography/hazmat/primitives/asymmetric/x448.py b/src/cryptography/hazmat/primitives/asymmetric/x448.py index 992ec0fd..475e678f 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/x448.py +++ b/src/cryptography/hazmat/primitives/asymmetric/x448.py @@ -46,6 +46,12 @@ class X448PrivateKey(object): @classmethod def from_private_bytes(cls, data): from cryptography.hazmat.backends.openssl.backend import backend + if not backend.x448_supported(): + raise UnsupportedAlgorithm( + "X448 is not supported by this version of OpenSSL.", + _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM + ) + return backend.x448_load_private_bytes(data) @abc.abstractmethod diff --git a/tests/hazmat/primitives/test_x25519.py b/tests/hazmat/primitives/test_x25519.py index 682c3125..f412f2e8 100644 --- a/tests/hazmat/primitives/test_x25519.py +++ b/tests/hazmat/primitives/test_x25519.py @@ -32,6 +32,9 @@ def test_x25519_unsupported(backend): X25519PublicKey.from_public_bytes(b"0" * 32) with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM): + X25519PrivateKey.from_private_bytes(b"0" * 32) + + with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM): X25519PrivateKey.generate() @@ -166,6 +169,13 @@ class TestX25519Exchange(object): with pytest.raises(ValueError): X25519PublicKey.from_public_bytes(b"a" * 33) + def test_invalid_length_from_private_bytes(self, backend): + with pytest.raises(ValueError): + X25519PrivateKey.from_private_bytes(b"a" * 31) + + with pytest.raises(ValueError): + X25519PrivateKey.from_private_bytes(b"a" * 33) + def test_invalid_private_bytes(self, backend): key = X25519PrivateKey.generate() with pytest.raises(ValueError): diff --git a/tests/hazmat/primitives/test_x448.py b/tests/hazmat/primitives/test_x448.py index 51be0e10..817de76f 100644 --- a/tests/hazmat/primitives/test_x448.py +++ b/tests/hazmat/primitives/test_x448.py @@ -28,7 +28,10 @@ from ...utils import ( @pytest.mark.requires_backend_interface(interface=DHBackend) def test_x448_unsupported(backend): with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM): - X448PublicKey.from_public_bytes(b"0" * 32) + X448PublicKey.from_public_bytes(b"0" * 56) + + with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM): + X448PrivateKey.from_private_bytes(b"0" * 56) with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM): X448PrivateKey.generate() @@ -176,6 +179,13 @@ class TestX448Exchange(object): with pytest.raises(ValueError): X448PublicKey.from_public_bytes(b"a" * 57) + def test_invalid_length_from_private_bytes(self, backend): + with pytest.raises(ValueError): + X448PrivateKey.from_private_bytes(b"a" * 55) + + with pytest.raises(ValueError): + X448PrivateKey.from_private_bytes(b"a" * 57) + def test_invalid_private_bytes(self, backend): key = X448PrivateKey.generate() with pytest.raises(ValueError): |