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"
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
) {
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
= {
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
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
));
267 } // namespace mozilla