|
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 SECItem* encodedKeyUsage, |
|
34 KeyUsage requiredKeyUsageIfPresent); |
|
35 |
|
36 } } // namespace mozilla::pkix |
|
37 |
|
38 #define ASSERT_BAD(x) \ |
|
39 ASSERT_RecoverableError(SEC_ERROR_INADEQUATE_KEY_USAGE, x) |
|
40 |
|
41 // Make it easy to define test data for the common, simplest cases. |
|
42 #define NAMED_SIMPLE_KU(name, unusedBits, bits) \ |
|
43 const uint8_t name##_bytes[4] = { \ |
|
44 0x03/*BIT STRING*/, 0x02/*LENGTH=2*/, unusedBits, bits \ |
|
45 }; \ |
|
46 const SECItem name = { \ |
|
47 siBuffer, \ |
|
48 const_cast<uint8_t*>(name##_bytes), \ |
|
49 4 \ |
|
50 } |
|
51 |
|
52 static uint8_t dummy; |
|
53 static const SECItem empty_null = { siBuffer, nullptr, 0 }; |
|
54 static const SECItem empty_nonnull = { siBuffer, &dummy, 0 }; |
|
55 |
|
56 // Note that keyCertSign is really the only interesting case for CA |
|
57 // certificates since we don't support cRLSign. |
|
58 |
|
59 TEST(pkixcheck_CheckKeyUsage, EE_none) |
|
60 { |
|
61 // The input SECItem is nullptr. This means the cert had no keyUsage |
|
62 // extension. This is always valid because no key usage in an end-entity |
|
63 // means that there are no key usage restrictions. |
|
64 |
|
65 ASSERT_Success(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, nullptr, |
|
66 KeyUsage::noParticularKeyUsageRequired)); |
|
67 ASSERT_Success(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, nullptr, |
|
68 KeyUsage::digitalSignature)); |
|
69 ASSERT_Success(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, nullptr, |
|
70 KeyUsage::nonRepudiation)); |
|
71 ASSERT_Success(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, nullptr, |
|
72 KeyUsage::keyEncipherment)); |
|
73 ASSERT_Success(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, nullptr, |
|
74 KeyUsage::dataEncipherment)); |
|
75 ASSERT_Success(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, nullptr, |
|
76 KeyUsage::keyAgreement)); |
|
77 } |
|
78 |
|
79 TEST(pkixcheck_CheckKeyUsage, EE_empty) |
|
80 { |
|
81 // The input SECItem is empty. The cert had an empty keyUsage extension, |
|
82 // which is syntactically invalid. |
|
83 ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, &empty_null, |
|
84 KeyUsage::digitalSignature)); |
|
85 ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, &empty_nonnull, |
|
86 KeyUsage::digitalSignature)); |
|
87 } |
|
88 |
|
89 TEST(pkixcheck_CheckKeyUsage, CA_none) |
|
90 { |
|
91 // A CA certificate does not have a KU extension. |
|
92 ASSERT_Success(CheckKeyUsage(EndEntityOrCA::MustBeCA, nullptr, |
|
93 KeyUsage::keyCertSign)); |
|
94 } |
|
95 |
|
96 TEST(pkixcheck_CheckKeyUsage, CA_empty) |
|
97 { |
|
98 // A CA certificate has an empty KU extension. |
|
99 ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeCA, &empty_null, |
|
100 KeyUsage::keyCertSign)); |
|
101 ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeCA, &empty_nonnull, |
|
102 KeyUsage::keyCertSign)); |
|
103 } |
|
104 |
|
105 TEST(pkixchekc_CheckKeyusage, maxUnusedBits) |
|
106 { |
|
107 NAMED_SIMPLE_KU(encoded, 7, 0x80); |
|
108 ASSERT_Success(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, &encoded, |
|
109 KeyUsage::digitalSignature)); |
|
110 } |
|
111 |
|
112 TEST(pkixchekc_CheckKeyusage, tooManyUnusedBits) |
|
113 { |
|
114 static uint8_t oneValueByteData[] = { |
|
115 0x03/*BIT STRING*/, 0x02/*LENGTH=2*/, 8/*unused bits*/, 0x80 |
|
116 }; |
|
117 const SECItem oneValueByte = { |
|
118 siBuffer, |
|
119 oneValueByteData, |
|
120 sizeof(oneValueByteData) |
|
121 }; |
|
122 ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, &oneValueByte, |
|
123 KeyUsage::digitalSignature)); |
|
124 |
|
125 static uint8_t twoValueBytesData[] = { |
|
126 0x03/*BIT STRING*/, 0x03/*LENGTH=3*/, 8/*unused bits*/, 0x01, 0x00 |
|
127 }; |
|
128 const SECItem twoValueBytes = { |
|
129 siBuffer, |
|
130 twoValueBytesData, |
|
131 sizeof(twoValueBytesData) |
|
132 }; |
|
133 ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, &twoValueBytes, |
|
134 KeyUsage::digitalSignature)); |
|
135 } |
|
136 |
|
137 TEST(pkixcheck_CheckKeyUsage, NoValueBytes_NoPaddingBits) |
|
138 { |
|
139 static const uint8_t DER_BYTES[] = { |
|
140 0x03/*BIT STRING*/, 0x01/*LENGTH=1*/, 0/*unused bits*/ |
|
141 }; |
|
142 static const SECItem DER = { |
|
143 siBuffer, |
|
144 const_cast<uint8_t*>(DER_BYTES), |
|
145 sizeof(DER_BYTES) |
|
146 }; |
|
147 |
|
148 ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, &DER, |
|
149 KeyUsage::digitalSignature)); |
|
150 ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeCA, &DER, |
|
151 KeyUsage::keyCertSign)); |
|
152 } |
|
153 |
|
154 TEST(pkixcheck_CheckKeyUsage, NoValueBytes_7PaddingBits) |
|
155 { |
|
156 static const uint8_t DER_BYTES[] = { |
|
157 0x03/*BIT STRING*/, 0x01/*LENGTH=1*/, 7/*unused bits*/ |
|
158 }; |
|
159 static const SECItem DER = { |
|
160 siBuffer, |
|
161 const_cast<uint8_t*>(DER_BYTES), |
|
162 sizeof(DER_BYTES) |
|
163 }; |
|
164 |
|
165 ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, &DER, |
|
166 KeyUsage::digitalSignature)); |
|
167 ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeCA, &DER, |
|
168 KeyUsage::keyCertSign)); |
|
169 } |
|
170 |
|
171 void ASSERT_SimpleCase(uint8_t unusedBits, uint8_t bits, KeyUsage usage) |
|
172 { |
|
173 // Test that only the right bit is accepted for the usage for both EE and CA |
|
174 // certs. |
|
175 NAMED_SIMPLE_KU(good, unusedBits, bits); |
|
176 ASSERT_Success(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, &good, usage)); |
|
177 ASSERT_Success(CheckKeyUsage(EndEntityOrCA::MustBeCA, &good, usage)); |
|
178 |
|
179 // We use (~bits >> unusedBits) << unusedBits) instead of using the same |
|
180 // calculation that is in CheckKeyUsage to validate that the calculation in |
|
181 // CheckKeyUsage is correct. |
|
182 |
|
183 // Test that none of the other non-padding bits are mistaken for the given |
|
184 // key usage in the single-byte value case. |
|
185 NAMED_SIMPLE_KU(notGood, unusedBits, |
|
186 static_cast<uint8_t>((~bits >> unusedBits) << unusedBits)); |
|
187 ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, ¬Good, usage)); |
|
188 ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeCA, ¬Good, usage)); |
|
189 |
|
190 // Test that none of the other non-padding bits are mistaken for the given |
|
191 // key usage in the two-byte value case. |
|
192 uint8_t twoByteNotGoodData[] = { |
|
193 0x03/*BIT STRING*/, 0x03/*LENGTH=3*/, unusedBits, |
|
194 static_cast<uint8_t>(~bits), |
|
195 static_cast<uint8_t>((0xFFu >> unusedBits) << unusedBits) |
|
196 }; |
|
197 const SECItem twoByteNotGood = { |
|
198 siBuffer, twoByteNotGoodData, sizeof(twoByteNotGoodData) |
|
199 }; |
|
200 ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, &twoByteNotGood, |
|
201 usage)); |
|
202 ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeCA, &twoByteNotGood, usage)); |
|
203 } |
|
204 |
|
205 TEST(pkixcheck_CheckKeyUsage, simpleCases) |
|
206 { |
|
207 ASSERT_SimpleCase(7, 0x80, KeyUsage::digitalSignature); |
|
208 ASSERT_SimpleCase(6, 0x40, KeyUsage::nonRepudiation); |
|
209 ASSERT_SimpleCase(5, 0x20, KeyUsage::keyEncipherment); |
|
210 ASSERT_SimpleCase(4, 0x10, KeyUsage::dataEncipherment); |
|
211 ASSERT_SimpleCase(3, 0x08, KeyUsage::keyAgreement); |
|
212 } |
|
213 |
|
214 // Only CAs are allowed to assert keyCertSign |
|
215 TEST(pkixcheck_CheckKeyUsage, keyCertSign) |
|
216 { |
|
217 NAMED_SIMPLE_KU(good, 2, 0x04); |
|
218 ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, &good, |
|
219 KeyUsage::keyCertSign)); |
|
220 ASSERT_Success(CheckKeyUsage(EndEntityOrCA::MustBeCA, &good, |
|
221 KeyUsage::keyCertSign)); |
|
222 |
|
223 // Test that none of the other non-padding bits are mistaken for the given |
|
224 // key usage in the one-byte value case. |
|
225 NAMED_SIMPLE_KU(notGood, 2, 0xFB); |
|
226 ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, ¬Good, |
|
227 KeyUsage::keyCertSign)); |
|
228 ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeCA, ¬Good, |
|
229 KeyUsage::keyCertSign)); |
|
230 |
|
231 // Test that none of the other non-padding bits are mistaken for the given |
|
232 // key usage in the two-byte value case. |
|
233 static uint8_t twoByteNotGoodData[] = { |
|
234 0x03/*BIT STRING*/, 0x03/*LENGTH=3*/, 2/*unused bits*/, 0xFBu, 0xFCu |
|
235 }; |
|
236 static const SECItem twoByteNotGood = { |
|
237 siBuffer, twoByteNotGoodData, sizeof(twoByteNotGoodData) |
|
238 }; |
|
239 ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, &twoByteNotGood, |
|
240 KeyUsage::keyCertSign)); |
|
241 ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeCA, &twoByteNotGood, |
|
242 KeyUsage::keyCertSign)); |
|
243 } |
|
244 |
|
245 TEST(pkixcheck_CheckKeyUsage, unusedBitNotZero) |
|
246 { |
|
247 // single byte control case |
|
248 static uint8_t controlOneValueByteData[] = { |
|
249 0x03/*BIT STRING*/, 0x02/*LENGTH=2*/, 7/*unused bits*/, 0x80 |
|
250 }; |
|
251 const SECItem controlOneValueByte = { |
|
252 siBuffer, |
|
253 controlOneValueByteData, |
|
254 sizeof(controlOneValueByteData) |
|
255 }; |
|
256 ASSERT_Success(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, |
|
257 &controlOneValueByte, |
|
258 KeyUsage::digitalSignature)); |
|
259 ASSERT_Success(CheckKeyUsage(EndEntityOrCA::MustBeCA, &controlOneValueByte, |
|
260 KeyUsage::digitalSignature)); |
|
261 |
|
262 // single-byte test case |
|
263 static uint8_t oneValueByteData[] = { |
|
264 0x03/*BIT STRING*/, 0x02/*LENGTH=2*/, 7/*unused bits*/, 0x80 | 0x01 |
|
265 }; |
|
266 const SECItem oneValueByte = { |
|
267 siBuffer, |
|
268 oneValueByteData, |
|
269 sizeof(oneValueByteData) |
|
270 }; |
|
271 ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, &oneValueByte, |
|
272 KeyUsage::digitalSignature)); |
|
273 ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeCA, &oneValueByte, |
|
274 KeyUsage::digitalSignature)); |
|
275 |
|
276 // two-byte control case |
|
277 static uint8_t controlTwoValueBytesData[] = { |
|
278 0x03/*BIT STRING*/, 0x03/*LENGTH=3*/, 7/*unused bits*/, |
|
279 0x80 | 0x01, 0x80 |
|
280 }; |
|
281 const SECItem controlTwoValueBytes = { |
|
282 siBuffer, |
|
283 controlTwoValueBytesData, |
|
284 sizeof(controlTwoValueBytesData) |
|
285 }; |
|
286 ASSERT_Success(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, |
|
287 &controlTwoValueBytes, |
|
288 KeyUsage::digitalSignature)); |
|
289 ASSERT_Success(CheckKeyUsage(EndEntityOrCA::MustBeCA, &controlTwoValueBytes, |
|
290 KeyUsage::digitalSignature)); |
|
291 |
|
292 // two-byte test case |
|
293 static uint8_t twoValueBytesData[] = { |
|
294 0x03/*BIT STRING*/, 0x03/*LENGTH=3*/, 7/*unused bits*/, |
|
295 0x80 | 0x01, 0x80 | 0x01 |
|
296 }; |
|
297 const SECItem twoValueBytes = { |
|
298 siBuffer, |
|
299 twoValueBytesData, |
|
300 sizeof(twoValueBytesData) |
|
301 }; |
|
302 ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, &twoValueBytes, |
|
303 KeyUsage::digitalSignature)); |
|
304 ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeCA, &twoValueBytes, |
|
305 KeyUsage::digitalSignature)); |
|
306 } |