Ejemplo n.º 1
0
 def signature(self):
     sig = self._backend._ffi.new("ASN1_BIT_STRING **")
     self._backend._lib.X509_REQ_get0_signature(
         self._x509_req, sig, self._backend._ffi.NULL
     )
     self._backend.openssl_assert(sig[0] != self._backend._ffi.NULL)
     return _asn1_string_to_bytes(self._backend, sig[0])
Ejemplo n.º 2
0
def _issuer_key_hash(backend, cert_id):
    key_hash = backend._ffi.new("ASN1_OCTET_STRING **")
    res = backend._lib.OCSP_id_get0_info(backend._ffi.NULL, backend._ffi.NULL,
                                         key_hash, backend._ffi.NULL, cert_id)
    backend.openssl_assert(res == 1)
    backend.openssl_assert(key_hash[0] != backend._ffi.NULL)
    return _asn1_string_to_bytes(backend, key_hash[0])
Ejemplo n.º 3
0
    def get_attribute_for_oid(self, oid: x509.ObjectIdentifier) -> bytes:
        obj = _txt2obj_gc(self._backend, oid.dotted_string)
        pos = self._backend._lib.X509_REQ_get_attr_by_OBJ(
            self._x509_req, obj, -1)
        if pos == -1:
            raise x509.AttributeNotFound(
                "No {} attribute was found".format(oid), oid)

        attr = self._backend._lib.X509_REQ_get_attr(self._x509_req, pos)
        self._backend.openssl_assert(attr != self._backend._ffi.NULL)
        # We don't support multiple valued attributes for now.
        self._backend.openssl_assert(
            self._backend._lib.X509_ATTRIBUTE_count(attr) == 1)
        asn1_type = self._backend._lib.X509_ATTRIBUTE_get0_type(attr, 0)
        self._backend.openssl_assert(asn1_type != self._backend._ffi.NULL)
        # We need this to ensure that our C type cast is safe.
        # Also this should always be a sane string type, but we'll see if
        # that is true in the real world...
        if asn1_type.type not in (
                _ASN1Type.UTF8String.value,
                _ASN1Type.PrintableString.value,
                _ASN1Type.IA5String.value,
        ):
            raise ValueError("OID {} has a disallowed ASN.1 type: {}".format(
                oid, asn1_type.type))

        data = self._backend._lib.X509_ATTRIBUTE_get0_data(
            attr, 0, asn1_type.type, self._backend._ffi.NULL)
        self._backend.openssl_assert(data != self._backend._ffi.NULL)
        # This cast is safe iff we assert on the type above to ensure
        # that it is always a type of ASN1_STRING
        data = self._backend._ffi.cast("ASN1_STRING *", data)
        return _asn1_string_to_bytes(self._backend, data)
Ejemplo n.º 4
0
 def signature(self):
     sig = self._backend._ffi.new("ASN1_BIT_STRING **")
     self._backend._lib.X509_REQ_get0_signature(
         self._x509_req, sig, self._backend._ffi.NULL
     )
     self._backend.openssl_assert(sig[0] != self._backend._ffi.NULL)
     return _asn1_string_to_bytes(self._backend, sig[0])
Ejemplo n.º 5
0
 def responder_key_hash(self) -> typing.Optional[bytes]:
     self._requires_successful_response()
     _, asn1_string = self._responder_key_name()
     if asn1_string == self._backend._ffi.NULL:
         return None
     else:
         return _asn1_string_to_bytes(self._backend, asn1_string)
Ejemplo n.º 6
0
def _issuer_name_hash(backend, cert_id):
    name_hash = backend._ffi.new("ASN1_OCTET_STRING **")
    res = backend._lib.OCSP_id_get0_info(
        name_hash, backend._ffi.NULL,
        backend._ffi.NULL, backend._ffi.NULL, cert_id
    )
    backend.openssl_assert(res == 1)
    backend.openssl_assert(name_hash[0] != backend._ffi.NULL)
    return _asn1_string_to_bytes(backend, name_hash[0])
Ejemplo n.º 7
0
 def issuer_name_hash(self):
     name_hash = self._backend._ffi.new("ASN1_OCTET_STRING **")
     res = self._backend._lib.OCSP_id_get0_info(name_hash,
                                                self._backend._ffi.NULL,
                                                self._backend._ffi.NULL,
                                                self._backend._ffi.NULL,
                                                self._cert_id)
     self._backend.openssl_assert(res == 1)
     self._backend.openssl_assert(name_hash[0] != self._backend._ffi.NULL)
     return _asn1_string_to_bytes(self._backend, name_hash[0])
Ejemplo n.º 8
0
def _patched_asn1_string_to_utf8(backend, asn1_string):
    buf = backend._ffi.new("unsigned char **")
    res = backend._lib.ASN1_STRING_to_UTF8(buf, asn1_string)
    if res == -1:
        # "Unsupported ASN1 string type. Type: {0}".format(asn1_string.type)
        # der = backend._lib.ASN1_STRING_data(asn1_string)
        # print(der)
        der = _asn1_string_to_bytes(backend, asn1_string)
        return der.hex()

    backend.openssl_assert(buf[0] != backend._ffi.NULL)
    buf = backend._ffi.gc(buf,
                          lambda buffer: backend._lib.OPENSSL_free(buffer[0]))

    try:
        return backend._ffi.buffer(buf[0], res)[:].decode('utf8')
    except UnicodeDecodeError:
        return backend._ffi.buffer(buf[0], res)[:].decode('latin1')
Ejemplo n.º 9
0
def _xep_patched_parse(self, backend, x509_obj):
    extensions = []
    seen_oids = set()
    for i in range(self.ext_count(backend, x509_obj)):
        ext = self.get_ext(backend, x509_obj, i)
        backend.openssl_assert(ext != backend._ffi.NULL)
        crit = backend._lib.X509_EXTENSION_get_critical(ext)
        critical = crit == 1
        oid = x509.ObjectIdentifier(
            _obj2txt(backend, backend._lib.X509_EXTENSION_get_object(ext)))

        # This OID is only supported in OpenSSL 1.1.0+ but we want
        # to support it in all versions of OpenSSL so we decode it
        # ourselves.
        if oid == ExtensionOID.TLS_FEATURE:
            data = backend._lib.X509_EXTENSION_get_data(ext)
            parsed = _Integers.load(_asn1_string_to_bytes(backend, data))
            value = x509.TLSFeature(
                [_TLS_FEATURE_TYPE_TO_ENUM[x.native] for x in parsed])
            extensions.append(x509.Extension(oid, critical, value))
            seen_oids.add(oid)
            continue

        try:
            handler = self.handlers[oid]
        except KeyError:
            # Dump the DER payload into an UnrecognizedExtension object
            der = dump_der(ext, backend)
            unrecognized = x509.UnrecognizedExtension(oid, der)
            extensions.append(x509.Extension(oid, critical, unrecognized))
        else:
            ext_data = backend._lib.X509V3_EXT_d2i(ext)
            if ext_data == backend._ffi.NULL:
                backend._consume_errors()
                der = dump_der(ext, backend)
                unrecognized = x509.UnrecognizedExtension(oid, der)
                extensions.append(x509.Extension(oid, critical, unrecognized))
            else:
                value = handler(backend, ext_data)
                extensions.append(x509.Extension(oid, critical, value))

        seen_oids.add(oid)

    return x509.Extensions(extensions)
Ejemplo n.º 10
0
 def responder_key_hash(self):
     _, asn1_string = self._responder_key_name()
     if asn1_string == self._backend._ffi.NULL:
         return None
     else:
         return _asn1_string_to_bytes(self._backend, asn1_string)
Ejemplo n.º 11
0
 def signature(self):
     sig = self._backend._lib.OCSP_resp_get0_signature(self._basic)
     self._backend.openssl_assert(sig != self._backend._ffi.NULL)
     return _asn1_string_to_bytes(self._backend, sig)
Ejemplo n.º 12
0
 def signature(self) -> bytes:
     self._requires_successful_response()
     sig = self._backend._lib.OCSP_resp_get0_signature(self._basic)
     self._backend.openssl_assert(sig != self._backend._ffi.NULL)
     return _asn1_string_to_bytes(self._backend, sig)
Ejemplo n.º 13
0
 def responder_key_hash(self):
     _, asn1_string = self._responder_key_name()
     if asn1_string == self._backend._ffi.NULL:
         return None
     else:
         return _asn1_string_to_bytes(self._backend, asn1_string)
Ejemplo n.º 14
0
 def signature(self):
     sig = self._backend._lib.OCSP_resp_get0_signature(self._basic)
     self._backend.openssl_assert(sig != self._backend._ffi.NULL)
     return _asn1_string_to_bytes(self._backend, sig)
Ejemplo n.º 15
0
def _patched_decode_general_name(backend, gn):
    if gn.type == backend._lib.GEN_DNS:
        # Convert to bytes and then decode to utf8. We don't use
        # asn1_string_to_utf8 here because it doesn't properly convert
        # utf8 from ia5strings.
        name_bytes = _asn1_string_to_bytes(backend, gn.d.dNSName)
        try:
            data = name_bytes.decode("utf8")
        except UnicodeDecodeError:
            data = name_bytes.hex()
        # We don't use the constructor for DNSName so we can bypass validation
        # This allows us to create DNSName objects that have unicode chars
        # when a certificate (against the RFC) contains them.
        return x509.DNSName._init_without_validation(data)
    elif gn.type == backend._lib.GEN_URI:
        # Convert to bytes and then decode to utf8. We don't use
        # asn1_string_to_utf8 here because it doesn't properly convert
        # utf8 from ia5strings.
        name_bytes = _asn1_string_to_bytes(backend,
                                           gn.d.uniformResourceIdentifier)
        try:
            data = name_bytes.decode("utf8")
        except UnicodeDecodeError:
            # TODO: we could try utf16-be
            data = name_bytes.hex()
        # We don't use the constructor for URI so we can bypass validation
        # This allows us to create URI objects that have unicode chars
        # when a certificate (against the RFC) contains them.
        return x509.UniformResourceIdentifier._init_without_validation(data)
    elif gn.type == backend._lib.GEN_RID:
        oid = _obj2txt(backend, gn.d.registeredID)
        return x509.RegisteredID(x509.ObjectIdentifier(oid))
    elif gn.type == backend._lib.GEN_IPADD:
        data = _asn1_string_to_bytes(backend, gn.d.iPAddress)
        data_len = len(data)
        if data_len == 8 or data_len == 32:
            # This is an IPv4 or IPv6 Network and not a single IP. This
            # type of data appears in Name Constraints. Unfortunately,
            # ipaddress doesn't support packed bytes + netmask. Additionally,
            # IPv6Network can only handle CIDR rather than the full 16 byte
            # netmask. To handle this we convert the netmask to integer, then
            # find the first 0 bit, which will be the prefix. If another 1
            # bit is present after that the netmask is invalid.
            base = ipaddress.ip_address(data[:data_len // 2])
            netmask = ipaddress.ip_address(data[data_len // 2:])
            bits = bin(int(netmask))[2:]
            prefix = bits.find('0')
            # If no 0 bits are found it is a /32 or /128
            if prefix == -1:
                prefix = len(bits)

            if "1" in bits[prefix:]:
                raise ValueError("Invalid netmask")

            ip = ipaddress.ip_network(base.exploded + u"/{0}".format(prefix))
        else:
            try:
                ip = ipaddress.ip_address(data)
            except ValueError:
                ip = data

        return x509.IPAddress(ip)
    elif gn.type == backend._lib.GEN_DIRNAME:
        return x509.DirectoryName(
            _decode_x509_name(backend, gn.d.directoryName))
    elif gn.type == backend._lib.GEN_EMAIL:
        # Convert to bytes and then decode to utf8. We don't use
        # asn1_string_to_utf8 here because it doesn't properly convert
        # utf8 from ia5strings.
        data = _asn1_string_to_bytes(backend, gn.d.rfc822Name).decode("utf8")
        # We don't use the constructor for RFC822Name so we can bypass
        # validation. This allows us to create RFC822Name objects that have
        # unicode chars when a certificate (against the RFC) contains them.
        return x509.RFC822Name._init_without_validation(data)
    elif gn.type == backend._lib.GEN_OTHERNAME:
        type_id = _obj2txt(backend, gn.d.otherName.type_id)
        value = _asn1_to_der(backend, gn.d.otherName.value)
        return x509.OtherName(x509.ObjectIdentifier(type_id), value)
    else:
        # x400Address or ediPartyName
        raise x509.UnsupportedGeneralNameType(
            "{0} is not a supported type".format(
                x509._GENERAL_NAMES.get(gn.type, gn.type)), gn.type)
Ejemplo n.º 16
0
 def signature(self):
     return _asn1_string_to_bytes(self._backend, self._x509_req.signature)