diff options
author | relyea%netscape.com <devnull@localhost> | 2004-06-21 23:01:53 +0000 |
---|---|---|
committer | relyea%netscape.com <devnull@localhost> | 2004-06-21 23:01:53 +0000 |
commit | 1d771e02adae5ef24c69569c3163a08c6156af7e (patch) | |
tree | ae0db9acb686019363e5cde1c10bb675c0294c25 | |
parent | db2ae0729b55f63331b7b49903f6a1bd3863cb9f (diff) | |
download | nss-hg-1d771e02adae5ef24c69569c3163a08c6156af7e.tar.gz |
Bug 244914, 244907 r=nelsonb
Add support for unprotected private keys without requiring authentication.
Add support to access application specific PKCS #11 objects through NSS.
-rw-r--r-- | security/nss/lib/nss/nss.def | 14 | ||||
-rw-r--r-- | security/nss/lib/nss/nssinit.c | 5 | ||||
-rw-r--r-- | security/nss/lib/pk11wrap/debug_module.c | 10 | ||||
-rw-r--r-- | security/nss/lib/pk11wrap/pk11cert.c | 180 | ||||
-rw-r--r-- | security/nss/lib/pk11wrap/pk11func.h | 15 | ||||
-rw-r--r-- | security/nss/lib/pk11wrap/pk11skey.c | 258 | ||||
-rw-r--r-- | security/nss/lib/pk11wrap/pk11slot.c | 16 | ||||
-rw-r--r-- | security/nss/lib/pk11wrap/secmodi.h | 2 | ||||
-rw-r--r-- | security/nss/lib/pk11wrap/secmodt.h | 12 | ||||
-rw-r--r-- | security/nss/lib/pk11wrap/secmodti.h | 13 | ||||
-rw-r--r-- | security/nss/lib/util/secerr.h | 3 |
11 files changed, 433 insertions, 95 deletions
diff --git a/security/nss/lib/nss/nss.def b/security/nss/lib/nss/nss.def index e418135f6..2533a0748 100644 --- a/security/nss/lib/nss/nss.def +++ b/security/nss/lib/nss/nss.def @@ -783,6 +783,20 @@ SEC_DupCrl; ;+ local: ;+ *; ;+}; +;+NSS_3.9.2 { # NSS 3.9.2 release +;+ global: +NSS_IsInitialized; +PK11_DestroyGenericObject; +PK11_DestroyGenericObjects; +PK11_FindGenericObjects; +PK11_GetNextGenericObject; +PK11_GetPrevGenericObject; +PK11_LinkGenericObject; +PK11_ReadRawAttribute; +PK11_UnlinkGenericObject; +;+ local: +;+ *; +;+}; ;+NSS_3.10 { # NSS 3.10 release ;+ global: CERT_DecodeAltNameExtension; diff --git a/security/nss/lib/nss/nssinit.c b/security/nss/lib/nss/nssinit.c index 4b2a71c19..a7693b55c 100644 --- a/security/nss/lib/nss/nssinit.c +++ b/security/nss/lib/nss/nssinit.c @@ -568,6 +568,11 @@ NSS_Shutdown(void) return rv; } +PRBool +NSS_IsInitialized(void) +{ + return nss_IsInitted; +} extern const char __nss_base_rcsid[]; diff --git a/security/nss/lib/pk11wrap/debug_module.c b/security/nss/lib/pk11wrap/debug_module.c index dd9436396..3775f4ad1 100644 --- a/security/nss/lib/pk11wrap/debug_module.c +++ b/security/nss/lib/pk11wrap/debug_module.c @@ -152,11 +152,11 @@ static void get_attr_type_str(CK_ATTRIBUTE_TYPE atype, char *str, int len) } } -static void get_obj_class(CK_OBJECT_CLASS class, char *str, int len) +static void get_obj_class(CK_OBJECT_CLASS objClass, char *str, int len) { #define SETO(objc) \ PR_snprintf(str, len, "%s", objc); break; - switch (class) { + switch (objClass) { #ifndef AIX_64BIT case CKO_DATA: SETO("CKO_DATA"); case CKO_CERTIFICATE: SETO("CKO_CERTIFICATE"); @@ -170,7 +170,7 @@ static void get_obj_class(CK_OBJECT_CLASS class, char *str, int len) case CKO_NETSCAPE_TRUST: SETO("CKO_NETSCAPE_TRUST"); case CKO_NETSCAPE_BUILTIN_ROOT_LIST: SETO("CKO_NETSCAPE_BUILTIN_ROOT_LIST"); #endif - default: PR_snprintf(str, len, "0x%p", class); break; + default: PR_snprintf(str, len, "0x%p", objClass); break; } } @@ -226,8 +226,8 @@ static void print_attr_value(CK_ATTRIBUTE_PTR attr) } case CKA_CLASS: if (attr->ulValueLen > 0 && attr->pValue) { - CK_OBJECT_CLASS class = *((CK_OBJECT_CLASS *)attr->pValue); - get_obj_class(class, valstr, sizeof valstr); + CK_OBJECT_CLASS objClass = *((CK_OBJECT_CLASS *)attr->pValue); + get_obj_class(objClass, valstr, sizeof valstr); PR_LOG(modlog, 4, (" %s = %s [%d]", atype, valstr, attr->ulValueLen)); break; diff --git a/security/nss/lib/pk11wrap/pk11cert.c b/security/nss/lib/pk11wrap/pk11cert.c index c57e87687..1d120ac45 100644 --- a/security/nss/lib/pk11wrap/pk11cert.c +++ b/security/nss/lib/pk11wrap/pk11cert.c @@ -327,7 +327,7 @@ PK11_IsUserCert(PK11SlotInfo *slot, CERTCertificate *cert, if (cert == NULL) return PR_FALSE; theClass = CKO_PRIVATE_KEY; - if (!PK11_IsLoggedIn(slot,NULL) && PK11_NeedLogin(slot)) { + if (pk11_LoginStillRequired(slot,NULL)) { theClass = CKO_PUBLIC_KEY; } if (PK11_MatchItem(slot, certID , theClass) != CK_INVALID_HANDLE) { @@ -991,6 +991,21 @@ typedef struct pk11CertCallbackStr { void *callbackArg; } pk11CertCallback; + +/* + * Authenticate to "unfriendly" tokens (tokens which need to be logged + * in to find the certs. + */ +static SECStatus +pk11_AuthenticateUnfriendly(PK11SlotInfo *slot, PRBool loadCerts, void *wincx) +{ + SECStatus rv = SECSuccess; + if (!PK11_IsFriendly(slot)) { + rv = PK11_Authenticate(slot, loadCerts, wincx); + } + return rv; +} + /* * Extract all the certs on a card from a slot. */ @@ -1007,9 +1022,9 @@ pk11_TraverseAllSlots( SECStatus (*callback)(PK11SlotInfo *,void *), /* look at each slot and authenticate as necessary */ for (le = list->head ; le; le = le->next) { - if (!PK11_IsFriendly(le->slot)) { - rv = PK11_Authenticate(le->slot, PR_FALSE, wincx); - if (rv != SECSuccess) continue; + rv = pk11_AuthenticateUnfriendly(le->slot, PR_FALSE, wincx); + if (rv != SECSuccess) { + continue; } if (callback) { (*callback)(le->slot,arg); @@ -1186,13 +1201,11 @@ PK11_FindObjectsFromNickname(char *nickname,PK11SlotInfo **slotptr, return CK_INVALID_HANDLE; } - if (!PK11_IsFriendly(slot)) { - rv = PK11_Authenticate(slot, PR_TRUE, wincx); - if (rv != SECSuccess) { - PK11_FreeSlot(slot); - *slotptr = NULL; - return CK_INVALID_HANDLE; - } + rv = pk11_AuthenticateUnfriendly(slot, PR_TRUE, wincx); + if (rv != SECSuccess) { + PK11_FreeSlot(slot); + *slotptr = NULL; + return CK_INVALID_HANDLE; } findTemplate[0].pValue = nickname; @@ -1272,11 +1285,13 @@ PK11_FindCertFromNickname(char *nickname, void *wincx) NSSCertificate **certs = NULL; NSSUsage usage; NSSToken *token; + NSSTrustDomain *defaultTD = STAN_GetDefaultTrustDomain(); PK11SlotInfo *slot = NULL; + SECStatus rv; char *nickCopy; char *delimit = NULL; char *tokenName; - NSSTrustDomain *defaultTD = STAN_GetDefaultTrustDomain(); + usage.anyUsage = PR_TRUE; nickCopy = PORT_Strdup(nickname); if ((delimit = PORT_Strchr(nickCopy,':')) != NULL) { @@ -1301,10 +1316,9 @@ PK11_FindCertFromNickname(char *nickname, void *wincx) if (!PK11_IsPresent(slot)) { goto loser; } - if (!PK11_IsFriendly(slot)) { - if (PK11_Authenticate(slot, PR_TRUE, wincx) != SECSuccess) { - goto loser; - } + rv = pk11_AuthenticateUnfriendly(slot, PR_TRUE, wincx); + if (rv != SECSuccess) { + goto loser; } collection = nssCertificateCollection_Create(defaultTD, NULL); if (!collection) { @@ -1413,6 +1427,8 @@ PK11_FindCertsFromNickname(char *nickname, void *wincx) { NSSCertificate *c; NSSToken *token; PK11SlotInfo *slot; + SECStatus rv; + nickCopy = PORT_Strdup(nickname); if ((delimit = PORT_Strchr(nickCopy,':')) != NULL) { tokenName = nickCopy; @@ -1435,12 +1451,11 @@ PK11_FindCertsFromNickname(char *nickname, void *wincx) { nssList *nameList; nssCryptokiObject **instances; nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly; - if (!PK11_IsFriendly(slot)) { - if (PK11_Authenticate(slot, PR_TRUE, wincx) != SECSuccess) { - PK11_FreeSlot(slot); - if (nickCopy) PORT_Free(nickCopy); - return NULL; - } + rv = pk11_AuthenticateUnfriendly(slot, PR_TRUE, wincx); + if (rv != SECSuccess) { + PK11_FreeSlot(slot); + if (nickCopy) PORT_Free(nickCopy); + return NULL; } collection = nssCertificateCollection_Create(defaultTD, NULL); if (!collection) { @@ -1910,7 +1925,7 @@ PK11_FindPrivateKeyFromCert(PK11SlotInfo *slot, CERTCertificate *cert, /* * issue the find */ - rv = PK11_Authenticate(slot, PR_TRUE, wincx); + rv = pk11_AuthenticateUnfriendly(slot, PR_TRUE, wincx); if (rv != SECSuccess) { return NULL; } @@ -1920,7 +1935,19 @@ PK11_FindPrivateKeyFromCert(PK11SlotInfo *slot, CERTCertificate *cert, return NULL; } keyh = PK11_MatchItem(slot,certh,CKO_PRIVATE_KEY); - if (keyh == CK_INVALID_HANDLE) { return NULL; } + if ((keyh == CK_INVALID_HANDLE) && + (PORT_GetError() == SSL_ERROR_NO_CERTIFICATE) && + pk11_LoginStillRequired(slot, wincx)) { + /* try it again authenticated */ + rv = PK11_Authenticate(slot, PR_TRUE, wincx); + if (rv != SECSuccess) { + return NULL; + } + keyh = PK11_MatchItem(slot,certh,CKO_PRIVATE_KEY); + } + if (keyh == CK_INVALID_HANDLE) { + return NULL; + } return PK11_MakePrivKey(slot, nullKey, PR_TRUE, keyh, wincx); } @@ -1970,10 +1997,15 @@ PK11_KeyForCertExists(CERTCertificate *cert, CK_OBJECT_HANDLE *keyPtr, /* Look for the slot that holds the Key */ for (le = list->head ; le; le = le->next) { - rv = PK11_Authenticate(le->slot, PR_TRUE, wincx); - if (rv != SECSuccess) continue; - key = pk11_FindPrivateKeyFromCertID(le->slot,keyID); + if ((key == CK_INVALID_HANDLE) && + (PORT_GetError() == SSL_ERROR_NO_CERTIFICATE) && + pk11_LoginStillRequired(le->slot,wincx)) { + /* authenticate and try again */ + rv = PK11_Authenticate(le->slot, PR_TRUE, wincx); + if (rv != SECSuccess) continue; + key = pk11_FindPrivateKeyFromCertID(le->slot,keyID); + } if (key != CK_INVALID_HANDLE) { slot = PK11_ReferenceSlot(le->slot); if (keyPtr) *keyPtr = key; @@ -2061,10 +2093,8 @@ pk11_FindCertObjectByTemplate(PK11SlotInfo **slotPtr, /* Look for the slot that holds the Key */ for (le = list->head ; le; le = le->next) { - if (!PK11_IsFriendly(le->slot)) { - rv = PK11_Authenticate(le->slot, PR_TRUE, wincx); - if (rv != SECSuccess) continue; - } + rv = pk11_AuthenticateUnfriendly(le->slot, PR_TRUE, wincx); + if (rv != SECSuccess) continue; certHandle = pk11_FindObjectByTemplate(le->slot,searchTemplate,count); if (certHandle != CK_INVALID_HANDLE) { @@ -2225,10 +2255,8 @@ pk11_AllFindCertObjectByRecipientNew(NSSCMSRecipient **recipientlist, void *winc /* Look for the slot that holds the Key */ for (le = list->head ; le; le = le->next) { - if ( !PK11_IsFriendly(le->slot)) { - rv = PK11_Authenticate(le->slot, PR_TRUE, wincx); - if (rv != SECSuccess) continue; - } + rv = pk11_AuthenticateUnfriendly(le->slot, PR_TRUE, wincx); + if (rv != SECSuccess) continue; cert = pk11_FindCertObjectByRecipientNew(le->slot, recipientlist, rlIndex, wincx); @@ -2300,10 +2328,8 @@ pk11_AllFindCertObjectByRecipient(PK11SlotInfo **slotPtr, /* Look for the slot that holds the Key */ for (le = list->head ; le; le = le->next) { - if ( !PK11_IsFriendly(le->slot)) { - rv = PK11_Authenticate(le->slot, PR_TRUE, wincx); - if (rv != SECSuccess) continue; - } + rv = pk11_AuthenticateUnfriendly(le->slot, PR_TRUE, wincx); + if (rv != SECSuccess) continue; cert = pk11_FindCertObjectByRecipient(le->slot, recipientArray, rip, wincx); @@ -2345,11 +2371,6 @@ PK11_FindCertAndKeyByRecipientList(PK11SlotInfo **slotPtr, return NULL; } - rv = PK11_Authenticate(*slotPtr,PR_TRUE,wincx); - if (rv != SECSuccess) { - goto loser; - } - *privKey = PK11_FindKeyByAnyCert(cert, wincx); if (*privKey == NULL) { goto loser; @@ -2417,11 +2438,6 @@ PK11_FindCertAndKeyByRecipientListNew(NSSCMSRecipient **recipientlist, void *win /* at this point, rl->slot is set */ - /* authenticate to the token */ - if (PK11_Authenticate(rl->slot, PR_TRUE, wincx) != SECSuccess) { - goto loser; - } - rl->privkey = PK11_FindKeyByAnyCert(cert, wincx); if (rl->privkey == NULL) { goto loser; @@ -2557,25 +2573,32 @@ PK11_FindKeyByAnyCert(CERTCertificate *cert, void *wincx) CK_OBJECT_HANDLE certHandle; CK_OBJECT_HANDLE keyHandle; PK11SlotInfo *slot = NULL; - SECKEYPrivateKey *privKey; + SECKEYPrivateKey *privKey = NULL; SECStatus rv; certHandle = PK11_FindObjectForCert(cert, wincx, &slot); if (certHandle == CK_INVALID_HANDLE) { return NULL; } - rv = PK11_Authenticate(slot, PR_TRUE, wincx); - if (rv != SECSuccess) { - PK11_FreeSlot(slot); - return NULL; - } keyHandle = PK11_MatchItem(slot,certHandle,CKO_PRIVATE_KEY); - if (keyHandle == CK_INVALID_HANDLE) { - PK11_FreeSlot(slot); - return NULL; + if ((keyHandle == CK_INVALID_HANDLE) && + (PORT_GetError() == SSL_ERROR_NO_CERTIFICATE) && + pk11_LoginStillRequired(slot,wincx)) { + /* authenticate and try again */ + rv = PK11_Authenticate(slot, PR_TRUE, wincx); + if (rv != SECSuccess) { + goto loser; + } + keyHandle = PK11_MatchItem(slot,certHandle,CKO_PRIVATE_KEY); + if (keyHandle == CK_INVALID_HANDLE) { + goto loser; + } } privKey = PK11_MakePrivKey(slot, nullKey, PR_TRUE, keyHandle, wincx); - PK11_FreeSlot(slot); +loser: + if (slot) { + PK11_FreeSlot(slot); + } return privKey; } @@ -2962,13 +2985,14 @@ PK11_FindCertFromDERCertItem(PK11SlotInfo *slot, SECItem *inDerCert, NSSDER derCert; NSSToken *tok; NSSTrustDomain *td = STAN_GetDefaultTrustDomain(); + SECStatus rv; + tok = PK11Slot_GetNSSToken(slot); NSSITEM_FROM_SECITEM(&derCert, inDerCert); - if (!PK11_IsFriendly(slot)) { - if (PK11_Authenticate(slot, PR_TRUE, wincx) != SECSuccess) { - PK11_FreeSlot(slot); - return NULL; - } + rv = pk11_AuthenticateUnfriendly(slot, PR_TRUE, wincx); + if (rv != SECSuccess) { + PK11_FreeSlot(slot); + return NULL; } c = NSSTrustDomain_FindCertificateByEncodedCertificate(td, &derCert); if (c) { @@ -3024,10 +3048,8 @@ PK11_FindCertFromDERSubjectAndNickname(PK11SlotInfo *slot, /* * issue the find */ - if ( !PK11_IsFriendly(slot)) { - rv = PK11_Authenticate(slot, PR_TRUE, wincx); - if (rv != SECSuccess) return NULL; - } + rv = pk11_AuthenticateUnfriendly(slot, PR_TRUE, wincx); + if (rv != SECSuccess) return NULL; certh = pk11_getcerthandle(slot,cert,theTemplate,tsize); if (certh == CK_INVALID_HANDLE) { @@ -3058,12 +3080,15 @@ pk11_findKeyObjectByDERCert(PK11SlotInfo *slot, CERTCertificate *cert, return CK_INVALID_HANDLE; } - key = CK_INVALID_HANDLE; - - rv = PK11_Authenticate(slot, PR_TRUE, wincx); - if (rv != SECSuccess) goto loser; - key = pk11_FindPrivateKeyFromCertID(slot, keyID); + if ((key == CK_INVALID_HANDLE) && + (PORT_GetError() == SSL_ERROR_NO_CERTIFICATE) && + pk11_LoginStillRequired(slot,wincx)) { + /* authenticate and try again */ + rv = PK11_Authenticate(slot, PR_TRUE, wincx); + if (rv != SECSuccess) goto loser; + key = pk11_FindPrivateKeyFromCertID(slot, keyID); + } loser: SECITEM_ZfreeItem(keyID, PR_TRUE); @@ -3253,7 +3278,7 @@ PK11_FindCertInSlot(PK11SlotInfo *slot, CERTCertificate *cert, void *wincx) /* * issue the find */ - rv = PK11_Authenticate(slot, PR_TRUE, wincx); + rv = pk11_AuthenticateUnfriendly(slot, PR_TRUE, wincx); if (rv != SECSuccess) { return CK_INVALID_HANDLE; } @@ -3278,7 +3303,6 @@ PK11_GetKeyIDFromCert(CERTCertificate *cert, void *wincx) goto loser; } - crv = PK11_GetAttributes(NULL,slot,handle,theTemplate,tsize); if (crv != CKR_OK) { PORT_SetError( PK11_MapError(crv) ); @@ -3291,7 +3315,6 @@ PK11_GetKeyIDFromCert(CERTCertificate *cert, void *wincx) item->len = theTemplate[0].ulValueLen; } - loser: PK11_FreeSlot(slot); return item; @@ -3320,7 +3343,6 @@ PK11_GetKeyIDFromPrivateKey(SECKEYPrivateKey *key, void *wincx) item->len = theTemplate[0].ulValueLen; } - loser: return item; } @@ -3497,8 +3519,8 @@ PK11_GetLowLevelKeyIDForCert(PK11SlotInfo *slot, if (slot) { PK11_SETATTRS(attrs, CKA_VALUE, cert->derCert.data, cert->derCert.len); attrs++; - - rv = PK11_Authenticate(slot, PR_TRUE, wincx); + + rv = pk11_AuthenticateUnfriendly(slot, PR_TRUE, wincx); if (rv != SECSuccess) { return NULL; } diff --git a/security/nss/lib/pk11wrap/pk11func.h b/security/nss/lib/pk11wrap/pk11func.h index 133099201..beae90538 100644 --- a/security/nss/lib/pk11wrap/pk11func.h +++ b/security/nss/lib/pk11wrap/pk11func.h @@ -652,6 +652,21 @@ PK11DefaultArrayEntry * PK11_GetDefaultArray(int *); SECStatus PK11_UpdateSlotAttribute(PK11SlotInfo *, PK11DefaultArrayEntry *, PRBool ); +/********************************************************************** + * Functions to look at PKCS #11 dependent data + **********************************************************************/ +PK11GenericObject *PK11_FindGenericObjects(PK11SlotInfo *slot, + CK_OBJECT_CLASS objClass); +PK11GenericObject *PK11_GetNextGenericObject(PK11GenericObject *object); +PK11GenericObject *PK11_GetPrevtGenericObject(PK11GenericObject *object); +SECStatus PK11_UnlinkGenericObject(PK11GenericObject *object); +SECStatus PK11_LinkGenericObject(PK11GenericObject *list, + PK11GenericObject *object); +SECStatus PK11_DestroyGenericObjects(PK11GenericObject *object); +SECStatus PK11_DestroyGenericObject(PK11GenericObject *object); +SECStatus PK11_ReadRawAttribute(PK11ObjectType type, void *object, + CK_ATTRIBUTE_TYPE attr, SECItem *item); + /********************************************************************** * New fucntions which are already depricated.... diff --git a/security/nss/lib/pk11wrap/pk11skey.c b/security/nss/lib/pk11wrap/pk11skey.c index 2f24bd7ef..e2e939cda 100644 --- a/security/nss/lib/pk11wrap/pk11skey.c +++ b/security/nss/lib/pk11wrap/pk11skey.c @@ -1004,6 +1004,8 @@ PK11_MakePrivKey(PK11SlotInfo *slot, KeyType keyType, { PRArenaPool *arena; SECKEYPrivateKey *privKey; + PRBool isPrivate; + SECStatus rv; /* don't know? look it up */ if (keyType == nullKey) { @@ -1024,6 +1026,16 @@ PK11_MakePrivKey(PK11SlotInfo *slot, KeyType keyType, } } + /* if the key is private, make sure we are authenticated to the + * token before we try to use it */ + isPrivate = (PRBool)PK11_HasAttributeSet(slot,privID,CKA_PRIVATE); + if (isPrivate) { + rv = PK11_Authenticate(slot, PR_TRUE, wincx); + if (rv != SECSuccess) { + return NULL; + } + } + /* now we need to create space for the private key */ arena = PORT_NewArena( DER_DEFAULT_CHUNKSIZE); if (arena == NULL) return NULL; @@ -3395,10 +3407,13 @@ PK11_PubUnwrapSymKey(SECKEYPrivateKey *wrappingKey, SECItem *wrappedKey, CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, int keySize) { CK_MECHANISM_TYPE wrapType = pk11_mapWrapKeyType(wrappingKey->keyType); + PK11SlotInfo *slot = wrappingKey->pkcs11Slot; - PK11_HandlePasswordCheck(wrappingKey->pkcs11Slot,wrappingKey->wincx); + if (!PK11_HasAttributeSet(slot,wrappingKey->pkcs11ID,CKA_PRIVATE)) { + PK11_HandlePasswordCheck(slot,wrappingKey->wincx); + } - return pk11_AnyUnwrapKey(wrappingKey->pkcs11Slot, wrappingKey->pkcs11ID, + return pk11_AnyUnwrapKey(slot, wrappingKey->pkcs11ID, wrapType, NULL, wrappedKey, target, operation, keySize, wrappingKey->wincx, NULL, 0, PR_FALSE); } @@ -3413,12 +3428,15 @@ PK11_PubUnwrapSymKeyWithFlags(SECKEYPrivateKey *wrappingKey, CK_BBOOL ckTrue = CK_TRUE; CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS]; unsigned int templateCount; + PK11SlotInfo *slot = wrappingKey->pkcs11Slot; templateCount = pk11_FlagsToAttributes(flags, keyTemplate, &ckTrue); - PK11_HandlePasswordCheck(wrappingKey->pkcs11Slot,wrappingKey->wincx); + if (!PK11_HasAttributeSet(slot,wrappingKey->pkcs11ID,CKA_PRIVATE)) { + PK11_HandlePasswordCheck(slot,wrappingKey->wincx); + } - return pk11_AnyUnwrapKey(wrappingKey->pkcs11Slot, wrappingKey->pkcs11ID, + return pk11_AnyUnwrapKey(slot, wrappingKey->pkcs11ID, wrapType, NULL, wrappedKey, target, operation, keySize, wrappingKey->wincx, keyTemplate, templateCount, PR_FALSE); } @@ -3434,6 +3452,7 @@ PK11_PubUnwrapSymKeyWithFlagsPerm(SECKEYPrivateKey *wrappingKey, CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS]; CK_ATTRIBUTE *attrs; unsigned int templateCount; + PK11SlotInfo *slot = wrappingKey->pkcs11Slot; attrs = keyTemplate; if (isPerm) { @@ -3443,9 +3462,11 @@ PK11_PubUnwrapSymKeyWithFlagsPerm(SECKEYPrivateKey *wrappingKey, templateCount += pk11_FlagsToAttributes(flags, attrs, &cktrue); - PK11_HandlePasswordCheck(wrappingKey->pkcs11Slot,wrappingKey->wincx); + if (!PK11_HasAttributeSet(slot,wrappingKey->pkcs11ID,CKA_PRIVATE)) { + PK11_HandlePasswordCheck(slot,wrappingKey->wincx); + } - return pk11_AnyUnwrapKey(wrappingKey->pkcs11Slot, wrappingKey->pkcs11ID, + return pk11_AnyUnwrapKey(slot, wrappingKey->pkcs11ID, wrapType, NULL, wrappedKey, target, operation, keySize, wrappingKey->wincx, keyTemplate, templateCount, isPerm); } @@ -3569,7 +3590,9 @@ PK11_Sign(SECKEYPrivateKey *key, SECItem *sig, SECItem *hash) mech.mechanism = pk11_mapSignKeyType(key->keyType); - PK11_HandlePasswordCheck(slot, key->wincx); + if (!PK11_HasAttributeSet(slot,key->pkcs11ID,CKA_PRIVATE)) { + PK11_HandlePasswordCheck(slot, key->wincx); + } session = pk11_GetNewSession(slot,&owner); if (!owner || !(slot->isThreadSafe)) PK11_EnterSlotMonitor(slot); @@ -3621,7 +3644,9 @@ PK11_PubDecryptRaw(SECKEYPrivateKey *key, unsigned char *data, * decryption? .. because the user may have asked for 'ask always' * and this is a private key operation. In practice, thought, it's mute * since only servers wind up using this function */ - PK11_HandlePasswordCheck(slot, key->wincx); + if (!PK11_HasAttributeSet(slot,key->pkcs11ID,CKA_PRIVATE)) { + PK11_HandlePasswordCheck(slot, key->wincx); + } session = pk11_GetNewSession(slot,&owner); if (!owner || !(slot->isThreadSafe)) PK11_EnterSlotMonitor(slot); crv = PK11_GETTAB(slot)->C_DecryptInit(session,&mech,key->pkcs11ID); @@ -5714,3 +5739,220 @@ PK11_ConvertSessionSymKeyToTokenSymKey(PK11SymKey *symk, void *wincx) return PK11_SymKeyFromHandle(slot, NULL /*parent*/, symk->origin, symk->type, newKeyID, PR_FALSE /*owner*/, NULL /*wincx*/); } + + +/* + * return a linked, non-circular list of generic objects. + * If you are only interested + * in one object, just use the first object in the list. To find the + * rest of the list use PK11_GetNextGenericObject() to return the next object. + * + * You can walk the list with the following code: + * firstObj = PK11_FindGenericObjects(slot, objClass); + * for (thisObj=firstObj; thisObj; + * thisObj=PK11_GetNextGenericObject(thisObj)) { + * /* operate on thisObj */ +/* } + * + * If you want a particular object from the list... + * firstObj = PK11_FindGenericObjects(slot, objClass); + * for (thisObj=firstObj; thisObj; + * thisObj=PK11_GetNextGenericObject(thisObj)) { + * if (isMyObj(thisObj)) { + * if ( thisObj == firstObj) { + * /* NOTE: firstObj could be NULL at this point */ +/* firstObj = PK11_GetNextGenericObject(thsObj); + * } + * PK11_UnlinkGenericObject(thisObj); + * myObj = thisObj; + * break; + * } + * + * PK11_DestroyGenericObjects(firstObj); + * + * /* use myObj */ +/* PK11_DestroyGenericObject(myObj); + */ +PK11GenericObject * +PK11_FindGenericObjects(PK11SlotInfo *slot, CK_OBJECT_CLASS objClass) +{ + CK_ATTRIBUTE template[1]; + CK_ATTRIBUTE *attrs = template; + CK_OBJECT_HANDLE *objectIDs = NULL; + PK11GenericObject *lastObj, *obj; + PK11GenericObject *firstObj = NULL; + int i, count = 0; + + + PK11_SETATTRS(attrs, CKA_CLASS, &objClass, sizeof(objClass)); attrs++; + + objectIDs = pk11_FindObjectsByTemplate(slot,template,1,&count); + if (objectIDs == NULL) { + return NULL; + } + + /* where we connect our object once we've created it.. */ + for (i=0; i < count; i++) { + obj = PORT_New(PK11GenericObject); + if ( !obj ) { + PK11_DestroyGenericObjects(firstObj); + PORT_Free(objectIDs); + return NULL; + } + /* initialize it */ + obj->slot = PK11_ReferenceSlot(slot); + obj->objectID = objectIDs[i]; + obj->next = NULL; + obj->prev = NULL; + + /* link it in */ + if (firstObj == NULL) { + firstObj = obj; + } else { + PK11_LinkGenericObject(lastObj, obj); + } + lastObj = obj; + } + PORT_Free(objectIDs); + return firstObj; +} + +/* + * get the Next Object in the list. + */ +PK11GenericObject * +PK11_GetNextGenericObject(PK11GenericObject *object) +{ + return object->next; +} + +PK11GenericObject * +PK11_GetPrevGenericObject(PK11GenericObject *object) +{ + return object->prev; +} + +/* + * Link a single object into a new list. + * if the object is already in another list, remove it first. + */ +SECStatus +PK11_LinkGenericObject(PK11GenericObject *list, PK11GenericObject *object) +{ + PK11_UnlinkGenericObject(object); + object->prev = list; + object->next = list->next; + list->next = object; + if (object->next != NULL) { + object->next->prev = object; + } + return SECSuccess; +} + +/* + * remove an object from the list. If the object isn't already in + * a list unlink becomes a noop. + */ +SECStatus +PK11_UnlinkGenericObject(PK11GenericObject *object) +{ + if (object->prev != NULL) { + object->prev->next = object->next; + } + if (object->next != NULL) { + object->next->prev = object->prev; + } + + object->next = NULL; + object->prev = NULL; + return SECSuccess; +} + +/* + * This function removes a single object from the list and destroys it. + * For an already unlinked object there is no difference between + * PK11_DestroyGenericObject and PK11_DestroyGenericObjects + */ +SECStatus +PK11_DestroyGenericObject(PK11GenericObject *object) +{ + if (object == NULL) { + return SECSuccess; + } + + PK11_UnlinkGenericObject(object); + if (object->slot) { + PK11_FreeSlot(object->slot); + } + PORT_Free(object); + return SECSuccess; +} + +/* + * walk down a link list of generic objects destroying them. + * This will destroy all objects in a list that the object is linked into. + * (the list is traversed in both directions). + */ +SECStatus +PK11_DestroyGenericObjects(PK11GenericObject *objects) +{ + PK11GenericObject *nextObject; + PK11GenericObject *prevObject = objects->prev; + + if (objects == NULL) { + return SECSuccess; + } + + nextObject = objects->next; + prevObject = objects->prev; + + /* delete all the objects after it in the list */ + for (; objects; objects = nextObject) { + nextObject = objects->next; + PK11_DestroyGenericObject(objects); + } + /* delete all the objects before it in the list */ + for (objects = prevObject; objects; objects = nextObject) { + prevObject = objects->prev; + PK11_DestroyGenericObject(objects); + } + return SECSuccess; +} + + +SECStatus +PK11_ReadRawAttribute(PK11ObjectType objType, void *objSpec, + CK_ATTRIBUTE_TYPE attrType, SECItem *item) +{ + PK11SlotInfo *slot = NULL; + CK_OBJECT_HANDLE handle; + + switch (objType) { + case PK11_TypeGeneric: + slot = ((PK11GenericObject *)objSpec)->slot; + handle = ((PK11GenericObject *)objSpec)->objectID; + break; + case PK11_TypePrivKey: + slot = ((SECKEYPrivateKey *)objSpec)->pkcs11Slot; + handle = ((SECKEYPrivateKey *)objSpec)->pkcs11ID; + break; + case PK11_TypePubKey: + slot = ((SECKEYPublicKey *)objSpec)->pkcs11Slot; + handle = ((SECKEYPublicKey *)objSpec)->pkcs11ID; + break; + case PK11_TypeSymKey: + slot = ((PK11SymKey *)objSpec)->slot; + handle = ((PK11SymKey *)objSpec)->objectID; + break; + case PK11_TypeCert: /* don't handle cert case for now */ + default: + break; + } + if (slot == NULL) { + PORT_SetError(SEC_ERROR_UNKNOWN_OBJECT_TYPE); + return SECFailure; + } + + return PK11_ReadAttribute(slot, handle, attrType, NULL, item); +} + diff --git a/security/nss/lib/pk11wrap/pk11slot.c b/security/nss/lib/pk11wrap/pk11slot.c index a7b59a6e0..034c34629 100644 --- a/security/nss/lib/pk11wrap/pk11slot.c +++ b/security/nss/lib/pk11wrap/pk11slot.c @@ -906,11 +906,23 @@ PK11_GetSlotPWValues(PK11SlotInfo *slot,int *askpw, int *timeout) } /* + * Returns true if the token is needLogin and isn't logged in. + * This function is used to determine if authentication is needed + * before attempting a potentially privelleged operation. + */ +PRBool +pk11_LoginStillRequired(PK11SlotInfo *slot, void *wincx) +{ + return slot->needLogin && !PK11_IsLoggedIn(slot,wincx); +} + +/* * make sure a slot is authenticated... + * This function only does the authentication if it is needed. */ SECStatus PK11_Authenticate(PK11SlotInfo *slot, PRBool loadCerts, void *wincx) { - if (slot->needLogin && !PK11_IsLoggedIn(slot,wincx)) { + if (pk11_LoginStillRequired(slot,wincx)) { return PK11_DoPassword(slot,loadCerts,wincx); } return SECSuccess; @@ -2644,7 +2656,7 @@ PK11_GetAllTokens(CK_MECHANISM_TYPE type, PRBool needRW, PRBool loadCerts, if (needRW && slot->readOnly) continue; if ((type == CKM_INVALID_MECHANISM) || PK11_DoesMechanism(slot, type)) { - if (slot->needLogin && !PK11_IsLoggedIn(slot, wincx)) { + if (pk11_LoginStillRequired(slot,wincx)) { if (PK11_IsFriendly(slot)) { PK11_AddSlotToList(friendlyList, slot); } else { diff --git a/security/nss/lib/pk11wrap/secmodi.h b/security/nss/lib/pk11wrap/secmodi.h index 65c7aaef8..1bfefaba0 100644 --- a/security/nss/lib/pk11wrap/secmodi.h +++ b/security/nss/lib/pk11wrap/secmodi.h @@ -114,6 +114,8 @@ SECStatus PBE_PK11ParamToAlgid(SECOidTag algTag, SECItem *param, extern void pk11sdr_Init(void); extern void pk11sdr_Shutdown(void); +PRBool pk11_LoginStillRequired(PK11SlotInfo *slot, void *wincx); + SEC_END_PROTOS #endif diff --git a/security/nss/lib/pk11wrap/secmodt.h b/security/nss/lib/pk11wrap/secmodt.h index 4e9599082..c2c7251f2 100644 --- a/security/nss/lib/pk11wrap/secmodt.h +++ b/security/nss/lib/pk11wrap/secmodt.h @@ -62,6 +62,7 @@ typedef struct PK11SlotListElementStr PK11SlotListElement; typedef struct PK11RSAGenParamsStr PK11RSAGenParams; typedef unsigned long SECMODModuleID; typedef struct PK11DefaultArrayEntryStr PK11DefaultArrayEntry; +typedef struct PK11GenericObjectStr PK11GenericObject; struct SECMODModuleStr { PRArenaPool *arena; @@ -212,6 +213,17 @@ typedef enum { PK11_DIS_TOKEN_NOT_PRESENT = 4 } PK11DisableReasons; +/* types of PKCS #11 objects */ +typedef enum { + PK11_TypeGeneric = 0, + PK11_TypePrivKey = 1, + PK11_TypePubKey = 2, + PK11_TypeCert = 3, + PK11_TypeSymKey = 4 +} PK11ObjectType; + + + /* function pointer type for password callback function. * This type is passed in to PK11_SetPasswordFunc() */ diff --git a/security/nss/lib/pk11wrap/secmodti.h b/security/nss/lib/pk11wrap/secmodti.h index 221feac81..c66d977cc 100644 --- a/security/nss/lib/pk11wrap/secmodti.h +++ b/security/nss/lib/pk11wrap/secmodti.h @@ -44,6 +44,8 @@ #include "prtypes.h" #include "nssilckt.h" #include "pk11init.h" +#include "secmodt.h" +#include "pkcs11t.h" #ifndef NSS_3_4_CODE #define NSS_3_4_CODE @@ -191,4 +193,15 @@ struct PK11ContextStr { * non-standard semantics*/ }; +/* + * structure to hold a pointer to a unique PKCS #11 object + * (pointer to the slot and the object id). + */ +struct PK11GenericObjectStr { + PK11GenericObject *prev; + PK11GenericObject *next; + PK11SlotInfo *slot; + CK_OBJECT_HANDLE objectID; +}; + #endif /* _SECMODTI_H_ */ diff --git a/security/nss/lib/util/secerr.h b/security/nss/lib/util/secerr.h index c4a66fcd5..db45149e7 100644 --- a/security/nss/lib/util/secerr.h +++ b/security/nss/lib/util/secerr.h @@ -199,7 +199,8 @@ SEC_ERROR_REVOKED_CERTIFICATE_CRL = (SEC_ERROR_BASE + 145), SEC_ERROR_REVOKED_CERTIFICATE_OCSP = (SEC_ERROR_BASE + 146), SEC_ERROR_CRL_INVALID_VERSION = (SEC_ERROR_BASE + 147), SEC_ERROR_CRL_V1_CRITICAL_EXTENSION = (SEC_ERROR_BASE + 148), -SEC_ERROR_CRL_UNKNOWN_CRITICAL_EXTENSION = (SEC_ERROR_BASE + 149) +SEC_ERROR_CRL_UNKNOWN_CRITICAL_EXTENSION = (SEC_ERROR_BASE + 149), +SEC_ERROR_UNKNOWN_OBJECT_TYPE = (SEC_ERROR_BASE + 150) } SECErrorCodes; #endif /* NO_SECURITY_ERROR_ENUM */ |