CA: use mockable clock in CA's OCSP signer. (#4539)

This brings OCSP signing into alignment with the other components of the
CA in that they use ca.clk, which can be mocked out in unittests.

This tweaks test_ocsp_exp_unauth to be compatible with the change.

Fixes #4441.
This commit is contained in:
Jacob Hoffman-Andrews 2019-11-11 13:17:46 -08:00 committed by Daniel McCarney
parent a44f346f88
commit 2ab1729a18
2 changed files with 25 additions and 11 deletions

View File

@ -412,16 +412,7 @@ func (ca *CertificateAuthorityImpl) GenerateOCSP(ctx context.Context, xferObj co
core.SerialToString(cert.SerialNumber), cn, err)
}
// We use time.Now() rather than ca.clk.Now() here as we use openssl
// to verify the validity of the OCSP responses we generate during testing
// and openssl doesn't understand our concept of fake time so it thinks
// our responses are expired when we are doing things with our fake clock
// time set in the past. Since we don't rely on fake clock time for any
// OCSP unit tests always using the real time doesn't cause any problems.
// Currently the only integration test case that triggers this is
// ocsp_exp_unauth_setup, but any other integration test introduced that
// sets the fake clock into the past and verifies OCSP will also do so.
now := time.Now().Truncate(time.Hour)
now := ca.clk.Now().Truncate(time.Hour)
tbsResponse := ocsp.Response{
Status: ocspStatusToCode[xferObj.Status],
SerialNumber: cert.SerialNumber,

View File

@ -1173,6 +1173,25 @@ def test_auth_deactivation_v2():
raise Exception("unexpected authorization status")
def check_ocsp_basic_oid(cert_file, issuer_file, url):
"""
This function checks if an OCSP response was successful, but doesn't verify
the signature or timestamp. This is useful when simulating the past, so we
don't incorrectly reject a response for being in the past.
"""
ocsp_request = make_ocsp_req(cert_file, issuer_file)
responses = fetch_ocsp(ocsp_request, url)
# An unauthorized response (for instance, if the OCSP responder doesn't know
# about this cert) will just be 30 03 0A 01 06. A "good" or "revoked"
# response will contain, among other things, the id-pkix-ocsp-basic OID
# identifying the response type. We look for that OID to confirm we got a
# succesful response.
expected = bytearray.fromhex("06 09 2B 06 01 05 05 07 30 01 01")
for resp in responses:
if not expected in bytearray(resp):
raise Exception("Did not receive successful OCSP response: %s doesn't contain %s" %
(base64.b64encode(resp), base64.b64encode(expected)))
expired_cert_name = ""
@register_six_months_ago
def ocsp_exp_unauth_setup():
@ -1184,7 +1203,11 @@ def ocsp_exp_unauth_setup():
with open(cert_file_pem, "w") as f:
f.write(OpenSSL.crypto.dump_certificate(
OpenSSL.crypto.FILETYPE_PEM, cert).decode())
verify_ocsp(cert_file_pem, "test/test-ca2.pem", "http://localhost:4002", "good")
# Since we're pretending to be in the past, we'll get an expired OCSP
# response. Just check that it exists; don't do the full verification (which
# would fail).
check_ocsp_basic_oid(cert_file_pem, "test/test-ca2.pem", "http://localhost:4002")
global expired_cert_name
expired_cert_name = cert_file_pem