Browse Source

backports

Frank-Rainer Grahl 7 months ago
parent
commit
ee1d6543a6

+ 35 - 0
mozilla-release/patches/1864385-PARTIAL-11508.patch

@@ -0,0 +1,35 @@
+# HG changeset patch
+# User edgul <edgul@mozilla.com>
+# Date 1705443461 0
+# Node ID ec81a0da67e2cbce802725c02e7ced429126c7af
+# Parent  ac3346be1fb9cf0aada39c49270a565edfb1e6e0
+Bug 1864385 - Block set-cookie from multipart/x-mixed-replace with pref. r=valentin,necko-reviewers a=RyanVM
+
+No pref handling just a removal.
+
+diff --git a/netwerk/streamconv/converters/nsMultiMixedConv.cpp b/netwerk/streamconv/converters/nsMultiMixedConv.cpp
+--- a/netwerk/streamconv/converters/nsMultiMixedConv.cpp
++++ b/netwerk/streamconv/converters/nsMultiMixedConv.cpp
+@@ -1031,22 +1031,17 @@ nsMultiMixedConv::ProcessHeader()
+         return NS_ERROR_CORRUPTED_CONTENT;
+       }
+       break;
+     case HEADER_CONTENT_DISPOSITION:
+       mContentDisposition = mResponseHeaderValue;
+       mContentDisposition.CompressWhitespace();
+       break;
+     case HEADER_SET_COOKIE: {
+-      nsCOMPtr<nsIHttpChannelInternal> httpInternal = do_QueryInterface(mChannel);
+       mResponseHeaderValue.CompressWhitespace();
+-      if (httpInternal) {
+-        DebugOnly<nsresult> rv = httpInternal->SetCookie(mResponseHeaderValue.get());
+-        MOZ_ASSERT(NS_SUCCEEDED(rv));
+-      }
+       break;
+     }
+     case HEADER_RANGE:
+     case HEADER_CONTENT_RANGE: {
+       if (!p.CheckWord("bytes") ||
+           !p.CheckWhite()) {
+         return NS_ERROR_CORRUPTED_CONTENT;
+       }

+ 84 - 0
mozilla-release/patches/1867982-124a1.patch

@@ -0,0 +1,84 @@
+# HG changeset patch
+# User Jens Stutte <jstutte@mozilla.com>
+# Date 1706285430 0
+# Node ID 233014f304aef171ed885462d999df30dce7d497
+# Parent  51f3e018ad5ae830eff13b15f49293d9d8f2e909
+Bug 1867982 - Check if WorkerRunnable::Run runs on top of WorkerThreadPrimaryRunnable::Run in a worker thread. r=dom-worker-reviewers,smaug,asuth
+
+Differential Revision: https://phabricator.services.mozilla.com/D199247
+
+diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp
+--- a/dom/workers/WorkerPrivate.cpp
++++ b/dom/workers/WorkerPrivate.cpp
+@@ -5568,17 +5568,19 @@ WorkerPrivate::ScheduleDeletion(WorkerRa
+   MOZ_ASSERT(mSyncLoopStack.IsEmpty());
+   MOZ_ASSERT(!mPendingEventQueueClearing);
+ 
+   ClearMainEventQueue(aRanOrNot);
+ #ifdef DEBUG
+   if (WorkerRan == aRanOrNot) {
+     nsIThread* currentThread = NS_GetCurrentThread();
+     MOZ_ASSERT(currentThread);
+-    MOZ_ASSERT(!NS_HasPendingEvents(currentThread));
++    // On the worker thread WorkerRunnable will refuse to run if not nested
++    // on top of a WorkerThreadPrimaryRunnable.
++    Unused << NS_WARN_IF(NS_HasPendingEvents(currentThread));
+   }
+ #endif
+ 
+   if (WorkerPrivate* parent = GetParent()) {
+     RefPtr<WorkerFinishedRunnable> runnable =
+       new WorkerFinishedRunnable(parent, this);
+     if (!runnable->Dispatch()) {
+       NS_WARNING("Failed to dispatch runnable!");
+diff --git a/dom/workers/WorkerRunnable.cpp b/dom/workers/WorkerRunnable.cpp
+--- a/dom/workers/WorkerRunnable.cpp
++++ b/dom/workers/WorkerRunnable.cpp
+@@ -7,16 +7,17 @@
+ #include "WorkerRunnable.h"
+ 
+ #include "nsGlobalWindow.h"
+ #include "nsIEventTarget.h"
+ #include "nsIGlobalObject.h"
+ #include "nsIRunnable.h"
+ #include "nsThreadUtils.h"
+ 
++#include "mozilla/CycleCollectedJSContext.h"
+ #include "mozilla/DebugOnly.h"
+ #include "mozilla/ErrorResult.h"
+ #include "mozilla/dom/ScriptSettings.h"
+ #include "mozilla/Telemetry.h"
+ 
+ #include "js/RootingAPI.h"
+ #include "js/Value.h"
+ 
+@@ -223,16 +224,29 @@ NS_INTERFACE_MAP_BEGIN(WorkerRunnable)
+ NS_INTERFACE_MAP_END
+ 
+ NS_IMETHODIMP
+ WorkerRunnable::Run()
+ {
+   bool targetIsWorkerThread = mBehavior == WorkerThreadModifyBusyCount ||
+                               mBehavior == WorkerThreadUnchangedBusyCount;
+ 
++  if (targetIsWorkerThread) {
++    // On a worker thread, a WorkerRunnable should only run when there is an
++    // underlying WorkerThreadPrimaryRunnable active, which means we should
++    // find a CycleCollectedJSContext.
++    if (!CycleCollectedJSContext::Get()) {
++      MOZ_DIAGNOSTIC_ASSERT(false,
++                            "A WorkerRunnable was executed after "
++                            "WorkerThreadPrimaryRunnable ended.");
++
++      return NS_OK;
++    }
++  }
++
+ #ifdef DEBUG
+   MOZ_ASSERT_IF(mCallingCancelWithinRun, targetIsWorkerThread);
+   if (targetIsWorkerThread) {
+     mWorkerPrivate->AssertIsOnWorkerThread();
+   }
+   else {
+     MOZ_ASSERT(mBehavior == ParentThreadUnchangedBusyCount);
+     mWorkerPrivate->AssertIsOnParentThread();

+ 50 - 0
mozilla-release/patches/1878211-11508.patch

@@ -0,0 +1,50 @@
+# HG changeset patch
+# User Eitan Isaacson <eitan@monotonous.org>
+# Date 1707365038 0
+# Node ID 17fcbdf6426663c10da5d0ba21927e71184304c3
+# Parent  c942361d08115de69b941037ce8db87b60b826c5
+Bug 1878211 - Process pairs in coord list in PolyArea. r=dholbert a=pascalc
+
+Differential Revision: https://phabricator.services.mozilla.com/D200695
+
+diff --git a/layout/generic/nsImageMap.cpp b/layout/generic/nsImageMap.cpp
+--- a/layout/generic/nsImageMap.cpp
++++ b/layout/generic/nsImageMap.cpp
+@@ -528,17 +528,17 @@ void PolyArea::Draw(nsIFrame* aFrame, Dr
+       // pixel rows or columns, and to start at pixel boundaries so that one
+       // pixel dashing neatly sits on pixels to give us neat lines. To achieve
+       // that we draw each line segment as a separate path, snapping it to
+       // device pixels if applicable.
+       nsPresContext* pc = aFrame->PresContext();
+       Point p1(pc->CSSPixelsToDevPixels(mCoords[0]),
+                pc->CSSPixelsToDevPixels(mCoords[1]));
+       Point p2, p1snapped, p2snapped;
+-      for (int32_t i = 2; i < mNumCoords; i += 2) {
++      for (int32_t i = 2; i < mNumCoords - 1; i += 2) {
+         p2.x = pc->CSSPixelsToDevPixels(mCoords[i]);
+         p2.y = pc->CSSPixelsToDevPixels(mCoords[i+1]);
+         p1snapped = p1;
+         p2snapped = p2;
+         SnapLineToDevicePixelsForStroking(p1snapped, p2snapped, aDrawTarget,
+                                           aStrokeOptions.mLineWidth);
+         aDrawTarget.StrokeLine(p1snapped, p2snapped, aColor, aStrokeOptions);
+         p1 = p2;
+@@ -555,17 +555,17 @@ void PolyArea::Draw(nsIFrame* aFrame, Dr
+ }
+ 
+ void PolyArea::GetRect(nsIFrame* aFrame, nsRect& aRect)
+ {
+   if (mNumCoords >= 6) {
+     nscoord x1, x2, y1, y2, xtmp, ytmp;
+     x1 = x2 = nsPresContext::CSSPixelsToAppUnits(mCoords[0]);
+     y1 = y2 = nsPresContext::CSSPixelsToAppUnits(mCoords[1]);
+-    for (int32_t i = 2; i < mNumCoords; i += 2) {
++    for (int32_t i = 2; i < mNumCoords - 1; i += 2) {
+       xtmp = nsPresContext::CSSPixelsToAppUnits(mCoords[i]);
+       ytmp = nsPresContext::CSSPixelsToAppUnits(mCoords[i+1]);
+       x1 = x1 < xtmp ? x1 : xtmp;
+       y1 = y1 < ytmp ? y1 : ytmp;
+       x2 = x2 > xtmp ? x2 : xtmp;
+       y2 = y2 > ytmp ? y2 : ytmp;
+     }
+ 

+ 85 - 0
mozilla-release/patches/1881093-11509.patch

@@ -0,0 +1,85 @@
+# HG changeset patch
+# User Ryan VanderMeulen <ryanvm@gmail.com>
+# Date 1708728937 0
+# Node ID abeabe4f7ff257cbedcb40bd08fb00342d64de8d
+# Parent  f80551b70a135306010ad1c639cdc78daaba121a
+Bug 1881093 - Cherry-pick dav1d commit 2b475307. r=chunmin a=diannaS
+
+Differential Revision: https://phabricator.services.mozilla.com/D202247
+
+diff --git a/third_party/dav1d/src/decode.c b/third_party/dav1d/src/decode.c
+--- a/third_party/dav1d/src/decode.c
++++ b/third_party/dav1d/src/decode.c
+@@ -2310,17 +2310,17 @@ static const uint8_t ss_size_mul[4][2] =
+     [DAV1D_PIXEL_LAYOUT_I422] = {  8, 6 },
+     [DAV1D_PIXEL_LAYOUT_I444] = { 12, 8 },
+ };
+ 
+ static void setup_tile(Dav1dTileState *const ts,
+                        const Dav1dFrameContext *const f,
+                        const uint8_t *const data, const size_t sz,
+                        const int tile_row, const int tile_col,
+-                       const int tile_start_off)
++                       const unsigned tile_start_off)
+ {
+     const int col_sb_start = f->frame_hdr->tiling.col_start_sb[tile_col];
+     const int col_sb128_start = col_sb_start >> !f->seq_hdr->sb128;
+     const int col_sb_end = f->frame_hdr->tiling.col_start_sb[tile_col + 1];
+     const int row_sb_start = f->frame_hdr->tiling.row_start_sb[tile_row];
+     const int row_sb_end = f->frame_hdr->tiling.row_start_sb[tile_row + 1];
+     const int sb_shift = f->sb_shift;
+ 
+@@ -2699,25 +2699,26 @@ int dav1d_decode_frame(Dav1dFrameContext
+         }
+         f->a_sz = a_sz;
+     }
+ 
+     const int num_sb128 = f->sb128w * f->sb128h;
+     const uint8_t *const size_mul = ss_size_mul[f->cur.p.layout];
+     const int hbd = !!f->seq_hdr->hbd;
+     if (c->n_fc > 1) {
++        const unsigned sb_step4 = f->sb_step * 4;
+         int tile_idx = 0;
+         for (int tile_row = 0; tile_row < f->frame_hdr->tiling.rows; tile_row++) {
+-            int row_off = f->frame_hdr->tiling.row_start_sb[tile_row] *
+-                          f->sb_step * 4 * f->sb128w * 128;
+-            int b_diff = (f->frame_hdr->tiling.row_start_sb[tile_row + 1] -
+-                          f->frame_hdr->tiling.row_start_sb[tile_row]) * f->sb_step * 4;
++            const unsigned row_off = f->frame_hdr->tiling.row_start_sb[tile_row] *
++                                     sb_step4 * f->sb128w * 128;
++            const unsigned b_diff = (f->frame_hdr->tiling.row_start_sb[tile_row + 1] -
++                                     f->frame_hdr->tiling.row_start_sb[tile_row]) * sb_step4;
+             for (int tile_col = 0; tile_col < f->frame_hdr->tiling.cols; tile_col++) {
+                 f->frame_thread.tile_start_off[tile_idx++] = row_off + b_diff *
+-                    f->frame_hdr->tiling.col_start_sb[tile_col] * f->sb_step * 4;
++                    f->frame_hdr->tiling.col_start_sb[tile_col] * sb_step4;
+             }
+         }
+ 
+         const int cf_sz = (num_sb128 * size_mul[0]) << hbd;
+         if (cf_sz != f->frame_thread.cf_sz) {
+             dav1d_freep_aligned(&f->frame_thread.cf);
+             f->frame_thread.cf =
+                 dav1d_alloc_aligned((size_t)cf_sz * 128 * 128 / 2, 32);
+diff --git a/third_party/dav1d/src/internal.h b/third_party/dav1d/src/internal.h
+--- a/third_party/dav1d/src/internal.h
++++ b/third_party/dav1d/src/internal.h
+@@ -202,17 +202,17 @@ struct Dav1dFrameContext {
+         } *cbi;
+         // indexed using (t->by >> 1) * (f->b4_stride >> 1) + (t->bx >> 1)
+         uint16_t (*pal)[3 /* plane */][8 /* idx */];
+         // iterated over inside tile state
+         uint8_t *pal_idx;
+         coef *cf;
+         int pal_sz, pal_idx_sz, cf_sz;
+         // start offsets per tile
+-        int *tile_start_off;
++        unsigned *tile_start_off;
+     } frame_thread;
+ 
+     // loopfilter
+     struct {
+         uint8_t (*level)[4];
+         Av1Filter *mask;
+         Av1Restoration *lr_mask;
+         int top_pre_cdef_toggle;

+ 1111 - 0
mozilla-release/patches/TOP-1880562-NSS3902-11509.patch

@@ -0,0 +1,1111 @@
+# HG changeset patch
+# User John Schanck <jschanck@mozilla.com>
+# Date 1708970358 0
+# Node ID 41273d890f85927e407a3009f908d0137ebf4baf
+# Parent  efc722ff57f40d3e90876e08701c3afbf72b22d4
+Bug 1880562 - land NSS NSS_3_90_2_RTM UPGRADE_NSS_RELEASE,  a=diannaS
+
+Original Revision: https://phabricator.services.mozilla.com/D202015
+
+Differential Revision: https://phabricator.services.mozilla.com/D202017
+
+diff --git a/security/nss/TAG-INFO b/security/nss/TAG-INFO
+--- a/security/nss/TAG-INFO
++++ b/security/nss/TAG-INFO
+@@ -1,1 +1,1 @@
+-NSS_3_90_1_RTM
+\ No newline at end of file
++NSS_3_90_2_RTM
+\ No newline at end of file
+diff --git a/security/nss/coreconf/coreconf.dep b/security/nss/coreconf/coreconf.dep
+--- a/security/nss/coreconf/coreconf.dep
++++ b/security/nss/coreconf/coreconf.dep
+@@ -5,9 +5,8 @@
+ 
+ /*
+  * A dummy header file that is a dependency for all the object files.
+  * Used to force a full recompilation of NSS in Mozilla's Tinderbox
+  * depend builds.  See comments in rules.mk.
+  */
+ 
+ #error "Do not include this header file."
+-
+diff --git a/security/nss/doc/rst/releases/nss_3_90_2.rst b/security/nss/doc/rst/releases/nss_3_90_2.rst
+new file mode 100644
+--- /dev/null
++++ b/security/nss/doc/rst/releases/nss_3_90_2.rst
+@@ -0,0 +1,56 @@
++.. _mozilla_projects_nss_nss_3_90_2_release_notes:
++
++NSS 3.90.2 release notes
++========================
++
++`Introduction <#introduction>`__
++--------------------------------
++
++.. container::
++
++   Network Security Services (NSS) 3.90.2 was released on *15th February 2024**.
++
++
++`Distribution Information <#distribution_information>`__
++--------------------------------------------------------
++
++.. container::
++
++   The HG tag is NSS_3_90_2_RTM. NSS 3.90.2 requires NSPR 4.35 or newer.
++
++   NSS 3.90.2 source distributions are available on ftp.mozilla.org for secure HTTPS download:
++
++   -  Source tarballs:
++      https://ftp.mozilla.org/pub/mozilla.org/security/nss/releases/NSS_3_90_2_RTM/src/
++
++   Other releases are available :ref:`mozilla_projects_nss_releases`.
++
++.. _changes_in_nss_3.90.2:
++
++`Changes in NSS 3.90.2 <#changes_in_nss_3.90.2>`__
++--------------------------------------------------
++
++.. container::
++
++   - Bug 1780432 - (CVE-2023-5388) Timing attack against RSA decryption in TLS.
++   - Bug 1867408 - add a defensive check for large ssl_DefSend return values.
++
++`Compatibility <#compatibility>`__
++----------------------------------
++
++.. container::
++
++   NSS 3.90.2 shared libraries are backwards-compatible with all older NSS 3.x shared
++   libraries. A program linked with older NSS 3.x shared libraries will work with
++   this new version of the shared libraries without recompiling or
++   relinking. Furthermore, applications that restrict their use of NSS APIs to the
++   functions listed in NSS Public Functions will remain compatible with future
++   versions of the NSS shared libraries.
++
++`Feedback <#feedback>`__
++------------------------
++
++.. container::
++
++   Bugs discovered should be reported by filing a bug report on
++   `bugzilla.mozilla.org <https://bugzilla.mozilla.org/enter_bug.cgi?product=NSS>`__ (product NSS).
+diff --git a/security/nss/lib/freebl/mpi/mpi-priv.h b/security/nss/lib/freebl/mpi/mpi-priv.h
+--- a/security/nss/lib/freebl/mpi/mpi-priv.h
++++ b/security/nss/lib/freebl/mpi/mpi-priv.h
+@@ -199,16 +199,19 @@ void MPI_ASM_DECL s_mpv_mul_d(const mp_d
+ void MPI_ASM_DECL s_mpv_mul_d_add(const mp_digit *a, mp_size a_len,
+                                   mp_digit b, mp_digit *c);
+ 
+ #endif
+ 
+ void MPI_ASM_DECL s_mpv_mul_d_add_prop(const mp_digit *a,
+                                        mp_size a_len, mp_digit b,
+                                        mp_digit *c);
++void MPI_ASM_DECL s_mpv_mul_d_add_propCT(const mp_digit *a,
++                                         mp_size a_len, mp_digit b,
++                                         mp_digit *c, mp_size c_len);
+ void MPI_ASM_DECL s_mpv_sqr_add_prop(const mp_digit *a,
+                                      mp_size a_len,
+                                      mp_digit *sqrs);
+ 
+ mp_err MPI_ASM_DECL s_mpv_div_2dx1d(mp_digit Nhi, mp_digit Nlo,
+                                     mp_digit divisor, mp_digit *quot, mp_digit *rem);
+ 
+ /* c += a * b * (MP_RADIX ** offset);  */
+diff --git a/security/nss/lib/freebl/mpi/mpi.c b/security/nss/lib/freebl/mpi/mpi.c
+--- a/security/nss/lib/freebl/mpi/mpi.c
++++ b/security/nss/lib/freebl/mpi/mpi.c
+@@ -5,16 +5,18 @@
+  *
+  * This Source Code Form is subject to the terms of the Mozilla Public
+  * License, v. 2.0. If a copy of the MPL was not distributed with this
+  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+ 
+ #include "mpi-priv.h"
+ #include "mplogic.h"
+ 
++#include <assert.h>
++
+ #if defined(__arm__) && \
+     ((defined(__thumb__) && !defined(__thumb2__)) || defined(__ARM_ARCH_3__))
+ /* 16-bit thumb or ARM v3 doesn't work inlined assember version */
+ #undef MP_ASSEMBLY_MULTIPLY
+ #undef MP_ASSEMBLY_SQUARE
+ #endif
+ 
+ #if MP_LOGTAB
+@@ -797,25 +799,28 @@ mp_sub(const mp_int *a, const mp_int *b,
+ 
+ CLEANUP:
+     return res;
+ 
+ } /* end mp_sub() */
+ 
+ /* }}} */
+ 
+-/* {{{ mp_mul(a, b, c) */
++/* {{{ s_mp_mulg(a, b, c) */
+ 
+ /*
+-  mp_mul(a, b, c)
+-
+-  Compute c = a * b.  All parameters may be identical.
++  s_mp_mulg(a, b, c)
++
++  Compute c = a * b.  All parameters may be identical. if constantTime is set,
++  then the operations are done in constant time. The original is mostly
++  constant time as long as s_mpv_mul_d_add() is constant time. This is true
++  of the x86 assembler, as well as the current c code.
+  */
+ mp_err
+-mp_mul(const mp_int *a, const mp_int *b, mp_int *c)
++s_mp_mulg(const mp_int *a, const mp_int *b, mp_int *c, int constantTime)
+ {
+     mp_digit *pb;
+     mp_int tmp;
+     mp_err res;
+     mp_size ib;
+     mp_size useda, usedb;
+ 
+     ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
+@@ -841,17 +846,24 @@ mp_mul(const mp_int *a, const mp_int *b,
+     }
+ 
+     MP_USED(c) = 1;
+     MP_DIGIT(c, 0) = 0;
+     if ((res = s_mp_pad(c, USED(a) + USED(b))) != MP_OKAY)
+         goto CLEANUP;
+ 
+ #ifdef NSS_USE_COMBA
+-    if ((MP_USED(a) == MP_USED(b)) && IS_POWER_OF_2(MP_USED(b))) {
++    /* comba isn't constant time because it clamps! If we cared
++     * (we needed a constant time version of multiply that was 'faster'
++     * we could easily pass constantTime down to the comba code and
++     * get it to skip the clamp... but here are assembler versions
++     * which add comba to platforms that can't compile the normal
++     * comba's imbedded assembler which would also need to change, so
++     * for now we just skip comba when we are running constant time. */
++    if (!constantTime && (MP_USED(a) == MP_USED(b)) && IS_POWER_OF_2(MP_USED(b))) {
+         if (MP_USED(a) == 4) {
+             s_mp_mul_comba_4(a, b, c);
+             goto CLEANUP;
+         }
+         if (MP_USED(a) == 8) {
+             s_mp_mul_comba_8(a, b, c);
+             goto CLEANUP;
+         }
+@@ -871,36 +883,82 @@ mp_mul(const mp_int *a, const mp_int *b,
+ 
+     /* Outer loop:  Digits of b */
+     useda = MP_USED(a);
+     usedb = MP_USED(b);
+     for (ib = 1; ib < usedb; ib++) {
+         mp_digit b_i = *pb++;
+ 
+         /* Inner product:  Digits of a */
+-        if (b_i)
++        if (constantTime || b_i)
+             s_mpv_mul_d_add(MP_DIGITS(a), useda, b_i, MP_DIGITS(c) + ib);
+         else
+             MP_DIGIT(c, ib + useda) = b_i;
+     }
+ 
+-    s_mp_clamp(c);
++    if (!constantTime) {
++        s_mp_clamp(c);
++    }
+ 
+     if (SIGN(a) == SIGN(b) || s_mp_cmp_d(c, 0) == MP_EQ)
+         SIGN(c) = ZPOS;
+     else
+         SIGN(c) = NEG;
+ 
+ CLEANUP:
+     mp_clear(&tmp);
+     return res;
++} /* end smp_mulg() */
++
++/* }}} */
++
++/* {{{ mp_mul(a, b, c) */
++
++/*
++  mp_mul(a, b, c)
++
++  Compute c = a * b.  All parameters may be identical.
++ */
++
++mp_err
++mp_mul(const mp_int *a, const mp_int *b, mp_int *c)
++{
++    return s_mp_mulg(a, b, c, 0);
+ } /* end mp_mul() */
+ 
+ /* }}} */
+ 
++/* {{{ mp_mulCT(a, b, c) */
++
++/*
++  mp_mulCT(a, b, c)
++
++  Compute c = a * b. In constant time. Parameters may not be identical.
++  NOTE: a and b may be modified.
++ */
++
++mp_err
++mp_mulCT(mp_int *a, mp_int *b, mp_int *c, mp_size setSize)
++{
++    mp_err res;
++
++    /* make the multiply values fixed length so multiply
++     * doesn't leak the length. at this point all the
++     * values are blinded, but once we finish we want the
++     * output size to be hidden (so no clamping the out put) */
++    MP_CHECKOK(s_mp_pad(a, setSize));
++    MP_CHECKOK(s_mp_pad(b, setSize));
++    MP_CHECKOK(s_mp_pad(c, 2 * setSize));
++    MP_CHECKOK(s_mp_mulg(a, b, c, 1));
++CLEANUP:
++    return res;
++} /* end mp_mulCT() */
++
++/* }}} */
++
+ /* {{{ mp_sqr(a, sqr) */
+ 
+ #if MP_SQUARE
+ /*
+   Computes the square of a.  This can be done more
+   efficiently than a general multiplication, because many of the
+   computation steps are redundant when squaring.  The inner product
+   step is a bit more complicated, but we save a fair number of
+@@ -1263,16 +1321,148 @@ mp_mod(const mp_int *a, const mp_int *m,
+     }
+ 
+     return MP_OKAY;
+ 
+ } /* end mp_mod() */
+ 
+ /* }}} */
+ 
++/* {{{ s_mp_subCT_d(a, b, borrow, c) */
++
++/*
++  s_mp_subCT_d(a, b, borrow, c)
++
++  Compute c = (a -b) - subtract in constant time. returns borrow
++ */
++mp_digit
++s_mp_subCT_d(mp_digit a, mp_digit b, mp_digit borrow, mp_digit *ret)
++{
++    *ret = a - b - borrow;
++    return MP_CT_LTU(a, *ret) | (MP_CT_EQ(a, *ret) & borrow);
++} /*  s_mp_subCT_d() */
++
++/* }}} */
++
++/* {{{ mp_subCT(a, b, ret, borrow) */
++
++/* return ret= a - b and borrow in borrow. done in constant time.
++ * b could be modified.
++ */
++mp_err
++mp_subCT(const mp_int *a, mp_int *b, mp_int *ret, mp_digit *borrow)
++{
++    mp_size used_a = MP_USED(a);
++    mp_size i;
++    mp_err res;
++
++    MP_CHECKOK(s_mp_pad(b, used_a));
++    MP_CHECKOK(s_mp_pad(ret, used_a));
++    *borrow = 0;
++    for (i = 0; i < used_a; i++) {
++        *borrow = s_mp_subCT_d(MP_DIGIT(a, i), MP_DIGIT(b, i), *borrow,
++                               &MP_DIGIT(ret, i));
++    }
++
++    res = MP_OKAY;
++CLEANUP:
++    return res;
++} /*  end mp_subCT() */
++
++/* }}} */
++
++/* {{{ mp_selectCT(cond, a, b, ret) */
++
++/*
++ * return ret= cond ? a : b; cond should be either 0 or 1
++ */
++mp_err
++mp_selectCT(mp_digit cond, const mp_int *a, const mp_int *b, mp_int *ret)
++{
++    mp_size used_a = MP_USED(a);
++    mp_err res;
++    mp_size i;
++
++    cond *= MP_DIGIT_MAX;
++
++    /* we currently require these to be equal on input,
++     * we could use pad to extend one of them, but that might
++     * leak data as it wouldn't be constant time */
++    if (used_a != MP_USED(b)) {
++        return MP_BADARG;
++    }
++
++    MP_CHECKOK(s_mp_pad(ret, used_a));
++    for (i = 0; i < used_a; i++) {
++        MP_DIGIT(ret, i) = MP_CT_SEL_DIGIT(cond, MP_DIGIT(a, i), MP_DIGIT(b, i));
++    }
++    res = MP_OKAY;
++CLEANUP:
++    return res;
++} /* end mp_selectCT() */
++
++/* {{{ mp_reduceCT(a, m, c) */
++
++/*
++  mp_reduceCT(a, m, c)
++
++  Compute c = aR^-1 (mod m) in constant time.
++   input should be in montgomery form. If input is the
++   result of a montgomery multiply then out put will be
++   in mongomery form.
++   Result will be reduced to MP_USED(m), but not be
++   clamped.
++ */
++
++mp_err
++mp_reduceCT(const mp_int *a, const mp_int *m, mp_digit n0i, mp_int *c)
++{
++    mp_size used_m = MP_USED(m);
++    mp_size used_c = used_m * 2 + 1;
++    mp_digit *m_digits, *c_digits;
++    mp_size i;
++    mp_digit borrow, carry;
++    mp_err res;
++    mp_int sub;
++
++    MP_DIGITS(&sub) = 0;
++    MP_CHECKOK(mp_init_size(&sub, used_m));
++
++    if (a != c) {
++        MP_CHECKOK(mp_copy(a, c));
++    }
++    MP_CHECKOK(s_mp_pad(c, used_c));
++    m_digits = MP_DIGITS(m);
++    c_digits = MP_DIGITS(c);
++    for (i = 0; i < used_m; i++) {
++        mp_digit m_i = MP_DIGIT(c, i) * n0i;
++        s_mpv_mul_d_add_propCT(m_digits, used_m, m_i, c_digits++, used_c--);
++    }
++    s_mp_rshd(c, used_m);
++    /* MP_USED(c) should be used_m+1 with the high word being any carry
++     * from the previous multiply, save that carry and drop the high
++     * word for the substraction below */
++    carry = MP_DIGIT(c, used_m);
++    MP_DIGIT(c, used_m) = 0;
++    MP_USED(c) = used_m;
++    /* mp_subCT wants c and m to be the same size, we've already
++     * guarrenteed that in the previous statement, so mp_subCT won't actually
++     * modify m, so it's safe to recast */
++    MP_CHECKOK(mp_subCT(c, (mp_int *)m, &sub, &borrow));
++
++    /* we return c-m if c >= m no borrow or there was a borrow and a carry */
++    MP_CHECKOK(mp_selectCT(borrow ^ carry, c, &sub, c));
++    res = MP_OKAY;
++CLEANUP:
++    mp_clear(&sub);
++    return res;
++} /* end mp_reduceCT() */
++
++/* }}} */
++
+ /* {{{ mp_mod_d(a, d, c) */
+ 
+ /*
+   mp_mod_d(a, d, c)
+ 
+   Compute c = a (mod d).  Result will always be 0 <= c < d
+  */
+ mp_err
+@@ -1379,16 +1569,47 @@ mp_mulmod(const mp_int *a, const mp_int 
+     if ((res = mp_mod(c, m, c)) != MP_OKAY)
+         return res;
+ 
+     return MP_OKAY;
+ }
+ 
+ /* }}} */
+ 
++/* {{{ mp_mulmontmodCT(a, b, m, c) */
++
++/*
++  mp_mulmontmodCT(a, b, m, c)
++
++  Compute c = (a * b) mod m in constant time wrt a and b. either a or b
++  should be in montgomery form and the output is native. If both a and b
++  are in montgomery form, then the output will also be in montgomery form
++  and can be recovered with an mp_reduceCT call.
++  NOTE: a and b may be modified.
++ */
++
++mp_err
++mp_mulmontmodCT(mp_int *a, mp_int *b, const mp_int *m, mp_digit n0i,
++                mp_int *c)
++{
++    mp_err res;
++
++    ARGCHK(a != NULL && b != NULL && m != NULL && c != NULL, MP_BADARG);
++
++    if ((res = mp_mulCT(a, b, c, MP_USED(m))) != MP_OKAY)
++        return res;
++
++    if ((res = mp_reduceCT(c, m, n0i, c)) != MP_OKAY)
++        return res;
++
++    return MP_OKAY;
++}
++
++/* }}} */
++
+ /* {{{ mp_sqrmod(a, m, c) */
+ 
+ #if MP_SQUARE
+ mp_err
+ mp_sqrmod(const mp_int *a, const mp_int *m, mp_int *c)
+ {
+     mp_err res;
+ 
+@@ -3936,25 +4157,73 @@ s_mp_mul(mp_int *a, const mp_int *b)
+     {                                                              \
+         mp_digit a0b1, a1b0;                                       \
+         Plo = (a & MP_HALF_DIGIT_MAX) * (b & MP_HALF_DIGIT_MAX);   \
+         Phi = (a >> MP_HALF_DIGIT_BIT) * (b >> MP_HALF_DIGIT_BIT); \
+         a0b1 = (a & MP_HALF_DIGIT_MAX) * (b >> MP_HALF_DIGIT_BIT); \
+         a1b0 = (a >> MP_HALF_DIGIT_BIT) * (b & MP_HALF_DIGIT_MAX); \
+         a1b0 += a0b1;                                              \
+         Phi += a1b0 >> MP_HALF_DIGIT_BIT;                          \
+-        if (a1b0 < a0b1)                                           \
+-            Phi += MP_HALF_RADIX;                                  \
++        Phi += (MP_CT_LTU(a1b0, a0b1)) << MP_HALF_DIGIT_BIT;       \
+         a1b0 <<= MP_HALF_DIGIT_BIT;                                \
+         Plo += a1b0;                                               \
+-        if (Plo < a1b0)                                            \
+-            ++Phi;                                                 \
++        Phi += MP_CT_LTU(Plo, a1b0);                               \
+     }
+ #endif
+ 
++/* Constant time version of s_mpv_mul_d_add_prop.
++ * Presently, this is only used by the Constant time Montgomery arithmetic code. */
++/* c += a * b */
++void
++s_mpv_mul_d_add_propCT(const mp_digit *a, mp_size a_len, mp_digit b,
++                       mp_digit *c, mp_size c_len)
++{
++#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_MUL_WORD)
++    mp_digit d = 0;
++
++    c_len -= a_len;
++    /* Inner product:  Digits of a */
++    while (a_len--) {
++        mp_word w = ((mp_word)b * *a++) + *c + d;
++        *c++ = ACCUM(w);
++        d = CARRYOUT(w);
++    }
++
++    /* propagate the carry to the end, even if carry is zero */
++    while (c_len--) {
++        mp_word w = (mp_word)*c + d;
++        *c++ = ACCUM(w);
++        d = CARRYOUT(w);
++    }
++#else
++    mp_digit carry = 0;
++    c_len -= a_len;
++    while (a_len--) {
++        mp_digit a_i = *a++;
++        mp_digit a0b0, a1b1;
++        MP_MUL_DxD(a_i, b, a1b1, a0b0);
++
++        a0b0 += carry;
++        a1b1 += MP_CT_LTU(a0b0, carry);
++        a0b0 += a_i = *c;
++        a1b1 += MP_CT_LTU(a0b0, a_i);
++
++        *c++ = a0b0;
++        carry = a1b1;
++    }
++    /* propagate the carry to the end, even if carry is zero */
++    while (c_len--) {
++        mp_digit c_i = *c;
++        carry += c_i;
++        *c++ = carry;
++        carry = MP_CT_LTU(carry, c_i);
++    }
++#endif
++}
++
+ #if !defined(MP_ASSEMBLY_MULTIPLY)
+ /* c = a * b */
+ void
+ s_mpv_mul_d(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c)
+ {
+ #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_MUL_WORD)
+     mp_digit d = 0;
+ 
+@@ -3969,18 +4238,17 @@ s_mpv_mul_d(const mp_digit *a, mp_size a
+     mp_digit carry = 0;
+     while (a_len--) {
+         mp_digit a_i = *a++;
+         mp_digit a0b0, a1b1;
+ 
+         MP_MUL_DxD(a_i, b, a1b1, a0b0);
+ 
+         a0b0 += carry;
+-        if (a0b0 < carry)
+-            ++a1b1;
++        a1b1 += MP_CT_LTU(a0b0, carry);
+         *c++ = a0b0;
+         carry = a1b1;
+     }
+     *c = carry;
+ #endif
+ }
+ 
+ /* c += a * b */
+@@ -4002,21 +4270,19 @@ s_mpv_mul_d_add(const mp_digit *a, mp_si
+     mp_digit carry = 0;
+     while (a_len--) {
+         mp_digit a_i = *a++;
+         mp_digit a0b0, a1b1;
+ 
+         MP_MUL_DxD(a_i, b, a1b1, a0b0);
+ 
+         a0b0 += carry;
+-        if (a0b0 < carry)
+-            ++a1b1;
++        a1b1 += MP_CT_LTU(a0b0, carry);
+         a0b0 += a_i = *c;
+-        if (a0b0 < a_i)
+-            ++a1b1;
++        a1b1 += MP_CT_LTU(a0b0, a_i);
+         *c++ = a0b0;
+         carry = a1b1;
+     }
+     *c = carry;
+ #endif
+ }
+ 
+ /* Presently, this is only used by the Montgomery arithmetic code. */
+diff --git a/security/nss/lib/freebl/mpi/mpi.h b/security/nss/lib/freebl/mpi/mpi.h
+--- a/security/nss/lib/freebl/mpi/mpi.h
++++ b/security/nss/lib/freebl/mpi/mpi.h
+@@ -145,16 +145,48 @@ typedef int mp_sword;
+ #define MP_USED(MP) ((MP)->used)
+ #define MP_ALLOC(MP) ((MP)->alloc)
+ #define MP_DIGITS(MP) ((MP)->dp)
+ #define MP_DIGIT(MP, N) (MP)->dp[(N)]
+ 
+ /* This defines the maximum I/O base (minimum is 2)   */
+ #define MP_MAX_RADIX 64
+ 
++/* Constant Time Macros on mp_digits */
++#define MP_CT_HIGH_TO_LOW(x) ((mp_digit)((mp_digit)(x) >> (MP_DIGIT_BIT - 1)))
++#define MP_CT_TRUE ((mp_digit)1)
++#define MP_CT_FALSE ((mp_digit)0)
++
++/* basic zero and non zero tests */
++#define MP_CT_NOT_ZERO(x) (MP_CT_HIGH_TO_LOW(((x) | (((mp_digit)0) - (x)))))
++#define MP_CT_ZERO(x) (MP_CT_TRUE ^ MP_CT_HIGH_TO_LOW(((x) | (((mp_digit)0) - (x)))))
++
++/* basic constant-time helper macro for equalities and inequalities.
++ * The inequalities will produce incorrect results if
++ * abs(a-b) >= MP_DIGIT_SIZE/2. This can be avoided if unsigned values stay
++ * within the range 0-MP_DIGIT_MAX/2. */
++#define MP_CT_EQ(a, b) MP_CT_ZERO(((a) ^ (b)))
++#define MP_CT_NE(a, b) MP_CT_NOT_ZERO(((a) ^ (b)))
++#define MP_CT_GT(a, b) MP_CT_HIGH_TO_LOW((b) - (a))
++#define MP_CT_LT(a, b) MP_CT_HIGH_TO_LOW((a) - (b))
++#define MP_CT_GE(a, b) (MP_CT_TRUE ^ MP_CT_LT(a, b))
++#define MP_CT_LE(a, b) (MP_CT_TRUE ^ MP_CT_GT(a, b))
++
++/* use constant time result to select a boolean value
++ * or an mp digit depending on the args */
++#define MP_CT_SEL(m, l, r) ((r) ^ ((m) & ((r) ^ (l))))
++#define MP_CT_SELB(m, l, r) MP_CT_SEL(m, l, r)      /* mask, l and r are booleans */
++#define MP_CT_SEL_DIGIT(m, l, r) MP_CT_SEL(m, l, r) /*mask, l, and r are mp_digit */
++
++/* full inequalities that work with full mp_digit values */
++#define MP_CT_OVERFLOW(a, b, c, d)           \
++    MP_CT_SELB(MP_CT_HIGH_TO_LOW((a) ^ (b)), \
++               (MP_CT_HIGH_TO_LOW(d)), c)
++#define MP_CT_LTU(a, b) MP_CT_OVERFLOW(a, b, MP_CT_LT(a, b), b)
++
+ typedef struct {
+     mp_sign sign;  /* sign of this quantity      */
+     mp_size alloc; /* how many digits allocated  */
+     mp_size used;  /* how many digits used       */
+     mp_digit *dp;  /* the digits themselves      */
+ } mp_int;
+ 
+ /* Default precision       */
+@@ -185,17 +217,19 @@ mp_err mp_expt_d(const mp_int *a, mp_dig
+ 
+ /* Sign manipulations      */
+ mp_err mp_abs(const mp_int *a, mp_int *b);
+ mp_err mp_neg(const mp_int *a, mp_int *b);
+ 
+ /* Full arithmetic         */
+ mp_err mp_add(const mp_int *a, const mp_int *b, mp_int *c);
+ mp_err mp_sub(const mp_int *a, const mp_int *b, mp_int *c);
++mp_err mp_subCT(const mp_int *a, mp_int *b, mp_int *c, mp_digit *borrow);
+ mp_err mp_mul(const mp_int *a, const mp_int *b, mp_int *c);
++mp_err mp_mulCT(mp_int *a, mp_int *b, mp_int *c, mp_size setSize);
+ #if MP_SQUARE
+ mp_err mp_sqr(const mp_int *a, mp_int *b);
+ #else
+ #define mp_sqr(a, b) mp_mul(a, a, b)
+ #endif
+ mp_err mp_div(const mp_int *a, const mp_int *b, mp_int *q, mp_int *r);
+ mp_err mp_div_2d(const mp_int *a, mp_digit d, mp_int *q, mp_int *r);
+ mp_err mp_expt(mp_int *a, mp_int *b, mp_int *c);
+@@ -212,23 +246,30 @@ mp_err mp_mulmod(const mp_int *a, const 
+ mp_err mp_sqrmod(const mp_int *a, const mp_int *m, mp_int *c);
+ #else
+ #define mp_sqrmod(a, m, c) mp_mulmod(a, a, m, c)
+ #endif
+ mp_err mp_exptmod(const mp_int *a, const mp_int *b, const mp_int *m, mp_int *c);
+ mp_err mp_exptmod_d(const mp_int *a, mp_digit d, const mp_int *m, mp_int *c);
+ #endif /* MP_MODARITH */
+ 
++/* montgomery math */
++mp_err mp_to_mont(const mp_int *x, const mp_int *N, mp_int *xMont);
++mp_digit mp_calculate_mont_n0i(const mp_int *N);
++mp_err mp_reduceCT(const mp_int *a, const mp_int *m, mp_digit n0i, mp_int *ct);
++mp_err mp_mulmontmodCT(mp_int *a, mp_int *b, const mp_int *m, mp_digit n0i, mp_int *c);
++
+ /* Comparisons             */
+ int mp_cmp_z(const mp_int *a);
+ int mp_cmp_d(const mp_int *a, mp_digit d);
+ int mp_cmp(const mp_int *a, const mp_int *b);
+ int mp_cmp_mag(const mp_int *a, const mp_int *b);
+ int mp_isodd(const mp_int *a);
+ int mp_iseven(const mp_int *a);
++mp_err mp_selectCT(mp_digit cond, const mp_int *a, const mp_int *b, mp_int *ret);
+ 
+ /* Number theoretic        */
+ mp_err mp_gcd(mp_int *a, mp_int *b, mp_int *c);
+ mp_err mp_lcm(mp_int *a, mp_int *b, mp_int *c);
+ mp_err mp_xgcd(const mp_int *a, const mp_int *b, mp_int *g, mp_int *x, mp_int *y);
+ mp_err mp_invmod(const mp_int *a, const mp_int *m, mp_int *c);
+ mp_err mp_invmod_xgcd(const mp_int *a, const mp_int *m, mp_int *c);
+ 
+diff --git a/security/nss/lib/freebl/mpi/mpmontg.c b/security/nss/lib/freebl/mpi/mpmontg.c
+--- a/security/nss/lib/freebl/mpi/mpmontg.c
++++ b/security/nss/lib/freebl/mpi/mpmontg.c
+@@ -124,30 +124,37 @@ s_mp_mul_mont(const mp_int *a, const mp_
+     }
+     res = MP_OKAY;
+ 
+ CLEANUP:
+     return res;
+ }
+ #endif
+ 
+-STATIC
+ mp_err
+-s_mp_to_mont(const mp_int *x, mp_mont_modulus *mmm, mp_int *xMont)
++mp_to_mont(const mp_int *x, const mp_int *N, mp_int *xMont)
+ {
+     mp_err res;
+ 
+     /* xMont = x * R mod N   where  N is modulus */
+-    MP_CHECKOK(mp_copy(x, xMont));
+-    MP_CHECKOK(s_mp_lshd(xMont, MP_USED(&mmm->N))); /* xMont = x << b */
+-    MP_CHECKOK(mp_div(xMont, &mmm->N, 0, xMont));   /*         mod N */
++    if (x != xMont) {
++        MP_CHECKOK(mp_copy(x, xMont));
++    }
++    MP_CHECKOK(s_mp_lshd(xMont, MP_USED(N))); /* xMont = x << b */
++    MP_CHECKOK(mp_div(xMont, N, 0, xMont));   /*         mod N */
+ CLEANUP:
+     return res;
+ }
+ 
++mp_digit
++mp_calculate_mont_n0i(const mp_int *N)
++{
++    return 0 - s_mp_invmod_radix(MP_DIGIT(N, 0));
++}
++
+ #ifdef MP_USING_MONT_MULF
+ 
+ /* the floating point multiply is already cache safe,
+  * don't turn on cache safe unless we specifically
+  * force it */
+ #ifndef MP_FORCE_CACHE_SAFE
+ #undef MP_USING_CACHE_SAFE_MOD_EXP
+ #endif
+@@ -193,17 +200,17 @@ mp_exptmod_f(const mp_int *montBase,
+     MP_DIGITS(&accum1) = 0;
+ 
+     for (i = 0; i < MAX_ODD_INTS; ++i)
+         oddPowers[i] = 0;
+ 
+     MP_CHECKOK(mp_init_size(&accum1, 3 * nLen + 2));
+ 
+     mp_set(&accum1, 1);
+-    MP_CHECKOK(s_mp_to_mont(&accum1, mmm, &accum1));
++    MP_CHECKOK(mp_to_mont(&accum1, &(mmm->N), &accum1));
+     MP_CHECKOK(s_mp_pad(&accum1, nLen));
+ 
+     oddPowSize = 2 * nLen + 1;
+     dTmpSize = 2 * oddPowSize;
+     dSize = sizeof(double) * (nLen * 4 + 1 +
+                               ((odd_ints + 1) * oddPowSize) + dTmpSize);
+     dBuf = malloc(dSize);
+     if (!dBuf) {
+@@ -473,17 +480,17 @@ mp_exptmod_i(const mp_int *montBase,
+     for (i = 1; i < odd_ints; ++i) {
+         MP_CHECKOK(mp_init_size(oddPowers + i, nLen + 2 * MP_USED(&power2) + 2));
+         MP_CHECKOK(mp_mul(oddPowers + (i - 1), &power2, oddPowers + i));
+         MP_CHECKOK(s_mp_redc(oddPowers + i, mmm));
+     }
+ 
+     /* set accumulator to montgomery residue of 1 */
+     mp_set(&accum1, 1);
+-    MP_CHECKOK(s_mp_to_mont(&accum1, mmm, &accum1));
++    MP_CHECKOK(mp_to_mont(&accum1, &(mmm->N), &accum1));
+     pa1 = &accum1;
+     pa2 = &accum2;
+ 
+     for (expOff = bits_in_exponent - window_bits; expOff >= 0; expOff -= window_bits) {
+         mp_size smallExp;
+         MP_CHECKOK(mpl_get_bits(exponent, expOff, window_bits));
+         smallExp = (mp_size)res;
+ 
+@@ -862,17 +869,17 @@ mp_exptmod_safe_i(const mp_int *montBase
+     /* build the first WEAVE_WORD powers inline */
+     /* if WEAVE_WORD_SIZE is not 4, this code will have to change */
+     if (num_powers > 2) {
+         MP_CHECKOK(mp_init_size(&accum[0], 3 * nLen + 2));
+         MP_CHECKOK(mp_init_size(&accum[1], 3 * nLen + 2));
+         MP_CHECKOK(mp_init_size(&accum[2], 3 * nLen + 2));
+         MP_CHECKOK(mp_init_size(&accum[3], 3 * nLen + 2));
+         mp_set(&accum[0], 1);
+-        MP_CHECKOK(s_mp_to_mont(&accum[0], mmm, &accum[0]));
++        MP_CHECKOK(mp_to_mont(&accum[0], &(mmm->N), &accum[0]));
+         MP_CHECKOK(mp_copy(montBase, &accum[1]));
+         SQR(montBase, &accum[2]);
+         MUL_NOWEAVE(montBase, &accum[2], &accum[3]);
+         powersArray = (mp_digit *)malloc(num_powers * (nLen * sizeof(mp_digit) + 1));
+         if (!powersArray) {
+             res = MP_MEM;
+             goto CLEANUP;
+         }
+@@ -881,17 +888,17 @@ mp_exptmod_safe_i(const mp_int *montBase
+         MP_CHECKOK(mpi_to_weave(accum, powers, nLen, num_powers));
+         if (first_window < 4) {
+             MP_CHECKOK(mp_copy(&accum[first_window], &accum1));
+             first_window = num_powers;
+         }
+     } else {
+         if (first_window == 0) {
+             mp_set(&accum1, 1);
+-            MP_CHECKOK(s_mp_to_mont(&accum1, mmm, &accum1));
++            MP_CHECKOK(mp_to_mont(&accum1, &(mmm->N), &accum1));
+         } else {
+             /* assert first_window == 1? */
+             MP_CHECKOK(mp_copy(montBase, &accum1));
+         }
+     }
+ 
+     /*
+      * calculate all the powers in the powers array.
+@@ -1052,19 +1059,19 @@ mp_exptmod(const mp_int *inBase, const m
+     nLen = MP_USED(modulus);
+     MP_CHECKOK(mp_init_size(&montBase, 2 * nLen + 2));
+ 
+     mmm.N = *modulus; /* a copy of the mp_int struct */
+ 
+     /* compute n0', given n0, n0' = -(n0 ** -1) mod MP_RADIX
+     **        where n0 = least significant mp_digit of N, the modulus.
+     */
+-    mmm.n0prime = 0 - s_mp_invmod_radix(MP_DIGIT(modulus, 0));
++    mmm.n0prime = mp_calculate_mont_n0i(modulus);
+ 
+-    MP_CHECKOK(s_mp_to_mont(base, &mmm, &montBase));
++    MP_CHECKOK(mp_to_mont(base, modulus, &montBase));
+ 
+     bits_in_exponent = mpl_significant_bits(exponent);
+ #ifdef MP_USING_CACHE_SAFE_MOD_EXP
+     if (mp_using_cache_safe_exp) {
+         if (bits_in_exponent > 780)
+             window_bits = 6;
+         else if (bits_in_exponent > 256)
+             window_bits = 5;
+diff --git a/security/nss/lib/freebl/rsa.c b/security/nss/lib/freebl/rsa.c
+--- a/security/nss/lib/freebl/rsa.c
++++ b/security/nss/lib/freebl/rsa.c
+@@ -65,16 +65,18 @@ struct blindingParamsStr {
+ ** the Handbook of Applied Cryptography, 11.118-11.119.
+ */
+ struct RSABlindingParamsStr {
+     /* Blinding-specific parameters */
+     PRCList link;              /* link to list of structs            */
+     SECItem modulus;           /* list element "key"                 */
+     blindingParams *free, *bp; /* Blinding parameters queue          */
+     blindingParams array[RSA_BLINDING_PARAMS_MAX_CACHE_SIZE];
++    /* precalculate montegomery reduction value */
++    mp_digit n0i; /* n0i = -( n & MP_DIGIT) ** -1 mod mp_RADIX */
+ };
+ typedef struct RSABlindingParamsStr RSABlindingParams;
+ 
+ /*
+ ** RSABlindingParamsListStr
+ **
+ ** List of key-specific blinding params.  The arena holds the volatile pool
+ ** of memory for each entry and the list itself.  The lock is for list
+@@ -1205,16 +1207,18 @@ generate_blinding_params(RSAPrivateKey *
+     CHECK_SEC_OK(RNG_GenerateGlobalRandomBytes(kb, modLen));
+     CHECK_MPI_OK(mp_read_unsigned_octets(&k, kb, modLen));
+     /* k < n */
+     CHECK_MPI_OK(mp_mod(&k, n, &k));
+     /* f = k**e mod n */
+     CHECK_MPI_OK(mp_exptmod(&k, &e, n, f));
+     /* g = k**-1 mod n */
+     CHECK_MPI_OK(mp_invmod(&k, n, g));
++    /* g in montgomery form.. */
++    CHECK_MPI_OK(mp_to_mont(g, n, g));
+ cleanup:
+     if (kb)
+         PORT_ZFree(kb, modLen);
+     mp_clear(&k);
+     mp_clear(&e);
+     if (err) {
+         MP_TO_SEC_ERROR(err);
+         rv = SECFailure;
+@@ -1241,23 +1245,26 @@ init_blinding_params(RSABlindingParams *
+      * of rsabp->array pointer and must be set to NULL
+      */
+     rsabp->array[RSA_BLINDING_PARAMS_MAX_CACHE_SIZE - 1].next = NULL;
+ 
+     bp = rsabp->array;
+     rsabp->bp = NULL;
+     rsabp->free = bp;
+ 
++    /* precalculate montgomery reduction parameter */
++    rsabp->n0i = mp_calculate_mont_n0i(n);
++
+     /* List elements are keyed using the modulus */
+     return SECITEM_CopyItem(NULL, &rsabp->modulus, &key->modulus);
+ }
+ 
+ static SECStatus
+ get_blinding_params(RSAPrivateKey *key, mp_int *n, unsigned int modLen,
+-                    mp_int *f, mp_int *g)
++                    mp_int *f, mp_int *g, mp_digit *n0i)
+ {
+     RSABlindingParams *rsabp = NULL;
+     blindingParams *bpUnlinked = NULL;
+     blindingParams *bp;
+     PRCList *el;
+     SECStatus rv = SECSuccess;
+     mp_err err = MP_OKAY;
+     int cmp = -1;
+@@ -1307,16 +1314,17 @@ get_blinding_params(RSAPrivateKey *key, 
+             ** head (since el would have looped back to the head).
+             */
+             PR_INSERT_BEFORE(&rsabp->link, el);
+         }
+ 
+         /* We've found (or created) the RSAblindingParams struct for this key.
+          * Now, search its list of ready blinding params for a usable one.
+          */
++        *n0i = rsabp->n0i;
+         while (0 != (bp = rsabp->bp)) {
+ #ifdef UNSAFE_FUZZER_MODE
+             /* Found a match and there are still remaining uses left */
+             /* Return the parameters */
+             CHECK_MPI_OK(mp_copy(&bp->f, f));
+             CHECK_MPI_OK(mp_copy(&bp->g, g));
+ 
+             PZ_Unlock(blindingParamsList.lock);
+@@ -1421,16 +1429,17 @@ cleanup:
+         rsabp->free = bp;
+     }
+     if (holdingLock) {
+         PZ_Unlock(blindingParamsList.lock);
+     }
+     if (err) {
+         MP_TO_SEC_ERROR(err);
+     }
++    *n0i = 0;
+     return SECFailure;
+ }
+ 
+ /*
+ ** Perform a raw private-key operation
+ **  Length of input and output buffers are equal to key's modulus len.
+ */
+ static SECStatus
+@@ -1440,16 +1449,17 @@ rsa_PrivateKeyOp(RSAPrivateKey *key,
+                  PRBool check)
+ {
+     unsigned int modLen;
+     unsigned int offset;
+     SECStatus rv = SECSuccess;
+     mp_err err;
+     mp_int n, c, m;
+     mp_int f, g;
++    mp_digit n0i;
+     if (!key || !output || !input) {
+         PORT_SetError(SEC_ERROR_INVALID_ARGS);
+         return SECFailure;
+     }
+     /* check input out of range (needs to be in range [0..n-1]) */
+     modLen = rsa_modulusLen(&key->modulus);
+     if (modLen == 0) {
+         PORT_SetError(SEC_ERROR_INVALID_ARGS);
+@@ -1471,17 +1481,17 @@ rsa_PrivateKeyOp(RSAPrivateKey *key,
+     CHECK_MPI_OK(mp_init(&f));
+     CHECK_MPI_OK(mp_init(&g));
+     SECITEM_TO_MPINT(key->modulus, &n);
+     OCTETS_TO_MPINT(input, &c, modLen);
+     /* If blinding, compute pre-image of ciphertext by multiplying by
+     ** blinding factor
+     */
+     if (nssRSAUseBlinding) {
+-        CHECK_SEC_OK(get_blinding_params(key, &n, modLen, &f, &g));
++        CHECK_SEC_OK(get_blinding_params(key, &n, modLen, &f, &g, &n0i));
+         /* c' = c*f mod n */
+         CHECK_MPI_OK(mp_mulmod(&c, &f, &n, &c));
+     }
+     /* Do the private key operation m = c**d mod n */
+     if (key->prime1.len == 0 ||
+         key->prime2.len == 0 ||
+         key->exponent1.len == 0 ||
+         key->exponent2.len == 0 ||
+@@ -1492,17 +1502,17 @@ rsa_PrivateKeyOp(RSAPrivateKey *key,
+     } else {
+         CHECK_SEC_OK(rsa_PrivateKeyOpCRTNoCheck(key, &m, &c));
+     }
+     /* If blinding, compute post-image of plaintext by multiplying by
+     ** blinding factor
+     */
+     if (nssRSAUseBlinding) {
+         /* m = m'*g mod n */
+-        CHECK_MPI_OK(mp_mulmod(&m, &g, &n, &m));
++        CHECK_MPI_OK(mp_mulmontmodCT(&m, &g, &n, n0i, &m));
+     }
+     err = mp_to_fixlen_octets(&m, output, modLen);
+     if (err >= 0)
+         err = MP_OKAY;
+ cleanup:
+     mp_clear(&n);
+     mp_clear(&c);
+     mp_clear(&m);
+diff --git a/security/nss/lib/nss/nss.h b/security/nss/lib/nss/nss.h
+--- a/security/nss/lib/nss/nss.h
++++ b/security/nss/lib/nss/nss.h
+@@ -17,20 +17,20 @@
+ 
+ /*
+  * NSS's major version, minor version, patch level, build number, and whether
+  * this is a beta release.
+  *
+  * The format of the version string should be
+  *     "<major version>.<minor version>[.<patch level>[.<build number>]][ <ECC>][ <Beta>]"
+  */
+-#define NSS_VERSION "3.90.1" _NSS_CUSTOMIZED
++#define NSS_VERSION "3.90.2" _NSS_CUSTOMIZED
+ #define NSS_VMAJOR 3
+ #define NSS_VMINOR 90
+-#define NSS_VPATCH 1
++#define NSS_VPATCH 2
+ #define NSS_VBUILD 0
+ #define NSS_BETA PR_FALSE
+ 
+ #ifndef RC_INVOKED
+ 
+ #include "seccomon.h"
+ 
+ typedef struct NSSInitParametersStr NSSInitParameters;
+diff --git a/security/nss/lib/softoken/softkver.h b/security/nss/lib/softoken/softkver.h
+--- a/security/nss/lib/softoken/softkver.h
++++ b/security/nss/lib/softoken/softkver.h
+@@ -12,16 +12,16 @@
+ 
+ /*
+  * Softoken's major version, minor version, patch level, build number,
+  * and whether this is a beta release.
+  *
+  * The format of the version string should be
+  *     "<major version>.<minor version>[.<patch level>[.<build number>]][ <ECC>][ <Beta>]"
+  */
+-#define SOFTOKEN_VERSION "3.90.1" SOFTOKEN_ECC_STRING
++#define SOFTOKEN_VERSION "3.90.2" SOFTOKEN_ECC_STRING
+ #define SOFTOKEN_VMAJOR 3
+ #define SOFTOKEN_VMINOR 90
+-#define SOFTOKEN_VPATCH 1
++#define SOFTOKEN_VPATCH 2
+ #define SOFTOKEN_VBUILD 0
+ #define SOFTOKEN_BETA PR_FALSE
+ 
+ #endif /* _SOFTKVER_H_ */
+diff --git a/security/nss/lib/ssl/sslsecur.c b/security/nss/lib/ssl/sslsecur.c
+--- a/security/nss/lib/ssl/sslsecur.c
++++ b/security/nss/lib/ssl/sslsecur.c
+@@ -483,17 +483,22 @@ ssl_SendSavedWriteData(sslSocket *ss)
+     PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
+     if (ss->pendingBuf.len != 0) {
+         SSL_TRC(5, ("%d: SSL[%d]: sending %d bytes of saved data",
+                     SSL_GETPID(), ss->fd, ss->pendingBuf.len));
+         rv = ssl_DefSend(ss, ss->pendingBuf.buf, ss->pendingBuf.len, 0);
+         if (rv < 0) {
+             return rv;
+         }
+-        ss->pendingBuf.len -= rv;
++        if (rv > ss->pendingBuf.len) {
++            PORT_Assert(0); /* This shouldn't happen */
++            ss->pendingBuf.len = 0;
++        } else {
++            ss->pendingBuf.len -= rv;
++        }
+         if (ss->pendingBuf.len > 0 && rv > 0) {
+             /* UGH !! This shifts the whole buffer down by copying it */
+             PORT_Memmove(ss->pendingBuf.buf, ss->pendingBuf.buf + rv,
+                          ss->pendingBuf.len);
+         }
+     }
+     return rv;
+ }
+diff --git a/security/nss/lib/util/nssutil.h b/security/nss/lib/util/nssutil.h
+--- a/security/nss/lib/util/nssutil.h
++++ b/security/nss/lib/util/nssutil.h
+@@ -14,20 +14,20 @@
+ 
+ /*
+  * NSS utilities's major version, minor version, patch level, build number,
+  * and whether this is a beta release.
+  *
+  * The format of the version string should be
+  *     "<major version>.<minor version>[.<patch level>[.<build number>]][ <Beta>]"
+  */
+-#define NSSUTIL_VERSION "3.90.1"
++#define NSSUTIL_VERSION "3.90.2"
+ #define NSSUTIL_VMAJOR 3
+ #define NSSUTIL_VMINOR 90
+-#define NSSUTIL_VPATCH 1
++#define NSSUTIL_VPATCH 2
+ #define NSSUTIL_VBUILD 0
+ #define NSSUTIL_BETA PR_FALSE
+ 
+ SEC_BEGIN_PROTOS
+ 
+ /*
+  * Returns a const string of the UTIL library version.
+  */

+ 5 - 0
mozilla-release/patches/series

@@ -6609,3 +6609,8 @@ TOP-NOBUG-REGEXP-43-1691184-88a1-25318.patch
 TOP-NOBUG-REGEXP-44-irregexp-25318.patch
 TOP-NOBUG-REGEXP-45-final-25318.patch
 TOP-NOBUG-REGEXP-46-fixes-25318.patch
+1864385-PARTIAL-11508.patch
+1867982-124a1.patch
+1878211-11508.patch
+1881093-11509.patch
+TOP-1880562-NSS3902-11509.patch