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
diff --git a/docs/hazmat/backends/interfaces.rst b/docs/hazmat/backends/interfaces.rst
index 4d0520f..8ea1cf9 100644
--- a/docs/hazmat/backends/interfaces.rst
+++ b/docs/hazmat/backends/interfaces.rst
@@ -452,6 +452,15 @@
             serialized data contains.
         :raises ValueError: If the data could not be deserialized.
 
+    .. method:: load_pem_parameters(data)
+
+        .. versionadded:: 2.0
+
+        :param bytes data: PEM data to load.
+        :return: A new instance of the appropriate type of encryption
+            parameters the serialized data contains.
+        :raises ValueError: If the data could not be deserialized.
+
 .. class:: DERSerializationBackend
 
     .. versionadded:: 0.8
@@ -476,6 +485,16 @@
             serialized data contains.
         :raises ValueError: If the data could not be deserialized.
 
+    .. method:: load_der_parameters(data)
+
+        .. versionadded:: 2.0
+
+        :param bytes data: DER data to load.
+        :return: A new instance of the appropriate type of encryption
+            parameters the serialized data contains.
+        :raises ValueError: If the data could not be deserialized.
+
+
 .. class:: X509Backend
 
     .. versionadded:: 0.7
diff --git a/docs/hazmat/primitives/asymmetric/dh.rst b/docs/hazmat/primitives/asymmetric/dh.rst
index f4cae1c..971d345 100644
--- a/docs/hazmat/primitives/asymmetric/dh.rst
+++ b/docs/hazmat/primitives/asymmetric/dh.rst
@@ -115,6 +115,25 @@
 
         :return: A :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHParameterNumbers`.
 
+    .. method:: parameter_bytes(encoding, format)
+
+        .. versionadded:: 2.0
+
+        Allows serialization of the parameters to bytes. Encoding (
+        :attr:`~cryptography.hazmat.primitives.serialization.Encoding.PEM` or
+        :attr:`~cryptography.hazmat.primitives.serialization.Encoding.DER`) and
+        format (
+        :attr:`~cryptography.hazmat.primitives.serialization.ParameterFormat.PKCS3`)
+        are chosen to define the exact serialization.
+
+        :param encoding: A value from the
+            :class:`~cryptography.hazmat.primitives.serialization.Encoding` enum.
+
+        :param format: A value from the
+            :class:`~cryptography.hazmat.primitives.serialization.ParameterFormat` enum.
+
+        :return bytes: Serialized parameters.
+
 
 Key interfaces
 ~~~~~~~~~~~~~~
diff --git a/docs/hazmat/primitives/asymmetric/serialization.rst b/docs/hazmat/primitives/asymmetric/serialization.rst
index b745332..b0cfbd0 100644
--- a/docs/hazmat/primitives/asymmetric/serialization.rst
+++ b/docs/hazmat/primitives/asymmetric/serialization.rst
@@ -63,6 +63,20 @@
     def sign_with_dsa_key(key, message):
         return b""
 
+    parameters_pem_data = b"""
+    -----BEGIN DH PARAMETERS-----
+    MIGHAoGBALsrWt44U1ojqTy88o0wfjysBE51V6Vtarjm2+5BslQK/RtlndHde3gx
+    +ccNs+InANszcuJFI8AHt4743kGRzy5XSlul4q4dDJENOHoyqYxueFuFVJELEwLQ
+    XrX/McKw+hS6GPVQnw6tZhgGo9apdNdYgeLQeQded8Bum8jqzP3rAgEC
+    -----END DH PARAMETERS-----
+    """.strip()
+
+    parameters_der_data = base64.b64decode(
+        b"MIGHAoGBALsrWt44U1ojqTy88o0wfjysBE51V6Vtarjm2+5BslQK/RtlndHde3gx+ccNs+In"
+        b"ANsz\ncuJFI8AHt4743kGRzy5XSlul4q4dDJENOHoyqYxueFuFVJELEwLQXrX/McKw+hS6GP"
+        b"VQnw6tZhgG\no9apdNdYgeLQeQded8Bum8jqzP3rAgEC"
+    )
+
 There are several common schemes for serializing asymmetric private and public
 keys to bytes. They generally support encryption of private keys and additional
 key metadata.
@@ -181,6 +195,37 @@
     :raises cryptography.exceptions.UnsupportedAlgorithm: If the serialized key
         is of a type that is not supported by the backend.
 
+.. function:: load_pem_parameters(data, backend)
+
+    .. versionadded:: 2.0
+
+    Deserialize encryption parameters from PEM encoded data to one of the supported
+    asymmetric encryption parameters types.
+
+    .. doctest::
+
+        >>> from cryptography.hazmat.primitives.serialization import load_pem_parameters
+        >>> from cryptography.hazmat.primitives.asymmetric import dh
+        >>> parameters = load_pem_parameters(parameters_pem_data, backend=default_backend())
+        >>> isinstance(parameters, dh.DHParameters)
+        True
+
+    :param bytes data: The PEM encoded parameters data.
+
+    :param backend: An instance of
+        :class:`~cryptography.hazmat.backends.interfaces.PEMSerializationBackend`.
+
+
+    :returns: Currently only
+        :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHParameters`
+        supported.
+
+    :raises ValueError: If the PEM data's structure could not be decoded
+        successfully.
+
+    :raises cryptography.exceptions.UnsupportedAlgorithm: If the serialized parameters
+        is of a type that is not supported by the backend.
+
 DER
 ~~~
 
@@ -268,6 +313,37 @@
         >>> isinstance(key, rsa.RSAPublicKey)
         True
 
+.. function:: load_der_parameters(data, backend)
+
+    .. versionadded:: 2.0
+
+    Deserialize encryption parameters from DER encoded data to one of the supported
+    asymmetric encryption parameters types.
+
+    :param bytes data: The DER encoded parameters data.
+
+    :param backend: An instance of
+        :class:`~cryptography.hazmat.backends.interfaces.DERSerializationBackend`.
+
+    :returns: Currently only
+        :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHParameters`
+        supported.
+
+    :raises ValueError: If the DER data's structure could not be decoded
+        successfully.
+
+    :raises cryptography.exceptions.UnsupportedAlgorithm: If the serialized key is of a type that
+        is not supported by the backend.
+
+    .. doctest::
+
+        >>> from cryptography.hazmat.backends import default_backend
+        >>> from cryptography.hazmat.primitives.asymmetric import dh
+        >>> from cryptography.hazmat.primitives.serialization import load_der_parameters
+        >>> parameters = load_der_parameters(parameters_der_data, backend=default_backend())
+        >>> isinstance(parameters, dh.DHParameters)
+        True
+
 
 OpenSSH Public Key
 ~~~~~~~~~~~~~~~~~~
@@ -379,6 +455,18 @@
         The public key format used by OpenSSH (e.g. as found in
         ``~/.ssh/id_rsa.pub`` or ``~/.ssh/authorized_keys``).
 
+.. class:: ParameterFormat
+
+    .. versionadded:: 2.0
+
+    An enumeration for parameters formats. Used with the ``parameter_bytes``
+    method available on
+    :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHParametersWithSerialization`.
+
+    .. attribute:: PKCS3
+
+        ASN1 DH parameters sequence as defined in `PKCS3`_.
+
 Serialization Encodings
 ~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -445,3 +533,6 @@
 .. class:: NoEncryption
 
     Do not encrypt.
+
+
+.. _`PKCS3`: https://www.emc.com/emc-plus/rsa-labs/standards-initiatives/pkcs-3-diffie-hellman-key-agreement-standar.htm