bug 279042 First performance improvement patch for shared db.
authorrrelyea%redhat.com
Thu, 06 Sep 2007 20:47:34 +0000
changeset 8036 f3682f2e22305a7f0b2cc5898af6abeed491d986
parent 8035 19622fc52fc4c64eac6f333d8abaa1cea2c14ddb
child 8037 1887266437e0d56ab6286b0b185272f561e1d1ff
push idunknown
push userunknown
push dateunknown
bugs279042
bug 279042 First performance improvement patch for shared db. r=neil
security/nss/lib/softoken/pkcs11.c
security/nss/lib/softoken/pkcs11i.h
security/nss/lib/softoken/pkcs11u.c
--- a/security/nss/lib/softoken/pkcs11.c
+++ b/security/nss/lib/softoken/pkcs11.c
@@ -1584,21 +1584,22 @@ NSSLOWKEYPublicKey *sftk_GetPubKey(SFTKO
     return pubKey;
 }
 
 /* make a private key from a verified object */
 static NSSLOWKEYPrivateKey *
 sftk_mkPrivKey(SFTKObject *object, CK_KEY_TYPE key_type, CK_RV *crvp)
 {
     NSSLOWKEYPrivateKey *privKey;
+    SFTKItemTemplate itemTemplate[SFTK_MAX_ITEM_TEMPLATE];
+    int itemTemplateCount = 0;
     PLArenaPool *arena;
     CK_RV crv = CKR_OK;
     SECStatus rv;
 
-    /*PORT_Assert(!sftk_isToken(object->handle)); */
     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
     if (arena == NULL) {
 	*crvp = CKR_HOST_MEMORY;
 	return NULL;
     }
 
     privKey = (NSSLOWKEYPrivateKey *)
 			PORT_ArenaZAlloc(arena,sizeof(NSSLOWKEYPrivateKey));
@@ -1608,122 +1609,122 @@ sftk_mkPrivKey(SFTKObject *object, CK_KE
 	return NULL;
     }
 
     /* in future this would be a switch on key_type */
     privKey->arena = arena;
     switch (key_type) {
     case CKK_RSA:
 	privKey->keyType = NSSLOWKEYRSAKey;
-	crv=sftk_Attribute2SSecItem(arena,&privKey->u.rsa.modulus,
-							object,CKA_MODULUS);
-	if (crv != CKR_OK) break;
-	crv=sftk_Attribute2SSecItem(arena,&privKey->u.rsa.publicExponent,object,
-							CKA_PUBLIC_EXPONENT);
-	if (crv != CKR_OK) break;
-	crv=sftk_Attribute2SSecItem(arena,&privKey->u.rsa.privateExponent,object,
-							CKA_PRIVATE_EXPONENT);
-	if (crv != CKR_OK) break;
-	crv=sftk_Attribute2SSecItem(arena,&privKey->u.rsa.prime1,object,
-								CKA_PRIME_1);
-	if (crv != CKR_OK) break;
-	crv=sftk_Attribute2SSecItem(arena,&privKey->u.rsa.prime2,object,
-								CKA_PRIME_2);
-	if (crv != CKR_OK) break;
-	crv=sftk_Attribute2SSecItem(arena,&privKey->u.rsa.exponent1,
-						object, CKA_EXPONENT_1);
-	if (crv != CKR_OK) break;
-	crv=sftk_Attribute2SSecItem(arena,&privKey->u.rsa.exponent2,
-							object, CKA_EXPONENT_2);
-	if (crv != CKR_OK) break;
-	crv=sftk_Attribute2SSecItem(arena,&privKey->u.rsa.coefficient,object,
-							      CKA_COEFFICIENT);
-	if (crv != CKR_OK) break;
+
+	SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount,
+		&privKey->u.rsa.modulus,CKA_MODULUS);
+	itemTemplateCount++;
+	SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount,
+		&privKey->u.rsa.publicExponent, CKA_PUBLIC_EXPONENT);
+	itemTemplateCount++;
+	SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount,
+		&privKey->u.rsa.privateExponent, CKA_PRIVATE_EXPONENT);
+	itemTemplateCount++;
+	SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount,
+		&privKey->u.rsa.prime1, CKA_PRIME_1);
+	itemTemplateCount++;
+	SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount,
+		&privKey->u.rsa.prime2, CKA_PRIME_2);
+	itemTemplateCount++;
+	SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount,
+		&privKey->u.rsa.exponent1, CKA_EXPONENT_1);
+	itemTemplateCount++;
+	SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount,
+		&privKey->u.rsa.exponent2, CKA_EXPONENT_2);
+	itemTemplateCount++;
+	SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount,
+		&privKey->u.rsa.coefficient, CKA_COEFFICIENT);
+	itemTemplateCount++;
         rv = DER_SetUInteger(privKey->arena, &privKey->u.rsa.version,
                           NSSLOWKEY_PRIVATE_KEY_INFO_VERSION);
 	if (rv != SECSuccess) crv = CKR_HOST_MEMORY;
 	break;
 
     case CKK_DSA:
 	privKey->keyType = NSSLOWKEYDSAKey;
-	crv = sftk_Attribute2SSecItem(arena,&privKey->u.dsa.params.prime,
-							object,CKA_PRIME);
-    	if (crv != CKR_OK) break;
-	crv = sftk_Attribute2SSecItem(arena,&privKey->u.dsa.params.subPrime,
-							object,CKA_SUBPRIME);
-    	if (crv != CKR_OK) break;
-	crv = sftk_Attribute2SSecItem(arena,&privKey->u.dsa.params.base,
-							object,CKA_BASE);
-    	if (crv != CKR_OK) break;
-    	crv = sftk_Attribute2SSecItem(arena,&privKey->u.dsa.privateValue,
-							object,CKA_VALUE);
-    	if (crv != CKR_OK) break;
-	if (sftk_hasAttribute(object,CKA_NETSCAPE_DB)) {
-	    crv = sftk_Attribute2SSecItem(arena, &privKey->u.dsa.publicValue,
-				      object,CKA_NETSCAPE_DB);
-	    /* privKey was zero'd so public value is already set to NULL, 0
-	     * if we don't set it explicitly */
-	}
+	SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount,
+		&privKey->u.dsa.params.prime, CKA_PRIME);
+	itemTemplateCount++;
+	SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount,
+		&privKey->u.dsa.params.subPrime, CKA_SUBPRIME);
+	itemTemplateCount++;
+	SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount,
+		&privKey->u.dsa.params.base, CKA_BASE);
+	itemTemplateCount++;
+	SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount,
+		&privKey->u.dsa.privateValue, CKA_VALUE);
+	itemTemplateCount++;
+	/* privKey was zero'd so public value is already set to NULL, 0
+	 * if we don't set it explicitly */
 	break;
 
     case CKK_DH:
 	privKey->keyType = NSSLOWKEYDHKey;
-	crv = sftk_Attribute2SSecItem(arena,&privKey->u.dh.prime,
-							object,CKA_PRIME);
-    	if (crv != CKR_OK) break;
-	crv = sftk_Attribute2SSecItem(arena,&privKey->u.dh.base,
-							object,CKA_BASE);
-    	if (crv != CKR_OK) break;
-    	crv = sftk_Attribute2SSecItem(arena,&privKey->u.dh.privateValue,
-							object,CKA_VALUE);
-    	if (crv != CKR_OK) break;
-	if (sftk_hasAttribute(object,CKA_NETSCAPE_DB)) {
-	    crv = sftk_Attribute2SSecItem(arena, &privKey->u.dh.publicValue,
-				      object,CKA_NETSCAPE_DB);
-	    /* privKey was zero'd so public value is already set to NULL, 0
-	     * if we don't set it explicitly */
-	}
+	SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount,
+		&privKey->u.dh.prime, CKA_PRIME);
+	itemTemplateCount++;
+	SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount,
+		&privKey->u.dh.base, CKA_BASE);
+	itemTemplateCount++;
+	SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount,
+		&privKey->u.dh.privateValue, CKA_VALUE);
+	itemTemplateCount++;
+	/* privKey was zero'd so public value is already set to NULL, 0
+	 * if we don't set it explicitly */
 	break;
 
 #ifdef NSS_ENABLE_ECC
     case CKK_EC:
 	privKey->keyType = NSSLOWKEYECKey;
 	crv = sftk_Attribute2SSecItem(arena, 
-	                              &privKey->u.ec.ecParams.DEREncoding,
-	                              object,CKA_EC_PARAMS);
+				      &privKey->u.ec.ecParams.DEREncoding,
+				      object,CKA_EC_PARAMS);
     	if (crv != CKR_OK) break;
 
 	/* Fill out the rest of the ecParams structure
 	 * based on the encoded params
 	 */
 	if (EC_FillParams(arena, &privKey->u.ec.ecParams.DEREncoding,
 		    &privKey->u.ec.ecParams) != SECSuccess) {
 	    crv = CKR_DOMAIN_PARAMS_INVALID;
 	    break;
 	}
 	crv = sftk_Attribute2SSecItem(arena,&privKey->u.ec.privateValue,
 							object,CKA_VALUE);
 	if (crv != CKR_OK) break;
-	if (sftk_hasAttribute(object,CKA_NETSCAPE_DB)) {
+
+	if (sftk_hasAttribute(object, CKA_NETSCAPE_DB)) {
 	    crv = sftk_Attribute2SSecItem(arena, &privKey->u.ec.publicValue,
-				      object,CKA_NETSCAPE_DB);
+ 				object, CKA_NETSCAPE_DB);
 	    if (crv != CKR_OK) break;
 	    /* privKey was zero'd so public value is already set to NULL, 0
 	     * if we don't set it explicitly */
 	}
         rv = DER_SetUInteger(privKey->arena, &privKey->u.ec.version,
                           NSSLOWKEY_EC_PRIVATE_KEY_VERSION);
 	if (rv != SECSuccess) crv = CKR_HOST_MEMORY;
 	break;
 #endif /* NSS_ENABLE_ECC */
 
     default:
 	crv = CKR_KEY_TYPE_INCONSISTENT;
 	break;
     }
+    if (crv == CKR_OK && itemTemplateCount != 0) {
+	PORT_Assert(itemTemplateCount > 0);
+	PORT_Assert(itemTemplateCount <= SFTK_MAX_ITEM_TEMPLATE);
+	crv = sftk_MultipleAttribute2SecItem(arena, object, itemTemplate, 
+						itemTemplateCount);
+    }
     *crvp = crv;
     if (crv != CKR_OK) {
 	PORT_FreeArena(arena,PR_FALSE);
 	return NULL;
     }
     return privKey;
 }
 
@@ -1738,30 +1739,17 @@ sftk_GetPrivKey(SFTKObject *object,CK_KE
 	*crvp = CKR_KEY_TYPE_INCONSISTENT;
 	return NULL;
     }
     if (object->objectInfo) {
 	*crvp = CKR_OK;
 	return (NSSLOWKEYPrivateKey *)object->objectInfo;
     }
 
-#ifdef notdef
-    if (sftk_isToken(object->handle)) {
-	/* grab it from the data base */
-	SFTKTokenObject *to = sftk_narrowToTokenObject(object);
-
-	PORT_Assert(to);
-	priv = sftk_FindKeyByPublicKey(object->slot, &to->dbKey);
-	*crvp = (priv == NULL) ? CKR_DEVICE_ERROR : CKR_OK;
-    } else {
-	priv = sftk_mkPrivKey(object, key_type, crvp);
-    }
-#else
     priv = sftk_mkPrivKey(object, key_type, crvp);
-#endif
     object->objectInfo = priv;
     object->infoFree = (SFTKFree) nsslowkey_DestroyPrivateKey;
     return priv;
 }
 
 /*
  **************************** Symetric Key utils ************************
  */
--- a/security/nss/lib/softoken/pkcs11i.h
+++ b/security/nss/lib/softoken/pkcs11i.h
@@ -131,16 +131,17 @@ typedef struct SFTKSessionObjectStr SFTK
 typedef struct SFTKTokenObjectStr SFTKTokenObject;
 typedef struct SFTKSessionStr SFTKSession;
 typedef struct SFTKSlotStr SFTKSlot;
 typedef struct SFTKSessionContextStr SFTKSessionContext;
 typedef struct SFTKSearchResultsStr SFTKSearchResults;
 typedef struct SFTKHashVerifyInfoStr SFTKHashVerifyInfo;
 typedef struct SFTKHashSignInfoStr SFTKHashSignInfo;
 typedef struct SFTKSSLMACInfoStr SFTKSSLMACInfo;
+typedef struct SFTKItemTemplateStr SFTKItemTemplate;
 
 /* define function pointer typdefs for pointer tables */
 typedef void (*SFTKDestroy)(void *, PRBool);
 typedef void (*SFTKBegin)(void *);
 typedef SECStatus (*SFTKCipher)(void *,void *,unsigned int *,unsigned int,
 					void *, unsigned int);
 typedef SECStatus (*SFTKVerify)(void *,void *,unsigned int,void *,unsigned int);
 typedef void (*SFTKHash)(void *,void *,unsigned int);
@@ -399,16 +400,31 @@ struct SFTKSSLMACInfoStr {
     SFTKEnd		end;
     CK_ULONG		macSize;
     int			padSize;
     unsigned char	key[MAX_KEY_LEN];
     unsigned int	keySize;
 };
 
 /*
+ * Template based on SECItems, suitable for passing as arrays
+ */
+struct SFTKItemTemplateStr {
+    CK_ATTRIBUTE_TYPE	type;
+    SECItem		*item;
+};
+
+/* macro for setting SFTKTemplates. */
+#define SFTK_SET_ITEM_TEMPLATE(templ, count, itemPtr, attr) \
+   templ[count].type = attr; \
+   templ[count].item = itemPtr
+
+#define SFTK_MAX_ITEM_TEMPLATE 10
+
+/*
  * session handle modifiers
  */
 #define SFTK_SESSION_SLOT_MASK	0xff000000L
 
 /*
  * object handle modifiers
  */
 #define SFTK_TOKEN_MASK		0x80000000L
@@ -576,16 +592,18 @@ extern CK_RV SFTK_ShutdownSlot(SFTKSlot 
 extern SFTKAttribute *sftk_FindAttribute(SFTKObject *object,
 					 CK_ATTRIBUTE_TYPE type);
 extern void sftk_FreeAttribute(SFTKAttribute *attribute);
 extern CK_RV sftk_AddAttributeType(SFTKObject *object, CK_ATTRIBUTE_TYPE type,
 				   void *valPtr,
 				  CK_ULONG length);
 extern CK_RV sftk_Attribute2SecItem(PLArenaPool *arena, SECItem *item,
 				    SFTKObject *object, CK_ATTRIBUTE_TYPE type);
+extern CK_RV sftk_MultipleAttribute2SecItem(PLArenaPool *arena, 
+		SFTKObject *object, SFTKItemTemplate *templ, int count);
 extern unsigned int sftk_GetLengthInBits(unsigned char *buf,
 							 unsigned int bufLen);
 extern CK_RV sftk_ConstrainAttribute(SFTKObject *object, 
 	CK_ATTRIBUTE_TYPE type, int minLength, int maxLength, int minMultiple);
 extern PRBool sftk_hasAttribute(SFTKObject *object, CK_ATTRIBUTE_TYPE type);
 extern PRBool sftk_isTrue(SFTKObject *object, CK_ATTRIBUTE_TYPE type);
 extern void sftk_DeleteAttributeType(SFTKObject *object,
 				     CK_ATTRIBUTE_TYPE type);
--- a/security/nss/lib/softoken/pkcs11u.c
+++ b/security/nss/lib/softoken/pkcs11u.c
@@ -356,16 +356,116 @@ sftk_Attribute2SSecItem(PLArenaPool *are
 	sftk_FreeAttribute(attribute);
 	return CKR_HOST_MEMORY;
     }
     PORT_Memcpy(item->data, attribute->attrib.pValue, item->len);
     sftk_FreeAttribute(attribute);
     return CKR_OK;
 }
 
+/* 
+ * fetch multiple attributes into  SECItems. Secitem data is allocated in
+ * the specified arena.
+ */
+CK_RV
+sftk_MultipleAttribute2SecItem(PLArenaPool *arena, SFTKObject *object,
+	 SFTKItemTemplate *itemTemplate, int itemTemplateCount)
+{
+
+    CK_RV crv = CKR_OK;
+    CK_ATTRIBUTE templateSpace[SFTK_MAX_ITEM_TEMPLATE];
+    CK_ATTRIBUTE *template;
+    SFTKTokenObject *tokObject;
+    SFTKDBHandle *dbHandle = NULL;
+    int i;
+
+    tokObject = sftk_narrowToTokenObject(object);
+
+    /* session objects, just loop through the list */
+    if (tokObject == NULL) {
+	for (i=0; i < itemTemplateCount; i++) {
+	    crv = sftk_Attribute2SecItem(arena,itemTemplate[i].item, object,
+					 itemTemplate[i].type);
+	    if (crv != CKR_OK) {
+		return crv;
+	    }
+	}
+	return CKR_OK;
+    }
+
+    /* don't do any work if none is required */
+    if (itemTemplateCount == 0) {
+	return CKR_OK;
+    }
+
+    /* don't allocate the template unless we need it */
+    if (itemTemplateCount > SFTK_MAX_ITEM_TEMPLATE) {
+	template = PORT_NewArray(CK_ATTRIBUTE, itemTemplateCount);
+    } else {
+	template = templateSpace;
+    }
+
+    if (template == NULL) {
+	crv = CKR_HOST_MEMORY;
+	goto loser;
+    }
+
+    dbHandle = sftk_getDBForTokenObject(object->slot, object->handle);
+    if (dbHandle == NULL) {
+	crv = CKR_OBJECT_HANDLE_INVALID;
+	goto loser;
+    }
+
+    /* set up the PKCS #11 template */
+    for (i=0; i < itemTemplateCount; i++) {
+	template[i].type = itemTemplate[i].type;
+	template[i].pValue = NULL;
+	template[i].ulValueLen = 0;
+    }
+
+    /* fetch the attribute lengths */
+    crv = sftkdb_GetAttributeValue(dbHandle, object->handle,
+				   template, itemTemplateCount);
+    if (crv != CKR_OK) {
+	goto loser;
+    }
+
+    /* allocate space for the attributes */
+    for (i=0; i < itemTemplateCount ; i++) {
+	template[i].pValue = PORT_ArenaAlloc(arena, template[i].ulValueLen);
+	if (template[i].pValue == NULL) {
+	    crv = CKR_HOST_MEMORY;
+	    goto loser;
+	}
+    }
+
+    /* fetch the attributes */
+    crv = sftkdb_GetAttributeValue(dbHandle, object->handle,
+				   template, itemTemplateCount);
+    if (crv != CKR_OK) {
+	goto loser;
+    }
+
+    /* Fill in the items */	
+    for (i=0; i < itemTemplateCount; i++) {
+	itemTemplate[i].item->data = template[i].pValue;
+	itemTemplate[i].item->len = template[i].ulValueLen;
+    }
+
+loser:
+    if (template != templateSpace) {
+	PORT_Free(template);
+    }
+    if (dbHandle) {
+	sftk_freeDB(dbHandle);
+    }
+	     
+    return crv;
+}
+
 
 /*
  * delete an attribute from an object
  */
 static void
 sftk_DeleteAttribute(SFTKObject *object, SFTKAttribute *attribute)
 {
     SFTKSessionObject *sessObject = sftk_narrowToSessionObject(object);