1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
14 * The Original Code is the PKIX-C library.
16 * The Initial Developer of the Original Code is
17 * Sun Microsystems, Inc.
18 * Portions created by the Initial Developer are
19 * Copyright 2004-2007 Sun Microsystems, Inc. All Rights Reserved.
22 * Sun Microsystems, Inc.
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
38 * pkix_pl_ocspresponse.c
42 #include "pkix_pl_ocspresponse.h"
44 /* ----Public functions------------------------------------- */
46 * This is the libpkix replacement for CERT_VerifyOCSPResponseSignature.
47 * It is used if it has been set as the verifyFcn member of ocspChecker.
50 PKIX_PL_OcspResponse_UseBuildChain(
51 PKIX_PL_Cert
*signerCert
,
52 PKIX_PL_Date
*producedAt
,
53 PKIX_ProcessingParams
*procParams
,
56 PKIX_BuildResult
**pBuildResult
,
57 PKIX_VerifyNode
**pVerifyTree
,
60 PKIX_ProcessingParams
*caProcParams
= NULL
;
61 PKIX_PL_Date
*date
= NULL
;
62 PKIX_ComCertSelParams
*certSelParams
= NULL
;
63 PKIX_CertSelector
*certSelector
= NULL
;
64 void *nbioContext
= NULL
;
65 PKIX_Error
*buildError
= NULL
;
67 PKIX_ENTER(OCSPRESPONSE
, "pkix_OcspResponse_UseBuildChain");
68 PKIX_NULLCHECK_THREE(signerCert
, producedAt
, procParams
);
69 PKIX_NULLCHECK_THREE(pNBIOContext
, pState
, pBuildResult
);
71 nbioContext
= *pNBIOContext
;
74 /* Are we resuming after a WOULDBLOCK return, or starting anew ? */
75 if (nbioContext
== NULL
) {
77 PKIX_CHECK(PKIX_PL_Object_Duplicate
78 ((PKIX_PL_Object
*)procParams
,
79 (PKIX_PL_Object
**)&caProcParams
,
81 PKIX_OBJECTDUPLICATEFAILED
);
83 PKIX_CHECK(PKIX_ProcessingParams_SetDate(procParams
, date
, plContext
),
84 PKIX_PROCESSINGPARAMSSETDATEFAILED
);
86 /* create CertSelector with target certificate in params */
88 PKIX_CHECK(PKIX_CertSelector_Create
89 (NULL
, NULL
, &certSelector
, plContext
),
90 PKIX_CERTSELECTORCREATEFAILED
);
92 PKIX_CHECK(PKIX_ComCertSelParams_Create
93 (&certSelParams
, plContext
),
94 PKIX_COMCERTSELPARAMSCREATEFAILED
);
96 PKIX_CHECK(PKIX_ComCertSelParams_SetCertificate
97 (certSelParams
, signerCert
, plContext
),
98 PKIX_COMCERTSELPARAMSSETCERTIFICATEFAILED
);
100 PKIX_CHECK(PKIX_CertSelector_SetCommonCertSelectorParams
101 (certSelector
, certSelParams
, plContext
),
102 PKIX_CERTSELECTORSETCOMMONCERTSELECTORPARAMSFAILED
);
104 PKIX_CHECK(PKIX_ProcessingParams_SetTargetCertConstraints
105 (caProcParams
, certSelector
, plContext
),
106 PKIX_PROCESSINGPARAMSSETTARGETCERTCONSTRAINTSFAILED
);
109 buildError
= PKIX_BuildChain
117 /* non-null nbioContext means the build would block */
118 if (nbioContext
!= NULL
) {
120 *pNBIOContext
= nbioContext
;
122 /* no buildResult means the build has failed */
123 } else if (buildError
) {
124 pkixErrorResult
= buildError
;
127 PKIX_DECREF(*pState
);
132 PKIX_DECREF(caProcParams
);
134 PKIX_DECREF(certSelParams
);
135 PKIX_DECREF(certSelector
);
137 PKIX_RETURN(OCSPRESPONSE
);
140 /* --Private-OcspResponse-Functions------------------------------------- */
143 * FUNCTION: pkix_pl_OcspResponse_Destroy
144 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
147 pkix_pl_OcspResponse_Destroy(
148 PKIX_PL_Object
*object
,
151 PKIX_PL_OcspResponse
*ocspRsp
= NULL
;
152 const SEC_HttpClientFcn
*httpClient
= NULL
;
153 const SEC_HttpClientFcnV1
*hcv1
= NULL
;
155 PKIX_ENTER(OCSPRESPONSE
, "pkix_pl_OcspResponse_Destroy");
156 PKIX_NULLCHECK_ONE(object
);
158 PKIX_CHECK(pkix_CheckType(object
, PKIX_OCSPRESPONSE_TYPE
, plContext
),
159 PKIX_OBJECTNOTANOCSPRESPONSE
);
161 ocspRsp
= (PKIX_PL_OcspResponse
*)object
;
163 if (ocspRsp
->nssOCSPResponse
!= NULL
) {
164 CERT_DestroyOCSPResponse(ocspRsp
->nssOCSPResponse
);
165 ocspRsp
->nssOCSPResponse
= NULL
;
166 ocspRsp
->signerCert
= NULL
;
169 if (ocspRsp
->signerCert
!= NULL
) {
170 CERT_DestroyCertificate(ocspRsp
->signerCert
);
171 ocspRsp
->signerCert
= NULL
;
174 httpClient
= (const SEC_HttpClientFcn
*)(ocspRsp
->httpClient
);
176 if (httpClient
&& (httpClient
->version
== 1)) {
178 hcv1
= &(httpClient
->fcnTable
.ftable1
);
180 if (ocspRsp
->requestSession
!= NULL
) {
181 hcv1
->freeFcn(ocspRsp
->requestSession
);
182 ocspRsp
->requestSession
= NULL
;
185 if (ocspRsp
->serverSession
!= NULL
) {
186 hcv1
->freeSessionFcn(ocspRsp
->serverSession
);
187 ocspRsp
->serverSession
= NULL
;
191 if (ocspRsp
->arena
!= NULL
) {
192 PORT_FreeArena(ocspRsp
->arena
, PR_FALSE
);
193 ocspRsp
->arena
= NULL
;
196 PKIX_DECREF(ocspRsp
->producedAtDate
);
197 PKIX_DECREF(ocspRsp
->pkixSignerCert
);
198 PKIX_DECREF(ocspRsp
->request
);
202 PKIX_RETURN(OCSPRESPONSE
);
206 * FUNCTION: pkix_pl_OcspResponse_Hashcode
207 * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
210 pkix_pl_OcspResponse_Hashcode(
211 PKIX_PL_Object
*object
,
212 PKIX_UInt32
*pHashcode
,
215 PKIX_PL_OcspResponse
*ocspRsp
= NULL
;
217 PKIX_ENTER(OCSPRESPONSE
, "pkix_pl_OcspResponse_Hashcode");
218 PKIX_NULLCHECK_TWO(object
, pHashcode
);
220 PKIX_CHECK(pkix_CheckType(object
, PKIX_OCSPRESPONSE_TYPE
, plContext
),
221 PKIX_OBJECTNOTANOCSPRESPONSE
);
223 ocspRsp
= (PKIX_PL_OcspResponse
*)object
;
225 if (ocspRsp
->encodedResponse
->data
== NULL
) {
229 (ocspRsp
->encodedResponse
->data
,
230 ocspRsp
->encodedResponse
->len
,
238 PKIX_RETURN(OCSPRESPONSE
);
242 * FUNCTION: pkix_pl_OcspResponse_Equals
243 * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
246 pkix_pl_OcspResponse_Equals(
247 PKIX_PL_Object
*firstObj
,
248 PKIX_PL_Object
*secondObj
,
249 PKIX_Boolean
*pResult
,
252 PKIX_UInt32 secondType
= 0;
253 PKIX_UInt32 firstLen
= 0;
255 PKIX_PL_OcspResponse
*rsp1
= NULL
;
256 PKIX_PL_OcspResponse
*rsp2
= NULL
;
257 const unsigned char *firstData
= NULL
;
258 const unsigned char *secondData
= NULL
;
260 PKIX_ENTER(OCSPRESPONSE
, "pkix_pl_OcspResponse_Equals");
261 PKIX_NULLCHECK_THREE(firstObj
, secondObj
, pResult
);
263 /* test that firstObj is a OcspResponse */
264 PKIX_CHECK(pkix_CheckType(firstObj
, PKIX_OCSPRESPONSE_TYPE
, plContext
),
265 PKIX_FIRSTOBJARGUMENTNOTANOCSPRESPONSE
);
268 * Since we know firstObj is a OcspResponse, if both references are
269 * identical, they must be equal
271 if (firstObj
== secondObj
){
272 *pResult
= PKIX_TRUE
;
277 * If secondObj isn't a OcspResponse, we don't throw an error.
278 * We simply return a Boolean result of FALSE
280 *pResult
= PKIX_FALSE
;
281 PKIX_CHECK(PKIX_PL_Object_GetType(secondObj
, &secondType
, plContext
),
282 PKIX_COULDNOTGETTYPEOFSECONDARGUMENT
);
283 if (secondType
!= PKIX_OCSPRESPONSE_TYPE
) {
287 rsp1
= (PKIX_PL_OcspResponse
*)firstObj
;
288 rsp2
= (PKIX_PL_OcspResponse
*)secondObj
;
290 /* If either lacks an encoded string, they cannot be compared */
291 firstData
= (const unsigned char *)rsp1
->encodedResponse
->data
;
292 secondData
= (const unsigned char *)rsp2
->encodedResponse
->data
;
293 if ((firstData
== NULL
) || (secondData
== NULL
)) {
297 firstLen
= rsp1
->encodedResponse
->len
;
299 if (firstLen
!= rsp2
->encodedResponse
->len
) {
303 for (i
= 0; i
< firstLen
; i
++) {
304 if (*firstData
++ != *secondData
++) {
309 *pResult
= PKIX_TRUE
;
313 PKIX_RETURN(OCSPRESPONSE
);
317 * FUNCTION: pkix_pl_OcspResponse_RegisterSelf
319 * Registers PKIX_OCSPRESPONSE_TYPE and its related functions with
323 * Platform-specific context pointer.
325 * Not Thread Safe - for performance and complexity reasons
327 * Since this function is only called by PKIX_PL_Initialize, which should
328 * only be called once, it is acceptable that this function is not
332 pkix_pl_OcspResponse_RegisterSelf(void *plContext
)
334 extern pkix_ClassTable_Entry systemClasses
[PKIX_NUMTYPES
];
335 pkix_ClassTable_Entry entry
;
337 PKIX_ENTER(OCSPRESPONSE
, "pkix_pl_OcspResponse_RegisterSelf");
339 entry
.description
= "OcspResponse";
340 entry
.objCounter
= 0;
341 entry
.typeObjectSize
= sizeof(PKIX_PL_OcspResponse
);
342 entry
.destructor
= pkix_pl_OcspResponse_Destroy
;
343 entry
.equalsFunction
= pkix_pl_OcspResponse_Equals
;
344 entry
.hashcodeFunction
= pkix_pl_OcspResponse_Hashcode
;
345 entry
.toStringFunction
= NULL
;
346 entry
.comparator
= NULL
;
347 entry
.duplicateFunction
= pkix_duplicateImmutable
;
349 systemClasses
[PKIX_OCSPRESPONSE_TYPE
] = entry
;
351 PKIX_RETURN(OCSPRESPONSE
);
354 /* --Public-Functions------------------------------------------------------- */
357 * FUNCTION: pkix_pl_OcspResponse_Create
360 * This function transmits the OcspRequest pointed to by "request" and obtains
361 * an OcspResponse, which it stores at "pOcspResponse". If the HTTPClient
362 * supports non-blocking I/O this function may store a non-NULL value at
363 * "pNBIOContext" (the WOULDBLOCK condition). In that case the caller should
364 * make a subsequent call with the same value in "pNBIOContext" and
365 * "pOcspResponse" to resume the operation. Additional WOULDBLOCK returns may
366 * occur; the caller should persist until a return occurs with NULL stored at
369 * If a SEC_HttpClientFcn "responder" is supplied, it is used as the client
370 * to which the OCSP query is sent. If none is supplied, the default responder
373 * If an OcspResponse_VerifyCallback "verifyFcn" is supplied, it is used to
374 * verify the Cert received from the responder as the signer. If none is
375 * supplied, the default verification function is used.
377 * The contents of "request" are ignored on calls subsequent to a WOULDBLOCK
378 * return, and the caller is permitted to supply NULL.
382 * Address of the OcspRequest for which a response is desired.
384 * Address, if non-NULL, of the SEC_HttpClientFcn to be sent the OCSP
387 * Address, if non-NULL, of the OcspResponse_VerifyCallback function to be
388 * used to verify the Cert of the OCSP responder.
390 * Address at which platform-dependent information is stored for handling
391 * of non-blocking I/O. Must be non-NULL.
393 * The address where the created OcspResponse is stored. Must be non-NULL.
395 * Platform-specific context pointer.
397 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
399 * Returns NULL if the function succeeds.
400 * Returns an OcspResponse Error if the function fails in a non-fatal way.
401 * Returns a Fatal Error if the function fails in an unrecoverable way.
404 pkix_pl_OcspResponse_Create(
405 PKIX_PL_OcspRequest
*request
,
407 PKIX_PL_OcspResponse_VerifyCallback verifyFcn
,
409 PKIX_PL_OcspResponse
**pResponse
,
412 void *nbioContext
= NULL
;
413 PKIX_PL_OcspResponse
*ocspResponse
= NULL
;
414 const SEC_HttpClientFcn
*httpClient
= NULL
;
415 const SEC_HttpClientFcnV1
*hcv1
= NULL
;
416 SECStatus rv
= SECFailure
;
417 char *location
= NULL
;
418 char *hostname
= NULL
;
421 SEC_HTTP_SERVER_SESSION serverSession
= NULL
;
422 SEC_HTTP_REQUEST_SESSION requestSession
= NULL
;
423 SECItem
*encodedRequest
= NULL
;
424 PRUint16 responseCode
= 0;
425 char *responseData
= NULL
;
426 PRUint32 responseDataLen
= 0;
428 PKIX_ENTER(OCSPRESPONSE
, "pkix_pl_OcspResponse_Create");
429 PKIX_NULLCHECK_TWO(pNBIOContext
, pResponse
);
431 nbioContext
= *pNBIOContext
;
432 *pNBIOContext
= NULL
;
434 if (nbioContext
!= NULL
) {
436 ocspResponse
= *pResponse
;
437 PKIX_NULLCHECK_ONE(ocspResponse
);
439 httpClient
= ocspResponse
->httpClient
;
440 serverSession
= ocspResponse
->serverSession
;
441 requestSession
= ocspResponse
->requestSession
;
442 PKIX_NULLCHECK_THREE(httpClient
, serverSession
, requestSession
);
446 PKIX_NULLCHECK_ONE(request
);
448 PKIX_CHECK(pkix_pl_OcspRequest_GetEncoded
449 (request
, &encodedRequest
, plContext
),
450 PKIX_OCSPREQUESTGETENCODEDFAILED
);
452 /* prepare initial message to HTTPClient */
454 /* Is there a default responder and is it enabled? */
459 (void *)SEC_GetRegisteredHttpClient
,
463 httpClient
= (const SEC_HttpClientFcn
*)responder
;
465 if (httpClient
&& (httpClient
->version
== 1)) {
467 hcv1
= &(httpClient
->fcnTable
.ftable1
);
469 PKIX_CHECK(pkix_pl_OcspRequest_GetLocation
470 (request
, &location
, plContext
),
471 PKIX_OCSPREQUESTGETLOCATIONFAILED
);
473 /* parse location -> hostname, port, path */
474 PKIX_PL_NSSCALLRV(OCSPRESPONSE
, rv
, CERT_ParseURL
,
475 (location
, &hostname
, &port
, &path
));
477 if ((hostname
== NULL
) || (path
== NULL
)) {
478 PKIX_ERROR(PKIX_URLPARSINGFAILED
);
484 hcv1
->createSessionFcn
,
485 (hostname
, port
, &serverSession
));
487 if (rv
!= SECSuccess
) {
488 PKIX_ERROR(PKIX_OCSPSERVERERROR
);
492 (OCSPRESPONSE
, rv
, hcv1
->createFcn
,
497 PR_TicksPerSecond() * 60,
500 if (rv
!= SECSuccess
) {
501 PKIX_ERROR(PKIX_OCSPSERVERERROR
);
505 (OCSPRESPONSE
, rv
, hcv1
->setPostDataFcn
,
507 (char *)encodedRequest
->data
,
509 "application/ocsp-request"));
511 if (rv
!= SECSuccess
) {
512 PKIX_ERROR(PKIX_OCSPSERVERERROR
);
515 /* create a PKIX_PL_OcspResponse object */
516 PKIX_CHECK(PKIX_PL_Object_Alloc
517 (PKIX_OCSPRESPONSE_TYPE
,
518 sizeof (PKIX_PL_OcspResponse
),
519 (PKIX_PL_Object
**)&ocspResponse
,
521 PKIX_COULDNOTCREATEOBJECT
);
523 PKIX_INCREF(request
);
524 ocspResponse
->request
= request
;
525 ocspResponse
->httpClient
= httpClient
;
526 ocspResponse
->serverSession
= serverSession
;
527 ocspResponse
->requestSession
= requestSession
;
528 ocspResponse
->verifyFcn
= verifyFcn
;
529 ocspResponse
->handle
= CERT_GetDefaultCertDB();
530 ocspResponse
->encodedResponse
= NULL
;
531 ocspResponse
->arena
= NULL
;
532 ocspResponse
->producedAt
= 0;
533 ocspResponse
->producedAtDate
= NULL
;
534 ocspResponse
->pkixSignerCert
= NULL
;
535 ocspResponse
->nssOCSPResponse
= NULL
;
536 ocspResponse
->signerCert
= NULL
;
540 /* begin or resume IO to HTTPClient */
541 if (httpClient
&& (httpClient
->version
== 1)) {
543 hcv1
= &(httpClient
->fcnTable
.ftable1
);
545 responseDataLen
= MAX_OCSP_RESPONSE_LEN
;
547 PKIX_PL_NSSCALLRV(OCSPRESPONSE
, rv
, hcv1
->trySendAndReceiveFcn
,
549 (PRPollDesc
**)&nbioContext
,
551 NULL
, /* responseContentType */
552 NULL
, /* responseHeaders */
553 (const char **)&responseData
,
556 if (rv
!= SECSuccess
) {
557 PKIX_ERROR(PKIX_OCSPSERVERERROR
);
560 if (nbioContext
!= NULL
) {
561 *pNBIOContext
= nbioContext
;
565 if (responseCode
!= 200) {
566 PKIX_ERROR(PKIX_OCSPBADHTTPRESPONSE
);
571 (OCSPRESPONSE
, ocspResponse
->arena
, PORT_NewArena
,
572 (DER_DEFAULT_CHUNKSIZE
));
574 if (ocspResponse
->arena
== NULL
) {
575 PKIX_ERROR(PKIX_OUTOFMEMORY
);
580 ocspResponse
->encodedResponse
,
582 (ocspResponse
->arena
, NULL
, responseDataLen
));
584 if (ocspResponse
->encodedResponse
== NULL
) {
585 PKIX_ERROR(PKIX_OUTOFMEMORY
);
588 PKIX_PL_NSSCALL(OCSPRESPONSE
, PORT_Memcpy
,
589 (ocspResponse
->encodedResponse
->data
,
595 *pResponse
= ocspResponse
;
600 PKIX_PL_NSSCALL(OCSPRESPONSE
, PORT_Free
, (path
));
603 if (hostname
!= NULL
) {
604 PKIX_PL_NSSCALL(OCSPRESPONSE
, PORT_Free
, (hostname
));
607 if (PKIX_ERROR_RECEIVED
){
608 PKIX_DECREF(ocspResponse
);
611 PKIX_RETURN(OCSPRESPONSE
);
615 * FUNCTION: pkix_pl_OcspResponse_Decode
618 * This function decodes the DER data contained in the OcspResponse pointed to
619 * by "response", storing PKIX_TRUE at "pPassed" if the decoding was
620 * successful, and PKIX_FALSE otherwise.
624 * The address of the OcspResponse whose DER data is to be decoded. Must
627 * Address at which the Boolean result is stored. Must be non-NULL.
629 * Address at which the SECErrorCodes result is stored. Must be non-NULL.
631 * Platform-specific context pointer.
633 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
635 * Returns NULL if the function succeeds.
636 * Returns an OcspResponse Error if the function fails in a non-fatal way.
637 * Returns a Fatal Error if the function fails in an unrecoverable way.
641 pkix_pl_OcspResponse_Decode(
642 PKIX_PL_OcspResponse
*response
,
643 PKIX_Boolean
*pPassed
,
644 SECErrorCodes
*pReturnCode
,
648 PKIX_ENTER(OCSPRESPONSE
, "PKIX_PL_OcspResponse_Decode");
649 PKIX_NULLCHECK_TWO(response
, response
->encodedResponse
);
651 response
->nssOCSPResponse
=
652 CERT_DecodeOCSPResponse(response
->encodedResponse
);
654 if (response
->nssOCSPResponse
!= NULL
) {
655 *pPassed
= PKIX_TRUE
;
658 *pPassed
= PKIX_FALSE
;
659 *pReturnCode
= PORT_GetError();
662 PKIX_RETURN(OCSPRESPONSE
);
666 * FUNCTION: pkix_pl_OcspResponse_GetStatus
669 * This function checks the response status of the OcspResponse pointed to
670 * by "response", storing PKIX_TRUE at "pPassed" if the responder understood
671 * the request and considered it valid, and PKIX_FALSE otherwise.
675 * The address of the OcspResponse whose status is to be retrieved. Must
678 * Address at which the Boolean result is stored. Must be non-NULL.
680 * Platform-specific context pointer.
682 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
684 * Returns NULL if the function succeeds.
685 * Returns an OcspResponse Error if the function fails in a non-fatal way.
686 * Returns a Fatal Error if the function fails in an unrecoverable way.
690 pkix_pl_OcspResponse_GetStatus(
691 PKIX_PL_OcspResponse
*response
,
692 PKIX_Boolean
*pPassed
,
693 SECErrorCodes
*pReturnCode
,
696 SECStatus rv
= SECFailure
;
698 PKIX_ENTER(OCSPRESPONSE
, "PKIX_PL_OcspResponse_GetStatus");
699 PKIX_NULLCHECK_FOUR(response
, response
->nssOCSPResponse
, pPassed
, pReturnCode
);
701 rv
= CERT_GetOCSPResponseStatus(response
->nssOCSPResponse
);
703 if (rv
== SECSuccess
) {
704 *pPassed
= PKIX_TRUE
;
707 *pPassed
= PKIX_FALSE
;
708 *pReturnCode
= PORT_GetError();
711 PKIX_RETURN(OCSPRESPONSE
);
716 pkix_pl_OcspResponse_CallCertVerify(
717 PKIX_PL_OcspResponse
*response
,
718 PKIX_ProcessingParams
*procParams
,
719 SECCertUsage certUsage
,
721 PKIX_BuildResult
**buildResult
,
725 SECStatus rv
= SECSuccess
;
727 PKIX_ENTER(OCSPRESPONSE
, "pkix_pl_OcspResponse_CallCertVerify");
729 if (response
->verifyFcn
!= NULL
) {
730 void *lplContext
= NULL
;
733 PKIX_PL_NssContext_Create(((SECCertificateUsage
)1) << certUsage
,
734 PKIX_FALSE
, NULL
, &lplContext
),
735 PKIX_NSSCONTEXTCREATEFAILED
);
738 (response
->verifyFcn
)(response
->pkixSignerCert
,
739 response
->producedAtDate
,
740 procParams
, pNBIOContext
,
743 PKIX_CERTVERIFYKEYUSAGEFAILED
);
745 rv
= CERT_VerifyCert(response
->handle
, response
->signerCert
, PKIX_TRUE
,
746 certUsage
, response
->producedAt
, NULL
, NULL
);
747 if (rv
!= SECSuccess
) {
748 PKIX_ERROR(PKIX_CERTVERIFYKEYUSAGEFAILED
);
754 PKIX_RETURN(OCSPRESPONSE
);
758 * FUNCTION: pkix_pl_OcspResponse_VerifySignature
761 * This function verifies the ocspResponse signature field in the OcspResponse
762 * pointed to by "response", storing PKIX_TRUE at "pPassed" if verification
763 * is successful and PKIX_FALSE otherwise. If verification is unsuccessful an
764 * error code (an enumeration of type SECErrorCodes) is stored at *pReturnCode.
768 * The address of the OcspResponse whose signature field is to be
769 * retrieved. Must be non-NULL.
771 * The address of the Cert for which the OCSP query was made. Must be
774 * Address of ProcessingParams used to initialize the ExpirationChecker
775 * and TargetCertChecker. Must be non-NULL.
777 * Address at which the Boolean result is stored. Must be non-NULL.
779 * Address at which the NBIOContext is stored indicating whether the
780 * checking is complete. Must be non-NULL.
782 * Platform-specific context pointer.
784 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
786 * Returns NULL if the function succeeds.
787 * Returns an OcspResponse Error if the function fails in a non-fatal way.
788 * Returns a Fatal Error if the function fails in an unrecoverable way.
791 pkix_pl_OcspResponse_VerifySignature(
792 PKIX_PL_OcspResponse
*response
,
794 PKIX_ProcessingParams
*procParams
,
795 PKIX_Boolean
*pPassed
,
799 SECStatus rv
= SECFailure
;
800 CERTOCSPResponse
*nssOCSPResponse
= NULL
;
801 CERTCertificate
*issuerCert
= NULL
;
802 PKIX_BuildResult
*buildResult
= NULL
;
806 ocspSignature
*signature
= NULL
;
807 ocspResponseData
*tbsData
= NULL
;
808 SECItem
*tbsResponseDataDER
= NULL
;
811 PKIX_ENTER(OCSPRESPONSE
, "pkix_pl_OcspResponse_VerifySignature");
812 PKIX_NULLCHECK_FOUR(response
, cert
, pPassed
, pNBIOContext
);
814 nbio
= *pNBIOContext
;
815 *pNBIOContext
= NULL
;
817 nssOCSPResponse
= response
->nssOCSPResponse
;
818 if (nssOCSPResponse
== NULL
) {
819 PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE
);
824 ocsp_GetResponseData(nssOCSPResponse
, &tbsResponseDataDER
);
826 signature
= ocsp_GetResponseSignature(nssOCSPResponse
);
829 /* Are we resuming after a WOULDBLOCK response? */
831 /* No, this is a new query */
833 issuerCert
= CERT_FindCertIssuer(cert
->nssCert
, PR_Now(),
837 * If this signature has already gone through verification,
838 * just return the cached result.
840 if (signature
->wasChecked
) {
841 if (signature
->status
== SECSuccess
) {
842 response
->signerCert
=
843 CERT_DupCertificate(signature
->cert
);
845 PORT_SetError(signature
->failureReason
);
850 response
->signerCert
=
851 ocsp_GetSignerCertificate(response
->handle
, tbsData
,
852 signature
, issuerCert
);
854 if (response
->signerCert
== NULL
) {
855 PORT_SetError(SEC_ERROR_UNKNOWN_SIGNER
);
860 PKIX_PL_Cert_CreateFromCERTCertificate(response
->signerCert
,
861 &(response
->pkixSignerCert
),
863 PKIX_CERTCREATEWITHNSSCERTFAILED
);
866 * We could mark this true at the top of this function, or
867 * always below at "finish", but if the problem was just that
868 * we could not find the signer's cert, leave that as if the
869 * signature hasn't been checked. Maybe a subsequent call will
872 signature
->wasChecked
= PR_TRUE
;
875 * We are about to verify the signer certificate; we need to
876 * specify *when* that certificate must be valid -- for our
877 * purposes we expect it to be valid when the response was
878 * signed. The value of "producedAt" is the signing time.
880 rv
= DER_GeneralizedTimeToTime(&response
->producedAt
,
881 &tbsData
->producedAt
);
882 if (rv
!= SECSuccess
) {
883 PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE
);
888 * We need producedAtDate and pkixSignerCert if we are calling a
889 * user-supplied verification function. Let's put their
890 * creation before the code that gets repeated when
891 * non-blocking I/O is used.
895 pkix_pl_Date_CreateFromPRTime((PRTime
)response
->producedAt
,
896 &(response
->producedAtDate
),
898 PKIX_DATECREATEFROMPRTIMEFAILED
);
903 * Just because we have a cert does not mean it is any good; check
904 * it for validity, trust and usage. Use the caller-supplied
905 * verification function, if one was supplied.
907 if (ocsp_CertIsOCSPDefaultResponder(response
->handle
,
908 response
->signerCert
)) {
911 SECCertUsage certUsage
;
912 if (CERT_IsCACert(response
->signerCert
, NULL
)) {
913 certUsage
= certUsageVerifyCA
;
915 certUsage
= certUsageStatusResponder
;
917 /* Set negative result before call. If fail to verify, will jump
918 * into cleanup with rv = SECFailure. Restore rv after the call. */
921 pkix_pl_OcspResponse_CallCertVerify(response
, procParams
,
925 PKIX_CERTVERIFYKEYUSAGEFAILED
);
930 *pNBIOContext
= nbio
;
935 rv
= ocsp_VerifyResponseSignature(response
->signerCert
, signature
,
936 tbsResponseDataDER
, NULL
);
939 if (rv
== SECSuccess
) {
940 *pPassed
= PKIX_TRUE
;
942 *pPassed
= PKIX_FALSE
;
945 if (signature
->wasChecked
) {
946 signature
->status
= rv
;
949 if (rv
!= SECSuccess
) {
950 signature
->failureReason
= PORT_GetError();
951 if (response
->signerCert
!= NULL
) {
952 CERT_DestroyCertificate(response
->signerCert
);
953 response
->signerCert
= NULL
;
956 /* Save signer's certificate in signature. */
957 signature
->cert
= CERT_DupCertificate(response
->signerCert
);
960 PKIX_RETURN(OCSPRESPONSE
);
964 * FUNCTION: pkix_pl_OcspResponse_GetStatusForCert
967 * This function checks the revocation status of the Cert for which the
968 * OcspResponse was obtained, storing PKIX_TRUE at "pPassed" if the Cert has
969 * not been revoked and PKIX_FALSE otherwise.
973 * The address of the OcspResponse whose certificate status is to be
974 * retrieved. Must be non-NULL.
976 * Address at which the Boolean result is stored. Must be non-NULL.
978 * Address at which the SECErrorCodes result is stored. Must be non-NULL.
980 * Platform-specific context pointer.
982 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
984 * Returns NULL if the function succeeds.
985 * Returns an OcspResponse Error if the function fails in a non-fatal way.
986 * Returns a Fatal Error if the function fails in an unrecoverable way.
989 pkix_pl_OcspResponse_GetStatusForCert(
990 PKIX_PL_OcspCertID
*cid
,
991 PKIX_PL_OcspResponse
*response
,
992 PKIX_Boolean
*pPassed
,
993 SECErrorCodes
*pReturnCode
,
996 SECStatus rv
= SECFailure
;
999 PKIX_ENTER(OCSPRESPONSE
, "pkix_pl_OcspResponse_GetStatusForCert");
1000 PKIX_NULLCHECK_THREE(response
, pPassed
, pReturnCode
);
1003 * It is an error to call this function except following a successful
1004 * return from pkix_pl_OcspResponse_VerifySignature, which would have
1005 * set response->signerCert.
1007 PKIX_NULLCHECK_TWO(response
->signerCert
, response
->request
);
1009 rv
= cert_ProcessOCSPResponse(response
->handle
,
1010 response
->nssOCSPResponse
,
1012 response
->signerCert
,
1014 &cid
->certIDWasConsumed
,
1016 if (rv
== SECSuccess
) {
1017 *pPassed
= PKIX_TRUE
;
1020 *pPassed
= PKIX_FALSE
;
1021 *pReturnCode
= PORT_GetError();
1024 PKIX_RETURN(OCSPRESPONSE
);