Import 1.9b4 NSS tag from cvs
[mozilla-nss.git] / security / nss / lib / libpkix / pkix_pl_nss / pki / pkix_pl_ocsprequest.c
blobd71cbc1d8cd1273376d12971e1029d0fc9206eb2
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;
57 PKIX_ENTER(OCSPREQUEST, "pkix_pl_OcspRequest_Destroy");
58 PKIX_NULLCHECK_ONE(object);
60 PKIX_CHECK(pkix_CheckType(object, PKIX_OCSPREQUEST_TYPE, plContext),
61 PKIX_OBJECTNOTOCSPREQUEST);
63 ocspReq = (PKIX_PL_OcspRequest *)object;
65 if (ocspReq->decoded != NULL) {
66 CERT_DestroyOCSPRequest(ocspReq->decoded);
69 if (ocspReq->encoded != NULL) {
70 SECITEM_FreeItem(ocspReq->encoded, PR_TRUE);
73 if (ocspReq->location != NULL) {
74 PORT_Free(ocspReq->location);
77 PKIX_DECREF(ocspReq->cert);
78 PKIX_DECREF(ocspReq->validity);
79 PKIX_DECREF(ocspReq->signerCert);
81 cleanup:
83 PKIX_RETURN(OCSPREQUEST);
87 * FUNCTION: pkix_pl_OcspRequest_Hashcode
88 * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
90 static PKIX_Error *
91 pkix_pl_OcspRequest_Hashcode(
92 PKIX_PL_Object *object,
93 PKIX_UInt32 *pHashcode,
94 void *plContext)
96 PKIX_UInt32 certHash = 0;
97 PKIX_UInt32 dateHash = 0;
98 PKIX_UInt32 extensionHash = 0;
99 PKIX_UInt32 signerHash = 0;
100 PKIX_PL_OcspRequest *ocspRq = NULL;
102 PKIX_ENTER(OCSPREQUEST, "pkix_pl_OcspRequest_Hashcode");
103 PKIX_NULLCHECK_TWO(object, pHashcode);
105 PKIX_CHECK(pkix_CheckType(object, PKIX_OCSPREQUEST_TYPE, plContext),
106 PKIX_OBJECTNOTOCSPREQUEST);
108 ocspRq = (PKIX_PL_OcspRequest *)object;
110 *pHashcode = 0;
112 PKIX_HASHCODE(ocspRq->cert, &certHash, plContext,
113 PKIX_CERTHASHCODEFAILED);
115 PKIX_HASHCODE(ocspRq->validity, &dateHash, plContext,
116 PKIX_DATEHASHCODEFAILED);
118 if (ocspRq->addServiceLocator == PKIX_TRUE) {
119 extensionHash = 0xff;
122 PKIX_HASHCODE(ocspRq->signerCert, &signerHash, plContext,
123 PKIX_CERTHASHCODEFAILED);
125 *pHashcode = (((((extensionHash << 8) || certHash) << 8) ||
126 dateHash) << 8) || signerHash;
128 cleanup:
130 PKIX_RETURN(OCSPREQUEST);
135 * FUNCTION: pkix_pl_OcspRequest_Equals
136 * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
138 static PKIX_Error *
139 pkix_pl_OcspRequest_Equals(
140 PKIX_PL_Object *firstObj,
141 PKIX_PL_Object *secondObj,
142 PKIX_Boolean *pResult,
143 void *plContext)
145 PKIX_Boolean match = PKIX_FALSE;
146 PKIX_UInt32 secondType = 0;
147 PKIX_PL_OcspRequest *firstReq = NULL;
148 PKIX_PL_OcspRequest *secondReq = NULL;
150 PKIX_ENTER(OCSPREQUEST, "pkix_pl_OcspRequest_Equals");
151 PKIX_NULLCHECK_THREE(firstObj, secondObj, pResult);
153 /* test that firstObj is a OcspRequest */
154 PKIX_CHECK(pkix_CheckType(firstObj, PKIX_OCSPREQUEST_TYPE, plContext),
155 PKIX_FIRSTOBJARGUMENTNOTOCSPREQUEST);
158 * Since we know firstObj is a OcspRequest, if both references are
159 * identical, they must be equal
161 if (firstObj == secondObj){
162 match = PKIX_TRUE;
163 goto cleanup;
167 * If secondObj isn't a OcspRequest, we don't throw an error.
168 * We simply return a Boolean result of FALSE
170 PKIX_CHECK(PKIX_PL_Object_GetType
171 (secondObj, &secondType, plContext),
172 PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
173 if (secondType != PKIX_OCSPREQUEST_TYPE) {
174 goto cleanup;
177 firstReq = (PKIX_PL_OcspRequest *)firstObj;
178 secondReq = (PKIX_PL_OcspRequest *)secondObj;
180 if (firstReq->addServiceLocator != secondReq->addServiceLocator) {
181 goto cleanup;
184 PKIX_EQUALS(firstReq->cert, secondReq->cert, &match, plContext,
185 PKIX_CERTEQUALSFAILED);
187 if (match == PKIX_FALSE) {
188 goto cleanup;
191 PKIX_EQUALS(firstReq->validity, secondReq->validity, &match, plContext,
192 PKIX_DATEEQUALSFAILED);
194 if (match == PKIX_FALSE) {
195 goto cleanup;
198 PKIX_EQUALS
199 (firstReq->signerCert, secondReq->signerCert, &match, plContext,
200 PKIX_CERTEQUALSFAILED);
202 cleanup:
204 *pResult = match;
206 PKIX_RETURN(OCSPREQUEST);
210 * FUNCTION: pkix_pl_OcspRequest_RegisterSelf
211 * DESCRIPTION:
212 * Registers PKIX_OCSPREQUEST_TYPE and its related functions with
213 * systemClasses[]
214 * PARAMETERS:
215 * "plContext"
216 * Platform-specific context pointer.
217 * THREAD SAFETY:
218 * Not Thread Safe - for performance and complexity reasons
220 * Since this function is only called by PKIX_PL_Initialize, which should
221 * only be called once, it is acceptable that this function is not
222 * thread-safe.
224 PKIX_Error *
225 pkix_pl_OcspRequest_RegisterSelf(void *plContext)
227 extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
228 pkix_ClassTable_Entry entry;
230 PKIX_ENTER(OCSPREQUEST, "pkix_pl_OcspRequest_RegisterSelf");
232 entry.description = "OcspRequest";
233 entry.objCounter = 0;
234 entry.typeObjectSize = sizeof(PKIX_PL_OcspRequest);
235 entry.destructor = pkix_pl_OcspRequest_Destroy;
236 entry.equalsFunction = pkix_pl_OcspRequest_Equals;
237 entry.hashcodeFunction = pkix_pl_OcspRequest_Hashcode;
238 entry.toStringFunction = NULL;
239 entry.comparator = NULL;
240 entry.duplicateFunction = pkix_duplicateImmutable;
242 systemClasses[PKIX_OCSPREQUEST_TYPE] = entry;
244 PKIX_RETURN(OCSPREQUEST);
247 /* --Public-Functions------------------------------------------------------- */
250 * FUNCTION: pkix_pl_OcspRequest_Create
251 * DESCRIPTION:
253 * This function creates an OcspRequest to be used in validating the Cert
254 * pointed to by "cert" and storing the result at "pRequest". If a URI
255 * is found for an OCSP responder, PKIX_TRUE is stored at "pURIFound". If no
256 * URI is found, PKIX_FALSE is stored.
258 * If a Date is provided in "validity" it may be used in the search for the
259 * issuer of "cert" but has no effect on the request itself. If
260 * "addServiceLocator" is TRUE, the AddServiceLocator extension will be
261 * included in the Request. If "signerCert" is provided it will be used to sign
262 * the Request. (Note: this signed request feature is not currently supported.)
264 * PARAMETERS:
265 * "cert"
266 * Address of the Cert for which an OcspRequest is to be created. Must be
267 * non-NULL.
268 * "validity"
269 * Address of the Date for which the Cert's validity is to be determined.
270 * May be NULL.
271 * "addServiceLocator"
272 * Boolean value indicating whether the request should include the
273 * AddServiceLocator extension
274 * "signerCert"
275 * Address of the Cert to be used, if present, in signing the request.
276 * May be NULL.
277 * "pRequest"
278 * Address at which the result is stored. Must be non-NULL.
279 * "plContext"
280 * Platform-specific context pointer.
281 * THREAD SAFETY:
282 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
283 * RETURNS:
284 * Returns NULL if the function succeeds.
285 * Returns an OcspRequest Error if the function fails in a non-fatal way.
286 * Returns a Fatal Error if the function fails in an unrecoverable way.
288 PKIX_Error *
289 pkix_pl_OcspRequest_Create(
290 PKIX_PL_Cert *cert,
291 PKIX_PL_OcspCertID *cid,
292 PKIX_PL_Date *validity,
293 PKIX_Boolean addServiceLocator,
294 PKIX_PL_Cert *signerCert,
295 PKIX_Boolean *pURIFound,
296 PKIX_PL_OcspRequest **pRequest,
297 void *plContext)
299 PKIX_PL_OcspRequest *ocspRequest = NULL;
301 SECStatus rv = SECFailure;
302 SECItem *encoding = NULL;
303 CERTOCSPRequest *certRequest = NULL;
304 int64 time = 0;
305 PRBool addServiceLocatorExtension = PR_FALSE;
306 CERTCertificate *nssCert = NULL;
307 CERTCertificate *nssSignerCert = NULL;
308 char *location = NULL;
309 PRErrorCode locError = 0;
311 PKIX_ENTER(OCSPREQUEST, "pkix_pl_OcspRequest_Create");
312 PKIX_NULLCHECK_TWO(cert, pRequest);
314 /* create a PKIX_PL_OcspRequest object */
315 PKIX_CHECK(PKIX_PL_Object_Alloc
316 (PKIX_OCSPREQUEST_TYPE,
317 sizeof (PKIX_PL_OcspRequest),
318 (PKIX_PL_Object **)&ocspRequest,
319 plContext),
320 PKIX_COULDNOTCREATEOBJECT);
322 PKIX_INCREF(cert);
323 ocspRequest->cert = cert;
325 PKIX_INCREF(validity);
326 ocspRequest->validity = validity;
328 ocspRequest->addServiceLocator = addServiceLocator;
330 PKIX_INCREF(signerCert);
331 ocspRequest->signerCert = signerCert;
333 ocspRequest->decoded = NULL;
334 ocspRequest->encoded = NULL;
336 ocspRequest->location = NULL;
338 nssCert = cert->nssCert;
341 * Does this Cert have an Authority Information Access extension with
342 * the URI of an OCSP responder?
344 location = CERT_GetOCSPAuthorityInfoAccessLocation(nssCert);
346 if (location == NULL) {
347 locError = PORT_GetError();
348 if (locError == SEC_ERROR_CERT_BAD_ACCESS_LOCATION) {
349 *pURIFound = PKIX_FALSE;
350 goto cleanup;
351 } else {
352 PKIX_ERROR(PKIX_ERRORFINDINGORPROCESSINGURI);
354 } else {
355 ocspRequest->location = location;
356 *pURIFound = PKIX_TRUE;
359 if (signerCert != NULL) {
360 nssSignerCert = signerCert->nssCert;
363 if (validity != NULL) {
364 PKIX_CHECK(pkix_pl_Date_GetPRTime(validity, &time, plContext),
365 PKIX_DATEGETPRTIMEFAILED);
366 } else {
367 time = PR_Now();
370 addServiceLocatorExtension =
371 ((addServiceLocator == PKIX_TRUE)? PR_TRUE : PR_FALSE);
373 certRequest = cert_CreateSingleCertOCSPRequest(
374 cid->certID, cert->nssCert, time,
375 addServiceLocatorExtension, nssSignerCert);
377 ocspRequest->decoded = certRequest;
379 if (certRequest == NULL) {
380 PKIX_ERROR(PKIX_UNABLETOCREATECERTOCSPREQUEST);
383 rv = CERT_AddOCSPAcceptableResponses(
384 certRequest, SEC_OID_PKIX_OCSP_BASIC_RESPONSE);
386 if (rv == SECFailure) {
387 PKIX_ERROR(PKIX_UNABLETOADDACCEPTABLERESPONSESTOREQUEST);
390 encoding = CERT_EncodeOCSPRequest(NULL, certRequest, NULL);
392 ocspRequest->encoded = encoding;
394 *pRequest = ocspRequest;
395 ocspRequest = NULL;
397 cleanup:
398 PKIX_DECREF(ocspRequest);
400 PKIX_RETURN(OCSPREQUEST);
404 * FUNCTION: pkix_pl_OcspRequest_GetEncoded
405 * DESCRIPTION:
407 * This function obtains the encoded message from the OcspRequest pointed to
408 * by "request", storing the result at "pRequest".
410 * PARAMETERS
411 * "request"
412 * The address of the OcspRequest whose encoded message is to be
413 * retrieved. Must be non-NULL.
414 * "pRequest"
415 * The address at which is stored the address of the encoded message. Must
416 * be non-NULL.
417 * "plContext"
418 * Platform-specific context pointer.
419 * THREAD SAFETY:
420 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
421 * RETURNS:
422 * Returns NULL if the function succeeds.
423 * Returns a Fatal Error if the function fails in an unrecoverable way.
425 PKIX_Error *
426 pkix_pl_OcspRequest_GetEncoded(
427 PKIX_PL_OcspRequest *request,
428 SECItem **pRequest,
429 void *plContext)
431 PKIX_ENTER(OCSPREQUEST, "pkix_pl_OcspRequest_GetEncoded");
432 PKIX_NULLCHECK_TWO(request, pRequest);
434 *pRequest = request->encoded;
436 PKIX_RETURN(OCSPREQUEST);
440 * FUNCTION: pkix_pl_OcspRequest_GetLocation
441 * DESCRIPTION:
443 * This function obtains the location from the OcspRequest pointed to
444 * by "request", storing the result at "pLocation".
446 * PARAMETERS
447 * "request"
448 * The address of the OcspRequest whose encoded message is to be
449 * retrieved. Must be non-NULL.
450 * "pLocation"
451 * The address at which is stored the address of the location. Must
452 * be non-NULL.
453 * "plContext"
454 * Platform-specific context pointer.
455 * THREAD SAFETY:
456 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
457 * RETURNS:
458 * Returns NULL if the function succeeds.
459 * Returns a Fatal Error if the function fails in an unrecoverable way.
461 PKIX_Error *
462 pkix_pl_OcspRequest_GetLocation(
463 PKIX_PL_OcspRequest *request,
464 char **pLocation,
465 void *plContext)
467 PKIX_ENTER(OCSPREQUEST, "pkix_pl_OcspRequest_GetLocation");
468 PKIX_NULLCHECK_TWO(request, pLocation);
470 *pLocation = request->location;
472 PKIX_RETURN(OCSPREQUEST);