Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(584)

Side by Side Diff: net/cert/multi_log_ct_verifier.cc

Issue 1216153010: Certificate Transparency: Add observer for Signed Certificate Timestamps (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Addressing nits Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/cert/multi_log_ct_verifier.h ('k') | net/cert/multi_log_ct_verifier_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/cert/multi_log_ct_verifier.h" 5 #include "net/cert/multi_log_ct_verifier.h"
6 6
7 #include <vector> 7 #include <vector>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/callback_helpers.h" 10 #include "base/callback_helpers.h"
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
49 result.invalid_scts.size() + 49 result.invalid_scts.size() +
50 result.verified_scts.size() + 50 result.verified_scts.size() +
51 result.unknown_logs_scts.size(), 51 result.unknown_logs_scts.size(),
52 1, 52 1,
53 10, 53 10,
54 11); 54 11);
55 } 55 }
56 56
57 } // namespace 57 } // namespace
58 58
59 MultiLogCTVerifier::MultiLogCTVerifier() { } 59 MultiLogCTVerifier::MultiLogCTVerifier() : observer_(nullptr) {
60 }
60 61
61 MultiLogCTVerifier::~MultiLogCTVerifier() { } 62 MultiLogCTVerifier::~MultiLogCTVerifier() { }
62 63
63 void MultiLogCTVerifier::AddLogs( 64 void MultiLogCTVerifier::AddLogs(
64 const std::vector<scoped_refptr<CTLogVerifier>>& log_verifiers) { 65 const std::vector<scoped_refptr<CTLogVerifier>>& log_verifiers) {
65 for (const auto& log_verifier : log_verifiers) { 66 for (const auto& log_verifier : log_verifiers) {
66 VLOG(1) << "Adding CT log: " << log_verifier->description(); 67 VLOG(1) << "Adding CT log: " << log_verifier->description();
67 logs_[log_verifier->key_id()] = log_verifier; 68 logs_[log_verifier->key_id()] = log_verifier;
68 } 69 }
69 } 70 }
70 71
72 void MultiLogCTVerifier::SetObserver(Observer* observer) {
73 observer_ = observer;
74 }
75
71 int MultiLogCTVerifier::Verify( 76 int MultiLogCTVerifier::Verify(
72 X509Certificate* cert, 77 X509Certificate* cert,
73 const std::string& stapled_ocsp_response, 78 const std::string& stapled_ocsp_response,
74 const std::string& sct_list_from_tls_extension, 79 const std::string& sct_list_from_tls_extension,
75 ct::CTVerifyResult* result, 80 ct::CTVerifyResult* result,
76 const BoundNetLog& net_log) { 81 const BoundNetLog& net_log) {
77 DCHECK(cert); 82 DCHECK(cert);
78 DCHECK(result); 83 DCHECK(result);
79 84
80 result->verified_scts.clear(); 85 result->verified_scts.clear();
81 result->invalid_scts.clear(); 86 result->invalid_scts.clear();
82 result->unknown_logs_scts.clear(); 87 result->unknown_logs_scts.clear();
83 88
84 bool has_verified_scts = false; 89 bool has_verified_scts = false;
85 90
86 std::string embedded_scts; 91 std::string embedded_scts;
87 if (!cert->GetIntermediateCertificates().empty() && 92 if (!cert->GetIntermediateCertificates().empty() &&
88 ct::ExtractEmbeddedSCTList( 93 ct::ExtractEmbeddedSCTList(
89 cert->os_cert_handle(), 94 cert->os_cert_handle(),
90 &embedded_scts)) { 95 &embedded_scts)) {
91 ct::LogEntry precert_entry; 96 ct::LogEntry precert_entry;
92 97
93 has_verified_scts = 98 has_verified_scts =
94 ct::GetPrecertLogEntry( 99 ct::GetPrecertLogEntry(cert->os_cert_handle(),
95 cert->os_cert_handle(), 100 cert->GetIntermediateCertificates().front(),
96 cert->GetIntermediateCertificates().front(), 101 &precert_entry) &&
97 &precert_entry) && 102 VerifySCTs(embedded_scts, precert_entry,
98 VerifySCTs( 103 ct::SignedCertificateTimestamp::SCT_EMBEDDED, cert, result);
99 embedded_scts,
100 precert_entry,
101 ct::SignedCertificateTimestamp::SCT_EMBEDDED,
102 result);
103 } 104 }
104 105
105 std::string sct_list_from_ocsp; 106 std::string sct_list_from_ocsp;
106 if (!stapled_ocsp_response.empty() && 107 if (!stapled_ocsp_response.empty() &&
107 !cert->GetIntermediateCertificates().empty()) { 108 !cert->GetIntermediateCertificates().empty()) {
108 ct::ExtractSCTListFromOCSPResponse( 109 ct::ExtractSCTListFromOCSPResponse(
109 cert->GetIntermediateCertificates().front(), cert->serial_number(), 110 cert->GetIntermediateCertificates().front(), cert->serial_number(),
110 stapled_ocsp_response, &sct_list_from_ocsp); 111 stapled_ocsp_response, &sct_list_from_ocsp);
111 } 112 }
112 113
113 // Log to Net Log, after extracting SCTs but before possibly failing on 114 // Log to Net Log, after extracting SCTs but before possibly failing on
114 // X.509 entry creation. 115 // X.509 entry creation.
115 NetLog::ParametersCallback net_log_callback = 116 NetLog::ParametersCallback net_log_callback =
116 base::Bind(&NetLogRawSignedCertificateTimestampCallback, 117 base::Bind(&NetLogRawSignedCertificateTimestampCallback,
117 &embedded_scts, &sct_list_from_ocsp, &sct_list_from_tls_extension); 118 &embedded_scts, &sct_list_from_ocsp, &sct_list_from_tls_extension);
118 119
119 net_log.AddEvent( 120 net_log.AddEvent(
120 NetLog::TYPE_SIGNED_CERTIFICATE_TIMESTAMPS_RECEIVED, 121 NetLog::TYPE_SIGNED_CERTIFICATE_TIMESTAMPS_RECEIVED,
121 net_log_callback); 122 net_log_callback);
122 123
123 ct::LogEntry x509_entry; 124 ct::LogEntry x509_entry;
124 if (ct::GetX509LogEntry(cert->os_cert_handle(), &x509_entry)) { 125 if (ct::GetX509LogEntry(cert->os_cert_handle(), &x509_entry)) {
125 has_verified_scts |= VerifySCTs( 126 has_verified_scts |= VerifySCTs(
126 sct_list_from_ocsp, 127 sct_list_from_ocsp, x509_entry,
127 x509_entry, 128 ct::SignedCertificateTimestamp::SCT_FROM_OCSP_RESPONSE, cert, result);
128 ct::SignedCertificateTimestamp::SCT_FROM_OCSP_RESPONSE,
129 result);
130 129
131 has_verified_scts |= VerifySCTs( 130 has_verified_scts |= VerifySCTs(
132 sct_list_from_tls_extension, 131 sct_list_from_tls_extension, x509_entry,
133 x509_entry, 132 ct::SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, cert, result);
134 ct::SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION,
135 result);
136 } 133 }
137 134
138 NetLog::ParametersCallback net_log_checked_callback = 135 NetLog::ParametersCallback net_log_checked_callback =
139 base::Bind(&NetLogSignedCertificateTimestampCallback, result); 136 base::Bind(&NetLogSignedCertificateTimestampCallback, result);
140 137
141 net_log.AddEvent( 138 net_log.AddEvent(
142 NetLog::TYPE_SIGNED_CERTIFICATE_TIMESTAMPS_CHECKED, 139 NetLog::TYPE_SIGNED_CERTIFICATE_TIMESTAMPS_CHECKED,
143 net_log_checked_callback); 140 net_log_checked_callback);
144 141
145 LogNumSCTsToUMA(*result); 142 LogNumSCTsToUMA(*result);
146 143
147 if (has_verified_scts) 144 if (has_verified_scts)
148 return OK; 145 return OK;
149 146
150 return ERR_CT_NO_SCTS_VERIFIED_OK; 147 return ERR_CT_NO_SCTS_VERIFIED_OK;
151 } 148 }
152 149
153 bool MultiLogCTVerifier::VerifySCTs( 150 bool MultiLogCTVerifier::VerifySCTs(
154 const std::string& encoded_sct_list, 151 const std::string& encoded_sct_list,
155 const ct::LogEntry& expected_entry, 152 const ct::LogEntry& expected_entry,
156 ct::SignedCertificateTimestamp::Origin origin, 153 ct::SignedCertificateTimestamp::Origin origin,
154 X509Certificate* cert,
157 ct::CTVerifyResult* result) { 155 ct::CTVerifyResult* result) {
158 if (logs_.empty()) 156 if (logs_.empty())
159 return false; 157 return false;
160 158
161 base::StringPiece temp(encoded_sct_list); 159 base::StringPiece temp(encoded_sct_list);
162 std::vector<base::StringPiece> sct_list; 160 std::vector<base::StringPiece> sct_list;
163 161
164 if (!ct::DecodeSCTList(&temp, &sct_list)) 162 if (!ct::DecodeSCTList(&temp, &sct_list))
165 return false; 163 return false;
166 164
167 bool verified = false; 165 bool verified = false;
168 for (std::vector<base::StringPiece>::const_iterator it = sct_list.begin(); 166 for (std::vector<base::StringPiece>::const_iterator it = sct_list.begin();
169 it != sct_list.end(); ++it) { 167 it != sct_list.end(); ++it) {
170 base::StringPiece encoded_sct(*it); 168 base::StringPiece encoded_sct(*it);
171 LogSCTOriginToUMA(origin); 169 LogSCTOriginToUMA(origin);
172 170
173 scoped_refptr<ct::SignedCertificateTimestamp> decoded_sct; 171 scoped_refptr<ct::SignedCertificateTimestamp> decoded_sct;
174 if (!DecodeSignedCertificateTimestamp(&encoded_sct, &decoded_sct)) { 172 if (!DecodeSignedCertificateTimestamp(&encoded_sct, &decoded_sct)) {
175 LogSCTStatusToUMA(ct::SCT_STATUS_NONE); 173 LogSCTStatusToUMA(ct::SCT_STATUS_NONE);
176 // XXX(rsleevi): Should we really just skip over bad SCTs? 174 // XXX(rsleevi): Should we really just skip over bad SCTs?
177 continue; 175 continue;
178 } 176 }
179 decoded_sct->origin = origin; 177 decoded_sct->origin = origin;
180 178
181 verified |= VerifySingleSCT(decoded_sct, expected_entry, result); 179 verified |= VerifySingleSCT(decoded_sct, expected_entry, cert, result);
182 } 180 }
183 181
184 return verified; 182 return verified;
185 } 183 }
186 184
187 bool MultiLogCTVerifier::VerifySingleSCT( 185 bool MultiLogCTVerifier::VerifySingleSCT(
188 scoped_refptr<ct::SignedCertificateTimestamp> sct, 186 scoped_refptr<ct::SignedCertificateTimestamp> sct,
189 const ct::LogEntry& expected_entry, 187 const ct::LogEntry& expected_entry,
188 X509Certificate* cert,
190 ct::CTVerifyResult* result) { 189 ct::CTVerifyResult* result) {
191
192 // Assume this SCT is untrusted until proven otherwise. 190 // Assume this SCT is untrusted until proven otherwise.
193 const auto& it = logs_.find(sct->log_id); 191 const auto& it = logs_.find(sct->log_id);
194 if (it == logs_.end()) { 192 if (it == logs_.end()) {
195 DVLOG(1) << "SCT does not match any known log."; 193 DVLOG(1) << "SCT does not match any known log.";
196 result->unknown_logs_scts.push_back(sct); 194 result->unknown_logs_scts.push_back(sct);
197 LogSCTStatusToUMA(ct::SCT_STATUS_LOG_UNKNOWN); 195 LogSCTStatusToUMA(ct::SCT_STATUS_LOG_UNKNOWN);
198 return false; 196 return false;
199 } 197 }
200 198
201 sct->log_description = it->second->description(); 199 sct->log_description = it->second->description();
202 200
203 if (!it->second->Verify(expected_entry, *sct.get())) { 201 if (!it->second->Verify(expected_entry, *sct.get())) {
204 DVLOG(1) << "Unable to verify SCT signature."; 202 DVLOG(1) << "Unable to verify SCT signature.";
205 result->invalid_scts.push_back(sct); 203 result->invalid_scts.push_back(sct);
206 LogSCTStatusToUMA(ct::SCT_STATUS_INVALID); 204 LogSCTStatusToUMA(ct::SCT_STATUS_INVALID);
207 return false; 205 return false;
208 } 206 }
209 207
210 // SCT verified ok, just make sure the timestamp is legitimate. 208 // SCT verified ok, just make sure the timestamp is legitimate.
211 if (sct->timestamp > base::Time::Now()) { 209 if (sct->timestamp > base::Time::Now()) {
212 DVLOG(1) << "SCT is from the future!"; 210 DVLOG(1) << "SCT is from the future!";
213 result->invalid_scts.push_back(sct); 211 result->invalid_scts.push_back(sct);
214 LogSCTStatusToUMA(ct::SCT_STATUS_INVALID); 212 LogSCTStatusToUMA(ct::SCT_STATUS_INVALID);
215 return false; 213 return false;
216 } 214 }
217 215
218 LogSCTStatusToUMA(ct::SCT_STATUS_OK); 216 LogSCTStatusToUMA(ct::SCT_STATUS_OK);
219 result->verified_scts.push_back(sct); 217 result->verified_scts.push_back(sct);
218 if (observer_)
219 observer_->OnSCTVerified(cert, sct.get());
220 return true; 220 return true;
221 } 221 }
222 222
223 } // namespace net 223 } // namespace net
OLDNEW
« no previous file with comments | « net/cert/multi_log_ct_verifier.h ('k') | net/cert/multi_log_ct_verifier_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698