1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
14 * The Original Code is the Netscape security libraries.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
19 * the Initial Developer. All Rights Reserved.
23 * Alternatively, the contents of this file may be used under the terms of
24 * either the GNU General Public License Version 2 or later (the "GPL"), or
25 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26 * in which case the provisions of the GPL or the LGPL are applicable instead
27 * of those above. If you wish to allow use of your version of this file only
28 * under the terms of either the GPL or the LGPL, and not to allow others to
29 * use your version of this file under the terms of the MPL, indicate your
30 * decision by deleting the provisions above and replace them with the notice
31 * and other provisions required by the GPL or the LGPL. If you do not delete
32 * the provisions above, a recipient may use your version of this file under
33 * the terms of any one of the MPL, the GPL or the LGPL.
35 * ***** END LICENSE BLOCK ***** */
38 static const char CVS_ID
[] = "@(#) $RCSfile: pki3hack.c,v $ $Revision: 1.96 $ $Date: 2008/08/09 01:26:05 $";
42 * Hacks to integrate NSS 3.4 and NSS 4.0 certificates.
63 #endif /* DEVNSS3HACK_H */
67 #endif /* PKINSS3HACK_H */
79 NSSTrustDomain
*g_default_trust_domain
= NULL
;
81 NSSCryptoContext
*g_default_crypto_context
= NULL
;
84 STAN_GetDefaultTrustDomain()
86 return g_default_trust_domain
;
90 STAN_GetDefaultCryptoContext()
92 return g_default_crypto_context
;
95 extern const NSSError NSS_ERROR_ALREADY_INITIALIZED
;
96 extern const NSSError NSS_ERROR_INTERNAL_ERROR
;
98 NSS_IMPLEMENT PRStatus
99 STAN_InitTokenForSlotInfo(NSSTrustDomain
*td
, PK11SlotInfo
*slot
)
103 td
= g_default_trust_domain
;
105 token
= nssToken_CreateFromPK11SlotInfo(td
, slot
);
106 PK11Slot_SetNSSToken(slot
, token
);
107 /* Don't add non-existent token to TD's token list */
109 NSSRWLock_LockWrite(td
->tokensLock
);
110 nssList_Add(td
->tokenList
, token
);
111 NSSRWLock_UnlockWrite(td
->tokensLock
);
116 NSS_IMPLEMENT PRStatus
117 STAN_ResetTokenInterator(NSSTrustDomain
*td
)
120 td
= g_default_trust_domain
;
122 NSSRWLock_LockWrite(td
->tokensLock
);
123 nssListIterator_Destroy(td
->tokens
);
124 td
->tokens
= nssList_CreateIterator(td
->tokenList
);
125 NSSRWLock_UnlockWrite(td
->tokensLock
);
129 NSS_IMPLEMENT PRStatus
130 STAN_LoadDefaultNSS3TrustDomain (
135 SECMODModuleList
*mlp
;
136 SECMODListLock
*moduleLock
= SECMOD_GetDefaultModuleListLock();
139 if (g_default_trust_domain
|| g_default_crypto_context
) {
140 /* Stan is already initialized or a previous shutdown failed. */
141 nss_SetError(NSS_ERROR_ALREADY_INITIALIZED
);
144 td
= NSSTrustDomain_Create(NULL
, NULL
, NULL
, NULL
);
149 * Deadlock warning: we should never acquire the moduleLock while
150 * we hold the tokensLock. We can use the NSSRWLock Rank feature to
151 * guarrentee this. tokensLock have a higher rank than module lock.
153 td
->tokenList
= nssList_Create(td
->arena
, PR_TRUE
);
154 if (!td
->tokenList
) {
157 SECMOD_GetReadLock(moduleLock
);
158 NSSRWLock_LockWrite(td
->tokensLock
);
159 for (mlp
= SECMOD_GetDefaultModuleList(); mlp
!= NULL
; mlp
=mlp
->next
) {
160 for (i
=0; i
< mlp
->module
->slotCount
; i
++) {
161 STAN_InitTokenForSlotInfo(td
, mlp
->module
->slots
[i
]);
164 td
->tokens
= nssList_CreateIterator(td
->tokenList
);
165 NSSRWLock_UnlockWrite(td
->tokensLock
);
166 SECMOD_ReleaseReadLock(moduleLock
);
170 g_default_crypto_context
= NSSTrustDomain_CreateCryptoContext(td
, NULL
);
171 if (!g_default_crypto_context
) {
174 g_default_trust_domain
= td
;
178 NSSTrustDomain_Destroy(td
);
183 * must be called holding the ModuleListLock (either read or write).
185 NSS_IMPLEMENT SECStatus
186 STAN_AddModuleToDefaultTrustDomain (
192 td
= STAN_GetDefaultTrustDomain();
193 for (i
=0; i
<module
->slotCount
; i
++) {
194 STAN_InitTokenForSlotInfo(td
, module
->slots
[i
]);
196 STAN_ResetTokenInterator(td
);
201 * must be called holding the ModuleListLock (either read or write).
203 NSS_IMPLEMENT SECStatus
204 STAN_RemoveModuleFromDefaultTrustDomain (
211 td
= STAN_GetDefaultTrustDomain();
212 NSSRWLock_LockWrite(td
->tokensLock
);
213 for (i
=0; i
<module
->slotCount
; i
++) {
214 token
= PK11Slot_GetNSSToken(module
->slots
[i
]);
216 nssToken_NotifyCertsNotVisible(token
);
217 nssList_Remove(td
->tokenList
, token
);
218 PK11Slot_SetNSSToken(module
->slots
[i
], NULL
);
219 nssToken_Destroy(token
);
222 nssListIterator_Destroy(td
->tokens
);
223 td
->tokens
= nssList_CreateIterator(td
->tokenList
);
224 NSSRWLock_UnlockWrite(td
->tokensLock
);
228 NSS_IMPLEMENT PRStatus
231 PRStatus status
= PR_SUCCESS
;
232 if (g_default_trust_domain
) {
233 if (NSSTrustDomain_Destroy(g_default_trust_domain
) == PR_SUCCESS
) {
234 g_default_trust_domain
= NULL
;
239 if (g_default_crypto_context
) {
240 if (NSSCryptoContext_Destroy(g_default_crypto_context
) == PR_SUCCESS
) {
241 g_default_crypto_context
= NULL
;
249 /* this function should not be a hack; it will be needed in 4.0 (rename) */
250 NSS_IMPLEMENT NSSItem
*
251 STAN_GetCertIdentifierFromDER(NSSArena
*arenaOpt
, NSSDER
*der
)
255 SECItem secKey
= { 0 };
259 SECITEM_FROM_NSSITEM(&secDER
, der
);
261 /* nss3 call uses nss3 arena's */
262 arena
= PORT_NewArena(256);
266 secrv
= CERT_KeyFromDERCert(arena
, &secDER
, &secKey
);
267 if (secrv
!= SECSuccess
) {
270 rvKey
= nssItem_Create(arenaOpt
, NULL
, secKey
.len
, (void *)secKey
.data
);
271 PORT_FreeArena(arena
,PR_FALSE
);
275 NSS_IMPLEMENT PRStatus
276 nssPKIX509_GetIssuerAndSerialFromDER(NSSDER
*der
, NSSArena
*arena
,
277 NSSDER
*issuer
, NSSDER
*serial
)
281 SECItem derIssuer
= { 0 };
282 SECItem derSerial
= { 0 };
283 SECITEM_FROM_NSSITEM(&derCert
, der
);
284 secrv
= CERT_SerialNumberFromDERCert(&derCert
, &derSerial
);
285 if (secrv
!= SECSuccess
) {
288 (void)nssItem_Create(arena
, serial
, derSerial
.len
, derSerial
.data
);
289 secrv
= CERT_IssuerNameFromDERCert(&derCert
, &derIssuer
);
290 if (secrv
!= SECSuccess
) {
291 PORT_Free(derSerial
.data
);
294 (void)nssItem_Create(arena
, issuer
, derIssuer
.len
, derIssuer
.data
);
295 PORT_Free(derSerial
.data
);
296 PORT_Free(derIssuer
.data
);
301 nss3certificate_getIdentifier(nssDecodedCert
*dc
)
304 CERTCertificate
*c
= (CERTCertificate
*)dc
->data
;
305 rvID
= nssItem_Create(NULL
, NULL
, c
->certKey
.len
, c
->certKey
.data
);
310 nss3certificate_getIssuerIdentifier(nssDecodedCert
*dc
)
312 CERTCertificate
*c
= (CERTCertificate
*)dc
->data
;
313 return (void *)c
->authKeyID
;
316 static nssCertIDMatch
317 nss3certificate_matchIdentifier(nssDecodedCert
*dc
, void *id
)
319 CERTCertificate
*c
= (CERTCertificate
*)dc
->data
;
320 CERTAuthKeyID
*authKeyID
= (CERTAuthKeyID
*)id
;
322 nssCertIDMatch match
= nssCertIDMatch_Unknown
;
325 if (authKeyID
->keyID
.len
> 0 &&
326 CERT_FindSubjectKeyIDExtension(c
, &skid
) == SECSuccess
) {
328 skiEqual
= SECITEM_ItemsAreEqual(&authKeyID
->keyID
, &skid
);
329 PORT_Free(skid
.data
);
331 /* change the state to positive match, but keep going */
332 match
= nssCertIDMatch_Yes
;
334 /* exit immediately on failure */
335 return nssCertIDMatch_No
;
339 /* issuer/serial (treated as pair) */
340 if (authKeyID
->authCertIssuer
) {
341 SECItem
*caName
= NULL
;
342 SECItem
*caSN
= &authKeyID
->authCertSerialNumber
;
344 caName
= (SECItem
*)CERT_GetGeneralNameByType(
345 authKeyID
->authCertIssuer
,
346 certDirectoryName
, PR_TRUE
);
347 if (caName
!= NULL
&&
348 SECITEM_ItemsAreEqual(&c
->derIssuer
, caName
) &&
349 SECITEM_ItemsAreEqual(&c
->serialNumber
, caSN
))
351 match
= nssCertIDMatch_Yes
;
353 match
= nssCertIDMatch_Unknown
;
360 nss3certificate_isValidIssuer(nssDecodedCert
*dc
)
362 CERTCertificate
*c
= (CERTCertificate
*)dc
->data
;
364 return CERT_IsCACert(c
, &ignore
);
368 nss3certificate_getUsage(nssDecodedCert
*dc
)
370 /* CERTCertificate *c = (CERTCertificate *)dc->data; */
375 nss3certificate_isValidAtTime(nssDecodedCert
*dc
, NSSTime
*time
)
377 SECCertTimeValidity validity
;
378 CERTCertificate
*c
= (CERTCertificate
*)dc
->data
;
379 validity
= CERT_CheckCertValidTimes(c
, NSSTime_GetPRTime(time
), PR_TRUE
);
380 if (validity
== secCertTimeValid
) {
387 nss3certificate_isNewerThan(nssDecodedCert
*dc
, nssDecodedCert
*cmpdc
)
389 /* I know this isn't right, but this is glue code anyway */
390 if (cmpdc
->type
== dc
->type
) {
391 CERTCertificate
*certa
= (CERTCertificate
*)dc
->data
;
392 CERTCertificate
*certb
= (CERTCertificate
*)cmpdc
->data
;
393 return CERT_IsNewer(certa
, certb
);
398 /* CERT_FilterCertListByUsage */
400 nss3certificate_matchUsage(nssDecodedCert
*dc
, const NSSUsage
*usage
)
403 unsigned int requiredKeyUsage
= 0;
404 unsigned int requiredCertType
= 0;
409 /* This is for NSS 3.3 functions that do not specify a usage */
410 if (usage
->anyUsage
) {
413 ca
= usage
->nss3lookingForCA
;
414 secrv
= CERT_KeyUsageAndTypeForCertUsage(usage
->nss3usage
, ca
,
417 if (secrv
!= SECSuccess
) {
420 cc
= (CERTCertificate
*)dc
->data
;
421 secrv
= CERT_CheckKeyUsage(cc
, requiredKeyUsage
);
422 match
= (PRBool
)(secrv
== SECSuccess
);
424 unsigned int certType
= 0;
426 (void)CERT_IsCACert(cc
, &certType
);
428 certType
= cc
->nsCertType
;
430 if (!(certType
& requiredCertType
)) {
438 nss3certificate_getEmailAddress(nssDecodedCert
*dc
)
440 CERTCertificate
*cc
= (CERTCertificate
*)dc
->data
;
441 return (cc
&& cc
->emailAddr
&& cc
->emailAddr
[0])
442 ? (NSSASCII7
*)cc
->emailAddr
: NULL
;
446 nss3certificate_getDERSerialNumber(nssDecodedCert
*dc
,
447 NSSDER
*serial
, NSSArena
*arena
)
449 CERTCertificate
*cc
= (CERTCertificate
*)dc
->data
;
450 SECItem derSerial
= { 0 };
452 secrv
= CERT_SerialNumberFromDERCert(&cc
->derCert
, &derSerial
);
453 if (secrv
== SECSuccess
) {
454 (void)nssItem_Create(arena
, serial
, derSerial
.len
, derSerial
.data
);
455 PORT_Free(derSerial
.data
);
461 /* Returns NULL if "encoding" cannot be decoded. */
462 NSS_IMPLEMENT nssDecodedCert
*
463 nssDecodedPKIXCertificate_Create (
468 nssDecodedCert
*rvDC
= NULL
;
469 CERTCertificate
*cert
;
472 SECITEM_FROM_NSSITEM(&secDER
, encoding
);
473 cert
= CERT_DecodeDERCertificate(&secDER
, PR_TRUE
, NULL
);
475 rvDC
= nss_ZNEW(arenaOpt
, nssDecodedCert
);
477 rvDC
->type
= NSSCertificateType_PKIX
;
478 rvDC
->data
= (void *)cert
;
479 rvDC
->getIdentifier
= nss3certificate_getIdentifier
;
480 rvDC
->getIssuerIdentifier
= nss3certificate_getIssuerIdentifier
;
481 rvDC
->matchIdentifier
= nss3certificate_matchIdentifier
;
482 rvDC
->isValidIssuer
= nss3certificate_isValidIssuer
;
483 rvDC
->getUsage
= nss3certificate_getUsage
;
484 rvDC
->isValidAtTime
= nss3certificate_isValidAtTime
;
485 rvDC
->isNewerThan
= nss3certificate_isNewerThan
;
486 rvDC
->matchUsage
= nss3certificate_matchUsage
;
487 rvDC
->getEmailAddress
= nss3certificate_getEmailAddress
;
488 rvDC
->getDERSerialNumber
= nss3certificate_getDERSerialNumber
;
490 CERT_DestroyCertificate(cert
);
496 static nssDecodedCert
*
497 create_decoded_pkix_cert_from_nss3cert (
502 nssDecodedCert
*rvDC
= nss_ZNEW(arenaOpt
, nssDecodedCert
);
504 rvDC
->type
= NSSCertificateType_PKIX
;
505 rvDC
->data
= (void *)cc
;
506 rvDC
->getIdentifier
= nss3certificate_getIdentifier
;
507 rvDC
->getIssuerIdentifier
= nss3certificate_getIssuerIdentifier
;
508 rvDC
->matchIdentifier
= nss3certificate_matchIdentifier
;
509 rvDC
->isValidIssuer
= nss3certificate_isValidIssuer
;
510 rvDC
->getUsage
= nss3certificate_getUsage
;
511 rvDC
->isValidAtTime
= nss3certificate_isValidAtTime
;
512 rvDC
->isNewerThan
= nss3certificate_isNewerThan
;
513 rvDC
->matchUsage
= nss3certificate_matchUsage
;
514 rvDC
->getEmailAddress
= nss3certificate_getEmailAddress
;
519 NSS_IMPLEMENT PRStatus
520 nssDecodedPKIXCertificate_Destroy (
524 CERTCertificate
*cert
= (CERTCertificate
*)dc
->data
;
526 /* The decoder may only be half initialized (the case where we find we
527 * could not decode the certificate). In this case, there is not cert to
528 * free, just free the dc structure. */
530 PRBool freeSlot
= cert
->ownSlot
;
531 PK11SlotInfo
*slot
= cert
->slot
;
532 PRArenaPool
*arena
= cert
->arena
;
533 /* zero cert before freeing. Any stale references to this cert
534 * after this point will probably cause an exception. */
535 PORT_Memset(cert
, 0, sizeof *cert
);
536 /* free the arena that contains the cert. */
537 PORT_FreeArena(arena
, PR_FALSE
);
538 if (slot
&& freeSlot
) {
546 /* see pk11cert.c:pk11_HandleTrustObject */
548 get_nss3trust_from_nss4trust(CK_TRUST t
)
551 if (t
== nssTrustLevel_Trusted
) {
552 rt
|= CERTDB_VALID_PEER
| CERTDB_TRUSTED
;
554 if (t
== nssTrustLevel_TrustedDelegator
) {
555 rt
|= CERTDB_VALID_CA
| CERTDB_TRUSTED_CA
/*| CERTDB_NS_TRUSTED_CA*/;
557 if (t
== nssTrustLevel_Valid
) {
558 rt
|= CERTDB_VALID_PEER
;
560 if (t
== nssTrustLevel_ValidDelegator
) {
561 rt
|= CERTDB_VALID_CA
;
566 static CERTCertTrust
*
567 cert_trust_from_stan_trust(NSSTrust
*t
, PRArenaPool
*arena
)
569 CERTCertTrust
*rvTrust
;
574 rvTrust
= PORT_ArenaAlloc(arena
, sizeof(CERTCertTrust
));
575 if (!rvTrust
) return NULL
;
576 rvTrust
->sslFlags
= get_nss3trust_from_nss4trust(t
->serverAuth
);
577 client
= get_nss3trust_from_nss4trust(t
->clientAuth
);
578 if (client
& (CERTDB_TRUSTED_CA
|CERTDB_NS_TRUSTED_CA
)) {
579 client
&= ~(CERTDB_TRUSTED_CA
|CERTDB_NS_TRUSTED_CA
);
580 rvTrust
->sslFlags
|= CERTDB_TRUSTED_CLIENT_CA
;
582 rvTrust
->sslFlags
|= client
;
583 rvTrust
->emailFlags
= get_nss3trust_from_nss4trust(t
->emailProtection
);
584 rvTrust
->objectSigningFlags
= get_nss3trust_from_nss4trust(t
->codeSigning
);
585 /* The cert is a valid step-up cert (in addition to/lieu of trust above */
586 if (t
->stepUpApproved
) {
587 rvTrust
->sslFlags
|= CERTDB_GOVT_APPROVED_CA
;
593 nssTrust_GetCERTCertTrustForCert(NSSCertificate
*c
, CERTCertificate
*cc
)
595 CERTCertTrust
*rvTrust
= NULL
;
596 NSSTrustDomain
*td
= STAN_GetDefaultTrustDomain();
598 t
= nssTrustDomain_FindTrustForCertificate(td
, c
);
600 rvTrust
= cert_trust_from_stan_trust(t
, cc
->arena
);
607 rvTrust
= PORT_ArenaAlloc(cc
->arena
, sizeof(CERTCertTrust
));
611 memset(rvTrust
, 0, sizeof(*rvTrust
));
613 if (NSSCertificate_IsPrivateKeyAvailable(c
, NULL
, NULL
)) {
614 rvTrust
->sslFlags
|= CERTDB_USER
;
615 rvTrust
->emailFlags
|= CERTDB_USER
;
616 rvTrust
->objectSigningFlags
|= CERTDB_USER
;
621 static nssCryptokiInstance
*
622 get_cert_instance(NSSCertificate
*c
)
624 nssCryptokiObject
*instance
, **ci
;
625 nssCryptokiObject
**instances
= nssPKIObject_GetInstances(&c
->object
);
630 for (ci
= instances
; *ci
; ci
++) {
632 instance
= nssCryptokiObject_Clone(*ci
);
634 /* This only really works for two instances... But 3.4 can't
635 * handle more anyway. The logic is, if there are multiple
636 * instances, prefer the one that is not internal (e.g., on
639 if (PK11_IsInternal(instance
->token
->pk11slot
)) {
640 nssCryptokiObject_Destroy(instance
);
641 instance
= nssCryptokiObject_Clone(*ci
);
645 nssCryptokiObjectArray_Destroy(instances
);
650 STAN_GetCERTCertificateNameForInstance (
651 PLArenaPool
*arenaOpt
,
653 nssCryptokiInstance
*instance
656 NSSCryptoContext
*context
= c
->object
.cryptoContext
;
658 int nicklen
, tokenlen
, len
;
659 NSSUTF8
*tokenName
= NULL
;
660 NSSUTF8
*stanNick
= NULL
;
661 char *nickname
= NULL
;
665 stanNick
= instance
->label
;
666 } else if (context
) {
667 stanNick
= c
->object
.tempName
;
670 /* fill other fields needed by NSS3 functions using CERTCertificate */
671 if (instance
&& (!PK11_IsInternal(instance
->token
->pk11slot
) ||
672 PORT_Strchr(stanNick
, ':') != NULL
) ) {
673 tokenName
= nssToken_GetName(instance
->token
);
674 tokenlen
= nssUTF8_Size(tokenName
, &nssrv
);
676 /* don't use token name for internal slot; 3.3 didn't */
679 nicklen
= nssUTF8_Size(stanNick
, &nssrv
);
680 len
= tokenlen
+ nicklen
;
682 nickname
= PORT_ArenaAlloc(arenaOpt
, len
);
684 nickname
= PORT_Alloc(len
);
688 memcpy(nick
, tokenName
, tokenlen
-1);
692 memcpy(nick
, stanNick
, nicklen
-1);
693 nickname
[len
-1] = '\0';
699 STAN_GetCERTCertificateName(PLArenaPool
*arenaOpt
, NSSCertificate
*c
)
702 nssCryptokiInstance
*instance
= get_cert_instance(c
);
703 /* It's OK to call this function, even if instance is NULL */
704 result
= STAN_GetCERTCertificateNameForInstance(arenaOpt
, c
, instance
);
706 nssCryptokiObject_Destroy(instance
);
711 fill_CERTCertificateFields(NSSCertificate
*c
, CERTCertificate
*cc
, PRBool forced
)
713 CERTCertTrust
* trust
= NULL
;
715 NSSCryptoContext
*context
= c
->object
.cryptoContext
;
716 nssCryptokiInstance
*instance
;
717 NSSUTF8
*stanNick
= NULL
;
719 /* We are holding the base class object's lock on entry of this function
720 * This lock protects writes to fields of the CERTCertificate .
721 * It is also needed by some functions to compute values such as trust.
723 instance
= get_cert_instance(c
);
726 stanNick
= instance
->label
;
727 } else if (context
) {
728 stanNick
= c
->object
.tempName
;
730 /* fill other fields needed by NSS3 functions using CERTCertificate */
731 if ((!cc
->nickname
&& stanNick
) || forced
) {
733 int nicklen
, tokenlen
, len
;
734 NSSUTF8
*tokenName
= NULL
;
737 (!PK11_IsInternal(instance
->token
->pk11slot
) ||
738 (stanNick
&& PORT_Strchr(stanNick
, ':') != NULL
))) {
739 tokenName
= nssToken_GetName(instance
->token
);
740 tokenlen
= nssUTF8_Size(tokenName
, &nssrv
);
742 /* don't use token name for internal slot; 3.3 didn't */
746 nicklen
= nssUTF8_Size(stanNick
, &nssrv
);
747 len
= tokenlen
+ nicklen
;
748 nick
= PORT_ArenaAlloc(cc
->arena
, len
);
750 memcpy(nick
, tokenName
, tokenlen
-1);
751 nick
[tokenlen
-1] = ':';
752 memcpy(nick
+tokenlen
, stanNick
, nicklen
-1);
754 memcpy(nick
, stanNick
, nicklen
-1);
764 nssTrust
= nssCryptoContext_FindTrustForCertificate(context
, c
);
766 trust
= cert_trust_from_stan_trust(nssTrust
, cc
->arena
);
768 /* we should destroy cc->trust before replacing it, but it's
769 allocated in cc->arena, so memory growth will occur on each
773 nssTrust_Destroy(nssTrust
);
775 } else if (instance
) {
777 if (cc
->slot
!= instance
->token
->pk11slot
) {
779 PK11_FreeSlot(cc
->slot
);
781 cc
->slot
= PK11_ReferenceSlot(instance
->token
->pk11slot
);
783 cc
->ownSlot
= PR_TRUE
;
785 cc
->pkcs11ID
= instance
->handle
;
787 trust
= nssTrust_GetCERTCertTrustForCert(c
, cc
);
789 /* we should destroy cc->trust before replacing it, but it's
790 allocated in cc->arena, so memory growth will occur on each
794 nssCryptokiObject_Destroy(instance
);
796 /* database handle is now the trust domain */
797 cc
->dbhandle
= c
->object
.trustDomain
;
799 /* istemp and isperm are supported in NSS 3.4 */
800 cc
->istemp
= PR_FALSE
; /* CERT_NewTemp will override this */
801 cc
->isperm
= PR_TRUE
; /* by default */
803 cc
->nssCertificate
= c
;
805 /* force the cert type to be recomputed to include trust info */
806 PRUint32 nsCertType
= cert_ComputeCertType(cc
);
808 /* Assert that it is safe to cast &cc->nsCertType to "PRInt32 *" */
809 PORT_Assert(sizeof(cc
->nsCertType
) == sizeof(PRInt32
));
810 PR_AtomicSet((PRInt32
*)&cc
->nsCertType
, nsCertType
);
814 static CERTCertificate
*
815 stan_GetCERTCertificate(NSSCertificate
*c
, PRBool forceUpdate
)
817 nssDecodedCert
*dc
= NULL
;
818 CERTCertificate
*cc
= NULL
;
820 nssPKIObject_Lock(&c
->object
);
824 dc
= nssDecodedPKIXCertificate_Create(NULL
, &c
->encoding
);
828 cc
= (CERTCertificate
*)dc
->data
;
829 PORT_Assert(cc
); /* software error */
831 nssDecodedPKIXCertificate_Destroy(dc
);
832 nss_SetError(NSS_ERROR_INTERNAL_ERROR
);
835 PORT_Assert(!c
->decoding
);
839 /* this should never happen. Fail. */
840 nssDecodedPKIXCertificate_Destroy(dc
);
841 nss_SetError(NSS_ERROR_INTERNAL_ERROR
);
845 cc
= (CERTCertificate
*)dc
->data
;
848 nss_SetError(NSS_ERROR_INTERNAL_ERROR
);
851 if (!cc
->nssCertificate
|| forceUpdate
) {
852 fill_CERTCertificateFields(c
, cc
, forceUpdate
);
853 } else if (!cc
->trust
&& !c
->object
.cryptoContext
) {
854 /* if it's a perm cert, it might have been stored before the
855 * trust, so look for the trust again. But a temp cert can be
858 CERTCertTrust
* trust
= NULL
;
859 trust
= nssTrust_GetCERTCertTrustForCert(c
, cc
);
864 nssPKIObject_Unlock(&c
->object
);
868 NSS_IMPLEMENT CERTCertificate
*
869 STAN_ForceCERTCertificateUpdate(NSSCertificate
*c
)
872 return stan_GetCERTCertificate(c
, PR_TRUE
);
877 NSS_IMPLEMENT CERTCertificate
*
878 STAN_GetCERTCertificate(NSSCertificate
*c
)
880 return stan_GetCERTCertificate(c
, PR_FALSE
);
883 * many callers of STAN_GetCERTCertificate() intend that
884 * the CERTCertificate returned inherits the reference to the
885 * NSSCertificate. For these callers it's convenient to have
886 * this function 'own' the reference and either return a valid
887 * CERTCertificate structure which inherits the reference or
888 * destroy the reference to NSSCertificate and returns NULL.
890 NSS_IMPLEMENT CERTCertificate
*
891 STAN_GetCERTCertificateOrRelease(NSSCertificate
*c
)
893 CERTCertificate
*nss3cert
= stan_GetCERTCertificate(c
, PR_FALSE
);
895 nssCertificate_Destroy(c
);
901 get_stan_trust(unsigned int t
, PRBool isClientAuth
)
904 if (t
& CERTDB_TRUSTED_CLIENT_CA
) {
905 return nssTrustLevel_TrustedDelegator
;
908 if (t
& CERTDB_TRUSTED_CA
|| t
& CERTDB_NS_TRUSTED_CA
) {
909 return nssTrustLevel_TrustedDelegator
;
912 if (t
& CERTDB_TRUSTED
) {
913 return nssTrustLevel_Trusted
;
915 if (t
& CERTDB_VALID_CA
) {
916 return nssTrustLevel_ValidDelegator
;
918 if (t
& CERTDB_VALID_PEER
) {
919 return nssTrustLevel_Valid
;
921 return nssTrustLevel_NotTrusted
;
924 NSS_EXTERN NSSCertificate
*
925 STAN_GetNSSCertificate(CERTCertificate
*cc
)
928 nssCryptokiInstance
*instance
;
931 c
= cc
->nssCertificate
;
935 /* i don't think this should happen. but if it can, need to create
936 * NSSCertificate from CERTCertificate values here. */
937 /* Yup, it can happen. */
938 arena
= NSSArena_Create();
942 c
= nss_ZNEW(arena
, NSSCertificate
);
944 nssArena_Destroy(arena
);
947 NSSITEM_FROM_SECITEM(&c
->encoding
, &cc
->derCert
);
948 c
->type
= NSSCertificateType_PKIX
;
949 pkiob
= nssPKIObject_Create(arena
, NULL
, cc
->dbhandle
, NULL
, nssPKIMonitor
);
951 nssArena_Destroy(arena
);
955 nssItem_Create(arena
,
956 &c
->issuer
, cc
->derIssuer
.len
, cc
->derIssuer
.data
);
957 nssItem_Create(arena
,
958 &c
->subject
, cc
->derSubject
.len
, cc
->derSubject
.data
);
960 /* CERTCertificate stores serial numbers decoded. I need the DER
965 secrv
= CERT_SerialNumberFromDERCert(&cc
->derCert
, &derSerial
);
966 if (secrv
== SECFailure
) {
967 nssArena_Destroy(arena
);
970 nssItem_Create(arena
, &c
->serial
, derSerial
.len
, derSerial
.data
);
971 PORT_Free(derSerial
.data
);
973 if (cc
->emailAddr
&& cc
->emailAddr
[0]) {
974 c
->email
= nssUTF8_Create(arena
,
975 nssStringType_PrintableString
,
976 (NSSUTF8
*)cc
->emailAddr
,
977 PORT_Strlen(cc
->emailAddr
));
980 instance
= nss_ZNEW(arena
, nssCryptokiInstance
);
982 nssArena_Destroy(arena
);
985 instance
->token
= nssToken_AddRef(PK11Slot_GetNSSToken(cc
->slot
));
986 instance
->handle
= cc
->pkcs11ID
;
987 instance
->isTokenObject
= PR_TRUE
;
989 instance
->label
= nssUTF8_Create(arena
,
990 nssStringType_UTF8String
,
991 (NSSUTF8
*)cc
->nickname
,
992 PORT_Strlen(cc
->nickname
));
994 nssPKIObject_AddInstance(&c
->object
, instance
);
996 c
->decoding
= create_decoded_pkix_cert_from_nss3cert(NULL
, cc
);
997 cc
->nssCertificate
= c
;
1002 stan_GetTrustToken (
1006 NSSToken
*ttok
= NULL
;
1007 NSSToken
*rtok
= NULL
;
1008 NSSToken
*tok
= NULL
;
1009 nssCryptokiObject
**ip
;
1010 nssCryptokiObject
**instances
= nssPKIObject_GetInstances(&c
->object
);
1014 for (ip
= instances
; *ip
; ip
++) {
1015 nssCryptokiObject
*instance
= *ip
;
1016 nssCryptokiObject
*to
=
1017 nssToken_FindTrustForCertificate(instance
->token
, NULL
,
1018 &c
->encoding
, &c
->issuer
, &c
->serial
,
1019 nssTokenSearchType_TokenOnly
);
1020 NSSToken
*ctok
= instance
->token
;
1021 PRBool ro
= PK11_IsReadOnly(ctok
->pk11slot
);
1024 nssCryptokiObject_Destroy(to
);
1038 nssCryptokiObjectArray_Destroy(instances
);
1039 return ttok
? ttok
: (tok
? tok
: rtok
);
1043 STAN_ChangeCertTrust(CERTCertificate
*cc
, CERTCertTrust
*trust
)
1046 NSSCertificate
*c
= STAN_GetNSSCertificate(cc
);
1051 CERTCertTrust
*oldTrust
;
1052 nssListIterator
*tokens
;
1053 PRBool moving_object
;
1054 nssCryptokiObject
*newInstance
;
1055 nssPKIObject
*pkiob
;
1060 oldTrust
= nssTrust_GetCERTCertTrustForCert(c
, cc
);
1062 if (memcmp(oldTrust
, trust
, sizeof (CERTCertTrust
)) == 0) {
1063 /* ... and the new trust is no different, done) */
1066 /* take over memory already allocated in cc's arena */
1067 cc
->trust
= oldTrust
;
1070 cc
->trust
= PORT_ArenaAlloc(cc
->arena
, sizeof(CERTCertTrust
));
1072 memcpy(cc
->trust
, trust
, sizeof(CERTCertTrust
));
1073 /* Set the NSSCerticate's trust */
1074 arena
= nssArena_Create();
1075 if (!arena
) return PR_FAILURE
;
1076 nssTrust
= nss_ZNEW(arena
, NSSTrust
);
1078 nssArena_Destroy(arena
);
1081 pkiob
= nssPKIObject_Create(arena
, NULL
, cc
->dbhandle
, NULL
, nssPKILock
);
1083 nssArena_Destroy(arena
);
1086 nssTrust
->object
= *pkiob
;
1087 nssTrust
->certificate
= c
;
1088 nssTrust
->serverAuth
= get_stan_trust(trust
->sslFlags
, PR_FALSE
);
1089 nssTrust
->clientAuth
= get_stan_trust(trust
->sslFlags
, PR_TRUE
);
1090 nssTrust
->emailProtection
= get_stan_trust(trust
->emailFlags
, PR_FALSE
);
1091 nssTrust
->codeSigning
= get_stan_trust(trust
->objectSigningFlags
, PR_FALSE
);
1092 nssTrust
->stepUpApproved
=
1093 (PRBool
)(trust
->sslFlags
& CERTDB_GOVT_APPROVED_CA
);
1094 if (c
->object
.cryptoContext
!= NULL
) {
1095 /* The cert is in a context, set the trust there */
1096 NSSCryptoContext
*cc
= c
->object
.cryptoContext
;
1097 nssrv
= nssCryptoContext_ImportTrust(cc
, nssTrust
);
1098 if (nssrv
!= PR_SUCCESS
) {
1101 if (c
->object
.numInstances
== 0) {
1102 /* The context is the only instance, finished */
1106 td
= STAN_GetDefaultTrustDomain();
1107 tok
= stan_GetTrustToken(c
);
1108 moving_object
= PR_FALSE
;
1109 if (tok
&& PK11_IsReadOnly(tok
->pk11slot
)) {
1110 NSSRWLock_LockRead(td
->tokensLock
);
1111 tokens
= nssList_CreateIterator(td
->tokenList
);
1114 NSSRWLock_UnlockRead(td
->tokensLock
);
1117 for (tok
= (NSSToken
*)nssListIterator_Start(tokens
);
1118 tok
!= (NSSToken
*)NULL
;
1119 tok
= (NSSToken
*)nssListIterator_Next(tokens
))
1121 if (!PK11_IsReadOnly(tok
->pk11slot
)) break;
1123 nssListIterator_Finish(tokens
);
1124 nssListIterator_Destroy(tokens
);
1125 NSSRWLock_UnlockRead(td
->tokensLock
);
1126 moving_object
= PR_TRUE
;
1129 if (moving_object
) {
1130 /* this is kind of hacky. the softoken needs the cert
1131 * object in order to store trust. forcing it to be perm
1133 NSSUTF8
*nickname
= nssCertificate_GetNickname(c
, NULL
);
1134 NSSASCII7
*email
= NULL
;
1136 if (PK11_IsInternal(tok
->pk11slot
)) {
1139 newInstance
= nssToken_ImportCertificate(tok
, NULL
,
1140 NSSCertificateType_PKIX
,
1153 nssPKIObject_AddInstance(&c
->object
, newInstance
);
1155 newInstance
= nssToken_ImportTrust(tok
, NULL
, &c
->encoding
,
1156 &c
->issuer
, &c
->serial
,
1157 nssTrust
->serverAuth
,
1158 nssTrust
->clientAuth
,
1159 nssTrust
->codeSigning
,
1160 nssTrust
->emailProtection
,
1161 nssTrust
->stepUpApproved
, PR_TRUE
);
1162 /* If the selected token can't handle trust, dump the trust on
1163 * the internal token */
1164 if (!newInstance
&& !PK11_IsInternal(tok
->pk11slot
)) {
1165 PK11SlotInfo
*slot
= PK11_GetInternalKeySlot();
1166 NSSUTF8
*nickname
= nssCertificate_GetNickname(c
, NULL
);
1167 NSSASCII7
*email
= c
->email
;
1168 tok
= PK11Slot_GetNSSToken(slot
);
1169 PK11_FreeSlot(slot
);
1171 newInstance
= nssToken_ImportCertificate(tok
, NULL
,
1172 NSSCertificateType_PKIX
,
1185 nssPKIObject_AddInstance(&c
->object
, newInstance
);
1186 newInstance
= nssToken_ImportTrust(tok
, NULL
, &c
->encoding
,
1187 &c
->issuer
, &c
->serial
,
1188 nssTrust
->serverAuth
,
1189 nssTrust
->clientAuth
,
1190 nssTrust
->codeSigning
,
1191 nssTrust
->emailProtection
,
1192 nssTrust
->stepUpApproved
, PR_TRUE
);
1195 nssCryptokiObject_Destroy(newInstance
);
1204 (void)nssTrust_Destroy(nssTrust
);
1208 /* CERT_TraversePermCertsForSubject */
1209 NSS_IMPLEMENT PRStatus
1210 nssTrustDomain_TraverseCertificatesBySubject (
1213 PRStatus (*callback
)(NSSCertificate
*c
, void *arg
),
1217 PRStatus nssrv
= PR_SUCCESS
;
1219 NSSCertificate
**subjectCerts
;
1222 tmpArena
= NSSArena_Create();
1226 subjectCerts
= NSSTrustDomain_FindCertificatesBySubject(td
, subject
, NULL
,
1229 for (i
=0, c
= subjectCerts
[i
]; c
; i
++) {
1230 nssrv
= callback(c
, arg
);
1231 if (nssrv
!= PR_SUCCESS
) break;
1234 nssArena_Destroy(tmpArena
);
1238 /* CERT_TraversePermCertsForNickname */
1239 NSS_IMPLEMENT PRStatus
1240 nssTrustDomain_TraverseCertificatesByNickname (
1243 PRStatus (*callback
)(NSSCertificate
*c
, void *arg
),
1247 PRStatus nssrv
= PR_SUCCESS
;
1249 NSSCertificate
**nickCerts
;
1252 tmpArena
= NSSArena_Create();
1256 nickCerts
= NSSTrustDomain_FindCertificatesByNickname(td
, nickname
, NULL
,
1259 for (i
=0, c
= nickCerts
[i
]; c
; i
++) {
1260 nssrv
= callback(c
, arg
);
1261 if (nssrv
!= PR_SUCCESS
) break;
1264 nssArena_Destroy(tmpArena
);
1268 static void cert_dump_iter(const void *k
, void *v
, void *a
)
1270 NSSCertificate
*c
= (NSSCertificate
*)k
;
1271 CERTCertificate
*cert
= STAN_GetCERTCertificate(c
);
1272 printf("[%2d] \"%s\"\n", c
->object
.refCount
, cert
->subjectName
);
1276 nss_DumpCertificateCacheInfo()
1279 NSSCryptoContext
*cc
;
1280 td
= STAN_GetDefaultTrustDomain();
1281 cc
= STAN_GetDefaultCryptoContext();
1282 printf("\n\nCertificates in the cache:\n");
1283 nssTrustDomain_DumpCacheInfo(td
, cert_dump_iter
, NULL
);
1284 printf("\n\nCertificates in the temporary store:\n");
1285 if (cc
->certStore
) {
1286 nssCertificateStore_DumpStoreInfo(cc
->certStore
, cert_dump_iter
, NULL
);