internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: pyca/cryptography

Issue:
Create a new installation document
Move all details about various platforms there.



Discussion:

Resolving patch:
diff --git a/cryptography/hazmat/backends/commoncrypto/backend.py b/cryptography/hazmat/backends/commoncrypto/backend.py
--- a/cryptography/hazmat/backends/commoncrypto/backend.py
+++ b/cryptography/hazmat/backends/commoncrypto/backend.py
@@ -20,7 +20,7 @@
     UnsupportedAlgorithm, InvalidTag, InternalError
 )
 from cryptography.hazmat.backends.interfaces import (
-    HashBackend, HMACBackend, CipherBackend
+    HashBackend, HMACBackend, CipherBackend, PBKDF2HMACBackend
 )
 from cryptography.hazmat.bindings.commoncrypto.binding import Binding
 from cryptography.hazmat.primitives import interfaces, constant_time
@@ -40,6 +40,7 @@
 @utils.register_interface(CipherBackend)
 @utils.register_interface(HashBackend)
 @utils.register_interface(HMACBackend)
+@utils.register_interface(PBKDF2HMACBackend)
 class Backend(object):
     """
     CommonCrypto API wrapper.
@@ -89,6 +90,14 @@ def __init__(self):
             "sha512": self._lib.kCCHmacAlgSHA512,
         }
 
+        self._supported_pbkdf2_hmac_algorithms = {
+            "sha1": self._lib.kCCPRFHmacAlgSHA1,
+            "sha224": self._lib.kCCPRFHmacAlgSHA224,
+            "sha256": self._lib.kCCPRFHmacAlgSHA256,
+            "sha384": self._lib.kCCPRFHmacAlgSHA384,
+            "sha512": self._lib.kCCPRFHmacAlgSHA512,
+        }
+
     def hash_supported(self, algorithm):
         try:
             self._hash_mapping[algorithm.name]
@@ -134,6 +143,28 @@ def create_symmetric_decryption_ctx(self, cipher, mode):
         else:
             return _CipherContext(self, cipher, mode, self._lib.kCCDecrypt)
 
+    def pbkdf2_hmac_supported(self, algorithm):
+        return algorithm.name in self._supported_pbkdf2_hmac_algorithms
+
+    def derive_pbkdf2_hmac(self, algorithm, length, salt, iterations,
+                           key_material):
+        alg_enum = self._supported_pbkdf2_hmac_algorithms[algorithm.name]
+        buf = self._ffi.new("char[]", length)
+        res = self._lib.CCKeyDerivationPBKDF(
+            self._lib.kCCPBKDF2,
+            key_material,
+            len(key_material),
+            salt,
+            len(salt),
+            alg_enum,
+            iterations,
+            buf,
+            length
+        )
+        self._check_response(res)
+
+        return self._ffi.buffer(buf)[:]
+
     def _register_cipher_adapter(self, cipher_cls, cipher_const, mode_cls,
                                  mode_const):
         if (cipher_cls, mode_cls) in self._cipher_registry:


Test patch:
Repository: pyca/cryptography

Issue:
Bind X509_verify_cert_error_string
pyOpenSSL 0.14 needs this.  https://github.com/pyca/pyopenssl/issues/30



Discussion:

Resolving patch:
diff --git a/cryptography/hazmat/bindings/openssl/x509.py b/cryptography/hazmat/bindings/openssl/x509.py
--- a/cryptography/hazmat/bindings/openssl/x509.py
+++ b/cryptography/hazmat/bindings/openssl/x509.py
@@ -167,6 +167,8 @@
 void X509_STORE_free(X509_STORE *);
 int X509_STORE_add_cert(X509_STORE *, X509 *);
 int X509_verify_cert(X509_STORE_CTX *);
+
+const char *X509_verify_cert_error_string(long);
 """
 
 MACROS = """


Test patch:
Repository: pyca/cryptography

Issue:
Add API for accessing SSL_CTX's "method" field
Currently there is no way to get the method (as in `TLSv1_METHOD`) of an existing Context object. I've filed pyca/pyopenssl#61 for that, but it requires cryptography to expose the relevant guts.



Discussion:

Resolving patch:
diff --git a/cryptography/hazmat/bindings/openssl/ssl.py b/cryptography/hazmat/bindings/openssl/ssl.py
--- a/cryptography/hazmat/bindings/openssl/ssl.py
+++ b/cryptography/hazmat/bindings/openssl/ssl.py
@@ -123,7 +123,12 @@
 static const long X509_V_OK;
 static const long X509_V_ERR_APPLICATION_VERIFICATION;
 typedef ... SSL_METHOD;
-typedef ... SSL_CTX;
+typedef struct ssl_st {
+    int version;
+    int type;
+    const SSL_METHOD *method;
+    ...;
+} SSL_CTX;
 
 typedef struct {
     int master_key_length;


Test patch:
Repository: pyca/cryptography

Issue:
cffi module names
Hi!

hazmat/bindings/utils.py already sets a modulename for ffi.verify.
However, hazmat/primitives/constant_time.py and hazmat/primitives/padding.py don't. Please set it there as well, this will help with packaging cffi.

Thanks!



Discussion:

Resolving patch:
diff --git a/cryptography/hazmat/primitives/constant_time.py b/cryptography/hazmat/primitives/constant_time.py
--- a/cryptography/hazmat/primitives/constant_time.py
+++ b/cryptography/hazmat/primitives/constant_time.py
@@ -13,18 +13,20 @@
 
 from __future__ import absolute_import, division, print_function
 
+import sys
+
 import cffi
 
 import six
 
+from cryptography.hazmat.bindings.utils import _create_modulename
 
-_ffi = cffi.FFI()
-_ffi.cdef("""
+TYPES = """
 uint8_t Cryptography_constant_time_bytes_eq(uint8_t *, size_t, uint8_t *,
                                             size_t);
-""")
-_lib = _ffi.verify(
-    """
+"""
+
+FUNCTIONS = """
 uint8_t Cryptography_constant_time_bytes_eq(uint8_t *a, size_t len_a,
                                             uint8_t *b, size_t len_b) {
     size_t i = 0;
@@ -43,7 +45,13 @@
     /* Now check the low bit to see if it's set */
     return (mismatch & 1) == 0;
 }
-""",
+"""
+
+_ffi = cffi.FFI()
+_ffi.cdef(TYPES)
+_lib = _ffi.verify(
+    source=FUNCTIONS,
+    modulename=_create_modulename([TYPES], FUNCTIONS, sys.version),
     ext_package="cryptography",
 )
 
diff --git a/cryptography/hazmat/primitives/padding.py b/cryptography/hazmat/primitives/padding.py
--- a/cryptography/hazmat/primitives/padding.py
+++ b/cryptography/hazmat/primitives/padding.py
@@ -13,20 +13,22 @@
 
 from __future__ import absolute_import, division, print_function
 
+import sys
+
 import cffi
 
 import six
 
 from cryptography import utils
+from cryptography.hazmat.bindings.utils import _create_modulename
 from cryptography.hazmat.primitives import interfaces
 
 
-_ffi = cffi.FFI()
-_ffi.cdef("""
+TYPES = """
 uint8_t Cryptography_check_pkcs7_padding(const uint8_t *, uint8_t);
-""")
-_lib = _ffi.verify(
-    """
+"""
+
+FUNCTIONS = """
 /* Returns the value of the input with the most-significant-bit copied to all
    of the bits. */
 static uint8_t Cryptography_DUPLICATE_MSB_TO_ALL(uint8_t a) {
@@ -62,7 +64,13 @@
     /* Now check the low bit to see if it's set */
     return (mismatch & 1) == 0;
 }
-""",
+"""
+
+_ffi = cffi.FFI()
+_ffi.cdef(TYPES)
+_lib = _ffi.verify(
+    source=FUNCTIONS,
+    modulename=_create_modulename([TYPES], FUNCTIONS, sys.version),
     ext_package="cryptography",
 )
 


Test patch:
Repository: pyca/cryptography

Issue:
Compile warning added by #784
When we exposed the insides of `SSL_CTX` in #784 we appear to have added a new compile warning.

> 'const SSL_METHOD *_' (aka 'const struct ssl_method_st *_') with an expression of type 'SSL_METHOD *_' (aka 'struct ssl_method_st *_') discards qualifiers in nested pointer types [-Wincompatible-pointer-types-discards-qualifiers]

This is basically because you shouldn't initialise a `const T**` from a `T**` (http://c-faq.com/ansi/constmismatch.html) and CFFIs code generation tries to do exactly that.

If we have `const` in the binding we get that error on 0.9.8, and if we remove const from the binding we get a regular const correctness error on 1.0.1.

I believe this needs a workaround in the code generated by CFFI to avoid. Or we need to make the structure opaque again and write a handy utility method that reaches into the SSL_CTX and pulls out the SSL_METHOD\* for pyopenssl to use.



Discussion:
@lvh This was added for something you were doing iirc? If we made the struct opaque again but provided a helper method you can use to get the `SSL_METHOD*` would that work for you or would it break PyOpenSSL?

I think a helper function is the only way to fix this, just removing the `const` doesn't work because then it fails on the other hald of the builders. @lvh, does a helper function work for you?


Resolving patch:
diff --git a/cryptography/hazmat/bindings/openssl/ssl.py b/cryptography/hazmat/bindings/openssl/ssl.py
--- a/cryptography/hazmat/bindings/openssl/ssl.py
+++ b/cryptography/hazmat/bindings/openssl/ssl.py
@@ -127,7 +127,6 @@
 typedef struct ssl_st {
     int version;
     int type;
-    const SSL_METHOD *method;
     ...;
 } SSL_CTX;
 
@@ -319,6 +318,8 @@
 /* This function does not exist in 0.9.8e. Once we drop support for
    RHEL/CentOS 5 this can be moved back to FUNCTIONS. */
 SSL_CTX *SSL_set_SSL_CTX(SSL *, SSL_CTX *);
+
+const SSL_METHOD* Cryptography_SSL_CTX_get_method(const SSL_CTX*);
 """
 
 CUSTOMIZATIONS = """
@@ -420,6 +421,11 @@
 #else
 static const long Cryptography_HAS_NETBSD_D1_METH = 1;
 #endif
+
+// Workaround for #794 caused by cffi const** bug.
+const SSL_METHOD* Cryptography_SSL_CTX_get_method(const SSL_CTX* ctx) {
+    return ctx->method;
+}
 """
 
 CONDITIONAL_NAMES = {


Test patch:
Repository: pyca/cryptography

Issue:
Update Windows 32 bit wheels to 1.0.1g
Follwing IRC chat with Alex_Gaynor and exarkun, Alex_Gaynor suggested this issue to be logged here.

Long story short:
- Windows 32 bit wheels bundle *.pyd files that somehow "hard-include" the underlying OpenSSL version as "1.0.1e".
- From exarkun's explanation, this results from the fact that OPENSSL_VERSION_TEXT is actually a macro and not a symbol, in OpenSSL code.
- Side-effect, the simple sample program, below, always displays whichever version the wheels were built-against, and not the actual underlying libraries (*.dll files) version.

```
from cryptography.hazmat.backends import openssl
print openssl.backend.openssl_version_text()
```

Food for thought: should (could?) cryptography somehow avoid this pitfall? In other words: not displaying the actual version of the libraries is not only misleading but could result in a false sense of security (or lack there of).



Discussion:

Resolving patch:
diff --git a/cryptography/hazmat/backends/openssl/backend.py b/cryptography/hazmat/backends/openssl/backend.py
--- a/cryptography/hazmat/backends/openssl/backend.py
+++ b/cryptography/hazmat/backends/openssl/backend.py
@@ -112,11 +112,14 @@ def activate_osrandom_engine(self):
 
     def openssl_version_text(self):
         """
-        Friendly string name of linked OpenSSL.
+        Friendly string name of the loaded OpenSSL library. This is not
+        necessarily the same version as it was compiled against.
 
         Example: OpenSSL 1.0.1e 11 Feb 2013
         """
-        return self._ffi.string(self._lib.OPENSSL_VERSION_TEXT).decode("ascii")
+        return self._ffi.string(
+            self._lib.SSLeay_version(self._lib.SSLEAY_VERSION)
+        ).decode("ascii")
 
     def create_hmac_ctx(self, key, algorithm):
         return _HMACContext(self, key, algorithm)
diff --git a/cryptography/hazmat/bindings/openssl/opensslv.py b/cryptography/hazmat/bindings/openssl/opensslv.py
--- a/cryptography/hazmat/bindings/openssl/opensslv.py
+++ b/cryptography/hazmat/bindings/openssl/opensslv.py
@@ -18,6 +18,8 @@
 """
 
 TYPES = """
+/* Note that these will be resolved when cryptography is compiled and are NOT
+   guaranteed to be the version that it actually loads. */
 static const int OPENSSL_VERSION_NUMBER;
 static const char *const OPENSSL_VERSION_TEXT;
 """


Test patch:
Repository: pyca/cryptography

Issue:
Add load_*_numbers functions to serialization.py
For consistency with the other things.



Discussion:

Resolving patch:
diff --git a/cryptography/hazmat/primitives/serialization.py b/cryptography/hazmat/primitives/serialization.py
--- a/cryptography/hazmat/primitives/serialization.py
+++ b/cryptography/hazmat/primitives/serialization.py
@@ -24,3 +24,11 @@ def load_pem_pkcs8_private_key(data, password, backend):
     return backend.load_pkcs8_pem_private_key(
         data, password
     )
+
+
+def load_rsa_private_numbers(numbers, backend):
+    return backend.load_rsa_private_numbers(numbers)
+
+
+def load_rsa_public_numbers(numbers, backend):
+    return backend.load_rsa_public_numbers(numbers)


Test patch:
diff --git a/tests/hazmat/primitives/test_serialization.py b/tests/hazmat/primitives/test_serialization.py
--- a/tests/hazmat/primitives/test_serialization.py
+++ b/tests/hazmat/primitives/test_serialization.py
@@ -23,9 +23,12 @@
 from cryptography.hazmat.primitives.asymmetric import dsa, rsa
 from cryptography.hazmat.primitives.serialization import (
     load_pem_pkcs8_private_key,
-    load_pem_traditional_openssl_private_key
+    load_pem_traditional_openssl_private_key,
+    load_rsa_private_numbers,
+    load_rsa_public_numbers
 )
 
+from .fixtures_rsa import RSA_KEY_1024
 from .utils import _check_rsa_private_key, load_vectors_from_file
 from ...utils import raises_unsupported_algorithm
 
@@ -544,3 +547,30 @@ def test_load_bad_encryption_oid_key(self, key_file, password, backend):
                     pemfile.read().encode(), password, backend
                 )
             )
+
+
+@pytest.mark.rsa
+class TestLoadRSANumbers(object):
+    def test_load_private_numbers(self, backend):
+        numbers = rsa.RSAPrivateNumbers(
+            p=RSA_KEY_1024["p"],
+            q=RSA_KEY_1024["q"],
+            d=RSA_KEY_1024["private_exponent"],
+            dmp1=RSA_KEY_1024["dmp1"],
+            dmq1=RSA_KEY_1024["dmq1"],
+            iqmp=RSA_KEY_1024["iqmp"],
+            public_numbers=rsa.RSAPublicNumbers(
+                n=RSA_KEY_1024["modulus"],
+                e=RSA_KEY_1024["public_exponent"]
+            )
+        )
+        private_key = load_rsa_private_numbers(numbers, backend)
+        assert private_key
+
+    def test_load_public_numbers(self, backend):
+        numbers = rsa.RSAPublicNumbers(
+            n=RSA_KEY_1024["modulus"],
+            e=RSA_KEY_1024["public_exponent"]
+        )
+        public_key = load_rsa_public_numbers(numbers, backend)
+        assert public_key
Repository: pyca/cryptography

Issue:
Implement constant_time.bytes_eq using hmac.compare_digest
This is available on 2.7.8+ and 3.<something>+, where available it could be used in place of our own code.



Discussion:

Resolving patch:
diff --git a/cryptography/hazmat/primitives/constant_time.py b/cryptography/hazmat/primitives/constant_time.py
--- a/cryptography/hazmat/primitives/constant_time.py
+++ b/cryptography/hazmat/primitives/constant_time.py
@@ -13,6 +13,7 @@
 
 from __future__ import absolute_import, division, print_function
 
+import hmac
 import sys
 
 import cffi
@@ -53,9 +54,18 @@
     ext_package="cryptography",
 )
 
+if hasattr(hmac, "compare_digest"):
+    def bytes_eq(a, b):
+        if not isinstance(a, bytes) or not isinstance(b, bytes):
+            raise TypeError("a and b must be bytes.")
+
+        return hmac.compare_digest(a, b)
 
-def bytes_eq(a, b):
-    if not isinstance(a, bytes) or not isinstance(b, bytes):
+else:
+    def bytes_eq(a, b):
+        if not isinstance(a, bytes) or not isinstance(b, bytes):
             raise TypeError("a and b must be bytes.")
 
-    return _lib.Cryptography_constant_time_bytes_eq(a, len(a), b, len(b)) == 1
+        return _lib.Cryptography_constant_time_bytes_eq(
+            a, len(a), b, len(b)
+        ) == 1


Test patch:
Repository: pyca/cryptography

Issue:
0.5 fails to compile on OS X 10.8
Full traceback: http://pastebin.com/raw.php?i=M9N6Fgzi

@reaperhulk has diagnosed, but this will require an 0.5.2 release to fix for supported platform.



Discussion:

Resolving patch:
diff --git a/cryptography/hazmat/bindings/commoncrypto/secitem.py b/cryptography/hazmat/bindings/commoncrypto/secitem.py
--- a/cryptography/hazmat/bindings/commoncrypto/secitem.py
+++ b/cryptography/hazmat/bindings/commoncrypto/secitem.py
@@ -23,8 +23,6 @@
 const CFTypeRef kSecAttrIsPermanent;
 const CFTypeRef kSecAttrKeyTypeRSA;
 const CFTypeRef kSecAttrKeyTypeDSA;
-const CFTypeRef kSecAttrKeyTypeEC;
-const CFTypeRef kSecAttrKeyTypeEC;
 const CFTypeRef kSecUseKeychain;
 """
 


Test patch:
Repository: pyca/cryptography

Issue:
RSAPublicNumbers should have a nicer repr
Instead of:

```
<cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicNumbers object at 0x106547290>
```

Something like:

```
<RSAPublicNumbers(e=65537, n=<some big product of primes>)>
```

would be great



Discussion:

Resolving patch:
diff --git a/cryptography/hazmat/primitives/asymmetric/rsa.py b/cryptography/hazmat/primitives/asymmetric/rsa.py
--- a/cryptography/hazmat/primitives/asymmetric/rsa.py
+++ b/cryptography/hazmat/primitives/asymmetric/rsa.py
@@ -402,3 +402,6 @@ def n(self):
 
     def public_key(self, backend):
         return backend.load_rsa_public_numbers(self)
+
+    def __repr__(self):
+        return "<RSAPublicNumbers(e={0}, n={1})>".format(self._e, self._n)


Test patch:
diff --git a/tests/hazmat/primitives/test_rsa.py b/tests/hazmat/primitives/test_rsa.py
--- a/tests/hazmat/primitives/test_rsa.py
+++ b/tests/hazmat/primitives/test_rsa.py
@@ -27,6 +27,7 @@
 )
 from cryptography.hazmat.primitives import hashes, interfaces
 from cryptography.hazmat.primitives.asymmetric import padding, rsa
+from cryptography.hazmat.primitives.asymmetric.rsa import RSAPublicNumbers
 
 from .fixtures_rsa import (
     RSA_KEY_1024, RSA_KEY_1025, RSA_KEY_1026, RSA_KEY_1027, RSA_KEY_1028,
@@ -1973,3 +1974,7 @@ def test_invalid_private_numbers_argument_values(self, backend):
                     n=33
                 )
             ).private_key(backend)
+
+    def test_public_number_repr(self):
+        num = RSAPublicNumbers(1, 1)
+        assert repr(num) == "<RSAPublicNumbers(e=1, n=1)>"
Repository: pyca/cryptography

Issue:
Need binding to void GENERAL_NAMES_free(GENERAL_NAMES *)
the function call to d2i methods on the altSubjectName extension returned a dynamicly allocated memory object that must be garbage collected so  binding for GENERAL_NAMES_free should be exposed from hazmat so that higher level code can avoid memory leaks. Not sure which module should expose the binding but I used x509v3.py module in the Proposed solution https://github.com/crc32a/cryptography/commit/24df02646de1e5c1773c9048076b5d67d4c5c0fa

this effects issue https://github.com/pyca/pyopenssl/issues/139 of pyopenssl and an example of its usage to avoid memory leaks is
https://github.com/rackerlabs/pyopenssl/commit/a479a74820619da13dfab8925cf49c4f766b6536



Discussion:
@crc32a Do you want to submit that as a PR? The `x509v3.py` file looks like an appropriate place to me, but it will probably need some conditional bindings to make it work with all the platforms we support. (For example I don't see GENERAL_NAMES_free in Fedora 20.)


Resolving patch:
diff --git a/cryptography/hazmat/bindings/openssl/x509v3.py b/cryptography/hazmat/bindings/openssl/x509v3.py
--- a/cryptography/hazmat/bindings/openssl/x509v3.py
+++ b/cryptography/hazmat/bindings/openssl/x509v3.py
@@ -82,6 +82,7 @@
 void X509V3_set_ctx(X509V3_CTX *, X509 *, X509 *, X509_REQ *, X509_CRL *, int);
 X509_EXTENSION *X509V3_EXT_nconf(CONF *, X509V3_CTX *, char *, char *);
 int GENERAL_NAME_print(BIO *, GENERAL_NAME *);
+void GENERAL_NAMES_free(GENERAL_NAMES *);
 """
 
 MACROS = """


Test patch:
Repository: pyca/cryptography

Issue:
RSAPublicKey.decrypt() should check that padding implements the appropriate interface
Right now if you do something like, pass the type instead of an instance, you get an abhorrent error message (or the `name` property is randomly shown to you, even if it's unrelated).



Discussion:

Resolving patch:
diff --git a/cryptography/hazmat/backends/openssl/rsa.py b/cryptography/hazmat/backends/openssl/rsa.py
--- a/cryptography/hazmat/backends/openssl/rsa.py
+++ b/cryptography/hazmat/backends/openssl/rsa.py
@@ -43,6 +43,9 @@ 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):
+        raise TypeError("Padding must be an instance of AsymmetricPadding.")
+
     if isinstance(padding, PKCS1v15):
         padding_enum = backend._lib.RSA_PKCS1_PADDING
     elif isinstance(padding, OAEP):


Test patch:
diff --git a/tests/hazmat/primitives/test_rsa.py b/tests/hazmat/primitives/test_rsa.py
--- a/tests/hazmat/primitives/test_rsa.py
+++ b/tests/hazmat/primitives/test_rsa.py
@@ -1616,6 +1616,8 @@ def test_unsupported_padding(self, backend):
 
         with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_PADDING):
             public_key.encrypt(b"somedata", DummyPadding())
+        with pytest.raises(TypeError):
+            public_key.encrypt(b"somedata", padding=object())
 
     def test_unsupported_oaep_mgf(self, backend):
         private_key = RSA_KEY_512.private_key(backend)
Repository: pyca/cryptography

Issue:
_truncate_digest_for_ecdsa in the OpenSSL document should be commented
Right now there are no comments explaining why it exists, or what it's attempting to do.



Discussion:
@public Do you remember exactly why this function exists? I think it's to accommodate hashes that are longer than the ECDSA bit length, but don't remember for sure.

This function also needs to be updated to use the BN_CTX manager once #1344 lands.

@reaperhulk Correct. It could probably be written in Python efficiently instead if you think that'd be clearer than the OpenSSL magic?

Eh, I think just a docstring that reminds us why it exists is good enough. I'll add one in the PR that uses the context manager.


Resolving patch:
diff --git a/cryptography/hazmat/backends/openssl/ec.py b/cryptography/hazmat/backends/openssl/ec.py
--- a/cryptography/hazmat/backends/openssl/ec.py
+++ b/cryptography/hazmat/backends/openssl/ec.py
@@ -24,6 +24,13 @@
 
 
 def _truncate_digest_for_ecdsa(ec_key_cdata, digest, backend):
+    """
+    This function truncates digests that are longer than a given elliptic
+    curve key's length so they can be signed. Since elliptic curve keys are
+    much shorter than RSA keys many digests (e.g. SHA-512) may require
+    truncation.
+    """
+
     _lib = backend._lib
     _ffi = backend._ffi
 
@@ -31,17 +38,14 @@ def _truncate_digest_for_ecdsa(ec_key_cdata, digest, backend):
 
     group = _lib.EC_KEY_get0_group(ec_key_cdata)
 
-    bn_ctx = _lib.BN_CTX_new()
-    assert bn_ctx != _ffi.NULL
-    bn_ctx = _ffi.gc(bn_ctx, _lib.BN_CTX_free)
-
-    order = _lib.BN_CTX_get(bn_ctx)
-    assert order != _ffi.NULL
+    with backend._bn_ctx_manager() as bn_ctx:
+        order = _lib.BN_CTX_get(bn_ctx)
+        assert order != _ffi.NULL
 
-    res = _lib.EC_GROUP_get_order(group, order, bn_ctx)
-    assert res == 1
+        res = _lib.EC_GROUP_get_order(group, order, bn_ctx)
+        assert res == 1
 
-    order_bits = _lib.BN_num_bits(order)
+        order_bits = _lib.BN_num_bits(order)
 
     if 8 * digest_len > order_bits:
         digest_len = (order_bits + 7) // 8


Test patch: