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/ct_log_verifier.h" | 5 #include "net/cert/ct_log_verifier.h" |
6 | 6 |
7 #include <string.h> | 7 #include <string.h> |
8 #include <openssl/bytestring.h> | 8 #include <openssl/bytestring.h> |
9 #include <openssl/evp.h> | 9 #include <openssl/evp.h> |
10 | 10 |
11 #include <vector> | |
12 | |
11 #include "base/logging.h" | 13 #include "base/logging.h" |
12 #include "crypto/openssl_util.h" | 14 #include "crypto/openssl_util.h" |
13 #include "crypto/scoped_openssl_types.h" | 15 #include "crypto/scoped_openssl_types.h" |
14 #include "crypto/sha2.h" | 16 #include "crypto/sha2.h" |
15 #include "net/cert/ct_log_verifier_util.h" | 17 #include "net/cert/ct_log_verifier_util.h" |
16 #include "net/cert/ct_serialization.h" | 18 #include "net/cert/ct_serialization.h" |
19 #include "net/cert/merkle_audit_proof.h" | |
17 #include "net/cert/merkle_consistency_proof.h" | 20 #include "net/cert/merkle_consistency_proof.h" |
18 #include "net/cert/signed_tree_head.h" | 21 #include "net/cert/signed_tree_head.h" |
19 | 22 |
20 namespace net { | 23 namespace net { |
21 | 24 |
22 namespace { | 25 namespace { |
23 | 26 |
24 // The SHA-256 hash of the empty string. | 27 // The SHA-256 hash of the empty string. |
25 const unsigned char kSHA256EmptyStringHash[ct::kSthRootHashLength] = { | 28 const unsigned char kSHA256EmptyStringHash[ct::kSthRootHashLength] = { |
26 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, | 29 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, |
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
236 sn >>= 1; | 239 sn >>= 1; |
237 } | 240 } |
238 | 241 |
239 // 6. After completing iterating through the "consistency_path" array as | 242 // 6. After completing iterating through the "consistency_path" array as |
240 // described above, verify that the "fr" calculated is equal to the | 243 // described above, verify that the "fr" calculated is equal to the |
241 // "first_hash" supplied, that the "sr" calculated is equal to the | 244 // "first_hash" supplied, that the "sr" calculated is equal to the |
242 // "second_hash" supplied and that "sn" is 0. | 245 // "second_hash" supplied and that "sn" is 0. |
243 return fr == old_tree_hash && sr == new_tree_hash && sn == 0; | 246 return fr == old_tree_hash && sr == new_tree_hash && sn == 0; |
244 } | 247 } |
245 | 248 |
249 bool CTLogVerifier::VerifyAuditProof(const ct::MerkleAuditProof& proof, | |
250 const std::string& root_hash, | |
251 const std::string& leaf_hash) const { | |
252 // Implements the algorithm described in | |
253 // https://tools.ietf.org/html/draft-ietf-trans-rfc6962-bis-19#section-10.4.1 | |
davidben
2016/10/18 22:18:57
Nit: Kind of similar to VerifyConsistencyProof, I
Rob Percival
2016/10/20 13:51:47
Done.
| |
254 | |
255 // 1. Compare "leaf_index" against "tree_size". If "leaf_index" is | |
256 // greater than or equal to "tree_size" fail the proof verification. | |
257 if (proof.leaf_index >= proof.tree_size) | |
258 return false; | |
259 | |
260 // 2. Set "fn" to "leaf_index" and "sn" to "tree_size - 1". | |
261 uint64_t fn = proof.leaf_index; | |
262 uint64_t sn = proof.tree_size - 1; | |
263 // 3. Set "r" to "hash". | |
264 std::string r = leaf_hash; | |
265 | |
266 // 4. For each value "p" in the "inclusion_path" array: | |
267 for (const std::string& p : proof.nodes) { | |
davidben
2016/10/18 22:18:57
Shouldn't this check if sn == 0 here? That means y
Rob Percival
2016/10/20 13:51:47
Done. Also reported this as a bug in RFC6962-bis (
| |
268 // If "LSB(fn)" is set, or if "fn" is equal to "sn", then: | |
269 if ((fn & 1) || fn == sn) { | |
270 // 1. Set "r" to "HASH(0x01 || p || r)" | |
271 r = ct::internal::HashNodes(p, r); | |
272 | |
273 // 2. If "LSB(fn)" is not set, then right-shift both "fn" and "sn" | |
274 // equally until either "LSB(fn)" is set or "fn" is "0". | |
275 while (!(fn & 1) && fn != 0) { | |
276 fn >>= 1; | |
277 sn >>= 1; | |
278 } | |
279 } else { // Otherwise: | |
280 // Set "r" to "HASH(0x01 || r || p)" | |
281 r = ct::internal::HashNodes(r, p); | |
282 } | |
283 | |
284 // Finally, right-shift both "fn" and "sn" one time. | |
285 fn >>= 1; | |
286 sn >>= 1; | |
287 } | |
davidben
2016/10/18 22:18:57
[Convinced myself this algorithm is correct, the n
| |
288 | |
289 // 5. Compare "sn" to 0. Compare "r" against the "root_hash". If "sn" | |
290 // is equal to 0, and "r" and the "root_hash" are equal, then the | |
291 // log has proven the inclusion of "hash". Otherwise, fail the | |
292 // proof verification. | |
293 return sn == 0 && r == root_hash; | |
294 } | |
295 | |
246 CTLogVerifier::~CTLogVerifier() { | 296 CTLogVerifier::~CTLogVerifier() { |
247 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); | 297 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); |
248 | 298 |
249 if (public_key_) | 299 if (public_key_) |
250 EVP_PKEY_free(public_key_); | 300 EVP_PKEY_free(public_key_); |
251 } | 301 } |
252 | 302 |
253 bool CTLogVerifier::Init(const base::StringPiece& public_key) { | 303 bool CTLogVerifier::Init(const base::StringPiece& public_key) { |
254 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); | 304 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); |
255 | 305 |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
306 data_to_sign.size()) && | 356 data_to_sign.size()) && |
307 1 == EVP_DigestVerifyFinal( | 357 1 == EVP_DigestVerifyFinal( |
308 &ctx, reinterpret_cast<const uint8_t*>(signature.data()), | 358 &ctx, reinterpret_cast<const uint8_t*>(signature.data()), |
309 signature.size())); | 359 signature.size())); |
310 | 360 |
311 EVP_MD_CTX_cleanup(&ctx); | 361 EVP_MD_CTX_cleanup(&ctx); |
312 return ok; | 362 return ok; |
313 } | 363 } |
314 | 364 |
315 } // namespace net | 365 } // namespace net |
OLD | NEW |