diff options
-rwxr-xr-x | .travis/install.sh | 6 | ||||
-rw-r--r-- | CHANGELOG.rst | 2 | ||||
-rw-r--r-- | cryptography/hazmat/backends/interfaces.py | 4 | ||||
-rw-r--r-- | cryptography/hazmat/backends/openssl/backend.py | 6 | ||||
-rw-r--r-- | cryptography/hazmat/bindings/commoncrypto/binding.py | 6 | ||||
-rw-r--r-- | cryptography/hazmat/bindings/openssl/binding.py | 10 | ||||
-rw-r--r-- | cryptography/hazmat/bindings/openssl/dsa.py | 4 | ||||
-rw-r--r-- | cryptography/hazmat/bindings/openssl/err.py | 1 | ||||
-rw-r--r-- | cryptography/hazmat/bindings/openssl/x509.py | 10 | ||||
-rw-r--r-- | cryptography/hazmat/bindings/utils.py | 5 | ||||
-rw-r--r-- | cryptography/hazmat/primitives/padding.py | 9 | ||||
-rw-r--r-- | docs/hazmat/backends/interfaces.rst | 6 | ||||
-rw-r--r-- | docs/hazmat/primitives/padding.rst | 11 | ||||
-rw-r--r-- | docs/spelling_wordlist.txt | 1 | ||||
-rw-r--r-- | pytest.ini | 1 | ||||
-rw-r--r-- | tests/conftest.py | 7 | ||||
-rw-r--r-- | tests/hazmat/bindings/test_openssl.py | 2 | ||||
-rw-r--r-- | tests/hazmat/primitives/test_padding.py | 9 | ||||
-rw-r--r-- | tests/hazmat/primitives/test_rsa.py | 24 | ||||
-rw-r--r-- | tests/hazmat/primitives/utils.py | 18 | ||||
-rw-r--r-- | tests/test_utils.py | 2 |
21 files changed, 94 insertions, 50 deletions
diff --git a/.travis/install.sh b/.travis/install.sh index 58d7404d..79790050 100755 --- a/.travis/install.sh +++ b/.travis/install.sh @@ -32,12 +32,12 @@ if [[ "$(uname -s)" == "Darwin" ]]; then if which pyenv > /dev/null; then eval "$(pyenv init -)"; fi case "${TOX_ENV}" in py26) - curl -O https://raw.github.com/pypa/pip/master/contrib/get-pip.py + curl -O https://raw.githubusercontent.com/pypa/pip/master/contrib/get-pip.py sudo python get-pip.py sudo pip install virtualenv ;; py27) - curl -O https://raw.github.com/pypa/pip/master/contrib/get-pip.py + curl -O https://raw.githubusercontent.com/pypa/pip/master/contrib/get-pip.py sudo python get-pip.py sudo pip install virtualenv ;; @@ -62,7 +62,7 @@ if [[ "$(uname -s)" == "Darwin" ]]; then pip install virtualenv ;; docs) - curl -O https://raw.github.com/pypa/pip/master/contrib/get-pip.py + curl -O https://raw.githubusercontent.com/pypa/pip/master/contrib/get-pip.py sudo python get-pip.py sudo pip install virtualenv ;; diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 2fa5e3ed..e09fa5d6 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -10,7 +10,7 @@ Changelog :class:`~cryptography.hazmat.primitives.asymmetric.padding.MGF1` and added it to :class:`~cryptography.hazmat.primitives.asymmetric.padding.PSS`. It will be removed from ``MGF1`` in two releases per our :doc:`/api-stability` policy. - +* Added :class:`~cryptography.hazmat.primitives.ciphers.algorithms.SEED` support. * Added :class:`~cryptography.hazmat.primitives.cmac.CMAC`. * Added decryption support to :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey` and encryption support to :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey`. diff --git a/cryptography/hazmat/backends/interfaces.py b/cryptography/hazmat/backends/interfaces.py index ca7122c2..aaaca5e2 100644 --- a/cryptography/hazmat/backends/interfaces.py +++ b/cryptography/hazmat/backends/interfaces.py @@ -147,9 +147,9 @@ class DSABackend(object): @six.add_metaclass(abc.ABCMeta) -class OpenSSLSerializationBackend(object): +class TraditionalOpenSSLSerializationBackend(object): @abc.abstractmethod - def load_openssl_pem_private_key(self, data, password): + def load_traditional_openssl_pem_private_key(self, data, password): """ Load a private key from PEM encoded data, using password if the data is encrypted. diff --git a/cryptography/hazmat/backends/openssl/backend.py b/cryptography/hazmat/backends/openssl/backend.py index 2114cd8f..f9154f3b 100644 --- a/cryptography/hazmat/backends/openssl/backend.py +++ b/cryptography/hazmat/backends/openssl/backend.py @@ -351,7 +351,7 @@ class Backend(object): def _new_evp_pkey(self): evp_pkey = self._lib.EVP_PKEY_new() assert evp_pkey != self._ffi.NULL - return self._ffi.gc(evp_pkey, backend._lib.EVP_PKEY_free) + return self._ffi.gc(evp_pkey, self._lib.EVP_PKEY_free) def _rsa_private_key_to_evp_pkey(self, private_key): evp_pkey = self._new_evp_pkey() @@ -603,8 +603,8 @@ class Backend(object): def cmac_algorithm_supported(self, algorithm): return ( - backend._lib.Cryptography_HAS_CMAC == 1 - and backend.cipher_supported(algorithm, CBC( + self._lib.Cryptography_HAS_CMAC == 1 + and self.cipher_supported(algorithm, CBC( b"\x00" * algorithm.block_size)) ) diff --git a/cryptography/hazmat/bindings/commoncrypto/binding.py b/cryptography/hazmat/bindings/commoncrypto/binding.py index 3673ea36..144bb099 100644 --- a/cryptography/hazmat/bindings/commoncrypto/binding.py +++ b/cryptography/hazmat/bindings/commoncrypto/binding.py @@ -42,8 +42,10 @@ class Binding(object): if cls.ffi is not None and cls.lib is not None: return - cls.ffi, cls.lib = build_ffi(cls._module_prefix, cls._modules, - "", "", []) + cls.ffi, cls.lib = build_ffi( + module_prefix=cls._module_prefix, + modules=cls._modules, + ) @classmethod def is_available(cls): diff --git a/cryptography/hazmat/bindings/openssl/binding.py b/cryptography/hazmat/bindings/openssl/binding.py index cc40a108..f0ff3275 100644 --- a/cryptography/hazmat/bindings/openssl/binding.py +++ b/cryptography/hazmat/bindings/openssl/binding.py @@ -97,9 +97,13 @@ class Binding(object): else: # pragma: no cover libraries = ["libeay32", "ssleay32", "advapi32"] - cls.ffi, cls.lib = build_ffi(cls._module_prefix, cls._modules, - _OSX_PRE_INCLUDE, _OSX_POST_INCLUDE, - libraries) + cls.ffi, cls.lib = build_ffi( + module_prefix=cls._module_prefix, + modules=cls._modules, + pre_include=_OSX_PRE_INCLUDE, + post_include=_OSX_POST_INCLUDE, + libraries=libraries, + ) res = cls.lib.Cryptography_add_osrandom_engine() assert res != 0 diff --git a/cryptography/hazmat/bindings/openssl/dsa.py b/cryptography/hazmat/bindings/openssl/dsa.py index a5305893..7db03326 100644 --- a/cryptography/hazmat/bindings/openssl/dsa.py +++ b/cryptography/hazmat/bindings/openssl/dsa.py @@ -48,6 +48,10 @@ void DSA_SIG_free(DSA_SIG *); int i2d_DSA_SIG(const DSA_SIG *, unsigned char **); DSA_SIG *d2i_DSA_SIG(DSA_SIG **, const unsigned char **, long); int DSA_size(const DSA *); +int DSA_sign(int, const unsigned char *, int, unsigned char *, unsigned int *, + DSA *); +int DSA_verify(int, const unsigned char *, int, const unsigned char *, int, + DSA *); """ MACROS = """ diff --git a/cryptography/hazmat/bindings/openssl/err.py b/cryptography/hazmat/bindings/openssl/err.py index c08c880c..f6456d66 100644 --- a/cryptography/hazmat/bindings/openssl/err.py +++ b/cryptography/hazmat/bindings/openssl/err.py @@ -138,6 +138,7 @@ static const int EVP_F_RC5_CTRL; static const int EVP_R_AES_KEY_SETUP_FAILED; static const int EVP_R_ASN1_LIB; static const int EVP_R_BAD_BLOCK_LENGTH; +static const int EVP_R_BAD_DECRYPT; static const int EVP_R_BAD_KEY_LENGTH; static const int EVP_R_BN_DECODE_ERROR; static const int EVP_R_BN_PUBKEY_ERROR; diff --git a/cryptography/hazmat/bindings/openssl/x509.py b/cryptography/hazmat/bindings/openssl/x509.py index 92870369..36a15e4a 100644 --- a/cryptography/hazmat/bindings/openssl/x509.py +++ b/cryptography/hazmat/bindings/openssl/x509.py @@ -183,8 +183,13 @@ const char *X509_get_default_private_dir(void); int i2d_RSA_PUBKEY(RSA *, unsigned char **); RSA *d2i_RSA_PUBKEY(RSA **, const unsigned char **, long); +RSA *d2i_RSAPublicKey(RSA **, const unsigned char **, long); +RSA *d2i_RSAPrivateKey(RSA **, const unsigned char **, long); int i2d_DSA_PUBKEY(DSA *, unsigned char **); DSA *d2i_DSA_PUBKEY(DSA **, const unsigned char **, long); +DSA *d2i_DSAPublicKey(DSA **, const unsigned char **, long); +DSA *d2i_DSAPrivateKey(DSA **, const unsigned char **, long); + RSA *d2i_RSAPrivateKey_bio(BIO *, RSA **); int i2d_RSAPrivateKey_bio(BIO *, RSA *); @@ -223,6 +228,11 @@ void sk_X509_EXTENSION_free(X509_EXTENSIONS *); int sk_X509_REVOKED_num(Cryptography_STACK_OF_X509_REVOKED *); X509_REVOKED *sk_X509_REVOKED_value(Cryptography_STACK_OF_X509_REVOKED *, int); +int i2d_RSAPublicKey(RSA *, unsigned char **); +int i2d_RSAPrivateKey(RSA *, unsigned char **); +int i2d_DSAPublicKey(DSA *, unsigned char **); +int i2d_DSAPrivateKey(DSA *, unsigned char **); + /* These aren't macros these arguments are all const X on openssl > 1.0.x */ int X509_CRL_set_lastUpdate(X509_CRL *, ASN1_TIME *); int X509_CRL_set_nextUpdate(X509_CRL *, ASN1_TIME *); diff --git a/cryptography/hazmat/bindings/utils.py b/cryptography/hazmat/bindings/utils.py index 318b82bb..1c48116e 100644 --- a/cryptography/hazmat/bindings/utils.py +++ b/cryptography/hazmat/bindings/utils.py @@ -20,7 +20,8 @@ import sys import cffi -def build_ffi(module_prefix, modules, pre_include, post_include, libraries): +def build_ffi(module_prefix, modules, pre_include="", post_include="", + libraries=[], extra_compile_args=[], extra_link_args=[]): """ Modules listed in ``modules`` should have the following attributes: @@ -75,6 +76,8 @@ def build_ffi(module_prefix, modules, pre_include, post_include, libraries): modulename=_create_modulename(cdef_sources, source, sys.version), libraries=libraries, ext_package="cryptography", + extra_compile_args=extra_compile_args, + extra_link_args=extra_link_args, ) for name in modules: diff --git a/cryptography/hazmat/primitives/padding.py b/cryptography/hazmat/primitives/padding.py index d78c6a5b..c1a763b5 100644 --- a/cryptography/hazmat/primitives/padding.py +++ b/cryptography/hazmat/primitives/padding.py @@ -20,6 +20,7 @@ import cffi import six from cryptography import utils +from cryptography.exceptions import AlreadyFinalized from cryptography.hazmat.bindings.utils import _create_modulename from cryptography.hazmat.primitives import interfaces @@ -101,7 +102,7 @@ class _PKCS7PaddingContext(object): def update(self, data): if self._buffer is None: - raise ValueError("Context was already finalized") + raise AlreadyFinalized("Context was already finalized") if isinstance(data, six.text_type): raise TypeError("Unicode-objects must be encoded before padding") @@ -117,7 +118,7 @@ class _PKCS7PaddingContext(object): def finalize(self): if self._buffer is None: - raise ValueError("Context was already finalized") + raise AlreadyFinalized("Context was already finalized") pad_size = self.block_size // 8 - len(self._buffer) result = self._buffer + six.int2byte(pad_size) * pad_size @@ -134,7 +135,7 @@ class _PKCS7UnpaddingContext(object): def update(self, data): if self._buffer is None: - raise ValueError("Context was already finalized") + raise AlreadyFinalized("Context was already finalized") if isinstance(data, six.text_type): raise TypeError("Unicode-objects must be encoded before unpadding") @@ -153,7 +154,7 @@ class _PKCS7UnpaddingContext(object): def finalize(self): if self._buffer is None: - raise ValueError("Context was already finalized") + raise AlreadyFinalized("Context was already finalized") if len(self._buffer) != self.block_size // 8: raise ValueError("Invalid padding bytes") diff --git a/docs/hazmat/backends/interfaces.rst b/docs/hazmat/backends/interfaces.rst index ef7c0841..2f63f3e0 100644 --- a/docs/hazmat/backends/interfaces.rst +++ b/docs/hazmat/backends/interfaces.rst @@ -288,7 +288,7 @@ A specific ``backend`` may provide one or more of these interfaces. provider. -.. class:: OpenSSLSerializationBackend +.. class:: TraditionalOpenSSLSerializationBackend .. versionadded:: 0.3 @@ -302,8 +302,8 @@ A specific ``backend`` may provide one or more of these interfaces. :param bytes password: The password to use if this data is encrypted. Should be None if the data is not encrypted. - :return: A new instance of - :class:`~cryptography.hazmat.primitives.serialization.OpenSSLPrivateKey` + :return: A new instance of the appropriate private key or public key + that the serialized data contains. :raises ValueError: If the data could not be deserialized correctly. diff --git a/docs/hazmat/primitives/padding.rst b/docs/hazmat/primitives/padding.rst index 83154c0d..3056eb92 100644 --- a/docs/hazmat/primitives/padding.rst +++ b/docs/hazmat/primitives/padding.rst @@ -5,7 +5,7 @@ Padding .. currentmodule:: cryptography.hazmat.primitives.padding -Padding is a way to take data that may or may not be be a multiple of the block +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 block cipher modes as they require the data to be encrypted to be an exact multiple of the block size. @@ -66,7 +66,16 @@ multiple of the block size. :param bytes data: The data you wish to pass into the context. :return bytes: Returns the data that was padded or unpadded. + :raises cryptography.exceptions.AlreadyFinalized: See :meth:`finalize`. .. method:: finalize() + Finalize the current context and return the rest of the data. + + After ``finalize`` has been called this object can no longer be used; + :meth:`update` and :meth:`finalize` will raise an + :class:`~cryptography.exceptions.AlreadyFinalized` exception. + :return bytes: Returns the remainder of the data. + :raises ValueError: When trying to remove padding from incorrectly + padded data. diff --git a/docs/spelling_wordlist.txt b/docs/spelling_wordlist.txt index 02b9f9ef..aae52ae7 100644 --- a/docs/spelling_wordlist.txt +++ b/docs/spelling_wordlist.txt @@ -25,6 +25,7 @@ interoperable introspectability invariants iOS +metadata pickleable plaintext pseudorandom @@ -8,4 +8,5 @@ markers = hmac: this test requires a backend providing HMACBackend pbkdf2hmac: this test requires a backend providing PBKDF2HMACBackend rsa: this test requires a backend providing RSABackend + traditional_openssl_serialization: this test requires a backend providing TraditionalOpenSSLSerializationBackend supported: parametrized test requiring only_if and skip_message diff --git a/tests/conftest.py b/tests/conftest.py index d55e6cf6..86d5a03b 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -18,7 +18,7 @@ import pytest from cryptography.hazmat.backends import _available_backends from cryptography.hazmat.backends.interfaces import ( CMACBackend, CipherBackend, DSABackend, HMACBackend, HashBackend, - PBKDF2HMACBackend, RSABackend + PBKDF2HMACBackend, RSABackend, TraditionalOpenSSLSerializationBackend ) from .utils import check_backend_support, check_for_iface, select_backends @@ -40,6 +40,11 @@ def pytest_runtest_setup(item): check_for_iface("pbkdf2hmac", PBKDF2HMACBackend, item) check_for_iface("dsa", DSABackend, item) check_for_iface("rsa", RSABackend, item) + check_for_iface( + "traditional_openssl_serialization", + TraditionalOpenSSLSerializationBackend, + item + ) check_backend_support(item) diff --git a/tests/hazmat/bindings/test_openssl.py b/tests/hazmat/bindings/test_openssl.py index 1dbd23b4..58d7602b 100644 --- a/tests/hazmat/bindings/test_openssl.py +++ b/tests/hazmat/bindings/test_openssl.py @@ -84,7 +84,7 @@ class TestOpenSSL(object): with pytest.raises(RuntimeError): b._lock_cb(0, b.lib.CRYPTO_LOCK_SSL, "<test>", 1) - # errors shouldnt cause locking + # errors shouldn't cause locking assert lock.acquire(False) lock.release() diff --git a/tests/hazmat/primitives/test_padding.py b/tests/hazmat/primitives/test_padding.py index 932cef1e..cac54f27 100644 --- a/tests/hazmat/primitives/test_padding.py +++ b/tests/hazmat/primitives/test_padding.py @@ -17,6 +17,7 @@ import pytest import six +from cryptography.exceptions import AlreadyFinalized from cryptography.hazmat.primitives import padding @@ -97,15 +98,15 @@ class TestPKCS7(object): def test_use_after_finalize(self): padder = padding.PKCS7(128).padder() b = padder.finalize() - with pytest.raises(ValueError): + with pytest.raises(AlreadyFinalized): padder.update(b"") - with pytest.raises(ValueError): + with pytest.raises(AlreadyFinalized): padder.finalize() unpadder = padding.PKCS7(128).unpadder() unpadder.update(b) unpadder.finalize() - with pytest.raises(ValueError): + with pytest.raises(AlreadyFinalized): unpadder.update(b"") - with pytest.raises(ValueError): + with pytest.raises(AlreadyFinalized): unpadder.finalize() diff --git a/tests/hazmat/primitives/test_rsa.py b/tests/hazmat/primitives/test_rsa.py index 602f5243..38a5d0af 100644 --- a/tests/hazmat/primitives/test_rsa.py +++ b/tests/hazmat/primitives/test_rsa.py @@ -26,7 +26,9 @@ from cryptography.exceptions import _Reasons from cryptography.hazmat.primitives import hashes, interfaces from cryptography.hazmat.primitives.asymmetric import padding, rsa -from .utils import generate_rsa_verification_test +from .utils import ( + _check_rsa_private_key, generate_rsa_verification_test +) from ...utils import ( load_pkcs1_vectors, load_rsa_nist_vectors, load_vectors_from_file, raises_unsupported_algorithm @@ -42,24 +44,6 @@ class DummyMGF(object): _salt_length = 0 -def _check_rsa_private_key(skey): - assert skey - assert skey.modulus - assert skey.public_exponent - assert skey.private_exponent - assert skey.p * skey.q == skey.modulus - assert skey.key_size - assert skey.dmp1 == rsa.rsa_crt_dmp1(skey.d, skey.p) - assert skey.dmq1 == rsa.rsa_crt_dmq1(skey.d, skey.q) - assert skey.iqmp == rsa.rsa_crt_iqmp(skey.p, skey.q) - - pkey = skey.public_key() - assert pkey - assert skey.modulus == pkey.modulus - assert skey.public_exponent == pkey.public_exponent - assert skey.key_size == pkey.key_size - - def _flatten_pkcs1_examples(vectors): flattened_vectors = [] for vector in vectors: @@ -95,7 +79,7 @@ def test_modular_inverse(): @pytest.mark.rsa class TestRSA(object): @pytest.mark.parametrize( - "public_exponent,key_size", + ("public_exponent", "key_size"), itertools.product( (3, 5, 65537), (1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1536, 2048) diff --git a/tests/hazmat/primitives/utils.py b/tests/hazmat/primitives/utils.py index 2e838474..6c3f4c95 100644 --- a/tests/hazmat/primitives/utils.py +++ b/tests/hazmat/primitives/utils.py @@ -406,3 +406,21 @@ def rsa_verification_test(backend, params, hash_alg, pad_factory): verifier.verify() else: verifier.verify() + + +def _check_rsa_private_key(skey): + assert skey + assert skey.modulus + assert skey.public_exponent + assert skey.private_exponent + assert skey.p * skey.q == skey.modulus + assert skey.key_size + assert skey.dmp1 == rsa.rsa_crt_dmp1(skey.d, skey.p) + assert skey.dmq1 == rsa.rsa_crt_dmq1(skey.d, skey.q) + assert skey.iqmp == rsa.rsa_crt_iqmp(skey.p, skey.q) + + pkey = skey.public_key() + assert pkey + assert skey.modulus == pkey.modulus + assert skey.public_exponent == pkey.public_exponent + assert skey.key_size == pkey.key_size diff --git a/tests/test_utils.py b/tests/test_utils.py index b50c21fe..7a0b9e74 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -2638,7 +2638,7 @@ def test_raises_unsupported_no_exc(): def test_raises_unsupported_algorithm(): - # Check that it doesnt assert if the right things are raised. + # Check that it doesn't assert if the right things are raised. with raises_unsupported_algorithm( _Reasons.BACKEND_MISSING_INTERFACE ) as exc_info: |