CTLogVerifierTest.cpp (3785B)
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 #include "signature_cache_ffi.h" 11 12 #include "gtest/gtest.h" 13 14 namespace mozilla { 15 namespace ct { 16 17 using namespace pkix; 18 19 class CTLogVerifierTest : public ::testing::Test { 20 public: 21 void SetUp() override { 22 // Does nothing if NSS is already initialized. 23 if (NSS_NoDB_Init(nullptr) != SECSuccess) { 24 abort(); 25 } 26 27 mSignatureCache = signature_cache_new(1); 28 29 ASSERT_EQ(Success, mLog.Init(InputForBuffer(GetTestPublicKey()))); 30 ASSERT_EQ(GetTestPublicKeyId(), mLog.keyId()); 31 } 32 33 void TearDown() override { signature_cache_free(mSignatureCache); } 34 35 protected: 36 CTLogVerifier mLog = 37 CTLogVerifier(-1, CTLogState::Admissible, CTLogFormat::RFC6962, 0); 38 // For some reason, the templating makes it impossible to use UniquePtr here. 39 SignatureCache* mSignatureCache; 40 }; 41 42 TEST_F(CTLogVerifierTest, VerifiesCertSCT) { 43 LogEntry certEntry; 44 GetX509CertLogEntry(certEntry); 45 46 SignedCertificateTimestamp certSct; 47 GetX509CertSCT(certSct); 48 49 EXPECT_EQ(Success, mLog.Verify(certEntry, certSct, mSignatureCache)); 50 } 51 52 TEST_F(CTLogVerifierTest, VerifiesPrecertSCT) { 53 LogEntry precertEntry; 54 GetPrecertLogEntry(precertEntry); 55 56 SignedCertificateTimestamp precertSct; 57 GetPrecertSCT(precertSct); 58 59 EXPECT_EQ(Success, mLog.Verify(precertEntry, precertSct, mSignatureCache)); 60 } 61 62 TEST_F(CTLogVerifierTest, FailsInvalidTimestamp) { 63 LogEntry certEntry; 64 GetX509CertLogEntry(certEntry); 65 66 SignedCertificateTimestamp certSct; 67 GetX509CertSCT(certSct); 68 69 // Mangle the timestamp, so that it should fail signature validation. 70 certSct.timestamp = 0; 71 72 EXPECT_EQ(pkix::Result::ERROR_BAD_SIGNATURE, 73 mLog.Verify(certEntry, certSct, mSignatureCache)); 74 } 75 76 TEST_F(CTLogVerifierTest, FailsInvalidSignature) { 77 LogEntry certEntry; 78 GetX509CertLogEntry(certEntry); 79 80 // Mangle the value of the signature, making the underlying signature 81 // verification code return ERROR_BAD_SIGNATURE. 82 SignedCertificateTimestamp certSct; 83 GetX509CertSCT(certSct); 84 certSct.signature.signatureData[20] ^= '\xFF'; 85 EXPECT_EQ(pkix::Result::ERROR_BAD_SIGNATURE, 86 mLog.Verify(certEntry, certSct, mSignatureCache)); 87 88 // Mangle the encoding of the signature, making the underlying implementation 89 // return ERROR_BAD_DER. We still expect the verifier to return 90 // ERROR_BAD_SIGNATURE. 91 SignedCertificateTimestamp certSct2; 92 GetX509CertSCT(certSct2); 93 certSct2.signature.signatureData[0] ^= '\xFF'; 94 EXPECT_EQ(pkix::Result::ERROR_BAD_SIGNATURE, 95 mLog.Verify(certEntry, certSct2, mSignatureCache)); 96 } 97 98 TEST_F(CTLogVerifierTest, FailsInvalidLogID) { 99 LogEntry certEntry; 100 GetX509CertLogEntry(certEntry); 101 102 SignedCertificateTimestamp certSct; 103 GetX509CertSCT(certSct); 104 105 // Mangle the log ID, which should cause it to match a different log before 106 // attempting signature validation. 107 certSct.logId.push_back('\x0'); 108 109 EXPECT_EQ(pkix::Result::FATAL_ERROR_INVALID_ARGS, 110 mLog.Verify(certEntry, certSct, mSignatureCache)); 111 } 112 113 // Test that excess data after the public key is rejected. 114 TEST_F(CTLogVerifierTest, ExcessDataInPublicKey) { 115 Buffer key = GetTestPublicKey(); 116 std::string extra = "extra"; 117 key.insert(key.end(), extra.begin(), extra.end()); 118 119 CTLogVerifier log(-1, CTLogState::Admissible, CTLogFormat::RFC6962, 0); 120 EXPECT_NE(Success, log.Init(InputForBuffer(key))); 121 } 122 123 } // namespace ct 124 } // namespace mozilla