Пример #1
0
    def 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)))
            if oid in seen_oids:
                raise x509.DuplicateExtension(
                    "Duplicate {} extension found".format(oid), oid)

            # These OIDs are only supported in OpenSSL 1.1.0+ but we want
            # to support them in all versions of OpenSSL so we decode them
            # ourselves.
            if oid == ExtensionOID.TLS_FEATURE:
                # The extension contents are a SEQUENCE OF INTEGERs.
                data = backend._lib.X509_EXTENSION_get_data(ext)
                data_bytes = _asn1_string_to_bytes(backend, data)
                features = DERReader(data_bytes).read_single_element(SEQUENCE)
                parsed = []
                while not features.is_empty():
                    parsed.append(features.read_element(INTEGER).as_integer())
                # Map the features to their enum value.
                value = x509.TLSFeature(
                    [_TLS_FEATURE_TYPE_TO_ENUM[x] for x in parsed])
                extensions.append(x509.Extension(oid, critical, value))
                seen_oids.add(oid)
                continue
            elif oid == ExtensionOID.PRECERT_POISON:
                data = backend._lib.X509_EXTENSION_get_data(ext)
                # The contents of the extension must be an ASN.1 NULL.
                reader = DERReader(_asn1_string_to_bytes(backend, data))
                reader.read_single_element(NULL).check_empty()
                extensions.append(
                    x509.Extension(oid, critical, x509.PrecertPoison()))
                seen_oids.add(oid)
                continue

            try:
                handler = self.handlers[oid]
            except KeyError:
                # Dump the DER payload into an UnrecognizedExtension object
                data = backend._lib.X509_EXTENSION_get_data(ext)
                backend.openssl_assert(data != backend._ffi.NULL)
                der = backend._ffi.buffer(data.data, data.length)[:]
                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()
                    raise ValueError(
                        "The {} extension is invalid and can't be "
                        "parsed".format(oid))

                value = handler(backend, ext_data)
                extensions.append(x509.Extension(oid, critical, value))

            seen_oids.add(oid)

        return x509.Extensions(extensions)
Пример #2
0
    def parse(self, x509_obj):
        extensions: typing.List[x509.Extension[x509.ExtensionType]] = []
        seen_oids = set()
        for i in range(self.ext_count(x509_obj)):
            ext = self.get_ext(x509_obj, i)
            self._backend.openssl_assert(ext != self._backend._ffi.NULL)
            crit = self._backend._lib.X509_EXTENSION_get_critical(ext)
            critical = crit == 1
            oid = x509.ObjectIdentifier(
                _obj2txt(
                    self._backend,
                    self._backend._lib.X509_EXTENSION_get_object(ext),
                ))
            if oid in seen_oids:
                raise x509.DuplicateExtension(
                    "Duplicate {} extension found".format(oid), oid)

            if self.rust_callback is not None:
                oid_ptr = self._backend._lib.X509_EXTENSION_get_object(ext)
                oid_der_bytes = self._backend._ffi.buffer(
                    self._backend._lib.Cryptography_OBJ_get0_data(oid_ptr),
                    self._backend._lib.Cryptography_OBJ_length(oid_ptr),
                )[:]
                data = self._backend._lib.X509_EXTENSION_get_data(ext)
                data_bytes = _asn1_string_to_bytes(self._backend, data)
                ext = self.rust_callback(oid_der_bytes, data_bytes)
                extensions.append(x509.Extension(oid, critical, ext))
                seen_oids.add(oid)
                continue

            # These OIDs are only supported in OpenSSL 1.1.0+ but we want
            # to support them in all versions of OpenSSL so we decode them
            # ourselves.
            if oid == ExtensionOID.TLS_FEATURE:
                # The extension contents are a SEQUENCE OF INTEGERs.
                data = self._backend._lib.X509_EXTENSION_get_data(ext)
                data_bytes = _asn1_string_to_bytes(self._backend, data)
                tls_feature = asn1.parse_tls_feature(data_bytes)

                extensions.append(x509.Extension(oid, critical, tls_feature))
                seen_oids.add(oid)
                continue
            elif oid == ExtensionOID.PRECERT_POISON:
                data = self._backend._lib.X509_EXTENSION_get_data(ext)
                data_bytes = _asn1_string_to_bytes(self._backend, data)
                precert_poison = asn1.parse_precert_poison(data_bytes)

                extensions.append(x509.Extension(oid, critical,
                                                 precert_poison))
                seen_oids.add(oid)
                continue

            try:
                handler = self.handlers[oid]
            except KeyError:
                # Dump the DER payload into an UnrecognizedExtension object
                data = self._backend._lib.X509_EXTENSION_get_data(ext)
                self._backend.openssl_assert(data != self._backend._ffi.NULL)
                der = self._backend._ffi.buffer(data.data, data.length)[:]
                unrecognized = x509.UnrecognizedExtension(oid, der)
                extensions.append(x509.Extension(oid, critical, unrecognized))
            else:
                ext_data = self._backend._lib.X509V3_EXT_d2i(ext)
                if ext_data == self._backend._ffi.NULL:
                    self._backend._consume_errors()
                    raise ValueError(
                        "The {} extension is invalid and can't be "
                        "parsed".format(oid))

                value = handler(self._backend, ext_data)
                extensions.append(x509.Extension(oid, critical, value))

            seen_oids.add(oid)

        return x509.Extensions(extensions)
Пример #3
0
    def 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))
            )
            if oid in seen_oids:
                raise x509.DuplicateExtension(
                    "Duplicate {0} extension found".format(oid), oid
                )

            # These OIDs are only supported in OpenSSL 1.1.0+ but we want
            # to support them in all versions of OpenSSL so we decode them
            # 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
            elif oid == ExtensionOID.PRECERT_POISON:
                data = backend._lib.X509_EXTENSION_get_data(ext)
                parsed = asn1crypto.core.Null.load(
                    _asn1_string_to_bytes(backend, data)
                )
                assert parsed == asn1crypto.core.Null()
                extensions.append(x509.Extension(
                    oid, critical, x509.PrecertPoison()
                ))
                seen_oids.add(oid)
                continue

            try:
                handler = self.handlers[oid]
            except KeyError:
                # Dump the DER payload into an UnrecognizedExtension object
                data = backend._lib.X509_EXTENSION_get_data(ext)
                backend.openssl_assert(data != backend._ffi.NULL)
                der = backend._ffi.buffer(data.data, data.length)[:]
                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()
                    raise ValueError(
                        "The {0} extension is invalid and can't be "
                        "parsed".format(oid)
                    )

                value = handler(backend, ext_data)
                extensions.append(x509.Extension(oid, critical, value))

            seen_oids.add(oid)

        return x509.Extensions(extensions)
Пример #4
0
def generate_x509_certificate(signing_key, key, subject, issuer, serial,
                              valid_after, valid_before, ca, ca_path_len,
                              purposes, user_principals, host_principals,
                              hash_alg, comment):
    """Generate a new X.509 certificate"""

    builder = x509.CertificateBuilder()

    subject = X509Name(subject)
    issuer = X509Name(issuer) if issuer else subject
    self_signed = subject == issuer

    builder = builder.subject_name(subject)
    builder = builder.issuer_name(issuer)

    if serial is None:
        serial = x509.random_serial_number()

    builder = builder.serial_number(serial)

    builder = builder.not_valid_before(_to_generalized_time(valid_after))
    builder = builder.not_valid_after(_to_generalized_time(valid_before))

    builder = builder.public_key(key.pyca_key)

    if ca:
        basic_constraints = x509.BasicConstraints(ca=True,
                                                  path_length=ca_path_len)
        key_usage = x509.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=False,
                                  decipher_only=False)
    else:
        basic_constraints = x509.BasicConstraints(ca=False, path_length=None)
        key_usage = x509.KeyUsage(digital_signature=True,
                                  content_commitment=False,
                                  key_encipherment=True,
                                  data_encipherment=False,
                                  key_agreement=True, key_cert_sign=False,
                                  crl_sign=False, encipher_only=False,
                                  decipher_only=False)

    builder = builder.add_extension(basic_constraints, critical=True)

    if ca or not self_signed:
        builder = builder.add_extension(key_usage, critical=True)

    purpose_oids = _to_purpose_oids(purposes)

    if purpose_oids:
        builder = builder.add_extension(x509.ExtendedKeyUsage(purpose_oids),
                                        critical=False)

    sans = _encode_user_principals(user_principals) + \
           _encode_host_principals(host_principals)

    if sans:
        builder = builder.add_extension(x509.SubjectAlternativeName(sans),
                                        critical=False)

    if comment:
        if isinstance(comment, str):
            comment = comment.encode('utf-8')

        comment = der_encode(IA5String(comment))
        builder = builder.add_extension(
            x509.UnrecognizedExtension(_nscomment_oid, comment), critical=False)

    try:
        hash_alg = _hashes[hash_alg]()
    except KeyError:
        raise ValueError('Unknown hash algorithm') from None

    cert = builder.sign(signing_key.pyca_key, hash_alg, default_backend())
    data = cert.public_bytes(Encoding.DER)

    return X509Certificate(cert, data)
Пример #5
0
  def 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))        
      )
      if oid in seen_oids:
        raise x509.DuplicateExtension(
          "Duplicate {} extension found".format(oid), oid        
        )

      if oid == ExtensionOID.TLS_FEATURE:
        data = backend._lib.X509_EXTENSION_get_data(ext)
        data_bytes = _asn1_string_to_bytes(backend, data)
        features = DERReader(data_bytes).read_single_element(SEQUENCE)
        parsed = []
        while not features.is_empty():
          parsed.append(features.read_element(INTEGER).as_integer())

        value = x509.TLSFeature(
          [_TLS_FEATURE_TYPE_TO_ENUM[x] for x in parsed]        
        )
        extensions.append(x509.Extension(oid, critical, value))
        seen_oids.add(oid)
        continue
      elif oid == ExtensionOID.PRECERT_POSION:
        data = backend._lib.X509_EXTENSION_get_data(ext)
        reader = DERReader(_asn1_string_to_bytes(backend, data))
        reader.read_single_element(NULL).check_empty()
        extensions.append(x509.Extension(
          oid, critical, x509.PrecertPoison()    
        ))
        seen_oids.add(oid)
        continue
      elif oid == ExtensionOID.PRECERT_POISON:
        data = backend._lib.X509_EXTENSION_get_data(ext)
        reader = DERReader(_asn1_string_to_bytes(backend, data))
        reader.read_single_element(NULL).check_empty()
        extensions.append(x509.Extension(
          oid, critical, x509.PrecertPoison()    
        ))
        seen_oids.add(oid)
        continue

      try:
        handler = self.handlers[oid]
      except KeyError:
        data = backend._lib.X509_EXTENSION_get_data(ext)
        backend.openssl_assert(data != backend._ffi.NULL)
        der = backend._ffi.buffer(data.data, data.length)[:]
        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()
          raise ValueError(
            "The {} extension is invalid and can't be "
            "parsed".format(oid)
          )

        value = handler(backend, ext_data)
        extensions.append(x509.Extension(oid, critical, value))

      seen_oids.add(oid)

    return x509.Extensions(extenions)