Skip to content

Commit

Permalink
Add uint64_t support in CBS and CBB.
Browse files Browse the repository at this point in the history
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 <[email protected]>
Reviewed-by: Adam Langley <[email protected]>
Commit-Queue: David Benjamin <[email protected]>
Commit-Queue: Adam Langley <[email protected]>
  • Loading branch information
Kaustubha Govind authored and CQ bot account: [email protected] committed Feb 22, 2019
1 parent f109f20 commit c18353d
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 17 deletions.
17 changes: 12 additions & 5 deletions crypto/bytestring/bytestring_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,12 @@ TEST(CBSTest, Skip) {
}

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;
uint16_t u16;
uint32_t u32;
uint64_t u64;
CBS data;

CBS_init(&data, kData, sizeof(kData));
Expand All @@ -57,10 +59,12 @@ TEST(CBSTest, GetUint) {
EXPECT_EQ(0x40506u, u32);
ASSERT_TRUE(CBS_get_u32(&data, &u32));
EXPECT_EQ(0x708090au, u32);
ASSERT_TRUE(CBS_get_u64(&data, &u64));
EXPECT_EQ(0xb0c0d0e0f101112u, u64);
ASSERT_TRUE(CBS_get_last_u8(&data, &u8));
EXPECT_EQ(0xcu, u8);
EXPECT_EQ(0x14u, 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_last_u8(&data, &u8));
}
Expand Down Expand Up @@ -310,7 +314,9 @@ TEST(CBBTest, InitUninitialized) {
}

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;
size_t buf_len;

Expand All @@ -323,7 +329,8 @@ TEST(CBBTest, Basic) {
ASSERT_TRUE(CBB_add_u16(cbb.get(), 0x203));
ASSERT_TRUE(CBB_add_u24(cbb.get(), 0x40506));
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));

bssl::UniquePtr<uint8_t> scoper(buf);
Expand Down
9 changes: 8 additions & 1 deletion crypto/bytestring/cbb.c
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ static int cbb_buffer_add(struct cbb_buffer_st *base, uint8_t **out,
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) {
if (len_len == 0) {
return 1;
Expand Down Expand Up @@ -459,6 +459,13 @@ int CBB_add_u32(CBB *cbb, uint32_t value) {
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) {
if (cbb->child == NULL) {
return;
Expand Down
39 changes: 28 additions & 11 deletions crypto/bytestring/cbs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

static int cbs_get_u(CBS *cbs, uint32_t *out, size_t len) {
uint32_t result = 0;
static int cbs_get_u(CBS *cbs, uint64_t *out, size_t len) {
uint64_t result = 0;
const uint8_t *data;

if (!cbs_get(cbs, &data, len)) {
Expand All @@ -113,7 +113,7 @@ int CBS_get_u8(CBS *cbs, uint8_t *out) {
}

int CBS_get_u16(CBS *cbs, uint16_t *out) {
uint32_t v;
uint64_t v;
if (!cbs_get_u(cbs, &v, 2)) {
return 0;
}
Expand All @@ -122,11 +122,25 @@ int CBS_get_u16(CBS *cbs, uint16_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) {
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) {
Expand Down Expand Up @@ -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) {
uint32_t len;
uint64_t len;
if (!cbs_get_u(cbs, &len, len_len)) {
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);
}

Expand Down Expand Up @@ -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
// X.690 clause 8.1.3.5.b).
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) {
// indefinite length
Expand All @@ -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) {
return 0;
}
if (!cbs_get_u(&header, &len32, num_bytes)) {
if (!cbs_get_u(&header, &len64, num_bytes)) {
return 0;
}
// ITU-T X.690 section 10.1 (DER length forms) requires encoding the length
// with the minimum number of octets.
if (len32 < 128) {
if (len64 < 128) {
// Length should have used short-form encoding.
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.
return 0;
}
len = len32;
len = len64;
if (len + header_len + num_bytes < len) {
// Overflow.
return 0;
Expand Down
8 changes: 8 additions & 0 deletions include/openssl/bytestring.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
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|. It returns one on success and zero on error.
OPENSSL_EXPORT int CBS_get_last_u8(CBS *cbs, uint8_t *out);
Expand Down Expand Up @@ -459,6 +463,10 @@ OPENSSL_EXPORT int CBB_add_u24(CBB *cbb, uint32_t value);
// returns one on success and zero otherwise.
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
// child's contents nor the length prefix will be included in the output.
OPENSSL_EXPORT void CBB_discard_child(CBB *cbb);
Expand Down

0 comments on commit c18353d

Please sign in to comment.