// 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 #include #include "extended_key_usage.h" #include "input.h" namespace bssl { namespace { // Helper method to check if an EKU is present in a std::vector of EKUs. bool HasEKU(const std::vector &list, der::Input eku) { for (const auto &oid : list) { if (oid == eku) { return true; } } return false; } // Check that we can read multiple EKUs from an extension. TEST(ExtendedKeyUsageTest, ParseEKUExtension) { // clang-format off const uint8_t raw_extension_value[] = { 0x30, 0x14, // SEQUENCE (20 bytes) 0x06, 0x08, // OBJECT IDENTIFIER (8 bytes) 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, // 1.3.6.1.5.5.7.3.1 0x06, 0x08, // OBJECT IDENTIFIER (8 bytes) 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02 // 1.3.6.1.5.5.7.3.2 // end of SEQUENCE }; // clang-format on der::Input extension_value(raw_extension_value); std::vector ekus; EXPECT_TRUE(ParseEKUExtension(extension_value, &ekus)); EXPECT_EQ(2u, ekus.size()); EXPECT_TRUE(HasEKU(ekus, der::Input(kServerAuth))); EXPECT_TRUE(HasEKU(ekus, der::Input(kClientAuth))); } // Check that an extension with the same OID present multiple times doesn't // cause an error. TEST(ExtendedKeyUsageTest, RepeatedOid) { // clang-format off const uint8_t extension_bytes[] = { 0x30, 0x14, // SEQUENCE (20 bytes) 0x06, 0x08, // OBJECT IDENTIFIER (8 bytes) 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, // 1.3.6.1.5.5.7.3.1 0x06, 0x08, // OBJECT IDENTIFIER (8 bytes) 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01 // 1.3.6.1.5.5.7.3.1 }; // clang-format on der::Input extension(extension_bytes); std::vector ekus; EXPECT_TRUE(ParseEKUExtension(extension, &ekus)); EXPECT_EQ(2u, ekus.size()); for (const auto &eku : ekus) { EXPECT_EQ(der::Input(kServerAuth), eku); } } // Check that parsing an EKU extension which contains a private OID doesn't // cause an error. TEST(ExtendedKeyUsageTest, ParseEKUExtensionGracefullyHandlesPrivateOids) { // clang-format off const uint8_t extension_bytes[] = { 0x30, 0x13, // SEQUENCE (19 bytes) 0x06, 0x08, // OBJECT IDENTIFIER (8 bytes) 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, // 1.3.6.1.5.5.7.3.1 0x06, 0x07, // OBJECT IDENTIFIER (7 bytes) 0x2B, 0x06, 0x01, 0x04, 0x01, 0xD6, 0x79 // 1.3.6.1.4.1.11129 }; // clang-format on der::Input extension(extension_bytes); std::vector ekus; EXPECT_TRUE(ParseEKUExtension(extension, &ekus)); EXPECT_EQ(2u, ekus.size()); EXPECT_TRUE(HasEKU(ekus, der::Input(kServerAuth))); const uint8_t google_oid[] = {0x2B, 0x06, 0x01, 0x04, 0x01, 0xD6, 0x79}; der::Input google(google_oid); EXPECT_TRUE(HasEKU(ekus, google)); } // Test a variety of bad inputs. // If the extension value has data following the sequence of oids, parsing it // should fail. TEST(ExtendedKeyUsageTest, ExtraData) { // clang-format off const uint8_t extra_data[] = { 0x30, 0x14, // SEQUENCE (20 bytes) 0x06, 0x08, // OBJECT IDENTIFIER (8 bytes) 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, // 1.3.6.1.5.5.7.3.1 0x06, 0x08, // OBJECT IDENTIFIER (8 bytes) 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, // 1.3.6.1.5.5.7.3.2 // end of SEQUENCE 0x02, 0x01, // INTEGER (1 byte) 0x01 // 1 }; // clang-format on std::vector ekus; EXPECT_FALSE(ParseEKUExtension(der::Input(extra_data), &ekus)); } // Check that ParseEKUExtension only accepts a sequence containing only oids. // This test case has an integer in the sequence (which should fail). A key // difference between this test case and ExtendedKeyUsageTest.ExtraData is where // the sequence ends - in this test case the integer is still part of the // sequence, while in ExtendedKeyUsageTest.ExtraData the integer is after the // sequence. TEST(ExtendedKeyUsageTest, NotAnOid) { // clang-format off const uint8_t not_an_oid[] = { 0x30, 0x0d, // SEQUENCE (13 bytes) 0x06, 0x08, // OBJECT IDENTIFIER (8 bytes) 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, // 1.3.6.1.5.5.7.3.1 0x02, 0x01, // INTEGER (1 byte) 0x01 // 1 // end of SEQUENCE }; // clang-format on std::vector ekus; EXPECT_FALSE(ParseEKUExtension(der::Input(not_an_oid), &ekus)); } // Checks that the list of oids passed to ParseEKUExtension are in a sequence, // instead of one or more oid tag-length-values concatenated together. TEST(ExtendedKeyUsageTest, NotASequence) { // clang-format off const uint8_t not_a_sequence[] = { 0x06, 0x08, // OBJECT IDENTIFIER (8 bytes) 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01 // 1.3.6.1.5.5.7.3.1 }; // clang-format on std::vector ekus; EXPECT_FALSE(ParseEKUExtension(der::Input(not_a_sequence), &ekus)); } // A sequence passed into ParseEKUExtension must have at least one oid in it. TEST(ExtendedKeyUsageTest, EmptySequence) { const uint8_t empty_sequence[] = {0x30, 0x00}; // SEQUENCE (0 bytes) std::vector ekus; EXPECT_FALSE(ParseEKUExtension(der::Input(empty_sequence), &ekus)); } // The extension value must not be empty. TEST(ExtendedKeyUsageTest, EmptyExtension) { std::vector ekus; EXPECT_FALSE(ParseEKUExtension(der::Input(), &ekus)); } } // namespace } // namespace bssl