Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a20bb7ff8b | |||
| b04ea033a3 |
@@ -29,7 +29,10 @@ static const unsigned kMaxDepth = 2048;
|
||||
// is_string_type returns one if |tag| is a string type and zero otherwise. It
|
||||
// ignores the constructed bit.
|
||||
static int is_string_type(unsigned tag) {
|
||||
switch (tag & ~CBS_ASN1_CONSTRUCTED) {
|
||||
if ((tag & 0xc0) != 0) {
|
||||
return 0;
|
||||
}
|
||||
switch (tag & 0x1f) {
|
||||
case CBS_ASN1_BITSTRING:
|
||||
case CBS_ASN1_OCTETSTRING:
|
||||
case CBS_ASN1_UTF8STRING:
|
||||
|
||||
@@ -123,27 +123,27 @@ TEST(CBSTest, GetASN1) {
|
||||
uint64_t value;
|
||||
|
||||
CBS_init(&data, kData1, sizeof(kData1));
|
||||
EXPECT_FALSE(CBS_peek_asn1_tag(&data, CBS_ASN1_BOOLEAN));
|
||||
EXPECT_TRUE(CBS_peek_asn1_tag(&data, CBS_ASN1_SEQUENCE));
|
||||
EXPECT_FALSE(CBS_peek_asn1_tag(&data, 0x1));
|
||||
EXPECT_TRUE(CBS_peek_asn1_tag(&data, 0x30));
|
||||
|
||||
ASSERT_TRUE(CBS_get_asn1(&data, &contents, CBS_ASN1_SEQUENCE));
|
||||
ASSERT_TRUE(CBS_get_asn1(&data, &contents, 0x30));
|
||||
EXPECT_EQ(Bytes("\x01\x02"), Bytes(CBS_data(&contents), CBS_len(&contents)));
|
||||
|
||||
CBS_init(&data, kData2, sizeof(kData2));
|
||||
// data is truncated
|
||||
EXPECT_FALSE(CBS_get_asn1(&data, &contents, CBS_ASN1_SEQUENCE));
|
||||
EXPECT_FALSE(CBS_get_asn1(&data, &contents, 0x30));
|
||||
|
||||
CBS_init(&data, kData3, sizeof(kData3));
|
||||
// zero byte length of length
|
||||
EXPECT_FALSE(CBS_get_asn1(&data, &contents, CBS_ASN1_SEQUENCE));
|
||||
EXPECT_FALSE(CBS_get_asn1(&data, &contents, 0x30));
|
||||
|
||||
CBS_init(&data, kData4, sizeof(kData4));
|
||||
// long form mistakenly used.
|
||||
EXPECT_FALSE(CBS_get_asn1(&data, &contents, CBS_ASN1_SEQUENCE));
|
||||
EXPECT_FALSE(CBS_get_asn1(&data, &contents, 0x30));
|
||||
|
||||
CBS_init(&data, kData5, sizeof(kData5));
|
||||
// length takes too many bytes.
|
||||
EXPECT_FALSE(CBS_get_asn1(&data, &contents, CBS_ASN1_SEQUENCE));
|
||||
EXPECT_FALSE(CBS_get_asn1(&data, &contents, 0x30));
|
||||
|
||||
CBS_init(&data, kData1, sizeof(kData1));
|
||||
// wrong tag.
|
||||
@@ -151,72 +151,56 @@ TEST(CBSTest, GetASN1) {
|
||||
|
||||
CBS_init(&data, NULL, 0);
|
||||
// peek at empty data.
|
||||
EXPECT_FALSE(CBS_peek_asn1_tag(&data, CBS_ASN1_SEQUENCE));
|
||||
EXPECT_FALSE(CBS_peek_asn1_tag(&data, 0x30));
|
||||
|
||||
CBS_init(&data, NULL, 0);
|
||||
// optional elements at empty data.
|
||||
ASSERT_TRUE(CBS_get_optional_asn1(
|
||||
&data, &contents, &present,
|
||||
CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0));
|
||||
ASSERT_TRUE(CBS_get_optional_asn1(&data, &contents, &present, 0xa0));
|
||||
EXPECT_FALSE(present);
|
||||
ASSERT_TRUE(CBS_get_optional_asn1_octet_string(
|
||||
&data, &contents, &present,
|
||||
CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0));
|
||||
ASSERT_TRUE(
|
||||
CBS_get_optional_asn1_octet_string(&data, &contents, &present, 0xa0));
|
||||
EXPECT_FALSE(present);
|
||||
EXPECT_EQ(0u, CBS_len(&contents));
|
||||
ASSERT_TRUE(CBS_get_optional_asn1_octet_string(
|
||||
&data, &contents, NULL,
|
||||
CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0));
|
||||
ASSERT_TRUE(CBS_get_optional_asn1_octet_string(&data, &contents, NULL, 0xa0));
|
||||
EXPECT_EQ(0u, CBS_len(&contents));
|
||||
ASSERT_TRUE(CBS_get_optional_asn1_uint64(
|
||||
&data, &value, CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0, 42));
|
||||
ASSERT_TRUE(CBS_get_optional_asn1_uint64(&data, &value, 0xa0, 42));
|
||||
EXPECT_EQ(42u, value);
|
||||
|
||||
CBS_init(&data, kData6, sizeof(kData6));
|
||||
// optional element.
|
||||
ASSERT_TRUE(CBS_get_optional_asn1(
|
||||
&data, &contents, &present,
|
||||
CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0));
|
||||
ASSERT_TRUE(CBS_get_optional_asn1(&data, &contents, &present, 0xa0));
|
||||
EXPECT_FALSE(present);
|
||||
ASSERT_TRUE(CBS_get_optional_asn1(
|
||||
&data, &contents, &present,
|
||||
CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1));
|
||||
ASSERT_TRUE(CBS_get_optional_asn1(&data, &contents, &present, 0xa1));
|
||||
EXPECT_TRUE(present);
|
||||
EXPECT_EQ(Bytes("\x04\x01\x01"),
|
||||
Bytes(CBS_data(&contents), CBS_len(&contents)));
|
||||
|
||||
CBS_init(&data, kData6, sizeof(kData6));
|
||||
// optional octet string.
|
||||
ASSERT_TRUE(CBS_get_optional_asn1_octet_string(
|
||||
&data, &contents, &present,
|
||||
CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0));
|
||||
ASSERT_TRUE(
|
||||
CBS_get_optional_asn1_octet_string(&data, &contents, &present, 0xa0));
|
||||
EXPECT_FALSE(present);
|
||||
EXPECT_EQ(0u, CBS_len(&contents));
|
||||
ASSERT_TRUE(CBS_get_optional_asn1_octet_string(
|
||||
&data, &contents, &present,
|
||||
CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1));
|
||||
ASSERT_TRUE(
|
||||
CBS_get_optional_asn1_octet_string(&data, &contents, &present, 0xa1));
|
||||
EXPECT_TRUE(present);
|
||||
EXPECT_EQ(Bytes("\x01"), Bytes(CBS_data(&contents), CBS_len(&contents)));
|
||||
|
||||
CBS_init(&data, kData7, sizeof(kData7));
|
||||
// invalid optional octet string.
|
||||
EXPECT_FALSE(CBS_get_optional_asn1_octet_string(
|
||||
&data, &contents, &present,
|
||||
CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1));
|
||||
EXPECT_FALSE(
|
||||
CBS_get_optional_asn1_octet_string(&data, &contents, &present, 0xa1));
|
||||
|
||||
CBS_init(&data, kData8, sizeof(kData8));
|
||||
// optional integer.
|
||||
ASSERT_TRUE(CBS_get_optional_asn1_uint64(
|
||||
&data, &value, CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0, 42));
|
||||
ASSERT_TRUE(CBS_get_optional_asn1_uint64(&data, &value, 0xa0, 42));
|
||||
EXPECT_EQ(42u, value);
|
||||
ASSERT_TRUE(CBS_get_optional_asn1_uint64(
|
||||
&data, &value, CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1, 42));
|
||||
ASSERT_TRUE(CBS_get_optional_asn1_uint64(&data, &value, 0xa1, 42));
|
||||
EXPECT_EQ(1u, value);
|
||||
|
||||
CBS_init(&data, kData9, sizeof(kData9));
|
||||
// invalid optional integer.
|
||||
EXPECT_FALSE(CBS_get_optional_asn1_uint64(
|
||||
&data, &value, CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1, 42));
|
||||
EXPECT_FALSE(CBS_get_optional_asn1_uint64(&data, &value, 0xa1, 42));
|
||||
|
||||
unsigned tag;
|
||||
CBS_init(&data, kData1, sizeof(kData1));
|
||||
@@ -233,54 +217,6 @@ TEST(CBSTest, GetASN1) {
|
||||
Bytes(CBS_data(&contents), CBS_len(&contents)));
|
||||
}
|
||||
|
||||
TEST(CBSTest, ParseASN1Tag) {
|
||||
const struct {
|
||||
bool ok;
|
||||
unsigned tag;
|
||||
std::vector<uint8_t> in;
|
||||
} kTests[] = {
|
||||
{true, CBS_ASN1_SEQUENCE, {0x30, 0}},
|
||||
{true, CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 4, {0xa4, 0}},
|
||||
{true, CBS_ASN1_APPLICATION | 30, {0x5e, 0}},
|
||||
{true, CBS_ASN1_APPLICATION | 31, {0x5f, 0x1f, 0}},
|
||||
{true, CBS_ASN1_APPLICATION | 32, {0x5f, 0x20, 0}},
|
||||
{true,
|
||||
CBS_ASN1_PRIVATE | CBS_ASN1_CONSTRUCTED | 0x1fffffff,
|
||||
{0xff, 0x81, 0xff, 0xff, 0xff, 0x7f, 0}},
|
||||
// Tag number fits in unsigned but not |CBS_ASN1_TAG_NUMBER_MASK|.
|
||||
{false, 0, {0xff, 0x82, 0xff, 0xff, 0xff, 0x7f, 0}},
|
||||
// Tag number does not fit in unsigned.
|
||||
{false, 0, {0xff, 0x90, 0x80, 0x80, 0x80, 0, 0}},
|
||||
// Tag number is not minimally-encoded
|
||||
{false, 0, {0x5f, 0x80, 0x1f, 0}},
|
||||
// Tag number should have used short form.
|
||||
{false, 0, {0x5f, 0x80, 0x1e, 0}},
|
||||
};
|
||||
for (const auto &t : kTests) {
|
||||
SCOPED_TRACE(Bytes(t.in));
|
||||
unsigned tag;
|
||||
CBS cbs, child;
|
||||
CBS_init(&cbs, t.in.data(), t.in.size());
|
||||
ASSERT_EQ(t.ok, !!CBS_get_any_asn1(&cbs, &child, &tag));
|
||||
if (t.ok) {
|
||||
EXPECT_EQ(t.tag, tag);
|
||||
EXPECT_EQ(0u, CBS_len(&child));
|
||||
EXPECT_EQ(0u, CBS_len(&cbs));
|
||||
|
||||
CBS_init(&cbs, t.in.data(), t.in.size());
|
||||
EXPECT_TRUE(CBS_peek_asn1_tag(&cbs, t.tag));
|
||||
EXPECT_FALSE(CBS_peek_asn1_tag(&cbs, t.tag + 1));
|
||||
|
||||
EXPECT_TRUE(CBS_get_asn1(&cbs, &child, t.tag));
|
||||
EXPECT_EQ(0u, CBS_len(&child));
|
||||
EXPECT_EQ(0u, CBS_len(&cbs));
|
||||
|
||||
CBS_init(&cbs, t.in.data(), t.in.size());
|
||||
EXPECT_FALSE(CBS_get_asn1(&cbs, &child, t.tag + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(CBSTest, GetOptionalASN1Bool) {
|
||||
static const uint8_t kTrue[] = {0x0a, 3, CBS_ASN1_BOOLEAN, 1, 0xff};
|
||||
static const uint8_t kFalse[] = {0x0a, 3, CBS_ASN1_BOOLEAN, 1, 0x00};
|
||||
@@ -480,42 +416,15 @@ TEST(CBBTest, Misuse) {
|
||||
}
|
||||
|
||||
TEST(CBBTest, ASN1) {
|
||||
static const uint8_t kExpected[] = {
|
||||
// SEQUENCE { 1 2 3 }
|
||||
0x30, 3, 1, 2, 3,
|
||||
// [4 CONSTRUCTED] { 4 5 6 }
|
||||
0xa4, 3, 4, 5, 6,
|
||||
// [APPLICATION 30 PRIMITIVE] { 7 8 9 }
|
||||
0x5e, 3, 7, 8, 9,
|
||||
// [APPLICATION 31 PRIMITIVE] { 10 11 12 }
|
||||
0x5f, 0x1f, 3, 10, 11, 12,
|
||||
// [PRIVATE 2^29-1 CONSTRUCTED] { 13 14 15 }
|
||||
0xff, 0x81, 0xff, 0xff, 0xff, 0x7f, 3, 13, 14, 15,
|
||||
};
|
||||
static const uint8_t kExpected[] = {0x30, 3, 1, 2, 3};
|
||||
uint8_t *buf;
|
||||
size_t buf_len;
|
||||
bssl::ScopedCBB cbb;
|
||||
CBB contents, inner_contents;
|
||||
|
||||
ASSERT_TRUE(CBB_init(cbb.get(), 0));
|
||||
ASSERT_TRUE(CBB_add_asn1(cbb.get(), &contents, CBS_ASN1_SEQUENCE));
|
||||
ASSERT_TRUE(CBB_add_asn1(cbb.get(), &contents, 0x30));
|
||||
ASSERT_TRUE(CBB_add_bytes(&contents, (const uint8_t *)"\x01\x02\x03", 3));
|
||||
ASSERT_TRUE(
|
||||
CBB_add_asn1(cbb.get(), &contents,
|
||||
CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 4));
|
||||
ASSERT_TRUE(CBB_add_bytes(&contents, (const uint8_t *)"\x04\x05\x06", 3));
|
||||
ASSERT_TRUE(
|
||||
CBB_add_asn1(cbb.get(), &contents,
|
||||
CBS_ASN1_APPLICATION | 30));
|
||||
ASSERT_TRUE(CBB_add_bytes(&contents, (const uint8_t *)"\x07\x08\x09", 3));
|
||||
ASSERT_TRUE(
|
||||
CBB_add_asn1(cbb.get(), &contents,
|
||||
CBS_ASN1_APPLICATION | 31));
|
||||
ASSERT_TRUE(CBB_add_bytes(&contents, (const uint8_t *)"\x0a\x0b\x0c", 3));
|
||||
ASSERT_TRUE(
|
||||
CBB_add_asn1(cbb.get(), &contents,
|
||||
CBS_ASN1_PRIVATE | CBS_ASN1_CONSTRUCTED | 0x1fffffff));
|
||||
ASSERT_TRUE(CBB_add_bytes(&contents, (const uint8_t *)"\x0d\x0e\x0f", 3));
|
||||
ASSERT_TRUE(CBB_finish(cbb.get(), &buf, &buf_len));
|
||||
bssl::UniquePtr<uint8_t> scoper(buf);
|
||||
|
||||
@@ -523,7 +432,7 @@ TEST(CBBTest, ASN1) {
|
||||
|
||||
std::vector<uint8_t> test_data(100000, 0x42);
|
||||
ASSERT_TRUE(CBB_init(cbb.get(), 0));
|
||||
ASSERT_TRUE(CBB_add_asn1(cbb.get(), &contents, CBS_ASN1_SEQUENCE));
|
||||
ASSERT_TRUE(CBB_add_asn1(cbb.get(), &contents, 0x30));
|
||||
ASSERT_TRUE(CBB_add_bytes(&contents, test_data.data(), 130));
|
||||
ASSERT_TRUE(CBB_finish(cbb.get(), &buf, &buf_len));
|
||||
scoper.reset(buf);
|
||||
@@ -533,7 +442,7 @@ TEST(CBBTest, ASN1) {
|
||||
EXPECT_EQ(Bytes(test_data.data(), 130), Bytes(buf + 3, 130));
|
||||
|
||||
ASSERT_TRUE(CBB_init(cbb.get(), 0));
|
||||
ASSERT_TRUE(CBB_add_asn1(cbb.get(), &contents, CBS_ASN1_SEQUENCE));
|
||||
ASSERT_TRUE(CBB_add_asn1(cbb.get(), &contents, 0x30));
|
||||
ASSERT_TRUE(CBB_add_bytes(&contents, test_data.data(), 1000));
|
||||
ASSERT_TRUE(CBB_finish(cbb.get(), &buf, &buf_len));
|
||||
scoper.reset(buf);
|
||||
@@ -543,8 +452,8 @@ TEST(CBBTest, ASN1) {
|
||||
EXPECT_EQ(Bytes(test_data.data(), 1000), Bytes(buf + 4, 1000));
|
||||
|
||||
ASSERT_TRUE(CBB_init(cbb.get(), 0));
|
||||
ASSERT_TRUE(CBB_add_asn1(cbb.get(), &contents, CBS_ASN1_SEQUENCE));
|
||||
ASSERT_TRUE(CBB_add_asn1(&contents, &inner_contents, CBS_ASN1_SEQUENCE));
|
||||
ASSERT_TRUE(CBB_add_asn1(cbb.get(), &contents, 0x30));
|
||||
ASSERT_TRUE(CBB_add_asn1(&contents, &inner_contents, 0x30));
|
||||
ASSERT_TRUE(CBB_add_bytes(&inner_contents, test_data.data(), 100000));
|
||||
ASSERT_TRUE(CBB_finish(cbb.get(), &buf, &buf_len));
|
||||
scoper.reset(buf);
|
||||
@@ -581,12 +490,6 @@ TEST(CBSTest, BerConvert) {
|
||||
static const uint8_t kIndefBER[] = {0x30, 0x80, 0x01, 0x01, 0x02, 0x00, 0x00};
|
||||
static const uint8_t kIndefDER[] = {0x30, 0x03, 0x01, 0x01, 0x02};
|
||||
|
||||
// kIndefBER2 contains a constructed [APPLICATION 31] with an indefinite
|
||||
// length.
|
||||
static const uint8_t kIndefBER2[] = {0x7f, 0x1f, 0x80, 0x01,
|
||||
0x01, 0x02, 0x00, 0x00};
|
||||
static const uint8_t kIndefDER2[] = {0x7f, 0x1f, 0x03, 0x01, 0x01, 0x02};
|
||||
|
||||
// kOctetStringBER contains an indefinite length OCTET STRING with two parts.
|
||||
// These parts need to be concatenated in DER form.
|
||||
static const uint8_t kOctetStringBER[] = {0x24, 0x80, 0x04, 0x02, 0, 1,
|
||||
@@ -631,8 +534,6 @@ TEST(CBSTest, BerConvert) {
|
||||
sizeof(kSimpleBER));
|
||||
ExpectBerConvert("kIndefBER", kIndefDER, sizeof(kIndefDER), kIndefBER,
|
||||
sizeof(kIndefBER));
|
||||
ExpectBerConvert("kIndefBER2", kIndefDER2, sizeof(kIndefDER2), kIndefBER2,
|
||||
sizeof(kIndefBER2));
|
||||
ExpectBerConvert("kOctetStringBER", kOctetStringDER, sizeof(kOctetStringDER),
|
||||
kOctetStringBER, sizeof(kOctetStringBER));
|
||||
ExpectBerConvert("kNSSBER", kNSSDER, sizeof(kNSSDER), kNSSBER,
|
||||
|
||||
+8
-11
@@ -356,20 +356,17 @@ static int add_base128_integer(CBB *cbb, uint32_t v) {
|
||||
}
|
||||
|
||||
int CBB_add_asn1(CBB *cbb, CBB *out_contents, unsigned tag) {
|
||||
if (!CBB_flush(cbb)) {
|
||||
if (tag > 0xff ||
|
||||
(tag & 0x1f) == 0x1f) {
|
||||
// Long form identifier octets are not supported. Further, all current valid
|
||||
// tag serializations are 8 bits.
|
||||
cbb->base->error = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Split the tag into leading bits and tag number.
|
||||
uint8_t tag_bits = (tag >> CBS_ASN1_TAG_SHIFT) & 0xe0;
|
||||
unsigned tag_number = tag & CBS_ASN1_TAG_NUMBER_MASK;
|
||||
if (tag_number >= 0x1f) {
|
||||
// Set all the bits in the tag number to signal high tag number form.
|
||||
if (!CBB_add_u8(cbb, tag_bits | 0x1f) ||
|
||||
!add_base128_integer(cbb, tag_number)) {
|
||||
return 0;
|
||||
}
|
||||
} else if (!CBB_add_u8(cbb, tag_bits | tag_number)) {
|
||||
if (!CBB_flush(cbb) ||
|
||||
// |tag|'s representation matches the DER encoding.
|
||||
!CBB_add_u8(cbb, (uint8_t)tag)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+22
-64
@@ -175,9 +175,18 @@ int CBS_get_u24_length_prefixed(CBS *cbs, CBS *out) {
|
||||
return cbs_get_length_prefixed(cbs, out, 3);
|
||||
}
|
||||
|
||||
static int parse_asn1_tag(CBS *cbs, unsigned *out) {
|
||||
uint8_t tag_byte;
|
||||
if (!CBS_get_u8(cbs, &tag_byte)) {
|
||||
static int cbs_get_any_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag,
|
||||
size_t *out_header_len, int ber_ok) {
|
||||
uint8_t tag, length_byte;
|
||||
CBS header = *cbs;
|
||||
CBS throwaway;
|
||||
|
||||
if (out == NULL) {
|
||||
out = &throwaway;
|
||||
}
|
||||
|
||||
if (!CBS_get_u8(&header, &tag) ||
|
||||
!CBS_get_u8(&header, &length_byte)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -188,70 +197,22 @@ static int parse_asn1_tag(CBS *cbs, unsigned *out) {
|
||||
// allotted bits), then the tag is more than one byte long and the
|
||||
// continuation bytes contain the tag number. This parser only supports tag
|
||||
// numbers less than 31 (and thus single-byte tags).
|
||||
unsigned tag = ((unsigned)tag_byte & 0xe0) << CBS_ASN1_TAG_SHIFT;
|
||||
unsigned tag_number = tag_byte & 0x1f;
|
||||
if (tag_number == 0x1f) {
|
||||
tag_number = 0;
|
||||
for (;;) {
|
||||
if (!CBS_get_u8(cbs, &tag_byte) ||
|
||||
((tag_number << 7) >> 7) != tag_number) {
|
||||
return 0;
|
||||
}
|
||||
tag_number = (tag_number << 7) | (tag_byte & 0x7f);
|
||||
// The tag must be represented in the minimal number of bytes.
|
||||
if (tag_number == 0) {
|
||||
return 0;
|
||||
}
|
||||
if ((tag_byte & 0x80) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (// Check the tag number is within our supported bounds.
|
||||
tag_number > CBS_ASN1_TAG_NUMBER_MASK ||
|
||||
// Small tag numbers should have used low tag number form.
|
||||
tag_number < 0x1f) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
tag |= tag_number;
|
||||
|
||||
*out = tag;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int cbs_get_any_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag,
|
||||
size_t *out_header_len, int ber_ok) {
|
||||
CBS header = *cbs;
|
||||
CBS throwaway;
|
||||
|
||||
if (out == NULL) {
|
||||
out = &throwaway;
|
||||
}
|
||||
|
||||
unsigned tag;
|
||||
if (!parse_asn1_tag(&header, &tag)) {
|
||||
if ((tag & 0x1f) == 0x1f) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (out_tag != NULL) {
|
||||
*out_tag = tag;
|
||||
}
|
||||
|
||||
uint8_t length_byte;
|
||||
if (!CBS_get_u8(&header, &length_byte)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t header_len = CBS_len(cbs) - CBS_len(&header);
|
||||
|
||||
size_t len;
|
||||
// The format for the length encoding is specified in ITU-T X.690 section
|
||||
// 8.1.3.
|
||||
if ((length_byte & 0x80) == 0) {
|
||||
// Short form length.
|
||||
len = ((size_t) length_byte) + header_len;
|
||||
len = ((size_t) length_byte) + 2;
|
||||
if (out_header_len != NULL) {
|
||||
*out_header_len = header_len;
|
||||
*out_header_len = 2;
|
||||
}
|
||||
} else {
|
||||
// The high bit indicate that this is the long form, while the next 7 bits
|
||||
@@ -263,9 +224,9 @@ static int cbs_get_any_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag,
|
||||
if (ber_ok && (tag & CBS_ASN1_CONSTRUCTED) != 0 && num_bytes == 0) {
|
||||
// indefinite length
|
||||
if (out_header_len != NULL) {
|
||||
*out_header_len = header_len;
|
||||
*out_header_len = 2;
|
||||
}
|
||||
return CBS_get_bytes(cbs, out, header_len);
|
||||
return CBS_get_bytes(cbs, out, 2);
|
||||
}
|
||||
|
||||
// ITU-T X.690 clause 8.1.3.5.c specifies that the value 0xff shall not be
|
||||
@@ -288,13 +249,13 @@ static int cbs_get_any_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag,
|
||||
return 0;
|
||||
}
|
||||
len = len32;
|
||||
if (len + header_len + num_bytes < len) {
|
||||
if (len + 2 + num_bytes < len) {
|
||||
// Overflow.
|
||||
return 0;
|
||||
}
|
||||
len += header_len + num_bytes;
|
||||
len += 2 + num_bytes;
|
||||
if (out_header_len != NULL) {
|
||||
*out_header_len = header_len + num_bytes;
|
||||
*out_header_len = 2 + num_bytes;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -362,10 +323,7 @@ int CBS_peek_asn1_tag(const CBS *cbs, unsigned tag_value) {
|
||||
if (CBS_len(cbs) < 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
CBS copy = *cbs;
|
||||
unsigned actual_tag;
|
||||
return parse_asn1_tag(©, &actual_tag) && tag_value == actual_tag;
|
||||
return CBS_data(cbs)[0] == tag_value;
|
||||
}
|
||||
|
||||
int CBS_get_asn1_uint64(CBS *cbs, uint64_t *out) {
|
||||
|
||||
@@ -232,7 +232,7 @@ $code.=<<___;
|
||||
vmovdqu 32*8-128($ap), $ACC8
|
||||
|
||||
lea 192(%rsp), $tp0 # 64+128=192
|
||||
vpbroadcastq .Land_mask(%rip), $AND_MASK
|
||||
vmovdqu .Land_mask(%rip), $AND_MASK
|
||||
jmp .LOOP_GRANDE_SQR_1024
|
||||
|
||||
.align 32
|
||||
@@ -1082,10 +1082,10 @@ $code.=<<___;
|
||||
vpmuludq 32*6-128($np),$Yi,$TEMP1
|
||||
vpaddq $TEMP1,$ACC6,$ACC6
|
||||
vpmuludq 32*7-128($np),$Yi,$TEMP2
|
||||
vpblendd \$3, $ZERO, $ACC9, $ACC9 # correct $ACC3
|
||||
vpblendd \$3, $ZERO, $ACC9, $TEMP1 # correct $ACC3
|
||||
vpaddq $TEMP2,$ACC7,$ACC7
|
||||
vpmuludq 32*8-128($np),$Yi,$TEMP0
|
||||
vpaddq $ACC9, $ACC3, $ACC3 # correct $ACC3
|
||||
vpaddq $TEMP1, $ACC3, $ACC3 # correct $ACC3
|
||||
vpaddq $TEMP0,$ACC8,$ACC8
|
||||
|
||||
mov %rbx, %rax
|
||||
@@ -1098,7 +1098,9 @@ $code.=<<___;
|
||||
vmovdqu -8+32*2-128($ap),$TEMP2
|
||||
|
||||
mov $r1, %rax
|
||||
vpblendd \$0xfc, $ZERO, $ACC9, $ACC9 # correct $ACC3
|
||||
imull $n0, %eax
|
||||
vpaddq $ACC9,$ACC4,$ACC4 # correct $ACC3
|
||||
and \$0x1fffffff, %eax
|
||||
|
||||
imulq 16-128($ap),%rbx
|
||||
@@ -1334,15 +1336,12 @@ ___
|
||||
# But as we underutilize resources, it's possible to correct in
|
||||
# each iteration with marginal performance loss. But then, as
|
||||
# we do it in each iteration, we can correct less digits, and
|
||||
# avoid performance penalties completely. Also note that we
|
||||
# correct only three digits out of four. This works because
|
||||
# most significant digit is subjected to less additions.
|
||||
# avoid performance penalties completely.
|
||||
|
||||
$TEMP0 = $ACC9;
|
||||
$TEMP3 = $Bi;
|
||||
$TEMP4 = $Yi;
|
||||
$code.=<<___;
|
||||
vpermq \$0, $AND_MASK, $AND_MASK
|
||||
vpaddq (%rsp), $TEMP1, $ACC0
|
||||
|
||||
vpsrlq \$29, $ACC0, $TEMP1
|
||||
@@ -1790,7 +1789,7 @@ $code.=<<___;
|
||||
|
||||
.align 64
|
||||
.Land_mask:
|
||||
.quad 0x1fffffff,0x1fffffff,0x1fffffff,-1
|
||||
.quad 0x1fffffff,0x1fffffff,0x1fffffff,0x1fffffff
|
||||
.Lscatter_permd:
|
||||
.long 0,2,4,6,7,7,7,7
|
||||
.Lgather_permd:
|
||||
|
||||
@@ -10507,6 +10507,12 @@ A = -80000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
E = 61803d4973ae68cfb2ba6770dbed70d36760fa42c01a16d1482eacf0d01adf7a917bc86ece58a73b920295c1291b90f49167ef856ecad149330e1fd49ec71392fb62d47270b53e6d4f3c8f044b80a5736753364896932abc6d872c4c5e135d1edb200597a93ceb262ff6c99079177cd10808b9ed20c8cd7352d80ac7f6963103
|
||||
M = b5d257b2c50b050d42f0852eff5cfa2571157c500cd0bd9aa0b2ccdd89c531c9609d520eb81d928fb52b06da25dc713561aa0bd365ee56db9e62ac6787a85936990f44438363560f7af9e0c16f378e5b83f658252390d849401817624da97ec613a1b855fd901847352f434a777e4e32af0cb4033c7547fb6437d067fcd3d965
|
||||
|
||||
# Regression test for CVE-2017-3738.
|
||||
ModExp = d360792bd8210786607817c3dda64cc38c8d0f25569597cb1f363c7919a0c3587baff01a2283edaeb04fc288ac0ab3f279b2a89ffcb452d8bdf72422a9f9780f4aa702dc964cf033149d3a339883062cab8564aebdbfac0bf68985e522c6fe545b346044690c525ca85d3f4eb3e3c25cdf541545afc84a309e9b1d7807003461
|
||||
A = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2020202020df
|
||||
E = 2020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020FF2020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2020202020ff
|
||||
|
||||
|
||||
# Exp tests.
|
||||
#
|
||||
|
||||
@@ -835,7 +835,7 @@ TEST(X509Test, TestFromBuffer) {
|
||||
|
||||
/* This ensures the X509 took a reference to |buf|, otherwise this will be a
|
||||
* reference to free memory and ASAN should notice. */
|
||||
ASSERT_EQ(0x30, enc_pointer[0]);
|
||||
ASSERT_EQ(CBS_ASN1_SEQUENCE, enc_pointer[0]);
|
||||
}
|
||||
|
||||
TEST(X509Test, TestFromBufferWithTrailingData) {
|
||||
|
||||
@@ -164,36 +164,34 @@ OPENSSL_EXPORT int CBS_get_u24_length_prefixed(CBS *cbs, CBS *out);
|
||||
#define CBS_ASN1_UNIVERSALSTRING 0x1cu
|
||||
#define CBS_ASN1_BMPSTRING 0x1eu
|
||||
|
||||
// CBS_ASN1_TAG_SHIFT is how much the in-memory representation shifts the class
|
||||
// and constructed bits from the DER serialization. This allows representing tag
|
||||
// numbers beyond 31.
|
||||
//
|
||||
// Consumers must use the following constants to decompose or assemble tags.
|
||||
#define CBS_ASN1_TAG_SHIFT 24
|
||||
|
||||
// CBS_ASN1_CONSTRUCTED may be ORed into a tag to toggle the constructed
|
||||
// bit. |CBS| and |CBB| APIs consider the constructed bit to be part of the
|
||||
// tag.
|
||||
#define CBS_ASN1_CONSTRUCTED (0x20u << CBS_ASN1_TAG_SHIFT)
|
||||
#define CBS_ASN1_CONSTRUCTED 0x20u
|
||||
|
||||
// The following values specify the tag class and may be ORed into a tag number
|
||||
// to produce the final tag. If none is used, the tag will be UNIVERSAL.
|
||||
#define CBS_ASN1_UNIVERSAL (0u << CBS_ASN1_TAG_SHIFT)
|
||||
#define CBS_ASN1_APPLICATION (0x40u << CBS_ASN1_TAG_SHIFT)
|
||||
#define CBS_ASN1_CONTEXT_SPECIFIC (0x80u << CBS_ASN1_TAG_SHIFT)
|
||||
#define CBS_ASN1_PRIVATE (0xc0u << CBS_ASN1_TAG_SHIFT)
|
||||
// The following values specify the constructed bit or tag class and may be ORed
|
||||
// into a tag number to produce the final tag. If none is used, the tag will be
|
||||
// UNIVERSAL.
|
||||
//
|
||||
// Note that although they currently match the DER serialization, consumers must
|
||||
// use these bits rather than make assumptions about the representation. This is
|
||||
// to allow for tag numbers beyond 31 in the future.
|
||||
#define CBS_ASN1_APPLICATION 0x40u
|
||||
#define CBS_ASN1_CONTEXT_SPECIFIC 0x80u
|
||||
#define CBS_ASN1_PRIVATE 0xc0u
|
||||
|
||||
// CBS_ASN1_CLASS_MASK may be ANDed with a tag to query its class. This will
|
||||
// give one of the four values above.
|
||||
#define CBS_ASN1_CLASS_MASK (0xc0u << CBS_ASN1_TAG_SHIFT)
|
||||
// CBS_ASN1_CLASS_MASK may be ANDed with a tag to query its class.
|
||||
#define CBS_ASN1_CLASS_MASK 0xc0u
|
||||
|
||||
// CBS_ASN1_TAG_NUMBER_MASK may be ANDed with a tag to query its number.
|
||||
#define CBS_ASN1_TAG_NUMBER_MASK ((1u << (5 + CBS_ASN1_TAG_SHIFT)) - 1)
|
||||
#define CBS_ASN1_TAG_NUMBER_MASK 0x1fu
|
||||
|
||||
// CBS_get_asn1 sets |*out| to the contents of DER-encoded, ASN.1 element (not
|
||||
// including tag and length bytes) and advances |cbs| over it. The ASN.1
|
||||
// element must match |tag_value|. It returns one on success and zero
|
||||
// on error.
|
||||
//
|
||||
// Tag numbers greater than 30 are not supported (i.e. short form only).
|
||||
OPENSSL_EXPORT int CBS_get_asn1(CBS *cbs, CBS *out, unsigned tag_value);
|
||||
|
||||
// CBS_get_asn1_element acts like |CBS_get_asn1| but |out| will include the
|
||||
@@ -211,12 +209,16 @@ OPENSSL_EXPORT int CBS_peek_asn1_tag(const CBS *cbs, unsigned tag_value);
|
||||
// (not including tag and length bytes), sets |*out_tag| to the tag number, and
|
||||
// advances |*cbs|. It returns one on success and zero on error. Either of |out|
|
||||
// and |out_tag| may be NULL to ignore the value.
|
||||
//
|
||||
// Tag numbers greater than 30 are not supported (i.e. short form only).
|
||||
OPENSSL_EXPORT int CBS_get_any_asn1(CBS *cbs, CBS *out, unsigned *out_tag);
|
||||
|
||||
// CBS_get_any_asn1_element sets |*out| to contain the next ASN.1 element from
|
||||
// |*cbs| (including header bytes) and advances |*cbs|. It sets |*out_tag| to
|
||||
// the tag number and |*out_header_len| to the length of the ASN.1 header. Each
|
||||
// of |out|, |out_tag|, and |out_header_len| may be NULL to ignore the value.
|
||||
//
|
||||
// Tag numbers greater than 30 are not supported (i.e. short form only).
|
||||
OPENSSL_EXPORT int CBS_get_any_asn1_element(CBS *cbs, CBS *out,
|
||||
unsigned *out_tag,
|
||||
size_t *out_header_len);
|
||||
@@ -394,7 +396,9 @@ OPENSSL_EXPORT int CBB_add_u24_length_prefixed(CBB *cbb, CBB *out_contents);
|
||||
|
||||
// CBB_add_asn1 sets |*out_contents| to a |CBB| into which the contents of an
|
||||
// ASN.1 object can be written. The |tag| argument will be used as the tag for
|
||||
// the object. It returns one on success or zero on error.
|
||||
// the object. Passing in |tag| number 31 will return in an error since only
|
||||
// single octet identifiers are supported. It returns one on success or zero
|
||||
// on error.
|
||||
OPENSSL_EXPORT int CBB_add_asn1(CBB *cbb, CBB *out_contents, unsigned tag);
|
||||
|
||||
// CBB_add_bytes appends |len| bytes from |data| to |cbb|. It returns one on
|
||||
|
||||
Reference in New Issue
Block a user