OCSPCommon.cpp (7711B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 #include "OCSPCommon.h" 6 7 #include <stdio.h> 8 9 #include "TLSServer.h" 10 #include "mozpkix/pkixder.h" 11 #include "mozpkix/test/pkixtestnss.h" 12 #include "mozpkix/test/pkixtestutil.h" 13 #include "nss.h" 14 #include "secder.h" 15 #include "secerr.h" 16 17 using namespace mozilla; 18 using namespace mozilla::pkix; 19 using namespace mozilla::pkix::test; 20 using namespace mozilla::test; 21 22 static TestKeyPair* CreateTestKeyPairFromCert( 23 const UniqueCERTCertificate& cert) { 24 ScopedSECKEYPrivateKey privateKey(PK11_FindKeyByAnyCert(cert.get(), nullptr)); 25 if (!privateKey) { 26 return nullptr; 27 } 28 ScopedSECKEYPublicKey publicKey(CERT_ExtractPublicKey(cert.get())); 29 if (!publicKey) { 30 return nullptr; 31 } 32 return CreateTestKeyPair(RSA_PKCS1(), publicKey, privateKey); 33 } 34 35 SECItemArray* GetOCSPResponseForType(OCSPResponseType aORT, 36 const UniqueCERTCertificate& aCert, 37 const UniquePLArenaPool& aArena, 38 const char* aAdditionalCertName, 39 time_t aThisUpdateSkew, 40 ByteString* aSCTList) { 41 MOZ_ASSERT(aArena); 42 MOZ_ASSERT(aCert); 43 // Note: |aAdditionalCertName| may or may not need to be non-null depending 44 // on the |aORT| value given. 45 46 // Ensure NSS can sign responses using small RSA keys. 47 NSS_OptionSet(NSS_RSA_MIN_KEY_SIZE, 512); 48 49 if (aORT == ORTNone) { 50 if (gDebugLevel >= DEBUG_WARNINGS) { 51 fprintf(stderr, 52 "GetOCSPResponseForType called with type ORTNone, " 53 "which makes no sense.\n"); 54 } 55 return nullptr; 56 } 57 58 if (aORT == ORTEmpty) { 59 SECItemArray* arr = SECITEM_AllocArray(aArena.get(), nullptr, 1); 60 arr->items[0].data = nullptr; 61 arr->items[0].len = 0; 62 return arr; 63 } 64 65 time_t now = time(nullptr) + aThisUpdateSkew; 66 time_t oldNow = now - (8 * Time::ONE_DAY_IN_SECONDS); 67 68 mozilla::UniqueCERTCertificate cert(CERT_DupCertificate(aCert.get())); 69 70 if (aORT == ORTGoodOtherCert) { 71 cert.reset(PK11_FindCertFromNickname(aAdditionalCertName, nullptr)); 72 if (!cert) { 73 PrintPRError("PK11_FindCertFromNickname failed"); 74 return nullptr; 75 } 76 } 77 // XXX CERT_FindCertIssuer uses the old, deprecated path-building logic 78 mozilla::UniqueCERTCertificate issuerCert( 79 CERT_FindCertIssuer(aCert.get(), PR_Now(), certUsageSSLCA)); 80 if (!issuerCert) { 81 PrintPRError("CERT_FindCertIssuer failed"); 82 return nullptr; 83 } 84 Input issuer; 85 if (issuer.Init(cert->derIssuer.data, cert->derIssuer.len) != Success) { 86 return nullptr; 87 } 88 Input issuerPublicKey; 89 if (issuerPublicKey.Init(issuerCert->derPublicKey.data, 90 issuerCert->derPublicKey.len) != Success) { 91 return nullptr; 92 } 93 Input serialNumber; 94 if (serialNumber.Init(cert->serialNumber.data, cert->serialNumber.len) != 95 Success) { 96 return nullptr; 97 } 98 CertID certID(issuer, issuerPublicKey, serialNumber); 99 OCSPResponseContext context(certID, now); 100 101 mozilla::UniqueCERTCertificate signerCert; 102 if (aORT == ORTGoodOtherCA || aORT == ORTDelegatedIncluded || 103 aORT == ORTDelegatedIncludedLast || aORT == ORTDelegatedMissing || 104 aORT == ORTDelegatedMissingMultiple) { 105 signerCert.reset(PK11_FindCertFromNickname(aAdditionalCertName, nullptr)); 106 if (!signerCert) { 107 PrintPRError("PK11_FindCertFromNickname failed"); 108 return nullptr; 109 } 110 } 111 112 ByteString certs[5]; 113 114 if (aORT == ORTDelegatedIncluded) { 115 certs[0].assign(signerCert->derCert.data, signerCert->derCert.len); 116 context.certs = certs; 117 } 118 if (aORT == ORTDelegatedIncludedLast || aORT == ORTDelegatedMissingMultiple) { 119 certs[0].assign(issuerCert->derCert.data, issuerCert->derCert.len); 120 certs[1].assign(cert->derCert.data, cert->derCert.len); 121 certs[2].assign(issuerCert->derCert.data, issuerCert->derCert.len); 122 if (aORT != ORTDelegatedMissingMultiple) { 123 certs[3].assign(signerCert->derCert.data, signerCert->derCert.len); 124 } 125 context.certs = certs; 126 } 127 128 switch (aORT) { 129 case ORTMalformed: 130 context.responseStatus = 1; 131 break; 132 case ORTSrverr: 133 context.responseStatus = 2; 134 break; 135 case ORTTryLater: 136 context.responseStatus = 3; 137 break; 138 case ORTNeedsSig: 139 context.responseStatus = 5; 140 break; 141 case ORTUnauthorized: 142 context.responseStatus = 6; 143 break; 144 default: 145 // context.responseStatus is 0 in all other cases, and it has 146 // already been initialized in the constructor. 147 break; 148 } 149 if (aORT == ORTSkipResponseBytes) { 150 context.skipResponseBytes = true; 151 } 152 if (aORT == ORTExpired || aORT == ORTExpiredFreshCA || 153 aORT == ORTRevokedOld || aORT == ORTUnknownOld) { 154 context.thisUpdate = oldNow; 155 context.nextUpdate = oldNow + Time::ONE_DAY_IN_SECONDS; 156 } 157 if (aORT == ORTLongValidityAlmostExpired) { 158 context.thisUpdate = now - (320 * Time::ONE_DAY_IN_SECONDS); 159 } 160 if (aORT == ORTAncientAlmostExpired) { 161 context.thisUpdate = now - (640 * Time::ONE_DAY_IN_SECONDS); 162 } 163 if (aORT == ORTRevoked || aORT == ORTRevokedOld) { 164 context.certStatus = 1; 165 } 166 if (aORT == ORTUnknown || aORT == ORTUnknownOld) { 167 context.certStatus = 2; 168 } 169 if (aORT == ORTBadSignature) { 170 context.badSignature = true; 171 } 172 OCSPResponseExtension extension; 173 if (aORT == ORTCriticalExtension || aORT == ORTNoncriticalExtension) { 174 // python DottedOIDToCode.py --tlv 175 // some-Mozilla-OID 1.3.6.1.4.1.13769.666.666.666.1.500.9.2 176 static const uint8_t tlv_some_Mozilla_OID[] = { 177 0x06, 0x12, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xeb, 0x49, 0x85, 178 0x1a, 0x85, 0x1a, 0x85, 0x1a, 0x01, 0x83, 0x74, 0x09, 0x02}; 179 180 extension.id.assign(tlv_some_Mozilla_OID, sizeof(tlv_some_Mozilla_OID)); 181 extension.critical = (aORT == ORTCriticalExtension); 182 extension.value.push_back(0x05); // tag: NULL 183 extension.value.push_back(0x00); // length: 0 184 extension.next = nullptr; 185 context.responseExtensions = &extension; 186 } 187 if (aORT == ORTEmptyExtensions) { 188 context.includeEmptyExtensions = true; 189 } 190 191 if (!signerCert) { 192 signerCert.reset(CERT_DupCertificate(issuerCert.get())); 193 } 194 context.signerKeyPair.reset(CreateTestKeyPairFromCert(signerCert)); 195 if (!context.signerKeyPair) { 196 PrintPRError("PK11_FindKeyByAnyCert failed"); 197 return nullptr; 198 } 199 200 OCSPResponseExtension singleExtension; 201 if (aSCTList) { 202 // SingleExtension for Signed Certificate Timestamp List. 203 // See Section 3.3 of RFC 6962. 204 // python DottedOIDToCode.py --tlv 205 // id_ocsp_singleExtensionSctList 1.3.6.1.4.1.11129.2.4.5 206 static const uint8_t tlv_id_ocsp_singleExtensionSctList[] = { 207 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xd6, 0x79, 0x02, 0x04, 0x05}; 208 singleExtension.id.assign(tlv_id_ocsp_singleExtensionSctList, 209 sizeof(tlv_id_ocsp_singleExtensionSctList)); 210 singleExtension.critical = true; 211 singleExtension.value = TLV(der::OCTET_STRING, *aSCTList); 212 singleExtension.next = nullptr; 213 context.singleExtensions = &singleExtension; 214 } 215 216 ByteString response(CreateEncodedOCSPResponse(context)); 217 if (ENCODING_FAILED(response)) { 218 PrintPRError("CreateEncodedOCSPResponse failed"); 219 return nullptr; 220 } 221 222 SECItem item = {siBuffer, const_cast<uint8_t*>(response.data()), 223 static_cast<unsigned int>(response.length())}; 224 SECItemArray arr = {&item, 1}; 225 return SECITEM_DupArray(aArena.get(), &arr); 226 }