Index: nss/mozilla/security/nss/lib/softoken/sftkdb.c |
=================================================================== |
--- nss/mozilla/security/nss/lib/softoken/sftkdb.c (revision 55475) |
+++ nss/mozilla/security/nss/lib/softoken/sftkdb.c (working copy) |
@@ -509,18 +509,23 @@ |
CK_ULONG count) |
{ |
int i; |
+ CK_RV crv; |
SFTKDBHandle *keyHandle = handle; |
SDB *keyTarget = NULL; |
+ PRBool usingPeerDB = PR_FALSE; |
+ PRBool inPeerDBTransaction = PR_FALSE; |
PORT_Assert(handle); |
if (handle->type != SFTK_KEYDB_TYPE) { |
keyHandle = handle->peerDB; |
+ usingPeerDB = PR_TRUE; |
} |
/* no key DB defined? then no need to sign anything */ |
if (keyHandle == NULL) { |
- return CKR_OK; |
+ crv = CKR_OK; |
+ goto loser; |
} |
/* When we are in a middle of an update, we have an update database set, |
@@ -532,9 +537,19 @@ |
/* skip the the database does not support meta data */ |
if ((keyTarget->sdb_flags & SDB_HAS_META) == 0) { |
- return CKR_OK; |
+ crv = CKR_OK; |
+ goto loser; |
} |
+ /* If we had to switch databases, we need to initialize a transaction. */ |
+ if (usingPeerDB) { |
+ crv = (*keyTarget->sdb_Begin)(keyTarget); |
+ if (crv != CKR_OK) { |
+ goto loser; |
+ } |
+ inPeerDBTransaction = PR_TRUE; |
+ } |
+ |
for (i=0; i < count; i ++) { |
if (sftkdb_isAuthenticatedAttribute(template[i].type)) { |
SECStatus rv; |
@@ -546,23 +561,44 @@ |
PZ_Lock(keyHandle->passwordLock); |
if (keyHandle->passwordKey.data == NULL) { |
PZ_Unlock(keyHandle->passwordLock); |
- return CKR_USER_NOT_LOGGED_IN; |
+ crv = CKR_USER_NOT_LOGGED_IN; |
+ goto loser; |
} |
rv = sftkdb_SignAttribute(arena, &keyHandle->passwordKey, |
objectID, template[i].type, |
&plainText, &signText); |
PZ_Unlock(keyHandle->passwordLock); |
if (rv != SECSuccess) { |
- return CKR_GENERAL_ERROR; /* better error code here? */ |
+ crv = CKR_GENERAL_ERROR; /* better error code here? */ |
+ goto loser; |
} |
rv = sftkdb_PutAttributeSignature(handle, keyTarget, |
objectID, template[i].type, signText); |
if (rv != SECSuccess) { |
- return CKR_GENERAL_ERROR; /* better error code here? */ |
+ crv = CKR_GENERAL_ERROR; /* better error code here? */ |
+ goto loser; |
} |
} |
} |
- return CKR_OK; |
+ crv = CKR_OK; |
+ |
+ /* If necessary, commit the transaction */ |
+ if (inPeerDBTransaction) { |
+ crv = (*keyTarget->sdb_Commit)(keyTarget); |
+ if (crv != CKR_OK) { |
+ goto loser; |
+ } |
+ inPeerDBTransaction = PR_FALSE; |
+ } |
+ |
+loser: |
+ if (inPeerDBTransaction) { |
+ /* The transaction must have failed. Abort. */ |
+ (*keyTarget->sdb_Abort)(keyTarget); |
+ PORT_Assert(crv != CKR_OK); |
+ if (crv == CKR_OK) crv = CKR_GENERAL_ERROR; |
+ } |
+ return crv; |
} |
static CK_RV |
@@ -766,6 +802,12 @@ |
if (attr == NULL) { |
return CKR_TEMPLATE_INCOMPLETE; |
} |
+ if (attr->ulValueLen == 0) { |
+ /* key is too generic to determine that it's unique, usually |
+ * happens in the key gen case */ |
+ return CKR_OBJECT_HANDLE_INVALID; |
+ } |
+ |
findTemplate[1] = *attr; |
count = 2; |
break; |
@@ -807,7 +849,7 @@ |
} |
/* |
- * look to see if this object already exists and return it's object ID if |
+ * look to see if this object already exists and return its object ID if |
* it does. |
*/ |
static CK_RV |
@@ -827,6 +869,13 @@ |
} |
crv = sftkdb_getFindTemplate(objectType, objTypeData, |
findTemplate, &count, ptemplate, len); |
+ |
+ if (crv == CKR_OBJECT_HANDLE_INVALID) { |
+ /* key is too generic to determine that it's unique, usually |
+ * happens in the key gen case, tell the caller to go ahead |
+ * and just create it */ |
+ return CKR_OK; |
+ } |
if (crv != CKR_OK) { |
return crv; |
} |