diff --git a/Revert-Another-sweep-removing-unused-bindings-9671.patch b/Revert-Another-sweep-removing-unused-bindings-9671.patch new file mode 100644 index 0000000000000000000000000000000000000000..b4ba76ec40cd50a2f4bb5d831a83e991219dc197 --- /dev/null +++ b/Revert-Another-sweep-removing-unused-bindings-9671.patch @@ -0,0 +1,64 @@ +From 0b350a4d2d97cbb0ae52e929cfaed1e25bc79845 Mon Sep 17 00:00:00 2001 +From: sxt1001 +Date: Sun, 25 May 2025 05:52:26 +0800 +Subject: [PATCH 3/5] Revert 'Another sweep removing unused bindings (#9671)' + +https://github.com/pyca/cryptography/commit/057241cd302271467a11dd796c41328b50460b0f +--- + src/_cffi_src/openssl/evp.py | 23 +++++++++++++++++++++++ + 1 file changed, 23 insertions(+) + +diff --git a/src/_cffi_src/openssl/evp.py b/src/_cffi_src/openssl/evp.py +index c304684..f1bf36d 100644 +--- a/src/_cffi_src/openssl/evp.py ++++ b/src/_cffi_src/openssl/evp.py +@@ -61,6 +61,11 @@ int EVP_PKEY_type(int); + int EVP_PKEY_size(EVP_PKEY *); + RSA *EVP_PKEY_get1_RSA(EVP_PKEY *); + ++int EVP_PKEY_encrypt(EVP_PKEY_CTX *, unsigned char *, size_t *, ++ const unsigned char *, size_t); ++int EVP_PKEY_decrypt(EVP_PKEY_CTX *, unsigned char *, size_t *, ++ const unsigned char *, size_t); ++ + int EVP_SignInit(EVP_MD_CTX *, const EVP_MD *); + int EVP_SignUpdate(EVP_MD_CTX *, const void *, size_t); + int EVP_SignFinal(EVP_MD_CTX *, unsigned char *, unsigned int *, EVP_PKEY *); +@@ -74,9 +79,25 @@ int EVP_DigestVerifyUpdate(EVP_MD_CTX *, const void *, size_t); + int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sig, + size_t siglen); + ++EVP_PKEY_CTX *EVP_PKEY_CTX_new(EVP_PKEY *, ENGINE *); ++void EVP_PKEY_CTX_free(EVP_PKEY_CTX *); ++int EVP_PKEY_sign_init(EVP_PKEY_CTX *); ++int EVP_PKEY_sign(EVP_PKEY_CTX *, unsigned char *, size_t *, ++ const unsigned char *, size_t); ++int EVP_PKEY_verify_init(EVP_PKEY_CTX *); ++int EVP_PKEY_verify(EVP_PKEY_CTX *, const unsigned char *, size_t, ++ const unsigned char *, size_t); ++int EVP_PKEY_verify_recover_init(EVP_PKEY_CTX *); ++int EVP_PKEY_verify_recover(EVP_PKEY_CTX *, unsigned char *, ++ size_t *, const unsigned char *, size_t); ++int EVP_PKEY_encrypt_init(EVP_PKEY_CTX *); ++int EVP_PKEY_decrypt_init(EVP_PKEY_CTX *); ++ + int EVP_PKEY_set1_RSA(EVP_PKEY *, RSA *); + int EVP_PKEY_set1_DSA(EVP_PKEY *, DSA *); + ++int EVP_PKEY_cmp(const EVP_PKEY *, const EVP_PKEY *); ++ + int EVP_PKEY_id(const EVP_PKEY *); + + EVP_MD_CTX *EVP_MD_CTX_new(void); +@@ -91,6 +112,8 @@ int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *, int, int, void *); + void EVP_MD_CTX_set_pkey_ctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX *pctx); + const EVP_MD *EVP_sm3(void); + ++int EVP_PKEY_CTX_set_signature_md(EVP_PKEY_CTX *, const EVP_MD *); ++ + int EVP_default_properties_enable_fips(OSSL_LIB_CTX *, int); + """ + +-- +2.43.0 + diff --git a/Revert-Remove-now-unused-OpenSSL-password-callback-1.patch b/Revert-Remove-now-unused-OpenSSL-password-callback-1.patch new file mode 100644 index 0000000000000000000000000000000000000000..9093bdc5d605aa56327086e9146d048850d4d32e --- /dev/null +++ b/Revert-Remove-now-unused-OpenSSL-password-callback-1.patch @@ -0,0 +1,125 @@ +From ef16eb7f84e5cdc9e0574092003d7227a9e2a8a5 Mon Sep 17 00:00:00 2001 +From: sxt1001 +Date: Sun, 25 May 2025 05:49:10 +0800 +Subject: [PATCH 2/5] Revert 'Remove now unused OpenSSL password callback + (#10145)' + +https://github.com/pyca/cryptography/commit/efb98b43f89466ff8034b5fe7667980e6cba31fb +--- + src/_cffi_src/build_openssl.py | 1 + + src/_cffi_src/openssl/callbacks.py | 52 +++++++++++++++++++++++++++ + tests/hazmat/backends/test_openssl.py | 27 ++++++++++++++ + 3 files changed, 80 insertions(+) + create mode 100644 src/_cffi_src/openssl/callbacks.py + +diff --git a/src/_cffi_src/build_openssl.py b/src/_cffi_src/build_openssl.py +index 6065e7a..5af6762 100644 +--- a/src/_cffi_src/build_openssl.py ++++ b/src/_cffi_src/build_openssl.py +@@ -46,6 +46,7 @@ ffi = build_ffi_for_binding( + "x509v3", + "x509_vfy", + "pkcs7", ++ "callbacks", + ], + ) + +diff --git a/src/_cffi_src/openssl/callbacks.py b/src/_cffi_src/openssl/callbacks.py +new file mode 100644 +index 0000000..ddb7642 +--- /dev/null ++++ b/src/_cffi_src/openssl/callbacks.py +@@ -0,0 +1,52 @@ ++# 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 annotations ++ ++INCLUDES = """ ++#include ++""" ++ ++TYPES = """ ++typedef struct { ++ char *password; ++ int length; ++ int called; ++ int error; ++ int maxsize; ++} CRYPTOGRAPHY_PASSWORD_DATA; ++""" ++ ++FUNCTIONS = """ ++int Cryptography_pem_password_cb(char *, int, int, void *); ++""" ++ ++CUSTOMIZATIONS = """ ++typedef struct { ++ char *password; ++ int length; ++ int called; ++ int error; ++ int maxsize; ++} CRYPTOGRAPHY_PASSWORD_DATA; ++ ++int Cryptography_pem_password_cb(char *buf, int size, ++ int rwflag, void *userdata) { ++ /* The password cb is only invoked if OpenSSL decides the private ++ key is encrypted. So this path only occurs if it needs a password */ ++ CRYPTOGRAPHY_PASSWORD_DATA *st = (CRYPTOGRAPHY_PASSWORD_DATA *)userdata; ++ st->called += 1; ++ st->maxsize = size; ++ if (st->length == 0) { ++ st->error = -1; ++ return 0; ++ } else if (st->length < size) { ++ memcpy(buf, st->password, (size_t)st->length); ++ return st->length; ++ } else { ++ st->error = -2; ++ return 0; ++ } ++} ++""" +diff --git a/tests/hazmat/backends/test_openssl.py b/tests/hazmat/backends/test_openssl.py +index a289c5b..5c86731 100644 +--- a/tests/hazmat/backends/test_openssl.py ++++ b/tests/hazmat/backends/test_openssl.py +@@ -238,6 +238,33 @@ class TestOpenSSLRSA: + + + class TestOpenSSLSerializationWithOpenSSL: ++ def test_pem_password_cb(self): ++ userdata = backend._ffi.new("CRYPTOGRAPHY_PASSWORD_DATA *") ++ pw = b"abcdefg" ++ password = backend._ffi.new("char []", pw) ++ userdata.password = password ++ userdata.length = len(pw) ++ buflen = 10 ++ buf = backend._ffi.new("char []", buflen) ++ res = backend._lib.Cryptography_pem_password_cb( ++ buf, buflen, 0, userdata ++ ) ++ assert res == len(pw) ++ assert userdata.called == 1 ++ assert backend._ffi.buffer(buf, len(pw))[:] == pw ++ assert userdata.maxsize == buflen ++ assert userdata.error == 0 ++ ++ def test_pem_password_cb_no_password(self): ++ userdata = backend._ffi.new("CRYPTOGRAPHY_PASSWORD_DATA *") ++ buflen = 10 ++ buf = backend._ffi.new("char []", buflen) ++ res = backend._lib.Cryptography_pem_password_cb( ++ buf, buflen, 0, userdata ++ ) ++ assert res == 0 ++ assert userdata.error == -1 ++ + def test_unsupported_evp_pkey_type(self): + key = backend._lib.EVP_PKEY_new() + key = backend._ffi.gc(key, backend._lib.EVP_PKEY_free) +-- +2.43.0 + diff --git a/Revert-Remove-now-unused-bindings-8778.patch b/Revert-Remove-now-unused-bindings-8778.patch new file mode 100644 index 0000000000000000000000000000000000000000..38f6e2499c99a160bece4ac295b239e12fa9d95e --- /dev/null +++ b/Revert-Remove-now-unused-bindings-8778.patch @@ -0,0 +1,49 @@ +From d07a36b452c23ed3b773bda49ebb811aab730718 Mon Sep 17 00:00:00 2001 +From: sxt1001 +Date: Sun, 25 May 2025 06:05:42 +0800 +Subject: [PATCH 5/5] Revert 'Remove now unused bindings (#8778)' + +https://github.com/pyca/cryptography/commit/c7cbfeccac42e434a5c67578054b9b5df50659bb +--- + src/_cffi_src/openssl/evp.py | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/src/_cffi_src/openssl/evp.py b/src/_cffi_src/openssl/evp.py +index e01b22f..5b0cd46 100644 +--- a/src/_cffi_src/openssl/evp.py ++++ b/src/_cffi_src/openssl/evp.py +@@ -53,6 +53,10 @@ EVP_CIPHER_CTX *EVP_CIPHER_CTX_new(void); + void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *); + int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *, int); + ++int EVP_MD_CTX_copy_ex(EVP_MD_CTX *, const EVP_MD_CTX *); ++int EVP_DigestInit_ex(EVP_MD_CTX *, const EVP_MD *, ENGINE *); ++int EVP_DigestUpdate(EVP_MD_CTX *, const void *, size_t); ++int EVP_DigestFinal_ex(EVP_MD_CTX *, unsigned char *, unsigned int *); + const EVP_MD *EVP_get_digestbyname(const char *); + + EVP_PKEY *EVP_PKEY_new(void); +@@ -83,8 +87,11 @@ int EVP_DigestSignFinal(EVP_MD_CTX *, unsigned char *, size_t *); + int EVP_DigestVerifyUpdate(EVP_MD_CTX *, const void *, size_t); + int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sig, + size_t siglen); ++int EVP_DigestVerifyInit(EVP_MD_CTX *, EVP_PKEY_CTX **, const EVP_MD *, ++ ENGINE *, EVP_PKEY *); + + EVP_PKEY_CTX *EVP_PKEY_CTX_new(EVP_PKEY *, ENGINE *); ++EVP_PKEY_CTX *EVP_PKEY_CTX_new_id(int, ENGINE *); + void EVP_PKEY_CTX_free(EVP_PKEY_CTX *); + int EVP_PKEY_sign_init(EVP_PKEY_CTX *); + int EVP_PKEY_sign(EVP_PKEY_CTX *, unsigned char *, size_t *, +@@ -110,6 +117,8 @@ void EVP_MD_CTX_free(EVP_MD_CTX *); + + int EVP_DigestSign(EVP_MD_CTX *, unsigned char *, size_t *, + const unsigned char *, size_t); ++int EVP_DigestVerify(EVP_MD_CTX *, const unsigned char *, size_t, ++ const unsigned char *, size_t); + + int EVP_PKEY_bits(const EVP_PKEY *); + +-- +2.43.0 + diff --git a/Revert-Remove-unused-bindings-8972.patch b/Revert-Remove-unused-bindings-8972.patch new file mode 100644 index 0000000000000000000000000000000000000000..817403bdcb0e1230b03e8003882baabce0a36d9a --- /dev/null +++ b/Revert-Remove-unused-bindings-8972.patch @@ -0,0 +1,39 @@ +From 985b1b01dfa9976d1b845cd5b24a932c0a30ec48 Mon Sep 17 00:00:00 2001 +From: sxt1001 +Date: Sun, 25 May 2025 06:01:19 +0800 +Subject: [PATCH 4/5] Revert 'Remove unused bindings (#8972)' + +https://github.com/pyca/cryptography/commit/288c302b5041c45dbdb1a567885f50cf953519a7 +--- + src/_cffi_src/openssl/evp.py | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/src/_cffi_src/openssl/evp.py b/src/_cffi_src/openssl/evp.py +index f1bf36d..e01b22f 100644 +--- a/src/_cffi_src/openssl/evp.py ++++ b/src/_cffi_src/openssl/evp.py +@@ -75,6 +75,11 @@ int EVP_VerifyUpdate(EVP_MD_CTX *, const void *, size_t); + int EVP_VerifyFinal(EVP_MD_CTX *, const unsigned char *, unsigned int, + EVP_PKEY *); + ++int EVP_DigestSignInit(EVP_MD_CTX *, EVP_PKEY_CTX **, const EVP_MD *, ++ ENGINE *, EVP_PKEY *); ++int EVP_DigestSignUpdate(EVP_MD_CTX *, const void *, size_t); ++int EVP_DigestSignFinal(EVP_MD_CTX *, unsigned char *, size_t *); ++ + int EVP_DigestVerifyUpdate(EVP_MD_CTX *, const void *, size_t); + int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sig, + size_t siglen); +@@ -103,6 +108,9 @@ int EVP_PKEY_id(const EVP_PKEY *); + EVP_MD_CTX *EVP_MD_CTX_new(void); + void EVP_MD_CTX_free(EVP_MD_CTX *); + ++int EVP_DigestSign(EVP_MD_CTX *, unsigned char *, size_t *, ++ const unsigned char *, size_t); ++ + int EVP_PKEY_bits(const EVP_PKEY *); + + int EVP_PKEY_assign_RSA(EVP_PKEY *, RSA *); +-- +2.43.0 + diff --git a/add-_load_key-function.patch b/add-_load_key-function.patch new file mode 100644 index 0000000000000000000000000000000000000000..744e926e15a5d9220f1cc534bc42cdffdaba4728 --- /dev/null +++ b/add-_load_key-function.patch @@ -0,0 +1,81 @@ +From 7dfaeee7c960f1f9ef87219ab1512d9feaa32d4a Mon Sep 17 00:00:00 2001 +From: sxt1001 +Date: Sun, 25 May 2025 04:34:13 +0800 +Subject: [PATCH 1/5] add _load_key() function + +Migrate private key parsing to Rust: +https://github.com/pyca/cryptography/commit/35dce91babab3e3e7553be2bbd10f87e06f25893#diff-f5134bf8f3cf0a5cc8601df55e50697acc866c603a38caff98802bd8e17976c5 (delete _load_key() function) + +add unsafe_skip_rsa_key_validation: +https://github.com/pyca/cryptography/commit/01687d63a5cb4475d84feae959bec6dea5fce3f1#diff-f5134bf8f3cf0a5cc8601df55e50697acc866c603a38caff98802bd8e17976c5 +--- + .../hazmat/backends/openssl/backend.py | 53 +++++++++++++++++++ + 1 file changed, 53 insertions(+) + +diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py +index 12fbebe..7d0769d 100644 +--- a/src/cryptography/hazmat/backends/openssl/backend.py ++++ b/src/cryptography/hazmat/backends/openssl/backend.py +@@ -453,6 +453,59 @@ class Backend: + self.openssl_assert(evp_pkey != self._ffi.NULL) + return self._ffi.gc(evp_pkey, self._lib.EVP_PKEY_free) + ++ def _load_key(self, openssl_read_func, convert_func, data, password): ++ mem_bio = self._bytes_to_bio(data) ++ ++ userdata = self._ffi.new("CRYPTOGRAPHY_PASSWORD_DATA *") ++ if password is not None: ++ utils._check_byteslike("password", password) ++ password_ptr = self._ffi.from_buffer(password) ++ userdata.password = password_ptr ++ userdata.length = len(password) ++ ++ evp_pkey = openssl_read_func( ++ mem_bio.bio, ++ self._ffi.NULL, ++ self._ffi.addressof( ++ self._lib._original_lib, "Cryptography_pem_password_cb" ++ ), ++ userdata, ++ ) ++ ++ if evp_pkey == self._ffi.NULL: ++ if userdata.error != 0: ++ self._consume_errors() ++ if userdata.error == -1: ++ raise TypeError( ++ "Password was not given but private key is encrypted" ++ ) ++ else: ++ assert userdata.error == -2 ++ raise ValueError( ++ "Passwords longer than {} bytes are not supported " ++ "by this backend.".format(userdata.maxsize - 1) ++ ) ++ else: ++ self._handle_key_loading_error() ++ ++ # In OpenSSL 3.0.0-alpha15 there exist scenarios where the key will ++ # successfully load but errors are still put on the stack. Tracked ++ # as https://github.com/openssl/openssl/issues/14996 ++ self._consume_errors() ++ ++ evp_pkey = self._ffi.gc(evp_pkey, self._lib.EVP_PKEY_free) ++ ++ if password is not None and userdata.called == 0: ++ raise TypeError( ++ "Password was given but private key is not encrypted." ++ ) ++ ++ assert ( ++ password is not None and userdata.called == 1 ++ ) or password is None ++ ++ return convert_func(evp_pkey) ++ + def _handle_key_loading_error( + self, errors: list[rust_openssl.OpenSSLError] + ) -> typing.NoReturn: +-- +2.43.0 + diff --git a/python-cryptography.spec b/python-cryptography.spec index d99157803f2be62622924902f99e47f4966a0ce5..22857883353c05db70dedb294ffb175d8853eca5 100644 --- a/python-cryptography.spec +++ b/python-cryptography.spec @@ -1,7 +1,7 @@ %global pypi_name cryptography Name: python-%{pypi_name} Version: 42.0.2 -Release: 5 +Release: 6 Summary: PyCA's cryptography library License: ASL 2.0 or BSD URL: https://cryptography.io/en/latest/ @@ -17,6 +17,12 @@ Source2: sw64-vendor.tar.gz Patch6002: backport-provide-openssl-apis-related-to-SM-for-python.patch Patch6003: backport-CVE-2024-26130.patch +Patch9000: add-_load_key-function.patch +Patch9001: Revert-Remove-now-unused-OpenSSL-password-callback-1.patch +Patch9002: Revert-Another-sweep-removing-unused-bindings-9671.patch +Patch9003: Revert-Remove-unused-bindings-8972.patch +Patch9004: Revert-Remove-now-unused-bindings-8778.patch + BuildRequires: openssl-devel cargo BuildRequires: gcc BuildRequires: rust-packaging rust @@ -100,6 +106,9 @@ PYTHONPATH=%{buildroot}%{python3_sitearch} %{__python3} -m pytest --ignore vendo %doc README.rst docs %changelog +* Tue Jun 10 2025 shixuantong - 42.0.2-6 +- Revert bound openssl symbols to support sm2 for python + * Mon May 12 2025 mahailiang - 42.0.2-5 - add sw_64 support