From 84fc4e01afaae95d5a92703b045a37183be27988 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Wed, 24 Sep 2014 16:24:21 -0500 Subject: Process curve name when loading EC keys. Fixes #1336 --- cryptography/hazmat/backends/openssl/backend.py | 31 ++++++++++++++++++++++--- cryptography/hazmat/primitives/asymmetric/ec.py | 24 +++++++++++++++++++ tests/hazmat/backends/test_openssl.py | 5 +++- tests/hazmat/primitives/test_ec.py | 28 ++++------------------ tests/hazmat/primitives/test_serialization.py | 2 ++ 5 files changed, 62 insertions(+), 28 deletions(-) diff --git a/cryptography/hazmat/backends/openssl/backend.py b/cryptography/hazmat/backends/openssl/backend.py index 0b129d1a..65fcbcb1 100644 --- a/cryptography/hazmat/backends/openssl/backend.py +++ b/cryptography/hazmat/backends/openssl/backend.py @@ -474,12 +474,28 @@ class Backend(object): assert dsa_cdata != self._ffi.NULL dsa_cdata = self._ffi.gc(dsa_cdata, self._lib.DSA_free) return _DSAPrivateKey(self, dsa_cdata) - elif self._lib.Cryptography_HAS_EC == 1 \ - and type == self._lib.EVP_PKEY_EC: + elif (self._lib.Cryptography_HAS_EC == 1 and + type == self._lib.EVP_PKEY_EC): ec_cdata = self._lib.EVP_PKEY_get1_EC_KEY(evp_pkey) assert ec_cdata != self._ffi.NULL ec_cdata = self._ffi.gc(ec_cdata, self._lib.EC_KEY_free) - return _EllipticCurvePrivateKey(self, ec_cdata, None) + group = self._lib.EC_KEY_get0_group(ec_cdata) + assert group != self._ffi.NULL + + nid = self._lib.EC_GROUP_get_curve_name(group) + assert nid != 0 + + curve_name = self._lib.OBJ_nid2sn(nid) + assert curve_name != self._ffi.NULL + + sn = self._ffi.string(curve_name).decode('ascii') + + curve = self._sn_to_elliptic_curve(sn) + + point = self._lib.EC_POINT_new(group) + assert point != self._ffi.NULL + point = self._ffi.gc(point, self._lib.EC_POINT_free) + return _EllipticCurvePrivateKey(self, ec_cdata, curve) else: raise UnsupportedAlgorithm("Unsupported key type.") @@ -1048,6 +1064,15 @@ class Backend(object): ) return curve_nid + def _sn_to_elliptic_curve(self, sn): + try: + return ec.CURVE_TYPES[sn]() + except KeyError: + raise UnsupportedAlgorithm( + "{0} is not a supported elliptic curve".format(sn), + _Reasons.UNSUPPORTED_ELLIPTIC_CURVE + ) + @contextmanager def _bn_ctx_manager(self): bn_ctx = self._lib.BN_CTX_new() diff --git a/cryptography/hazmat/primitives/asymmetric/ec.py b/cryptography/hazmat/primitives/asymmetric/ec.py index 220a419c..813e2c9e 100644 --- a/cryptography/hazmat/primitives/asymmetric/ec.py +++ b/cryptography/hazmat/primitives/asymmetric/ec.py @@ -184,6 +184,30 @@ class SECP192R1(object): return 192 +CURVE_TYPES = { + "prime192v1": SECP192R1, + "prime256v1": SECP256R1, + + "secp192r1": SECP192R1, + "secp224r1": SECP224R1, + "secp256r1": SECP256R1, + "secp384r1": SECP384R1, + "secp521r1": SECP521R1, + + "sect163k1": SECT163K1, + "sect233k1": SECT233K1, + "sect283k1": SECT283K1, + "sect409k1": SECT409K1, + "sect571k1": SECT571K1, + + "sect163r2": SECT163R2, + "sect233r1": SECT233R1, + "sect283r1": SECT283R1, + "sect409r1": SECT409R1, + "sect571r1": SECT571R1, +} + + @utils.register_interface(interfaces.EllipticCurveSignatureAlgorithm) class ECDSA(object): def __init__(self, algorithm): diff --git a/tests/hazmat/backends/test_openssl.py b/tests/hazmat/backends/test_openssl.py index d4c5e2e7..d2620060 100644 --- a/tests/hazmat/backends/test_openssl.py +++ b/tests/hazmat/backends/test_openssl.py @@ -493,7 +493,7 @@ class TestOpenSSLSerialisationWithOpenSSL(object): ) -class TestOpenSSLNoEllipticCurve(object): +class TestOpenSSLEllipticCurve(object): def test_elliptic_curve_supported(self, monkeypatch): monkeypatch.setattr(backend._lib, "Cryptography_HAS_EC", 0) @@ -506,6 +506,9 @@ class TestOpenSSLNoEllipticCurve(object): None, None ) is False + def test_sn_to_elliptic_curve_not_supported(self): + with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_ELLIPTIC_CURVE): + backend._sn_to_elliptic_curve(b"fake") class TestDeprecatedRSABackendMethods(object): def test_create_rsa_signature_ctx(self): diff --git a/tests/hazmat/primitives/test_ec.py b/tests/hazmat/primitives/test_ec.py index 2690e794..84a25868 100644 --- a/tests/hazmat/primitives/test_ec.py +++ b/tests/hazmat/primitives/test_ec.py @@ -29,26 +29,6 @@ from ...utils import ( raises_unsupported_algorithm ) -_CURVE_TYPES = { - "secp192r1": ec.SECP192R1, - "secp224r1": ec.SECP224R1, - "secp256r1": ec.SECP256R1, - "secp384r1": ec.SECP384R1, - "secp521r1": ec.SECP521R1, - - "sect163k1": ec.SECT163K1, - "sect233k1": ec.SECT233K1, - "sect283k1": ec.SECT283K1, - "sect409k1": ec.SECT409K1, - "sect571k1": ec.SECT571K1, - - "sect163r2": ec.SECT163R2, - "sect233r1": ec.SECT233R1, - "sect283r1": ec.SECT283R1, - "sect409r1": ec.SECT409R1, - "sect571r1": ec.SECT571R1, -} - _HASH_TYPES = { "SHA-1": hashes.SHA1, "SHA-224": hashes.SHA224, @@ -162,7 +142,7 @@ class TestECDSAVectors(object): )) ) def test_signing_with_example_keys(self, backend, vector, hash_type): - curve_type = _CURVE_TYPES[vector['curve']] + curve_type = ec.CURVE_TYPES[vector['curve']] _skip_ecdsa_vector(backend, curve_type, hash_type) @@ -188,7 +168,7 @@ class TestECDSAVectors(object): verifier.verify() @pytest.mark.parametrize( - "curve", _CURVE_TYPES.values() + "curve", ec.CURVE_TYPES.values() ) def test_generate_vector_curves(self, backend, curve): _skip_curve_unsupported(backend, curve()) @@ -244,7 +224,7 @@ class TestECDSAVectors(object): ) def test_signatures(self, backend, vector): hash_type = _HASH_TYPES[vector['digest_algorithm']] - curve_type = _CURVE_TYPES[vector['curve']] + curve_type = ec.CURVE_TYPES[vector['curve']] _skip_ecdsa_vector(backend, curve_type, hash_type) @@ -276,7 +256,7 @@ class TestECDSAVectors(object): ) def test_signature_failures(self, backend, vector): hash_type = _HASH_TYPES[vector['digest_algorithm']] - curve_type = _CURVE_TYPES[vector['curve']] + curve_type = ec.CURVE_TYPES[vector['curve']] _skip_ecdsa_vector(backend, curve_type, hash_type) diff --git a/tests/hazmat/primitives/test_serialization.py b/tests/hazmat/primitives/test_serialization.py index 8405f4b2..06997491 100644 --- a/tests/hazmat/primitives/test_serialization.py +++ b/tests/hazmat/primitives/test_serialization.py @@ -412,6 +412,8 @@ class TestPKCS8Serialization(object): ) assert key assert isinstance(key, interfaces.EllipticCurvePrivateKey) + assert key.curve.name == "secp256r1" + assert key.curve.key_size == 256 def test_unused_password(self, backend): key_file = os.path.join( -- cgit v1.2.3 From c5e43429c26dd1b1baddeec9fddf3cb5d98bcfc1 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Wed, 24 Sep 2014 22:37:22 -0500 Subject: learn to pep8 --- tests/hazmat/backends/test_openssl.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/hazmat/backends/test_openssl.py b/tests/hazmat/backends/test_openssl.py index d2620060..110bbdba 100644 --- a/tests/hazmat/backends/test_openssl.py +++ b/tests/hazmat/backends/test_openssl.py @@ -510,6 +510,7 @@ class TestOpenSSLEllipticCurve(object): with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_ELLIPTIC_CURVE): backend._sn_to_elliptic_curve(b"fake") + class TestDeprecatedRSABackendMethods(object): def test_create_rsa_signature_ctx(self): private_key = rsa.RSAPrivateKey.generate(65537, 512, backend) -- cgit v1.2.3 From fc5f4f97c52b07f0345efd11b03b7996ff1168d6 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Thu, 25 Sep 2014 07:40:24 -0500 Subject: CURVE_TYPES back to private, removed unneeded point creation --- cryptography/hazmat/backends/openssl/backend.py | 5 +---- cryptography/hazmat/primitives/asymmetric/ec.py | 2 +- tests/hazmat/primitives/test_ec.py | 8 ++++---- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/cryptography/hazmat/backends/openssl/backend.py b/cryptography/hazmat/backends/openssl/backend.py index 65fcbcb1..46ecde15 100644 --- a/cryptography/hazmat/backends/openssl/backend.py +++ b/cryptography/hazmat/backends/openssl/backend.py @@ -492,9 +492,6 @@ class Backend(object): curve = self._sn_to_elliptic_curve(sn) - point = self._lib.EC_POINT_new(group) - assert point != self._ffi.NULL - point = self._ffi.gc(point, self._lib.EC_POINT_free) return _EllipticCurvePrivateKey(self, ec_cdata, curve) else: raise UnsupportedAlgorithm("Unsupported key type.") @@ -1066,7 +1063,7 @@ class Backend(object): def _sn_to_elliptic_curve(self, sn): try: - return ec.CURVE_TYPES[sn]() + return ec._CURVE_TYPES[sn]() except KeyError: raise UnsupportedAlgorithm( "{0} is not a supported elliptic curve".format(sn), diff --git a/cryptography/hazmat/primitives/asymmetric/ec.py b/cryptography/hazmat/primitives/asymmetric/ec.py index 813e2c9e..98eca276 100644 --- a/cryptography/hazmat/primitives/asymmetric/ec.py +++ b/cryptography/hazmat/primitives/asymmetric/ec.py @@ -184,7 +184,7 @@ class SECP192R1(object): return 192 -CURVE_TYPES = { +_CURVE_TYPES = { "prime192v1": SECP192R1, "prime256v1": SECP256R1, diff --git a/tests/hazmat/primitives/test_ec.py b/tests/hazmat/primitives/test_ec.py index 84a25868..65461f70 100644 --- a/tests/hazmat/primitives/test_ec.py +++ b/tests/hazmat/primitives/test_ec.py @@ -142,7 +142,7 @@ class TestECDSAVectors(object): )) ) def test_signing_with_example_keys(self, backend, vector, hash_type): - curve_type = ec.CURVE_TYPES[vector['curve']] + curve_type = ec._CURVE_TYPES[vector['curve']] _skip_ecdsa_vector(backend, curve_type, hash_type) @@ -168,7 +168,7 @@ class TestECDSAVectors(object): verifier.verify() @pytest.mark.parametrize( - "curve", ec.CURVE_TYPES.values() + "curve", ec._CURVE_TYPES.values() ) def test_generate_vector_curves(self, backend, curve): _skip_curve_unsupported(backend, curve()) @@ -224,7 +224,7 @@ class TestECDSAVectors(object): ) def test_signatures(self, backend, vector): hash_type = _HASH_TYPES[vector['digest_algorithm']] - curve_type = ec.CURVE_TYPES[vector['curve']] + curve_type = ec._CURVE_TYPES[vector['curve']] _skip_ecdsa_vector(backend, curve_type, hash_type) @@ -256,7 +256,7 @@ class TestECDSAVectors(object): ) def test_signature_failures(self, backend, vector): hash_type = _HASH_TYPES[vector['digest_algorithm']] - curve_type = ec.CURVE_TYPES[vector['curve']] + curve_type = ec._CURVE_TYPES[vector['curve']] _skip_ecdsa_vector(backend, curve_type, hash_type) -- cgit v1.2.3 From 0bcfa2d5503f3bc7b77aea514fe5ffce97b8abdb Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Fri, 26 Sep 2014 16:34:54 -0500 Subject: add curve name parsing to public key loader --- cryptography/hazmat/backends/openssl/backend.py | 34 ++++++++++++++----------- tests/hazmat/primitives/test_serialization.py | 2 ++ 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/cryptography/hazmat/backends/openssl/backend.py b/cryptography/hazmat/backends/openssl/backend.py index 46ecde15..4fdede5b 100644 --- a/cryptography/hazmat/backends/openssl/backend.py +++ b/cryptography/hazmat/backends/openssl/backend.py @@ -479,19 +479,8 @@ class Backend(object): ec_cdata = self._lib.EVP_PKEY_get1_EC_KEY(evp_pkey) assert ec_cdata != self._ffi.NULL ec_cdata = self._ffi.gc(ec_cdata, self._lib.EC_KEY_free) - group = self._lib.EC_KEY_get0_group(ec_cdata) - assert group != self._ffi.NULL - - nid = self._lib.EC_GROUP_get_curve_name(group) - assert nid != 0 - - curve_name = self._lib.OBJ_nid2sn(nid) - assert curve_name != self._ffi.NULL - - sn = self._ffi.string(curve_name).decode('ascii') - + sn = self._ec_key_curve_sn(ec_cdata) curve = self._sn_to_elliptic_curve(sn) - return _EllipticCurvePrivateKey(self, ec_cdata, curve) else: raise UnsupportedAlgorithm("Unsupported key type.") @@ -514,15 +503,30 @@ class Backend(object): assert dsa_cdata != self._ffi.NULL dsa_cdata = self._ffi.gc(dsa_cdata, self._lib.DSA_free) return _DSAPublicKey(self, dsa_cdata) - elif self._lib.Cryptography_HAS_EC == 1 \ - and type == self._lib.EVP_PKEY_EC: + elif (self._lib.Cryptography_HAS_EC == 1 and + type == self._lib.EVP_PKEY_EC): ec_cdata = self._lib.EVP_PKEY_get1_EC_KEY(evp_pkey) assert ec_cdata != self._ffi.NULL ec_cdata = self._ffi.gc(ec_cdata, self._lib.EC_KEY_free) - return _EllipticCurvePublicKey(self, ec_cdata, None) + sn = self._ec_key_curve_sn(ec_cdata) + curve = self._sn_to_elliptic_curve(sn) + return _EllipticCurvePublicKey(self, ec_cdata, curve) else: raise UnsupportedAlgorithm("Unsupported key type.") + def _ec_key_curve_sn(self, ec_key): + group = self._lib.EC_KEY_get0_group(ec_key) + assert group != self._ffi.NULL + + nid = self._lib.EC_GROUP_get_curve_name(group) + assert nid != 0 + + curve_name = self._lib.OBJ_nid2sn(nid) + assert curve_name != self._ffi.NULL + + sn = self._ffi.string(curve_name).decode('ascii') + return sn + def _pem_password_cb(self, password): """ Generate a pem_password_cb function pointer that copied the password to diff --git a/tests/hazmat/primitives/test_serialization.py b/tests/hazmat/primitives/test_serialization.py index 06997491..5ee68b23 100644 --- a/tests/hazmat/primitives/test_serialization.py +++ b/tests/hazmat/primitives/test_serialization.py @@ -135,6 +135,8 @@ class TestPEMSerialization(object): ) assert key assert isinstance(key, interfaces.EllipticCurvePublicKey) + assert key.curve.name == "secp256r1" + assert key.curve.key_size == 256 @pytest.mark.traditional_openssl_serialization -- cgit v1.2.3 From 768a2815081239ae63d479cf4ea42eac16ff7fbe Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Fri, 26 Sep 2014 17:28:30 -0500 Subject: fix indentation --- cryptography/hazmat/backends/openssl/backend.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/cryptography/hazmat/backends/openssl/backend.py b/cryptography/hazmat/backends/openssl/backend.py index 4fdede5b..d9d8458e 100644 --- a/cryptography/hazmat/backends/openssl/backend.py +++ b/cryptography/hazmat/backends/openssl/backend.py @@ -515,17 +515,17 @@ class Backend(object): raise UnsupportedAlgorithm("Unsupported key type.") def _ec_key_curve_sn(self, ec_key): - group = self._lib.EC_KEY_get0_group(ec_key) - assert group != self._ffi.NULL + group = self._lib.EC_KEY_get0_group(ec_key) + assert group != self._ffi.NULL - nid = self._lib.EC_GROUP_get_curve_name(group) - assert nid != 0 + nid = self._lib.EC_GROUP_get_curve_name(group) + assert nid != 0 - curve_name = self._lib.OBJ_nid2sn(nid) - assert curve_name != self._ffi.NULL + curve_name = self._lib.OBJ_nid2sn(nid) + assert curve_name != self._ffi.NULL - sn = self._ffi.string(curve_name).decode('ascii') - return sn + sn = self._ffi.string(curve_name).decode('ascii') + return sn def _pem_password_cb(self, password): """ -- cgit v1.2.3 From afca2d508702e7e749db49aeee83940d547015a7 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Fri, 26 Sep 2014 17:29:45 -0500 Subject: use NID_undef instead of literal value --- cryptography/hazmat/backends/openssl/backend.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cryptography/hazmat/backends/openssl/backend.py b/cryptography/hazmat/backends/openssl/backend.py index d9d8458e..c28d2335 100644 --- a/cryptography/hazmat/backends/openssl/backend.py +++ b/cryptography/hazmat/backends/openssl/backend.py @@ -519,7 +519,7 @@ class Backend(object): assert group != self._ffi.NULL nid = self._lib.EC_GROUP_get_curve_name(group) - assert nid != 0 + assert nid != self._lib.NID_undef curve_name = self._lib.OBJ_nid2sn(nid) assert curve_name != self._ffi.NULL -- cgit v1.2.3