Blame SOURCES/nss-softokn-3.16-fips.patch

6fbbf4
diff -up ./nss/lib/freebl/ctr.c.fips ./nss/lib/freebl/ctr.c
6fbbf4
--- ./nss/lib/freebl/ctr.c.fips	2014-06-24 13:45:27.000000000 -0700
6fbbf4
+++ ./nss/lib/freebl/ctr.c	2014-09-22 11:03:48.410869823 -0700
6fbbf4
@@ -30,6 +30,7 @@ CTR_InitContext(CTRContext *ctr, void *c
6fbbf4
     }
6fbbf4
 
6fbbf4
     /* Invariant: 0 < ctr->bufPtr <= blocksize */
6fbbf4
+    ctr->checkWrap = PR_FALSE;
6fbbf4
     ctr->bufPtr = blocksize; /* no unused data in the buffer */
6fbbf4
     ctr->cipher = cipher;
6fbbf4
     ctr->context = context;
6fbbf4
@@ -40,6 +41,10 @@ CTR_InitContext(CTRContext *ctr, void *c
6fbbf4
 	return SECFailure;
6fbbf4
     }
6fbbf4
     PORT_Memcpy(ctr->counter, ctrParams->cb, blocksize);
6fbbf4
+    if (ctr->counterBits < 64) {
6fbbf4
+	PORT_Memcpy(ctr->counterFirst, ctr->counter, blocksize);
6fbbf4
+	ctr->checkWrap = PR_TRUE;
6fbbf4
+    }
6fbbf4
     return SECSuccess;
6fbbf4
 }
6fbbf4
 
6fbbf4
@@ -147,6 +152,12 @@ CTR_Update(CTRContext *ctr, unsigned cha
6fbbf4
 	rv = (*ctr->cipher)(ctr->context, ctr->buffer, &tmp, blocksize,
6fbbf4
 			ctr->counter, blocksize, blocksize);
6fbbf4
 	ctr_GetNextCtr(ctr->counter, ctr->counterBits, blocksize);
6fbbf4
+	if (ctr->checkWrap) {
6fbbf4
+	    if (PORT_Memcmp(ctr->counter, ctr->counterFirst, blocksize) == 0) {
6fbbf4
+		PORT_SetError(SEC_ERROR_INVALID_ARGS);
6fbbf4
+		return SECFailure;
6fbbf4
+	    }
6fbbf4
+	}
6fbbf4
 	if (rv != SECSuccess) {
6fbbf4
 	    return SECFailure;
6fbbf4
 	}
6fbbf4
@@ -162,6 +173,12 @@ CTR_Update(CTRContext *ctr, unsigned cha
6fbbf4
     rv = (*ctr->cipher)(ctr->context, ctr->buffer, &tmp, blocksize,
6fbbf4
 			ctr->counter, blocksize, blocksize);
6fbbf4
     ctr_GetNextCtr(ctr->counter, ctr->counterBits, blocksize);
6fbbf4
+    if (ctr->checkWrap) {
6fbbf4
+	if (PORT_Memcmp(ctr->counter, ctr->counterFirst, blocksize) == 0) {
6fbbf4
+	    PORT_SetError(SEC_ERROR_INVALID_ARGS);
6fbbf4
+	    return SECFailure;
6fbbf4
+	}
6fbbf4
+    }
6fbbf4
     if (rv != SECSuccess) {
6fbbf4
 	return SECFailure;
6fbbf4
     }
6fbbf4
diff -up ./nss/lib/freebl/ctr.h.fips ./nss/lib/freebl/ctr.h
6fbbf4
--- ./nss/lib/freebl/ctr.h.fips	2014-06-24 13:45:27.000000000 -0700
6fbbf4
+++ ./nss/lib/freebl/ctr.h	2014-09-22 11:03:48.411869840 -0700
6fbbf4
@@ -14,6 +14,8 @@ struct CTRContextStr {
6fbbf4
    void *context;
6fbbf4
    unsigned char counter[MAX_BLOCK_SIZE];
6fbbf4
    unsigned char buffer[MAX_BLOCK_SIZE];
6fbbf4
+   unsigned char counterFirst[MAX_BLOCK_SIZE];  /* counter overlfow value */
6fbbf4
+   PRBool checkWrap;				/*check for counter overflow*/
6fbbf4
    unsigned long counterBits;
6fbbf4
    unsigned int bufPtr;
6fbbf4
 };
6fbbf4
diff -up ./nss/lib/freebl/cts.c.fips ./nss/lib/freebl/cts.c
6fbbf4
--- ./nss/lib/freebl/cts.c.fips	2014-06-24 13:45:27.000000000 -0700
6fbbf4
+++ ./nss/lib/freebl/cts.c	2014-09-22 11:03:48.411869840 -0700
6fbbf4
@@ -97,6 +97,7 @@ CTS_EncryptUpdate(CTSContext *cts, unsig
6fbbf4
     unsigned int tmp;
6fbbf4
     int fullblocks;
6fbbf4
     int written;
6fbbf4
+    char *saveout = outbuf;
6fbbf4
     SECStatus rv;
6fbbf4
 
6fbbf4
     if (inlen < blocksize) {
6fbbf4
@@ -141,6 +142,8 @@ CTS_EncryptUpdate(CTSContext *cts, unsig
6fbbf4
     PORT_Memset(lastBlock, 0, blocksize);
6fbbf4
     if (rv == SECSuccess) {
6fbbf4
 	*outlen = written + blocksize;
6fbbf4
+    } else {
6fbbf4
+	PORT_Memset(saveout, 0, written+blocksize);
6fbbf4
     }
6fbbf4
     return rv;
6fbbf4
 }
6fbbf4
@@ -184,6 +187,7 @@ CTS_DecryptUpdate(CTSContext *cts, unsig
6fbbf4
     unsigned char Cn[MAX_BLOCK_SIZE];   /* block Cn   */
6fbbf4
     unsigned char lastBlock[MAX_BLOCK_SIZE];
6fbbf4
     const unsigned char *tmp;
6fbbf4
+    char *saveout = outbuf;
6fbbf4
     unsigned int tmpLen;
6fbbf4
     int fullblocks, pad;
6fbbf4
     unsigned int i;
6fbbf4
@@ -281,6 +285,8 @@ CTS_DecryptUpdate(CTSContext *cts, unsig
6fbbf4
     rv = (*cts->cipher)(cts->context, Pn, &tmpLen, blocksize, lastBlock,
6fbbf4
 	 blocksize, blocksize);
6fbbf4
     if (rv != SECSuccess) {
6fbbf4
+	PORT_Memset(lastBlock, 0, blocksize);
6fbbf4
+	PORT_Memset(saveout, 0, *outlen);
6fbbf4
 	return SECFailure;
6fbbf4
     }
6fbbf4
     /* make up for the out of order CBC decryption */
6fbbf4
diff -up ./nss/lib/freebl/dh.c.fips ./nss/lib/freebl/dh.c
6fbbf4
--- ./nss/lib/freebl/dh.c.fips	2014-06-24 13:45:27.000000000 -0700
6fbbf4
+++ ./nss/lib/freebl/dh.c	2014-09-22 11:03:48.412869857 -0700
6fbbf4
@@ -173,8 +173,8 @@ DH_NewKey(DHParams *params, DHPrivateKey
6fbbf4
     /* Generate private key xa */
6fbbf4
     SECITEM_AllocItem(arena, &key->privateValue,
6fbbf4
                       dh_GetSecretKeyLen(params->prime.len));
6fbbf4
-    RNG_GenerateGlobalRandomBytes(key->privateValue.data, 
6fbbf4
-                                  key->privateValue.len);
6fbbf4
+    CHECK_SEC_OK(RNG_GenerateGlobalRandomBytes(key->privateValue.data, 
6fbbf4
+                                  key->privateValue.len));
6fbbf4
     SECITEM_TO_MPINT( key->privateValue, &xa );
6fbbf4
     /* xa < p */
6fbbf4
     CHECK_MPI_OK( mp_mod(&xa, &p, &xa) );
6fbbf4
@@ -191,8 +191,10 @@ cleanup:
6fbbf4
 	MP_TO_SEC_ERROR(err);
6fbbf4
 	rv = SECFailure;
6fbbf4
     }
6fbbf4
-    if (rv)
6fbbf4
+    if (rv) {
6fbbf4
+	*privKey = NULL;
6fbbf4
 	PORT_FreeArena(arena, PR_TRUE);
6fbbf4
+    }
6fbbf4
     return rv;
6fbbf4
 }
6fbbf4
 
6fbbf4
@@ -254,6 +256,10 @@ DH_Derive(SECItem *publicValue,
6fbbf4
     }
6fbbf4
     /* allocate a buffer which can hold the entire derived secret. */
6fbbf4
     secret = PORT_Alloc(len);
6fbbf4
+    if (secret == NULL) {
6fbbf4
+	err = MP_MEM;
6fbbf4
+	goto cleanup;
6fbbf4
+    }
6fbbf4
     /* grab the derived secret */
6fbbf4
     err = mp_to_unsigned_octets(&ZZ, secret, len);
6fbbf4
     if (err >= 0) err = MP_OKAY;
6fbbf4
@@ -267,7 +273,10 @@ DH_Derive(SECItem *publicValue,
6fbbf4
 	nb = outBytes;
6fbbf4
     else
6fbbf4
 	nb = len;
6fbbf4
-    SECITEM_AllocItem(NULL, derivedSecret, nb);
6fbbf4
+    if (SECITEM_AllocItem(NULL, derivedSecret, nb)  == NULL) {
6fbbf4
+	err = MP_MEM;
6fbbf4
+	goto cleanup;
6fbbf4
+    }
6fbbf4
     if (len < nb) {
6fbbf4
 	unsigned int offset = nb - len;
6fbbf4
 	memset(derivedSecret->data, 0, offset);
6fbbf4
@@ -342,11 +351,19 @@ KEA_Derive(SECItem *prime,
6fbbf4
     /* allocate a buffer for the full derived secret */
6fbbf4
     len = mp_unsigned_octet_size(&w);
6fbbf4
     secret = PORT_Alloc(len);
6fbbf4
+    if (secret == NULL) {
6fbbf4
+	err = MP_MEM;
6fbbf4
+	goto cleanup;
6fbbf4
+    }
6fbbf4
     /* grab the secret */
6fbbf4
     err = mp_to_unsigned_octets(&w, secret, len);
6fbbf4
     if (err > 0) err = MP_OKAY;
6fbbf4
     /* allocate output buffer */
6fbbf4
-    SECITEM_AllocItem(NULL, derivedSecret, KEA_DERIVED_SECRET_LEN);
6fbbf4
+    if (SECITEM_AllocItem(NULL, derivedSecret, KEA_DERIVED_SECRET_LEN)
6fbbf4
+								  == NULL) {
6fbbf4
+	err = MP_MEM;
6fbbf4
+	goto cleanup;
6fbbf4
+    }
6fbbf4
     memset(derivedSecret->data, 0, derivedSecret->len);
6fbbf4
     /* copy in the 128 lsb of the secret */
6fbbf4
     if (len >= KEA_DERIVED_SECRET_LEN) {
6fbbf4
@@ -369,6 +386,8 @@ cleanup:
6fbbf4
 	PORT_ZFree(secret, len);
6fbbf4
     if (err) {
6fbbf4
 	MP_TO_SEC_ERROR(err);
6fbbf4
+	if (derivedSecret->data) 
6fbbf4
+	    PORT_ZFree(derivedSecret->data, derivedSecret->len);
6fbbf4
 	return SECFailure;
6fbbf4
     }
6fbbf4
     return SECSuccess;
6fbbf4
diff -up ./nss/lib/freebl/drbg.c.fips ./nss/lib/freebl/drbg.c
6fbbf4
--- ./nss/lib/freebl/drbg.c.fips	2014-06-24 13:45:27.000000000 -0700
6fbbf4
+++ ./nss/lib/freebl/drbg.c	2014-09-22 11:03:48.413869874 -0700
6fbbf4
@@ -76,7 +76,7 @@ struct RNGContextStr {
6fbbf4
 #define  V(rng)       (((rng)->V_Data)+1)
6fbbf4
 #define  VSize(rng)   ((sizeof (rng)->V_Data) -1)
6fbbf4
     PRUint8  C[PRNG_SEEDLEN];        /* internal state variables */
6fbbf4
-    PRUint8  oldV[PRNG_SEEDLEN];     /* for continuous rng checking */
6fbbf4
+    PRUint8  lastOutput[SHA256_LENGTH];     /* for continuous rng checking */
6fbbf4
     /* If we get calls for the PRNG to return less than the length of our
6fbbf4
      * hash, we extend the request for a full hash (since we'll be doing
6fbbf4
      * the full hash anyway). Future requests for random numbers are fulfilled
6fbbf4
@@ -280,6 +280,8 @@ prng_Hashgen(RNGContext *rng, PRUint8 *r
6fbbf4
 	     unsigned int no_of_returned_bytes)
6fbbf4
 {
6fbbf4
     PRUint8 data[VSize(rng)];
6fbbf4
+    PRUint8 thisHash[SHA256_LENGTH];
6fbbf4
+    PRUint8 *lastHash = rng->lastOutput;
6fbbf4
 
6fbbf4
     PORT_Memcpy(data, V(rng), VSize(rng));
6fbbf4
     while (no_of_returned_bytes) {
6fbbf4
@@ -290,14 +292,25 @@ prng_Hashgen(RNGContext *rng, PRUint8 *r
6fbbf4
 
6fbbf4
  	SHA256_Begin(&ctx;;
6fbbf4
  	SHA256_Update(&ctx, data, sizeof data);
6fbbf4
-	SHA256_End(&ctx, returned_bytes, &len, no_of_returned_bytes);
6fbbf4
+	SHA256_End(&ctx, thisHash, &len, SHA256_LENGTH);
6fbbf4
+	if (PORT_Memcmp(lastHash, thisHash, len) == 0) {
6fbbf4
+	    rng->isValid = PR_FALSE;
6fbbf4
+	    break;
6fbbf4
+	}
6fbbf4
+	if (no_of_returned_bytes < SHA256_LENGTH) {
6fbbf4
+	    len = no_of_returned_bytes;
6fbbf4
+	}
6fbbf4
+	PORT_Memcpy(returned_bytes, thisHash, len);
6fbbf4
+	lastHash = returned_bytes;
6fbbf4
 	returned_bytes += len;
6fbbf4
 	no_of_returned_bytes -= len;
6fbbf4
 	/* The carry parameter is a bool (increment or not). 
6fbbf4
 	 * This increments data if no_of_returned_bytes is not zero */
6fbbf4
 	PRNG_ADD_CARRY_ONLY(data, (sizeof data)- 1, no_of_returned_bytes);
6fbbf4
     }
6fbbf4
+    PORT_Memcpy(rng->lastOutput, thisHash, SHA256_LENGTH);
6fbbf4
     PORT_Memset(data, 0, sizeof data); 
6fbbf4
+    PORT_Memset(thisHash, 0, sizeof thisHash); 
6fbbf4
 }
6fbbf4
 
6fbbf4
 /* 
6fbbf4
@@ -342,8 +355,13 @@ prng_generateNewBytes(RNGContext *rng,
6fbbf4
     }
6fbbf4
 
6fbbf4
     if (no_of_returned_bytes == SHA256_LENGTH) {
6fbbf4
-	/* short_cut to hashbuf and save a copy and a clear */
6fbbf4
+	/* short_cut to hashbuf and a couple of copies and clears */
6fbbf4
 	SHA256_HashBuf(returned_bytes, V(rng), VSize(rng) );
6fbbf4
+	/* continuous rng check */
6fbbf4
+	if (memcmp(rng->lastOutput, returned_bytes, SHA256_LENGTH) == 0) {
6fbbf4
+	    rng->isValid = PR_FALSE;
6fbbf4
+	}
6fbbf4
+	PORT_Memcpy(rng->lastOutput, returned_bytes, sizeof rng->lastOutput);
6fbbf4
     } else {
6fbbf4
     	prng_Hashgen(rng, returned_bytes, no_of_returned_bytes);
6fbbf4
     }
6fbbf4
@@ -356,13 +374,12 @@ prng_generateNewBytes(RNGContext *rng,
6fbbf4
 					sizeof rng->reseed_counter)
6fbbf4
     PRNG_ADD_CARRY_ONLY(rng->reseed_counter,(sizeof rng->reseed_counter)-1, 1);
6fbbf4
 
6fbbf4
-    /* continuous rng check */
6fbbf4
-    if (memcmp(V(rng), rng->oldV, sizeof rng->oldV) == 0) {
6fbbf4
-	rng->isValid = PR_FALSE;
6fbbf4
+    /* if the prng failed, don't return any output, signal softoken */
6fbbf4
+    if (!rng->isValid) {
6fbbf4
+	PORT_Memset(returned_bytes, 0,  no_of_returned_bytes);
6fbbf4
 	PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
6fbbf4
 	return SECFailure;
6fbbf4
     }
6fbbf4
-    PORT_Memcpy(rng->oldV, V(rng), sizeof rng->oldV);
6fbbf4
     return SECSuccess;
6fbbf4
 }
6fbbf4
 
6fbbf4
diff -up ./nss/lib/freebl/ec.c.fips ./nss/lib/freebl/ec.c
6fbbf4
--- ./nss/lib/freebl/ec.c.fips	2014-06-24 13:45:27.000000000 -0700
6fbbf4
+++ ./nss/lib/freebl/ec.c	2014-09-22 11:03:48.413869874 -0700
6fbbf4
@@ -376,7 +376,7 @@ cleanup:
6fbbf4
 	rv = SECFailure;
6fbbf4
     }
6fbbf4
     if (rv != SECSuccess && privKeyBytes) {
6fbbf4
-	PORT_Free(privKeyBytes);
6fbbf4
+	PORT_ZFree(privKeyBytes,2*len);
6fbbf4
 	privKeyBytes = NULL;
6fbbf4
     }
6fbbf4
     return privKeyBytes;
6fbbf4
@@ -1061,7 +1061,7 @@ cleanup:
6fbbf4
     mp_clear(&v);
6fbbf4
     mp_clear(&n);
6fbbf4
 
6fbbf4
-    if (pointC.data) SECITEM_FreeItem(&pointC, PR_FALSE);
6fbbf4
+    if (pointC.data) SECITEM_ZfreeItem(&pointC, PR_FALSE);
6fbbf4
     if (err) {
6fbbf4
 	MP_TO_SEC_ERROR(err);
6fbbf4
 	rv = SECFailure;
6fbbf4
diff -up ./nss/lib/freebl/gcm.c.fips ./nss/lib/freebl/gcm.c
6fbbf4
--- ./nss/lib/freebl/gcm.c.fips	2014-06-24 13:45:27.000000000 -0700
6fbbf4
+++ ./nss/lib/freebl/gcm.c	2014-09-22 11:03:48.414869890 -0700
6fbbf4
@@ -192,9 +192,7 @@ gcmHash_DestroyContext(gcmHashContext *g
6fbbf4
     mp_clear(&ghash->H);
6fbbf4
     mp_clear(&ghash->X);
6fbbf4
     mp_clear(&ghash->C_i);
6fbbf4
-    MP_DIGITS(&ghash->H) = 0;
6fbbf4
-    MP_DIGITS(&ghash->X) = 0;
6fbbf4
-    MP_DIGITS(&ghash->C_i) = 0;
6fbbf4
+    PORT_Memset(ghash, 0, sizeof(gcmHashContext));
6fbbf4
     if (freeit) {
6fbbf4
 	PORT_Free(ghash);
6fbbf4
     }
6fbbf4
@@ -267,6 +265,7 @@ gcm_HashMult(gcmHashContext *ghash, cons
6fbbf4
     }
6fbbf4
     rv = SECSuccess;
6fbbf4
 cleanup:
6fbbf4
+    PORT_Memset(tmp_buf, 0, sizeof(tmp_buf));
6fbbf4
     if (rv != SECSuccess) {
6fbbf4
 	MP_TO_SEC_ERROR(err);
6fbbf4
     }
6fbbf4
@@ -366,6 +365,7 @@ cleanup:
6fbbf4
 static void
6fbbf4
 gcmHash_DestroyContext(gcmHashContext *ghash, PRBool freeit)
6fbbf4
 {
6fbbf4
+    PORT_Memset(ghash, 0, sizeof(gcmHashContext));
6fbbf4
     if (freeit) {
6fbbf4
 	PORT_Free(ghash);
6fbbf4
     }
6fbbf4
@@ -423,6 +423,7 @@ gcm_HashMult(gcmHashContext *ghash, cons
6fbbf4
 	}
6fbbf4
 	GCM_TRACE_X(ghash, "X%d = ")
6fbbf4
     }
6fbbf4
+    PORT_Memset(C_i, 0, sizeof(C_i));
6fbbf4
     return SECSuccess;
6fbbf4
 }
6fbbf4
 
6fbbf4
@@ -538,26 +539,30 @@ gcmHash_Final(gcmHashContext *ghash, uns
6fbbf4
 
6fbbf4
     rv = gcmHash_Sync(ghash, blocksize);
6fbbf4
     if (rv != SECSuccess) {
6fbbf4
-	return SECFailure;
6fbbf4
+	goto cleanup;
6fbbf4
     }
6fbbf4
 
6fbbf4
     rv = gcm_HashMult(ghash, ghash->counterBuf, (GCM_HASH_LEN_LEN*2)/blocksize,
6fbbf4
 								blocksize);
6fbbf4
     if (rv != SECSuccess) {
6fbbf4
-	return SECFailure;
6fbbf4
+	goto cleanup;
6fbbf4
     }
6fbbf4
 
6fbbf4
     GCM_TRACE_X(ghash, "GHASH(H,A,C) = ")
6fbbf4
 
6fbbf4
     rv = gcm_getX(ghash, T, blocksize);
6fbbf4
     if (rv != SECSuccess) {
6fbbf4
-	return SECFailure;
6fbbf4
+	goto cleanup;
6fbbf4
     }
6fbbf4
 
6fbbf4
     if (maxout > blocksize) maxout = blocksize;
6fbbf4
     PORT_Memcpy(outbuf, T, maxout);
6fbbf4
     *outlen = maxout;
6fbbf4
-    return SECSuccess;
6fbbf4
+    rv = SECSuccess;
6fbbf4
+
6fbbf4
+cleanup:
6fbbf4
+    PORT_Memset(T, 0, sizeof(T));
6fbbf4
+    return rv;
6fbbf4
 }
6fbbf4
 
6fbbf4
 SECStatus
6fbbf4
@@ -695,6 +700,8 @@ GCM_DestroyContext(GCMContext *gcm, PRBo
6fbbf4
      * allocated data (like mp_int's) */
6fbbf4
     CTR_DestroyContext(&gcm->ctr_context, PR_FALSE);
6fbbf4
     gcmHash_DestroyContext(&gcm->ghash_context, PR_FALSE);
6fbbf4
+    PORT_Memset(&gcm->tagBits, 0, sizeof(gcm->tagBits));
6fbbf4
+    PORT_Memset(gcm->tagKey, 0, sizeof(gcm->tagKey));
6fbbf4
     if (freeit) {
6fbbf4
 	PORT_Free(gcm);
6fbbf4
     }
6fbbf4
@@ -838,8 +845,10 @@ GCM_DecryptUpdate(GCMContext *gcm, unsig
6fbbf4
     if (NSS_SecureMemcmp(tag, intag, tagBytes) != 0) {
6fbbf4
 	/* force a CKR_ENCRYPTED_DATA_INVALID error at in softoken */
6fbbf4
 	PORT_SetError(SEC_ERROR_BAD_DATA);
6fbbf4
+	PORT_Memset(tag, 0, sizeof(tag));
6fbbf4
 	return SECFailure;
6fbbf4
     }
6fbbf4
+    PORT_Memset(tag, 0, sizeof(tag));
6fbbf4
     /* finish the decryption */
6fbbf4
     return CTR_Update(&gcm->ctr_context, outbuf, outlen, maxout,
6fbbf4
 			  inbuf, inlen, blocksize);
6fbbf4
diff -up ./nss/lib/freebl/pqg.c.fips ./nss/lib/freebl/pqg.c
6fbbf4
--- ./nss/lib/freebl/pqg.c.fips	2014-06-24 13:45:27.000000000 -0700
6fbbf4
+++ ./nss/lib/freebl/pqg.c	2014-09-22 11:03:48.414869890 -0700
6fbbf4
@@ -701,6 +701,7 @@ cleanup:
6fbbf4
     mp_clear(&a);
6fbbf4
     mp_clear(&z);
6fbbf4
     mp_clear(&two_length_minus_1);
6fbbf4
+    PORT_Memset(x, 0, sizeof(x));
6fbbf4
     if (err) {
6fbbf4
 	MP_TO_SEC_ERROR(err);
6fbbf4
 	rv = SECFailure;
6fbbf4
@@ -856,6 +857,7 @@ cleanup:
6fbbf4
     mp_clear(&c);
6fbbf4
     mp_clear(&c0;;
6fbbf4
     mp_clear(&one);
6fbbf4
+    PORT_Memset(x, 0, sizeof(x));
6fbbf4
     if (err) {
6fbbf4
 	MP_TO_SEC_ERROR(err);
6fbbf4
 	rv = SECFailure;
6fbbf4
diff -up ./nss/lib/freebl/rijndael.c.fips ./nss/lib/freebl/rijndael.c
6fbbf4
--- ./nss/lib/freebl/rijndael.c.fips	2014-06-24 13:45:27.000000000 -0700
6fbbf4
+++ ./nss/lib/freebl/rijndael.c	2014-09-22 11:03:48.415869907 -0700
6fbbf4
@@ -1164,6 +1164,7 @@ AES_InitContext(AESContext *cx, const un
6fbbf4
 	AES_DestroyContext(cx, PR_FALSE);
6fbbf4
 	return rv;
6fbbf4
     }
6fbbf4
+    cx->mode = mode;
6fbbf4
 
6fbbf4
     /* finally, set up any mode specific contexts */
6fbbf4
     switch (mode) {
6fbbf4
@@ -1287,6 +1288,23 @@ AES_Encrypt(AESContext *cx, unsigned cha
6fbbf4
 	return SECFailure;
6fbbf4
     }
6fbbf4
     *outputLen = inputLen;
6fbbf4
+#if  UINT_MAX > MP_32BIT_MAX
6fbbf4
+    /*
6fbbf4
+     * we can guarentee that GSM won't overlfow if we limit the input to
6fbbf4
+     * 2^36 bytes. For simplicity, we are limiting it to 2^32 for now.
6fbbf4
+     *
6fbbf4
+     * We do it here to cover both hardware and software GCM operations.
6fbbf4
+     */
6fbbf4
+    PR_STATIC_ASSERT(sizeof(unsigned int) > 4);
6fbbf4
+    if ((cx->mode == NSS_AES_GCM) && (inputLen > MP_32_BIT_MAX)) {
6fbbf4
+	PORT_SetError(SEC_ERROR_OUTPUT_LEN);
6fbbf4
+	return SECFailure;
6fbbf4
+    }
6fbbf4
+#else
6fbbf4
+    /* if we can't pass in a 32_bit number, then no such check needed */
6fbbf4
+    PR_STATIC_ASSERT(sizeof(unsigned int) <= 4);
6fbbf4
+#endif
6fbbf4
+
6fbbf4
     return (*cx->worker)(cx->worker_cx, output, outputLen, maxOutputLen,	
6fbbf4
                              input, inputLen, blocksize);
6fbbf4
 }
6fbbf4
diff -up ./nss/lib/freebl/rijndael.h.fips ./nss/lib/freebl/rijndael.h
6fbbf4
--- ./nss/lib/freebl/rijndael.h.fips	2014-06-24 13:45:27.000000000 -0700
6fbbf4
+++ ./nss/lib/freebl/rijndael.h	2014-09-22 11:03:48.415869907 -0700
6fbbf4
@@ -62,6 +62,7 @@ struct AESContextStr
6fbbf4
     freeblDestroyFunc destroy;
6fbbf4
     void	      *worker_cx;
6fbbf4
     PRBool	      isBlock;
6fbbf4
+    int           mode;
6fbbf4
 };
6fbbf4
 
6fbbf4
 #endif /* _RIJNDAEL_H_ */