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_ocsprequest.c
42 #include "pkix_pl_ocsprequest.h"
44 /* --Private-OcspRequest-Functions------------------------------------- */
47 * FUNCTION: pkix_pl_OcspRequest_Destroy
48 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
51 pkix_pl_OcspRequest_Destroy(
52 PKIX_PL_Object
*object
,
55 PKIX_PL_OcspRequest
*ocspReq
= NULL
;
58 PKIX_ENTER(OCSPREQUEST
, "pkix_pl_OcspRequest_Destroy");
59 PKIX_NULLCHECK_ONE(object
);
61 PKIX_CHECK(pkix_CheckType(object
, PKIX_OCSPREQUEST_TYPE
, plContext
),
62 PKIX_OBJECTNOTOCSPREQUEST
);
64 ocspReq
= (PKIX_PL_OcspRequest
*)object
;
66 if (ocspReq
->decoded
!= NULL
) {
67 PKIX_PL_NSSCALL(OCSPREQUEST
, CERT_DestroyOCSPRequest
,
71 if (ocspReq
->encoded
!= NULL
) {
72 PKIX_PL_NSSCALL(OCSPREQUEST
, SECITEM_FreeItem
,
73 (ocspReq
->encoded
, PR_TRUE
));
76 if (ocspReq
->certList
!= NULL
) {
78 * The CertList thinks it owns the nssCert. If it destroys it,
79 * PKIX_PL_Cert_Destroy(ocspReq->cert) will crash. Let's
80 * remove the nssCert first, and then destroy the CertList.
82 node
= PR_LIST_HEAD(&ocspReq
->certList
->list
);
84 PKIX_PL_NSSCALL(OCSPREQUEST
, CERT_DestroyCertList
,
88 if (ocspReq
->location
!= NULL
) {
89 PKIX_PL_NSSCALL(OCSPREQUEST
, PORT_Free
, (ocspReq
->location
));
92 PKIX_DECREF(ocspReq
->cert
);
93 PKIX_DECREF(ocspReq
->validity
);
94 PKIX_DECREF(ocspReq
->signerCert
);
98 PKIX_RETURN(OCSPREQUEST
);
102 * FUNCTION: pkix_pl_OcspRequest_Hashcode
103 * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
106 pkix_pl_OcspRequest_Hashcode(
107 PKIX_PL_Object
*object
,
108 PKIX_UInt32
*pHashcode
,
111 PKIX_UInt32 certHash
= 0;
112 PKIX_UInt32 dateHash
= 0;
113 PKIX_UInt32 extensionHash
= 0;
114 PKIX_UInt32 signerHash
= 0;
115 PKIX_PL_OcspRequest
*ocspRq
= NULL
;
117 PKIX_ENTER(OCSPREQUEST
, "pkix_pl_OcspRequest_Hashcode");
118 PKIX_NULLCHECK_TWO(object
, pHashcode
);
120 PKIX_CHECK(pkix_CheckType(object
, PKIX_OCSPREQUEST_TYPE
, plContext
),
121 PKIX_OBJECTNOTOCSPREQUEST
);
123 ocspRq
= (PKIX_PL_OcspRequest
*)object
;
127 PKIX_HASHCODE(ocspRq
->cert
, &certHash
, plContext
,
128 PKIX_CERTHASHCODEFAILED
);
130 PKIX_HASHCODE(ocspRq
->validity
, &dateHash
, plContext
,
131 PKIX_DATEHASHCODEFAILED
);
133 if (ocspRq
->addServiceLocator
== PKIX_TRUE
) {
134 extensionHash
= 0xff;
137 PKIX_HASHCODE(ocspRq
->signerCert
, &signerHash
, plContext
,
138 PKIX_CERTHASHCODEFAILED
);
140 *pHashcode
= (((((extensionHash
<< 8) || certHash
) << 8) ||
141 dateHash
) << 8) || signerHash
;
145 PKIX_RETURN(OCSPREQUEST
);
150 * FUNCTION: pkix_pl_OcspRequest_Equals
151 * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
154 pkix_pl_OcspRequest_Equals(
155 PKIX_PL_Object
*firstObj
,
156 PKIX_PL_Object
*secondObj
,
157 PKIX_Boolean
*pResult
,
160 PKIX_Boolean match
= PKIX_FALSE
;
161 PKIX_UInt32 secondType
= 0;
162 PKIX_PL_OcspRequest
*firstReq
= NULL
;
163 PKIX_PL_OcspRequest
*secondReq
= NULL
;
165 PKIX_ENTER(OCSPREQUEST
, "pkix_pl_OcspRequest_Equals");
166 PKIX_NULLCHECK_THREE(firstObj
, secondObj
, pResult
);
168 /* test that firstObj is a OcspRequest */
169 PKIX_CHECK(pkix_CheckType(firstObj
, PKIX_OCSPREQUEST_TYPE
, plContext
),
170 PKIX_FIRSTOBJARGUMENTNOTOCSPREQUEST
);
173 * Since we know firstObj is a OcspRequest, if both references are
174 * identical, they must be equal
176 if (firstObj
== secondObj
){
182 * If secondObj isn't a OcspRequest, we don't throw an error.
183 * We simply return a Boolean result of FALSE
185 PKIX_CHECK(PKIX_PL_Object_GetType
186 (secondObj
, &secondType
, plContext
),
187 PKIX_COULDNOTGETTYPEOFSECONDARGUMENT
);
188 if (secondType
!= PKIX_OCSPREQUEST_TYPE
) {
192 firstReq
= (PKIX_PL_OcspRequest
*)firstObj
;
193 secondReq
= (PKIX_PL_OcspRequest
*)secondObj
;
195 if (firstReq
->addServiceLocator
!= secondReq
->addServiceLocator
) {
199 PKIX_EQUALS(firstReq
->cert
, secondReq
->cert
, &match
, plContext
,
200 PKIX_CERTEQUALSFAILED
);
202 if (match
== PKIX_FALSE
) {
206 PKIX_EQUALS(firstReq
->validity
, secondReq
->validity
, &match
, plContext
,
207 PKIX_DATEEQUALSFAILED
);
209 if (match
== PKIX_FALSE
) {
214 (firstReq
->signerCert
, secondReq
->signerCert
, &match
, plContext
,
215 PKIX_CERTEQUALSFAILED
);
221 PKIX_RETURN(OCSPREQUEST
);
225 * FUNCTION: pkix_pl_OcspRequest_RegisterSelf
227 * Registers PKIX_OCSPREQUEST_TYPE and its related functions with
231 * Platform-specific context pointer.
233 * Not Thread Safe - for performance and complexity reasons
235 * Since this function is only called by PKIX_PL_Initialize, which should
236 * only be called once, it is acceptable that this function is not
240 pkix_pl_OcspRequest_RegisterSelf(void *plContext
)
242 extern pkix_ClassTable_Entry systemClasses
[PKIX_NUMTYPES
];
243 pkix_ClassTable_Entry entry
;
245 PKIX_ENTER(OCSPREQUEST
, "pkix_pl_OcspRequest_RegisterSelf");
247 entry
.description
= "OcspRequest";
248 entry
.destructor
= pkix_pl_OcspRequest_Destroy
;
249 entry
.equalsFunction
= pkix_pl_OcspRequest_Equals
;
250 entry
.hashcodeFunction
= pkix_pl_OcspRequest_Hashcode
;
251 entry
.toStringFunction
= NULL
;
252 entry
.comparator
= NULL
;
253 entry
.duplicateFunction
= pkix_duplicateImmutable
;
255 systemClasses
[PKIX_OCSPREQUEST_TYPE
] = entry
;
257 PKIX_RETURN(OCSPREQUEST
);
260 /* --Public-Functions------------------------------------------------------- */
263 * FUNCTION: pkix_pl_OcspRequest_Create
266 * This function creates an OcspRequest to be used in validating the Cert
267 * pointed to by "cert" and storing the result at "pRequest". If a URI
268 * is found for an OCSP responder, PKIX_TRUE is stored at "pURIFound". If no
269 * URI is found, PKIX_FALSE is stored.
271 * If a Date is provided in "validity" it may be used in the search for the
272 * issuer of "cert" but has no effect on the request itself. If
273 * "addServiceLocator" is TRUE, the AddServiceLocator extension will be
274 * included in the Request. If "signerCert" is provided it will be used to sign
275 * the Request. (Note: this signed request feature is not currently supported.)
279 * Address of the Cert for which an OcspRequest is to be created. Must be
282 * Address of the Date for which the Cert's validity is to be determined.
284 * "addServiceLocator"
285 * Boolean value indicating whether the request should include the
286 * AddServiceLocator extension
288 * Address of the Cert to be used, if present, in signing the request.
291 * Address at which the result is stored. Must be non-NULL.
293 * Platform-specific context pointer.
295 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
297 * Returns NULL if the function succeeds.
298 * Returns an OcspRequest Error if the function fails in a non-fatal way.
299 * Returns a Fatal Error if the function fails in an unrecoverable way.
302 pkix_pl_OcspRequest_Create(
304 PKIX_PL_Date
*validity
,
305 PKIX_Boolean addServiceLocator
,
306 PKIX_PL_Cert
*signerCert
,
307 PKIX_Boolean
*pURIFound
,
308 PKIX_PL_OcspRequest
**pRequest
,
311 PKIX_PL_OcspRequest
*ocspRequest
= NULL
;
313 SECStatus rv
= SECFailure
;
314 SECItem
*encoding
= NULL
;
315 CERTOCSPRequest
*certRequest
= NULL
;
316 CERTCertList
*certList
= NULL
;
318 PRBool addServiceLocatorExtension
= PR_FALSE
;
319 CERTCertificate
*nssCert
= NULL
;
320 CERTCertificate
*nssSignerCert
= NULL
;
321 char *location
= NULL
;
322 PRErrorCode locError
= 0;
324 PKIX_ENTER(OCSPREQUEST
, "pkix_pl_OcspRequest_Create");
325 PKIX_NULLCHECK_TWO(cert
, pRequest
);
327 /* create a PKIX_PL_OcspRequest object */
328 PKIX_CHECK(PKIX_PL_Object_Alloc
329 (PKIX_OCSPREQUEST_TYPE
,
330 sizeof (PKIX_PL_OcspRequest
),
331 (PKIX_PL_Object
**)&ocspRequest
,
333 PKIX_COULDNOTCREATEOBJECT
);
336 ocspRequest
->cert
= cert
;
338 PKIX_INCREF(validity
);
339 ocspRequest
->validity
= validity
;
341 ocspRequest
->addServiceLocator
= addServiceLocator
;
343 PKIX_INCREF(signerCert
);
344 ocspRequest
->signerCert
= signerCert
;
346 ocspRequest
->decoded
= NULL
;
347 ocspRequest
->encoded
= NULL
;
349 nssCert
= cert
->nssCert
;
352 * Does this Cert have an Authority Information Access extension with
353 * the URI of an OCSP responder?
356 (OCSPREQUEST
, location
, CERT_GetOCSPAuthorityInfoAccessLocation
,
359 if (location
== NULL
) {
360 PKIX_PL_NSSCALLRV(OCSPREQUEST
, locError
, PORT_GetError
, ());
361 if (locError
== SEC_ERROR_CERT_BAD_ACCESS_LOCATION
) {
362 *pURIFound
= PKIX_FALSE
;
365 PKIX_ERROR(PKIX_ERRORFINDINGORPROCESSINGURI
);
368 ocspRequest
->location
= location
;
369 *pURIFound
= PKIX_TRUE
;
372 if (signerCert
!= NULL
) {
373 nssSignerCert
= signerCert
->nssCert
;
377 * Build a CertList with this one Cert. But be careful: apparently it
378 * is customary for CertLists to "own" the Certs, and to destroy
379 * them as part of CERT_DestroyCertList. We must remember to remove
380 * this Cert from the List before destroying the List. Otherwise it
381 * will be destroyed when the CertList is destroyed and again when
382 * the PKIX_PL_Cert that owns it is destroyed.
384 PKIX_PL_NSSCALLRV(OCSPREQUEST
, certList
, CERT_NewCertList
, ());
385 if (certList
== NULL
) {
386 PKIX_ERROR(PKIX_UNABLETOCREATENEWCERTLIST
);
389 ocspRequest
->certList
= certList
;
391 PKIX_PL_NSSCALLRV(OCSPREQUEST
, rv
, CERT_AddCertToListTail
,
392 (certList
, nssCert
));
394 if (rv
== SECFailure
) {
395 PKIX_ERROR(PKIX_UNABLETOADDCERTTOCERTLIST
);
398 if (validity
!= NULL
) {
399 PKIX_CHECK(pkix_pl_Date_GetPRTime(validity
, &time
, plContext
),
400 PKIX_DATEGETPRTIMEFAILED
);
402 PKIX_PL_NSSCALLRV(OCSPREQUEST
, time
, PR_Now
, ());
405 addServiceLocatorExtension
=
406 ((addServiceLocator
== PKIX_TRUE
)? PR_TRUE
: PR_FALSE
);
408 PKIX_PL_NSSCALLRV(OCSPREQUEST
, certRequest
, CERT_CreateOCSPRequest
,
409 (certList
, time
, addServiceLocatorExtension
, nssSignerCert
));
411 if (certRequest
== NULL
) {
412 PKIX_ERROR(PKIX_UNABLETOCREATECERTOCSPREQUEST
);
416 (OCSPREQUEST
, rv
, CERT_AddOCSPAcceptableResponses
,
417 (certRequest
, SEC_OID_PKIX_OCSP_BASIC_RESPONSE
));
419 if (rv
== SECFailure
) {
420 PKIX_ERROR(PKIX_UNABLETOADDACCEPTABLERESPONSESTOREQUEST
);
423 ocspRequest
->decoded
= certRequest
;
425 PKIX_PL_NSSCALLRV(OCSPREQUEST
, encoding
, CERT_EncodeOCSPRequest
,
426 (NULL
, certRequest
, NULL
));
428 ocspRequest
->encoded
= encoding
;
430 *pRequest
= ocspRequest
;
434 PKIX_RETURN(OCSPREQUEST
);
438 * FUNCTION: pkix_pl_OcspRequest_GetEncoded
441 * This function obtains the encoded message from the OcspRequest pointed to
442 * by "request", storing the result at "pRequest".
446 * The address of the OcspRequest whose encoded message is to be
447 * retrieved. Must be non-NULL.
449 * The address at which is stored the address of the encoded message. Must
452 * Platform-specific context pointer.
454 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
456 * Returns NULL if the function succeeds.
457 * Returns a Fatal Error if the function fails in an unrecoverable way.
460 pkix_pl_OcspRequest_GetEncoded(
461 PKIX_PL_OcspRequest
*request
,
465 PKIX_ENTER(OCSPREQUEST
, "pkix_pl_OcspRequest_GetEncoded");
466 PKIX_NULLCHECK_TWO(request
, pRequest
);
468 *pRequest
= request
->encoded
;
470 PKIX_RETURN(OCSPREQUEST
);
474 * FUNCTION: pkix_pl_OcspRequest_GetLocation
477 * This function obtains the location from the OcspRequest pointed to
478 * by "request", storing the result at "pLocation".
482 * The address of the OcspRequest whose encoded message is to be
483 * retrieved. Must be non-NULL.
485 * The address at which is stored the address of the location. Must
488 * Platform-specific context pointer.
490 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
492 * Returns NULL if the function succeeds.
493 * Returns a Fatal Error if the function fails in an unrecoverable way.
496 pkix_pl_OcspRequest_GetLocation(
497 PKIX_PL_OcspRequest
*request
,
501 PKIX_ENTER(OCSPREQUEST
, "pkix_pl_OcspRequest_GetLocation");
502 PKIX_NULLCHECK_TWO(request
, pLocation
);
504 *pLocation
= request
->location
;
506 PKIX_RETURN(OCSPREQUEST
);
510 * FUNCTION: pkix_pl_OcspRequest_GetCertID
513 * This function obtains the certID from the OcspRequest pointed to
514 * by "request", storing the result at "pCertID".
518 * The address of the OcspRequest whose certID is to be retrieved. Must
521 * The address at which is stored the certID of the request. Must be
524 * Platform-specific context pointer.
526 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
528 * Returns NULL if the function succeeds.
529 * Returns a Fatal Error if the function fails in an unrecoverable way.
532 pkix_pl_OcspRequest_GetCertID(
533 PKIX_PL_OcspRequest
*request
,
534 CERTOCSPCertID
**pCertID
,
537 ocspTBSRequest
*tbsRequest
= NULL
;
539 PKIX_ENTER(OCSPREQUEST
, "pkix_pl_OcspRequest_GetCertID");
540 PKIX_NULLCHECK_TWO(request
, pCertID
);
542 PKIX_NULLCHECK_ONE(request
->decoded
);
543 tbsRequest
= request
->decoded
->tbsRequest
;
544 PKIX_NULLCHECK_ONE(tbsRequest
);
545 *pCertID
= tbsRequest
->requestList
[0]->reqCert
;
547 PKIX_RETURN(OCSPREQUEST
);