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 /*
6  * Hacks to integrate NSS 3.4 and NSS 4.0 certificates.
7  */
8 
9 #ifndef NSSPKI_H
10 #include "nsspki.h"
11 #endif /* NSSPKI_H */
12 
13 #ifndef PKI_H
14 #include "pki.h"
15 #endif /* PKI_H */
16 
17 #ifndef PKIM_H
18 #include "pkim.h"
19 #endif /* PKIM_H */
20 
21 #ifndef DEV_H
22 #include "dev.h"
23 #endif /* DEV_H */
24 
25 #ifndef DEVNSS3HACK_H
26 #include "dev3hack.h"
27 #endif /* DEVNSS3HACK_H */
28 
29 #ifndef PKINSS3HACK_H
30 #include "pki3hack.h"
31 #endif /* PKINSS3HACK_H */
32 
33 #include "secitem.h"
34 #include "certdb.h"
35 #include "certt.h"
36 #include "cert.h"
37 #include "certi.h"
38 #include "pk11func.h"
39 #include "pkistore.h"
40 #include "secmod.h"
41 #include "nssrwlk.h"
42 
43 NSSTrustDomain *g_default_trust_domain = NULL;
44 
45 NSSCryptoContext *g_default_crypto_context = NULL;
46 
47 NSSTrustDomain *
STAN_GetDefaultTrustDomain()48 STAN_GetDefaultTrustDomain()
49 {
50     return g_default_trust_domain;
51 }
52 
53 NSSCryptoContext *
STAN_GetDefaultCryptoContext()54 STAN_GetDefaultCryptoContext()
55 {
56     return g_default_crypto_context;
57 }
58 
59 extern const NSSError NSS_ERROR_ALREADY_INITIALIZED;
60 extern const NSSError NSS_ERROR_INTERNAL_ERROR;
61 
62 NSS_IMPLEMENT PRStatus
STAN_InitTokenForSlotInfo(NSSTrustDomain * td,PK11SlotInfo * slot)63 STAN_InitTokenForSlotInfo(NSSTrustDomain *td, PK11SlotInfo *slot)
64 {
65     NSSToken *token;
66     if (!td) {
67         td = g_default_trust_domain;
68         if (!td) {
69             /* we're called while still initting. slot will get added
70              * appropriately through normal init processes */
71             return PR_SUCCESS;
72         }
73     }
74     token = nssToken_CreateFromPK11SlotInfo(td, slot);
75     if (token) {
76         /* PK11Slot_SetNSSToken increments the refcount on |token| to 2 */
77         PK11Slot_SetNSSToken(slot, token);
78 
79         /* we give our reference to |td->tokenList| */
80         NSSRWLock_LockWrite(td->tokensLock);
81         nssList_Add(td->tokenList, token);
82         NSSRWLock_UnlockWrite(td->tokensLock);
83     } else {
84         PK11Slot_SetNSSToken(slot, NULL);
85     }
86     return PR_SUCCESS;
87 }
88 
89 NSS_IMPLEMENT PRStatus
STAN_ResetTokenInterator(NSSTrustDomain * td)90 STAN_ResetTokenInterator(NSSTrustDomain *td)
91 {
92     if (!td) {
93         td = g_default_trust_domain;
94         if (!td) {
95             /* we're called while still initting. slot will get added
96              * appropriately through normal init processes */
97             return PR_SUCCESS;
98         }
99     }
100     NSSRWLock_LockWrite(td->tokensLock);
101     nssListIterator_Destroy(td->tokens);
102     td->tokens = nssList_CreateIterator(td->tokenList);
103     NSSRWLock_UnlockWrite(td->tokensLock);
104     return PR_SUCCESS;
105 }
106 
107 NSS_IMPLEMENT PRStatus
STAN_LoadDefaultNSS3TrustDomain(void)108 STAN_LoadDefaultNSS3TrustDomain(
109     void)
110 {
111     NSSTrustDomain *td;
112     SECMODModuleList *mlp;
113     SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock();
114     int i;
115 
116     if (g_default_trust_domain || g_default_crypto_context) {
117         /* Stan is already initialized or a previous shutdown failed. */
118         nss_SetError(NSS_ERROR_ALREADY_INITIALIZED);
119         return PR_FAILURE;
120     }
121     td = NSSTrustDomain_Create(NULL, NULL, NULL, NULL);
122     if (!td) {
123         return PR_FAILURE;
124     }
125     /*
126      * Deadlock warning: we should never acquire the moduleLock while
127      * we hold the tokensLock. We can use the NSSRWLock Rank feature to
128      * guarrentee this. tokensLock have a higher rank than module lock.
129      */
130     td->tokenList = nssList_Create(td->arena, PR_TRUE);
131     if (!td->tokenList) {
132         goto loser;
133     }
134     SECMOD_GetReadLock(moduleLock);
135     NSSRWLock_LockWrite(td->tokensLock);
136     for (mlp = SECMOD_GetDefaultModuleList(); mlp != NULL; mlp = mlp->next) {
137         for (i = 0; i < mlp->module->slotCount; i++) {
138             STAN_InitTokenForSlotInfo(td, mlp->module->slots[i]);
139         }
140     }
141     td->tokens = nssList_CreateIterator(td->tokenList);
142     NSSRWLock_UnlockWrite(td->tokensLock);
143     SECMOD_ReleaseReadLock(moduleLock);
144     if (!td->tokens) {
145         goto loser;
146     }
147     g_default_crypto_context = NSSTrustDomain_CreateCryptoContext(td, NULL);
148     if (!g_default_crypto_context) {
149         goto loser;
150     }
151     g_default_trust_domain = td;
152     return PR_SUCCESS;
153 
154 loser:
155     NSSTrustDomain_Destroy(td);
156     return PR_FAILURE;
157 }
158 
159 /*
160  * must be called holding the ModuleListLock (either read or write).
161  */
162 NSS_IMPLEMENT SECStatus
STAN_AddModuleToDefaultTrustDomain(SECMODModule * module)163 STAN_AddModuleToDefaultTrustDomain(
164     SECMODModule *module)
165 {
166     NSSTrustDomain *td;
167     int i;
168     td = STAN_GetDefaultTrustDomain();
169     for (i = 0; i < module->slotCount; i++) {
170         STAN_InitTokenForSlotInfo(td, module->slots[i]);
171     }
172     STAN_ResetTokenInterator(td);
173     return SECSuccess;
174 }
175 
176 /*
177  * must be called holding the ModuleListLock (either read or write).
178  */
179 NSS_IMPLEMENT SECStatus
STAN_RemoveModuleFromDefaultTrustDomain(SECMODModule * module)180 STAN_RemoveModuleFromDefaultTrustDomain(
181     SECMODModule *module)
182 {
183     NSSToken *token;
184     NSSTrustDomain *td;
185     int i;
186     td = STAN_GetDefaultTrustDomain();
187     for (i = 0; i < module->slotCount; i++) {
188         token = PK11Slot_GetNSSToken(module->slots[i]);
189         if (token) {
190             nssToken_NotifyCertsNotVisible(token);
191             NSSRWLock_LockWrite(td->tokensLock);
192             nssList_Remove(td->tokenList, token);
193             NSSRWLock_UnlockWrite(td->tokensLock);
194             PK11Slot_SetNSSToken(module->slots[i], NULL);
195             (void)nssToken_Destroy(token); /* for the |td->tokenList| reference */
196             (void)nssToken_Destroy(token); /* for our PK11Slot_GetNSSToken reference */
197         }
198     }
199     NSSRWLock_LockWrite(td->tokensLock);
200     nssListIterator_Destroy(td->tokens);
201     td->tokens = nssList_CreateIterator(td->tokenList);
202     NSSRWLock_UnlockWrite(td->tokensLock);
203     return SECSuccess;
204 }
205 
206 NSS_IMPLEMENT PRStatus
STAN_Shutdown()207 STAN_Shutdown()
208 {
209     PRStatus status = PR_SUCCESS;
210     if (g_default_trust_domain) {
211         if (NSSTrustDomain_Destroy(g_default_trust_domain) == PR_SUCCESS) {
212             g_default_trust_domain = NULL;
213         } else {
214             status = PR_FAILURE;
215         }
216     }
217     if (g_default_crypto_context) {
218         if (NSSCryptoContext_Destroy(g_default_crypto_context) == PR_SUCCESS) {
219             g_default_crypto_context = NULL;
220         } else {
221             status = PR_FAILURE;
222         }
223     }
224     return status;
225 }
226 
227 /* this function should not be a hack; it will be needed in 4.0 (rename) */
228 NSS_IMPLEMENT NSSItem *
STAN_GetCertIdentifierFromDER(NSSArena * arenaOpt,NSSDER * der)229 STAN_GetCertIdentifierFromDER(NSSArena *arenaOpt, NSSDER *der)
230 {
231     NSSItem *rvKey;
232     SECItem secDER;
233     SECItem secKey = { 0 };
234     SECStatus secrv;
235     PLArenaPool *arena;
236 
237     SECITEM_FROM_NSSITEM(&secDER, der);
238 
239     /* nss3 call uses nss3 arena's */
240     arena = PORT_NewArena(256);
241     if (!arena) {
242         return NULL;
243     }
244     secrv = CERT_KeyFromDERCert(arena, &secDER, &secKey);
245     if (secrv != SECSuccess) {
246         PORT_FreeArena(arena, PR_FALSE);
247         return NULL;
248     }
249     rvKey = nssItem_Create(arenaOpt, NULL, secKey.len, (void *)secKey.data);
250     PORT_FreeArena(arena, PR_FALSE);
251     return rvKey;
252 }
253 
254 NSS_IMPLEMENT PRStatus
nssPKIX509_GetIssuerAndSerialFromDER(NSSDER * der,NSSDER * issuer,NSSDER * serial)255 nssPKIX509_GetIssuerAndSerialFromDER(NSSDER *der,
256                                      NSSDER *issuer, NSSDER *serial)
257 {
258     SECItem derCert = { 0 };
259     SECItem derIssuer = { 0 };
260     SECItem derSerial = { 0 };
261     SECStatus secrv;
262     derCert.data = (unsigned char *)der->data;
263     derCert.len = der->size;
264     secrv = CERT_IssuerNameFromDERCert(&derCert, &derIssuer);
265     if (secrv != SECSuccess) {
266         return PR_FAILURE;
267     }
268     secrv = CERT_SerialNumberFromDERCert(&derCert, &derSerial);
269     if (secrv != SECSuccess) {
270         PORT_Free(derSerial.data);
271         return PR_FAILURE;
272     }
273     issuer->data = derIssuer.data;
274     issuer->size = derIssuer.len;
275     serial->data = derSerial.data;
276     serial->size = derSerial.len;
277     return PR_SUCCESS;
278 }
279 
280 static NSSItem *
nss3certificate_getIdentifier(nssDecodedCert * dc)281 nss3certificate_getIdentifier(nssDecodedCert *dc)
282 {
283     NSSItem *rvID;
284     CERTCertificate *c = (CERTCertificate *)dc->data;
285     rvID = nssItem_Create(NULL, NULL, c->certKey.len, c->certKey.data);
286     return rvID;
287 }
288 
289 static void *
nss3certificate_getIssuerIdentifier(nssDecodedCert * dc)290 nss3certificate_getIssuerIdentifier(nssDecodedCert *dc)
291 {
292     CERTCertificate *c = (CERTCertificate *)dc->data;
293     return (void *)c->authKeyID;
294 }
295 
296 static nssCertIDMatch
nss3certificate_matchIdentifier(nssDecodedCert * dc,void * id)297 nss3certificate_matchIdentifier(nssDecodedCert *dc, void *id)
298 {
299     CERTCertificate *c = (CERTCertificate *)dc->data;
300     CERTAuthKeyID *authKeyID = (CERTAuthKeyID *)id;
301     SECItem skid;
302     nssCertIDMatch match = nssCertIDMatch_Unknown;
303 
304     /* keyIdentifier */
305     if (authKeyID->keyID.len > 0 &&
306         CERT_FindSubjectKeyIDExtension(c, &skid) == SECSuccess) {
307         PRBool skiEqual;
308         skiEqual = SECITEM_ItemsAreEqual(&authKeyID->keyID, &skid);
309         PORT_Free(skid.data);
310         if (skiEqual) {
311             /* change the state to positive match, but keep going */
312             match = nssCertIDMatch_Yes;
313         } else {
314             /* exit immediately on failure */
315             return nssCertIDMatch_No;
316         }
317     }
318 
319     /* issuer/serial (treated as pair) */
320     if (authKeyID->authCertIssuer) {
321         SECItem *caName = NULL;
322         SECItem *caSN = &authKeyID->authCertSerialNumber;
323 
324         caName = (SECItem *)CERT_GetGeneralNameByType(
325             authKeyID->authCertIssuer,
326             certDirectoryName, PR_TRUE);
327         if (caName != NULL &&
328             SECITEM_ItemsAreEqual(&c->derIssuer, caName) &&
329             SECITEM_ItemsAreEqual(&c->serialNumber, caSN)) {
330             match = nssCertIDMatch_Yes;
331         } else {
332             match = nssCertIDMatch_Unknown;
333         }
334     }
335     return match;
336 }
337 
338 static PRBool
nss3certificate_isValidIssuer(nssDecodedCert * dc)339 nss3certificate_isValidIssuer(nssDecodedCert *dc)
340 {
341     CERTCertificate *c = (CERTCertificate *)dc->data;
342     unsigned int ignore;
343     return CERT_IsCACert(c, &ignore);
344 }
345 
346 static NSSUsage *
nss3certificate_getUsage(nssDecodedCert * dc)347 nss3certificate_getUsage(nssDecodedCert *dc)
348 {
349     /* CERTCertificate *c = (CERTCertificate *)dc->data; */
350     return NULL;
351 }
352 
353 static PRBool
nss3certificate_isValidAtTime(nssDecodedCert * dc,NSSTime * time)354 nss3certificate_isValidAtTime(nssDecodedCert *dc, NSSTime *time)
355 {
356     SECCertTimeValidity validity;
357     CERTCertificate *c = (CERTCertificate *)dc->data;
358     validity = CERT_CheckCertValidTimes(c, NSSTime_GetPRTime(time), PR_TRUE);
359     if (validity == secCertTimeValid) {
360         return PR_TRUE;
361     }
362     return PR_FALSE;
363 }
364 
365 static PRBool
nss3certificate_isNewerThan(nssDecodedCert * dc,nssDecodedCert * cmpdc)366 nss3certificate_isNewerThan(nssDecodedCert *dc, nssDecodedCert *cmpdc)
367 {
368     /* I know this isn't right, but this is glue code anyway */
369     if (cmpdc->type == dc->type) {
370         CERTCertificate *certa = (CERTCertificate *)dc->data;
371         CERTCertificate *certb = (CERTCertificate *)cmpdc->data;
372         return CERT_IsNewer(certa, certb);
373     }
374     return PR_FALSE;
375 }
376 
377 /* CERT_FilterCertListByUsage */
378 static PRBool
nss3certificate_matchUsage(nssDecodedCert * dc,const NSSUsage * usage)379 nss3certificate_matchUsage(nssDecodedCert *dc, const NSSUsage *usage)
380 {
381     CERTCertificate *cc;
382     unsigned int requiredKeyUsage = 0;
383     unsigned int requiredCertType = 0;
384     SECStatus secrv;
385     PRBool match;
386     PRBool ca;
387 
388     /* This is for NSS 3.3 functions that do not specify a usage */
389     if (usage->anyUsage) {
390         return PR_TRUE;
391     }
392     ca = usage->nss3lookingForCA;
393     secrv = CERT_KeyUsageAndTypeForCertUsage(usage->nss3usage, ca,
394                                              &requiredKeyUsage,
395                                              &requiredCertType);
396     if (secrv != SECSuccess) {
397         return PR_FALSE;
398     }
399     cc = (CERTCertificate *)dc->data;
400     secrv = CERT_CheckKeyUsage(cc, requiredKeyUsage);
401     match = (PRBool)(secrv == SECSuccess);
402     if (match) {
403         unsigned int certType = 0;
404         if (ca) {
405             (void)CERT_IsCACert(cc, &certType);
406         } else {
407             certType = cc->nsCertType;
408         }
409         if (!(certType & requiredCertType)) {
410             match = PR_FALSE;
411         }
412     }
413     return match;
414 }
415 
416 static PRBool
nss3certificate_isTrustedForUsage(nssDecodedCert * dc,const NSSUsage * usage)417 nss3certificate_isTrustedForUsage(nssDecodedCert *dc, const NSSUsage *usage)
418 {
419     CERTCertificate *cc;
420     PRBool ca;
421     SECStatus secrv;
422     unsigned int requiredFlags;
423     unsigned int trustFlags;
424     SECTrustType trustType;
425     CERTCertTrust trust;
426 
427     /* This is for NSS 3.3 functions that do not specify a usage */
428     if (usage->anyUsage) {
429         return PR_FALSE; /* XXX is this right? */
430     }
431     cc = (CERTCertificate *)dc->data;
432     ca = usage->nss3lookingForCA;
433     if (!ca) {
434         PRBool trusted;
435         unsigned int failedFlags;
436         secrv = cert_CheckLeafTrust(cc, usage->nss3usage,
437                                     &failedFlags, &trusted);
438         return secrv == SECSuccess && trusted;
439     }
440     secrv = CERT_TrustFlagsForCACertUsage(usage->nss3usage, &requiredFlags,
441                                           &trustType);
442     if (secrv != SECSuccess) {
443         return PR_FALSE;
444     }
445     secrv = CERT_GetCertTrust(cc, &trust);
446     if (secrv != SECSuccess) {
447         return PR_FALSE;
448     }
449     if (trustType == trustTypeNone) {
450         /* normally trustTypeNone usages accept any of the given trust bits
451          * being on as acceptable. */
452         trustFlags = trust.sslFlags | trust.emailFlags |
453                      trust.objectSigningFlags;
454     } else {
455         trustFlags = SEC_GET_TRUST_FLAGS(&trust, trustType);
456     }
457     return (trustFlags & requiredFlags) == requiredFlags;
458 }
459 
460 static NSSASCII7 *
nss3certificate_getEmailAddress(nssDecodedCert * dc)461 nss3certificate_getEmailAddress(nssDecodedCert *dc)
462 {
463     CERTCertificate *cc = (CERTCertificate *)dc->data;
464     return (cc && cc->emailAddr && cc->emailAddr[0])
465                ? (NSSASCII7 *)cc->emailAddr
466                : NULL;
467 }
468 
469 static PRStatus
nss3certificate_getDERSerialNumber(nssDecodedCert * dc,NSSDER * serial,NSSArena * arena)470 nss3certificate_getDERSerialNumber(nssDecodedCert *dc,
471                                    NSSDER *serial, NSSArena *arena)
472 {
473     CERTCertificate *cc = (CERTCertificate *)dc->data;
474     SECItem derSerial = { 0 };
475     SECStatus secrv;
476     secrv = CERT_SerialNumberFromDERCert(&cc->derCert, &derSerial);
477     if (secrv == SECSuccess) {
478         (void)nssItem_Create(arena, serial, derSerial.len, derSerial.data);
479         PORT_Free(derSerial.data);
480         return PR_SUCCESS;
481     }
482     return PR_FAILURE;
483 }
484 
485 /* Returns NULL if "encoding" cannot be decoded. */
486 NSS_IMPLEMENT nssDecodedCert *
nssDecodedPKIXCertificate_Create(NSSArena * arenaOpt,NSSDER * encoding)487 nssDecodedPKIXCertificate_Create(
488     NSSArena *arenaOpt,
489     NSSDER *encoding)
490 {
491     nssDecodedCert *rvDC = NULL;
492     CERTCertificate *cert;
493     SECItem secDER;
494 
495     SECITEM_FROM_NSSITEM(&secDER, encoding);
496     cert = CERT_DecodeDERCertificate(&secDER, PR_TRUE, NULL);
497     if (cert) {
498         rvDC = nss_ZNEW(arenaOpt, nssDecodedCert);
499         if (rvDC) {
500             rvDC->type = NSSCertificateType_PKIX;
501             rvDC->data = (void *)cert;
502             rvDC->getIdentifier = nss3certificate_getIdentifier;
503             rvDC->getIssuerIdentifier = nss3certificate_getIssuerIdentifier;
504             rvDC->matchIdentifier = nss3certificate_matchIdentifier;
505             rvDC->isValidIssuer = nss3certificate_isValidIssuer;
506             rvDC->getUsage = nss3certificate_getUsage;
507             rvDC->isValidAtTime = nss3certificate_isValidAtTime;
508             rvDC->isNewerThan = nss3certificate_isNewerThan;
509             rvDC->matchUsage = nss3certificate_matchUsage;
510             rvDC->isTrustedForUsage = nss3certificate_isTrustedForUsage;
511             rvDC->getEmailAddress = nss3certificate_getEmailAddress;
512             rvDC->getDERSerialNumber = nss3certificate_getDERSerialNumber;
513         } else {
514             CERT_DestroyCertificate(cert);
515         }
516     }
517     return rvDC;
518 }
519 
520 static nssDecodedCert *
create_decoded_pkix_cert_from_nss3cert(NSSArena * arenaOpt,CERTCertificate * cc)521 create_decoded_pkix_cert_from_nss3cert(
522     NSSArena *arenaOpt,
523     CERTCertificate *cc)
524 {
525     nssDecodedCert *rvDC = nss_ZNEW(arenaOpt, nssDecodedCert);
526     if (rvDC) {
527         rvDC->type = NSSCertificateType_PKIX;
528         rvDC->data = (void *)cc;
529         rvDC->getIdentifier = nss3certificate_getIdentifier;
530         rvDC->getIssuerIdentifier = nss3certificate_getIssuerIdentifier;
531         rvDC->matchIdentifier = nss3certificate_matchIdentifier;
532         rvDC->isValidIssuer = nss3certificate_isValidIssuer;
533         rvDC->getUsage = nss3certificate_getUsage;
534         rvDC->isValidAtTime = nss3certificate_isValidAtTime;
535         rvDC->isNewerThan = nss3certificate_isNewerThan;
536         rvDC->matchUsage = nss3certificate_matchUsage;
537         rvDC->isTrustedForUsage = nss3certificate_isTrustedForUsage;
538         rvDC->getEmailAddress = nss3certificate_getEmailAddress;
539         rvDC->getDERSerialNumber = nss3certificate_getDERSerialNumber;
540     }
541     return rvDC;
542 }
543 
544 NSS_IMPLEMENT PRStatus
nssDecodedPKIXCertificate_Destroy(nssDecodedCert * dc)545 nssDecodedPKIXCertificate_Destroy(nssDecodedCert *dc)
546 {
547     CERTCertificate *cert = (CERTCertificate *)dc->data;
548 
549     /* The decoder may only be half initialized (the case where we find we
550      * could not decode the certificate). In this case, there is not cert to
551      * free, just free the dc structure. */
552     if (cert) {
553         PRBool freeSlot = cert->ownSlot;
554         PK11SlotInfo *slot = cert->slot;
555         PLArenaPool *arena = cert->arena;
556         /* zero cert before freeing. Any stale references to this cert
557          * after this point will probably cause an exception.  */
558         PORT_Memset(cert, 0, sizeof *cert);
559         /* free the arena that contains the cert. */
560         PORT_FreeArena(arena, PR_FALSE);
561         if (slot && freeSlot) {
562             PK11_FreeSlot(slot);
563         }
564     }
565     nss_ZFreeIf(dc);
566     return PR_SUCCESS;
567 }
568 
569 /* see pk11cert.c:pk11_HandleTrustObject */
570 static unsigned int
get_nss3trust_from_nss4trust(nssTrustLevel t)571 get_nss3trust_from_nss4trust(nssTrustLevel t)
572 {
573     unsigned int rt = 0;
574     if (t == nssTrustLevel_Trusted) {
575         rt |= CERTDB_TERMINAL_RECORD | CERTDB_TRUSTED;
576     }
577     if (t == nssTrustLevel_TrustedDelegator) {
578         rt |= CERTDB_VALID_CA | CERTDB_TRUSTED_CA;
579     }
580     if (t == nssTrustLevel_NotTrusted) {
581         rt |= CERTDB_TERMINAL_RECORD;
582     }
583     if (t == nssTrustLevel_ValidDelegator) {
584         rt |= CERTDB_VALID_CA;
585     }
586     return rt;
587 }
588 
589 static CERTCertTrust *
cert_trust_from_stan_trust(NSSTrust * t,PLArenaPool * arena)590 cert_trust_from_stan_trust(NSSTrust *t, PLArenaPool *arena)
591 {
592     CERTCertTrust *rvTrust;
593     unsigned int client;
594     if (!t) {
595         return NULL;
596     }
597     rvTrust = PORT_ArenaAlloc(arena, sizeof(CERTCertTrust));
598     if (!rvTrust)
599         return NULL;
600     rvTrust->sslFlags = get_nss3trust_from_nss4trust(t->serverAuth);
601     client = get_nss3trust_from_nss4trust(t->clientAuth);
602     if (client & (CERTDB_TRUSTED_CA | CERTDB_NS_TRUSTED_CA)) {
603         client &= ~(CERTDB_TRUSTED_CA | CERTDB_NS_TRUSTED_CA);
604         rvTrust->sslFlags |= CERTDB_TRUSTED_CLIENT_CA;
605     }
606     rvTrust->sslFlags |= client;
607     rvTrust->emailFlags = get_nss3trust_from_nss4trust(t->emailProtection);
608     rvTrust->objectSigningFlags = get_nss3trust_from_nss4trust(t->codeSigning);
609     return rvTrust;
610 }
611 
612 CERTCertTrust *
nssTrust_GetCERTCertTrustForCert(NSSCertificate * c,CERTCertificate * cc)613 nssTrust_GetCERTCertTrustForCert(NSSCertificate *c, CERTCertificate *cc)
614 {
615     CERTCertTrust *rvTrust = NULL;
616     NSSTrustDomain *td = STAN_GetDefaultTrustDomain();
617     NSSTrust *t;
618     t = nssTrustDomain_FindTrustForCertificate(td, c);
619     if (t) {
620         rvTrust = cert_trust_from_stan_trust(t, cc->arena);
621         if (!rvTrust) {
622             nssTrust_Destroy(t);
623             return NULL;
624         }
625         nssTrust_Destroy(t);
626     } else {
627         rvTrust = PORT_ArenaAlloc(cc->arena, sizeof(CERTCertTrust));
628         if (!rvTrust) {
629             return NULL;
630         }
631         memset(rvTrust, 0, sizeof(*rvTrust));
632     }
633     if (NSSCertificate_IsPrivateKeyAvailable(c, NULL, NULL)) {
634         rvTrust->sslFlags |= CERTDB_USER;
635         rvTrust->emailFlags |= CERTDB_USER;
636         rvTrust->objectSigningFlags |= CERTDB_USER;
637     }
638     return rvTrust;
639 }
640 
641 static nssCryptokiInstance *
get_cert_instance(NSSCertificate * c)642 get_cert_instance(NSSCertificate *c)
643 {
644     nssCryptokiObject *instance, **ci;
645     nssCryptokiObject **instances = nssPKIObject_GetInstances(&c->object);
646     if (!instances) {
647         return NULL;
648     }
649     instance = NULL;
650     for (ci = instances; *ci; ci++) {
651         if (!instance) {
652             instance = nssCryptokiObject_Clone(*ci);
653         } else {
654             /* This only really works for two instances...  But 3.4 can't
655              * handle more anyway.  The logic is, if there are multiple
656              * instances, prefer the one that is not internal (e.g., on
657              * a hardware device.
658              */
659             if (PK11_IsInternal(instance->token->pk11slot)) {
660                 nssCryptokiObject_Destroy(instance);
661                 instance = nssCryptokiObject_Clone(*ci);
662             }
663         }
664     }
665     nssCryptokiObjectArray_Destroy(instances);
666     return instance;
667 }
668 
669 char *
STAN_GetCERTCertificateNameForInstance(PLArenaPool * arenaOpt,NSSCertificate * c,nssCryptokiInstance * instance)670 STAN_GetCERTCertificateNameForInstance(
671     PLArenaPool *arenaOpt,
672     NSSCertificate *c,
673     nssCryptokiInstance *instance)
674 {
675     NSSCryptoContext *context = c->object.cryptoContext;
676     PRStatus nssrv;
677     int nicklen, tokenlen, len;
678     NSSUTF8 *tokenName = NULL;
679     NSSUTF8 *stanNick = NULL;
680     char *nickname = NULL;
681     char *nick;
682 
683     if (instance) {
684         stanNick = instance->label;
685     } else if (context) {
686         stanNick = c->object.tempName;
687     }
688     if (stanNick) {
689         /* fill other fields needed by NSS3 functions using CERTCertificate */
690         if (instance && (!PK11_IsInternalKeySlot(instance->token->pk11slot) ||
691                          PORT_Strchr(stanNick, ':') != NULL)) {
692             tokenName = nssToken_GetName(instance->token);
693             tokenlen = nssUTF8_Size(tokenName, &nssrv);
694         } else {
695             /* don't use token name for internal slot; 3.3 didn't */
696             tokenlen = 0;
697         }
698         nicklen = nssUTF8_Size(stanNick, &nssrv);
699         len = tokenlen + nicklen;
700         if (arenaOpt) {
701             nickname = PORT_ArenaAlloc(arenaOpt, len);
702         } else {
703             nickname = PORT_Alloc(len);
704         }
705         nick = nickname;
706         if (tokenName) {
707             memcpy(nick, tokenName, tokenlen - 1);
708             nick += tokenlen - 1;
709             *nick++ = ':';
710         }
711         memcpy(nick, stanNick, nicklen - 1);
712         nickname[len - 1] = '\0';
713     }
714     return nickname;
715 }
716 
717 char *
STAN_GetCERTCertificateName(PLArenaPool * arenaOpt,NSSCertificate * c)718 STAN_GetCERTCertificateName(PLArenaPool *arenaOpt, NSSCertificate *c)
719 {
720     char *result;
721     nssCryptokiInstance *instance = get_cert_instance(c);
722     /* It's OK to call this function, even if instance is NULL */
723     result = STAN_GetCERTCertificateNameForInstance(arenaOpt, c, instance);
724     if (instance)
725         nssCryptokiObject_Destroy(instance);
726     return result;
727 }
728 
729 static void
fill_CERTCertificateFields(NSSCertificate * c,CERTCertificate * cc,PRBool forced)730 fill_CERTCertificateFields(NSSCertificate *c, CERTCertificate *cc, PRBool forced)
731 {
732     CERTCertTrust *trust = NULL;
733     NSSTrust *nssTrust;
734     NSSCryptoContext *context = c->object.cryptoContext;
735     nssCryptokiInstance *instance;
736     NSSUTF8 *stanNick = NULL;
737 
738     /* We are holding the base class object's lock on entry of this function
739      * This lock protects writes to fields of the CERTCertificate .
740      * It is also needed by some functions to compute values such as trust.
741      */
742     instance = get_cert_instance(c);
743 
744     if (instance) {
745         stanNick = instance->label;
746     } else if (context) {
747         stanNick = c->object.tempName;
748     }
749     /* fill other fields needed by NSS3 functions using CERTCertificate */
750     if ((!cc->nickname && stanNick) || forced) {
751         PRStatus nssrv;
752         int nicklen, tokenlen, len;
753         NSSUTF8 *tokenName = NULL;
754         char *nick;
755         if (instance &&
756             (!PK11_IsInternalKeySlot(instance->token->pk11slot) ||
757              (stanNick && PORT_Strchr(stanNick, ':') != NULL))) {
758             tokenName = nssToken_GetName(instance->token);
759             tokenlen = nssUTF8_Size(tokenName, &nssrv);
760         } else {
761             /* don't use token name for internal slot; 3.3 didn't */
762             tokenlen = 0;
763         }
764         if (stanNick) {
765             nicklen = nssUTF8_Size(stanNick, &nssrv);
766             len = tokenlen + nicklen;
767             nick = PORT_ArenaAlloc(cc->arena, len);
768             if (tokenName) {
769                 memcpy(nick, tokenName, tokenlen - 1);
770                 nick[tokenlen - 1] = ':';
771                 memcpy(nick + tokenlen, stanNick, nicklen - 1);
772             } else {
773                 memcpy(nick, stanNick, nicklen - 1);
774             }
775             nick[len - 1] = '\0';
776             cc->nickname = nick;
777         } else {
778             cc->nickname = NULL;
779         }
780     }
781     if (context) {
782         /* trust */
783         nssTrust = nssCryptoContext_FindTrustForCertificate(context, c);
784         if (!nssTrust) {
785             /* chicken and egg issue:
786              *
787              * c->issuer and c->serial are empty at this point, but
788              * nssTrustDomain_FindTrustForCertificate use them to look up
789              * up the trust object, so we point them to cc->derIssuer and
790              * cc->serialNumber.
791              *
792              * Our caller will fill these in with proper arena copies when we
793              * return. */
794             c->issuer.data = cc->derIssuer.data;
795             c->issuer.size = cc->derIssuer.len;
796             c->serial.data = cc->serialNumber.data;
797             c->serial.size = cc->serialNumber.len;
798             nssTrust = nssTrustDomain_FindTrustForCertificate(context->td, c);
799         }
800         if (nssTrust) {
801             trust = cert_trust_from_stan_trust(nssTrust, cc->arena);
802             if (trust) {
803                 /* we should destroy cc->trust before replacing it, but it's
804                    allocated in cc->arena, so memory growth will occur on each
805                    refresh */
806                 CERT_LockCertTrust(cc);
807                 cc->trust = trust;
808                 CERT_UnlockCertTrust(cc);
809             }
810             nssTrust_Destroy(nssTrust);
811         }
812     } else if (instance) {
813         /* slot */
814         if (cc->slot != instance->token->pk11slot) {
815             if (cc->slot) {
816                 PK11_FreeSlot(cc->slot);
817             }
818             cc->slot = PK11_ReferenceSlot(instance->token->pk11slot);
819         }
820         cc->ownSlot = PR_TRUE;
821         /* pkcs11ID */
822         cc->pkcs11ID = instance->handle;
823         /* trust */
824         trust = nssTrust_GetCERTCertTrustForCert(c, cc);
825         if (trust) {
826             /* we should destroy cc->trust before replacing it, but it's
827                allocated in cc->arena, so memory growth will occur on each
828                refresh */
829             CERT_LockCertTrust(cc);
830             cc->trust = trust;
831             CERT_UnlockCertTrust(cc);
832         }
833         /* Read the distrust fields from a nssckbi/builtins certificate and
834          * fill the fields in CERTCertificate structure when any valid date
835          * is found. */
836         if (PK11_IsReadOnly(cc->slot) && PK11_HasRootCerts(cc->slot)) {
837             /* The values are hard-coded and readonly. Read just once. */
838             if (cc->distrust == NULL) {
839                 CERTCertDistrust distrustModel;
840                 SECItem model = { siUTCTime, NULL, 0 };
841                 distrustModel.serverDistrustAfter = model;
842                 distrustModel.emailDistrustAfter = model;
843                 SECStatus rServer = PK11_ReadAttribute(
844                     cc->slot, cc->pkcs11ID, CKA_NSS_SERVER_DISTRUST_AFTER,
845                     cc->arena, &distrustModel.serverDistrustAfter);
846                 SECStatus rEmail = PK11_ReadAttribute(
847                     cc->slot, cc->pkcs11ID, CKA_NSS_EMAIL_DISTRUST_AFTER,
848                     cc->arena, &distrustModel.emailDistrustAfter);
849                 /* Only allocate the Distrust structure if a valid date is found.
850                  * The result length of a encoded valid timestamp is exactly 13 */
851                 const unsigned int kDistrustFieldSize = 13;
852                 if ((rServer == SECSuccess && rEmail == SECSuccess) &&
853                     (distrustModel.serverDistrustAfter.len == kDistrustFieldSize ||
854                      distrustModel.emailDistrustAfter.len == kDistrustFieldSize)) {
855                     CERTCertDistrust *tmpPtr = PORT_ArenaAlloc(
856                         cc->arena, sizeof(CERTCertDistrust));
857                     PORT_Memcpy(tmpPtr, &distrustModel,
858                                 sizeof(CERTCertDistrust));
859                     cc->distrust = tmpPtr;
860                 }
861             }
862         }
863     }
864     if (instance) {
865         nssCryptokiObject_Destroy(instance);
866     }
867     /* database handle is now the trust domain */
868     cc->dbhandle = c->object.trustDomain;
869     /* subjectList ? */
870     /* istemp and isperm are supported in NSS 3.4 */
871     CERT_LockCertTempPerm(cc);
872     cc->istemp = PR_FALSE; /* CERT_NewTemp will override this */
873     cc->isperm = PR_TRUE;  /* by default */
874     /* pointer back */
875     cc->nssCertificate = c;
876     CERT_UnlockCertTempPerm(cc);
877     if (trust) {
878         /* force the cert type to be recomputed to include trust info */
879         PRUint32 nsCertType = cert_ComputeCertType(cc);
880 
881         /* Assert that it is safe to cast &cc->nsCertType to "PRInt32 *" */
882         PORT_Assert(sizeof(cc->nsCertType) == sizeof(PRInt32));
883         PR_ATOMIC_SET((PRInt32 *)&cc->nsCertType, nsCertType);
884     }
885 }
886 
887 static CERTCertificate *
stan_GetCERTCertificate(NSSCertificate * c,PRBool forceUpdate)888 stan_GetCERTCertificate(NSSCertificate *c, PRBool forceUpdate)
889 {
890     nssDecodedCert *dc = NULL;
891     CERTCertificate *cc = NULL;
892     CERTCertTrust certTrust;
893 
894     /* make sure object does not go away until we finish */
895     nssPKIObject_AddRef(&c->object);
896     nssPKIObject_Lock(&c->object);
897 
898     dc = c->decoding;
899     if (!dc) {
900         dc = nssDecodedPKIXCertificate_Create(NULL, &c->encoding);
901         if (!dc) {
902             goto loser;
903         }
904         cc = (CERTCertificate *)dc->data;
905         PORT_Assert(cc); /* software error */
906         if (!cc) {
907             nssDecodedPKIXCertificate_Destroy(dc);
908             nss_SetError(NSS_ERROR_INTERNAL_ERROR);
909             goto loser;
910         }
911         PORT_Assert(!c->decoding);
912         if (!c->decoding) {
913             c->decoding = dc;
914         } else {
915             /* this should never happen. Fail. */
916             nssDecodedPKIXCertificate_Destroy(dc);
917             nss_SetError(NSS_ERROR_INTERNAL_ERROR);
918             goto loser;
919         }
920     }
921     cc = (CERTCertificate *)dc->data;
922     PORT_Assert(cc);
923     if (!cc) {
924         nss_SetError(NSS_ERROR_INTERNAL_ERROR);
925         goto loser;
926     }
927     CERT_LockCertTempPerm(cc);
928     NSSCertificate *nssCert = cc->nssCertificate;
929     CERT_UnlockCertTempPerm(cc);
930     if (!nssCert || forceUpdate) {
931         fill_CERTCertificateFields(c, cc, forceUpdate);
932     } else if (CERT_GetCertTrust(cc, &certTrust) != SECSuccess) {
933         CERTCertTrust *trust;
934         if (!c->object.cryptoContext) {
935             /* If it's a perm cert, it might have been stored before the
936              * trust, so look for the trust again.
937              */
938             trust = nssTrust_GetCERTCertTrustForCert(c, cc);
939         } else {
940             /* If it's a temp cert, it might have been stored before the
941              * builtin trust module is loaded, so look for the trust
942              * again, but don't set the empty trust if it is not found.
943              */
944             NSSTrust *t = nssTrustDomain_FindTrustForCertificate(c->object.cryptoContext->td, c);
945             if (!t) {
946                 goto loser;
947             }
948             trust = cert_trust_from_stan_trust(t, cc->arena);
949             nssTrust_Destroy(t);
950             if (!trust) {
951                 goto loser;
952             }
953         }
954 
955         CERT_LockCertTrust(cc);
956         cc->trust = trust;
957         CERT_UnlockCertTrust(cc);
958     }
959 
960 loser:
961     nssPKIObject_Unlock(&c->object);
962     nssPKIObject_Destroy(&c->object);
963     return cc;
964 }
965 
966 NSS_IMPLEMENT CERTCertificate *
STAN_ForceCERTCertificateUpdate(NSSCertificate * c)967 STAN_ForceCERTCertificateUpdate(NSSCertificate *c)
968 {
969     if (c->decoding) {
970         return stan_GetCERTCertificate(c, PR_TRUE);
971     }
972     return NULL;
973 }
974 
975 NSS_IMPLEMENT CERTCertificate *
STAN_GetCERTCertificate(NSSCertificate * c)976 STAN_GetCERTCertificate(NSSCertificate *c)
977 {
978     return stan_GetCERTCertificate(c, PR_FALSE);
979 }
980 /*
981  * many callers of STAN_GetCERTCertificate() intend that
982  * the CERTCertificate returned inherits the reference to the
983  * NSSCertificate. For these callers it's convenient to have
984  * this function 'own' the reference and either return a valid
985  * CERTCertificate structure which inherits the reference or
986  * destroy the reference to NSSCertificate and returns NULL.
987  */
988 NSS_IMPLEMENT CERTCertificate *
STAN_GetCERTCertificateOrRelease(NSSCertificate * c)989 STAN_GetCERTCertificateOrRelease(NSSCertificate *c)
990 {
991     CERTCertificate *nss3cert = stan_GetCERTCertificate(c, PR_FALSE);
992     if (!nss3cert) {
993         nssCertificate_Destroy(c);
994     }
995     return nss3cert;
996 }
997 
998 static nssTrustLevel
get_stan_trust(unsigned int t,PRBool isClientAuth)999 get_stan_trust(unsigned int t, PRBool isClientAuth)
1000 {
1001     if (isClientAuth) {
1002         if (t & CERTDB_TRUSTED_CLIENT_CA) {
1003             return nssTrustLevel_TrustedDelegator;
1004         }
1005     } else {
1006         if (t & CERTDB_TRUSTED_CA || t & CERTDB_NS_TRUSTED_CA) {
1007             return nssTrustLevel_TrustedDelegator;
1008         }
1009     }
1010     if (t & CERTDB_TRUSTED) {
1011         return nssTrustLevel_Trusted;
1012     }
1013     if (t & CERTDB_TERMINAL_RECORD) {
1014         return nssTrustLevel_NotTrusted;
1015     }
1016     if (t & CERTDB_VALID_CA) {
1017         return nssTrustLevel_ValidDelegator;
1018     }
1019     return nssTrustLevel_MustVerify;
1020 }
1021 
1022 NSS_EXTERN NSSCertificate *
STAN_GetNSSCertificate(CERTCertificate * cc)1023 STAN_GetNSSCertificate(CERTCertificate *cc)
1024 {
1025     NSSCertificate *c;
1026     nssCryptokiInstance *instance;
1027     nssPKIObject *pkiob;
1028     NSSArena *arena;
1029     CERT_LockCertTempPerm(cc);
1030     c = cc->nssCertificate;
1031     CERT_UnlockCertTempPerm(cc);
1032     if (c) {
1033         return c;
1034     }
1035     /* i don't think this should happen.  but if it can, need to create
1036      * NSSCertificate from CERTCertificate values here.  */
1037     /* Yup, it can happen. */
1038     arena = NSSArena_Create();
1039     if (!arena) {
1040         return NULL;
1041     }
1042     c = nss_ZNEW(arena, NSSCertificate);
1043     if (!c) {
1044         nssArena_Destroy(arena);
1045         return NULL;
1046     }
1047     NSSITEM_FROM_SECITEM(&c->encoding, &cc->derCert);
1048     c->type = NSSCertificateType_PKIX;
1049     pkiob = nssPKIObject_Create(arena, NULL, cc->dbhandle, NULL, nssPKIMonitor);
1050     if (!pkiob) {
1051         nssArena_Destroy(arena);
1052         return NULL;
1053     }
1054     c->object = *pkiob;
1055     nssItem_Create(arena,
1056                    &c->issuer, cc->derIssuer.len, cc->derIssuer.data);
1057     nssItem_Create(arena,
1058                    &c->subject, cc->derSubject.len, cc->derSubject.data);
1059     /* CERTCertificate stores serial numbers decoded.  I need the DER
1060     * here.  sigh.
1061     */
1062     SECItem derSerial;
1063     SECStatus secrv;
1064     secrv = CERT_SerialNumberFromDERCert(&cc->derCert, &derSerial);
1065     if (secrv == SECFailure) {
1066         nssArena_Destroy(arena);
1067         return NULL;
1068     }
1069     nssItem_Create(arena, &c->serial, derSerial.len, derSerial.data);
1070     PORT_Free(derSerial.data);
1071 
1072     if (cc->emailAddr && cc->emailAddr[0]) {
1073         c->email = nssUTF8_Create(arena,
1074                                   nssStringType_PrintableString,
1075                                   (NSSUTF8 *)cc->emailAddr,
1076                                   PORT_Strlen(cc->emailAddr));
1077     }
1078     if (cc->slot) {
1079         instance = nss_ZNEW(arena, nssCryptokiInstance);
1080         if (!instance) {
1081             nssArena_Destroy(arena);
1082             return NULL;
1083         }
1084         instance->token = PK11Slot_GetNSSToken(cc->slot);
1085         if (!instance->token) {
1086             nssArena_Destroy(arena);
1087             return NULL;
1088         }
1089         instance->handle = cc->pkcs11ID;
1090         instance->isTokenObject = PR_TRUE;
1091         if (cc->nickname) {
1092             instance->label = nssUTF8_Create(arena,
1093                                              nssStringType_UTF8String,
1094                                              (NSSUTF8 *)cc->nickname,
1095                                              PORT_Strlen(cc->nickname));
1096         }
1097         nssPKIObject_AddInstance(&c->object, instance);
1098     }
1099     c->decoding = create_decoded_pkix_cert_from_nss3cert(NULL, cc);
1100     CERT_LockCertTempPerm(cc);
1101     cc->nssCertificate = c;
1102     CERT_UnlockCertTempPerm(cc);
1103     return c;
1104 }
1105 
1106 static NSSToken *
stan_GetTrustToken(NSSCertificate * c)1107 stan_GetTrustToken(
1108     NSSCertificate *c)
1109 {
1110     NSSToken *ttok = NULL;
1111     NSSToken *rtok = NULL;
1112     NSSToken *tok = NULL;
1113     nssCryptokiObject **ip;
1114     nssCryptokiObject **instances = nssPKIObject_GetInstances(&c->object);
1115     if (!instances) {
1116         return PR_FALSE;
1117     }
1118     for (ip = instances; *ip; ip++) {
1119         nssCryptokiObject *instance = *ip;
1120         nssCryptokiObject *to =
1121             nssToken_FindTrustForCertificate(instance->token, NULL,
1122                                              &c->encoding, &c->issuer, &c->serial,
1123                                              nssTokenSearchType_TokenOnly);
1124         NSSToken *ctok = instance->token;
1125         PRBool ro = PK11_IsReadOnly(ctok->pk11slot);
1126 
1127         if (to) {
1128             nssCryptokiObject_Destroy(to);
1129             ttok = ctok;
1130             if (!ro) {
1131                 break;
1132             }
1133         } else {
1134             if (!rtok && ro) {
1135                 rtok = ctok;
1136             }
1137             if (!tok && !ro) {
1138                 tok = ctok;
1139             }
1140         }
1141     }
1142     nssCryptokiObjectArray_Destroy(instances);
1143     return ttok ? ttok : (tok ? tok : rtok);
1144 }
1145 
1146 NSS_EXTERN PRStatus
STAN_ChangeCertTrust(CERTCertificate * cc,CERTCertTrust * trust)1147 STAN_ChangeCertTrust(CERTCertificate *cc, CERTCertTrust *trust)
1148 {
1149     PRStatus nssrv;
1150     NSSCertificate *c = STAN_GetNSSCertificate(cc);
1151     NSSToken *tok;
1152     NSSTrustDomain *td;
1153     NSSTrust *nssTrust;
1154     NSSArena *arena;
1155     CERTCertTrust *oldTrust;
1156     CERTCertTrust *newTrust;
1157     nssListIterator *tokens;
1158     PRBool moving_object;
1159     nssCryptokiObject *newInstance;
1160     nssPKIObject *pkiob;
1161 
1162     if (c == NULL) {
1163         return PR_FAILURE;
1164     }
1165     oldTrust = nssTrust_GetCERTCertTrustForCert(c, cc);
1166     if (oldTrust) {
1167         if (memcmp(oldTrust, trust, sizeof(CERTCertTrust)) == 0) {
1168             /* ... and the new trust is no different, done) */
1169             return PR_SUCCESS;
1170         } else {
1171             /* take over memory already allocated in cc's arena */
1172             newTrust = oldTrust;
1173         }
1174     } else {
1175         newTrust = PORT_ArenaAlloc(cc->arena, sizeof(CERTCertTrust));
1176     }
1177     memcpy(newTrust, trust, sizeof(CERTCertTrust));
1178     CERT_LockCertTrust(cc);
1179     cc->trust = newTrust;
1180     CERT_UnlockCertTrust(cc);
1181     /* Set the NSSCerticate's trust */
1182     arena = nssArena_Create();
1183     if (!arena)
1184         return PR_FAILURE;
1185     nssTrust = nss_ZNEW(arena, NSSTrust);
1186     if (!nssTrust) {
1187         nssArena_Destroy(arena);
1188         return PR_FAILURE;
1189     }
1190     pkiob = nssPKIObject_Create(arena, NULL, cc->dbhandle, NULL, nssPKILock);
1191     if (!pkiob) {
1192         nssArena_Destroy(arena);
1193         return PR_FAILURE;
1194     }
1195     nssTrust->object = *pkiob;
1196     nssTrust->certificate = c;
1197     nssTrust->serverAuth = get_stan_trust(trust->sslFlags, PR_FALSE);
1198     nssTrust->clientAuth = get_stan_trust(trust->sslFlags, PR_TRUE);
1199     nssTrust->emailProtection = get_stan_trust(trust->emailFlags, PR_FALSE);
1200     nssTrust->codeSigning = get_stan_trust(trust->objectSigningFlags, PR_FALSE);
1201     nssTrust->stepUpApproved =
1202         (PRBool)(trust->sslFlags & CERTDB_GOVT_APPROVED_CA);
1203     if (c->object.cryptoContext != NULL) {
1204         /* The cert is in a context, set the trust there */
1205         NSSCryptoContext *cctx = c->object.cryptoContext;
1206         nssrv = nssCryptoContext_ImportTrust(cctx, nssTrust);
1207         if (nssrv != PR_SUCCESS) {
1208             goto done;
1209         }
1210         if (c->object.numInstances == 0) {
1211             /* The context is the only instance, finished */
1212             goto done;
1213         }
1214     }
1215     td = STAN_GetDefaultTrustDomain();
1216     tok = stan_GetTrustToken(c);
1217     moving_object = PR_FALSE;
1218     if (tok && PK11_IsReadOnly(tok->pk11slot)) {
1219         NSSRWLock_LockRead(td->tokensLock);
1220         tokens = nssList_CreateIterator(td->tokenList);
1221         if (!tokens) {
1222             nssrv = PR_FAILURE;
1223             NSSRWLock_UnlockRead(td->tokensLock);
1224             goto done;
1225         }
1226         for (tok = (NSSToken *)nssListIterator_Start(tokens);
1227              tok != (NSSToken *)NULL;
1228              tok = (NSSToken *)nssListIterator_Next(tokens)) {
1229             if (!PK11_IsReadOnly(tok->pk11slot))
1230                 break;
1231         }
1232         nssListIterator_Finish(tokens);
1233         nssListIterator_Destroy(tokens);
1234         NSSRWLock_UnlockRead(td->tokensLock);
1235         moving_object = PR_TRUE;
1236     }
1237     if (tok) {
1238         if (moving_object) {
1239             /* this is kind of hacky.  the softoken needs the cert
1240              * object in order to store trust.  forcing it to be perm
1241              */
1242             NSSUTF8 *nickname = nssCertificate_GetNickname(c, NULL);
1243             NSSASCII7 *email = NULL;
1244 
1245             if (PK11_IsInternal(tok->pk11slot)) {
1246                 email = c->email;
1247             }
1248             newInstance = nssToken_ImportCertificate(tok, NULL,
1249                                                      NSSCertificateType_PKIX,
1250                                                      &c->id,
1251                                                      nickname,
1252                                                      &c->encoding,
1253                                                      &c->issuer,
1254                                                      &c->subject,
1255                                                      &c->serial,
1256                                                      email,
1257                                                      PR_TRUE);
1258             nss_ZFreeIf(nickname);
1259             nickname = NULL;
1260             if (!newInstance) {
1261                 nssrv = PR_FAILURE;
1262                 goto done;
1263             }
1264             nssPKIObject_AddInstance(&c->object, newInstance);
1265         }
1266         newInstance = nssToken_ImportTrust(tok, NULL, &c->encoding,
1267                                            &c->issuer, &c->serial,
1268                                            nssTrust->serverAuth,
1269                                            nssTrust->clientAuth,
1270                                            nssTrust->codeSigning,
1271                                            nssTrust->emailProtection,
1272                                            nssTrust->stepUpApproved, PR_TRUE);
1273         /* If the selected token can't handle trust, dump the trust on
1274          * the internal token */
1275         if (!newInstance && !PK11_IsInternalKeySlot(tok->pk11slot)) {
1276             PK11SlotInfo *slot = PK11_GetInternalKeySlot();
1277             NSSUTF8 *nickname = nssCertificate_GetNickname(c, NULL);
1278             NSSASCII7 *email = c->email;
1279             tok = PK11Slot_GetNSSToken(slot);
1280             PK11_FreeSlot(slot);
1281             if (!tok) {
1282                 nssrv = PR_FAILURE;
1283                 goto done;
1284             }
1285 
1286             newInstance = nssToken_ImportCertificate(tok, NULL,
1287                                                      NSSCertificateType_PKIX,
1288                                                      &c->id,
1289                                                      nickname,
1290                                                      &c->encoding,
1291                                                      &c->issuer,
1292                                                      &c->subject,
1293                                                      &c->serial,
1294                                                      email,
1295                                                      PR_TRUE);
1296             nss_ZFreeIf(nickname);
1297             nickname = NULL;
1298             if (!newInstance) {
1299                 (void)nssToken_Destroy(tok);
1300                 nssrv = PR_FAILURE;
1301                 goto done;
1302             }
1303             nssPKIObject_AddInstance(&c->object, newInstance);
1304             newInstance = nssToken_ImportTrust(tok, NULL, &c->encoding,
1305                                                &c->issuer, &c->serial,
1306                                                nssTrust->serverAuth,
1307                                                nssTrust->clientAuth,
1308                                                nssTrust->codeSigning,
1309                                                nssTrust->emailProtection,
1310                                                nssTrust->stepUpApproved, PR_TRUE);
1311             (void)nssToken_Destroy(tok);
1312         }
1313         if (newInstance) {
1314             nssCryptokiObject_Destroy(newInstance);
1315             nssrv = PR_SUCCESS;
1316         } else {
1317             nssrv = PR_FAILURE;
1318         }
1319     } else {
1320         nssrv = PR_FAILURE;
1321     }
1322 done:
1323     (void)nssTrust_Destroy(nssTrust);
1324     return nssrv;
1325 }
1326 
1327 /*
1328 ** Delete trust objects matching the given slot.
1329 ** Returns error if a device fails to delete.
1330 **
1331 ** This function has the side effect of moving the
1332 ** surviving entries to the front of the object list
1333 ** and nullifying the rest.
1334 */
1335 static PRStatus
DeleteCertTrustMatchingSlot(PK11SlotInfo * pk11slot,nssPKIObject * tObject)1336 DeleteCertTrustMatchingSlot(PK11SlotInfo *pk11slot, nssPKIObject *tObject)
1337 {
1338     int numNotDestroyed = 0; /* the ones skipped plus the failures */
1339     int failureCount = 0;    /* actual deletion failures by devices */
1340     unsigned int index;
1341 
1342     nssPKIObject_AddRef(tObject);
1343     nssPKIObject_Lock(tObject);
1344     /* Keep going even if a module fails to delete. */
1345     for (index = 0; index < tObject->numInstances; index++) {
1346         nssCryptokiObject *instance = tObject->instances[index];
1347         if (!instance) {
1348             continue;
1349         }
1350 
1351         /* ReadOnly and not matched treated the same */
1352         if (PK11_IsReadOnly(instance->token->pk11slot) ||
1353             pk11slot != instance->token->pk11slot) {
1354             tObject->instances[numNotDestroyed++] = instance;
1355             continue;
1356         }
1357 
1358         /* Here we have found a matching one */
1359         tObject->instances[index] = NULL;
1360         if (nssToken_DeleteStoredObject(instance) == PR_SUCCESS) {
1361             nssCryptokiObject_Destroy(instance);
1362         } else {
1363             tObject->instances[numNotDestroyed++] = instance;
1364             failureCount++;
1365         }
1366     }
1367     if (numNotDestroyed == 0) {
1368         nss_ZFreeIf(tObject->instances);
1369         tObject->numInstances = 0;
1370     } else {
1371         tObject->numInstances = numNotDestroyed;
1372     }
1373 
1374     nssPKIObject_Unlock(tObject);
1375     nssPKIObject_Destroy(tObject);
1376 
1377     return failureCount == 0 ? PR_SUCCESS : PR_FAILURE;
1378 }
1379 
1380 /*
1381 ** Delete trust objects matching the slot of the given certificate.
1382 ** Returns an error if any device fails to delete.
1383 */
1384 NSS_EXTERN PRStatus
STAN_DeleteCertTrustMatchingSlot(NSSCertificate * c)1385 STAN_DeleteCertTrustMatchingSlot(NSSCertificate *c)
1386 {
1387     PRStatus nssrv = PR_SUCCESS;
1388 
1389     unsigned int i;
1390     nssPKIObject *tobject = NULL;
1391     nssPKIObject *cobject = &c->object;
1392 
1393     NSSTrustDomain *td = STAN_GetDefaultTrustDomain();
1394     NSSTrust *nssTrust = nssTrustDomain_FindTrustForCertificate(td, c);
1395     if (!nssTrust) {
1396         return PR_FAILURE;
1397     }
1398 
1399     tobject = &nssTrust->object;
1400 
1401     /* Iterate through the cert and trust object instances looking for
1402      * those with matching pk11 slots to delete. Even if some device
1403      * can't delete we keep going. Keeping a status variable for the
1404      * loop so that once it's failed the other gets set.
1405      */
1406     NSSRWLock_LockRead(td->tokensLock);
1407     nssPKIObject_AddRef(cobject);
1408     nssPKIObject_Lock(cobject);
1409     for (i = 0; i < cobject->numInstances; i++) {
1410         nssCryptokiObject *cInstance = cobject->instances[i];
1411         if (cInstance && !PK11_IsReadOnly(cInstance->token->pk11slot)) {
1412             PRStatus status;
1413             if (!tobject->numInstances || !tobject->instances)
1414                 continue;
1415             status = DeleteCertTrustMatchingSlot(cInstance->token->pk11slot, tobject);
1416             if (status == PR_FAILURE) {
1417                 /* set the outer one but keep going */
1418                 nssrv = PR_FAILURE;
1419             }
1420         }
1421     }
1422     nssTrust_Destroy(nssTrust);
1423     nssPKIObject_Unlock(cobject);
1424     nssPKIObject_Destroy(cobject);
1425     NSSRWLock_UnlockRead(td->tokensLock);
1426     return nssrv;
1427 }
1428 
1429 /* CERT_TraversePermCertsForSubject */
1430 NSS_IMPLEMENT PRStatus
nssTrustDomain_TraverseCertificatesBySubject(NSSTrustDomain * td,NSSDER * subject,PRStatus (* callback)(NSSCertificate * c,void * arg),void * arg)1431 nssTrustDomain_TraverseCertificatesBySubject(
1432     NSSTrustDomain *td,
1433     NSSDER *subject,
1434     PRStatus (*callback)(NSSCertificate *c, void *arg),
1435     void *arg)
1436 {
1437     PRStatus nssrv = PR_SUCCESS;
1438     NSSArena *tmpArena;
1439     NSSCertificate **subjectCerts;
1440     NSSCertificate *c;
1441     PRIntn i;
1442     tmpArena = NSSArena_Create();
1443     if (!tmpArena) {
1444         return PR_FAILURE;
1445     }
1446     subjectCerts = NSSTrustDomain_FindCertificatesBySubject(td, subject, NULL,
1447                                                             0, tmpArena);
1448     if (subjectCerts) {
1449         for (i = 0, c = subjectCerts[i]; c; i++) {
1450             nssrv = callback(c, arg);
1451             if (nssrv != PR_SUCCESS)
1452                 break;
1453         }
1454     }
1455     nssArena_Destroy(tmpArena);
1456     return nssrv;
1457 }
1458 
1459 /* CERT_TraversePermCertsForNickname */
1460 NSS_IMPLEMENT PRStatus
nssTrustDomain_TraverseCertificatesByNickname(NSSTrustDomain * td,NSSUTF8 * nickname,PRStatus (* callback)(NSSCertificate * c,void * arg),void * arg)1461 nssTrustDomain_TraverseCertificatesByNickname(
1462     NSSTrustDomain *td,
1463     NSSUTF8 *nickname,
1464     PRStatus (*callback)(NSSCertificate *c, void *arg),
1465     void *arg)
1466 {
1467     PRStatus nssrv = PR_SUCCESS;
1468     NSSArena *tmpArena;
1469     NSSCertificate **nickCerts;
1470     NSSCertificate *c;
1471     PRIntn i;
1472     tmpArena = NSSArena_Create();
1473     if (!tmpArena) {
1474         return PR_FAILURE;
1475     }
1476     nickCerts = NSSTrustDomain_FindCertificatesByNickname(td, nickname, NULL,
1477                                                           0, tmpArena);
1478     if (nickCerts) {
1479         for (i = 0, c = nickCerts[i]; c; i++) {
1480             nssrv = callback(c, arg);
1481             if (nssrv != PR_SUCCESS)
1482                 break;
1483         }
1484     }
1485     nssArena_Destroy(tmpArena);
1486     return nssrv;
1487 }
1488 
1489 static void
cert_dump_iter(const void * k,void * v,void * a)1490 cert_dump_iter(const void *k, void *v, void *a)
1491 {
1492     NSSCertificate *c = (NSSCertificate *)k;
1493     CERTCertificate *cert = STAN_GetCERTCertificate(c);
1494     printf("[%2d] \"%s\"\n", c->object.refCount, cert->subjectName);
1495 }
1496 
1497 void
nss_DumpCertificateCacheInfo()1498 nss_DumpCertificateCacheInfo()
1499 {
1500     NSSTrustDomain *td;
1501     NSSCryptoContext *cc;
1502     td = STAN_GetDefaultTrustDomain();
1503     cc = STAN_GetDefaultCryptoContext();
1504     printf("\n\nCertificates in the cache:\n");
1505     nssTrustDomain_DumpCacheInfo(td, cert_dump_iter, NULL);
1506     printf("\n\nCertificates in the temporary store:\n");
1507     if (cc->certStore) {
1508         nssCertificateStore_DumpStoreInfo(cc->certStore, cert_dump_iter, NULL);
1509     }
1510 }
1511