Merge pull request #1961 from AndreLouisCaron/refactor-openssl-extensions

Prepares X509 decoding functions for more CA functionality.
diff --git a/src/cryptography/hazmat/backends/openssl/x509.py b/src/cryptography/hazmat/backends/openssl/x509.py
index 07e54ba..b36694d 100644
--- a/src/cryptography/hazmat/backends/openssl/x509.py
+++ b/src/cryptography/hazmat/backends/openssl/x509.py
@@ -56,7 +56,7 @@
     return backend._ffi.buffer(buf[0], res)[:].decode('utf8')
 
 
-def _build_x509_name_entry(backend, x509_name_entry):
+def _decode_x509_name_entry(backend, x509_name_entry):
     obj = backend._lib.X509_NAME_ENTRY_get_object(x509_name_entry)
     assert obj != backend._ffi.NULL
     data = backend._lib.X509_NAME_ENTRY_get_data(x509_name_entry)
@@ -67,28 +67,28 @@
     return x509.NameAttribute(x509.ObjectIdentifier(oid), value)
 
 
-def _build_x509_name(backend, x509_name):
+def _decode_x509_name(backend, x509_name):
     count = backend._lib.X509_NAME_entry_count(x509_name)
     attributes = []
     for x in range(count):
         entry = backend._lib.X509_NAME_get_entry(x509_name, x)
-        attributes.append(_build_x509_name_entry(backend, entry))
+        attributes.append(_decode_x509_name_entry(backend, entry))
 
     return x509.Name(attributes)
 
 
-def _build_general_names(backend, gns):
+def _decode_general_names(backend, gns):
     num = backend._lib.sk_GENERAL_NAME_num(gns)
     names = []
     for i in range(num):
         gn = backend._lib.sk_GENERAL_NAME_value(gns, i)
         assert gn != backend._ffi.NULL
-        names.append(_build_general_name(backend, gn))
+        names.append(_decode_general_name(backend, gn))
 
     return names
 
 
-def _build_general_name(backend, gn):
+def _decode_general_name(backend, gn):
     if gn.type == backend._lib.GEN_DNS:
         data = backend._ffi.buffer(gn.d.dNSName.data, gn.d.dNSName.length)[:]
         return x509.DNSName(idna.decode(data))
@@ -129,7 +129,7 @@
         )
     elif gn.type == backend._lib.GEN_DIRNAME:
         return x509.DirectoryName(
-            _build_x509_name(backend, gn.d.directoryName)
+            _decode_x509_name(backend, gn.d.directoryName)
         )
     elif gn.type == backend._lib.GEN_EMAIL:
         data = backend._ffi.buffer(
@@ -244,13 +244,13 @@
     def issuer(self):
         issuer = self._backend._lib.X509_get_issuer_name(self._x509)
         assert issuer != self._backend._ffi.NULL
-        return _build_x509_name(self._backend, issuer)
+        return _decode_x509_name(self._backend, issuer)
 
     @property
     def subject(self):
         subject = self._backend._lib.X509_get_subject_name(self._x509)
         assert subject != self._backend._ffi.NULL
-        return _build_x509_name(self._backend, subject)
+        return _decode_x509_name(self._backend, subject)
 
     @property
     def signature_hash_algorithm(self):
@@ -278,23 +278,25 @@
                     "Duplicate {0} extension found".format(oid), oid
                 )
             elif oid == x509.OID_BASIC_CONSTRAINTS:
-                value = self._build_basic_constraints(ext)
+                value = _decode_basic_constraints(self._backend, ext)
             elif oid == x509.OID_SUBJECT_KEY_IDENTIFIER:
-                value = self._build_subject_key_identifier(ext)
+                value = _decode_subject_key_identifier(self._backend, ext)
             elif oid == x509.OID_KEY_USAGE:
-                value = self._build_key_usage(ext)
+                value = _decode_key_usage(self._backend, ext)
             elif oid == x509.OID_SUBJECT_ALTERNATIVE_NAME:
-                value = self._build_subject_alt_name(ext)
+                value = _decode_subject_alt_name(self._backend, ext)
             elif oid == x509.OID_EXTENDED_KEY_USAGE:
-                value = self._build_extended_key_usage(ext)
+                value = _decode_extended_key_usage(self._backend, ext)
             elif oid == x509.OID_AUTHORITY_KEY_IDENTIFIER:
-                value = self._build_authority_key_identifier(ext)
+                value = _decode_authority_key_identifier(self._backend, ext)
             elif oid == x509.OID_AUTHORITY_INFORMATION_ACCESS:
-                value = self._build_authority_information_access(ext)
+                value = _decode_authority_information_access(
+                    self._backend, ext
+                )
             elif oid == x509.OID_CERTIFICATE_POLICIES:
-                value = self._build_certificate_policies(ext)
+                value = _decode_certificate_policies(self._backend, ext)
             elif oid == x509.OID_CRL_DISTRIBUTION_POINTS:
-                value = self._build_crl_distribution_points(ext)
+                value = _decode_crl_distribution_points(self._backend, ext)
             elif critical:
                 raise x509.UnsupportedExtension(
                     "{0} is not currently supported".format(oid), oid
@@ -309,311 +311,323 @@
 
         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
+def _decode_certificate_policies(backend, ext):
+    cp = backend._ffi.cast(
+        "Cryptography_STACK_OF_POLICYINFO *",
+        backend._lib.X509V3_EXT_d2i(ext)
+    )
+    assert cp != backend._ffi.NULL
+    cp = backend._ffi.gc(cp, backend._lib.sk_POLICYINFO_free)
+    num = backend._lib.sk_POLICYINFO_num(cp)
+    certificate_policies = []
+    for i in range(num):
+        qualifiers = None
+        pi = backend._lib.sk_POLICYINFO_value(cp, i)
+        oid = x509.ObjectIdentifier(_obj2txt(backend, pi.policyid))
+        if pi.qualifiers != backend._ffi.NULL:
+            qnum = backend._lib.sk_POLICYQUALINFO_num(pi.qualifiers)
+            qualifiers = []
+            for j in range(qnum):
+                pqi = backend._lib.sk_POLICYQUALINFO_value(
+                    pi.qualifiers, j
                 )
-                notice_num = _asn1_integer_to_int(
-                    self._backend, asn1_int
+                pqualid = x509.ObjectIdentifier(
+                    _obj2txt(backend, pqi.pqualid)
                 )
-                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
-        basic_constraints = self._backend._ffi.cast(
-            "BASIC_CONSTRAINTS *", bc_st
-        )
-        basic_constraints = self._backend._ffi.gc(
-            basic_constraints, self._backend._lib.BASIC_CONSTRAINTS_free
-        )
-        # The byte representation of an ASN.1 boolean true is \xff. OpenSSL
-        # chooses to just map this to its ordinal value, so true is 255 and
-        # false is 0.
-        ca = basic_constraints.ca == 255
-        if basic_constraints.pathlen == self._backend._ffi.NULL:
-            path_length = None
-        else:
-            path_length = _asn1_integer_to_int(
-                self._backend, basic_constraints.pathlen
-            )
-
-        return x509.BasicConstraints(ca, path_length)
-
-    def _build_subject_key_identifier(self, ext):
-        asn1_string = self._backend._lib.X509V3_EXT_d2i(ext)
-        assert asn1_string != self._backend._ffi.NULL
-        asn1_string = self._backend._ffi.cast(
-            "ASN1_OCTET_STRING *", asn1_string
-        )
-        asn1_string = self._backend._ffi.gc(
-            asn1_string, self._backend._lib.ASN1_OCTET_STRING_free
-        )
-        return x509.SubjectKeyIdentifier(
-            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 = _build_general_names(
-                self._backend, akid.issuer
-            )
-
-        if akid.serial != self._backend._ffi.NULL:
-            authority_cert_serial_number = _asn1_integer_to_int(
-                self._backend, akid.serial
-            )
-
-        return x509.AuthorityKeyIdentifier(
-            key_identifier, authority_cert_issuer, authority_cert_serial_number
-        )
-
-    def _build_authority_information_access(self, ext):
-        aia = self._backend._lib.X509V3_EXT_d2i(ext)
-        assert aia != self._backend._ffi.NULL
-        aia = self._backend._ffi.cast(
-            "Cryptography_STACK_OF_ACCESS_DESCRIPTION *", aia
-        )
-        aia = self._backend._ffi.gc(
-            aia, self._backend._lib.sk_ACCESS_DESCRIPTION_free
-        )
-        num = self._backend._lib.sk_ACCESS_DESCRIPTION_num(aia)
-        access_descriptions = []
-        for i in range(num):
-            ad = self._backend._lib.sk_ACCESS_DESCRIPTION_value(aia, i)
-            assert ad.method != self._backend._ffi.NULL
-            oid = x509.ObjectIdentifier(_obj2txt(self._backend, ad.method))
-            assert ad.location != self._backend._ffi.NULL
-            gn = _build_general_name(self._backend, ad.location)
-            access_descriptions.append(x509.AccessDescription(oid, gn))
-
-        return x509.AuthorityInformationAccess(access_descriptions)
-
-    def _build_key_usage(self, ext):
-        bit_string = self._backend._lib.X509V3_EXT_d2i(ext)
-        assert bit_string != self._backend._ffi.NULL
-        bit_string = self._backend._ffi.cast("ASN1_BIT_STRING *", bit_string)
-        bit_string = self._backend._ffi.gc(
-            bit_string, self._backend._lib.ASN1_BIT_STRING_free
-        )
-        get_bit = self._backend._lib.ASN1_BIT_STRING_get_bit
-        digital_signature = get_bit(bit_string, 0) == 1
-        content_commitment = get_bit(bit_string, 1) == 1
-        key_encipherment = get_bit(bit_string, 2) == 1
-        data_encipherment = get_bit(bit_string, 3) == 1
-        key_agreement = get_bit(bit_string, 4) == 1
-        key_cert_sign = get_bit(bit_string, 5) == 1
-        crl_sign = get_bit(bit_string, 6) == 1
-        encipher_only = get_bit(bit_string, 7) == 1
-        decipher_only = get_bit(bit_string, 8) == 1
-        return x509.KeyUsage(
-            digital_signature,
-            content_commitment,
-            key_encipherment,
-            data_encipherment,
-            key_agreement,
-            key_cert_sign,
-            crl_sign,
-            encipher_only,
-            decipher_only
-        )
-
-    def _build_subject_alt_name(self, ext):
-        gns = self._backend._ffi.cast(
-            "GENERAL_NAMES *", self._backend._lib.X509V3_EXT_d2i(ext)
-        )
-        assert gns != self._backend._ffi.NULL
-        gns = self._backend._ffi.gc(gns, self._backend._lib.GENERAL_NAMES_free)
-        general_names = _build_general_names(self._backend, gns)
-
-        return x509.SubjectAlternativeName(general_names)
-
-    def _build_extended_key_usage(self, ext):
-        sk = self._backend._ffi.cast(
-            "Cryptography_STACK_OF_ASN1_OBJECT *",
-            self._backend._lib.X509V3_EXT_d2i(ext)
-        )
-        assert sk != self._backend._ffi.NULL
-        sk = self._backend._ffi.gc(sk, self._backend._lib.sk_ASN1_OBJECT_free)
-        num = self._backend._lib.sk_ASN1_OBJECT_num(sk)
-        ekus = []
-
-        for i in range(num):
-            obj = self._backend._lib.sk_ASN1_OBJECT_value(sk, i)
-            assert obj != self._backend._ffi.NULL
-            oid = x509.ObjectIdentifier(_obj2txt(self._backend, obj))
-            ekus.append(oid)
-
-        return x509.ExtendedKeyUsage(ekus)
-
-    def _build_crl_distribution_points(self, ext):
-        cdps = self._backend._ffi.cast(
-            "Cryptography_STACK_OF_DIST_POINT *",
-            self._backend._lib.X509V3_EXT_d2i(ext)
-        )
-        assert cdps != self._backend._ffi.NULL
-        cdps = self._backend._ffi.gc(
-            cdps, self._backend._lib.sk_DIST_POINT_free)
-        num = self._backend._lib.sk_DIST_POINT_num(cdps)
-
-        dist_points = []
-        for i in range(num):
-            full_name = None
-            relative_name = None
-            crl_issuer = None
-            reasons = None
-            cdp = self._backend._lib.sk_DIST_POINT_value(cdps, i)
-            if cdp.reasons != self._backend._ffi.NULL:
-                # We will check each bit from RFC 5280
-                # ReasonFlags ::= BIT STRING {
-                #      unused                  (0),
-                #      keyCompromise           (1),
-                #      cACompromise            (2),
-                #      affiliationChanged      (3),
-                #      superseded              (4),
-                #      cessationOfOperation    (5),
-                #      certificateHold         (6),
-                #      privilegeWithdrawn      (7),
-                #      aACompromise            (8) }
-                reasons = []
-                get_bit = self._backend._lib.ASN1_BIT_STRING_get_bit
-                if get_bit(cdp.reasons, 1):
-                    reasons.append(x509.ReasonFlags.key_compromise)
-
-                if get_bit(cdp.reasons, 2):
-                    reasons.append(x509.ReasonFlags.ca_compromise)
-
-                if get_bit(cdp.reasons, 3):
-                    reasons.append(x509.ReasonFlags.affiliation_changed)
-
-                if get_bit(cdp.reasons, 4):
-                    reasons.append(x509.ReasonFlags.superseded)
-
-                if get_bit(cdp.reasons, 5):
-                    reasons.append(x509.ReasonFlags.cessation_of_operation)
-
-                if get_bit(cdp.reasons, 6):
-                    reasons.append(x509.ReasonFlags.certificate_hold)
-
-                if get_bit(cdp.reasons, 7):
-                    reasons.append(x509.ReasonFlags.privilege_withdrawn)
-
-                if get_bit(cdp.reasons, 8):
-                    reasons.append(x509.ReasonFlags.aa_compromise)
-
-                reasons = frozenset(reasons)
-
-            if cdp.CRLissuer != self._backend._ffi.NULL:
-                crl_issuer = _build_general_names(self._backend, cdp.CRLissuer)
-
-            # Certificates may have a crl_issuer/reasons and no distribution
-            # point so make sure it's not null.
-            if cdp.distpoint != self._backend._ffi.NULL:
-                # Type 0 is fullName, there is no #define for it in the code.
-                if cdp.distpoint.type == 0:
-                    full_name = _build_general_names(
-                        self._backend, cdp.distpoint.name.fullname
+                if pqualid == x509.OID_CPS_QUALIFIER:
+                    cpsuri = 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 = _decode_user_notice(
+                        backend, pqi.d.usernotice
                     )
-                # OpenSSL code doesn't test for a specific type for
-                # relativename, everything that isn't fullname is considered
-                # relativename.
-                else:
-                    rns = cdp.distpoint.name.relativename
-                    rnum = self._backend._lib.sk_X509_NAME_ENTRY_num(rns)
-                    attributes = []
-                    for i in range(rnum):
-                        rn = self._backend._lib.sk_X509_NAME_ENTRY_value(
-                            rns, i
-                        )
-                        assert rn != self._backend._ffi.NULL
-                        attributes.append(
-                            _build_x509_name_entry(self._backend, rn)
-                        )
+                    qualifiers.append(user_notice)
 
-                    relative_name = x509.Name(attributes)
+        certificate_policies.append(
+            x509.PolicyInformation(oid, qualifiers)
+        )
 
-            dist_points.append(
-                x509.DistributionPoint(
-                    full_name, relative_name, reasons, crl_issuer
-                )
+    return x509.CertificatePolicies(certificate_policies)
+
+
+def _decode_user_notice(backend, un):
+    explicit_text = None
+    notice_reference = None
+
+    if un.exptext != backend._ffi.NULL:
+        explicit_text = _asn1_string_to_utf8(backend, un.exptext)
+
+    if un.noticeref != backend._ffi.NULL:
+        organization = _asn1_string_to_utf8(
+            backend, un.noticeref.organization
+        )
+
+        num = backend._lib.sk_ASN1_INTEGER_num(
+            un.noticeref.noticenos
+        )
+        notice_numbers = []
+        for i in range(num):
+            asn1_int = backend._lib.sk_ASN1_INTEGER_value(
+                un.noticeref.noticenos, i
             )
+            notice_num = _asn1_integer_to_int(
+                backend, asn1_int
+            )
+            notice_numbers.append(notice_num)
 
-        return x509.CRLDistributionPoints(dist_points)
+        notice_reference = x509.NoticeReference(
+            organization, notice_numbers
+        )
+
+    return x509.UserNotice(notice_reference, explicit_text)
+
+
+def _decode_basic_constraints(backend, ext):
+    bc_st = backend._lib.X509V3_EXT_d2i(ext)
+    assert bc_st != backend._ffi.NULL
+    basic_constraints = backend._ffi.cast(
+        "BASIC_CONSTRAINTS *", bc_st
+    )
+    basic_constraints = backend._ffi.gc(
+        basic_constraints, backend._lib.BASIC_CONSTRAINTS_free
+    )
+    # The byte representation of an ASN.1 boolean true is \xff. OpenSSL
+    # chooses to just map this to its ordinal value, so true is 255 and
+    # false is 0.
+    ca = basic_constraints.ca == 255
+    if basic_constraints.pathlen == backend._ffi.NULL:
+        path_length = None
+    else:
+        path_length = _asn1_integer_to_int(
+            backend, basic_constraints.pathlen
+        )
+
+    return x509.BasicConstraints(ca, path_length)
+
+
+def _decode_subject_key_identifier(backend, ext):
+    asn1_string = backend._lib.X509V3_EXT_d2i(ext)
+    assert asn1_string != backend._ffi.NULL
+    asn1_string = backend._ffi.cast(
+        "ASN1_OCTET_STRING *", asn1_string
+    )
+    asn1_string = backend._ffi.gc(
+        asn1_string, backend._lib.ASN1_OCTET_STRING_free
+    )
+    return x509.SubjectKeyIdentifier(
+        backend._ffi.buffer(asn1_string.data, asn1_string.length)[:]
+    )
+
+
+def _decode_authority_key_identifier(backend, ext):
+    akid = backend._lib.X509V3_EXT_d2i(ext)
+    assert akid != backend._ffi.NULL
+    akid = backend._ffi.cast("AUTHORITY_KEYID *", akid)
+    akid = backend._ffi.gc(
+        akid, backend._lib.AUTHORITY_KEYID_free
+    )
+    key_identifier = None
+    authority_cert_issuer = None
+    authority_cert_serial_number = None
+
+    if akid.keyid != backend._ffi.NULL:
+        key_identifier = backend._ffi.buffer(
+            akid.keyid.data, akid.keyid.length
+        )[:]
+
+    if akid.issuer != backend._ffi.NULL:
+        authority_cert_issuer = _decode_general_names(
+            backend, akid.issuer
+        )
+
+    if akid.serial != backend._ffi.NULL:
+        authority_cert_serial_number = _asn1_integer_to_int(
+            backend, akid.serial
+        )
+
+    return x509.AuthorityKeyIdentifier(
+        key_identifier, authority_cert_issuer, authority_cert_serial_number
+    )
+
+
+def _decode_authority_information_access(backend, ext):
+    aia = backend._lib.X509V3_EXT_d2i(ext)
+    assert aia != backend._ffi.NULL
+    aia = backend._ffi.cast(
+        "Cryptography_STACK_OF_ACCESS_DESCRIPTION *", aia
+    )
+    aia = backend._ffi.gc(
+        aia, backend._lib.sk_ACCESS_DESCRIPTION_free
+    )
+    num = backend._lib.sk_ACCESS_DESCRIPTION_num(aia)
+    access_descriptions = []
+    for i in range(num):
+        ad = backend._lib.sk_ACCESS_DESCRIPTION_value(aia, i)
+        assert ad.method != backend._ffi.NULL
+        oid = x509.ObjectIdentifier(_obj2txt(backend, ad.method))
+        assert ad.location != backend._ffi.NULL
+        gn = _decode_general_name(backend, ad.location)
+        access_descriptions.append(x509.AccessDescription(oid, gn))
+
+    return x509.AuthorityInformationAccess(access_descriptions)
+
+
+def _decode_key_usage(backend, ext):
+    bit_string = backend._lib.X509V3_EXT_d2i(ext)
+    assert bit_string != backend._ffi.NULL
+    bit_string = backend._ffi.cast("ASN1_BIT_STRING *", bit_string)
+    bit_string = backend._ffi.gc(
+        bit_string, backend._lib.ASN1_BIT_STRING_free
+    )
+    get_bit = backend._lib.ASN1_BIT_STRING_get_bit
+    digital_signature = get_bit(bit_string, 0) == 1
+    content_commitment = get_bit(bit_string, 1) == 1
+    key_encipherment = get_bit(bit_string, 2) == 1
+    data_encipherment = get_bit(bit_string, 3) == 1
+    key_agreement = get_bit(bit_string, 4) == 1
+    key_cert_sign = get_bit(bit_string, 5) == 1
+    crl_sign = get_bit(bit_string, 6) == 1
+    encipher_only = get_bit(bit_string, 7) == 1
+    decipher_only = get_bit(bit_string, 8) == 1
+    return x509.KeyUsage(
+        digital_signature,
+        content_commitment,
+        key_encipherment,
+        data_encipherment,
+        key_agreement,
+        key_cert_sign,
+        crl_sign,
+        encipher_only,
+        decipher_only
+    )
+
+
+def _decode_subject_alt_name(backend, ext):
+    gns = backend._ffi.cast(
+        "GENERAL_NAMES *", backend._lib.X509V3_EXT_d2i(ext)
+    )
+    assert gns != backend._ffi.NULL
+    gns = backend._ffi.gc(gns, backend._lib.GENERAL_NAMES_free)
+    general_names = _decode_general_names(backend, gns)
+
+    return x509.SubjectAlternativeName(general_names)
+
+
+def _decode_extended_key_usage(backend, ext):
+    sk = backend._ffi.cast(
+        "Cryptography_STACK_OF_ASN1_OBJECT *",
+        backend._lib.X509V3_EXT_d2i(ext)
+    )
+    assert sk != backend._ffi.NULL
+    sk = backend._ffi.gc(sk, backend._lib.sk_ASN1_OBJECT_free)
+    num = backend._lib.sk_ASN1_OBJECT_num(sk)
+    ekus = []
+
+    for i in range(num):
+        obj = backend._lib.sk_ASN1_OBJECT_value(sk, i)
+        assert obj != backend._ffi.NULL
+        oid = x509.ObjectIdentifier(_obj2txt(backend, obj))
+        ekus.append(oid)
+
+    return x509.ExtendedKeyUsage(ekus)
+
+
+def _decode_crl_distribution_points(backend, ext):
+    cdps = backend._ffi.cast(
+        "Cryptography_STACK_OF_DIST_POINT *",
+        backend._lib.X509V3_EXT_d2i(ext)
+    )
+    assert cdps != backend._ffi.NULL
+    cdps = backend._ffi.gc(
+        cdps, backend._lib.sk_DIST_POINT_free)
+    num = backend._lib.sk_DIST_POINT_num(cdps)
+
+    dist_points = []
+    for i in range(num):
+        full_name = None
+        relative_name = None
+        crl_issuer = None
+        reasons = None
+        cdp = backend._lib.sk_DIST_POINT_value(cdps, i)
+        if cdp.reasons != backend._ffi.NULL:
+            # We will check each bit from RFC 5280
+            # ReasonFlags ::= BIT STRING {
+            #      unused                  (0),
+            #      keyCompromise           (1),
+            #      cACompromise            (2),
+            #      affiliationChanged      (3),
+            #      superseded              (4),
+            #      cessationOfOperation    (5),
+            #      certificateHold         (6),
+            #      privilegeWithdrawn      (7),
+            #      aACompromise            (8) }
+            reasons = []
+            get_bit = backend._lib.ASN1_BIT_STRING_get_bit
+            if get_bit(cdp.reasons, 1):
+                reasons.append(x509.ReasonFlags.key_compromise)
+
+            if get_bit(cdp.reasons, 2):
+                reasons.append(x509.ReasonFlags.ca_compromise)
+
+            if get_bit(cdp.reasons, 3):
+                reasons.append(x509.ReasonFlags.affiliation_changed)
+
+            if get_bit(cdp.reasons, 4):
+                reasons.append(x509.ReasonFlags.superseded)
+
+            if get_bit(cdp.reasons, 5):
+                reasons.append(x509.ReasonFlags.cessation_of_operation)
+
+            if get_bit(cdp.reasons, 6):
+                reasons.append(x509.ReasonFlags.certificate_hold)
+
+            if get_bit(cdp.reasons, 7):
+                reasons.append(x509.ReasonFlags.privilege_withdrawn)
+
+            if get_bit(cdp.reasons, 8):
+                reasons.append(x509.ReasonFlags.aa_compromise)
+
+            reasons = frozenset(reasons)
+
+        if cdp.CRLissuer != backend._ffi.NULL:
+            crl_issuer = _decode_general_names(backend, cdp.CRLissuer)
+
+        # Certificates may have a crl_issuer/reasons and no distribution
+        # point so make sure it's not null.
+        if cdp.distpoint != backend._ffi.NULL:
+            # Type 0 is fullName, there is no #define for it in the code.
+            if cdp.distpoint.type == 0:
+                full_name = _decode_general_names(
+                    backend, cdp.distpoint.name.fullname
+                )
+            # OpenSSL code doesn't test for a specific type for
+            # relativename, everything that isn't fullname is considered
+            # relativename.
+            else:
+                rns = cdp.distpoint.name.relativename
+                rnum = backend._lib.sk_X509_NAME_ENTRY_num(rns)
+                attributes = []
+                for i in range(rnum):
+                    rn = backend._lib.sk_X509_NAME_ENTRY_value(
+                        rns, i
+                    )
+                    assert rn != backend._ffi.NULL
+                    attributes.append(
+                        _decode_x509_name_entry(backend, rn)
+                    )
+
+                relative_name = x509.Name(attributes)
+
+        dist_points.append(
+            x509.DistributionPoint(
+                full_name, relative_name, reasons, crl_issuer
+            )
+        )
+
+    return x509.CRLDistributionPoints(dist_points)
 
 
 @utils.register_interface(x509.CertificateSigningRequest)
@@ -632,7 +646,7 @@
     def subject(self):
         subject = self._backend._lib.X509_REQ_get_subject_name(self._x509_req)
         assert subject != self._backend._ffi.NULL
-        return _build_x509_name(self._backend, subject)
+        return _decode_x509_name(self._backend, subject)
 
     @property
     def signature_hash_algorithm(self):