diff --git a/crypto/x509/x509_test.cc b/crypto/x509/x509_test.cc index 48b83da3a..b201afe96 100644 --- a/crypto/x509/x509_test.cc +++ b/crypto/x509/x509_test.cc @@ -3891,3 +3891,23 @@ TEST(X509Test, AddDuplicates) { EXPECT_EQ(sk_X509_OBJECT_num(X509_STORE_get0_objects(store.get())), 2u); } + +TEST(X509Test, BytesToHex) { + struct { + std::vector bytes; + const char *hex; + } kTests[] = { + {{}, ""}, + {{0x00}, "00"}, + {{0x00, 0x11, 0x22}, "00:11:22"}, + {{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}, + "01:23:45:67:89:AB:CD:EF"}, + }; + for (const auto &t : kTests) { + SCOPED_TRACE(Bytes(t.bytes)); + bssl::UniquePtr hex( + x509v3_bytes_to_hex(t.bytes.data(), t.bytes.size())); + ASSERT_TRUE(hex); + EXPECT_STREQ(hex.get(), t.hex); + } +} diff --git a/crypto/x509v3/internal.h b/crypto/x509v3/internal.h index 3e6081b48..976e34d33 100644 --- a/crypto/x509v3/internal.h +++ b/crypto/x509v3/internal.h @@ -70,21 +70,21 @@ extern "C" { #endif -// x509v3_bytes_to_hex encodes |len| bytes from |buffer| to hex and returns a +// x509v3_bytes_to_hex encodes |len| bytes from |in| to hex and returns a // newly-allocated NUL-terminated string containing the result, or NULL on // allocation error. // -// Note this function was historically named |hex_to_string| in OpenSSL, not -// |string_to_hex|. -char *x509v3_bytes_to_hex(const unsigned char *buffer, long len); +// This function was historically named |hex_to_string| in OpenSSL. Despite the +// name, |hex_to_string| converted to hex. +OPENSSL_EXPORT char *x509v3_bytes_to_hex(const uint8_t *in, size_t len); // x509v3_hex_string_to_bytes decodes |str| in hex and returns a newly-allocated // array containing the result, or NULL on error. On success, it sets |*len| to // the length of the result. Colon separators between bytes in the input are // allowed and ignored. // -// Note this function was historically named |string_to_hex| in OpenSSL, not -// |hex_to_string|. +// This function was historically named |string_to_hex| in OpenSSL. Despite the +// name, |string_to_hex| converted from hex. unsigned char *x509v3_hex_to_bytes(const char *str, long *len); // x509v3_name_cmp returns zero if |name| is equal to |cmp| or begins with |cmp| diff --git a/crypto/x509v3/v3_utl.c b/crypto/x509v3/v3_utl.c index 474acf852..960c407a1 100644 --- a/crypto/x509v3/v3_utl.c +++ b/crypto/x509v3/v3_utl.c @@ -63,6 +63,7 @@ #include #include +#include #include #include #include @@ -467,33 +468,33 @@ static char *strip_spaces(char *name) /* hex string utilities */ -/* - * Given a buffer of length 'len' return a OPENSSL_malloc'ed string with its - * hex representation @@@ (Contents of buffer are always kept in ASCII, also - * on EBCDIC machines) - */ - -char *x509v3_bytes_to_hex(const unsigned char *buffer, long len) +char *x509v3_bytes_to_hex(const uint8_t *in, size_t len) { - char *tmp, *q; - const unsigned char *p; - int i; - static const char hexdig[] = "0123456789ABCDEF"; - if (!buffer || !len) - return NULL; - if (!(tmp = OPENSSL_malloc(len * 3 + 1))) { - OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); - return NULL; + CBB cbb; + if (!CBB_init(&cbb, len * 3 + 1)) { + goto err; } - q = tmp; - for (i = 0, p = buffer; i < len; i++, p++) { - *q++ = hexdig[(*p >> 4) & 0xf]; - *q++ = hexdig[*p & 0xf]; - *q++ = ':'; + for (size_t i = 0; i < len; i++) { + static const char hex[] = "0123456789ABCDEF"; + if ((i > 0 && !CBB_add_u8(&cbb, ':')) || + !CBB_add_u8(&cbb, hex[in[i] >> 4]) || + !CBB_add_u8(&cbb, hex[in[i] & 0xf])) { + goto err; + } + } + uint8_t *ret; + size_t unused_len; + if (!CBB_add_u8(&cbb, 0) || + !CBB_finish(&cbb, &ret, &unused_len)) { + goto err; } - q[-1] = 0; - return tmp; + return (char *)ret; + +err: + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + CBB_cleanup(&cbb); + return NULL; } unsigned char *x509v3_hex_to_bytes(const char *str, long *len)