Mirror of BoringSSL (grpc依赖)
https://boringssl.googlesource.com/boringssl
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
365 lines
11 KiB
365 lines
11 KiB
// Copyright 2015 The Chromium Authors |
|
// Use of this source code is governed by a BSD-style license that can be |
|
// found in the LICENSE file. |
|
|
|
#include "parser.h" |
|
|
|
#include "input.h" |
|
#include "parse_values.h" |
|
#include <gtest/gtest.h> |
|
|
|
namespace bssl::der::test { |
|
|
|
TEST(ParserTest, ConsumesAllBytesOfTLV) { |
|
const uint8_t der[] = {0x04 /* OCTET STRING */, 0x00}; |
|
Parser parser((Input(der))); |
|
Tag tag; |
|
Input value; |
|
ASSERT_TRUE(parser.ReadTagAndValue(&tag, &value)); |
|
ASSERT_EQ(kOctetString, tag); |
|
ASSERT_FALSE(parser.HasMore()); |
|
} |
|
|
|
TEST(ParserTest, CanReadRawTLV) { |
|
const uint8_t der[] = {0x02, 0x01, 0x01}; |
|
Parser parser((Input(der))); |
|
Input tlv; |
|
ASSERT_TRUE(parser.ReadRawTLV(&tlv)); |
|
ByteReader tlv_reader(tlv); |
|
size_t tlv_len = tlv_reader.BytesLeft(); |
|
ASSERT_EQ(3u, tlv_len); |
|
Input tlv_data; |
|
ASSERT_TRUE(tlv_reader.ReadBytes(tlv_len, &tlv_data)); |
|
ASSERT_FALSE(parser.HasMore()); |
|
} |
|
|
|
TEST(ParserTest, IgnoresContentsOfInnerValues) { |
|
// This is a SEQUENCE which has one member. The member is another SEQUENCE |
|
// with an invalid encoding - its length is too long. |
|
const uint8_t der[] = {0x30, 0x02, 0x30, 0x7e}; |
|
Parser parser((Input(der))); |
|
Tag tag; |
|
Input value; |
|
ASSERT_TRUE(parser.ReadTagAndValue(&tag, &value)); |
|
} |
|
|
|
TEST(ParserTest, FailsIfLengthOverlapsAnotherTLV) { |
|
// This DER encoding has 2 top-level TLV tuples. The first is a SEQUENCE; |
|
// the second is an INTEGER. The SEQUENCE contains an INTEGER, but its length |
|
// is longer than what it has contents for. |
|
const uint8_t der[] = {0x30, 0x02, 0x02, 0x01, 0x02, 0x01, 0x01}; |
|
Parser parser((Input(der))); |
|
|
|
Parser inner_sequence; |
|
ASSERT_TRUE(parser.ReadSequence(&inner_sequence)); |
|
uint64_t int_value; |
|
ASSERT_TRUE(parser.ReadUint64(&int_value)); |
|
ASSERT_EQ(1u, int_value); |
|
ASSERT_FALSE(parser.HasMore()); |
|
|
|
// Try to read the INTEGER from the SEQUENCE, which should fail. |
|
Tag tag; |
|
Input value; |
|
ASSERT_FALSE(inner_sequence.ReadTagAndValue(&tag, &value)); |
|
} |
|
|
|
TEST(ParserTest, ReadOptionalTagPresent) { |
|
// DER encoding of 2 top-level TLV values: |
|
// INTEGER { 1 } |
|
// OCTET_STRING { `02` } |
|
const uint8_t der[] = {0x02, 0x01, 0x01, 0x04, 0x01, 0x02}; |
|
Parser parser((Input(der))); |
|
|
|
Input value; |
|
bool present; |
|
ASSERT_TRUE(parser.ReadOptionalTag(kInteger, &value, &present)); |
|
ASSERT_TRUE(present); |
|
const uint8_t expected_int_value[] = {0x01}; |
|
ASSERT_EQ(Input(expected_int_value), value); |
|
|
|
Tag tag; |
|
ASSERT_TRUE(parser.ReadTagAndValue(&tag, &value)); |
|
ASSERT_EQ(kOctetString, tag); |
|
const uint8_t expected_octet_string_value[] = {0x02}; |
|
ASSERT_EQ(Input(expected_octet_string_value), value); |
|
|
|
ASSERT_FALSE(parser.HasMore()); |
|
} |
|
|
|
TEST(ParserTest, ReadOptionalTag2Present) { |
|
// DER encoding of 2 top-level TLV values: |
|
// INTEGER { 1 } |
|
// OCTET_STRING { `02` } |
|
const uint8_t der[] = {0x02, 0x01, 0x01, 0x04, 0x01, 0x02}; |
|
Parser parser((Input(der))); |
|
|
|
std::optional<Input> optional_value; |
|
ASSERT_TRUE(parser.ReadOptionalTag(kInteger, &optional_value)); |
|
ASSERT_TRUE(optional_value.has_value()); |
|
const uint8_t expected_int_value[] = {0x01}; |
|
ASSERT_EQ(Input(expected_int_value), *optional_value); |
|
|
|
Tag tag; |
|
Input value; |
|
ASSERT_TRUE(parser.ReadTagAndValue(&tag, &value)); |
|
ASSERT_EQ(kOctetString, tag); |
|
const uint8_t expected_octet_string_value[] = {0x02}; |
|
ASSERT_EQ(Input(expected_octet_string_value), value); |
|
|
|
ASSERT_FALSE(parser.HasMore()); |
|
} |
|
|
|
TEST(ParserTest, ReadOptionalTagNotPresent) { |
|
// DER encoding of 1 top-level TLV value: |
|
// OCTET_STRING { `02` } |
|
const uint8_t der[] = {0x04, 0x01, 0x02}; |
|
Parser parser((Input(der))); |
|
|
|
Input value; |
|
bool present; |
|
ASSERT_TRUE(parser.ReadOptionalTag(kInteger, &value, &present)); |
|
ASSERT_FALSE(present); |
|
|
|
Tag tag; |
|
ASSERT_TRUE(parser.ReadTagAndValue(&tag, &value)); |
|
ASSERT_EQ(kOctetString, tag); |
|
const uint8_t expected_octet_string_value[] = {0x02}; |
|
ASSERT_EQ(Input(expected_octet_string_value), value); |
|
|
|
ASSERT_FALSE(parser.HasMore()); |
|
} |
|
|
|
TEST(ParserTest, ReadOptionalTag2NotPresent) { |
|
// DER encoding of 1 top-level TLV value: |
|
// OCTET_STRING { `02` } |
|
const uint8_t der[] = {0x04, 0x01, 0x02}; |
|
Parser parser((Input(der))); |
|
|
|
std::optional<Input> optional_value; |
|
ASSERT_TRUE(parser.ReadOptionalTag(kInteger, &optional_value)); |
|
ASSERT_FALSE(optional_value.has_value()); |
|
|
|
Tag tag; |
|
Input value; |
|
ASSERT_TRUE(parser.ReadTagAndValue(&tag, &value)); |
|
ASSERT_EQ(kOctetString, tag); |
|
const uint8_t expected_octet_string_value[] = {0x02}; |
|
ASSERT_EQ(Input(expected_octet_string_value), value); |
|
|
|
ASSERT_FALSE(parser.HasMore()); |
|
} |
|
|
|
TEST(ParserTest, CanSkipOptionalTagAtEndOfInput) { |
|
const uint8_t der[] = {0x02 /* INTEGER */, 0x01, 0x01}; |
|
Parser parser((Input(der))); |
|
|
|
Tag tag; |
|
Input value; |
|
ASSERT_TRUE(parser.ReadTagAndValue(&tag, &value)); |
|
bool present; |
|
ASSERT_TRUE(parser.ReadOptionalTag(kInteger, &value, &present)); |
|
ASSERT_FALSE(present); |
|
ASSERT_FALSE(parser.HasMore()); |
|
} |
|
|
|
TEST(ParserTest, SkipOptionalTagDoesntConsumePresentNonMatchingTLVs) { |
|
const uint8_t der[] = {0x02 /* INTEGER */, 0x01, 0x01}; |
|
Parser parser((Input(der))); |
|
|
|
bool present; |
|
ASSERT_TRUE(parser.SkipOptionalTag(kOctetString, &present)); |
|
ASSERT_FALSE(present); |
|
ASSERT_TRUE(parser.SkipOptionalTag(kInteger, &present)); |
|
ASSERT_TRUE(present); |
|
ASSERT_FALSE(parser.HasMore()); |
|
} |
|
|
|
TEST(ParserTest, TagNumbersAboveThirtySupported) { |
|
// Context-specific class, tag number 31, length 0. |
|
const uint8_t der[] = {0x9f, 0x1f, 0x00}; |
|
Parser parser((Input(der))); |
|
|
|
Tag tag; |
|
Input value; |
|
ASSERT_TRUE(parser.ReadTagAndValue(&tag, &value)); |
|
EXPECT_EQ(kTagContextSpecific | 31u, tag); |
|
ASSERT_FALSE(parser.HasMore()); |
|
} |
|
|
|
TEST(ParserTest, ParseTags) { |
|
{ |
|
// Universal primitive tag, tag number 4. |
|
const uint8_t der[] = {0x04, 0x00}; |
|
Parser parser((Input(der))); |
|
|
|
Tag tag; |
|
Input value; |
|
ASSERT_TRUE(parser.ReadTagAndValue(&tag, &value)); |
|
EXPECT_EQ(kOctetString, tag); |
|
} |
|
|
|
{ |
|
// Universal constructed tag, tag number 16. |
|
const uint8_t der[] = {0x30, 0x00}; |
|
Parser parser((Input(der))); |
|
|
|
Tag tag; |
|
Input value; |
|
ASSERT_TRUE(parser.ReadTagAndValue(&tag, &value)); |
|
EXPECT_EQ(kSequence, tag); |
|
} |
|
|
|
{ |
|
// Application primitive tag, tag number 1. |
|
const uint8_t der[] = {0x41, 0x00}; |
|
Parser parser((Input(der))); |
|
|
|
Tag tag; |
|
Input value; |
|
ASSERT_TRUE(parser.ReadTagAndValue(&tag, &value)); |
|
EXPECT_EQ(kTagApplication | 1, tag); |
|
} |
|
|
|
{ |
|
// Context-specific constructed tag, tag number 30. |
|
const uint8_t der[] = {0xbe, 0x00}; |
|
Parser parser((Input(der))); |
|
|
|
Tag tag; |
|
Input value; |
|
ASSERT_TRUE(parser.ReadTagAndValue(&tag, &value)); |
|
EXPECT_EQ(kTagContextSpecific | kTagConstructed | 30, tag); |
|
} |
|
|
|
{ |
|
// Private primitive tag, tag number 15. |
|
const uint8_t der[] = {0xcf, 0x00}; |
|
Parser parser((Input(der))); |
|
|
|
Tag tag; |
|
Input value; |
|
ASSERT_TRUE(parser.ReadTagAndValue(&tag, &value)); |
|
EXPECT_EQ(kTagPrivate | 15, tag); |
|
} |
|
} |
|
|
|
TEST(ParserTest, IncompleteEncodingTagOnly) { |
|
const uint8_t der[] = {0x01}; |
|
Parser parser((Input(der))); |
|
|
|
Tag tag; |
|
Input value; |
|
ASSERT_FALSE(parser.ReadTagAndValue(&tag, &value)); |
|
ASSERT_TRUE(parser.HasMore()); |
|
} |
|
|
|
TEST(ParserTest, IncompleteEncodingLengthTruncated) { |
|
// Tag: octet string; length: long form, should have 2 total octets, but |
|
// the last one is missing. (There's also no value.) |
|
const uint8_t der[] = {0x04, 0x81}; |
|
Parser parser((Input(der))); |
|
|
|
Tag tag; |
|
Input value; |
|
ASSERT_FALSE(parser.ReadTagAndValue(&tag, &value)); |
|
ASSERT_TRUE(parser.HasMore()); |
|
} |
|
|
|
TEST(ParserTest, IncompleteEncodingValueShorterThanLength) { |
|
// Tag: octet string; length: 2; value: first octet 'T', second octet missing. |
|
const uint8_t der[] = {0x04, 0x02, 0x84}; |
|
Parser parser((Input(der))); |
|
|
|
Tag tag; |
|
Input value; |
|
ASSERT_FALSE(parser.ReadTagAndValue(&tag, &value)); |
|
ASSERT_TRUE(parser.HasMore()); |
|
} |
|
|
|
TEST(ParserTest, LengthMustBeEncodedWithMinimumNumberOfOctets) { |
|
const uint8_t der[] = {0x01, 0x81, 0x01, 0x00}; |
|
Parser parser((Input(der))); |
|
|
|
Tag tag; |
|
Input value; |
|
ASSERT_FALSE(parser.ReadTagAndValue(&tag, &value)); |
|
ASSERT_TRUE(parser.HasMore()); |
|
} |
|
|
|
TEST(ParserTest, LengthMustNotHaveLeadingZeroes) { |
|
// Tag: octet string; length: 3 bytes of length encoding a value of 128 |
|
// (it should be encoded in only 2 bytes). Value: 128 bytes of 0. |
|
const uint8_t der[] = { |
|
0x04, 0x83, 0x80, 0x81, 0x80, // group the 0s separately |
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; |
|
Parser parser((Input(der))); |
|
|
|
Tag tag; |
|
Input value; |
|
ASSERT_FALSE(parser.ReadTagAndValue(&tag, &value)); |
|
ASSERT_TRUE(parser.HasMore()); |
|
} |
|
|
|
TEST(ParserTest, ReadConstructedFailsForNonConstructedTags) { |
|
// Tag number is for SEQUENCE, but the constructed bit isn't set. |
|
const uint8_t der[] = {0x10, 0x00}; |
|
Parser parser((Input(der))); |
|
|
|
Tag expected_tag = 0x10; |
|
Parser sequence_parser; |
|
ASSERT_FALSE(parser.ReadConstructed(expected_tag, &sequence_parser)); |
|
|
|
// Check that we didn't fail above because of a tag mismatch or an improperly |
|
// encoded TLV. |
|
Input value; |
|
ASSERT_TRUE(parser.ReadTag(expected_tag, &value)); |
|
ASSERT_FALSE(parser.HasMore()); |
|
} |
|
|
|
TEST(ParserTest, CannotAdvanceAfterReadOptionalTag) { |
|
const uint8_t der[] = {0x02, 0x01, 0x01}; |
|
Parser parser((Input(der))); |
|
|
|
Input value; |
|
bool present; |
|
ASSERT_TRUE(parser.ReadOptionalTag(0x04, &value, &present)); |
|
ASSERT_FALSE(present); |
|
ASSERT_FALSE(parser.Advance()); |
|
} |
|
|
|
// Reads a valid BIT STRING with 1 unused bit. |
|
TEST(ParserTest, ReadBitString) { |
|
const uint8_t der[] = {0x03, 0x03, 0x01, 0xAA, 0xBE}; |
|
Parser parser((Input(der))); |
|
|
|
std::optional<BitString> bit_string = parser.ReadBitString(); |
|
ASSERT_TRUE(bit_string.has_value()); |
|
EXPECT_FALSE(parser.HasMore()); |
|
|
|
EXPECT_EQ(1u, bit_string->unused_bits()); |
|
ASSERT_EQ(2u, bit_string->bytes().Length()); |
|
EXPECT_EQ(0xAA, bit_string->bytes().UnsafeData()[0]); |
|
EXPECT_EQ(0xBE, bit_string->bytes().UnsafeData()[1]); |
|
} |
|
|
|
// Tries reading a BIT STRING. This should fail because the tag is not for a |
|
// BIT STRING. |
|
TEST(ParserTest, ReadBitStringBadTag) { |
|
const uint8_t der[] = {0x05, 0x03, 0x01, 0xAA, 0xBE}; |
|
Parser parser((Input(der))); |
|
|
|
std::optional<BitString> bit_string = parser.ReadBitString(); |
|
EXPECT_FALSE(bit_string.has_value()); |
|
} |
|
|
|
} // namespace bssl::der::test
|
|
|