summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdam Langley <agl@google.com>2015-04-23 13:54:37 -0700
committerKenny Root <kroot@google.com>2015-04-23 21:57:00 +0000
commitd82ab38ca2b63638a2cb0b5d8a2c76d90c86dd31 (patch)
tree3cea780c4956edec6e4be340cf510a618b794c8c
parent217eaab310220731646f2a1a0159d71e4eb09d4a (diff)
downloadexternal_boringssl-d82ab38ca2b63638a2cb0b5d8a2c76d90c86dd31.zip
external_boringssl-d82ab38ca2b63638a2cb0b5d8a2c76d90c86dd31.tar.gz
external_boringssl-d82ab38ca2b63638a2cb0b5d8a2c76d90c86dd31.tar.bz2
Ensure BN_asc2bn, BN_dec2bn, and BN_hex2bn never give -0.
When |BN_dec2bn| and |BN_hex2bn| were merged (way back in the initial BoringSSL change), the neg flag was set too soon and could be cleared by |BN_add_word|. This is an import of upstream's c85573cc. The unittest change isn't included here because bn_test.c has changed significantly in upstream and BoringSSL unittests aren't run in the Android environment. Bug: 20523350 Change-Id: Iaf8efe2fe3419218437f5ebb9a15f73559860a0f
-rw-r--r--src/crypto/asn1/a_int.c2
-rw-r--r--src/crypto/bn/convert.c19
2 files changed, 11 insertions, 10 deletions
diff --git a/src/crypto/asn1/a_int.c b/src/crypto/asn1/a_int.c
index eb0887a..2ecccc5 100644
--- a/src/crypto/asn1/a_int.c
+++ b/src/crypto/asn1/a_int.c
@@ -416,7 +416,7 @@ ASN1_INTEGER *BN_to_ASN1_INTEGER(const BIGNUM *bn, ASN1_INTEGER *ai)
OPENSSL_PUT_ERROR(ASN1, BN_to_ASN1_INTEGER, ASN1_R_NESTED_ASN1_ERROR);
goto err;
}
- if (BN_is_negative(bn))
+ if (BN_is_negative(bn) && !BN_is_zero(bn))
ret->type = V_ASN1_NEG_INTEGER;
else ret->type=V_ASN1_INTEGER;
j=BN_num_bits(bn);
diff --git a/src/crypto/bn/convert.c b/src/crypto/bn/convert.c
index f764eed..9c7b9be 100644
--- a/src/crypto/bn/convert.c
+++ b/src/crypto/bn/convert.c
@@ -263,20 +263,19 @@ static void decode_hex(BIGNUM *bn, const char *in, int i) {
bn->top = h;
}
-/* decode_dec decodes |i| bytes of decimal data from |in| and updates |bn|. */
-static void decode_dec(BIGNUM *bn, const char *in, int i) {
- int j;
+/* decode_dec decodes |in_len| bytes of decimal data from |in| and updates |bn|. */
+static void decode_dec(BIGNUM *bn, const char *in, int in_len) {
+ int i, j;
BN_ULONG l = 0;
- j = BN_DEC_NUM - (i % BN_DEC_NUM);
+ j = BN_DEC_NUM - (in_len % BN_DEC_NUM);
if (j == BN_DEC_NUM) {
j = 0;
}
l = 0;
- while (*in) {
+ for (i = 0; i < in_len; i++) {
l *= 10;
- l += *in - '0';
- in++;
+ l += in[i] - '0';
if (++j == BN_DEC_NUM) {
BN_mul_word(bn, BN_DEC_CONV);
BN_add_word(bn, l);
@@ -320,7 +319,6 @@ static int bn_x2bn(BIGNUM **outp, const char *in, decode_func decode, char_test_
ret = *outp;
BN_zero(ret);
}
- ret->neg = neg;
/* i is the number of hex digests; */
if (bn_expand(ret, i * 4) == NULL) {
@@ -330,6 +328,9 @@ static int bn_x2bn(BIGNUM **outp, const char *in, decode_func decode, char_test_
decode(ret, in, i);
bn_correct_top(ret);
+ if (!BN_is_zero(ret)) {
+ ret->neg = neg;
+ }
*outp = ret;
return num;
@@ -440,7 +441,7 @@ int BN_asc2bn(BIGNUM **outp, const char *in) {
}
}
- if (*orig_in == '-') {
+ if (*orig_in == '-' && !BN_is_zero(*outp)) {
(*outp)->neg = 1;
}