mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-22 00:17:32 +09:00
Update NSS to 3.48 while keeping vc2013 hackfix and no-sslkeylogfile intact.
This commit is contained in:
parent
0b9855b841
commit
171849c8e5
351 changed files with 115185 additions and 57946 deletions
|
|
@ -645,17 +645,37 @@ FC_SetPIN(CK_SESSION_HANDLE hSession, CK_CHAR_PTR pOldPin,
|
|||
|
||||
CHECK_FORK();
|
||||
|
||||
if ((rv = sftk_fipsCheck()) == CKR_OK &&
|
||||
(rv = sftk_newPinCheck(pNewPin, usNewLen)) == CKR_OK) {
|
||||
rv = sftk_fipsCheck();
|
||||
if (rv != CKR_OK) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
if (isLevel2 || usNewLen > 0) {
|
||||
rv = sftk_newPinCheck(pNewPin, usNewLen);
|
||||
if (rv != CKR_OK) {
|
||||
goto loser;
|
||||
}
|
||||
rv = NSC_SetPIN(hSession, pOldPin, usOldLen, pNewPin, usNewLen);
|
||||
if ((rv == CKR_OK) &&
|
||||
(sftk_SlotIDFromSessionHandle(hSession) == FIPS_SLOT_ID)) {
|
||||
if (rv != CKR_OK) {
|
||||
goto loser;
|
||||
}
|
||||
if (sftk_SlotIDFromSessionHandle(hSession) == FIPS_SLOT_ID) {
|
||||
/* if we set the password in level1 we now go
|
||||
* to level2. NOTE: we don't allow the user to
|
||||
* go from level2 to level1 */
|
||||
isLevel2 = PR_TRUE;
|
||||
}
|
||||
} else {
|
||||
/* here both old and new passwords are empty, but we need to
|
||||
* call NSC_SetPIN to force rekey the database entries */
|
||||
PORT_Assert(usNewLen == 0);
|
||||
rv = NSC_SetPIN(hSession, pOldPin, usOldLen, pNewPin, usNewLen);
|
||||
if (rv != CKR_OK) {
|
||||
goto loser;
|
||||
}
|
||||
}
|
||||
|
||||
loser:
|
||||
if (sftk_audit_enabled) {
|
||||
char msg[128];
|
||||
NSSAuditSeverity severity = (rv == CKR_OK) ? NSS_AUDIT_INFO : NSS_AUDIT_ERROR;
|
||||
|
|
|
|||
|
|
@ -1213,6 +1213,8 @@ nsslowkey_EncodePW(SECOidTag alg, const SECItem *salt, SECItem *data)
|
|||
unsigned char one = 1;
|
||||
SECItem *epw = NULL;
|
||||
SECItem *encParam;
|
||||
int iterLen = 0;
|
||||
int saltLen;
|
||||
SECStatus rv;
|
||||
|
||||
param.salt = *salt;
|
||||
|
|
@ -1221,6 +1223,17 @@ nsslowkey_EncodePW(SECOidTag alg, const SECItem *salt, SECItem *data)
|
|||
param.iter.len = 1;
|
||||
edi.encryptedData = *data;
|
||||
|
||||
iterLen = salt->len > 1 ? salt->data[salt->len - 1] : 2;
|
||||
saltLen = (salt->len - iterLen) - 1;
|
||||
/* if the resulting saltLen is a sha hash length, then assume that
|
||||
* the iteration count is tacked on the end of the buffer */
|
||||
if ((saltLen == SHA1_LENGTH) || (saltLen == SHA256_LENGTH) || (saltLen == SHA384_LENGTH) || (saltLen == SHA224_LENGTH) ||
|
||||
(saltLen == SHA512_LENGTH)) {
|
||||
param.iter.data = &salt->data[saltLen];
|
||||
param.iter.len = iterLen;
|
||||
param.salt.len = saltLen;
|
||||
}
|
||||
|
||||
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
|
||||
if (arena == NULL) {
|
||||
return NULL;
|
||||
|
|
@ -1270,9 +1283,23 @@ nsslowkey_DecodePW(const SECItem *derData, SECOidTag *alg, SECItem *salt)
|
|||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
}
|
||||
rv = SECITEM_CopyItem(NULL, salt, ¶m.salt);
|
||||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
/* if the iteration count isn't one, tack it at the end of the salt */
|
||||
if (!((param.iter.len == 1) && (param.iter.data[0] == 1))) {
|
||||
int total_len = param.salt.len + param.iter.len + 1;
|
||||
salt->data = PORT_Alloc(total_len);
|
||||
if (salt->data == NULL) {
|
||||
goto loser;
|
||||
}
|
||||
PORT_Memcpy(salt->data, param.salt.data, param.salt.len);
|
||||
PORT_Memcpy(&salt->data[param.salt.len], param.iter.data,
|
||||
param.iter.len);
|
||||
salt->data[total_len - 1] = param.iter.len;
|
||||
salt->len = total_len;
|
||||
} else {
|
||||
rv = SECITEM_CopyItem(NULL, salt, ¶m.salt);
|
||||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
}
|
||||
}
|
||||
pwe = SECITEM_DupItem(&edi.encryptedData);
|
||||
|
||||
|
|
|
|||
|
|
@ -1069,7 +1069,7 @@ lg_FindTrustAttribute(LGObjectCache *obj, CK_ATTRIBUTE_TYPE type,
|
|||
NSSLOWCERTCertificate *cert;
|
||||
unsigned char hash[SHA1_LENGTH];
|
||||
unsigned int trustFlags;
|
||||
CK_RV crv;
|
||||
CK_RV crv = CKR_CANCEL;
|
||||
|
||||
switch (type) {
|
||||
case CKA_PRIVATE:
|
||||
|
|
|
|||
|
|
@ -171,6 +171,8 @@ sftkdb_encrypt_stub(PLArenaPool *arena, SDB *sdb, SECItem *plainText,
|
|||
{
|
||||
SFTKDBHandle *handle = sdb->app_private;
|
||||
SECStatus rv;
|
||||
SECItem *key;
|
||||
int iterationCount;
|
||||
|
||||
if (handle == NULL) {
|
||||
return SECFailure;
|
||||
|
|
@ -192,9 +194,18 @@ sftkdb_encrypt_stub(PLArenaPool *arena, SDB *sdb, SECItem *plainText,
|
|||
/* PORT_SetError */
|
||||
return SECFailure;
|
||||
}
|
||||
key = handle->newKey ? handle->newKey : &handle->passwordKey;
|
||||
if (sftk_isLegacyIterationCountAllowed()) {
|
||||
if (handle->newKey) {
|
||||
iterationCount = handle->newDefaultIterationCount;
|
||||
} else {
|
||||
iterationCount = handle->defaultIterationCount;
|
||||
}
|
||||
} else {
|
||||
iterationCount = 1;
|
||||
}
|
||||
|
||||
rv = sftkdb_EncryptAttribute(arena,
|
||||
handle->newKey ? handle->newKey : &handle->passwordKey,
|
||||
rv = sftkdb_EncryptAttribute(arena, key, iterationCount,
|
||||
plainText, cipherText);
|
||||
PZ_Unlock(handle->passwordLock);
|
||||
|
||||
|
|
|
|||
|
|
@ -324,6 +324,8 @@ static const struct mechanismList mechanisms[] = {
|
|||
{ CKM_AES_CBC, { 16, 32, CKF_EN_DE_WR_UN }, PR_TRUE },
|
||||
{ CKM_AES_MAC, { 16, 32, CKF_SN_VR }, PR_TRUE },
|
||||
{ CKM_AES_MAC_GENERAL, { 16, 32, CKF_SN_VR }, PR_TRUE },
|
||||
{ CKM_AES_CMAC, { 16, 32, CKF_SN_VR }, PR_TRUE },
|
||||
{ CKM_AES_CMAC_GENERAL, { 16, 32, CKF_SN_VR }, PR_TRUE },
|
||||
{ CKM_AES_CBC_PAD, { 16, 32, CKF_EN_DE_WR_UN }, PR_TRUE },
|
||||
{ CKM_AES_CTS, { 16, 32, CKF_EN_DE }, PR_TRUE },
|
||||
{ CKM_AES_CTR, { 16, 32, CKF_EN_DE }, PR_TRUE },
|
||||
|
|
@ -624,7 +626,7 @@ sftk_hasNullPassword(SFTKSlot *slot, SFTKDBHandle *keydb)
|
|||
pwenabled = PR_FALSE;
|
||||
if (sftkdb_HasPasswordSet(keydb) == SECSuccess) {
|
||||
PRBool tokenRemoved = PR_FALSE;
|
||||
SECStatus rv = sftkdb_CheckPassword(keydb, "", &tokenRemoved);
|
||||
SECStatus rv = sftkdb_CheckPasswordNull(keydb, &tokenRemoved);
|
||||
if (tokenRemoved) {
|
||||
sftk_CloseAllSessions(slot, PR_FALSE);
|
||||
}
|
||||
|
|
@ -2283,14 +2285,19 @@ sftk_PutPubKey(SFTKObject *publicKey, SFTKObject *privateKey, CK_KEY_TYPE keyTyp
|
|||
default:
|
||||
return CKR_KEY_TYPE_INCONSISTENT;
|
||||
}
|
||||
if (crv != CKR_OK) {
|
||||
return crv;
|
||||
}
|
||||
crv = sftk_AddAttributeType(publicKey, CKA_CLASS, &classType,
|
||||
sizeof(CK_OBJECT_CLASS));
|
||||
if (crv != CKR_OK)
|
||||
if (crv != CKR_OK) {
|
||||
return crv;
|
||||
}
|
||||
crv = sftk_AddAttributeType(publicKey, CKA_KEY_TYPE, &keyType,
|
||||
sizeof(CK_KEY_TYPE));
|
||||
if (crv != CKR_OK)
|
||||
if (crv != CKR_OK) {
|
||||
return crv;
|
||||
}
|
||||
/* now handle the operator attributes */
|
||||
if (sftk_isTrue(privateKey, CKA_DECRYPT)) {
|
||||
crv = sftk_forceAttribute(publicKey, CKA_ENCRYPT, &cktrue, sizeof(CK_BBOOL));
|
||||
|
|
@ -3901,7 +3908,10 @@ NSC_SetPIN(CK_SESSION_HANDLE hSession, CK_CHAR_PTR pOldPin,
|
|||
crv = CKR_PIN_LEN_RANGE;
|
||||
goto loser;
|
||||
}
|
||||
if (ulNewLen < (CK_ULONG)slot->minimumPinLen) {
|
||||
/* check the length of new pin, unless both old and new passwords
|
||||
* are empty */
|
||||
if ((ulNewLen != 0 || ulOldLen != 0) &&
|
||||
ulNewLen < (CK_ULONG)slot->minimumPinLen) {
|
||||
crv = CKR_PIN_LEN_RANGE;
|
||||
goto loser;
|
||||
}
|
||||
|
|
@ -3937,7 +3947,7 @@ NSC_SetPIN(CK_SESSION_HANDLE hSession, CK_CHAR_PTR pOldPin,
|
|||
PZ_Unlock(slot->slotLock);
|
||||
|
||||
tokenRemoved = PR_FALSE;
|
||||
rv = sftkdb_CheckPassword(handle, "", &tokenRemoved);
|
||||
rv = sftkdb_CheckPasswordNull(handle, &tokenRemoved);
|
||||
if (tokenRemoved) {
|
||||
sftk_CloseAllSessions(slot, PR_FALSE);
|
||||
}
|
||||
|
|
@ -4059,7 +4069,6 @@ NSC_CloseSession(CK_SESSION_HANDLE hSession)
|
|||
session = NULL;
|
||||
}
|
||||
|
||||
sftk_FreeSession(session);
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include "lowpbe.h" /* We do PBE below */
|
||||
#include "pkcs11t.h"
|
||||
#include "secoid.h"
|
||||
#include "cmac.h"
|
||||
#include "alghmac.h"
|
||||
#include "softoken.h"
|
||||
#include "secasn1.h"
|
||||
|
|
@ -39,7 +40,7 @@
|
|||
#include "prenv.h"
|
||||
|
||||
#define __PASTE(x, y) x##y
|
||||
|
||||
#define BAD_PARAM_CAST(pMech, typeSize) (!pMech->pParameter || pMech->ulParameterLen < typeSize)
|
||||
/*
|
||||
* we renamed all our internal functions, get the correct
|
||||
* definitions for them...
|
||||
|
|
@ -782,6 +783,10 @@ sftk_CryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
|
|||
PRBool useNewKey = PR_FALSE;
|
||||
int t;
|
||||
|
||||
if (!pMechanism) {
|
||||
return CKR_MECHANISM_PARAM_INVALID;
|
||||
}
|
||||
|
||||
crv = sftk_MechAllowsOperation(pMechanism->mechanism, mechUsage);
|
||||
if (crv != CKR_OK)
|
||||
return crv;
|
||||
|
|
@ -895,6 +900,11 @@ sftk_CryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
|
|||
crv = CKR_KEY_HANDLE_INVALID;
|
||||
break;
|
||||
}
|
||||
|
||||
if (BAD_PARAM_CAST(pMechanism, sizeof(CK_RC2_CBC_PARAMS))) {
|
||||
crv = CKR_MECHANISM_PARAM_INVALID;
|
||||
break;
|
||||
}
|
||||
rc2_param = (CK_RC2_CBC_PARAMS *)pMechanism->pParameter;
|
||||
effectiveKeyLength = (rc2_param->ulEffectiveBits + 7) / 8;
|
||||
context->cipherInfo =
|
||||
|
|
@ -924,6 +934,11 @@ sftk_CryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
|
|||
crv = CKR_KEY_HANDLE_INVALID;
|
||||
break;
|
||||
}
|
||||
|
||||
if (BAD_PARAM_CAST(pMechanism, sizeof(CK_RC5_CBC_PARAMS))) {
|
||||
crv = CKR_MECHANISM_PARAM_INVALID;
|
||||
break;
|
||||
}
|
||||
rc5_param = (CK_RC5_CBC_PARAMS *)pMechanism->pParameter;
|
||||
context->blockSize = rc5_param->ulWordsize * 2;
|
||||
rc5Key.data = (unsigned char *)att->attrib.pValue;
|
||||
|
|
@ -987,6 +1002,10 @@ sftk_CryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
|
|||
crv = CKR_KEY_TYPE_INCONSISTENT;
|
||||
break;
|
||||
}
|
||||
if (pMechanism->ulParameterLen < 8) {
|
||||
crv = CKR_DOMAIN_PARAMS_INVALID;
|
||||
break;
|
||||
}
|
||||
t = NSS_DES_CBC;
|
||||
goto finish_des;
|
||||
case CKM_DES3_ECB:
|
||||
|
|
@ -1004,6 +1023,10 @@ sftk_CryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
|
|||
crv = CKR_KEY_TYPE_INCONSISTENT;
|
||||
break;
|
||||
}
|
||||
if (pMechanism->ulParameterLen < 8) {
|
||||
crv = CKR_DOMAIN_PARAMS_INVALID;
|
||||
break;
|
||||
}
|
||||
t = NSS_DES_EDE3_CBC;
|
||||
finish_des:
|
||||
context->blockSize = 8;
|
||||
|
|
@ -1121,6 +1144,13 @@ sftk_CryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
|
|||
case CKM_AES_CTS:
|
||||
case CKM_AES_CTR:
|
||||
case CKM_AES_GCM:
|
||||
if ((pMechanism->mechanism == CKM_AES_GCM && BAD_PARAM_CAST(pMechanism, sizeof(CK_GCM_PARAMS))) ||
|
||||
(pMechanism->mechanism == CKM_AES_CTR && BAD_PARAM_CAST(pMechanism, sizeof(CK_AES_CTR_PARAMS))) ||
|
||||
((pMechanism->mechanism == CKM_AES_CBC || pMechanism->mechanism == CKM_AES_CTS) && BAD_PARAM_CAST(pMechanism, AES_BLOCK_SIZE))) {
|
||||
crv = CKR_MECHANISM_PARAM_INVALID;
|
||||
break;
|
||||
}
|
||||
|
||||
if (pMechanism->mechanism == CKM_AES_GCM) {
|
||||
context->multi = PR_FALSE;
|
||||
}
|
||||
|
|
@ -1347,8 +1377,11 @@ NSC_EncryptUpdate(CK_SESSION_HANDLE hSession,
|
|||
/* do it: NOTE: this assumes buf size in is >= buf size out! */
|
||||
rv = (*context->update)(context->cipherInfo, pEncryptedPart,
|
||||
&outlen, maxout, pPart, ulPartLen);
|
||||
if (rv != SECSuccess) {
|
||||
return sftk_MapCryptError(PORT_GetError());
|
||||
}
|
||||
*pulEncryptedPartLen = (CK_ULONG)(outlen + padoutlen);
|
||||
return (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError());
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
/* NSC_EncryptFinal finishes a multiple-part encryption operation. */
|
||||
|
|
@ -1428,26 +1461,29 @@ NSC_Encrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
|
|||
return crv;
|
||||
|
||||
if (!pEncryptedData) {
|
||||
*pulEncryptedDataLen = context->rsa ? context->maxLen : ulDataLen + 2 * context->blockSize;
|
||||
goto finish;
|
||||
outlen = context->rsa ? context->maxLen : ulDataLen + 2 * context->blockSize;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (context->doPad) {
|
||||
if (context->multi) {
|
||||
CK_ULONG updateLen = maxoutlen;
|
||||
CK_ULONG finalLen;
|
||||
/* padding is fairly complicated, have the update and final
|
||||
* code deal with it */
|
||||
sftk_FreeSession(session);
|
||||
crv = NSC_EncryptUpdate(hSession, pData, ulDataLen, pEncryptedData,
|
||||
pulEncryptedDataLen);
|
||||
if (crv != CKR_OK)
|
||||
*pulEncryptedDataLen = 0;
|
||||
maxoutlen -= *pulEncryptedDataLen;
|
||||
pEncryptedData += *pulEncryptedDataLen;
|
||||
&updateLen);
|
||||
if (crv != CKR_OK) {
|
||||
updateLen = 0;
|
||||
}
|
||||
maxoutlen -= updateLen;
|
||||
pEncryptedData += updateLen;
|
||||
finalLen = maxoutlen;
|
||||
crv2 = NSC_EncryptFinal(hSession, pEncryptedData, &finalLen);
|
||||
if (crv2 == CKR_OK)
|
||||
*pulEncryptedDataLen += finalLen;
|
||||
if (crv == CKR_OK && crv2 == CKR_OK) {
|
||||
*pulEncryptedDataLen = updateLen + finalLen;
|
||||
}
|
||||
return crv == CKR_OK ? crv2 : crv;
|
||||
}
|
||||
/* doPad without multi means that padding must be done on the first
|
||||
|
|
@ -1473,14 +1509,15 @@ NSC_Encrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
|
|||
rv = (*context->update)(context->cipherInfo, pEncryptedData,
|
||||
&outlen, maxoutlen, pText.data, pText.len);
|
||||
crv = (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError());
|
||||
*pulEncryptedDataLen = (CK_ULONG)outlen;
|
||||
if (pText.data != pData)
|
||||
PORT_ZFree(pText.data, pText.len);
|
||||
fail:
|
||||
sftk_TerminateOp(session, SFTK_ENCRYPT, context);
|
||||
finish:
|
||||
done:
|
||||
sftk_FreeSession(session);
|
||||
|
||||
if (crv == CKR_OK) {
|
||||
*pulEncryptedDataLen = (CK_ULONG)outlen;
|
||||
}
|
||||
return crv;
|
||||
}
|
||||
|
||||
|
|
@ -1569,8 +1606,73 @@ NSC_DecryptUpdate(CK_SESSION_HANDLE hSession,
|
|||
/* do it: NOTE: this assumes buf size in is >= buf size out! */
|
||||
rv = (*context->update)(context->cipherInfo, pPart, &outlen,
|
||||
maxout, pEncryptedPart, ulEncryptedPartLen);
|
||||
if (rv != SECSuccess) {
|
||||
return sftk_MapDecryptError(PORT_GetError());
|
||||
}
|
||||
*pulPartLen = (CK_ULONG)(outlen + padoutlen);
|
||||
return (rv == SECSuccess) ? CKR_OK : sftk_MapDecryptError(PORT_GetError());
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
/* From ssl3con.c: Constant-time helper macro that copies the MSB of x to all
|
||||
* other bits. */
|
||||
#define DUPLICATE_MSB_TO_ALL(x) ((unsigned int)((int)(x) >> (sizeof(int) * 8 - 1)))
|
||||
/* CK_RVToMask returns, in constant time, a mask value of
|
||||
* all ones if rv == CKR_OK. Otherwise it returns zero. */
|
||||
static unsigned int
|
||||
CK_RVToMask(CK_RV rv)
|
||||
{
|
||||
unsigned int good;
|
||||
/* rv ^ CKR_OK is zero iff rv == CKR_OK. Subtracting one results
|
||||
* in the MSB being set to one iff it was zero before. */
|
||||
good = rv ^ CKR_OK;
|
||||
good--;
|
||||
return DUPLICATE_MSB_TO_ALL(good);
|
||||
}
|
||||
/* Constant-time helper macro that selects l or r depending on all-1 or all-0
|
||||
* mask m */
|
||||
#define CT_SEL(m, l, r) (((m) & (l)) | (~(m) & (r)))
|
||||
/* Constant-time helper macro that returns all-1s if x is not 0; and all-0s
|
||||
* otherwise. */
|
||||
#define CT_NOT_ZERO(x) (DUPLICATE_MSB_TO_ALL(((x) | (0 - x))))
|
||||
|
||||
/* sftk_CheckCBCPadding checks, in constant time, the padding validity and
|
||||
* accordingly sets the pad length. */
|
||||
static CK_RV
|
||||
sftk_CheckCBCPadding(CK_BYTE_PTR pLastPart,
|
||||
unsigned int blockSize, unsigned int *outPadSize)
|
||||
{
|
||||
PORT_Assert(outPadSize);
|
||||
|
||||
unsigned int padSize = (unsigned int)pLastPart[blockSize - 1];
|
||||
|
||||
/* If padSize <= blockSize, set goodPad to all-1s and all-0s otherwise.*/
|
||||
unsigned int goodPad = DUPLICATE_MSB_TO_ALL(~(blockSize - padSize));
|
||||
/* padSize should not be 0 */
|
||||
goodPad &= CT_NOT_ZERO(padSize);
|
||||
|
||||
unsigned int i;
|
||||
for (i = 0; i < blockSize; i++) {
|
||||
/* If i < padSize, set loopMask to all-1s and all-0s otherwise.*/
|
||||
unsigned int loopMask = DUPLICATE_MSB_TO_ALL(~(padSize - 1 - i));
|
||||
/* Get the padding value (should be padSize) from buffer */
|
||||
unsigned int padVal = pLastPart[blockSize - 1 - i];
|
||||
/* Update goodPad only if i < padSize */
|
||||
goodPad &= CT_SEL(loopMask, ~(padVal ^ padSize), goodPad);
|
||||
}
|
||||
|
||||
/* If any of the final padding bytes had the wrong value, one or more
|
||||
* of the lower eight bits of |goodPad| will be cleared. We AND the
|
||||
* bottom 8 bits together and duplicate the result to all the bits. */
|
||||
goodPad &= goodPad >> 4;
|
||||
goodPad &= goodPad >> 2;
|
||||
goodPad &= goodPad >> 1;
|
||||
goodPad <<= sizeof(goodPad) * 8 - 1;
|
||||
goodPad = DUPLICATE_MSB_TO_ALL(goodPad);
|
||||
|
||||
/* Set outPadSize to padSize or 0 */
|
||||
*outPadSize = CT_SEL(goodPad, padSize, 0);
|
||||
/* Return OK if the pad is valid */
|
||||
return CT_SEL(goodPad, CKR_OK, CKR_ENCRYPTED_DATA_INVALID);
|
||||
}
|
||||
|
||||
/* NSC_DecryptFinal finishes a multiple-part decryption operation. */
|
||||
|
|
@ -1611,24 +1713,10 @@ NSC_DecryptFinal(CK_SESSION_HANDLE hSession,
|
|||
if (rv != SECSuccess) {
|
||||
crv = sftk_MapDecryptError(PORT_GetError());
|
||||
} else {
|
||||
unsigned int padSize =
|
||||
(unsigned int)pLastPart[context->blockSize - 1];
|
||||
if ((padSize > context->blockSize) || (padSize == 0)) {
|
||||
crv = CKR_ENCRYPTED_DATA_INVALID;
|
||||
} else {
|
||||
unsigned int i;
|
||||
unsigned int badPadding = 0; /* used as a boolean */
|
||||
for (i = 0; i < padSize; i++) {
|
||||
badPadding |=
|
||||
(unsigned int)pLastPart[context->blockSize - 1 - i] ^
|
||||
padSize;
|
||||
}
|
||||
if (badPadding) {
|
||||
crv = CKR_ENCRYPTED_DATA_INVALID;
|
||||
} else {
|
||||
*pulLastPartLen = outlen - padSize;
|
||||
}
|
||||
}
|
||||
unsigned int padSize = 0;
|
||||
crv = sftk_CheckCBCPadding(&pLastPart[outlen - context->blockSize], context->blockSize, &padSize);
|
||||
/* Update pulLastPartLen, in constant time, if crv is OK */
|
||||
*pulLastPartLen = CT_SEL(CK_RVToMask(crv), outlen - padSize, *pulLastPartLen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1661,52 +1749,48 @@ NSC_Decrypt(CK_SESSION_HANDLE hSession,
|
|||
return crv;
|
||||
|
||||
if (!pData) {
|
||||
*pulDataLen = ulEncryptedDataLen + context->blockSize;
|
||||
goto finish;
|
||||
*pulDataLen = (CK_ULONG)(ulEncryptedDataLen + context->blockSize);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (context->doPad && context->multi) {
|
||||
CK_ULONG updateLen = maxoutlen;
|
||||
CK_ULONG finalLen;
|
||||
/* padding is fairly complicated, have the update and final
|
||||
* code deal with it */
|
||||
sftk_FreeSession(session);
|
||||
crv = NSC_DecryptUpdate(hSession, pEncryptedData, ulEncryptedDataLen,
|
||||
pData, pulDataLen);
|
||||
if (crv != CKR_OK)
|
||||
*pulDataLen = 0;
|
||||
maxoutlen -= *pulDataLen;
|
||||
pData += *pulDataLen;
|
||||
pData, &updateLen);
|
||||
if (crv == CKR_OK) {
|
||||
maxoutlen -= updateLen;
|
||||
pData += updateLen;
|
||||
}
|
||||
finalLen = maxoutlen;
|
||||
crv2 = NSC_DecryptFinal(hSession, pData, &finalLen);
|
||||
if (crv2 == CKR_OK)
|
||||
*pulDataLen += finalLen;
|
||||
return crv == CKR_OK ? crv2 : crv;
|
||||
if (crv == CKR_OK) {
|
||||
*pulDataLen = CT_SEL(CK_RVToMask(crv2), updateLen + finalLen, *pulDataLen);
|
||||
return crv2;
|
||||
} else {
|
||||
return crv;
|
||||
}
|
||||
}
|
||||
|
||||
rv = (*context->update)(context->cipherInfo, pData, &outlen, maxoutlen,
|
||||
pEncryptedData, ulEncryptedDataLen);
|
||||
/* XXX need to do MUCH better error mapping than this. */
|
||||
crv = (rv == SECSuccess) ? CKR_OK : sftk_MapDecryptError(PORT_GetError());
|
||||
if (rv == SECSuccess && context->doPad) {
|
||||
unsigned int padding = pData[outlen - 1];
|
||||
if (padding > context->blockSize || !padding) {
|
||||
crv = CKR_ENCRYPTED_DATA_INVALID;
|
||||
if (rv == SECSuccess) {
|
||||
if (context->doPad) {
|
||||
unsigned int padSize = 0;
|
||||
crv = sftk_CheckCBCPadding(&pData[outlen - context->blockSize], context->blockSize, &padSize);
|
||||
/* Update pulDataLen, in constant time, if crv is OK */
|
||||
*pulDataLen = CT_SEL(CK_RVToMask(crv), outlen - padSize, *pulDataLen);
|
||||
} else {
|
||||
unsigned int i;
|
||||
unsigned int badPadding = 0; /* used as a boolean */
|
||||
for (i = 0; i < padding; i++) {
|
||||
badPadding |= (unsigned int)pData[outlen - 1 - i] ^ padding;
|
||||
}
|
||||
if (badPadding) {
|
||||
crv = CKR_ENCRYPTED_DATA_INVALID;
|
||||
} else {
|
||||
outlen -= padding;
|
||||
}
|
||||
*pulDataLen = (CK_ULONG)outlen;
|
||||
}
|
||||
}
|
||||
*pulDataLen = (CK_ULONG)outlen;
|
||||
sftk_TerminateOp(session, SFTK_DECRYPT, context);
|
||||
finish:
|
||||
done:
|
||||
sftk_FreeSession(session);
|
||||
return crv;
|
||||
}
|
||||
|
|
@ -1920,54 +2004,55 @@ sftk_HMACCmp(CK_ULONG *copyLen, unsigned char *sig, unsigned int sigLen,
|
|||
}
|
||||
|
||||
/*
|
||||
* common HMAC initalization routine
|
||||
* common HMAC + CMAC initialization routine
|
||||
*/
|
||||
static CK_RV
|
||||
sftk_doHMACInit(SFTKSessionContext *context, HASH_HashType hash,
|
||||
SFTKObject *key, CK_ULONG mac_size)
|
||||
sftk_doMACInit(CK_MECHANISM_TYPE mech, SFTKSessionContext *session,
|
||||
SFTKObject *key, CK_ULONG mac_size)
|
||||
{
|
||||
SFTKAttribute *keyval;
|
||||
HMACContext *HMACcontext;
|
||||
CK_RV crv;
|
||||
sftk_MACCtx *context;
|
||||
CK_ULONG *intpointer;
|
||||
const SECHashObject *hashObj = HASH_GetRawHashObject(hash);
|
||||
PRBool isFIPS = (key->slot->slotID == FIPS_SLOT_ID);
|
||||
|
||||
/* required by FIPS 198 Section 4 */
|
||||
if (isFIPS && (mac_size < 4 || mac_size < hashObj->length / 2)) {
|
||||
/* Set up the initial context. */
|
||||
crv = sftk_MAC_Create(mech, key, &context);
|
||||
if (crv != CKR_OK) {
|
||||
return crv;
|
||||
}
|
||||
|
||||
session->hashInfo = context;
|
||||
session->multi = PR_TRUE;
|
||||
|
||||
/* Required by FIPS 198 Section 4. Delay this check until after the MAC
|
||||
* has been initialized to steal the output size of the MAC. */
|
||||
if (isFIPS && (mac_size < 4 || mac_size < context->mac_size / 2)) {
|
||||
sftk_MAC_Destroy(context, PR_TRUE);
|
||||
return CKR_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
keyval = sftk_FindAttribute(key, CKA_VALUE);
|
||||
if (keyval == NULL)
|
||||
return CKR_KEY_SIZE_RANGE;
|
||||
/* Configure our helper functions appropriately. Note that these casts
|
||||
* ignore the return values. */
|
||||
session->hashUpdate = (SFTKHash)sftk_MAC_Update;
|
||||
session->end = (SFTKEnd)sftk_MAC_Finish;
|
||||
session->hashdestroy = (SFTKDestroy)sftk_MAC_Destroy;
|
||||
|
||||
HMACcontext = HMAC_Create(hashObj,
|
||||
(const unsigned char *)keyval->attrib.pValue,
|
||||
keyval->attrib.ulValueLen, isFIPS);
|
||||
context->hashInfo = HMACcontext;
|
||||
context->multi = PR_TRUE;
|
||||
sftk_FreeAttribute(keyval);
|
||||
if (context->hashInfo == NULL) {
|
||||
if (PORT_GetError() == SEC_ERROR_INVALID_ARGS) {
|
||||
return CKR_KEY_SIZE_RANGE;
|
||||
}
|
||||
return CKR_HOST_MEMORY;
|
||||
}
|
||||
context->hashUpdate = (SFTKHash)HMAC_Update;
|
||||
context->end = (SFTKEnd)HMAC_Finish;
|
||||
|
||||
context->hashdestroy = (SFTKDestroy)HMAC_Destroy;
|
||||
intpointer = PORT_New(CK_ULONG);
|
||||
if (intpointer == NULL) {
|
||||
sftk_MAC_Destroy(context, PR_TRUE);
|
||||
return CKR_HOST_MEMORY;
|
||||
}
|
||||
*intpointer = mac_size;
|
||||
context->cipherInfo = intpointer;
|
||||
context->destroy = (SFTKDestroy)sftk_Space;
|
||||
context->update = (SFTKCipher)sftk_SignCopy;
|
||||
context->verify = (SFTKVerify)sftk_HMACCmp;
|
||||
context->maxLen = hashObj->length;
|
||||
HMAC_Begin(HMACcontext);
|
||||
session->cipherInfo = intpointer;
|
||||
|
||||
/* Since we're only "hashing", copy the result from session->end to the
|
||||
* caller using sftk_SignCopy. */
|
||||
session->update = (SFTKCipher)sftk_SignCopy;
|
||||
session->verify = (SFTKVerify)sftk_HMACCmp;
|
||||
session->destroy = (SFTKDestroy)sftk_Space;
|
||||
|
||||
session->maxLen = context->mac_size;
|
||||
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
|
|
@ -2123,9 +2208,13 @@ sftk_InitCBCMac(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
|
|||
unsigned int blockSize;
|
||||
PRBool isXCBC = PR_FALSE;
|
||||
|
||||
if (!pMechanism) {
|
||||
return CKR_MECHANISM_PARAM_INVALID;
|
||||
}
|
||||
|
||||
switch (pMechanism->mechanism) {
|
||||
case CKM_RC2_MAC_GENERAL:
|
||||
if (!pMechanism->pParameter) {
|
||||
if (BAD_PARAM_CAST(pMechanism, sizeof(CK_RC2_MAC_GENERAL_PARAMS))) {
|
||||
return CKR_MECHANISM_PARAM_INVALID;
|
||||
}
|
||||
mac_bytes =
|
||||
|
|
@ -2145,12 +2234,18 @@ sftk_InitCBCMac(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
|
|||
break;
|
||||
#if NSS_SOFTOKEN_DOES_RC5
|
||||
case CKM_RC5_MAC_GENERAL:
|
||||
if (BAD_PARAM_CAST(pMechanism, sizeof(CK_RC5_MAC_GENERAL_PARAMS))) {
|
||||
return CKR_MECHANISM_PARAM_INVALID;
|
||||
}
|
||||
mac_bytes =
|
||||
((CK_RC5_MAC_GENERAL_PARAMS *)pMechanism->pParameter)->ulMacLength;
|
||||
/* fall through */
|
||||
case CKM_RC5_MAC:
|
||||
/* this works because ulEffectiveBits is in the same place in both the
|
||||
* CK_RC5_MAC_GENERAL_PARAMS and CK_RC5_CBC_PARAMS */
|
||||
if (BAD_PARAM_CAST(pMechanism, sizeof(CK_RC5_MAC_GENERAL_PARAMS))) {
|
||||
return CKR_MECHANISM_PARAM_INVALID;
|
||||
}
|
||||
rc5_mac = (CK_RC5_MAC_GENERAL_PARAMS *)pMechanism->pParameter;
|
||||
rc5_params.ulWordsize = rc5_mac->ulWordsize;
|
||||
rc5_params.ulRounds = rc5_mac->ulRounds;
|
||||
|
|
@ -2707,18 +2802,19 @@ NSC_SignInit(CK_SESSION_HANDLE hSession,
|
|||
|
||||
break;
|
||||
|
||||
#define INIT_HMAC_MECH(mmm) \
|
||||
case CKM_##mmm##_HMAC_GENERAL: \
|
||||
PORT_Assert(pMechanism->pParameter); \
|
||||
if (!pMechanism->pParameter) { \
|
||||
crv = CKR_MECHANISM_PARAM_INVALID; \
|
||||
break; \
|
||||
} \
|
||||
crv = sftk_doHMACInit(context, HASH_Alg##mmm, key, \
|
||||
*(CK_ULONG *)pMechanism->pParameter); \
|
||||
break; \
|
||||
case CKM_##mmm##_HMAC: \
|
||||
crv = sftk_doHMACInit(context, HASH_Alg##mmm, key, mmm##_LENGTH); \
|
||||
#define INIT_HMAC_MECH(mmm) \
|
||||
case CKM_##mmm##_HMAC_GENERAL: \
|
||||
PORT_Assert(pMechanism->pParameter); \
|
||||
if (!pMechanism->pParameter) { \
|
||||
crv = CKR_MECHANISM_PARAM_INVALID; \
|
||||
break; \
|
||||
} \
|
||||
crv = sftk_doMACInit(pMechanism->mechanism, context, key, \
|
||||
*(CK_ULONG *)pMechanism->pParameter); \
|
||||
break; \
|
||||
case CKM_##mmm##_HMAC: \
|
||||
crv = sftk_doMACInit(pMechanism->mechanism, context, key, \
|
||||
mmm##_LENGTH); \
|
||||
break;
|
||||
|
||||
INIT_HMAC_MECH(MD2)
|
||||
|
|
@ -2730,17 +2826,27 @@ NSC_SignInit(CK_SESSION_HANDLE hSession,
|
|||
|
||||
case CKM_SHA_1_HMAC_GENERAL:
|
||||
PORT_Assert(pMechanism->pParameter);
|
||||
if (!pMechanism->pParameter) {
|
||||
if (!pMechanism->pParameter || pMechanism->ulParameterLen != sizeof(CK_MAC_GENERAL_PARAMS)) {
|
||||
crv = CKR_MECHANISM_PARAM_INVALID;
|
||||
break;
|
||||
}
|
||||
crv = sftk_doHMACInit(context, HASH_AlgSHA1, key,
|
||||
*(CK_ULONG *)pMechanism->pParameter);
|
||||
crv = sftk_doMACInit(pMechanism->mechanism, context, key,
|
||||
*(CK_ULONG *)pMechanism->pParameter);
|
||||
break;
|
||||
case CKM_SHA_1_HMAC:
|
||||
crv = sftk_doHMACInit(context, HASH_AlgSHA1, key, SHA1_LENGTH);
|
||||
crv = sftk_doMACInit(pMechanism->mechanism, context, key, SHA1_LENGTH);
|
||||
break;
|
||||
case CKM_AES_CMAC_GENERAL:
|
||||
PORT_Assert(pMechanism->pParameter);
|
||||
if (!pMechanism->pParameter || pMechanism->ulParameterLen != sizeof(CK_MAC_GENERAL_PARAMS)) {
|
||||
crv = CKR_MECHANISM_PARAM_INVALID;
|
||||
break;
|
||||
}
|
||||
crv = sftk_doMACInit(pMechanism->mechanism, context, key, *(CK_ULONG *)pMechanism->pParameter);
|
||||
break;
|
||||
case CKM_AES_CMAC:
|
||||
crv = sftk_doMACInit(pMechanism->mechanism, context, key, AES_BLOCK_SIZE);
|
||||
break;
|
||||
|
||||
case CKM_SSL3_MD5_MAC:
|
||||
PORT_Assert(pMechanism->pParameter);
|
||||
if (!pMechanism->pParameter) {
|
||||
|
|
@ -3414,11 +3520,11 @@ NSC_VerifyInit(CK_SESSION_HANDLE hSession,
|
|||
crv = CKR_MECHANISM_PARAM_INVALID;
|
||||
break;
|
||||
}
|
||||
crv = sftk_doHMACInit(context, HASH_AlgSHA1, key,
|
||||
*(CK_ULONG *)pMechanism->pParameter);
|
||||
crv = sftk_doMACInit(pMechanism->mechanism, context, key,
|
||||
*(CK_ULONG *)pMechanism->pParameter);
|
||||
break;
|
||||
case CKM_SHA_1_HMAC:
|
||||
crv = sftk_doHMACInit(context, HASH_AlgSHA1, key, SHA1_LENGTH);
|
||||
crv = sftk_doMACInit(pMechanism->mechanism, context, key, SHA1_LENGTH);
|
||||
break;
|
||||
|
||||
case CKM_SSL3_MD5_MAC:
|
||||
|
|
@ -3744,11 +3850,17 @@ nsc_pbe_key_gen(NSSPKCS5PBEParameter *pkcs5_pbe, CK_MECHANISM_PTR pMechanism,
|
|||
iv.len = 0;
|
||||
|
||||
if (pMechanism->mechanism == CKM_PKCS5_PBKD2) {
|
||||
if (BAD_PARAM_CAST(pMechanism, sizeof(CK_PKCS5_PBKD2_PARAMS))) {
|
||||
return CKR_MECHANISM_PARAM_INVALID;
|
||||
}
|
||||
pbkd2_params = (CK_PKCS5_PBKD2_PARAMS *)pMechanism->pParameter;
|
||||
pwitem.data = (unsigned char *)pbkd2_params->pPassword;
|
||||
/* was this a typo in the PKCS #11 spec? */
|
||||
pwitem.len = *pbkd2_params->ulPasswordLen;
|
||||
} else {
|
||||
if (BAD_PARAM_CAST(pMechanism, sizeof(CK_PBE_PARAMS))) {
|
||||
return CKR_MECHANISM_PARAM_INVALID;
|
||||
}
|
||||
pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter;
|
||||
pwitem.data = (unsigned char *)pbe_params->pPassword;
|
||||
pwitem.len = pbe_params->ulPasswordLen;
|
||||
|
|
@ -4048,6 +4160,10 @@ nsc_SetupHMACKeyGen(CK_MECHANISM_PTR pMechanism, NSSPKCS5PBEParameter **pbe)
|
|||
PORT_FreeArena(arena, PR_TRUE);
|
||||
return CKR_HOST_MEMORY;
|
||||
}
|
||||
if (BAD_PARAM_CAST(pMechanism, sizeof(CK_PBE_PARAMS))) {
|
||||
PORT_FreeArena(arena, PR_TRUE);
|
||||
return CKR_MECHANISM_PARAM_INVALID;
|
||||
}
|
||||
|
||||
params->poolp = arena;
|
||||
params->ivLen = 0;
|
||||
|
|
@ -4127,10 +4243,10 @@ nsc_SetupPBEKeyGen(CK_MECHANISM_PTR pMechanism, NSSPKCS5PBEParameter **pbe,
|
|||
}
|
||||
|
||||
if (pMechanism->mechanism == CKM_PKCS5_PBKD2) {
|
||||
pbkd2_params = (CK_PKCS5_PBKD2_PARAMS *)pMechanism->pParameter;
|
||||
if (pbkd2_params == NULL) {
|
||||
if (BAD_PARAM_CAST(pMechanism, sizeof(CK_PKCS5_PBKD2_PARAMS))) {
|
||||
return CKR_MECHANISM_PARAM_INVALID;
|
||||
}
|
||||
pbkd2_params = (CK_PKCS5_PBKD2_PARAMS *)pMechanism->pParameter;
|
||||
switch (pbkd2_params->prf) {
|
||||
case CKP_PKCS5_PBKD2_HMAC_SHA1:
|
||||
hashType = HASH_AlgSHA1;
|
||||
|
|
@ -4157,6 +4273,9 @@ nsc_SetupPBEKeyGen(CK_MECHANISM_PTR pMechanism, NSSPKCS5PBEParameter **pbe,
|
|||
salt.len = (unsigned int)pbkd2_params->ulSaltSourceDataLen;
|
||||
iteration = pbkd2_params->iterations;
|
||||
} else {
|
||||
if (BAD_PARAM_CAST(pMechanism, sizeof(CK_PBE_PARAMS))) {
|
||||
return CKR_MECHANISM_PARAM_INVALID;
|
||||
}
|
||||
pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter;
|
||||
salt.data = (unsigned char *)pbe_params->pSalt;
|
||||
salt.len = (unsigned int)pbe_params->ulSaltLen;
|
||||
|
|
@ -4203,11 +4322,12 @@ nsc_SetupPBEKeyGen(CK_MECHANISM_PTR pMechanism, NSSPKCS5PBEParameter **pbe,
|
|||
break;
|
||||
default:
|
||||
crv = CKR_MECHANISM_INVALID;
|
||||
nsspkcs5_DestroyPBEParameter(params);
|
||||
break;
|
||||
}
|
||||
if (crv == CKR_OK) {
|
||||
*pbe = params;
|
||||
} else {
|
||||
nsspkcs5_DestroyPBEParameter(params);
|
||||
}
|
||||
return crv;
|
||||
}
|
||||
|
|
@ -4272,12 +4392,12 @@ NSC_GenerateKey(CK_SESSION_HANDLE hSession,
|
|||
}
|
||||
|
||||
crv = sftk_AddAttributeType(key, sftk_attr_expand(&pTemplate[i]));
|
||||
if (crv != CKR_OK)
|
||||
if (crv != CKR_OK) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (crv != CKR_OK) {
|
||||
sftk_FreeObject(key);
|
||||
return crv;
|
||||
goto loser;
|
||||
}
|
||||
|
||||
/* make sure we don't have any class, key_type, or value fields */
|
||||
|
|
@ -4390,8 +4510,10 @@ NSC_GenerateKey(CK_SESSION_HANDLE hSession,
|
|||
}
|
||||
|
||||
if (crv != CKR_OK) {
|
||||
sftk_FreeObject(key);
|
||||
return crv;
|
||||
if (pbe_param) {
|
||||
nsspkcs5_DestroyPBEParameter(pbe_param);
|
||||
}
|
||||
goto loser;
|
||||
}
|
||||
|
||||
/* if there was no error,
|
||||
|
|
@ -4409,6 +4531,10 @@ NSC_GenerateKey(CK_SESSION_HANDLE hSession,
|
|||
break;
|
||||
case nsc_ssl:
|
||||
rsa_pms = (SSL3RSAPreMasterSecret *)buf;
|
||||
if (BAD_PARAM_CAST(pMechanism, sizeof(CK_VERSION))) {
|
||||
crv = CKR_MECHANISM_PARAM_INVALID;
|
||||
goto loser;
|
||||
}
|
||||
version = (CK_VERSION *)pMechanism->pParameter;
|
||||
rsa_pms->client_version[0] = version->major;
|
||||
rsa_pms->client_version[1] = version->minor;
|
||||
|
|
@ -4427,6 +4553,10 @@ NSC_GenerateKey(CK_SESSION_HANDLE hSession,
|
|||
crv = nsc_parameter_gen(key_type, key);
|
||||
break;
|
||||
case nsc_jpake:
|
||||
if (BAD_PARAM_CAST(pMechanism, sizeof(CK_NSS_JPAKERound1Params))) {
|
||||
crv = CKR_MECHANISM_PARAM_INVALID;
|
||||
goto loser;
|
||||
}
|
||||
crv = jpake_Round1(hashType,
|
||||
(CK_NSS_JPAKERound1Params *)pMechanism->pParameter,
|
||||
key);
|
||||
|
|
@ -4434,34 +4564,30 @@ NSC_GenerateKey(CK_SESSION_HANDLE hSession,
|
|||
}
|
||||
|
||||
if (crv != CKR_OK) {
|
||||
sftk_FreeObject(key);
|
||||
return crv;
|
||||
goto loser;
|
||||
}
|
||||
|
||||
/* Add the class, key_type, and value */
|
||||
crv = sftk_AddAttributeType(key, CKA_CLASS, &objclass, sizeof(CK_OBJECT_CLASS));
|
||||
if (crv != CKR_OK) {
|
||||
sftk_FreeObject(key);
|
||||
return crv;
|
||||
goto loser;
|
||||
}
|
||||
crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &key_type, sizeof(CK_KEY_TYPE));
|
||||
if (crv != CKR_OK) {
|
||||
sftk_FreeObject(key);
|
||||
return crv;
|
||||
goto loser;
|
||||
}
|
||||
if (key_length != 0) {
|
||||
crv = sftk_AddAttributeType(key, CKA_VALUE, buf, key_length);
|
||||
if (crv != CKR_OK) {
|
||||
sftk_FreeObject(key);
|
||||
return crv;
|
||||
goto loser;
|
||||
}
|
||||
}
|
||||
|
||||
/* get the session */
|
||||
session = sftk_SessionFromHandle(hSession);
|
||||
if (session == NULL) {
|
||||
sftk_FreeObject(key);
|
||||
return CKR_SESSION_HANDLE_INVALID;
|
||||
crv = CKR_SESSION_HANDLE_INVALID;
|
||||
goto loser;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -4478,6 +4604,7 @@ NSC_GenerateKey(CK_SESSION_HANDLE hSession,
|
|||
if (crv == CKR_OK) {
|
||||
*phKey = key->handle;
|
||||
}
|
||||
loser:
|
||||
sftk_FreeObject(key);
|
||||
return crv;
|
||||
}
|
||||
|
|
@ -5591,8 +5718,8 @@ NSC_WrapKey(CK_SESSION_HANDLE hSession,
|
|||
}
|
||||
|
||||
key = sftk_ObjectFromHandle(hKey, session);
|
||||
sftk_FreeSession(session);
|
||||
if (key == NULL) {
|
||||
sftk_FreeSession(session);
|
||||
return CKR_KEY_HANDLE_INVALID;
|
||||
}
|
||||
|
||||
|
|
@ -5698,7 +5825,7 @@ NSC_WrapKey(CK_SESSION_HANDLE hSession,
|
|||
break;
|
||||
}
|
||||
sftk_FreeObject(key);
|
||||
|
||||
sftk_FreeSession(session);
|
||||
return sftk_mapWrap(crv);
|
||||
}
|
||||
|
||||
|
|
@ -6507,7 +6634,6 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession,
|
|||
CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
|
||||
CK_OBJECT_CLASS classType = CKO_SECRET_KEY;
|
||||
CK_KEY_DERIVATION_STRING_DATA *stringPtr;
|
||||
CK_MECHANISM_TYPE mechanism = pMechanism->mechanism;
|
||||
PRBool isTLS = PR_FALSE;
|
||||
PRBool isDH = PR_FALSE;
|
||||
HASH_HashType tlsPrfHash = HASH_AlgNULL;
|
||||
|
|
@ -6525,6 +6651,11 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession,
|
|||
if (!slot) {
|
||||
return CKR_SESSION_HANDLE_INVALID;
|
||||
}
|
||||
if (!pMechanism) {
|
||||
return CKR_MECHANISM_PARAM_INVALID;
|
||||
}
|
||||
CK_MECHANISM_TYPE mechanism = pMechanism->mechanism;
|
||||
|
||||
/*
|
||||
* now lets create an object to hang the attributes off of
|
||||
*/
|
||||
|
|
@ -6698,6 +6829,10 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession,
|
|||
|
||||
if ((mechanism == CKM_TLS12_MASTER_KEY_DERIVE) ||
|
||||
(mechanism == CKM_TLS12_MASTER_KEY_DERIVE_DH)) {
|
||||
if (BAD_PARAM_CAST(pMechanism, sizeof(CK_TLS12_MASTER_KEY_DERIVE_PARAMS))) {
|
||||
crv = CKR_MECHANISM_PARAM_INVALID;
|
||||
break;
|
||||
}
|
||||
CK_TLS12_MASTER_KEY_DERIVE_PARAMS *tls12_master =
|
||||
(CK_TLS12_MASTER_KEY_DERIVE_PARAMS *)pMechanism->pParameter;
|
||||
tlsPrfHash = GetHashTypeFromMechanism(tls12_master->prfHashMechanism);
|
||||
|
|
@ -6965,6 +7100,10 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession,
|
|||
unsigned char crsrdata[SSL3_RANDOM_LENGTH * 2];
|
||||
|
||||
if (mechanism == CKM_TLS12_KEY_AND_MAC_DERIVE) {
|
||||
if (BAD_PARAM_CAST(pMechanism, sizeof(CK_TLS12_KEY_MAT_PARAMS))) {
|
||||
crv = CKR_MECHANISM_PARAM_INVALID;
|
||||
break;
|
||||
}
|
||||
CK_TLS12_KEY_MAT_PARAMS *tls12_keys =
|
||||
(CK_TLS12_KEY_MAT_PARAMS *)pMechanism->pParameter;
|
||||
tlsPrfHash = GetHashTypeFromMechanism(tls12_keys->prfHashMechanism);
|
||||
|
|
@ -7008,6 +7147,13 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession,
|
|||
crv = CKR_HOST_MEMORY;
|
||||
break;
|
||||
}
|
||||
|
||||
if (BAD_PARAM_CAST(pMechanism, sizeof(CK_SSL3_KEY_MAT_PARAMS))) {
|
||||
MD5_DestroyContext(md5, PR_TRUE);
|
||||
SHA1_DestroyContext(sha, PR_TRUE);
|
||||
crv = CKR_MECHANISM_PARAM_INVALID;
|
||||
break;
|
||||
}
|
||||
ssl3_keys = (CK_SSL3_KEY_MAT_PARAMS *)pMechanism->pParameter;
|
||||
|
||||
PORT_Memcpy(srcrdata,
|
||||
|
|
@ -7202,6 +7348,10 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession,
|
|||
CK_ULONG len;
|
||||
|
||||
if (mechanism == CKM_DES3_ECB_ENCRYPT_DATA) {
|
||||
if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) {
|
||||
crv = CKR_MECHANISM_PARAM_INVALID;
|
||||
break;
|
||||
}
|
||||
stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)
|
||||
pMechanism->pParameter;
|
||||
mode = NSS_DES_EDE3;
|
||||
|
|
@ -7251,10 +7401,18 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession,
|
|||
if (mechanism == CKM_AES_ECB_ENCRYPT_DATA) {
|
||||
mode = NSS_AES;
|
||||
iv = NULL;
|
||||
if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) {
|
||||
crv = CKR_MECHANISM_PARAM_INVALID;
|
||||
break;
|
||||
}
|
||||
stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter;
|
||||
data = stringPtr->pData;
|
||||
len = stringPtr->ulLen;
|
||||
} else {
|
||||
if (BAD_PARAM_CAST(pMechanism, sizeof(CK_AES_CBC_ENCRYPT_DATA_PARAMS))) {
|
||||
crv = CKR_MECHANISM_PARAM_INVALID;
|
||||
break;
|
||||
}
|
||||
aesEncryptPtr =
|
||||
(CK_AES_CBC_ENCRYPT_DATA_PARAMS *)pMechanism->pParameter;
|
||||
mode = NSS_AES_CBC;
|
||||
|
|
@ -7287,6 +7445,10 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession,
|
|||
CK_ULONG len;
|
||||
|
||||
if (mechanism == CKM_CAMELLIA_ECB_ENCRYPT_DATA) {
|
||||
if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) {
|
||||
crv = CKR_MECHANISM_PARAM_INVALID;
|
||||
break;
|
||||
}
|
||||
stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)
|
||||
pMechanism->pParameter;
|
||||
aesEncryptPtr = NULL;
|
||||
|
|
@ -7295,6 +7457,10 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession,
|
|||
len = stringPtr->ulLen;
|
||||
iv = NULL;
|
||||
} else {
|
||||
if (BAD_PARAM_CAST(pMechanism, sizeof(CK_AES_CBC_ENCRYPT_DATA_PARAMS))) {
|
||||
crv = CKR_MECHANISM_PARAM_INVALID;
|
||||
break;
|
||||
}
|
||||
stringPtr = NULL;
|
||||
aesEncryptPtr = (CK_AES_CBC_ENCRYPT_DATA_PARAMS *)
|
||||
pMechanism->pParameter;
|
||||
|
|
@ -7328,6 +7494,10 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession,
|
|||
CK_ULONG len;
|
||||
|
||||
if (mechanism == CKM_SEED_ECB_ENCRYPT_DATA) {
|
||||
if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) {
|
||||
crv = CKR_MECHANISM_PARAM_INVALID;
|
||||
break;
|
||||
}
|
||||
mode = NSS_SEED;
|
||||
stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)
|
||||
pMechanism->pParameter;
|
||||
|
|
@ -7336,6 +7506,10 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession,
|
|||
len = stringPtr->ulLen;
|
||||
iv = NULL;
|
||||
} else {
|
||||
if (BAD_PARAM_CAST(pMechanism, sizeof(CK_AES_CBC_ENCRYPT_DATA_PARAMS))) {
|
||||
crv = CKR_MECHANISM_PARAM_INVALID;
|
||||
break;
|
||||
}
|
||||
mode = NSS_SEED_CBC;
|
||||
aesEncryptPtr = (CK_AES_CBC_ENCRYPT_DATA_PARAMS *)
|
||||
pMechanism->pParameter;
|
||||
|
|
@ -7427,6 +7601,10 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession,
|
|||
if (crv != CKR_OK)
|
||||
break;
|
||||
|
||||
if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) {
|
||||
crv = CKR_MECHANISM_PARAM_INVALID;
|
||||
break;
|
||||
}
|
||||
stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter;
|
||||
tmpKeySize = att->attrib.ulValueLen + stringPtr->ulLen;
|
||||
if (keySize == 0)
|
||||
|
|
@ -7453,6 +7631,10 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession,
|
|||
if (crv != CKR_OK)
|
||||
break;
|
||||
|
||||
if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) {
|
||||
crv = CKR_MECHANISM_PARAM_INVALID;
|
||||
break;
|
||||
}
|
||||
stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter;
|
||||
tmpKeySize = att->attrib.ulValueLen + stringPtr->ulLen;
|
||||
if (keySize == 0)
|
||||
|
|
@ -7479,6 +7661,10 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession,
|
|||
if (crv != CKR_OK)
|
||||
break;
|
||||
|
||||
if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) {
|
||||
crv = CKR_MECHANISM_PARAM_INVALID;
|
||||
break;
|
||||
}
|
||||
stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter;
|
||||
tmpKeySize = PR_MIN(att->attrib.ulValueLen, stringPtr->ulLen);
|
||||
if (keySize == 0)
|
||||
|
|
@ -7503,6 +7689,10 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession,
|
|||
break;
|
||||
|
||||
case CKM_EXTRACT_KEY_FROM_KEY: {
|
||||
if (BAD_PARAM_CAST(pMechanism, sizeof(CK_EXTRACT_PARAMS))) {
|
||||
crv = CKR_MECHANISM_PARAM_INVALID;
|
||||
break;
|
||||
}
|
||||
/* the following assumes 8 bits per byte */
|
||||
CK_ULONG extract = *(CK_EXTRACT_PARAMS *)pMechanism->pParameter;
|
||||
CK_ULONG shift = extract & 0x7; /* extract mod 8 the fast way */
|
||||
|
|
|
|||
|
|
@ -17,6 +17,9 @@
|
|||
#include "chacha20poly1305.h"
|
||||
#include "hasht.h"
|
||||
|
||||
#include "alghmac.h"
|
||||
#include "cmac.h"
|
||||
|
||||
/*
|
||||
* Configuration Defines
|
||||
*
|
||||
|
|
@ -458,7 +461,7 @@ struct SFTKItemTemplateStr {
|
|||
|
||||
#define SFTK_TOKEN_KRL_HANDLE (SFTK_TOKEN_MAGIC | SFTK_TOKEN_TYPE_CRL | 1)
|
||||
/* how big (in bytes) a password/pin we can deal with */
|
||||
#define SFTK_MAX_PIN 255
|
||||
#define SFTK_MAX_PIN 500
|
||||
/* minimum password/pin length (in Unicode characters) in FIPS mode */
|
||||
#define FIPS_MIN_PIN 7
|
||||
|
||||
|
|
@ -595,6 +598,73 @@ typedef struct sftk_parametersStr {
|
|||
#define CERT_DB_FMT "%scert%s.db"
|
||||
#define KEY_DB_FMT "%skey%s.db"
|
||||
|
||||
struct sftk_MACConstantTimeCtxStr {
|
||||
const SECHashObject *hash;
|
||||
unsigned char mac[64];
|
||||
unsigned char secret[64];
|
||||
unsigned int headerLength;
|
||||
unsigned int secretLength;
|
||||
unsigned int totalLength;
|
||||
unsigned char header[75];
|
||||
};
|
||||
typedef struct sftk_MACConstantTimeCtxStr sftk_MACConstantTimeCtx;
|
||||
|
||||
struct sftk_MACCtxStr {
|
||||
/* This is a common MAC context that supports both HMAC and CMAC
|
||||
* operations. This also presents a unified set of semantics:
|
||||
*
|
||||
* - Everything except Destroy returns a CK_RV, indicating success
|
||||
* or failure. (This handles the difference between HMAC's and CMAC's
|
||||
* interfaces, since the underlying AES _might_ fail with CMAC).
|
||||
*
|
||||
* - The underlying MAC is started on Init(...), so Update(...) can
|
||||
* called right away. (This handles the difference between HMAC and
|
||||
* CMAC in their *_Init(...) functions).
|
||||
*
|
||||
* - Calling semantics:
|
||||
*
|
||||
* - One of sftk_MAC_{Create,Init,InitRaw}(...) to set up the MAC
|
||||
* context, checking the return code.
|
||||
* - sftk_MAC_Update(...) as many times as necessary to process
|
||||
* input data, checking the return code.
|
||||
* - sftk_MAC_Finish(...) to get the output of the MAC; result_len
|
||||
* may be NULL if the caller knows the expected output length,
|
||||
* checking the return code. If result_len is NULL, this will
|
||||
* PR_ASSERT(...) that the actual returned length was equal to
|
||||
* max_result_len.
|
||||
*
|
||||
* Note: unlike HMAC_Finish(...), this allows the caller to specify
|
||||
* a return value less than return length, to align with
|
||||
* CMAC_Finish(...)'s semantics. This will force an additional
|
||||
* stack allocation of size SFTK_MAX_MAC_LENGTH.
|
||||
* - sftk_MAC_Reset(...) if the caller wishes to compute a new MAC
|
||||
* with the same key, checking the return code.
|
||||
* - sftk_MAC_Destroy(...) when the caller frees its associated
|
||||
* memory, passing PR_TRUE if sftk_MAC_Create(...) was called,
|
||||
* and PR_FALSE otherwise.
|
||||
*/
|
||||
|
||||
CK_MECHANISM_TYPE mech;
|
||||
unsigned int mac_size;
|
||||
|
||||
union {
|
||||
HMACContext *hmac;
|
||||
CMACContext *cmac;
|
||||
|
||||
/* Functions to update when adding a new MAC or a new hash:
|
||||
*
|
||||
* - sftk_MAC_Init
|
||||
* - sftk_MAC_Update
|
||||
* - sftk_MAC_Finish
|
||||
* - sftk_MAC_Reset
|
||||
*/
|
||||
void *raw;
|
||||
} mac;
|
||||
|
||||
void (*destroy_func)(void *ctx, PRBool free_it);
|
||||
};
|
||||
typedef struct sftk_MACCtxStr sftk_MACCtx;
|
||||
|
||||
SEC_BEGIN_PROTOS
|
||||
|
||||
/* shared functions between pkcs11.c and fipstokn.c */
|
||||
|
|
@ -766,17 +836,6 @@ extern CK_RV jpake_Final(HASH_HashType hashType,
|
|||
SFTKObject *sourceKey, SFTKObject *key);
|
||||
|
||||
/* Constant time MAC functions (hmacct.c) */
|
||||
|
||||
struct sftk_MACConstantTimeCtxStr {
|
||||
const SECHashObject *hash;
|
||||
unsigned char mac[64];
|
||||
unsigned char secret[64];
|
||||
unsigned int headerLength;
|
||||
unsigned int secretLength;
|
||||
unsigned int totalLength;
|
||||
unsigned char header[75];
|
||||
};
|
||||
typedef struct sftk_MACConstantTimeCtxStr sftk_MACConstantTimeCtx;
|
||||
sftk_MACConstantTimeCtx *sftk_HMACConstantTime_New(
|
||||
CK_MECHANISM_PTR mech, SFTKObject *key);
|
||||
sftk_MACConstantTimeCtx *sftk_SSLv3MACConstantTime_New(
|
||||
|
|
@ -798,6 +857,16 @@ sftk_TLSPRFInit(SFTKSessionContext *context,
|
|||
HASH_HashType hash_alg,
|
||||
unsigned int out_len);
|
||||
|
||||
/* PKCS#11 MAC implementation. See sftk_MACCtxStr declaration above for
|
||||
* calling semantics for these functions. */
|
||||
CK_RV sftk_MAC_Create(CK_MECHANISM_TYPE mech, SFTKObject *key, sftk_MACCtx **ret_ctx);
|
||||
CK_RV sftk_MAC_Init(sftk_MACCtx *ctx, CK_MECHANISM_TYPE mech, SFTKObject *key);
|
||||
CK_RV sftk_MAC_InitRaw(sftk_MACCtx *ctx, CK_MECHANISM_TYPE mech, const unsigned char *key, unsigned int key_len, PRBool isFIPS);
|
||||
CK_RV sftk_MAC_Update(sftk_MACCtx *ctx, CK_BYTE_PTR data, unsigned int data_len);
|
||||
CK_RV sftk_MAC_Finish(sftk_MACCtx *ctx, CK_BYTE_PTR result, unsigned int *result_len, unsigned int max_result_len);
|
||||
CK_RV sftk_MAC_Reset(sftk_MACCtx *ctx);
|
||||
void sftk_MAC_Destroy(sftk_MACCtx *ctx, PRBool free_it);
|
||||
|
||||
SEC_END_PROTOS
|
||||
|
||||
#endif /* _PKCS11I_H_ */
|
||||
|
|
|
|||
|
|
@ -141,7 +141,7 @@ sftk_DestroyAttribute(SFTKAttribute *attribute)
|
|||
void
|
||||
sftk_FreeAttribute(SFTKAttribute *attribute)
|
||||
{
|
||||
if (attribute->freeAttr) {
|
||||
if (attribute && attribute->freeAttr) {
|
||||
sftk_DestroyAttribute(attribute);
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -159,7 +159,7 @@ static const CK_ATTRIBUTE_TYPE known_attributes[] = {
|
|||
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_PUBLIC_KEY_INFO
|
||||
CKA_PUBLIC_KEY_INFO, CKA_NSS_SERVER_DISTRUST_AFTER, CKA_NSS_EMAIL_DISTRUST_AFTER
|
||||
};
|
||||
|
||||
static int known_attributes_size = sizeof(known_attributes) /
|
||||
|
|
|
|||
|
|
@ -530,6 +530,7 @@ sftk_signTemplate(PLArenaPool *arena, SFTKDBHandle *handle,
|
|||
goto loser;
|
||||
}
|
||||
rv = sftkdb_SignAttribute(arena, &keyHandle->passwordKey,
|
||||
keyHandle->defaultIterationCount,
|
||||
objectID, template[i].type,
|
||||
&plainText, &signText);
|
||||
PZ_Unlock(keyHandle->passwordLock);
|
||||
|
|
@ -663,6 +664,7 @@ sftk_ExtractTemplate(PLArenaPool *arena, SFTKObject *object,
|
|||
break;
|
||||
}
|
||||
rv = sftkdb_EncryptAttribute(arena, &handle->passwordKey,
|
||||
handle->defaultIterationCount,
|
||||
&plainText, &cipherText);
|
||||
PZ_Unlock(handle->passwordLock);
|
||||
if (rv == SECSuccess) {
|
||||
|
|
@ -2449,7 +2451,7 @@ sftk_getDBForTokenObject(SFTKSlot *slot, CK_OBJECT_HANDLE objectID)
|
|||
* initialize a new database handle
|
||||
*/
|
||||
static SFTKDBHandle *
|
||||
sftk_NewDBHandle(SDB *sdb, int type)
|
||||
sftk_NewDBHandle(SDB *sdb, int type, PRBool legacy)
|
||||
{
|
||||
SFTKDBHandle *handle = PORT_New(SFTKDBHandle);
|
||||
handle->ref = 1;
|
||||
|
|
@ -2461,6 +2463,7 @@ sftk_NewDBHandle(SDB *sdb, int type)
|
|||
handle->updatePasswordKey = NULL;
|
||||
handle->updateID = NULL;
|
||||
handle->type = type;
|
||||
handle->usesLegacyStorage = legacy;
|
||||
handle->passwordKey.data = NULL;
|
||||
handle->passwordKey.len = 0;
|
||||
handle->passwordLock = NULL;
|
||||
|
|
@ -2620,6 +2623,7 @@ sftk_DBInit(const char *configdir, const char *certPrefix,
|
|||
PRBool newInit = PR_FALSE;
|
||||
PRBool needUpdate = PR_FALSE;
|
||||
char *nconfdir = NULL;
|
||||
PRBool legacy = PR_TRUE;
|
||||
|
||||
if (!readOnly) {
|
||||
flags = SDB_CREATE;
|
||||
|
|
@ -2652,12 +2656,14 @@ sftk_DBInit(const char *configdir, const char *certPrefix,
|
|||
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);
|
||||
legacy = PR_FALSE;
|
||||
|
||||
/*
|
||||
* if we failed to open the DB's read only, use the old ones if
|
||||
* the exists.
|
||||
*/
|
||||
if (crv != CKR_OK) {
|
||||
legacy = PR_TRUE;
|
||||
if ((flags & SDB_RDONLY) == SDB_RDONLY) {
|
||||
nconfdir = sftk_legacyPathFromSDBPath(confdir);
|
||||
}
|
||||
|
|
@ -2711,12 +2717,12 @@ sftk_DBInit(const char *configdir, const char *certPrefix,
|
|||
goto done;
|
||||
}
|
||||
if (!noCertDB) {
|
||||
*certDB = sftk_NewDBHandle(certSDB, SFTK_CERTDB_TYPE);
|
||||
*certDB = sftk_NewDBHandle(certSDB, SFTK_CERTDB_TYPE, legacy);
|
||||
} else {
|
||||
*certDB = NULL;
|
||||
}
|
||||
if (!noKeyDB) {
|
||||
*keyDB = sftk_NewDBHandle(keySDB, SFTK_KEYDB_TYPE);
|
||||
*keyDB = sftk_NewDBHandle(keySDB, SFTK_KEYDB_TYPE, legacy);
|
||||
} else {
|
||||
*keyDB = NULL;
|
||||
}
|
||||
|
|
@ -2759,7 +2765,7 @@ sftk_DBInit(const char *configdir, const char *certPrefix,
|
|||
(sftkdb_HasPasswordSet(*keyDB) == SECSuccess) ? PR_TRUE : PR_FALSE;
|
||||
/* if the password on the key db is NULL, kick off our update
|
||||
* chain of events */
|
||||
sftkdb_CheckPassword((*keyDB), "", &tokenRemoved);
|
||||
sftkdb_CheckPasswordNull((*keyDB), &tokenRemoved);
|
||||
} else {
|
||||
/* we don't have a key DB, update the certificate DB now */
|
||||
sftkdb_Update(*certDB, NULL);
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ CK_RV sftkdb_closeDB(SFTKDBHandle *handle);
|
|||
SECStatus sftkdb_PWIsInitialized(SFTKDBHandle *keydb);
|
||||
SECStatus sftkdb_CheckPassword(SFTKDBHandle *keydb, const char *pw,
|
||||
PRBool *tokenRemoved);
|
||||
SECStatus sftkdb_CheckPasswordNull(SFTKDBHandle *keydb, PRBool *tokenRemoved);
|
||||
SECStatus sftkdb_PWCached(SFTKDBHandle *keydb);
|
||||
SECStatus sftkdb_HasPasswordSet(SFTKDBHandle *keydb);
|
||||
SECStatus sftkdb_ResetKeyDB(SFTKDBHandle *keydb);
|
||||
|
|
@ -69,3 +70,5 @@ SFTKDBHandle *sftk_getKeyDB(SFTKSlot *slot);
|
|||
SFTKDBHandle *sftk_getDBForTokenObject(SFTKSlot *slot,
|
||||
CK_OBJECT_HANDLE objectID);
|
||||
void sftk_freeDB(SFTKDBHandle *certHandle);
|
||||
|
||||
PRBool sftk_isLegacyIterationCountAllowed(void);
|
||||
|
|
|
|||
|
|
@ -13,7 +13,9 @@ struct SFTKDBHandleStr {
|
|||
PRInt32 ref;
|
||||
CK_OBJECT_HANDLE type;
|
||||
SECItem passwordKey;
|
||||
int defaultIterationCount;
|
||||
SECItem *newKey;
|
||||
int newDefaultIterationCount;
|
||||
SECItem *oldKey;
|
||||
SECItem *updatePasswordKey;
|
||||
PZLock *passwordLock;
|
||||
|
|
@ -21,6 +23,7 @@ struct SFTKDBHandleStr {
|
|||
SDB *update;
|
||||
char *updateID;
|
||||
PRBool updateDBIsInit;
|
||||
PRBool usesLegacyStorage;
|
||||
};
|
||||
|
||||
#define SFTK_KEYDB_TYPE 0x40000000
|
||||
|
|
@ -39,9 +42,10 @@ struct SFTKDBHandleStr {
|
|||
SECStatus sftkdb_DecryptAttribute(SECItem *passKey, SECItem *cipherText,
|
||||
SECItem **plainText);
|
||||
SECStatus sftkdb_EncryptAttribute(PLArenaPool *arena, SECItem *passKey,
|
||||
SECItem *plainText, SECItem **cipherText);
|
||||
int iterationCount, SECItem *plainText,
|
||||
SECItem **cipherText);
|
||||
SECStatus sftkdb_SignAttribute(PLArenaPool *arena, SECItem *passKey,
|
||||
CK_OBJECT_HANDLE objectID,
|
||||
int iterationCount, CK_OBJECT_HANDLE objectID,
|
||||
CK_ATTRIBUTE_TYPE attrType,
|
||||
SECItem *plainText, SECItem **sigText);
|
||||
SECStatus sftkdb_VerifyAttribute(SECItem *passKey,
|
||||
|
|
|
|||
|
|
@ -9,12 +9,14 @@
|
|||
#include "softoken.h"
|
||||
#include "hmacct.h"
|
||||
|
||||
/* MACMechanismToHash converts a PKCS#11 MAC mechanism into a freebl hash
|
||||
/* HMACMechanismToHash converts a PKCS#11 MAC mechanism into a freebl hash
|
||||
* type. */
|
||||
static HASH_HashType
|
||||
MACMechanismToHash(CK_MECHANISM_TYPE mech)
|
||||
HMACMechanismToHash(CK_MECHANISM_TYPE mech)
|
||||
{
|
||||
switch (mech) {
|
||||
case CKM_MD2_HMAC:
|
||||
return HASH_AlgMD2;
|
||||
case CKM_MD5_HMAC:
|
||||
case CKM_SSL3_MD5_MAC:
|
||||
return HASH_AlgMD5;
|
||||
|
|
@ -48,7 +50,7 @@ SetupMAC(CK_MECHANISM_PTR mech, SFTKObject *key)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
alg = MACMechanismToHash(params->macAlg);
|
||||
alg = HMACMechanismToHash(params->macAlg);
|
||||
if (alg == HASH_AlgNULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -188,3 +190,284 @@ sftk_MACConstantTime_DestroyContext(void *pctx, PRBool free)
|
|||
{
|
||||
PORT_Free(pctx);
|
||||
}
|
||||
|
||||
CK_RV
|
||||
sftk_MAC_Create(CK_MECHANISM_TYPE mech, SFTKObject *key, sftk_MACCtx **ret_ctx)
|
||||
{
|
||||
CK_RV ret;
|
||||
|
||||
if (ret_ctx == NULL || key == NULL) {
|
||||
return CKR_HOST_MEMORY;
|
||||
}
|
||||
|
||||
*ret_ctx = PORT_New(sftk_MACCtx);
|
||||
if (*ret_ctx == NULL) {
|
||||
return CKR_HOST_MEMORY;
|
||||
}
|
||||
|
||||
ret = sftk_MAC_Init(*ret_ctx, mech, key);
|
||||
if (ret != CKR_OK) {
|
||||
sftk_MAC_Destroy(*ret_ctx, PR_TRUE);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
CK_RV
|
||||
sftk_MAC_Init(sftk_MACCtx *ctx, CK_MECHANISM_TYPE mech, SFTKObject *key)
|
||||
{
|
||||
SFTKAttribute *keyval = NULL;
|
||||
PRBool isFIPS = (key->slot->slotID == FIPS_SLOT_ID);
|
||||
CK_RV ret = CKR_OK;
|
||||
|
||||
/* Find the actual value of the key. */
|
||||
keyval = sftk_FindAttribute(key, CKA_VALUE);
|
||||
if (keyval == NULL) {
|
||||
ret = CKR_KEY_SIZE_RANGE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = sftk_MAC_InitRaw(ctx, mech,
|
||||
(const unsigned char *)keyval->attrib.pValue,
|
||||
keyval->attrib.ulValueLen, isFIPS);
|
||||
|
||||
done:
|
||||
sftk_FreeAttribute(keyval);
|
||||
return ret;
|
||||
}
|
||||
|
||||
CK_RV
|
||||
sftk_MAC_InitRaw(sftk_MACCtx *ctx, CK_MECHANISM_TYPE mech, const unsigned char *key, unsigned int key_len, PRBool isFIPS)
|
||||
{
|
||||
const SECHashObject *hashObj = NULL;
|
||||
CK_RV ret = CKR_OK;
|
||||
|
||||
if (ctx == NULL) {
|
||||
return CKR_HOST_MEMORY;
|
||||
}
|
||||
|
||||
/* Clear the context before use. */
|
||||
PORT_Memset(ctx, 0, sizeof(*ctx));
|
||||
|
||||
/* Save the mech. */
|
||||
ctx->mech = mech;
|
||||
|
||||
/* Initialize the correct MAC context. */
|
||||
switch (mech) {
|
||||
case CKM_MD2_HMAC:
|
||||
case CKM_MD5_HMAC:
|
||||
case CKM_SHA_1_HMAC:
|
||||
case CKM_SHA224_HMAC:
|
||||
case CKM_SHA256_HMAC:
|
||||
case CKM_SHA384_HMAC:
|
||||
case CKM_SHA512_HMAC:
|
||||
hashObj = HASH_GetRawHashObject(HMACMechanismToHash(mech));
|
||||
|
||||
/* Because we condition above only on hashes we know to be valid,
|
||||
* hashObj should never be NULL. This assert is only useful when
|
||||
* adding a new hash function (for which only partial support has
|
||||
* been added); thus there is no need to turn it into an if and
|
||||
* avoid the NULL dereference on the following line. */
|
||||
PR_ASSERT(hashObj != NULL);
|
||||
ctx->mac_size = hashObj->length;
|
||||
|
||||
goto hmac;
|
||||
case CKM_AES_CMAC:
|
||||
ctx->mac.cmac = CMAC_Create(CMAC_AES, key, key_len);
|
||||
ctx->destroy_func = (void (*)(void *, PRBool))(&CMAC_Destroy);
|
||||
|
||||
/* Copy the behavior of sftk_doCMACInit here. */
|
||||
if (ctx->mac.cmac == NULL) {
|
||||
if (PORT_GetError() == SEC_ERROR_INVALID_ARGS) {
|
||||
ret = CKR_KEY_SIZE_RANGE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = CKR_HOST_MEMORY;
|
||||
goto done;
|
||||
}
|
||||
|
||||
ctx->mac_size = AES_BLOCK_SIZE;
|
||||
|
||||
goto done;
|
||||
default:
|
||||
ret = CKR_MECHANISM_PARAM_INVALID;
|
||||
goto done;
|
||||
}
|
||||
|
||||
hmac:
|
||||
ctx->mac.hmac = HMAC_Create(hashObj, key, key_len, isFIPS);
|
||||
ctx->destroy_func = (void (*)(void *, PRBool))(&HMAC_Destroy);
|
||||
|
||||
/* Copy the behavior of sftk_doHMACInit here. */
|
||||
if (ctx->mac.hmac == NULL) {
|
||||
if (PORT_GetError() == SEC_ERROR_INVALID_ARGS) {
|
||||
ret = CKR_KEY_SIZE_RANGE;
|
||||
goto done;
|
||||
}
|
||||
ret = CKR_HOST_MEMORY;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Semantics: HMAC and CMAC should behave the same. Begin HMAC now. */
|
||||
HMAC_Begin(ctx->mac.hmac);
|
||||
|
||||
done:
|
||||
/* Handle a failure: ctx->mac.raw should be NULL, but make sure
|
||||
* destroy_func isn't set. */
|
||||
if (ret != CKR_OK) {
|
||||
ctx->destroy_func = NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
CK_RV
|
||||
sftk_MAC_Reset(sftk_MACCtx *ctx)
|
||||
{
|
||||
/* Useful for resetting the state of MAC prior to calling update again
|
||||
*
|
||||
* This lets the caller keep a single MAC instance and re-use it as long
|
||||
* as the key stays the same. */
|
||||
switch (ctx->mech) {
|
||||
case CKM_MD2_HMAC:
|
||||
case CKM_MD5_HMAC:
|
||||
case CKM_SHA_1_HMAC:
|
||||
case CKM_SHA224_HMAC:
|
||||
case CKM_SHA256_HMAC:
|
||||
case CKM_SHA384_HMAC:
|
||||
case CKM_SHA512_HMAC:
|
||||
HMAC_Begin(ctx->mac.hmac);
|
||||
break;
|
||||
case CKM_AES_CMAC:
|
||||
if (CMAC_Begin(ctx->mac.cmac) != SECSuccess) {
|
||||
return CKR_FUNCTION_FAILED;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* This shouldn't happen -- asserting indicates partial support
|
||||
* for a new MAC type. */
|
||||
PR_ASSERT(PR_FALSE);
|
||||
return CKR_FUNCTION_FAILED;
|
||||
}
|
||||
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
CK_RV
|
||||
sftk_MAC_Update(sftk_MACCtx *ctx, CK_BYTE_PTR data, unsigned int data_len)
|
||||
{
|
||||
switch (ctx->mech) {
|
||||
case CKM_MD2_HMAC:
|
||||
case CKM_MD5_HMAC:
|
||||
case CKM_SHA_1_HMAC:
|
||||
case CKM_SHA224_HMAC:
|
||||
case CKM_SHA256_HMAC:
|
||||
case CKM_SHA384_HMAC:
|
||||
case CKM_SHA512_HMAC:
|
||||
/* HMAC doesn't indicate failure in the return code. */
|
||||
HMAC_Update(ctx->mac.hmac, data, data_len);
|
||||
break;
|
||||
case CKM_AES_CMAC:
|
||||
/* CMAC indicates failure in the return code, however this is
|
||||
* unlikely to occur. */
|
||||
if (CMAC_Update(ctx->mac.cmac, data, data_len) != SECSuccess) {
|
||||
return CKR_FUNCTION_FAILED;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* This shouldn't happen -- asserting indicates partial support
|
||||
* for a new MAC type. */
|
||||
PR_ASSERT(PR_FALSE);
|
||||
return CKR_FUNCTION_FAILED;
|
||||
}
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
CK_RV
|
||||
sftk_MAC_Finish(sftk_MACCtx *ctx, CK_BYTE_PTR result, unsigned int *result_len, unsigned int max_result_len)
|
||||
{
|
||||
unsigned int actual_result_len;
|
||||
|
||||
switch (ctx->mech) {
|
||||
case CKM_MD2_HMAC:
|
||||
case CKM_MD5_HMAC:
|
||||
case CKM_SHA_1_HMAC:
|
||||
case CKM_SHA224_HMAC:
|
||||
case CKM_SHA256_HMAC:
|
||||
case CKM_SHA384_HMAC:
|
||||
case CKM_SHA512_HMAC:
|
||||
/* HMAC doesn't indicate failure in the return code. Additionally,
|
||||
* unlike CMAC, it doesn't support partial results. This means that we
|
||||
* need to allocate a buffer if max_result_len < ctx->mac_size. */
|
||||
if (max_result_len >= ctx->mac_size) {
|
||||
/* Split this into two calls to avoid an unnecessary stack
|
||||
* allocation and memcpy when possible. */
|
||||
HMAC_Finish(ctx->mac.hmac, result, &actual_result_len, max_result_len);
|
||||
} else {
|
||||
uint8_t tmp_buffer[SFTK_MAX_MAC_LENGTH];
|
||||
|
||||
/* Assumption: buffer is large enough to hold this HMAC's
|
||||
* output. */
|
||||
PR_ASSERT(SFTK_MAX_MAC_LENGTH >= ctx->mac_size);
|
||||
|
||||
HMAC_Finish(ctx->mac.hmac, tmp_buffer, &actual_result_len, SFTK_MAX_MAC_LENGTH);
|
||||
|
||||
if (actual_result_len > max_result_len) {
|
||||
/* This should always be true since:
|
||||
*
|
||||
* (SFTK_MAX_MAC_LENGTH >= ctx->mac_size =
|
||||
* actual_result_len) > max_result_len,
|
||||
*
|
||||
* but guard this truncation just in case. */
|
||||
actual_result_len = max_result_len;
|
||||
}
|
||||
|
||||
PORT_Memcpy(result, tmp_buffer, actual_result_len);
|
||||
}
|
||||
break;
|
||||
case CKM_AES_CMAC:
|
||||
/* CMAC indicates failure in the return code, however this is
|
||||
* unlikely to occur. */
|
||||
if (CMAC_Finish(ctx->mac.cmac, result, &actual_result_len, max_result_len) != SECSuccess) {
|
||||
return CKR_FUNCTION_FAILED;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* This shouldn't happen -- asserting indicates partial support
|
||||
* for a new MAC type. */
|
||||
PR_ASSERT(PR_FALSE);
|
||||
return CKR_FUNCTION_FAILED;
|
||||
}
|
||||
|
||||
if (result_len) {
|
||||
/* When result length is passed, inform the caller of its value. */
|
||||
*result_len = actual_result_len;
|
||||
} else if (max_result_len == ctx->mac_size) {
|
||||
/* Validate that the amount requested was what was actually given; the
|
||||
* caller assumes that what they passed was the output size of the
|
||||
* underlying MAC and that they got all the bytes the asked for. */
|
||||
PR_ASSERT(actual_result_len == max_result_len);
|
||||
}
|
||||
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
void
|
||||
sftk_MAC_Destroy(sftk_MACCtx *ctx, PRBool free_it)
|
||||
{
|
||||
if (ctx == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ctx->mac.raw != NULL && ctx->destroy_func != NULL) {
|
||||
ctx->destroy_func(ctx->mac.raw, PR_TRUE);
|
||||
}
|
||||
|
||||
/* Clean up the struct so we don't double free accidentally. */
|
||||
PORT_Memset(ctx, 0, sizeof(sftk_MACCtx));
|
||||
|
||||
if (free_it == PR_TRUE) {
|
||||
PORT_Free(ctx);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,6 +34,41 @@
|
|||
#include "secerr.h"
|
||||
#include "softoken.h"
|
||||
|
||||
static const int NSS_MP_PBE_ITERATION_COUNT = 10000;
|
||||
|
||||
static int
|
||||
getPBEIterationCount(void)
|
||||
{
|
||||
int c = NSS_MP_PBE_ITERATION_COUNT;
|
||||
|
||||
char *val = getenv("NSS_MIN_MP_PBE_ITERATION_COUNT");
|
||||
if (val) {
|
||||
int minimum = atoi(val);
|
||||
if (c < minimum) {
|
||||
c = minimum;
|
||||
}
|
||||
}
|
||||
|
||||
val = getenv("NSS_MAX_MP_PBE_ITERATION_COUNT");
|
||||
if (val) {
|
||||
int maximum = atoi(val);
|
||||
if (c > maximum) {
|
||||
c = maximum;
|
||||
}
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
PRBool
|
||||
sftk_isLegacyIterationCountAllowed(void)
|
||||
{
|
||||
static const char *legacyCountEnvVar =
|
||||
"NSS_ALLOW_LEGACY_DBM_ITERATION_COUNT";
|
||||
char *iterEnv = getenv(legacyCountEnvVar);
|
||||
return (iterEnv && strcmp("0", iterEnv) != 0);
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
*
|
||||
* Key DB password handling functions
|
||||
|
|
@ -132,7 +167,7 @@ const SEC_ASN1Template sftkdb_EncryptedDataInfoTemplate[] = {
|
|||
* to data in cipherText, if cipherText is freed, cipherValue will be invalid.
|
||||
*/
|
||||
static SECStatus
|
||||
sftkdb_decodeCipherText(SECItem *cipherText, sftkCipherValue *cipherValue)
|
||||
sftkdb_decodeCipherText(const SECItem *cipherText, sftkCipherValue *cipherValue)
|
||||
{
|
||||
PLArenaPool *arena = NULL;
|
||||
SFTKDBEncryptedDataInfo edi;
|
||||
|
|
@ -225,7 +260,8 @@ loser:
|
|||
* with SECITEM_FreeItem by the caller.
|
||||
*/
|
||||
SECStatus
|
||||
sftkdb_DecryptAttribute(SECItem *passKey, SECItem *cipherText, SECItem **plain)
|
||||
sftkdb_DecryptAttribute(SECItem *passKey, SECItem *cipherText,
|
||||
SECItem **plain)
|
||||
{
|
||||
SECStatus rv;
|
||||
sftkCipherValue cipherValue;
|
||||
|
|
@ -235,6 +271,7 @@ sftkdb_DecryptAttribute(SECItem *passKey, SECItem *cipherText, SECItem **plain)
|
|||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
}
|
||||
/* fprintf(stderr, "sftkdb_DecryptAttribute iteration: %d\n", cipherValue.param->iter); */
|
||||
|
||||
*plain = nsspkcs5_CipherData(cipherValue.param, passKey, &cipherValue.value,
|
||||
PR_FALSE, NULL);
|
||||
|
|
@ -261,7 +298,8 @@ loser:
|
|||
*/
|
||||
SECStatus
|
||||
sftkdb_EncryptAttribute(PLArenaPool *arena, SECItem *passKey,
|
||||
SECItem *plainText, SECItem **cipherText)
|
||||
int iterationCount, SECItem *plainText,
|
||||
SECItem **cipherText)
|
||||
{
|
||||
SECStatus rv;
|
||||
sftkCipherValue cipherValue;
|
||||
|
|
@ -275,7 +313,7 @@ sftkdb_EncryptAttribute(PLArenaPool *arena, SECItem *passKey,
|
|||
RNG_GenerateGlobalRandomBytes(saltData, cipherValue.salt.len);
|
||||
|
||||
param = nsspkcs5_NewParam(cipherValue.alg, HASH_AlgSHA1, &cipherValue.salt,
|
||||
1);
|
||||
iterationCount);
|
||||
if (param == NULL) {
|
||||
rv = SECFailure;
|
||||
goto loser;
|
||||
|
|
@ -413,7 +451,8 @@ loser:
|
|||
*/
|
||||
SECStatus
|
||||
sftkdb_SignAttribute(PLArenaPool *arena, SECItem *passKey,
|
||||
CK_OBJECT_HANDLE objectID, CK_ATTRIBUTE_TYPE attrType,
|
||||
int iterationCount, CK_OBJECT_HANDLE objectID,
|
||||
CK_ATTRIBUTE_TYPE attrType,
|
||||
SECItem *plainText, SECItem **signature)
|
||||
{
|
||||
SECStatus rv;
|
||||
|
|
@ -446,7 +485,8 @@ sftkdb_SignAttribute(PLArenaPool *arena, SECItem *passKey,
|
|||
RNG_GenerateGlobalRandomBytes(saltData, prfLength);
|
||||
|
||||
/* initialize our pkcs5 parameter */
|
||||
param = nsspkcs5_NewParam(signValue.alg, HASH_AlgSHA1, &signValue.salt, 1);
|
||||
param = nsspkcs5_NewParam(signValue.alg, HASH_AlgSHA1, &signValue.salt,
|
||||
iterationCount);
|
||||
if (param == NULL) {
|
||||
rv = SECFailure;
|
||||
goto loser;
|
||||
|
|
@ -491,7 +531,7 @@ loser:
|
|||
* and sftkdb_DecryptAttribute calls.
|
||||
*/
|
||||
static void
|
||||
sftkdb_switchKeys(SFTKDBHandle *keydb, SECItem *passKey)
|
||||
sftkdb_switchKeys(SFTKDBHandle *keydb, SECItem *passKey, int iterationCount)
|
||||
{
|
||||
unsigned char *data;
|
||||
int len;
|
||||
|
|
@ -507,6 +547,7 @@ sftkdb_switchKeys(SFTKDBHandle *keydb, SECItem *passKey)
|
|||
len = keydb->passwordKey.len;
|
||||
keydb->passwordKey.data = passKey->data;
|
||||
keydb->passwordKey.len = passKey->len;
|
||||
keydb->defaultIterationCount = iterationCount;
|
||||
passKey->data = data;
|
||||
passKey->len = len;
|
||||
SKIP_AFTER_FORK(PZ_Unlock(keydb->passwordLock));
|
||||
|
|
@ -660,6 +701,90 @@ sftkdb_HasPasswordSet(SFTKDBHandle *keydb)
|
|||
return (crv == CKR_OK) ? SECSuccess : SECFailure;
|
||||
}
|
||||
|
||||
/* pull out the common final part of checking a password */
|
||||
SECStatus
|
||||
sftkdb_finishPasswordCheck(SFTKDBHandle *keydb, SECItem *key,
|
||||
const char *pw, SECItem *value,
|
||||
PRBool *tokenRemoved);
|
||||
|
||||
/*
|
||||
* check to see if we have the NULL password set.
|
||||
* We special case the NULL password so that if you have no password set, you
|
||||
* don't do thousands of hash rounds. This allows us to startup and get
|
||||
* webpages without slowdown in normal mode.
|
||||
*/
|
||||
SECStatus
|
||||
sftkdb_CheckPasswordNull(SFTKDBHandle *keydb, PRBool *tokenRemoved)
|
||||
{
|
||||
/* just like sftkdb_CheckPassowd, we get the salt and value, and
|
||||
* create a dbkey */
|
||||
SECStatus rv;
|
||||
SECItem salt, value;
|
||||
unsigned char saltData[SDB_MAX_META_DATA_LEN];
|
||||
unsigned char valueData[SDB_MAX_META_DATA_LEN];
|
||||
SECItem key;
|
||||
SDB *db;
|
||||
CK_RV crv;
|
||||
sftkCipherValue cipherValue;
|
||||
|
||||
cipherValue.param = NULL;
|
||||
cipherValue.arena = NULL;
|
||||
|
||||
if (keydb == NULL) {
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
db = sftk_getPWSDB(keydb);
|
||||
if (db == NULL) {
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
key.data = NULL;
|
||||
key.len = 0;
|
||||
|
||||
/* get the entry from the database */
|
||||
salt.data = saltData;
|
||||
salt.len = sizeof(saltData);
|
||||
value.data = valueData;
|
||||
value.len = sizeof(valueData);
|
||||
crv = (*db->sdb_GetMetaData)(db, "password", &salt, &value);
|
||||
if (crv != CKR_OK) {
|
||||
rv = SECFailure;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* get our intermediate key based on the entry salt value */
|
||||
rv = sftkdb_passwordToKey(keydb, &salt, "", &key);
|
||||
if (rv != SECSuccess) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* First get the cipher type */
|
||||
rv = sftkdb_decodeCipherText(&value, &cipherValue);
|
||||
if (rv != SECSuccess) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (cipherValue.param->iter != 1) {
|
||||
rv = SECFailure;
|
||||
goto done;
|
||||
}
|
||||
|
||||
rv = sftkdb_finishPasswordCheck(keydb, &key, "", &value, tokenRemoved);
|
||||
|
||||
done:
|
||||
if (key.data) {
|
||||
PORT_ZFree(key.data, key.len);
|
||||
}
|
||||
if (cipherValue.param) {
|
||||
nsspkcs5_DestroyPBEParameter(cipherValue.param);
|
||||
}
|
||||
if (cipherValue.arena) {
|
||||
PORT_FreeArena(cipherValue.arena, PR_FALSE);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
#define SFTK_PW_CHECK_STRING "password-check"
|
||||
#define SFTK_PW_CHECK_LEN 14
|
||||
|
||||
|
|
@ -674,7 +799,6 @@ sftkdb_CheckPassword(SFTKDBHandle *keydb, const char *pw, PRBool *tokenRemoved)
|
|||
unsigned char saltData[SDB_MAX_META_DATA_LEN];
|
||||
unsigned char valueData[SDB_MAX_META_DATA_LEN];
|
||||
SECItem key;
|
||||
SECItem *result = NULL;
|
||||
SDB *db;
|
||||
CK_RV crv;
|
||||
|
||||
|
|
@ -710,8 +834,33 @@ sftkdb_CheckPassword(SFTKDBHandle *keydb, const char *pw, PRBool *tokenRemoved)
|
|||
goto done;
|
||||
}
|
||||
|
||||
rv = sftkdb_finishPasswordCheck(keydb, &key, pw, &value, tokenRemoved);
|
||||
|
||||
done:
|
||||
if (key.data) {
|
||||
PORT_ZFree(key.data, key.len);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* we need to pass iterationCount in case we are updating a new database
|
||||
* and from an old one. */
|
||||
SECStatus
|
||||
sftkdb_finishPasswordCheck(SFTKDBHandle *keydb, SECItem *key, const char *pw,
|
||||
SECItem *value, PRBool *tokenRemoved)
|
||||
{
|
||||
SECItem *result = NULL;
|
||||
SECStatus rv;
|
||||
int iterationCount = getPBEIterationCount();
|
||||
|
||||
if (*pw == 0) {
|
||||
iterationCount = 1;
|
||||
} else if (keydb->usesLegacyStorage && !sftk_isLegacyIterationCountAllowed()) {
|
||||
iterationCount = 1;
|
||||
}
|
||||
|
||||
/* decrypt the entry value */
|
||||
rv = sftkdb_DecryptAttribute(&key, &value, &result);
|
||||
rv = sftkdb_DecryptAttribute(key, value, &result);
|
||||
if (rv != SECSuccess) {
|
||||
goto done;
|
||||
}
|
||||
|
|
@ -752,7 +901,7 @@ sftkdb_CheckPassword(SFTKDBHandle *keydb, const char *pw, PRBool *tokenRemoved)
|
|||
* as well as changing which database is returned from
|
||||
* SFTK_GET_PW_DB (thus effecting both sftkdb_CheckPassword()
|
||||
* and sftkdb_HasPasswordSet()) */
|
||||
keydb->updatePasswordKey = SECITEM_DupItem(&key);
|
||||
keydb->updatePasswordKey = SECITEM_DupItem(key);
|
||||
PZ_Unlock(keydb->passwordLock);
|
||||
if (keydb->updatePasswordKey == NULL) {
|
||||
/* PORT_Error set by SECITEM_DupItem */
|
||||
|
|
@ -787,7 +936,7 @@ sftkdb_CheckPassword(SFTKDBHandle *keydb, const char *pw, PRBool *tokenRemoved)
|
|||
* are good to go */
|
||||
goto done;
|
||||
}
|
||||
sftkdb_CheckPassword(keydb, "", tokenRemoved);
|
||||
sftkdb_CheckPasswordNull(keydb, tokenRemoved);
|
||||
|
||||
/*
|
||||
* Important 'NULL' code here. At this point either we
|
||||
|
|
@ -821,15 +970,15 @@ sftkdb_CheckPassword(SFTKDBHandle *keydb, const char *pw, PRBool *tokenRemoved)
|
|||
PZ_Unlock(keydb->passwordLock);
|
||||
}
|
||||
/* load the keys, so the keydb can parse it's key set */
|
||||
sftkdb_switchKeys(keydb, &key);
|
||||
sftkdb_switchKeys(keydb, key, iterationCount);
|
||||
|
||||
/* we need to update, do it now */
|
||||
if (((keydb->db->sdb_flags & SDB_RDONLY) == 0) && keydb->update) {
|
||||
/* update the peer certdb if it exists */
|
||||
if (keydb->peerDB) {
|
||||
sftkdb_Update(keydb->peerDB, &key);
|
||||
sftkdb_Update(keydb->peerDB, key);
|
||||
}
|
||||
sftkdb_Update(keydb, &key);
|
||||
sftkdb_Update(keydb, key);
|
||||
}
|
||||
} else {
|
||||
rv = SECFailure;
|
||||
|
|
@ -837,9 +986,6 @@ sftkdb_CheckPassword(SFTKDBHandle *keydb, const char *pw, PRBool *tokenRemoved)
|
|||
}
|
||||
|
||||
done:
|
||||
if (key.data) {
|
||||
PORT_ZFree(key.data, key.len);
|
||||
}
|
||||
if (result) {
|
||||
SECITEM_FreeItem(result, PR_TRUE);
|
||||
}
|
||||
|
|
@ -857,7 +1003,7 @@ sftkdb_PWCached(SFTKDBHandle *keydb)
|
|||
|
||||
static CK_RV
|
||||
sftk_updateMacs(PLArenaPool *arena, SFTKDBHandle *handle,
|
||||
CK_OBJECT_HANDLE id, SECItem *newKey)
|
||||
CK_OBJECT_HANDLE id, SECItem *newKey, int iterationCount)
|
||||
{
|
||||
SFTKDBHandle *keyHandle = handle;
|
||||
SDB *keyTarget = NULL;
|
||||
|
|
@ -924,7 +1070,8 @@ sftk_updateMacs(PLArenaPool *arena, SFTKDBHandle *handle,
|
|||
SECItem plainText;
|
||||
plainText.data = authAttr.pValue;
|
||||
plainText.len = authAttr.ulValueLen;
|
||||
if (sftkdb_SignAttribute(arena, newKey, id, authAttr.type, &plainText,
|
||||
if (sftkdb_SignAttribute(arena, newKey, iterationCount, id,
|
||||
authAttr.type, &plainText,
|
||||
&signText) != SECSuccess) {
|
||||
return CKR_GENERAL_ERROR;
|
||||
}
|
||||
|
|
@ -939,7 +1086,7 @@ sftk_updateMacs(PLArenaPool *arena, SFTKDBHandle *handle,
|
|||
|
||||
static CK_RV
|
||||
sftk_updateEncrypted(PLArenaPool *arena, SFTKDBHandle *keydb,
|
||||
CK_OBJECT_HANDLE id, SECItem *newKey)
|
||||
CK_OBJECT_HANDLE id, SECItem *newKey, int iterationCount)
|
||||
{
|
||||
CK_ATTRIBUTE_TYPE privAttrTypes[] = {
|
||||
CKA_VALUE,
|
||||
|
|
@ -980,7 +1127,8 @@ sftk_updateEncrypted(PLArenaPool *arena, SFTKDBHandle *keydb,
|
|||
SECItem *result;
|
||||
plainText.data = privAttr.pValue;
|
||||
plainText.len = privAttr.ulValueLen;
|
||||
if (sftkdb_EncryptAttribute(arena, newKey, &plainText, &result) != SECSuccess) {
|
||||
if (sftkdb_EncryptAttribute(arena, newKey, iterationCount,
|
||||
&plainText, &result) != SECSuccess) {
|
||||
return CKR_GENERAL_ERROR;
|
||||
}
|
||||
privAttr.pValue = result->data;
|
||||
|
|
@ -991,6 +1139,7 @@ sftk_updateEncrypted(PLArenaPool *arena, SFTKDBHandle *keydb,
|
|||
// Write the newly encrypted attributes out directly.
|
||||
CK_OBJECT_HANDLE newId = id & SFTK_OBJ_ID_MASK;
|
||||
keydb->newKey = newKey;
|
||||
keydb->newDefaultIterationCount = iterationCount;
|
||||
crv = (*keydb->db->sdb_SetAttributeValue)(keydb->db, newId, &privAttr, 1);
|
||||
keydb->newKey = NULL;
|
||||
if (crv != CKR_OK) {
|
||||
|
|
@ -1002,8 +1151,8 @@ sftk_updateEncrypted(PLArenaPool *arena, SFTKDBHandle *keydb,
|
|||
}
|
||||
|
||||
static CK_RV
|
||||
sftk_convertAttributes(SFTKDBHandle *handle,
|
||||
CK_OBJECT_HANDLE id, SECItem *newKey)
|
||||
sftk_convertAttributes(SFTKDBHandle *handle, CK_OBJECT_HANDLE id,
|
||||
SECItem *newKey, int iterationCount)
|
||||
{
|
||||
CK_RV crv = CKR_OK;
|
||||
PLArenaPool *arena = NULL;
|
||||
|
|
@ -1017,13 +1166,14 @@ sftk_convertAttributes(SFTKDBHandle *handle,
|
|||
/*
|
||||
* first handle the MACS
|
||||
*/
|
||||
crv = sftk_updateMacs(arena, handle, id, newKey);
|
||||
crv = sftk_updateMacs(arena, handle, id, newKey, iterationCount);
|
||||
if (crv != CKR_OK) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
if (handle->type == SFTK_KEYDB_TYPE) {
|
||||
crv = sftk_updateEncrypted(arena, handle, id, newKey);
|
||||
crv = sftk_updateEncrypted(arena, handle, id, newKey,
|
||||
iterationCount);
|
||||
if (crv != CKR_OK) {
|
||||
goto loser;
|
||||
}
|
||||
|
|
@ -1045,7 +1195,7 @@ loser:
|
|||
*/
|
||||
CK_RV
|
||||
sftkdb_convertObjects(SFTKDBHandle *handle, CK_ATTRIBUTE *template,
|
||||
CK_ULONG count, SECItem *newKey)
|
||||
CK_ULONG count, SECItem *newKey, int iterationCount)
|
||||
{
|
||||
SDBFind *find = NULL;
|
||||
CK_ULONG idCount = SFTK_MAX_IDS;
|
||||
|
|
@ -1061,7 +1211,8 @@ sftkdb_convertObjects(SFTKDBHandle *handle, CK_ATTRIBUTE *template,
|
|||
while ((crv == CKR_OK) && (idCount == SFTK_MAX_IDS)) {
|
||||
crv = sftkdb_FindObjects(handle, find, ids, SFTK_MAX_IDS, &idCount);
|
||||
for (i = 0; (crv == CKR_OK) && (i < idCount); i++) {
|
||||
crv = sftk_convertAttributes(handle, ids[i], newKey);
|
||||
crv = sftk_convertAttributes(handle, ids[i], newKey,
|
||||
iterationCount);
|
||||
}
|
||||
}
|
||||
crv2 = sftkdb_FindObjectsFinal(handle, find);
|
||||
|
|
@ -1086,6 +1237,7 @@ sftkdb_ChangePassword(SFTKDBHandle *keydb,
|
|||
SFTKDBHandle *certdb;
|
||||
unsigned char saltData[SDB_MAX_META_DATA_LEN];
|
||||
unsigned char valueData[SDB_MAX_META_DATA_LEN];
|
||||
int iterationCount = getPBEIterationCount();
|
||||
CK_RV crv;
|
||||
SDB *db;
|
||||
|
||||
|
|
@ -1121,6 +1273,12 @@ sftkdb_ChangePassword(SFTKDBHandle *keydb,
|
|||
RNG_GenerateGlobalRandomBytes(salt.data, salt.len);
|
||||
}
|
||||
|
||||
if (newPin && *newPin == 0) {
|
||||
iterationCount = 1;
|
||||
} else if (keydb->usesLegacyStorage && !sftk_isLegacyIterationCountAllowed()) {
|
||||
iterationCount = 1;
|
||||
}
|
||||
|
||||
rv = sftkdb_passwordToKey(keydb, &salt, newPin, &newKey);
|
||||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
|
|
@ -1129,7 +1287,7 @@ sftkdb_ChangePassword(SFTKDBHandle *keydb,
|
|||
/*
|
||||
* convert encrypted entries here.
|
||||
*/
|
||||
crv = sftkdb_convertObjects(keydb, NULL, 0, &newKey);
|
||||
crv = sftkdb_convertObjects(keydb, NULL, 0, &newKey, iterationCount);
|
||||
if (crv != CKR_OK) {
|
||||
rv = SECFailure;
|
||||
goto loser;
|
||||
|
|
@ -1141,13 +1299,15 @@ sftkdb_ChangePassword(SFTKDBHandle *keydb,
|
|||
CK_OBJECT_CLASS myClass = CKO_NETSCAPE_TRUST;
|
||||
|
||||
objectType.pValue = &myClass;
|
||||
crv = sftkdb_convertObjects(certdb, &objectType, 1, &newKey);
|
||||
crv = sftkdb_convertObjects(certdb, &objectType, 1, &newKey,
|
||||
iterationCount);
|
||||
if (crv != CKR_OK) {
|
||||
rv = SECFailure;
|
||||
goto loser;
|
||||
}
|
||||
myClass = CKO_PUBLIC_KEY;
|
||||
crv = sftkdb_convertObjects(certdb, &objectType, 1, &newKey);
|
||||
crv = sftkdb_convertObjects(certdb, &objectType, 1, &newKey,
|
||||
iterationCount);
|
||||
if (crv != CKR_OK) {
|
||||
rv = SECFailure;
|
||||
goto loser;
|
||||
|
|
@ -1157,7 +1317,8 @@ sftkdb_ChangePassword(SFTKDBHandle *keydb,
|
|||
plainText.data = (unsigned char *)SFTK_PW_CHECK_STRING;
|
||||
plainText.len = SFTK_PW_CHECK_LEN;
|
||||
|
||||
rv = sftkdb_EncryptAttribute(NULL, &newKey, &plainText, &result);
|
||||
rv = sftkdb_EncryptAttribute(NULL, &newKey, iterationCount,
|
||||
&plainText, &result);
|
||||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
}
|
||||
|
|
@ -1176,7 +1337,7 @@ sftkdb_ChangePassword(SFTKDBHandle *keydb,
|
|||
|
||||
keydb->newKey = NULL;
|
||||
|
||||
sftkdb_switchKeys(keydb, &newKey);
|
||||
sftkdb_switchKeys(keydb, &newKey, iterationCount);
|
||||
|
||||
loser:
|
||||
if (newKey.data) {
|
||||
|
|
@ -1201,7 +1362,7 @@ sftkdb_ClearPassword(SFTKDBHandle *keydb)
|
|||
SECItem oldKey;
|
||||
oldKey.data = NULL;
|
||||
oldKey.len = 0;
|
||||
sftkdb_switchKeys(keydb, &oldKey);
|
||||
sftkdb_switchKeys(keydb, &oldKey, 1);
|
||||
if (oldKey.data) {
|
||||
PORT_ZFree(oldKey.data, oldKey.len);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,10 +17,10 @@
|
|||
* The format of the version string should be
|
||||
* "<major version>.<minor version>[.<patch level>[.<build number>]][ <ECC>][ <Beta>]"
|
||||
*/
|
||||
#define SOFTOKEN_VERSION "3.44.3" SOFTOKEN_ECC_STRING
|
||||
#define SOFTOKEN_VERSION "3.48" SOFTOKEN_ECC_STRING
|
||||
#define SOFTOKEN_VMAJOR 3
|
||||
#define SOFTOKEN_VMINOR 44
|
||||
#define SOFTOKEN_VPATCH 3
|
||||
#define SOFTOKEN_VMINOR 48
|
||||
#define SOFTOKEN_VPATCH 0
|
||||
#define SOFTOKEN_VBUILD 0
|
||||
#define SOFTOKEN_BETA PR_FALSE
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue