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;
     }
openSUSE Build Service is sponsored by