diff options
43 files changed, 817 insertions, 541 deletions
diff --git a/.travis/install.sh b/.travis/install.sh index 418aeedf..26a82c44 100755 --- a/.travis/install.sh +++ b/.travis/install.sh @@ -46,8 +46,8 @@ if [[ "$DARWIN" = true ]]; then ;; 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 f903b7f9..e8c25219 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -13,10 +13,39 @@ Changelog :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 @@ Changelog :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 15d8b980..0ce8f5f7 100644 --- a/docs/hazmat/backends/interfaces.rst +++ b/docs/hazmat/backends/interfaces.rst @@ -30,10 +30,10 @@ A specific ``backend`` may provide one or more of these interfaces. 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 @@ A specific ``backend`` may provide one or more of these interfaces. .. 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 @@ A specific ``backend`` may provide one or more of these interfaces. .. 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 @@ A specific ``backend`` may provide one or more of these interfaces. .. 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 @@ A specific ``backend`` may provide one or more of these interfaces. 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 @@ A specific ``backend`` may provide one or more of these interfaces. 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 6c3d8752..4e0f6282 100644 --- a/docs/hazmat/backends/openssl.rst +++ b/docs/hazmat/backends/openssl.rst @@ -80,4 +80,4 @@ seeded from the same pool as ``/dev/random``. .. _`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 36bc801f..3a47da45 100644 --- a/docs/hazmat/primitives/asymmetric/dsa.rst +++ b/docs/hazmat/primitives/asymmetric/dsa.rst @@ -275,7 +275,7 @@ Key interfaces provider. :returns: - :class:`~cryptography.hazmat.primitives.interfaces.AsymmetricSignatureContext` + :class:`~cryptography.hazmat.primitives.asymmetric.AsymmetricSignatureContext` .. attribute:: key_size @@ -338,7 +338,7 @@ Key interfaces 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 5b114710..8b9a584b 100644 --- a/docs/hazmat/primitives/asymmetric/ec.rst +++ b/docs/hazmat/primitives/asymmetric/ec.rst @@ -304,7 +304,7 @@ Key Interfaces :class:`EllipticCurveSignatureAlgorithm` provider. :returns: - :class:`~cryptography.hazmat.primitives.interfaces.AsymmetricSignatureContext` + :class:`~cryptography.hazmat.primitives.asymmetric.AsymmetricSignatureContext` .. method:: public_key() @@ -344,7 +344,7 @@ Key Interfaces :class:`EllipticCurveSignatureAlgorithm` provider. :returns: - :class:`~cryptography.hazmat.primitives.interfaces.AsymmetricSignatureContext` + :class:`~cryptography.hazmat.primitives.asymmetric.AsymmetricVerificationContext` .. attribute:: curve @@ -370,7 +370,7 @@ Key Interfaces .. _`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 43761fde..59f00c5d 100644 --- a/docs/hazmat/primitives/asymmetric/index.rst +++ b/docs/hazmat/primitives/asymmetric/index.rst @@ -30,6 +30,8 @@ and Elliptic Curve. 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 00000000..4932faa5 --- /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 4855a45c..fd97d75b 100644 --- a/docs/hazmat/primitives/asymmetric/rsa.rst +++ b/docs/hazmat/primitives/asymmetric/rsa.rst @@ -186,7 +186,13 @@ Once you have an encrypted message, it can be decrypted using the private key: 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 @@ Key interfaces 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 @@ Key interfaces provider. :returns: - :class:`~cryptography.hazmat.primitives.interfaces.AsymmetricSignatureContext` + :class:`~cryptography.hazmat.primitives.asymmetric.AsymmetricSignatureContext` .. method:: decrypt(ciphertext, padding) @@ -444,7 +450,7 @@ Key interfaces :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 @@ Key interfaces :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 @@ Key interfaces provider. :returns: - :class:`~cryptography.hazmat.primitives.interfaces.AsymmetricVerificationContext` + :class:`~cryptography.hazmat.primitives.asymmetric.AsymmetricVerificationContext` .. method:: encrypt(plaintext, padding) @@ -514,7 +520,7 @@ Key interfaces :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 86a3a7e4..f58d324d 100644 --- a/docs/hazmat/primitives/interfaces.rst +++ b/docs/hazmat/primitives/interfaces.rst @@ -14,130 +14,14 @@ to document argument and return types. .. _`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 - - .. 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 +In 0.8 the asymmetric signature and verification interfaces were moved to the +:mod:`cryptography.hazmat.primitives.asymmetric` module. - .. 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 @@ In 0.8 the EC key interfaces were moved to the 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 4a47159f..78d40315 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 @@ Different KDFs are suitable for different tasks such as: 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 @@ Different KDFs are suitable for different tasks such as: ``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 1ba1b3fa..e04a849f 100644 --- a/docs/hazmat/primitives/mac/cmac.rst +++ b/docs/hazmat/primitives/mac/cmac.rst @@ -22,7 +22,7 @@ A subset of CMAC with the AES-128 algorithm is described in :rfc:`4493`. .. 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 @@ A subset of CMAC with the AES-128 algorithm is described in :rfc:`4493`. 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 @@ A subset of CMAC with the AES-128 algorithm is described in :rfc:`4493`. 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 0322f9d2..a60f5ac8 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 @@ multiple of the block size. .. 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 b2ce376b..0f7e0377 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 @@ in an "encrypt-then-MAC" formulation as `described by Colin Percival`_. '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 @@ in an "encrypt-then-MAC" formulation as `described by Colin Percival`_. .. 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 @@ in an "encrypt-then-MAC" formulation as `described by Colin Percival`_. .. 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 @@ Weak ciphers Modes ~~~~~ -.. currentmodule:: cryptography.hazmat.primitives.ciphers.modes +.. module:: cryptography.hazmat.primitives.ciphers.modes .. class:: CBC(initialization_vector) @@ -293,7 +293,7 @@ Modes .. 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 @@ Insecure modes Interfaces ---------- -.. currentmodule:: cryptography.hazmat.primitives.interfaces + +.. currentmodule:: cryptography.hazmat.primitives.ciphers .. class:: CipherContext @@ -505,13 +506,110 @@ Interfaces :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 7e537db9..1ce8aec5 100644 --- a/src/cryptography/hazmat/backends/commoncrypto/ciphers.py +++ b/src/cryptography/hazmat/backends/commoncrypto/ciphers.py @@ -8,13 +8,14 @@ from cryptography import utils 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 @@ class _CipherContext(object): # 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 @@ class _CipherContext(object): 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 @@ class _CipherContext(object): 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 75d7e32f..8441e891 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -225,8 +225,8 @@ class Backend(object): ) 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 @@ class Backend(object): 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 @@ class Backend(object): 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 d665f36d..64097c7b 100644 --- a/src/cryptography/hazmat/backends/openssl/ciphers.py +++ b/src/cryptography/hazmat/backends/openssl/ciphers.py @@ -6,13 +6,13 @@ from __future__ import absolute_import, division, print_function 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 @@ class _CipherContext(object): 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 @@ class _CipherContext(object): _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 @@ class _CipherContext(object): 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 @@ class _CipherContext(object): # 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 @@ class _CipherContext(object): # 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 @@ class _CipherContext(object): 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 @@ class _CipherContext(object): 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 @@ class _CipherContext(object): 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 9488e260..d2972e4a 100644 --- a/src/cryptography/hazmat/backends/openssl/dsa.py +++ b/src/cryptography/hazmat/backends/openssl/dsa.py @@ -7,8 +7,10 @@ from __future__ import absolute_import, division, print_function 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 @@ def _truncate_digest_for_dsa(dsa_cdata, digest, backend): 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 @@ class _DSAVerificationContext(object): 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 d050c6b2..52c93da9 100644 --- a/src/cryptography/hazmat/backends/openssl/ec.py +++ b/src/cryptography/hazmat/backends/openssl/ec.py @@ -9,8 +9,10 @@ from cryptography.exceptions import ( 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 @@ def _sn_to_elliptic_curve(backend, sn): ) -@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 @@ class _ECDSASignatureContext(object): 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 310b9949..00ddcda3 100644 --- a/src/cryptography/hazmat/backends/openssl/rsa.py +++ b/src/cryptography/hazmat/backends/openssl/rsa.py @@ -10,10 +10,12 @@ from cryptography import utils 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 _get_rsa_pss_salt_length(pss, key_size, digest_size): 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 @@ def _handle_rsa_enc_dec_error(backend, key): 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 @@ class _RSASignatureContext(object): 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 33c79982..3ebfa6c1 100644 --- a/src/cryptography/hazmat/bindings/openssl/engine.py +++ b/src/cryptography/hazmat/bindings/openssl/engine.py @@ -9,6 +9,8 @@ INCLUDES = """ """ TYPES = """ +static const long Cryptography_HAS_ENGINE_CRYPTODEV; + typedef ... ENGINE; typedef ... RSA_METHOD; typedef ... DSA_METHOD; @@ -49,7 +51,6 @@ int ENGINE_init(ENGINE *); 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 @@ void ENGINE_add_conf_module(void); """ 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 c30af921..6330482c 100644 --- a/src/cryptography/hazmat/bindings/openssl/rand.py +++ b/src/cryptography/hazmat/bindings/openssl/rand.py @@ -9,6 +9,7 @@ INCLUDES = """ """ TYPES = """ +static const long Cryptography_HAS_EGD; """ FUNCTIONS = """ @@ -16,9 +17,6 @@ void ERR_load_RAND_strings(void); 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 @@ int RAND_pseudo_bytes(unsigned char *, int); """ 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 bf627139..bc4b2e79 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_SSL3_METHOD; 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 @@ int SSL_shutdown(SSL *); 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 @@ size_t SSL_get_peer_finished(const SSL *, void *, size_t); """ 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 @@ static const long Cryptography_HAS_ALPN = 0; #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 @@ CONDITIONAL_NAMES = { "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 6f05f4d7..1f75b86f 100644 --- a/src/cryptography/hazmat/bindings/openssl/x509_vfy.py +++ b/src/cryptography/hazmat/bindings/openssl/x509_vfy.py @@ -191,7 +191,7 @@ int X509_VERIFY_PARAM_set1_ip_asc(X509_VERIFY_PARAM *, const char *); 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 @@ static const long X509_V_ERR_IP_ADDRESS_MISMATCH = 0; #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 4b540884..494a7a13 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 d0c3eade..c796d8e4 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 + + +@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(interfaces.AsymmetricPadding) +@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 @@ class PSS(object): 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 d779531d..b5dd0ed7 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 677d7027..b71dddbb 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 @@ def _verify_key_size(algorithm, key): 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 @@ class AES(object): 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 @@ class Camellia(object): 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 @@ class TripleDES(object): 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 @@ class Blowfish(object): 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 @@ class CAST5(object): 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 @@ class ARC4(object): 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 @@ class IDEA(object): 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 81b8d778..8f3028fc 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 @@ class Cipher(object): _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 @@ class Cipher(object): 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 @@ class Cipher(object): 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 @@ class Cipher(object): 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 @@ class Cipher(object): 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 @@ class _CipherContext(object): 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 @@ class _AEADCipherContext(object): 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 fc269de9..e31c9060 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 @@ def _check_iv_length(self, algorithm): )) -@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 @@ class CBC(object): validate_for_algorithm = _check_iv_length -@utils.register_interface(interfaces.Mode) +@utils.register_interface(Mode) class ECB(object): name = "ECB" @@ -35,8 +81,8 @@ class ECB(object): 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 @@ class OFB(object): 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 @@ class CFB(object): 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 @@ class CFB8(object): 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 @@ class CTR(object): )) -@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 ccbe07ee..c2038a30 100644 --- a/src/cryptography/hazmat/primitives/cmac.py +++ b/src/cryptography/hazmat/primitives/cmac.py @@ -9,7 +9,7 @@ from cryptography.exceptions import ( 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 @@ class CMAC(object): _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 17bac1e6..6b4241bd 100644 --- a/src/cryptography/hazmat/primitives/interfaces/__init__.py +++ b/src/cryptography/hazmat/primitives/interfaces/__init__.py @@ -9,21 +9,113 @@ import abc 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 -__all__ = [ - "BlockCipherAlgorithm", - "CipherAlgorithm", - "Mode", - "ModeWithAuthenticationTag", - "ModeWithInitializationVector", - "ModeWithNonce" -] + +BlockCipherAlgorithm = utils.deprecated( + ciphers.BlockCipherAlgorithm, + __name__, + ( + "The BlockCipherAlgorithm interface has moved to the " + "cryptography.hazmat.primitives.ciphers module" + ), + utils.DeprecatedIn08 +) + + +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 @@ DSAPublicKeyWithNumbers = utils.deprecated( ) -@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 @@ RSAPublicKeyWithNumbers = utils.deprecated( 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. - """ - - @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. - """ - - -@six.add_metaclass(abc.ABCMeta) -class AsymmetricPadding(object): - @abc.abstractproperty - def name(self): - """ - A string naming this padding (e.g. "PSS", "PKCS1"). - """ - +AsymmetricSignatureContext = utils.deprecated( + AsymmetricSignatureContext, + __name__, + ( + "The AsymmetricPadding interface has moved to the " + "cryptography.hazmat.primitives.asymmetric module" + ), + utils.DeprecatedIn08 +) -@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. - """ +AsymmetricVerificationContext = utils.deprecated( + AsymmetricVerificationContext, + __name__, + ( + "The AsymmetricVerificationContext interface has moved to the " + "cryptography.hazmat.primitives.asymmetric module" + ), + utils.DeprecatedIn08 +) - @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 075a9c25..00000000 --- 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 4b540884..2d0724e5 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 3d4c9fb1..65b7091a 100644 --- a/src/cryptography/hazmat/primitives/kdf/hkdf.py +++ b/src/cryptography/hazmat/primitives/kdf/hkdf.py @@ -11,10 +11,11 @@ from cryptography.exceptions import ( 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 @@ class HKDF(object): 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 3d565be2..f8ce7a3b 100644 --- a/src/cryptography/hazmat/primitives/kdf/pbkdf2.py +++ b/src/cryptography/hazmat/primitives/kdf/pbkdf2.py @@ -9,10 +9,11 @@ from cryptography.exceptions import ( 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 49cae9d6..8ad64dec 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 @@ _ffi = build_ffi(cdef_source=TYPES, verify_source=FUNCTIONS) _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 @@ class PKCS7(object): 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 @@ class _PKCS7PaddingContext(object): 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 a46367ed..ad7ebbe0 100644 --- a/src/cryptography/x509.py +++ b/src/cryptography/x509.py @@ -123,7 +123,7 @@ class Name(object): 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 7ccc1aff..f7200016 100644 --- a/tests/hazmat/backends/test_commoncrypto.py +++ b/tests/hazmat/backends/test_commoncrypto.py @@ -9,15 +9,14 @@ import pytest 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 97d58085..2bf66a0c 100644 --- a/tests/hazmat/backends/test_openssl.py +++ b/tests/hazmat/backends/test_openssl.py @@ -19,18 +19,19 @@ from cryptography.hazmat.backends.openssl.backend import ( 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 @@ class DummyMode(object): 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 @@ class TestOpenSSL(object): 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 22e6d0e9..1b3fc1cb 100644 --- a/tests/hazmat/primitives/test_block.py +++ b/tests/hazmat/primitives/test_block.py @@ -13,9 +13,8 @@ from cryptography.exceptions import ( 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 ( 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 @@ class DummyMode(object): pass -@utils.register_interface(interfaces.CipherAlgorithm) +@utils.register_interface(base.CipherAlgorithm) class DummyCipher(object): name = "dummy-cipher" key_size = None @@ -46,7 +45,7 @@ class TestCipher(object): 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 @@ class TestCipher(object): 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 33e5373b..6d8e6874 100644 --- a/tests/hazmat/primitives/test_rsa.py +++ b/tests/hazmat/primitives/test_rsa.py @@ -37,7 +37,7 @@ from ...utils import ( ) -@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 37efc580..65c99fbf 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -83,8 +83,8 @@ def load_nist_vectors(vector_data): 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": |