summaryrefslogtreecommitdiffstats
path: root/security/nss/lib/freebl
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/lib/freebl')
-rw-r--r--security/nss/lib/freebl/ctr.c21
-rw-r--r--security/nss/lib/freebl/freebl.gyp35
-rw-r--r--security/nss/lib/freebl/freebl_base.gypi7
-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
-rw-r--r--security/nss/lib/freebl/rsapkcs.c68
7 files changed, 148 insertions, 85 deletions
diff --git a/security/nss/lib/freebl/ctr.c b/security/nss/lib/freebl/ctr.c
index b7167d4c4..d7652c060 100644
--- a/security/nss/lib/freebl/ctr.c
+++ b/security/nss/lib/freebl/ctr.c
@@ -219,15 +219,18 @@ CTR_Update_HW_AES(CTRContext *ctr, unsigned char *outbuf,
PORT_Assert(ctr->bufPtr == blocksize);
}
- intel_aes_ctr_worker(((AESContext *)(ctr->context))->Nr)(
- ctr, outbuf, outlen, maxout, inbuf, inlen, blocksize);
- /* XXX intel_aes_ctr_worker should set *outlen. */
- PORT_Assert(*outlen == 0);
- fullblocks = (inlen / blocksize) * blocksize;
- *outlen += fullblocks;
- outbuf += fullblocks;
- inbuf += fullblocks;
- inlen -= fullblocks;
+ if (inlen >= blocksize) {
+ rv = intel_aes_ctr_worker(((AESContext *)(ctr->context))->Nr)(
+ ctr, outbuf, outlen, maxout, inbuf, inlen, blocksize);
+ if (rv != SECSuccess) {
+ return SECFailure;
+ }
+ fullblocks = (inlen / blocksize) * blocksize;
+ *outlen += fullblocks;
+ outbuf += fullblocks;
+ inbuf += fullblocks;
+ inlen -= fullblocks;
+ }
if (inlen == 0) {
return SECSuccess;
diff --git a/security/nss/lib/freebl/freebl.gyp b/security/nss/lib/freebl/freebl.gyp
index 004807483..288ff07a3 100644
--- a/security/nss/lib/freebl/freebl.gyp
+++ b/security/nss/lib/freebl/freebl.gyp
@@ -7,6 +7,30 @@
],
'targets': [
{
+ 'target_name': 'intel-gcm-s_lib',
+ 'type': 'static_library',
+ 'sources': [
+ 'intel-aes.s',
+ 'intel-gcm.s',
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ],
+ 'conditions': [
+ [ 'cc_is_clang==1', {
+ 'cflags': [
+ '-no-integrated-as',
+ ],
+ 'cflags_mozilla': [
+ '-no-integrated-as',
+ ],
+ 'asflags_mozilla': [
+ '-no-integrated-as',
+ ],
+ }],
+ ],
+ },
+ {
'target_name': 'intel-gcm-wrap_c_lib',
'type': 'static_library',
'sources': [
@@ -15,12 +39,19 @@
'dependencies': [
'<(DEPTH)/exports.gyp:nss_exports'
],
+ 'conditions': [
+ [ '(OS=="linux" or OS=="android") and target_arch=="x64"', {
+ 'dependencies': [
+ 'intel-gcm-s_lib',
+ ],
+ }],
+ ],
'cflags': [
- '-mssse3'
+ '-mssse3',
],
'cflags_mozilla': [
'-mssse3'
- ]
+ ],
},
{
# TODO: make this so that all hardware accelerated code is in here.
diff --git a/security/nss/lib/freebl/freebl_base.gypi b/security/nss/lib/freebl/freebl_base.gypi
index 1372994f4..76df71497 100644
--- a/security/nss/lib/freebl/freebl_base.gypi
+++ b/security/nss/lib/freebl/freebl_base.gypi
@@ -67,14 +67,12 @@
[ 'target_arch=="x64"', {
'sources': [
'arcfour-amd64-gas.s',
- 'intel-aes.s',
- 'intel-gcm.s',
'mpi/mpi_amd64.c',
'mpi/mpi_amd64_gas.s',
'mpi/mp_comba.c',
],
'conditions': [
- [ 'cc_is_clang==1', {
+ [ 'cc_is_clang==1 and fuzz!=1', {
'cflags': [
'-no-integrated-as',
],
@@ -114,8 +112,7 @@
'intel-gcm-x64-masm.asm',
],
}],
- [ 'cc_use_gnu_ld!=1 and target_arch!="x64"', {
- # not x64
+ [ 'cc_use_gnu_ld!=1 and target_arch=="ia32"', {
'sources': [
'mpi/mpi_x86_asm.c',
'intel-aes-x86-masm.asm',
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
diff --git a/security/nss/lib/freebl/rsapkcs.c b/security/nss/lib/freebl/rsapkcs.c
index ad18c8b73..875e4e28d 100644
--- a/security/nss/lib/freebl/rsapkcs.c
+++ b/security/nss/lib/freebl/rsapkcs.c
@@ -938,48 +938,56 @@ RSA_DecryptBlock(RSAPrivateKey *key,
const unsigned char *input,
unsigned int inputLen)
{
- SECStatus rv;
+ PRInt8 rv;
unsigned int modulusLen = rsa_modulusLen(&key->modulus);
unsigned int i;
- unsigned char *buffer;
+ unsigned char *buffer = NULL;
+ unsigned int outLen = 0;
+ unsigned int copyOutLen = modulusLen - 11;
- if (inputLen != modulusLen)
- goto failure;
+ if (inputLen != modulusLen || modulusLen < 10) {
+ return SECFailure;
+ }
- buffer = (unsigned char *)PORT_Alloc(modulusLen + 1);
- if (!buffer)
- goto failure;
+ if (copyOutLen > maxOutputLen) {
+ copyOutLen = maxOutputLen;
+ }
- rv = RSA_PrivateKeyOp(key, buffer, input);
- if (rv != SECSuccess)
- goto loser;
+ // Allocate enough space to decrypt + copyOutLen to allow copying outLen later.
+ buffer = PORT_ZAlloc(modulusLen + 1 + copyOutLen);
+ if (!buffer) {
+ return SECFailure;
+ }
- /* XXX(rsleevi): Constant time */
- if (buffer[0] != RSA_BLOCK_FIRST_OCTET ||
- buffer[1] != (unsigned char)RSA_BlockPublic) {
- goto loser;
+ // rv is 0 if everything is going well and 1 if an error occurs.
+ rv = RSA_PrivateKeyOp(key, buffer, input) != SECSuccess;
+ rv |= (buffer[0] != RSA_BLOCK_FIRST_OCTET) |
+ (buffer[1] != (unsigned char)RSA_BlockPublic);
+
+ // There have to be at least 8 bytes of padding.
+ for (i = 2; i < 10; i++) {
+ rv |= buffer[i] == RSA_BLOCK_AFTER_PAD_OCTET;
}
- *outputLen = 0;
- for (i = 2; i < modulusLen; i++) {
- if (buffer[i] == RSA_BLOCK_AFTER_PAD_OCTET) {
- *outputLen = modulusLen - i - 1;
- break;
- }
+
+ for (i = 10; i < modulusLen; i++) {
+ unsigned int newLen = modulusLen - i - 1;
+ unsigned int c = (buffer[i] == RSA_BLOCK_AFTER_PAD_OCTET) & (outLen == 0);
+ outLen = constantTimeCondition(c, newLen, outLen);
}
- if (*outputLen == 0)
- goto loser;
- if (*outputLen > maxOutputLen)
- goto loser;
+ rv |= outLen == 0;
+ rv |= outLen > maxOutputLen;
- PORT_Memcpy(output, buffer + modulusLen - *outputLen, *outputLen);
+ // Note that output is set even if SECFailure is returned.
+ PORT_Memcpy(output, buffer + modulusLen - outLen, copyOutLen);
+ *outputLen = constantTimeCondition(outLen > maxOutputLen, maxOutputLen,
+ outLen);
PORT_Free(buffer);
- return SECSuccess;
-loser:
- PORT_Free(buffer);
-failure:
- return SECFailure;
+ for (i = 1; i < sizeof(rv) * 8; i <<= 1) {
+ rv |= rv << i;
+ }
+ return (SECStatus)rv;
}
/*