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