1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/lib/pki/certificate.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1172 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +#ifndef NSSPKI_H 1.9 +#include "nsspki.h" 1.10 +#endif /* NSSPKI_H */ 1.11 + 1.12 +#ifndef PKIT_H 1.13 +#include "pkit.h" 1.14 +#endif /* PKIT_H */ 1.15 + 1.16 +#ifndef PKIM_H 1.17 +#include "pkim.h" 1.18 +#endif /* PKIM_H */ 1.19 + 1.20 +#ifndef DEV_H 1.21 +#include "dev.h" 1.22 +#endif /* DEV_H */ 1.23 + 1.24 +#include "pkistore.h" 1.25 + 1.26 +#include "pki3hack.h" 1.27 +#include "pk11func.h" 1.28 +#include "hasht.h" 1.29 + 1.30 +#ifndef BASE_H 1.31 +#include "base.h" 1.32 +#endif /* BASE_H */ 1.33 + 1.34 +extern const NSSError NSS_ERROR_NOT_FOUND; 1.35 + 1.36 +/* Creates a certificate from a base object */ 1.37 +NSS_IMPLEMENT NSSCertificate * 1.38 +nssCertificate_Create ( 1.39 + nssPKIObject *object 1.40 +) 1.41 +{ 1.42 + PRStatus status; 1.43 + NSSCertificate *rvCert; 1.44 + nssArenaMark * mark; 1.45 + NSSArena *arena = object->arena; 1.46 + PR_ASSERT(object->instances != NULL && object->numInstances > 0); 1.47 + PR_ASSERT(object->lockType == nssPKIMonitor); 1.48 + mark = nssArena_Mark(arena); 1.49 + rvCert = nss_ZNEW(arena, NSSCertificate); 1.50 + if (!rvCert) { 1.51 + return (NSSCertificate *)NULL; 1.52 + } 1.53 + rvCert->object = *object; 1.54 + /* XXX should choose instance based on some criteria */ 1.55 + status = nssCryptokiCertificate_GetAttributes(object->instances[0], 1.56 + NULL, /* XXX sessionOpt */ 1.57 + arena, 1.58 + &rvCert->type, 1.59 + &rvCert->id, 1.60 + &rvCert->encoding, 1.61 + &rvCert->issuer, 1.62 + &rvCert->serial, 1.63 + &rvCert->subject); 1.64 + if (status != PR_SUCCESS || 1.65 + !rvCert->encoding.data || 1.66 + !rvCert->encoding.size || 1.67 + !rvCert->issuer.data || 1.68 + !rvCert->issuer.size || 1.69 + !rvCert->serial.data || 1.70 + !rvCert->serial.size) { 1.71 + if (mark) 1.72 + nssArena_Release(arena, mark); 1.73 + return (NSSCertificate *)NULL; 1.74 + } 1.75 + if (mark) 1.76 + nssArena_Unmark(arena, mark); 1.77 + return rvCert; 1.78 +} 1.79 + 1.80 +NSS_IMPLEMENT NSSCertificate * 1.81 +nssCertificate_AddRef ( 1.82 + NSSCertificate *c 1.83 +) 1.84 +{ 1.85 + if (c) { 1.86 + nssPKIObject_AddRef(&c->object); 1.87 + } 1.88 + return c; 1.89 +} 1.90 + 1.91 +NSS_IMPLEMENT PRStatus 1.92 +nssCertificate_Destroy ( 1.93 + NSSCertificate *c 1.94 +) 1.95 +{ 1.96 + nssCertificateStoreTrace lockTrace = {NULL, NULL, PR_FALSE, PR_FALSE}; 1.97 + nssCertificateStoreTrace unlockTrace = {NULL, NULL, PR_FALSE, PR_FALSE}; 1.98 + 1.99 + if (c) { 1.100 + PRUint32 i; 1.101 + nssDecodedCert *dc = c->decoding; 1.102 + NSSTrustDomain *td = STAN_GetDefaultTrustDomain(); 1.103 + NSSCryptoContext *cc = c->object.cryptoContext; 1.104 + 1.105 + PR_ASSERT(c->object.refCount > 0); 1.106 + 1.107 + /* --- LOCK storage --- */ 1.108 + if (cc) { 1.109 + nssCertificateStore_Lock(cc->certStore, &lockTrace); 1.110 + } else { 1.111 + nssTrustDomain_LockCertCache(td); 1.112 + } 1.113 + if (PR_ATOMIC_DECREMENT(&c->object.refCount) == 0) { 1.114 + /* --- remove cert and UNLOCK storage --- */ 1.115 + if (cc) { 1.116 + nssCertificateStore_RemoveCertLOCKED(cc->certStore, c); 1.117 + nssCertificateStore_Unlock(cc->certStore, &lockTrace, 1.118 + &unlockTrace); 1.119 + } else { 1.120 + nssTrustDomain_RemoveCertFromCacheLOCKED(td, c); 1.121 + nssTrustDomain_UnlockCertCache(td); 1.122 + } 1.123 + /* free cert data */ 1.124 + for (i=0; i<c->object.numInstances; i++) { 1.125 + nssCryptokiObject_Destroy(c->object.instances[i]); 1.126 + } 1.127 + nssPKIObject_DestroyLock(&c->object); 1.128 + nssArena_Destroy(c->object.arena); 1.129 + nssDecodedCert_Destroy(dc); 1.130 + } else { 1.131 + /* --- UNLOCK storage --- */ 1.132 + if (cc) { 1.133 + nssCertificateStore_Unlock(cc->certStore, 1.134 + &lockTrace, 1.135 + &unlockTrace); 1.136 + } else { 1.137 + nssTrustDomain_UnlockCertCache(td); 1.138 + } 1.139 + } 1.140 + } 1.141 + return PR_SUCCESS; 1.142 +} 1.143 + 1.144 +NSS_IMPLEMENT PRStatus 1.145 +NSSCertificate_Destroy ( 1.146 + NSSCertificate *c 1.147 +) 1.148 +{ 1.149 + return nssCertificate_Destroy(c); 1.150 +} 1.151 + 1.152 +NSS_IMPLEMENT NSSDER * 1.153 +nssCertificate_GetEncoding ( 1.154 + NSSCertificate *c 1.155 +) 1.156 +{ 1.157 + if (c->encoding.size > 0 && c->encoding.data) { 1.158 + return &c->encoding; 1.159 + } else { 1.160 + return (NSSDER *)NULL; 1.161 + } 1.162 +} 1.163 + 1.164 +NSS_IMPLEMENT NSSDER * 1.165 +nssCertificate_GetIssuer ( 1.166 + NSSCertificate *c 1.167 +) 1.168 +{ 1.169 + if (c->issuer.size > 0 && c->issuer.data) { 1.170 + return &c->issuer; 1.171 + } else { 1.172 + return (NSSDER *)NULL; 1.173 + } 1.174 +} 1.175 + 1.176 +NSS_IMPLEMENT NSSDER * 1.177 +nssCertificate_GetSerialNumber ( 1.178 + NSSCertificate *c 1.179 +) 1.180 +{ 1.181 + if (c->serial.size > 0 && c->serial.data) { 1.182 + return &c->serial; 1.183 + } else { 1.184 + return (NSSDER *)NULL; 1.185 + } 1.186 +} 1.187 + 1.188 +NSS_IMPLEMENT NSSDER * 1.189 +nssCertificate_GetSubject ( 1.190 + NSSCertificate *c 1.191 +) 1.192 +{ 1.193 + if (c->subject.size > 0 && c->subject.data) { 1.194 + return &c->subject; 1.195 + } else { 1.196 + return (NSSDER *)NULL; 1.197 + } 1.198 +} 1.199 + 1.200 +/* Returns a copy, Caller must free using nss_ZFreeIf */ 1.201 +NSS_IMPLEMENT NSSUTF8 * 1.202 +nssCertificate_GetNickname ( 1.203 + NSSCertificate *c, 1.204 + NSSToken *tokenOpt 1.205 +) 1.206 +{ 1.207 + return nssPKIObject_GetNicknameForToken(&c->object, tokenOpt); 1.208 +} 1.209 + 1.210 +NSS_IMPLEMENT NSSASCII7 * 1.211 +nssCertificate_GetEmailAddress ( 1.212 + NSSCertificate *c 1.213 +) 1.214 +{ 1.215 + return c->email; 1.216 +} 1.217 + 1.218 +NSS_IMPLEMENT PRStatus 1.219 +NSSCertificate_DeleteStoredObject ( 1.220 + NSSCertificate *c, 1.221 + NSSCallback *uhh 1.222 +) 1.223 +{ 1.224 + return nssPKIObject_DeleteStoredObject(&c->object, uhh, PR_TRUE); 1.225 +} 1.226 + 1.227 +NSS_IMPLEMENT PRStatus 1.228 +NSSCertificate_Validate ( 1.229 + NSSCertificate *c, 1.230 + NSSTime *timeOpt, /* NULL for "now" */ 1.231 + NSSUsage *usage, 1.232 + NSSPolicies *policiesOpt /* NULL for none */ 1.233 +) 1.234 +{ 1.235 + nss_SetError(NSS_ERROR_NOT_FOUND); 1.236 + return PR_FAILURE; 1.237 +} 1.238 + 1.239 +NSS_IMPLEMENT void ** /* void *[] */ 1.240 +NSSCertificate_ValidateCompletely ( 1.241 + NSSCertificate *c, 1.242 + NSSTime *timeOpt, /* NULL for "now" */ 1.243 + NSSUsage *usage, 1.244 + NSSPolicies *policiesOpt, /* NULL for none */ 1.245 + void **rvOpt, /* NULL for allocate */ 1.246 + PRUint32 rvLimit, /* zero for no limit */ 1.247 + NSSArena *arenaOpt /* NULL for heap */ 1.248 +) 1.249 +{ 1.250 + nss_SetError(NSS_ERROR_NOT_FOUND); 1.251 + return NULL; 1.252 +} 1.253 + 1.254 +NSS_IMPLEMENT PRStatus 1.255 +NSSCertificate_ValidateAndDiscoverUsagesAndPolicies ( 1.256 + NSSCertificate *c, 1.257 + NSSTime **notBeforeOutOpt, 1.258 + NSSTime **notAfterOutOpt, 1.259 + void *allowedUsages, 1.260 + void *disallowedUsages, 1.261 + void *allowedPolicies, 1.262 + void *disallowedPolicies, 1.263 + /* more args.. work on this fgmr */ 1.264 + NSSArena *arenaOpt 1.265 +) 1.266 +{ 1.267 + nss_SetError(NSS_ERROR_NOT_FOUND); 1.268 + return PR_FAILURE; 1.269 +} 1.270 + 1.271 +NSS_IMPLEMENT NSSDER * 1.272 +NSSCertificate_Encode ( 1.273 + NSSCertificate *c, 1.274 + NSSDER *rvOpt, 1.275 + NSSArena *arenaOpt 1.276 +) 1.277 +{ 1.278 + /* Item, DER, BER are all typedefs now... */ 1.279 + return nssItem_Duplicate((NSSItem *)&c->encoding, arenaOpt, rvOpt); 1.280 +} 1.281 + 1.282 +NSS_IMPLEMENT nssDecodedCert * 1.283 +nssCertificate_GetDecoding ( 1.284 + NSSCertificate *c 1.285 +) 1.286 +{ 1.287 + nssDecodedCert* deco = NULL; 1.288 + if (c->type == NSSCertificateType_PKIX) { 1.289 + (void)STAN_GetCERTCertificate(c); 1.290 + } 1.291 + nssPKIObject_Lock(&c->object); 1.292 + if (!c->decoding) { 1.293 + deco = nssDecodedCert_Create(NULL, &c->encoding, c->type); 1.294 + PORT_Assert(!c->decoding); 1.295 + c->decoding = deco; 1.296 + } else { 1.297 + deco = c->decoding; 1.298 + } 1.299 + nssPKIObject_Unlock(&c->object); 1.300 + return deco; 1.301 +} 1.302 + 1.303 +static NSSCertificate ** 1.304 +filter_subject_certs_for_id ( 1.305 + NSSCertificate **subjectCerts, 1.306 + void *id 1.307 +) 1.308 +{ 1.309 + NSSCertificate **si; 1.310 + nssDecodedCert *dcp; 1.311 + int nextOpenSlot = 0; 1.312 + int i; 1.313 + nssCertIDMatch matchLevel = nssCertIDMatch_Unknown; 1.314 + nssCertIDMatch match; 1.315 + 1.316 + /* walk the subject certs */ 1.317 + for (si = subjectCerts; *si; si++) { 1.318 + dcp = nssCertificate_GetDecoding(*si); 1.319 + if (!dcp) { 1.320 + NSSCertificate_Destroy(*si); 1.321 + continue; 1.322 + } 1.323 + match = dcp->matchIdentifier(dcp, id); 1.324 + switch (match) { 1.325 + case nssCertIDMatch_Yes: 1.326 + if (matchLevel == nssCertIDMatch_Unknown) { 1.327 + /* we have non-definitive matches, forget them */ 1.328 + for (i = 0; i < nextOpenSlot; i++) { 1.329 + NSSCertificate_Destroy(subjectCerts[i]); 1.330 + subjectCerts[i] = NULL; 1.331 + } 1.332 + nextOpenSlot = 0; 1.333 + /* only keep definitive matches from now on */ 1.334 + matchLevel = nssCertIDMatch_Yes; 1.335 + } 1.336 + /* keep the cert */ 1.337 + subjectCerts[nextOpenSlot++] = *si; 1.338 + break; 1.339 + case nssCertIDMatch_Unknown: 1.340 + if (matchLevel == nssCertIDMatch_Unknown) { 1.341 + /* only have non-definitive matches so far, keep it */ 1.342 + subjectCerts[nextOpenSlot++] = *si; 1.343 + break; 1.344 + } 1.345 + /* else fall through, we have a definitive match already */ 1.346 + case nssCertIDMatch_No: 1.347 + default: 1.348 + NSSCertificate_Destroy(*si); 1.349 + *si = NULL; 1.350 + } 1.351 + } 1.352 + subjectCerts[nextOpenSlot] = NULL; 1.353 + return subjectCerts; 1.354 +} 1.355 + 1.356 +static NSSCertificate ** 1.357 +filter_certs_for_valid_issuers ( 1.358 + NSSCertificate **certs 1.359 +) 1.360 +{ 1.361 + NSSCertificate **cp; 1.362 + nssDecodedCert *dcp; 1.363 + int nextOpenSlot = 0; 1.364 + 1.365 + for (cp = certs; *cp; cp++) { 1.366 + dcp = nssCertificate_GetDecoding(*cp); 1.367 + if (dcp && dcp->isValidIssuer(dcp)) { 1.368 + certs[nextOpenSlot++] = *cp; 1.369 + } else { 1.370 + NSSCertificate_Destroy(*cp); 1.371 + } 1.372 + } 1.373 + certs[nextOpenSlot] = NULL; 1.374 + return certs; 1.375 +} 1.376 + 1.377 +static NSSCertificate * 1.378 +find_cert_issuer ( 1.379 + NSSCertificate *c, 1.380 + NSSTime *timeOpt, 1.381 + NSSUsage *usage, 1.382 + NSSPolicies *policiesOpt, 1.383 + NSSTrustDomain *td, 1.384 + NSSCryptoContext *cc 1.385 +) 1.386 +{ 1.387 + NSSArena *arena; 1.388 + NSSCertificate **certs = NULL; 1.389 + NSSCertificate **ccIssuers = NULL; 1.390 + NSSCertificate **tdIssuers = NULL; 1.391 + NSSCertificate *issuer = NULL; 1.392 + 1.393 + if (!cc) 1.394 + cc = c->object.cryptoContext; 1.395 + if (!td) 1.396 + td = NSSCertificate_GetTrustDomain(c); 1.397 + arena = nssArena_Create(); 1.398 + if (!arena) { 1.399 + return (NSSCertificate *)NULL; 1.400 + } 1.401 + if (cc) { 1.402 + ccIssuers = nssCryptoContext_FindCertificatesBySubject(cc, 1.403 + &c->issuer, 1.404 + NULL, 1.405 + 0, 1.406 + arena); 1.407 + } 1.408 + if (td) 1.409 + tdIssuers = nssTrustDomain_FindCertificatesBySubject(td, 1.410 + &c->issuer, 1.411 + NULL, 1.412 + 0, 1.413 + arena); 1.414 + certs = nssCertificateArray_Join(ccIssuers, tdIssuers); 1.415 + if (certs) { 1.416 + nssDecodedCert *dc = NULL; 1.417 + void *issuerID = NULL; 1.418 + dc = nssCertificate_GetDecoding(c); 1.419 + if (dc) { 1.420 + issuerID = dc->getIssuerIdentifier(dc); 1.421 + } 1.422 + /* XXX review based on CERT_FindCertIssuer 1.423 + * this function is not using the authCertIssuer field as a fallback 1.424 + * if authority key id does not exist 1.425 + */ 1.426 + if (issuerID) { 1.427 + certs = filter_subject_certs_for_id(certs, issuerID); 1.428 + } 1.429 + certs = filter_certs_for_valid_issuers(certs); 1.430 + issuer = nssCertificateArray_FindBestCertificate(certs, 1.431 + timeOpt, 1.432 + usage, 1.433 + policiesOpt); 1.434 + nssCertificateArray_Destroy(certs); 1.435 + } 1.436 + nssArena_Destroy(arena); 1.437 + return issuer; 1.438 +} 1.439 + 1.440 +/* This function returns the built chain, as far as it gets, 1.441 +** even if/when it fails to find an issuer, and returns PR_FAILURE 1.442 +*/ 1.443 +NSS_IMPLEMENT NSSCertificate ** 1.444 +nssCertificate_BuildChain ( 1.445 + NSSCertificate *c, 1.446 + NSSTime *timeOpt, 1.447 + NSSUsage *usage, 1.448 + NSSPolicies *policiesOpt, 1.449 + NSSCertificate **rvOpt, 1.450 + PRUint32 rvLimit, 1.451 + NSSArena *arenaOpt, 1.452 + PRStatus *statusOpt, 1.453 + NSSTrustDomain *td, 1.454 + NSSCryptoContext *cc 1.455 +) 1.456 +{ 1.457 + NSSCertificate **rvChain = NULL; 1.458 + NSSUsage issuerUsage = *usage; 1.459 + nssPKIObjectCollection *collection = NULL; 1.460 + PRUint32 rvCount = 0; 1.461 + PRStatus st; 1.462 + PRStatus ret = PR_SUCCESS; 1.463 + 1.464 + if (!c || !cc || 1.465 + (!td && (td = NSSCertificate_GetTrustDomain(c)) == NULL)) { 1.466 + goto loser; 1.467 + } 1.468 + /* bump the usage up to CA level */ 1.469 + issuerUsage.nss3lookingForCA = PR_TRUE; 1.470 + collection = nssCertificateCollection_Create(td, NULL); 1.471 + if (!collection) 1.472 + goto loser; 1.473 + st = nssPKIObjectCollection_AddObject(collection, (nssPKIObject *)c); 1.474 + if (st != PR_SUCCESS) 1.475 + goto loser; 1.476 + for (rvCount = 1; (!rvLimit || rvCount < rvLimit); ++rvCount) { 1.477 + CERTCertificate *cCert = STAN_GetCERTCertificate(c); 1.478 + if (cCert->isRoot) { 1.479 + /* not including the issuer of the self-signed cert, which is, 1.480 + * of course, itself 1.481 + */ 1.482 + break; 1.483 + } 1.484 + c = find_cert_issuer(c, timeOpt, &issuerUsage, policiesOpt, td, cc); 1.485 + if (!c) { 1.486 + ret = PR_FAILURE; 1.487 + break; 1.488 + } 1.489 + st = nssPKIObjectCollection_AddObject(collection, (nssPKIObject *)c); 1.490 + nssCertificate_Destroy(c); /* collection has it */ 1.491 + if (st != PR_SUCCESS) 1.492 + goto loser; 1.493 + } 1.494 + rvChain = nssPKIObjectCollection_GetCertificates(collection, 1.495 + rvOpt, 1.496 + rvLimit, 1.497 + arenaOpt); 1.498 + if (rvChain) { 1.499 + nssPKIObjectCollection_Destroy(collection); 1.500 + if (statusOpt) 1.501 + *statusOpt = ret; 1.502 + if (ret != PR_SUCCESS) 1.503 + nss_SetError(NSS_ERROR_CERTIFICATE_ISSUER_NOT_FOUND); 1.504 + return rvChain; 1.505 + } 1.506 + 1.507 +loser: 1.508 + if (collection) 1.509 + nssPKIObjectCollection_Destroy(collection); 1.510 + if (statusOpt) 1.511 + *statusOpt = PR_FAILURE; 1.512 + nss_SetError(NSS_ERROR_CERTIFICATE_ISSUER_NOT_FOUND); 1.513 + return rvChain; 1.514 +} 1.515 + 1.516 +NSS_IMPLEMENT NSSCertificate ** 1.517 +NSSCertificate_BuildChain ( 1.518 + NSSCertificate *c, 1.519 + NSSTime *timeOpt, 1.520 + NSSUsage *usage, 1.521 + NSSPolicies *policiesOpt, 1.522 + NSSCertificate **rvOpt, 1.523 + PRUint32 rvLimit, /* zero for no limit */ 1.524 + NSSArena *arenaOpt, 1.525 + PRStatus *statusOpt, 1.526 + NSSTrustDomain *td, 1.527 + NSSCryptoContext *cc 1.528 +) 1.529 +{ 1.530 + return nssCertificate_BuildChain(c, timeOpt, usage, policiesOpt, 1.531 + rvOpt, rvLimit, arenaOpt, statusOpt, 1.532 + td, cc); 1.533 +} 1.534 + 1.535 +NSS_IMPLEMENT NSSCryptoContext * 1.536 +nssCertificate_GetCryptoContext ( 1.537 + NSSCertificate *c 1.538 +) 1.539 +{ 1.540 + return c->object.cryptoContext; 1.541 +} 1.542 + 1.543 +NSS_IMPLEMENT NSSTrustDomain * 1.544 +nssCertificate_GetTrustDomain ( 1.545 + NSSCertificate *c 1.546 +) 1.547 +{ 1.548 + return c->object.trustDomain; 1.549 +} 1.550 + 1.551 +NSS_IMPLEMENT NSSTrustDomain * 1.552 +NSSCertificate_GetTrustDomain ( 1.553 + NSSCertificate *c 1.554 +) 1.555 +{ 1.556 + return nssCertificate_GetTrustDomain(c); 1.557 +} 1.558 + 1.559 +NSS_IMPLEMENT NSSToken * 1.560 +NSSCertificate_GetToken ( 1.561 + NSSCertificate *c, 1.562 + PRStatus *statusOpt 1.563 +) 1.564 +{ 1.565 + return (NSSToken *)NULL; 1.566 +} 1.567 + 1.568 +NSS_IMPLEMENT NSSSlot * 1.569 +NSSCertificate_GetSlot ( 1.570 + NSSCertificate *c, 1.571 + PRStatus *statusOpt 1.572 +) 1.573 +{ 1.574 + return (NSSSlot *)NULL; 1.575 +} 1.576 + 1.577 +NSS_IMPLEMENT NSSModule * 1.578 +NSSCertificate_GetModule ( 1.579 + NSSCertificate *c, 1.580 + PRStatus *statusOpt 1.581 +) 1.582 +{ 1.583 + return (NSSModule *)NULL; 1.584 +} 1.585 + 1.586 +NSS_IMPLEMENT NSSItem * 1.587 +NSSCertificate_Encrypt ( 1.588 + NSSCertificate *c, 1.589 + NSSAlgorithmAndParameters *apOpt, 1.590 + NSSItem *data, 1.591 + NSSTime *timeOpt, 1.592 + NSSUsage *usage, 1.593 + NSSPolicies *policiesOpt, 1.594 + NSSCallback *uhh, 1.595 + NSSItem *rvOpt, 1.596 + NSSArena *arenaOpt 1.597 +) 1.598 +{ 1.599 + nss_SetError(NSS_ERROR_NOT_FOUND); 1.600 + return NULL; 1.601 +} 1.602 + 1.603 +NSS_IMPLEMENT PRStatus 1.604 +NSSCertificate_Verify ( 1.605 + NSSCertificate *c, 1.606 + NSSAlgorithmAndParameters *apOpt, 1.607 + NSSItem *data, 1.608 + NSSItem *signature, 1.609 + NSSTime *timeOpt, 1.610 + NSSUsage *usage, 1.611 + NSSPolicies *policiesOpt, 1.612 + NSSCallback *uhh 1.613 +) 1.614 +{ 1.615 + nss_SetError(NSS_ERROR_NOT_FOUND); 1.616 + return PR_FAILURE; 1.617 +} 1.618 + 1.619 +NSS_IMPLEMENT NSSItem * 1.620 +NSSCertificate_VerifyRecover ( 1.621 + NSSCertificate *c, 1.622 + NSSAlgorithmAndParameters *apOpt, 1.623 + NSSItem *signature, 1.624 + NSSTime *timeOpt, 1.625 + NSSUsage *usage, 1.626 + NSSPolicies *policiesOpt, 1.627 + NSSCallback *uhh, 1.628 + NSSItem *rvOpt, 1.629 + NSSArena *arenaOpt 1.630 +) 1.631 +{ 1.632 + nss_SetError(NSS_ERROR_NOT_FOUND); 1.633 + return NULL; 1.634 +} 1.635 + 1.636 +NSS_IMPLEMENT NSSItem * 1.637 +NSSCertificate_WrapSymmetricKey ( 1.638 + NSSCertificate *c, 1.639 + NSSAlgorithmAndParameters *apOpt, 1.640 + NSSSymmetricKey *keyToWrap, 1.641 + NSSTime *timeOpt, 1.642 + NSSUsage *usage, 1.643 + NSSPolicies *policiesOpt, 1.644 + NSSCallback *uhh, 1.645 + NSSItem *rvOpt, 1.646 + NSSArena *arenaOpt 1.647 +) 1.648 +{ 1.649 + nss_SetError(NSS_ERROR_NOT_FOUND); 1.650 + return NULL; 1.651 +} 1.652 + 1.653 +NSS_IMPLEMENT NSSCryptoContext * 1.654 +NSSCertificate_CreateCryptoContext ( 1.655 + NSSCertificate *c, 1.656 + NSSAlgorithmAndParameters *apOpt, 1.657 + NSSTime *timeOpt, 1.658 + NSSUsage *usage, 1.659 + NSSPolicies *policiesOpt, 1.660 + NSSCallback *uhh 1.661 +) 1.662 +{ 1.663 + nss_SetError(NSS_ERROR_NOT_FOUND); 1.664 + return NULL; 1.665 +} 1.666 + 1.667 +NSS_IMPLEMENT NSSPublicKey * 1.668 +NSSCertificate_GetPublicKey ( 1.669 + NSSCertificate *c 1.670 +) 1.671 +{ 1.672 +#if 0 1.673 + CK_ATTRIBUTE pubktemplate[] = { 1.674 + { CKA_CLASS, NULL, 0 }, 1.675 + { CKA_ID, NULL, 0 }, 1.676 + { CKA_SUBJECT, NULL, 0 } 1.677 + }; 1.678 + PRStatus nssrv; 1.679 + CK_ULONG count = sizeof(pubktemplate) / sizeof(pubktemplate[0]); 1.680 + NSS_CK_SET_ATTRIBUTE_ITEM(pubktemplate, 0, &g_ck_class_pubkey); 1.681 + if (c->id.size > 0) { 1.682 + /* CKA_ID */ 1.683 + NSS_CK_ITEM_TO_ATTRIBUTE(&c->id, &pubktemplate[1]); 1.684 + } else { 1.685 + /* failure, yes? */ 1.686 + return (NSSPublicKey *)NULL; 1.687 + } 1.688 + if (c->subject.size > 0) { 1.689 + /* CKA_SUBJECT */ 1.690 + NSS_CK_ITEM_TO_ATTRIBUTE(&c->subject, &pubktemplate[2]); 1.691 + } else { 1.692 + /* failure, yes? */ 1.693 + return (NSSPublicKey *)NULL; 1.694 + } 1.695 + /* Try the cert's token first */ 1.696 + if (c->token) { 1.697 + nssrv = nssToken_FindObjectByTemplate(c->token, pubktemplate, count); 1.698 + } 1.699 +#endif 1.700 + /* Try all other key tokens */ 1.701 + return (NSSPublicKey *)NULL; 1.702 +} 1.703 + 1.704 +NSS_IMPLEMENT NSSPrivateKey * 1.705 +NSSCertificate_FindPrivateKey ( 1.706 + NSSCertificate *c, 1.707 + NSSCallback *uhh 1.708 +) 1.709 +{ 1.710 + nss_SetError(NSS_ERROR_NOT_FOUND); 1.711 + return NULL; 1.712 +} 1.713 + 1.714 +NSS_IMPLEMENT PRBool 1.715 +NSSCertificate_IsPrivateKeyAvailable ( 1.716 + NSSCertificate *c, 1.717 + NSSCallback *uhh, 1.718 + PRStatus *statusOpt 1.719 +) 1.720 +{ 1.721 + PRBool isUser = PR_FALSE; 1.722 + nssCryptokiObject **ip; 1.723 + nssCryptokiObject **instances = nssPKIObject_GetInstances(&c->object); 1.724 + if (!instances) { 1.725 + return PR_FALSE; 1.726 + } 1.727 + for (ip = instances; *ip; ip++) { 1.728 + nssCryptokiObject *instance = *ip; 1.729 + if (nssToken_IsPrivateKeyAvailable(instance->token, c, instance)) { 1.730 + isUser = PR_TRUE; 1.731 + } 1.732 + } 1.733 + nssCryptokiObjectArray_Destroy(instances); 1.734 + return isUser; 1.735 +} 1.736 + 1.737 +/* sort the subject cert list from newest to oldest */ 1.738 +PRIntn 1.739 +nssCertificate_SubjectListSort ( 1.740 + void *v1, 1.741 + void *v2 1.742 +) 1.743 +{ 1.744 + NSSCertificate *c1 = (NSSCertificate *)v1; 1.745 + NSSCertificate *c2 = (NSSCertificate *)v2; 1.746 + nssDecodedCert *dc1 = nssCertificate_GetDecoding(c1); 1.747 + nssDecodedCert *dc2 = nssCertificate_GetDecoding(c2); 1.748 + if (!dc1) { 1.749 + return dc2 ? 1 : 0; 1.750 + } else if (!dc2) { 1.751 + return -1; 1.752 + } else { 1.753 + return dc1->isNewerThan(dc1, dc2) ? -1 : 1; 1.754 + } 1.755 +} 1.756 + 1.757 +NSS_IMPLEMENT PRBool 1.758 +NSSUserCertificate_IsStillPresent ( 1.759 + NSSUserCertificate *uc, 1.760 + PRStatus *statusOpt 1.761 +) 1.762 +{ 1.763 + nss_SetError(NSS_ERROR_NOT_FOUND); 1.764 + return PR_FALSE; 1.765 +} 1.766 + 1.767 +NSS_IMPLEMENT NSSItem * 1.768 +NSSUserCertificate_Decrypt ( 1.769 + NSSUserCertificate *uc, 1.770 + NSSAlgorithmAndParameters *apOpt, 1.771 + NSSItem *data, 1.772 + NSSTime *timeOpt, 1.773 + NSSUsage *usage, 1.774 + NSSPolicies *policiesOpt, 1.775 + NSSCallback *uhh, 1.776 + NSSItem *rvOpt, 1.777 + NSSArena *arenaOpt 1.778 +) 1.779 +{ 1.780 + nss_SetError(NSS_ERROR_NOT_FOUND); 1.781 + return NULL; 1.782 +} 1.783 + 1.784 +NSS_IMPLEMENT NSSItem * 1.785 +NSSUserCertificate_Sign ( 1.786 + NSSUserCertificate *uc, 1.787 + NSSAlgorithmAndParameters *apOpt, 1.788 + NSSItem *data, 1.789 + NSSTime *timeOpt, 1.790 + NSSUsage *usage, 1.791 + NSSPolicies *policiesOpt, 1.792 + NSSCallback *uhh, 1.793 + NSSItem *rvOpt, 1.794 + NSSArena *arenaOpt 1.795 +) 1.796 +{ 1.797 + nss_SetError(NSS_ERROR_NOT_FOUND); 1.798 + return NULL; 1.799 +} 1.800 + 1.801 +NSS_IMPLEMENT NSSItem * 1.802 +NSSUserCertificate_SignRecover ( 1.803 + NSSUserCertificate *uc, 1.804 + NSSAlgorithmAndParameters *apOpt, 1.805 + NSSItem *data, 1.806 + NSSTime *timeOpt, 1.807 + NSSUsage *usage, 1.808 + NSSPolicies *policiesOpt, 1.809 + NSSCallback *uhh, 1.810 + NSSItem *rvOpt, 1.811 + NSSArena *arenaOpt 1.812 +) 1.813 +{ 1.814 + nss_SetError(NSS_ERROR_NOT_FOUND); 1.815 + return NULL; 1.816 +} 1.817 + 1.818 +NSS_IMPLEMENT NSSSymmetricKey * 1.819 +NSSUserCertificate_UnwrapSymmetricKey ( 1.820 + NSSUserCertificate *uc, 1.821 + NSSAlgorithmAndParameters *apOpt, 1.822 + NSSItem *wrappedKey, 1.823 + NSSTime *timeOpt, 1.824 + NSSUsage *usage, 1.825 + NSSPolicies *policiesOpt, 1.826 + NSSCallback *uhh, 1.827 + NSSItem *rvOpt, 1.828 + NSSArena *arenaOpt 1.829 +) 1.830 +{ 1.831 + nss_SetError(NSS_ERROR_NOT_FOUND); 1.832 + return NULL; 1.833 +} 1.834 + 1.835 +NSS_IMPLEMENT NSSSymmetricKey * 1.836 +NSSUserCertificate_DeriveSymmetricKey ( 1.837 + NSSUserCertificate *uc, /* provides private key */ 1.838 + NSSCertificate *c, /* provides public key */ 1.839 + NSSAlgorithmAndParameters *apOpt, 1.840 + NSSOID *target, 1.841 + PRUint32 keySizeOpt, /* zero for best allowed */ 1.842 + NSSOperations operations, 1.843 + NSSCallback *uhh 1.844 +) 1.845 +{ 1.846 + nss_SetError(NSS_ERROR_NOT_FOUND); 1.847 + return NULL; 1.848 +} 1.849 + 1.850 +NSS_IMPLEMENT nssSMIMEProfile * 1.851 +nssSMIMEProfile_Create ( 1.852 + NSSCertificate *cert, 1.853 + NSSItem *profileTime, 1.854 + NSSItem *profileData 1.855 +) 1.856 +{ 1.857 + NSSArena *arena; 1.858 + nssSMIMEProfile *rvProfile; 1.859 + nssPKIObject *object; 1.860 + NSSTrustDomain *td = nssCertificate_GetTrustDomain(cert); 1.861 + NSSCryptoContext *cc = nssCertificate_GetCryptoContext(cert); 1.862 + arena = nssArena_Create(); 1.863 + if (!arena) { 1.864 + return NULL; 1.865 + } 1.866 + object = nssPKIObject_Create(arena, NULL, td, cc, nssPKILock); 1.867 + if (!object) { 1.868 + goto loser; 1.869 + } 1.870 + rvProfile = nss_ZNEW(arena, nssSMIMEProfile); 1.871 + if (!rvProfile) { 1.872 + goto loser; 1.873 + } 1.874 + rvProfile->object = *object; 1.875 + rvProfile->certificate = cert; 1.876 + rvProfile->email = nssUTF8_Duplicate(cert->email, arena); 1.877 + rvProfile->subject = nssItem_Duplicate(&cert->subject, arena, NULL); 1.878 + if (profileTime) { 1.879 + rvProfile->profileTime = nssItem_Duplicate(profileTime, arena, NULL); 1.880 + } 1.881 + if (profileData) { 1.882 + rvProfile->profileData = nssItem_Duplicate(profileData, arena, NULL); 1.883 + } 1.884 + return rvProfile; 1.885 +loser: 1.886 + if (object) nssPKIObject_Destroy(object); 1.887 + else if (arena) nssArena_Destroy(arena); 1.888 + return (nssSMIMEProfile *)NULL; 1.889 +} 1.890 + 1.891 +/* execute a callback function on all members of a cert list */ 1.892 +NSS_EXTERN PRStatus 1.893 +nssCertificateList_DoCallback ( 1.894 + nssList *certList, 1.895 + PRStatus (* callback)(NSSCertificate *c, void *arg), 1.896 + void *arg 1.897 +) 1.898 +{ 1.899 + nssListIterator *certs; 1.900 + NSSCertificate *cert; 1.901 + PRStatus nssrv; 1.902 + certs = nssList_CreateIterator(certList); 1.903 + if (!certs) { 1.904 + return PR_FAILURE; 1.905 + } 1.906 + for (cert = (NSSCertificate *)nssListIterator_Start(certs); 1.907 + cert != (NSSCertificate *)NULL; 1.908 + cert = (NSSCertificate *)nssListIterator_Next(certs)) 1.909 + { 1.910 + nssrv = (*callback)(cert, arg); 1.911 + } 1.912 + nssListIterator_Finish(certs); 1.913 + nssListIterator_Destroy(certs); 1.914 + return PR_SUCCESS; 1.915 +} 1.916 + 1.917 +static PRStatus add_ref_callback(NSSCertificate *c, void *a) 1.918 +{ 1.919 + nssCertificate_AddRef(c); 1.920 + return PR_SUCCESS; 1.921 +} 1.922 + 1.923 +NSS_IMPLEMENT void 1.924 +nssCertificateList_AddReferences ( 1.925 + nssList *certList 1.926 +) 1.927 +{ 1.928 + (void)nssCertificateList_DoCallback(certList, add_ref_callback, NULL); 1.929 +} 1.930 + 1.931 + 1.932 +/* 1.933 + * Is this trust record safe to apply to all certs of the same issuer/SN 1.934 + * independent of the cert matching the hash. This is only true is the trust 1.935 + * is unknown or distrusted. In general this feature is only useful to 1.936 + * explicitly distrusting certs. It is not safe to use to trust certs, so 1.937 + * only allow unknown and untrusted trust types. 1.938 + */ 1.939 +PRBool 1.940 +nssTrust_IsSafeToIgnoreCertHash(nssTrustLevel serverAuth, 1.941 + nssTrustLevel clientAuth, nssTrustLevel codeSigning, 1.942 + nssTrustLevel email, PRBool stepup) 1.943 +{ 1.944 + /* step up is a trust type, if it's on, we must have a hash for the cert */ 1.945 + if (stepup) { 1.946 + return PR_FALSE; 1.947 + } 1.948 + if ((serverAuth != nssTrustLevel_Unknown) && 1.949 + (serverAuth != nssTrustLevel_NotTrusted)) { 1.950 + return PR_FALSE; 1.951 + } 1.952 + if ((clientAuth != nssTrustLevel_Unknown) && 1.953 + (clientAuth != nssTrustLevel_NotTrusted)) { 1.954 + return PR_FALSE; 1.955 + } 1.956 + if ((codeSigning != nssTrustLevel_Unknown) && 1.957 + (codeSigning != nssTrustLevel_NotTrusted)) { 1.958 + return PR_FALSE; 1.959 + } 1.960 + if ((email != nssTrustLevel_Unknown) && 1.961 + (email != nssTrustLevel_NotTrusted)) { 1.962 + return PR_FALSE; 1.963 + } 1.964 + /* record only has Unknown and Untrusted entries, ok to accept without a 1.965 + * hash */ 1.966 + return PR_TRUE; 1.967 +} 1.968 + 1.969 +NSS_IMPLEMENT NSSTrust * 1.970 +nssTrust_Create ( 1.971 + nssPKIObject *object, 1.972 + NSSItem *certData 1.973 +) 1.974 +{ 1.975 + PRStatus status; 1.976 + PRUint32 i; 1.977 + PRUint32 lastTrustOrder, myTrustOrder; 1.978 + unsigned char sha1_hashcmp[SHA1_LENGTH]; 1.979 + unsigned char sha1_hashin[SHA1_LENGTH]; 1.980 + NSSItem sha1_hash; 1.981 + NSSTrust *rvt; 1.982 + nssCryptokiObject *instance; 1.983 + nssTrustLevel serverAuth, clientAuth, codeSigning, emailProtection; 1.984 + SECStatus rv; /* Should be stan flavor */ 1.985 + PRBool stepUp; 1.986 + 1.987 + lastTrustOrder = 1<<16; /* just make it big */ 1.988 + PR_ASSERT(object->instances != NULL && object->numInstances > 0); 1.989 + rvt = nss_ZNEW(object->arena, NSSTrust); 1.990 + if (!rvt) { 1.991 + return (NSSTrust *)NULL; 1.992 + } 1.993 + rvt->object = *object; 1.994 + 1.995 + /* should be stan flavor of Hashbuf */ 1.996 + rv = PK11_HashBuf(SEC_OID_SHA1,sha1_hashcmp,certData->data,certData->size); 1.997 + if (rv != SECSuccess) { 1.998 + return (NSSTrust *)NULL; 1.999 + } 1.1000 + sha1_hash.data = sha1_hashin; 1.1001 + sha1_hash.size = sizeof (sha1_hashin); 1.1002 + /* trust has to peek into the base object members */ 1.1003 + nssPKIObject_Lock(object); 1.1004 + for (i=0; i<object->numInstances; i++) { 1.1005 + instance = object->instances[i]; 1.1006 + myTrustOrder = nssToken_GetTrustOrder(instance->token); 1.1007 + status = nssCryptokiTrust_GetAttributes(instance, NULL, 1.1008 + &sha1_hash, 1.1009 + &serverAuth, 1.1010 + &clientAuth, 1.1011 + &codeSigning, 1.1012 + &emailProtection, 1.1013 + &stepUp); 1.1014 + if (status != PR_SUCCESS) { 1.1015 + nssPKIObject_Unlock(object); 1.1016 + return (NSSTrust *)NULL; 1.1017 + } 1.1018 + /* if no hash is specified, then trust applies to all certs with 1.1019 + * this issuer/SN. NOTE: This is only true for entries that 1.1020 + * have distrust and unknown record */ 1.1021 + if (!( 1.1022 + /* we continue if there is no hash, and the trust type is 1.1023 + * safe to accept without a hash ... or ... */ 1.1024 + ((sha1_hash.size == 0) && 1.1025 + nssTrust_IsSafeToIgnoreCertHash(serverAuth,clientAuth, 1.1026 + codeSigning, emailProtection,stepUp)) 1.1027 + || 1.1028 + /* we have a hash of the correct size, and it matches */ 1.1029 + ((sha1_hash.size == SHA1_LENGTH) && (PORT_Memcmp(sha1_hashin, 1.1030 + sha1_hashcmp,SHA1_LENGTH) == 0)) )) { 1.1031 + nssPKIObject_Unlock(object); 1.1032 + return (NSSTrust *)NULL; 1.1033 + } 1.1034 + if (rvt->serverAuth == nssTrustLevel_Unknown || 1.1035 + myTrustOrder < lastTrustOrder) 1.1036 + { 1.1037 + rvt->serverAuth = serverAuth; 1.1038 + } 1.1039 + if (rvt->clientAuth == nssTrustLevel_Unknown || 1.1040 + myTrustOrder < lastTrustOrder) 1.1041 + { 1.1042 + rvt->clientAuth = clientAuth; 1.1043 + } 1.1044 + if (rvt->emailProtection == nssTrustLevel_Unknown || 1.1045 + myTrustOrder < lastTrustOrder) 1.1046 + { 1.1047 + rvt->emailProtection = emailProtection; 1.1048 + } 1.1049 + if (rvt->codeSigning == nssTrustLevel_Unknown || 1.1050 + myTrustOrder < lastTrustOrder) 1.1051 + { 1.1052 + rvt->codeSigning = codeSigning; 1.1053 + } 1.1054 + rvt->stepUpApproved = stepUp; 1.1055 + lastTrustOrder = myTrustOrder; 1.1056 + } 1.1057 + nssPKIObject_Unlock(object); 1.1058 + return rvt; 1.1059 +} 1.1060 + 1.1061 +NSS_IMPLEMENT NSSTrust * 1.1062 +nssTrust_AddRef ( 1.1063 + NSSTrust *trust 1.1064 +) 1.1065 +{ 1.1066 + if (trust) { 1.1067 + nssPKIObject_AddRef(&trust->object); 1.1068 + } 1.1069 + return trust; 1.1070 +} 1.1071 + 1.1072 +NSS_IMPLEMENT PRStatus 1.1073 +nssTrust_Destroy ( 1.1074 + NSSTrust *trust 1.1075 +) 1.1076 +{ 1.1077 + if (trust) { 1.1078 + (void)nssPKIObject_Destroy(&trust->object); 1.1079 + } 1.1080 + return PR_SUCCESS; 1.1081 +} 1.1082 + 1.1083 +NSS_IMPLEMENT nssSMIMEProfile * 1.1084 +nssSMIMEProfile_AddRef ( 1.1085 + nssSMIMEProfile *profile 1.1086 +) 1.1087 +{ 1.1088 + if (profile) { 1.1089 + nssPKIObject_AddRef(&profile->object); 1.1090 + } 1.1091 + return profile; 1.1092 +} 1.1093 + 1.1094 +NSS_IMPLEMENT PRStatus 1.1095 +nssSMIMEProfile_Destroy ( 1.1096 + nssSMIMEProfile *profile 1.1097 +) 1.1098 +{ 1.1099 + if (profile) { 1.1100 + (void)nssPKIObject_Destroy(&profile->object); 1.1101 + } 1.1102 + return PR_SUCCESS; 1.1103 +} 1.1104 + 1.1105 +NSS_IMPLEMENT NSSCRL * 1.1106 +nssCRL_Create ( 1.1107 + nssPKIObject *object 1.1108 +) 1.1109 +{ 1.1110 + PRStatus status; 1.1111 + NSSCRL *rvCRL; 1.1112 + NSSArena *arena = object->arena; 1.1113 + PR_ASSERT(object->instances != NULL && object->numInstances > 0); 1.1114 + rvCRL = nss_ZNEW(arena, NSSCRL); 1.1115 + if (!rvCRL) { 1.1116 + return (NSSCRL *)NULL; 1.1117 + } 1.1118 + rvCRL->object = *object; 1.1119 + /* XXX should choose instance based on some criteria */ 1.1120 + status = nssCryptokiCRL_GetAttributes(object->instances[0], 1.1121 + NULL, /* XXX sessionOpt */ 1.1122 + arena, 1.1123 + &rvCRL->encoding, 1.1124 + NULL, /* subject */ 1.1125 + NULL, /* class */ 1.1126 + &rvCRL->url, 1.1127 + &rvCRL->isKRL); 1.1128 + if (status != PR_SUCCESS) { 1.1129 + return (NSSCRL *)NULL; 1.1130 + } 1.1131 + return rvCRL; 1.1132 +} 1.1133 + 1.1134 +NSS_IMPLEMENT NSSCRL * 1.1135 +nssCRL_AddRef ( 1.1136 + NSSCRL *crl 1.1137 +) 1.1138 +{ 1.1139 + if (crl) { 1.1140 + nssPKIObject_AddRef(&crl->object); 1.1141 + } 1.1142 + return crl; 1.1143 +} 1.1144 + 1.1145 +NSS_IMPLEMENT PRStatus 1.1146 +nssCRL_Destroy ( 1.1147 + NSSCRL *crl 1.1148 +) 1.1149 +{ 1.1150 + if (crl) { 1.1151 + (void)nssPKIObject_Destroy(&crl->object); 1.1152 + } 1.1153 + return PR_SUCCESS; 1.1154 +} 1.1155 + 1.1156 +NSS_IMPLEMENT PRStatus 1.1157 +nssCRL_DeleteStoredObject ( 1.1158 + NSSCRL *crl, 1.1159 + NSSCallback *uhh 1.1160 +) 1.1161 +{ 1.1162 + return nssPKIObject_DeleteStoredObject(&crl->object, uhh, PR_TRUE); 1.1163 +} 1.1164 + 1.1165 +NSS_IMPLEMENT NSSDER * 1.1166 +nssCRL_GetEncoding ( 1.1167 + NSSCRL *crl 1.1168 +) 1.1169 +{ 1.1170 + if (crl && crl->encoding.data != NULL && crl->encoding.size > 0) { 1.1171 + return &crl->encoding; 1.1172 + } else { 1.1173 + return (NSSDER *)NULL; 1.1174 + } 1.1175 +}