tor-browser

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

BTVerificationTest.cpp (11102B)


      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 Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "BTVerifier.h"
      8 #include "CTTestUtils.h"
      9 #include "gtest/gtest.h"
     10 
     11 #include "nss.h"
     12 
     13 namespace mozilla {
     14 namespace ct {
     15 
     16 using namespace pkix;
     17 
     18 struct BTVerificationTestParams {
     19  const char* mInclusionProofHex;
     20  const char* mExpectedRootHashHex;
     21  const char* mInputHex;
     22  pkix::DigestAlgorithm mDigestAlgorithm;
     23  pkix::Result mExpectedVerificationResult;
     24 };
     25 
     26 class BTVerificationTest
     27    : public ::testing::Test,
     28      public ::testing::WithParamInterface<BTVerificationTestParams> {
     29  void SetUp() override {
     30    if (!NSS_IsInitialized()) {
     31      if (NSS_NoDB_Init(nullptr) != SECSuccess) {
     32        abort();
     33      }
     34    }
     35  }
     36 };
     37 
     38 // This comes from testing/mozharness/test/test_mozilla_merkle.py
     39 static const char* kValidInclusionProofHex =
     40    "020000"
     41    "0000000000000007"  // 7 total nodes
     42    "0000000000000005"  // leaf index is 5
     43    "0063"              // 99 (in base 10) bytes follow
     44    "20"                // 32 byte hash
     45    "2ff3bdac9bec3580b82da8a357746f15919414d9cbe517e2dd96910c9814c30c"
     46    "20"
     47    "bb13dfb7b202a95f241ea1715c8549dc048d9936ec747028002f7c795de72fcf"
     48    "20"
     49    "380d0dc6fd7d4f37859a12dbfc7171b3cce29ab0688c6cffd2b15f3e0b21af49";
     50 
     51 static const char* kExpectedRootHashHex =
     52    "d1a0d3947db4ae8305f2ac32985957e02659b2ea3c10da52a48d2526e9af3bbc";
     53 
     54 static const char* kInputHex = "81aae91cf90be172eedd1c75c349bf9e";
     55 static const char* kAlteredInputHex = "81aae91c0000000000000000c349bf9e";
     56 
     57 // Same as kValidInclusionProofHex, but missing the last hash (the proof is
     58 // still structurally valid, so it decodes successfully).
     59 static const char* kShortInclusionProofHex =
     60    "020000"
     61    "0000000000000007"  // 7 total nodes
     62    "0000000000000005"  // leaf index is 5
     63    "0042"              // 66 (in base 10) bytes follow
     64    "20"                // 32 byte hash
     65    "2ff3bdac9bec3580b82da8a357746f15919414d9cbe517e2dd96910c9814c30c"
     66    "20"
     67    "bb13dfb7b202a95f241ea1715c8549dc048d9936ec747028002f7c795de72fcf";
     68 
     69 // Same as kValidInclusionProofHex, but has too many hashes (the proof is
     70 // still structurally valid, so it decodes successfully).
     71 static const char* kLongInclusionProofHex =
     72    "020000"
     73    "0000000000000007"  // 7 total nodes
     74    "0000000000000005"  // leaf index is 5
     75    "0084"              // 132 (in base 10) bytes follow
     76    "20"                // 32 byte hash
     77    "2ff3bdac9bec3580b82da8a357746f15919414d9cbe517e2dd96910c9814c30c"
     78    "20"
     79    "bb13dfb7b202a95f241ea1715c8549dc048d9936ec747028002f7c795de72fcf"
     80    "20"
     81    "380d0dc6fd7d4f37859a12dbfc7171b3cce29ab0688c6cffd2b15f3e0b21af49"
     82    "20"
     83    "abbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabba";
     84 
     85 static const char* kIncorrectRootHashHex =
     86    "beebeebeebeebeebeebeebeebeebeebeebeebeebeebeebeebeebeebeebeebeee";
     87 
     88 static const char* kWrongTreeSizeInclusionProofHex =
     89    "020000"
     90    "0000000000000009"  // 9 total nodes (this is wrong)
     91    "0000000000000005"  // leaf index is 5
     92    "0063"              // 99 (in base 10) bytes follow
     93    "20"                // 32 byte hash
     94    "2ff3bdac9bec3580b82da8a357746f15919414d9cbe517e2dd96910c9814c30c"
     95    "20"
     96    "bb13dfb7b202a95f241ea1715c8549dc048d9936ec747028002f7c795de72fcf"
     97    "20"
     98    "380d0dc6fd7d4f37859a12dbfc7171b3cce29ab0688c6cffd2b15f3e0b21af49";
     99 
    100 static const char* kWrongLeafIndexInclusionProofHex =
    101    "020000"
    102    "0000000000000007"  // 7 total nodes
    103    "0000000000000002"  // leaf index is 2 (this is wrong)
    104    "0063"              // 99 (in base 10) bytes follow
    105    "20"                // 32 byte hash
    106    "2ff3bdac9bec3580b82da8a357746f15919414d9cbe517e2dd96910c9814c30c"
    107    "20"
    108    "bb13dfb7b202a95f241ea1715c8549dc048d9936ec747028002f7c795de72fcf"
    109    "20"
    110    "380d0dc6fd7d4f37859a12dbfc7171b3cce29ab0688c6cffd2b15f3e0b21af49";
    111 
    112 // This is a longer proof taken from the Firefox 62.0.2 release.
    113 static const char* kValidInclusionProof2Hex =
    114    "020000"
    115    "0000000000000cb3"
    116    "00000000000000e2"
    117    "018c"
    118    "20"
    119    "6d3d060c72c28cd1967a6ce4e87a470c266981ee8beb6e5956745b5839120338"
    120    "20"
    121    "cd028053c51f52447cd2b1ffea7761be546b72832d776db155008dc3071231eb"
    122    "20"
    123    "36167b32f7ba4980257c79ed65d133d8c53efbfd7addaa391a121953c78b2b98"
    124    "20"
    125    "f2b4abf09140b05058a74e25f4008157655e73fa4aeece9b3f2a40dbbae95c16"
    126    "20"
    127    "a2be4813b2ca0e7bb755ed5459789c25a83465fb3f2808590c04c64cdbb404ef"
    128    "20"
    129    "43e4341b74ea11f075f35761b867cb256e9d42c4c1253d6b5c958174daa800da"
    130    "20"
    131    "1c925ec8d2d4014c0b84d7bed8065d9e7b326e3e4eaebc90d7a6a66431249851"
    132    "20"
    133    "bd275e9e4e48c3725f6ef68c2661d4d6ae415129cfb0ea0881177f5347d683ae"
    134    "20"
    135    "01e84996a7cc1719b19a4a7e48941657b125bcd0dfd03d183daff87de6a480c3"
    136    "20"
    137    "664b6962909692980661be55e8bdadc48350b2461d37372457e8ff97824ae8da"
    138    "20"
    139    "39f7ab1500a58643fccc9e07ed409be4c707c5536b95c57f6716207656464019"
    140    "20"
    141    "d68c856664d660456d4c85498c2cc2abfb955a63bd1fb23f3e25850da80153f6";
    142 
    143 static const char* kExpectedRootHash2Hex =
    144    "0d489b16a64b80035a8d08ce55549c89c4b67be64a0456382cc5be1e51ddae1a";
    145 
    146 // This the hex encoding of the SHA-256 hash of
    147 // linux-x86_64/en-US/firefox-62.0.2.tar.bz2, encoded (again) in hex (because
    148 // that's how generate-checksums.py currently builds the binary transparency
    149 // tree).
    150 static const char* kInput2Hex =
    151    "3231623461306361626538663030306261663236373235643530313462386434"
    152    "3865353561333832336538653665656131343638313062313031623034396536";
    153 
    154 // This is the hex encoding of an inclusion proof for
    155 // update/win32/en-GB/firefox-61.0-62.0.2.partial.mar using SHA-512.
    156 static const char* kValidInclusionProofSHA512Hex =
    157    "020000"
    158    "0000000000000cb3"
    159    "00000000000007ac"
    160    "030c"
    161    "40"
    162    "b39fbe359108724ec1daed2a8c88511c6b94a74563bfaaf25b774286ab03cab9"
    163    "b2e64bbd4eeb02003b7397cd814b5d18a160e14ad08eca04559abe146201e027"
    164    "40"
    165    "de119745a41884ed482a41638cc1979d89e1bd0ca295e0c412e7ee4b5c2e042d"
    166    "a1f4aa9c7f1e58b78fac10400b207197383177401976ef6baa80d482c102a94f"
    167    "40"
    168    "d0fe203b0e95cbe48e2e663538aba382718c85ae167d8c4ccf326519f81b3860"
    169    "55058f6a49943b8ed228af88b3414ec00e939ad8dc736f502ca90d63494eddcd"
    170    "40"
    171    "ae825352bbe12845fb1d3be27375c27dd462ebd6dc6d7bd0b5929df97aaccf1a"
    172    "9eedb304ae1e9742b1e2a2ba8b22408d2d52e3bb3d547632d5f03cfe112572d2"
    173    "40"
    174    "1ab0f7f7d674c691cf8e51d4409d3402d94927231b82f7f71f16828dd9e36152"
    175    "1a69f7e571df06aea16c83df88dc74042444ae8771375a7118477275395b570d"
    176    "40"
    177    "9c6b94c5be456c68518753cf626daf11b30ce981e18b76c036664dcafeba19b7"
    178    "3f5ee20ab35aa38b11c92e2c8f103d1b19113b7171c615ce0b9c5ff520242d8c"
    179    "40"
    180    "d395ef3cd63ae617a96bd6c5c361d5f6aaccff1ed90599115394310dfa0c528d"
    181    "611998d325f374c01a827ee900d72ed66d299845438bba565ba666c588b232a0"
    182    "40"
    183    "ce3548561f5ec7a94a6c7a2adc604f5e32869d0727cee80f12c95cab2a996965"
    184    "6ad61a02b35e0fb2d0031ea496381f1413d33b8cbfdf092accd903881e083ee0"
    185    "40"
    186    "a4247b649fee9017d9c9e729c4763719b7155056013abc488de0079dc7bddce6"
    187    "57a93f2596967cfb123d812a901bc4ffe0338cbecf30adc1a821e7261f88e3cd"
    188    "40"
    189    "7d2056ea6645b0306373fa2e26fbc4a4ccd4c82cb7d605d2372fa297654cd3a0"
    190    "b151f6b0fffe7472661de79c7ce7873cb75e05cad5ea40173be540e16d51414d"
    191    "40"
    192    "eed2c98b3d8b8035777af74a0d5dd38963f84c09e6f42b6ca4e290674c175035"
    193    "b9bc85bb4304fcf3d042c444f951b3b134563c6936a1b176679e35e94c42416b"
    194    "40"
    195    "6167cccd9d03909f95bb389936766340234b5b3e35dfa8c81d330db9055d7b7d"
    196    "bfaf262f1821b4a68f43af62c53987550b4174eaab8357f9bd83f2715c98d441";
    197 
    198 // This is the hex encoding of the expected root hash of the SHA-512 tree.
    199 static const char* kExpectedRootHashSHA512Hex =
    200    "6f20812da2980393767e98dd7f79d89aa41e029c790d3908739c02c01d9c6525"
    201    "8bb3e24ab608c95b063259620751ce258930d48929cbe543b166c33c4de65e60";
    202 
    203 // This the hex encoding of the SHA-512 hash of
    204 // update/win32/en-GB/firefox-61.0-62.0.2.partial.mar, encoded (again) in hex.
    205 static const char* kInputSHA512Hex =
    206    "6237656563626164353363386432346230383763666437323333303162326437"
    207    "6234326136323536663462636336356134623231636437376133613830613734"
    208    "3865396533623666306432333839666234623763396563356638643833373534"
    209    "6239313635313165333661373238653863303236376564653761666561316638";
    210 
    211 MOZ_RUNINIT static const BTVerificationTestParams
    212    BT_VERIFICATION_TEST_PARAMS[] = {
    213        {kValidInclusionProofHex, kExpectedRootHashHex, kInputHex,
    214         pkix::DigestAlgorithm::sha256, Success},
    215        {kValidInclusionProofHex, kExpectedRootHashHex, kAlteredInputHex,
    216         pkix::DigestAlgorithm::sha256, pkix::Result::ERROR_BAD_SIGNATURE},
    217        {kShortInclusionProofHex, kExpectedRootHashHex, kInputHex,
    218         pkix::DigestAlgorithm::sha256, pkix::Result::ERROR_BAD_SIGNATURE},
    219        {kLongInclusionProofHex, kExpectedRootHashHex, kInputHex,
    220         pkix::DigestAlgorithm::sha256, pkix::Result::ERROR_BAD_SIGNATURE},
    221        {kValidInclusionProofHex, kIncorrectRootHashHex, kInputHex,
    222         pkix::DigestAlgorithm::sha256, pkix::Result::ERROR_BAD_SIGNATURE},
    223        {kWrongTreeSizeInclusionProofHex, kExpectedRootHashHex, kInputHex,
    224         pkix::DigestAlgorithm::sha256, pkix::Result::ERROR_BAD_SIGNATURE},
    225        {kWrongLeafIndexInclusionProofHex, kExpectedRootHashHex, kInputHex,
    226         pkix::DigestAlgorithm::sha256, pkix::Result::ERROR_BAD_SIGNATURE},
    227        {kValidInclusionProofHex, kExpectedRootHashHex, kInputHex,
    228         pkix::DigestAlgorithm::sha512, pkix::Result::ERROR_BAD_SIGNATURE},
    229        {kValidInclusionProof2Hex, kExpectedRootHash2Hex, kInput2Hex,
    230         pkix::DigestAlgorithm::sha256, Success},
    231        {kValidInclusionProofSHA512Hex, kExpectedRootHashSHA512Hex,
    232         kInputSHA512Hex, pkix::DigestAlgorithm::sha512, Success},
    233        {kValidInclusionProofSHA512Hex, kExpectedRootHashSHA512Hex,
    234         kInputSHA512Hex, pkix::DigestAlgorithm::sha256,
    235         pkix::Result::ERROR_BAD_SIGNATURE},
    236 };
    237 
    238 TEST_P(BTVerificationTest, BTVerificationSimpleTest) {
    239  const BTVerificationTestParams& params(GetParam());
    240 
    241  Buffer encodedProofBuffer(HexToBytes(params.mInclusionProofHex));
    242  Input encodedProof = InputForBuffer(encodedProofBuffer);
    243  InclusionProofDataV2 ipr;
    244  ASSERT_EQ(Success, DecodeInclusionProof(encodedProof, ipr));
    245 
    246  Buffer leafEntryBuffer(HexToBytes(params.mInputHex));
    247  Input leafEntry = InputForBuffer(leafEntryBuffer);
    248  Buffer expectedRootHashBuffer(HexToBytes(params.mExpectedRootHashHex));
    249  Input expectedRootHash = InputForBuffer(expectedRootHashBuffer);
    250  ASSERT_EQ(params.mExpectedVerificationResult,
    251            VerifyInclusionProof(ipr, leafEntry, expectedRootHash,
    252                                 params.mDigestAlgorithm));
    253 }
    254 
    255 INSTANTIATE_TEST_SUITE_P(BTVerificationTest, BTVerificationTest,
    256                         testing::ValuesIn(BT_VERIFICATION_TEST_PARAMS));
    257 
    258 }  // namespace ct
    259 }  // namespace mozilla