diff options
author | Aviv Palivoda <palaviv@gmail.com> | 2017-06-24 22:00:28 +0300 |
---|---|---|
committer | Paul Kehrer <paul.l.kehrer@gmail.com> | 2017-06-24 09:00:28 -1000 |
commit | 6b08aba7f1eb296461528328a3c9871fa7594fc4 (patch) | |
tree | bdf2bbbd1fc71815b97cafc02a747d428ce4b464 /src | |
parent | 1cff0c08cfc7385f46a188f13f08ca5a87f85b48 (diff) | |
download | cryptography-6b08aba7f1eb296461528328a3c9871fa7594fc4.tar.gz cryptography-6b08aba7f1eb296461528328a3c9871fa7594fc4.tar.bz2 cryptography-6b08aba7f1eb296461528328a3c9871fa7594fc4.zip |
Dh parameters serialization (#3504)
* Support DH parameter serizalization - no X9.42
* Support X9.42 serialization - DER not working
* Fix dhp_rfc5114_2.der
Changing the DER parameters serialization after the
fix in openssl commit a292c9f1b835
* DH parameters X9.42 DER serialization fixed
* fix _skip_dhx_unsupported
* document DH parameter_bytes
* PEP8 fixes
* Document load_pem_parameters
* Document load_der_parameters
* document ParameterFormat
* Increase test coverage
* Increase test covrage
* Remove unneeded check
* Fix typo
* Fix error in load_der_parameters
* Add load_pem_parameters and load_der_parameters to interfaces
* CR fixes
* Removed unverified phrase
* Update version to 2.0
* Fix pep8
* Rename ParameterFormat.ASN1 to ParameterFormat.DHParameter
* link pkcs3
* Add new line at end of file to serialization.rst
* Rename DHparameters to PKCS3
* doc CR fix
Diffstat (limited to 'src')
-rw-r--r-- | src/cryptography/hazmat/backends/interfaces.py | 12 | ||||
-rw-r--r-- | src/cryptography/hazmat/backends/openssl/backend.py | 63 | ||||
-rw-r--r-- | src/cryptography/hazmat/backends/openssl/dh.py | 22 | ||||
-rw-r--r-- | src/cryptography/hazmat/primitives/serialization.py | 12 |
4 files changed, 109 insertions, 0 deletions
diff --git a/src/cryptography/hazmat/backends/interfaces.py b/src/cryptography/hazmat/backends/interfaces.py index 9ed50cc4..0a476b99 100644 --- a/src/cryptography/hazmat/backends/interfaces.py +++ b/src/cryptography/hazmat/backends/interfaces.py @@ -243,6 +243,12 @@ class PEMSerializationBackend(object): Loads a public key from PEM encoded data. """ + @abc.abstractmethod + def load_pem_parameters(self, data): + """ + Load encryption parameters from PEM encoded data. + """ + @six.add_metaclass(abc.ABCMeta) class DERSerializationBackend(object): @@ -259,6 +265,12 @@ class DERSerializationBackend(object): Loads a public key from DER encoded data. """ + @abc.abstractmethod + def load_der_parameters(self, data): + """ + Load encryption parameters from DER encoded data. + """ + @six.add_metaclass(abc.ABCMeta) class X509Backend(object): diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index d17b38ca..5458a0f8 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -1007,6 +1007,17 @@ class Backend(object): else: self._handle_key_loading_error() + def load_pem_parameters(self, data): + mem_bio = self._bytes_to_bio(data) + # only DH is supported currently + dh_cdata = self._lib.PEM_read_bio_DHparams( + mem_bio.bio, self._ffi.NULL, self._ffi.NULL, self._ffi.NULL) + if dh_cdata != self._ffi.NULL: + dh_cdata = self._ffi.gc(dh_cdata, self._lib.DH_free) + return _DHParameters(self, dh_cdata) + else: + self._handle_key_loading_error() + def load_der_private_key(self, data, password): # OpenSSL has a function called d2i_AutoPrivateKey that in theory # handles this automatically, however it doesn't handle encrypted @@ -1063,6 +1074,28 @@ class Backend(object): else: self._handle_key_loading_error() + def load_der_parameters(self, data): + mem_bio = self._bytes_to_bio(data) + dh_cdata = self._lib.d2i_DHparams_bio( + mem_bio.bio, self._ffi.NULL + ) + if dh_cdata != self._ffi.NULL: + dh_cdata = self._ffi.gc(dh_cdata, self._lib.DH_free) + return _DHParameters(self, dh_cdata) + elif self._lib.Cryptography_HAS_EVP_PKEY_DHX: + # We check to see if the is dhx. + self._consume_errors() + res = self._lib.BIO_reset(mem_bio.bio) + self.openssl_assert(res == 1) + dh_cdata = self._lib.Cryptography_d2i_DHxparams_bio( + mem_bio.bio, self._ffi.NULL + ) + if dh_cdata != self._ffi.NULL: + dh_cdata = self._ffi.gc(dh_cdata, self._lib.DH_free) + return _DHParameters(self, dh_cdata) + + self._handle_key_loading_error() + def load_pem_x509_certificate(self, data): mem_bio = self._bytes_to_bio(data) x509 = self._lib.PEM_read_bio_X509( @@ -1618,6 +1651,36 @@ class Backend(object): serialization._ssh_write_string(public_numbers.encode_point()) ) + def _parameter_bytes(self, encoding, format, cdata): + if encoding is serialization.Encoding.OpenSSH: + raise TypeError( + "OpenSSH encoding is not supported" + ) + + # Only DH is supported here currently. + q = self._ffi.new("BIGNUM **") + self._lib.DH_get0_pqg(cdata, + self._ffi.NULL, + q, + self._ffi.NULL) + if encoding is serialization.Encoding.PEM: + if q[0] != self._ffi.NULL: + write_bio = self._lib.PEM_write_bio_DHxparams + else: + write_bio = self._lib.PEM_write_bio_DHparams + elif encoding is serialization.Encoding.DER: + if q[0] != self._ffi.NULL: + write_bio = self._lib.Cryptography_i2d_DHxparams_bio + else: + write_bio = self._lib.i2d_DHparams_bio + else: + raise TypeError("encoding must be an item from the Encoding enum") + + bio = self._create_mem_bio_gc() + res = write_bio(bio, cdata) + self.openssl_assert(res == 1) + return self._read_mem_bio(bio) + def generate_dh_parameters(self, generator, key_size): if key_size < 512: raise ValueError("DH key_size must be at least 512 bits") diff --git a/src/cryptography/hazmat/backends/openssl/dh.py b/src/cryptography/hazmat/backends/openssl/dh.py index 456e9bea..e5f76447 100644 --- a/src/cryptography/hazmat/backends/openssl/dh.py +++ b/src/cryptography/hazmat/backends/openssl/dh.py @@ -59,6 +59,28 @@ class _DHParameters(object): def generate_private_key(self): return self._backend.generate_dh_private_key(self) + def parameter_bytes(self, encoding, format): + if format is not serialization.ParameterFormat.PKCS3: + raise ValueError( + "Only PKCS3 serialization is supported" + ) + if not self._backend._lib.Cryptography_HAS_EVP_PKEY_DHX: + q = self._backend._ffi.new("BIGNUM **") + self._backend._lib.DH_get0_pqg(self._dh_cdata, + self._backend._ffi.NULL, + q, + self._backend._ffi.NULL) + if q[0] != self._backend._ffi.NULL: + raise UnsupportedAlgorithm( + "DH X9.42 serialization is not supported", + _Reasons.UNSUPPORTED_SERIALIZATION) + + return self._backend._parameter_bytes( + encoding, + format, + self._dh_cdata + ) + def _handle_dh_compute_key_error(errors, backend): lib = backend._lib diff --git a/src/cryptography/hazmat/primitives/serialization.py b/src/cryptography/hazmat/primitives/serialization.py index 992fd42f..bd09e6e3 100644 --- a/src/cryptography/hazmat/primitives/serialization.py +++ b/src/cryptography/hazmat/primitives/serialization.py @@ -24,6 +24,10 @@ def load_pem_public_key(data, backend): return backend.load_pem_public_key(data) +def load_pem_parameters(data, backend): + return backend.load_pem_parameters(data) + + def load_der_private_key(data, password, backend): return backend.load_der_private_key(data, password) @@ -32,6 +36,10 @@ def load_der_public_key(data, backend): return backend.load_der_public_key(data) +def load_der_parameters(data, backend): + return backend.load_der_parameters(data) + + def load_ssh_public_key(data, backend): key_parts = data.split(b' ', 2) @@ -178,6 +186,10 @@ class PublicFormat(Enum): OpenSSH = "OpenSSH" +class ParameterFormat(Enum): + PKCS3 = "PKCS3" + + @six.add_metaclass(abc.ABCMeta) class KeySerializationEncryption(object): pass |