Bug 357025, additional patch to fix locking and session authentication, contributed by Robert Relyea, r=kaie
git-svn-id: svn://10.0.0.236/trunk@264448 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
parent
0cde057de2
commit
84c2f811ec
@ -214,7 +214,12 @@ typedef struct SECKEYPublicKeyStr SECKEYPublicKey;
|
||||
#define SECKEY_HAS_ATTRIBUTE_SET(key,attribute) \
|
||||
(0 != (key->staticflags & SECKEY_Attributes_Cached)) ? \
|
||||
(0 != (key->staticflags & SECKEY_##attribute)) : \
|
||||
PK11_HasAttributeSet(key->pkcs11Slot,key->pkcs11ID,attribute)
|
||||
PK11_HasAttributeSet(key->pkcs11Slot,key->pkcs11ID,attribute, PR_FALSE)
|
||||
|
||||
#define SECKEY_HAS_ATTRIBUTE_SET_LOCK(key,attribute, haslock) \
|
||||
(0 != (key->staticflags & SECKEY_Attributes_Cached)) ? \
|
||||
(0 != (key->staticflags & SECKEY_##attribute)) : \
|
||||
PK11_HasAttributeSet(key->pkcs11Slot,key->pkcs11ID,attribute, haslock)
|
||||
|
||||
/*
|
||||
** A generic key structure
|
||||
|
||||
@ -1918,7 +1918,7 @@ loser:
|
||||
}
|
||||
|
||||
#define SECKEY_CacheAttribute(key, attribute) \
|
||||
if (CK_TRUE == PK11_HasAttributeSet(key->pkcs11Slot, key->pkcs11ID, attribute)) { \
|
||||
if (CK_TRUE == PK11_HasAttributeSet(key->pkcs11Slot, key->pkcs11ID, attribute, PR_FALSE)) { \
|
||||
key->staticflags |= SECKEY_##attribute; \
|
||||
} else { \
|
||||
key->staticflags &= (~SECKEY_##attribute); \
|
||||
|
||||
@ -740,7 +740,7 @@ PK11_MakePrivKey(PK11SlotInfo *slot, KeyType keyType,
|
||||
CK_KEY_TYPE pk11Type = CKK_RSA;
|
||||
|
||||
pk11Type = PK11_ReadULongAttribute(slot,privID,CKA_KEY_TYPE);
|
||||
isTemp = (PRBool)!PK11_HasAttributeSet(slot,privID,CKA_TOKEN);
|
||||
isTemp = (PRBool)!PK11_HasAttributeSet(slot,privID,CKA_TOKEN,PR_FALSE);
|
||||
switch (pk11Type) {
|
||||
case CKK_RSA: keyType = rsaKey; break;
|
||||
case CKK_DSA: keyType = dsaKey; break;
|
||||
@ -754,7 +754,7 @@ 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);
|
||||
isPrivate = (PRBool)PK11_HasAttributeSet(slot,privID,CKA_PRIVATE,PR_FALSE);
|
||||
if (isPrivate) {
|
||||
rv = PK11_Authenticate(slot, PR_TRUE, wincx);
|
||||
if (rv != SECSuccess) {
|
||||
@ -1432,7 +1432,7 @@ PK11_GenerateKeyPairWithOpFlags(PK11SlotInfo *slot,CK_MECHANISM_TYPE type,
|
||||
|
||||
/* set the ID to the public key so we can find it again */
|
||||
cka_id = pk11_MakeIDFromPublicKey(*pubKey);
|
||||
pubIsToken = (PRBool)PK11_HasAttributeSet(slot,pubID, CKA_TOKEN);
|
||||
pubIsToken = (PRBool)PK11_HasAttributeSet(slot,pubID, CKA_TOKEN,PR_FALSE);
|
||||
|
||||
PK11_SETATTRS(&setTemplate, CKA_ID, cka_id->data, cka_id->len);
|
||||
|
||||
|
||||
@ -45,8 +45,9 @@ static struct PK11GlobalStruct {
|
||||
* Check the user's password. Log into the card if it's correct.
|
||||
* succeed if the user is already logged in.
|
||||
*/
|
||||
SECStatus
|
||||
pk11_CheckPassword(PK11SlotInfo *slot,char *pw,PRBool contextSpecific)
|
||||
static SECStatus
|
||||
pk11_CheckPassword(PK11SlotInfo *slot, CK_SESSION_HANDLE session,
|
||||
char *pw, PRBool alreadyLocked, PRBool contextSpecific)
|
||||
{
|
||||
int len = 0;
|
||||
CK_RV crv;
|
||||
@ -66,13 +67,13 @@ pk11_CheckPassword(PK11SlotInfo *slot,char *pw,PRBool contextSpecific)
|
||||
}
|
||||
|
||||
do {
|
||||
PK11_EnterSlotMonitor(slot);
|
||||
crv = PK11_GETTAB(slot)->C_Login(slot->session,
|
||||
if (!alreadyLocked) PK11_EnterSlotMonitor(slot);
|
||||
crv = PK11_GETTAB(slot)->C_Login(session,
|
||||
contextSpecific ? CKU_CONTEXT_SPECIFIC : CKU_USER,
|
||||
(unsigned char *)pw,len);
|
||||
slot->lastLoginCheck = 0;
|
||||
mustRetry = PR_FALSE;
|
||||
PK11_ExitSlotMonitor(slot);
|
||||
if (!alreadyLocked) PK11_ExitSlotMonitor(slot);
|
||||
switch (crv) {
|
||||
/* if we're already logged in, we're good to go */
|
||||
case CKR_OK:
|
||||
@ -91,10 +92,19 @@ pk11_CheckPassword(PK11SlotInfo *slot,char *pw,PRBool contextSpecific)
|
||||
* if the token is still there. */
|
||||
case CKR_SESSION_HANDLE_INVALID:
|
||||
case CKR_SESSION_CLOSED:
|
||||
if (session != slot->session) {
|
||||
/* don't bother retrying, we were in a middle of an operation,
|
||||
* which is now lost. Just fail. */
|
||||
PORT_SetError(PK11_MapError(crv));
|
||||
rv = SECFailure;
|
||||
break;
|
||||
}
|
||||
if (retry++ == 0) {
|
||||
rv = PK11_InitToken(slot,PR_FALSE);
|
||||
if (rv == SECSuccess) {
|
||||
if (slot->session != CK_INVALID_SESSION) {
|
||||
session = slot->session; /* we should have
|
||||
* a new session now */
|
||||
mustRetry = PR_TRUE;
|
||||
} else {
|
||||
PORT_SetError(PK11_MapError(crv));
|
||||
@ -242,7 +252,8 @@ PK11_HandlePasswordCheck(PK11SlotInfo *slot,void *wincx)
|
||||
NeedAuth = PR_TRUE;
|
||||
}
|
||||
}
|
||||
if (NeedAuth) PK11_DoPassword(slot,PR_TRUE,wincx,PR_FALSE);
|
||||
if (NeedAuth) PK11_DoPassword(slot, slot->session, PR_TRUE,
|
||||
wincx, PR_FALSE, PR_FALSE);
|
||||
}
|
||||
|
||||
void
|
||||
@ -301,7 +312,8 @@ pk11_LoginStillRequired(PK11SlotInfo *slot, void *wincx)
|
||||
SECStatus
|
||||
PK11_Authenticate(PK11SlotInfo *slot, PRBool loadCerts, void *wincx) {
|
||||
if (pk11_LoginStillRequired(slot,wincx)) {
|
||||
return PK11_DoPassword(slot,loadCerts,wincx,PR_FALSE);
|
||||
return PK11_DoPassword(slot, slot->session, loadCerts, wincx,
|
||||
PR_FALSE, PR_FALSE);
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
@ -532,7 +544,8 @@ PK11_SetIsLoggedInFunc(PK11IsLoggedInFunc func)
|
||||
* of the PKCS 11 module.
|
||||
*/
|
||||
SECStatus
|
||||
PK11_DoPassword(PK11SlotInfo *slot, PRBool loadCerts, void *wincx,
|
||||
PK11_DoPassword(PK11SlotInfo *slot, CK_SESSION_HANDLE session,
|
||||
PRBool loadCerts, void *wincx, PRBool alreadyLocked,
|
||||
PRBool contextSpecific)
|
||||
{
|
||||
SECStatus rv = SECFailure;
|
||||
@ -602,7 +615,8 @@ PK11_DoPassword(PK11SlotInfo *slot, PRBool loadCerts, void *wincx,
|
||||
break;
|
||||
}
|
||||
}
|
||||
rv = pk11_CheckPassword(slot,password,contextSpecific);
|
||||
rv = pk11_CheckPassword(slot, session, password,
|
||||
alreadyLocked, contextSpecific);
|
||||
PORT_Memset(password, 0, PORT_Strlen(password));
|
||||
PORT_Free(password);
|
||||
if (rv != SECWouldBlock) break;
|
||||
|
||||
@ -169,15 +169,15 @@ pk11_getPrivateKeyUsage(PK11SlotInfo *slot, CK_OBJECT_HANDLE id)
|
||||
{
|
||||
unsigned int usage = 0;
|
||||
|
||||
if ((PK11_HasAttributeSet(slot, id, CKA_UNWRAP) ||
|
||||
PK11_HasAttributeSet(slot,id, CKA_DECRYPT))) {
|
||||
if ((PK11_HasAttributeSet(slot, id, CKA_UNWRAP,PR_FALSE) ||
|
||||
PK11_HasAttributeSet(slot,id, CKA_DECRYPT,PR_FALSE))) {
|
||||
usage |= KU_KEY_ENCIPHERMENT;
|
||||
}
|
||||
if (PK11_HasAttributeSet(slot, id, CKA_DERIVE)) {
|
||||
if (PK11_HasAttributeSet(slot, id, CKA_DERIVE, PR_FALSE)) {
|
||||
usage |= KU_KEY_AGREEMENT;
|
||||
}
|
||||
if ((PK11_HasAttributeSet(slot, id, CKA_SIGN_RECOVER) ||
|
||||
PK11_HasAttributeSet(slot, id, CKA_SIGN))) {
|
||||
if ((PK11_HasAttributeSet(slot, id, CKA_SIGN_RECOVER, PR_FALSE) ||
|
||||
PK11_HasAttributeSet(slot, id, CKA_SIGN, PR_FALSE))) {
|
||||
usage |= KU_DIGITAL_SIGNATURE;
|
||||
}
|
||||
return usage;
|
||||
@ -373,31 +373,31 @@ pk11_getSecretKeyFlags(PK11SlotInfo *slot, CK_OBJECT_HANDLE id)
|
||||
{
|
||||
CK_FLAGS flags = 0;
|
||||
|
||||
if (PK11_HasAttributeSet(slot, id, CKA_UNWRAP)) {
|
||||
if (PK11_HasAttributeSet(slot, id, CKA_UNWRAP, PR_FALSE)) {
|
||||
flags |= CKF_UNWRAP;
|
||||
}
|
||||
if (PK11_HasAttributeSet(slot, id, CKA_WRAP)) {
|
||||
if (PK11_HasAttributeSet(slot, id, CKA_WRAP, PR_FALSE)) {
|
||||
flags |= CKF_WRAP;
|
||||
}
|
||||
if (PK11_HasAttributeSet(slot, id, CKA_ENCRYPT)) {
|
||||
if (PK11_HasAttributeSet(slot, id, CKA_ENCRYPT, PR_FALSE)) {
|
||||
flags |= CKF_ENCRYPT;
|
||||
}
|
||||
if (PK11_HasAttributeSet(slot, id, CKA_DECRYPT)) {
|
||||
if (PK11_HasAttributeSet(slot, id, CKA_DECRYPT, PR_FALSE)) {
|
||||
flags |= CKF_DECRYPT;
|
||||
}
|
||||
if (PK11_HasAttributeSet(slot, id, CKA_DERIVE)) {
|
||||
if (PK11_HasAttributeSet(slot, id, CKA_DERIVE, PR_FALSE)) {
|
||||
flags |= CKF_DERIVE;
|
||||
}
|
||||
if (PK11_HasAttributeSet(slot, id, CKA_SIGN)) {
|
||||
if (PK11_HasAttributeSet(slot, id, CKA_SIGN, PR_FALSE)) {
|
||||
flags |= CKF_SIGN;
|
||||
}
|
||||
if (PK11_HasAttributeSet(slot, id, CKA_SIGN_RECOVER)) {
|
||||
if (PK11_HasAttributeSet(slot, id, CKA_SIGN_RECOVER, PR_FALSE)) {
|
||||
flags |= CKF_SIGN_RECOVER;
|
||||
}
|
||||
if (PK11_HasAttributeSet(slot, id, CKA_VERIFY)) {
|
||||
if (PK11_HasAttributeSet(slot, id, CKA_VERIFY, PR_FALSE)) {
|
||||
flags |= CKF_VERIFY;
|
||||
}
|
||||
if (PK11_HasAttributeSet(slot, id, CKA_VERIFY_RECOVER)) {
|
||||
if (PK11_HasAttributeSet(slot, id, CKA_VERIFY_RECOVER, PR_FALSE)) {
|
||||
flags |= CKF_VERIFY_RECOVER;
|
||||
}
|
||||
return flags;
|
||||
|
||||
@ -146,7 +146,7 @@ PK11_ReadULongAttribute(PK11SlotInfo *slot, CK_OBJECT_HANDLE id,
|
||||
*/
|
||||
CK_BBOOL
|
||||
PK11_HasAttributeSet( PK11SlotInfo *slot, CK_OBJECT_HANDLE id,
|
||||
CK_ATTRIBUTE_TYPE type )
|
||||
CK_ATTRIBUTE_TYPE type, PRBool haslock )
|
||||
{
|
||||
CK_BBOOL ckvalue = CK_FALSE;
|
||||
CK_ATTRIBUTE theTemplate;
|
||||
@ -156,10 +156,10 @@ PK11_HasAttributeSet( PK11SlotInfo *slot, CK_OBJECT_HANDLE id,
|
||||
PK11_SETATTRS( &theTemplate, type, &ckvalue, sizeof( CK_BBOOL ) );
|
||||
|
||||
/* Retrieve attribute value. */
|
||||
PK11_EnterSlotMonitor(slot);
|
||||
if (!haslock) PK11_EnterSlotMonitor(slot);
|
||||
crv = PK11_GETTAB( slot )->C_GetAttributeValue( slot->session, id,
|
||||
&theTemplate, 1 );
|
||||
PK11_ExitSlotMonitor(slot);
|
||||
if (!haslock) PK11_ExitSlotMonitor(slot);
|
||||
if( crv != CKR_OK ) {
|
||||
PORT_SetError( PK11_MapError( crv ) );
|
||||
return CK_FALSE;
|
||||
@ -254,7 +254,7 @@ PK11_GetAttributes(PRArenaPool *arena,PK11SlotInfo *slot,
|
||||
PRBool
|
||||
PK11_IsPermObject(PK11SlotInfo *slot, CK_OBJECT_HANDLE handle)
|
||||
{
|
||||
return (PRBool) PK11_HasAttributeSet(slot, handle, CKA_TOKEN);
|
||||
return (PRBool) PK11_HasAttributeSet(slot, handle, CKA_TOKEN, PR_FALSE);
|
||||
}
|
||||
|
||||
char *
|
||||
@ -735,6 +735,7 @@ PK11_Sign(SECKEYPrivateKey *key, SECItem *sig, SECItem *hash)
|
||||
CK_MECHANISM mech = {0, NULL, 0 };
|
||||
PRBool owner = PR_TRUE;
|
||||
CK_SESSION_HANDLE session;
|
||||
PRBool haslock = PR_FALSE;
|
||||
CK_ULONG len;
|
||||
CK_RV crv;
|
||||
|
||||
@ -745,24 +746,27 @@ PK11_Sign(SECKEYPrivateKey *key, SECItem *sig, SECItem *hash)
|
||||
}
|
||||
|
||||
session = pk11_GetNewSession(slot,&owner);
|
||||
if (!owner || !(slot->isThreadSafe)) PK11_EnterSlotMonitor(slot);
|
||||
haslock = (!owner || !(slot->isThreadSafe));
|
||||
if (haslock) PK11_EnterSlotMonitor(slot);
|
||||
crv = PK11_GETTAB(slot)->C_SignInit(session,&mech,key->pkcs11ID);
|
||||
if (crv != CKR_OK) {
|
||||
if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot);
|
||||
if (haslock) PK11_ExitSlotMonitor(slot);
|
||||
pk11_CloseSession(slot,session,owner);
|
||||
PORT_SetError( PK11_MapError(crv) );
|
||||
return SECFailure;
|
||||
}
|
||||
/* PKCS11 2.20 says if CKA_ALWAYS_AUTHENTICATE then
|
||||
* do C_Login with CKU_CONTEXT_SPECIFIC
|
||||
* between C_SignInit and C_Sign */
|
||||
if (SECKEY_HAS_ATTRIBUTE_SET(key,CKA_ALWAYS_AUTHENTICATE)) {
|
||||
PK11_DoPassword(slot, PR_FALSE, key->wincx, PR_TRUE);
|
||||
}
|
||||
|
||||
/* PKCS11 2.20 says if CKA_ALWAYS_AUTHENTICATE then
|
||||
* do C_Login with CKU_CONTEXT_SPECIFIC
|
||||
* between C_SignInit and C_Sign */
|
||||
if (SECKEY_HAS_ATTRIBUTE_SET_LOCK(key, CKA_ALWAYS_AUTHENTICATE, haslock)) {
|
||||
PK11_DoPassword(slot, session, PR_FALSE, key->wincx, haslock, PR_TRUE);
|
||||
}
|
||||
|
||||
len = sig->len;
|
||||
crv = PK11_GETTAB(slot)->C_Sign(session,hash->data,
|
||||
hash->len, sig->data, &len);
|
||||
if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot);
|
||||
if (haslock) PK11_ExitSlotMonitor(slot);
|
||||
pk11_CloseSession(slot,session,owner);
|
||||
sig->len = len;
|
||||
if (crv != CKR_OK) {
|
||||
@ -788,6 +792,7 @@ pk11_PrivDecryptRaw(SECKEYPrivateKey *key, unsigned char *data,
|
||||
CK_ULONG out = maxLen;
|
||||
PRBool owner = PR_TRUE;
|
||||
CK_SESSION_HANDLE session;
|
||||
PRBool haslock = PR_FALSE;
|
||||
CK_RV crv;
|
||||
|
||||
if (key->keyType != rsaKey) {
|
||||
@ -803,23 +808,26 @@ pk11_PrivDecryptRaw(SECKEYPrivateKey *key, unsigned char *data,
|
||||
PK11_HandlePasswordCheck(slot, key->wincx);
|
||||
}
|
||||
session = pk11_GetNewSession(slot,&owner);
|
||||
if (!owner || !(slot->isThreadSafe)) PK11_EnterSlotMonitor(slot);
|
||||
haslock = (!owner || !(slot->isThreadSafe));
|
||||
if (haslock) PK11_EnterSlotMonitor(slot);
|
||||
crv = PK11_GETTAB(slot)->C_DecryptInit(session, mech, key->pkcs11ID);
|
||||
if (crv != CKR_OK) {
|
||||
if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot);
|
||||
if (haslock) PK11_ExitSlotMonitor(slot);
|
||||
pk11_CloseSession(slot,session,owner);
|
||||
PORT_SetError( PK11_MapError(crv) );
|
||||
return SECFailure;
|
||||
}
|
||||
/* PKCS11 2.20 says if CKA_ALWAYS_AUTHENTICATE then
|
||||
* do C_Login with CKU_CONTEXT_SPECIFIC
|
||||
* between C_DecryptInit and C_Decrypt */
|
||||
/* But see note above about servers */
|
||||
if (SECKEY_HAS_ATTRIBUTE_SET(key,CKA_ALWAYS_AUTHENTICATE)) {
|
||||
PK11_DoPassword(slot, PR_FALSE, key->wincx, PR_TRUE);
|
||||
}
|
||||
|
||||
/* PKCS11 2.20 says if CKA_ALWAYS_AUTHENTICATE then
|
||||
* do C_Login with CKU_CONTEXT_SPECIFIC
|
||||
* between C_DecryptInit and C_Decrypt
|
||||
* ... But see note above about servers */
|
||||
if (SECKEY_HAS_ATTRIBUTE_SET_LOCK(key, CKA_ALWAYS_AUTHENTICATE, haslock)) {
|
||||
PK11_DoPassword(slot, session, PR_FALSE, key->wincx, haslock, PR_TRUE);
|
||||
}
|
||||
|
||||
crv = PK11_GETTAB(slot)->C_Decrypt(session,enc, encLen, data, &out);
|
||||
if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot);
|
||||
if (haslock) PK11_ExitSlotMonitor(slot);
|
||||
pk11_CloseSession(slot,session,owner);
|
||||
*outLen = out;
|
||||
if (crv != CKR_OK) {
|
||||
|
||||
@ -59,8 +59,9 @@ void PK11_CleanKeyList(PK11SlotInfo *slot);
|
||||
/************************************************************
|
||||
* Slot Password Management
|
||||
************************************************************/
|
||||
SECStatus PK11_DoPassword(PK11SlotInfo *slot, PRBool loadCerts, void *wincx,
|
||||
PRBool contextSpecific);
|
||||
SECStatus PK11_DoPassword(PK11SlotInfo *slot, CK_SESSION_HANDLE session,
|
||||
PRBool loadCerts, void *wincx, PRBool alreadyLocked,
|
||||
PRBool contextSpecific);
|
||||
SECStatus PK11_VerifyPW(PK11SlotInfo *slot,char *pw);
|
||||
void PK11_HandlePasswordCheck(PK11SlotInfo *slot,void *wincx);
|
||||
void PK11_SetVerifyPasswordFunc(PK11VerifyPasswordFunc func);
|
||||
@ -121,7 +122,8 @@ CK_OBJECT_HANDLE PK11_MatchItem(PK11SlotInfo *slot,CK_OBJECT_HANDLE peer,
|
||||
CK_OBJECT_CLASS o_class);
|
||||
CK_BBOOL PK11_HasAttributeSet( PK11SlotInfo *slot,
|
||||
CK_OBJECT_HANDLE id,
|
||||
CK_ATTRIBUTE_TYPE type );
|
||||
CK_ATTRIBUTE_TYPE type,
|
||||
PRBool haslock );
|
||||
CK_RV PK11_GetAttributes(PLArenaPool *arena,PK11SlotInfo *slot,
|
||||
CK_OBJECT_HANDLE obj,CK_ATTRIBUTE *attr, int count);
|
||||
int PK11_NumberCertsForCertSubject(CERTCertificate *cert);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user