File nss-fips-ctr-wrap-check.patch of Package mozilla-nss.6304
commit 0a65b8640b1f93c9f53cccf7e4bfe57e099aedec
Author: Hans Petter Jansson <hpj@cl.no>
Date: Mon Oct 16 03:01:00 2017 +0200
Rebase nss-CC-ctr.patch.
diff --git a/nss/lib/freebl/ctr.c b/nss/lib/freebl/ctr.c
index d5715a5..b7dec51 100644
--- a/nss/lib/freebl/ctr.c
+++ b/nss/lib/freebl/ctr.c
@@ -83,30 +83,44 @@ CTR_DestroyContext(CTRContext *ctr, PRBool freeit)
* are part of the counter. The counter block is blocksize long. It's a
* big endian value.
*
- * XXX Does not handle counter rollover.
+ * Returns SECFailure when rollover of the counter happens, SECSuccess
+ * otherwise.
*/
-static void
+static SECStatus
ctr_GetNextCtr(unsigned char *counter, unsigned int counterBits,
unsigned int blocksize)
{
unsigned char *counterPtr = counter + blocksize - 1;
unsigned char mask, count;
+ SECStatus rv = SECSuccess;
PORT_Assert(counterBits <= blocksize * PR_BITS_PER_BYTE);
while (counterBits >= PR_BITS_PER_BYTE) {
if (++(*(counterPtr--))) {
- return;
+ goto check_rv;
}
counterBits -= PR_BITS_PER_BYTE;
}
if (counterBits == 0) {
- return;
+ /* If we got here, it means that the last char processed overflowed
+ * while containing exactly the last PR_BITS_PER_BYTE bits of the
+ * counter. That in turn means that the counter as a whole overflowed
+ * and we are thus in error mode */
+ rv = SECFailure;
+ goto check_rv;
}
/* increment the final partial byte */
mask = (1 << counterBits) - 1;
count = ++(*counterPtr) & mask;
+ if (count == 0) {
+ /* the last counter bits overflowed */
+ rv = SECFailure;
+ goto check_rv;
+ }
+
*counterPtr = ((*counterPtr) & ~mask) | count;
- return;
+check_rv:
+ return rv;
}
static void
@@ -151,7 +165,10 @@ CTR_Update(CTRContext *ctr, unsigned char *outbuf,
while (inlen >= blocksize) {
rv = (*ctr->cipher)(ctr->context, ctr->buffer, &tmp, blocksize,
ctr->counter, blocksize, blocksize);
- ctr_GetNextCtr(ctr->counter, ctr->counterBits, blocksize);
+ if (rv != SECSuccess) {
+ return SECFailure;
+ }
+ rv = ctr_GetNextCtr(ctr->counter, ctr->counterBits, blocksize);
if (ctr->checkWrap) {
if (PORT_Memcmp(ctr->counter, ctr->counterFirst, blocksize) == 0) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
@@ -172,7 +189,13 @@ CTR_Update(CTRContext *ctr, unsigned char *outbuf,
}
rv = (*ctr->cipher)(ctr->context, ctr->buffer, &tmp, blocksize,
ctr->counter, blocksize, blocksize);
- ctr_GetNextCtr(ctr->counter, ctr->counterBits, blocksize);
+ if (rv != SECSuccess) {
+ return SECFailure;
+ }
+ rv = ctr_GetNextCtr(ctr->counter, ctr->counterBits, blocksize);
+ if (rv != SECSuccess) {
+ return SECFailure;
+ }
if (ctr->checkWrap) {
if (PORT_Memcmp(ctr->counter, ctr->counterFirst, blocksize) == 0) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
@@ -234,7 +257,10 @@ CTR_Update_HW_AES(CTRContext *ctr, unsigned char *outbuf,
}
rv = (*ctr->cipher)(ctr->context, ctr->buffer, &tmp, blocksize,
ctr->counter, blocksize, blocksize);
- ctr_GetNextCtr(ctr->counter, ctr->counterBits, blocksize);
+ if (rv != SECSuccess) {
+ return SECFailure;
+ }
+ rv = ctr_GetNextCtr(ctr->counter, ctr->counterBits, blocksize);
if (rv != SECSuccess) {
return SECFailure;
}