mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-21 15:57:31 +09:00
nss: update to 3.44.1, with vc2013 fix and gyp fix
This commit is contained in:
parent
a2ef5fcde7
commit
d4b834111b
553 changed files with 1515569 additions and 1130 deletions
|
|
@ -12,6 +12,7 @@
|
|||
#include "lowkeyi.h"
|
||||
#include "secoid.h"
|
||||
#include "secerr.h"
|
||||
#include "pkcs11i.h"
|
||||
|
||||
/*
|
||||
* different platforms have different ways of calling and initial entry point
|
||||
|
|
@ -626,6 +627,10 @@ sftk_startup_tests(void)
|
|||
* the token */
|
||||
return;
|
||||
}
|
||||
rv = sftk_fips_IKE_PowerUpSelfTests();
|
||||
if (rv != SECSuccess) {
|
||||
return;
|
||||
}
|
||||
sftk_self_tests_success = PR_TRUE;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -950,9 +950,9 @@ lg_FindECPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type,
|
|||
case CKA_UNWRAP:
|
||||
return LG_CLONE_ATTR(attribute, type, lg_StaticFalseAttr);
|
||||
case CKA_VALUE:
|
||||
return lg_CopyPrivAttrSigned(attribute, type,
|
||||
key->u.ec.privateValue.data,
|
||||
key->u.ec.privateValue.len, sdbpw);
|
||||
return lg_CopyPrivAttribute(attribute, type,
|
||||
key->u.ec.privateValue.data,
|
||||
key->u.ec.privateValue.len, sdbpw);
|
||||
case CKA_EC_PARAMS:
|
||||
return lg_CopyAttributeSigned(attribute, type,
|
||||
key->u.ec.ecParams.DEREncoding.data,
|
||||
|
|
|
|||
|
|
@ -261,6 +261,7 @@ NSSLOWKEYPublicKey *
|
|||
nsslowkey_ConvertToPublicKey(NSSLOWKEYPrivateKey *privk)
|
||||
{
|
||||
NSSLOWKEYPublicKey *pubk;
|
||||
SECItem publicValue;
|
||||
PLArenaPool *arena;
|
||||
|
||||
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
|
||||
|
|
@ -301,6 +302,19 @@ nsslowkey_ConvertToPublicKey(NSSLOWKEYPrivateKey *privk)
|
|||
|
||||
pubk->arena = arena;
|
||||
pubk->keyType = privk->keyType;
|
||||
/* if the public key value doesn't exist, calculate it */
|
||||
if (privk->u.dsa.publicValue.len == 0) {
|
||||
rv = DH_Derive(&privk->u.dsa.params.base, &privk->u.dsa.params.prime,
|
||||
&privk->u.dsa.privateValue, &publicValue, 0);
|
||||
if (rv != SECSuccess) {
|
||||
break;
|
||||
}
|
||||
rv = SECITEM_CopyItem(privk->arena, &privk->u.dsa.publicValue, &publicValue);
|
||||
SECITEM_FreeItem(&publicValue, PR_FALSE);
|
||||
if (rv != SECSuccess) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
rv = SECITEM_CopyItem(arena, &pubk->u.dsa.publicValue,
|
||||
&privk->u.dsa.publicValue);
|
||||
if (rv != SECSuccess)
|
||||
|
|
@ -327,6 +341,19 @@ nsslowkey_ConvertToPublicKey(NSSLOWKEYPrivateKey *privk)
|
|||
|
||||
pubk->arena = arena;
|
||||
pubk->keyType = privk->keyType;
|
||||
/* if the public key value doesn't exist, calculate it */
|
||||
if (privk->u.dh.publicValue.len == 0) {
|
||||
rv = DH_Derive(&privk->u.dh.base, &privk->u.dh.prime,
|
||||
&privk->u.dh.privateValue, &publicValue, 0);
|
||||
if (rv != SECSuccess) {
|
||||
break;
|
||||
}
|
||||
rv = SECITEM_CopyItem(privk->arena, &privk->u.dh.publicValue, &publicValue);
|
||||
SECITEM_FreeItem(&publicValue, PR_FALSE);
|
||||
if (rv != SECSuccess) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
rv = SECITEM_CopyItem(arena, &pubk->u.dh.publicValue,
|
||||
&privk->u.dh.publicValue);
|
||||
if (rv != SECSuccess)
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ CSRCS = \
|
|||
sdb.c \
|
||||
sftkdb.c \
|
||||
sftkhmac.c \
|
||||
sftkike.c \
|
||||
sftkpars.c \
|
||||
sftkpwd.c \
|
||||
softkver.c \
|
||||
|
|
|
|||
|
|
@ -328,6 +328,8 @@ static const struct mechanismList mechanisms[] = {
|
|||
{ CKM_AES_CTS, { 16, 32, CKF_EN_DE }, PR_TRUE },
|
||||
{ CKM_AES_CTR, { 16, 32, CKF_EN_DE }, PR_TRUE },
|
||||
{ CKM_AES_GCM, { 16, 32, CKF_EN_DE }, PR_TRUE },
|
||||
{ CKM_AES_XCBC_MAC_96, { 16, 16, CKF_SN_VR }, PR_TRUE },
|
||||
{ CKM_AES_XCBC_MAC, { 16, 16, CKF_SN_VR }, PR_TRUE },
|
||||
/* ------------------------- Camellia Operations --------------------- */
|
||||
{ CKM_CAMELLIA_KEY_GEN, { 16, 32, CKF_GENERATE }, PR_TRUE },
|
||||
{ CKM_CAMELLIA_ECB, { 16, 32, CKF_EN_DE_WR_UN }, PR_TRUE },
|
||||
|
|
@ -346,6 +348,7 @@ static const struct mechanismList mechanisms[] = {
|
|||
/* ------------------------- ChaCha20 Operations ---------------------- */
|
||||
{ CKM_NSS_CHACHA20_KEY_GEN, { 32, 32, CKF_GENERATE }, PR_TRUE },
|
||||
{ CKM_NSS_CHACHA20_POLY1305, { 32, 32, CKF_EN_DE }, PR_TRUE },
|
||||
{ CKM_NSS_CHACHA20_CTR, { 32, 32, CKF_EN_DE }, PR_TRUE },
|
||||
#endif /* NSS_DISABLE_CHACHAPOLY */
|
||||
/* ------------------------- Hashing Operations ----------------------- */
|
||||
{ CKM_MD2, { 0, 0, CKF_DIGEST }, PR_FALSE },
|
||||
|
|
@ -509,7 +512,11 @@ static const struct mechanismList mechanisms[] = {
|
|||
{ CKM_NSS_JPAKE_FINAL_SHA512, { 0, 0, CKF_DERIVE }, PR_TRUE },
|
||||
/* -------------------- Constant Time TLS MACs ----------------------- */
|
||||
{ CKM_NSS_HMAC_CONSTANT_TIME, { 0, 0, CKF_DIGEST }, PR_TRUE },
|
||||
{ CKM_NSS_SSL3_MAC_CONSTANT_TIME, { 0, 0, CKF_DIGEST }, PR_TRUE }
|
||||
{ CKM_NSS_SSL3_MAC_CONSTANT_TIME, { 0, 0, CKF_DIGEST }, PR_TRUE },
|
||||
/* --------------------IPSEC ----------------------- */
|
||||
{ CKM_NSS_IKE_PRF_PLUS_DERIVE, { 8, 255 * 64, CKF_DERIVE }, PR_TRUE },
|
||||
{ CKM_NSS_IKE_PRF_DERIVE, { 8, 64, CKF_DERIVE }, PR_TRUE },
|
||||
{ CKM_NSS_IKE1_PRF_DERIVE, { 8, 64, CKF_DERIVE }, PR_TRUE }
|
||||
};
|
||||
static const CK_ULONG mechanismCount = sizeof(mechanisms) / sizeof(mechanisms[0]);
|
||||
|
||||
|
|
@ -2199,6 +2206,119 @@ sftk_GetPrivKey(SFTKObject *object, CK_KEY_TYPE key_type, CK_RV *crvp)
|
|||
return priv;
|
||||
}
|
||||
|
||||
/* populate a public key object from a lowpublic keys structure */
|
||||
CK_RV
|
||||
sftk_PutPubKey(SFTKObject *publicKey, SFTKObject *privateKey, CK_KEY_TYPE keyType, NSSLOWKEYPublicKey *pubKey)
|
||||
{
|
||||
CK_OBJECT_CLASS classType = CKO_PUBLIC_KEY;
|
||||
CK_BBOOL cktrue = CK_TRUE;
|
||||
CK_RV crv = CKR_OK;
|
||||
sftk_DeleteAttributeType(publicKey, CKA_CLASS);
|
||||
sftk_DeleteAttributeType(publicKey, CKA_KEY_TYPE);
|
||||
sftk_DeleteAttributeType(publicKey, CKA_VALUE);
|
||||
|
||||
switch (keyType) {
|
||||
case CKK_RSA:
|
||||
sftk_DeleteAttributeType(publicKey, CKA_MODULUS);
|
||||
sftk_DeleteAttributeType(publicKey, CKA_PUBLIC_EXPONENT);
|
||||
/* format the keys */
|
||||
/* fill in the RSA dependent paramenters in the public key */
|
||||
crv = sftk_AddAttributeType(publicKey, CKA_MODULUS,
|
||||
sftk_item_expand(&pubKey->u.rsa.modulus));
|
||||
if (crv != CKR_OK) {
|
||||
break;
|
||||
}
|
||||
crv = sftk_AddAttributeType(publicKey, CKA_PUBLIC_EXPONENT,
|
||||
sftk_item_expand(&pubKey->u.rsa.publicExponent));
|
||||
break;
|
||||
case CKK_DSA:
|
||||
sftk_DeleteAttributeType(publicKey, CKA_PRIME);
|
||||
sftk_DeleteAttributeType(publicKey, CKA_SUBPRIME);
|
||||
sftk_DeleteAttributeType(publicKey, CKA_BASE);
|
||||
crv = sftk_AddAttributeType(publicKey, CKA_PRIME,
|
||||
sftk_item_expand(&pubKey->u.dsa.params.prime));
|
||||
if (crv != CKR_OK) {
|
||||
break;
|
||||
}
|
||||
crv = sftk_AddAttributeType(publicKey, CKA_SUBPRIME,
|
||||
sftk_item_expand(&pubKey->u.dsa.params.subPrime));
|
||||
if (crv != CKR_OK) {
|
||||
break;
|
||||
}
|
||||
crv = sftk_AddAttributeType(publicKey, CKA_BASE,
|
||||
sftk_item_expand(&pubKey->u.dsa.params.base));
|
||||
if (crv != CKR_OK) {
|
||||
break;
|
||||
}
|
||||
crv = sftk_AddAttributeType(publicKey, CKA_VALUE,
|
||||
sftk_item_expand(&pubKey->u.dsa.publicValue));
|
||||
break;
|
||||
case CKK_DH:
|
||||
sftk_DeleteAttributeType(publicKey, CKA_PRIME);
|
||||
sftk_DeleteAttributeType(publicKey, CKA_BASE);
|
||||
crv = sftk_AddAttributeType(publicKey, CKA_PRIME,
|
||||
sftk_item_expand(&pubKey->u.dh.prime));
|
||||
if (crv != CKR_OK) {
|
||||
break;
|
||||
}
|
||||
crv = sftk_AddAttributeType(publicKey, CKA_BASE,
|
||||
sftk_item_expand(&pubKey->u.dh.base));
|
||||
if (crv != CKR_OK) {
|
||||
break;
|
||||
}
|
||||
crv = sftk_AddAttributeType(publicKey, CKA_VALUE,
|
||||
sftk_item_expand(&pubKey->u.dh.publicValue));
|
||||
break;
|
||||
case CKK_EC:
|
||||
sftk_DeleteAttributeType(publicKey, CKA_EC_PARAMS);
|
||||
sftk_DeleteAttributeType(publicKey, CKA_EC_POINT);
|
||||
crv = sftk_AddAttributeType(publicKey, CKA_EC_PARAMS,
|
||||
sftk_item_expand(&pubKey->u.ec.ecParams.DEREncoding));
|
||||
if (crv != CKR_OK) {
|
||||
break;
|
||||
}
|
||||
crv = sftk_AddAttributeType(publicKey, CKA_EC_POINT,
|
||||
sftk_item_expand(&pubKey->u.ec.publicValue));
|
||||
break;
|
||||
default:
|
||||
return CKR_KEY_TYPE_INCONSISTENT;
|
||||
}
|
||||
crv = sftk_AddAttributeType(publicKey, CKA_CLASS, &classType,
|
||||
sizeof(CK_OBJECT_CLASS));
|
||||
if (crv != CKR_OK)
|
||||
return crv;
|
||||
crv = sftk_AddAttributeType(publicKey, CKA_KEY_TYPE, &keyType,
|
||||
sizeof(CK_KEY_TYPE));
|
||||
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));
|
||||
if (crv != CKR_OK) {
|
||||
return crv;
|
||||
}
|
||||
}
|
||||
if (sftk_isTrue(privateKey, CKA_SIGN)) {
|
||||
crv = sftk_forceAttribute(publicKey, CKA_VERIFY, &cktrue, sizeof(CK_BBOOL));
|
||||
if (crv != CKR_OK) {
|
||||
return crv;
|
||||
}
|
||||
}
|
||||
if (sftk_isTrue(privateKey, CKA_SIGN_RECOVER)) {
|
||||
crv = sftk_forceAttribute(publicKey, CKA_VERIFY_RECOVER, &cktrue, sizeof(CK_BBOOL));
|
||||
if (crv != CKR_OK) {
|
||||
return crv;
|
||||
}
|
||||
}
|
||||
if (sftk_isTrue(privateKey, CKA_DERIVE)) {
|
||||
crv = sftk_forceAttribute(publicKey, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL));
|
||||
if (crv != CKR_OK) {
|
||||
return crv;
|
||||
}
|
||||
}
|
||||
return crv;
|
||||
}
|
||||
|
||||
/*
|
||||
**************************** Symetric Key utils ************************
|
||||
*/
|
||||
|
|
@ -3156,7 +3276,7 @@ nsc_CommonFinalize(CK_VOID_PTR pReserved, PRBool isFIPS)
|
|||
* this call doesn't force freebl to be reloaded. */
|
||||
BL_SetForkState(PR_FALSE);
|
||||
|
||||
#ifndef NSS_TEST_BUILD
|
||||
#ifndef NSS_STATIC_SOFTOKEN
|
||||
/* unload freeBL shared library from memory. This may only decrement the
|
||||
* OS refcount if it's been loaded multiple times, eg. by libssl */
|
||||
BL_Unload();
|
||||
|
|
|
|||
|
|
@ -96,42 +96,10 @@ sftk_Space(void *data, PRBool freeit)
|
|||
|
||||
/*
|
||||
* map all the SEC_ERROR_xxx error codes that may be returned by freebl
|
||||
* functions to CKR_xxx. return CKR_DEVICE_ERROR by default for backward
|
||||
* compatibility.
|
||||
* functions to CKR_xxx. Most of the mapping is done in
|
||||
* sftk_mapCryptError (now in pkcs11u.c). The next two functions adjust
|
||||
* that mapping based for different contexts (Decrypt or Verify).
|
||||
*/
|
||||
static CK_RV
|
||||
sftk_MapCryptError(int error)
|
||||
{
|
||||
switch (error) {
|
||||
case SEC_ERROR_INVALID_ARGS:
|
||||
case SEC_ERROR_BAD_DATA: /* MP_RANGE gets mapped to this */
|
||||
return CKR_ARGUMENTS_BAD;
|
||||
case SEC_ERROR_INPUT_LEN:
|
||||
return CKR_DATA_LEN_RANGE;
|
||||
case SEC_ERROR_OUTPUT_LEN:
|
||||
return CKR_BUFFER_TOO_SMALL;
|
||||
case SEC_ERROR_LIBRARY_FAILURE:
|
||||
return CKR_GENERAL_ERROR;
|
||||
case SEC_ERROR_NO_MEMORY:
|
||||
return CKR_HOST_MEMORY;
|
||||
case SEC_ERROR_BAD_SIGNATURE:
|
||||
return CKR_SIGNATURE_INVALID;
|
||||
case SEC_ERROR_INVALID_KEY:
|
||||
return CKR_KEY_SIZE_RANGE;
|
||||
case SEC_ERROR_BAD_KEY: /* an EC public key that fails validation */
|
||||
return CKR_KEY_SIZE_RANGE; /* the closest error code */
|
||||
case SEC_ERROR_UNSUPPORTED_EC_POINT_FORM:
|
||||
return CKR_TEMPLATE_INCONSISTENT;
|
||||
case SEC_ERROR_UNSUPPORTED_KEYALG:
|
||||
return CKR_MECHANISM_INVALID;
|
||||
case SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE:
|
||||
return CKR_DOMAIN_PARAMS_INVALID;
|
||||
/* key pair generation failed after max number of attempts */
|
||||
case SEC_ERROR_NEED_RANDOM:
|
||||
return CKR_FUNCTION_FAILED;
|
||||
}
|
||||
return CKR_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
/* used by Decrypt and UnwrapKey (indirectly) */
|
||||
static CK_RV
|
||||
|
|
@ -760,6 +728,32 @@ sftk_ChaCha20Poly1305_Decrypt(const SFTKChaCha20Poly1305Info *ctx,
|
|||
sizeof(ctx->nonce), ad, ctx->adLen);
|
||||
}
|
||||
|
||||
static SECStatus
|
||||
sftk_ChaCha20Ctr(const SFTKChaCha20CtrInfo *ctx,
|
||||
unsigned char *output, unsigned int *outputLen,
|
||||
unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
if (maxOutputLen < inputLen) {
|
||||
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
|
||||
return SECFailure;
|
||||
}
|
||||
ChaCha20_Xor(output, input, inputLen, ctx->key,
|
||||
ctx->nonce, ctx->counter);
|
||||
*outputLen = inputLen;
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
static void
|
||||
sftk_ChaCha20Ctr_DestroyContext(SFTKChaCha20CtrInfo *ctx,
|
||||
PRBool freeit)
|
||||
{
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
if (freeit) {
|
||||
PORT_Free(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
/** NSC_CryptInit initializes an encryption/Decryption operation.
|
||||
*
|
||||
* Always called by NSC_EncryptInit, NSC_DecryptInit, NSC_WrapKey,NSC_UnwrapKey.
|
||||
|
|
@ -1180,6 +1174,48 @@ sftk_CryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
|
|||
context->destroy = (SFTKDestroy)sftk_ChaCha20Poly1305_DestroyContext;
|
||||
break;
|
||||
|
||||
case CKM_NSS_CHACHA20_CTR:
|
||||
if (key_type != CKK_NSS_CHACHA20) {
|
||||
crv = CKR_KEY_TYPE_INCONSISTENT;
|
||||
break;
|
||||
}
|
||||
if (pMechanism->pParameter == NULL || pMechanism->ulParameterLen != 16) {
|
||||
crv = CKR_MECHANISM_PARAM_INVALID;
|
||||
break;
|
||||
}
|
||||
|
||||
att = sftk_FindAttribute(key, CKA_VALUE);
|
||||
if (att == NULL) {
|
||||
crv = CKR_KEY_HANDLE_INVALID;
|
||||
break;
|
||||
}
|
||||
SFTKChaCha20CtrInfo *ctx = PORT_ZNew(SFTKChaCha20CtrInfo);
|
||||
if (!ctx) {
|
||||
sftk_FreeAttribute(att);
|
||||
crv = CKR_HOST_MEMORY;
|
||||
break;
|
||||
}
|
||||
if (att->attrib.ulValueLen != sizeof(ctx->key)) {
|
||||
sftk_FreeAttribute(att);
|
||||
PORT_Free(ctx);
|
||||
crv = CKR_KEY_HANDLE_INVALID;
|
||||
break;
|
||||
}
|
||||
memcpy(ctx->key, att->attrib.pValue, att->attrib.ulValueLen);
|
||||
sftk_FreeAttribute(att);
|
||||
|
||||
/* The counter is little endian. */
|
||||
PRUint8 *param = pMechanism->pParameter;
|
||||
int i = 0;
|
||||
for (; i < 4; ++i) {
|
||||
ctx->counter |= param[i] << (i * 8);
|
||||
}
|
||||
memcpy(ctx->nonce, param + 4, 12);
|
||||
context->cipherInfo = ctx;
|
||||
context->update = (SFTKCipher)sftk_ChaCha20Ctr;
|
||||
context->destroy = (SFTKDestroy)sftk_ChaCha20Ctr_DestroyContext;
|
||||
break;
|
||||
|
||||
case CKM_NSS_AES_KEY_WRAP_PAD:
|
||||
context->doPad = PR_TRUE;
|
||||
/* fall thru */
|
||||
|
|
@ -2080,9 +2116,12 @@ sftk_InitCBCMac(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
|
|||
CK_RC5_MAC_GENERAL_PARAMS *rc5_mac;
|
||||
#endif
|
||||
unsigned char ivBlock[SFTK_MAX_BLOCK_SIZE];
|
||||
unsigned char k2[SFTK_MAX_BLOCK_SIZE];
|
||||
unsigned char k3[SFTK_MAX_BLOCK_SIZE];
|
||||
SFTKSessionContext *context;
|
||||
CK_RV crv;
|
||||
unsigned int blockSize;
|
||||
PRBool isXCBC = PR_FALSE;
|
||||
|
||||
switch (pMechanism->mechanism) {
|
||||
case CKM_RC2_MAC_GENERAL:
|
||||
|
|
@ -2186,6 +2225,26 @@ sftk_InitCBCMac(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
|
|||
cbc_mechanism.pParameter = &ivBlock;
|
||||
cbc_mechanism.ulParameterLen = blockSize;
|
||||
break;
|
||||
case CKM_AES_XCBC_MAC_96:
|
||||
case CKM_AES_XCBC_MAC:
|
||||
/* The only difference between CKM_AES_XCBC_MAC
|
||||
* and CKM_AES_XCBC_MAC_96 is the size of the returned mac. */
|
||||
mac_bytes = pMechanism->mechanism == CKM_AES_XCBC_MAC_96 ? 12 : 16;
|
||||
blockSize = 16;
|
||||
PORT_Memset(ivBlock, 0, blockSize);
|
||||
cbc_mechanism.mechanism = CKM_AES_CBC;
|
||||
cbc_mechanism.pParameter = &ivBlock;
|
||||
cbc_mechanism.ulParameterLen = blockSize;
|
||||
/* is XCBC requires extra processing at the end of the operation */
|
||||
isXCBC = PR_TRUE;
|
||||
/* The input key is used to generate k1, k2, and k3. k2 and k3
|
||||
* are used at the end in the pad step. k1 replaces the input
|
||||
* key in the aes cbc mac */
|
||||
crv = sftk_aes_xcbc_new_keys(hSession, hKey, &hKey, k2, k3);
|
||||
if (crv != CKR_OK) {
|
||||
return crv;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return CKR_FUNCTION_NOT_SUPPORTED;
|
||||
}
|
||||
|
|
@ -2195,24 +2254,43 @@ sftk_InitCBCMac(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
|
|||
if (mac_bytes == SFTK_INVALID_MAC_SIZE)
|
||||
mac_bytes = blockSize >> 1;
|
||||
else {
|
||||
if (mac_bytes > blockSize)
|
||||
return CKR_MECHANISM_PARAM_INVALID;
|
||||
if (mac_bytes > blockSize) {
|
||||
crv = CKR_MECHANISM_PARAM_INVALID;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
crv = sftk_CryptInit(hSession, &cbc_mechanism, hKey,
|
||||
CKA_ENCRYPT, /* CBC mech is able to ENCRYPT, not SIGN/VERIFY */
|
||||
keyUsage, contextType, PR_TRUE);
|
||||
if (crv != CKR_OK)
|
||||
return crv;
|
||||
goto fail;
|
||||
crv = sftk_GetContext(hSession, &context, contextType, PR_TRUE, NULL);
|
||||
|
||||
/* this shouldn't happen! */
|
||||
PORT_Assert(crv == CKR_OK);
|
||||
if (crv != CKR_OK)
|
||||
return crv;
|
||||
goto fail;
|
||||
context->blockSize = blockSize;
|
||||
context->macSize = mac_bytes;
|
||||
context->isXCBC = isXCBC;
|
||||
if (isXCBC) {
|
||||
/* save the xcbc specific parameters */
|
||||
PORT_Memcpy(context->k2, k2, blockSize);
|
||||
PORT_Memcpy(context->k3, k3, blockSize);
|
||||
PORT_Memset(k2, 0, blockSize);
|
||||
PORT_Memset(k3, 0, blockSize);
|
||||
/* get rid of the temp key now that the context has been created */
|
||||
NSC_DestroyObject(hSession, hKey);
|
||||
}
|
||||
return CKR_OK;
|
||||
fail:
|
||||
if (isXCBC) {
|
||||
PORT_Memset(k2, 0, blockSize);
|
||||
PORT_Memset(k3, 0, blockSize);
|
||||
NSC_DestroyObject(hSession, hKey); /* get rid of our temp key */
|
||||
}
|
||||
return crv;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -2828,6 +2906,13 @@ sftk_MACFinal(SFTKSessionContext *ctx)
|
|||
{
|
||||
unsigned int padLen = ctx->padDataLength;
|
||||
/* pad and proceed the residual */
|
||||
if (ctx->isXCBC) {
|
||||
CK_RV crv = sftk_xcbc_mac_pad(ctx->padBuf, padLen, ctx->blockSize,
|
||||
ctx->k2, ctx->k3);
|
||||
if (crv != CKR_OK)
|
||||
return crv;
|
||||
return sftk_MACBlock(ctx, ctx->padBuf);
|
||||
}
|
||||
if (padLen) {
|
||||
/* shd clr ctx->padLen to make sftk_MACFinal idempotent */
|
||||
PORT_Memset(ctx->padBuf + padLen, 0, ctx->blockSize - padLen);
|
||||
|
|
@ -2866,7 +2951,7 @@ sftk_MACUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
|
|||
blkSize - context->padDataLength;
|
||||
|
||||
/* not enough data even for one block */
|
||||
if (ulPartLen < minInput) {
|
||||
if (ulPartLen <= minInput) {
|
||||
PORT_Memcpy(residual, pPart, ulPartLen);
|
||||
context->padDataLength += ulPartLen;
|
||||
goto cleanup;
|
||||
|
|
@ -2880,7 +2965,7 @@ sftk_MACUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
|
|||
goto terminate;
|
||||
}
|
||||
/* MACing full blocks */
|
||||
while (ulPartLen >= blkSize) {
|
||||
while (ulPartLen > blkSize) {
|
||||
if (CKR_OK != (crv = sftk_MACBlock(context, pPart)))
|
||||
goto terminate;
|
||||
ulPartLen -= blkSize;
|
||||
|
|
@ -4645,6 +4730,13 @@ sftk_PairwiseConsistencyCheck(CK_SESSION_HANDLE hSession,
|
|||
return crv;
|
||||
}
|
||||
|
||||
/* detect trivial signing transforms */
|
||||
if ((signature_length >= pairwise_digest_length) &&
|
||||
(PORT_Memcmp(known_digest, signature + (signature_length - pairwise_digest_length), pairwise_digest_length) == 0)) {
|
||||
PORT_Free(signature);
|
||||
return CKR_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
/* Verify the known hash using the public key. */
|
||||
crv = NSC_VerifyInit(hSession, &mech, publicKey->handle);
|
||||
if (crv != CKR_OK) {
|
||||
|
|
@ -6477,6 +6569,10 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession,
|
|||
extractValue = PR_FALSE;
|
||||
classType = CKO_PRIVATE_KEY;
|
||||
break;
|
||||
case CKM_NSS_PUB_FROM_PRIV:
|
||||
extractValue = PR_FALSE;
|
||||
classType = CKO_PUBLIC_KEY;
|
||||
break;
|
||||
case CKM_NSS_JPAKE_FINAL_SHA1: /* fall through */
|
||||
case CKM_NSS_JPAKE_FINAL_SHA256: /* fall through */
|
||||
case CKM_NSS_JPAKE_FINAL_SHA384: /* fall through */
|
||||
|
|
@ -6518,6 +6614,73 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession,
|
|||
}
|
||||
|
||||
switch (mechanism) {
|
||||
/* get a public key from a private key. nsslowkey_ConvertToPublickey()
|
||||
* will generate the public portion if it doesn't already exist. */
|
||||
case CKM_NSS_PUB_FROM_PRIV: {
|
||||
NSSLOWKEYPrivateKey *privKey;
|
||||
NSSLOWKEYPublicKey *pubKey;
|
||||
int error;
|
||||
|
||||
crv = sftk_GetULongAttribute(sourceKey, CKA_KEY_TYPE, &keyType);
|
||||
if (crv != CKR_OK) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* privKey is stored in sourceKey and will be destroyed when
|
||||
* the sourceKey is freed. */
|
||||
privKey = sftk_GetPrivKey(sourceKey, keyType, &crv);
|
||||
if (privKey == NULL) {
|
||||
break;
|
||||
}
|
||||
pubKey = nsslowkey_ConvertToPublicKey(privKey);
|
||||
if (pubKey == NULL) {
|
||||
error = PORT_GetError();
|
||||
crv = sftk_MapCryptError(error);
|
||||
break;
|
||||
}
|
||||
crv = sftk_PutPubKey(key, sourceKey, keyType, pubKey);
|
||||
nsslowkey_DestroyPublicKey(pubKey);
|
||||
break;
|
||||
}
|
||||
case CKM_NSS_IKE_PRF_DERIVE:
|
||||
if (pMechanism->ulParameterLen !=
|
||||
sizeof(CK_NSS_IKE_PRF_DERIVE_PARAMS)) {
|
||||
crv = CKR_MECHANISM_PARAM_INVALID;
|
||||
break;
|
||||
}
|
||||
crv = sftk_ike_prf(hSession, att,
|
||||
(CK_NSS_IKE_PRF_DERIVE_PARAMS *)pMechanism->pParameter, key);
|
||||
break;
|
||||
case CKM_NSS_IKE1_PRF_DERIVE:
|
||||
if (pMechanism->ulParameterLen !=
|
||||
sizeof(CK_NSS_IKE1_PRF_DERIVE_PARAMS)) {
|
||||
crv = CKR_MECHANISM_PARAM_INVALID;
|
||||
break;
|
||||
}
|
||||
crv = sftk_ike1_prf(hSession, att,
|
||||
(CK_NSS_IKE1_PRF_DERIVE_PARAMS *)pMechanism->pParameter,
|
||||
key, keySize);
|
||||
break;
|
||||
case CKM_NSS_IKE1_APP_B_PRF_DERIVE:
|
||||
if (pMechanism->ulParameterLen !=
|
||||
sizeof(CK_MECHANISM_TYPE)) {
|
||||
crv = CKR_MECHANISM_PARAM_INVALID;
|
||||
break;
|
||||
}
|
||||
crv = sftk_ike1_appendix_b_prf(hSession, att,
|
||||
(CK_MECHANISM_TYPE *)pMechanism->pParameter,
|
||||
key, keySize);
|
||||
break;
|
||||
case CKM_NSS_IKE_PRF_PLUS_DERIVE:
|
||||
if (pMechanism->ulParameterLen !=
|
||||
sizeof(CK_NSS_IKE_PRF_PLUS_DERIVE_PARAMS)) {
|
||||
crv = CKR_MECHANISM_PARAM_INVALID;
|
||||
break;
|
||||
}
|
||||
crv = sftk_ike_prf_plus(hSession, att,
|
||||
(CK_NSS_IKE_PRF_PLUS_DERIVE_PARAMS *)pMechanism->pParameter,
|
||||
key, keySize);
|
||||
break;
|
||||
/*
|
||||
* generate the master secret
|
||||
*/
|
||||
|
|
@ -7480,14 +7643,14 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession,
|
|||
|
||||
case CKM_DH_PKCS_DERIVE: {
|
||||
SECItem derived, dhPublic;
|
||||
SECItem dhPrime, dhValue;
|
||||
SECItem dhPrime, dhSubPrime, dhValue;
|
||||
/* sourceKey - values for the local existing low key */
|
||||
/* get prime and value attributes */
|
||||
crv = sftk_Attribute2SecItem(NULL, &dhPrime, sourceKey, CKA_PRIME);
|
||||
if (crv != SECSuccess)
|
||||
if (crv != CKR_OK)
|
||||
break;
|
||||
crv = sftk_Attribute2SecItem(NULL, &dhValue, sourceKey, CKA_VALUE);
|
||||
if (crv != SECSuccess) {
|
||||
if (crv != CKR_OK) {
|
||||
PORT_Free(dhPrime.data);
|
||||
break;
|
||||
}
|
||||
|
|
@ -7495,6 +7658,20 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession,
|
|||
dhPublic.data = pMechanism->pParameter;
|
||||
dhPublic.len = pMechanism->ulParameterLen;
|
||||
|
||||
/* If the caller bothered to provide Q, use Q to validate
|
||||
* the public key. */
|
||||
crv = sftk_Attribute2SecItem(NULL, &dhSubPrime, sourceKey, CKA_SUBPRIME);
|
||||
if (crv == CKR_OK) {
|
||||
rv = KEA_Verify(&dhPublic, &dhPrime, &dhSubPrime);
|
||||
PORT_Free(dhSubPrime.data);
|
||||
if (rv != SECSuccess) {
|
||||
crv = CKR_ARGUMENTS_BAD;
|
||||
PORT_Free(dhPrime.data);
|
||||
PORT_Free(dhValue.data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* calculate private value - oct */
|
||||
rv = DH_Derive(&dhPublic, &dhPrime, &dhValue, &derived, keySize);
|
||||
|
||||
|
|
@ -7504,6 +7681,7 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession,
|
|||
if (rv == SECSuccess) {
|
||||
sftk_forceAttribute(key, CKA_VALUE, derived.data, derived.len);
|
||||
PORT_ZFree(derived.data, derived.len);
|
||||
crv = CKR_OK;
|
||||
} else
|
||||
crv = CKR_HOST_MEMORY;
|
||||
|
||||
|
|
@ -7569,7 +7747,7 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession,
|
|||
|
||||
rv = ECDH_Derive(&ecPoint, &privKey->u.ec.ecParams, &ecScalar,
|
||||
withCofactor, &tmp);
|
||||
PORT_Free(ecScalar.data);
|
||||
PORT_ZFree(ecScalar.data, ecScalar.len);
|
||||
ecScalar.data = NULL;
|
||||
if (privKey != sourceKey->objectInfo) {
|
||||
nsslowkey_DestroyPrivateKey(privKey);
|
||||
|
|
|
|||
|
|
@ -106,6 +106,7 @@ typedef struct SFTKOAEPEncryptInfoStr SFTKOAEPEncryptInfo;
|
|||
typedef struct SFTKOAEPDecryptInfoStr SFTKOAEPDecryptInfo;
|
||||
typedef struct SFTKSSLMACInfoStr SFTKSSLMACInfo;
|
||||
typedef struct SFTKChaCha20Poly1305InfoStr SFTKChaCha20Poly1305Info;
|
||||
typedef struct SFTKChaCha20CtrInfoStr SFTKChaCha20CtrInfo;
|
||||
typedef struct SFTKItemTemplateStr SFTKItemTemplate;
|
||||
|
||||
/* define function pointer typdefs for pointer tables */
|
||||
|
|
@ -253,12 +254,15 @@ struct SFTKSessionContextStr {
|
|||
PRBool multi; /* is multipart */
|
||||
PRBool rsa; /* is rsa */
|
||||
PRBool doPad; /* use PKCS padding for block ciphers */
|
||||
PRBool isXCBC; /* xcbc, use special handling in final */
|
||||
unsigned int blockSize; /* blocksize for padding */
|
||||
unsigned int padDataLength; /* length of the valid data in padbuf */
|
||||
/** latest incomplete block of data for block cipher */
|
||||
unsigned char padBuf[SFTK_MAX_BLOCK_SIZE];
|
||||
/** result of MAC'ing of latest full block of data with block cipher */
|
||||
unsigned char macBuf[SFTK_MAX_BLOCK_SIZE];
|
||||
unsigned char k2[SFTK_MAX_BLOCK_SIZE];
|
||||
unsigned char k3[SFTK_MAX_BLOCK_SIZE];
|
||||
CK_ULONG macSize; /* size of a general block cipher mac*/
|
||||
void *cipherInfo;
|
||||
void *hashInfo;
|
||||
|
|
@ -409,6 +413,14 @@ struct SFTKChaCha20Poly1305InfoStr {
|
|||
unsigned int adLen;
|
||||
};
|
||||
|
||||
/* SFTKChaCha20BlockInfoStr the key, nonce and counter for a
|
||||
* ChaCha20 block operation. */
|
||||
struct SFTKChaCha20CtrInfoStr {
|
||||
PRUint8 key[32];
|
||||
PRUint8 nonce[12];
|
||||
PRUint32 counter;
|
||||
};
|
||||
|
||||
/*
|
||||
* Template based on SECItems, suitable for passing as arrays
|
||||
*/
|
||||
|
|
@ -605,6 +617,7 @@ extern CK_RV SFTK_ShutdownSlot(SFTKSlot *slot);
|
|||
extern CK_RV sftk_CloseAllSessions(SFTKSlot *slot, PRBool logout);
|
||||
|
||||
/* internal utility functions used by pkcs11.c */
|
||||
extern CK_RV sftk_MapCryptError(int error);
|
||||
extern SFTKAttribute *sftk_FindAttribute(SFTKObject *object,
|
||||
CK_ATTRIBUTE_TYPE type);
|
||||
extern void sftk_FreeAttribute(SFTKAttribute *attribute);
|
||||
|
|
@ -682,10 +695,36 @@ extern NSSLOWKEYPublicKey *sftk_GetPubKey(SFTKObject *object,
|
|||
CK_KEY_TYPE key_type, CK_RV *crvp);
|
||||
extern NSSLOWKEYPrivateKey *sftk_GetPrivKey(SFTKObject *object,
|
||||
CK_KEY_TYPE key_type, CK_RV *crvp);
|
||||
extern CK_RV sftk_PutPubKey(SFTKObject *publicKey, SFTKObject *privKey, CK_KEY_TYPE keyType,
|
||||
NSSLOWKEYPublicKey *pubKey);
|
||||
extern void sftk_FormatDESKey(unsigned char *key, int length);
|
||||
extern PRBool sftk_CheckDESKey(unsigned char *key);
|
||||
extern PRBool sftk_IsWeakKey(unsigned char *key, CK_KEY_TYPE key_type);
|
||||
|
||||
/* ike and xcbc helpers */
|
||||
extern CK_RV sftk_ike_prf(CK_SESSION_HANDLE hSession,
|
||||
const SFTKAttribute *inKey,
|
||||
const CK_NSS_IKE_PRF_DERIVE_PARAMS *params, SFTKObject *outKey);
|
||||
extern CK_RV sftk_ike1_prf(CK_SESSION_HANDLE hSession,
|
||||
const SFTKAttribute *inKey,
|
||||
const CK_NSS_IKE1_PRF_DERIVE_PARAMS *params, SFTKObject *outKey,
|
||||
unsigned int keySize);
|
||||
extern CK_RV sftk_ike1_appendix_b_prf(CK_SESSION_HANDLE hSession,
|
||||
const SFTKAttribute *inKey,
|
||||
const CK_MECHANISM_TYPE *params, SFTKObject *outKey,
|
||||
unsigned int keySize);
|
||||
extern CK_RV sftk_ike_prf_plus(CK_SESSION_HANDLE hSession,
|
||||
const SFTKAttribute *inKey,
|
||||
const CK_NSS_IKE_PRF_PLUS_DERIVE_PARAMS *params, SFTKObject *outKey,
|
||||
unsigned int keySize);
|
||||
extern CK_RV sftk_aes_xcbc_new_keys(CK_SESSION_HANDLE hSession,
|
||||
CK_OBJECT_HANDLE hKey, CK_OBJECT_HANDLE_PTR phKey,
|
||||
unsigned char *k2, unsigned char *k3);
|
||||
extern CK_RV sftk_xcbc_mac_pad(unsigned char *padBuf, unsigned int bufLen,
|
||||
int blockSize, const unsigned char *k2,
|
||||
const unsigned char *k3);
|
||||
extern SECStatus sftk_fips_IKE_PowerUpSelfTests(void);
|
||||
|
||||
/* mechanism allows this operation */
|
||||
extern CK_RV sftk_MechAllowsOperation(CK_MECHANISM_TYPE type, CK_ATTRIBUTE_TYPE op);
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,47 @@
|
|||
#include "sftkdb.h"
|
||||
#include "softoken.h"
|
||||
|
||||
/*
|
||||
* ******************** Error mapping *******************************
|
||||
*/
|
||||
/*
|
||||
* map all the SEC_ERROR_xxx error codes that may be returned by freebl
|
||||
* functions to CKR_xxx. return CKR_DEVICE_ERROR by default for backward
|
||||
* compatibility.
|
||||
*/
|
||||
CK_RV
|
||||
sftk_MapCryptError(int error)
|
||||
{
|
||||
switch (error) {
|
||||
case SEC_ERROR_INVALID_ARGS:
|
||||
case SEC_ERROR_BAD_DATA: /* MP_RANGE gets mapped to this */
|
||||
return CKR_ARGUMENTS_BAD;
|
||||
case SEC_ERROR_INPUT_LEN:
|
||||
return CKR_DATA_LEN_RANGE;
|
||||
case SEC_ERROR_OUTPUT_LEN:
|
||||
return CKR_BUFFER_TOO_SMALL;
|
||||
case SEC_ERROR_LIBRARY_FAILURE:
|
||||
return CKR_GENERAL_ERROR;
|
||||
case SEC_ERROR_NO_MEMORY:
|
||||
return CKR_HOST_MEMORY;
|
||||
case SEC_ERROR_BAD_SIGNATURE:
|
||||
return CKR_SIGNATURE_INVALID;
|
||||
case SEC_ERROR_INVALID_KEY:
|
||||
return CKR_KEY_SIZE_RANGE;
|
||||
case SEC_ERROR_BAD_KEY: /* an EC public key that fails validation */
|
||||
return CKR_KEY_SIZE_RANGE; /* the closest error code */
|
||||
case SEC_ERROR_UNSUPPORTED_EC_POINT_FORM:
|
||||
return CKR_TEMPLATE_INCONSISTENT;
|
||||
case SEC_ERROR_UNSUPPORTED_KEYALG:
|
||||
return CKR_MECHANISM_INVALID;
|
||||
case SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE:
|
||||
return CKR_DOMAIN_PARAMS_INVALID;
|
||||
/* key pair generation failed after max number of attempts */
|
||||
case SEC_ERROR_NEED_RANDOM:
|
||||
return CKR_FUNCTION_FAILED;
|
||||
}
|
||||
return CKR_DEVICE_ERROR;
|
||||
}
|
||||
/*
|
||||
* ******************** Attribute Utilities *******************************
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -858,7 +858,6 @@ sdb_FindObjectsFinal(SDB *sdb, SDBFind *sdbFind)
|
|||
return sdb_mapSQLError(sdb_p->type, sqlerr);
|
||||
}
|
||||
|
||||
static const char GET_ATTRIBUTE_CMD[] = "SELECT ALL %s FROM %s WHERE id=$ID;";
|
||||
CK_RV
|
||||
sdb_GetAttributeValueNoLock(SDB *sdb, CK_OBJECT_HANDLE object_id,
|
||||
CK_ATTRIBUTE *template, CK_ULONG count)
|
||||
|
|
@ -866,8 +865,6 @@ sdb_GetAttributeValueNoLock(SDB *sdb, CK_OBJECT_HANDLE object_id,
|
|||
SDBPrivate *sdb_p = sdb->private;
|
||||
sqlite3 *sqlDB = NULL;
|
||||
sqlite3_stmt *stmt = NULL;
|
||||
char *getStr = NULL;
|
||||
char *newStr = NULL;
|
||||
const char *table = NULL;
|
||||
int sqlerr = SQLITE_OK;
|
||||
CK_RV error = CKR_OK;
|
||||
|
|
@ -875,59 +872,79 @@ sdb_GetAttributeValueNoLock(SDB *sdb, CK_OBJECT_HANDLE object_id,
|
|||
int retry = 0;
|
||||
unsigned int i;
|
||||
|
||||
if (count == 0) {
|
||||
error = CKR_OBJECT_HANDLE_INVALID;
|
||||
goto loser;
|
||||
}
|
||||
|
||||
/* open a new db if necessary */
|
||||
error = sdb_openDBLocal(sdb_p, &sqlDB, &table);
|
||||
if (error != CKR_OK) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
char *columns = NULL;
|
||||
for (i = 0; i < count; i++) {
|
||||
getStr = sqlite3_mprintf("a%x", template[i].type);
|
||||
|
||||
if (getStr == NULL) {
|
||||
char *newColumns;
|
||||
if (columns) {
|
||||
newColumns = sqlite3_mprintf("%s, a%x", columns, template[i].type);
|
||||
sqlite3_free(columns);
|
||||
columns = NULL;
|
||||
} else {
|
||||
newColumns = sqlite3_mprintf("a%x", template[i].type);
|
||||
}
|
||||
if (!newColumns) {
|
||||
error = CKR_HOST_MEMORY;
|
||||
goto loser;
|
||||
}
|
||||
columns = newColumns;
|
||||
}
|
||||
|
||||
newStr = sqlite3_mprintf(GET_ATTRIBUTE_CMD, getStr, table);
|
||||
sqlite3_free(getStr);
|
||||
getStr = NULL;
|
||||
if (newStr == NULL) {
|
||||
error = CKR_HOST_MEMORY;
|
||||
goto loser;
|
||||
PORT_Assert(columns);
|
||||
|
||||
char *statement = sqlite3_mprintf("SELECT DISTINCT %s FROM %s where id=$ID LIMIT 1;",
|
||||
columns, table);
|
||||
sqlite3_free(columns);
|
||||
columns = NULL;
|
||||
if (!statement) {
|
||||
error = CKR_HOST_MEMORY;
|
||||
goto loser;
|
||||
}
|
||||
|
||||
sqlerr = sqlite3_prepare_v2(sqlDB, statement, -1, &stmt, NULL);
|
||||
sqlite3_free(statement);
|
||||
statement = NULL;
|
||||
if (sqlerr != SQLITE_OK) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
// NB: indices in sqlite3_bind_int are 1-indexed
|
||||
sqlerr = sqlite3_bind_int(stmt, 1, object_id);
|
||||
if (sqlerr != SQLITE_OK) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
do {
|
||||
sqlerr = sqlite3_step(stmt);
|
||||
if (sqlerr == SQLITE_BUSY) {
|
||||
PR_Sleep(SDB_BUSY_RETRY_TIME);
|
||||
}
|
||||
|
||||
sqlerr = sqlite3_prepare_v2(sqlDB, newStr, -1, &stmt, NULL);
|
||||
sqlite3_free(newStr);
|
||||
newStr = NULL;
|
||||
if (sqlerr == SQLITE_ERROR) {
|
||||
template[i].ulValueLen = -1;
|
||||
error = CKR_ATTRIBUTE_TYPE_INVALID;
|
||||
continue;
|
||||
} else if (sqlerr != SQLITE_OK) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
sqlerr = sqlite3_bind_int(stmt, 1, object_id);
|
||||
if (sqlerr != SQLITE_OK) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
do {
|
||||
sqlerr = sqlite3_step(stmt);
|
||||
if (sqlerr == SQLITE_BUSY) {
|
||||
PR_Sleep(SDB_BUSY_RETRY_TIME);
|
||||
}
|
||||
if (sqlerr == SQLITE_ROW) {
|
||||
if (sqlerr == SQLITE_ROW) {
|
||||
PORT_Assert(!found);
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int blobSize;
|
||||
const char *blobData;
|
||||
|
||||
blobSize = sqlite3_column_bytes(stmt, 0);
|
||||
blobData = sqlite3_column_blob(stmt, 0);
|
||||
// NB: indices in sqlite_column_{bytes,blob} are 0-indexed
|
||||
blobSize = sqlite3_column_bytes(stmt, i);
|
||||
blobData = sqlite3_column_blob(stmt, i);
|
||||
if (blobData == NULL) {
|
||||
/* PKCS 11 requires that get attributes process all the
|
||||
* attributes in the template, marking the attributes with
|
||||
* issues with -1. Mark the error but continue */
|
||||
template[i].ulValueLen = -1;
|
||||
error = CKR_ATTRIBUTE_TYPE_INVALID;
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
/* If the blob equals our explicit NULL value, then the
|
||||
* attribute is a NULL. */
|
||||
|
|
@ -938,20 +955,21 @@ sdb_GetAttributeValueNoLock(SDB *sdb, CK_OBJECT_HANDLE object_id,
|
|||
}
|
||||
if (template[i].pValue) {
|
||||
if (template[i].ulValueLen < blobSize) {
|
||||
/* like CKR_ATTRIBUTE_TYPE_INVALID, continue processing */
|
||||
template[i].ulValueLen = -1;
|
||||
error = CKR_BUFFER_TOO_SMALL;
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
PORT_Memcpy(template[i].pValue, blobData, blobSize);
|
||||
}
|
||||
template[i].ulValueLen = blobSize;
|
||||
found = 1;
|
||||
}
|
||||
} while (!sdb_done(sqlerr, &retry));
|
||||
sqlite3_reset(stmt);
|
||||
sqlite3_finalize(stmt);
|
||||
stmt = NULL;
|
||||
}
|
||||
found = 1;
|
||||
}
|
||||
} while (!sdb_done(sqlerr, &retry));
|
||||
sqlite3_reset(stmt);
|
||||
sqlite3_finalize(stmt);
|
||||
stmt = NULL;
|
||||
|
||||
loser:
|
||||
/* fix up the error if necessary */
|
||||
|
|
|
|||
1294
security/nss/lib/softoken/sftkike.c
Normal file
1294
security/nss/lib/softoken/sftkike.c
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -859,92 +859,77 @@ static CK_RV
|
|||
sftk_updateMacs(PLArenaPool *arena, SFTKDBHandle *handle,
|
||||
CK_OBJECT_HANDLE id, SECItem *newKey)
|
||||
{
|
||||
CK_ATTRIBUTE authAttrs[] = {
|
||||
{ CKA_MODULUS, NULL, 0 },
|
||||
{ CKA_PUBLIC_EXPONENT, NULL, 0 },
|
||||
{ CKA_CERT_SHA1_HASH, NULL, 0 },
|
||||
{ CKA_CERT_MD5_HASH, NULL, 0 },
|
||||
{ CKA_TRUST_SERVER_AUTH, NULL, 0 },
|
||||
{ CKA_TRUST_CLIENT_AUTH, NULL, 0 },
|
||||
{ CKA_TRUST_EMAIL_PROTECTION, NULL, 0 },
|
||||
{ CKA_TRUST_CODE_SIGNING, NULL, 0 },
|
||||
{ CKA_TRUST_STEP_UP_APPROVED, NULL, 0 },
|
||||
{ CKA_NSS_OVERRIDE_EXTENSIONS, NULL, 0 },
|
||||
};
|
||||
CK_ULONG authAttrCount = sizeof(authAttrs) / sizeof(CK_ATTRIBUTE);
|
||||
unsigned int i, count;
|
||||
SFTKDBHandle *keyHandle = handle;
|
||||
SDB *keyTarget = NULL;
|
||||
|
||||
id &= SFTK_OBJ_ID_MASK;
|
||||
|
||||
if (handle->type != SFTK_KEYDB_TYPE) {
|
||||
keyHandle = handle->peerDB;
|
||||
}
|
||||
|
||||
if (keyHandle == NULL) {
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
/* old DB's don't have meta data, finished with MACs */
|
||||
// Old DBs don't have metadata, so we can return early here.
|
||||
keyTarget = SFTK_GET_SDB(keyHandle);
|
||||
if ((keyTarget->sdb_flags & SDB_HAS_META) == 0) {
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* STEP 1: find the MACed attributes of this object
|
||||
*/
|
||||
(void)sftkdb_GetAttributeValue(handle, id, authAttrs, authAttrCount);
|
||||
count = 0;
|
||||
/* allocate space for the attributes */
|
||||
for (i = 0; i < authAttrCount; i++) {
|
||||
if ((authAttrs[i].ulValueLen == -1) || (authAttrs[i].ulValueLen == 0)) {
|
||||
id &= SFTK_OBJ_ID_MASK;
|
||||
|
||||
CK_ATTRIBUTE_TYPE authAttrTypes[] = {
|
||||
CKA_MODULUS,
|
||||
CKA_PUBLIC_EXPONENT,
|
||||
CKA_CERT_SHA1_HASH,
|
||||
CKA_CERT_MD5_HASH,
|
||||
CKA_TRUST_SERVER_AUTH,
|
||||
CKA_TRUST_CLIENT_AUTH,
|
||||
CKA_TRUST_EMAIL_PROTECTION,
|
||||
CKA_TRUST_CODE_SIGNING,
|
||||
CKA_TRUST_STEP_UP_APPROVED,
|
||||
CKA_NSS_OVERRIDE_EXTENSIONS,
|
||||
};
|
||||
const CK_ULONG authAttrTypeCount = sizeof(authAttrTypes) / sizeof(authAttrTypes[0]);
|
||||
|
||||
// We don't know what attributes this object has, so we update them one at a
|
||||
// time.
|
||||
unsigned int i;
|
||||
for (i = 0; i < authAttrTypeCount; i++) {
|
||||
CK_ATTRIBUTE authAttr = { authAttrTypes[i], NULL, 0 };
|
||||
CK_RV rv = sftkdb_GetAttributeValue(handle, id, &authAttr, 1);
|
||||
if (rv != CKR_OK) {
|
||||
continue;
|
||||
}
|
||||
count++;
|
||||
authAttrs[i].pValue = PORT_ArenaAlloc(arena, authAttrs[i].ulValueLen);
|
||||
if (authAttrs[i].pValue == NULL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* if count was zero, none were found, finished with MACs */
|
||||
if (count == 0) {
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
(void)sftkdb_GetAttributeValue(handle, id, authAttrs, authAttrCount);
|
||||
/* ignore error code, we expect some possible errors */
|
||||
|
||||
/* GetAttributeValue just verified the old macs, safe to write
|
||||
* them out then... */
|
||||
for (i = 0; i < authAttrCount; i++) {
|
||||
SECItem *signText;
|
||||
SECItem plainText;
|
||||
SECStatus rv;
|
||||
|
||||
if ((authAttrs[i].ulValueLen == -1) || (authAttrs[i].ulValueLen == 0)) {
|
||||
if ((authAttr.ulValueLen == -1) || (authAttr.ulValueLen == 0)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (authAttrs[i].ulValueLen == sizeof(CK_ULONG) &&
|
||||
sftkdb_isULONGAttribute(authAttrs[i].type)) {
|
||||
CK_ULONG value = *(CK_ULONG *)authAttrs[i].pValue;
|
||||
sftk_ULong2SDBULong(authAttrs[i].pValue, value);
|
||||
authAttrs[i].ulValueLen = SDB_ULONG_SIZE;
|
||||
authAttr.pValue = PORT_ArenaAlloc(arena, authAttr.ulValueLen);
|
||||
if (authAttr.pValue == NULL) {
|
||||
return CKR_HOST_MEMORY;
|
||||
}
|
||||
|
||||
plainText.data = authAttrs[i].pValue;
|
||||
plainText.len = authAttrs[i].ulValueLen;
|
||||
rv = sftkdb_SignAttribute(arena, newKey, id,
|
||||
authAttrs[i].type, &plainText, &signText);
|
||||
if (rv != SECSuccess) {
|
||||
rv = sftkdb_GetAttributeValue(handle, id, &authAttr, 1);
|
||||
if (rv != CKR_OK) {
|
||||
return rv;
|
||||
}
|
||||
if ((authAttr.ulValueLen == -1) || (authAttr.ulValueLen == 0)) {
|
||||
return CKR_GENERAL_ERROR;
|
||||
}
|
||||
rv = sftkdb_PutAttributeSignature(handle, keyTarget, id,
|
||||
authAttrs[i].type, signText);
|
||||
if (rv != SECSuccess) {
|
||||
// GetAttributeValue just verified the old macs, so it is safe to write
|
||||
// them out now.
|
||||
if (authAttr.ulValueLen == sizeof(CK_ULONG) &&
|
||||
sftkdb_isULONGAttribute(authAttr.type)) {
|
||||
CK_ULONG value = *(CK_ULONG *)authAttr.pValue;
|
||||
sftk_ULong2SDBULong(authAttr.pValue, value);
|
||||
authAttr.ulValueLen = SDB_ULONG_SIZE;
|
||||
}
|
||||
SECItem *signText;
|
||||
SECItem plainText;
|
||||
plainText.data = authAttr.pValue;
|
||||
plainText.len = authAttr.ulValueLen;
|
||||
if (sftkdb_SignAttribute(arena, newKey, id, authAttr.type, &plainText,
|
||||
&signText) != SECSuccess) {
|
||||
return CKR_GENERAL_ERROR;
|
||||
}
|
||||
if (sftkdb_PutAttributeSignature(handle, keyTarget, id, authAttr.type,
|
||||
signText) != SECSuccess) {
|
||||
return CKR_GENERAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
|
@ -956,110 +941,64 @@ static CK_RV
|
|||
sftk_updateEncrypted(PLArenaPool *arena, SFTKDBHandle *keydb,
|
||||
CK_OBJECT_HANDLE id, SECItem *newKey)
|
||||
{
|
||||
CK_RV crv = CKR_OK;
|
||||
CK_RV crv2;
|
||||
CK_ATTRIBUTE *first, *last;
|
||||
CK_ATTRIBUTE privAttrs[] = {
|
||||
{ CKA_VALUE, NULL, 0 },
|
||||
{ CKA_PRIVATE_EXPONENT, NULL, 0 },
|
||||
{ CKA_PRIME_1, NULL, 0 },
|
||||
{ CKA_PRIME_2, NULL, 0 },
|
||||
{ CKA_EXPONENT_1, NULL, 0 },
|
||||
{ CKA_EXPONENT_2, NULL, 0 },
|
||||
{ CKA_COEFFICIENT, NULL, 0 }
|
||||
CK_ATTRIBUTE_TYPE privAttrTypes[] = {
|
||||
CKA_VALUE,
|
||||
CKA_PRIVATE_EXPONENT,
|
||||
CKA_PRIME_1,
|
||||
CKA_PRIME_2,
|
||||
CKA_EXPONENT_1,
|
||||
CKA_EXPONENT_2,
|
||||
CKA_COEFFICIENT,
|
||||
};
|
||||
CK_ULONG privAttrCount = sizeof(privAttrs) / sizeof(CK_ATTRIBUTE);
|
||||
unsigned int i, count;
|
||||
const CK_ULONG privAttrCount = sizeof(privAttrTypes) / sizeof(privAttrTypes[0]);
|
||||
|
||||
/*
|
||||
* STEP 1. Read the old attributes in the clear.
|
||||
*/
|
||||
|
||||
/* Get the attribute sizes.
|
||||
* ignore the error code, we will have unknown attributes here */
|
||||
crv2 = sftkdb_GetAttributeValue(keydb, id, privAttrs, privAttrCount);
|
||||
|
||||
/*
|
||||
* find the valid block of attributes and fill allocate space for
|
||||
* their data */
|
||||
first = last = NULL;
|
||||
// We don't know what attributes this object has, so we update them one at a
|
||||
// time.
|
||||
unsigned int i;
|
||||
for (i = 0; i < privAttrCount; i++) {
|
||||
/* find the block of attributes that are appropriate for this
|
||||
* objects. There should only be once contiguous block, if not
|
||||
* there's an error.
|
||||
*
|
||||
* find the first and last good entry.
|
||||
*/
|
||||
if ((privAttrs[i].ulValueLen == -1) || (privAttrs[i].ulValueLen == 0)) {
|
||||
if (!first)
|
||||
continue;
|
||||
if (!last) {
|
||||
/* previous entry was last good entry */
|
||||
last = &privAttrs[i - 1];
|
||||
}
|
||||
// Read the old attribute in the clear.
|
||||
CK_ATTRIBUTE privAttr = { privAttrTypes[i], NULL, 0 };
|
||||
CK_RV crv = sftkdb_GetAttributeValue(keydb, id, &privAttr, 1);
|
||||
if (crv != CKR_OK) {
|
||||
continue;
|
||||
}
|
||||
if (!first) {
|
||||
first = &privAttrs[i];
|
||||
if ((privAttr.ulValueLen == -1) || (privAttr.ulValueLen == 0)) {
|
||||
continue;
|
||||
}
|
||||
if (last) {
|
||||
/* OOPS, we've found another good entry beyond the end of the
|
||||
* last good entry, we need to fail here. */
|
||||
crv = CKR_GENERAL_ERROR;
|
||||
break;
|
||||
privAttr.pValue = PORT_ArenaAlloc(arena, privAttr.ulValueLen);
|
||||
if (privAttr.pValue == NULL) {
|
||||
return CKR_HOST_MEMORY;
|
||||
}
|
||||
privAttrs[i].pValue = PORT_ArenaAlloc(arena, privAttrs[i].ulValueLen);
|
||||
if (privAttrs[i].pValue == NULL) {
|
||||
crv = CKR_HOST_MEMORY;
|
||||
break;
|
||||
crv = sftkdb_GetAttributeValue(keydb, id, &privAttr, 1);
|
||||
if (crv != CKR_OK) {
|
||||
return crv;
|
||||
}
|
||||
}
|
||||
if (first == NULL) {
|
||||
/* no valid entries found, return error based on crv2 */
|
||||
return crv2;
|
||||
}
|
||||
if (last == NULL) {
|
||||
last = &privAttrs[privAttrCount - 1];
|
||||
}
|
||||
if (crv != CKR_OK) {
|
||||
return crv;
|
||||
}
|
||||
/* read the attributes */
|
||||
count = (last - first) + 1;
|
||||
crv = sftkdb_GetAttributeValue(keydb, id, first, count);
|
||||
if (crv != CKR_OK) {
|
||||
return crv;
|
||||
}
|
||||
|
||||
/*
|
||||
* STEP 2: read the encrypt the attributes with the new key.
|
||||
*/
|
||||
for (i = 0; i < count; i++) {
|
||||
SECItem plainText;
|
||||
SECItem *result;
|
||||
SECStatus rv;
|
||||
|
||||
plainText.data = first[i].pValue;
|
||||
plainText.len = first[i].ulValueLen;
|
||||
rv = sftkdb_EncryptAttribute(arena, newKey, &plainText, &result);
|
||||
if (rv != SECSuccess) {
|
||||
if ((privAttr.ulValueLen == -1) || (privAttr.ulValueLen == 0)) {
|
||||
return CKR_GENERAL_ERROR;
|
||||
}
|
||||
first[i].pValue = result->data;
|
||||
first[i].ulValueLen = result->len;
|
||||
/* clear our sensitive data out */
|
||||
SECItem plainText;
|
||||
SECItem *result;
|
||||
plainText.data = privAttr.pValue;
|
||||
plainText.len = privAttr.ulValueLen;
|
||||
if (sftkdb_EncryptAttribute(arena, newKey, &plainText, &result) != SECSuccess) {
|
||||
return CKR_GENERAL_ERROR;
|
||||
}
|
||||
privAttr.pValue = result->data;
|
||||
privAttr.ulValueLen = result->len;
|
||||
// Clear sensitive data.
|
||||
PORT_Memset(plainText.data, 0, plainText.len);
|
||||
|
||||
// Write the newly encrypted attributes out directly.
|
||||
CK_OBJECT_HANDLE newId = id & SFTK_OBJ_ID_MASK;
|
||||
keydb->newKey = newKey;
|
||||
crv = (*keydb->db->sdb_SetAttributeValue)(keydb->db, newId, &privAttr, 1);
|
||||
keydb->newKey = NULL;
|
||||
if (crv != CKR_OK) {
|
||||
return crv;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* STEP 3: write the newly encrypted attributes out directly
|
||||
*/
|
||||
id &= SFTK_OBJ_ID_MASK;
|
||||
keydb->newKey = newKey;
|
||||
crv = (*keydb->db->sdb_SetAttributeValue)(keydb->db, id, first, count);
|
||||
keydb->newKey = NULL;
|
||||
|
||||
return crv;
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
static CK_RV
|
||||
|
|
|
|||
|
|
@ -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.43" SOFTOKEN_ECC_STRING
|
||||
#define SOFTOKEN_VERSION "3.44.1" SOFTOKEN_ECC_STRING
|
||||
#define SOFTOKEN_VMAJOR 3
|
||||
#define SOFTOKEN_VMINOR 43
|
||||
#define SOFTOKEN_VPATCH 0
|
||||
#define SOFTOKEN_VMINOR 44
|
||||
#define SOFTOKEN_VPATCH 1
|
||||
#define SOFTOKEN_VBUILD 0
|
||||
#define SOFTOKEN_BETA PR_FALSE
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
'target_name': 'softokn_static',
|
||||
'type': 'static_library',
|
||||
'defines': [
|
||||
'NSS_TEST_BUILD',
|
||||
'NSS_STATIC_SOFTOKEN',
|
||||
],
|
||||
'dependencies': [
|
||||
'softokn_base',
|
||||
|
|
@ -58,6 +58,7 @@
|
|||
'sdb.c',
|
||||
'sftkdb.c',
|
||||
'sftkhmac.c',
|
||||
'sftkike.c',
|
||||
'sftkpars.c',
|
||||
'sftkpwd.c',
|
||||
'softkver.c',
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue