Repository: pyca/cryptography

Issue:
Loading private numbers fails on an assertion for bad numbers
(I assume they're bad numbers, either way we should never fail assertions).

``` pycon
>>>> from cryptography.hazmat.primitives.asymmetric import ec
>>>> from cryptography.hazmat.backends import default_backend
>>>> numbers = ec.EllipticCurvePrivateNumbers(
....     35764650566032008086366661818264207095808177403860908948280156930896899025506,
....     ec.EllipticCurvePublicNumbers(
....         47250808410553270231315736020083458949276863817723245770432653745561185532964,
....         112025329241792435454837567787427195373731133352317839821028450450273536789915,
....         ec.SECP256R1(),
....     )
.... )
>>>> numbers.private_key(default_backend())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "cryptography/hazmat/primitives/asymmetric/ec.py", line 275, in private_key
    return backend.load_elliptic_curve_private_numbers(self)
  File "cryptography/hazmat/backends/multibackend.py", line 277, in load_elliptic_curve_private_numbers
    return b.load_elliptic_curve_private_numbers(numbers)
  File "cryptography/hazmat/backends/openssl/backend.py", line 881, in load_elliptic_curve_private_numbers
    ec_cdata, public.x, public.y)
  File "cryptography/hazmat/backends/openssl/backend.py", line 1010, in _ec_key_set_public_key_affine_coordinates
    assert res == 1
AssertionError
```



Discussion:
Looks like line 1010 is an error in EC_KEY_check_key so we should possibly handle errors there more like we do with the DSA/RSA python function checks. We could also try to write a pure python EC check, although I'm unsure how difficult that would be.

I think handling the error from OpenSSL is the right first step here


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
@@ -1007,7 +1007,9 @@ def _ec_key_set_public_key_affine_coordinates(self, ctx, x, y):
         assert res == 1
 
         res = self._lib.EC_KEY_check_key(ctx)
-        assert res == 1
+        if res != 1:
+            self._consume_errors()
+            raise ValueError("Invalid EC key.")
 
         return ctx
 


Test patch:
diff --git a/tests/hazmat/primitives/test_ec.py b/tests/hazmat/primitives/test_ec.py
--- a/tests/hazmat/primitives/test_ec.py
+++ b/tests/hazmat/primitives/test_ec.py
@@ -260,6 +260,20 @@ def test_unknown_signature_algoritm(self, backend):
             ec.SECP192R1()
         ) is False
 
+    def test_load_invalid_ec_key_from_numbers(self, backend):
+        _skip_curve_unsupported(backend, ec.SECP256R1())
+
+        numbers = ec.EllipticCurvePrivateNumbers(
+            357646505660320080863666618182642070958081774038609089496899025506,
+            ec.EllipticCurvePublicNumbers(
+                47250808410327023131573602008345894927686381772325561185532964,
+                1120253292479243545483756778742719537373113335231773536789915,
+                ec.SECP256R1(),
+            )
+        )
+        with pytest.raises(ValueError):
+            numbers.private_key(backend)
+
     @pytest.mark.parametrize(
         "vector",
         load_vectors_from_file(