cherry-picked mozilla NSS upstream changes (to rev 632864c9, which is on par with 3.21.4):

bug1221620, bug1244324, bug1241034, bug1206283, bug1241037, bug1245528, bug1293334, bug1306103, bug1345089, bug1344380
This commit is contained in:
Roy Tam 2020-01-07 22:30:39 +08:00
parent 9b2e59866b
commit 6712ac7edb
12 changed files with 245 additions and 54 deletions

View File

@ -61,6 +61,12 @@ ifndef WARNING_CFLAGS
ifeq ($(NSS_ENABLE_WERROR),1)
WARNING_CFLAGS += -Werror
# For gcc 6 and newer we need -Wno-error=misleading-indentation
# to prevent compiler errors caused by mixed whitespace.
CC_VERSION := $(subst ., ,$(shell $(CC) -dumpversion))
ifeq (,$(filter 0 1 2 3 4 5,$(word 1,$(CC_VERSION))))
WARNING_CFLAGS += -Wno-error=misleading-indentation
endif
else
# Old versions of gcc (< 4.8) don't support #pragma diagnostic in functions.
# Use this to disable use of that #pragma and the warnings it suppresses.

View File

@ -1444,6 +1444,12 @@ FIPS186Change_ReduceModQForDSA(const unsigned char *w,
const unsigned char *q,
unsigned char *xj);
/* To allow NIST KAT tests */
extern SECStatus
PRNGTEST_Instantiate_Kat(const PRUint8 *entropy, unsigned int entropy_len,
const PRUint8 *nonce, unsigned int nonce_len,
const PRUint8 *personal_string, unsigned int ps_len);
/*
* The following functions are for FIPS poweron self test and FIPS algorithm
* testing.

View File

@ -96,7 +96,8 @@ struct RNGContextStr {
* RNG_RandomUpdate. */
PRUint8 additionalDataCache[PRNG_ADDITONAL_DATA_CACHE_SIZE];
PRUint32 additionalAvail;
PRBool isValid; /* false if RNG reaches an invalid state */
PRBool isValid; /* false if RNG reaches an invalid state */
PRBool isKatTest; /* true if running NIST PRNG KAT tests */
};
typedef struct RNGContextStr RNGContext;
@ -149,7 +150,7 @@ prng_Hash_df(PRUint8 *requested_bytes, unsigned int no_of_bytes_to_return,
/*
* Hash_DRBG Instantiate NIST SP 800-80 10.1.1.2
* Hash_DRBG Instantiate NIST SP 800-90 10.1.1.2
*
* NOTE: bytes & len are entropy || nonce || personalization_string. In
* normal operation, NSS calculates them all together in a single call.
@ -157,9 +158,11 @@ prng_Hash_df(PRUint8 *requested_bytes, unsigned int no_of_bytes_to_return,
static SECStatus
prng_instantiate(RNGContext *rng, const PRUint8 *bytes, unsigned int len)
{
if (len < PRNG_SEEDLEN) {
/* if the seedlen is to small, it's probably because we failed to get
* enough random data */
if (!rng->isKatTest && len < PRNG_SEEDLEN) {
/* If the seedlen is too small, it's probably because we failed to get
* enough random data.
* This is stricter than NIST SP800-90A requires. Don't enforce it for
* tests. */
PORT_SetError(SEC_ERROR_NEED_RANDOM);
return SECFailure;
}
@ -272,7 +275,7 @@ prng_reseed_test(RNGContext *rng, const PRUint8 *entropy,
#define PRNG_ADD_BITS_AND_CARRY(dest, dest_len, add, len, carry) \
PRNG_ADD_BITS(dest, dest_len, add, len, carry) \
PRNG_ADD_CARRY_ONLY(dest, dest_len - len, carry)
PRNG_ADD_CARRY_ONLY(dest, dest_len - len - 1, carry)
/*
* This function expands the internal state of the prng to fulfill any number
@ -423,6 +426,7 @@ static PRStatus rng_init(void)
}
/* the RNG is in a valid state */
globalrng->isValid = PR_TRUE;
globalrng->isKatTest = PR_FALSE;
/* fetch one random value so that we can populate rng->oldV for our
* continous random number test. */
@ -667,6 +671,17 @@ RNG_RNGShutdown(void)
* entropy we may have previously collected. */
RNGContext testContext;
SECStatus
PRNGTEST_Instantiate_Kat(const PRUint8 *entropy, unsigned int entropy_len,
const PRUint8 *nonce, unsigned int nonce_len,
const PRUint8 *personal_string, unsigned int ps_len)
{
testContext.isKatTest = PR_TRUE;
return PRNGTEST_Instantiate(entropy, entropy_len,
nonce, nonce_len,
personal_string, ps_len);
}
/*
* Test vector API. Use NIST SP 800-90 general interface so one of the
* other NIST SP 800-90 algorithms may be used in the future.

View File

@ -36,10 +36,10 @@
* The format of the version string should be
* "<major version>.<minor version>[.<patch level>[.<build number>]][ <ECC>][ <Beta>]"
*/
#define NSS_VERSION "3.21" _NSS_ECC_STRING _NSS_CUSTOMIZED
#define NSS_VERSION "3.21.4" _NSS_ECC_STRING _NSS_CUSTOMIZED
#define NSS_VMAJOR 3
#define NSS_VMINOR 21
#define NSS_VPATCH 0
#define NSS_VPATCH 4
#define NSS_VBUILD 0
#define NSS_BETA PR_FALSE

View File

@ -25,10 +25,10 @@
* The format of the version string should be
* "<major version>.<minor version>[.<patch level>[.<build number>]][ <ECC>][ <Beta>]"
*/
#define SOFTOKEN_VERSION "3.21" SOFTOKEN_ECC_STRING
#define SOFTOKEN_VERSION "3.21.4" SOFTOKEN_ECC_STRING
#define SOFTOKEN_VMAJOR 3
#define SOFTOKEN_VMINOR 21
#define SOFTOKEN_VPATCH 0
#define SOFTOKEN_VPATCH 4
#define SOFTOKEN_VBUILD 0
#define SOFTOKEN_BETA PR_FALSE

View File

@ -9963,6 +9963,7 @@ ssl3_HandleDHClientKeyExchange(sslSocket *ss,
CKM_DH_PKCS_DERIVE, target, CKA_DERIVE, 0, NULL);
if (pms == NULL) {
ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
rv = SECFailure;
goto loser;
}
@ -11867,6 +11868,13 @@ ssl_ConstantTimeEQ8(unsigned char a, unsigned char b)
return DUPLICATE_MSB_TO_ALL_8(c);
}
/* ssl_constantTimeSelect return a if mask is 0xFF and b if mask is 0x00 */
static unsigned char
ssl_constantTimeSelect(unsigned char mask, unsigned char a, unsigned char b)
{
return (mask & a) | (~mask & b);
}
static SECStatus
ssl_RemoveSSLv3CBCPadding(sslBuffer *plaintext,
unsigned int blockSize,
@ -11970,22 +11978,54 @@ ssl_CBCExtractMAC(sslBuffer *plaintext,
/* scanStart contains the number of bytes that we can ignore because
* the MAC's position can only vary by 255 bytes. */
unsigned scanStart = 0;
unsigned i, j, divSpoiler;
unsigned i, j;
unsigned char rotateOffset;
if (originalLength > macSize + 255 + 1)
if (originalLength > macSize + 255 + 1) {
scanStart = originalLength - (macSize + 255 + 1);
}
/* divSpoiler contains a multiple of macSize that is used to cause the
* modulo operation to be constant time. Without this, the time varies
* based on the amount of padding when running on Intel chips at least.
*
* The aim of right-shifting macSize is so that the compiler doesn't
* figure out that it can remove divSpoiler as that would require it
* to prove that macSize is always even, which I hope is beyond it. */
divSpoiler = macSize >> 1;
divSpoiler <<= (sizeof(divSpoiler)-1)*8;
rotateOffset = (divSpoiler + macStart - scanStart) % macSize;
/* We want to compute
* rotateOffset = (macStart - scanStart) % macSize
* But the time to compute this varies based on the amount of padding. Thus
* we explicitely handle all mac sizes with (hopefully) constant time modulo
* using Barrett reduction:
* q := (rotateOffset * m) >> k
* rotateOffset -= q * n
* if (n <= rotateOffset) rotateOffset -= n
*/
rotateOffset = macStart - scanStart;
/* rotateOffset < 255 + 1 + 48 = 304 */
if (macSize == 16) {
rotateOffset &= 15;
} else if (macSize == 20) {
/*
* Correctness: rotateOffset * ( 1/20 - 25/2^9 ) < 1
* with rotateOffset <= 853
*/
unsigned q = (rotateOffset * 25) >> 9; /* m = 25, k = 9 */
rotateOffset -= q * 20;
rotateOffset -= ssl_constantTimeSelect(ssl_ConstantTimeGE(rotateOffset, 20),
20, 0);
} else if (macSize == 32) {
rotateOffset &= 31;
} else if (macSize == 48) {
/*
* Correctness: rotateOffset * ( 1/48 - 10/2^9 ) < 1
* with rotateOffset < 768
*/
unsigned q = (rotateOffset * 10) >> 9; /* m = 25, k = 9 */
rotateOffset -= q * 48;
rotateOffset -= ssl_constantTimeSelect(ssl_ConstantTimeGE(rotateOffset, 48),
48, 0);
} else {
/*
* SHA384 (macSize == 48) is the largest we support. We should never
* get here.
*/
PORT_Assert(0);
rotateOffset = rotateOffset % macSize;
}
memset(rotatedMac, 0, macSize);
for (i = scanStart; i < originalLength;) {
@ -12001,12 +12041,16 @@ ssl_CBCExtractMAC(sslBuffer *plaintext,
/* Now rotate the MAC. If we knew that the MAC fit into a CPU cache line
* we could line-align |rotatedMac| and rotate in place. */
memset(out, 0, macSize);
rotateOffset = macSize - rotateOffset;
rotateOffset = ssl_constantTimeSelect(ssl_ConstantTimeGE(rotateOffset, macSize),
0, rotateOffset);
for (i = 0; i < macSize; i++) {
unsigned char offset =
(divSpoiler + macSize - rotateOffset + i) % macSize;
for (j = 0; j < macSize; j++) {
out[j] |= rotatedMac[i] & ssl_ConstantTimeEQ8(j, offset);
}
out[j] |= rotatedMac[i] & ssl_ConstantTimeEQ8(j, rotateOffset);
}
rotateOffset++;
rotateOffset = ssl_constantTimeSelect(ssl_ConstantTimeGE(rotateOffset, macSize),
0, rotateOffset);
}
}

View File

@ -179,10 +179,12 @@ long
DER_GetInteger(const SECItem *it)
{
long ival = 0;
unsigned len = it->len;
PRBool negative = PR_FALSE;
unsigned int len = it->len;
unsigned int originalLength = len;
unsigned char *cp = it->data;
unsigned long overflow = 0x1ffUL << (((sizeof(ival) - 1) * 8) - 1);
unsigned long ofloinit;
unsigned long mask = 1;
PORT_Assert(len);
if (!len) {
@ -190,14 +192,15 @@ DER_GetInteger(const SECItem *it)
return 0;
}
if (*cp & 0x80)
ival = -1L;
ofloinit = ival & overflow;
if (*cp & 0x80) {
negative = PR_TRUE;
overflow <<= 1;
}
while (len) {
if ((ival & overflow) != ofloinit) {
if ((ival & overflow) != 0) {
PORT_SetError(SEC_ERROR_BAD_DER);
if (ival < 0) {
if (negative) {
return LONG_MIN;
}
return LONG_MAX;
@ -206,6 +209,11 @@ DER_GetInteger(const SECItem *it)
ival |= *cp++;
--len;
}
if (negative && ival && (overflow & ival) == 0) {
mask <<= ((originalLength * 8) - 1);
ival &= ~mask;
ival -= mask;
}
return ival;
}

View File

@ -373,7 +373,7 @@ pl_base64_decode_flush (PLBase64Decoder *data)
static PRUint32
PL_Base64MaxDecodedLength (PRUint32 size)
{
return ((size * 3) / 4);
return size * 0.75;
}

View File

@ -285,6 +285,11 @@ PL_Base64MaxEncodedLength (PRUint32 size, PRUint32 line_length)
{
PRUint32 tokens, tokens_per_line, full_lines, line_break_chars, remainder;
/* This is the maximum length we support. */
if (size > 0x3fffffff) {
return 0;
}
tokens = (size + 2) / 3;
if (line_length == 0)
@ -461,6 +466,10 @@ PL_Base64EncodeBuffer (const unsigned char *src, PRUint32 srclen,
* How much space could we possibly need for encoding this input?
*/
need_length = PL_Base64MaxEncodedLength (srclen, line_length);
if (need_length == 0) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return NULL;
}
/*
* Make sure we have at least that much, if output buffer provided.
@ -643,6 +652,10 @@ NSSBase64_EncodeItem (PLArenaPool *arenaOpt, char *outStrOpt,
}
max_out_len = PL_Base64MaxEncodedLength (inItem->len, 64);
if (max_out_len == 0) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return NULL;
}
if (arenaOpt != NULL)
mark = PORT_ArenaMark (arenaOpt);

View File

@ -19,10 +19,10 @@
* The format of the version string should be
* "<major version>.<minor version>[.<patch level>[.<build number>]][ <Beta>]"
*/
#define NSSUTIL_VERSION "3.21"
#define NSSUTIL_VERSION "3.21.4"
#define NSSUTIL_VMAJOR 3
#define NSSUTIL_VMINOR 21
#define NSSUTIL_VPATCH 0
#define NSSUTIL_VPATCH 4
#define NSSUTIL_VBUILD 0
#define NSSUTIL_BETA PR_FALSE

View File

@ -14,6 +14,8 @@
#define PR_Assert sec_asn1d_Assert
#endif
#include <limits.h>
#include "secasn1.h"
#include "secerr.h"
@ -1593,6 +1595,7 @@ sec_asn1d_parse_leaf (sec_asn1d_state *state,
item = (SECItem *)(state->dest);
if (item != NULL && item->data != NULL) {
unsigned long offset;
/* Strip leading zeroes when target is unsigned integer */
if (state->underlying_kind == SEC_ASN1_INTEGER && /* INTEGER */
item->len == 0 && /* MSB */
@ -1603,8 +1606,42 @@ sec_asn1d_parse_leaf (sec_asn1d_state *state,
len--;
}
}
PORT_Memcpy (item->data + item->len, buf, len);
item->len += len;
offset = item->len;
if (state->underlying_kind == SEC_ASN1_BIT_STRING) {
// The previous bit string must have no unused bits.
if (item->len & 0x7) {
PORT_SetError (SEC_ERROR_BAD_DER);
state->top->status = decodeError;
return 0;
}
// If this is a bit string, the length is bits, not bytes.
offset = item->len >> 3;
}
if (state->underlying_kind == SEC_ASN1_BIT_STRING) {
unsigned long len_in_bits;
// Protect against overflow during the bytes-to-bits conversion.
if (len >= (ULONG_MAX >> 3) + 1) {
PORT_SetError (SEC_ERROR_BAD_DER);
state->top->status = decodeError;
return 0;
}
len_in_bits = (len << 3) - state->bit_string_unused_bits;
// Protect against overflow when computing the total length in bits.
if (UINT_MAX - item->len < len_in_bits) {
PORT_SetError (SEC_ERROR_BAD_DER);
state->top->status = decodeError;
return 0;
}
item->len += len_in_bits;
} else {
if (UINT_MAX - item->len < len) {
PORT_SetError (SEC_ERROR_BAD_DER);
state->top->status = decodeError;
return 0;
}
item->len += len;
}
PORT_Memcpy (item->data + offset, buf, len);
}
state->pending -= bufLen;
if (state->pending == 0)
@ -1671,14 +1708,6 @@ sec_asn1d_parse_more_bit_string (sec_asn1d_state *state,
}
len = sec_asn1d_parse_leaf (state, buf, len);
if (state->place == beforeEndOfContents && state->dest != NULL) {
SECItem *item;
item = (SECItem *)(state->dest);
if (item->len)
item->len = (item->len << 3) - state->bit_string_unused_bits;
}
return len;
}
@ -2208,7 +2237,7 @@ sec_asn1d_concat_substrings (sec_asn1d_state *state)
* All bit-string substrings except the last one should be
* a clean multiple of 8 bits.
*/
if (is_bit_string && (substring->next == NULL)
if (is_bit_string && (substring->next != NULL)
&& (substring->len & 0x7)) {
PORT_SetError (SEC_ERROR_BAD_DER);
state->top->status = decodeError;

View File

@ -319,10 +319,10 @@ sec_port_ucs2_utf8_conversion_function
}
for( i = 0; i < inBufLen; i += 2 ) {
if( (inBuf[i+H_0] == 0x00) && ((inBuf[i+H_0] & 0x80) == 0x00) ) len += 1;
if( (inBuf[i+H_0] == 0x00) && ((inBuf[i+H_1] & 0x80) == 0x00) ) len += 1;
else if( inBuf[i+H_0] < 0x08 ) len += 2;
else if( ((inBuf[i+0+H_0] & 0xDC) == 0xD8) ) {
if( ((inBuf[i+2+H_0] & 0xDC) == 0xDC) && ((inBufLen - i) > 2) ) {
else if( ((inBuf[i+0+H_0] & 0xFC) == 0xD8) ) {
if( ((inBufLen - i) > 2) && ((inBuf[i+2+H_0] & 0xFC) == 0xDC) ) {
i += 2;
len += 4;
} else {
@ -356,10 +356,10 @@ sec_port_ucs2_utf8_conversion_function
outBuf[len+1] = 0x80 | ((inBuf[i+H_1] & 0x3F) >> 0);
len += 2;
} else if( (inBuf[i+H_0] & 0xDC) == 0xD8 ) {
} else if( (inBuf[i+H_0] & 0xFC) == 0xD8 ) {
int abcde, BCDE;
PORT_Assert(((inBuf[i+2+H_0] & 0xDC) == 0xDC) && ((inBufLen - i) > 2));
PORT_Assert(((inBufLen - i) > 2) && ((inBuf[i+2+H_0] & 0xFC) == 0xDC) );
/* D800-DBFF DC00-DFFF -> 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
/* 110110BC DEfghijk 110111lm nopqrstu ->
@ -852,6 +852,7 @@ struct ucs2 ucs2[] = {
{ 0x9000, "\xE9\x80\x80" },
{ 0xA000, "\xEA\x80\x80" },
{ 0xC000, "\xEC\x80\x80" },
{ 0xFB01, "\xEF\xAC\x81" },
{ 0xFFFF, "\xEF\xBF\xBF" }
};
@ -1153,6 +1154,18 @@ char *utf8_bad[] = {
"\xED\xA0\x80\xE0\xBF\xBF",
};
/* illegal UTF-16 sequences, 0-terminated */
uint16_t utf16_bad[][3] = {
/* leading surrogate not followed by trailing surrogate */
{ 0xD800, 0, 0 },
{ 0xD800, 0x41, 0 },
{ 0xD800, 0xfe, 0 },
{ 0xD800, 0x3bb, 0 },
{ 0xD800, 0xD800, 0 },
{ 0xD800, 0xFEFF, 0 },
{ 0xD800, 0xFFFD, 0 },
};
static void
dump_utf8
(
@ -1220,6 +1233,18 @@ test_ucs4_chars
rv = PR_FALSE;
continue;
}
len = strlen(e->utf8) - 1;
result = sec_port_ucs4_utf8_conversion_function(PR_FALSE,
(unsigned char *)&e->c, sizeof(e->c), utf8 + sizeof(utf8) - len, len,
&len);
if( result || len != strlen(e->utf8) ) {
fprintf(stdout, "Length computation error converting UCS-4 0x%08.8x"
" to UTF-8\n", e->c);
rv = PR_FALSE;
continue;
}
}
return rv;
@ -1277,6 +1302,18 @@ test_ucs2_chars
rv = PR_FALSE;
continue;
}
len = strlen(e->utf8) - 1;
result = sec_port_ucs2_utf8_conversion_function(PR_FALSE,
(unsigned char *)&e->c, sizeof(e->c), utf8 + sizeof(utf8) - len, len,
&len);
if( result || len != strlen(e->utf8) ) {
fprintf(stdout, "Length computation error converting UCS-2 0x%04.4x"
" to UTF-8\n", e->c);
rv = PR_FALSE;
continue;
}
}
return rv;
@ -1426,6 +1463,38 @@ test_utf8_bad_chars
return rv;
}
static PRBool
test_utf16_bad_chars(void)
{
PRBool rv = PR_TRUE;
int i;
for( i = 0; i < sizeof(utf16_bad)/sizeof(utf16_bad[0]); ++i ) {
PRBool result;
unsigned char destbuf[18];
unsigned int j, len, destlen;
uint16_t *buf;
for( len = 0; utf16_bad[i][len] != 0; ++len )
/* nothing */;
buf = malloc(sizeof(uint16_t) * len);
for( j = 0; j < len; ++j )
buf[j] = htons(utf16_bad[i][j]);
result = sec_port_ucs2_utf8_conversion_function(PR_FALSE,
(unsigned char *)buf, sizeof(uint16_t) * len, destbuf, sizeof(destbuf),
&destlen);
if( result ) {
fprintf(stdout, "Failed to detect bad UTF-16 string conversion for "
"{0x%x,0x%x} (UTF-8 len = %u)\n", utf16_bad[i][0], utf16_bad[i][1],
destlen);
rv = PR_FALSE;
}
free(buf);
}
}
static PRBool
test_iso88591_chars
(
@ -1576,7 +1645,7 @@ test_multichars
exit(1);
}
len = 0;
len = 1;
for( i = 0; i < sizeof(ucs4)/sizeof(ucs4[0]); i++ ) {
ucs4s[i] = ucs4[i].c;
len += strlen(ucs4[i].utf8);
@ -1584,7 +1653,7 @@ test_multichars
ucs4_utf8 = (char *)malloc(len);
len = 0;
len = 1;
for( i = 0; i < sizeof(ucs2)/sizeof(ucs2[0]); i++ ) {
ucs2s[i] = ucs2[i].c;
len += strlen(ucs2[i].utf8);
@ -1781,6 +1850,7 @@ main
test_ucs2_chars() &&
test_utf16_chars() &&
test_utf8_bad_chars() &&
test_utf16_bad_chars() &&
test_iso88591_chars() &&
test_zeroes() &&
test_multichars() &&