mirror of
https://boringssl.googlesource.com/boringssl
synced 2026-07-21 14:43:51 +00:00
Expose CBS_get_asn1_oid_component
Only needed in libssl actually, but we have CBB_add_asn1_oid_component, so this is a natural counterpart. Bug: 524722668 Change-Id: I14c1a4935919f2ddca971e925dc57c413e0234c4 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/98487 Commit-Queue: David Benjamin <davidben@google.com> Reviewed-by: Lily Chen <chlily@google.com>
This commit is contained in:
committed by
boringssl-scoped@luci-project-accounts.iam.gserviceaccount.com
parent
b35f9f1d1a
commit
a22861da5e
@@ -16,6 +16,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
@@ -2186,5 +2187,65 @@ TEST(CBSTest, GetU64Decimal) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST(CBSTest, OIDComponent) {
|
||||
const struct {
|
||||
// enc is an encoded OID component.
|
||||
std::vector<uint8_t> enc;
|
||||
// v is the decoded OID component, or nullopt if invalid.
|
||||
std::optional<uint64_t> v;
|
||||
} kTests[] = {
|
||||
// The empty string is not an OID component.
|
||||
{{}, std::nullopt},
|
||||
// Some valid OID components.
|
||||
{{0x00}, 0},
|
||||
{{0x01}, 1},
|
||||
{{0x7f}, 127},
|
||||
{{0x81, 0x00}, 128},
|
||||
{{0x81, 0x01}, 129},
|
||||
{{0x81, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f},
|
||||
UINT64_MAX},
|
||||
// 2^64 is too large and overflows.
|
||||
{{0x82, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00},
|
||||
std::nullopt},
|
||||
// Non-minimal OID components are invalid.
|
||||
{{0x80, 0x01}, std::nullopt},
|
||||
{{0x80, 0x81, 0x00}, std::nullopt},
|
||||
{{0x80, 0x81, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f},
|
||||
std::nullopt},
|
||||
// Truncated OID component.
|
||||
{{0xff}, std::nullopt},
|
||||
{{0x81}, std::nullopt},
|
||||
};
|
||||
for (const auto &t : kTests) {
|
||||
SCOPED_TRACE(Bytes(t.enc));
|
||||
CBS cbs;
|
||||
CBS_init(&cbs, t.enc.data(), t.enc.size());
|
||||
uint64_t v;
|
||||
if (!t.v.has_value()) {
|
||||
EXPECT_FALSE(CBS_get_asn1_oid_component(&cbs, &v));
|
||||
continue;
|
||||
}
|
||||
|
||||
ASSERT_TRUE(CBS_get_asn1_oid_component(&cbs, &v));
|
||||
EXPECT_EQ(v, t.v.value());
|
||||
EXPECT_EQ(CBS_len(&cbs), 0u);
|
||||
|
||||
// Trailing data should be left in `cbs`.
|
||||
std::vector<uint8_t> trailing_data = t.enc;
|
||||
trailing_data.push_back(42);
|
||||
CBS_init(&cbs, trailing_data.data(), trailing_data.size());
|
||||
ASSERT_TRUE(CBS_get_asn1_oid_component(&cbs, &v));
|
||||
EXPECT_EQ(v, t.v.value());
|
||||
EXPECT_EQ(CBS_data(&cbs), trailing_data.data() + t.enc.size());
|
||||
EXPECT_EQ(CBS_len(&cbs), 1u);
|
||||
|
||||
// Test serialization.
|
||||
ScopedCBB cbb;
|
||||
ASSERT_TRUE(CBB_init(cbb.get(), t.enc.size()));
|
||||
ASSERT_TRUE(CBB_add_asn1_oid_component(cbb.get(), t.v.value()));
|
||||
EXPECT_EQ(Bytes(CBBAsSpan(cbb.get())), Bytes(t.enc));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
BSSL_NAMESPACE_END
|
||||
|
||||
+10
-12
@@ -277,10 +277,7 @@ int CBS_get_u64_decimal(CBS *cbs, uint64_t *out) {
|
||||
return seen_digit;
|
||||
}
|
||||
|
||||
// parse_base128_integer reads a big-endian base-128 integer from `cbs` and sets
|
||||
// `*out` to the result. This is the encoding used in DER for both high tag
|
||||
// number form and OID components.
|
||||
static int parse_base128_integer(CBS *cbs, uint64_t *out) {
|
||||
int CBS_get_asn1_oid_component(CBS *cbs, uint64_t *out) {
|
||||
uint64_t v = 0;
|
||||
uint8_t b;
|
||||
do {
|
||||
@@ -319,8 +316,9 @@ static int parse_asn1_tag(CBS *cbs, CBS_ASN1_TAG *out) {
|
||||
CBS_ASN1_TAG tag = ((CBS_ASN1_TAG)tag_byte & 0xe0) << CBS_ASN1_TAG_SHIFT;
|
||||
CBS_ASN1_TAG tag_number = tag_byte & 0x1f;
|
||||
if (tag_number == 0x1f) {
|
||||
// High tag numbers are encoded in the same format as OID components.
|
||||
uint64_t v;
|
||||
if (!parse_base128_integer(cbs, &v) ||
|
||||
if (!CBS_get_asn1_oid_component(cbs, &v) ||
|
||||
// Check the tag number is within our supported bounds.
|
||||
v > CBS_ASN1_TAG_NUMBER_MASK ||
|
||||
// Small tag numbers should have used low tag number form, even in BER.
|
||||
@@ -747,9 +745,9 @@ int CBS_is_valid_asn1_oid(const CBS *cbs) {
|
||||
uint8_t v, prev = 0;
|
||||
while (CBS_get_u8(©, &v)) {
|
||||
// OID encodings are a sequence of minimally-encoded base-128 integers (see
|
||||
// `parse_base128_integer`). If `prev`'s MSB was clear, it was the last byte
|
||||
// of an integer (or `v` is the first byte). `v` is then the first byte of
|
||||
// the next integer. If first byte of an integer is 0x80, it is not
|
||||
// `CBS_get_asn1_oid_component`). If `prev`'s MSB was clear, it was the last
|
||||
// byte of an integer (or `v` is the first byte). `v` is then the first byte
|
||||
// of the next integer. If first byte of an integer is 0x80, it is not
|
||||
// minimally-encoded.
|
||||
if ((prev & 0x80) == 0 && v == 0x80) {
|
||||
return 0;
|
||||
@@ -770,7 +768,7 @@ char *CBS_asn1_oid_to_text(const CBS *cbs) {
|
||||
|
||||
// The first component is 40 * value1 + value2, where value1 is 0, 1, or 2.
|
||||
uint64_t v;
|
||||
if (!parse_base128_integer(©, &v)) {
|
||||
if (!CBS_get_asn1_oid_component(©, &v)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -785,7 +783,7 @@ char *CBS_asn1_oid_to_text(const CBS *cbs) {
|
||||
}
|
||||
|
||||
while (CBS_len(©) != 0) {
|
||||
if (!parse_base128_integer(©, &v) || !CBB_add_u8(&cbb, '.') ||
|
||||
if (!CBS_get_asn1_oid_component(©, &v) || !CBB_add_u8(&cbb, '.') ||
|
||||
!add_decimal(&cbb, v)) {
|
||||
goto err;
|
||||
}
|
||||
@@ -817,12 +815,12 @@ char *CBS_asn1_relative_oid_to_text(const CBS *cbs) {
|
||||
|
||||
// Relative OIDs must have at least one component.
|
||||
uint64_t v;
|
||||
if (!parse_base128_integer(©, &v) || !add_decimal(cbb.get(), v)) {
|
||||
if (!CBS_get_asn1_oid_component(©, &v) || !add_decimal(cbb.get(), v)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
while (CBS_len(©) != 0) {
|
||||
if (!parse_base128_integer(©, &v) || !CBB_add_u8(cbb.get(), '.') ||
|
||||
if (!CBS_get_asn1_oid_component(©, &v) || !CBB_add_u8(cbb.get(), '.') ||
|
||||
!add_decimal(cbb.get(), v)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -429,6 +429,16 @@ OPENSSL_EXPORT int CBS_is_valid_asn1_relative_oid(const CBS *cbs);
|
||||
// OID components are too large.
|
||||
OPENSSL_EXPORT char *CBS_asn1_relative_oid_to_text(const CBS *cbs);
|
||||
|
||||
// CBS_get_asn1_oid_component gets a single OID component from `cbs`. On
|
||||
// success, it sets `*out` to the value, advances `cbs` past the component, and
|
||||
// returns one. If the input does not contain a valid OID component or if the
|
||||
// OID component is bigger than `uint64_t`, it returns zero.
|
||||
//
|
||||
// Specifically, this decodes a non-empty, minimal-width, base-128, big-endian
|
||||
// integer. The high bit of each byte is set for continuation bytes and unset
|
||||
// for the final byte. This encoding is also used for DER tag numbers 31 and up.
|
||||
OPENSSL_EXPORT int CBS_get_asn1_oid_component(CBS *cbs, uint64_t *out);
|
||||
|
||||
// CBS_parse_generalized_time returns one if `cbs` is a valid DER-encoded, ASN.1
|
||||
// GeneralizedTime body within the limitations imposed by RFC 5280, or zero
|
||||
// otherwise. If `allow_timezone_offset` is non-zero, four-digit timezone
|
||||
@@ -706,6 +716,11 @@ OPENSSL_EXPORT int CBB_add_asn1_relative_oid_from_text(CBB *cbb,
|
||||
|
||||
// CBB_add_asn1_oid_component appends a single OID component to `cbb`.
|
||||
// It returns one on success and zero on error.
|
||||
//
|
||||
// Specifically, this encodes `value` as a non-empty, minimal-width, base-128,
|
||||
// big-endian integer. The high bit of each byte is set for continuation bytes
|
||||
// and unset for the final byte. This encoding is also used for DER tag numbers
|
||||
// 31 and up.
|
||||
OPENSSL_EXPORT int CBB_add_asn1_oid_component(CBB *cbb, uint64_t value);
|
||||
|
||||
// CBB_flush_asn1_set_of calls `CBB_flush` on `cbb` and then reorders the
|
||||
|
||||
Generated
+2
@@ -554,6 +554,7 @@
|
||||
#pragma redefine_extname CBS_get_asn1_element BORINGSSL_ADD_USER_LABEL_AND_PREFIX(CBS_get_asn1_element)
|
||||
#pragma redefine_extname CBS_get_asn1_int64 BORINGSSL_ADD_USER_LABEL_AND_PREFIX(CBS_get_asn1_int64)
|
||||
#pragma redefine_extname CBS_get_asn1_int64_with_tag BORINGSSL_ADD_USER_LABEL_AND_PREFIX(CBS_get_asn1_int64_with_tag)
|
||||
#pragma redefine_extname CBS_get_asn1_oid_component BORINGSSL_ADD_USER_LABEL_AND_PREFIX(CBS_get_asn1_oid_component)
|
||||
#pragma redefine_extname CBS_get_asn1_uint64 BORINGSSL_ADD_USER_LABEL_AND_PREFIX(CBS_get_asn1_uint64)
|
||||
#pragma redefine_extname CBS_get_asn1_uint64_with_tag BORINGSSL_ADD_USER_LABEL_AND_PREFIX(CBS_get_asn1_uint64_with_tag)
|
||||
#pragma redefine_extname CBS_get_bytes BORINGSSL_ADD_USER_LABEL_AND_PREFIX(CBS_get_bytes)
|
||||
@@ -3673,6 +3674,7 @@
|
||||
#define CBS_get_asn1_element BORINGSSL_ADD_PREFIX(CBS_get_asn1_element)
|
||||
#define CBS_get_asn1_int64 BORINGSSL_ADD_PREFIX(CBS_get_asn1_int64)
|
||||
#define CBS_get_asn1_int64_with_tag BORINGSSL_ADD_PREFIX(CBS_get_asn1_int64_with_tag)
|
||||
#define CBS_get_asn1_oid_component BORINGSSL_ADD_PREFIX(CBS_get_asn1_oid_component)
|
||||
#define CBS_get_asn1_uint64 BORINGSSL_ADD_PREFIX(CBS_get_asn1_uint64)
|
||||
#define CBS_get_asn1_uint64_with_tag BORINGSSL_ADD_PREFIX(CBS_get_asn1_uint64_with_tag)
|
||||
#define CBS_get_bytes BORINGSSL_ADD_PREFIX(CBS_get_bytes)
|
||||
|
||||
Reference in New Issue
Block a user