From 1252dec0c85cd3cb9ea70dcb0ac2a4afc976f2ce Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 18 Jun 2016 11:11:57 -0400 Subject: Drop OpenSSL 0.9.8 (#2978) * Drop OpenSSL 0.9.8 * Drop this test, it's not relevant any longer * unused import * Remove CRYPTOGRAPHY_ALLOW_OPENSSL_098=1 from our tox * removed unused code for Cryptography_HAS_PKEY_CTX * return unused code for _AESCTRCipherContext * syntax :-( * remove some unused tests and skips * remove unused code for Cryptography_HAS_PBKDF2_HMAC * Revert "return unused code for _AESCTRCipherContext" This reverts commit 7d149729205aa4c9735eb322414b167a75b302df. * Remove unused RSA code * Remove unused test code for conditional bindings * Remove unused dsa code * unused import * Remove unused x509 extension code * Remove unused EC code * Attempt to remove unused DER key loading code * document this * grammar * Added back this paragraph * Update docs --- src/_cffi_src/openssl/evp.py | 28 +--- .../hazmat/backends/openssl/backend.py | 132 +++-------------- src/cryptography/hazmat/backends/openssl/rsa.py | 158 ++------------------- .../hazmat/bindings/openssl/_conditional.py | 21 --- .../hazmat/bindings/openssl/binding.py | 16 +-- 5 files changed, 32 insertions(+), 323 deletions(-) (limited to 'src') diff --git a/src/_cffi_src/openssl/evp.py b/src/_cffi_src/openssl/evp.py index 308e2b3c..62847265 100644 --- a/src/_cffi_src/openssl/evp.py +++ b/src/_cffi_src/openssl/evp.py @@ -180,7 +180,7 @@ const long EVP_CTRL_GCM_GET_TAG = -1; const long EVP_CTRL_GCM_SET_TAG = -1; const long EVP_CTRL_GCM_SET_IVLEN = -1; #endif -#if OPENSSL_VERSION_NUMBER >= 0x10000000L + const long Cryptography_HAS_PBKDF2_HMAC = 1; const long Cryptography_HAS_PKEY_CTX = 1; @@ -198,31 +198,7 @@ int Cryptography_EVP_PKEY_decrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t inlen) { return EVP_PKEY_decrypt(ctx, out, outlen, in, inlen); } -#else -const long Cryptography_HAS_PBKDF2_HMAC = 0; -int (*PKCS5_PBKDF2_HMAC)(const char *, int, const unsigned char *, int, int, - const EVP_MD *, int, unsigned char *) = NULL; -const long Cryptography_HAS_PKEY_CTX = 0; -typedef void EVP_PKEY_CTX; -int (*EVP_PKEY_CTX_set_signature_md)(EVP_PKEY_CTX *, const EVP_MD *) = NULL; -int (*EVP_PKEY_sign_init)(EVP_PKEY_CTX *) = NULL; -int (*EVP_PKEY_sign)(EVP_PKEY_CTX *, unsigned char *, size_t *, - const unsigned char *, size_t) = NULL; -int (*EVP_PKEY_verify_init)(EVP_PKEY_CTX *) = NULL; -int (*EVP_PKEY_verify)(EVP_PKEY_CTX *, const unsigned char *, size_t, - const unsigned char *, size_t) = NULL; -EVP_PKEY_CTX *(*EVP_PKEY_CTX_new)(EVP_PKEY *, ENGINE *) = NULL; -EVP_PKEY_CTX *(*EVP_PKEY_CTX_new_id)(int, ENGINE *) = NULL; -EVP_PKEY_CTX *(*EVP_PKEY_CTX_dup)(EVP_PKEY_CTX *) = NULL; -void (*EVP_PKEY_CTX_free)(EVP_PKEY_CTX *) = NULL; -int (*EVP_PKEY_encrypt_init)(EVP_PKEY_CTX *) = NULL; -int (*EVP_PKEY_decrypt_init)(EVP_PKEY_CTX *) = NULL; -int (*Cryptography_EVP_PKEY_encrypt)(EVP_PKEY_CTX *, unsigned char *, size_t *, - const unsigned char *, size_t) = NULL; -int (*Cryptography_EVP_PKEY_decrypt)(EVP_PKEY_CTX *, unsigned char *, size_t *, - const unsigned char *, size_t) = NULL; -int (*EVP_PKEY_id)(const EVP_PKEY *) = NULL; -#endif + #ifdef OPENSSL_NO_EC int (*EVP_PKEY_assign_EC_KEY)(EVP_PKEY *, EC_KEY *) = NULL; EC_KEY *(*EVP_PKEY_get1_EC_KEY)(EVP_PKEY *) = NULL; diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index 9a89ae83..37621b14 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -290,50 +290,25 @@ class Backend(object): return _CipherContext(self, cipher, mode, _CipherContext._DECRYPT) def pbkdf2_hmac_supported(self, algorithm): - if self._lib.Cryptography_HAS_PBKDF2_HMAC: - return self.hmac_supported(algorithm) - else: - # OpenSSL < 1.0.0 has an explicit PBKDF2-HMAC-SHA1 function, - # so if the PBKDF2_HMAC function is missing we only support - # SHA1 via PBKDF2_HMAC_SHA1. - return isinstance(algorithm, hashes.SHA1) + return self.hmac_supported(algorithm) def derive_pbkdf2_hmac(self, algorithm, length, salt, iterations, key_material): buf = self._ffi.new("char[]", length) - if self._lib.Cryptography_HAS_PBKDF2_HMAC: - evp_md = self._lib.EVP_get_digestbyname( - algorithm.name.encode("ascii")) - self.openssl_assert(evp_md != self._ffi.NULL) - res = self._lib.PKCS5_PBKDF2_HMAC( - key_material, - len(key_material), - salt, - len(salt), - iterations, - evp_md, - length, - buf - ) - self.openssl_assert(res == 1) - else: - if not isinstance(algorithm, hashes.SHA1): - raise UnsupportedAlgorithm( - "This version of OpenSSL only supports PBKDF2HMAC with " - "SHA1.", - _Reasons.UNSUPPORTED_HASH - ) - res = self._lib.PKCS5_PBKDF2_HMAC_SHA1( - key_material, - len(key_material), - salt, - len(salt), - iterations, - length, - buf - ) - self.openssl_assert(res == 1) - + evp_md = self._lib.EVP_get_digestbyname( + algorithm.name.encode("ascii")) + self.openssl_assert(evp_md != self._ffi.NULL) + res = self._lib.PKCS5_PBKDF2_HMAC( + key_material, + len(key_material), + salt, + len(salt), + iterations, + evp_md, + length, + buf + ) + self.openssl_assert(res == 1) return self._ffi.buffer(buf)[:] def _consume_errors(self): @@ -617,12 +592,6 @@ class Backend(object): if key_size not in (1024, 2048, 3072): raise ValueError("Key size must be 1024 or 2048 or 3072 bits.") - if (self._lib.OPENSSL_VERSION_NUMBER < 0x1000000f and - key_size > 1024): - raise ValueError( - "Key size must be 1024 because OpenSSL < 1.0.0 doesn't " - "support larger key sizes.") - ctx = self._lib.DSA_new() self.openssl_assert(ctx != self._ffi.NULL) ctx = self._ffi.gc(ctx, self._lib.DSA_free) @@ -731,16 +700,10 @@ class Backend(object): return evp_pkey def dsa_hash_supported(self, algorithm): - if self._lib.OPENSSL_VERSION_NUMBER < 0x1000000f: - return isinstance(algorithm, hashes.SHA1) - else: - return self.hash_supported(algorithm) + return self.hash_supported(algorithm) def dsa_parameters_supported(self, p, q, g): - if self._lib.OPENSSL_VERSION_NUMBER < 0x1000000f: - return utils.bit_length(p) <= 1024 and utils.bit_length(q) <= 160 - else: - return True + return True def cmac_algorithm_supported(self, algorithm): return ( @@ -1049,32 +1012,9 @@ class Backend(object): extension.oid.dotted_string.encode("ascii") ) backend.openssl_assert(nid != self._lib.NID_undef) - x509_extension = self._lib.X509V3_EXT_i2d( + return self._lib.X509V3_EXT_i2d( nid, 1 if extension.critical else 0, ext_struct ) - if ( - x509_extension == self._ffi.NULL and - extension.oid == x509.OID_CERTIFICATE_ISSUER - ): - # This path exists to support OpenSSL 0.9.8, which does not - # know how to encode a CERTIFICATE_ISSUER for CRLs. Once we - # drop 0.9.8 support we can remove this. - self._consume_errors() - pp = backend._ffi.new("unsigned char **") - r = self._lib.i2d_GENERAL_NAMES(ext_struct, pp) - backend.openssl_assert(r > 0) - pp = backend._ffi.gc( - pp, - lambda pointer: backend._lib.OPENSSL_free(pointer[0]) - ) - obj = _txt2obj_gc(self, extension.oid.dotted_string) - return self._lib.X509_EXTENSION_create_by_OBJ( - self._ffi.NULL, - obj, - 1 if extension.critical else 0, - _encode_asn1_str_gc(self, pp[0], r) - ) - return x509_extension def create_x509_revoked_certificate(self, builder): if not isinstance(builder, x509.RevokedCertificateBuilder): @@ -1142,19 +1082,10 @@ class Backend(object): def load_der_private_key(self, data, password): # OpenSSL has a function called d2i_AutoPrivateKey that can simplify # this. Unfortunately it doesn't properly support PKCS8 on OpenSSL - # 0.9.8 so we can't use it. Instead we sequentially try to load it 3 + # 0.9.8 so we can't use it. Instead we sequentially try to load it 2 # different ways. First we'll try to load it as a traditional key bio_data = self._bytes_to_bio(data) key = self._evp_pkey_from_der_traditional_key(bio_data, password) - if not key: - # Okay so it's not a traditional key. Let's try - # PKCS8 unencrypted. OpenSSL 0.9.8 can't load unencrypted - # PKCS8 keys using d2i_PKCS8PrivateKey_bio so we do this instead. - # Reset the memory BIO so we can read the data again. - res = self._lib.BIO_reset(bio_data.bio) - self.openssl_assert(res == 1) - key = self._evp_pkey_from_der_unencrypted_pkcs8(bio_data, password) - if key: return self._evp_pkey_to_private_key(key) else: @@ -1181,24 +1112,6 @@ class Backend(object): self._consume_errors() return None - def _evp_pkey_from_der_unencrypted_pkcs8(self, bio_data, password): - info = self._lib.d2i_PKCS8_PRIV_KEY_INFO_bio( - bio_data.bio, self._ffi.NULL - ) - info = self._ffi.gc(info, self._lib.PKCS8_PRIV_KEY_INFO_free) - if info != self._ffi.NULL: - key = self._lib.EVP_PKCS82PKEY(info) - self.openssl_assert(key != self._ffi.NULL) - key = self._ffi.gc(key, self._lib.EVP_PKEY_free) - if password is not None: - raise TypeError( - "Password was given but private key is not encrypted." - ) - return key - else: - self._consume_errors() - return None - def load_der_public_key(self, data): mem_bio = self._bytes_to_bio(data) evp_pkey = self._lib.d2i_PUBKEY_bio(mem_bio.bio, self._ffi.NULL) @@ -1418,13 +1331,6 @@ class Backend(object): if not isinstance(signature_algorithm, ec.ECDSA): return False - # Before 0.9.8m OpenSSL can't cope with digests longer than the curve. - if ( - self._lib.OPENSSL_VERSION_NUMBER < 0x009080df and - curve.key_size < signature_algorithm.algorithm.digest_size * 8 - ): - return False - return self.elliptic_curve_supported(curve) def generate_elliptic_curve_private_key(self, curve): diff --git a/src/cryptography/hazmat/backends/openssl/rsa.py b/src/cryptography/hazmat/backends/openssl/rsa.py index 10c51fee..e0f2a853 100644 --- a/src/cryptography/hazmat/backends/openssl/rsa.py +++ b/src/cryptography/hazmat/backends/openssl/rsa.py @@ -8,7 +8,7 @@ import math from cryptography import utils from cryptography.exceptions import ( - AlreadyFinalized, InvalidSignature, UnsupportedAlgorithm, _Reasons + InvalidSignature, UnsupportedAlgorithm, _Reasons ) from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.asymmetric import ( @@ -68,10 +68,7 @@ def _enc_dec_rsa(backend, key, data, padding): _Reasons.UNSUPPORTED_PADDING ) - if backend._lib.Cryptography_HAS_PKEY_CTX: - return _enc_dec_rsa_pkey_ctx(backend, key, data, padding_enum, padding) - else: - return _enc_dec_rsa_098(backend, key, data, padding_enum) + return _enc_dec_rsa_pkey_ctx(backend, key, data, padding_enum, padding) def _enc_dec_rsa_pkey_ctx(backend, key, data, padding_enum, padding): @@ -118,22 +115,6 @@ def _enc_dec_rsa_pkey_ctx(backend, key, data, padding_enum, padding): return backend._ffi.buffer(buf)[:outlen[0]] -def _enc_dec_rsa_098(backend, key, data, padding_enum): - if isinstance(key, _RSAPublicKey): - crypt = backend._lib.RSA_public_encrypt - else: - crypt = backend._lib.RSA_private_decrypt - - key_size = backend._lib.RSA_size(key._rsa_cdata) - backend.openssl_assert(key_size > 0) - buf = backend._ffi.new("unsigned char[]", key_size) - res = crypt(len(data), data, buf, key._rsa_cdata, padding_enum) - if res < 0: - _handle_rsa_enc_dec_error(backend, key) - - return backend._ffi.buffer(buf)[:res] - - def _handle_rsa_enc_dec_error(backend, key): errors = backend._consume_errors() assert errors @@ -177,11 +158,8 @@ class _RSASignatureContext(object): self._backend.openssl_assert(self._pkey_size > 0) if isinstance(padding, PKCS1v15): - if self._backend._lib.Cryptography_HAS_PKEY_CTX: - self._finalize_method = self._finalize_pkey_ctx - self._padding_enum = self._backend._lib.RSA_PKCS1_PADDING - else: - self._finalize_method = self._finalize_pkcs1 + self._finalize_method = self._finalize_pkey_ctx + self._padding_enum = self._backend._lib.RSA_PKCS1_PADDING elif isinstance(padding, PSS): if not isinstance(padding._mgf, MGF1): raise UnsupportedAlgorithm( @@ -204,11 +182,8 @@ class _RSASignatureContext(object): _Reasons.UNSUPPORTED_HASH ) - if self._backend._lib.Cryptography_HAS_PKEY_CTX: - self._finalize_method = self._finalize_pkey_ctx - self._padding_enum = self._backend._lib.RSA_PKCS1_PSS_PADDING - else: - self._finalize_method = self._finalize_pss + self._finalize_method = self._finalize_pkey_ctx + self._padding_enum = self._backend._lib.RSA_PKCS1_PSS_PADDING else: raise UnsupportedAlgorithm( "{0} is not supported by this backend.".format(padding.name), @@ -297,62 +272,6 @@ class _RSASignatureContext(object): return self._backend._ffi.buffer(buf)[:] - def _finalize_pkcs1(self, evp_md): - if self._hash_ctx._ctx is None: - raise AlreadyFinalized("Context has already been finalized.") - - sig_buf = self._backend._ffi.new("char[]", self._pkey_size) - sig_len = self._backend._ffi.new("unsigned int *") - res = self._backend._lib.EVP_SignFinal( - self._hash_ctx._ctx._ctx, - sig_buf, - sig_len, - self._private_key._evp_pkey - ) - self._hash_ctx.finalize() - if res == 0: - errors = self._backend._consume_errors() - assert errors[0].lib == self._backend._lib.ERR_LIB_RSA - assert (errors[0].reason == - self._backend._lib.RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY) - raise ValueError("Digest too large for key size. Use a larger " - "key.") - - return self._backend._ffi.buffer(sig_buf)[:sig_len[0]] - - def _finalize_pss(self, evp_md): - data_to_sign = self._hash_ctx.finalize() - padded = self._backend._ffi.new("unsigned char[]", self._pkey_size) - res = self._backend._lib.RSA_padding_add_PKCS1_PSS( - self._private_key._rsa_cdata, - padded, - data_to_sign, - evp_md, - _get_rsa_pss_salt_length( - self._padding, - self._private_key.key_size, - len(data_to_sign) - ) - ) - if res != 1: - errors = self._backend._consume_errors() - assert errors[0].lib == self._backend._lib.ERR_LIB_RSA - assert (errors[0].reason == - self._backend._lib.RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE) - raise ValueError("Salt length too long for key size. Try using " - "MAX_LENGTH instead.") - - sig_buf = self._backend._ffi.new("char[]", self._pkey_size) - sig_len = self._backend._lib.RSA_private_encrypt( - self._pkey_size, - padded, - sig_buf, - self._private_key._rsa_cdata, - self._backend._lib.RSA_NO_PADDING - ) - self._backend.openssl_assert(sig_len != -1) - return self._backend._ffi.buffer(sig_buf)[:sig_len] - @utils.register_interface(AsymmetricVerificationContext) class _RSAVerificationContext(object): @@ -370,11 +289,8 @@ class _RSAVerificationContext(object): self._backend.openssl_assert(self._pkey_size > 0) if isinstance(padding, PKCS1v15): - if self._backend._lib.Cryptography_HAS_PKEY_CTX: - self._verify_method = self._verify_pkey_ctx - self._padding_enum = self._backend._lib.RSA_PKCS1_PADDING - else: - self._verify_method = self._verify_pkcs1 + self._verify_method = self._verify_pkey_ctx + self._padding_enum = self._backend._lib.RSA_PKCS1_PADDING elif isinstance(padding, PSS): if not isinstance(padding._mgf, MGF1): raise UnsupportedAlgorithm( @@ -399,11 +315,8 @@ class _RSAVerificationContext(object): _Reasons.UNSUPPORTED_HASH ) - if self._backend._lib.Cryptography_HAS_PKEY_CTX: - self._verify_method = self._verify_pkey_ctx - self._padding_enum = self._backend._lib.RSA_PKCS1_PSS_PADDING - else: - self._verify_method = self._verify_pss + self._verify_method = self._verify_pkey_ctx + self._padding_enum = self._backend._lib.RSA_PKCS1_PSS_PADDING else: raise UnsupportedAlgorithm( "{0} is not supported by this backend.".format(padding.name), @@ -479,57 +392,6 @@ class _RSAVerificationContext(object): assert errors raise InvalidSignature - def _verify_pkcs1(self, evp_md): - if self._hash_ctx._ctx is None: - raise AlreadyFinalized("Context has already been finalized.") - - res = self._backend._lib.EVP_VerifyFinal( - self._hash_ctx._ctx._ctx, - self._signature, - len(self._signature), - self._public_key._evp_pkey - ) - self._hash_ctx.finalize() - # The previous call can return negative numbers in the event of an - # error. This is not a signature failure but we need to fail if it - # occurs. - self._backend.openssl_assert(res >= 0) - if res == 0: - errors = self._backend._consume_errors() - assert errors - raise InvalidSignature - - def _verify_pss(self, evp_md): - buf = self._backend._ffi.new("unsigned char[]", self._pkey_size) - res = self._backend._lib.RSA_public_decrypt( - len(self._signature), - self._signature, - buf, - self._public_key._rsa_cdata, - self._backend._lib.RSA_NO_PADDING - ) - if res != self._pkey_size: - errors = self._backend._consume_errors() - assert errors - raise InvalidSignature - - data_to_verify = self._hash_ctx.finalize() - res = self._backend._lib.RSA_verify_PKCS1_PSS( - self._public_key._rsa_cdata, - data_to_verify, - evp_md, - buf, - _get_rsa_pss_salt_length( - self._padding, - self._public_key.key_size, - len(data_to_verify) - ) - ) - if res != 1: - errors = self._backend._consume_errors() - assert errors - raise InvalidSignature - @utils.register_interface(RSAPrivateKeyWithSerialization) class _RSAPrivateKey(object): diff --git a/src/cryptography/hazmat/bindings/openssl/_conditional.py b/src/cryptography/hazmat/bindings/openssl/_conditional.py index 18bb54b6..bdfeca91 100644 --- a/src/cryptography/hazmat/bindings/openssl/_conditional.py +++ b/src/cryptography/hazmat/bindings/openssl/_conditional.py @@ -215,27 +215,6 @@ CONDITIONAL_NAMES = { "EVP_CTRL_GCM_SET_TAG", "EVP_CTRL_GCM_SET_IVLEN", ], - "Cryptography_HAS_PBKDF2_HMAC": [ - "PKCS5_PBKDF2_HMAC" - ], - "Cryptography_HAS_PKEY_CTX": [ - "EVP_PKEY_CTX_new", - "EVP_PKEY_CTX_new_id", - "EVP_PKEY_CTX_dup", - "EVP_PKEY_CTX_free", - "EVP_PKEY_sign", - "EVP_PKEY_sign_init", - "EVP_PKEY_verify", - "EVP_PKEY_verify_init", - "Cryptography_EVP_PKEY_encrypt", - "EVP_PKEY_encrypt_init", - "Cryptography_EVP_PKEY_decrypt", - "EVP_PKEY_decrypt_init", - "EVP_PKEY_CTX_set_signature_md", - "EVP_PKEY_id", - "EVP_PKEY_CTX_set_rsa_padding", - "EVP_PKEY_CTX_set_rsa_pss_saltlen", - ], "Cryptography_HAS_ECDSA_SHA2_NIDS": [ "NID_ecdsa_with_SHA224", "NID_ecdsa_with_SHA256", diff --git a/src/cryptography/hazmat/bindings/openssl/binding.py b/src/cryptography/hazmat/bindings/openssl/binding.py index 7727ad8d..2b9dca5c 100644 --- a/src/cryptography/hazmat/bindings/openssl/binding.py +++ b/src/cryptography/hazmat/bindings/openssl/binding.py @@ -217,21 +217,7 @@ class Binding(object): def _verify_openssl_version(version): - if version < 0x10000000: - if os.environ.get("CRYPTOGRAPHY_ALLOW_OPENSSL_098"): - warnings.warn( - "OpenSSL version 0.9.8 is no longer supported by the OpenSSL " - "project, please upgrade. The next version of cryptography " - "will completely remove support for it.", - DeprecationWarning - ) - else: - raise RuntimeError( - "You are linking against OpenSSL 0.9.8, which is no longer " - "support by the OpenSSL project. You need to upgrade to a " - "newer version of OpenSSL." - ) - elif version < 0x10001000: + if version < 0x10001000: warnings.warn( "OpenSSL versions less than 1.0.1 are no longer supported by the " "OpenSSL project, please upgrade. A future version of " -- cgit v1.2.3