From f328b31b65994393618ebc88057efd871b3a848b Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 13 Dec 2015 21:34:03 -0700 Subject: require not_valid_after >= not_valid_before --- src/cryptography/x509/base.py | 11 +++++++++++ tests/test_x509.py | 22 ++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/src/cryptography/x509/base.py b/src/cryptography/x509/base.py index c56ca5ee..49761046 100644 --- a/src/cryptography/x509/base.py +++ b/src/cryptography/x509/base.py @@ -436,6 +436,11 @@ class CertificateBuilder(object): if time <= _UNIX_EPOCH: raise ValueError('The not valid before date must be after the unix' ' epoch (1970 January 1).') + if self._not_valid_after is not None and time > self._not_valid_after: + raise ValueError( + 'The not valid before date must be before the not valid after ' + 'date.' + ) return CertificateBuilder( self._issuer_name, self._subject_name, self._public_key, self._serial_number, time, @@ -453,6 +458,12 @@ class CertificateBuilder(object): if time <= _UNIX_EPOCH: raise ValueError('The not valid after date must be after the unix' ' epoch (1970 January 1).') + if (self._not_valid_before is not None and + time < self._not_valid_before): + raise ValueError( + 'The not valid after date must be after the not valid before ' + 'date.' + ) return CertificateBuilder( self._issuer_name, self._subject_name, self._public_key, self._serial_number, self._not_valid_before, diff --git a/tests/test_x509.py b/tests/test_x509.py index 0a1870d5..86f771b3 100644 --- a/tests/test_x509.py +++ b/tests/test_x509.py @@ -1437,6 +1437,28 @@ class TestCertificateBuilder(object): with pytest.raises(ValueError): builder.subject_name(name) + def test_not_valid_before_after_not_valid_after(self): + builder = x509.CertificateBuilder() + + builder = builder.not_valid_after( + datetime.datetime(2002, 1, 1, 12, 1) + ) + with pytest.raises(ValueError): + builder.not_valid_before( + datetime.datetime(2003, 1, 1, 12, 1) + ) + + def test_not_valid_after_before_not_valid_before(self): + builder = x509.CertificateBuilder() + + builder = builder.not_valid_before( + datetime.datetime(2002, 1, 1, 12, 1) + ) + with pytest.raises(ValueError): + builder.not_valid_after( + datetime.datetime(2001, 1, 1, 12, 1) + ) + @pytest.mark.requires_backend_interface(interface=RSABackend) @pytest.mark.requires_backend_interface(interface=X509Backend) def test_public_key_must_be_public_key(self, backend): -- cgit v1.2.3 From 90c6a53a885dd5c66992309e0af98ac554f1bb97 Mon Sep 17 00:00:00 2001 From: Cory Benfield Date: Mon, 14 Dec 2015 08:35:20 +0000 Subject: Remove SSLv2 bindings. This commit removes bindings that allow users to set SSLv2 handshake methods. These are regarded as unnecessary and out-of-date: see #2527. This commit does leave in a few options that refer to SSLv2 in order to avoid breaking deployments that rely on them, and in order to allow users to continue to request that SSLv2 not be enabled at all in their OpenSSL. --- src/_cffi_src/openssl/ssl.py | 17 +---------------- .../hazmat/bindings/openssl/_conditional.py | 6 ------ 2 files changed, 1 insertion(+), 22 deletions(-) diff --git a/src/_cffi_src/openssl/ssl.py b/src/_cffi_src/openssl/ssl.py index 83a7386f..4d66f6cd 100644 --- a/src/_cffi_src/openssl/ssl.py +++ b/src/_cffi_src/openssl/ssl.py @@ -301,15 +301,6 @@ unsigned long SSL_CTX_add_extra_chain_cert(SSL_CTX *, X509 *); /* methods */ -/* SSLv2 support is compiled out of some versions of OpenSSL. These will - * get special support when we generate the bindings so that if they are - * available they will be wrapped, but if they are not they won't cause - * problems (like link errors). - */ -const SSL_METHOD *SSLv2_method(void); -const SSL_METHOD *SSLv2_server_method(void); -const SSL_METHOD *SSLv2_client_method(void); - /* * TLSv1_1 and TLSv1_2 are recent additions. Only sufficiently new versions of * OpenSSL support them. @@ -441,14 +432,8 @@ const long SSL_OP_LEGACY_SERVER_CONNECT = 0; #else static const long Cryptography_HAS_SECURE_RENEGOTIATION = 1; #endif -#ifdef OPENSSL_NO_SSL2 + static const long Cryptography_HAS_SSL2 = 0; -SSL_METHOD* (*SSLv2_method)(void) = NULL; -SSL_METHOD* (*SSLv2_client_method)(void) = NULL; -SSL_METHOD* (*SSLv2_server_method)(void) = NULL; -#else -static const long Cryptography_HAS_SSL2 = 1; -#endif #ifdef OPENSSL_NO_SSL3_METHOD static const long Cryptography_HAS_SSL3_METHOD = 0; diff --git a/src/cryptography/hazmat/bindings/openssl/_conditional.py b/src/cryptography/hazmat/bindings/openssl/_conditional.py index dad37436..206c2915 100644 --- a/src/cryptography/hazmat/bindings/openssl/_conditional.py +++ b/src/cryptography/hazmat/bindings/openssl/_conditional.py @@ -276,12 +276,6 @@ CONDITIONAL_NAMES = { "TLSv1_2_client_method", ], - "Cryptography_HAS_SSL2": [ - "SSLv2_method", - "SSLv2_client_method", - "SSLv2_server_method", - ], - "Cryptography_HAS_SSL3_METHOD": [ "SSLv3_method", "SSLv3_client_method", -- cgit v1.2.3 From f326e4a97cce6b9479560ce0c65ad18d54393f96 Mon Sep 17 00:00:00 2001 From: Cory Benfield Date: Mon, 14 Dec 2015 15:37:46 +0000 Subject: Comment lingering SSLv2 symbol. --- src/_cffi_src/openssl/ssl.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/_cffi_src/openssl/ssl.py b/src/_cffi_src/openssl/ssl.py index 4d66f6cd..64e4e2f0 100644 --- a/src/_cffi_src/openssl/ssl.py +++ b/src/_cffi_src/openssl/ssl.py @@ -433,6 +433,10 @@ const long SSL_OP_LEGACY_SERVER_CONNECT = 0; static const long Cryptography_HAS_SECURE_RENEGOTIATION = 1; #endif +/* Cryptography now compiles out all SSLv2 bindings. This exists to allow + * clients that use it to check for SSLv2 support to keep functioning as + * expected. + */ static const long Cryptography_HAS_SSL2 = 0; #ifdef OPENSSL_NO_SSL3_METHOD -- cgit v1.2.3 From 6721fb8dd70a2d392aa70b67b35e3c6efa34230b Mon Sep 17 00:00:00 2001 From: Nick Bastin Date: Mon, 14 Dec 2015 12:26:24 -0800 Subject: OID validation --- src/cryptography/x509/oid.py | 24 +++++++++++++++ tests/test_x509.py | 73 ++++++++++++++++++++++++++++---------------- tests/test_x509_ext.py | 31 +++++++++++++------ 3 files changed, 92 insertions(+), 36 deletions(-) diff --git a/src/cryptography/x509/oid.py b/src/cryptography/x509/oid.py index ead40169..ba77a8b8 100644 --- a/src/cryptography/x509/oid.py +++ b/src/cryptography/x509/oid.py @@ -12,6 +12,30 @@ class ObjectIdentifier(object): def __init__(self, dotted_string): self._dotted_string = dotted_string + nodes = self._dotted_string.split(".") + intnodes = [] + + # There must be at least 2 nodes, the first node must be 0..2, and + # if less than 2, the second node cannot have a value outside the + # range 0..39. All nodes must be integers. + for node in nodes: + try: + intnodes.append(int(node, 0)) + except ValueError: + raise ValueError( + "Malformed OID: %s (non-integer nodes)" % ( + self._dotted_string)) + + if intnodes[0] > 2: + raise ValueError( + "Malformed OID: %s (first node outside valid range)" % ( + self._dotted_string)) + + if intnodes[0] < 2 and intnodes[1] >= 40: + raise ValueError( + "Malformed OID: %s (second node outside valid range)" % ( + self._dotted_string)) + def __eq__(self, other): if not isinstance(other, ObjectIdentifier): return NotImplemented diff --git a/tests/test_x509.py b/tests/test_x509.py index 0a1870d5..164aff37 100644 --- a/tests/test_x509.py +++ b/tests/test_x509.py @@ -3188,15 +3188,15 @@ class TestNameAttribute(object): def test_init_bad_value(self): with pytest.raises(TypeError): x509.NameAttribute( - x509.ObjectIdentifier('oid'), + x509.ObjectIdentifier('2.999.1'), b'bytes' ) def test_eq(self): assert x509.NameAttribute( - x509.ObjectIdentifier('oid'), u'value' + x509.ObjectIdentifier('2.999.1'), u'value' ) == x509.NameAttribute( - x509.ObjectIdentifier('oid'), u'value' + x509.ObjectIdentifier('2.999.1'), u'value' ) def test_ne(self): @@ -3206,12 +3206,12 @@ class TestNameAttribute(object): x509.ObjectIdentifier('2.5.4.5'), u'value' ) assert x509.NameAttribute( - x509.ObjectIdentifier('oid'), u'value' + x509.ObjectIdentifier('2.999.1'), u'value' ) != x509.NameAttribute( - x509.ObjectIdentifier('oid'), u'value2' + x509.ObjectIdentifier('2.999.1'), u'value2' ) assert x509.NameAttribute( - x509.ObjectIdentifier('oid'), u'value' + x509.ObjectIdentifier('2.999.2'), u'value' ) != object() def test_repr(self): @@ -3230,64 +3230,83 @@ class TestNameAttribute(object): class TestObjectIdentifier(object): def test_eq(self): - oid1 = x509.ObjectIdentifier('oid') - oid2 = x509.ObjectIdentifier('oid') + oid1 = x509.ObjectIdentifier('2.999.1') + oid2 = x509.ObjectIdentifier('2.999.1') assert oid1 == oid2 def test_ne(self): - oid1 = x509.ObjectIdentifier('oid') - assert oid1 != x509.ObjectIdentifier('oid1') + oid1 = x509.ObjectIdentifier('2.999.1') + assert oid1 != x509.ObjectIdentifier('2.999.2') assert oid1 != object() def test_repr(self): oid = x509.ObjectIdentifier("2.5.4.3") assert repr(oid) == "" - oid = x509.ObjectIdentifier("oid1") - assert repr(oid) == "" + oid = x509.ObjectIdentifier("2.999.1") + assert repr(oid) == "" def test_name_property(self): oid = x509.ObjectIdentifier("2.5.4.3") assert oid._name == 'commonName' - oid = x509.ObjectIdentifier("oid1") + oid = x509.ObjectIdentifier("2.999.1") assert oid._name == 'Unknown OID' + def test_invalid_input(self): + with pytest.raises(ValueError): + x509.ObjectIdentifier("notavalidform") + + def test_invalid_node1(self): + with pytest.raises(ValueError): + x509.ObjectIdentifier("7.1.37") + + def test_invalid_node2(self): + with pytest.raises(ValueError): + x509.ObjectIdentifier("1.50.200") + + def test_valid(self): + x509.ObjectIdentifier("0.35.200") + x509.ObjectIdentifier("1.39.999") + x509.ObjectIdentifier("2.5.29.3") + x509.ObjectIdentifier("2.999.37.5.22.8") + x509.ObjectIdentifier("2.25.305821105408246119474742976030998643995") + class TestName(object): def test_eq(self): name1 = x509.Name([ - x509.NameAttribute(x509.ObjectIdentifier('oid'), u'value1'), - x509.NameAttribute(x509.ObjectIdentifier('oid2'), u'value2'), + x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'value1'), + x509.NameAttribute(x509.ObjectIdentifier('2.999.2'), u'value2'), ]) name2 = x509.Name([ - x509.NameAttribute(x509.ObjectIdentifier('oid'), u'value1'), - x509.NameAttribute(x509.ObjectIdentifier('oid2'), u'value2'), + x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'value1'), + x509.NameAttribute(x509.ObjectIdentifier('2.999.2'), u'value2'), ]) assert name1 == name2 def test_ne(self): name1 = x509.Name([ - x509.NameAttribute(x509.ObjectIdentifier('oid'), u'value1'), - x509.NameAttribute(x509.ObjectIdentifier('oid2'), u'value2'), + x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'value1'), + x509.NameAttribute(x509.ObjectIdentifier('2.999.2'), u'value2'), ]) name2 = x509.Name([ - x509.NameAttribute(x509.ObjectIdentifier('oid2'), u'value2'), - x509.NameAttribute(x509.ObjectIdentifier('oid'), u'value1'), + x509.NameAttribute(x509.ObjectIdentifier('2.999.2'), u'value2'), + x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'value1'), ]) assert name1 != name2 assert name1 != object() def test_hash(self): name1 = x509.Name([ - x509.NameAttribute(x509.ObjectIdentifier('oid'), u'value1'), - x509.NameAttribute(x509.ObjectIdentifier('oid2'), u'value2'), + x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'value1'), + x509.NameAttribute(x509.ObjectIdentifier('2.999.2'), u'value2'), ]) name2 = x509.Name([ - x509.NameAttribute(x509.ObjectIdentifier('oid'), u'value1'), - x509.NameAttribute(x509.ObjectIdentifier('oid2'), u'value2'), + x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'value1'), + x509.NameAttribute(x509.ObjectIdentifier('2.999.2'), u'value2'), ]) name3 = x509.Name([ - x509.NameAttribute(x509.ObjectIdentifier('oid2'), u'value2'), - x509.NameAttribute(x509.ObjectIdentifier('oid'), u'value1'), + x509.NameAttribute(x509.ObjectIdentifier('2.999.2'), u'value2'), + x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'value1'), ]) assert hash(name1) == hash(name2) diff --git a/tests/test_x509_ext.py b/tests/test_x509_ext.py index 8f469366..751de08d 100644 --- a/tests/test_x509_ext.py +++ b/tests/test_x509_ext.py @@ -18,7 +18,8 @@ from cryptography.hazmat.backends.interfaces import ( ) from cryptography.hazmat.primitives.asymmetric import ec from cryptography.x509.oid import ( - AuthorityInformationAccessOID, ExtendedKeyUsageOID, ExtensionOID, NameOID + AuthorityInformationAccessOID, ExtendedKeyUsageOID, + ExtensionOID, NameOID ) from .hazmat.primitives.test_ec import _skip_curve_unsupported @@ -603,8 +604,14 @@ class TestAuthorityKeyIdentifier(object): def test_authority_cert_serial_number_not_integer(self): dirname = x509.DirectoryName( x509.Name([ - x509.NameAttribute(x509.ObjectIdentifier('oid'), u'value1'), - x509.NameAttribute(x509.ObjectIdentifier('oid2'), u'value2'), + x509.NameAttribute( + x509.ObjectIdentifier('2.999.1'), + u'value1' + ), + x509.NameAttribute( + x509.ObjectIdentifier('2.999.2'), + u'value2' + ), ]) ) with pytest.raises(TypeError): @@ -617,8 +624,14 @@ class TestAuthorityKeyIdentifier(object): def test_authority_issuer_not_none_serial_none(self): dirname = x509.DirectoryName( x509.Name([ - x509.NameAttribute(x509.ObjectIdentifier('oid'), u'value1'), - x509.NameAttribute(x509.ObjectIdentifier('oid2'), u'value2'), + x509.NameAttribute( + x509.ObjectIdentifier('2.999.1'), + u'value1' + ), + x509.NameAttribute( + x509.ObjectIdentifier('2.999.2'), + u'value2' + ), ]) ) with pytest.raises(ValueError): @@ -1166,10 +1179,10 @@ class TestDirectoryName(object): def test_eq(self): name = x509.Name([ - x509.NameAttribute(x509.ObjectIdentifier('oid'), u'value1') + x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'value1') ]) name2 = x509.Name([ - x509.NameAttribute(x509.ObjectIdentifier('oid'), u'value1') + x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'value1') ]) gn = x509.DirectoryName(x509.Name([name])) gn2 = x509.DirectoryName(x509.Name([name2])) @@ -1177,10 +1190,10 @@ class TestDirectoryName(object): def test_ne(self): name = x509.Name([ - x509.NameAttribute(x509.ObjectIdentifier('oid'), u'value1') + x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'value1') ]) name2 = x509.Name([ - x509.NameAttribute(x509.ObjectIdentifier('oid'), u'value2') + x509.NameAttribute(x509.ObjectIdentifier('2.999.2'), u'value2') ]) gn = x509.DirectoryName(x509.Name([name])) gn2 = x509.DirectoryName(x509.Name([name2])) -- cgit v1.2.3 From 80d8d4af618def517f021e77a25d06fe8319c7d0 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Tue, 15 Dec 2015 17:01:03 -0700 Subject: X509_set_subject_name and X509_set_issuer_name copy the object So we need to register our own copy for gc. This fixes a memory leak reported by Wulf. --- src/cryptography/hazmat/backends/openssl/backend.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index 8d9e5e0e..768559cf 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -1372,7 +1372,7 @@ class Backend(object): # Set the subject's name. res = self._lib.X509_set_subject_name( - x509_cert, _encode_name(self, list(builder._subject_name)) + x509_cert, _encode_name_gc(self, list(builder._subject_name)) ) self.openssl_assert(res == 1) @@ -1423,7 +1423,7 @@ class Backend(object): # Set the issuer name. res = self._lib.X509_set_issuer_name( - x509_cert, _encode_name(self, list(builder._issuer_name)) + x509_cert, _encode_name_gc(self, list(builder._issuer_name)) ) self.openssl_assert(res == 1) -- cgit v1.2.3 From f9c30b39f28f25c7da462fe16d989c2050dee2a7 Mon Sep 17 00:00:00 2001 From: Nick Bastin Date: Thu, 17 Dec 2015 05:28:49 -0800 Subject: Avoid IndexError on too-short OIDs, add test for regression --- src/cryptography/x509/oid.py | 5 +++++ tests/test_x509.py | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/src/cryptography/x509/oid.py b/src/cryptography/x509/oid.py index ba77a8b8..f5dc2f81 100644 --- a/src/cryptography/x509/oid.py +++ b/src/cryptography/x509/oid.py @@ -26,6 +26,11 @@ class ObjectIdentifier(object): "Malformed OID: %s (non-integer nodes)" % ( self._dotted_string)) + if len(nodes) < 2: + raise ValueError( + "Malformed OID: %s (insufficient number of nodes)" % ( + self._dotted_string) + if intnodes[0] > 2: raise ValueError( "Malformed OID: %s (first node outside valid range)" % ( diff --git a/tests/test_x509.py b/tests/test_x509.py index 164aff37..ccdff7c4 100644 --- a/tests/test_x509.py +++ b/tests/test_x509.py @@ -3251,6 +3251,10 @@ class TestObjectIdentifier(object): oid = x509.ObjectIdentifier("2.999.1") assert oid._name == 'Unknown OID' + def test_too_short(self): + with pytest.raises(ValueError): + x509.ObjectIdentifier("1") + def test_invalid_input(self): with pytest.raises(ValueError): x509.ObjectIdentifier("notavalidform") -- cgit v1.2.3 From 241c390d5622be832b034141a634eeac38e325fb Mon Sep 17 00:00:00 2001 From: Nick Bastin Date: Thu, 17 Dec 2015 05:30:07 -0800 Subject: Typo --- src/cryptography/x509/oid.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cryptography/x509/oid.py b/src/cryptography/x509/oid.py index f5dc2f81..27fab86b 100644 --- a/src/cryptography/x509/oid.py +++ b/src/cryptography/x509/oid.py @@ -29,7 +29,7 @@ class ObjectIdentifier(object): if len(nodes) < 2: raise ValueError( "Malformed OID: %s (insufficient number of nodes)" % ( - self._dotted_string) + self._dotted_string)) if intnodes[0] > 2: raise ValueError( -- cgit v1.2.3 From d242ebbfd73a5b0aeb085e903cadbe4f13b5d63d Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 19 Dec 2015 12:44:36 -0500 Subject: use the non-deprecated name for this function --- docs/development/custom-vectors/secp256k1/verify_secp256k1.py | 4 ++-- tests/hazmat/primitives/test_ec.py | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/development/custom-vectors/secp256k1/verify_secp256k1.py b/docs/development/custom-vectors/secp256k1/verify_secp256k1.py index 3d2c25b9..b236d77f 100644 --- a/docs/development/custom-vectors/secp256k1/verify_secp256k1.py +++ b/docs/development/custom-vectors/secp256k1/verify_secp256k1.py @@ -6,7 +6,7 @@ from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.asymmetric import ec from cryptography.hazmat.primitives.asymmetric.utils import ( - encode_rfc6979_signature + encode_dss_signature ) from tests.utils import ( @@ -27,7 +27,7 @@ def verify_one_vector(vector): message = vector['message'] x = vector['x'] y = vector['y'] - signature = encode_rfc6979_signature(vector['r'], vector['s']) + signature = encode_dss_signature(vector['r'], vector['s']) numbers = ec.EllipticCurvePublicNumbers( x, y, diff --git a/tests/hazmat/primitives/test_ec.py b/tests/hazmat/primitives/test_ec.py index a0417fbd..86132678 100644 --- a/tests/hazmat/primitives/test_ec.py +++ b/tests/hazmat/primitives/test_ec.py @@ -19,7 +19,7 @@ from cryptography.hazmat.backends.interfaces import ( from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import ec from cryptography.hazmat.primitives.asymmetric.utils import ( - encode_rfc6979_signature + encode_dss_signature ) from .fixtures_ec import EC_KEY_SECP384R1 @@ -434,7 +434,7 @@ class TestECDSAVectors(object): curve_type() ).public_key(backend) - signature = encode_rfc6979_signature(vector['r'], vector['s']) + signature = encode_dss_signature(vector['r'], vector['s']) verifier = key.verifier( signature, @@ -463,7 +463,7 @@ class TestECDSAVectors(object): curve_type() ).public_key(backend) - signature = encode_rfc6979_signature(vector['r'], vector['s']) + signature = encode_dss_signature(vector['r'], vector['s']) verifier = key.verifier( signature, -- cgit v1.2.3