Esempio n. 1
0
 def test_sign_with_extension(self):
     builder = ocsp.OCSPResponseBuilder()
     cert, issuer = _cert_and_issuer()
     root_cert, private_key = _generate_root()
     current_time = datetime.datetime.utcnow().replace(microsecond=0)
     this_update = current_time - datetime.timedelta(days=1)
     next_update = this_update + datetime.timedelta(days=7)
     builder = (builder.responder_id(ocsp.OCSPResponderEncoding.HASH,
                                     root_cert).add_response(
                                         cert,
                                         issuer,
                                         hashes.SHA1(),
                                         ocsp.OCSPCertStatus.GOOD,
                                         this_update,
                                         next_update,
                                         None,
                                         None,
                                     ).add_extension(
                                         x509.OCSPNonce(b"012345"), False))
     resp = builder.sign(private_key, hashes.SHA256())
     assert len(resp.extensions) == 1
     assert resp.extensions[0].value == x509.OCSPNonce(b"012345")
     assert resp.extensions[0].critical is False
     private_key.public_key().verify(resp.signature,
                                     resp.tbs_response_bytes,
                                     ec.ECDSA(hashes.SHA256()))
Esempio n. 2
0
 def test_response_extensions(self):
     resp = _load_data(
         os.path.join("x509", "ocsp", "resp-revoked-reason.der"),
         ocsp.load_der_ocsp_response,
     )
     assert len(resp.extensions) == 1
     ext = resp.extensions[0]
     assert ext.critical is False
     assert ext.value == x509.OCSPNonce(
         b'\x04\x105\x957\x9fa\x03\x83\x87\x89rW\x8f\xae\x99\xf7"')
Esempio n. 3
0
 def test_load_request_with_extensions(self):
     req = _load_data(
         os.path.join("x509", "ocsp", "req-ext-nonce.der"),
         ocsp.load_der_ocsp_request,
     )
     assert len(req.extensions) == 1
     ext = req.extensions[0]
     assert ext.critical is False
     assert ext.value == x509.OCSPNonce(
         b"\x04\x10{\x80Z\x1d7&\xb8\xb8OH\xd2\xf8\xbf\xd7-\xfd")
Esempio n. 4
0
 def test_add_extension_twice(self):
     builder = ocsp.OCSPRequestBuilder()
     builder = builder.add_extension(x509.OCSPNonce(b"123"), False)
     with pytest.raises(ValueError):
         builder.add_extension(x509.OCSPNonce(b"123"), False)
Esempio n. 5
0
class TestOCSPRequestBuilder(object):
    def test_add_two_certs(self):
        cert, issuer = _cert_and_issuer()
        builder = ocsp.OCSPRequestBuilder()
        builder = builder.add_certificate(cert, issuer, hashes.SHA1())
        with pytest.raises(ValueError):
            builder.add_certificate(cert, issuer, hashes.SHA1())

    def test_create_ocsp_request_no_req(self):
        builder = ocsp.OCSPRequestBuilder()
        with pytest.raises(ValueError):
            builder.build()

    def test_create_ocsp_request_invalid_alg(self):
        cert, issuer = _cert_and_issuer()
        builder = ocsp.OCSPRequestBuilder()
        with pytest.raises(ValueError):
            builder.add_certificate(cert, issuer, hashes.MD5())

    def test_add_extension_twice(self):
        builder = ocsp.OCSPRequestBuilder()
        builder = builder.add_extension(x509.OCSPNonce(b"123"), False)
        with pytest.raises(ValueError):
            builder.add_extension(x509.OCSPNonce(b"123"), False)

    def test_add_invalid_extension(self):
        builder = ocsp.OCSPRequestBuilder()
        with pytest.raises(TypeError):
            builder.add_extension("notanext", False)

    def test_create_ocsp_request_invalid_cert(self):
        cert, issuer = _cert_and_issuer()
        builder = ocsp.OCSPRequestBuilder()
        with pytest.raises(TypeError):
            builder.add_certificate(b"notacert", issuer, hashes.SHA1())

        with pytest.raises(TypeError):
            builder.add_certificate(cert, b"notacert", hashes.SHA1())

    def test_create_ocsp_request(self):
        cert, issuer = _cert_and_issuer()
        builder = ocsp.OCSPRequestBuilder()
        builder = builder.add_certificate(cert, issuer, hashes.SHA1())
        req = builder.build()
        serialized = req.public_bytes(serialization.Encoding.DER)
        assert serialized == base64.b64decode(
            b"MEMwQTA/MD0wOzAJBgUrDgMCGgUABBRAC0Z68eay0wmDug1gfn5ZN0gkxAQUw5zz"
            b"/NNGCDS7zkZ/oHxb8+IIy1kCAj8g")

    @pytest.mark.parametrize(
        ("ext", "critical"),
        [
            [x509.OCSPNonce(b"0000"), False],
            [x509.OCSPNonce(b"\x00\x01\x02"), True],
        ],
    )
    def test_create_ocsp_request_with_extension(self, ext, critical):
        cert, issuer = _cert_and_issuer()
        builder = ocsp.OCSPRequestBuilder()
        builder = builder.add_certificate(cert, issuer,
                                          hashes.SHA1()).add_extension(
                                              ext, critical)
        req = builder.build()
        assert len(req.extensions) == 1
        assert req.extensions[0].value == ext
        assert req.extensions[0].oid == ext.oid
        assert req.extensions[0].critical is critical
Esempio n. 6
0
def _decode_nonce(backend, nonce):
    nonce = backend._ffi.cast("ASN1_OCTET_STRING *", nonce)
    nonce = backend._ffi.gc(nonce, backend._lib.ASN1_OCTET_STRING_free)
    return x509.OCSPNonce(_asn1_string_to_bytes(backend, nonce))
Esempio n. 7
0
        if not os.path.exists(ocsp_base):
            os.makedirs(ocsp_base)
        ocsp_builder = ocsp.OCSPRequestBuilder()
        ocsp_builder = ocsp_builder.add_certificate(
            data["child-cert"]["parsed_cert"].pub.loaded,
            CertificateAuthority.objects.get(
                name=data["child-cert"]["ca"]).pub.loaded,
            hashes.SHA1(),
        )

        no_nonce_req = ocsp_builder.build().public_bytes(Encoding.DER)
        with open(os.path.join(ocsp_base, ocsp_data["no-nonce"]["filename"]),
                  "wb") as stream:
            stream.write(no_nonce_req)

        ocsp_builder = ocsp_builder.add_extension(x509.OCSPNonce(
            hex_to_bytes(ocsp_data["nonce"]["nonce"])),
                                                  critical=False)
        nonce_req = ocsp_builder.build().public_bytes(Encoding.DER)
        with open(os.path.join(ocsp_base, ocsp_data["nonce"]["filename"]),
                  "wb") as stream:
            stream.write(nonce_req)
else:
    # updating only contrib, so remove existing data
    data = {}

# Load data from Sphinx files
if args.generate_contrib:
    for filename in os.listdir(os.path.join(_sphinx_dir, "ca")):
        name, _ext = os.path.splitext(filename)

        with open(os.path.join(_sphinx_dir, "ca", filename), "rb") as stream:
Esempio n. 8
0
def _get_ocsp_response(data, pebble_urlopen, log):
    try:
        ocsp_request = ocsp.load_der_ocsp_request(data)
    except Exception:
        log('Error while decoding OCSP request')
        return ocsp.OCSPResponseBuilder.build_unsuccessful(
            ocsp.OCSPResponseStatus.MALFORMED_REQUEST)

    log('OCSP request for certificate # {0}'.format(
        ocsp_request.serial_number))

    # Process possible extensions
    nonce = None
    for ext in ocsp_request.extensions:
        if isinstance(ext.value, x509.OCSPNonce):
            nonce = ext.value.nonce
            continue
        if ext.critical:
            return ocsp.OCSPResponseBuilder.build_unsuccessful(
                ocsp.OCSPResponseStatus.MALFORMED_REQUEST)

    # Determine issuer
    root_count = int(os.environ.get('PEBBLE_ALTERNATE_ROOTS') or '0') + 1
    for root in range(root_count):
        req, intermediate, intermediate_key = _get_sample_request_for_root(
            root, ocsp_request.hash_algorithm, pebble_urlopen)
        if req.issuer_key_hash == ocsp_request.issuer_key_hash and req.issuer_name_hash == ocsp_request.issuer_name_hash:
            log('Identified intermediate certificate {0}'.format(
                intermediate.subject))
            break
        intermediate = None
        intermediate_key = None
    if intermediate is None or intermediate_key is None:
        log(ocsp_request.issuer_key_hash, ocsp_request.issuer_name_hash)
        log('Cannot identify intermediate certificate')
        return ocsp.OCSPResponseBuilder.build_unsuccessful(
            ocsp.OCSPResponseStatus.UNAUTHORIZED)

    serial_hex = hex(ocsp_request.serial_number)[2:]
    if len(serial_hex) % 2 == 1:
        serial_hex = '0' + serial_hex
    try:
        url = pebble_urlopen("/cert-status-by-serial/{0}".format(serial_hex))
    except urllib.error.HTTPError as e:
        if e.code == 404:
            log('Unknown certificate with # {0}'.format(
                ocsp_request.serial_number))
            return ocsp.OCSPResponseBuilder.build_unsuccessful(
                ocsp.OCSPResponseStatus.UNAUTHORIZED)
        raise

    data = json.loads(url.read())
    log('Pebble result on certificate:',
        json.dumps(data, sort_keys=True, indent=2))

    cert = x509.load_pem_x509_certificate(data['Certificate'].encode('utf-8'),
                                          backend=default_backend())

    now = datetime.datetime.now()
    if data['Status'] == 'Revoked':
        cert_status = ocsp.OCSPCertStatus.REVOKED
        revoked_at = data.get('RevokedAt')
        if revoked_at is not None:
            revoked_at = ' '.join(
                revoked_at.split(' ')[:2])  # remove time zones
            if '.' in revoked_at:
                revoked_at = revoked_at[:revoked_at.index(
                    '.')]  # remove milli- or nanoseconds
            revoked_at = datetime.datetime.strptime(revoked_at,
                                                    '%Y-%m-%d %H:%M:%S')
        revocation_time = revoked_at,
        revocation_reason = RECOVATION_REASONS.get(
            data.get('Reason'), x509.ReasonFlags.unspecified)
    elif data['Status'] == 'Valid':
        cert_status = ocsp.OCSPCertStatus.GOOD
        revocation_time = None
        revocation_reason = None
    else:
        log('Unknown certificate status "{0}"'.format(data['Status']))
        return ocsp.OCSPResponseBuilder.build_unsuccessful(
            ocsp.OCSPResponseStatus.INTERNAL_ERROR)

    response = ocsp.OCSPResponseBuilder()
    response = response.add_response(cert=cert,
                                     issuer=intermediate,
                                     algorithm=ocsp_request.hash_algorithm,
                                     cert_status=cert_status,
                                     this_update=now,
                                     next_update=None,
                                     revocation_time=revocation_time,
                                     revocation_reason=revocation_reason)
    response = response.responder_id(ocsp.OCSPResponderEncoding.HASH,
                                     intermediate)
    if nonce is not None:
        response = response.add_extension(x509.OCSPNonce(nonce), False)
    return response.sign(intermediate_key, hashes.SHA256())
Esempio n. 9
0
        ocsp_base = os.path.join(args.dest, 'ocsp')
        if not os.path.exists(ocsp_base):
            os.makedirs(ocsp_base)
        ocsp_builder = ocsp.OCSPRequestBuilder()
        ocsp_builder = ocsp_builder.add_certificate(
            data['child-cert']['parsed_cert'].x509,
            CertificateAuthority.objects.get(name=data['child-cert']['ca']).x509,
            hashes.SHA1()
        )

        no_nonce_req = ocsp_builder.build().public_bytes(Encoding.DER)
        with open(os.path.join(ocsp_base, ocsp_data['no-nonce']['filename']), 'wb') as stream:
            stream.write(no_nonce_req)

        ocsp_builder = ocsp_builder.add_extension(
            x509.OCSPNonce(hex_to_bytes(ocsp_data['nonce']['nonce'])), critical=False
        )
        nonce_req = ocsp_builder.build().public_bytes(Encoding.DER)
        with open(os.path.join(ocsp_base, ocsp_data['nonce']['filename']), 'wb') as stream:
            stream.write(nonce_req)
else:
    # updating only contrib, so remove existing data
    data = {}

# Load data from Sphinx files
if args.generate_contrib:
    for filename in os.listdir(os.path.join(_sphinx_dir, 'ca')):
        name, _ext = os.path.splitext(filename)

        with open(os.path.join(_sphinx_dir, 'ca', filename), 'rb') as stream:
            pem = stream.read()