SECStatus VerifyEncodedOCSPResponse(TrustDomain& trustDomain, const CERTCertificate* cert, CERTCertificate* issuerCert, PRTime time, const SECItem* encodedResponse, PRTime* thisUpdate, PRTime* validThrough) { PR_ASSERT(cert); PR_ASSERT(issuerCert); // TODO: PR_Assert(pinArg) PR_ASSERT(encodedResponse); if (!cert || !issuerCert || !encodedResponse || !encodedResponse->data) { PR_SetError(SEC_ERROR_INVALID_ARGS, 0); return SECFailure; } der::Input input; if (input.Init(encodedResponse->data, encodedResponse->len) != der::Success) { SetErrorToMalformedResponseOnBadDERError(); return SECFailure; } Context context(trustDomain, *cert, *issuerCert, time, thisUpdate, validThrough); if (der::Nested(input, der::SEQUENCE, bind(OCSPResponse, _1, ref(context))) != der::Success) { SetErrorToMalformedResponseOnBadDERError(); return SECFailure; } if (der::End(input) != der::Success) { SetErrorToMalformedResponseOnBadDERError(); return SECFailure; } switch (context.certStatus) { case CertStatus::Good: return SECSuccess; case CertStatus::Revoked: PR_SetError(SEC_ERROR_REVOKED_CERTIFICATE, 0); return SECFailure; case CertStatus::Unknown: PR_SetError(SEC_ERROR_OCSP_UNKNOWN_CERT, 0); return SECFailure; } PR_NOT_REACHED("unknown CertStatus"); PR_SetError(SEC_ERROR_OCSP_UNKNOWN_CERT, 0); return SECFailure; }
SECStatus VerifyEncodedOCSPResponse(TrustDomain& trustDomain, const struct CertID& certID, PRTime time, uint16_t maxOCSPLifetimeInDays, const SECItem& encodedResponse, /*out*/ bool& expired, /*optional out*/ PRTime* thisUpdate, /*optional out*/ PRTime* validThrough) { // Always initialize this to something reasonable. expired = false; Input input; if (input.Init(encodedResponse.data, encodedResponse.len) != Success) { SetErrorToMalformedResponseOnBadDERError(); return SECFailure; } Context context(trustDomain, certID, time, maxOCSPLifetimeInDays, thisUpdate, validThrough); if (der::Nested(input, der::SEQUENCE, bind(OCSPResponse, _1, ref(context))) != Success) { SetErrorToMalformedResponseOnBadDERError(); return SECFailure; } if (der::End(input) != Success) { SetErrorToMalformedResponseOnBadDERError(); return SECFailure; } expired = context.expired; switch (context.certStatus) { case CertStatus::Good: if (expired) { PR_SetError(SEC_ERROR_OCSP_OLD_RESPONSE, 0); return SECFailure; } return SECSuccess; case CertStatus::Revoked: PR_SetError(SEC_ERROR_REVOKED_CERTIFICATE, 0); return SECFailure; case CertStatus::Unknown: PR_SetError(SEC_ERROR_OCSP_UNKNOWN_CERT, 0); return SECFailure; } PR_NOT_REACHED("unknown CertStatus"); PR_SetError(SEC_ERROR_OCSP_UNKNOWN_CERT, 0); return SECFailure; }