Chromium Code Reviews| 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/multi_log_ct_verifier.h" | |
| 6 | |
| 7 #include "net/base/net_errors.h" | |
| 8 #include "net/cert/ct_log_verifier.h" | |
| 9 #include "net/cert/ct_objects_extractor.h" | |
| 10 #include "net/cert/ct_serialization.h" | |
| 11 #include "net/cert/ct_verify_result.h" | |
| 12 #include "net/cert/signed_certificate_timestamp.h" | |
|
wtc
2013/11/21 02:05:02
Nit: already included by the .h file.
Eran M. (Google)
2013/11/21 20:06:02
Done.
| |
| 13 #include "net/cert/x509_certificate.h" | |
| 14 | |
| 15 namespace net { | |
| 16 | |
| 17 MultiLogCTVerifier::MultiLogCTVerifier() { | |
| 18 } | |
| 19 | |
| 20 MultiLogCTVerifier::~MultiLogCTVerifier() { } | |
|
wtc
2013/11/21 02:05:02
Nit: the constructor and destructor should use the
wtc
2013/11/21 02:05:02
Nit: the constructor and destructor should use the
Eran M. (Google)
2013/11/21 20:06:02
Done.
Eran M. (Google)
2013/11/21 20:06:02
Done.
| |
| 21 | |
| 22 void MultiLogCTVerifier::AddLog(scoped_ptr<CTLogVerifier> log_verifier) { | |
| 23 std::string log_id(log_verifier->key_id()); | |
| 24 logs_[log_id] = linked_ptr<CTLogVerifier>(log_verifier.release()); | |
|
wtc
2013/11/21 02:05:02
1. Nit: you should be able to do
logs_[log_id].r
Eran M. (Google)
2013/11/21 20:06:02
1. Done
2. Will look into changing the type of th
wtc
2013/11/21 23:26:34
You can declare the |log_verifier| parameter as a
Ryan Sleevi
2013/11/21 23:37:02
Taking a scoped_ptr<CTLogVerifier> and turning it
Eran M. (Google)
2013/11/23 21:02:06
Done as Ryan suggested - only modification is I've
wtc
2013/11/25 01:48:32
I think
logs_[log_id].reset(log_verifier.relea
wtc
2013/11/25 23:01:59
Thanks for the explanation.
You wrote:
| |
| 25 } | |
| 26 | |
| 27 int MultiLogCTVerifier::Verify( | |
| 28 X509Certificate* verified_cert, | |
| 29 const std::string& sct_list_from_ocsp, | |
| 30 const std::string& sct_list_from_tls_handshake, | |
| 31 ct::CTVerifyResult* result) { | |
| 32 DCHECK(verified_cert); | |
| 33 DCHECK(result); | |
| 34 | |
| 35 result->verified_scts.clear(); | |
| 36 result->unverified_scts.clear(); | |
| 37 result->unknown_logs_scts.clear(); | |
| 38 | |
| 39 bool has_verified_scts = false; | |
| 40 | |
| 41 std::string embedded_scts; | |
| 42 if (!verified_cert->GetIntermediateCertificates().empty() && | |
| 43 ct::ExtractEmbeddedSCTList( | |
| 44 verified_cert->os_cert_handle(), | |
| 45 &embedded_scts)) { | |
|
wtc
2013/11/21 02:05:02
Nit: indent by four spaces with respect to "ct::Ex
Eran M. (Google)
2013/11/21 20:06:02
Done.
| |
| 46 ct::LogEntry embedded_log_entry; | |
|
wtc
2013/11/21 02:05:02
Nit: if the |x509_entry| variable you declare belo
Eran M. (Google)
2013/11/21 20:06:02
Done.
| |
| 47 | |
| 48 has_verified_scts = | |
| 49 ct::GetPrecertLogEntry( | |
|
wtc
2013/11/21 02:05:02
Nit: indent by four spaces.
Eran M. (Google)
2013/11/21 20:06:02
Done.
| |
| 50 verified_cert->os_cert_handle(), | |
| 51 verified_cert->GetIntermediateCertificates().front(), | |
| 52 &embedded_log_entry) && | |
| 53 VerifySCTs( | |
| 54 embedded_scts, | |
| 55 embedded_log_entry, | |
| 56 ct::SignedCertificateTimestamp::SCT_EMBEDDED, | |
| 57 result); | |
| 58 } | |
| 59 | |
| 60 ct::LogEntry x509_entry; | |
| 61 if (!ct::GetX509LogEntry(verified_cert->os_cert_handle(), &x509_entry)) { | |
| 62 return has_verified_scts ? OK : ERR_FAILED; | |
|
wtc
2013/11/21 02:05:02
IMPORTANT: use a more informative error code than
Eran M. (Google)
2013/11/21 20:06:02
Done - ended up adding another category for the va
| |
| 63 } | |
|
wtc
2013/11/21 02:05:02
Nit: omit curly braces.
Eran M. (Google)
2013/11/21 20:06:02
Done.
| |
| 64 | |
| 65 has_verified_scts |= VerifySCTs( | |
| 66 sct_list_from_ocsp, | |
| 67 x509_entry, | |
| 68 ct::SignedCertificateTimestamp::SCT_FROM_OCSP_RESPONSE, | |
| 69 result); | |
| 70 | |
| 71 has_verified_scts |= VerifySCTs( | |
| 72 sct_list_from_tls_handshake, | |
| 73 x509_entry, | |
| 74 ct::SignedCertificateTimestamp::SCT_FROM_TLS_HANDSHAKE, | |
| 75 result); | |
| 76 | |
| 77 //XXX(eranm): Add a specific error code to indicate no presence | |
| 78 // of SCTs at all. | |
| 79 return has_verified_scts ? OK : ERR_FAILED; | |
| 80 } | |
| 81 | |
| 82 bool MultiLogCTVerifier::VerifySCTs( | |
| 83 const std::string& encoded_sct_list, | |
| 84 const ct::LogEntry& expected_entry, | |
| 85 ct::SignedCertificateTimestamp::Origin origin, | |
| 86 ct::CTVerifyResult* result) { | |
| 87 if (logs_.empty()) | |
| 88 return false; | |
| 89 | |
| 90 base::StringPiece temp(encoded_sct_list); | |
| 91 std::vector<base::StringPiece> sct_list; | |
| 92 | |
| 93 if (!ct::DecodeSCTList(&temp, &sct_list)) | |
| 94 return false; | |
| 95 | |
| 96 bool verified = false; | |
| 97 for (std::vector<base::StringPiece>::const_iterator it = sct_list.begin(); | |
| 98 it != sct_list.end(); ++it) { | |
| 99 base::StringPiece encoded_sct(*it); | |
| 100 ct::SignedCertificateTimestamp decoded_sct; | |
| 101 if (!DecodeSignedCertificateTimestamp(&encoded_sct, &decoded_sct)) { | |
| 102 // XXX(rsleevi): Should we really just skip over bad SCTs? | |
| 103 continue; | |
| 104 } | |
| 105 decoded_sct.origin = origin; | |
| 106 | |
| 107 verified |= VerifySingleSCT(decoded_sct, expected_entry, result); | |
| 108 } | |
| 109 | |
| 110 return verified; | |
| 111 } | |
| 112 | |
| 113 bool MultiLogCTVerifier::VerifySingleSCT( | |
| 114 const ct::SignedCertificateTimestamp& sct, | |
| 115 const ct::LogEntry& expected_entry, | |
| 116 ct::CTVerifyResult* result) { | |
| 117 | |
| 118 // Assume this SCT is untrusted until proven otherwise. | |
| 119 result->unverified_scts.push_back(sct); | |
|
wtc
2013/11/21 02:05:02
Nit: it seems clearer to just push |sct| to the ap
Eran M. (Google)
2013/11/21 20:06:02
Done - that was my attempt at defensive programmin
| |
| 120 | |
| 121 IDToLogMap::iterator it = logs_.find(sct.log_id); | |
| 122 if (it == logs_.end()) { | |
| 123 DVLOG(1) << "SCT does not match any known log."; | |
| 124 result->unverified_scts.pop_back(); | |
| 125 result->unknown_logs_scts.push_back(sct); | |
| 126 return false; | |
| 127 } | |
| 128 | |
| 129 if (!it->second->Verify(expected_entry, sct)) { | |
| 130 DVLOG(1) << "Unable to verify SCT signature."; | |
| 131 return false; | |
| 132 } | |
| 133 | |
| 134 // SCT verified ok, just make sure the timestamp is legitimate. | |
| 135 if (sct.timestamp + base::TimeDelta::FromSeconds(1) > base::Time::Now()) { | |
|
wtc
2013/11/21 02:05:02
Should add a comment to explain why we need to add
Eran M. (Google)
2013/11/21 20:06:02
Done, although I'll be the first to admit it's not
| |
| 136 DVLOG(1) << "SCT is from the future!"; | |
| 137 return false; | |
| 138 } | |
| 139 | |
| 140 result->unverified_scts.pop_back(); | |
| 141 result->verified_scts.push_back(sct); | |
| 142 return true; | |
| 143 } | |
| 144 | |
| 145 } // namespace net | |
| OLD | NEW |