tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

pkixcheck_CheckKeyUsage_tests.cpp (12698B)


      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 
     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 
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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.
    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 
    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 
    286 TEST_F(pkixcheck_CheckKeyUsage, trailingData)
    287 {
    288  static uint8_t keyUsageWithTrailingDataData[] = {
    289    0x03/*BIT STRING*/, 0x02/*LENGTH=2*/, 7/*unused bits*/, 0x80,
    290    // The BIT STRING has already ended, but there's trailing data
    291    0xab, 0xba
    292  };
    293  static const Input keyUsageWithTrailingDataBytes(keyUsageWithTrailingDataData);
    294  ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity,
    295                           &keyUsageWithTrailingDataBytes,
    296                           KeyUsage::digitalSignature));
    297  ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeCA,
    298                           &keyUsageWithTrailingDataBytes,
    299                           KeyUsage::digitalSignature));
    300 }