|
|
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_ */
|