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 | 8 |
| 9 #include <vector> |
| 10 |
9 #include "base/logging.h" | 11 #include "base/logging.h" |
10 #include "crypto/openssl_util.h" | 12 #include "crypto/openssl_util.h" |
11 #include "crypto/sha2.h" | 13 #include "crypto/sha2.h" |
12 #include "net/cert/ct_log_verifier_util.h" | 14 #include "net/cert/ct_log_verifier_util.h" |
13 #include "net/cert/ct_serialization.h" | 15 #include "net/cert/ct_serialization.h" |
| 16 #include "net/cert/merkle_audit_proof.h" |
14 #include "net/cert/merkle_consistency_proof.h" | 17 #include "net/cert/merkle_consistency_proof.h" |
15 #include "net/cert/signed_tree_head.h" | 18 #include "net/cert/signed_tree_head.h" |
16 #include "third_party/boringssl/src/include/openssl/bytestring.h" | 19 #include "third_party/boringssl/src/include/openssl/bytestring.h" |
17 #include "third_party/boringssl/src/include/openssl/evp.h" | 20 #include "third_party/boringssl/src/include/openssl/evp.h" |
18 | 21 |
19 namespace net { | 22 namespace net { |
20 | 23 |
21 namespace { | 24 namespace { |
22 | 25 |
23 // The SHA-256 hash of the empty string. | 26 // The SHA-256 hash of the empty string. |
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
235 sn >>= 1; | 238 sn >>= 1; |
236 } | 239 } |
237 | 240 |
238 // 6. After completing iterating through the "consistency_path" array as | 241 // 6. After completing iterating through the "consistency_path" array as |
239 // described above, verify that the "fr" calculated is equal to the | 242 // described above, verify that the "fr" calculated is equal to the |
240 // "first_hash" supplied, that the "sr" calculated is equal to the | 243 // "first_hash" supplied, that the "sr" calculated is equal to the |
241 // "second_hash" supplied and that "sn" is 0. | 244 // "second_hash" supplied and that "sn" is 0. |
242 return fr == old_tree_hash && sr == new_tree_hash && sn == 0; | 245 return fr == old_tree_hash && sr == new_tree_hash && sn == 0; |
243 } | 246 } |
244 | 247 |
| 248 bool CTLogVerifier::VerifyAuditProof(const ct::MerkleAuditProof& proof, |
| 249 const std::string& root_hash, |
| 250 const std::string& leaf_hash) const { |
| 251 // Implements the algorithm described in |
| 252 // https://tools.ietf.org/html/draft-ietf-trans-rfc6962-bis-19#section-10.4.1 |
| 253 // |
| 254 // It maintains a hash |r|, initialized to |leaf_hash|, and hashes nodes from |
| 255 // |proof| into it. The proof is then valid if |r| is |root_hash|, proving |
| 256 // that |root_hash| includes |leaf_hash|. |
| 257 |
| 258 // 1. Compare "leaf_index" against "tree_size". If "leaf_index" is |
| 259 // greater than or equal to "tree_size" fail the proof verification. |
| 260 if (proof.leaf_index >= proof.tree_size) |
| 261 return false; |
| 262 |
| 263 // 2. Set "fn" to "leaf_index" and "sn" to "tree_size - 1". |
| 264 uint64_t fn = proof.leaf_index; |
| 265 uint64_t sn = proof.tree_size - 1; |
| 266 // 3. Set "r" to "hash". |
| 267 std::string r = leaf_hash; |
| 268 |
| 269 // 4. For each value "p" in the "inclusion_path" array: |
| 270 for (const std::string& p : proof.nodes) { |
| 271 // If "sn" is 0, stop the iteration and fail the proof verification. |
| 272 if (sn == 0) |
| 273 return false; |
| 274 |
| 275 // If "LSB(fn)" is set, or if "fn" is equal to "sn", then: |
| 276 if ((fn & 1) || fn == sn) { |
| 277 // 1. Set "r" to "HASH(0x01 || p || r)" |
| 278 r = ct::internal::HashNodes(p, r); |
| 279 |
| 280 // 2. If "LSB(fn)" is not set, then right-shift both "fn" and "sn" |
| 281 // equally until either "LSB(fn)" is set or "fn" is "0". |
| 282 while (!(fn & 1) && fn != 0) { |
| 283 fn >>= 1; |
| 284 sn >>= 1; |
| 285 } |
| 286 } else { // Otherwise: |
| 287 // Set "r" to "HASH(0x01 || r || p)" |
| 288 r = ct::internal::HashNodes(r, p); |
| 289 } |
| 290 |
| 291 // Finally, right-shift both "fn" and "sn" one time. |
| 292 fn >>= 1; |
| 293 sn >>= 1; |
| 294 } |
| 295 |
| 296 // 5. Compare "sn" to 0. Compare "r" against the "root_hash". If "sn" |
| 297 // is equal to 0, and "r" and the "root_hash" are equal, then the |
| 298 // log has proven the inclusion of "hash". Otherwise, fail the |
| 299 // proof verification. |
| 300 return sn == 0 && r == root_hash; |
| 301 } |
| 302 |
245 CTLogVerifier::~CTLogVerifier() { | 303 CTLogVerifier::~CTLogVerifier() { |
246 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); | 304 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); |
247 | 305 |
248 if (public_key_) | 306 if (public_key_) |
249 EVP_PKEY_free(public_key_); | 307 EVP_PKEY_free(public_key_); |
250 } | 308 } |
251 | 309 |
252 bool CTLogVerifier::Init(const base::StringPiece& public_key) { | 310 bool CTLogVerifier::Init(const base::StringPiece& public_key) { |
253 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); | 311 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); |
254 | 312 |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
305 data_to_sign.size()) && | 363 data_to_sign.size()) && |
306 1 == EVP_DigestVerifyFinal( | 364 1 == EVP_DigestVerifyFinal( |
307 &ctx, reinterpret_cast<const uint8_t*>(signature.data()), | 365 &ctx, reinterpret_cast<const uint8_t*>(signature.data()), |
308 signature.size())); | 366 signature.size())); |
309 | 367 |
310 EVP_MD_CTX_cleanup(&ctx); | 368 EVP_MD_CTX_cleanup(&ctx); |
311 return ok; | 369 return ok; |
312 } | 370 } |
313 | 371 |
314 } // namespace net | 372 } // namespace net |
OLD | NEW |