| 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_publickey.c | |
| 6 * | |
| 7 * Certificate Object Functions | |
| 8 * | |
| 9 */ | |
| 10 | |
| 11 #include "pkix_pl_publickey.h" | |
| 12 | |
| 13 /* --Private-Cert-Functions------------------------------------- */ | |
| 14 | |
| 15 /* | |
| 16 * FUNCTION: pkix_pl_PublicKey_ToString_Helper | |
| 17 * DESCRIPTION: | |
| 18 * | |
| 19 * Helper function that creates a string representation of the PublicKey | |
| 20 * pointed to by "pkixPubKey" and stores it at "pString". | |
| 21 * | |
| 22 * PARAMETERS | |
| 23 * "pkixPubKey" | |
| 24 * Address of PublicKey whose string representation is desired. | |
| 25 * Must be non-NULL. | |
| 26 * "pString" | |
| 27 * Address where object pointer will be stored. Must be non-NULL. | |
| 28 * "plContext" - Platform-specific context pointer. | |
| 29 * THREAD SAFETY: | |
| 30 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
| 31 * RETURNS: | |
| 32 * Returns NULL if the function succeeds. | |
| 33 * Returns a PublicKey Error if the function fails in a non-fatal way. | |
| 34 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
| 35 */ | |
| 36 static PKIX_Error * | |
| 37 pkix_pl_PublicKey_ToString_Helper( | |
| 38 PKIX_PL_PublicKey *pkixPubKey, | |
| 39 PKIX_PL_String **pString, | |
| 40 void *plContext) | |
| 41 { | |
| 42 SECAlgorithmID algorithm; | |
| 43 SECOidTag pubKeyTag; | |
| 44 char *asciiOID = NULL; | |
| 45 PKIX_Boolean freeAsciiOID = PKIX_FALSE; | |
| 46 SECItem oidBytes; | |
| 47 | |
| 48 PKIX_ENTER(PUBLICKEY, "pkix_pl_PublicKey_ToString_Helper"); | |
| 49 PKIX_NULLCHECK_THREE(pkixPubKey, pkixPubKey->nssSPKI, pString); | |
| 50 | |
| 51 /* | |
| 52 * XXX for now, we print out public key algorithm's | |
| 53 * description - add params and bytes later | |
| 54 */ | |
| 55 | |
| 56 /* | |
| 57 * If the algorithm OID is known to NSS, | |
| 58 * we print out the ASCII description that is | |
| 59 * registered with NSS. Otherwise, if unknown, | |
| 60 * we print out the OID numbers (eg. "1.2.840.3") | |
| 61 */ | |
| 62 | |
| 63 algorithm = pkixPubKey->nssSPKI->algorithm; | |
| 64 | |
| 65 PKIX_PUBLICKEY_DEBUG("\t\tCalling SECOID_GetAlgorithmTag).\n"); | |
| 66 pubKeyTag = SECOID_GetAlgorithmTag(&algorithm); | |
| 67 if (pubKeyTag != SEC_OID_UNKNOWN){ | |
| 68 PKIX_PUBLICKEY_DEBUG | |
| 69 ("\t\tCalling SECOID_FindOIDTagDescription).\n"); | |
| 70 asciiOID = (char *)SECOID_FindOIDTagDescription(pubKeyTag); | |
| 71 if (!asciiOID){ | |
| 72 PKIX_ERROR(PKIX_SECOIDFINDOIDTAGDESCRIPTIONFAILED); | |
| 73 } | |
| 74 } else { /* pubKeyTag == SEC_OID_UNKNOWN */ | |
| 75 oidBytes = algorithm.algorithm; | |
| 76 PKIX_CHECK(pkix_pl_oidBytes2Ascii | |
| 77 (&oidBytes, &asciiOID, plContext), | |
| 78 PKIX_OIDBYTES2ASCIIFAILED); | |
| 79 freeAsciiOID = PKIX_TRUE; | |
| 80 } | |
| 81 | |
| 82 PKIX_CHECK(PKIX_PL_String_Create | |
| 83 (PKIX_ESCASCII, (void *)asciiOID, 0, pString, plContext), | |
| 84 PKIX_UNABLETOCREATEPSTRING); | |
| 85 | |
| 86 cleanup: | |
| 87 | |
| 88 /* | |
| 89 * we only free asciiOID if it was malloc'ed by pkix_pl_oidBytes2Ascii | |
| 90 */ | |
| 91 if (freeAsciiOID){ | |
| 92 PKIX_FREE(asciiOID); | |
| 93 } | |
| 94 | |
| 95 PKIX_RETURN(PUBLICKEY); | |
| 96 } | |
| 97 | |
| 98 /* | |
| 99 * FUNCTION: pkix_pl_DestroySPKI | |
| 100 * DESCRIPTION: | |
| 101 * Frees all memory associated with the CERTSubjectPublicKeyInfo pointed to | |
| 102 * by "nssSPKI". | |
| 103 * PARAMETERS | |
| 104 * "nssSPKI" | |
| 105 * Address of CERTSubjectPublicKeyInfo. Must be non-NULL. | |
| 106 * "plContext" - Platform-specific context pointer. | |
| 107 * THREAD SAFETY: | |
| 108 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
| 109 * RETURNS: | |
| 110 * Returns NULL if the function succeeds. | |
| 111 * Returns an Object Error if the function fails in a non-fatal way. | |
| 112 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
| 113 */ | |
| 114 static PKIX_Error * | |
| 115 pkix_pl_DestroySPKI( | |
| 116 CERTSubjectPublicKeyInfo *nssSPKI, | |
| 117 void *plContext) | |
| 118 { | |
| 119 PKIX_ENTER(PUBLICKEY, "pkix_pl_DestroySPKI"); | |
| 120 | |
| 121 PKIX_NULLCHECK_ONE(nssSPKI); | |
| 122 | |
| 123 PKIX_PUBLICKEY_DEBUG("\t\tCalling SECOID_DestroyAlgorithmID).\n"); | |
| 124 SECOID_DestroyAlgorithmID(&nssSPKI->algorithm, PKIX_FALSE); | |
| 125 | |
| 126 PKIX_PUBLICKEY_DEBUG("\t\tCalling SECITEM_FreeItem).\n"); | |
| 127 SECITEM_FreeItem(&nssSPKI->subjectPublicKey, PKIX_FALSE); | |
| 128 | |
| 129 PKIX_RETURN(PUBLICKEY); | |
| 130 } | |
| 131 | |
| 132 /* | |
| 133 * FUNCTION: pkix_pl_PublicKey_Destroy | |
| 134 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) | |
| 135 */ | |
| 136 static PKIX_Error * | |
| 137 pkix_pl_PublicKey_Destroy( | |
| 138 PKIX_PL_Object *object, | |
| 139 void *plContext) | |
| 140 { | |
| 141 PKIX_PL_PublicKey *pubKey = NULL; | |
| 142 | |
| 143 PKIX_ENTER(PUBLICKEY, "pkix_pl_PublicKey_Destroy"); | |
| 144 | |
| 145 PKIX_NULLCHECK_ONE(object); | |
| 146 | |
| 147 PKIX_CHECK(pkix_CheckType(object, PKIX_PUBLICKEY_TYPE, plContext), | |
| 148 PKIX_OBJECTNOTPUBLICKEY); | |
| 149 | |
| 150 pubKey = (PKIX_PL_PublicKey *)object; | |
| 151 | |
| 152 if (pubKey->nssSPKI) { | |
| 153 | |
| 154 PKIX_CHECK(pkix_pl_DestroySPKI(pubKey->nssSPKI, plContext), | |
| 155 PKIX_DESTROYSPKIFAILED); | |
| 156 | |
| 157 PKIX_FREE(pubKey->nssSPKI); | |
| 158 } | |
| 159 | |
| 160 cleanup: | |
| 161 | |
| 162 PKIX_RETURN(PUBLICKEY); | |
| 163 } | |
| 164 | |
| 165 /* | |
| 166 * FUNCTION: pkix_pl_PublicKey_ToString | |
| 167 * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h) | |
| 168 */ | |
| 169 static PKIX_Error * | |
| 170 pkix_pl_PublicKey_ToString( | |
| 171 PKIX_PL_Object *object, | |
| 172 PKIX_PL_String **pString, | |
| 173 void *plContext) | |
| 174 { | |
| 175 PKIX_PL_PublicKey *pkixPubKey = NULL; | |
| 176 PKIX_PL_String *pubKeyString = NULL; | |
| 177 | |
| 178 PKIX_ENTER(PUBLICKEY, "pkix_pl_PublicKey_toString"); | |
| 179 PKIX_NULLCHECK_TWO(object, pString); | |
| 180 | |
| 181 PKIX_CHECK(pkix_CheckType(object, PKIX_PUBLICKEY_TYPE, plContext), | |
| 182 PKIX_OBJECTNOTPUBLICKEY); | |
| 183 | |
| 184 pkixPubKey = (PKIX_PL_PublicKey *)object; | |
| 185 | |
| 186 PKIX_CHECK(pkix_pl_PublicKey_ToString_Helper | |
| 187 (pkixPubKey, &pubKeyString, plContext), | |
| 188 PKIX_PUBLICKEYTOSTRINGHELPERFAILED); | |
| 189 | |
| 190 *pString = pubKeyString; | |
| 191 | |
| 192 cleanup: | |
| 193 | |
| 194 PKIX_RETURN(PUBLICKEY); | |
| 195 } | |
| 196 | |
| 197 /* | |
| 198 * FUNCTION: pkix_pl_PublicKey_Hashcode | |
| 199 * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) | |
| 200 */ | |
| 201 static PKIX_Error * | |
| 202 pkix_pl_PublicKey_Hashcode( | |
| 203 PKIX_PL_Object *object, | |
| 204 PKIX_UInt32 *pHashcode, | |
| 205 void *plContext) | |
| 206 { | |
| 207 PKIX_PL_PublicKey *pkixPubKey = NULL; | |
| 208 SECItem algOID; | |
| 209 SECItem algParams; | |
| 210 SECItem nssPubKey; | |
| 211 PKIX_UInt32 algOIDHash; | |
| 212 PKIX_UInt32 algParamsHash; | |
| 213 PKIX_UInt32 pubKeyHash; | |
| 214 | |
| 215 PKIX_ENTER(PUBLICKEY, "pkix_pl_PublicKey_Hashcode"); | |
| 216 PKIX_NULLCHECK_TWO(object, pHashcode); | |
| 217 | |
| 218 PKIX_CHECK(pkix_CheckType(object, PKIX_PUBLICKEY_TYPE, plContext), | |
| 219 PKIX_OBJECTNOTPUBLICKEY); | |
| 220 | |
| 221 pkixPubKey = (PKIX_PL_PublicKey *)object; | |
| 222 | |
| 223 PKIX_NULLCHECK_ONE(pkixPubKey->nssSPKI); | |
| 224 | |
| 225 algOID = pkixPubKey->nssSPKI->algorithm.algorithm; | |
| 226 algParams = pkixPubKey->nssSPKI->algorithm.parameters; | |
| 227 nssPubKey = pkixPubKey->nssSPKI->subjectPublicKey; | |
| 228 | |
| 229 PKIX_CHECK(pkix_hash | |
| 230 (algOID.data, algOID.len, &algOIDHash, plContext), | |
| 231 PKIX_HASHFAILED); | |
| 232 | |
| 233 PKIX_CHECK(pkix_hash | |
| 234 (algParams.data, algParams.len, &algParamsHash, plContext), | |
| 235 PKIX_HASHFAILED); | |
| 236 | |
| 237 PKIX_CHECK(pkix_hash | |
| 238 (nssPubKey.data, nssPubKey.len, &pubKeyHash, plContext), | |
| 239 PKIX_HASHFAILED); | |
| 240 | |
| 241 *pHashcode = pubKeyHash; | |
| 242 | |
| 243 cleanup: | |
| 244 | |
| 245 PKIX_RETURN(PUBLICKEY); | |
| 246 } | |
| 247 | |
| 248 | |
| 249 /* | |
| 250 * FUNCTION: pkix_pl_PublicKey_Equals | |
| 251 * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h) | |
| 252 */ | |
| 253 static PKIX_Error * | |
| 254 pkix_pl_PublicKey_Equals( | |
| 255 PKIX_PL_Object *firstObject, | |
| 256 PKIX_PL_Object *secondObject, | |
| 257 PKIX_Boolean *pResult, | |
| 258 void *plContext) | |
| 259 { | |
| 260 PKIX_PL_PublicKey *firstPKIXPubKey = NULL; | |
| 261 PKIX_PL_PublicKey *secondPKIXPubKey = NULL; | |
| 262 CERTSubjectPublicKeyInfo *firstSPKI = NULL; | |
| 263 CERTSubjectPublicKeyInfo *secondSPKI = NULL; | |
| 264 SECComparison cmpResult; | |
| 265 PKIX_UInt32 secondType; | |
| 266 | |
| 267 PKIX_ENTER(PUBLICKEY, "pkix_pl_PublicKey_Equals"); | |
| 268 PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); | |
| 269 | |
| 270 /* test that firstObject is a PublicKey */ | |
| 271 PKIX_CHECK(pkix_CheckType(firstObject, PKIX_PUBLICKEY_TYPE, plContext), | |
| 272 PKIX_FIRSTOBJECTNOTPUBLICKEY); | |
| 273 | |
| 274 /* | |
| 275 * Since we know firstObject is a PublicKey, if both references are | |
| 276 * identical, they must be equal | |
| 277 */ | |
| 278 if (firstObject == secondObject){ | |
| 279 *pResult = PKIX_TRUE; | |
| 280 goto cleanup; | |
| 281 } | |
| 282 | |
| 283 /* | |
| 284 * If secondObject isn't a PublicKey, we don't throw an error. | |
| 285 * We simply return a Boolean result of FALSE | |
| 286 */ | |
| 287 *pResult = PKIX_FALSE; | |
| 288 PKIX_CHECK(PKIX_PL_Object_GetType | |
| 289 (secondObject, &secondType, plContext), | |
| 290 PKIX_COULDNOTGETTYPEOFSECONDARGUMENT); | |
| 291 if (secondType != PKIX_PUBLICKEY_TYPE) goto cleanup; | |
| 292 | |
| 293 firstPKIXPubKey = ((PKIX_PL_PublicKey *)firstObject); | |
| 294 secondPKIXPubKey = (PKIX_PL_PublicKey *)secondObject; | |
| 295 | |
| 296 firstSPKI = firstPKIXPubKey->nssSPKI; | |
| 297 secondSPKI = secondPKIXPubKey->nssSPKI; | |
| 298 | |
| 299 PKIX_NULLCHECK_TWO(firstSPKI, secondSPKI); | |
| 300 | |
| 301 PKIX_PL_NSSCALLRV(PUBLICKEY, cmpResult, SECOID_CompareAlgorithmID, | |
| 302 (&firstSPKI->algorithm, &secondSPKI->algorithm)); | |
| 303 | |
| 304 if (cmpResult == SECEqual){ | |
| 305 PKIX_PUBLICKEY_DEBUG("\t\tCalling SECITEM_CompareItem).\n"); | |
| 306 cmpResult = SECITEM_CompareItem | |
| 307 (&firstSPKI->subjectPublicKey, | |
| 308 &secondSPKI->subjectPublicKey); | |
| 309 } | |
| 310 | |
| 311 *pResult = (cmpResult == SECEqual)?PKIX_TRUE:PKIX_FALSE; | |
| 312 | |
| 313 cleanup: | |
| 314 | |
| 315 PKIX_RETURN(PUBLICKEY); | |
| 316 } | |
| 317 | |
| 318 /* | |
| 319 * FUNCTION: pkix_pl_PublicKey_RegisterSelf | |
| 320 * DESCRIPTION: | |
| 321 * Registers PKIX_PUBLICKEY_TYPE and its related functions with systemClasses[] | |
| 322 * THREAD SAFETY: | |
| 323 * Not Thread Safe - for performance and complexity reasons | |
| 324 * | |
| 325 * Since this function is only called by PKIX_PL_Initialize, which should | |
| 326 * only be called once, it is acceptable that this function is not | |
| 327 * thread-safe. | |
| 328 */ | |
| 329 PKIX_Error * | |
| 330 pkix_pl_PublicKey_RegisterSelf(void *plContext) | |
| 331 { | |
| 332 | |
| 333 extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; | |
| 334 pkix_ClassTable_Entry entry; | |
| 335 | |
| 336 PKIX_ENTER(PUBLICKEY, "pkix_pl_PublicKey_RegisterSelf"); | |
| 337 | |
| 338 entry.description = "PublicKey"; | |
| 339 entry.objCounter = 0; | |
| 340 entry.typeObjectSize = sizeof(PKIX_PL_PublicKey); | |
| 341 entry.destructor = pkix_pl_PublicKey_Destroy; | |
| 342 entry.equalsFunction = pkix_pl_PublicKey_Equals; | |
| 343 entry.hashcodeFunction = pkix_pl_PublicKey_Hashcode; | |
| 344 entry.toStringFunction = pkix_pl_PublicKey_ToString; | |
| 345 entry.comparator = NULL; | |
| 346 entry.duplicateFunction = pkix_duplicateImmutable; | |
| 347 systemClasses[PKIX_PUBLICKEY_TYPE] = entry; | |
| 348 | |
| 349 PKIX_RETURN(PUBLICKEY); | |
| 350 } | |
| 351 | |
| 352 /* --Public-Functions------------------------------------------------------- */ | |
| 353 | |
| 354 /* | |
| 355 * FUNCTION: PKIX_PL_PublicKey_NeedsDSAParameters | |
| 356 * (see comments in pkix_pl_pki.h) | |
| 357 */ | |
| 358 PKIX_Error * | |
| 359 PKIX_PL_PublicKey_NeedsDSAParameters( | |
| 360 PKIX_PL_PublicKey *pubKey, | |
| 361 PKIX_Boolean *pNeedsParams, | |
| 362 void *plContext) | |
| 363 { | |
| 364 CERTSubjectPublicKeyInfo *nssSPKI = NULL; | |
| 365 KeyType pubKeyType; | |
| 366 PKIX_Boolean needsParams = PKIX_FALSE; | |
| 367 | |
| 368 PKIX_ENTER(PUBLICKEY, "PKIX_PL_PublicKey_NeedsDSAParameters"); | |
| 369 PKIX_NULLCHECK_TWO(pubKey, pNeedsParams); | |
| 370 | |
| 371 nssSPKI = pubKey->nssSPKI; | |
| 372 | |
| 373 PKIX_PUBLICKEY_DEBUG("\t\tCalling CERT_GetCertKeyType).\n"); | |
| 374 pubKeyType = CERT_GetCertKeyType(nssSPKI); | |
| 375 if (!pubKeyType){ | |
| 376 PKIX_ERROR(PKIX_PUBKEYTYPENULLKEY); | |
| 377 } | |
| 378 | |
| 379 if ((pubKeyType == dsaKey) && | |
| 380 (nssSPKI->algorithm.parameters.len == 0)){ | |
| 381 needsParams = PKIX_TRUE; | |
| 382 } | |
| 383 | |
| 384 *pNeedsParams = needsParams; | |
| 385 | |
| 386 cleanup: | |
| 387 | |
| 388 PKIX_RETURN(PUBLICKEY); | |
| 389 } | |
| 390 | |
| 391 /* | |
| 392 * FUNCTION: PKIX_PL_PublicKey_MakeInheritedDSAPublicKey | |
| 393 * (see comments in pkix_pl_pki.h) | |
| 394 */ | |
| 395 PKIX_Error * | |
| 396 PKIX_PL_PublicKey_MakeInheritedDSAPublicKey( | |
| 397 PKIX_PL_PublicKey *firstKey, | |
| 398 PKIX_PL_PublicKey *secondKey, | |
| 399 PKIX_PL_PublicKey **pResultKey, | |
| 400 void *plContext) | |
| 401 { | |
| 402 CERTSubjectPublicKeyInfo *firstSPKI = NULL; | |
| 403 CERTSubjectPublicKeyInfo *secondSPKI = NULL; | |
| 404 CERTSubjectPublicKeyInfo *thirdSPKI = NULL; | |
| 405 PKIX_PL_PublicKey *resultKey = NULL; | |
| 406 KeyType firstPubKeyType; | |
| 407 KeyType secondPubKeyType; | |
| 408 SECStatus rv; | |
| 409 | |
| 410 PKIX_ENTER(PUBLICKEY, "PKIX_PL_PublicKey_MakeInheritedDSAPublicKey"); | |
| 411 PKIX_NULLCHECK_THREE(firstKey, secondKey, pResultKey); | |
| 412 PKIX_NULLCHECK_TWO(firstKey->nssSPKI, secondKey->nssSPKI); | |
| 413 | |
| 414 firstSPKI = firstKey->nssSPKI; | |
| 415 secondSPKI = secondKey->nssSPKI; | |
| 416 | |
| 417 PKIX_PUBLICKEY_DEBUG("\t\tCalling CERT_GetCertKeyType).\n"); | |
| 418 firstPubKeyType = CERT_GetCertKeyType(firstSPKI); | |
| 419 if (!firstPubKeyType){ | |
| 420 PKIX_ERROR(PKIX_FIRSTPUBKEYTYPENULLKEY); | |
| 421 } | |
| 422 | |
| 423 PKIX_PUBLICKEY_DEBUG("\t\tCalling CERT_GetCertKeyType).\n"); | |
| 424 secondPubKeyType = CERT_GetCertKeyType(secondSPKI); | |
| 425 if (!secondPubKeyType){ | |
| 426 PKIX_ERROR(PKIX_SECONDPUBKEYTYPENULLKEY); | |
| 427 } | |
| 428 | |
| 429 if ((firstPubKeyType == dsaKey) && | |
| 430 (firstSPKI->algorithm.parameters.len == 0)){ | |
| 431 if (secondPubKeyType != dsaKey) { | |
| 432 PKIX_ERROR(PKIX_SECONDKEYNOTDSAPUBLICKEY); | |
| 433 } else if (secondSPKI->algorithm.parameters.len == 0) { | |
| 434 PKIX_ERROR | |
| 435 (PKIX_SECONDKEYDSAPUBLICKEY); | |
| 436 } else { | |
| 437 PKIX_CHECK(PKIX_PL_Calloc | |
| 438 (1, | |
| 439 sizeof (CERTSubjectPublicKeyInfo), | |
| 440 (void **)&thirdSPKI, | |
| 441 plContext), | |
| 442 PKIX_CALLOCFAILED); | |
| 443 | |
| 444 PKIX_PUBLICKEY_DEBUG | |
| 445 ("\t\tCalling" | |
| 446 "SECKEY_CopySubjectPublicKeyInfo).\n"); | |
| 447 rv = SECKEY_CopySubjectPublicKeyInfo | |
| 448 (NULL, thirdSPKI, firstSPKI); | |
| 449 if (rv != SECSuccess) { | |
| 450 PKIX_ERROR | |
| 451 (PKIX_SECKEYCOPYSUBJECTPUBLICKEYINFOFAILED); | |
| 452 } | |
| 453 | |
| 454 PKIX_PUBLICKEY_DEBUG | |
| 455 ("\t\tCalling SECITEM_CopyItem).\n"); | |
| 456 rv = SECITEM_CopyItem(NULL, | |
| 457 &thirdSPKI->algorithm.parameters, | |
| 458 &secondSPKI->algorithm.parameters); | |
| 459 | |
| 460 if (rv != SECSuccess) { | |
| 461 PKIX_ERROR(PKIX_OUTOFMEMORY); | |
| 462 } | |
| 463 | |
| 464 /* create a PKIX_PL_PublicKey object */ | |
| 465 PKIX_CHECK(PKIX_PL_Object_Alloc | |
| 466 (PKIX_PUBLICKEY_TYPE, | |
| 467 sizeof (PKIX_PL_PublicKey), | |
| 468 (PKIX_PL_Object **)&resultKey, | |
| 469 plContext), | |
| 470 PKIX_COULDNOTCREATEOBJECT); | |
| 471 | |
| 472 /* populate the SPKI field */ | |
| 473 resultKey->nssSPKI = thirdSPKI; | |
| 474 *pResultKey = resultKey; | |
| 475 } | |
| 476 } else { | |
| 477 *pResultKey = NULL; | |
| 478 } | |
| 479 | |
| 480 cleanup: | |
| 481 | |
| 482 if (thirdSPKI && PKIX_ERROR_RECEIVED){ | |
| 483 PKIX_CHECK(pkix_pl_DestroySPKI(thirdSPKI, plContext), | |
| 484 PKIX_DESTROYSPKIFAILED); | |
| 485 PKIX_FREE(thirdSPKI); | |
| 486 } | |
| 487 | |
| 488 PKIX_RETURN(PUBLICKEY); | |
| 489 } | |
| OLD | NEW |