mirror of
https://github.com/rn10950/RetroZilla.git
synced 2024-06-03 06:10:13 +02:00
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:
parent
9b2e59866b
commit
6712ac7edb
|
@ -61,6 +61,12 @@ ifndef WARNING_CFLAGS
|
||||||
|
|
||||||
ifeq ($(NSS_ENABLE_WERROR),1)
|
ifeq ($(NSS_ENABLE_WERROR),1)
|
||||||
WARNING_CFLAGS += -Werror
|
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
|
else
|
||||||
# Old versions of gcc (< 4.8) don't support #pragma diagnostic in functions.
|
# 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.
|
# Use this to disable use of that #pragma and the warnings it suppresses.
|
||||||
|
|
|
@ -1444,6 +1444,12 @@ FIPS186Change_ReduceModQForDSA(const unsigned char *w,
|
||||||
const unsigned char *q,
|
const unsigned char *q,
|
||||||
unsigned char *xj);
|
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
|
* The following functions are for FIPS poweron self test and FIPS algorithm
|
||||||
* testing.
|
* testing.
|
||||||
|
|
|
@ -96,7 +96,8 @@ struct RNGContextStr {
|
||||||
* RNG_RandomUpdate. */
|
* RNG_RandomUpdate. */
|
||||||
PRUint8 additionalDataCache[PRNG_ADDITONAL_DATA_CACHE_SIZE];
|
PRUint8 additionalDataCache[PRNG_ADDITONAL_DATA_CACHE_SIZE];
|
||||||
PRUint32 additionalAvail;
|
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;
|
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
|
* NOTE: bytes & len are entropy || nonce || personalization_string. In
|
||||||
* normal operation, NSS calculates them all together in a single call.
|
* 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
|
static SECStatus
|
||||||
prng_instantiate(RNGContext *rng, const PRUint8 *bytes, unsigned int len)
|
prng_instantiate(RNGContext *rng, const PRUint8 *bytes, unsigned int len)
|
||||||
{
|
{
|
||||||
if (len < PRNG_SEEDLEN) {
|
if (!rng->isKatTest && len < PRNG_SEEDLEN) {
|
||||||
/* if the seedlen is to small, it's probably because we failed to get
|
/* If the seedlen is too small, it's probably because we failed to get
|
||||||
* enough random data */
|
* enough random data.
|
||||||
|
* This is stricter than NIST SP800-90A requires. Don't enforce it for
|
||||||
|
* tests. */
|
||||||
PORT_SetError(SEC_ERROR_NEED_RANDOM);
|
PORT_SetError(SEC_ERROR_NEED_RANDOM);
|
||||||
return SECFailure;
|
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) \
|
#define PRNG_ADD_BITS_AND_CARRY(dest, dest_len, add, len, carry) \
|
||||||
PRNG_ADD_BITS(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
|
* 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 */
|
/* the RNG is in a valid state */
|
||||||
globalrng->isValid = PR_TRUE;
|
globalrng->isValid = PR_TRUE;
|
||||||
|
globalrng->isKatTest = PR_FALSE;
|
||||||
|
|
||||||
/* fetch one random value so that we can populate rng->oldV for our
|
/* fetch one random value so that we can populate rng->oldV for our
|
||||||
* continous random number test. */
|
* continous random number test. */
|
||||||
|
@ -667,6 +671,17 @@ RNG_RNGShutdown(void)
|
||||||
* entropy we may have previously collected. */
|
* entropy we may have previously collected. */
|
||||||
RNGContext testContext;
|
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
|
* 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.
|
* other NIST SP 800-90 algorithms may be used in the future.
|
||||||
|
|
|
@ -36,10 +36,10 @@
|
||||||
* The format of the version string should be
|
* The format of the version string should be
|
||||||
* "<major version>.<minor version>[.<patch level>[.<build number>]][ <ECC>][ <Beta>]"
|
* "<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_VMAJOR 3
|
||||||
#define NSS_VMINOR 21
|
#define NSS_VMINOR 21
|
||||||
#define NSS_VPATCH 0
|
#define NSS_VPATCH 4
|
||||||
#define NSS_VBUILD 0
|
#define NSS_VBUILD 0
|
||||||
#define NSS_BETA PR_FALSE
|
#define NSS_BETA PR_FALSE
|
||||||
|
|
||||||
|
|
|
@ -25,10 +25,10 @@
|
||||||
* The format of the version string should be
|
* The format of the version string should be
|
||||||
* "<major version>.<minor version>[.<patch level>[.<build number>]][ <ECC>][ <Beta>]"
|
* "<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_VMAJOR 3
|
||||||
#define SOFTOKEN_VMINOR 21
|
#define SOFTOKEN_VMINOR 21
|
||||||
#define SOFTOKEN_VPATCH 0
|
#define SOFTOKEN_VPATCH 4
|
||||||
#define SOFTOKEN_VBUILD 0
|
#define SOFTOKEN_VBUILD 0
|
||||||
#define SOFTOKEN_BETA PR_FALSE
|
#define SOFTOKEN_BETA PR_FALSE
|
||||||
|
|
||||||
|
|
|
@ -9963,6 +9963,7 @@ ssl3_HandleDHClientKeyExchange(sslSocket *ss,
|
||||||
CKM_DH_PKCS_DERIVE, target, CKA_DERIVE, 0, NULL);
|
CKM_DH_PKCS_DERIVE, target, CKA_DERIVE, 0, NULL);
|
||||||
if (pms == NULL) {
|
if (pms == NULL) {
|
||||||
ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
|
ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
|
||||||
|
rv = SECFailure;
|
||||||
goto loser;
|
goto loser;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11867,6 +11868,13 @@ ssl_ConstantTimeEQ8(unsigned char a, unsigned char b)
|
||||||
return DUPLICATE_MSB_TO_ALL_8(c);
|
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
|
static SECStatus
|
||||||
ssl_RemoveSSLv3CBCPadding(sslBuffer *plaintext,
|
ssl_RemoveSSLv3CBCPadding(sslBuffer *plaintext,
|
||||||
unsigned int blockSize,
|
unsigned int blockSize,
|
||||||
|
@ -11970,22 +11978,54 @@ ssl_CBCExtractMAC(sslBuffer *plaintext,
|
||||||
/* scanStart contains the number of bytes that we can ignore because
|
/* scanStart contains the number of bytes that we can ignore because
|
||||||
* the MAC's position can only vary by 255 bytes. */
|
* the MAC's position can only vary by 255 bytes. */
|
||||||
unsigned scanStart = 0;
|
unsigned scanStart = 0;
|
||||||
unsigned i, j, divSpoiler;
|
unsigned i, j;
|
||||||
unsigned char rotateOffset;
|
unsigned char rotateOffset;
|
||||||
|
|
||||||
if (originalLength > macSize + 255 + 1)
|
if (originalLength > macSize + 255 + 1) {
|
||||||
scanStart = originalLength - (macSize + 255 + 1);
|
scanStart = originalLength - (macSize + 255 + 1);
|
||||||
|
}
|
||||||
|
|
||||||
/* divSpoiler contains a multiple of macSize that is used to cause the
|
/* We want to compute
|
||||||
* modulo operation to be constant time. Without this, the time varies
|
* rotateOffset = (macStart - scanStart) % macSize
|
||||||
* based on the amount of padding when running on Intel chips at least.
|
* 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
|
||||||
* The aim of right-shifting macSize is so that the compiler doesn't
|
* using Barrett reduction:
|
||||||
* figure out that it can remove divSpoiler as that would require it
|
* q := (rotateOffset * m) >> k
|
||||||
* to prove that macSize is always even, which I hope is beyond it. */
|
* rotateOffset -= q * n
|
||||||
divSpoiler = macSize >> 1;
|
* if (n <= rotateOffset) rotateOffset -= n
|
||||||
divSpoiler <<= (sizeof(divSpoiler)-1)*8;
|
*/
|
||||||
rotateOffset = (divSpoiler + macStart - scanStart) % macSize;
|
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);
|
memset(rotatedMac, 0, macSize);
|
||||||
for (i = scanStart; i < originalLength;) {
|
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
|
/* 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. */
|
* we could line-align |rotatedMac| and rotate in place. */
|
||||||
memset(out, 0, macSize);
|
memset(out, 0, macSize);
|
||||||
|
rotateOffset = macSize - rotateOffset;
|
||||||
|
rotateOffset = ssl_constantTimeSelect(ssl_ConstantTimeGE(rotateOffset, macSize),
|
||||||
|
0, rotateOffset);
|
||||||
for (i = 0; i < macSize; i++) {
|
for (i = 0; i < macSize; i++) {
|
||||||
unsigned char offset =
|
|
||||||
(divSpoiler + macSize - rotateOffset + i) % macSize;
|
|
||||||
for (j = 0; j < macSize; j++) {
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -179,10 +179,12 @@ long
|
||||||
DER_GetInteger(const SECItem *it)
|
DER_GetInteger(const SECItem *it)
|
||||||
{
|
{
|
||||||
long ival = 0;
|
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 char *cp = it->data;
|
||||||
unsigned long overflow = 0x1ffUL << (((sizeof(ival) - 1) * 8) - 1);
|
unsigned long overflow = 0x1ffUL << (((sizeof(ival) - 1) * 8) - 1);
|
||||||
unsigned long ofloinit;
|
unsigned long mask = 1;
|
||||||
|
|
||||||
PORT_Assert(len);
|
PORT_Assert(len);
|
||||||
if (!len) {
|
if (!len) {
|
||||||
|
@ -190,14 +192,15 @@ DER_GetInteger(const SECItem *it)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*cp & 0x80)
|
if (*cp & 0x80) {
|
||||||
ival = -1L;
|
negative = PR_TRUE;
|
||||||
ofloinit = ival & overflow;
|
overflow <<= 1;
|
||||||
|
}
|
||||||
|
|
||||||
while (len) {
|
while (len) {
|
||||||
if ((ival & overflow) != ofloinit) {
|
if ((ival & overflow) != 0) {
|
||||||
PORT_SetError(SEC_ERROR_BAD_DER);
|
PORT_SetError(SEC_ERROR_BAD_DER);
|
||||||
if (ival < 0) {
|
if (negative) {
|
||||||
return LONG_MIN;
|
return LONG_MIN;
|
||||||
}
|
}
|
||||||
return LONG_MAX;
|
return LONG_MAX;
|
||||||
|
@ -206,6 +209,11 @@ DER_GetInteger(const SECItem *it)
|
||||||
ival |= *cp++;
|
ival |= *cp++;
|
||||||
--len;
|
--len;
|
||||||
}
|
}
|
||||||
|
if (negative && ival && (overflow & ival) == 0) {
|
||||||
|
mask <<= ((originalLength * 8) - 1);
|
||||||
|
ival &= ~mask;
|
||||||
|
ival -= mask;
|
||||||
|
}
|
||||||
return ival;
|
return ival;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -373,7 +373,7 @@ pl_base64_decode_flush (PLBase64Decoder *data)
|
||||||
static PRUint32
|
static PRUint32
|
||||||
PL_Base64MaxDecodedLength (PRUint32 size)
|
PL_Base64MaxDecodedLength (PRUint32 size)
|
||||||
{
|
{
|
||||||
return ((size * 3) / 4);
|
return size * 0.75;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -285,6 +285,11 @@ PL_Base64MaxEncodedLength (PRUint32 size, PRUint32 line_length)
|
||||||
{
|
{
|
||||||
PRUint32 tokens, tokens_per_line, full_lines, line_break_chars, remainder;
|
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;
|
tokens = (size + 2) / 3;
|
||||||
|
|
||||||
if (line_length == 0)
|
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?
|
* How much space could we possibly need for encoding this input?
|
||||||
*/
|
*/
|
||||||
need_length = PL_Base64MaxEncodedLength (srclen, line_length);
|
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.
|
* 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);
|
max_out_len = PL_Base64MaxEncodedLength (inItem->len, 64);
|
||||||
|
if (max_out_len == 0) {
|
||||||
|
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (arenaOpt != NULL)
|
if (arenaOpt != NULL)
|
||||||
mark = PORT_ArenaMark (arenaOpt);
|
mark = PORT_ArenaMark (arenaOpt);
|
||||||
|
|
|
@ -19,10 +19,10 @@
|
||||||
* The format of the version string should be
|
* The format of the version string should be
|
||||||
* "<major version>.<minor version>[.<patch level>[.<build number>]][ <Beta>]"
|
* "<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_VMAJOR 3
|
||||||
#define NSSUTIL_VMINOR 21
|
#define NSSUTIL_VMINOR 21
|
||||||
#define NSSUTIL_VPATCH 0
|
#define NSSUTIL_VPATCH 4
|
||||||
#define NSSUTIL_VBUILD 0
|
#define NSSUTIL_VBUILD 0
|
||||||
#define NSSUTIL_BETA PR_FALSE
|
#define NSSUTIL_BETA PR_FALSE
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
#define PR_Assert sec_asn1d_Assert
|
#define PR_Assert sec_asn1d_Assert
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
#include "secasn1.h"
|
#include "secasn1.h"
|
||||||
#include "secerr.h"
|
#include "secerr.h"
|
||||||
|
|
||||||
|
@ -1593,6 +1595,7 @@ sec_asn1d_parse_leaf (sec_asn1d_state *state,
|
||||||
|
|
||||||
item = (SECItem *)(state->dest);
|
item = (SECItem *)(state->dest);
|
||||||
if (item != NULL && item->data != NULL) {
|
if (item != NULL && item->data != NULL) {
|
||||||
|
unsigned long offset;
|
||||||
/* Strip leading zeroes when target is unsigned integer */
|
/* Strip leading zeroes when target is unsigned integer */
|
||||||
if (state->underlying_kind == SEC_ASN1_INTEGER && /* INTEGER */
|
if (state->underlying_kind == SEC_ASN1_INTEGER && /* INTEGER */
|
||||||
item->len == 0 && /* MSB */
|
item->len == 0 && /* MSB */
|
||||||
|
@ -1603,8 +1606,42 @@ sec_asn1d_parse_leaf (sec_asn1d_state *state,
|
||||||
len--;
|
len--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PORT_Memcpy (item->data + item->len, buf, len);
|
offset = item->len;
|
||||||
item->len += 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;
|
state->pending -= bufLen;
|
||||||
if (state->pending == 0)
|
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);
|
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;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2208,7 +2237,7 @@ sec_asn1d_concat_substrings (sec_asn1d_state *state)
|
||||||
* All bit-string substrings except the last one should be
|
* All bit-string substrings except the last one should be
|
||||||
* a clean multiple of 8 bits.
|
* a clean multiple of 8 bits.
|
||||||
*/
|
*/
|
||||||
if (is_bit_string && (substring->next == NULL)
|
if (is_bit_string && (substring->next != NULL)
|
||||||
&& (substring->len & 0x7)) {
|
&& (substring->len & 0x7)) {
|
||||||
PORT_SetError (SEC_ERROR_BAD_DER);
|
PORT_SetError (SEC_ERROR_BAD_DER);
|
||||||
state->top->status = decodeError;
|
state->top->status = decodeError;
|
||||||
|
|
|
@ -319,10 +319,10 @@ sec_port_ucs2_utf8_conversion_function
|
||||||
}
|
}
|
||||||
|
|
||||||
for( i = 0; i < inBufLen; i += 2 ) {
|
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+H_0] < 0x08 ) len += 2;
|
||||||
else if( ((inBuf[i+0+H_0] & 0xDC) == 0xD8) ) {
|
else if( ((inBuf[i+0+H_0] & 0xFC) == 0xD8) ) {
|
||||||
if( ((inBuf[i+2+H_0] & 0xDC) == 0xDC) && ((inBufLen - i) > 2) ) {
|
if( ((inBufLen - i) > 2) && ((inBuf[i+2+H_0] & 0xFC) == 0xDC) ) {
|
||||||
i += 2;
|
i += 2;
|
||||||
len += 4;
|
len += 4;
|
||||||
} else {
|
} else {
|
||||||
|
@ -356,10 +356,10 @@ sec_port_ucs2_utf8_conversion_function
|
||||||
outBuf[len+1] = 0x80 | ((inBuf[i+H_1] & 0x3F) >> 0);
|
outBuf[len+1] = 0x80 | ((inBuf[i+H_1] & 0x3F) >> 0);
|
||||||
|
|
||||||
len += 2;
|
len += 2;
|
||||||
} else if( (inBuf[i+H_0] & 0xDC) == 0xD8 ) {
|
} else if( (inBuf[i+H_0] & 0xFC) == 0xD8 ) {
|
||||||
int abcde, BCDE;
|
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 */
|
/* D800-DBFF DC00-DFFF -> 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
|
||||||
/* 110110BC DEfghijk 110111lm nopqrstu ->
|
/* 110110BC DEfghijk 110111lm nopqrstu ->
|
||||||
|
@ -852,6 +852,7 @@ struct ucs2 ucs2[] = {
|
||||||
{ 0x9000, "\xE9\x80\x80" },
|
{ 0x9000, "\xE9\x80\x80" },
|
||||||
{ 0xA000, "\xEA\x80\x80" },
|
{ 0xA000, "\xEA\x80\x80" },
|
||||||
{ 0xC000, "\xEC\x80\x80" },
|
{ 0xC000, "\xEC\x80\x80" },
|
||||||
|
{ 0xFB01, "\xEF\xAC\x81" },
|
||||||
{ 0xFFFF, "\xEF\xBF\xBF" }
|
{ 0xFFFF, "\xEF\xBF\xBF" }
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -1153,6 +1154,18 @@ char *utf8_bad[] = {
|
||||||
"\xED\xA0\x80\xE0\xBF\xBF",
|
"\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
|
static void
|
||||||
dump_utf8
|
dump_utf8
|
||||||
(
|
(
|
||||||
|
@ -1220,6 +1233,18 @@ test_ucs4_chars
|
||||||
rv = PR_FALSE;
|
rv = PR_FALSE;
|
||||||
continue;
|
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;
|
return rv;
|
||||||
|
@ -1277,6 +1302,18 @@ test_ucs2_chars
|
||||||
rv = PR_FALSE;
|
rv = PR_FALSE;
|
||||||
continue;
|
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;
|
return rv;
|
||||||
|
@ -1426,6 +1463,38 @@ test_utf8_bad_chars
|
||||||
return rv;
|
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
|
static PRBool
|
||||||
test_iso88591_chars
|
test_iso88591_chars
|
||||||
(
|
(
|
||||||
|
@ -1576,7 +1645,7 @@ test_multichars
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
len = 0;
|
len = 1;
|
||||||
for( i = 0; i < sizeof(ucs4)/sizeof(ucs4[0]); i++ ) {
|
for( i = 0; i < sizeof(ucs4)/sizeof(ucs4[0]); i++ ) {
|
||||||
ucs4s[i] = ucs4[i].c;
|
ucs4s[i] = ucs4[i].c;
|
||||||
len += strlen(ucs4[i].utf8);
|
len += strlen(ucs4[i].utf8);
|
||||||
|
@ -1584,7 +1653,7 @@ test_multichars
|
||||||
|
|
||||||
ucs4_utf8 = (char *)malloc(len);
|
ucs4_utf8 = (char *)malloc(len);
|
||||||
|
|
||||||
len = 0;
|
len = 1;
|
||||||
for( i = 0; i < sizeof(ucs2)/sizeof(ucs2[0]); i++ ) {
|
for( i = 0; i < sizeof(ucs2)/sizeof(ucs2[0]); i++ ) {
|
||||||
ucs2s[i] = ucs2[i].c;
|
ucs2s[i] = ucs2[i].c;
|
||||||
len += strlen(ucs2[i].utf8);
|
len += strlen(ucs2[i].utf8);
|
||||||
|
@ -1781,6 +1850,7 @@ main
|
||||||
test_ucs2_chars() &&
|
test_ucs2_chars() &&
|
||||||
test_utf16_chars() &&
|
test_utf16_chars() &&
|
||||||
test_utf8_bad_chars() &&
|
test_utf8_bad_chars() &&
|
||||||
|
test_utf16_bad_chars() &&
|
||||||
test_iso88591_chars() &&
|
test_iso88591_chars() &&
|
||||||
test_zeroes() &&
|
test_zeroes() &&
|
||||||
test_multichars() &&
|
test_multichars() &&
|
||||||
|
|
Loading…
Reference in New Issue
Block a user