diff options
author | Paul Kehrer <paul.l.kehrer@gmail.com> | 2015-05-03 10:52:25 -0500 |
---|---|---|
committer | Paul Kehrer <paul.l.kehrer@gmail.com> | 2015-05-03 18:27:55 -0500 |
commit | d774de9d49512a16b58e1461dd982c072fd36b8e (patch) | |
tree | aa5f7ba01d5b557934a03640f8ec7421cdb317e4 | |
parent | 555905218bff81b9aadf1fff247b29bcc0e67351 (diff) | |
download | cryptography-d774de9d49512a16b58e1461dd982c072fd36b8e.tar.gz cryptography-d774de9d49512a16b58e1461dd982c072fd36b8e.tar.bz2 cryptography-d774de9d49512a16b58e1461dd982c072fd36b8e.zip |
authority key identifier support in the openssl backend
-rw-r--r-- | docs/x509.rst | 1 | ||||
-rw-r--r-- | src/cryptography/hazmat/backends/openssl/x509.py | 41 | ||||
-rw-r--r-- | src/cryptography/hazmat/bindings/openssl/x509v3.py | 3 | ||||
-rw-r--r-- | tests/test_x509_ext.py | 84 |
4 files changed, 129 insertions, 0 deletions
diff --git a/docs/x509.rst b/docs/x509.rst index f9c9af2f..f4ea2a52 100644 --- a/docs/x509.rst +++ b/docs/x509.rst @@ -317,6 +317,7 @@ X.509 Certificate Object >>> for ext in cert.extensions: ... print(ext) + <Extension(oid=<ObjectIdentifier(oid=2.5.29.35, name=authorityKeyIdentifier)>, critical=False, value=<AuthorityKeyIdentifier(key_identifier='\xe4}_\xd1\\\x95\x86\x08,\x05\xae\xbeu\xb6e\xa7\xd9]\xa8f', authority_cert_issuer=None, authority_cert_serial_number=None)>)> <Extension(oid=<ObjectIdentifier(oid=2.5.29.14, name=subjectKeyIdentifier)>, critical=False, value=<SubjectKeyIdentifier(digest='X\x01\x84$\x1b\xbc+R\x94J=\xa5\x10r\x14Q\xf5\xaf:\xc9')>)> <Extension(oid=<ObjectIdentifier(oid=2.5.29.15, name=keyUsage)>, critical=True, value=<KeyUsage(digital_signature=False, content_commitment=False, key_encipherment=False, data_encipherment=False, key_agreement=False, key_cert_sign=True, crl_sign=True, encipher_only=None, decipher_only=None)>)> <Extension(oid=<ObjectIdentifier(oid=2.5.29.19, name=basicConstraints)>, critical=True, value=<BasicConstraints(ca=True, path_length=None)>)> diff --git a/src/cryptography/hazmat/backends/openssl/x509.py b/src/cryptography/hazmat/backends/openssl/x509.py index dd2aba65..c6b85c9f 100644 --- a/src/cryptography/hazmat/backends/openssl/x509.py +++ b/src/cryptography/hazmat/backends/openssl/x509.py @@ -269,6 +269,8 @@ class _Certificate(object): value = self._build_subject_alt_name(ext) elif oid == x509.OID_EXTENDED_KEY_USAGE: value = self._build_extended_key_usage(ext) + elif oid == x509.OID_AUTHORITY_KEY_IDENTIFIER: + value = self._build_authority_key_identifier(ext) elif critical: raise x509.UnsupportedExtension( "{0} is not currently supported".format(oid), oid @@ -321,6 +323,45 @@ class _Certificate(object): self._backend._ffi.buffer(asn1_string.data, asn1_string.length)[:] ) + def _build_authority_key_identifier(self, ext): + akid = self._backend._lib.X509V3_EXT_d2i(ext) + assert akid != self._backend._ffi.NULL + akid = self._backend._ffi.cast("AUTHORITY_KEYID *", akid) + akid = self._backend._ffi.gc( + akid, self._backend._lib.AUTHORITY_KEYID_free + ) + key_identifier = None + authority_cert_issuer = None + authority_cert_serial_number = None + + if akid.keyid != self._backend._ffi.NULL: + key_identifier = self._backend._ffi.buffer( + akid.keyid.data, akid.keyid.length + )[:] + + if akid.issuer != self._backend._ffi.NULL: + authority_cert_issuer = [] + + num = self._backend._lib.sk_GENERAL_NAME_num(akid.issuer) + for i in range(num): + gn = self._backend._lib.sk_GENERAL_NAME_value(akid.issuer, i) + assert gn != self._backend._ffi.NULL + value = _build_general_name(self._backend, gn) + + authority_cert_issuer.append(value) + + if akid.serial != self._backend._ffi.NULL: + bn = self._backend._lib.ASN1_INTEGER_to_BN( + akid.serial, self._backend._ffi.NULL + ) + assert bn != self._backend._ffi.NULL + bn = self._backend._ffi.gc(bn, self._backend._lib.BN_free) + authority_cert_serial_number = self._backend._bn_to_int(bn) + + return x509.AuthorityKeyIdentifier( + key_identifier, authority_cert_issuer, authority_cert_serial_number + ) + def _build_key_usage(self, ext): bit_string = self._backend._lib.X509V3_EXT_d2i(ext) assert bit_string != self._backend._ffi.NULL diff --git a/src/cryptography/hazmat/bindings/openssl/x509v3.py b/src/cryptography/hazmat/bindings/openssl/x509v3.py index 28dd7f32..311261f0 100644 --- a/src/cryptography/hazmat/bindings/openssl/x509v3.py +++ b/src/cryptography/hazmat/bindings/openssl/x509v3.py @@ -109,6 +109,9 @@ MACROS = """ /* This is a macro defined by a call to DECLARE_ASN1_FUNCTIONS in the x509v3.h header. */ void BASIC_CONSTRAINTS_free(BASIC_CONSTRAINTS *); +/* This is a macro defined by a call to DECLARE_ASN1_FUNCTIONS in the + x509v3.h header. */ +void AUTHORITY_KEYID_free(AUTHORITY_KEYID *); void *X509V3_set_ctx_nodb(X509V3_CTX *); int sk_GENERAL_NAME_num(struct stack_st_GENERAL_NAME *); int sk_GENERAL_NAME_push(struct stack_st_GENERAL_NAME *, GENERAL_NAME *); diff --git a/tests/test_x509_ext.py b/tests/test_x509_ext.py index ab6d6ffa..ad36b5c0 100644 --- a/tests/test_x509_ext.py +++ b/tests/test_x509_ext.py @@ -1136,3 +1136,87 @@ class TestAuthorityInformationAccess(object): assert aia != aia2 assert aia != object() + + +@pytest.mark.requires_backend_interface(interface=RSABackend) +@pytest.mark.requires_backend_interface(interface=X509Backend) +class TestAuthorityKeyIdentifierExtension(object): + def test_aki_keyid(self, backend): + cert = _load_cert( + os.path.join( + "x509", "cryptography.io.pem" + ), + x509.load_pem_x509_certificate, + backend + ) + ext = cert.extensions.get_extension_for_oid( + x509.OID_AUTHORITY_KEY_IDENTIFIER + ) + assert ext is not None + assert ext.critical is False + + assert ext.value.key_identifier == ( + b"\xc3\x9c\xf3\xfc\xd3F\x084\xbb\xceF\x7f\xa0|[\xf3\xe2\x08\xcbY" + ) + assert ext.value.authority_cert_issuer is None + assert ext.value.authority_cert_serial_number is None + + def test_aki_all_fields(self, backend): + cert = _load_cert( + os.path.join( + "x509", "custom", "authority_key_identifier.pem" + ), + x509.load_pem_x509_certificate, + backend + ) + ext = cert.extensions.get_extension_for_oid( + x509.OID_AUTHORITY_KEY_IDENTIFIER + ) + assert ext is not None + assert ext.critical is False + + assert ext.value.key_identifier == ( + b"9E>\xca=b\x1d\xea\x86I\xf6Z\xab@\xb7\xa4p\x98\xf1\xec" + ) + assert ext.value.authority_cert_issuer == [ + x509.DirectoryName( + x509.Name([ + x509.NameAttribute( + x509.OID_ORGANIZATION_NAME, u"PyCA" + ), + x509.NameAttribute( + x509.OID_COMMON_NAME, u"cryptography.io" + ) + ]) + ) + ] + assert ext.value.authority_cert_serial_number == 3 + + def test_aki_no_keyid(self, backend): + cert = _load_cert( + os.path.join( + "x509", "custom", "authority_key_identifier_no_keyid.pem" + ), + x509.load_pem_x509_certificate, + backend + ) + ext = cert.extensions.get_extension_for_oid( + x509.OID_AUTHORITY_KEY_IDENTIFIER + ) + assert ext is not None + assert ext.critical is False + + assert ext.value.key_identifier is None + assert ext.value.authority_cert_issuer == [ + x509.DirectoryName( + x509.Name([ + x509.NameAttribute( + x509.OID_ORGANIZATION_NAME, u"PyCA" + ), + x509.NameAttribute( + x509.OID_COMMON_NAME, u"cryptography.io" + ) + ]) + ) + ] + assert ext.value.authority_cert_serial_number == 3 |