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
;
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
);
83 PKIX_RETURN(OCSPREQUEST
);
87 * FUNCTION: pkix_pl_OcspRequest_Hashcode
88 * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
91 pkix_pl_OcspRequest_Hashcode(
92 PKIX_PL_Object
*object
,
93 PKIX_UInt32
*pHashcode
,
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
;
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
;
130 PKIX_RETURN(OCSPREQUEST
);
135 * FUNCTION: pkix_pl_OcspRequest_Equals
136 * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
139 pkix_pl_OcspRequest_Equals(
140 PKIX_PL_Object
*firstObj
,
141 PKIX_PL_Object
*secondObj
,
142 PKIX_Boolean
*pResult
,
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
){
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
) {
177 firstReq
= (PKIX_PL_OcspRequest
*)firstObj
;
178 secondReq
= (PKIX_PL_OcspRequest
*)secondObj
;
180 if (firstReq
->addServiceLocator
!= secondReq
->addServiceLocator
) {
184 PKIX_EQUALS(firstReq
->cert
, secondReq
->cert
, &match
, plContext
,
185 PKIX_CERTEQUALSFAILED
);
187 if (match
== PKIX_FALSE
) {
191 PKIX_EQUALS(firstReq
->validity
, secondReq
->validity
, &match
, plContext
,
192 PKIX_DATEEQUALSFAILED
);
194 if (match
== PKIX_FALSE
) {
199 (firstReq
->signerCert
, secondReq
->signerCert
, &match
, plContext
,
200 PKIX_CERTEQUALSFAILED
);
206 PKIX_RETURN(OCSPREQUEST
);
210 * FUNCTION: pkix_pl_OcspRequest_RegisterSelf
212 * Registers PKIX_OCSPREQUEST_TYPE and its related functions with
216 * Platform-specific context pointer.
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
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
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.)
266 * Address of the Cert for which an OcspRequest is to be created. Must be
269 * Address of the Date for which the Cert's validity is to be determined.
271 * "addServiceLocator"
272 * Boolean value indicating whether the request should include the
273 * AddServiceLocator extension
275 * Address of the Cert to be used, if present, in signing the request.
278 * Address at which the result is stored. Must be non-NULL.
280 * Platform-specific context pointer.
282 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
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.
289 pkix_pl_OcspRequest_Create(
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
,
299 PKIX_PL_OcspRequest
*ocspRequest
= NULL
;
301 SECStatus rv
= SECFailure
;
302 SECItem
*encoding
= NULL
;
303 CERTOCSPRequest
*certRequest
= NULL
;
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
,
320 PKIX_COULDNOTCREATEOBJECT
);
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
;
352 PKIX_ERROR(PKIX_ERRORFINDINGORPROCESSINGURI
);
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
);
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
;
398 PKIX_DECREF(ocspRequest
);
400 PKIX_RETURN(OCSPREQUEST
);
404 * FUNCTION: pkix_pl_OcspRequest_GetEncoded
407 * This function obtains the encoded message from the OcspRequest pointed to
408 * by "request", storing the result at "pRequest".
412 * The address of the OcspRequest whose encoded message is to be
413 * retrieved. Must be non-NULL.
415 * The address at which is stored the address of the encoded message. Must
418 * Platform-specific context pointer.
420 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
422 * Returns NULL if the function succeeds.
423 * Returns a Fatal Error if the function fails in an unrecoverable way.
426 pkix_pl_OcspRequest_GetEncoded(
427 PKIX_PL_OcspRequest
*request
,
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
443 * This function obtains the location from the OcspRequest pointed to
444 * by "request", storing the result at "pLocation".
448 * The address of the OcspRequest whose encoded message is to be
449 * retrieved. Must be non-NULL.
451 * The address at which is stored the address of the location. Must
454 * Platform-specific context pointer.
456 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
458 * Returns NULL if the function succeeds.
459 * Returns a Fatal Error if the function fails in an unrecoverable way.
462 pkix_pl_OcspRequest_GetLocation(
463 PKIX_PL_OcspRequest
*request
,
467 PKIX_ENTER(OCSPREQUEST
, "pkix_pl_OcspRequest_GetLocation");
468 PKIX_NULLCHECK_TWO(request
, pLocation
);
470 *pLocation
= request
->location
;
472 PKIX_RETURN(OCSPREQUEST
);