File nss-fips-constructor-self-tests.patch of Package mozilla-nss.6304
commit 4da64c30d3c93472b86d3479563ac8d6cb14225e
Author: Hans Petter Jansson <hpj@cl.no>
Date: Mon Oct 16 00:36:18 2017 +0200
Add constructor self-tests and FIPS mode discovery support.
diff --git a/nss/cmd/chktest/chktest.c b/nss/cmd/chktest/chktest.c
index a33d184..f09283a 100644
--- a/nss/cmd/chktest/chktest.c
+++ b/nss/cmd/chktest/chktest.c
@@ -38,7 +38,7 @@ main(int argc, char **argv)
}
RNG_SystemInfoForRNG();
- good_result = BLAPI_SHVerifyFile(argv[1]);
+ good_result = BLAPI_SHVerifyFile(argv[1], NULL);
printf("%s\n",
(good_result ? "SUCCESS" : "FAILURE"));
return (good_result) ? SECSuccess : SECFailure;
diff --git a/nss/lib/freebl/blapi.h b/nss/lib/freebl/blapi.h
index e5a6cf3..4d1cf57 100644
--- a/nss/lib/freebl/blapi.h
+++ b/nss/lib/freebl/blapi.h
@@ -1588,17 +1588,17 @@ extern void BL_Unload(void);
/**************************************************************************
* Verify a given Shared library signature *
**************************************************************************/
-PRBool BLAPI_SHVerify(const char *name, PRFuncPtr addr);
+PRBool BLAPI_SHVerify(const char *name, PRFuncPtr addr, int *err);
/**************************************************************************
* Verify a given filename's signature *
**************************************************************************/
-PRBool BLAPI_SHVerifyFile(const char *shName);
+PRBool BLAPI_SHVerifyFile(const char *shName, int *err);
/**************************************************************************
* Verify Are Own Shared library signature *
**************************************************************************/
-PRBool BLAPI_VerifySelf(const char *name);
+PRBool BLAPI_VerifySelf(const char *name, int *err);
/*********************************************************************/
extern const SECHashObject *HASH_GetRawHashObject(HASH_HashType hashType);
diff --git a/nss/lib/freebl/fips-selftest.inc b/nss/lib/freebl/fips-selftest.inc
new file mode 100644
index 0000000..6c67945
--- /dev/null
+++ b/nss/lib/freebl/fips-selftest.inc
@@ -0,0 +1,285 @@
+/*
+ * PKCS #11 FIPS Power-Up Self Test - common stuff.
+ *
+ * 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/. */
+
+#ifndef FIPS_INC
+#define FIPS_INC
+
+/* common functions used for FIPS selftests. Due to the modular design of NSS
+ * putting these into libfreebl would mean either amending the API represented
+ * by FREEBLVectorStr - which might cause problems with newer applications, or
+ * extending the API with another similar function set. Thus, to make things
+ * less complicated in the binaries, we mess up the source a bit. */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <limits.h>
+
+#include <prtypes.h>
+#include <prerror.h>
+
+#include <prlink.h>
+
+#include "blapi.h"
+
+#define NSS_FORCE_FIPS_ENV "NSS_FIPS"
+#define FIPS_PROC_PATH "/proc/sys/crypto/fips_enabled"
+
+#define CHECKSUM_SUFFIX ".chk"
+
+typedef enum fips_check_status {
+ CHECK_UNCHECKED = -1,
+ CHECK_OK = 0,
+ CHECK_FAIL,
+ CHECK_FAIL_CRYPTO,
+ CHECK_MISSING
+} fips_check_status;
+
+/* initial value of FIPS state is -1 */
+static int fips_state = -1;
+
+static int fips_wanted = -1;
+
+/* debug messages are sent to stderr */
+static void
+debug(const char *fmt,...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ vfprintf(stderr, fmt, args);
+ va_end(args);
+ fputc('\n', stderr);
+ return;
+}
+
+/* Fatal messages ending with abort(); this function never returns */
+static void __attribute__ ((__noreturn__))
+fatal(const char *fmt,...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ vfprintf(stderr, fmt, args);
+ va_end(args);
+ fputc('\n', stderr);
+ abort();
+}
+
+/* check whether FIPS moode is mandated by the kernel */
+static int
+fips_isWantedProc(void)
+{
+ int fips_wanted = 0;
+ int fips_fd;
+ char fips_sys = 0;
+
+ struct stat dummy;
+ if (-1 == stat(FIPS_PROC_PATH, &dummy)) {
+ switch (errno) {
+ case ENOENT:
+ case ENOTDIR:
+ break;
+ default:
+ fatal("Check for system-wide FIPS mode is required and %s cannot"
+ " be accessed for reason other than non-existence - aborting"
+ , FIPS_PROC_PATH);
+ break;
+ }
+ } else {
+ if (-1 == (fips_fd = open(FIPS_PROC_PATH, O_RDONLY))) {
+ fatal("Check for system-wide FIPS mode is required and %s cannot"
+ " be opened for reading - aborting"
+ , FIPS_PROC_PATH);
+ }
+ if (1 > read(fips_fd, &fips_sys, 1)) {
+ fatal("Check for system-wide FIPS mode is required and %s doesn't"
+ " return at least one character - aborting"
+ , FIPS_PROC_PATH);
+ }
+ close(fips_fd);
+ switch (fips_sys) {
+ case '0':
+ case '1':
+ fips_wanted = fips_sys - '0';
+ break;
+ default:
+ fatal("Bogus character %c found in %s - aborting"
+ , fips_sys, FIPS_PROC_PATH);
+ }
+ }
+ return fips_wanted;
+}
+
+/* "legacy" from lib/sysinit/nsssysinit.c */
+static PRBool
+getFIPSEnv(void)
+{
+ char *fipsEnv = getenv("NSS_FIPS");
+ if (!fipsEnv) {
+ return PR_FALSE;
+ }
+ if ((strcasecmp(fipsEnv,"fips") == 0) ||
+ (strcasecmp(fipsEnv,"true") == 0) ||
+ (strcasecmp(fipsEnv,"on") == 0) ||
+ (strcasecmp(fipsEnv,"1") == 0)) {
+ return PR_TRUE;
+ }
+ return PR_FALSE;
+}
+
+static int
+fips_isWantedEnv(void)
+{
+ return getFIPSEnv() ? 1 : 0;
+}
+
+static int
+fips_isWanted(void)
+{
+ int fips_requests = 0;
+#ifdef LINUX
+ fips_requests += fips_isWantedProc();
+#endif
+ fips_requests += fips_isWantedEnv();
+ return fips_requests;
+}
+
+/* check integrity signatures (if present) */
+static fips_check_status
+fips_checkSignature(char *libName, PRFuncPtr addr)
+{
+ PRBool rv;
+ fips_check_status rv_check = CHECK_UNCHECKED;
+ int l = PATH_MAX;
+ int err = 0;
+ int err_NOENT = 0;
+ char full_lib_name[PATH_MAX+1];
+ full_lib_name[0] = '\0';
+
+ if (NULL == libName) {
+ err_NOENT = PR_FILE_NOT_FOUND_ERROR;
+ rv = BLAPI_VerifySelf(SHLIB_PREFIX"freebl"SHLIB_VERSION"."SHLIB_SUFFIX, &err);
+ } else {
+ err_NOENT = PR_FILE_NOT_FOUND_ERROR;
+ strncat(full_lib_name, SHLIB_PREFIX, l);
+ l -= strlen(SHLIB_PREFIX);
+ strncat(full_lib_name, libName, l);
+ l -= strlen(libName);
+ strncat(full_lib_name, SHLIB_VERSION"."SHLIB_SUFFIX, l);
+ l -= strlen(SHLIB_VERSION"."SHLIB_SUFFIX);
+#if 1
+ rv = BLAPI_SHVerify(full_lib_name, addr, &err);
+#else
+ rv = 1;
+#endif
+ }
+
+ if (rv) {
+ rv_check = CHECK_OK;
+ } else {
+ if (err_NOENT == err) {
+ rv_check = CHECK_MISSING;
+ } else {
+ rv_check = CHECK_FAIL;
+ }
+ }
+
+ return rv_check;
+}
+
+/* decide what to do depending on the results of tests and system/required FIPS
+ * mode */
+static int
+fips_resolve(fips_check_status check, char *libName)
+{
+ int state;
+
+ if (fips_wanted) {
+ switch (check) {
+ case CHECK_OK:
+ debug("fips - %s: mandatory checksum ok"
+ , (libName) ? libName : "freebl");
+ break;
+ case CHECK_FAIL:
+ fatal("fips - %s: mandatory checksum failed - aborting"
+ , (libName) ? libName : "freebl");
+ break;
+ case CHECK_FAIL_CRYPTO:
+ fatal("fips - %s: mandatory crypto test failed - aborting"
+ , (libName) ? libName : "freebl");
+ break;
+ case CHECK_MISSING:
+ fatal("fips - %s: mandatory checksum data missing - aborting"
+ , (libName) ? libName : "freebl");
+ break;
+ default:
+ fatal("Fatal error: internal error at %s:%u"
+ , __FILE__, __LINE__);
+ break;
+ }
+ state = 1;
+ } else {
+ switch (check) {
+ case CHECK_OK:
+ debug("fips - %s: checksum ok"
+ , (libName) ? libName : "freebl");
+ break;
+ case CHECK_FAIL:
+ fatal("fips - %s: checksum failed - aborting"
+ , (libName) ? libName : "freebl");
+ break;
+ case CHECK_FAIL_CRYPTO:
+ fatal("fips - %s: crypto test failed - aborting"
+ , (libName) ? libName : "freebl");
+ break;
+ case CHECK_MISSING:
+ debug("fips - %s: mandatory checksum data missing, but not required in non FIPS mode; continuing non-FIPS"
+ , (libName) ? libName : "freebl");
+ break;
+ default:
+ fatal("Fatal error: internal error at %s:%u"
+ , __FILE__, __LINE__);
+ break;
+ }
+ state = 0;
+ }
+ return state;
+}
+
+/* generic selftest
+ * libName and addr are the name of shared object to check and a function
+ * contained therein; (NULL, NULL) performs selfcheck of freebl.
+ * crypto_check is callback that performs cryptographic algorithms checks; NULL
+ * for libraries that do not implement any cryptographic algorithms per se
+ */
+static int
+fips_initTest(char *libName, PRFuncPtr addr, fips_check_status cryptoCheck(void))
+{
+ fips_check_status check = CHECK_OK;
+
+ fips_wanted = fips_isWanted();
+
+ if (cryptoCheck) {
+ check = cryptoCheck();
+ debug("fips - %s: crypto check %s"
+ , (libName) ? libName : "freebl"
+ , (CHECK_OK == check) ? "ok" : "failed");
+ }
+
+ if (CHECK_OK == check) {
+ check = fips_checkSignature(libName, addr);
+ }
+
+ return fips_resolve(check, libName);
+}
+
+#endif
diff --git a/nss/lib/freebl/fips.c b/nss/lib/freebl/fips.c
new file mode 100644
index 0000000..9065b93
--- /dev/null
+++ b/nss/lib/freebl/fips.c
@@ -0,0 +1,7 @@
+/*
+ * PKCS #11 FIPS Power-Up Self Test.
+ *
+ * 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/. */
+
diff --git a/nss/lib/freebl/fips.h b/nss/lib/freebl/fips.h
new file mode 100644
index 0000000..a4ac7a9
--- /dev/null
+++ b/nss/lib/freebl/fips.h
@@ -0,0 +1,15 @@
+/*
+ * PKCS #11 FIPS Power-Up Self Test.
+ *
+ * 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/. */
+
+#ifndef FIPS_H
+#define FIPS_H
+
+int FIPS_mode(void);
+char* FIPS_rngDev(void);
+
+#endif
+
diff --git a/nss/lib/freebl/fipsfreebl.c b/nss/lib/freebl/fipsfreebl.c
index c7c279f..8a078ea 100644
--- a/nss/lib/freebl/fipsfreebl.c
+++ b/nss/lib/freebl/fipsfreebl.c
@@ -19,6 +19,13 @@
#include "ec.h" /* Required for ECDSA */
#endif
+#include "fips-selftest.inc"
+
+#include "fips.h"
+
+#define RNG_DEV_FIPS0 "/dev/urandom"
+#define RNG_DEV_FIPS1 "/dev/random"
+
/*
* different platforms have different ways of calling and initial entry point
* when the dll/.so is loaded. Most platforms support either a posix pragma
@@ -1778,9 +1785,8 @@ freebl_fips_RNG_PowerUpSelfTest(void)
0x0a, 0x26, 0x21, 0xd0, 0x19, 0xcb, 0x86, 0x73,
0x10, 0x1f, 0x60, 0xd7
};
-
SECStatus rng_status = SECSuccess;
- PRUint8 DSAX[FIPS_DSA_SUBPRIME_LENGTH];
+ PRUint8 DSAX[DSA1_SUBPRIME_LEN];
/*******************************************/
/* Run the SP 800-90 Health tests */
@@ -1794,13 +1800,12 @@ freebl_fips_RNG_PowerUpSelfTest(void)
/*******************************************/
/* Generate DSAX fow given Q. */
/*******************************************/
-
rng_status = FIPS186Change_ReduceModQForDSA(GENX, Q, DSAX);
/* Verify DSAX to perform the RNG integrity check */
if ((rng_status != SECSuccess) ||
(PORT_Memcmp(DSAX, rng_known_DSAX,
- (FIPS_DSA_SUBPRIME_LENGTH)) != 0)) {
+ (DSA1_SUBPRIME_LEN)) != 0)) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
@@ -1814,7 +1819,7 @@ freebl_fipsSoftwareIntegrityTest(const char *libname)
SECStatus rv = SECSuccess;
/* make sure that our check file signatures are OK */
- if (!BLAPI_VerifySelf(libname)) {
+ if (!BLAPI_VerifySelf(libname, NULL)) {
rv = SECFailure;
}
return rv;
@@ -1979,6 +1984,15 @@ BL_POSTRan(PRBool freebl_only)
#include "blname.c"
+/* crypto algorithms selftest wrapper */
+static fips_check_status
+fips_checkCryptoFreebl(void)
+{
+ /* currently there are no crypto selftets in FreeBL, since it is not
+ * considered to be a stand-alone FIPS crypto module */
+ return CHECK_OK;
+}
+
/*
* This function is called at dll load time, the code tha makes this
* happen is platform specific on defined above.
@@ -2004,6 +2018,10 @@ bl_startup_tests(void)
}
#endif
+ /* Detect FIPS mode and verify checksums */
+ fips_state = fips_initTest(NULL, NULL, fips_checkCryptoFreebl);
+ debug("FIPS mode: %i\n", FIPS_mode());
+
self_tests_freebl_ran = PR_TRUE; /* we are running the tests */
if (!freebl_only) {
@@ -2039,17 +2057,11 @@ bl_startup_tests(void)
SECStatus
BL_FIPSEntryOK(PRBool freebl_only)
{
-#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
- */
+ /* For platforms that don't support on-load constructors */
if (!self_tests_freebl_ran) {
bl_startup_tests();
}
-#endif
+
/* if the general self tests succeeded, we're done */
if (self_tests_success) {
return SECSuccess;
@@ -2061,3 +2073,71 @@ BL_FIPSEntryOK(PRBool freebl_only)
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
+
+/* returns the FIPS mode we are running in or the one that we aspire to if the
+ * tests have not completed yet - which might happen during the crypto selftest
+ */
+int
+FIPS_mode(void)
+{
+ int fips;
+
+ if (fips_wanted < 0)
+ fips_wanted = fips_isWanted ();
+
+ /* until FIPS mode is cleared up, assume we are running in whatever is
+ * wanted by the environment */
+ fips = (-1 != fips_state) ? fips_state : fips_wanted;
+ switch (fips) {
+ case 0:
+ case 1:
+ return fips;
+ default:
+ fatal("Fatal error: internal error at %s:%u"
+ , __FILE__, __LINE__);
+ }
+}
+
+/* returns string specifying what system RNG file to use for seeding */
+char *
+FIPS_rngDev(void)
+{
+ switch (FIPS_mode()) {
+ case 0:
+ return RNG_DEV_FIPS0;
+ case 1:
+ return RNG_DEV_FIPS1;
+ default:
+ fatal("Fatal error: internal error at %s:%u"
+ , __FILE__, __LINE__);
+ }
+}
+
+/* either returns the input or aborts if in FIPS and the algorithm is not
+ * approved */
+PRBool
+FIPS_hashAlgApproved(HASH_HashType hashAlg)
+{
+ PRBool rv = PR_FALSE;
+
+ switch (hashAlg) {
+ case HASH_AlgNULL:
+ case HASH_AlgSHA1:
+ case HASH_AlgSHA256:
+ case HASH_AlgSHA384:
+ case HASH_AlgSHA512:
+ case HASH_AlgSHA224:
+ rv = PR_TRUE;
+ break;
+ default:
+ /*
+ fatal("Fatal error: non-approved hash algorithm (id %i)"
+ "requested while running in FIPS mode"
+ , hashAlg);
+ */
+ if (!FIPS_mode())
+ rv = PR_TRUE;
+ break;
+ }
+ return rv;
+}
diff --git a/nss/lib/freebl/loader.c b/nss/lib/freebl/loader.c
index 792171b..910f68e 100644
--- a/nss/lib/freebl/loader.c
+++ b/nss/lib/freebl/loader.c
@@ -1137,11 +1137,11 @@ AESKeyWrap_Decrypt(AESKeyWrapContext *cx, unsigned char *output,
}
PRBool
-BLAPI_SHVerify(const char *name, PRFuncPtr addr)
+BLAPI_SHVerify(const char *name, PRFuncPtr addr, int *err)
{
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
return PR_FALSE;
- return vector->p_BLAPI_SHVerify(name, addr);
+ return vector->p_BLAPI_SHVerify(name, addr, err);
}
/*
@@ -1151,12 +1151,12 @@ BLAPI_SHVerify(const char *name, PRFuncPtr addr)
* in freebl_LoadDSO) to p_BLAPI_VerifySelf.
*/
PRBool
-BLAPI_VerifySelf(const char *name)
+BLAPI_VerifySelf(const char *name, int *err)
{
PORT_Assert(!name);
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
return PR_FALSE;
- return vector->p_BLAPI_VerifySelf(libraryName);
+ return vector->p_BLAPI_VerifySelf(libraryName, err);
}
/* ============== New for 3.006 =============================== */
@@ -1748,11 +1748,11 @@ SHA224_Clone(SHA224Context *dest, SHA224Context *src)
}
PRBool
-BLAPI_SHVerifyFile(const char *name)
+BLAPI_SHVerifyFile(const char *name, int *err)
{
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
return PR_FALSE;
- return vector->p_BLAPI_SHVerifyFile(name);
+ return vector->p_BLAPI_SHVerifyFile(name, err);
}
/* === new for DSA-2 === */
diff --git a/nss/lib/freebl/loader.h b/nss/lib/freebl/loader.h
index ed392cc..2757418 100644
--- a/nss/lib/freebl/loader.h
+++ b/nss/lib/freebl/loader.h
@@ -299,8 +299,8 @@ struct FREEBLVectorStr {
/* Version 3.004 came to here */
- PRBool (*p_BLAPI_SHVerify)(const char *name, PRFuncPtr addr);
- PRBool (*p_BLAPI_VerifySelf)(const char *name);
+ PRBool (*p_BLAPI_SHVerify)(const char *name, PRFuncPtr addr, int *err);
+ PRBool (*p_BLAPI_VerifySelf)(const char *name, int *err);
/* Version 3.005 came to here */
@@ -556,7 +556,7 @@ struct FREEBLVectorStr {
SECStatus (*p_SHA224_Flatten)(SHA224Context *cx, unsigned char *space);
SHA224Context *(*p_SHA224_Resurrect)(unsigned char *space, void *arg);
void (*p_SHA224_Clone)(SHA224Context *dest, SHA224Context *src);
- PRBool (*p_BLAPI_SHVerifyFile)(const char *name);
+ PRBool (*p_BLAPI_SHVerifyFile)(const char *name, int *err);
/* Version 3.013 came to here */
diff --git a/nss/lib/freebl/manifest.mn b/nss/lib/freebl/manifest.mn
index 1ef9839..cbe30de 100644
--- a/nss/lib/freebl/manifest.mn
+++ b/nss/lib/freebl/manifest.mn
@@ -94,6 +94,7 @@ PRIVATE_EXPORTS = \
ec.h \
ecl.h \
ecl-curve.h \
+ fips.h \
$(NULL)
MPI_HDRS = mpi-config.h mpi.h mpi-priv.h mplogic.h mpprime.h logtab.h mp_gf2m.h
@@ -173,6 +174,7 @@ ALL_HDRS = \
shsign.h \
vis_proto.h \
seed.h \
+ fips.h \
$(NULL)
diff --git a/nss/lib/freebl/shvfy.c b/nss/lib/freebl/shvfy.c
index af4a34f..b8dd358 100644
--- a/nss/lib/freebl/shvfy.c
+++ b/nss/lib/freebl/shvfy.c
@@ -18,6 +18,8 @@
#include "pqg.h"
#include "blapii.h"
+#define DEBUG_SHVERIFY 1
+
/*
* Most modern version of Linux support a speed optimization scheme where an
* application called prelink modifies programs and shared libraries to quickly
@@ -279,10 +281,10 @@ readItem(PRFileDesc *fd, SECItem *item)
return SECSuccess;
}
-static PRBool blapi_SHVerifyFile(const char *shName, PRBool self);
+static PRBool blapi_SHVerifyFile(const char *shName, PRBool self, int *err);
static PRBool
-blapi_SHVerify(const char *name, PRFuncPtr addr, PRBool self)
+blapi_SHVerify(const char *name, PRFuncPtr addr, PRBool self, int *err)
{
PRBool result = PR_FALSE; /* if anything goes wrong,
* the signature does not verify */
@@ -291,7 +293,7 @@ blapi_SHVerify(const char *name, PRFuncPtr addr, PRBool self)
if (!shName) {
goto loser;
}
- result = blapi_SHVerifyFile(shName, self);
+ result = blapi_SHVerifyFile(shName, self, err);
loser:
if (shName != NULL) {
@@ -302,19 +304,19 @@ loser:
}
PRBool
-BLAPI_SHVerify(const char *name, PRFuncPtr addr)
+BLAPI_SHVerify(const char *name, PRFuncPtr addr, int *err)
{
- return blapi_SHVerify(name, addr, PR_FALSE);
+ return blapi_SHVerify(name, addr, PR_FALSE, err);
}
PRBool
-BLAPI_SHVerifyFile(const char *shName)
+BLAPI_SHVerifyFile(const char *shName, int *err)
{
- return blapi_SHVerifyFile(shName, PR_FALSE);
+ return blapi_SHVerifyFile(shName, PR_FALSE, err);
}
static PRBool
-blapi_SHVerifyFile(const char *shName, PRBool self)
+blapi_SHVerifyFile(const char *shName, PRBool self, int *err)
{
char *checkName = NULL;
PRFileDesc *checkFD = NULL;
@@ -340,11 +342,13 @@ blapi_SHVerifyFile(const char *shName, PRBool self)
hash.data = hashBuf;
hash.len = sizeof(hashBuf);
+#if 0
/* 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)) {
return PR_FALSE;
}
+#endif
if (!shName) {
goto loser;
@@ -359,9 +363,12 @@ blapi_SHVerifyFile(const char *shName, PRBool self)
/* open the check File */
checkFD = PR_Open(checkName, PR_RDONLY, 0);
if (checkFD == NULL) {
+ if (err) {
+ *err = PORT_GetError();
+ }
#ifdef DEBUG_SHVERIFY
- fprintf(stderr, "Failed to open the check file %s: (%d, %d)\n",
- checkName, (int)PR_GetError(), (int)PR_GetOSError());
+ fprintf(stderr, "Failed to open the check file %s: (%d)\n",
+ checkName, (int)PORT_GetError());
#endif /* DEBUG_SHVERIFY */
goto loser;
}
@@ -430,8 +437,8 @@ blapi_SHVerifyFile(const char *shName, PRBool self)
#endif
if (shFD == NULL) {
#ifdef DEBUG_SHVERIFY
- fprintf(stderr, "Failed to open the library file %s: (%d, %d)\n",
- shName, (int)PR_GetError(), (int)PR_GetOSError());
+ fprintf(stderr, "Failed to open the library file %s: (%d)\n",
+ shName, (int)PORT_GetError());
#endif /* DEBUG_SHVERIFY */
goto loser;
}
@@ -521,7 +528,7 @@ loser:
}
PRBool
-BLAPI_VerifySelf(const char *name)
+BLAPI_VerifySelf(const char *name, int *err)
{
if (name == NULL) {
/*
@@ -530,5 +537,5 @@ BLAPI_VerifySelf(const char *name)
*/
return PR_TRUE;
}
- return blapi_SHVerify(name, (PRFuncPtr)decodeInt, PR_TRUE);
+ return blapi_SHVerify(name, (PRFuncPtr)decodeInt, PR_TRUE, err);
}
diff --git a/nss/lib/softoken/fips.c b/nss/lib/softoken/fips.c
new file mode 100644
index 0000000..63e36d5
--- /dev/null
+++ b/nss/lib/softoken/fips.c
@@ -0,0 +1,29 @@
+#include "../freebl/fips-selftest.inc"
+
+#include "fips.h"
+
+#include "softoken.h"
+
+/* crypto algorithms selftest wrapper */
+static fips_check_status
+fips_checkCryptoSoftoken(void)
+{
+ if (CKR_OK == sftk_FIPSEntryOK()) {
+ return CHECK_OK;
+ } else {
+ return CHECK_FAIL_CRYPTO;
+ }
+
+ return CHECK_OK;
+}
+
+/* constructor - load-time selfchecks */
+static void __attribute__ ((constructor))
+fips_initTestSoftoken(void)
+{
+ fprintf (stderr, "\nsoftokn constructor begin\n");
+ fips_state = fips_initTest("softokn", (PRFuncPtr)fips_initTestSoftoken, fips_checkCryptoSoftoken);
+ fprintf (stderr, "\nsoftokn constructor end\n");
+
+ return;
+}
diff --git a/nss/lib/softoken/fips.h b/nss/lib/softoken/fips.h
new file mode 100644
index 0000000..c3b7fcf
--- /dev/null
+++ b/nss/lib/softoken/fips.h
@@ -0,0 +1,10 @@
+#ifndef FIPS_H
+#define FIPS_H
+
+#include "softoken.h"
+
+CK_RV FIPS_cryptoSelftestSoftoken(void);
+CK_RV sftk_fipsPowerUpSelfTest(void);
+
+#endif
+
diff --git a/nss/lib/softoken/fipstest.c b/nss/lib/softoken/fipstest.c
index 3563bd2..283d6c8 100644
--- a/nss/lib/softoken/fipstest.c
+++ b/nss/lib/softoken/fipstest.c
@@ -590,7 +590,6 @@ static void
sftk_startup_tests(void)
{
SECStatus rv;
- const char *libraryName = SOFTOKEN_LIB_NAME;
PORT_Assert(!sftk_self_tests_ran);
PORT_Assert(!sftk_self_tests_success);
@@ -602,6 +601,7 @@ sftk_startup_tests(void)
if (rv != SECSuccess) {
return;
}
+
/* make sure freebl is initialized, or our RSA check
* may fail. This is normally done at freebl load time, but it's
* possible we may have shut freebl down without unloading it. */
@@ -614,17 +614,15 @@ sftk_startup_tests(void)
if (rv != SECSuccess) {
return;
}
+
/* check the RSA combined functions in softoken */
rv = sftk_fips_RSA_PowerUpSelfTest();
if (rv != SECSuccess) {
return;
}
- if (!BLAPI_SHVerify(libraryName,
- (PRFuncPtr)&sftk_fips_RSA_PowerUpSelfTest)) {
- /* something is wrong with the library, fail without enabling
- * the token */
- return;
- }
+
+ /* Checksum is done by fips_initTestSoftoken() in fips.c */
+
sftk_self_tests_success = PR_TRUE;
}
@@ -636,17 +634,11 @@ sftk_startup_tests(void)
CK_RV
sftk_FIPSEntryOK()
{
-#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
- */
+ /* For platforms that don't support on-load constructors */
if (!sftk_self_tests_ran) {
sftk_startup_tests();
}
-#endif
+
if (!sftk_self_tests_success) {
return CKR_DEVICE_ERROR;
}
diff --git a/nss/lib/softoken/legacydb/fips.c b/nss/lib/softoken/legacydb/fips.c
new file mode 100644
index 0000000..41eac65
--- /dev/null
+++ b/nss/lib/softoken/legacydb/fips.c
@@ -0,0 +1,25 @@
+#include "../../freebl/fips-selftest.inc"
+
+#include "fips.h"
+
+/*** private per-module symbols ***/
+
+/* crypto algorithms selftest wrapper */
+static fips_check_status
+fips_checkCryptoDbm(void)
+{
+ /* no checks in dbm */
+ return CHECK_OK;
+}
+
+/* constructor - load-time selfchecks */
+static void __attribute__ ((constructor))
+fips_initTestDbm(void)
+{
+ fips_state = fips_initTest("nssdbm", (PRFuncPtr)fips_checkCryptoDbm, NULL);
+
+ return;
+}
+
+/*** public per-module symbols ***/
+
diff --git a/nss/lib/softoken/legacydb/fips.h b/nss/lib/softoken/legacydb/fips.h
new file mode 100644
index 0000000..a203e66
--- /dev/null
+++ b/nss/lib/softoken/legacydb/fips.h
@@ -0,0 +1,5 @@
+#ifndef FIPS_H
+#define FIPS_H
+
+#endif
+
diff --git a/nss/lib/softoken/legacydb/lgfips.c b/nss/lib/softoken/legacydb/lgfips.c
index b017424..6de84d1 100644
--- a/nss/lib/softoken/legacydb/lgfips.c
+++ b/nss/lib/softoken/legacydb/lgfips.c
@@ -88,7 +88,7 @@ lg_startup_tests(void)
/* no self tests required for the legacy db, only the integrity check */
/* check the integrity of our shared library */
- if (!BLAPI_SHVerify(libraryName, (PRFuncPtr)&lg_local_function)) {
+ if (!BLAPI_SHVerify(libraryName, (PRFuncPtr)&lg_local_function, NULL)) {
/* something is wrong with the library, fail without enabling
* the fips token */
return;
diff --git a/nss/lib/softoken/legacydb/manifest.mn b/nss/lib/softoken/legacydb/manifest.mn
index 9cce849..e734651 100644
--- a/nss/lib/softoken/legacydb/manifest.mn
+++ b/nss/lib/softoken/legacydb/manifest.mn
@@ -12,7 +12,7 @@ LIBRARY_NAME = nssdbm
LIBRARY_VERSION = 3
MAPFILE = $(OBJDIR)/nssdbm.def
-DEFINES += -DSHLIB_SUFFIX=\"$(DLL_SUFFIX)\" -DSHLIB_PREFIX=\"$(DLL_PREFIX)\" -DLG_LIB_NAME=\"$(notdir $(SHARED_LIBRARY))\"
+DEFINES += -DSHLIB_SUFFIX=\"$(DLL_SUFFIX)\" -DSHLIB_PREFIX=\"$(DLL_PREFIX)\" -DLG_LIB_NAME=\"$(notdir $(SHARED_LIBRARY))\" -DSHLIB_VERSION=\"$(LIBRARY_VERSION)\"
CSRCS = \
dbmshim.c \
@@ -28,5 +28,6 @@ CSRCS = \
lowkey.c \
pcertdb.c \
pk11db.c \
+ fips.c \
$(NULL)
diff --git a/nss/lib/softoken/manifest.mn b/nss/lib/softoken/manifest.mn
index 256d443..d7b61e7 100644
--- a/nss/lib/softoken/manifest.mn
+++ b/nss/lib/softoken/manifest.mn
@@ -30,6 +30,7 @@ PRIVATE_EXPORTS = \
softkver.h \
sdb.h \
sftkdbt.h \
+ fips.h \
$(NULL)
CSRCS = \
@@ -51,6 +52,7 @@ CSRCS = \
softkver.c \
tlsprf.c \
jpakesftk.c \
+ fips.c \
$(NULL)
ifdef SQLITE_UNSAFE_THREADS