Replace NSS with Pale Moon's

This commit is contained in:
wuggy 2026-06-29 21:29:25 +01:00
commit 8c2e376f94
2870 changed files with 1762232 additions and 1374220 deletions

View file

@ -56,7 +56,6 @@ endif
# (7) Execute "local" rules. (OPTIONAL). #
#######################################################################
export:: private_export
# indicates dependency on freebl static lib
$(SHARED_LIBRARY): $(CRYPTOLIB)
@ -67,11 +66,10 @@ $(SHARED_LIBRARY): $(CRYPTOLIB)
ifeq ($(OS_TARGET)$(OS_RELEASE),AIX4.3)
ifeq ($(USE_64),1)
ifndef BUILD_OPT
$(OBJDIR)/pkcs11.o: pkcs11.c
@$(MAKE_OBJDIR)
$(OBJDIR)/pkcs11.o: pkcs11.c | $$(@D)/d
$(CC) -o $@ -c -O2 $(CFLAGS) $<
$(OBJDIR)/pkcs11c.o: pkcs11c.c
@$(MAKE_OBJDIR)
$(OBJDIR)/pkcs11c.o: pkcs11c.c | $$(@D)/d
$(CC) -o $@ -c -O2 $(CFLAGS) $<
endif
endif

View file

@ -13,13 +13,6 @@ EXTRA_LIBS += \
# can't do this in manifest.mn because OS_TARGET isn't defined there.
ifeq (,$(filter-out WIN%,$(OS_TARGET)))
# don't want the 32 in the shared library name
SHARED_LIBRARY = $(OBJDIR)/$(DLL_PREFIX)$(LIBRARY_NAME)$(LIBRARY_VERSION).$(DLL_SUFFIX)
IMPORT_LIBRARY = $(OBJDIR)/$(IMPORT_LIB_PREFIX)$(LIBRARY_NAME)$(LIBRARY_VERSION)$(IMPORT_LIB_SUFFIX)
RES = $(OBJDIR)/$(LIBRARY_NAME).res
RESNAME = $(LIBRARY_NAME).rc
ifdef NS_USE_GCC
EXTRA_SHARED_LIBS += \
-L$(SQLITE_LIB_DIR) \
@ -61,3 +54,12 @@ endif
ifeq ($(OS_TARGET),AIX)
OS_LIBS += -lpthread
endif
ifdef NSS_ENABLE_FIPS_INDICATORS
DEFINES += -DNSS_ENABLE_FIPS_INDICATORS
endif
ifdef NSS_FIPS_MODULE_ID
DEFINES += -DNSS_FIPS_MODULE_ID=\"${NSS_FIPS_MODULE_ID}\"
endif

View file

@ -19,7 +19,6 @@
},
{
'files': [
'lgglue.h',
'pkcs11ni.h',
'sdb.h',
'sftkdbt.h',
@ -27,7 +26,14 @@
'softoken.h',
'softoknt.h'
],
'destination': '<(nss_private_dist_dir)/<(module)'
'destination': '<(nss_private_dist_dir)/<(module)',
'conditions': [
[ 'disable_dbm==0', {
'files': [
'lgglue.h',
]
}]
]
}
]
}

View file

@ -0,0 +1,182 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
* Vendors should replace this header file with the file containing those
* algorithms which have NIST algorithm Certificates.
*/
/* handle special cases. Classes require existing code to already be
* in place for that class */
typedef enum {
SFTKFIPSNone = 0,
SFTKFIPSDH, /* allow only specific primes */
SFTKFIPSECC, /* not just keys but specific curves */
SFTKFIPSAEAD, /* single shot AEAD functions not allowed in FIPS mode */
SFTKFIPSRSAPSS
} SFTKFIPSSpecialClass;
typedef struct SFTKFIPSAlgorithmListStr SFTKFIPSAlgorithmList;
struct SFTKFIPSAlgorithmListStr {
CK_MECHANISM_TYPE type;
CK_MECHANISM_INFO info;
CK_ULONG step;
SFTKFIPSSpecialClass special;
};
SFTKFIPSAlgorithmList sftk_fips_mechs[] = {
/* A sample set of algorithms to allow basic testing in our continous
* testing infrastructure. The vendor version should replace this with
* a version that matches their algorithm testing and security policy */
/* NOTE, This looks a lot like the PKCS #11 mechanism list in pkcs11.c, it
* differs in the following ways:
* 1) the addition of step and class elements to help restrict
* the supported key sizes and types.
* 2) The mechanism flags are restricted to only those that map to
* fips approved operations.
* 3) All key sizes are in bits, independent of mechanism.
* 4) You can add more then one entry for the same mechanism to handle
* multiple descrete keys where the MIN/MAX/STEP semantics doesn't apply
* or where different operations have different key requirements.
* This table does not encode all the modules legal FIPS semantics, only
* those semantics that might possibly change due to algorithms dropping
* of the security policy late in the process. */
/* handy common flag types */
#define CKF_KPG CKF_GENERATE_KEY_PAIR
#define CKF_GEN CKF_GENERATE
#define CKF_SGN (CKF_SIGN | CKF_VERIFY)
#define CKF_ENC (CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP)
#define CKF_KEK (CKF_WRAP | CKF_UNWRAP)
#define CKF_KEA CKF_DERIVE
#define CKF_KDF CKF_DERIVE
#define CKF_HSH CKF_DIGEST
#define CK_MAX 0xffffffffUL
/* mechanisms using the same key types share the same key type
* limits */
#define RSA_FB_KEY 2048, 4096 /* min, max */
#define RSA_FB_STEP 1
#define RSA_LEGACY_FB_KEY 1024, 1792 /* min, max */
#define RSA_LEGACY_FB_STEP 256
#define DSA_FB_KEY 2048, 4096 /* min, max */
#define DSA_FB_STEP 1024
#define DH_FB_KEY 2048, 4096 /* min, max */
#define DH_FB_STEP 1024
#define EC_FB_KEY 256, 521 /* min, max */
#define EC_FB_STEP 1 /* key limits handled by special operation */
#define AES_FB_KEY 128, 256
#define AES_FB_STEP 64
{ CKM_RSA_PKCS_KEY_PAIR_GEN, { RSA_FB_KEY, CKF_KPG }, RSA_FB_STEP, SFTKFIPSNone },
{ CKM_RSA_PKCS_PSS, { RSA_FB_KEY, CKF_SGN }, RSA_FB_STEP, SFTKFIPSRSAPSS },
{ CKM_RSA_PKCS_OAEP, { RSA_FB_KEY, CKF_ENC }, RSA_FB_STEP, SFTKFIPSNone },
{ CKM_RSA_PKCS_PSS, { RSA_LEGACY_FB_KEY, CKF_VERIFY }, RSA_LEGACY_FB_STEP, SFTKFIPSRSAPSS },
/* -------------- RSA Multipart Signing Operations -------------------- */
{ CKM_SHA224_RSA_PKCS, { RSA_FB_KEY, CKF_SGN }, RSA_FB_STEP, SFTKFIPSNone },
{ CKM_SHA256_RSA_PKCS, { RSA_FB_KEY, CKF_SGN }, RSA_FB_STEP, SFTKFIPSNone },
{ CKM_SHA384_RSA_PKCS, { RSA_FB_KEY, CKF_SGN }, RSA_FB_STEP, SFTKFIPSNone },
{ CKM_SHA512_RSA_PKCS, { RSA_FB_KEY, CKF_SGN }, RSA_FB_STEP, SFTKFIPSNone },
{ CKM_SHA224_RSA_PKCS_PSS, { RSA_FB_KEY, CKF_SGN }, RSA_FB_STEP, SFTKFIPSRSAPSS },
{ CKM_SHA256_RSA_PKCS_PSS, { RSA_FB_KEY, CKF_SGN }, RSA_FB_STEP, SFTKFIPSRSAPSS },
{ CKM_SHA384_RSA_PKCS_PSS, { RSA_FB_KEY, CKF_SGN }, RSA_FB_STEP, SFTKFIPSRSAPSS },
{ CKM_SHA512_RSA_PKCS_PSS, { RSA_FB_KEY, CKF_SGN }, RSA_FB_STEP, SFTKFIPSRSAPSS },
{ CKM_SHA224_RSA_PKCS, { RSA_LEGACY_FB_KEY, CKF_VERIFY }, RSA_LEGACY_FB_STEP, SFTKFIPSRSAPSS },
{ CKM_SHA256_RSA_PKCS, { RSA_LEGACY_FB_KEY, CKF_VERIFY }, RSA_LEGACY_FB_STEP, SFTKFIPSRSAPSS },
{ CKM_SHA384_RSA_PKCS, { RSA_LEGACY_FB_KEY, CKF_VERIFY }, RSA_LEGACY_FB_STEP, SFTKFIPSRSAPSS },
{ CKM_SHA512_RSA_PKCS, { RSA_LEGACY_FB_KEY, CKF_VERIFY }, RSA_LEGACY_FB_STEP, SFTKFIPSRSAPSS },
{ CKM_SHA224_RSA_PKCS_PSS, { RSA_LEGACY_FB_KEY, CKF_VERIFY }, RSA_LEGACY_FB_STEP, SFTKFIPSRSAPSS },
{ CKM_SHA256_RSA_PKCS_PSS, { RSA_LEGACY_FB_KEY, CKF_VERIFY }, RSA_LEGACY_FB_STEP, SFTKFIPSRSAPSS },
{ CKM_SHA384_RSA_PKCS_PSS, { RSA_LEGACY_FB_KEY, CKF_VERIFY }, RSA_LEGACY_FB_STEP, SFTKFIPSRSAPSS },
{ CKM_SHA512_RSA_PKCS_PSS, { RSA_LEGACY_FB_KEY, CKF_VERIFY }, RSA_LEGACY_FB_STEP, SFTKFIPSRSAPSS },
/* ------------------------- DSA Operations --------------------------- */
{ CKM_DSA_KEY_PAIR_GEN, { DSA_FB_KEY, CKF_KPG }, DSA_FB_STEP, SFTKFIPSNone },
{ CKM_DSA, { DSA_FB_KEY, CKF_SGN }, DSA_FB_STEP, SFTKFIPSNone },
{ CKM_DSA_PARAMETER_GEN, { DSA_FB_KEY, CKF_KPG }, DSA_FB_STEP, SFTKFIPSNone },
{ CKM_DSA_SHA224, { DSA_FB_KEY, CKF_SGN }, DSA_FB_STEP, SFTKFIPSNone },
{ CKM_DSA_SHA256, { DSA_FB_KEY, CKF_SGN }, DSA_FB_STEP, SFTKFIPSNone },
{ CKM_DSA_SHA384, { DSA_FB_KEY, CKF_SGN }, DSA_FB_STEP, SFTKFIPSNone },
{ CKM_DSA_SHA512, { DSA_FB_KEY, CKF_SGN }, DSA_FB_STEP, SFTKFIPSNone },
/* -------------------- Diffie Hellman Operations --------------------- */
/* no diffie hellman yet */
{ CKM_DH_PKCS_KEY_PAIR_GEN, { DH_FB_KEY, CKF_KPG }, DH_FB_STEP, SFTKFIPSDH },
{ CKM_DH_PKCS_DERIVE, { DH_FB_KEY, CKF_KEA }, DH_FB_STEP, SFTKFIPSDH },
/* -------------------- Elliptic Curve Operations --------------------- */
{ CKM_EC_KEY_PAIR_GEN, { EC_FB_KEY, CKF_KPG }, EC_FB_STEP, SFTKFIPSECC },
{ CKM_ECDH1_DERIVE, { EC_FB_KEY, CKF_KEA }, EC_FB_STEP, SFTKFIPSECC },
{ CKM_ECDSA, { EC_FB_KEY, CKF_SGN }, EC_FB_STEP, SFTKFIPSECC },
{ CKM_ECDSA_SHA224, { EC_FB_KEY, CKF_SGN }, EC_FB_STEP, SFTKFIPSECC },
{ CKM_ECDSA_SHA256, { EC_FB_KEY, CKF_SGN }, EC_FB_STEP, SFTKFIPSECC },
{ CKM_ECDSA_SHA384, { EC_FB_KEY, CKF_SGN }, EC_FB_STEP, SFTKFIPSECC },
{ CKM_ECDSA_SHA512, { EC_FB_KEY, CKF_SGN }, EC_FB_STEP, SFTKFIPSECC },
/* ------------------------- RC2 Operations --------------------------- */
/* ------------------------- AES Operations --------------------------- */
{ CKM_AES_KEY_GEN, { AES_FB_KEY, CKF_GEN }, AES_FB_STEP, SFTKFIPSNone },
{ CKM_AES_ECB, { AES_FB_KEY, CKF_ENC }, AES_FB_STEP, SFTKFIPSNone },
{ CKM_AES_CBC, { AES_FB_KEY, CKF_ENC }, AES_FB_STEP, SFTKFIPSNone },
{ CKM_AES_MAC, { AES_FB_KEY, CKF_SGN }, AES_FB_STEP, SFTKFIPSNone },
{ CKM_AES_MAC_GENERAL, { AES_FB_KEY, CKF_SGN }, AES_FB_STEP, SFTKFIPSNone },
{ CKM_AES_CMAC, { AES_FB_KEY, CKF_SGN }, AES_FB_STEP, SFTKFIPSNone },
{ CKM_AES_CMAC_GENERAL, { AES_FB_KEY, CKF_SGN }, AES_FB_STEP, SFTKFIPSNone },
{ CKM_AES_CBC_PAD, { AES_FB_KEY, CKF_ENC }, AES_FB_STEP, SFTKFIPSNone },
{ CKM_AES_CTS, { AES_FB_KEY, CKF_ENC }, AES_FB_STEP, SFTKFIPSNone },
{ CKM_AES_CTR, { AES_FB_KEY, CKF_ENC }, AES_FB_STEP, SFTKFIPSNone },
{ CKM_AES_GCM, { AES_FB_KEY, CKF_ENC }, AES_FB_STEP, SFTKFIPSAEAD },
{ CKM_AES_KEY_WRAP, { AES_FB_KEY, CKF_ENC }, AES_FB_STEP, SFTKFIPSNone },
{ CKM_AES_KEY_WRAP_PAD, { AES_FB_KEY, CKF_ENC }, AES_FB_STEP, SFTKFIPSNone },
{ CKM_AES_KEY_WRAP_KWP, { AES_FB_KEY, CKF_ENC }, AES_FB_STEP, SFTKFIPSNone },
{ CKM_AES_XCBC_MAC_96, { 96, 96, CKF_SGN }, 1, SFTKFIPSNone },
{ CKM_AES_XCBC_MAC, { 128, 128, CKF_SGN }, 1, SFTKFIPSNone },
/* ------------------------- Hashing Operations ----------------------- */
{ CKM_SHA224, { 0, 0, CKF_HSH }, 1, SFTKFIPSNone },
{ CKM_SHA224_HMAC, { 112, 224, CKF_SGN }, 1, SFTKFIPSNone },
{ CKM_SHA224_HMAC_GENERAL, { 112, 224, CKF_SGN }, 1, SFTKFIPSNone },
{ CKM_SHA256, { 0, 0, CKF_HSH }, 1, SFTKFIPSNone },
{ CKM_SHA256_HMAC, { 128, 256, CKF_SGN }, 1, SFTKFIPSNone },
{ CKM_SHA256_HMAC_GENERAL, { 128, 256, CKF_SGN }, 1, SFTKFIPSNone },
{ CKM_SHA384, { 0, 0, CKF_HSH }, 1, SFTKFIPSNone },
{ CKM_SHA384_HMAC, { 192, 384, CKF_SGN }, 1, SFTKFIPSNone },
{ CKM_SHA384_HMAC_GENERAL, { 192, 384, CKF_SGN }, 1, SFTKFIPSNone },
{ CKM_SHA512, { 0, 0, CKF_HSH }, 1, SFTKFIPSNone },
{ CKM_SHA512_HMAC, { 256, 512, CKF_SGN }, 1, SFTKFIPSNone },
{ CKM_SHA512_HMAC_GENERAL, { 256, 512, CKF_SGN }, 1, SFTKFIPSNone },
/* --------------------- Secret Key Operations ------------------------ */
{ CKM_GENERIC_SECRET_KEY_GEN, { 8, 256, CKF_GEN }, 1, SFTKFIPSNone },
/* ---------------------- SSL/TLS operations ------------------------- */
{ CKM_SHA224_KEY_DERIVATION, { 112, 224, CKF_KDF }, 1, SFTKFIPSNone },
{ CKM_SHA256_KEY_DERIVATION, { 128, 256, CKF_KDF }, 1, SFTKFIPSNone },
{ CKM_SHA384_KEY_DERIVATION, { 192, 384, CKF_KDF }, 1, SFTKFIPSNone },
{ CKM_SHA512_KEY_DERIVATION, { 256, 512, CKF_KDF }, 1, SFTKFIPSNone },
{ CKM_TLS12_MASTER_KEY_DERIVE, { 384, 384, CKF_KDF }, 1, SFTKFIPSNone },
{ CKM_TLS12_MASTER_KEY_DERIVE_DH, { DH_FB_KEY, CKF_KDF }, 1, SFTKFIPSNone },
{ CKM_TLS12_KEY_AND_MAC_DERIVE, { 384, 384, CKF_KDF }, 1, SFTKFIPSNone },
{ CKM_TLS_PRF_GENERAL, { 8, 512, CKF_SGN }, 1, SFTKFIPSNone },
{ CKM_TLS_MAC, { 8, 512, CKF_SGN }, 1, SFTKFIPSNone },
/* sigh, is this algorithm really tested. ssl doesn't seem to have a
* way of turning the extension off */
{ CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE, { 192, 1024, CKF_KDF }, 1, SFTKFIPSNone },
{ CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_DH, { 192, 1024, CKF_DERIVE }, 1, SFTKFIPSNone },
/* ------------------------- HKDF Operations -------------------------- */
{ CKM_HKDF_DERIVE, { 8, 255 * 64 * 8, CKF_KDF }, 1, SFTKFIPSNone },
{ CKM_HKDF_DATA, { 8, 255 * 64 * 8, CKF_KDF }, 1, SFTKFIPSNone },
{ CKM_HKDF_KEY_GEN, { 160, 224, CKF_GEN }, 1, SFTKFIPSNone },
{ CKM_HKDF_KEY_GEN, { 256, 512, CKF_GEN }, 128, SFTKFIPSNone },
/* ------------------ NIST 800-108 Key Derivations ------------------- */
{ CKM_SP800_108_COUNTER_KDF, { 0, CK_MAX, CKF_KDF }, 1, SFTKFIPSNone },
{ CKM_SP800_108_FEEDBACK_KDF, { 0, CK_MAX, CKF_KDF }, 1, SFTKFIPSNone },
{ CKM_SP800_108_DOUBLE_PIPELINE_KDF, { 0, CK_MAX, CKF_KDF }, 1, SFTKFIPSNone },
{ CKM_NSS_SP800_108_COUNTER_KDF_DERIVE_DATA, { 0, CK_MAX, CKF_KDF }, 1, SFTKFIPSNone },
{ CKM_NSS_SP800_108_FEEDBACK_KDF_DERIVE_DATA, { 0, CK_MAX, CKF_KDF }, 1, SFTKFIPSNone },
{ CKM_NSS_SP800_108_DOUBLE_PIPELINE_KDF_DERIVE_DATA, { 0, CK_MAX, CKF_KDF }, 1, SFTKFIPSNone },
/* --------------------IPSEC ----------------------- */
{ CKM_NSS_IKE_PRF_PLUS_DERIVE, { 8, 255 * 64, CKF_KDF }, 1, SFTKFIPSNone },
{ CKM_NSS_IKE_PRF_DERIVE, { 8, 64, CKF_KDF }, 1, SFTKFIPSNone },
{ CKM_NSS_IKE1_PRF_DERIVE, { 8, 64, CKF_KDF }, 1, SFTKFIPSNone },
{ CKM_NSS_IKE1_APP_B_PRF_DERIVE, { 8, 255 * 64, CKF_KDF }, 1, SFTKFIPSNone },
/* ------------------ PBE Key Derivations ------------------- */
{ CKM_PKCS5_PBKD2, { 1, 256, CKF_GEN }, 1, SFTKFIPSNone },
{ CKM_NSS_PKCS12_PBE_SHA224_HMAC_KEY_GEN, { 224, 224, CKF_GEN }, 1, SFTKFIPSNone },
{ CKM_NSS_PKCS12_PBE_SHA256_HMAC_KEY_GEN, { 256, 256, CKF_GEN }, 1, SFTKFIPSNone },
{ CKM_NSS_PKCS12_PBE_SHA384_HMAC_KEY_GEN, { 384, 384, CKF_GEN }, 1, SFTKFIPSNone },
{ CKM_NSS_PKCS12_PBE_SHA512_HMAC_KEY_GEN, { 512, 512, CKF_GEN }, 1, SFTKFIPSNone }
};
const int SFTK_NUMBER_FIPS_ALGORITHMS = PR_ARRAY_SIZE(sftk_fips_mechs);

View file

@ -13,6 +13,7 @@
#include "secoid.h"
#include "secerr.h"
#include "pkcs11i.h"
#include "lowpbe.h"
/*
* different platforms have different ways of calling and initial entry point
@ -39,7 +40,8 @@ static void INIT_FUNCTION sftk_startup_tests(void);
#if defined(XP_WIN) && !defined(NSS_NO_INIT_SUPPORT)
#include <windows.h>
BOOL WINAPI DllMain(
BOOL WINAPI
DllMain(
HINSTANCE hinstDLL, // handle to DLL module
DWORD fdwReason, // reason for calling function
LPVOID lpReserved) // reserved
@ -581,6 +583,106 @@ rsa_loser:
return (SECFailure);
}
static SECStatus
sftk_fips_HKDF_PowerUpSelfTest(void)
{
SECStatus status;
static const unsigned char base_key[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f
};
static const unsigned char known_hkdf_sha256_key[] = {
0xdd, 0xdb, 0xeb, 0xe5, 0x6d, 0xd2, 0x96, 0xa4,
0x07, 0xc5, 0x7d, 0xda, 0x31, 0x56, 0x8d, 0xa5,
0x41, 0x3e, 0x90, 0xd4, 0xe6, 0x98, 0xeb, 0xf8,
0x5a, 0x49, 0x7f, 0x38, 0xef, 0x01, 0x8a, 0xe5,
0xda, 0x36, 0xe5, 0xcf, 0x21, 0xe3, 0x9f, 0xc3,
0x32, 0xb3, 0x1e, 0xf6, 0xc5, 0x10, 0x4c, 0x86,
0x53, 0x5e, 0x6f, 0xe0, 0x63, 0x6e, 0x43, 0x33,
0x61, 0x35, 0xf4, 0x17, 0x10, 0x77, 0x75, 0x2a
};
/* current NIST IG's say we only need to test one instance
* of kdfs, keep these others around in case the guidance
* changes */
#ifdef NSS_FULL_POST
static const unsigned char known_hkdf_sha384_key[] = {
0x35, 0x64, 0xc4, 0xa1, 0xcc, 0xc1, 0xdc, 0xe4,
0xe2, 0xca, 0x51, 0xae, 0xe8, 0x92, 0x88, 0x30,
0x8b, 0xb0, 0x2b, 0xac, 0x00, 0x15, 0xac, 0x15,
0x97, 0xc9, 0xf4, 0x6b, 0xf6, 0x3f, 0x97, 0xea,
0x48, 0x55, 0x38, 0x25, 0x06, 0x5d, 0x91, 0x64,
0xbd, 0x09, 0xf3, 0x44, 0xbc, 0x82, 0xbe, 0xdb,
0x5c, 0xd7, 0xf2, 0x24, 0xa5, 0x55, 0x8d, 0xa9,
0xa8, 0x85, 0xde, 0x8c, 0x33, 0xe0, 0x4d, 0xc3
};
static const unsigned char known_hkdf_sha512_key[] = {
0x63, 0x4e, 0xbc, 0x42, 0xb3, 0x56, 0x74, 0x7d,
0x1b, 0x55, 0xf0, 0x34, 0x54, 0xcb, 0x6d, 0x58,
0x39, 0x96, 0x10, 0xda, 0x03, 0x20, 0x8f, 0x77,
0x0d, 0xb4, 0xf7, 0xf6, 0x67, 0x0d, 0x5b, 0x6b,
0xd0, 0x30, 0xc4, 0xdd, 0x67, 0x61, 0x5d, 0x9a,
0xf5, 0x18, 0x6e, 0x1b, 0x60, 0x97, 0xc2, 0x4d,
0x23, 0x43, 0x69, 0xe6, 0x3b, 0xa5, 0xdf, 0xe9,
0x7c, 0xf1, 0x87, 0x48, 0x6f, 0xb9, 0xd3, 0x02
};
#endif
unsigned char outBytes[64] = { 0 };
CK_HKDF_PARAMS hkdf_params;
hkdf_params.bExpand = CK_TRUE;
hkdf_params.bExtract = CK_TRUE;
hkdf_params.ulSaltType = CKF_HKDF_SALT_DATA;
hkdf_params.pSalt = (CK_BYTE_PTR)base_key;
hkdf_params.ulSaltLen = sizeof(base_key);
hkdf_params.pInfo = (CK_BYTE_PTR)base_key;
hkdf_params.ulInfoLen = sizeof(base_key);
/**************************************************/
/* HKDF tests */
/**************************************************/
hkdf_params.prfHashMechanism = CKM_SHA256_HMAC;
status = sftk_HKDF(&hkdf_params, CK_INVALID_HANDLE, NULL,
base_key, 32, NULL, outBytes, sizeof(outBytes),
PR_TRUE, PR_TRUE);
if ((status != SECSuccess) ||
PORT_Memcmp(outBytes, known_hkdf_sha256_key, sizeof(outBytes)) != 0) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return (SECFailure);
}
#ifdef NSS_FULL_POST
hkdf_params.prfHashMechanism = CKM_SHA384_HMAC;
status = sftk_HKDF(&hkdf_params, CK_INVALID_HANDLE, NULL,
base_key, 48, NULL, outBytes, sizeof(outBytes),
PR_TRUE, PR_TRUE);
if ((status != SECSuccess) ||
PORT_Memcmp(outBytes, known_hkdf_sha384_key, sizeof(outBytes)) != 0) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return (SECFailure);
}
hkdf_params.prfHashMechanism = CKM_SHA512_HMAC;
status = sftk_HKDF(&hkdf_params, CK_INVALID_HANDLE, NULL,
base_key, 64, NULL, outBytes, sizeof(outBytes),
PR_TRUE, PR_TRUE);
if ((status != SECSuccess) ||
PORT_Memcmp(outBytes, known_hkdf_sha512_key, sizeof(outBytes)) != 0) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return (SECFailure);
}
#endif
return (SECSuccess);
}
static PRBool sftk_self_tests_ran = PR_FALSE;
static PRBool sftk_self_tests_success = PR_FALSE;
@ -588,11 +690,11 @@ static PRBool sftk_self_tests_success = PR_FALSE;
* This function is called at dll load time, the code tha makes this
* happen is platform specific on defined above.
*/
static void
sftk_startup_tests(void)
void
sftk_startup_tests_with_rerun(PRBool rerun)
{
SECStatus rv;
const char *libraryName = SOFTOKEN_LIB_NAME;
const char *libraryName = rerun ? BLAPI_FIPS_RERUN_FLAG_STRING SOFTOKEN_LIB_NAME : SOFTOKEN_LIB_NAME;
PORT_Assert(!sftk_self_tests_ran);
PORT_Assert(!sftk_self_tests_success);
@ -631,16 +733,38 @@ sftk_startup_tests(void)
if (rv != SECSuccess) {
return;
}
rv = sftk_fips_SP800_108_PowerUpSelfTests();
if (rv != SECSuccess) {
return;
}
rv = sftk_fips_HKDF_PowerUpSelfTest();
if (rv != SECSuccess) {
return;
}
rv = sftk_fips_pbkdf_PowerUpSelfTests();
if (rv != SECSuccess) {
return;
}
sftk_self_tests_success = PR_TRUE;
}
static void
sftk_startup_tests(void)
{
sftk_startup_tests_with_rerun(PR_FALSE);
}
/*
* this is called from nsc_Common_Initizialize entry points that gates access
* to * all other pkcs11 functions. This prevents softoken operation if our
* power on selftest failed.
*/
CK_RV
sftk_FIPSEntryOK()
sftk_FIPSEntryOK(PRBool rerun)
{
#ifdef NSS_NO_INIT_SUPPORT
/* this should only be set on platforms that can't handle one of the INIT
@ -653,6 +777,11 @@ sftk_FIPSEntryOK()
sftk_startup_tests();
}
#endif
if (rerun) {
sftk_self_tests_ran = PR_FALSE;
sftk_self_tests_success = PR_FALSE;
sftk_startup_tests_with_rerun(PR_TRUE);
}
if (!sftk_self_tests_success) {
return CKR_DEVICE_ERROR;
}

View file

@ -230,6 +230,8 @@ fc_getAttribute(CK_ATTRIBUTE_PTR pTemplate,
#undef CK_NEED_ARG_LIST
#undef CK_PKCS11_FUNCTION_INFO
#define CK_PKCS11_3_0 1
#define CK_PKCS11_FUNCTION_INFO(name) CK_RV __PASTE(NS, name)
#define CK_NEED_ARG_LIST 1
@ -245,8 +247,8 @@ fc_getAttribute(CK_ATTRIBUTE_PTR pTemplate,
#include "pkcs11f.h"
/* ------------- build the CK_CRYPTO_TABLE ------------------------- */
static CK_FUNCTION_LIST sftk_fipsTable = {
{ 1, 10 },
static CK_FUNCTION_LIST_3_0 sftk_fipsTable = {
{ CRYPTOKI_VERSION_MAJOR, CRYPTOKI_VERSION_MINOR },
#undef CK_NEED_ARG_LIST
#undef CK_PKCS11_FUNCTION_INFO
@ -259,11 +261,52 @@ static CK_FUNCTION_LIST sftk_fipsTable = {
};
/* forward declaration of special GetInfo functions */
CK_RV FC_GetInfoV2(CK_INFO_PTR pInfo);
CK_RV NSC_GetInfoV2(CK_INFO_PTR pInfo);
CK_RV FC_GetMechanismInfoV2(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type,
CK_MECHANISM_INFO_PTR pInfo);
CK_RV NSC_GetMechanismInfoV2(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type,
CK_MECHANISM_INFO_PTR pInfo);
static CK_FUNCTION_LIST sftk_fipsTable_v2 = {
{ 2, 40 },
#undef CK_PKCS11_3_0
#define CK_PKCS11_2_0_ONLY 1
#undef CK_NEED_ARG_LIST
#undef CK_PKCS11_FUNCTION_INFO
#define C_GetInfo C_GetInfoV2
#define C_GetMechanismInfo C_GetMechanismInfoV2
#define CK_PKCS11_FUNCTION_INFO(name) \
__PASTE(F, name) \
,
#include "pkcs11f.h"
};
#undef C_GetInfo
#undef C_GetMechanismInfo
#undef CK_NEED_ARG_LIST
#undef CK_PKCS11_FUNCTION_INFO
#undef CK_PKCS11_2_0_ONLY
#undef __PASTE
/*
* Array is orderd by default first
*/
static CK_INTERFACE fips_interfaces[] = {
{ (CK_UTF8CHAR_PTR) "PKCS 11", &sftk_fipsTable, NSS_INTERFACE_FLAGS },
{ (CK_UTF8CHAR_PTR) "PKCS 11", &sftk_fipsTable_v2, NSS_INTERFACE_FLAGS },
{ (CK_UTF8CHAR_PTR) "Vendor NSS Module Interface", &sftk_module_funcList, NSS_INTERFACE_FLAGS },
{ (CK_UTF8CHAR_PTR) "Vendor NSS FIPS Interface", &sftk_fips_funcList, NSS_INTERFACE_FLAGS }
};
/* must match the count of interfaces in fips_interfaces above*/
#define FIPS_INTERFACE_COUNT 4
/* CKO_NOT_A_KEY can be any object class that's not a key object. */
#define CKO_NOT_A_KEY CKO_DATA
@ -419,10 +462,51 @@ FC_GetFunctionList(CK_FUNCTION_LIST_PTR *pFunctionList)
CHECK_FORK();
*pFunctionList = &sftk_fipsTable;
*pFunctionList = &sftk_fipsTable_v2;
return CKR_OK;
}
CK_RV
FC_GetInterfaceList(CK_INTERFACE_PTR interfaces, CK_ULONG_PTR pulCount)
{
CK_ULONG count = *pulCount;
*pulCount = FIPS_INTERFACE_COUNT;
if (interfaces == NULL) {
return CKR_OK;
}
if (count < FIPS_INTERFACE_COUNT) {
return CKR_BUFFER_TOO_SMALL;
}
PORT_Memcpy(interfaces, fips_interfaces, sizeof(fips_interfaces));
return CKR_OK;
}
/*
* Get the requested interface, use the fips_interfaces array so we can
* easily add new interfaces as they occur.
*/
CK_RV
FC_GetInterface(CK_UTF8CHAR_PTR pInterfaceName, CK_VERSION_PTR pVersion,
CK_INTERFACE_PTR_PTR ppInterface, CK_FLAGS flags)
{
int i;
for (i = 0; i < FIPS_INTERFACE_COUNT; i++) {
CK_INTERFACE_PTR interface = &fips_interfaces[i];
if (pInterfaceName && PORT_Strcmp((char *)pInterfaceName, (char *)interface->pInterfaceName) != 0) {
continue;
}
if (pVersion && PORT_Memcmp(pVersion, (CK_VERSION *)interface->pFunctionList, sizeof(CK_VERSION)) != 0) {
continue;
}
if (flags & ((interface->flags & flags) != flags)) {
continue;
}
*ppInterface = interface;
return CKR_OK;
}
return CKR_ARGUMENTS_BAD;
}
/* sigh global so pkcs11 can read it */
PRBool nsf_init = PR_FALSE;
@ -445,15 +529,22 @@ FC_Initialize(CK_VOID_PTR pReserved)
{
const char *envp;
CK_RV crv;
PRBool rerun;
if ((envp = PR_GetEnv("NSS_ENABLE_AUDIT")) != NULL) {
sftk_audit_enabled = (atoi(envp) == 1);
}
/* if we have the forcePOST flag on, rerun the integrity checks */
/* we need to know this before we fully parse the arguments in
* nsc_CommonInitialize, so read it now */
rerun = sftk_RawArgHasFlag("flags", "forcePost", pReserved);
/* At this point we should have already done post and integrity checks.
* if we haven't, it probably means the FIPS product has not been installed
* or the tests failed. Don't let an application try to enter FIPS mode */
crv = sftk_FIPSEntryOK();
* or the tests failed. Don't let an application try to enter FIPS mode. This
* also forces the tests to be rerun if forcePOST is set. */
crv = sftk_FIPSEntryOK(rerun);
if (crv != CKR_OK) {
sftk_fatalError = PR_TRUE;
fc_log_init_error(crv);
@ -510,6 +601,15 @@ FC_GetInfo(CK_INFO_PTR pInfo)
return NSC_GetInfo(pInfo);
}
/* FC_GetInfo returns general information about PKCS #11. */
CK_RV
FC_GetInfoV2(CK_INFO_PTR pInfo)
{
CHECK_FORK();
return NSC_GetInfoV2(pInfo);
}
/* FC_GetSlotList obtains a list of slots in the system. */
CK_RV
FC_GetSlotList(CK_BBOOL tokenPresent,
@ -540,7 +640,7 @@ FC_GetTokenInfo(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo)
crv = NSC_GetTokenInfo(slotID, pInfo);
if (crv == CKR_OK) {
/* use the global database to figure out if we are running in
/* use the global database to figure out if we are running in
* FIPS 140 Level 1 or Level 2 */
if (slotID == FIPS_SLOT_ID &&
(pInfo->flags & CKF_LOGIN_REQUIRED) == 0) {
@ -558,7 +658,7 @@ FC_GetMechanismList(CK_SLOT_ID slotID,
CHECK_FORK();
SFTK_FIPSFATALCHECK();
if ((slotID == FIPS_SLOT_ID) || (slotID >= SFTK_MIN_FIPS_USER_SLOT_ID)) {
if (sftk_isFIPS(slotID)) {
slotID = NETSCAPE_SLOT_ID;
}
/* FIPS Slots support all functions */
@ -574,13 +674,29 @@ FC_GetMechanismInfo(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type,
CHECK_FORK();
SFTK_FIPSFATALCHECK();
if ((slotID == FIPS_SLOT_ID) || (slotID >= SFTK_MIN_FIPS_USER_SLOT_ID)) {
if (sftk_isFIPS(slotID)) {
slotID = NETSCAPE_SLOT_ID;
}
/* FIPS Slots support all functions */
return NSC_GetMechanismInfo(slotID, type, pInfo);
}
/* FC_GetMechanismInfoV2 same as FC_GetMechanismInfo except the Message
* flags have been stripped out */
CK_RV
FC_GetMechanismInfoV2(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type,
CK_MECHANISM_INFO_PTR pInfo)
{
CHECK_FORK();
SFTK_FIPSFATALCHECK();
if (sftk_isFIPS(slotID)) {
slotID = NETSCAPE_SLOT_ID;
}
/* FIPS Slots support all functions */
return NSC_GetMechanismInfoV2(slotID, type, pInfo);
}
/* FC_InitToken initializes a token. */
CK_RV
FC_InitToken(CK_SLOT_ID slotID, CK_CHAR_PTR pPin,
@ -718,6 +834,16 @@ FC_CloseAllSessions(CK_SLOT_ID slotID)
return NSC_CloseAllSessions(slotID);
}
CK_RV
FC_SessionCancel(CK_SESSION_HANDLE hSession, CK_FLAGS flags)
{
SFTK_FIPSFATALCHECK();
CHECK_FORK();
return NSC_SessionCancel(hSession, flags);
}
/* FC_GetSessionInfo obtains information about the session. */
CK_RV
FC_GetSessionInfo(CK_SESSION_HANDLE hSession,
@ -777,6 +903,36 @@ FC_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType,
return rv;
}
CK_RV
FC_LoginUser(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType,
CK_CHAR_PTR pPin, CK_ULONG ulPinLen, CK_UTF8CHAR_PTR pUsername,
CK_ULONG ulUsernameLen)
{
CK_RV rv;
PRBool successful;
if (sftk_fatalError)
return CKR_DEVICE_ERROR;
rv = NSC_LoginUser(hSession, userType, pPin, ulPinLen,
pUsername, ulUsernameLen);
successful = (rv == CKR_OK) || (rv == CKR_USER_ALREADY_LOGGED_IN);
if (successful)
isLoggedIn = PR_TRUE;
if (sftk_audit_enabled) {
char msg[128];
char user[61];
int len = PR_MIN(ulUsernameLen, sizeof(user) - 1);
PORT_Memcpy(user, pUsername, len);
user[len] = 0;
NSSAuditSeverity severity;
severity = successful ? NSS_AUDIT_INFO : NSS_AUDIT_ERROR;
PR_snprintf(msg, sizeof msg,
"C_LoginUser(hSession=0x%08lX, userType=%lu username=%s)=0x%08lX",
(PRUint32)hSession, (PRUint32)userType, user, (PRUint32)rv);
sftk_LogAuditMessage(severity, NSS_AUDIT_LOGIN, msg);
}
return rv;
}
/* FC_Logout logs a user out from a token. */
CK_RV
FC_Logout(CK_SESSION_HANDLE hSession)
@ -815,7 +971,7 @@ FC_CreateObject(CK_SESSION_HANDLE hSession,
if (classptr == NULL)
return CKR_TEMPLATE_INCOMPLETE;
if (*classptr == CKO_NETSCAPE_NEWSLOT || *classptr == CKO_NETSCAPE_DELSLOT) {
if (*classptr == CKO_NSS_NEWSLOT || *classptr == CKO_NSS_DELSLOT) {
if (sftk_fatalError)
return CKR_DEVICE_ERROR;
} else {
@ -1691,3 +1847,234 @@ FC_WaitForSlotEvent(CK_FLAGS flags, CK_SLOT_ID_PTR pSlot,
return NSC_WaitForSlotEvent(flags, pSlot, pReserved);
}
CK_RV
FC_MessageEncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
CK_OBJECT_HANDLE hKey)
{
SFTK_FIPSCHECK();
CHECK_FORK();
rv = NSC_MessageEncryptInit(hSession, pMechanism, hKey);
if (sftk_audit_enabled) {
sftk_AuditCryptInit("MessageEncrypt", hSession, pMechanism, hKey, rv);
}
return rv;
}
CK_RV
FC_EncryptMessage(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
CK_ULONG ulParameterLen, CK_BYTE_PTR pAssociatedData,
CK_ULONG ulAssociatedDataLen, CK_BYTE_PTR pPlaintext,
CK_ULONG ulPlaintextLen, CK_BYTE_PTR pCiphertext,
CK_ULONG_PTR pulCiphertextLen)
{
SFTK_FIPSCHECK();
CHECK_FORK();
return NSC_EncryptMessage(hSession, pParameter, ulParameterLen,
pAssociatedData, ulAssociatedDataLen,
pPlaintext, ulPlaintextLen, pCiphertext,
pulCiphertextLen);
}
CK_RV
FC_EncryptMessageBegin(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
CK_ULONG ulParameterLen, CK_BYTE_PTR pAssociatedData,
CK_ULONG ulAssociatedDataLen)
{
SFTK_FIPSCHECK();
CHECK_FORK();
return NSC_EncryptMessageBegin(hSession, pParameter, ulParameterLen,
pAssociatedData, ulAssociatedDataLen);
}
CK_RV
FC_EncryptMessageNext(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
CK_ULONG ulParameterLen, CK_BYTE_PTR pPlaintextPart,
CK_ULONG ulPlaintextPartLen, CK_BYTE_PTR pCiphertextPart,
CK_ULONG_PTR pulCiphertextPartLen, CK_FLAGS flags)
{
SFTK_FIPSCHECK();
CHECK_FORK();
return NSC_EncryptMessageNext(hSession, pParameter, ulParameterLen,
pPlaintextPart, ulPlaintextPartLen,
pCiphertextPart, pulCiphertextPartLen, flags);
}
CK_RV
FC_MessageEncryptFinal(CK_SESSION_HANDLE hSession)
{
SFTK_FIPSCHECK();
CHECK_FORK();
return NSC_MessageEncryptFinal(hSession);
}
CK_RV
FC_MessageDecryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
CK_OBJECT_HANDLE hKey)
{
SFTK_FIPSCHECK();
CHECK_FORK();
rv = NSC_MessageDecryptInit(hSession, pMechanism, hKey);
if (sftk_audit_enabled) {
sftk_AuditCryptInit("MessageDecrypt", hSession, pMechanism, hKey, rv);
}
return rv;
}
CK_RV
FC_DecryptMessage(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
CK_ULONG ulParameterLen, CK_BYTE_PTR pAssociatedData,
CK_ULONG ulAssociatedDataLen, CK_BYTE_PTR pCiphertext,
CK_ULONG ulCiphertextLen, CK_BYTE_PTR pPlaintext,
CK_ULONG_PTR pulPlaintextLen)
{
SFTK_FIPSCHECK();
CHECK_FORK();
return NSC_DecryptMessage(hSession, pParameter, ulParameterLen,
pAssociatedData, ulAssociatedDataLen,
pCiphertext, ulCiphertextLen, pPlaintext,
pulPlaintextLen);
}
CK_RV
FC_DecryptMessageBegin(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
CK_ULONG ulParameterLen, CK_BYTE_PTR pAssociatedData,
CK_ULONG ulAssociatedDataLen)
{
SFTK_FIPSCHECK();
CHECK_FORK();
return NSC_DecryptMessageBegin(hSession, pParameter, ulParameterLen,
pAssociatedData, ulAssociatedDataLen);
}
CK_RV
FC_DecryptMessageNext(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
CK_ULONG ulParameterLen, CK_BYTE_PTR pCiphertextPart,
CK_ULONG ulCiphertextPartLen, CK_BYTE_PTR pPlaintextPart,
CK_ULONG_PTR pulPlaintextPartLen, CK_FLAGS flags)
{
SFTK_FIPSCHECK();
CHECK_FORK();
return NSC_DecryptMessageNext(hSession, pParameter, ulParameterLen,
pCiphertextPart, ulCiphertextPartLen,
pPlaintextPart, pulPlaintextPartLen, flags);
}
CK_RV
FC_MessageDecryptFinal(CK_SESSION_HANDLE hSession)
{
SFTK_FIPSCHECK();
CHECK_FORK();
return NSC_MessageDecryptFinal(hSession);
}
CK_RV
FC_MessageSignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
CK_OBJECT_HANDLE hKey)
{
SFTK_FIPSCHECK();
CHECK_FORK();
rv = NSC_MessageSignInit(hSession, pMechanism, hKey);
if (sftk_audit_enabled) {
sftk_AuditCryptInit("MessageSign", hSession, pMechanism, hKey, rv);
}
return rv;
}
CK_RV
FC_SignMessage(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
CK_ULONG ulParameterLen, CK_BYTE_PTR pData, CK_ULONG ulDataLen,
CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
{
SFTK_FIPSCHECK();
CHECK_FORK();
return NSC_SignMessage(hSession, pParameter, ulParameterLen, pData,
ulDataLen, pSignature, pulSignatureLen);
}
CK_RV
FC_SignMessageBegin(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
CK_ULONG ulParameterLen)
{
SFTK_FIPSCHECK();
CHECK_FORK();
return NSC_SignMessageBegin(hSession, pParameter, ulParameterLen);
}
CK_RV
FC_SignMessageNext(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
CK_ULONG ulParameterLen, CK_BYTE_PTR pData,
CK_ULONG ulDataLen, CK_BYTE_PTR pSignature,
CK_ULONG_PTR pulSignatureLen)
{
SFTK_FIPSCHECK();
CHECK_FORK();
return NSC_SignMessageNext(hSession, pParameter, ulParameterLen, pData,
ulDataLen, pSignature, pulSignatureLen);
}
CK_RV
FC_MessageSignFinal(CK_SESSION_HANDLE hSession)
{
SFTK_FIPSCHECK();
CHECK_FORK();
return NSC_MessageSignFinal(hSession);
}
CK_RV
FC_MessageVerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
CK_OBJECT_HANDLE hKey)
{
SFTK_FIPSCHECK();
CHECK_FORK();
rv = NSC_MessageVerifyInit(hSession, pMechanism, hKey);
if (sftk_audit_enabled) {
sftk_AuditCryptInit("MessageVerify", hSession, pMechanism, hKey, rv);
}
return rv;
}
CK_RV
FC_VerifyMessage(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
CK_ULONG ulParameterLen, CK_BYTE_PTR pData,
CK_ULONG ulDataLen, CK_BYTE_PTR pSignature,
CK_ULONG ulSignatureLen)
{
SFTK_FIPSCHECK();
CHECK_FORK();
return NSC_VerifyMessage(hSession, pParameter, ulParameterLen, pData,
ulDataLen, pSignature, ulSignatureLen);
}
CK_RV
FC_VerifyMessageBegin(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
CK_ULONG ulParameterLen)
{
SFTK_FIPSCHECK();
CHECK_FORK();
return NSC_VerifyMessageBegin(hSession, pParameter, ulParameterLen);
}
CK_RV
FC_VerifyMessageNext(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
CK_ULONG ulParameterLen, CK_BYTE_PTR pData,
CK_ULONG ulDataLen, CK_BYTE_PTR pSignature,
CK_ULONG ulSignatureLen)
{
SFTK_FIPSCHECK();
CHECK_FORK();
return NSC_VerifyMessageNext(hSession, pParameter, ulParameterLen,
pData, ulDataLen, pSignature, ulSignatureLen);
}
CK_RV
FC_MessageVerifyFinal(CK_SESSION_HANDLE hSession)
{
SFTK_FIPSCHECK();
CHECK_FORK();
return NSC_MessageVerifyFinal(hSession);
}

File diff suppressed because it is too large Load diff

View file

@ -56,7 +56,5 @@ include $(CORE_DEPTH)/coreconf/rules.mk
# (7) Execute "local" rules. (OPTIONAL). #
#######################################################################
export:: private_export
# indicates dependency on freebl static lib
$(SHARED_LIBRARY): $(CRYPTOLIB)

View file

@ -14,13 +14,6 @@ EXTRA_LIBS += \
# can't do this in manifest.mn because OS_TARGET isn't defined there.
ifeq (,$(filter-out WIN%,$(OS_TARGET)))
# don't want the 32 in the shared library name
SHARED_LIBRARY = $(OBJDIR)/$(DLL_PREFIX)$(LIBRARY_NAME)$(LIBRARY_VERSION).$(DLL_SUFFIX)
IMPORT_LIBRARY = $(OBJDIR)/$(IMPORT_LIB_PREFIX)$(LIBRARY_NAME)$(LIBRARY_VERSION)$(IMPORT_LIB_SUFFIX)
RES = $(OBJDIR)/$(LIBRARY_NAME).res
RESNAME = $(LIBRARY_NAME).rc
ifdef NS_USE_GCC
EXTRA_SHARED_LIBS += \
-L$(DIST)/lib \

View file

@ -1180,13 +1180,12 @@ typedef struct NSSLowPasswordDataParamStr {
SECItem iter;
} NSSLowPasswordDataParam;
static const SEC_ASN1Template NSSLOWPasswordParamTemplate[] =
{
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLowPasswordDataParam) },
{ SEC_ASN1_OCTET_STRING, offsetof(NSSLowPasswordDataParam, salt) },
{ SEC_ASN1_INTEGER, offsetof(NSSLowPasswordDataParam, iter) },
{ 0 }
};
static const SEC_ASN1Template NSSLOWPasswordParamTemplate[] = {
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLowPasswordDataParam) },
{ SEC_ASN1_OCTET_STRING, offsetof(NSSLowPasswordDataParam, salt) },
{ SEC_ASN1_INTEGER, offsetof(NSSLowPasswordDataParam, iter) },
{ 0 }
};
struct LGEncryptedDataInfoStr {
SECAlgorithmID algorithm;
SECItem encryptedData;
@ -2251,6 +2250,12 @@ lg_PutMetaData(SDB *sdb, const char *id,
return CKR_OK;
}
CK_RV
lg_DestroyMetaData(SDB *db, const char *id)
{
return CKR_GENERAL_ERROR; /* no extra data stored */
}
CK_RV
lg_Reset(SDB *sdb)
{

View file

@ -879,7 +879,7 @@ lg_FindDSAPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type,
return lg_CopyAttributeSigned(attribute, type,
key->u.dsa.params.base.data,
key->u.dsa.params.base.len);
case CKA_NETSCAPE_DB:
case CKA_NSS_DB:
return lg_CopyAttributeSigned(attribute, type,
key->u.dsa.publicValue.data,
key->u.dsa.publicValue.len);
@ -919,7 +919,7 @@ lg_FindDHPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type,
case CKA_BASE:
return lg_CopyAttributeSigned(attribute, type, key->u.dh.base.data,
key->u.dh.base.len);
case CKA_NETSCAPE_DB:
case CKA_NSS_DB:
return lg_CopyAttributeSigned(attribute, type,
key->u.dh.publicValue.data,
key->u.dh.publicValue.len);
@ -957,7 +957,7 @@ lg_FindECPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type,
return lg_CopyAttributeSigned(attribute, type,
key->u.ec.ecParams.DEREncoding.data,
key->u.ec.ecParams.DEREncoding.len);
case CKA_NETSCAPE_DB:
case CKA_NSS_DB:
return lg_CopyAttributeSigned(attribute, type,
key->u.ec.publicValue.data,
key->u.ec.publicValue.len);
@ -1689,7 +1689,7 @@ lg_SetSingleAttribute(LGObjectCache *obj, const CK_ATTRIBUTE *attr,
CK_ATTRIBUTE attribLocal;
CK_RV crv;
if ((attr->type == CKA_NETSCAPE_DB) && (obj->objclass == CKO_PRIVATE_KEY)) {
if ((attr->type == CKA_NSS_DB) && (obj->objclass == CKO_PRIVATE_KEY)) {
*writePrivate = PR_TRUE;
return CKR_OK;
}

View file

@ -26,11 +26,9 @@ lg_createCertObject(SDB *sdb, CK_OBJECT_HANDLE *handle,
SECItem derCert;
NSSLOWCERTCertificate *cert;
NSSLOWCERTCertTrust *trust = NULL;
NSSLOWCERTCertTrust userTrust =
{ CERTDB_USER, CERTDB_USER, CERTDB_USER };
NSSLOWCERTCertTrust defTrust =
{ CERTDB_TRUSTED_UNKNOWN,
CERTDB_TRUSTED_UNKNOWN, CERTDB_TRUSTED_UNKNOWN };
NSSLOWCERTCertTrust userTrust = { CERTDB_USER, CERTDB_USER, CERTDB_USER };
NSSLOWCERTCertTrust defTrust = { CERTDB_TRUSTED_UNKNOWN,
CERTDB_TRUSTED_UNKNOWN, CERTDB_TRUSTED_UNKNOWN };
char *label = NULL;
char *email = NULL;
SECStatus rv;
@ -574,8 +572,8 @@ lg_mkPrivKey(SDB *sdb, const CK_ATTRIBUTE *templ, CK_ULONG count,
&privKey->u.dsa.privateValue, sdb);
if (crv != CKR_OK)
break;
if (lg_hasAttribute(CKA_NETSCAPE_DB, templ, count)) {
crv = lg_Attribute2SSecItem(arena, CKA_NETSCAPE_DB, templ, count,
if (lg_hasAttribute(CKA_NSS_DB, templ, count)) {
crv = lg_Attribute2SSecItem(arena, CKA_NSS_DB, templ, count,
&privKey->u.dsa.publicValue);
/* privKey was zero'd so public value is already set to NULL, 0
* if we don't set it explicitly */
@ -596,8 +594,8 @@ lg_mkPrivKey(SDB *sdb, const CK_ATTRIBUTE *templ, CK_ULONG count,
&privKey->u.dh.privateValue, sdb);
if (crv != CKR_OK)
break;
if (lg_hasAttribute(CKA_NETSCAPE_DB, templ, count)) {
crv = lg_Attribute2SSecItem(arena, CKA_NETSCAPE_DB, templ, count,
if (lg_hasAttribute(CKA_NSS_DB, templ, count)) {
crv = lg_Attribute2SSecItem(arena, CKA_NSS_DB, templ, count,
&privKey->u.dh.publicValue);
/* privKey was zero'd so public value is already set to NULL, 0
* if we don't set it explicitly */
@ -623,8 +621,8 @@ lg_mkPrivKey(SDB *sdb, const CK_ATTRIBUTE *templ, CK_ULONG count,
&privKey->u.ec.privateValue, sdb);
if (crv != CKR_OK)
break;
if (lg_hasAttribute(CKA_NETSCAPE_DB, templ, count)) {
crv = lg_Attribute2SSecItem(arena, CKA_NETSCAPE_DB, templ, count,
if (lg_hasAttribute(CKA_NSS_DB, templ, count)) {
crv = lg_Attribute2SSecItem(arena, CKA_NSS_DB, templ, count,
&privKey->u.ec.publicValue);
if (crv != CKR_OK)
break;
@ -672,7 +670,7 @@ lg_createPrivateKeyObject(SDB *sdb, CK_KEY_TYPE key_type,
return crv;
label = lg_getString(CKA_LABEL, templ, count);
crv = lg_Attribute2SSecItem(NULL, CKA_NETSCAPE_DB, templ, count, &pubKey);
crv = lg_Attribute2SSecItem(NULL, CKA_NSS_DB, templ, count, &pubKey);
if (crv != CKR_OK) {
crv = CKR_TEMPLATE_INCOMPLETE;
rv = SECFailure;
@ -960,6 +958,22 @@ lg_createKeyObject(SDB *sdb, CK_OBJECT_CLASS objclass,
return CKR_ATTRIBUTE_VALUE_INVALID;
}
/*
* return the 'next' key handle
*/
CK_RV
lg_GetNewObjectID(SDB *sdb, CK_OBJECT_HANDLE *handle)
{
/* the upper level needs the Object ID early to populate any
* signature attributes. The legacy can't really return a new
* handle without the full object template (chicken and egg issue).
* Fortunately we can just return a bogus handle because the legacy
* database doesn't support meta data and can't store any of the signed
* attributes anyway */
*handle = CK_INVALID_HANDLE;
return CKR_OK;
}
/*
* Parse the template and create an object stored in the DB that reflects.
* the object specified in the database.

View file

@ -150,6 +150,8 @@ CK_RV lg_Abort(SDB *sdb);
CK_RV lg_GetMetaData(SDB *sdb, const char *id, SECItem *item1, SECItem *item2);
CK_RV lg_PutMetaData(SDB *sdb, const char *id,
const SECItem *item1, const SECItem *item2);
CK_RV lg_DestroyMetaData(SDB *sdb, const char *id);
CK_RV lg_GetNewObjectID(SDB *sdb, CK_OBJECT_HANDLE *object_id);
SEC_END_PROTOS

View file

@ -666,11 +666,11 @@ lg_searchTokenList(SDB *sdb, SDBFind *search,
case CKA_LABEL:
copy = &name;
break;
case CKA_NETSCAPE_EMAIL:
case CKA_NSS_EMAIL:
copy = &email;
classFlags &= LG_SMIME | LG_CERT;
break;
case CKA_NETSCAPE_SMIME_TIMESTAMP:
case CKA_NSS_SMIME_TIMESTAMP:
classFlags &= LG_SMIME;
break;
case CKA_CLASS:
@ -683,13 +683,13 @@ lg_searchTokenList(SDB *sdb, SDBFind *search,
case CKO_CERTIFICATE:
classFlags &= LG_CERT;
break;
case CKO_NETSCAPE_TRUST:
case CKO_NSS_TRUST:
classFlags &= LG_TRUST;
break;
case CKO_NETSCAPE_CRL:
case CKO_NSS_CRL:
classFlags &= LG_CRL;
break;
case CKO_NETSCAPE_SMIME:
case CKO_NSS_SMIME:
classFlags &= LG_SMIME;
break;
case CKO_PRIVATE_KEY:
@ -761,7 +761,7 @@ lg_searchTokenList(SDB *sdb, SDBFind *search,
copy = &key_id;
classFlags &= (LG_CERT | LG_PRIVATE | LG_KEY | LG_PUBLIC);
break;
case CKA_NETSCAPE_KRL:
case CKA_NSS_KRL:
if (pTemplate[i].ulValueLen != sizeof(CK_BBOOL)) {
classFlags = 0;
break;

View file

@ -37,7 +37,8 @@ static void INIT_FUNCTION lg_startup_tests(void);
#if defined(XP_WIN) && !defined(NSS_NO_INIT_SUPPORT)
#include <windows.h>
BOOL WINAPI DllMain(
BOOL WINAPI
DllMain(
HINSTANCE hinstDLL, // handle to DLL module
DWORD fdwReason, // reason for calling function
LPVOID lpReserved) // reserved

View file

@ -341,7 +341,7 @@ lg_OpenCertDB(const char *configdir, const char *prefix, PRBool readOnly,
NSSLOWCERTCertDBHandle **certdbPtr)
{
NSSLOWCERTCertDBHandle *certdb = NULL;
CK_RV crv = CKR_NETSCAPE_CERTDB_FAILED;
CK_RV crv = CKR_NSS_CERTDB_FAILED;
SECStatus rv;
char *name = NULL;
char *appName = NULL;
@ -401,7 +401,7 @@ lg_OpenKeyDB(const char *configdir, const char *prefix, PRBool readOnly,
if (appName)
PORT_Free(appName);
if (keydb == NULL)
return CKR_NETSCAPE_KEYDB_FAILED;
return CKR_NSS_KEYDB_FAILED;
*keydbPtr = keydb;
return CKR_OK;
@ -520,7 +520,7 @@ lg_init(SDB **pSdb, int flags, NSSLOWCERTCertDBHandle *certdbPtr,
}
sdb->private = lgdb_p;
sdb->version = 0;
sdb->version = 1;
sdb->sdb_flags = flags;
sdb->app_private = NULL;
sdb->sdb_FindObjectsInit = lg_FindObjectsInit;
@ -532,12 +532,14 @@ lg_init(SDB **pSdb, int flags, NSSLOWCERTCertDBHandle *certdbPtr,
sdb->sdb_DestroyObject = lg_DestroyObject;
sdb->sdb_GetMetaData = lg_GetMetaData;
sdb->sdb_PutMetaData = lg_PutMetaData;
sdb->sdb_DestroyMetaData = lg_DestroyMetaData;
sdb->sdb_Begin = lg_Begin;
sdb->sdb_Commit = lg_Commit;
sdb->sdb_Abort = lg_Abort;
sdb->sdb_Reset = lg_Reset;
sdb->sdb_Close = lg_Close;
sdb->sdb_SetForkState = lg_SetForkState;
sdb->sdb_GetNewObjectID = lg_GetNewObjectID;
*pSdb = sdb;
return CKR_OK;

View file

@ -10,7 +10,7 @@ REQUIRES = dbm
LIBRARY_NAME = nssdbm
LIBRARY_VERSION = 3
MAPFILE = $(OBJDIR)/nssdbm.def
MAPFILE = $(OBJDIR)/$(LIBRARY_NAME).def
DEFINES += -DSHLIB_SUFFIX=\"$(DLL_SUFFIX)\" -DSHLIB_PREFIX=\"$(DLL_PREFIX)\" -DLG_LIB_NAME=\"$(notdir $(SHARED_LIBRARY))\"

View file

@ -4277,6 +4277,7 @@ CreateTrust(void)
if (trust) {
trustListCount--;
trustListHead = trust->next;
trust->next = NULL;
}
PORT_Assert(trustListCount >= 0);
nsslowcert_UnlockFreeList();
@ -5160,9 +5161,11 @@ nsslowcert_hasTrust(NSSLOWCERTCertTrust *trust)
if (trust == NULL) {
return PR_FALSE;
}
return !((trust->sslFlags & CERTDB_TRUSTED_UNKNOWN) &&
(trust->emailFlags & CERTDB_TRUSTED_UNKNOWN) &&
(trust->objectSigningFlags & CERTDB_TRUSTED_UNKNOWN));
/* if we only have CERTDB__USER and CERTDB_TRUSTED_UNKNOWN bits, then
* we don't have a trust record. */
return !(((trust->sslFlags & ~(CERTDB_USER | CERTDB_TRUSTED_UNKNOWN)) == 0) &&
((trust->emailFlags & ~(CERTDB_USER | CERTDB_TRUSTED_UNKNOWN)) == 0) &&
((trust->objectSigningFlags & ~(CERTDB_USER | CERTDB_TRUSTED_UNKNOWN)) == 0));
}
/*

View file

@ -205,7 +205,8 @@ sftkdb_encrypt_stub(PLArenaPool *arena, SDB *sdb, SECItem *plainText,
iterationCount = 1;
}
rv = sftkdb_EncryptAttribute(arena, key, iterationCount,
rv = sftkdb_EncryptAttribute(arena, handle, sdb, key, iterationCount,
CK_INVALID_HANDLE, CKT_INVALID_TYPE,
plainText, cipherText);
PZ_Unlock(handle->passwordLock);
@ -227,7 +228,7 @@ sftkdb_decrypt_stub(SDB *sdb, SECItem *cipherText, SECItem **plainText)
return SECFailure;
}
/* if we aren't th handle, try the other handle */
/* if we aren't the key handle, try the other handle */
oldKey = handle->oldKey;
if (handle->type != SFTK_KEYDB_TYPE) {
handle = handle->peerDB;
@ -244,7 +245,9 @@ sftkdb_decrypt_stub(SDB *sdb, SECItem *cipherText, SECItem **plainText)
/* PORT_SetError */
return SECFailure;
}
rv = sftkdb_DecryptAttribute(oldKey ? oldKey : &handle->passwordKey,
rv = sftkdb_DecryptAttribute(NULL, oldKey ? oldKey : &handle->passwordKey,
CK_INVALID_HANDLE,
CKT_INVALID_TYPE,
cipherText, plainText);
PZ_Unlock(handle->passwordLock);

View file

@ -220,21 +220,24 @@ void
nsslowkey_DestroyPublicKey(NSSLOWKEYPublicKey *pubk)
{
if (pubk && pubk->arena) {
PORT_FreeArena(pubk->arena, PR_FALSE);
PORT_FreeArena(pubk->arena, PR_TRUE);
}
}
unsigned
nsslowkey_PublicModulusLen(NSSLOWKEYPublicKey *pubk)
{
unsigned char b0;
/* interpret modulus length as key strength... in
* fortezza that's the public key length */
switch (pubk->keyType) {
case NSSLOWKEYRSAKey:
b0 = pubk->u.rsa.modulus.data[0];
return b0 ? pubk->u.rsa.modulus.len : pubk->u.rsa.modulus.len - 1;
if (pubk->u.rsa.modulus.len == 0) {
return 0;
}
if (pubk->u.rsa.modulus.data[0] == 0) {
return pubk->u.rsa.modulus.len - 1;
}
return pubk->u.rsa.modulus.len;
default:
break;
}
@ -244,13 +247,15 @@ nsslowkey_PublicModulusLen(NSSLOWKEYPublicKey *pubk)
unsigned
nsslowkey_PrivateModulusLen(NSSLOWKEYPrivateKey *privk)
{
unsigned char b0;
switch (privk->keyType) {
case NSSLOWKEYRSAKey:
b0 = privk->u.rsa.modulus.data[0];
return b0 ? privk->u.rsa.modulus.len : privk->u.rsa.modulus.len - 1;
if (privk->u.rsa.modulus.len == 0) {
return 0;
}
if (privk->u.rsa.modulus.data[0] == 0) {
return privk->u.rsa.modulus.len - 1;
}
return privk->u.rsa.modulus.len;
default:
break;
}
@ -310,7 +315,7 @@ nsslowkey_ConvertToPublicKey(NSSLOWKEYPrivateKey *privk)
break;
}
rv = SECITEM_CopyItem(privk->arena, &privk->u.dsa.publicValue, &publicValue);
SECITEM_FreeItem(&publicValue, PR_FALSE);
SECITEM_ZfreeItem(&publicValue, PR_FALSE);
if (rv != SECSuccess) {
break;
}
@ -349,7 +354,7 @@ nsslowkey_ConvertToPublicKey(NSSLOWKEYPrivateKey *privk)
break;
}
rv = SECITEM_CopyItem(privk->arena, &privk->u.dh.publicValue, &publicValue);
SECITEM_FreeItem(&publicValue, PR_FALSE);
SECITEM_ZfreeItem(&publicValue, PR_FALSE);
if (rv != SECSuccess) {
break;
}
@ -394,7 +399,7 @@ nsslowkey_ConvertToPublicKey(NSSLOWKEYPrivateKey *privk)
break;
}
PORT_FreeArena(arena, PR_FALSE);
PORT_FreeArena(arena, PR_TRUE);
return NULL;
}

View file

@ -22,28 +22,29 @@
SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate)
/* how much a crypto encrypt/decryption may expand a buffer */
#define MAX_CRYPTO_EXPANSION 64
/* template for PKCS 5 PBE Parameter. This template has been expanded
* based upon the additions in PKCS 12. This should eventually be moved
* if RSA updates PKCS 5.
*/
static const SEC_ASN1Template NSSPKCS5PBEParameterTemplate[] =
{
{ SEC_ASN1_SEQUENCE,
0, NULL, sizeof(NSSPKCS5PBEParameter) },
{ SEC_ASN1_OCTET_STRING,
offsetof(NSSPKCS5PBEParameter, salt) },
{ SEC_ASN1_INTEGER,
offsetof(NSSPKCS5PBEParameter, iteration) },
{ 0 }
};
static const SEC_ASN1Template NSSPKCS5PBEParameterTemplate[] = {
{ SEC_ASN1_SEQUENCE,
0, NULL, sizeof(NSSPKCS5PBEParameter) },
{ SEC_ASN1_OCTET_STRING,
offsetof(NSSPKCS5PBEParameter, salt) },
{ SEC_ASN1_INTEGER,
offsetof(NSSPKCS5PBEParameter, iteration) },
{ 0 }
};
static const SEC_ASN1Template NSSPKCS5PKCS12V2PBEParameterTemplate[] =
{
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSPKCS5PBEParameter) },
{ SEC_ASN1_OCTET_STRING, offsetof(NSSPKCS5PBEParameter, salt) },
{ SEC_ASN1_INTEGER, offsetof(NSSPKCS5PBEParameter, iteration) },
{ 0 }
};
static const SEC_ASN1Template NSSPKCS5PKCS12V2PBEParameterTemplate[] = {
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSPKCS5PBEParameter) },
{ SEC_ASN1_OCTET_STRING, offsetof(NSSPKCS5PBEParameter, salt) },
{ SEC_ASN1_INTEGER, offsetof(NSSPKCS5PBEParameter, iteration) },
{ 0 }
};
/* PKCS5 v2 */
@ -54,31 +55,29 @@ struct nsspkcs5V2PBEParameterStr {
typedef struct nsspkcs5V2PBEParameterStr nsspkcs5V2PBEParameter;
static const SEC_ASN1Template NSSPKCS5V2PBES2ParameterTemplate[] =
{
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(nsspkcs5V2PBEParameter) },
{ SEC_ASN1_INLINE | SEC_ASN1_XTRN,
offsetof(nsspkcs5V2PBEParameter, keyParams),
SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
{ SEC_ASN1_INLINE | SEC_ASN1_XTRN,
offsetof(nsspkcs5V2PBEParameter, algParams),
SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
{ 0 }
};
static const SEC_ASN1Template NSSPKCS5V2PBES2ParameterTemplate[] = {
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(nsspkcs5V2PBEParameter) },
{ SEC_ASN1_INLINE | SEC_ASN1_XTRN,
offsetof(nsspkcs5V2PBEParameter, keyParams),
SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
{ SEC_ASN1_INLINE | SEC_ASN1_XTRN,
offsetof(nsspkcs5V2PBEParameter, algParams),
SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
{ 0 }
};
static const SEC_ASN1Template NSSPKCS5V2PBEParameterTemplate[] =
{
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSPKCS5PBEParameter) },
/* this is really a choice, but since we don't understand any other
static const SEC_ASN1Template NSSPKCS5V2PBEParameterTemplate[] = {
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSPKCS5PBEParameter) },
/* this is really a choice, but since we don't understand any other
* choice, just inline it. */
{ SEC_ASN1_OCTET_STRING, offsetof(NSSPKCS5PBEParameter, salt) },
{ SEC_ASN1_INTEGER, offsetof(NSSPKCS5PBEParameter, iteration) },
{ SEC_ASN1_INTEGER, offsetof(NSSPKCS5PBEParameter, keyLength) },
{ SEC_ASN1_INLINE | SEC_ASN1_XTRN,
offsetof(NSSPKCS5PBEParameter, prfAlg),
SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
{ 0 }
};
{ SEC_ASN1_OCTET_STRING, offsetof(NSSPKCS5PBEParameter, salt) },
{ SEC_ASN1_INTEGER, offsetof(NSSPKCS5PBEParameter, iteration) },
{ SEC_ASN1_INTEGER, offsetof(NSSPKCS5PBEParameter, keyLength) },
{ SEC_ASN1_INLINE | SEC_ASN1_XTRN,
offsetof(NSSPKCS5PBEParameter, prfAlg),
SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
{ 0 }
};
SECStatus
nsspkcs5_HashBuf(const SECHashObject *hashObj, unsigned char *dest,
@ -161,11 +160,11 @@ nsspkcs5_PBKDF1(const SECHashObject *hashObj, SECItem *salt, SECItem *pwd,
}
if (pre_hash != NULL) {
SECITEM_FreeItem(pre_hash, PR_TRUE);
SECITEM_ZfreeItem(pre_hash, PR_TRUE);
}
if ((rv != SECSuccess) && (hash != NULL)) {
SECITEM_FreeItem(hash, PR_TRUE);
SECITEM_ZfreeItem(hash, PR_TRUE);
hash = NULL;
}
@ -294,7 +293,7 @@ nsspkcs5_PBKDF1Extended(const SECHashObject *hashObj,
newHash = nsspkcs5_PFXPBE(hashObj, pbe_param, hash, bytes_needed);
if (hash != newHash)
SECITEM_FreeItem(hash, PR_TRUE);
SECITEM_ZfreeItem(hash, PR_TRUE);
return newHash;
}
@ -400,7 +399,7 @@ loser:
PORT_ZFree(T, hLen);
}
if (rv != SECSuccess) {
SECITEM_FreeItem(result, PR_TRUE);
SECITEM_ZfreeItem(result, PR_TRUE);
result = NULL;
} else {
result->len = dkLen;
@ -567,6 +566,7 @@ typedef struct KDFCacheItemStr KDFCacheItem;
/* Bug 1606992 - Cache the hash result for the common case that we're
* asked to repeatedly compute the key for the same password item,
* hash, iterations and salt. */
#define KDF2_CACHE_COUNT 150
static struct {
PZLock *lock;
struct {
@ -575,7 +575,8 @@ static struct {
PRBool faulty3DES;
} cacheKDF1;
struct {
KDFCacheItem common;
KDFCacheItem common[KDF2_CACHE_COUNT];
int next;
} cacheKDF2;
} PBECache;
@ -595,7 +596,7 @@ sftk_clearPBECommonCacheItemsLocked(KDFCacheItem *item)
item->hash = NULL;
}
if (item->salt) {
SECITEM_FreeItem(item->salt, PR_TRUE);
SECITEM_ZfreeItem(item->salt, PR_TRUE);
item->salt = NULL;
}
if (item->pwItem) {
@ -604,7 +605,7 @@ sftk_clearPBECommonCacheItemsLocked(KDFCacheItem *item)
}
}
static SECStatus
static void
sftk_setPBECommonCacheItemsKDFLocked(KDFCacheItem *cacheItem,
const SECItem *hash,
const NSSPKCS5PBEParameter *pbe_param,
@ -616,8 +617,6 @@ sftk_setPBECommonCacheItemsKDFLocked(KDFCacheItem *cacheItem,
cacheItem->keyLen = pbe_param->keyLen;
cacheItem->salt = SECITEM_DupItem(&pbe_param->salt);
cacheItem->pwItem = SECITEM_DupItem(pwItem);
return SECSuccess;
}
static void
@ -626,12 +625,18 @@ sftk_setPBECacheKDF2(const SECItem *hash,
const SECItem *pwItem)
{
PZ_Lock(PBECache.lock);
sftk_clearPBECommonCacheItemsLocked(&PBECache.cacheKDF2.common);
sftk_setPBECommonCacheItemsKDFLocked(&PBECache.cacheKDF2.common,
hash, pbe_param, pwItem);
KDFCacheItem *next = &PBECache.cacheKDF2.common[PBECache.cacheKDF2.next];
sftk_clearPBECommonCacheItemsLocked(next);
sftk_setPBECommonCacheItemsKDFLocked(next, hash, pbe_param, pwItem);
PBECache.cacheKDF2.next++;
if (PBECache.cacheKDF2.next >= KDF2_CACHE_COUNT) {
PBECache.cacheKDF2.next = 0;
}
PZ_Unlock(PBECache.lock);
}
}
static void
sftk_setPBECacheKDF1(const SECItem *hash,
@ -671,11 +676,16 @@ sftk_getPBECacheKDF2(const NSSPKCS5PBEParameter *pbe_param,
const SECItem *pwItem)
{
SECItem *result = NULL;
const KDFCacheItem *cacheItem = &PBECache.cacheKDF2.common;
int i;
PZ_Lock(PBECache.lock);
if (sftk_comparePBECommonCacheItemLocked(cacheItem, pbe_param, pwItem)) {
result = SECITEM_DupItem(cacheItem->hash);
for (i = 0; i < KDF2_CACHE_COUNT; i++) {
const KDFCacheItem *cacheItem = &PBECache.cacheKDF2.common[i];
if (sftk_comparePBECommonCacheItemLocked(cacheItem,
pbe_param, pwItem)) {
result = SECITEM_DupItem(cacheItem->hash);
break;
}
}
PZ_Unlock(PBECache.lock);
@ -701,16 +711,19 @@ sftk_getPBECacheKDF1(const NSSPKCS5PBEParameter *pbe_param,
return result;
}
void
sftk_PBELockShutdown(void)
{
int i;
if (PBECache.lock) {
PZ_DestroyLock(PBECache.lock);
PBECache.lock = 0;
}
sftk_clearPBECommonCacheItemsLocked(&PBECache.cacheKDF1.common);
sftk_clearPBECommonCacheItemsLocked(&PBECache.cacheKDF2.common);
for (i = 0; i < KDF2_CACHE_COUNT; i++) {
sftk_clearPBECommonCacheItemsLocked(&PBECache.cacheKDF2.common[i]);
}
PBECache.cacheKDF2.next = 0;
}
/*
@ -811,11 +824,49 @@ loser:
return NULL;
}
#define MAX_IV_LENGTH 64
/* get a random IV into the parameters */
static SECStatus
nsspkcs5_SetIVParam(NSSPKCS5PBEParameter *pbe_param, int ivLen)
{
SECStatus rv;
SECItem derIV;
SECItem iv;
SECItem *dummy = NULL;
unsigned char ivData[MAX_IV_LENGTH];
PORT_Assert(ivLen <= MAX_IV_LENGTH);
/* Because of a bug in the decode section, the IV's not are expected
* to be der encoded, but still need to parse as if they were der data.
* because we want to be compatible with existing versions of nss that
* have that bug, create an IV that looks like der data. That still
* leaves 14 bytes of entropy in the IV */
rv = RNG_GenerateGlobalRandomBytes(ivData, ivLen - 2);
if (rv != SECSuccess) {
return SECFailure;
}
derIV.data = NULL;
derIV.len = 0;
iv.data = ivData;
iv.len = ivLen - 2;
dummy = SEC_ASN1EncodeItem(pbe_param->poolp, &derIV, &iv,
SEC_ASN1_GET(SEC_OctetStringTemplate));
if (dummy == NULL) {
return SECFailure;
}
pbe_param->ivData = derIV.data;
pbe_param->ivLen = derIV.len;
PORT_Assert(pbe_param->ivLen == ivLen);
return SECSuccess;
}
static SECStatus
nsspkcs5_FillInParam(SECOidTag algorithm, HASH_HashType hashType,
NSSPKCS5PBEParameter *pbe_param)
{
PRBool skipType = PR_FALSE;
SECStatus rv;
pbe_param->keyLen = 5;
pbe_param->ivLen = 8;
@ -849,6 +900,7 @@ nsspkcs5_FillInParam(SECOidTag algorithm, HASH_HashType hashType,
pbe_param->encAlg = SEC_OID_DES_CBC;
break;
#ifndef NSS_DISABLE_DEPRECATED_RC2
/* RC2 Algorithms */
case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
pbe_param->keyLen = 16;
@ -861,6 +913,7 @@ nsspkcs5_FillInParam(SECOidTag algorithm, HASH_HashType hashType,
/* fall through */
case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
break;
#endif
/* RC4 algorithms */
case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4:
@ -888,11 +941,68 @@ nsspkcs5_FillInParam(SECOidTag algorithm, HASH_HashType hashType,
pbe_param->encAlg = SEC_OID_PKCS5_PBKDF2;
pbe_param->keyLen = 0; /* needs to be set by caller after return */
break;
/* AES uses PBKDF2 */
case SEC_OID_AES_128_CBC:
rv = nsspkcs5_SetIVParam(pbe_param, 16);
if (rv != SECSuccess) {
return rv;
}
pbe_param->ivLen = 16;
pbe_param->pbeType = NSSPKCS5_PBKDF2;
pbe_param->encAlg = algorithm;
pbe_param->keyLen = 128 / 8;
break;
case SEC_OID_AES_192_CBC:
rv = nsspkcs5_SetIVParam(pbe_param, 16);
if (rv != SECSuccess) {
return rv;
}
pbe_param->pbeType = NSSPKCS5_PBKDF2;
pbe_param->encAlg = algorithm;
pbe_param->keyLen = 192 / 8;
break;
case SEC_OID_AES_256_CBC:
rv = nsspkcs5_SetIVParam(pbe_param, 16);
if (rv != SECSuccess) {
return rv;
}
pbe_param->pbeType = NSSPKCS5_PBKDF2;
pbe_param->encAlg = algorithm;
pbe_param->keyLen = 256 / 8;
break;
case SEC_OID_AES_128_KEY_WRAP:
pbe_param->ivLen = 0;
pbe_param->pbeType = NSSPKCS5_PBKDF2;
pbe_param->encAlg = algorithm;
pbe_param->keyLen = 128 / 8;
break;
case SEC_OID_AES_192_KEY_WRAP:
pbe_param->ivLen = 0;
pbe_param->pbeType = NSSPKCS5_PBKDF2;
pbe_param->encAlg = algorithm;
pbe_param->keyLen = 192 / 8;
break;
case SEC_OID_AES_256_KEY_WRAP:
pbe_param->ivLen = 0;
pbe_param->pbeType = NSSPKCS5_PBKDF2;
pbe_param->encAlg = algorithm;
pbe_param->keyLen = 256 / 8;
break;
default:
return SECFailure;
}
if (pbe_param->pbeType == NSSPKCS5_PBKDF2) {
SECOidTag prfAlg = HASH_HMACOidFromHash(pbe_param->hashType);
if (prfAlg == SEC_OID_UNKNOWN) {
return SECFailure;
}
rv = SECOID_SetAlgorithmID(pbe_param->poolp, &pbe_param->prfAlg,
prfAlg, NULL);
if (rv != SECSuccess) {
return rv;
}
}
return SECSuccess;
}
@ -965,6 +1075,29 @@ HASH_FromHMACOid(SECOidTag hmac)
return HASH_AlgNULL;
}
SECOidTag
HASH_HMACOidFromHash(HASH_HashType hashType)
{
switch (hashType) {
case HASH_AlgSHA1:
return SEC_OID_HMAC_SHA1;
case HASH_AlgSHA256:
return SEC_OID_HMAC_SHA256;
case HASH_AlgSHA384:
return SEC_OID_HMAC_SHA384;
case HASH_AlgSHA512:
return SEC_OID_HMAC_SHA512;
case HASH_AlgSHA224:
return SEC_OID_HMAC_SHA224;
case HASH_AlgMD2:
case HASH_AlgMD5:
case HASH_AlgTOTAL:
default:
break;
}
return SEC_OID_UNKNOWN;
}
/* decode the algid and generate a PKCS 5 parameter from it
*/
NSSPKCS5PBEParameter *
@ -1037,6 +1170,7 @@ nsspkcs5_AlgidToParam(SECAlgorithmID *algid)
}
loser:
PORT_Memset(&pbev2_param, 0, sizeof(pbev2_param));
if (rv == SECSuccess) {
pbe_param->iter = DER_GetInteger(&pbe_param->iteration);
} else {
@ -1055,7 +1189,7 @@ void
nsspkcs5_DestroyPBEParameter(NSSPKCS5PBEParameter *pbe_param)
{
if (pbe_param != NULL) {
PORT_FreeArena(pbe_param->poolp, PR_FALSE);
PORT_FreeArena(pbe_param->poolp, PR_TRUE);
}
}
@ -1069,11 +1203,16 @@ sec_pkcs5_des(SECItem *key, SECItem *iv, SECItem *src, PRBool triple_des,
{
SECItem *dest;
SECItem *dup_src;
CK_RV crv = CKR_DEVICE_ERROR;
int error;
SECStatus rv = SECFailure;
int pad;
DESContext *ctxt;
unsigned int pad;
if ((src == NULL) || (key == NULL) || (iv == NULL))
if ((src == NULL) || (key == NULL) || (iv == NULL)) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return NULL;
}
dup_src = SECITEM_DupItem(src);
if (dup_src == NULL) {
@ -1084,58 +1223,49 @@ sec_pkcs5_des(SECItem *key, SECItem *iv, SECItem *src, PRBool triple_des,
void *dummy;
dummy = CBC_PadBuffer(NULL, dup_src->data,
dup_src->len, &dup_src->len, 8 /* DES_BLOCK_SIZE */);
dup_src->len, &dup_src->len, DES_BLOCK_SIZE);
if (dummy == NULL) {
SECITEM_FreeItem(dup_src, PR_TRUE);
SECITEM_ZfreeItem(dup_src, PR_TRUE);
return NULL;
}
dup_src->data = (unsigned char *)dummy;
}
dest = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
if (dest != NULL) {
/* allocate with over flow */
dest->data = (unsigned char *)PORT_ZAlloc(dup_src->len + 64);
if (dest->data != NULL) {
DESContext *ctxt;
ctxt = DES_CreateContext(key->data, iv->data,
(triple_des ? NSS_DES_EDE3_CBC : NSS_DES_CBC),
encrypt);
if (ctxt != NULL) {
rv = (encrypt ? DES_Encrypt : DES_Decrypt)(
ctxt, dest->data, &dest->len,
dup_src->len + 64, dup_src->data, dup_src->len);
/* remove padding -- assumes 64 bit blocks */
if ((encrypt == PR_FALSE) && (rv == SECSuccess)) {
pad = dest->data[dest->len - 1];
if ((pad > 0) && (pad <= 8)) {
if (dest->data[dest->len - pad] != pad) {
rv = SECFailure;
PORT_SetError(SEC_ERROR_BAD_PASSWORD);
} else {
dest->len -= pad;
}
} else {
rv = SECFailure;
PORT_SetError(SEC_ERROR_BAD_PASSWORD);
}
}
DES_DestroyContext(ctxt, PR_TRUE);
}
}
dest = SECITEM_AllocItem(NULL, NULL, dup_src->len + MAX_CRYPTO_EXPANSION);
if (dest == NULL) {
goto loser;
}
ctxt = DES_CreateContext(key->data, iv->data,
(triple_des ? NSS_DES_EDE3_CBC : NSS_DES_CBC),
encrypt);
if (ctxt == NULL) {
goto loser;
}
rv = (encrypt ? DES_Encrypt : DES_Decrypt)(
ctxt, dest->data, &dest->len,
dest->len, dup_src->data, dup_src->len);
if (rv == SECFailure) {
crv = (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR;
error = PORT_GetError();
/* remove padding */
if ((encrypt == PR_FALSE) && (rv == SECSuccess)) {
crv = sftk_CheckCBCPadding(dest->data, dest->len, DES_BLOCK_SIZE, &pad);
dest->len = PORT_CT_SEL(sftk_CKRVToMask(crv), dest->len - pad, dest->len);
PORT_SetError(PORT_CT_SEL(sftk_CKRVToMask(crv), error, SEC_ERROR_BAD_PASSWORD));
}
DES_DestroyContext(ctxt, PR_TRUE);
loser:
if (crv != CKR_OK) {
if (dest != NULL) {
SECITEM_FreeItem(dest, PR_TRUE);
SECITEM_ZfreeItem(dest, PR_TRUE);
}
dest = NULL;
}
if (dup_src != NULL) {
SECITEM_FreeItem(dup_src, PR_TRUE);
SECITEM_ZfreeItem(dup_src, PR_TRUE);
}
return dest;
@ -1149,11 +1279,16 @@ sec_pkcs5_aes(SECItem *key, SECItem *iv, SECItem *src, PRBool triple_des,
{
SECItem *dest;
SECItem *dup_src;
CK_RV crv = CKR_DEVICE_ERROR;
int error;
SECStatus rv = SECFailure;
int pad;
AESContext *ctxt;
unsigned int pad;
if ((src == NULL) || (key == NULL) || (iv == NULL))
if ((src == NULL) || (key == NULL) || (iv == NULL)) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return NULL;
}
dup_src = SECITEM_DupItem(src);
if (dup_src == NULL) {
@ -1166,60 +1301,128 @@ sec_pkcs5_aes(SECItem *key, SECItem *iv, SECItem *src, PRBool triple_des,
dummy = CBC_PadBuffer(NULL, dup_src->data,
dup_src->len, &dup_src->len, AES_BLOCK_SIZE);
if (dummy == NULL) {
SECITEM_FreeItem(dup_src, PR_TRUE);
SECITEM_ZfreeItem(dup_src, PR_TRUE);
return NULL;
}
dup_src->data = (unsigned char *)dummy;
}
dest = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
if (dest != NULL) {
/* allocate with over flow */
dest->data = (unsigned char *)PORT_ZAlloc(dup_src->len + 64);
if (dest->data != NULL) {
AESContext *ctxt;
ctxt = AES_CreateContext(key->data, iv->data,
NSS_AES_CBC, encrypt, key->len, 16);
if (ctxt != NULL) {
rv = (encrypt ? AES_Encrypt : AES_Decrypt)(
ctxt, dest->data, &dest->len,
dup_src->len + 64, dup_src->data, dup_src->len);
/* remove padding -- assumes 64 bit blocks */
if ((encrypt == PR_FALSE) && (rv == SECSuccess)) {
pad = dest->data[dest->len - 1];
if ((pad > 0) && (pad <= 16)) {
if (dest->data[dest->len - pad] != pad) {
rv = SECFailure;
PORT_SetError(SEC_ERROR_BAD_PASSWORD);
} else {
dest->len -= pad;
}
} else {
rv = SECFailure;
PORT_SetError(SEC_ERROR_BAD_PASSWORD);
}
}
AES_DestroyContext(ctxt, PR_TRUE);
}
}
dest = SECITEM_AllocItem(NULL, NULL, dup_src->len + MAX_CRYPTO_EXPANSION);
if (dest == NULL) {
goto loser;
}
ctxt = AES_CreateContext(key->data, iv->data, NSS_AES_CBC,
encrypt, key->len, AES_BLOCK_SIZE);
if (ctxt == NULL) {
goto loser;
}
rv = (encrypt ? AES_Encrypt : AES_Decrypt)(
ctxt, dest->data, &dest->len,
dest->len, dup_src->data, dup_src->len);
if (rv == SECFailure) {
crv = (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR;
error = PORT_GetError();
/* remove padding */
if ((encrypt == PR_FALSE) && (rv == SECSuccess)) {
crv = sftk_CheckCBCPadding(dest->data, dest->len, AES_BLOCK_SIZE, &pad);
dest->len = PORT_CT_SEL(sftk_CKRVToMask(crv), dest->len - pad, dest->len);
PORT_SetError(PORT_CT_SEL(sftk_CKRVToMask(crv), error, SEC_ERROR_BAD_PASSWORD));
}
AES_DestroyContext(ctxt, PR_TRUE);
loser:
if (crv != CKR_OK) {
if (dest != NULL) {
SECITEM_FreeItem(dest, PR_TRUE);
SECITEM_ZfreeItem(dest, PR_TRUE);
}
dest = NULL;
}
if (dup_src != NULL) {
SECITEM_FreeItem(dup_src, PR_TRUE);
SECITEM_ZfreeItem(dup_src, PR_TRUE);
}
return dest;
}
/* perform aes encryption/decryption if an error occurs, NULL is returned
*/
static SECItem *
sec_pkcs5_aes_key_wrap(SECItem *key, SECItem *iv, SECItem *src, PRBool triple_des,
PRBool encrypt)
{
SECItem *dest;
SECItem *dup_src;
CK_RV crv = CKR_DEVICE_ERROR;
int error;
SECStatus rv = SECFailure;
AESKeyWrapContext *ctxt;
unsigned int pad;
if ((src == NULL) || (key == NULL) || (iv == NULL)) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return NULL;
}
dup_src = SECITEM_DupItem(src);
if (dup_src == NULL) {
return NULL;
}
if (encrypt != PR_FALSE) {
void *dummy;
dummy = CBC_PadBuffer(NULL, dup_src->data,
dup_src->len, &dup_src->len, AES_BLOCK_SIZE);
if (dummy == NULL) {
SECITEM_ZfreeItem(dup_src, PR_TRUE);
return NULL;
}
dup_src->data = (unsigned char *)dummy;
}
dest = SECITEM_AllocItem(NULL, NULL, dup_src->len + MAX_CRYPTO_EXPANSION);
if (dest == NULL) {
goto loser;
}
ctxt = AESKeyWrap_CreateContext(key->data, iv->data, encrypt,
key->len);
if (ctxt == NULL) {
goto loser;
}
rv = (encrypt ? AESKeyWrap_Encrypt : AESKeyWrap_Decrypt)(
ctxt, dest->data, &dest->len,
dest->len, dup_src->data, dup_src->len);
crv = (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR;
error = PORT_GetError();
/* remove padding */
if ((encrypt == PR_FALSE) && (rv == SECSuccess)) {
crv = sftk_CheckCBCPadding(dest->data, dest->len, AES_BLOCK_SIZE, &pad);
dest->len = PORT_CT_SEL(sftk_CKRVToMask(crv), dest->len - pad, dest->len);
PORT_SetError(PORT_CT_SEL(sftk_CKRVToMask(crv), error, SEC_ERROR_BAD_PASSWORD));
}
AESKeyWrap_DestroyContext(ctxt, PR_TRUE);
loser:
if (crv != CKR_OK) {
if (dest != NULL) {
SECITEM_ZfreeItem(dest, PR_TRUE);
}
dest = NULL;
}
if (dup_src != NULL) {
SECITEM_ZfreeItem(dup_src, PR_TRUE);
}
return dest;
}
#ifndef NSS_DISABLE_DEPRECATED_RC2
/* perform rc2 encryption/decryption if an error occurs, NULL is returned
*/
static SECItem *
@ -1232,6 +1435,7 @@ sec_pkcs5_rc2(SECItem *key, SECItem *iv, SECItem *src, PRBool dummy,
int pad;
if ((src == NULL) || (key == NULL) || (iv == NULL)) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return NULL;
}
@ -1246,7 +1450,7 @@ sec_pkcs5_rc2(SECItem *key, SECItem *iv, SECItem *src, PRBool dummy,
v = CBC_PadBuffer(NULL, dup_src->data,
dup_src->len, &dup_src->len, 8 /* RC2_BLOCK_SIZE */);
if (v == NULL) {
SECITEM_FreeItem(dup_src, PR_TRUE);
SECITEM_ZfreeItem(dup_src, PR_TRUE);
return NULL;
}
dup_src->data = (unsigned char *)v;
@ -1286,16 +1490,17 @@ sec_pkcs5_rc2(SECItem *key, SECItem *iv, SECItem *src, PRBool dummy,
}
if ((rv != SECSuccess) && (dest != NULL)) {
SECITEM_FreeItem(dest, PR_TRUE);
SECITEM_ZfreeItem(dest, PR_TRUE);
dest = NULL;
}
if (dup_src != NULL) {
SECITEM_FreeItem(dup_src, PR_TRUE);
SECITEM_ZfreeItem(dup_src, PR_TRUE);
}
return dest;
}
#endif /* NSS_DISABLE_DEPRECATED_RC2 */
/* perform rc4 encryption and decryption */
static SECItem *
@ -1306,6 +1511,7 @@ sec_pkcs5_rc4(SECItem *key, SECItem *iv, SECItem *src, PRBool dummy_op,
SECStatus rv = SECFailure;
if ((src == NULL) || (key == NULL) || (iv == NULL)) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return NULL;
}
@ -1327,7 +1533,7 @@ sec_pkcs5_rc4(SECItem *key, SECItem *iv, SECItem *src, PRBool dummy_op,
}
if ((rv != SECSuccess) && (dest)) {
SECITEM_FreeItem(dest, PR_TRUE);
SECITEM_ZfreeItem(dest, PR_TRUE);
dest = NULL;
}
@ -1360,6 +1566,7 @@ nsspkcs5_CipherData(NSSPKCS5PBEParameter *pbe_param, SECItem *pwitem,
}
if ((pwitem == NULL) || (src == NULL)) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return NULL;
}
@ -1371,6 +1578,11 @@ nsspkcs5_CipherData(NSSPKCS5PBEParameter *pbe_param, SECItem *pwitem,
switch (pbe_param->encAlg) {
/* PKCS 5 v2 only */
case SEC_OID_AES_128_KEY_WRAP:
case SEC_OID_AES_192_KEY_WRAP:
case SEC_OID_AES_256_KEY_WRAP:
cryptof = sec_pkcs5_aes_key_wrap;
break;
case SEC_OID_AES_128_CBC:
case SEC_OID_AES_192_CBC:
case SEC_OID_AES_256_CBC:
@ -1384,9 +1596,11 @@ nsspkcs5_CipherData(NSSPKCS5PBEParameter *pbe_param, SECItem *pwitem,
cryptof = sec_pkcs5_des;
tripleDES = PR_FALSE;
break;
#ifndef NSS_DISABLE_DEPRECATED_RC2
case SEC_OID_RC2_CBC:
cryptof = sec_pkcs5_rc2;
break;
#endif
case SEC_OID_RC4:
cryptof = sec_pkcs5_rc4;
break;
@ -1408,8 +1622,8 @@ nsspkcs5_CipherData(NSSPKCS5PBEParameter *pbe_param, SECItem *pwitem,
* The case can only happen on decrypted of a
* SEC_OID_DES_EDE3_CBD.
*/
if ((dest == NULL) && (encrypt == PR_FALSE) &&
(pbe_param->encAlg == SEC_OID_DES_EDE3_CBC)) {
if ((pbe_param->encAlg == SEC_OID_DES_EDE3_CBC) &&
(dest == NULL) && (encrypt == PR_FALSE)) {
dest = (*cryptof)(key, &iv, src, PR_FALSE, encrypt);
if (update && (dest != NULL))
*update = PR_TRUE;
@ -1499,10 +1713,19 @@ nsspkcs5_CreateAlgorithmID(PLArenaPool *arena, SECOidTag algorithm,
rv = SECOID_SetAlgorithmID(arena, &pkcs5v2_param.algParams,
pbe_param->encAlg, pbe_param->ivLen ? &der_param : NULL);
if (rv != SECSuccess) {
dummy = NULL;
break;
}
der_param.data = NULL;
der_param.len = 0;
dummy = SEC_ASN1EncodeItem(arena, &der_param, &pkcs5v2_param,
NSSPKCS5V2PBES2ParameterTemplate);
/* If the algorithm was set to some encryption oid, set it
* to PBES2 */
if ((algorithm != SEC_OID_PKCS5_PBKDF2) &&
(algorithm != SEC_OID_PKCS5_PBMAC1)) {
algorithm = SEC_OID_PKCS5_PBES2;
}
break;
default:
break;
@ -1532,3 +1755,66 @@ loser:
return ret_algid;
}
#define TEST_KEY "pbkdf test key"
SECStatus
sftk_fips_pbkdf_PowerUpSelfTests(void)
{
SECItem *result;
SECItem inKey;
NSSPKCS5PBEParameter pbe_params;
unsigned char iteration_count = 5;
unsigned char keyLen = 64;
char *inKeyData = TEST_KEY;
static const unsigned char saltData[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 };
static const unsigned char pbkdf_known_answer[] = {
0x31, 0xf0, 0xe5, 0x39, 0x9f, 0x39, 0xb9, 0x29,
0x68, 0xac, 0xf2, 0xe9, 0x53, 0x9b, 0xb4, 0x9c,
0x28, 0x59, 0x8b, 0x5c, 0xd8, 0xd4, 0x02, 0x37,
0x18, 0x22, 0xc1, 0x92, 0xd0, 0xfa, 0x72, 0x90,
0x2c, 0x8d, 0x19, 0xd4, 0x56, 0xfb, 0x16, 0xfa,
0x8d, 0x5c, 0x06, 0x33, 0xd1, 0x5f, 0x17, 0xb1,
0x22, 0xd9, 0x9c, 0xaf, 0x5e, 0x3f, 0xf3, 0x66,
0xc6, 0x14, 0xfe, 0x83, 0xfa, 0x1a, 0x2a, 0xc5
};
sftk_PBELockInit();
inKey.data = (unsigned char *)inKeyData;
inKey.len = sizeof(TEST_KEY) - 1;
pbe_params.salt.data = (unsigned char *)saltData;
pbe_params.salt.len = sizeof(saltData);
/* the interation and keyLength are used as intermediate
* values when decoding the Algorithm ID, set them for completeness,
* but they are not used */
pbe_params.iteration.data = &iteration_count;
pbe_params.iteration.len = 1;
pbe_params.keyLength.data = &keyLen;
pbe_params.keyLength.len = 1;
/* pkcs5v2 stores the key in the AlgorithmID, so we don't need to
* generate it here */
pbe_params.ivLen = 0;
pbe_params.ivData = NULL;
/* keyID is only used by pkcs12 extensions to pkcs5v1 */
pbe_params.keyID = pbeBitGenCipherKey;
/* Algorithm is used by the decryption code after get get our key */
pbe_params.encAlg = SEC_OID_AES_256_CBC;
/* these are the fields actually used in nsspkcs5_ComputeKeyAndIV
* for NSSPKCS5_PBKDF2 */
pbe_params.iter = iteration_count;
pbe_params.keyLen = keyLen;
pbe_params.hashType = HASH_AlgSHA256;
pbe_params.pbeType = NSSPKCS5_PBKDF2;
pbe_params.is2KeyDES = PR_FALSE;
result = nsspkcs5_ComputeKeyAndIV(&pbe_params, &inKey, NULL, PR_FALSE);
if ((result == NULL) || (result->len != sizeof(pbkdf_known_answer)) ||
(PORT_Memcmp(result->data, pbkdf_known_answer, sizeof(pbkdf_known_answer)) != 0)) {
SECITEM_FreeItem(result, PR_TRUE);
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
SECITEM_FreeItem(result, PR_TRUE);
return SECSuccess;
}

View file

@ -101,6 +101,11 @@ extern void
nsspkcs5_DestroyPBEParameter(NSSPKCS5PBEParameter *param);
HASH_HashType HASH_FromHMACOid(SECOidTag oid);
SECOidTag HASH_HMACOidFromHash(HASH_HashType);
/* fips selftest */
extern SECStatus
sftk_fips_pbkdf_PowerUpSelfTests(void);
SEC_END_PROTOS

View file

@ -5,11 +5,13 @@
CORE_DEPTH = ../..
MODULE = nss
ifndef NSS_DISABLE_DBM
DIRS = legacydb
endif
LIBRARY_NAME = softokn
LIBRARY_VERSION = 3
MAPFILE = $(OBJDIR)/softokn.def
MAPFILE = $(OBJDIR)/$(LIBRARY_NAME).def
DEFINES += -DSHLIB_SUFFIX=\"$(DLL_SUFFIX)\" -DSHLIB_PREFIX=\"$(DLL_PREFIX)\" -DSOFTOKEN_LIB_NAME=\"$(notdir $(SHARED_LIBRARY))\" -DSHLIB_VERSION=\"$(LIBRARY_VERSION)\"
@ -23,7 +25,6 @@ EXPORTS = \
$(NULL)
PRIVATE_EXPORTS = \
lgglue.h \
pkcs11ni.h \
softoken.h \
softoknt.h \
@ -36,7 +37,7 @@ CSRCS = \
fipsaudt.c \
fipstest.c \
fipstokn.c \
lgglue.c \
kbkdf.c \
lowkey.c \
lowpbe.c \
padbuf.c \
@ -45,8 +46,10 @@ CSRCS = \
pkcs11u.c \
sdb.c \
sftkdb.c \
sftkdhverify.c \
sftkhmac.c \
sftkike.c \
sftkmessage.c \
sftkpars.c \
sftkpwd.c \
softkver.c \
@ -54,6 +57,11 @@ CSRCS = \
jpakesftk.c \
$(NULL)
ifndef NSS_DISABLE_DBM
PRIVATE_EXPORTS += lgglue.h
CSRCS += lgglue.c
endif
ifdef SQLITE_UNSAFE_THREADS
DEFINES += -DSQLITE_UNSAFE_THREADS
endif

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -49,6 +49,8 @@
#define NSC_SEARCH_BLOCK_SIZE 5
#define NSC_SLOT_LIST_BLOCK_SIZE 10
#define NSC_MIN_SESSION_OBJECT_HANDLE 1U
#define NSC_FIPS_MODULE 1
#define NSC_NON_FIPS_MODULE 0
@ -105,8 +107,9 @@ typedef struct SFTKSessionContextStr SFTKSessionContext;
typedef struct SFTKSearchResultsStr SFTKSearchResults;
typedef struct SFTKHashVerifyInfoStr SFTKHashVerifyInfo;
typedef struct SFTKHashSignInfoStr SFTKHashSignInfo;
typedef struct SFTKOAEPEncryptInfoStr SFTKOAEPEncryptInfo;
typedef struct SFTKOAEPDecryptInfoStr SFTKOAEPDecryptInfo;
typedef struct SFTKOAEPInfoStr SFTKOAEPInfo;
typedef struct SFTKPSSSignInfoStr SFTKPSSSignInfo;
typedef struct SFTKPSSVerifyInfoStr SFTKPSSVerifyInfo;
typedef struct SFTKSSLMACInfoStr SFTKSSLMACInfo;
typedef struct SFTKChaCha20Poly1305InfoStr SFTKChaCha20Poly1305Info;
typedef struct SFTKChaCha20CtrInfoStr SFTKChaCha20CtrInfo;
@ -117,6 +120,9 @@ typedef void (*SFTKDestroy)(void *, PRBool);
typedef void (*SFTKBegin)(void *);
typedef SECStatus (*SFTKCipher)(void *, void *, unsigned int *, unsigned int,
void *, unsigned int);
typedef SECStatus (*SFTKAEADCipher)(void *, void *, unsigned int *,
unsigned int, void *, unsigned int,
void *, unsigned int, void *, unsigned int);
typedef SECStatus (*SFTKVerify)(void *, void *, unsigned int, void *, unsigned int);
typedef void (*SFTKHash)(void *, const void *, unsigned int);
typedef void (*SFTKEnd)(void *, void *, unsigned int *, unsigned int);
@ -187,6 +193,7 @@ struct SFTKObjectStr {
SFTKSlot *slot;
void *objectInfo;
SFTKFree infoFree;
PRBool isFIPS;
};
struct SFTKTokenObjectStr {
@ -235,7 +242,11 @@ typedef enum {
SFTK_SIGN,
SFTK_SIGN_RECOVER,
SFTK_VERIFY,
SFTK_VERIFY_RECOVER
SFTK_VERIFY_RECOVER,
SFTK_MESSAGE_ENCRYPT,
SFTK_MESSAGE_DECRYPT,
SFTK_MESSAGE_SIGN,
SFTK_MESSAGE_VERIFY
} SFTKContextType;
/** max block size of supported block ciphers */
@ -258,6 +269,7 @@ struct SFTKSessionContextStr {
PRBool rsa; /* is rsa */
PRBool doPad; /* use PKCS padding for block ciphers */
PRBool isXCBC; /* xcbc, use special handling in final */
PRBool isFIPS; /* current operation is in FIPS mode */
unsigned int blockSize; /* blocksize for padding */
unsigned int padDataLength; /* length of the valid data in padbuf */
/** latest incomplete block of data for block cipher */
@ -272,6 +284,7 @@ struct SFTKSessionContextStr {
unsigned int cipherInfoLen;
CK_MECHANISM_TYPE currentMech;
SFTKCipher update;
SFTKAEADCipher aeadUpdate;
SFTKHash hashUpdate;
SFTKEnd end;
SFTKDestroy destroy;
@ -298,6 +311,7 @@ struct SFTKSessionStr {
SFTKSessionContext *enc_context;
SFTKSessionContext *hash_context;
SFTKSessionContext *sign_context;
PRBool lastOpWasFIPS;
SFTKObjectList *objects[1];
};
@ -309,9 +323,9 @@ struct SFTKSessionStr {
* (head[]->refCount), objectLock protects all elements of the slot's
* object hash tables (sessObjHashTable[] and tokObjHashTable), and
* sessionObjectHandleCount.
* slotLock protects the remaining protected elements:
* password, needLogin, isLoggedIn, ssoLoggedIn, and sessionCount,
* and pwCheckLock serializes the key database password checks in
* slotLock protects password, needLogin, isLoggedIn, ssoLoggedIn,
* sessionCount, and rwSessionCount.
* pwCheckLock serializes the key database password checks in
* NSC_SetPIN and NSC_Login.
*
* Each of the fields below has the following lifetime as commented
@ -351,8 +365,7 @@ struct SFTKSlotStr {
int sessionIDConflict; /* not protected by a lock */
/* (preserved) */
int sessionCount; /* variable - reset */
PRInt32 rwSessionCount; /* set by atomic operations */
/* (reset) */
int rwSessionCount; /* variable - reset */
int sessionObjectHandleCount; /* variable - perserved */
CK_ULONG index; /* invariant */
PLHashTable *tokObjHashTable; /* invariant */
@ -363,6 +376,9 @@ struct SFTKSlotStr {
char tokDescription[33]; /* per load */
char updateTokDescription[33]; /* per load */
char slotDescription[65]; /* invariant */
SFTKSession moduleObjects; /* global session to hang module specific
* objects like profile objects or
* validation objects */
};
/*
@ -380,21 +396,33 @@ struct SFTKHashSignInfoStr {
NSSLOWKEYPrivateKey *key;
};
/**
* Contexts for RSA-OAEP
*/
struct SFTKOAEPEncryptInfoStr {
CK_RSA_PKCS_OAEP_PARAMS *params;
struct SFTKPSSVerifyInfoStr {
size_t size; /* must be first */
CK_RSA_PKCS_PSS_PARAMS params;
NSSLOWKEYPublicKey *key;
};
struct SFTKOAEPDecryptInfoStr {
CK_RSA_PKCS_OAEP_PARAMS *params;
struct SFTKPSSSignInfoStr {
size_t size; /* must be first */
CK_RSA_PKCS_PSS_PARAMS params;
NSSLOWKEYPrivateKey *key;
};
/**
* Contexts for RSA-OAEP
*/
struct SFTKOAEPInfoStr {
CK_RSA_PKCS_OAEP_PARAMS params;
PRBool isEncrypt;
union {
NSSLOWKEYPublicKey *pub;
NSSLOWKEYPrivateKey *priv;
} key;
};
/* context for the Final SSLMAC message */
struct SFTKSSLMACInfoStr {
size_t size; /* must be first */
void *hashContext;
SFTKBegin begin;
SFTKHash update;
@ -473,6 +501,8 @@ struct SFTKItemTemplateStr {
/* slot helper macros */
#define sftk_SlotFromSession(sp) ((sp)->slot)
#define sftk_isToken(id) (((id)&SFTK_TOKEN_MASK) == SFTK_TOKEN_MAGIC)
#define sftk_isFIPS(id) \
(((id) == FIPS_SLOT_ID) || ((id) >= SFTK_MIN_FIPS_USER_SLOT_ID))
/* the session hash multiplier (see bug 201081) */
#define SHMULTIPLIER 1791398085
@ -665,6 +695,9 @@ struct sftk_MACCtxStr {
};
typedef struct sftk_MACCtxStr sftk_MACCtx;
extern CK_NSS_MODULE_FUNCTIONS sftk_module_funcList;
extern CK_NSS_FIPS_FUNCTIONS sftk_fips_funcList;
SEC_BEGIN_PROTOS
/* shared functions between pkcs11.c and fipstokn.c */
@ -673,20 +706,26 @@ extern CK_RV nsc_CommonInitialize(CK_VOID_PTR pReserved, PRBool isFIPS);
extern CK_RV nsc_CommonFinalize(CK_VOID_PTR pReserved, PRBool isFIPS);
extern PRBool sftk_ForkReset(CK_VOID_PTR pReserved, CK_RV *crv);
extern CK_RV nsc_CommonGetSlotList(CK_BBOOL tokPresent,
CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount, int moduleIndex);
CK_SLOT_ID_PTR pSlotList,
CK_ULONG_PTR pulCount,
unsigned int moduleIndex);
/* slot initialization, reinit, shutdown and destruction */
extern CK_RV SFTK_SlotInit(char *configdir, char *updatedir, char *updateID,
sftk_token_parameters *params, int moduleIndex);
sftk_token_parameters *params,
unsigned int moduleIndex);
extern CK_RV SFTK_SlotReInit(SFTKSlot *slot, char *configdir,
char *updatedir, char *updateID,
sftk_token_parameters *params, int moduleIndex);
sftk_token_parameters *params,
unsigned int moduleIndex);
extern CK_RV SFTK_DestroySlotData(SFTKSlot *slot);
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 CK_RV sftk_MapDecryptError(int error);
extern CK_RV sftk_MapVerifyError(int error);
extern SFTKAttribute *sftk_FindAttribute(SFTKObject *object,
CK_ATTRIBUTE_TYPE type);
extern void sftk_FreeAttribute(SFTKAttribute *attribute);
@ -731,6 +770,7 @@ extern CK_RV sftk_DeleteObject(SFTKSession *session, SFTKObject *object);
extern void sftk_ReferenceObject(SFTKObject *object);
extern SFTKObject *sftk_ObjectFromHandle(CK_OBJECT_HANDLE handle,
SFTKSession *session);
extern CK_OBJECT_HANDLE sftk_getNextHandle(SFTKSlot *slot);
extern void sftk_AddSlotObject(SFTKSlot *slot, SFTKObject *object);
extern void sftk_AddObject(SFTKSession *session, SFTKObject *object);
/* clear out all the existing object ID to database key mappings.
@ -752,15 +792,38 @@ extern SFTKSlot *sftk_SlotFromSessionHandle(CK_SESSION_HANDLE handle);
extern CK_SLOT_ID sftk_SlotIDFromSessionHandle(CK_SESSION_HANDLE handle);
extern SFTKSession *sftk_SessionFromHandle(CK_SESSION_HANDLE handle);
extern void sftk_FreeSession(SFTKSession *session);
extern void sftk_ClearSession(SFTKSession *session);
extern void sftk_DestroySession(SFTKSession *session);
extern CK_RV sftk_InitSession(SFTKSession *session, SFTKSlot *slot,
CK_SLOT_ID slotID, CK_NOTIFY notify,
CK_VOID_PTR pApplication, CK_FLAGS flags);
extern SFTKSession *sftk_NewSession(CK_SLOT_ID slotID, CK_NOTIFY notify,
CK_VOID_PTR pApplication, CK_FLAGS flags);
extern void sftk_update_state(SFTKSlot *slot, SFTKSession *session);
extern void sftk_update_all_states(SFTKSlot *slot);
extern void sftk_FreeContext(SFTKSessionContext *context);
extern void sftk_InitFreeLists(void);
extern void sftk_CleanupFreeLists(void);
/*
* Helper functions to handle the session crypto contexts
*/
extern CK_RV sftk_InitGeneric(SFTKSession *session,
CK_MECHANISM *pMechanism,
SFTKSessionContext **contextPtr,
SFTKContextType ctype, SFTKObject **keyPtr,
CK_OBJECT_HANDLE hKey, CK_KEY_TYPE *keyTypePtr,
CK_OBJECT_CLASS pubKeyType,
CK_ATTRIBUTE_TYPE operation);
void sftk_SetContextByType(SFTKSession *session, SFTKContextType type,
SFTKSessionContext *context);
extern CK_RV sftk_GetContext(CK_SESSION_HANDLE handle,
SFTKSessionContext **contextPtr,
SFTKContextType type, PRBool needMulti,
SFTKSession **sessionPtr);
extern void sftk_TerminateOp(SFTKSession *session, SFTKContextType ctype,
SFTKSessionContext *context);
extern void sftk_FreeContext(SFTKSessionContext *context);
extern NSSLOWKEYPublicKey *sftk_GetPubKey(SFTKObject *object,
CK_KEY_TYPE key_type, CK_RV *crvp);
extern NSSLOWKEYPrivateKey *sftk_GetPrivKey(SFTKObject *object,
@ -770,6 +833,8 @@ extern CK_RV sftk_PutPubKey(SFTKObject *publicKey, SFTKObject *privKey, CK_KEY_T
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);
extern void sftk_EncodeInteger(PRUint64 integer, CK_ULONG num_bits, CK_BBOOL littleEndian,
CK_BYTE_PTR output, CK_ULONG_PTR output_len);
/* ike and xcbc helpers */
extern CK_RV sftk_ike_prf(CK_SESSION_HANDLE hSession,
@ -781,7 +846,8 @@ extern CK_RV sftk_ike1_prf(CK_SESSION_HANDLE hSession,
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,
const CK_NSS_IKE1_APP_B_PRF_DERIVE_PARAMS *params,
SFTKObject *outKey,
unsigned int keySize);
extern CK_RV sftk_ike_prf_plus(CK_SESSION_HANDLE hSession,
const SFTKAttribute *inKey,
@ -791,7 +857,7 @@ 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,
unsigned int blockSize, const unsigned char *k2,
const unsigned char *k3);
extern SECStatus sftk_fips_IKE_PowerUpSelfTests(void);
@ -807,6 +873,7 @@ NSSLOWKEYPrivateKey *sftk_FindKeyByPublicKey(SFTKSlot *slot, SECItem *dbKey);
*/
CK_RV sftk_parseParameters(char *param, sftk_parameters *parsed, PRBool isFIPS);
void sftk_freeParams(sftk_parameters *params);
PRBool sftk_RawArgHasFlag(const char *entry, const char *flag, const void *pReserved);
/*
* narrow objects
@ -846,6 +913,9 @@ void sftk_MACConstantTime_EndHash(
void *pctx, void *out, unsigned int *outLength, unsigned int maxLength);
void sftk_MACConstantTime_DestroyContext(void *pctx, PRBool);
/* Crypto Utilities */
HASH_HashType sftk_GetHashTypeFromMechanism(CK_MECHANISM_TYPE mech);
/****************************************
* implement TLS Pseudo Random Function (PRF)
*/
@ -859,14 +929,48 @@ sftk_TLSPRFInit(SFTKSessionContext *context,
/* PKCS#11 MAC implementation. See sftk_MACCtxStr declaration above for
* calling semantics for these functions. */
HASH_HashType sftk_HMACMechanismToHash(CK_MECHANISM_TYPE mech);
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_Update(sftk_MACCtx *ctx, const CK_BYTE *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);
/* constant time helpers */
unsigned int sftk_CKRVToMask(CK_RV rv);
CK_RV sftk_CheckCBCPadding(CK_BYTE_PTR pBuf, unsigned int bufLen,
unsigned int blockSize, unsigned int *outPadSize);
/* NIST 800-108 (kbkdf.c) implementations */
extern CK_RV kbkdf_Dispatch(CK_MECHANISM_TYPE mech, CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, SFTKObject *base_key, SFTKObject *ret_key, CK_ULONG keySize);
extern SECStatus sftk_fips_SP800_108_PowerUpSelfTests(void);
/* export the HKDF function for use in PowerupSelfTests */
CK_RV sftk_HKDF(CK_HKDF_PARAMS_PTR params, CK_SESSION_HANDLE hSession,
SFTKObject *sourceKey, const unsigned char *sourceKeyBytes,
int sourceKeyLen, SFTKObject *key,
unsigned char *outKeyBytes, int keySize,
PRBool canBeData, PRBool isFIPS);
char **NSC_ModuleDBFunc(unsigned long function, char *parameters, void *args);
/* dh verify functions */
/* verify that dhPrime matches one of our known primes, and if so return
* it's subprime value */
const SECItem *sftk_VerifyDH_Prime(SECItem *dhPrime, PRBool isFIPS);
/* check if dhSubPrime claims dhPrime is a safe prime. */
SECStatus sftk_IsSafePrime(SECItem *dhPrime, SECItem *dhSubPrime, PRBool *isSafe);
/* map an operation Attribute to a Mechanism flag */
CK_FLAGS sftk_AttributeToFlags(CK_ATTRIBUTE_TYPE op);
/* check the FIPS table to determine if this current operation is allowed by
* FIPS security policy */
PRBool sftk_operationIsFIPS(SFTKSlot *slot, CK_MECHANISM *mech,
CK_ATTRIBUTE_TYPE op, SFTKObject *source);
/* add validation objects to the slot */
CK_RV sftk_CreateValidationObjects(SFTKSlot *slot);
SEC_END_PROTOS
#endif /* _PKCS11I_H_ */

View file

@ -13,6 +13,19 @@
#include "prnetdb.h" /* for PR_ntohl */
#include "sftkdb.h"
#include "softoken.h"
#include "secoid.h"
#include "softkver.h"
#if !defined(NSS_FIPS_DISABLED) && defined(NSS_ENABLE_FIPS_INDICATORS)
/* this file should be supplied by the vendor and include all the
* algorithms which have Algorithm certs and have been reviewed by
* the lab. A blank file is included for the base so that FIPS mode
* will still be compiled and run, but FIPS indicators will always
* return PR_FALSE
*/
#include "fips_algorithms.h"
#define NSS_HAS_FIPS_INDICATORS 1
#endif
/*
* ******************** Error mapping *******************************
@ -55,6 +68,38 @@ sftk_MapCryptError(int error)
}
return CKR_DEVICE_ERROR;
}
/*
* functions which adjust the mapping based on different contexts
* (Decrypt or Verify).
*/
/* used by Decrypt and UnwrapKey (indirectly) and Decrypt message */
CK_RV
sftk_MapDecryptError(int error)
{
switch (error) {
/* usually a padding error, or aead tag mismatch */
case SEC_ERROR_BAD_DATA:
return CKR_ENCRYPTED_DATA_INVALID;
default:
return sftk_MapCryptError(error);
}
}
/*
* return CKR_SIGNATURE_INVALID instead of CKR_DEVICE_ERROR by default for
* backward compatibilty.
*/
CK_RV
sftk_MapVerifyError(int error)
{
CK_RV crv = sftk_MapCryptError(error);
if (crv == CKR_DEVICE_ERROR)
crv = CKR_SIGNATURE_INVALID;
return crv;
}
/*
* ******************** Attribute Utilities *******************************
*/
@ -123,16 +168,19 @@ sftk_NewAttribute(SFTKObject *object,
static void
sftk_DestroyAttribute(SFTKAttribute *attribute)
{
if (attribute->freeData) {
if (attribute->attrib.pValue) {
/* clear out the data in the attribute value... it may have been
* sensitive data */
PORT_Memset(attribute->attrib.pValue, 0,
attribute->attrib.ulValueLen);
if (attribute->attrib.pValue) {
/* clear out the data in the attribute value... it may have been
* sensitive data */
PORT_Memset(attribute->attrib.pValue, 0, attribute->attrib.ulValueLen);
if (attribute->freeData) {
PORT_Free(attribute->attrib.pValue);
attribute->attrib.pValue = NULL;
attribute->freeData = PR_FALSE;
}
PORT_Free(attribute->attrib.pValue);
}
PORT_Free(attribute);
if (attribute->freeAttr) {
PORT_Free(attribute);
}
}
/*
@ -684,7 +732,6 @@ sftk_modifyType(CK_ATTRIBUTE_TYPE type, CK_OBJECT_CLASS inClass)
case CKA_PUBLIC_EXPONENT:
case CKA_PRIVATE_EXPONENT:
case CKA_PRIME:
case CKA_SUBPRIME:
case CKA_BASE:
case CKA_PRIME_1:
case CKA_PRIME_2:
@ -694,7 +741,7 @@ sftk_modifyType(CK_ATTRIBUTE_TYPE type, CK_OBJECT_CLASS inClass)
case CKA_VALUE_LEN:
case CKA_ALWAYS_SENSITIVE:
case CKA_NEVER_EXTRACTABLE:
case CKA_NETSCAPE_DB:
case CKA_NSS_DB:
mtype = SFTK_NEVER;
break;
@ -735,6 +782,11 @@ sftk_modifyType(CK_ATTRIBUTE_TYPE type, CK_OBJECT_CLASS inClass)
mtype = (inClass == CKO_DATA) ? SFTK_ALWAYS : SFTK_NEVER;
break;
case CKA_SUBPRIME:
/* allow the CKA_SUBPRIME to be added to dh private keys */
mtype = (inClass == CKO_PRIVATE_KEY) ? SFTK_ALWAYS : SFTK_NEVER;
break;
case CKA_SUBJECT:
mtype = (inClass == CKO_CERTIFICATE) ? SFTK_NEVER : SFTK_ALWAYS;
break;
@ -828,7 +880,7 @@ sftk_DeleteAttributeType(SFTKObject *object, CK_ATTRIBUTE_TYPE type)
if (attribute == NULL)
return;
sftk_DeleteAttribute(object, attribute);
sftk_FreeAttribute(attribute);
sftk_DestroyAttribute(attribute);
}
CK_RV
@ -852,7 +904,7 @@ sftk_AddAttributeType(SFTKObject *object, CK_ATTRIBUTE_TYPE type,
static SECItem *
sftk_lookupTokenKeyByHandle(SFTKSlot *slot, CK_OBJECT_HANDLE handle)
{
return (SECItem *)PL_HashTableLookup(slot->tokObjHashTable, (void *)handle);
return (SECItem *)PL_HashTableLookup(slot->tokObjHashTable, (void *)(uintptr_t)handle);
}
/*
@ -1042,6 +1094,7 @@ sftk_NewObject(SFTKSlot *slot)
object->handle = 0;
object->next = object->prev = NULL;
object->slot = slot;
object->isFIPS = sftk_isFIPS(slot->slotID);
object->refCount = 1;
sessObject->sessionList.next = NULL;
@ -1191,6 +1244,36 @@ sftk_FreeObject(SFTKObject *object)
return SFTK_Busy;
}
/* find the next available object handle that isn't currently in use */
/* NOTE: This function could loop forever if we've exhausted all
* 3^31-1 handles. This is highly unlikely (NSS has been running for
* decades with this code) uless we start increasing the size of the
* SFTK_TOKEN_MASK (which is just the high bit currently). */
CK_OBJECT_HANDLE
sftk_getNextHandle(SFTKSlot *slot)
{
CK_OBJECT_HANDLE handle;
SFTKObject *duplicateObject = NULL;
do {
PRUint32 wrappedAround;
duplicateObject = NULL;
PZ_Lock(slot->objectLock);
wrappedAround = slot->sessionObjectHandleCount & SFTK_TOKEN_MASK;
handle = slot->sessionObjectHandleCount & ~SFTK_TOKEN_MASK;
if (!handle) /* don't allow zero handle */
handle = NSC_MIN_SESSION_OBJECT_HANDLE;
slot->sessionObjectHandleCount = (handle + 1U) | wrappedAround;
/* Is there already a session object with this handle? */
if (wrappedAround) {
sftkqueue_find(duplicateObject, handle, slot->sessObjHashTable,
slot->sessObjHashSize);
}
PZ_Unlock(slot->objectLock);
} while (duplicateObject != NULL);
return handle;
}
/*
* add an object to a slot and session queue. These two functions
* adopt the object.
@ -1249,7 +1332,7 @@ sftk_DeleteObject(SFTKSession *session, SFTKObject *object)
SFTKTokenObject *to = sftk_narrowToTokenObject(object);
PORT_Assert(to);
#endif
crv = sftkdb_DestroyObject(handle, object->handle);
crv = sftkdb_DestroyObject(handle, object->handle, object->objclass);
sftk_freeDB(handle);
}
return crv;
@ -1310,7 +1393,7 @@ static const CK_ULONG ecPubKeyAttrsCount =
static const CK_ATTRIBUTE_TYPE commonPrivKeyAttrs[] = {
CKA_DECRYPT, CKA_SIGN, CKA_SIGN_RECOVER, CKA_UNWRAP, CKA_SUBJECT,
CKA_SENSITIVE, CKA_EXTRACTABLE, CKA_NETSCAPE_DB, CKA_PUBLIC_KEY_INFO
CKA_SENSITIVE, CKA_EXTRACTABLE, CKA_NSS_DB, CKA_PUBLIC_KEY_INFO
};
static const CK_ULONG commonPrivKeyAttrsCount =
sizeof(commonPrivKeyAttrs) / sizeof(commonPrivKeyAttrs[0]);
@ -1354,13 +1437,13 @@ static const CK_ULONG trustAttrsCount =
sizeof(trustAttrs) / sizeof(trustAttrs[0]);
static const CK_ATTRIBUTE_TYPE smimeAttrs[] = {
CKA_SUBJECT, CKA_NETSCAPE_EMAIL, CKA_NETSCAPE_SMIME_TIMESTAMP, CKA_VALUE
CKA_SUBJECT, CKA_NSS_EMAIL, CKA_NSS_SMIME_TIMESTAMP, CKA_VALUE
};
static const CK_ULONG smimeAttrsCount =
sizeof(smimeAttrs) / sizeof(smimeAttrs[0]);
static const CK_ATTRIBUTE_TYPE crlAttrs[] = {
CKA_SUBJECT, CKA_VALUE, CKA_NETSCAPE_URL, CKA_NETSCAPE_KRL
CKA_SUBJECT, CKA_VALUE, CKA_NSS_URL, CKA_NSS_KRL
};
static const CK_ULONG crlAttrsCount =
sizeof(crlAttrs) / sizeof(crlAttrs[0]);
@ -1554,15 +1637,15 @@ sftk_CopyTokenObject(SFTKObject *destObject, SFTKObject *srcObject)
crv = stfk_CopyTokenAttributes(destObject, src_to, certAttrs,
certAttrsCount);
break;
case CKO_NETSCAPE_TRUST:
case CKO_NSS_TRUST:
crv = stfk_CopyTokenAttributes(destObject, src_to, trustAttrs,
trustAttrsCount);
break;
case CKO_NETSCAPE_SMIME:
case CKO_NSS_SMIME:
crv = stfk_CopyTokenAttributes(destObject, src_to, smimeAttrs,
smimeAttrsCount);
break;
case CKO_NETSCAPE_CRL:
case CKO_NSS_CRL:
crv = stfk_CopyTokenAttributes(destObject, src_to, crlAttrs,
crlAttrsCount);
break;
@ -1595,6 +1678,7 @@ sftk_CopyObject(SFTKObject *destObject, SFTKObject *srcObject)
SFTKSessionObject *src_so = sftk_narrowToSessionObject(srcObject);
unsigned int i;
destObject->isFIPS = srcObject->isFIPS;
if (src_so == NULL) {
return sftk_CopyTokenObject(destObject, srcObject);
}
@ -1795,23 +1879,13 @@ sftk_FreeContext(SFTKSessionContext *context)
}
/*
* create a new nession. NOTE: The session handle is not set, and the
* Init a new session. NOTE: The session handle is not set, and the
* session is not added to the slot's session queue.
*/
SFTKSession *
sftk_NewSession(CK_SLOT_ID slotID, CK_NOTIFY notify, CK_VOID_PTR pApplication,
CK_FLAGS flags)
CK_RV
sftk_InitSession(SFTKSession *session, SFTKSlot *slot, CK_SLOT_ID slotID,
CK_NOTIFY notify, CK_VOID_PTR pApplication, CK_FLAGS flags)
{
SFTKSession *session;
SFTKSlot *slot = sftk_SlotFromID(slotID, PR_FALSE);
if (slot == NULL)
return NULL;
session = (SFTKSession *)PORT_Alloc(sizeof(SFTKSession));
if (session == NULL)
return NULL;
session->next = session->prev = NULL;
session->enc_context = NULL;
session->hash_context = NULL;
@ -1820,8 +1894,7 @@ sftk_NewSession(CK_SLOT_ID slotID, CK_NOTIFY notify, CK_VOID_PTR pApplication,
session->objectIDCount = 1;
session->objectLock = PZ_NewLock(nssILockObject);
if (session->objectLock == NULL) {
PORT_Free(session);
return NULL;
return CKR_HOST_MEMORY;
}
session->objects[0] = NULL;
@ -1832,12 +1905,40 @@ sftk_NewSession(CK_SLOT_ID slotID, CK_NOTIFY notify, CK_VOID_PTR pApplication,
session->info.slotID = slotID;
session->info.ulDeviceError = 0;
sftk_update_state(slot, session);
/* no ops completed yet, so the last one couldn't be a FIPS op */
session->lastOpWasFIPS = PR_FALSE;
return CKR_OK;
}
/*
* Create a new session and init it.
*/
SFTKSession *
sftk_NewSession(CK_SLOT_ID slotID, CK_NOTIFY notify, CK_VOID_PTR pApplication,
CK_FLAGS flags)
{
SFTKSession *session;
SFTKSlot *slot = sftk_SlotFromID(slotID, PR_FALSE);
CK_RV crv;
if (slot == NULL)
return NULL;
session = (SFTKSession *)PORT_Alloc(sizeof(SFTKSession));
if (session == NULL)
return NULL;
crv = sftk_InitSession(session, slot, slotID, notify, pApplication, flags);
if (crv != CKR_OK) {
PORT_Free(session);
return NULL;
}
return session;
}
/* free all the data associated with a session. */
void
sftk_DestroySession(SFTKSession *session)
sftk_ClearSession(SFTKSession *session)
{
SFTKObjectList *op, *next;
@ -1863,6 +1964,13 @@ sftk_DestroySession(SFTKSession *session)
if (session->search) {
sftk_FreeSearch(session->search);
}
}
/* free the data associated with the session, and the session */
void
sftk_DestroySession(SFTKSession *session)
{
sftk_ClearSession(session);
PORT_Free(session);
}
@ -1955,6 +2063,7 @@ sftk_NewTokenObject(SFTKSlot *slot, SECItem *dbKey, CK_OBJECT_HANDLE handle)
goto loser;
}
object->slot = slot;
object->isFIPS = sftk_isFIPS(slot->slotID);
object->objectInfo = NULL;
object->infoFree = NULL;
if (!hasLocks) {
@ -2010,3 +2119,451 @@ sftk_narrowToTokenObject(SFTKObject *obj)
{
return sftk_isToken(obj->handle) ? (SFTKTokenObject *)obj : NULL;
}
/* Constant time helper functions */
/* sftk_CKRVToMask returns, in constant time, a mask value of
* all ones if rv == CKR_OK. Otherwise it returns zero. */
unsigned int
sftk_CKRVToMask(CK_RV rv)
{
PR_STATIC_ASSERT(CKR_OK == 0);
return ~PORT_CT_NOT_ZERO(rv);
}
/* sftk_CheckCBCPadding checks, in constant time, the padding validity and
* accordingly sets the pad length. */
CK_RV
sftk_CheckCBCPadding(CK_BYTE_PTR pBuf, unsigned int bufLen,
unsigned int blockSize, unsigned int *outPadSize)
{
PORT_Assert(outPadSize);
/* CBC-padded plaintext is always at least one full block */
if (bufLen < blockSize || blockSize == 0) {
*outPadSize = 0;
return CKR_ENCRYPTED_DATA_INVALID;
}
unsigned int padSize = (unsigned int)pBuf[bufLen - 1];
/* If padSize <= blockSize, set goodPad to all-1s and all-0s otherwise.*/
unsigned int goodPad = PORT_CT_DUPLICATE_MSB_TO_ALL(~(blockSize - padSize));
/* padSize should not be 0 */
goodPad &= PORT_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 = PORT_CT_DUPLICATE_MSB_TO_ALL(~(padSize - 1 - i));
/* Get the padding value (should be padSize) from buffer */
unsigned int padVal = pBuf[bufLen - 1 - i];
/* Update goodPad only if i < padSize */
goodPad &= PORT_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 = PORT_CT_DUPLICATE_MSB_TO_ALL(goodPad);
/* Set outPadSize to padSize or 0 */
*outPadSize = PORT_CT_SEL(goodPad, padSize, 0);
/* Return OK if the pad is valid */
return PORT_CT_SEL(goodPad, CKR_OK, CKR_ENCRYPTED_DATA_INVALID);
}
void
sftk_EncodeInteger(PRUint64 integer, CK_ULONG num_bits, CK_BBOOL littleEndian,
CK_BYTE_PTR output, CK_ULONG_PTR output_len)
{
if (output_len) {
*output_len = (num_bits / 8);
}
PR_ASSERT(num_bits > 0 && num_bits <= 64 && (num_bits % 8) == 0);
if (littleEndian == CK_TRUE) {
for (size_t offset = 0; offset < num_bits / 8; offset++) {
output[offset] = (unsigned char)((integer >> (offset * 8)) & 0xFF);
}
} else {
for (size_t offset = 0; offset < num_bits / 8; offset++) {
PRUint64 shift = num_bits - (offset + 1) * 8;
output[offset] = (unsigned char)((integer >> shift) & 0xFF);
}
}
}
CK_FLAGS
sftk_AttributeToFlags(CK_ATTRIBUTE_TYPE op)
{
CK_FLAGS flags = 0;
switch (op) {
case CKA_ENCRYPT:
flags = CKF_ENCRYPT;
break;
case CKA_DECRYPT:
flags = CKF_DECRYPT;
break;
case CKA_WRAP:
flags = CKF_WRAP;
break;
case CKA_UNWRAP:
flags = CKF_UNWRAP;
break;
case CKA_SIGN:
flags = CKF_SIGN;
break;
case CKA_SIGN_RECOVER:
flags = CKF_SIGN_RECOVER;
break;
case CKA_VERIFY:
flags = CKF_VERIFY;
break;
case CKA_VERIFY_RECOVER:
flags = CKF_VERIFY_RECOVER;
break;
case CKA_DERIVE:
flags = CKF_DERIVE;
break;
/* fake attribute to select digesting */
case CKA_DIGEST:
flags = CKF_DIGEST;
break;
case CKA_NSS_MESSAGE | CKA_ENCRYPT:
flags = CKF_MESSAGE_ENCRYPT;
break;
case CKA_NSS_MESSAGE | CKA_DECRYPT:
flags = CKF_MESSAGE_DECRYPT;
break;
case CKA_NSS_MESSAGE | CKA_SIGN:
flags = CKF_MESSAGE_SIGN;
break;
case CKA_NSS_MESSAGE | CKA_VERIFY:
flags = CKF_MESSAGE_VERIFY;
break;
default:
break;
}
return flags;
}
/*
* ******************** Hash Utilities **************************
*/
/*
* Utility function for converting PSS/OAEP parameter types into
* HASH_HashTypes. Note: Only SHA family functions are defined in RFC 3447.
*/
HASH_HashType
sftk_GetHashTypeFromMechanism(CK_MECHANISM_TYPE mech)
{
switch (mech) {
case CKM_SHA_1:
case CKG_MGF1_SHA1:
return HASH_AlgSHA1;
case CKM_SHA224:
case CKG_MGF1_SHA224:
return HASH_AlgSHA224;
case CKM_SHA256:
case CKG_MGF1_SHA256:
return HASH_AlgSHA256;
case CKM_SHA384:
case CKG_MGF1_SHA384:
return HASH_AlgSHA384;
case CKM_SHA512:
case CKG_MGF1_SHA512:
return HASH_AlgSHA512;
default:
return HASH_AlgNULL;
}
}
#ifdef NSS_HAS_FIPS_INDICATORS
/**************** FIPS Indicator Utilities *************************/
/* sigh, we probably need a version of this in secutil so that both
* softoken and NSS can use it */
static SECOidTag
sftk_quickGetECCCurveOid(SFTKObject *source)
{
SFTKAttribute *attribute = sftk_FindAttribute(source, CKA_EC_PARAMS);
unsigned char *encoded;
int len;
SECItem oid;
SECOidTag tag;
if (attribute == NULL) {
return SEC_OID_UNKNOWN;
}
encoded = attribute->attrib.pValue;
len = attribute->attrib.ulValueLen;
if ((len < 2) || (encoded[0] != SEC_ASN1_OBJECT_ID) ||
(len != encoded[1] + 2)) {
sftk_FreeAttribute(attribute);
return SEC_OID_UNKNOWN;
}
oid.data = encoded + 2;
oid.len = len - 2;
tag = SECOID_FindOIDTag(&oid);
sftk_FreeAttribute(attribute);
return tag;
}
/* This function currently only returns valid lengths for
* FIPS approved ECC curves. If we want to make this generic
* in the future, that Curve determination can be done in
* the sftk_handleSpecial. Since it's currently only used
* in FIPS indicators, it's currently only compiled with
* the FIPS indicator code */
static int
sftk_getKeyLength(SFTKObject *source)
{
CK_KEY_TYPE keyType = CK_INVALID_HANDLE;
CK_ATTRIBUTE_TYPE keyAttribute;
CK_ULONG keyLength = 0;
SFTKAttribute *attribute;
CK_RV crv;
/* If we don't have a key, then it doesn't have a length.
* this may be OK (say we are hashing). The mech info will
* sort this out because algorithms which expect no keys
* will accept zero length for the keys */
if (source == NULL) {
return 0;
}
crv = sftk_GetULongAttribute(source, CKA_KEY_TYPE, &keyType);
if (crv != CKR_OK) {
/* sometimes we're passed a data object, in that case the
* key length is CKA_VALUE, which is the default */
keyType = CKK_INVALID_KEY_TYPE;
}
if (keyType == CKK_EC) {
SECOidTag curve = sftk_quickGetECCCurveOid(source);
switch (curve) {
case SEC_OID_CURVE25519:
/* change when we start algorithm testing on curve25519 */
return 0;
case SEC_OID_SECG_EC_SECP256R1:
return 256;
case SEC_OID_SECG_EC_SECP384R1:
return 384;
case SEC_OID_SECG_EC_SECP521R1:
/* this is a lie, but it makes the table easier. We don't
* have to have a double entry for every ECC mechanism */
return 512;
default:
break;
}
/* other curves aren't NIST approved, returning 0 will cause these
* curves to fail FIPS length criteria */
return 0;
}
switch (keyType) {
case CKK_RSA:
keyAttribute = CKA_MODULUS;
break;
case CKK_DSA:
case CKK_DH:
keyAttribute = CKA_PRIME;
break;
default:
keyAttribute = CKA_VALUE;
break;
}
attribute = sftk_FindAttribute(source, keyAttribute);
if (attribute) {
keyLength = attribute->attrib.ulValueLen * 8;
sftk_FreeAttribute(attribute);
}
return keyLength;
}
/*
* handle specialized FIPS semantics that are too complicated to
* handle with just a table. NOTE: this means any additional semantics
* would have to be coded here before they can be added to the table */
static PRBool
sftk_handleSpecial(SFTKSlot *slot, CK_MECHANISM *mech,
SFTKFIPSAlgorithmList *mechInfo, SFTKObject *source)
{
switch (mechInfo->special) {
case SFTKFIPSDH: {
SECItem dhPrime;
const SECItem *dhSubPrime;
CK_RV crv = sftk_Attribute2SecItem(NULL, &dhPrime,
source, CKA_PRIME);
if (crv != CKR_OK) {
return PR_FALSE;
}
dhSubPrime = sftk_VerifyDH_Prime(&dhPrime, PR_TRUE);
SECITEM_ZfreeItem(&dhPrime, PR_FALSE);
return (dhSubPrime) ? PR_TRUE : PR_FALSE;
}
case SFTKFIPSNone:
return PR_FALSE;
case SFTKFIPSECC:
/* we've already handled the curve selection in the 'getlength'
* function */
return PR_TRUE;
case SFTKFIPSAEAD: {
if (mech->ulParameterLen == 0) {
/* AEAD ciphers are only in FIPS mode if we are using the
* MESSAGE interface. This takes an empty parameter
* in the init function */
return PR_TRUE;
}
return PR_FALSE;
}
case SFTKFIPSRSAPSS: {
/* PSS salt must not be longer than the underlying hash.
* We verify that the underlying hash of the
* parameters matches Hash of the combined hash mechanisms, so
* we don't need to look at the specific PSS mechanism */
CK_RSA_PKCS_PSS_PARAMS *pss = (CK_RSA_PKCS_PSS_PARAMS *)
mech->pParameter;
const SECHashObject *hashObj = NULL;
if (mech->ulParameterLen != sizeof(*pss)) {
return PR_FALSE;
}
/* we use the existing hash utilities to find the length of
* the hash */
hashObj = HASH_GetRawHashObject(sftk_GetHashTypeFromMechanism(
pss->hashAlg));
if (hashObj == NULL) {
return PR_FALSE;
}
if (pss->sLen > hashObj->length) {
return PR_FALSE;
}
return PR_TRUE;
}
default:
break;
}
/* if we didn't understand the special processing, mark it non-fips */
return PR_FALSE;
}
#endif
PRBool
sftk_operationIsFIPS(SFTKSlot *slot, CK_MECHANISM *mech, CK_ATTRIBUTE_TYPE op,
SFTKObject *source)
{
#ifndef NSS_HAS_FIPS_INDICATORS
return PR_FALSE;
#else
int i;
CK_FLAGS opFlags;
CK_ULONG keyLength;
/* handle all the quick stuff first */
if (!sftk_isFIPS(slot->slotID)) {
return PR_FALSE;
}
if (source && !source->isFIPS) {
return PR_FALSE;
}
if (mech == NULL) {
return PR_FALSE;
}
/* now get the calculated values */
opFlags = sftk_AttributeToFlags(op);
if (opFlags == 0) {
return PR_FALSE;
}
keyLength = sftk_getKeyLength(source);
/* check against our algorithm array */
for (i = 0; i < SFTK_NUMBER_FIPS_ALGORITHMS; i++) {
SFTKFIPSAlgorithmList *mechs = &sftk_fips_mechs[i];
/* if we match the number of records exactly, then we are an
* approved algorithm in the approved mode with an approved key */
if (((mech->mechanism == mechs->type) &&
(opFlags == (mechs->info.flags & opFlags)) &&
(keyLength <= mechs->info.ulMaxKeySize) &&
(keyLength >= mechs->info.ulMinKeySize) &&
((keyLength - mechs->info.ulMinKeySize) % mechs->step) == 0) &&
((mechs->special == SFTKFIPSNone) ||
sftk_handleSpecial(slot, mech, mechs, source))) {
return PR_TRUE;
}
}
return PR_FALSE;
#endif
}
/*
* create the FIPS Validation objects. If the vendor
* doesn't supply an NSS_FIPS_MODULE_ID, at compile time,
* then we assumethis is an unvalidated module.
*/
CK_RV
sftk_CreateValidationObjects(SFTKSlot *slot)
{
const char *module_id;
int module_id_len;
CK_RV crv = CKR_OK;
/* we currently use vendor specific values until the validation
* objects are approved for PKCS #11 v3.2. */
CK_OBJECT_CLASS cko_validation = CKO_NSS_VALIDATION;
CK_NSS_VALIDATION_TYPE ckv_fips = CKV_NSS_FIPS_140;
CK_VERSION fips_version = { 3, 0 }; /* FIPS-140-3 */
CK_ULONG fips_level = 1; /* or 2 if you validated at level 2 */
#ifndef NSS_FIPS_MODULE_ID
#define NSS_FIPS_MODULE_ID "Generic NSS " SOFTOKEN_VERSION " Unvalidated"
#endif
module_id = NSS_FIPS_MODULE_ID;
module_id_len = sizeof(NSS_FIPS_MODULE_ID) - 1;
SFTKObject *object;
object = sftk_NewObject(slot); /* fill in the handle later */
if (object == NULL) {
return CKR_HOST_MEMORY;
}
object->isFIPS = PR_FALSE;
crv = sftk_AddAttributeType(object, CKA_CLASS,
&cko_validation, sizeof(cko_validation));
if (crv != CKR_OK) {
goto loser;
}
crv = sftk_AddAttributeType(object, CKA_NSS_VALIDATION_TYPE,
&ckv_fips, sizeof(ckv_fips));
if (crv != CKR_OK) {
goto loser;
}
crv = sftk_AddAttributeType(object, CKA_NSS_VALIDATION_VERSION,
&fips_version, sizeof(fips_version));
if (crv != CKR_OK) {
goto loser;
}
crv = sftk_AddAttributeType(object, CKA_NSS_VALIDATION_LEVEL,
&fips_level, sizeof(fips_level));
if (crv != CKR_OK) {
goto loser;
}
crv = sftk_AddAttributeType(object, CKA_NSS_VALIDATION_MODULE_ID,
module_id, module_id_len);
if (crv != CKR_OK) {
goto loser;
}
/* future, fill in validation certificate information from a supplied
* pointer to a config file */
object->handle = sftk_getNextHandle(slot);
object->slot = slot;
sftk_AddObject(&slot->moduleObjects, object);
loser:
sftk_FreeObject(object);
return crv;
}

View file

@ -82,44 +82,12 @@ typedef enum {
* total wait time for automatic operations:
* 1 second (SDB_SQLITE_BUSY_TIMEOUT/1000).
* total wait time for manual operations:
* (1 second + 5 seconds) * 10 = 60 seconds.
* (1 second + SDB_BUSY_RETRY_TIME) * 30 = 30 seconds.
* (SDB_SQLITE_BUSY_TIMEOUT/1000 + SDB_BUSY_RETRY_TIME)*SDB_MAX_BUSY_RETRIES
*/
#define SDB_SQLITE_BUSY_TIMEOUT 1000 /* milliseconds */
#define SDB_BUSY_RETRY_TIME 5 /* seconds */
#define SDB_MAX_BUSY_RETRIES 10
/*
* Note on use of sqlReadDB: Only one thread at a time may have an actual
* operation going on given sqlite3 * database. An operation is defined as
* the time from a sqlite3_prepare() until the sqlite3_finalize().
* Multiple sqlite3 * databases can be open and have simultaneous operations
* going. We use the sqlXactDB for all write operations. This database
* is only opened when we first create a transaction and closed when the
* transaction is complete. sqlReadDB is open when we first opened the database
* and is used for all read operation. It's use is protected by a monitor. This
* is because an operation can span the use of FindObjectsInit() through the
* call to FindObjectsFinal(). In the intermediate time it is possible to call
* other operations like NSC_GetAttributeValue */
struct SDBPrivateStr {
char *sqlDBName; /* invariant, path to this database */
sqlite3 *sqlXactDB; /* access protected by dbMon, use protected
* by the transaction. Current transaction db*/
PRThread *sqlXactThread; /* protected by dbMon,
* current transaction thread */
sqlite3 *sqlReadDB; /* use protected by dbMon, value invariant */
PRIntervalTime lastUpdateTime; /* last time the cache was updated */
PRIntervalTime updateInterval; /* how long the cache can go before it
* must be updated again */
sdbDataType type; /* invariant, database type */
char *table; /* invariant, SQL table which contains the db */
char *cacheTable; /* invariant, SQL table cache of db */
PRMonitor *dbMon; /* invariant, monitor to protect
* sqlXact* fields, and use of the sqlReadDB */
};
typedef struct SDBPrivateStr SDBPrivate;
#define SDB_BUSY_RETRY_TIME 5 /* 'ticks', varies by platforms */
#define SDB_MAX_BUSY_RETRIES 30
/*
* known attributes
@ -135,35 +103,68 @@ static const CK_ATTRIBUTE_TYPE known_attributes[] = {
CKA_VERIFY, CKA_VERIFY_RECOVER, CKA_DERIVE, CKA_START_DATE, CKA_END_DATE,
CKA_MODULUS, CKA_MODULUS_BITS, CKA_PUBLIC_EXPONENT, CKA_PRIVATE_EXPONENT,
CKA_PRIME_1, CKA_PRIME_2, CKA_EXPONENT_1, CKA_EXPONENT_2, CKA_COEFFICIENT,
CKA_PRIME, CKA_SUBPRIME, CKA_BASE, CKA_PRIME_BITS,
CKA_PUBLIC_KEY_INFO, CKA_PRIME, CKA_SUBPRIME, CKA_BASE, CKA_PRIME_BITS,
CKA_SUB_PRIME_BITS, CKA_VALUE_BITS, CKA_VALUE_LEN, CKA_EXTRACTABLE,
CKA_LOCAL, CKA_NEVER_EXTRACTABLE, CKA_ALWAYS_SENSITIVE,
CKA_KEY_GEN_MECHANISM, CKA_MODIFIABLE, CKA_EC_PARAMS,
CKA_EC_POINT, CKA_SECONDARY_AUTH, CKA_AUTH_PIN_FLAGS,
CKA_ALWAYS_AUTHENTICATE, CKA_WRAP_WITH_TRUSTED, CKA_WRAP_TEMPLATE,
CKA_UNWRAP_TEMPLATE, CKA_HW_FEATURE_TYPE, CKA_RESET_ON_INIT,
CKA_HAS_RESET, CKA_PIXEL_X, CKA_PIXEL_Y, CKA_RESOLUTION, CKA_CHAR_ROWS,
CKA_CHAR_COLUMNS, CKA_COLOR, CKA_BITS_PER_PIXEL, CKA_CHAR_SETS,
CKA_ENCODING_METHODS, CKA_MIME_TYPES, CKA_MECHANISM_TYPE,
CKA_REQUIRED_CMS_ATTRIBUTES, CKA_DEFAULT_CMS_ATTRIBUTES,
CKA_SUPPORTED_CMS_ATTRIBUTES, CKA_NETSCAPE_URL, CKA_NETSCAPE_EMAIL,
CKA_NETSCAPE_SMIME_INFO, CKA_NETSCAPE_SMIME_TIMESTAMP,
CKA_NETSCAPE_PKCS8_SALT, CKA_NETSCAPE_PASSWORD_CHECK, CKA_NETSCAPE_EXPIRES,
CKA_NETSCAPE_KRL, CKA_NETSCAPE_PQG_COUNTER, CKA_NETSCAPE_PQG_SEED,
CKA_NETSCAPE_PQG_H, CKA_NETSCAPE_PQG_SEED_BITS, CKA_NETSCAPE_MODULE_SPEC,
CKA_TRUST_DIGITAL_SIGNATURE, CKA_TRUST_NON_REPUDIATION,
CKA_TRUST_KEY_ENCIPHERMENT, CKA_TRUST_DATA_ENCIPHERMENT,
CKA_TRUST_KEY_AGREEMENT, CKA_TRUST_KEY_CERT_SIGN, CKA_TRUST_CRL_SIGN,
CKA_TRUST_SERVER_AUTH, CKA_TRUST_CLIENT_AUTH, CKA_TRUST_CODE_SIGNING,
CKA_TRUST_EMAIL_PROTECTION, CKA_TRUST_IPSEC_END_SYSTEM,
CKA_TRUST_IPSEC_TUNNEL, CKA_TRUST_IPSEC_USER, CKA_TRUST_TIME_STAMPING,
CKA_TRUST_STEP_UP_APPROVED, CKA_CERT_SHA1_HASH, CKA_CERT_MD5_HASH,
CKA_NETSCAPE_DB, CKA_NETSCAPE_TRUST, CKA_NSS_OVERRIDE_EXTENSIONS,
CKA_PUBLIC_KEY_INFO, CKA_NSS_SERVER_DISTRUST_AFTER, CKA_NSS_EMAIL_DISTRUST_AFTER
CKA_ALWAYS_AUTHENTICATE, CKA_WRAP_WITH_TRUSTED, CKA_HW_FEATURE_TYPE,
CKA_RESET_ON_INIT, CKA_HAS_RESET, CKA_PIXEL_X, CKA_PIXEL_Y,
CKA_RESOLUTION, CKA_CHAR_ROWS, CKA_CHAR_COLUMNS, CKA_COLOR,
CKA_BITS_PER_PIXEL, CKA_CHAR_SETS, CKA_ENCODING_METHODS, CKA_MIME_TYPES,
CKA_MECHANISM_TYPE, CKA_REQUIRED_CMS_ATTRIBUTES,
CKA_DEFAULT_CMS_ATTRIBUTES, CKA_SUPPORTED_CMS_ATTRIBUTES,
CKA_WRAP_TEMPLATE, CKA_UNWRAP_TEMPLATE, CKA_NSS_TRUST, CKA_NSS_URL,
CKA_NSS_EMAIL, CKA_NSS_SMIME_INFO, CKA_NSS_SMIME_TIMESTAMP,
CKA_NSS_PKCS8_SALT, CKA_NSS_PASSWORD_CHECK, CKA_NSS_EXPIRES,
CKA_NSS_KRL, CKA_NSS_PQG_COUNTER, CKA_NSS_PQG_SEED,
CKA_NSS_PQG_H, CKA_NSS_PQG_SEED_BITS, CKA_NSS_MODULE_SPEC,
CKA_NSS_OVERRIDE_EXTENSIONS, CKA_NSS_SERVER_DISTRUST_AFTER,
CKA_NSS_EMAIL_DISTRUST_AFTER, CKA_TRUST_DIGITAL_SIGNATURE,
CKA_TRUST_NON_REPUDIATION, CKA_TRUST_KEY_ENCIPHERMENT,
CKA_TRUST_DATA_ENCIPHERMENT, CKA_TRUST_KEY_AGREEMENT,
CKA_TRUST_KEY_CERT_SIGN, CKA_TRUST_CRL_SIGN, CKA_TRUST_SERVER_AUTH,
CKA_TRUST_CLIENT_AUTH, CKA_TRUST_CODE_SIGNING, CKA_TRUST_EMAIL_PROTECTION,
CKA_TRUST_IPSEC_END_SYSTEM, CKA_TRUST_IPSEC_TUNNEL, CKA_TRUST_IPSEC_USER,
CKA_TRUST_TIME_STAMPING, CKA_TRUST_STEP_UP_APPROVED, CKA_CERT_SHA1_HASH,
CKA_CERT_MD5_HASH, CKA_NSS_DB
};
static int known_attributes_size = sizeof(known_attributes) /
sizeof(known_attributes[0]);
static const int known_attributes_size = PR_ARRAY_SIZE(known_attributes);
/*
* Note on use of sqlReadDB: Only one thread at a time may have an actual
* operation going on given sqlite3 * database. An operation is defined as
* the time from a sqlite3_prepare() until the sqlite3_finalize().
* Multiple sqlite3 * databases can be open and have simultaneous operations
* going. We use the sqlXactDB for all write operations. This database
* is only opened when we first create a transaction and closed when the
* transaction is complete. sqlReadDB is open when we first opened the database
* and is used for all read operation. It's use is protected by a monitor. This
* is because an operation can span the use of FindObjectsInit() through the
* call to FindObjectsFinal(). In the intermediate time it is possible to call
* other operations like NSC_GetAttributeValue */
struct SDBPrivateStr {
char *sqlDBName; /* invariant, path to this database */
sqlite3 *sqlXactDB; /* access protected by dbMon, use protected
* by the transaction. Current transaction db*/
PRThread *sqlXactThread; /* protected by dbMon,
* current transaction thread */
sqlite3 *sqlReadDB; /* use protected by dbMon, value invariant */
PRIntervalTime lastUpdateTime; /* last time the cache was updated */
PRIntervalTime updateInterval; /* how long the cache can go before it
* must be updated again */
sdbDataType type; /* invariant, database type */
char *table; /* invariant, SQL table which contains the db */
char *cacheTable; /* invariant, SQL table cache of db */
PRMonitor *dbMon; /* invariant, monitor to protect
* sqlXact* fields, and use of the sqlReadDB */
CK_ATTRIBUTE_TYPE *schemaAttrs; /* Attribute columns that exist in the table. */
unsigned int numSchemaAttrs;
};
typedef struct SDBPrivateStr SDBPrivate;
/* Magic for an explicit NULL. NOTE: ideally this should be
* out of band data. Since it's not completely out of band, pick
@ -362,7 +363,7 @@ sdb_mapSQLError(sdbDataType type, int sqlerr)
case SQLITE_CANTOPEN:
case SQLITE_NOTFOUND:
/* NSS distiguishes between failure to open the cert and the key db */
return type == SDB_CERT ? CKR_NETSCAPE_CERTDB_FAILED : CKR_NETSCAPE_KEYDB_FAILED;
return type == SDB_CERT ? CKR_NSS_CERTDB_FAILED : CKR_NSS_KEYDB_FAILED;
case SQLITE_IOERR:
return CKR_DEVICE_ERROR;
default:
@ -400,8 +401,20 @@ sdb_measureAccess(const char *directory)
PRIntervalTime duration = PR_MillisecondsToInterval(33);
const char *doesntExistName = "_dOeSnotExist_.db";
char *temp, *tempStartOfFilename;
size_t maxTempLen, maxFileNameLen, directoryLength;
size_t maxTempLen, maxFileNameLen, directoryLength, tmpdirLength = 0;
#ifdef SDB_MEASURE_USE_TEMP_DIR
/*
* on some OS's and Filesystems, creating a bunch of files and deleting
* them messes up the systems's caching, but if we create the files in
* a temp directory which we later delete, then the cache gets cleared
* up. This code uses several OS dependent calls, and it's not clear
* that temp directory use won't mess up other filesystems and OS caching,
* so if you need this for your OS, you can turn on the
* 'SDB_MEASURE_USE_TEMP_DIR' define in coreconf
*/
const char template[] = "dbTemp.XXXXXX";
tmpdirLength = sizeof(template);
#endif
/* no directory, just return one */
if (directory == NULL) {
return 1;
@ -412,24 +425,39 @@ sdb_measureAccess(const char *directory)
directoryLength = strlen(directory);
maxTempLen = directoryLength + strlen(doesntExistName) + 1 /* potential additional separator char */
+ 11 /* max chars for 32 bit int plus potential sign */
+ 1; /* zero terminator */
maxTempLen = directoryLength + 1 /* dirname + / */
+ tmpdirLength /* tmpdirname includes / */
+ strlen(doesntExistName) /* filename base */
+ 11 /* max chars for 32 bit int plus potential sign */
+ 1; /* zero terminator */
temp = PORT_Alloc(maxTempLen);
temp = PORT_ZAlloc(maxTempLen);
if (!temp) {
return 1;
}
/* We'll copy directory into temp just once, then ensure it ends
* with the directory separator, then remember the position after
* the separator, and calculate the number of remaining bytes. */
* with the directory separator. */
strcpy(temp, directory);
if (directory[directoryLength - 1] != PR_GetDirectorySeparator()) {
temp[directoryLength++] = PR_GetDirectorySeparator();
}
tempStartOfFilename = temp + directoryLength;
#ifdef SDB_MEASURE_USE_TEMP_DIR
/* add the template for a temporary subdir, and create it */
strcat(temp, template);
if (!mkdtemp(temp)) {
PORT_Free(temp);
return 1;
}
/* and terminate that tmp subdir with a / */
strcat(temp, "/");
#endif
/* Remember the position after the last separator, and calculate the
* number of remaining bytes. */
tempStartOfFilename = temp + directoryLength + tmpdirLength;
maxFileNameLen = maxTempLen - directoryLength;
/* measure number of Access operations that can be done in 33 milliseconds
@ -453,6 +481,12 @@ sdb_measureAccess(const char *directory)
break;
}
#ifdef SDB_MEASURE_USE_TEMP_DIR
/* turn temp back into our tmpdir path by removing doesntExistName, and
* remove the tmp dir */
*tempStartOfFilename = '\0';
(void)rmdir(temp);
#endif
PORT_Free(temp);
/* always return 1 or greater */
@ -863,9 +897,9 @@ sdb_FindObjectsFinal(SDB *sdb, SDBFind *sdbFind)
return sdb_mapSQLError(sdb_p->type, sqlerr);
}
CK_RV
sdb_GetAttributeValueNoLock(SDB *sdb, CK_OBJECT_HANDLE object_id,
CK_ATTRIBUTE *template, CK_ULONG count)
static CK_RV
sdb_GetValidAttributeValueNoLock(SDB *sdb, CK_OBJECT_HANDLE object_id,
CK_ATTRIBUTE *template, CK_ULONG count)
{
SDBPrivate *sdb_p = sdb->private;
sqlite3 *sqlDB = NULL;
@ -972,6 +1006,7 @@ sdb_GetAttributeValueNoLock(SDB *sdb, CK_OBJECT_HANDLE object_id,
found = 1;
}
} while (!sdb_done(sqlerr, &retry));
sqlite3_reset(stmt);
sqlite3_finalize(stmt);
stmt = NULL;
@ -997,19 +1032,109 @@ loser:
return error;
}
/* NOTE: requires sdb_p->schemaAttrs to be sorted asc. */
inline static PRBool
sdb_attributeExists(SDB *sdb, CK_ATTRIBUTE_TYPE attr)
{
SDBPrivate *sdb_p = sdb->private;
int first = 0;
int last = (int)sdb_p->numSchemaAttrs - 1;
while (last >= first) {
int mid = first + (last - first) / 2;
if (sdb_p->schemaAttrs[mid] == attr) {
return PR_TRUE;
}
if (attr > sdb_p->schemaAttrs[mid]) {
first = mid + 1;
} else {
last = mid - 1;
}
}
return PR_FALSE;
}
CK_RV
sdb_GetAttributeValue(SDB *sdb, CK_OBJECT_HANDLE object_id,
CK_ATTRIBUTE *template, CK_ULONG count)
{
CK_RV crv;
CK_RV crv = CKR_OK;
unsigned int tmplIdx;
unsigned int resIdx = 0;
unsigned int validCount = 0;
unsigned int i;
if (count == 0) {
return CKR_OK;
return crv;
}
CK_ATTRIBUTE *validTemplate;
PRBool invalidExists = PR_FALSE;
for (tmplIdx = 0; tmplIdx < count; tmplIdx++) {
if (!sdb_attributeExists(sdb, template[tmplIdx].type)) {
template[tmplIdx].ulValueLen = -1;
crv = CKR_ATTRIBUTE_TYPE_INVALID;
invalidExists = PR_TRUE;
break;
}
}
if (!invalidExists) {
validTemplate = template;
validCount = count;
} else {
/* Create a new template containing only the valid subset of
* input |template|, and query with that. */
validCount = tmplIdx;
validTemplate = malloc(sizeof(CK_ATTRIBUTE) * count);
if (!validTemplate) {
return CKR_HOST_MEMORY;
}
/* Copy in what we already know is valid. */
for (i = 0; i < validCount; i++) {
validTemplate[i] = template[i];
}
/* tmplIdx was left at the index of the first invalid
* attribute, which has been handled. We only need to
* deal with the remainder. */
tmplIdx++;
for (; tmplIdx < count; tmplIdx++) {
if (sdb_attributeExists(sdb, template[tmplIdx].type)) {
validTemplate[validCount++] = template[tmplIdx];
} else {
template[tmplIdx].ulValueLen = -1;
}
}
}
if (validCount) {
LOCK_SQLITE()
CK_RV crv2 = sdb_GetValidAttributeValueNoLock(sdb, object_id, validTemplate, validCount);
UNLOCK_SQLITE()
/* If an invalid attribute was removed above, let
* the caller know. Any other error from the actual
* query should propogate. */
crv = (crv2 == CKR_OK) ? crv : crv2;
}
if (invalidExists) {
/* Copy out valid lengths. */
tmplIdx = 0;
for (resIdx = 0; resIdx < validCount; resIdx++) {
for (; tmplIdx < count; tmplIdx++) {
if (template[tmplIdx].type != validTemplate[resIdx].type) {
continue;
}
template[tmplIdx].ulValueLen = validTemplate[resIdx].ulValueLen;
tmplIdx++;
break;
}
}
free(validTemplate);
}
LOCK_SQLITE()
crv = sdb_GetAttributeValueNoLock(sdb, object_id, template, count);
UNLOCK_SQLITE()
return crv;
}
@ -1120,7 +1245,7 @@ sdb_objectExists(SDB *sdb, CK_OBJECT_HANDLE candidate)
CK_RV crv;
CK_ATTRIBUTE template = { CKA_LABEL, NULL, 0 };
crv = sdb_GetAttributeValueNoLock(sdb, candidate, &template, 1);
crv = sdb_GetValidAttributeValueNoLock(sdb, candidate, &template, 1);
if (crv == CKR_OBJECT_HANDLE_INVALID) {
return PR_FALSE;
}
@ -1166,6 +1291,19 @@ sdb_getObjectId(SDB *sdb)
return CK_INVALID_HANDLE;
}
CK_RV
sdb_GetNewObjectID(SDB *sdb, CK_OBJECT_HANDLE *object)
{
CK_OBJECT_HANDLE id;
id = sdb_getObjectId(sdb);
if (id == CK_INVALID_HANDLE) {
return CKR_DEVICE_MEMORY; /* basically we ran out of resources */
}
*object = id;
return CKR_OK;
}
static const char CREATE_CMD[] = "INSERT INTO %s (id%s) VALUES($ID%s);";
CK_RV
sdb_CreateObject(SDB *sdb, CK_OBJECT_HANDLE *object_id,
@ -1273,10 +1411,13 @@ loser:
return error;
}
/*
* Generic destroy that can destroy metadata or objects
*/
static const char DESTROY_CMD[] = "DELETE FROM %s WHERE (id=$ID);";
CK_RV
sdb_DestroyObject(SDB *sdb, CK_OBJECT_HANDLE object_id)
sdb_destroyAnyObject(SDB *sdb, const char *table,
CK_OBJECT_HANDLE object_id, const char *string_id)
{
SDBPrivate *sdb_p = sdb->private;
sqlite3 *sqlDB = NULL;
@ -1295,7 +1436,7 @@ sdb_DestroyObject(SDB *sdb, CK_OBJECT_HANDLE object_id)
if (error != CKR_OK) {
goto loser;
}
newStr = sqlite3_mprintf(DESTROY_CMD, sdb_p->table);
newStr = sqlite3_mprintf(DESTROY_CMD, table);
if (newStr == NULL) {
error = CKR_HOST_MEMORY;
goto loser;
@ -1304,7 +1445,12 @@ sdb_DestroyObject(SDB *sdb, CK_OBJECT_HANDLE object_id)
sqlite3_free(newStr);
if (sqlerr != SQLITE_OK)
goto loser;
sqlerr = sqlite3_bind_int(stmt, 1, object_id);
if (string_id == NULL) {
sqlerr = sqlite3_bind_int(stmt, 1, object_id);
} else {
sqlerr = sqlite3_bind_text(stmt, 1, string_id,
PORT_Strlen(string_id), SQLITE_STATIC);
}
if (sqlerr != SQLITE_OK)
goto loser;
@ -1333,6 +1479,19 @@ loser:
return error;
}
CK_RV
sdb_DestroyObject(SDB *sdb, CK_OBJECT_HANDLE object_id)
{
SDBPrivate *sdb_p = sdb->private;
return sdb_destroyAnyObject(sdb, sdb_p->table, object_id, NULL);
}
CK_RV
sdb_DestroyMetaData(SDB *sdb, const char *id)
{
return sdb_destroyAnyObject(sdb, "metaData", 0, id);
}
static const char BEGIN_CMD[] = "BEGIN IMMEDIATE TRANSACTION;";
/*
@ -1371,6 +1530,8 @@ sdb_Begin(SDB *sdb)
if (sqlerr == SQLITE_BUSY) {
PR_Sleep(SDB_BUSY_RETRY_TIME);
}
/* don't retry BEGIN transaction*/
retry = 0;
} while (!sdb_done(sqlerr, &retry));
if (stmt) {
@ -1730,6 +1891,7 @@ sdb_Close(SDB *sdb)
if (sdb_p->dbMon) {
PR_DestroyMonitor(sdb_p->dbMon);
}
free(sdb_p->schemaAttrs);
free(sdb_p);
free(sdb);
return sdb_mapSQLError(type, sqlerr);
@ -1767,6 +1929,18 @@ sdb_SetForkState(PRBool forked)
* interface, we will need to set it and reset it from here */
}
static int
sdb_attributeComparator(const void *a, const void *b)
{
if (*(CK_ATTRIBUTE_TYPE *)a < *(CK_ATTRIBUTE_TYPE *)b) {
return -1;
}
if (*(CK_ATTRIBUTE_TYPE *)a > *(CK_ATTRIBUTE_TYPE *)b) {
return 1;
}
return 0;
}
/*
* initialize a single database
*/
@ -1780,6 +1954,7 @@ sdb_init(char *dbname, char *table, sdbDataType type, int *inUpdate,
int i;
char *initStr = NULL;
char *newStr;
char *queryStr = NULL;
int inTransaction = 0;
SDB *sdb = NULL;
SDBPrivate *sdb_p = NULL;
@ -2033,7 +2208,86 @@ sdb_init(char *dbname, char *table, sdbDataType type, int *inUpdate,
}
sdb = (SDB *)malloc(sizeof(SDB));
if (!sdb) {
error = CKR_HOST_MEMORY;
goto loser;
}
sdb_p = (SDBPrivate *)malloc(sizeof(SDBPrivate));
if (!sdb_p) {
error = CKR_HOST_MEMORY;
goto loser;
}
/* Cache the attributes that are held in the table, so we can later check
* that queried attributes actually exist. We don't assume the schema
* to be exactly |known_attributes|, as it may change over time. */
sdb_p->schemaAttrs = NULL;
if (!PORT_Strcmp("nssPublic", table) ||
!PORT_Strcmp("nssPrivate", table)) {
sqlite3_stmt *stmt = NULL;
int retry = 0;
unsigned int backedAttrs = 0;
/* Can't bind parameters to a PRAGMA. */
queryStr = sqlite3_mprintf("PRAGMA table_info(%s);", table);
if (queryStr == NULL) {
error = CKR_HOST_MEMORY;
goto loser;
}
sqlerr = sqlite3_prepare_v2(sqlDB, queryStr, -1, &stmt, NULL);
sqlite3_free(queryStr);
queryStr = NULL;
if (sqlerr != SQLITE_OK) {
goto loser;
}
unsigned int schemaAttrsCapacity = known_attributes_size;
sdb_p->schemaAttrs = malloc(schemaAttrsCapacity * sizeof(CK_ATTRIBUTE_TYPE));
if (!sdb_p->schemaAttrs) {
error = CKR_HOST_MEMORY;
goto loser;
}
do {
sqlerr = sqlite3_step(stmt);
if (sqlerr == SQLITE_BUSY) {
PR_Sleep(SDB_BUSY_RETRY_TIME);
}
if (sqlerr == SQLITE_ROW) {
if (backedAttrs == schemaAttrsCapacity) {
schemaAttrsCapacity += known_attributes_size;
sdb_p->schemaAttrs = realloc(sdb_p->schemaAttrs,
schemaAttrsCapacity * sizeof(CK_ATTRIBUTE_TYPE));
if (!sdb_p->schemaAttrs) {
error = CKR_HOST_MEMORY;
goto loser;
}
}
/* Record the ULONG attribute value. */
char *val = (char *)sqlite3_column_text(stmt, 1);
if (val && val[0] == 'a') {
CK_ATTRIBUTE_TYPE attr = strtoul(&val[1], NULL, 16);
sdb_p->schemaAttrs[backedAttrs++] = attr;
}
}
} while (!sdb_done(sqlerr, &retry));
if (sqlerr != SQLITE_DONE) {
goto loser;
}
sqlerr = sqlite3_reset(stmt);
if (sqlerr != SQLITE_OK) {
goto loser;
}
sqlerr = sqlite3_finalize(stmt);
if (sqlerr != SQLITE_OK) {
goto loser;
}
sdb_p->numSchemaAttrs = backedAttrs;
/* Sort these once so we can shortcut invalid attribute searches. */
qsort(sdb_p->schemaAttrs, sdb_p->numSchemaAttrs,
sizeof(CK_ATTRIBUTE_TYPE), sdb_attributeComparator);
}
/* invariant fields */
sdb_p->sqlDBName = PORT_Strdup(dbname);
@ -2049,7 +2303,7 @@ sdb_init(char *dbname, char *table, sdbDataType type, int *inUpdate,
sdb_p->sqlXactDB = NULL;
sdb_p->sqlXactThread = NULL;
sdb->private = sdb_p;
sdb->version = 0;
sdb->version = 1;
sdb->sdb_flags = inFlags | SDB_HAS_META;
sdb->app_private = NULL;
sdb->sdb_FindObjectsInit = sdb_FindObjectsInit;
@ -2061,12 +2315,14 @@ sdb_init(char *dbname, char *table, sdbDataType type, int *inUpdate,
sdb->sdb_DestroyObject = sdb_DestroyObject;
sdb->sdb_GetMetaData = sdb_GetMetaData;
sdb->sdb_PutMetaData = sdb_PutMetaData;
sdb->sdb_DestroyMetaData = sdb_DestroyMetaData;
sdb->sdb_Begin = sdb_Begin;
sdb->sdb_Commit = sdb_Commit;
sdb->sdb_Abort = sdb_Abort;
sdb->sdb_Reset = sdb_Reset;
sdb->sdb_Close = sdb_Close;
sdb->sdb_SetForkState = sdb_SetForkState;
sdb->sdb_GetNewObjectID = sdb_GetNewObjectID;
if (inTransaction) {
sqlerr = sqlite3_exec(sqlDB, COMMIT_CMD, NULL, 0, NULL);
@ -2092,6 +2348,9 @@ loser:
free(sdb);
}
if (sdb_p) {
if (sdb_p->schemaAttrs) {
free(sdb_p->schemaAttrs);
}
free(sdb_p);
}
if (sqlDB) {

View file

@ -75,6 +75,10 @@ struct SDBStr {
CK_RV(*sdb_Close)
(SDB *sdb);
void (*sdb_SetForkState)(PRBool forked);
CK_RV(*sdb_GetNewObjectID)
(SDB *db, CK_OBJECT_HANDLE *object);
CK_RV(*sdb_DestroyMetaData)
(SDB *db, const char *id);
};
CK_RV s_open(const char *directory, const char *certPrefix,

View file

@ -124,7 +124,6 @@ sftkdb_isAuthenticatedAttribute(CK_ATTRIBUTE_TYPE type)
}
return PR_FALSE;
}
/*
* convert a native ULONG to a database ulong. Database ulong's
* are all 4 byte big endian values.
@ -141,7 +140,7 @@ sftk_ULong2SDBULong(unsigned char *data, CK_ULONG value)
/*
* convert a database ulong back to a native ULONG. (reverse of the above
* function.
* function).
*/
static CK_ULONG
sftk_SDBULong2ULong(unsigned char *data)
@ -155,6 +154,39 @@ sftk_SDBULong2ULong(unsigned char *data)
return value;
}
/* certain trust records are default values, which are the values
* returned if the signature check fails anyway.
* In those cases, we can skip the signature check. */
PRBool
sftkdb_isNullTrust(const CK_ATTRIBUTE *template)
{
switch (template->type) {
case CKA_TRUST_SERVER_AUTH:
case CKA_TRUST_CLIENT_AUTH:
case CKA_TRUST_EMAIL_PROTECTION:
case CKA_TRUST_CODE_SIGNING:
if (template->ulValueLen != SDB_ULONG_SIZE) {
break;
}
if (sftk_SDBULong2ULong(template->pValue) ==
CKT_NSS_TRUST_UNKNOWN) {
return PR_TRUE;
}
break;
case CKA_TRUST_STEP_UP_APPROVED:
if (template->ulValueLen != 1) {
break;
}
if (*((unsigned char *)(template->pValue)) == 0) {
return PR_TRUE;
}
break;
default:
break;
}
return PR_FALSE;
}
/*
* fix up the input templates. Our fixed up ints are stored in data and must
* be freed by the caller. The new template must also be freed. If there are no
@ -162,7 +194,7 @@ sftk_SDBULong2ULong(unsigned char *data)
*/
static CK_ATTRIBUTE *
sftkdb_fixupTemplateIn(const CK_ATTRIBUTE *template, int count,
unsigned char **dataOut)
unsigned char **dataOut, int *dataOutSize)
{
int i;
int ulongCount = 0;
@ -170,6 +202,7 @@ sftkdb_fixupTemplateIn(const CK_ATTRIBUTE *template, int count,
CK_ATTRIBUTE *ntemplate;
*dataOut = NULL;
*dataOutSize = 0;
/* first count the number of CK_ULONG attributes */
for (i = 0; i < count; i++) {
@ -201,6 +234,7 @@ sftkdb_fixupTemplateIn(const CK_ATTRIBUTE *template, int count,
return NULL;
}
*dataOut = data;
*dataOutSize = SDB_ULONG_SIZE * ulongCount;
/* copy the old template, fixup the actual ulongs */
for (i = 0; i < count; i++) {
ntemplate[i] = template[i];
@ -245,24 +279,47 @@ sftkdb_TypeString(SFTKDBHandle *handle)
* function will fail with CKR_BUFFER_TOO_SMALL.
*/
static CK_RV
sftkdb_getAttributeSignature(SFTKDBHandle *handle, SFTKDBHandle *keyHandle,
CK_OBJECT_HANDLE objectID, CK_ATTRIBUTE_TYPE type,
SECItem *signText)
sftkdb_getRawAttributeSignature(SFTKDBHandle *handle, SDB *db,
CK_OBJECT_HANDLE objectID,
CK_ATTRIBUTE_TYPE type,
SECItem *signText)
{
SDB *db;
char id[30];
CK_RV crv;
db = SFTK_GET_SDB(keyHandle);
sprintf(id, SFTKDB_META_SIG_TEMPLATE,
sftkdb_TypeString(handle),
(unsigned int)objectID, (unsigned int)type);
snprintf(id, sizeof(id), SFTKDB_META_SIG_TEMPLATE,
sftkdb_TypeString(handle),
(unsigned int)objectID, (unsigned int)type);
crv = (*db->sdb_GetMetaData)(db, id, signText, NULL);
return crv;
}
CK_RV
sftkdb_GetAttributeSignature(SFTKDBHandle *handle, SFTKDBHandle *keyHandle,
CK_OBJECT_HANDLE objectID, CK_ATTRIBUTE_TYPE type,
SECItem *signText)
{
SDB *db = SFTK_GET_SDB(keyHandle);
return sftkdb_getRawAttributeSignature(handle, db, objectID, type, signText);
}
CK_RV
sftkdb_DestroyAttributeSignature(SFTKDBHandle *handle, SDB *db,
CK_OBJECT_HANDLE objectID,
CK_ATTRIBUTE_TYPE type)
{
char id[30];
CK_RV crv;
snprintf(id, sizeof(id), SFTKDB_META_SIG_TEMPLATE,
sftkdb_TypeString(handle),
(unsigned int)objectID, (unsigned int)type);
crv = (*db->sdb_DestroyMetaData)(db, id);
return crv;
}
/*
* Some attributes are signed with an Hmac and a pbe key generated from
* the password. This signature is stored indexed by object handle and
@ -281,9 +338,9 @@ sftkdb_PutAttributeSignature(SFTKDBHandle *handle, SDB *keyTarget,
char id[30];
CK_RV crv;
sprintf(id, SFTKDB_META_SIG_TEMPLATE,
sftkdb_TypeString(handle),
(unsigned int)objectID, (unsigned int)type);
snprintf(id, sizeof(id), SFTKDB_META_SIG_TEMPLATE,
sftkdb_TypeString(handle),
(unsigned int)objectID, (unsigned int)type);
crv = (*keyTarget->sdb_PutMetaData)(keyTarget, id, signText, NULL);
return crv;
@ -363,7 +420,10 @@ sftkdb_fixupTemplateOut(CK_ATTRIBUTE *template, CK_OBJECT_HANDLE objectID,
crv = CKR_USER_NOT_LOGGED_IN;
continue;
}
rv = sftkdb_DecryptAttribute(&handle->passwordKey,
rv = sftkdb_DecryptAttribute(handle,
&handle->passwordKey,
objectID,
ntemplate[i].type,
&cipherText, &plainText);
PZ_Unlock(handle->passwordLock);
if (rv != SECSuccess) {
@ -374,7 +434,7 @@ sftkdb_fixupTemplateOut(CK_ATTRIBUTE *template, CK_OBJECT_HANDLE objectID,
}
PORT_Assert(template[i].ulValueLen >= plainText->len);
if (template[i].ulValueLen < plainText->len) {
SECITEM_FreeItem(plainText, PR_TRUE);
SECITEM_ZfreeItem(plainText, PR_TRUE);
PORT_Memset(template[i].pValue, 0, template[i].ulValueLen);
template[i].ulValueLen = -1;
crv = CKR_GENERAL_ERROR;
@ -384,11 +444,12 @@ sftkdb_fixupTemplateOut(CK_ATTRIBUTE *template, CK_OBJECT_HANDLE objectID,
/* copy the plain text back into the template */
PORT_Memcpy(template[i].pValue, plainText->data, plainText->len);
template[i].ulValueLen = plainText->len;
SECITEM_FreeItem(plainText, PR_TRUE);
SECITEM_ZfreeItem(plainText, PR_TRUE);
}
/* make sure signed attributes are valid */
if (checkSig && sftkdb_isAuthenticatedAttribute(ntemplate[i].type)) {
if (checkSig && sftkdb_isAuthenticatedAttribute(ntemplate[i].type) && !sftkdb_isNullTrust(&ntemplate[i])) {
SECStatus rv;
CK_RV local_crv;
SECItem signText;
SECItem plainText;
unsigned char signData[SDB_MAX_META_DATA_LEN];
@ -396,12 +457,17 @@ sftkdb_fixupTemplateOut(CK_ATTRIBUTE *template, CK_OBJECT_HANDLE objectID,
signText.data = signData;
signText.len = sizeof(signData);
rv = sftkdb_getAttributeSignature(handle, keyHandle,
objectID, ntemplate[i].type, &signText);
if (rv != SECSuccess) {
/* Use a local variable so that we don't clobber any already
* set error. This function returns either CKR_OK or the last
* found error in the template */
local_crv = sftkdb_GetAttributeSignature(handle, keyHandle,
objectID,
ntemplate[i].type,
&signText);
if (local_crv != CKR_OK) {
PORT_Memset(template[i].pValue, 0, template[i].ulValueLen);
template[i].ulValueLen = -1;
crv = CKR_DATA_INVALID; /* better error code? */
crv = local_crv;
continue;
}
@ -421,7 +487,8 @@ sftkdb_fixupTemplateOut(CK_ATTRIBUTE *template, CK_OBJECT_HANDLE objectID,
continue;
}
rv = sftkdb_VerifyAttribute(&keyHandle->passwordKey,
rv = sftkdb_VerifyAttribute(keyHandle,
&keyHandle->passwordKey,
objectID, ntemplate[i].type,
&plainText, &signText);
PZ_Unlock(keyHandle->passwordLock);
@ -529,7 +596,8 @@ sftk_signTemplate(PLArenaPool *arena, SFTKDBHandle *handle,
crv = CKR_USER_NOT_LOGGED_IN;
goto loser;
}
rv = sftkdb_SignAttribute(arena, &keyHandle->passwordKey,
rv = sftkdb_SignAttribute(arena, keyHandle, keyTarget,
&keyHandle->passwordKey,
keyHandle->defaultIterationCount,
objectID, template[i].type,
&plainText, &signText);
@ -538,10 +606,9 @@ sftk_signTemplate(PLArenaPool *arena, SFTKDBHandle *handle,
crv = CKR_GENERAL_ERROR; /* better error code here? */
goto loser;
}
rv = sftkdb_PutAttributeSignature(handle, keyTarget,
objectID, template[i].type, signText);
if (rv != SECSuccess) {
crv = CKR_GENERAL_ERROR; /* better error code here? */
crv = sftkdb_PutAttributeSignature(handle, keyTarget, objectID,
template[i].type, signText);
if (crv != CKR_OK) {
goto loser;
}
}
@ -586,10 +653,56 @@ loser:
return crv;
}
static CK_RV
sftkdb_fixupSignatures(SFTKDBHandle *handle,
SDB *db, CK_OBJECT_HANDLE oldID, CK_OBJECT_HANDLE newID,
CK_ATTRIBUTE *ptemplate, CK_ULONG max_attributes)
{
unsigned int i;
CK_RV crv = CKR_OK;
/* if we don't have a meta table, we didn't write any signature objects */
if ((db->sdb_flags & SDB_HAS_META) == 0) {
return CKR_OK;
}
for (i = 0; i < max_attributes; i++) {
CK_ATTRIBUTE *att = &ptemplate[i];
CK_ATTRIBUTE_TYPE type = att->type;
if (sftkdb_isPrivateAttribute(type)) {
/* move the signature from one object handle to another and delete
* the old entry */
SECItem signature;
unsigned char signData[SDB_MAX_META_DATA_LEN];
signature.data = signData;
signature.len = sizeof(signData);
crv = sftkdb_getRawAttributeSignature(handle, db, oldID, type,
&signature);
if (crv != CKR_OK) {
/* NOTE: if we ever change our default write from AES_CBC
* to AES_KW, We'll need to change this to a continue as
* we won't need the integrity record for AES_KW */
break;
}
crv = sftkdb_PutAttributeSignature(handle, db, newID, type,
&signature);
if (crv != CKR_OK) {
break;
}
/* now get rid of the old one */
crv = sftkdb_DestroyAttributeSignature(handle, db, oldID, type);
if (crv != CKR_OK) {
break;
}
}
}
return crv;
}
CK_ATTRIBUTE *
sftk_ExtractTemplate(PLArenaPool *arena, SFTKObject *object,
SFTKDBHandle *handle, CK_ULONG *pcount,
CK_RV *crv)
SFTKDBHandle *handle, CK_OBJECT_HANDLE objectID,
SDB *db, CK_ULONG *pcount, CK_RV *crv)
{
unsigned int count;
CK_ATTRIBUTE *template;
@ -663,8 +776,11 @@ sftk_ExtractTemplate(PLArenaPool *arena, SFTKObject *object,
*crv = CKR_USER_NOT_LOGGED_IN;
break;
}
rv = sftkdb_EncryptAttribute(arena, &handle->passwordKey,
rv = sftkdb_EncryptAttribute(arena, handle, db,
&handle->passwordKey,
handle->defaultIterationCount,
objectID,
tp->type,
&plainText, &cipherText);
PZ_Unlock(handle->passwordLock);
if (rv == SECSuccess) {
@ -1111,7 +1227,7 @@ sftkdb_write(SFTKDBHandle *handle, SFTKObject *object,
CK_RV crv;
SDB *db;
PRBool inTransaction = PR_FALSE;
CK_OBJECT_HANDLE id;
CK_OBJECT_HANDLE id, candidateID;
*objectID = CK_INVALID_HANDLE;
@ -1136,17 +1252,22 @@ sftkdb_write(SFTKDBHandle *handle, SFTKObject *object,
return CKR_HOST_MEMORY;
}
template = sftk_ExtractTemplate(arena, object, handle, &count, &crv);
if (!template) {
goto loser;
}
crv = (*db->sdb_Begin)(db);
if (crv != CKR_OK) {
goto loser;
}
inTransaction = PR_TRUE;
crv = (*db->sdb_GetNewObjectID)(db, &candidateID);
if (crv != CKR_OK) {
goto loser;
}
template = sftk_ExtractTemplate(arena, object, handle, candidateID, db, &count, &crv);
if (!template) {
goto loser;
}
/*
* We want to make the base database as free from object specific knowledge
* as possible. To maintain compatibility, keep some of the desirable
@ -1174,16 +1295,23 @@ sftkdb_write(SFTKDBHandle *handle, SFTKObject *object,
goto loser;
}
if (id == CK_INVALID_HANDLE) {
*objectID = candidateID;
crv = sftkdb_CreateObject(arena, handle, db, objectID, template, count);
} else {
/* object already exists, modify it's attributes */
*objectID = id;
/* The object ID changed from our candidate, we need to move any
* signature attribute signatures to the new object ID. */
crv = sftkdb_fixupSignatures(handle, db, candidateID, id,
template, count);
if (crv != CKR_OK) {
goto loser;
}
crv = sftkdb_setAttributeValue(arena, handle, db, id, template, count);
}
if (crv != CKR_OK) {
goto loser;
}
crv = (*db->sdb_Commit)(db);
inTransaction = PR_FALSE;
@ -1199,7 +1327,7 @@ loser:
}
if (arena) {
PORT_FreeArena(arena, PR_FALSE);
PORT_FreeArena(arena, PR_TRUE);
}
if (crv == CKR_OK) {
*objectID |= (handle->type | SFTK_TOKEN_TYPE);
@ -1214,6 +1342,7 @@ sftkdb_FindObjectsInit(SFTKDBHandle *handle, const CK_ATTRIBUTE *template,
unsigned char *data = NULL;
CK_ATTRIBUTE *ntemplate = NULL;
CK_RV crv;
int dataSize;
SDB *db;
if (handle == NULL) {
@ -1222,7 +1351,7 @@ sftkdb_FindObjectsInit(SFTKDBHandle *handle, const CK_ATTRIBUTE *template,
db = SFTK_GET_SDB(handle);
if (count != 0) {
ntemplate = sftkdb_fixupTemplateIn(template, count, &data);
ntemplate = sftkdb_fixupTemplateIn(template, count, &data, &dataSize);
if (ntemplate == NULL) {
return CKR_HOST_MEMORY;
}
@ -1232,7 +1361,7 @@ sftkdb_FindObjectsInit(SFTKDBHandle *handle, const CK_ATTRIBUTE *template,
count, find);
if (data) {
PORT_Free(ntemplate);
PORT_Free(data);
PORT_ZFree(data, dataSize);
}
return crv;
}
@ -1279,6 +1408,7 @@ sftkdb_GetAttributeValue(SFTKDBHandle *handle, CK_OBJECT_HANDLE objectID,
CK_RV crv, crv2;
CK_ATTRIBUTE *ntemplate;
unsigned char *data = NULL;
int dataSize = 0;
SDB *db;
if (handle == NULL) {
@ -1319,7 +1449,7 @@ sftkdb_GetAttributeValue(SFTKDBHandle *handle, CK_OBJECT_HANDLE objectID,
if (count == 0) {
return CKR_OK;
}
ntemplate = sftkdb_fixupTemplateIn(template, count, &data);
ntemplate = sftkdb_fixupTemplateIn(template, count, &data, &dataSize);
if (ntemplate == NULL) {
return CKR_HOST_MEMORY;
}
@ -1332,7 +1462,7 @@ sftkdb_GetAttributeValue(SFTKDBHandle *handle, CK_OBJECT_HANDLE objectID,
crv = crv2;
if (data) {
PORT_Free(ntemplate);
PORT_Free(data);
PORT_ZFree(data, dataSize);
}
return crv;
}
@ -1348,6 +1478,7 @@ sftkdb_SetAttributeValue(SFTKDBHandle *handle, SFTKObject *object,
CK_RV crv = CKR_OK;
CK_OBJECT_HANDLE objectID = (object->handle & SFTK_OBJ_ID_MASK);
PRBool inTransaction = PR_FALSE;
int dataSize;
if (handle == NULL) {
return CKR_TOKEN_WRITE_PROTECTED;
@ -1369,7 +1500,7 @@ sftkdb_SetAttributeValue(SFTKDBHandle *handle, SFTKObject *object,
return CKR_USER_NOT_LOGGED_IN;
}
ntemplate = sftkdb_fixupTemplateIn(template, count, &data);
ntemplate = sftkdb_fixupTemplateIn(template, count, &data, &dataSize);
if (ntemplate == NULL) {
return CKR_HOST_MEMORY;
}
@ -1404,7 +1535,7 @@ loser:
}
if (data) {
PORT_Free(ntemplate);
PORT_Free(data);
PORT_ZFree(data, dataSize);
}
if (arena) {
PORT_FreeArena(arena, PR_FALSE);
@ -1413,7 +1544,8 @@ loser:
}
CK_RV
sftkdb_DestroyObject(SFTKDBHandle *handle, CK_OBJECT_HANDLE objectID)
sftkdb_DestroyObject(SFTKDBHandle *handle, CK_OBJECT_HANDLE objectID,
CK_OBJECT_CLASS objclass)
{
CK_RV crv = CKR_OK;
SDB *db;
@ -1423,14 +1555,60 @@ sftkdb_DestroyObject(SFTKDBHandle *handle, CK_OBJECT_HANDLE objectID)
}
db = SFTK_GET_SDB(handle);
objectID &= SFTK_OBJ_ID_MASK;
crv = (*db->sdb_Begin)(db);
if (crv != CKR_OK) {
goto loser;
return crv;
}
crv = (*db->sdb_DestroyObject)(db, objectID);
if (crv != CKR_OK) {
goto loser;
}
/* if the database supports meta data, delete any old signatures
* that we may have added */
if ((db->sdb_flags & SDB_HAS_META) == SDB_HAS_META) {
SDB *keydb = db;
if (handle->type == SFTK_KEYDB_TYPE) {
/* delete any private attribute signatures that might exist */
(void)sftkdb_DestroyAttributeSignature(handle, keydb, objectID,
CKA_VALUE);
(void)sftkdb_DestroyAttributeSignature(handle, keydb, objectID,
CKA_PRIVATE_EXPONENT);
(void)sftkdb_DestroyAttributeSignature(handle, keydb, objectID,
CKA_PRIME_1);
(void)sftkdb_DestroyAttributeSignature(handle, keydb, objectID,
CKA_PRIME_2);
(void)sftkdb_DestroyAttributeSignature(handle, keydb, objectID,
CKA_EXPONENT_1);
(void)sftkdb_DestroyAttributeSignature(handle, keydb, objectID,
CKA_EXPONENT_2);
(void)sftkdb_DestroyAttributeSignature(handle, keydb, objectID,
CKA_COEFFICIENT);
} else {
keydb = SFTK_GET_SDB(handle->peerDB);
}
/* now destroy any authenticated attributes that may exist */
(void)sftkdb_DestroyAttributeSignature(handle, keydb, objectID,
CKA_MODULUS);
(void)sftkdb_DestroyAttributeSignature(handle, keydb, objectID,
CKA_PUBLIC_EXPONENT);
(void)sftkdb_DestroyAttributeSignature(handle, keydb, objectID,
CKA_CERT_SHA1_HASH);
(void)sftkdb_DestroyAttributeSignature(handle, keydb, objectID,
CKA_CERT_MD5_HASH);
(void)sftkdb_DestroyAttributeSignature(handle, keydb, objectID,
CKA_TRUST_SERVER_AUTH);
(void)sftkdb_DestroyAttributeSignature(handle, keydb, objectID,
CKA_TRUST_CLIENT_AUTH);
(void)sftkdb_DestroyAttributeSignature(handle, keydb, objectID,
CKA_TRUST_EMAIL_PROTECTION);
(void)sftkdb_DestroyAttributeSignature(handle, keydb, objectID,
CKA_TRUST_CODE_SIGNING);
(void)sftkdb_DestroyAttributeSignature(handle, keydb, objectID,
CKA_TRUST_STEP_UP_APPROVED);
(void)sftkdb_DestroyAttributeSignature(handle, keydb, objectID,
CKA_NSS_OVERRIDE_EXTENSIONS);
}
crv = (*db->sdb_Commit)(db);
loser:
if (crv != CKR_OK) {
@ -1464,14 +1642,14 @@ sftkdb_CloseDB(SFTKDBHandle *handle)
PZ_Lock(handle->passwordLock);
}
if (handle->passwordKey.data) {
PORT_ZFree(handle->passwordKey.data, handle->passwordKey.len);
SECITEM_ZfreeItem(&handle->passwordKey, PR_FALSE);
}
if (handle->passwordLock) {
PZ_Unlock(handle->passwordLock);
SKIP_AFTER_FORK(PZ_DestroyLock(handle->passwordLock));
}
if (handle->updatePasswordKey) {
SECITEM_FreeItem(handle->updatePasswordKey, PR_TRUE);
SECITEM_ZfreeItem(handle->updatePasswordKey, PR_TRUE);
}
if (handle->updateID) {
PORT_Free(handle->updateID);
@ -1597,7 +1775,7 @@ static const CK_ATTRIBUTE_TYPE known_attributes[] = {
CKA_TRUST_EMAIL_PROTECTION, CKA_TRUST_IPSEC_END_SYSTEM,
CKA_TRUST_IPSEC_TUNNEL, CKA_TRUST_IPSEC_USER, CKA_TRUST_TIME_STAMPING,
CKA_TRUST_STEP_UP_APPROVED, CKA_CERT_SHA1_HASH, CKA_CERT_MD5_HASH,
CKA_NETSCAPE_DB, CKA_NETSCAPE_TRUST, CKA_NSS_OVERRIDE_EXTENSIONS,
CKA_NSS_DB, CKA_NSS_TRUST, CKA_NSS_OVERRIDE_EXTENSIONS,
CKA_PUBLIC_KEY_INFO
};
@ -1901,11 +2079,10 @@ sftkdb_reconcileTrustEntry(PLArenaPool *arena, CK_ATTRIBUTE *target,
return SFTKDB_DROP_ATTRIBUTE;
}
const CK_ATTRIBUTE_TYPE sftkdb_trustList[] =
{ CKA_TRUST_SERVER_AUTH, CKA_TRUST_CLIENT_AUTH,
CKA_TRUST_CODE_SIGNING, CKA_TRUST_EMAIL_PROTECTION,
CKA_TRUST_IPSEC_TUNNEL, CKA_TRUST_IPSEC_USER,
CKA_TRUST_TIME_STAMPING };
const CK_ATTRIBUTE_TYPE sftkdb_trustList[] = { CKA_TRUST_SERVER_AUTH, CKA_TRUST_CLIENT_AUTH,
CKA_TRUST_CODE_SIGNING, CKA_TRUST_EMAIL_PROTECTION,
CKA_TRUST_IPSEC_TUNNEL, CKA_TRUST_IPSEC_USER,
CKA_TRUST_TIME_STAMPING };
#define SFTK_TRUST_TEMPLATE_COUNT \
(sizeof(sftkdb_trustList) / sizeof(sftkdb_trustList[0]))
@ -2148,6 +2325,56 @@ sftkdb_updateObjectTemplate(PLArenaPool *arena, SDB *db,
return SFTKDB_ADD_OBJECT;
}
static CK_RV
sftkdb_updateIntegrity(PLArenaPool *arena, SFTKDBHandle *handle,
SDB *source, CK_OBJECT_HANDLE sourceID,
SDB *target, CK_OBJECT_HANDLE targetID,
CK_ATTRIBUTE *ptemplate, CK_ULONG max_attributes)
{
unsigned int i;
CK_RV global_crv = CKR_OK;
/* if the target doesn't have META data, don't need to do anything */
if ((target->sdb_flags & SDB_HAS_META) == 0) {
return CKR_OK;
}
/* if the source doesn't have meta data, then the record won't require
* integrity */
if ((source->sdb_flags & SDB_HAS_META) == 0) {
return CKR_OK;
}
for (i = 0; i < max_attributes; i++) {
CK_ATTRIBUTE *att = &ptemplate[i];
CK_ATTRIBUTE_TYPE type = att->type;
if (sftkdb_isPrivateAttribute(type)) {
/* copy integrity signatures associated with this record (if any) */
SECItem signature;
unsigned char signData[SDB_MAX_META_DATA_LEN];
CK_RV crv;
signature.data = signData;
signature.len = sizeof(signData);
crv = sftkdb_getRawAttributeSignature(handle, source, sourceID, type,
&signature);
if (crv != CKR_OK) {
/* old databases don't have signature IDs because they are
* 3DES encrypted. Since we know not to look for integrity
* for 3DES records it's OK not to find one here. A new record
* will be created when we reencrypt using AES CBC */
continue;
}
crv = sftkdb_PutAttributeSignature(handle, target, targetID, type,
&signature);
if (crv != CKR_OK) {
/* we had a signature in the source db, but we couldn't store
* it in the target, remember the error so we can report it. */
global_crv = crv;
}
}
}
return global_crv;
}
#define MAX_ATTRIBUTES 500
static CK_RV
sftkdb_mergeObject(SFTKDBHandle *handle, CK_OBJECT_HANDLE id,
@ -2160,6 +2387,7 @@ sftkdb_mergeObject(SFTKDBHandle *handle, CK_OBJECT_HANDLE id,
SDB *source = handle->update;
SDB *target = handle->db;
unsigned int i;
CK_OBJECT_HANDLE newID = CK_INVALID_HANDLE;
CK_RV crv;
PLArenaPool *arena = NULL;
@ -2199,27 +2427,26 @@ sftkdb_mergeObject(SFTKDBHandle *handle, CK_OBJECT_HANDLE id,
objectType = sftkdb_getULongFromTemplate(CKA_CLASS, ptemplate,
max_attributes);
/*
* Update Object updates the object template if necessary then returns
* whether or not we need to actually write the object out to our target
* database.
*/
if (!handle->updateID) {
crv = sftkdb_CreateObject(arena, handle, target, &id,
crv = sftkdb_CreateObject(arena, handle, target, &newID,
ptemplate, max_attributes);
} else {
sftkdbUpdateStatus update_status;
update_status = sftkdb_updateObjectTemplate(arena, target,
objectType, ptemplate, &max_attributes, &id);
objectType, ptemplate, &max_attributes, &newID);
switch (update_status) {
case SFTKDB_ADD_OBJECT:
crv = sftkdb_CreateObject(arena, handle, target, &id,
crv = sftkdb_CreateObject(arena, handle, target, &newID,
ptemplate, max_attributes);
break;
case SFTKDB_MODIFY_OBJECT:
crv = sftkdb_setAttributeValue(arena, handle, target,
id, ptemplate, max_attributes);
newID, ptemplate, max_attributes);
break;
case SFTKDB_DO_NOTHING:
case SFTKDB_DROP_ATTRIBUTE:
@ -2227,6 +2454,13 @@ sftkdb_mergeObject(SFTKDBHandle *handle, CK_OBJECT_HANDLE id,
}
}
/* if keyDB copy any meta data hashes to target, Update for the new
* object ID */
if (crv == CKR_OK) {
crv = sftkdb_updateIntegrity(arena, handle, source, id, target, newID,
ptemplate, max_attributes);
}
loser:
if (arena) {
PORT_FreeArena(arena, PR_TRUE);
@ -2255,14 +2489,13 @@ sftkdb_Update(SFTKDBHandle *handle, SECItem *key)
if (handle->update == NULL) {
return CKR_OK;
}
/*
* put the whole update under a transaction. This allows us to handle
* any possible race conditions between with the updateID check.
*/
crv = (*handle->db->sdb_Begin)(handle->db);
if (crv != CKR_OK) {
goto loser;
return crv;
}
inTransaction = PR_TRUE;
@ -2487,7 +2720,7 @@ sftkdb_ResetKeyDB(SFTKDBHandle *handle)
{
CK_RV crv;
/* only reset the key db */
/* only rest the key db */
if (handle->type != SFTK_KEYDB_TYPE) {
return SECFailure;
}
@ -2505,6 +2738,7 @@ sftkdb_ResetKeyDB(SFTKDBHandle *handle)
return SECSuccess;
}
#ifndef NSS_DISABLE_DBM
static PRBool
sftk_oldVersionExists(const char *dir, int version)
{
@ -2608,6 +2842,7 @@ sftk_hasLegacyDB(const char *confdir, const char *certPrefix,
PR_smprintf_free(dir);
return exists;
}
#endif /* NSS_DISABLE_DBM */
/*
* initialize certificate and key database handles as a pair.
@ -2631,7 +2866,9 @@ sftk_DBInit(const char *configdir, const char *certPrefix,
CK_RV crv = CKR_OK;
int flags = SDB_RDONLY;
PRBool newInit = PR_FALSE;
#ifndef NSS_DISABLE_DBM
PRBool needUpdate = PR_FALSE;
#endif /* NSS_DISABLE_DBM */
char *nconfdir = NULL;
PRBool legacy = PR_TRUE;
@ -2654,6 +2891,7 @@ sftk_DBInit(const char *configdir, const char *certPrefix,
* now initialize the appropriate database
*/
switch (dbType) {
#ifndef NSS_DISABLE_DBM
case NSS_DB_TYPE_LEGACY:
crv = sftkdbCall_open(confdir, certPrefix, keyPrefix, 8, 3, flags,
noCertDB ? NULL : &certSDB, noKeyDB ? NULL : &keySDB);
@ -2662,12 +2900,14 @@ sftk_DBInit(const char *configdir, const char *certPrefix,
crv = sftkdbCall_open(configdir, certPrefix, keyPrefix, 8, 3, flags,
noCertDB ? NULL : &certSDB, noKeyDB ? NULL : &keySDB);
break;
#endif /* NSS_DISABLE_DBM */
case NSS_DB_TYPE_SQL:
case NSS_DB_TYPE_EXTERN: /* SHOULD open a loadable db */
crv = s_open(confdir, certPrefix, keyPrefix, 9, 4, flags,
noCertDB ? NULL : &certSDB, noKeyDB ? NULL : &keySDB, &newInit);
legacy = PR_FALSE;
#ifndef NSS_DISABLE_DBM
/*
* if we failed to open the DB's read only, use the old ones if
* the exists.
@ -2717,6 +2957,7 @@ sftk_DBInit(const char *configdir, const char *certPrefix,
needUpdate = PR_TRUE;
}
}
#endif /* NSS_DISABLE_DBM */
break;
default:
crv = CKR_GENERAL_ERROR; /* can't happen, EvaluationConfigDir MUST
@ -2745,6 +2986,7 @@ sftk_DBInit(const char *configdir, const char *certPrefix,
(*keyDB)->peerDB = *certDB;
}
#ifndef NSS_DISABLE_DBM
/*
* if we need to update, open the legacy database and
* mark the handle as needing update.
@ -2782,6 +3024,8 @@ sftk_DBInit(const char *configdir, const char *certPrefix,
}
}
}
#endif /* NSS_DISABLE_DBM */
done:
if (appName) {
PORT_Free(appName);
@ -2796,6 +3040,8 @@ CK_RV
sftkdb_Shutdown(void)
{
s_shutdown();
#ifndef NSS_DISABLE_DBM
sftkdbCall_Shutdown();
#endif /* NSS_DISABLE_DBM */
return CKR_OK;
}

View file

@ -17,7 +17,8 @@ CK_RV sftkdb_GetAttributeValue(SFTKDBHandle *handle,
CK_OBJECT_HANDLE object_id, CK_ATTRIBUTE *template, CK_ULONG count);
CK_RV sftkdb_SetAttributeValue(SFTKDBHandle *handle, SFTKObject *object,
const CK_ATTRIBUTE *template, CK_ULONG count);
CK_RV sftkdb_DestroyObject(SFTKDBHandle *handle, CK_OBJECT_HANDLE object_id);
CK_RV sftkdb_DestroyObject(SFTKDBHandle *handle, CK_OBJECT_HANDLE object_id,
CK_OBJECT_CLASS objclass);
CK_RV sftkdb_closeDB(SFTKDBHandle *handle);
/* keydb functions */

View file

@ -39,16 +39,26 @@ struct SFTKDBHandleStr {
#define SFTK_GET_SDB(handle) \
((handle)->update ? (handle)->update : (handle)->db)
SECStatus sftkdb_DecryptAttribute(SECItem *passKey, SECItem *cipherText,
SECItem **plainText);
SECStatus sftkdb_EncryptAttribute(PLArenaPool *arena, SECItem *passKey,
int iterationCount, SECItem *plainText,
SECItem **cipherText);
SECStatus sftkdb_SignAttribute(PLArenaPool *arena, SECItem *passKey,
SECStatus sftkdb_DecryptAttribute(SFTKDBHandle *handle,
SECItem *passKey,
CK_OBJECT_HANDLE id,
CK_ATTRIBUTE_TYPE attrType,
SECItem *cipherText, SECItem **plainText);
SECStatus sftkdb_EncryptAttribute(PLArenaPool *arena,
SFTKDBHandle *handle, SDB *db,
SECItem *passKey,
int iterationCount,
CK_OBJECT_HANDLE id,
CK_ATTRIBUTE_TYPE attrType,
SECItem *plainText, SECItem **cipherText);
SECStatus sftkdb_SignAttribute(PLArenaPool *arena,
SFTKDBHandle *handle, SDB *db,
SECItem *passKey,
int iterationCount, CK_OBJECT_HANDLE objectID,
CK_ATTRIBUTE_TYPE attrType,
SECItem *plainText, SECItem **sigText);
SECStatus sftkdb_VerifyAttribute(SECItem *passKey,
SECStatus sftkdb_VerifyAttribute(SFTKDBHandle *handle,
SECItem *passKey,
CK_OBJECT_HANDLE objectID,
CK_ATTRIBUTE_TYPE attrType,
SECItem *plainText, SECItem *sigText);
@ -59,5 +69,14 @@ CK_RV sftkdb_Update(SFTKDBHandle *handle, SECItem *key);
CK_RV sftkdb_PutAttributeSignature(SFTKDBHandle *handle,
SDB *keyTarget, CK_OBJECT_HANDLE objectID,
CK_ATTRIBUTE_TYPE type, SECItem *signText);
CK_RV sftkdb_GetAttributeSignature(SFTKDBHandle *handle,
SFTKDBHandle *keyHandle,
CK_OBJECT_HANDLE objectID,
CK_ATTRIBUTE_TYPE type,
SECItem *signText);
CK_RV
sftkdb_DestroyAttributeSignature(SFTKDBHandle *handle, SDB *db,
CK_OBJECT_HANDLE objectID,
CK_ATTRIBUTE_TYPE type);
#endif

File diff suppressed because it is too large Load diff

View file

@ -9,10 +9,10 @@
#include "softoken.h"
#include "hmacct.h"
/* HMACMechanismToHash converts a PKCS#11 MAC mechanism into a freebl hash
/* sftk_HMACMechanismToHash converts a PKCS#11 MAC mechanism into a freebl hash
* type. */
static HASH_HashType
HMACMechanismToHash(CK_MECHANISM_TYPE mech)
HASH_HashType
sftk_HMACMechanismToHash(CK_MECHANISM_TYPE mech)
{
switch (mech) {
case CKM_MD2_HMAC:
@ -50,7 +50,7 @@ SetupMAC(CK_MECHANISM_PTR mech, SFTKObject *key)
return NULL;
}
alg = HMACMechanismToHash(params->macAlg);
alg = sftk_HMACMechanismToHash(params->macAlg);
if (alg == HASH_AlgNULL) {
return NULL;
}
@ -69,6 +69,7 @@ SetupMAC(CK_MECHANISM_PTR mech, SFTKObject *key)
ctx = PORT_Alloc(sizeof(sftk_MACConstantTimeCtx));
if (!ctx) {
PORT_Memset(secret, 0, secretLength);
return NULL;
}
@ -76,6 +77,7 @@ SetupMAC(CK_MECHANISM_PTR mech, SFTKObject *key)
ctx->secretLength = secretLength;
ctx->hash = HASH_GetRawHashObject(alg);
ctx->totalLength = params->ulBodyTotalLen;
PORT_Memset(secret, 0, secretLength);
return ctx;
}
@ -188,7 +190,7 @@ sftk_MACConstantTime_EndHash(void *pctx, void *out, unsigned int *outLength,
void
sftk_MACConstantTime_DestroyContext(void *pctx, PRBool free)
{
PORT_Free(pctx);
PORT_ZFree(pctx, sizeof(sftk_MACConstantTimeCtx));
}
CK_RV
@ -217,7 +219,7 @@ 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);
PRBool isFIPS = sftk_isFIPS(key->slot->slotID);
CK_RV ret = CKR_OK;
/* Find the actual value of the key. */
@ -232,7 +234,9 @@ sftk_MAC_Init(sftk_MACCtx *ctx, CK_MECHANISM_TYPE mech, SFTKObject *key)
keyval->attrib.ulValueLen, isFIPS);
done:
sftk_FreeAttribute(keyval);
if (keyval) {
sftk_FreeAttribute(keyval);
}
return ret;
}
@ -261,7 +265,7 @@ sftk_MAC_InitRaw(sftk_MACCtx *ctx, CK_MECHANISM_TYPE mech, const unsigned char *
case CKM_SHA256_HMAC:
case CKM_SHA384_HMAC:
case CKM_SHA512_HMAC:
hashObj = HASH_GetRawHashObject(HMACMechanismToHash(mech));
hashObj = HASH_GetRawHashObject(sftk_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
@ -355,7 +359,7 @@ sftk_MAC_Reset(sftk_MACCtx *ctx)
}
CK_RV
sftk_MAC_Update(sftk_MACCtx *ctx, CK_BYTE_PTR data, unsigned int data_len)
sftk_MAC_Update(sftk_MACCtx *ctx, const CK_BYTE *data, unsigned int data_len)
{
switch (ctx->mech) {
case CKM_MD2_HMAC:

View file

@ -189,10 +189,11 @@ fail:
/* encode the final pad block of aes xcbc, padBuf is modified */
CK_RV
sftk_xcbc_mac_pad(unsigned char *padBuf, unsigned int bufLen, int blockSize,
const unsigned char *k2, const unsigned char *k3)
sftk_xcbc_mac_pad(unsigned char *padBuf, unsigned int bufLen,
unsigned int blockSize, const unsigned char *k2,
const unsigned char *k3)
{
int i;
unsigned int i;
if (bufLen == blockSize) {
for (i = 0; i < blockSize; i++) {
padBuf[i] ^= k2[i];
@ -464,7 +465,7 @@ sftk_ike_prf(CK_SESSION_HANDLE hSession, const SFTKAttribute *inKey,
SFTKObject *newKeyObj = NULL;
unsigned char outKeyData[HASH_LENGTH_MAX];
unsigned char *newInKey = NULL;
unsigned int newInKeySize;
unsigned int newInKeySize = 0;
unsigned int macSize;
CK_RV crv = CKR_OK;
prfContext context;
@ -544,7 +545,7 @@ sftk_ike_prf(CK_SESSION_HANDLE hSession, const SFTKAttribute *inKey,
crv = sftk_forceAttribute(outKey, CKA_VALUE, outKeyData, macSize);
fail:
if (newInKey) {
PORT_Free(newInKey);
PORT_ZFree(newInKey, newInKeySize);
}
if (newKeyValue) {
sftk_FreeAttribute(newKeyValue);
@ -697,42 +698,80 @@ fail:
* This function returns (from rfc2409 appendix b):
* Ka = K1 | K2 | K3 | K4 |... Kn
* where:
* K1 = prf(K, 0x00)
* K2 = prf(K, K1)
* K3 = prf(K, K2)
* K4 = prf(K, K3)
* K1 = prf(K, [gxyKey]|[extraData]) or prf(K, 0) if gxyKey and extraData
* ar not present.
* K2 = prf(K, K1|[gxyKey]|[extraData])
* K3 = prf(K, K2|[gxyKey]|[extraData])
* K4 = prf(K, K3|[gxyKey]|[extraData])
* .
* Kn = prf(K, K(n-1))
* Kn = prf(K, K(n-1)|[gxyKey]|[extraData])
* K = inKey
*/
CK_RV
sftk_ike1_appendix_b_prf(CK_SESSION_HANDLE hSession, const SFTKAttribute *inKey,
const CK_MECHANISM_TYPE *mech, SFTKObject *outKey, unsigned int keySize)
const CK_NSS_IKE1_APP_B_PRF_DERIVE_PARAMS *params,
SFTKObject *outKey, unsigned int keySize)
{
SFTKAttribute *gxyKeyValue = NULL;
SFTKObject *gxyKeyObj = NULL;
unsigned char *outKeyData = NULL;
unsigned char *thisKey = NULL;
unsigned char *lastKey = NULL;
unsigned int macSize;
unsigned int outKeySize;
unsigned int genKeySize;
PRBool quickMode = PR_FALSE;
CK_RV crv;
prfContext context;
crv = prf_setup(&context, *mech);
if ((params->ulExtraDataLen != 0) && (params->pExtraData == NULL)) {
return CKR_ARGUMENTS_BAD;
}
crv = prf_setup(&context, params->prfMechanism);
if (crv != CKR_OK) {
return crv;
}
if (params->bHasKeygxy) {
SFTKSession *session;
session = sftk_SessionFromHandle(hSession);
if (session == NULL) {
return CKR_SESSION_HANDLE_INVALID;
}
gxyKeyObj = sftk_ObjectFromHandle(params->hKeygxy, session);
sftk_FreeSession(session);
if (gxyKeyObj == NULL) {
crv = CKR_KEY_HANDLE_INVALID;
goto fail;
}
gxyKeyValue = sftk_FindAttribute(gxyKeyObj, CKA_VALUE);
if (gxyKeyValue == NULL) {
crv = CKR_KEY_HANDLE_INVALID;
goto fail;
}
quickMode = PR_TRUE;
}
if (params->ulExtraDataLen != 0) {
quickMode = PR_TRUE;
}
macSize = prf_length(&context);
if (keySize == 0) {
keySize = macSize;
}
if (keySize <= inKey->attrib.ulValueLen) {
/* In appendix B, we are just expanding or contracting a single key.
* If the input key is less than or equal to the the key size we want,
* just subset the original key. In quick mode we are actually getting
* new keys (salted with our seed data and our gxy key), so we want to
* run through our algorithm */
if ((!quickMode) && (keySize <= inKey->attrib.ulValueLen)) {
return sftk_forceAttribute(outKey, CKA_VALUE,
inKey->attrib.pValue, keySize);
}
outKeySize = PR_ROUNDUP(keySize, macSize);
outKeyData = PORT_Alloc(outKeySize);
if (outKeyData == NULL) {
@ -741,25 +780,47 @@ sftk_ike1_appendix_b_prf(CK_SESSION_HANDLE hSession, const SFTKAttribute *inKey,
}
/*
* this loop generates on block of the prf, basically
* kn = prf(key, Kn-1)
* Kn is thisKey, Kn-1 is lastKey
* key is inKey
*/
* this loop generates on block of the prf, basically
* kn = prf(key, Kn-1 | [Keygxy] | [ExtraData])
* Kn is thisKey, Kn-1 is lastKey
* key is inKey
*/
thisKey = outKeyData;
for (genKeySize = 0; genKeySize <= keySize; genKeySize += macSize) {
for (genKeySize = 0; genKeySize < keySize; genKeySize += macSize) {
PRBool hashedData = PR_FALSE;
crv = prf_init(&context, inKey->attrib.pValue, inKey->attrib.ulValueLen);
if (crv != CKR_OK) {
goto fail;
}
if (lastKey == NULL) {
if (lastKey != NULL) {
crv = prf_update(&context, lastKey, macSize);
if (crv != CKR_OK) {
goto fail;
}
hashedData = PR_TRUE;
}
if (gxyKeyValue != NULL) {
crv = prf_update(&context, gxyKeyValue->attrib.pValue,
gxyKeyValue->attrib.ulValueLen);
if (crv != CKR_OK) {
goto fail;
}
hashedData = PR_TRUE;
}
if (params->ulExtraDataLen != 0) {
crv = prf_update(&context, params->pExtraData, params->ulExtraDataLen);
if (crv != CKR_OK) {
goto fail;
}
hashedData = PR_TRUE;
}
/* if we haven't hashed anything yet, hash a zero */
if (hashedData == PR_FALSE) {
const unsigned char zero = 0;
crv = prf_update(&context, &zero, 1);
} else {
crv = prf_update(&context, lastKey, macSize);
}
if (crv != CKR_OK) {
goto fail;
if (crv != CKR_OK) {
goto fail;
}
}
crv = prf_final(&context, thisKey, macSize);
if (crv != CKR_OK) {
@ -770,6 +831,12 @@ sftk_ike1_appendix_b_prf(CK_SESSION_HANDLE hSession, const SFTKAttribute *inKey,
}
crv = sftk_forceAttribute(outKey, CKA_VALUE, outKeyData, keySize);
fail:
if (gxyKeyValue) {
sftk_FreeAttribute(gxyKeyValue);
}
if (gxyKeyObj) {
sftk_FreeObject(gxyKeyObj);
}
if (outKeyData) {
PORT_ZFree(outKeyData, outKeySize);
}
@ -800,10 +867,12 @@ fail:
* K = inKey, S = seedKey | seedData
*/
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)
static CK_RV
sftk_ike_prf_plus_raw(CK_SESSION_HANDLE hSession,
const unsigned char *inKeyData, CK_ULONG inKeyLen,
const CK_NSS_IKE_PRF_PLUS_DERIVE_PARAMS *params,
unsigned char **outKeyDataPtr, unsigned int *outKeySizePtr,
unsigned int keySize)
{
SFTKAttribute *seedValue = NULL;
SFTKObject *seedKeyObj = NULL;
@ -869,8 +938,7 @@ sftk_ike_prf_plus(CK_SESSION_HANDLE hSession, const SFTKAttribute *inKey,
crv = CKR_KEY_SIZE_RANGE;
goto fail;
}
crv = prf_init(&context, inKey->attrib.pValue,
inKey->attrib.ulValueLen);
crv = prf_init(&context, inKeyData, inKeyLen);
if (crv != CKR_OK) {
goto fail;
}
@ -909,7 +977,9 @@ sftk_ike_prf_plus(CK_SESSION_HANDLE hSession, const SFTKAttribute *inKey,
lastKey = thisKey;
thisKey += macSize;
}
crv = sftk_forceAttribute(outKey, CKA_VALUE, outKeyData, keySize);
*outKeyDataPtr = outKeyData;
*outKeySizePtr = outKeySize;
outKeyData = NULL; /* don't free it here, our caller will free it */
fail:
if (outKeyData) {
PORT_ZFree(outKeyData, outKeySize);
@ -924,6 +994,30 @@ fail:
return crv;
}
/*
* ike prf + with code to deliever results tosoftoken objects.
*/
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)
{
unsigned char *outKeyData = NULL;
unsigned int outKeySize;
CK_RV crv;
crv = sftk_ike_prf_plus_raw(hSession, inKey->attrib.pValue,
inKey->attrib.ulValueLen, params,
&outKeyData, &outKeySize, keySize);
if (crv != CKR_OK) {
return crv;
}
crv = sftk_forceAttribute(outKey, CKA_VALUE, outKeyData, keySize);
PORT_ZFree(outKeyData, outKeySize);
return crv;
}
/* sftk_aes_xcbc_new_keys:
*
* aes xcbc creates 3 new keys from the input key. The first key will be the
@ -1239,7 +1333,21 @@ sftk_fips_IKE_PowerUpSelfTests(void)
0x7f, 0x6f, 0x77, 0x2e, 0x5d, 0x65, 0xb5, 0x8e,
0xb1, 0x13, 0x40, 0x96, 0xe8, 0x47, 0x8d, 0x2b
};
static const PRUint8 ike_known_sha256_prf_plus[] = {
0xe6, 0xf1, 0x9b, 0x4a, 0x02, 0xe9, 0x73, 0x72,
0x93, 0x9f, 0xdb, 0x46, 0x1d, 0xb1, 0x49, 0xcb,
0x53, 0x08, 0x98, 0x3d, 0x41, 0x36, 0xfa, 0x8b,
0x47, 0x04, 0x49, 0x11, 0x0d, 0x6e, 0x96, 0x1d,
0xab, 0xbe, 0x94, 0x28, 0xa0, 0xb7, 0x9c, 0xa3,
0x29, 0xe1, 0x40, 0xf8, 0xf8, 0x88, 0xb9, 0xb5,
0x40, 0xd4, 0x54, 0x4d, 0x25, 0xab, 0x94, 0xd4,
0x98, 0xd8, 0x00, 0xbf, 0x6f, 0xef, 0xe8, 0x39
};
SECStatus rv;
CK_RV crv;
unsigned char *outKeyData = NULL;
unsigned int outKeySize;
CK_NSS_IKE_PRF_PLUS_DERIVE_PARAMS ike_params;
rv = prf_test(CKM_AES_XCBC_MAC,
ike_xcbc_known_key, sizeof(ike_xcbc_known_key),
@ -1290,5 +1398,22 @@ sftk_fips_IKE_PowerUpSelfTests(void)
ike_sha512_known_plain_text,
sizeof(ike_sha512_known_plain_text),
ike_sha512_known_mac, sizeof(ike_sha512_known_mac));
ike_params.prfMechanism = CKM_SHA256_HMAC;
ike_params.bHasSeedKey = PR_FALSE;
ike_params.hSeedKey = CK_INVALID_HANDLE;
ike_params.pSeedData = (CK_BYTE_PTR)ike_sha256_known_plain_text;
ike_params.ulSeedDataLen = sizeof(ike_sha256_known_plain_text);
crv = sftk_ike_prf_plus_raw(CK_INVALID_HANDLE, ike_sha256_known_key,
sizeof(ike_sha256_known_key), &ike_params,
&outKeyData, &outKeySize, 64);
if ((crv != CKR_OK) ||
(outKeySize != sizeof(ike_known_sha256_prf_plus)) ||
(PORT_Memcmp(outKeyData, ike_known_sha256_prf_plus,
sizeof(ike_known_sha256_prf_plus)) != 0)) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
PORT_ZFree(outKeyData, outKeySize);
return rv;
}

View file

@ -0,0 +1,377 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
* This file implements PKCS 11 on top of our existing security modules
*
* Implement the PKCS #11 v3.0 Message interfaces
*/
#include "seccomon.h"
#include "pkcs11.h"
#include "pkcs11i.h"
#include "blapi.h"
#include "prenv.h"
#include "softoken.h"
static SECStatus
sftk_ChaCha20_Poly1305_Message_Encrypt(ChaCha20Poly1305Context *ctx,
unsigned char *cipherText, unsigned int *cipherTextLen,
unsigned int maxOutLen, const unsigned char *plainText,
unsigned int plainTextLen,
CK_SALSA20_CHACHA20_POLY1305_MSG_PARAMS *params,
unsigned int paramsLen, const unsigned char *aad,
unsigned int aadLen)
{
return ChaCha20Poly1305_Encrypt(ctx, cipherText, cipherTextLen, maxOutLen,
plainText, plainTextLen, params->pNonce, params->ulNonceLen,
aad, aadLen, params->pTag);
}
static SECStatus
sftk_ChaCha20_Poly1305_Message_Decrypt(ChaCha20Poly1305Context *ctx,
unsigned char *plainText, unsigned int *plainTextLen,
unsigned int maxOutLen, const unsigned char *cipherText,
unsigned int cipherTextLen,
CK_SALSA20_CHACHA20_POLY1305_MSG_PARAMS *params,
unsigned int paramsLen, const unsigned char *aad,
unsigned int aadLen)
{
return ChaCha20Poly1305_Decrypt(ctx, plainText, plainTextLen, maxOutLen,
cipherText, cipherTextLen, params->pNonce, params->ulNonceLen,
aad, aadLen, params->pTag);
}
/*
* Handle AEAD Encryption operation
*
* The setup is similiar to sftk_CryptInit except we set the aeadUpdate
* function instead of the normal update function. This function handles
* both the Encrypt case and the Decrypt case.
*/
static CK_RV
sftk_MessageCryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
CK_OBJECT_HANDLE hKey, SFTKContextType contextType,
CK_ATTRIBUTE_TYPE operation, PRBool encrypt)
{
SFTKSession *session;
SFTKObject *key;
SFTKSessionContext *context;
SFTKAttribute *att;
CK_KEY_TYPE key_type;
CK_RV crv = CKR_OK;
if (!pMechanism) {
return CKR_MECHANISM_PARAM_INVALID;
}
crv = sftk_MechAllowsOperation(pMechanism->mechanism,
CKA_NSS_MESSAGE | operation);
if (crv != CKR_OK)
return crv;
session = sftk_SessionFromHandle(hSession);
if (session == NULL)
return CKR_SESSION_HANDLE_INVALID;
crv = sftk_InitGeneric(session, pMechanism, &context, contextType, &key,
hKey, &key_type, CKO_SECRET_KEY, operation);
if (crv != CKR_OK) {
sftk_FreeSession(session);
return crv;
}
att = sftk_FindAttribute(key, CKA_VALUE);
if (att == NULL) {
sftk_FreeSession(session);
sftk_FreeContext(context);
return CKR_KEY_HANDLE_INVALID;
}
context->doPad = PR_FALSE;
context->multi = PR_TRUE; /* All message are 'multi' operations */
switch (pMechanism->mechanism) {
case CKM_AES_GCM:
context->cipherInfo = AES_CreateContext(
(unsigned char *)att->attrib.pValue,
NULL, NSS_AES_GCM, encrypt, att->attrib.ulValueLen,
AES_BLOCK_SIZE);
context->aeadUpdate = (SFTKAEADCipher)AES_AEAD;
context->destroy = (SFTKDestroy)AES_DestroyContext;
break;
case CKM_CHACHA20_POLY1305:
context->cipherInfo = ChaCha20Poly1305_CreateContext(
(unsigned char *)att->attrib.pValue, att->attrib.ulValueLen,
16);
context->aeadUpdate = (SFTKAEADCipher)(encrypt ? sftk_ChaCha20_Poly1305_Message_Encrypt : sftk_ChaCha20_Poly1305_Message_Decrypt);
context->destroy = (SFTKDestroy)ChaCha20Poly1305_DestroyContext;
break;
default:
crv = CKR_MECHANISM_INVALID;
break;
}
if (context->cipherInfo == NULL) {
crv = sftk_MapCryptError(PORT_GetError());
if (crv == CKR_OK) {
crv = CKR_GENERAL_ERROR;
}
}
if (crv != CKR_OK) {
sftk_FreeContext(context);
sftk_FreeSession(session);
return crv;
}
sftk_SetContextByType(session, contextType, context);
sftk_FreeSession(session);
return CKR_OK;
}
/*
* Generic handler for the actual encryption/decryption. Each call handles
* The authentication data for the entire block. Multiple calls using
* BeginMessage and NextMessage are not supported and CKF_MESSSAGE_MULTI is
* not set on the supported algorithms
*/
static CK_RV
sftk_CryptMessage(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
CK_ULONG ulParameterLen, CK_BYTE_PTR pAssociatedData,
CK_ULONG ulAssociatedDataLen, CK_BYTE_PTR pIntext,
CK_ULONG ulIntextLen, CK_BYTE_PTR pOuttext,
CK_ULONG_PTR pulOuttextLen, SFTKContextType contextType)
{
SFTKSessionContext *context;
unsigned int outlen;
unsigned int maxout = *pulOuttextLen;
CK_RV crv;
SECStatus rv;
CHECK_FORK();
/* make sure we're legal */
crv = sftk_GetContext(hSession, &context, contextType, PR_TRUE, NULL);
if (crv != CKR_OK)
return crv;
if (!pOuttext) {
*pulOuttextLen = ulIntextLen;
return CKR_OK;
}
rv = (*context->aeadUpdate)(context->cipherInfo, pOuttext, &outlen,
maxout, pIntext, ulIntextLen,
pParameter, ulParameterLen,
pAssociatedData, ulAssociatedDataLen);
if (rv != SECSuccess) {
if (contextType == SFTK_MESSAGE_ENCRYPT) {
return sftk_MapCryptError(PORT_GetError());
} else {
return sftk_MapDecryptError(PORT_GetError());
}
}
*pulOuttextLen = (CK_ULONG)(outlen);
return CKR_OK;
}
/*
* Common message cleanup rountine
*/
static CK_RV
sftk_MessageCryptFinal(CK_SESSION_HANDLE hSession,
SFTKContextType contextType)
{
SFTKSession *session;
SFTKSessionContext *context;
CK_RV crv;
CHECK_FORK();
/* make sure we're legal */
crv = sftk_GetContext(hSession, &context, contextType, PR_TRUE, &session);
if (crv != CKR_OK)
return crv;
sftk_TerminateOp(session, contextType, context);
sftk_FreeSession(session);
return CKR_OK;
}
/* MessageEncrypt and EncryptMessage functions just use the helper functions
* above */
CK_RV
NSC_MessageEncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
CK_OBJECT_HANDLE hKey)
{
return sftk_MessageCryptInit(hSession, pMechanism, hKey,
SFTK_MESSAGE_ENCRYPT, CKA_ENCRYPT, PR_TRUE);
}
CK_RV
NSC_EncryptMessage(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
CK_ULONG ulParameterLen, CK_BYTE_PTR pAssociatedData,
CK_ULONG ulAssociatedDataLen, CK_BYTE_PTR pPlaintext,
CK_ULONG ulPlaintextLen, CK_BYTE_PTR pCiphertext,
CK_ULONG_PTR pulCiphertextLen)
{
return sftk_CryptMessage(hSession, pParameter, ulParameterLen,
pAssociatedData, ulAssociatedDataLen, pPlaintext,
ulPlaintextLen, pCiphertext, pulCiphertextLen,
SFTK_MESSAGE_ENCRYPT);
}
/*
* We only support the single shot function. The Begin/Next version can be
* dealt with if we need to support S/MIME or something. It would probably
* just buffer rather then returning intermediate results.
*/
CK_RV
NSC_EncryptMessageBegin(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
CK_ULONG ulParameterLen, CK_BYTE_PTR pAssociatedData,
CK_ULONG ulAssociatedDataLen)
{
return CKR_FUNCTION_NOT_SUPPORTED;
}
CK_RV
NSC_EncryptMessageNext(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
CK_ULONG ulParameterLen, CK_BYTE_PTR pPlaintextPart,
CK_ULONG ulPlaintextPartLen, CK_BYTE_PTR pCiphertextPart,
CK_ULONG_PTR pulCiphertextPartLen, CK_FLAGS flags)
{
return CKR_FUNCTION_NOT_SUPPORTED;
}
CK_RV
NSC_MessageEncryptFinal(CK_SESSION_HANDLE hSession)
{
return sftk_MessageCryptFinal(hSession, SFTK_MESSAGE_ENCRYPT);
}
/* MessageDecrypt and DecryptMessage functions just use the helper functions
* above */
CK_RV
NSC_MessageDecryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
CK_OBJECT_HANDLE hKey)
{
return sftk_MessageCryptInit(hSession, pMechanism, hKey,
SFTK_MESSAGE_DECRYPT, CKA_DECRYPT, PR_FALSE);
}
CK_RV
NSC_DecryptMessage(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
CK_ULONG ulParameterLen, CK_BYTE_PTR pAssociatedData,
CK_ULONG ulAssociatedDataLen, CK_BYTE_PTR pCiphertext,
CK_ULONG ulCiphertextLen, CK_BYTE_PTR pPlaintext,
CK_ULONG_PTR pulPlaintextLen)
{
return sftk_CryptMessage(hSession, pParameter, ulParameterLen,
pAssociatedData, ulAssociatedDataLen, pCiphertext,
ulCiphertextLen, pPlaintext, pulPlaintextLen,
SFTK_MESSAGE_DECRYPT);
}
/*
* We only support the single shot function. The Begin/Next version can be
* dealt with if we need to support S/MIME or something. It would probably
* just buffer rather then returning intermediate results. This is expecially
* true for decrypt, which isn't supposed to return any data unless it's been
* authenticated (which can't happen until the last block is processed).
*/
CK_RV
NSC_DecryptMessageBegin(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
CK_ULONG ulParameterLen, CK_BYTE_PTR pAssociatedData,
CK_ULONG ulAssociatedDataLen)
{
return CKR_FUNCTION_NOT_SUPPORTED;
}
CK_RV
NSC_DecryptMessageNext(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
CK_ULONG ulParameterLen, CK_BYTE_PTR pCiphertextPart,
CK_ULONG ulCiphertextPartLen, CK_BYTE_PTR pPlaintextPart,
CK_ULONG_PTR pulPlaintextPartLen, CK_FLAGS flags)
{
return CKR_FUNCTION_NOT_SUPPORTED;
}
CK_RV
NSC_MessageDecryptFinal(CK_SESSION_HANDLE hSession)
{
return sftk_MessageCryptFinal(hSession, SFTK_MESSAGE_DECRYPT);
}
/*
* There are no mechanisms defined to use the MessageSign and MessageVerify
* interfaces yet, so we don't need to implement anything.
*/
CK_RV
NSC_MessageSignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
CK_OBJECT_HANDLE hKey)
{
return CKR_FUNCTION_NOT_SUPPORTED;
}
CK_RV
NSC_SignMessage(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
CK_ULONG ulParameterLen, CK_BYTE_PTR pData, CK_ULONG ulDataLen,
CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
{
return CKR_FUNCTION_NOT_SUPPORTED;
}
CK_RV
NSC_SignMessageBegin(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
CK_ULONG ulParameterLen)
{
return CKR_FUNCTION_NOT_SUPPORTED;
}
CK_RV
NSC_SignMessageNext(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
CK_ULONG ulParameterLen, CK_BYTE_PTR pData,
CK_ULONG ulDataLen, CK_BYTE_PTR pSignature,
CK_ULONG_PTR pulSignatureLen)
{
return CKR_FUNCTION_NOT_SUPPORTED;
}
CK_RV
NSC_MessageSignFinal(CK_SESSION_HANDLE hSession)
{
return CKR_FUNCTION_NOT_SUPPORTED;
}
CK_RV
NSC_MessageVerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
CK_OBJECT_HANDLE hKey)
{
return CKR_FUNCTION_NOT_SUPPORTED;
}
CK_RV
NSC_VerifyMessage(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
CK_ULONG ulParameterLen, CK_BYTE_PTR pData,
CK_ULONG ulDataLen, CK_BYTE_PTR pSignature,
CK_ULONG ulSignatureLen)
{
return CKR_FUNCTION_NOT_SUPPORTED;
}
CK_RV
NSC_VerifyMessageBegin(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
CK_ULONG ulParameterLen)
{
return CKR_FUNCTION_NOT_SUPPORTED;
}
CK_RV
NSC_VerifyMessageNext(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
CK_ULONG ulParameterLen, CK_BYTE_PTR pData,
CK_ULONG ulDataLen, CK_BYTE_PTR pSignature,
CK_ULONG ulSignatureLen)
{
return CKR_FUNCTION_NOT_SUPPORTED;
}
CK_RV
NSC_MessageVerifyFinal(CK_SESSION_HANDLE hSession)
{
return CKR_FUNCTION_NOT_SUPPORTED;
}

View file

@ -62,10 +62,12 @@ sftk_parseTokenParameters(char *param, sftk_token_parameters *parsed)
NSSUTIL_HANDLE_STRING_ARG(index, parsed->tokdes, "tokenDescription=", ;)
NSSUTIL_HANDLE_STRING_ARG(index, parsed->updtokdes, "updateTokenDescription=", ;)
NSSUTIL_HANDLE_STRING_ARG(index, parsed->slotdes, "slotDescription=", ;)
NSSUTIL_HANDLE_STRING_ARG(index, tmp, "minPWLen=",
if (tmp) { parsed->minPW=atoi(tmp); PORT_Free(tmp); tmp = NULL; })
NSSUTIL_HANDLE_STRING_ARG(index, tmp, "flags=",
if (tmp) { sftk_parseTokenFlags(param,parsed); PORT_Free(tmp); tmp = NULL; })
NSSUTIL_HANDLE_STRING_ARG(
index, tmp, "minPWLen=",
if (tmp) { parsed->minPW=atoi(tmp); PORT_Free(tmp); tmp = NULL; })
NSSUTIL_HANDLE_STRING_ARG(
index, tmp, "flags=",
if (tmp) { sftk_parseTokenFlags(param,parsed); PORT_Free(tmp); tmp = NULL; })
NSSUTIL_HANDLE_FINAL_ARG(index)
}
return CKR_OK;
@ -154,10 +156,12 @@ sftk_parseParameters(char *param, sftk_parameters *parsed, PRBool isFIPS)
NSSUTIL_HANDLE_STRING_ARG(index, pupdtokdes, "updateTokenDescription=", ;)
NSSUTIL_HANDLE_STRING_ARG(index, minPW, "minPWLen=", ;)
NSSUTIL_HANDLE_STRING_ARG(index, tmp, "flags=",
if (tmp) { sftk_parseFlags(param,parsed); PORT_Free(tmp); tmp = NULL; })
NSSUTIL_HANDLE_STRING_ARG(index, tmp, "tokens=",
if (tmp) { sftk_parseTokens(tmp,parsed); PORT_Free(tmp); tmp = NULL; })
NSSUTIL_HANDLE_STRING_ARG(
index, tmp, "flags=",
if (tmp) { sftk_parseFlags(param,parsed); PORT_Free(tmp); tmp = NULL; })
NSSUTIL_HANDLE_STRING_ARG(
index, tmp, "tokens=",
if (tmp) { sftk_parseTokens(tmp,parsed); PORT_Free(tmp); tmp = NULL; })
NSSUTIL_HANDLE_FINAL_ARG(index)
}
if (parsed->tokens == NULL) {
@ -249,3 +253,16 @@ sftk_freeParams(sftk_parameters *params)
FREE_CLEAR(params->updatedir);
FREE_CLEAR(params->updateID);
}
PRBool
sftk_RawArgHasFlag(const char *entry, const char *flag, const void *pReserved)
{
CK_C_INITIALIZE_ARGS *init_args = (CK_C_INITIALIZE_ARGS *)pReserved;
/* if we don't have any params, the flag isn't set */
if ((!init_args || !init_args->LibraryParameters)) {
return PR_FALSE;
}
return NSSUTIL_ArgHasFlag(entry, flag, (const char *)init_args->LibraryParameters);
}

View file

@ -1,14 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "pkcs11i.h"
#include "sftkdbt.h"
/* parsing functions */
char *sftk_argFetchValue(char *string, int *pcount);
char *sftk_getSecmodName(char *param, SDBType *dbType, char **appName, char **filename, PRBool *rw);
char *sftk_argStrip(char *c);
CK_RV sftk_parseParameters(char *param, sftk_parameters *parsed, PRBool isFIPS);
void sftk_freeParams(sftk_parameters *params);
const char *sftk_EvaluateConfigDir(const char *configdir, SDBType *dbType, char **app);
char *sftk_argGetParamValue(char *paramName, char *parameters);

View file

@ -92,6 +92,11 @@ sftkdb_passwordToKey(SFTKDBHandle *keydb, SECItem *salt,
SHA1Context *cx = NULL;
SECStatus rv = SECFailure;
if (!pw) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
key->data = PORT_Alloc(SHA1_LENGTH);
if (key->data == NULL) {
goto loser;
@ -247,7 +252,7 @@ sftkdb_encodeCipherText(PLArenaPool *arena, sftkCipherValue *cipherValue,
loser:
if (localArena) {
PORT_FreeArena(localArena, PR_FALSE);
PORT_FreeArena(localArena, PR_TRUE);
}
return rv;
@ -260,18 +265,19 @@ loser:
* with SECITEM_FreeItem by the caller.
*/
SECStatus
sftkdb_DecryptAttribute(SECItem *passKey, SECItem *cipherText,
SECItem **plain)
sftkdb_DecryptAttribute(SFTKDBHandle *handle, SECItem *passKey,
CK_OBJECT_HANDLE id, CK_ATTRIBUTE_TYPE type,
SECItem *cipherText, SECItem **plain)
{
SECStatus rv;
sftkCipherValue cipherValue;
/* First get the cipher type */
*plain = NULL;
rv = sftkdb_decodeCipherText(cipherText, &cipherValue);
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);
@ -280,6 +286,49 @@ sftkdb_DecryptAttribute(SECItem *passKey, SECItem *cipherText,
goto loser;
}
/* If we are using aes 256, we need to check authentication as well.*/
if ((type != CKT_INVALID_TYPE) &&
(cipherValue.alg == SEC_OID_PKCS5_PBES2) &&
(cipherValue.param->encAlg == SEC_OID_AES_256_CBC)) {
SECItem signature;
unsigned char signData[SDB_MAX_META_DATA_LEN];
CK_RV crv;
/* if we get here from the old legacy db, there is clearly an
* error, don't return the plaintext */
if (handle == NULL) {
rv = SECFailure;
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
goto loser;
}
signature.data = signData;
signature.len = sizeof(signData);
rv = SECFailure;
/* sign sftkdb_GetAttriibuteSignature returns a crv, not an rv */
crv = sftkdb_GetAttributeSignature(handle, handle, id, type,
&signature);
if (crv == CKR_OK) {
rv = sftkdb_VerifyAttribute(handle, passKey, CK_INVALID_HANDLE,
type, *plain, &signature);
}
if (rv != SECSuccess) {
/* handle bug 1720226 where old versions of NSS misfiled the signature
* attribute on password update */
id |= SFTK_KEYDB_TYPE | SFTK_TOKEN_TYPE;
signature.len = sizeof(signData);
crv = sftkdb_GetAttributeSignature(handle, handle, id, type,
&signature);
if (crv != CKR_OK) {
rv = SECFailure;
PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
goto loser;
}
rv = sftkdb_VerifyAttribute(handle, passKey, CK_INVALID_HANDLE,
type, *plain, &signature);
}
}
loser:
if (cipherValue.param) {
nsspkcs5_DestroyPBEParameter(cipherValue.param);
@ -287,9 +336,36 @@ loser:
if (cipherValue.arena) {
PORT_FreeArena(cipherValue.arena, PR_FALSE);
}
/* Item decrypted, but failed integrity, clear it out */
if (*plain && rv != SECSuccess) {
SECITEM_ZfreeItem(*plain, PR_TRUE);
*plain = NULL;
}
return rv;
}
/* If the database can't store the integrity check, it's a non-FIPS database
* and we use the old encryption scheme for it */
static PRBool
sftkdb_useLegacyEncryption(SFTKDBHandle *handle, SDB *db)
{
if ((handle == NULL) || (db == NULL)) {
/* this is the case where the legacy db is calling back to us to
* encrypt or decrypt attributes inside the lower level db code.
* This is because the legacy db stored keys as pkcs #8 encrypted
* blobs rather than individual encrypted attributes */
return PR_TRUE;
}
/* currently, only the legacy db can't store meta data, but if we
* add a new db that also can't store meta data, then it to wouldn't
* be able to do the integrity checks. In both cases use the old encryption
* algorithms. */
if ((db->sdb_flags & SDB_HAS_META) == 0) {
return PR_TRUE;
}
return PR_FALSE;
}
/*
* encrypt a block. This function returned the encrypted ciphertext which
* the caller must free. If the caller provides an arena, cipherText will
@ -297,22 +373,32 @@ loser:
* salt automatically.
*/
SECStatus
sftkdb_EncryptAttribute(PLArenaPool *arena, SECItem *passKey,
int iterationCount, SECItem *plainText,
SECItem **cipherText)
sftkdb_EncryptAttribute(PLArenaPool *arena, SFTKDBHandle *handle, SDB *db,
SECItem *passKey, int iterationCount,
CK_OBJECT_HANDLE id, CK_ATTRIBUTE_TYPE type,
SECItem *plainText, SECItem **cipherText)
{
SECStatus rv;
sftkCipherValue cipherValue;
SECItem *cipher = NULL;
NSSPKCS5PBEParameter *param = NULL;
unsigned char saltData[HASH_LENGTH_MAX];
SECItem *signature = NULL;
HASH_HashType hashType = HASH_AlgNULL;
cipherValue.alg = SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC;
cipherValue.salt.len = SHA1_LENGTH;
if (sftkdb_useLegacyEncryption(handle, db)) {
cipherValue.alg = SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC;
cipherValue.salt.len = SHA1_LENGTH;
hashType = HASH_AlgSHA1;
} else {
cipherValue.alg = SEC_OID_AES_256_CBC;
cipherValue.salt.len = SHA256_LENGTH;
hashType = HASH_AlgSHA256;
}
cipherValue.salt.data = saltData;
RNG_GenerateGlobalRandomBytes(saltData, cipherValue.salt.len);
param = nsspkcs5_NewParam(cipherValue.alg, HASH_AlgSHA1, &cipherValue.salt,
param = nsspkcs5_NewParam(cipherValue.alg, hashType, &cipherValue.salt,
iterationCount);
if (param == NULL) {
rv = SECFailure;
@ -331,7 +417,26 @@ sftkdb_EncryptAttribute(PLArenaPool *arena, SECItem *passKey,
goto loser;
}
/* If we are using aes 256, we need to add authentication as well */
if ((type != CKT_INVALID_TYPE) &&
(cipherValue.param->encAlg == SEC_OID_AES_256_CBC)) {
rv = sftkdb_SignAttribute(arena, handle, db, passKey, iterationCount,
CK_INVALID_HANDLE, type, plainText,
&signature);
if (rv != SECSuccess) {
goto loser;
}
rv = sftkdb_PutAttributeSignature(handle, db, id, type,
signature);
if (rv != SECSuccess) {
goto loser;
}
}
loser:
if ((arena == NULL) && signature) {
SECITEM_ZfreeItem(signature, PR_TRUE);
}
if (cipher) {
SECITEM_FreeItem(cipher, PR_TRUE);
}
@ -397,7 +502,7 @@ loser:
HMAC_Destroy(hashCx, PR_TRUE);
}
if (key) {
SECITEM_FreeItem(key, PR_TRUE);
SECITEM_ZfreeItem(key, PR_TRUE);
}
return rv;
}
@ -408,7 +513,8 @@ loser:
* plainText is the plainText of the attribute.
*/
SECStatus
sftkdb_VerifyAttribute(SECItem *passKey, CK_OBJECT_HANDLE objectID,
sftkdb_VerifyAttribute(SFTKDBHandle *handle,
SECItem *passKey, CK_OBJECT_HANDLE objectID,
CK_ATTRIBUTE_TYPE attrType,
SECItem *plainText, SECItem *signText)
{
@ -436,11 +542,12 @@ sftkdb_VerifyAttribute(SECItem *passKey, CK_OBJECT_HANDLE objectID,
}
loser:
PORT_Memset(signData, 0, sizeof signData);
if (signValue.param) {
nsspkcs5_DestroyPBEParameter(signValue.param);
}
if (signValue.arena) {
PORT_FreeArena(signValue.arena, PR_FALSE);
PORT_FreeArena(signValue.arena, PR_TRUE);
}
return rv;
}
@ -450,8 +557,9 @@ loser:
* attribute. The signText is a PKCS 5 v2 pbe.
*/
SECStatus
sftkdb_SignAttribute(PLArenaPool *arena, SECItem *passKey,
int iterationCount, CK_OBJECT_HANDLE objectID,
sftkdb_SignAttribute(PLArenaPool *arena, SFTKDBHandle *keyDB, SDB *db,
SECItem *passKey, int iterationCount,
CK_OBJECT_HANDLE objectID,
CK_ATTRIBUTE_TYPE attrType,
SECItem *plainText, SECItem **signature)
{
@ -517,6 +625,7 @@ sftkdb_SignAttribute(PLArenaPool *arena, SECItem *passKey,
}
loser:
PORT_Memset(signData, 0, sizeof signData);
if (param) {
nsspkcs5_DestroyPBEParameter(param);
}
@ -860,7 +969,8 @@ sftkdb_finishPasswordCheck(SFTKDBHandle *keydb, SECItem *key, const char *pw,
}
/* decrypt the entry value */
rv = sftkdb_DecryptAttribute(key, value, &result);
rv = sftkdb_DecryptAttribute(keydb, key, CK_INVALID_HANDLE,
CKT_INVALID_TYPE, value, &result);
if (rv != SECSuccess) {
goto done;
}
@ -987,7 +1097,7 @@ sftkdb_finishPasswordCheck(SFTKDBHandle *keydb, SECItem *key, const char *pw,
done:
if (result) {
SECITEM_FreeItem(result, PR_TRUE);
SECITEM_ZfreeItem(result, PR_TRUE);
}
return rv;
}
@ -1074,9 +1184,9 @@ sftk_updateMacs(PLArenaPool *arena, SFTKDBHandle *handle,
SECItem plainText;
plainText.data = authAttr.pValue;
plainText.len = authAttr.ulValueLen;
if (sftkdb_SignAttribute(arena, newKey, iterationCount, id,
authAttr.type, &plainText,
&signText) != SECSuccess) {
if (sftkdb_SignAttribute(arena, handle, keyTarget, newKey,
iterationCount, id, authAttr.type,
&plainText, &signText) != SECSuccess) {
return CKR_GENERAL_ERROR;
}
if (sftkdb_PutAttributeSignature(handle, keyTarget, id, authAttr.type,
@ -1108,6 +1218,7 @@ sftk_updateEncrypted(PLArenaPool *arena, SFTKDBHandle *keydb,
unsigned int i;
for (i = 0; i < privAttrCount; i++) {
// Read the old attribute in the clear.
CK_OBJECT_HANDLE sdbId = id & SFTK_OBJ_ID_MASK;
CK_ATTRIBUTE privAttr = { privAttrTypes[i], NULL, 0 };
CK_RV crv = sftkdb_GetAttributeValue(keydb, id, &privAttr, 1);
if (crv != CKR_OK) {
@ -1131,7 +1242,8 @@ sftk_updateEncrypted(PLArenaPool *arena, SFTKDBHandle *keydb,
SECItem *result;
plainText.data = privAttr.pValue;
plainText.len = privAttr.ulValueLen;
if (sftkdb_EncryptAttribute(arena, newKey, iterationCount,
if (sftkdb_EncryptAttribute(arena, keydb, keydb->db, newKey,
iterationCount, sdbId, privAttr.type,
&plainText, &result) != SECSuccess) {
return CKR_GENERAL_ERROR;
}
@ -1141,10 +1253,9 @@ sftk_updateEncrypted(PLArenaPool *arena, SFTKDBHandle *keydb,
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;
keydb->newDefaultIterationCount = iterationCount;
crv = (*keydb->db->sdb_SetAttributeValue)(keydb->db, newId, &privAttr, 1);
crv = (*keydb->db->sdb_SetAttributeValue)(keydb->db, sdbId, &privAttr, 1);
keydb->newKey = NULL;
if (crv != CKR_OK) {
return crv;
@ -1184,8 +1295,7 @@ sftk_convertAttributes(SFTKDBHandle *handle, CK_OBJECT_HANDLE id,
}
/* free up our mess */
/* NOTE: at this point we know we've cleared out any unencrypted data */
PORT_FreeArena(arena, PR_FALSE);
PORT_FreeArena(arena, PR_TRUE);
return CKR_OK;
loser:
@ -1300,7 +1410,7 @@ sftkdb_ChangePassword(SFTKDBHandle *keydb,
certdb = keydb->peerDB;
if (certdb) {
CK_ATTRIBUTE objectType = { CKA_CLASS, 0, sizeof(CK_OBJECT_CLASS) };
CK_OBJECT_CLASS myClass = CKO_NETSCAPE_TRUST;
CK_OBJECT_CLASS myClass = CKO_NSS_TRUST;
objectType.pValue = &myClass;
crv = sftkdb_convertObjects(certdb, &objectType, 1, &newKey,
@ -1321,8 +1431,9 @@ sftkdb_ChangePassword(SFTKDBHandle *keydb,
plainText.data = (unsigned char *)SFTK_PW_CHECK_STRING;
plainText.len = SFTK_PW_CHECK_LEN;
rv = sftkdb_EncryptAttribute(NULL, &newKey, iterationCount,
&plainText, &result);
rv = sftkdb_EncryptAttribute(NULL, keydb, keydb->db, &newKey,
iterationCount, CK_INVALID_HANDLE,
CKT_INVALID_TYPE, &plainText, &result);
if (rv != SECSuccess) {
goto loser;
}

View file

@ -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.48.6" SOFTOKEN_ECC_STRING
#define SOFTOKEN_VERSION "3.90.12.0 (UXP)" SOFTOKEN_ECC_STRING
#define SOFTOKEN_VMAJOR 3
#define SOFTOKEN_VMINOR 48
#define SOFTOKEN_VPATCH 6
#define SOFTOKEN_VMINOR 90
#define SOFTOKEN_VPATCH 12
#define SOFTOKEN_VBUILD 0
#define SOFTOKEN_BETA PR_FALSE

View file

@ -48,7 +48,7 @@
'fipstest.c',
'fipstokn.c',
'jpakesftk.c',
'lgglue.c',
'kbkdf.c',
'lowkey.c',
'lowpbe.c',
'padbuf.c',
@ -56,14 +56,23 @@
'pkcs11c.c',
'pkcs11u.c',
'sdb.c',
'sftkdhverify.c',
'sftkdb.c',
'sftkhmac.c',
'sftkike.c',
'sftkmessage.c',
'sftkpars.c',
'sftkpwd.c',
'softkver.c',
'tlsprf.c'
],
'conditions': [
[ 'disable_dbm==0', {
'sources': [
'lgglue.c',
]
}]
]
},
},
{

View file

@ -57,7 +57,7 @@ extern unsigned char *CBC_PadBuffer(PLArenaPool *arena, unsigned char *inbuf,
** Power-Up selftests are required for FIPS.
*/
/* make sure Power-up selftests have been run. */
extern CK_RV sftk_FIPSEntryOK(void);
extern CK_RV sftk_FIPSEntryOK(PRBool rerun);
/*
** make known fixed PKCS #11 key types to their sizes in bytes
@ -145,7 +145,9 @@ extern PRBool sftk_fatalError;
/*
** macros to check for forked child process after C_Initialize
*/
#if defined(XP_UNIX) && !defined(NO_FORK_CHECK)
/* for PKCS #11 3.0, default is NO_FORK_CHECK, if you want it, now you
* need to define DO_FORK_CHECK */
#if defined(XP_UNIX) && defined(DO_FORK_CHECK)
#ifdef DEBUG
@ -260,6 +262,19 @@ extern PRBool sftkForkCheckDisabled;
#endif
/*
* If we were trying to be complete, we would have both FORK_SAFE
* and non-Fork safe interfaces here. That would require doubling
* the functions in our function list for both this and the FIPS
* interface. Since NSS now always asks for a FORK_SAFE interface,
* and can fall back to a non-FORK_SAFE interface, we set only
* export one set of interfaces here */
#ifdef NO_FORK_CHECK
#define NSS_INTERFACE_FLAGS CKF_INTERFACE_FORK_SAFE
#else
#define NSS_INTERFACE_FLAGS 0
#endif
SEC_END_PROTOS
#endif /* _SOFTOKEN_H_ */

View file

@ -26,3 +26,14 @@ NSC_ModuleDBFunc;
;+ local:
;+ *;
;+};
;+NSS_3.52 { # NSS 3.52 release adds pkcs #11 v3.0
;+ global:
C_GetInterfaceList;
FC_GetInterfaceList;
NSC_GetInterfaceList;
C_GetInterface;
FC_GetInterface;
NSC_GetInterface;
;+ local:
;+ *;
;+};

View file

@ -174,7 +174,7 @@ sftk_TLSPRFInit(SFTKSessionContext *context,
prf_cx->cxDataLen = 0;
prf_cx->cxBufSize = blockSize - offsetof(TLSPRFContext, cxBuf);
prf_cx->cxRv = SECSuccess;
prf_cx->cxIsFIPS = (key->slot->slotID == FIPS_SLOT_ID);
prf_cx->cxIsFIPS = sftk_isFIPS(key->slot->slotID);
prf_cx->cxBufPtr = prf_cx->cxBuf;
prf_cx->cxHashAlg = hash_alg;
prf_cx->cxOutLen = out_len;