def test_add_extension_checks_for_duplicates(self):
        builder = x509.RevokedCertificateBuilder().add_extension(
            x509.CRLReason(x509.ReasonFlags.ca_compromise), False)

        with pytest.raises(ValueError):
            builder.add_extension(
                x509.CRLReason(x509.ReasonFlags.ca_compromise), False)
Exemple #2
0
    def test_add_multiple_extensions(self, backend):
        serial_number = 333
        revocation_date = datetime.datetime(2002, 1, 1, 12, 1)
        invalidity_date = x509.InvalidityDate(
            datetime.datetime(2015, 1, 1, 0, 0)
        )
        certificate_issuer = x509.CertificateIssuer(
            [x509.DNSName(u"cryptography.io")]
        )
        crl_reason = x509.CRLReason(x509.ReasonFlags.aa_compromise)
        builder = (
            x509.RevokedCertificateBuilder()
            .serial_number(serial_number)
            .revocation_date(revocation_date)
            .add_extension(invalidity_date, True)
            .add_extension(crl_reason, True)
            .add_extension(certificate_issuer, True)
        )

        revoked_certificate = builder.build(backend)
        assert len(revoked_certificate.extensions) == 3
        for ext_data in [invalidity_date, certificate_issuer, crl_reason]:
            ext = revoked_certificate.extensions.get_extension_for_class(
                type(ext_data)
            )
            assert ext.critical is True
            assert ext.value == ext_data
Exemple #3
0
def create_crl(crl_path, ca_key, ca_cert):
    now = datetime.utcnow()

    builder = (
        x509.CertificateRevocationListBuilder()
        .last_update(now)
        .next_update(now + timedelta(days=1))
        .issuer_name(ca_cert.subject)
    )

    for i in [3,4,5]:
        cert = (
            x509.RevokedCertificateBuilder()
            .revocation_date(now)
            .serial_number(i)
            .add_extension(
                x509.CRLReason(x509.ReasonFlags.key_compromise),
                critical=False)
            .build(default_backend())
        )
        builder = builder.add_revoked_certificate(cert)

    cert = builder.sign(
        private_key=ca_key,
        algorithm=hashes.SHA256(),
        backend=default_backend())

    write_public(cert, crl_path)
Exemple #4
0
 def test_single_extensions(self, backend):
     resp = _load_data(
         os.path.join("x509", "ocsp", "resp-single-extension-reason.der"),
         ocsp.load_der_ocsp_response,
     )
     assert len(resp.single_extensions) == 1
     ext = resp.single_extensions[0]
     assert ext.oid == x509.CRLReason.oid
     assert ext.value == x509.CRLReason(x509.ReasonFlags.unspecified)
Exemple #5
0
def _decode_crl_reason(backend, enum):
    enum = backend._ffi.cast("ASN1_ENUMERATED *", enum)
    enum = backend._ffi.gc(enum, backend._lib.ASN1_ENUMERATED_free)
    code = backend._lib.ASN1_ENUMERATED_get(enum)

    try:
        return x509.CRLReason(_CRL_ENTRY_REASON_CODE_TO_ENUM[code])
    except KeyError:
        raise ValueError("Unsupported reason code: {}".format(code))
Exemple #6
0
    def _generate_crl(self):
        backend = default_backend()
        crl = CertificateRevocationListBuilder()

        try:
            crl = crl.issuer_name(
                Name([
                    NameAttribute(cryptography_name_to_oid(entry[0]),
                                  to_text(entry[1])) for entry in self.issuer
                ]))
        except ValueError as e:
            raise CRLError(e)

        crl = crl.last_update(self.last_update)
        crl = crl.next_update(self.next_update)

        if self.update and self.crl:
            new_entries = set([
                self._compress_entry(entry)
                for entry in self.revoked_certificates
            ])
            for entry in self.crl:
                decoded_entry = self._compress_entry(
                    cryptography_decode_revoked_certificate(entry))
                if decoded_entry not in new_entries:
                    crl = crl.add_revoked_certificate(entry)
        for entry in self.revoked_certificates:
            revoked_cert = RevokedCertificateBuilder()
            revoked_cert = revoked_cert.serial_number(entry['serial_number'])
            revoked_cert = revoked_cert.revocation_date(
                entry['revocation_date'])
            if entry['issuer'] is not None:
                revoked_cert = revoked_cert.add_extension(
                    x509.CertificateIssuer([
                        cryptography_get_name(name, 'issuer')
                        for name in entry['issuer']
                    ]), entry['issuer_critical'])
            if entry['reason'] is not None:
                revoked_cert = revoked_cert.add_extension(
                    x509.CRLReason(entry['reason']), entry['reason_critical'])
            if entry['invalidity_date'] is not None:
                revoked_cert = revoked_cert.add_extension(
                    x509.InvalidityDate(entry['invalidity_date']),
                    entry['invalidity_date_critical'])
            crl = crl.add_revoked_certificate(revoked_cert.build(backend))

        self.crl = crl.sign(self.privatekey, self.digest, backend=backend)
        if self.format == 'pem':
            return self.crl.public_bytes(Encoding.PEM)
        else:
            return self.crl.public_bytes(Encoding.DER)
Exemple #7
0
    def get_revocation(self):
        """Get a crypto.Revoked object or None if the cert is not revoked."""

        if self.revoked is False:
            raise ValueError('Certificate is not revoked.')

        revoked_cert = x509.RevokedCertificateBuilder().serial_number(
            self.x509.serial).revocation_date(self.revoked_date)

        if self.revoked_reason:
            reason_flag = getattr(x509.ReasonFlags, self.revoked_reason)
            revoked_cert = revoked_cert.add_extension(
                x509.CRLReason(reason_flag), critical=False)

        return revoked_cert.build(default_backend())
Exemple #8
0
    def _upki_generate_crl(self, params):
        self.output('Start CRL generation')
        now = datetime.datetime.utcnow()
        try:
            builder = (
                x509.CertificateRevocationListBuilder()
                .issuer_name(self._ca['cert'].issuer)
                .last_update(now)
                .next_update(now + datetime.timedelta(days=3))
            )
        except Exception as err:
            raise Exception('Unable to build CRL: {e}'.format(e=err))

        for entry in self._storage.get_revoked():
            try:
                revoked_cert = (
                    x509.RevokedCertificateBuilder()
                    .serial_number(entry['Serial'])
                    .revocation_date(datetime.datetime.strptime(entry['Revoke_Date'],'%Y%m%d%H%M%SZ'))
                    .add_extension(x509.CRLReason(x509.ReasonFlags.cessation_of_operation), critical=False)
                    .build(self._backend)
                )
            except Exception as err:
                self.output('Unable to build CRL entry for {d}: {e}'.format(d=entry['DN'], e=err), level='ERROR')
                continue

            try:
                builder = builder.add_revoked_certificate(revoked_cert)
            except Exception as err:
                self.output('Unable to add CRL entry for {d}: {e}'.format(d=entry['DN'], e=err), level='ERROR')
                continue
        
        try:
            crl = builder.sign(private_key=self._ca['key'], algorithm=hashes.SHA256(), backend=self._backend)
        except Exception as err:
            raise Exception('Unable to sign CSR: {e}'.format(e=err))

        try:
            crl_pem = crl.public_bytes(serialization.Encoding.PEM)
            self._storage.store_crl(crl_pem)
        except Exception as err:
            raise Exception(err)

        return {'state': 'OK'}
Exemple #9
0
    def test_sign_with_revoked_certificates(self, backend):
        private_key = RSA_KEY_2048.private_key(backend)
        last_update = datetime.datetime(2002, 1, 1, 12, 1)
        next_update = datetime.datetime(2030, 1, 1, 12, 1)
        invalidity_date = x509.InvalidityDate(
            datetime.datetime(2002, 1, 1, 0, 0))
        revoked_cert0 = (
            x509.RevokedCertificateBuilder().serial_number(38).revocation_date(
                datetime.datetime(2011, 1, 1, 1, 1)).build(backend))
        revoked_cert1 = (
            x509.RevokedCertificateBuilder().serial_number(2).revocation_date(
                datetime.datetime(2012, 1, 1, 1, 1)).add_extension(
                    invalidity_date, False).add_extension(
                        x509.CRLReason(x509.ReasonFlags.ca_compromise),
                        False).build(backend))
        ci = x509.CertificateIssuer([x509.DNSName("cryptography.io")])
        revoked_cert2 = (
            x509.RevokedCertificateBuilder().serial_number(40).revocation_date(
                datetime.datetime(2011, 1, 1, 1,
                                  1)).add_extension(ci, False).build(backend))
        builder = (
            x509.CertificateRevocationListBuilder().issuer_name(
                x509.Name([
                    x509.NameAttribute(NameOID.COMMON_NAME,
                                       "cryptography.io CA")
                ])).last_update(last_update).next_update(next_update).
            add_revoked_certificate(revoked_cert0).add_revoked_certificate(
                revoked_cert1).add_revoked_certificate(revoked_cert2))

        crl = builder.sign(private_key, hashes.SHA256(), backend)
        assert len(crl) == 3
        assert crl.last_update == last_update
        assert crl.next_update == next_update
        assert crl[0].serial_number == revoked_cert0.serial_number
        assert crl[0].revocation_date == revoked_cert0.revocation_date
        assert len(crl[0].extensions) == 0
        assert crl[1].serial_number == revoked_cert1.serial_number
        assert crl[1].revocation_date == revoked_cert1.revocation_date
        assert len(crl[1].extensions) == 2
        ext = crl[1].extensions.get_extension_for_class(x509.InvalidityDate)
        assert ext.critical is False
        assert ext.value == invalidity_date
        assert (crl[2].extensions.get_extension_for_class(
            x509.CertificateIssuer).value == ci)
Exemple #10
0
    def get_revocation(self):
        if self.revoked is False:
            raise ValueError('Certificate is not revoked.')

        revoked_cert = x509.RevokedCertificateBuilder().serial_number(
            self.x509.serial_number).revocation_date(self.revoked_date)

        reason = self.get_revocation_reason()
        if reason != x509.ReasonFlags.unspecified:
            # RFC 5270, 5.3.1: "reason code CRL entry extension SHOULD be absent instead of using the
            # unspecified (0) reasonCode value"
            revoked_cert = revoked_cert.add_extension(x509.CRLReason(reason), critical=False)

        compromised = self.get_compromised_time()
        if compromised:
            # RFC 5280, 5.3.2 says that this extension MUST be non-critical
            revoked_cert = revoked_cert.add_extension(x509.InvalidityDate(compromised), critical=False)

        return revoked_cert.build(default_backend())
class TestRevokedCertificateBuilder(object):
    def test_serial_number_must_be_integer(self):
        with pytest.raises(TypeError):
            x509.RevokedCertificateBuilder().serial_number("notanx509name")

    def test_serial_number_must_be_non_negative(self):
        with pytest.raises(ValueError):
            x509.RevokedCertificateBuilder().serial_number(-1)

    def test_serial_number_must_be_positive(self):
        with pytest.raises(ValueError):
            x509.RevokedCertificateBuilder().serial_number(0)

    @pytest.mark.requires_backend_interface(interface=X509Backend)
    def test_minimal_serial_number(self, backend):
        revocation_date = datetime.datetime(2002, 1, 1, 12, 1)
        builder = x509.RevokedCertificateBuilder().serial_number(
            1).revocation_date(revocation_date)

        revoked_certificate = builder.build(backend)
        assert revoked_certificate.serial_number == 1

    @pytest.mark.requires_backend_interface(interface=X509Backend)
    def test_biggest_serial_number(self, backend):
        revocation_date = datetime.datetime(2002, 1, 1, 12, 1)
        builder = x509.RevokedCertificateBuilder().serial_number(
            (1 << 159) - 1).revocation_date(revocation_date)

        revoked_certificate = builder.build(backend)
        assert revoked_certificate.serial_number == (1 << 159) - 1

    def test_serial_number_must_be_less_than_160_bits_long(self):
        with pytest.raises(ValueError):
            x509.RevokedCertificateBuilder().serial_number(1 << 159)

    def test_set_serial_number_twice(self):
        builder = x509.RevokedCertificateBuilder().serial_number(3)
        with pytest.raises(ValueError):
            builder.serial_number(4)

    def test_revocation_date_invalid(self):
        with pytest.raises(TypeError):
            x509.RevokedCertificateBuilder().revocation_date("notadatetime")

    def test_revocation_date_before_unix_epoch(self):
        with pytest.raises(ValueError):
            x509.RevokedCertificateBuilder().revocation_date(
                datetime.datetime(1960, 8, 10))

    def test_set_revocation_date_twice(self):
        builder = x509.RevokedCertificateBuilder().revocation_date(
            datetime.datetime(2002, 1, 1, 12, 1))
        with pytest.raises(ValueError):
            builder.revocation_date(datetime.datetime(2002, 1, 1, 12, 1))

    def test_add_extension_checks_for_duplicates(self):
        builder = x509.RevokedCertificateBuilder().add_extension(
            x509.CRLReason(x509.ReasonFlags.ca_compromise), False)

        with pytest.raises(ValueError):
            builder.add_extension(
                x509.CRLReason(x509.ReasonFlags.ca_compromise), False)

    def test_add_invalid_extension(self):
        with pytest.raises(TypeError):
            x509.RevokedCertificateBuilder().add_extension(
                "notanextension", False)

    @pytest.mark.requires_backend_interface(interface=X509Backend)
    def test_no_serial_number(self, backend):
        builder = x509.RevokedCertificateBuilder().revocation_date(
            datetime.datetime(2002, 1, 1, 12, 1))

        with pytest.raises(ValueError):
            builder.build(backend)

    @pytest.mark.requires_backend_interface(interface=X509Backend)
    def test_no_revocation_date(self, backend):
        builder = x509.RevokedCertificateBuilder().serial_number(3)

        with pytest.raises(ValueError):
            builder.build(backend)

    @pytest.mark.requires_backend_interface(interface=X509Backend)
    def test_create_revoked(self, backend):
        serial_number = 333
        revocation_date = datetime.datetime(2002, 1, 1, 12, 1)
        builder = x509.RevokedCertificateBuilder().serial_number(
            serial_number).revocation_date(revocation_date)

        revoked_certificate = builder.build(backend)
        assert revoked_certificate.serial_number == serial_number
        assert revoked_certificate.revocation_date == revocation_date
        assert len(revoked_certificate.extensions) == 0

    @pytest.mark.parametrize("extension", [
        x509.InvalidityDate(datetime.datetime(2015, 1, 1, 0, 0)),
        x509.CRLReason(x509.ReasonFlags.ca_compromise),
        x509.CertificateIssuer([
            x509.DNSName(u"cryptography.io"),
        ])
    ])
    @pytest.mark.requires_backend_interface(interface=X509Backend)
    def test_add_extensions(self, backend, extension):
        serial_number = 333
        revocation_date = datetime.datetime(2002, 1, 1, 12, 1)
        builder = x509.RevokedCertificateBuilder().serial_number(
            serial_number).revocation_date(revocation_date).add_extension(
                extension, False)

        revoked_certificate = builder.build(backend)
        assert revoked_certificate.serial_number == serial_number
        assert revoked_certificate.revocation_date == revocation_date
        assert len(revoked_certificate.extensions) == 1
        ext = revoked_certificate.extensions.get_extension_for_class(
            type(extension))
        assert ext.critical is False
        assert ext.value == extension

    @pytest.mark.requires_backend_interface(interface=X509Backend)
    def test_add_multiple_extensions(self, backend):
        serial_number = 333
        revocation_date = datetime.datetime(2002, 1, 1, 12, 1)
        invalidity_date = x509.InvalidityDate(
            datetime.datetime(2015, 1, 1, 0, 0))
        certificate_issuer = x509.CertificateIssuer([
            x509.DNSName(u"cryptography.io"),
        ])
        crl_reason = x509.CRLReason(x509.ReasonFlags.aa_compromise)
        builder = x509.RevokedCertificateBuilder().serial_number(
            serial_number).revocation_date(revocation_date).add_extension(
                invalidity_date,
                True).add_extension(crl_reason, True).add_extension(
                    certificate_issuer, True)

        revoked_certificate = builder.build(backend)
        assert len(revoked_certificate.extensions) == 3
        for ext_data in [invalidity_date, certificate_issuer, crl_reason]:
            ext = revoked_certificate.extensions.get_extension_for_class(
                type(ext_data))
            assert ext.critical is True
            assert ext.value == ext_data
Exemple #12
0
class TestRevokedCertificateBuilder(object):
    def test_serial_number_must_be_integer(self):
        with pytest.raises(TypeError):
            x509.RevokedCertificateBuilder().serial_number(
                "notanx509name"  # type: ignore[arg-type]
            )

    def test_serial_number_must_be_non_negative(self):
        with pytest.raises(ValueError):
            x509.RevokedCertificateBuilder().serial_number(-1)

    def test_serial_number_must_be_positive(self):
        with pytest.raises(ValueError):
            x509.RevokedCertificateBuilder().serial_number(0)

    def test_minimal_serial_number(self, backend):
        revocation_date = datetime.datetime(2002, 1, 1, 12, 1)
        builder = (x509.RevokedCertificateBuilder().serial_number(
            1).revocation_date(revocation_date))

        revoked_certificate = builder.build(backend)
        assert revoked_certificate.serial_number == 1

    def test_biggest_serial_number(self, backend):
        revocation_date = datetime.datetime(2002, 1, 1, 12, 1)
        builder = (x509.RevokedCertificateBuilder().serial_number(
            (1 << 159) - 1).revocation_date(revocation_date))

        revoked_certificate = builder.build(backend)
        assert revoked_certificate.serial_number == (1 << 159) - 1

    def test_serial_number_must_be_less_than_160_bits_long(self):
        with pytest.raises(ValueError):
            x509.RevokedCertificateBuilder().serial_number(1 << 159)

    def test_set_serial_number_twice(self):
        builder = x509.RevokedCertificateBuilder().serial_number(3)
        with pytest.raises(ValueError):
            builder.serial_number(4)

    def test_aware_revocation_date(self, backend):
        time = datetime.datetime(2012, 1, 16, 22, 43)
        tz = pytz.timezone("US/Pacific")
        time = tz.localize(time)
        utc_time = datetime.datetime(2012, 1, 17, 6, 43)
        serial_number = 333
        builder = (x509.RevokedCertificateBuilder().serial_number(
            serial_number).revocation_date(time))

        revoked_certificate = builder.build(backend)
        assert revoked_certificate.revocation_date == utc_time

    def test_revocation_date_invalid(self):
        with pytest.raises(TypeError):
            x509.RevokedCertificateBuilder().revocation_date(
                "notadatetime"  # type: ignore[arg-type]
            )

    def test_revocation_date_before_1950(self):
        with pytest.raises(ValueError):
            x509.RevokedCertificateBuilder().revocation_date(
                datetime.datetime(1940, 8, 10))

    def test_set_revocation_date_twice(self):
        builder = x509.RevokedCertificateBuilder().revocation_date(
            datetime.datetime(2002, 1, 1, 12, 1))
        with pytest.raises(ValueError):
            builder.revocation_date(datetime.datetime(2002, 1, 1, 12, 1))

    def test_add_extension_checks_for_duplicates(self):
        builder = x509.RevokedCertificateBuilder().add_extension(
            x509.CRLReason(x509.ReasonFlags.ca_compromise), False)

        with pytest.raises(ValueError):
            builder.add_extension(
                x509.CRLReason(x509.ReasonFlags.ca_compromise), False)

    def test_add_invalid_extension(self):
        with pytest.raises(TypeError):
            x509.RevokedCertificateBuilder().add_extension(
                "notanextension",
                False  # type: ignore[arg-type]
            )

    def test_no_serial_number(self, backend):
        builder = x509.RevokedCertificateBuilder().revocation_date(
            datetime.datetime(2002, 1, 1, 12, 1))

        with pytest.raises(ValueError):
            builder.build(backend)

    def test_no_revocation_date(self, backend):
        builder = x509.RevokedCertificateBuilder().serial_number(3)

        with pytest.raises(ValueError):
            builder.build(backend)

    def test_create_revoked(self, backend):
        serial_number = 333
        revocation_date = datetime.datetime(2002, 1, 1, 12, 1)
        builder = (x509.RevokedCertificateBuilder().serial_number(
            serial_number).revocation_date(revocation_date))

        revoked_certificate = builder.build(backend)
        assert revoked_certificate.serial_number == serial_number
        assert revoked_certificate.revocation_date == revocation_date
        assert len(revoked_certificate.extensions) == 0

    @pytest.mark.parametrize(
        "extension",
        [
            x509.InvalidityDate(datetime.datetime(2015, 1, 1, 0, 0)),
            x509.CRLReason(x509.ReasonFlags.ca_compromise),
            x509.CertificateIssuer([x509.DNSName("cryptography.io")]),
        ],
    )
    def test_add_extensions(self, backend, extension):
        serial_number = 333
        revocation_date = datetime.datetime(2002, 1, 1, 12, 1)
        builder = (x509.RevokedCertificateBuilder().serial_number(
            serial_number).revocation_date(revocation_date).add_extension(
                extension, False))

        revoked_certificate = builder.build(backend)
        assert revoked_certificate.serial_number == serial_number
        assert revoked_certificate.revocation_date == revocation_date
        assert len(revoked_certificate.extensions) == 1
        ext = revoked_certificate.extensions.get_extension_for_class(
            type(extension))
        assert ext.critical is False
        assert ext.value == extension

    def test_add_multiple_extensions(self, backend):
        serial_number = 333
        revocation_date = datetime.datetime(2002, 1, 1, 12, 1)
        invalidity_date = x509.InvalidityDate(
            datetime.datetime(2015, 1, 1, 0, 0))
        certificate_issuer = x509.CertificateIssuer(
            [x509.DNSName("cryptography.io")])
        crl_reason = x509.CRLReason(x509.ReasonFlags.aa_compromise)
        builder = (x509.RevokedCertificateBuilder().serial_number(
            serial_number).revocation_date(revocation_date).add_extension(
                invalidity_date,
                True).add_extension(crl_reason, True).add_extension(
                    certificate_issuer, True))

        revoked_certificate = builder.build(backend)
        assert len(revoked_certificate.extensions) == 3
        for ext_data in [invalidity_date, certificate_issuer, crl_reason]:
            ext = revoked_certificate.extensions.get_extension_for_class(
                type(ext_data))
            assert ext.critical is True
            assert ext.value == ext_data
Exemple #13
0
 def _get_revoked(self, serial):
     return x509.RevokedCertificateBuilder().serial_number(
         int(serial)).revocation_date(
             datetime.datetime.today()).add_extension(
                 x509.CRLReason(x509.ReasonFlags.unspecified),
                 critical=False).build(backend=backends.default_backend())