Import from firefox-3.0b1 tarball
[mozilla-nss.git] / security / nss / lib / libpkix / pkix_pl_nss / pki / pkix_pl_ocsprequest.c
blob31752c6fbf7dcf2141dc33e4242e1140e4209456
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
12 * License.
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.
21 * Contributor(s):
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)
50 static PKIX_Error *
51 pkix_pl_OcspRequest_Destroy(
52 PKIX_PL_Object *object,
53 void *plContext)
55 PKIX_PL_OcspRequest *ocspReq = NULL;
56 PRCList *node = 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,
68 (ocspReq->decoded));
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);
83 PR_REMOVE_LINK(node);
84 PKIX_PL_NSSCALL(OCSPREQUEST, CERT_DestroyCertList,
85 (ocspReq->certList));
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);
96 cleanup:
98 PKIX_RETURN(OCSPREQUEST);
102 * FUNCTION: pkix_pl_OcspRequest_Hashcode
103 * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
105 static PKIX_Error *
106 pkix_pl_OcspRequest_Hashcode(
107 PKIX_PL_Object *object,
108 PKIX_UInt32 *pHashcode,
109 void *plContext)
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;
125 *pHashcode = 0;
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;
143 cleanup:
145 PKIX_RETURN(OCSPREQUEST);
150 * FUNCTION: pkix_pl_OcspRequest_Equals
151 * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
153 static PKIX_Error *
154 pkix_pl_OcspRequest_Equals(
155 PKIX_PL_Object *firstObj,
156 PKIX_PL_Object *secondObj,
157 PKIX_Boolean *pResult,
158 void *plContext)
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){
177 match = PKIX_TRUE;
178 goto cleanup;
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) {
189 goto cleanup;
192 firstReq = (PKIX_PL_OcspRequest *)firstObj;
193 secondReq = (PKIX_PL_OcspRequest *)secondObj;
195 if (firstReq->addServiceLocator != secondReq->addServiceLocator) {
196 goto cleanup;
199 PKIX_EQUALS(firstReq->cert, secondReq->cert, &match, plContext,
200 PKIX_CERTEQUALSFAILED);
202 if (match == PKIX_FALSE) {
203 goto cleanup;
206 PKIX_EQUALS(firstReq->validity, secondReq->validity, &match, plContext,
207 PKIX_DATEEQUALSFAILED);
209 if (match == PKIX_FALSE) {
210 goto cleanup;
213 PKIX_EQUALS
214 (firstReq->signerCert, secondReq->signerCert, &match, plContext,
215 PKIX_CERTEQUALSFAILED);
217 cleanup:
219 *pResult = match;
221 PKIX_RETURN(OCSPREQUEST);
225 * FUNCTION: pkix_pl_OcspRequest_RegisterSelf
226 * DESCRIPTION:
227 * Registers PKIX_OCSPREQUEST_TYPE and its related functions with
228 * systemClasses[]
229 * PARAMETERS:
230 * "plContext"
231 * Platform-specific context pointer.
232 * THREAD SAFETY:
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
237 * thread-safe.
239 PKIX_Error *
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
264 * DESCRIPTION:
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.)
277 * PARAMETERS:
278 * "cert"
279 * Address of the Cert for which an OcspRequest is to be created. Must be
280 * non-NULL.
281 * "validity"
282 * Address of the Date for which the Cert's validity is to be determined.
283 * May be NULL.
284 * "addServiceLocator"
285 * Boolean value indicating whether the request should include the
286 * AddServiceLocator extension
287 * "signerCert"
288 * Address of the Cert to be used, if present, in signing the request.
289 * May be NULL.
290 * "pRequest"
291 * Address at which the result is stored. Must be non-NULL.
292 * "plContext"
293 * Platform-specific context pointer.
294 * THREAD SAFETY:
295 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
296 * RETURNS:
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.
301 PKIX_Error *
302 pkix_pl_OcspRequest_Create(
303 PKIX_PL_Cert *cert,
304 PKIX_PL_Date *validity,
305 PKIX_Boolean addServiceLocator,
306 PKIX_PL_Cert *signerCert,
307 PKIX_Boolean *pURIFound,
308 PKIX_PL_OcspRequest **pRequest,
309 void *plContext)
311 PKIX_PL_OcspRequest *ocspRequest = NULL;
313 SECStatus rv = SECFailure;
314 SECItem *encoding = NULL;
315 CERTOCSPRequest *certRequest = NULL;
316 CERTCertList *certList = NULL;
317 int64 time = 0;
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,
332 plContext),
333 PKIX_COULDNOTCREATEOBJECT);
335 PKIX_INCREF(cert);
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?
355 PKIX_PL_NSSCALLRV
356 (OCSPREQUEST, location, CERT_GetOCSPAuthorityInfoAccessLocation,
357 (nssCert));
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;
363 goto cleanup;
364 } else {
365 PKIX_ERROR(PKIX_ERRORFINDINGORPROCESSINGURI);
367 } else {
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);
401 } else {
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);
415 PKIX_PL_NSSCALLRV
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;
432 cleanup:
434 PKIX_RETURN(OCSPREQUEST);
438 * FUNCTION: pkix_pl_OcspRequest_GetEncoded
439 * DESCRIPTION:
441 * This function obtains the encoded message from the OcspRequest pointed to
442 * by "request", storing the result at "pRequest".
444 * PARAMETERS
445 * "request"
446 * The address of the OcspRequest whose encoded message is to be
447 * retrieved. Must be non-NULL.
448 * "pRequest"
449 * The address at which is stored the address of the encoded message. Must
450 * be non-NULL.
451 * "plContext"
452 * Platform-specific context pointer.
453 * THREAD SAFETY:
454 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
455 * RETURNS:
456 * Returns NULL if the function succeeds.
457 * Returns a Fatal Error if the function fails in an unrecoverable way.
459 PKIX_Error *
460 pkix_pl_OcspRequest_GetEncoded(
461 PKIX_PL_OcspRequest *request,
462 SECItem **pRequest,
463 void *plContext)
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
475 * DESCRIPTION:
477 * This function obtains the location from the OcspRequest pointed to
478 * by "request", storing the result at "pLocation".
480 * PARAMETERS
481 * "request"
482 * The address of the OcspRequest whose encoded message is to be
483 * retrieved. Must be non-NULL.
484 * "pLocation"
485 * The address at which is stored the address of the location. Must
486 * be non-NULL.
487 * "plContext"
488 * Platform-specific context pointer.
489 * THREAD SAFETY:
490 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
491 * RETURNS:
492 * Returns NULL if the function succeeds.
493 * Returns a Fatal Error if the function fails in an unrecoverable way.
495 PKIX_Error *
496 pkix_pl_OcspRequest_GetLocation(
497 PKIX_PL_OcspRequest *request,
498 char **pLocation,
499 void *plContext)
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
511 * DESCRIPTION:
513 * This function obtains the certID from the OcspRequest pointed to
514 * by "request", storing the result at "pCertID".
516 * PARAMETERS
517 * "request"
518 * The address of the OcspRequest whose certID is to be retrieved. Must
519 * be non-NULL.
520 * "pCertID"
521 * The address at which is stored the certID of the request. Must be
522 * non-NULL.
523 * "plContext"
524 * Platform-specific context pointer.
525 * THREAD SAFETY:
526 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
527 * RETURNS:
528 * Returns NULL if the function succeeds.
529 * Returns a Fatal Error if the function fails in an unrecoverable way.
531 PKIX_Error *
532 pkix_pl_OcspRequest_GetCertID(
533 PKIX_PL_OcspRequest *request,
534 CERTOCSPCertID **pCertID,
535 void *plContext)
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);