security/pkix/test/gtest/pkixcheck_CheckKeyUsage_tests.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

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

mercurial