| 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_cert.c | |
| 6 * | |
| 7 * Certificate Object Functions | |
| 8 * | |
| 9 */ | |
| 10 | |
| 11 #include "pkix_pl_cert.h" | |
| 12 | |
| 13 extern PKIX_PL_HashTable *cachedCertSigTable; | |
| 14 | |
| 15 /* --Private-Cert-Functions------------------------------------- */ | |
| 16 | |
| 17 /* | |
| 18 * FUNCTION: pkix_pl_Cert_IsExtensionCritical | |
| 19 * DESCRIPTION: | |
| 20 * | |
| 21 * Checks the Cert specified by "cert" to determine whether the extension | |
| 22 * whose tag is the UInt32 value given by "tag" is marked as a critical | |
| 23 * extension, and stores the result in "pCritical". | |
| 24 * | |
| 25 * Tags are the index into the table "oids" of SECOidData defined in the | |
| 26 * file secoid.c. Constants, such as SEC_OID_X509_CERTIFICATE_POLICIES, are | |
| 27 * are defined in secoidt.h for most of the table entries. | |
| 28 * | |
| 29 * If the specified tag is invalid (not in the list of tags) or if the | |
| 30 * extension is not found in the certificate, PKIX_FALSE is stored. | |
| 31 * | |
| 32 * PARAMETERS | |
| 33 * "cert" | |
| 34 * Address of Cert whose extensions are to be examined. Must be non-NULL. | |
| 35 * "tag" | |
| 36 * The UInt32 value of the tag for the extension whose criticality is | |
| 37 * to be determined | |
| 38 * "pCritical" | |
| 39 * Address where the Boolean value will be stored. Must be non-NULL. | |
| 40 * "plContext" | |
| 41 * Platform-specific context pointer. | |
| 42 * THREAD SAFETY: | |
| 43 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
| 44 * RETURNS: | |
| 45 * Returns NULL if the function succeeds. | |
| 46 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
| 47 */ | |
| 48 static PKIX_Error * | |
| 49 pkix_pl_Cert_IsExtensionCritical( | |
| 50 PKIX_PL_Cert *cert, | |
| 51 PKIX_UInt32 tag, | |
| 52 PKIX_Boolean *pCritical, | |
| 53 void *plContext) | |
| 54 { | |
| 55 PKIX_Boolean criticality = PKIX_FALSE; | |
| 56 CERTCertExtension **extensions = NULL; | |
| 57 SECStatus rv; | |
| 58 | |
| 59 PKIX_ENTER(CERT, "pkix_pl_Cert_IsExtensionCritical"); | |
| 60 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pCritical); | |
| 61 | |
| 62 extensions = cert->nssCert->extensions; | |
| 63 PKIX_NULLCHECK_ONE(extensions); | |
| 64 | |
| 65 PKIX_CERT_DEBUG("\t\tCalling CERT_GetExtenCriticality).\n"); | |
| 66 rv = CERT_GetExtenCriticality(extensions, tag, &criticality); | |
| 67 if (SECSuccess == rv) { | |
| 68 *pCritical = criticality; | |
| 69 } else { | |
| 70 *pCritical = PKIX_FALSE; | |
| 71 } | |
| 72 | |
| 73 PKIX_RETURN(CERT); | |
| 74 } | |
| 75 | |
| 76 /* | |
| 77 * FUNCTION: pkix_pl_Cert_DecodePolicyInfo | |
| 78 * DESCRIPTION: | |
| 79 * | |
| 80 * Decodes the contents of the CertificatePolicy extension in the | |
| 81 * CERTCertificate pointed to by "nssCert", to create a List of | |
| 82 * CertPolicyInfos, which is stored at the address "pCertPolicyInfos". | |
| 83 * A CERTCertificate contains the DER representation of the Cert. | |
| 84 * If this certificate does not have a CertificatePolicy extension, | |
| 85 * NULL will be stored. If a List is returned, it will be immutable. | |
| 86 * | |
| 87 * PARAMETERS | |
| 88 * "nssCert" | |
| 89 * Address of the Cert data whose extension is to be examined. Must be | |
| 90 * non-NULL. | |
| 91 * "pCertPolicyInfos" | |
| 92 * Address where the List of CertPolicyInfos will be stored. Must be | |
| 93 * non-NULL. | |
| 94 * "plContext" | |
| 95 * Platform-specific context pointer. | |
| 96 * THREAD SAFETY: | |
| 97 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
| 98 * RETURNS: | |
| 99 * Returns NULL if the function succeeds. | |
| 100 * Returns a Cert Error if the function fails in a non-fatal way. | |
| 101 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
| 102 */ | |
| 103 static PKIX_Error * | |
| 104 pkix_pl_Cert_DecodePolicyInfo( | |
| 105 CERTCertificate *nssCert, | |
| 106 PKIX_List **pCertPolicyInfos, | |
| 107 void *plContext) | |
| 108 { | |
| 109 | |
| 110 SECStatus rv; | |
| 111 SECItem encodedCertPolicyInfo; | |
| 112 | |
| 113 /* Allocated in the arena; freed in CERT_Destroy... */ | |
| 114 CERTCertificatePolicies *certPol = NULL; | |
| 115 CERTPolicyInfo **policyInfos = NULL; | |
| 116 | |
| 117 /* Holder for the return value */ | |
| 118 PKIX_List *infos = NULL; | |
| 119 | |
| 120 PKIX_PL_OID *pkixOID = NULL; | |
| 121 PKIX_List *qualifiers = NULL; | |
| 122 PKIX_PL_CertPolicyInfo *certPolicyInfo = NULL; | |
| 123 PKIX_PL_CertPolicyQualifier *certPolicyQualifier = NULL; | |
| 124 PKIX_PL_ByteArray *qualifierArray = NULL; | |
| 125 | |
| 126 PKIX_ENTER(CERT, "pkix_pl_Cert_DecodePolicyInfo"); | |
| 127 PKIX_NULLCHECK_TWO(nssCert, pCertPolicyInfos); | |
| 128 | |
| 129 /* get PolicyInfo as a SECItem */ | |
| 130 PKIX_CERT_DEBUG("\t\tCERT_FindCertExtension).\n"); | |
| 131 rv = CERT_FindCertExtension | |
| 132 (nssCert, | |
| 133 SEC_OID_X509_CERTIFICATE_POLICIES, | |
| 134 &encodedCertPolicyInfo); | |
| 135 if (SECSuccess != rv) { | |
| 136 *pCertPolicyInfos = NULL; | |
| 137 goto cleanup; | |
| 138 } | |
| 139 | |
| 140 /* translate PolicyInfo to CERTCertificatePolicies */ | |
| 141 PKIX_CERT_DEBUG("\t\tCERT_DecodeCertificatePoliciesExtension).\n"); | |
| 142 certPol = CERT_DecodeCertificatePoliciesExtension | |
| 143 (&encodedCertPolicyInfo); | |
| 144 | |
| 145 PORT_Free(encodedCertPolicyInfo.data); | |
| 146 | |
| 147 if (NULL == certPol) { | |
| 148 PKIX_ERROR(PKIX_CERTDECODECERTIFICATEPOLICIESEXTENSIONFAILED); | |
| 149 } | |
| 150 | |
| 151 /* | |
| 152 * Check whether there are any policyInfos, so we can | |
| 153 * avoid creating an unnecessary List | |
| 154 */ | |
| 155 policyInfos = certPol->policyInfos; | |
| 156 if (!policyInfos) { | |
| 157 *pCertPolicyInfos = NULL; | |
| 158 goto cleanup; | |
| 159 } | |
| 160 | |
| 161 /* create a List of CertPolicyInfo Objects */ | |
| 162 PKIX_CHECK(PKIX_List_Create(&infos, plContext), | |
| 163 PKIX_LISTCREATEFAILED); | |
| 164 | |
| 165 /* | |
| 166 * Traverse the CERTCertificatePolicies structure, | |
| 167 * building each PKIX_PL_CertPolicyInfo object in turn | |
| 168 */ | |
| 169 while (*policyInfos != NULL) { | |
| 170 CERTPolicyInfo *policyInfo = *policyInfos; | |
| 171 CERTPolicyQualifier **policyQualifiers = | |
| 172 policyInfo->policyQualifiers; | |
| 173 if (policyQualifiers) { | |
| 174 /* create a PKIX_List of PKIX_PL_CertPolicyQualifiers */ | |
| 175 PKIX_CHECK(PKIX_List_Create(&qualifiers, plContext), | |
| 176 PKIX_LISTCREATEFAILED); | |
| 177 | |
| 178 while (*policyQualifiers != NULL) { | |
| 179 CERTPolicyQualifier *policyQualifier = | |
| 180 *policyQualifiers; | |
| 181 | |
| 182 /* create the qualifier's OID object */ | |
| 183 PKIX_CHECK(PKIX_PL_OID_CreateBySECItem | |
| 184 (&policyQualifier->qualifierID, | |
| 185 &pkixOID, plContext), | |
| 186 PKIX_OIDCREATEFAILED); | |
| 187 | |
| 188 /* create qualifier's ByteArray object */ | |
| 189 | |
| 190 PKIX_CHECK(PKIX_PL_ByteArray_Create | |
| 191 (policyQualifier->qualifierValue.data, | |
| 192 policyQualifier->qualifierValue.len, | |
| 193 &qualifierArray, | |
| 194 plContext), | |
| 195 PKIX_BYTEARRAYCREATEFAILED); | |
| 196 | |
| 197 /* create a CertPolicyQualifier object */ | |
| 198 | |
| 199 PKIX_CHECK(pkix_pl_CertPolicyQualifier_Create | |
| 200 (pkixOID, | |
| 201 qualifierArray, | |
| 202 &certPolicyQualifier, | |
| 203 plContext), | |
| 204 PKIX_CERTPOLICYQUALIFIERCREATEFAILED); | |
| 205 | |
| 206 PKIX_CHECK(PKIX_List_AppendItem | |
| 207 (qualifiers, | |
| 208 (PKIX_PL_Object *)certPolicyQualifier, | |
| 209 plContext), | |
| 210 PKIX_LISTAPPENDITEMFAILED); | |
| 211 | |
| 212 PKIX_DECREF(pkixOID); | |
| 213 PKIX_DECREF(qualifierArray); | |
| 214 PKIX_DECREF(certPolicyQualifier); | |
| 215 | |
| 216 policyQualifiers++; | |
| 217 } | |
| 218 | |
| 219 PKIX_CHECK(PKIX_List_SetImmutable | |
| 220 (qualifiers, plContext), | |
| 221 PKIX_LISTSETIMMUTABLEFAILED); | |
| 222 } | |
| 223 | |
| 224 | |
| 225 /* | |
| 226 * Create an OID object pkixOID from policyInfo->policyID. | |
| 227 * (The CERTPolicyInfo structure has an oid field, but it | |
| 228 * is of type SECOidTag. This function wants a SECItem.) | |
| 229 */ | |
| 230 PKIX_CHECK(PKIX_PL_OID_CreateBySECItem | |
| 231 (&policyInfo->policyID, &pkixOID, plContext), | |
| 232 PKIX_OIDCREATEFAILED); | |
| 233 | |
| 234 /* Create a CertPolicyInfo object */ | |
| 235 PKIX_CHECK(pkix_pl_CertPolicyInfo_Create | |
| 236 (pkixOID, qualifiers, &certPolicyInfo, plContext), | |
| 237 PKIX_CERTPOLICYINFOCREATEFAILED); | |
| 238 | |
| 239 /* Append the new CertPolicyInfo object to the list */ | |
| 240 PKIX_CHECK(PKIX_List_AppendItem | |
| 241 (infos, (PKIX_PL_Object *)certPolicyInfo, plContext), | |
| 242 PKIX_LISTAPPENDITEMFAILED); | |
| 243 | |
| 244 PKIX_DECREF(pkixOID); | |
| 245 PKIX_DECREF(qualifiers); | |
| 246 PKIX_DECREF(certPolicyInfo); | |
| 247 | |
| 248 policyInfos++; | |
| 249 } | |
| 250 | |
| 251 /* | |
| 252 * If there were no policies, we went straight to | |
| 253 * cleanup, so we don't have to NULLCHECK infos. | |
| 254 */ | |
| 255 PKIX_CHECK(PKIX_List_SetImmutable(infos, plContext), | |
| 256 PKIX_LISTSETIMMUTABLEFAILED); | |
| 257 | |
| 258 *pCertPolicyInfos = infos; | |
| 259 infos = NULL; | |
| 260 | |
| 261 cleanup: | |
| 262 if (certPol) { | |
| 263 PKIX_CERT_DEBUG | |
| 264 ("\t\tCalling CERT_DestroyCertificatePoliciesExtension).\n"); | |
| 265 CERT_DestroyCertificatePoliciesExtension(certPol); | |
| 266 } | |
| 267 | |
| 268 PKIX_DECREF(infos); | |
| 269 PKIX_DECREF(pkixOID); | |
| 270 PKIX_DECREF(qualifiers); | |
| 271 PKIX_DECREF(certPolicyInfo); | |
| 272 PKIX_DECREF(certPolicyQualifier); | |
| 273 PKIX_DECREF(qualifierArray); | |
| 274 | |
| 275 PKIX_RETURN(CERT); | |
| 276 } | |
| 277 | |
| 278 /* | |
| 279 * FUNCTION: pkix_pl_Cert_DecodePolicyMapping | |
| 280 * DESCRIPTION: | |
| 281 * | |
| 282 * Decodes the contents of the PolicyMapping extension of the CERTCertificate | |
| 283 * pointed to by "nssCert", storing the resulting List of CertPolicyMaps at | |
| 284 * the address pointed to by "pCertPolicyMaps". If this certificate does not | |
| 285 * have a PolicyMapping extension, NULL will be stored. If a List is returned, | |
| 286 * it will be immutable. | |
| 287 * | |
| 288 * PARAMETERS | |
| 289 * "nssCert" | |
| 290 * Address of the Cert data whose extension is to be examined. Must be | |
| 291 * non-NULL. | |
| 292 * "pCertPolicyMaps" | |
| 293 * Address where the List of CertPolicyMaps will be stored. Must be | |
| 294 * non-NULL. | |
| 295 * "plContext" | |
| 296 * Platform-specific context pointer. | |
| 297 * THREAD SAFETY: | |
| 298 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
| 299 * RETURNS: | |
| 300 * Returns NULL if the function succeeds. | |
| 301 * Returns a Cert Error if the function fails in a non-fatal way. | |
| 302 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
| 303 */ | |
| 304 static PKIX_Error * | |
| 305 pkix_pl_Cert_DecodePolicyMapping( | |
| 306 CERTCertificate *nssCert, | |
| 307 PKIX_List **pCertPolicyMaps, | |
| 308 void *plContext) | |
| 309 { | |
| 310 SECStatus rv; | |
| 311 SECItem encodedCertPolicyMaps; | |
| 312 | |
| 313 /* Allocated in the arena; freed in CERT_Destroy... */ | |
| 314 CERTCertificatePolicyMappings *certPolMaps = NULL; | |
| 315 CERTPolicyMap **policyMaps = NULL; | |
| 316 | |
| 317 /* Holder for the return value */ | |
| 318 PKIX_List *maps = NULL; | |
| 319 | |
| 320 PKIX_PL_OID *issuerDomainOID = NULL; | |
| 321 PKIX_PL_OID *subjectDomainOID = NULL; | |
| 322 PKIX_PL_CertPolicyMap *certPolicyMap = NULL; | |
| 323 | |
| 324 PKIX_ENTER(CERT, "pkix_pl_Cert_DecodePolicyMapping"); | |
| 325 PKIX_NULLCHECK_TWO(nssCert, pCertPolicyMaps); | |
| 326 | |
| 327 /* get PolicyMappings as a SECItem */ | |
| 328 PKIX_CERT_DEBUG("\t\tCERT_FindCertExtension).\n"); | |
| 329 rv = CERT_FindCertExtension | |
| 330 (nssCert, SEC_OID_X509_POLICY_MAPPINGS, &encodedCertPolicyMaps); | |
| 331 if (SECSuccess != rv) { | |
| 332 *pCertPolicyMaps = NULL; | |
| 333 goto cleanup; | |
| 334 } | |
| 335 | |
| 336 /* translate PolicyMaps to CERTCertificatePolicyMappings */ | |
| 337 certPolMaps = CERT_DecodePolicyMappingsExtension | |
| 338 (&encodedCertPolicyMaps); | |
| 339 | |
| 340 PORT_Free(encodedCertPolicyMaps.data); | |
| 341 | |
| 342 if (!certPolMaps) { | |
| 343 PKIX_ERROR(PKIX_CERTDECODEPOLICYMAPPINGSEXTENSIONFAILED); | |
| 344 } | |
| 345 | |
| 346 PKIX_NULLCHECK_ONE(certPolMaps->policyMaps); | |
| 347 | |
| 348 policyMaps = certPolMaps->policyMaps; | |
| 349 | |
| 350 /* create a List of CertPolicyMap Objects */ | |
| 351 PKIX_CHECK(PKIX_List_Create(&maps, plContext), | |
| 352 PKIX_LISTCREATEFAILED); | |
| 353 | |
| 354 /* | |
| 355 * Traverse the CERTCertificatePolicyMappings structure, | |
| 356 * building each CertPolicyMap object in turn | |
| 357 */ | |
| 358 do { | |
| 359 CERTPolicyMap *policyMap = *policyMaps; | |
| 360 | |
| 361 /* create the OID for the issuer Domain Policy */ | |
| 362 PKIX_CHECK(PKIX_PL_OID_CreateBySECItem | |
| 363 (&policyMap->issuerDomainPolicy, | |
| 364 &issuerDomainOID, plContext), | |
| 365 PKIX_OIDCREATEFAILED); | |
| 366 | |
| 367 /* create the OID for the subject Domain Policy */ | |
| 368 PKIX_CHECK(PKIX_PL_OID_CreateBySECItem | |
| 369 (&policyMap->subjectDomainPolicy, | |
| 370 &subjectDomainOID, plContext), | |
| 371 PKIX_OIDCREATEFAILED); | |
| 372 | |
| 373 /* create the CertPolicyMap */ | |
| 374 | |
| 375 PKIX_CHECK(pkix_pl_CertPolicyMap_Create | |
| 376 (issuerDomainOID, | |
| 377 subjectDomainOID, | |
| 378 &certPolicyMap, | |
| 379 plContext), | |
| 380 PKIX_CERTPOLICYMAPCREATEFAILED); | |
| 381 | |
| 382 PKIX_CHECK(PKIX_List_AppendItem | |
| 383 (maps, (PKIX_PL_Object *)certPolicyMap, plContext), | |
| 384 PKIX_LISTAPPENDITEMFAILED); | |
| 385 | |
| 386 PKIX_DECREF(issuerDomainOID); | |
| 387 PKIX_DECREF(subjectDomainOID); | |
| 388 PKIX_DECREF(certPolicyMap); | |
| 389 | |
| 390 policyMaps++; | |
| 391 } while (*policyMaps != NULL); | |
| 392 | |
| 393 PKIX_CHECK(PKIX_List_SetImmutable(maps, plContext), | |
| 394 PKIX_LISTSETIMMUTABLEFAILED); | |
| 395 | |
| 396 *pCertPolicyMaps = maps; | |
| 397 maps = NULL; | |
| 398 | |
| 399 cleanup: | |
| 400 if (certPolMaps) { | |
| 401 PKIX_CERT_DEBUG | |
| 402 ("\t\tCalling CERT_DestroyPolicyMappingsExtension).\n"); | |
| 403 CERT_DestroyPolicyMappingsExtension(certPolMaps); | |
| 404 } | |
| 405 | |
| 406 PKIX_DECREF(maps); | |
| 407 PKIX_DECREF(issuerDomainOID); | |
| 408 PKIX_DECREF(subjectDomainOID); | |
| 409 PKIX_DECREF(certPolicyMap); | |
| 410 | |
| 411 PKIX_RETURN(CERT); | |
| 412 } | |
| 413 | |
| 414 /* | |
| 415 * FUNCTION: pkix_pl_Cert_DecodePolicyConstraints | |
| 416 * DESCRIPTION: | |
| 417 * | |
| 418 * Decodes the contents of the PolicyConstraints extension in the | |
| 419 * CERTCertificate pointed to by "nssCert", to obtain SkipCerts values | |
| 420 * which are stored at the addresses "pExplicitPolicySkipCerts" and | |
| 421 * "pInhibitMappingSkipCerts", respectively. If this certificate does | |
| 422 * not have an PolicyConstraints extension, or if either of the optional | |
| 423 * components is not supplied, this function stores a value of -1 for any | |
| 424 * missing component. | |
| 425 * | |
| 426 * PARAMETERS | |
| 427 * "nssCert" | |
| 428 * Address of the Cert data whose extension is to be examined. Must be | |
| 429 * non-NULL. | |
| 430 * "pExplicitPolicySkipCerts" | |
| 431 * Address where the SkipCert value for the requireExplicitPolicy | |
| 432 * component will be stored. Must be non-NULL. | |
| 433 * "pInhibitMappingSkipCerts" | |
| 434 * Address where the SkipCert value for the inhibitPolicyMapping | |
| 435 * component will be stored. Must be non-NULL. | |
| 436 * "plContext" | |
| 437 * Platform-specific context pointer. | |
| 438 * THREAD SAFETY: | |
| 439 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
| 440 * RETURNS: | |
| 441 * Returns NULL if the function succeeds. | |
| 442 * Returns a Cert Error if the function fails in a non-fatal way. | |
| 443 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
| 444 */ | |
| 445 static PKIX_Error * | |
| 446 pkix_pl_Cert_DecodePolicyConstraints( | |
| 447 CERTCertificate *nssCert, | |
| 448 PKIX_Int32 *pExplicitPolicySkipCerts, | |
| 449 PKIX_Int32 *pInhibitMappingSkipCerts, | |
| 450 void *plContext) | |
| 451 { | |
| 452 CERTCertificatePolicyConstraints policyConstraints; | |
| 453 SECStatus rv; | |
| 454 SECItem encodedCertPolicyConstraints; | |
| 455 PKIX_Int32 explicitPolicySkipCerts = -1; | |
| 456 PKIX_Int32 inhibitMappingSkipCerts = -1; | |
| 457 | |
| 458 PKIX_ENTER(CERT, "pkix_pl_Cert_DecodePolicyConstraints"); | |
| 459 PKIX_NULLCHECK_THREE | |
| 460 (nssCert, pExplicitPolicySkipCerts, pInhibitMappingSkipCerts); | |
| 461 | |
| 462 /* get the two skipCert values as SECItems */ | |
| 463 PKIX_CERT_DEBUG("\t\tCalling CERT_FindCertExtension).\n"); | |
| 464 rv = CERT_FindCertExtension | |
| 465 (nssCert, | |
| 466 SEC_OID_X509_POLICY_CONSTRAINTS, | |
| 467 &encodedCertPolicyConstraints); | |
| 468 | |
| 469 if (rv == SECSuccess) { | |
| 470 | |
| 471 policyConstraints.explicitPolicySkipCerts.data = | |
| 472 (unsigned char *)&explicitPolicySkipCerts; | |
| 473 policyConstraints.inhibitMappingSkipCerts.data = | |
| 474 (unsigned char *)&inhibitMappingSkipCerts; | |
| 475 | |
| 476 /* translate DER to CERTCertificatePolicyConstraints */ | |
| 477 rv = CERT_DecodePolicyConstraintsExtension | |
| 478 (&policyConstraints, &encodedCertPolicyConstraints); | |
| 479 | |
| 480 PORT_Free(encodedCertPolicyConstraints.data); | |
| 481 | |
| 482 if (rv != SECSuccess) { | |
| 483 PKIX_ERROR | |
| 484 (PKIX_CERTDECODEPOLICYCONSTRAINTSEXTENSIONFAILED); | |
| 485 } | |
| 486 } | |
| 487 | |
| 488 *pExplicitPolicySkipCerts = explicitPolicySkipCerts; | |
| 489 *pInhibitMappingSkipCerts = inhibitMappingSkipCerts; | |
| 490 | |
| 491 cleanup: | |
| 492 PKIX_RETURN(CERT); | |
| 493 } | |
| 494 | |
| 495 /* | |
| 496 * FUNCTION: pkix_pl_Cert_DecodeInhibitAnyPolicy | |
| 497 * DESCRIPTION: | |
| 498 * | |
| 499 * Decodes the contents of the InhibitAnyPolicy extension in the | |
| 500 * CERTCertificate pointed to by "nssCert", to obtain a SkipCerts value, | |
| 501 * which is stored at the address "pSkipCerts". If this certificate does | |
| 502 * not have an InhibitAnyPolicy extension, -1 will be stored. | |
| 503 * | |
| 504 * PARAMETERS | |
| 505 * "nssCert" | |
| 506 * Address of the Cert data whose InhibitAnyPolicy extension is to be | |
| 507 * processed. Must be non-NULL. | |
| 508 * "pSkipCerts" | |
| 509 * Address where the SkipCert value from the InhibitAnyPolicy extension | |
| 510 * will be stored. Must be non-NULL. | |
| 511 * "plContext" | |
| 512 * Platform-specific context pointer. | |
| 513 * THREAD SAFETY: | |
| 514 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
| 515 * RETURNS: | |
| 516 * Returns NULL if the function succeeds. | |
| 517 * Returns a Cert Error if the function fails in a non-fatal way. | |
| 518 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
| 519 */ | |
| 520 PKIX_Error * | |
| 521 pkix_pl_Cert_DecodeInhibitAnyPolicy( | |
| 522 CERTCertificate *nssCert, | |
| 523 PKIX_Int32 *pSkipCerts, | |
| 524 void *plContext) | |
| 525 { | |
| 526 CERTCertificateInhibitAny inhibitAny; | |
| 527 SECStatus rv; | |
| 528 SECItem encodedCertInhibitAny; | |
| 529 PKIX_Int32 skipCerts = -1; | |
| 530 | |
| 531 PKIX_ENTER(CERT, "pkix_pl_Cert_DecodeInhibitAnyPolicy"); | |
| 532 PKIX_NULLCHECK_TWO(nssCert, pSkipCerts); | |
| 533 | |
| 534 /* get InhibitAny as a SECItem */ | |
| 535 PKIX_CERT_DEBUG("\t\tCalling CERT_FindCertExtension).\n"); | |
| 536 rv = CERT_FindCertExtension | |
| 537 (nssCert, SEC_OID_X509_INHIBIT_ANY_POLICY, &encodedCertInhibitAn
y); | |
| 538 | |
| 539 if (rv == SECSuccess) { | |
| 540 inhibitAny.inhibitAnySkipCerts.data = | |
| 541 (unsigned char *)&skipCerts; | |
| 542 | |
| 543 /* translate DER to CERTCertificateInhibitAny */ | |
| 544 rv = CERT_DecodeInhibitAnyExtension | |
| 545 (&inhibitAny, &encodedCertInhibitAny); | |
| 546 | |
| 547 PORT_Free(encodedCertInhibitAny.data); | |
| 548 | |
| 549 if (rv != SECSuccess) { | |
| 550 PKIX_ERROR(PKIX_CERTDECODEINHIBITANYEXTENSIONFAILED); | |
| 551 } | |
| 552 } | |
| 553 | |
| 554 *pSkipCerts = skipCerts; | |
| 555 | |
| 556 cleanup: | |
| 557 PKIX_RETURN(CERT); | |
| 558 } | |
| 559 | |
| 560 /* | |
| 561 * FUNCTION: pkix_pl_Cert_GetNssSubjectAltNames | |
| 562 * DESCRIPTION: | |
| 563 * | |
| 564 * Retrieves the Subject Alternative Names of the certificate specified by | |
| 565 * "cert" and stores it at "pNssSubjAltNames". If the Subject Alternative | |
| 566 * Name extension is not present, NULL is returned at "pNssSubjAltNames". | |
| 567 * If the Subject Alternative Names has not been previously decoded, it is | |
| 568 * decoded here with lock on the "cert" unless the flag "hasLock" indicates | |
| 569 * the lock had been obtained at a higher call level. | |
| 570 * | |
| 571 * PARAMETERS | |
| 572 * "cert" | |
| 573 * Address of the certificate whose Subject Alternative Names extensions | |
| 574 * is retrieved. Must be non-NULL. | |
| 575 * "hasLock" | |
| 576 * Boolean indicates caller has acquired a lock. | |
| 577 * Must be non-NULL. | |
| 578 * "pNssSubjAltNames" | |
| 579 * Address where the returned Subject Alternative Names will be stored. | |
| 580 * Must be non-NULL. | |
| 581 * "plContext" | |
| 582 * Platform-specific context pointer. | |
| 583 * THREAD SAFETY: | |
| 584 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
| 585 * RETURNS: | |
| 586 * Returns NULL if the function succeeds. | |
| 587 * Returns a Cert Error if the function fails in a non-fatal way. | |
| 588 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
| 589 */ | |
| 590 static PKIX_Error * | |
| 591 pkix_pl_Cert_GetNssSubjectAltNames( | |
| 592 PKIX_PL_Cert *cert, | |
| 593 PKIX_Boolean hasLock, | |
| 594 CERTGeneralName **pNssSubjAltNames, | |
| 595 void *plContext) | |
| 596 { | |
| 597 CERTCertificate *nssCert = NULL; | |
| 598 CERTGeneralName *nssOriginalAltName = NULL; | |
| 599 PLArenaPool *arena = NULL; | |
| 600 SECItem altNameExtension = {siBuffer, NULL, 0}; | |
| 601 SECStatus rv = SECFailure; | |
| 602 | |
| 603 PKIX_ENTER(CERT, "pkix_pl_Cert_GetNssSubjectAltNames"); | |
| 604 PKIX_NULLCHECK_THREE(cert, pNssSubjAltNames, cert->nssCert); | |
| 605 | |
| 606 nssCert = cert->nssCert; | |
| 607 | |
| 608 if ((cert->nssSubjAltNames == NULL) && (!cert->subjAltNamesAbsent)){ | |
| 609 | |
| 610 if (!hasLock) { | |
| 611 PKIX_OBJECT_LOCK(cert); | |
| 612 } | |
| 613 | |
| 614 if ((cert->nssSubjAltNames == NULL) && | |
| 615 (!cert->subjAltNamesAbsent)){ | |
| 616 | |
| 617 PKIX_PL_NSSCALLRV(CERT, rv, CERT_FindCertExtension, | |
| 618 (nssCert, | |
| 619 SEC_OID_X509_SUBJECT_ALT_NAME, | |
| 620 &altNameExtension)); | |
| 621 | |
| 622 if (rv != SECSuccess) { | |
| 623 *pNssSubjAltNames = NULL; | |
| 624 cert->subjAltNamesAbsent = PKIX_TRUE; | |
| 625 goto cleanup; | |
| 626 } | |
| 627 | |
| 628 if (cert->arenaNameConstraints == NULL) { | |
| 629 PKIX_PL_NSSCALLRV(CERT, arena, PORT_NewArena, | |
| 630 (DER_DEFAULT_CHUNKSIZE)); | |
| 631 | |
| 632 if (arena == NULL) { | |
| 633 PKIX_ERROR(PKIX_OUTOFMEMORY); | |
| 634 } | |
| 635 cert->arenaNameConstraints = arena; | |
| 636 } | |
| 637 | |
| 638 PKIX_PL_NSSCALLRV | |
| 639 (CERT, | |
| 640 nssOriginalAltName, | |
| 641 (CERTGeneralName *) CERT_DecodeAltNameExtension, | |
| 642 (cert->arenaNameConstraints, &altNameExtension)); | |
| 643 | |
| 644 PKIX_PL_NSSCALL(CERT, PORT_Free, (altNameExtension.data)); | |
| 645 | |
| 646 if (nssOriginalAltName == NULL) { | |
| 647 PKIX_ERROR(PKIX_CERTDECODEALTNAMEEXTENSIONFAILED); | |
| 648 } | |
| 649 cert->nssSubjAltNames = nssOriginalAltName; | |
| 650 | |
| 651 } | |
| 652 | |
| 653 if (!hasLock) { | |
| 654 PKIX_OBJECT_UNLOCK(cert); | |
| 655 } | |
| 656 } | |
| 657 | |
| 658 *pNssSubjAltNames = cert->nssSubjAltNames; | |
| 659 | |
| 660 cleanup: | |
| 661 PKIX_OBJECT_UNLOCK(lockedObject); | |
| 662 PKIX_RETURN(CERT); | |
| 663 } | |
| 664 | |
| 665 /* | |
| 666 * FUNCTION: pkix_pl_Cert_CheckExtendKeyUsage | |
| 667 * DESCRIPTION: | |
| 668 * | |
| 669 * For each of the ON bit in "requiredExtendedKeyUsages" that represents its | |
| 670 * SECCertUsageEnum type, this function checks "cert"'s certType (extended | |
| 671 * key usage) and key usage with what is required for SECCertUsageEnum type. | |
| 672 * | |
| 673 * PARAMETERS | |
| 674 * "cert" | |
| 675 * Address of the certificate whose Extended Key Usage extensions | |
| 676 * is retrieved. Must be non-NULL. | |
| 677 * "requiredExtendedKeyUsages" | |
| 678 * An unsigned integer, its bit location is ON based on the required key | |
| 679 * usage value representing in SECCertUsageEnum. | |
| 680 * "pPass" | |
| 681 * Address where the return value, indicating key usage check passed, is | |
| 682 * stored. Must be non-NULL. | |
| 683 * "plContext" | |
| 684 * Platform-specific context pointer. | |
| 685 * THREAD SAFETY: | |
| 686 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
| 687 * RETURNS: | |
| 688 * Returns NULL if the function succeeds. | |
| 689 * Returns a Cert Error if the function fails in a non-fatal way. | |
| 690 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
| 691 */ | |
| 692 PKIX_Error * | |
| 693 pkix_pl_Cert_CheckExtendedKeyUsage( | |
| 694 PKIX_PL_Cert *cert, | |
| 695 PKIX_UInt32 requiredExtendedKeyUsages, | |
| 696 PKIX_Boolean *pPass, | |
| 697 void *plContext) | |
| 698 { | |
| 699 PKIX_PL_CertBasicConstraints *basicConstraints = NULL; | |
| 700 PKIX_UInt32 certType = 0; | |
| 701 PKIX_UInt32 requiredKeyUsage = 0; | |
| 702 PKIX_UInt32 requiredCertType = 0; | |
| 703 PKIX_UInt32 requiredExtendedKeyUsage = 0; | |
| 704 PKIX_UInt32 i; | |
| 705 PKIX_Boolean isCA = PKIX_FALSE; | |
| 706 SECStatus rv = SECFailure; | |
| 707 | |
| 708 PKIX_ENTER(CERT, "pkix_pl_Cert_CheckExtendKeyUsage"); | |
| 709 PKIX_NULLCHECK_THREE(cert, pPass, cert->nssCert); | |
| 710 | |
| 711 *pPass = PKIX_FALSE; | |
| 712 | |
| 713 PKIX_CERT_DEBUG("\t\tCalling cert_GetCertType).\n"); | |
| 714 cert_GetCertType(cert->nssCert); | |
| 715 certType = cert->nssCert->nsCertType; | |
| 716 | |
| 717 PKIX_CHECK(PKIX_PL_Cert_GetBasicConstraints | |
| 718 (cert, | |
| 719 &basicConstraints, | |
| 720 plContext), | |
| 721 PKIX_CERTGETBASICCONSTRAINTFAILED); | |
| 722 | |
| 723 if (basicConstraints != NULL) { | |
| 724 PKIX_CHECK(PKIX_PL_BasicConstraints_GetCAFlag | |
| 725 (basicConstraints, &isCA, plContext), | |
| 726 PKIX_BASICCONSTRAINTSGETCAFLAGFAILED); | |
| 727 } | |
| 728 | |
| 729 i = 0; | |
| 730 while (requiredExtendedKeyUsages != 0) { | |
| 731 | |
| 732 /* Find the bit location of the right-most non-zero bit */ | |
| 733 while (requiredExtendedKeyUsages != 0) { | |
| 734 if (((1 << i) & requiredExtendedKeyUsages) != 0) { | |
| 735 requiredExtendedKeyUsage = 1 << i; | |
| 736 break; | |
| 737 } | |
| 738 i++; | |
| 739 } | |
| 740 requiredExtendedKeyUsages ^= requiredExtendedKeyUsage; | |
| 741 | |
| 742 requiredExtendedKeyUsage = i; | |
| 743 | |
| 744 PKIX_PL_NSSCALLRV(CERT, rv, CERT_KeyUsageAndTypeForCertUsage, | |
| 745 (requiredExtendedKeyUsage, | |
| 746 isCA, | |
| 747 &requiredKeyUsage, | |
| 748 &requiredCertType)); | |
| 749 | |
| 750 if (!(certType & requiredCertType)) { | |
| 751 goto cleanup; | |
| 752 } | |
| 753 | |
| 754 PKIX_PL_NSSCALLRV(CERT, rv, CERT_CheckKeyUsage, | |
| 755 (cert->nssCert, requiredKeyUsage)); | |
| 756 if (rv != SECSuccess) { | |
| 757 goto cleanup; | |
| 758 } | |
| 759 i++; | |
| 760 | |
| 761 } | |
| 762 | |
| 763 *pPass = PKIX_TRUE; | |
| 764 | |
| 765 cleanup: | |
| 766 PKIX_DECREF(basicConstraints); | |
| 767 PKIX_RETURN(CERT); | |
| 768 } | |
| 769 | |
| 770 /* | |
| 771 * FUNCTION: pkix_pl_Cert_ToString_Helper | |
| 772 * DESCRIPTION: | |
| 773 * | |
| 774 * Helper function that creates a string representation of the Cert pointed | |
| 775 * to by "cert" and stores it at "pString", where the value of | |
| 776 * "partialString" determines whether a full or partial representation of | |
| 777 * the Cert is stored. | |
| 778 * | |
| 779 * PARAMETERS | |
| 780 * "cert" | |
| 781 * Address of Cert whose string representation is desired. | |
| 782 * Must be non-NULL. | |
| 783 * "partialString" | |
| 784 * Boolean indicating whether a partial Cert representation is desired. | |
| 785 * "pString" | |
| 786 * Address where object pointer will be stored. Must be non-NULL. | |
| 787 * "plContext" | |
| 788 * Platform-specific context pointer. | |
| 789 * THREAD SAFETY: | |
| 790 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
| 791 * RETURNS: | |
| 792 * Returns NULL if the function succeeds. | |
| 793 * Returns a Cert Error if the function fails in a non-fatal way. | |
| 794 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
| 795 */ | |
| 796 PKIX_Error * | |
| 797 pkix_pl_Cert_ToString_Helper( | |
| 798 PKIX_PL_Cert *cert, | |
| 799 PKIX_Boolean partialString, | |
| 800 PKIX_PL_String **pString, | |
| 801 void *plContext) | |
| 802 { | |
| 803 PKIX_PL_String *certString = NULL; | |
| 804 char *asciiFormat = NULL; | |
| 805 PKIX_PL_String *formatString = NULL; | |
| 806 PKIX_UInt32 certVersion; | |
| 807 PKIX_PL_BigInt *certSN = NULL; | |
| 808 PKIX_PL_String *certSNString = NULL; | |
| 809 PKIX_PL_X500Name *certIssuer = NULL; | |
| 810 PKIX_PL_String *certIssuerString = NULL; | |
| 811 PKIX_PL_X500Name *certSubject = NULL; | |
| 812 PKIX_PL_String *certSubjectString = NULL; | |
| 813 PKIX_PL_String *notBeforeString = NULL; | |
| 814 PKIX_PL_String *notAfterString = NULL; | |
| 815 PKIX_List *subjAltNames = NULL; | |
| 816 PKIX_PL_String *subjAltNamesString = NULL; | |
| 817 PKIX_PL_ByteArray *authKeyId = NULL; | |
| 818 PKIX_PL_String *authKeyIdString = NULL; | |
| 819 PKIX_PL_ByteArray *subjKeyId = NULL; | |
| 820 PKIX_PL_String *subjKeyIdString = NULL; | |
| 821 PKIX_PL_PublicKey *nssPubKey = NULL; | |
| 822 PKIX_PL_String *nssPubKeyString = NULL; | |
| 823 PKIX_List *critExtOIDs = NULL; | |
| 824 PKIX_PL_String *critExtOIDsString = NULL; | |
| 825 PKIX_List *extKeyUsages = NULL; | |
| 826 PKIX_PL_String *extKeyUsagesString = NULL; | |
| 827 PKIX_PL_CertBasicConstraints *basicConstraint = NULL; | |
| 828 PKIX_PL_String *certBasicConstraintsString = NULL; | |
| 829 PKIX_List *policyInfo = NULL; | |
| 830 PKIX_PL_String *certPolicyInfoString = NULL; | |
| 831 PKIX_List *certPolicyMappings = NULL; | |
| 832 PKIX_PL_String *certPolicyMappingsString = NULL; | |
| 833 PKIX_Int32 certExplicitPolicy = 0; | |
| 834 PKIX_Int32 certInhibitMapping = 0; | |
| 835 PKIX_Int32 certInhibitAnyPolicy = 0; | |
| 836 PKIX_PL_CertNameConstraints *nameConstraints = NULL; | |
| 837 PKIX_PL_String *nameConstraintsString = NULL; | |
| 838 PKIX_List *authorityInfoAccess = NULL; | |
| 839 PKIX_PL_String *authorityInfoAccessString = NULL; | |
| 840 PKIX_List *subjectInfoAccess = NULL; | |
| 841 PKIX_PL_String *subjectInfoAccessString = NULL; | |
| 842 | |
| 843 PKIX_ENTER(CERT, "pkix_pl_Cert_ToString_Helper"); | |
| 844 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pString); | |
| 845 | |
| 846 /* | |
| 847 * XXX Add to this format as certificate components are developed. | |
| 848 */ | |
| 849 | |
| 850 if (partialString){ | |
| 851 asciiFormat = | |
| 852 "\t[Issuer: %s\n" | |
| 853 "\t Subject: %s]"; | |
| 854 } else { | |
| 855 asciiFormat = | |
| 856 "[\n" | |
| 857 "\tVersion: v%d\n" | |
| 858 "\tSerialNumber: %s\n" | |
| 859 "\tIssuer: %s\n" | |
| 860 "\tSubject: %s\n" | |
| 861 "\tValidity: [From: %s\n" | |
| 862 "\t To: %s]\n" | |
| 863 "\tSubjectAltNames: %s\n" | |
| 864 "\tAuthorityKeyId: %s\n" | |
| 865 "\tSubjectKeyId: %s\n" | |
| 866 "\tSubjPubKeyAlgId: %s\n" | |
| 867 "\tCritExtOIDs: %s\n" | |
| 868 "\tExtKeyUsages: %s\n" | |
| 869 "\tBasicConstraint: %s\n" | |
| 870 "\tCertPolicyInfo: %s\n" | |
| 871 "\tPolicyMappings: %s\n" | |
| 872 "\tExplicitPolicy: %d\n" | |
| 873 "\tInhibitMapping: %d\n" | |
| 874 "\tInhibitAnyPolicy:%d\n" | |
| 875 "\tNameConstraints: %s\n" | |
| 876 "\tAuthorityInfoAccess: %s\n" | |
| 877 "\tSubjectInfoAccess: %s\n" | |
| 878 "\tCacheFlag: %d\n" | |
| 879 "]\n"; | |
| 880 } | |
| 881 | |
| 882 | |
| 883 | |
| 884 PKIX_CHECK(PKIX_PL_String_Create | |
| 885 (PKIX_ESCASCII, asciiFormat, 0, &formatString, plContext), | |
| 886 PKIX_STRINGCREATEFAILED); | |
| 887 | |
| 888 /* Issuer */ | |
| 889 PKIX_CHECK(PKIX_PL_Cert_GetIssuer | |
| 890 (cert, &certIssuer, plContext), | |
| 891 PKIX_CERTGETISSUERFAILED); | |
| 892 | |
| 893 PKIX_CHECK(PKIX_PL_Object_ToString | |
| 894 ((PKIX_PL_Object *)certIssuer, &certIssuerString, plContext), | |
| 895 PKIX_X500NAMETOSTRINGFAILED); | |
| 896 | |
| 897 /* Subject */ | |
| 898 PKIX_CHECK(PKIX_PL_Cert_GetSubject(cert, &certSubject, plContext), | |
| 899 PKIX_CERTGETSUBJECTFAILED); | |
| 900 | |
| 901 PKIX_TOSTRING(certSubject, &certSubjectString, plContext, | |
| 902 PKIX_X500NAMETOSTRINGFAILED); | |
| 903 | |
| 904 if (partialString){ | |
| 905 PKIX_CHECK(PKIX_PL_Sprintf | |
| 906 (&certString, | |
| 907 plContext, | |
| 908 formatString, | |
| 909 certIssuerString, | |
| 910 certSubjectString), | |
| 911 PKIX_SPRINTFFAILED); | |
| 912 | |
| 913 *pString = certString; | |
| 914 goto cleanup; | |
| 915 } | |
| 916 | |
| 917 /* Version */ | |
| 918 PKIX_CHECK(PKIX_PL_Cert_GetVersion(cert, &certVersion, plContext), | |
| 919 PKIX_CERTGETVERSIONFAILED); | |
| 920 | |
| 921 /* SerialNumber */ | |
| 922 PKIX_CHECK(PKIX_PL_Cert_GetSerialNumber(cert, &certSN, plContext), | |
| 923 PKIX_CERTGETSERIALNUMBERFAILED); | |
| 924 | |
| 925 PKIX_CHECK(PKIX_PL_Object_ToString | |
| 926 ((PKIX_PL_Object *)certSN, &certSNString, plContext), | |
| 927 PKIX_BIGINTTOSTRINGFAILED); | |
| 928 | |
| 929 /* Validity: NotBefore */ | |
| 930 PKIX_CHECK(pkix_pl_Date_ToString_Helper | |
| 931 (&(cert->nssCert->validity.notBefore), | |
| 932 ¬BeforeString, | |
| 933 plContext), | |
| 934 PKIX_DATETOSTRINGHELPERFAILED); | |
| 935 | |
| 936 /* Validity: NotAfter */ | |
| 937 PKIX_CHECK(pkix_pl_Date_ToString_Helper | |
| 938 (&(cert->nssCert->validity.notAfter), | |
| 939 ¬AfterString, | |
| 940 plContext), | |
| 941 PKIX_DATETOSTRINGHELPERFAILED); | |
| 942 | |
| 943 /* SubjectAltNames */ | |
| 944 PKIX_CHECK(PKIX_PL_Cert_GetSubjectAltNames | |
| 945 (cert, &subjAltNames, plContext), | |
| 946 PKIX_CERTGETSUBJECTALTNAMESFAILED); | |
| 947 | |
| 948 PKIX_TOSTRING(subjAltNames, &subjAltNamesString, plContext, | |
| 949 PKIX_LISTTOSTRINGFAILED); | |
| 950 | |
| 951 /* AuthorityKeyIdentifier */ | |
| 952 PKIX_CHECK(PKIX_PL_Cert_GetAuthorityKeyIdentifier | |
| 953 (cert, &authKeyId, plContext), | |
| 954 PKIX_CERTGETAUTHORITYKEYIDENTIFIERFAILED); | |
| 955 | |
| 956 PKIX_TOSTRING(authKeyId, &authKeyIdString, plContext, | |
| 957 PKIX_BYTEARRAYTOSTRINGFAILED); | |
| 958 | |
| 959 /* SubjectKeyIdentifier */ | |
| 960 PKIX_CHECK(PKIX_PL_Cert_GetSubjectKeyIdentifier | |
| 961 (cert, &subjKeyId, plContext), | |
| 962 PKIX_CERTGETSUBJECTKEYIDENTIFIERFAILED); | |
| 963 | |
| 964 PKIX_TOSTRING(subjKeyId, &subjKeyIdString, plContext, | |
| 965 PKIX_BYTEARRAYTOSTRINGFAILED); | |
| 966 | |
| 967 /* SubjectPublicKey */ | |
| 968 PKIX_CHECK(PKIX_PL_Cert_GetSubjectPublicKey | |
| 969 (cert, &nssPubKey, plContext), | |
| 970 PKIX_CERTGETSUBJECTPUBLICKEYFAILED); | |
| 971 | |
| 972 PKIX_CHECK(PKIX_PL_Object_ToString | |
| 973 ((PKIX_PL_Object *)nssPubKey, &nssPubKeyString, plContext), | |
| 974 PKIX_PUBLICKEYTOSTRINGFAILED); | |
| 975 | |
| 976 /* CriticalExtensionOIDs */ | |
| 977 PKIX_CHECK(PKIX_PL_Cert_GetCriticalExtensionOIDs | |
| 978 (cert, &critExtOIDs, plContext), | |
| 979 PKIX_CERTGETCRITICALEXTENSIONOIDSFAILED); | |
| 980 | |
| 981 PKIX_TOSTRING(critExtOIDs, &critExtOIDsString, plContext, | |
| 982 PKIX_LISTTOSTRINGFAILED); | |
| 983 | |
| 984 /* ExtendedKeyUsages */ | |
| 985 PKIX_CHECK(PKIX_PL_Cert_GetExtendedKeyUsage | |
| 986 (cert, &extKeyUsages, plContext), | |
| 987 PKIX_CERTGETEXTENDEDKEYUSAGEFAILED); | |
| 988 | |
| 989 PKIX_TOSTRING(extKeyUsages, &extKeyUsagesString, plContext, | |
| 990 PKIX_LISTTOSTRINGFAILED); | |
| 991 | |
| 992 /* CertBasicConstraints */ | |
| 993 PKIX_CHECK(PKIX_PL_Cert_GetBasicConstraints | |
| 994 (cert, &basicConstraint, plContext), | |
| 995 PKIX_CERTGETBASICCONSTRAINTSFAILED); | |
| 996 | |
| 997 PKIX_TOSTRING(basicConstraint, &certBasicConstraintsString, plContext, | |
| 998 PKIX_CERTBASICCONSTRAINTSTOSTRINGFAILED); | |
| 999 | |
| 1000 /* CertPolicyInfo */ | |
| 1001 PKIX_CHECK(PKIX_PL_Cert_GetPolicyInformation | |
| 1002 (cert, &policyInfo, plContext), | |
| 1003 PKIX_CERTGETPOLICYINFORMATIONFAILED); | |
| 1004 | |
| 1005 PKIX_TOSTRING(policyInfo, &certPolicyInfoString, plContext, | |
| 1006 PKIX_LISTTOSTRINGFAILED); | |
| 1007 | |
| 1008 /* Advanced Policies */ | |
| 1009 PKIX_CHECK(PKIX_PL_Cert_GetPolicyMappings | |
| 1010 (cert, &certPolicyMappings, plContext), | |
| 1011 PKIX_CERTGETPOLICYMAPPINGSFAILED); | |
| 1012 | |
| 1013 PKIX_TOSTRING(certPolicyMappings, &certPolicyMappingsString, plContext, | |
| 1014 PKIX_LISTTOSTRINGFAILED); | |
| 1015 | |
| 1016 PKIX_CHECK(PKIX_PL_Cert_GetRequireExplicitPolicy | |
| 1017 (cert, &certExplicitPolicy, plContext), | |
| 1018 PKIX_CERTGETREQUIREEXPLICITPOLICYFAILED); | |
| 1019 | |
| 1020 PKIX_CHECK(PKIX_PL_Cert_GetPolicyMappingInhibited | |
| 1021 (cert, &certInhibitMapping, plContext), | |
| 1022 PKIX_CERTGETPOLICYMAPPINGINHIBITEDFAILED); | |
| 1023 | |
| 1024 PKIX_CHECK(PKIX_PL_Cert_GetInhibitAnyPolicy | |
| 1025 (cert, &certInhibitAnyPolicy, plContext), | |
| 1026 PKIX_CERTGETINHIBITANYPOLICYFAILED); | |
| 1027 | |
| 1028 /* Name Constraints */ | |
| 1029 PKIX_CHECK(PKIX_PL_Cert_GetNameConstraints | |
| 1030 (cert, &nameConstraints, plContext), | |
| 1031 PKIX_CERTGETNAMECONSTRAINTSFAILED); | |
| 1032 | |
| 1033 PKIX_TOSTRING(nameConstraints, &nameConstraintsString, plContext, | |
| 1034 PKIX_LISTTOSTRINGFAILED); | |
| 1035 | |
| 1036 /* Authority Information Access */ | |
| 1037 PKIX_CHECK(PKIX_PL_Cert_GetAuthorityInfoAccess | |
| 1038 (cert, &authorityInfoAccess, plContext), | |
| 1039 PKIX_CERTGETAUTHORITYINFOACCESSFAILED); | |
| 1040 | |
| 1041 PKIX_TOSTRING(authorityInfoAccess, &authorityInfoAccessString, plContext
, | |
| 1042 PKIX_LISTTOSTRINGFAILED); | |
| 1043 | |
| 1044 /* Subject Information Access */ | |
| 1045 PKIX_CHECK(PKIX_PL_Cert_GetSubjectInfoAccess | |
| 1046 (cert, &subjectInfoAccess, plContext), | |
| 1047 PKIX_CERTGETSUBJECTINFOACCESSFAILED); | |
| 1048 | |
| 1049 PKIX_TOSTRING(subjectInfoAccess, &subjectInfoAccessString, plContext, | |
| 1050 PKIX_LISTTOSTRINGFAILED); | |
| 1051 | |
| 1052 PKIX_CHECK(PKIX_PL_Sprintf | |
| 1053 (&certString, | |
| 1054 plContext, | |
| 1055 formatString, | |
| 1056 certVersion + 1, | |
| 1057 certSNString, | |
| 1058 certIssuerString, | |
| 1059 certSubjectString, | |
| 1060 notBeforeString, | |
| 1061 notAfterString, | |
| 1062 subjAltNamesString, | |
| 1063 authKeyIdString, | |
| 1064 subjKeyIdString, | |
| 1065 nssPubKeyString, | |
| 1066 critExtOIDsString, | |
| 1067 extKeyUsagesString, | |
| 1068 certBasicConstraintsString, | |
| 1069 certPolicyInfoString, | |
| 1070 certPolicyMappingsString, | |
| 1071 certExplicitPolicy, /* an Int32, not a String */ | |
| 1072 certInhibitMapping, /* an Int32, not a String */ | |
| 1073 certInhibitAnyPolicy, /* an Int32, not a String */ | |
| 1074 nameConstraintsString, | |
| 1075 authorityInfoAccessString, | |
| 1076 subjectInfoAccessString, | |
| 1077 cert->cacheFlag), /* a boolean */ | |
| 1078 PKIX_SPRINTFFAILED); | |
| 1079 | |
| 1080 *pString = certString; | |
| 1081 | |
| 1082 cleanup: | |
| 1083 PKIX_DECREF(certSN); | |
| 1084 PKIX_DECREF(certSNString); | |
| 1085 PKIX_DECREF(certIssuer); | |
| 1086 PKIX_DECREF(certIssuerString); | |
| 1087 PKIX_DECREF(certSubject); | |
| 1088 PKIX_DECREF(certSubjectString); | |
| 1089 PKIX_DECREF(notBeforeString); | |
| 1090 PKIX_DECREF(notAfterString); | |
| 1091 PKIX_DECREF(subjAltNames); | |
| 1092 PKIX_DECREF(subjAltNamesString); | |
| 1093 PKIX_DECREF(authKeyId); | |
| 1094 PKIX_DECREF(authKeyIdString); | |
| 1095 PKIX_DECREF(subjKeyId); | |
| 1096 PKIX_DECREF(subjKeyIdString); | |
| 1097 PKIX_DECREF(nssPubKey); | |
| 1098 PKIX_DECREF(nssPubKeyString); | |
| 1099 PKIX_DECREF(critExtOIDs); | |
| 1100 PKIX_DECREF(critExtOIDsString); | |
| 1101 PKIX_DECREF(extKeyUsages); | |
| 1102 PKIX_DECREF(extKeyUsagesString); | |
| 1103 PKIX_DECREF(basicConstraint); | |
| 1104 PKIX_DECREF(certBasicConstraintsString); | |
| 1105 PKIX_DECREF(policyInfo); | |
| 1106 PKIX_DECREF(certPolicyInfoString); | |
| 1107 PKIX_DECREF(certPolicyMappings); | |
| 1108 PKIX_DECREF(certPolicyMappingsString); | |
| 1109 PKIX_DECREF(nameConstraints); | |
| 1110 PKIX_DECREF(nameConstraintsString); | |
| 1111 PKIX_DECREF(authorityInfoAccess); | |
| 1112 PKIX_DECREF(authorityInfoAccessString); | |
| 1113 PKIX_DECREF(subjectInfoAccess); | |
| 1114 PKIX_DECREF(subjectInfoAccessString); | |
| 1115 PKIX_DECREF(formatString); | |
| 1116 | |
| 1117 PKIX_RETURN(CERT); | |
| 1118 } | |
| 1119 | |
| 1120 /* | |
| 1121 * FUNCTION: pkix_pl_Cert_Destroy | |
| 1122 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) | |
| 1123 */ | |
| 1124 static PKIX_Error * | |
| 1125 pkix_pl_Cert_Destroy( | |
| 1126 PKIX_PL_Object *object, | |
| 1127 void *plContext) | |
| 1128 { | |
| 1129 PKIX_PL_Cert *cert = NULL; | |
| 1130 | |
| 1131 PKIX_ENTER(CERT, "pkix_pl_Cert_Destroy"); | |
| 1132 PKIX_NULLCHECK_ONE(object); | |
| 1133 | |
| 1134 PKIX_CHECK(pkix_CheckType(object, PKIX_CERT_TYPE, plContext), | |
| 1135 PKIX_OBJECTNOTCERT); | |
| 1136 | |
| 1137 cert = (PKIX_PL_Cert*)object; | |
| 1138 | |
| 1139 PKIX_DECREF(cert->subject); | |
| 1140 PKIX_DECREF(cert->issuer); | |
| 1141 PKIX_DECREF(cert->subjAltNames); | |
| 1142 PKIX_DECREF(cert->publicKeyAlgId); | |
| 1143 PKIX_DECREF(cert->publicKey); | |
| 1144 PKIX_DECREF(cert->serialNumber); | |
| 1145 PKIX_DECREF(cert->critExtOids); | |
| 1146 PKIX_DECREF(cert->authKeyId); | |
| 1147 PKIX_DECREF(cert->subjKeyId); | |
| 1148 PKIX_DECREF(cert->extKeyUsages); | |
| 1149 PKIX_DECREF(cert->certBasicConstraints); | |
| 1150 PKIX_DECREF(cert->certPolicyInfos); | |
| 1151 PKIX_DECREF(cert->certPolicyMappings); | |
| 1152 PKIX_DECREF(cert->nameConstraints); | |
| 1153 PKIX_DECREF(cert->store); | |
| 1154 PKIX_DECREF(cert->authorityInfoAccess); | |
| 1155 PKIX_DECREF(cert->subjectInfoAccess); | |
| 1156 PKIX_DECREF(cert->crldpList); | |
| 1157 | |
| 1158 if (cert->arenaNameConstraints){ | |
| 1159 /* This arena was allocated for SubjectAltNames */ | |
| 1160 PKIX_PL_NSSCALL(CERT, PORT_FreeArena, | |
| 1161 (cert->arenaNameConstraints, PR_FALSE)); | |
| 1162 | |
| 1163 cert->arenaNameConstraints = NULL; | |
| 1164 cert->nssSubjAltNames = NULL; | |
| 1165 } | |
| 1166 | |
| 1167 CERT_DestroyCertificate(cert->nssCert); | |
| 1168 cert->nssCert = NULL; | |
| 1169 | |
| 1170 cleanup: | |
| 1171 PKIX_RETURN(CERT); | |
| 1172 } | |
| 1173 | |
| 1174 /* | |
| 1175 * FUNCTION: pkix_pl_Cert_ToString | |
| 1176 * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h) | |
| 1177 */ | |
| 1178 static PKIX_Error * | |
| 1179 pkix_pl_Cert_ToString( | |
| 1180 PKIX_PL_Object *object, | |
| 1181 PKIX_PL_String **pString, | |
| 1182 void *plContext) | |
| 1183 { | |
| 1184 PKIX_PL_String *certString = NULL; | |
| 1185 PKIX_PL_Cert *pkixCert = NULL; | |
| 1186 | |
| 1187 PKIX_ENTER(CERT, "pkix_pl_Cert_toString"); | |
| 1188 PKIX_NULLCHECK_TWO(object, pString); | |
| 1189 | |
| 1190 PKIX_CHECK(pkix_CheckType(object, PKIX_CERT_TYPE, plContext), | |
| 1191 PKIX_OBJECTNOTCERT); | |
| 1192 | |
| 1193 pkixCert = (PKIX_PL_Cert *)object; | |
| 1194 | |
| 1195 PKIX_CHECK(pkix_pl_Cert_ToString_Helper | |
| 1196 (pkixCert, PKIX_FALSE, &certString, plContext), | |
| 1197 PKIX_CERTTOSTRINGHELPERFAILED); | |
| 1198 | |
| 1199 *pString = certString; | |
| 1200 | |
| 1201 cleanup: | |
| 1202 PKIX_RETURN(CERT); | |
| 1203 } | |
| 1204 | |
| 1205 /* | |
| 1206 * FUNCTION: pkix_pl_Cert_Hashcode | |
| 1207 * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) | |
| 1208 */ | |
| 1209 static PKIX_Error * | |
| 1210 pkix_pl_Cert_Hashcode( | |
| 1211 PKIX_PL_Object *object, | |
| 1212 PKIX_UInt32 *pHashcode, | |
| 1213 void *plContext) | |
| 1214 { | |
| 1215 PKIX_PL_Cert *pkixCert = NULL; | |
| 1216 CERTCertificate *nssCert = NULL; | |
| 1217 unsigned char *derBytes = NULL; | |
| 1218 PKIX_UInt32 derLength; | |
| 1219 PKIX_UInt32 certHash; | |
| 1220 | |
| 1221 PKIX_ENTER(CERT, "pkix_pl_Cert_Hashcode"); | |
| 1222 PKIX_NULLCHECK_TWO(object, pHashcode); | |
| 1223 | |
| 1224 PKIX_CHECK(pkix_CheckType(object, PKIX_CERT_TYPE, plContext), | |
| 1225 PKIX_OBJECTNOTCERT); | |
| 1226 | |
| 1227 pkixCert = (PKIX_PL_Cert *)object; | |
| 1228 | |
| 1229 nssCert = pkixCert->nssCert; | |
| 1230 derBytes = (nssCert->derCert).data; | |
| 1231 derLength = (nssCert->derCert).len; | |
| 1232 | |
| 1233 PKIX_CHECK(pkix_hash(derBytes, derLength, &certHash, plContext), | |
| 1234 PKIX_HASHFAILED); | |
| 1235 | |
| 1236 *pHashcode = certHash; | |
| 1237 | |
| 1238 cleanup: | |
| 1239 PKIX_RETURN(CERT); | |
| 1240 } | |
| 1241 | |
| 1242 | |
| 1243 /* | |
| 1244 * FUNCTION: pkix_pl_Cert_Equals | |
| 1245 * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h) | |
| 1246 */ | |
| 1247 static PKIX_Error * | |
| 1248 pkix_pl_Cert_Equals( | |
| 1249 PKIX_PL_Object *firstObject, | |
| 1250 PKIX_PL_Object *secondObject, | |
| 1251 PKIX_Boolean *pResult, | |
| 1252 void *plContext) | |
| 1253 { | |
| 1254 CERTCertificate *firstCert = NULL; | |
| 1255 CERTCertificate *secondCert = NULL; | |
| 1256 PKIX_UInt32 secondType; | |
| 1257 PKIX_Boolean cmpResult; | |
| 1258 | |
| 1259 PKIX_ENTER(CERT, "pkix_pl_Cert_Equals"); | |
| 1260 PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); | |
| 1261 | |
| 1262 /* test that firstObject is a Cert */ | |
| 1263 PKIX_CHECK(pkix_CheckType(firstObject, PKIX_CERT_TYPE, plContext), | |
| 1264 PKIX_FIRSTOBJECTNOTCERT); | |
| 1265 | |
| 1266 /* | |
| 1267 * Since we know firstObject is a Cert, if both references are | |
| 1268 * identical, they must be equal | |
| 1269 */ | |
| 1270 if (firstObject == secondObject){ | |
| 1271 *pResult = PKIX_TRUE; | |
| 1272 goto cleanup; | |
| 1273 } | |
| 1274 | |
| 1275 /* | |
| 1276 * If secondObject isn't a Cert, we don't throw an error. | |
| 1277 * We simply return a Boolean result of FALSE | |
| 1278 */ | |
| 1279 *pResult = PKIX_FALSE; | |
| 1280 PKIX_CHECK(PKIX_PL_Object_GetType | |
| 1281 (secondObject, &secondType, plContext), | |
| 1282 PKIX_COULDNOTGETTYPEOFSECONDARGUMENT); | |
| 1283 if (secondType != PKIX_CERT_TYPE) goto cleanup; | |
| 1284 | |
| 1285 firstCert = ((PKIX_PL_Cert *)firstObject)->nssCert; | |
| 1286 secondCert = ((PKIX_PL_Cert *)secondObject)->nssCert; | |
| 1287 | |
| 1288 PKIX_NULLCHECK_TWO(firstCert, secondCert); | |
| 1289 | |
| 1290 /* CERT_CompareCerts does byte comparison on DER encodings of certs */ | |
| 1291 PKIX_CERT_DEBUG("\t\tCalling CERT_CompareCerts).\n"); | |
| 1292 cmpResult = CERT_CompareCerts(firstCert, secondCert); | |
| 1293 | |
| 1294 *pResult = cmpResult; | |
| 1295 | |
| 1296 cleanup: | |
| 1297 PKIX_RETURN(CERT); | |
| 1298 } | |
| 1299 | |
| 1300 /* | |
| 1301 * FUNCTION: pkix_pl_Cert_RegisterSelf | |
| 1302 * DESCRIPTION: | |
| 1303 * Registers PKIX_CERT_TYPE and its related functions with systemClasses[] | |
| 1304 * THREAD SAFETY: | |
| 1305 * Not Thread Safe - for performance and complexity reasons | |
| 1306 * | |
| 1307 * Since this function is only called by PKIX_PL_Initialize, which should | |
| 1308 * only be called once, it is acceptable that this function is not | |
| 1309 * thread-safe. | |
| 1310 */ | |
| 1311 PKIX_Error * | |
| 1312 pkix_pl_Cert_RegisterSelf(void *plContext) | |
| 1313 { | |
| 1314 | |
| 1315 extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; | |
| 1316 pkix_ClassTable_Entry entry; | |
| 1317 | |
| 1318 PKIX_ENTER(CERT, "pkix_pl_Cert_RegisterSelf"); | |
| 1319 | |
| 1320 entry.description = "Cert"; | |
| 1321 entry.objCounter = 0; | |
| 1322 entry.typeObjectSize = sizeof(PKIX_PL_Cert); | |
| 1323 entry.destructor = pkix_pl_Cert_Destroy; | |
| 1324 entry.equalsFunction = pkix_pl_Cert_Equals; | |
| 1325 entry.hashcodeFunction = pkix_pl_Cert_Hashcode; | |
| 1326 entry.toStringFunction = pkix_pl_Cert_ToString; | |
| 1327 entry.comparator = NULL; | |
| 1328 entry.duplicateFunction = pkix_duplicateImmutable; | |
| 1329 | |
| 1330 systemClasses[PKIX_CERT_TYPE] = entry; | |
| 1331 | |
| 1332 PKIX_RETURN(CERT); | |
| 1333 } | |
| 1334 | |
| 1335 /* | |
| 1336 * FUNCTION: pkix_pl_Cert_CreateWithNSSCert | |
| 1337 * DESCRIPTION: | |
| 1338 * | |
| 1339 * Creates a new certificate using the CERTCertificate pointed to by "nssCert" | |
| 1340 * and stores it at "pCert". Once created, a Cert is immutable. | |
| 1341 * | |
| 1342 * This function is primarily used as a convenience function for the | |
| 1343 * performance tests that have easy access to a CERTCertificate. | |
| 1344 * | |
| 1345 * PARAMETERS: | |
| 1346 * "nssCert" | |
| 1347 * Address of CERTCertificate representing the NSS certificate. | |
| 1348 * Must be non-NULL. | |
| 1349 * "pCert" | |
| 1350 * Address where object pointer will be stored. Must be non-NULL. | |
| 1351 * "plContext" | |
| 1352 * Platform-specific context pointer. | |
| 1353 * THREAD SAFETY: | |
| 1354 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
| 1355 * RETURNS: | |
| 1356 * Returns NULL if the function succeeds. | |
| 1357 * Returns a Cert Error if the function fails in a non-fatal way. | |
| 1358 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
| 1359 */ | |
| 1360 PKIX_Error * | |
| 1361 pkix_pl_Cert_CreateWithNSSCert( | |
| 1362 CERTCertificate *nssCert, | |
| 1363 PKIX_PL_Cert **pCert, | |
| 1364 void *plContext) | |
| 1365 { | |
| 1366 PKIX_PL_Cert *cert = NULL; | |
| 1367 | |
| 1368 PKIX_ENTER(CERT, "pkix_pl_Cert_CreateWithNSSCert"); | |
| 1369 PKIX_NULLCHECK_TWO(pCert, nssCert); | |
| 1370 | |
| 1371 /* create a PKIX_PL_Cert object */ | |
| 1372 PKIX_CHECK(PKIX_PL_Object_Alloc | |
| 1373 (PKIX_CERT_TYPE, | |
| 1374 sizeof (PKIX_PL_Cert), | |
| 1375 (PKIX_PL_Object **)&cert, | |
| 1376 plContext), | |
| 1377 PKIX_COULDNOTCREATEOBJECT); | |
| 1378 | |
| 1379 /* populate the nssCert field */ | |
| 1380 cert->nssCert = nssCert; | |
| 1381 | |
| 1382 /* initialize remaining fields */ | |
| 1383 /* | |
| 1384 * Fields ending with Absent are initialized to PKIX_FALSE so that the | |
| 1385 * first time we need the value we will look for it. If we find it is | |
| 1386 * actually absent, the flag will at that time be set to PKIX_TRUE to | |
| 1387 * prevent searching for it later. | |
| 1388 * Fields ending with Processed are those where a value is defined | |
| 1389 * for the Absent case, and a value of zero is possible. When the | |
| 1390 * flag is still true we have to look for the field, set the default | |
| 1391 * value if necessary, and set the Processed flag to PKIX_TRUE. | |
| 1392 */ | |
| 1393 cert->subject = NULL; | |
| 1394 cert->issuer = NULL; | |
| 1395 cert->subjAltNames = NULL; | |
| 1396 cert->subjAltNamesAbsent = PKIX_FALSE; | |
| 1397 cert->publicKeyAlgId = NULL; | |
| 1398 cert->publicKey = NULL; | |
| 1399 cert->serialNumber = NULL; | |
| 1400 cert->critExtOids = NULL; | |
| 1401 cert->subjKeyId = NULL; | |
| 1402 cert->subjKeyIdAbsent = PKIX_FALSE; | |
| 1403 cert->authKeyId = NULL; | |
| 1404 cert->authKeyIdAbsent = PKIX_FALSE; | |
| 1405 cert->extKeyUsages = NULL; | |
| 1406 cert->extKeyUsagesAbsent = PKIX_FALSE; | |
| 1407 cert->certBasicConstraints = NULL; | |
| 1408 cert->basicConstraintsAbsent = PKIX_FALSE; | |
| 1409 cert->certPolicyInfos = NULL; | |
| 1410 cert->policyInfoAbsent = PKIX_FALSE; | |
| 1411 cert->policyMappingsAbsent = PKIX_FALSE; | |
| 1412 cert->certPolicyMappings = NULL; | |
| 1413 cert->policyConstraintsProcessed = PKIX_FALSE; | |
| 1414 cert->policyConstraintsExplicitPolicySkipCerts = 0; | |
| 1415 cert->policyConstraintsInhibitMappingSkipCerts = 0; | |
| 1416 cert->inhibitAnyPolicyProcessed = PKIX_FALSE; | |
| 1417 cert->inhibitAnySkipCerts = 0; | |
| 1418 cert->nameConstraints = NULL; | |
| 1419 cert->nameConstraintsAbsent = PKIX_FALSE; | |
| 1420 cert->arenaNameConstraints = NULL; | |
| 1421 cert->nssSubjAltNames = NULL; | |
| 1422 cert->cacheFlag = PKIX_FALSE; | |
| 1423 cert->store = NULL; | |
| 1424 cert->authorityInfoAccess = NULL; | |
| 1425 cert->subjectInfoAccess = NULL; | |
| 1426 cert->isUserTrustAnchor = PKIX_FALSE; | |
| 1427 cert->crldpList = NULL; | |
| 1428 | |
| 1429 *pCert = cert; | |
| 1430 | |
| 1431 cleanup: | |
| 1432 PKIX_RETURN(CERT); | |
| 1433 } | |
| 1434 | |
| 1435 /* | |
| 1436 * FUNCTION: pkix_pl_Cert_CreateToList | |
| 1437 * DESCRIPTION: | |
| 1438 * | |
| 1439 * Creates a new certificate using the DER-encoding pointed to by "derCertItem" | |
| 1440 * and appends it to the list pointed to by "certList". If Cert creation fails, | |
| 1441 * the function returns with certList unchanged, but any decoding Error is | |
| 1442 * discarded. | |
| 1443 * | |
| 1444 * PARAMETERS: | |
| 1445 * "derCertItem" | |
| 1446 * Address of SECItem containing the DER representation of a certificate. | |
| 1447 * Must be non-NULL. | |
| 1448 * "certList" | |
| 1449 * Address of List to which the Cert will be appended, if successfully | |
| 1450 * created. May be empty, but must be non-NULL. | |
| 1451 * "plContext" | |
| 1452 * Platform-specific context pointer. | |
| 1453 * THREAD SAFETY: | |
| 1454 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
| 1455 * RETURNS: | |
| 1456 * Returns NULL if the function succeeds. | |
| 1457 * Returns a Cert Error if the function fails in a non-fatal way. | |
| 1458 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
| 1459 */ | |
| 1460 PKIX_Error * | |
| 1461 pkix_pl_Cert_CreateToList( | |
| 1462 SECItem *derCertItem, | |
| 1463 PKIX_List *certList, | |
| 1464 void *plContext) | |
| 1465 { | |
| 1466 CERTCertificate *nssCert = NULL; | |
| 1467 PKIX_PL_Cert *cert = NULL; | |
| 1468 CERTCertDBHandle *handle; | |
| 1469 | |
| 1470 PKIX_ENTER(CERT, "pkix_pl_Cert_CreateToList"); | |
| 1471 PKIX_NULLCHECK_TWO(derCertItem, certList); | |
| 1472 | |
| 1473 handle = CERT_GetDefaultCertDB(); | |
| 1474 nssCert = CERT_NewTempCertificate(handle, derCertItem, | |
| 1475 /* nickname */ NULL, | |
| 1476 /* isPerm */ PR_FALSE, | |
| 1477 /* copyDer */ PR_TRUE); | |
| 1478 if (!nssCert) { | |
| 1479 goto cleanup; | |
| 1480 } | |
| 1481 | |
| 1482 PKIX_CHECK(pkix_pl_Cert_CreateWithNSSCert | |
| 1483 (nssCert, &cert, plContext), | |
| 1484 PKIX_CERTCREATEWITHNSSCERTFAILED); | |
| 1485 | |
| 1486 nssCert = NULL; | |
| 1487 | |
| 1488 PKIX_CHECK(PKIX_List_AppendItem | |
| 1489 (certList, (PKIX_PL_Object *) cert, plContext), | |
| 1490 PKIX_LISTAPPENDITEMFAILED); | |
| 1491 | |
| 1492 cleanup: | |
| 1493 if (nssCert) { | |
| 1494 CERT_DestroyCertificate(nssCert); | |
| 1495 } | |
| 1496 | |
| 1497 PKIX_DECREF(cert); | |
| 1498 PKIX_RETURN(CERT); | |
| 1499 } | |
| 1500 | |
| 1501 /* --Public-Functions------------------------------------------------------- */ | |
| 1502 | |
| 1503 /* | |
| 1504 * FUNCTION: PKIX_PL_Cert_Create (see comments in pkix_pl_pki.h) | |
| 1505 * XXX We may want to cache the cert after parsing it, so it can be reused | |
| 1506 * XXX Are the NSS/NSPR functions thread safe | |
| 1507 */ | |
| 1508 PKIX_Error * | |
| 1509 PKIX_PL_Cert_Create( | |
| 1510 PKIX_PL_ByteArray *byteArray, | |
| 1511 PKIX_PL_Cert **pCert, | |
| 1512 void *plContext) | |
| 1513 { | |
| 1514 CERTCertificate *nssCert = NULL; | |
| 1515 SECItem *derCertItem = NULL; | |
| 1516 void *derBytes = NULL; | |
| 1517 PKIX_UInt32 derLength; | |
| 1518 PKIX_PL_Cert *cert = NULL; | |
| 1519 CERTCertDBHandle *handle; | |
| 1520 | |
| 1521 PKIX_ENTER(CERT, "PKIX_PL_Cert_Create"); | |
| 1522 PKIX_NULLCHECK_TWO(pCert, byteArray); | |
| 1523 | |
| 1524 PKIX_CHECK(PKIX_PL_ByteArray_GetPointer | |
| 1525 (byteArray, &derBytes, plContext), | |
| 1526 PKIX_BYTEARRAYGETPOINTERFAILED); | |
| 1527 | |
| 1528 PKIX_CHECK(PKIX_PL_ByteArray_GetLength | |
| 1529 (byteArray, &derLength, plContext), | |
| 1530 PKIX_BYTEARRAYGETLENGTHFAILED); | |
| 1531 | |
| 1532 derCertItem = SECITEM_AllocItem(NULL, NULL, derLength); | |
| 1533 if (derCertItem == NULL){ | |
| 1534 PKIX_ERROR(PKIX_OUTOFMEMORY); | |
| 1535 } | |
| 1536 | |
| 1537 (void) PORT_Memcpy(derCertItem->data, derBytes, derLength); | |
| 1538 | |
| 1539 /* | |
| 1540 * setting copyDER to true forces NSS to make its own copy of the DER, | |
| 1541 * allowing us to free our copy without worrying about whether NSS | |
| 1542 * is still using it | |
| 1543 */ | |
| 1544 handle = CERT_GetDefaultCertDB(); | |
| 1545 nssCert = CERT_NewTempCertificate(handle, derCertItem, | |
| 1546 /* nickname */ NULL, | |
| 1547 /* isPerm */ PR_FALSE, | |
| 1548 /* copyDer */ PR_TRUE); | |
| 1549 if (!nssCert){ | |
| 1550 PKIX_ERROR(PKIX_CERTDECODEDERCERTIFICATEFAILED); | |
| 1551 } | |
| 1552 | |
| 1553 PKIX_CHECK(pkix_pl_Cert_CreateWithNSSCert | |
| 1554 (nssCert, &cert, plContext), | |
| 1555 PKIX_CERTCREATEWITHNSSCERTFAILED); | |
| 1556 | |
| 1557 *pCert = cert; | |
| 1558 | |
| 1559 cleanup: | |
| 1560 if (derCertItem){ | |
| 1561 SECITEM_FreeItem(derCertItem, PKIX_TRUE); | |
| 1562 } | |
| 1563 | |
| 1564 if (nssCert && PKIX_ERROR_RECEIVED){ | |
| 1565 PKIX_CERT_DEBUG("\t\tCalling CERT_DestroyCertificate).\n"); | |
| 1566 CERT_DestroyCertificate(nssCert); | |
| 1567 nssCert = NULL; | |
| 1568 } | |
| 1569 | |
| 1570 PKIX_FREE(derBytes); | |
| 1571 PKIX_RETURN(CERT); | |
| 1572 } | |
| 1573 | |
| 1574 | |
| 1575 /* | |
| 1576 * FUNCTION: PKIX_PL_Cert_CreateFromCERTCertificate | |
| 1577 * (see comments in pkix_pl_pki.h) | |
| 1578 */ | |
| 1579 PKIX_Error * | |
| 1580 PKIX_PL_Cert_CreateFromCERTCertificate( | |
| 1581 const CERTCertificate *nssCert, | |
| 1582 PKIX_PL_Cert **pCert, | |
| 1583 void *plContext) | |
| 1584 { | |
| 1585 void *buf = NULL; | |
| 1586 PKIX_UInt32 len; | |
| 1587 PKIX_PL_ByteArray *byteArray = NULL; | |
| 1588 | |
| 1589 PKIX_ENTER(CERT, "PKIX_PL_Cert_CreateWithNssCert"); | |
| 1590 PKIX_NULLCHECK_TWO(pCert, nssCert); | |
| 1591 | |
| 1592 buf = (void*)nssCert->derCert.data; | |
| 1593 len = nssCert->derCert.len; | |
| 1594 | |
| 1595 PKIX_CHECK( | |
| 1596 PKIX_PL_ByteArray_Create(buf, len, &byteArray, plContext), | |
| 1597 PKIX_BYTEARRAYCREATEFAILED); | |
| 1598 | |
| 1599 PKIX_CHECK( | |
| 1600 PKIX_PL_Cert_Create(byteArray, pCert, plContext), | |
| 1601 PKIX_CERTCREATEWITHNSSCERTFAILED); | |
| 1602 | |
| 1603 #ifdef PKIX_UNDEF | |
| 1604 /* will be tested and used as a patch for bug 391612 */ | |
| 1605 nssCert = CERT_DupCertificate(nssInCert); | |
| 1606 | |
| 1607 PKIX_CHECK(pkix_pl_Cert_CreateWithNSSCert | |
| 1608 (nssCert, &cert, plContext), | |
| 1609 PKIX_CERTCREATEWITHNSSCERTFAILED); | |
| 1610 #endif /* PKIX_UNDEF */ | |
| 1611 | |
| 1612 cleanup: | |
| 1613 | |
| 1614 #ifdef PKIX_UNDEF | |
| 1615 if (nssCert && PKIX_ERROR_RECEIVED){ | |
| 1616 PKIX_CERT_DEBUG("\t\tCalling CERT_DestroyCertificate).\n"); | |
| 1617 CERT_DestroyCertificate(nssCert); | |
| 1618 nssCert = NULL; | |
| 1619 } | |
| 1620 #endif /* PKIX_UNDEF */ | |
| 1621 | |
| 1622 PKIX_DECREF(byteArray); | |
| 1623 PKIX_RETURN(CERT); | |
| 1624 } | |
| 1625 | |
| 1626 | |
| 1627 /* | |
| 1628 * FUNCTION: PKIX_PL_Cert_GetVersion (see comments in pkix_pl_pki.h) | |
| 1629 */ | |
| 1630 PKIX_Error * | |
| 1631 PKIX_PL_Cert_GetVersion( | |
| 1632 PKIX_PL_Cert *cert, | |
| 1633 PKIX_UInt32 *pVersion, | |
| 1634 void *plContext) | |
| 1635 { | |
| 1636 CERTCertificate *nssCert = NULL; | |
| 1637 PKIX_UInt32 myVersion = 0; /* v1 */ | |
| 1638 | |
| 1639 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetVersion"); | |
| 1640 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pVersion); | |
| 1641 | |
| 1642 nssCert = cert->nssCert; | |
| 1643 if (nssCert->version.len != 0) { | |
| 1644 myVersion = *(nssCert->version.data); | |
| 1645 } | |
| 1646 | |
| 1647 if (myVersion > 2){ | |
| 1648 PKIX_ERROR(PKIX_VERSIONVALUEMUSTBEV1V2ORV3); | |
| 1649 } | |
| 1650 | |
| 1651 *pVersion = myVersion; | |
| 1652 | |
| 1653 cleanup: | |
| 1654 PKIX_RETURN(CERT); | |
| 1655 } | |
| 1656 | |
| 1657 /* | |
| 1658 * FUNCTION: PKIX_PL_Cert_GetSerialNumber (see comments in pkix_pl_pki.h) | |
| 1659 */ | |
| 1660 PKIX_Error * | |
| 1661 PKIX_PL_Cert_GetSerialNumber( | |
| 1662 PKIX_PL_Cert *cert, | |
| 1663 PKIX_PL_BigInt **pSerialNumber, | |
| 1664 void *plContext) | |
| 1665 { | |
| 1666 CERTCertificate *nssCert = NULL; | |
| 1667 SECItem serialNumItem; | |
| 1668 PKIX_PL_BigInt *serialNumber = NULL; | |
| 1669 char *bytes = NULL; | |
| 1670 PKIX_UInt32 length; | |
| 1671 | |
| 1672 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSerialNumber"); | |
| 1673 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSerialNumber); | |
| 1674 | |
| 1675 if (cert->serialNumber == NULL){ | |
| 1676 | |
| 1677 PKIX_OBJECT_LOCK(cert); | |
| 1678 | |
| 1679 if (cert->serialNumber == NULL){ | |
| 1680 | |
| 1681 nssCert = cert->nssCert; | |
| 1682 serialNumItem = nssCert->serialNumber; | |
| 1683 | |
| 1684 length = serialNumItem.len; | |
| 1685 bytes = (char *)serialNumItem.data; | |
| 1686 | |
| 1687 PKIX_CHECK(pkix_pl_BigInt_CreateWithBytes | |
| 1688 (bytes, length, &serialNumber, plContext), | |
| 1689 PKIX_BIGINTCREATEWITHBYTESFAILED); | |
| 1690 | |
| 1691 /* save a cached copy in case it is asked for again */ | |
| 1692 cert->serialNumber = serialNumber; | |
| 1693 } | |
| 1694 | |
| 1695 PKIX_OBJECT_UNLOCK(cert); | |
| 1696 } | |
| 1697 | |
| 1698 PKIX_INCREF(cert->serialNumber); | |
| 1699 *pSerialNumber = cert->serialNumber; | |
| 1700 | |
| 1701 cleanup: | |
| 1702 PKIX_OBJECT_UNLOCK(lockedObject); | |
| 1703 PKIX_RETURN(CERT); | |
| 1704 } | |
| 1705 | |
| 1706 /* | |
| 1707 * FUNCTION: PKIX_PL_Cert_GetSubject (see comments in pkix_pl_pki.h) | |
| 1708 */ | |
| 1709 PKIX_Error * | |
| 1710 PKIX_PL_Cert_GetSubject( | |
| 1711 PKIX_PL_Cert *cert, | |
| 1712 PKIX_PL_X500Name **pCertSubject, | |
| 1713 void *plContext) | |
| 1714 { | |
| 1715 PKIX_PL_X500Name *pkixSubject = NULL; | |
| 1716 CERTName *subjName = NULL; | |
| 1717 SECItem *derSubjName = NULL; | |
| 1718 | |
| 1719 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubject"); | |
| 1720 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pCertSubject); | |
| 1721 | |
| 1722 /* if we don't have a cached copy from before, we create one */ | |
| 1723 if (cert->subject == NULL){ | |
| 1724 | |
| 1725 PKIX_OBJECT_LOCK(cert); | |
| 1726 | |
| 1727 if (cert->subject == NULL){ | |
| 1728 | |
| 1729 subjName = &cert->nssCert->subject; | |
| 1730 derSubjName = &cert->nssCert->derSubject; | |
| 1731 | |
| 1732 /* if there is no subject name */ | |
| 1733 if (derSubjName->data == NULL) { | |
| 1734 | |
| 1735 pkixSubject = NULL; | |
| 1736 | |
| 1737 } else { | |
| 1738 PKIX_CHECK(PKIX_PL_X500Name_CreateFromCERTName | |
| 1739 (derSubjName, subjName, &pkixSubject, | |
| 1740 plContext), | |
| 1741 PKIX_X500NAMECREATEFROMCERTNAMEFAILED); | |
| 1742 | |
| 1743 } | |
| 1744 /* save a cached copy in case it is asked for again */ | |
| 1745 cert->subject = pkixSubject; | |
| 1746 } | |
| 1747 | |
| 1748 PKIX_OBJECT_UNLOCK(cert); | |
| 1749 } | |
| 1750 | |
| 1751 PKIX_INCREF(cert->subject); | |
| 1752 *pCertSubject = cert->subject; | |
| 1753 | |
| 1754 cleanup: | |
| 1755 PKIX_OBJECT_UNLOCK(lockedObject); | |
| 1756 PKIX_RETURN(CERT); | |
| 1757 } | |
| 1758 | |
| 1759 /* | |
| 1760 * FUNCTION: PKIX_PL_Cert_GetIssuer (see comments in pkix_pl_pki.h) | |
| 1761 */ | |
| 1762 PKIX_Error * | |
| 1763 PKIX_PL_Cert_GetIssuer( | |
| 1764 PKIX_PL_Cert *cert, | |
| 1765 PKIX_PL_X500Name **pCertIssuer, | |
| 1766 void *plContext) | |
| 1767 { | |
| 1768 PKIX_PL_X500Name *pkixIssuer = NULL; | |
| 1769 SECItem *derIssuerName = NULL; | |
| 1770 CERTName *issuerName = NULL; | |
| 1771 | |
| 1772 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetIssuer"); | |
| 1773 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pCertIssuer); | |
| 1774 | |
| 1775 /* if we don't have a cached copy from before, we create one */ | |
| 1776 if (cert->issuer == NULL){ | |
| 1777 | |
| 1778 PKIX_OBJECT_LOCK(cert); | |
| 1779 | |
| 1780 if (cert->issuer == NULL){ | |
| 1781 | |
| 1782 issuerName = &cert->nssCert->issuer; | |
| 1783 derIssuerName = &cert->nssCert->derIssuer; | |
| 1784 | |
| 1785 /* if there is no subject name */ | |
| 1786 PKIX_CHECK(PKIX_PL_X500Name_CreateFromCERTName | |
| 1787 (derIssuerName, issuerName, | |
| 1788 &pkixIssuer, plContext), | |
| 1789 PKIX_X500NAMECREATEFROMCERTNAMEFAILED); | |
| 1790 | |
| 1791 /* save a cached copy in case it is asked for again */ | |
| 1792 cert->issuer = pkixIssuer; | |
| 1793 } | |
| 1794 | |
| 1795 PKIX_OBJECT_UNLOCK(cert); | |
| 1796 } | |
| 1797 | |
| 1798 PKIX_INCREF(cert->issuer); | |
| 1799 *pCertIssuer = cert->issuer; | |
| 1800 | |
| 1801 cleanup: | |
| 1802 PKIX_RETURN(CERT); | |
| 1803 } | |
| 1804 | |
| 1805 /* | |
| 1806 * FUNCTION: PKIX_PL_Cert_GetSubjectAltNames (see comments in pkix_pl_pki.h) | |
| 1807 */ | |
| 1808 PKIX_Error * | |
| 1809 PKIX_PL_Cert_GetSubjectAltNames( | |
| 1810 PKIX_PL_Cert *cert, | |
| 1811 PKIX_List **pSubjectAltNames, /* list of PKIX_PL_GeneralName */ | |
| 1812 void *plContext) | |
| 1813 { | |
| 1814 PKIX_PL_GeneralName *pkixAltName = NULL; | |
| 1815 PKIX_List *altNamesList = NULL; | |
| 1816 | |
| 1817 CERTGeneralName *nssOriginalAltName = NULL; | |
| 1818 CERTGeneralName *nssTempAltName = NULL; | |
| 1819 | |
| 1820 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubjectAltNames"); | |
| 1821 PKIX_NULLCHECK_TWO(cert, pSubjectAltNames); | |
| 1822 | |
| 1823 /* if we don't have a cached copy from before, we create one */ | |
| 1824 if ((cert->subjAltNames == NULL) && (!cert->subjAltNamesAbsent)){ | |
| 1825 | |
| 1826 PKIX_OBJECT_LOCK(cert); | |
| 1827 | |
| 1828 if ((cert->subjAltNames == NULL) && | |
| 1829 (!cert->subjAltNamesAbsent)){ | |
| 1830 | |
| 1831 PKIX_CHECK(pkix_pl_Cert_GetNssSubjectAltNames | |
| 1832 (cert, | |
| 1833 PKIX_TRUE, | |
| 1834 &nssOriginalAltName, | |
| 1835 plContext), | |
| 1836 PKIX_CERTGETNSSSUBJECTALTNAMESFAILED); | |
| 1837 | |
| 1838 if (nssOriginalAltName == NULL) { | |
| 1839 cert->subjAltNamesAbsent = PKIX_TRUE; | |
| 1840 pSubjectAltNames = NULL; | |
| 1841 goto cleanup; | |
| 1842 } | |
| 1843 | |
| 1844 nssTempAltName = nssOriginalAltName; | |
| 1845 | |
| 1846 PKIX_CHECK(PKIX_List_Create(&altNamesList, plContext), | |
| 1847 PKIX_LISTCREATEFAILED); | |
| 1848 | |
| 1849 do { | |
| 1850 PKIX_CHECK(pkix_pl_GeneralName_Create | |
| 1851 (nssTempAltName, &pkixAltName, plContext), | |
| 1852 PKIX_GENERALNAMECREATEFAILED); | |
| 1853 | |
| 1854 PKIX_CHECK(PKIX_List_AppendItem | |
| 1855 (altNamesList, | |
| 1856 (PKIX_PL_Object *)pkixAltName, | |
| 1857 plContext), | |
| 1858 PKIX_LISTAPPENDITEMFAILED); | |
| 1859 | |
| 1860 PKIX_DECREF(pkixAltName); | |
| 1861 | |
| 1862 PKIX_CERT_DEBUG | |
| 1863 ("\t\tCalling CERT_GetNextGeneralName).\n"); | |
| 1864 nssTempAltName = CERT_GetNextGeneralName | |
| 1865 (nssTempAltName); | |
| 1866 | |
| 1867 } while (nssTempAltName != nssOriginalAltName); | |
| 1868 | |
| 1869 /* save a cached copy in case it is asked for again */ | |
| 1870 cert->subjAltNames = altNamesList; | |
| 1871 PKIX_CHECK(PKIX_List_SetImmutable | |
| 1872 (cert->subjAltNames, plContext), | |
| 1873 PKIX_LISTSETIMMUTABLEFAILED); | |
| 1874 | |
| 1875 } | |
| 1876 | |
| 1877 PKIX_OBJECT_UNLOCK(cert); | |
| 1878 } | |
| 1879 | |
| 1880 PKIX_INCREF(cert->subjAltNames); | |
| 1881 | |
| 1882 *pSubjectAltNames = cert->subjAltNames; | |
| 1883 | |
| 1884 cleanup: | |
| 1885 PKIX_DECREF(pkixAltName); | |
| 1886 if (PKIX_ERROR_RECEIVED){ | |
| 1887 PKIX_DECREF(altNamesList); | |
| 1888 } | |
| 1889 PKIX_RETURN(CERT); | |
| 1890 } | |
| 1891 | |
| 1892 /* | |
| 1893 * FUNCTION: PKIX_PL_Cert_GetAllSubjectNames (see comments in pkix_pl_pki.h) | |
| 1894 */ | |
| 1895 PKIX_Error * | |
| 1896 PKIX_PL_Cert_GetAllSubjectNames( | |
| 1897 PKIX_PL_Cert *cert, | |
| 1898 PKIX_List **pAllSubjectNames, /* list of PKIX_PL_GeneralName */ | |
| 1899 void *plContext) | |
| 1900 { | |
| 1901 CERTGeneralName *nssOriginalSubjectName = NULL; | |
| 1902 CERTGeneralName *nssTempSubjectName = NULL; | |
| 1903 PKIX_List *allSubjectNames = NULL; | |
| 1904 PKIX_PL_GeneralName *pkixSubjectName = NULL; | |
| 1905 PLArenaPool *arena = NULL; | |
| 1906 | |
| 1907 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetAllSubjectNames"); | |
| 1908 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pAllSubjectNames); | |
| 1909 | |
| 1910 | |
| 1911 if (cert->nssCert->subjectName == NULL){ | |
| 1912 /* if there is no subject DN, just get altnames */ | |
| 1913 | |
| 1914 PKIX_CHECK(pkix_pl_Cert_GetNssSubjectAltNames | |
| 1915 (cert, | |
| 1916 PKIX_FALSE, /* hasLock */ | |
| 1917 &nssOriginalSubjectName, | |
| 1918 plContext), | |
| 1919 PKIX_CERTGETNSSSUBJECTALTNAMESFAILED); | |
| 1920 | |
| 1921 } else { /* get subject DN and altnames */ | |
| 1922 | |
| 1923 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | |
| 1924 if (arena == NULL) { | |
| 1925 PKIX_ERROR(PKIX_OUTOFMEMORY); | |
| 1926 } | |
| 1927 | |
| 1928 /* This NSS call returns both Subject and Subject Alt Names */ | |
| 1929 PKIX_CERT_DEBUG("\t\tCalling CERT_GetCertificateNames\n"); | |
| 1930 nssOriginalSubjectName = | |
| 1931 CERT_GetCertificateNames(cert->nssCert, arena); | |
| 1932 } | |
| 1933 | |
| 1934 if (nssOriginalSubjectName == NULL) { | |
| 1935 pAllSubjectNames = NULL; | |
| 1936 goto cleanup; | |
| 1937 } | |
| 1938 | |
| 1939 nssTempSubjectName = nssOriginalSubjectName; | |
| 1940 | |
| 1941 PKIX_CHECK(PKIX_List_Create(&allSubjectNames, plContext), | |
| 1942 PKIX_LISTCREATEFAILED); | |
| 1943 | |
| 1944 do { | |
| 1945 PKIX_CHECK(pkix_pl_GeneralName_Create | |
| 1946 (nssTempSubjectName, &pkixSubjectName, plContext), | |
| 1947 PKIX_GENERALNAMECREATEFAILED); | |
| 1948 | |
| 1949 PKIX_CHECK(PKIX_List_AppendItem | |
| 1950 (allSubjectNames, | |
| 1951 (PKIX_PL_Object *)pkixSubjectName, | |
| 1952 plContext), | |
| 1953 PKIX_LISTAPPENDITEMFAILED); | |
| 1954 | |
| 1955 PKIX_DECREF(pkixSubjectName); | |
| 1956 | |
| 1957 PKIX_CERT_DEBUG | |
| 1958 ("\t\tCalling CERT_GetNextGeneralName).\n"); | |
| 1959 nssTempSubjectName = CERT_GetNextGeneralName | |
| 1960 (nssTempSubjectName); | |
| 1961 } while (nssTempSubjectName != nssOriginalSubjectName); | |
| 1962 | |
| 1963 *pAllSubjectNames = allSubjectNames; | |
| 1964 | |
| 1965 cleanup: | |
| 1966 if (PKIX_ERROR_RECEIVED){ | |
| 1967 PKIX_DECREF(allSubjectNames); | |
| 1968 } | |
| 1969 | |
| 1970 if (arena){ | |
| 1971 PORT_FreeArena(arena, PR_FALSE); | |
| 1972 } | |
| 1973 PKIX_DECREF(pkixSubjectName); | |
| 1974 PKIX_RETURN(CERT); | |
| 1975 } | |
| 1976 | |
| 1977 /* | |
| 1978 * FUNCTION: PKIX_PL_Cert_GetSubjectPublicKeyAlgId | |
| 1979 * (see comments in pkix_pl_pki.h) | |
| 1980 */ | |
| 1981 PKIX_Error * | |
| 1982 PKIX_PL_Cert_GetSubjectPublicKeyAlgId( | |
| 1983 PKIX_PL_Cert *cert, | |
| 1984 PKIX_PL_OID **pSubjKeyAlgId, | |
| 1985 void *plContext) | |
| 1986 { | |
| 1987 PKIX_PL_OID *pubKeyAlgId = NULL; | |
| 1988 | |
| 1989 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubjectPublicKeyAlgId"); | |
| 1990 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSubjKeyAlgId); | |
| 1991 | |
| 1992 /* if we don't have a cached copy from before, we create one */ | |
| 1993 if (cert->publicKeyAlgId == NULL){ | |
| 1994 PKIX_OBJECT_LOCK(cert); | |
| 1995 if (cert->publicKeyAlgId == NULL){ | |
| 1996 CERTCertificate *nssCert = cert->nssCert; | |
| 1997 SECAlgorithmID *algorithm; | |
| 1998 SECItem *algBytes; | |
| 1999 | |
| 2000 algorithm = &nssCert->subjectPublicKeyInfo.algorithm; | |
| 2001 algBytes = &algorithm->algorithm; | |
| 2002 if (!algBytes->data || !algBytes->len) { | |
| 2003 PKIX_ERROR_FATAL(PKIX_ALGORITHMBYTESLENGTH0); | |
| 2004 } | |
| 2005 PKIX_CHECK(PKIX_PL_OID_CreateBySECItem | |
| 2006 (algBytes, &pubKeyAlgId, plContext), | |
| 2007 PKIX_OIDCREATEFAILED); | |
| 2008 | |
| 2009 /* save a cached copy in case it is asked for again */ | |
| 2010 cert->publicKeyAlgId = pubKeyAlgId; | |
| 2011 pubKeyAlgId = NULL; | |
| 2012 } | |
| 2013 PKIX_OBJECT_UNLOCK(cert); | |
| 2014 } | |
| 2015 | |
| 2016 PKIX_INCREF(cert->publicKeyAlgId); | |
| 2017 *pSubjKeyAlgId = cert->publicKeyAlgId; | |
| 2018 | |
| 2019 cleanup: | |
| 2020 PKIX_DECREF(pubKeyAlgId); | |
| 2021 PKIX_RETURN(CERT); | |
| 2022 } | |
| 2023 | |
| 2024 /* | |
| 2025 * FUNCTION: PKIX_PL_Cert_GetSubjectPublicKey (see comments in pkix_pl_pki.h) | |
| 2026 */ | |
| 2027 PKIX_Error * | |
| 2028 PKIX_PL_Cert_GetSubjectPublicKey( | |
| 2029 PKIX_PL_Cert *cert, | |
| 2030 PKIX_PL_PublicKey **pPublicKey, | |
| 2031 void *plContext) | |
| 2032 { | |
| 2033 PKIX_PL_PublicKey *pkixPubKey = NULL; | |
| 2034 SECStatus rv; | |
| 2035 | |
| 2036 CERTSubjectPublicKeyInfo *from = NULL; | |
| 2037 CERTSubjectPublicKeyInfo *to = NULL; | |
| 2038 SECItem *fromItem = NULL; | |
| 2039 SECItem *toItem = NULL; | |
| 2040 | |
| 2041 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubjectPublicKey"); | |
| 2042 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pPublicKey); | |
| 2043 | |
| 2044 /* if we don't have a cached copy from before, we create one */ | |
| 2045 if (cert->publicKey == NULL){ | |
| 2046 | |
| 2047 PKIX_OBJECT_LOCK(cert); | |
| 2048 | |
| 2049 if (cert->publicKey == NULL){ | |
| 2050 | |
| 2051 /* create a PKIX_PL_PublicKey object */ | |
| 2052 PKIX_CHECK(PKIX_PL_Object_Alloc | |
| 2053 (PKIX_PUBLICKEY_TYPE, | |
| 2054 sizeof (PKIX_PL_PublicKey), | |
| 2055 (PKIX_PL_Object **)&pkixPubKey, | |
| 2056 plContext), | |
| 2057 PKIX_COULDNOTCREATEOBJECT); | |
| 2058 | |
| 2059 /* initialize fields */ | |
| 2060 pkixPubKey->nssSPKI = NULL; | |
| 2061 | |
| 2062 /* populate the SPKI field */ | |
| 2063 PKIX_CHECK(PKIX_PL_Malloc | |
| 2064 (sizeof (CERTSubjectPublicKeyInfo), | |
| 2065 (void **)&pkixPubKey->nssSPKI, | |
| 2066 plContext), | |
| 2067 PKIX_MALLOCFAILED); | |
| 2068 | |
| 2069 to = pkixPubKey->nssSPKI; | |
| 2070 from = &cert->nssCert->subjectPublicKeyInfo; | |
| 2071 | |
| 2072 PKIX_NULLCHECK_TWO(to, from); | |
| 2073 | |
| 2074 PKIX_CERT_DEBUG | |
| 2075 ("\t\tCalling SECOID_CopyAlgorithmID).\n"); | |
| 2076 rv = SECOID_CopyAlgorithmID | |
| 2077 (NULL, &to->algorithm, &from->algorithm); | |
| 2078 if (rv != SECSuccess) { | |
| 2079 PKIX_ERROR(PKIX_SECOIDCOPYALGORITHMIDFAILED); | |
| 2080 } | |
| 2081 | |
| 2082 /* | |
| 2083 * NSS stores the length of subjectPublicKey in bits. | |
| 2084 * Therefore, we use that length converted to bytes | |
| 2085 * using ((length+7)>>3) before calling PORT_Memcpy | |
| 2086 * in order to avoid "read from uninitialized memory" | |
| 2087 * errors. | |
| 2088 */ | |
| 2089 | |
| 2090 toItem = &to->subjectPublicKey; | |
| 2091 fromItem = &from->subjectPublicKey; | |
| 2092 | |
| 2093 PKIX_NULLCHECK_TWO(toItem, fromItem); | |
| 2094 | |
| 2095 toItem->type = fromItem->type; | |
| 2096 | |
| 2097 toItem->data = | |
| 2098 (unsigned char*) PORT_ZAlloc(fromItem->len); | |
| 2099 if (!toItem->data){ | |
| 2100 PKIX_ERROR(PKIX_OUTOFMEMORY); | |
| 2101 } | |
| 2102 | |
| 2103 (void) PORT_Memcpy(toItem->data, | |
| 2104 fromItem->data, | |
| 2105 (fromItem->len + 7)>>3); | |
| 2106 toItem->len = fromItem->len; | |
| 2107 | |
| 2108 /* save a cached copy in case it is asked for again */ | |
| 2109 cert->publicKey = pkixPubKey; | |
| 2110 } | |
| 2111 | |
| 2112 PKIX_OBJECT_UNLOCK(cert); | |
| 2113 } | |
| 2114 | |
| 2115 PKIX_INCREF(cert->publicKey); | |
| 2116 *pPublicKey = cert->publicKey; | |
| 2117 | |
| 2118 cleanup: | |
| 2119 | |
| 2120 if (PKIX_ERROR_RECEIVED && pkixPubKey){ | |
| 2121 PKIX_DECREF(pkixPubKey); | |
| 2122 cert->publicKey = NULL; | |
| 2123 } | |
| 2124 PKIX_RETURN(CERT); | |
| 2125 } | |
| 2126 | |
| 2127 /* | |
| 2128 * FUNCTION: PKIX_PL_Cert_GetCriticalExtensionOIDs | |
| 2129 * (see comments in pkix_pl_pki.h) | |
| 2130 */ | |
| 2131 PKIX_Error * | |
| 2132 PKIX_PL_Cert_GetCriticalExtensionOIDs( | |
| 2133 PKIX_PL_Cert *cert, | |
| 2134 PKIX_List **pList, /* list of PKIX_PL_OID */ | |
| 2135 void *plContext) | |
| 2136 { | |
| 2137 PKIX_List *oidsList = NULL; | |
| 2138 CERTCertExtension **extensions = NULL; | |
| 2139 CERTCertificate *nssCert = NULL; | |
| 2140 | |
| 2141 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetCriticalExtensionOIDs"); | |
| 2142 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pList); | |
| 2143 | |
| 2144 /* if we don't have a cached copy from before, we create one */ | |
| 2145 if (cert->critExtOids == NULL) { | |
| 2146 | |
| 2147 PKIX_OBJECT_LOCK(cert); | |
| 2148 | |
| 2149 if (cert->critExtOids == NULL) { | |
| 2150 | |
| 2151 nssCert = cert->nssCert; | |
| 2152 | |
| 2153 /* | |
| 2154 * ASN.1 for Extension | |
| 2155 * | |
| 2156 * Extension ::= SEQUENCE { | |
| 2157 * extnID OBJECT IDENTIFIER, | |
| 2158 * critical BOOLEAN DEFAULT FALSE, | |
| 2159 * extnValue OCTET STRING } | |
| 2160 * | |
| 2161 */ | |
| 2162 | |
| 2163 extensions = nssCert->extensions; | |
| 2164 | |
| 2165 PKIX_CHECK(pkix_pl_OID_GetCriticalExtensionOIDs | |
| 2166 (extensions, &oidsList, plContext), | |
| 2167 PKIX_GETCRITICALEXTENSIONOIDSFAILED); | |
| 2168 | |
| 2169 /* save a cached copy in case it is asked for again */ | |
| 2170 cert->critExtOids = oidsList; | |
| 2171 } | |
| 2172 | |
| 2173 PKIX_OBJECT_UNLOCK(cert); | |
| 2174 } | |
| 2175 | |
| 2176 /* We should return a copy of the List since this list changes */ | |
| 2177 PKIX_DUPLICATE(cert->critExtOids, pList, plContext, | |
| 2178 PKIX_OBJECTDUPLICATELISTFAILED); | |
| 2179 | |
| 2180 cleanup: | |
| 2181 PKIX_OBJECT_UNLOCK(lockedObject); | |
| 2182 PKIX_RETURN(CERT); | |
| 2183 } | |
| 2184 | |
| 2185 /* | |
| 2186 * FUNCTION: PKIX_PL_Cert_GetAuthorityKeyIdentifier | |
| 2187 * (see comments in pkix_pl_pki.h) | |
| 2188 */ | |
| 2189 PKIX_Error * | |
| 2190 PKIX_PL_Cert_GetAuthorityKeyIdentifier( | |
| 2191 PKIX_PL_Cert *cert, | |
| 2192 PKIX_PL_ByteArray **pAuthKeyId, | |
| 2193 void *plContext) | |
| 2194 { | |
| 2195 PKIX_PL_ByteArray *authKeyId = NULL; | |
| 2196 CERTCertificate *nssCert = NULL; | |
| 2197 CERTAuthKeyID *authKeyIdExtension = NULL; | |
| 2198 PLArenaPool *arena = NULL; | |
| 2199 SECItem retItem; | |
| 2200 | |
| 2201 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetAuthorityKeyIdentifier"); | |
| 2202 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pAuthKeyId); | |
| 2203 | |
| 2204 /* if we don't have a cached copy from before, we create one */ | |
| 2205 if ((cert->authKeyId == NULL) && (!cert->authKeyIdAbsent)){ | |
| 2206 | |
| 2207 PKIX_OBJECT_LOCK(cert); | |
| 2208 | |
| 2209 if ((cert->authKeyId == NULL) && (!cert->authKeyIdAbsent)){ | |
| 2210 | |
| 2211 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | |
| 2212 if (arena == NULL) { | |
| 2213 PKIX_ERROR(PKIX_OUTOFMEMORY); | |
| 2214 } | |
| 2215 | |
| 2216 nssCert = cert->nssCert; | |
| 2217 | |
| 2218 authKeyIdExtension = | |
| 2219 CERT_FindAuthKeyIDExten(arena, nssCert); | |
| 2220 if (authKeyIdExtension == NULL){ | |
| 2221 cert->authKeyIdAbsent = PKIX_TRUE; | |
| 2222 *pAuthKeyId = NULL; | |
| 2223 goto cleanup; | |
| 2224 } | |
| 2225 | |
| 2226 retItem = authKeyIdExtension->keyID; | |
| 2227 | |
| 2228 if (retItem.len == 0){ | |
| 2229 cert->authKeyIdAbsent = PKIX_TRUE; | |
| 2230 *pAuthKeyId = NULL; | |
| 2231 goto cleanup; | |
| 2232 } | |
| 2233 | |
| 2234 PKIX_CHECK(PKIX_PL_ByteArray_Create | |
| 2235 (retItem.data, | |
| 2236 retItem.len, | |
| 2237 &authKeyId, | |
| 2238 plContext), | |
| 2239 PKIX_BYTEARRAYCREATEFAILED); | |
| 2240 | |
| 2241 /* save a cached copy in case it is asked for again */ | |
| 2242 cert->authKeyId = authKeyId; | |
| 2243 } | |
| 2244 | |
| 2245 PKIX_OBJECT_UNLOCK(cert); | |
| 2246 } | |
| 2247 | |
| 2248 PKIX_INCREF(cert->authKeyId); | |
| 2249 *pAuthKeyId = cert->authKeyId; | |
| 2250 | |
| 2251 cleanup: | |
| 2252 PKIX_OBJECT_UNLOCK(lockedObject); | |
| 2253 if (arena){ | |
| 2254 PORT_FreeArena(arena, PR_FALSE); | |
| 2255 } | |
| 2256 PKIX_RETURN(CERT); | |
| 2257 } | |
| 2258 | |
| 2259 /* | |
| 2260 * FUNCTION: PKIX_PL_Cert_GetSubjectKeyIdentifier | |
| 2261 * (see comments in pkix_pl_pki.h) | |
| 2262 */ | |
| 2263 PKIX_Error * | |
| 2264 PKIX_PL_Cert_GetSubjectKeyIdentifier( | |
| 2265 PKIX_PL_Cert *cert, | |
| 2266 PKIX_PL_ByteArray **pSubjKeyId, | |
| 2267 void *plContext) | |
| 2268 { | |
| 2269 PKIX_PL_ByteArray *subjKeyId = NULL; | |
| 2270 CERTCertificate *nssCert = NULL; | |
| 2271 SECItem *retItem = NULL; | |
| 2272 SECStatus status; | |
| 2273 | |
| 2274 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubjectKeyIdentifier"); | |
| 2275 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSubjKeyId); | |
| 2276 | |
| 2277 /* if we don't have a cached copy from before, we create one */ | |
| 2278 if ((cert->subjKeyId == NULL) && (!cert->subjKeyIdAbsent)){ | |
| 2279 | |
| 2280 PKIX_OBJECT_LOCK(cert); | |
| 2281 | |
| 2282 if ((cert->subjKeyId == NULL) && (!cert->subjKeyIdAbsent)){ | |
| 2283 | |
| 2284 retItem = SECITEM_AllocItem(NULL, NULL, 0); | |
| 2285 if (retItem == NULL){ | |
| 2286 PKIX_ERROR(PKIX_OUTOFMEMORY); | |
| 2287 } | |
| 2288 | |
| 2289 nssCert = cert->nssCert; | |
| 2290 | |
| 2291 status = CERT_FindSubjectKeyIDExtension | |
| 2292 (nssCert, retItem); | |
| 2293 if (status != SECSuccess) { | |
| 2294 cert->subjKeyIdAbsent = PKIX_TRUE; | |
| 2295 *pSubjKeyId = NULL; | |
| 2296 goto cleanup; | |
| 2297 } | |
| 2298 | |
| 2299 PKIX_CHECK(PKIX_PL_ByteArray_Create | |
| 2300 (retItem->data, | |
| 2301 retItem->len, | |
| 2302 &subjKeyId, | |
| 2303 plContext), | |
| 2304 PKIX_BYTEARRAYCREATEFAILED); | |
| 2305 | |
| 2306 /* save a cached copy in case it is asked for again */ | |
| 2307 cert->subjKeyId = subjKeyId; | |
| 2308 } | |
| 2309 | |
| 2310 PKIX_OBJECT_UNLOCK(cert); | |
| 2311 } | |
| 2312 | |
| 2313 PKIX_INCREF(cert->subjKeyId); | |
| 2314 *pSubjKeyId = cert->subjKeyId; | |
| 2315 | |
| 2316 cleanup: | |
| 2317 PKIX_OBJECT_UNLOCK(lockedObject); | |
| 2318 if (retItem){ | |
| 2319 SECITEM_FreeItem(retItem, PKIX_TRUE); | |
| 2320 } | |
| 2321 PKIX_RETURN(CERT); | |
| 2322 } | |
| 2323 | |
| 2324 /* | |
| 2325 * FUNCTION: PKIX_PL_Cert_GetExtendedKeyUsage (see comments in pkix_pl_pki.h) | |
| 2326 */ | |
| 2327 PKIX_Error * | |
| 2328 PKIX_PL_Cert_GetExtendedKeyUsage( | |
| 2329 PKIX_PL_Cert *cert, | |
| 2330 PKIX_List **pKeyUsage, /* list of PKIX_PL_OID */ | |
| 2331 void *plContext) | |
| 2332 { | |
| 2333 CERTOidSequence *extKeyUsage = NULL; | |
| 2334 CERTCertificate *nssCert = NULL; | |
| 2335 PKIX_PL_OID *pkixOID = NULL; | |
| 2336 PKIX_List *oidsList = NULL; | |
| 2337 SECItem **oids = NULL; | |
| 2338 SECItem encodedExtKeyUsage; | |
| 2339 SECStatus rv; | |
| 2340 | |
| 2341 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetExtendedKeyUsage"); | |
| 2342 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pKeyUsage); | |
| 2343 | |
| 2344 /* if we don't have a cached copy from before, we create one */ | |
| 2345 if ((cert->extKeyUsages == NULL) && (!cert->extKeyUsagesAbsent)){ | |
| 2346 | |
| 2347 PKIX_OBJECT_LOCK(cert); | |
| 2348 | |
| 2349 if ((cert->extKeyUsages == NULL) && | |
| 2350 (!cert->extKeyUsagesAbsent)){ | |
| 2351 | |
| 2352 nssCert = cert->nssCert; | |
| 2353 | |
| 2354 rv = CERT_FindCertExtension | |
| 2355 (nssCert, SEC_OID_X509_EXT_KEY_USAGE, | |
| 2356 &encodedExtKeyUsage); | |
| 2357 if (rv != SECSuccess){ | |
| 2358 cert->extKeyUsagesAbsent = PKIX_TRUE; | |
| 2359 *pKeyUsage = NULL; | |
| 2360 goto cleanup; | |
| 2361 } | |
| 2362 | |
| 2363 extKeyUsage = | |
| 2364 CERT_DecodeOidSequence(&encodedExtKeyUsage); | |
| 2365 if (extKeyUsage == NULL){ | |
| 2366 PKIX_ERROR(PKIX_CERTDECODEOIDSEQUENCEFAILED); | |
| 2367 } | |
| 2368 | |
| 2369 PORT_Free(encodedExtKeyUsage.data); | |
| 2370 | |
| 2371 oids = extKeyUsage->oids; | |
| 2372 | |
| 2373 if (!oids){ | |
| 2374 /* no extended key usage extensions found */ | |
| 2375 cert->extKeyUsagesAbsent = PKIX_TRUE; | |
| 2376 *pKeyUsage = NULL; | |
| 2377 goto cleanup; | |
| 2378 } | |
| 2379 | |
| 2380 PKIX_CHECK(PKIX_List_Create(&oidsList, plContext), | |
| 2381 PKIX_LISTCREATEFAILED); | |
| 2382 | |
| 2383 while (*oids){ | |
| 2384 SECItem *oid = *oids++; | |
| 2385 | |
| 2386 PKIX_CHECK(PKIX_PL_OID_CreateBySECItem | |
| 2387 (oid, &pkixOID, plContext), | |
| 2388 PKIX_OIDCREATEFAILED); | |
| 2389 | |
| 2390 PKIX_CHECK(PKIX_List_AppendItem | |
| 2391 (oidsList, | |
| 2392 (PKIX_PL_Object *)pkixOID, | |
| 2393 plContext), | |
| 2394 PKIX_LISTAPPENDITEMFAILED); | |
| 2395 PKIX_DECREF(pkixOID); | |
| 2396 } | |
| 2397 | |
| 2398 PKIX_CHECK(PKIX_List_SetImmutable | |
| 2399 (oidsList, plContext), | |
| 2400 PKIX_LISTSETIMMUTABLEFAILED); | |
| 2401 | |
| 2402 /* save a cached copy in case it is asked for again */ | |
| 2403 cert->extKeyUsages = oidsList; | |
| 2404 oidsList = NULL; | |
| 2405 } | |
| 2406 | |
| 2407 PKIX_OBJECT_UNLOCK(cert); | |
| 2408 } | |
| 2409 | |
| 2410 PKIX_INCREF(cert->extKeyUsages); | |
| 2411 *pKeyUsage = cert->extKeyUsages; | |
| 2412 | |
| 2413 cleanup: | |
| 2414 PKIX_OBJECT_UNLOCK(lockedObject); | |
| 2415 | |
| 2416 PKIX_DECREF(pkixOID); | |
| 2417 PKIX_DECREF(oidsList); | |
| 2418 CERT_DestroyOidSequence(extKeyUsage); | |
| 2419 | |
| 2420 PKIX_RETURN(CERT); | |
| 2421 } | |
| 2422 | |
| 2423 /* | |
| 2424 * FUNCTION: PKIX_PL_Cert_GetBasicConstraints | |
| 2425 * (see comments in pkix_pl_pki.h) | |
| 2426 */ | |
| 2427 PKIX_Error * | |
| 2428 PKIX_PL_Cert_GetBasicConstraints( | |
| 2429 PKIX_PL_Cert *cert, | |
| 2430 PKIX_PL_CertBasicConstraints **pBasicConstraints, | |
| 2431 void *plContext) | |
| 2432 { | |
| 2433 CERTCertificate *nssCert = NULL; | |
| 2434 CERTBasicConstraints nssBasicConstraint; | |
| 2435 SECStatus rv; | |
| 2436 PKIX_PL_CertBasicConstraints *basic; | |
| 2437 PKIX_Int32 pathLen = 0; | |
| 2438 PKIX_Boolean isCA = PKIX_FALSE; | |
| 2439 enum { | |
| 2440 realBC, synthBC, absentBC | |
| 2441 } constraintSource = absentBC; | |
| 2442 | |
| 2443 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetBasicConstraints"); | |
| 2444 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pBasicConstraints); | |
| 2445 | |
| 2446 /* if we don't have a cached copy from before, we create one */ | |
| 2447 if ((cert->certBasicConstraints == NULL) && | |
| 2448 (!cert->basicConstraintsAbsent)) { | |
| 2449 | |
| 2450 PKIX_OBJECT_LOCK(cert); | |
| 2451 | |
| 2452 if ((cert->certBasicConstraints == NULL) && | |
| 2453 (!cert->basicConstraintsAbsent)) { | |
| 2454 | |
| 2455 nssCert = cert->nssCert; | |
| 2456 | |
| 2457 PKIX_CERT_DEBUG( | |
| 2458 "\t\tCalling Cert_FindBasicConstraintExten\n"); | |
| 2459 rv = CERT_FindBasicConstraintExten | |
| 2460 (nssCert, &nssBasicConstraint); | |
| 2461 if (rv == SECSuccess) { | |
| 2462 constraintSource = realBC; | |
| 2463 } | |
| 2464 | |
| 2465 if (constraintSource == absentBC) { | |
| 2466 /* can we deduce it's a CA and create a | |
| 2467 synthetic constraint? | |
| 2468 */ | |
| 2469 CERTCertTrust trust; | |
| 2470 rv = CERT_GetCertTrust(nssCert, &trust); | |
| 2471 if (rv == SECSuccess) { | |
| 2472 int anyWantedFlag = CERTDB_TRUSTED_CA | CERTDB_V
ALID_CA; | |
| 2473 if ((trust.sslFlags & anyWantedFlag) | |
| 2474 || (trust.emailFlags & anyWantedFlag) | |
| 2475 || (trust.objectSigningFlags & anyWantedFlag
)) { | |
| 2476 | |
| 2477 constraintSource = synthBC; | |
| 2478 } | |
| 2479 } | |
| 2480 } | |
| 2481 | |
| 2482 if (constraintSource == absentBC) { | |
| 2483 cert->basicConstraintsAbsent = PKIX_TRUE; | |
| 2484 *pBasicConstraints = NULL; | |
| 2485 goto cleanup; | |
| 2486 } | |
| 2487 } | |
| 2488 | |
| 2489 if (constraintSource == synthBC) { | |
| 2490 isCA = PKIX_TRUE; | |
| 2491 pathLen = PKIX_UNLIMITED_PATH_CONSTRAINT; | |
| 2492 } else { | |
| 2493 isCA = (nssBasicConstraint.isCA)?PKIX_TRUE:PKIX_FALSE; | |
| 2494 | |
| 2495 /* The pathLen has meaning only for CAs */ | |
| 2496 if (isCA) { | |
| 2497 if (CERT_UNLIMITED_PATH_CONSTRAINT == | |
| 2498 nssBasicConstraint.pathLenConstraint) { | |
| 2499 pathLen = PKIX_UNLIMITED_PATH_CONSTRAINT; | |
| 2500 } else { | |
| 2501 pathLen = nssBasicConstraint.pathLenConstraint; | |
| 2502 } | |
| 2503 } | |
| 2504 } | |
| 2505 | |
| 2506 PKIX_CHECK(pkix_pl_CertBasicConstraints_Create | |
| 2507 (isCA, pathLen, &basic, plContext), | |
| 2508 PKIX_CERTBASICCONSTRAINTSCREATEFAILED); | |
| 2509 | |
| 2510 /* save a cached copy in case it is asked for again */ | |
| 2511 cert->certBasicConstraints = basic; | |
| 2512 } | |
| 2513 | |
| 2514 PKIX_INCREF(cert->certBasicConstraints); | |
| 2515 *pBasicConstraints = cert->certBasicConstraints; | |
| 2516 | |
| 2517 cleanup: | |
| 2518 PKIX_OBJECT_UNLOCK(lockedObject); | |
| 2519 PKIX_RETURN(CERT); | |
| 2520 } | |
| 2521 | |
| 2522 /* | |
| 2523 * FUNCTION: PKIX_PL_Cert_GetPolicyInformation | |
| 2524 * (see comments in pkix_pl_pki.h) | |
| 2525 */ | |
| 2526 PKIX_Error * | |
| 2527 PKIX_PL_Cert_GetPolicyInformation( | |
| 2528 PKIX_PL_Cert *cert, | |
| 2529 PKIX_List **pPolicyInfo, | |
| 2530 void *plContext) | |
| 2531 { | |
| 2532 PKIX_List *policyList = NULL; | |
| 2533 | |
| 2534 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetPolicyInformation"); | |
| 2535 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pPolicyInfo); | |
| 2536 | |
| 2537 /* if we don't have a cached copy from before, we create one */ | |
| 2538 if ((cert->certPolicyInfos == NULL) && | |
| 2539 (!cert->policyInfoAbsent)) { | |
| 2540 | |
| 2541 PKIX_OBJECT_LOCK(cert); | |
| 2542 | |
| 2543 if ((cert->certPolicyInfos == NULL) && | |
| 2544 (!cert->policyInfoAbsent)) { | |
| 2545 | |
| 2546 PKIX_CHECK(pkix_pl_Cert_DecodePolicyInfo | |
| 2547 (cert->nssCert, &policyList, plContext), | |
| 2548 PKIX_CERTDECODEPOLICYINFOFAILED); | |
| 2549 | |
| 2550 if (!policyList) { | |
| 2551 cert->policyInfoAbsent = PKIX_TRUE; | |
| 2552 *pPolicyInfo = NULL; | |
| 2553 goto cleanup; | |
| 2554 } | |
| 2555 } | |
| 2556 | |
| 2557 PKIX_OBJECT_UNLOCK(cert); | |
| 2558 | |
| 2559 /* save a cached copy in case it is asked for again */ | |
| 2560 cert->certPolicyInfos = policyList; | |
| 2561 policyList = NULL; | |
| 2562 } | |
| 2563 | |
| 2564 PKIX_INCREF(cert->certPolicyInfos); | |
| 2565 *pPolicyInfo = cert->certPolicyInfos; | |
| 2566 | |
| 2567 cleanup: | |
| 2568 PKIX_OBJECT_UNLOCK(lockedObject); | |
| 2569 | |
| 2570 PKIX_DECREF(policyList); | |
| 2571 PKIX_RETURN(CERT); | |
| 2572 } | |
| 2573 | |
| 2574 /* | |
| 2575 * FUNCTION: PKIX_PL_Cert_GetPolicyMappings (see comments in pkix_pl_pki.h) | |
| 2576 */ | |
| 2577 PKIX_Error * | |
| 2578 PKIX_PL_Cert_GetPolicyMappings( | |
| 2579 PKIX_PL_Cert *cert, | |
| 2580 PKIX_List **pPolicyMappings, /* list of PKIX_PL_CertPolicyMap */ | |
| 2581 void *plContext) | |
| 2582 { | |
| 2583 PKIX_List *policyMappings = NULL; /* list of PKIX_PL_CertPolicyMap */ | |
| 2584 | |
| 2585 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetPolicyMappings"); | |
| 2586 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pPolicyMappings); | |
| 2587 | |
| 2588 /* if we don't have a cached copy from before, we create one */ | |
| 2589 if (!(cert->certPolicyMappings) && !(cert->policyMappingsAbsent)) { | |
| 2590 | |
| 2591 PKIX_OBJECT_LOCK(cert); | |
| 2592 | |
| 2593 if (!(cert->certPolicyMappings) && | |
| 2594 !(cert->policyMappingsAbsent)) { | |
| 2595 | |
| 2596 PKIX_CHECK(pkix_pl_Cert_DecodePolicyMapping | |
| 2597 (cert->nssCert, &policyMappings, plContext), | |
| 2598 PKIX_CERTDECODEPOLICYMAPPINGFAILED); | |
| 2599 | |
| 2600 if (!policyMappings) { | |
| 2601 cert->policyMappingsAbsent = PKIX_TRUE; | |
| 2602 *pPolicyMappings = NULL; | |
| 2603 goto cleanup; | |
| 2604 } | |
| 2605 } | |
| 2606 | |
| 2607 PKIX_OBJECT_UNLOCK(cert); | |
| 2608 | |
| 2609 /* save a cached copy in case it is asked for again */ | |
| 2610 cert->certPolicyMappings = policyMappings; | |
| 2611 policyMappings = NULL; | |
| 2612 } | |
| 2613 | |
| 2614 PKIX_INCREF(cert->certPolicyMappings); | |
| 2615 *pPolicyMappings = cert->certPolicyMappings; | |
| 2616 | |
| 2617 cleanup: | |
| 2618 PKIX_OBJECT_UNLOCK(lockedObject); | |
| 2619 | |
| 2620 PKIX_DECREF(policyMappings); | |
| 2621 PKIX_RETURN(CERT); | |
| 2622 } | |
| 2623 | |
| 2624 /* | |
| 2625 * FUNCTION: PKIX_PL_Cert_GetRequireExplicitPolicy | |
| 2626 * (see comments in pkix_pl_pki.h) | |
| 2627 */ | |
| 2628 PKIX_Error * | |
| 2629 PKIX_PL_Cert_GetRequireExplicitPolicy( | |
| 2630 PKIX_PL_Cert *cert, | |
| 2631 PKIX_Int32 *pSkipCerts, | |
| 2632 void *plContext) | |
| 2633 { | |
| 2634 PKIX_Int32 explicitPolicySkipCerts = 0; | |
| 2635 PKIX_Int32 inhibitMappingSkipCerts = 0; | |
| 2636 | |
| 2637 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetRequireExplicitPolicy"); | |
| 2638 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSkipCerts); | |
| 2639 | |
| 2640 if (!(cert->policyConstraintsProcessed)) { | |
| 2641 PKIX_OBJECT_LOCK(cert); | |
| 2642 | |
| 2643 if (!(cert->policyConstraintsProcessed)) { | |
| 2644 | |
| 2645 /* | |
| 2646 * If we can't process it now, we probably will be | |
| 2647 * unable to process it later. Set the default value. | |
| 2648 */ | |
| 2649 cert->policyConstraintsProcessed = PKIX_TRUE; | |
| 2650 cert->policyConstraintsExplicitPolicySkipCerts = -1; | |
| 2651 cert->policyConstraintsInhibitMappingSkipCerts = -1; | |
| 2652 | |
| 2653 PKIX_CHECK(pkix_pl_Cert_DecodePolicyConstraints | |
| 2654 (cert->nssCert, | |
| 2655 &explicitPolicySkipCerts, | |
| 2656 &inhibitMappingSkipCerts, | |
| 2657 plContext), | |
| 2658 PKIX_CERTDECODEPOLICYCONSTRAINTSFAILED); | |
| 2659 | |
| 2660 cert->policyConstraintsExplicitPolicySkipCerts = | |
| 2661 explicitPolicySkipCerts; | |
| 2662 cert->policyConstraintsInhibitMappingSkipCerts = | |
| 2663 inhibitMappingSkipCerts; | |
| 2664 } | |
| 2665 | |
| 2666 PKIX_OBJECT_UNLOCK(cert); | |
| 2667 } | |
| 2668 | |
| 2669 *pSkipCerts = cert->policyConstraintsExplicitPolicySkipCerts; | |
| 2670 | |
| 2671 cleanup: | |
| 2672 PKIX_OBJECT_UNLOCK(lockedObject); | |
| 2673 PKIX_RETURN(CERT); | |
| 2674 } | |
| 2675 | |
| 2676 /* | |
| 2677 * FUNCTION: PKIX_PL_Cert_GetPolicyMappingInhibited | |
| 2678 * (see comments in pkix_pl_pki.h) | |
| 2679 */ | |
| 2680 PKIX_Error * | |
| 2681 PKIX_PL_Cert_GetPolicyMappingInhibited( | |
| 2682 PKIX_PL_Cert *cert, | |
| 2683 PKIX_Int32 *pSkipCerts, | |
| 2684 void *plContext) | |
| 2685 { | |
| 2686 PKIX_Int32 explicitPolicySkipCerts = 0; | |
| 2687 PKIX_Int32 inhibitMappingSkipCerts = 0; | |
| 2688 | |
| 2689 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetPolicyMappingInhibited"); | |
| 2690 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSkipCerts); | |
| 2691 | |
| 2692 if (!(cert->policyConstraintsProcessed)) { | |
| 2693 PKIX_OBJECT_LOCK(cert); | |
| 2694 | |
| 2695 if (!(cert->policyConstraintsProcessed)) { | |
| 2696 | |
| 2697 /* | |
| 2698 * If we can't process it now, we probably will be | |
| 2699 * unable to process it later. Set the default value. | |
| 2700 */ | |
| 2701 cert->policyConstraintsProcessed = PKIX_TRUE; | |
| 2702 cert->policyConstraintsExplicitPolicySkipCerts = -1; | |
| 2703 cert->policyConstraintsInhibitMappingSkipCerts = -1; | |
| 2704 | |
| 2705 PKIX_CHECK(pkix_pl_Cert_DecodePolicyConstraints | |
| 2706 (cert->nssCert, | |
| 2707 &explicitPolicySkipCerts, | |
| 2708 &inhibitMappingSkipCerts, | |
| 2709 plContext), | |
| 2710 PKIX_CERTDECODEPOLICYCONSTRAINTSFAILED); | |
| 2711 | |
| 2712 cert->policyConstraintsExplicitPolicySkipCerts = | |
| 2713 explicitPolicySkipCerts; | |
| 2714 cert->policyConstraintsInhibitMappingSkipCerts = | |
| 2715 inhibitMappingSkipCerts; | |
| 2716 } | |
| 2717 | |
| 2718 PKIX_OBJECT_UNLOCK(cert); | |
| 2719 } | |
| 2720 | |
| 2721 *pSkipCerts = cert->policyConstraintsInhibitMappingSkipCerts; | |
| 2722 | |
| 2723 cleanup: | |
| 2724 PKIX_OBJECT_UNLOCK(lockedObject); | |
| 2725 PKIX_RETURN(CERT); | |
| 2726 } | |
| 2727 | |
| 2728 /* | |
| 2729 * FUNCTION: PKIX_PL_Cert_GetInhibitAnyPolicy (see comments in pkix_pl_pki.h) | |
| 2730 */ | |
| 2731 PKIX_Error * | |
| 2732 PKIX_PL_Cert_GetInhibitAnyPolicy( | |
| 2733 PKIX_PL_Cert *cert, | |
| 2734 PKIX_Int32 *pSkipCerts, | |
| 2735 void *plContext) | |
| 2736 { | |
| 2737 PKIX_Int32 skipCerts = 0; | |
| 2738 | |
| 2739 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetInhibitAnyPolicy"); | |
| 2740 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSkipCerts); | |
| 2741 | |
| 2742 if (!(cert->inhibitAnyPolicyProcessed)) { | |
| 2743 | |
| 2744 PKIX_OBJECT_LOCK(cert); | |
| 2745 | |
| 2746 if (!(cert->inhibitAnyPolicyProcessed)) { | |
| 2747 | |
| 2748 /* | |
| 2749 * If we can't process it now, we probably will be | |
| 2750 * unable to process it later. Set the default value. | |
| 2751 */ | |
| 2752 cert->inhibitAnyPolicyProcessed = PKIX_TRUE; | |
| 2753 cert->inhibitAnySkipCerts = -1; | |
| 2754 | |
| 2755 PKIX_CHECK(pkix_pl_Cert_DecodeInhibitAnyPolicy | |
| 2756 (cert->nssCert, &skipCerts, plContext), | |
| 2757 PKIX_CERTDECODEINHIBITANYPOLICYFAILED); | |
| 2758 | |
| 2759 cert->inhibitAnySkipCerts = skipCerts; | |
| 2760 } | |
| 2761 | |
| 2762 PKIX_OBJECT_UNLOCK(cert); | |
| 2763 } | |
| 2764 | |
| 2765 cleanup: | |
| 2766 PKIX_OBJECT_UNLOCK(lockedObject); | |
| 2767 *pSkipCerts = cert->inhibitAnySkipCerts; | |
| 2768 PKIX_RETURN(CERT); | |
| 2769 } | |
| 2770 | |
| 2771 /* | |
| 2772 * FUNCTION: PKIX_PL_Cert_AreCertPoliciesCritical | |
| 2773 * (see comments in pkix_pl_pki.h) | |
| 2774 */ | |
| 2775 PKIX_Error * | |
| 2776 PKIX_PL_Cert_AreCertPoliciesCritical( | |
| 2777 PKIX_PL_Cert *cert, | |
| 2778 PKIX_Boolean *pCritical, | |
| 2779 void *plContext) | |
| 2780 { | |
| 2781 PKIX_Boolean criticality = PKIX_FALSE; | |
| 2782 | |
| 2783 PKIX_ENTER(CERT, "PKIX_PL_Cert_AreCertPoliciesCritical"); | |
| 2784 PKIX_NULLCHECK_TWO(cert, pCritical); | |
| 2785 | |
| 2786 PKIX_CHECK(pkix_pl_Cert_IsExtensionCritical( | |
| 2787 cert, | |
| 2788 SEC_OID_X509_CERTIFICATE_POLICIES, | |
| 2789 &criticality, | |
| 2790 plContext), | |
| 2791 PKIX_CERTISEXTENSIONCRITICALFAILED); | |
| 2792 | |
| 2793 *pCritical = criticality; | |
| 2794 | |
| 2795 cleanup: | |
| 2796 PKIX_RETURN(CERT); | |
| 2797 } | |
| 2798 | |
| 2799 /* | |
| 2800 * FUNCTION: PKIX_PL_Cert_VerifySignature (see comments in pkix_pl_pki.h) | |
| 2801 */ | |
| 2802 PKIX_Error * | |
| 2803 PKIX_PL_Cert_VerifySignature( | |
| 2804 PKIX_PL_Cert *cert, | |
| 2805 PKIX_PL_PublicKey *pubKey, | |
| 2806 void *plContext) | |
| 2807 { | |
| 2808 CERTCertificate *nssCert = NULL; | |
| 2809 SECKEYPublicKey *nssPubKey = NULL; | |
| 2810 CERTSignedData *tbsCert = NULL; | |
| 2811 PKIX_PL_Cert *cachedCert = NULL; | |
| 2812 PKIX_Error *verifySig = NULL; | |
| 2813 PKIX_Error *cachedSig = NULL; | |
| 2814 SECStatus status; | |
| 2815 PKIX_Boolean certEqual = PKIX_FALSE; | |
| 2816 PKIX_Boolean certInHash = PKIX_FALSE; | |
| 2817 void* wincx = NULL; | |
| 2818 | |
| 2819 PKIX_ENTER(CERT, "PKIX_PL_Cert_VerifySignature"); | |
| 2820 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pubKey); | |
| 2821 | |
| 2822 verifySig = PKIX_PL_HashTable_Lookup | |
| 2823 (cachedCertSigTable, | |
| 2824 (PKIX_PL_Object *) pubKey, | |
| 2825 (PKIX_PL_Object **) &cachedCert, | |
| 2826 plContext); | |
| 2827 | |
| 2828 if (cachedCert != NULL && verifySig == NULL) { | |
| 2829 /* Cached Signature Table lookup succeed */ | |
| 2830 PKIX_EQUALS(cert, cachedCert, &certEqual, plContext, | |
| 2831 PKIX_OBJECTEQUALSFAILED); | |
| 2832 if (certEqual == PKIX_TRUE) { | |
| 2833 goto cleanup; | |
| 2834 } | |
| 2835 /* Different PubKey may hash to same value, skip add */ | |
| 2836 certInHash = PKIX_TRUE; | |
| 2837 } | |
| 2838 | |
| 2839 nssCert = cert->nssCert; | |
| 2840 tbsCert = &nssCert->signatureWrap; | |
| 2841 | |
| 2842 PKIX_CERT_DEBUG("\t\tCalling SECKEY_ExtractPublicKey).\n"); | |
| 2843 nssPubKey = SECKEY_ExtractPublicKey(pubKey->nssSPKI); | |
| 2844 if (!nssPubKey){ | |
| 2845 PKIX_ERROR(PKIX_SECKEYEXTRACTPUBLICKEYFAILED); | |
| 2846 } | |
| 2847 | |
| 2848 PKIX_CERT_DEBUG("\t\tCalling CERT_VerifySignedDataWithPublicKey).\n"); | |
| 2849 | |
| 2850 PKIX_CHECK(pkix_pl_NssContext_GetWincx | |
| 2851 ((PKIX_PL_NssContext *)plContext, &wincx), | |
| 2852 PKIX_NSSCONTEXTGETWINCXFAILED); | |
| 2853 | |
| 2854 status = CERT_VerifySignedDataWithPublicKey(tbsCert, nssPubKey, wincx); | |
| 2855 | |
| 2856 if (status != SECSuccess) { | |
| 2857 if (PORT_GetError() != SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABL
ED) { | |
| 2858 PORT_SetError(SEC_ERROR_BAD_SIGNATURE); | |
| 2859 } | |
| 2860 PKIX_ERROR(PKIX_SIGNATUREDIDNOTVERIFYWITHTHEPUBLICKEY); | |
| 2861 } | |
| 2862 | |
| 2863 if (certInHash == PKIX_FALSE) { | |
| 2864 cachedSig = PKIX_PL_HashTable_Add | |
| 2865 (cachedCertSigTable, | |
| 2866 (PKIX_PL_Object *) pubKey, | |
| 2867 (PKIX_PL_Object *) cert, | |
| 2868 plContext); | |
| 2869 | |
| 2870 if (cachedSig != NULL) { | |
| 2871 PKIX_DEBUG("PKIX_PL_HashTable_Add skipped: entry existed
\n"); | |
| 2872 } | |
| 2873 } | |
| 2874 | |
| 2875 cleanup: | |
| 2876 if (nssPubKey){ | |
| 2877 PKIX_CERT_DEBUG("\t\tCalling SECKEY_DestroyPublicKey).\n"); | |
| 2878 SECKEY_DestroyPublicKey(nssPubKey); | |
| 2879 } | |
| 2880 | |
| 2881 PKIX_DECREF(cachedCert); | |
| 2882 PKIX_DECREF(verifySig); | |
| 2883 PKIX_DECREF(cachedSig); | |
| 2884 | |
| 2885 PKIX_RETURN(CERT); | |
| 2886 } | |
| 2887 | |
| 2888 /* | |
| 2889 * FUNCTION: PKIX_PL_Cert_CheckValidity (see comments in pkix_pl_pki.h) | |
| 2890 */ | |
| 2891 PKIX_Error * | |
| 2892 PKIX_PL_Cert_CheckValidity( | |
| 2893 PKIX_PL_Cert *cert, | |
| 2894 PKIX_PL_Date *date, | |
| 2895 void *plContext) | |
| 2896 { | |
| 2897 SECCertTimeValidity val; | |
| 2898 PRTime timeToCheck; | |
| 2899 PKIX_Boolean allowOverride; | |
| 2900 SECCertificateUsage requiredUsages; | |
| 2901 | |
| 2902 PKIX_ENTER(CERT, "PKIX_PL_Cert_CheckValidity"); | |
| 2903 PKIX_NULLCHECK_ONE(cert); | |
| 2904 | |
| 2905 /* if the caller supplies a date, we use it; else, use current time */ | |
| 2906 if (date != NULL){ | |
| 2907 PKIX_CHECK(pkix_pl_Date_GetPRTime | |
| 2908 (date, &timeToCheck, plContext), | |
| 2909 PKIX_DATEGETPRTIMEFAILED); | |
| 2910 } else { | |
| 2911 timeToCheck = PR_Now(); | |
| 2912 } | |
| 2913 | |
| 2914 requiredUsages = ((PKIX_PL_NssContext*)plContext)->certificateUsage; | |
| 2915 allowOverride = | |
| 2916 (PRBool)((requiredUsages & certificateUsageSSLServer) || | |
| 2917 (requiredUsages & certificateUsageSSLServerWithStepUp)); | |
| 2918 val = CERT_CheckCertValidTimes(cert->nssCert, timeToCheck, allowOverride
); | |
| 2919 if (val != secCertTimeValid){ | |
| 2920 PKIX_ERROR(PKIX_CERTCHECKCERTVALIDTIMESFAILED); | |
| 2921 } | |
| 2922 | |
| 2923 cleanup: | |
| 2924 PKIX_RETURN(CERT); | |
| 2925 } | |
| 2926 | |
| 2927 /* | |
| 2928 * FUNCTION: PKIX_PL_Cert_GetValidityNotAfter (see comments in pkix_pl_pki.h) | |
| 2929 */ | |
| 2930 PKIX_Error * | |
| 2931 PKIX_PL_Cert_GetValidityNotAfter( | |
| 2932 PKIX_PL_Cert *cert, | |
| 2933 PKIX_PL_Date **pDate, | |
| 2934 void *plContext) | |
| 2935 { | |
| 2936 PRTime prtime; | |
| 2937 SECStatus rv = SECFailure; | |
| 2938 | |
| 2939 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetValidityNotAfter"); | |
| 2940 PKIX_NULLCHECK_TWO(cert, pDate); | |
| 2941 | |
| 2942 PKIX_DATE_DEBUG("\t\tCalling DER_DecodeTimeChoice).\n"); | |
| 2943 rv = DER_DecodeTimeChoice(&prtime, &(cert->nssCert->validity.notAfter)); | |
| 2944 if (rv != SECSuccess){ | |
| 2945 PKIX_ERROR(PKIX_DERDECODETIMECHOICEFAILED); | |
| 2946 } | |
| 2947 | |
| 2948 PKIX_CHECK(pkix_pl_Date_CreateFromPRTime | |
| 2949 (prtime, pDate, plContext), | |
| 2950 PKIX_DATECREATEFROMPRTIMEFAILED); | |
| 2951 | |
| 2952 cleanup: | |
| 2953 PKIX_RETURN(CERT); | |
| 2954 } | |
| 2955 | |
| 2956 /* | |
| 2957 * FUNCTION: PKIX_PL_Cert_VerifyCertAndKeyType (see comments in pkix_pl_pki.h) | |
| 2958 */ | |
| 2959 PKIX_Error * | |
| 2960 PKIX_PL_Cert_VerifyCertAndKeyType( | |
| 2961 PKIX_PL_Cert *cert, | |
| 2962 PKIX_Boolean isChainCert, | |
| 2963 void *plContext) | |
| 2964 { | |
| 2965 PKIX_PL_CertBasicConstraints *basicConstraints = NULL; | |
| 2966 SECCertificateUsage certificateUsage; | |
| 2967 SECCertUsage certUsage = 0; | |
| 2968 unsigned int requiredKeyUsage; | |
| 2969 unsigned int requiredCertType; | |
| 2970 unsigned int certType; | |
| 2971 SECStatus rv = SECSuccess; | |
| 2972 | |
| 2973 PKIX_ENTER(CERT, "PKIX_PL_Cert_VerifyCertType"); | |
| 2974 PKIX_NULLCHECK_TWO(cert, plContext); | |
| 2975 | |
| 2976 certificateUsage = ((PKIX_PL_NssContext*)plContext)->certificateUsage; | |
| 2977 | |
| 2978 /* ensure we obtained a single usage bit only */ | |
| 2979 PORT_Assert(!(certificateUsage & (certificateUsage - 1))); | |
| 2980 | |
| 2981 /* convert SECertificateUsage (bit mask) to SECCertUsage (enum) */ | |
| 2982 while (0 != (certificateUsage = certificateUsage >> 1)) { certUsage++; } | |
| 2983 | |
| 2984 /* check key usage and netscape cert type */ | |
| 2985 cert_GetCertType(cert->nssCert); | |
| 2986 certType = cert->nssCert->nsCertType; | |
| 2987 if (isChainCert || | |
| 2988 (certUsage != certUsageVerifyCA && certUsage != certUsageAnyCA)) { | |
| 2989 rv = CERT_KeyUsageAndTypeForCertUsage(certUsage, isChainCert, | |
| 2990 &requiredKeyUsage, | |
| 2991 &requiredCertType); | |
| 2992 if (rv == SECFailure) { | |
| 2993 PKIX_ERROR(PKIX_UNSUPPORTEDCERTUSAGE); | |
| 2994 } | |
| 2995 } else { | |
| 2996 /* use this key usage and cert type for certUsageAnyCA and | |
| 2997 * certUsageVerifyCA. */ | |
| 2998 requiredKeyUsage = KU_KEY_CERT_SIGN; | |
| 2999 requiredCertType = NS_CERT_TYPE_CA; | |
| 3000 } | |
| 3001 if (CERT_CheckKeyUsage(cert->nssCert, requiredKeyUsage) != SECSuccess) { | |
| 3002 PKIX_ERROR(PKIX_CERTCHECKKEYUSAGEFAILED); | |
| 3003 } | |
| 3004 if (!(certType & requiredCertType)) { | |
| 3005 PKIX_ERROR(PKIX_CERTCHECKCERTTYPEFAILED); | |
| 3006 } | |
| 3007 cleanup: | |
| 3008 PKIX_DECREF(basicConstraints); | |
| 3009 PKIX_RETURN(CERT); | |
| 3010 } | |
| 3011 | |
| 3012 /* | |
| 3013 * FUNCTION: PKIX_PL_Cert_VerifyKeyUsage (see comments in pkix_pl_pki.h) | |
| 3014 */ | |
| 3015 PKIX_Error * | |
| 3016 PKIX_PL_Cert_VerifyKeyUsage( | |
| 3017 PKIX_PL_Cert *cert, | |
| 3018 PKIX_UInt32 keyUsage, | |
| 3019 void *plContext) | |
| 3020 { | |
| 3021 CERTCertificate *nssCert = NULL; | |
| 3022 PKIX_UInt32 nssKeyUsage = 0; | |
| 3023 SECStatus status; | |
| 3024 | |
| 3025 PKIX_ENTER(CERT, "PKIX_PL_Cert_VerifyKeyUsage"); | |
| 3026 PKIX_NULLCHECK_TWO(cert, cert->nssCert); | |
| 3027 | |
| 3028 nssCert = cert->nssCert; | |
| 3029 | |
| 3030 /* if cert doesn't have keyUsage extension, all keyUsages are valid */ | |
| 3031 if (!nssCert->keyUsagePresent){ | |
| 3032 goto cleanup; | |
| 3033 } | |
| 3034 | |
| 3035 if (keyUsage & PKIX_DIGITAL_SIGNATURE){ | |
| 3036 nssKeyUsage = nssKeyUsage | KU_DIGITAL_SIGNATURE; | |
| 3037 } | |
| 3038 | |
| 3039 if (keyUsage & PKIX_NON_REPUDIATION){ | |
| 3040 nssKeyUsage = nssKeyUsage | KU_NON_REPUDIATION; | |
| 3041 } | |
| 3042 | |
| 3043 if (keyUsage & PKIX_KEY_ENCIPHERMENT){ | |
| 3044 nssKeyUsage = nssKeyUsage | KU_KEY_ENCIPHERMENT; | |
| 3045 } | |
| 3046 | |
| 3047 if (keyUsage & PKIX_DATA_ENCIPHERMENT){ | |
| 3048 nssKeyUsage = nssKeyUsage | KU_DATA_ENCIPHERMENT; | |
| 3049 } | |
| 3050 | |
| 3051 if (keyUsage & PKIX_KEY_AGREEMENT){ | |
| 3052 nssKeyUsage = nssKeyUsage | KU_KEY_AGREEMENT; | |
| 3053 } | |
| 3054 | |
| 3055 if (keyUsage & PKIX_KEY_CERT_SIGN){ | |
| 3056 nssKeyUsage = nssKeyUsage | KU_KEY_CERT_SIGN; | |
| 3057 } | |
| 3058 | |
| 3059 if (keyUsage & PKIX_CRL_SIGN){ | |
| 3060 nssKeyUsage = nssKeyUsage | KU_CRL_SIGN; | |
| 3061 } | |
| 3062 | |
| 3063 if (keyUsage & PKIX_ENCIPHER_ONLY){ | |
| 3064 nssKeyUsage = nssKeyUsage | 0x01; | |
| 3065 } | |
| 3066 | |
| 3067 if (keyUsage & PKIX_DECIPHER_ONLY){ | |
| 3068 /* XXX we should support this once it is fixed in NSS */ | |
| 3069 PKIX_ERROR(PKIX_DECIPHERONLYKEYUSAGENOTSUPPORTED); | |
| 3070 } | |
| 3071 | |
| 3072 status = CERT_CheckKeyUsage(nssCert, nssKeyUsage); | |
| 3073 if (status != SECSuccess) { | |
| 3074 PKIX_ERROR(PKIX_CERTCHECKKEYUSAGEFAILED); | |
| 3075 } | |
| 3076 | |
| 3077 cleanup: | |
| 3078 PKIX_RETURN(CERT); | |
| 3079 } | |
| 3080 | |
| 3081 /* | |
| 3082 * FUNCTION: PKIX_PL_Cert_GetNameConstraints | |
| 3083 * (see comments in pkix_pl_pki.h) | |
| 3084 */ | |
| 3085 PKIX_Error * | |
| 3086 PKIX_PL_Cert_GetNameConstraints( | |
| 3087 PKIX_PL_Cert *cert, | |
| 3088 PKIX_PL_CertNameConstraints **pNameConstraints, | |
| 3089 void *plContext) | |
| 3090 { | |
| 3091 PKIX_PL_CertNameConstraints *nameConstraints = NULL; | |
| 3092 | |
| 3093 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetNameConstraints"); | |
| 3094 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pNameConstraints); | |
| 3095 | |
| 3096 /* if we don't have a cached copy from before, we create one */ | |
| 3097 if (cert->nameConstraints == NULL && !cert->nameConstraintsAbsent) { | |
| 3098 | |
| 3099 PKIX_OBJECT_LOCK(cert); | |
| 3100 | |
| 3101 if (cert->nameConstraints == NULL && | |
| 3102 !cert->nameConstraintsAbsent) { | |
| 3103 | |
| 3104 PKIX_CHECK(pkix_pl_CertNameConstraints_Create | |
| 3105 (cert->nssCert, &nameConstraints, plContext), | |
| 3106 PKIX_CERTNAMECONSTRAINTSCREATEFAILED); | |
| 3107 | |
| 3108 if (nameConstraints == NULL) { | |
| 3109 cert->nameConstraintsAbsent = PKIX_TRUE; | |
| 3110 } | |
| 3111 | |
| 3112 cert->nameConstraints = nameConstraints; | |
| 3113 } | |
| 3114 | |
| 3115 PKIX_OBJECT_UNLOCK(cert); | |
| 3116 | |
| 3117 } | |
| 3118 | |
| 3119 PKIX_INCREF(cert->nameConstraints); | |
| 3120 | |
| 3121 *pNameConstraints = cert->nameConstraints; | |
| 3122 | |
| 3123 cleanup: | |
| 3124 PKIX_OBJECT_UNLOCK(lockedObject); | |
| 3125 PKIX_RETURN(CERT); | |
| 3126 } | |
| 3127 | |
| 3128 /* | |
| 3129 * FUNCTION: PKIX_PL_Cert_CheckNameConstraints | |
| 3130 * (see comments in pkix_pl_pki.h) | |
| 3131 */ | |
| 3132 PKIX_Error * | |
| 3133 PKIX_PL_Cert_CheckNameConstraints( | |
| 3134 PKIX_PL_Cert *cert, | |
| 3135 PKIX_PL_CertNameConstraints *nameConstraints, | |
| 3136 PKIX_Boolean treatCommonNameAsDNSName, | |
| 3137 void *plContext) | |
| 3138 { | |
| 3139 PKIX_Boolean checkPass = PKIX_TRUE; | |
| 3140 CERTGeneralName *nssSubjectNames = NULL; | |
| 3141 PLArenaPool *arena = NULL; | |
| 3142 | |
| 3143 PKIX_ENTER(CERT, "PKIX_PL_Cert_CheckNameConstraints"); | |
| 3144 PKIX_NULLCHECK_ONE(cert); | |
| 3145 | |
| 3146 if (nameConstraints != NULL) { | |
| 3147 | |
| 3148 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | |
| 3149 if (arena == NULL) { | |
| 3150 PKIX_ERROR(PKIX_OUTOFMEMORY); | |
| 3151 } | |
| 3152 | |
| 3153 /* This NSS call returns Subject Alt Names. If | |
| 3154 * treatCommonNameAsDNSName is true, it also returns the | |
| 3155 * Subject Common Name | |
| 3156 */ | |
| 3157 PKIX_CERT_DEBUG | |
| 3158 ("\t\tCalling CERT_GetConstrainedCertificateNames\n"); | |
| 3159 nssSubjectNames = CERT_GetConstrainedCertificateNames | |
| 3160 (cert->nssCert, arena, treatCommonNameAsDNSName); | |
| 3161 | |
| 3162 PKIX_CHECK(pkix_pl_CertNameConstraints_CheckNameSpaceNssNames | |
| 3163 (nssSubjectNames, | |
| 3164 nameConstraints, | |
| 3165 &checkPass, | |
| 3166 plContext), | |
| 3167 PKIX_CERTNAMECONSTRAINTSCHECKNAMESPACENSSNAMESFAILED); | |
| 3168 | |
| 3169 if (checkPass != PKIX_TRUE) { | |
| 3170 PKIX_ERROR(PKIX_CERTFAILEDNAMECONSTRAINTSCHECKING); | |
| 3171 } | |
| 3172 } | |
| 3173 | |
| 3174 cleanup: | |
| 3175 if (arena){ | |
| 3176 PORT_FreeArena(arena, PR_FALSE); | |
| 3177 } | |
| 3178 | |
| 3179 PKIX_RETURN(CERT); | |
| 3180 } | |
| 3181 | |
| 3182 /* | |
| 3183 * FUNCTION: PKIX_PL_Cert_MergeNameConstraints | |
| 3184 * (see comments in pkix_pl_pki.h) | |
| 3185 */ | |
| 3186 PKIX_Error * | |
| 3187 PKIX_PL_Cert_MergeNameConstraints( | |
| 3188 PKIX_PL_CertNameConstraints *firstNC, | |
| 3189 PKIX_PL_CertNameConstraints *secondNC, | |
| 3190 PKIX_PL_CertNameConstraints **pResultNC, | |
| 3191 void *plContext) | |
| 3192 { | |
| 3193 PKIX_PL_CertNameConstraints *mergedNC = NULL; | |
| 3194 | |
| 3195 PKIX_ENTER(CERT, "PKIX_PL_Cert_MergeNameConstraints"); | |
| 3196 PKIX_NULLCHECK_TWO(firstNC, pResultNC); | |
| 3197 | |
| 3198 if (secondNC == NULL) { | |
| 3199 | |
| 3200 PKIX_INCREF(firstNC); | |
| 3201 *pResultNC = firstNC; | |
| 3202 | |
| 3203 goto cleanup; | |
| 3204 } | |
| 3205 | |
| 3206 PKIX_CHECK(pkix_pl_CertNameConstraints_Merge | |
| 3207 (firstNC, secondNC, &mergedNC, plContext), | |
| 3208 PKIX_CERTNAMECONSTRAINTSMERGEFAILED); | |
| 3209 | |
| 3210 *pResultNC = mergedNC; | |
| 3211 | |
| 3212 cleanup: | |
| 3213 PKIX_RETURN(CERT); | |
| 3214 } | |
| 3215 | |
| 3216 /* | |
| 3217 * Find out the state of the NSS trust bits for the requested usage. | |
| 3218 * Returns SECFailure if the cert is explicitly distrusted. | |
| 3219 * Returns SECSuccess if the cert can be used to form a chain (normal case), | |
| 3220 * or it is explicitly trusted. The trusted bool is set to true if it is | |
| 3221 * explicitly trusted. | |
| 3222 */ | |
| 3223 static SECStatus | |
| 3224 pkix_pl_Cert_GetTrusted(void *plContext, | |
| 3225 PKIX_PL_Cert *cert, | |
| 3226 PKIX_Boolean *trusted, | |
| 3227 PKIX_Boolean isCA) | |
| 3228 { | |
| 3229 SECStatus rv; | |
| 3230 CERTCertificate *nssCert = NULL; | |
| 3231 SECCertUsage certUsage = 0; | |
| 3232 SECCertificateUsage certificateUsage; | |
| 3233 SECTrustType trustType; | |
| 3234 unsigned int trustFlags; | |
| 3235 unsigned int requiredFlags; | |
| 3236 CERTCertTrust trust; | |
| 3237 | |
| 3238 *trusted = PKIX_FALSE; | |
| 3239 | |
| 3240 /* no key usage information */ | |
| 3241 if (plContext == NULL) { | |
| 3242 return SECSuccess; | |
| 3243 } | |
| 3244 | |
| 3245 certificateUsage = ((PKIX_PL_NssContext*)plContext)->certificateUsage; | |
| 3246 | |
| 3247 /* ensure we obtained a single usage bit only */ | |
| 3248 PORT_Assert(!(certificateUsage & (certificateUsage - 1))); | |
| 3249 | |
| 3250 /* convert SECertificateUsage (bit mask) to SECCertUsage (enum) */ | |
| 3251 while (0 != (certificateUsage = certificateUsage >> 1)) { certUsage++; } | |
| 3252 | |
| 3253 nssCert = cert->nssCert; | |
| 3254 | |
| 3255 if (!isCA) { | |
| 3256 PRBool prTrusted; | |
| 3257 unsigned int failedFlags; | |
| 3258 rv = cert_CheckLeafTrust(nssCert, certUsage, | |
| 3259 &failedFlags, &prTrusted); | |
| 3260 *trusted = (PKIX_Boolean) prTrusted; | |
| 3261 return rv; | |
| 3262 } | |
| 3263 rv = CERT_TrustFlagsForCACertUsage(certUsage, &requiredFlags, | |
| 3264 &trustType); | |
| 3265 if (rv != SECSuccess) { | |
| 3266 return SECSuccess; | |
| 3267 } | |
| 3268 | |
| 3269 rv = CERT_GetCertTrust(nssCert, &trust); | |
| 3270 if (rv != SECSuccess) { | |
| 3271 return SECSuccess; | |
| 3272 } | |
| 3273 trustFlags = SEC_GET_TRUST_FLAGS(&trust, trustType); | |
| 3274 /* normally trustTypeNone usages accept any of the given trust bits | |
| 3275 * being on as acceptable. If any are distrusted (and none are trusted), | |
| 3276 * then we will also distrust the cert */ | |
| 3277 if ((trustFlags == 0) && (trustType == trustTypeNone)) { | |
| 3278 trustFlags = trust.sslFlags | trust.emailFlags | | |
| 3279 trust.objectSigningFlags; | |
| 3280 } | |
| 3281 if ((trustFlags & requiredFlags) == requiredFlags) { | |
| 3282 *trusted = PKIX_TRUE; | |
| 3283 return SECSuccess; | |
| 3284 } | |
| 3285 if ((trustFlags & CERTDB_TERMINAL_RECORD) && | |
| 3286 ((trustFlags & (CERTDB_VALID_CA|CERTDB_TRUSTED)) == 0)) { | |
| 3287 return SECFailure; | |
| 3288 } | |
| 3289 return SECSuccess; | |
| 3290 } | |
| 3291 | |
| 3292 /* | |
| 3293 * FUNCTION: PKIX_PL_Cert_IsCertTrusted | |
| 3294 * (see comments in pkix_pl_pki.h) | |
| 3295 */ | |
| 3296 PKIX_Error * | |
| 3297 PKIX_PL_Cert_IsCertTrusted( | |
| 3298 PKIX_PL_Cert *cert, | |
| 3299 PKIX_PL_TrustAnchorMode trustAnchorMode, | |
| 3300 PKIX_Boolean *pTrusted, | |
| 3301 void *plContext) | |
| 3302 { | |
| 3303 PKIX_CertStore_CheckTrustCallback trustCallback = NULL; | |
| 3304 PKIX_Boolean trusted = PKIX_FALSE; | |
| 3305 SECStatus rv = SECFailure; | |
| 3306 | |
| 3307 PKIX_ENTER(CERT, "PKIX_PL_Cert_IsCertTrusted"); | |
| 3308 PKIX_NULLCHECK_TWO(cert, pTrusted); | |
| 3309 | |
| 3310 /* Call GetTrusted first to see if we are going to distrust the | |
| 3311 * certificate */ | |
| 3312 rv = pkix_pl_Cert_GetTrusted(plContext, cert, &trusted, PKIX_TRUE); | |
| 3313 if (rv != SECSuccess) { | |
| 3314 /* Failure means the cert is explicitly distrusted, | |
| 3315 * let the next level know not to use it. */ | |
| 3316 *pTrusted = PKIX_FALSE; | |
| 3317 PKIX_ERROR(PKIX_CERTISCERTTRUSTEDFAILED); | |
| 3318 } | |
| 3319 | |
| 3320 if (trustAnchorMode == PKIX_PL_TrustAnchorMode_Exclusive || | |
| 3321 (trustAnchorMode == PKIX_PL_TrustAnchorMode_Additive && | |
| 3322 cert->isUserTrustAnchor)) { | |
| 3323 /* Use the trust anchor's |trusted| value */ | |
| 3324 *pTrusted = cert->isUserTrustAnchor; | |
| 3325 goto cleanup; | |
| 3326 } | |
| 3327 | |
| 3328 /* no key usage information or store is not trusted */ | |
| 3329 if (plContext == NULL || cert->store == NULL) { | |
| 3330 *pTrusted = PKIX_FALSE; | |
| 3331 goto cleanup; | |
| 3332 } | |
| 3333 | |
| 3334 PKIX_CHECK(PKIX_CertStore_GetTrustCallback | |
| 3335 (cert->store, &trustCallback, plContext), | |
| 3336 PKIX_CERTSTOREGETTRUSTCALLBACKFAILED); | |
| 3337 | |
| 3338 PKIX_CHECK_ONLY_FATAL(trustCallback | |
| 3339 (cert->store, cert, &trusted, plContext), | |
| 3340 PKIX_CHECKTRUSTCALLBACKFAILED); | |
| 3341 | |
| 3342 /* allow trust store to override if we can trust the trust | |
| 3343 * bits */ | |
| 3344 if (PKIX_ERROR_RECEIVED || (trusted == PKIX_FALSE)) { | |
| 3345 *pTrusted = PKIX_FALSE; | |
| 3346 goto cleanup; | |
| 3347 } | |
| 3348 | |
| 3349 *pTrusted = trusted; | |
| 3350 | |
| 3351 cleanup: | |
| 3352 PKIX_RETURN(CERT); | |
| 3353 } | |
| 3354 | |
| 3355 /* | |
| 3356 * FUNCTION: PKIX_PL_Cert_IsLeafCertTrusted | |
| 3357 * (see comments in pkix_pl_pki.h) | |
| 3358 */ | |
| 3359 PKIX_Error * | |
| 3360 PKIX_PL_Cert_IsLeafCertTrusted( | |
| 3361 PKIX_PL_Cert *cert, | |
| 3362 PKIX_Boolean *pTrusted, | |
| 3363 void *plContext) | |
| 3364 { | |
| 3365 SECStatus rv; | |
| 3366 | |
| 3367 PKIX_ENTER(CERT, "PKIX_PL_Cert_IsLeafCertTrusted"); | |
| 3368 PKIX_NULLCHECK_TWO(cert, pTrusted); | |
| 3369 | |
| 3370 *pTrusted = PKIX_FALSE; | |
| 3371 | |
| 3372 rv = pkix_pl_Cert_GetTrusted(plContext, cert, pTrusted, PKIX_FALSE); | |
| 3373 if (rv != SECSuccess) { | |
| 3374 /* Failure means the cert is explicitly distrusted, | |
| 3375 * let the next level know not to use it. */ | |
| 3376 *pTrusted = PKIX_FALSE; | |
| 3377 PKIX_ERROR(PKIX_CERTISCERTTRUSTEDFAILED); | |
| 3378 } | |
| 3379 | |
| 3380 cleanup: | |
| 3381 PKIX_RETURN(CERT); | |
| 3382 } | |
| 3383 | |
| 3384 /* FUNCTION: PKIX_PL_Cert_SetAsTrustAnchor */ | |
| 3385 PKIX_Error* | |
| 3386 PKIX_PL_Cert_SetAsTrustAnchor(PKIX_PL_Cert *cert, | |
| 3387 void *plContext) | |
| 3388 { | |
| 3389 PKIX_ENTER(CERT, "PKIX_PL_Cert_SetAsTrustAnchor"); | |
| 3390 PKIX_NULLCHECK_ONE(cert); | |
| 3391 | |
| 3392 cert->isUserTrustAnchor = PKIX_TRUE; | |
| 3393 | |
| 3394 PKIX_RETURN(CERT); | |
| 3395 } | |
| 3396 | |
| 3397 /* | |
| 3398 * FUNCTION: PKIX_PL_Cert_GetCacheFlag (see comments in pkix_pl_pki.h) | |
| 3399 */ | |
| 3400 PKIX_Error * | |
| 3401 PKIX_PL_Cert_GetCacheFlag( | |
| 3402 PKIX_PL_Cert *cert, | |
| 3403 PKIX_Boolean *pCacheFlag, | |
| 3404 void *plContext) | |
| 3405 { | |
| 3406 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetCacheFlag"); | |
| 3407 PKIX_NULLCHECK_TWO(cert, pCacheFlag); | |
| 3408 | |
| 3409 *pCacheFlag = cert->cacheFlag; | |
| 3410 | |
| 3411 PKIX_RETURN(CERT); | |
| 3412 } | |
| 3413 | |
| 3414 /* | |
| 3415 * FUNCTION: PKIX_PL_Cert_SetCacheFlag (see comments in pkix_pl_pki.h) | |
| 3416 */ | |
| 3417 PKIX_Error * | |
| 3418 PKIX_PL_Cert_SetCacheFlag( | |
| 3419 PKIX_PL_Cert *cert, | |
| 3420 PKIX_Boolean cacheFlag, | |
| 3421 void *plContext) | |
| 3422 { | |
| 3423 PKIX_ENTER(CERT, "PKIX_PL_Cert_SetCacheFlag"); | |
| 3424 PKIX_NULLCHECK_ONE(cert); | |
| 3425 | |
| 3426 cert->cacheFlag = cacheFlag; | |
| 3427 | |
| 3428 PKIX_RETURN(CERT); | |
| 3429 } | |
| 3430 | |
| 3431 /* | |
| 3432 * FUNCTION: PKIX_PL_Cert_GetTrustCertStore (see comments in pkix_pl_pki.h) | |
| 3433 */ | |
| 3434 PKIX_Error * | |
| 3435 PKIX_PL_Cert_GetTrustCertStore( | |
| 3436 PKIX_PL_Cert *cert, | |
| 3437 PKIX_CertStore **pTrustCertStore, | |
| 3438 void *plContext) | |
| 3439 { | |
| 3440 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetTrustCertStore"); | |
| 3441 PKIX_NULLCHECK_TWO(cert, pTrustCertStore); | |
| 3442 | |
| 3443 PKIX_INCREF(cert->store); | |
| 3444 *pTrustCertStore = cert->store; | |
| 3445 | |
| 3446 cleanup: | |
| 3447 PKIX_RETURN(CERT); | |
| 3448 } | |
| 3449 | |
| 3450 /* | |
| 3451 * FUNCTION: PKIX_PL_Cert_SetTrustCertStore (see comments in pkix_pl_pki.h) | |
| 3452 */ | |
| 3453 PKIX_Error * | |
| 3454 PKIX_PL_Cert_SetTrustCertStore( | |
| 3455 PKIX_PL_Cert *cert, | |
| 3456 PKIX_CertStore *trustCertStore, | |
| 3457 void *plContext) | |
| 3458 { | |
| 3459 PKIX_ENTER(CERT, "PKIX_PL_Cert_SetTrustCertStore"); | |
| 3460 PKIX_NULLCHECK_TWO(cert, trustCertStore); | |
| 3461 | |
| 3462 PKIX_INCREF(trustCertStore); | |
| 3463 cert->store = trustCertStore; | |
| 3464 | |
| 3465 cleanup: | |
| 3466 PKIX_RETURN(CERT); | |
| 3467 } | |
| 3468 | |
| 3469 /* | |
| 3470 * FUNCTION: PKIX_PL_Cert_GetAuthorityInfoAccess | |
| 3471 * (see comments in pkix_pl_pki.h) | |
| 3472 */ | |
| 3473 PKIX_Error * | |
| 3474 PKIX_PL_Cert_GetAuthorityInfoAccess( | |
| 3475 PKIX_PL_Cert *cert, | |
| 3476 PKIX_List **pAiaList, /* of PKIX_PL_InfoAccess */ | |
| 3477 void *plContext) | |
| 3478 { | |
| 3479 PKIX_List *aiaList = NULL; /* of PKIX_PL_InfoAccess */ | |
| 3480 SECItem *encodedAIA = NULL; | |
| 3481 CERTAuthInfoAccess **aia = NULL; | |
| 3482 PLArenaPool *arena = NULL; | |
| 3483 SECStatus rv; | |
| 3484 | |
| 3485 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetAuthorityInfoAccess"); | |
| 3486 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pAiaList); | |
| 3487 | |
| 3488 /* if we don't have a cached copy from before, we create one */ | |
| 3489 if (cert->authorityInfoAccess == NULL) { | |
| 3490 | |
| 3491 PKIX_OBJECT_LOCK(cert); | |
| 3492 | |
| 3493 if (cert->authorityInfoAccess == NULL) { | |
| 3494 | |
| 3495 PKIX_PL_NSSCALLRV(CERT, encodedAIA, SECITEM_AllocItem, | |
| 3496 (NULL, NULL, 0)); | |
| 3497 | |
| 3498 if (encodedAIA == NULL) { | |
| 3499 PKIX_ERROR(PKIX_OUTOFMEMORY); | |
| 3500 } | |
| 3501 | |
| 3502 PKIX_PL_NSSCALLRV(CERT, rv, CERT_FindCertExtension, | |
| 3503 (cert->nssCert, | |
| 3504 SEC_OID_X509_AUTH_INFO_ACCESS, | |
| 3505 encodedAIA)); | |
| 3506 | |
| 3507 if (rv == SECFailure) { | |
| 3508 goto cleanup; | |
| 3509 } | |
| 3510 | |
| 3511 PKIX_PL_NSSCALLRV(CERT, arena, PORT_NewArena, | |
| 3512 (DER_DEFAULT_CHUNKSIZE)); | |
| 3513 | |
| 3514 if (arena == NULL) { | |
| 3515 PKIX_ERROR(PKIX_OUTOFMEMORY); | |
| 3516 } | |
| 3517 | |
| 3518 PKIX_PL_NSSCALLRV | |
| 3519 (CERT, aia, CERT_DecodeAuthInfoAccessExtension, | |
| 3520 (arena, encodedAIA)); | |
| 3521 | |
| 3522 PKIX_CHECK(pkix_pl_InfoAccess_CreateList | |
| 3523 (aia, &aiaList, plContext), | |
| 3524 PKIX_INFOACCESSCREATELISTFAILED); | |
| 3525 | |
| 3526 cert->authorityInfoAccess = aiaList; | |
| 3527 } | |
| 3528 | |
| 3529 PKIX_OBJECT_UNLOCK(cert); | |
| 3530 } | |
| 3531 | |
| 3532 PKIX_INCREF(cert->authorityInfoAccess); | |
| 3533 | |
| 3534 *pAiaList = cert->authorityInfoAccess; | |
| 3535 | |
| 3536 cleanup: | |
| 3537 PKIX_OBJECT_UNLOCK(lockedObject); | |
| 3538 if (arena != NULL) { | |
| 3539 PORT_FreeArena(arena, PR_FALSE); | |
| 3540 } | |
| 3541 | |
| 3542 if (encodedAIA != NULL) { | |
| 3543 SECITEM_FreeItem(encodedAIA, PR_TRUE); | |
| 3544 } | |
| 3545 | |
| 3546 PKIX_RETURN(CERT); | |
| 3547 } | |
| 3548 | |
| 3549 /* XXX Following defines belongs to NSS */ | |
| 3550 static const unsigned char siaOIDString[] = {0x2b, 0x06, 0x01, 0x05, 0x05, | |
| 3551 0x07, 0x01, 0x0b}; | |
| 3552 #define OI(x) { siDEROID, (unsigned char *)x, sizeof x } | |
| 3553 | |
| 3554 /* | |
| 3555 * FUNCTION: PKIX_PL_Cert_GetSubjectInfoAccess | |
| 3556 * (see comments in pkix_pl_pki.h) | |
| 3557 */ | |
| 3558 PKIX_Error * | |
| 3559 PKIX_PL_Cert_GetSubjectInfoAccess( | |
| 3560 PKIX_PL_Cert *cert, | |
| 3561 PKIX_List **pSiaList, /* of PKIX_PL_InfoAccess */ | |
| 3562 void *plContext) | |
| 3563 { | |
| 3564 PKIX_List *siaList; /* of PKIX_PL_InfoAccess */ | |
| 3565 SECItem siaOID = OI(siaOIDString); | |
| 3566 SECItem *encodedSubjInfoAccess = NULL; | |
| 3567 CERTAuthInfoAccess **subjInfoAccess = NULL; | |
| 3568 PLArenaPool *arena = NULL; | |
| 3569 SECStatus rv; | |
| 3570 | |
| 3571 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubjectInfoAccess"); | |
| 3572 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSiaList); | |
| 3573 | |
| 3574 /* XXX | |
| 3575 * Codes to deal with SubjectInfoAccess OID should be moved to | |
| 3576 * NSS soon. I implemented them here so we don't touch NSS | |
| 3577 * source tree, from JP's suggestion. | |
| 3578 */ | |
| 3579 | |
| 3580 /* if we don't have a cached copy from before, we create one */ | |
| 3581 if (cert->subjectInfoAccess == NULL) { | |
| 3582 | |
| 3583 PKIX_OBJECT_LOCK(cert); | |
| 3584 | |
| 3585 if (cert->subjectInfoAccess == NULL) { | |
| 3586 | |
| 3587 encodedSubjInfoAccess = SECITEM_AllocItem(NULL, NULL, 0); | |
| 3588 if (encodedSubjInfoAccess == NULL) { | |
| 3589 PKIX_ERROR(PKIX_OUTOFMEMORY); | |
| 3590 } | |
| 3591 | |
| 3592 PKIX_CERT_DEBUG | |
| 3593 ("\t\tCalling CERT_FindCertExtensionByOID).\n"); | |
| 3594 rv = CERT_FindCertExtensionByOID | |
| 3595 (cert->nssCert, &siaOID, encodedSubjInfoAccess); | |
| 3596 | |
| 3597 if (rv == SECFailure) { | |
| 3598 goto cleanup; | |
| 3599 } | |
| 3600 | |
| 3601 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | |
| 3602 if (arena == NULL) { | |
| 3603 PKIX_ERROR(PKIX_OUTOFMEMORY); | |
| 3604 } | |
| 3605 | |
| 3606 /* XXX | |
| 3607 * Decode Subject Information Access - | |
| 3608 * since its type is the same as Authority Information | |
| 3609 * Access, reuse the call. NSS- change name to avoid | |
| 3610 * confusion. | |
| 3611 */ | |
| 3612 PKIX_CERT_DEBUG | |
| 3613 ("\t\tCalling CERT_DecodeAuthInfoAccessExtension).\n"); | |
| 3614 subjInfoAccess = CERT_DecodeAuthInfoAccessExtension | |
| 3615 (arena, encodedSubjInfoAccess); | |
| 3616 | |
| 3617 PKIX_CHECK(pkix_pl_InfoAccess_CreateList | |
| 3618 (subjInfoAccess, &siaList, plContext), | |
| 3619 PKIX_INFOACCESSCREATELISTFAILED); | |
| 3620 | |
| 3621 cert->subjectInfoAccess = siaList; | |
| 3622 | |
| 3623 } | |
| 3624 | |
| 3625 PKIX_OBJECT_UNLOCK(cert); | |
| 3626 } | |
| 3627 | |
| 3628 PKIX_INCREF(cert->subjectInfoAccess); | |
| 3629 *pSiaList = cert->subjectInfoAccess; | |
| 3630 | |
| 3631 cleanup: | |
| 3632 PKIX_OBJECT_UNLOCK(lockedObject); | |
| 3633 if (arena != NULL) { | |
| 3634 PORT_FreeArena(arena, PR_FALSE); | |
| 3635 } | |
| 3636 | |
| 3637 if (encodedSubjInfoAccess != NULL) { | |
| 3638 SECITEM_FreeItem(encodedSubjInfoAccess, PR_TRUE); | |
| 3639 } | |
| 3640 PKIX_RETURN(CERT); | |
| 3641 } | |
| 3642 | |
| 3643 /* | |
| 3644 * FUNCTION: PKIX_PL_Cert_GetCrlDp | |
| 3645 * (see comments in pkix_pl_pki.h) | |
| 3646 */ | |
| 3647 PKIX_Error * | |
| 3648 PKIX_PL_Cert_GetCrlDp( | |
| 3649 PKIX_PL_Cert *cert, | |
| 3650 PKIX_List **pDpList, | |
| 3651 void *plContext) | |
| 3652 { | |
| 3653 PKIX_UInt32 dpIndex = 0; | |
| 3654 pkix_pl_CrlDp *dp = NULL; | |
| 3655 CERTCrlDistributionPoints *dpoints = NULL; | |
| 3656 | |
| 3657 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetCrlDp"); | |
| 3658 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pDpList); | |
| 3659 | |
| 3660 /* if we don't have a cached copy from before, we create one */ | |
| 3661 if (cert->crldpList == NULL) { | |
| 3662 PKIX_OBJECT_LOCK(cert); | |
| 3663 if (cert->crldpList != NULL) { | |
| 3664 goto cleanup; | |
| 3665 } | |
| 3666 PKIX_CHECK(PKIX_List_Create(&cert->crldpList, plContext), | |
| 3667 PKIX_LISTCREATEFAILED); | |
| 3668 dpoints = CERT_FindCRLDistributionPoints(cert->nssCert); | |
| 3669 if (!dpoints || !dpoints->distPoints) { | |
| 3670 goto cleanup; | |
| 3671 } | |
| 3672 for (;dpoints->distPoints[dpIndex];dpIndex++) { | |
| 3673 PKIX_CHECK( | |
| 3674 pkix_pl_CrlDp_Create(dpoints->distPoints[dpIndex], | |
| 3675 &cert->nssCert->issuer, | |
| 3676 &dp, plContext), | |
| 3677 PKIX_CRLDPCREATEFAILED); | |
| 3678 /* Create crldp list in reverse order in attempt to get | |
| 3679 * to the whole crl first. */ | |
| 3680 PKIX_CHECK( | |
| 3681 PKIX_List_InsertItem(cert->crldpList, 0, | |
| 3682 (PKIX_PL_Object*)dp, | |
| 3683 plContext), | |
| 3684 PKIX_LISTAPPENDITEMFAILED); | |
| 3685 PKIX_DECREF(dp); | |
| 3686 } | |
| 3687 } | |
| 3688 cleanup: | |
| 3689 PKIX_INCREF(cert->crldpList); | |
| 3690 *pDpList = cert->crldpList; | |
| 3691 | |
| 3692 PKIX_OBJECT_UNLOCK(lockedObject); | |
| 3693 PKIX_DECREF(dp); | |
| 3694 | |
| 3695 PKIX_RETURN(CERT); | |
| 3696 } | |
| 3697 | |
| 3698 /* | |
| 3699 * FUNCTION: PKIX_PL_Cert_GetCERTCertificate | |
| 3700 * (see comments in pkix_pl_pki.h) | |
| 3701 */ | |
| 3702 PKIX_Error * | |
| 3703 PKIX_PL_Cert_GetCERTCertificate( | |
| 3704 PKIX_PL_Cert *cert, | |
| 3705 CERTCertificate **pnssCert, | |
| 3706 void *plContext) | |
| 3707 { | |
| 3708 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetNssCert"); | |
| 3709 PKIX_NULLCHECK_TWO(cert, pnssCert); | |
| 3710 | |
| 3711 *pnssCert = CERT_DupCertificate(cert->nssCert); | |
| 3712 | |
| 3713 PKIX_RETURN(CERT); | |
| 3714 } | |
| OLD | NEW |