Add uint64_t support in CBS and CBB.
We need these APIs to parse some Certificate Transparency structures. Bug: chromium:634570 Change-Id: I4eb46058985a7369dc119ba6a1214913b237da39 Reviewed-on: https://boringssl-review.googlesource.com/c/34944 Reviewed-by: David Benjamin <davidben@google.com> Reviewed-by: Adam Langley <agl@google.com> Commit-Queue: David Benjamin <davidben@google.com> Commit-Queue: Adam Langley <agl@google.com>
This commit is contained in:
parent
f109f20873
commit
c18353d214
@ -42,10 +42,12 @@ TEST(CBSTest, Skip) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST(CBSTest, GetUint) {
|
TEST(CBSTest, GetUint) {
|
||||||
static const uint8_t kData[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
|
static const uint8_t kData[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
|
||||||
|
11, 12, 13, 14, 15, 16, 17, 18, 19, 20};
|
||||||
uint8_t u8;
|
uint8_t u8;
|
||||||
uint16_t u16;
|
uint16_t u16;
|
||||||
uint32_t u32;
|
uint32_t u32;
|
||||||
|
uint64_t u64;
|
||||||
CBS data;
|
CBS data;
|
||||||
|
|
||||||
CBS_init(&data, kData, sizeof(kData));
|
CBS_init(&data, kData, sizeof(kData));
|
||||||
@ -57,10 +59,12 @@ TEST(CBSTest, GetUint) {
|
|||||||
EXPECT_EQ(0x40506u, u32);
|
EXPECT_EQ(0x40506u, u32);
|
||||||
ASSERT_TRUE(CBS_get_u32(&data, &u32));
|
ASSERT_TRUE(CBS_get_u32(&data, &u32));
|
||||||
EXPECT_EQ(0x708090au, u32);
|
EXPECT_EQ(0x708090au, u32);
|
||||||
|
ASSERT_TRUE(CBS_get_u64(&data, &u64));
|
||||||
|
EXPECT_EQ(0xb0c0d0e0f101112u, u64);
|
||||||
ASSERT_TRUE(CBS_get_last_u8(&data, &u8));
|
ASSERT_TRUE(CBS_get_last_u8(&data, &u8));
|
||||||
EXPECT_EQ(0xcu, u8);
|
EXPECT_EQ(0x14u, u8);
|
||||||
ASSERT_TRUE(CBS_get_last_u8(&data, &u8));
|
ASSERT_TRUE(CBS_get_last_u8(&data, &u8));
|
||||||
EXPECT_EQ(0xbu, u8);
|
EXPECT_EQ(0x13u, u8);
|
||||||
EXPECT_FALSE(CBS_get_u8(&data, &u8));
|
EXPECT_FALSE(CBS_get_u8(&data, &u8));
|
||||||
EXPECT_FALSE(CBS_get_last_u8(&data, &u8));
|
EXPECT_FALSE(CBS_get_last_u8(&data, &u8));
|
||||||
}
|
}
|
||||||
@ -310,7 +314,9 @@ TEST(CBBTest, InitUninitialized) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST(CBBTest, Basic) {
|
TEST(CBBTest, Basic) {
|
||||||
static const uint8_t kExpected[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc};
|
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};
|
||||||
uint8_t *buf;
|
uint8_t *buf;
|
||||||
size_t buf_len;
|
size_t buf_len;
|
||||||
|
|
||||||
@ -323,7 +329,8 @@ TEST(CBBTest, Basic) {
|
|||||||
ASSERT_TRUE(CBB_add_u16(cbb.get(), 0x203));
|
ASSERT_TRUE(CBB_add_u16(cbb.get(), 0x203));
|
||||||
ASSERT_TRUE(CBB_add_u24(cbb.get(), 0x40506));
|
ASSERT_TRUE(CBB_add_u24(cbb.get(), 0x40506));
|
||||||
ASSERT_TRUE(CBB_add_u32(cbb.get(), 0x708090a));
|
ASSERT_TRUE(CBB_add_u32(cbb.get(), 0x708090a));
|
||||||
ASSERT_TRUE(CBB_add_bytes(cbb.get(), (const uint8_t *)"\x0b\x0c", 2));
|
ASSERT_TRUE(CBB_add_u64(cbb.get(), 0xb0c0d0e0f101112));
|
||||||
|
ASSERT_TRUE(CBB_add_bytes(cbb.get(), (const uint8_t *)"\x13\x14", 2));
|
||||||
ASSERT_TRUE(CBB_finish(cbb.get(), &buf, &buf_len));
|
ASSERT_TRUE(CBB_finish(cbb.get(), &buf, &buf_len));
|
||||||
|
|
||||||
bssl::UniquePtr<uint8_t> scoper(buf);
|
bssl::UniquePtr<uint8_t> scoper(buf);
|
||||||
|
@ -144,7 +144,7 @@ static int cbb_buffer_add(struct cbb_buffer_st *base, uint8_t **out,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cbb_buffer_add_u(struct cbb_buffer_st *base, uint32_t v,
|
static int cbb_buffer_add_u(struct cbb_buffer_st *base, uint64_t v,
|
||||||
size_t len_len) {
|
size_t len_len) {
|
||||||
if (len_len == 0) {
|
if (len_len == 0) {
|
||||||
return 1;
|
return 1;
|
||||||
@ -459,6 +459,13 @@ int CBB_add_u32(CBB *cbb, uint32_t value) {
|
|||||||
return cbb_buffer_add_u(cbb->base, value, 4);
|
return cbb_buffer_add_u(cbb->base, value, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int CBB_add_u64(CBB *cbb, uint64_t value) {
|
||||||
|
if (!CBB_flush(cbb)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return cbb_buffer_add_u(cbb->base, value, 8);
|
||||||
|
}
|
||||||
|
|
||||||
void CBB_discard_child(CBB *cbb) {
|
void CBB_discard_child(CBB *cbb) {
|
||||||
if (cbb->child == NULL) {
|
if (cbb->child == NULL) {
|
||||||
return;
|
return;
|
||||||
|
@ -88,8 +88,8 @@ int CBS_mem_equal(const CBS *cbs, const uint8_t *data, size_t len) {
|
|||||||
return CRYPTO_memcmp(cbs->data, data, len) == 0;
|
return CRYPTO_memcmp(cbs->data, data, len) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cbs_get_u(CBS *cbs, uint32_t *out, size_t len) {
|
static int cbs_get_u(CBS *cbs, uint64_t *out, size_t len) {
|
||||||
uint32_t result = 0;
|
uint64_t result = 0;
|
||||||
const uint8_t *data;
|
const uint8_t *data;
|
||||||
|
|
||||||
if (!cbs_get(cbs, &data, len)) {
|
if (!cbs_get(cbs, &data, len)) {
|
||||||
@ -113,7 +113,7 @@ int CBS_get_u8(CBS *cbs, uint8_t *out) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int CBS_get_u16(CBS *cbs, uint16_t *out) {
|
int CBS_get_u16(CBS *cbs, uint16_t *out) {
|
||||||
uint32_t v;
|
uint64_t v;
|
||||||
if (!cbs_get_u(cbs, &v, 2)) {
|
if (!cbs_get_u(cbs, &v, 2)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -122,11 +122,25 @@ int CBS_get_u16(CBS *cbs, uint16_t *out) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int CBS_get_u24(CBS *cbs, uint32_t *out) {
|
int CBS_get_u24(CBS *cbs, uint32_t *out) {
|
||||||
return cbs_get_u(cbs, out, 3);
|
uint64_t v;
|
||||||
|
if (!cbs_get_u(cbs, &v, 3)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
*out = v;
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CBS_get_u32(CBS *cbs, uint32_t *out) {
|
int CBS_get_u32(CBS *cbs, uint32_t *out) {
|
||||||
return cbs_get_u(cbs, out, 4);
|
uint64_t v;
|
||||||
|
if (!cbs_get_u(cbs, &v, 4)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
*out = v;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CBS_get_u64(CBS *cbs, uint64_t *out) {
|
||||||
|
return cbs_get_u(cbs, out, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
int CBS_get_last_u8(CBS *cbs, uint8_t *out) {
|
int CBS_get_last_u8(CBS *cbs, uint8_t *out) {
|
||||||
@ -157,10 +171,13 @@ int CBS_copy_bytes(CBS *cbs, uint8_t *out, size_t len) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int cbs_get_length_prefixed(CBS *cbs, CBS *out, size_t len_len) {
|
static int cbs_get_length_prefixed(CBS *cbs, CBS *out, size_t len_len) {
|
||||||
uint32_t len;
|
uint64_t len;
|
||||||
if (!cbs_get_u(cbs, &len, len_len)) {
|
if (!cbs_get_u(cbs, &len, len_len)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
// If |len_len| <= 3 then we know that |len| will fit into a |size_t|, even on
|
||||||
|
// 32-bit systems.
|
||||||
|
assert(len_len <= 3);
|
||||||
return CBS_get_bytes(cbs, out, len);
|
return CBS_get_bytes(cbs, out, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -274,7 +291,7 @@ static int cbs_get_any_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag,
|
|||||||
// encode the number of subsequent octets used to encode the length (ITU-T
|
// encode the number of subsequent octets used to encode the length (ITU-T
|
||||||
// X.690 clause 8.1.3.5.b).
|
// X.690 clause 8.1.3.5.b).
|
||||||
const size_t num_bytes = length_byte & 0x7f;
|
const size_t num_bytes = length_byte & 0x7f;
|
||||||
uint32_t len32;
|
uint64_t len64;
|
||||||
|
|
||||||
if (ber_ok && (tag & CBS_ASN1_CONSTRUCTED) != 0 && num_bytes == 0) {
|
if (ber_ok && (tag & CBS_ASN1_CONSTRUCTED) != 0 && num_bytes == 0) {
|
||||||
// indefinite length
|
// indefinite length
|
||||||
@ -290,20 +307,20 @@ static int cbs_get_any_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag,
|
|||||||
if (num_bytes == 0 || num_bytes > 4) {
|
if (num_bytes == 0 || num_bytes > 4) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (!cbs_get_u(&header, &len32, num_bytes)) {
|
if (!cbs_get_u(&header, &len64, num_bytes)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
// ITU-T X.690 section 10.1 (DER length forms) requires encoding the length
|
// ITU-T X.690 section 10.1 (DER length forms) requires encoding the length
|
||||||
// with the minimum number of octets.
|
// with the minimum number of octets.
|
||||||
if (len32 < 128) {
|
if (len64 < 128) {
|
||||||
// Length should have used short-form encoding.
|
// Length should have used short-form encoding.
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if ((len32 >> ((num_bytes-1)*8)) == 0) {
|
if ((len64 >> ((num_bytes-1)*8)) == 0) {
|
||||||
// Length should have been at least one byte shorter.
|
// Length should have been at least one byte shorter.
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
len = len32;
|
len = len64;
|
||||||
if (len + header_len + num_bytes < len) {
|
if (len + header_len + num_bytes < len) {
|
||||||
// Overflow.
|
// Overflow.
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -110,6 +110,10 @@ OPENSSL_EXPORT int CBS_get_u24(CBS *cbs, uint32_t *out);
|
|||||||
// and advances |cbs|. It returns one on success and zero on error.
|
// and advances |cbs|. It returns one on success and zero on error.
|
||||||
OPENSSL_EXPORT int CBS_get_u32(CBS *cbs, uint32_t *out);
|
OPENSSL_EXPORT int CBS_get_u32(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_last_u8 sets |*out| to the last uint8_t from |cbs| and shortens
|
// 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.
|
// |cbs|. It returns one on success and zero on error.
|
||||||
OPENSSL_EXPORT int CBS_get_last_u8(CBS *cbs, uint8_t *out);
|
OPENSSL_EXPORT int CBS_get_last_u8(CBS *cbs, uint8_t *out);
|
||||||
@ -459,6 +463,10 @@ OPENSSL_EXPORT int CBB_add_u24(CBB *cbb, uint32_t value);
|
|||||||
// returns one on success and zero otherwise.
|
// returns one on success and zero otherwise.
|
||||||
OPENSSL_EXPORT int CBB_add_u32(CBB *cbb, uint32_t value);
|
OPENSSL_EXPORT int CBB_add_u32(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_discard_child discards the current unflushed child of |cbb|. Neither the
|
// 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.
|
// child's contents nor the length prefix will be included in the output.
|
||||||
OPENSSL_EXPORT void CBB_discard_child(CBB *cbb);
|
OPENSSL_EXPORT void CBB_discard_child(CBB *cbb);
|
||||||
|
Loading…
Reference in New Issue
Block a user