MultiLogCTVerifierTest.cpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #include "MultiLogCTVerifier.h"
  6. #include <stdint.h>
  7. #include "CTLogVerifier.h"
  8. #include "CTObjectsExtractor.h"
  9. #include "CTSerialization.h"
  10. #include "CTTestUtils.h"
  11. #include "gtest/gtest.h"
  12. #include "mozilla/EnumSet.h"
  13. #include "mozilla/Move.h"
  14. #include "nss.h"
  15. namespace mozilla { namespace ct {
  16. using namespace mozilla::pkix;
  17. class MultiLogCTVerifierTest : public ::testing::Test
  18. {
  19. public:
  20. MultiLogCTVerifierTest()
  21. : mNow(Time::uninitialized)
  22. {}
  23. void SetUp() override
  24. {
  25. // Does nothing if NSS is already initialized.
  26. MOZ_RELEASE_ASSERT(NSS_NoDB_Init(nullptr) == SECSuccess);
  27. ASSERT_EQ(Success, mVerifier.AddLog(InputForBuffer(GetTestPublicKey())));
  28. mTestCert = GetDEREncodedX509Cert();
  29. mEmbeddedCert = GetDEREncodedTestEmbeddedCert();
  30. mCaCert = GetDEREncodedCACert();
  31. mCaCertSPKI = ExtractCertSPKI(mCaCert);
  32. mIntermediateCert = GetDEREncodedIntermediateCert();
  33. mIntermediateCertSPKI = ExtractCertSPKI(mIntermediateCert);
  34. // Set the current time making sure all test timestamps are in the past.
  35. mNow = TimeFromEpochInSeconds(1451606400u); // Date.parse("2016-01-01")/1000
  36. }
  37. void CheckForSingleVerifiedSCTInResult(const CTVerifyResult& result,
  38. SignedCertificateTimestamp::Origin origin)
  39. {
  40. EXPECT_EQ(0U, result.decodingErrors);
  41. ASSERT_EQ(1U, result.scts.length());
  42. EXPECT_EQ(SignedCertificateTimestamp::VerificationStatus::OK,
  43. result.scts[0].verificationStatus);
  44. EXPECT_EQ(origin, result.scts[0].origin);
  45. }
  46. // Writes an SCTList containing a single |sct| into |output|.
  47. void EncodeSCTListForTesting(Input sct, Buffer& output)
  48. {
  49. Vector<Input> list;
  50. ASSERT_TRUE(list.append(Move(sct)));
  51. ASSERT_EQ(Success, EncodeSCTList(list, output));
  52. }
  53. void GetSCTListWithInvalidLogID(Buffer& result)
  54. {
  55. result.clear();
  56. Buffer sct(GetTestSignedCertificateTimestamp());
  57. // Change a byte inside the Log ID part of the SCT so it does
  58. // not match the log used in the tests.
  59. sct[15] ^= '\xFF';
  60. EncodeSCTListForTesting(InputForBuffer(sct), result);
  61. }
  62. void CheckPrecertVerification(const Buffer& cert, const Buffer& issuerSPKI)
  63. {
  64. Buffer sctList;
  65. ExtractEmbeddedSCTList(cert, sctList);
  66. ASSERT_FALSE(sctList.empty());
  67. CTVerifyResult result;
  68. ASSERT_EQ(Success,
  69. mVerifier.Verify(InputForBuffer(cert), InputForBuffer(issuerSPKI),
  70. InputForBuffer(sctList), Input(), Input(),
  71. mNow, result));
  72. CheckForSingleVerifiedSCTInResult(result,
  73. SignedCertificateTimestamp::Origin::Embedded);
  74. }
  75. protected:
  76. MultiLogCTVerifier mVerifier;
  77. Buffer mTestCert;
  78. Buffer mEmbeddedCert;
  79. Buffer mCaCert;
  80. Buffer mCaCertSPKI;
  81. Buffer mIntermediateCert;
  82. Buffer mIntermediateCertSPKI;
  83. Time mNow;
  84. };
  85. // Test that an embedded SCT can be extracted and the extracted SCT contains
  86. // the expected data. This tests the ExtractEmbeddedSCTList function from
  87. // CTTestUtils.h that other tests here rely upon.
  88. TEST_F(MultiLogCTVerifierTest, ExtractEmbeddedSCT)
  89. {
  90. SignedCertificateTimestamp sct;
  91. // Extract the embedded SCT.
  92. Buffer sctList;
  93. ExtractEmbeddedSCTList(mEmbeddedCert, sctList);
  94. ASSERT_FALSE(sctList.empty());
  95. Reader sctReader;
  96. ASSERT_EQ(Success, DecodeSCTList(InputForBuffer(sctList), sctReader));
  97. Input sctItemInput;
  98. ASSERT_EQ(Success, ReadSCTListItem(sctReader, sctItemInput));
  99. EXPECT_TRUE(sctReader.AtEnd()); // we only expect one sct in the list
  100. Reader sctItemReader(sctItemInput);
  101. ASSERT_EQ(Success, DecodeSignedCertificateTimestamp(sctItemReader, sct));
  102. // Make sure the SCT contains the expected data.
  103. EXPECT_EQ(SignedCertificateTimestamp::Version::V1, sct.version);
  104. EXPECT_EQ(GetTestPublicKeyId(), sct.logId);
  105. uint64_t expectedTimestamp = 1365181456275;
  106. EXPECT_EQ(expectedTimestamp, sct.timestamp);
  107. }
  108. TEST_F(MultiLogCTVerifierTest, VerifiesEmbeddedSCT)
  109. {
  110. CheckPrecertVerification(mEmbeddedCert, mCaCertSPKI);
  111. }
  112. TEST_F(MultiLogCTVerifierTest, VerifiesEmbeddedSCTWithPreCA)
  113. {
  114. CheckPrecertVerification(GetDEREncodedTestEmbeddedWithPreCACert(),
  115. mCaCertSPKI);
  116. }
  117. TEST_F(MultiLogCTVerifierTest, VerifiesEmbeddedSCTWithIntermediate)
  118. {
  119. CheckPrecertVerification(GetDEREncodedTestEmbeddedWithIntermediateCert(),
  120. mIntermediateCertSPKI);
  121. }
  122. TEST_F(MultiLogCTVerifierTest, VerifiesEmbeddedSCTWithIntermediateAndPreCA)
  123. {
  124. CheckPrecertVerification(GetDEREncodedTestEmbeddedWithIntermediatePreCACert(),
  125. mIntermediateCertSPKI);
  126. }
  127. TEST_F(MultiLogCTVerifierTest, VerifiesSCTFromOCSP)
  128. {
  129. Buffer sct(GetTestSignedCertificateTimestamp());
  130. Buffer sctList;
  131. EncodeSCTListForTesting(InputForBuffer(sct), sctList);
  132. CTVerifyResult result;
  133. ASSERT_EQ(Success,
  134. mVerifier.Verify(InputForBuffer(mTestCert), Input(),
  135. Input(), InputForBuffer(sctList), Input(),
  136. mNow, result));
  137. CheckForSingleVerifiedSCTInResult(result,
  138. SignedCertificateTimestamp::Origin::OCSPResponse);
  139. }
  140. TEST_F(MultiLogCTVerifierTest, VerifiesSCTFromTLS)
  141. {
  142. Buffer sct(GetTestSignedCertificateTimestamp());
  143. Buffer sctList;
  144. EncodeSCTListForTesting(InputForBuffer(sct), sctList);
  145. CTVerifyResult result;
  146. ASSERT_EQ(Success,
  147. mVerifier.Verify(InputForBuffer(mTestCert), Input(),
  148. Input(), Input(), InputForBuffer(sctList),
  149. mNow, result));
  150. CheckForSingleVerifiedSCTInResult(result,
  151. SignedCertificateTimestamp::Origin::TLSExtension);
  152. }
  153. TEST_F(MultiLogCTVerifierTest, VerifiesSCTFromMultipleSources)
  154. {
  155. Buffer sct(GetTestSignedCertificateTimestamp());
  156. Buffer sctList;
  157. EncodeSCTListForTesting(InputForBuffer(sct), sctList);
  158. CTVerifyResult result;
  159. ASSERT_EQ(Success,
  160. mVerifier.Verify(InputForBuffer(mTestCert), Input(), Input(),
  161. InputForBuffer(sctList), InputForBuffer(sctList),
  162. mNow, result));
  163. // The result should contain verified SCTs from TLS and OCSP origins.
  164. EnumSet<SignedCertificateTimestamp::Origin> origins;
  165. for (const SignedCertificateTimestamp& sct : result.scts) {
  166. EXPECT_EQ(SignedCertificateTimestamp::VerificationStatus::OK,
  167. sct.verificationStatus);
  168. origins += sct.origin;
  169. }
  170. EXPECT_FALSE(
  171. origins.contains(SignedCertificateTimestamp::Origin::Embedded));
  172. EXPECT_TRUE(
  173. origins.contains(SignedCertificateTimestamp::Origin::OCSPResponse));
  174. EXPECT_TRUE(
  175. origins.contains(SignedCertificateTimestamp::Origin::TLSExtension));
  176. }
  177. TEST_F(MultiLogCTVerifierTest, IdentifiesSCTFromUnknownLog)
  178. {
  179. Buffer sctList;
  180. GetSCTListWithInvalidLogID(sctList);
  181. CTVerifyResult result;
  182. ASSERT_EQ(Success,
  183. mVerifier.Verify(InputForBuffer(mTestCert), Input(),
  184. Input(), Input(), InputForBuffer(sctList),
  185. mNow, result));
  186. EXPECT_EQ(0U, result.decodingErrors);
  187. ASSERT_EQ(1U, result.scts.length());
  188. EXPECT_EQ(SignedCertificateTimestamp::VerificationStatus::UnknownLog,
  189. result.scts[0].verificationStatus);
  190. }
  191. } } // namespace mozilla::ct