1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/lib/pki/pkistore.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,739 @@ 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 PKIM_H 1.9 +#include "pkim.h" 1.10 +#endif /* PKIM_H */ 1.11 + 1.12 +#ifndef PKI_H 1.13 +#include "pki.h" 1.14 +#endif /* PKI_H */ 1.15 + 1.16 +#ifndef NSSPKI_H 1.17 +#include "nsspki.h" 1.18 +#endif /* NSSPKI_H */ 1.19 + 1.20 +#ifndef BASE_H 1.21 +#include "base.h" 1.22 +#endif /* BASE_H */ 1.23 + 1.24 +#ifndef PKISTORE_H 1.25 +#include "pkistore.h" 1.26 +#endif /* PKISTORE_H */ 1.27 + 1.28 +#include "cert.h" 1.29 + 1.30 +#include "prbit.h" 1.31 + 1.32 +/* 1.33 + * Certificate Store 1.34 + * 1.35 + * This differs from the cache in that it is a true storage facility. Items 1.36 + * stay in until they are explicitly removed. It is only used by crypto 1.37 + * contexts at this time, but may be more generally useful... 1.38 + * 1.39 + */ 1.40 + 1.41 +struct nssCertificateStoreStr 1.42 +{ 1.43 + PRBool i_alloced_arena; 1.44 + NSSArena *arena; 1.45 + PZLock *lock; 1.46 + nssHash *subject; 1.47 + nssHash *issuer_and_serial; 1.48 +}; 1.49 + 1.50 +typedef struct certificate_hash_entry_str certificate_hash_entry; 1.51 + 1.52 +struct certificate_hash_entry_str 1.53 +{ 1.54 + NSSCertificate *cert; 1.55 + NSSTrust *trust; 1.56 + nssSMIMEProfile *profile; 1.57 +}; 1.58 + 1.59 +/* forward static declarations */ 1.60 +static NSSCertificate * 1.61 +nssCertStore_FindCertByIssuerAndSerialNumberLocked ( 1.62 + nssCertificateStore *store, 1.63 + NSSDER *issuer, 1.64 + NSSDER *serial 1.65 +); 1.66 + 1.67 +NSS_IMPLEMENT nssCertificateStore * 1.68 +nssCertificateStore_Create ( 1.69 + NSSArena *arenaOpt 1.70 +) 1.71 +{ 1.72 + NSSArena *arena; 1.73 + nssCertificateStore *store; 1.74 + PRBool i_alloced_arena; 1.75 + if (arenaOpt) { 1.76 + arena = arenaOpt; 1.77 + i_alloced_arena = PR_FALSE; 1.78 + } else { 1.79 + arena = nssArena_Create(); 1.80 + if (!arena) { 1.81 + return NULL; 1.82 + } 1.83 + i_alloced_arena = PR_TRUE; 1.84 + } 1.85 + store = nss_ZNEW(arena, nssCertificateStore); 1.86 + if (!store) { 1.87 + goto loser; 1.88 + } 1.89 + store->lock = PZ_NewLock(nssILockOther); 1.90 + if (!store->lock) { 1.91 + goto loser; 1.92 + } 1.93 + /* Create the issuer/serial --> {cert, trust, S/MIME profile } hash */ 1.94 + store->issuer_and_serial = nssHash_CreateCertificate(arena, 0); 1.95 + if (!store->issuer_and_serial) { 1.96 + goto loser; 1.97 + } 1.98 + /* Create the subject DER --> subject list hash */ 1.99 + store->subject = nssHash_CreateItem(arena, 0); 1.100 + if (!store->subject) { 1.101 + goto loser; 1.102 + } 1.103 + store->arena = arena; 1.104 + store->i_alloced_arena = i_alloced_arena; 1.105 + return store; 1.106 +loser: 1.107 + if (store) { 1.108 + if (store->lock) { 1.109 + PZ_DestroyLock(store->lock); 1.110 + } 1.111 + if (store->issuer_and_serial) { 1.112 + nssHash_Destroy(store->issuer_and_serial); 1.113 + } 1.114 + if (store->subject) { 1.115 + nssHash_Destroy(store->subject); 1.116 + } 1.117 + } 1.118 + if (i_alloced_arena) { 1.119 + nssArena_Destroy(arena); 1.120 + } 1.121 + return NULL; 1.122 +} 1.123 + 1.124 +extern const NSSError NSS_ERROR_BUSY; 1.125 + 1.126 +NSS_IMPLEMENT PRStatus 1.127 +nssCertificateStore_Destroy ( 1.128 + nssCertificateStore *store 1.129 +) 1.130 +{ 1.131 + if (nssHash_Count(store->issuer_and_serial) > 0) { 1.132 + nss_SetError(NSS_ERROR_BUSY); 1.133 + return PR_FAILURE; 1.134 + } 1.135 + PZ_DestroyLock(store->lock); 1.136 + nssHash_Destroy(store->issuer_and_serial); 1.137 + nssHash_Destroy(store->subject); 1.138 + if (store->i_alloced_arena) { 1.139 + nssArena_Destroy(store->arena); 1.140 + } else { 1.141 + nss_ZFreeIf(store); 1.142 + } 1.143 + return PR_SUCCESS; 1.144 +} 1.145 + 1.146 +static PRStatus 1.147 +add_certificate_entry ( 1.148 + nssCertificateStore *store, 1.149 + NSSCertificate *cert 1.150 +) 1.151 +{ 1.152 + PRStatus nssrv; 1.153 + certificate_hash_entry *entry; 1.154 + entry = nss_ZNEW(cert->object.arena, certificate_hash_entry); 1.155 + if (!entry) { 1.156 + return PR_FAILURE; 1.157 + } 1.158 + entry->cert = cert; 1.159 + nssrv = nssHash_Add(store->issuer_and_serial, cert, entry); 1.160 + if (nssrv != PR_SUCCESS) { 1.161 + nss_ZFreeIf(entry); 1.162 + } 1.163 + return nssrv; 1.164 +} 1.165 + 1.166 +static PRStatus 1.167 +add_subject_entry ( 1.168 + nssCertificateStore *store, 1.169 + NSSCertificate *cert 1.170 +) 1.171 +{ 1.172 + PRStatus nssrv; 1.173 + nssList *subjectList; 1.174 + subjectList = (nssList *)nssHash_Lookup(store->subject, &cert->subject); 1.175 + if (subjectList) { 1.176 + /* The subject is already in, add this cert to the list */ 1.177 + nssrv = nssList_AddUnique(subjectList, cert); 1.178 + } else { 1.179 + /* Create a new subject list for the subject */ 1.180 + subjectList = nssList_Create(NULL, PR_FALSE); 1.181 + if (!subjectList) { 1.182 + return PR_FAILURE; 1.183 + } 1.184 + nssList_SetSortFunction(subjectList, nssCertificate_SubjectListSort); 1.185 + /* Add the cert entry to this list of subjects */ 1.186 + nssrv = nssList_Add(subjectList, cert); 1.187 + if (nssrv != PR_SUCCESS) { 1.188 + return nssrv; 1.189 + } 1.190 + /* Add the subject list to the cache */ 1.191 + nssrv = nssHash_Add(store->subject, &cert->subject, subjectList); 1.192 + } 1.193 + return nssrv; 1.194 +} 1.195 + 1.196 +/* declared below */ 1.197 +static void 1.198 +remove_certificate_entry ( 1.199 + nssCertificateStore *store, 1.200 + NSSCertificate *cert 1.201 +); 1.202 + 1.203 +/* Caller must hold store->lock */ 1.204 +static PRStatus 1.205 +nssCertificateStore_AddLocked ( 1.206 + nssCertificateStore *store, 1.207 + NSSCertificate *cert 1.208 +) 1.209 +{ 1.210 + PRStatus nssrv = add_certificate_entry(store, cert); 1.211 + if (nssrv == PR_SUCCESS) { 1.212 + nssrv = add_subject_entry(store, cert); 1.213 + if (nssrv == PR_FAILURE) { 1.214 + remove_certificate_entry(store, cert); 1.215 + } 1.216 + } 1.217 + return nssrv; 1.218 +} 1.219 + 1.220 + 1.221 +NSS_IMPLEMENT NSSCertificate * 1.222 +nssCertificateStore_FindOrAdd ( 1.223 + nssCertificateStore *store, 1.224 + NSSCertificate *c 1.225 +) 1.226 +{ 1.227 + PRStatus nssrv; 1.228 + NSSCertificate *rvCert = NULL; 1.229 + 1.230 + PZ_Lock(store->lock); 1.231 + rvCert = nssCertStore_FindCertByIssuerAndSerialNumberLocked( 1.232 + store, &c->issuer, &c->serial); 1.233 + if (!rvCert) { 1.234 + nssrv = nssCertificateStore_AddLocked(store, c); 1.235 + if (PR_SUCCESS == nssrv) { 1.236 + rvCert = nssCertificate_AddRef(c); 1.237 + } 1.238 + } 1.239 + PZ_Unlock(store->lock); 1.240 + return rvCert; 1.241 +} 1.242 + 1.243 +static void 1.244 +remove_certificate_entry ( 1.245 + nssCertificateStore *store, 1.246 + NSSCertificate *cert 1.247 +) 1.248 +{ 1.249 + certificate_hash_entry *entry; 1.250 + entry = (certificate_hash_entry *) 1.251 + nssHash_Lookup(store->issuer_and_serial, cert); 1.252 + if (entry) { 1.253 + nssHash_Remove(store->issuer_and_serial, cert); 1.254 + if (entry->trust) { 1.255 + nssTrust_Destroy(entry->trust); 1.256 + } 1.257 + if (entry->profile) { 1.258 + nssSMIMEProfile_Destroy(entry->profile); 1.259 + } 1.260 + nss_ZFreeIf(entry); 1.261 + } 1.262 +} 1.263 + 1.264 +static void 1.265 +remove_subject_entry ( 1.266 + nssCertificateStore *store, 1.267 + NSSCertificate *cert 1.268 +) 1.269 +{ 1.270 + nssList *subjectList; 1.271 + /* Get the subject list for the cert's subject */ 1.272 + subjectList = (nssList *)nssHash_Lookup(store->subject, &cert->subject); 1.273 + if (subjectList) { 1.274 + /* Remove the cert from the subject hash */ 1.275 + nssList_Remove(subjectList, cert); 1.276 + nssHash_Remove(store->subject, &cert->subject); 1.277 + if (nssList_Count(subjectList) == 0) { 1.278 + nssList_Destroy(subjectList); 1.279 + } else { 1.280 + /* The cert being released may have keyed the subject entry. 1.281 + * Since there are still subject certs around, get another and 1.282 + * rekey the entry just in case. 1.283 + */ 1.284 + NSSCertificate *subjectCert; 1.285 + (void)nssList_GetArray(subjectList, (void **)&subjectCert, 1); 1.286 + nssHash_Add(store->subject, &subjectCert->subject, subjectList); 1.287 + } 1.288 + } 1.289 +} 1.290 + 1.291 +NSS_IMPLEMENT void 1.292 +nssCertificateStore_RemoveCertLOCKED ( 1.293 + nssCertificateStore *store, 1.294 + NSSCertificate *cert 1.295 +) 1.296 +{ 1.297 + certificate_hash_entry *entry; 1.298 + entry = (certificate_hash_entry *) 1.299 + nssHash_Lookup(store->issuer_and_serial, cert); 1.300 + if (entry && entry->cert == cert) { 1.301 + remove_certificate_entry(store, cert); 1.302 + remove_subject_entry(store, cert); 1.303 + } 1.304 +} 1.305 + 1.306 +NSS_IMPLEMENT void 1.307 +nssCertificateStore_Lock ( 1.308 + nssCertificateStore *store, nssCertificateStoreTrace* out 1.309 +) 1.310 +{ 1.311 +#ifdef DEBUG 1.312 + PORT_Assert(out); 1.313 + out->store = store; 1.314 + out->lock = store->lock; 1.315 + out->locked = PR_TRUE; 1.316 + PZ_Lock(out->lock); 1.317 +#else 1.318 + PZ_Lock(store->lock); 1.319 +#endif 1.320 +} 1.321 + 1.322 +NSS_IMPLEMENT void 1.323 +nssCertificateStore_Unlock ( 1.324 + nssCertificateStore *store, const nssCertificateStoreTrace* in, 1.325 + nssCertificateStoreTrace* out 1.326 +) 1.327 +{ 1.328 +#ifdef DEBUG 1.329 + PORT_Assert(in); 1.330 + PORT_Assert(out); 1.331 + out->store = store; 1.332 + out->lock = store->lock; 1.333 + PORT_Assert(!out->locked); 1.334 + out->unlocked = PR_TRUE; 1.335 + 1.336 + PORT_Assert(in->store == out->store); 1.337 + PORT_Assert(in->lock == out->lock); 1.338 + PORT_Assert(in->locked); 1.339 + PORT_Assert(!in->unlocked); 1.340 + 1.341 + PZ_Unlock(out->lock); 1.342 +#else 1.343 + PZ_Unlock(store->lock); 1.344 +#endif 1.345 +} 1.346 + 1.347 +static NSSCertificate ** 1.348 +get_array_from_list ( 1.349 + nssList *certList, 1.350 + NSSCertificate *rvOpt[], 1.351 + PRUint32 maximumOpt, 1.352 + NSSArena *arenaOpt 1.353 +) 1.354 +{ 1.355 + PRUint32 count; 1.356 + NSSCertificate **rvArray = NULL; 1.357 + count = nssList_Count(certList); 1.358 + if (count == 0) { 1.359 + return NULL; 1.360 + } 1.361 + if (maximumOpt > 0) { 1.362 + count = PR_MIN(maximumOpt, count); 1.363 + } 1.364 + if (rvOpt) { 1.365 + nssList_GetArray(certList, (void **)rvOpt, count); 1.366 + } else { 1.367 + rvArray = nss_ZNEWARRAY(arenaOpt, NSSCertificate *, count + 1); 1.368 + if (rvArray) { 1.369 + nssList_GetArray(certList, (void **)rvArray, count); 1.370 + } 1.371 + } 1.372 + return rvArray; 1.373 +} 1.374 + 1.375 +NSS_IMPLEMENT NSSCertificate ** 1.376 +nssCertificateStore_FindCertificatesBySubject ( 1.377 + nssCertificateStore *store, 1.378 + NSSDER *subject, 1.379 + NSSCertificate *rvOpt[], 1.380 + PRUint32 maximumOpt, 1.381 + NSSArena *arenaOpt 1.382 +) 1.383 +{ 1.384 + NSSCertificate **rvArray = NULL; 1.385 + nssList *subjectList; 1.386 + PZ_Lock(store->lock); 1.387 + subjectList = (nssList *)nssHash_Lookup(store->subject, subject); 1.388 + if (subjectList) { 1.389 + nssCertificateList_AddReferences(subjectList); 1.390 + rvArray = get_array_from_list(subjectList, 1.391 + rvOpt, maximumOpt, arenaOpt); 1.392 + } 1.393 + PZ_Unlock(store->lock); 1.394 + return rvArray; 1.395 +} 1.396 + 1.397 +/* Because only subject indexing is implemented, all other lookups require 1.398 + * full traversal (unfortunately, PLHashTable doesn't allow you to exit 1.399 + * early from the enumeration). The assumptions are that 1) lookups by 1.400 + * fields other than subject will be rare, and 2) the hash will not have 1.401 + * a large number of entries. These assumptions will be tested. 1.402 + * 1.403 + * XXX 1.404 + * For NSS 3.4, it is worth consideration to do all forms of indexing, 1.405 + * because the only crypto context is global and persistent. 1.406 + */ 1.407 + 1.408 +struct nickname_template_str 1.409 +{ 1.410 + NSSUTF8 *nickname; 1.411 + nssList *subjectList; 1.412 +}; 1.413 + 1.414 +static void match_nickname(const void *k, void *v, void *a) 1.415 +{ 1.416 + PRStatus nssrv; 1.417 + NSSCertificate *c; 1.418 + NSSUTF8 *nickname; 1.419 + nssList *subjectList = (nssList *)v; 1.420 + struct nickname_template_str *nt = (struct nickname_template_str *)a; 1.421 + nssrv = nssList_GetArray(subjectList, (void **)&c, 1); 1.422 + nickname = nssCertificate_GetNickname(c, NULL); 1.423 + if (nssrv == PR_SUCCESS && nickname && 1.424 + nssUTF8_Equal(nickname, nt->nickname, &nssrv)) 1.425 + { 1.426 + nt->subjectList = subjectList; 1.427 + } 1.428 + nss_ZFreeIf(nickname); 1.429 +} 1.430 + 1.431 +/* 1.432 + * Find all cached certs with this label. 1.433 + */ 1.434 +NSS_IMPLEMENT NSSCertificate ** 1.435 +nssCertificateStore_FindCertificatesByNickname ( 1.436 + nssCertificateStore *store, 1.437 + const NSSUTF8 *nickname, 1.438 + NSSCertificate *rvOpt[], 1.439 + PRUint32 maximumOpt, 1.440 + NSSArena *arenaOpt 1.441 +) 1.442 +{ 1.443 + NSSCertificate **rvArray = NULL; 1.444 + struct nickname_template_str nt; 1.445 + nt.nickname = (char*) nickname; 1.446 + nt.subjectList = NULL; 1.447 + PZ_Lock(store->lock); 1.448 + nssHash_Iterate(store->subject, match_nickname, &nt); 1.449 + if (nt.subjectList) { 1.450 + nssCertificateList_AddReferences(nt.subjectList); 1.451 + rvArray = get_array_from_list(nt.subjectList, 1.452 + rvOpt, maximumOpt, arenaOpt); 1.453 + } 1.454 + PZ_Unlock(store->lock); 1.455 + return rvArray; 1.456 +} 1.457 + 1.458 +struct email_template_str 1.459 +{ 1.460 + NSSASCII7 *email; 1.461 + nssList *emailList; 1.462 +}; 1.463 + 1.464 +static void match_email(const void *k, void *v, void *a) 1.465 +{ 1.466 + PRStatus nssrv; 1.467 + NSSCertificate *c; 1.468 + nssList *subjectList = (nssList *)v; 1.469 + struct email_template_str *et = (struct email_template_str *)a; 1.470 + nssrv = nssList_GetArray(subjectList, (void **)&c, 1); 1.471 + if (nssrv == PR_SUCCESS && 1.472 + nssUTF8_Equal(c->email, et->email, &nssrv)) 1.473 + { 1.474 + nssListIterator *iter = nssList_CreateIterator(subjectList); 1.475 + if (iter) { 1.476 + for (c = (NSSCertificate *)nssListIterator_Start(iter); 1.477 + c != (NSSCertificate *)NULL; 1.478 + c = (NSSCertificate *)nssListIterator_Next(iter)) 1.479 + { 1.480 + nssList_Add(et->emailList, c); 1.481 + } 1.482 + nssListIterator_Finish(iter); 1.483 + nssListIterator_Destroy(iter); 1.484 + } 1.485 + } 1.486 +} 1.487 + 1.488 +/* 1.489 + * Find all cached certs with this email address. 1.490 + */ 1.491 +NSS_IMPLEMENT NSSCertificate ** 1.492 +nssCertificateStore_FindCertificatesByEmail ( 1.493 + nssCertificateStore *store, 1.494 + NSSASCII7 *email, 1.495 + NSSCertificate *rvOpt[], 1.496 + PRUint32 maximumOpt, 1.497 + NSSArena *arenaOpt 1.498 +) 1.499 +{ 1.500 + NSSCertificate **rvArray = NULL; 1.501 + struct email_template_str et; 1.502 + et.email = email; 1.503 + et.emailList = nssList_Create(NULL, PR_FALSE); 1.504 + if (!et.emailList) { 1.505 + return NULL; 1.506 + } 1.507 + PZ_Lock(store->lock); 1.508 + nssHash_Iterate(store->subject, match_email, &et); 1.509 + if (et.emailList) { 1.510 + /* get references before leaving the store's lock protection */ 1.511 + nssCertificateList_AddReferences(et.emailList); 1.512 + } 1.513 + PZ_Unlock(store->lock); 1.514 + if (et.emailList) { 1.515 + rvArray = get_array_from_list(et.emailList, 1.516 + rvOpt, maximumOpt, arenaOpt); 1.517 + nssList_Destroy(et.emailList); 1.518 + } 1.519 + return rvArray; 1.520 +} 1.521 + 1.522 +/* Caller holds store->lock */ 1.523 +static NSSCertificate * 1.524 +nssCertStore_FindCertByIssuerAndSerialNumberLocked ( 1.525 + nssCertificateStore *store, 1.526 + NSSDER *issuer, 1.527 + NSSDER *serial 1.528 +) 1.529 +{ 1.530 + certificate_hash_entry *entry; 1.531 + NSSCertificate *rvCert = NULL; 1.532 + NSSCertificate index; 1.533 + 1.534 + index.issuer = *issuer; 1.535 + index.serial = *serial; 1.536 + entry = (certificate_hash_entry *) 1.537 + nssHash_Lookup(store->issuer_and_serial, &index); 1.538 + if (entry) { 1.539 + rvCert = nssCertificate_AddRef(entry->cert); 1.540 + } 1.541 + return rvCert; 1.542 +} 1.543 + 1.544 +NSS_IMPLEMENT NSSCertificate * 1.545 +nssCertificateStore_FindCertificateByIssuerAndSerialNumber ( 1.546 + nssCertificateStore *store, 1.547 + NSSDER *issuer, 1.548 + NSSDER *serial 1.549 +) 1.550 +{ 1.551 + NSSCertificate *rvCert = NULL; 1.552 + 1.553 + PZ_Lock(store->lock); 1.554 + rvCert = nssCertStore_FindCertByIssuerAndSerialNumberLocked ( 1.555 + store, issuer, serial); 1.556 + PZ_Unlock(store->lock); 1.557 + return rvCert; 1.558 +} 1.559 + 1.560 +static PRStatus 1.561 +issuer_and_serial_from_encoding ( 1.562 + NSSBER *encoding, 1.563 + NSSDER *issuer, 1.564 + NSSDER *serial 1.565 +) 1.566 +{ 1.567 + SECItem derCert, derIssuer, derSerial; 1.568 + SECStatus secrv; 1.569 + derCert.data = (unsigned char *)encoding->data; 1.570 + derCert.len = encoding->size; 1.571 + secrv = CERT_IssuerNameFromDERCert(&derCert, &derIssuer); 1.572 + if (secrv != SECSuccess) { 1.573 + return PR_FAILURE; 1.574 + } 1.575 + secrv = CERT_SerialNumberFromDERCert(&derCert, &derSerial); 1.576 + if (secrv != SECSuccess) { 1.577 + PORT_Free(derIssuer.data); 1.578 + return PR_FAILURE; 1.579 + } 1.580 + issuer->data = derIssuer.data; 1.581 + issuer->size = derIssuer.len; 1.582 + serial->data = derSerial.data; 1.583 + serial->size = derSerial.len; 1.584 + return PR_SUCCESS; 1.585 +} 1.586 + 1.587 +NSS_IMPLEMENT NSSCertificate * 1.588 +nssCertificateStore_FindCertificateByEncodedCertificate ( 1.589 + nssCertificateStore *store, 1.590 + NSSDER *encoding 1.591 +) 1.592 +{ 1.593 + PRStatus nssrv = PR_FAILURE; 1.594 + NSSDER issuer, serial; 1.595 + NSSCertificate *rvCert = NULL; 1.596 + nssrv = issuer_and_serial_from_encoding(encoding, &issuer, &serial); 1.597 + if (nssrv != PR_SUCCESS) { 1.598 + return NULL; 1.599 + } 1.600 + rvCert = nssCertificateStore_FindCertificateByIssuerAndSerialNumber(store, 1.601 + &issuer, 1.602 + &serial); 1.603 + PORT_Free(issuer.data); 1.604 + PORT_Free(serial.data); 1.605 + return rvCert; 1.606 +} 1.607 + 1.608 +NSS_EXTERN PRStatus 1.609 +nssCertificateStore_AddTrust ( 1.610 + nssCertificateStore *store, 1.611 + NSSTrust *trust 1.612 +) 1.613 +{ 1.614 + NSSCertificate *cert; 1.615 + certificate_hash_entry *entry; 1.616 + cert = trust->certificate; 1.617 + PZ_Lock(store->lock); 1.618 + entry = (certificate_hash_entry *) 1.619 + nssHash_Lookup(store->issuer_and_serial, cert); 1.620 + if (entry) { 1.621 + NSSTrust* newTrust = nssTrust_AddRef(trust); 1.622 + if (entry->trust) { 1.623 + nssTrust_Destroy(entry->trust); 1.624 + } 1.625 + entry->trust = newTrust; 1.626 + } 1.627 + PZ_Unlock(store->lock); 1.628 + return (entry) ? PR_SUCCESS : PR_FAILURE; 1.629 +} 1.630 + 1.631 +NSS_IMPLEMENT NSSTrust * 1.632 +nssCertificateStore_FindTrustForCertificate ( 1.633 + nssCertificateStore *store, 1.634 + NSSCertificate *cert 1.635 +) 1.636 +{ 1.637 + certificate_hash_entry *entry; 1.638 + NSSTrust *rvTrust = NULL; 1.639 + PZ_Lock(store->lock); 1.640 + entry = (certificate_hash_entry *) 1.641 + nssHash_Lookup(store->issuer_and_serial, cert); 1.642 + if (entry && entry->trust) { 1.643 + rvTrust = nssTrust_AddRef(entry->trust); 1.644 + } 1.645 + PZ_Unlock(store->lock); 1.646 + return rvTrust; 1.647 +} 1.648 + 1.649 +NSS_EXTERN PRStatus 1.650 +nssCertificateStore_AddSMIMEProfile ( 1.651 + nssCertificateStore *store, 1.652 + nssSMIMEProfile *profile 1.653 +) 1.654 +{ 1.655 + NSSCertificate *cert; 1.656 + certificate_hash_entry *entry; 1.657 + cert = profile->certificate; 1.658 + PZ_Lock(store->lock); 1.659 + entry = (certificate_hash_entry *) 1.660 + nssHash_Lookup(store->issuer_and_serial, cert); 1.661 + if (entry) { 1.662 + nssSMIMEProfile* newProfile = nssSMIMEProfile_AddRef(profile); 1.663 + if (entry->profile) { 1.664 + nssSMIMEProfile_Destroy(entry->profile); 1.665 + } 1.666 + entry->profile = newProfile; 1.667 + } 1.668 + PZ_Unlock(store->lock); 1.669 + return (entry) ? PR_SUCCESS : PR_FAILURE; 1.670 +} 1.671 + 1.672 +NSS_IMPLEMENT nssSMIMEProfile * 1.673 +nssCertificateStore_FindSMIMEProfileForCertificate ( 1.674 + nssCertificateStore *store, 1.675 + NSSCertificate *cert 1.676 +) 1.677 +{ 1.678 + certificate_hash_entry *entry; 1.679 + nssSMIMEProfile *rvProfile = NULL; 1.680 + PZ_Lock(store->lock); 1.681 + entry = (certificate_hash_entry *) 1.682 + nssHash_Lookup(store->issuer_and_serial, cert); 1.683 + if (entry && entry->profile) { 1.684 + rvProfile = nssSMIMEProfile_AddRef(entry->profile); 1.685 + } 1.686 + PZ_Unlock(store->lock); 1.687 + return rvProfile; 1.688 +} 1.689 + 1.690 +/* XXX this is also used by cache and should be somewhere else */ 1.691 + 1.692 +static PLHashNumber 1.693 +nss_certificate_hash ( 1.694 + const void *key 1.695 +) 1.696 +{ 1.697 + unsigned int i; 1.698 + PLHashNumber h; 1.699 + NSSCertificate *c = (NSSCertificate *)key; 1.700 + h = 0; 1.701 + for (i=0; i<c->issuer.size; i++) 1.702 + h = PR_ROTATE_LEFT32(h, 4) ^ ((unsigned char *)c->issuer.data)[i]; 1.703 + for (i=0; i<c->serial.size; i++) 1.704 + h = PR_ROTATE_LEFT32(h, 4) ^ ((unsigned char *)c->serial.data)[i]; 1.705 + return h; 1.706 +} 1.707 + 1.708 +static int 1.709 +nss_compare_certs(const void *v1, const void *v2) 1.710 +{ 1.711 + PRStatus ignore; 1.712 + NSSCertificate *c1 = (NSSCertificate *)v1; 1.713 + NSSCertificate *c2 = (NSSCertificate *)v2; 1.714 + return (int)(nssItem_Equal(&c1->issuer, &c2->issuer, &ignore) && 1.715 + nssItem_Equal(&c1->serial, &c2->serial, &ignore)); 1.716 +} 1.717 + 1.718 +NSS_IMPLEMENT nssHash * 1.719 +nssHash_CreateCertificate ( 1.720 + NSSArena *arenaOpt, 1.721 + PRUint32 numBuckets 1.722 +) 1.723 +{ 1.724 + return nssHash_Create(arenaOpt, 1.725 + numBuckets, 1.726 + nss_certificate_hash, 1.727 + nss_compare_certs, 1.728 + PL_CompareValues); 1.729 +} 1.730 + 1.731 +NSS_IMPLEMENT void 1.732 +nssCertificateStore_DumpStoreInfo ( 1.733 + nssCertificateStore *store, 1.734 + void (* cert_dump_iter)(const void *, void *, void *), 1.735 + void *arg 1.736 +) 1.737 +{ 1.738 + PZ_Lock(store->lock); 1.739 + nssHash_Iterate(store->issuer_and_serial, cert_dump_iter, arg); 1.740 + PZ_Unlock(store->lock); 1.741 +} 1.742 +