123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365 |
- // Copyright 2015 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "net/der/parser.h"
- #include "net/der/input.h"
- #include "net/der/parse_values.h"
- #include "testing/gtest/include/gtest/gtest.h"
- namespace net::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)));
- absl::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)));
- absl::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)));
- absl::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)));
- absl::optional<BitString> bit_string = parser.ReadBitString();
- EXPECT_FALSE(bit_string.has_value());
- }
- } // namespace net::der::test
|