|  | // 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 <algorithm> | 
|  |  | 
|  | #include <gtest/gtest.h> | 
|  | #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<der::Input> &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<der::Input> 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<der::Input> 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<der::Input> 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<der::Input> 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<der::Input> 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<der::Input> 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<der::Input> ekus; | 
|  | EXPECT_FALSE(ParseEKUExtension(der::Input(empty_sequence), &ekus)); | 
|  | } | 
|  |  | 
|  | // The extension value must not be empty. | 
|  | TEST(ExtendedKeyUsageTest, EmptyExtension) { | 
|  | std::vector<der::Input> ekus; | 
|  | EXPECT_FALSE(ParseEKUExtension(der::Input(), &ekus)); | 
|  | } | 
|  |  | 
|  | }  // namespace | 
|  |  | 
|  | }  // namespace bssl |