| Index: net/cert/single_log_ct_verifier.cc
|
| diff --git a/net/cert/single_log_ct_verifier.cc b/net/cert/single_log_ct_verifier.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..874b7e623cea540f76cddfc6efddf90869b2e621
|
| --- /dev/null
|
| +++ b/net/cert/single_log_ct_verifier.cc
|
| @@ -0,0 +1,109 @@
|
| +// Copyright (c) 2013 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "net/cert/single_log_ct_verifier.h"
|
| +
|
| +#include "net/base/net_errors.h"
|
| +#include "net/base/net_log.h"
|
| +#include "net/cert/ct_log_verifier.h"
|
| +#include "net/cert/ct_objects_extractor.h"
|
| +#include "net/cert/ct_serialization.h"
|
| +#include "net/cert/ct_verify_result.h"
|
| +#include "net/cert/signed_certificate_timestamp.h"
|
| +#include "net/cert/x509_certificate.h"
|
| +
|
| +namespace net {
|
| +
|
| +SingleLogCTVerifier::SingleLogCTVerifier(
|
| + scoped_ptr<CTLogVerifier> log_verifier)
|
| + : log_(log_verifier.Pass()) {
|
| +}
|
| +
|
| +SingleLogCTVerifier::~SingleLogCTVerifier() {
|
| +}
|
| +
|
| +int SingleLogCTVerifier::Verify(X509Certificate* cert,
|
| + X509Certificate* verified_cert,
|
| + ct::CTVerifyResult* result,
|
| + const CompletionCallback& callback,
|
| + const BoundNetLog& net_log) {
|
| + DCHECK(cert);
|
| + DCHECK(result);
|
| +
|
| + std::string embedded_scts;
|
| + ct::LogEntry embedded_log_entry;
|
| +
|
| + result->verified_scts.clear();
|
| + result->unverified_scts.clear();
|
| + result->unknown_logs_scts.clear();
|
| +
|
| + bool has_valid_embedded_sct =
|
| + !verified_cert->GetIntermediateCertificates().empty() &&
|
| + ct::ExtractEmbeddedSCTs(cert->os_cert_handle(), &embedded_scts) &&
|
| + ct::GetPrecertLogEntry(
|
| + cert->os_cert_handle(),
|
| + verified_cert->GetIntermediateCertificates().front(),
|
| + &embedded_log_entry) &&
|
| + VerifySCTs(embedded_scts, embedded_log_entry, result);
|
| +
|
| + if (!has_valid_embedded_sct) {
|
| + // XXX(rsleevi): Add some SCT error codes?
|
| + return ERR_FAILED;
|
| + }
|
| +
|
| + return OK;
|
| +}
|
| +
|
| +bool SingleLogCTVerifier::VerifySCTs(const std::string& encoded_sct_list,
|
| + const ct::LogEntry& expected_entry,
|
| + ct::CTVerifyResult* result) {
|
| + if (!log_)
|
| + return false;
|
| +
|
| + base::StringPiece temp(encoded_sct_list);
|
| + std::vector<base::StringPiece> sct_list;
|
| +
|
| + if (!ct::DecodeSCTList(&temp, &sct_list))
|
| + return false;
|
| +
|
| + bool verified = false;
|
| + for (std::vector<base::StringPiece>::const_iterator it = sct_list.begin();
|
| + it != sct_list.end(); ++it) {
|
| + base::StringPiece temp_sct(*it);
|
| + ct::SignedCertificateTimestamp decoded_sct;
|
| + if (!DecodeSignedCertificateTimestamp(&temp_sct, &decoded_sct)) {
|
| + // XXX(rsleevi): Should we really just skip over bad SCTs?
|
| + continue;
|
| + }
|
| + // Assume this SCT is untrusted until proven otherwise.
|
| + result->unverified_scts.push_back(decoded_sct);
|
| +
|
| + CTLogVerifier::VerifyResult verify_result =
|
| + log_->Verify(expected_entry, decoded_sct);
|
| + if (verify_result == CTLogVerifier::SCT_NOT_FROM_THIS_LOG) {
|
| + DVLOG(1) << "SCT does not match this log.";
|
| + result->unverified_scts.pop_back();
|
| + result->unknown_logs_scts.push_back(decoded_sct);
|
| + continue;
|
| + } else if (verify_result != CTLogVerifier::SCT_VERIFIED_OK) {
|
| + DVLOG(1) << "Unable to verify SCT signature.";
|
| + continue;
|
| + }
|
| +
|
| + if (decoded_sct.timestamp + base::TimeDelta::FromSeconds(1) >
|
| + base::Time::Now()) {
|
| + DVLOG(1) << "SCT is from the future!";
|
| + continue;
|
| + }
|
| +
|
| + // Proven otherwise - remove.
|
| + result->unverified_scts.pop_back();
|
| + result->verified_scts.push_back(decoded_sct);
|
| + verified = true;
|
| + }
|
| +
|
| + return verified;
|
| +}
|
| +
|
| +} // namespace net
|
|
|