summaryrefslogtreecommitdiff
path: root/security/nss/lib/softoken/sftkdb.c
diff options
context:
space:
mode:
authorMoonchild <moonchild@palemoon.org>2020-12-23 19:02:52 +0000
committerMoonchild <moonchild@palemoon.org>2020-12-23 19:02:52 +0000
commit029bcfe189eae5eebbaf58ccff4e1200dd78b228 (patch)
tree1c226a334ea1a88e2d1c6f949c9320eb0c3bff59 /security/nss/lib/softoken/sftkdb.c
parent149d2ffa779826cb48a381099858e76e4624d471 (diff)
downloaduxp-029bcfe189eae5eebbaf58ccff4e1200dd78b228.tar.gz
Issue #1693 - Update NSS to 3.59.1.1
This updates to MoonchildProductions/NSS@bd49b2b88 in the repo created for our consumption of the library.
Diffstat (limited to 'security/nss/lib/softoken/sftkdb.c')
-rw-r--r--security/nss/lib/softoken/sftkdb.c276
1 files changed, 244 insertions, 32 deletions
diff --git a/security/nss/lib/softoken/sftkdb.c b/security/nss/lib/softoken/sftkdb.c
index 61cb2ce8b9..a1a723fe87 100644
--- a/security/nss/lib/softoken/sftkdb.c
+++ b/security/nss/lib/softoken/sftkdb.c
@@ -245,21 +245,44 @@ sftkdb_TypeString(SFTKDBHandle *handle)
* function will fail with CKR_BUFFER_TOO_SMALL.
*/
static CK_RV
-sftkdb_getAttributeSignature(SFTKDBHandle *handle, SFTKDBHandle *keyHandle,
+sftkdb_getRawAttributeSignature(SFTKDBHandle *handle, SDB *db,
+ CK_OBJECT_HANDLE objectID,
+ CK_ATTRIBUTE_TYPE type,
+ SECItem *signText)
+{
+ char id[30];
+ CK_RV crv;
+
+ sprintf(id, SFTKDB_META_SIG_TEMPLATE,
+ sftkdb_TypeString(handle),
+ (unsigned int)objectID, (unsigned int)type);
+
+ crv = (*db->sdb_GetMetaData)(db, id, signText, NULL);
+ return crv;
+}
+
+CK_RV
+sftkdb_GetAttributeSignature(SFTKDBHandle *handle, SFTKDBHandle *keyHandle,
CK_OBJECT_HANDLE objectID, CK_ATTRIBUTE_TYPE type,
SECItem *signText)
{
- SDB *db;
+ SDB *db = SFTK_GET_SDB(keyHandle);
+ return sftkdb_getRawAttributeSignature(handle, db, objectID, type, signText);
+}
+
+CK_RV
+sftkdb_DestroyAttributeSignature(SFTKDBHandle *handle, SDB *db,
+ CK_OBJECT_HANDLE objectID,
+ CK_ATTRIBUTE_TYPE type)
+{
char id[30];
CK_RV crv;
- db = SFTK_GET_SDB(keyHandle);
-
sprintf(id, SFTKDB_META_SIG_TEMPLATE,
sftkdb_TypeString(handle),
(unsigned int)objectID, (unsigned int)type);
- crv = (*db->sdb_GetMetaData)(db, id, signText, NULL);
+ crv = (*db->sdb_DestroyMetaData)(db, id);
return crv;
}
@@ -363,7 +386,10 @@ sftkdb_fixupTemplateOut(CK_ATTRIBUTE *template, CK_OBJECT_HANDLE objectID,
crv = CKR_USER_NOT_LOGGED_IN;
continue;
}
- rv = sftkdb_DecryptAttribute(&handle->passwordKey,
+ rv = sftkdb_DecryptAttribute(handle,
+ &handle->passwordKey,
+ objectID,
+ ntemplate[i].type,
&cipherText, &plainText);
PZ_Unlock(handle->passwordLock);
if (rv != SECSuccess) {
@@ -389,6 +415,7 @@ sftkdb_fixupTemplateOut(CK_ATTRIBUTE *template, CK_OBJECT_HANDLE objectID,
/* make sure signed attributes are valid */
if (checkSig && sftkdb_isAuthenticatedAttribute(ntemplate[i].type)) {
SECStatus rv;
+ CK_RV local_crv;
SECItem signText;
SECItem plainText;
unsigned char signData[SDB_MAX_META_DATA_LEN];
@@ -396,12 +423,17 @@ sftkdb_fixupTemplateOut(CK_ATTRIBUTE *template, CK_OBJECT_HANDLE objectID,
signText.data = signData;
signText.len = sizeof(signData);
- rv = sftkdb_getAttributeSignature(handle, keyHandle,
- objectID, ntemplate[i].type, &signText);
- if (rv != SECSuccess) {
+ /* Use a local variable so that we don't clobber any already
+ * set error. This function returns either CKR_OK or the last
+ * found error in the template */
+ local_crv = sftkdb_GetAttributeSignature(handle, keyHandle,
+ objectID,
+ ntemplate[i].type,
+ &signText);
+ if (local_crv != CKR_OK) {
PORT_Memset(template[i].pValue, 0, template[i].ulValueLen);
template[i].ulValueLen = -1;
- crv = CKR_DATA_INVALID; /* better error code? */
+ crv = local_crv;
continue;
}
@@ -421,7 +453,8 @@ sftkdb_fixupTemplateOut(CK_ATTRIBUTE *template, CK_OBJECT_HANDLE objectID,
continue;
}
- rv = sftkdb_VerifyAttribute(&keyHandle->passwordKey,
+ rv = sftkdb_VerifyAttribute(keyHandle,
+ &keyHandle->passwordKey,
objectID, ntemplate[i].type,
&plainText, &signText);
PZ_Unlock(keyHandle->passwordLock);
@@ -529,7 +562,8 @@ sftk_signTemplate(PLArenaPool *arena, SFTKDBHandle *handle,
crv = CKR_USER_NOT_LOGGED_IN;
goto loser;
}
- rv = sftkdb_SignAttribute(arena, &keyHandle->passwordKey,
+ rv = sftkdb_SignAttribute(arena, keyHandle, keyTarget,
+ &keyHandle->passwordKey,
keyHandle->defaultIterationCount,
objectID, template[i].type,
&plainText, &signText);
@@ -538,10 +572,9 @@ sftk_signTemplate(PLArenaPool *arena, SFTKDBHandle *handle,
crv = CKR_GENERAL_ERROR; /* better error code here? */
goto loser;
}
- rv = sftkdb_PutAttributeSignature(handle, keyTarget,
- objectID, template[i].type, signText);
- if (rv != SECSuccess) {
- crv = CKR_GENERAL_ERROR; /* better error code here? */
+ crv = sftkdb_PutAttributeSignature(handle, keyTarget, objectID,
+ template[i].type, signText);
+ if (crv != CKR_OK) {
goto loser;
}
}
@@ -586,10 +619,56 @@ loser:
return crv;
}
+static CK_RV
+sftkdb_fixupSignatures(SFTKDBHandle *handle,
+ SDB *db, CK_OBJECT_HANDLE oldID, CK_OBJECT_HANDLE newID,
+ CK_ATTRIBUTE *ptemplate, CK_ULONG max_attributes)
+{
+ unsigned int i;
+ CK_RV crv = CKR_OK;
+
+ /* if we don't have a meta table, we didn't write any signature objects */
+ if ((db->sdb_flags & SDB_HAS_META) == 0) {
+ return CKR_OK;
+ }
+ for (i = 0; i < max_attributes; i++) {
+ CK_ATTRIBUTE *att = &ptemplate[i];
+ CK_ATTRIBUTE_TYPE type = att->type;
+ if (sftkdb_isPrivateAttribute(type)) {
+ /* move the signature from one object handle to another and delete
+ * the old entry */
+ SECItem signature;
+ unsigned char signData[SDB_MAX_META_DATA_LEN];
+
+ signature.data = signData;
+ signature.len = sizeof(signData);
+ crv = sftkdb_getRawAttributeSignature(handle, db, oldID, type,
+ &signature);
+ if (crv != CKR_OK) {
+ /* NOTE: if we ever change our default write from AES_CBC
+ * to AES_KW, We'll need to change this to a continue as
+ * we won't need the integrity record for AES_KW */
+ break;
+ }
+ crv = sftkdb_PutAttributeSignature(handle, db, newID, type,
+ &signature);
+ if (crv != CKR_OK) {
+ break;
+ }
+ /* now get rid of the old one */
+ crv = sftkdb_DestroyAttributeSignature(handle, db, oldID, type);
+ if (crv != CKR_OK) {
+ break;
+ }
+ }
+ }
+ return crv;
+}
+
CK_ATTRIBUTE *
sftk_ExtractTemplate(PLArenaPool *arena, SFTKObject *object,
- SFTKDBHandle *handle, CK_ULONG *pcount,
- CK_RV *crv)
+ SFTKDBHandle *handle, CK_OBJECT_HANDLE objectID,
+ SDB *db, CK_ULONG *pcount, CK_RV *crv)
{
unsigned int count;
CK_ATTRIBUTE *template;
@@ -663,8 +742,11 @@ sftk_ExtractTemplate(PLArenaPool *arena, SFTKObject *object,
*crv = CKR_USER_NOT_LOGGED_IN;
break;
}
- rv = sftkdb_EncryptAttribute(arena, &handle->passwordKey,
+ rv = sftkdb_EncryptAttribute(arena, handle, db,
+ &handle->passwordKey,
handle->defaultIterationCount,
+ objectID,
+ tp->type,
&plainText, &cipherText);
PZ_Unlock(handle->passwordLock);
if (rv == SECSuccess) {
@@ -1111,7 +1193,7 @@ sftkdb_write(SFTKDBHandle *handle, SFTKObject *object,
CK_RV crv;
SDB *db;
PRBool inTransaction = PR_FALSE;
- CK_OBJECT_HANDLE id;
+ CK_OBJECT_HANDLE id, candidateID;
*objectID = CK_INVALID_HANDLE;
@@ -1136,16 +1218,21 @@ sftkdb_write(SFTKDBHandle *handle, SFTKObject *object,
return CKR_HOST_MEMORY;
}
- template = sftk_ExtractTemplate(arena, object, handle, &count, &crv);
- if (!template) {
+ crv = (*db->sdb_Begin)(db);
+ if (crv != CKR_OK) {
goto loser;
}
+ inTransaction = PR_TRUE;
- crv = (*db->sdb_Begin)(db);
+ crv = (*db->sdb_GetNewObjectID)(db, &candidateID);
if (crv != CKR_OK) {
goto loser;
}
- inTransaction = PR_TRUE;
+
+ template = sftk_ExtractTemplate(arena, object, handle, candidateID, db, &count, &crv);
+ if (!template) {
+ goto loser;
+ }
/*
* We want to make the base database as free from object specific knowledge
@@ -1174,16 +1261,23 @@ sftkdb_write(SFTKDBHandle *handle, SFTKObject *object,
goto loser;
}
if (id == CK_INVALID_HANDLE) {
+ *objectID = candidateID;
crv = sftkdb_CreateObject(arena, handle, db, objectID, template, count);
} else {
/* object already exists, modify it's attributes */
*objectID = id;
+ /* The object ID changed from our candidate, we need to move any
+ * signature attribute signatures to the new object ID. */
+ crv = sftkdb_fixupSignatures(handle, db, candidateID, id,
+ template, count);
+ if (crv != CKR_OK) {
+ goto loser;
+ }
crv = sftkdb_setAttributeValue(arena, handle, db, id, template, count);
}
if (crv != CKR_OK) {
goto loser;
}
-
crv = (*db->sdb_Commit)(db);
inTransaction = PR_FALSE;
@@ -1413,7 +1507,8 @@ loser:
}
CK_RV
-sftkdb_DestroyObject(SFTKDBHandle *handle, CK_OBJECT_HANDLE objectID)
+sftkdb_DestroyObject(SFTKDBHandle *handle, CK_OBJECT_HANDLE objectID,
+ CK_OBJECT_CLASS objclass)
{
CK_RV crv = CKR_OK;
SDB *db;
@@ -1423,6 +1518,7 @@ sftkdb_DestroyObject(SFTKDBHandle *handle, CK_OBJECT_HANDLE objectID)
}
db = SFTK_GET_SDB(handle);
objectID &= SFTK_OBJ_ID_MASK;
+
crv = (*db->sdb_Begin)(db);
if (crv != CKR_OK) {
goto loser;
@@ -1431,6 +1527,51 @@ sftkdb_DestroyObject(SFTKDBHandle *handle, CK_OBJECT_HANDLE objectID)
if (crv != CKR_OK) {
goto loser;
}
+ /* if the database supports meta data, delete any old signatures
+ * that we may have added */
+ if ((db->sdb_flags & SDB_HAS_META) == SDB_HAS_META) {
+ SDB *keydb = db;
+ if (handle->type == SFTK_KEYDB_TYPE) {
+ /* delete any private attribute signatures that might exist */
+ (void)sftkdb_DestroyAttributeSignature(handle, keydb, objectID,
+ CKA_VALUE);
+ (void)sftkdb_DestroyAttributeSignature(handle, keydb, objectID,
+ CKA_PRIVATE_EXPONENT);
+ (void)sftkdb_DestroyAttributeSignature(handle, keydb, objectID,
+ CKA_PRIME_1);
+ (void)sftkdb_DestroyAttributeSignature(handle, keydb, objectID,
+ CKA_PRIME_2);
+ (void)sftkdb_DestroyAttributeSignature(handle, keydb, objectID,
+ CKA_EXPONENT_1);
+ (void)sftkdb_DestroyAttributeSignature(handle, keydb, objectID,
+ CKA_EXPONENT_2);
+ (void)sftkdb_DestroyAttributeSignature(handle, keydb, objectID,
+ CKA_COEFFICIENT);
+ } else {
+ keydb = SFTK_GET_SDB(handle->peerDB);
+ }
+ /* now destroy any authenticated attributes that may exist */
+ (void)sftkdb_DestroyAttributeSignature(handle, keydb, objectID,
+ CKA_MODULUS);
+ (void)sftkdb_DestroyAttributeSignature(handle, keydb, objectID,
+ CKA_PUBLIC_EXPONENT);
+ (void)sftkdb_DestroyAttributeSignature(handle, keydb, objectID,
+ CKA_CERT_SHA1_HASH);
+ (void)sftkdb_DestroyAttributeSignature(handle, keydb, objectID,
+ CKA_CERT_MD5_HASH);
+ (void)sftkdb_DestroyAttributeSignature(handle, keydb, objectID,
+ CKA_TRUST_SERVER_AUTH);
+ (void)sftkdb_DestroyAttributeSignature(handle, keydb, objectID,
+ CKA_TRUST_CLIENT_AUTH);
+ (void)sftkdb_DestroyAttributeSignature(handle, keydb, objectID,
+ CKA_TRUST_EMAIL_PROTECTION);
+ (void)sftkdb_DestroyAttributeSignature(handle, keydb, objectID,
+ CKA_TRUST_CODE_SIGNING);
+ (void)sftkdb_DestroyAttributeSignature(handle, keydb, objectID,
+ CKA_TRUST_STEP_UP_APPROVED);
+ (void)sftkdb_DestroyAttributeSignature(handle, keydb, objectID,
+ CKA_NSS_OVERRIDE_EXTENSIONS);
+ }
crv = (*db->sdb_Commit)(db);
loser:
if (crv != CKR_OK) {
@@ -1593,7 +1734,7 @@ static const CK_ATTRIBUTE_TYPE known_attributes[] = {
CKA_TRUST_EMAIL_PROTECTION, CKA_TRUST_IPSEC_END_SYSTEM,
CKA_TRUST_IPSEC_TUNNEL, CKA_TRUST_IPSEC_USER, CKA_TRUST_TIME_STAMPING,
CKA_TRUST_STEP_UP_APPROVED, CKA_CERT_SHA1_HASH, CKA_CERT_MD5_HASH,
- CKA_NETSCAPE_DB, CKA_NETSCAPE_TRUST, CKA_NSS_OVERRIDE_EXTENSIONS,
+ CKA_NSS_DB, CKA_NSS_TRUST, CKA_NSS_OVERRIDE_EXTENSIONS,
CKA_PUBLIC_KEY_INFO
};
@@ -2144,6 +2285,56 @@ sftkdb_updateObjectTemplate(PLArenaPool *arena, SDB *db,
return SFTKDB_ADD_OBJECT;
}
+static CK_RV
+sftkdb_updateIntegrity(PLArenaPool *arena, SFTKDBHandle *handle,
+ SDB *source, CK_OBJECT_HANDLE sourceID,
+ SDB *target, CK_OBJECT_HANDLE targetID,
+ CK_ATTRIBUTE *ptemplate, CK_ULONG max_attributes)
+{
+ unsigned int i;
+ CK_RV global_crv = CKR_OK;
+
+ /* if the target doesn't have META data, don't need to do anything */
+ if ((target->sdb_flags & SDB_HAS_META) == 0) {
+ return CKR_OK;
+ }
+ /* if the source doesn't have meta data, then the record won't require
+ * integrity */
+ if ((source->sdb_flags & SDB_HAS_META) == 0) {
+ return CKR_OK;
+ }
+ for (i = 0; i < max_attributes; i++) {
+ CK_ATTRIBUTE *att = &ptemplate[i];
+ CK_ATTRIBUTE_TYPE type = att->type;
+ if (sftkdb_isPrivateAttribute(type)) {
+ /* copy integrity signatures associated with this record (if any) */
+ SECItem signature;
+ unsigned char signData[SDB_MAX_META_DATA_LEN];
+ CK_RV crv;
+
+ signature.data = signData;
+ signature.len = sizeof(signData);
+ crv = sftkdb_getRawAttributeSignature(handle, source, sourceID, type,
+ &signature);
+ if (crv != CKR_OK) {
+ /* old databases don't have signature IDs because they are
+ * 3DES encrypted. Since we know not to look for integrity
+ * for 3DES records it's OK not to find one here. A new record
+ * will be created when we reencrypt using AES CBC */
+ continue;
+ }
+ crv = sftkdb_PutAttributeSignature(handle, target, targetID, type,
+ &signature);
+ if (crv != CKR_OK) {
+ /* we had a signature in the source db, but we couldn't store
+ * it in the target, remember the error so we can report it. */
+ global_crv = crv;
+ }
+ }
+ }
+ return global_crv;
+}
+
#define MAX_ATTRIBUTES 500
static CK_RV
sftkdb_mergeObject(SFTKDBHandle *handle, CK_OBJECT_HANDLE id,
@@ -2156,6 +2347,7 @@ sftkdb_mergeObject(SFTKDBHandle *handle, CK_OBJECT_HANDLE id,
SDB *source = handle->update;
SDB *target = handle->db;
unsigned int i;
+ CK_OBJECT_HANDLE newID = CK_INVALID_HANDLE;
CK_RV crv;
PLArenaPool *arena = NULL;
@@ -2202,20 +2394,20 @@ sftkdb_mergeObject(SFTKDBHandle *handle, CK_OBJECT_HANDLE id,
* database.
*/
if (!handle->updateID) {
- crv = sftkdb_CreateObject(arena, handle, target, &id,
+ crv = sftkdb_CreateObject(arena, handle, target, &newID,
ptemplate, max_attributes);
} else {
sftkdbUpdateStatus update_status;
update_status = sftkdb_updateObjectTemplate(arena, target,
- objectType, ptemplate, &max_attributes, &id);
+ objectType, ptemplate, &max_attributes, &newID);
switch (update_status) {
case SFTKDB_ADD_OBJECT:
- crv = sftkdb_CreateObject(arena, handle, target, &id,
+ crv = sftkdb_CreateObject(arena, handle, target, &newID,
ptemplate, max_attributes);
break;
case SFTKDB_MODIFY_OBJECT:
crv = sftkdb_setAttributeValue(arena, handle, target,
- id, ptemplate, max_attributes);
+ newID, ptemplate, max_attributes);
break;
case SFTKDB_DO_NOTHING:
case SFTKDB_DROP_ATTRIBUTE:
@@ -2223,6 +2415,13 @@ sftkdb_mergeObject(SFTKDBHandle *handle, CK_OBJECT_HANDLE id,
}
}
+ /* if keyDB copy any meta data hashes to target, Update for the new
+ * object ID */
+ if (crv == CKR_OK) {
+ crv = sftkdb_updateIntegrity(arena, handle, source, id, target, newID,
+ ptemplate, max_attributes);
+ }
+
loser:
if (arena) {
PORT_FreeArena(arena, PR_TRUE);
@@ -2251,7 +2450,6 @@ sftkdb_Update(SFTKDBHandle *handle, SECItem *key)
if (handle->update == NULL) {
return CKR_OK;
}
-
/*
* put the whole update under a transaction. This allows us to handle
* any possible race conditions between with the updateID check.
@@ -2495,6 +2693,7 @@ sftkdb_ResetKeyDB(SFTKDBHandle *handle)
return SECSuccess;
}
+#ifndef NSS_DISABLE_DBM
static PRBool
sftk_oldVersionExists(const char *dir, int version)
{
@@ -2598,6 +2797,7 @@ sftk_hasLegacyDB(const char *confdir, const char *certPrefix,
PR_smprintf_free(dir);
return exists;
}
+#endif /* NSS_DISABLE_DBM */
/*
* initialize certificate and key database handles as a pair.
@@ -2621,7 +2821,9 @@ sftk_DBInit(const char *configdir, const char *certPrefix,
CK_RV crv = CKR_OK;
int flags = SDB_RDONLY;
PRBool newInit = PR_FALSE;
+#ifndef NSS_DISABLE_DBM
PRBool needUpdate = PR_FALSE;
+#endif /* NSS_DISABLE_DBM */
char *nconfdir = NULL;
PRBool legacy = PR_TRUE;
@@ -2644,6 +2846,7 @@ sftk_DBInit(const char *configdir, const char *certPrefix,
* now initialize the appropriate database
*/
switch (dbType) {
+#ifndef NSS_DISABLE_DBM
case NSS_DB_TYPE_LEGACY:
crv = sftkdbCall_open(confdir, certPrefix, keyPrefix, 8, 3, flags,
noCertDB ? NULL : &certSDB, noKeyDB ? NULL : &keySDB);
@@ -2652,10 +2855,13 @@ sftk_DBInit(const char *configdir, const char *certPrefix,
crv = sftkdbCall_open(configdir, certPrefix, keyPrefix, 8, 3, flags,
noCertDB ? NULL : &certSDB, noKeyDB ? NULL : &keySDB);
break;
+#endif /* NSS_DISABLE_DBM */
case NSS_DB_TYPE_SQL:
case NSS_DB_TYPE_EXTERN: /* SHOULD open a loadable db */
crv = s_open(confdir, certPrefix, keyPrefix, 9, 4, flags,
noCertDB ? NULL : &certSDB, noKeyDB ? NULL : &keySDB, &newInit);
+
+#ifndef NSS_DISABLE_DBM
legacy = PR_FALSE;
/*
@@ -2707,6 +2913,7 @@ sftk_DBInit(const char *configdir, const char *certPrefix,
needUpdate = PR_TRUE;
}
}
+#endif /* NSS_DISABLE_DBM */
break;
default:
crv = CKR_GENERAL_ERROR; /* can't happen, EvaluationConfigDir MUST
@@ -2735,6 +2942,7 @@ sftk_DBInit(const char *configdir, const char *certPrefix,
(*keyDB)->peerDB = *certDB;
}
+#ifndef NSS_DISABLE_DBM
/*
* if we need to update, open the legacy database and
* mark the handle as needing update.
@@ -2772,6 +2980,8 @@ sftk_DBInit(const char *configdir, const char *certPrefix,
}
}
}
+#endif /* NSS_DISABLE_DBM */
+
done:
if (appName) {
PORT_Free(appName);
@@ -2786,6 +2996,8 @@ CK_RV
sftkdb_Shutdown(void)
{
s_shutdown();
+#ifndef NSS_DISABLE_DBM
sftkdbCall_Shutdown();
+#endif /* NSS_DISABLE_DBM */
return CKR_OK;
}