tor-browser

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

pkixcheck_CheckSignatureAlgorithm_tests.cpp (13603B)


      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 2015 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 #include "mozpkix/pkixder.h"
     28 
     29 using namespace mozilla::pkix;
     30 using namespace mozilla::pkix::test;
     31 
     32 namespace mozilla { namespace pkix {
     33 
     34 extern Result CheckSignatureAlgorithm(
     35                TrustDomain& trustDomain, EndEntityOrCA endEntityOrCA,
     36                Time notBefore,
     37                const der::SignedDataWithSignature& signedData,
     38                Input signatureValue);
     39 
     40 } } // namespace mozilla::pkix
     41 
     42 struct CheckSignatureAlgorithmTestParams
     43 {
     44  ByteString signatureAlgorithmValue;
     45  ByteString signatureValue;
     46  unsigned int signatureLengthInBytes;
     47  Result expectedResult;
     48 };
     49 
     50 ::std::ostream& operator<<(::std::ostream& os,
     51                           const CheckSignatureAlgorithmTestParams&)
     52 {
     53  return os << "TODO (bug 1318770)";
     54 }
     55 
     56 #define BS(s) ByteString(s, MOZILLA_PKIX_ARRAY_LENGTH(s))
     57 
     58 // python DottedOIDToCode.py --tlv sha256WithRSAEncryption 1.2.840.113549.1.1.11
     59 static const uint8_t tlv_sha256WithRSAEncryption[] = {
     60  0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b
     61 };
     62 
     63 // Same as tlv_sha256WithRSAEncryption, except one without the "0x0b" and with
     64 // the DER length decreased accordingly.
     65 static const uint8_t tlv_sha256WithRSAEncryption_truncated[] = {
     66  0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01
     67 };
     68 
     69 // python DottedOIDToCode.py --tlv sha-1WithRSAEncryption 1.2.840.113549.1.1.5
     70 static const uint8_t tlv_sha_1WithRSAEncryption[] = {
     71  0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05
     72 };
     73 
     74 // python DottedOIDToCode.py --tlv sha1WithRSASignature 1.3.14.3.2.29
     75 static const uint8_t tlv_sha1WithRSASignature[] = {
     76  0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d
     77 };
     78 
     79 // python DottedOIDToCode.py --tlv md5WithRSAEncryption 1.2.840.113549.1.1.4
     80 static const uint8_t tlv_md5WithRSAEncryption[] = {
     81  0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x04
     82 };
     83 
     84 // CA/B Forum BR 1.8.1 Section 7.1.3.2.1
     85 // Params for RSA-PSS with SHA-256, MGF-1 with SHA-256, and a salt length
     86 // of 32 bytes:
     87 static const uint8_t rsaPSSWithSHA256[] = {
     88  0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0a, 0x30,
     89  0x34, 0xa0, 0x0f, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65,
     90  0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0xa1, 0x1c, 0x30, 0x1a, 0x06, 0x09,
     91  0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x08, 0x30, 0x0d, 0x06,
     92  0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00,
     93  0xa2, 0x03, 0x02, 0x01, 0x20
     94 };
     95 
     96 static const CheckSignatureAlgorithmTestParams
     97  CHECKSIGNATUREALGORITHM_TEST_PARAMS[] =
     98 {
     99  { // Both algorithm IDs are empty
    100    ByteString(),
    101    ByteString(),
    102    2048 / 8,
    103    Result::ERROR_BAD_DER,
    104  },
    105  { // signatureAlgorithm is empty, signature is supported.
    106    ByteString(),
    107    BS(tlv_sha256WithRSAEncryption),
    108    2048 / 8,
    109    Result::ERROR_BAD_DER,
    110  },
    111  { // signatureAlgorithm is supported, signature is empty.
    112    BS(tlv_sha256WithRSAEncryption),
    113    ByteString(),
    114    2048 / 8,
    115    Result::ERROR_BAD_DER,
    116  },
    117  { // Algorithms match, both are supported.
    118    BS(tlv_sha256WithRSAEncryption),
    119    BS(tlv_sha256WithRSAEncryption),
    120    2048 / 8,
    121    Success
    122  },
    123  { // Algorithms do not match because signatureAlgorithm is truncated.
    124    BS(tlv_sha256WithRSAEncryption_truncated),
    125    BS(tlv_sha256WithRSAEncryption),
    126    2048 / 8,
    127    Result::ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED
    128  },
    129  { // Algorithms do not match because signature is truncated.
    130    BS(tlv_sha256WithRSAEncryption),
    131    BS(tlv_sha256WithRSAEncryption_truncated),
    132    2048 / 8,
    133    Result::ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED
    134  },
    135  { // Algorithms do not match, both are supported.
    136    BS(tlv_sha_1WithRSAEncryption),
    137    BS(tlv_sha256WithRSAEncryption),
    138    2048 / 8,
    139    Result::ERROR_SIGNATURE_ALGORITHM_MISMATCH,
    140  },
    141  { // Algorithms do not match, both are supported.
    142    BS(tlv_sha256WithRSAEncryption),
    143    BS(tlv_sha_1WithRSAEncryption),
    144    2048 / 8,
    145    Result::ERROR_SIGNATURE_ALGORITHM_MISMATCH,
    146  },
    147  { // Algorithms match, both are unsupported.
    148    BS(tlv_md5WithRSAEncryption),
    149    BS(tlv_md5WithRSAEncryption),
    150    2048 / 8,
    151    Result::ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED
    152  },
    153  { // signatureAlgorithm is unsupported, signature is supported.
    154    BS(tlv_md5WithRSAEncryption),
    155    BS(tlv_sha256WithRSAEncryption),
    156    2048 / 8,
    157    Result::ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED
    158  },
    159  { // signatureAlgorithm is supported, signature is unsupported.
    160    BS(tlv_sha256WithRSAEncryption),
    161    BS(tlv_md5WithRSAEncryption),
    162    2048 / 8,
    163    Result::ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED
    164  },
    165  { // Both have the optional NULL parameter.
    166    BS(tlv_sha256WithRSAEncryption) + TLV(der::NULLTag, ByteString()),
    167    BS(tlv_sha256WithRSAEncryption) + TLV(der::NULLTag, ByteString()),
    168    2048 / 8,
    169    Success
    170  },
    171  { // signatureAlgorithm has the optional NULL parameter, signature doesn't.
    172    BS(tlv_sha256WithRSAEncryption) + TLV(der::NULLTag, ByteString()),
    173    BS(tlv_sha256WithRSAEncryption),
    174    2048 / 8,
    175    Success
    176  },
    177  { // signatureAlgorithm does not have the optional NULL parameter, signature
    178    // does.
    179    BS(tlv_sha256WithRSAEncryption),
    180    BS(tlv_sha256WithRSAEncryption) + TLV(der::NULLTag, ByteString()),
    181    2048 / 8,
    182    Success
    183  },
    184  { // The different OIDs for RSA-with-SHA1 we support are semantically
    185    // equivalent.
    186    BS(tlv_sha1WithRSASignature),
    187    BS(tlv_sha_1WithRSAEncryption),
    188    2048 / 8,
    189    Success,
    190  },
    191  { // The different OIDs for RSA-with-SHA1 we support are semantically
    192    // equivalent (opposite order).
    193    BS(tlv_sha_1WithRSAEncryption),
    194    BS(tlv_sha1WithRSASignature),
    195    2048 / 8,
    196    Success,
    197  },
    198  { // Algorithms match, both are supported, key size is not a multile of 128
    199    // bits. This test verifies that we're not wrongly rounding up the
    200    // signature size like we did in the original patch for bug 1131767.
    201    BS(tlv_sha256WithRSAEncryption),
    202    BS(tlv_sha256WithRSAEncryption),
    203    (2048 / 8) - 1,
    204    Success
    205  },
    206  {
    207    // signatureAlgorithm and signature are RSA-PSS
    208    BS(rsaPSSWithSHA256),
    209    BS(rsaPSSWithSHA256),
    210    2048 / 8,
    211    Success
    212  },
    213  {
    214    // signatureAlgorithm is RSA-PSS, signature is RSA PKCS#1v1.5
    215    BS(rsaPSSWithSHA256),
    216    BS(tlv_sha256WithRSAEncryption),
    217    2048 / 8,
    218    Result::ERROR_SIGNATURE_ALGORITHM_MISMATCH
    219  },
    220 };
    221 
    222 class pkixcheck_CheckSignatureAlgorithm
    223  : public ::testing::Test
    224  , public ::testing::WithParamInterface<CheckSignatureAlgorithmTestParams>
    225 {
    226 };
    227 
    228 class pkixcheck_CheckSignatureAlgorithm_TrustDomain final
    229  : public EverythingFailsByDefaultTrustDomain
    230 {
    231 public:
    232  explicit pkixcheck_CheckSignatureAlgorithm_TrustDomain(
    233             unsigned int aPublicKeySizeInBits)
    234    : publicKeySizeInBits(aPublicKeySizeInBits)
    235    , checkedDigestAlgorithm(false)
    236    , checkedModulusSizeInBits(false)
    237  {
    238  }
    239 
    240  Result CheckSignatureDigestAlgorithm(DigestAlgorithm, EndEntityOrCA, Time)
    241    override
    242  {
    243    checkedDigestAlgorithm = true;
    244    return Success;
    245  }
    246 
    247  Result CheckRSAPublicKeyModulusSizeInBits(EndEntityOrCA endEntityOrCA,
    248                                            unsigned int modulusSizeInBits)
    249    override
    250  {
    251    EXPECT_EQ(EndEntityOrCA::MustBeEndEntity, endEntityOrCA);
    252    EXPECT_EQ(publicKeySizeInBits, modulusSizeInBits);
    253    checkedModulusSizeInBits = true;
    254    return Success;
    255  }
    256 
    257  const unsigned int publicKeySizeInBits;
    258  bool checkedDigestAlgorithm;
    259  bool checkedModulusSizeInBits;
    260 };
    261 
    262 TEST_P(pkixcheck_CheckSignatureAlgorithm, CheckSignatureAlgorithm)
    263 {
    264  const Time now(Now());
    265  const CheckSignatureAlgorithmTestParams& params(GetParam());
    266 
    267  Input signatureValueInput;
    268  ASSERT_EQ(Success,
    269            signatureValueInput.Init(params.signatureValue.data(),
    270                                     params.signatureValue.length()));
    271 
    272  pkixcheck_CheckSignatureAlgorithm_TrustDomain
    273    trustDomain(params.signatureLengthInBytes * 8);
    274 
    275  der::SignedDataWithSignature signedData;
    276  ASSERT_EQ(Success,
    277            signedData.algorithm.Init(params.signatureAlgorithmValue.data(),
    278                                      params.signatureAlgorithmValue.length()));
    279 
    280  ByteString dummySignature(params.signatureLengthInBytes, 0xDE);
    281  ASSERT_EQ(Success,
    282            signedData.signature.Init(dummySignature.data(),
    283                                      dummySignature.length()));
    284 
    285  ASSERT_EQ(params.expectedResult,
    286            CheckSignatureAlgorithm(trustDomain, EndEntityOrCA::MustBeEndEntity,
    287                                    now, signedData, signatureValueInput));
    288  ASSERT_EQ(params.expectedResult == Success,
    289            trustDomain.checkedDigestAlgorithm);
    290  ASSERT_EQ(params.expectedResult == Success,
    291            trustDomain.checkedModulusSizeInBits);
    292 }
    293 
    294 INSTANTIATE_TEST_SUITE_P(
    295  pkixcheck_CheckSignatureAlgorithm, pkixcheck_CheckSignatureAlgorithm,
    296  testing::ValuesIn(CHECKSIGNATUREALGORITHM_TEST_PARAMS));
    297 
    298 class pkixcheck_CheckSignatureAlgorithm_BuildCertChain_TrustDomain
    299  : public DefaultCryptoTrustDomain
    300 {
    301 public:
    302  explicit pkixcheck_CheckSignatureAlgorithm_BuildCertChain_TrustDomain(
    303             const ByteString& aIssuer)
    304    : issuer(aIssuer)
    305  {
    306  }
    307 
    308  Result GetCertTrust(EndEntityOrCA, const CertPolicyId&,
    309                      Input cert, /*out*/ TrustLevel& trustLevel) override
    310  {
    311    trustLevel = InputEqualsByteString(cert, issuer)
    312               ? TrustLevel::TrustAnchor
    313               : TrustLevel::InheritsTrust;
    314    return Success;
    315  }
    316 
    317  Result FindIssuer(Input, IssuerChecker& checker, Time) override
    318  {
    319    EXPECT_FALSE(ENCODING_FAILED(issuer));
    320 
    321    Input issuerInput;
    322    EXPECT_EQ(Success, issuerInput.Init(issuer.data(), issuer.length()));
    323 
    324    bool keepGoing;
    325    EXPECT_EQ(Success, checker.Check(issuerInput, nullptr, keepGoing));
    326    EXPECT_FALSE(keepGoing);
    327 
    328    return Success;
    329  }
    330 
    331  Result CheckRevocation(EndEntityOrCA, const CertID&, Time, Duration,
    332                         /*optional*/ const Input*,
    333                         /*optional*/ const Input*) override
    334  {
    335    return Success;
    336  }
    337 
    338  Result IsChainValid(const DERArray&, Time, const CertPolicyId&) override
    339  {
    340    return Success;
    341  }
    342 
    343  ByteString issuer;
    344 };
    345 
    346 // Test that CheckSignatureAlgorithm actually gets called at some point when
    347 // BuildCertChain is called.
    348 TEST_F(pkixcheck_CheckSignatureAlgorithm, BuildCertChain)
    349 {
    350  ScopedTestKeyPair keyPair(CloneReusedKeyPair());
    351  ASSERT_TRUE(keyPair.get());
    352 
    353  ByteString issuerExtensions[2];
    354  issuerExtensions[0] = CreateEncodedBasicConstraints(true, nullptr,
    355                                                      Critical::No);
    356  ASSERT_FALSE(ENCODING_FAILED(issuerExtensions[0]));
    357 
    358  ByteString issuer(CreateEncodedCertificate(3,
    359                                             sha256WithRSAEncryption(),
    360                                             CreateEncodedSerialNumber(1),
    361                                             CNToDERName("issuer"),
    362                                             oneDayBeforeNow, oneDayAfterNow,
    363                                             CNToDERName("issuer"),
    364                                             *keyPair,
    365                                             issuerExtensions,
    366                                             *keyPair,
    367                                             sha256WithRSAEncryption()));
    368  ASSERT_FALSE(ENCODING_FAILED(issuer));
    369 
    370  ByteString subject(CreateEncodedCertificate(3,
    371                                              sha1WithRSAEncryption(),
    372                                              CreateEncodedSerialNumber(2),
    373                                              CNToDERName("issuer"),
    374                                              oneDayBeforeNow, oneDayAfterNow,
    375                                              CNToDERName("subject"),
    376                                              *keyPair,
    377                                              nullptr,
    378                                              *keyPair,
    379                                              sha256WithRSAEncryption()));
    380  ASSERT_FALSE(ENCODING_FAILED(subject));
    381 
    382  Input subjectInput;
    383  ASSERT_EQ(Success, subjectInput.Init(subject.data(), subject.length()));
    384  pkixcheck_CheckSignatureAlgorithm_BuildCertChain_TrustDomain
    385    trustDomain(issuer);
    386  Result rv = BuildCertChain(trustDomain, subjectInput, Now(),
    387                             EndEntityOrCA::MustBeEndEntity,
    388                             KeyUsage::noParticularKeyUsageRequired,
    389                             KeyPurposeId::anyExtendedKeyUsage,
    390                             CertPolicyId::anyPolicy,
    391                             nullptr);
    392  ASSERT_EQ(Result::ERROR_SIGNATURE_ALGORITHM_MISMATCH, rv);
    393 }