You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
522 lines
17 KiB
522 lines
17 KiB
diff --git a/cmd/bltest/blapitest.c b/cmd/bltest/blapitest.c |
|
--- a/cmd/bltest/blapitest.c |
|
+++ b/cmd/bltest/blapitest.c |
|
@@ -3870,17 +3870,17 @@ main(int argc, char **argv) |
|
rv = blapi_selftest(modesToTest, numModesToTest, inoff, outoff, |
|
encrypt, decrypt); |
|
PORT_Free(cipherInfo); |
|
return rv == SECSuccess ? 0 : 1; |
|
} |
|
|
|
/* Do FIPS self-test */ |
|
if (bltest.commands[cmd_FIPS].activated) { |
|
- CK_RV ckrv = sftk_FIPSEntryOK(); |
|
+ CK_RV ckrv = sftk_FIPSEntryOK(PR_FALSE); |
|
fprintf(stdout, "CK_RV: %ld.\n", ckrv); |
|
PORT_Free(cipherInfo); |
|
if (ckrv == CKR_OK) |
|
return SECSuccess; |
|
return SECFailure; |
|
} |
|
|
|
/* |
|
diff --git a/cmd/pk11mode/pk11mode.c b/cmd/pk11mode/pk11mode.c |
|
--- a/cmd/pk11mode/pk11mode.c |
|
+++ b/cmd/pk11mode/pk11mode.c |
|
@@ -318,23 +318,25 @@ static PRBool verbose = PR_FALSE; |
|
|
|
int |
|
main(int argc, char **argv) |
|
{ |
|
CK_C_GetFunctionList pC_GetFunctionList; |
|
CK_FUNCTION_LIST_PTR pFunctionList; |
|
CK_RV crv = CKR_OK; |
|
CK_C_INITIALIZE_ARGS_NSS initArgs; |
|
+ CK_C_INITIALIZE_ARGS_NSS initArgsRerun; /* rerun selftests */ |
|
CK_SLOT_ID *pSlotList = NULL; |
|
CK_TOKEN_INFO tokenInfo; |
|
CK_ULONG slotID = 0; /* slotID == 0 for FIPSMODE */ |
|
|
|
CK_UTF8CHAR *pwd = NULL; |
|
CK_ULONG pwdLen = 0; |
|
char *moduleSpec = NULL; |
|
+ char *moduleSpecRerun = NULL; |
|
char *configDir = NULL; |
|
char *dbPrefix = NULL; |
|
char *disableUnload = NULL; |
|
PRBool doForkTests = PR_TRUE; |
|
|
|
PLOptStatus os; |
|
PLOptState *opt = PL_CreateOptState(argc, argv, "nvhf:Fd:p:"); |
|
while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { |
|
@@ -458,18 +460,23 @@ main(int argc, char **argv) |
|
initArgs.CreateMutex = NULL; |
|
initArgs.DestroyMutex = NULL; |
|
initArgs.LockMutex = NULL; |
|
initArgs.UnlockMutex = NULL; |
|
initArgs.flags = CKF_OS_LOCKING_OK; |
|
moduleSpec = PR_smprintf("configdir='%s' certPrefix='%s' " |
|
"keyPrefix='%s' secmod='secmod.db' flags= ", |
|
configDir, dbPrefix, dbPrefix); |
|
+ moduleSpecRerun = PR_smprintf("configdir='%s' certPrefix='%s' " |
|
+ "keyPrefix='%s' secmod='secmod.db' flags=forcePOST ", |
|
+ configDir, dbPrefix, dbPrefix); |
|
initArgs.LibraryParameters = (CK_CHAR_PTR *)moduleSpec; |
|
initArgs.pReserved = NULL; |
|
+ initArgsRerun = initArgs; |
|
+ initArgsRerun.LibraryParameters = (CK_CHAR_PTR *)moduleSpecRerun; |
|
|
|
/*DebugBreak();*/ |
|
/* FIPSMODE invokes FC_Initialize as pFunctionList->C_Initialize */ |
|
/* NSS cryptographic module library initialization for the FIPS */ |
|
/* Approved mode when FC_Initialize is envoked will perfom */ |
|
/* software integrity test, and power-up self-tests before */ |
|
/* FC_Initialize returns */ |
|
crv = pFunctionList->C_Initialize(&initArgs); |
|
@@ -705,17 +712,17 @@ main(int argc, char **argv) |
|
PKM_Error("PKM_HybridMode failed with 0x%08X, %-26s\n", crv, |
|
PKM_CK_RVtoStr(crv)); |
|
goto cleanup; |
|
} |
|
|
|
if (doForkTests) { |
|
/* testing one more C_Initialize / C_Finalize to exercise getpid() |
|
* fork check code */ |
|
- crv = pFunctionList->C_Initialize(&initArgs); |
|
+ crv = pFunctionList->C_Initialize(&initArgsRerun); |
|
if (crv == CKR_OK) { |
|
PKM_LogIt("C_Initialize succeeded\n"); |
|
} else { |
|
PKM_Error("C_Initialize failed with 0x%08X, %-26s\n", crv, |
|
PKM_CK_RVtoStr(crv)); |
|
goto cleanup; |
|
} |
|
crv = pFunctionList->C_Finalize(NULL); |
|
@@ -741,16 +748,19 @@ cleanup: |
|
free(configDir); |
|
} |
|
if (dbPrefix) { |
|
free(dbPrefix); |
|
} |
|
if (moduleSpec) { |
|
PR_smprintf_free(moduleSpec); |
|
} |
|
+ if (moduleSpecRerun) { |
|
+ PR_smprintf_free(moduleSpecRerun); |
|
+ } |
|
|
|
#ifdef _WIN32 |
|
FreeLibrary(hModule); |
|
#else |
|
disableUnload = PR_GetEnvSecure("NSS_DISABLE_UNLOAD"); |
|
if (!disableUnload) { |
|
PR_UnloadLibrary(lib); |
|
} |
|
diff --git a/lib/freebl/blapii.h b/lib/freebl/blapii.h |
|
--- a/lib/freebl/blapii.h |
|
+++ b/lib/freebl/blapii.h |
|
@@ -24,17 +24,17 @@ typedef SECStatus (*freeblAeadFunc)(void |
|
void *params, unsigned int paramsLen, |
|
const unsigned char *aad, unsigned int aadLen, |
|
unsigned int blocksize); |
|
typedef void (*freeblDestroyFunc)(void *cx, PRBool freeit); |
|
|
|
SEC_BEGIN_PROTOS |
|
|
|
#ifndef NSS_FIPS_DISABLED |
|
-SECStatus BL_FIPSEntryOK(PRBool freeblOnly); |
|
+SECStatus BL_FIPSEntryOK(PRBool freeblOnly, PRBool rerun); |
|
PRBool BL_POSTRan(PRBool freeblOnly); |
|
#endif |
|
|
|
#if defined(XP_UNIX) && !defined(NO_FORK_CHECK) |
|
|
|
extern PRBool bl_parentForkedAfterC_Initialize; |
|
|
|
#define SKIP_AFTER_FORK(x) \ |
|
diff --git a/lib/freebl/blapit.h b/lib/freebl/blapit.h |
|
--- a/lib/freebl/blapit.h |
|
+++ b/lib/freebl/blapit.h |
|
@@ -223,16 +223,21 @@ typedef int __BLAPI_DEPRECATED __attribu |
|
* |
|
* If we arbitrarily set p = 10^-18 (1 chance in trillion trillion operation) |
|
* we get GCMIV_RANDOM_BIRTHDAY_BITS = -(-18)/.301 -1 = 59 (.301 = log10 2) |
|
* GCMIV_RANDOM_BIRTHDAY_BITS should be at least 59, call it a round 64. NOTE: |
|
* the variable IV size for TLS is 64 bits, which explains why it's not safe |
|
* to use a random value for the nonce in TLS. */ |
|
#define GCMIV_RANDOM_BIRTHDAY_BITS 64 |
|
|
|
+/* flag to tell BLAPI_Verify* to rerun the post and integrity tests */ |
|
+#define BLAPI_FIPS_RERUN_FLAG '\377' /* 0xff, 255 invalide code for UFT8/ASCII */ |
|
+#define BLAPI_FIPS_RERUN_FLAG_STRING "\377" /* The above as a C string */ |
|
+ |
|
+ |
|
/*************************************************************************** |
|
** Opaque objects |
|
*/ |
|
|
|
struct DESContextStr; |
|
struct RC2ContextStr; |
|
struct RC4ContextStr; |
|
struct RC5ContextStr; |
|
diff --git a/lib/freebl/fipsfreebl.c b/lib/freebl/fipsfreebl.c |
|
--- a/lib/freebl/fipsfreebl.c |
|
+++ b/lib/freebl/fipsfreebl.c |
|
@@ -2211,29 +2211,37 @@ bl_startup_tests(void) |
|
} |
|
|
|
/* |
|
* this is called from the freebl init entry points that controll access to |
|
* all other freebl functions. This prevents freebl from operating if our |
|
* power on selftest failed. |
|
*/ |
|
SECStatus |
|
-BL_FIPSEntryOK(PRBool freebl_only) |
|
+BL_FIPSEntryOK(PRBool freebl_only, PRBool rerun) |
|
{ |
|
#ifdef NSS_NO_INIT_SUPPORT |
|
/* this should only be set on platforms that can't handle one of the INIT |
|
* schemes. This code allows those platforms to continue to function, |
|
* though they don't meet the strict NIST requirements. If NSS_NO_INIT_SUPPORT |
|
* is not set, and init support has not been properly enabled, freebl |
|
* will always fail because of the test below |
|
*/ |
|
if (!self_tests_freebl_ran) { |
|
bl_startup_tests(); |
|
} |
|
#endif |
|
+ if (rerun) { |
|
+ /* reset the flags */ |
|
+ self_tests_freebl_ran = PR_FALSE; |
|
+ self_tests_success = PR_FALSE; |
|
+ self_tests_success = PR_FALSE; |
|
+ self_tests_freebl_success = PR_FALSE; |
|
+ bl_startup_tests(); |
|
+ } |
|
/* if the general self tests succeeded, we're done */ |
|
if (self_tests_success) { |
|
return SECSuccess; |
|
} |
|
/* standalone freebl can initialize */ |
|
if (freebl_only && self_tests_freebl_success) { |
|
return SECSuccess; |
|
} |
|
diff --git a/lib/freebl/nsslowhash.c b/lib/freebl/nsslowhash.c |
|
--- a/lib/freebl/nsslowhash.c |
|
+++ b/lib/freebl/nsslowhash.c |
|
@@ -55,17 +55,17 @@ NSSLOW_Init(void) |
|
#ifdef FREEBL_NO_DEPEND |
|
(void)FREEBL_InitStubs(); |
|
#endif |
|
|
|
#ifndef NSS_FIPS_DISABLED |
|
/* make sure the FIPS product is installed if we are trying to |
|
* go into FIPS mode */ |
|
if (nsslow_GetFIPSEnabled()) { |
|
- if (BL_FIPSEntryOK(PR_TRUE) != SECSuccess) { |
|
+ if (BL_FIPSEntryOK(PR_TRUE, PR_FALSE) != SECSuccess) { |
|
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
|
post_failed = PR_TRUE; |
|
return NULL; |
|
} |
|
} |
|
#endif |
|
post_failed = PR_FALSE; |
|
|
|
diff --git a/lib/freebl/shvfy.c b/lib/freebl/shvfy.c |
|
--- a/lib/freebl/shvfy.c |
|
+++ b/lib/freebl/shvfy.c |
|
@@ -282,52 +282,62 @@ readItem(PRFileDesc *fd, SECItem *item) |
|
PORT_Free(item->data); |
|
item->data = NULL; |
|
item->len = 0; |
|
return SECFailure; |
|
} |
|
return SECSuccess; |
|
} |
|
|
|
-static PRBool blapi_SHVerifyFile(const char *shName, PRBool self); |
|
+static PRBool blapi_SHVerifyFile(const char *shName, PRBool self, PRBool rerun); |
|
|
|
static PRBool |
|
-blapi_SHVerify(const char *name, PRFuncPtr addr, PRBool self) |
|
+blapi_SHVerify(const char *name, PRFuncPtr addr, PRBool self, PRBool rerun) |
|
{ |
|
PRBool result = PR_FALSE; /* if anything goes wrong, |
|
* the signature does not verify */ |
|
/* find our shared library name */ |
|
char *shName = PR_GetLibraryFilePathname(name, addr); |
|
if (!shName) { |
|
goto loser; |
|
} |
|
- result = blapi_SHVerifyFile(shName, self); |
|
+ result = blapi_SHVerifyFile(shName, self, rerun); |
|
|
|
loser: |
|
if (shName != NULL) { |
|
PR_Free(shName); |
|
} |
|
|
|
return result; |
|
} |
|
|
|
PRBool |
|
BLAPI_SHVerify(const char *name, PRFuncPtr addr) |
|
{ |
|
- return blapi_SHVerify(name, addr, PR_FALSE); |
|
+ PRBool rerun = PR_FALSE; |
|
+ if (name && *name == BLAPI_FIPS_RERUN_FLAG) { |
|
+ name++; |
|
+ rerun = PR_TRUE; |
|
+ } |
|
+ return blapi_SHVerify(name, addr, PR_FALSE, rerun); |
|
} |
|
|
|
PRBool |
|
BLAPI_SHVerifyFile(const char *shName) |
|
{ |
|
- return blapi_SHVerifyFile(shName, PR_FALSE); |
|
+ PRBool rerun = PR_FALSE; |
|
+ if (shName && *shName == BLAPI_FIPS_RERUN_FLAG) { |
|
+ shName++; |
|
+ rerun = PR_TRUE; |
|
+ } |
|
+ return blapi_SHVerifyFile(shName, PR_FALSE, rerun); |
|
} |
|
|
|
static PRBool |
|
-blapi_SHVerifyFile(const char *shName, PRBool self) |
|
+blapi_SHVerifyFile(const char *shName, PRBool self, PRBool rerun) |
|
{ |
|
char *checkName = NULL; |
|
PRFileDesc *checkFD = NULL; |
|
PRFileDesc *shFD = NULL; |
|
void *hashcx = NULL; |
|
const SECHashObject *hashObj = NULL; |
|
SECItem signature = { 0, NULL, 0 }; |
|
SECItem hash; |
|
@@ -346,17 +356,17 @@ blapi_SHVerifyFile(const char *shName, P |
|
unsigned char hashBuf[HASH_LENGTH_MAX]; |
|
|
|
PORT_Memset(&key, 0, sizeof(key)); |
|
hash.data = hashBuf; |
|
hash.len = sizeof(hashBuf); |
|
|
|
/* If our integrity check was never ran or failed, fail any other |
|
* integrity checks to prevent any token going into FIPS mode. */ |
|
- if (!self && (BL_FIPSEntryOK(PR_FALSE) != SECSuccess)) { |
|
+ if (!self && (BL_FIPSEntryOK(PR_FALSE, rerun) != SECSuccess)) { |
|
return PR_FALSE; |
|
} |
|
|
|
if (!shName) { |
|
goto loser; |
|
} |
|
|
|
/* figure out the name of our check file */ |
|
@@ -536,17 +546,17 @@ BLAPI_VerifySelf(const char *name) |
|
{ |
|
if (name == NULL) { |
|
/* |
|
* If name is NULL, freebl is statically linked into softoken. |
|
* softoken will call BLAPI_SHVerify next to verify itself. |
|
*/ |
|
return PR_TRUE; |
|
} |
|
- return blapi_SHVerify(name, (PRFuncPtr)decodeInt, PR_TRUE); |
|
+ return blapi_SHVerify(name, (PRFuncPtr)decodeInt, PR_TRUE, PR_FALSE); |
|
} |
|
|
|
#else /* NSS_FIPS_DISABLED */ |
|
|
|
PRBool |
|
BLAPI_SHVerifyFile(const char *shName) |
|
{ |
|
return PR_FALSE; |
|
diff --git a/lib/softoken/fipstest.c b/lib/softoken/fipstest.c |
|
--- a/lib/softoken/fipstest.c |
|
+++ b/lib/softoken/fipstest.c |
|
@@ -684,22 +684,25 @@ sftk_fips_HKDF_PowerUpSelfTest(void) |
|
|
|
static PRBool sftk_self_tests_ran = PR_FALSE; |
|
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 *nlibraryName = SOFTOKEN_LIB_NAME; |
|
+ const char *rlibraryName = BLAPI_FIPS_RERUN_FLAG_STRING 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); |
|
sftk_self_tests_ran = PR_TRUE; |
|
sftk_self_tests_success = PR_FALSE; /* just in case */ |
|
|
|
/* need to initiallize the oid library before the RSA tests */ |
|
rv = SECOID_Init(); |
|
if (rv != SECSuccess) { |
|
@@ -746,35 +749,46 @@ sftk_startup_tests(void) |
|
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 |
|
* schemes. This code allows those platforms to continue to function, |
|
* though they don't meet the strict NIST requirements. If NSS_NO_INIT_SUPPORT |
|
* is not set, and init support has not been properly enabled, softken |
|
* will always fail because of the test below |
|
*/ |
|
if (!sftk_self_tests_ran) { |
|
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; |
|
} |
|
return CKR_OK; |
|
} |
|
#else |
|
#include "pkcs11t.h" |
|
CK_RV |
|
diff --git a/lib/softoken/fipstokn.c b/lib/softoken/fipstokn.c |
|
--- a/lib/softoken/fipstokn.c |
|
+++ b/lib/softoken/fipstokn.c |
|
@@ -524,25 +524,32 @@ fc_log_init_error(CK_RV crv) |
|
} |
|
|
|
/* FC_Initialize initializes the PKCS #11 library. */ |
|
CK_RV |
|
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); |
|
return crv; |
|
} |
|
|
|
sftk_ForkReset(pReserved, &crv); |
|
|
|
diff --git a/lib/softoken/pkcs11i.h b/lib/softoken/pkcs11i.h |
|
--- a/lib/softoken/pkcs11i.h |
|
+++ b/lib/softoken/pkcs11i.h |
|
@@ -869,16 +869,17 @@ extern CK_RV sftk_MechAllowsOperation(CK |
|
* acquiring a reference to the keydb from the slot */ |
|
NSSLOWKEYPrivateKey *sftk_FindKeyByPublicKey(SFTKSlot *slot, SECItem *dbKey); |
|
|
|
/* |
|
* parameter parsing functions |
|
*/ |
|
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 |
|
*/ |
|
SFTKSessionObject *sftk_narrowToSessionObject(SFTKObject *); |
|
SFTKTokenObject *sftk_narrowToTokenObject(SFTKObject *); |
|
|
|
/* |
|
diff --git a/lib/softoken/sftkpars.c b/lib/softoken/sftkpars.c |
|
--- a/lib/softoken/sftkpars.c |
|
+++ b/lib/softoken/sftkpars.c |
|
@@ -244,8 +244,21 @@ sftk_freeParams(sftk_parameters *params) |
|
FREE_CLEAR(params->configdir); |
|
FREE_CLEAR(params->secmodName); |
|
FREE_CLEAR(params->man); |
|
FREE_CLEAR(params->libdes); |
|
FREE_CLEAR(params->tokens); |
|
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); |
|
+} |
|
diff --git a/lib/softoken/softoken.h b/lib/softoken/softoken.h |
|
--- a/lib/softoken/softoken.h |
|
+++ b/lib/softoken/softoken.h |
|
@@ -52,17 +52,17 @@ extern unsigned char *CBC_PadBuffer(PLAr |
|
unsigned int inlen, unsigned int *outlen, |
|
int blockSize); |
|
|
|
/****************************************/ |
|
/* |
|
** 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 |
|
*/ |
|
unsigned long sftk_MapKeySize(CK_KEY_TYPE keyType); |
|
|
|
/* |
|
** FIPS 140-2 auditing
|
|
|