aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Gaynor <alex.gaynor@gmail.com>2015-05-13 07:28:36 -0400
committerAlex Gaynor <alex.gaynor@gmail.com>2015-05-13 07:28:36 -0400
commit91ea3a91fe67ecf2577b3f88955c4baad4d4f131 (patch)
tree4619a7c2b364676ff615a4d70198eecc670f0449
parent8eca316a8f98bb607d886a0503d4fd50c4d20fd0 (diff)
parent2008d9c83cf99c56f961b6b726cfdfae426f2a31 (diff)
downloadcryptography-91ea3a91fe67ecf2577b3f88955c4baad4d4f131.tar.gz
cryptography-91ea3a91fe67ecf2577b3f88955c4baad4d4f131.tar.bz2
cryptography-91ea3a91fe67ecf2577b3f88955c4baad4d4f131.zip
Merge pull request #1940 from reaperhulk/x509-ossl-cp
support certificate policies in the openssl backend
-rw-r--r--docs/x509.rst1
-rw-r--r--src/cryptography/hazmat/backends/openssl/x509.py71
-rw-r--r--tests/test_x509_ext.py94
3 files changed, 166 insertions, 0 deletions
diff --git a/docs/x509.rst b/docs/x509.rst
index a40727cc..ff43be01 100644
--- a/docs/x509.rst
+++ b/docs/x509.rst
@@ -320,6 +320,7 @@ X.509 Certificate Object
<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.32, name=certificatePolicies)>, critical=False, value=<CertificatePolicies([<PolicyInformation(policy_identifier=<ObjectIdentifier(oid=2.16.840.1.101.3.2.1.48.1, name=Unknown OID)>, policy_qualifiers=None)>])>)>
<Extension(oid=<ObjectIdentifier(oid=2.5.29.19, name=basicConstraints)>, critical=True, value=<BasicConstraints(ca=True, path_length=None)>)>
X.509 CSR (Certificate Signing Request) Object
diff --git a/src/cryptography/hazmat/backends/openssl/x509.py b/src/cryptography/hazmat/backends/openssl/x509.py
index 8b5f3920..9d70d72f 100644
--- a/src/cryptography/hazmat/backends/openssl/x509.py
+++ b/src/cryptography/hazmat/backends/openssl/x509.py
@@ -290,6 +290,8 @@ class _Certificate(object):
value = self._build_authority_key_identifier(ext)
elif oid == x509.OID_AUTHORITY_INFORMATION_ACCESS:
value = self._build_authority_information_access(ext)
+ elif oid == x509.OID_CERTIFICATE_POLICIES:
+ value = self._build_certificate_policies(ext)
elif critical:
raise x509.UnsupportedExtension(
"{0} is not currently supported".format(oid), oid
@@ -304,6 +306,75 @@ class _Certificate(object):
return x509.Extensions(extensions)
+ def _build_certificate_policies(self, ext):
+ cp = self._backend._ffi.cast(
+ "Cryptography_STACK_OF_POLICYINFO *",
+ self._backend._lib.X509V3_EXT_d2i(ext)
+ )
+ assert cp != self._backend._ffi.NULL
+ cp = self._backend._ffi.gc(cp, self._backend._lib.sk_POLICYINFO_free)
+ num = self._backend._lib.sk_POLICYINFO_num(cp)
+ certificate_policies = []
+ for i in range(num):
+ qualifiers = None
+ pi = self._backend._lib.sk_POLICYINFO_value(cp, i)
+ oid = x509.ObjectIdentifier(_obj2txt(self._backend, pi.policyid))
+ if pi.qualifiers != self._backend._ffi.NULL:
+ qnum = self._backend._lib.sk_POLICYQUALINFO_num(pi.qualifiers)
+ qualifiers = []
+ for j in range(qnum):
+ pqi = self._backend._lib.sk_POLICYQUALINFO_value(
+ pi.qualifiers, j
+ )
+ pqualid = x509.ObjectIdentifier(
+ _obj2txt(self._backend, pqi.pqualid)
+ )
+ if pqualid == x509.OID_CPS_QUALIFIER:
+ cpsuri = self._backend._ffi.buffer(
+ pqi.d.cpsuri.data, pqi.d.cpsuri.length
+ )[:].decode('ascii')
+ qualifiers.append(cpsuri)
+ elif pqualid == x509.OID_CPS_USER_NOTICE:
+ user_notice = self._build_user_notice(pqi.d.usernotice)
+ qualifiers.append(user_notice)
+
+ certificate_policies.append(
+ x509.PolicyInformation(oid, qualifiers)
+ )
+
+ return x509.CertificatePolicies(certificate_policies)
+
+ def _build_user_notice(self, un):
+ explicit_text = None
+ notice_reference = None
+
+ if un.exptext != self._backend._ffi.NULL:
+ explicit_text = _asn1_string_to_utf8(self._backend, un.exptext)
+
+ if un.noticeref != self._backend._ffi.NULL:
+ organization = _asn1_string_to_utf8(
+ self._backend, un.noticeref.organization
+ )
+
+ num = self._backend._lib.sk_ASN1_INTEGER_num(
+ un.noticeref.noticenos
+ )
+ notice_numbers = []
+ for i in range(num):
+ asn1_int = self._backend._lib.sk_ASN1_INTEGER_value(
+ un.noticeref.noticenos, i
+ )
+ notice_num = _asn1_integer_to_int(
+ self._backend, asn1_int
+ )
+ notice_numbers.append(notice_num)
+
+ notice_reference = x509.NoticeReference(
+ organization, notice_numbers
+ )
+
+ return x509.UserNotice(notice_reference, explicit_text)
+
def _build_basic_constraints(self, ext):
bc_st = self._backend._lib.X509V3_EXT_d2i(ext)
assert bc_st != self._backend._ffi.NULL
diff --git a/tests/test_x509_ext.py b/tests/test_x509_ext.py
index 701ea167..2852776b 100644
--- a/tests/test_x509_ext.py
+++ b/tests/test_x509_ext.py
@@ -235,6 +235,100 @@ class TestCertificatePolicies(object):
assert cp != object()
+@pytest.mark.requires_backend_interface(interface=RSABackend)
+@pytest.mark.requires_backend_interface(interface=X509Backend)
+class TestCertificatePoliciesExtension(object):
+ def test_cps_uri_policy_qualifier(self, backend):
+ cert = _load_cert(
+ os.path.join("x509", "custom", "cp_cps_uri.pem"),
+ x509.load_pem_x509_certificate,
+ backend
+ )
+
+ cp = cert.extensions.get_extension_for_oid(
+ x509.OID_CERTIFICATE_POLICIES
+ ).value
+
+ assert cp == x509.CertificatePolicies([
+ x509.PolicyInformation(
+ x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
+ [u"http://other.com/cps"]
+ )
+ ])
+
+ def test_user_notice_with_notice_reference(self, backend):
+ cert = _load_cert(
+ os.path.join(
+ "x509", "custom", "cp_user_notice_with_notice_reference.pem"
+ ),
+ x509.load_pem_x509_certificate,
+ backend
+ )
+
+ cp = cert.extensions.get_extension_for_oid(
+ x509.OID_CERTIFICATE_POLICIES
+ ).value
+
+ assert cp == x509.CertificatePolicies([
+ x509.PolicyInformation(
+ x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
+ [
+ u"http://example.com/cps",
+ u"http://other.com/cps",
+ x509.UserNotice(
+ x509.NoticeReference(u"my org", [1, 2, 3, 4]),
+ u"thing"
+ )
+ ]
+ )
+ ])
+
+ def test_user_notice_with_explicit_text(self, backend):
+ cert = _load_cert(
+ os.path.join(
+ "x509", "custom", "cp_user_notice_with_explicit_text.pem"
+ ),
+ x509.load_pem_x509_certificate,
+ backend
+ )
+
+ cp = cert.extensions.get_extension_for_oid(
+ x509.OID_CERTIFICATE_POLICIES
+ ).value
+
+ assert cp == x509.CertificatePolicies([
+ x509.PolicyInformation(
+ x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
+ [x509.UserNotice(None, u"thing")]
+ )
+ ])
+
+ def test_user_notice_no_explicit_text(self, backend):
+ cert = _load_cert(
+ os.path.join(
+ "x509", "custom", "cp_user_notice_no_explicit_text.pem"
+ ),
+ x509.load_pem_x509_certificate,
+ backend
+ )
+
+ cp = cert.extensions.get_extension_for_oid(
+ x509.OID_CERTIFICATE_POLICIES
+ ).value
+
+ assert cp == x509.CertificatePolicies([
+ x509.PolicyInformation(
+ x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
+ [
+ x509.UserNotice(
+ x509.NoticeReference(u"my org", [1, 2, 3, 4]),
+ None
+ )
+ ]
+ )
+ ])
+
+
class TestKeyUsage(object):
def test_key_agreement_false_encipher_decipher_true(self):
with pytest.raises(ValueError):