Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-12-SP1:GA
mozilla-nss.2166
nss-CC-constructor_selftests.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File nss-CC-constructor_selftests.patch of Package mozilla-nss.2166
# HG changeset patch # Parent a4116725d048eff8480c58c19ba4abe30351b906 # Parent 2bf609fcef400204ec013dbfbb60dfe0e3668712 Perform necessary selftests in the libraaary constructors so that they get called at library load time. Do not test non-FIPS-approved tests by default. diff --git a/cmd/chktest/chktest.c b/cmd/chktest/chktest.c --- a/cmd/chktest/chktest.c +++ b/cmd/chktest/chktest.c @@ -31,13 +31,13 @@ int main(int argc, char **argv) } rv = BL_Init(); if (rv != SECSuccess) { SECU_PrintPRandOSError(""); return -1; } 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/lib/freebl/blapi.h b/lib/freebl/blapi.h --- a/lib/freebl/blapi.h +++ b/lib/freebl/blapi.h @@ -1554,27 +1554,27 @@ extern void PQG_DestroyVerify(PQGVerify extern void BL_Cleanup(void); /* unload freebl shared library from memory */ 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); extern void BL_SetForkState(PRBool forked); #ifndef NSS_DISABLE_ECC /* diff --git a/lib/freebl/fips-selftest.inc b/lib/freebl/fips-selftest.inc new file mode 100644 --- /dev/null +++ b/lib/freebl/fips-selftest.inc @@ -0,0 +1,280 @@ +/* + * 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,...) +{ +#ifdef DEBUG_FIPS + va_list args; + + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); + fputc('\n', stderr); +#endif + 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)) { + close(fips_fd); + 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 = ENOENT; + 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); + rv = BLAPI_SHVerify(full_lib_name, addr, &err); + } + + 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 = fips_checkSignature(libName, addr); + + fips_wanted = fips_isWanted(); + + if ((cryptoCheck) && (CHECK_OK == check)) { + check = cryptoCheck(); + debug("fips - %s: crypto check %s" + , (libName) ? libName : "freebl" + , (CHECK_OK == check) ? "ok" : "failed"); + } + + return fips_resolve(check, libName); +} + +#endif diff --git a/lib/freebl/fips.c b/lib/freebl/fips.c new file mode 100644 --- /dev/null +++ b/lib/freebl/fips.c @@ -0,0 +1,69 @@ +/* + * 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/. */ + +#include "fips-selftest.inc" + +#include "fips.h" + +#define RNG_DEV_FIPS0 "/dev/urandom" +#define RNG_DEV_FIPS1 "/dev/random" + +/* 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; +} + +/* constructor - load-time selfchecks */ +static void __attribute__ ((constructor)) +fips_initTestFreebl(void) +{ + fips_state = fips_initTest(NULL, NULL, fips_checkCryptoFreebl); + + debug("FIPS mode: %i\n", FIPS_mode()); + return; +} + +/* 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; + + /* 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__); + } +} + diff --git a/lib/freebl/fips.h b/lib/freebl/fips.h new file mode 100644 --- /dev/null +++ b/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/lib/freebl/loader.c b/lib/freebl/loader.c --- a/lib/freebl/loader.c +++ b/lib/freebl/loader.c @@ -1217,36 +1217,36 @@ AESKeyWrap_Decrypt(AESKeyWrapContext *cx { if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) return SECFailure; return vector->p_AESKeyWrap_Decrypt(cx, output, outputLen, maxOutputLen, input, inputLen); } 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); } /* * The Caller is expected to pass NULL as the name, which will * trigger the p_BLAPI_VerifySelf() to return 'TRUE'. Pass the real * name of the shared library we loaded (the static libraryName set * 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 =============================== */ SECStatus EC_NewKey(ECParams * params, ECPrivateKey ** privKey) { if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) @@ -1831,21 +1831,21 @@ void SHA224_Clone(SHA224Context *dest, SHA224Context *src) { if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) return; (vector->p_SHA224_Clone)(dest, 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 === */ SECStatus PQG_ParamGenV2( unsigned int L, unsigned int N, unsigned int seedBytes, PQGParams **pParams, PQGVerify **pVfy) { if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) diff --git a/lib/freebl/loader.h b/lib/freebl/loader.h --- a/lib/freebl/loader.h +++ b/lib/freebl/loader.h @@ -294,18 +294,18 @@ struct FREEBLVectorStr { SECStatus (* p_AESKeyWrap_Decrypt)(AESKeyWrapContext *cx, unsigned char *output, unsigned int *outputLen, unsigned int maxOutputLen, const unsigned char *input, unsigned int inputLen); /* 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 */ SECStatus (* p_EC_NewKey)(ECParams * params, ECPrivateKey ** privKey); SECStatus (* p_EC_NewKeyFromSeed)(ECParams * params, ECPrivateKey ** privKey, @@ -553,17 +553,17 @@ struct FREEBLVectorStr { SECStatus (*p_SHA224_HashBuf)(unsigned char *dest, const unsigned char *src, PRUint32 src_length); SECStatus (*p_SHA224_Hash)(unsigned char *dest, const char *src); void (*p_SHA224_TraceState)(SHA224Context *cx); unsigned int (* p_SHA224_FlattenSize)(SHA224Context *cx); 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 */ SECStatus (* p_PQG_ParamGenV2)( unsigned int L, unsigned int N, unsigned int seedBytes, PQGParams **pParams, PQGVerify **pVfy); SECStatus (*p_PRNGTEST_RunHealthTests)(void); diff --git a/lib/freebl/manifest.mn b/lib/freebl/manifest.mn --- a/lib/freebl/manifest.mn +++ b/lib/freebl/manifest.mn @@ -57,16 +57,17 @@ PRIVATE_EXPORTS = \ alghmac.h \ blapi.h \ hmacct.h \ secmpi.h \ secrng.h \ 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 MPI_SRCS = mpprime.c mpmontg.c mplogic.c mpi.c mp_gf2m.c ECL_HDRS = ecl-exp.h ecl.h ec2.h ecp.h ecl-priv.h ifndef NSS_DISABLE_ECC @@ -120,16 +121,17 @@ CSRCS = \ seed.c \ jpake.c \ $(MPI_SRCS) \ $(MPCPU_SRCS) \ $(ECL_SRCS) \ $(STUBS_SRCS) \ $(LOWHASH_SRCS) \ $(EXTRA_SRCS) \ + fips.c \ $(NULL) ALL_CSRCS := $(CSRCS) ALL_HDRS = \ alghmac.h \ blapi.h \ blapit.h \ @@ -139,16 +141,17 @@ ALL_HDRS = \ rijndael.h \ camellia.h \ secmpi.h \ sha_fast.h \ sha256.h \ shsign.h \ vis_proto.h \ seed.h \ + fips.h \ $(NULL) ifdef AES_GEN_TBL DEFINES += -DRIJNDAEL_GENERATE_TABLES else ifdef AES_GEN_TBL_M DEFINES += -DRIJNDAEL_GENERATE_TABLES_MACRO diff --git a/lib/freebl/nsslowhash.c b/lib/freebl/nsslowhash.c --- a/lib/freebl/nsslowhash.c +++ b/lib/freebl/nsslowhash.c @@ -8,343 +8,75 @@ #include "prtypes.h" #include "secerr.h" #include "pkcs11t.h" #include "blapi.h" #include "hasht.h" #include "plhash.h" #include "nsslowhash.h" -/* FIPS preprocessor directives for message digests */ -#define FIPS_KNOWN_HASH_MESSAGE_LENGTH 64 /* 512-bits */ - -/* Known Hash Message (512-bits). Used for all hashes (incl. SHA-N [N>1]). */ -static const PRUint8 known_hash_message[] = { - "The test message for the MD2, MD5, and SHA-1 hashing algorithms." }; - -static CK_RV -freebl_fips_MD2_PowerUpSelfTest( void ) -{ - /* MD2 Known Digest Message (128-bits). */ - static const PRUint8 md2_known_digest[] = { - 0x41,0x5a,0x12,0xb2,0x3f,0x28,0x97,0x17, - 0x0c,0x71,0x4e,0xcc,0x40,0xc8,0x1d,0x1b}; - - /* MD2 variables. */ - MD2Context * md2_context; - unsigned int md2_bytes_hashed; - PRUint8 md2_computed_digest[MD2_LENGTH]; - - - /***********************************************/ - /* MD2 Single-Round Known Answer Hashing Test. */ - /***********************************************/ - - md2_context = MD2_NewContext(); - - if( md2_context == NULL ) - return( CKR_HOST_MEMORY ); - - MD2_Begin( md2_context ); - - MD2_Update( md2_context, known_hash_message, - FIPS_KNOWN_HASH_MESSAGE_LENGTH ); - - MD2_End( md2_context, md2_computed_digest, &md2_bytes_hashed, MD2_LENGTH ); - - MD2_DestroyContext( md2_context , PR_TRUE ); - - if( ( md2_bytes_hashed != MD2_LENGTH ) || - ( PORT_Memcmp( md2_computed_digest, md2_known_digest, - MD2_LENGTH ) != 0 ) ) - return( CKR_DEVICE_ERROR ); - - return( CKR_OK ); -} - - - -static CK_RV -freebl_fips_MD5_PowerUpSelfTest( void ) -{ - /* MD5 Known Digest Message (128-bits). */ - static const PRUint8 md5_known_digest[] = { - 0x25,0xc8,0xc0,0x10,0xc5,0x6e,0x68,0x28, - 0x28,0xa4,0xa5,0xd2,0x98,0x9a,0xea,0x2d}; - - /* MD5 variables. */ - PRUint8 md5_computed_digest[MD5_LENGTH]; - SECStatus md5_status; - - - /***********************************************/ - /* MD5 Single-Round Known Answer Hashing Test. */ - /***********************************************/ - - md5_status = MD5_HashBuf( md5_computed_digest, known_hash_message, - FIPS_KNOWN_HASH_MESSAGE_LENGTH ); - - if( ( md5_status != SECSuccess ) || - ( PORT_Memcmp( md5_computed_digest, md5_known_digest, - MD5_LENGTH ) != 0 ) ) - return( CKR_DEVICE_ERROR ); - - return( CKR_OK ); -} - -static CK_RV -freebl_fips_SHA_PowerUpSelfTest( void ) -{ - /* SHA-1 Known Digest Message (160-bits). */ - static const PRUint8 sha1_known_digest[] = { - 0x0a,0x6d,0x07,0xba,0x1e,0xbd,0x8a,0x1b, - 0x72,0xf6,0xc7,0x22,0xf1,0x27,0x9f,0xf0, - 0xe0,0x68,0x47,0x7a}; - - /* SHA-224 Known Digest Message (224-bits). */ - static const PRUint8 sha224_known_digest[] = { - 0x89,0x5e,0x7f,0xfd,0x0e,0xd8,0x35,0x6f, - 0x64,0x6d,0xf2,0xde,0x5e,0xed,0xa6,0x7f, - 0x29,0xd1,0x12,0x73,0x42,0x84,0x95,0x4f, - 0x8e,0x08,0xe5,0xcb}; - - /* SHA-256 Known Digest Message (256-bits). */ - static const PRUint8 sha256_known_digest[] = { - 0x38,0xa9,0xc1,0xf0,0x35,0xf6,0x5d,0x61, - 0x11,0xd4,0x0b,0xdc,0xce,0x35,0x14,0x8d, - 0xf2,0xdd,0xaf,0xaf,0xcf,0xb7,0x87,0xe9, - 0x96,0xa5,0xd2,0x83,0x62,0x46,0x56,0x79}; - - /* SHA-384 Known Digest Message (384-bits). */ - static const PRUint8 sha384_known_digest[] = { - 0x11,0xfe,0x1c,0x00,0x89,0x48,0xde,0xb3, - 0x99,0xee,0x1c,0x18,0xb4,0x10,0xfb,0xfe, - 0xe3,0xa8,0x2c,0xf3,0x04,0xb0,0x2f,0xc8, - 0xa3,0xc4,0x5e,0xea,0x7e,0x60,0x48,0x7b, - 0xce,0x2c,0x62,0xf7,0xbc,0xa7,0xe8,0xa3, - 0xcf,0x24,0xce,0x9c,0xe2,0x8b,0x09,0x72}; - - /* SHA-512 Known Digest Message (512-bits). */ - static const PRUint8 sha512_known_digest[] = { - 0xc8,0xb3,0x27,0xf9,0x0b,0x24,0xc8,0xbf, - 0x4c,0xba,0x33,0x54,0xf2,0x31,0xbf,0xdb, - 0xab,0xfd,0xb3,0x15,0xd7,0xfa,0x48,0x99, - 0x07,0x60,0x0f,0x57,0x41,0x1a,0xdd,0x28, - 0x12,0x55,0x25,0xac,0xba,0x3a,0x99,0x12, - 0x2c,0x7a,0x8f,0x75,0x3a,0xe1,0x06,0x6f, - 0x30,0x31,0xc9,0x33,0xc6,0x1b,0x90,0x1a, - 0x6c,0x98,0x9a,0x87,0xd0,0xb2,0xf8,0x07}; - - /* SHA-X variables. */ - PRUint8 sha_computed_digest[HASH_LENGTH_MAX]; - SECStatus sha_status; - - /*************************************************/ - /* SHA-1 Single-Round Known Answer Hashing Test. */ - /*************************************************/ - - sha_status = SHA1_HashBuf( sha_computed_digest, known_hash_message, - FIPS_KNOWN_HASH_MESSAGE_LENGTH ); - - if( ( sha_status != SECSuccess ) || - ( PORT_Memcmp( sha_computed_digest, sha1_known_digest, - SHA1_LENGTH ) != 0 ) ) - return( CKR_DEVICE_ERROR ); - - /***************************************************/ - /* SHA-224 Single-Round Known Answer Hashing Test. */ - /***************************************************/ - - sha_status = SHA224_HashBuf( sha_computed_digest, known_hash_message, - FIPS_KNOWN_HASH_MESSAGE_LENGTH ); - - if( ( sha_status != SECSuccess ) || - ( PORT_Memcmp( sha_computed_digest, sha224_known_digest, - SHA224_LENGTH ) != 0 ) ) - return( CKR_DEVICE_ERROR ); - - /***************************************************/ - /* SHA-256 Single-Round Known Answer Hashing Test. */ - /***************************************************/ - - sha_status = SHA256_HashBuf( sha_computed_digest, known_hash_message, - FIPS_KNOWN_HASH_MESSAGE_LENGTH ); - - if( ( sha_status != SECSuccess ) || - ( PORT_Memcmp( sha_computed_digest, sha256_known_digest, - SHA256_LENGTH ) != 0 ) ) - return( CKR_DEVICE_ERROR ); - - /***************************************************/ - /* SHA-384 Single-Round Known Answer Hashing Test. */ - /***************************************************/ - - sha_status = SHA384_HashBuf( sha_computed_digest, known_hash_message, - FIPS_KNOWN_HASH_MESSAGE_LENGTH ); - - if( ( sha_status != SECSuccess ) || - ( PORT_Memcmp( sha_computed_digest, sha384_known_digest, - SHA384_LENGTH ) != 0 ) ) - return( CKR_DEVICE_ERROR ); - - /***************************************************/ - /* SHA-512 Single-Round Known Answer Hashing Test. */ - /***************************************************/ - - sha_status = SHA512_HashBuf( sha_computed_digest, known_hash_message, - FIPS_KNOWN_HASH_MESSAGE_LENGTH ); - - if( ( sha_status != SECSuccess ) || - ( PORT_Memcmp( sha_computed_digest, sha512_known_digest, - SHA512_LENGTH ) != 0 ) ) - return( CKR_DEVICE_ERROR ); - - return( CKR_OK ); -} - - -static CK_RV -freebl_fipsSoftwareIntegrityTest(void) -{ - CK_RV crv = CKR_OK; - - /* make sure that our check file signatures are OK */ - if (!BLAPI_VerifySelf(SHLIB_PREFIX"freebl"SHLIB_VERSION"."SHLIB_SUFFIX)) { - crv = CKR_DEVICE_ERROR; /* better error code? checksum error? */ - } - return crv; -} - +/* FIPS selftests are implemented in library constructors and abort on failure + * - if anybody gets to call this function it means the tests passed and this + * can be a successful no-op; the integrity selftest that used to be here is + * handled by the freebl constructor as well + */ CK_RV freebl_fipsPowerUpSelfTest( void ) { - CK_RV rv; - - /* MD2 Power-Up SelfTest(s). */ - rv = freebl_fips_MD2_PowerUpSelfTest(); - - if( rv != CKR_OK ) - return rv; - - /* MD5 Power-Up SelfTest(s). */ - rv = freebl_fips_MD5_PowerUpSelfTest(); - - if( rv != CKR_OK ) - return rv; - - /* SHA-X Power-Up SelfTest(s). */ - rv = freebl_fips_SHA_PowerUpSelfTest(); - - if( rv != CKR_OK ) - return rv; - - /* Software/Firmware Integrity Test. */ - rv = freebl_fipsSoftwareIntegrityTest(); - - if( rv != CKR_OK ) - return rv; - - /* Passed Power-Up SelfTest(s). */ return( CKR_OK ); } struct NSSLOWInitContextStr { int count; }; struct NSSLOWHASHContextStr { const SECHashObject *hashObj; void *hashCtxt; }; -static int nsslow_GetFIPSEnabled(void) { -#ifdef LINUX - FILE *f; - char d; - size_t size; - - f = fopen("/proc/sys/crypto/fips_enabled", "r"); - if (!f) - return 0; - - size = fread(&d, 1, 1, f); - fclose(f); - if (size != 1) - return 0; - if (d != '1') - return 0; -#endif - return 1; -} - - -static int post = 0; -static int post_failed = 0; - static NSSLOWInitContext dummyContext = { 0 }; NSSLOWInitContext * NSSLOW_Init(void) { SECStatus rv; CK_RV crv; #ifdef FREEBL_NO_DEPEND PRBool nsprAvailable = PR_FALSE; rv = FREEBL_InitStubs(); nsprAvailable = (rv == SECSuccess ) ? PR_TRUE : PR_FALSE; #endif - if (post_failed) { - return NULL; - } - - - if (!post && nsslow_GetFIPSEnabled()) { - crv = freebl_fipsPowerUpSelfTest(); - if (crv != CKR_OK) { - post_failed = 1; - return NULL; - } - } - post = 1; - - return &dummyContext; } void NSSLOW_Shutdown(NSSLOWInitContext *context) { PORT_Assert(context == &dummyContext); return; } void NSSLOW_Reset(NSSLOWInitContext *context) { PORT_Assert(context == &dummyContext); - post_failed = 0; - post = 0; return; } NSSLOWHASHContext * NSSLOWHASH_NewContext(NSSLOWInitContext *initContext, HASH_HashType hashType) { NSSLOWHASHContext *context; - if (post_failed) { - PORT_SetError(SEC_ERROR_PKCS11_DEVICE_ERROR); - return NULL; - } - if (initContext != &dummyContext) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return (NULL); } context = PORT_ZNew(NSSLOWHASHContext); if (!context) { return NULL; diff --git a/lib/freebl/shvfy.c b/lib/freebl/shvfy.c --- a/lib/freebl/shvfy.c +++ b/lib/freebl/shvfy.c @@ -269,37 +269,37 @@ readItem(PRFileDesc *fd, SECItem *item) item->data = NULL; item->len = 0; return SECFailure; } return SECSuccess; } PRBool -BLAPI_SHVerify(const char *name, PRFuncPtr addr) +BLAPI_SHVerify(const char *name, PRFuncPtr addr, int *err) { 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); + result = BLAPI_SHVerifyFile(shName, err); loser: if (shName != NULL) { PR_Free(shName); } return result; } PRBool -BLAPI_SHVerifyFile(const char *shName) +BLAPI_SHVerifyFile(const char *shName, int *err) { char *checkName = NULL; PRFileDesc *checkFD = NULL; PRFileDesc *shFD = NULL; void *hashcx = NULL; const SECHashObject *hashObj = NULL; SECItem signature = { 0, NULL, 0 }; SECItem hash; @@ -332,16 +332,19 @@ BLAPI_SHVerifyFile(const char *shName) /* open the check File */ checkFD = PR_Open(checkName, PR_RDONLY, 0); if (checkFD == NULL) { #ifdef DEBUG_SHVERIFY fprintf(stderr, "Failed to open the check file %s: (%d, %d)\n", checkName, (int)PR_GetError(), (int)PR_GetOSError()); #endif /* DEBUG_SHVERIFY */ + if (err) { + *err = PORT_GetError(); + } goto loser; } /* read and Verify the headerthe header */ bytesRead = PR_Read(checkFD, buf, 12); if (bytesRead != 12) { goto loser; } @@ -490,19 +493,19 @@ loser: if (key.publicValue.data != NULL) { PORT_Free(key.publicValue.data); } return result; } PRBool -BLAPI_VerifySelf(const char *name) +BLAPI_VerifySelf(const char *name, int *err) { 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); + return BLAPI_SHVerify(name, (PRFuncPtr) decodeInt, err); } diff --git a/lib/softoken/fips.c b/lib/softoken/fips.c new file mode 100644 --- /dev/null +++ b/lib/softoken/fips.c @@ -0,0 +1,26 @@ +#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 == FIPS_cryptoSelftestSoftoken()) { + return CHECK_OK; + } else { + return CHECK_FAIL_CRYPTO; + } +} + +/* constructor - load-time selfchecks */ +static void __attribute__ ((constructor)) +fips_initTestSoftoken(void) +{ + fips_state = fips_initTest("softokn", (PRFuncPtr)fips_initTestSoftoken, fips_checkCryptoSoftoken); + + return; +} + diff --git a/lib/softoken/fips.h b/lib/softoken/fips.h new file mode 100644 --- /dev/null +++ b/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/lib/softoken/fipstest.c b/lib/softoken/fipstest.c --- a/lib/softoken/fipstest.c +++ b/lib/softoken/fipstest.c @@ -77,16 +77,22 @@ #define FIPS_DSA_SUBPRIME_LENGTH 20 /* 160-bits */ #define FIPS_DSA_SIGNATURE_LENGTH 40 /* 320-bits */ #define FIPS_DSA_PRIME_LENGTH 128 /* 1024-bits */ #define FIPS_DSA_BASE_LENGTH 128 /* 1024-bits */ /* FIPS preprocessor directives for RNG. */ #define FIPS_RNG_XKEY_LENGTH 32 /* 256-bits */ +/* Do not test algorithms not approved for use in FIPS 140-2 - it adds + * unnecessary time and code overhead for no noticable gain. + * Build with -DRUN_ALL_SELFTESTS to compile the tests in + */ + +#ifdef RUN_ALL_SELFTESTS static CK_RV sftk_fips_RC2_PowerUpSelfTest( void ) { /* RC2 Known Key (40-bits). */ static const PRUint8 rc2_known_key[] = { "RSARC" }; /* RC2-CBC Known Initialization Vector (64-bits). */ static const PRUint8 rc2_cbc_known_initialization_vector[] = {"Security"}; @@ -402,16 +408,17 @@ sftk_fips_DES_PowerUpSelfTest( void ) if( ( des_status != SECSuccess ) || ( des_bytes_decrypted != FIPS_DES_DECRYPT_LENGTH ) || ( PORT_Memcmp( des_computed_plaintext, des_cbc_known_plaintext, FIPS_DES_DECRYPT_LENGTH ) != 0 ) ) return( CKR_DEVICE_ERROR ); return( CKR_OK ); } +#endif static CK_RV sftk_fips_DES3_PowerUpSelfTest( void ) { /* DES3 Known Key (56-bits). */ static const PRUint8 des3_known_key[] = { "ANSI Triple-DES Key Data" }; @@ -1985,34 +1992,40 @@ sftk_fips_RNG_PowerUpSelfTest( void ) if( ( rng_status != SECSuccess ) || ( PORT_Memcmp( DSAX, rng_known_DSAX, (FIPS_DSA_SUBPRIME_LENGTH) ) != 0 ) ) return( CKR_DEVICE_ERROR ); return( CKR_OK ); } -static CK_RV -sftk_fipsSoftwareIntegrityTest(void) +/* FIPS selftests are implemented in library constructors and abort on failure + * - if anybody gets to call this function it means the tests passed and this + * can be a successful no-op + */ +CK_RV +sftk_fipsPowerUpSelfTest( void ) { - CK_RV crv = CKR_OK; - - /* make sure that our check file signatures are OK */ - if( !BLAPI_VerifySelf( NULL ) || - !BLAPI_SHVerify( SOFTOKEN_LIB_NAME, (PRFuncPtr) sftk_fips_HMAC ) ) { - crv = CKR_DEVICE_ERROR; /* better error code? checksum error? */ - } - return crv; + return CKR_OK; } CK_RV -sftk_fipsPowerUpSelfTest( void ) +FIPS_cryptoSelftestSoftoken( void ) { CK_RV rv; + /* intialise BL */ + if( SECSuccess != BL_Init() ) + return CKR_GENERAL_ERROR; + + /* intialise RNG (needed for RSA blinging parameters */ + if( SECSuccess != RNG_RNGInit() ) + return CKR_GENERAL_ERROR; + +#ifdef RUN_ALL_SELFTESTS /* RC2 Power-Up SelfTest(s). */ rv = sftk_fips_RC2_PowerUpSelfTest(); if( rv != CKR_OK ) return rv; /* RC4 Power-Up SelfTest(s). */ rv = sftk_fips_RC4_PowerUpSelfTest(); @@ -2020,16 +2033,17 @@ sftk_fipsPowerUpSelfTest( void ) if( rv != CKR_OK ) return rv; /* DES Power-Up SelfTest(s). */ rv = sftk_fips_DES_PowerUpSelfTest(); if( rv != CKR_OK ) return rv; +#endif /* DES3 Power-Up SelfTest(s). */ rv = sftk_fips_DES3_PowerUpSelfTest(); if( rv != CKR_OK ) return rv; /* AES Power-Up SelfTest(s) for 128-bit key. */ @@ -2045,27 +2059,29 @@ sftk_fipsPowerUpSelfTest( void ) return rv; /* AES Power-Up SelfTest(s) for 256-bit key. */ rv = sftk_fips_AES_PowerUpSelfTest(FIPS_AES_256_KEY_SIZE); if( rv != CKR_OK ) return rv; +#ifdef RUN_ALL_SELFTESTS /* MD2 Power-Up SelfTest(s). */ rv = sftk_fips_MD2_PowerUpSelfTest(); if( rv != CKR_OK ) return rv; /* MD5 Power-Up SelfTest(s). */ rv = sftk_fips_MD5_PowerUpSelfTest(); if( rv != CKR_OK ) return rv; +#endif /* SHA-X Power-Up SelfTest(s). */ rv = sftk_fips_SHA_PowerUpSelfTest(); if( rv != CKR_OK ) return rv; /* HMAC SHA-X Power-Up SelfTest(s). */ @@ -2095,18 +2111,12 @@ sftk_fipsPowerUpSelfTest( void ) #ifndef NSS_DISABLE_ECC /* ECDSA Power-Up SelfTest(s). */ rv = sftk_fips_ECDSA_PowerUpSelfTest(); if( rv != CKR_OK ) return rv; #endif - /* Software/Firmware Integrity Test. */ - rv = sftk_fipsSoftwareIntegrityTest(); - - if( rv != CKR_OK ) - return rv; - /* Passed Power-Up SelfTest(s). */ return( CKR_OK ); } diff --git a/lib/softoken/fipstokn.c b/lib/softoken/fipstokn.c --- a/lib/softoken/fipstokn.c +++ b/lib/softoken/fipstokn.c @@ -445,30 +445,19 @@ CK_RV FC_Initialize(CK_VOID_PTR pReserve /* not an 'else' rv can be set by either SFTK_LowInit or SFTK_SlotInit*/ if (crv != CKR_OK) { sftk_fatalError = PR_TRUE; return crv; } sftk_fatalError = PR_FALSE; /* any error has been reset */ - crv = sftk_fipsPowerUpSelfTest(); - if (crv != CKR_OK) { - nsc_CommonFinalize(NULL, PR_TRUE); - sftk_fatalError = PR_TRUE; - if (sftk_audit_enabled) { - char msg[128]; - PR_snprintf(msg,sizeof msg, - "C_Initialize()=0x%08lX " - "power-up self-tests failed", - (PRUint32)crv); - sftk_LogAuditMessage(NSS_AUDIT_ERROR, NSS_AUDIT_SELF_TEST, msg); - } - return crv; - } + /* FIPS selftests that were here have been moved to constructors + * (freebl, softoken and dbm) as to be executed at library load time */ + nsf_init = PR_TRUE; return CKR_OK; } /*FC_Finalize indicates that an application is done with the PKCS #11 library.*/ CK_RV FC_Finalize (CK_VOID_PTR pReserved) { CK_RV crv; diff --git a/lib/softoken/legacydb/fips.c b/lib/softoken/legacydb/fips.c new file mode 100644 --- /dev/null +++ b/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/lib/softoken/legacydb/fips.h b/lib/softoken/legacydb/fips.h new file mode 100644 --- /dev/null +++ b/lib/softoken/legacydb/fips.h @@ -0,0 +1,5 @@ +#ifndef FIPS_H +#define FIPS_H + +#endif + diff --git a/lib/softoken/legacydb/manifest.mn b/lib/softoken/legacydb/manifest.mn --- a/lib/softoken/legacydb/manifest.mn +++ b/lib/softoken/legacydb/manifest.mn @@ -2,16 +2,17 @@ # 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/. CORE_DEPTH = ../../.. MODULE = nss REQUIRES = dbm +DEFINES += -DSHLIB_SUFFIX=\"$(DLL_SUFFIX)\" -DSHLIB_PREFIX=\"$(DLL_PREFIX)\" -DSHLIB_VERSION=\"$(LIBRARY_VERSION)\" LIBRARY_NAME = nssdbm LIBRARY_VERSION = 3 MAPFILE = $(OBJDIR)/nssdbm.def DEFINES += -DSHLIB_SUFFIX=\"$(DLL_SUFFIX)\" -DSHLIB_PREFIX=\"$(DLL_PREFIX)\" CSRCS = \ @@ -22,10 +23,11 @@ CSRCS = \ lgdestroy.c \ lgfind.c \ lginit.c \ lgutil.c \ lowcert.c \ lowkey.c \ pcertdb.c \ pk11db.c \ + fips.c \ $(NULL) diff --git a/lib/softoken/lgglue.c b/lib/softoken/lgglue.c --- a/lib/softoken/lgglue.c +++ b/lib/softoken/lgglue.c @@ -256,17 +256,17 @@ sftkdbLoad_Legacy(PRBool isFIPS) LGSetCryptFunc setCryptFunction = NULL; if (legacy_glue_lib) { /* this check is necessary because it's possible we loaded the * legacydb to read secmod.db, which told us whether we were in * FIPS mode or not. */ if (isFIPS && !legacy_glue_libCheckSucceeded) { if (legacy_glue_libCheckFailed || - !BLAPI_SHVerify(LEGACY_LIB_NAME,(PRFuncPtr)legacy_glue_open)) { + !BLAPI_SHVerify(LEGACY_LIB_NAME,(PRFuncPtr)legacy_glue_open, NULL)) { legacy_glue_libCheckFailed = PR_TRUE; /* don't clobber legacy glue to avoid race. just let it * get cleared in shutdown */ return SECFailure; } legacy_glue_libCheckSucceeded = PR_TRUE; } return SECSuccess; @@ -295,17 +295,17 @@ sftkdbLoad_Legacy(PRBool isFIPS) !legacy_glue_releaseSecmod || !legacy_glue_deleteSecmod || !legacy_glue_addSecmod || !setCryptFunction) { PR_UnloadLibrary(lib); return SECFailure; } /* verify the loaded library if we are in FIPS mode */ if (isFIPS) { - if (!BLAPI_SHVerify(LEGACY_LIB_NAME,(PRFuncPtr)legacy_glue_open)) { + if (!BLAPI_SHVerify(LEGACY_LIB_NAME,(PRFuncPtr)legacy_glue_open, NULL)) { PR_UnloadLibrary(lib); return SECFailure; } legacy_glue_libCheckSucceeded = PR_TRUE; } setCryptFunction(sftkdb_encrypt_stub,sftkdb_decrypt_stub); legacy_glue_lib = lib; diff --git a/lib/softoken/manifest.mn b/lib/softoken/manifest.mn --- a/lib/softoken/manifest.mn +++ b/lib/softoken/manifest.mn @@ -25,16 +25,17 @@ PRIVATE_EXPORTS = \ lowkeyi.h \ lowkeyti.h \ pkcs11ni.h \ softoken.h \ softoknt.h \ softkver.h \ sdb.h \ sftkdbt.h \ + fips.h \ $(NULL) CSRCS = \ fipsaudt.c \ fipstest.c \ fipstokn.c \ lgglue.c \ lowkey.c \ @@ -46,16 +47,17 @@ CSRCS = \ sdb.c \ sftkdb.c \ sftkhmac.c \ sftkpars.c \ sftkpwd.c \ softkver.c \ tlsprf.c \ jpakesftk.c \ + fips.c \ $(NULL) ifdef SQLITE_UNSAFE_THREADS DEFINES += -DSQLITE_UNSAFE_THREADS endif # This part of the code, including all sub-dirs, can be optimized for size export ALLOW_OPT_CODE_SIZE = 1
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor