| OLD | NEW |
| (Empty) |
| 1 /* This Source Code Form is subject to the terms of the Mozilla Public | |
| 2 * License, v. 2.0. If a copy of the MPL was not distributed with this | |
| 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | |
| 4 /* | |
| 5 * pkix_pl_ocsprequest.c | |
| 6 * | |
| 7 */ | |
| 8 | |
| 9 #include "pkix_pl_ocsprequest.h" | |
| 10 | |
| 11 /* --Private-OcspRequest-Functions------------------------------------- */ | |
| 12 | |
| 13 /* | |
| 14 * FUNCTION: pkix_pl_OcspRequest_Destroy | |
| 15 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) | |
| 16 */ | |
| 17 static PKIX_Error * | |
| 18 pkix_pl_OcspRequest_Destroy( | |
| 19 PKIX_PL_Object *object, | |
| 20 void *plContext) | |
| 21 { | |
| 22 PKIX_PL_OcspRequest *ocspReq = NULL; | |
| 23 | |
| 24 PKIX_ENTER(OCSPREQUEST, "pkix_pl_OcspRequest_Destroy"); | |
| 25 PKIX_NULLCHECK_ONE(object); | |
| 26 | |
| 27 PKIX_CHECK(pkix_CheckType(object, PKIX_OCSPREQUEST_TYPE, plContext), | |
| 28 PKIX_OBJECTNOTOCSPREQUEST); | |
| 29 | |
| 30 ocspReq = (PKIX_PL_OcspRequest *)object; | |
| 31 | |
| 32 if (ocspReq->decoded != NULL) { | |
| 33 CERT_DestroyOCSPRequest(ocspReq->decoded); | |
| 34 } | |
| 35 | |
| 36 if (ocspReq->encoded != NULL) { | |
| 37 SECITEM_FreeItem(ocspReq->encoded, PR_TRUE); | |
| 38 } | |
| 39 | |
| 40 if (ocspReq->location != NULL) { | |
| 41 PORT_Free(ocspReq->location); | |
| 42 } | |
| 43 | |
| 44 PKIX_DECREF(ocspReq->cert); | |
| 45 PKIX_DECREF(ocspReq->validity); | |
| 46 PKIX_DECREF(ocspReq->signerCert); | |
| 47 | |
| 48 cleanup: | |
| 49 | |
| 50 PKIX_RETURN(OCSPREQUEST); | |
| 51 } | |
| 52 | |
| 53 /* | |
| 54 * FUNCTION: pkix_pl_OcspRequest_Hashcode | |
| 55 * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) | |
| 56 */ | |
| 57 static PKIX_Error * | |
| 58 pkix_pl_OcspRequest_Hashcode( | |
| 59 PKIX_PL_Object *object, | |
| 60 PKIX_UInt32 *pHashcode, | |
| 61 void *plContext) | |
| 62 { | |
| 63 PKIX_UInt32 certHash = 0; | |
| 64 PKIX_UInt32 dateHash = 0; | |
| 65 PKIX_UInt32 extensionHash = 0; | |
| 66 PKIX_UInt32 signerHash = 0; | |
| 67 PKIX_PL_OcspRequest *ocspRq = NULL; | |
| 68 | |
| 69 PKIX_ENTER(OCSPREQUEST, "pkix_pl_OcspRequest_Hashcode"); | |
| 70 PKIX_NULLCHECK_TWO(object, pHashcode); | |
| 71 | |
| 72 PKIX_CHECK(pkix_CheckType(object, PKIX_OCSPREQUEST_TYPE, plContext), | |
| 73 PKIX_OBJECTNOTOCSPREQUEST); | |
| 74 | |
| 75 ocspRq = (PKIX_PL_OcspRequest *)object; | |
| 76 | |
| 77 *pHashcode = 0; | |
| 78 | |
| 79 PKIX_HASHCODE(ocspRq->cert, &certHash, plContext, | |
| 80 PKIX_CERTHASHCODEFAILED); | |
| 81 | |
| 82 PKIX_HASHCODE(ocspRq->validity, &dateHash, plContext, | |
| 83 PKIX_DATEHASHCODEFAILED); | |
| 84 | |
| 85 if (ocspRq->addServiceLocator == PKIX_TRUE) { | |
| 86 extensionHash = 0xff; | |
| 87 } | |
| 88 | |
| 89 PKIX_HASHCODE(ocspRq->signerCert, &signerHash, plContext, | |
| 90 PKIX_CERTHASHCODEFAILED); | |
| 91 | |
| 92 *pHashcode = (((((extensionHash << 8) || certHash) << 8) || | |
| 93 dateHash) << 8) || signerHash; | |
| 94 | |
| 95 cleanup: | |
| 96 | |
| 97 PKIX_RETURN(OCSPREQUEST); | |
| 98 | |
| 99 } | |
| 100 | |
| 101 /* | |
| 102 * FUNCTION: pkix_pl_OcspRequest_Equals | |
| 103 * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h) | |
| 104 */ | |
| 105 static PKIX_Error * | |
| 106 pkix_pl_OcspRequest_Equals( | |
| 107 PKIX_PL_Object *firstObj, | |
| 108 PKIX_PL_Object *secondObj, | |
| 109 PKIX_Boolean *pResult, | |
| 110 void *plContext) | |
| 111 { | |
| 112 PKIX_Boolean match = PKIX_FALSE; | |
| 113 PKIX_UInt32 secondType = 0; | |
| 114 PKIX_PL_OcspRequest *firstReq = NULL; | |
| 115 PKIX_PL_OcspRequest *secondReq = NULL; | |
| 116 | |
| 117 PKIX_ENTER(OCSPREQUEST, "pkix_pl_OcspRequest_Equals"); | |
| 118 PKIX_NULLCHECK_THREE(firstObj, secondObj, pResult); | |
| 119 | |
| 120 /* test that firstObj is a OcspRequest */ | |
| 121 PKIX_CHECK(pkix_CheckType(firstObj, PKIX_OCSPREQUEST_TYPE, plContext), | |
| 122 PKIX_FIRSTOBJARGUMENTNOTOCSPREQUEST); | |
| 123 | |
| 124 /* | |
| 125 * Since we know firstObj is a OcspRequest, if both references are | |
| 126 * identical, they must be equal | |
| 127 */ | |
| 128 if (firstObj == secondObj){ | |
| 129 match = PKIX_TRUE; | |
| 130 goto cleanup; | |
| 131 } | |
| 132 | |
| 133 /* | |
| 134 * If secondObj isn't a OcspRequest, we don't throw an error. | |
| 135 * We simply return a Boolean result of FALSE | |
| 136 */ | |
| 137 PKIX_CHECK(PKIX_PL_Object_GetType | |
| 138 (secondObj, &secondType, plContext), | |
| 139 PKIX_COULDNOTGETTYPEOFSECONDARGUMENT); | |
| 140 if (secondType != PKIX_OCSPREQUEST_TYPE) { | |
| 141 goto cleanup; | |
| 142 } | |
| 143 | |
| 144 firstReq = (PKIX_PL_OcspRequest *)firstObj; | |
| 145 secondReq = (PKIX_PL_OcspRequest *)secondObj; | |
| 146 | |
| 147 if (firstReq->addServiceLocator != secondReq->addServiceLocator) { | |
| 148 goto cleanup; | |
| 149 } | |
| 150 | |
| 151 PKIX_EQUALS(firstReq->cert, secondReq->cert, &match, plContext, | |
| 152 PKIX_CERTEQUALSFAILED); | |
| 153 | |
| 154 if (match == PKIX_FALSE) { | |
| 155 goto cleanup; | |
| 156 } | |
| 157 | |
| 158 PKIX_EQUALS(firstReq->validity, secondReq->validity, &match, plContext, | |
| 159 PKIX_DATEEQUALSFAILED); | |
| 160 | |
| 161 if (match == PKIX_FALSE) { | |
| 162 goto cleanup; | |
| 163 } | |
| 164 | |
| 165 PKIX_EQUALS | |
| 166 (firstReq->signerCert, secondReq->signerCert, &match, plContext, | |
| 167 PKIX_CERTEQUALSFAILED); | |
| 168 | |
| 169 cleanup: | |
| 170 | |
| 171 *pResult = match; | |
| 172 | |
| 173 PKIX_RETURN(OCSPREQUEST); | |
| 174 } | |
| 175 | |
| 176 /* | |
| 177 * FUNCTION: pkix_pl_OcspRequest_RegisterSelf | |
| 178 * DESCRIPTION: | |
| 179 * Registers PKIX_OCSPREQUEST_TYPE and its related functions with | |
| 180 * systemClasses[] | |
| 181 * PARAMETERS: | |
| 182 * "plContext" | |
| 183 * Platform-specific context pointer. | |
| 184 * THREAD SAFETY: | |
| 185 * Not Thread Safe - for performance and complexity reasons | |
| 186 * | |
| 187 * Since this function is only called by PKIX_PL_Initialize, which should | |
| 188 * only be called once, it is acceptable that this function is not | |
| 189 * thread-safe. | |
| 190 */ | |
| 191 PKIX_Error * | |
| 192 pkix_pl_OcspRequest_RegisterSelf(void *plContext) | |
| 193 { | |
| 194 extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; | |
| 195 pkix_ClassTable_Entry entry; | |
| 196 | |
| 197 PKIX_ENTER(OCSPREQUEST, "pkix_pl_OcspRequest_RegisterSelf"); | |
| 198 | |
| 199 entry.description = "OcspRequest"; | |
| 200 entry.objCounter = 0; | |
| 201 entry.typeObjectSize = sizeof(PKIX_PL_OcspRequest); | |
| 202 entry.destructor = pkix_pl_OcspRequest_Destroy; | |
| 203 entry.equalsFunction = pkix_pl_OcspRequest_Equals; | |
| 204 entry.hashcodeFunction = pkix_pl_OcspRequest_Hashcode; | |
| 205 entry.toStringFunction = NULL; | |
| 206 entry.comparator = NULL; | |
| 207 entry.duplicateFunction = pkix_duplicateImmutable; | |
| 208 | |
| 209 systemClasses[PKIX_OCSPREQUEST_TYPE] = entry; | |
| 210 | |
| 211 PKIX_RETURN(OCSPREQUEST); | |
| 212 } | |
| 213 | |
| 214 /* --Public-Functions------------------------------------------------------- */ | |
| 215 | |
| 216 /* | |
| 217 * FUNCTION: pkix_pl_OcspRequest_Create | |
| 218 * DESCRIPTION: | |
| 219 * | |
| 220 * This function creates an OcspRequest to be used in validating the Cert | |
| 221 * pointed to by "cert" and storing the result at "pRequest". If a URI | |
| 222 * is found for an OCSP responder, PKIX_TRUE is stored at "pURIFound". If no | |
| 223 * URI is found, PKIX_FALSE is stored. | |
| 224 * | |
| 225 * If a Date is provided in "validity" it may be used in the search for the | |
| 226 * issuer of "cert" but has no effect on the request itself. If | |
| 227 * "addServiceLocator" is TRUE, the AddServiceLocator extension will be | |
| 228 * included in the Request. If "signerCert" is provided it will be used to sign | |
| 229 * the Request. (Note: this signed request feature is not currently supported.) | |
| 230 * | |
| 231 * PARAMETERS: | |
| 232 * "cert" | |
| 233 * Address of the Cert for which an OcspRequest is to be created. Must be | |
| 234 * non-NULL. | |
| 235 * "validity" | |
| 236 * Address of the Date for which the Cert's validity is to be determined. | |
| 237 * May be NULL. | |
| 238 * "signerCert" | |
| 239 * Address of the Cert to be used, if present, in signing the request. | |
| 240 * May be NULL. | |
| 241 * "pRequest" | |
| 242 * Address at which the result is stored. Must be non-NULL. | |
| 243 * "plContext" | |
| 244 * Platform-specific context pointer. | |
| 245 * THREAD SAFETY: | |
| 246 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
| 247 * RETURNS: | |
| 248 * Returns NULL if the function succeeds. | |
| 249 * Returns an OcspRequest Error if the function fails in a non-fatal way. | |
| 250 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
| 251 */ | |
| 252 PKIX_Error * | |
| 253 pkix_pl_OcspRequest_Create( | |
| 254 PKIX_PL_Cert *cert, | |
| 255 PKIX_PL_OcspCertID *cid, | |
| 256 PKIX_PL_Date *validity, | |
| 257 PKIX_PL_Cert *signerCert, | |
| 258 PKIX_UInt32 methodFlags, | |
| 259 PKIX_Boolean *pURIFound, | |
| 260 PKIX_PL_OcspRequest **pRequest, | |
| 261 void *plContext) | |
| 262 { | |
| 263 PKIX_PL_OcspRequest *ocspRequest = NULL; | |
| 264 | |
| 265 CERTCertDBHandle *handle = NULL; | |
| 266 SECStatus rv = SECFailure; | |
| 267 SECItem *encoding = NULL; | |
| 268 CERTOCSPRequest *certRequest = NULL; | |
| 269 PRTime time = 0; | |
| 270 PRBool addServiceLocatorExtension = PR_FALSE; | |
| 271 CERTCertificate *nssCert = NULL; | |
| 272 CERTCertificate *nssSignerCert = NULL; | |
| 273 char *location = NULL; | |
| 274 PRErrorCode locError = 0; | |
| 275 PKIX_Boolean canUseDefaultSource = PKIX_FALSE; | |
| 276 | |
| 277 PKIX_ENTER(OCSPREQUEST, "pkix_pl_OcspRequest_Create"); | |
| 278 PKIX_NULLCHECK_TWO(cert, pRequest); | |
| 279 | |
| 280 /* create a PKIX_PL_OcspRequest object */ | |
| 281 PKIX_CHECK(PKIX_PL_Object_Alloc | |
| 282 (PKIX_OCSPREQUEST_TYPE, | |
| 283 sizeof (PKIX_PL_OcspRequest), | |
| 284 (PKIX_PL_Object **)&ocspRequest, | |
| 285 plContext), | |
| 286 PKIX_COULDNOTCREATEOBJECT); | |
| 287 | |
| 288 PKIX_INCREF(cert); | |
| 289 ocspRequest->cert = cert; | |
| 290 | |
| 291 PKIX_INCREF(validity); | |
| 292 ocspRequest->validity = validity; | |
| 293 | |
| 294 PKIX_INCREF(signerCert); | |
| 295 ocspRequest->signerCert = signerCert; | |
| 296 | |
| 297 ocspRequest->decoded = NULL; | |
| 298 ocspRequest->encoded = NULL; | |
| 299 | |
| 300 ocspRequest->location = NULL; | |
| 301 | |
| 302 nssCert = cert->nssCert; | |
| 303 | |
| 304 /* | |
| 305 * Does this Cert have an Authority Information Access extension with | |
| 306 * the URI of an OCSP responder? | |
| 307 */ | |
| 308 handle = CERT_GetDefaultCertDB(); | |
| 309 | |
| 310 if (!(methodFlags & PKIX_REV_M_IGNORE_IMPLICIT_DEFAULT_SOURCE)) { | |
| 311 canUseDefaultSource = PKIX_TRUE; | |
| 312 } | |
| 313 location = ocsp_GetResponderLocation(handle, nssCert, | |
| 314 canUseDefaultSource, | |
| 315 &addServiceLocatorExtension); | |
| 316 if (location == NULL) { | |
| 317 locError = PORT_GetError(); | |
| 318 if (locError == SEC_ERROR_EXTENSION_NOT_FOUND || | |
| 319 locError == SEC_ERROR_CERT_BAD_ACCESS_LOCATION) { | |
| 320 PORT_SetError(0); | |
| 321 *pURIFound = PKIX_FALSE; | |
| 322 goto cleanup; | |
| 323 } | |
| 324 PKIX_ERROR(PKIX_ERRORFINDINGORPROCESSINGURI); | |
| 325 } | |
| 326 | |
| 327 ocspRequest->location = location; | |
| 328 *pURIFound = PKIX_TRUE; | |
| 329 | |
| 330 if (signerCert != NULL) { | |
| 331 nssSignerCert = signerCert->nssCert; | |
| 332 } | |
| 333 | |
| 334 if (validity != NULL) { | |
| 335 PKIX_CHECK(pkix_pl_Date_GetPRTime(validity, &time, plContext), | |
| 336 PKIX_DATEGETPRTIMEFAILED); | |
| 337 } else { | |
| 338 time = PR_Now(); | |
| 339 } | |
| 340 | |
| 341 certRequest = cert_CreateSingleCertOCSPRequest( | |
| 342 cid->certID, cert->nssCert, time, | |
| 343 addServiceLocatorExtension, nssSignerCert); | |
| 344 | |
| 345 ocspRequest->decoded = certRequest; | |
| 346 | |
| 347 if (certRequest == NULL) { | |
| 348 PKIX_ERROR(PKIX_UNABLETOCREATECERTOCSPREQUEST); | |
| 349 } | |
| 350 | |
| 351 rv = CERT_AddOCSPAcceptableResponses( | |
| 352 certRequest, SEC_OID_PKIX_OCSP_BASIC_RESPONSE); | |
| 353 | |
| 354 if (rv == SECFailure) { | |
| 355 PKIX_ERROR(PKIX_UNABLETOADDACCEPTABLERESPONSESTOREQUEST); | |
| 356 } | |
| 357 | |
| 358 encoding = CERT_EncodeOCSPRequest(NULL, certRequest, NULL); | |
| 359 | |
| 360 ocspRequest->encoded = encoding; | |
| 361 | |
| 362 *pRequest = ocspRequest; | |
| 363 ocspRequest = NULL; | |
| 364 | |
| 365 cleanup: | |
| 366 PKIX_DECREF(ocspRequest); | |
| 367 | |
| 368 PKIX_RETURN(OCSPREQUEST); | |
| 369 } | |
| 370 | |
| 371 /* | |
| 372 * FUNCTION: pkix_pl_OcspRequest_GetEncoded | |
| 373 * DESCRIPTION: | |
| 374 * | |
| 375 * This function obtains the encoded message from the OcspRequest pointed to | |
| 376 * by "request", storing the result at "pRequest". | |
| 377 * | |
| 378 * PARAMETERS | |
| 379 * "request" | |
| 380 * The address of the OcspRequest whose encoded message is to be | |
| 381 * retrieved. Must be non-NULL. | |
| 382 * "pRequest" | |
| 383 * The address at which is stored the address of the encoded message. Must | |
| 384 * be non-NULL. | |
| 385 * "plContext" | |
| 386 * Platform-specific context pointer. | |
| 387 * THREAD SAFETY: | |
| 388 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
| 389 * RETURNS: | |
| 390 * Returns NULL if the function succeeds. | |
| 391 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
| 392 */ | |
| 393 PKIX_Error * | |
| 394 pkix_pl_OcspRequest_GetEncoded( | |
| 395 PKIX_PL_OcspRequest *request, | |
| 396 SECItem **pRequest, | |
| 397 void *plContext) | |
| 398 { | |
| 399 PKIX_ENTER(OCSPREQUEST, "pkix_pl_OcspRequest_GetEncoded"); | |
| 400 PKIX_NULLCHECK_TWO(request, pRequest); | |
| 401 | |
| 402 *pRequest = request->encoded; | |
| 403 | |
| 404 PKIX_RETURN(OCSPREQUEST); | |
| 405 } | |
| 406 | |
| 407 /* | |
| 408 * FUNCTION: pkix_pl_OcspRequest_GetLocation | |
| 409 * DESCRIPTION: | |
| 410 * | |
| 411 * This function obtains the location from the OcspRequest pointed to | |
| 412 * by "request", storing the result at "pLocation". | |
| 413 * | |
| 414 * PARAMETERS | |
| 415 * "request" | |
| 416 * The address of the OcspRequest whose encoded message is to be | |
| 417 * retrieved. Must be non-NULL. | |
| 418 * "pLocation" | |
| 419 * The address at which is stored the address of the location. Must | |
| 420 * be non-NULL. | |
| 421 * "plContext" | |
| 422 * Platform-specific context pointer. | |
| 423 * THREAD SAFETY: | |
| 424 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
| 425 * RETURNS: | |
| 426 * Returns NULL if the function succeeds. | |
| 427 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
| 428 */ | |
| 429 PKIX_Error * | |
| 430 pkix_pl_OcspRequest_GetLocation( | |
| 431 PKIX_PL_OcspRequest *request, | |
| 432 char **pLocation, | |
| 433 void *plContext) | |
| 434 { | |
| 435 PKIX_ENTER(OCSPREQUEST, "pkix_pl_OcspRequest_GetLocation"); | |
| 436 PKIX_NULLCHECK_TWO(request, pLocation); | |
| 437 | |
| 438 *pLocation = request->location; | |
| 439 | |
| 440 PKIX_RETURN(OCSPREQUEST); | |
| 441 } | |
| OLD | NEW |