Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/security/certverifier/tests/gtest/MultiLogCTVerifierTest.cpp
Line
Count
Source (jump to first uncovered line)
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 "MultiLogCTVerifier.h"
8
9
#include <stdint.h>
10
11
#include "CTLogVerifier.h"
12
#include "CTObjectsExtractor.h"
13
#include "CTSerialization.h"
14
#include "CTTestUtils.h"
15
#include "gtest/gtest.h"
16
#include "mozilla/EnumSet.h"
17
#include "mozilla/Move.h"
18
#include "nss.h"
19
20
namespace mozilla { namespace ct {
21
22
using namespace mozilla::pkix;
23
24
class MultiLogCTVerifierTest : public ::testing::Test
25
{
26
public:
27
  MultiLogCTVerifierTest()
28
    : mNow(Time::uninitialized)
29
    , mLogOperatorID(123)
30
0
  {}
31
32
  void SetUp() override
33
0
  {
34
0
    // Does nothing if NSS is already initialized.
35
0
    MOZ_RELEASE_ASSERT(NSS_NoDB_Init(nullptr) == SECSuccess);
36
0
37
0
    CTLogVerifier log;
38
0
    ASSERT_EQ(Success, log.Init(InputForBuffer(GetTestPublicKey()),
39
0
                                mLogOperatorID,
40
0
                                CTLogStatus::Included,
41
0
                                0 /*disqualification time*/));
42
0
    ASSERT_EQ(Success, mVerifier.AddLog(std::move(log)));
43
0
44
0
    mTestCert = GetDEREncodedX509Cert();
45
0
    mEmbeddedCert = GetDEREncodedTestEmbeddedCert();
46
0
    mCaCert = GetDEREncodedCACert();
47
0
    mCaCertSPKI = ExtractCertSPKI(mCaCert);
48
0
    mIntermediateCert = GetDEREncodedIntermediateCert();
49
0
    mIntermediateCertSPKI = ExtractCertSPKI(mIntermediateCert);
50
0
51
0
    // Set the current time making sure all test timestamps are in the past.
52
0
    mNow = TimeFromEpochInSeconds(1451606400u); // Date.parse("2016-01-01")/1000
53
0
  }
54
55
  void CheckForSingleValidSCTInResult(const CTVerifyResult& result,
56
                                      VerifiedSCT::Origin origin)
57
0
  {
58
0
    EXPECT_EQ(0U, result.decodingErrors);
59
0
    ASSERT_EQ(1U, result.verifiedScts.length());
60
0
    EXPECT_EQ(VerifiedSCT::Status::Valid, result.verifiedScts[0].status);
61
0
    EXPECT_EQ(origin, result.verifiedScts[0].origin);
62
0
    EXPECT_EQ(mLogOperatorID, result.verifiedScts[0].logOperatorId);
63
0
  }
64
65
  // Writes an SCTList containing a single |sct| into |output|.
66
  void EncodeSCTListForTesting(Input sct, Buffer& output)
67
0
  {
68
0
    Vector<Input> list;
69
0
    ASSERT_TRUE(list.append(std::move(sct)));
70
0
    ASSERT_EQ(Success, EncodeSCTList(list, output));
71
0
  }
72
73
  void GetSCTListWithInvalidLogID(Buffer& result)
74
0
  {
75
0
    result.clear();
76
0
    Buffer sct(GetTestSignedCertificateTimestamp());
77
0
    // Change a byte inside the Log ID part of the SCT so it does
78
0
    // not match the log used in the tests.
79
0
    sct[15] ^= '\xFF';
80
0
    EncodeSCTListForTesting(InputForBuffer(sct), result);
81
0
  }
82
83
  void CheckPrecertVerification(const Buffer& cert, const Buffer& issuerSPKI)
84
0
  {
85
0
    Buffer sctList;
86
0
    ExtractEmbeddedSCTList(cert, sctList);
87
0
    ASSERT_FALSE(sctList.empty());
88
0
89
0
    CTVerifyResult result;
90
0
    ASSERT_EQ(Success,
91
0
              mVerifier.Verify(InputForBuffer(cert), InputForBuffer(issuerSPKI),
92
0
                               InputForBuffer(sctList), Input(), Input(),
93
0
                               mNow, result));
94
0
    CheckForSingleValidSCTInResult(result, VerifiedSCT::Origin::Embedded);
95
0
  }
96
97
protected:
98
  MultiLogCTVerifier mVerifier;
99
  Buffer mTestCert;
100
  Buffer mEmbeddedCert;
101
  Buffer mCaCert;
102
  Buffer mCaCertSPKI;
103
  Buffer mIntermediateCert;
104
  Buffer mIntermediateCertSPKI;
105
  Time mNow;
106
  CTLogOperatorId mLogOperatorID;
107
};
108
109
// Test that an embedded SCT can be extracted and the extracted SCT contains
110
// the expected data. This tests the ExtractEmbeddedSCTList function from
111
// CTTestUtils.h that other tests here rely upon.
112
TEST_F(MultiLogCTVerifierTest, ExtractEmbeddedSCT)
113
0
{
114
0
  SignedCertificateTimestamp sct;
115
0
116
0
  // Extract the embedded SCT.
117
0
118
0
  Buffer sctList;
119
0
  ExtractEmbeddedSCTList(mEmbeddedCert, sctList);
120
0
  ASSERT_FALSE(sctList.empty());
121
0
122
0
  Reader sctReader;
123
0
  ASSERT_EQ(Success, DecodeSCTList(InputForBuffer(sctList), sctReader));
124
0
  Input sctItemInput;
125
0
  ASSERT_EQ(Success, ReadSCTListItem(sctReader, sctItemInput));
126
0
  EXPECT_TRUE(sctReader.AtEnd()); // we only expect one sct in the list
127
0
128
0
  Reader sctItemReader(sctItemInput);
129
0
  ASSERT_EQ(Success, DecodeSignedCertificateTimestamp(sctItemReader, sct));
130
0
131
0
  // Make sure the SCT contains the expected data.
132
0
133
0
  EXPECT_EQ(SignedCertificateTimestamp::Version::V1, sct.version);
134
0
  EXPECT_EQ(GetTestPublicKeyId(), sct.logId);
135
0
136
0
  uint64_t expectedTimestamp = 1365181456275;
137
0
  EXPECT_EQ(expectedTimestamp, sct.timestamp);
138
0
}
139
140
TEST_F(MultiLogCTVerifierTest, VerifiesEmbeddedSCT)
141
0
{
142
0
  CheckPrecertVerification(mEmbeddedCert, mCaCertSPKI);
143
0
}
144
145
TEST_F(MultiLogCTVerifierTest, VerifiesEmbeddedSCTWithPreCA)
146
0
{
147
0
  CheckPrecertVerification(GetDEREncodedTestEmbeddedWithPreCACert(),
148
0
                           mCaCertSPKI);
149
0
}
150
151
TEST_F(MultiLogCTVerifierTest, VerifiesEmbeddedSCTWithIntermediate)
152
0
{
153
0
  CheckPrecertVerification(GetDEREncodedTestEmbeddedWithIntermediateCert(),
154
0
                           mIntermediateCertSPKI);
155
0
}
156
157
TEST_F(MultiLogCTVerifierTest, VerifiesEmbeddedSCTWithIntermediateAndPreCA)
158
0
{
159
0
  CheckPrecertVerification(GetDEREncodedTestEmbeddedWithIntermediatePreCACert(),
160
0
                           mIntermediateCertSPKI);
161
0
}
162
163
TEST_F(MultiLogCTVerifierTest, VerifiesSCTFromOCSP)
164
0
{
165
0
  Buffer sct(GetTestSignedCertificateTimestamp());
166
0
  Buffer sctList;
167
0
  EncodeSCTListForTesting(InputForBuffer(sct), sctList);
168
0
169
0
  CTVerifyResult result;
170
0
  ASSERT_EQ(Success,
171
0
            mVerifier.Verify(InputForBuffer(mTestCert), Input(),
172
0
                             Input(), InputForBuffer(sctList), Input(),
173
0
                             mNow, result));
174
0
175
0
  CheckForSingleValidSCTInResult(result, VerifiedSCT::Origin::OCSPResponse);
176
0
}
177
178
TEST_F(MultiLogCTVerifierTest, VerifiesSCTFromTLS)
179
0
{
180
0
  Buffer sct(GetTestSignedCertificateTimestamp());
181
0
  Buffer sctList;
182
0
  EncodeSCTListForTesting(InputForBuffer(sct), sctList);
183
0
184
0
  CTVerifyResult result;
185
0
  ASSERT_EQ(Success,
186
0
            mVerifier.Verify(InputForBuffer(mTestCert), Input(),
187
0
                             Input(), Input(), InputForBuffer(sctList),
188
0
                             mNow, result));
189
0
190
0
  CheckForSingleValidSCTInResult(result, VerifiedSCT::Origin::TLSExtension);
191
0
}
192
193
TEST_F(MultiLogCTVerifierTest, VerifiesSCTFromMultipleSources)
194
0
{
195
0
  Buffer sct(GetTestSignedCertificateTimestamp());
196
0
  Buffer sctList;
197
0
  EncodeSCTListForTesting(InputForBuffer(sct), sctList);
198
0
199
0
  CTVerifyResult result;
200
0
  ASSERT_EQ(Success,
201
0
            mVerifier.Verify(InputForBuffer(mTestCert), Input(), Input(),
202
0
                             InputForBuffer(sctList), InputForBuffer(sctList),
203
0
                             mNow, result));
204
0
205
0
  // The result should contain verified SCTs from TLS and OCSP origins.
206
0
  EnumSet<VerifiedSCT::Origin> origins;
207
0
  for (const VerifiedSCT& verifiedSct : result.verifiedScts) {
208
0
    EXPECT_EQ(VerifiedSCT::Status::Valid, verifiedSct.status);
209
0
    origins += verifiedSct.origin;
210
0
  }
211
0
  EXPECT_FALSE(origins.contains(VerifiedSCT::Origin::Embedded));
212
0
  EXPECT_TRUE(origins.contains(VerifiedSCT::Origin::OCSPResponse));
213
0
  EXPECT_TRUE(origins.contains(VerifiedSCT::Origin::TLSExtension));
214
0
}
215
216
TEST_F(MultiLogCTVerifierTest, IdentifiesSCTFromUnknownLog)
217
0
{
218
0
  Buffer sctList;
219
0
  GetSCTListWithInvalidLogID(sctList);
220
0
221
0
  CTVerifyResult result;
222
0
  ASSERT_EQ(Success,
223
0
            mVerifier.Verify(InputForBuffer(mTestCert), Input(),
224
0
                             Input(), Input(), InputForBuffer(sctList),
225
0
                             mNow, result));
226
0
227
0
  EXPECT_EQ(0U, result.decodingErrors);
228
0
  ASSERT_EQ(1U, result.verifiedScts.length());
229
0
  EXPECT_EQ(VerifiedSCT::Status::UnknownLog, result.verifiedScts[0].status);
230
0
}
231
232
TEST_F(MultiLogCTVerifierTest, IdentifiesSCTFromDisqualifiedLog)
233
0
{
234
0
  MultiLogCTVerifier verifier;
235
0
  CTLogVerifier log;
236
0
  const uint64_t disqualificationTime = 12345u;
237
0
  ASSERT_EQ(Success, log.Init(InputForBuffer(GetTestPublicKey()),
238
0
    mLogOperatorID, CTLogStatus::Disqualified, disqualificationTime));
239
0
  ASSERT_EQ(Success, verifier.AddLog(std::move(log)));
240
0
241
0
  Buffer sct(GetTestSignedCertificateTimestamp());
242
0
  Buffer sctList;
243
0
  EncodeSCTListForTesting(InputForBuffer(sct), sctList);
244
0
245
0
  CTVerifyResult result;
246
0
  ASSERT_EQ(Success,
247
0
            verifier.Verify(InputForBuffer(mTestCert), Input(),
248
0
                            Input(), Input(), InputForBuffer(sctList),
249
0
                            mNow, result));
250
0
251
0
  EXPECT_EQ(0U, result.decodingErrors);
252
0
  ASSERT_EQ(1U, result.verifiedScts.length());
253
0
  EXPECT_EQ(VerifiedSCT::Status::ValidFromDisqualifiedLog,
254
0
            result.verifiedScts[0].status);
255
0
  EXPECT_EQ(disqualificationTime,
256
0
            result.verifiedScts[0].logDisqualificationTime);
257
0
  EXPECT_EQ(mLogOperatorID, result.verifiedScts[0].logOperatorId);
258
0
}
259
260
} } // namespace mozilla::ct