1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This code is made available to you under your choice of the following sets
4  * of licensing terms:
5  */
6 /* This Source Code Form is subject to the terms of the Mozilla Public
7  * License, v. 2.0. If a copy of the MPL was not distributed with this
8  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9  */
10 /* Copyright 2013 Mozilla Contributors
11  *
12  * Licensed under the Apache License, Version 2.0 (the "License");
13  * you may not use this file except in compliance with the License.
14  * You may obtain a copy of the License at
15  *
16  *     http://www.apache.org/licenses/LICENSE-2.0
17  *
18  * Unless required by applicable law or agreed to in writing, software
19  * distributed under the License is distributed on an "AS IS" BASIS,
20  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21  * See the License for the specific language governing permissions and
22  * limitations under the License.
23  */
24 
25 #include "pkixgtest.h"
26 
27 using namespace mozilla::pkix;
28 using namespace mozilla::pkix::test;
29 
30 namespace mozilla { namespace pkix {
31 
32 extern Result CheckKeyUsage(EndEntityOrCA endEntityOrCA,
33                             const Input* encodedKeyUsage,
34                             KeyUsage requiredKeyUsageIfPresent);
35 
36 } } // namespace mozilla::pkix
37 
38 class pkixcheck_CheckKeyUsage : public ::testing::Test { };
39 
40 #define ASSERT_BAD(x) ASSERT_EQ(Result::ERROR_INADEQUATE_KEY_USAGE, x)
41 
42 // Make it easy to define test data for the common, simplest cases.
43 #define NAMED_SIMPLE_KU(name, unusedBits, bits) \
44   const uint8_t name##_bytes[4] = { \
45     0x03/*BIT STRING*/, 0x02/*LENGTH=2*/, unusedBits, bits \
46   }; \
47   const Input name(name##_bytes);
48 
49 static const Input empty_null;
50 
51 // Note that keyCertSign is really the only interesting case for CA
52 // certificates since we don't support cRLSign.
53 
TEST_F(pkixcheck_CheckKeyUsage,EE_none)54 TEST_F(pkixcheck_CheckKeyUsage, EE_none)
55 {
56   // The input Input is nullptr. This means the cert had no keyUsage
57   // extension. This is always valid because no key usage in an end-entity
58   // means that there are no key usage restrictions.
59 
60   ASSERT_EQ(Success, CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, nullptr,
61                                    KeyUsage::noParticularKeyUsageRequired));
62   ASSERT_EQ(Success, CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, nullptr,
63                                    KeyUsage::digitalSignature));
64   ASSERT_EQ(Success, CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, nullptr,
65                                    KeyUsage::nonRepudiation));
66   ASSERT_EQ(Success, CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, nullptr,
67                                    KeyUsage::keyEncipherment));
68   ASSERT_EQ(Success, CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, nullptr,
69                                    KeyUsage::dataEncipherment));
70   ASSERT_EQ(Success, CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, nullptr,
71                                    KeyUsage::keyAgreement));
72 }
73 
TEST_F(pkixcheck_CheckKeyUsage,EE_empty)74 TEST_F(pkixcheck_CheckKeyUsage, EE_empty)
75 {
76   // The input Input is empty. The cert had an empty keyUsage extension,
77   // which is syntactically invalid.
78   ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, &empty_null,
79                            KeyUsage::digitalSignature));
80   static const uint8_t dummy = 0x00;
81   Input empty_nonnull;
82   ASSERT_EQ(Success, empty_nonnull.Init(&dummy, 0));
83   ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, &empty_nonnull,
84                            KeyUsage::digitalSignature));
85 }
86 
TEST_F(pkixcheck_CheckKeyUsage,CA_none)87 TEST_F(pkixcheck_CheckKeyUsage, CA_none)
88 {
89   // A CA certificate does not have a KU extension.
90   ASSERT_EQ(Success, CheckKeyUsage(EndEntityOrCA::MustBeCA, nullptr,
91                                    KeyUsage::keyCertSign));
92 }
93 
TEST_F(pkixcheck_CheckKeyUsage,CA_empty)94 TEST_F(pkixcheck_CheckKeyUsage, CA_empty)
95 {
96   // A CA certificate has an empty KU extension.
97   ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeCA, &empty_null,
98                            KeyUsage::keyCertSign));
99   static const uint8_t dummy = 0x00;
100   Input empty_nonnull;
101   ASSERT_EQ(Success, empty_nonnull.Init(&dummy, 0));
102   ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeCA, &empty_nonnull,
103                            KeyUsage::keyCertSign));
104 }
105 
TEST_F(pkixcheck_CheckKeyUsage,maxUnusedBits)106 TEST_F(pkixcheck_CheckKeyUsage, maxUnusedBits)
107 {
108   NAMED_SIMPLE_KU(encoded, 7, 0x80);
109   ASSERT_EQ(Success, CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, &encoded,
110                                    KeyUsage::digitalSignature));
111 }
112 
TEST_F(pkixcheck_CheckKeyUsage,tooManyUnusedBits)113 TEST_F(pkixcheck_CheckKeyUsage, tooManyUnusedBits)
114 {
115   static uint8_t oneValueByteData[] = {
116     0x03/*BIT STRING*/, 0x02/*LENGTH=2*/, 8/*unused bits*/, 0x80
117   };
118   static const Input oneValueByte(oneValueByteData);
119   ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, &oneValueByte,
120                            KeyUsage::digitalSignature));
121 
122   static uint8_t twoValueBytesData[] = {
123     0x03/*BIT STRING*/, 0x03/*LENGTH=3*/, 8/*unused bits*/, 0x01, 0x00
124   };
125   static const Input twoValueBytes(twoValueBytesData);
126   ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, &twoValueBytes,
127                            KeyUsage::digitalSignature));
128 }
129 
TEST_F(pkixcheck_CheckKeyUsage,NoValueBytes_NoPaddingBits)130 TEST_F(pkixcheck_CheckKeyUsage, NoValueBytes_NoPaddingBits)
131 {
132   static const uint8_t DER_BYTES[] = {
133     0x03/*BIT STRING*/, 0x01/*LENGTH=1*/, 0/*unused bits*/
134   };
135   static const Input DER(DER_BYTES);
136   ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, &DER,
137                            KeyUsage::digitalSignature));
138   ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeCA, &DER,
139                            KeyUsage::keyCertSign));
140 }
141 
TEST_F(pkixcheck_CheckKeyUsage,NoValueBytes_7PaddingBits)142 TEST_F(pkixcheck_CheckKeyUsage, NoValueBytes_7PaddingBits)
143 {
144   static const uint8_t DER_BYTES[] = {
145     0x03/*BIT STRING*/, 0x01/*LENGTH=1*/, 7/*unused bits*/
146   };
147   static const Input DER(DER_BYTES);
148   ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, &DER,
149                            KeyUsage::digitalSignature));
150   ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeCA, &DER,
151                            KeyUsage::keyCertSign));
152 }
153 
ASSERT_SimpleCase(uint8_t unusedBits,uint8_t bits,KeyUsage usage)154 void ASSERT_SimpleCase(uint8_t unusedBits, uint8_t bits, KeyUsage usage)
155 {
156   // Test that only the right bit is accepted for the usage for both EE and CA
157   // certs.
158   NAMED_SIMPLE_KU(good, unusedBits, bits);
159   ASSERT_EQ(Success,
160             CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, &good, usage));
161   ASSERT_EQ(Success, CheckKeyUsage(EndEntityOrCA::MustBeCA, &good, usage));
162 
163   // We use (~bits >> unusedBits) << unusedBits) instead of using the same
164   // calculation that is in CheckKeyUsage to validate that the calculation in
165   // CheckKeyUsage is correct.
166 
167   // Test that none of the other non-padding bits are mistaken for the given
168   // key usage in the single-byte value case.
169   uint8_t paddingBits = (static_cast<uint8_t>(~bits) >> unusedBits) << unusedBits;
170   NAMED_SIMPLE_KU(notGood, unusedBits, paddingBits);
171   ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, &notGood, usage));
172   ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeCA, &notGood, usage));
173 
174   // Test that none of the other non-padding bits are mistaken for the given
175   // key usage in the two-byte value case.
176   const uint8_t twoByteNotGoodData[] = {
177     0x03/*BIT STRING*/, 0x03/*LENGTH=3*/, unusedBits,
178     static_cast<uint8_t>(~bits),
179     static_cast<uint8_t>((0xFFu >> unusedBits) << unusedBits)
180   };
181   Input twoByteNotGood(twoByteNotGoodData);
182   ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, &twoByteNotGood,
183                            usage));
184   ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeCA, &twoByteNotGood, usage));
185 }
186 
TEST_F(pkixcheck_CheckKeyUsage,simpleCases)187 TEST_F(pkixcheck_CheckKeyUsage, simpleCases)
188 {
189   ASSERT_SimpleCase(7, 0x80, KeyUsage::digitalSignature);
190   ASSERT_SimpleCase(6, 0x40, KeyUsage::nonRepudiation);
191   ASSERT_SimpleCase(5, 0x20, KeyUsage::keyEncipherment);
192   ASSERT_SimpleCase(4, 0x10, KeyUsage::dataEncipherment);
193   ASSERT_SimpleCase(3, 0x08, KeyUsage::keyAgreement);
194 }
195 
196 // Only CAs are allowed to assert keyCertSign.
197 // End-entity certs may assert it along with other key usages if keyCertSign
198 // isn't the required key usage. This is for compatibility.
TEST_F(pkixcheck_CheckKeyUsage,keyCertSign)199 TEST_F(pkixcheck_CheckKeyUsage, keyCertSign)
200 {
201   NAMED_SIMPLE_KU(good, 2, 0x04);
202   ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, &good,
203                            KeyUsage::keyCertSign));
204   ASSERT_EQ(Success, CheckKeyUsage(EndEntityOrCA::MustBeCA, &good,
205                                    KeyUsage::keyCertSign));
206 
207   // Test that none of the other non-padding bits are mistaken for the given
208   // key usage in the one-byte value case.
209   NAMED_SIMPLE_KU(notGood, 2, 0xFB);
210   ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, &notGood,
211                            KeyUsage::keyCertSign));
212   ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeCA, &notGood,
213                            KeyUsage::keyCertSign));
214 
215   // Test that none of the other non-padding bits are mistaken for the given
216   // key usage in the two-byte value case.
217   static uint8_t twoByteNotGoodData[] = {
218     0x03/*BIT STRING*/, 0x03/*LENGTH=3*/, 2/*unused bits*/, 0xFBu, 0xFCu
219   };
220   static const Input twoByteNotGood(twoByteNotGoodData);
221   ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, &twoByteNotGood,
222                            KeyUsage::keyCertSign));
223   ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeCA, &twoByteNotGood,
224                            KeyUsage::keyCertSign));
225 
226   // If an end-entity certificate does assert keyCertSign, this is allowed
227   // as long as that isn't the required key usage.
228   NAMED_SIMPLE_KU(digitalSignatureAndKeyCertSign, 2, 0x84);
229   ASSERT_EQ(Success, CheckKeyUsage(EndEntityOrCA::MustBeEndEntity,
230                                    &digitalSignatureAndKeyCertSign,
231                                    KeyUsage::digitalSignature));
232   ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity,
233                            &digitalSignatureAndKeyCertSign,
234                            KeyUsage::keyCertSign));
235 }
236 
TEST_F(pkixcheck_CheckKeyUsage,unusedBitNotZero)237 TEST_F(pkixcheck_CheckKeyUsage, unusedBitNotZero)
238 {
239   // single byte control case
240   static uint8_t controlOneValueByteData[] = {
241     0x03/*BIT STRING*/, 0x02/*LENGTH=2*/, 7/*unused bits*/, 0x80
242   };
243   static const Input controlOneValueByte(controlOneValueByteData);
244   ASSERT_EQ(Success, CheckKeyUsage(EndEntityOrCA::MustBeEndEntity,
245                                    &controlOneValueByte,
246                                    KeyUsage::digitalSignature));
247   ASSERT_EQ(Success, CheckKeyUsage(EndEntityOrCA::MustBeCA,
248                                    &controlOneValueByte,
249                                    KeyUsage::digitalSignature));
250 
251   // single-byte test case
252   static uint8_t oneValueByteData[] = {
253     0x03/*BIT STRING*/, 0x02/*LENGTH=2*/, 7/*unused bits*/, 0x80 | 0x01
254   };
255   static const Input oneValueByte(oneValueByteData);
256   ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, &oneValueByte,
257                            KeyUsage::digitalSignature));
258   ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeCA, &oneValueByte,
259                            KeyUsage::digitalSignature));
260 
261   // two-byte control case
262   static uint8_t controlTwoValueBytesData[] = {
263     0x03/*BIT STRING*/, 0x03/*LENGTH=3*/, 7/*unused bits*/,
264     0x80 | 0x01, 0x80
265   };
266   static const Input controlTwoValueBytes(controlTwoValueBytesData);
267   ASSERT_EQ(Success, CheckKeyUsage(EndEntityOrCA::MustBeEndEntity,
268                                    &controlTwoValueBytes,
269                                    KeyUsage::digitalSignature));
270   ASSERT_EQ(Success, CheckKeyUsage(EndEntityOrCA::MustBeCA,
271                                    &controlTwoValueBytes,
272                                    KeyUsage::digitalSignature));
273 
274   // two-byte test case
275   static uint8_t twoValueBytesData[] = {
276     0x03/*BIT STRING*/, 0x03/*LENGTH=3*/, 7/*unused bits*/,
277     0x80 | 0x01, 0x80 | 0x01
278   };
279   static const Input twoValueBytes(twoValueBytesData);
280   ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, &twoValueBytes,
281                            KeyUsage::digitalSignature));
282   ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeCA, &twoValueBytes,
283                            KeyUsage::digitalSignature));
284 }
285