aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAviv Palivoda <palaviv@gmail.com>2017-06-24 22:00:28 +0300
committerPaul Kehrer <paul.l.kehrer@gmail.com>2017-06-24 09:00:28 -1000
commit6b08aba7f1eb296461528328a3c9871fa7594fc4 (patch)
treebdf2bbbd1fc71815b97cafc02a747d428ce4b464 /src
parent1cff0c08cfc7385f46a188f13f08ca5a87f85b48 (diff)
downloadcryptography-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.py12
-rw-r--r--src/cryptography/hazmat/backends/openssl/backend.py63
-rw-r--r--src/cryptography/hazmat/backends/openssl/dh.py22
-rw-r--r--src/cryptography/hazmat/primitives/serialization.py12
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