summaryrefslogtreecommitdiff
path: root/security/nss/lib/pk11wrap/pk11skey.c
diff options
context:
space:
mode:
authorrelyea%netscape.com <devnull@localhost>2004-06-21 23:01:53 +0000
committerrelyea%netscape.com <devnull@localhost>2004-06-21 23:01:53 +0000
commit1d771e02adae5ef24c69569c3163a08c6156af7e (patch)
treeae0db9acb686019363e5cde1c10bb675c0294c25 /security/nss/lib/pk11wrap/pk11skey.c
parentdb2ae0729b55f63331b7b49903f6a1bd3863cb9f (diff)
downloadnss-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.c258
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);
+}
+