/src/mozilla-central/security/certverifier/tests/gtest/CTLogVerifierTest.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 "CTLogVerifier.h" |
8 | | #include "CTTestUtils.h" |
9 | | #include "nss.h" |
10 | | |
11 | | #include "gtest/gtest.h" |
12 | | |
13 | | namespace mozilla { namespace ct { |
14 | | |
15 | | using namespace pkix; |
16 | | |
17 | | class CTLogVerifierTest : public ::testing::Test |
18 | | { |
19 | | public: |
20 | | void SetUp() override |
21 | 0 | { |
22 | 0 | // Does nothing if NSS is already initialized. |
23 | 0 | MOZ_RELEASE_ASSERT(NSS_NoDB_Init(nullptr) == SECSuccess); |
24 | 0 |
|
25 | 0 | ASSERT_EQ(Success, mLog.Init(InputForBuffer(GetTestPublicKey()), |
26 | 0 | -1 /*operator id*/, |
27 | 0 | CTLogStatus::Included, |
28 | 0 | 0 /*disqualification time*/)); |
29 | 0 | ASSERT_EQ(GetTestPublicKeyId(), mLog.keyId()); |
30 | 0 | } |
31 | | |
32 | | protected: |
33 | | CTLogVerifier mLog; |
34 | | }; |
35 | | |
36 | | TEST_F(CTLogVerifierTest, VerifiesCertSCT) |
37 | 0 | { |
38 | 0 | LogEntry certEntry; |
39 | 0 | GetX509CertLogEntry(certEntry); |
40 | 0 |
|
41 | 0 | SignedCertificateTimestamp certSct; |
42 | 0 | GetX509CertSCT(certSct); |
43 | 0 |
|
44 | 0 | EXPECT_EQ(Success, mLog.Verify(certEntry, certSct)); |
45 | 0 | } |
46 | | |
47 | | TEST_F(CTLogVerifierTest, VerifiesPrecertSCT) |
48 | 0 | { |
49 | 0 | LogEntry precertEntry; |
50 | 0 | GetPrecertLogEntry(precertEntry); |
51 | 0 |
|
52 | 0 | SignedCertificateTimestamp precertSct; |
53 | 0 | GetPrecertSCT(precertSct); |
54 | 0 |
|
55 | 0 | EXPECT_EQ(Success, mLog.Verify(precertEntry, precertSct)); |
56 | 0 | } |
57 | | |
58 | | TEST_F(CTLogVerifierTest, FailsInvalidTimestamp) |
59 | 0 | { |
60 | 0 | LogEntry certEntry; |
61 | 0 | GetX509CertLogEntry(certEntry); |
62 | 0 |
|
63 | 0 | SignedCertificateTimestamp certSct; |
64 | 0 | GetX509CertSCT(certSct); |
65 | 0 |
|
66 | 0 | // Mangle the timestamp, so that it should fail signature validation. |
67 | 0 | certSct.timestamp = 0; |
68 | 0 |
|
69 | 0 | EXPECT_EQ(pkix::Result::ERROR_BAD_SIGNATURE, mLog.Verify(certEntry, certSct)); |
70 | 0 | } |
71 | | |
72 | | TEST_F(CTLogVerifierTest, FailsInvalidSignature) |
73 | 0 | { |
74 | 0 | LogEntry certEntry; |
75 | 0 | GetX509CertLogEntry(certEntry); |
76 | 0 |
|
77 | 0 | // Mangle the value of the signature, making the underlying signature |
78 | 0 | // verification code return ERROR_BAD_SIGNATURE. |
79 | 0 | SignedCertificateTimestamp certSct; |
80 | 0 | GetX509CertSCT(certSct); |
81 | 0 | certSct.signature.signatureData[20] ^= '\xFF'; |
82 | 0 | EXPECT_EQ(pkix::Result::ERROR_BAD_SIGNATURE, mLog.Verify(certEntry, certSct)); |
83 | 0 |
|
84 | 0 | // Mangle the encoding of the signature, making the underlying implementation |
85 | 0 | // return ERROR_BAD_DER. We still expect the verifier to return |
86 | 0 | // ERROR_BAD_SIGNATURE. |
87 | 0 | SignedCertificateTimestamp certSct2; |
88 | 0 | GetX509CertSCT(certSct2); |
89 | 0 | certSct2.signature.signatureData[0] ^= '\xFF'; |
90 | 0 | EXPECT_EQ(pkix::Result::ERROR_BAD_SIGNATURE, mLog.Verify(certEntry, |
91 | 0 | certSct2)); |
92 | 0 | } |
93 | | |
94 | | TEST_F(CTLogVerifierTest, FailsInvalidLogID) |
95 | 0 | { |
96 | 0 | LogEntry certEntry; |
97 | 0 | GetX509CertLogEntry(certEntry); |
98 | 0 |
|
99 | 0 | SignedCertificateTimestamp certSct; |
100 | 0 | GetX509CertSCT(certSct); |
101 | 0 |
|
102 | 0 | // Mangle the log ID, which should cause it to match a different log before |
103 | 0 | // attempting signature validation. |
104 | 0 | MOZ_RELEASE_ASSERT(certSct.logId.append('\x0')); |
105 | 0 |
|
106 | 0 | EXPECT_EQ(pkix::Result::FATAL_ERROR_INVALID_ARGS, mLog.Verify(certEntry, |
107 | 0 | certSct)); |
108 | 0 | } |
109 | | |
110 | | TEST_F(CTLogVerifierTest, VerifiesValidSTH) |
111 | 0 | { |
112 | 0 | SignedTreeHead sth; |
113 | 0 | GetSampleSignedTreeHead(sth); |
114 | 0 | EXPECT_EQ(Success, mLog.VerifySignedTreeHead(sth)); |
115 | 0 | } |
116 | | |
117 | | TEST_F(CTLogVerifierTest, DoesNotVerifyInvalidSTH) |
118 | 0 | { |
119 | 0 | SignedTreeHead sth; |
120 | 0 | GetSampleSignedTreeHead(sth); |
121 | 0 | sth.sha256RootHash[0] ^= '\xFF'; |
122 | 0 | EXPECT_EQ(pkix::Result::ERROR_BAD_SIGNATURE, mLog.VerifySignedTreeHead(sth)); |
123 | 0 | } |
124 | | |
125 | | // Test that excess data after the public key is rejected. |
126 | | TEST_F(CTLogVerifierTest, ExcessDataInPublicKey) |
127 | 0 | { |
128 | 0 | Buffer key = GetTestPublicKey(); |
129 | 0 | MOZ_RELEASE_ASSERT(key.append("extra", 5)); |
130 | 0 |
|
131 | 0 | CTLogVerifier log; |
132 | 0 | EXPECT_NE(Success, log.Init(InputForBuffer(key), |
133 | 0 | -1 /*operator id*/, |
134 | 0 | CTLogStatus::Included, |
135 | 0 | 0 /*disqualification time*/)); |
136 | 0 | } |
137 | | |
138 | | } } // namespace mozilla::ct |