security/pkix/test/gtest/pkixcheck_CheckKeyUsage_tests.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     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  */
    25 #include "pkixgtest.h"
    27 using namespace mozilla::pkix;
    28 using namespace mozilla::pkix::test;
    30 namespace mozilla { namespace pkix {
    32 extern Result CheckKeyUsage(EndEntityOrCA endEntityOrCA,
    33                             const SECItem* encodedKeyUsage,
    34                             KeyUsage requiredKeyUsageIfPresent);
    36 } } // namespace mozilla::pkix
    38 #define ASSERT_BAD(x) \
    39   ASSERT_RecoverableError(SEC_ERROR_INADEQUATE_KEY_USAGE, x)
    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   }
    52 static uint8_t dummy;
    53 static const SECItem empty_null    = { siBuffer, nullptr, 0 };
    54 static const SECItem empty_nonnull = { siBuffer, &dummy, 0 };
    56 // Note that keyCertSign is really the only interesting case for CA
    57 // certificates since we don't support cRLSign.
    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.
    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 }
    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 }
    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 }
    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 }
   105 TEST(pkixchekc_CheckKeyusage, maxUnusedBits)
   106 {
   107   NAMED_SIMPLE_KU(encoded, 7, 0x80);
   108   ASSERT_Success(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, &encoded,
   109                                KeyUsage::digitalSignature));
   110 }
   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));
   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 }
   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   };
   148   ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, &DER,
   149                            KeyUsage::digitalSignature));
   150   ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeCA, &DER,
   151                            KeyUsage::keyCertSign));
   152 }
   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   };
   165   ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity, &DER,
   166                            KeyUsage::digitalSignature));
   167   ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeCA, &DER,
   168                            KeyUsage::keyCertSign));
   169 }
   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));
   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.
   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));
   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 }
   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 }
   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));
   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));
   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 }
   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));
   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));
   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));
   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