Add CBB_add_u48

Change-Id: Ic1d3507e22b3d88ca5396ad78711628d84a4a38d
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/99287
Commit-Queue: Matt Mueller <mattm@google.com>
Reviewed-by: Matt Mueller <mattm@google.com>
Auto-Submit: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
diff --git a/crypto/bytestring/bytestring_test.cc b/crypto/bytestring/bytestring_test.cc
index 113637c..fca6109 100644
--- a/crypto/bytestring/bytestring_test.cc
+++ b/crypto/bytestring/bytestring_test.cc
@@ -430,10 +430,10 @@
 
 TEST(CBBTest, Basic) {
   static const uint8_t kExpected[] = {
-      0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
-      0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14,
-      0x03, 0x02, 0x0a, 0x09, 0x08, 0x07, 0x12, 0x11, 0x10, 0x0f,
-      0x0e, 0x0d, 0x0c, 0x0b, 0x00, 0x00, 0x00, 0x00};
+      0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
+      0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x03, 0x02,
+      0x0a, 0x09, 0x08, 0x07, 0x12, 0x11, 0x10, 0x0f, 0x0e, 0x0d, 0x0c,
+      0x0b, 0x00, 0x00, 0x00, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
   uint8_t *buf;
   size_t buf_len;
 
@@ -453,6 +453,7 @@
   ASSERT_TRUE(CBB_add_u32le(cbb.get(), 0x708090a));
   ASSERT_TRUE(CBB_add_u64le(cbb.get(), 0xb0c0d0e0f101112));
   ASSERT_TRUE(CBB_add_zeros(cbb.get(), 4));
+  ASSERT_TRUE(CBB_add_u48(cbb.get(), 0x112233445566));
   ASSERT_TRUE(CBB_finish(cbb.get(), &buf, &buf_len));
 
   UniquePtr<uint8_t> scoper(buf);
@@ -1371,6 +1372,15 @@
   // All future operations should fail.
   EXPECT_FALSE(CBB_add_u8(cbb.get(), 0));
   EXPECT_FALSE(CBB_finish(cbb.get(), &ptr, &len));
+
+  // Write a u64 that cannot fit in a u48.
+  cbb.Reset();
+  ASSERT_TRUE(CBB_init(cbb.get(), 0));
+  ASSERT_FALSE(CBB_add_u48(cbb.get(), uint64_t{1} << 48));
+
+  // All future operations should fail.
+  EXPECT_FALSE(CBB_add_u8(cbb.get(), 0));
+  EXPECT_FALSE(CBB_finish(cbb.get(), &ptr, &len));
 }
 
 TEST(CBSTest, BitString) {
diff --git a/crypto/bytestring/cbb.cc b/crypto/bytestring/cbb.cc
index 2289098..9400ab9 100644
--- a/crypto/bytestring/cbb.cc
+++ b/crypto/bytestring/cbb.cc
@@ -477,6 +477,8 @@
   return CBB_add_u32(cbb, CRYPTO_bswap4(value));
 }
 
+int CBB_add_u48(CBB *cbb, uint64_t value) { return cbb_add_u(cbb, value, 6); }
+
 int CBB_add_u64(CBB *cbb, uint64_t value) { return cbb_add_u(cbb, value, 8); }
 
 int CBB_add_u64le(CBB *cbb, uint64_t value) {
diff --git a/include/openssl/bytestring.h b/include/openssl/bytestring.h
index 7005074..f0453fa 100644
--- a/include/openssl/bytestring.h
+++ b/include/openssl/bytestring.h
@@ -638,6 +638,10 @@
 // It returns one on success and zero otherwise.
 OPENSSL_EXPORT int CBB_add_u32le(CBB *cbb, uint32_t value);
 
+// CBB_add_u48 appends a 48-bit, big-endian number from `value` to `cbb`. It
+// returns one on success and zero otherwise.
+OPENSSL_EXPORT int CBB_add_u48(CBB *cbb, uint64_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);
diff --git a/include/openssl/prefix_symbols.h b/include/openssl/prefix_symbols.h
index d46dc70..79df391 100644
--- a/include/openssl/prefix_symbols.h
+++ b/include/openssl/prefix_symbols.h
@@ -519,6 +519,7 @@
 #pragma redefine_extname CBB_add_u24_length_prefixed BORINGSSL_ADD_USER_LABEL_AND_PREFIX(CBB_add_u24_length_prefixed)
 #pragma redefine_extname CBB_add_u32 BORINGSSL_ADD_USER_LABEL_AND_PREFIX(CBB_add_u32)
 #pragma redefine_extname CBB_add_u32le BORINGSSL_ADD_USER_LABEL_AND_PREFIX(CBB_add_u32le)
+#pragma redefine_extname CBB_add_u48 BORINGSSL_ADD_USER_LABEL_AND_PREFIX(CBB_add_u48)
 #pragma redefine_extname CBB_add_u64 BORINGSSL_ADD_USER_LABEL_AND_PREFIX(CBB_add_u64)
 #pragma redefine_extname CBB_add_u64le BORINGSSL_ADD_USER_LABEL_AND_PREFIX(CBB_add_u64le)
 #pragma redefine_extname CBB_add_u8 BORINGSSL_ADD_USER_LABEL_AND_PREFIX(CBB_add_u8)
@@ -3652,6 +3653,7 @@
 #define CBB_add_u24_length_prefixed BORINGSSL_ADD_PREFIX(CBB_add_u24_length_prefixed)
 #define CBB_add_u32 BORINGSSL_ADD_PREFIX(CBB_add_u32)
 #define CBB_add_u32le BORINGSSL_ADD_PREFIX(CBB_add_u32le)
+#define CBB_add_u48 BORINGSSL_ADD_PREFIX(CBB_add_u48)
 #define CBB_add_u64 BORINGSSL_ADD_PREFIX(CBB_add_u64)
 #define CBB_add_u64le BORINGSSL_ADD_PREFIX(CBB_add_u64le)
 #define CBB_add_u8 BORINGSSL_ADD_PREFIX(CBB_add_u8)