diff --git a/security/nss/lib/nss/nss.def b/security/nss/lib/nss/nss.def index 15289bbcb3e4..9b002400c870 100644 --- a/security/nss/lib/nss/nss.def +++ b/security/nss/lib/nss/nss.def @@ -769,6 +769,7 @@ NSS_Get_CERT_TimeChoiceTemplate; PK11_DeriveWithFlagsPerm; PK11_ExportEncryptedPrivKeyInfo; PK11_FindSlotsByAliases; +PK11_GetSymKeyType; PK11_MoveKey; PK11_PubDeriveExtended; PK11_PubUnwrapSymKeyWithFlagsPerm; diff --git a/security/nss/lib/pk11wrap/pk11func.h b/security/nss/lib/pk11wrap/pk11func.h index 8eedbd254560..06c5fe13da8f 100644 --- a/security/nss/lib/pk11wrap/pk11func.h +++ b/security/nss/lib/pk11wrap/pk11func.h @@ -233,7 +233,9 @@ int PK11_GetBestKeyLength(PK11SlotInfo *slot, CK_MECHANISM_TYPE type); void PK11_AddMechanismEntry(CK_MECHANISM_TYPE type, CK_KEY_TYPE key, CK_MECHANISM_TYPE keygen, int ivLen, int blocksize); CK_MECHANISM_TYPE PK11_GetKeyType(CK_MECHANISM_TYPE type,unsigned long len); +CK_MECHANISM_TYPE PK11_GetKeyMechanism(CK_KEY_TYPE type); CK_MECHANISM_TYPE PK11_GetKeyGen(CK_MECHANISM_TYPE type); +CK_MECHANISM_TYPE PK11_GetKeyGenWithSize(CK_MECHANISM_TYPE type, int size); int PK11_GetBlockSize(CK_MECHANISM_TYPE type,SECItem *params); int PK11_GetIVLength(CK_MECHANISM_TYPE type); SECItem *PK11_ParamFromIV(CK_MECHANISM_TYPE type,SECItem *iv); @@ -260,7 +262,7 @@ CK_MECHANISM_TYPE PK11_GetPadMechanism(CK_MECHANISM_TYPE); * Symetric, Public, and Private Keys **********************************************************************/ PK11SymKey *PK11_CreateSymKey(PK11SlotInfo *slot, - CK_MECHANISM_TYPE type, void *wincx); + CK_MECHANISM_TYPE type, PRBool owner, void *wincx); void PK11_FreeSymKey(PK11SymKey *key); PK11SymKey *PK11_ReferenceSymKey(PK11SymKey *symKey); PK11SymKey *PK11_ImportSymKey(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, @@ -289,6 +291,7 @@ PK11SymKey *PK11_TokenKeyGen(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, PK11SymKey * PK11_ListFixedKeysInSlot(PK11SlotInfo *slot, char *nickname, void *wincx); PK11SymKey *PK11_GetNextSymKey(PK11SymKey *symKey); +CK_KEY_TYPE PK11_GetSymKeyType(PK11SymKey *key); /* Key Generation specialized for SDR (fixed DES3 key) */ PK11SymKey *PK11_GenDES3TokenKey(PK11SlotInfo *slot, SECItem *keyid, void *cx); diff --git a/security/nss/lib/pk11wrap/pk11kea.c b/security/nss/lib/pk11wrap/pk11kea.c index a4cda1d27141..4c88910e1c47 100644 --- a/security/nss/lib/pk11wrap/pk11kea.c +++ b/security/nss/lib/pk11wrap/pk11kea.c @@ -88,6 +88,7 @@ pk11_KeyExchange(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, SECKEYPublicKey *pubKey = NULL; SECKEYPrivateKey *privKey = NULL; SECItem wrapData; + unsigned int symKeyLength = PK11_GetKeyLength(symKey); wrapData.data = NULL; @@ -99,7 +100,6 @@ pk11_KeyExchange(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, /* if no key exists, generate a key pair */ if (privKeyHandle == CK_INVALID_HANDLE) { - unsigned int symKeyLength = PK11_GetKeyLength(symKey); PK11RSAGenParams rsaParams; if (symKeyLength > 53) /* bytes */ { @@ -139,7 +139,7 @@ pk11_KeyExchange(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, rv = PK11_PubWrapSymKey(CKM_RSA_PKCS, pubKey, symKey, &wrapData); if (rv == SECSuccess) { newSymKey = PK11_PubUnwrapSymKeyWithFlagsPerm(privKey, - &wrapData,type,operation,0,flags,isPerm); + &wrapData,type,operation,symKeyLength,flags,isPerm); } rsa_failed: if (wrapData.data != NULL) PORT_Free(wrapData.data); diff --git a/security/nss/lib/pk11wrap/pk11skey.c b/security/nss/lib/pk11wrap/pk11skey.c index 236db5e6cdb0..f7a5a9f6ba09 100644 --- a/security/nss/lib/pk11wrap/pk11skey.c +++ b/security/nss/lib/pk11wrap/pk11skey.c @@ -213,7 +213,8 @@ PK11_CleanKeyList(PK11SlotInfo *slot) * type is the mechanism type */ PK11SymKey * -PK11_CreateSymKey(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, void *wincx) +PK11_CreateSymKey(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, PRBool owner, + void *wincx) { PK11SymKey *symKey = pk11_getKeyFromList(slot); @@ -226,7 +227,7 @@ PK11_CreateSymKey(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, void *wincx) symKey->type = type; symKey->data.data = NULL; symKey->data.len = 0; - symKey->owner = PR_TRUE; + symKey->owner = owner; symKey->objectID = CK_INVALID_HANDLE; symKey->slot = slot; symKey->series = slot->series; @@ -298,14 +299,13 @@ PK11_SymKeyFromHandle(PK11SlotInfo *slot, PK11SymKey *parent, PK11Origin origin, return NULL; } - symKey = PK11_CreateSymKey(slot,type,wincx); + symKey = PK11_CreateSymKey(slot,type,owner,wincx); if (symKey == NULL) { return NULL; } symKey->objectID = keyID; symKey->origin = origin; - symKey->owner = owner; /* adopt the parent's session */ /* This is only used by SSL. What we really want here is a session @@ -414,7 +414,7 @@ pk11_ImportSymKeyWithTempl(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, PK11SymKey * symKey; SECStatus rv; - symKey = PK11_CreateSymKey(slot,type,wincx); + symKey = PK11_CreateSymKey(slot,type,!isToken,wincx); if (symKey == NULL) { return NULL; } @@ -651,6 +651,11 @@ PK11_GetSlotFromKey(PK11SymKey *symKey) return PK11_ReferenceSlot(symKey->slot); } +CK_KEY_TYPE PK11_GetSymKeyType(PK11SymKey *symKey) +{ + return PK11_GetKeyType(symKey->type,symKey->size); +} + PK11SymKey * PK11_FindFixedKey(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, SECItem *keyID, void *wincx) @@ -697,7 +702,7 @@ PK11_ListFixedKeysInSlot(PK11SlotInfo *slot, char *nickname, void *wincx) PK11_SETATTRS(attrs, CKA_CLASS, &keyclass, sizeof(keyclass)); attrs++; PK11_SETATTRS(attrs, CKA_TOKEN, &ckTrue, sizeof(ckTrue)); attrs++; if (nickname) { - len = PORT_Strlen(nickname)-1; + len = PORT_Strlen(nickname); PK11_SETATTRS(attrs, CKA_LABEL, nickname, len); attrs++; } tsize = attrs - findTemp; @@ -709,8 +714,18 @@ PK11_ListFixedKeysInSlot(PK11SlotInfo *slot, char *nickname, void *wincx) } for (i=0; i < objCount ; i++) { + SECItem typeData; + CK_KEY_TYPE type = CKK_GENERIC_SECRET; + SECStatus rv = PK11_ReadAttribute(slot, key_ids[i], + CKA_KEY_TYPE, NULL, &typeData); + if (rv == SECSuccess) { + if (typeData.len == sizeof(CK_KEY_TYPE)) { + type = *(CK_KEY_TYPE *)typeData.data; + } + PORT_Free(typeData.data); + } nextKey = PK11_SymKeyFromHandle(slot, NULL, PK11_OriginDerive, - CKM_INVALID_MECHANISM, key_ids[i], PR_FALSE, wincx); + PK11_GetKeyMechanism(type), key_ids[i], PR_FALSE, wincx); if (nextKey) { nextKey->next = topKey; topKey = nextKey; @@ -1491,11 +1506,11 @@ PK11_TokenKeyGen(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, SECItem *param, return NULL; } - symKey = PK11_CreateSymKey(bestSlot,type,wincx); + symKey = PK11_CreateSymKey(bestSlot, type, !isToken, wincx); PK11_FreeSlot(bestSlot); } else { - symKey = PK11_CreateSymKey(slot, type, wincx); + symKey = PK11_CreateSymKey(slot, type, !isToken, wincx); } if (symKey == NULL) return NULL; @@ -1503,7 +1518,7 @@ PK11_TokenKeyGen(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, SECItem *param, symKey->origin = (!weird) ? PK11_OriginGenerated : PK11_OriginFortezzaHack; /* Initialize the Key Gen Mechanism */ - mechanism.mechanism = PK11_GetKeyGen(type); + mechanism.mechanism = PK11_GetKeyGenWithSize(type, keySize); if (mechanism.mechanism == CKM_FAKE_RANDOM) { PORT_SetError( SEC_ERROR_NO_MODULE ); return NULL; @@ -2632,7 +2647,7 @@ PK11_DeriveWithFlagsPerm( PK11SymKey *baseKey, CK_MECHANISM_TYPE derive, PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL)); attrs++; } templateCount = attrs - keyTemplate; - templateCount += pk11_FlagsToAttributes(flags, keyTemplate, &cktrue); + templateCount += pk11_FlagsToAttributes(flags, attrs, &cktrue); return pk11_DeriveWithTemplate(baseKey, derive, param, target, operation, keySize, keyTemplate, templateCount, isPerm); } @@ -2721,7 +2736,7 @@ pk11_DeriveWithTemplate( PK11SymKey *baseKey, CK_MECHANISM_TYPE derive, /* get our key Structure */ - symKey = PK11_CreateSymKey(slot,target,baseKey->cx); + symKey = PK11_CreateSymKey(slot,target,!isPerm,baseKey->cx); if (symKey == NULL) { return NULL; } @@ -2823,7 +2838,7 @@ PK11_PubDerive(SECKEYPrivateKey *privKey, SECKEYPublicKey *pubKey, } /* get our key Structure */ - symKey = PK11_CreateSymKey(slot,target,wincx); + symKey = PK11_CreateSymKey(slot,target,PR_TRUE,wincx); if (symKey == NULL) { return NULL; } @@ -2993,7 +3008,7 @@ PK11_PubDeriveExtended(SECKEYPrivateKey *privKey, SECKEYPublicKey *pubKey, #endif /* get our key Structure */ - symKey = PK11_CreateSymKey(slot,target,wincx); + symKey = PK11_CreateSymKey(slot,target,PR_TRUE,wincx); if (symKey == NULL) { return NULL; } @@ -3281,7 +3296,7 @@ pk11_AnyUnwrapKey(PK11SlotInfo *slot, CK_OBJECT_HANDLE wrappingKey, } /* get our key Structure */ - symKey = PK11_CreateSymKey(slot,target,wincx); + symKey = PK11_CreateSymKey(slot,target,!isPerm,wincx); if (symKey == NULL) { if (param_free) SECITEM_FreeItem(param_free,PR_TRUE); return NULL; @@ -3362,11 +3377,11 @@ PK11_UnwrapSymKeyWithFlagsPerm(PK11SymKey *wrappingKey, PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL)); attrs++; } templateCount = attrs-keyTemplate; - templateCount += pk11_FlagsToAttributes(flags, keyTemplate, &cktrue); + templateCount += pk11_FlagsToAttributes(flags, attrs, &cktrue); return pk11_AnyUnwrapKey(wrappingKey->slot, wrappingKey->objectID, wrapType, param, wrappedKey, target, operation, keySize, - wrappingKey->cx, keyTemplate, templateCount, PR_TRUE); + wrappingKey->cx, keyTemplate, templateCount, isPerm); } @@ -3422,7 +3437,7 @@ PK11_PubUnwrapSymKeyWithFlagsPerm(SECKEYPrivateKey *wrappingKey, } templateCount = attrs-keyTemplate; - templateCount += pk11_FlagsToAttributes(flags, keyTemplate, &cktrue); + templateCount += pk11_FlagsToAttributes(flags, attrs, &cktrue); PK11_HandlePasswordCheck(wrappingKey->pkcs11Slot,wrappingKey->wincx); diff --git a/security/nss/lib/pk11wrap/pk11slot.c b/security/nss/lib/pk11wrap/pk11slot.c index 374b32ae83da..74dfe89ad96c 100644 --- a/security/nss/lib/pk11wrap/pk11slot.c +++ b/security/nss/lib/pk11wrap/pk11slot.c @@ -2872,6 +2872,58 @@ PK11_AddMechanismEntry(CK_MECHANISM_TYPE type, CK_KEY_TYPE key, if (old) PORT_Free(old); } +/* + * Get the key type needed for the given mechanism + */ +CK_MECHANISM_TYPE +PK11_GetKeyMechanism(CK_KEY_TYPE type) +{ + switch (type) { + case CKK_AES: + return CKM_AES_CBC; + case CKK_DES: + return CKM_DES_CBC; + case CKK_DES3: + return CKM_DES3_KEY_GEN; + case CKK_DES2: + return CKM_DES2_KEY_GEN; + case CKK_CDMF: + return CKM_CDMF_CBC; + case CKK_RC2: + return CKM_RC2_CBC; + case CKK_RC4: + return CKM_RC4; + case CKK_RC5: + return CKM_RC5_CBC; + case CKK_SKIPJACK: + return CKM_SKIPJACK_CBC64; + case CKK_BATON: + return CKM_BATON_CBC128; + case CKK_JUNIPER: + return CKM_JUNIPER_CBC128; + case CKK_IDEA: + return CKM_IDEA_CBC; + case CKK_CAST: + return CKM_CAST_CBC; + case CKK_CAST3: + return CKM_CAST3_CBC; + case CKK_CAST5: + return CKM_CAST5_CBC; + case CKK_RSA: + return CKM_RSA_PKCS; + case CKK_DSA: + return CKM_DSA; + case CKK_DH: + return CKM_DH_PKCS_DERIVE; + case CKK_KEA: + return CKM_KEA_KEY_DERIVE; + case CKK_EC: /* CKK_ECDSA is deprecated */ + return CKM_ECDSA; + case CKK_GENERIC_SECRET: + default: + return CKM_SHA_1_HMAC; + } +} /* * Get the key type needed for the given mechanism */ @@ -3053,6 +3105,12 @@ PK11_GetKeyType(CK_MECHANISM_TYPE type,unsigned long len) */ CK_MECHANISM_TYPE PK11_GetKeyGen(CK_MECHANISM_TYPE type) +{ + return PK11_GetKeyGenWithSize(type, 0); +} + +CK_MECHANISM_TYPE +PK11_GetKeyGenWithSize(CK_MECHANISM_TYPE type, int size) { switch (type) { case CKM_AES_ECB: @@ -3075,6 +3133,7 @@ PK11_GetKeyGen(CK_MECHANISM_TYPE type) case CKM_DES3_MAC: case CKM_DES3_MAC_GENERAL: case CKM_DES3_CBC_PAD: + return (size == 16) ? CKM_DES2_KEY_GEN : CKM_DES3_KEY_GEN; case CKM_DES3_KEY_GEN: return CKM_DES3_KEY_GEN; case CKM_DES2_KEY_GEN: diff --git a/security/nss/lib/softoken/pkcs11.c b/security/nss/lib/softoken/pkcs11.c index 1b524a62ee0d..5c3e5ed52b30 100644 --- a/security/nss/lib/softoken/pkcs11.c +++ b/security/nss/lib/softoken/pkcs11.c @@ -2160,6 +2160,8 @@ pk11_mkSecretKeyRep(PK11Object *object) { NSSLOWKEYPrivateKey *privKey = 0; PLArenaPool *arena = 0; + CK_KEY_TYPE keyType; + SECItem keyTypeItem; CK_RV crv; SECStatus rv; static unsigned char derZero[1] = { 0 }; @@ -2210,9 +2212,17 @@ pk11_mkSecretKeyRep(PK11Object *object) privKey->u.rsa.exponent2.data = derZero; /* Coeficient set to KEY_TYPE */ - crv=pk11_Attribute2SecItem(arena,&privKey->u.rsa.coefficient,object,CKA_KEY_TYPE); + crv = pk11_GetULongAttribute(object, CKA_KEY_TYPE, &keyType); if (crv != CKR_OK) goto loser; - + keyType = PR_htonl(keyType); + keyTypeItem.data = (unsigned char *)&keyType; + keyTypeItem.len = sizeof (keyType); + rv = SECITEM_CopyItem(arena, &privKey->u.rsa.coefficient, &keyTypeItem); + if (rv != SECSuccess) { + crv = CKR_HOST_MEMORY; + goto loser; + } + /* Private key version field set normally for compatibility */ rv = DER_SetUInteger(privKey->arena, &privKey->u.rsa.version, NSSLOWKEY_VERSION); @@ -4108,7 +4118,7 @@ loser: static void pk11_searchKeys(PK11Slot *slot, SECItem *key_id, PRBool isLoggedIn, - unsigned long classFlags, PK11SearchResults *search, + unsigned long classFlags, PK11SearchResults *search, PRBool mustStrict, CK_ATTRIBUTE *pTemplate, CK_ULONG ulCount) { NSSLOWKEYDBHandle *keyHandle = NULL; @@ -4162,7 +4172,7 @@ pk11_searchKeys(PK11Slot *slot, SECItem *key_id, PRBool isLoggedIn, keyData.templ_count = ulCount; keyData.isLoggedIn = isLoggedIn; keyData.classFlags = classFlags; - keyData.strict = NSC_STRICT; + keyData.strict = mustStrict ? mustStrict : NSC_STRICT; nsslowkey_TraverseKeys(keyHandle, pk11_key_collect, &keyData); } @@ -4625,8 +4635,9 @@ pk11_searchTokenList(PK11Slot *slot, PK11SearchResults *search, /* keys */ if (classFlags & (NSC_PRIVATE|NSC_PUBLIC|NSC_KEY)) { + PRBool mustStrict = ((classFlags & NSC_KEY) != 0) && (name.len != 0); pk11_searchKeys(slot, &key_id, isLoggedIn, classFlags, search, - pTemplate, ulCount); + mustStrict, pTemplate, ulCount); } /* crl's */ diff --git a/security/nss/lib/softoken/pkcs11i.h b/security/nss/lib/softoken/pkcs11i.h index 27375b679ef5..0f382f8ba6f5 100644 --- a/security/nss/lib/softoken/pkcs11i.h +++ b/security/nss/lib/softoken/pkcs11i.h @@ -600,6 +600,8 @@ extern PK11ModifyType pk11_modifyType(CK_ATTRIBUTE_TYPE type, extern PRBool pk11_isSensitive(CK_ATTRIBUTE_TYPE type, CK_OBJECT_CLASS inClass); extern char *pk11_getString(PK11Object *object, CK_ATTRIBUTE_TYPE type); extern void pk11_nullAttribute(PK11Object *object,CK_ATTRIBUTE_TYPE type); +extern CK_RV pk11_GetULongAttribute(PK11Object *object, CK_ATTRIBUTE_TYPE type, + CK_ULONG *longData); extern CK_RV pk11_forceAttribute(PK11Object *object, CK_ATTRIBUTE_TYPE type, void *value, unsigned int len); extern CK_RV pk11_defaultAttribute(PK11Object *object, CK_ATTRIBUTE_TYPE type, diff --git a/security/nss/lib/softoken/pkcs11u.c b/security/nss/lib/softoken/pkcs11u.c index 16f5c282a2bd..b8d8db941ed5 100644 --- a/security/nss/lib/softoken/pkcs11u.c +++ b/security/nss/lib/softoken/pkcs11u.c @@ -682,8 +682,11 @@ pk11_FindSecretKeyAttribute(PK11TokenObject *object, CK_ATTRIBUTE_TYPE type) { NSSLOWKEYPrivateKey *key; char *label; + unsigned char *keyString; PK11Attribute *att; + int keyTypeLen; CK_ULONG keyLen; + CK_KEY_TYPE keyType; switch (type) { case CKA_PRIVATE: @@ -724,8 +727,30 @@ pk11_FindSecretKeyAttribute(PK11TokenObject *object, CK_ATTRIBUTE_TYPE type) } switch (type) { case CKA_KEY_TYPE: - return pk11_NewTokenAttribute(type,key->u.rsa.coefficient.data, - key->u.rsa.coefficient.len, PR_FALSE); + /* handle legacy databases. In legacy databases key_type was stored + * in host order, with any leading zeros stripped off. Only key types + * under 0x1f (AES) were stored. We assume that any values which are + * either 1 byte long (big endian), or have byte[0] between 0 and + * 0x1f and bytes[1]-bytes[3] equal to '0' (little endian). All other + * values are assumed to be from the new database, which is always 4 + * bytes in host order */ + keyType=0; + keyString = key->u.rsa.coefficient.data; + keyTypeLen = key->u.rsa.coefficient.len; + /* only length of 1 or 4 are valid */ + if ((keyTypeLen != sizeof(keyType)) && (keyTypeLen != 1)) { + PORT_SetError(SEC_ERROR_BAD_DATABASE); + return NULL; + } + if ((keyTypeLen == 1) || + ((keyString[0] <= 0x1f) && (keyString[1] == 0) && + (keyString[2] == 0) && (keyString[3] == 0))) { + keyType = (CK_KEY_TYPE) keyString[0] ; + } else { + keyType = *(CK_KEY_TYPE *) keyString; + keyType = PR_ntohl(keyType); + } + return pk11_NewTokenAttribute(type,&keyType,sizeof(keyType),PR_TRUE); case CKA_VALUE: return pk11_NewTokenAttribute(type,key->u.rsa.privateExponent.data, key->u.rsa.privateExponent.len, PR_FALSE); @@ -1892,6 +1917,25 @@ pk11_Attribute2SecItem(PLArenaPool *arena,SECItem *item,PK11Object *object, return CKR_OK; } +CK_RV +pk11_GetULongAttribute(PK11Object *object, CK_ATTRIBUTE_TYPE type, + CK_ULONG *longData) +{ + int len; + PK11Attribute *attribute; + + attribute = pk11_FindAttribute(object, type); + if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE; + + if (attribute->attrib.ulValueLen != sizeof(CK_ULONG)) { + return CKR_ATTRIBUTE_VALUE_INVALID; + } + + *longData = *(CK_ULONG *)attribute->attrib.pValue; + pk11_FreeAttribute(attribute); + return CKR_OK; +} + void pk11_DeleteAttributeType(PK11Object *object,CK_ATTRIBUTE_TYPE type) { @@ -2133,7 +2177,7 @@ pk11_NewObject(PK11Slot *slot) object->handle = 0; object->next = object->prev = NULL; object->slot = slot; - object->objclass = 0xffff; + object->refCount = 1; sessObject->sessionList.next = NULL; sessObject->sessionList.prev = NULL;