michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "OCSPCommon.h" michael@0: michael@0: #include michael@0: michael@0: #include "ScopedNSSTypes.h" michael@0: #include "TLSServer.h" michael@0: #include "pkixtestutil.h" michael@0: #include "secder.h" michael@0: #include "secerr.h" michael@0: michael@0: using namespace mozilla; michael@0: using namespace mozilla::test; michael@0: using namespace mozilla::pkix::test; michael@0: michael@0: michael@0: SECItemArray * michael@0: GetOCSPResponseForType(OCSPResponseType aORT, CERTCertificate *aCert, michael@0: PLArenaPool *aArena, const char *aAdditionalCertName) michael@0: { michael@0: if (aORT == ORTNone) { michael@0: if (gDebugLevel >= DEBUG_WARNINGS) { michael@0: fprintf(stderr, "GetOCSPResponseForType called with type ORTNone, " michael@0: "which makes no sense.\n"); michael@0: } michael@0: return nullptr; michael@0: } michael@0: michael@0: if (aORT == ORTEmpty) { michael@0: SECItemArray* arr = SECITEM_AllocArray(aArena, nullptr, 1); michael@0: arr->items[0].data = nullptr; michael@0: arr->items[0].len = 0; michael@0: return arr; michael@0: } michael@0: michael@0: PRTime now = PR_Now(); michael@0: PRTime oneDay = 60*60*24 * (PRTime)PR_USEC_PER_SEC; michael@0: PRTime oldNow = now - (8 * oneDay); michael@0: michael@0: OCSPResponseContext context(aArena, aCert, now); michael@0: michael@0: if (aORT == ORTGoodOtherCert) { michael@0: context.cert = PK11_FindCertFromNickname(aAdditionalCertName, nullptr); michael@0: if (!context.cert) { michael@0: PrintPRError("PK11_FindCertFromNickname failed"); michael@0: return nullptr; michael@0: } michael@0: } michael@0: // XXX CERT_FindCertIssuer uses the old, deprecated path-building logic michael@0: context.issuerCert = CERT_FindCertIssuer(aCert, now, certUsageSSLCA); michael@0: if (!context.issuerCert) { michael@0: PrintPRError("CERT_FindCertIssuer failed"); michael@0: return nullptr; michael@0: } michael@0: if (aORT == ORTGoodOtherCA || aORT == ORTDelegatedIncluded || michael@0: aORT == ORTDelegatedIncludedLast || aORT == ORTDelegatedMissing || michael@0: aORT == ORTDelegatedMissingMultiple) { michael@0: context.signerCert = PK11_FindCertFromNickname(aAdditionalCertName, michael@0: nullptr); michael@0: if (!context.signerCert) { michael@0: PrintPRError("PK11_FindCertFromNickname failed"); michael@0: return nullptr; michael@0: } michael@0: } michael@0: if (aORT == ORTDelegatedIncluded) { michael@0: context.includedCertificates[0] = michael@0: CERT_DupCertificate(context.signerCert.get()); michael@0: } michael@0: if (aORT == ORTDelegatedIncludedLast || aORT == ORTDelegatedMissingMultiple) { michael@0: context.includedCertificates[0] = michael@0: CERT_DupCertificate(context.issuerCert.get()); michael@0: context.includedCertificates[1] = CERT_DupCertificate(context.cert.get()); michael@0: context.includedCertificates[2] = michael@0: CERT_DupCertificate(context.issuerCert.get()); michael@0: if (aORT != ORTDelegatedMissingMultiple) { michael@0: context.includedCertificates[3] = michael@0: CERT_DupCertificate(context.signerCert.get()); michael@0: } michael@0: } michael@0: switch (aORT) { michael@0: case ORTMalformed: michael@0: context.responseStatus = 1; michael@0: break; michael@0: case ORTSrverr: michael@0: context.responseStatus = 2; michael@0: break; michael@0: case ORTTryLater: michael@0: context.responseStatus = 3; michael@0: break; michael@0: case ORTNeedsSig: michael@0: context.responseStatus = 5; michael@0: break; michael@0: case ORTUnauthorized: michael@0: context.responseStatus = 6; michael@0: break; michael@0: default: michael@0: // context.responseStatus is 0 in all other cases, and it has michael@0: // already been initialized in the constructor. michael@0: break; michael@0: } michael@0: if (aORT == ORTSkipResponseBytes) { michael@0: context.skipResponseBytes = true; michael@0: } michael@0: if (aORT == ORTExpired || aORT == ORTExpiredFreshCA || michael@0: aORT == ORTRevokedOld || aORT == ORTUnknownOld) { michael@0: context.thisUpdate = oldNow; michael@0: context.nextUpdate = oldNow + 10 * PR_USEC_PER_SEC; michael@0: } michael@0: if (aORT == ORTLongValidityAlmostExpired) { michael@0: context.thisUpdate = now - (320 * oneDay); michael@0: } michael@0: if (aORT == ORTAncientAlmostExpired) { michael@0: context.thisUpdate = now - (640 * oneDay); michael@0: } michael@0: if (aORT == ORTRevoked || aORT == ORTRevokedOld) { michael@0: context.certStatus = 1; michael@0: } michael@0: if (aORT == ORTUnknown || aORT == ORTUnknownOld) { michael@0: context.certStatus = 2; michael@0: } michael@0: if (aORT == ORTBadSignature) { michael@0: context.badSignature = true; michael@0: } michael@0: OCSPResponseExtension extension; michael@0: if (aORT == ORTCriticalExtension || aORT == ORTNoncriticalExtension) { michael@0: SECItem oidItem = { michael@0: siBuffer, michael@0: nullptr, michael@0: 0 michael@0: }; michael@0: // 1.3.6.1.4.1.13769.666.666.666 is the root of Mozilla's testing OID space michael@0: static const char* testExtensionOID = "1.3.6.1.4.1.13769.666.666.666.1.500.9.2"; michael@0: if (SEC_StringToOID(aArena, &oidItem, testExtensionOID, michael@0: PL_strlen(testExtensionOID)) != SECSuccess) { michael@0: return nullptr; michael@0: } michael@0: DERTemplate oidTemplate[2] = { { DER_OBJECT_ID, 0 }, { 0 } }; michael@0: extension.id.data = nullptr; michael@0: extension.id.len = 0; michael@0: if (DER_Encode(aArena, &extension.id, oidTemplate, &oidItem) michael@0: != SECSuccess) { michael@0: return nullptr; michael@0: } michael@0: extension.critical = (aORT == ORTCriticalExtension); michael@0: static const uint8_t value[2] = { 0x05, 0x00 }; michael@0: extension.value.data = const_cast(value); michael@0: extension.value.len = PR_ARRAY_SIZE(value); michael@0: extension.next = nullptr; michael@0: context.extensions = &extension; michael@0: } michael@0: if (aORT == ORTEmptyExtensions) { michael@0: context.includeEmptyExtensions = true; michael@0: } michael@0: michael@0: if (!context.signerCert) { michael@0: context.signerCert = CERT_DupCertificate(context.issuerCert.get()); michael@0: } michael@0: michael@0: SECItem* response = CreateEncodedOCSPResponse(context); michael@0: if (!response) { michael@0: PrintPRError("CreateEncodedOCSPResponse failed"); michael@0: return nullptr; michael@0: } michael@0: michael@0: SECItemArray* arr = SECITEM_AllocArray(aArena, nullptr, 1); michael@0: if (!arr) { michael@0: PrintPRError("SECITEM_AllocArray failed"); michael@0: return nullptr; michael@0: } michael@0: arr->items[0].data = response->data; michael@0: arr->items[0].len = response->len; michael@0: michael@0: return arr; michael@0: }