From f61dce8746a177c599087a97d685c8c1f502cc93 Mon Sep 17 00:00:00 2001 From: jordan Date: Fri, 3 Feb 2023 08:51:46 -0600 Subject: [PATCH] Fix wolfSSL_ASN1_INTEGER_to_BN for negative values Added mp_setneg for ZD#15531. --- src/ssl.c | 6 ++++++ tests/api.c | 26 ++++++++++++++++++++++---- wolfssl/wolfcrypt/integer.h | 1 + wolfssl/wolfcrypt/sp_int.h | 7 +++++++ wolfssl/wolfcrypt/tfm.h | 2 ++ 5 files changed, 38 insertions(+), 4 deletions(-) diff --git a/src/ssl.c b/src/ssl.c index ca75c3730..7208ef9eb 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -36125,6 +36125,7 @@ WOLFSSL_BIGNUM *wolfSSL_ASN1_INTEGER_to_BN(const WOLFSSL_ASN1_INTEGER *ai, } #endif + /* First get the magnitude of ASN1_INTEGER. */ ret = GetInt(mpi, ai->data, &idx, ai->dataMax); if (ret != 0) { #if defined(WOLFSSL_QT) || defined(WOLFSSL_HAPROXY) @@ -36153,6 +36154,11 @@ WOLFSSL_BIGNUM *wolfSSL_ASN1_INTEGER_to_BN(const WOLFSSL_ASN1_INTEGER *ai, #endif } + /* Now get the sign of ASN1_INTEGER. */ + if (ai->negative) { + mp_setneg(mpi); + } + /* mp_clear needs called because mpi is copied and causes memory leak with * --disable-fastmath */ ret = SetIndividualExternal(&bn, mpi); diff --git a/tests/api.c b/tests/api.c index 2546377d7..945c90e26 100644 --- a/tests/api.c +++ b/tests/api.c @@ -36312,10 +36312,28 @@ static int test_wolfSSL_BN(void) AssertIntEQ(BN_sub(c, a, b), SSL_SUCCESS); #if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) { - char* ret; - AssertNotNull(ret = BN_bn2dec(c)); - AssertIntEQ(XMEMCMP(ret, "-4", sizeof("-4")), 0); - XFREE(ret, NULL, DYNAMIC_TYPE_OPENSSL); + /* Do additional tests on negative BN conversions. */ + char * ret; + ASN1_INTEGER * asn1; + BIGNUM * tmp; + + /* Sanity check we have a negative BN. */ + AssertIntEQ(BN_is_negative(c), 1); + AssertNotNull(ret = BN_bn2dec(c)); + AssertIntEQ(XMEMCMP(ret, "-4", sizeof("-4")), 0); + XFREE(ret, NULL, DYNAMIC_TYPE_OPENSSL); + + /* Convert to ASN1_INTEGER and back to BN. */ + AssertNotNull(asn1 = BN_to_ASN1_INTEGER(c, NULL)); + AssertNotNull(tmp = ASN1_INTEGER_to_BN(asn1, NULL)); + + /* After converting back BN should be negative and correct. */ + AssertIntEQ(BN_is_negative(tmp), 1); + AssertNotNull(ret = BN_bn2dec(tmp)); + AssertIntEQ(XMEMCMP(ret, "-4", sizeof("-4")), 0); + XFREE(ret, NULL, DYNAMIC_TYPE_OPENSSL); + ASN1_INTEGER_free(asn1); + BN_free(tmp); } #endif AssertIntEQ(BN_get_word(c), 4); diff --git a/wolfssl/wolfcrypt/integer.h b/wolfssl/wolfcrypt/integer.h index cc1e0a8ca..84c6d1dba 100644 --- a/wolfssl/wolfcrypt/integer.h +++ b/wolfssl/wolfcrypt/integer.h @@ -234,6 +234,7 @@ typedef int ltm_prime_callback(unsigned char *dst, int len, void *dat); #define mp_isodd(a) \ (((a)->used > 0 && (((a)->dp[0] & 1u) == 1u)) ? MP_YES : MP_NO) #define mp_isneg(a) (((a)->sign != MP_ZPOS) ? MP_YES : MP_NO) +#define mp_setneg(a) ((a)->sign = MP_NEG) #define mp_isword(a, w) \ ((((a)->used == 1) && ((a)->dp[0] == (w))) || (((w) == 0) && ((a)->used == 0)) \ ? MP_YES : MP_NO) diff --git a/wolfssl/wolfcrypt/sp_int.h b/wolfssl/wolfcrypt/sp_int.h index 284940327..bcbd03b93 100644 --- a/wolfssl/wolfcrypt/sp_int.h +++ b/wolfssl/wolfcrypt/sp_int.h @@ -639,6 +639,10 @@ typedef struct sp_ecc_ctx { * @return 0 indicating not negative always. */ #define sp_isneg(a) (0) +/* Sets the multi-precision number negative. + * + * Negative support not compiled in, so does nothing. */ +#define sp_setneg(a) do{}while(0) #else /* Returns whether multi-precision number is negative. * @@ -650,6 +654,8 @@ typedef struct sp_ecc_ctx { * @return 0 when not negative. */ #define sp_isneg(a) ((a)->sign == MP_NEG) +/* Sets the multi-precision number negative. */ +#define sp_setneg(a) ((a)->sign = MP_NEG) #endif /* Updates the used count to exclude leading zeros. @@ -985,6 +991,7 @@ WOLFSSL_LOCAL void sp_memzero_check(sp_int* sp); #define mp_isword sp_isword #define mp_abs sp_abs #define mp_isneg sp_isneg +#define mp_setneg sp_setneg #define mp_clamp sp_clamp /* One to one mappings. */ diff --git a/wolfssl/wolfcrypt/tfm.h b/wolfssl/wolfcrypt/tfm.h index f7a7f2279..7ec518b79 100644 --- a/wolfssl/wolfcrypt/tfm.h +++ b/wolfssl/wolfcrypt/tfm.h @@ -444,6 +444,7 @@ MP_API void fp_free(fp_int* a); #define fp_isodd(a) \ (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? FP_YES : FP_NO) #define fp_isneg(a) (((a)->sign != FP_ZPOS) ? FP_YES : FP_NO) +#define fp_setneg(a) ((a)->sign = FP_NEG) #define fp_isword(a, w) \ (((((a)->used == 1) && ((a)->dp[0] == (w))) || \ (((w) == 0) && ((a)->used == 0))) ? FP_YES : FP_NO) @@ -737,6 +738,7 @@ int fp_sqr_comba64(fp_int *a, fp_int *b); #define mp_isone(a) fp_isone(a) #define mp_iseven(a) fp_iseven(a) #define mp_isneg(a) fp_isneg(a) +#define mp_setneg(a) fp_setneg(a) #define mp_isword(a, w) fp_isword(a, w) #define MP_RADIX_BIN 2