diff options
author | Moonchild <moonchild@palemoon.org> | 2020-12-23 19:02:52 +0000 |
---|---|---|
committer | Moonchild <moonchild@palemoon.org> | 2020-12-23 19:02:52 +0000 |
commit | 029bcfe189eae5eebbaf58ccff4e1200dd78b228 (patch) | |
tree | 1c226a334ea1a88e2d1c6f949c9320eb0c3bff59 /security/nss/lib/softoken/sftkdb.c | |
parent | 149d2ffa779826cb48a381099858e76e4624d471 (diff) | |
download | uxp-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.c | 276 |
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; } |