Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix UNSAFE_TODO for wallet [part 2 of N] #26469

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

supermassive
Copy link
Collaborator

@supermassive supermassive commented Nov 11, 2024

Resolves brave/brave-browser#42200

Submitter Checklist:

  • I confirm that no security/privacy review is needed and no other type of reviews are needed, or that I have requested them
  • There is a ticket for my issue
  • Used Github auto-closing keywords in the PR description above
  • Wrote a good PR/commit description
  • Squashed any review feedback or "fixup" commits before merge, so that history is a record of what happened in the repo, not your PR
  • Added appropriate labels (QA/Yes or QA/No; release-notes/include or release-notes/exclude; OS/...) to the associated issue
  • Checked the PR locally:
    • npm run test -- brave_browser_tests, npm run test -- brave_unit_tests wiki
    • npm run presubmit wiki, npm run gn_check, npm run tslint
  • Ran git rebase master (if needed)

Reviewer Checklist:

  • A security review is not needed, or a link to one is included in the PR description
  • New files have MPL-2.0 license header
  • Adequate test coverage exists to prevent regressions
  • Major classes, functions and non-trivial code blocks are well-commented
  • Changes in component dependencies are properly reflected in gn
  • Code follows the style guide
  • Test plan is specified in PR before merging

After-merge Checklist:

Test Plan:

Copy link
Contributor

[puLL-Merge] - brave/brave-core@26469

Description

This PR makes several changes to the Brave Wallet codebase, primarily focusing on improvements to hash functions, memory safety, and code readability. The changes span across multiple files and involve modifications to how Keccak hashes are computed and used throughout the wallet functionality.

Changes

Changes

  1. components/brave_wallet/browser/eip1559_transaction.cc and components/brave_wallet/browser/eip2930_transaction.cc:

    • Changed KeccakHash to KeccakHashToVector
  2. components/brave_wallet/browser/eth_allowance_manager.cc:

    • Modified how the approval topic hash is computed using KeccakHash and ToHex
  3. components/brave_wallet/browser/eth_topics_builder.cc:

    • Updated the way the Transfer event signature hash is computed
  4. components/brave_wallet/browser/eth_transaction.cc:

    • Changed KeccakHash to KeccakHashToVector and ToHex(KeccakHash(...))
  5. components/brave_wallet/browser/ethereum_keyring.cc:

    • Improved the message hash computation using base::StrCat and KeccakHashToVector
  6. components/brave_wallet/browser/ethereum_provider_impl.cc:

    • Minor change to convert message_to_sign to a vector
  7. components/brave_wallet/browser/internal/hd_key.cc:

    • Updated hash computations using HexEncodeLower and Hash160
  8. components/brave_wallet/browser/zcash/zcash_keyring.cc:

    • Modified Hash160 usage
  9. components/brave_wallet/common/eth_address.cc:

    • Improved address computation from public key using KeccakHash
    • Updated checksum address computation
  10. components/brave_wallet/common/eth_request_helper.cc:

    • Changed how domain and primary hashes are assigned
  11. components/brave_wallet/common/eth_sign_typed_data_helper.cc and .h:

    • Major refactoring of hash-related functions
    • Introduced Eip712HashArray type
    • Updated various methods to use the new hash types and functions
  12. components/brave_wallet/common/hash_utils.cc and .h:

    • Significant refactoring of hash functions
    • Introduced new types like KeccakHashArray and Ripemd160HashArray
    • Removed some old hash functions and updated others
  13. components/brave_wallet/common/hash_utils_unittest.cc:

    • Updated test cases to use new hash function signatures
  14. components/brave_wallet/common/zcash_utils.cc:

    • Minor improvements in address parsing and computation

Possible Issues

  • The changes to hash functions and types might require updates in other parts of the codebase that are not included in this PR.
  • Some of the changes (like in eth_address.cc) involve modifying how addresses are computed, which could potentially affect compatibility if not thoroughly tested.

Security Hotspots

No significant security issues are apparent in this PR. The changes mostly involve refactoring existing cryptographic operations rather than introducing new ones. However, thorough testing should be done to ensure that all hash computations still produce the expected results, especially in critical areas like address generation and transaction signing.

@supermassive supermassive changed the title Fix UNSAFE_TODO for wallet Fix UNSAFE_TODO for wallet [part 2 of N] Nov 11, 2024
static_assert(sizeof(result) == sizeof(hash.bytes));
base::ranges::copy(hash.bytes, result.begin());
return result;
}

std::vector<uint8_t> KeccakHashToVector(base::span<const uint8_t> input) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel it would be better to dispense this function and just do base::ToVector(KeccakHash(...)) in the places we are creating are instantiating a vector from the resulting hash. That's much easier to the reader to understand what's going on.

std::move(id));
SignMessageInternal(
account_id, std::move(sign_data),
std::vector<uint8_t>(message_to_sign.begin(), message_to_sign.end()),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unless I'm missing something, i thinkstd::vector<uint8_t>(message_to_sign.begin(), message_to_sign.end()) should be just std::move(message_to_sign).

Comment on lines +400 to +401
auto pubkey_hash = Hash160(public_key_);
identifier_.assign(pubkey_hash.begin(), pubkey_hash.end());
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before it used to be just:

identifier_ = Hash160(public_key_);

But now we are assigning to a local, and then copying it into identifier. Is there a reason to change this from a move operation to a copy?

Comment on lines +430 to +431
auto pubkey_hash = Hash160(public_key_);
identifier_.assign(pubkey_hash.begin(), pubkey_hash.end());
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto

Comment on lines +75 to +76
auto hash = Hash160(hd_key_base->GetPublicKeyBytes());
return std::vector<uint8_t>{hash.begin(), hash.end()};
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto

@@ -179,13 +172,11 @@ EthSignTypedDataHelper::EncodeData(const std::string& primary_type_name,
if (!encoded_field) {
return std::nullopt;
}
result.insert(result.end(), encoded_field->begin(), encoded_field->end());
base::Extend(result, *encoded_field);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit confused about this loop. EncodeField returns <EthSignTypedDataHelper::Eip712HashArray, which is a array<uint8_t, 32u>. So it is extending the vector with this value, but the loop doesn't bail out at this point, so potentially there could be another call, that could extend the vector further. Maybe this doesn't happen because of the data being passed in. Am I missing something?

for (size_t i = 0; i < 32; ++i) {
result.push_back(0);
}
result.insert(result.end(), 32, 0);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this some type of failure case?

const std::string& type,
const base::Value& value) const {
std::optional<EthSignTypedDataHelper::Eip712HashArray>
EthSignTypedDataHelper::EncodeField(const std::string& type_string,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if possible, but if possible, change to std::string_view

const base::Value& value) const {
std::optional<EthSignTypedDataHelper::Eip712HashArray>
EthSignTypedDataHelper::EncodeField(const std::string& type_string,
const base::Value& value) const {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you could be taking base::Value::List here, and with that the check could be moved outside.

@@ -221,22 +212,20 @@ std::optional<std::vector<uint8_t>> EthSignTypedDataHelper::EncodeField(
if (!encoded_item) {
return std::nullopt;
}
array_result.insert(array_result.end(), encoded_item->begin(),
encoded_item->end());
base::Extend(array_result, *encoded_item);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

array_result should be a Eip712HashArray, not a vector.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Fix -Wunsafe-buffer-usage exclusions for wallet files [2/N]
2 participants