mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-21 15:57:31 +09:00
Replace NSS with Pale Moon's
This commit is contained in:
parent
ff1e5e48bf
commit
8c2e376f94
2870 changed files with 1762232 additions and 1374220 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
]
|
||||
}]
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
182
security/nss/lib/softoken/fips_algorithms.h
Normal file
182
security/nss/lib/softoken/fips_algorithms.h
Normal 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);
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
1520
security/nss/lib/softoken/kbkdf.c
Normal file
1520
security/nss/lib/softoken/kbkdf.c
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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))\"
|
||||
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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_ */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
6845
security/nss/lib/softoken/sftkdhverify.c
Normal file
6845
security/nss/lib/softoken/sftkdhverify.c
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
377
security/nss/lib/softoken/sftkmessage.c
Normal file
377
security/nss/lib/softoken/sftkmessage.c
Normal 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;
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
]
|
||||
}]
|
||||
]
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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_ */
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
;+ *;
|
||||
;+};
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue