Skip to content

Commit

Permalink
Support EC and DSA signing of CRLs in the OpenSSL backend
Browse files Browse the repository at this point in the history
  • Loading branch information
reaperhulk committed Dec 27, 2015
1 parent d5d0a31 commit 9d34531
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 15 deletions.
21 changes: 11 additions & 10 deletions src/cryptography/hazmat/backends/openssl/backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -1453,16 +1453,17 @@ def create_x509_crl(self, builder, private_key, algorithm):
if not isinstance(algorithm, hashes.HashAlgorithm):
raise TypeError('Algorithm must be a registered hash algorithm.')

if isinstance(private_key, _DSAPrivateKey):
raise NotImplementedError(
"CRL signatures aren't implemented for DSA"
" keys at this time."
)
if isinstance(private_key, _EllipticCurvePrivateKey):
raise NotImplementedError(
"CRL signatures aren't implemented for EC"
" keys at this time."
)
if self._lib.OPENSSL_VERSION_NUMBER <= 0x10001000:
if isinstance(private_key, _DSAPrivateKey):
raise NotImplementedError(
"CRL signatures aren't implemented for DSA"
" keys on OpenSSL versions less than 1.0.1."
)
if isinstance(private_key, _EllipticCurvePrivateKey):
raise NotImplementedError(
"CRL signatures aren't implemented for EC"
" keys on OpenSSL versions less than 1.0.1."
)

evp_md = self._lib.EVP_get_digestbyname(
algorithm.name.encode('ascii')
Expand Down
37 changes: 37 additions & 0 deletions tests/hazmat/backends/test_openssl.py
Original file line number Diff line number Diff line change
Expand Up @@ -558,6 +558,43 @@ def test_invalid_builder(self):
with pytest.raises(TypeError):
backend.create_x509_crl(object(), private_key, hashes.SHA256())

@pytest.mark.skipif(
backend._lib.OPENSSL_VERSION_NUMBER >= 0x10001000,
reason="Requires an older OpenSSL. Must be < 1.0.1"
)
def test_sign_with_dsa_private_key_is_unsupported(self):
private_key = DSA_KEY_2048.private_key(backend)
builder = x509.CertificateRevocationListBuilder()
builder = builder.issuer_name(
x509.Name([x509.NameAttribute(x509.NameOID.COUNTRY_NAME, u'US')])
).last_update(
datetime.datetime(2002, 1, 1, 12, 1)
).next_update(
datetime.datetime(2032, 1, 1, 12, 1)
)

with pytest.raises(NotImplementedError):
builder.sign(private_key, hashes.SHA1(), backend)

@pytest.mark.skipif(
backend._lib.OPENSSL_VERSION_NUMBER >= 0x10001000,
reason="Requires an older OpenSSL. Must be < 1.0.1"
)
def test_sign_with_ec_private_key_is_unsupported(self):
_skip_curve_unsupported(backend, ec.SECP256R1())
private_key = ec.generate_private_key(ec.SECP256R1(), backend)
builder = x509.CertificateRevocationListBuilder()
builder = builder.issuer_name(
x509.Name([x509.NameAttribute(x509.NameOID.COUNTRY_NAME, u'US')])
).last_update(
datetime.datetime(2002, 1, 1, 12, 1)
).next_update(
datetime.datetime(2032, 1, 1, 12, 1)
)

with pytest.raises(NotImplementedError):
builder.sign(private_key, hashes.SHA512(), backend)


class TestOpenSSLCreateRevokedCertificate(object):
def test_invalid_builder(self):
Expand Down
64 changes: 59 additions & 5 deletions tests/test_x509_crlbuilder.py
Original file line number Diff line number Diff line change
Expand Up @@ -308,8 +308,23 @@ def test_sign_with_invalid_hash(self, backend):

@pytest.mark.requires_backend_interface(interface=DSABackend)
@pytest.mark.requires_backend_interface(interface=X509Backend)
def test_sign_dsa_key_unsupported(self, backend):
def test_sign_dsa_key(self, backend):
if backend._lib.OPENSSL_VERSION_NUMBER < 0x10001000:
pytest.skip("Requires a newer OpenSSL. Must be >= 1.0.1")
private_key = DSA_KEY_2048.private_key(backend)
invalidity_date = x509.InvalidityDate(
datetime.datetime(2002, 1, 1, 0, 0)
)
ian = x509.IssuerAlternativeName([
x509.UniformResourceIdentifier(u"https://cryptography.io"),
])
revoked_cert0 = x509.RevokedCertificateBuilder().serial_number(
2
).revocation_date(
datetime.datetime(2012, 1, 1, 1, 1)
).add_extension(
invalidity_date, False
).build(backend)
last_update = datetime.datetime(2002, 1, 1, 12, 1)
next_update = datetime.datetime(2030, 1, 1, 12, 1)
builder = x509.CertificateRevocationListBuilder().issuer_name(
Expand All @@ -320,16 +335,43 @@ def test_sign_dsa_key_unsupported(self, backend):
last_update
).next_update(
next_update
).add_revoked_certificate(
revoked_cert0
).add_extension(
ian, False
)

with pytest.raises(NotImplementedError):
builder.sign(private_key, hashes.SHA256(), backend)
crl = builder.sign(private_key, hashes.SHA256(), backend)
assert crl.extensions.get_extension_for_class(
x509.IssuerAlternativeName
).value == ian
assert crl[0].serial_number == revoked_cert0.serial_number
assert crl[0].revocation_date == revoked_cert0.revocation_date
assert len(crl[0].extensions) == 1
ext = crl[0].extensions.get_extension_for_class(x509.InvalidityDate)
assert ext.critical is False
assert ext.value == invalidity_date

@pytest.mark.requires_backend_interface(interface=EllipticCurveBackend)
@pytest.mark.requires_backend_interface(interface=X509Backend)
def test_sign_ec_key_unsupported(self, backend):
if backend._lib.OPENSSL_VERSION_NUMBER < 0x10001000:
pytest.skip("Requires a newer OpenSSL. Must be >= 1.0.1")
_skip_curve_unsupported(backend, ec.SECP256R1())
private_key = ec.generate_private_key(ec.SECP256R1(), backend)
invalidity_date = x509.InvalidityDate(
datetime.datetime(2002, 1, 1, 0, 0)
)
ian = x509.IssuerAlternativeName([
x509.UniformResourceIdentifier(u"https://cryptography.io"),
])
revoked_cert0 = x509.RevokedCertificateBuilder().serial_number(
2
).revocation_date(
datetime.datetime(2012, 1, 1, 1, 1)
).add_extension(
invalidity_date, False
).build(backend)
last_update = datetime.datetime(2002, 1, 1, 12, 1)
next_update = datetime.datetime(2030, 1, 1, 12, 1)
builder = x509.CertificateRevocationListBuilder().issuer_name(
Expand All @@ -340,10 +382,22 @@ def test_sign_ec_key_unsupported(self, backend):
last_update
).next_update(
next_update
).add_revoked_certificate(
revoked_cert0
).add_extension(
ian, False
)

with pytest.raises(NotImplementedError):
builder.sign(private_key, hashes.SHA256(), backend)
crl = builder.sign(private_key, hashes.SHA256(), backend)
assert crl.extensions.get_extension_for_class(
x509.IssuerAlternativeName
).value == ian
assert crl[0].serial_number == revoked_cert0.serial_number
assert crl[0].revocation_date == revoked_cert0.revocation_date
assert len(crl[0].extensions) == 1
ext = crl[0].extensions.get_extension_for_class(x509.InvalidityDate)
assert ext.critical is False
assert ext.value == invalidity_date

@pytest.mark.requires_backend_interface(interface=RSABackend)
@pytest.mark.requires_backend_interface(interface=X509Backend)
Expand Down

0 comments on commit 9d34531

Please sign in to comment.