File nss-fips-approved-crypto-non-ec.patch of Package mozilla-nss.14856

diff --git a/nss/lib/freebl/alg2268.c b/nss/lib/freebl/alg2268.c
index 54c6f4d..8200bc9 100644
--- a/nss/lib/freebl/alg2268.c
+++ b/nss/lib/freebl/alg2268.c
@@ -16,6 +16,8 @@
 #include <stddef.h> /* for ptrdiff_t */
 #endif
 
+#include "fips.h"
+
 /*
 ** RC2 symmetric block cypher
 */
@@ -119,6 +121,7 @@ static const PRUint8 S[256] = {
 RC2Context *
 RC2_AllocateContext(void)
 {
+    IN_FIPS_RETURN(NULL);
     return PORT_ZNew(RC2Context);
 }
 SECStatus
@@ -133,6 +136,8 @@ RC2_InitContext(RC2Context *cx, const unsigned char *key, unsigned int len,
 #endif
     PRUint8 tmpB;
 
+    IN_FIPS_RETURN(SECFailure);
+
     if (!key || !cx || !len || len > (sizeof cx->B) ||
         efLen8 > (sizeof cx->B)) {
         PORT_SetError(SEC_ERROR_INVALID_ARGS);
@@ -204,7 +209,11 @@ RC2Context *
 RC2_CreateContext(const unsigned char *key, unsigned int len,
                   const unsigned char *iv, int mode, unsigned efLen8)
 {
-    RC2Context *cx = PORT_ZNew(RC2Context);
+    RC2Context *cx;
+
+    IN_FIPS_RETURN(NULL);
+
+    cx = PORT_ZNew(RC2Context);
     if (cx) {
         SECStatus rv = RC2_InitContext(cx, key, len, iv, mode, efLen8, 0);
         if (rv != SECSuccess) {
@@ -456,7 +465,11 @@ RC2_Encrypt(RC2Context *cx, unsigned char *output,
             unsigned int *outputLen, unsigned int maxOutputLen,
             const unsigned char *input, unsigned int inputLen)
 {
-    SECStatus rv = SECSuccess;
+    SECStatus rv;
+
+    IN_FIPS_RETURN(SECFailure);
+
+    rv = SECSuccess;
     if (inputLen) {
         if (inputLen % RC2_BLOCK_SIZE) {
             PORT_SetError(SEC_ERROR_INPUT_LEN);
@@ -490,7 +503,11 @@ RC2_Decrypt(RC2Context *cx, unsigned char *output,
             unsigned int *outputLen, unsigned int maxOutputLen,
             const unsigned char *input, unsigned int inputLen)
 {
-    SECStatus rv = SECSuccess;
+    SECStatus rv;
+
+    IN_FIPS_RETURN(SECFailure);
+
+    rv = SECSuccess;
     if (inputLen) {
         if (inputLen % RC2_BLOCK_SIZE) {
             PORT_SetError(SEC_ERROR_INPUT_LEN);
diff --git a/nss/lib/freebl/arcfour.c b/nss/lib/freebl/arcfour.c
index e37b458..5d4a8b2 100644
--- a/nss/lib/freebl/arcfour.c
+++ b/nss/lib/freebl/arcfour.c
@@ -13,6 +13,7 @@
 
 #include "prtypes.h"
 #include "blapi.h"
+#include "fips.h"
 
 /* Architecture-dependent defines */
 
@@ -108,6 +109,7 @@ static const Stype Kinit[256] = {
 RC4Context *
 RC4_AllocateContext(void)
 {
+    IN_FIPS_RETURN(NULL);
     return PORT_ZNew(RC4Context);
 }
 
@@ -121,6 +123,8 @@ RC4_InitContext(RC4Context *cx, const unsigned char *key, unsigned int len,
     PRUint8 K[256];
     PRUint8 *L;
 
+    IN_FIPS_RETURN(SECFailure);
+
     /* verify the key length. */
     PORT_Assert(len > 0 && len < ARCFOUR_STATE_SIZE);
     if (len == 0 || len >= ARCFOUR_STATE_SIZE) {
@@ -162,7 +166,11 @@ RC4_InitContext(RC4Context *cx, const unsigned char *key, unsigned int len,
 RC4Context *
 RC4_CreateContext(const unsigned char *key, int len)
 {
-    RC4Context *cx = RC4_AllocateContext();
+    RC4Context *cx;
+
+    IN_FIPS_RETURN(NULL);
+
+    cx = RC4_AllocateContext();
     if (cx) {
         SECStatus rv = RC4_InitContext(cx, key, len, NULL, 0, 0, 0);
         if (rv != SECSuccess) {
@@ -176,6 +184,7 @@ RC4_CreateContext(const unsigned char *key, int len)
 void
 RC4_DestroyContext(RC4Context *cx, PRBool freeit)
 {
+    IN_FIPS_RETURN();
     if (freeit)
         PORT_ZFree(cx, sizeof(*cx));
 }
@@ -548,6 +557,8 @@ RC4_Encrypt(RC4Context *cx, unsigned char *output,
             unsigned int *outputLen, unsigned int maxOutputLen,
             const unsigned char *input, unsigned int inputLen)
 {
+    IN_FIPS_RETURN(SECFailure);
+
     PORT_Assert(maxOutputLen >= inputLen);
     if (maxOutputLen < inputLen) {
         PORT_SetError(SEC_ERROR_OUTPUT_LEN);
@@ -571,6 +582,8 @@ RC4_Decrypt(RC4Context *cx, unsigned char *output,
             unsigned int *outputLen, unsigned int maxOutputLen,
             const unsigned char *input, unsigned int inputLen)
 {
+    IN_FIPS_RETURN(SECFailure);
+
     PORT_Assert(maxOutputLen >= inputLen);
     if (maxOutputLen < inputLen) {
         PORT_SetError(SEC_ERROR_OUTPUT_LEN);
diff --git a/nss/lib/freebl/fips.h b/nss/lib/freebl/fips.h
index a4ac7a9..d5f4a0b 100644
--- a/nss/lib/freebl/fips.h
+++ b/nss/lib/freebl/fips.h
@@ -8,8 +8,20 @@
 #ifndef FIPS_H
 #define FIPS_H
 
+#include "hasht.h"
+#include "secerr.h"
+
+#define IN_FIPS_RETURN(rv) \
+    do { \
+	if (FIPS_mode()) { \
+	    PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); \
+	    return rv; \
+	} \
+    } while (0)
+
 int	FIPS_mode(void);
 char*	FIPS_rngDev(void);
+PRBool	FIPS_hashAlgApproved(HASH_HashType hashAlg);
 
 #endif
 
diff --git a/nss/lib/freebl/md2.c b/nss/lib/freebl/md2.c
index cb3d3d8..6b1bea5 100644
--- a/nss/lib/freebl/md2.c
+++ b/nss/lib/freebl/md2.c
@@ -13,6 +13,8 @@
 
 #include "blapi.h"
 
+#include "fips.h"
+
 #define MD2_DIGEST_LEN 16
 #define MD2_BUFSIZE 16
 #define MD2_X_SIZE 48  /* The X array, [CV | INPUT | TMP VARS] */
@@ -66,7 +68,11 @@ SECStatus
 MD2_Hash(unsigned char *dest, const char *src)
 {
     unsigned int len;
-    MD2Context *cx = MD2_NewContext();
+    MD2Context *cx;
+
+    IN_FIPS_RETURN(SECFailure);
+
+    cx = MD2_NewContext();
     if (!cx) {
         PORT_SetError(PR_OUT_OF_MEMORY_ERROR);
         return SECFailure;
@@ -81,7 +87,11 @@ MD2_Hash(unsigned char *dest, const char *src)
 MD2Context *
 MD2_NewContext(void)
 {
-    MD2Context *cx = (MD2Context *)PORT_ZAlloc(sizeof(MD2Context));
+    MD2Context *cx;
+
+    IN_FIPS_RETURN(NULL);
+
+    cx = (MD2Context *)PORT_ZAlloc(sizeof(MD2Context));
     if (cx == NULL) {
         PORT_SetError(PR_OUT_OF_MEMORY_ERROR);
         return NULL;
@@ -99,6 +109,8 @@ MD2_DestroyContext(MD2Context *cx, PRBool freeit)
 void
 MD2_Begin(MD2Context *cx)
 {
+    IN_FIPS_RETURN();
+
     memset(cx, 0, sizeof(*cx));
     cx->unusedBuffer = MD2_BUFSIZE;
 }
@@ -196,6 +208,8 @@ MD2_Update(MD2Context *cx, const unsigned char *input, unsigned int inputLen)
 {
     PRUint32 bytesToConsume;
 
+    IN_FIPS_RETURN();
+
     /* Fill the remaining input buffer. */
     if (cx->unusedBuffer != MD2_BUFSIZE) {
         bytesToConsume = PR_MIN(inputLen, cx->unusedBuffer);
@@ -226,6 +240,9 @@ MD2_End(MD2Context *cx, unsigned char *digest,
         unsigned int *digestLen, unsigned int maxDigestLen)
 {
     PRUint8 padStart;
+
+    IN_FIPS_RETURN();
+
     if (maxDigestLen < MD2_BUFSIZE) {
         PORT_SetError(SEC_ERROR_INVALID_ARGS);
         return;
diff --git a/nss/lib/freebl/md5.c b/nss/lib/freebl/md5.c
index bdd36a6..b3a796b 100644
--- a/nss/lib/freebl/md5.c
+++ b/nss/lib/freebl/md5.c
@@ -15,6 +15,8 @@
 #include "blapi.h"
 #include "blapii.h"
 
+#include "fips.h"
+
 #define MD5_HASH_LEN 16
 #define MD5_BUFFER_SIZE 64
 #define MD5_END_BUFFER (MD5_BUFFER_SIZE - 8)
@@ -195,6 +197,7 @@ struct MD5ContextStr {
 SECStatus
 MD5_Hash(unsigned char *dest, const char *src)
 {
+    IN_FIPS_RETURN(SECFailure);
     return MD5_HashBuf(dest, (const unsigned char *)src, PORT_Strlen(src));
 }
 
@@ -204,6 +207,8 @@ MD5_HashBuf(unsigned char *dest, const unsigned char *src, PRUint32 src_length)
     unsigned int len;
     MD5Context cx;
 
+    IN_FIPS_RETURN(SECFailure);
+
     MD5_Begin(&cx);
     MD5_Update(&cx, src, src_length);
     MD5_End(&cx, dest, &len, MD5_HASH_LEN);
@@ -215,7 +220,11 @@ MD5Context *
 MD5_NewContext(void)
 {
     /* no need to ZAlloc, MD5_Begin will init the context */
-    MD5Context *cx = (MD5Context *)PORT_Alloc(sizeof(MD5Context));
+    MD5Context *cx;
+
+    IN_FIPS_RETURN(NULL);
+
+    cx = (MD5Context *)PORT_Alloc(sizeof(MD5Context));
     if (cx == NULL) {
         PORT_SetError(PR_OUT_OF_MEMORY_ERROR);
         return NULL;
@@ -226,7 +235,8 @@ MD5_NewContext(void)
 void
 MD5_DestroyContext(MD5Context *cx, PRBool freeit)
 {
-    memset(cx, 0, sizeof *cx);
+    if (cx)
+        memset(cx, 0, sizeof *cx);
     if (freeit) {
         PORT_Free(cx);
     }
@@ -235,6 +245,8 @@ MD5_DestroyContext(MD5Context *cx, PRBool freeit)
 void
 MD5_Begin(MD5Context *cx)
 {
+    IN_FIPS_RETURN();
+
     cx->lsbInput = 0;
     cx->msbInput = 0;
     /*  memset(cx->inBuf, 0, sizeof(cx->inBuf)); */
@@ -425,6 +437,8 @@ MD5_Update(MD5Context *cx, const unsigned char *input, unsigned int inputLen)
     PRUint32 inBufIndex = cx->lsbInput & 63;
     const PRUint32 *wBuf;
 
+    IN_FIPS_RETURN();
+
     /* Add the number of input bytes to the 64-bit input counter. */
     addto64(cx->msbInput, cx->lsbInput, inputLen);
     if (inBufIndex) {
@@ -498,6 +512,8 @@ MD5_End(MD5Context *cx, unsigned char *digest,
     PRUint32 lowInput, highInput;
     PRUint32 inBufIndex = cx->lsbInput & 63;
 
+    IN_FIPS_RETURN();
+
     if (maxDigestLen < MD5_HASH_LEN) {
         PORT_SetError(SEC_ERROR_INVALID_ARGS);
         return;
@@ -546,6 +562,8 @@ MD5_EndRaw(MD5Context *cx, unsigned char *digest,
 #endif
     PRUint32 cv[4];
 
+    IN_FIPS_RETURN();
+
     if (maxDigestLen < MD5_HASH_LEN) {
         PORT_SetError(SEC_ERROR_INVALID_ARGS);
         return;
diff --git a/nss/lib/freebl/nsslowhash.c b/nss/lib/freebl/nsslowhash.c
index 22f9781..69a2c1a 100644
--- a/nss/lib/freebl/nsslowhash.c
+++ b/nss/lib/freebl/nsslowhash.c
@@ -12,6 +12,7 @@
 #include "plhash.h"
 #include "nsslowhash.h"
 #include "blapii.h"
+#include "fips.h"
 
 struct NSSLOWInitContextStr {
     int count;
@@ -92,6 +93,12 @@ NSSLOWHASH_NewContext(NSSLOWInitContext *initContext,
 {
     NSSLOWHASHContext *context;
 
+    /* return with an error if unapproved hash is requested in FIPS mode */
+    if (!FIPS_hashAlgApproved(hashType)) {
+	PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
+	return NULL;
+    }
+
     if (post_failed) {
         PORT_SetError(SEC_ERROR_PKCS11_DEVICE_ERROR);
         return NULL;
diff --git a/nss/lib/freebl/rawhash.c b/nss/lib/freebl/rawhash.c
index 551727b..d0e8ee8 100644
--- a/nss/lib/freebl/rawhash.c
+++ b/nss/lib/freebl/rawhash.c
@@ -10,6 +10,7 @@
 #include "hasht.h"
 #include "blapi.h" /* below the line */
 #include "secerr.h"
+#include "fips.h"
 
 static void *
 null_hash_new_context(void)
@@ -146,7 +147,8 @@ const SECHashObject SECRawHashObjects[] = {
 const SECHashObject *
 HASH_GetRawHashObject(HASH_HashType hashType)
 {
-    if (hashType <= HASH_AlgNULL || hashType >= HASH_AlgTOTAL) {
+    if (hashType <= HASH_AlgNULL || hashType >= HASH_AlgTOTAL
+        || (!FIPS_hashAlgApproved(hashType))) {
         PORT_SetError(SEC_ERROR_INVALID_ARGS);
         return NULL;
     }
diff --git a/nss/lib/freebl/seed.c b/nss/lib/freebl/seed.c
index 377bdeb..95a76b8 100644
--- a/nss/lib/freebl/seed.c
+++ b/nss/lib/freebl/seed.c
@@ -17,6 +17,8 @@
 #include "seed.h"
 #include "secerr.h"
 
+#include "fips.h"
+
 static const seed_word SS[4][256] = {
     { 0x2989a1a8, 0x05858184, 0x16c6d2d4, 0x13c3d3d0,
       0x14445054, 0x1d0d111c, 0x2c8ca0ac, 0x25052124,
@@ -301,6 +303,8 @@ SEED_set_key(const unsigned char rawkey[SEED_KEY_LENGTH],
     seed_word K0, K1, K2, K3;
     seed_word t0, t1;
 
+    IN_FIPS_RETURN();
+
     char2word(rawkey, K0);
     char2word(rawkey + 4, K1);
     char2word(rawkey + 8, K2);
@@ -349,6 +353,8 @@ SEED_encrypt(const unsigned char s[SEED_BLOCK_SIZE],
     seed_word L0, L1, R0, R1;
     seed_word t0, t1;
 
+    IN_FIPS_RETURN();
+
     char2word(s, L0);
     char2word(s + 4, L1);
     char2word(s + 8, R0);
@@ -385,6 +391,8 @@ SEED_decrypt(const unsigned char s[SEED_BLOCK_SIZE],
     seed_word L0, L1, R0, R1;
     seed_word t0, t1;
 
+    IN_FIPS_RETURN();
+
     char2word(s, L0);
     char2word(s + 4, L1);
     char2word(s + 8, R0);
@@ -418,6 +426,8 @@ SEED_ecb_encrypt(const unsigned char *in,
                  unsigned char *out,
                  const SEED_KEY_SCHEDULE *ks, int enc)
 {
+    IN_FIPS_RETURN();
+
     if (enc) {
         SEED_encrypt(in, out, ks);
     } else {
@@ -434,6 +444,8 @@ SEED_cbc_encrypt(const unsigned char *in, unsigned char *out,
     unsigned char tmp[SEED_BLOCK_SIZE];
     const unsigned char *iv = ivec;
 
+    IN_FIPS_RETURN();
+
     if (enc) {
         while (len >= SEED_BLOCK_SIZE) {
             for (n = 0; n < SEED_BLOCK_SIZE; ++n) {
@@ -517,6 +529,7 @@ SEED_cbc_encrypt(const unsigned char *in, unsigned char *out,
 SEEDContext *
 SEED_AllocateContext(void)
 {
+    IN_FIPS_RETURN(NULL);
     return PORT_ZNew(SEEDContext);
 }
 
@@ -525,6 +538,8 @@ SEED_InitContext(SEEDContext *cx, const unsigned char *key,
                  unsigned int keylen, const unsigned char *iv,
                  int mode, unsigned int encrypt, unsigned int unused)
 {
+    IN_FIPS_RETURN(SECFailure);
+
     if (!cx) {
         PORT_SetError(SEC_ERROR_INVALID_ARGS);
         return SECFailure;
@@ -556,10 +571,14 @@ SEEDContext *
 SEED_CreateContext(const unsigned char *key, const unsigned char *iv,
                    int mode, PRBool encrypt)
 {
-    SEEDContext *cx = PORT_ZNew(SEEDContext);
-    SECStatus rv = SEED_InitContext(cx, key, SEED_KEY_LENGTH, iv, mode,
-                                    encrypt, 0);
+    SEEDContext *cx;
+    SECStatus rv;
+
+    IN_FIPS_RETURN(NULL);
 
+    cx = PORT_ZNew(SEEDContext);
+    rv = SEED_InitContext(cx, key, SEED_KEY_LENGTH, iv, mode,
+                          encrypt, 0);
     if (rv != SECSuccess) {
         PORT_ZFree(cx, sizeof *cx);
         cx = NULL;
@@ -584,6 +603,8 @@ SEED_Encrypt(SEEDContext *cx, unsigned char *out, unsigned int *outLen,
              unsigned int maxOutLen, const unsigned char *in,
              unsigned int inLen)
 {
+    IN_FIPS_RETURN(SECFailure);
+
     if (!cx) {
         PORT_SetError(SEC_ERROR_INVALID_ARGS);
         return SECFailure;
@@ -624,6 +645,8 @@ SEED_Decrypt(SEEDContext *cx, unsigned char *out, unsigned int *outLen,
              unsigned int maxOutLen, const unsigned char *in,
              unsigned int inLen)
 {
+    IN_FIPS_RETURN(SECFailure);
+
     if (!cx) {
         PORT_SetError(SEC_ERROR_INVALID_ARGS);
         return SECFailure;
diff --git a/nss/lib/softoken/pkcs11c.c b/nss/lib/softoken/pkcs11c.c
index 4b68f7a..bf47acc 100644
--- a/nss/lib/softoken/pkcs11c.c
+++ b/nss/lib/softoken/pkcs11c.c
@@ -6997,7 +6997,7 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession,
             } else {
                 /* now allocate the hash contexts */
                 md5 = MD5_NewContext();
-                if (md5 == NULL) {
+                if (md5 == NULL && !isTLS) {
                     crv = CKR_HOST_MEMORY;
                     break;
                 }
openSUSE Build Service is sponsored by