certvfy.c (77253B)
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 #include "nspr.h" 5 #include "secerr.h" 6 #include "secport.h" 7 #include "seccomon.h" 8 #include "secoid.h" 9 #include "genname.h" 10 #include "keyhi.h" 11 #include "cert.h" 12 #include "certdb.h" 13 #include "certi.h" 14 #include "cryptohi.h" 15 16 #ifndef NSS_DISABLE_LIBPKIX 17 #include "pkix.h" 18 #include "pkix_pl_cert.h" 19 #else 20 #include "nss.h" 21 #endif /* NSS_DISABLE_LIBPKIX */ 22 23 #include "nsspki.h" 24 #include "pkitm.h" 25 #include "pkim.h" 26 #include "pki3hack.h" 27 #include "base.h" 28 #include "keyi.h" 29 30 /* 31 * Check the validity times of a certificate 32 */ 33 SECStatus 34 CERT_CertTimesValid(CERTCertificate *c) 35 { 36 SECCertTimeValidity valid = CERT_CheckCertValidTimes(c, PR_Now(), PR_TRUE); 37 return (valid == secCertTimeValid) ? SECSuccess : SECFailure; 38 } 39 40 static SECStatus 41 checkKeyParams(const SECAlgorithmID *sigAlgorithm, const SECKEYPublicKey *key) 42 { 43 SECStatus rv; 44 SECOidTag sigAlg; 45 SECOidTag curve; 46 PRUint32 policyFlags = 0; 47 PRInt32 minLen, len, optFlags; 48 49 sigAlg = SECOID_GetAlgorithmTag(sigAlgorithm); 50 51 switch (sigAlg) { 52 case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE: 53 case SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE: 54 case SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE: 55 case SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE: 56 case SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE: 57 if (key->keyType != ecKey) { 58 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); 59 return SECFailure; 60 } 61 62 curve = SECKEY_GetECCOid(&key->u.ec.DEREncodedParams); 63 if (curve != 0) { 64 if (NSS_GetAlgorithmPolicy(curve, &policyFlags) == SECFailure || 65 !(policyFlags & NSS_USE_ALG_IN_CERT_SIGNATURE)) { 66 PORT_SetError(SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED); 67 return SECFailure; 68 } 69 return SECSuccess; 70 } 71 PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); 72 return SECFailure; 73 74 case SEC_OID_PKCS1_RSA_PSS_SIGNATURE: { 75 PORTCheapArenaPool tmpArena; 76 SECOidTag hashAlg; 77 SECOidTag maskHashAlg; 78 79 PORT_InitCheapArena(&tmpArena, DER_DEFAULT_CHUNKSIZE); 80 rv = sec_DecodeRSAPSSParams(&tmpArena.arena, 81 &sigAlgorithm->parameters, 82 &hashAlg, &maskHashAlg, NULL); 83 PORT_DestroyCheapArena(&tmpArena); 84 if (rv != SECSuccess) { 85 return SECFailure; 86 } 87 88 if (NSS_GetAlgorithmPolicy(hashAlg, &policyFlags) == SECSuccess && 89 !(policyFlags & NSS_USE_ALG_IN_CERT_SIGNATURE)) { 90 PORT_SetError(SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED); 91 return SECFailure; 92 } 93 if (NSS_GetAlgorithmPolicy(maskHashAlg, &policyFlags) == SECSuccess && 94 !(policyFlags & NSS_USE_ALG_IN_CERT_SIGNATURE)) { 95 PORT_SetError(SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED); 96 return SECFailure; 97 } 98 } 99 /* fall through to RSA key checking */ 100 case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION: 101 case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION: 102 case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION: 103 case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION: 104 case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION: 105 case SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE: 106 case SEC_OID_ISO_SHA1_WITH_RSA_SIGNATURE: 107 if (key->keyType != rsaKey && key->keyType != rsaPssKey) { 108 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); 109 return SECFailure; 110 } 111 112 if (NSS_OptionGet(NSS_KEY_SIZE_POLICY_FLAGS, &optFlags) == SECFailure) { 113 return SECSuccess; 114 } 115 if ((optFlags & NSS_KEY_SIZE_POLICY_VERIFY_FLAG) == 0) { 116 return SECSuccess; 117 } 118 119 len = 8 * key->u.rsa.modulus.len; 120 121 rv = NSS_OptionGet(NSS_RSA_MIN_KEY_SIZE, &minLen); 122 if (rv != SECSuccess) { 123 return SECFailure; 124 } 125 126 if (len < minLen) { 127 return SECFailure; 128 } 129 130 return SECSuccess; 131 case SEC_OID_ANSIX9_DSA_SIGNATURE: 132 case SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST: 133 case SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST: 134 case SEC_OID_SDN702_DSA_SIGNATURE: 135 case SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA224_DIGEST: 136 case SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA256_DIGEST: 137 if (key->keyType != dsaKey) { 138 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); 139 return SECFailure; 140 } 141 if (NSS_OptionGet(NSS_KEY_SIZE_POLICY_FLAGS, &optFlags) == SECFailure) { 142 return SECSuccess; 143 } 144 if ((optFlags & NSS_KEY_SIZE_POLICY_VERIFY_FLAG) == 0) { 145 return SECSuccess; 146 } 147 148 len = 8 * key->u.dsa.params.prime.len; 149 150 rv = NSS_OptionGet(NSS_DSA_MIN_KEY_SIZE, &minLen); 151 if (rv != SECSuccess) { 152 return SECFailure; 153 } 154 155 if (len < minLen) { 156 return SECFailure; 157 } 158 159 return SECSuccess; 160 case SEC_OID_ML_DSA_44: 161 case SEC_OID_ML_DSA_65: 162 case SEC_OID_ML_DSA_87: 163 if (key->keyType != mldsaKey) { 164 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); 165 return SECFailure; 166 } 167 if (key->u.mldsa.paramSet != sigAlg) { 168 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); 169 return SECFailure; 170 } 171 default: 172 return SECSuccess; 173 } 174 } 175 176 /* 177 * verify the signature of a signed data object with the given DER publickey 178 */ 179 SECStatus 180 CERT_VerifySignedDataWithPublicKey(const CERTSignedData *sd, 181 SECKEYPublicKey *pubKey, 182 void *wincx) 183 { 184 SECStatus rv; 185 SECItem sig; 186 SECOidTag sigAlg; 187 SECOidTag encAlg; 188 SECOidTag hashAlg; 189 CK_MECHANISM_TYPE mech; 190 PRUint32 policyFlags; 191 192 if (!pubKey || !sd) { 193 PORT_SetError(PR_INVALID_ARGUMENT_ERROR); 194 return SECFailure; 195 } 196 197 /* Can we use this algorithm for signature verification? */ 198 sigAlg = SECOID_GetAlgorithmTag(&sd->signatureAlgorithm); 199 rv = sec_DecodeSigAlg(pubKey, sigAlg, 200 &sd->signatureAlgorithm.parameters, 201 &encAlg, &hashAlg, &mech, NULL); 202 if (rv != SECSuccess) { 203 return SECFailure; /* error is set */ 204 } 205 rv = NSS_GetAlgorithmPolicy(encAlg, &policyFlags); 206 if (rv == SECSuccess && 207 !(policyFlags & NSS_USE_ALG_IN_CERT_SIGNATURE)) { 208 PORT_SetError(SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED); 209 return SECFailure; 210 } 211 rv = NSS_GetAlgorithmPolicy(hashAlg, &policyFlags); 212 if (rv == SECSuccess && 213 !(policyFlags & NSS_USE_ALG_IN_CERT_SIGNATURE)) { 214 PORT_SetError(SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED); 215 return SECFailure; 216 } 217 rv = checkKeyParams(&sd->signatureAlgorithm, pubKey); 218 if (rv != SECSuccess) { 219 PORT_SetError(SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED); 220 return SECFailure; 221 } 222 223 /* check the signature */ 224 sig = sd->signature; 225 /* convert sig->len from bit counts to byte count. */ 226 DER_ConvertBitString(&sig); 227 228 rv = VFY_VerifyDataWithAlgorithmID(sd->data.data, sd->data.len, pubKey, 229 &sig, &sd->signatureAlgorithm, 230 &hashAlg, wincx); 231 if (rv != SECSuccess) { 232 return SECFailure; /* error is set */ 233 } 234 235 /* for some algorithms, hash algorithm is only known after verification */ 236 rv = NSS_GetAlgorithmPolicy(hashAlg, &policyFlags); 237 if (rv == SECSuccess && 238 !(policyFlags & NSS_USE_ALG_IN_CERT_SIGNATURE)) { 239 PORT_SetError(SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED); 240 return SECFailure; 241 } 242 return SECSuccess; 243 } 244 245 /* 246 * verify the signature of a signed data object with the given DER publickey 247 */ 248 SECStatus 249 CERT_VerifySignedDataWithPublicKeyInfo(CERTSignedData *sd, 250 CERTSubjectPublicKeyInfo *pubKeyInfo, 251 void *wincx) 252 { 253 SECKEYPublicKey *pubKey; 254 SECStatus rv = SECFailure; 255 256 /* get cert's public key */ 257 pubKey = SECKEY_ExtractPublicKey(pubKeyInfo); 258 if (pubKey) { 259 rv = CERT_VerifySignedDataWithPublicKey(sd, pubKey, wincx); 260 SECKEY_DestroyPublicKey(pubKey); 261 } 262 return rv; 263 } 264 265 /* 266 * verify the signature of a signed data object with the given certificate 267 */ 268 SECStatus 269 CERT_VerifySignedData(CERTSignedData *sd, CERTCertificate *cert, 270 PRTime t, void *wincx) 271 { 272 SECKEYPublicKey *pubKey = 0; 273 SECStatus rv = SECFailure; 274 SECCertTimeValidity validity; 275 276 /* check the certificate's validity */ 277 validity = CERT_CheckCertValidTimes(cert, t, PR_FALSE); 278 if (validity != secCertTimeValid) { 279 return rv; 280 } 281 282 /* get cert's public key */ 283 pubKey = CERT_ExtractPublicKey(cert); 284 if (pubKey) { 285 rv = CERT_VerifySignedDataWithPublicKey(sd, pubKey, wincx); 286 SECKEY_DestroyPublicKey(pubKey); 287 } 288 return rv; 289 } 290 291 SECStatus 292 SEC_CheckCRL(CERTCertDBHandle *handle, CERTCertificate *cert, 293 CERTCertificate *caCert, PRTime t, void *wincx) 294 { 295 return CERT_CheckCRL(cert, caCert, NULL, t, wincx); 296 } 297 298 /* 299 * Find the issuer of a cert. Use the authorityKeyID if it exists. 300 */ 301 CERTCertificate * 302 CERT_FindCertIssuer(CERTCertificate *cert, PRTime validTime, SECCertUsage usage) 303 { 304 NSSCertificate *me; 305 NSSTime *nssTime; 306 NSSTrustDomain *td; 307 NSSCryptoContext *cc; 308 NSSCertificate *chain[3]; 309 NSSUsage nssUsage; 310 PRStatus status; 311 312 me = STAN_GetNSSCertificate(cert); 313 if (!me) { 314 PORT_SetError(SEC_ERROR_NO_MEMORY); 315 return NULL; 316 } 317 nssTime = NSSTime_SetPRTime(NULL, validTime); 318 nssUsage.anyUsage = PR_FALSE; 319 nssUsage.nss3usage = usage; 320 nssUsage.nss3lookingForCA = PR_TRUE; 321 memset(chain, 0, 3 * sizeof(NSSCertificate *)); 322 td = STAN_GetDefaultTrustDomain(); 323 cc = STAN_GetDefaultCryptoContext(); 324 (void)NSSCertificate_BuildChain(me, nssTime, &nssUsage, NULL, 325 chain, 2, NULL, &status, td, cc); 326 nss_ZFreeIf(nssTime); 327 if (status == PR_SUCCESS) { 328 PORT_Assert(me == chain[0]); 329 /* if it's a root, the chain will only have one cert */ 330 if (!chain[1]) { 331 /* already has a reference from the call to BuildChain */ 332 return cert; 333 } 334 NSSCertificate_Destroy(chain[0]); /* the first cert in the chain */ 335 return STAN_GetCERTCertificate(chain[1]); /* return the 2nd */ 336 } 337 if (chain[0]) { 338 PORT_Assert(me == chain[0]); 339 NSSCertificate_Destroy(chain[0]); /* the first cert in the chain */ 340 } 341 PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER); 342 return NULL; 343 } 344 345 /* 346 * return required trust flags for various cert usages for CAs 347 */ 348 SECStatus 349 CERT_TrustFlagsForCACertUsage(SECCertUsage usage, 350 unsigned int *retFlags, 351 SECTrustType *retTrustType) 352 { 353 unsigned int requiredFlags; 354 SECTrustType trustType; 355 356 switch (usage) { 357 case certUsageSSLClient: 358 requiredFlags = CERTDB_TRUSTED_CLIENT_CA; 359 trustType = trustSSL; 360 break; 361 case certUsageSSLServer: 362 case certUsageSSLCA: 363 requiredFlags = CERTDB_TRUSTED_CA; 364 trustType = trustSSL; 365 break; 366 case certUsageIPsec: 367 requiredFlags = CERTDB_TRUSTED_CA; 368 trustType = trustSSL; 369 break; 370 case certUsageSSLServerWithStepUp: 371 requiredFlags = CERTDB_TRUSTED_CA | CERTDB_GOVT_APPROVED_CA; 372 trustType = trustSSL; 373 break; 374 case certUsageEmailSigner: 375 case certUsageEmailRecipient: 376 requiredFlags = CERTDB_TRUSTED_CA; 377 trustType = trustEmail; 378 break; 379 case certUsageObjectSigner: 380 requiredFlags = CERTDB_TRUSTED_CA; 381 trustType = trustObjectSigning; 382 break; 383 case certUsageVerifyCA: 384 case certUsageAnyCA: 385 case certUsageStatusResponder: 386 requiredFlags = CERTDB_TRUSTED_CA; 387 trustType = trustTypeNone; 388 break; 389 default: 390 PORT_Assert(0); 391 goto loser; 392 } 393 if (retFlags != NULL) { 394 *retFlags = requiredFlags; 395 } 396 if (retTrustType != NULL) { 397 *retTrustType = trustType; 398 } 399 400 return (SECSuccess); 401 loser: 402 return (SECFailure); 403 } 404 405 void 406 cert_AddToVerifyLog(CERTVerifyLog *log, CERTCertificate *cert, long error, 407 unsigned int depth, void *arg) 408 { 409 CERTVerifyLogNode *node, *tnode; 410 411 PORT_Assert(log != NULL); 412 413 node = (CERTVerifyLogNode *)PORT_ArenaAlloc(log->arena, 414 sizeof(CERTVerifyLogNode)); 415 if (node != NULL) { 416 node->cert = CERT_DupCertificate(cert); 417 node->error = error; 418 node->depth = depth; 419 node->arg = arg; 420 421 if (log->tail == NULL) { 422 /* empty list */ 423 log->head = log->tail = node; 424 node->prev = NULL; 425 node->next = NULL; 426 } else if (depth >= log->tail->depth) { 427 /* add to tail */ 428 node->prev = log->tail; 429 log->tail->next = node; 430 log->tail = node; 431 node->next = NULL; 432 } else if (depth < log->head->depth) { 433 /* add at head */ 434 node->prev = NULL; 435 node->next = log->head; 436 log->head->prev = node; 437 log->head = node; 438 } else { 439 /* add in middle */ 440 tnode = log->tail; 441 while (tnode != NULL) { 442 if (depth >= tnode->depth) { 443 /* insert after tnode */ 444 node->prev = tnode; 445 node->next = tnode->next; 446 tnode->next->prev = node; 447 tnode->next = node; 448 break; 449 } 450 451 tnode = tnode->prev; 452 } 453 } 454 455 log->count++; 456 } 457 return; 458 } 459 460 #define EXIT_IF_NOT_LOGGING(log) \ 461 if (log == NULL) { \ 462 goto loser; \ 463 } 464 465 #define LOG_ERROR_OR_EXIT(log, cert, depth, arg) \ 466 if (log != NULL) { \ 467 cert_AddToVerifyLog(log, cert, PORT_GetError(), depth, \ 468 (void *)(PRWord)arg); \ 469 } else { \ 470 goto loser; \ 471 } 472 473 #define LOG_ERROR(log, cert, depth, arg) \ 474 if (log != NULL) { \ 475 cert_AddToVerifyLog(log, cert, PORT_GetError(), depth, \ 476 (void *)(PRWord)arg); \ 477 } 478 479 /* /C=CN/O=WoSign CA Limited/CN=CA \xE6\xB2\x83\xE9\x80\x9A\xE6\xA0\xB9\xE8\xAF\x81\xE4\xB9\xA6 480 * Using a consistent naming convention, this would actually be called 481 * 'CA沃通根证书DN', but since GCC 6.2.1 apparently can't handle UTF-8 482 * identifiers, this will have to do. 483 */ 484 static const unsigned char CAWoSignRootDN[72] = { 485 0x30, 0x46, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 486 0x43, 0x4E, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x11, 487 0x57, 0x6F, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x43, 0x41, 0x20, 0x4C, 0x69, 0x6D, 488 0x69, 0x74, 0x65, 0x64, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x03, 489 0x0C, 0x12, 0x43, 0x41, 0x20, 0xE6, 0xB2, 0x83, 0xE9, 0x80, 0x9A, 0xE6, 0xA0, 490 0xB9, 0xE8, 0xAF, 0x81, 0xE4, 0xB9, 0xA6 491 }; 492 493 /* /C=CN/O=WoSign CA Limited/CN=CA WoSign ECC Root */ 494 static const unsigned char CAWoSignECCRootDN[72] = { 495 0x30, 0x46, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 496 0x43, 0x4E, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x11, 497 0x57, 0x6F, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x43, 0x41, 0x20, 0x4C, 0x69, 0x6D, 498 0x69, 0x74, 0x65, 0x64, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x03, 499 0x13, 0x12, 0x43, 0x41, 0x20, 0x57, 0x6F, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x45, 500 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74 501 }; 502 503 /* /C=CN/O=WoSign CA Limited/CN=Certification Authority of WoSign */ 504 static const unsigned char CertificationAuthorityofWoSignDN[87] = { 505 0x30, 0x55, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 506 0x43, 0x4E, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x11, 507 0x57, 0x6F, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x43, 0x41, 0x20, 0x4C, 0x69, 0x6D, 508 0x69, 0x74, 0x65, 0x64, 0x31, 0x2A, 0x30, 0x28, 0x06, 0x03, 0x55, 0x04, 0x03, 509 0x13, 0x21, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 510 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 511 0x6F, 0x66, 0x20, 0x57, 0x6F, 0x53, 0x69, 0x67, 0x6E 512 }; 513 514 /* /C=CN/O=WoSign CA Limited/CN=Certification Authority of WoSign G2 */ 515 static const unsigned char CertificationAuthorityofWoSignG2DN[90] = { 516 0x30, 0x58, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 517 0x43, 0x4E, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x11, 518 0x57, 0x6F, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x43, 0x41, 0x20, 0x4C, 0x69, 0x6D, 519 0x69, 0x74, 0x65, 0x64, 0x31, 0x2D, 0x30, 0x2B, 0x06, 0x03, 0x55, 0x04, 0x03, 520 0x13, 0x24, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 521 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 522 0x6F, 0x66, 0x20, 0x57, 0x6F, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x47, 0x32 523 }; 524 525 /* /C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Certification Authority */ 526 static const unsigned char StartComCertificationAuthorityDN[127] = { 527 0x30, 0x7D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 528 0x49, 0x4C, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0D, 529 0x53, 0x74, 0x61, 0x72, 0x74, 0x43, 0x6F, 0x6D, 0x20, 0x4C, 0x74, 0x64, 0x2E, 530 0x31, 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x22, 0x53, 0x65, 531 0x63, 0x75, 0x72, 0x65, 0x20, 0x44, 0x69, 0x67, 0x69, 0x74, 0x61, 0x6C, 0x20, 532 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x53, 533 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, 0x55, 534 0x04, 0x03, 0x13, 0x20, 0x53, 0x74, 0x61, 0x72, 0x74, 0x43, 0x6F, 0x6D, 0x20, 535 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 536 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 537 }; 538 539 /* /C=IL/O=StartCom Ltd./CN=StartCom Certification Authority G2 */ 540 static const unsigned char StartComCertificationAuthorityG2DN[85] = { 541 0x30, 0x53, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 542 0x49, 0x4C, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0D, 543 0x53, 0x74, 0x61, 0x72, 0x74, 0x43, 0x6F, 0x6D, 0x20, 0x4C, 0x74, 0x64, 0x2E, 544 0x31, 0x2C, 0x30, 0x2A, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x23, 0x53, 0x74, 545 0x61, 0x72, 0x74, 0x43, 0x6F, 0x6D, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 546 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 547 0x72, 0x69, 0x74, 0x79, 0x20, 0x47, 0x32 548 }; 549 550 struct DataAndLength { 551 const unsigned char *data; 552 PRUint32 len; 553 }; 554 555 static const struct DataAndLength StartComAndWoSignDNs[] = { 556 { CAWoSignRootDN, 557 sizeof(CAWoSignRootDN) }, 558 { CAWoSignECCRootDN, 559 sizeof(CAWoSignECCRootDN) }, 560 { CertificationAuthorityofWoSignDN, 561 sizeof(CertificationAuthorityofWoSignDN) }, 562 { CertificationAuthorityofWoSignG2DN, 563 sizeof(CertificationAuthorityofWoSignG2DN) }, 564 { StartComCertificationAuthorityDN, 565 sizeof(StartComCertificationAuthorityDN) }, 566 { StartComCertificationAuthorityG2DN, 567 sizeof(StartComCertificationAuthorityG2DN) }, 568 }; 569 570 static PRBool 571 CertIsStartComOrWoSign(const CERTCertificate *cert) 572 { 573 int i; 574 const struct DataAndLength *dn = StartComAndWoSignDNs; 575 576 for (i = 0; i < sizeof(StartComAndWoSignDNs) / sizeof(struct DataAndLength); ++i, dn++) { 577 if (cert->derSubject.len == dn->len && 578 memcmp(cert->derSubject.data, dn->data, dn->len) == 0) { 579 return PR_TRUE; 580 } 581 } 582 return PR_FALSE; 583 } 584 585 SECStatus 586 isIssuerCertAllowedAtCertIssuanceTime(CERTCertificate *issuerCert, 587 CERTCertificate *referenceCert) 588 { 589 if (!issuerCert || !referenceCert) { 590 PORT_SetError(SEC_ERROR_INVALID_ARGS); 591 return SECFailure; 592 } 593 594 if (CertIsStartComOrWoSign(issuerCert)) { 595 /* PRTime is microseconds since the epoch, whereas JS time is milliseconds. 596 * (new Date("2016-10-21T00:00:00Z")).getTime() * 1000 597 */ 598 static const PRTime OCTOBER_21_2016 = 1477008000000000; 599 600 PRTime notBefore, notAfter; 601 SECStatus rv; 602 603 rv = CERT_GetCertTimes(referenceCert, ¬Before, ¬After); 604 if (rv != SECSuccess) 605 return rv; 606 607 if (notBefore > OCTOBER_21_2016) { 608 return SECFailure; 609 } 610 } 611 612 return SECSuccess; 613 } 614 615 static SECStatus 616 cert_VerifyCertChainOld(CERTCertDBHandle *handle, CERTCertificate *cert, 617 PRBool checkSig, PRBool *sigerror, 618 SECCertUsage certUsage, PRTime t, void *wincx, 619 CERTVerifyLog *log, PRBool *revoked) 620 { 621 SECTrustType trustType; 622 CERTBasicConstraints basicConstraint; 623 CERTCertificate *issuerCert = NULL; 624 CERTCertificate *subjectCert = NULL; 625 CERTCertificate *badCert = NULL; 626 PRBool isca; 627 SECStatus rv; 628 SECStatus rvFinal = SECSuccess; 629 int count; 630 int currentPathLen = 0; 631 int pathLengthLimit = CERT_UNLIMITED_PATH_CONSTRAINT; 632 unsigned int caCertType; 633 unsigned int requiredCAKeyUsage; 634 unsigned int requiredFlags; 635 PLArenaPool *arena = NULL; 636 CERTGeneralName *namesList = NULL; 637 CERTCertificate **certsList = NULL; 638 int certsListLen = 16; 639 int namesCount = 0; 640 PRBool subjectCertIsSelfIssued; 641 CERTCertTrust issuerTrust; 642 643 if (revoked) { 644 *revoked = PR_FALSE; 645 } 646 647 if (CERT_KeyUsageAndTypeForCertUsage(certUsage, PR_TRUE, 648 &requiredCAKeyUsage, 649 &caCertType) != 650 SECSuccess) { 651 PORT_Assert(0); 652 EXIT_IF_NOT_LOGGING(log); 653 requiredCAKeyUsage = 0; 654 caCertType = 0; 655 } 656 657 switch (certUsage) { 658 case certUsageSSLClient: 659 case certUsageSSLServer: 660 case certUsageIPsec: 661 case certUsageSSLCA: 662 case certUsageSSLServerWithStepUp: 663 case certUsageEmailSigner: 664 case certUsageEmailRecipient: 665 case certUsageObjectSigner: 666 case certUsageVerifyCA: 667 case certUsageAnyCA: 668 case certUsageStatusResponder: 669 if (CERT_TrustFlagsForCACertUsage(certUsage, &requiredFlags, 670 &trustType) != SECSuccess) { 671 PORT_Assert(0); 672 EXIT_IF_NOT_LOGGING(log); 673 /* XXX continuing with requiredFlags = 0 seems wrong. It'll 674 * cause the following test to be true incorrectly: 675 * flags = SEC_GET_TRUST_FLAGS(issuerCert->trust, trustType); 676 * if (( flags & requiredFlags ) == requiredFlags) { 677 * rv = rvFinal; 678 * goto done; 679 * } 680 * There are three other instances of this problem. 681 */ 682 requiredFlags = 0; 683 trustType = trustSSL; 684 } 685 break; 686 default: 687 PORT_Assert(0); 688 EXIT_IF_NOT_LOGGING(log); 689 requiredFlags = 0; 690 trustType = trustSSL; /* This used to be 0, but we need something 691 * that matches the enumeration type. 692 */ 693 caCertType = 0; 694 } 695 696 subjectCert = CERT_DupCertificate(cert); 697 if (subjectCert == NULL) { 698 goto loser; 699 } 700 701 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 702 if (arena == NULL) { 703 goto loser; 704 } 705 706 certsList = PORT_ZNewArray(CERTCertificate *, certsListLen); 707 if (certsList == NULL) 708 goto loser; 709 710 /* RFC 3280 says that the name constraints will apply to the names 711 ** in the leaf (EE) cert, whether it is self issued or not, so 712 ** we pretend that it is not. 713 */ 714 subjectCertIsSelfIssued = PR_FALSE; 715 for (count = 0; count < CERT_MAX_CERT_CHAIN; count++) { 716 PRBool validCAOverride = PR_FALSE; 717 718 /* Construct a list of names for the current and all previous 719 * certifcates (except leaf (EE) certs, root CAs, and self-issued 720 * intermediate CAs) to be verified against the name constraints 721 * extension of the issuer certificate. 722 */ 723 if (subjectCertIsSelfIssued == PR_FALSE) { 724 CERTGeneralName *subjectNameList; 725 int subjectNameListLen; 726 int i; 727 PRBool getSubjectCN = (!count && 728 (certUsage == certUsageSSLServer || certUsage == certUsageIPsec)); 729 subjectNameList = 730 CERT_GetConstrainedCertificateNames(subjectCert, arena, 731 getSubjectCN); 732 if (!subjectNameList) 733 goto loser; 734 subjectNameListLen = CERT_GetNamesLength(subjectNameList); 735 if (!subjectNameListLen) 736 goto loser; 737 if (certsListLen <= namesCount + subjectNameListLen) { 738 CERTCertificate **tmpCertsList; 739 certsListLen = (namesCount + subjectNameListLen) * 2; 740 tmpCertsList = 741 (CERTCertificate **)PORT_Realloc(certsList, 742 certsListLen * 743 sizeof(CERTCertificate *)); 744 if (tmpCertsList == NULL) { 745 goto loser; 746 } 747 certsList = tmpCertsList; 748 } 749 for (i = 0; i < subjectNameListLen; i++) { 750 certsList[namesCount + i] = subjectCert; 751 } 752 namesCount += subjectNameListLen; 753 namesList = cert_CombineNamesLists(namesList, subjectNameList); 754 } 755 756 /* check if the cert has an unsupported critical extension */ 757 if (subjectCert->options.bits.hasUnsupportedCriticalExt) { 758 PORT_SetError(SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION); 759 LOG_ERROR_OR_EXIT(log, subjectCert, count, 0); 760 } 761 762 /* check that the signatureAlgorithm field of the certificate 763 * matches the signature field of the tbsCertificate */ 764 if (SECOID_CompareAlgorithmID( 765 &subjectCert->signatureWrap.signatureAlgorithm, 766 &subjectCert->signature)) { 767 PORT_SetError(SEC_ERROR_ALGORITHM_MISMATCH); 768 LOG_ERROR(log, subjectCert, count, 0); 769 goto loser; 770 } 771 772 /* find the certificate of the issuer */ 773 issuerCert = CERT_FindCertIssuer(subjectCert, t, certUsage); 774 if (!issuerCert) { 775 PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER); 776 LOG_ERROR(log, subjectCert, count, 0); 777 goto loser; 778 } 779 780 /* verify the signature on the cert */ 781 if (checkSig) { 782 rv = CERT_VerifySignedData(&subjectCert->signatureWrap, 783 issuerCert, t, wincx); 784 785 if (rv != SECSuccess) { 786 if (sigerror) { 787 *sigerror = PR_TRUE; 788 } 789 if (PORT_GetError() == SEC_ERROR_EXPIRED_CERTIFICATE) { 790 PORT_SetError(SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE); 791 LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, 0); 792 } else { 793 if (PORT_GetError() != 794 SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED) { 795 PORT_SetError(SEC_ERROR_BAD_SIGNATURE); 796 } 797 LOG_ERROR_OR_EXIT(log, subjectCert, count, 0); 798 } 799 } 800 } 801 802 /* If the basicConstraint extension is included in an immediate CA 803 * certificate, make sure that the isCA flag is on. If the 804 * pathLenConstraint component exists, it must be greater than the 805 * number of CA certificates we have seen so far. If the extension 806 * is omitted, we will assume that this is a CA certificate with 807 * an unlimited pathLenConstraint (since it already passes the 808 * netscape-cert-type extension checking). 809 */ 810 811 rv = CERT_FindBasicConstraintExten(issuerCert, &basicConstraint); 812 if (rv != SECSuccess) { 813 if (PORT_GetError() != SEC_ERROR_EXTENSION_NOT_FOUND) { 814 LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, 0); 815 } 816 pathLengthLimit = CERT_UNLIMITED_PATH_CONSTRAINT; 817 /* no basic constraints found, we aren't (yet) a CA. */ 818 isca = PR_FALSE; 819 } else { 820 if (basicConstraint.isCA == PR_FALSE) { 821 PORT_SetError(SEC_ERROR_CA_CERT_INVALID); 822 LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, 0); 823 } 824 pathLengthLimit = basicConstraint.pathLenConstraint; 825 isca = PR_TRUE; 826 } 827 /* make sure that the path len constraint is properly set.*/ 828 if (pathLengthLimit >= 0 && currentPathLen > pathLengthLimit) { 829 PORT_SetError(SEC_ERROR_PATH_LEN_CONSTRAINT_INVALID); 830 LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, pathLengthLimit); 831 } 832 833 /* make sure that the entire chain is within the name space of the 834 * current issuer certificate. 835 */ 836 rv = CERT_CompareNameSpace(issuerCert, namesList, certsList, 837 arena, &badCert); 838 if (rv != SECSuccess || badCert != NULL) { 839 PORT_SetError(SEC_ERROR_CERT_NOT_IN_NAME_SPACE); 840 LOG_ERROR_OR_EXIT(log, badCert, count + 1, 0); 841 goto loser; 842 } 843 844 rv = isIssuerCertAllowedAtCertIssuanceTime(issuerCert, cert); 845 if (rv != SECSuccess) { 846 PORT_SetError(SEC_ERROR_UNTRUSTED_ISSUER); 847 LOG_ERROR(log, issuerCert, count + 1, 0); 848 goto loser; 849 } 850 851 /* XXX - the error logging may need to go down into CRL stuff at some 852 * point 853 */ 854 /* check revoked list (issuer) */ 855 rv = SEC_CheckCRL(handle, subjectCert, issuerCert, t, wincx); 856 if (rv == SECFailure) { 857 if (revoked) { 858 *revoked = PR_TRUE; 859 } 860 LOG_ERROR_OR_EXIT(log, subjectCert, count, 0); 861 } else if (rv == SECWouldBlock) { 862 /* We found something fishy, so we intend to issue an 863 * error to the user, but the user may wish to continue 864 * processing, in which case we better make sure nothing 865 * worse has happened... so keep cranking the loop */ 866 rvFinal = SECFailure; 867 if (revoked) { 868 *revoked = PR_TRUE; 869 } 870 LOG_ERROR(log, subjectCert, count, 0); 871 } 872 873 if (CERT_GetCertTrust(issuerCert, &issuerTrust) == SECSuccess) { 874 /* we have some trust info, but this does NOT imply that this 875 * cert is actually trusted for any purpose. The cert may be 876 * explicitly UNtrusted. We won't know until we examine the 877 * trust bits. 878 */ 879 unsigned int flags; 880 881 if (certUsage != certUsageAnyCA && 882 certUsage != certUsageStatusResponder) { 883 884 /* 885 * XXX This choice of trustType seems arbitrary. 886 */ 887 if (certUsage == certUsageVerifyCA) { 888 if (subjectCert->nsCertType & NS_CERT_TYPE_EMAIL_CA) { 889 trustType = trustEmail; 890 } else if (subjectCert->nsCertType & NS_CERT_TYPE_SSL_CA) { 891 trustType = trustSSL; 892 } else { 893 trustType = trustObjectSigning; 894 } 895 } 896 897 flags = SEC_GET_TRUST_FLAGS(&issuerTrust, trustType); 898 if ((flags & requiredFlags) == requiredFlags) { 899 /* we found a trusted one, so return */ 900 rv = rvFinal; 901 goto done; 902 } 903 if (flags & CERTDB_VALID_CA) { 904 validCAOverride = PR_TRUE; 905 } 906 /* is it explicitly distrusted? */ 907 if ((flags & CERTDB_TERMINAL_RECORD) && 908 ((flags & (CERTDB_TRUSTED | CERTDB_TRUSTED_CA)) == 0)) { 909 /* untrusted -- the cert is explicitly untrusted, not 910 * just that it doesn't chain to a trusted cert */ 911 PORT_SetError(SEC_ERROR_UNTRUSTED_ISSUER); 912 LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, flags); 913 } 914 } else { 915 /* Check if we have any valid trust when cheching for 916 * certUsageAnyCA or certUsageStatusResponder. */ 917 for (trustType = trustSSL; trustType < trustTypeNone; 918 trustType++) { 919 flags = SEC_GET_TRUST_FLAGS(&issuerTrust, trustType); 920 if ((flags & requiredFlags) == requiredFlags) { 921 rv = rvFinal; 922 goto done; 923 } 924 if (flags & CERTDB_VALID_CA) 925 validCAOverride = PR_TRUE; 926 } 927 /* We have 2 separate loops because we want any single trust 928 * bit to allow this usage to return trusted. Only if none of 929 * the trust bits are on do we check to see if the cert is 930 * untrusted */ 931 for (trustType = trustSSL; trustType < trustTypeNone; 932 trustType++) { 933 flags = SEC_GET_TRUST_FLAGS(&issuerTrust, trustType); 934 /* is it explicitly distrusted? */ 935 if ((flags & CERTDB_TERMINAL_RECORD) && 936 ((flags & (CERTDB_TRUSTED | CERTDB_TRUSTED_CA)) == 0)) { 937 /* untrusted -- the cert is explicitly untrusted, not 938 * just that it doesn't chain to a trusted cert */ 939 PORT_SetError(SEC_ERROR_UNTRUSTED_ISSUER); 940 LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, flags); 941 } 942 } 943 } 944 } 945 946 if (!validCAOverride) { 947 /* 948 * Make sure that if this is an intermediate CA in the chain that 949 * it was given permission by its signer to be a CA. 950 */ 951 /* 952 * if basicConstraints says it is a ca, then we check the 953 * nsCertType. If the nsCertType has any CA bits set, then 954 * it must have the right one. 955 */ 956 if (!isca || (issuerCert->nsCertType & NS_CERT_TYPE_CA)) { 957 isca = (issuerCert->nsCertType & caCertType) ? PR_TRUE : PR_FALSE; 958 } 959 960 if (!isca) { 961 PORT_SetError(SEC_ERROR_CA_CERT_INVALID); 962 LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, 0); 963 } 964 965 /* make sure key usage allows cert signing */ 966 if (CERT_CheckKeyUsage(issuerCert, requiredCAKeyUsage) != SECSuccess) { 967 PORT_SetError(SEC_ERROR_INADEQUATE_KEY_USAGE); 968 LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, requiredCAKeyUsage); 969 } 970 } 971 972 /* make sure that the issuer is not self signed. If it is, then 973 * stop here to prevent looping. 974 */ 975 if (issuerCert->isRoot) { 976 PORT_SetError(SEC_ERROR_UNTRUSTED_ISSUER); 977 LOG_ERROR(log, issuerCert, count + 1, 0); 978 goto loser; 979 } 980 /* The issuer cert will be the subject cert in the next loop. 981 * A cert is self-issued if its subject and issuer are equal and 982 * both are of non-zero length. 983 */ 984 subjectCertIsSelfIssued = (PRBool) 985 SECITEM_ItemsAreEqual(&issuerCert->derIssuer, 986 &issuerCert->derSubject) && 987 issuerCert->derSubject.len > 988 0; 989 if (subjectCertIsSelfIssued == PR_FALSE) { 990 /* RFC 3280 says only non-self-issued intermediate CA certs 991 * count in path length. 992 */ 993 ++currentPathLen; 994 } 995 996 CERT_DestroyCertificate(subjectCert); 997 subjectCert = issuerCert; 998 issuerCert = NULL; 999 } 1000 1001 PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER); 1002 LOG_ERROR(log, subjectCert, count, 0); 1003 loser: 1004 rv = SECFailure; 1005 done: 1006 if (certsList != NULL) { 1007 PORT_Free(certsList); 1008 } 1009 if (issuerCert) { 1010 CERT_DestroyCertificate(issuerCert); 1011 } 1012 1013 if (subjectCert) { 1014 CERT_DestroyCertificate(subjectCert); 1015 } 1016 1017 if (arena != NULL) { 1018 PORT_FreeArena(arena, PR_FALSE); 1019 } 1020 return rv; 1021 } 1022 1023 SECStatus 1024 cert_VerifyCertChain(CERTCertDBHandle *handle, CERTCertificate *cert, 1025 PRBool checkSig, PRBool *sigerror, 1026 SECCertUsage certUsage, PRTime t, void *wincx, 1027 CERTVerifyLog *log, PRBool *revoked) 1028 { 1029 if (CERT_GetUsePKIXForValidation()) { 1030 return cert_VerifyCertChainPkix(cert, checkSig, certUsage, t, 1031 wincx, log, sigerror, revoked); 1032 } 1033 return cert_VerifyCertChainOld(handle, cert, checkSig, sigerror, 1034 certUsage, t, wincx, log, revoked); 1035 } 1036 1037 SECStatus 1038 CERT_VerifyCertChain(CERTCertDBHandle *handle, CERTCertificate *cert, 1039 PRBool checkSig, SECCertUsage certUsage, PRTime t, 1040 void *wincx, CERTVerifyLog *log) 1041 { 1042 return cert_VerifyCertChain(handle, cert, checkSig, NULL, certUsage, t, 1043 wincx, log, NULL); 1044 } 1045 1046 /* 1047 * verify that a CA can sign a certificate with the requested usage. 1048 */ 1049 SECStatus 1050 CERT_VerifyCACertForUsage(CERTCertDBHandle *handle, CERTCertificate *cert, 1051 PRBool checkSig, SECCertUsage certUsage, PRTime t, 1052 void *wincx, CERTVerifyLog *log) 1053 { 1054 SECTrustType trustType; 1055 CERTBasicConstraints basicConstraint; 1056 PRBool isca; 1057 PRBool validCAOverride = PR_FALSE; 1058 SECStatus rv; 1059 SECStatus rvFinal = SECSuccess; 1060 unsigned int flags; 1061 unsigned int caCertType; 1062 unsigned int requiredCAKeyUsage; 1063 unsigned int requiredFlags; 1064 CERTCertificate *issuerCert; 1065 CERTCertTrust certTrust; 1066 1067 if (CERT_KeyUsageAndTypeForCertUsage(certUsage, PR_TRUE, 1068 &requiredCAKeyUsage, 1069 &caCertType) != SECSuccess) { 1070 PORT_Assert(0); 1071 EXIT_IF_NOT_LOGGING(log); 1072 requiredCAKeyUsage = 0; 1073 caCertType = 0; 1074 } 1075 1076 switch (certUsage) { 1077 case certUsageSSLClient: 1078 case certUsageSSLServer: 1079 case certUsageIPsec: 1080 case certUsageSSLCA: 1081 case certUsageSSLServerWithStepUp: 1082 case certUsageEmailSigner: 1083 case certUsageEmailRecipient: 1084 case certUsageObjectSigner: 1085 case certUsageVerifyCA: 1086 case certUsageStatusResponder: 1087 if (CERT_TrustFlagsForCACertUsage(certUsage, &requiredFlags, 1088 &trustType) != SECSuccess) { 1089 PORT_Assert(0); 1090 EXIT_IF_NOT_LOGGING(log); 1091 requiredFlags = 0; 1092 trustType = trustSSL; 1093 } 1094 break; 1095 default: 1096 PORT_Assert(0); 1097 EXIT_IF_NOT_LOGGING(log); 1098 requiredFlags = 0; 1099 trustType = trustSSL; /* This used to be 0, but we need something 1100 * that matches the enumeration type. 1101 */ 1102 caCertType = 0; 1103 } 1104 1105 /* If the basicConstraint extension is included in an intermmediate CA 1106 * certificate, make sure that the isCA flag is on. If the 1107 * pathLenConstraint component exists, it must be greater than the 1108 * number of CA certificates we have seen so far. If the extension 1109 * is omitted, we will assume that this is a CA certificate with 1110 * an unlimited pathLenConstraint (since it already passes the 1111 * netscape-cert-type extension checking). 1112 */ 1113 1114 rv = CERT_FindBasicConstraintExten(cert, &basicConstraint); 1115 if (rv != SECSuccess) { 1116 if (PORT_GetError() != SEC_ERROR_EXTENSION_NOT_FOUND) { 1117 LOG_ERROR_OR_EXIT(log, cert, 0, 0); 1118 } 1119 /* no basic constraints found, we aren't (yet) a CA. */ 1120 isca = PR_FALSE; 1121 } else { 1122 if (basicConstraint.isCA == PR_FALSE) { 1123 PORT_SetError(SEC_ERROR_CA_CERT_INVALID); 1124 LOG_ERROR_OR_EXIT(log, cert, 0, 0); 1125 } 1126 1127 /* can't check path length if we don't know the previous path */ 1128 isca = PR_TRUE; 1129 } 1130 1131 if (CERT_GetCertTrust(cert, &certTrust) == SECSuccess) { 1132 /* we have some trust info, but this does NOT imply that this 1133 * cert is actually trusted for any purpose. The cert may be 1134 * explicitly UNtrusted. We won't know until we examine the 1135 * trust bits. 1136 */ 1137 if (certUsage == certUsageStatusResponder) { 1138 /* Check the special case of certUsageStatusResponder */ 1139 issuerCert = CERT_FindCertIssuer(cert, t, certUsage); 1140 if (issuerCert) { 1141 if (SEC_CheckCRL(handle, cert, issuerCert, t, wincx) != 1142 SECSuccess) { 1143 PORT_SetError(SEC_ERROR_REVOKED_CERTIFICATE); 1144 CERT_DestroyCertificate(issuerCert); 1145 goto loser; 1146 } 1147 CERT_DestroyCertificate(issuerCert); 1148 } 1149 /* XXX We have NOT determined that this cert is trusted. 1150 * For years, NSS has treated this as trusted, 1151 * but it seems incorrect. 1152 */ 1153 rv = rvFinal; 1154 goto done; 1155 } 1156 1157 /* 1158 * check the trust params of the issuer 1159 */ 1160 flags = SEC_GET_TRUST_FLAGS(&certTrust, trustType); 1161 if ((flags & requiredFlags) == requiredFlags) { 1162 /* we found a trusted one, so return */ 1163 rv = rvFinal; 1164 goto done; 1165 } 1166 if (flags & CERTDB_VALID_CA) { 1167 validCAOverride = PR_TRUE; 1168 } 1169 /* is it explicitly distrusted? */ 1170 if ((flags & CERTDB_TERMINAL_RECORD) && 1171 ((flags & (CERTDB_TRUSTED | CERTDB_TRUSTED_CA)) == 0)) { 1172 /* untrusted -- the cert is explicitly untrusted, not 1173 * just that it doesn't chain to a trusted cert */ 1174 PORT_SetError(SEC_ERROR_UNTRUSTED_CERT); 1175 LOG_ERROR_OR_EXIT(log, cert, 0, flags); 1176 } 1177 } 1178 if (!validCAOverride) { 1179 /* 1180 * Make sure that if this is an intermediate CA in the chain that 1181 * it was given permission by its signer to be a CA. 1182 */ 1183 /* 1184 * if basicConstraints says it is a ca, then we check the 1185 * nsCertType. If the nsCertType has any CA bits set, then 1186 * it must have the right one. 1187 */ 1188 if (!isca || (cert->nsCertType & NS_CERT_TYPE_CA)) { 1189 isca = (cert->nsCertType & caCertType) ? PR_TRUE : PR_FALSE; 1190 } 1191 1192 if (!isca) { 1193 PORT_SetError(SEC_ERROR_CA_CERT_INVALID); 1194 LOG_ERROR_OR_EXIT(log, cert, 0, 0); 1195 } 1196 1197 /* make sure key usage allows cert signing */ 1198 if (CERT_CheckKeyUsage(cert, requiredCAKeyUsage) != SECSuccess) { 1199 PORT_SetError(SEC_ERROR_INADEQUATE_KEY_USAGE); 1200 LOG_ERROR_OR_EXIT(log, cert, 0, requiredCAKeyUsage); 1201 } 1202 } 1203 /* make sure that the issuer is not self signed. If it is, then 1204 * stop here to prevent looping. 1205 */ 1206 if (cert->isRoot) { 1207 PORT_SetError(SEC_ERROR_UNTRUSTED_ISSUER); 1208 LOG_ERROR(log, cert, 0, 0); 1209 goto loser; 1210 } 1211 1212 return CERT_VerifyCertChain(handle, cert, checkSig, certUsage, t, 1213 wincx, log); 1214 loser: 1215 rv = SECFailure; 1216 done: 1217 return rv; 1218 } 1219 1220 #define NEXT_USAGE() \ 1221 { \ 1222 i *= 2; \ 1223 certUsage++; \ 1224 continue; \ 1225 } 1226 1227 #define VALID_USAGE() \ 1228 { \ 1229 NEXT_USAGE(); \ 1230 } 1231 1232 #define INVALID_USAGE() \ 1233 { \ 1234 if (returnedUsages) { \ 1235 *returnedUsages &= (~i); \ 1236 } \ 1237 if (PR_TRUE == requiredUsage) { \ 1238 valid = SECFailure; \ 1239 } \ 1240 NEXT_USAGE(); \ 1241 } 1242 1243 /* 1244 * check the leaf cert against trust and usage. 1245 * returns success if the cert is not distrusted. If the cert is 1246 * trusted, then the trusted bool will be true. 1247 * returns failure if the cert is distrusted. If failure, flags 1248 * will return the flag bits that indicated distrust. 1249 */ 1250 SECStatus 1251 cert_CheckLeafTrust(CERTCertificate *cert, SECCertUsage certUsage, 1252 unsigned int *failedFlags, PRBool *trusted) 1253 { 1254 unsigned int flags; 1255 CERTCertTrust trust; 1256 1257 *failedFlags = 0; 1258 *trusted = PR_FALSE; 1259 1260 /* check trust flags to see if this cert is directly trusted */ 1261 if (CERT_GetCertTrust(cert, &trust) == SECSuccess) { 1262 switch (certUsage) { 1263 case certUsageSSLClient: 1264 case certUsageSSLServer: 1265 case certUsageIPsec: 1266 flags = trust.sslFlags; 1267 1268 /* is the cert directly trusted or not trusted ? */ 1269 if (flags & CERTDB_TERMINAL_RECORD) { /* the trust record is 1270 * authoritative */ 1271 if (flags & CERTDB_TRUSTED) { /* trust this cert */ 1272 *trusted = PR_TRUE; 1273 return SECSuccess; 1274 } else { /* don't trust this cert */ 1275 *failedFlags = flags; 1276 return SECFailure; 1277 } 1278 } 1279 break; 1280 case certUsageSSLServerWithStepUp: 1281 /* XXX - step up certs can't be directly trusted, only distrust */ 1282 flags = trust.sslFlags; 1283 if (flags & CERTDB_TERMINAL_RECORD) { /* the trust record is 1284 * authoritative */ 1285 if ((flags & CERTDB_TRUSTED) == 0) { 1286 /* don't trust this cert */ 1287 *failedFlags = flags; 1288 return SECFailure; 1289 } 1290 } 1291 break; 1292 case certUsageSSLCA: 1293 flags = trust.sslFlags; 1294 if (flags & CERTDB_TERMINAL_RECORD) { /* the trust record is 1295 * authoritative */ 1296 if ((flags & (CERTDB_TRUSTED | CERTDB_TRUSTED_CA)) == 0) { 1297 /* don't trust this cert */ 1298 *failedFlags = flags; 1299 return SECFailure; 1300 } 1301 } 1302 break; 1303 case certUsageEmailSigner: 1304 case certUsageEmailRecipient: 1305 flags = trust.emailFlags; 1306 if (flags & CERTDB_TERMINAL_RECORD) { /* the trust record is 1307 * authoritative */ 1308 if (flags & CERTDB_TRUSTED) { /* trust this cert */ 1309 *trusted = PR_TRUE; 1310 return SECSuccess; 1311 } else { /* don't trust this cert */ 1312 *failedFlags = flags; 1313 return SECFailure; 1314 } 1315 } 1316 1317 break; 1318 case certUsageObjectSigner: 1319 flags = trust.objectSigningFlags; 1320 1321 if (flags & CERTDB_TERMINAL_RECORD) { /* the trust record is 1322 * authoritative */ 1323 if (flags & CERTDB_TRUSTED) { /* trust this cert */ 1324 *trusted = PR_TRUE; 1325 return SECSuccess; 1326 } else { /* don't trust this cert */ 1327 *failedFlags = flags; 1328 return SECFailure; 1329 } 1330 } 1331 break; 1332 case certUsageVerifyCA: 1333 case certUsageStatusResponder: 1334 flags = trust.sslFlags; 1335 /* is the cert directly trusted or not trusted ? */ 1336 if ((flags & (CERTDB_VALID_CA | CERTDB_TRUSTED_CA)) == 1337 (CERTDB_VALID_CA | CERTDB_TRUSTED_CA)) { 1338 *trusted = PR_TRUE; 1339 return SECSuccess; 1340 } 1341 flags = trust.emailFlags; 1342 /* is the cert directly trusted or not trusted ? */ 1343 if ((flags & (CERTDB_VALID_CA | CERTDB_TRUSTED_CA)) == 1344 (CERTDB_VALID_CA | CERTDB_TRUSTED_CA)) { 1345 *trusted = PR_TRUE; 1346 return SECSuccess; 1347 } 1348 flags = trust.objectSigningFlags; 1349 /* is the cert directly trusted or not trusted ? */ 1350 if ((flags & (CERTDB_VALID_CA | CERTDB_TRUSTED_CA)) == 1351 (CERTDB_VALID_CA | CERTDB_TRUSTED_CA)) { 1352 *trusted = PR_TRUE; 1353 return SECSuccess; 1354 } 1355 /* fall through to test distrust */ 1356 case certUsageAnyCA: 1357 case certUsageUserCertImport: 1358 /* do we distrust these certs explicitly */ 1359 flags = trust.sslFlags; 1360 if (flags & CERTDB_TERMINAL_RECORD) { /* the trust record is 1361 * authoritative */ 1362 if ((flags & (CERTDB_TRUSTED | CERTDB_TRUSTED_CA)) == 0) { 1363 *failedFlags = flags; 1364 return SECFailure; 1365 } 1366 } 1367 flags = trust.emailFlags; 1368 if (flags & CERTDB_TERMINAL_RECORD) { /* the trust record is 1369 * authoritative */ 1370 if ((flags & (CERTDB_TRUSTED | CERTDB_TRUSTED_CA)) == 0) { 1371 *failedFlags = flags; 1372 return SECFailure; 1373 } 1374 } 1375 /* fall through */ 1376 case certUsageProtectedObjectSigner: 1377 flags = trust.objectSigningFlags; 1378 if (flags & CERTDB_TERMINAL_RECORD) { /* the trust record is 1379 * authoritative */ 1380 if ((flags & (CERTDB_TRUSTED | CERTDB_TRUSTED_CA)) == 0) { 1381 *failedFlags = flags; 1382 return SECFailure; 1383 } 1384 } 1385 break; 1386 } 1387 } 1388 return SECSuccess; 1389 } 1390 1391 /* 1392 * verify a certificate by checking if it's valid and that we 1393 * trust the issuer. 1394 * 1395 * certificateUsage contains a bitfield of all cert usages that are 1396 * required for verification to succeed 1397 * 1398 * a bitfield of cert usages is returned in *returnedUsages 1399 * if requiredUsages is non-zero, the returned bitmap is only 1400 * for those required usages, otherwise it is for all usages 1401 * 1402 */ 1403 SECStatus 1404 CERT_VerifyCertificate(CERTCertDBHandle *handle, CERTCertificate *cert, 1405 PRBool checkSig, SECCertificateUsage requiredUsages, PRTime t, 1406 void *wincx, CERTVerifyLog *log, SECCertificateUsage *returnedUsages) 1407 { 1408 SECStatus rv; 1409 SECStatus valid; 1410 unsigned int requiredKeyUsage; 1411 unsigned int requiredCertType; 1412 unsigned int flags; 1413 unsigned int certType; 1414 PRBool allowOverride; 1415 SECCertTimeValidity validity; 1416 CERTStatusConfig *statusConfig; 1417 PRInt32 i; 1418 SECCertUsage certUsage = 0; 1419 PRBool checkedOCSP = PR_FALSE; 1420 PRBool checkAllUsages = PR_FALSE; 1421 PRBool revoked = PR_FALSE; 1422 PRBool sigerror = PR_FALSE; 1423 PRBool trusted = PR_FALSE; 1424 1425 if (!requiredUsages) { 1426 /* there are no required usages, so the user probably wants to 1427 get status for all usages */ 1428 checkAllUsages = PR_TRUE; 1429 } 1430 1431 if (returnedUsages) { 1432 *returnedUsages = 0; 1433 } else { 1434 /* we don't have a place to return status for all usages, 1435 so we can skip checks for usages that aren't required */ 1436 checkAllUsages = PR_FALSE; 1437 } 1438 valid = SECSuccess; /* start off assuming cert is valid */ 1439 1440 /* make sure that the cert is valid at time t */ 1441 allowOverride = (PRBool)((requiredUsages & certificateUsageSSLServer) || 1442 (requiredUsages & certificateUsageSSLServerWithStepUp) || 1443 (requiredUsages & certificateUsageIPsec)); 1444 validity = CERT_CheckCertValidTimes(cert, t, allowOverride); 1445 if (validity != secCertTimeValid) { 1446 valid = SECFailure; 1447 LOG_ERROR_OR_EXIT(log, cert, 0, validity); 1448 } 1449 1450 /* check key usage and netscape cert type */ 1451 cert_GetCertType(cert); 1452 certType = cert->nsCertType; 1453 1454 for (i = 1; i <= certificateUsageHighest && 1455 (SECSuccess == valid || returnedUsages || log);) { 1456 PRBool requiredUsage = (i & requiredUsages) ? PR_TRUE : PR_FALSE; 1457 if (PR_FALSE == requiredUsage && PR_FALSE == checkAllUsages) { 1458 NEXT_USAGE(); 1459 } 1460 if (returnedUsages) { 1461 *returnedUsages |= i; /* start off assuming this usage is valid */ 1462 } 1463 switch (certUsage) { 1464 case certUsageSSLClient: 1465 case certUsageSSLServer: 1466 case certUsageSSLServerWithStepUp: 1467 case certUsageSSLCA: 1468 case certUsageEmailSigner: 1469 case certUsageEmailRecipient: 1470 case certUsageObjectSigner: 1471 case certUsageStatusResponder: 1472 case certUsageIPsec: 1473 rv = CERT_KeyUsageAndTypeForCertUsage(certUsage, PR_FALSE, 1474 &requiredKeyUsage, 1475 &requiredCertType); 1476 if (rv != SECSuccess) { 1477 PORT_Assert(0); 1478 /* EXIT_IF_NOT_LOGGING(log); XXX ??? */ 1479 requiredKeyUsage = 0; 1480 requiredCertType = 0; 1481 INVALID_USAGE(); 1482 } 1483 break; 1484 1485 case certUsageAnyCA: 1486 case certUsageProtectedObjectSigner: 1487 case certUsageUserCertImport: 1488 case certUsageVerifyCA: 1489 /* these usages cannot be verified */ 1490 NEXT_USAGE(); 1491 1492 default: 1493 PORT_Assert(0); 1494 requiredKeyUsage = 0; 1495 requiredCertType = 0; 1496 INVALID_USAGE(); 1497 } 1498 if (CERT_CheckKeyUsage(cert, requiredKeyUsage) != SECSuccess) { 1499 if (PR_TRUE == requiredUsage) { 1500 PORT_SetError(SEC_ERROR_INADEQUATE_KEY_USAGE); 1501 } 1502 LOG_ERROR(log, cert, 0, requiredKeyUsage); 1503 INVALID_USAGE(); 1504 } 1505 if (!(certType & requiredCertType)) { 1506 if (PR_TRUE == requiredUsage) { 1507 PORT_SetError(SEC_ERROR_INADEQUATE_CERT_TYPE); 1508 } 1509 LOG_ERROR(log, cert, 0, requiredCertType); 1510 INVALID_USAGE(); 1511 } 1512 1513 rv = cert_CheckLeafTrust(cert, certUsage, &flags, &trusted); 1514 if (rv == SECFailure) { 1515 if (PR_TRUE == requiredUsage) { 1516 PORT_SetError(SEC_ERROR_UNTRUSTED_CERT); 1517 } 1518 LOG_ERROR(log, cert, 0, flags); 1519 INVALID_USAGE(); 1520 } else if (trusted) { 1521 VALID_USAGE(); 1522 } 1523 1524 if (PR_TRUE == revoked || PR_TRUE == sigerror) { 1525 INVALID_USAGE(); 1526 } 1527 1528 rv = cert_VerifyCertChain(handle, cert, 1529 checkSig, &sigerror, 1530 certUsage, t, wincx, log, 1531 &revoked); 1532 1533 if (rv != SECSuccess) { 1534 /* EXIT_IF_NOT_LOGGING(log); XXX ???? */ 1535 INVALID_USAGE(); 1536 } 1537 1538 /* 1539 * Check OCSP revocation status, but only if the cert we are checking 1540 * is not a status responder itself. We only do this in the case 1541 * where we checked the cert chain (above); explicit trust "wins" 1542 * (avoids status checking, just as it avoids CRL checking) by 1543 * bypassing this code. 1544 */ 1545 1546 if (PR_FALSE == checkedOCSP) { 1547 checkedOCSP = PR_TRUE; /* only check OCSP once */ 1548 statusConfig = CERT_GetStatusConfig(handle); 1549 if (requiredUsages != certificateUsageStatusResponder && 1550 statusConfig != NULL) { 1551 if (statusConfig->statusChecker != NULL) { 1552 rv = (*statusConfig->statusChecker)(handle, cert, 1553 t, wincx); 1554 if (rv != SECSuccess) { 1555 LOG_ERROR(log, cert, 0, 0); 1556 revoked = PR_TRUE; 1557 INVALID_USAGE(); 1558 } 1559 } 1560 } 1561 } 1562 1563 NEXT_USAGE(); 1564 } 1565 1566 loser: 1567 return (valid); 1568 } 1569 1570 SECStatus 1571 CERT_VerifyCert(CERTCertDBHandle *handle, CERTCertificate *cert, 1572 PRBool checkSig, SECCertUsage certUsage, PRTime t, 1573 void *wincx, CERTVerifyLog *log) 1574 { 1575 return cert_VerifyCertWithFlags(handle, cert, checkSig, certUsage, t, 1576 CERT_VERIFYCERT_USE_DEFAULTS, wincx, log); 1577 } 1578 1579 SECStatus 1580 cert_VerifyCertWithFlags(CERTCertDBHandle *handle, CERTCertificate *cert, 1581 PRBool checkSig, SECCertUsage certUsage, PRTime t, 1582 PRUint32 flags, void *wincx, CERTVerifyLog *log) 1583 { 1584 SECStatus rv; 1585 unsigned int requiredKeyUsage; 1586 unsigned int requiredCertType; 1587 unsigned int failedFlags; 1588 unsigned int certType; 1589 PRBool trusted; 1590 PRBool allowOverride; 1591 SECCertTimeValidity validity; 1592 CERTStatusConfig *statusConfig; 1593 1594 #ifdef notdef 1595 /* check if this cert is in the Evil list */ 1596 rv = CERT_CheckForEvilCert(cert); 1597 if (rv != SECSuccess) { 1598 PORT_SetError(SEC_ERROR_REVOKED_CERTIFICATE); 1599 LOG_ERROR_OR_EXIT(log, cert, 0, 0); 1600 } 1601 #endif 1602 1603 /* make sure that the cert is valid at time t */ 1604 allowOverride = (PRBool)((certUsage == certUsageSSLServer) || 1605 (certUsage == certUsageSSLServerWithStepUp) || 1606 (certUsage == certUsageIPsec)); 1607 validity = CERT_CheckCertValidTimes(cert, t, allowOverride); 1608 if (validity != secCertTimeValid) { 1609 LOG_ERROR_OR_EXIT(log, cert, 0, validity); 1610 } 1611 1612 /* check key usage and netscape cert type */ 1613 cert_GetCertType(cert); 1614 certType = cert->nsCertType; 1615 switch (certUsage) { 1616 case certUsageSSLClient: 1617 case certUsageSSLServer: 1618 case certUsageSSLServerWithStepUp: 1619 case certUsageIPsec: 1620 case certUsageSSLCA: 1621 case certUsageEmailSigner: 1622 case certUsageEmailRecipient: 1623 case certUsageObjectSigner: 1624 case certUsageStatusResponder: 1625 rv = CERT_KeyUsageAndTypeForCertUsage(certUsage, PR_FALSE, 1626 &requiredKeyUsage, 1627 &requiredCertType); 1628 if (rv != SECSuccess) { 1629 PORT_Assert(0); 1630 EXIT_IF_NOT_LOGGING(log); 1631 requiredKeyUsage = 0; 1632 requiredCertType = 0; 1633 } 1634 break; 1635 case certUsageVerifyCA: 1636 case certUsageAnyCA: 1637 requiredKeyUsage = KU_KEY_CERT_SIGN; 1638 requiredCertType = NS_CERT_TYPE_CA; 1639 if (!(certType & NS_CERT_TYPE_CA)) { 1640 certType |= NS_CERT_TYPE_CA; 1641 } 1642 break; 1643 default: 1644 PORT_Assert(0); 1645 EXIT_IF_NOT_LOGGING(log); 1646 requiredKeyUsage = 0; 1647 requiredCertType = 0; 1648 } 1649 if (CERT_CheckKeyUsage(cert, requiredKeyUsage) != SECSuccess) { 1650 PORT_SetError(SEC_ERROR_INADEQUATE_KEY_USAGE); 1651 LOG_ERROR_OR_EXIT(log, cert, 0, requiredKeyUsage); 1652 } 1653 if (!(certType & requiredCertType)) { 1654 PORT_SetError(SEC_ERROR_INADEQUATE_CERT_TYPE); 1655 LOG_ERROR_OR_EXIT(log, cert, 0, requiredCertType); 1656 } 1657 1658 rv = cert_CheckLeafTrust(cert, certUsage, &failedFlags, &trusted); 1659 if (rv == SECFailure) { 1660 PORT_SetError(SEC_ERROR_UNTRUSTED_CERT); 1661 LOG_ERROR_OR_EXIT(log, cert, 0, failedFlags); 1662 } else if (trusted) { 1663 goto done; 1664 } 1665 1666 rv = CERT_VerifyCertChain(handle, cert, checkSig, certUsage, 1667 t, wincx, log); 1668 if (rv != SECSuccess) { 1669 EXIT_IF_NOT_LOGGING(log); 1670 } 1671 1672 /* 1673 * Check revocation status, but only if the cert we are checking is not a 1674 * status responder itself and the caller did not ask us to skip the check. 1675 * We only do this in the case where we checked the cert chain (above); 1676 * explicit trust "wins" (avoids status checking, just as it avoids CRL 1677 * checking, which is all done inside VerifyCertChain) by bypassing this 1678 * code. 1679 */ 1680 if (!(flags & CERT_VERIFYCERT_SKIP_OCSP) && 1681 certUsage != certUsageStatusResponder) { 1682 statusConfig = CERT_GetStatusConfig(handle); 1683 if (statusConfig && statusConfig->statusChecker) { 1684 rv = (*statusConfig->statusChecker)(handle, cert, 1685 t, wincx); 1686 if (rv != SECSuccess) { 1687 LOG_ERROR_OR_EXIT(log, cert, 0, 0); 1688 } 1689 } 1690 } 1691 1692 done: 1693 if (log && log->head) { 1694 return SECFailure; 1695 } 1696 return (SECSuccess); 1697 1698 loser: 1699 rv = SECFailure; 1700 1701 return (rv); 1702 } 1703 1704 /* 1705 * verify a certificate by checking if its valid and that we 1706 * trust the issuer. Verify time against now. 1707 */ 1708 SECStatus 1709 CERT_VerifyCertificateNow(CERTCertDBHandle *handle, CERTCertificate *cert, 1710 PRBool checkSig, SECCertificateUsage requiredUsages, 1711 void *wincx, SECCertificateUsage *returnedUsages) 1712 { 1713 return (CERT_VerifyCertificate(handle, cert, checkSig, 1714 requiredUsages, PR_Now(), wincx, NULL, returnedUsages)); 1715 } 1716 1717 /* obsolete, do not use for new code */ 1718 SECStatus 1719 CERT_VerifyCertNow(CERTCertDBHandle *handle, CERTCertificate *cert, 1720 PRBool checkSig, SECCertUsage certUsage, void *wincx) 1721 { 1722 return (CERT_VerifyCert(handle, cert, checkSig, 1723 certUsage, PR_Now(), wincx, NULL)); 1724 } 1725 1726 /* [ FROM pcertdb.c ] */ 1727 /* 1728 * Supported usage values and types: 1729 * certUsageSSLClient 1730 * certUsageSSLServer 1731 * certUsageSSLServerWithStepUp 1732 * certUsageIPsec 1733 * certUsageEmailSigner 1734 * certUsageEmailRecipient 1735 * certUsageObjectSigner 1736 */ 1737 1738 CERTCertificate * 1739 CERT_FindMatchingCert(CERTCertDBHandle *handle, SECItem *derName, 1740 CERTCertOwner owner, SECCertUsage usage, 1741 PRBool preferTrusted, PRTime validTime, PRBool validOnly) 1742 { 1743 CERTCertList *certList = NULL; 1744 CERTCertificate *cert = NULL; 1745 CERTCertTrust certTrust; 1746 unsigned int requiredTrustFlags; 1747 SECTrustType requiredTrustType; 1748 unsigned int flags; 1749 1750 PRBool lookingForCA = PR_FALSE; 1751 SECStatus rv; 1752 CERTCertListNode *node; 1753 CERTCertificate *saveUntrustedCA = NULL; 1754 1755 /* if preferTrusted is set, must be a CA cert */ 1756 PORT_Assert(!(preferTrusted && (owner != certOwnerCA))); 1757 1758 if (owner == certOwnerCA) { 1759 lookingForCA = PR_TRUE; 1760 if (preferTrusted) { 1761 rv = CERT_TrustFlagsForCACertUsage(usage, &requiredTrustFlags, 1762 &requiredTrustType); 1763 if (rv != SECSuccess) { 1764 goto loser; 1765 } 1766 requiredTrustFlags |= CERTDB_VALID_CA; 1767 } 1768 } 1769 1770 certList = CERT_CreateSubjectCertList(NULL, handle, derName, validTime, 1771 validOnly); 1772 if (certList != NULL) { 1773 rv = CERT_FilterCertListByUsage(certList, usage, lookingForCA); 1774 if (rv != SECSuccess) { 1775 goto loser; 1776 } 1777 1778 node = CERT_LIST_HEAD(certList); 1779 1780 while (!CERT_LIST_END(node, certList)) { 1781 cert = node->cert; 1782 1783 /* looking for a trusted CA cert */ 1784 if ((owner == certOwnerCA) && preferTrusted && 1785 (requiredTrustType != trustTypeNone)) { 1786 1787 if (CERT_GetCertTrust(cert, &certTrust) != SECSuccess) { 1788 flags = 0; 1789 } else { 1790 flags = SEC_GET_TRUST_FLAGS(&certTrust, requiredTrustType); 1791 } 1792 1793 if ((flags & requiredTrustFlags) != requiredTrustFlags) { 1794 /* cert is not trusted */ 1795 /* if this is the first cert to get this far, then save 1796 * it, so we can use it if we can't find a trusted one 1797 */ 1798 if (saveUntrustedCA == NULL) { 1799 saveUntrustedCA = cert; 1800 } 1801 goto endloop; 1802 } 1803 } 1804 /* if we got this far, then this cert meets all criteria */ 1805 break; 1806 1807 endloop: 1808 node = CERT_LIST_NEXT(node); 1809 cert = NULL; 1810 } 1811 1812 /* use the saved one if we have it */ 1813 if (cert == NULL) { 1814 cert = saveUntrustedCA; 1815 } 1816 1817 /* if we found one then bump the ref count before freeing the list */ 1818 if (cert != NULL) { 1819 /* bump the ref count */ 1820 cert = CERT_DupCertificate(cert); 1821 } 1822 1823 CERT_DestroyCertList(certList); 1824 } 1825 1826 return (cert); 1827 1828 loser: 1829 if (certList != NULL) { 1830 CERT_DestroyCertList(certList); 1831 } 1832 1833 return (NULL); 1834 } 1835 1836 /* [ From certdb.c ] */ 1837 /* 1838 * Filter a list of certificates, removing those certs that do not have 1839 * one of the named CA certs somewhere in their cert chain. 1840 * 1841 * "certList" - the list of certificates to filter 1842 * "nCANames" - number of CA names 1843 * "caNames" - array of CA names in string(rfc 1485) form 1844 * "usage" - what use the certs are for, this is used when 1845 * selecting CA certs 1846 */ 1847 SECStatus 1848 CERT_FilterCertListByCANames(CERTCertList *certList, int nCANames, 1849 char **caNames, SECCertUsage usage) 1850 { 1851 CERTCertificate *issuerCert = NULL; 1852 CERTCertificate *subjectCert; 1853 CERTCertListNode *node, *freenode; 1854 CERTCertificate *cert; 1855 int n; 1856 char **names; 1857 PRBool found; 1858 PRTime time; 1859 1860 if (nCANames <= 0) { 1861 return (SECSuccess); 1862 } 1863 1864 time = PR_Now(); 1865 1866 node = CERT_LIST_HEAD(certList); 1867 1868 while (!CERT_LIST_END(node, certList)) { 1869 cert = node->cert; 1870 1871 subjectCert = CERT_DupCertificate(cert); 1872 1873 /* traverse the CA certs for this cert */ 1874 found = PR_FALSE; 1875 while (subjectCert != NULL) { 1876 n = nCANames; 1877 names = caNames; 1878 1879 if (subjectCert->issuerName != NULL) { 1880 while (n > 0) { 1881 if (PORT_Strcmp(*names, subjectCert->issuerName) == 0) { 1882 found = PR_TRUE; 1883 break; 1884 } 1885 1886 n--; 1887 names++; 1888 } 1889 } 1890 1891 if (found) { 1892 break; 1893 } 1894 1895 issuerCert = CERT_FindCertIssuer(subjectCert, time, usage); 1896 if (issuerCert == subjectCert) { 1897 CERT_DestroyCertificate(issuerCert); 1898 issuerCert = NULL; 1899 break; 1900 } 1901 CERT_DestroyCertificate(subjectCert); 1902 subjectCert = issuerCert; 1903 } 1904 CERT_DestroyCertificate(subjectCert); 1905 if (!found) { 1906 /* CA was not found, so remove this cert from the list */ 1907 freenode = node; 1908 node = CERT_LIST_NEXT(node); 1909 CERT_RemoveCertListNode(freenode); 1910 } else { 1911 /* CA was found, so leave it in the list */ 1912 node = CERT_LIST_NEXT(node); 1913 } 1914 } 1915 1916 return (SECSuccess); 1917 } 1918 1919 /* 1920 * Given a certificate, return a string containing the nickname, and possibly 1921 * one of the validity strings, based on the current validity state of the 1922 * certificate. 1923 * 1924 * "arena" - arena to allocate returned string from. If NULL, then heap 1925 * is used. 1926 * "cert" - the cert to get nickname from 1927 * "expiredString" - the string to append to the nickname if the cert is 1928 * expired. 1929 * "notYetGoodString" - the string to append to the nickname if the cert is 1930 * not yet good. 1931 */ 1932 char * 1933 CERT_GetCertNicknameWithValidity(PLArenaPool *arena, CERTCertificate *cert, 1934 char *expiredString, char *notYetGoodString) 1935 { 1936 SECCertTimeValidity validity; 1937 char *nickname = NULL, *tmpstr = NULL; 1938 const char *srcNickname = cert->nickname; 1939 if (!srcNickname) { 1940 srcNickname = "{???}"; 1941 } 1942 1943 validity = CERT_CheckCertValidTimes(cert, PR_Now(), PR_FALSE); 1944 1945 /* if the cert is good, then just use the nickname directly */ 1946 if (validity == secCertTimeValid) { 1947 if (arena == NULL) { 1948 nickname = PORT_Strdup(srcNickname); 1949 } else { 1950 nickname = PORT_ArenaStrdup(arena, srcNickname); 1951 } 1952 1953 if (nickname == NULL) { 1954 goto loser; 1955 } 1956 } else { 1957 1958 /* if the cert is not valid, then tack one of the strings on the 1959 * end 1960 */ 1961 if (validity == secCertTimeExpired) { 1962 tmpstr = PR_smprintf("%s%s", srcNickname, 1963 expiredString); 1964 } else if (validity == secCertTimeNotValidYet) { 1965 /* not yet valid */ 1966 tmpstr = PR_smprintf("%s%s", srcNickname, 1967 notYetGoodString); 1968 } else { 1969 /* undetermined */ 1970 tmpstr = PR_smprintf("%s", 1971 "(NULL) (Validity Unknown)"); 1972 } 1973 1974 if (tmpstr == NULL) { 1975 goto loser; 1976 } 1977 1978 if (arena) { 1979 /* copy the string into the arena and free the malloc'd one */ 1980 nickname = PORT_ArenaStrdup(arena, tmpstr); 1981 PORT_Free(tmpstr); 1982 } else { 1983 nickname = tmpstr; 1984 } 1985 if (nickname == NULL) { 1986 goto loser; 1987 } 1988 } 1989 return (nickname); 1990 1991 loser: 1992 return (NULL); 1993 } 1994 1995 /* 1996 * Collect the nicknames from all certs in a CertList. If the cert is not 1997 * valid, append a string to that nickname. 1998 * 1999 * "certList" - the list of certificates 2000 * "expiredString" - the string to append to the nickname of any expired cert 2001 * "notYetGoodString" - the string to append to the nickname of any cert 2002 * that is not yet valid 2003 */ 2004 CERTCertNicknames * 2005 CERT_NicknameStringsFromCertList(CERTCertList *certList, char *expiredString, 2006 char *notYetGoodString) 2007 { 2008 CERTCertNicknames *names; 2009 PLArenaPool *arena; 2010 CERTCertListNode *node; 2011 char **nn; 2012 2013 /* allocate an arena */ 2014 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 2015 if (arena == NULL) { 2016 return (NULL); 2017 } 2018 2019 /* allocate the structure */ 2020 names = PORT_ArenaAlloc(arena, sizeof(CERTCertNicknames)); 2021 if (names == NULL) { 2022 goto loser; 2023 } 2024 2025 /* init the structure */ 2026 names->arena = arena; 2027 names->head = NULL; 2028 names->numnicknames = 0; 2029 names->nicknames = NULL; 2030 names->totallen = 0; 2031 2032 /* count the certs in the list */ 2033 node = CERT_LIST_HEAD(certList); 2034 while (!CERT_LIST_END(node, certList)) { 2035 names->numnicknames++; 2036 node = CERT_LIST_NEXT(node); 2037 } 2038 2039 /* allocate nicknames array */ 2040 names->nicknames = PORT_ArenaAlloc(arena, 2041 sizeof(char *) * names->numnicknames); 2042 if (names->nicknames == NULL) { 2043 goto loser; 2044 } 2045 2046 /* just in case printf can't deal with null strings */ 2047 if (expiredString == NULL) { 2048 expiredString = ""; 2049 } 2050 2051 if (notYetGoodString == NULL) { 2052 notYetGoodString = ""; 2053 } 2054 2055 /* traverse the list of certs and collect the nicknames */ 2056 nn = names->nicknames; 2057 node = CERT_LIST_HEAD(certList); 2058 while (!CERT_LIST_END(node, certList)) { 2059 *nn = CERT_GetCertNicknameWithValidity(arena, node->cert, 2060 expiredString, 2061 notYetGoodString); 2062 if (*nn == NULL) { 2063 goto loser; 2064 } 2065 2066 names->totallen += PORT_Strlen(*nn); 2067 2068 nn++; 2069 node = CERT_LIST_NEXT(node); 2070 } 2071 2072 return (names); 2073 2074 loser: 2075 PORT_FreeArena(arena, PR_FALSE); 2076 return (NULL); 2077 } 2078 2079 /* 2080 * Extract the nickname from a nickmake string that may have either 2081 * expiredString or notYetGoodString appended. 2082 * 2083 * Args: 2084 * "namestring" - the string containing the nickname, and possibly 2085 * one of the validity label strings 2086 * "expiredString" - the expired validity label string 2087 * "notYetGoodString" - the not yet good validity label string 2088 * 2089 * Returns the raw nickname 2090 */ 2091 char * 2092 CERT_ExtractNicknameString(char *namestring, char *expiredString, 2093 char *notYetGoodString) 2094 { 2095 int explen, nyglen, namelen; 2096 int retlen; 2097 char *retstr; 2098 2099 namelen = PORT_Strlen(namestring); 2100 explen = PORT_Strlen(expiredString); 2101 nyglen = PORT_Strlen(notYetGoodString); 2102 2103 if (namelen > explen) { 2104 if (PORT_Strcmp(expiredString, &namestring[namelen - explen]) == 0) { 2105 retlen = namelen - explen; 2106 retstr = (char *)PORT_Alloc(retlen + 1); 2107 if (retstr == NULL) { 2108 goto loser; 2109 } 2110 2111 PORT_Memcpy(retstr, namestring, retlen); 2112 retstr[retlen] = '\0'; 2113 goto done; 2114 } 2115 } 2116 2117 if (namelen > nyglen) { 2118 if (PORT_Strcmp(notYetGoodString, &namestring[namelen - nyglen]) == 0) { 2119 retlen = namelen - nyglen; 2120 retstr = (char *)PORT_Alloc(retlen + 1); 2121 if (retstr == NULL) { 2122 goto loser; 2123 } 2124 2125 PORT_Memcpy(retstr, namestring, retlen); 2126 retstr[retlen] = '\0'; 2127 goto done; 2128 } 2129 } 2130 2131 /* if name string is shorter than either invalid string, then it must 2132 * be a raw nickname 2133 */ 2134 retstr = PORT_Strdup(namestring); 2135 2136 done: 2137 return (retstr); 2138 2139 loser: 2140 return (NULL); 2141 } 2142 2143 CERTCertList * 2144 CERT_GetCertChainFromCert(CERTCertificate *cert, PRTime time, SECCertUsage usage) 2145 { 2146 CERTCertList *chain = NULL; 2147 int count = 0; 2148 2149 if (NULL == cert) { 2150 return NULL; 2151 } 2152 2153 cert = CERT_DupCertificate(cert); 2154 if (NULL == cert) { 2155 PORT_SetError(SEC_ERROR_NO_MEMORY); 2156 return NULL; 2157 } 2158 2159 chain = CERT_NewCertList(); 2160 if (NULL == chain) { 2161 CERT_DestroyCertificate(cert); 2162 PORT_SetError(SEC_ERROR_NO_MEMORY); 2163 return NULL; 2164 } 2165 2166 while (cert != NULL && ++count <= CERT_MAX_CERT_CHAIN) { 2167 if (SECSuccess != CERT_AddCertToListTail(chain, cert)) { 2168 /* return partial chain */ 2169 CERT_DestroyCertificate(cert); 2170 PORT_SetError(SEC_ERROR_NO_MEMORY); 2171 return chain; 2172 } 2173 2174 if (cert->isRoot) { 2175 /* return complete chain */ 2176 return chain; 2177 } 2178 2179 cert = CERT_FindCertIssuer(cert, time, usage); 2180 } 2181 2182 /* return partial chain */ 2183 CERT_DestroyCertificate(cert); 2184 PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER); 2185 return chain; 2186 }