blob: bbda7dd2e5b74b230cbfa990af0a0b3f4fae9a8a [file] [log] [blame]
Avi Drissman60039d42022-09-13 21:49:051// Copyright 2014 The Chromium Authors
[email protected]dca94c72014-05-13 08:26:252// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "extensions/browser/content_hash_tree.h"
6
dchengf5d241082016-04-21 03:43:117#include <memory>
8
David Dorwin3f503b82022-04-20 04:07:039#include "base/check_op.h"
[email protected]dca94c72014-05-13 08:26:2510#include "crypto/secure_hash.h"
11#include "crypto/sha2.h"
12
13namespace extensions {
14
15std::string ComputeTreeHashRoot(const std::vector<std::string>& leaf_hashes,
16 int branch_factor) {
17 if (leaf_hashes.empty() || branch_factor < 2)
18 return std::string();
19
20 // The nodes of the tree we're currently operating on.
21 std::vector<std::string> current_nodes;
22
23 // We avoid having to copy all of the input leaf nodes into |current_nodes|
24 // by using a pointer. So the first iteration of the loop this points at
25 // |leaf_hashes|, but thereafter it points at |current_nodes|.
26 const std::vector<std::string>* current = &leaf_hashes;
27
28 // Where we're inserting new hashes computed from the current level.
29 std::vector<std::string> parent_nodes;
30
31 while (current->size() > 1) {
32 // Iterate over the current level of hashes, computing the hash of up to
33 // |branch_factor| elements to form the hash of each parent node.
jdoerriea1e1598b2018-10-10 09:10:3734 auto i = current->cbegin();
35 while (i != current->cend()) {
dchengf5d241082016-04-21 03:43:1136 std::unique_ptr<crypto::SecureHash> hash(
[email protected]dca94c72014-05-13 08:26:2537 crypto::SecureHash::Create(crypto::SecureHash::SHA256));
38 for (int j = 0; j < branch_factor && i != current->end(); j++) {
39 DCHECK_EQ(i->size(), crypto::kSHA256Length);
40 hash->Update(i->data(), i->size());
41 ++i;
42 }
43 parent_nodes.push_back(std::string(crypto::kSHA256Length, 0));
Daniel Chengd54aee22022-02-26 09:26:3244 hash->Finish(std::data(parent_nodes.back()), crypto::kSHA256Length);
[email protected]dca94c72014-05-13 08:26:2545 }
46 current_nodes.swap(parent_nodes);
47 parent_nodes.clear();
48 current = &current_nodes;
49 }
50 DCHECK_EQ(1u, current->size());
51 return (*current)[0];
52}
53
54} // namespace extensions