OLD | NEW |
---|---|
(Empty) | |
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 | |
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/x509_certificate.h" | |
13 | |
14 namespace net { | |
15 | |
16 MultiLogCTVerifier::MultiLogCTVerifier() { } | |
17 | |
18 MultiLogCTVerifier::~MultiLogCTVerifier() { } | |
19 | |
20 void MultiLogCTVerifier::AddLog(scoped_ptr<CTLogVerifier> log_verifier) { | |
21 DCHECK(log_verifier); | |
22 if (!log_verifier) | |
23 return; | |
24 | |
25 linked_ptr<CTLogVerifier> log(log_verifier.release()); | |
26 logs_[log->key_id()] = log; | |
27 } | |
28 | |
29 int MultiLogCTVerifier::Verify( | |
30 X509Certificate* cert, | |
31 const std::string& sct_list_from_ocsp, | |
32 const std::string& sct_list_from_tls_extension, | |
33 ct::CTVerifyResult* result) { | |
34 DCHECK(cert); | |
35 DCHECK(result); | |
36 | |
37 result->verified_scts.clear(); | |
38 result->unverified_scts.clear(); | |
39 result->unknown_logs_scts.clear(); | |
40 | |
41 bool has_verified_scts = false; | |
42 | |
43 std::string embedded_scts; | |
44 if (!cert->GetIntermediateCertificates().empty() && | |
45 ct::ExtractEmbeddedSCTList( | |
46 cert->os_cert_handle(), | |
47 &embedded_scts)) { | |
48 ct::LogEntry precert_entry; | |
49 | |
50 has_verified_scts = | |
51 ct::GetPrecertLogEntry( | |
52 cert->os_cert_handle(), | |
53 cert->GetIntermediateCertificates().front(), | |
54 &precert_entry) && | |
55 VerifySCTs( | |
56 embedded_scts, | |
57 precert_entry, | |
58 ct::SignedCertificateTimestamp::SCT_EMBEDDED, | |
59 result); | |
60 } | |
61 | |
62 ct::LogEntry x509_entry; | |
63 if (!ct::GetX509LogEntry(cert->os_cert_handle(), &x509_entry)) | |
64 return has_verified_scts ? OK : ERR_FAILED; | |
65 | |
66 has_verified_scts |= VerifySCTs( | |
67 sct_list_from_ocsp, | |
68 x509_entry, | |
69 ct::SignedCertificateTimestamp::SCT_FROM_OCSP_RESPONSE, | |
70 result); | |
71 | |
72 has_verified_scts |= VerifySCTs( | |
73 sct_list_from_tls_extension, | |
74 x509_entry, | |
75 ct::SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, | |
76 result); | |
77 | |
78 if (has_verified_scts) | |
79 return OK; | |
80 | |
81 return ERR_FAILED; | |
82 } | |
83 | |
84 bool MultiLogCTVerifier::VerifySCTs( | |
85 const std::string& encoded_sct_list, | |
86 const ct::LogEntry& expected_entry, | |
87 ct::SignedCertificateTimestamp::Origin origin, | |
88 ct::CTVerifyResult* result) { | |
89 if (logs_.empty()) | |
90 return false; | |
91 | |
92 base::StringPiece temp(encoded_sct_list); | |
93 std::vector<base::StringPiece> sct_list; | |
94 | |
95 if (!ct::DecodeSCTList(&temp, &sct_list)) | |
96 return false; | |
97 | |
98 bool verified = false; | |
99 for (std::vector<base::StringPiece>::const_iterator it = sct_list.begin(); | |
100 it != sct_list.end(); ++it) { | |
101 base::StringPiece encoded_sct(*it); | |
102 | |
103 scoped_refptr<ct::SignedCertificateTimestamp> decoded_sct; | |
104 if (!DecodeSignedCertificateTimestamp(&encoded_sct, &decoded_sct)) { | |
105 // XXX(rsleevi): Should we really just skip over bad SCTs? | |
106 continue; | |
107 } | |
108 decoded_sct->origin = origin; | |
109 | |
110 verified |= VerifySingleSCT(decoded_sct, expected_entry, result); | |
111 } | |
112 | |
113 return verified; | |
114 } | |
115 | |
116 bool MultiLogCTVerifier::VerifySingleSCT( | |
117 scoped_refptr<ct::SignedCertificateTimestamp> sct, | |
118 const ct::LogEntry& expected_entry, | |
119 ct::CTVerifyResult* result) { | |
120 | |
121 // Assume this SCT is untrusted until proven otherwise. | |
122 | |
123 IDToLogMap::iterator it = logs_.find(sct->log_id); | |
124 if (it == logs_.end()) { | |
125 DVLOG(1) << "SCT does not match any known log."; | |
126 result->unknown_logs_scts.push_back(sct); | |
127 return false; | |
128 } | |
129 | |
130 if (!it->second->Verify(expected_entry, *sct)) { | |
131 DVLOG(1) << "Unable to verify SCT signature."; | |
132 result->unverified_scts.push_back(sct); | |
133 return false; | |
134 } | |
135 | |
136 // SCT verified ok, just make sure the timestamp is legitimate. | |
137 // Add 1 second to allow some slack for accepting SCTs which have *Just* | |
138 // been issued. | |
wtc
2013/11/25 23:15:50
Delete the stale comment about the 1-second slack
Eran M. (Google)
2013/11/26 10:10:24
Done.
| |
139 if (sct->timestamp > base::Time::Now()) { | |
140 DVLOG(1) << "SCT is from the future!"; | |
141 result->unverified_scts.push_back(sct); | |
142 return false; | |
143 } | |
144 | |
145 result->verified_scts.push_back(sct); | |
146 return true; | |
147 } | |
148 | |
149 } // namespace net | |
OLD | NEW |