|
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 "ScopedNSSTypes.h" |
|
10 #include "TLSServer.h" |
|
11 #include "pkixtestutil.h" |
|
12 #include "secder.h" |
|
13 #include "secerr.h" |
|
14 |
|
15 using namespace mozilla; |
|
16 using namespace mozilla::test; |
|
17 using namespace mozilla::pkix::test; |
|
18 |
|
19 |
|
20 SECItemArray * |
|
21 GetOCSPResponseForType(OCSPResponseType aORT, CERTCertificate *aCert, |
|
22 PLArenaPool *aArena, const char *aAdditionalCertName) |
|
23 { |
|
24 if (aORT == ORTNone) { |
|
25 if (gDebugLevel >= DEBUG_WARNINGS) { |
|
26 fprintf(stderr, "GetOCSPResponseForType called with type ORTNone, " |
|
27 "which makes no sense.\n"); |
|
28 } |
|
29 return nullptr; |
|
30 } |
|
31 |
|
32 if (aORT == ORTEmpty) { |
|
33 SECItemArray* arr = SECITEM_AllocArray(aArena, nullptr, 1); |
|
34 arr->items[0].data = nullptr; |
|
35 arr->items[0].len = 0; |
|
36 return arr; |
|
37 } |
|
38 |
|
39 PRTime now = PR_Now(); |
|
40 PRTime oneDay = 60*60*24 * (PRTime)PR_USEC_PER_SEC; |
|
41 PRTime oldNow = now - (8 * oneDay); |
|
42 |
|
43 OCSPResponseContext context(aArena, aCert, now); |
|
44 |
|
45 if (aORT == ORTGoodOtherCert) { |
|
46 context.cert = PK11_FindCertFromNickname(aAdditionalCertName, nullptr); |
|
47 if (!context.cert) { |
|
48 PrintPRError("PK11_FindCertFromNickname failed"); |
|
49 return nullptr; |
|
50 } |
|
51 } |
|
52 // XXX CERT_FindCertIssuer uses the old, deprecated path-building logic |
|
53 context.issuerCert = CERT_FindCertIssuer(aCert, now, certUsageSSLCA); |
|
54 if (!context.issuerCert) { |
|
55 PrintPRError("CERT_FindCertIssuer failed"); |
|
56 return nullptr; |
|
57 } |
|
58 if (aORT == ORTGoodOtherCA || aORT == ORTDelegatedIncluded || |
|
59 aORT == ORTDelegatedIncludedLast || aORT == ORTDelegatedMissing || |
|
60 aORT == ORTDelegatedMissingMultiple) { |
|
61 context.signerCert = PK11_FindCertFromNickname(aAdditionalCertName, |
|
62 nullptr); |
|
63 if (!context.signerCert) { |
|
64 PrintPRError("PK11_FindCertFromNickname failed"); |
|
65 return nullptr; |
|
66 } |
|
67 } |
|
68 if (aORT == ORTDelegatedIncluded) { |
|
69 context.includedCertificates[0] = |
|
70 CERT_DupCertificate(context.signerCert.get()); |
|
71 } |
|
72 if (aORT == ORTDelegatedIncludedLast || aORT == ORTDelegatedMissingMultiple) { |
|
73 context.includedCertificates[0] = |
|
74 CERT_DupCertificate(context.issuerCert.get()); |
|
75 context.includedCertificates[1] = CERT_DupCertificate(context.cert.get()); |
|
76 context.includedCertificates[2] = |
|
77 CERT_DupCertificate(context.issuerCert.get()); |
|
78 if (aORT != ORTDelegatedMissingMultiple) { |
|
79 context.includedCertificates[3] = |
|
80 CERT_DupCertificate(context.signerCert.get()); |
|
81 } |
|
82 } |
|
83 switch (aORT) { |
|
84 case ORTMalformed: |
|
85 context.responseStatus = 1; |
|
86 break; |
|
87 case ORTSrverr: |
|
88 context.responseStatus = 2; |
|
89 break; |
|
90 case ORTTryLater: |
|
91 context.responseStatus = 3; |
|
92 break; |
|
93 case ORTNeedsSig: |
|
94 context.responseStatus = 5; |
|
95 break; |
|
96 case ORTUnauthorized: |
|
97 context.responseStatus = 6; |
|
98 break; |
|
99 default: |
|
100 // context.responseStatus is 0 in all other cases, and it has |
|
101 // already been initialized in the constructor. |
|
102 break; |
|
103 } |
|
104 if (aORT == ORTSkipResponseBytes) { |
|
105 context.skipResponseBytes = true; |
|
106 } |
|
107 if (aORT == ORTExpired || aORT == ORTExpiredFreshCA || |
|
108 aORT == ORTRevokedOld || aORT == ORTUnknownOld) { |
|
109 context.thisUpdate = oldNow; |
|
110 context.nextUpdate = oldNow + 10 * PR_USEC_PER_SEC; |
|
111 } |
|
112 if (aORT == ORTLongValidityAlmostExpired) { |
|
113 context.thisUpdate = now - (320 * oneDay); |
|
114 } |
|
115 if (aORT == ORTAncientAlmostExpired) { |
|
116 context.thisUpdate = now - (640 * oneDay); |
|
117 } |
|
118 if (aORT == ORTRevoked || aORT == ORTRevokedOld) { |
|
119 context.certStatus = 1; |
|
120 } |
|
121 if (aORT == ORTUnknown || aORT == ORTUnknownOld) { |
|
122 context.certStatus = 2; |
|
123 } |
|
124 if (aORT == ORTBadSignature) { |
|
125 context.badSignature = true; |
|
126 } |
|
127 OCSPResponseExtension extension; |
|
128 if (aORT == ORTCriticalExtension || aORT == ORTNoncriticalExtension) { |
|
129 SECItem oidItem = { |
|
130 siBuffer, |
|
131 nullptr, |
|
132 0 |
|
133 }; |
|
134 // 1.3.6.1.4.1.13769.666.666.666 is the root of Mozilla's testing OID space |
|
135 static const char* testExtensionOID = "1.3.6.1.4.1.13769.666.666.666.1.500.9.2"; |
|
136 if (SEC_StringToOID(aArena, &oidItem, testExtensionOID, |
|
137 PL_strlen(testExtensionOID)) != SECSuccess) { |
|
138 return nullptr; |
|
139 } |
|
140 DERTemplate oidTemplate[2] = { { DER_OBJECT_ID, 0 }, { 0 } }; |
|
141 extension.id.data = nullptr; |
|
142 extension.id.len = 0; |
|
143 if (DER_Encode(aArena, &extension.id, oidTemplate, &oidItem) |
|
144 != SECSuccess) { |
|
145 return nullptr; |
|
146 } |
|
147 extension.critical = (aORT == ORTCriticalExtension); |
|
148 static const uint8_t value[2] = { 0x05, 0x00 }; |
|
149 extension.value.data = const_cast<uint8_t*>(value); |
|
150 extension.value.len = PR_ARRAY_SIZE(value); |
|
151 extension.next = nullptr; |
|
152 context.extensions = &extension; |
|
153 } |
|
154 if (aORT == ORTEmptyExtensions) { |
|
155 context.includeEmptyExtensions = true; |
|
156 } |
|
157 |
|
158 if (!context.signerCert) { |
|
159 context.signerCert = CERT_DupCertificate(context.issuerCert.get()); |
|
160 } |
|
161 |
|
162 SECItem* response = CreateEncodedOCSPResponse(context); |
|
163 if (!response) { |
|
164 PrintPRError("CreateEncodedOCSPResponse failed"); |
|
165 return nullptr; |
|
166 } |
|
167 |
|
168 SECItemArray* arr = SECITEM_AllocArray(aArena, nullptr, 1); |
|
169 if (!arr) { |
|
170 PrintPRError("SECITEM_AllocArray failed"); |
|
171 return nullptr; |
|
172 } |
|
173 arr->items[0].data = response->data; |
|
174 arr->items[0].len = response->len; |
|
175 |
|
176 return arr; |
|
177 } |