We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Invalid ecdsa certificate can trigger "cryptography.exceptions.InternalError: Unknown OpenSSL error."
Trying to access the public numbers of an ECDSA key where the public key is "0" (which I believe is the encoding for point at infinity, it's not a valid key, but one can of course encode such a key) causes an InternalError. Based on the error output I believe this is not supposed to happen.

Such a key is part of OpenSSL's test suite:
https://github.com/openssl/openssl/blob/master/test/recipes/91-test_pkey_check_data/ec_p256_bad_0.pem

reproducer:
```
#!/usr/bin/python3

from cryptography.hazmat.primitives.serialization import load_pem_private_key

privkey = """-----BEGIN PRIVATE KEY-----
MEECAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQcEJzAlAgEBBCD/////AAAAAP//////
////vOb6racXnoTzucrC/GMlUQ==
-----END PRIVATE KEY-----"""

pk = load_pem_private_key(privkey.encode(), password=None)

print(pk.public_key().public_numbers())
```

Exception message:
```
cryptography.exceptions.InternalError: Unknown OpenSSL error. This error is commonly encountered when another library is not cleaning up the OpenSSL error stack. If you are using cryptography with another library that uses OpenSSL try disabling it before reporting a bug. Otherwise please file an issue at https://github.com/pyca/cryptography/issues with information on how to reproduce this. ([_OpenSSLErrorWithText(code=269635690, lib=16, reason=106, reason_text=b'error:1012506A:elliptic curve routines:EC_POINT_get_affine_coordinates:point at infinity')])
```

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `src/cryptography/hazmat/backends/openssl/ec.py`
Content:
```
1 # This file is dual licensed under the terms of the Apache License, Version
2 # 2.0, and the BSD License. See the LICENSE file in the root of this repository
3 # for complete details.
4 
5 import typing
6 
7 from cryptography.exceptions import (
8     InvalidSignature,
9     UnsupportedAlgorithm,
10     _Reasons,
11 )
12 from cryptography.hazmat.backends.openssl.utils import (
13     _calculate_digest_and_algorithm,
14     _evp_pkey_derive,
15 )
16 from cryptography.hazmat.primitives import serialization
17 from cryptography.hazmat.primitives.asymmetric import ec
18 
19 if typing.TYPE_CHECKING:
20     from cryptography.hazmat.backends.openssl.backend import Backend
21 
22 
23 def _check_signature_algorithm(
24     signature_algorithm: ec.EllipticCurveSignatureAlgorithm,
25 ) -> None:
26     if not isinstance(signature_algorithm, ec.ECDSA):
27         raise UnsupportedAlgorithm(
28             "Unsupported elliptic curve signature algorithm.",
29             _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM,
30         )
31 
32 
33 def _ec_key_curve_sn(backend: "Backend", ec_key) -> str:
34     group = backend._lib.EC_KEY_get0_group(ec_key)
35     backend.openssl_assert(group != backend._ffi.NULL)
36 
37     nid = backend._lib.EC_GROUP_get_curve_name(group)
38     # The following check is to find EC keys with unnamed curves and raise
39     # an error for now.
40     if nid == backend._lib.NID_undef:
41         raise ValueError(
42             "ECDSA keys with explicit parameters are unsupported at this time"
43         )
44 
45     # This is like the above check, but it also catches the case where you
46     # explicitly encoded a curve with the same parameters as a named curve.
47     # Don't do that.
48     if (
49         not backend._lib.CRYPTOGRAPHY_IS_LIBRESSL
50         and backend._lib.EC_GROUP_get_asn1_flag(group) == 0
51     ):
52         raise ValueError(
53             "ECDSA keys with explicit parameters are unsupported at this time"
54         )
55 
56     curve_name = backend._lib.OBJ_nid2sn(nid)
57     backend.openssl_assert(curve_name != backend._ffi.NULL)
58 
59     sn = backend._ffi.string(curve_name).decode("ascii")
60     return sn
61 
62 
63 def _mark_asn1_named_ec_curve(backend: "Backend", ec_cdata):
64     """
65     Set the named curve flag on the EC_KEY. This causes OpenSSL to
66     serialize EC keys along with their curve OID which makes
67     deserialization easier.
68     """
69 
70     backend._lib.EC_KEY_set_asn1_flag(
71         ec_cdata, backend._lib.OPENSSL_EC_NAMED_CURVE
72     )
73 
74 
75 def _sn_to_elliptic_curve(backend: "Backend", sn: str) -> ec.EllipticCurve:
76     try:
77         return ec._CURVE_TYPES[sn]()
78     except KeyError:
79         raise UnsupportedAlgorithm(
80             "{} is not a supported elliptic curve".format(sn),
81             _Reasons.UNSUPPORTED_ELLIPTIC_CURVE,
82         )
83 
84 
85 def _ecdsa_sig_sign(
86     backend: "Backend", private_key: "_EllipticCurvePrivateKey", data: bytes
87 ) -> bytes:
88     max_size = backend._lib.ECDSA_size(private_key._ec_key)
89     backend.openssl_assert(max_size > 0)
90 
91     sigbuf = backend._ffi.new("unsigned char[]", max_size)
92     siglen_ptr = backend._ffi.new("unsigned int[]", 1)
93     res = backend._lib.ECDSA_sign(
94         0, data, len(data), sigbuf, siglen_ptr, private_key._ec_key
95     )
96     backend.openssl_assert(res == 1)
97     return backend._ffi.buffer(sigbuf)[: siglen_ptr[0]]
98 
99 
100 def _ecdsa_sig_verify(
101     backend: "Backend",
102     public_key: "_EllipticCurvePublicKey",
103     signature: bytes,
104     data: bytes,
105 ) -> None:
106     res = backend._lib.ECDSA_verify(
107         0, data, len(data), signature, len(signature), public_key._ec_key
108     )
109     if res != 1:
110         backend._consume_errors()
111         raise InvalidSignature
112 
113 
114 class _EllipticCurvePrivateKey(ec.EllipticCurvePrivateKey):
115     def __init__(self, backend: "Backend", ec_key_cdata, evp_pkey):
116         self._backend = backend
117         self._ec_key = ec_key_cdata
118         self._evp_pkey = evp_pkey
119 
120         sn = _ec_key_curve_sn(backend, ec_key_cdata)
121         self._curve = _sn_to_elliptic_curve(backend, sn)
122         _mark_asn1_named_ec_curve(backend, ec_key_cdata)
123 
124     @property
125     def curve(self) -> ec.EllipticCurve:
126         return self._curve
127 
128     @property
129     def key_size(self) -> int:
130         return self.curve.key_size
131 
132     def exchange(
133         self, algorithm: ec.ECDH, peer_public_key: ec.EllipticCurvePublicKey
134     ) -> bytes:
135         if not (
136             self._backend.elliptic_curve_exchange_algorithm_supported(
137                 algorithm, self.curve
138             )
139         ):
140             raise UnsupportedAlgorithm(
141                 "This backend does not support the ECDH algorithm.",
142                 _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM,
143             )
144 
145         if peer_public_key.curve.name != self.curve.name:
146             raise ValueError(
147                 "peer_public_key and self are not on the same curve"
148             )
149 
150         return _evp_pkey_derive(self._backend, self._evp_pkey, peer_public_key)
151 
152     def public_key(self) -> ec.EllipticCurvePublicKey:
153         group = self._backend._lib.EC_KEY_get0_group(self._ec_key)
154         self._backend.openssl_assert(group != self._backend._ffi.NULL)
155 
156         curve_nid = self._backend._lib.EC_GROUP_get_curve_name(group)
157         public_ec_key = self._backend._ec_key_new_by_curve_nid(curve_nid)
158 
159         point = self._backend._lib.EC_KEY_get0_public_key(self._ec_key)
160         self._backend.openssl_assert(point != self._backend._ffi.NULL)
161 
162         res = self._backend._lib.EC_KEY_set_public_key(public_ec_key, point)
163         self._backend.openssl_assert(res == 1)
164 
165         evp_pkey = self._backend._ec_cdata_to_evp_pkey(public_ec_key)
166 
167         return _EllipticCurvePublicKey(self._backend, public_ec_key, evp_pkey)
168 
169     def private_numbers(self) -> ec.EllipticCurvePrivateNumbers:
170         bn = self._backend._lib.EC_KEY_get0_private_key(self._ec_key)
171         private_value = self._backend._bn_to_int(bn)
172         return ec.EllipticCurvePrivateNumbers(
173             private_value=private_value,
174             public_numbers=self.public_key().public_numbers(),
175         )
176 
177     def private_bytes(
178         self,
179         encoding: serialization.Encoding,
180         format: serialization.PrivateFormat,
181         encryption_algorithm: serialization.KeySerializationEncryption,
182     ) -> bytes:
183         return self._backend._private_key_bytes(
184             encoding,
185             format,
186             encryption_algorithm,
187             self,
188             self._evp_pkey,
189             self._ec_key,
190         )
191 
192     def sign(
193         self,
194         data: bytes,
195         signature_algorithm: ec.EllipticCurveSignatureAlgorithm,
196     ) -> bytes:
197         _check_signature_algorithm(signature_algorithm)
198         data, _ = _calculate_digest_and_algorithm(
199             data,
200             signature_algorithm.algorithm,
201         )
202         return _ecdsa_sig_sign(self._backend, self, data)
203 
204 
205 class _EllipticCurvePublicKey(ec.EllipticCurvePublicKey):
206     def __init__(self, backend: "Backend", ec_key_cdata, evp_pkey):
207         self._backend = backend
208         self._ec_key = ec_key_cdata
209         self._evp_pkey = evp_pkey
210 
211         sn = _ec_key_curve_sn(backend, ec_key_cdata)
212         self._curve = _sn_to_elliptic_curve(backend, sn)
213         _mark_asn1_named_ec_curve(backend, ec_key_cdata)
214 
215     @property
216     def curve(self) -> ec.EllipticCurve:
217         return self._curve
218 
219     @property
220     def key_size(self) -> int:
221         return self.curve.key_size
222 
223     def public_numbers(self) -> ec.EllipticCurvePublicNumbers:
224         get_func, group = self._backend._ec_key_determine_group_get_func(
225             self._ec_key
226         )
227         point = self._backend._lib.EC_KEY_get0_public_key(self._ec_key)
228         self._backend.openssl_assert(point != self._backend._ffi.NULL)
229 
230         with self._backend._tmp_bn_ctx() as bn_ctx:
231             bn_x = self._backend._lib.BN_CTX_get(bn_ctx)
232             bn_y = self._backend._lib.BN_CTX_get(bn_ctx)
233 
234             res = get_func(group, point, bn_x, bn_y, bn_ctx)
235             self._backend.openssl_assert(res == 1)
236 
237             x = self._backend._bn_to_int(bn_x)
238             y = self._backend._bn_to_int(bn_y)
239 
240         return ec.EllipticCurvePublicNumbers(x=x, y=y, curve=self._curve)
241 
242     def _encode_point(self, format: serialization.PublicFormat) -> bytes:
243         if format is serialization.PublicFormat.CompressedPoint:
244             conversion = self._backend._lib.POINT_CONVERSION_COMPRESSED
245         else:
246             assert format is serialization.PublicFormat.UncompressedPoint
247             conversion = self._backend._lib.POINT_CONVERSION_UNCOMPRESSED
248 
249         group = self._backend._lib.EC_KEY_get0_group(self._ec_key)
250         self._backend.openssl_assert(group != self._backend._ffi.NULL)
251         point = self._backend._lib.EC_KEY_get0_public_key(self._ec_key)
252         self._backend.openssl_assert(point != self._backend._ffi.NULL)
253         with self._backend._tmp_bn_ctx() as bn_ctx:
254             buflen = self._backend._lib.EC_POINT_point2oct(
255                 group, point, conversion, self._backend._ffi.NULL, 0, bn_ctx
256             )
257             self._backend.openssl_assert(buflen > 0)
258             buf = self._backend._ffi.new("char[]", buflen)
259             res = self._backend._lib.EC_POINT_point2oct(
260                 group, point, conversion, buf, buflen, bn_ctx
261             )
262             self._backend.openssl_assert(buflen == res)
263 
264         return self._backend._ffi.buffer(buf)[:]
265 
266     def public_bytes(
267         self,
268         encoding: serialization.Encoding,
269         format: serialization.PublicFormat,
270     ) -> bytes:
271         if (
272             encoding is serialization.Encoding.X962
273             or format is serialization.PublicFormat.CompressedPoint
274             or format is serialization.PublicFormat.UncompressedPoint
275         ):
276             if encoding is not serialization.Encoding.X962 or format not in (
277                 serialization.PublicFormat.CompressedPoint,
278                 serialization.PublicFormat.UncompressedPoint,
279             ):
280                 raise ValueError(
281                     "X962 encoding must be used with CompressedPoint or "
282                     "UncompressedPoint format"
283                 )
284 
285             return self._encode_point(format)
286         else:
287             return self._backend._public_key_bytes(
288                 encoding, format, self, self._evp_pkey, None
289             )
290 
291     def verify(
292         self,
293         signature: bytes,
294         data: bytes,
295         signature_algorithm: ec.EllipticCurveSignatureAlgorithm,
296     ) -> None:
297         _check_signature_algorithm(signature_algorithm)
298         data, _ = _calculate_digest_and_algorithm(
299             data,
300             signature_algorithm.algorithm,
301         )
302         _ecdsa_sig_verify(self._backend, self, signature, data)
303
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/src/cryptography/hazmat/backends/openssl/ec.py b/src/cryptography/hazmat/backends/openssl/ec.py
--- a/src/cryptography/hazmat/backends/openssl/ec.py
+++ b/src/cryptography/hazmat/backends/openssl/ec.py
@@ -72,6 +72,17 @@
     )
 
 
+def _check_key_infinity(backend: "Backend", ec_cdata) -> None:
+    point = backend._lib.EC_KEY_get0_public_key(ec_cdata)
+    backend.openssl_assert(point != backend._ffi.NULL)
+    group = backend._lib.EC_KEY_get0_group(ec_cdata)
+    backend.openssl_assert(group != backend._ffi.NULL)
+    if backend._lib.EC_POINT_is_at_infinity(group, point):
+        raise ValueError(
+            "Cannot load an EC public key where the point is at infinity"
+        )
+
+
 def _sn_to_elliptic_curve(backend: "Backend", sn: str) -> ec.EllipticCurve:
     try:
         return ec._CURVE_TYPES[sn]()
@@ -120,6 +131,7 @@
         sn = _ec_key_curve_sn(backend, ec_key_cdata)
         self._curve = _sn_to_elliptic_curve(backend, sn)
         _mark_asn1_named_ec_curve(backend, ec_key_cdata)
+        _check_key_infinity(backend, ec_key_cdata)
 
     @property
     def curve(self) -> ec.EllipticCurve:
@@ -211,6 +223,7 @@
         sn = _ec_key_curve_sn(backend, ec_key_cdata)
         self._curve = _sn_to_elliptic_curve(backend, sn)
         _mark_asn1_named_ec_curve(backend, ec_key_cdata)
+        _check_key_infinity(backend, ec_key_cdata)
 
     @property
     def curve(self) -> ec.EllipticCurve:

{"golden_diff": "diff --git a/src/cryptography/hazmat/backends/openssl/ec.py b/src/cryptography/hazmat/backends/openssl/ec.py\n--- a/src/cryptography/hazmat/backends/openssl/ec.py\n+++ b/src/cryptography/hazmat/backends/openssl/ec.py\n@@ -72,6 +72,17 @@\n     )\n \n \n+def _check_key_infinity(backend: \"Backend\", ec_cdata) -> None:\n+    point = backend._lib.EC_KEY_get0_public_key(ec_cdata)\n+    backend.openssl_assert(point != backend._ffi.NULL)\n+    group = backend._lib.EC_KEY_get0_group(ec_cdata)\n+    backend.openssl_assert(group != backend._ffi.NULL)\n+    if backend._lib.EC_POINT_is_at_infinity(group, point):\n+        raise ValueError(\n+            \"Cannot load an EC public key where the point is at infinity\"\n+        )\n+\n+\n def _sn_to_elliptic_curve(backend: \"Backend\", sn: str) -> ec.EllipticCurve:\n     try:\n         return ec._CURVE_TYPES[sn]()\n@@ -120,6 +131,7 @@\n         sn = _ec_key_curve_sn(backend, ec_key_cdata)\n         self._curve = _sn_to_elliptic_curve(backend, sn)\n         _mark_asn1_named_ec_curve(backend, ec_key_cdata)\n+        _check_key_infinity(backend, ec_key_cdata)\n \n     @property\n     def curve(self) -> ec.EllipticCurve:\n@@ -211,6 +223,7 @@\n         sn = _ec_key_curve_sn(backend, ec_key_cdata)\n         self._curve = _sn_to_elliptic_curve(backend, sn)\n         _mark_asn1_named_ec_curve(backend, ec_key_cdata)\n+        _check_key_infinity(backend, ec_key_cdata)\n \n     @property\n     def curve(self) -> ec.EllipticCurve:\n", "issue": "Invalid ecdsa certificate can trigger \"cryptography.exceptions.InternalError: Unknown OpenSSL error.\"\nTrying to access the public numbers of an ECDSA key where the public key is \"0\" (which I believe is the encoding for point at infinity, it's not a valid key, but one can of course encode such a key) causes an InternalError. Based on the error output I believe this is not supposed to happen.\r\n\r\nSuch a key is part of OpenSSL's test suite:\r\nhttps://github.com/openssl/openssl/blob/master/test/recipes/91-test_pkey_check_data/ec_p256_bad_0.pem\r\n\r\nreproducer:\r\n```\r\n#!/usr/bin/python3\r\n\r\nfrom cryptography.hazmat.primitives.serialization import load_pem_private_key\r\n\r\nprivkey = \"\"\"-----BEGIN PRIVATE KEY-----\r\nMEECAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQcEJzAlAgEBBCD/////AAAAAP//////\r\n////vOb6racXnoTzucrC/GMlUQ==\r\n-----END PRIVATE KEY-----\"\"\"\r\n\r\npk = load_pem_private_key(privkey.encode(), password=None)\r\n\r\nprint(pk.public_key().public_numbers())\r\n```\r\n\r\nException message:\r\n```\r\ncryptography.exceptions.InternalError: Unknown OpenSSL error. This error is commonly encountered when another library is not cleaning up the OpenSSL error stack. If you are using cryptography with another library that uses OpenSSL try disabling it before reporting a bug. Otherwise please file an issue at https://github.com/pyca/cryptography/issues with information on how to reproduce this. ([_OpenSSLErrorWithText(code=269635690, lib=16, reason=106, reason_text=b'error:1012506A:elliptic curve routines:EC_POINT_get_affine_coordinates:point at infinity')])\r\n```\n", "before_files": [{"content": "# This file is dual licensed under the terms of the Apache License, Version\n# 2.0, and the BSD License. See the LICENSE file in the root of this repository\n# for complete details.\n\nimport typing\n\nfrom cryptography.exceptions import (\n    InvalidSignature,\n    UnsupportedAlgorithm,\n    _Reasons,\n)\nfrom cryptography.hazmat.backends.openssl.utils import (\n    _calculate_digest_and_algorithm,\n    _evp_pkey_derive,\n)\nfrom cryptography.hazmat.primitives import serialization\nfrom cryptography.hazmat.primitives.asymmetric import ec\n\nif typing.TYPE_CHECKING:\n    from cryptography.hazmat.backends.openssl.backend import Backend\n\n\ndef _check_signature_algorithm(\n    signature_algorithm: ec.EllipticCurveSignatureAlgorithm,\n) -> None:\n    if not isinstance(signature_algorithm, ec.ECDSA):\n        raise UnsupportedAlgorithm(\n            \"Unsupported elliptic curve signature algorithm.\",\n            _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM,\n        )\n\n\ndef _ec_key_curve_sn(backend: \"Backend\", ec_key) -> str:\n    group = backend._lib.EC_KEY_get0_group(ec_key)\n    backend.openssl_assert(group != backend._ffi.NULL)\n\n    nid = backend._lib.EC_GROUP_get_curve_name(group)\n    # The following check is to find EC keys with unnamed curves and raise\n    # an error for now.\n    if nid == backend._lib.NID_undef:\n        raise ValueError(\n            \"ECDSA keys with explicit parameters are unsupported at this time\"\n        )\n\n    # This is like the above check, but it also catches the case where you\n    # explicitly encoded a curve with the same parameters as a named curve.\n    # Don't do that.\n    if (\n        not backend._lib.CRYPTOGRAPHY_IS_LIBRESSL\n        and backend._lib.EC_GROUP_get_asn1_flag(group) == 0\n    ):\n        raise ValueError(\n            \"ECDSA keys with explicit parameters are unsupported at this time\"\n        )\n\n    curve_name = backend._lib.OBJ_nid2sn(nid)\n    backend.openssl_assert(curve_name != backend._ffi.NULL)\n\n    sn = backend._ffi.string(curve_name).decode(\"ascii\")\n    return sn\n\n\ndef _mark_asn1_named_ec_curve(backend: \"Backend\", ec_cdata):\n    \"\"\"\n    Set the named curve flag on the EC_KEY. This causes OpenSSL to\n    serialize EC keys along with their curve OID which makes\n    deserialization easier.\n    \"\"\"\n\n    backend._lib.EC_KEY_set_asn1_flag(\n        ec_cdata, backend._lib.OPENSSL_EC_NAMED_CURVE\n    )\n\n\ndef _sn_to_elliptic_curve(backend: \"Backend\", sn: str) -> ec.EllipticCurve:\n    try:\n        return ec._CURVE_TYPES[sn]()\n    except KeyError:\n        raise UnsupportedAlgorithm(\n            \"{} is not a supported elliptic curve\".format(sn),\n            _Reasons.UNSUPPORTED_ELLIPTIC_CURVE,\n        )\n\n\ndef _ecdsa_sig_sign(\n    backend: \"Backend\", private_key: \"_EllipticCurvePrivateKey\", data: bytes\n) -> bytes:\n    max_size = backend._lib.ECDSA_size(private_key._ec_key)\n    backend.openssl_assert(max_size > 0)\n\n    sigbuf = backend._ffi.new(\"unsigned char[]\", max_size)\n    siglen_ptr = backend._ffi.new(\"unsigned int[]\", 1)\n    res = backend._lib.ECDSA_sign(\n        0, data, len(data), sigbuf, siglen_ptr, private_key._ec_key\n    )\n    backend.openssl_assert(res == 1)\n    return backend._ffi.buffer(sigbuf)[: siglen_ptr[0]]\n\n\ndef _ecdsa_sig_verify(\n    backend: \"Backend\",\n    public_key: \"_EllipticCurvePublicKey\",\n    signature: bytes,\n    data: bytes,\n) -> None:\n    res = backend._lib.ECDSA_verify(\n        0, data, len(data), signature, len(signature), public_key._ec_key\n    )\n    if res != 1:\n        backend._consume_errors()\n        raise InvalidSignature\n\n\nclass _EllipticCurvePrivateKey(ec.EllipticCurvePrivateKey):\n    def __init__(self, backend: \"Backend\", ec_key_cdata, evp_pkey):\n        self._backend = backend\n        self._ec_key = ec_key_cdata\n        self._evp_pkey = evp_pkey\n\n        sn = _ec_key_curve_sn(backend, ec_key_cdata)\n        self._curve = _sn_to_elliptic_curve(backend, sn)\n        _mark_asn1_named_ec_curve(backend, ec_key_cdata)\n\n    @property\n    def curve(self) -> ec.EllipticCurve:\n        return self._curve\n\n    @property\n    def key_size(self) -> int:\n        return self.curve.key_size\n\n    def exchange(\n        self, algorithm: ec.ECDH, peer_public_key: ec.EllipticCurvePublicKey\n    ) -> bytes:\n        if not (\n            self._backend.elliptic_curve_exchange_algorithm_supported(\n                algorithm, self.curve\n            )\n        ):\n            raise UnsupportedAlgorithm(\n                \"This backend does not support the ECDH algorithm.\",\n                _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM,\n            )\n\n        if peer_public_key.curve.name != self.curve.name:\n            raise ValueError(\n                \"peer_public_key and self are not on the same curve\"\n            )\n\n        return _evp_pkey_derive(self._backend, self._evp_pkey, peer_public_key)\n\n    def public_key(self) -> ec.EllipticCurvePublicKey:\n        group = self._backend._lib.EC_KEY_get0_group(self._ec_key)\n        self._backend.openssl_assert(group != self._backend._ffi.NULL)\n\n        curve_nid = self._backend._lib.EC_GROUP_get_curve_name(group)\n        public_ec_key = self._backend._ec_key_new_by_curve_nid(curve_nid)\n\n        point = self._backend._lib.EC_KEY_get0_public_key(self._ec_key)\n        self._backend.openssl_assert(point != self._backend._ffi.NULL)\n\n        res = self._backend._lib.EC_KEY_set_public_key(public_ec_key, point)\n        self._backend.openssl_assert(res == 1)\n\n        evp_pkey = self._backend._ec_cdata_to_evp_pkey(public_ec_key)\n\n        return _EllipticCurvePublicKey(self._backend, public_ec_key, evp_pkey)\n\n    def private_numbers(self) -> ec.EllipticCurvePrivateNumbers:\n        bn = self._backend._lib.EC_KEY_get0_private_key(self._ec_key)\n        private_value = self._backend._bn_to_int(bn)\n        return ec.EllipticCurvePrivateNumbers(\n            private_value=private_value,\n            public_numbers=self.public_key().public_numbers(),\n        )\n\n    def private_bytes(\n        self,\n        encoding: serialization.Encoding,\n        format: serialization.PrivateFormat,\n        encryption_algorithm: serialization.KeySerializationEncryption,\n    ) -> bytes:\n        return self._backend._private_key_bytes(\n            encoding,\n            format,\n            encryption_algorithm,\n            self,\n            self._evp_pkey,\n            self._ec_key,\n        )\n\n    def sign(\n        self,\n        data: bytes,\n        signature_algorithm: ec.EllipticCurveSignatureAlgorithm,\n    ) -> bytes:\n        _check_signature_algorithm(signature_algorithm)\n        data, _ = _calculate_digest_and_algorithm(\n            data,\n            signature_algorithm.algorithm,\n        )\n        return _ecdsa_sig_sign(self._backend, self, data)\n\n\nclass _EllipticCurvePublicKey(ec.EllipticCurvePublicKey):\n    def __init__(self, backend: \"Backend\", ec_key_cdata, evp_pkey):\n        self._backend = backend\n        self._ec_key = ec_key_cdata\n        self._evp_pkey = evp_pkey\n\n        sn = _ec_key_curve_sn(backend, ec_key_cdata)\n        self._curve = _sn_to_elliptic_curve(backend, sn)\n        _mark_asn1_named_ec_curve(backend, ec_key_cdata)\n\n    @property\n    def curve(self) -> ec.EllipticCurve:\n        return self._curve\n\n    @property\n    def key_size(self) -> int:\n        return self.curve.key_size\n\n    def public_numbers(self) -> ec.EllipticCurvePublicNumbers:\n        get_func, group = self._backend._ec_key_determine_group_get_func(\n            self._ec_key\n        )\n        point = self._backend._lib.EC_KEY_get0_public_key(self._ec_key)\n        self._backend.openssl_assert(point != self._backend._ffi.NULL)\n\n        with self._backend._tmp_bn_ctx() as bn_ctx:\n            bn_x = self._backend._lib.BN_CTX_get(bn_ctx)\n            bn_y = self._backend._lib.BN_CTX_get(bn_ctx)\n\n            res = get_func(group, point, bn_x, bn_y, bn_ctx)\n            self._backend.openssl_assert(res == 1)\n\n            x = self._backend._bn_to_int(bn_x)\n            y = self._backend._bn_to_int(bn_y)\n\n        return ec.EllipticCurvePublicNumbers(x=x, y=y, curve=self._curve)\n\n    def _encode_point(self, format: serialization.PublicFormat) -> bytes:\n        if format is serialization.PublicFormat.CompressedPoint:\n            conversion = self._backend._lib.POINT_CONVERSION_COMPRESSED\n        else:\n            assert format is serialization.PublicFormat.UncompressedPoint\n            conversion = self._backend._lib.POINT_CONVERSION_UNCOMPRESSED\n\n        group = self._backend._lib.EC_KEY_get0_group(self._ec_key)\n        self._backend.openssl_assert(group != self._backend._ffi.NULL)\n        point = self._backend._lib.EC_KEY_get0_public_key(self._ec_key)\n        self._backend.openssl_assert(point != self._backend._ffi.NULL)\n        with self._backend._tmp_bn_ctx() as bn_ctx:\n            buflen = self._backend._lib.EC_POINT_point2oct(\n                group, point, conversion, self._backend._ffi.NULL, 0, bn_ctx\n            )\n            self._backend.openssl_assert(buflen > 0)\n            buf = self._backend._ffi.new(\"char[]\", buflen)\n            res = self._backend._lib.EC_POINT_point2oct(\n                group, point, conversion, buf, buflen, bn_ctx\n            )\n            self._backend.openssl_assert(buflen == res)\n\n        return self._backend._ffi.buffer(buf)[:]\n\n    def public_bytes(\n        self,\n        encoding: serialization.Encoding,\n        format: serialization.PublicFormat,\n    ) -> bytes:\n        if (\n            encoding is serialization.Encoding.X962\n            or format is serialization.PublicFormat.CompressedPoint\n            or format is serialization.PublicFormat.UncompressedPoint\n        ):\n            if encoding is not serialization.Encoding.X962 or format not in (\n                serialization.PublicFormat.CompressedPoint,\n                serialization.PublicFormat.UncompressedPoint,\n            ):\n                raise ValueError(\n                    \"X962 encoding must be used with CompressedPoint or \"\n                    \"UncompressedPoint format\"\n                )\n\n            return self._encode_point(format)\n        else:\n            return self._backend._public_key_bytes(\n                encoding, format, self, self._evp_pkey, None\n            )\n\n    def verify(\n        self,\n        signature: bytes,\n        data: bytes,\n        signature_algorithm: ec.EllipticCurveSignatureAlgorithm,\n    ) -> None:\n        _check_signature_algorithm(signature_algorithm)\n        data, _ = _calculate_digest_and_algorithm(\n            data,\n            signature_algorithm.algorithm,\n        )\n        _ecdsa_sig_verify(self._backend, self, signature, data)\n", "path": "src/cryptography/hazmat/backends/openssl/ec.py"}], "after_files": [{"content": "# This file is dual licensed under the terms of the Apache License, Version\n# 2.0, and the BSD License. See the LICENSE file in the root of this repository\n# for complete details.\n\nimport typing\n\nfrom cryptography.exceptions import (\n    InvalidSignature,\n    UnsupportedAlgorithm,\n    _Reasons,\n)\nfrom cryptography.hazmat.backends.openssl.utils import (\n    _calculate_digest_and_algorithm,\n    _evp_pkey_derive,\n)\nfrom cryptography.hazmat.primitives import serialization\nfrom cryptography.hazmat.primitives.asymmetric import ec\n\nif typing.TYPE_CHECKING:\n    from cryptography.hazmat.backends.openssl.backend import Backend\n\n\ndef _check_signature_algorithm(\n    signature_algorithm: ec.EllipticCurveSignatureAlgorithm,\n) -> None:\n    if not isinstance(signature_algorithm, ec.ECDSA):\n        raise UnsupportedAlgorithm(\n            \"Unsupported elliptic curve signature algorithm.\",\n            _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM,\n        )\n\n\ndef _ec_key_curve_sn(backend: \"Backend\", ec_key) -> str:\n    group = backend._lib.EC_KEY_get0_group(ec_key)\n    backend.openssl_assert(group != backend._ffi.NULL)\n\n    nid = backend._lib.EC_GROUP_get_curve_name(group)\n    # The following check is to find EC keys with unnamed curves and raise\n    # an error for now.\n    if nid == backend._lib.NID_undef:\n        raise ValueError(\n            \"ECDSA keys with explicit parameters are unsupported at this time\"\n        )\n\n    # This is like the above check, but it also catches the case where you\n    # explicitly encoded a curve with the same parameters as a named curve.\n    # Don't do that.\n    if (\n        not backend._lib.CRYPTOGRAPHY_IS_LIBRESSL\n        and backend._lib.EC_GROUP_get_asn1_flag(group) == 0\n    ):\n        raise ValueError(\n            \"ECDSA keys with explicit parameters are unsupported at this time\"\n        )\n\n    curve_name = backend._lib.OBJ_nid2sn(nid)\n    backend.openssl_assert(curve_name != backend._ffi.NULL)\n\n    sn = backend._ffi.string(curve_name).decode(\"ascii\")\n    return sn\n\n\ndef _mark_asn1_named_ec_curve(backend: \"Backend\", ec_cdata):\n    \"\"\"\n    Set the named curve flag on the EC_KEY. This causes OpenSSL to\n    serialize EC keys along with their curve OID which makes\n    deserialization easier.\n    \"\"\"\n\n    backend._lib.EC_KEY_set_asn1_flag(\n        ec_cdata, backend._lib.OPENSSL_EC_NAMED_CURVE\n    )\n\n\ndef _check_key_infinity(backend: \"Backend\", ec_cdata) -> None:\n    point = backend._lib.EC_KEY_get0_public_key(ec_cdata)\n    backend.openssl_assert(point != backend._ffi.NULL)\n    group = backend._lib.EC_KEY_get0_group(ec_cdata)\n    backend.openssl_assert(group != backend._ffi.NULL)\n    if backend._lib.EC_POINT_is_at_infinity(group, point):\n        raise ValueError(\n            \"Cannot load an EC public key where the point is at infinity\"\n        )\n\n\ndef _sn_to_elliptic_curve(backend: \"Backend\", sn: str) -> ec.EllipticCurve:\n    try:\n        return ec._CURVE_TYPES[sn]()\n    except KeyError:\n        raise UnsupportedAlgorithm(\n            \"{} is not a supported elliptic curve\".format(sn),\n            _Reasons.UNSUPPORTED_ELLIPTIC_CURVE,\n        )\n\n\ndef _ecdsa_sig_sign(\n    backend: \"Backend\", private_key: \"_EllipticCurvePrivateKey\", data: bytes\n) -> bytes:\n    max_size = backend._lib.ECDSA_size(private_key._ec_key)\n    backend.openssl_assert(max_size > 0)\n\n    sigbuf = backend._ffi.new(\"unsigned char[]\", max_size)\n    siglen_ptr = backend._ffi.new(\"unsigned int[]\", 1)\n    res = backend._lib.ECDSA_sign(\n        0, data, len(data), sigbuf, siglen_ptr, private_key._ec_key\n    )\n    backend.openssl_assert(res == 1)\n    return backend._ffi.buffer(sigbuf)[: siglen_ptr[0]]\n\n\ndef _ecdsa_sig_verify(\n    backend: \"Backend\",\n    public_key: \"_EllipticCurvePublicKey\",\n    signature: bytes,\n    data: bytes,\n) -> None:\n    res = backend._lib.ECDSA_verify(\n        0, data, len(data), signature, len(signature), public_key._ec_key\n    )\n    if res != 1:\n        backend._consume_errors()\n        raise InvalidSignature\n\n\nclass _EllipticCurvePrivateKey(ec.EllipticCurvePrivateKey):\n    def __init__(self, backend: \"Backend\", ec_key_cdata, evp_pkey):\n        self._backend = backend\n        self._ec_key = ec_key_cdata\n        self._evp_pkey = evp_pkey\n\n        sn = _ec_key_curve_sn(backend, ec_key_cdata)\n        self._curve = _sn_to_elliptic_curve(backend, sn)\n        _mark_asn1_named_ec_curve(backend, ec_key_cdata)\n        _check_key_infinity(backend, ec_key_cdata)\n\n    @property\n    def curve(self) -> ec.EllipticCurve:\n        return self._curve\n\n    @property\n    def key_size(self) -> int:\n        return self.curve.key_size\n\n    def exchange(\n        self, algorithm: ec.ECDH, peer_public_key: ec.EllipticCurvePublicKey\n    ) -> bytes:\n        if not (\n            self._backend.elliptic_curve_exchange_algorithm_supported(\n                algorithm, self.curve\n            )\n        ):\n            raise UnsupportedAlgorithm(\n                \"This backend does not support the ECDH algorithm.\",\n                _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM,\n            )\n\n        if peer_public_key.curve.name != self.curve.name:\n            raise ValueError(\n                \"peer_public_key and self are not on the same curve\"\n            )\n\n        return _evp_pkey_derive(self._backend, self._evp_pkey, peer_public_key)\n\n    def public_key(self) -> ec.EllipticCurvePublicKey:\n        group = self._backend._lib.EC_KEY_get0_group(self._ec_key)\n        self._backend.openssl_assert(group != self._backend._ffi.NULL)\n\n        curve_nid = self._backend._lib.EC_GROUP_get_curve_name(group)\n        public_ec_key = self._backend._ec_key_new_by_curve_nid(curve_nid)\n\n        point = self._backend._lib.EC_KEY_get0_public_key(self._ec_key)\n        self._backend.openssl_assert(point != self._backend._ffi.NULL)\n\n        res = self._backend._lib.EC_KEY_set_public_key(public_ec_key, point)\n        self._backend.openssl_assert(res == 1)\n\n        evp_pkey = self._backend._ec_cdata_to_evp_pkey(public_ec_key)\n\n        return _EllipticCurvePublicKey(self._backend, public_ec_key, evp_pkey)\n\n    def private_numbers(self) -> ec.EllipticCurvePrivateNumbers:\n        bn = self._backend._lib.EC_KEY_get0_private_key(self._ec_key)\n        private_value = self._backend._bn_to_int(bn)\n        return ec.EllipticCurvePrivateNumbers(\n            private_value=private_value,\n            public_numbers=self.public_key().public_numbers(),\n        )\n\n    def private_bytes(\n        self,\n        encoding: serialization.Encoding,\n        format: serialization.PrivateFormat,\n        encryption_algorithm: serialization.KeySerializationEncryption,\n    ) -> bytes:\n        return self._backend._private_key_bytes(\n            encoding,\n            format,\n            encryption_algorithm,\n            self,\n            self._evp_pkey,\n            self._ec_key,\n        )\n\n    def sign(\n        self,\n        data: bytes,\n        signature_algorithm: ec.EllipticCurveSignatureAlgorithm,\n    ) -> bytes:\n        _check_signature_algorithm(signature_algorithm)\n        data, _ = _calculate_digest_and_algorithm(\n            data,\n            signature_algorithm.algorithm,\n        )\n        return _ecdsa_sig_sign(self._backend, self, data)\n\n\nclass _EllipticCurvePublicKey(ec.EllipticCurvePublicKey):\n    def __init__(self, backend: \"Backend\", ec_key_cdata, evp_pkey):\n        self._backend = backend\n        self._ec_key = ec_key_cdata\n        self._evp_pkey = evp_pkey\n\n        sn = _ec_key_curve_sn(backend, ec_key_cdata)\n        self._curve = _sn_to_elliptic_curve(backend, sn)\n        _mark_asn1_named_ec_curve(backend, ec_key_cdata)\n        _check_key_infinity(backend, ec_key_cdata)\n\n    @property\n    def curve(self) -> ec.EllipticCurve:\n        return self._curve\n\n    @property\n    def key_size(self) -> int:\n        return self.curve.key_size\n\n    def public_numbers(self) -> ec.EllipticCurvePublicNumbers:\n        get_func, group = self._backend._ec_key_determine_group_get_func(\n            self._ec_key\n        )\n        point = self._backend._lib.EC_KEY_get0_public_key(self._ec_key)\n        self._backend.openssl_assert(point != self._backend._ffi.NULL)\n\n        with self._backend._tmp_bn_ctx() as bn_ctx:\n            bn_x = self._backend._lib.BN_CTX_get(bn_ctx)\n            bn_y = self._backend._lib.BN_CTX_get(bn_ctx)\n\n            res = get_func(group, point, bn_x, bn_y, bn_ctx)\n            self._backend.openssl_assert(res == 1)\n\n            x = self._backend._bn_to_int(bn_x)\n            y = self._backend._bn_to_int(bn_y)\n\n        return ec.EllipticCurvePublicNumbers(x=x, y=y, curve=self._curve)\n\n    def _encode_point(self, format: serialization.PublicFormat) -> bytes:\n        if format is serialization.PublicFormat.CompressedPoint:\n            conversion = self._backend._lib.POINT_CONVERSION_COMPRESSED\n        else:\n            assert format is serialization.PublicFormat.UncompressedPoint\n            conversion = self._backend._lib.POINT_CONVERSION_UNCOMPRESSED\n\n        group = self._backend._lib.EC_KEY_get0_group(self._ec_key)\n        self._backend.openssl_assert(group != self._backend._ffi.NULL)\n        point = self._backend._lib.EC_KEY_get0_public_key(self._ec_key)\n        self._backend.openssl_assert(point != self._backend._ffi.NULL)\n        with self._backend._tmp_bn_ctx() as bn_ctx:\n            buflen = self._backend._lib.EC_POINT_point2oct(\n                group, point, conversion, self._backend._ffi.NULL, 0, bn_ctx\n            )\n            self._backend.openssl_assert(buflen > 0)\n            buf = self._backend._ffi.new(\"char[]\", buflen)\n            res = self._backend._lib.EC_POINT_point2oct(\n                group, point, conversion, buf, buflen, bn_ctx\n            )\n            self._backend.openssl_assert(buflen == res)\n\n        return self._backend._ffi.buffer(buf)[:]\n\n    def public_bytes(\n        self,\n        encoding: serialization.Encoding,\n        format: serialization.PublicFormat,\n    ) -> bytes:\n        if (\n            encoding is serialization.Encoding.X962\n            or format is serialization.PublicFormat.CompressedPoint\n            or format is serialization.PublicFormat.UncompressedPoint\n        ):\n            if encoding is not serialization.Encoding.X962 or format not in (\n                serialization.PublicFormat.CompressedPoint,\n                serialization.PublicFormat.UncompressedPoint,\n            ):\n                raise ValueError(\n                    \"X962 encoding must be used with CompressedPoint or \"\n                    \"UncompressedPoint format\"\n                )\n\n            return self._encode_point(format)\n        else:\n            return self._backend._public_key_bytes(\n                encoding, format, self, self._evp_pkey, None\n            )\n\n    def verify(\n        self,\n        signature: bytes,\n        data: bytes,\n        signature_algorithm: ec.EllipticCurveSignatureAlgorithm,\n    ) -> None:\n        _check_signature_algorithm(signature_algorithm)\n        data, _ = _calculate_digest_and_algorithm(\n            data,\n            signature_algorithm.algorithm,\n        )\n        _ecdsa_sig_verify(self._backend, self, signature, data)\n", "path": "src/cryptography/hazmat/backends/openssl/ec.py"}]}