Merge pull request #1651 from reaperhulk/x509-signature-algorithm

X509 certificate signature algorithm support
diff --git a/.travis/install.sh b/.travis/install.sh
index 418aeed..26a82c4 100755
--- a/.travis/install.sh
+++ b/.travis/install.sh
@@ -46,8 +46,8 @@
             ;;
         pypy)
             brew upgrade pyenv
-            pyenv install pypy-2.4.0
-            pyenv global pypy-2.4.0
+            pyenv install pypy-2.5.0
+            pyenv global pypy-2.5.0
             ;;
         pypy3)
             brew upgrade pyenv
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index f903b7f..e8c2521 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -13,10 +13,39 @@
   :class:`~cryptography.x509.Certificate`.
 * Added
   :func:`~cryptography.hazmat.primitives.asymmetric.rsa.rsa_recover_prime_factors`
+* :class:`~cryptography.hazmat.primitives.kdf.KeyDerivationFunction` was moved
+  from :mod:`~cryptography.hazmat.primitives.interfaces` to
+  :mod:`~cryptography.hazmat.primitives.kdf`.
 * :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` and
   :class:`~cryptography.hazmat.primitives.hashes.HashContext` were moved from
   :mod:`~cryptography.hazmat.primitives.interfaces` to
   :mod:`~cryptography.hazmat.primitives.hashes`.
+* :class:`~cryptography.hazmat.primitives.ciphers.CipherContext`,
+  :class:`~cryptography.hazmat.primitives.ciphers.AEADCipherContext`,
+  :class:`~cryptography.hazmat.primitives.ciphers.AEADEncryptionContext`,
+  :class:`~cryptography.hazmat.primitives.ciphers.CipherAlgorithm`, and
+  :class:`~cryptography.hazmat.primitives.ciphers.BlockCipherAlgorithm`
+  were moved from :mod:`~cryptography.hazmat.primitives.interfaces` to
+  :mod:`~cryptography.hazmat.primitives.ciphers`.
+* :class:`~cryptography.hazmat.primitives.ciphers.modes.Mode`,
+  :class:`~cryptography.hazmat.primitives.ciphers.modes.ModeWithInitializationVector`,
+  :class:`~cryptography.hazmat.primitives.ciphers.modes.ModeWithNonce`, and
+  :class:`~cryptography.hazmat.primitives.ciphers.modes.ModeWithAuthenticationTag`
+  were moved from :mod:`~cryptography.hazmat.primitives.interfaces` to
+  :mod:`~cryptography.hazmat.primitives.ciphers.modes`.
+* :class:`~cryptography.hazmat.primitives.padding.PaddingContext` was moved
+  from :mod:`~cryptography.hazmat.primitives.interfaces` to
+  :mod:`~cryptography.hazmat.primitives.padding`.
+*
+  :class:`~cryptography.hazmat.primitives.asymmetric.padding.AsymmetricPadding`
+  was moved from :mod:`~cryptography.hazmat.primitives.interfaces` to
+  :mod:`~cryptography.hazmat.primitives.asymmetric.padding`.
+*
+  :class:`~cryptography.hazmat.primitives.asymmetric.AsymmetricSignatureContext`
+  and
+  :class:`~cryptography.hazmat.primitives.asymmetric.AsymmetricVerificationContext`
+  were moved from :mod:`~cryptography.hazmat.primitives.interfaces` to
+  :mod:`~cryptography.hazmat.primitives.asymmetric`.
 * :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAParameters`,
   :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAParametersWithNumbers`,
   :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey`,
@@ -42,6 +71,7 @@
   :mod:`~cryptography.hazmat.primitives.asymmetric.rsa`.
 * Added support for parsing X.509 names. See the
   :doc:`X.509 documentation</x509>` for more information.
+* Fixed building against LibreSSL, a compile-time substitute for OpenSSL.
 
 0.7.2 - 2015-01-16
 ~~~~~~~~~~~~~~~~~~
diff --git a/docs/hazmat/backends/interfaces.rst b/docs/hazmat/backends/interfaces.rst
index 15d8b98..0ce8f5f 100644
--- a/docs/hazmat/backends/interfaces.rst
+++ b/docs/hazmat/backends/interfaces.rst
@@ -30,10 +30,10 @@
         this backend.
 
         :param cipher: An instance of a
-            :class:`~cryptography.hazmat.primitives.interfaces.CipherAlgorithm`
+            :class:`~cryptography.hazmat.primitives.ciphers.CipherAlgorithm`
             provider.
         :param mode: An instance of a
-            :class:`~cryptography.hazmat.primitives.interfaces.Mode` provider.
+            :class:`~cryptography.hazmat.primitives.ciphers.modes.Mode` provider.
 
         :returns: ``True`` if the specified ``cipher`` and ``mode`` combination
             is supported by this backend, otherwise ``False``
@@ -42,18 +42,18 @@
     .. method:: create_symmetric_encryption_ctx(cipher, mode)
 
         Create a
-        :class:`~cryptography.hazmat.primitives.interfaces.CipherContext` that
+        :class:`~cryptography.hazmat.primitives.ciphers.CipherContext` that
         can be used for encrypting data with the symmetric ``cipher`` using
         the given ``mode``.
 
         :param cipher: An instance of a
-            :class:`~cryptography.hazmat.primitives.interfaces.CipherAlgorithm`
+            :class:`~cryptography.hazmat.primitives.ciphers.CipherAlgorithm`
             provider.
         :param mode: An instance of a
-            :class:`~cryptography.hazmat.primitives.interfaces.Mode` provider.
+            :class:`~cryptography.hazmat.primitives.ciphers.modes.Mode` provider.
 
         :returns:
-            :class:`~cryptography.hazmat.primitives.interfaces.CipherContext`
+            :class:`~cryptography.hazmat.primitives.ciphers.CipherContext`
 
         :raises ValueError: When tag is not None in an AEAD mode
 
@@ -61,18 +61,18 @@
     .. method:: create_symmetric_decryption_ctx(cipher, mode)
 
         Create a
-        :class:`~cryptography.hazmat.primitives.interfaces.CipherContext` that
+        :class:`~cryptography.hazmat.primitives.ciphers.CipherContext` that
         can be used for decrypting data with the symmetric ``cipher`` using
         the given ``mode``.
 
         :param cipher: An instance of a
-            :class:`~cryptography.hazmat.primitives.interfaces.CipherAlgorithm`
+            :class:`~cryptography.hazmat.primitives.ciphers.CipherAlgorithm`
             provider.
         :param mode: An instance of a
-            :class:`~cryptography.hazmat.primitives.interfaces.Mode` provider.
+            :class:`~cryptography.hazmat.primitives.ciphers.modes.Mode` provider.
 
         :returns:
-            :class:`~cryptography.hazmat.primitives.interfaces.CipherContext`
+            :class:`~cryptography.hazmat.primitives.ciphers.CipherContext`
 
         :raises ValueError: When tag is None in an AEAD mode
 
@@ -157,7 +157,7 @@
     .. method:: cmac_algorithm_supported(algorithm)
 
         :param algorithm: An instance of a
-            :class:`~cryptography.hazmat.primitives.interfaces.BlockCipherAlgorithm`
+            :class:`~cryptography.hazmat.primitives.ciphers.BlockCipherAlgorithm`
             provider.
         :return: Returns True if the block cipher is supported for CMAC by this backend
 
@@ -168,7 +168,7 @@
         uses the specified ``algorithm`` to calculate a message authentication code.
 
         :param algorithm: An instance of a
-            :class:`~cryptography.hazmat.primitives.interfaces.BlockCipherAlgorithm`
+            :class:`~cryptography.hazmat.primitives.ciphers.BlockCipherAlgorithm`
             provider.
 
         :returns:
@@ -244,7 +244,7 @@
         Check if the specified ``padding`` is supported by the backend.
 
         :param padding: An instance of an
-            :class:`~cryptography.hazmat.primitives.interfaces.AsymmetricPadding`
+            :class:`~cryptography.hazmat.primitives.asymmetric.padding.AsymmetricPadding`
             provider.
 
         :returns: ``True`` if the specified ``padding`` is supported by this
diff --git a/docs/hazmat/backends/openssl.rst b/docs/hazmat/backends/openssl.rst
index 6c3d875..4e0f628 100644
--- a/docs/hazmat/backends/openssl.rst
+++ b/docs/hazmat/backends/openssl.rst
@@ -80,4 +80,4 @@
 .. _`OpenSSL`: https://www.openssl.org/
 .. _`initializing the RNG`: https://en.wikipedia.org/wiki/OpenSSL#Predictable_keys_.28Debian-specific.29
 .. _`Yarrow`: https://en.wikipedia.org/wiki/Yarrow_algorithm
-.. _`Microsoft documentation`: http://msdn.microsoft.com/en-us/library/windows/desktop/aa379942(v=vs.85).aspx
+.. _`Microsoft documentation`: https://msdn.microsoft.com/en-us/library/windows/desktop/aa379942(v=vs.85).aspx
diff --git a/docs/hazmat/primitives/asymmetric/dsa.rst b/docs/hazmat/primitives/asymmetric/dsa.rst
index 36bc801..3a47da4 100644
--- a/docs/hazmat/primitives/asymmetric/dsa.rst
+++ b/docs/hazmat/primitives/asymmetric/dsa.rst
@@ -275,7 +275,7 @@
             provider.
 
         :returns:
-            :class:`~cryptography.hazmat.primitives.interfaces.AsymmetricSignatureContext`
+            :class:`~cryptography.hazmat.primitives.asymmetric.AsymmetricSignatureContext`
 
     .. attribute:: key_size
 
@@ -338,7 +338,7 @@
             provider.
 
         :returns:
-            :class:`~cryptography.hazmat.primitives.interfaces.AsymmetricVerificationContext`
+            :class:`~cryptography.hazmat.primitives.asymmetric.AsymmetricVerificationContext`
 
 
 .. class:: DSAPublicKeyWithNumbers
diff --git a/docs/hazmat/primitives/asymmetric/ec.rst b/docs/hazmat/primitives/asymmetric/ec.rst
index 5b11471..8b9a584 100644
--- a/docs/hazmat/primitives/asymmetric/ec.rst
+++ b/docs/hazmat/primitives/asymmetric/ec.rst
@@ -304,7 +304,7 @@
             :class:`EllipticCurveSignatureAlgorithm` provider.
 
         :returns:
-            :class:`~cryptography.hazmat.primitives.interfaces.AsymmetricSignatureContext`
+            :class:`~cryptography.hazmat.primitives.asymmetric.AsymmetricSignatureContext`
 
     .. method:: public_key()
 
@@ -344,7 +344,7 @@
             :class:`EllipticCurveSignatureAlgorithm` provider.
 
         :returns:
-            :class:`~cryptography.hazmat.primitives.interfaces.AsymmetricSignatureContext`
+            :class:`~cryptography.hazmat.primitives.asymmetric.AsymmetricVerificationContext`
 
      .. attribute:: curve
 
@@ -370,7 +370,7 @@
 .. _`FIPS 186-4`: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf
 .. _`some concern`: https://crypto.stackexchange.com/questions/10263/should-we-trust-the-nist-recommended-ecc-parameters
 .. _`less than 224 bits`: http://www.ecrypt.eu.org/documents/D.SPA.20.pdf
-.. _`64x lower computational cost than DH`: http://www.nsa.gov/business/programs/elliptic_curve.shtml
+.. _`64x lower computational cost than DH`: https://www.nsa.gov/business/programs/elliptic_curve.shtml
 .. _`minimize the number of security concerns for elliptic-curve cryptography`: http://cr.yp.to/ecdh/curve25519-20060209.pdf
 .. _`SafeCurves`: http://safecurves.cr.yp.to/
 .. _`ECDSA`: https://en.wikipedia.org/wiki/ECDSA
diff --git a/docs/hazmat/primitives/asymmetric/index.rst b/docs/hazmat/primitives/asymmetric/index.rst
index 43761fd..59f00c5 100644
--- a/docs/hazmat/primitives/asymmetric/index.rst
+++ b/docs/hazmat/primitives/asymmetric/index.rst
@@ -30,6 +30,8 @@
     ec
     rsa
     serialization
+    interfaces
     utils
 
+
 .. _`proof of identity`: https://en.wikipedia.org/wiki/Public-key_infrastructure
diff --git a/docs/hazmat/primitives/asymmetric/interfaces.rst b/docs/hazmat/primitives/asymmetric/interfaces.rst
new file mode 100644
index 0000000..4932faa
--- /dev/null
+++ b/docs/hazmat/primitives/asymmetric/interfaces.rst
@@ -0,0 +1,33 @@
+.. hazmat::
+
+.. module:: cryptography.hazmat.primitives.asymmetric
+
+Signature Interfaces
+====================
+
+.. class:: AsymmetricSignatureContext
+
+    .. versionadded:: 0.2
+
+    .. method:: update(data)
+
+        :param bytes data: The data you want to sign.
+
+    .. method:: finalize()
+
+        :return bytes signature: The signature.
+
+
+.. class:: AsymmetricVerificationContext
+
+    .. versionadded:: 0.2
+
+    .. method:: update(data)
+
+        :param bytes data: The data you wish to verify using the signature.
+
+    .. method:: verify()
+
+        :raises cryptography.exceptions.InvalidSignature: If the signature does
+            not validate.
+
diff --git a/docs/hazmat/primitives/asymmetric/rsa.rst b/docs/hazmat/primitives/asymmetric/rsa.rst
index 4855a45..fd97d75 100644
--- a/docs/hazmat/primitives/asymmetric/rsa.rst
+++ b/docs/hazmat/primitives/asymmetric/rsa.rst
@@ -186,7 +186,13 @@
 Padding
 ~~~~~~~
 
-.. currentmodule:: cryptography.hazmat.primitives.asymmetric.padding
+.. module:: cryptography.hazmat.primitives.asymmetric.padding
+
+.. class:: AsymmetricPadding
+
+    .. versionadded:: 0.2
+
+    .. attribute:: name
 
 .. class:: PSS(mgf, salt_length)
 
@@ -425,7 +431,7 @@
         Sign data which can be verified later by others using the public key.
 
         :param padding: An instance of a
-            :class:`~cryptography.hazmat.primitives.interfaces.AsymmetricPadding`
+            :class:`~cryptography.hazmat.primitives.asymmetric.padding.AsymmetricPadding`
             provider.
 
         :param algorithm: An instance of a
@@ -433,7 +439,7 @@
             provider.
 
         :returns:
-            :class:`~cryptography.hazmat.primitives.interfaces.AsymmetricSignatureContext`
+            :class:`~cryptography.hazmat.primitives.asymmetric.AsymmetricSignatureContext`
 
     .. method:: decrypt(ciphertext, padding)
 
@@ -444,7 +450,7 @@
         :param bytes ciphertext: The ciphertext to decrypt.
 
         :param padding: An instance of an
-            :class:`~cryptography.hazmat.primitives.interfaces.AsymmetricPadding`
+            :class:`~cryptography.hazmat.primitives.asymmetric.padding.AsymmetricPadding`
             provider.
 
         :return bytes: Decrypted data.
@@ -495,7 +501,7 @@
         :param bytes signature: The signature to verify.
 
         :param padding: An instance of a
-            :class:`~cryptography.hazmat.primitives.interfaces.AsymmetricPadding`
+            :class:`~cryptography.hazmat.primitives.asymmetric.padding.AsymmetricPadding`
             provider.
 
         :param algorithm: An instance of a
@@ -503,7 +509,7 @@
             provider.
 
         :returns:
-            :class:`~cryptography.hazmat.primitives.interfaces.AsymmetricVerificationContext`
+            :class:`~cryptography.hazmat.primitives.asymmetric.AsymmetricVerificationContext`
 
     .. method:: encrypt(plaintext, padding)
 
@@ -514,7 +520,7 @@
         :param bytes plaintext: The plaintext to encrypt.
 
         :param padding: An instance of a
-            :class:`~cryptography.hazmat.primitives.interfaces.AsymmetricPadding`
+            :class:`~cryptography.hazmat.primitives.asymmetric.padding.AsymmetricPadding`
             provider.
 
         :return bytes: Encrypted data.
diff --git a/docs/hazmat/primitives/interfaces.rst b/docs/hazmat/primitives/interfaces.rst
index 86a3a7e..f58d324 100644
--- a/docs/hazmat/primitives/interfaces.rst
+++ b/docs/hazmat/primitives/interfaces.rst
@@ -14,130 +14,14 @@
 .. _`Abstract Base Classes`: https://docs.python.org/3/library/abc.html
 
 
-Symmetric ciphers
------------------
-
-.. class:: CipherAlgorithm
-
-    A named symmetric encryption algorithm.
-
-    .. attribute:: name
-
-        :type: str
-
-        The standard name for the mode, for example, "AES", "Camellia", or
-        "Blowfish".
-
-    .. attribute:: key_size
-
-        :type: int
-
-        The number of bits in the key being used.
-
-
-.. class:: BlockCipherAlgorithm
-
-    A block cipher algorithm.
-
-    .. attribute:: block_size
-
-        :type: int
-
-        The number of bits in a block.
-
-
-Cipher modes
-~~~~~~~~~~~~
-
-Interfaces used by the symmetric cipher modes described in
-:ref:`Symmetric Encryption Modes <symmetric-encryption-modes>`.
-
-.. class:: Mode
-
-    A named cipher mode.
-
-    .. attribute:: name
-
-        :type: str
-
-        This should be the standard shorthand name for the mode, for example
-        Cipher-Block Chaining mode is "CBC".
-
-        The name may be used by a backend to influence the operation of a
-        cipher in conjunction with the algorithm's name.
-
-    .. method:: validate_for_algorithm(algorithm)
-
-        :param CipherAlgorithm algorithm:
-
-        Checks that the combination of this mode with the provided algorithm
-        meets any necessary invariants. This should raise an exception if they
-        are not met.
-
-        For example, the
-        :class:`~cryptography.hazmat.primitives.ciphers.modes.CBC` mode uses
-        this method to check that the provided initialization vector's length
-        matches the block size of the algorithm.
-
-
-.. class:: ModeWithInitializationVector
-
-    A cipher mode with an initialization vector.
-
-    .. attribute:: initialization_vector
-
-        :type: bytes
-
-        Exact requirements of the initialization are described by the
-        documentation of individual modes.
-
-
-.. class:: ModeWithNonce
-
-    A cipher mode with a nonce.
-
-    .. attribute:: nonce
-
-        :type: bytes
-
-        Exact requirements of the nonce are described by the documentation of
-        individual modes.
-
 Asymmetric interfaces
 ---------------------
 
-.. class:: AsymmetricSignatureContext
+In 0.8 the asymmetric signature and verification interfaces were moved to the
+:mod:`cryptography.hazmat.primitives.asymmetric` module.
 
-    .. versionadded:: 0.2
-
-    .. method:: update(data)
-
-        :param bytes data: The data you want to sign.
-
-    .. method:: finalize()
-
-        :return bytes signature: The signature.
-
-
-.. class:: AsymmetricVerificationContext
-
-    .. versionadded:: 0.2
-
-    .. method:: update(data)
-
-        :param bytes data: The data you wish to verify using the signature.
-
-    .. method:: verify()
-
-        :raises cryptography.exceptions.InvalidSignature: If the signature does
-            not validate.
-
-
-.. class:: AsymmetricPadding
-
-    .. versionadded:: 0.2
-
-    .. attribute:: name
+In 0.8 the asymmetric padding interface was moved to the
+:mod:`cryptography.hazmat.primitives.asymmetric.padding` module.
 
 DSA
 ~~~
@@ -163,46 +47,8 @@
 Key derivation functions
 ------------------------
 
-.. class:: KeyDerivationFunction
-
-    .. versionadded:: 0.2
-
-    .. method:: derive(key_material)
-
-        :param bytes key_material: The input key material. Depending on what
-                                   key derivation function you are using this
-                                   could be either random bytes, or a user
-                                   supplied password.
-        :return: The new key.
-        :raises cryptography.exceptions.AlreadyFinalized: This is raised when
-                                                          :meth:`derive` or
-                                                          :meth:`verify` is
-                                                          called more than
-                                                          once.
-
-        This generates and returns a new key from the supplied key material.
-
-    .. method:: verify(key_material, expected_key)
-
-        :param bytes key_material: The input key material. This is the same as
-                                   ``key_material`` in :meth:`derive`.
-        :param bytes expected_key: The expected result of deriving a new key,
-                                   this is the same as the return value of
-                                   :meth:`derive`.
-        :raises cryptography.exceptions.InvalidKey: This is raised when the
-                                                    derived key does not match
-                                                    the expected key.
-        :raises cryptography.exceptions.AlreadyFinalized: This is raised when
-                                                          :meth:`derive` or
-                                                          :meth:`verify` is
-                                                          called more than
-                                                          once.
-
-        This checks whether deriving a new key from the supplied
-        ``key_material`` generates the same key as the ``expected_key``, and
-        raises an exception if they do not match. This can be used for
-        something like checking whether a user's password attempt matches the
-        stored derived key.
+In 0.8 the key derivation function interface was moved to the
+:mod:`cryptography.hazmat.primitives.kdf` module.
 
 
 `Message Authentication Code`_
diff --git a/docs/hazmat/primitives/key-derivation-functions.rst b/docs/hazmat/primitives/key-derivation-functions.rst
index 4a47159..78d4031 100644
--- a/docs/hazmat/primitives/key-derivation-functions.rst
+++ b/docs/hazmat/primitives/key-derivation-functions.rst
@@ -3,7 +3,7 @@
 Key derivation functions
 ========================
 
-.. currentmodule:: cryptography.hazmat.primitives.kdf
+.. module:: cryptography.hazmat.primitives.kdf
 
 Key derivation functions derive bytes suitable for cryptographic operations
 from passwords or other data sources using a pseudo-random function (PRF).
@@ -38,7 +38,7 @@
     considered a better solution.
 
     This class conforms to the
-    :class:`~cryptography.hazmat.primitives.interfaces.KeyDerivationFunction`
+    :class:`~cryptography.hazmat.primitives.kdf.KeyDerivationFunction`
     interface.
 
     .. doctest::
@@ -324,6 +324,53 @@
         ``key_material`` generates the same key as the ``expected_key``, and
         raises an exception if they do not match.
 
+Interface
+~~~~~~~~~
+
+.. currentmodule:: cryptography.hazmat.primitives.kdf
+
+.. class:: KeyDerivationFunction
+
+    .. versionadded:: 0.2
+
+    .. method:: derive(key_material)
+
+        :param bytes key_material: The input key material. Depending on what
+                                   key derivation function you are using this
+                                   could be either random bytes, or a user
+                                   supplied password.
+        :return: The new key.
+        :raises cryptography.exceptions.AlreadyFinalized: This is raised when
+                                                          :meth:`derive` or
+                                                          :meth:`verify` is
+                                                          called more than
+                                                          once.
+
+        This generates and returns a new key from the supplied key material.
+
+    .. method:: verify(key_material, expected_key)
+
+        :param bytes key_material: The input key material. This is the same as
+                                   ``key_material`` in :meth:`derive`.
+        :param bytes expected_key: The expected result of deriving a new key,
+                                   this is the same as the return value of
+                                   :meth:`derive`.
+        :raises cryptography.exceptions.InvalidKey: This is raised when the
+                                                    derived key does not match
+                                                    the expected key.
+        :raises cryptography.exceptions.AlreadyFinalized: This is raised when
+                                                          :meth:`derive` or
+                                                          :meth:`verify` is
+                                                          called more than
+                                                          once.
+
+        This checks whether deriving a new key from the supplied
+        ``key_material`` generates the same key as the ``expected_key``, and
+        raises an exception if they do not match. This can be used for
+        something like checking whether a user's password attempt matches the
+        stored derived key.
+
+
 .. _`NIST SP 800-132`: http://csrc.nist.gov/publications/nistpubs/800-132/nist-sp800-132.pdf
 .. _`Password Storage Cheat Sheet`: https://www.owasp.org/index.php/Password_Storage_Cheat_Sheet
 .. _`PBKDF2`: https://en.wikipedia.org/wiki/PBKDF2
diff --git a/docs/hazmat/primitives/mac/cmac.rst b/docs/hazmat/primitives/mac/cmac.rst
index 1ba1b3f..e04a849 100644
--- a/docs/hazmat/primitives/mac/cmac.rst
+++ b/docs/hazmat/primitives/mac/cmac.rst
@@ -22,7 +22,7 @@
     .. versionadded:: 0.4
 
     CMAC objects take a
-    :class:`~cryptography.hazmat.primitives.interfaces.BlockCipherAlgorithm` provider.
+    :class:`~cryptography.hazmat.primitives.ciphers.BlockCipherAlgorithm` provider.
 
     .. doctest::
 
@@ -39,7 +39,7 @@
     raised.
 
     If ``algorithm`` isn't a
-    :class:`~cryptography.hazmat.primitives.interfaces.BlockCipherAlgorithm`
+    :class:`~cryptography.hazmat.primitives.ciphers.BlockCipherAlgorithm`
     provider then ``TypeError`` will be raised.
 
     To check that a given signature is correct use the :meth:`verify` method.
@@ -55,13 +55,13 @@
         cryptography.exceptions.InvalidSignature: Signature did not match digest.
 
     :param algorithm: An
-        :class:`~cryptography.hazmat.primitives.interfaces.BlockCipherAlgorithm`
+        :class:`~cryptography.hazmat.primitives.ciphers.BlockCipherAlgorithm`
         provider.
     :param backend: An
         :class:`~cryptography.hazmat.backends.interfaces.CMACBackend`
         provider.
     :raises TypeError: This is raised if the provided ``algorithm`` is not an instance of
-        :class:`~cryptography.hazmat.primitives.interfaces.BlockCipherAlgorithm`
+        :class:`~cryptography.hazmat.primitives.ciphers.BlockCipherAlgorithm`
     :raises cryptography.exceptions.UnsupportedAlgorithm: This is raised if the
         provided ``backend`` does not implement
         :class:`~cryptography.hazmat.backends.interfaces.CMACBackend`
diff --git a/docs/hazmat/primitives/padding.rst b/docs/hazmat/primitives/padding.rst
index 0322f9d..a60f5ac 100644
--- a/docs/hazmat/primitives/padding.rst
+++ b/docs/hazmat/primitives/padding.rst
@@ -3,7 +3,7 @@
 Padding
 =======
 
-.. currentmodule:: cryptography.hazmat.primitives.padding
+.. module:: cryptography.hazmat.primitives.padding
 
 Padding is a way to take data that may or may not be a multiple of the block
 size for a cipher and extend it out so that it is. This is required for many
@@ -44,18 +44,16 @@
     .. method:: padder()
 
         :returns: A padding
-            :class:`~cryptography.hazmat.primitives.interfaces.PaddingContext`
+            :class:`~cryptography.hazmat.primitives.padding.PaddingContext`
             provider.
 
     .. method:: unpadder()
 
         :returns: An unpadding
-            :class:`~cryptography.hazmat.primitives.interfaces.PaddingContext`
+            :class:`~cryptography.hazmat.primitives.padding.PaddingContext`
             provider.
 
 
-.. currentmodule:: cryptography.hazmat.primitives.interfaces
-
 .. class:: PaddingContext
 
     When calling ``padder()`` or ``unpadder()`` the result will conform to the
diff --git a/docs/hazmat/primitives/symmetric-encryption.rst b/docs/hazmat/primitives/symmetric-encryption.rst
index b2ce376..0f7e037 100644
--- a/docs/hazmat/primitives/symmetric-encryption.rst
+++ b/docs/hazmat/primitives/symmetric-encryption.rst
@@ -4,7 +4,7 @@
 Symmetric encryption
 ====================
 
-.. currentmodule:: cryptography.hazmat.primitives.ciphers
+.. module:: cryptography.hazmat.primitives.ciphers
 
 
 Symmetric encryption is a way to `encrypt`_ or hide the contents of material
@@ -43,10 +43,10 @@
         'a secret message'
 
     :param algorithms: A
-        :class:`~cryptography.hazmat.primitives.interfaces.CipherAlgorithm`
+        :class:`~cryptography.hazmat.primitives.ciphers.CipherAlgorithm`
         provider such as those described
         :ref:`below <symmetric-encryption-algorithms>`.
-    :param mode: A :class:`~cryptography.hazmat.primitives.interfaces.Mode`
+    :param mode: A :class:`~cryptography.hazmat.primitives.ciphers.modes.Mode`
         provider such as those described
         :ref:`below <symmetric-encryption-modes>`.
     :param backend: A
@@ -60,7 +60,7 @@
     .. method:: encryptor()
 
         :return: An encrypting
-            :class:`~cryptography.hazmat.primitives.interfaces.CipherContext`
+            :class:`~cryptography.hazmat.primitives.ciphers.CipherContext`
             provider.
 
         If the backend doesn't support the requested combination of ``cipher``
@@ -70,7 +70,7 @@
     .. method:: decryptor()
 
         :return: A decrypting
-            :class:`~cryptography.hazmat.primitives.interfaces.CipherContext`
+            :class:`~cryptography.hazmat.primitives.ciphers.CipherContext`
             provider.
 
         If the backend doesn't support the requested combination of ``cipher``
@@ -193,7 +193,7 @@
 Modes
 ~~~~~
 
-.. currentmodule:: cryptography.hazmat.primitives.ciphers.modes
+.. module:: cryptography.hazmat.primitives.ciphers.modes
 
 .. class:: CBC(initialization_vector)
 
@@ -293,7 +293,7 @@
     .. danger::
 
         When using this mode you **must** not use the decrypted data until
-        :meth:`~cryptography.hazmat.primitives.interfaces.CipherContext.finalize`
+        :meth:`~cryptography.hazmat.primitives.ciphers.CipherContext.finalize`
         has been called. GCM provides **no** guarantees of ciphertext integrity
         until decryption is complete.
 
@@ -422,7 +422,8 @@
 
 Interfaces
 ----------
-.. currentmodule:: cryptography.hazmat.primitives.interfaces
+
+.. currentmodule:: cryptography.hazmat.primitives.ciphers
 
 .. class:: CipherContext
 
@@ -505,13 +506,110 @@
         :raises: :class:`~cryptography.exceptions.NotYetFinalized` if called
             before the context is finalized.
 
+.. class:: CipherAlgorithm
+
+    A named symmetric encryption algorithm.
+
+    .. attribute:: name
+
+        :type: str
+
+        The standard name for the mode, for example, "AES", "Camellia", or
+        "Blowfish".
+
+    .. attribute:: key_size
+
+        :type: int
+
+        The number of bits in the key being used.
+
+
+.. class:: BlockCipherAlgorithm
+
+    A block cipher algorithm.
+
+    .. attribute:: block_size
+
+        :type: int
+
+        The number of bits in a block.
+
+Interfaces used by the symmetric cipher modes described in
+:ref:`Symmetric Encryption Modes <symmetric-encryption-modes>`.
+
+.. currentmodule:: cryptography.hazmat.primitives.ciphers.modes
+
+.. class:: Mode
+
+    A named cipher mode.
+
+    .. attribute:: name
+
+        :type: str
+
+        This should be the standard shorthand name for the mode, for example
+        Cipher-Block Chaining mode is "CBC".
+
+        The name may be used by a backend to influence the operation of a
+        cipher in conjunction with the algorithm's name.
+
+    .. method:: validate_for_algorithm(algorithm)
+
+        :param CipherAlgorithm algorithm:
+
+        Checks that the combination of this mode with the provided algorithm
+        meets any necessary invariants. This should raise an exception if they
+        are not met.
+
+        For example, the
+        :class:`~cryptography.hazmat.primitives.ciphers.modes.CBC` mode uses
+        this method to check that the provided initialization vector's length
+        matches the block size of the algorithm.
+
+
+.. class:: ModeWithInitializationVector
+
+    A cipher mode with an initialization vector.
+
+    .. attribute:: initialization_vector
+
+        :type: bytes
+
+        Exact requirements of the initialization are described by the
+        documentation of individual modes.
+
+
+.. class:: ModeWithNonce
+
+    A cipher mode with a nonce.
+
+    .. attribute:: nonce
+
+        :type: bytes
+
+        Exact requirements of the nonce are described by the documentation of
+        individual modes.
+
+
+.. class:: ModeWithAuthenticationTag
+
+    A cipher mode with an authentication tag.
+
+    .. attribute:: tag
+
+        :type: bytes
+
+        Exact requirements of the tag are described by the documentation of
+        individual modes.
+
+
 
 .. _`described by Colin Percival`: http://www.daemonology.net/blog/2009-06-11-cryptographic-right-answers.html
 .. _`recommends a 96-bit IV length`: http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-spec.pdf
 .. _`NIST SP-800-38D`: http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf
-.. _`Communications Security Establishment`: http://www.cse-cst.gc.ca
-.. _`encrypt`: https://ssd.eff.org/tech/encryption
+.. _`Communications Security Establishment`: https://www.cse-cst.gc.ca
+.. _`encrypt`: https://ssd.eff.org/en/module/what-encryption
 .. _`CRYPTREC`: http://www.cryptrec.go.jp/english/
-.. _`significant patterns in the output`: https://en.wikipedia.org/wiki/Cipher_block_chaining#Electronic_codebook_.28ECB.29
+.. _`significant patterns in the output`: https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Electronic_Codebook_.28ECB.29
 .. _`International Data Encryption Algorithm`: https://en.wikipedia.org/wiki/International_Data_Encryption_Algorithm
 .. _`OpenPGP`: http://www.openpgp.org
diff --git a/src/cryptography/hazmat/backends/commoncrypto/ciphers.py b/src/cryptography/hazmat/backends/commoncrypto/ciphers.py
index 7e537db..1ce8aec 100644
--- a/src/cryptography/hazmat/backends/commoncrypto/ciphers.py
+++ b/src/cryptography/hazmat/backends/commoncrypto/ciphers.py
@@ -8,13 +8,14 @@
 from cryptography.exceptions import (
     InvalidTag, UnsupportedAlgorithm, _Reasons
 )
-from cryptography.hazmat.primitives import constant_time, interfaces
+from cryptography.hazmat.primitives import ciphers, constant_time
+from cryptography.hazmat.primitives.ciphers import modes
 from cryptography.hazmat.primitives.ciphers.modes import (
     CFB, CFB8, CTR, OFB
 )
 
 
-@utils.register_interface(interfaces.CipherContext)
+@utils.register_interface(ciphers.CipherContext)
 class _CipherContext(object):
     def __init__(self, backend, cipher, mode, operation):
         self._backend = backend
@@ -31,7 +32,7 @@
         # treat RC4 and other stream cipher block sizes).
         # This bug has been filed as rdar://15589470
         self._bytes_processed = 0
-        if (isinstance(cipher, interfaces.BlockCipherAlgorithm) and not
+        if (isinstance(cipher, ciphers.BlockCipherAlgorithm) and not
                 isinstance(mode, (OFB, CFB, CFB8, CTR))):
             self._byte_block_size = cipher.block_size // 8
         else:
@@ -51,9 +52,9 @@
         ctx = self._backend._ffi.new("CCCryptorRef *")
         ctx = self._backend._ffi.gc(ctx, self._backend._release_cipher_ctx)
 
-        if isinstance(mode, interfaces.ModeWithInitializationVector):
+        if isinstance(mode, modes.ModeWithInitializationVector):
             iv_nonce = mode.initialization_vector
-        elif isinstance(mode, interfaces.ModeWithNonce):
+        elif isinstance(mode, modes.ModeWithNonce):
             iv_nonce = mode.nonce
         else:
             iv_nonce = self._backend._ffi.NULL
@@ -101,8 +102,8 @@
         return self._backend._ffi.buffer(buf)[:outlen[0]]
 
 
-@utils.register_interface(interfaces.AEADCipherContext)
-@utils.register_interface(interfaces.AEADEncryptionContext)
+@utils.register_interface(ciphers.AEADCipherContext)
+@utils.register_interface(ciphers.AEADEncryptionContext)
 class _GCMCipherContext(object):
     def __init__(self, backend, cipher, mode, operation):
         self._backend = backend
diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py
index 75d7e32..8441e89 100644
--- a/src/cryptography/hazmat/backends/openssl/backend.py
+++ b/src/cryptography/hazmat/backends/openssl/backend.py
@@ -225,8 +225,8 @@
         )
 
     def create_symmetric_encryption_ctx(self, cipher, mode):
-        if (isinstance(mode, CTR) and isinstance(cipher, AES)
-                and not self._evp_cipher_supported(cipher, mode)):
+        if (isinstance(mode, CTR) and isinstance(cipher, AES) and
+                not self._evp_cipher_supported(cipher, mode)):
             # This is needed to provide support for AES CTR mode in OpenSSL
             # 0.9.8. It can be removed when we drop 0.9.8 support (RHEL 5
             # extended life ends 2020).
@@ -235,8 +235,8 @@
             return _CipherContext(self, cipher, mode, _CipherContext._ENCRYPT)
 
     def create_symmetric_decryption_ctx(self, cipher, mode):
-        if (isinstance(mode, CTR) and isinstance(cipher, AES)
-                and not self._evp_cipher_supported(cipher, mode)):
+        if (isinstance(mode, CTR) and isinstance(cipher, AES) and
+                not self._evp_cipher_supported(cipher, mode)):
             # This is needed to provide support for AES CTR mode in OpenSSL
             # 0.9.8. It can be removed when we drop 0.9.8 support (RHEL 5
             # extended life ends 2020).
@@ -671,9 +671,10 @@
 
     def cmac_algorithm_supported(self, algorithm):
         return (
-            self._lib.Cryptography_HAS_CMAC == 1
-            and self.cipher_supported(algorithm, CBC(
-                b"\x00" * algorithm.block_size))
+            self._lib.Cryptography_HAS_CMAC == 1 and
+            self.cipher_supported(
+                algorithm, CBC(b"\x00" * algorithm.block_size)
+            )
         )
 
     def create_cmac_ctx(self, algorithm):
diff --git a/src/cryptography/hazmat/backends/openssl/ciphers.py b/src/cryptography/hazmat/backends/openssl/ciphers.py
index d665f36..64097c7 100644
--- a/src/cryptography/hazmat/backends/openssl/ciphers.py
+++ b/src/cryptography/hazmat/backends/openssl/ciphers.py
@@ -6,13 +6,13 @@
 
 from cryptography import utils
 from cryptography.exceptions import InvalidTag, UnsupportedAlgorithm, _Reasons
-from cryptography.hazmat.primitives import interfaces
-from cryptography.hazmat.primitives.ciphers.modes import GCM
+from cryptography.hazmat.primitives import ciphers
+from cryptography.hazmat.primitives.ciphers import modes
 
 
-@utils.register_interface(interfaces.CipherContext)
-@utils.register_interface(interfaces.AEADCipherContext)
-@utils.register_interface(interfaces.AEADEncryptionContext)
+@utils.register_interface(ciphers.CipherContext)
+@utils.register_interface(ciphers.AEADCipherContext)
+@utils.register_interface(ciphers.AEADEncryptionContext)
 class _CipherContext(object):
     _ENCRYPT = 1
     _DECRYPT = 0
@@ -24,7 +24,7 @@
         self._operation = operation
         self._tag = None
 
-        if isinstance(self._cipher, interfaces.BlockCipherAlgorithm):
+        if isinstance(self._cipher, ciphers.BlockCipherAlgorithm):
             self._block_size = self._cipher.block_size
         else:
             self._block_size = 1
@@ -54,9 +54,9 @@
                 _Reasons.UNSUPPORTED_CIPHER
             )
 
-        if isinstance(mode, interfaces.ModeWithInitializationVector):
+        if isinstance(mode, modes.ModeWithInitializationVector):
             iv_nonce = mode.initialization_vector
-        elif isinstance(mode, interfaces.ModeWithNonce):
+        elif isinstance(mode, modes.ModeWithNonce):
             iv_nonce = mode.nonce
         else:
             iv_nonce = self._backend._ffi.NULL
@@ -72,7 +72,7 @@
             ctx, len(cipher.key)
         )
         assert res != 0
-        if isinstance(mode, GCM):
+        if isinstance(mode, modes.GCM):
             res = self._backend._lib.EVP_CIPHER_CTX_ctrl(
                 ctx, self._backend._lib.EVP_CTRL_GCM_SET_IVLEN,
                 len(iv_nonce), self._backend._ffi.NULL
@@ -107,7 +107,7 @@
         # should be taken only when length is zero and mode is not GCM because
         # AES GCM can return improper tag values if you don't call update
         # with empty plaintext when authenticating AAD for ...reasons.
-        if len(data) == 0 and not isinstance(self._mode, GCM):
+        if len(data) == 0 and not isinstance(self._mode, modes.GCM):
             return b""
 
         buf = self._backend._ffi.new("unsigned char[]",
@@ -124,7 +124,7 @@
         # even if you are only using authenticate_additional_data or the
         # GCM tag will be wrong. An (empty) call to update resolves this
         # and is harmless for all other versions of OpenSSL.
-        if isinstance(self._mode, GCM):
+        if isinstance(self._mode, modes.GCM):
             self.update(b"")
 
         buf = self._backend._ffi.new("unsigned char[]", self._block_size)
@@ -133,7 +133,7 @@
         if res == 0:
             errors = self._backend._consume_errors()
 
-            if not errors and isinstance(self._mode, GCM):
+            if not errors and isinstance(self._mode, modes.GCM):
                 raise InvalidTag
 
             assert errors
@@ -154,7 +154,7 @@
             else:
                 raise self._backend._unknown_error(errors[0])
 
-        if (isinstance(self._mode, GCM) and
+        if (isinstance(self._mode, modes.GCM) and
            self._operation == self._ENCRYPT):
             block_byte_size = self._block_size // 8
             tag_buf = self._backend._ffi.new(
@@ -181,7 +181,7 @@
     tag = utils.read_only_property("_tag")
 
 
-@utils.register_interface(interfaces.CipherContext)
+@utils.register_interface(ciphers.CipherContext)
 class _AESCTRCipherContext(object):
     """
     This is needed to provide support for AES CTR mode in OpenSSL 0.9.8. It can
diff --git a/src/cryptography/hazmat/backends/openssl/dsa.py b/src/cryptography/hazmat/backends/openssl/dsa.py
index 9488e26..d2972e4 100644
--- a/src/cryptography/hazmat/backends/openssl/dsa.py
+++ b/src/cryptography/hazmat/backends/openssl/dsa.py
@@ -7,8 +7,10 @@
 from cryptography import utils
 from cryptography.exceptions import InvalidSignature
 from cryptography.hazmat.backends.openssl.utils import _truncate_digest
-from cryptography.hazmat.primitives import hashes, interfaces
-from cryptography.hazmat.primitives.asymmetric import dsa
+from cryptography.hazmat.primitives import hashes
+from cryptography.hazmat.primitives.asymmetric import (
+    AsymmetricSignatureContext, AsymmetricVerificationContext, dsa
+)
 from cryptography.hazmat.primitives.interfaces import (
     DSAParametersWithNumbers, DSAPrivateKeyWithNumbers, DSAPublicKeyWithNumbers
 )
@@ -27,7 +29,7 @@
     return _truncate_digest(digest, order_bits)
 
 
-@utils.register_interface(interfaces.AsymmetricVerificationContext)
+@utils.register_interface(AsymmetricVerificationContext)
 class _DSAVerificationContext(object):
     def __init__(self, backend, public_key, signature, algorithm):
         self._backend = backend
@@ -61,7 +63,7 @@
             raise InvalidSignature
 
 
-@utils.register_interface(interfaces.AsymmetricSignatureContext)
+@utils.register_interface(AsymmetricSignatureContext)
 class _DSASignatureContext(object):
     def __init__(self, backend, private_key, algorithm):
         self._backend = backend
diff --git a/src/cryptography/hazmat/backends/openssl/ec.py b/src/cryptography/hazmat/backends/openssl/ec.py
index d050c6b..52c93da 100644
--- a/src/cryptography/hazmat/backends/openssl/ec.py
+++ b/src/cryptography/hazmat/backends/openssl/ec.py
@@ -9,8 +9,10 @@
     InvalidSignature, UnsupportedAlgorithm, _Reasons
 )
 from cryptography.hazmat.backends.openssl.utils import _truncate_digest
-from cryptography.hazmat.primitives import hashes, interfaces
-from cryptography.hazmat.primitives.asymmetric import ec
+from cryptography.hazmat.primitives import hashes
+from cryptography.hazmat.primitives.asymmetric import (
+    AsymmetricSignatureContext, AsymmetricVerificationContext, ec
+)
 
 
 def _truncate_digest_for_ecdsa(ec_key_cdata, digest, backend):
@@ -80,7 +82,7 @@
         )
 
 
-@utils.register_interface(interfaces.AsymmetricSignatureContext)
+@utils.register_interface(AsymmetricSignatureContext)
 class _ECDSASignatureContext(object):
     def __init__(self, backend, private_key, algorithm):
         self._backend = backend
@@ -114,7 +116,7 @@
         return self._backend._ffi.buffer(sigbuf)[:siglen_ptr[0]]
 
 
-@utils.register_interface(interfaces.AsymmetricVerificationContext)
+@utils.register_interface(AsymmetricVerificationContext)
 class _ECDSAVerificationContext(object):
     def __init__(self, backend, public_key, signature, algorithm):
         self._backend = backend
diff --git a/src/cryptography/hazmat/backends/openssl/rsa.py b/src/cryptography/hazmat/backends/openssl/rsa.py
index 310b994..00ddcda 100644
--- a/src/cryptography/hazmat/backends/openssl/rsa.py
+++ b/src/cryptography/hazmat/backends/openssl/rsa.py
@@ -10,10 +10,12 @@
 from cryptography.exceptions import (
     AlreadyFinalized, InvalidSignature, UnsupportedAlgorithm, _Reasons
 )
-from cryptography.hazmat.primitives import hashes, interfaces
-from cryptography.hazmat.primitives.asymmetric import rsa
+from cryptography.hazmat.primitives import hashes
+from cryptography.hazmat.primitives.asymmetric import (
+    AsymmetricSignatureContext, AsymmetricVerificationContext, rsa
+)
 from cryptography.hazmat.primitives.asymmetric.padding import (
-    MGF1, OAEP, PKCS1v15, PSS
+    AsymmetricPadding, MGF1, OAEP, PKCS1v15, PSS
 )
 from cryptography.hazmat.primitives.interfaces import (
     RSAPrivateKeyWithNumbers, RSAPublicKeyWithNumbers
@@ -34,7 +36,7 @@
 
 
 def _enc_dec_rsa(backend, key, data, padding):
-    if not isinstance(padding, interfaces.AsymmetricPadding):
+    if not isinstance(padding, AsymmetricPadding):
         raise TypeError("Padding must be an instance of AsymmetricPadding.")
 
     if isinstance(padding, PKCS1v15):
@@ -144,15 +146,14 @@
         raise ValueError("Decryption failed.")
 
 
-@utils.register_interface(interfaces.AsymmetricSignatureContext)
+@utils.register_interface(AsymmetricSignatureContext)
 class _RSASignatureContext(object):
     def __init__(self, backend, private_key, padding, algorithm):
         self._backend = backend
         self._private_key = private_key
 
-        if not isinstance(padding, interfaces.AsymmetricPadding):
-            raise TypeError(
-                "Expected provider of interfaces.AsymmetricPadding.")
+        if not isinstance(padding, AsymmetricPadding):
+            raise TypeError("Expected provider of AsymmetricPadding.")
 
         self._pkey_size = self._backend._lib.EVP_PKEY_size(
             self._private_key._evp_pkey
@@ -332,16 +333,15 @@
         return self._backend._ffi.buffer(sig_buf)[:sig_len]
 
 
-@utils.register_interface(interfaces.AsymmetricVerificationContext)
+@utils.register_interface(AsymmetricVerificationContext)
 class _RSAVerificationContext(object):
     def __init__(self, backend, public_key, signature, padding, algorithm):
         self._backend = backend
         self._public_key = public_key
         self._signature = signature
 
-        if not isinstance(padding, interfaces.AsymmetricPadding):
-            raise TypeError(
-                "Expected provider of interfaces.AsymmetricPadding.")
+        if not isinstance(padding, AsymmetricPadding):
+            raise TypeError("Expected provider of AsymmetricPadding.")
 
         self._pkey_size = self._backend._lib.EVP_PKEY_size(
             self._public_key._evp_pkey
diff --git a/src/cryptography/hazmat/bindings/openssl/engine.py b/src/cryptography/hazmat/bindings/openssl/engine.py
index 33c7998..3ebfa6c 100644
--- a/src/cryptography/hazmat/bindings/openssl/engine.py
+++ b/src/cryptography/hazmat/bindings/openssl/engine.py
@@ -9,6 +9,8 @@
 """
 
 TYPES = """
+static const long Cryptography_HAS_ENGINE_CRYPTODEV;
+
 typedef ... ENGINE;
 typedef ... RSA_METHOD;
 typedef ... DSA_METHOD;
@@ -49,7 +51,6 @@
 int ENGINE_finish(ENGINE *);
 void ENGINE_load_openssl(void);
 void ENGINE_load_dynamic(void);
-void ENGINE_load_cryptodev(void);
 void ENGINE_load_builtin_engines(void);
 void ENGINE_cleanup(void);
 ENGINE *ENGINE_get_default_RSA(void);
@@ -148,9 +149,20 @@
 """
 
 MACROS = """
+void ENGINE_load_cryptodev(void);
 """
 
 CUSTOMIZATIONS = """
+#if defined(LIBRESSL_VERSION_NUMBER)
+static const long Cryptography_HAS_ENGINE_CRYPTODEV = 0;
+void (*ENGINE_load_cryptodev)(void) = NULL;
+#else
+static const long Cryptography_HAS_ENGINE_CRYPTODEV = 1;
+#endif
 """
 
-CONDITIONAL_NAMES = {}
+CONDITIONAL_NAMES = {
+    "Cryptography_HAS_ENGINE_CRYPTODEV": [
+        "ENGINE_load_cryptodev"
+    ]
+}
diff --git a/src/cryptography/hazmat/bindings/openssl/rand.py b/src/cryptography/hazmat/bindings/openssl/rand.py
index c30af92..6330482 100644
--- a/src/cryptography/hazmat/bindings/openssl/rand.py
+++ b/src/cryptography/hazmat/bindings/openssl/rand.py
@@ -9,6 +9,7 @@
 """
 
 TYPES = """
+static const long Cryptography_HAS_EGD;
 """
 
 FUNCTIONS = """
@@ -16,9 +17,6 @@
 void RAND_seed(const void *, int);
 void RAND_add(const void *, int, double);
 int RAND_status(void);
-int RAND_egd(const char *);
-int RAND_egd_bytes(const char *, int);
-int RAND_query_egd_bytes(const char *, unsigned char *, int);
 const char *RAND_file_name(char *, size_t);
 int RAND_load_file(const char *, long);
 int RAND_write_file(const char *);
@@ -28,9 +26,26 @@
 """
 
 MACROS = """
+int RAND_egd(const char *);
+int RAND_egd_bytes(const char *, int);
+int RAND_query_egd_bytes(const char *, unsigned char *, int);
 """
 
 CUSTOMIZATIONS = """
+#if defined(LIBRESSL_VERSION_NUMBER)
+static const long Cryptography_HAS_EGD = 0;
+int (*RAND_egd)(const char *) = NULL;
+int (*RAND_egd_bytes)(const char *, int) = NULL;
+int (*RAND_query_egd_bytes)(const char *, unsigned char *, int) = NULL;
+#else
+static const long Cryptography_HAS_EGD = 1;
+#endif
 """
 
-CONDITIONAL_NAMES = {}
+CONDITIONAL_NAMES = {
+    "Cryptography_HAS_EGD": [
+        "RAND_egd",
+        "RAND_egd_bytes",
+        "RAND_query_egd_bytes",
+    ]
+}
diff --git a/src/cryptography/hazmat/bindings/openssl/ssl.py b/src/cryptography/hazmat/bindings/openssl/ssl.py
index bf62713..bc4b2e7 100644
--- a/src/cryptography/hazmat/bindings/openssl/ssl.py
+++ b/src/cryptography/hazmat/bindings/openssl/ssl.py
@@ -19,6 +19,7 @@
 static const long Cryptography_HAS_TLSv1_1;
 static const long Cryptography_HAS_TLSv1_2;
 static const long Cryptography_HAS_SECURE_RENEGOTIATION;
+static const long Cryptography_HAS_COMPRESSION;
 
 /* Internally invented symbol to tell us if SNI is supported */
 static const long Cryptography_HAS_TLSEXT_HOSTNAME;
@@ -189,10 +190,6 @@
 const char *SSL_get_cipher_list(const SSL *, int);
 Cryptography_STACK_OF_SSL_CIPHER *SSL_get_ciphers(const SSL *);
 
-const COMP_METHOD *SSL_get_current_compression(SSL *);
-const COMP_METHOD *SSL_get_current_expansion(SSL *);
-const char *SSL_COMP_get_name(const COMP_METHOD *);
-
 /*  context */
 void SSL_CTX_free(SSL_CTX *);
 long SSL_CTX_set_timeout(SSL_CTX *, long);
@@ -232,6 +229,11 @@
 """
 
 MACROS = """
+/* not macros, but will be conditionally bound so can't live in functions */
+const COMP_METHOD *SSL_get_current_compression(SSL *);
+const COMP_METHOD *SSL_get_current_expansion(SSL *);
+const char *SSL_COMP_get_name(const COMP_METHOD *);
+
 unsigned long SSL_set_mode(SSL *, unsigned long);
 unsigned long SSL_get_mode(SSL *);
 
@@ -544,6 +546,17 @@
 #else
 static const long Cryptography_HAS_ALPN = 1;
 #endif
+/* LibreSSL has removed support for compression, and with it the
+ * COMP_METHOD use in ssl.h. This is a hack to make the function types
+ * in this code match those in ssl.h.
+ */
+#ifdef LIBRESSL_VERSION_NUMBER
+static const long Cryptography_HAS_COMPRESSION = 0;
+typedef void COMP_METHOD;
+#else
+static const long Cryptography_HAS_COMPRESSION = 1;
+#endif
+
 """
 
 CONDITIONAL_NAMES = {
@@ -626,5 +639,11 @@
         "SSL_set_alpn_protos",
         "SSL_CTX_set_alpn_select_cb",
         "SSL_get0_alpn_selected",
+    ],
+
+    "Cryptography_HAS_COMPRESSION": [
+        "SSL_get_current_compression",
+        "SSL_get_current_expansion",
+        "SSL_COMP_get_name",
     ]
 }
diff --git a/src/cryptography/hazmat/bindings/openssl/x509_vfy.py b/src/cryptography/hazmat/bindings/openssl/x509_vfy.py
index 6f05f4d..1f75b86 100644
--- a/src/cryptography/hazmat/bindings/openssl/x509_vfy.py
+++ b/src/cryptography/hazmat/bindings/openssl/x509_vfy.py
@@ -191,7 +191,7 @@
 
 CUSTOMIZATIONS = """
 /* OpenSSL 1.0.2+ verification error codes */
-#if OPENSSL_VERSION_NUMBER >= 0x10002000L
+#if OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(LIBRESSL_VERSION_NUMBER)
 static const long Cryptography_HAS_102_VERIFICATION_ERROR_CODES = 1;
 #else
 static const long Cryptography_HAS_102_VERIFICATION_ERROR_CODES = 0;
@@ -207,7 +207,7 @@
 #endif
 
 /* OpenSSL 1.0.2+ verification parameters */
-#if OPENSSL_VERSION_NUMBER >= 0x10002000L
+#if OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(LIBRESSL_VERSION_NUMBER)
 static const long Cryptography_HAS_102_VERIFICATION_PARAMS = 1;
 #else
 static const long Cryptography_HAS_102_VERIFICATION_PARAMS = 0;
diff --git a/src/cryptography/hazmat/primitives/asymmetric/__init__.py b/src/cryptography/hazmat/primitives/asymmetric/__init__.py
index 4b54088..494a7a1 100644
--- a/src/cryptography/hazmat/primitives/asymmetric/__init__.py
+++ b/src/cryptography/hazmat/primitives/asymmetric/__init__.py
@@ -3,3 +3,38 @@
 # for complete details.
 
 from __future__ import absolute_import, division, print_function
+
+import abc
+
+import six
+
+
+@six.add_metaclass(abc.ABCMeta)
+class AsymmetricSignatureContext(object):
+    @abc.abstractmethod
+    def update(self, data):
+        """
+        Processes the provided bytes and returns nothing.
+        """
+
+    @abc.abstractmethod
+    def finalize(self):
+        """
+        Returns the signature as bytes.
+        """
+
+
+@six.add_metaclass(abc.ABCMeta)
+class AsymmetricVerificationContext(object):
+    @abc.abstractmethod
+    def update(self, data):
+        """
+        Processes the provided bytes and returns nothing.
+        """
+
+    @abc.abstractmethod
+    def verify(self):
+        """
+        Raises an exception if the bytes provided to update do not match the
+        signature or the signature does not match the public key.
+        """
diff --git a/src/cryptography/hazmat/primitives/asymmetric/padding.py b/src/cryptography/hazmat/primitives/asymmetric/padding.py
index d0c3ead..c796d8e 100644
--- a/src/cryptography/hazmat/primitives/asymmetric/padding.py
+++ b/src/cryptography/hazmat/primitives/asymmetric/padding.py
@@ -4,18 +4,29 @@
 
 from __future__ import absolute_import, division, print_function
 
+import abc
+
 import six
 
 from cryptography import utils
-from cryptography.hazmat.primitives import hashes, interfaces
+from cryptography.hazmat.primitives import hashes
 
 
-@utils.register_interface(interfaces.AsymmetricPadding)
+@six.add_metaclass(abc.ABCMeta)
+class AsymmetricPadding(object):
+    @abc.abstractproperty
+    def name(self):
+        """
+        A string naming this padding (e.g. "PSS", "PKCS1").
+        """
+
+
+@utils.register_interface(AsymmetricPadding)
 class PKCS1v15(object):
     name = "EMSA-PKCS1-v1_5"
 
 
-@utils.register_interface(interfaces.AsymmetricPadding)
+@utils.register_interface(AsymmetricPadding)
 class PSS(object):
     MAX_LENGTH = object()
     name = "EMSA-PSS"
@@ -33,7 +44,7 @@
         self._salt_length = salt_length
 
 
-@utils.register_interface(interfaces.AsymmetricPadding)
+@utils.register_interface(AsymmetricPadding)
 class OAEP(object):
     name = "EME-OAEP"
 
diff --git a/src/cryptography/hazmat/primitives/ciphers/__init__.py b/src/cryptography/hazmat/primitives/ciphers/__init__.py
index d779531..b5dd0ed 100644
--- a/src/cryptography/hazmat/primitives/ciphers/__init__.py
+++ b/src/cryptography/hazmat/primitives/ciphers/__init__.py
@@ -4,9 +4,17 @@
 
 from __future__ import absolute_import, division, print_function
 
-from cryptography.hazmat.primitives.ciphers.base import Cipher
+from cryptography.hazmat.primitives.ciphers.base import (
+    AEADCipherContext, AEADEncryptionContext, BlockCipherAlgorithm, Cipher,
+    CipherAlgorithm, CipherContext
+)
 
 
 __all__ = [
     "Cipher",
+    "CipherAlgorithm",
+    "BlockCipherAlgorithm",
+    "CipherContext",
+    "AEADCipherContext",
+    "AEADEncryptionContext",
 ]
diff --git a/src/cryptography/hazmat/primitives/ciphers/algorithms.py b/src/cryptography/hazmat/primitives/ciphers/algorithms.py
index 677d702..b71dddb 100644
--- a/src/cryptography/hazmat/primitives/ciphers/algorithms.py
+++ b/src/cryptography/hazmat/primitives/ciphers/algorithms.py
@@ -5,7 +5,9 @@
 from __future__ import absolute_import, division, print_function
 
 from cryptography import utils
-from cryptography.hazmat.primitives import interfaces
+from cryptography.hazmat.primitives.ciphers import (
+    BlockCipherAlgorithm, CipherAlgorithm
+)
 
 
 def _verify_key_size(algorithm, key):
@@ -17,8 +19,8 @@
     return key
 
 
-@utils.register_interface(interfaces.BlockCipherAlgorithm)
-@utils.register_interface(interfaces.CipherAlgorithm)
+@utils.register_interface(BlockCipherAlgorithm)
+@utils.register_interface(CipherAlgorithm)
 class AES(object):
     name = "AES"
     block_size = 128
@@ -32,8 +34,8 @@
         return len(self.key) * 8
 
 
-@utils.register_interface(interfaces.BlockCipherAlgorithm)
-@utils.register_interface(interfaces.CipherAlgorithm)
+@utils.register_interface(BlockCipherAlgorithm)
+@utils.register_interface(CipherAlgorithm)
 class Camellia(object):
     name = "camellia"
     block_size = 128
@@ -47,8 +49,8 @@
         return len(self.key) * 8
 
 
-@utils.register_interface(interfaces.BlockCipherAlgorithm)
-@utils.register_interface(interfaces.CipherAlgorithm)
+@utils.register_interface(BlockCipherAlgorithm)
+@utils.register_interface(CipherAlgorithm)
 class TripleDES(object):
     name = "3DES"
     block_size = 64
@@ -66,8 +68,8 @@
         return len(self.key) * 8
 
 
-@utils.register_interface(interfaces.BlockCipherAlgorithm)
-@utils.register_interface(interfaces.CipherAlgorithm)
+@utils.register_interface(BlockCipherAlgorithm)
+@utils.register_interface(CipherAlgorithm)
 class Blowfish(object):
     name = "Blowfish"
     block_size = 64
@@ -81,8 +83,8 @@
         return len(self.key) * 8
 
 
-@utils.register_interface(interfaces.BlockCipherAlgorithm)
-@utils.register_interface(interfaces.CipherAlgorithm)
+@utils.register_interface(BlockCipherAlgorithm)
+@utils.register_interface(CipherAlgorithm)
 class CAST5(object):
     name = "CAST5"
     block_size = 64
@@ -96,7 +98,7 @@
         return len(self.key) * 8
 
 
-@utils.register_interface(interfaces.CipherAlgorithm)
+@utils.register_interface(CipherAlgorithm)
 class ARC4(object):
     name = "RC4"
     key_sizes = frozenset([40, 56, 64, 80, 128, 192, 256])
@@ -109,7 +111,7 @@
         return len(self.key) * 8
 
 
-@utils.register_interface(interfaces.CipherAlgorithm)
+@utils.register_interface(CipherAlgorithm)
 class IDEA(object):
     name = "IDEA"
     block_size = 64
@@ -123,8 +125,8 @@
         return len(self.key) * 8
 
 
-@utils.register_interface(interfaces.BlockCipherAlgorithm)
-@utils.register_interface(interfaces.CipherAlgorithm)
+@utils.register_interface(BlockCipherAlgorithm)
+@utils.register_interface(CipherAlgorithm)
 class SEED(object):
     name = "SEED"
     block_size = 128
diff --git a/src/cryptography/hazmat/primitives/ciphers/base.py b/src/cryptography/hazmat/primitives/ciphers/base.py
index 81b8d77..8f3028f 100644
--- a/src/cryptography/hazmat/primitives/ciphers/base.py
+++ b/src/cryptography/hazmat/primitives/ciphers/base.py
@@ -4,13 +4,76 @@
 
 from __future__ import absolute_import, division, print_function
 
+import abc
+
+import six
+
 from cryptography import utils
 from cryptography.exceptions import (
     AlreadyFinalized, AlreadyUpdated, NotYetFinalized, UnsupportedAlgorithm,
     _Reasons
 )
 from cryptography.hazmat.backends.interfaces import CipherBackend
-from cryptography.hazmat.primitives import interfaces
+from cryptography.hazmat.primitives.ciphers import modes
+
+
+@six.add_metaclass(abc.ABCMeta)
+class CipherAlgorithm(object):
+    @abc.abstractproperty
+    def name(self):
+        """
+        A string naming this mode (e.g. "AES", "Camellia").
+        """
+
+    @abc.abstractproperty
+    def key_size(self):
+        """
+        The size of the key being used as an integer in bits (e.g. 128, 256).
+        """
+
+
+@six.add_metaclass(abc.ABCMeta)
+class BlockCipherAlgorithm(object):
+    @abc.abstractproperty
+    def block_size(self):
+        """
+        The size of a block as an integer in bits (e.g. 64, 128).
+        """
+
+
+@six.add_metaclass(abc.ABCMeta)
+class CipherContext(object):
+    @abc.abstractmethod
+    def update(self, data):
+        """
+        Processes the provided bytes through the cipher and returns the results
+        as bytes.
+        """
+
+    @abc.abstractmethod
+    def finalize(self):
+        """
+        Returns the results of processing the final block as bytes.
+        """
+
+
+@six.add_metaclass(abc.ABCMeta)
+class AEADCipherContext(object):
+    @abc.abstractmethod
+    def authenticate_additional_data(self, data):
+        """
+        Authenticates the provided bytes.
+        """
+
+
+@six.add_metaclass(abc.ABCMeta)
+class AEADEncryptionContext(object):
+    @abc.abstractproperty
+    def tag(self):
+        """
+        Returns tag bytes. This is only available after encryption is
+        finalized.
+        """
 
 
 class Cipher(object):
@@ -21,10 +84,8 @@
                 _Reasons.BACKEND_MISSING_INTERFACE
             )
 
-        if not isinstance(algorithm, interfaces.CipherAlgorithm):
-            raise TypeError(
-                "Expected interface of interfaces.CipherAlgorithm."
-            )
+        if not isinstance(algorithm, CipherAlgorithm):
+            raise TypeError("Expected interface of CipherAlgorithm.")
 
         if mode is not None:
             mode.validate_for_algorithm(algorithm)
@@ -34,7 +95,7 @@
         self._backend = backend
 
     def encryptor(self):
-        if isinstance(self.mode, interfaces.ModeWithAuthenticationTag):
+        if isinstance(self.mode, modes.ModeWithAuthenticationTag):
             if self.mode.tag is not None:
                 raise ValueError(
                     "Authentication tag must be None when encrypting."
@@ -45,7 +106,7 @@
         return self._wrap_ctx(ctx, encrypt=True)
 
     def decryptor(self):
-        if isinstance(self.mode, interfaces.ModeWithAuthenticationTag):
+        if isinstance(self.mode, modes.ModeWithAuthenticationTag):
             if self.mode.tag is None:
                 raise ValueError(
                     "Authentication tag must be provided when decrypting."
@@ -56,7 +117,7 @@
         return self._wrap_ctx(ctx, encrypt=False)
 
     def _wrap_ctx(self, ctx, encrypt):
-        if isinstance(self.mode, interfaces.ModeWithAuthenticationTag):
+        if isinstance(self.mode, modes.ModeWithAuthenticationTag):
             if encrypt:
                 return _AEADEncryptionContext(ctx)
             else:
@@ -65,7 +126,7 @@
             return _CipherContext(ctx)
 
 
-@utils.register_interface(interfaces.CipherContext)
+@utils.register_interface(CipherContext)
 class _CipherContext(object):
     def __init__(self, ctx):
         self._ctx = ctx
@@ -83,8 +144,8 @@
         return data
 
 
-@utils.register_interface(interfaces.AEADCipherContext)
-@utils.register_interface(interfaces.CipherContext)
+@utils.register_interface(AEADCipherContext)
+@utils.register_interface(CipherContext)
 class _AEADCipherContext(object):
     def __init__(self, ctx):
         self._ctx = ctx
@@ -113,7 +174,7 @@
         self._ctx.authenticate_additional_data(data)
 
 
-@utils.register_interface(interfaces.AEADEncryptionContext)
+@utils.register_interface(AEADEncryptionContext)
 class _AEADEncryptionContext(_AEADCipherContext):
     @property
     def tag(self):
diff --git a/src/cryptography/hazmat/primitives/ciphers/modes.py b/src/cryptography/hazmat/primitives/ciphers/modes.py
index fc269de..e31c906 100644
--- a/src/cryptography/hazmat/primitives/ciphers/modes.py
+++ b/src/cryptography/hazmat/primitives/ciphers/modes.py
@@ -4,8 +4,54 @@
 
 from __future__ import absolute_import, division, print_function
 
+import abc
+
+import six
+
 from cryptography import utils
-from cryptography.hazmat.primitives import interfaces
+
+
+@six.add_metaclass(abc.ABCMeta)
+class Mode(object):
+    @abc.abstractproperty
+    def name(self):
+        """
+        A string naming this mode (e.g. "ECB", "CBC").
+        """
+
+    @abc.abstractmethod
+    def validate_for_algorithm(self, algorithm):
+        """
+        Checks that all the necessary invariants of this (mode, algorithm)
+        combination are met.
+        """
+
+
+@six.add_metaclass(abc.ABCMeta)
+class ModeWithInitializationVector(object):
+    @abc.abstractproperty
+    def initialization_vector(self):
+        """
+        The value of the initialization vector for this mode as bytes.
+        """
+
+
+@six.add_metaclass(abc.ABCMeta)
+class ModeWithNonce(object):
+    @abc.abstractproperty
+    def nonce(self):
+        """
+        The value of the nonce for this mode as bytes.
+        """
+
+
+@six.add_metaclass(abc.ABCMeta)
+class ModeWithAuthenticationTag(object):
+    @abc.abstractproperty
+    def tag(self):
+        """
+        The value of the tag supplied to the constructor of this mode.
+        """
 
 
 def _check_iv_length(self, algorithm):
@@ -15,8 +61,8 @@
         ))
 
 
-@utils.register_interface(interfaces.Mode)
-@utils.register_interface(interfaces.ModeWithInitializationVector)
+@utils.register_interface(Mode)
+@utils.register_interface(ModeWithInitializationVector)
 class CBC(object):
     name = "CBC"
 
@@ -27,7 +73,7 @@
     validate_for_algorithm = _check_iv_length
 
 
-@utils.register_interface(interfaces.Mode)
+@utils.register_interface(Mode)
 class ECB(object):
     name = "ECB"
 
@@ -35,8 +81,8 @@
         pass
 
 
-@utils.register_interface(interfaces.Mode)
-@utils.register_interface(interfaces.ModeWithInitializationVector)
+@utils.register_interface(Mode)
+@utils.register_interface(ModeWithInitializationVector)
 class OFB(object):
     name = "OFB"
 
@@ -47,8 +93,8 @@
     validate_for_algorithm = _check_iv_length
 
 
-@utils.register_interface(interfaces.Mode)
-@utils.register_interface(interfaces.ModeWithInitializationVector)
+@utils.register_interface(Mode)
+@utils.register_interface(ModeWithInitializationVector)
 class CFB(object):
     name = "CFB"
 
@@ -59,8 +105,8 @@
     validate_for_algorithm = _check_iv_length
 
 
-@utils.register_interface(interfaces.Mode)
-@utils.register_interface(interfaces.ModeWithInitializationVector)
+@utils.register_interface(Mode)
+@utils.register_interface(ModeWithInitializationVector)
 class CFB8(object):
     name = "CFB8"
 
@@ -71,8 +117,8 @@
     validate_for_algorithm = _check_iv_length
 
 
-@utils.register_interface(interfaces.Mode)
-@utils.register_interface(interfaces.ModeWithNonce)
+@utils.register_interface(Mode)
+@utils.register_interface(ModeWithNonce)
 class CTR(object):
     name = "CTR"
 
@@ -88,9 +134,9 @@
             ))
 
 
-@utils.register_interface(interfaces.Mode)
-@utils.register_interface(interfaces.ModeWithInitializationVector)
-@utils.register_interface(interfaces.ModeWithAuthenticationTag)
+@utils.register_interface(Mode)
+@utils.register_interface(ModeWithInitializationVector)
+@utils.register_interface(ModeWithAuthenticationTag)
 class GCM(object):
     name = "GCM"
 
diff --git a/src/cryptography/hazmat/primitives/cmac.py b/src/cryptography/hazmat/primitives/cmac.py
index ccbe07e..c2038a3 100644
--- a/src/cryptography/hazmat/primitives/cmac.py
+++ b/src/cryptography/hazmat/primitives/cmac.py
@@ -9,7 +9,7 @@
     AlreadyFinalized, UnsupportedAlgorithm, _Reasons
 )
 from cryptography.hazmat.backends.interfaces import CMACBackend
-from cryptography.hazmat.primitives import interfaces
+from cryptography.hazmat.primitives import ciphers, interfaces
 
 
 @utils.register_interface(interfaces.MACContext)
@@ -21,9 +21,9 @@
                 _Reasons.BACKEND_MISSING_INTERFACE
             )
 
-        if not isinstance(algorithm, interfaces.BlockCipherAlgorithm):
+        if not isinstance(algorithm, ciphers.BlockCipherAlgorithm):
             raise TypeError(
-                "Expected instance of interfaces.BlockCipherAlgorithm."
+                "Expected instance of BlockCipherAlgorithm."
             )
         self._algorithm = algorithm
 
diff --git a/src/cryptography/hazmat/primitives/interfaces/__init__.py b/src/cryptography/hazmat/primitives/interfaces/__init__.py
index 17bac1e..6b4241b 100644
--- a/src/cryptography/hazmat/primitives/interfaces/__init__.py
+++ b/src/cryptography/hazmat/primitives/interfaces/__init__.py
@@ -9,21 +9,113 @@
 import six
 
 from cryptography import utils
-from cryptography.hazmat.primitives import hashes
-from cryptography.hazmat.primitives.asymmetric import dsa, ec, rsa
-from cryptography.hazmat.primitives.interfaces.ciphers import (
-    BlockCipherAlgorithm, CipherAlgorithm, Mode,
-    ModeWithAuthenticationTag, ModeWithInitializationVector, ModeWithNonce
+from cryptography.hazmat.primitives import ciphers, hashes
+from cryptography.hazmat.primitives.asymmetric import (
+    AsymmetricSignatureContext, AsymmetricVerificationContext, dsa, ec,
+    padding, rsa
+)
+from cryptography.hazmat.primitives.ciphers import modes
+from cryptography.hazmat.primitives.kdf import KeyDerivationFunction
+from cryptography.hazmat.primitives.padding import PaddingContext
+
+
+BlockCipherAlgorithm = utils.deprecated(
+    ciphers.BlockCipherAlgorithm,
+    __name__,
+    (
+        "The BlockCipherAlgorithm interface has moved to the "
+        "cryptography.hazmat.primitives.ciphers module"
+    ),
+    utils.DeprecatedIn08
 )
 
-__all__ = [
-    "BlockCipherAlgorithm",
-    "CipherAlgorithm",
-    "Mode",
-    "ModeWithAuthenticationTag",
-    "ModeWithInitializationVector",
-    "ModeWithNonce"
-]
+
+CipherAlgorithm = utils.deprecated(
+    ciphers.CipherAlgorithm,
+    __name__,
+    (
+        "The CipherAlgorithm interface has moved to the "
+        "cryptography.hazmat.primitives.ciphers module"
+    ),
+    utils.DeprecatedIn08
+)
+
+
+Mode = utils.deprecated(
+    modes.Mode,
+    __name__,
+    (
+        "The Mode interface has moved to the "
+        "cryptography.hazmat.primitives.ciphers.modes module"
+    ),
+    utils.DeprecatedIn08
+)
+
+
+ModeWithAuthenticationTag = utils.deprecated(
+    modes.ModeWithAuthenticationTag,
+    __name__,
+    (
+        "The ModeWithAuthenticationTag interface has moved to the "
+        "cryptography.hazmat.primitives.ciphers.modes module"
+    ),
+    utils.DeprecatedIn08
+)
+
+
+ModeWithInitializationVector = utils.deprecated(
+    modes.ModeWithInitializationVector,
+    __name__,
+    (
+        "The ModeWithInitializationVector interface has moved to the "
+        "cryptography.hazmat.primitives.ciphers.modes module"
+    ),
+    utils.DeprecatedIn08
+)
+
+
+ModeWithNonce = utils.deprecated(
+    modes.ModeWithNonce,
+    __name__,
+    (
+        "The ModeWithNonce interface has moved to the "
+        "cryptography.hazmat.primitives.ciphers.modes module"
+    ),
+    utils.DeprecatedIn08
+)
+
+
+CipherContext = utils.deprecated(
+    ciphers.CipherContext,
+    __name__,
+    (
+        "The CipherContext interface has moved to the "
+        "cryptography.hazmat.primitives.ciphers module"
+    ),
+    utils.DeprecatedIn08
+)
+
+
+AEADCipherContext = utils.deprecated(
+    ciphers.AEADCipherContext,
+    __name__,
+    (
+        "The AEADCipherContext interface has moved to the "
+        "cryptography.hazmat.primitives.ciphers module"
+    ),
+    utils.DeprecatedIn08
+)
+
+
+AEADEncryptionContext = utils.deprecated(
+    ciphers.AEADEncryptionContext,
+    __name__,
+    (
+        "The AEADEncryptionContext interface has moved to the "
+        "cryptography.hazmat.primitives.ciphers module"
+    ),
+    utils.DeprecatedIn08
+)
 
 
 EllipticCurve = utils.deprecated(
@@ -153,54 +245,15 @@
 )
 
 
-@six.add_metaclass(abc.ABCMeta)
-class CipherContext(object):
-    @abc.abstractmethod
-    def update(self, data):
-        """
-        Processes the provided bytes through the cipher and returns the results
-        as bytes.
-        """
-
-    @abc.abstractmethod
-    def finalize(self):
-        """
-        Returns the results of processing the final block as bytes.
-        """
-
-
-@six.add_metaclass(abc.ABCMeta)
-class AEADCipherContext(object):
-    @abc.abstractmethod
-    def authenticate_additional_data(self, data):
-        """
-        Authenticates the provided bytes.
-        """
-
-
-@six.add_metaclass(abc.ABCMeta)
-class AEADEncryptionContext(object):
-    @abc.abstractproperty
-    def tag(self):
-        """
-        Returns tag bytes. This is only available after encryption is
-        finalized.
-        """
-
-
-@six.add_metaclass(abc.ABCMeta)
-class PaddingContext(object):
-    @abc.abstractmethod
-    def update(self, data):
-        """
-        Pads the provided bytes and returns any available data as bytes.
-        """
-
-    @abc.abstractmethod
-    def finalize(self):
-        """
-        Finalize the padding, returns bytes.
-        """
+PaddingContext = utils.deprecated(
+    PaddingContext,
+    __name__,
+    (
+        "The PaddingContext interface has moved to the "
+        "cryptography.hazmat.primitives.padding module"
+    ),
+    utils.DeprecatedIn08
+)
 
 
 HashContext = utils.deprecated(
@@ -265,62 +318,45 @@
     utils.DeprecatedIn08
 )
 
+AsymmetricPadding = utils.deprecated(
+    padding.AsymmetricPadding,
+    __name__,
+    (
+        "The AsymmetricPadding interface has moved to the "
+        "cryptography.hazmat.primitives.asymmetric.padding module"
+    ),
+    utils.DeprecatedIn08
+)
 
-@six.add_metaclass(abc.ABCMeta)
-class AsymmetricSignatureContext(object):
-    @abc.abstractmethod
-    def update(self, data):
-        """
-        Processes the provided bytes and returns nothing.
-        """
+AsymmetricSignatureContext = utils.deprecated(
+    AsymmetricSignatureContext,
+    __name__,
+    (
+        "The AsymmetricPadding interface has moved to the "
+        "cryptography.hazmat.primitives.asymmetric module"
+    ),
+    utils.DeprecatedIn08
+)
 
-    @abc.abstractmethod
-    def finalize(self):
-        """
-        Returns the signature as bytes.
-        """
+AsymmetricVerificationContext = utils.deprecated(
+    AsymmetricVerificationContext,
+    __name__,
+    (
+        "The AsymmetricVerificationContext interface has moved to the "
+        "cryptography.hazmat.primitives.asymmetric module"
+    ),
+    utils.DeprecatedIn08
+)
 
-
-@six.add_metaclass(abc.ABCMeta)
-class AsymmetricVerificationContext(object):
-    @abc.abstractmethod
-    def update(self, data):
-        """
-        Processes the provided bytes and returns nothing.
-        """
-
-    @abc.abstractmethod
-    def verify(self):
-        """
-        Raises an exception if the bytes provided to update do not match the
-        signature or the signature does not match the public key.
-        """
-
-
-@six.add_metaclass(abc.ABCMeta)
-class AsymmetricPadding(object):
-    @abc.abstractproperty
-    def name(self):
-        """
-        A string naming this padding (e.g. "PSS", "PKCS1").
-        """
-
-
-@six.add_metaclass(abc.ABCMeta)
-class KeyDerivationFunction(object):
-    @abc.abstractmethod
-    def derive(self, key_material):
-        """
-        Deterministically generates and returns a new key based on the existing
-        key material.
-        """
-
-    @abc.abstractmethod
-    def verify(self, key_material, expected_key):
-        """
-        Checks whether the key generated by the key material matches the
-        expected derived key. Raises an exception if they do not match.
-        """
+KeyDerivationFunction = utils.deprecated(
+    KeyDerivationFunction,
+    __name__,
+    (
+        "The KeyDerivationFunction interface has moved to the "
+        "cryptography.hazmat.primitives.kdf module"
+    ),
+    utils.DeprecatedIn08
+)
 
 
 @six.add_metaclass(abc.ABCMeta)
diff --git a/src/cryptography/hazmat/primitives/interfaces/ciphers.py b/src/cryptography/hazmat/primitives/interfaces/ciphers.py
deleted file mode 100644
index 075a9c2..0000000
--- a/src/cryptography/hazmat/primitives/interfaces/ciphers.py
+++ /dev/null
@@ -1,76 +0,0 @@
-# This file is dual licensed under the terms of the Apache License, Version
-# 2.0, and the BSD License. See the LICENSE file in the root of this repository
-# for complete details.
-
-from __future__ import absolute_import, division, print_function
-
-import abc
-
-import six
-
-
-@six.add_metaclass(abc.ABCMeta)
-class CipherAlgorithm(object):
-    @abc.abstractproperty
-    def name(self):
-        """
-        A string naming this mode (e.g. "AES", "Camellia").
-        """
-
-    @abc.abstractproperty
-    def key_size(self):
-        """
-        The size of the key being used as an integer in bits (e.g. 128, 256).
-        """
-
-
-@six.add_metaclass(abc.ABCMeta)
-class BlockCipherAlgorithm(object):
-    @abc.abstractproperty
-    def block_size(self):
-        """
-        The size of a block as an integer in bits (e.g. 64, 128).
-        """
-
-
-@six.add_metaclass(abc.ABCMeta)
-class Mode(object):
-    @abc.abstractproperty
-    def name(self):
-        """
-        A string naming this mode (e.g. "ECB", "CBC").
-        """
-
-    @abc.abstractmethod
-    def validate_for_algorithm(self, algorithm):
-        """
-        Checks that all the necessary invariants of this (mode, algorithm)
-        combination are met.
-        """
-
-
-@six.add_metaclass(abc.ABCMeta)
-class ModeWithInitializationVector(object):
-    @abc.abstractproperty
-    def initialization_vector(self):
-        """
-        The value of the initialization vector for this mode as bytes.
-        """
-
-
-@six.add_metaclass(abc.ABCMeta)
-class ModeWithNonce(object):
-    @abc.abstractproperty
-    def nonce(self):
-        """
-        The value of the nonce for this mode as bytes.
-        """
-
-
-@six.add_metaclass(abc.ABCMeta)
-class ModeWithAuthenticationTag(object):
-    @abc.abstractproperty
-    def tag(self):
-        """
-        The value of the tag supplied to the constructor of this mode.
-        """
diff --git a/src/cryptography/hazmat/primitives/kdf/__init__.py b/src/cryptography/hazmat/primitives/kdf/__init__.py
index 4b54088..2d0724e 100644
--- a/src/cryptography/hazmat/primitives/kdf/__init__.py
+++ b/src/cryptography/hazmat/primitives/kdf/__init__.py
@@ -3,3 +3,24 @@
 # for complete details.
 
 from __future__ import absolute_import, division, print_function
+
+import abc
+
+import six
+
+
+@six.add_metaclass(abc.ABCMeta)
+class KeyDerivationFunction(object):
+    @abc.abstractmethod
+    def derive(self, key_material):
+        """
+        Deterministically generates and returns a new key based on the existing
+        key material.
+        """
+
+    @abc.abstractmethod
+    def verify(self, key_material, expected_key):
+        """
+        Checks whether the key generated by the key material matches the
+        expected derived key. Raises an exception if they do not match.
+        """
diff --git a/src/cryptography/hazmat/primitives/kdf/hkdf.py b/src/cryptography/hazmat/primitives/kdf/hkdf.py
index 3d4c9fb..65b7091 100644
--- a/src/cryptography/hazmat/primitives/kdf/hkdf.py
+++ b/src/cryptography/hazmat/primitives/kdf/hkdf.py
@@ -11,10 +11,11 @@
     AlreadyFinalized, InvalidKey, UnsupportedAlgorithm, _Reasons
 )
 from cryptography.hazmat.backends.interfaces import HMACBackend
-from cryptography.hazmat.primitives import constant_time, hmac, interfaces
+from cryptography.hazmat.primitives import constant_time, hmac
+from cryptography.hazmat.primitives.kdf import KeyDerivationFunction
 
 
-@utils.register_interface(interfaces.KeyDerivationFunction)
+@utils.register_interface(KeyDerivationFunction)
 class HKDF(object):
     def __init__(self, algorithm, length, salt, info, backend):
         if not isinstance(backend, HMACBackend):
@@ -53,7 +54,7 @@
             raise InvalidKey
 
 
-@utils.register_interface(interfaces.KeyDerivationFunction)
+@utils.register_interface(KeyDerivationFunction)
 class HKDFExpand(object):
     def __init__(self, algorithm, length, info, backend):
         if not isinstance(backend, HMACBackend):
diff --git a/src/cryptography/hazmat/primitives/kdf/pbkdf2.py b/src/cryptography/hazmat/primitives/kdf/pbkdf2.py
index 3d565be..f8ce7a3 100644
--- a/src/cryptography/hazmat/primitives/kdf/pbkdf2.py
+++ b/src/cryptography/hazmat/primitives/kdf/pbkdf2.py
@@ -9,10 +9,11 @@
     AlreadyFinalized, InvalidKey, UnsupportedAlgorithm, _Reasons
 )
 from cryptography.hazmat.backends.interfaces import PBKDF2HMACBackend
-from cryptography.hazmat.primitives import constant_time, interfaces
+from cryptography.hazmat.primitives import constant_time
+from cryptography.hazmat.primitives.kdf import KeyDerivationFunction
 
 
-@utils.register_interface(interfaces.KeyDerivationFunction)
+@utils.register_interface(KeyDerivationFunction)
 class PBKDF2HMAC(object):
     def __init__(self, algorithm, length, salt, iterations, backend):
         if not isinstance(backend, PBKDF2HMACBackend):
diff --git a/src/cryptography/hazmat/primitives/padding.py b/src/cryptography/hazmat/primitives/padding.py
index 49cae9d..8ad64de 100644
--- a/src/cryptography/hazmat/primitives/padding.py
+++ b/src/cryptography/hazmat/primitives/padding.py
@@ -4,12 +4,13 @@
 
 from __future__ import absolute_import, division, print_function
 
+import abc
+
 import six
 
 from cryptography import utils
 from cryptography.exceptions import AlreadyFinalized
 from cryptography.hazmat.bindings.utils import LazyLibrary, build_ffi
-from cryptography.hazmat.primitives import interfaces
 
 
 TYPES = """
@@ -59,6 +60,21 @@
 _lib = LazyLibrary(_ffi)
 
 
+@six.add_metaclass(abc.ABCMeta)
+class PaddingContext(object):
+    @abc.abstractmethod
+    def update(self, data):
+        """
+        Pads the provided bytes and returns any available data as bytes.
+        """
+
+    @abc.abstractmethod
+    def finalize(self):
+        """
+        Finalize the padding, returns bytes.
+        """
+
+
 class PKCS7(object):
     def __init__(self, block_size):
         if not (0 <= block_size < 256):
@@ -76,7 +92,7 @@
         return _PKCS7UnpaddingContext(self.block_size)
 
 
-@utils.register_interface(interfaces.PaddingContext)
+@utils.register_interface(PaddingContext)
 class _PKCS7PaddingContext(object):
     def __init__(self, block_size):
         self.block_size = block_size
@@ -109,7 +125,7 @@
         return result
 
 
-@utils.register_interface(interfaces.PaddingContext)
+@utils.register_interface(PaddingContext)
 class _PKCS7UnpaddingContext(object):
     def __init__(self, block_size):
         self.block_size = block_size
diff --git a/src/cryptography/x509.py b/src/cryptography/x509.py
index a46367e..ad7ebbe 100644
--- a/src/cryptography/x509.py
+++ b/src/cryptography/x509.py
@@ -123,7 +123,7 @@
         self._attributes = attributes
 
     def get_attributes_for_oid(self, oid):
-        return [i for i in self._attributes if i.oid == oid]
+        return [i for i in self if i.oid == oid]
 
     def __eq__(self, other):
         if not isinstance(other, Name):
diff --git a/tests/hazmat/backends/test_commoncrypto.py b/tests/hazmat/backends/test_commoncrypto.py
index 7ccc1af..f720001 100644
--- a/tests/hazmat/backends/test_commoncrypto.py
+++ b/tests/hazmat/backends/test_commoncrypto.py
@@ -9,15 +9,14 @@
 from cryptography import utils
 from cryptography.exceptions import InternalError, _Reasons
 from cryptography.hazmat.backends import _available_backends
-from cryptography.hazmat.primitives import interfaces
+from cryptography.hazmat.primitives.ciphers import Cipher, CipherAlgorithm
 from cryptography.hazmat.primitives.ciphers.algorithms import AES
-from cryptography.hazmat.primitives.ciphers.base import Cipher
 from cryptography.hazmat.primitives.ciphers.modes import CBC, GCM
 
 from ...utils import raises_unsupported_algorithm
 
 
-@utils.register_interface(interfaces.CipherAlgorithm)
+@utils.register_interface(CipherAlgorithm)
 class DummyCipher(object):
     name = "dummy-cipher"
     block_size = None
diff --git a/tests/hazmat/backends/test_openssl.py b/tests/hazmat/backends/test_openssl.py
index 97d5808..2bf66a0 100644
--- a/tests/hazmat/backends/test_openssl.py
+++ b/tests/hazmat/backends/test_openssl.py
@@ -19,18 +19,19 @@
     Backend, backend
 )
 from cryptography.hazmat.backends.openssl.ec import _sn_to_elliptic_curve
-from cryptography.hazmat.primitives import hashes, interfaces
+from cryptography.hazmat.primitives import hashes
 from cryptography.hazmat.primitives.asymmetric import dsa, padding
-from cryptography.hazmat.primitives.ciphers import Cipher
+from cryptography.hazmat.primitives.ciphers import (
+    BlockCipherAlgorithm, Cipher, CipherAlgorithm
+)
 from cryptography.hazmat.primitives.ciphers.algorithms import AES
-from cryptography.hazmat.primitives.ciphers.modes import CBC, CTR
-from cryptography.hazmat.primitives.interfaces import BlockCipherAlgorithm
+from cryptography.hazmat.primitives.ciphers.modes import CBC, CTR, Mode
 
 from ..primitives.fixtures_rsa import RSA_KEY_512
 from ...utils import load_vectors_from_file, raises_unsupported_algorithm
 
 
-@utils.register_interface(interfaces.Mode)
+@utils.register_interface(Mode)
 class DummyMode(object):
     name = "dummy-mode"
 
@@ -38,13 +39,13 @@
         pass
 
 
-@utils.register_interface(interfaces.CipherAlgorithm)
+@utils.register_interface(CipherAlgorithm)
 class DummyCipher(object):
     name = "dummy-cipher"
     key_size = None
 
 
-@utils.register_interface(interfaces.AsymmetricPadding)
+@utils.register_interface(padding.AsymmetricPadding)
 class DummyPadding(object):
     name = "dummy-cipher"
 
@@ -70,10 +71,13 @@
 
         Unfortunately, this define does not appear to have a
         formal content definition, so for now we'll test to see
-        if it starts with OpenSSL as that appears to be true
-        for every OpenSSL.
+        if it starts with OpenSSL or LibreSSL as that appears
+        to be true for every OpenSSL-alike.
         """
-        assert backend.openssl_version_text().startswith("OpenSSL")
+        assert (
+            backend.openssl_version_text().startswith("OpenSSL") or
+            backend.openssl_version_text().startswith("LibreSSL")
+        )
 
     def test_supports_cipher(self):
         assert backend.cipher_supported(None, None) is False
diff --git a/tests/hazmat/primitives/test_block.py b/tests/hazmat/primitives/test_block.py
index 22e6d0e..1b3fc1c 100644
--- a/tests/hazmat/primitives/test_block.py
+++ b/tests/hazmat/primitives/test_block.py
@@ -13,9 +13,8 @@
     AlreadyFinalized, _Reasons
 )
 from cryptography.hazmat.backends.interfaces import CipherBackend
-from cryptography.hazmat.primitives import interfaces
 from cryptography.hazmat.primitives.ciphers import (
-    Cipher, algorithms, modes
+    Cipher, algorithms, base, modes
 )
 
 from .utils import (
@@ -24,7 +23,7 @@
 from ...utils import raises_unsupported_algorithm
 
 
-@utils.register_interface(interfaces.Mode)
+@utils.register_interface(modes.Mode)
 class DummyMode(object):
     name = "dummy-mode"
 
@@ -32,7 +31,7 @@
         pass
 
 
-@utils.register_interface(interfaces.CipherAlgorithm)
+@utils.register_interface(base.CipherAlgorithm)
 class DummyCipher(object):
     name = "dummy-cipher"
     key_size = None
@@ -46,7 +45,7 @@
             modes.CBC(binascii.unhexlify(b"0" * 32)),
             backend
         )
-        assert isinstance(cipher.encryptor(), interfaces.CipherContext)
+        assert isinstance(cipher.encryptor(), base.CipherContext)
 
     def test_creates_decryptor(self, backend):
         cipher = Cipher(
@@ -54,7 +53,7 @@
             modes.CBC(binascii.unhexlify(b"0" * 32)),
             backend
         )
-        assert isinstance(cipher.decryptor(), interfaces.CipherContext)
+        assert isinstance(cipher.decryptor(), base.CipherContext)
 
     def test_instantiate_with_non_algorithm(self, backend):
         algorithm = object()
diff --git a/tests/hazmat/primitives/test_rsa.py b/tests/hazmat/primitives/test_rsa.py
index 33e5373..6d8e687 100644
--- a/tests/hazmat/primitives/test_rsa.py
+++ b/tests/hazmat/primitives/test_rsa.py
@@ -37,7 +37,7 @@
 )
 
 
-@utils.register_interface(interfaces.AsymmetricPadding)
+@utils.register_interface(padding.AsymmetricPadding)
 class DummyPadding(object):
     name = "UNSUPPORTED-PADDING"
 
diff --git a/tests/utils.py b/tests/utils.py
index 37efc58..65c99fb 100644
--- a/tests/utils.py
+++ b/tests/utils.py
@@ -83,8 +83,8 @@
         line = line.strip()
 
         # Blank lines, comments, and section headers are ignored
-        if not line or line.startswith("#") or (line.startswith("[")
-                                                and line.endswith("]")):
+        if not line or line.startswith("#") or (line.startswith("[") and
+                                                line.endswith("]")):
             continue
 
         if line.strip() == "FAIL":