dev-libs/nss: fix multiple CVEs

BUG=b/335667969,b/336056326,b/336056837,b/336172624
TEST=presubmit
RELEASE_NOTE=Fixed CVE-2023-0767, CVE-2023-5388, CVE-2023-6135, CVE-2024-0743 in dev-libs/nss.

cos-patch: security-high
Change-Id: Ib123d064e8c000878292ca454785de90d33e3afb
Reviewed-on: https://cos-review.googlesource.com/c/third_party/overlays/chromiumos-overlay/+/70293
Tested-by: Cusky Presubmit Bot <presubmit@cos-infra-prod.iam.gserviceaccount.com>
Main-Branch-Verified: Cusky Presubmit Bot <presubmit@cos-infra-prod.iam.gserviceaccount.com>
Reviewed-by: Kevin Berry <kpberry@google.com>
diff --git a/dev-libs/nss/files/nss-3.73-CVE-2023-0767.patch b/dev-libs/nss/files/nss-3.73-CVE-2023-0767.patch
new file mode 100644
index 0000000..5e1be72
--- /dev/null
+++ b/dev-libs/nss/files/nss-3.73-CVE-2023-0767.patch
@@ -0,0 +1,120 @@
+
+# HG changeset patch
+# User John M. Schanck <jschanck@mozilla.com>
+# Date 1675974326 0
+# Node ID 57c60a4da16503b7827ccd763354faf151514b57
+# Parent  36cbafe2cccee540930531810e2a75cd7a74c5b1
+Bug 1804640 - improve handling of unknown PKCS#12 safe bag types. r=rrelyea
+
+Differential Revision: https://phabricator.services.mozilla.com/D167443
+
+diff --git a/lib/pkcs12/p12d.c b/lib/pkcs12/p12d.c
+--- a/lib/pkcs12/p12d.c
++++ b/lib/pkcs12/p12d.c
+@@ -332,41 +332,48 @@ sec_pkcs12_decoder_safe_bag_update(void 
+                                    unsigned long len, int depth,
+                                    SEC_ASN1EncodingPart data_kind)
+ {
+     sec_PKCS12SafeContentsContext *safeContentsCtx =
+         (sec_PKCS12SafeContentsContext *)arg;
+     SEC_PKCS12DecoderContext *p12dcx;
+     SECStatus rv;
+ 
+-    /* make sure that we are not skipping the current safeBag,
+-     * and that there are no errors.  If so, just return rather
+-     * than continuing to process.
+-     */
+-    if (!safeContentsCtx || !safeContentsCtx->p12dcx ||
+-        safeContentsCtx->p12dcx->error || safeContentsCtx->skipCurrentSafeBag) {
++    if (!safeContentsCtx || !safeContentsCtx->p12dcx || !safeContentsCtx->currentSafeBagA1Dcx) {
+         return;
+     }
+     p12dcx = safeContentsCtx->p12dcx;
+ 
++    /* make sure that there are no errors and we are not skipping the current safeBag */
++    if (p12dcx->error || safeContentsCtx->skipCurrentSafeBag) {
++        goto loser;
++    }
++
+     rv = SEC_ASN1DecoderUpdate(safeContentsCtx->currentSafeBagA1Dcx, data, len);
+     if (rv != SECSuccess) {
+         p12dcx->errorValue = PORT_GetError();
++        p12dcx->error = PR_TRUE;
++        goto loser;
++    }
++
++    /* The update may have set safeContentsCtx->skipCurrentSafeBag, and we
++     * may not get another opportunity to clean up the decoder context.
++     */
++    if (safeContentsCtx->skipCurrentSafeBag) {
+         goto loser;
+     }
+ 
+     return;
+ 
+ loser:
+-    /* set the error, and finish the decoder context.  because there
++    /* Finish the decoder context. Because there
+      * is not a way of returning an error message, it may be worth
+      * while to do a check higher up and finish any decoding contexts
+      * that are still open.
+      */
+-    p12dcx->error = PR_TRUE;
+     SEC_ASN1DecoderFinish(safeContentsCtx->currentSafeBagA1Dcx);
+     safeContentsCtx->currentSafeBagA1Dcx = NULL;
+     return;
+ }
+ 
+ /* notify function for decoding safeBags.  This function is
+  * used to filter safeBag types which are not supported,
+  * initiate the decoding of nested safe contents, and decode
+diff --git a/lib/pkcs12/p12t.h b/lib/pkcs12/p12t.h
+--- a/lib/pkcs12/p12t.h
++++ b/lib/pkcs12/p12t.h
+@@ -68,16 +68,17 @@ struct sec_PKCS12SafeBagStr {
+     /* Dependent upon the type of bag being used. */
+     union {
+         SECKEYPrivateKeyInfo *pkcs8KeyBag;
+         SECKEYEncryptedPrivateKeyInfo *pkcs8ShroudedKeyBag;
+         sec_PKCS12CertBag *certBag;
+         sec_PKCS12CRLBag *crlBag;
+         sec_PKCS12SecretBag *secretBag;
+         sec_PKCS12SafeContents *safeContents;
++        SECItem *unknownBag;
+     } safeBagContent;
+ 
+     sec_PKCS12Attribute **attribs;
+ 
+     /* used locally */
+     SECOidData *bagTypeTag;
+     PLArenaPool *arena;
+     unsigned int nAttribs;
+diff --git a/lib/pkcs12/p12tmpl.c b/lib/pkcs12/p12tmpl.c
+--- a/lib/pkcs12/p12tmpl.c
++++ b/lib/pkcs12/p12tmpl.c
+@@ -25,22 +25,22 @@ sec_pkcs12_choose_safe_bag_type(void *sr
+     if (src_or_dest == NULL) {
+         return NULL;
+     }
+ 
+     safeBag = (sec_PKCS12SafeBag *)src_or_dest;
+ 
+     oiddata = SECOID_FindOID(&safeBag->safeBagType);
+     if (oiddata == NULL) {
+-        return SEC_ASN1_GET(SEC_AnyTemplate);
++        return SEC_ASN1_GET(SEC_PointerToAnyTemplate);
+     }
+ 
+     switch (oiddata->offset) {
+         default:
+-            theTemplate = SEC_ASN1_GET(SEC_AnyTemplate);
++            theTemplate = SEC_ASN1_GET(SEC_PointerToAnyTemplate);
+             break;
+         case SEC_OID_PKCS12_V1_KEY_BAG_ID:
+             theTemplate = SEC_ASN1_GET(SECKEY_PointerToPrivateKeyInfoTemplate);
+             break;
+         case SEC_OID_PKCS12_V1_CERT_BAG_ID:
+             theTemplate = sec_PKCS12PointerToCertBagTemplate;
+             break;
+         case SEC_OID_PKCS12_V1_CRL_BAG_ID:
+
diff --git a/dev-libs/nss/files/nss-3.73-CVE-2023-5388.patch b/dev-libs/nss/files/nss-3.73-CVE-2023-5388.patch
new file mode 100644
index 0000000..e166775
--- /dev/null
+++ b/dev-libs/nss/files/nss-3.73-CVE-2023-5388.patch
@@ -0,0 +1,638 @@
+--- a/lib/freebl/mpi/mpi.c
++++ b/lib/freebl/mpi/mpi.c
+@@ -13,6 +13,8 @@
+ #include <c_asm.h>
+ #endif
+ 
++#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 */
+@@ -817,15 +819,18 @@
+ 
+ /* }}} */
+ 
+-/* {{{ mp_mul(a, b, c) */
++/* {{{ s_mp_mulg(a, b, c) */
+ 
+ /*
+-  mp_mul(a, b, c)
++  s_mp_mulg(a, b, c)
+ 
+-  Compute c = a * b.  All parameters may be identical.
++  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;
+@@ -861,7 +866,14 @@
+         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;
+@@ -891,13 +903,15 @@
+         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;
+@@ -907,10 +921,54 @@
+ 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
+@@ -1283,6 +1341,138 @@
+ 
+ /* }}} */
+ 
++/* {{{ 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) */
+ 
+ /*
+@@ -1399,6 +1589,37 @@
+ 
+ /* }}} */
+ 
++/* {{{ 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
+@@ -3942,14 +4163,62 @@
+         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 */
+@@ -3975,8 +4244,7 @@
+         MP_MUL_DxD(a_i, b, a1b1, a0b0);
+ 
+         a0b0 += carry;
+-        if (a0b0 < carry)
+-            ++a1b1;
++        a1b1 += MP_CT_LTU(a0b0, carry);
+         *c++ = a0b0;
+         carry = a1b1;
+     }
+@@ -4008,11 +4276,9 @@
+         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;
+     }
+--- a/lib/freebl/mpi/mpi.h
++++ b/lib/freebl/mpi/mpi.h
+@@ -150,6 +150,38 @@
+ /* 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  */
+@@ -190,7 +222,9 @@
+ /* 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
+@@ -217,6 +251,12 @@
+ 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);
+@@ -224,6 +264,7 @@
+ 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);
+--- a/lib/freebl/mpi/mpmontg.c
++++ b/lib/freebl/mpi/mpmontg.c
+@@ -129,20 +129,27 @@
+ }
+ #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,
+@@ -198,7 +205,7 @@
+     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;
+@@ -478,7 +485,7 @@
+ 
+     /* 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;
+ 
+@@ -865,7 +872,7 @@
+         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]);
+@@ -884,7 +891,7 @@
+     } 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));
+@@ -1051,9 +1058,9 @@
+     /* 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
+--- a/lib/freebl/rsa.c
++++ b/lib/freebl/rsa.c
+@@ -64,6 +64,8 @@
+     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;
+ 
+@@ -1146,6 +1148,8 @@
+     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);
+@@ -1182,13 +1186,16 @@
+     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;
+@@ -1248,6 +1255,7 @@
+         /* 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)) {
+ #ifndef UNSAFE_FUZZER_MODE
+             if (--(bp->counter) > 0)
+@@ -1355,6 +1363,7 @@
+     if (err) {
+         MP_TO_SEC_ERROR(err);
+     }
++    *n0i = 0;
+     return SECFailure;
+ }
+ 
+@@ -1374,6 +1383,7 @@
+     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;
+@@ -1401,7 +1411,7 @@
+     ** 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));
+     }
+@@ -1422,7 +1432,7 @@
+     */
+     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)
+--- a/lib/freebl/mpi/mpi-priv.h
++++ b/lib/freebl/mpi/mpi-priv.h
+@@ -204,6 +204,9 @@
+ 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);
diff --git a/dev-libs/nss/files/nss-3.73-CVE-2023-6135-part1.patch b/dev-libs/nss/files/nss-3.73-CVE-2023-6135-part1.patch
new file mode 100644
index 0000000..af90663
--- /dev/null
+++ b/dev-libs/nss/files/nss-3.73-CVE-2023-6135-part1.patch
@@ -0,0 +1,364 @@
+Description:  Upstream patch for CVE-2023-6125, part 1
+ NOTE: It is unclear what exactly are the fixing parts, and
+ the version in buster has only support for Curve25519 and not
+ for ECCurve_NIST_P256.
+ Therefore this patch is currently not applied, until more
+ information is available, but it is kept for later reference.
+Origin: (security tracker) https://deb.freexian.com/extended-lts/tracker/CVE-2023-6135
+Origin: https://hg.mozilla.org/projects/nss/rev/e68b42b773657000078d104aaccbe26e71a1e0be
+
+
+# HG changeset patch
+# User Karthikeyan Bhargavan <karthik.bhargavan@gmail.com>
+# Date 1698703971 0
+# Node ID e68b42b773657000078d104aaccbe26e71a1e0be
+# Parent  a69c9f36bb8ac1c47cacb6c6ec9f06309de33951
+Bug 1861728 - Include P-256 Scalar Validation from HACL*. r=jschanck
+
+Differential Revision: https://phabricator.services.mozilla.com/D192126
+
+--- a/lib/freebl/ec.c
++++ b/lib/freebl/ec.c
+@@ -18,7 +18,8 @@
+ static const ECMethod kMethods[] = {
+     { ECCurve25519,
+       ec_Curve25519_pt_mul,
+-      ec_Curve25519_pt_validate }
++      ec_Curve25519_pt_validate,
++      ec_Curve25519_scalar_validate }
+ };
+ 
+ static const ECMethod *
+@@ -274,12 +275,12 @@
+     /* Use curve specific code for point multiplication */
+     if (ecParams->fieldID.type == ec_field_plain) {
+         const ECMethod *method = ec_get_method_from_name(ecParams->name);
+-        if (method == NULL || method->mul == NULL) {
++        if (method == NULL || method->pt_mul == NULL) {
+             /* unknown curve */
+             rv = SECFailure;
+             goto cleanup;
+         }
+-        rv = method->mul(&key->publicValue, &key->privateValue, NULL);
++        rv = method->pt_mul(&key->publicValue, &key->privateValue, NULL);
+         goto done;
+     }
+ 
+@@ -323,26 +324,56 @@
+     return rv;
+ }
+ 
+-/* Generate a random private key using the algorithm A.4.1 of ANSI X9.62,
++/* Generate a random private key using the algorithm A.4.1 or A.4.2 of ANSI X9.62,
+  * modified a la FIPS 186-2 Change Notice 1 to eliminate the bias in the
+  * random number generator.
+- *
+- * Parameters
+- * - order: a buffer that holds the curve's group order
+- * - len: the length in octets of the order buffer
+- *
+- * Return Value
+- * Returns a buffer of len octets that holds the private key. The caller
+- * is responsible for freeing the buffer with PORT_ZFree.
+  */
+-static unsigned char *
+-ec_GenerateRandomPrivateKey(const unsigned char *order, int len)
++
++SECStatus
++ec_GenerateRandomPrivateKey(ECParams *ecParams, SECItem *privKey)
+ {
+     SECStatus rv = SECSuccess;
+     mp_err err;
+-    unsigned char *privKeyBytes = NULL;
++
++    unsigned int len = EC_GetScalarSize(ecParams);
++
++    if (privKey->len != len || privKey->data == NULL) {
++        PORT_SetError(SEC_ERROR_INVALID_ARGS);
++        return SECFailure;
++    }
++
++    /* For known curves, use rejection sampling A.4.2 */
++    if (ecParams->fieldID.type == ec_field_plain) {
++        const ECMethod *method = ec_get_method_from_name(ecParams->name);
++        rv = SECFailure;
++        if (method == NULL || method->scalar_validate == NULL) {
++            /* unknown curve */
++            PORT_SetError(SEC_ERROR_INVALID_ARGS);
++            goto done;
++        }
++        int count = 100;
++        while (rv != SECSuccess && count >= 0) {
++            rv = RNG_GenerateGlobalRandomBytes(privKey->data, len);
++            if (rv != SECSuccess) {
++                PORT_SetError(SEC_ERROR_NEED_RANDOM);
++                goto done;
++            }
++            rv = method->scalar_validate(privKey);
++            count--;
++        }
++        if (rv != SECSuccess) {
++            PORT_SetError(SEC_ERROR_BAD_KEY);
++        }
++        goto done;
++    }
++
++    /* For unknown curves, use algotithm A.4.1 */
++
++    unsigned char *order = ecParams->order.data;
+     mp_int privKeyVal, order_1, one;
+ 
++    unsigned char *privKeyBytes = NULL;
++
+     MP_DIGITS(&privKeyVal) = 0;
+     MP_DIGITS(&order_1) = 0;
+     MP_DIGITS(&one) = 0;
+@@ -354,8 +385,13 @@
+      * (which implements Algorithm 1 of FIPS 186-2 Change Notice 1) then
+      * reduces modulo the group order.
+      */
+-    if ((privKeyBytes = PORT_Alloc(2 * len)) == NULL)
++
++    if ((privKeyBytes = PORT_Alloc(2 * len)) == NULL) {
++        PORT_SetError(SEC_ERROR_NO_MEMORY);
++        rv = SECFailure;
+         goto cleanup;
++    }
++
+     CHECK_SEC_OK(RNG_GenerateGlobalRandomBytes(privKeyBytes, 2 * len));
+     CHECK_MPI_OK(mp_read_unsigned_octets(&privKeyVal, privKeyBytes, 2 * len));
+     CHECK_MPI_OK(mp_read_unsigned_octets(&order_1, order, len));
+@@ -364,20 +400,26 @@
+     CHECK_MPI_OK(mp_mod(&privKeyVal, &order_1, &privKeyVal));
+     CHECK_MPI_OK(mp_add(&privKeyVal, &one, &privKeyVal));
+     CHECK_MPI_OK(mp_to_fixlen_octets(&privKeyVal, privKeyBytes, len));
+-    memset(privKeyBytes + len, 0, len);
++    memcpy(privKey->data, privKeyBytes, len);
++
+ cleanup:
+     mp_clear(&privKeyVal);
+     mp_clear(&order_1);
+     mp_clear(&one);
++    if (privKeyBytes) {
++        PORT_ZFree(privKeyBytes, 2 * len);
++    }
+     if (err < MP_OKAY) {
+         MP_TO_SEC_ERROR(err);
+         rv = SECFailure;
+     }
+-    if (rv != SECSuccess && privKeyBytes) {
+-        PORT_ZFree(privKeyBytes, 2 * len);
+-        privKeyBytes = NULL;
++
++done:
++    if (rv != SECSuccess && privKey->data) {
++        SECITEM_ZfreeItem(privKey, PR_FALSE);
++        return rv;
+     }
+-    return privKeyBytes;
++    return rv;
+ }
+ 
+ /* Generates a new EC key pair. The private key is a random value and
+@@ -388,24 +430,28 @@
+ EC_NewKey(ECParams *ecParams, ECPrivateKey **privKey)
+ {
+     SECStatus rv = SECFailure;
+-    int len;
+-    unsigned char *privKeyBytes = NULL;
++    SECItem privKeyRand = { siBuffer, NULL, 0 };
+ 
+     if (!ecParams || ecParams->name == ECCurve_noName || !privKey) {
+         PORT_SetError(SEC_ERROR_INVALID_ARGS);
+         return SECFailure;
+     }
+ 
+-    len = ecParams->order.len;
+-    privKeyBytes = ec_GenerateRandomPrivateKey(ecParams->order.data, len);
+-    if (privKeyBytes == NULL)
++    SECITEM_AllocItem(NULL, &privKeyRand, EC_GetScalarSize(ecParams));
++    if (privKeyRand.data == NULL) {
++        PORT_SetError(SEC_ERROR_NO_MEMORY);
++        rv = SECFailure;
++        goto cleanup;
++    }
++    rv = ec_GenerateRandomPrivateKey(ecParams, &privKeyRand);
++    if (rv != SECSuccess || privKeyRand.data == NULL)
+         goto cleanup;
+     /* generate public key */
+-    CHECK_SEC_OK(ec_NewKey(ecParams, privKey, privKeyBytes, len));
++    CHECK_SEC_OK(ec_NewKey(ecParams, privKey, privKeyRand.data, privKeyRand.len));
+ 
+ cleanup:
+-    if (privKeyBytes) {
+-        PORT_ZFree(privKeyBytes, len);
++    if (privKeyRand.data) {
++        SECITEM_ZfreeItem(&privKeyRand, PR_FALSE);
+     }
+ #if EC_DEBUG
+     printf("EC_NewKey returning %s\n",
+@@ -439,12 +485,12 @@
+     /* Uses curve specific code for point validation. */
+     if (ecParams->fieldID.type == ec_field_plain) {
+         const ECMethod *method = ec_get_method_from_name(ecParams->name);
+-        if (method == NULL || method->validate == NULL) {
++        if (method == NULL || method->pt_validate == NULL) {
+             /* unknown curve */
+             PORT_SetError(SEC_ERROR_INVALID_ARGS);
+             return SECFailure;
+         }
+-        return method->validate(publicValue);
++        return method->pt_validate(publicValue);
+     }
+ 
+     /* NOTE: We only support uncompressed points for now */
+@@ -563,12 +609,12 @@
+             return SECFailure;
+         }
+         method = ec_get_method_from_name(ecParams->name);
+-        if (method == NULL || method->validate == NULL ||
+-            method->mul == NULL) {
++        if (method == NULL || method->pt_validate == NULL ||
++            method->pt_mul == NULL) {
+             PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
+             return SECFailure;
+         }
+-        rv = method->mul(derivedSecret, privateValue, publicValue);
++        rv = method->pt_mul(derivedSecret, privateValue, publicValue);
+         if (rv != SECSuccess) {
+             SECITEM_ZfreeItem(derivedSecret, PR_FALSE);
+         }
+@@ -886,8 +932,7 @@
+ ECDSA_SignDigest(ECPrivateKey *key, SECItem *signature, const SECItem *digest)
+ {
+     SECStatus rv = SECFailure;
+-    int len;
+-    unsigned char *kBytes = NULL;
++    SECItem nonceRand = { siBuffer, NULL, 0 };
+ 
+     if (!key) {
+         PORT_SetError(SEC_ERROR_INVALID_ARGS);
+@@ -895,17 +940,22 @@
+     }
+ 
+     /* Generate random value k */
+-    len = key->ecParams.order.len;
+-    kBytes = ec_GenerateRandomPrivateKey(key->ecParams.order.data, len);
+-    if (kBytes == NULL)
++    SECITEM_AllocItem(NULL, &nonceRand, EC_GetScalarSize(&key->ecParams));
++    if (nonceRand.data == NULL) {
++        PORT_SetError(SEC_ERROR_NO_MEMORY);
++        rv = SECFailure;
++        goto cleanup;
++    }
++    rv = ec_GenerateRandomPrivateKey(&key->ecParams, &nonceRand);
++    if (rv != SECSuccess || nonceRand.data == NULL)
+         goto cleanup;
+ 
+     /* Generate ECDSA signature with the specified k value */
+-    rv = ECDSA_SignDigestWithSeed(key, signature, digest, kBytes, len);
++    rv = ECDSA_SignDigestWithSeed(key, signature, digest, nonceRand.data, nonceRand.len);
+ 
+ cleanup:
+-    if (kBytes) {
+-        PORT_ZFree(kBytes, len);
++    if (nonceRand.data) {
++        SECITEM_ZfreeItem(&nonceRand, PR_FALSE);
+     }
+ 
+ #if EC_DEBUG
+--- a/lib/freebl/ec.h
++++ b/lib/freebl/ec.h
+@@ -13,8 +13,9 @@
+ 
+ struct ECMethodStr {
+     ECCurveName name;
+-    SECStatus (*mul)(SECItem *result, SECItem *scalar, SECItem *point);
+-    SECStatus (*validate)(const SECItem *point);
++    SECStatus (*pt_mul)(SECItem *result, SECItem *scalar, SECItem *point);
++    SECStatus (*pt_validate)(const SECItem *point);
++    SECStatus (*scalar_validate)(const SECItem *scalar);
+ };
+ typedef struct ECMethodStr ECMethod;
+ 
+--- a/lib/freebl/ecl/ecl.h
++++ b/lib/freebl/ecl/ecl.h
+@@ -45,5 +45,6 @@
+ 
+ SECStatus ec_Curve25519_pt_mul(SECItem *X, SECItem *k, SECItem *P);
+ SECStatus ec_Curve25519_pt_validate(const SECItem *px);
++SECStatus ec_Curve25519_scalar_validate(const SECItem *scalar);
+ 
+ #endif /* __ecl_h_ */
+--- a/lib/freebl/ecl/ecp_25519.c
++++ b/lib/freebl/ecl/ecp_25519.c
+@@ -15,6 +15,7 @@
+ #include "mpi-priv.h"
+ #include "secmpi.h"
+ #include "secitem.h"
++#include "secerr.h"
+ #include "secport.h"
+ #include <stdlib.h>
+ #include <stdio.h>
+@@ -94,6 +95,24 @@
+     return SECSuccess;
+ }
+ 
++/*
++ * scalar validation is not necessary.
++ */
++SECStatus
++ec_Curve25519_scalar_validate(const SECItem *scalar)
++{
++    if (!scalar || !scalar->data) {
++        PORT_SetError(SEC_ERROR_INVALID_ARGS);
++        return SECFailure;
++    }
++
++    if (scalar->len != 32) {
++        PORT_SetError(SEC_ERROR_BAD_KEY);
++        return SECFailure;
++    }
++    return SECSuccess;
++}
++
+ /*
+  * Scalar multiplication for Curve25519.
+  * If P == NULL, the base point is used.
+--- a/lib/freebl/blapi.h
++++ b/lib/freebl/blapi.h
+@@ -1695,6 +1695,12 @@
+  */
+ extern int EC_GetPointSize(const ECParams *params);
+ 
++// needed for the patch for CVE-2023-6135
++/*
++ * use the internal table to get the size in bytes of a single EC coordinate
++ */
++extern int EC_GetScalarSize(const ECParams *params);
++
+ SEC_END_PROTOS
+ 
+ #endif /* _BLAPI_H_ */
+--- a/lib/freebl/ecdecode.c
++++ b/lib/freebl/ecdecode.c
+@@ -250,3 +250,19 @@
+     }
+     return curveParams->pointSize - 1;
+ }
++
++int
++EC_GetScalarSize(const ECParams *params)
++{
++    ECCurveName name = params->name;
++    const ECCurveBytes *curveParams;
++
++    if ((name < ECCurve_noName) || (name > ECCurve_pastLastCurve) ||
++        ((curveParams = ecCurve_map[name]) == NULL)) {
++        /* unknown curve, calculate scalar size from field size in params */
++        int sizeInBytes = (params->fieldID.size + 7) / 8;
++        return sizeInBytes;
++    }
++    return curveParams->scalarSize;
++}
++
diff --git a/dev-libs/nss/files/nss-3.73-CVE-2023-6135-part2.patch b/dev-libs/nss/files/nss-3.73-CVE-2023-6135-part2.patch
new file mode 100644
index 0000000..6c3ce54
--- /dev/null
+++ b/dev-libs/nss/files/nss-3.73-CVE-2023-6135-part2.patch
@@ -0,0 +1,147 @@
+Description:  Upstream patch for CVE-2023-6125, part 2
+ NOTE: It is unclear what exactly are the fixing parts, and
+ the version in buster has only support for Curve25519 and not
+ for ECCurve_NIST_P256 (and NIST_P384 and NIST_P521.)
+ Therefore this patch is currently not applied, until more
+ information is available, but it is kept for later reference.
+
+# HG changeset patch
+# User John Schanck <jschanck@mozilla.com>
+# Date 1699567562 0
+# Node ID 39f0db972e9d4803f386585bc4d8858ad6f019b8
+# Parent  e68b42b773657000078d104aaccbe26e71a1e0be
+Bug 1863605 - Include P-384 and P-521 Scalar Validation from HACL*. r=nkulatova
+
+Differential Revision: https://phabricator.services.mozilla.com/D192985
+
+--- a/lib/freebl/ec.c
++++ b/lib/freebl/ec.c
+@@ -19,7 +19,8 @@
+     { ECCurve25519,
+       ec_Curve25519_pt_mul,
+       ec_Curve25519_pt_validate,
+-      ec_Curve25519_scalar_validate }
++      ec_Curve25519_scalar_validate
++    }
+ };
+ 
+ static const ECMethod *
+@@ -332,8 +333,8 @@
+ SECStatus
+ ec_GenerateRandomPrivateKey(ECParams *ecParams, SECItem *privKey)
+ {
+-    SECStatus rv = SECSuccess;
+-    mp_err err;
++
++    SECStatus rv = SECFailure;
+ 
+     unsigned int len = EC_GetScalarSize(ecParams);
+ 
+@@ -342,82 +343,36 @@
+         return SECFailure;
+     }
+ 
+-    /* For known curves, use rejection sampling A.4.2 */
+-    if (ecParams->fieldID.type == ec_field_plain) {
+-        const ECMethod *method = ec_get_method_from_name(ecParams->name);
+-        rv = SECFailure;
+-        if (method == NULL || method->scalar_validate == NULL) {
+-            /* unknown curve */
+-            PORT_SetError(SEC_ERROR_INVALID_ARGS);
+-            goto done;
+-        }
+-        int count = 100;
+-        while (rv != SECSuccess && count >= 0) {
+-            rv = RNG_GenerateGlobalRandomBytes(privKey->data, len);
+-            if (rv != SECSuccess) {
+-                PORT_SetError(SEC_ERROR_NEED_RANDOM);
+-                goto done;
+-            }
+-            rv = method->scalar_validate(privKey);
+-            count--;
+-        }
+-        if (rv != SECSuccess) {
+-            PORT_SetError(SEC_ERROR_BAD_KEY);
+-        }
+-        goto done;
++    const ECMethod *method = ec_get_method_from_name(ecParams->name);
++    if (method == NULL || method->scalar_validate == NULL) {
++        PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
++        return SECFailure;
+     }
+ 
+-    /* For unknown curves, use algotithm A.4.1 */
+-
+-    unsigned char *order = ecParams->order.data;
+-    mp_int privKeyVal, order_1, one;
+-
+-    unsigned char *privKeyBytes = NULL;
+-
+-    MP_DIGITS(&privKeyVal) = 0;
+-    MP_DIGITS(&order_1) = 0;
+-    MP_DIGITS(&one) = 0;
+-    CHECK_MPI_OK(mp_init(&privKeyVal));
+-    CHECK_MPI_OK(mp_init(&order_1));
+-    CHECK_MPI_OK(mp_init(&one));
+-
+-    /* Generates 2*len random bytes using the global random bit generator
+-     * (which implements Algorithm 1 of FIPS 186-2 Change Notice 1) then
+-     * reduces modulo the group order.
+-     */
+-
+-    if ((privKeyBytes = PORT_Alloc(2 * len)) == NULL) {
+-        PORT_SetError(SEC_ERROR_NO_MEMORY);
+-        rv = SECFailure;
+-        goto cleanup;
++    uint8_t leading_coeff_mask;
++    switch (ecParams->name) {
++        case ECCurve25519:
++            leading_coeff_mask = 0xff;
++            break;
++        default:
++            PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
++            return SECFailure;
+     }
+ 
+-    CHECK_SEC_OK(RNG_GenerateGlobalRandomBytes(privKeyBytes, 2 * len));
+-    CHECK_MPI_OK(mp_read_unsigned_octets(&privKeyVal, privKeyBytes, 2 * len));
+-    CHECK_MPI_OK(mp_read_unsigned_octets(&order_1, order, len));
+-    CHECK_MPI_OK(mp_set_int(&one, 1));
+-    CHECK_MPI_OK(mp_sub(&order_1, &one, &order_1));
+-    CHECK_MPI_OK(mp_mod(&privKeyVal, &order_1, &privKeyVal));
+-    CHECK_MPI_OK(mp_add(&privKeyVal, &one, &privKeyVal));
+-    CHECK_MPI_OK(mp_to_fixlen_octets(&privKeyVal, privKeyBytes, len));
+-    memcpy(privKey->data, privKeyBytes, len);
+-
+-cleanup:
+-    mp_clear(&privKeyVal);
+-    mp_clear(&order_1);
+-    mp_clear(&one);
+-    if (privKeyBytes) {
+-        PORT_ZFree(privKeyBytes, 2 * len);
+-    }
+-    if (err < MP_OKAY) {
+-        MP_TO_SEC_ERROR(err);
+-        rv = SECFailure;
+-    }
++    /* The rejection sampling method from FIPS 186-5 A.4.2 */
++    int count = 100;
++    do {
++        rv = RNG_GenerateGlobalRandomBytes(privKey->data, len);
++        if (rv != SECSuccess) {
++            PORT_SetError(SEC_ERROR_NEED_RANDOM);
++            return SECFailure;
++        }
++        privKey->data[0] &= leading_coeff_mask;
++        rv = method->scalar_validate(privKey);
++    } while (rv != SECSuccess && --count > 0);
+ 
+-done:
+-    if (rv != SECSuccess && privKey->data) {
+-        SECITEM_ZfreeItem(privKey, PR_FALSE);
+-        return rv;
++    if (rv != SECSuccess) { // implies count == 0
++        PORT_SetError(SEC_ERROR_BAD_KEY);
+     }
+     return rv;
+ }
diff --git a/dev-libs/nss/files/nss-3.73-CVE-2024-0743.patch b/dev-libs/nss/files/nss-3.73-CVE-2024-0743.patch
new file mode 100644
index 0000000..90d9c2b
--- /dev/null
+++ b/dev-libs/nss/files/nss-3.73-CVE-2024-0743.patch
@@ -0,0 +1,38 @@
+
+# HG changeset patch
+# User John Schanck <jschanck@mozilla.com>
+# Date 1702322654 0
+# Node ID 1bda168c0da97e19e5f14bc4227c15c0a9f493bf
+# Parent  e934c6d1d4366d152e3307cb76af4c02667c9147
+Bug 1867408 - add a defensive check for large ssl_DefSend return values. r=nkulatova
+
+Differential Revision: https://phabricator.services.mozilla.com/D195054
+
+diff --git a/lib/ssl/sslsecur.c b/lib/ssl/sslsecur.c
+--- a/lib/ssl/sslsecur.c
++++ b/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/dev-libs/nss/nss-3.73-r1.ebuild b/dev-libs/nss/nss-3.73-r2.ebuild
similarity index 100%
rename from dev-libs/nss/nss-3.73-r1.ebuild
rename to dev-libs/nss/nss-3.73-r2.ebuild
diff --git a/dev-libs/nss/nss-3.73.ebuild b/dev-libs/nss/nss-3.73.ebuild
index 34c8539..06a6084 100644
--- a/dev-libs/nss/nss-3.73.ebuild
+++ b/dev-libs/nss/nss-3.73.ebuild
@@ -41,6 +41,11 @@
 	"${FILESDIR}/${PN}-3.21-gentoo-fixup-warnings.patch"
 	"${FILESDIR}/${PN}-3.23-hppa-byte_order.patch"
 	"${FILESDIR}/${PN}-3.44-prefer-writable-tokens-for-trust.patch"
+	"${FILESDIR}/${PN}-3.73-CVE-2023-0767.patch"
+	"${FILESDIR}/${PN}-3.73-CVE-2023-5388.patch"
+	"${FILESDIR}/${PN}-3.73-CVE-2023-6135-part1.patch"
+	"${FILESDIR}/${PN}-3.73-CVE-2023-6135-part2.patch"
+	"${FILESDIR}/${PN}-3.73-CVE-2024-0743.patch"
 )
 
 src_prepare() {