1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <algorithm>
6 
7 #include "base/macros.h"
8 #include "net/cert/internal/extended_key_usage.h"
9 #include "net/der/input.h"
10 #include "testing/gtest/include/gtest/gtest.h"
11 
12 namespace net {
13 
14 namespace {
15 
16 // Helper method to check if an EKU is present in a std::vector of EKUs.
HasEKU(const std::vector<der::Input> & list,const der::Input & eku)17 bool HasEKU(const std::vector<der::Input>& list, const der::Input& eku) {
18   for (const auto& oid : list) {
19     if (oid == eku)
20       return true;
21   }
22   return false;
23 }
24 
25 // Check that we can read multiple EKUs from an extension.
TEST(ExtendedKeyUsageTest,ParseEKUExtension)26 TEST(ExtendedKeyUsageTest, ParseEKUExtension) {
27   // clang-format off
28   const uint8_t raw_extension_value[] = {
29       0x30, 0x14,  // SEQUENCE (20 bytes)
30       0x06, 0x08,  // OBJECT IDENTIFIER (8 bytes)
31       0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01,  // 1.3.6.1.5.5.7.3.1
32       0x06, 0x08,  // OBJECT IDENTIFIER (8 bytes)
33       0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02  // 1.3.6.1.5.5.7.3.2
34       // end of SEQUENCE
35   };
36   // clang-format on
37   der::Input extension_value(raw_extension_value);
38 
39   std::vector<der::Input> ekus;
40   EXPECT_TRUE(ParseEKUExtension(extension_value, &ekus));
41 
42   EXPECT_EQ(2u, ekus.size());
43   EXPECT_TRUE(HasEKU(ekus, ServerAuth()));
44   EXPECT_TRUE(HasEKU(ekus, ClientAuth()));
45 }
46 
47 // Check that an extension with the same OID present multiple times doesn't
48 // cause an error.
TEST(ExtendedKeyUsageTest,RepeatedOid)49 TEST(ExtendedKeyUsageTest, RepeatedOid) {
50   // clang-format off
51   const uint8_t extension_bytes[] = {
52       0x30, 0x14,  // SEQUENCE (20 bytes)
53       0x06, 0x08,  // OBJECT IDENTIFIER (8 bytes)
54       0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01,  // 1.3.6.1.5.5.7.3.1
55       0x06, 0x08,  // OBJECT IDENTIFIER (8 bytes)
56       0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01  // 1.3.6.1.5.5.7.3.1
57   };
58   // clang-format on
59   der::Input extension(extension_bytes);
60 
61   std::vector<der::Input> ekus;
62   EXPECT_TRUE(ParseEKUExtension(extension, &ekus));
63   EXPECT_EQ(2u, ekus.size());
64   for (const auto& eku : ekus) {
65     EXPECT_EQ(ServerAuth(), eku);
66   }
67 }
68 
69 // Check that parsing an EKU extension which contains a private OID doesn't
70 // cause an error.
TEST(ExtendedKeyUsageTest,ParseEKUExtensionGracefullyHandlesPrivateOids)71 TEST(ExtendedKeyUsageTest, ParseEKUExtensionGracefullyHandlesPrivateOids) {
72   // clang-format off
73   const uint8_t extension_bytes[] = {
74     0x30, 0x13,  // SEQUENCE (19 bytes)
75     0x06, 0x08,  // OBJECT IDENTIFIER (8 bytes)
76     0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01,  // 1.3.6.1.5.5.7.3.1
77     0x06, 0x07,  // OBJECT IDENTIFIER (7 bytes)
78     0x2B, 0x06, 0x01, 0x04, 0x01, 0xD6, 0x79  // 1.3.6.1.4.1.11129
79   };
80   // clang-format on
81   der::Input extension(extension_bytes);
82 
83   std::vector<der::Input> ekus;
84   EXPECT_TRUE(ParseEKUExtension(extension, &ekus));
85   EXPECT_EQ(2u, ekus.size());
86   EXPECT_TRUE(HasEKU(ekus, ServerAuth()));
87 
88   const uint8_t google_oid[] = {0x2B, 0x06, 0x01, 0x04, 0x01, 0xD6, 0x79};
89   der::Input google(google_oid);
90   EXPECT_TRUE(HasEKU(ekus, google));
91 }
92 
93 // Test a variety of bad inputs.
94 
95 // If the extension value has data following the sequence of oids, parsing it
96 // should fail.
TEST(ExtendedKeyUsageTest,ExtraData)97 TEST(ExtendedKeyUsageTest, ExtraData) {
98   // clang-format off
99   const uint8_t extra_data[] = {
100       0x30, 0x14,  // SEQUENCE (20 bytes)
101       0x06, 0x08,  // OBJECT IDENTIFIER (8 bytes)
102       0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01,  // 1.3.6.1.5.5.7.3.1
103       0x06, 0x08,  // OBJECT IDENTIFIER (8 bytes)
104       0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02,  // 1.3.6.1.5.5.7.3.2
105       // end of SEQUENCE
106       0x02, 0x01,  // INTEGER (1 byte)
107       0x01  // 1
108   };
109   // clang-format on
110 
111   std::vector<der::Input> ekus;
112   EXPECT_FALSE(ParseEKUExtension(der::Input(extra_data), &ekus));
113 }
114 
115 // Check that ParseEKUExtension only accepts a sequence containing only oids.
116 // This test case has an integer in the sequence (which should fail). A key
117 // difference between this test case and ExtendedKeyUsageTest.ExtraData is where
118 // the sequence ends - in this test case the integer is still part of the
119 // sequence, while in ExtendedKeyUsageTest.ExtraData the integer is after the
120 // sequence.
TEST(ExtendedKeyUsageTest,NotAnOid)121 TEST(ExtendedKeyUsageTest, NotAnOid) {
122   // clang-format off
123   const uint8_t not_an_oid[] = {
124       0x30, 0x0d,  // SEQUENCE (13 bytes)
125       0x06, 0x08,  // OBJECT IDENTIFIER (8 bytes)
126       0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01,  // 1.3.6.1.5.5.7.3.1
127       0x02, 0x01,  // INTEGER (1 byte)
128       0x01  // 1
129       // end of SEQUENCE
130   };
131   // clang-format on
132 
133   std::vector<der::Input> ekus;
134   EXPECT_FALSE(ParseEKUExtension(der::Input(not_an_oid), &ekus));
135 }
136 
137 // Checks that the list of oids passed to ParseEKUExtension are in a sequence,
138 // instead of one or more oid tag-length-values concatenated together.
TEST(ExtendedKeyUsageTest,NotASequence)139 TEST(ExtendedKeyUsageTest, NotASequence) {
140   // clang-format off
141   const uint8_t not_a_sequence[] = {
142       0x06, 0x08,  // OBJECT IDENTIFIER (8 bytes)
143       0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01  // 1.3.6.1.5.5.7.3.1
144   };
145   // clang-format on
146 
147   std::vector<der::Input> ekus;
148   EXPECT_FALSE(ParseEKUExtension(der::Input(not_a_sequence), &ekus));
149 }
150 
151 // A sequence passed into ParseEKUExtension must have at least one oid in it.
TEST(ExtendedKeyUsageTest,EmptySequence)152 TEST(ExtendedKeyUsageTest, EmptySequence) {
153   const uint8_t empty_sequence[] = {0x30, 0x00};  // SEQUENCE (0 bytes)
154 
155   std::vector<der::Input> ekus;
156   EXPECT_FALSE(ParseEKUExtension(der::Input(empty_sequence), &ekus));
157 }
158 
159 // The extension value must not be empty.
TEST(ExtendedKeyUsageTest,EmptyExtension)160 TEST(ExtendedKeyUsageTest, EmptyExtension) {
161   std::vector<der::Input> ekus;
162   EXPECT_FALSE(ParseEKUExtension(der::Input(), &ekus));
163 }
164 
165 }  // namespace
166 
167 }  // namespace net
168