From 10a3195fcf7d04ba519651cf12e945a8fe470a3c Mon Sep 17 00:00:00 2001 From: David Benjamin Date: Fri, 24 Nov 2017 12:56:32 -0500 Subject: [PATCH] Pretty-print large INTEGERs and ENUMERATEDs in hex. This avoids taking quadratic time to pretty-print certificates with excessively large integer fields. Very large integers aren't any more readable in decimal than hexadecimal anyway, and the i2s_* functions will parse either form. Found by libFuzzer. Reviewed-by: Rich Salz Reviewed-by: Richard Levitte (Merged from https://github.com/openssl/openssl/pull/4790) --- crypto/err/openssl.txt | 1 + crypto/x509v3/v3_utl.c | 42 +++++++++++++++++++++++++++++++++++-- crypto/x509v3/v3err.c | 2 ++ include/openssl/x509v3err.h | 1 + 4 files changed, 44 insertions(+), 2 deletions(-) diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index e7353aa3e8..23c32fb850 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -1390,6 +1390,7 @@ X509V3_F_A2I_GENERAL_NAME:164:a2i_GENERAL_NAME X509V3_F_ADDR_VALIDATE_PATH_INTERNAL:166:addr_validate_path_internal X509V3_F_ASIDENTIFIERCHOICE_CANONIZE:161:ASIdentifierChoice_canonize X509V3_F_ASIDENTIFIERCHOICE_IS_CANONICAL:162:ASIdentifierChoice_is_canonical +X509V3_F_BIGNUM_TO_STRING:167:bignum_to_string X509V3_F_COPY_EMAIL:122:copy_email X509V3_F_COPY_ISSUER:123:copy_issuer X509V3_F_DO_DIRNAME:144:do_dirname diff --git a/crypto/x509v3/v3_utl.c b/crypto/x509v3/v3_utl.c index 4dbcfaa430..c9b40d2c76 100644 --- a/crypto/x509v3/v3_utl.c +++ b/crypto/x509v3/v3_utl.c @@ -14,6 +14,7 @@ #include #include "internal/ctype.h" #include +#include #include #include "internal/x509_int.h" #include @@ -100,6 +101,43 @@ int X509V3_add_value_bool_nf(const char *name, int asn1_bool, return 1; } +static char *bignum_to_string(const BIGNUM *bn) +{ + char *tmp, *ret; + size_t len; + + /* + * Display large numbers in hex and small numbers in decimal. Converting to + * decimal takes quadratic time and is no more useful than hex for large + * numbers. + */ + if (BN_num_bits(bn) < 128) + return BN_bn2dec(bn); + + tmp = BN_bn2hex(bn); + if (tmp == NULL) + return NULL; + + len = strlen(tmp) + 3; + ret = OPENSSL_malloc(len); + if (ret == NULL) { + X509V3err(X509V3_F_BIGNUM_TO_STRING, ERR_R_MALLOC_FAILURE); + OPENSSL_free(tmp); + return NULL; + } + + /* Prepend "0x", but place it after the "-" if negative. */ + if (tmp[0] == '-') { + OPENSSL_strlcpy(ret, "-0x", len); + OPENSSL_strlcat(ret, tmp + 1, len); + } else { + OPENSSL_strlcpy(ret, "0x", len); + OPENSSL_strlcat(ret, tmp, len); + } + OPENSSL_free(tmp); + return ret; +} + char *i2s_ASN1_ENUMERATED(X509V3_EXT_METHOD *method, const ASN1_ENUMERATED *a) { BIGNUM *bntmp = NULL; @@ -108,7 +146,7 @@ char *i2s_ASN1_ENUMERATED(X509V3_EXT_METHOD *method, const ASN1_ENUMERATED *a) if (!a) return NULL; if ((bntmp = ASN1_ENUMERATED_to_BN(a, NULL)) == NULL - || (strtmp = BN_bn2dec(bntmp)) == NULL) + || (strtmp = bignum_to_string(bntmp)) == NULL) X509V3err(X509V3_F_I2S_ASN1_ENUMERATED, ERR_R_MALLOC_FAILURE); BN_free(bntmp); return strtmp; @@ -122,7 +160,7 @@ char *i2s_ASN1_INTEGER(X509V3_EXT_METHOD *method, const ASN1_INTEGER *a) if (!a) return NULL; if ((bntmp = ASN1_INTEGER_to_BN(a, NULL)) == NULL - || (strtmp = BN_bn2dec(bntmp)) == NULL) + || (strtmp = bignum_to_string(bntmp)) == NULL) X509V3err(X509V3_F_I2S_ASN1_INTEGER, ERR_R_MALLOC_FAILURE); BN_free(bntmp); return strtmp; diff --git a/crypto/x509v3/v3err.c b/crypto/x509v3/v3err.c index d661623f92..6f30ba3a1f 100644 --- a/crypto/x509v3/v3err.c +++ b/crypto/x509v3/v3err.c @@ -22,6 +22,8 @@ static const ERR_STRING_DATA X509V3_str_functs[] = { "ASIdentifierChoice_canonize"}, {ERR_PACK(ERR_LIB_X509V3, X509V3_F_ASIDENTIFIERCHOICE_IS_CANONICAL, 0), "ASIdentifierChoice_is_canonical"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_BIGNUM_TO_STRING, 0), + "bignum_to_string"}, {ERR_PACK(ERR_LIB_X509V3, X509V3_F_COPY_EMAIL, 0), "copy_email"}, {ERR_PACK(ERR_LIB_X509V3, X509V3_F_COPY_ISSUER, 0), "copy_issuer"}, {ERR_PACK(ERR_LIB_X509V3, X509V3_F_DO_DIRNAME, 0), "do_dirname"}, diff --git a/include/openssl/x509v3err.h b/include/openssl/x509v3err.h index 2bd515cc75..5349d9dd6f 100644 --- a/include/openssl/x509v3err.h +++ b/include/openssl/x509v3err.h @@ -26,6 +26,7 @@ int ERR_load_X509V3_strings(void); # define X509V3_F_ADDR_VALIDATE_PATH_INTERNAL 166 # define X509V3_F_ASIDENTIFIERCHOICE_CANONIZE 161 # define X509V3_F_ASIDENTIFIERCHOICE_IS_CANONICAL 162 +# define X509V3_F_BIGNUM_TO_STRING 167 # define X509V3_F_COPY_EMAIL 122 # define X509V3_F_COPY_ISSUER 123 # define X509V3_F_DO_DIRNAME 144 -- 2.25.1