Bug 1943761 - Add class alignment to the mozsearch analysis file. r=asuth
[gecko.git] / security / ct / tests / gtest / BTSignedTreeHeadTest.cpp
blobaddd6698090e85b7919e709592af0b1c92f4e43b
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/. */
7 #include "BTVerifier.h"
8 #include "CTTestUtils.h"
9 #include "gtest/gtest.h"
11 #include "nss.h"
13 namespace mozilla {
14 namespace ct {
16 using namespace pkix;
18 struct BTSignedTreeHeadTestParams {
19 const char* mSubjectPublicKeyInfoHex;
20 pkix::DigestAlgorithm mDigestAlgorithm;
21 pkix::der::PublicKeyAlgorithm mPublicKeyAlgorithm;
22 const char* mSignedTreeHeadHex;
24 pkix::Result mExpectedSignedTreeHeadResult;
25 uint64_t mExpectedTimestamp;
26 uint64_t mExpectedTreeSize;
27 const char* mExpectedRootHashHex;
30 class BTSignedTreeHeadTest
31 : public ::testing::Test,
32 public ::testing::WithParamInterface<BTSignedTreeHeadTestParams> {
33 void SetUp() override {
34 if (!NSS_IsInitialized()) {
35 if (NSS_NoDB_Init(nullptr) != SECSuccess) {
36 abort();
42 namespace ValidSTH {
43 #include "valid-sth.inc"
45 namespace ValidWithExtensionSTH {
46 #include "valid-with-extension-sth.inc"
48 namespace ValidSecp521r1SHA512STH {
49 #include "valid-secp521r1-sha512-sth.inc"
51 namespace SignatureCoversLogIDSTH {
52 #include "signature-covers-log-id-sth.inc"
54 namespace WrongSPKISTH {
55 #include "wrong-spki-sth.inc"
57 namespace WrongSigningKeySTH {
58 #include "wrong-signing-key-sth.inc"
60 namespace MissingLogIDSTH {
61 #include "missing-log-id-sth.inc"
63 namespace MissingTimestampSTH {
64 #include "missing-timestamp-sth.inc"
66 namespace MissingTreeSizeSTH {
67 #include "missing-tree-size-sth.inc"
69 namespace MissingRootHashSTH {
70 #include "missing-root-hash-sth.inc"
72 namespace MissingExtensionsSTH {
73 #include "missing-extensions-sth.inc"
75 namespace TruncatedLogIDSTH {
76 #include "truncated-log-id-sth.inc"
78 namespace TruncatedTimestampSTH {
79 #include "truncated-timestamp-sth.inc"
81 namespace TruncatedTreeSizeSTH {
82 #include "truncated-tree-size-sth.inc"
84 namespace TruncatedRootHashSTH {
85 #include "truncated-root-hash-sth.inc"
87 namespace TruncatedExtensionSTH {
88 #include "truncated-extension-sth.inc"
90 namespace RSASignerRSASPKISTH {
91 #include "rsa-signer-rsa-spki-sth.inc"
93 namespace RSASignerECSPKISTH {
94 #include "rsa-signer-ec-spki-sth.inc"
96 namespace ECSignerRSASPKISTH {
97 #include "ec-signer-rsa-spki-sth.inc"
100 static const char* kValidRootHashHex =
101 "d1a0d3947db4ae8305f2ac32985957e02659b2ea3c10da52a48d2526e9af3bbc";
103 static const char* kValidRootHashSHA512Hex =
104 "374d794a95cdcfd8b35993185fef9ba368f160d8daf432d08ba9f1ed1e5abe6c"
105 "c69291e0fa2fe0006a52570ef18c19def4e617c33ce52ef0a6e5fbe318cb0387";
107 MOZ_RUNINIT static const BTSignedTreeHeadTestParams
108 BT_SIGNED_TREE_HEAD_TEST_PARAMS[] = {
109 {ValidSTH::kSPKIHex, pkix::DigestAlgorithm::sha256,
110 pkix::der::PublicKeyAlgorithm::ECDSA, ValidSTH::kSTHHex, Success,
111 1541189938000, 7, kValidRootHashHex},
112 {ValidSTH::kSPKIHex, pkix::DigestAlgorithm::sha512,
113 pkix::der::PublicKeyAlgorithm::ECDSA, ValidSTH::kSTHHex,
114 Result::ERROR_BAD_SIGNATURE, 0, 0, nullptr},
115 {ValidSTH::kSPKIHex, pkix::DigestAlgorithm::sha256,
116 pkix::der::PublicKeyAlgorithm::RSA_PKCS1, ValidSTH::kSTHHex,
117 Result::FATAL_ERROR_INVALID_ARGS, 0, 0, nullptr},
118 {ValidWithExtensionSTH::kSPKIHex, pkix::DigestAlgorithm::sha256,
119 pkix::der::PublicKeyAlgorithm::ECDSA, ValidWithExtensionSTH::kSTHHex,
120 Success, 1541189938000, 7, kValidRootHashHex},
121 {ValidSecp521r1SHA512STH::kSPKIHex, pkix::DigestAlgorithm::sha512,
122 pkix::der::PublicKeyAlgorithm::ECDSA, ValidSecp521r1SHA512STH::kSTHHex,
123 Success, 1542136309473, 731393445, kValidRootHashSHA512Hex},
124 {ValidSecp521r1SHA512STH::kSPKIHex, pkix::DigestAlgorithm::sha256,
125 pkix::der::PublicKeyAlgorithm::ECDSA, ValidSecp521r1SHA512STH::kSTHHex,
126 Result::ERROR_BAD_SIGNATURE, 0, 0, nullptr},
127 {ValidSTH::kSPKIHex, pkix::DigestAlgorithm::sha512,
128 pkix::der::PublicKeyAlgorithm::ECDSA, ValidSecp521r1SHA512STH::kSTHHex,
129 Result::ERROR_BAD_SIGNATURE, 0, 0, nullptr},
130 {SignatureCoversLogIDSTH::kSPKIHex, pkix::DigestAlgorithm::sha256,
131 pkix::der::PublicKeyAlgorithm::ECDSA, SignatureCoversLogIDSTH::kSTHHex,
132 Result::ERROR_BAD_SIGNATURE, 0, 0, nullptr},
133 {WrongSPKISTH::kSPKIHex, pkix::DigestAlgorithm::sha256,
134 pkix::der::PublicKeyAlgorithm::ECDSA, WrongSPKISTH::kSTHHex,
135 Result::ERROR_BAD_SIGNATURE, 0, 0, nullptr},
136 {WrongSigningKeySTH::kSPKIHex, pkix::DigestAlgorithm::sha256,
137 pkix::der::PublicKeyAlgorithm::ECDSA, WrongSigningKeySTH::kSTHHex,
138 Result::ERROR_BAD_SIGNATURE, 0, 0, nullptr},
139 {MissingLogIDSTH::kSPKIHex, pkix::DigestAlgorithm::sha256,
140 pkix::der::PublicKeyAlgorithm::ECDSA, MissingLogIDSTH::kSTHHex,
141 Result::ERROR_BAD_DER, 0, 0, nullptr},
142 {MissingTimestampSTH::kSPKIHex, pkix::DigestAlgorithm::sha256,
143 pkix::der::PublicKeyAlgorithm::ECDSA, MissingTimestampSTH::kSTHHex,
144 Result::ERROR_BAD_DER, 0, 0, nullptr},
145 {MissingTreeSizeSTH::kSPKIHex, pkix::DigestAlgorithm::sha256,
146 pkix::der::PublicKeyAlgorithm::ECDSA, MissingTreeSizeSTH::kSTHHex,
147 Result::ERROR_BAD_DER, 0, 0, nullptr},
148 {MissingRootHashSTH::kSPKIHex, pkix::DigestAlgorithm::sha256,
149 pkix::der::PublicKeyAlgorithm::ECDSA, MissingRootHashSTH::kSTHHex,
150 Result::ERROR_BAD_DER, 0, 0, nullptr},
151 {MissingExtensionsSTH::kSPKIHex, pkix::DigestAlgorithm::sha256,
152 pkix::der::PublicKeyAlgorithm::ECDSA, MissingExtensionsSTH::kSTHHex,
153 Result::ERROR_BAD_DER, 0, 0, nullptr},
154 {TruncatedLogIDSTH::kSPKIHex, pkix::DigestAlgorithm::sha256,
155 pkix::der::PublicKeyAlgorithm::ECDSA, TruncatedLogIDSTH::kSTHHex,
156 Result::ERROR_BAD_DER, 0, 0, nullptr},
157 {TruncatedTimestampSTH::kSPKIHex, pkix::DigestAlgorithm::sha256,
158 pkix::der::PublicKeyAlgorithm::ECDSA, TruncatedTimestampSTH::kSTHHex,
159 Result::ERROR_BAD_DER, 0, 0, nullptr},
160 {TruncatedTreeSizeSTH::kSPKIHex, pkix::DigestAlgorithm::sha256,
161 pkix::der::PublicKeyAlgorithm::ECDSA, TruncatedTreeSizeSTH::kSTHHex,
162 Result::ERROR_BAD_DER, 0, 0, nullptr},
163 {TruncatedRootHashSTH::kSPKIHex, pkix::DigestAlgorithm::sha256,
164 pkix::der::PublicKeyAlgorithm::ECDSA, TruncatedRootHashSTH::kSTHHex,
165 Result::ERROR_BAD_DER, 0, 0, nullptr},
166 {TruncatedExtensionSTH::kSPKIHex, pkix::DigestAlgorithm::sha256,
167 pkix::der::PublicKeyAlgorithm::ECDSA, TruncatedExtensionSTH::kSTHHex,
168 Result::ERROR_BAD_DER, 0, 0, nullptr},
169 {RSASignerRSASPKISTH::kSPKIHex, pkix::DigestAlgorithm::sha256,
170 pkix::der::PublicKeyAlgorithm::ECDSA, RSASignerRSASPKISTH::kSTHHex,
171 Result::ERROR_BAD_SIGNATURE, 0, 0, nullptr},
172 {RSASignerECSPKISTH::kSPKIHex, pkix::DigestAlgorithm::sha256,
173 pkix::der::PublicKeyAlgorithm::ECDSA, RSASignerECSPKISTH::kSTHHex,
174 Result::ERROR_BAD_SIGNATURE, 0, 0, nullptr},
175 {ECSignerRSASPKISTH::kSPKIHex, pkix::DigestAlgorithm::sha256,
176 pkix::der::PublicKeyAlgorithm::ECDSA, ECSignerRSASPKISTH::kSTHHex,
177 Result::ERROR_INVALID_KEY, 0, 0, nullptr},
180 TEST_P(BTSignedTreeHeadTest, BTSignedTreeHeadSimpleTest) {
181 const BTSignedTreeHeadTestParams& params(GetParam());
183 Buffer subjectPublicKeyInfoBuffer(
184 HexToBytes(params.mSubjectPublicKeyInfoHex));
185 Input subjectPublicKeyInfoInput = InputForBuffer(subjectPublicKeyInfoBuffer);
187 Buffer signedTreeHeadBuffer(HexToBytes(params.mSignedTreeHeadHex));
188 Input signedTreeHeadInput = InputForBuffer(signedTreeHeadBuffer);
190 SignedTreeHeadDataV2 sth;
191 EXPECT_EQ(params.mExpectedSignedTreeHeadResult,
192 DecodeAndVerifySignedTreeHead(
193 subjectPublicKeyInfoInput, params.mDigestAlgorithm,
194 params.mPublicKeyAlgorithm, signedTreeHeadInput, sth));
196 if (params.mExpectedSignedTreeHeadResult == Success) {
197 EXPECT_EQ(params.mExpectedTimestamp, sth.timestamp);
198 EXPECT_EQ(params.mExpectedTreeSize, sth.treeSize);
199 EXPECT_EQ(HexToBytes(params.mExpectedRootHashHex), sth.rootHash);
203 INSTANTIATE_TEST_SUITE_P(BTSignedTreeHeadTest, BTSignedTreeHeadTest,
204 testing::ValuesIn(BT_SIGNED_TREE_HEAD_TEST_PARAMS));
206 TEST_F(BTSignedTreeHeadTest, BTSignedTreeHeadTamperedSignatureTest) {
207 Buffer subjectPublicKeyInfoBuffer(HexToBytes(ValidSTH::kSPKIHex));
208 Input subjectPublicKeyInfoInput = InputForBuffer(subjectPublicKeyInfoBuffer);
210 Buffer signedTreeHeadBuffer(HexToBytes(ValidSTH::kSTHHex));
211 ASSERT_TRUE(signedTreeHeadBuffer.size() > 15);
212 signedTreeHeadBuffer[signedTreeHeadBuffer.size() - 15] ^= 0xff;
213 Input signedTreeHeadInput = InputForBuffer(signedTreeHeadBuffer);
215 SignedTreeHeadDataV2 sth;
216 EXPECT_EQ(Result::ERROR_BAD_SIGNATURE,
217 DecodeAndVerifySignedTreeHead(subjectPublicKeyInfoInput,
218 pkix::DigestAlgorithm::sha256,
219 pkix::der::PublicKeyAlgorithm::ECDSA,
220 signedTreeHeadInput, sth));
223 TEST_F(BTSignedTreeHeadTest, BTSignedTreeHeadTruncatedSignatureTest) {
224 Buffer subjectPublicKeyInfoBuffer(HexToBytes(ValidSTH::kSPKIHex));
225 Input subjectPublicKeyInfoInput = InputForBuffer(subjectPublicKeyInfoBuffer);
227 Buffer signedTreeHeadBuffer(HexToBytes(ValidSTH::kSTHHex));
228 ASSERT_TRUE(signedTreeHeadBuffer.size() > 17);
229 signedTreeHeadBuffer.resize(signedTreeHeadBuffer.size() - 17);
230 Input signedTreeHeadInput = InputForBuffer(signedTreeHeadBuffer);
232 SignedTreeHeadDataV2 sth;
233 EXPECT_EQ(Result::ERROR_BAD_DER,
234 DecodeAndVerifySignedTreeHead(subjectPublicKeyInfoInput,
235 pkix::DigestAlgorithm::sha256,
236 pkix::der::PublicKeyAlgorithm::ECDSA,
237 signedTreeHeadInput, sth));
240 TEST_F(BTSignedTreeHeadTest, BTSignedTreeHeadMissingSignatureTest) {
241 Buffer subjectPublicKeyInfoBuffer(HexToBytes(ValidSTH::kSPKIHex));
242 Input subjectPublicKeyInfoInput = InputForBuffer(subjectPublicKeyInfoBuffer);
244 Buffer signedTreeHeadBuffer = {
245 0x02, 0x00, 0x00,
246 // 1541189938000 milliseconds since the epoch
247 0x00, 0x00, 0x01, 0x66, 0xd6, 0x14, 0x2b, 0x50, 0x00, 0x00, 0x00, 0x00,
248 0x00, 0x00, 0x00, 0x07, // 7 total nodes
249 0x20, // 32 byte hash
250 0xd1, 0xa0, 0xd3, 0x94, 0x7d, 0xb4, 0xae, 0x83, 0x05, 0xf2, 0xac, 0x32,
251 0x98, 0x59, 0x57, 0xe0, 0x26, 0x59, 0xb2, 0xea, 0x3c, 0x10, 0xda, 0x52,
252 0xa4, 0x8d, 0x25, 0x26, 0xe9, 0xaf, 0x3b, 0xbc, 0x00,
253 0x00, // no extensions
254 // missing signature
256 Input signedTreeHeadInput = InputForBuffer(signedTreeHeadBuffer);
258 SignedTreeHeadDataV2 sth;
259 EXPECT_EQ(Result::ERROR_BAD_DER,
260 DecodeAndVerifySignedTreeHead(subjectPublicKeyInfoInput,
261 pkix::DigestAlgorithm::sha256,
262 pkix::der::PublicKeyAlgorithm::ECDSA,
263 signedTreeHeadInput, sth));
266 } // namespace ct
267 } // namespace mozilla