security/pkix/test/gtest/pkixcheck_CheckKeyUsage_tests.cpp

branch
TOR_BUG_9701
changeset 8
97036ab72558
equal deleted inserted replaced
-1:000000000000 0:7c9aeed26716
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, &notGood, usage));
188 ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeCA, &notGood, 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, &notGood,
227 KeyUsage::keyCertSign));
228 ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeCA, &notGood,
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 }

mercurial