Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(384)

Side by Side Diff: nss/lib/pki/pkistore.c

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

Powered by Google App Engine
This is Rietveld 408576698