Mercurial > trustbridge > nss-cmake-static
comparison nss/lib/pki/pkistore.c @ 0:1e5118fa0cb1
This is NSS with a Cmake Buildsyste
To compile a static NSS library for Windows we've used the
Chromium-NSS fork and added a Cmake buildsystem to compile
it statically for Windows. See README.chromium for chromium
changes and README.trustbridge for our modifications.
author | Andre Heinecke <andre.heinecke@intevation.de> |
---|---|
date | Mon, 28 Jul 2014 10:47:06 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:1e5118fa0cb1 |
---|---|
1 /* This Source Code Form is subject to the terms of the Mozilla Public | |
2 * License, v. 2.0. If a copy of the MPL was not distributed with this | |
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | |
4 | |
5 #ifndef PKIM_H | |
6 #include "pkim.h" | |
7 #endif /* PKIM_H */ | |
8 | |
9 #ifndef PKI_H | |
10 #include "pki.h" | |
11 #endif /* PKI_H */ | |
12 | |
13 #ifndef NSSPKI_H | |
14 #include "nsspki.h" | |
15 #endif /* NSSPKI_H */ | |
16 | |
17 #ifndef BASE_H | |
18 #include "base.h" | |
19 #endif /* BASE_H */ | |
20 | |
21 #ifndef PKISTORE_H | |
22 #include "pkistore.h" | |
23 #endif /* PKISTORE_H */ | |
24 | |
25 #include "cert.h" | |
26 | |
27 #include "prbit.h" | |
28 | |
29 /* | |
30 * Certificate Store | |
31 * | |
32 * This differs from the cache in that it is a true storage facility. Items | |
33 * stay in until they are explicitly removed. It is only used by crypto | |
34 * contexts at this time, but may be more generally useful... | |
35 * | |
36 */ | |
37 | |
38 struct nssCertificateStoreStr | |
39 { | |
40 PRBool i_alloced_arena; | |
41 NSSArena *arena; | |
42 PZLock *lock; | |
43 nssHash *subject; | |
44 nssHash *issuer_and_serial; | |
45 }; | |
46 | |
47 typedef struct certificate_hash_entry_str certificate_hash_entry; | |
48 | |
49 struct certificate_hash_entry_str | |
50 { | |
51 NSSCertificate *cert; | |
52 NSSTrust *trust; | |
53 nssSMIMEProfile *profile; | |
54 }; | |
55 | |
56 /* forward static declarations */ | |
57 static NSSCertificate * | |
58 nssCertStore_FindCertByIssuerAndSerialNumberLocked ( | |
59 nssCertificateStore *store, | |
60 NSSDER *issuer, | |
61 NSSDER *serial | |
62 ); | |
63 | |
64 NSS_IMPLEMENT nssCertificateStore * | |
65 nssCertificateStore_Create ( | |
66 NSSArena *arenaOpt | |
67 ) | |
68 { | |
69 NSSArena *arena; | |
70 nssCertificateStore *store; | |
71 PRBool i_alloced_arena; | |
72 if (arenaOpt) { | |
73 arena = arenaOpt; | |
74 i_alloced_arena = PR_FALSE; | |
75 } else { | |
76 arena = nssArena_Create(); | |
77 if (!arena) { | |
78 return NULL; | |
79 } | |
80 i_alloced_arena = PR_TRUE; | |
81 } | |
82 store = nss_ZNEW(arena, nssCertificateStore); | |
83 if (!store) { | |
84 goto loser; | |
85 } | |
86 store->lock = PZ_NewLock(nssILockOther); | |
87 if (!store->lock) { | |
88 goto loser; | |
89 } | |
90 /* Create the issuer/serial --> {cert, trust, S/MIME profile } hash */ | |
91 store->issuer_and_serial = nssHash_CreateCertificate(arena, 0); | |
92 if (!store->issuer_and_serial) { | |
93 goto loser; | |
94 } | |
95 /* Create the subject DER --> subject list hash */ | |
96 store->subject = nssHash_CreateItem(arena, 0); | |
97 if (!store->subject) { | |
98 goto loser; | |
99 } | |
100 store->arena = arena; | |
101 store->i_alloced_arena = i_alloced_arena; | |
102 return store; | |
103 loser: | |
104 if (store) { | |
105 if (store->lock) { | |
106 PZ_DestroyLock(store->lock); | |
107 } | |
108 if (store->issuer_and_serial) { | |
109 nssHash_Destroy(store->issuer_and_serial); | |
110 } | |
111 if (store->subject) { | |
112 nssHash_Destroy(store->subject); | |
113 } | |
114 } | |
115 if (i_alloced_arena) { | |
116 nssArena_Destroy(arena); | |
117 } | |
118 return NULL; | |
119 } | |
120 | |
121 extern const NSSError NSS_ERROR_BUSY; | |
122 | |
123 NSS_IMPLEMENT PRStatus | |
124 nssCertificateStore_Destroy ( | |
125 nssCertificateStore *store | |
126 ) | |
127 { | |
128 if (nssHash_Count(store->issuer_and_serial) > 0) { | |
129 nss_SetError(NSS_ERROR_BUSY); | |
130 return PR_FAILURE; | |
131 } | |
132 PZ_DestroyLock(store->lock); | |
133 nssHash_Destroy(store->issuer_and_serial); | |
134 nssHash_Destroy(store->subject); | |
135 if (store->i_alloced_arena) { | |
136 nssArena_Destroy(store->arena); | |
137 } else { | |
138 nss_ZFreeIf(store); | |
139 } | |
140 return PR_SUCCESS; | |
141 } | |
142 | |
143 static PRStatus | |
144 add_certificate_entry ( | |
145 nssCertificateStore *store, | |
146 NSSCertificate *cert | |
147 ) | |
148 { | |
149 PRStatus nssrv; | |
150 certificate_hash_entry *entry; | |
151 entry = nss_ZNEW(cert->object.arena, certificate_hash_entry); | |
152 if (!entry) { | |
153 return PR_FAILURE; | |
154 } | |
155 entry->cert = cert; | |
156 nssrv = nssHash_Add(store->issuer_and_serial, cert, entry); | |
157 if (nssrv != PR_SUCCESS) { | |
158 nss_ZFreeIf(entry); | |
159 } | |
160 return nssrv; | |
161 } | |
162 | |
163 static PRStatus | |
164 add_subject_entry ( | |
165 nssCertificateStore *store, | |
166 NSSCertificate *cert | |
167 ) | |
168 { | |
169 PRStatus nssrv; | |
170 nssList *subjectList; | |
171 subjectList = (nssList *)nssHash_Lookup(store->subject, &cert->subject); | |
172 if (subjectList) { | |
173 /* The subject is already in, add this cert to the list */ | |
174 nssrv = nssList_AddUnique(subjectList, cert); | |
175 } else { | |
176 /* Create a new subject list for the subject */ | |
177 subjectList = nssList_Create(NULL, PR_FALSE); | |
178 if (!subjectList) { | |
179 return PR_FAILURE; | |
180 } | |
181 nssList_SetSortFunction(subjectList, nssCertificate_SubjectListSort); | |
182 /* Add the cert entry to this list of subjects */ | |
183 nssrv = nssList_Add(subjectList, cert); | |
184 if (nssrv != PR_SUCCESS) { | |
185 return nssrv; | |
186 } | |
187 /* Add the subject list to the cache */ | |
188 nssrv = nssHash_Add(store->subject, &cert->subject, subjectList); | |
189 } | |
190 return nssrv; | |
191 } | |
192 | |
193 /* declared below */ | |
194 static void | |
195 remove_certificate_entry ( | |
196 nssCertificateStore *store, | |
197 NSSCertificate *cert | |
198 ); | |
199 | |
200 /* Caller must hold store->lock */ | |
201 static PRStatus | |
202 nssCertificateStore_AddLocked ( | |
203 nssCertificateStore *store, | |
204 NSSCertificate *cert | |
205 ) | |
206 { | |
207 PRStatus nssrv = add_certificate_entry(store, cert); | |
208 if (nssrv == PR_SUCCESS) { | |
209 nssrv = add_subject_entry(store, cert); | |
210 if (nssrv == PR_FAILURE) { | |
211 remove_certificate_entry(store, cert); | |
212 } | |
213 } | |
214 return nssrv; | |
215 } | |
216 | |
217 | |
218 NSS_IMPLEMENT NSSCertificate * | |
219 nssCertificateStore_FindOrAdd ( | |
220 nssCertificateStore *store, | |
221 NSSCertificate *c | |
222 ) | |
223 { | |
224 PRStatus nssrv; | |
225 NSSCertificate *rvCert = NULL; | |
226 | |
227 PZ_Lock(store->lock); | |
228 rvCert = nssCertStore_FindCertByIssuerAndSerialNumberLocked( | |
229 store, &c->issuer, &c->serial); | |
230 if (!rvCert) { | |
231 nssrv = nssCertificateStore_AddLocked(store, c); | |
232 if (PR_SUCCESS == nssrv) { | |
233 rvCert = nssCertificate_AddRef(c); | |
234 } | |
235 } | |
236 PZ_Unlock(store->lock); | |
237 return rvCert; | |
238 } | |
239 | |
240 static void | |
241 remove_certificate_entry ( | |
242 nssCertificateStore *store, | |
243 NSSCertificate *cert | |
244 ) | |
245 { | |
246 certificate_hash_entry *entry; | |
247 entry = (certificate_hash_entry *) | |
248 nssHash_Lookup(store->issuer_and_serial, cert); | |
249 if (entry) { | |
250 nssHash_Remove(store->issuer_and_serial, cert); | |
251 if (entry->trust) { | |
252 nssTrust_Destroy(entry->trust); | |
253 } | |
254 if (entry->profile) { | |
255 nssSMIMEProfile_Destroy(entry->profile); | |
256 } | |
257 nss_ZFreeIf(entry); | |
258 } | |
259 } | |
260 | |
261 static void | |
262 remove_subject_entry ( | |
263 nssCertificateStore *store, | |
264 NSSCertificate *cert | |
265 ) | |
266 { | |
267 nssList *subjectList; | |
268 /* Get the subject list for the cert's subject */ | |
269 subjectList = (nssList *)nssHash_Lookup(store->subject, &cert->subject); | |
270 if (subjectList) { | |
271 /* Remove the cert from the subject hash */ | |
272 nssList_Remove(subjectList, cert); | |
273 nssHash_Remove(store->subject, &cert->subject); | |
274 if (nssList_Count(subjectList) == 0) { | |
275 nssList_Destroy(subjectList); | |
276 } else { | |
277 /* The cert being released may have keyed the subject entry. | |
278 * Since there are still subject certs around, get another and | |
279 * rekey the entry just in case. | |
280 */ | |
281 NSSCertificate *subjectCert; | |
282 (void)nssList_GetArray(subjectList, (void **)&subjectCert, 1); | |
283 nssHash_Add(store->subject, &subjectCert->subject, subjectList); | |
284 } | |
285 } | |
286 } | |
287 | |
288 NSS_IMPLEMENT void | |
289 nssCertificateStore_RemoveCertLOCKED ( | |
290 nssCertificateStore *store, | |
291 NSSCertificate *cert | |
292 ) | |
293 { | |
294 certificate_hash_entry *entry; | |
295 entry = (certificate_hash_entry *) | |
296 nssHash_Lookup(store->issuer_and_serial, cert); | |
297 if (entry && entry->cert == cert) { | |
298 remove_certificate_entry(store, cert); | |
299 remove_subject_entry(store, cert); | |
300 } | |
301 } | |
302 | |
303 NSS_IMPLEMENT void | |
304 nssCertificateStore_Lock ( | |
305 nssCertificateStore *store, nssCertificateStoreTrace* out | |
306 ) | |
307 { | |
308 #ifdef DEBUG | |
309 PORT_Assert(out); | |
310 out->store = store; | |
311 out->lock = store->lock; | |
312 out->locked = PR_TRUE; | |
313 PZ_Lock(out->lock); | |
314 #else | |
315 PZ_Lock(store->lock); | |
316 #endif | |
317 } | |
318 | |
319 NSS_IMPLEMENT void | |
320 nssCertificateStore_Unlock ( | |
321 nssCertificateStore *store, const nssCertificateStoreTrace* in, | |
322 nssCertificateStoreTrace* out | |
323 ) | |
324 { | |
325 #ifdef DEBUG | |
326 PORT_Assert(in); | |
327 PORT_Assert(out); | |
328 out->store = store; | |
329 out->lock = store->lock; | |
330 PORT_Assert(!out->locked); | |
331 out->unlocked = PR_TRUE; | |
332 | |
333 PORT_Assert(in->store == out->store); | |
334 PORT_Assert(in->lock == out->lock); | |
335 PORT_Assert(in->locked); | |
336 PORT_Assert(!in->unlocked); | |
337 | |
338 PZ_Unlock(out->lock); | |
339 #else | |
340 PZ_Unlock(store->lock); | |
341 #endif | |
342 } | |
343 | |
344 static NSSCertificate ** | |
345 get_array_from_list ( | |
346 nssList *certList, | |
347 NSSCertificate *rvOpt[], | |
348 PRUint32 maximumOpt, | |
349 NSSArena *arenaOpt | |
350 ) | |
351 { | |
352 PRUint32 count; | |
353 NSSCertificate **rvArray = NULL; | |
354 count = nssList_Count(certList); | |
355 if (count == 0) { | |
356 return NULL; | |
357 } | |
358 if (maximumOpt > 0) { | |
359 count = PR_MIN(maximumOpt, count); | |
360 } | |
361 if (rvOpt) { | |
362 nssList_GetArray(certList, (void **)rvOpt, count); | |
363 } else { | |
364 rvArray = nss_ZNEWARRAY(arenaOpt, NSSCertificate *, count + 1); | |
365 if (rvArray) { | |
366 nssList_GetArray(certList, (void **)rvArray, count); | |
367 } | |
368 } | |
369 return rvArray; | |
370 } | |
371 | |
372 NSS_IMPLEMENT NSSCertificate ** | |
373 nssCertificateStore_FindCertificatesBySubject ( | |
374 nssCertificateStore *store, | |
375 NSSDER *subject, | |
376 NSSCertificate *rvOpt[], | |
377 PRUint32 maximumOpt, | |
378 NSSArena *arenaOpt | |
379 ) | |
380 { | |
381 NSSCertificate **rvArray = NULL; | |
382 nssList *subjectList; | |
383 PZ_Lock(store->lock); | |
384 subjectList = (nssList *)nssHash_Lookup(store->subject, subject); | |
385 if (subjectList) { | |
386 nssCertificateList_AddReferences(subjectList); | |
387 rvArray = get_array_from_list(subjectList, | |
388 rvOpt, maximumOpt, arenaOpt); | |
389 } | |
390 PZ_Unlock(store->lock); | |
391 return rvArray; | |
392 } | |
393 | |
394 /* Because only subject indexing is implemented, all other lookups require | |
395 * full traversal (unfortunately, PLHashTable doesn't allow you to exit | |
396 * early from the enumeration). The assumptions are that 1) lookups by | |
397 * fields other than subject will be rare, and 2) the hash will not have | |
398 * a large number of entries. These assumptions will be tested. | |
399 * | |
400 * XXX | |
401 * For NSS 3.4, it is worth consideration to do all forms of indexing, | |
402 * because the only crypto context is global and persistent. | |
403 */ | |
404 | |
405 struct nickname_template_str | |
406 { | |
407 NSSUTF8 *nickname; | |
408 nssList *subjectList; | |
409 }; | |
410 | |
411 static void match_nickname(const void *k, void *v, void *a) | |
412 { | |
413 PRStatus nssrv; | |
414 NSSCertificate *c; | |
415 NSSUTF8 *nickname; | |
416 nssList *subjectList = (nssList *)v; | |
417 struct nickname_template_str *nt = (struct nickname_template_str *)a; | |
418 nssrv = nssList_GetArray(subjectList, (void **)&c, 1); | |
419 nickname = nssCertificate_GetNickname(c, NULL); | |
420 if (nssrv == PR_SUCCESS && nickname && | |
421 nssUTF8_Equal(nickname, nt->nickname, &nssrv)) | |
422 { | |
423 nt->subjectList = subjectList; | |
424 } | |
425 nss_ZFreeIf(nickname); | |
426 } | |
427 | |
428 /* | |
429 * Find all cached certs with this label. | |
430 */ | |
431 NSS_IMPLEMENT NSSCertificate ** | |
432 nssCertificateStore_FindCertificatesByNickname ( | |
433 nssCertificateStore *store, | |
434 const NSSUTF8 *nickname, | |
435 NSSCertificate *rvOpt[], | |
436 PRUint32 maximumOpt, | |
437 NSSArena *arenaOpt | |
438 ) | |
439 { | |
440 NSSCertificate **rvArray = NULL; | |
441 struct nickname_template_str nt; | |
442 nt.nickname = (char*) nickname; | |
443 nt.subjectList = NULL; | |
444 PZ_Lock(store->lock); | |
445 nssHash_Iterate(store->subject, match_nickname, &nt); | |
446 if (nt.subjectList) { | |
447 nssCertificateList_AddReferences(nt.subjectList); | |
448 rvArray = get_array_from_list(nt.subjectList, | |
449 rvOpt, maximumOpt, arenaOpt); | |
450 } | |
451 PZ_Unlock(store->lock); | |
452 return rvArray; | |
453 } | |
454 | |
455 struct email_template_str | |
456 { | |
457 NSSASCII7 *email; | |
458 nssList *emailList; | |
459 }; | |
460 | |
461 static void match_email(const void *k, void *v, void *a) | |
462 { | |
463 PRStatus nssrv; | |
464 NSSCertificate *c; | |
465 nssList *subjectList = (nssList *)v; | |
466 struct email_template_str *et = (struct email_template_str *)a; | |
467 nssrv = nssList_GetArray(subjectList, (void **)&c, 1); | |
468 if (nssrv == PR_SUCCESS && | |
469 nssUTF8_Equal(c->email, et->email, &nssrv)) | |
470 { | |
471 nssListIterator *iter = nssList_CreateIterator(subjectList); | |
472 if (iter) { | |
473 for (c = (NSSCertificate *)nssListIterator_Start(iter); | |
474 c != (NSSCertificate *)NULL; | |
475 c = (NSSCertificate *)nssListIterator_Next(iter)) | |
476 { | |
477 nssList_Add(et->emailList, c); | |
478 } | |
479 nssListIterator_Finish(iter); | |
480 nssListIterator_Destroy(iter); | |
481 } | |
482 } | |
483 } | |
484 | |
485 /* | |
486 * Find all cached certs with this email address. | |
487 */ | |
488 NSS_IMPLEMENT NSSCertificate ** | |
489 nssCertificateStore_FindCertificatesByEmail ( | |
490 nssCertificateStore *store, | |
491 NSSASCII7 *email, | |
492 NSSCertificate *rvOpt[], | |
493 PRUint32 maximumOpt, | |
494 NSSArena *arenaOpt | |
495 ) | |
496 { | |
497 NSSCertificate **rvArray = NULL; | |
498 struct email_template_str et; | |
499 et.email = email; | |
500 et.emailList = nssList_Create(NULL, PR_FALSE); | |
501 if (!et.emailList) { | |
502 return NULL; | |
503 } | |
504 PZ_Lock(store->lock); | |
505 nssHash_Iterate(store->subject, match_email, &et); | |
506 if (et.emailList) { | |
507 /* get references before leaving the store's lock protection */ | |
508 nssCertificateList_AddReferences(et.emailList); | |
509 } | |
510 PZ_Unlock(store->lock); | |
511 if (et.emailList) { | |
512 rvArray = get_array_from_list(et.emailList, | |
513 rvOpt, maximumOpt, arenaOpt); | |
514 nssList_Destroy(et.emailList); | |
515 } | |
516 return rvArray; | |
517 } | |
518 | |
519 /* Caller holds store->lock */ | |
520 static NSSCertificate * | |
521 nssCertStore_FindCertByIssuerAndSerialNumberLocked ( | |
522 nssCertificateStore *store, | |
523 NSSDER *issuer, | |
524 NSSDER *serial | |
525 ) | |
526 { | |
527 certificate_hash_entry *entry; | |
528 NSSCertificate *rvCert = NULL; | |
529 NSSCertificate index; | |
530 | |
531 index.issuer = *issuer; | |
532 index.serial = *serial; | |
533 entry = (certificate_hash_entry *) | |
534 nssHash_Lookup(store->issuer_and_serial, &index); | |
535 if (entry) { | |
536 rvCert = nssCertificate_AddRef(entry->cert); | |
537 } | |
538 return rvCert; | |
539 } | |
540 | |
541 NSS_IMPLEMENT NSSCertificate * | |
542 nssCertificateStore_FindCertificateByIssuerAndSerialNumber ( | |
543 nssCertificateStore *store, | |
544 NSSDER *issuer, | |
545 NSSDER *serial | |
546 ) | |
547 { | |
548 NSSCertificate *rvCert = NULL; | |
549 | |
550 PZ_Lock(store->lock); | |
551 rvCert = nssCertStore_FindCertByIssuerAndSerialNumberLocked ( | |
552 store, issuer, serial); | |
553 PZ_Unlock(store->lock); | |
554 return rvCert; | |
555 } | |
556 | |
557 static PRStatus | |
558 issuer_and_serial_from_encoding ( | |
559 NSSBER *encoding, | |
560 NSSDER *issuer, | |
561 NSSDER *serial | |
562 ) | |
563 { | |
564 SECItem derCert, derIssuer, derSerial; | |
565 SECStatus secrv; | |
566 derCert.data = (unsigned char *)encoding->data; | |
567 derCert.len = encoding->size; | |
568 secrv = CERT_IssuerNameFromDERCert(&derCert, &derIssuer); | |
569 if (secrv != SECSuccess) { | |
570 return PR_FAILURE; | |
571 } | |
572 secrv = CERT_SerialNumberFromDERCert(&derCert, &derSerial); | |
573 if (secrv != SECSuccess) { | |
574 PORT_Free(derIssuer.data); | |
575 return PR_FAILURE; | |
576 } | |
577 issuer->data = derIssuer.data; | |
578 issuer->size = derIssuer.len; | |
579 serial->data = derSerial.data; | |
580 serial->size = derSerial.len; | |
581 return PR_SUCCESS; | |
582 } | |
583 | |
584 NSS_IMPLEMENT NSSCertificate * | |
585 nssCertificateStore_FindCertificateByEncodedCertificate ( | |
586 nssCertificateStore *store, | |
587 NSSDER *encoding | |
588 ) | |
589 { | |
590 PRStatus nssrv = PR_FAILURE; | |
591 NSSDER issuer, serial; | |
592 NSSCertificate *rvCert = NULL; | |
593 nssrv = issuer_and_serial_from_encoding(encoding, &issuer, &serial); | |
594 if (nssrv != PR_SUCCESS) { | |
595 return NULL; | |
596 } | |
597 rvCert = nssCertificateStore_FindCertificateByIssuerAndSerialNumber(store, | |
598 &issuer, | |
599 &serial); | |
600 PORT_Free(issuer.data); | |
601 PORT_Free(serial.data); | |
602 return rvCert; | |
603 } | |
604 | |
605 NSS_EXTERN PRStatus | |
606 nssCertificateStore_AddTrust ( | |
607 nssCertificateStore *store, | |
608 NSSTrust *trust | |
609 ) | |
610 { | |
611 NSSCertificate *cert; | |
612 certificate_hash_entry *entry; | |
613 cert = trust->certificate; | |
614 PZ_Lock(store->lock); | |
615 entry = (certificate_hash_entry *) | |
616 nssHash_Lookup(store->issuer_and_serial, cert); | |
617 if (entry) { | |
618 NSSTrust* newTrust = nssTrust_AddRef(trust); | |
619 if (entry->trust) { | |
620 nssTrust_Destroy(entry->trust); | |
621 } | |
622 entry->trust = newTrust; | |
623 } | |
624 PZ_Unlock(store->lock); | |
625 return (entry) ? PR_SUCCESS : PR_FAILURE; | |
626 } | |
627 | |
628 NSS_IMPLEMENT NSSTrust * | |
629 nssCertificateStore_FindTrustForCertificate ( | |
630 nssCertificateStore *store, | |
631 NSSCertificate *cert | |
632 ) | |
633 { | |
634 certificate_hash_entry *entry; | |
635 NSSTrust *rvTrust = NULL; | |
636 PZ_Lock(store->lock); | |
637 entry = (certificate_hash_entry *) | |
638 nssHash_Lookup(store->issuer_and_serial, cert); | |
639 if (entry && entry->trust) { | |
640 rvTrust = nssTrust_AddRef(entry->trust); | |
641 } | |
642 PZ_Unlock(store->lock); | |
643 return rvTrust; | |
644 } | |
645 | |
646 NSS_EXTERN PRStatus | |
647 nssCertificateStore_AddSMIMEProfile ( | |
648 nssCertificateStore *store, | |
649 nssSMIMEProfile *profile | |
650 ) | |
651 { | |
652 NSSCertificate *cert; | |
653 certificate_hash_entry *entry; | |
654 cert = profile->certificate; | |
655 PZ_Lock(store->lock); | |
656 entry = (certificate_hash_entry *) | |
657 nssHash_Lookup(store->issuer_and_serial, cert); | |
658 if (entry) { | |
659 nssSMIMEProfile* newProfile = nssSMIMEProfile_AddRef(profile); | |
660 if (entry->profile) { | |
661 nssSMIMEProfile_Destroy(entry->profile); | |
662 } | |
663 entry->profile = newProfile; | |
664 } | |
665 PZ_Unlock(store->lock); | |
666 return (entry) ? PR_SUCCESS : PR_FAILURE; | |
667 } | |
668 | |
669 NSS_IMPLEMENT nssSMIMEProfile * | |
670 nssCertificateStore_FindSMIMEProfileForCertificate ( | |
671 nssCertificateStore *store, | |
672 NSSCertificate *cert | |
673 ) | |
674 { | |
675 certificate_hash_entry *entry; | |
676 nssSMIMEProfile *rvProfile = NULL; | |
677 PZ_Lock(store->lock); | |
678 entry = (certificate_hash_entry *) | |
679 nssHash_Lookup(store->issuer_and_serial, cert); | |
680 if (entry && entry->profile) { | |
681 rvProfile = nssSMIMEProfile_AddRef(entry->profile); | |
682 } | |
683 PZ_Unlock(store->lock); | |
684 return rvProfile; | |
685 } | |
686 | |
687 /* XXX this is also used by cache and should be somewhere else */ | |
688 | |
689 static PLHashNumber | |
690 nss_certificate_hash ( | |
691 const void *key | |
692 ) | |
693 { | |
694 unsigned int i; | |
695 PLHashNumber h; | |
696 NSSCertificate *c = (NSSCertificate *)key; | |
697 h = 0; | |
698 for (i=0; i<c->issuer.size; i++) | |
699 h = PR_ROTATE_LEFT32(h, 4) ^ ((unsigned char *)c->issuer.data)[i]; | |
700 for (i=0; i<c->serial.size; i++) | |
701 h = PR_ROTATE_LEFT32(h, 4) ^ ((unsigned char *)c->serial.data)[i]; | |
702 return h; | |
703 } | |
704 | |
705 static int | |
706 nss_compare_certs(const void *v1, const void *v2) | |
707 { | |
708 PRStatus ignore; | |
709 NSSCertificate *c1 = (NSSCertificate *)v1; | |
710 NSSCertificate *c2 = (NSSCertificate *)v2; | |
711 return (int)(nssItem_Equal(&c1->issuer, &c2->issuer, &ignore) && | |
712 nssItem_Equal(&c1->serial, &c2->serial, &ignore)); | |
713 } | |
714 | |
715 NSS_IMPLEMENT nssHash * | |
716 nssHash_CreateCertificate ( | |
717 NSSArena *arenaOpt, | |
718 PRUint32 numBuckets | |
719 ) | |
720 { | |
721 return nssHash_Create(arenaOpt, | |
722 numBuckets, | |
723 nss_certificate_hash, | |
724 nss_compare_certs, | |
725 PL_CompareValues); | |
726 } | |
727 | |
728 NSS_IMPLEMENT void | |
729 nssCertificateStore_DumpStoreInfo ( | |
730 nssCertificateStore *store, | |
731 void (* cert_dump_iter)(const void *, void *, void *), | |
732 void *arg | |
733 ) | |
734 { | |
735 PZ_Lock(store->lock); | |
736 nssHash_Iterate(store->issuer_and_serial, cert_dump_iter, arg); | |
737 PZ_Unlock(store->lock); | |
738 } | |
739 |