certificate.c (31987B)
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 #ifndef NSSPKI_H 6 #include "nsspki.h" 7 #endif /* NSSPKI_H */ 8 9 #ifndef PKIT_H 10 #include "pkit.h" 11 #endif /* PKIT_H */ 12 13 #ifndef PKIM_H 14 #include "pkim.h" 15 #endif /* PKIM_H */ 16 17 #ifndef DEV_H 18 #include "dev.h" 19 #endif /* DEV_H */ 20 21 #include "pkistore.h" 22 23 #include "pki3hack.h" 24 #include "pk11func.h" 25 #include "hasht.h" 26 27 #ifndef BASE_H 28 #include "base.h" 29 #endif /* BASE_H */ 30 31 extern const NSSError NSS_ERROR_NOT_FOUND; 32 33 /* Creates a certificate from a base object */ 34 NSS_IMPLEMENT NSSCertificate * 35 nssCertificate_Create( 36 nssPKIObject *object) 37 { 38 PRStatus status; 39 NSSCertificate *rvCert; 40 nssArenaMark *mark; 41 NSSArena *arena = object->arena; 42 PR_ASSERT(object->instances != NULL && object->numInstances > 0); 43 PR_ASSERT(object->lockType == nssPKIMonitor); 44 mark = nssArena_Mark(arena); 45 rvCert = nss_ZNEW(arena, NSSCertificate); 46 if (!rvCert) { 47 return (NSSCertificate *)NULL; 48 } 49 rvCert->object = *object; 50 /* XXX should choose instance based on some criteria */ 51 status = nssCryptokiCertificate_GetAttributes(object->instances[0], 52 NULL, /* XXX sessionOpt */ 53 arena, 54 &rvCert->type, 55 &rvCert->id, 56 &rvCert->encoding, 57 &rvCert->issuer, 58 &rvCert->serial, 59 &rvCert->subject); 60 if (status != PR_SUCCESS || 61 !rvCert->encoding.data || 62 !rvCert->encoding.size || 63 !rvCert->issuer.data || 64 !rvCert->issuer.size || 65 !rvCert->serial.data || 66 !rvCert->serial.size) { 67 if (mark) 68 nssArena_Release(arena, mark); 69 return (NSSCertificate *)NULL; 70 } 71 if (mark) 72 nssArena_Unmark(arena, mark); 73 return rvCert; 74 } 75 76 NSS_IMPLEMENT NSSCertificate * 77 nssCertificate_AddRef( 78 NSSCertificate *c) 79 { 80 if (c) { 81 nssPKIObject_AddRef(&c->object); 82 } 83 return c; 84 } 85 86 NSS_IMPLEMENT PRStatus 87 nssCertificate_Destroy( 88 NSSCertificate *c) 89 { 90 nssCertificateStoreTrace lockTrace = { NULL, NULL, PR_FALSE, PR_FALSE }; 91 nssCertificateStoreTrace unlockTrace = { NULL, NULL, PR_FALSE, PR_FALSE }; 92 93 if (c) { 94 PRUint32 i; 95 nssDecodedCert *dc = c->decoding; 96 NSSTrustDomain *td = STAN_GetDefaultTrustDomain(); 97 NSSCryptoContext *cc = c->object.cryptoContext; 98 99 PR_ASSERT(c->object.refCount > 0); 100 101 /* --- LOCK storage --- */ 102 if (cc) { 103 nssCertificateStore_Lock(cc->certStore, &lockTrace); 104 } else { 105 nssTrustDomain_LockCertCache(td); 106 } 107 if (PR_ATOMIC_DECREMENT(&c->object.refCount) == 0) { 108 /* --- remove cert and UNLOCK storage --- */ 109 if (cc) { 110 nssCertificateStore_RemoveCertLOCKED(cc->certStore, c); 111 nssCertificateStore_Unlock(cc->certStore, &lockTrace, 112 &unlockTrace); 113 } else { 114 nssTrustDomain_RemoveCertFromCacheLOCKED(td, c); 115 nssTrustDomain_UnlockCertCache(td); 116 } 117 /* free cert data */ 118 for (i = 0; i < c->object.numInstances; i++) { 119 nssCryptokiObject_Destroy(c->object.instances[i]); 120 } 121 nssPKIObject_DestroyLock(&c->object); 122 nssArena_Destroy(c->object.arena); 123 nssDecodedCert_Destroy(dc); 124 } else { 125 /* --- UNLOCK storage --- */ 126 if (cc) { 127 nssCertificateStore_Unlock(cc->certStore, 128 &lockTrace, 129 &unlockTrace); 130 } else { 131 nssTrustDomain_UnlockCertCache(td); 132 } 133 } 134 } 135 return PR_SUCCESS; 136 } 137 138 NSS_IMPLEMENT PRStatus 139 NSSCertificate_Destroy(NSSCertificate *c) 140 { 141 return nssCertificate_Destroy(c); 142 } 143 144 NSS_IMPLEMENT NSSDER * 145 nssCertificate_GetEncoding(NSSCertificate *c) 146 { 147 if (c->encoding.size > 0 && c->encoding.data) { 148 return &c->encoding; 149 } else { 150 return (NSSDER *)NULL; 151 } 152 } 153 154 NSS_IMPLEMENT NSSDER * 155 nssCertificate_GetIssuer(NSSCertificate *c) 156 { 157 if (c->issuer.size > 0 && c->issuer.data) { 158 return &c->issuer; 159 } else { 160 return (NSSDER *)NULL; 161 } 162 } 163 164 NSS_IMPLEMENT NSSDER * 165 nssCertificate_GetSerialNumber(NSSCertificate *c) 166 { 167 if (c->serial.size > 0 && c->serial.data) { 168 return &c->serial; 169 } else { 170 return (NSSDER *)NULL; 171 } 172 } 173 174 NSS_IMPLEMENT NSSDER * 175 nssCertificate_GetSubject(NSSCertificate *c) 176 { 177 if (c->subject.size > 0 && c->subject.data) { 178 return &c->subject; 179 } else { 180 return (NSSDER *)NULL; 181 } 182 } 183 184 /* Returns a copy, Caller must free using nss_ZFreeIf */ 185 NSS_IMPLEMENT NSSUTF8 * 186 nssCertificate_GetNickname( 187 NSSCertificate *c, 188 NSSToken *tokenOpt) 189 { 190 return nssPKIObject_GetNicknameForToken(&c->object, tokenOpt); 191 } 192 193 NSS_IMPLEMENT NSSASCII7 * 194 nssCertificate_GetEmailAddress(NSSCertificate *c) 195 { 196 return c->email; 197 } 198 199 NSS_IMPLEMENT PRStatus 200 NSSCertificate_DeleteStoredObject( 201 NSSCertificate *c, 202 NSSCallback *uhh) 203 { 204 return nssPKIObject_DeleteStoredObject(&c->object, uhh, PR_TRUE); 205 } 206 207 NSS_IMPLEMENT PRStatus 208 NSSCertificate_Validate( 209 NSSCertificate *c, 210 NSSTime *timeOpt, /* NULL for "now" */ 211 NSSUsage *usage, 212 NSSPolicies *policiesOpt /* NULL for none */ 213 ) 214 { 215 nss_SetError(NSS_ERROR_NOT_FOUND); 216 return PR_FAILURE; 217 } 218 219 NSS_IMPLEMENT void ** /* void *[] */ 220 NSSCertificate_ValidateCompletely( 221 NSSCertificate *c, 222 NSSTime *timeOpt, /* NULL for "now" */ 223 NSSUsage *usage, 224 NSSPolicies *policiesOpt, /* NULL for none */ 225 void **rvOpt, /* NULL for allocate */ 226 PRUint32 rvLimit, /* zero for no limit */ 227 NSSArena *arenaOpt /* NULL for heap */ 228 ) 229 { 230 nss_SetError(NSS_ERROR_NOT_FOUND); 231 return NULL; 232 } 233 234 NSS_IMPLEMENT PRStatus 235 NSSCertificate_ValidateAndDiscoverUsagesAndPolicies( 236 NSSCertificate *c, 237 NSSTime **notBeforeOutOpt, 238 NSSTime **notAfterOutOpt, 239 void *allowedUsages, 240 void *disallowedUsages, 241 void *allowedPolicies, 242 void *disallowedPolicies, 243 /* more args.. work on this fgmr */ 244 NSSArena *arenaOpt) 245 { 246 nss_SetError(NSS_ERROR_NOT_FOUND); 247 return PR_FAILURE; 248 } 249 250 NSS_IMPLEMENT NSSDER * 251 NSSCertificate_Encode( 252 NSSCertificate *c, 253 NSSDER *rvOpt, 254 NSSArena *arenaOpt) 255 { 256 /* Item, DER, BER are all typedefs now... */ 257 return nssItem_Duplicate((NSSItem *)&c->encoding, arenaOpt, rvOpt); 258 } 259 260 NSS_IMPLEMENT nssDecodedCert * 261 nssCertificate_GetDecoding( 262 NSSCertificate *c) 263 { 264 nssDecodedCert *deco = NULL; 265 if (c->type == NSSCertificateType_PKIX) { 266 (void)STAN_GetCERTCertificate(c); 267 } 268 nssPKIObject_Lock(&c->object); 269 if (!c->decoding) { 270 deco = nssDecodedCert_Create(NULL, &c->encoding, c->type); 271 PORT_Assert(!c->decoding); 272 c->decoding = deco; 273 } else { 274 deco = c->decoding; 275 } 276 nssPKIObject_Unlock(&c->object); 277 return deco; 278 } 279 280 static NSSCertificate ** 281 filter_subject_certs_for_id( 282 NSSCertificate **subjectCerts, 283 void *id) 284 { 285 NSSCertificate **si; 286 nssDecodedCert *dcp; 287 int nextOpenSlot = 0; 288 int i; 289 nssCertIDMatch matchLevel = nssCertIDMatch_Unknown; 290 nssCertIDMatch match; 291 292 /* walk the subject certs */ 293 for (si = subjectCerts; *si; si++) { 294 dcp = nssCertificate_GetDecoding(*si); 295 if (!dcp) { 296 NSSCertificate_Destroy(*si); 297 continue; 298 } 299 match = dcp->matchIdentifier(dcp, id); 300 switch (match) { 301 case nssCertIDMatch_Yes: 302 if (matchLevel == nssCertIDMatch_Unknown) { 303 /* we have non-definitive matches, forget them */ 304 for (i = 0; i < nextOpenSlot; i++) { 305 NSSCertificate_Destroy(subjectCerts[i]); 306 subjectCerts[i] = NULL; 307 } 308 nextOpenSlot = 0; 309 /* only keep definitive matches from now on */ 310 matchLevel = nssCertIDMatch_Yes; 311 } 312 /* keep the cert */ 313 subjectCerts[nextOpenSlot++] = *si; 314 break; 315 case nssCertIDMatch_Unknown: 316 if (matchLevel == nssCertIDMatch_Unknown) { 317 /* only have non-definitive matches so far, keep it */ 318 subjectCerts[nextOpenSlot++] = *si; 319 break; 320 } 321 /* else fall through, we have a definitive match already */ 322 case nssCertIDMatch_No: 323 default: 324 NSSCertificate_Destroy(*si); 325 *si = NULL; 326 } 327 } 328 subjectCerts[nextOpenSlot] = NULL; 329 return subjectCerts; 330 } 331 332 static NSSCertificate ** 333 filter_certs_for_valid_issuers(NSSCertificate **certs) 334 { 335 NSSCertificate **cp; 336 nssDecodedCert *dcp; 337 int nextOpenSlot = 0; 338 339 for (cp = certs; *cp; cp++) { 340 dcp = nssCertificate_GetDecoding(*cp); 341 if (dcp && dcp->isValidIssuer(dcp)) { 342 certs[nextOpenSlot++] = *cp; 343 } else { 344 NSSCertificate_Destroy(*cp); 345 } 346 } 347 certs[nextOpenSlot] = NULL; 348 return certs; 349 } 350 351 static NSSCertificate * 352 find_cert_issuer( 353 NSSCertificate *c, 354 NSSTime *timeOpt, 355 NSSUsage *usage, 356 NSSPolicies *policiesOpt, 357 NSSTrustDomain *td, 358 NSSCryptoContext *cc) 359 { 360 NSSArena *arena; 361 NSSCertificate **certs = NULL; 362 NSSCertificate **ccIssuers = NULL; 363 NSSCertificate **tdIssuers = NULL; 364 NSSCertificate *issuer = NULL; 365 366 if (!cc) 367 cc = c->object.cryptoContext; 368 if (!td) 369 td = NSSCertificate_GetTrustDomain(c); 370 arena = nssArena_Create(); 371 if (!arena) { 372 return (NSSCertificate *)NULL; 373 } 374 if (cc) { 375 ccIssuers = nssCryptoContext_FindCertificatesBySubject(cc, 376 &c->issuer, 377 NULL, 378 0, 379 arena); 380 } 381 if (td) 382 tdIssuers = nssTrustDomain_FindCertificatesBySubject(td, 383 &c->issuer, 384 NULL, 385 0, 386 arena); 387 certs = nssCertificateArray_Join(ccIssuers, tdIssuers); 388 if (certs) { 389 nssDecodedCert *dc = NULL; 390 void *issuerID = NULL; 391 dc = nssCertificate_GetDecoding(c); 392 if (dc) { 393 issuerID = dc->getIssuerIdentifier(dc); 394 } 395 /* XXX review based on CERT_FindCertIssuer 396 * this function is not using the authCertIssuer field as a fallback 397 * if authority key id does not exist 398 */ 399 if (issuerID) { 400 certs = filter_subject_certs_for_id(certs, issuerID); 401 } 402 certs = filter_certs_for_valid_issuers(certs); 403 issuer = nssCertificateArray_FindBestCertificate(certs, 404 timeOpt, 405 usage, 406 policiesOpt); 407 nssCertificateArray_Destroy(certs); 408 } 409 nssArena_Destroy(arena); 410 return issuer; 411 } 412 413 /* This function returns the built chain, as far as it gets, 414 ** even if/when it fails to find an issuer, and returns PR_FAILURE 415 */ 416 NSS_IMPLEMENT NSSCertificate ** 417 nssCertificate_BuildChain( 418 NSSCertificate *c, 419 NSSTime *timeOpt, 420 NSSUsage *usage, 421 NSSPolicies *policiesOpt, 422 NSSCertificate **rvOpt, 423 PRUint32 rvLimit, 424 NSSArena *arenaOpt, 425 PRStatus *statusOpt, 426 NSSTrustDomain *td, 427 NSSCryptoContext *cc) 428 { 429 NSSCertificate **rvChain = NULL; 430 NSSUsage issuerUsage = *usage; 431 nssPKIObjectCollection *collection = NULL; 432 PRUint32 rvCount = 0; 433 PRStatus st; 434 PRStatus ret = PR_SUCCESS; 435 436 if (!c || !cc || 437 (!td && (td = NSSCertificate_GetTrustDomain(c)) == NULL)) { 438 goto loser; 439 } 440 /* bump the usage up to CA level */ 441 issuerUsage.nss3lookingForCA = PR_TRUE; 442 collection = nssCertificateCollection_Create(td, NULL); 443 if (!collection) 444 goto loser; 445 st = nssPKIObjectCollection_AddObject(collection, (nssPKIObject *)c); 446 if (st != PR_SUCCESS) 447 goto loser; 448 for (rvCount = 1; (!rvLimit || rvCount < rvLimit); ++rvCount) { 449 CERTCertificate *cCert = STAN_GetCERTCertificate(c); 450 if (cCert->isRoot) { 451 /* not including the issuer of the self-signed cert, which is, 452 * of course, itself 453 */ 454 break; 455 } 456 c = find_cert_issuer(c, timeOpt, &issuerUsage, policiesOpt, td, cc); 457 if (!c) { 458 ret = PR_FAILURE; 459 break; 460 } 461 st = nssPKIObjectCollection_AddObject(collection, (nssPKIObject *)c); 462 nssCertificate_Destroy(c); /* collection has it */ 463 if (st != PR_SUCCESS) 464 goto loser; 465 } 466 rvChain = nssPKIObjectCollection_GetCertificates(collection, 467 rvOpt, 468 rvLimit, 469 arenaOpt); 470 if (rvChain) { 471 nssPKIObjectCollection_Destroy(collection); 472 if (statusOpt) 473 *statusOpt = ret; 474 if (ret != PR_SUCCESS) 475 nss_SetError(NSS_ERROR_CERTIFICATE_ISSUER_NOT_FOUND); 476 return rvChain; 477 } 478 479 loser: 480 if (collection) 481 nssPKIObjectCollection_Destroy(collection); 482 if (statusOpt) 483 *statusOpt = PR_FAILURE; 484 nss_SetError(NSS_ERROR_CERTIFICATE_ISSUER_NOT_FOUND); 485 return rvChain; 486 } 487 488 NSS_IMPLEMENT NSSCertificate ** 489 NSSCertificate_BuildChain( 490 NSSCertificate *c, 491 NSSTime *timeOpt, 492 NSSUsage *usage, 493 NSSPolicies *policiesOpt, 494 NSSCertificate **rvOpt, 495 PRUint32 rvLimit, /* zero for no limit */ 496 NSSArena *arenaOpt, 497 PRStatus *statusOpt, 498 NSSTrustDomain *td, 499 NSSCryptoContext *cc) 500 { 501 return nssCertificate_BuildChain(c, timeOpt, usage, policiesOpt, 502 rvOpt, rvLimit, arenaOpt, statusOpt, 503 td, cc); 504 } 505 506 NSS_IMPLEMENT NSSCryptoContext * 507 nssCertificate_GetCryptoContext(NSSCertificate *c) 508 { 509 return c->object.cryptoContext; 510 } 511 512 NSS_IMPLEMENT NSSTrustDomain * 513 nssCertificate_GetTrustDomain(NSSCertificate *c) 514 { 515 return c->object.trustDomain; 516 } 517 518 NSS_IMPLEMENT NSSTrustDomain * 519 NSSCertificate_GetTrustDomain(NSSCertificate *c) 520 { 521 return nssCertificate_GetTrustDomain(c); 522 } 523 524 NSS_IMPLEMENT NSSToken * 525 NSSCertificate_GetToken( 526 NSSCertificate *c, 527 PRStatus *statusOpt) 528 { 529 return (NSSToken *)NULL; 530 } 531 532 NSS_IMPLEMENT NSSSlot * 533 NSSCertificate_GetSlot( 534 NSSCertificate *c, 535 PRStatus *statusOpt) 536 { 537 return (NSSSlot *)NULL; 538 } 539 540 NSS_IMPLEMENT NSSModule * 541 NSSCertificate_GetModule( 542 NSSCertificate *c, 543 PRStatus *statusOpt) 544 { 545 return (NSSModule *)NULL; 546 } 547 548 NSS_IMPLEMENT NSSItem * 549 NSSCertificate_Encrypt( 550 NSSCertificate *c, 551 NSSAlgorithmAndParameters *apOpt, 552 NSSItem *data, 553 NSSTime *timeOpt, 554 NSSUsage *usage, 555 NSSPolicies *policiesOpt, 556 NSSCallback *uhh, 557 NSSItem *rvOpt, 558 NSSArena *arenaOpt) 559 { 560 nss_SetError(NSS_ERROR_NOT_FOUND); 561 return NULL; 562 } 563 564 NSS_IMPLEMENT PRStatus 565 NSSCertificate_Verify( 566 NSSCertificate *c, 567 NSSAlgorithmAndParameters *apOpt, 568 NSSItem *data, 569 NSSItem *signature, 570 NSSTime *timeOpt, 571 NSSUsage *usage, 572 NSSPolicies *policiesOpt, 573 NSSCallback *uhh) 574 { 575 nss_SetError(NSS_ERROR_NOT_FOUND); 576 return PR_FAILURE; 577 } 578 579 NSS_IMPLEMENT NSSItem * 580 NSSCertificate_VerifyRecover( 581 NSSCertificate *c, 582 NSSAlgorithmAndParameters *apOpt, 583 NSSItem *signature, 584 NSSTime *timeOpt, 585 NSSUsage *usage, 586 NSSPolicies *policiesOpt, 587 NSSCallback *uhh, 588 NSSItem *rvOpt, 589 NSSArena *arenaOpt) 590 { 591 nss_SetError(NSS_ERROR_NOT_FOUND); 592 return NULL; 593 } 594 595 NSS_IMPLEMENT NSSItem * 596 NSSCertificate_WrapSymmetricKey( 597 NSSCertificate *c, 598 NSSAlgorithmAndParameters *apOpt, 599 NSSSymmetricKey *keyToWrap, 600 NSSTime *timeOpt, 601 NSSUsage *usage, 602 NSSPolicies *policiesOpt, 603 NSSCallback *uhh, 604 NSSItem *rvOpt, 605 NSSArena *arenaOpt) 606 { 607 nss_SetError(NSS_ERROR_NOT_FOUND); 608 return NULL; 609 } 610 611 NSS_IMPLEMENT NSSCryptoContext * 612 NSSCertificate_CreateCryptoContext( 613 NSSCertificate *c, 614 NSSAlgorithmAndParameters *apOpt, 615 NSSTime *timeOpt, 616 NSSUsage *usage, 617 NSSPolicies *policiesOpt, 618 NSSCallback *uhh) 619 { 620 nss_SetError(NSS_ERROR_NOT_FOUND); 621 return NULL; 622 } 623 624 NSS_IMPLEMENT NSSPublicKey * 625 NSSCertificate_GetPublicKey( 626 NSSCertificate *c) 627 { 628 #if 0 629 CK_ATTRIBUTE pubktemplate[] = { 630 { CKA_CLASS, NULL, 0 }, 631 { CKA_ID, NULL, 0 }, 632 { CKA_SUBJECT, NULL, 0 } 633 }; 634 PRStatus nssrv; 635 CK_ULONG count = sizeof(pubktemplate) / sizeof(pubktemplate[0]); 636 NSS_CK_SET_ATTRIBUTE_ITEM(pubktemplate, 0, &g_ck_class_pubkey); 637 if (c->id.size > 0) { 638 /* CKA_ID */ 639 NSS_CK_ITEM_TO_ATTRIBUTE(&c->id, &pubktemplate[1]); 640 } else { 641 /* failure, yes? */ 642 return (NSSPublicKey *)NULL; 643 } 644 if (c->subject.size > 0) { 645 /* CKA_SUBJECT */ 646 NSS_CK_ITEM_TO_ATTRIBUTE(&c->subject, &pubktemplate[2]); 647 } else { 648 /* failure, yes? */ 649 return (NSSPublicKey *)NULL; 650 } 651 /* Try the cert's token first */ 652 if (c->token) { 653 nssrv = nssToken_FindObjectByTemplate(c->token, pubktemplate, count); 654 } 655 #endif 656 /* Try all other key tokens */ 657 return (NSSPublicKey *)NULL; 658 } 659 660 NSS_IMPLEMENT NSSPrivateKey * 661 NSSCertificate_FindPrivateKey( 662 NSSCertificate *c, 663 NSSCallback *uhh) 664 { 665 nss_SetError(NSS_ERROR_NOT_FOUND); 666 return NULL; 667 } 668 669 NSS_IMPLEMENT PRBool 670 NSSCertificate_IsPrivateKeyAvailable( 671 NSSCertificate *c, 672 NSSCallback *uhh, 673 PRStatus *statusOpt) 674 { 675 PRBool isUser = PR_FALSE; 676 nssCryptokiObject **ip; 677 nssCryptokiObject **instances = nssPKIObject_GetInstances(&c->object); 678 if (!instances) { 679 return PR_FALSE; 680 } 681 for (ip = instances; *ip; ip++) { 682 nssCryptokiObject *instance = *ip; 683 if (nssToken_IsPrivateKeyAvailable(instance->token, c, instance)) { 684 isUser = PR_TRUE; 685 } 686 } 687 nssCryptokiObjectArray_Destroy(instances); 688 return isUser; 689 } 690 691 /* sort the subject cert list from newest to oldest */ 692 PRIntn 693 nssCertificate_SubjectListSort( 694 void *v1, 695 void *v2) 696 { 697 NSSCertificate *c1 = (NSSCertificate *)v1; 698 NSSCertificate *c2 = (NSSCertificate *)v2; 699 nssDecodedCert *dc1 = nssCertificate_GetDecoding(c1); 700 nssDecodedCert *dc2 = nssCertificate_GetDecoding(c2); 701 if (!dc1) { 702 return dc2 ? 1 : 0; 703 } else if (!dc2) { 704 return -1; 705 } else { 706 return dc1->isNewerThan(dc1, dc2) ? -1 : 1; 707 } 708 } 709 710 NSS_IMPLEMENT PRBool 711 NSSUserCertificate_IsStillPresent( 712 NSSUserCertificate *uc, 713 PRStatus *statusOpt) 714 { 715 nss_SetError(NSS_ERROR_NOT_FOUND); 716 return PR_FALSE; 717 } 718 719 NSS_IMPLEMENT NSSItem * 720 NSSUserCertificate_Decrypt( 721 NSSUserCertificate *uc, 722 NSSAlgorithmAndParameters *apOpt, 723 NSSItem *data, 724 NSSTime *timeOpt, 725 NSSUsage *usage, 726 NSSPolicies *policiesOpt, 727 NSSCallback *uhh, 728 NSSItem *rvOpt, 729 NSSArena *arenaOpt) 730 { 731 nss_SetError(NSS_ERROR_NOT_FOUND); 732 return NULL; 733 } 734 735 NSS_IMPLEMENT NSSItem * 736 NSSUserCertificate_Sign( 737 NSSUserCertificate *uc, 738 NSSAlgorithmAndParameters *apOpt, 739 NSSItem *data, 740 NSSTime *timeOpt, 741 NSSUsage *usage, 742 NSSPolicies *policiesOpt, 743 NSSCallback *uhh, 744 NSSItem *rvOpt, 745 NSSArena *arenaOpt) 746 { 747 nss_SetError(NSS_ERROR_NOT_FOUND); 748 return NULL; 749 } 750 751 NSS_IMPLEMENT NSSItem * 752 NSSUserCertificate_SignRecover( 753 NSSUserCertificate *uc, 754 NSSAlgorithmAndParameters *apOpt, 755 NSSItem *data, 756 NSSTime *timeOpt, 757 NSSUsage *usage, 758 NSSPolicies *policiesOpt, 759 NSSCallback *uhh, 760 NSSItem *rvOpt, 761 NSSArena *arenaOpt) 762 { 763 nss_SetError(NSS_ERROR_NOT_FOUND); 764 return NULL; 765 } 766 767 NSS_IMPLEMENT NSSSymmetricKey * 768 NSSUserCertificate_UnwrapSymmetricKey( 769 NSSUserCertificate *uc, 770 NSSAlgorithmAndParameters *apOpt, 771 NSSItem *wrappedKey, 772 NSSTime *timeOpt, 773 NSSUsage *usage, 774 NSSPolicies *policiesOpt, 775 NSSCallback *uhh, 776 NSSItem *rvOpt, 777 NSSArena *arenaOpt) 778 { 779 nss_SetError(NSS_ERROR_NOT_FOUND); 780 return NULL; 781 } 782 783 NSS_IMPLEMENT NSSSymmetricKey * 784 NSSUserCertificate_DeriveSymmetricKey( 785 NSSUserCertificate *uc, /* provides private key */ 786 NSSCertificate *c, /* provides public key */ 787 NSSAlgorithmAndParameters *apOpt, 788 NSSOID *target, 789 PRUint32 keySizeOpt, /* zero for best allowed */ 790 NSSOperations operations, 791 NSSCallback *uhh) 792 { 793 nss_SetError(NSS_ERROR_NOT_FOUND); 794 return NULL; 795 } 796 797 NSS_IMPLEMENT nssSMIMEProfile * 798 nssSMIMEProfile_Create( 799 NSSCertificate *cert, 800 NSSItem *profileTime, 801 NSSItem *profileData) 802 { 803 NSSArena *arena; 804 nssSMIMEProfile *rvProfile; 805 nssPKIObject *object; 806 NSSTrustDomain *td = nssCertificate_GetTrustDomain(cert); 807 NSSCryptoContext *cc = nssCertificate_GetCryptoContext(cert); 808 arena = nssArena_Create(); 809 if (!arena) { 810 return NULL; 811 } 812 object = nssPKIObject_Create(arena, NULL, td, cc, nssPKILock); 813 if (!object) { 814 goto loser; 815 } 816 rvProfile = nss_ZNEW(arena, nssSMIMEProfile); 817 if (!rvProfile) { 818 goto loser; 819 } 820 rvProfile->object = *object; 821 rvProfile->certificate = cert; 822 rvProfile->email = nssUTF8_Duplicate(cert->email, arena); 823 rvProfile->subject = nssItem_Duplicate(&cert->subject, arena, NULL); 824 if (profileTime) { 825 rvProfile->profileTime = nssItem_Duplicate(profileTime, arena, NULL); 826 } 827 if (profileData) { 828 rvProfile->profileData = nssItem_Duplicate(profileData, arena, NULL); 829 } 830 return rvProfile; 831 loser: 832 if (object) 833 nssPKIObject_Destroy(object); 834 else if (arena) 835 nssArena_Destroy(arena); 836 return (nssSMIMEProfile *)NULL; 837 } 838 839 /* execute a callback function on all members of a cert list */ 840 NSS_EXTERN PRStatus 841 nssCertificateList_DoCallback( 842 nssList *certList, 843 PRStatus (*callback)(NSSCertificate *c, void *arg), 844 void *arg) 845 { 846 nssListIterator *certs; 847 NSSCertificate *cert; 848 certs = nssList_CreateIterator(certList); 849 if (!certs) { 850 return PR_FAILURE; 851 } 852 for (cert = (NSSCertificate *)nssListIterator_Start(certs); 853 cert != (NSSCertificate *)NULL; 854 cert = (NSSCertificate *)nssListIterator_Next(certs)) { 855 (void)(*callback)(cert, arg); 856 } 857 nssListIterator_Finish(certs); 858 nssListIterator_Destroy(certs); 859 return PR_SUCCESS; 860 } 861 862 static PRStatus 863 add_ref_callback(NSSCertificate *c, void *a) 864 { 865 nssCertificate_AddRef(c); 866 return PR_SUCCESS; 867 } 868 869 NSS_IMPLEMENT void 870 nssCertificateList_AddReferences( 871 nssList *certList) 872 { 873 (void)nssCertificateList_DoCallback(certList, add_ref_callback, NULL); 874 } 875 876 /* 877 * Is this trust record safe to apply to all certs of the same issuer/SN 878 * independent of the cert matching the hash. This is only true is the trust 879 * is unknown or distrusted. In general this feature is only useful to 880 * explicitly distrusting certs. It is not safe to use to trust certs, so 881 * only allow unknown and untrusted trust types. 882 */ 883 PRBool 884 nssTrust_IsSafeToIgnoreCertHash(nssTrustLevel serverAuth, 885 nssTrustLevel clientAuth, nssTrustLevel codeSigning, 886 nssTrustLevel email, PRBool stepup) 887 { 888 /* step up is a trust type, if it's on, we must have a hash for the cert */ 889 if (stepup) { 890 return PR_FALSE; 891 } 892 if ((serverAuth != nssTrustLevel_Unknown) && 893 (serverAuth != nssTrustLevel_NotTrusted)) { 894 return PR_FALSE; 895 } 896 if ((clientAuth != nssTrustLevel_Unknown) && 897 (clientAuth != nssTrustLevel_NotTrusted)) { 898 return PR_FALSE; 899 } 900 if ((codeSigning != nssTrustLevel_Unknown) && 901 (codeSigning != nssTrustLevel_NotTrusted)) { 902 return PR_FALSE; 903 } 904 if ((email != nssTrustLevel_Unknown) && 905 (email != nssTrustLevel_NotTrusted)) { 906 return PR_FALSE; 907 } 908 /* record only has Unknown and Untrusted entries, ok to accept without a 909 * hash */ 910 return PR_TRUE; 911 } 912 913 /* verify that hash and mechanism matches certifcate. This function 914 * uses hashCache and hashCacheMech from the caller to allow us to 915 * use previous calculated hash values if they are the same */ 916 static PRBool 917 nssTrust_isValidHash(const NSSItem *hash, CK_MECHANISM_TYPE hashMech, 918 NSSItem *cert, NSSItem *hashCache, 919 CK_MECHANISM_TYPE *hashCacheMech) 920 { 921 if ((hashMech == CKM_INVALID_MECHANISM) || (hash->size == 0)) { 922 return PR_FALSE; 923 } 924 if (*hashCacheMech != hashMech) { 925 /* the cache doesn't have the correct mech, get a 926 * new hash for the cert */ 927 hashCache->size = HASH_LENGTH_MAX; 928 PRStatus ret = NSSAlgorithm_DigestBuf(hashMech, cert, hashCache); 929 if (ret != PR_SUCCESS) { 930 *hashCacheMech = CKM_INVALID_MECHANISM; 931 return PR_FALSE; 932 } 933 *hashCacheMech = hashMech; 934 } 935 return ((hash->size == hashCache->size) && (PORT_Memcmp(hash->data, 936 hashCache->data, 937 hash->size) == 0)); 938 } 939 940 NSS_IMPLEMENT NSSTrust * 941 nssTrust_Create( 942 nssPKIObject *object, 943 NSSItem *certData) 944 { 945 PRStatus status; 946 PRUint32 i; 947 PRUint32 lastTrustOrder, myTrustOrder; 948 unsigned char hashCacheBuf[HASH_LENGTH_MAX]; 949 unsigned char hashAttrBuf[HASH_LENGTH_MAX]; 950 NSSItem hashAttr = { hashAttrBuf, sizeof(hashAttrBuf) }; 951 NSSItem hashCache = { hashCacheBuf, sizeof(hashCacheBuf) }; 952 NSSTrust *rvt; 953 CK_MECHANISM_TYPE hashMech = CKM_INVALID_MECHANISM; 954 CK_MECHANISM_TYPE hashCacheMech = CKM_INVALID_MECHANISM; 955 nssCryptokiObject *instance; 956 nssTrustLevel serverAuth, clientAuth, codeSigning, emailProtection; 957 PRBool stepUp; 958 959 lastTrustOrder = 1 << 16; /* just make it big */ 960 PR_ASSERT(object->instances != NULL && object->numInstances > 0); 961 rvt = nss_ZNEW(object->arena, NSSTrust); 962 if (!rvt) { 963 return (NSSTrust *)NULL; 964 } 965 rvt->object = *object; 966 967 /* trust has to peek into the base object members */ 968 nssPKIObject_Lock(object); 969 for (i = 0; i < object->numInstances; i++) { 970 hashAttr.size = sizeof(hashAttrBuf); /* reset to allocated size */ 971 instance = object->instances[i]; 972 myTrustOrder = nssToken_GetTrustOrder(instance->token); 973 status = nssCryptokiTrust_GetAttributes(instance, NULL, 974 &hashAttr, 975 &hashMech, 976 &serverAuth, 977 &clientAuth, 978 &codeSigning, 979 &emailProtection, 980 &stepUp); 981 if (status != PR_SUCCESS) { 982 nssPKIObject_Unlock(object); 983 return (NSSTrust *)NULL; 984 } 985 /* if no hash is specified, then trust applies to all certs with 986 * this issuer/SN. NOTE: This is only true for entries that 987 * have distrust and unknown record */ 988 if (!( 989 /* we continue if there is no hash, and the trust type is 990 * safe to accept without a hash ... or ... */ 991 (((hashAttr.size == 0) || (hashMech == CKM_INVALID_MECHANISM)) && 992 nssTrust_IsSafeToIgnoreCertHash(serverAuth, clientAuth, 993 codeSigning, emailProtection, 994 stepUp)) || 995 /* we have a hash of the correct size, and it matches */ 996 nssTrust_isValidHash(&hashAttr, hashMech, certData, 997 &hashCache, &hashCacheMech))) { 998 999 nssPKIObject_Unlock(object); 1000 return (NSSTrust *)NULL; 1001 } 1002 if (rvt->serverAuth == nssTrustLevel_Unknown || 1003 myTrustOrder < lastTrustOrder) { 1004 rvt->serverAuth = serverAuth; 1005 } 1006 if (rvt->clientAuth == nssTrustLevel_Unknown || 1007 myTrustOrder < lastTrustOrder) { 1008 rvt->clientAuth = clientAuth; 1009 } 1010 if (rvt->emailProtection == nssTrustLevel_Unknown || 1011 myTrustOrder < lastTrustOrder) { 1012 rvt->emailProtection = emailProtection; 1013 } 1014 if (rvt->codeSigning == nssTrustLevel_Unknown || 1015 myTrustOrder < lastTrustOrder) { 1016 rvt->codeSigning = codeSigning; 1017 } 1018 rvt->stepUpApproved = stepUp; 1019 lastTrustOrder = myTrustOrder; 1020 } 1021 nssPKIObject_Unlock(object); 1022 return rvt; 1023 } 1024 1025 NSS_IMPLEMENT NSSTrust * 1026 nssTrust_AddRef(NSSTrust *trust) 1027 { 1028 if (trust) { 1029 nssPKIObject_AddRef(&trust->object); 1030 } 1031 return trust; 1032 } 1033 1034 NSS_IMPLEMENT PRStatus 1035 nssTrust_Destroy(NSSTrust *trust) 1036 { 1037 if (trust) { 1038 (void)nssPKIObject_Destroy(&trust->object); 1039 } 1040 return PR_SUCCESS; 1041 } 1042 1043 NSS_IMPLEMENT nssSMIMEProfile * 1044 nssSMIMEProfile_AddRef(nssSMIMEProfile *profile) 1045 { 1046 if (profile) { 1047 nssPKIObject_AddRef(&profile->object); 1048 } 1049 return profile; 1050 } 1051 1052 NSS_IMPLEMENT PRStatus 1053 nssSMIMEProfile_Destroy(nssSMIMEProfile *profile) 1054 { 1055 if (profile) { 1056 (void)nssPKIObject_Destroy(&profile->object); 1057 } 1058 return PR_SUCCESS; 1059 } 1060 1061 NSS_IMPLEMENT NSSCRL * 1062 nssCRL_Create(nssPKIObject *object) 1063 { 1064 PRStatus status; 1065 NSSCRL *rvCRL; 1066 NSSArena *arena = object->arena; 1067 PR_ASSERT(object->instances != NULL && object->numInstances > 0); 1068 rvCRL = nss_ZNEW(arena, NSSCRL); 1069 if (!rvCRL) { 1070 return (NSSCRL *)NULL; 1071 } 1072 rvCRL->object = *object; 1073 /* XXX should choose instance based on some criteria */ 1074 status = nssCryptokiCRL_GetAttributes(object->instances[0], 1075 NULL, /* XXX sessionOpt */ 1076 arena, 1077 &rvCRL->encoding, 1078 NULL, /* subject */ 1079 NULL, /* class */ 1080 &rvCRL->url, 1081 &rvCRL->isKRL); 1082 if (status != PR_SUCCESS) { 1083 if (!arena) { 1084 nssPKIObject_Destroy((nssPKIObject *)rvCRL); 1085 } 1086 return (NSSCRL *)NULL; 1087 } 1088 return rvCRL; 1089 } 1090 1091 NSS_IMPLEMENT NSSCRL * 1092 nssCRL_AddRef(NSSCRL *crl) 1093 { 1094 if (crl) { 1095 nssPKIObject_AddRef(&crl->object); 1096 } 1097 return crl; 1098 } 1099 1100 NSS_IMPLEMENT PRStatus 1101 nssCRL_Destroy(NSSCRL *crl) 1102 { 1103 if (crl) { 1104 (void)nssPKIObject_Destroy(&crl->object); 1105 } 1106 return PR_SUCCESS; 1107 } 1108 1109 NSS_IMPLEMENT PRStatus 1110 nssCRL_DeleteStoredObject( 1111 NSSCRL *crl, 1112 NSSCallback *uhh) 1113 { 1114 return nssPKIObject_DeleteStoredObject(&crl->object, uhh, PR_TRUE); 1115 } 1116 1117 NSS_IMPLEMENT NSSDER * 1118 nssCRL_GetEncoding(NSSCRL *crl) 1119 { 1120 if (crl && crl->encoding.data != NULL && crl->encoding.size > 0) { 1121 return &crl->encoding; 1122 } else { 1123 return (NSSDER *)NULL; 1124 } 1125 }