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