Fix x509v3_bytes_to_hex when passed the empty string.
Change-Id: I0a27b98ea1b8fd28ec415cb6c9ca789d438dd545
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/51627
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
diff --git a/crypto/x509/x509_test.cc b/crypto/x509/x509_test.cc
index 48b83da..b201afe 100644
--- a/crypto/x509/x509_test.cc
+++ b/crypto/x509/x509_test.cc
@@ -3891,3 +3891,23 @@
EXPECT_EQ(sk_X509_OBJECT_num(X509_STORE_get0_objects(store.get())), 2u);
}
+
+TEST(X509Test, BytesToHex) {
+ struct {
+ std::vector<uint8_t> 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<char> 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 3e6081b..976e34d 100644
--- a/crypto/x509v3/internal.h
+++ b/crypto/x509v3/internal.h
@@ -70,21 +70,21 @@
#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 474acf8..960c407 100644
--- a/crypto/x509v3/v3_utl.c
+++ b/crypto/x509v3/v3_utl.c
@@ -63,6 +63,7 @@
#include <string.h>
#include <openssl/bn.h>
+#include <openssl/bytestring.h>
#include <openssl/conf.h>
#include <openssl/err.h>
#include <openssl/mem.h>
@@ -467,33 +468,33 @@
/* 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;
+ }
}
- q[-1] = 0;
+ uint8_t *ret;
+ size_t unused_len;
+ if (!CBB_add_u8(&cbb, 0) ||
+ !CBB_finish(&cbb, &ret, &unused_len)) {
+ goto err;
+ }
- 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)