summaryrefslogtreecommitdiffstats
path: root/security/nss/lib/freebl/mpi
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/lib/freebl/mpi')
-rw-r--r--security/nss/lib/freebl/mpi/mpi.c61
-rw-r--r--security/nss/lib/freebl/mpi/mpi.h3
-rw-r--r--security/nss/lib/freebl/mpi/mpi_arm.c38
3 files changed, 63 insertions, 39 deletions
diff --git a/security/nss/lib/freebl/mpi/mpi.c b/security/nss/lib/freebl/mpi/mpi.c
index 8c893fb5f..401eac51d 100644
--- a/security/nss/lib/freebl/mpi/mpi.c
+++ b/security/nss/lib/freebl/mpi/mpi.c
@@ -4775,38 +4775,61 @@ mp_to_signed_octets(const mp_int *mp, unsigned char *str, mp_size maxlen)
/* }}} */
/* {{{ mp_to_fixlen_octets(mp, str) */
-/* output a buffer of big endian octets exactly as long as requested. */
+/* output a buffer of big endian octets exactly as long as requested.
+ constant time on the value of mp. */
mp_err
mp_to_fixlen_octets(const mp_int *mp, unsigned char *str, mp_size length)
{
- int ix, pos = 0;
+ int ix, jx;
unsigned int bytes;
- ARGCHK(mp != NULL && str != NULL && !SIGN(mp), MP_BADARG);
-
- bytes = mp_unsigned_octet_size(mp);
- ARGCHK(bytes <= length, MP_BADARG);
+ ARGCHK(mp != NULL, MP_BADARG);
+ ARGCHK(str != NULL, MP_BADARG);
+ ARGCHK(!SIGN(mp), MP_BADARG);
+ ARGCHK(length > 0, MP_BADARG);
+
+ /* Constant time on the value of mp. Don't use mp_unsigned_octet_size. */
+ bytes = USED(mp) * MP_DIGIT_SIZE;
+
+ /* If the output is shorter than the native size of mp, then check that any
+ * bytes not written have zero values. This check isn't constant time on
+ * the assumption that timing-sensitive callers can guarantee that mp fits
+ * in the allocated space. */
+ ix = USED(mp) - 1;
+ if (bytes > length) {
+ unsigned int zeros = bytes - length;
+
+ while (zeros >= MP_DIGIT_SIZE) {
+ ARGCHK(DIGIT(mp, ix) == 0, MP_BADARG);
+ zeros -= MP_DIGIT_SIZE;
+ ix--;
+ }
- /* place any needed leading zeros */
- for (; length > bytes; --length) {
- *str++ = 0;
+ if (zeros > 0) {
+ mp_digit d = DIGIT(mp, ix);
+ mp_digit m = ~0ULL << ((MP_DIGIT_SIZE - zeros) * CHAR_BIT);
+ ARGCHK((d & m) == 0, MP_BADARG);
+ for (jx = MP_DIGIT_SIZE - zeros - 1; jx >= 0; jx--) {
+ *str++ = d >> (jx * CHAR_BIT);
+ }
+ ix--;
+ }
+ } else if (bytes < length) {
+ /* Place any needed leading zeros. */
+ unsigned int zeros = length - bytes;
+ memset(str, 0, zeros);
+ str += zeros;
}
- /* Iterate over each digit... */
- for (ix = USED(mp) - 1; ix >= 0; ix--) {
+ /* Iterate over each whole digit... */
+ for (; ix >= 0; ix--) {
mp_digit d = DIGIT(mp, ix);
- int jx;
/* Unpack digit bytes, high order first */
- for (jx = sizeof(mp_digit) - 1; jx >= 0; jx--) {
- unsigned char x = (unsigned char)(d >> (jx * CHAR_BIT));
- if (!pos && !x) /* suppress leading zeros */
- continue;
- str[pos++] = x;
+ for (jx = MP_DIGIT_SIZE - 1; jx >= 0; jx--) {
+ *str++ = d >> (jx * CHAR_BIT);
}
}
- if (!pos)
- str[pos++] = 0;
return MP_OKAY;
} /* end mp_to_fixlen_octets() */
/* }}} */
diff --git a/security/nss/lib/freebl/mpi/mpi.h b/security/nss/lib/freebl/mpi/mpi.h
index 97af0f069..d5aef46d7 100644
--- a/security/nss/lib/freebl/mpi/mpi.h
+++ b/security/nss/lib/freebl/mpi/mpi.h
@@ -128,7 +128,8 @@ typedef int mp_sword;
#define MP_WORD_MAX UINT_MAX
#endif
-#define MP_DIGIT_BIT (CHAR_BIT * sizeof(mp_digit))
+#define MP_DIGIT_SIZE sizeof(mp_digit)
+#define MP_DIGIT_BIT (CHAR_BIT * MP_DIGIT_SIZE)
#define MP_WORD_BIT (CHAR_BIT * sizeof(mp_word))
#define MP_RADIX (1 + (mp_word)MP_DIGIT_MAX)
diff --git a/security/nss/lib/freebl/mpi/mpi_arm.c b/security/nss/lib/freebl/mpi/mpi_arm.c
index b5139f28d..27e4efdad 100644
--- a/security/nss/lib/freebl/mpi/mpi_arm.c
+++ b/security/nss/lib/freebl/mpi/mpi_arm.c
@@ -29,17 +29,17 @@ s_mpv_mul_d(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c)
"1:\n"
"mov r4, #0\n"
"ldr r6, [%0], #4\n"
- "umlal r5, r4, r6, %2\n"
- "str r5, [%3], #4\n"
+ "umlal r5, r4, r6, %3\n"
+ "str r5, [%2], #4\n"
"mov r5, r4\n"
"subs %1, #1\n"
"bne 1b\n"
"2:\n"
- "str r5, [%3]\n"
- :
- : "r"(a), "r"(a_len), "r"(b), "r"(c)
+ "str r5, [%2]\n"
+ : "+r"(a), "+l"(a_len), "+r"(c)
+ : "r"(b)
: "memory", "cc", "%r4", "%r5", "%r6");
}
@@ -57,22 +57,22 @@ s_mpv_mul_d_add(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c)
"1:\n"
"mov r4, #0\n"
- "ldr r6, [%3]\n"
+ "ldr r6, [%2]\n"
"adds r5, r6\n"
"adc r4, r4, #0\n"
"ldr r6, [%0], #4\n"
- "umlal r5, r4, r6, %2\n"
- "str r5, [%3], #4\n"
+ "umlal r5, r4, r6, %3\n"
+ "str r5, [%2], #4\n"
"mov r5, r4\n"
"subs %1, #1\n"
"bne 1b\n"
"2:\n"
- "str r5, [%3]\n"
- :
- : "r"(a), "r"(a_len), "r"(b), "r"(c)
+ "str r5, [%2]\n"
+ : "+r"(a), "+l"(a_len), "+r"(c)
+ : "r"(b)
: "memory", "cc", "%r4", "%r5", "%r6");
}
@@ -87,12 +87,12 @@ s_mpv_mul_d_add_prop(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c)
"1:\n"
"mov r4, #0\n"
- "ldr r6, [%3]\n"
+ "ldr r6, [%2]\n"
"adds r5, r6\n"
"adc r4, r4, #0\n"
"ldr r6, [%0], #4\n"
- "umlal r5, r4, r6, %2\n"
- "str r5, [%3], #4\n"
+ "umlal r5, r4, r6, %3\n"
+ "str r5, [%2], #4\n"
"mov r5, r4\n"
"subs %1, #1\n"
@@ -107,16 +107,16 @@ s_mpv_mul_d_add_prop(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c)
"2:\n"
"mov r4, #0\n"
- "ldr r6, [%3]\n"
+ "ldr r6, [%2]\n"
"adds r5, r6\n"
"adc r4, r4, #0\n"
- "str r5, [%3], #4\n"
+ "str r5, [%2], #4\n"
"movs r5, r4\n"
"bne 2b\n"
"3:\n"
- :
- : "r"(a), "r"(a_len), "r"(b), "r"(c)
+ : "+r"(a), "+l"(a_len), "+r"(c)
+ : "r"(b)
: "memory", "cc", "%r4", "%r5", "%r6");
}
#endif
@@ -167,8 +167,8 @@ s_mpv_sqr_add_prop(const mp_digit *pa, mp_size a_len, mp_digit *ps)
"bne 2b\n"
"3:"
+ : "+r"(pa), "+r"(a_len), "+r"(ps)
:
- : "r"(pa), "r"(a_len), "r"(ps)
: "memory", "cc", "%r3", "%r4", "%r5", "%r6");
}
#endif