| // 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 |