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.
742 lines
30 KiB
742 lines
30 KiB
diff --git a/lib/freebl/config.mk b/lib/freebl/config.mk |
|
--- a/lib/freebl/config.mk |
|
+++ b/lib/freebl/config.mk |
|
@@ -85,9 +85,13 @@ EXTRA_SHARED_LIBS += \ |
|
$(NULL) |
|
endif |
|
endif |
|
|
|
ifeq ($(OS_ARCH), Darwin) |
|
EXTRA_SHARED_LIBS += -dylib_file @executable_path/libplc4.dylib:$(DIST)/lib/libplc4.dylib -dylib_file @executable_path/libplds4.dylib:$(DIST)/lib/libplds4.dylib |
|
endif |
|
|
|
+ifdef NSS_FIPS_140_3 |
|
+DEFINES += -DNSS_FIPS_140_3 |
|
endif |
|
+ |
|
+endif |
|
diff --git a/lib/freebl/unix_urandom.c b/lib/freebl/unix_urandom.c |
|
--- a/lib/freebl/unix_urandom.c |
|
+++ b/lib/freebl/unix_urandom.c |
|
@@ -20,53 +20,110 @@ RNG_SystemInfoForRNG(void) |
|
if (!numBytes) { |
|
/* error is set */ |
|
return; |
|
} |
|
RNG_RandomUpdate(bytes, numBytes); |
|
PORT_Memset(bytes, 0, sizeof bytes); |
|
} |
|
|
|
+#ifdef NSS_FIPS_140_3 |
|
+#include <sys/random.h> |
|
+#include "prinit.h" |
|
+ |
|
+static int rng_grndFlags= 0; |
|
+static PRCallOnceType rng_KernelFips; |
|
+ |
|
+static PRStatus |
|
+rng_getKernelFips() |
|
+{ |
|
+#ifdef LINUX |
|
+ FILE *f; |
|
+ char d; |
|
+ size_t size; |
|
+ |
|
+ f = fopen("/proc/sys/crypto/fips_enabled", "r"); |
|
+ if (!f) |
|
+ return PR_FAILURE; |
|
+ |
|
+ size = fread(&d, 1, 1, f); |
|
+ fclose(f); |
|
+ if (size != 1) |
|
+ return PR_SUCCESS; |
|
+ if (d != '1') |
|
+ return PR_SUCCESS; |
|
+ /* if the kernel is in FIPS mode, set the GRND_RANDOM flag */ |
|
+ rng_grndFlags = GRND_RANDOM; |
|
+#endif /* LINUX */ |
|
+ return PR_SUCCESS; |
|
+} |
|
+#endif |
|
+ |
|
size_t |
|
RNG_SystemRNG(void *dest, size_t maxLen) |
|
{ |
|
+ size_t fileBytes = 0; |
|
+ unsigned char *buffer = dest; |
|
+#ifndef NSS_FIPS_140_3 |
|
int fd; |
|
int bytes; |
|
- size_t fileBytes = 0; |
|
- unsigned char *buffer = dest; |
|
+#else |
|
+ PR_CallOnce(&rng_KernelFips, rng_getKernelFips); |
|
+#endif |
|
|
|
#if defined(__OpenBSD__) || (defined(__FreeBSD__) && __FreeBSD_version >= 1200000) || (defined(LINUX) && defined(__GLIBC__) && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 25)))) |
|
int result; |
|
- |
|
while (fileBytes < maxLen) { |
|
size_t getBytes = maxLen - fileBytes; |
|
if (getBytes > GETENTROPY_MAX_BYTES) { |
|
getBytes = GETENTROPY_MAX_BYTES; |
|
} |
|
+#ifdef NSS_FIPS_140_3 |
|
+ /* FIP 140-3 requires full kernel reseeding for chained entropy sources |
|
+ * so we need to use getrandom with GRND_RANDOM. |
|
+ * getrandom returns -1 on failure, otherwise returns |
|
+ * the number of bytes, which can be less than getBytes */ |
|
+ result = getrandom(buffer, getBytes, rng_grndFlags); |
|
+ if (result < 0) { |
|
+ break; |
|
+ } |
|
+ fileBytes += result; |
|
+ buffer += result; |
|
+#else |
|
+ /* get entropy returns 0 on success and always return |
|
+ * getBytes on success */ |
|
result = getentropy(buffer, getBytes); |
|
if (result == 0) { /* success */ |
|
fileBytes += getBytes; |
|
buffer += getBytes; |
|
} else { |
|
break; |
|
} |
|
+#endif |
|
} |
|
if (fileBytes == maxLen) { /* success */ |
|
return maxLen; |
|
} |
|
+#ifdef NSS_FIPS_140_3 |
|
+ /* in FIPS 104-3 we don't fallback, just fail */ |
|
+ PORT_SetError(SEC_ERROR_NEED_RANDOM); |
|
+ return 0; |
|
+#else |
|
/* If we failed with an error other than ENOSYS, it means the destination |
|
* buffer is not writeable. We don't need to try writing to it again. */ |
|
if (errno != ENOSYS) { |
|
PORT_SetError(SEC_ERROR_NEED_RANDOM); |
|
return 0; |
|
} |
|
+#endif /*!NSS_FIPS_140_3 */ |
|
+#endif /* platorm has getentropy */ |
|
+#ifndef NSS_FIPS_140_3 |
|
/* ENOSYS means the kernel doesn't support getentropy()/getrandom(). |
|
* Reset the number of bytes to get and fall back to /dev/urandom. */ |
|
fileBytes = 0; |
|
-#endif |
|
fd = open("/dev/urandom", O_RDONLY); |
|
if (fd < 0) { |
|
PORT_SetError(SEC_ERROR_NEED_RANDOM); |
|
return 0; |
|
} |
|
while (fileBytes < maxLen) { |
|
bytes = read(fd, buffer, maxLen - fileBytes); |
|
if (bytes <= 0) { |
|
@@ -76,9 +133,10 @@ RNG_SystemRNG(void *dest, size_t maxLen) |
|
buffer += bytes; |
|
} |
|
(void)close(fd); |
|
if (fileBytes != maxLen) { |
|
PORT_SetError(SEC_ERROR_NEED_RANDOM); |
|
return 0; |
|
} |
|
return fileBytes; |
|
+#endif |
|
} |
|
diff --git a/lib/softoken/config.mk b/lib/softoken/config.mk |
|
--- a/lib/softoken/config.mk |
|
+++ b/lib/softoken/config.mk |
|
@@ -58,8 +58,12 @@ 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 |
|
|
|
+ifdef NSS_FIPS_140_3 |
|
+DEFINES += -DNSS_FIPS_140_3 |
|
+endif |
|
+ |
|
diff --git a/lib/softoken/fips_algorithms.h b/lib/softoken/fips_algorithms.h |
|
--- a/lib/softoken/fips_algorithms.h |
|
+++ b/lib/softoken/fips_algorithms.h |
|
@@ -49,33 +49,45 @@ SFTKFIPSAlgorithmList sftk_fips_mechs[] |
|
#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 1024 |
|
+#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, SFTKFIPSNone }, |
|
- { 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, SFTKFIPSNone }, |
|
+ |
|
/* -------------- 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, { RSA_LEGACY_FB_KEY, CKF_VERIFY }, RSA_LEGACY_FB_STEP, SFTKFIPSNone }, |
|
+ { CKM_SHA256_RSA_PKCS, { RSA_LEGACY_FB_KEY, CKF_VERIFY }, RSA_LEGACY_FB_STEP, SFTKFIPSNone }, |
|
+ { CKM_SHA384_RSA_PKCS, { RSA_LEGACY_FB_KEY, CKF_VERIFY }, RSA_LEGACY_FB_STEP, SFTKFIPSNone }, |
|
+ { CKM_SHA512_RSA_PKCS, { RSA_LEGACY_FB_KEY, CKF_VERIFY }, RSA_LEGACY_FB_STEP, SFTKFIPSNone }, |
|
+ { CKM_SHA224_RSA_PKCS_PSS, { RSA_LEGACY_FB_KEY, CKF_VERIFY }, RSA_LEGACY_FB_STEP, SFTKFIPSNone }, |
|
+ { CKM_SHA256_RSA_PKCS_PSS, { RSA_LEGACY_FB_KEY, CKF_VERIFY }, RSA_LEGACY_FB_STEP, SFTKFIPSNone }, |
|
+ { CKM_SHA384_RSA_PKCS_PSS, { RSA_LEGACY_FB_KEY, CKF_VERIFY }, RSA_LEGACY_FB_STEP, SFTKFIPSNone }, |
|
+ { CKM_SHA512_RSA_PKCS_PSS, { RSA_LEGACY_FB_KEY, CKF_VERIFY }, RSA_LEGACY_FB_STEP, SFTKFIPSNone }, |
|
{ CKM_SHA224_RSA_PKCS_PSS, { RSA_FB_KEY, CKF_SGN }, RSA_FB_STEP, SFTKFIPSNone }, |
|
{ CKM_SHA256_RSA_PKCS_PSS, { RSA_FB_KEY, CKF_SGN }, RSA_FB_STEP, SFTKFIPSNone }, |
|
{ CKM_SHA384_RSA_PKCS_PSS, { RSA_FB_KEY, CKF_SGN }, RSA_FB_STEP, SFTKFIPSNone }, |
|
{ CKM_SHA512_RSA_PKCS_PSS, { RSA_FB_KEY, CKF_SGN }, RSA_FB_STEP, SFTKFIPSNone }, |
|
/* ------------------------- 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 }, |
|
@@ -95,76 +107,73 @@ SFTKFIPSAlgorithmList sftk_fips_mechs[] |
|
{ 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_SHA256_HMAC, { 112, 256, CKF_SGN }, 1, SFTKFIPSNone }, |
|
+ { CKM_SHA256_HMAC_GENERAL, { 112, 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_SHA384_HMAC, { 112, 384, CKF_SGN }, 1, SFTKFIPSNone }, |
|
+ { CKM_SHA384_HMAC_GENERAL, { 112, 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 }, |
|
+ { CKM_SHA512_HMAC, { 112, 512, CKF_SGN }, 1, SFTKFIPSNone }, |
|
+ { CKM_SHA512_HMAC_GENERAL, { 112, 512, CKF_SGN }, 1, SFTKFIPSNone }, |
|
/* --------------------- Secret Key Operations ------------------------ */ |
|
- { CKM_GENERIC_SECRET_KEY_GEN, { 8, 256, CKF_GEN }, 1, SFTKFIPSNone }, |
|
+ { CKM_GENERIC_SECRET_KEY_GEN, { 112, 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, 284, CKF_KDF }, 1, SFTKFIPSNone }, |
|
- { CKM_SHA512_KEY_DERIVATION, { 256, 512, CKF_KDF }, 1, SFTKFIPSNone }, |
|
+ { CKM_SHA256_KEY_DERIVATION, { 112, 256, CKF_KDF }, 1, SFTKFIPSNone }, |
|
+ { CKM_SHA384_KEY_DERIVATION, { 112, 284, CKF_KDF }, 1, SFTKFIPSNone }, |
|
+ { CKM_SHA512_KEY_DERIVATION, { 112, 512, CKF_KDF }, 1, SFTKFIPSNone }, |
|
+ { CKM_SSL3_PRE_MASTER_KEY_GEN, { 384, 384, CKF_GEN }, 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 }, |
|
+ { CKM_TLS_PRF_GENERAL, { 112, 512, CKF_SGN }, 1, SFTKFIPSNone }, |
|
+ { CKM_TLS_MAC, { 112, 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_DERIVE, { 112, 255 * 64 * 8, CKF_KDF }, 1, SFTKFIPSNone }, |
|
+ { CKM_HKDF_DATA, { 112, 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 }, |
|
+ { CKM_SP800_108_COUNTER_KDF, { 112, CK_MAX, CKF_KDF }, 1, SFTKFIPSNone }, |
|
+ { CKM_SP800_108_FEEDBACK_KDF, { 112, CK_MAX, CKF_KDF }, 1, SFTKFIPSNone }, |
|
+ { CKM_SP800_108_DOUBLE_PIPELINE_KDF, { 112, CK_MAX, CKF_KDF }, 1, SFTKFIPSNone }, |
|
+ { CKM_NSS_SP800_108_COUNTER_KDF_DERIVE_DATA, { 112, CK_MAX, CKF_KDF }, 1, SFTKFIPSNone }, |
|
+ { CKM_NSS_SP800_108_FEEDBACK_KDF_DERIVE_DATA, { 112, CK_MAX, CKF_KDF }, 1, SFTKFIPSNone }, |
|
+ { CKM_NSS_SP800_108_DOUBLE_PIPELINE_KDF_DERIVE_DATA, { 112, 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 }, |
|
+ { CKM_NSS_IKE_PRF_PLUS_DERIVE, { 112, 255 * 64, CKF_KDF }, 1, SFTKFIPSNone }, |
|
+ { CKM_NSS_IKE_PRF_DERIVE, { 112, 64, CKF_KDF }, 1, SFTKFIPSNone }, |
|
+ { CKM_NSS_IKE1_PRF_DERIVE, { 112, 64, CKF_KDF }, 1, SFTKFIPSNone }, |
|
+ { CKM_NSS_IKE1_APP_B_PRF_DERIVE, { 112, 255 * 64, CKF_KDF }, 1, SFTKFIPSNone }, |
|
/* ------------------ PBE Key Derivations ------------------- */ |
|
- { CKM_PKCS5_PBKD2, { 1, 256, CKF_GEN }, 1, SFTKFIPSNone }, |
|
+ { CKM_PKCS5_PBKD2, { 112, 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); |
|
diff --git a/lib/softoken/lowpbe.c b/lib/softoken/lowpbe.c |
|
--- a/lib/softoken/lowpbe.c |
|
+++ b/lib/softoken/lowpbe.c |
|
@@ -1765,27 +1765,29 @@ 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 saltData[] = { |
|
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, |
|
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f |
|
+ }; |
|
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 |
|
+ 0x73, 0x8c, 0xfa, 0x02, 0xe8, 0xdb, 0x43, 0xe4, |
|
+ 0x99, 0xc5, 0xfd, 0xd9, 0x4d, 0x8e, 0x3e, 0x7b, |
|
+ 0xc4, 0xda, 0x22, 0x1b, 0xe1, 0xae, 0x23, 0x7a, |
|
+ 0x21, 0x27, 0xbd, 0xcc, 0x78, 0xc4, 0xe6, 0xc5, |
|
+ 0x33, 0x38, 0x35, 0xe0, 0x68, 0x1a, 0x1e, 0x06, |
|
+ 0xad, 0xaf, 0x7f, 0xd7, 0x3f, 0x0e, 0xc0, 0x90, |
|
+ 0x17, 0x97, 0x73, 0x75, 0x7b, 0x88, 0x49, 0xd8, |
|
+ 0x6f, 0x78, 0x5a, 0xde, 0x50, 0x20, 0x55, 0x33 |
|
}; |
|
|
|
sftk_PBELockInit(); |
|
|
|
inKey.data = (unsigned char *)inKeyData; |
|
inKey.len = sizeof(TEST_KEY) - 1; |
|
|
|
pbe_params.salt.data = (unsigned char *)saltData; |
|
diff --git a/lib/softoken/pkcs11c.c b/lib/softoken/pkcs11c.c |
|
--- a/lib/softoken/pkcs11c.c |
|
+++ b/lib/softoken/pkcs11c.c |
|
@@ -4609,16 +4609,17 @@ NSC_GenerateKey(CK_SESSION_HANDLE hSessi |
|
goto loser; |
|
} |
|
|
|
/* make sure we don't have any class, key_type, or value fields */ |
|
sftk_DeleteAttributeType(key, CKA_CLASS); |
|
sftk_DeleteAttributeType(key, CKA_KEY_TYPE); |
|
sftk_DeleteAttributeType(key, CKA_VALUE); |
|
|
|
+ |
|
/* Now Set up the parameters to generate the key (based on mechanism) */ |
|
key_gen_type = nsc_bulk; /* bulk key by default */ |
|
switch (pMechanism->mechanism) { |
|
case CKM_CDMF_KEY_GEN: |
|
case CKM_DES_KEY_GEN: |
|
case CKM_DES2_KEY_GEN: |
|
case CKM_DES3_KEY_GEN: |
|
checkWeak = PR_TRUE; |
|
@@ -4812,16 +4813,19 @@ NSC_GenerateKey(CK_SESSION_HANDLE hSessi |
|
crv = sftk_handleObject(key, session); |
|
sftk_FreeSession(session); |
|
if (crv == CKR_OK && sftk_isTrue(key, CKA_SENSITIVE)) { |
|
crv = sftk_forceAttribute(key, CKA_ALWAYS_SENSITIVE, &cktrue, sizeof(CK_BBOOL)); |
|
} |
|
if (crv == CKR_OK && !sftk_isTrue(key, CKA_EXTRACTABLE)) { |
|
crv = sftk_forceAttribute(key, CKA_NEVER_EXTRACTABLE, &cktrue, sizeof(CK_BBOOL)); |
|
} |
|
+ /* we need to do this check at the end, so we can check the generated key length against |
|
+ * fips requirements */ |
|
+ key->isFIPS = sftk_operationIsFIPS(slot, pMechanism, CKA_NSS_GENERATE, key); |
|
if (crv == CKR_OK) { |
|
*phKey = key->handle; |
|
} |
|
loser: |
|
PORT_Memset(buf, 0, sizeof buf); |
|
sftk_FreeObject(key); |
|
return crv; |
|
} |
|
@@ -5780,16 +5784,19 @@ NSC_GenerateKeyPair(CK_SESSION_HANDLE hS |
|
|
|
if (crv != CKR_OK) { |
|
NSC_DestroyObject(hSession, publicKey->handle); |
|
sftk_FreeObject(publicKey); |
|
NSC_DestroyObject(hSession, privateKey->handle); |
|
sftk_FreeObject(privateKey); |
|
return crv; |
|
} |
|
+ /* we need to do this check at the end to make sure the generated key meets the key length requirements */ |
|
+ privateKey->isFIPS = sftk_operationIsFIPS(slot, pMechanism, CKA_NSS_GENERATE_KEY_PAIR, privateKey); |
|
+ publicKey->isFIPS = privateKey->isFIPS; |
|
|
|
*phPrivateKey = privateKey->handle; |
|
*phPublicKey = publicKey->handle; |
|
sftk_FreeObject(publicKey); |
|
sftk_FreeObject(privateKey); |
|
|
|
return CKR_OK; |
|
} |
|
@@ -6990,16 +6997,17 @@ sftk_HKDF(CK_HKDF_PARAMS_PTR params, CK_ |
|
} |
|
|
|
/* HKDF-Extract(salt, base key value) */ |
|
if (params->bExtract) { |
|
CK_BYTE *salt; |
|
CK_ULONG saltLen; |
|
HMACContext *hmac; |
|
unsigned int bufLen; |
|
+ SFTKSource saltKeySource = SFTK_SOURCE_DEFAULT; |
|
|
|
switch (params->ulSaltType) { |
|
case CKF_HKDF_SALT_NULL: |
|
saltLen = hashLen; |
|
salt = hashbuf; |
|
memset(salt, 0, saltLen); |
|
break; |
|
case CKF_HKDF_SALT_DATA: |
|
@@ -7026,29 +7034,54 @@ sftk_HKDF(CK_HKDF_PARAMS_PTR params, CK_ |
|
if (isFIPS && (key->isFIPS == 0) && (saltKey->isFIPS == 1)) { |
|
CK_MECHANISM mech; |
|
mech.mechanism = CKM_HKDF_DERIVE; |
|
mech.pParameter = params; |
|
mech.ulParameterLen = sizeof(*params); |
|
key->isFIPS = sftk_operationIsFIPS(saltKey->slot, &mech, |
|
CKA_DERIVE, saltKey); |
|
} |
|
+ saltKeySource = saltKey->source; |
|
saltKey_att = sftk_FindAttribute(saltKey, CKA_VALUE); |
|
if (saltKey_att == NULL) { |
|
sftk_FreeObject(saltKey); |
|
return CKR_KEY_HANDLE_INVALID; |
|
} |
|
/* save the resulting salt */ |
|
salt = saltKey_att->attrib.pValue; |
|
saltLen = saltKey_att->attrib.ulValueLen; |
|
break; |
|
default: |
|
return CKR_MECHANISM_PARAM_INVALID; |
|
break; |
|
} |
|
+ /* only TLS style usage is FIPS approved, |
|
+ * turn off the FIPS indicator for other usages */ |
|
+ if (isFIPS && key && sourceKey) { |
|
+ PRBool fipsOK = PR_FALSE; |
|
+ /* case one: mix the kea with a previous or default |
|
+ * salt */ |
|
+ if ((sourceKey->source == SFTK_SOURCE_KEA) && |
|
+ (saltKeySource == SFTK_SOURCE_HKDF_EXPAND) && |
|
+ (saltLen == rawHash->length)) { |
|
+ fipsOK = PR_TRUE; |
|
+ } |
|
+ /* case two: restart, remix the previous secret as a salt */ |
|
+ if ((sourceKey->objclass == CKO_DATA) && |
|
+ (NSS_SecureMemcmpZero(sourceKeyBytes, sourceKeyLen) == 0) && |
|
+ (sourceKeyLen == rawHash->length) && |
|
+ (saltKeySource == SFTK_SOURCE_HKDF_EXPAND) && |
|
+ (saltLen == rawHash->length)) { |
|
+ fipsOK = PR_TRUE; |
|
+ } |
|
+ if (!fipsOK) { |
|
+ key->isFIPS = PR_FALSE; |
|
+ } |
|
+ } |
|
+ if (key) key->source = SFTK_SOURCE_HKDF_EXTRACT; |
|
|
|
hmac = HMAC_Create(rawHash, salt, saltLen, isFIPS); |
|
if (saltKey_att) { |
|
sftk_FreeAttribute(saltKey_att); |
|
} |
|
if (saltKey) { |
|
sftk_FreeObject(saltKey); |
|
} |
|
@@ -7076,16 +7109,40 @@ sftk_HKDF(CK_HKDF_PARAMS_PTR params, CK_ |
|
/* T(1) = HMAC-Hash(prk, "" | info | 0x01) |
|
* T(n) = HMAC-Hash(prk, T(n-1) | info | n |
|
* key material = T(1) | ... | T(n) |
|
*/ |
|
HMACContext *hmac; |
|
CK_BYTE bi; |
|
unsigned iterations; |
|
|
|
+ /* only TLS style usage is FIPS approved, |
|
+ * turn off the FIPS indicator for other usages */ |
|
+ if (isFIPS && key && key->isFIPS && sourceKey) { |
|
+ unsigned char *info=¶ms->pInfo[3]; |
|
+ /* only one case, |
|
+ * 1) Expand only |
|
+ * 2) with a key whose source was |
|
+ * SFTK_SOURCE_HKDF_EXPAND or SFTK_SOURCE_HKDF_EXTRACT |
|
+ * 3) source key length == rawHash->length |
|
+ * 4) Info has tls or dtls |
|
+ * If any of those conditions aren't met, then we turn |
|
+ * off the fips indicator */ |
|
+ if (params->bExtract || |
|
+ ((sourceKey->source != SFTK_SOURCE_HKDF_EXTRACT) && |
|
+ (sourceKey->source != SFTK_SOURCE_HKDF_EXPAND)) || |
|
+ (sourceKeyLen != rawHash->length) || |
|
+ (params->ulInfoLen < 7) || |
|
+ ((PORT_Memcmp(info,"tls",3) != 0) && |
|
+ (PORT_Memcmp(info,"dtls",4) != 0))) { |
|
+ key->isFIPS = PR_FALSE; |
|
+ } |
|
+ } |
|
+ if (key) key->source = SFTK_SOURCE_HKDF_EXPAND; |
|
+ |
|
genLen = PR_ROUNDUP(keySize, hashLen); |
|
iterations = genLen / hashLen; |
|
|
|
if (genLen > sizeof(keyBlock)) { |
|
keyBlockAlloc = PORT_Alloc(genLen); |
|
if (keyBlockAlloc == NULL) { |
|
return CKR_HOST_MEMORY; |
|
} |
|
@@ -8434,16 +8491,17 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession |
|
|
|
/* calculate private value - oct */ |
|
rv = DH_Derive(&dhPublic, &dhPrime, &dhValue, &derived, keySize); |
|
|
|
SECITEM_ZfreeItem(&dhPrime, PR_FALSE); |
|
SECITEM_ZfreeItem(&dhValue, PR_FALSE); |
|
|
|
if (rv == SECSuccess) { |
|
+ key->source = SFTK_SOURCE_KEA; |
|
sftk_forceAttribute(key, CKA_VALUE, derived.data, derived.len); |
|
SECITEM_ZfreeItem(&derived, PR_FALSE); |
|
crv = CKR_OK; |
|
} else |
|
crv = CKR_HOST_MEMORY; |
|
|
|
break; |
|
} |
|
@@ -8564,16 +8622,17 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession |
|
} |
|
PORT_Memcpy(&keyData[keySize - secretlen], secret, secretlen); |
|
secret = keyData; |
|
} else { |
|
secret += (secretlen - keySize); |
|
} |
|
secretlen = keySize; |
|
} |
|
+ key->source = SFTK_SOURCE_KEA; |
|
|
|
sftk_forceAttribute(key, CKA_VALUE, secret, secretlen); |
|
PORT_ZFree(tmp.data, tmp.len); |
|
if (keyData) { |
|
PORT_ZFree(keyData, keySize); |
|
} |
|
break; |
|
|
|
diff --git a/lib/softoken/pkcs11i.h b/lib/softoken/pkcs11i.h |
|
--- a/lib/softoken/pkcs11i.h |
|
+++ b/lib/softoken/pkcs11i.h |
|
@@ -147,16 +147,26 @@ typedef enum { |
|
*/ |
|
typedef enum { |
|
SFTK_DestroyFailure, |
|
SFTK_Destroyed, |
|
SFTK_Busy |
|
} SFTKFreeStatus; |
|
|
|
/* |
|
+ * Source of various objects |
|
+ */ |
|
+typedef enum { |
|
+ SFTK_SOURCE_DEFAULT=0, |
|
+ SFTK_SOURCE_KEA, |
|
+ SFTK_SOURCE_HKDF_EXPAND, |
|
+ SFTK_SOURCE_HKDF_EXTRACT |
|
+} SFTKSource; |
|
+ |
|
+/* |
|
* attribute values of an object. |
|
*/ |
|
struct SFTKAttributeStr { |
|
SFTKAttribute *next; |
|
SFTKAttribute *prev; |
|
PRBool freeAttr; |
|
PRBool freeData; |
|
/*must be called handle to make sftkqueue_find work */ |
|
@@ -189,16 +199,17 @@ struct SFTKObjectStr { |
|
CK_OBJECT_CLASS objclass; |
|
CK_OBJECT_HANDLE handle; |
|
int refCount; |
|
PZLock *refLock; |
|
SFTKSlot *slot; |
|
void *objectInfo; |
|
SFTKFree infoFree; |
|
PRBool isFIPS; |
|
+ SFTKSource source; |
|
}; |
|
|
|
struct SFTKTokenObjectStr { |
|
SFTKObject obj; |
|
SECItem dbKey; |
|
}; |
|
|
|
struct SFTKSessionObjectStr { |
|
diff --git a/lib/softoken/pkcs11u.c b/lib/softoken/pkcs11u.c |
|
--- a/lib/softoken/pkcs11u.c |
|
+++ b/lib/softoken/pkcs11u.c |
|
@@ -1090,16 +1090,17 @@ sftk_NewObject(SFTKSlot *slot) |
|
sessObject->attrList[i].freeData = PR_FALSE; |
|
} |
|
sessObject->optimizeSpace = slot->optimizeSpace; |
|
|
|
object->handle = 0; |
|
object->next = object->prev = NULL; |
|
object->slot = slot; |
|
object->isFIPS = sftk_isFIPS(slot->slotID); |
|
+ object->source = SFTK_SOURCE_DEFAULT; |
|
|
|
object->refCount = 1; |
|
sessObject->sessionList.next = NULL; |
|
sessObject->sessionList.prev = NULL; |
|
sessObject->sessionList.parent = object; |
|
sessObject->session = NULL; |
|
sessObject->wasDerived = PR_FALSE; |
|
if (!hasLocks) |
|
@@ -1674,16 +1675,17 @@ fail: |
|
CK_RV |
|
sftk_CopyObject(SFTKObject *destObject, SFTKObject *srcObject) |
|
{ |
|
SFTKAttribute *attribute; |
|
SFTKSessionObject *src_so = sftk_narrowToSessionObject(srcObject); |
|
unsigned int i; |
|
|
|
destObject->isFIPS = srcObject->isFIPS; |
|
+ destObject->source = srcObject->source; |
|
if (src_so == NULL) { |
|
return sftk_CopyTokenObject(destObject, srcObject); |
|
} |
|
|
|
PZ_Lock(src_so->attributeLock); |
|
for (i = 0; i < src_so->hashSize; i++) { |
|
attribute = src_so->head[i]; |
|
do { |
|
@@ -2059,16 +2061,17 @@ sftk_NewTokenObject(SFTKSlot *slot, SECI |
|
/* every object must have a class, if we can't get it, the object |
|
* doesn't exist */ |
|
crv = handleToClass(slot, handle, &object->objclass); |
|
if (crv != CKR_OK) { |
|
goto loser; |
|
} |
|
object->slot = slot; |
|
object->isFIPS = sftk_isFIPS(slot->slotID); |
|
+ object->source = SFTK_SOURCE_DEFAULT; |
|
object->objectInfo = NULL; |
|
object->infoFree = NULL; |
|
if (!hasLocks) { |
|
object->refLock = PZ_NewLock(nssILockRefLock); |
|
} |
|
if (object->refLock == NULL) { |
|
goto loser; |
|
} |
|
@@ -2225,16 +2228,25 @@ sftk_AttributeToFlags(CK_ATTRIBUTE_TYPE |
|
break; |
|
case CKA_DERIVE: |
|
flags = CKF_DERIVE; |
|
break; |
|
/* fake attribute to select digesting */ |
|
case CKA_DIGEST: |
|
flags = CKF_DIGEST; |
|
break; |
|
+ /* fake attribute to select key gen */ |
|
+ case CKA_NSS_GENERATE: |
|
+ flags = CKF_GENERATE; |
|
+ break; |
|
+ /* fake attribute to select key pair gen */ |
|
+ case CKA_NSS_GENERATE_KEY_PAIR: |
|
+ flags = CKF_GENERATE_KEY_PAIR; |
|
+ break; |
|
+ /* fake attributes to to handle MESSAGE* flags */ |
|
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; |
|
@@ -2278,17 +2290,17 @@ sftk_quickGetECCCurveOid(SFTKObject *sou |
|
} |
|
|
|
/* 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 |
|
+static CK_ULONG |
|
sftk_getKeyLength(SFTKObject *source) |
|
{ |
|
CK_KEY_TYPE keyType = CK_INVALID_HANDLE; |
|
CK_ATTRIBUTE_TYPE keyAttribute; |
|
CK_ULONG keyLength = 0; |
|
SFTKAttribute *attribute; |
|
CK_RV crv; |
|
|
|
diff --git a/lib/util/pkcs11n.h b/lib/util/pkcs11n.h |
|
--- a/lib/util/pkcs11n.h |
|
+++ b/lib/util/pkcs11n.h |
|
@@ -58,16 +58,18 @@ |
|
/* |
|
* NSS-defined certificate types |
|
* |
|
*/ |
|
#define CKC_NSS (CKC_VENDOR_DEFINED | NSSCK_VENDOR_NSS) |
|
|
|
/* FAKE PKCS #11 defines */ |
|
#define CKA_DIGEST 0x81000000L |
|
+#define CKA_NSS_GENERATE 0x81000001L |
|
+#define CKA_NSS_GENERATE_KEY_PAIR 0x81000002L |
|
#define CKA_NSS_MESSAGE 0x82000000L |
|
#define CKA_NSS_MESSAGE_MASK 0xff000000L |
|
#define CKA_FLAGS_ONLY 0 /* CKA_CLASS */ |
|
|
|
/* |
|
* NSS-defined object attributes |
|
* |
|
*/
|
|
|