1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/lib/pki/pki3hack.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1431 @@ 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 +/* 1.9 + * Hacks to integrate NSS 3.4 and NSS 4.0 certificates. 1.10 + */ 1.11 + 1.12 +#ifndef NSSPKI_H 1.13 +#include "nsspki.h" 1.14 +#endif /* NSSPKI_H */ 1.15 + 1.16 +#ifndef PKI_H 1.17 +#include "pki.h" 1.18 +#endif /* PKI_H */ 1.19 + 1.20 +#ifndef PKIM_H 1.21 +#include "pkim.h" 1.22 +#endif /* PKIM_H */ 1.23 + 1.24 +#ifndef DEV_H 1.25 +#include "dev.h" 1.26 +#endif /* DEV_H */ 1.27 + 1.28 +#ifndef DEVNSS3HACK_H 1.29 +#include "dev3hack.h" 1.30 +#endif /* DEVNSS3HACK_H */ 1.31 + 1.32 +#ifndef PKINSS3HACK_H 1.33 +#include "pki3hack.h" 1.34 +#endif /* PKINSS3HACK_H */ 1.35 + 1.36 +#include "secitem.h" 1.37 +#include "certdb.h" 1.38 +#include "certt.h" 1.39 +#include "cert.h" 1.40 +#include "certi.h" 1.41 +#include "pk11func.h" 1.42 +#include "pkistore.h" 1.43 +#include "secmod.h" 1.44 +#include "nssrwlk.h" 1.45 + 1.46 +NSSTrustDomain *g_default_trust_domain = NULL; 1.47 + 1.48 +NSSCryptoContext *g_default_crypto_context = NULL; 1.49 + 1.50 +NSSTrustDomain * 1.51 +STAN_GetDefaultTrustDomain() 1.52 +{ 1.53 + return g_default_trust_domain; 1.54 +} 1.55 + 1.56 +NSSCryptoContext * 1.57 +STAN_GetDefaultCryptoContext() 1.58 +{ 1.59 + return g_default_crypto_context; 1.60 +} 1.61 + 1.62 +extern const NSSError NSS_ERROR_ALREADY_INITIALIZED; 1.63 +extern const NSSError NSS_ERROR_INTERNAL_ERROR; 1.64 + 1.65 +NSS_IMPLEMENT PRStatus 1.66 +STAN_InitTokenForSlotInfo(NSSTrustDomain *td, PK11SlotInfo *slot) 1.67 +{ 1.68 + NSSToken *token; 1.69 + if (!td) { 1.70 + td = g_default_trust_domain; 1.71 + if (!td) { 1.72 + /* we're called while still initting. slot will get added 1.73 + * appropriately through normal init processes */ 1.74 + return PR_SUCCESS; 1.75 + } 1.76 + } 1.77 + token = nssToken_CreateFromPK11SlotInfo(td, slot); 1.78 + PK11Slot_SetNSSToken(slot, token); 1.79 + /* Don't add nonexistent token to TD's token list */ 1.80 + if (token) { 1.81 + NSSRWLock_LockWrite(td->tokensLock); 1.82 + nssList_Add(td->tokenList, token); 1.83 + NSSRWLock_UnlockWrite(td->tokensLock); 1.84 + } 1.85 + return PR_SUCCESS; 1.86 +} 1.87 + 1.88 +NSS_IMPLEMENT PRStatus 1.89 +STAN_ResetTokenInterator(NSSTrustDomain *td) 1.90 +{ 1.91 + if (!td) { 1.92 + td = g_default_trust_domain; 1.93 + if (!td) { 1.94 + /* we're called while still initting. slot will get added 1.95 + * appropriately through normal init processes */ 1.96 + return PR_SUCCESS; 1.97 + } 1.98 + } 1.99 + NSSRWLock_LockWrite(td->tokensLock); 1.100 + nssListIterator_Destroy(td->tokens); 1.101 + td->tokens = nssList_CreateIterator(td->tokenList); 1.102 + NSSRWLock_UnlockWrite(td->tokensLock); 1.103 + return PR_SUCCESS; 1.104 +} 1.105 + 1.106 +NSS_IMPLEMENT PRStatus 1.107 +STAN_LoadDefaultNSS3TrustDomain ( 1.108 + void 1.109 +) 1.110 +{ 1.111 + NSSTrustDomain *td; 1.112 + SECMODModuleList *mlp; 1.113 + SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock(); 1.114 + int i; 1.115 + 1.116 + if (g_default_trust_domain || g_default_crypto_context) { 1.117 + /* Stan is already initialized or a previous shutdown failed. */ 1.118 + nss_SetError(NSS_ERROR_ALREADY_INITIALIZED); 1.119 + return PR_FAILURE; 1.120 + } 1.121 + td = NSSTrustDomain_Create(NULL, NULL, NULL, NULL); 1.122 + if (!td) { 1.123 + return PR_FAILURE; 1.124 + } 1.125 + /* 1.126 + * Deadlock warning: we should never acquire the moduleLock while 1.127 + * we hold the tokensLock. We can use the NSSRWLock Rank feature to 1.128 + * guarrentee this. tokensLock have a higher rank than module lock. 1.129 + */ 1.130 + td->tokenList = nssList_Create(td->arena, PR_TRUE); 1.131 + if (!td->tokenList) { 1.132 + goto loser; 1.133 + } 1.134 + SECMOD_GetReadLock(moduleLock); 1.135 + NSSRWLock_LockWrite(td->tokensLock); 1.136 + for (mlp = SECMOD_GetDefaultModuleList(); mlp != NULL; mlp=mlp->next) { 1.137 + for (i=0; i < mlp->module->slotCount; i++) { 1.138 + STAN_InitTokenForSlotInfo(td, mlp->module->slots[i]); 1.139 + } 1.140 + } 1.141 + td->tokens = nssList_CreateIterator(td->tokenList); 1.142 + NSSRWLock_UnlockWrite(td->tokensLock); 1.143 + SECMOD_ReleaseReadLock(moduleLock); 1.144 + if (!td->tokens) { 1.145 + goto loser; 1.146 + } 1.147 + g_default_crypto_context = NSSTrustDomain_CreateCryptoContext(td, NULL); 1.148 + if (!g_default_crypto_context) { 1.149 + goto loser; 1.150 + } 1.151 + g_default_trust_domain = td; 1.152 + return PR_SUCCESS; 1.153 + 1.154 + loser: 1.155 + NSSTrustDomain_Destroy(td); 1.156 + return PR_FAILURE; 1.157 +} 1.158 + 1.159 +/* 1.160 + * must be called holding the ModuleListLock (either read or write). 1.161 + */ 1.162 +NSS_IMPLEMENT SECStatus 1.163 +STAN_AddModuleToDefaultTrustDomain ( 1.164 + SECMODModule *module 1.165 +) 1.166 +{ 1.167 + NSSTrustDomain *td; 1.168 + int i; 1.169 + td = STAN_GetDefaultTrustDomain(); 1.170 + for (i=0; i<module->slotCount; i++) { 1.171 + STAN_InitTokenForSlotInfo(td, module->slots[i]); 1.172 + } 1.173 + STAN_ResetTokenInterator(td); 1.174 + return SECSuccess; 1.175 +} 1.176 + 1.177 +/* 1.178 + * must be called holding the ModuleListLock (either read or write). 1.179 + */ 1.180 +NSS_IMPLEMENT SECStatus 1.181 +STAN_RemoveModuleFromDefaultTrustDomain ( 1.182 + SECMODModule *module 1.183 +) 1.184 +{ 1.185 + NSSToken *token; 1.186 + NSSTrustDomain *td; 1.187 + int i; 1.188 + td = STAN_GetDefaultTrustDomain(); 1.189 + NSSRWLock_LockWrite(td->tokensLock); 1.190 + for (i=0; i<module->slotCount; i++) { 1.191 + token = PK11Slot_GetNSSToken(module->slots[i]); 1.192 + if (token) { 1.193 + nssToken_NotifyCertsNotVisible(token); 1.194 + nssList_Remove(td->tokenList, token); 1.195 + PK11Slot_SetNSSToken(module->slots[i], NULL); 1.196 + nssToken_Destroy(token); 1.197 + } 1.198 + } 1.199 + nssListIterator_Destroy(td->tokens); 1.200 + td->tokens = nssList_CreateIterator(td->tokenList); 1.201 + NSSRWLock_UnlockWrite(td->tokensLock); 1.202 + return SECSuccess; 1.203 +} 1.204 + 1.205 +NSS_IMPLEMENT PRStatus 1.206 +STAN_Shutdown() 1.207 +{ 1.208 + PRStatus status = PR_SUCCESS; 1.209 + if (g_default_trust_domain) { 1.210 + if (NSSTrustDomain_Destroy(g_default_trust_domain) == PR_SUCCESS) { 1.211 + g_default_trust_domain = NULL; 1.212 + } else { 1.213 + status = PR_FAILURE; 1.214 + } 1.215 + } 1.216 + if (g_default_crypto_context) { 1.217 + if (NSSCryptoContext_Destroy(g_default_crypto_context) == PR_SUCCESS) { 1.218 + g_default_crypto_context = NULL; 1.219 + } else { 1.220 + status = PR_FAILURE; 1.221 + } 1.222 + } 1.223 + return status; 1.224 +} 1.225 + 1.226 +/* this function should not be a hack; it will be needed in 4.0 (rename) */ 1.227 +NSS_IMPLEMENT NSSItem * 1.228 +STAN_GetCertIdentifierFromDER(NSSArena *arenaOpt, NSSDER *der) 1.229 +{ 1.230 + NSSItem *rvKey; 1.231 + SECItem secDER; 1.232 + SECItem secKey = { 0 }; 1.233 + SECStatus secrv; 1.234 + PLArenaPool *arena; 1.235 + 1.236 + SECITEM_FROM_NSSITEM(&secDER, der); 1.237 + 1.238 + /* nss3 call uses nss3 arena's */ 1.239 + arena = PORT_NewArena(256); 1.240 + if (!arena) { 1.241 + return NULL; 1.242 + } 1.243 + secrv = CERT_KeyFromDERCert(arena, &secDER, &secKey); 1.244 + if (secrv != SECSuccess) { 1.245 + return NULL; 1.246 + } 1.247 + rvKey = nssItem_Create(arenaOpt, NULL, secKey.len, (void *)secKey.data); 1.248 + PORT_FreeArena(arena,PR_FALSE); 1.249 + return rvKey; 1.250 +} 1.251 + 1.252 +NSS_IMPLEMENT PRStatus 1.253 +nssPKIX509_GetIssuerAndSerialFromDER(NSSDER *der, NSSArena *arena, 1.254 + NSSDER *issuer, NSSDER *serial) 1.255 +{ 1.256 + SECStatus secrv; 1.257 + SECItem derCert; 1.258 + SECItem derIssuer = { 0 }; 1.259 + SECItem derSerial = { 0 }; 1.260 + SECITEM_FROM_NSSITEM(&derCert, der); 1.261 + secrv = CERT_SerialNumberFromDERCert(&derCert, &derSerial); 1.262 + if (secrv != SECSuccess) { 1.263 + return PR_FAILURE; 1.264 + } 1.265 + (void)nssItem_Create(arena, serial, derSerial.len, derSerial.data); 1.266 + secrv = CERT_IssuerNameFromDERCert(&derCert, &derIssuer); 1.267 + if (secrv != SECSuccess) { 1.268 + PORT_Free(derSerial.data); 1.269 + return PR_FAILURE; 1.270 + } 1.271 + (void)nssItem_Create(arena, issuer, derIssuer.len, derIssuer.data); 1.272 + PORT_Free(derSerial.data); 1.273 + PORT_Free(derIssuer.data); 1.274 + return PR_SUCCESS; 1.275 +} 1.276 + 1.277 +static NSSItem * 1.278 +nss3certificate_getIdentifier(nssDecodedCert *dc) 1.279 +{ 1.280 + NSSItem *rvID; 1.281 + CERTCertificate *c = (CERTCertificate *)dc->data; 1.282 + rvID = nssItem_Create(NULL, NULL, c->certKey.len, c->certKey.data); 1.283 + return rvID; 1.284 +} 1.285 + 1.286 +static void * 1.287 +nss3certificate_getIssuerIdentifier(nssDecodedCert *dc) 1.288 +{ 1.289 + CERTCertificate *c = (CERTCertificate *)dc->data; 1.290 + return (void *)c->authKeyID; 1.291 +} 1.292 + 1.293 +static nssCertIDMatch 1.294 +nss3certificate_matchIdentifier(nssDecodedCert *dc, void *id) 1.295 +{ 1.296 + CERTCertificate *c = (CERTCertificate *)dc->data; 1.297 + CERTAuthKeyID *authKeyID = (CERTAuthKeyID *)id; 1.298 + SECItem skid; 1.299 + nssCertIDMatch match = nssCertIDMatch_Unknown; 1.300 + 1.301 + /* keyIdentifier */ 1.302 + if (authKeyID->keyID.len > 0 && 1.303 + CERT_FindSubjectKeyIDExtension(c, &skid) == SECSuccess) { 1.304 + PRBool skiEqual; 1.305 + skiEqual = SECITEM_ItemsAreEqual(&authKeyID->keyID, &skid); 1.306 + PORT_Free(skid.data); 1.307 + if (skiEqual) { 1.308 + /* change the state to positive match, but keep going */ 1.309 + match = nssCertIDMatch_Yes; 1.310 + } else { 1.311 + /* exit immediately on failure */ 1.312 + return nssCertIDMatch_No; 1.313 + } 1.314 + } 1.315 + 1.316 + /* issuer/serial (treated as pair) */ 1.317 + if (authKeyID->authCertIssuer) { 1.318 + SECItem *caName = NULL; 1.319 + SECItem *caSN = &authKeyID->authCertSerialNumber; 1.320 + 1.321 + caName = (SECItem *)CERT_GetGeneralNameByType( 1.322 + authKeyID->authCertIssuer, 1.323 + certDirectoryName, PR_TRUE); 1.324 + if (caName != NULL && 1.325 + SECITEM_ItemsAreEqual(&c->derIssuer, caName) && 1.326 + SECITEM_ItemsAreEqual(&c->serialNumber, caSN)) 1.327 + { 1.328 + match = nssCertIDMatch_Yes; 1.329 + } else { 1.330 + match = nssCertIDMatch_Unknown; 1.331 + } 1.332 + } 1.333 + return match; 1.334 +} 1.335 + 1.336 +static PRBool 1.337 +nss3certificate_isValidIssuer(nssDecodedCert *dc) 1.338 +{ 1.339 + CERTCertificate *c = (CERTCertificate *)dc->data; 1.340 + unsigned int ignore; 1.341 + return CERT_IsCACert(c, &ignore); 1.342 +} 1.343 + 1.344 +static NSSUsage * 1.345 +nss3certificate_getUsage(nssDecodedCert *dc) 1.346 +{ 1.347 + /* CERTCertificate *c = (CERTCertificate *)dc->data; */ 1.348 + return NULL; 1.349 +} 1.350 + 1.351 +static PRBool 1.352 +nss3certificate_isValidAtTime(nssDecodedCert *dc, NSSTime *time) 1.353 +{ 1.354 + SECCertTimeValidity validity; 1.355 + CERTCertificate *c = (CERTCertificate *)dc->data; 1.356 + validity = CERT_CheckCertValidTimes(c, NSSTime_GetPRTime(time), PR_TRUE); 1.357 + if (validity == secCertTimeValid) { 1.358 + return PR_TRUE; 1.359 + } 1.360 + return PR_FALSE; 1.361 +} 1.362 + 1.363 +static PRBool 1.364 +nss3certificate_isNewerThan(nssDecodedCert *dc, nssDecodedCert *cmpdc) 1.365 +{ 1.366 + /* I know this isn't right, but this is glue code anyway */ 1.367 + if (cmpdc->type == dc->type) { 1.368 + CERTCertificate *certa = (CERTCertificate *)dc->data; 1.369 + CERTCertificate *certb = (CERTCertificate *)cmpdc->data; 1.370 + return CERT_IsNewer(certa, certb); 1.371 + } 1.372 + return PR_FALSE; 1.373 +} 1.374 + 1.375 +/* CERT_FilterCertListByUsage */ 1.376 +static PRBool 1.377 +nss3certificate_matchUsage(nssDecodedCert *dc, const NSSUsage *usage) 1.378 +{ 1.379 + CERTCertificate *cc; 1.380 + unsigned int requiredKeyUsage = 0; 1.381 + unsigned int requiredCertType = 0; 1.382 + SECStatus secrv; 1.383 + PRBool match; 1.384 + PRBool ca; 1.385 + 1.386 + /* This is for NSS 3.3 functions that do not specify a usage */ 1.387 + if (usage->anyUsage) { 1.388 + return PR_TRUE; 1.389 + } 1.390 + ca = usage->nss3lookingForCA; 1.391 + secrv = CERT_KeyUsageAndTypeForCertUsage(usage->nss3usage, ca, 1.392 + &requiredKeyUsage, 1.393 + &requiredCertType); 1.394 + if (secrv != SECSuccess) { 1.395 + return PR_FALSE; 1.396 + } 1.397 + cc = (CERTCertificate *)dc->data; 1.398 + secrv = CERT_CheckKeyUsage(cc, requiredKeyUsage); 1.399 + match = (PRBool)(secrv == SECSuccess); 1.400 + if (match) { 1.401 + unsigned int certType = 0; 1.402 + if (ca) { 1.403 + (void)CERT_IsCACert(cc, &certType); 1.404 + } else { 1.405 + certType = cc->nsCertType; 1.406 + } 1.407 + if (!(certType & requiredCertType)) { 1.408 + match = PR_FALSE; 1.409 + } 1.410 + } 1.411 + return match; 1.412 +} 1.413 + 1.414 +static PRBool 1.415 +nss3certificate_isTrustedForUsage(nssDecodedCert *dc, const NSSUsage *usage) 1.416 +{ 1.417 + CERTCertificate *cc; 1.418 + PRBool ca; 1.419 + SECStatus secrv; 1.420 + unsigned int requiredFlags; 1.421 + unsigned int trustFlags; 1.422 + SECTrustType trustType; 1.423 + CERTCertTrust trust; 1.424 + 1.425 + /* This is for NSS 3.3 functions that do not specify a usage */ 1.426 + if (usage->anyUsage) { 1.427 + return PR_FALSE; /* XXX is this right? */ 1.428 + } 1.429 + cc = (CERTCertificate *)dc->data; 1.430 + ca = usage->nss3lookingForCA; 1.431 + if (!ca) { 1.432 + PRBool trusted; 1.433 + unsigned int failedFlags; 1.434 + secrv = cert_CheckLeafTrust(cc, usage->nss3usage, 1.435 + &failedFlags, &trusted); 1.436 + return secrv == SECSuccess && trusted; 1.437 + } 1.438 + secrv = CERT_TrustFlagsForCACertUsage(usage->nss3usage, &requiredFlags, 1.439 + &trustType); 1.440 + if (secrv != SECSuccess) { 1.441 + return PR_FALSE; 1.442 + } 1.443 + secrv = CERT_GetCertTrust(cc, &trust); 1.444 + if (secrv != SECSuccess) { 1.445 + return PR_FALSE; 1.446 + } 1.447 + if (trustType == trustTypeNone) { 1.448 + /* normally trustTypeNone usages accept any of the given trust bits 1.449 + * being on as acceptable. */ 1.450 + trustFlags = trust.sslFlags | trust.emailFlags | 1.451 + trust.objectSigningFlags; 1.452 + } else { 1.453 + trustFlags = SEC_GET_TRUST_FLAGS(&trust, trustType); 1.454 + } 1.455 + return (trustFlags & requiredFlags) == requiredFlags; 1.456 +} 1.457 + 1.458 +static NSSASCII7 * 1.459 +nss3certificate_getEmailAddress(nssDecodedCert *dc) 1.460 +{ 1.461 + CERTCertificate *cc = (CERTCertificate *)dc->data; 1.462 + return (cc && cc->emailAddr && cc->emailAddr[0]) 1.463 + ? (NSSASCII7 *)cc->emailAddr : NULL; 1.464 +} 1.465 + 1.466 +static PRStatus 1.467 +nss3certificate_getDERSerialNumber(nssDecodedCert *dc, 1.468 + NSSDER *serial, NSSArena *arena) 1.469 +{ 1.470 + CERTCertificate *cc = (CERTCertificate *)dc->data; 1.471 + SECItem derSerial = { 0 }; 1.472 + SECStatus secrv; 1.473 + secrv = CERT_SerialNumberFromDERCert(&cc->derCert, &derSerial); 1.474 + if (secrv == SECSuccess) { 1.475 + (void)nssItem_Create(arena, serial, derSerial.len, derSerial.data); 1.476 + PORT_Free(derSerial.data); 1.477 + return PR_SUCCESS; 1.478 + } 1.479 + return PR_FAILURE; 1.480 +} 1.481 + 1.482 +/* Returns NULL if "encoding" cannot be decoded. */ 1.483 +NSS_IMPLEMENT nssDecodedCert * 1.484 +nssDecodedPKIXCertificate_Create ( 1.485 + NSSArena *arenaOpt, 1.486 + NSSDER *encoding 1.487 +) 1.488 +{ 1.489 + nssDecodedCert *rvDC = NULL; 1.490 + CERTCertificate *cert; 1.491 + SECItem secDER; 1.492 + 1.493 + SECITEM_FROM_NSSITEM(&secDER, encoding); 1.494 + cert = CERT_DecodeDERCertificate(&secDER, PR_TRUE, NULL); 1.495 + if (cert) { 1.496 + rvDC = nss_ZNEW(arenaOpt, nssDecodedCert); 1.497 + if (rvDC) { 1.498 + rvDC->type = NSSCertificateType_PKIX; 1.499 + rvDC->data = (void *)cert; 1.500 + rvDC->getIdentifier = nss3certificate_getIdentifier; 1.501 + rvDC->getIssuerIdentifier = nss3certificate_getIssuerIdentifier; 1.502 + rvDC->matchIdentifier = nss3certificate_matchIdentifier; 1.503 + rvDC->isValidIssuer = nss3certificate_isValidIssuer; 1.504 + rvDC->getUsage = nss3certificate_getUsage; 1.505 + rvDC->isValidAtTime = nss3certificate_isValidAtTime; 1.506 + rvDC->isNewerThan = nss3certificate_isNewerThan; 1.507 + rvDC->matchUsage = nss3certificate_matchUsage; 1.508 + rvDC->isTrustedForUsage = nss3certificate_isTrustedForUsage; 1.509 + rvDC->getEmailAddress = nss3certificate_getEmailAddress; 1.510 + rvDC->getDERSerialNumber = nss3certificate_getDERSerialNumber; 1.511 + } else { 1.512 + CERT_DestroyCertificate(cert); 1.513 + } 1.514 + } 1.515 + return rvDC; 1.516 +} 1.517 + 1.518 +static nssDecodedCert * 1.519 +create_decoded_pkix_cert_from_nss3cert ( 1.520 + NSSArena *arenaOpt, 1.521 + CERTCertificate *cc 1.522 +) 1.523 +{ 1.524 + nssDecodedCert *rvDC = nss_ZNEW(arenaOpt, nssDecodedCert); 1.525 + if (rvDC) { 1.526 + rvDC->type = NSSCertificateType_PKIX; 1.527 + rvDC->data = (void *)cc; 1.528 + rvDC->getIdentifier = nss3certificate_getIdentifier; 1.529 + rvDC->getIssuerIdentifier = nss3certificate_getIssuerIdentifier; 1.530 + rvDC->matchIdentifier = nss3certificate_matchIdentifier; 1.531 + rvDC->isValidIssuer = nss3certificate_isValidIssuer; 1.532 + rvDC->getUsage = nss3certificate_getUsage; 1.533 + rvDC->isValidAtTime = nss3certificate_isValidAtTime; 1.534 + rvDC->isNewerThan = nss3certificate_isNewerThan; 1.535 + rvDC->matchUsage = nss3certificate_matchUsage; 1.536 + rvDC->isTrustedForUsage = nss3certificate_isTrustedForUsage; 1.537 + rvDC->getEmailAddress = nss3certificate_getEmailAddress; 1.538 + rvDC->getDERSerialNumber = nss3certificate_getDERSerialNumber; 1.539 + } 1.540 + return rvDC; 1.541 +} 1.542 + 1.543 +NSS_IMPLEMENT PRStatus 1.544 +nssDecodedPKIXCertificate_Destroy ( 1.545 + nssDecodedCert *dc 1.546 +) 1.547 +{ 1.548 + CERTCertificate *cert = (CERTCertificate *)dc->data; 1.549 + 1.550 + /* The decoder may only be half initialized (the case where we find we 1.551 + * could not decode the certificate). In this case, there is not cert to 1.552 + * free, just free the dc structure. */ 1.553 + if (cert) { 1.554 + PRBool freeSlot = cert->ownSlot; 1.555 + PK11SlotInfo *slot = cert->slot; 1.556 + PLArenaPool *arena = cert->arena; 1.557 + /* zero cert before freeing. Any stale references to this cert 1.558 + * after this point will probably cause an exception. */ 1.559 + PORT_Memset(cert, 0, sizeof *cert); 1.560 + /* free the arena that contains the cert. */ 1.561 + PORT_FreeArena(arena, PR_FALSE); 1.562 + if (slot && freeSlot) { 1.563 + PK11_FreeSlot(slot); 1.564 + } 1.565 + } 1.566 + nss_ZFreeIf(dc); 1.567 + return PR_SUCCESS; 1.568 +} 1.569 + 1.570 +/* see pk11cert.c:pk11_HandleTrustObject */ 1.571 +static unsigned int 1.572 +get_nss3trust_from_nss4trust(nssTrustLevel t) 1.573 +{ 1.574 + unsigned int rt = 0; 1.575 + if (t == nssTrustLevel_Trusted) { 1.576 + rt |= CERTDB_TERMINAL_RECORD | CERTDB_TRUSTED; 1.577 + } 1.578 + if (t == nssTrustLevel_TrustedDelegator) { 1.579 + rt |= CERTDB_VALID_CA | CERTDB_TRUSTED_CA; 1.580 + } 1.581 + if (t == nssTrustLevel_NotTrusted) { 1.582 + rt |= CERTDB_TERMINAL_RECORD; 1.583 + } 1.584 + if (t == nssTrustLevel_ValidDelegator) { 1.585 + rt |= CERTDB_VALID_CA; 1.586 + } 1.587 + return rt; 1.588 +} 1.589 + 1.590 +static CERTCertTrust * 1.591 +cert_trust_from_stan_trust(NSSTrust *t, PLArenaPool *arena) 1.592 +{ 1.593 + CERTCertTrust *rvTrust; 1.594 + unsigned int client; 1.595 + if (!t) { 1.596 + return NULL; 1.597 + } 1.598 + rvTrust = PORT_ArenaAlloc(arena, sizeof(CERTCertTrust)); 1.599 + if (!rvTrust) return NULL; 1.600 + rvTrust->sslFlags = get_nss3trust_from_nss4trust(t->serverAuth); 1.601 + client = get_nss3trust_from_nss4trust(t->clientAuth); 1.602 + if (client & (CERTDB_TRUSTED_CA|CERTDB_NS_TRUSTED_CA)) { 1.603 + client &= ~(CERTDB_TRUSTED_CA|CERTDB_NS_TRUSTED_CA); 1.604 + rvTrust->sslFlags |= CERTDB_TRUSTED_CLIENT_CA; 1.605 + } 1.606 + rvTrust->sslFlags |= client; 1.607 + rvTrust->emailFlags = get_nss3trust_from_nss4trust(t->emailProtection); 1.608 + rvTrust->objectSigningFlags = get_nss3trust_from_nss4trust(t->codeSigning); 1.609 + return rvTrust; 1.610 +} 1.611 + 1.612 +CERTCertTrust * 1.613 +nssTrust_GetCERTCertTrustForCert(NSSCertificate *c, CERTCertificate *cc) 1.614 +{ 1.615 + CERTCertTrust *rvTrust = NULL; 1.616 + NSSTrustDomain *td = STAN_GetDefaultTrustDomain(); 1.617 + NSSTrust *t; 1.618 + t = nssTrustDomain_FindTrustForCertificate(td, c); 1.619 + if (t) { 1.620 + rvTrust = cert_trust_from_stan_trust(t, cc->arena); 1.621 + if (!rvTrust) { 1.622 + nssTrust_Destroy(t); 1.623 + return NULL; 1.624 + } 1.625 + nssTrust_Destroy(t); 1.626 + } else { 1.627 + rvTrust = PORT_ArenaAlloc(cc->arena, sizeof(CERTCertTrust)); 1.628 + if (!rvTrust) { 1.629 + return NULL; 1.630 + } 1.631 + memset(rvTrust, 0, sizeof(*rvTrust)); 1.632 + } 1.633 + if (NSSCertificate_IsPrivateKeyAvailable(c, NULL, NULL)) { 1.634 + rvTrust->sslFlags |= CERTDB_USER; 1.635 + rvTrust->emailFlags |= CERTDB_USER; 1.636 + rvTrust->objectSigningFlags |= CERTDB_USER; 1.637 + } 1.638 + return rvTrust; 1.639 +} 1.640 + 1.641 +static nssCryptokiInstance * 1.642 +get_cert_instance(NSSCertificate *c) 1.643 +{ 1.644 + nssCryptokiObject *instance, **ci; 1.645 + nssCryptokiObject **instances = nssPKIObject_GetInstances(&c->object); 1.646 + if (!instances) { 1.647 + return NULL; 1.648 + } 1.649 + instance = NULL; 1.650 + for (ci = instances; *ci; ci++) { 1.651 + if (!instance) { 1.652 + instance = nssCryptokiObject_Clone(*ci); 1.653 + } else { 1.654 + /* This only really works for two instances... But 3.4 can't 1.655 + * handle more anyway. The logic is, if there are multiple 1.656 + * instances, prefer the one that is not internal (e.g., on 1.657 + * a hardware device. 1.658 + */ 1.659 + if (PK11_IsInternal(instance->token->pk11slot)) { 1.660 + nssCryptokiObject_Destroy(instance); 1.661 + instance = nssCryptokiObject_Clone(*ci); 1.662 + } 1.663 + } 1.664 + } 1.665 + nssCryptokiObjectArray_Destroy(instances); 1.666 + return instance; 1.667 +} 1.668 + 1.669 +char * 1.670 +STAN_GetCERTCertificateNameForInstance ( 1.671 + PLArenaPool *arenaOpt, 1.672 + NSSCertificate *c, 1.673 + nssCryptokiInstance *instance 1.674 +) 1.675 +{ 1.676 + NSSCryptoContext *context = c->object.cryptoContext; 1.677 + PRStatus nssrv; 1.678 + int nicklen, tokenlen, len; 1.679 + NSSUTF8 *tokenName = NULL; 1.680 + NSSUTF8 *stanNick = NULL; 1.681 + char *nickname = NULL; 1.682 + char *nick; 1.683 + 1.684 + if (instance) { 1.685 + stanNick = instance->label; 1.686 + } else if (context) { 1.687 + stanNick = c->object.tempName; 1.688 + } 1.689 + if (stanNick) { 1.690 + /* fill other fields needed by NSS3 functions using CERTCertificate */ 1.691 + if (instance && (!PK11_IsInternalKeySlot(instance->token->pk11slot) || 1.692 + PORT_Strchr(stanNick, ':') != NULL) ) { 1.693 + tokenName = nssToken_GetName(instance->token); 1.694 + tokenlen = nssUTF8_Size(tokenName, &nssrv); 1.695 + } else { 1.696 + /* don't use token name for internal slot; 3.3 didn't */ 1.697 + tokenlen = 0; 1.698 + } 1.699 + nicklen = nssUTF8_Size(stanNick, &nssrv); 1.700 + len = tokenlen + nicklen; 1.701 + if (arenaOpt) { 1.702 + nickname = PORT_ArenaAlloc(arenaOpt, len); 1.703 + } else { 1.704 + nickname = PORT_Alloc(len); 1.705 + } 1.706 + nick = nickname; 1.707 + if (tokenName) { 1.708 + memcpy(nick, tokenName, tokenlen-1); 1.709 + nick += tokenlen-1; 1.710 + *nick++ = ':'; 1.711 + } 1.712 + memcpy(nick, stanNick, nicklen-1); 1.713 + nickname[len-1] = '\0'; 1.714 + } 1.715 + return nickname; 1.716 +} 1.717 + 1.718 +char * 1.719 +STAN_GetCERTCertificateName(PLArenaPool *arenaOpt, NSSCertificate *c) 1.720 +{ 1.721 + char * result; 1.722 + nssCryptokiInstance *instance = get_cert_instance(c); 1.723 + /* It's OK to call this function, even if instance is NULL */ 1.724 + result = STAN_GetCERTCertificateNameForInstance(arenaOpt, c, instance); 1.725 + if (instance) 1.726 + nssCryptokiObject_Destroy(instance); 1.727 + return result; 1.728 +} 1.729 + 1.730 +static void 1.731 +fill_CERTCertificateFields(NSSCertificate *c, CERTCertificate *cc, PRBool forced) 1.732 +{ 1.733 + CERTCertTrust* trust = NULL; 1.734 + NSSTrust *nssTrust; 1.735 + NSSCryptoContext *context = c->object.cryptoContext; 1.736 + nssCryptokiInstance *instance; 1.737 + NSSUTF8 *stanNick = NULL; 1.738 + 1.739 + /* We are holding the base class object's lock on entry of this function 1.740 + * This lock protects writes to fields of the CERTCertificate . 1.741 + * It is also needed by some functions to compute values such as trust. 1.742 + */ 1.743 + instance = get_cert_instance(c); 1.744 + 1.745 + if (instance) { 1.746 + stanNick = instance->label; 1.747 + } else if (context) { 1.748 + stanNick = c->object.tempName; 1.749 + } 1.750 + /* fill other fields needed by NSS3 functions using CERTCertificate */ 1.751 + if ((!cc->nickname && stanNick) || forced) { 1.752 + PRStatus nssrv; 1.753 + int nicklen, tokenlen, len; 1.754 + NSSUTF8 *tokenName = NULL; 1.755 + char *nick; 1.756 + if (instance && 1.757 + (!PK11_IsInternalKeySlot(instance->token->pk11slot) || 1.758 + (stanNick && PORT_Strchr(stanNick, ':') != NULL))) { 1.759 + tokenName = nssToken_GetName(instance->token); 1.760 + tokenlen = nssUTF8_Size(tokenName, &nssrv); 1.761 + } else { 1.762 + /* don't use token name for internal slot; 3.3 didn't */ 1.763 + tokenlen = 0; 1.764 + } 1.765 + if (stanNick) { 1.766 + nicklen = nssUTF8_Size(stanNick, &nssrv); 1.767 + len = tokenlen + nicklen; 1.768 + nick = PORT_ArenaAlloc(cc->arena, len); 1.769 + if (tokenName) { 1.770 + memcpy(nick, tokenName, tokenlen-1); 1.771 + nick[tokenlen-1] = ':'; 1.772 + memcpy(nick+tokenlen, stanNick, nicklen-1); 1.773 + } else { 1.774 + memcpy(nick, stanNick, nicklen-1); 1.775 + } 1.776 + nick[len-1] = '\0'; 1.777 + cc->nickname = nick; 1.778 + } else { 1.779 + cc->nickname = NULL; 1.780 + } 1.781 + } 1.782 + if (context) { 1.783 + /* trust */ 1.784 + nssTrust = nssCryptoContext_FindTrustForCertificate(context, c); 1.785 + if (!nssTrust) { 1.786 + /* chicken and egg issue: 1.787 + * 1.788 + * c->issuer and c->serial are empty at this point, but 1.789 + * nssTrustDomain_FindTrustForCertificate use them to look up 1.790 + * up the trust object, so we point them to cc->derIssuer and 1.791 + * cc->serialNumber. 1.792 + * 1.793 + * Our caller will fill these in with proper arena copies when we 1.794 + * return. */ 1.795 + c->issuer.data = cc->derIssuer.data; 1.796 + c->issuer.size = cc->derIssuer.len; 1.797 + c->serial.data = cc->serialNumber.data; 1.798 + c->serial.size = cc->serialNumber.len; 1.799 + nssTrust = nssTrustDomain_FindTrustForCertificate(context->td, c); 1.800 + } 1.801 + if (nssTrust) { 1.802 + trust = cert_trust_from_stan_trust(nssTrust, cc->arena); 1.803 + if (trust) { 1.804 + /* we should destroy cc->trust before replacing it, but it's 1.805 + allocated in cc->arena, so memory growth will occur on each 1.806 + refresh */ 1.807 + CERT_LockCertTrust(cc); 1.808 + cc->trust = trust; 1.809 + CERT_UnlockCertTrust(cc); 1.810 + } 1.811 + nssTrust_Destroy(nssTrust); 1.812 + } 1.813 + } else if (instance) { 1.814 + /* slot */ 1.815 + if (cc->slot != instance->token->pk11slot) { 1.816 + if (cc->slot) { 1.817 + PK11_FreeSlot(cc->slot); 1.818 + } 1.819 + cc->slot = PK11_ReferenceSlot(instance->token->pk11slot); 1.820 + } 1.821 + cc->ownSlot = PR_TRUE; 1.822 + /* pkcs11ID */ 1.823 + cc->pkcs11ID = instance->handle; 1.824 + /* trust */ 1.825 + trust = nssTrust_GetCERTCertTrustForCert(c, cc); 1.826 + if (trust) { 1.827 + /* we should destroy cc->trust before replacing it, but it's 1.828 + allocated in cc->arena, so memory growth will occur on each 1.829 + refresh */ 1.830 + CERT_LockCertTrust(cc); 1.831 + cc->trust = trust; 1.832 + CERT_UnlockCertTrust(cc); 1.833 + } 1.834 + nssCryptokiObject_Destroy(instance); 1.835 + } 1.836 + /* database handle is now the trust domain */ 1.837 + cc->dbhandle = c->object.trustDomain; 1.838 + /* subjectList ? */ 1.839 + /* istemp and isperm are supported in NSS 3.4 */ 1.840 + cc->istemp = PR_FALSE; /* CERT_NewTemp will override this */ 1.841 + cc->isperm = PR_TRUE; /* by default */ 1.842 + /* pointer back */ 1.843 + cc->nssCertificate = c; 1.844 + if (trust) { 1.845 + /* force the cert type to be recomputed to include trust info */ 1.846 + PRUint32 nsCertType = cert_ComputeCertType(cc); 1.847 + 1.848 + /* Assert that it is safe to cast &cc->nsCertType to "PRInt32 *" */ 1.849 + PORT_Assert(sizeof(cc->nsCertType) == sizeof(PRInt32)); 1.850 + PR_ATOMIC_SET((PRInt32 *)&cc->nsCertType, nsCertType); 1.851 + } 1.852 +} 1.853 + 1.854 +static CERTCertificate * 1.855 +stan_GetCERTCertificate(NSSCertificate *c, PRBool forceUpdate) 1.856 +{ 1.857 + nssDecodedCert *dc = NULL; 1.858 + CERTCertificate *cc = NULL; 1.859 + CERTCertTrust certTrust; 1.860 + 1.861 + nssPKIObject_Lock(&c->object); 1.862 + 1.863 + dc = c->decoding; 1.864 + if (!dc) { 1.865 + dc = nssDecodedPKIXCertificate_Create(NULL, &c->encoding); 1.866 + if (!dc) { 1.867 + goto loser; 1.868 + } 1.869 + cc = (CERTCertificate *)dc->data; 1.870 + PORT_Assert(cc); /* software error */ 1.871 + if (!cc) { 1.872 + nssDecodedPKIXCertificate_Destroy(dc); 1.873 + nss_SetError(NSS_ERROR_INTERNAL_ERROR); 1.874 + goto loser; 1.875 + } 1.876 + PORT_Assert(!c->decoding); 1.877 + if (!c->decoding) { 1.878 + c->decoding = dc; 1.879 + } else { 1.880 + /* this should never happen. Fail. */ 1.881 + nssDecodedPKIXCertificate_Destroy(dc); 1.882 + nss_SetError(NSS_ERROR_INTERNAL_ERROR); 1.883 + goto loser; 1.884 + } 1.885 + } 1.886 + cc = (CERTCertificate *)dc->data; 1.887 + PORT_Assert(cc); 1.888 + if (!cc) { 1.889 + nss_SetError(NSS_ERROR_INTERNAL_ERROR); 1.890 + goto loser; 1.891 + } 1.892 + if (!cc->nssCertificate || forceUpdate) { 1.893 + fill_CERTCertificateFields(c, cc, forceUpdate); 1.894 + } else if (CERT_GetCertTrust(cc, &certTrust) != SECSuccess && 1.895 + !c->object.cryptoContext) { 1.896 + /* if it's a perm cert, it might have been stored before the 1.897 + * trust, so look for the trust again. But a temp cert can be 1.898 + * ignored. 1.899 + */ 1.900 + CERTCertTrust* trust = NULL; 1.901 + trust = nssTrust_GetCERTCertTrustForCert(c, cc); 1.902 + 1.903 + CERT_LockCertTrust(cc); 1.904 + cc->trust = trust; 1.905 + CERT_UnlockCertTrust(cc); 1.906 + } 1.907 + 1.908 + loser: 1.909 + nssPKIObject_Unlock(&c->object); 1.910 + return cc; 1.911 +} 1.912 + 1.913 +NSS_IMPLEMENT CERTCertificate * 1.914 +STAN_ForceCERTCertificateUpdate(NSSCertificate *c) 1.915 +{ 1.916 + if (c->decoding) { 1.917 + return stan_GetCERTCertificate(c, PR_TRUE); 1.918 + } 1.919 + return NULL; 1.920 +} 1.921 + 1.922 +NSS_IMPLEMENT CERTCertificate * 1.923 +STAN_GetCERTCertificate(NSSCertificate *c) 1.924 +{ 1.925 + return stan_GetCERTCertificate(c, PR_FALSE); 1.926 +} 1.927 +/* 1.928 + * many callers of STAN_GetCERTCertificate() intend that 1.929 + * the CERTCertificate returned inherits the reference to the 1.930 + * NSSCertificate. For these callers it's convenient to have 1.931 + * this function 'own' the reference and either return a valid 1.932 + * CERTCertificate structure which inherits the reference or 1.933 + * destroy the reference to NSSCertificate and returns NULL. 1.934 + */ 1.935 +NSS_IMPLEMENT CERTCertificate * 1.936 +STAN_GetCERTCertificateOrRelease(NSSCertificate *c) 1.937 +{ 1.938 + CERTCertificate *nss3cert = stan_GetCERTCertificate(c, PR_FALSE); 1.939 + if (!nss3cert) { 1.940 + nssCertificate_Destroy(c); 1.941 + } 1.942 + return nss3cert; 1.943 +} 1.944 + 1.945 +static nssTrustLevel 1.946 +get_stan_trust(unsigned int t, PRBool isClientAuth) 1.947 +{ 1.948 + if (isClientAuth) { 1.949 + if (t & CERTDB_TRUSTED_CLIENT_CA) { 1.950 + return nssTrustLevel_TrustedDelegator; 1.951 + } 1.952 + } else { 1.953 + if (t & CERTDB_TRUSTED_CA || t & CERTDB_NS_TRUSTED_CA) { 1.954 + return nssTrustLevel_TrustedDelegator; 1.955 + } 1.956 + } 1.957 + if (t & CERTDB_TRUSTED) { 1.958 + return nssTrustLevel_Trusted; 1.959 + } 1.960 + if (t & CERTDB_TERMINAL_RECORD) { 1.961 + return nssTrustLevel_NotTrusted; 1.962 + } 1.963 + if (t & CERTDB_VALID_CA) { 1.964 + return nssTrustLevel_ValidDelegator; 1.965 + } 1.966 + return nssTrustLevel_MustVerify; 1.967 +} 1.968 + 1.969 +NSS_EXTERN NSSCertificate * 1.970 +STAN_GetNSSCertificate(CERTCertificate *cc) 1.971 +{ 1.972 + NSSCertificate *c; 1.973 + nssCryptokiInstance *instance; 1.974 + nssPKIObject *pkiob; 1.975 + NSSArena *arena; 1.976 + c = cc->nssCertificate; 1.977 + if (c) { 1.978 + return c; 1.979 + } 1.980 + /* i don't think this should happen. but if it can, need to create 1.981 + * NSSCertificate from CERTCertificate values here. */ 1.982 + /* Yup, it can happen. */ 1.983 + arena = NSSArena_Create(); 1.984 + if (!arena) { 1.985 + return NULL; 1.986 + } 1.987 + c = nss_ZNEW(arena, NSSCertificate); 1.988 + if (!c) { 1.989 + nssArena_Destroy(arena); 1.990 + return NULL; 1.991 + } 1.992 + NSSITEM_FROM_SECITEM(&c->encoding, &cc->derCert); 1.993 + c->type = NSSCertificateType_PKIX; 1.994 + pkiob = nssPKIObject_Create(arena, NULL, cc->dbhandle, NULL, nssPKIMonitor); 1.995 + if (!pkiob) { 1.996 + nssArena_Destroy(arena); 1.997 + return NULL; 1.998 + } 1.999 + c->object = *pkiob; 1.1000 + nssItem_Create(arena, 1.1001 + &c->issuer, cc->derIssuer.len, cc->derIssuer.data); 1.1002 + nssItem_Create(arena, 1.1003 + &c->subject, cc->derSubject.len, cc->derSubject.data); 1.1004 + if (PR_TRUE) { 1.1005 + /* CERTCertificate stores serial numbers decoded. I need the DER 1.1006 + * here. sigh. 1.1007 + */ 1.1008 + SECItem derSerial; 1.1009 + SECStatus secrv; 1.1010 + secrv = CERT_SerialNumberFromDERCert(&cc->derCert, &derSerial); 1.1011 + if (secrv == SECFailure) { 1.1012 + nssArena_Destroy(arena); 1.1013 + return NULL; 1.1014 + } 1.1015 + nssItem_Create(arena, &c->serial, derSerial.len, derSerial.data); 1.1016 + PORT_Free(derSerial.data); 1.1017 + } 1.1018 + if (cc->emailAddr && cc->emailAddr[0]) { 1.1019 + c->email = nssUTF8_Create(arena, 1.1020 + nssStringType_PrintableString, 1.1021 + (NSSUTF8 *)cc->emailAddr, 1.1022 + PORT_Strlen(cc->emailAddr)); 1.1023 + } 1.1024 + if (cc->slot) { 1.1025 + instance = nss_ZNEW(arena, nssCryptokiInstance); 1.1026 + if (!instance) { 1.1027 + nssArena_Destroy(arena); 1.1028 + return NULL; 1.1029 + } 1.1030 + instance->token = nssToken_AddRef(PK11Slot_GetNSSToken(cc->slot)); 1.1031 + instance->handle = cc->pkcs11ID; 1.1032 + instance->isTokenObject = PR_TRUE; 1.1033 + if (cc->nickname) { 1.1034 + instance->label = nssUTF8_Create(arena, 1.1035 + nssStringType_UTF8String, 1.1036 + (NSSUTF8 *)cc->nickname, 1.1037 + PORT_Strlen(cc->nickname)); 1.1038 + } 1.1039 + nssPKIObject_AddInstance(&c->object, instance); 1.1040 + } 1.1041 + c->decoding = create_decoded_pkix_cert_from_nss3cert(NULL, cc); 1.1042 + cc->nssCertificate = c; 1.1043 + return c; 1.1044 +} 1.1045 + 1.1046 +static NSSToken* 1.1047 +stan_GetTrustToken ( 1.1048 + NSSCertificate *c 1.1049 +) 1.1050 +{ 1.1051 + NSSToken *ttok = NULL; 1.1052 + NSSToken *rtok = NULL; 1.1053 + NSSToken *tok = NULL; 1.1054 + nssCryptokiObject **ip; 1.1055 + nssCryptokiObject **instances = nssPKIObject_GetInstances(&c->object); 1.1056 + if (!instances) { 1.1057 + return PR_FALSE; 1.1058 + } 1.1059 + for (ip = instances; *ip; ip++) { 1.1060 + nssCryptokiObject *instance = *ip; 1.1061 + nssCryptokiObject *to = 1.1062 + nssToken_FindTrustForCertificate(instance->token, NULL, 1.1063 + &c->encoding, &c->issuer, &c->serial, 1.1064 + nssTokenSearchType_TokenOnly); 1.1065 + NSSToken *ctok = instance->token; 1.1066 + PRBool ro = PK11_IsReadOnly(ctok->pk11slot); 1.1067 + 1.1068 + if (to) { 1.1069 + nssCryptokiObject_Destroy(to); 1.1070 + ttok = ctok; 1.1071 + if (!ro) { 1.1072 + break; 1.1073 + } 1.1074 + } else { 1.1075 + if (!rtok && ro) { 1.1076 + rtok = ctok; 1.1077 + } 1.1078 + if (!tok && !ro) { 1.1079 + tok = ctok; 1.1080 + } 1.1081 + } 1.1082 + } 1.1083 + nssCryptokiObjectArray_Destroy(instances); 1.1084 + return ttok ? ttok : (tok ? tok : rtok); 1.1085 +} 1.1086 + 1.1087 +NSS_EXTERN PRStatus 1.1088 +STAN_ChangeCertTrust(CERTCertificate *cc, CERTCertTrust *trust) 1.1089 +{ 1.1090 + PRStatus nssrv; 1.1091 + NSSCertificate *c = STAN_GetNSSCertificate(cc); 1.1092 + NSSToken *tok; 1.1093 + NSSTrustDomain *td; 1.1094 + NSSTrust *nssTrust; 1.1095 + NSSArena *arena; 1.1096 + CERTCertTrust *oldTrust; 1.1097 + CERTCertTrust *newTrust; 1.1098 + nssListIterator *tokens; 1.1099 + PRBool moving_object; 1.1100 + nssCryptokiObject *newInstance; 1.1101 + nssPKIObject *pkiob; 1.1102 + 1.1103 + if (c == NULL) { 1.1104 + return PR_FAILURE; 1.1105 + } 1.1106 + oldTrust = nssTrust_GetCERTCertTrustForCert(c, cc); 1.1107 + if (oldTrust) { 1.1108 + if (memcmp(oldTrust, trust, sizeof (CERTCertTrust)) == 0) { 1.1109 + /* ... and the new trust is no different, done) */ 1.1110 + return PR_SUCCESS; 1.1111 + } else { 1.1112 + /* take over memory already allocated in cc's arena */ 1.1113 + newTrust = oldTrust; 1.1114 + } 1.1115 + } else { 1.1116 + newTrust = PORT_ArenaAlloc(cc->arena, sizeof(CERTCertTrust)); 1.1117 + } 1.1118 + memcpy(newTrust, trust, sizeof(CERTCertTrust)); 1.1119 + CERT_LockCertTrust(cc); 1.1120 + cc->trust = newTrust; 1.1121 + CERT_UnlockCertTrust(cc); 1.1122 + /* Set the NSSCerticate's trust */ 1.1123 + arena = nssArena_Create(); 1.1124 + if (!arena) return PR_FAILURE; 1.1125 + nssTrust = nss_ZNEW(arena, NSSTrust); 1.1126 + if (!nssTrust) { 1.1127 + nssArena_Destroy(arena); 1.1128 + return PR_FAILURE; 1.1129 + } 1.1130 + pkiob = nssPKIObject_Create(arena, NULL, cc->dbhandle, NULL, nssPKILock); 1.1131 + if (!pkiob) { 1.1132 + nssArena_Destroy(arena); 1.1133 + return PR_FAILURE; 1.1134 + } 1.1135 + nssTrust->object = *pkiob; 1.1136 + nssTrust->certificate = c; 1.1137 + nssTrust->serverAuth = get_stan_trust(trust->sslFlags, PR_FALSE); 1.1138 + nssTrust->clientAuth = get_stan_trust(trust->sslFlags, PR_TRUE); 1.1139 + nssTrust->emailProtection = get_stan_trust(trust->emailFlags, PR_FALSE); 1.1140 + nssTrust->codeSigning = get_stan_trust(trust->objectSigningFlags, PR_FALSE); 1.1141 + nssTrust->stepUpApproved = 1.1142 + (PRBool)(trust->sslFlags & CERTDB_GOVT_APPROVED_CA); 1.1143 + if (c->object.cryptoContext != NULL) { 1.1144 + /* The cert is in a context, set the trust there */ 1.1145 + NSSCryptoContext *cc = c->object.cryptoContext; 1.1146 + nssrv = nssCryptoContext_ImportTrust(cc, nssTrust); 1.1147 + if (nssrv != PR_SUCCESS) { 1.1148 + goto done; 1.1149 + } 1.1150 + if (c->object.numInstances == 0) { 1.1151 + /* The context is the only instance, finished */ 1.1152 + goto done; 1.1153 + } 1.1154 + } 1.1155 + td = STAN_GetDefaultTrustDomain(); 1.1156 + tok = stan_GetTrustToken(c); 1.1157 + moving_object = PR_FALSE; 1.1158 + if (tok && PK11_IsReadOnly(tok->pk11slot)) { 1.1159 + NSSRWLock_LockRead(td->tokensLock); 1.1160 + tokens = nssList_CreateIterator(td->tokenList); 1.1161 + if (!tokens) { 1.1162 + nssrv = PR_FAILURE; 1.1163 + NSSRWLock_UnlockRead(td->tokensLock); 1.1164 + goto done; 1.1165 + } 1.1166 + for (tok = (NSSToken *)nssListIterator_Start(tokens); 1.1167 + tok != (NSSToken *)NULL; 1.1168 + tok = (NSSToken *)nssListIterator_Next(tokens)) 1.1169 + { 1.1170 + if (!PK11_IsReadOnly(tok->pk11slot)) break; 1.1171 + } 1.1172 + nssListIterator_Finish(tokens); 1.1173 + nssListIterator_Destroy(tokens); 1.1174 + NSSRWLock_UnlockRead(td->tokensLock); 1.1175 + moving_object = PR_TRUE; 1.1176 + } 1.1177 + if (tok) { 1.1178 + if (moving_object) { 1.1179 + /* this is kind of hacky. the softoken needs the cert 1.1180 + * object in order to store trust. forcing it to be perm 1.1181 + */ 1.1182 + NSSUTF8 *nickname = nssCertificate_GetNickname(c, NULL); 1.1183 + NSSASCII7 *email = NULL; 1.1184 + 1.1185 + if (PK11_IsInternal(tok->pk11slot)) { 1.1186 + email = c->email; 1.1187 + } 1.1188 + newInstance = nssToken_ImportCertificate(tok, NULL, 1.1189 + NSSCertificateType_PKIX, 1.1190 + &c->id, 1.1191 + nickname, 1.1192 + &c->encoding, 1.1193 + &c->issuer, 1.1194 + &c->subject, 1.1195 + &c->serial, 1.1196 + email, 1.1197 + PR_TRUE); 1.1198 + nss_ZFreeIf(nickname); 1.1199 + nickname = NULL; 1.1200 + if (!newInstance) { 1.1201 + nssrv = PR_FAILURE; 1.1202 + goto done; 1.1203 + } 1.1204 + nssPKIObject_AddInstance(&c->object, newInstance); 1.1205 + } 1.1206 + newInstance = nssToken_ImportTrust(tok, NULL, &c->encoding, 1.1207 + &c->issuer, &c->serial, 1.1208 + nssTrust->serverAuth, 1.1209 + nssTrust->clientAuth, 1.1210 + nssTrust->codeSigning, 1.1211 + nssTrust->emailProtection, 1.1212 + nssTrust->stepUpApproved, PR_TRUE); 1.1213 + /* If the selected token can't handle trust, dump the trust on 1.1214 + * the internal token */ 1.1215 + if (!newInstance && !PK11_IsInternalKeySlot(tok->pk11slot)) { 1.1216 + PK11SlotInfo *slot = PK11_GetInternalKeySlot(); 1.1217 + NSSUTF8 *nickname = nssCertificate_GetNickname(c, NULL); 1.1218 + NSSASCII7 *email = c->email; 1.1219 + tok = PK11Slot_GetNSSToken(slot); 1.1220 + PK11_FreeSlot(slot); 1.1221 + 1.1222 + newInstance = nssToken_ImportCertificate(tok, NULL, 1.1223 + NSSCertificateType_PKIX, 1.1224 + &c->id, 1.1225 + nickname, 1.1226 + &c->encoding, 1.1227 + &c->issuer, 1.1228 + &c->subject, 1.1229 + &c->serial, 1.1230 + email, 1.1231 + PR_TRUE); 1.1232 + nss_ZFreeIf(nickname); 1.1233 + nickname = NULL; 1.1234 + if (!newInstance) { 1.1235 + nssrv = PR_FAILURE; 1.1236 + goto done; 1.1237 + } 1.1238 + nssPKIObject_AddInstance(&c->object, newInstance); 1.1239 + newInstance = nssToken_ImportTrust(tok, NULL, &c->encoding, 1.1240 + &c->issuer, &c->serial, 1.1241 + nssTrust->serverAuth, 1.1242 + nssTrust->clientAuth, 1.1243 + nssTrust->codeSigning, 1.1244 + nssTrust->emailProtection, 1.1245 + nssTrust->stepUpApproved, PR_TRUE); 1.1246 + } 1.1247 + if (newInstance) { 1.1248 + nssCryptokiObject_Destroy(newInstance); 1.1249 + nssrv = PR_SUCCESS; 1.1250 + } else { 1.1251 + nssrv = PR_FAILURE; 1.1252 + } 1.1253 + } else { 1.1254 + nssrv = PR_FAILURE; 1.1255 + } 1.1256 +done: 1.1257 + (void)nssTrust_Destroy(nssTrust); 1.1258 + return nssrv; 1.1259 +} 1.1260 + 1.1261 +/* 1.1262 +** Delete trust objects matching the given slot. 1.1263 +** Returns error if a device fails to delete. 1.1264 +** 1.1265 +** This function has the side effect of moving the 1.1266 +** surviving entries to the front of the object list 1.1267 +** and nullifying the rest. 1.1268 +*/ 1.1269 +static PRStatus 1.1270 +DeleteCertTrustMatchingSlot(PK11SlotInfo *pk11slot, nssPKIObject *tObject) 1.1271 +{ 1.1272 + int numNotDestroyed = 0; /* the ones skipped plus the failures */ 1.1273 + int failureCount = 0; /* actual deletion failures by devices */ 1.1274 + int index; 1.1275 + 1.1276 + nssPKIObject_Lock(tObject); 1.1277 + /* Keep going even if a module fails to delete. */ 1.1278 + for (index = 0; index < tObject->numInstances; index++) { 1.1279 + nssCryptokiObject *instance = tObject->instances[index]; 1.1280 + if (!instance) { 1.1281 + continue; 1.1282 + } 1.1283 + 1.1284 + /* ReadOnly and not matched treated the same */ 1.1285 + if (PK11_IsReadOnly(instance->token->pk11slot) || 1.1286 + pk11slot != instance->token->pk11slot) { 1.1287 + tObject->instances[numNotDestroyed++] = instance; 1.1288 + continue; 1.1289 + } 1.1290 + 1.1291 + /* Here we have found a matching one */ 1.1292 + tObject->instances[index] = NULL; 1.1293 + if (nssToken_DeleteStoredObject(instance) == PR_SUCCESS) { 1.1294 + nssCryptokiObject_Destroy(instance); 1.1295 + } else { 1.1296 + tObject->instances[numNotDestroyed++] = instance; 1.1297 + failureCount++; 1.1298 + } 1.1299 + 1.1300 + } 1.1301 + if (numNotDestroyed == 0) { 1.1302 + nss_ZFreeIf(tObject->instances); 1.1303 + tObject->numInstances = 0; 1.1304 + } else { 1.1305 + tObject->numInstances = numNotDestroyed; 1.1306 + } 1.1307 + 1.1308 + nssPKIObject_Unlock(tObject); 1.1309 + 1.1310 + return failureCount == 0 ? PR_SUCCESS : PR_FAILURE; 1.1311 +} 1.1312 + 1.1313 +/* 1.1314 +** Delete trust objects matching the slot of the given certificate. 1.1315 +** Returns an error if any device fails to delete. 1.1316 +*/ 1.1317 +NSS_EXTERN PRStatus 1.1318 +STAN_DeleteCertTrustMatchingSlot(NSSCertificate *c) 1.1319 +{ 1.1320 + PRStatus nssrv = PR_SUCCESS; 1.1321 + 1.1322 + NSSTrustDomain *td = STAN_GetDefaultTrustDomain(); 1.1323 + NSSTrust *nssTrust = nssTrustDomain_FindTrustForCertificate(td, c); 1.1324 + /* caller made sure nssTrust isn't NULL */ 1.1325 + nssPKIObject *tobject = &nssTrust->object; 1.1326 + nssPKIObject *cobject = &c->object; 1.1327 + int i; 1.1328 + 1.1329 + /* Iterate through the cert and trust object instances looking for 1.1330 + * those with matching pk11 slots to delete. Even if some device 1.1331 + * can't delete we keep going. Keeping a status variable for the 1.1332 + * loop so that once it's failed the other gets set. 1.1333 + */ 1.1334 + NSSRWLock_LockRead(td->tokensLock); 1.1335 + nssPKIObject_Lock(cobject); 1.1336 + for (i = 0; i < cobject->numInstances; i++) { 1.1337 + nssCryptokiObject *cInstance = cobject->instances[i]; 1.1338 + if (cInstance && !PK11_IsReadOnly(cInstance->token->pk11slot)) { 1.1339 + PRStatus status; 1.1340 + if (!tobject->numInstances || !tobject->instances) continue; 1.1341 + status = DeleteCertTrustMatchingSlot(cInstance->token->pk11slot, tobject); 1.1342 + if (status == PR_FAILURE) { 1.1343 + /* set the outer one but keep going */ 1.1344 + nssrv = PR_FAILURE; 1.1345 + } 1.1346 + } 1.1347 + } 1.1348 + nssPKIObject_Unlock(cobject); 1.1349 + NSSRWLock_UnlockRead(td->tokensLock); 1.1350 + return nssrv; 1.1351 +} 1.1352 + 1.1353 +/* CERT_TraversePermCertsForSubject */ 1.1354 +NSS_IMPLEMENT PRStatus 1.1355 +nssTrustDomain_TraverseCertificatesBySubject ( 1.1356 + NSSTrustDomain *td, 1.1357 + NSSDER *subject, 1.1358 + PRStatus (*callback)(NSSCertificate *c, void *arg), 1.1359 + void *arg 1.1360 +) 1.1361 +{ 1.1362 + PRStatus nssrv = PR_SUCCESS; 1.1363 + NSSArena *tmpArena; 1.1364 + NSSCertificate **subjectCerts; 1.1365 + NSSCertificate *c; 1.1366 + PRIntn i; 1.1367 + tmpArena = NSSArena_Create(); 1.1368 + if (!tmpArena) { 1.1369 + return PR_FAILURE; 1.1370 + } 1.1371 + subjectCerts = NSSTrustDomain_FindCertificatesBySubject(td, subject, NULL, 1.1372 + 0, tmpArena); 1.1373 + if (subjectCerts) { 1.1374 + for (i=0, c = subjectCerts[i]; c; i++) { 1.1375 + nssrv = callback(c, arg); 1.1376 + if (nssrv != PR_SUCCESS) break; 1.1377 + } 1.1378 + } 1.1379 + nssArena_Destroy(tmpArena); 1.1380 + return nssrv; 1.1381 +} 1.1382 + 1.1383 +/* CERT_TraversePermCertsForNickname */ 1.1384 +NSS_IMPLEMENT PRStatus 1.1385 +nssTrustDomain_TraverseCertificatesByNickname ( 1.1386 + NSSTrustDomain *td, 1.1387 + NSSUTF8 *nickname, 1.1388 + PRStatus (*callback)(NSSCertificate *c, void *arg), 1.1389 + void *arg 1.1390 +) 1.1391 +{ 1.1392 + PRStatus nssrv = PR_SUCCESS; 1.1393 + NSSArena *tmpArena; 1.1394 + NSSCertificate **nickCerts; 1.1395 + NSSCertificate *c; 1.1396 + PRIntn i; 1.1397 + tmpArena = NSSArena_Create(); 1.1398 + if (!tmpArena) { 1.1399 + return PR_FAILURE; 1.1400 + } 1.1401 + nickCerts = NSSTrustDomain_FindCertificatesByNickname(td, nickname, NULL, 1.1402 + 0, tmpArena); 1.1403 + if (nickCerts) { 1.1404 + for (i=0, c = nickCerts[i]; c; i++) { 1.1405 + nssrv = callback(c, arg); 1.1406 + if (nssrv != PR_SUCCESS) break; 1.1407 + } 1.1408 + } 1.1409 + nssArena_Destroy(tmpArena); 1.1410 + return nssrv; 1.1411 +} 1.1412 + 1.1413 +static void cert_dump_iter(const void *k, void *v, void *a) 1.1414 +{ 1.1415 + NSSCertificate *c = (NSSCertificate *)k; 1.1416 + CERTCertificate *cert = STAN_GetCERTCertificate(c); 1.1417 + printf("[%2d] \"%s\"\n", c->object.refCount, cert->subjectName); 1.1418 +} 1.1419 + 1.1420 +void 1.1421 +nss_DumpCertificateCacheInfo() 1.1422 +{ 1.1423 + NSSTrustDomain *td; 1.1424 + NSSCryptoContext *cc; 1.1425 + td = STAN_GetDefaultTrustDomain(); 1.1426 + cc = STAN_GetDefaultCryptoContext(); 1.1427 + printf("\n\nCertificates in the cache:\n"); 1.1428 + nssTrustDomain_DumpCacheInfo(td, cert_dump_iter, NULL); 1.1429 + printf("\n\nCertificates in the temporary store:\n"); 1.1430 + if (cc->certStore) { 1.1431 + nssCertificateStore_DumpStoreInfo(cc->certStore, cert_dump_iter, NULL); 1.1432 + } 1.1433 +} 1.1434 +