Mercurial > trustbridge > nss-cmake-static
comparison nss/lib/certhigh/ocspsig.c @ 0:1e5118fa0cb1
This is NSS with a Cmake Buildsyste
To compile a static NSS library for Windows we've used the
Chromium-NSS fork and added a Cmake buildsystem to compile
it statically for Windows. See README.chromium for chromium
changes and README.trustbridge for our modifications.
author | Andre Heinecke <andre.heinecke@intevation.de> |
---|---|
date | Mon, 28 Jul 2014 10:47:06 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:1e5118fa0cb1 |
---|---|
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 "plarena.h" | |
6 | |
7 #include "seccomon.h" | |
8 #include "secitem.h" | |
9 #include "secasn1.h" | |
10 #include "secder.h" | |
11 #include "cert.h" | |
12 #include "secerr.h" | |
13 #include "secoid.h" | |
14 #include "sechash.h" | |
15 #include "keyhi.h" | |
16 #include "cryptohi.h" | |
17 #include "ocsp.h" | |
18 #include "ocspti.h" | |
19 #include "ocspi.h" | |
20 #include "pk11pub.h" | |
21 | |
22 | |
23 extern const SEC_ASN1Template ocsp_ResponderIDByNameTemplate[]; | |
24 extern const SEC_ASN1Template ocsp_ResponderIDByKeyTemplate[]; | |
25 extern const SEC_ASN1Template ocsp_OCSPResponseTemplate[]; | |
26 | |
27 ocspCertStatus* | |
28 ocsp_CreateCertStatus(PLArenaPool *arena, | |
29 ocspCertStatusType status, | |
30 PRTime revocationTime) | |
31 { | |
32 ocspCertStatus *cs; | |
33 | |
34 if (!arena) { | |
35 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
36 return NULL; | |
37 } | |
38 | |
39 switch (status) { | |
40 case ocspCertStatus_good: | |
41 case ocspCertStatus_unknown: | |
42 case ocspCertStatus_revoked: | |
43 break; | |
44 default: | |
45 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
46 return NULL; | |
47 } | |
48 | |
49 cs = PORT_ArenaZNew(arena, ocspCertStatus); | |
50 if (!cs) | |
51 return NULL; | |
52 cs->certStatusType = status; | |
53 switch (status) { | |
54 case ocspCertStatus_good: | |
55 cs->certStatusInfo.goodInfo = SECITEM_AllocItem(arena, NULL, 0); | |
56 if (!cs->certStatusInfo.goodInfo) | |
57 return NULL; | |
58 break; | |
59 case ocspCertStatus_unknown: | |
60 cs->certStatusInfo.unknownInfo = SECITEM_AllocItem(arena, NULL, 0); | |
61 if (!cs->certStatusInfo.unknownInfo) | |
62 return NULL; | |
63 break; | |
64 case ocspCertStatus_revoked: | |
65 cs->certStatusInfo.revokedInfo = | |
66 PORT_ArenaZNew(arena, ocspRevokedInfo); | |
67 if (!cs->certStatusInfo.revokedInfo) | |
68 return NULL; | |
69 cs->certStatusInfo.revokedInfo->revocationReason = | |
70 SECITEM_AllocItem(arena, NULL, 0); | |
71 if (!cs->certStatusInfo.revokedInfo->revocationReason) | |
72 return NULL; | |
73 if (DER_TimeToGeneralizedTimeArena(arena, | |
74 &cs->certStatusInfo.revokedInfo->revocationTime, | |
75 revocationTime) != SECSuccess) | |
76 return NULL; | |
77 break; | |
78 default: | |
79 PORT_Assert(PR_FALSE); | |
80 } | |
81 return cs; | |
82 } | |
83 | |
84 static const SEC_ASN1Template mySEC_EnumeratedTemplate[] = { | |
85 { SEC_ASN1_ENUMERATED, 0, NULL, sizeof(SECItem) } | |
86 }; | |
87 | |
88 static const SEC_ASN1Template mySEC_PointerToEnumeratedTemplate[] = { | |
89 { SEC_ASN1_POINTER, 0, mySEC_EnumeratedTemplate } | |
90 }; | |
91 | |
92 static const SEC_ASN1Template ocsp_EncodeRevokedInfoTemplate[] = { | |
93 { SEC_ASN1_GENERALIZED_TIME, | |
94 offsetof(ocspRevokedInfo, revocationTime) }, | |
95 { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | | |
96 SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC| 0, | |
97 offsetof(ocspRevokedInfo, revocationReason), | |
98 mySEC_PointerToEnumeratedTemplate }, | |
99 { 0 } | |
100 }; | |
101 | |
102 static const SEC_ASN1Template ocsp_PointerToEncodeRevokedInfoTemplate[] = { | |
103 { SEC_ASN1_POINTER, 0, | |
104 ocsp_EncodeRevokedInfoTemplate } | |
105 }; | |
106 | |
107 static const SEC_ASN1Template mySEC_NullTemplate[] = { | |
108 { SEC_ASN1_NULL, 0, NULL, sizeof(SECItem) } | |
109 }; | |
110 | |
111 static const SEC_ASN1Template ocsp_CertStatusTemplate[] = { | |
112 { SEC_ASN1_CHOICE, offsetof(ocspCertStatus, certStatusType), | |
113 0, sizeof(ocspCertStatus) }, | |
114 { SEC_ASN1_CONTEXT_SPECIFIC | 0, | |
115 0, mySEC_NullTemplate, ocspCertStatus_good }, | |
116 { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | | |
117 SEC_ASN1_CONTEXT_SPECIFIC | 1, | |
118 offsetof(ocspCertStatus, certStatusInfo.revokedInfo), | |
119 ocsp_PointerToEncodeRevokedInfoTemplate, ocspCertStatus_revoked }, | |
120 { SEC_ASN1_CONTEXT_SPECIFIC | 2, | |
121 0, mySEC_NullTemplate, ocspCertStatus_unknown }, | |
122 { 0 } | |
123 }; | |
124 | |
125 static const SEC_ASN1Template mySECOID_AlgorithmIDTemplate[] = { | |
126 { SEC_ASN1_SEQUENCE, | |
127 0, NULL, sizeof(SECAlgorithmID) }, | |
128 { SEC_ASN1_OBJECT_ID, | |
129 offsetof(SECAlgorithmID,algorithm), }, | |
130 { SEC_ASN1_OPTIONAL | SEC_ASN1_ANY, | |
131 offsetof(SECAlgorithmID,parameters), }, | |
132 { 0, } | |
133 }; | |
134 | |
135 static const SEC_ASN1Template mySEC_AnyTemplate[] = { | |
136 { SEC_ASN1_ANY | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem) } | |
137 }; | |
138 | |
139 static const SEC_ASN1Template mySEC_SequenceOfAnyTemplate[] = { | |
140 { SEC_ASN1_SEQUENCE_OF, 0, mySEC_AnyTemplate } | |
141 }; | |
142 | |
143 static const SEC_ASN1Template mySEC_PointerToSequenceOfAnyTemplate[] = { | |
144 { SEC_ASN1_POINTER, 0, mySEC_SequenceOfAnyTemplate } | |
145 }; | |
146 | |
147 static const SEC_ASN1Template mySEC_IntegerTemplate[] = { | |
148 { SEC_ASN1_INTEGER, 0, NULL, sizeof(SECItem) } | |
149 }; | |
150 | |
151 static const SEC_ASN1Template mySEC_PointerToIntegerTemplate[] = { | |
152 { SEC_ASN1_POINTER, 0, mySEC_IntegerTemplate } | |
153 }; | |
154 | |
155 static const SEC_ASN1Template mySEC_GeneralizedTimeTemplate[] = { | |
156 { SEC_ASN1_GENERALIZED_TIME | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem)} | |
157 }; | |
158 | |
159 static const SEC_ASN1Template mySEC_PointerToGeneralizedTimeTemplate[] = { | |
160 { SEC_ASN1_POINTER, 0, mySEC_GeneralizedTimeTemplate } | |
161 }; | |
162 | |
163 static const SEC_ASN1Template ocsp_myCertIDTemplate[] = { | |
164 { SEC_ASN1_SEQUENCE, | |
165 0, NULL, sizeof(CERTOCSPCertID) }, | |
166 { SEC_ASN1_INLINE, | |
167 offsetof(CERTOCSPCertID, hashAlgorithm), | |
168 mySECOID_AlgorithmIDTemplate }, | |
169 { SEC_ASN1_OCTET_STRING, | |
170 offsetof(CERTOCSPCertID, issuerNameHash) }, | |
171 { SEC_ASN1_OCTET_STRING, | |
172 offsetof(CERTOCSPCertID, issuerKeyHash) }, | |
173 { SEC_ASN1_INTEGER, | |
174 offsetof(CERTOCSPCertID, serialNumber) }, | |
175 { 0 } | |
176 }; | |
177 | |
178 static const SEC_ASN1Template myCERT_CertExtensionTemplate[] = { | |
179 { SEC_ASN1_SEQUENCE, | |
180 0, NULL, sizeof(CERTCertExtension) }, | |
181 { SEC_ASN1_OBJECT_ID, | |
182 offsetof(CERTCertExtension,id) }, | |
183 { SEC_ASN1_OPTIONAL | SEC_ASN1_BOOLEAN, /* XXX DER_DEFAULT */ | |
184 offsetof(CERTCertExtension,critical) }, | |
185 { SEC_ASN1_OCTET_STRING, | |
186 offsetof(CERTCertExtension,value) }, | |
187 { 0, } | |
188 }; | |
189 | |
190 static const SEC_ASN1Template myCERT_SequenceOfCertExtensionTemplate[] = { | |
191 { SEC_ASN1_SEQUENCE_OF, 0, myCERT_CertExtensionTemplate } | |
192 }; | |
193 | |
194 static const SEC_ASN1Template myCERT_PointerToSequenceOfCertExtensionTemplate[] = { | |
195 { SEC_ASN1_POINTER, 0, myCERT_SequenceOfCertExtensionTemplate } | |
196 }; | |
197 | |
198 static const SEC_ASN1Template ocsp_mySingleResponseTemplate[] = { | |
199 { SEC_ASN1_SEQUENCE, | |
200 0, NULL, sizeof(CERTOCSPSingleResponse) }, | |
201 { SEC_ASN1_POINTER, | |
202 offsetof(CERTOCSPSingleResponse, certID), | |
203 ocsp_myCertIDTemplate }, | |
204 { SEC_ASN1_ANY, | |
205 offsetof(CERTOCSPSingleResponse, derCertStatus) }, | |
206 { SEC_ASN1_GENERALIZED_TIME, | |
207 offsetof(CERTOCSPSingleResponse, thisUpdate) }, | |
208 { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | | |
209 SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, | |
210 offsetof(CERTOCSPSingleResponse, nextUpdate), | |
211 mySEC_PointerToGeneralizedTimeTemplate }, | |
212 { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | | |
213 SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1, | |
214 offsetof(CERTOCSPSingleResponse, singleExtensions), | |
215 myCERT_PointerToSequenceOfCertExtensionTemplate }, | |
216 { 0 } | |
217 }; | |
218 | |
219 static const SEC_ASN1Template ocsp_myResponseDataTemplate[] = { | |
220 { SEC_ASN1_SEQUENCE, | |
221 0, NULL, sizeof(ocspResponseData) }, | |
222 { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | /* XXX DER_DEFAULT */ | |
223 SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, | |
224 offsetof(ocspResponseData, version), | |
225 mySEC_PointerToIntegerTemplate }, | |
226 { SEC_ASN1_ANY, | |
227 offsetof(ocspResponseData, derResponderID) }, | |
228 { SEC_ASN1_GENERALIZED_TIME, | |
229 offsetof(ocspResponseData, producedAt) }, | |
230 { SEC_ASN1_SEQUENCE_OF, | |
231 offsetof(ocspResponseData, responses), | |
232 ocsp_mySingleResponseTemplate }, | |
233 { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | | |
234 SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1, | |
235 offsetof(ocspResponseData, responseExtensions), | |
236 myCERT_PointerToSequenceOfCertExtensionTemplate }, | |
237 { 0 } | |
238 }; | |
239 | |
240 | |
241 static const SEC_ASN1Template ocsp_EncodeBasicOCSPResponseTemplate[] = { | |
242 { SEC_ASN1_SEQUENCE, | |
243 0, NULL, sizeof(ocspBasicOCSPResponse) }, | |
244 { SEC_ASN1_POINTER, | |
245 offsetof(ocspBasicOCSPResponse, tbsResponseData), | |
246 ocsp_myResponseDataTemplate }, | |
247 { SEC_ASN1_INLINE, | |
248 offsetof(ocspBasicOCSPResponse, responseSignature.signatureAlgorithm), | |
249 mySECOID_AlgorithmIDTemplate }, | |
250 { SEC_ASN1_BIT_STRING, | |
251 offsetof(ocspBasicOCSPResponse, responseSignature.signature) }, | |
252 { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | | |
253 SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, | |
254 offsetof(ocspBasicOCSPResponse, responseSignature.derCerts), | |
255 mySEC_PointerToSequenceOfAnyTemplate }, | |
256 { 0 } | |
257 }; | |
258 | |
259 static CERTOCSPSingleResponse* | |
260 ocsp_CreateSingleResponse(PLArenaPool *arena, | |
261 CERTOCSPCertID *id, ocspCertStatus *status, | |
262 PRTime thisUpdate, const PRTime *nextUpdate) | |
263 { | |
264 CERTOCSPSingleResponse *sr; | |
265 | |
266 if (!arena || !id || !status) { | |
267 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
268 return NULL; | |
269 } | |
270 | |
271 sr = PORT_ArenaZNew(arena, CERTOCSPSingleResponse); | |
272 if (!sr) | |
273 return NULL; | |
274 sr->arena = arena; | |
275 sr->certID = id; | |
276 sr->certStatus = status; | |
277 if (DER_TimeToGeneralizedTimeArena(arena, &sr->thisUpdate, thisUpdate) | |
278 != SECSuccess) | |
279 return NULL; | |
280 sr->nextUpdate = NULL; | |
281 if (nextUpdate) { | |
282 sr->nextUpdate = SECITEM_AllocItem(arena, NULL, 0); | |
283 if (!sr->nextUpdate) | |
284 return NULL; | |
285 if (DER_TimeToGeneralizedTimeArena(arena, sr->nextUpdate, *nextUpdate) | |
286 != SECSuccess) | |
287 return NULL; | |
288 } | |
289 | |
290 sr->singleExtensions = PORT_ArenaNewArray(arena, CERTCertExtension*, 1); | |
291 if (!sr->singleExtensions) | |
292 return NULL; | |
293 | |
294 sr->singleExtensions[0] = NULL; | |
295 | |
296 if (!SEC_ASN1EncodeItem(arena, &sr->derCertStatus, | |
297 status, ocsp_CertStatusTemplate)) | |
298 return NULL; | |
299 | |
300 return sr; | |
301 } | |
302 | |
303 CERTOCSPSingleResponse* | |
304 CERT_CreateOCSPSingleResponseGood(PLArenaPool *arena, | |
305 CERTOCSPCertID *id, | |
306 PRTime thisUpdate, | |
307 const PRTime *nextUpdate) | |
308 { | |
309 ocspCertStatus * cs; | |
310 if (!arena) { | |
311 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
312 return NULL; | |
313 } | |
314 cs = ocsp_CreateCertStatus(arena, ocspCertStatus_good, 0); | |
315 if (!cs) | |
316 return NULL; | |
317 return ocsp_CreateSingleResponse(arena, id, cs, thisUpdate, nextUpdate); | |
318 } | |
319 | |
320 CERTOCSPSingleResponse* | |
321 CERT_CreateOCSPSingleResponseUnknown(PLArenaPool *arena, | |
322 CERTOCSPCertID *id, | |
323 PRTime thisUpdate, | |
324 const PRTime *nextUpdate) | |
325 { | |
326 ocspCertStatus * cs; | |
327 if (!arena) { | |
328 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
329 return NULL; | |
330 } | |
331 cs = ocsp_CreateCertStatus(arena, ocspCertStatus_unknown, 0); | |
332 if (!cs) | |
333 return NULL; | |
334 return ocsp_CreateSingleResponse(arena, id, cs, thisUpdate, nextUpdate); | |
335 } | |
336 | |
337 CERTOCSPSingleResponse* | |
338 CERT_CreateOCSPSingleResponseRevoked( | |
339 PLArenaPool *arena, | |
340 CERTOCSPCertID *id, | |
341 PRTime thisUpdate, | |
342 const PRTime *nextUpdate, | |
343 PRTime revocationTime, | |
344 const CERTCRLEntryReasonCode* revocationReason) | |
345 { | |
346 ocspCertStatus * cs; | |
347 /* revocationReason is not yet supported, so it must be NULL. */ | |
348 if (!arena || revocationReason) { | |
349 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
350 return NULL; | |
351 } | |
352 cs = ocsp_CreateCertStatus(arena, ocspCertStatus_revoked, revocationTime); | |
353 if (!cs) | |
354 return NULL; | |
355 return ocsp_CreateSingleResponse(arena, id, cs, thisUpdate, nextUpdate); | |
356 } | |
357 | |
358 /* responderCert == 0 means: | |
359 * create a response with an invalid signature (for testing purposes) */ | |
360 SECItem* | |
361 CERT_CreateEncodedOCSPSuccessResponse( | |
362 PLArenaPool *arena, | |
363 CERTCertificate *responderCert, | |
364 CERTOCSPResponderIDType responderIDType, | |
365 PRTime producedAt, | |
366 CERTOCSPSingleResponse **responses, | |
367 void *wincx) | |
368 { | |
369 PLArenaPool *tmpArena; | |
370 ocspResponseData *rd = NULL; | |
371 ocspResponderID *rid = NULL; | |
372 const SEC_ASN1Template *responderIDTemplate = NULL; | |
373 ocspBasicOCSPResponse *br = NULL; | |
374 ocspResponseBytes *rb = NULL; | |
375 CERTOCSPResponse *response = NULL; | |
376 | |
377 SECOidTag algID; | |
378 SECOidData *od = NULL; | |
379 SECKEYPrivateKey *privKey = NULL; | |
380 SECItem *result = NULL; | |
381 | |
382 if (!arena || !responses) { | |
383 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
384 return NULL; | |
385 } | |
386 if (responderIDType != ocspResponderID_byName && | |
387 responderIDType != ocspResponderID_byKey) { | |
388 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
389 return NULL; | |
390 } | |
391 | |
392 tmpArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | |
393 if (!tmpArena) | |
394 return NULL; | |
395 | |
396 rd = PORT_ArenaZNew(tmpArena, ocspResponseData); | |
397 if (!rd) | |
398 goto done; | |
399 rid = PORT_ArenaZNew(tmpArena, ocspResponderID); | |
400 if (!rid) | |
401 goto done; | |
402 br = PORT_ArenaZNew(tmpArena, ocspBasicOCSPResponse); | |
403 if (!br) | |
404 goto done; | |
405 rb = PORT_ArenaZNew(tmpArena, ocspResponseBytes); | |
406 if (!rb) | |
407 goto done; | |
408 response = PORT_ArenaZNew(tmpArena, CERTOCSPResponse); | |
409 if (!response) | |
410 goto done; | |
411 | |
412 rd->version.data=NULL; | |
413 rd->version.len=0; | |
414 rd->responseExtensions = NULL; | |
415 rd->responses = responses; | |
416 if (DER_TimeToGeneralizedTimeArena(tmpArena, &rd->producedAt, producedAt) | |
417 != SECSuccess) | |
418 goto done; | |
419 | |
420 if (!responderCert) { | |
421 /* use invalid signature for testing purposes */ | |
422 unsigned char dummyChar = 'd'; | |
423 SECItem dummy; | |
424 | |
425 dummy.len = 1; | |
426 dummy.data = &dummyChar; | |
427 | |
428 /* it's easier to produdce a keyHash out of nowhere, | |
429 * than to produce an encoded subject, | |
430 * so for our dummy response we always use byKey | |
431 */ | |
432 | |
433 rid->responderIDType = ocspResponderID_byKey; | |
434 if (!ocsp_DigestValue(tmpArena, SEC_OID_SHA1, &rid->responderIDValue.keyHash, | |
435 &dummy)) | |
436 goto done; | |
437 | |
438 if (!SEC_ASN1EncodeItem(tmpArena, &rd->derResponderID, rid, | |
439 ocsp_ResponderIDByKeyTemplate)) | |
440 goto done; | |
441 | |
442 br->tbsResponseData = rd; | |
443 | |
444 if (!SEC_ASN1EncodeItem(tmpArena, &br->tbsResponseDataDER, br->tbsResponseData, | |
445 ocsp_myResponseDataTemplate)) | |
446 goto done; | |
447 | |
448 br->responseSignature.derCerts = PORT_ArenaNewArray(tmpArena, SECItem*, 1); | |
449 if (!br->responseSignature.derCerts) | |
450 goto done; | |
451 br->responseSignature.derCerts[0] = NULL; | |
452 | |
453 algID = SEC_GetSignatureAlgorithmOidTag(rsaKey, SEC_OID_SHA1); | |
454 if (algID == SEC_OID_UNKNOWN) | |
455 goto done; | |
456 | |
457 /* match the regular signature code, which doesn't use the arena */ | |
458 if (!SECITEM_AllocItem(NULL, &br->responseSignature.signature, 1)) | |
459 goto done; | |
460 PORT_Memcpy(br->responseSignature.signature.data, &dummyChar, 1); | |
461 | |
462 /* convert len-in-bytes to len-in-bits */ | |
463 br->responseSignature.signature.len = br->responseSignature.signature.len << 3; | |
464 } | |
465 else { | |
466 rid->responderIDType = responderIDType; | |
467 if (responderIDType == ocspResponderID_byName) { | |
468 responderIDTemplate = ocsp_ResponderIDByNameTemplate; | |
469 if (CERT_CopyName(tmpArena, &rid->responderIDValue.name, | |
470 &responderCert->subject) != SECSuccess) | |
471 goto done; | |
472 } | |
473 else { | |
474 responderIDTemplate = ocsp_ResponderIDByKeyTemplate; | |
475 if (!CERT_GetSubjectPublicKeyDigest(tmpArena, responderCert, | |
476 SEC_OID_SHA1, &rid->responderIDValue.keyHash)) | |
477 goto done; | |
478 } | |
479 | |
480 if (!SEC_ASN1EncodeItem(tmpArena, &rd->derResponderID, rid, | |
481 responderIDTemplate)) | |
482 goto done; | |
483 | |
484 br->tbsResponseData = rd; | |
485 | |
486 if (!SEC_ASN1EncodeItem(tmpArena, &br->tbsResponseDataDER, br->tbsResponseData, | |
487 ocsp_myResponseDataTemplate)) | |
488 goto done; | |
489 | |
490 br->responseSignature.derCerts = PORT_ArenaNewArray(tmpArena, SECItem*, 1); | |
491 if (!br->responseSignature.derCerts) | |
492 goto done; | |
493 br->responseSignature.derCerts[0] = NULL; | |
494 | |
495 privKey = PK11_FindKeyByAnyCert(responderCert, wincx); | |
496 if (!privKey) | |
497 goto done; | |
498 | |
499 algID = SEC_GetSignatureAlgorithmOidTag(privKey->keyType, SEC_OID_SHA1); | |
500 if (algID == SEC_OID_UNKNOWN) | |
501 goto done; | |
502 | |
503 if (SEC_SignData(&br->responseSignature.signature, | |
504 br->tbsResponseDataDER.data, br->tbsResponseDataDER.len, | |
505 privKey, algID) | |
506 != SECSuccess) | |
507 goto done; | |
508 | |
509 /* convert len-in-bytes to len-in-bits */ | |
510 br->responseSignature.signature.len = br->responseSignature.signature.len << 3; | |
511 | |
512 /* br->responseSignature.signature wasn't allocated from arena, | |
513 * we must free it when done. */ | |
514 } | |
515 | |
516 if (SECOID_SetAlgorithmID(tmpArena, &br->responseSignature.signatureAlgorithm, algID, 0) | |
517 != SECSuccess) | |
518 goto done; | |
519 | |
520 if (!SEC_ASN1EncodeItem(tmpArena, &rb->response, br, | |
521 ocsp_EncodeBasicOCSPResponseTemplate)) | |
522 goto done; | |
523 | |
524 rb->responseTypeTag = SEC_OID_PKIX_OCSP_BASIC_RESPONSE; | |
525 | |
526 od = SECOID_FindOIDByTag(rb->responseTypeTag); | |
527 if (!od) | |
528 goto done; | |
529 | |
530 rb->responseType = od->oid; | |
531 rb->decodedResponse.basic = br; | |
532 | |
533 response->arena = tmpArena; | |
534 response->responseBytes = rb; | |
535 response->statusValue = ocspResponse_successful; | |
536 | |
537 if (!SEC_ASN1EncodeInteger(tmpArena, &response->responseStatus, | |
538 response->statusValue)) | |
539 goto done; | |
540 | |
541 result = SEC_ASN1EncodeItem(arena, NULL, response, ocsp_OCSPResponseTemplate); | |
542 | |
543 done: | |
544 if (privKey) | |
545 SECKEY_DestroyPrivateKey(privKey); | |
546 if (br->responseSignature.signature.data) | |
547 SECITEM_FreeItem(&br->responseSignature.signature, PR_FALSE); | |
548 PORT_FreeArena(tmpArena, PR_FALSE); | |
549 | |
550 return result; | |
551 } | |
552 | |
553 static const SEC_ASN1Template ocsp_OCSPErrorResponseTemplate[] = { | |
554 { SEC_ASN1_SEQUENCE, | |
555 0, NULL, sizeof(CERTOCSPResponse) }, | |
556 { SEC_ASN1_ENUMERATED, | |
557 offsetof(CERTOCSPResponse, responseStatus) }, | |
558 { 0, 0, | |
559 mySEC_NullTemplate }, | |
560 { 0 } | |
561 }; | |
562 | |
563 SECItem* | |
564 CERT_CreateEncodedOCSPErrorResponse(PLArenaPool *arena, int error) | |
565 { | |
566 CERTOCSPResponse response; | |
567 SECItem *result = NULL; | |
568 | |
569 switch (error) { | |
570 case SEC_ERROR_OCSP_MALFORMED_REQUEST: | |
571 response.statusValue = ocspResponse_malformedRequest; | |
572 break; | |
573 case SEC_ERROR_OCSP_SERVER_ERROR: | |
574 response.statusValue = ocspResponse_internalError; | |
575 break; | |
576 case SEC_ERROR_OCSP_TRY_SERVER_LATER: | |
577 response.statusValue = ocspResponse_tryLater; | |
578 break; | |
579 case SEC_ERROR_OCSP_REQUEST_NEEDS_SIG: | |
580 response.statusValue = ocspResponse_sigRequired; | |
581 break; | |
582 case SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST: | |
583 response.statusValue = ocspResponse_unauthorized; | |
584 break; | |
585 default: | |
586 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
587 return NULL; | |
588 } | |
589 | |
590 if (!SEC_ASN1EncodeInteger(NULL, &response.responseStatus, | |
591 response.statusValue)) | |
592 return NULL; | |
593 | |
594 result = SEC_ASN1EncodeItem(arena, NULL, &response, | |
595 ocsp_OCSPErrorResponseTemplate); | |
596 | |
597 SECITEM_FreeItem(&response.responseStatus, PR_FALSE); | |
598 | |
599 return result; | |
600 } |