diff --git a/crypto/x509/x509_test.cc b/crypto/x509/x509_test.cc index cd4e61d7..b4cecca2 100644 --- a/crypto/x509/x509_test.cc +++ b/crypto/x509/x509_test.cc @@ -26,6 +26,7 @@ #include #include #include +#include #include "../internal.h" @@ -996,3 +997,41 @@ TEST(X509Test, TestPrintUTCTIME) { std::string(reinterpret_cast(contents), len)); } } + +TEST(X509Test, PrettyPrintIntegers) { + static const char *kTests[] = { + // Small numbers are pretty-printed in decimal. + "0", + "-1", + "1", + "42", + "-42", + "256", + "-256", + // Large numbers are pretty-printed in hex to avoid taking quadratic time. + "0x0123456789", + "-0x0123456789", + }; + for (const char *in : kTests) { + SCOPED_TRACE(in); + BIGNUM *bn = nullptr; + ASSERT_TRUE(BN_asc2bn(&bn, in)); + bssl::UniquePtr free_bn(bn); + + { + bssl::UniquePtr asn1(BN_to_ASN1_INTEGER(bn, nullptr)); + ASSERT_TRUE(asn1); + bssl::UniquePtr out(i2s_ASN1_INTEGER(nullptr, asn1.get())); + ASSERT_TRUE(out.get()); + EXPECT_STREQ(in, out.get()); + } + + { + bssl::UniquePtr asn1(BN_to_ASN1_ENUMERATED(bn, nullptr)); + ASSERT_TRUE(asn1); + bssl::UniquePtr out(i2s_ASN1_ENUMERATED(nullptr, asn1.get())); + ASSERT_TRUE(out.get()); + EXPECT_STREQ(in, out.get()); + } + } +} diff --git a/crypto/x509v3/v3_utl.c b/crypto/x509v3/v3_utl.c index feb3dc6a..7d109ee6 100644 --- a/crypto/x509v3/v3_utl.c +++ b/crypto/x509v3/v3_utl.c @@ -155,6 +155,45 @@ int X509V3_add_value_bool_nf(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) < 32) { + return BN_bn2dec(bn); + } + + tmp = BN_bn2hex(bn); + if (tmp == NULL) { + return NULL; + } + + len = strlen(tmp) + 3; + ret = OPENSSL_malloc(len); + if (ret == NULL) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + OPENSSL_free(tmp); + return NULL; + } + + /* Prepend "0x", but place it after the "-" if negative. */ + if (tmp[0] == '-') { + BUF_strlcpy(ret, "-0x", len); + BUF_strlcat(ret, tmp + 1, len); + } else { + BUF_strlcpy(ret, "0x", len); + BUF_strlcat(ret, tmp, len); + } + OPENSSL_free(tmp); + return ret; +} + char *i2s_ASN1_ENUMERATED(X509V3_EXT_METHOD *method, ASN1_ENUMERATED *a) { BIGNUM *bntmp = NULL; @@ -162,7 +201,7 @@ char *i2s_ASN1_ENUMERATED(X509V3_EXT_METHOD *method, ASN1_ENUMERATED *a) if (!a) return NULL; if (!(bntmp = ASN1_ENUMERATED_to_BN(a, NULL)) || - !(strtmp = BN_bn2dec(bntmp))) + !(strtmp = bignum_to_string(bntmp))) OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); BN_free(bntmp); return strtmp; @@ -175,7 +214,7 @@ char *i2s_ASN1_INTEGER(X509V3_EXT_METHOD *method, ASN1_INTEGER *a) if (!a) return NULL; if (!(bntmp = ASN1_INTEGER_to_BN(a, NULL)) || - !(strtmp = BN_bn2dec(bntmp))) + !(strtmp = bignum_to_string(bntmp))) OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); BN_free(bntmp); return strtmp;