comparison nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocspresponse.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 * pkix_pl_ocspresponse.c
6 *
7 */
8
9 #include "pkix_pl_ocspresponse.h"
10
11 /* ----Public functions------------------------------------- */
12 /*
13 * This is the libpkix replacement for CERT_VerifyOCSPResponseSignature.
14 * It is used if it has been set as the verifyFcn member of ocspChecker.
15 */
16 PKIX_Error *
17 PKIX_PL_OcspResponse_UseBuildChain(
18 PKIX_PL_Cert *signerCert,
19 PKIX_PL_Date *producedAt,
20 PKIX_ProcessingParams *procParams,
21 void **pNBIOContext,
22 void **pState,
23 PKIX_BuildResult **pBuildResult,
24 PKIX_VerifyNode **pVerifyTree,
25 void *plContext)
26 {
27 PKIX_ProcessingParams *caProcParams = NULL;
28 PKIX_PL_Date *date = NULL;
29 PKIX_ComCertSelParams *certSelParams = NULL;
30 PKIX_CertSelector *certSelector = NULL;
31 void *nbioContext = NULL;
32 PKIX_Error *buildError = NULL;
33
34 PKIX_ENTER(OCSPRESPONSE, "pkix_OcspResponse_UseBuildChain");
35 PKIX_NULLCHECK_THREE(signerCert, producedAt, procParams);
36 PKIX_NULLCHECK_THREE(pNBIOContext, pState, pBuildResult);
37
38 nbioContext = *pNBIOContext;
39 *pNBIOContext = NULL;
40
41 /* Are we resuming after a WOULDBLOCK return, or starting anew ? */
42 if (nbioContext == NULL) {
43 /* Starting anew */
44 PKIX_CHECK(PKIX_PL_Object_Duplicate
45 ((PKIX_PL_Object *)procParams,
46 (PKIX_PL_Object **)&caProcParams,
47 plContext),
48 PKIX_OBJECTDUPLICATEFAILED);
49
50 PKIX_CHECK(PKIX_ProcessingParams_SetDate(procParams, date, plContext),
51 PKIX_PROCESSINGPARAMSSETDATEFAILED);
52
53 /* create CertSelector with target certificate in params */
54
55 PKIX_CHECK(PKIX_CertSelector_Create
56 (NULL, NULL, &certSelector, plContext),
57 PKIX_CERTSELECTORCREATEFAILED);
58
59 PKIX_CHECK(PKIX_ComCertSelParams_Create
60 (&certSelParams, plContext),
61 PKIX_COMCERTSELPARAMSCREATEFAILED);
62
63 PKIX_CHECK(PKIX_ComCertSelParams_SetCertificate
64 (certSelParams, signerCert, plContext),
65 PKIX_COMCERTSELPARAMSSETCERTIFICATEFAILED);
66
67 PKIX_CHECK(PKIX_CertSelector_SetCommonCertSelectorParams
68 (certSelector, certSelParams, plContext),
69 PKIX_CERTSELECTORSETCOMMONCERTSELECTORPARAMSFAILED);
70
71 PKIX_CHECK(PKIX_ProcessingParams_SetTargetCertConstraints
72 (caProcParams, certSelector, plContext),
73 PKIX_PROCESSINGPARAMSSETTARGETCERTCONSTRAINTSFAILED);
74 }
75
76 buildError = PKIX_BuildChain
77 (caProcParams,
78 &nbioContext,
79 pState,
80 pBuildResult,
81 pVerifyTree,
82 plContext);
83
84 /* non-null nbioContext means the build would block */
85 if (nbioContext != NULL) {
86
87 *pNBIOContext = nbioContext;
88
89 /* no buildResult means the build has failed */
90 } else if (buildError) {
91 pkixErrorResult = buildError;
92 buildError = NULL;
93 } else {
94 PKIX_DECREF(*pState);
95 }
96
97 cleanup:
98
99 PKIX_DECREF(caProcParams);
100 PKIX_DECREF(date);
101 PKIX_DECREF(certSelParams);
102 PKIX_DECREF(certSelector);
103
104 PKIX_RETURN(OCSPRESPONSE);
105 }
106
107 /* --Private-OcspResponse-Functions------------------------------------- */
108
109 /*
110 * FUNCTION: pkix_pl_OcspResponse_Destroy
111 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
112 */
113 static PKIX_Error *
114 pkix_pl_OcspResponse_Destroy(
115 PKIX_PL_Object *object,
116 void *plContext)
117 {
118 PKIX_PL_OcspResponse *ocspRsp = NULL;
119 const SEC_HttpClientFcn *httpClient = NULL;
120 const SEC_HttpClientFcnV1 *hcv1 = NULL;
121
122 PKIX_ENTER(OCSPRESPONSE, "pkix_pl_OcspResponse_Destroy");
123 PKIX_NULLCHECK_ONE(object);
124
125 PKIX_CHECK(pkix_CheckType(object, PKIX_OCSPRESPONSE_TYPE, plContext),
126 PKIX_OBJECTNOTANOCSPRESPONSE);
127
128 ocspRsp = (PKIX_PL_OcspResponse *)object;
129
130 if (ocspRsp->nssOCSPResponse != NULL) {
131 CERT_DestroyOCSPResponse(ocspRsp->nssOCSPResponse);
132 ocspRsp->nssOCSPResponse = NULL;
133 }
134
135 if (ocspRsp->signerCert != NULL) {
136 CERT_DestroyCertificate(ocspRsp->signerCert);
137 ocspRsp->signerCert = NULL;
138 }
139
140 httpClient = (const SEC_HttpClientFcn *)(ocspRsp->httpClient);
141
142 if (httpClient && (httpClient->version == 1)) {
143
144 hcv1 = &(httpClient->fcnTable.ftable1);
145
146 if (ocspRsp->sessionRequest != NULL) {
147 (*hcv1->freeFcn)(ocspRsp->sessionRequest);
148 ocspRsp->sessionRequest = NULL;
149 }
150
151 if (ocspRsp->serverSession != NULL) {
152 (*hcv1->freeSessionFcn)(ocspRsp->serverSession);
153 ocspRsp->serverSession = NULL;
154 }
155 }
156
157 if (ocspRsp->arena != NULL) {
158 PORT_FreeArena(ocspRsp->arena, PR_FALSE);
159 ocspRsp->arena = NULL;
160 }
161
162 PKIX_DECREF(ocspRsp->producedAtDate);
163 PKIX_DECREF(ocspRsp->pkixSignerCert);
164 PKIX_DECREF(ocspRsp->request);
165
166 cleanup:
167
168 PKIX_RETURN(OCSPRESPONSE);
169 }
170
171 /*
172 * FUNCTION: pkix_pl_OcspResponse_Hashcode
173 * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
174 */
175 static PKIX_Error *
176 pkix_pl_OcspResponse_Hashcode(
177 PKIX_PL_Object *object,
178 PKIX_UInt32 *pHashcode,
179 void *plContext)
180 {
181 PKIX_PL_OcspResponse *ocspRsp = NULL;
182
183 PKIX_ENTER(OCSPRESPONSE, "pkix_pl_OcspResponse_Hashcode");
184 PKIX_NULLCHECK_TWO(object, pHashcode);
185
186 PKIX_CHECK(pkix_CheckType(object, PKIX_OCSPRESPONSE_TYPE, plContext),
187 PKIX_OBJECTNOTANOCSPRESPONSE);
188
189 ocspRsp = (PKIX_PL_OcspResponse *)object;
190
191 if (ocspRsp->encodedResponse->data == NULL) {
192 *pHashcode = 0;
193 } else {
194 PKIX_CHECK(pkix_hash
195 (ocspRsp->encodedResponse->data,
196 ocspRsp->encodedResponse->len,
197 pHashcode,
198 plContext),
199 PKIX_HASHFAILED);
200 }
201
202 cleanup:
203
204 PKIX_RETURN(OCSPRESPONSE);
205 }
206
207 /*
208 * FUNCTION: pkix_pl_OcspResponse_Equals
209 * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
210 */
211 static PKIX_Error *
212 pkix_pl_OcspResponse_Equals(
213 PKIX_PL_Object *firstObj,
214 PKIX_PL_Object *secondObj,
215 PKIX_Boolean *pResult,
216 void *plContext)
217 {
218 PKIX_UInt32 secondType = 0;
219 PKIX_UInt32 firstLen = 0;
220 PKIX_UInt32 i = 0;
221 PKIX_PL_OcspResponse *rsp1 = NULL;
222 PKIX_PL_OcspResponse *rsp2 = NULL;
223 const unsigned char *firstData = NULL;
224 const unsigned char *secondData = NULL;
225
226 PKIX_ENTER(OCSPRESPONSE, "pkix_pl_OcspResponse_Equals");
227 PKIX_NULLCHECK_THREE(firstObj, secondObj, pResult);
228
229 /* test that firstObj is a OcspResponse */
230 PKIX_CHECK(pkix_CheckType(firstObj, PKIX_OCSPRESPONSE_TYPE, plContext),
231 PKIX_FIRSTOBJARGUMENTNOTANOCSPRESPONSE);
232
233 /*
234 * Since we know firstObj is a OcspResponse, if both references are
235 * identical, they must be equal
236 */
237 if (firstObj == secondObj){
238 *pResult = PKIX_TRUE;
239 goto cleanup;
240 }
241
242 /*
243 * If secondObj isn't a OcspResponse, we don't throw an error.
244 * We simply return a Boolean result of FALSE
245 */
246 *pResult = PKIX_FALSE;
247 PKIX_CHECK(PKIX_PL_Object_GetType(secondObj, &secondType, plContext),
248 PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
249 if (secondType != PKIX_OCSPRESPONSE_TYPE) {
250 goto cleanup;
251 }
252
253 rsp1 = (PKIX_PL_OcspResponse *)firstObj;
254 rsp2 = (PKIX_PL_OcspResponse *)secondObj;
255
256 /* If either lacks an encoded string, they cannot be compared */
257 firstData = (const unsigned char *)rsp1->encodedResponse->data;
258 secondData = (const unsigned char *)rsp2->encodedResponse->data;
259 if ((firstData == NULL) || (secondData == NULL)) {
260 goto cleanup;
261 }
262
263 firstLen = rsp1->encodedResponse->len;
264
265 if (firstLen != rsp2->encodedResponse->len) {
266 goto cleanup;
267 }
268
269 for (i = 0; i < firstLen; i++) {
270 if (*firstData++ != *secondData++) {
271 goto cleanup;
272 }
273 }
274
275 *pResult = PKIX_TRUE;
276
277 cleanup:
278
279 PKIX_RETURN(OCSPRESPONSE);
280 }
281
282 /*
283 * FUNCTION: pkix_pl_OcspResponse_RegisterSelf
284 * DESCRIPTION:
285 * Registers PKIX_OCSPRESPONSE_TYPE and its related functions with
286 * systemClasses[]
287 * PARAMETERS:
288 * "plContext"
289 * Platform-specific context pointer.
290 * THREAD SAFETY:
291 * Not Thread Safe - for performance and complexity reasons
292 *
293 * Since this function is only called by PKIX_PL_Initialize, which should
294 * only be called once, it is acceptable that this function is not
295 * thread-safe.
296 */
297 PKIX_Error *
298 pkix_pl_OcspResponse_RegisterSelf(void *plContext)
299 {
300 extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
301 pkix_ClassTable_Entry *entry = &systemClasses[PKIX_OCSPRESPONSE_TYPE];
302
303 PKIX_ENTER(OCSPRESPONSE, "pkix_pl_OcspResponse_RegisterSelf");
304
305 entry->description = "OcspResponse";
306 entry->typeObjectSize = sizeof(PKIX_PL_OcspResponse);
307 entry->destructor = pkix_pl_OcspResponse_Destroy;
308 entry->equalsFunction = pkix_pl_OcspResponse_Equals;
309 entry->hashcodeFunction = pkix_pl_OcspResponse_Hashcode;
310 entry->duplicateFunction = pkix_duplicateImmutable;
311
312 PKIX_RETURN(OCSPRESPONSE);
313 }
314
315 /* --Public-Functions------------------------------------------------------- */
316
317 /*
318 * FUNCTION: pkix_pl_OcspResponse_Create
319 * DESCRIPTION:
320 *
321 * This function transmits the OcspRequest pointed to by "request" and obtains
322 * an OcspResponse, which it stores at "pOcspResponse". If the HTTPClient
323 * supports non-blocking I/O this function may store a non-NULL value at
324 * "pNBIOContext" (the WOULDBLOCK condition). In that case the caller should
325 * make a subsequent call with the same value in "pNBIOContext" and
326 * "pOcspResponse" to resume the operation. Additional WOULDBLOCK returns may
327 * occur; the caller should persist until a return occurs with NULL stored at
328 * "pNBIOContext".
329 *
330 * If a SEC_HttpClientFcn "responder" is supplied, it is used as the client
331 * to which the OCSP query is sent. If none is supplied, the default responder
332 * is used.
333 *
334 * If an OcspResponse_VerifyCallback "verifyFcn" is supplied, it is used to
335 * verify the Cert received from the responder as the signer. If none is
336 * supplied, the default verification function is used.
337 *
338 * The contents of "request" are ignored on calls subsequent to a WOULDBLOCK
339 * return, and the caller is permitted to supply NULL.
340 *
341 * PARAMETERS
342 * "request"
343 * Address of the OcspRequest for which a response is desired.
344 * "httpMethod"
345 * GET or POST
346 * "responder"
347 * Address, if non-NULL, of the SEC_HttpClientFcn to be sent the OCSP
348 * query.
349 * "verifyFcn"
350 * Address, if non-NULL, of the OcspResponse_VerifyCallback function to be
351 * used to verify the Cert of the OCSP responder.
352 * "pNBIOContext"
353 * Address at which platform-dependent information is stored for handling
354 * of non-blocking I/O. Must be non-NULL.
355 * "pOcspResponse"
356 * The address where the created OcspResponse is stored. Must be non-NULL.
357 * "plContext"
358 * Platform-specific context pointer.
359 * THREAD SAFETY:
360 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
361 * RETURNS:
362 * Returns NULL if the function succeeds.
363 * Returns an OcspResponse Error if the function fails in a non-fatal way.
364 * Returns a Fatal Error if the function fails in an unrecoverable way.
365 */
366 PKIX_Error *
367 pkix_pl_OcspResponse_Create(
368 PKIX_PL_OcspRequest *request,
369 const char *httpMethod,
370 void *responder,
371 PKIX_PL_VerifyCallback verifyFcn,
372 void **pNBIOContext,
373 PKIX_PL_OcspResponse **pResponse,
374 void *plContext)
375 {
376 void *nbioContext = NULL;
377 PKIX_PL_OcspResponse *ocspResponse = NULL;
378 const SEC_HttpClientFcn *httpClient = NULL;
379 const SEC_HttpClientFcnV1 *hcv1 = NULL;
380 SECStatus rv = SECFailure;
381 char *location = NULL;
382 char *hostname = NULL;
383 char *path = NULL;
384 char *responseContentType = NULL;
385 PRUint16 port = 0;
386 SEC_HTTP_SERVER_SESSION serverSession = NULL;
387 SEC_HTTP_REQUEST_SESSION sessionRequest = NULL;
388 SECItem *encodedRequest = NULL;
389 PRUint16 responseCode = 0;
390 char *responseData = NULL;
391
392 PKIX_ENTER(OCSPRESPONSE, "pkix_pl_OcspResponse_Create");
393 PKIX_NULLCHECK_TWO(pNBIOContext, pResponse);
394
395 if (!strcmp(httpMethod, "GET") && !strcmp(httpMethod, "POST")) {
396 PKIX_ERROR(PKIX_INVALIDOCSPHTTPMETHOD);
397 }
398
399 nbioContext = *pNBIOContext;
400 *pNBIOContext = NULL;
401
402 if (nbioContext != NULL) {
403
404 ocspResponse = *pResponse;
405 PKIX_NULLCHECK_ONE(ocspResponse);
406
407 httpClient = ocspResponse->httpClient;
408 serverSession = ocspResponse->serverSession;
409 sessionRequest = ocspResponse->sessionRequest;
410 PKIX_NULLCHECK_THREE(httpClient, serverSession, sessionRequest);
411
412 } else {
413 PKIX_UInt32 timeout =
414 ((PKIX_PL_NssContext*)plContext)->timeoutSeconds;
415
416 PKIX_NULLCHECK_ONE(request);
417
418 PKIX_CHECK(pkix_pl_OcspRequest_GetEncoded
419 (request, &encodedRequest, plContext),
420 PKIX_OCSPREQUESTGETENCODEDFAILED);
421
422 /* prepare initial message to HTTPClient */
423
424 /* Is there a default responder and is it enabled? */
425 if (responder) {
426 httpClient = (const SEC_HttpClientFcn *)responder;
427 } else {
428 httpClient = SEC_GetRegisteredHttpClient();
429 }
430
431 if (httpClient && (httpClient->version == 1)) {
432 char *fullGetPath = NULL;
433 const char *sessionPath = NULL;
434 PRBool usePOST = !strcmp(httpMethod, "POST");
435
436 hcv1 = &(httpClient->fcnTable.ftable1);
437
438 PKIX_CHECK(pkix_pl_OcspRequest_GetLocation
439 (request, &location, plContext),
440 PKIX_OCSPREQUESTGETLOCATIONFAILED);
441
442 /* parse location -> hostname, port, path */
443 rv = CERT_ParseURL(location, &hostname, &port, &path);
444 if (rv == SECFailure || hostname == NULL || path == NULL) {
445 PKIX_ERROR(PKIX_URLPARSINGFAILED);
446 }
447
448 rv = (*hcv1->createSessionFcn)(hostname, port,
449 &serverSession);
450 if (rv != SECSuccess) {
451 PKIX_ERROR(PKIX_OCSPSERVERERROR);
452 }
453
454 if (usePOST) {
455 sessionPath = path;
456 } else {
457 /* calculate, are we allowed to use GET? */
458 enum { max_get_request_size = 255 }; /* defined by RFC2560 */
459 char b64ReqBuf[max_get_request_size+1];
460 size_t base64size;
461 size_t slashLengthIfNeeded = 0;
462 size_t pathLength;
463 PRInt32 urlEncodedBufLength;
464 size_t getURLLength;
465 char *walkOutput = NULL;
466
467 pathLength = strlen(path);
468 if (path[pathLength-1] != '/') {
469 slashLengthIfNeeded = 1;
470 }
471 base64size = (((encodedRequest->len +2)/3) * 4);
472 if (base64size > max_get_request_size) {
473 PKIX_ERROR(PKIX_OCSPGETREQUESTTOOBIG);
474 }
475 memset(b64ReqBuf, 0, sizeof(b64ReqBuf));
476 PL_Base64Encode((const char *)encodedRequest->data, encodedRequest->len, b64ReqBuf);
477 urlEncodedBufLength = ocsp_UrlEncodeBase64Buf(b64ReqBuf, NULL);
478 getURLLength = pathLength + urlEncodedBufLength + slashLengthIfNeeded;
479 fullGetPath = (char*)PORT_Alloc(getURLLength);
480 if (!fullGetPath) {
481 PKIX_ERROR(PKIX_OUTOFMEMORY);
482 }
483 strcpy(fullGetPath, path);
484 walkOutput = fullGetPath + pathLength;
485 if (walkOutput > fullGetPath && slashLengthIfNeeded) {
486 strcpy(walkOutput, "/");
487 ++walkOutput;
488 }
489 ocsp_UrlEncodeBase64Buf(b64ReqBuf, walkOutput);
490 sessionPath = fullGetPath;
491 }
492
493 rv = (*hcv1->createFcn)(serverSession, "http",
494 sessionPath, httpMethod,
495 PR_SecondsToInterval(timeout),
496 &sessionRequest);
497 sessionPath = NULL;
498 if (fullGetPath) {
499 PORT_Free(fullGetPath);
500 fullGetPath = NULL;
501 }
502
503 if (rv != SECSuccess) {
504 PKIX_ERROR(PKIX_OCSPSERVERERROR);
505 }
506
507 if (usePOST) {
508 rv = (*hcv1->setPostDataFcn)(sessionRequest,
509 (char *)encodedRequest->data,
510 encodedRequest->len,
511 "application/ocsp-request");
512 if (rv != SECSuccess) {
513 PKIX_ERROR(PKIX_OCSPSERVERERROR);
514 }
515 }
516
517 /* create a PKIX_PL_OcspResponse object */
518 PKIX_CHECK(PKIX_PL_Object_Alloc
519 (PKIX_OCSPRESPONSE_TYPE,
520 sizeof (PKIX_PL_OcspResponse),
521 (PKIX_PL_Object **)&ocspResponse,
522 plContext),
523 PKIX_COULDNOTCREATEOBJECT);
524
525 PKIX_INCREF(request);
526 ocspResponse->request = request;
527 ocspResponse->httpClient = httpClient;
528 ocspResponse->serverSession = serverSession;
529 serverSession = NULL;
530 ocspResponse->sessionRequest = sessionRequest;
531 sessionRequest = NULL;
532 ocspResponse->verifyFcn = verifyFcn;
533 ocspResponse->handle = CERT_GetDefaultCertDB();
534 ocspResponse->encodedResponse = NULL;
535 ocspResponse->arena = NULL;
536 ocspResponse->producedAt = 0;
537 ocspResponse->producedAtDate = NULL;
538 ocspResponse->pkixSignerCert = NULL;
539 ocspResponse->nssOCSPResponse = NULL;
540 ocspResponse->signerCert = NULL;
541 }
542 }
543
544 /* begin or resume IO to HTTPClient */
545 if (httpClient && (httpClient->version == 1)) {
546 PRUint32 responseDataLen =
547 ((PKIX_PL_NssContext*)plContext)->maxResponseLength;
548
549 hcv1 = &(httpClient->fcnTable.ftable1);
550
551 rv = (*hcv1->trySendAndReceiveFcn)(ocspResponse->sessionRequest,
552 (PRPollDesc **)&nbioContext,
553 &responseCode,
554 (const char **)&responseContentType,
555 NULL, /* responseHeaders */
556 (const char **)&responseData,
557 &responseDataLen);
558
559 if (rv != SECSuccess) {
560 PKIX_ERROR(PKIX_OCSPSERVERERROR);
561 }
562 /* responseContentType is a pointer to the null-terminated
563 * string returned by httpclient. Memory allocated for context
564 * type will be freed with freeing of the HttpClient struct. */
565 if (PORT_Strcasecmp(responseContentType,
566 "application/ocsp-response")) {
567 PKIX_ERROR(PKIX_OCSPSERVERERROR);
568 }
569 if (nbioContext != NULL) {
570 *pNBIOContext = nbioContext;
571 goto cleanup;
572 }
573 if (responseCode != 200) {
574 PKIX_ERROR(PKIX_OCSPBADHTTPRESPONSE);
575 }
576 ocspResponse->arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
577 if (ocspResponse->arena == NULL) {
578 PKIX_ERROR(PKIX_OUTOFMEMORY);
579 }
580 ocspResponse->encodedResponse = SECITEM_AllocItem
581 (ocspResponse->arena, NULL, responseDataLen);
582 if (ocspResponse->encodedResponse == NULL) {
583 PKIX_ERROR(PKIX_OUTOFMEMORY);
584 }
585 PORT_Memcpy(ocspResponse->encodedResponse->data,
586 responseData, responseDataLen);
587 }
588 *pResponse = ocspResponse;
589 ocspResponse = NULL;
590
591 cleanup:
592
593 if (path != NULL) {
594 PORT_Free(path);
595 }
596 if (hostname != NULL) {
597 PORT_Free(hostname);
598 }
599 if (ocspResponse) {
600 PKIX_DECREF(ocspResponse);
601 }
602 if (serverSession) {
603 hcv1->freeSessionFcn(serverSession);
604 }
605 if (sessionRequest) {
606 hcv1->freeFcn(sessionRequest);
607 }
608
609 PKIX_RETURN(OCSPRESPONSE);
610 }
611
612 /*
613 * FUNCTION: pkix_pl_OcspResponse_Decode
614 * DESCRIPTION:
615 *
616 * This function decodes the DER data contained in the OcspResponse pointed to
617 * by "response", storing PKIX_TRUE at "pPassed" if the decoding was
618 * successful, and PKIX_FALSE otherwise.
619 *
620 * PARAMETERS
621 * "response"
622 * The address of the OcspResponse whose DER data is to be decoded. Must
623 * be non-NULL.
624 * "pPassed"
625 * Address at which the Boolean result is stored. Must be non-NULL.
626 * "pReturnCode"
627 * Address at which the SECErrorCodes result is stored. Must be non-NULL.
628 * "plContext"
629 * Platform-specific context pointer.
630 * THREAD SAFETY:
631 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
632 * RETURNS:
633 * Returns NULL if the function succeeds.
634 * Returns an OcspResponse Error if the function fails in a non-fatal way.
635 * Returns a Fatal Error if the function fails in an unrecoverable way.
636 */
637
638 PKIX_Error *
639 pkix_pl_OcspResponse_Decode(
640 PKIX_PL_OcspResponse *response,
641 PKIX_Boolean *pPassed,
642 SECErrorCodes *pReturnCode,
643 void *plContext)
644 {
645
646 PKIX_ENTER(OCSPRESPONSE, "PKIX_PL_OcspResponse_Decode");
647 PKIX_NULLCHECK_TWO(response, response->encodedResponse);
648
649 response->nssOCSPResponse =
650 CERT_DecodeOCSPResponse(response->encodedResponse);
651
652 if (response->nssOCSPResponse != NULL) {
653 *pPassed = PKIX_TRUE;
654 *pReturnCode = 0;
655 } else {
656 *pPassed = PKIX_FALSE;
657 *pReturnCode = PORT_GetError();
658 }
659
660 PKIX_RETURN(OCSPRESPONSE);
661 }
662
663 /*
664 * FUNCTION: pkix_pl_OcspResponse_GetStatus
665 * DESCRIPTION:
666 *
667 * This function checks the response status of the OcspResponse pointed to
668 * by "response", storing PKIX_TRUE at "pPassed" if the responder understood
669 * the request and considered it valid, and PKIX_FALSE otherwise.
670 *
671 * PARAMETERS
672 * "response"
673 * The address of the OcspResponse whose status is to be retrieved. Must
674 * be non-NULL.
675 * "pPassed"
676 * Address at which the Boolean result is stored. Must be non-NULL.
677 * "plContext"
678 * Platform-specific context pointer.
679 * THREAD SAFETY:
680 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
681 * RETURNS:
682 * Returns NULL if the function succeeds.
683 * Returns an OcspResponse Error if the function fails in a non-fatal way.
684 * Returns a Fatal Error if the function fails in an unrecoverable way.
685 */
686
687 PKIX_Error *
688 pkix_pl_OcspResponse_GetStatus(
689 PKIX_PL_OcspResponse *response,
690 PKIX_Boolean *pPassed,
691 SECErrorCodes *pReturnCode,
692 void *plContext)
693 {
694 SECStatus rv = SECFailure;
695
696 PKIX_ENTER(OCSPRESPONSE, "PKIX_PL_OcspResponse_GetStatus");
697 PKIX_NULLCHECK_FOUR(response, response->nssOCSPResponse, pPassed, pReturnCode);
698
699 rv = CERT_GetOCSPResponseStatus(response->nssOCSPResponse);
700
701 if (rv == SECSuccess) {
702 *pPassed = PKIX_TRUE;
703 *pReturnCode = 0;
704 } else {
705 *pPassed = PKIX_FALSE;
706 *pReturnCode = PORT_GetError();
707 }
708
709 PKIX_RETURN(OCSPRESPONSE);
710 }
711
712
713 static PKIX_Error*
714 pkix_pl_OcspResponse_VerifyResponse(
715 PKIX_PL_OcspResponse *response,
716 PKIX_ProcessingParams *procParams,
717 SECCertUsage certUsage,
718 void **state,
719 PKIX_BuildResult **buildResult,
720 void **pNBIOContext,
721 void *plContext)
722 {
723 SECStatus rv = SECFailure;
724
725 PKIX_ENTER(OCSPRESPONSE, "pkix_pl_OcspResponse_VerifyResponse");
726
727 if (response->verifyFcn != NULL) {
728 void *lplContext = NULL;
729
730 PKIX_CHECK(
731 PKIX_PL_NssContext_Create(((SECCertificateUsage)1) << certUsage,
732 PKIX_FALSE, NULL, &lplContext),
733 PKIX_NSSCONTEXTCREATEFAILED);
734
735 PKIX_CHECK(
736 (response->verifyFcn)((PKIX_PL_Object*)response->pkixSignerCert,
737 NULL, response->producedAtDate,
738 procParams, pNBIOContext,
739 state, buildResult,
740 NULL, lplContext),
741 PKIX_CERTVERIFYKEYUSAGEFAILED);
742 rv = SECSuccess;
743 } else {
744 rv = CERT_VerifyCert(response->handle, response->signerCert, PKIX_TRUE,
745 certUsage, response->producedAt, NULL, NULL);
746 if (rv != SECSuccess) {
747 PKIX_ERROR(PKIX_CERTVERIFYKEYUSAGEFAILED);
748 }
749 }
750
751 cleanup:
752 if (rv != SECSuccess) {
753 PORT_SetError(SEC_ERROR_OCSP_INVALID_SIGNING_CERT);
754 }
755
756 PKIX_RETURN(OCSPRESPONSE);
757 }
758
759 /*
760 * FUNCTION: pkix_pl_OcspResponse_VerifySignature
761 * DESCRIPTION:
762 *
763 * This function verifies the ocspResponse signature field in the OcspResponse
764 * pointed to by "response", storing PKIX_TRUE at "pPassed" if verification
765 * is successful and PKIX_FALSE otherwise. If verification is unsuccessful an
766 * error code (an enumeration of type SECErrorCodes) is stored at *pReturnCode.
767 *
768 * PARAMETERS
769 * "response"
770 * The address of the OcspResponse whose signature field is to be
771 * retrieved. Must be non-NULL.
772 * "cert"
773 * The address of the Cert for which the OCSP query was made. Must be
774 * non-NULL.
775 * "procParams"
776 * Address of ProcessingParams used to initialize the ExpirationChecker
777 * and TargetCertChecker. Must be non-NULL.
778 * "pPassed"
779 * Address at which the Boolean result is stored. Must be non-NULL.
780 * "pNBIOContext"
781 * Address at which the NBIOContext is stored indicating whether the
782 * checking is complete. Must be non-NULL.
783 * "plContext"
784 * Platform-specific context pointer.
785 * THREAD SAFETY:
786 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
787 * RETURNS:
788 * Returns NULL if the function succeeds.
789 * Returns an OcspResponse Error if the function fails in a non-fatal way.
790 * Returns a Fatal Error if the function fails in an unrecoverable way.
791 */
792 PKIX_Error *
793 pkix_pl_OcspResponse_VerifySignature(
794 PKIX_PL_OcspResponse *response,
795 PKIX_PL_Cert *cert,
796 PKIX_ProcessingParams *procParams,
797 PKIX_Boolean *pPassed,
798 void **pNBIOContext,
799 void *plContext)
800 {
801 SECStatus rv = SECFailure;
802 CERTOCSPResponse *nssOCSPResponse = NULL;
803 CERTCertificate *issuerCert = NULL;
804 PKIX_BuildResult *buildResult = NULL;
805 void *nbio = NULL;
806 void *state = NULL;
807
808 ocspSignature *signature = NULL;
809 ocspResponseData *tbsData = NULL;
810 SECItem *tbsResponseDataDER = NULL;
811
812
813 PKIX_ENTER(OCSPRESPONSE, "pkix_pl_OcspResponse_VerifySignature");
814 PKIX_NULLCHECK_FOUR(response, cert, pPassed, pNBIOContext);
815
816 nbio = *pNBIOContext;
817 *pNBIOContext = NULL;
818
819 nssOCSPResponse = response->nssOCSPResponse;
820 if (nssOCSPResponse == NULL) {
821 PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE);
822 goto cleanup;
823 }
824
825 tbsData =
826 ocsp_GetResponseData(nssOCSPResponse, &tbsResponseDataDER);
827
828 signature = ocsp_GetResponseSignature(nssOCSPResponse);
829
830
831 /* Are we resuming after a WOULDBLOCK response? */
832 if (nbio == NULL) {
833 /* No, this is a new query */
834
835 issuerCert = CERT_FindCertIssuer(cert->nssCert, PR_Now(),
836 certUsageAnyCA);
837
838 /*
839 * If this signature has already gone through verification,
840 * just return the cached result.
841 */
842 if (signature->wasChecked) {
843 if (signature->status == SECSuccess) {
844 response->signerCert =
845 CERT_DupCertificate(signature->cert);
846 } else {
847 PORT_SetError(signature->failureReason);
848 goto cleanup;
849 }
850 }
851
852 response->signerCert =
853 ocsp_GetSignerCertificate(response->handle, tbsData,
854 signature, issuerCert);
855
856 if (response->signerCert == NULL) {
857 if (PORT_GetError() == SEC_ERROR_UNKNOWN_CERT) {
858 /* Make the error a little more specific. */
859 PORT_SetError(SEC_ERROR_OCSP_INVALID_SIGNING_CERT);
860 }
861 goto cleanup;
862 }
863 PKIX_CHECK(
864 PKIX_PL_Cert_CreateFromCERTCertificate(response->signerCert,
865 &(response->pkixSignerCert),
866 plContext),
867 PKIX_CERTCREATEWITHNSSCERTFAILED);
868
869 /*
870 * We could mark this true at the top of this function, or
871 * always below at "finish", but if the problem was just that
872 * we could not find the signer's cert, leave that as if the
873 * signature hasn't been checked. Maybe a subsequent call will
874 * have better luck.
875 */
876 signature->wasChecked = PR_TRUE;
877
878 /*
879 * We are about to verify the signer certificate; we need to
880 * specify *when* that certificate must be valid -- for our
881 * purposes we expect it to be valid when the response was
882 * signed. The value of "producedAt" is the signing time.
883 */
884 rv = DER_GeneralizedTimeToTime(&response->producedAt,
885 &tbsData->producedAt);
886 if (rv != SECSuccess) {
887 PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE);
888 goto cleanup;
889 }
890
891 /*
892 * We need producedAtDate and pkixSignerCert if we are calling a
893 * user-supplied verification function. Let's put their
894 * creation before the code that gets repeated when
895 * non-blocking I/O is used.
896 */
897
898 PKIX_CHECK(
899 pkix_pl_Date_CreateFromPRTime((PRTime)response->producedAt,
900 &(response->producedAtDate),
901 plContext),
902 PKIX_DATECREATEFROMPRTIMEFAILED);
903
904 }
905
906 /*
907 * Just because we have a cert does not mean it is any good; check
908 * it for validity, trust and usage. Use the caller-supplied
909 * verification function, if one was supplied.
910 */
911 if (ocsp_CertIsOCSPDefaultResponder(response->handle,
912 response->signerCert)) {
913 rv = SECSuccess;
914 } else {
915 SECCertUsage certUsage;
916 if (CERT_IsCACert(response->signerCert, NULL)) {
917 certUsage = certUsageAnyCA;
918 } else {
919 certUsage = certUsageStatusResponder;
920 }
921 PKIX_CHECK_ONLY_FATAL(
922 pkix_pl_OcspResponse_VerifyResponse(response, procParams,
923 certUsage, &state,
924 &buildResult, &nbio,
925 plContext),
926 PKIX_CERTVERIFYKEYUSAGEFAILED);
927 if (pkixTempErrorReceived) {
928 rv = SECFailure;
929 goto cleanup;
930 }
931 if (nbio != NULL) {
932 *pNBIOContext = nbio;
933 goto cleanup;
934 }
935 }
936
937 rv = ocsp_VerifyResponseSignature(response->signerCert, signature,
938 tbsResponseDataDER, NULL);
939
940 cleanup:
941 if (rv == SECSuccess) {
942 *pPassed = PKIX_TRUE;
943 } else {
944 *pPassed = PKIX_FALSE;
945 }
946
947 if (signature) {
948 if (signature->wasChecked) {
949 signature->status = rv;
950 }
951
952 if (rv != SECSuccess) {
953 signature->failureReason = PORT_GetError();
954 if (response->signerCert != NULL) {
955 CERT_DestroyCertificate(response->signerCert);
956 response->signerCert = NULL;
957 }
958 } else {
959 /* Save signer's certificate in signature. */
960 signature->cert = CERT_DupCertificate(response->signerCert);
961 }
962 }
963
964 if (issuerCert)
965 CERT_DestroyCertificate(issuerCert);
966
967 PKIX_RETURN(OCSPRESPONSE);
968 }
969
970 /*
971 * FUNCTION: pkix_pl_OcspResponse_GetStatusForCert
972 * DESCRIPTION:
973 *
974 * This function checks the revocation status of the Cert for which the
975 * OcspResponse was obtained, storing PKIX_TRUE at "pPassed" if the Cert has
976 * not been revoked and PKIX_FALSE otherwise.
977 *
978 * PARAMETERS
979 * "response"
980 * The address of the OcspResponse whose certificate status is to be
981 * retrieved. Must be non-NULL.
982 * "pPassed"
983 * Address at which the Boolean result is stored. Must be non-NULL.
984 * "pReturnCode"
985 * Address at which the SECErrorCodes result is stored. Must be non-NULL.
986 * "plContext"
987 * Platform-specific context pointer.
988 * THREAD SAFETY:
989 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
990 * RETURNS:
991 * Returns NULL if the function succeeds.
992 * Returns an OcspResponse Error if the function fails in a non-fatal way.
993 * Returns a Fatal Error if the function fails in an unrecoverable way.
994 */
995 PKIX_Error *
996 pkix_pl_OcspResponse_GetStatusForCert(
997 PKIX_PL_OcspCertID *cid,
998 PKIX_PL_OcspResponse *response,
999 PKIX_Boolean allowCachingOfFailures,
1000 PKIX_PL_Date *validity,
1001 PKIX_Boolean *pPassed,
1002 SECErrorCodes *pReturnCode,
1003 void *plContext)
1004 {
1005 PRTime time = 0;
1006 SECStatus rv = SECFailure;
1007 CERTOCSPSingleResponse *single = NULL;
1008
1009 PKIX_ENTER(OCSPRESPONSE, "pkix_pl_OcspResponse_GetStatusForCert");
1010 PKIX_NULLCHECK_THREE(response, pPassed, pReturnCode);
1011
1012 /*
1013 * It is an error to call this function except following a successful
1014 * return from pkix_pl_OcspResponse_VerifySignature, which would have
1015 * set response->signerCert.
1016 */
1017 PKIX_NULLCHECK_TWO(response->signerCert, response->request);
1018 PKIX_NULLCHECK_TWO(cid, cid->certID);
1019
1020 if (validity != NULL) {
1021 PKIX_Error *er = pkix_pl_Date_GetPRTime(validity, &time, plContext);
1022 PKIX_DECREF(er);
1023 }
1024 if (!time) {
1025 time = PR_Now();
1026 }
1027
1028 rv = ocsp_GetVerifiedSingleResponseForCertID(response->handle,
1029 response->nssOCSPResponse,
1030 cid->certID,
1031 response->signerCert,
1032 time, &single);
1033 if (rv == SECSuccess) {
1034 /*
1035 * Check whether the status says revoked, and if so
1036 * how that compares to the time value passed into this routine.
1037 */
1038 rv = ocsp_CertHasGoodStatus(single->certStatus, time);
1039 }
1040
1041 if (rv == SECSuccess || allowCachingOfFailures) {
1042 /* allowed to update the cache */
1043 PRBool certIDWasConsumed = PR_FALSE;
1044
1045 if (single) {
1046 ocsp_CacheSingleResponse(cid->certID,single,
1047 &certIDWasConsumed);
1048 } else {
1049 cert_RememberOCSPProcessingFailure(cid->certID,
1050 &certIDWasConsumed);
1051 }
1052
1053 if (certIDWasConsumed) {
1054 cid->certID = NULL;
1055 }
1056 }
1057
1058 if (rv == SECSuccess) {
1059 *pPassed = PKIX_TRUE;
1060 *pReturnCode = 0;
1061 } else {
1062 *pPassed = PKIX_FALSE;
1063 *pReturnCode = PORT_GetError();
1064 }
1065
1066 PKIX_RETURN(OCSPRESPONSE);
1067 }
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)