OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "net/cert/single_log_ct_verifier.h" |
| 6 |
| 7 #include "net/base/net_errors.h" |
| 8 #include "net/base/net_log.h" |
| 9 #include "net/cert/ct_log_verifier.h" |
| 10 #include "net/cert/ct_objects_extractor.h" |
| 11 #include "net/cert/ct_serialization.h" |
| 12 #include "net/cert/ct_verify_result.h" |
| 13 #include "net/cert/signed_certificate_timestamp.h" |
| 14 #include "net/cert/x509_certificate.h" |
| 15 |
| 16 namespace net { |
| 17 |
| 18 SingleLogCTVerifier::SingleLogCTVerifier( |
| 19 scoped_ptr<CTLogVerifier> log_verifier) |
| 20 : log_(log_verifier.Pass()) { |
| 21 } |
| 22 |
| 23 SingleLogCTVerifier::~SingleLogCTVerifier() { |
| 24 } |
| 25 |
| 26 int SingleLogCTVerifier::Verify(X509Certificate* cert, |
| 27 X509Certificate* verified_cert, |
| 28 ct::CTVerifyResult* result, |
| 29 const CompletionCallback& callback, |
| 30 const BoundNetLog& net_log) { |
| 31 DCHECK(cert); |
| 32 DCHECK(result); |
| 33 |
| 34 std::string embedded_scts; |
| 35 ct::LogEntry embedded_log_entry; |
| 36 |
| 37 result->verified_scts.clear(); |
| 38 result->unverified_scts.clear(); |
| 39 result->unknown_logs_scts.clear(); |
| 40 |
| 41 bool has_valid_embedded_sct = |
| 42 !verified_cert->GetIntermediateCertificates().empty() && |
| 43 ct::ExtractEmbeddedSCTs(cert->os_cert_handle(), &embedded_scts) && |
| 44 ct::GetPrecertLogEntry( |
| 45 cert->os_cert_handle(), |
| 46 verified_cert->GetIntermediateCertificates().front(), |
| 47 &embedded_log_entry) && |
| 48 VerifySCTs(embedded_scts, embedded_log_entry, result); |
| 49 |
| 50 if (!has_valid_embedded_sct) { |
| 51 // XXX(rsleevi): Add some SCT error codes? |
| 52 return ERR_FAILED; |
| 53 } |
| 54 |
| 55 return OK; |
| 56 } |
| 57 |
| 58 bool SingleLogCTVerifier::VerifySCTs(const std::string& encoded_sct_list, |
| 59 const ct::LogEntry& expected_entry, |
| 60 ct::CTVerifyResult* result) { |
| 61 if (!log_) |
| 62 return false; |
| 63 |
| 64 base::StringPiece temp(encoded_sct_list); |
| 65 std::vector<base::StringPiece> sct_list; |
| 66 |
| 67 if (!ct::DecodeSCTList(&temp, &sct_list)) |
| 68 return false; |
| 69 |
| 70 bool verified = false; |
| 71 for (std::vector<base::StringPiece>::const_iterator it = sct_list.begin(); |
| 72 it != sct_list.end(); ++it) { |
| 73 base::StringPiece temp_sct(*it); |
| 74 ct::SignedCertificateTimestamp decoded_sct; |
| 75 if (!DecodeSignedCertificateTimestamp(&temp_sct, &decoded_sct)) { |
| 76 // XXX(rsleevi): Should we really just skip over bad SCTs? |
| 77 continue; |
| 78 } |
| 79 // Assume this SCT is untrusted until proven otherwise. |
| 80 result->unverified_scts.push_back(decoded_sct); |
| 81 |
| 82 CTLogVerifier::VerifyResult verify_result = |
| 83 log_->Verify(expected_entry, decoded_sct); |
| 84 if (verify_result == CTLogVerifier::SCT_NOT_FROM_THIS_LOG) { |
| 85 DVLOG(1) << "SCT does not match this log."; |
| 86 result->unverified_scts.pop_back(); |
| 87 result->unknown_logs_scts.push_back(decoded_sct); |
| 88 continue; |
| 89 } else if (verify_result != CTLogVerifier::SCT_VERIFIED_OK) { |
| 90 DVLOG(1) << "Unable to verify SCT signature."; |
| 91 continue; |
| 92 } |
| 93 |
| 94 if (decoded_sct.timestamp + base::TimeDelta::FromSeconds(1) > |
| 95 base::Time::Now()) { |
| 96 DVLOG(1) << "SCT is from the future!"; |
| 97 continue; |
| 98 } |
| 99 |
| 100 // Proven otherwise - remove. |
| 101 result->unverified_scts.pop_back(); |
| 102 result->verified_scts.push_back(decoded_sct); |
| 103 verified = true; |
| 104 } |
| 105 |
| 106 return verified; |
| 107 } |
| 108 |
| 109 } // namespace net |
OLD | NEW |