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.
22 * Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
38 * This file manages PKCS #11 instances of certificates.
54 #include "cmsreclist.h"
62 #endif /* NSS_3_4_CODE */
71 #include "pkistore.h" /* to remove temp cert */
74 extern const NSSError NSS_ERROR_NOT_FOUND
;
75 extern const NSSError NSS_ERROR_INVALID_CERTIFICATE
;
77 struct nss3_cert_cbstr
{
78 SECStatus(* callback
)(CERTCertificate
*, void *);
83 /* Translate from NSSCertificate to CERTCertificate, then pass the latter
86 static PRStatus
convert_cert(NSSCertificate
*c
, void *arg
)
88 CERTCertificate
*nss3cert
;
90 struct nss3_cert_cbstr
*nss3cb
= (struct nss3_cert_cbstr
*)arg
;
91 /* 'c' is not adopted. caller will free it */
92 nss3cert
= STAN_GetCERTCertificate(c
);
93 if (!nss3cert
) return PR_FAILURE
;
94 secrv
= (*nss3cb
->callback
)(nss3cert
, nss3cb
->arg
);
95 return (secrv
) ? PR_FAILURE
: PR_SUCCESS
;
99 * build a cert nickname based on the token name and the label of the
100 * certificate If the label in NULL, build a label based on the ID.
102 static int toHex(int x
) { return (x
< 10) ? (x
+'0') : (x
+'a'-10); }
103 #define MAX_CERT_ID 4
104 #define DEFAULT_STRING "Cert ID "
106 pk11_buildNickname(PK11SlotInfo
*slot
,CK_ATTRIBUTE
*cert_label
,
107 CK_ATTRIBUTE
*key_label
, CK_ATTRIBUTE
*cert_id
)
109 int prefixLen
= PORT_Strlen(slot
->token_name
);
112 char buildNew
[sizeof(DEFAULT_STRING
)+MAX_CERT_ID
*2];
113 char *next
,*nickname
;
115 if (cert_label
&& (cert_label
->ulValueLen
)) {
116 suffixLen
= cert_label
->ulValueLen
;
117 suffix
= (char*)cert_label
->pValue
;
118 } else if (key_label
&& (key_label
->ulValueLen
)) {
119 suffixLen
= key_label
->ulValueLen
;
120 suffix
= (char*)key_label
->pValue
;
121 } else if (cert_id
&& cert_id
->ulValueLen
> 0) {
122 int i
,first
= cert_id
->ulValueLen
- MAX_CERT_ID
;
123 int offset
= sizeof(DEFAULT_STRING
);
124 char *idValue
= (char *)cert_id
->pValue
;
126 PORT_Memcpy(buildNew
,DEFAULT_STRING
,sizeof(DEFAULT_STRING
)-1);
127 next
= buildNew
+ offset
;
128 if (first
< 0) first
= 0;
129 for (i
=first
; i
< (int) cert_id
->ulValueLen
; i
++) {
130 *next
++ = toHex((idValue
[i
] >> 4) & 0xf);
131 *next
++ = toHex(idValue
[i
] & 0xf);
135 suffixLen
= PORT_Strlen(buildNew
);
137 PORT_SetError( SEC_ERROR_LIBRARY_FAILURE
);
141 /* if is internal key slot, add code to skip the prefix!! */
142 next
= nickname
= (char *)PORT_Alloc(prefixLen
+1+suffixLen
+1);
143 if (nickname
== NULL
) return NULL
;
145 PORT_Memcpy(next
,slot
->token_name
,prefixLen
);
148 PORT_Memcpy(next
,suffix
,suffixLen
);
155 PK11_IsUserCert(PK11SlotInfo
*slot
, CERTCertificate
*cert
,
156 CK_OBJECT_HANDLE certID
)
158 CK_OBJECT_CLASS theClass
;
160 if (slot
== NULL
) return PR_FALSE
;
161 if (cert
== NULL
) return PR_FALSE
;
163 theClass
= CKO_PRIVATE_KEY
;
164 if (pk11_LoginStillRequired(slot
,NULL
)) {
165 theClass
= CKO_PUBLIC_KEY
;
167 if (PK11_MatchItem(slot
, certID
, theClass
) != CK_INVALID_HANDLE
) {
171 if (theClass
== CKO_PUBLIC_KEY
) {
172 SECKEYPublicKey
*pubKey
= CERT_ExtractPublicKey(cert
);
173 CK_ATTRIBUTE theTemplate
;
175 if (pubKey
== NULL
) {
179 PK11_SETATTRS(&theTemplate
,0,NULL
,0);
180 switch (pubKey
->keyType
) {
182 PK11_SETATTRS(&theTemplate
,CKA_MODULUS
, pubKey
->u
.rsa
.modulus
.data
,
183 pubKey
->u
.rsa
.modulus
.len
);
186 PK11_SETATTRS(&theTemplate
,CKA_VALUE
, pubKey
->u
.dsa
.publicValue
.data
,
187 pubKey
->u
.dsa
.publicValue
.len
);
190 PK11_SETATTRS(&theTemplate
,CKA_VALUE
, pubKey
->u
.dh
.publicValue
.data
,
191 pubKey
->u
.dh
.publicValue
.len
);
194 PK11_SETATTRS(&theTemplate
,CKA_EC_POINT
,
195 pubKey
->u
.ec
.publicValue
.data
,
196 pubKey
->u
.ec
.publicValue
.len
);
201 /* fall through and return false */
205 if (theTemplate
.ulValueLen
== 0) {
206 SECKEY_DestroyPublicKey(pubKey
);
209 pk11_SignedToUnsigned(&theTemplate
);
210 if (pk11_FindObjectByTemplate(slot
,&theTemplate
,1) != CK_INVALID_HANDLE
) {
211 SECKEY_DestroyPublicKey(pubKey
);
214 SECKEY_DestroyPublicKey(pubKey
);
220 * Check out if a cert has ID of zero. This is a magic ID that tells
221 * NSS that this cert may be an automagically trusted cert.
222 * The Cert has to be self signed as well. That check is done elsewhere.
226 pk11_isID0(PK11SlotInfo
*slot
, CK_OBJECT_HANDLE certID
)
228 CK_ATTRIBUTE keyID
= {CKA_ID
, NULL
, 0};
229 PRBool isZero
= PR_FALSE
;
234 crv
= PK11_GetAttributes(NULL
,slot
,certID
,&keyID
,1);
239 if (keyID
.ulValueLen
!= 0) {
240 char *value
= (char *)keyID
.pValue
;
241 isZero
= PR_TRUE
; /* ID exists, may be zero */
242 for (i
=0; i
< (int) keyID
.ulValueLen
; i
++) {
244 isZero
= PR_FALSE
; /* nope */
249 PORT_Free(keyID
.pValue
);
255 * Create an NSSCertificate from a slot/certID pair, return it as a
258 static CERTCertificate
259 *pk11_fastCert(PK11SlotInfo
*slot
, CK_OBJECT_HANDLE certID
,
260 CK_ATTRIBUTE
*privateLabel
, char **nickptr
)
263 nssCryptokiObject
*co
;
266 NSSTrustDomain
*td
= STAN_GetDefaultTrustDomain();
268 /* Get the cryptoki object from the handle */
269 token
= PK11Slot_GetNSSToken(slot
);
270 co
= nssCryptokiObject_Create(token
, token
->defaultSession
, certID
);
275 /* Create a PKI object from the cryptoki instance */
276 pkio
= nssPKIObject_Create(NULL
, co
, td
, NULL
, nssPKIMonitor
);
278 nssCryptokiObject_Destroy(co
);
282 /* Create a certificate */
283 c
= nssCertificate_Create(pkio
);
285 nssPKIObject_Destroy(pkio
);
289 nssTrustDomain_AddCertsToCache(td
, &c
, 1);
291 /* Build the old-fashioned nickname */
292 if ((nickptr
) && (co
->label
)) {
293 CK_ATTRIBUTE label
, id
;
294 label
.type
= CKA_LABEL
;
295 label
.pValue
= co
->label
;
296 label
.ulValueLen
= PORT_Strlen(co
->label
);
298 id
.pValue
= c
->id
.data
;
299 id
.ulValueLen
= c
->id
.size
;
300 *nickptr
= pk11_buildNickname(slot
, &label
, privateLabel
, &id
);
302 return STAN_GetCERTCertificateOrRelease(c
);
306 * Build an CERTCertificate structure from a PKCS#11 object ID.... certID
307 * Must be a CertObject. This code does not explicitly checks that.
310 PK11_MakeCertFromHandle(PK11SlotInfo
*slot
,CK_OBJECT_HANDLE certID
,
311 CK_ATTRIBUTE
*privateLabel
)
313 char * nickname
= NULL
;
314 CERTCertificate
*cert
= NULL
;
315 CERTCertTrust
*trust
;
316 PRBool isFortezzaRootCA
= PR_FALSE
;
317 PRBool swapNickname
= PR_FALSE
;
319 cert
= pk11_fastCert(slot
,certID
,privateLabel
, &nickname
);
320 if (cert
== NULL
) goto loser
;
323 if (cert
->nickname
!= NULL
) {
324 cert
->dbnickname
= cert
->nickname
;
326 cert
->nickname
= PORT_ArenaStrdup(cert
->arena
,nickname
);
329 swapNickname
= PR_TRUE
;
332 /* remember where this cert came from.... If we have just looked
333 * it up from the database and it already has a slot, don't add a new
335 if (cert
->slot
== NULL
) {
336 cert
->slot
= PK11_ReferenceSlot(slot
);
337 cert
->pkcs11ID
= certID
;
338 cert
->ownSlot
= PR_TRUE
;
339 cert
->series
= slot
->series
;
342 trust
= (CERTCertTrust
*)PORT_ArenaAlloc(cert
->arena
, sizeof(CERTCertTrust
));
343 if (trust
== NULL
) goto loser
;
344 PORT_Memset(trust
,0, sizeof(CERTCertTrust
));
349 if(! pk11_HandleTrustObject(slot
, cert
, trust
) ) {
352 /* build some cert trust flags */
353 if (CERT_IsCACert(cert
, &type
)) {
354 unsigned int trustflags
= CERTDB_VALID_CA
;
356 /* Allow PKCS #11 modules to give us trusted CA's. We only accept
357 * valid CA's which are self-signed here. They must have an object
359 if (pk11_isID0(slot
,certID
) &&
360 SECITEM_CompareItem(&cert
->derSubject
,&cert
->derIssuer
)
362 trustflags
|= CERTDB_TRUSTED_CA
;
363 /* is the slot a fortezza card? allow the user or
364 * admin to turn on objectSigning, but don't turn
365 * full trust on explicitly */
366 if (PK11_DoesMechanism(slot
,CKM_KEA_KEY_DERIVE
)) {
367 trust
->objectSigningFlags
|= CERTDB_VALID_CA
;
368 isFortezzaRootCA
= PR_TRUE
;
371 if ((type
& NS_CERT_TYPE_SSL_CA
) == NS_CERT_TYPE_SSL_CA
) {
372 trust
->sslFlags
|= trustflags
;
374 if ((type
& NS_CERT_TYPE_EMAIL_CA
) == NS_CERT_TYPE_EMAIL_CA
) {
375 trust
->emailFlags
|= trustflags
;
377 if ((type
& NS_CERT_TYPE_OBJECT_SIGNING_CA
)
378 == NS_CERT_TYPE_OBJECT_SIGNING_CA
) {
379 trust
->objectSigningFlags
|= trustflags
;
384 if (PK11_IsUserCert(slot
,cert
,certID
)) {
385 trust
->sslFlags
|= CERTDB_USER
;
386 trust
->emailFlags
|= CERTDB_USER
;
387 /* trust->objectSigningFlags |= CERTDB_USER; */
393 if (nickname
) PORT_Free(nickname
);
394 if (cert
) CERT_DestroyCertificate(cert
);
400 * Build get a certificate from a private key
403 PK11_GetCertFromPrivateKey(SECKEYPrivateKey
*privKey
)
405 PK11SlotInfo
*slot
= privKey
->pkcs11Slot
;
406 CK_OBJECT_HANDLE handle
= privKey
->pkcs11ID
;
407 CK_OBJECT_HANDLE certID
=
408 PK11_MatchItem(slot
,handle
,CKO_CERTIFICATE
);
409 CERTCertificate
*cert
;
411 if (certID
== CK_INVALID_HANDLE
) {
412 PORT_SetError(SSL_ERROR_NO_CERTIFICATE
);
415 cert
= PK11_MakeCertFromHandle(slot
,certID
,NULL
);
421 * delete a cert and it's private key (if no other certs are pointing to the
425 PK11_DeleteTokenCertAndKey(CERTCertificate
*cert
,void *wincx
)
427 SECKEYPrivateKey
*privKey
= PK11_FindKeyByAnyCert(cert
,wincx
);
428 CK_OBJECT_HANDLE pubKey
;
429 PK11SlotInfo
*slot
= NULL
;
431 pubKey
= pk11_FindPubKeyByAnyCert(cert
, &slot
, wincx
);
433 /* For 3.4, utilize the generic cert delete function */
434 SEC_DeletePermCertificate(cert
);
435 PK11_DeleteTokenPrivateKey(privKey
, PR_FALSE
);
437 if ((pubKey
!= CK_INVALID_HANDLE
) && (slot
!= NULL
)) {
438 PK11_DestroyTokenObject(slot
,pubKey
);
445 * cert callback structure
447 typedef struct pk11DoCertCallbackStr
{
448 SECStatus(* callback
)(PK11SlotInfo
*slot
, CERTCertificate
*, void *);
449 SECStatus(* noslotcallback
)(CERTCertificate
*, void *);
450 SECStatus(* itemcallback
)(CERTCertificate
*, SECItem
*, void *);
452 } pk11DoCertCallback
;
455 typedef struct pk11CertCallbackStr
{
456 SECStatus(* callback
)(CERTCertificate
*,SECItem
*,void *);
460 struct fake_der_cb_argstr
462 SECStatus(* callback
)(CERTCertificate
*, SECItem
*, void *);
466 static SECStatus
fake_der_cb(CERTCertificate
*c
, void *a
)
468 struct fake_der_cb_argstr
*fda
= (struct fake_der_cb_argstr
*)a
;
469 return (*fda
->callback
)(c
, &c
->derCert
, fda
->arg
);
473 * Extract all the certs on a card from a slot.
476 PK11_TraverseSlotCerts(SECStatus(* callback
)(CERTCertificate
*,SECItem
*,void *),
477 void *arg
, void *wincx
)
479 NSSTrustDomain
*defaultTD
= STAN_GetDefaultTrustDomain();
480 struct fake_der_cb_argstr fda
;
481 struct nss3_cert_cbstr pk11cb
;
483 /* authenticate to the tokens first */
484 (void) pk11_TraverseAllSlots( NULL
, NULL
, PR_TRUE
, wincx
);
486 fda
.callback
= callback
;
488 pk11cb
.callback
= fake_der_cb
;
490 NSSTrustDomain_TraverseCertificates(defaultTD
, convert_cert
, &pk11cb
);
495 transfer_token_certs_to_collection(nssList
*certList
, NSSToken
*token
,
496 nssPKIObjectCollection
*collection
)
498 NSSCertificate
**certs
;
500 NSSToken
**tokens
, **tp
;
501 count
= nssList_Count(certList
);
505 certs
= nss_ZNEWARRAY(NULL
, NSSCertificate
*, count
);
509 nssList_GetArray(certList
, (void **)certs
, count
);
510 for (i
=0; i
<count
; i
++) {
511 tokens
= nssPKIObject_GetTokens(&certs
[i
]->object
, NULL
);
513 for (tp
= tokens
; *tp
; tp
++) {
515 nssPKIObjectCollection_AddObject(collection
,
516 (nssPKIObject
*)certs
[i
]);
519 nssTokenArray_Destroy(tokens
);
521 CERT_DestroyCertificate(STAN_GetCERTCertificateOrRelease(certs
[i
]));
527 PK11_FindCertFromNickname(char *nickname
, void *wincx
)
530 CERTCertificate
*rvCert
= NULL
;
531 NSSCertificate
*cert
= NULL
;
532 NSSCertificate
**certs
= NULL
;
533 static const NSSUsage usage
= {PR_TRUE
/* ... */ };
535 NSSTrustDomain
*defaultTD
= STAN_GetDefaultTrustDomain();
536 PK11SlotInfo
*slot
= NULL
;
539 char *delimit
= NULL
;
542 nickCopy
= PORT_Strdup(nickname
);
544 /* error code is set */
547 if ((delimit
= PORT_Strchr(nickCopy
,':')) != NULL
) {
548 tokenName
= nickCopy
;
549 nickname
= delimit
+ 1;
551 /* find token by name */
552 token
= NSSTrustDomain_FindTokenByName(defaultTD
, (NSSUTF8
*)tokenName
);
554 slot
= PK11_ReferenceSlot(token
->pk11slot
);
558 slot
= PK11_GetInternalKeySlot();
559 token
= PK11Slot_GetNSSToken(slot
);
563 nssCryptokiObject
**instances
;
564 nssPKIObjectCollection
*collection
;
565 nssTokenSearchType tokenOnly
= nssTokenSearchType_TokenOnly
;
566 if (!PK11_IsPresent(slot
)) {
569 rv
= pk11_AuthenticateUnfriendly(slot
, PR_TRUE
, wincx
);
570 if (rv
!= SECSuccess
) {
573 collection
= nssCertificateCollection_Create(defaultTD
, NULL
);
577 certList
= nssList_Create(NULL
, PR_FALSE
);
579 nssPKIObjectCollection_Destroy(collection
);
582 (void)nssTrustDomain_GetCertsForNicknameFromCache(defaultTD
,
585 transfer_token_certs_to_collection(certList
, token
, collection
);
586 instances
= nssToken_FindCertificatesByNickname(token
,
592 nssPKIObjectCollection_AddInstances(collection
, instances
, 0);
593 nss_ZFreeIf(instances
);
594 /* if it wasn't found, repeat the process for email address */
595 if (nssPKIObjectCollection_Count(collection
) == 0 &&
596 PORT_Strchr(nickname
, '@') != NULL
)
598 char* lowercaseName
= CERT_FixupEmailAddr(nickname
);
600 (void)nssTrustDomain_GetCertsForEmailAddressFromCache(defaultTD
,
603 transfer_token_certs_to_collection(certList
, token
, collection
);
604 instances
= nssToken_FindCertificatesByEmail(token
,
610 nssPKIObjectCollection_AddInstances(collection
, instances
, 0);
611 nss_ZFreeIf(instances
);
612 PORT_Free(lowercaseName
);
615 certs
= nssPKIObjectCollection_GetCertificates(collection
,
617 nssPKIObjectCollection_Destroy(collection
);
619 cert
= nssCertificateArray_FindBestCertificate(certs
, NULL
,
622 rvCert
= STAN_GetCERTCertificateOrRelease(cert
);
624 nssCertificateArray_Destroy(certs
);
626 nssList_Destroy(certList
);
631 if (nickCopy
) PORT_Free(nickCopy
);
637 if (nickCopy
) PORT_Free(nickCopy
);
642 PK11_FindCertsFromNickname(char *nickname
, void *wincx
)
645 char *delimit
= NULL
;
648 CERTCertList
*certList
= NULL
;
649 nssPKIObjectCollection
*collection
= NULL
;
650 NSSCertificate
**foundCerts
= NULL
;
651 NSSTrustDomain
*defaultTD
= STAN_GetDefaultTrustDomain();
657 nickCopy
= PORT_Strdup(nickname
);
659 /* error code is set */
662 if ((delimit
= PORT_Strchr(nickCopy
,':')) != NULL
) {
663 tokenName
= nickCopy
;
664 nickname
= delimit
+ 1;
666 /* find token by name */
667 token
= NSSTrustDomain_FindTokenByName(defaultTD
, (NSSUTF8
*)tokenName
);
669 slot
= PK11_ReferenceSlot(token
->pk11slot
);
675 slot
= PK11_GetInternalKeySlot();
676 token
= PK11Slot_GetNSSToken(slot
);
681 nssCryptokiObject
**instances
;
682 nssTokenSearchType tokenOnly
= nssTokenSearchType_TokenOnly
;
683 rv
= pk11_AuthenticateUnfriendly(slot
, PR_TRUE
, wincx
);
684 if (rv
!= SECSuccess
) {
686 if (nickCopy
) PORT_Free(nickCopy
);
689 collection
= nssCertificateCollection_Create(defaultTD
, NULL
);
692 if (nickCopy
) PORT_Free(nickCopy
);
695 nameList
= nssList_Create(NULL
, PR_FALSE
);
698 if (nickCopy
) PORT_Free(nickCopy
);
701 (void)nssTrustDomain_GetCertsForNicknameFromCache(defaultTD
,
704 transfer_token_certs_to_collection(nameList
, token
, collection
);
705 instances
= nssToken_FindCertificatesByNickname(token
,
711 nssPKIObjectCollection_AddInstances(collection
, instances
, 0);
712 nss_ZFreeIf(instances
);
714 /* if it wasn't found, repeat the process for email address */
715 if (nssPKIObjectCollection_Count(collection
) == 0 &&
716 PORT_Strchr(nickname
, '@') != NULL
)
718 char* lowercaseName
= CERT_FixupEmailAddr(nickname
);
720 (void)nssTrustDomain_GetCertsForEmailAddressFromCache(defaultTD
,
723 transfer_token_certs_to_collection(nameList
, token
, collection
);
724 instances
= nssToken_FindCertificatesByEmail(token
,
730 nssPKIObjectCollection_AddInstances(collection
, instances
, 0);
731 nss_ZFreeIf(instances
);
732 PORT_Free(lowercaseName
);
736 nssList_Destroy(nameList
);
737 foundCerts
= nssPKIObjectCollection_GetCertificates(collection
,
739 nssPKIObjectCollection_Destroy(collection
);
744 if (nickCopy
) PORT_Free(nickCopy
);
746 PRTime now
= PR_Now();
747 certList
= CERT_NewCertList();
748 for (i
=0, c
= *foundCerts
; c
; c
= foundCerts
[++i
]) {
750 CERTCertificate
*certCert
= STAN_GetCERTCertificateOrRelease(c
);
751 /* c may be invalid after this, don't reference it */
753 /* CERT_AddCertToListSorted adopts certCert */
754 CERT_AddCertToListSorted(certList
, certCert
,
755 CERT_SortCBValidity
, &now
);
758 nssCertificate_Destroy(c
);
761 if (certList
&& CERT_LIST_HEAD(certList
) == NULL
) {
762 CERT_DestroyCertList(certList
);
765 /* all the certs have been adopted or freed, free the raw array */
766 nss_ZFreeIf(foundCerts
);
772 * extract a key ID for a certificate...
773 * NOTE: We call this function from PKCS11.c If we ever use
774 * pkcs11 to extract the public key (we currently do not), this will break.
777 PK11_GetPubIndexKeyID(CERTCertificate
*cert
) {
778 SECKEYPublicKey
*pubk
;
779 SECItem
*newItem
= NULL
;
781 pubk
= CERT_ExtractPublicKey(cert
);
782 if (pubk
== NULL
) return NULL
;
784 switch (pubk
->keyType
) {
786 newItem
= SECITEM_DupItem(&pubk
->u
.rsa
.modulus
);
789 newItem
= SECITEM_DupItem(&pubk
->u
.dsa
.publicValue
);
792 newItem
= SECITEM_DupItem(&pubk
->u
.dh
.publicValue
);
795 newItem
= SECITEM_DupItem(&pubk
->u
.ec
.publicValue
);
799 newItem
= NULL
; /* Fortezza Fix later... */
801 SECKEY_DestroyPublicKey(pubk
);
802 /* make hash of it */
807 * generate a CKA_ID from a certificate.
810 pk11_mkcertKeyID(CERTCertificate
*cert
) {
811 SECItem
*pubKeyData
= PK11_GetPubIndexKeyID(cert
) ;
814 if (pubKeyData
== NULL
) return NULL
;
816 certCKA_ID
= PK11_MakeIDFromPubKey(pubKeyData
);
817 SECITEM_FreeItem(pubKeyData
,PR_TRUE
);
822 * Write the cert into the token.
825 PK11_ImportCert(PK11SlotInfo
*slot
, CERTCertificate
*cert
,
826 CK_OBJECT_HANDLE key
, char *nickname
, PRBool includeTrust
)
830 nssCryptokiObject
*keyobj
, *certobj
;
831 NSSToken
*token
= PK11Slot_GetNSSToken(slot
);
832 SECItem
*keyID
= pk11_mkcertKeyID(cert
);
833 char *emailAddr
= NULL
;
834 nssCertificateStoreTrace lockTrace
= {NULL
, NULL
, PR_FALSE
, PR_FALSE
};
835 nssCertificateStoreTrace unlockTrace
= {NULL
, NULL
, PR_FALSE
, PR_FALSE
};
841 if (PK11_IsInternal(slot
) && cert
->emailAddr
&& cert
->emailAddr
[0]) {
842 emailAddr
= cert
->emailAddr
;
845 /* need to get the cert as a stan cert */
846 if (cert
->nssCertificate
) {
847 c
= cert
->nssCertificate
;
849 c
= STAN_GetNSSCertificate(cert
);
855 if (c
->object
.cryptoContext
) {
856 /* Delete the temp instance */
857 NSSCryptoContext
*cc
= c
->object
.cryptoContext
;
858 nssCertificateStore_Lock(cc
->certStore
, &lockTrace
);
859 nssCertificateStore_RemoveCertLOCKED(cc
->certStore
, c
);
860 nssCertificateStore_Unlock(cc
->certStore
, &lockTrace
, &unlockTrace
);
861 nssCertificateStore_Check(&lockTrace
, &unlockTrace
);
862 c
->object
.cryptoContext
= NULL
;
863 cert
->istemp
= PR_FALSE
;
864 cert
->isperm
= PR_TRUE
;
867 /* set the id for the cert */
868 nssItem_Create(c
->object
.arena
, &c
->id
, keyID
->len
, keyID
->data
);
873 if (key
!= CK_INVALID_HANDLE
) {
874 /* create an object for the key, ... */
875 keyobj
= nss_ZNEW(NULL
, nssCryptokiObject
);
879 keyobj
->token
= nssToken_AddRef(token
);
880 keyobj
->handle
= key
;
881 keyobj
->isTokenObject
= PR_TRUE
;
883 /* ... in order to set matching attributes for the key */
884 status
= nssCryptokiPrivateKey_SetCertificate(keyobj
, NULL
, nickname
,
885 &c
->id
, &c
->subject
);
886 nssCryptokiObject_Destroy(keyobj
);
887 if (status
!= PR_SUCCESS
) {
892 /* do the token import */
893 certobj
= nssToken_ImportCertificate(token
, NULL
,
894 NSSCertificateType_PKIX
,
904 if (NSS_GetError() == NSS_ERROR_INVALID_CERTIFICATE
) {
905 PORT_SetError(SEC_ERROR_REUSED_ISSUER_AND_SERIAL
);
906 SECITEM_FreeItem(keyID
,PR_TRUE
);
911 /* add the new instance to the cert, force an update of the
912 * CERTCertificate, and finish
914 nssPKIObject_AddInstance(&c
->object
, certobj
);
915 nssTrustDomain_AddCertsToCache(STAN_GetDefaultTrustDomain(), &c
, 1);
916 (void)STAN_ForceCERTCertificateUpdate(c
);
917 SECITEM_FreeItem(keyID
,PR_TRUE
);
920 SECITEM_FreeItem(keyID
,PR_TRUE
);
921 PORT_SetError(SEC_ERROR_ADDING_CERT
);
926 PK11_ImportDERCert(PK11SlotInfo
*slot
, SECItem
*derCert
,
927 CK_OBJECT_HANDLE key
, char *nickname
, PRBool includeTrust
) {
928 CERTCertificate
*cert
;
931 cert
= CERT_NewTempCertificate(CERT_GetDefaultCertDB(),
932 derCert
, NULL
, PR_FALSE
, PR_TRUE
);
933 if (cert
== NULL
) return SECFailure
;
935 rv
= PK11_ImportCert(slot
, cert
, key
, nickname
, includeTrust
);
936 CERT_DestroyCertificate (cert
);
941 * get a certificate handle, look at the cached handle first..
944 pk11_getcerthandle(PK11SlotInfo
*slot
, CERTCertificate
*cert
,
945 CK_ATTRIBUTE
*theTemplate
,int tsize
)
947 CK_OBJECT_HANDLE certh
;
949 if (cert
->slot
== slot
) {
950 certh
= cert
->pkcs11ID
;
951 if ((certh
== CK_INVALID_HANDLE
) ||
952 (cert
->series
!= slot
->series
)) {
953 certh
= pk11_FindObjectByTemplate(slot
,theTemplate
,tsize
);
954 cert
->pkcs11ID
= certh
;
955 cert
->series
= slot
->series
;
958 certh
= pk11_FindObjectByTemplate(slot
,theTemplate
,tsize
);
964 * return the private key From a given Cert
967 PK11_FindPrivateKeyFromCert(PK11SlotInfo
*slot
, CERTCertificate
*cert
,
970 CK_OBJECT_CLASS certClass
= CKO_CERTIFICATE
;
971 CK_ATTRIBUTE theTemplate
[] = {
972 { CKA_VALUE
, NULL
, 0 },
973 { CKA_CLASS
, NULL
, 0 }
975 /* if you change the array, change the variable below as well */
976 int tsize
= sizeof(theTemplate
)/sizeof(theTemplate
[0]);
977 CK_OBJECT_HANDLE certh
;
978 CK_OBJECT_HANDLE keyh
;
979 CK_ATTRIBUTE
*attrs
= theTemplate
;
983 PK11_SETATTRS(attrs
, CKA_VALUE
, cert
->derCert
.data
,
984 cert
->derCert
.len
); attrs
++;
985 PK11_SETATTRS(attrs
, CKA_CLASS
, &certClass
, sizeof(certClass
));
990 rv
= pk11_AuthenticateUnfriendly(slot
, PR_TRUE
, wincx
);
991 if (rv
!= SECSuccess
) {
995 certh
= pk11_getcerthandle(slot
,cert
,theTemplate
,tsize
);
996 if (certh
== CK_INVALID_HANDLE
) {
1000 * prevent a login race condition. If slot is logged in between
1001 * our call to pk11_LoginStillRequired and the
1002 * PK11_MatchItem. The matchItem call will either succeed, or
1003 * we will call it one more time after calling PK11_Authenticate
1004 * (which is a noop on an authenticated token).
1006 needLogin
= pk11_LoginStillRequired(slot
,wincx
);
1007 keyh
= PK11_MatchItem(slot
,certh
,CKO_PRIVATE_KEY
);
1008 if ((keyh
== CK_INVALID_HANDLE
) && needLogin
&&
1009 (SSL_ERROR_NO_CERTIFICATE
== (err
= PORT_GetError()) ||
1010 SEC_ERROR_TOKEN_NOT_LOGGED_IN
== err
)) {
1011 /* try it again authenticated */
1012 rv
= PK11_Authenticate(slot
, PR_TRUE
, wincx
);
1013 if (rv
!= SECSuccess
) {
1016 keyh
= PK11_MatchItem(slot
,certh
,CKO_PRIVATE_KEY
);
1018 if (keyh
== CK_INVALID_HANDLE
) {
1021 return PK11_MakePrivKey(slot
, nullKey
, PR_TRUE
, keyh
, wincx
);
1025 * import a cert for a private key we have already generated. Set the label
1026 * on both to be the nickname. This is for the Key Gen, orphaned key case.
1029 PK11_KeyForCertExists(CERTCertificate
*cert
, CK_OBJECT_HANDLE
*keyPtr
,
1032 PK11SlotListElement
*le
;
1034 CK_OBJECT_HANDLE key
;
1035 PK11SlotInfo
*slot
= NULL
;
1039 keyID
= pk11_mkcertKeyID(cert
);
1041 list
= PK11_GetAllTokens(CKM_INVALID_MECHANISM
,PR_FALSE
,PR_TRUE
,wincx
);
1042 if ((keyID
== NULL
) || (list
== NULL
)) {
1043 if (keyID
) SECITEM_FreeItem(keyID
,PR_TRUE
);
1044 if (list
) PK11_FreeSlotList(list
);
1048 /* Look for the slot that holds the Key */
1049 for (le
= list
->head
; le
; le
= le
->next
) {
1051 * prevent a login race condition. If le->slot is logged in between
1052 * our call to pk11_LoginStillRequired and the
1053 * pk11_FindPrivateKeyFromCertID, the find will either succeed, or
1054 * we will call it one more time after calling PK11_Authenticate
1055 * (which is a noop on an authenticated token).
1057 PRBool needLogin
= pk11_LoginStillRequired(le
->slot
,wincx
);
1058 key
= pk11_FindPrivateKeyFromCertID(le
->slot
,keyID
);
1059 if ((key
== CK_INVALID_HANDLE
) && needLogin
&&
1060 (SSL_ERROR_NO_CERTIFICATE
== (err
= PORT_GetError()) ||
1061 SEC_ERROR_TOKEN_NOT_LOGGED_IN
== err
)) {
1062 /* authenticate and try again */
1063 rv
= PK11_Authenticate(le
->slot
, PR_TRUE
, wincx
);
1064 if (rv
!= SECSuccess
) continue;
1065 key
= pk11_FindPrivateKeyFromCertID(le
->slot
,keyID
);
1067 if (key
!= CK_INVALID_HANDLE
) {
1068 slot
= PK11_ReferenceSlot(le
->slot
);
1069 if (keyPtr
) *keyPtr
= key
;
1074 SECITEM_FreeItem(keyID
,PR_TRUE
);
1075 PK11_FreeSlotList(list
);
1080 * import a cert for a private key we have already generated. Set the label
1081 * on both to be the nickname. This is for the Key Gen, orphaned key case.
1084 PK11_KeyForDERCertExists(SECItem
*derCert
, CK_OBJECT_HANDLE
*keyPtr
,
1086 CERTCertificate
*cert
;
1087 PK11SlotInfo
*slot
= NULL
;
1089 /* letting this use go -- the only thing that the cert is used for is
1090 * to get the ID attribute.
1092 cert
= CERT_DecodeDERCertificate(derCert
, PR_FALSE
, NULL
);
1093 if (cert
== NULL
) return NULL
;
1095 slot
= PK11_KeyForCertExists(cert
, keyPtr
, wincx
);
1096 CERT_DestroyCertificate (cert
);
1101 PK11_ImportCertForKey(CERTCertificate
*cert
, char *nickname
,void *wincx
) {
1102 PK11SlotInfo
*slot
= NULL
;
1103 CK_OBJECT_HANDLE key
;
1105 slot
= PK11_KeyForCertExists(cert
,&key
,wincx
);
1108 if (PK11_ImportCert(slot
,cert
,key
,nickname
,PR_FALSE
) != SECSuccess
) {
1109 PK11_FreeSlot(slot
);
1113 PORT_SetError(SEC_ERROR_ADDING_CERT
);
1120 PK11_ImportDERCertForKey(SECItem
*derCert
, char *nickname
,void *wincx
) {
1121 CERTCertificate
*cert
;
1122 PK11SlotInfo
*slot
= NULL
;
1124 cert
= CERT_NewTempCertificate(CERT_GetDefaultCertDB(),
1125 derCert
, NULL
, PR_FALSE
, PR_TRUE
);
1126 if (cert
== NULL
) return NULL
;
1128 slot
= PK11_ImportCertForKey(cert
, nickname
, wincx
);
1129 CERT_DestroyCertificate (cert
);
1133 static CK_OBJECT_HANDLE
1134 pk11_FindCertObjectByTemplate(PK11SlotInfo
**slotPtr
,
1135 CK_ATTRIBUTE
*searchTemplate
, int count
, void *wincx
) {
1137 PK11SlotListElement
*le
;
1138 CK_OBJECT_HANDLE certHandle
= CK_INVALID_HANDLE
;
1139 PK11SlotInfo
*slot
= NULL
;
1145 list
= PK11_GetAllTokens(CKM_INVALID_MECHANISM
,PR_FALSE
,PR_TRUE
,wincx
);
1147 return CK_INVALID_HANDLE
;
1151 /* Look for the slot that holds the Key */
1152 for (le
= list
->head
; le
; le
= le
->next
) {
1153 rv
= pk11_AuthenticateUnfriendly(le
->slot
, PR_TRUE
, wincx
);
1154 if (rv
!= SECSuccess
) continue;
1156 certHandle
= pk11_FindObjectByTemplate(le
->slot
,searchTemplate
,count
);
1157 if (certHandle
!= CK_INVALID_HANDLE
) {
1158 slot
= PK11_ReferenceSlot(le
->slot
);
1163 PK11_FreeSlotList(list
);
1166 return CK_INVALID_HANDLE
;
1173 PK11_FindCertByIssuerAndSNOnToken(PK11SlotInfo
*slot
,
1174 CERTIssuerAndSN
*issuerSN
, void *wincx
)
1176 CERTCertificate
*rvCert
= NULL
;
1177 NSSCertificate
*cert
= NULL
;
1178 NSSDER issuer
, serial
;
1179 NSSTrustDomain
*td
= STAN_GetDefaultTrustDomain();
1180 NSSToken
*token
= slot
->nssToken
;
1181 nssSession
*session
;
1182 nssCryptokiObject
*instance
= NULL
;
1183 nssPKIObject
*object
= NULL
;
1188 if (token
== NULL
) {
1189 PORT_SetError(SEC_ERROR_NO_TOKEN
);
1194 /* PKCS#11 needs to use DER-encoded serial numbers. Create a
1195 * CERTIssuerAndSN that actually has the encoded value and pass that
1196 * to PKCS#11 (and the crypto context).
1198 derSerial
= SEC_ASN1EncodeItem(NULL
, NULL
,
1199 &issuerSN
->serialNumber
,
1200 SEC_IntegerTemplate
);
1205 NSSITEM_FROM_SECITEM(&issuer
, &issuerSN
->derIssuer
);
1206 NSSITEM_FROM_SECITEM(&serial
, derSerial
);
1208 session
= nssToken_GetDefaultSession(token
);
1213 instance
= nssToken_FindCertificateByIssuerAndSerialNumber(token
,session
,
1214 &issuer
, &serial
, nssTokenSearchType_TokenForced
, &status
);
1216 SECITEM_FreeItem(derSerial
, PR_TRUE
);
1221 object
= nssPKIObject_Create(NULL
, instance
, td
, NULL
, nssPKIMonitor
);
1225 instance
= NULL
; /* adopted by the previous call */
1226 cert
= nssCertificate_Create(object
);
1230 object
= NULL
; /* adopted by the previous call */
1231 nssTrustDomain_AddCertsToCache(td
, &cert
,1);
1232 /* on failure, cert is freed below */
1233 rvCert
= STAN_GetCERTCertificate(cert
);
1241 nssCryptokiObject_Destroy(instance
);
1244 nssPKIObject_Destroy(object
);
1247 nssCertificate_Destroy(cert
);
1253 * We're looking for a cert which we have the private key for that's on the
1254 * list of recipients. This searches one slot.
1255 * this is the new version for NSS SMIME code
1256 * this stuff should REALLY be in the SMIME code, but some things in here are not public
1259 static CERTCertificate
*
1260 pk11_FindCertObjectByRecipientNew(PK11SlotInfo
*slot
, NSSCMSRecipient
**recipientlist
, int *rlIndex
, void *pwarg
)
1262 NSSCMSRecipient
*ri
= NULL
;
1265 for (i
=0; (ri
= recipientlist
[i
]) != NULL
; i
++) {
1266 CERTCertificate
*cert
= NULL
;
1267 if (ri
->kind
== RLSubjKeyID
) {
1268 SECItem
*derCert
= cert_FindDERCertBySubjectKeyID(ri
->id
.subjectKeyID
);
1270 cert
= PK11_FindCertFromDERCertItem(slot
, derCert
, pwarg
);
1271 SECITEM_FreeItem(derCert
, PR_TRUE
);
1274 cert
= PK11_FindCertByIssuerAndSNOnToken(slot
, ri
->id
.issuerAndSN
,
1278 /* this isn't our cert */
1279 if ((cert
->trust
== NULL
) ||
1280 ((cert
->trust
->emailFlags
& CERTDB_USER
) != CERTDB_USER
)) {
1281 CERT_DestroyCertificate(cert
);
1284 ri
->slot
= PK11_ReferenceSlot(slot
);
1294 * This function is the same as above, but it searches all the slots.
1295 * this is the new version for NSS SMIME code
1296 * this stuff should REALLY be in the SMIME code, but some things in here are not public
1299 static CERTCertificate
*
1300 pk11_AllFindCertObjectByRecipientNew(NSSCMSRecipient
**recipientlist
, void *wincx
, int *rlIndex
)
1303 PK11SlotListElement
*le
;
1304 CERTCertificate
*cert
= NULL
;
1308 list
= PK11_GetAllTokens(CKM_INVALID_MECHANISM
,PR_FALSE
,PR_TRUE
,wincx
);
1310 return CK_INVALID_HANDLE
;
1313 /* Look for the slot that holds the Key */
1314 for (le
= list
->head
; le
; le
= le
->next
) {
1315 rv
= pk11_AuthenticateUnfriendly(le
->slot
, PR_TRUE
, wincx
);
1316 if (rv
!= SECSuccess
) continue;
1318 cert
= pk11_FindCertObjectByRecipientNew(le
->slot
,
1319 recipientlist
, rlIndex
, wincx
);
1324 PK11_FreeSlotList(list
);
1330 * We're looking for a cert which we have the private key for that's on the
1331 * list of recipients. This searches one slot.
1333 static CERTCertificate
*
1334 pk11_FindCertObjectByRecipient(PK11SlotInfo
*slot
,
1335 SEC_PKCS7RecipientInfo
**recipientArray
,
1336 SEC_PKCS7RecipientInfo
**rip
, void *pwarg
)
1338 SEC_PKCS7RecipientInfo
*ri
= NULL
;
1341 for (i
=0; (ri
= recipientArray
[i
]) != NULL
; i
++) {
1342 CERTCertificate
*cert
;
1344 cert
= PK11_FindCertByIssuerAndSNOnToken(slot
, ri
->issuerAndSN
,
1347 /* this isn't our cert */
1348 if ((cert
->trust
== NULL
) ||
1349 ((cert
->trust
->emailFlags
& CERTDB_USER
) != CERTDB_USER
)) {
1350 CERT_DestroyCertificate(cert
);
1363 * This function is the same as above, but it searches all the slots.
1365 static CERTCertificate
*
1366 pk11_AllFindCertObjectByRecipient(PK11SlotInfo
**slotPtr
,
1367 SEC_PKCS7RecipientInfo
**recipientArray
,SEC_PKCS7RecipientInfo
**rip
,
1370 PK11SlotListElement
*le
;
1371 CERTCertificate
* cert
= NULL
;
1372 PK11SlotInfo
*slot
= NULL
;
1378 list
= PK11_GetAllTokens(CKM_INVALID_MECHANISM
,PR_FALSE
,PR_TRUE
,wincx
);
1380 return CK_INVALID_HANDLE
;
1385 /* Look for the slot that holds the Key */
1386 for (le
= list
->head
; le
; le
= le
->next
) {
1387 rv
= pk11_AuthenticateUnfriendly(le
->slot
, PR_TRUE
, wincx
);
1388 if (rv
!= SECSuccess
) continue;
1390 cert
= pk11_FindCertObjectByRecipient(le
->slot
, recipientArray
,
1393 slot
= PK11_ReferenceSlot(le
->slot
);
1398 PK11_FreeSlotList(list
);
1404 PORT_Assert(cert
!= NULL
);
1409 * We need to invert the search logic for PKCS 7 because if we search for
1410 * each cert on the list over all the slots, we wind up with lots of spurious
1411 * password prompts. This way we get only one password prompt per slot, at
1412 * the max, and most of the time we can find the cert, and only prompt for
1416 PK11_FindCertAndKeyByRecipientList(PK11SlotInfo
**slotPtr
,
1417 SEC_PKCS7RecipientInfo
**array
, SEC_PKCS7RecipientInfo
**rip
,
1418 SECKEYPrivateKey
**privKey
, void *wincx
)
1420 CERTCertificate
*cert
= NULL
;
1424 cert
= pk11_AllFindCertObjectByRecipient(slotPtr
,array
,rip
,wincx
);
1429 *privKey
= PK11_FindKeyByAnyCert(cert
, wincx
);
1430 if (*privKey
== NULL
) {
1436 if (cert
) CERT_DestroyCertificate(cert
);
1437 if (*slotPtr
) PK11_FreeSlot(*slotPtr
);
1442 static PRCallOnceType keyIDHashCallOnce
;
1444 static PRStatus PR_CALLBACK
1445 pk11_keyIDHash_populate(void *wincx
)
1447 CERTCertList
*certList
;
1448 CERTCertListNode
*node
= NULL
;
1449 SECItem subjKeyID
= {siBuffer
, NULL
, 0};
1451 certList
= PK11_ListCerts(PK11CertListUser
, wincx
);
1456 for (node
= CERT_LIST_HEAD(certList
);
1457 !CERT_LIST_END(node
, certList
);
1458 node
= CERT_LIST_NEXT(node
)) {
1459 if (CERT_FindSubjectKeyIDExtension(node
->cert
,
1460 &subjKeyID
) == SECSuccess
&&
1461 subjKeyID
.data
!= NULL
) {
1462 cert_AddSubjectKeyIDMapping(&subjKeyID
, node
->cert
);
1463 SECITEM_FreeItem(&subjKeyID
, PR_FALSE
);
1466 CERT_DestroyCertList(certList
);
1471 * This is the new version of the above function for NSS SMIME code
1472 * this stuff should REALLY be in the SMIME code, but some things in here are not public
1476 PK11_FindCertAndKeyByRecipientListNew(NSSCMSRecipient
**recipientlist
, void *wincx
)
1478 CERTCertificate
*cert
;
1479 NSSCMSRecipient
*rl
;
1483 rv
= PR_CallOnceWithArg(&keyIDHashCallOnce
, pk11_keyIDHash_populate
, wincx
);
1484 if (rv
!= PR_SUCCESS
)
1487 cert
= pk11_AllFindCertObjectByRecipientNew(recipientlist
, wincx
, &rlIndex
);
1492 rl
= recipientlist
[rlIndex
];
1494 /* at this point, rl->slot is set */
1496 rl
->privkey
= PK11_FindKeyByAnyCert(cert
, wincx
);
1497 if (rl
->privkey
== NULL
) {
1501 /* make a cert from the cert handle */
1506 if (cert
) CERT_DestroyCertificate(cert
);
1507 if (rl
->slot
) PK11_FreeSlot(rl
->slot
);
1513 PK11_FindCertByIssuerAndSN(PK11SlotInfo
**slotPtr
, CERTIssuerAndSN
*issuerSN
,
1516 CERTCertificate
*rvCert
= NULL
;
1517 NSSCertificate
*cert
;
1518 NSSDER issuer
, serial
;
1519 NSSCryptoContext
*cc
;
1522 if (slotPtr
) *slotPtr
= NULL
;
1524 /* PKCS#11 needs to use DER-encoded serial numbers. Create a
1525 * CERTIssuerAndSN that actually has the encoded value and pass that
1526 * to PKCS#11 (and the crypto context).
1528 derSerial
= SEC_ASN1EncodeItem(NULL
, NULL
,
1529 &issuerSN
->serialNumber
,
1530 SEC_IntegerTemplate
);
1535 NSSITEM_FROM_SECITEM(&issuer
, &issuerSN
->derIssuer
);
1536 NSSITEM_FROM_SECITEM(&serial
, derSerial
);
1538 cc
= STAN_GetDefaultCryptoContext();
1539 cert
= NSSCryptoContext_FindCertificateByIssuerAndSerialNumber(cc
,
1543 SECITEM_FreeItem(derSerial
, PR_TRUE
);
1544 return STAN_GetCERTCertificateOrRelease(cert
);
1548 /* free the old cert on retry. Associated slot was not present */
1550 CERT_DestroyCertificate(rvCert
);
1554 cert
= NSSTrustDomain_FindCertificateByIssuerAndSerialNumber(
1555 STAN_GetDefaultTrustDomain(),
1562 rvCert
= STAN_GetCERTCertificateOrRelease(cert
);
1563 if (rvCert
== NULL
) {
1567 /* Check to see if the cert's token is still there */
1568 } while (!PK11_IsPresent(rvCert
->slot
));
1570 if (rvCert
&& slotPtr
) *slotPtr
= PK11_ReferenceSlot(rvCert
->slot
);
1572 SECITEM_FreeItem(derSerial
, PR_TRUE
);
1577 PK11_FindObjectForCert(CERTCertificate
*cert
, void *wincx
, PK11SlotInfo
**pSlot
)
1579 CK_OBJECT_HANDLE certHandle
;
1580 CK_ATTRIBUTE searchTemplate
= { CKA_VALUE
, NULL
, 0 };
1582 PK11_SETATTRS(&searchTemplate
, CKA_VALUE
, cert
->derCert
.data
,
1586 certHandle
= pk11_getcerthandle(cert
->slot
,cert
,&searchTemplate
,1);
1587 if (certHandle
!= CK_INVALID_HANDLE
) {
1588 *pSlot
= PK11_ReferenceSlot(cert
->slot
);
1593 certHandle
= pk11_FindCertObjectByTemplate(pSlot
,&searchTemplate
,1,wincx
);
1594 if (certHandle
!= CK_INVALID_HANDLE
) {
1595 if (cert
->slot
== NULL
) {
1596 cert
->slot
= PK11_ReferenceSlot(*pSlot
);
1597 cert
->pkcs11ID
= certHandle
;
1598 cert
->ownSlot
= PR_TRUE
;
1599 cert
->series
= cert
->slot
->series
;
1607 PK11_FindKeyByAnyCert(CERTCertificate
*cert
, void *wincx
)
1609 CK_OBJECT_HANDLE certHandle
;
1610 CK_OBJECT_HANDLE keyHandle
;
1611 PK11SlotInfo
*slot
= NULL
;
1612 SECKEYPrivateKey
*privKey
= NULL
;
1617 certHandle
= PK11_FindObjectForCert(cert
, wincx
, &slot
);
1618 if (certHandle
== CK_INVALID_HANDLE
) {
1622 * prevent a login race condition. If slot is logged in between
1623 * our call to pk11_LoginStillRequired and the
1624 * PK11_MatchItem. The matchItem call will either succeed, or
1625 * we will call it one more time after calling PK11_Authenticate
1626 * (which is a noop on an authenticated token).
1628 needLogin
= pk11_LoginStillRequired(slot
,wincx
);
1629 keyHandle
= PK11_MatchItem(slot
,certHandle
,CKO_PRIVATE_KEY
);
1630 if ((keyHandle
== CK_INVALID_HANDLE
) && needLogin
&&
1631 (SSL_ERROR_NO_CERTIFICATE
== (err
= PORT_GetError()) ||
1632 SEC_ERROR_TOKEN_NOT_LOGGED_IN
== err
) ) {
1633 /* authenticate and try again */
1634 rv
= PK11_Authenticate(slot
, PR_TRUE
, wincx
);
1635 if (rv
== SECSuccess
) {
1636 keyHandle
= PK11_MatchItem(slot
,certHandle
,CKO_PRIVATE_KEY
);
1639 if (keyHandle
!= CK_INVALID_HANDLE
) {
1640 privKey
= PK11_MakePrivKey(slot
, nullKey
, PR_TRUE
, keyHandle
, wincx
);
1643 PK11_FreeSlot(slot
);
1649 pk11_FindPubKeyByAnyCert(CERTCertificate
*cert
, PK11SlotInfo
**slot
, void *wincx
)
1651 CK_OBJECT_HANDLE certHandle
;
1652 CK_OBJECT_HANDLE keyHandle
;
1654 certHandle
= PK11_FindObjectForCert(cert
, wincx
, slot
);
1655 if (certHandle
== CK_INVALID_HANDLE
) {
1656 return CK_INVALID_HANDLE
;
1658 keyHandle
= PK11_MatchItem(*slot
,certHandle
,CKO_PUBLIC_KEY
);
1659 if (keyHandle
== CK_INVALID_HANDLE
) {
1660 PK11_FreeSlot(*slot
);
1661 return CK_INVALID_HANDLE
;
1667 * find the number of certs in the slot with the same subject name
1670 PK11_NumberCertsForCertSubject(CERTCertificate
*cert
)
1672 CK_OBJECT_CLASS certClass
= CKO_CERTIFICATE
;
1673 CK_ATTRIBUTE theTemplate
[] = {
1674 { CKA_CLASS
, NULL
, 0 },
1675 { CKA_SUBJECT
, NULL
, 0 },
1677 CK_ATTRIBUTE
*attr
= theTemplate
;
1678 int templateSize
= sizeof(theTemplate
)/sizeof(theTemplate
[0]);
1680 PK11_SETATTRS(attr
,CKA_CLASS
, &certClass
, sizeof(certClass
)); attr
++;
1681 PK11_SETATTRS(attr
,CKA_SUBJECT
,cert
->derSubject
.data
,cert
->derSubject
.len
);
1683 if (cert
->slot
== NULL
) {
1684 PK11SlotList
*list
= PK11_GetAllTokens(CKM_INVALID_MECHANISM
,
1685 PR_FALSE
,PR_TRUE
,NULL
);
1686 PK11SlotListElement
*le
;
1690 /* error code is set */
1694 /* loop through all the fortezza tokens */
1695 for (le
= list
->head
; le
; le
= le
->next
) {
1696 count
+= PK11_NumberObjectsFor(le
->slot
,theTemplate
,templateSize
);
1698 PK11_FreeSlotList(list
);
1702 return PK11_NumberObjectsFor(cert
->slot
,theTemplate
,templateSize
);
1706 * Walk all the certs with the same subject
1709 PK11_TraverseCertsForSubject(CERTCertificate
*cert
,
1710 SECStatus(* callback
)(CERTCertificate
*, void *), void *arg
)
1715 if (cert
->slot
== NULL
) {
1716 PK11SlotList
*list
= PK11_GetAllTokens(CKM_INVALID_MECHANISM
,
1717 PR_FALSE
,PR_TRUE
,NULL
);
1718 PK11SlotListElement
*le
;
1721 /* error code is set */
1724 /* loop through all the tokens */
1725 for (le
= list
->head
; le
; le
= le
->next
) {
1726 PK11_TraverseCertsForSubjectInSlot(cert
,le
->slot
,callback
,arg
);
1728 PK11_FreeSlotList(list
);
1733 return PK11_TraverseCertsForSubjectInSlot(cert
, cert
->slot
, callback
, arg
);
1737 PK11_TraverseCertsForSubjectInSlot(CERTCertificate
*cert
, PK11SlotInfo
*slot
,
1738 SECStatus(* callback
)(CERTCertificate
*, void *), void *arg
)
1740 PRStatus nssrv
= PR_SUCCESS
;
1744 nssList
*subjectList
;
1745 nssPKIObjectCollection
*collection
;
1746 nssCryptokiObject
**instances
;
1747 NSSCertificate
**certs
;
1748 nssTokenSearchType tokenOnly
= nssTokenSearchType_TokenOnly
;
1749 td
= STAN_GetDefaultTrustDomain();
1750 NSSITEM_FROM_SECITEM(&subject
, &cert
->derSubject
);
1751 token
= PK11Slot_GetNSSToken(slot
);
1752 if (!nssToken_IsPresent(token
)) {
1755 collection
= nssCertificateCollection_Create(td
, NULL
);
1759 subjectList
= nssList_Create(NULL
, PR_FALSE
);
1761 nssPKIObjectCollection_Destroy(collection
);
1764 (void)nssTrustDomain_GetCertsForSubjectFromCache(td
, &subject
,
1766 transfer_token_certs_to_collection(subjectList
, token
, collection
);
1767 instances
= nssToken_FindCertificatesBySubject(token
, NULL
,
1769 tokenOnly
, 0, &nssrv
);
1770 nssPKIObjectCollection_AddInstances(collection
, instances
, 0);
1771 nss_ZFreeIf(instances
);
1772 nssList_Destroy(subjectList
);
1773 certs
= nssPKIObjectCollection_GetCertificates(collection
,
1775 nssPKIObjectCollection_Destroy(collection
);
1777 CERTCertificate
*oldie
;
1778 NSSCertificate
**cp
;
1779 for (cp
= certs
; *cp
; cp
++) {
1780 oldie
= STAN_GetCERTCertificate(*cp
);
1784 if ((*callback
)(oldie
, arg
) != SECSuccess
) {
1789 nssCertificateArray_Destroy(certs
);
1791 return (nssrv
== PR_SUCCESS
) ? SECSuccess
: SECFailure
;
1795 PK11_TraverseCertsForNicknameInSlot(SECItem
*nickname
, PK11SlotInfo
*slot
,
1796 SECStatus(* callback
)(CERTCertificate
*, void *), void *arg
)
1798 struct nss3_cert_cbstr pk11cb
;
1799 PRStatus nssrv
= PR_SUCCESS
;
1803 PRBool created
= PR_FALSE
;
1804 nssCryptokiObject
**instances
;
1805 nssPKIObjectCollection
*collection
= NULL
;
1806 NSSCertificate
**certs
;
1807 nssList
*nameList
= NULL
;
1808 nssTokenSearchType tokenOnly
= nssTokenSearchType_TokenOnly
;
1809 pk11cb
.callback
= callback
;
1811 token
= PK11Slot_GetNSSToken(slot
);
1812 if (!nssToken_IsPresent(token
)) {
1815 if (nickname
->data
[nickname
->len
-1] != '\0') {
1816 nick
= nssUTF8_Create(NULL
, nssStringType_UTF8String
,
1817 nickname
->data
, nickname
->len
);
1820 nick
= (NSSUTF8
*)nickname
->data
;
1822 td
= STAN_GetDefaultTrustDomain();
1823 collection
= nssCertificateCollection_Create(td
, NULL
);
1827 nameList
= nssList_Create(NULL
, PR_FALSE
);
1831 (void)nssTrustDomain_GetCertsForNicknameFromCache(td
, nick
, nameList
);
1832 transfer_token_certs_to_collection(nameList
, token
, collection
);
1833 instances
= nssToken_FindCertificatesByNickname(token
, NULL
,
1835 tokenOnly
, 0, &nssrv
);
1836 nssPKIObjectCollection_AddInstances(collection
, instances
, 0);
1837 nss_ZFreeIf(instances
);
1838 nssList_Destroy(nameList
);
1839 certs
= nssPKIObjectCollection_GetCertificates(collection
,
1841 nssPKIObjectCollection_Destroy(collection
);
1843 CERTCertificate
*oldie
;
1844 NSSCertificate
**cp
;
1845 for (cp
= certs
; *cp
; cp
++) {
1846 oldie
= STAN_GetCERTCertificate(*cp
);
1850 if ((*callback
)(oldie
, arg
) != SECSuccess
) {
1855 nssCertificateArray_Destroy(certs
);
1857 if (created
) nss_ZFreeIf(nick
);
1858 return (nssrv
== PR_SUCCESS
) ? SECSuccess
: SECFailure
;
1864 nssPKIObjectCollection_Destroy(collection
);
1867 nssList_Destroy(nameList
);
1873 PK11_TraverseCertsInSlot(PK11SlotInfo
*slot
,
1874 SECStatus(* callback
)(CERTCertificate
*, void *), void *arg
)
1877 NSSTrustDomain
*td
= STAN_GetDefaultTrustDomain();
1879 nssList
*certList
= NULL
;
1880 nssCryptokiObject
**instances
;
1881 nssPKIObjectCollection
*collection
;
1882 NSSCertificate
**certs
;
1883 nssTokenSearchType tokenOnly
= nssTokenSearchType_TokenOnly
;
1884 tok
= PK11Slot_GetNSSToken(slot
);
1885 if (!nssToken_IsPresent(tok
)) {
1888 collection
= nssCertificateCollection_Create(td
, NULL
);
1892 certList
= nssList_Create(NULL
, PR_FALSE
);
1894 nssPKIObjectCollection_Destroy(collection
);
1897 (void *)nssTrustDomain_GetCertsFromCache(td
, certList
);
1898 transfer_token_certs_to_collection(certList
, tok
, collection
);
1899 instances
= nssToken_FindCertificates(tok
, NULL
,
1900 tokenOnly
, 0, &nssrv
);
1901 nssPKIObjectCollection_AddInstances(collection
, instances
, 0);
1902 nss_ZFreeIf(instances
);
1903 nssList_Destroy(certList
);
1904 certs
= nssPKIObjectCollection_GetCertificates(collection
,
1906 nssPKIObjectCollection_Destroy(collection
);
1908 CERTCertificate
*oldie
;
1909 NSSCertificate
**cp
;
1910 for (cp
= certs
; *cp
; cp
++) {
1911 oldie
= STAN_GetCERTCertificate(*cp
);
1915 if ((*callback
)(oldie
, arg
) != SECSuccess
) {
1920 nssCertificateArray_Destroy(certs
);
1922 return (nssrv
== PR_SUCCESS
) ? SECSuccess
: SECFailure
;
1926 * return the certificate associated with a derCert
1929 PK11_FindCertFromDERCert(PK11SlotInfo
*slot
, CERTCertificate
*cert
,
1932 return PK11_FindCertFromDERCertItem(slot
, &cert
->derCert
, wincx
);
1936 PK11_FindCertFromDERCertItem(PK11SlotInfo
*slot
, SECItem
*inDerCert
,
1943 NSSTrustDomain
*td
= STAN_GetDefaultTrustDomain();
1946 tok
= PK11Slot_GetNSSToken(slot
);
1947 NSSITEM_FROM_SECITEM(&derCert
, inDerCert
);
1948 rv
= pk11_AuthenticateUnfriendly(slot
, PR_TRUE
, wincx
);
1949 if (rv
!= SECSuccess
) {
1950 PK11_FreeSlot(slot
);
1953 c
= NSSTrustDomain_FindCertificateByEncodedCertificate(td
, &derCert
);
1955 PRBool isToken
= PR_FALSE
;
1957 NSSToken
**tokens
= nssPKIObject_GetTokens(&c
->object
, NULL
);
1959 for (tp
= tokens
; *tp
; tp
++) {
1966 NSSCertificate_Destroy(c
);
1969 nssTokenArray_Destroy(tokens
);
1972 return c
? STAN_GetCERTCertificateOrRelease(c
) : NULL
;
1975 /* mcgreer 3.4 -- nobody uses this, ignoring */
1977 * return the certificate associated with a derCert
1980 PK11_FindCertFromDERSubjectAndNickname(PK11SlotInfo
*slot
,
1981 CERTCertificate
*cert
,
1982 char *nickname
, void *wincx
)
1984 CK_OBJECT_CLASS certClass
= CKO_CERTIFICATE
;
1985 CK_ATTRIBUTE theTemplate
[] = {
1986 { CKA_SUBJECT
, NULL
, 0 },
1987 { CKA_LABEL
, NULL
, 0 },
1988 { CKA_CLASS
, NULL
, 0 }
1990 /* if you change the array, change the variable below as well */
1991 int tsize
= sizeof(theTemplate
)/sizeof(theTemplate
[0]);
1992 CK_OBJECT_HANDLE certh
;
1993 CK_ATTRIBUTE
*attrs
= theTemplate
;
1996 PK11_SETATTRS(attrs
, CKA_SUBJECT
, cert
->derSubject
.data
,
1997 cert
->derSubject
.len
); attrs
++;
1998 PK11_SETATTRS(attrs
, CKA_LABEL
, nickname
, PORT_Strlen(nickname
));
1999 PK11_SETATTRS(attrs
, CKA_CLASS
, &certClass
, sizeof(certClass
));
2004 rv
= pk11_AuthenticateUnfriendly(slot
, PR_TRUE
, wincx
);
2005 if (rv
!= SECSuccess
) return NULL
;
2007 certh
= pk11_getcerthandle(slot
,cert
,theTemplate
,tsize
);
2008 if (certh
== CK_INVALID_HANDLE
) {
2012 return PK11_MakeCertFromHandle(slot
, certh
, NULL
);
2016 * import a cert for a private key we have already generated. Set the label
2017 * on both to be the nickname.
2019 static CK_OBJECT_HANDLE
2020 pk11_findKeyObjectByDERCert(PK11SlotInfo
*slot
, CERTCertificate
*cert
,
2024 CK_OBJECT_HANDLE key
;
2029 if((slot
== NULL
) || (cert
== NULL
)) {
2030 return CK_INVALID_HANDLE
;
2033 keyID
= pk11_mkcertKeyID(cert
);
2035 return CK_INVALID_HANDLE
;
2039 * prevent a login race condition. If slot is logged in between
2040 * our call to pk11_LoginStillRequired and the
2041 * pk11_FindPrivateKeyFromCerID. The matchItem call will either succeed, or
2042 * we will call it one more time after calling PK11_Authenticate
2043 * (which is a noop on an authenticated token).
2045 needLogin
= pk11_LoginStillRequired(slot
,wincx
);
2046 key
= pk11_FindPrivateKeyFromCertID(slot
, keyID
);
2047 if ((key
== CK_INVALID_HANDLE
) && needLogin
&&
2048 (SSL_ERROR_NO_CERTIFICATE
== (err
= PORT_GetError()) ||
2049 SEC_ERROR_TOKEN_NOT_LOGGED_IN
== err
)) {
2050 /* authenticate and try again */
2051 rv
= PK11_Authenticate(slot
, PR_TRUE
, wincx
);
2052 if (rv
!= SECSuccess
) goto loser
;
2053 key
= pk11_FindPrivateKeyFromCertID(slot
, keyID
);
2057 SECITEM_ZfreeItem(keyID
, PR_TRUE
);
2062 PK11_FindKeyByDERCert(PK11SlotInfo
*slot
, CERTCertificate
*cert
,
2065 CK_OBJECT_HANDLE keyHandle
;
2067 if((slot
== NULL
) || (cert
== NULL
)) {
2071 keyHandle
= pk11_findKeyObjectByDERCert(slot
, cert
, wincx
);
2072 if (keyHandle
== CK_INVALID_HANDLE
) {
2076 return PK11_MakePrivKey(slot
,nullKey
,PR_TRUE
,keyHandle
,wincx
);
2080 PK11_ImportCertForKeyToSlot(PK11SlotInfo
*slot
, CERTCertificate
*cert
,
2082 PRBool addCertUsage
,void *wincx
)
2084 CK_OBJECT_HANDLE keyHandle
;
2086 if((slot
== NULL
) || (cert
== NULL
) || (nickname
== NULL
)) {
2090 keyHandle
= pk11_findKeyObjectByDERCert(slot
, cert
, wincx
);
2091 if (keyHandle
== CK_INVALID_HANDLE
) {
2095 return PK11_ImportCert(slot
, cert
, keyHandle
, nickname
, addCertUsage
);
2099 /* remove when the real version comes out */
2100 #define SEC_OID_MISSI_KEA 300 /* until we have v3 stuff merged */
2102 KEAPQGCompare(CERTCertificate
*server
,CERTCertificate
*cert
) {
2104 if ( SECKEY_KEAParamCompare(server
,cert
) == SECEqual
) {
2112 PK11_FortezzaHasKEA(CERTCertificate
*cert
) {
2113 /* look at the subject and see if it is a KEA for MISSI key */
2116 if ((cert
->trust
== NULL
) ||
2117 ((cert
->trust
->sslFlags
& CERTDB_USER
) != CERTDB_USER
)) {
2121 oid
= SECOID_FindOID(&cert
->subjectPublicKeyInfo
.algorithm
.algorithm
);
2126 return (PRBool
)((oid
->offset
== SEC_OID_MISSI_KEA_DSS_OLD
) ||
2127 (oid
->offset
== SEC_OID_MISSI_KEA_DSS
) ||
2128 (oid
->offset
== SEC_OID_MISSI_KEA
)) ;
2132 * Find a kea cert on this slot that matches the domain of it's peer
2134 static CERTCertificate
2135 *pk11_GetKEAMate(PK11SlotInfo
*slot
,CERTCertificate
*peer
)
2138 CERTCertificate
*returnedCert
= NULL
;
2140 for (i
=0; i
< slot
->cert_count
; i
++) {
2141 CERTCertificate
*cert
= slot
->cert_array
[i
];
2143 if (PK11_FortezzaHasKEA(cert
) && KEAPQGCompare(peer
,cert
)) {
2144 returnedCert
= CERT_DupCertificate(cert
);
2148 return returnedCert
;
2152 * The following is a FORTEZZA only Certificate request. We call this when we
2153 * are doing a non-client auth SSL connection. We are only interested in the
2154 * fortezza slots, and we are only interested in certs that share the same root
2155 * key as the server.
2158 PK11_FindBestKEAMatch(CERTCertificate
*server
, void *wincx
)
2160 PK11SlotList
*keaList
= PK11_GetAllTokens(CKM_KEA_KEY_DERIVE
,
2161 PR_FALSE
,PR_TRUE
,wincx
);
2162 PK11SlotListElement
*le
;
2163 CERTCertificate
*returnedCert
= NULL
;
2167 /* error code is set */
2171 /* loop through all the fortezza tokens */
2172 for (le
= keaList
->head
; le
; le
= le
->next
) {
2173 rv
= PK11_Authenticate(le
->slot
, PR_TRUE
, wincx
);
2174 if (rv
!= SECSuccess
) continue;
2175 if (le
->slot
->session
== CK_INVALID_SESSION
) {
2178 returnedCert
= pk11_GetKEAMate(le
->slot
,server
);
2179 if (returnedCert
) break;
2181 PK11_FreeSlotList(keaList
);
2183 return returnedCert
;
2187 * find a matched pair of kea certs to key exchange parameters from one
2188 * fortezza card to another as necessary.
2191 PK11_GetKEAMatchedCerts(PK11SlotInfo
*slot1
, PK11SlotInfo
*slot2
,
2192 CERTCertificate
**cert1
, CERTCertificate
**cert2
)
2194 CERTCertificate
*returnedCert
= NULL
;
2197 for (i
=0; i
< slot1
->cert_count
; i
++) {
2198 CERTCertificate
*cert
= slot1
->cert_array
[i
];
2200 if (PK11_FortezzaHasKEA(cert
)) {
2201 returnedCert
= pk11_GetKEAMate(slot2
,cert
);
2202 if (returnedCert
!= NULL
) {
2203 *cert2
= returnedCert
;
2204 *cert1
= CERT_DupCertificate(cert
);
2213 * return the private key From a given Cert
2216 PK11_FindCertInSlot(PK11SlotInfo
*slot
, CERTCertificate
*cert
, void *wincx
)
2218 CK_OBJECT_CLASS certClass
= CKO_CERTIFICATE
;
2219 CK_ATTRIBUTE theTemplate
[] = {
2220 { CKA_VALUE
, NULL
, 0 },
2221 { CKA_CLASS
, NULL
, 0 }
2223 /* if you change the array, change the variable below as well */
2224 int tsize
= sizeof(theTemplate
)/sizeof(theTemplate
[0]);
2225 CK_ATTRIBUTE
*attrs
= theTemplate
;
2228 PK11_SETATTRS(attrs
, CKA_VALUE
, cert
->derCert
.data
,
2229 cert
->derCert
.len
); attrs
++;
2230 PK11_SETATTRS(attrs
, CKA_CLASS
, &certClass
, sizeof(certClass
));
2235 rv
= pk11_AuthenticateUnfriendly(slot
, PR_TRUE
, wincx
);
2236 if (rv
!= SECSuccess
) {
2237 return CK_INVALID_HANDLE
;
2240 return pk11_getcerthandle(slot
,cert
,theTemplate
,tsize
);
2244 PK11_GetKeyIDFromCert(CERTCertificate
*cert
, void *wincx
)
2246 CK_OBJECT_HANDLE handle
;
2247 PK11SlotInfo
*slot
= NULL
;
2248 CK_ATTRIBUTE theTemplate
[] = {
2249 { CKA_ID
, NULL
, 0 },
2251 int tsize
= sizeof(theTemplate
)/sizeof(theTemplate
[0]);
2252 SECItem
*item
= NULL
;
2255 handle
= PK11_FindObjectForCert(cert
,wincx
,&slot
);
2256 if (handle
== CK_INVALID_HANDLE
) {
2260 crv
= PK11_GetAttributes(NULL
,slot
,handle
,theTemplate
,tsize
);
2261 if (crv
!= CKR_OK
) {
2262 PORT_SetError( PK11_MapError(crv
) );
2266 item
= PORT_ZNew(SECItem
);
2268 item
->data
= (unsigned char*) theTemplate
[0].pValue
;
2269 item
->len
= theTemplate
[0].ulValueLen
;
2273 PK11_FreeSlot(slot
);
2277 struct listCertsStr
{
2278 PK11CertListType type
;
2279 CERTCertList
*certList
;
2283 pk11ListCertCallback(NSSCertificate
*c
, void *arg
)
2285 struct listCertsStr
*listCertP
= (struct listCertsStr
*)arg
;
2286 CERTCertificate
*newCert
= NULL
;
2287 PK11CertListType type
= listCertP
->type
;
2288 CERTCertList
*certList
= listCertP
->certList
;
2289 PRBool isUnique
= PR_FALSE
;
2290 PRBool isCA
= PR_FALSE
;
2291 char *nickname
= NULL
;
2292 unsigned int certType
;
2294 if ((type
== PK11CertListUnique
) || (type
== PK11CertListRootUnique
) ||
2295 (type
== PK11CertListCAUnique
) || (type
== PK11CertListUserUnique
) ) {
2296 /* only list one instance of each certificate, even if several exist */
2299 if ((type
== PK11CertListCA
) || (type
== PK11CertListRootUnique
) ||
2300 (type
== PK11CertListCAUnique
)) {
2304 /* if we want user certs and we don't have one skip this cert */
2305 if ( ( (type
== PK11CertListUser
) || (type
== PK11CertListUserUnique
) ) &&
2306 !NSSCertificate_IsPrivateKeyAvailable(c
, NULL
,NULL
)) {
2310 /* PK11CertListRootUnique means we want CA certs without a private key.
2311 * This is for legacy app support . PK11CertListCAUnique should be used
2312 * instead to get all CA certs, regardless of private key
2314 if ((type
== PK11CertListRootUnique
) &&
2315 NSSCertificate_IsPrivateKeyAvailable(c
, NULL
,NULL
)) {
2319 /* caller still owns the reference to 'c' */
2320 newCert
= STAN_GetCERTCertificate(c
);
2324 /* if we want CA certs and it ain't one, skip it */
2325 if( isCA
&& (!CERT_IsCACert(newCert
, &certType
)) ) {
2329 CERT_DupCertificate(newCert
);
2331 nickname
= STAN_GetCERTCertificateName(certList
->arena
, c
);
2333 /* put slot certs at the end */
2334 if (newCert
->slot
&& !PK11_IsInternal(newCert
->slot
)) {
2335 CERT_AddCertToListTailWithData(certList
,newCert
,nickname
);
2337 CERT_AddCertToListHeadWithData(certList
,newCert
,nickname
);
2340 /* add multiple instances to the cert list */
2341 nssCryptokiObject
**ip
;
2342 nssCryptokiObject
**instances
= nssPKIObject_GetInstances(&c
->object
);
2346 for (ip
= instances
; *ip
; ip
++) {
2347 nssCryptokiObject
*instance
= *ip
;
2348 PK11SlotInfo
*slot
= instance
->token
->pk11slot
;
2350 /* put the same CERTCertificate in the list for all instances */
2351 CERT_DupCertificate(newCert
);
2353 nickname
= STAN_GetCERTCertificateNameForInstance(
2354 certList
->arena
, c
, instance
);
2356 /* put slot certs at the end */
2357 if (slot
&& !PK11_IsInternal(slot
)) {
2358 CERT_AddCertToListTailWithData(certList
,newCert
,nickname
);
2360 CERT_AddCertToListHeadWithData(certList
,newCert
,nickname
);
2363 nssCryptokiObjectArray_Destroy(instances
);
2370 PK11_ListCerts(PK11CertListType type
, void *pwarg
)
2372 NSSTrustDomain
*defaultTD
= STAN_GetDefaultTrustDomain();
2373 CERTCertList
*certList
= NULL
;
2374 struct listCertsStr listCerts
;
2375 certList
= CERT_NewCertList();
2376 listCerts
.type
= type
;
2377 listCerts
.certList
= certList
;
2379 /* authenticate to the slots */
2380 (void) pk11_TraverseAllSlots( NULL
, NULL
, PR_TRUE
, pwarg
);
2381 NSSTrustDomain_TraverseCertificates(defaultTD
, pk11ListCertCallback
,
2387 PK11_GetLowLevelKeyIDForCert(PK11SlotInfo
*slot
,
2388 CERTCertificate
*cert
, void *wincx
)
2390 CK_ATTRIBUTE theTemplate
[] = {
2391 { CKA_VALUE
, NULL
, 0 },
2392 { CKA_CLASS
, NULL
, 0 }
2394 /* if you change the array, change the variable below as well */
2395 int tsize
= sizeof(theTemplate
)/sizeof(theTemplate
[0]);
2396 CK_OBJECT_HANDLE certHandle
;
2397 CK_ATTRIBUTE
*attrs
= theTemplate
;
2398 PK11SlotInfo
*slotRef
= NULL
;
2403 PK11_SETATTRS(attrs
, CKA_VALUE
, cert
->derCert
.data
,
2404 cert
->derCert
.len
); attrs
++;
2406 rv
= pk11_AuthenticateUnfriendly(slot
, PR_TRUE
, wincx
);
2407 if (rv
!= SECSuccess
) {
2410 certHandle
= pk11_getcerthandle(slot
,cert
,theTemplate
,tsize
);
2412 certHandle
= PK11_FindObjectForCert(cert
, wincx
, &slotRef
);
2413 if (certHandle
== CK_INVALID_HANDLE
) {
2414 return pk11_mkcertKeyID(cert
);
2419 if (certHandle
== CK_INVALID_HANDLE
) {
2423 item
= pk11_GetLowLevelKeyFromHandle(slot
,certHandle
);
2424 if (slotRef
) PK11_FreeSlot(slotRef
);
2428 /* argument type for listCertsCallback */
2435 listCertsCallback(CERTCertificate
* cert
, void*arg
)
2437 ListCertsArg
*cdata
= (ListCertsArg
*)arg
;
2438 char *nickname
= NULL
;
2439 nssCryptokiObject
*instance
, **ci
;
2440 nssCryptokiObject
**instances
;
2441 NSSCertificate
*c
= STAN_GetNSSCertificate(cert
);
2446 instances
= nssPKIObject_GetInstances(&c
->object
);
2451 for (ci
= instances
; *ci
; ci
++) {
2452 if ((*ci
)->token
->pk11slot
== cdata
->slot
) {
2457 PORT_Assert(instance
!= NULL
);
2459 nssCryptokiObjectArray_Destroy(instances
);
2460 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE
);
2463 nickname
= STAN_GetCERTCertificateNameForInstance(cdata
->list
->arena
,
2465 nssCryptokiObjectArray_Destroy(instances
);
2467 return CERT_AddCertToListTailWithData(cdata
->list
,
2468 CERT_DupCertificate(cert
),nickname
);
2472 PK11_ListCertsInSlot(PK11SlotInfo
*slot
)
2475 CERTCertList
*certs
;
2478 certs
= CERT_NewCertList();
2479 if(certs
== NULL
) return NULL
;
2483 status
= PK11_TraverseCertsInSlot(slot
, listCertsCallback
,
2486 if( status
!= SECSuccess
) {
2487 CERT_DestroyCertList(certs
);
2495 PK11_GetAllSlotsForCert(CERTCertificate
*cert
, void *arg
)
2497 NSSCertificate
*c
= STAN_GetNSSCertificate(cert
);
2498 /* add multiple instances to the cert list */
2499 nssCryptokiObject
**ip
;
2500 nssCryptokiObject
**instances
= nssPKIObject_GetInstances(&c
->object
);
2501 PK11SlotList
*slotList
;
2502 PRBool found
= PR_FALSE
;
2505 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
2510 PORT_SetError(SEC_ERROR_NO_TOKEN
);
2514 slotList
= PK11_NewSlotList();
2516 nssCryptokiObjectArray_Destroy(instances
);
2520 for (ip
= instances
; *ip
; ip
++) {
2521 nssCryptokiObject
*instance
= *ip
;
2522 PK11SlotInfo
*slot
= instance
->token
->pk11slot
;
2524 PK11_AddSlotToList(slotList
, slot
);
2529 PK11_FreeSlotList(slotList
);
2530 PORT_SetError(SEC_ERROR_NO_TOKEN
);
2534 nssCryptokiObjectArray_Destroy(instances
);