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() {