1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/pkix/test/gtest/pkixcheck_CheckKeyUsage_tests.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,306 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ 1.6 +/* This code is made available to you under your choice of the following sets 1.7 + * of licensing terms: 1.8 + */ 1.9 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.10 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.11 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. 1.12 + */ 1.13 +/* Copyright 2013 Mozilla Contributors 1.14 + * 1.15 + * Licensed under the Apache License, Version 2.0 (the "License"); 1.16 + * you may not use this file except in compliance with the License. 1.17 + * You may obtain a copy of the License at 1.18 + * 1.19 + * http://www.apache.org/licenses/LICENSE-2.0 1.20 + * 1.21 + * Unless required by applicable law or agreed to in writing, software 1.22 + * distributed under the License is distributed on an "AS IS" BASIS, 1.23 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1.24 + * See the License for the specific language governing permissions and 1.25 + * limitations under the License. 1.26 + */ 1.27 + 1.28 +#include "pkixgtest.h" 1.29 + 1.30 +using namespace mozilla::pkix; 1.31 +using namespace mozilla::pkix::test; 1.32 + 1.33 +namespace mozilla { namespace pkix { 1.34 + 1.35 +extern Result CheckKeyUsage(EndEntityOrCA endEntityOrCA, 1.36 + const SECItem* encodedKeyUsage, 1.37 + KeyUsage requiredKeyUsageIfPresent); 1.38 + 1.39 +} } // namespace mozilla::pkix 1.40 + 1.41 +#define ASSERT_BAD(x) \ 1.42 + ASSERT_RecoverableError(SEC_ERROR_INADEQUATE_KEY_USAGE, x) 1.43 + 1.44 +// Make it easy to define test data for the common, simplest cases. 1.45 +#define NAMED_SIMPLE_KU(name, unusedBits, bits) \ 1.46 + const uint8_t name##_bytes[4] = { \ 1.47 + 0x03/*BIT STRING*/, 0x02/*LENGTH=2*/, unusedBits, bits \ 1.48 + }; \ 1.49 + const SECItem name = { \ 1.50 + siBuffer, \ 1.51 + const_cast<uint8_t*>(name##_bytes), \ 1.52 + 4 \ 1.53 + } 1.54 + 1.55 +static uint8_t dummy; 1.56 +static const SECItem empty_null = { siBuffer, nullptr, 0 }; 1.57 +static const SECItem empty_nonnull = { siBuffer, &dummy, 0 }; 1.58 + 1.59 +// Note that keyCertSign is really the only interesting case for CA 1.60 +// certificates since we don't support cRLSign. 1.61 + 1.62 +TEST(pkixcheck_CheckKeyUsage, EE_none) 1.63 +{ 1.64 + // The input SECItem is nullptr. This means the cert had no keyUsage 1.65 + // extension. This is always valid because no key usage in an end-entity 1.66 + // means that there are no key usage restrictions. 1.67 + 1.68 + ASSERT_Success(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, nullptr, 1.69 + KeyUsage::noParticularKeyUsageRequired)); 1.70 + ASSERT_Success(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, nullptr, 1.71 + KeyUsage::digitalSignature)); 1.72 + ASSERT_Success(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, nullptr, 1.73 + KeyUsage::nonRepudiation)); 1.74 + ASSERT_Success(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, nullptr, 1.75 + KeyUsage::keyEncipherment)); 1.76 + ASSERT_Success(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, nullptr, 1.77 + KeyUsage::dataEncipherment)); 1.78 + ASSERT_Success(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, nullptr, 1.79 + KeyUsage::keyAgreement)); 1.80 +} 1.81 + 1.82 +TEST(pkixcheck_CheckKeyUsage, EE_empty) 1.83 +{ 1.84 + // The input SECItem is empty. The cert had an empty keyUsage extension, 1.85 + // which is syntactically invalid. 1.86 + ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, &empty_null, 1.87 + KeyUsage::digitalSignature)); 1.88 + ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, &empty_nonnull, 1.89 + KeyUsage::digitalSignature)); 1.90 +} 1.91 + 1.92 +TEST(pkixcheck_CheckKeyUsage, CA_none) 1.93 +{ 1.94 + // A CA certificate does not have a KU extension. 1.95 + ASSERT_Success(CheckKeyUsage(EndEntityOrCA::MustBeCA, nullptr, 1.96 + KeyUsage::keyCertSign)); 1.97 +} 1.98 + 1.99 +TEST(pkixcheck_CheckKeyUsage, CA_empty) 1.100 +{ 1.101 + // A CA certificate has an empty KU extension. 1.102 + ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeCA, &empty_null, 1.103 + KeyUsage::keyCertSign)); 1.104 + ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeCA, &empty_nonnull, 1.105 + KeyUsage::keyCertSign)); 1.106 +} 1.107 + 1.108 +TEST(pkixchekc_CheckKeyusage, maxUnusedBits) 1.109 +{ 1.110 + NAMED_SIMPLE_KU(encoded, 7, 0x80); 1.111 + ASSERT_Success(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, &encoded, 1.112 + KeyUsage::digitalSignature)); 1.113 +} 1.114 + 1.115 +TEST(pkixchekc_CheckKeyusage, tooManyUnusedBits) 1.116 +{ 1.117 + static uint8_t oneValueByteData[] = { 1.118 + 0x03/*BIT STRING*/, 0x02/*LENGTH=2*/, 8/*unused bits*/, 0x80 1.119 + }; 1.120 + const SECItem oneValueByte = { 1.121 + siBuffer, 1.122 + oneValueByteData, 1.123 + sizeof(oneValueByteData) 1.124 + }; 1.125 + ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, &oneValueByte, 1.126 + KeyUsage::digitalSignature)); 1.127 + 1.128 + static uint8_t twoValueBytesData[] = { 1.129 + 0x03/*BIT STRING*/, 0x03/*LENGTH=3*/, 8/*unused bits*/, 0x01, 0x00 1.130 + }; 1.131 + const SECItem twoValueBytes = { 1.132 + siBuffer, 1.133 + twoValueBytesData, 1.134 + sizeof(twoValueBytesData) 1.135 + }; 1.136 + ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, &twoValueBytes, 1.137 + KeyUsage::digitalSignature)); 1.138 +} 1.139 + 1.140 +TEST(pkixcheck_CheckKeyUsage, NoValueBytes_NoPaddingBits) 1.141 +{ 1.142 + static const uint8_t DER_BYTES[] = { 1.143 + 0x03/*BIT STRING*/, 0x01/*LENGTH=1*/, 0/*unused bits*/ 1.144 + }; 1.145 + static const SECItem DER = { 1.146 + siBuffer, 1.147 + const_cast<uint8_t*>(DER_BYTES), 1.148 + sizeof(DER_BYTES) 1.149 + }; 1.150 + 1.151 + ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, &DER, 1.152 + KeyUsage::digitalSignature)); 1.153 + ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeCA, &DER, 1.154 + KeyUsage::keyCertSign)); 1.155 +} 1.156 + 1.157 +TEST(pkixcheck_CheckKeyUsage, NoValueBytes_7PaddingBits) 1.158 +{ 1.159 + static const uint8_t DER_BYTES[] = { 1.160 + 0x03/*BIT STRING*/, 0x01/*LENGTH=1*/, 7/*unused bits*/ 1.161 + }; 1.162 + static const SECItem DER = { 1.163 + siBuffer, 1.164 + const_cast<uint8_t*>(DER_BYTES), 1.165 + sizeof(DER_BYTES) 1.166 + }; 1.167 + 1.168 + ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, &DER, 1.169 + KeyUsage::digitalSignature)); 1.170 + ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeCA, &DER, 1.171 + KeyUsage::keyCertSign)); 1.172 +} 1.173 + 1.174 +void ASSERT_SimpleCase(uint8_t unusedBits, uint8_t bits, KeyUsage usage) 1.175 +{ 1.176 + // Test that only the right bit is accepted for the usage for both EE and CA 1.177 + // certs. 1.178 + NAMED_SIMPLE_KU(good, unusedBits, bits); 1.179 + ASSERT_Success(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, &good, usage)); 1.180 + ASSERT_Success(CheckKeyUsage(EndEntityOrCA::MustBeCA, &good, usage)); 1.181 + 1.182 + // We use (~bits >> unusedBits) << unusedBits) instead of using the same 1.183 + // calculation that is in CheckKeyUsage to validate that the calculation in 1.184 + // CheckKeyUsage is correct. 1.185 + 1.186 + // Test that none of the other non-padding bits are mistaken for the given 1.187 + // key usage in the single-byte value case. 1.188 + NAMED_SIMPLE_KU(notGood, unusedBits, 1.189 + static_cast<uint8_t>((~bits >> unusedBits) << unusedBits)); 1.190 + ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, ¬Good, usage)); 1.191 + ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeCA, ¬Good, usage)); 1.192 + 1.193 + // Test that none of the other non-padding bits are mistaken for the given 1.194 + // key usage in the two-byte value case. 1.195 + uint8_t twoByteNotGoodData[] = { 1.196 + 0x03/*BIT STRING*/, 0x03/*LENGTH=3*/, unusedBits, 1.197 + static_cast<uint8_t>(~bits), 1.198 + static_cast<uint8_t>((0xFFu >> unusedBits) << unusedBits) 1.199 + }; 1.200 + const SECItem twoByteNotGood = { 1.201 + siBuffer, twoByteNotGoodData, sizeof(twoByteNotGoodData) 1.202 + }; 1.203 + ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, &twoByteNotGood, 1.204 + usage)); 1.205 + ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeCA, &twoByteNotGood, usage)); 1.206 +} 1.207 + 1.208 +TEST(pkixcheck_CheckKeyUsage, simpleCases) 1.209 +{ 1.210 + ASSERT_SimpleCase(7, 0x80, KeyUsage::digitalSignature); 1.211 + ASSERT_SimpleCase(6, 0x40, KeyUsage::nonRepudiation); 1.212 + ASSERT_SimpleCase(5, 0x20, KeyUsage::keyEncipherment); 1.213 + ASSERT_SimpleCase(4, 0x10, KeyUsage::dataEncipherment); 1.214 + ASSERT_SimpleCase(3, 0x08, KeyUsage::keyAgreement); 1.215 +} 1.216 + 1.217 +// Only CAs are allowed to assert keyCertSign 1.218 +TEST(pkixcheck_CheckKeyUsage, keyCertSign) 1.219 +{ 1.220 + NAMED_SIMPLE_KU(good, 2, 0x04); 1.221 + ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, &good, 1.222 + KeyUsage::keyCertSign)); 1.223 + ASSERT_Success(CheckKeyUsage(EndEntityOrCA::MustBeCA, &good, 1.224 + KeyUsage::keyCertSign)); 1.225 + 1.226 + // Test that none of the other non-padding bits are mistaken for the given 1.227 + // key usage in the one-byte value case. 1.228 + NAMED_SIMPLE_KU(notGood, 2, 0xFB); 1.229 + ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, ¬Good, 1.230 + KeyUsage::keyCertSign)); 1.231 + ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeCA, ¬Good, 1.232 + KeyUsage::keyCertSign)); 1.233 + 1.234 + // Test that none of the other non-padding bits are mistaken for the given 1.235 + // key usage in the two-byte value case. 1.236 + static uint8_t twoByteNotGoodData[] = { 1.237 + 0x03/*BIT STRING*/, 0x03/*LENGTH=3*/, 2/*unused bits*/, 0xFBu, 0xFCu 1.238 + }; 1.239 + static const SECItem twoByteNotGood = { 1.240 + siBuffer, twoByteNotGoodData, sizeof(twoByteNotGoodData) 1.241 + }; 1.242 + ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, &twoByteNotGood, 1.243 + KeyUsage::keyCertSign)); 1.244 + ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeCA, &twoByteNotGood, 1.245 + KeyUsage::keyCertSign)); 1.246 +} 1.247 + 1.248 +TEST(pkixcheck_CheckKeyUsage, unusedBitNotZero) 1.249 +{ 1.250 + // single byte control case 1.251 + static uint8_t controlOneValueByteData[] = { 1.252 + 0x03/*BIT STRING*/, 0x02/*LENGTH=2*/, 7/*unused bits*/, 0x80 1.253 + }; 1.254 + const SECItem controlOneValueByte = { 1.255 + siBuffer, 1.256 + controlOneValueByteData, 1.257 + sizeof(controlOneValueByteData) 1.258 + }; 1.259 + ASSERT_Success(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, 1.260 + &controlOneValueByte, 1.261 + KeyUsage::digitalSignature)); 1.262 + ASSERT_Success(CheckKeyUsage(EndEntityOrCA::MustBeCA, &controlOneValueByte, 1.263 + KeyUsage::digitalSignature)); 1.264 + 1.265 + // single-byte test case 1.266 + static uint8_t oneValueByteData[] = { 1.267 + 0x03/*BIT STRING*/, 0x02/*LENGTH=2*/, 7/*unused bits*/, 0x80 | 0x01 1.268 + }; 1.269 + const SECItem oneValueByte = { 1.270 + siBuffer, 1.271 + oneValueByteData, 1.272 + sizeof(oneValueByteData) 1.273 + }; 1.274 + ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, &oneValueByte, 1.275 + KeyUsage::digitalSignature)); 1.276 + ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeCA, &oneValueByte, 1.277 + KeyUsage::digitalSignature)); 1.278 + 1.279 + // two-byte control case 1.280 + static uint8_t controlTwoValueBytesData[] = { 1.281 + 0x03/*BIT STRING*/, 0x03/*LENGTH=3*/, 7/*unused bits*/, 1.282 + 0x80 | 0x01, 0x80 1.283 + }; 1.284 + const SECItem controlTwoValueBytes = { 1.285 + siBuffer, 1.286 + controlTwoValueBytesData, 1.287 + sizeof(controlTwoValueBytesData) 1.288 + }; 1.289 + ASSERT_Success(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, 1.290 + &controlTwoValueBytes, 1.291 + KeyUsage::digitalSignature)); 1.292 + ASSERT_Success(CheckKeyUsage(EndEntityOrCA::MustBeCA, &controlTwoValueBytes, 1.293 + KeyUsage::digitalSignature)); 1.294 + 1.295 + // two-byte test case 1.296 + static uint8_t twoValueBytesData[] = { 1.297 + 0x03/*BIT STRING*/, 0x03/*LENGTH=3*/, 7/*unused bits*/, 1.298 + 0x80 | 0x01, 0x80 | 0x01 1.299 + }; 1.300 + const SECItem twoValueBytes = { 1.301 + siBuffer, 1.302 + twoValueBytesData, 1.303 + sizeof(twoValueBytesData) 1.304 + }; 1.305 + ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, &twoValueBytes, 1.306 + KeyUsage::digitalSignature)); 1.307 + ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeCA, &twoValueBytes, 1.308 + KeyUsage::digitalSignature)); 1.309 +}