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 /security/nss/lib/pk11wrap/pk11skey.c | |
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.
Diffstat (limited to 'security/nss/lib/pk11wrap/pk11skey.c')
-rw-r--r-- | security/nss/lib/pk11wrap/pk11skey.c | 258 |
1 files changed, 250 insertions, 8 deletions
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); +} + |