OLD | NEW |
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 "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/callback_helpers.h" | 8 #include "base/callback_helpers.h" |
9 #include "base/metrics/histogram.h" | 9 #include "base/metrics/histogram.h" |
10 #include "net/base/net_errors.h" | 10 #include "net/base/net_errors.h" |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
46 result.invalid_scts.size() + | 46 result.invalid_scts.size() + |
47 result.verified_scts.size() + | 47 result.verified_scts.size() + |
48 result.unknown_logs_scts.size(), | 48 result.unknown_logs_scts.size(), |
49 1, | 49 1, |
50 10, | 50 10, |
51 11); | 51 11); |
52 } | 52 } |
53 | 53 |
54 } // namespace | 54 } // namespace |
55 | 55 |
56 MultiLogCTVerifier::MultiLogCTVerifier() { } | 56 MultiLogCTVerifier::MultiLogCTVerifier() { |
| 57 } |
57 | 58 |
58 MultiLogCTVerifier::~MultiLogCTVerifier() { } | 59 MultiLogCTVerifier::~MultiLogCTVerifier() { |
| 60 } |
59 | 61 |
60 void MultiLogCTVerifier::AddLog(scoped_ptr<CTLogVerifier> log_verifier) { | 62 void MultiLogCTVerifier::AddLog(scoped_ptr<CTLogVerifier> log_verifier) { |
61 DCHECK(log_verifier); | 63 DCHECK(log_verifier); |
62 if (!log_verifier) | 64 if (!log_verifier) |
63 return; | 65 return; |
64 | 66 |
65 linked_ptr<CTLogVerifier> log(log_verifier.release()); | 67 linked_ptr<CTLogVerifier> log(log_verifier.release()); |
66 logs_[log->key_id()] = log; | 68 logs_[log->key_id()] = log; |
67 } | 69 } |
68 | 70 |
69 int MultiLogCTVerifier::Verify( | 71 int MultiLogCTVerifier::Verify(X509Certificate* cert, |
70 X509Certificate* cert, | 72 const std::string& stapled_ocsp_response, |
71 const std::string& stapled_ocsp_response, | 73 const std::string& sct_list_from_tls_extension, |
72 const std::string& sct_list_from_tls_extension, | 74 ct::CTVerifyResult* result, |
73 ct::CTVerifyResult* result, | 75 const BoundNetLog& net_log) { |
74 const BoundNetLog& net_log) { | |
75 DCHECK(cert); | 76 DCHECK(cert); |
76 DCHECK(result); | 77 DCHECK(result); |
77 | 78 |
78 result->verified_scts.clear(); | 79 result->verified_scts.clear(); |
79 result->invalid_scts.clear(); | 80 result->invalid_scts.clear(); |
80 result->unknown_logs_scts.clear(); | 81 result->unknown_logs_scts.clear(); |
81 | 82 |
82 bool has_verified_scts = false; | 83 bool has_verified_scts = false; |
83 | 84 |
84 std::string embedded_scts; | 85 std::string embedded_scts; |
85 if (!cert->GetIntermediateCertificates().empty() && | 86 if (!cert->GetIntermediateCertificates().empty() && |
86 ct::ExtractEmbeddedSCTList( | 87 ct::ExtractEmbeddedSCTList(cert->os_cert_handle(), &embedded_scts)) { |
87 cert->os_cert_handle(), | |
88 &embedded_scts)) { | |
89 ct::LogEntry precert_entry; | 88 ct::LogEntry precert_entry; |
90 | 89 |
91 has_verified_scts = | 90 has_verified_scts = |
92 ct::GetPrecertLogEntry( | 91 ct::GetPrecertLogEntry(cert->os_cert_handle(), |
93 cert->os_cert_handle(), | 92 cert->GetIntermediateCertificates().front(), |
94 cert->GetIntermediateCertificates().front(), | 93 &precert_entry) && |
95 &precert_entry) && | 94 VerifySCTs(embedded_scts, |
96 VerifySCTs( | 95 precert_entry, |
97 embedded_scts, | 96 ct::SignedCertificateTimestamp::SCT_EMBEDDED, |
98 precert_entry, | 97 result); |
99 ct::SignedCertificateTimestamp::SCT_EMBEDDED, | |
100 result); | |
101 } | 98 } |
102 | 99 |
103 std::string sct_list_from_ocsp; | 100 std::string sct_list_from_ocsp; |
104 if (!stapled_ocsp_response.empty() && | 101 if (!stapled_ocsp_response.empty() && |
105 !cert->GetIntermediateCertificates().empty()) { | 102 !cert->GetIntermediateCertificates().empty()) { |
106 ct::ExtractSCTListFromOCSPResponse( | 103 ct::ExtractSCTListFromOCSPResponse( |
107 cert->GetIntermediateCertificates().front(), cert->serial_number(), | 104 cert->GetIntermediateCertificates().front(), |
108 stapled_ocsp_response, &sct_list_from_ocsp); | 105 cert->serial_number(), |
| 106 stapled_ocsp_response, |
| 107 &sct_list_from_ocsp); |
109 } | 108 } |
110 | 109 |
111 // Log to Net Log, after extracting SCTs but before possibly failing on | 110 // Log to Net Log, after extracting SCTs but before possibly failing on |
112 // X.509 entry creation. | 111 // X.509 entry creation. |
113 NetLog::ParametersCallback net_log_callback = | 112 NetLog::ParametersCallback net_log_callback = |
114 base::Bind(&NetLogRawSignedCertificateTimestampCallback, | 113 base::Bind(&NetLogRawSignedCertificateTimestampCallback, |
115 &embedded_scts, &sct_list_from_ocsp, &sct_list_from_tls_extension); | 114 &embedded_scts, |
| 115 &sct_list_from_ocsp, |
| 116 &sct_list_from_tls_extension); |
116 | 117 |
117 net_log.AddEvent( | 118 net_log.AddEvent(NetLog::TYPE_SIGNED_CERTIFICATE_TIMESTAMPS_RECEIVED, |
118 NetLog::TYPE_SIGNED_CERTIFICATE_TIMESTAMPS_RECEIVED, | 119 net_log_callback); |
119 net_log_callback); | |
120 | 120 |
121 ct::LogEntry x509_entry; | 121 ct::LogEntry x509_entry; |
122 if (ct::GetX509LogEntry(cert->os_cert_handle(), &x509_entry)) { | 122 if (ct::GetX509LogEntry(cert->os_cert_handle(), &x509_entry)) { |
123 has_verified_scts |= VerifySCTs( | 123 has_verified_scts |= |
124 sct_list_from_ocsp, | 124 VerifySCTs(sct_list_from_ocsp, |
125 x509_entry, | 125 x509_entry, |
126 ct::SignedCertificateTimestamp::SCT_FROM_OCSP_RESPONSE, | 126 ct::SignedCertificateTimestamp::SCT_FROM_OCSP_RESPONSE, |
127 result); | 127 result); |
128 | 128 |
129 has_verified_scts |= VerifySCTs( | 129 has_verified_scts |= |
130 sct_list_from_tls_extension, | 130 VerifySCTs(sct_list_from_tls_extension, |
131 x509_entry, | 131 x509_entry, |
132 ct::SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, | 132 ct::SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, |
133 result); | 133 result); |
134 } | 134 } |
135 | 135 |
136 NetLog::ParametersCallback net_log_checked_callback = | 136 NetLog::ParametersCallback net_log_checked_callback = |
137 base::Bind(&NetLogSignedCertificateTimestampCallback, result); | 137 base::Bind(&NetLogSignedCertificateTimestampCallback, result); |
138 | 138 |
139 net_log.AddEvent( | 139 net_log.AddEvent(NetLog::TYPE_SIGNED_CERTIFICATE_TIMESTAMPS_CHECKED, |
140 NetLog::TYPE_SIGNED_CERTIFICATE_TIMESTAMPS_CHECKED, | 140 net_log_checked_callback); |
141 net_log_checked_callback); | |
142 | 141 |
143 LogNumSCTsToUMA(*result); | 142 LogNumSCTsToUMA(*result); |
144 | 143 |
145 if (has_verified_scts) | 144 if (has_verified_scts) |
146 return OK; | 145 return OK; |
147 | 146 |
148 return ERR_CT_NO_SCTS_VERIFIED_OK; | 147 return ERR_CT_NO_SCTS_VERIFIED_OK; |
149 } | 148 } |
150 | 149 |
151 bool MultiLogCTVerifier::VerifySCTs( | 150 bool MultiLogCTVerifier::VerifySCTs( |
152 const std::string& encoded_sct_list, | 151 const std::string& encoded_sct_list, |
153 const ct::LogEntry& expected_entry, | 152 const ct::LogEntry& expected_entry, |
154 ct::SignedCertificateTimestamp::Origin origin, | 153 ct::SignedCertificateTimestamp::Origin origin, |
155 ct::CTVerifyResult* result) { | 154 ct::CTVerifyResult* result) { |
156 if (logs_.empty()) | 155 if (logs_.empty()) |
157 return false; | 156 return false; |
158 | 157 |
159 base::StringPiece temp(encoded_sct_list); | 158 base::StringPiece temp(encoded_sct_list); |
160 std::vector<base::StringPiece> sct_list; | 159 std::vector<base::StringPiece> sct_list; |
161 | 160 |
162 if (!ct::DecodeSCTList(&temp, &sct_list)) | 161 if (!ct::DecodeSCTList(&temp, &sct_list)) |
163 return false; | 162 return false; |
164 | 163 |
165 bool verified = false; | 164 bool verified = false; |
166 for (std::vector<base::StringPiece>::const_iterator it = sct_list.begin(); | 165 for (std::vector<base::StringPiece>::const_iterator it = sct_list.begin(); |
167 it != sct_list.end(); ++it) { | 166 it != sct_list.end(); |
| 167 ++it) { |
168 base::StringPiece encoded_sct(*it); | 168 base::StringPiece encoded_sct(*it); |
169 LogSCTOriginToUMA(origin); | 169 LogSCTOriginToUMA(origin); |
170 | 170 |
171 scoped_refptr<ct::SignedCertificateTimestamp> decoded_sct; | 171 scoped_refptr<ct::SignedCertificateTimestamp> decoded_sct; |
172 if (!DecodeSignedCertificateTimestamp(&encoded_sct, &decoded_sct)) { | 172 if (!DecodeSignedCertificateTimestamp(&encoded_sct, &decoded_sct)) { |
173 LogSCTStatusToUMA(ct::SCT_STATUS_NONE); | 173 LogSCTStatusToUMA(ct::SCT_STATUS_NONE); |
174 // XXX(rsleevi): Should we really just skip over bad SCTs? | 174 // XXX(rsleevi): Should we really just skip over bad SCTs? |
175 continue; | 175 continue; |
176 } | 176 } |
177 decoded_sct->origin = origin; | 177 decoded_sct->origin = origin; |
178 | 178 |
179 verified |= VerifySingleSCT(decoded_sct, expected_entry, result); | 179 verified |= VerifySingleSCT(decoded_sct, expected_entry, result); |
180 } | 180 } |
181 | 181 |
182 return verified; | 182 return verified; |
183 } | 183 } |
184 | 184 |
185 bool MultiLogCTVerifier::VerifySingleSCT( | 185 bool MultiLogCTVerifier::VerifySingleSCT( |
186 scoped_refptr<ct::SignedCertificateTimestamp> sct, | 186 scoped_refptr<ct::SignedCertificateTimestamp> sct, |
187 const ct::LogEntry& expected_entry, | 187 const ct::LogEntry& expected_entry, |
188 ct::CTVerifyResult* result) { | 188 ct::CTVerifyResult* result) { |
189 | |
190 // Assume this SCT is untrusted until proven otherwise. | 189 // Assume this SCT is untrusted until proven otherwise. |
191 IDToLogMap::iterator it = logs_.find(sct->log_id); | 190 IDToLogMap::iterator it = logs_.find(sct->log_id); |
192 if (it == logs_.end()) { | 191 if (it == logs_.end()) { |
193 DVLOG(1) << "SCT does not match any known log."; | 192 DVLOG(1) << "SCT does not match any known log."; |
194 result->unknown_logs_scts.push_back(sct); | 193 result->unknown_logs_scts.push_back(sct); |
195 LogSCTStatusToUMA(ct::SCT_STATUS_LOG_UNKNOWN); | 194 LogSCTStatusToUMA(ct::SCT_STATUS_LOG_UNKNOWN); |
196 return false; | 195 return false; |
197 } | 196 } |
198 | 197 |
199 sct->log_description = it->second->description(); | 198 sct->log_description = it->second->description(); |
(...skipping 11 matching lines...) Expand all Loading... |
211 result->invalid_scts.push_back(sct); | 210 result->invalid_scts.push_back(sct); |
212 LogSCTStatusToUMA(ct::SCT_STATUS_INVALID); | 211 LogSCTStatusToUMA(ct::SCT_STATUS_INVALID); |
213 return false; | 212 return false; |
214 } | 213 } |
215 | 214 |
216 LogSCTStatusToUMA(ct::SCT_STATUS_OK); | 215 LogSCTStatusToUMA(ct::SCT_STATUS_OK); |
217 result->verified_scts.push_back(sct); | 216 result->verified_scts.push_back(sct); |
218 return true; | 217 return true; |
219 } | 218 } |
220 | 219 |
221 } // namespace net | 220 } // namespace net |
OLD | NEW |