Add a few little-endian functions to CBS/CBB.

Change-Id: Idf962d587f031c1feed541a43be55dc9a65ca444
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39607
Reviewed-by: David Benjamin <davidben@google.com>
diff --git a/crypto/bytestring/bytestring_test.cc b/crypto/bytestring/bytestring_test.cc
index ad5f947..93593e9 100644
--- a/crypto/bytestring/bytestring_test.cc
+++ b/crypto/bytestring/bytestring_test.cc
@@ -67,6 +67,14 @@
   EXPECT_EQ(0x13u, u8);
   EXPECT_FALSE(CBS_get_u8(&data, &u8));
   EXPECT_FALSE(CBS_get_last_u8(&data, &u8));
+
+  CBS_init(&data, kData, sizeof(kData));
+  ASSERT_TRUE(CBS_get_u16le(&data, &u16));
+  EXPECT_EQ(0x0201u, u16);
+  ASSERT_TRUE(CBS_get_u32le(&data, &u32));
+  EXPECT_EQ(0x06050403u, u32);
+  ASSERT_TRUE(CBS_get_u64le(&data, &u64));
+  EXPECT_EQ(0x0e0d0c0b0a090807u, u64);
 }
 
 TEST(CBSTest, GetPrefixed) {
@@ -316,7 +324,9 @@
 TEST(CBBTest, Basic) {
   static const uint8_t kExpected[] = {1,   2,    3,    4,    5,    6,   7,
                                       8,   9,    0xa,  0xb,  0xc,  0xd, 0xe,
-                                      0xf, 0x10, 0x11, 0x12, 0x13, 0x14};
+                                      0xf, 0x10, 0x11, 0x12, 0x13, 0x14, 3, 2,
+                                      10,  9,    8,    7,    0x12, 0x11, 0x10,
+                                      0xf, 0xe,  0xd,  0xc,  0xb};
   uint8_t *buf;
   size_t buf_len;
 
@@ -331,6 +341,9 @@
   ASSERT_TRUE(CBB_add_u32(cbb.get(), 0x708090a));
   ASSERT_TRUE(CBB_add_u64(cbb.get(), 0xb0c0d0e0f101112));
   ASSERT_TRUE(CBB_add_bytes(cbb.get(), (const uint8_t *)"\x13\x14", 2));
+  ASSERT_TRUE(CBB_add_u16le(cbb.get(), 0x203));
+  ASSERT_TRUE(CBB_add_u32le(cbb.get(), 0x708090a));
+  ASSERT_TRUE(CBB_add_u64le(cbb.get(), 0xb0c0d0e0f101112));
   ASSERT_TRUE(CBB_finish(cbb.get(), &buf, &buf_len));
 
   bssl::UniquePtr<uint8_t> scoper(buf);
diff --git a/crypto/bytestring/cbb.c b/crypto/bytestring/cbb.c
index 501cb1b..efb89c7 100644
--- a/crypto/bytestring/cbb.c
+++ b/crypto/bytestring/cbb.c
@@ -447,6 +447,10 @@
   return cbb_buffer_add_u(cbb->base, value, 2);
 }
 
+int CBB_add_u16le(CBB *cbb, uint16_t value) {
+  return CBB_add_u16(cbb, CRYPTO_bswap2(value));
+}
+
 int CBB_add_u24(CBB *cbb, uint32_t value) {
   if (!CBB_flush(cbb)) {
     return 0;
@@ -463,6 +467,10 @@
   return cbb_buffer_add_u(cbb->base, value, 4);
 }
 
+int CBB_add_u32le(CBB *cbb, uint32_t value) {
+  return CBB_add_u32(cbb, CRYPTO_bswap4(value));
+}
+
 int CBB_add_u64(CBB *cbb, uint64_t value) {
   if (!CBB_flush(cbb)) {
     return 0;
@@ -470,6 +478,10 @@
   return cbb_buffer_add_u(cbb->base, value, 8);
 }
 
+int CBB_add_u64le(CBB *cbb, uint64_t value) {
+  return CBB_add_u64(cbb, CRYPTO_bswap8(value));
+}
+
 void CBB_discard_child(CBB *cbb) {
   if (cbb->child == NULL) {
     return;
diff --git a/crypto/bytestring/cbs.c b/crypto/bytestring/cbs.c
index cd0eaa8..49d7003 100644
--- a/crypto/bytestring/cbs.c
+++ b/crypto/bytestring/cbs.c
@@ -120,6 +120,14 @@
   return 1;
 }
 
+int CBS_get_u16le(CBS *cbs, uint16_t *out) {
+  if (!CBS_get_u16(cbs, out)) {
+    return 0;
+  }
+  *out = CRYPTO_bswap2(*out);
+  return 1;
+}
+
 int CBS_get_u24(CBS *cbs, uint32_t *out) {
   uint64_t v;
   if (!cbs_get_u(cbs, &v, 3)) {
@@ -138,10 +146,26 @@
   return 1;
 }
 
+int CBS_get_u32le(CBS *cbs, uint32_t *out) {
+  if (!CBS_get_u32(cbs, out)) {
+    return 0;
+  }
+  *out = CRYPTO_bswap4(*out);
+  return 1;
+}
+
 int CBS_get_u64(CBS *cbs, uint64_t *out) {
   return cbs_get_u(cbs, out, 8);
 }
 
+int CBS_get_u64le(CBS *cbs, uint64_t *out) {
+  if (!cbs_get_u(cbs, out, 8)) {
+    return 0;
+  }
+  *out = CRYPTO_bswap8(*out);
+  return 1;
+}
+
 int CBS_get_last_u8(CBS *cbs, uint8_t *out) {
   if (cbs->len == 0) {
     return 0;
diff --git a/crypto/internal.h b/crypto/internal.h
index b75f9af..edba9f9 100644
--- a/crypto/internal.h
+++ b/crypto/internal.h
@@ -689,6 +689,10 @@
 // Endianness conversions.
 
 #if defined(__GNUC__) && __GNUC__ >= 2
+static inline uint16_t CRYPTO_bswap2(uint16_t x) {
+  return __builtin_bswap16(x);
+}
+
 static inline uint32_t CRYPTO_bswap4(uint32_t x) {
   return __builtin_bswap32(x);
 }
@@ -700,7 +704,11 @@
 OPENSSL_MSVC_PRAGMA(warning(push, 3))
 #include <stdlib.h>
 OPENSSL_MSVC_PRAGMA(warning(pop))
-#pragma intrinsic(_byteswap_uint64, _byteswap_ulong)
+#pragma intrinsic(_byteswap_uint64, _byteswap_ulong, _byteswap_ushort)
+static inline uint16_t CRYPTO_bswap2(uint16_t x) {
+  return _byteswap_ushort(x);
+}
+
 static inline uint32_t CRYPTO_bswap4(uint32_t x) {
   return _byteswap_ulong(x);
 }
@@ -709,6 +717,10 @@
   return _byteswap_uint64(x);
 }
 #else
+static inline uint16_t CRYPTO_bswap2(uint16_t x) {
+  return (x >> 8) | (x << 8);
+}
+
 static inline uint32_t CRYPTO_bswap4(uint32_t x) {
   x = (x >> 16) | (x << 16);
   x = ((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8);
diff --git a/include/openssl/bytestring.h b/include/openssl/bytestring.h
index 2fe4b01..1f9c879 100644
--- a/include/openssl/bytestring.h
+++ b/include/openssl/bytestring.h
@@ -102,6 +102,10 @@
 // advances |cbs|. It returns one on success and zero on error.
 OPENSSL_EXPORT int CBS_get_u16(CBS *cbs, uint16_t *out);
 
+// CBS_get_u16le sets |*out| to the next, little-endian uint16_t from |cbs| and
+// advances |cbs|. It returns one on success and zero on error.
+OPENSSL_EXPORT int CBS_get_u16le(CBS *cbs, uint16_t *out);
+
 // CBS_get_u24 sets |*out| to the next, big-endian 24-bit value from |cbs| and
 // advances |cbs|. It returns one on success and zero on error.
 OPENSSL_EXPORT int CBS_get_u24(CBS *cbs, uint32_t *out);
@@ -110,10 +114,18 @@
 // and advances |cbs|. It returns one on success and zero on error.
 OPENSSL_EXPORT int CBS_get_u32(CBS *cbs, uint32_t *out);
 
+// CBS_get_u32le sets |*out| to the next, little-endian uint32_t value from
+// |cbs| and advances |cbs|. It returns one on success and zero on error.
+OPENSSL_EXPORT int CBS_get_u32le(CBS *cbs, uint32_t *out);
+
 // CBS_get_u64 sets |*out| to the next, big-endian uint64_t value from |cbs|
 // and advances |cbs|. It returns one on success and zero on error.
 OPENSSL_EXPORT int CBS_get_u64(CBS *cbs, uint64_t *out);
 
+// CBS_get_u64le sets |*out| to the next, little-endian uint64_t value from
+// |cbs| and advances |cbs|. It returns one on success and zero on error.
+OPENSSL_EXPORT int CBS_get_u64le(CBS *cbs, uint64_t *out);
+
 // CBS_get_last_u8 sets |*out| to the last uint8_t from |cbs| and shortens
 // |cbs|. It returns one on success and zero on error.
 OPENSSL_EXPORT int CBS_get_last_u8(CBS *cbs, uint8_t *out);
@@ -460,6 +472,10 @@
 // returns one on success and zero otherwise.
 OPENSSL_EXPORT int CBB_add_u16(CBB *cbb, uint16_t value);
 
+// CBB_add_u16le appends a 16-bit, little-endian number from |value| to |cbb|.
+// It returns one on success and zero otherwise.
+OPENSSL_EXPORT int CBB_add_u16le(CBB *cbb, uint16_t value);
+
 // CBB_add_u24 appends a 24-bit, big-endian number from |value| to |cbb|. It
 // returns one on success and zero otherwise.
 OPENSSL_EXPORT int CBB_add_u24(CBB *cbb, uint32_t value);
@@ -468,10 +484,18 @@
 // returns one on success and zero otherwise.
 OPENSSL_EXPORT int CBB_add_u32(CBB *cbb, uint32_t value);
 
+// CBB_add_u32le appends a 32-bit, little-endian number from |value| to |cbb|.
+// It returns one on success and zero otherwise.
+OPENSSL_EXPORT int CBB_add_u32le(CBB *cbb, uint32_t value);
+
 // CBB_add_u64 appends a 64-bit, big-endian number from |value| to |cbb|. It
 // returns one on success and zero otherwise.
 OPENSSL_EXPORT int CBB_add_u64(CBB *cbb, uint64_t value);
 
+// CBB_add_u64le appends a 64-bit, little-endian number from |value| to |cbb|.
+// It returns one on success and zero otherwise.
+OPENSSL_EXPORT int CBB_add_u64le(CBB *cbb, uint64_t value);
+
 // CBB_discard_child discards the current unflushed child of |cbb|. Neither the
 // child's contents nor the length prefix will be included in the output.
 OPENSSL_EXPORT void CBB_discard_child(CBB *cbb);