aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-x.travis/install.sh4
-rw-r--r--docs/development/custom-vectors/secp256k1/verify_secp256k1.py4
-rw-r--r--src/cryptography/hazmat/backends/openssl/backend.py81
-rw-r--r--src/cryptography/x509/oid.py29
-rw-r--r--tests/hazmat/backends/test_openssl.py17
-rw-r--r--tests/hazmat/primitives/test_ec.py6
-rw-r--r--tests/test_x509.py77
-rw-r--r--tests/test_x509_ext.py31
8 files changed, 171 insertions, 78 deletions
diff --git a/.travis/install.sh b/.travis/install.sh
index 112add24..142b4988 100755
--- a/.travis/install.sh
+++ b/.travis/install.sh
@@ -34,8 +34,8 @@ if [[ "$(uname -s)" == 'Darwin' ]]; then
pyenv global 3.4.2
;;
py35)
- pyenv install 3.5.0
- pyenv global 3.5.0
+ pyenv install 3.5.1
+ pyenv global 3.5.1
;;
pypy)
pyenv install pypy-4.0.1
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/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py
index 768559cf..e69554f9 100644
--- a/src/cryptography/hazmat/backends/openssl/backend.py
+++ b/src/cryptography/hazmat/backends/openssl/backend.py
@@ -40,6 +40,7 @@ from cryptography.hazmat.backends.openssl.x509 import (
_Certificate, _CertificateRevocationList, _CertificateSigningRequest,
_DISTPOINT_TYPE_FULLNAME, _DISTPOINT_TYPE_RELATIVENAME
)
+from cryptography.hazmat.bindings._openssl import ffi as _ffi
from cryptography.hazmat.bindings.openssl import binding
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import dsa, ec, rsa
@@ -625,6 +626,34 @@ _EXTENSION_ENCODE_HANDLERS = {
}
+class _PasswordUserdata(object):
+ def __init__(self, password):
+ self.password = password
+ self.called = 0
+ self.exception = None
+
+
+def _pem_password_cb(buf, size, writing, userdata_handle):
+ ud = _ffi.from_handle(userdata_handle)
+ ud.called += 1
+
+ if not ud.password:
+ ud.exception = TypeError(
+ "Password was not given but private key is encrypted."
+ )
+ return -1
+ elif len(ud.password) < size:
+ pw_buf = _ffi.buffer(buf, size)
+ pw_buf[:len(ud.password)] = ud.password
+ return len(ud.password)
+ else:
+ ud.exception = ValueError(
+ "Passwords longer than {0} bytes are not supported "
+ "by this backend.".format(size - 1)
+ )
+ return 0
+
+
@utils.register_interface(CipherBackend)
@utils.register_interface(CMACBackend)
@utils.register_interface(DERSerializationBackend)
@@ -1090,37 +1119,22 @@ class Backend(object):
Useful for decrypting PKCS8 files and so on.
- Returns a tuple of (cdata function pointer, callback function).
+ Returns a tuple of (cdata function pointer, userdata).
"""
+ # Forward compatibility for new static callbacks:
+ # _pem_password_cb is not a nested function because closures don't
+ # work well with static callbacks. Static callbacks are registered
+ # globally. The backend is passed in as userdata argument.
- def pem_password_cb(buf, size, writing, userdata):
- pem_password_cb.called += 1
+ userdata = _PasswordUserdata(password=password)
- if not password:
- pem_password_cb.exception = TypeError(
- "Password was not given but private key is encrypted."
- )
- return 0
- elif len(password) < size:
- pw_buf = self._ffi.buffer(buf, size)
- pw_buf[:len(password)] = password
- return len(password)
- else:
- pem_password_cb.exception = ValueError(
- "Passwords longer than {0} bytes are not supported "
- "by this backend.".format(size - 1)
- )
- return 0
-
- pem_password_cb.called = 0
- pem_password_cb.exception = None
-
- return (
- self._ffi.callback("int (char *, int, int, void *)",
- pem_password_cb),
- pem_password_cb
+ pem_password_cb = self._ffi.callback(
+ "int (char *, int, int, void *)",
+ _pem_password_cb,
)
+ return pem_password_cb, userdata
+
def _mgf1_hash_supported(self, algorithm):
if self._lib.Cryptography_HAS_MGF1_MD:
return self.hash_supported(algorithm)
@@ -1626,31 +1640,32 @@ class Backend(object):
def _load_key(self, openssl_read_func, convert_func, data, password):
mem_bio = self._bytes_to_bio(data)
- password_callback, password_func = self._pem_password_cb(password)
+ password_cb, userdata = self._pem_password_cb(password)
+ userdata_handle = self._ffi.new_handle(userdata)
evp_pkey = openssl_read_func(
mem_bio.bio,
self._ffi.NULL,
- password_callback,
- self._ffi.NULL
+ password_cb,
+ userdata_handle,
)
if evp_pkey == self._ffi.NULL:
- if password_func.exception is not None:
+ if userdata.exception is not None:
errors = self._consume_errors()
self.openssl_assert(errors)
- raise password_func.exception
+ raise userdata.exception
else:
self._handle_key_loading_error()
evp_pkey = self._ffi.gc(evp_pkey, self._lib.EVP_PKEY_free)
- if password is not None and password_func.called == 0:
+ if password is not None and userdata.called == 0:
raise TypeError(
"Password was given but private key is not encrypted.")
assert (
- (password is not None and password_func.called == 1) or
+ (password is not None and userdata.called == 1) or
password is None
)
diff --git a/src/cryptography/x509/oid.py b/src/cryptography/x509/oid.py
index 98a61e0b..7b4df1c9 100644
--- a/src/cryptography/x509/oid.py
+++ b/src/cryptography/x509/oid.py
@@ -12,6 +12,35 @@ 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 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)" % (
+ 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/hazmat/backends/test_openssl.py b/tests/hazmat/backends/test_openssl.py
index 85331595..d048fe68 100644
--- a/tests/hazmat/backends/test_openssl.py
+++ b/tests/hazmat/backends/test_openssl.py
@@ -503,8 +503,21 @@ class TestOpenSSLSignX509Certificate(object):
class TestOpenSSLSerialisationWithOpenSSL(object):
def test_pem_password_cb_buffer_too_small(self):
- ffi_cb, cb = backend._pem_password_cb(b"aa")
- assert cb(None, 1, False, None) == 0
+ ffi_cb, userdata = backend._pem_password_cb(b"aa")
+ handle = backend._ffi.new_handle(userdata)
+ buf = backend._ffi.new('char *')
+ assert ffi_cb(buf, 1, False, handle) == 0
+ assert userdata.called == 1
+ assert isinstance(userdata.exception, ValueError)
+
+ def test_pem_password_cb(self):
+ password = b'abcdefg'
+ ffi_cb, userdata = backend._pem_password_cb(password)
+ handle = backend._ffi.new_handle(userdata)
+ buf = backend._ffi.new('char *')
+ assert ffi_cb(buf, len(password) + 1, False, handle) == len(password)
+ assert userdata.called == 1
+ assert backend._ffi.string(buf, len(password)) == password
def test_unsupported_evp_pkey_type(self):
key = pretend.stub(type="unsupported")
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,
diff --git a/tests/test_x509.py b/tests/test_x509.py
index 86f771b3..67066f04 100644
--- a/tests/test_x509.py
+++ b/tests/test_x509.py
@@ -3210,15 +3210,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):
@@ -3228,12 +3228,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):
@@ -3252,64 +3252,87 @@ 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) == "<ObjectIdentifier(oid=2.5.4.3, name=commonName)>"
- oid = x509.ObjectIdentifier("oid1")
- assert repr(oid) == "<ObjectIdentifier(oid=oid1, name=Unknown OID)>"
+ oid = x509.ObjectIdentifier("2.999.1")
+ assert repr(oid) == "<ObjectIdentifier(oid=2.999.1, name=Unknown 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_too_short(self):
+ with pytest.raises(ValueError):
+ x509.ObjectIdentifier("1")
+
+ 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]))