From 8960c5e212ce2ec46a27bc048c38db29f9816f7e Mon Sep 17 00:00:00 2001 From: Alexandre Paillier Date: Thu, 19 Dec 2024 15:43:21 +0100 Subject: [PATCH 01/25] Bumped version to 1.15.0-dev (cherry picked from commit 1a26a016b00d53c54ef1af95072159b23a4d157c) --- CHANGELOG.md | 2 ++ Makefile | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fff895cff..54b29d4d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [1.15.0](https://github.com/ledgerhq/app-ethereum/compare/1.14.0...1.15.0) - 2025-xx-xx + ## [1.14.0](https://github.com/ledgerhq/app-ethereum/compare/1.13.0...1.14.0) - 2024-12-19 ### Added diff --git a/Makefile b/Makefile index 2928b10f6..b18b14c96 100644 --- a/Makefile +++ b/Makefile @@ -36,9 +36,9 @@ endif include ./makefile_conf/chain/$(CHAIN).mk APPVERSION_M = 1 -APPVERSION_N = 14 +APPVERSION_N = 15 APPVERSION_P = 0 -APPVERSION = $(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P) +APPVERSION = $(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P)-dev # Application source files APP_SOURCE_PATH += src src_features src_plugins From e9a90e3ca4adf2de8a94608ae89ef39fe7d08fe0 Mon Sep 17 00:00:00 2001 From: Alexandre Paillier Date: Thu, 19 Dec 2024 15:46:15 +0100 Subject: [PATCH 02/25] Switch to relative links for version diff (cherry picked from commit 5111fda740cd6c1e9a2022a58e65a07397161bc1) --- CHANGELOG.md | 108 +++++++++++++++++++++++++-------------------------- 1 file changed, 54 insertions(+), 54 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 54b29d4d6..ea0361cc3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,9 +5,9 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). -## [1.15.0](https://github.com/ledgerhq/app-ethereum/compare/1.14.0...1.15.0) - 2025-xx-xx +## [1.15.0](../../compare/1.14.0...1.15.0) - 2025-xx-xx -## [1.14.0](https://github.com/ledgerhq/app-ethereum/compare/1.13.0...1.14.0) - 2024-12-19 +## [1.14.0](../../compare/1.13.0...1.14.0) - 2024-12-19 ### Added @@ -26,7 +26,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Key ID & public key used for trusted names coming from CAL - PKI key usage in trusted name feature -## [1.13.0](https://github.com/ledgerhq/app-ethereum/compare/1.12.2...1.13.0) - 2024-11-26 +## [1.13.0](../../compare/1.12.2...1.13.0) - 2024-11-26 ### Added @@ -51,20 +51,20 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Potential overflow on the UI buffer used for amounts - RLP parsing issue with legacy transactions -## [1.12.2](https://github.com/ledgerhq/app-ethereum/compare/1.12.1...1.12.2) - 2024-10-24 +## [1.12.2](../../compare/1.12.1...1.12.2) - 2024-10-24 ### Fixed - Token swap with calldata -## [1.12.1](https://github.com/ledgerhq/app-ethereum/compare/1.12.0...1.12.1) - 2024-10-02 +## [1.12.1](../../compare/1.12.0...1.12.1) - 2024-10-02 ### Fixed - Review of EIP-191 messages getting stuck and not responding to APDUs - (clone) Ethereum Classic, gave it back the Ethereum derivation path -## [1.12.0](https://github.com/ledgerhq/app-ethereum/compare/1.11.3...1.12.0) - 2024-09-27 +## [1.12.0](../../compare/1.11.3...1.12.0) - 2024-09-27 ### Added @@ -116,13 +116,13 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Added blind-signing friction to EIP-712 v0 & unfiltered flows - EIP-712 unfiltered flow now defaults to raw/verbose mode on Stax & Flex, but adds a skip button -## [1.11.3](https://github.com/ledgerhq/app-ethereum/compare/1.11.2...1.11.3) - 2024-09-04 +## [1.11.3](../../compare/1.11.2...1.11.3) - 2024-09-04 ### Changed - Replaced MATIC by POL ticker for Polygon network -## [1.11.2](https://github.com/ledgerhq/app-ethereum/compare/1.11.1...1.11.2) - 2024-08-13 +## [1.11.2](../../compare/1.11.1...1.11.2) - 2024-08-13 ### Added @@ -133,14 +133,14 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Simplified blind-signing warnings on Flex & Stax - Restored blind-signing warning screen from < 1.11.0 on Nano devices -## [1.11.1](https://github.com/ledgerhq/app-ethereum/compare/1.11.0...1.11.1) - 2024-07-26 +## [1.11.1](../../compare/1.11.0...1.11.1) - 2024-07-26 ### Fixed - (network/clone) Wanchain - Refusal of EIP-712 messages after another transaction or message -## [1.11.0](https://github.com/ledgerhq/app-ethereum/compare/1.10.4...1.11.0) - 2024-07-24 +## [1.11.0](../../compare/1.10.4...1.11.0) - 2024-07-24 ### Added @@ -186,7 +186,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Handling of EIP-712 empty arrays within nested structs -## [1.10.4](https://github.com/ledgerhq/app-ethereum/compare/1.10.3...1.10.4) - 2024-03-08 +## [1.10.4](../../compare/1.10.3...1.10.4) - 2024-03-08 ### Added @@ -219,7 +219,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - (network) Wanchain chain ID - (network) Sepolia chain ID -## [1.10.3](https://github.com/ledgerhq/app-ethereum/compare/1.10.2...1.10.3) - 2023-07-27 +## [1.10.3](../../compare/1.10.2...1.10.3) - 2023-07-27 ### Added @@ -246,7 +246,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Miscellaneous swap issues - Improper EIP-712 array handling -## [1.10.2](https://github.com/ledgerhq/app-ethereum/compare/1.10.1...1.10.2) - 2023-04-24 +## [1.10.2](../../compare/1.10.1...1.10.2) - 2023-04-24 ### Added @@ -279,19 +279,19 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Error handling on EIP-191 APDUs - Swap transactions handling -## [1.10.1](https://github.com/ledgerhq/app-ethereum/compare/1.10.0...1.10.1) - 2022-11-09 +## [1.10.1](../../compare/1.10.0...1.10.1) - 2022-11-09 ### Fixed - App/device crash with fast button clicks on slow APDU transport on the new EIP-712 signature UI -## [1.10.0](https://github.com/ledgerhq/app-ethereum/compare/1.9.20...1.10.0) - 2022-10-26 +## [1.10.0](../../compare/1.9.20...1.10.0) - 2022-10-26 ### Changed - EIP-712 signatures are now computed on-device and display their content (clear-signing) (LNX & LNS+) -## [1.9.20](https://github.com/ledgerhq/app-ethereum/compare/1.9.19...1.9.20) - 2022-10-10 +## [1.9.20](../../compare/1.9.19...1.9.20) - 2022-10-10 ### Added @@ -314,7 +314,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Compound support (will become its own plugin) -## [1.9.19](https://github.com/ledgerhq/app-ethereum/compare/1.9.18...1.9.19) - 2022-06-15 +## [1.9.19](../../compare/1.9.18...1.9.19) - 2022-06-15 ### Added @@ -332,7 +332,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Bug with huge swap amounts -## [1.9.18](https://github.com/ledgerhq/app-ethereum/compare/1.9.17...1.9.18) - 2022-04-25 +## [1.9.18](../../compare/1.9.17...1.9.18) - 2022-04-25 ### Added @@ -354,19 +354,19 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - App crashing when trying to approve an NFT transaction without having received the NFT information beforehand - App refusing to approve an NFT transaction with a long collection name -## [1.9.17](https://github.com/ledgerhq/app-ethereum/compare/1.9.16...1.9.17) - 2022-01-14 +## [1.9.17](../../compare/1.9.16...1.9.17) - 2022-01-14 ### Added - Support for Non-Fungible Tokens (ERC-721 & ERC-1155) -## [1.9.16](https://github.com/ledgerhq/app-ethereum/compare/1.9.14...1.9.16) - 2022-01-13 +## [1.9.16](../../compare/1.9.14...1.9.16) - 2022-01-13 ### Added - Shyft variant -## [1.9.14](https://github.com/ledgerhq/app-ethereum/compare/1.9.13...1.9.14) - 2021-11-30 +## [1.9.14](../../compare/1.9.13...1.9.14) - 2021-11-30 ### Added @@ -376,38 +376,38 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Fixed stark order signature on LNS -## [1.9.13](https://github.com/ledgerhq/app-ethereum/compare/1.9.12...1.9.13) - 2021-11-17 +## [1.9.13](../../compare/1.9.12...1.9.13) - 2021-11-17 ### Changed - Small improvement in app size -## [1.9.12](https://github.com/ledgerhq/app-ethereum/compare/1.9.11...1.9.12) - 2021-11-12 +## [1.9.12](../../compare/1.9.11...1.9.12) - 2021-11-12 ### Fixed - Fixed stark order signature on LNX -## [1.9.11](https://github.com/ledgerhq/app-ethereum/compare/1.9.10...1.9.11) - 2021-10-12 +## [1.9.11](../../compare/1.9.10...1.9.11) - 2021-10-12 ### Added - Provide network ticker to plugins (especially helpful for Paraswap plugin) - Polygon variant -## [1.9.10](https://github.com/ledgerhq/app-ethereum/compare/1.9.9...1.9.10) - 2021-10-08 +## [1.9.10](../../compare/1.9.9...1.9.10) - 2021-10-08 ### Added - Add new app: Moonriver -## [1.9.9](https://github.com/ledgerhq/app-ethereum/compare/1.9.8...1.9.9) - 2021-10-08 +## [1.9.9](../../compare/1.9.8...1.9.9) - 2021-10-08 ### Changed - Rollback the revert in wording change of "Contract data" in "Blind signing" that was introduced in v1.9.8 -## [1.9.8](https://github.com/ledgerhq/app-ethereum/compare/1.9.7...1.9.8) - 2021-10-06 +## [1.9.8](../../compare/1.9.7...1.9.8) - 2021-10-06 ### Changed @@ -417,19 +417,19 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Goerli now has its own standalone app, with hardcoded deversifi tokens -## [1.9.7](https://github.com/ledgerhq/app-ethereum/compare/1.9.6...1.9.7) - 2021-9-30 +## [1.9.7](../../compare/1.9.6...1.9.7) - 2021-9-30 ### Fixed - Fixed a bug where amounts displayed where wrong when the amount was huge (>=2^87) -## [1.9.6](https://github.com/ledgerhq/app-ethereum/compare/1.9.5...1.9.6) - 2021-9-29 +## [1.9.6](../../compare/1.9.5...1.9.6) - 2021-9-29 ### Fixed - Fixed a bug where fees displayed were wrong on Starkware transactions -## [1.9.5](https://github.com/ledgerhq/app-ethereum/compare/1.9.4...1.9.5) - 2021-9-27 +## [1.9.5](../../compare/1.9.4...1.9.5) - 2021-9-27 ### Changed @@ -440,13 +440,13 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - When blind signing is disabled in settings, and a transaction with smart conract interactions is sent to the app, a new warning screen pops to let the user know that the setting must be enabled to sign this kind of transactions. -## [1.9.4](https://github.com/ledgerhq/app-ethereum/compare/1.9.3...1.9.4) - 2021-9-14 +## [1.9.4](../../compare/1.9.3...1.9.4) - 2021-9-14 ### Added - Added Arbitrum network -## [1.9.3](https://github.com/ledgerhq/app-ethereum/compare/1.9.2...1.9.3) - 2021-9-03 +## [1.9.3](../../compare/1.9.2...1.9.3) - 2021-9-03 ### Added @@ -461,7 +461,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Increased plugin interface to version 2 - Remove support for Theta and Flare -## [1.9.2](https://github.com/ledgerhq/app-ethereum/compare/1.9.0...1.9.2) - 2021-8-11 +## [1.9.2](../../compare/1.9.0...1.9.2) - 2021-8-11 ### Added @@ -472,20 +472,20 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Fixed BSC icon colors. - Fixed theta tokens. -## [1.9.0](https://github.com/ledgerhq/app-ethereum/compare/1.8.8...1.9.0) - 2021-8-05 +## [1.9.0](../../compare/1.8.8...1.9.0) - 2021-8-05 ### Added - Added support for EIP-1559 and EIP-2930 style transactions. -## [1.8.8](https://github.com/ledgerhq/app-ethereum/compare/1.8.7...1.8.8) - 2021-7-21 +## [1.8.8](../../compare/1.8.7...1.8.8) - 2021-7-21 ### Added - Added support for BSC. - Add support for Lido plugin -## [1.8.7](https://github.com/ledgerhq/app-ethereum/compare/1.8.6...1.8.7) - 2021-7-9 +## [1.8.7](../../compare/1.8.6...1.8.7) - 2021-7-9 ### Added @@ -496,7 +496,7 @@ Remove `m/44'/60'` derivation path authorisation for Theta app. `additional_screens` was introduced previously but wasn't properly initialized in some cases. -## [1.8.6](https://github.com/ledgerhq/app-ethereum/compare/1.8.5...1.8.6) - 2021-7-5 +## [1.8.6](../../compare/1.8.5...1.8.6) - 2021-7-5 ### Added @@ -507,63 +507,63 @@ When the network is known, amounts and fees are displayed in the network unit in Fix some compilation warning -## [1.8.5](https://github.com/ledgerhq/app-ethereum/compare/1.7.9...1.8.5) - 2021-6-8 +## [1.8.5](../../compare/1.7.9...1.8.5) - 2021-6-8 ### Added - Added support for external plugins. -## [1.7.9](https://github.com/ledgerhq/app-ethereum/compare/1.7.8...1.7.9) - 2021-6-2 +## [1.7.9](../../compare/1.7.8...1.7.9) - 2021-6-2 ### Added - Added support for Flare Network and Theta Chain. -## [1.7.8](https://github.com/ledgerhq/app-ethereum/compare/1.7.7...1.7.8) - 2021-5-20 +## [1.7.8](../../compare/1.7.7...1.7.8) - 2021-5-20 ### Fixed - Fixed a bug where transaction would sometimes not get properly signed. -## [1.7.7](https://github.com/ledgerhq/app-ethereum/compare/1.7.6...1.7.7) - 2021-5-19 +## [1.7.7](../../compare/1.7.6...1.7.7) - 2021-5-19 ### Special - Version bump needed for deployment reasons, nothing changed. -## [1.7.6](https://github.com/ledgerhq/app-ethereum/compare/1.7.5...1.7.6) - 2021-5-14 +## [1.7.6](../../compare/1.7.5...1.7.6) - 2021-5-14 ### Special - Version bump needed for deployment reasons, nothing changed. -## [1.7.7](https://github.com/ledgerhq/app-ethereum/compare/1.7.6...1.7.7) - 2021-5-19 +## [1.7.7](../../compare/1.7.6...1.7.7) - 2021-5-19 - N/A -## [1.7.6](https://github.com/ledgerhq/app-ethereum/compare/1.7.6...1.7.6) - 2021-5-14 +## [1.7.6](../../compare/1.7.6...1.7.6) - 2021-5-14 - N/A -## [1.7.5](https://github.com/ledgerhq/app-ethereum/compare/1.7.4...1.7.5) - 2021-5-10 +## [1.7.5](../../compare/1.7.4...1.7.5) - 2021-5-10 ### Fixed - Fixed a bug with cx_ecfp_scalar_mult -## [1.7.4](https://github.com/ledgerhq/app-ethereum/compare/1.7.3...1.7.4) - 2021-5-6 +## [1.7.4](../../compare/1.7.3...1.7.4) - 2021-5-6 ### Fixed - Fixed a bug that prevented using Ethereum sidechains -## [1.7.3](https://github.com/ledgerhq/app-ethereum/compare/1.7.2...1.7.3) - 2021-5-5 +## [1.7.3](../../compare/1.7.2...1.7.3) - 2021-5-5 ### Added - Enable Ethereum 2 deposit on Nano S 2.0.0 -## [1.7.2](https://github.com/ledgerhq/app-ethereum/compare/1.7.1...1.7.2) - 2021-5-5 +## [1.7.2](../../compare/1.7.1...1.7.2) - 2021-5-5 ### Added @@ -572,38 +572,38 @@ Fix some compilation warning - Abort signing when the account index of the withdrawal key is higher than INDEX_MAX. - Check that the destination field of the transaction is Ethereum 2 deposit contract. -## [1.7.1](https://github.com/ledgerhq/app-ethereum/compare/1.7.0...1.7.1) - 2021-5-5 +## [1.7.1](../../compare/1.7.0...1.7.1) - 2021-5-5 ### Added - Support for Berlin hard fork: EIP2718 (transaction types) and EIP2930 (access list transactions) - Display ChainID when transacting on chains which are not ethereum (BSC, Polygon, etc) -## [1.7.0](https://github.com/ledgerhq/app-ethereum/compare/1.6.6...1.7.0) - 2021-4-30 +## [1.7.0](../../compare/1.6.6...1.7.0) - 2021-4-30 ### Added - Wallet ID feature now available on Nano X -## [1.6.6](https://github.com/ledgerhq/app-ethereum/compare/1.6.5...1.6.6) - 2021-4-16 +## [1.6.6](../../compare/1.6.5...1.6.6) - 2021-4-16 ### Added - Improved Starkware support -## [1.6.5](https://github.com/ledgerhq/app-ethereum/compare/1.6.4...1.6.5) - 2021-2-12 +## [1.6.5](../../compare/1.6.4...1.6.5) - 2021-2-12 ### Added - Add a setting to enable nonce display when approving transactions -## [1.6.4](https://github.com/ledgerhq/app-ethereum/compare/1.6.3...1.6.4) - 2021-1-12 +## [1.6.4](../../compare/1.6.3...1.6.4) - 2021-1-12 ### Fixed - "warning" icon wasn't correctly displayed -## [1.6.3](https://github.com/ledgerhq/app-ethereum/compare/1.6.2...1.6.3) - 2020-12-10 +## [1.6.3](../../compare/1.6.2...1.6.3) - 2020-12-10 ### Added From 7fcad82a3378eb549c273acaf8e52fd486e0243c Mon Sep 17 00:00:00 2001 From: Charles-Edouard de la Vergne Date: Mon, 16 Dec 2024 18:58:41 +0100 Subject: [PATCH 03/25] Add 1st fuzzing (cherry picked from commit a48055ff6b1ccb1603e31242dca7ba44e606b20c) --- .clusterfuzzlite/Dockerfile | 17 +++ .clusterfuzzlite/build.sh | 9 ++ .clusterfuzzlite/project.yaml | 1 + .github/workflows/cflite_cron.yml | 40 +++++++ .github/workflows/cflite_pr.yml | 43 +++++++ tests/fuzzing/CMakeLists.txt | 184 ++++++++++++++++++++++++++++++ tests/fuzzing/README.md | 83 ++++++++++++++ tests/fuzzing/src/fuzz_app_eth.c | 36 ++++++ tests/fuzzing/src/glyphs.h | 0 tests/fuzzing/src/mock.c | 110 ++++++++++++++++++ 10 files changed, 523 insertions(+) create mode 100644 .clusterfuzzlite/Dockerfile create mode 100644 .clusterfuzzlite/build.sh create mode 100644 .clusterfuzzlite/project.yaml create mode 100644 .github/workflows/cflite_cron.yml create mode 100644 .github/workflows/cflite_pr.yml create mode 100644 tests/fuzzing/CMakeLists.txt create mode 100644 tests/fuzzing/README.md create mode 100644 tests/fuzzing/src/fuzz_app_eth.c create mode 100644 tests/fuzzing/src/glyphs.h create mode 100644 tests/fuzzing/src/mock.c diff --git a/.clusterfuzzlite/Dockerfile b/.clusterfuzzlite/Dockerfile new file mode 100644 index 000000000..32efe99a5 --- /dev/null +++ b/.clusterfuzzlite/Dockerfile @@ -0,0 +1,17 @@ +FROM ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder-lite:latest AS LITE_BUILDER + +# Base image with clang toolchain +FROM gcr.io/oss-fuzz-base/base-builder:v1 + +# Copy the project's source code. +COPY . $SRC/app-ethereum +COPY --from=LITE_BUILDER /opt/ledger-secure-sdk $SRC/app-ethereum/BOLOS_SDK + +# Add the ethereum-plugin-sdk submodule +RUN git clone https://github.com/LedgerHQ/ethereum-plugin-sdk.git $SRC/app-ethereum/ethereum-plugin-sdk + +# Working directory for build.sh +WORKDIR $SRC/app-ethereum + +# Copy build.sh into $SRC dir. +COPY ./.clusterfuzzlite/build.sh $SRC/ diff --git a/.clusterfuzzlite/build.sh b/.clusterfuzzlite/build.sh new file mode 100644 index 000000000..7d9169f61 --- /dev/null +++ b/.clusterfuzzlite/build.sh @@ -0,0 +1,9 @@ +#!/bin/bash -eu + +# build fuzzers + +pushd tests/fuzzing +cmake -DBOLOS_SDK=../../BOLOS_SDK -Bbuild -H. +make -C build +mv ./build/fuzz_app_eth "${OUT}" +popd diff --git a/.clusterfuzzlite/project.yaml b/.clusterfuzzlite/project.yaml new file mode 100644 index 000000000..b455aa397 --- /dev/null +++ b/.clusterfuzzlite/project.yaml @@ -0,0 +1 @@ +language: c diff --git a/.github/workflows/cflite_cron.yml b/.github/workflows/cflite_cron.yml new file mode 100644 index 000000000..17c1e65a2 --- /dev/null +++ b/.github/workflows/cflite_cron.yml @@ -0,0 +1,40 @@ +name: ClusterFuzzLite cron tasks +on: + workflow_dispatch: + push: + branches: + - main # Use your actual default branch here. + schedule: + - cron: '0 13 * * 6' # At 01:00 PM, only on Saturday +permissions: read-all +jobs: + Fuzzing: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + include: + - mode: batch + sanitizer: address + - mode: batch + sanitizer: memory + - mode: prune + sanitizer: address + - mode: coverage + sanitizer: coverage + steps: + - name: Build Fuzzers (${{ matrix.mode }} - ${{ matrix.sanitizer }}) + id: build + uses: google/clusterfuzzlite/actions/build_fuzzers@v1 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + language: c # Change this to the language you are fuzzing. + sanitizer: ${{ matrix.sanitizer }} + - name: Run Fuzzers (${{ matrix.mode }} - ${{ matrix.sanitizer }}) + id: run + uses: google/clusterfuzzlite/actions/run_fuzzers@v1 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + fuzz-seconds: 300 # 5 minutes + mode: ${{ matrix.mode }} + sanitizer: ${{ matrix.sanitizer }} diff --git a/.github/workflows/cflite_pr.yml b/.github/workflows/cflite_pr.yml new file mode 100644 index 000000000..09f91dafe --- /dev/null +++ b/.github/workflows/cflite_pr.yml @@ -0,0 +1,43 @@ +name: ClusterFuzzLite PR fuzzing +on: + pull_request: + paths: + - '**' +permissions: read-all +jobs: + PR: + runs-on: ubuntu-latest + concurrency: + group: ${{ github.workflow }}-${{ matrix.sanitizer }}-${{ github.ref }} + cancel-in-progress: true + strategy: + fail-fast: false + matrix: + sanitizer: [address, undefined, memory] # Override this with the sanitizers you want. + steps: + - name: Build Fuzzers (${{ matrix.sanitizer }}) + id: build + uses: google/clusterfuzzlite/actions/build_fuzzers@v1 + with: + language: c # Change this to the language you are fuzzing. + github-token: ${{ secrets.GITHUB_TOKEN }} + sanitizer: ${{ matrix.sanitizer }} + # Optional but recommended: used to only run fuzzers that are affected + # by the PR. + # storage-repo: https://${{ secrets.PERSONAL_ACCESS_TOKEN }}@github.com/OWNER/STORAGE-REPO-NAME.git + # storage-repo-branch: main # Optional. Defaults to "main" + # storage-repo-branch-coverage: gh-pages # Optional. Defaults to "gh-pages". + - name: Run Fuzzers (${{ matrix.sanitizer }}) + id: run + uses: google/clusterfuzzlite/actions/run_fuzzers@v1 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + fuzz-seconds: 300 # 5 minutes + mode: 'code-change' + sanitizer: ${{ matrix.sanitizer }} + output-sarif: true + # Optional but recommended: used to download the corpus produced by + # batch fuzzing. + # storage-repo: https://${{ secrets.PERSONAL_ACCESS_TOKEN }}@github.com/OWNER/STORAGE-REPO-NAME.git + # storage-repo-branch: main # Optional. Defaults to "main" + # storage-repo-branch-coverage: gh-pages # Optional. Defaults to "gh-pages". diff --git a/tests/fuzzing/CMakeLists.txt b/tests/fuzzing/CMakeLists.txt new file mode 100644 index 000000000..1a59c68f7 --- /dev/null +++ b/tests/fuzzing/CMakeLists.txt @@ -0,0 +1,184 @@ +cmake_minimum_required(VERSION 3.10) + +if(${CMAKE_VERSION} VERSION_LESS 3.10) + cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}) +endif() + +# project information +project(Fuzzer + VERSION 1.0 + DESCRIPTION "Eth Fuzzer" + LANGUAGES C) + +set(CMAKE_C_COMPILER clang) + +set(CMAKE_BUILD_TYPE "Debug") + +# compatible with ClusterFuzzLite +if (NOT DEFINED ENV{LIB_FUZZING_ENGINE}) + set(COMPILATION_FLAGS_ "-g -Wall -fsanitize=fuzzer,address,undefined") +else() + set(COMPILATION_FLAGS_ "$ENV{LIB_FUZZING_ENGINE} $ENV{CXXFLAGS}") +endif() + +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + +string(REPLACE " " ";" COMPILATION_FLAGS ${COMPILATION_FLAGS_}) + +# specify C standard +set(CMAKE_C_STANDARD 11) +set(CMAKE_C_STANDARD_REQUIRED True) +set(CMAKE_C_FLAGS_DEBUG + "${CMAKE_C_FLAGS_DEBUG} -Wall -Wextra -Wno-unused-function -DFUZZ -pedantic -g -O0" +) + +# guard against in-source builds +if(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR}) + message(FATAL_ERROR "In-source builds not allowed. Please make a new directory (called a build directory) and run CMake from there. You may need to remove CMakeCache.txt. ") +endif() + +set(TARGET_DEVICE flex) +if (NOT DEFINED BOLOS_SDK) + message(FATAL_ERROR "BOLOS_SDK environment variable not found.") +endif() + +set(DEFINES + gcc + APPNAME=\"Fuzzing\" + API_LEVEL=21 + TARGET=\"flex\" + TARGET_NAME=\"TARGET_FLEX\" + APPVERSION=\"1.1.0\" + SDK_NAME=\"ledger-secure-sdk\" + SDK_VERSION=\"v21.3.3\" + SDK_HASH=\"d88d4db3c93665f52b5b1f45099d9d36dfaa06ba\" + gcc + __IO=volatile + NDEBUG + HAVE_BAGL_FONT_INTER_REGULAR_28PX + HAVE_BAGL_FONT_INTER_SEMIBOLD_28PX + HAVE_BAGL_FONT_INTER_MEDIUM_36PX + HAVE_INAPP_BLE_PAIRING + HAVE_NBGL + HAVE_PIEZO_SOUND + HAVE_SE_TOUCH + HAVE_SE_EINK_DISPLAY + NBGL_PAGE + NBGL_USE_CASE + SCREEN_SIZE_WALLET + HAVE_FAST_HOLD_TO_APPROVE + HAVE_LEDGER_PKI + HAVE_NES_CRYPT + HAVE_ST_AES + NATIVE_LITTLE_ENDIAN + HAVE_CRC + HAVE_HASH + HAVE_RIPEMD160 + HAVE_SHA224 + HAVE_SHA256 + HAVE_SHA3 + HAVE_SHA384 + HAVE_SHA512 + HAVE_SHA512_WITH_BLOCK_ALT_METHOD + HAVE_SHA512_WITH_BLOCK_ALT_METHOD_M0 + HAVE_BLAKE2 + HAVE_HMAC + HAVE_PBKDF2 + HAVE_AES + HAVE_MATH + HAVE_RNG + HAVE_RNG_RFC6979 + HAVE_RNG_SP800_90A + HAVE_ECC + HAVE_ECC_WEIERSTRASS + HAVE_ECC_TWISTED_EDWARDS + HAVE_ECC_MONTGOMERY + HAVE_SECP256K1_CURVE + HAVE_SECP256R1_CURVE + HAVE_SECP384R1_CURVE + HAVE_SECP521R1_CURVE + HAVE_FR256V1_CURVE + HAVE_STARK256_CURVE + HAVE_BRAINPOOL_P256R1_CURVE + HAVE_BRAINPOOL_P256T1_CURVE + HAVE_BRAINPOOL_P320R1_CURVE + HAVE_BRAINPOOL_P320T1_CURVE + HAVE_BRAINPOOL_P384R1_CURVE + HAVE_BRAINPOOL_P384T1_CURVE + HAVE_BRAINPOOL_P512R1_CURVE + HAVE_BRAINPOOL_P512T1_CURVE + HAVE_BLS12_381_G1_CURVE + HAVE_CV25519_CURVE + HAVE_CV448_CURVE + HAVE_ED25519_CURVE + HAVE_ED448_CURVE + HAVE_ECDH + HAVE_ECDSA + HAVE_EDDSA + HAVE_ECSCHNORR + HAVE_X25519 + HAVE_X448 + HAVE_AES_GCM + HAVE_CMAC + HAVE_AES_SIV + COIN_VARIANT=1 + HAVE_BOLOS_APP_STACK_CANARY + IO_SEPROXYHAL_BUFFER_SIZE_B=300 + HAVE_BLE + BLE_COMMAND_TIMEOUT_MS=2000 + HAVE_BLE_APDU + BLE_SEGMENT_SIZE=32 + HAVE_DEBUG_THROWS + NBGL_QRCODE + MAJOR_VERSION=1 + MINOR_VERSION=1 + PATCH_VERSION=0 + IO_HID_EP_LENGTH=64 + HAVE_SPRINTF + HAVE_SNPRINTF_FORMAT_U + HAVE_IO_USB + HAVE_L4_USBLIB + IO_USB_MAX_ENDPOINTS=4 + HAVE_USB_APDU + USB_SEGMENT_SIZE=64 + HAVE_WEBUSB + WEBUSB_URL_SIZE_B=0 + WEBUSB_URL= + OS_IO_SEPROXYHAL + STANDARD_APP_SYNC_RAPDU + HAVE_GENERIC_TX_PARSER + HAVE_TRUSTED_NAME + HAVE_DYN_MEM_ALLOC + HAVE_SWAP + HAVE_ENUM_VALUE + HAVE_NFT_SUPPORT +) +set(DEFINE ${DEFINES} HAVE_PRINTF PRINTF=printf) + +add_compile_definitions(${DEFINES}) + +FILE(GLOB_RECURSE SDK_STD_SOURCES ${BOLOS_SDK}/lib_standard_app/write.c src/mock.c) + + +include_directories( + ${CMAKE_SOURCE_DIR}/../../ethereum-plugin-sdk/src/ + ${CMAKE_SOURCE_DIR}/../../src + ${CMAKE_SOURCE_DIR}/../../src_features/provideDynamicNetwork/ + ${BOLOS_SDK}/include + ${BOLOS_SDK}/lib_standard_app + ${BOLOS_SDK}/target/${TARGET_DEVICE}/include + ${BOLOS_SDK}/lib_cxng/include + ${BOLOS_SDK}/lib_cxng/src + ${BOLOS_SDK}/lib_ux_nbgl + ${BOLOS_SDK}/lib_nbgl/include + ${CMAKE_SOURCE_DIR}/src +) + +FILE(GLOB_RECURSE SOURCES + ${CMAKE_SOURCE_DIR}/../../src_features/provideDynamicNetwork/*.c + ${CMAKE_SOURCE_DIR}/../../src/hash_bytes.c +) + +add_executable(fuzz_app_eth src/fuzz_app_eth.c ${SDK_STD_SOURCES} ${SOURCES}) +target_compile_options(fuzz_app_eth PUBLIC ${COMPILATION_FLAGS}) +target_link_options(fuzz_app_eth PUBLIC ${COMPILATION_FLAGS}) diff --git a/tests/fuzzing/README.md b/tests/fuzzing/README.md new file mode 100644 index 000000000..43ad67b02 --- /dev/null +++ b/tests/fuzzing/README.md @@ -0,0 +1,83 @@ +# Fuzzing Tests + +## Fuzzing + +Fuzzing allows us to test how a program behaves when provided with invalid, unexpected, or random data as input. + +Our fuzz target needs to implement `int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)`, +which provides an array of random bytes that can be used to simulate a serialized buffer. +If the application crashes, or a [sanitizer](https://github.com/google/sanitizers) detects +any kind of access violation, the fuzzing process is stopped, a report regarding the vulnerability is shown, +and the input that triggered the bug is written to disk under the name `crash-*`. +The vulnerable input file created can be passed as an argument to the fuzzer to triage the issue. + +> **Note**: Usually we want to write a separate fuzz target for each functionality. + +## Manual usage based on Ledger container + +### Preparation + +The fuzzer can run from the docker `ledger-app-builder-legacy`. You can download it from the `ghcr.io` docker repository: + +```console +sudo docker pull ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder-legacy:latest +``` + +You can then enter this development environment by executing the following command from the repository root directory: + +```console +sudo docker run --rm -ti --user "$(id -u):$(id -g)" -v "$(realpath .):/app" ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder-legacy:latest +``` + +### Compilation + +Once in the container, go into the `tests/fuzzing` folder to compile the fuzzer: + +```console +cd tests/fuzzing + +# cmake initialization +cmake -DBOLOS_SDK=/opt/ledger-secure-sdk -Bbuild -H. + +# Fuzzer compilation +make -C build +``` + +### Run + +```console +./build/fuzz_app_eth +``` + +## Full usage based on `clusterfuzzlite` container + +Exactly the same context as the CI, directly using the `clusterfuzzlite` environment. + +More info can be found here: + + +### Preparation + +The principle is to build the container, and run it to perform the fuzzing. + +> **Note**: The container contains a copy of the sources (they are not cloned), +> which means the `docker build` command must be re-executed after each code modification. + +```console +# Prepare directory tree +mkdir tests/fuzzing/{corpus,out} +# Container generation +docker build -t app-ethereum --file .clusterfuzzlite/Dockerfile . +``` + +### Compilation + +```console +docker run --rm --privileged -e FUZZING_LANGUAGE=c -v "$(realpath .)/tests/fuzzing/out:/out" -ti app-ethereum +``` + +### Run + +```console +docker run --rm --privileged -e FUZZING_ENGINE=libfuzzer -e RUN_FUZZER_MODE=interactive -v "$(realpath .)/tests/fuzzing/corpus:/tmp/fuzz_corpus" -v "$(realpath .)/tests/fuzzing/out:/out" -ti gcr.io/oss-fuzz-base/base-runner run_fuzzer fuzz_app_eth +``` diff --git a/tests/fuzzing/src/fuzz_app_eth.c b/tests/fuzzing/src/fuzz_app_eth.c new file mode 100644 index 000000000..c4f55501a --- /dev/null +++ b/tests/fuzzing/src/fuzz_app_eth.c @@ -0,0 +1,36 @@ +#include +#include +#include +#include +#include +#include + +#include "shared_context.h" +#include "network_dynamic.h" + +unsigned char G_io_apdu_buffer[IO_APDU_BUFFER_SIZE]; +tmpContent_t tmpContent; +const chain_config_t *chainConfig; +txContext_t txContext; + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + explicit_bzero(G_io_apdu_buffer, 500); + explicit_bzero(&tmpContent, sizeof(tmpContent_t)); + explicit_bzero(&txContext, sizeof(txContext_t)); + size_t offset = 0; + size_t len = 0; + uint8_t p1; + uint8_t p2; + unsigned int tx; + + while (size - offset > 4) { + if (data[offset++] == 0) break; + p1 = data[offset++]; + p2 = data[offset++]; + len = data[offset++]; + if (size - offset < len) return 0; + handleNetworkConfiguration(p1, p2, data + offset, len, &tx); + offset += len; + } + return 0; +} diff --git a/tests/fuzzing/src/glyphs.h b/tests/fuzzing/src/glyphs.h new file mode 100644 index 000000000..e69de29bb diff --git a/tests/fuzzing/src/mock.c b/tests/fuzzing/src/mock.c new file mode 100644 index 000000000..7328a6adc --- /dev/null +++ b/tests/fuzzing/src/mock.c @@ -0,0 +1,110 @@ +#include + +#include "cx_errors.h" +#include "cx_sha256.h" +#include "cx_sha3.h" + +cx_err_t cx_sha256_init_no_throw(cx_sha256_t *hash) { + memset(hash, 0, sizeof(cx_sha256_t)); + return CX_OK; +} + +cx_err_t cx_hash_no_throw(cx_hash_t *hash, + uint32_t mode, + const uint8_t *in, + size_t len, + uint8_t *out, + size_t out_len) { + UNUSED(hash); + UNUSED(mode); + if (len > 0 && out_len > 0) out[out_len - 1] = in[len - 1]; + return CX_OK; +} + +void assert_exit(bool confirm) { + UNUSED(confirm); + exit(1); +} + +cx_err_t cx_keccak_256_hash_iovec(const cx_iovec_t *iovec, + size_t iovec_len, + uint8_t digest[static CX_KECCAK_256_SIZE]) { + UNUSED(iovec); + UNUSED(iovec_len); + digest[CX_KECCAK_256_SIZE - 1] = 0; + return CX_OK; +} + +cx_err_t cx_sha256_hash_iovec(const cx_iovec_t *iovec, + size_t iovec_len, + uint8_t digest[static CX_SHA256_SIZE]) { + UNUSED(iovec); + UNUSED(iovec_len); + digest[CX_SHA256_SIZE - 1] = 0; + return CX_OK; +} + +int check_signature_with_pubkey(const char *tag, + uint8_t *buffer, + const uint8_t bufLen, + const uint8_t *PubKey, + const uint8_t keyLen, +#ifdef HAVE_LEDGER_PKI + const uint8_t keyUsageExp, +#endif + uint8_t *signature, + const uint8_t sigLen) { + UNUSED(tag); + UNUSED(buffer); + UNUSED(bufLen); + UNUSED(PubKey); +#ifdef HAVE_LEDGER_PKI + UNUSED(keyUsageExp); +#endif + UNUSED(keyLen); + UNUSED(signature); + UNUSED(sigLen); + return CX_OK; +} + +uint64_t u64_from_BE(const uint8_t *in, uint8_t size) { + uint8_t i = 0; + uint64_t res = 0; + + while (i < size && i < sizeof(res)) { + res <<= 8; + res |= in[i]; + i++; + } + + return res; +} + +bool u64_to_string(uint64_t src, char *dst, uint8_t dst_size) { + // Copy the numbers in ASCII format. + uint8_t i = 0; + do { + // Checking `i + 1` to make sure we have enough space for '\0'. + if (i + 1 >= dst_size) { + return false; + } + dst[i] = src % 10 + '0'; + src /= 10; + i++; + } while (src); + + // Null terminate string + dst[i] = '\0'; + + // Revert the string + i--; + uint8_t j = 0; + while (j < i) { + char tmp = dst[i]; + dst[i] = dst[j]; + dst[j] = tmp; + i--; + j++; + } + return true; +} From f1a2f45b38b4dda2fb69e113532c846b2af76b55 Mon Sep 17 00:00:00 2001 From: Charles-Edouard de la Vergne Date: Mon, 16 Dec 2024 18:57:54 +0100 Subject: [PATCH 04/25] fix fuzzing findings (cherry picked from commit ce5962a0fc37ec27ed95f3914b0f16f506372128) --- src/shared_context.h | 2 +- .../provideDynamicNetwork/network_dynamic.c | 25 ++++++++++++++++--- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/src/shared_context.h b/src/shared_context.h index eaac84fb0..d329d043f 100644 --- a/src/shared_context.h +++ b/src/shared_context.h @@ -16,7 +16,7 @@ #include "nbgl_types.h" #endif -extern void app_exit(); +extern void app_exit(void); extern void common_app_init(void); #define SELECTOR_LENGTH 4 diff --git a/src_features/provideDynamicNetwork/network_dynamic.c b/src_features/provideDynamicNetwork/network_dynamic.c index 3ff7d7c09..45f5474ad 100644 --- a/src_features/provideDynamicNetwork/network_dynamic.c +++ b/src_features/provideDynamicNetwork/network_dynamic.c @@ -288,6 +288,7 @@ static uint16_t parse_icon_buffer(void) { uint8_t digest[CX_SHA256_SIZE]; const uint8_t *data = g_network_icon[g_current_slot].bitmap; const uint16_t field_len = g_icon_payload.received_size; + cx_err_t error = CX_INTERNAL_ERROR; // Check the icon header sw = check_icon_header(data, field_len, &img_len); @@ -298,7 +299,7 @@ static uint16_t parse_icon_buffer(void) { CHECK_FIELD_OVERFLOW("NETWORK_ICON", g_network_icon[g_current_slot].bitmap); // Check icon hash - cx_sha256_hash(data, field_len, digest); + CX_CHECK(cx_sha256_hash(data, field_len, digest)); if (memcmp(digest, g_network_icon[g_current_slot].hash, CX_SHA256_SIZE) != 0) { PRINTF("NETWORK_ICON hash mismatch!\n"); return APDU_RESPONSE_INVALID_DATA; @@ -313,7 +314,9 @@ static uint16_t parse_icon_buffer(void) { DYNAMIC_NETWORK_INFO[g_current_slot].icon.isFile = true; COPY_FIELD(DYNAMIC_NETWORK_INFO[g_current_slot].icon.bitmap); print_icon_info(); - return APDU_RESPONSE_OK; + error = APDU_RESPONSE_OK; +end: + return error; } /** @@ -376,6 +379,12 @@ static uint16_t handle_next_icon_chunk(const uint8_t *data, uint8_t length) { */ static uint16_t handle_icon_chunks(uint8_t p1, const uint8_t *data, uint8_t length) { uint16_t sw = APDU_RESPONSE_UNKNOWN; + uint8_t hash[CX_SHA256_SIZE] = {0}; + + if (memcmp(g_network_icon[g_current_slot].hash, hash, CX_SHA256_SIZE) == 0) { + PRINTF("Error: Icon hash not set!\n"); + return APDU_RESPONSE_INVALID_DATA; + } // Check the received chunk index if (p1 == P1_FIRST_CHUNK) { @@ -432,16 +441,24 @@ static bool verify_signature(s_sig_ctx *sig_ctx) { CX_CHECK( cx_hash_no_throw((cx_hash_t *) &sig_ctx->hash_ctx, CX_LAST, NULL, 0, hash, INT256_LENGTH)); +#ifdef HAVE_LEDGER_PKI CX_CHECK(check_signature_with_pubkey("Dynamic Network", hash, sizeof(hash), LEDGER_SIGNATURE_PUBLIC_KEY, sizeof(LEDGER_SIGNATURE_PUBLIC_KEY), -#ifdef HAVE_LEDGER_PKI CERTIFICATE_PUBLIC_KEY_USAGE_COIN_META, -#endif (uint8_t *) (sig_ctx->sig), sig_ctx->sig_size)); +#else + CX_CHECK(check_signature_with_pubkey("Dynamic Network", + hash, + sizeof(hash), + LEDGER_SIGNATURE_PUBLIC_KEY, + sizeof(LEDGER_SIGNATURE_PUBLIC_KEY), + (uint8_t *) (sig_ctx->sig), + sig_ctx->sig_size)); +#endif ret_code = true; end: From 3b924c6d7191062af511a4cd30d5482b7695a9b9 Mon Sep 17 00:00:00 2001 From: Baptistin BOILOT Date: Tue, 3 Dec 2024 17:48:40 +0100 Subject: [PATCH 05/25] test: add gcs fuzzer (cherry picked from commit 3811c4c192c91c29256a405b265f207b6057d877) --- .gitignore | 2 + fuzzing/CMakeLists.txt | 200 +++++++++++++++++++ fuzzing/README.md | 21 ++ fuzzing/coverage.sh | 3 + fuzzing/fuzzer_tlv.c | 93 +++++++++ fuzzing/mock/glyphs.h | 0 fuzzing/mock/mock.c | 87 ++++++++ src_features/generic_tx_parser/cmd_tx_info.h | 2 + src_features/signTx/logic_signTx.c | 2 +- 9 files changed, 409 insertions(+), 1 deletion(-) create mode 100644 fuzzing/CMakeLists.txt create mode 100644 fuzzing/README.md create mode 100755 fuzzing/coverage.sh create mode 100644 fuzzing/fuzzer_tlv.c create mode 100644 fuzzing/mock/glyphs.h create mode 100644 fuzzing/mock/mock.c diff --git a/.gitignore b/.gitignore index 20f25ff19..019c7207d 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,5 @@ __version__.py .vscode .idea + +fuzzing/CORPUS/ \ No newline at end of file diff --git a/fuzzing/CMakeLists.txt b/fuzzing/CMakeLists.txt new file mode 100644 index 000000000..5dcefbb46 --- /dev/null +++ b/fuzzing/CMakeLists.txt @@ -0,0 +1,200 @@ +cmake_minimum_required(VERSION 3.14) + +if(${CMAKE_VERSION} VERSION_LESS 3.14) + cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}) +endif() + +# project information +project(FuzzWithdraw + VERSION 1.0 + DESCRIPTION "Fuzzing of Ethereum app" + LANGUAGES C) + +# guard against bad build-type strings +if (NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE "Debug") +endif() + +if (NOT CMAKE_C_COMPILER_ID MATCHES "Clang") + message(FATAL_ERROR "Fuzzer needs to be built with Clang") +endif() + +# default fuzz device target +if (NOT TARGET_DEVICE) + set(TARGET_DEVICE "flex") +endif() + +set(BOLOS_SDK /opt/${TARGET_DEVICE}-secure-sdk) +if (NOT DEFINED BOLOS_SDK) + message(FATAL_ERROR "BOLOS_SDK environment variable not found.") +endif() + +# compatible with ClusterFuzzLite +if (NOT DEFINED ENV{LIB_FUZZING_ENGINE}) + set(COMPILATION_FLAGS -std=gnu99 -Wall -Wextra -pedantic -fshort-enums -Wno-unused-parameter -Wno-embedded-directive -g -O0 -fsanitize=fuzzer,address,undefined -fprofile-instr-generate -fcoverage-mapping) +else() + set(COMPILATION_FLAGS $ENV{LIB_FUZZING_ENGINE} $ENV{CXXFLAGS}) +endif() + +set(DEFINES + gcc + APPNAME=\"Fuzzing\" + API_LEVEL=21 + TARGET=\"flex\" + TARGET_NAME=\"TARGET_FLEX\" + APPVERSION=\"1.1.0\" + SDK_NAME=\"ledger-secure-sdk\" + SDK_VERSION=\"v21.3.3\" + SDK_HASH=\"d88d4db3c93665f52b5b1f45099d9d36dfaa06ba\" + gcc + __IO=volatile + NDEBUG + HAVE_BAGL_FONT_INTER_REGULAR_28PX + HAVE_BAGL_FONT_INTER_SEMIBOLD_28PX + HAVE_BAGL_FONT_INTER_MEDIUM_36PX + HAVE_INAPP_BLE_PAIRING + HAVE_NBGL + HAVE_PIEZO_SOUND + HAVE_SE_TOUCH + HAVE_SE_EINK_DISPLAY + NBGL_PAGE + NBGL_USE_CASE + SCREEN_SIZE_WALLET + HAVE_FAST_HOLD_TO_APPROVE + HAVE_LEDGER_PKI + HAVE_NES_CRYPT + HAVE_ST_AES + NATIVE_LITTLE_ENDIAN + HAVE_CRC + HAVE_HASH + HAVE_RIPEMD160 + HAVE_SHA224 + HAVE_SHA256 + HAVE_SHA3 + HAVE_SHA384 + HAVE_SHA512 + HAVE_SHA512_WITH_BLOCK_ALT_METHOD + HAVE_SHA512_WITH_BLOCK_ALT_METHOD_M0 + HAVE_BLAKE2 + HAVE_HMAC + HAVE_PBKDF2 + HAVE_AES + HAVE_MATH + HAVE_RNG + HAVE_RNG_RFC6979 + HAVE_RNG_SP800_90A + HAVE_ECC + HAVE_ECC_WEIERSTRASS + HAVE_ECC_TWISTED_EDWARDS + HAVE_ECC_MONTGOMERY + HAVE_SECP256K1_CURVE + HAVE_SECP256R1_CURVE + HAVE_SECP384R1_CURVE + HAVE_SECP521R1_CURVE + HAVE_FR256V1_CURVE + HAVE_STARK256_CURVE + HAVE_BRAINPOOL_P256R1_CURVE + HAVE_BRAINPOOL_P256T1_CURVE + HAVE_BRAINPOOL_P320R1_CURVE + HAVE_BRAINPOOL_P320T1_CURVE + HAVE_BRAINPOOL_P384R1_CURVE + HAVE_BRAINPOOL_P384T1_CURVE + HAVE_BRAINPOOL_P512R1_CURVE + HAVE_BRAINPOOL_P512T1_CURVE + HAVE_BLS12_381_G1_CURVE + HAVE_CV25519_CURVE + HAVE_CV448_CURVE + HAVE_ED25519_CURVE + HAVE_ED448_CURVE + HAVE_ECDH + HAVE_ECDSA + HAVE_EDDSA + HAVE_ECSCHNORR + HAVE_X25519 + HAVE_X448 + HAVE_AES_GCM + HAVE_CMAC + HAVE_AES_SIV + COIN_VARIANT=1 + HAVE_BOLOS_APP_STACK_CANARY + IO_SEPROXYHAL_BUFFER_SIZE_B=300 + HAVE_BLE + BLE_COMMAND_TIMEOUT_MS=2000 + HAVE_BLE_APDU + BLE_SEGMENT_SIZE=32 + HAVE_DEBUG_THROWS + NBGL_QRCODE + MAJOR_VERSION=1 + MINOR_VERSION=1 + PATCH_VERSION=0 + IO_HID_EP_LENGTH=64 + HAVE_SPRINTF + HAVE_SNPRINTF_FORMAT_U + HAVE_IO_USB + HAVE_L4_USBLIB + IO_USB_MAX_ENDPOINTS=4 + HAVE_USB_APDU + USB_SEGMENT_SIZE=64 + HAVE_WEBUSB + WEBUSB_URL_SIZE_B=0 + WEBUSB_URL= + OS_IO_SEPROXYHAL + STANDARD_APP_SYNC_RAPDU + HAVE_GENERIC_TX_PARSER + HAVE_TRUSTED_NAME + HAVE_DYN_MEM_ALLOC + HAVE_SWAP + HAVE_ENUM_VALUE + HAVE_NFT_SUPPORT +) + +add_compile_definitions(${DEFINES}) + +include_directories( + ${CMAKE_SOURCE_DIR}/../ethereum-plugin-sdk/src/ + ${CMAKE_SOURCE_DIR}/../src + ${CMAKE_SOURCE_DIR}/../src_features/generic_tx_parser/ + ${CMAKE_SOURCE_DIR}/../src_features/provide_enum_value/ + ${CMAKE_SOURCE_DIR}/../src_features/provideDynamicNetwork/ + ${CMAKE_SOURCE_DIR}/../src_features/signTx/ + ${CMAKE_SOURCE_DIR}/../src_features/provideTrustedName/ + ${CMAKE_SOURCE_DIR}/../src_features/getChallenge/ + ${CMAKE_SOURCE_DIR}/../src_features/signMessageEIP712/ + ${BOLOS_SDK}/include + ${BOLOS_SDK}/target/${TARGET_DEVICE}/include + ${BOLOS_SDK}/lib_cxng/include + ${BOLOS_SDK}/lib_cxng/src + ${BOLOS_SDK}/lib_ux_nbgl + ${BOLOS_SDK}/lib_nbgl/include + ${BOLOS_SDK}/lib_standard_app/ + ./mock/ +) + +FILE(GLOB_RECURSE SDK_STD_SOURCES ${BOLOS_SDK}/lib_standard_app/*.c ${CMAKE_SOURCE_DIR}/../ethereum-plugin-sdk/src/*.c ./mock/mock.c) +list(REMOVE_ITEM SDK_STD_SOURCES ${BOLOS_SDK}/lib_standard_app/io.c ${CMAKE_SOURCE_DIR}/../ethereum-plugin-sdk/src/main.c ${BOLOS_SDK}/lib_standard_app/main.c ${BOLOS_SDK}/lib_standard_app/crypto_helpers.c) + +FILE(GLOB_RECURSE SOURCES + ${CMAKE_SOURCE_DIR}/../src_features/generic_tx_parser/*.c + ${CMAKE_SOURCE_DIR}/../src_features/provideTrustedName/*.c + ${CMAKE_SOURCE_DIR}/../src_features/getChallenge/*.c + ${CMAKE_SOURCE_DIR}/../src_features/provide_enum_value/*.c + ${CMAKE_SOURCE_DIR}/../src_features/provideDynamicNetwork/*.c + ${CMAKE_SOURCE_DIR}/../src/mem.c + ${CMAKE_SOURCE_DIR}/../src/mem_utils.c + ${CMAKE_SOURCE_DIR}/../src/network.c + ${CMAKE_SOURCE_DIR}/../src/tlv.c + ${CMAKE_SOURCE_DIR}/../src/tlv_apdu.c + ${CMAKE_SOURCE_DIR}/../src/uint128.c + ${CMAKE_SOURCE_DIR}/../src/uint256.c + ${CMAKE_SOURCE_DIR}/../src/time_format.c + ${CMAKE_SOURCE_DIR}/../src/uint_common.c + ${CMAKE_SOURCE_DIR}/../src/utils.c + ${CMAKE_SOURCE_DIR}/../src/manage_asset_info.c + ${CMAKE_SOURCE_DIR}/../src/hash_bytes.c +) + +add_executable(fuzzer_tlv fuzzer_tlv.c ${SDK_STD_SOURCES} ${SOURCES}) +target_link_libraries(fuzzer_tlv bsd) # strlcpy / strlcat + +target_compile_options(fuzzer_tlv PRIVATE ${COMPILATION_FLAGS}) +target_link_options(fuzzer_tlv PRIVATE ${COMPILATION_FLAGS}) \ No newline at end of file diff --git a/fuzzing/README.md b/fuzzing/README.md new file mode 100644 index 000000000..503fc4049 --- /dev/null +++ b/fuzzing/README.md @@ -0,0 +1,21 @@ +# Fuzzing ethereum app + +## Build + +The fuzzer can be built using the following commands from the app directory: +```bash +docker run --rm -it --user "$(id -u):$(id -g)" -v "$(realpath .):/app" ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder-legacy:latest bash + +apt install libbsd-dev + +cd fuzzing +cmake -DBOLOS_SDK=/opt/ledger-secure-sdk -DCMAKE_C_COMPILER=/usr/bin/clang -Bbuild -H. +cmake --build build +``` + +## Run + +The fuzzer can be run using the following commands from the fuzzing directory: +```bash +./build/fuzzer_tlv -max_len=8192 +``` diff --git a/fuzzing/coverage.sh b/fuzzing/coverage.sh new file mode 100755 index 000000000..a6c2c3b93 --- /dev/null +++ b/fuzzing/coverage.sh @@ -0,0 +1,3 @@ +llvm-profdata merge -sparse *.profraw -o default.profdata +llvm-cov show build/fuzzer_tlv -instr-profile=default.profdata -format=html > report.html +llvm-cov report build/fuzzer_tlv -instr-profile=default.profdata diff --git a/fuzzing/fuzzer_tlv.c b/fuzzing/fuzzer_tlv.c new file mode 100644 index 000000000..6bc67087e --- /dev/null +++ b/fuzzing/fuzzer_tlv.c @@ -0,0 +1,93 @@ +#include +#include + +#include "cmd_field.h" +#include "cmd_tx_info.h" +#include "cmd_enum_value.h" + +#include "gtp_field.h" +#include "gtp_tx_info.h" +#include "enum_value.h" + +#include "shared_context.h" +#include "tlv.h" + +cx_sha3_t sha3 = {0}; +unsigned char G_io_apdu_buffer[260]; +tmpContent_t tmpContent; +txContext_t txContext; +txContent_t txContent; +chain_config_t config = { + .coinName = "FUZZ", + .chainId = 0x42, +}; +const chain_config_t *chainConfig = &config; +uint8_t appState; +tmpCtx_t tmpCtx; +strings_t strings; + + +int fuzzGenericParserFieldCmd(const uint8_t *data, size_t size) { + s_field field = {0}; + s_field_ctx ctx = {0}; + ctx.field = &field; + + if (!tlv_parse(data, size, (f_tlv_data_handler)&handle_field_struct, &ctx)) + return 1; + + if (!verify_field_struct(&ctx)) + return 1; + + return format_field(&field); +} + +int fuzzGenericParserTxInfoCmd(const uint8_t *data, size_t size) { + s_tx_info tx_info = {0}; + s_tx_info_ctx ctx = {0}; + ctx.tx_info = &tx_info; + + if (!tlv_parse(data, size, (f_tlv_data_handler)&handle_tx_info_struct, &ctx)) + return 1; + + return verify_tx_info_struct(&ctx); +} + +int fuzzGenericParserEnumCmd(const uint8_t *data, size_t size) { + s_enum_value_ctx ctx = {0}; + + if (!tlv_parse(data, size, (f_tlv_data_handler)&handle_enum_value_struct, &ctx)) + return 1; + + return verify_enum_value_struct(&ctx); +} + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + explicit_bzero(&tmpContent, sizeof(tmpContent_t)); + explicit_bzero(&txContext, sizeof(txContext_t)); + explicit_bzero(&txContent, sizeof(txContent_t)); + explicit_bzero(&tmpCtx, sizeof(tmpCtx_t)); + explicit_bzero(&strings, sizeof(strings_t)); + explicit_bzero(&G_io_apdu_buffer, 260); + + txContext.content = &txContent; + txContext.sha3 = &sha3; + + if (size < 1) + return 0; + switch (data[0]) + { + case 0: + fuzzGenericParserFieldCmd(++data, --size); + break; + case 1: + fuzzGenericParserTxInfoCmd(++data, --size); + break; + case 2: + fuzzGenericParserEnumCmd(++data, --size); + break; + default: + return 0; + } + + return 0; +} diff --git a/fuzzing/mock/glyphs.h b/fuzzing/mock/glyphs.h new file mode 100644 index 000000000..e69de29bb diff --git a/fuzzing/mock/mock.c b/fuzzing/mock/mock.c new file mode 100644 index 000000000..36d687b38 --- /dev/null +++ b/fuzzing/mock/mock.c @@ -0,0 +1,87 @@ +#include + +#include "cx_errors.h" +#include "cx_sha256.h" +#include "cx_sha3.h" + +void *pic(void *addr) +{ + return addr; +} + +cx_err_t cx_sha256_init_no_throw(cx_sha256_t *hash) +{ + memset(hash, 0, sizeof(cx_sha256_t)); + return CX_OK; +} + +cx_err_t cx_sha3_init_no_throw(cx_sha3_t *hash PLENGTH(sizeof(cx_sha3_t)), size_t size) +{ + memset(hash, 0, sizeof(cx_sha3_t)); + return CX_OK; +} + +cx_err_t cx_hash_no_throw(cx_hash_t *hash, + uint32_t mode, + const uint8_t *in, + size_t len, + uint8_t *out, + size_t out_len) +{ + if (len > 0 && out_len > 0) + out[out_len - 1] = in[len - 1]; + return CX_OK; +} + +cx_err_t cx_math_mult_no_throw(uint8_t *r, const uint8_t *a, const uint8_t *b, size_t len) +{ + return CX_OK; +} + +void cx_rng_no_throw(uint8_t *buffer, size_t len) +{ + if (len > 0) + buffer[len - 1] = 0; +} + +uint16_t get_public_key(uint8_t *out, uint8_t outLength) { + if (outLength > 0) + out[outLength - 1] = 0; + return 0; +} + +void assert_exit(bool confirm) +{ + exit(1); +} + +cx_err_t cx_keccak_256_hash_iovec(const cx_iovec_t *iovec, + size_t iovec_len, + uint8_t digest[static CX_KECCAK_256_SIZE]) { + digest[CX_KECCAK_256_SIZE - 1] = 0; + return CX_OK; +} + +cx_err_t cx_sha256_hash_iovec(const cx_iovec_t *iovec, + size_t iovec_len, + uint8_t digest[static CX_SHA256_SIZE]) +{ + digest[CX_SHA256_SIZE - 1] = 0; + return CX_OK; +} + +int check_signature_with_pubkey(const char *tag, + uint8_t *buffer, + const uint8_t bufLen, + const uint8_t *PubKey, + const uint8_t keyLen, +#ifdef HAVE_LEDGER_PKI + const uint8_t keyUsageExp, +#endif + uint8_t *signature, + const uint8_t sigLen) { + return CX_OK; +} + +void ui_gcs_cleanup(void) { +} diff --git a/src_features/generic_tx_parser/cmd_tx_info.h b/src_features/generic_tx_parser/cmd_tx_info.h index a093669b4..6f8d94607 100644 --- a/src_features/generic_tx_parser/cmd_tx_info.h +++ b/src_features/generic_tx_parser/cmd_tx_info.h @@ -2,7 +2,9 @@ #define CMD_TX_INFO_H_ #include +#include "gtp_tx_info.h" + bool verify_struct(const s_tx_info_ctx *context); uint16_t handle_tx_info(uint8_t p1, uint8_t p2, uint8_t lc, const uint8_t *payload); void gcs_cleanup(void); diff --git a/src_features/signTx/logic_signTx.c b/src_features/signTx/logic_signTx.c index 1f9085346..6d3c304ca 100644 --- a/src_features/signTx/logic_signTx.c +++ b/src_features/signTx/logic_signTx.c @@ -343,7 +343,7 @@ __attribute__((noreturn)) void send_swap_error(uint8_t error_code, const char *str1, const char *str2) { uint32_t tx = 0; - uint len = 0; + size_t len = 0; PRINTF("APDU_RESPONSE_MODE_CHECK_FAILED: 0x%x\n", error_code); // Set RAPDU error codes G_io_apdu_buffer[tx++] = error_code; From 39ccc077d86b44ad6269face017f34d510308511 Mon Sep 17 00:00:00 2001 From: Baptistin BOILOT Date: Fri, 27 Dec 2024 14:33:17 +0100 Subject: [PATCH 06/25] chore: merge all fuzzers and clean the cmake (cherry picked from commit 432393500065238d851480f7a6c9b072293c91d5) --- .clusterfuzzlite/build.sh | 6 +- .gitignore | 9 +- fuzzing/CMakeLists.txt | 200 ------------------- fuzzing/README.md | 21 -- fuzzing/coverage.sh | 3 - fuzzing/fuzzer_tlv.c | 93 --------- fuzzing/mock/glyphs.h | 0 fuzzing/mock/mock.c | 87 -------- src_features/generic_tx_parser/cmd_tx_info.h | 1 - tests/fuzzing/CMakeLists.txt | 97 +++++---- tests/fuzzing/README.md | 11 +- tests/fuzzing/src/fuzz_app_eth.c | 36 ---- tests/fuzzing/src/fuzzer.c | 140 +++++++++++++ tests/fuzzing/src/mock.c | 74 +++---- 14 files changed, 257 insertions(+), 521 deletions(-) delete mode 100644 fuzzing/CMakeLists.txt delete mode 100644 fuzzing/README.md delete mode 100755 fuzzing/coverage.sh delete mode 100644 fuzzing/fuzzer_tlv.c delete mode 100644 fuzzing/mock/glyphs.h delete mode 100644 fuzzing/mock/mock.c delete mode 100644 tests/fuzzing/src/fuzz_app_eth.c create mode 100644 tests/fuzzing/src/fuzzer.c diff --git a/.clusterfuzzlite/build.sh b/.clusterfuzzlite/build.sh index 7d9169f61..6fc75a929 100644 --- a/.clusterfuzzlite/build.sh +++ b/.clusterfuzzlite/build.sh @@ -3,7 +3,7 @@ # build fuzzers pushd tests/fuzzing -cmake -DBOLOS_SDK=../../BOLOS_SDK -Bbuild -H. -make -C build -mv ./build/fuzz_app_eth "${OUT}" +cmake -DBOLOS_SDK=$(pwd)/../../BOLOS_SDK -B build -S . +cmake --build build +mv ./build/fuzzer "${OUT}" popd diff --git a/.gitignore b/.gitignore index 019c7207d..ed206c628 100644 --- a/.gitignore +++ b/.gitignore @@ -16,4 +16,11 @@ __version__.py .vscode .idea -fuzzing/CORPUS/ \ No newline at end of file +# Fuzzing +tests/fuzzing/corpus/ +tests/fuzzing/out/ +default.profraw +default.profdata +fuzz-*.log +crash-* +report.html diff --git a/fuzzing/CMakeLists.txt b/fuzzing/CMakeLists.txt deleted file mode 100644 index 5dcefbb46..000000000 --- a/fuzzing/CMakeLists.txt +++ /dev/null @@ -1,200 +0,0 @@ -cmake_minimum_required(VERSION 3.14) - -if(${CMAKE_VERSION} VERSION_LESS 3.14) - cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}) -endif() - -# project information -project(FuzzWithdraw - VERSION 1.0 - DESCRIPTION "Fuzzing of Ethereum app" - LANGUAGES C) - -# guard against bad build-type strings -if (NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE "Debug") -endif() - -if (NOT CMAKE_C_COMPILER_ID MATCHES "Clang") - message(FATAL_ERROR "Fuzzer needs to be built with Clang") -endif() - -# default fuzz device target -if (NOT TARGET_DEVICE) - set(TARGET_DEVICE "flex") -endif() - -set(BOLOS_SDK /opt/${TARGET_DEVICE}-secure-sdk) -if (NOT DEFINED BOLOS_SDK) - message(FATAL_ERROR "BOLOS_SDK environment variable not found.") -endif() - -# compatible with ClusterFuzzLite -if (NOT DEFINED ENV{LIB_FUZZING_ENGINE}) - set(COMPILATION_FLAGS -std=gnu99 -Wall -Wextra -pedantic -fshort-enums -Wno-unused-parameter -Wno-embedded-directive -g -O0 -fsanitize=fuzzer,address,undefined -fprofile-instr-generate -fcoverage-mapping) -else() - set(COMPILATION_FLAGS $ENV{LIB_FUZZING_ENGINE} $ENV{CXXFLAGS}) -endif() - -set(DEFINES - gcc - APPNAME=\"Fuzzing\" - API_LEVEL=21 - TARGET=\"flex\" - TARGET_NAME=\"TARGET_FLEX\" - APPVERSION=\"1.1.0\" - SDK_NAME=\"ledger-secure-sdk\" - SDK_VERSION=\"v21.3.3\" - SDK_HASH=\"d88d4db3c93665f52b5b1f45099d9d36dfaa06ba\" - gcc - __IO=volatile - NDEBUG - HAVE_BAGL_FONT_INTER_REGULAR_28PX - HAVE_BAGL_FONT_INTER_SEMIBOLD_28PX - HAVE_BAGL_FONT_INTER_MEDIUM_36PX - HAVE_INAPP_BLE_PAIRING - HAVE_NBGL - HAVE_PIEZO_SOUND - HAVE_SE_TOUCH - HAVE_SE_EINK_DISPLAY - NBGL_PAGE - NBGL_USE_CASE - SCREEN_SIZE_WALLET - HAVE_FAST_HOLD_TO_APPROVE - HAVE_LEDGER_PKI - HAVE_NES_CRYPT - HAVE_ST_AES - NATIVE_LITTLE_ENDIAN - HAVE_CRC - HAVE_HASH - HAVE_RIPEMD160 - HAVE_SHA224 - HAVE_SHA256 - HAVE_SHA3 - HAVE_SHA384 - HAVE_SHA512 - HAVE_SHA512_WITH_BLOCK_ALT_METHOD - HAVE_SHA512_WITH_BLOCK_ALT_METHOD_M0 - HAVE_BLAKE2 - HAVE_HMAC - HAVE_PBKDF2 - HAVE_AES - HAVE_MATH - HAVE_RNG - HAVE_RNG_RFC6979 - HAVE_RNG_SP800_90A - HAVE_ECC - HAVE_ECC_WEIERSTRASS - HAVE_ECC_TWISTED_EDWARDS - HAVE_ECC_MONTGOMERY - HAVE_SECP256K1_CURVE - HAVE_SECP256R1_CURVE - HAVE_SECP384R1_CURVE - HAVE_SECP521R1_CURVE - HAVE_FR256V1_CURVE - HAVE_STARK256_CURVE - HAVE_BRAINPOOL_P256R1_CURVE - HAVE_BRAINPOOL_P256T1_CURVE - HAVE_BRAINPOOL_P320R1_CURVE - HAVE_BRAINPOOL_P320T1_CURVE - HAVE_BRAINPOOL_P384R1_CURVE - HAVE_BRAINPOOL_P384T1_CURVE - HAVE_BRAINPOOL_P512R1_CURVE - HAVE_BRAINPOOL_P512T1_CURVE - HAVE_BLS12_381_G1_CURVE - HAVE_CV25519_CURVE - HAVE_CV448_CURVE - HAVE_ED25519_CURVE - HAVE_ED448_CURVE - HAVE_ECDH - HAVE_ECDSA - HAVE_EDDSA - HAVE_ECSCHNORR - HAVE_X25519 - HAVE_X448 - HAVE_AES_GCM - HAVE_CMAC - HAVE_AES_SIV - COIN_VARIANT=1 - HAVE_BOLOS_APP_STACK_CANARY - IO_SEPROXYHAL_BUFFER_SIZE_B=300 - HAVE_BLE - BLE_COMMAND_TIMEOUT_MS=2000 - HAVE_BLE_APDU - BLE_SEGMENT_SIZE=32 - HAVE_DEBUG_THROWS - NBGL_QRCODE - MAJOR_VERSION=1 - MINOR_VERSION=1 - PATCH_VERSION=0 - IO_HID_EP_LENGTH=64 - HAVE_SPRINTF - HAVE_SNPRINTF_FORMAT_U - HAVE_IO_USB - HAVE_L4_USBLIB - IO_USB_MAX_ENDPOINTS=4 - HAVE_USB_APDU - USB_SEGMENT_SIZE=64 - HAVE_WEBUSB - WEBUSB_URL_SIZE_B=0 - WEBUSB_URL= - OS_IO_SEPROXYHAL - STANDARD_APP_SYNC_RAPDU - HAVE_GENERIC_TX_PARSER - HAVE_TRUSTED_NAME - HAVE_DYN_MEM_ALLOC - HAVE_SWAP - HAVE_ENUM_VALUE - HAVE_NFT_SUPPORT -) - -add_compile_definitions(${DEFINES}) - -include_directories( - ${CMAKE_SOURCE_DIR}/../ethereum-plugin-sdk/src/ - ${CMAKE_SOURCE_DIR}/../src - ${CMAKE_SOURCE_DIR}/../src_features/generic_tx_parser/ - ${CMAKE_SOURCE_DIR}/../src_features/provide_enum_value/ - ${CMAKE_SOURCE_DIR}/../src_features/provideDynamicNetwork/ - ${CMAKE_SOURCE_DIR}/../src_features/signTx/ - ${CMAKE_SOURCE_DIR}/../src_features/provideTrustedName/ - ${CMAKE_SOURCE_DIR}/../src_features/getChallenge/ - ${CMAKE_SOURCE_DIR}/../src_features/signMessageEIP712/ - ${BOLOS_SDK}/include - ${BOLOS_SDK}/target/${TARGET_DEVICE}/include - ${BOLOS_SDK}/lib_cxng/include - ${BOLOS_SDK}/lib_cxng/src - ${BOLOS_SDK}/lib_ux_nbgl - ${BOLOS_SDK}/lib_nbgl/include - ${BOLOS_SDK}/lib_standard_app/ - ./mock/ -) - -FILE(GLOB_RECURSE SDK_STD_SOURCES ${BOLOS_SDK}/lib_standard_app/*.c ${CMAKE_SOURCE_DIR}/../ethereum-plugin-sdk/src/*.c ./mock/mock.c) -list(REMOVE_ITEM SDK_STD_SOURCES ${BOLOS_SDK}/lib_standard_app/io.c ${CMAKE_SOURCE_DIR}/../ethereum-plugin-sdk/src/main.c ${BOLOS_SDK}/lib_standard_app/main.c ${BOLOS_SDK}/lib_standard_app/crypto_helpers.c) - -FILE(GLOB_RECURSE SOURCES - ${CMAKE_SOURCE_DIR}/../src_features/generic_tx_parser/*.c - ${CMAKE_SOURCE_DIR}/../src_features/provideTrustedName/*.c - ${CMAKE_SOURCE_DIR}/../src_features/getChallenge/*.c - ${CMAKE_SOURCE_DIR}/../src_features/provide_enum_value/*.c - ${CMAKE_SOURCE_DIR}/../src_features/provideDynamicNetwork/*.c - ${CMAKE_SOURCE_DIR}/../src/mem.c - ${CMAKE_SOURCE_DIR}/../src/mem_utils.c - ${CMAKE_SOURCE_DIR}/../src/network.c - ${CMAKE_SOURCE_DIR}/../src/tlv.c - ${CMAKE_SOURCE_DIR}/../src/tlv_apdu.c - ${CMAKE_SOURCE_DIR}/../src/uint128.c - ${CMAKE_SOURCE_DIR}/../src/uint256.c - ${CMAKE_SOURCE_DIR}/../src/time_format.c - ${CMAKE_SOURCE_DIR}/../src/uint_common.c - ${CMAKE_SOURCE_DIR}/../src/utils.c - ${CMAKE_SOURCE_DIR}/../src/manage_asset_info.c - ${CMAKE_SOURCE_DIR}/../src/hash_bytes.c -) - -add_executable(fuzzer_tlv fuzzer_tlv.c ${SDK_STD_SOURCES} ${SOURCES}) -target_link_libraries(fuzzer_tlv bsd) # strlcpy / strlcat - -target_compile_options(fuzzer_tlv PRIVATE ${COMPILATION_FLAGS}) -target_link_options(fuzzer_tlv PRIVATE ${COMPILATION_FLAGS}) \ No newline at end of file diff --git a/fuzzing/README.md b/fuzzing/README.md deleted file mode 100644 index 503fc4049..000000000 --- a/fuzzing/README.md +++ /dev/null @@ -1,21 +0,0 @@ -# Fuzzing ethereum app - -## Build - -The fuzzer can be built using the following commands from the app directory: -```bash -docker run --rm -it --user "$(id -u):$(id -g)" -v "$(realpath .):/app" ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder-legacy:latest bash - -apt install libbsd-dev - -cd fuzzing -cmake -DBOLOS_SDK=/opt/ledger-secure-sdk -DCMAKE_C_COMPILER=/usr/bin/clang -Bbuild -H. -cmake --build build -``` - -## Run - -The fuzzer can be run using the following commands from the fuzzing directory: -```bash -./build/fuzzer_tlv -max_len=8192 -``` diff --git a/fuzzing/coverage.sh b/fuzzing/coverage.sh deleted file mode 100755 index a6c2c3b93..000000000 --- a/fuzzing/coverage.sh +++ /dev/null @@ -1,3 +0,0 @@ -llvm-profdata merge -sparse *.profraw -o default.profdata -llvm-cov show build/fuzzer_tlv -instr-profile=default.profdata -format=html > report.html -llvm-cov report build/fuzzer_tlv -instr-profile=default.profdata diff --git a/fuzzing/fuzzer_tlv.c b/fuzzing/fuzzer_tlv.c deleted file mode 100644 index 6bc67087e..000000000 --- a/fuzzing/fuzzer_tlv.c +++ /dev/null @@ -1,93 +0,0 @@ -#include -#include - -#include "cmd_field.h" -#include "cmd_tx_info.h" -#include "cmd_enum_value.h" - -#include "gtp_field.h" -#include "gtp_tx_info.h" -#include "enum_value.h" - -#include "shared_context.h" -#include "tlv.h" - -cx_sha3_t sha3 = {0}; -unsigned char G_io_apdu_buffer[260]; -tmpContent_t tmpContent; -txContext_t txContext; -txContent_t txContent; -chain_config_t config = { - .coinName = "FUZZ", - .chainId = 0x42, -}; -const chain_config_t *chainConfig = &config; -uint8_t appState; -tmpCtx_t tmpCtx; -strings_t strings; - - -int fuzzGenericParserFieldCmd(const uint8_t *data, size_t size) { - s_field field = {0}; - s_field_ctx ctx = {0}; - ctx.field = &field; - - if (!tlv_parse(data, size, (f_tlv_data_handler)&handle_field_struct, &ctx)) - return 1; - - if (!verify_field_struct(&ctx)) - return 1; - - return format_field(&field); -} - -int fuzzGenericParserTxInfoCmd(const uint8_t *data, size_t size) { - s_tx_info tx_info = {0}; - s_tx_info_ctx ctx = {0}; - ctx.tx_info = &tx_info; - - if (!tlv_parse(data, size, (f_tlv_data_handler)&handle_tx_info_struct, &ctx)) - return 1; - - return verify_tx_info_struct(&ctx); -} - -int fuzzGenericParserEnumCmd(const uint8_t *data, size_t size) { - s_enum_value_ctx ctx = {0}; - - if (!tlv_parse(data, size, (f_tlv_data_handler)&handle_enum_value_struct, &ctx)) - return 1; - - return verify_enum_value_struct(&ctx); -} - -int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - explicit_bzero(&tmpContent, sizeof(tmpContent_t)); - explicit_bzero(&txContext, sizeof(txContext_t)); - explicit_bzero(&txContent, sizeof(txContent_t)); - explicit_bzero(&tmpCtx, sizeof(tmpCtx_t)); - explicit_bzero(&strings, sizeof(strings_t)); - explicit_bzero(&G_io_apdu_buffer, 260); - - txContext.content = &txContent; - txContext.sha3 = &sha3; - - if (size < 1) - return 0; - switch (data[0]) - { - case 0: - fuzzGenericParserFieldCmd(++data, --size); - break; - case 1: - fuzzGenericParserTxInfoCmd(++data, --size); - break; - case 2: - fuzzGenericParserEnumCmd(++data, --size); - break; - default: - return 0; - } - - return 0; -} diff --git a/fuzzing/mock/glyphs.h b/fuzzing/mock/glyphs.h deleted file mode 100644 index e69de29bb..000000000 diff --git a/fuzzing/mock/mock.c b/fuzzing/mock/mock.c deleted file mode 100644 index 36d687b38..000000000 --- a/fuzzing/mock/mock.c +++ /dev/null @@ -1,87 +0,0 @@ -#include - -#include "cx_errors.h" -#include "cx_sha256.h" -#include "cx_sha3.h" - -void *pic(void *addr) -{ - return addr; -} - -cx_err_t cx_sha256_init_no_throw(cx_sha256_t *hash) -{ - memset(hash, 0, sizeof(cx_sha256_t)); - return CX_OK; -} - -cx_err_t cx_sha3_init_no_throw(cx_sha3_t *hash PLENGTH(sizeof(cx_sha3_t)), size_t size) -{ - memset(hash, 0, sizeof(cx_sha3_t)); - return CX_OK; -} - -cx_err_t cx_hash_no_throw(cx_hash_t *hash, - uint32_t mode, - const uint8_t *in, - size_t len, - uint8_t *out, - size_t out_len) -{ - if (len > 0 && out_len > 0) - out[out_len - 1] = in[len - 1]; - return CX_OK; -} - -cx_err_t cx_math_mult_no_throw(uint8_t *r, const uint8_t *a, const uint8_t *b, size_t len) -{ - return CX_OK; -} - -void cx_rng_no_throw(uint8_t *buffer, size_t len) -{ - if (len > 0) - buffer[len - 1] = 0; -} - -uint16_t get_public_key(uint8_t *out, uint8_t outLength) { - if (outLength > 0) - out[outLength - 1] = 0; - return 0; -} - -void assert_exit(bool confirm) -{ - exit(1); -} - -cx_err_t cx_keccak_256_hash_iovec(const cx_iovec_t *iovec, - size_t iovec_len, - uint8_t digest[static CX_KECCAK_256_SIZE]) { - digest[CX_KECCAK_256_SIZE - 1] = 0; - return CX_OK; -} - -cx_err_t cx_sha256_hash_iovec(const cx_iovec_t *iovec, - size_t iovec_len, - uint8_t digest[static CX_SHA256_SIZE]) -{ - digest[CX_SHA256_SIZE - 1] = 0; - return CX_OK; -} - -int check_signature_with_pubkey(const char *tag, - uint8_t *buffer, - const uint8_t bufLen, - const uint8_t *PubKey, - const uint8_t keyLen, -#ifdef HAVE_LEDGER_PKI - const uint8_t keyUsageExp, -#endif - uint8_t *signature, - const uint8_t sigLen) { - return CX_OK; -} - -void ui_gcs_cleanup(void) { -} diff --git a/src_features/generic_tx_parser/cmd_tx_info.h b/src_features/generic_tx_parser/cmd_tx_info.h index 6f8d94607..d8c13442c 100644 --- a/src_features/generic_tx_parser/cmd_tx_info.h +++ b/src_features/generic_tx_parser/cmd_tx_info.h @@ -4,7 +4,6 @@ #include #include "gtp_tx_info.h" - bool verify_struct(const s_tx_info_ctx *context); uint16_t handle_tx_info(uint8_t p1, uint8_t p2, uint8_t lc, const uint8_t *payload); void gcs_cleanup(void); diff --git a/tests/fuzzing/CMakeLists.txt b/tests/fuzzing/CMakeLists.txt index 1a59c68f7..466765889 100644 --- a/tests/fuzzing/CMakeLists.txt +++ b/tests/fuzzing/CMakeLists.txt @@ -1,53 +1,48 @@ -cmake_minimum_required(VERSION 3.10) - -if(${CMAKE_VERSION} VERSION_LESS 3.10) - cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}) -endif() +cmake_minimum_required(VERSION 3.14) # project information -project(Fuzzer +project(EthereumAppFuzzer VERSION 1.0 DESCRIPTION "Eth Fuzzer" LANGUAGES C) -set(CMAKE_C_COMPILER clang) +if (NOT CMAKE_C_COMPILER_ID MATCHES "Clang") + message(FATAL_ERROR "Fuzzer needs to be built with Clang") +endif() + +# guard against bad build-type strings +if (NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE "Debug") +endif() + +# default fuzz device target +if (NOT TARGET_DEVICE) + set(TARGET_DEVICE "flex") +endif() -set(CMAKE_BUILD_TYPE "Debug") +if (NOT DEFINED BOLOS_SDK) + set(BOLOS_SDK /opt/${TARGET_DEVICE}-secure-sdk) +endif() # compatible with ClusterFuzzLite if (NOT DEFINED ENV{LIB_FUZZING_ENGINE}) - set(COMPILATION_FLAGS_ "-g -Wall -fsanitize=fuzzer,address,undefined") + set(COMPILATION_FLAGS -g -O0 -Wall -Wextra -fsanitize=fuzzer,address,undefined -fprofile-instr-generate -fcoverage-mapping) else() - set(COMPILATION_FLAGS_ "$ENV{LIB_FUZZING_ENGINE} $ENV{CXXFLAGS}") + set(COMPILATION_FLAGS "$ENV{LIB_FUZZING_ENGINE} $ENV{CFLAGS}") + separate_arguments(COMPILATION_FLAGS) endif() -set(CMAKE_EXPORT_COMPILE_COMMANDS ON) - -string(REPLACE " " ";" COMPILATION_FLAGS ${COMPILATION_FLAGS_}) - -# specify C standard -set(CMAKE_C_STANDARD 11) -set(CMAKE_C_STANDARD_REQUIRED True) -set(CMAKE_C_FLAGS_DEBUG - "${CMAKE_C_FLAGS_DEBUG} -Wall -Wextra -Wno-unused-function -DFUZZ -pedantic -g -O0" -) - # guard against in-source builds if(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR}) message(FATAL_ERROR "In-source builds not allowed. Please make a new directory (called a build directory) and run CMake from there. You may need to remove CMakeCache.txt. ") endif() -set(TARGET_DEVICE flex) -if (NOT DEFINED BOLOS_SDK) - message(FATAL_ERROR "BOLOS_SDK environment variable not found.") -endif() - set(DEFINES gcc APPNAME=\"Fuzzing\" API_LEVEL=21 TARGET=\"flex\" - TARGET_NAME=\"TARGET_FLEX\" + TARGET_NAME=\"TARGET_FUZZ\" APPVERSION=\"1.1.0\" SDK_NAME=\"ledger-secure-sdk\" SDK_VERSION=\"v21.3.3\" @@ -153,32 +148,64 @@ set(DEFINES HAVE_ENUM_VALUE HAVE_NFT_SUPPORT ) -set(DEFINE ${DEFINES} HAVE_PRINTF PRINTF=printf) add_compile_definitions(${DEFINES}) -FILE(GLOB_RECURSE SDK_STD_SOURCES ${BOLOS_SDK}/lib_standard_app/write.c src/mock.c) - +FILE( + GLOB_RECURSE SDK_STD_SOURCES + ${BOLOS_SDK}/lib_standard_app/*.c + ${CMAKE_SOURCE_DIR}/../../ethereum-plugin-sdk/src/*.c + ./src/mock.c +) +list( + REMOVE_ITEM SDK_STD_SOURCES + ${BOLOS_SDK}/lib_standard_app/io.c + ${CMAKE_SOURCE_DIR}/../../ethereum-plugin-sdk/src/main.c + ${BOLOS_SDK}/lib_standard_app/main.c + ${BOLOS_SDK}/lib_standard_app/crypto_helpers.c +) include_directories( ${CMAKE_SOURCE_DIR}/../../ethereum-plugin-sdk/src/ ${CMAKE_SOURCE_DIR}/../../src + ${CMAKE_SOURCE_DIR}/../../src_features/generic_tx_parser/ + ${CMAKE_SOURCE_DIR}/../../src_features/provide_enum_value/ ${CMAKE_SOURCE_DIR}/../../src_features/provideDynamicNetwork/ + ${CMAKE_SOURCE_DIR}/../../src_features/signTx/ + ${CMAKE_SOURCE_DIR}/../../src_features/provideTrustedName/ + ${CMAKE_SOURCE_DIR}/../../src_features/getChallenge/ + ${CMAKE_SOURCE_DIR}/../../src_features/signMessageEIP712/ ${BOLOS_SDK}/include - ${BOLOS_SDK}/lib_standard_app ${BOLOS_SDK}/target/${TARGET_DEVICE}/include ${BOLOS_SDK}/lib_cxng/include ${BOLOS_SDK}/lib_cxng/src ${BOLOS_SDK}/lib_ux_nbgl ${BOLOS_SDK}/lib_nbgl/include - ${CMAKE_SOURCE_DIR}/src + ${BOLOS_SDK}/lib_standard_app/ + ${CMAKE_SOURCE_DIR}/src/ ) FILE(GLOB_RECURSE SOURCES + ${CMAKE_SOURCE_DIR}/../../src_features/generic_tx_parser/*.c + ${CMAKE_SOURCE_DIR}/../../src_features/provideTrustedName/*.c + ${CMAKE_SOURCE_DIR}/../../src_features/getChallenge/*.c + ${CMAKE_SOURCE_DIR}/../../src_features/provide_enum_value/*.c ${CMAKE_SOURCE_DIR}/../../src_features/provideDynamicNetwork/*.c + ${CMAKE_SOURCE_DIR}/../../src_features/provideNFTInformation/*.c + ${CMAKE_SOURCE_DIR}/../../src/mem.c + ${CMAKE_SOURCE_DIR}/../../src/mem_utils.c + ${CMAKE_SOURCE_DIR}/../../src/network.c + ${CMAKE_SOURCE_DIR}/../../src/tlv.c + ${CMAKE_SOURCE_DIR}/../../src/tlv_apdu.c + ${CMAKE_SOURCE_DIR}/../../src/uint128.c + ${CMAKE_SOURCE_DIR}/../../src/uint256.c + ${CMAKE_SOURCE_DIR}/../../src/time_format.c + ${CMAKE_SOURCE_DIR}/../../src/uint_common.c + ${CMAKE_SOURCE_DIR}/../../src/utils.c + ${CMAKE_SOURCE_DIR}/../../src/manage_asset_info.c ${CMAKE_SOURCE_DIR}/../../src/hash_bytes.c ) -add_executable(fuzz_app_eth src/fuzz_app_eth.c ${SDK_STD_SOURCES} ${SOURCES}) -target_compile_options(fuzz_app_eth PUBLIC ${COMPILATION_FLAGS}) -target_link_options(fuzz_app_eth PUBLIC ${COMPILATION_FLAGS}) +add_executable(fuzzer src/fuzzer.c ${SDK_STD_SOURCES} ${SOURCES}) +target_compile_options(fuzzer PRIVATE ${COMPILATION_FLAGS}) +target_link_options(fuzzer PRIVATE ${COMPILATION_FLAGS}) diff --git a/tests/fuzzing/README.md b/tests/fuzzing/README.md index 43ad67b02..6db9fafe8 100644 --- a/tests/fuzzing/README.md +++ b/tests/fuzzing/README.md @@ -11,7 +11,6 @@ any kind of access violation, the fuzzing process is stopped, a report regarding and the input that triggered the bug is written to disk under the name `crash-*`. The vulnerable input file created can be passed as an argument to the fuzzer to triage the issue. -> **Note**: Usually we want to write a separate fuzz target for each functionality. ## Manual usage based on Ledger container @@ -37,18 +36,20 @@ Once in the container, go into the `tests/fuzzing` folder to compile the fuzzer: cd tests/fuzzing # cmake initialization -cmake -DBOLOS_SDK=/opt/ledger-secure-sdk -Bbuild -H. +cmake -DBOLOS_SDK=/opt/ledger-secure-sdk -DCMAKE_C_COMPILER=/usr/bin/clang -Bbuild -S. # Fuzzer compilation -make -C build +cmake --build build ``` ### Run ```console -./build/fuzz_app_eth +./build/fuzzer -max_len=8192 ``` +If you want to do a fuzzing campain on more than one core and compute the coverage results, you can use the `local_run.sh` script within the container. + ## Full usage based on `clusterfuzzlite` container Exactly the same context as the CI, directly using the `clusterfuzzlite` environment. @@ -79,5 +80,5 @@ docker run --rm --privileged -e FUZZING_LANGUAGE=c -v "$(realpath .)/tests/fuzzi ### Run ```console -docker run --rm --privileged -e FUZZING_ENGINE=libfuzzer -e RUN_FUZZER_MODE=interactive -v "$(realpath .)/tests/fuzzing/corpus:/tmp/fuzz_corpus" -v "$(realpath .)/tests/fuzzing/out:/out" -ti gcr.io/oss-fuzz-base/base-runner run_fuzzer fuzz_app_eth +docker run --rm --privileged -e FUZZING_ENGINE=libfuzzer -e RUN_FUZZER_MODE=interactive -v "$(realpath .)/tests/fuzzing/corpus:/tmp/fuzz_corpus" -v "$(realpath .)/tests/fuzzing/out:/out" -ti gcr.io/oss-fuzz-base/base-runner run_fuzzer fuzzer ``` diff --git a/tests/fuzzing/src/fuzz_app_eth.c b/tests/fuzzing/src/fuzz_app_eth.c deleted file mode 100644 index c4f55501a..000000000 --- a/tests/fuzzing/src/fuzz_app_eth.c +++ /dev/null @@ -1,36 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include "shared_context.h" -#include "network_dynamic.h" - -unsigned char G_io_apdu_buffer[IO_APDU_BUFFER_SIZE]; -tmpContent_t tmpContent; -const chain_config_t *chainConfig; -txContext_t txContext; - -int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - explicit_bzero(G_io_apdu_buffer, 500); - explicit_bzero(&tmpContent, sizeof(tmpContent_t)); - explicit_bzero(&txContext, sizeof(txContext_t)); - size_t offset = 0; - size_t len = 0; - uint8_t p1; - uint8_t p2; - unsigned int tx; - - while (size - offset > 4) { - if (data[offset++] == 0) break; - p1 = data[offset++]; - p2 = data[offset++]; - len = data[offset++]; - if (size - offset < len) return 0; - handleNetworkConfiguration(p1, p2, data + offset, len, &tx); - offset += len; - } - return 0; -} diff --git a/tests/fuzzing/src/fuzzer.c b/tests/fuzzing/src/fuzzer.c new file mode 100644 index 000000000..3b024c80b --- /dev/null +++ b/tests/fuzzing/src/fuzzer.c @@ -0,0 +1,140 @@ +#include +#include + +#include "network_dynamic.h" + +#include "cmd_field.h" +#include "cmd_tx_info.h" +#include "cmd_enum_value.h" + +#include "gtp_field.h" +#include "gtp_tx_info.h" +#include "enum_value.h" + +#include "shared_context.h" +#include "tlv.h" +#include "apdu_constants.h" + +// Fuzzing harness interface +typedef int (*harness)(const uint8_t *data, size_t size); + +// Global state required by the app features +cx_sha3_t sha3; +unsigned char G_io_apdu_buffer[260]; +tmpContent_t tmpContent; +txContext_t txContext; +txContent_t txContent; +chain_config_t config = { + .coinName = "FUZZ", + .chainId = 0x42, +}; +const chain_config_t *chainConfig = &config; +uint8_t appState; +tmpCtx_t tmpCtx; +strings_t strings; + +int fuzzGenericParserFieldCmd(const uint8_t *data, size_t size) { + s_field field = {0}; + s_field_ctx ctx = {0}; + ctx.field = &field; + + if (!tlv_parse(data, size, (f_tlv_data_handler) &handle_field_struct, &ctx)) return 1; + + if (!verify_field_struct(&ctx)) return 1; + + return format_field(&field); +} + +int fuzzGenericParserTxInfoCmd(const uint8_t *data, size_t size) { + s_tx_info tx_info = {0}; + s_tx_info_ctx ctx = {0}; + ctx.tx_info = &tx_info; + + if (!tlv_parse(data, size, (f_tlv_data_handler) &handle_tx_info_struct, &ctx)) return 1; + + return verify_tx_info_struct(&ctx); +} + +int fuzzGenericParserEnumCmd(const uint8_t *data, size_t size) { + s_enum_value_ctx ctx = {0}; + + if (!tlv_parse(data, size, (f_tlv_data_handler) &handle_enum_value_struct, &ctx)) return 1; + + return verify_enum_value_struct(&ctx); +} + +int fuzzDynamicNetworks(const uint8_t *data, size_t size) { + size_t offset = 0; + size_t len = 0; + uint8_t p1; + uint8_t p2; + unsigned int tx; + + while (size - offset > 4) { + if (data[offset++] == 0) break; + p1 = data[offset++]; + p2 = data[offset++]; + len = data[offset++]; + if (size - offset < len) return 0; + if (handleNetworkConfiguration(p1, p2, data + offset, len, &tx) != APDU_RESPONSE_OK) + return 1; + offset += len; + } + return 0; +} + +int fuzzTrustedNames(const uint8_t *data, size_t size) { + size_t offset = 0; + size_t len = 0; + uint8_t p1; + + while (size - offset > 3) { + if (data[offset++] == 0) break; + p1 = data[offset++]; + len = data[offset++]; + if (size - offset < len) return 0; + if (handle_provide_trusted_name(p1, data + offset, len) != APDU_RESPONSE_OK) return 1; + offset += len; + } + return 0; +} + +int fuzzNFTInfo(const uint8_t *data, size_t size) { + unsigned int tx; + return handleProvideNFTInformation(data, size, &tx) != APDU_RESPONSE_OK; +} + +// Array of fuzzing harness functions +harness harnesses[] = { + fuzzGenericParserFieldCmd, + fuzzGenericParserTxInfoCmd, + fuzzGenericParserEnumCmd, + fuzzDynamicNetworks, + fuzzTrustedNames, + fuzzNFTInfo, +}; + +/* Main fuzzing handler called by libfuzzer */ +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + // Clear global structures to ensure a clean state for each fuzzing iteration + explicit_bzero(&tmpContent, sizeof(tmpContent_t)); + explicit_bzero(&txContext, sizeof(txContext_t)); + explicit_bzero(&txContent, sizeof(txContent_t)); + explicit_bzero(&tmpCtx, sizeof(tmpCtx_t)); + explicit_bzero(&strings, sizeof(strings_t)); + explicit_bzero(&G_io_apdu_buffer, 260); + explicit_bzero(&sha3, sizeof(sha3)); + + uint8_t target; + + txContext.content = &txContent; + txContext.sha3 = &sha3; + + // Determine which harness function to call based on the first byte of data + if (size < 1) return 0; + target = data[0]; + if (target >= sizeof(harnesses) / sizeof(harnesses[0])) return 0; + + // Call the selected harness function with the remaining data (which can be of size 0) + return harnesses[target](++data, --size); +} diff --git a/tests/fuzzing/src/mock.c b/tests/fuzzing/src/mock.c index 7328a6adc..2e8d8ab86 100644 --- a/tests/fuzzing/src/mock.c +++ b/tests/fuzzing/src/mock.c @@ -1,14 +1,29 @@ +#include #include #include "cx_errors.h" #include "cx_sha256.h" #include "cx_sha3.h" +size_t strlcpy(char *dst, const char *src, size_t size) { + return strncpy(dst, src, size); +} + +size_t strlcat(char *dst, const char *src, size_t size) { + return strncat(dst, src, size); +} + cx_err_t cx_sha256_init_no_throw(cx_sha256_t *hash) { memset(hash, 0, sizeof(cx_sha256_t)); return CX_OK; } +cx_err_t cx_sha3_init_no_throw(cx_sha3_t *hash PLENGTH(sizeof(cx_sha3_t)), size_t size) { + UNUSED(size); + memset(hash, 0, sizeof(cx_sha3_t)); + return CX_OK; +} + cx_err_t cx_hash_no_throw(cx_hash_t *hash, uint32_t mode, const uint8_t *in, @@ -67,44 +82,31 @@ int check_signature_with_pubkey(const char *tag, return CX_OK; } -uint64_t u64_from_BE(const uint8_t *in, uint8_t size) { - uint8_t i = 0; - uint64_t res = 0; +void *pic(void *addr) { + return addr; +} - while (i < size && i < sizeof(res)) { - res <<= 8; - res |= in[i]; - i++; - } +cx_err_t cx_math_mult_no_throw(uint8_t *r, const uint8_t *a, const uint8_t *b, size_t len) { + UNUSED(r); + UNUSED(a); + UNUSED(b); + UNUSED(len); + return CX_OK; +} + +void cx_rng_no_throw(uint8_t *buffer, size_t len) { + if (len > 0) buffer[len - 1] = 0; +} - return res; +uint16_t get_public_key(uint8_t *out, uint8_t outLength) { + if (outLength > 0) out[outLength - 1] = 0; + return 0; } -bool u64_to_string(uint64_t src, char *dst, uint8_t dst_size) { - // Copy the numbers in ASCII format. - uint8_t i = 0; - do { - // Checking `i + 1` to make sure we have enough space for '\0'. - if (i + 1 >= dst_size) { - return false; - } - dst[i] = src % 10 + '0'; - src /= 10; - i++; - } while (src); - - // Null terminate string - dst[i] = '\0'; - - // Revert the string - i--; - uint8_t j = 0; - while (j < i) { - char tmp = dst[i]; - dst[i] = dst[j]; - dst[j] = tmp; - i--; - j++; - } - return true; +void ui_gcs_cleanup(void) { +} + +size_t cx_hash_sha256(const uint8_t *in, size_t in_len, uint8_t *out, size_t out_len) { + if (in_len > 0 && out_len > 0) out[out_len - 1] = in[in_len - 1]; + return CX_OK; } From a133e8c87f89da67b491bc5f9f99dc6ef3d0cee8 Mon Sep 17 00:00:00 2001 From: Baptistin BOILOT Date: Fri, 27 Dec 2024 14:33:50 +0100 Subject: [PATCH 07/25] test: add a script to run the fuzzer and compute the coverage (cherry picked from commit f86eb28696deff2aa3a5e843eb42638c6cc9d18d) --- tests/fuzzing/local_run.sh | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100755 tests/fuzzing/local_run.sh diff --git a/tests/fuzzing/local_run.sh b/tests/fuzzing/local_run.sh new file mode 100755 index 000000000..e76ee005b --- /dev/null +++ b/tests/fuzzing/local_run.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +# Clean +rm -rf build + +# Build the fuzzer +cmake -B build -S . -DCMAKE_C_COMPILER=/usr/bin/clang +cmake --build build + +# Create the corpus directory if it doesn't exist +if ! [ -d ./corpus ]; then + mkdir corpus +fi + +# Run the fuzzer on half CPU cores +ncpus=$(nproc) +jobs=$(($ncpus/2)) +echo "The fuzzer will start very soon, press Ctrl-C when you want to stop it and compute the coverage" +./build/fuzzer -max_len=8192 -jobs="$jobs" ./corpus + + +read -p "Would you like to compute coverage (y/n)? " -n 1 -r +echo +if [[ $REPLY =~ ^[Nn]$ ]] +then + exit 0 +fi + +# Remove previous artifcats +rm default.profdata default.profraw + +# Run profiling on the corpus +./build/fuzzer -max_len=8192 -runs=0 ./corpus + +# Compute coverage +llvm-profdata merge -sparse *.profraw -o default.profdata +llvm-cov show build/fuzzer -instr-profile=default.profdata -format=html -ignore-filename-regex='ethereum-plugin-sdk\/|secure-sdk\/' > report.html +llvm-cov report build/fuzzer -instr-profile=default.profdata -ignore-filename-regex='ethereum-plugin-sdk\/|secure-sdk\/' From 1b6062689bddce2a00b139d5a6d7044250cd1f58 Mon Sep 17 00:00:00 2001 From: Baptistin BOILOT Date: Fri, 27 Dec 2024 16:49:02 +0100 Subject: [PATCH 08/25] fix: use a uninitialized values (cherry picked from commit d20c831cc24097efcb30b78b3c3a92151240162e) --- src_features/generic_tx_parser/gtp_param_datetime.c | 2 +- src_features/generic_tx_parser/gtp_param_duration.c | 2 +- src_features/generic_tx_parser/gtp_param_trusted_name.c | 2 +- src_features/generic_tx_parser/gtp_tx_info.c | 6 +++--- src_features/provideTrustedName/cmd_provide_trusted_name.c | 2 +- src_features/provide_enum_value/enum_value.c | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src_features/generic_tx_parser/gtp_param_datetime.c b/src_features/generic_tx_parser/gtp_param_datetime.c index ca3fdade0..2242aded1 100644 --- a/src_features/generic_tx_parser/gtp_param_datetime.c +++ b/src_features/generic_tx_parser/gtp_param_datetime.c @@ -68,7 +68,7 @@ bool format_param_datetime(const s_param_datetime *param, const char *name) { s_parsed_value_collection collec; char *buf = strings.tmp.tmp; size_t buf_size = sizeof(strings.tmp.tmp); - uint8_t time_buf[sizeof(uint32_t)]; + uint8_t time_buf[sizeof(uint32_t)] = {0}; time_t timestamp; uint256_t block_height; diff --git a/src_features/generic_tx_parser/gtp_param_duration.c b/src_features/generic_tx_parser/gtp_param_duration.c index d55a94e58..01eae53a5 100644 --- a/src_features/generic_tx_parser/gtp_param_duration.c +++ b/src_features/generic_tx_parser/gtp_param_duration.c @@ -60,7 +60,7 @@ bool format_param_duration(const s_param_duration *param, const char *name) { uint8_t minutes; uint8_t seconds; uint64_t remaining; - uint8_t raw_buf[sizeof(remaining)]; + uint8_t raw_buf[sizeof(remaining)] = {0}; int off; if (!value_get(¶m->value, &collec)) { diff --git a/src_features/generic_tx_parser/gtp_param_trusted_name.c b/src_features/generic_tx_parser/gtp_param_trusted_name.c index 5fffb9fe2..4c6c27989 100644 --- a/src_features/generic_tx_parser/gtp_param_trusted_name.c +++ b/src_features/generic_tx_parser/gtp_param_trusted_name.c @@ -78,7 +78,7 @@ bool format_param_trusted_name(const s_param_trusted_name *param, const char *na char *buf = strings.tmp.tmp; size_t buf_size = sizeof(strings.tmp.tmp); uint64_t chain_id; - uint8_t addr[ADDRESS_LENGTH]; + uint8_t addr[ADDRESS_LENGTH] = {0}; const char *tname; e_param_type param_type; diff --git a/src_features/generic_tx_parser/gtp_tx_info.c b/src_features/generic_tx_parser/gtp_tx_info.c index 7913ab08d..bb523ff54 100644 --- a/src_features/generic_tx_parser/gtp_tx_info.c +++ b/src_features/generic_tx_parser/gtp_tx_info.c @@ -55,7 +55,7 @@ static bool handle_version(const s_tlv_data *data, s_tx_info_ctx *context) { static bool handle_chain_id(const s_tlv_data *data, s_tx_info_ctx *context) { uint64_t chain_id; - uint8_t buf[sizeof(chain_id)]; + uint8_t buf[sizeof(chain_id)] = {0}; if (data->length > sizeof(buf)) { return false; @@ -72,7 +72,7 @@ static bool handle_chain_id(const s_tlv_data *data, s_tx_info_ctx *context) { } static bool handle_contract_addr(const s_tlv_data *data, s_tx_info_ctx *context) { - uint8_t buf[ADDRESS_LENGTH]; + uint8_t buf[ADDRESS_LENGTH] = {0}; if (data->length > sizeof(buf)) { return false; @@ -165,7 +165,7 @@ static bool handle_contract_name(const s_tlv_data *data, s_tx_info_ctx *context) } static bool handle_deploy_date(const s_tlv_data *data, s_tx_info_ctx *context) { - uint8_t buf[sizeof(uint32_t)]; + uint8_t buf[sizeof(uint32_t)] = {0}; time_t timestamp; if (data->length > sizeof(buf)) { diff --git a/src_features/provideTrustedName/cmd_provide_trusted_name.c b/src_features/provideTrustedName/cmd_provide_trusted_name.c index a540c2369..d0015e973 100644 --- a/src_features/provideTrustedName/cmd_provide_trusted_name.c +++ b/src_features/provideTrustedName/cmd_provide_trusted_name.c @@ -822,7 +822,7 @@ static bool parse_tlv(const s_tlv_payload *payload, {.tag = NFT_ID, .func = &handle_nft_id}, }; e_tlv_step step = TLV_TAG; - s_tlv_data data; + s_tlv_data data = {0}; size_t offset = 0; size_t tag_start_off; diff --git a/src_features/provide_enum_value/enum_value.c b/src_features/provide_enum_value/enum_value.c index 64cf2fc30..db0dfb9a1 100644 --- a/src_features/provide_enum_value/enum_value.c +++ b/src_features/provide_enum_value/enum_value.c @@ -28,7 +28,7 @@ static bool handle_version(const s_tlv_data *data, s_enum_value_ctx *context) { } static bool handle_chain_id(const s_tlv_data *data, s_enum_value_ctx *context) { - uint8_t buf[sizeof(context->enum_value.entry.chain_id)]; + uint8_t buf[sizeof(context->enum_value.entry.chain_id)] = {0}; if (data->length > sizeof(buf)) { return false; From 7aabca972222519d98e1c3c034af3d5f4c3d1d8a Mon Sep 17 00:00:00 2001 From: Baptistin BOILOT Date: Mon, 30 Dec 2024 17:57:07 +0100 Subject: [PATCH 09/25] fix: improve the mocks to avoid false positives (cherry picked from commit 649aa607371d7f10c890cf23d1de483a45adeb98) --- tests/fuzzing/src/mock.c | 71 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 65 insertions(+), 6 deletions(-) diff --git a/tests/fuzzing/src/mock.c b/tests/fuzzing/src/mock.c index 2e8d8ab86..09a2a4a87 100644 --- a/tests/fuzzing/src/mock.c +++ b/tests/fuzzing/src/mock.c @@ -5,12 +5,67 @@ #include "cx_sha256.h" #include "cx_sha3.h" +#define explicit_bzero(X, Y) memset_s(X, 0, Y) + +/** MemorySanitizer does not wrap explicit_bzero https://github.com/google/sanitizers/issues/1507 + * which results in false positives when running MemorySanitizer. + */ +void memset_s(void *buffer, char c, size_t n) { + if (buffer == NULL) return; + + volatile char *ptr = buffer; + while (n--) *ptr++ = c; +} + size_t strlcpy(char *dst, const char *src, size_t size) { - return strncpy(dst, src, size); + const char *s = src; + size_t n = size; + + if (n != 0) { + while (--n != 0) { + if ((*dst++ = *s++) == '\0') { + break; + } + } + } + + if (n == 0) { + if (size != 0) { + *dst = '\0'; + } + while (*s++) + ; + } + + return (s - src - 1); } size_t strlcat(char *dst, const char *src, size_t size) { - return strncat(dst, src, size); + char *d = dst; + const char *s = src; + size_t n = size; + size_t dsize; + + while (n-- != 0 && *d != '\0') { + d++; + } + dsize = d - dst; + n = size - dsize; + + if (n == 0) { + return (dsize + strlen(s)); + } + + while (*s != '\0') { + if (n != 1) { + *d++ = *s; + n--; + } + s++; + } + *d = '\0'; + + return (dsize + (s - src)); } cx_err_t cx_sha256_init_no_throw(cx_sha256_t *hash) { @@ -32,6 +87,8 @@ cx_err_t cx_hash_no_throw(cx_hash_t *hash, size_t out_len) { UNUSED(hash); UNUSED(mode); + explicit_bzero(out, out_len); // let's initialize the buffer + // if arrays are not empty, read the last element of in and write it in the last element of out if (len > 0 && out_len > 0) out[out_len - 1] = in[len - 1]; return CX_OK; } @@ -46,7 +103,7 @@ cx_err_t cx_keccak_256_hash_iovec(const cx_iovec_t *iovec, uint8_t digest[static CX_KECCAK_256_SIZE]) { UNUSED(iovec); UNUSED(iovec_len); - digest[CX_KECCAK_256_SIZE - 1] = 0; + explicit_bzero(digest, CX_SHA256_SIZE); return CX_OK; } @@ -55,7 +112,7 @@ cx_err_t cx_sha256_hash_iovec(const cx_iovec_t *iovec, uint8_t digest[static CX_SHA256_SIZE]) { UNUSED(iovec); UNUSED(iovec_len); - digest[CX_SHA256_SIZE - 1] = 0; + explicit_bzero(digest, CX_SHA256_SIZE); return CX_OK; } @@ -95,11 +152,11 @@ cx_err_t cx_math_mult_no_throw(uint8_t *r, const uint8_t *a, const uint8_t *b, s } void cx_rng_no_throw(uint8_t *buffer, size_t len) { - if (len > 0) buffer[len - 1] = 0; + explicit_bzero(buffer, len); } uint16_t get_public_key(uint8_t *out, uint8_t outLength) { - if (outLength > 0) out[outLength - 1] = 0; + explicit_bzero(out, outLength); return 0; } @@ -107,6 +164,8 @@ void ui_gcs_cleanup(void) { } size_t cx_hash_sha256(const uint8_t *in, size_t in_len, uint8_t *out, size_t out_len) { + explicit_bzero(out, out_len); // let's initialize the buffer + // if arrays are not empty, read the last element of in and write it in the last element of out if (in_len > 0 && out_len > 0) out[out_len - 1] = in[in_len - 1]; return CX_OK; } From 4edb5e6730e8a11966d3d7f233329b42e16ef61a Mon Sep 17 00:00:00 2001 From: Baptistin BOILOT Date: Mon, 30 Dec 2024 17:58:24 +0100 Subject: [PATCH 10/25] build: support msan and asan for fuzzing locally (cherry picked from commit 3a1dd71c34e56ebf7d2deb58b8fc0dee373a0aec) --- tests/fuzzing/CMakeLists.txt | 9 ++++++++- tests/fuzzing/README.md | 4 ++-- tests/fuzzing/local_run.sh | 2 +- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/tests/fuzzing/CMakeLists.txt b/tests/fuzzing/CMakeLists.txt index 466765889..f27ae3401 100644 --- a/tests/fuzzing/CMakeLists.txt +++ b/tests/fuzzing/CMakeLists.txt @@ -26,7 +26,14 @@ endif() # compatible with ClusterFuzzLite if (NOT DEFINED ENV{LIB_FUZZING_ENGINE}) - set(COMPILATION_FLAGS -g -O0 -Wall -Wextra -fsanitize=fuzzer,address,undefined -fprofile-instr-generate -fcoverage-mapping) + set(COMPILATION_FLAGS -g -O0 -Wall -Wextra -fprofile-instr-generate -fcoverage-mapping) + if (SANITIZER MATCHES "address") + set(COMPILATION_FLAGS ${COMPILATION_FLAGS} -fsanitize=fuzzer,address,undefined) + elseif (SANITIZER MATCHES "memory") + set(COMPILATION_FLAGS ${COMPILATION_FLAGS} -fsanitize=fuzzer,memory,undefined -fsanitize-memory-track-origins -fsanitize=fuzzer-no-link) + else() + message(FATAL_ERROR "Unkown sanitizer type. It must be set to `address` or `memory`.") + endif() else() set(COMPILATION_FLAGS "$ENV{LIB_FUZZING_ENGINE} $ENV{CFLAGS}") separate_arguments(COMPILATION_FLAGS) diff --git a/tests/fuzzing/README.md b/tests/fuzzing/README.md index 6db9fafe8..89db1e283 100644 --- a/tests/fuzzing/README.md +++ b/tests/fuzzing/README.md @@ -36,7 +36,7 @@ Once in the container, go into the `tests/fuzzing` folder to compile the fuzzer: cd tests/fuzzing # cmake initialization -cmake -DBOLOS_SDK=/opt/ledger-secure-sdk -DCMAKE_C_COMPILER=/usr/bin/clang -Bbuild -S. +cmake -DBOLOS_SDK=/opt/ledger-secure-sdk -DCMAKE_C_COMPILER=/usr/bin/clang -DSANITIZER=[address|memory] -B build -S . # Fuzzer compilation cmake --build build @@ -48,7 +48,7 @@ cmake --build build ./build/fuzzer -max_len=8192 ``` -If you want to do a fuzzing campain on more than one core and compute the coverage results, you can use the `local_run.sh` script within the container. +If you want to do a fuzzing campain on more than one core and compute the coverage results, you can use the `local_run.sh` script within the container (it'll only run the address and UB sanitizers). ## Full usage based on `clusterfuzzlite` container diff --git a/tests/fuzzing/local_run.sh b/tests/fuzzing/local_run.sh index e76ee005b..cbc179247 100755 --- a/tests/fuzzing/local_run.sh +++ b/tests/fuzzing/local_run.sh @@ -4,7 +4,7 @@ rm -rf build # Build the fuzzer -cmake -B build -S . -DCMAKE_C_COMPILER=/usr/bin/clang +cmake -B build -S . -DCMAKE_C_COMPILER=/usr/bin/clang -DSANITIZER=address cmake --build build # Create the corpus directory if it doesn't exist From d2093d74bc57ce14584e7bf1fe3d5082ec063819 Mon Sep 17 00:00:00 2001 From: Baptistin BOILOT Date: Thu, 2 Jan 2025 17:07:41 +0100 Subject: [PATCH 11/25] refactor: remove explicit_bzero macro in fuzzing mocks (cherry picked from commit 0ff2f9491f6ae0a4a8d2f32de717c62742dbd2be) --- tests/fuzzing/src/mock.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/tests/fuzzing/src/mock.c b/tests/fuzzing/src/mock.c index 09a2a4a87..cfcd65c83 100644 --- a/tests/fuzzing/src/mock.c +++ b/tests/fuzzing/src/mock.c @@ -5,8 +5,6 @@ #include "cx_sha256.h" #include "cx_sha3.h" -#define explicit_bzero(X, Y) memset_s(X, 0, Y) - /** MemorySanitizer does not wrap explicit_bzero https://github.com/google/sanitizers/issues/1507 * which results in false positives when running MemorySanitizer. */ @@ -69,13 +67,13 @@ size_t strlcat(char *dst, const char *src, size_t size) { } cx_err_t cx_sha256_init_no_throw(cx_sha256_t *hash) { - memset(hash, 0, sizeof(cx_sha256_t)); + memset_s(hash, 0, sizeof(cx_sha256_t)); return CX_OK; } cx_err_t cx_sha3_init_no_throw(cx_sha3_t *hash PLENGTH(sizeof(cx_sha3_t)), size_t size) { UNUSED(size); - memset(hash, 0, sizeof(cx_sha3_t)); + memset_s(hash, 0, sizeof(cx_sha3_t)); return CX_OK; } @@ -87,7 +85,7 @@ cx_err_t cx_hash_no_throw(cx_hash_t *hash, size_t out_len) { UNUSED(hash); UNUSED(mode); - explicit_bzero(out, out_len); // let's initialize the buffer + memset_s(out, 0, out_len); // let's initialize the buffer // if arrays are not empty, read the last element of in and write it in the last element of out if (len > 0 && out_len > 0) out[out_len - 1] = in[len - 1]; return CX_OK; @@ -103,7 +101,7 @@ cx_err_t cx_keccak_256_hash_iovec(const cx_iovec_t *iovec, uint8_t digest[static CX_KECCAK_256_SIZE]) { UNUSED(iovec); UNUSED(iovec_len); - explicit_bzero(digest, CX_SHA256_SIZE); + memset_s(digest, 0, CX_SHA256_SIZE); return CX_OK; } @@ -112,7 +110,7 @@ cx_err_t cx_sha256_hash_iovec(const cx_iovec_t *iovec, uint8_t digest[static CX_SHA256_SIZE]) { UNUSED(iovec); UNUSED(iovec_len); - explicit_bzero(digest, CX_SHA256_SIZE); + memset_s(digest, 0, CX_SHA256_SIZE); return CX_OK; } @@ -152,11 +150,11 @@ cx_err_t cx_math_mult_no_throw(uint8_t *r, const uint8_t *a, const uint8_t *b, s } void cx_rng_no_throw(uint8_t *buffer, size_t len) { - explicit_bzero(buffer, len); + memset_s(buffer, 0, len); } uint16_t get_public_key(uint8_t *out, uint8_t outLength) { - explicit_bzero(out, outLength); + memset_s(out, 0, outLength); return 0; } @@ -164,7 +162,7 @@ void ui_gcs_cleanup(void) { } size_t cx_hash_sha256(const uint8_t *in, size_t in_len, uint8_t *out, size_t out_len) { - explicit_bzero(out, out_len); // let's initialize the buffer + memset_s(out, 0, out_len); // let's initialize the buffer // if arrays are not empty, read the last element of in and write it in the last element of out if (in_len > 0 && out_len > 0) out[out_len - 1] = in[in_len - 1]; return CX_OK; From fcd4024d813197d5bfc0fdd226dcf76845a49e6e Mon Sep 17 00:00:00 2001 From: Alexandre Paillier Date: Thu, 9 Jan 2025 14:14:33 +0100 Subject: [PATCH 12/25] Changed "Domain Name" to "Trusted Name" in PKI printf (cherry picked from commit b0d9bb981a7915ec0a1764d25712e7b6f02f587b) --- src_features/provideTrustedName/cmd_provide_trusted_name.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src_features/provideTrustedName/cmd_provide_trusted_name.c b/src_features/provideTrustedName/cmd_provide_trusted_name.c index d0015e973..ffb98e671 100644 --- a/src_features/provideTrustedName/cmd_provide_trusted_name.c +++ b/src_features/provideTrustedName/cmd_provide_trusted_name.c @@ -613,7 +613,7 @@ static bool verify_signature(const s_sig_ctx *sig_ctx) { CX_CHECK( cx_hash_no_throw((cx_hash_t *) &sig_ctx->hash_ctx, CX_LAST, NULL, 0, hash, INT256_LENGTH)); - CX_CHECK(check_signature_with_pubkey("Domain Name", + CX_CHECK(check_signature_with_pubkey("Trusted Name", hash, sizeof(hash), pk, From cf4e1af2f46be094b5c61f58ea4fa38e8956714d Mon Sep 17 00:00:00 2001 From: Alexandre Paillier Date: Thu, 9 Jan 2025 11:33:18 +0100 Subject: [PATCH 13/25] Fix trusted name PKI depending on name source in Python client (cherry picked from commit 21d52943066c505f3609788b0652b0faabf37362) --- .../src/ledger_app_clients/ethereum/client.py | 41 ++++++++++++------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/client/src/ledger_app_clients/ethereum/client.py b/client/src/ledger_app_clients/ethereum/client.py index a26404d74..fac250354 100644 --- a/client/src/ledger_app_clients/ethereum/client.py +++ b/client/src/ledger_app_clients/ethereum/client.py @@ -272,28 +272,39 @@ def perform_privacy_operation(self, pubkey)) def _provide_trusted_name_common(self, payload: bytes, name_source: TrustedNameSource) -> RAPDU: - if self._pki_client is None: - print(f"Ledger-PKI Not supported on '{self._firmware.name}'") - else: - # pylint: disable=line-too-long - if self._firmware == Firmware.NANOSP: - cert_apdu = "01010102010210040102000011040000000212010013020002140101160400000000200b446f6d61696e5f4e616d6530020007310108320121332102b91fbec173e3ba4a714e014ebc827b6f899a9fa7f4ac769cde284317a00f4f653401013501031546304402201b5188f5af5cd4d40d2e5eee85609323ee129b789082d079644c89c0df9b6ce0022076c5d26bb5c8db8ab02771ecd577f63f68eaf1c90523173f161f9c12f6e978bd" # noqa: E501 - elif self._firmware == Firmware.NANOX: - cert_apdu = "01010102010211040000000212010013020002140101160400000000200B446F6D61696E5F4E616D6530020007310108320121332102B91FBEC173E3BA4A714E014EBC827B6F899A9FA7F4AC769CDE284317A00F4F653401013501021546304402202CD052029B756890F0C56713409C58C24785FEFFD1A997E9C840A7BDB176B512022059A30E04E491CD27BD1DA1B5CB810CF8E4EAE67F6406F054FDFC371F7EB9F2C4" # noqa: E501 - elif self._firmware == Firmware.STAX: - cert_apdu = "01010102010211040000000212010013020002140101160400000000200B446F6D61696E5F4E616D6530020007310108320121332102B91FBEC173E3BA4A714E014EBC827B6F899A9FA7F4AC769CDE284317A00F4F65340101350104154630440220741DB4E738749D4188436419B20B9AEF8F07581312A9B3C9BAA3F3E879690F6002204C4A3510569247777BC43DB830D129ACA8985B88552E2E234E14D8AA2863026B" # noqa: E501 - elif self._firmware == Firmware.FLEX: - cert_apdu = "01010102010211040000000212010013020002140101160400000000200B446F6D61696E5F4E616D6530020007310108320121332102B91FBEC173E3BA4A714E014EBC827B6F899A9FA7F4AC769CDE284317A00F4F65340101350105154730450221008B6BBCE1716C0A06F110C77FE181F8395D1692441459A106411463F01A45D4A7022044AB69037E6FA9D1D1A409E00B202C2D4451D464C8E5D4962D509FE63153FE93" # noqa: E501 - # pylint: enable=line-too-long - - self._pki_client.send_certificate(PKIPubKeyUsage.PUBKEY_USAGE_COIN_META, bytes.fromhex(cert_apdu)) payload += format_tlv(FieldTag.STRUCT_TYPE, 3) # TrustedName if name_source == TrustedNameSource.CAL: + if self._pki_client is not None: + # pylint: disable=line-too-long + if self._firmware == Firmware.NANOSP: + cert_apdu = "010101020102110400000002120100130200021401011604000000002010547275737465645F4E616D655F43414C300200073101043201213321024CCA8FAD496AA5040A00A7EB2F5CC3B85376D88BA147A7D7054A99C64056188734010135010315473045022100CD7F858EDED3A6F2EFECA4D7392618533FDD13BB9920C2CA9AD551B2C3C45D1A022041AAE52DCB50BD9E97D859417D5DA1463AB2A8CBF30B9D06DBF7C84863E6076D" # noqa: E501 + elif self._firmware == Firmware.NANOX: + cert_apdu = "010101020102110400000002120100130200021401011604000000002010547275737465645F4E616D655F43414C300200073101043201213321024CCA8FAD496AA5040A00A7EB2F5CC3B85376D88BA147A7D7054A99C64056188734010135010215473045022100E017EA39279846D531D3A7986178B2A2E25ECA27D89C3C75B61FF936C1A5E78E02202C5F6686186A9314A1DCCF9292F9494C3DA4C1568ED020DD7941D60B39A7C95C" # noqa: E501 + elif self._firmware == Firmware.STAX: + cert_apdu = "010101020102110400000002120100130200021401011604000000002010547275737465645F4E616D655F43414C300200073101043201213321024CCA8FAD496AA5040A00A7EB2F5CC3B85376D88BA147A7D7054A99C64056188734010135010415473045022100D072546754CEDC1A94C1821A998900C1022D109AFC8FA83D534C1D9193D9EEEC022056906F4A0FDCC7EB5AD37874E556DE4925AD0C654831DB255FDACFAF339AE9B6" # noqa: E501 + elif self._firmware == Firmware.FLEX: + cert_apdu = "010101020102110400000002120100130200021401011604000000002010547275737465645F4E616D655F43414C300200073101043201213321024CCA8FAD496AA5040A00A7EB2F5CC3B85376D88BA147A7D7054A99C6405618873401013501051546304402206FB5CBEDAC961D6D64750FC6AFF1C2797B1C6809CC42FAEAA44D15398A3E20D5022042B53D6C0D07703FAC2B2A70864178F82B0AEDC4C451AB438AE7D1883714C5A9" # noqa: E501 + # pylint: enable=line-too-long key_id = 6 key = Key.CAL else: + if self._pki_client is not None: + # pylint: disable=line-too-long + if self._firmware == Firmware.NANOSP: + cert_apdu = "01010102010211040000000212010013020002140101160400000000200C547275737465645F4E616D6530020007310104320121332102B91FBEC173E3BA4A714E014EBC827B6F899A9FA7F4AC769CDE284317A00F4F6534010135010315473045022100F394484C045418507E0F76A3231F233B920C733D3E5BB68AFBAA80A55195F70D022012BC1FD796CD2081D8355DEEFA051FBB9329E34826FF3125098F4C6A0C29992A" # noqa: E501 + elif self._firmware == Firmware.NANOX: + cert_apdu = "01010102010211040000000212010013020002140101160400000000200C547275737465645F4E616D6530020007310104320121332102B91FBEC173E3BA4A714E014EBC827B6F899A9FA7F4AC769CDE284317A00F4F65340101350102154730450221009D97646C49EE771BE56C321AB59C732E10D5D363EBB9944BF284A3A04EC5A14102200633518E851984A7EA00C5F81EDA9DAA58B4A6C98E57DA1FBB9074AEFF0FE49F" # noqa: E501 + elif self._firmware == Firmware.STAX: + cert_apdu = "01010102010211040000000212010013020002140101160400000000200C547275737465645F4E616D6530020007310104320121332102B91FBEC173E3BA4A714E014EBC827B6F899A9FA7F4AC769CDE284317A00F4F6534010135010415473045022100A57DC7AB3F0E38A8D10783C7449024D929C60843BB75E5FF7B8088CB71CB130C022045A03E6F501F3702871466473BA08CE1F111357ED9EF395959733477165924C4" # noqa: E501 + elif self._firmware == Firmware.FLEX: + cert_apdu = "01010102010211040000000212010013020002140101160400000000200C547275737465645F4E616D6530020007310104320121332102B91FBEC173E3BA4A714E014EBC827B6F899A9FA7F4AC769CDE284317A00F4F6534010135010515473045022100D5BB77756C3D7C1B4254EA8D5351B94A89B13BA69C3631A523F293A10B7144B302201519B29A882BB22DCDDF6BE79A9CBA76566717FA877B7CA4B9CC40361A2D579E" # noqa: E501 + # pylint: enable=line-too-long key_id = 3 key = Key.TRUSTED_NAME + + if self._pki_client is not None: + self._pki_client.send_certificate(PKIPubKeyUsage.PUBKEY_USAGE_TRUSTED_NAME, bytes.fromhex(cert_apdu)) + payload += format_tlv(FieldTag.SIGNER_KEY_ID, key_id) # test key payload += format_tlv(FieldTag.SIGNER_ALGO, 1) # secp256k1 payload += format_tlv(FieldTag.DER_SIGNATURE, From 79c180d1b1146c71017a5781672160bba6a0572a Mon Sep 17 00:00:00 2001 From: Alexandre Paillier Date: Tue, 14 Jan 2025 17:34:01 +0100 Subject: [PATCH 14/25] Removed hardcoded contract list from ERC-20 internal plugin (cherry picked from commit 3da3968cf095bc93cf9889419f11ee09518b5a7c) --- src_plugins/erc20/erc20_plugin.c | 78 +++----------------------------- 1 file changed, 6 insertions(+), 72 deletions(-) diff --git a/src_plugins/erc20/erc20_plugin.c b/src_plugins/erc20/erc20_plugin.c index c7a5af884..b15268c33 100644 --- a/src_plugins/erc20/erc20_plugin.c +++ b/src_plugins/erc20/erc20_plugin.c @@ -7,8 +7,6 @@ typedef enum { ERC20_TRANSFER = 0, ERC20_APPROVE } erc20Selector_t; -typedef enum { TARGET_ADDRESS = 0, TARGET_CONTRACT } targetType_t; - #define MAX_CONTRACT_NAME_LEN 15 typedef struct erc20_parameters_t { @@ -17,61 +15,9 @@ typedef struct erc20_parameters_t { uint8_t amount[INT256_LENGTH]; char ticker[MAX_TICKER_LEN]; uint8_t decimals; - uint8_t target; char contract_name[MAX_CONTRACT_NAME_LEN]; } erc20_parameters_t; -typedef struct contract_t { - char name[MAX_CONTRACT_NAME_LEN]; - uint8_t address[ADDRESS_LENGTH]; -} contract_t; - -#define NUM_CONTRACTS 13 -const contract_t CONTRACTS[NUM_CONTRACTS] = { - // Compound - {"Compound DAI", {0x5d, 0x3a, 0x53, 0x6e, 0x4d, 0x6d, 0xbd, 0x61, 0x14, 0xcc, - 0x1e, 0xad, 0x35, 0x77, 0x7b, 0xab, 0x94, 0x8e, 0x36, 0x43}}, - {"Compound ETH", {0x4d, 0xdc, 0x2d, 0x19, 0x39, 0x48, 0x92, 0x6d, 0x02, 0xf9, - 0xb1, 0xfe, 0x9e, 0x1d, 0xaa, 0x07, 0x18, 0x27, 0x0e, 0xd5}}, - {"Compound USDC", {0x39, 0xaa, 0x39, 0xc0, 0x21, 0xdf, 0xba, 0xe8, 0xfa, 0xc5, - 0x45, 0x93, 0x66, 0x93, 0xac, 0x91, 0x7d, 0x5e, 0x75, 0x63}}, - {"Compound ZRX", {0xb3, 0x31, 0x9f, 0x5d, 0x18, 0xbc, 0x0d, 0x84, 0xdd, 0x1b, - 0x48, 0x25, 0xdc, 0xde, 0x5d, 0x5f, 0x72, 0x66, 0xd4, 0x07}}, - {"Compound USDT", {0xf6, 0x50, 0xc3, 0xd8, 0x8d, 0x12, 0xdb, 0x85, 0x5b, 0x8b, - 0xf7, 0xd1, 0x1b, 0xe6, 0xc5, 0x5a, 0x4e, 0x07, 0xdc, 0xc9}}, - {"Compound WBTC", {0xc1, 0x1b, 0x12, 0x68, 0xc1, 0xa3, 0x84, 0xe5, 0x5c, 0x48, - 0xc2, 0x39, 0x1d, 0x8d, 0x48, 0x02, 0x64, 0xa3, 0xa7, 0xf4}}, - {"Compound BAT", {0x6c, 0x8c, 0x6b, 0x02, 0xe7, 0xb2, 0xbe, 0x14, 0xd4, 0xfa, - 0x60, 0x22, 0xdf, 0xd6, 0xd7, 0x59, 0x21, 0xd9, 0x0e, 0x4e}}, - {"Compound REP", {0x15, 0x80, 0x79, 0xee, 0x67, 0xfc, 0xe2, 0xf5, 0x84, 0x72, - 0xa9, 0x65, 0x84, 0xa7, 0x3c, 0x7a, 0xb9, 0xac, 0x95, 0xc1}}, - {"Compound SAI", {0xf5, 0xdc, 0xe5, 0x72, 0x82, 0xa5, 0x84, 0xd2, 0x74, 0x6f, - 0xaf, 0x15, 0x93, 0xd3, 0x12, 0x1f, 0xca, 0xc4, 0x44, 0xdc}}, - {"Compound UNI", {0x35, 0xa1, 0x80, 0x00, 0x23, 0x0d, 0xa7, 0x75, 0xca, 0xc2, - 0x48, 0x73, 0xd0, 0x0f, 0xf8, 0x5b, 0xcc, 0xde, 0xd5, 0x50}}, - // Paraswap - {"Paraswap", {0x1b, 0xd4, 0x35, 0xf3, 0xc0, 0x54, 0xb6, 0xe9, 0x01, 0xb7, - 0xb1, 0x08, 0xa0, 0xab, 0x76, 0x17, 0xc8, 0x08, 0x67, 0x7b}}, - - // stETH - {"Lido", {0x7f, 0x39, 0xc5, 0x81, 0xf5, 0x95, 0xb5, 0x3c, 0x5c, 0xb1, - 0x9b, 0xd0, 0xb3, 0xf8, 0xda, 0x6c, 0x93, 0x5e, 0x2c, 0xa0}}, - - // wstETH - {"Wrapped stETH", {0xae, 0x7a, 0xb9, 0x65, 0x20, 0xde, 0x3a, 0x18, 0xe5, 0xe1, - 0x11, 0xb5, 0xea, 0xab, 0x09, 0x53, 0x12, 0xd7, 0xfe, 0x84}}}; - -bool check_contract(erc20_parameters_t *context) { - for (size_t i = 0; i < NUM_CONTRACTS; i++) { - const contract_t *contract = (const contract_t *) PIC(&CONTRACTS[i]); - if (memcmp(contract->address, context->destinationAddress, ADDRESS_LENGTH) == 0) { - strlcpy(context->contract_name, contract->name, sizeof(context->contract_name)); - return true; - } - } - return false; -} - void erc20_plugin_call(int message, void *parameters) { switch (message) { case ETH_PLUGIN_INIT_CONTRACT: { @@ -148,14 +94,8 @@ void erc20_plugin_call(int message, void *parameters) { (msg->item1 != NULL), (msg->item2 != NULL)); if (msg->item1 != NULL) { - context->target = TARGET_ADDRESS; strlcpy(context->ticker, msg->item1->token.ticker, MAX_TICKER_LEN); context->decimals = msg->item1->token.decimals; - if (context->selectorIndex == ERC20_APPROVE) { - if (check_contract(context)) { - context->target = TARGET_CONTRACT; - } - } msg->result = ETH_PLUGIN_RESULT_OK; } else { msg->result = ETH_PLUGIN_RESULT_FALLBACK; @@ -196,19 +136,13 @@ void erc20_plugin_call(int message, void *parameters) { msg->result = ETH_PLUGIN_RESULT_OK; break; case 1: - if (context->target >= TARGET_CONTRACT) { - strlcpy(msg->title, "Contract", msg->titleLength); - strlcpy(msg->msg, context->contract_name, msg->msgLength); - } else { - strlcpy(msg->title, "Approve to", msg->titleLength); - if (!getEthDisplayableAddress(context->destinationAddress, - msg->msg, - msg->msgLength, - chainConfig->chainId)) { - msg->result = ETH_PLUGIN_RESULT_ERROR; - } + strlcpy(msg->title, "Approve to", msg->titleLength); + if (!getEthDisplayableAddress(context->destinationAddress, + msg->msg, + msg->msgLength, + chainConfig->chainId)) { + msg->result = ETH_PLUGIN_RESULT_ERROR; } - msg->result = ETH_PLUGIN_RESULT_OK; break; default: From b91e420cf31541b69b12de5198a00629c26399eb Mon Sep 17 00:00:00 2001 From: Victor Forgeoux <100780559+vforgeoux-ledger@users.noreply.github.com> Date: Thu, 23 Jan 2025 15:43:04 +0100 Subject: [PATCH 15/25] Update networks & clones (#713) * update devices list in the Readme * add Lumia as new network * add Odyssey Chain as new network * add swellchain and swellchain testnet as new networks * replace Klaytn network with Kaia * add Harmony One S0 and S1 as new networks * add Sonic as new network * add Bahamut as new network * fix some glyphs * add Soneium and Soneium Testnet as new networks * Remove some unused clones * add harmony as new clone * move chain 1946 gif to the right folder * remove .DS_Store file (cherry picked from commit 6611aaa3ce4700273fcead180d1d1942ec48b9a7) --- README.md | 2 +- glyphs/chain_146_64px.gif | Bin 0 -> 604 bytes glyphs/chain_153153_64px.gif | Bin 0 -> 902 bytes glyphs/chain_1666600000_64px.gif | Bin 0 -> 964 bytes glyphs/chain_1666600001_64px.gif | 1 + glyphs/chain_1868_64px.gif | Bin 0 -> 511 bytes glyphs/chain_1923_64px.gif | Bin 0 -> 529 bytes glyphs/chain_1924_64px.gif | 1 + glyphs/chain_1946_64px.gif | 1 + glyphs/chain_246785_64px.gif | Bin 985 -> 0 bytes glyphs/chain_5165_64px.gif | Bin 0 -> 587 bytes glyphs/chain_8217_64px.gif | Bin 660 -> 485 bytes glyphs/chain_994873017_64px.gif | Bin 0 -> 443 bytes icons/flex_app_chain_1666600000.gif | Bin 0 -> 584 bytes icons/flex_app_chain_20531811.gif | Bin 536 -> 0 bytes icons/flex_app_chain_246785.gif | Bin 669 -> 0 bytes icons/flex_app_chain_73799.gif | Bin 464 -> 0 bytes icons/nanos_app_chain_1666600000.gif | Bin 0 -> 87 bytes icons/nanos_app_chain_20531811.gif | Bin 1124 -> 0 bytes icons/nanos_app_chain_246785.gif | Bin 71 -> 0 bytes icons/nanos_app_chain_73799.gif | Bin 1131 -> 0 bytes icons/nanox_app_chain_1666600000.gif | Bin 0 -> 76 bytes icons/nanox_app_chain_20531811.gif | Bin 98 -> 0 bytes icons/nanox_app_chain_246785.gif | Bin 69 -> 0 bytes icons/nanox_app_chain_73799.gif | Bin 61 -> 0 bytes icons/stax_app_chain_1666600000.gif | Bin 0 -> 492 bytes icons/stax_app_chain_20531811.gif | Bin 174 -> 0 bytes icons/stax_app_chain_246785.gif | Bin 481 -> 0 bytes icons/stax_app_chain_73799.gif | Bin 158 -> 0 bytes makefile_conf/chain/artis_tau1.mk | 4 ---- makefile_conf/chain/harmony.mk | 4 ++++ makefile_conf/chain/tecratestnet.mk | 4 ---- makefile_conf/chain/volta.mk | 4 ---- src/network.c | 12 +++++++++++- 34 files changed, 19 insertions(+), 14 deletions(-) create mode 100644 glyphs/chain_146_64px.gif create mode 100644 glyphs/chain_153153_64px.gif create mode 100644 glyphs/chain_1666600000_64px.gif create mode 120000 glyphs/chain_1666600001_64px.gif create mode 100644 glyphs/chain_1868_64px.gif create mode 100644 glyphs/chain_1923_64px.gif create mode 120000 glyphs/chain_1924_64px.gif create mode 120000 glyphs/chain_1946_64px.gif delete mode 100644 glyphs/chain_246785_64px.gif create mode 100644 glyphs/chain_5165_64px.gif create mode 100644 glyphs/chain_994873017_64px.gif create mode 100644 icons/flex_app_chain_1666600000.gif delete mode 100644 icons/flex_app_chain_20531811.gif delete mode 100644 icons/flex_app_chain_246785.gif delete mode 100644 icons/flex_app_chain_73799.gif create mode 100644 icons/nanos_app_chain_1666600000.gif delete mode 100644 icons/nanos_app_chain_20531811.gif delete mode 100644 icons/nanos_app_chain_246785.gif delete mode 100644 icons/nanos_app_chain_73799.gif create mode 100644 icons/nanox_app_chain_1666600000.gif delete mode 100644 icons/nanox_app_chain_20531811.gif delete mode 100644 icons/nanox_app_chain_246785.gif delete mode 100644 icons/nanox_app_chain_73799.gif create mode 100644 icons/stax_app_chain_1666600000.gif delete mode 100644 icons/stax_app_chain_20531811.gif delete mode 100644 icons/stax_app_chain_246785.gif delete mode 100644 icons/stax_app_chain_73799.gif delete mode 100644 makefile_conf/chain/artis_tau1.mk create mode 100644 makefile_conf/chain/harmony.mk delete mode 100644 makefile_conf/chain/tecratestnet.mk delete mode 100644 makefile_conf/chain/volta.mk diff --git a/README.md b/README.md index f356b91d9..14d991c11 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ ## About the project -Ethereum wallet application framework for Nano S, Nano S Plus and Nano X. +Ethereum wallet application framework for Ledger Nano S, Ledger Nano S Plus, Ledger Nano X, Ledger Flex and Ledger Stax. Ledger Blue is not maintained anymore, but the app can still be compiled for this target using the branch [`blue-final-release`](https://github.com/LedgerHQ/app-ethereum/tree/blue-final-release). ## Documentation diff --git a/glyphs/chain_146_64px.gif b/glyphs/chain_146_64px.gif new file mode 100644 index 0000000000000000000000000000000000000000..f77a2e9661153148a61d78c49c69679f5c5dad0b GIT binary patch literal 604 zcmV-i0;By$Nk%w1VL$*t0P_F<6ciL6A0I3%EI&U#PEJl=Ute!;Z-0M(kdTnGv$May zztPdr-{0T=|Nj6000000A^8LV00000EC2ui06+jh000F4u*pfQy*TU5yZ>M)j$~<` zXsWJk>%K6@EOgDpBadJySumeiXP_{pHW-M+Byr7} z0|sPlK>!H4jReq4Cx~I>CIK#|(*<`f22TWPd45>|2rmqSP6dW#h+2UtY7Gc;L68${ zlURT$3-JsV8Buo3BaGmAC6ge6*_IgvP+)@Ig(ig;tK{vu3+$>t{w@WTjDwp?Azu? z90zif{#}xFK}Ugn0Ca@_hl|v{DhM8;3cCjs*RE@oJepq>wrBR%4Zk^m(Jk_$KJ zNIe##0s%2EO%Of38LfCCLoV|AZhZ=#HSXgW|TB71VTg# zEyVniKqD53Ao?ZbB6i0>9tA}>^~1J8$s*d=`LQbEYqE3S+$htF$lVBDSQO=Dmc|=J zLM)j-=Hv zictsw00cr|C`?n{(y0o3(7G=ePgcW$PALI!$!rQ{MWd#nC^WBFU_oJ%niy8BZ%qDO z3sLW*VK6U+ytusQ1_lgWDYy=p`~NI;0cb`iN=$%>e{}+BB8E(GijzHvjvx$&E^)weSZT42G!)$*MLjB8&svj;^pwivAJ??TpD0@r_$62{{H~UDf457 zPzD8|_KiCRuwlb$1LrJJkb#XpVGE5p-1yHNHi~4Ig{ReD34wx7wRgId?5@aK&4n!1~m3jj+Si| z6lj`L)T+Ov3(~4hy44y1r(-ErFfdk5*4fR$#@!d>a>piwXC-! z_Ru)A72~|Ub~S6abKH#n%_F#Q;>DNhKK9xU$tgClvPP&GqN*P4zPme`{S2rb0$2s%&Ex>UslwHm^{3ROgYFHso)DDanoiZsSJZm zqJDmoj-4A!MHQsw$pTk4JdW~bcBUkQZb)j4`%6M;(IteIm z7$n6nS8zfJAB?_Q!U^6)QpOlrcxfy%4pb!DY!+KQ`zs1`O?$-?G+3*~8Vu|}haF=K cVSugQu7m9g*u?;ax9P?!@4WQZ`#}T%JGN<%w*UYD literal 0 HcmV?d00001 diff --git a/glyphs/chain_1666600000_64px.gif b/glyphs/chain_1666600000_64px.gif new file mode 100644 index 0000000000000000000000000000000000000000..ebe181085db3cb1f061c202cbd63c7d954168281 GIT binary patch literal 964 zcmV;#13UajNk%w1VL$*t0P_F<1qB5R3=9?)7Aq?&QBhHBY;28zJ&(F{3=;-wH z^!obx|Ns900000000000A^8LV00000A^!_WZDD6+O<`wgV`~m)VQp<;JuogbH8eFe zH2^FC0000$06+i$1pbi8Nvpj$>&?6WU?`5eI}}{6 zY8MEpnJ=LXMyUV>7Ydg@0tXqRRluUIN(FHhc|nO42vk4?8@J8R46{K9yB4HC#udz} z<;Uj$1GN;|Kz)9x$`s=O1k)K(nC=q?lDJh6)=Zod0v-M+N%s#E!wmPZRfw1n&_f0Q zgIv5Y41h#?{?J5Zc>Fkz~TCa<8ZFf3EbLnFz-4778C zrGhkpwA`RjD72Ux<{-5<)z8bPM6-4Dne@j}t0b|W)Nr)Q#|Z`KoXybm2TmnmGA#14 zmchNRY;O)7Yau}yFI=grbQzXH&SDg#7$6YRO5K@EuNsbNWU(*0Kk)^1%V5{xN0-k8 zcw7@tDgri8r`FSGaa9Rv2Unn>0txHeKbRCyGi-F`vojDZHiWxQfC0M|K!J?5^a8)O zi{EadDVBtuq*Wp)5ZXj0-o+%7Hm- z;#CO#q6s){0q_=o8=#lj7uAJQ;DLN?;GbP*2oXj}dWpr3e6YPnp%nyNc)^2v>C}OO zU0vf(Ns{dsp$6jwHs3c)WjGmvFnSnUZuPL$q6CL=c%F`MtvI5ME}FD}q zL2-Vlijfwq(~br3{9u52(9px85{D|%Q9gY=3Md8ZTscrGaa~|SrSh1QjB;jTs?P*u z*a0XRfDCF2E}c#wg)gld<%@w7z5n=}m6siXwbPj|qV0V159c!>eAzX9@Wur0028|^^J@G literal 0 HcmV?d00001 diff --git a/glyphs/chain_1666600001_64px.gif b/glyphs/chain_1666600001_64px.gif new file mode 120000 index 000000000..96de1d4cd --- /dev/null +++ b/glyphs/chain_1666600001_64px.gif @@ -0,0 +1 @@ +chain_1666600000_64px.gif \ No newline at end of file diff --git a/glyphs/chain_1868_64px.gif b/glyphs/chain_1868_64px.gif new file mode 100644 index 0000000000000000000000000000000000000000..b5cabbf72068264a37d361d140cdcba399b30020 GIT binary patch literal 511 zcmZ?wbhEHbbYO5`_{;zTTwGid5)yiPdI<>$^XJdMa^=d47cV}4{`~*{f3Q3Xq4<*p z%+~>tATtu@@g36a?5$KV#vTDmC${#`w vN7Q6FCNO_+XN={wm}+zLSnp*vm&tKwcWr%reM9o;dA_^1<#Gu!FjxZspWD-m literal 0 HcmV?d00001 diff --git a/glyphs/chain_1923_64px.gif b/glyphs/chain_1923_64px.gif new file mode 100644 index 0000000000000000000000000000000000000000..5e6cd050e60438eb7494377c10bef0ae4c4b70e6 GIT binary patch literal 529 zcmV+s0`C1sNk%w1VL$*t0P+O@0000G5D+3FB2-jVsHmv_|Nrmr@7>+qA^8LV00000 zEC2ui06+jh000C3Si0Q)Fv>}*y*TU5yZ;a|2ml}qhXJn4F$6&g!~m)ttaFfZUkbPf zAwXaZOM{$Z=WCjRjRT;lFa!i5Vvgx-0v&{@s$d`#rG)W^+x0@pXvTN|cz4)sw{hxt zQP(_qU0-l~3kGz59(aOIe_;b=MFIhlW{ZK1JtqWjQZhh3NgRxVm7P^;WJ)cWd7LV$ ztPrJ6k#@5ZwW4XVxe>cEk-r$hC5prp#sdbv$+WIL!x;x6BLdhbkeFSxjd%~D^#ngZ8kf#@aPWMCU9es(CXS;|8GzIr^%rDM#8 zhDMzHs~R1U|?XLo}SRq(C6pp^Yioh`T76< z{{R30000000000000000A^8LV00000A^!_WZDD6+O<`wgV`~m)VQp<;JuogbH8eFe zH2^FC0000$06+i$1pZLTNvpj$>&?6WU?`4cX`X0WCR}nH#=)v0nA0(LYBX>J66F$gn~5(ou^js^${jZZ@~2AEF-GYX}q2?YaR1e!Mr1z-e} zD2+j0iWLb4t8N1YrwXB91)C=agaHM%#uEmEU5RBD2!{Z@i72txyUD;Tf}#Rs!4!=? zo(qR00Y~R*=W@+>KYJ8@KV4wUeW`7)ouUY#}HVJ!?c}7B#Awheo_B3>)yM`7%tr zZ5vhD&Uj`g1B|D_j@zxM$S~Ux21#hZDKw)%cfmM5!^#cI;|}|3p(+5L?TNNCat~fJ zlw)B2Aj&UCQRk3bfDjZ^c2@AEiD};@7Tz_gz|$R43`*b{Y?X=8N`4f)g@|h8U1N+v zPRV7PNMwMZ6D|s3cT_*^@v@#2#e8tZBL)n$oFsFBg$Z+C5V%w&*0Chxb{2ZDjWQKx z0^&;Gp%aJ(( zR6HRd&l>RHH>EJ;xi$hLPB?YL6_~v7iz{vJQQ8O%-DQQBA~9FYCLB_LloThlG+l_0 ziJ|F(*F}*WNAy$>%NxtAV&6fUS{D*#CRpM{ilXjgNfvn&`UeZX-KPS2*YwDVjH_$y zK-wI?T!s)RG$qu;st5wxn6X6!H3no^nvw$`e*D1L9BlFfs27hclSL4GZ7UI+RiG5b zxxX>i#1=sK@JM$mh#1DcKrq)XBrlvYXqZ9t+XoM66=+5XIUJDW#29C+@x~l??D5AR HM*sjjv>us8 diff --git a/glyphs/chain_5165_64px.gif b/glyphs/chain_5165_64px.gif new file mode 100644 index 0000000000000000000000000000000000000000..03839c7b815e4750ba54e744b152d72a3c922b4c GIT binary patch literal 587 zcmV-R0<`@{Nk%w1VL$*t0P_m~D=RBaO-)xM)j-;lX z=vl6nk{pLY41y5ccs&pXoG7f0;!wB&j>x2P3Ahmsz+fd&WLmGwKp`PrC=A%J7-@)> z5P`8eEZ~yR>-aT*7$M~NYaNtG=l@9oZbAZphDZWt8(@b?PX%%Y9SMy|2NMT!gBg&O zbQOhbk|utKf))gE0g4uxjcpbRrD}T^orVLf5~*?p8liv$x(lvy0vWP~z88IYs~D7k zqp`qvn-q6{ml%wHwH3vx+ZWk@;}zX&pBTx8(-pUBry0D;81-X`8sWhh18c%I#3(?( z#;i31FjT`*VAzHe2@u3sXysU}gI3D5tUg)UJMA0h* zY&8m-p;??|7KF-?SpiNY4E*qX1Lrf$Ic)AS#9cFY0!cjjE~s6TQ^HL#^DH!7tMaSe zk6evuSS*HY3#@?9Uf5ewR|3az?w*YE)Nfr?OBYa{)AsaP4u8jt*aPk1R{C~0jvUE4JHCHEU%482nJx(;H_~Ez;{gKEOKO4A1zE&_Giu<- ZLA5}Sq`}LZND*JY{rmXy>z5J%06QL1{xbjo literal 0 HcmV?d00001 diff --git a/glyphs/chain_8217_64px.gif b/glyphs/chain_8217_64px.gif index 787694c2369a29983419ebe913c8ae731dd3ba1d..d6db41dcbe7b10eeffb6261a280a9af01b14a38e 100644 GIT binary patch literal 485 zcmZ?wbhEHbbYO5`_{_?{!ongVBBG|ImXMI};lqdj|NlRE^5pR0!*l1(Wxxg$f3mPJ z0VQ-mk{~k}SpIJ~;kkOR#p|=X|0ihlrMN3JFIbmVFl9q22P4CkvOMKNe;)I>2FG7d z<=L`OD8Qs^!s*n@KNUF^1!Zw`$g(ZF)w^&uZ~2ZC#Tzw}%iFWdSTD*dy!)}+ah;=f ze2r4L7bA0{as*4eQbf0sg;!Ufd~;meWVt#gy%{p8*i><6n?itKN{eGg>panOFu7|&O$u;n7Ne%d9jdw;Y%~PC zWq95s9h0a$JfDsEb3|@W>Xx(TYTWF$7JDWhGgW7qbWNgRB7<&bh|;p)g|B?iX?d=- zEfES?8<3Khn^gPiTMmbIX7^1|#WK$A+dkeK%K;PfrdU|>g5D+jhFd!fx@9*!gudlzq zzt7LlprD|TkdOcX0RR90A^8LV00000EC2ui06+jh000F4@X1N5y*TU5yZ>M)j-)p@ zg&`2hP`+K@%(P=PF05Ba?K=U*Zm0Me0lA^6A~PBZ$_|4;IXRt&WYoeqR2bK5LAd<_ zD~7PsfGAVIjzv{%WVvM_08EmJ z5|%RulqHUXbBCS}pfpgVK6-elqn~L$m?EWT6t!xpt3CoFxp5Q=eZIUuWFNz@5`0(4 zVVlfOj1q=dq7}bR1+yB%GmvUo+{srBQdiUy0Ac2p=vToT;xpG)SX!#{Vc=%81vC;* zk-sp@xTp!hW8XPRG}K+VN8{E5V+8qilf+PAIZi+S3etjD!+=LM*B)e}AyUG@KF%Z@ z(vqv?185{?Sm@JE!n+zaaprWelTN-@{8X(RO0)ueUC68KE(WoYzqWt)HMi}aPHk25cEJkon&?I9u}Ci zP(Ek%+8p4wA9@&hi1|#rmcS2IzX<-_`3HhQ0$6qTgMA~+Wnf6e=|I403$jAl4g&xO ukpK;DQ6YpmVF<_ti~Mwm01Zs|Az%#v@EA}A1i*rcC&nn_j5NLw0RTJm3>+i? diff --git a/glyphs/chain_994873017_64px.gif b/glyphs/chain_994873017_64px.gif new file mode 100644 index 0000000000000000000000000000000000000000..b4ab07b6bd88e0d0ac3d892a4dfb85e915f40fe8 GIT binary patch literal 443 zcmV;s0Yv^sNk%w1VL$*t0P_F<000072L}lW2^bg{FE1}*Vq&DEq|ngN|NsB~{{H#- z`SbJh=jZ1D0000000000A^8LZ00000EC2ui06+jh000F45Xniay*TU5yZ>M)j$~<` zXsWJk>%MR-&vgAN2ea6wQ5*$cNl;(_grft%pjax9A4Oq_00^KTqZ2^Ia;94V!Mj;- z!+^t+d;z1!Y)kWOFrN=`io$S41A=)I1ATRU01SZ$e1vvqfO!Olg@!w13@)@KDJx~vl0rry9Ozjr?Eu16b7uo zM2IDq1_lS&+S|Ps3QyeO2iL<%*bLg}IoUcL+v@P+TV!P@CW; z)&K(x)~EnzP@yqW2fx9n6$=owV>G@|B=zLs8D2bSp5PG0X%nhh3WX?G=7$TOlvozg zY2+#qf@PEL*enpu51d3abEdH=!3~o$1Bgn{5=HI5ao lh3w!`MyObSU1Tf#qolCc_-Me`6>OBzw06S8Vw`BkT literal 0 HcmV?d00001 diff --git a/icons/flex_app_chain_1666600000.gif b/icons/flex_app_chain_1666600000.gif new file mode 100644 index 0000000000000000000000000000000000000000..6575822e67d2bad28c6d1a6315ed7d5ddac9a7a4 GIT binary patch literal 584 zcmV-O0=NA~Nk%w1VJHA70P_F<0000C3=A0=87nI*O-)U4adDlUoz&FS=;-M4^Yi-p z`v3p`000000000000000A^8LV00000A^!_WZDD6+O<`wgV`~m)VQp<;JuogbH8eFe zH2^FC0000e04M+e1paWzNvpj$r&D?{hmuWOL7bn6aRT7FLV=9z3lm3DDaK$2Hr!?7 zv)Kj)g=%pa00Dvl!TBQ0DhI+VASJY5IY~kb2;dM2MDJzT6<)|0B3r#0zSf0K(sT{3 zd_@BX6lr7uZ3_lq7mH|n6bD}g5@dfC3YIQO6OICe76@bnnJ%ao2t}9^ZvcZB zr>SNut`xDe7X(17wHJK=uM)d}6~S7!!nv@1q!p&BsQ{}M!^I27jZXu%*I3TRj1_Ct z3&Ex1+t3thU+C)MF5294=RwulmF%$s1`PNzQl(lrG4TAHI8lV43q;D$>ESRX-b05k zq7)z$(HfH;*cLGw5kTMrppFFcIgBzuN)dnukX8GZZp)7WA1*CW(oR;iWWTCy!5Jo- zETB+}!W)@Bjb*A^8LV00000 zA^!_WZDD6+O<`wgV`~m)VQp<;JuogbH8eFeH2^FC0000e04M+e1O9lr-2TkSDIpvp z01(6=g+o!6VtnC2Xj=;ipka=cbq4sL6oTu*Gg@gk*a%WZU+YM#HC7(kfwvh*2+CG~ z&=g@>R@neYP++qg?g(NiBmrfWMt4GU)DwpLvv3f!I$HD9l!L!E{N!~+DK z-LOI_fPz#7I#jE4Zox4)ZE%DbW95vPaxn`^+_7QjwsAKbk^yH2pN*pEbQGIcDb3Ia zA9sc9FojtbZ$o&^b9V8c(5nx)Et4m589^VwhUAmi@({eBSyZA;+bJqjQE%YJk~>Bz zz_|mJ=-mqe1STl|JiLWqA0(TcNiS&i aSH}Yn46nuYoKRh3W5weAT=Nx7+C%Zob+71_sfg58~=+QZ+y}y z(K4}9wo}s0k%J+@D<@mlxo}ZSkp`Mxpg-uIC3xpPg+C)pwH|u&>nQi#G)cqC5ZjG5N zAJjMkQ`{cRjN10;tH6_<9!c2+93it60()2`9J8iO3S#RPcl?+7;EL8`)fS=7tTu;_ zlUy0*TRaM>>}WkYyG@emie*m8;fYoW5-D#yFSARo;B(14_@Yp`i(RUQ;VYvBvz*W} z@0BYgDi-<}u4Lff(cfgX4 v!b@Eo4>TEwT$hz*jrwp`0WbbXNk%w1VJHA70P+U_0000G5D+CLB~?{bo}QlC+S>2$@Bjb*A^8LV00000 zA^!_WZDD6+O<`wgV`~m)VQp<;JuogbH8eFeH2^FC0000e04M+e1O9lr-2TkSDWNlD zhyXwk15sSmWGz{zu4)*S6=W0}Yp(*KPy`V>g~4se8Wbcn-)}MF5TB}mRJl|Tpn|Lb z8aPrK*BeL|35vbnMZsA-9SY%&0Jhw+1S9uBC`Xr2HUfGF1Z;Q*bOsA{Du*XDIEsif zJtl-Uc@SnD90LrS07?pcDr67?Y#yErqyPgI1uR_<1dOE)tpG=tE3ZJg9ll^JK6@;g z3&6KPMT)t&sl*QkcZ#Wk5m2EQwsQw}4F=ISvrM^)ZD3MZ5v>8%D*+FXP?CtY0E+m? zOyf8a*PIpQ(NDFSkv{4y{$oZ5wiGXWy~ERi!p)2)`re-Z#8A8;bF{Oym@5|iU3za G0suQPb*{Vs diff --git a/icons/nanos_app_chain_1666600000.gif b/icons/nanos_app_chain_1666600000.gif new file mode 100644 index 0000000000000000000000000000000000000000..6e4e96d16e967ecc97c772d6f57724d524585013 GIT binary patch literal 87 zcmZ?wbhEHb6krfwXkY+=|Ns9h{$v3&bwDIYhJi`1r@!(*!&{z|qHEF_eSyEe*3P|_ istP)JEENd(gW?JEirle1Gx6p~WY zGxKbf-tXS8q>!0ns}yePYv5bpoSKp8QB{;0T;&&%T$P<{nWAKGr(jcI1=O2clBiIT zo0C^;Rbi`?n3A8AY6WEHrj{h?D=C0glw{i~If5h3^Q z^-@z3jgpMh5|eclj0}tn^$mf@T-VUt%E;Kt&{6>clz`S1rKDK}xwt`X1M+N@GD=Dc ztn~HE%k|2Q_413-^$jg8E%gnI^o@*kfeLhsEAxOJ)Xghah8f_JTAW;zSx}OhpQiva zFfl2=wB*07640#>PvjQBjm<081A9m>IX_pwBC$Z1t|uF zOmRt2D#Eo`6&Ht87NqJ2r55Lx7A2aDv3%LmC5sm=Trhv$+&Qyn&73iP+SDnNCrzBt z-`CsI-PPIA-qzaE+|<}mUsqdGT~%38URGLCTvS+)pO>4Hot2r9o|c-DoRpXl9~T=F z9Tgc79u^uB926Mf@8|2|?d9p=?&j*^?BwWRZ)a;`ZDna;Zf0s?Y-DJlucxb{t);1< zuBNJ@tfZ(QFDEM_EhQ--E+#4>EF>tv&&SKd&CSKh!Oq6Y!psCLCv-sN1E|noU{dJm nUwQhj07J=!bD_z5G@?5*=Re9-(3~~p)snRb_kOw~#$XKqcgB+7 diff --git a/icons/nanos_app_chain_246785.gif b/icons/nanos_app_chain_246785.gif deleted file mode 100644 index e9525ae9115e6bffe659b46a866338db6094abed..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 71 zcmZ?wbhEHb6krfwXkY+=|Ns9h{$v3&bwDIYhJi`0r+?+?y9|xopRSbZPM(;|s}w%1 R@o}2nqbt7exRqHMtO1K$6*>R_ diff --git a/icons/nanos_app_chain_73799.gif b/icons/nanos_app_chain_73799.gif deleted file mode 100644 index d15c9370de7b5f20a08deefb07d4e84cffd5f9d0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1131 zcmZ?wbhEHb6krfwXkY+=|Ns9h{^ySH4N!1NEJ*~?Hue<-iOJciB??KY>6v-9O7C~? zS5nAKu~iB;^)>JzK!Rz^k&P@n{~ttchUD#*nRY8Q}atCUevQedU8UtV6WS8lAA zUzDzIXlZGwZ(yWvWTXpJp<7&;SCUwvn^&w1Gr=XbIJqdZpd>RtPXT0NVp4u-iLDaQ zr4TRV7Ql_oE7k*hM=v=)SHB{$K;KZ$0OTc@LSJ9}N^^7Js*6j4QW5UOYH)E#WkITb zP-=00X;E@2P`NV5ssbzLqSVBa{GyQj{2W*)24v)yucqiS6q^qmz?V9Vygr+M=vuo#md>m)Y!?~+}O~?%-PV;)zZnx(%IR`&CJ}{ z&CSrs)flGNB|o_|H#M&WrZ)wl*950tP=d%U0NU)5T9jFqn&MWJpQ`}&xK$=@w;19y z52`l>w_A*G>eUB2MjsTtNYM=w0;VAl6P|d19C-3i%>$zB`;K7M%r?(Lh`uU@`*{_N?K$B!O9xPR~No!hr=-nf44>XplvE?zi)?(CVz2)%Hf~tIZta@Yt5&X9zHI4|#fug$m_KjsoY}Kx z&X_)J>XgZoCQj(@>+R|8>g;H5Yi((6YHX;ltF5W7s;nq4D=jH5DlEv)%gxEo%FIYl zOHD~mN=%54i;annii`*k3k?Yl3Jmb~^Y!ue^7L?bb9Hfca&)k_v$e6dva~QaGc_?b zGBnWF)78<|($r8_Q&mw`QdE$ala-N{l9Uh^6BQ8_5)|O)nRsBdM~!my|KOWHOtg9rk9sDi8ELO06qvB<^TWy literal 0 HcmV?d00001 diff --git a/icons/nanox_app_chain_20531811.gif b/icons/nanox_app_chain_20531811.gif deleted file mode 100644 index 36a8eb70514b595ecc5e30b34925ffe322e94e23..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 98 zcmZ?wbhEHbB&gM%`%*{=-HPACL t1wjTKkZO=V1}5pA{*|X?8RRpB{Y0~ULi6U;&MDWOl|1FeDI-<}YXBYi8?XQX diff --git a/icons/nanox_app_chain_246785.gif b/icons/nanox_app_chain_246785.gif deleted file mode 100644 index 47ceeb506de3af6d142926e8e63921bef44d5192..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 69 zcmZ?wbhEHbj>wsvG2m_N$OaIE#Vsr0t35BS9F8PyjyYznO#EIfb MH(9rOGcs5M0Q*oAR{#J2 diff --git a/icons/stax_app_chain_1666600000.gif b/icons/stax_app_chain_1666600000.gif new file mode 100644 index 0000000000000000000000000000000000000000..a7ab292066d4d348cb3b0d01f4e7e8b75f5f7717 GIT binary patch literal 492 zcmZ?wbhEHbRA5kG_{_k-$jHde%`GY_YG7dC@9$q&SU7X$%&S+gzJC4s^XJb$fByXc z|33o~Q2faP<|+Q?_RLL8PxVbq&rHtdOHa(rO|&)8Gcg501|5(ZkPQqh{|ZieuHO4Y z;?P-7i6Vi+4iz1xJd6*RnkI&ID(-PGkeGV$P;>OT1q(E|8kZ>C=<*G-Jd_x8C&F%?!`*0{TM{nRlASKx zP%G3Sn#b6~-IpdhiFrzGXGV8Y3uBu|gVh4&McjD?OIs%h*{yE3TDM{5>@C^}Yj!Q^ z-7I8UV>y4vT9YNN?7BfxEKK&3PcP!)=w`c{o~Nh&L-l}Djlowe zzP(e^xTW)HM*KUbJQj@$yeDVzuViXG^gPi;CuzBkN&6%vwep90mpriS&s`T9x9KGE3Qtx59KA@Mk?_?1D&iqg;bnb(R=3Ru9` z!I>4HdqDVj#O21`A3SfG9J+;9gaycC+;Z<1^KrZ;TG7SUIcbY#uY|)lB{rsQ$F4lM caWF8LQHW)S#(~>uIi0eKh8l4(icAdF08d%E@c;k- literal 0 HcmV?d00001 diff --git a/icons/stax_app_chain_20531811.gif b/icons/stax_app_chain_20531811.gif deleted file mode 100644 index a1ccb2d47410b7dc321415d881f514c21a0c2e18..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 174 zcmZ?wbhEHbRA5kGXkY+=|Ns9h{$v3&bwDIYhJmTIr+?*XUjErG4-Q1DSBtr?t!X@- z`Dn&MxfNx1x#HYBr*-~07ddy|qPeR)3$`d^e$srEa9S?l`ESFiE7bZX@wm-2SH98} znRGPt>cuy|rd3}1!ml%RQl;7FVBh0yr?a=kom0QEl|5yPxyP2^649a^C$<`Fz53W8 XBci?J>xob8$9GQrrl}Rkz+epk|3pmB diff --git a/icons/stax_app_chain_246785.gif b/icons/stax_app_chain_246785.gif deleted file mode 100644 index 555be4a6d6e3344f9acff781dca0e1278889b014..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 481 zcmZ?wbhEHbRA5kG_{_k-&dx3-CT3)0C3pPxT*;=~ObHe9%H;pNMhU%q_#_3PLF z|Nj|~fZ|UUFi-J6w`Xo*da7??dS-GqUwUG0ZlbM$o{1?4GU$NRfNWr3`B!k#bM;<} z;H6vEdo?K>PZT-&F|eah?1%w}Bg35o4Qsj+@0&IzI0)RyU^wJu$iNcB?&4G^!NS7I zaxn6T%(@1>=MF0b1?DmZEY*}=bFpcrt|QADCe3Ho5g#&{**G~xIGu}Fg2nT=Ioz1o zth*Vb{Kfm2xj1~&CAsV-hOvniMf$R~2+1g}tYh?IcghfMV+!@}N-^5Kn7fU+#m-9D z&UKn_s!2F=tWc^3o151@U(>z9YMjQ+B3XX-8HMcpu8Z!Mz3Z=*Rm<%=LGrmM8^hkz z9J9`k&dMTR7MI=9y)kKVOl!)vj;qlNp3O2-U=CSu*v$EUlmFKziOeC&-K@Ta(*G`I zKYM>}w)P5}KeH8AHqCOm$hB>g!~2^@oX$&~+&MXEnT7fky@CRf2Hw3=Hp-ci4I}^R#MGVufFf1xPswU&nDxer};3(rJNj?Yd Qi~bt@`x}^(I~W+O0pgLa*8l(j diff --git a/icons/stax_app_chain_73799.gif b/icons/stax_app_chain_73799.gif deleted file mode 100644 index ea4c024475faf0b7e7a0131a7af0fb16144c00d4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 158 zcmZ?wbhEHbRA5kGXkY+=|Ns9h{$v3&bwDIYhJmTHr+?*XUjErG8=~0e+%-)-)7o#? z^ysJVoSPe$URfnBb6T)=cZJ-C&6}*QWF1QQ_*J>JLHE(gZ-sWY=1KWgJ)bs7XKAi9 zX`6Uk^>e9fx2Ch{jc&W+Pc<{{)}^0+S^3T`_i6j5FcY&M*O|> Date: Fri, 24 Jan 2025 13:58:59 +0100 Subject: [PATCH 16/25] TX info & provide enum value now use calldata PKI key usage Also no longer use hardcoded PK fallback (cherry picked from commit 44a6bd95a57accff7cca41430d95ac345e9e5885) --- src_features/generic_tx_parser/gtp_tx_info.c | 8 ++++---- src_features/provide_enum_value/enum_value.c | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src_features/generic_tx_parser/gtp_tx_info.c b/src_features/generic_tx_parser/gtp_tx_info.c index bb523ff54..39ed016ca 100644 --- a/src_features/generic_tx_parser/gtp_tx_info.c +++ b/src_features/generic_tx_parser/gtp_tx_info.c @@ -281,14 +281,14 @@ bool verify_tx_info_struct(const s_tx_info_ctx *context) { return false; } - // TODO: change to LEDGER_CALLDATA_DESCRIPTOR key once available if (check_signature_with_pubkey("TX info", hash, sizeof(hash), - LEDGER_SIGNATURE_PUBLIC_KEY, - sizeof(LEDGER_SIGNATURE_PUBLIC_KEY), + NULL, + 0, #ifdef HAVE_LEDGER_PKI - CERTIFICATE_PUBLIC_KEY_USAGE_COIN_META, + // TODO: change once SDK has the enum value for this + 0x0b, #endif (uint8_t *) context->tx_info->signature, context->tx_info->signature_len) != CX_OK) { diff --git a/src_features/provide_enum_value/enum_value.c b/src_features/provide_enum_value/enum_value.c index db0dfb9a1..84c34d40e 100644 --- a/src_features/provide_enum_value/enum_value.c +++ b/src_features/provide_enum_value/enum_value.c @@ -150,14 +150,14 @@ bool verify_enum_value_struct(const s_enum_value_ctx *context) { PRINTF("Could not finalize struct hash!\n"); return false; } - // TODO: change to LEDGER_CALLDATA_DESCRIPTOR key once available if (check_signature_with_pubkey("enum value", hash, sizeof(hash), - LEDGER_SIGNATURE_PUBLIC_KEY, - sizeof(LEDGER_SIGNATURE_PUBLIC_KEY), + NULL, + 0, #ifdef HAVE_LEDGER_PKI - CERTIFICATE_PUBLIC_KEY_USAGE_COIN_META, + // TODO: change once SDK has the enum value for this + 0x0b, #endif (uint8_t *) context->enum_value.signature, context->enum_value.signature_length) != CX_OK) { From 0ef54fe6a7efc56d58aa0d937a9994e9444334db Mon Sep 17 00:00:00 2001 From: Alexandre Paillier Date: Fri, 24 Jan 2025 13:58:44 +0100 Subject: [PATCH 17/25] New calldata test key & certificates in Python client (cherry picked from commit 30e5f03856d33f8d1b3bf9965f37f4aa8f66ac4a) --- client/src/ledger_app_clients/ethereum/client.py | 16 ++++++++++++++++ client/src/ledger_app_clients/ethereum/gcs.py | 2 +- .../src/ledger_app_clients/ethereum/keychain.py | 1 + .../ethereum/keychain/calldata.pem | 8 ++++++++ 4 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 client/src/ledger_app_clients/ethereum/keychain/calldata.pem diff --git a/client/src/ledger_app_clients/ethereum/client.py b/client/src/ledger_app_clients/ethereum/client.py index fac250354..b595e00e8 100644 --- a/client/src/ledger_app_clients/ethereum/client.py +++ b/client/src/ledger_app_clients/ethereum/client.py @@ -75,6 +75,7 @@ class PKIPubKeyUsage(IntEnum): PUBKEY_USAGE_PLUGIN_METADATA = 0x07 PUBKEY_USAGE_COIN_META = 0x08 PUBKEY_USAGE_SEED_ID_AUTH = 0x09 + PUBKEY_USAGE_CALLDATA = 0x0b class SignMode(IntEnum): @@ -565,6 +566,21 @@ def provide_enum_value(self, payload: bytes) -> RAPDU: return self._exchange(chunks[-1]) def provide_transaction_info(self, payload: bytes) -> RAPDU: + if self._pki_client is None: + print(f"Ledger-PKI Not supported on '{self._firmware.name}'") + else: + # pylint: disable=line-too-long + if self._firmware == Firmware.NANOSP: + cert_apdu = "01010102010211040000000212010013020002140101160400000000200863616C6C646174613002000831010B32012133210381C0821E2A14AC2546FB0B9852F37CA2789D7D76483D79217FB36F51DCE1E7B434010135010315463044022076DD2EAB72E69D440D6ED8290C8C37E39F54294C23FF0F8520F836E7BE07455C02201D9A8A75223C1ADA1D9D00966A12EBB919D0BBF2E66F144C83FADCAA23672566" # noqa: E501 + elif self._firmware == Firmware.NANOX: + cert_apdu = "01010102010211040000000212010013020002140101160400000000200863616C6C646174613002000831010B32012133210381C0821E2A14AC2546FB0B9852F37CA2789D7D76483D79217FB36F51DCE1E7B434010135010215463044022077FF9625006CB8A4AD41A4B04FF2112E92A732BD263CCE9B97D8E7D2536D04300220445B8EE3616FB907AA5E68359275E94D0A099C3E32A4FC8B3669C34083671F2F" # noqa: E501 + elif self._firmware == Firmware.STAX: + cert_apdu = "01010102010211040000000212010013020002140101160400000000200863616C6C646174613002000831010B32012133210381C0821E2A14AC2546FB0B9852F37CA2789D7D76483D79217FB36F51DCE1E7B434010135010415473045022100A88646AD72CA012D5FDAF8F6AE0B7EBEF079212768D57323CB5B57CADD9EB20D022005872F8EA06092C9783F01AF02C5510588FB60CBF4BA51FB382B39C1E060BB6B" # noqa: E501 + elif self._firmware == Firmware.FLEX: + cert_apdu = "01010102010211040000000212010013020002140101160400000000200863616C6C646174613002000831010B32012133210381C0821E2A14AC2546FB0B9852F37CA2789D7D76483D79217FB36F51DCE1E7B43401013501051546304402205305BDDDAD0284A2EAC2A9BE4CEF6604AE9415C5F46883448F5F6325026234A3022001ED743BCF33CCEB070FDD73C3D3FCC2CEE5AB30A5C3EB7D2A8D21C6F58D493F" # noqa: E501 + # pylint: enable=line-too-long + + self._pki_client.send_certificate(PKIPubKeyUsage.PUBKEY_USAGE_CALLDATA, bytes.fromhex(cert_apdu)) chunks = self._cmd_builder.provide_transaction_info(payload) for chunk in chunks[:-1]: self._exchange(chunk) diff --git a/client/src/ledger_app_clients/ethereum/gcs.py b/client/src/ledger_app_clients/ethereum/gcs.py index b48fc6f43..3913b2223 100644 --- a/client/src/ledger_app_clients/ethereum/gcs.py +++ b/client/src/ledger_app_clients/ethereum/gcs.py @@ -67,7 +67,7 @@ def serialize(self) -> bytes: payload += format_tlv(0x0a, self.deploy_date) signature = self.signature if signature is None: - signature = sign_data(Key.CAL, payload) + signature = sign_data(Key.CALLDATA, payload) payload += format_tlv(0xff, signature) return payload diff --git a/client/src/ledger_app_clients/ethereum/keychain.py b/client/src/ledger_app_clients/ethereum/keychain.py index 4eb638573..cc1e7ec6c 100644 --- a/client/src/ledger_app_clients/ethereum/keychain.py +++ b/client/src/ledger_app_clients/ethereum/keychain.py @@ -12,6 +12,7 @@ class Key(Enum): TRUSTED_NAME = auto() SET_PLUGIN = auto() NFT = auto() + CALLDATA = auto() _keys: dict[Key, SigningKey] = dict() diff --git a/client/src/ledger_app_clients/ethereum/keychain/calldata.pem b/client/src/ledger_app_clients/ethereum/keychain/calldata.pem new file mode 100644 index 000000000..f97d7bf16 --- /dev/null +++ b/client/src/ledger_app_clients/ethereum/keychain/calldata.pem @@ -0,0 +1,8 @@ +-----BEGIN EC PARAMETERS----- +BgUrgQQACg== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MHQCAQEEIHZBTCI/Q1M5E9r4P4VWDLOewcY+2BmgULfSvzYynWkqoAcGBSuBBAAK +oUQDQgAEgcCCHioUrCVG+wuYUvN8onidfXZIPXkhf7NvUdzh57QGca5YJUtFU1DS +ys87vfMyysGQtD1aymex2r+OcAa2RQ== +-----END EC PRIVATE KEY----- From f55ed40b2f6f8d92cae5b4ddc299ca329ccc49d6 Mon Sep 17 00:00:00 2001 From: Alexandre Paillier Date: Mon, 27 Jan 2025 12:39:34 +0100 Subject: [PATCH 18/25] Provide network now uses the network PKI key usage (cherry picked from commit 49a69bad3822e0fa08a7c2b95748dc9f53350c6c) --- .../provideDynamicNetwork/network_dynamic.c | 40 ++++++++----------- 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/src_features/provideDynamicNetwork/network_dynamic.c b/src_features/provideDynamicNetwork/network_dynamic.c index 45f5474ad..54ceb06d7 100644 --- a/src_features/provideDynamicNetwork/network_dynamic.c +++ b/src_features/provideDynamicNetwork/network_dynamic.c @@ -435,34 +435,26 @@ static uint16_t parse_signature(const uint8_t *data, uint16_t field_len, s_sig_c */ static bool verify_signature(s_sig_ctx *sig_ctx) { uint8_t hash[INT256_LENGTH]; - cx_err_t error = CX_INTERNAL_ERROR; - bool ret_code = false; - CX_CHECK( - cx_hash_no_throw((cx_hash_t *) &sig_ctx->hash_ctx, CX_LAST, NULL, 0, hash, INT256_LENGTH)); + if (cx_hash_no_throw((cx_hash_t *) &sig_ctx->hash_ctx, CX_LAST, NULL, 0, hash, INT256_LENGTH) != + CX_OK) { + return false; + } + if (check_signature_with_pubkey("Dynamic Network", + hash, + sizeof(hash), + NULL, + 0, #ifdef HAVE_LEDGER_PKI - CX_CHECK(check_signature_with_pubkey("Dynamic Network", - hash, - sizeof(hash), - LEDGER_SIGNATURE_PUBLIC_KEY, - sizeof(LEDGER_SIGNATURE_PUBLIC_KEY), - CERTIFICATE_PUBLIC_KEY_USAGE_COIN_META, - (uint8_t *) (sig_ctx->sig), - sig_ctx->sig_size)); -#else - CX_CHECK(check_signature_with_pubkey("Dynamic Network", - hash, - sizeof(hash), - LEDGER_SIGNATURE_PUBLIC_KEY, - sizeof(LEDGER_SIGNATURE_PUBLIC_KEY), - (uint8_t *) (sig_ctx->sig), - sig_ctx->sig_size)); + // TODO: change once SDK has the enum value for this + 0x0c, #endif - - ret_code = true; -end: - return ret_code; + (uint8_t *) (sig_ctx->sig), + sig_ctx->sig_size) != CX_OK) { + return false; + } + return true; } /** From 2b2440e5c9d52cc57ac341e62fe3a543f5b81ca8 Mon Sep 17 00:00:00 2001 From: Alexandre Paillier Date: Mon, 27 Jan 2025 12:40:19 +0100 Subject: [PATCH 19/25] Remove dynamic networks support from LNS From the lack of PKI support (cherry picked from commit 9777726ca4398a733fb4ff225d0c5a8fda296a33) --- makefile_conf/features.mk | 6 ++++++ src/main.c | 13 +++++++------ src/network.c | 3 +++ .../provideDynamicNetwork/network_dynamic.c | 4 ++++ tests/fuzzing/CMakeLists.txt | 15 ++++++++------- tests/ragger/test_get_address.py | 2 +- tests/ragger/test_sign.py | 2 +- 7 files changed, 30 insertions(+), 15 deletions(-) diff --git a/makefile_conf/features.mk b/makefile_conf/features.mk index b56dc9fee..615b8b2f7 100644 --- a/makefile_conf/features.mk +++ b/makefile_conf/features.mk @@ -62,6 +62,12 @@ ifneq ($(TARGET_NAME),TARGET_NANOS) endif endif +# Dynamic networks +ifneq ($(TARGET_NAME),TARGET_NANOS) + DEFINES += HAVE_DYNAMIC_NETWORKS +endif + + # Check features incompatibilities # -------------------------------- # NFTs diff --git a/src/main.c b/src/main.c index 3e4890801..3a0625f8f 100644 --- a/src/main.c +++ b/src/main.c @@ -147,9 +147,6 @@ static uint16_t handleApdu(command_t *cmd, uint32_t *flags, uint32_t *tx) { } switch (cmd->ins) { - case INS_PROVIDE_NETWORK_CONFIGURATION: - sw = handleNetworkConfiguration(cmd->p1, cmd->p2, cmd->data, cmd->lc, tx); - break; case INS_GET_PUBLIC_KEY: forget_known_assets(); sw = handleGetPublicKey(cmd->p1, cmd->p2, cmd->data, cmd->lc, flags, tx); @@ -207,7 +204,6 @@ static uint16_t handleApdu(command_t *cmd, uint32_t *flags, uint32_t *tx) { break; #ifdef HAVE_ETH2 - case INS_GET_ETH2_PUBLIC_KEY: forget_known_assets(); sw = handleGetEth2PublicKey(cmd->p1, cmd->p2, cmd->data, cmd->lc, flags, tx); @@ -216,8 +212,7 @@ static uint16_t handleApdu(command_t *cmd, uint32_t *flags, uint32_t *tx) { case INS_SET_ETH2_WITHDRAWAL_INDEX: sw = handleSetEth2WithdrawalIndex(cmd->p1, cmd->p2, cmd->data, cmd->lc); break; - -#endif +#endif // HAVE_ETH2 #ifdef HAVE_EIP712_FULL_SUPPORT case INS_EIP712_STRUCT_DEF: @@ -259,6 +254,12 @@ static uint16_t handleApdu(command_t *cmd, uint32_t *flags, uint32_t *tx) { break; #endif // HAVE_GENERIC_TX_PARSER +#ifdef HAVE_DYNAMIC_NETWORKS + case INS_PROVIDE_NETWORK_CONFIGURATION: + sw = handleNetworkConfiguration(cmd->p1, cmd->p2, cmd->data, cmd->lc, tx); + break; +#endif // HAVE_DYNAMIC_NETWORKS + default: sw = APDU_RESPONSE_INVALID_INS; break; diff --git a/src/network.c b/src/network.c index 77b863713..70ffef78f 100644 --- a/src/network.c +++ b/src/network.c @@ -123,6 +123,7 @@ static const network_info_t NETWORK_MAPPING[] = { static const network_info_t *get_network_from_chain_id(const uint64_t *chain_id) { if (*chain_id != 0) { +#ifdef HAVE_DYNAMIC_NETWORKS // Look if the network is available for (size_t i = 0; i < MAX_DYNAMIC_NETWORKS; i++) { if (DYNAMIC_NETWORK_INFO[i].chain_id == *chain_id) { @@ -130,6 +131,8 @@ static const network_info_t *get_network_from_chain_id(const uint64_t *chain_id) return (const network_info_t *) &DYNAMIC_NETWORK_INFO[i]; } } +#endif // HAVE_DYNAMIC_NETWORKS + // Fallback to hardcoded table for (size_t i = 0; i < ARRAYLEN(NETWORK_MAPPING); i++) { if (NETWORK_MAPPING[i].chain_id == *chain_id) { diff --git a/src_features/provideDynamicNetwork/network_dynamic.c b/src_features/provideDynamicNetwork/network_dynamic.c index 54ceb06d7..32a9db20a 100644 --- a/src_features/provideDynamicNetwork/network_dynamic.c +++ b/src_features/provideDynamicNetwork/network_dynamic.c @@ -1,3 +1,5 @@ +#ifdef HAVE_DYNAMIC_NETWORKS + #include #include #include "os_utils.h" @@ -656,3 +658,5 @@ uint16_t handleNetworkConfiguration(uint8_t p1, return sw; } + +#endif // HAVE_DYNAMIC_NETWORKS diff --git a/tests/fuzzing/CMakeLists.txt b/tests/fuzzing/CMakeLists.txt index f27ae3401..02d603c7e 100644 --- a/tests/fuzzing/CMakeLists.txt +++ b/tests/fuzzing/CMakeLists.txt @@ -154,21 +154,22 @@ set(DEFINES HAVE_SWAP HAVE_ENUM_VALUE HAVE_NFT_SUPPORT + HAVE_DYNAMIC_NETWORKS ) add_compile_definitions(${DEFINES}) FILE( - GLOB_RECURSE SDK_STD_SOURCES - ${BOLOS_SDK}/lib_standard_app/*.c - ${CMAKE_SOURCE_DIR}/../../ethereum-plugin-sdk/src/*.c + GLOB_RECURSE SDK_STD_SOURCES + ${BOLOS_SDK}/lib_standard_app/*.c + ${CMAKE_SOURCE_DIR}/../../ethereum-plugin-sdk/src/*.c ./src/mock.c ) list( - REMOVE_ITEM SDK_STD_SOURCES - ${BOLOS_SDK}/lib_standard_app/io.c - ${CMAKE_SOURCE_DIR}/../../ethereum-plugin-sdk/src/main.c - ${BOLOS_SDK}/lib_standard_app/main.c + REMOVE_ITEM SDK_STD_SOURCES + ${BOLOS_SDK}/lib_standard_app/io.c + ${CMAKE_SOURCE_DIR}/../../ethereum-plugin-sdk/src/main.c + ${BOLOS_SDK}/lib_standard_app/main.c ${BOLOS_SDK}/lib_standard_app/crypto_helpers.c ) diff --git a/tests/ragger/test_get_address.py b/tests/ragger/test_get_address.py index 39e0ab16a..e670295a2 100644 --- a/tests/ragger/test_get_address.py +++ b/tests/ragger/test_get_address.py @@ -67,7 +67,7 @@ def test_get_pk(backend: BackendInterface, else: name = "" - if name: + if (app_client._firmware != Firmware.NANOS) and name: app_client.provide_network_information(name, ticker, chain, bytes.fromhex(icon)) with app_client.get_public_addr(chaincode=with_chaincode, chain_id=chain): diff --git a/tests/ragger/test_sign.py b/tests/ragger/test_sign.py index 499ed651c..3ac93064d 100644 --- a/tests/ragger/test_sign.py +++ b/tests/ragger/test_sign.py @@ -56,7 +56,7 @@ def common(firmware: Firmware, else: name = "" - if name: + if (app_client._firmware != Firmware.NANOS) and name: app_client.provide_network_information(name, ticker, tx_params["chainId"], bytes.fromhex(icon)) with app_client.get_public_addr(bip32_path=path, display=False): From d1c05c42c6f82c4b3304b2a18bf7b782471a1613 Mon Sep 17 00:00:00 2001 From: Alexandre Paillier Date: Mon, 27 Jan 2025 14:20:57 +0100 Subject: [PATCH 20/25] New network test key & certificates in Python client (cherry picked from commit a9cb26ff132a70400c6f2b2166711062c6733691) --- client/src/ledger_app_clients/ethereum/client.py | 13 +++++++------ client/src/ledger_app_clients/ethereum/keychain.py | 1 + .../ethereum/keychain/network.pem | 8 ++++++++ 3 files changed, 16 insertions(+), 6 deletions(-) create mode 100644 client/src/ledger_app_clients/ethereum/keychain/network.pem diff --git a/client/src/ledger_app_clients/ethereum/client.py b/client/src/ledger_app_clients/ethereum/client.py index b595e00e8..3ab287d75 100644 --- a/client/src/ledger_app_clients/ethereum/client.py +++ b/client/src/ledger_app_clients/ethereum/client.py @@ -76,6 +76,7 @@ class PKIPubKeyUsage(IntEnum): PUBKEY_USAGE_COIN_META = 0x08 PUBKEY_USAGE_SEED_ID_AUTH = 0x09 PUBKEY_USAGE_CALLDATA = 0x0b + PUBKEY_USAGE_NETWORK = 0x0c class SignMode(IntEnum): @@ -525,7 +526,7 @@ def _prepare_network_info(self, payload += format_tlv(FieldTag.NETWORK_ICON_HASH, sha256(icon).digest()) # Append the data Signature payload += format_tlv(FieldTag.DER_SIGNATURE, - sign_data(Key.CAL, payload)) + sign_data(Key.NETWORK, payload)) return payload def provide_network_information(self, @@ -539,16 +540,16 @@ def provide_network_information(self, else: # pylint: disable=line-too-long if self._firmware == Firmware.NANOSP: - cert_apdu = "01010102010211040000000212010013020002140101160400000000200B45524332305F546F6B656E300200063101083201213321024CCA8FAD496AA5040A00A7EB2F5CC3B85376D88BA147A7D7054A99C64056188734010135010310040102000015473045022100C15795C2AE41E6FAE6B1362EE1AE216428507D7C1D6939B928559CC7A1F6425C02206139CF2E133DD62F3E00F183E42109C9853AC62B6B70C5079B9A80DBB9D54AB5" # noqa: E501 + cert_apdu = "0101010201021104000000021201001302000214010116040000000020076E6574776F726B3002000A31010C32012133210304AF5CF32094F855E93235E9EB43F48E9B436C2E1DFAEA58ECAFA68AAFB1D27C3401013501031546304402207BDE0D30C0A573ECF2F8377F30D9A064CFDD8C85E3B328E4C0867A5C7E95EC7E02204B3546342571AE54E7524DD66D4F801E3E4F4F2EA9008F943661F62E48053E92" # noqa: E501 elif self._firmware == Firmware.NANOX: - cert_apdu = "01010102010211040000000212010013020002140101160400000000200B45524332305F546F6B656E300200063101083201213321024CCA8FAD496AA5040A00A7EB2F5CC3B85376D88BA147A7D7054A99C64056188734010135010215473045022100E3B956F93FBFF0D41908483888F0F75D4714662A692F7A38DC6C41A13294F9370220471991BECB3CA4F43413CADC8FF738A8CC03568BFA832B4DCFE8C469080984E5" # noqa: E501 + cert_apdu = "0101010201021104000000021201001302000214010116040000000020076E6574776F726B3002000A31010C32012133210304AF5CF32094F855E93235E9EB43F48E9B436C2E1DFAEA58ECAFA68AAFB1D27C34010135010215473045022100E1CE7DAC7A23B9422B0764F8FE80246B2CF0780227289FBFB203985DA6326A9502205F90B43600407A094DD6DEBCEB92F34DA3EDA9EB5463568440BDC21635FF2044" # noqa: E501 elif self._firmware == Firmware.STAX: - cert_apdu = "01010102010211040000000212010013020002140101160400000000200B45524332305F546F6B656E300200063101083201213321024CCA8FAD496AA5040A00A7EB2F5CC3B85376D88BA147A7D7054A99C6405618873401013501041546304402206731FCD3E2432C5CA162381392FD17AD3A41EEF852E1D706F21A656AB165263602204B89FAE8DBAF191E2D79FB00EBA80D613CB7EDF0BE960CB6F6B29D96E1437F5F" # noqa: E501 + cert_apdu = "0101010201021104000000021201001302000214010116040000000020076E6574776F726B3002000A31010C32012133210304AF5CF32094F855E93235E9EB43F48E9B436C2E1DFAEA58ECAFA68AAFB1D27C34010135010415463044022044C595C3E98100D4ECA75A73BF294090FF94948E80EE1430624C886B15BE862302200994E1D98CA72B78D57808B5FD236F439376AFC7C651B55D4AFBFB5AF4C15E00" # noqa: E501 elif self._firmware == Firmware.FLEX: - cert_apdu = "01010102010211040000000212010013020002140101160400000000200B45524332305F546F6B656E300200063101083201213321024CCA8FAD496AA5040A00A7EB2F5CC3B85376D88BA147A7D7054A99C64056188734010135010515473045022100B59EA8B958AA40578A6FBE9BBFB761020ACD5DBD8AA863C11DA17F42B2AFDE790220186316059EFA58811337D47C7F815F772EA42BBBCEA4AE123D1118C80588F5CB" # noqa: E501 + cert_apdu = "0101010201021104000000021201001302000214010116040000000020076E6574776F726B3002000A31010C32012133210304AF5CF32094F855E93235E9EB43F48E9B436C2E1DFAEA58ECAFA68AAFB1D27C34010135010515463044022008D276684F1A1CC3A89DB0B15120860414FF6A60E227FCAA29ED8F2096C982460220343FE956D443CEA33A2F8BD9DD1EAD783ACFF86088CF01BCE63C224DC815D7F0" # noqa: E501 # pylint: enable=line-too-long - self._pki_client.send_certificate(PKIPubKeyUsage.PUBKEY_USAGE_COIN_META, bytes.fromhex(cert_apdu)) + self._pki_client.send_certificate(PKIPubKeyUsage.PUBKEY_USAGE_NETWORK, bytes.fromhex(cert_apdu)) # Add the network info payload = self._prepare_network_info(name, ticker, chain_id, icon) diff --git a/client/src/ledger_app_clients/ethereum/keychain.py b/client/src/ledger_app_clients/ethereum/keychain.py index cc1e7ec6c..b913c867a 100644 --- a/client/src/ledger_app_clients/ethereum/keychain.py +++ b/client/src/ledger_app_clients/ethereum/keychain.py @@ -13,6 +13,7 @@ class Key(Enum): SET_PLUGIN = auto() NFT = auto() CALLDATA = auto() + NETWORK = auto() _keys: dict[Key, SigningKey] = dict() diff --git a/client/src/ledger_app_clients/ethereum/keychain/network.pem b/client/src/ledger_app_clients/ethereum/keychain/network.pem new file mode 100644 index 000000000..160a4aedb --- /dev/null +++ b/client/src/ledger_app_clients/ethereum/keychain/network.pem @@ -0,0 +1,8 @@ +-----BEGIN EC PARAMETERS----- +BgUrgQQACg== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MHQCAQEEIBWMfLNb5rHjqi1tyaZ0toOPu9U0gUSSXOeNQ9k1C4jaoAcGBSuBBAAK +oUQDQgAEBK9c8yCU+FXpMjXp60P0jptDbC4d+upY7K+miq+x0nyHMUmG/f/vNNKW +0vGHFHx8FKpAaFSMAsUh92NlAg8ZJQ== +-----END EC PRIVATE KEY----- From a3233191c5089900654ff8543bff87cc5f2abaf1 Mon Sep 17 00:00:00 2001 From: Alexandre Paillier Date: Mon, 27 Jan 2025 15:11:21 +0100 Subject: [PATCH 21/25] Fix CAL trusted name certificates in Python client (cherry picked from commit 27785130985b762925cec1801c768fb568f0d817) --- client/src/ledger_app_clients/ethereum/client.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/src/ledger_app_clients/ethereum/client.py b/client/src/ledger_app_clients/ethereum/client.py index 3ab287d75..4a4801597 100644 --- a/client/src/ledger_app_clients/ethereum/client.py +++ b/client/src/ledger_app_clients/ethereum/client.py @@ -279,13 +279,13 @@ def _provide_trusted_name_common(self, payload: bytes, name_source: TrustedNameS if self._pki_client is not None: # pylint: disable=line-too-long if self._firmware == Firmware.NANOSP: - cert_apdu = "010101020102110400000002120100130200021401011604000000002010547275737465645F4E616D655F43414C300200073101043201213321024CCA8FAD496AA5040A00A7EB2F5CC3B85376D88BA147A7D7054A99C64056188734010135010315473045022100CD7F858EDED3A6F2EFECA4D7392618533FDD13BB9920C2CA9AD551B2C3C45D1A022041AAE52DCB50BD9E97D859417D5DA1463AB2A8CBF30B9D06DBF7C84863E6076D" # noqa: E501 + cert_apdu = "010101020102110400000002120100130200021401011604000000002010547275737465645F4E616D655F43414C300200093101043201213321024CCA8FAD496AA5040A00A7EB2F5CC3B85376D88BA147A7D7054A99C6405618873401013501031546304402202397E6D4F5A9C13532810619EB766CB41919F7A814935CA207429966E41CE80202202E43159A04BB0596A6B1F0DDE1A12931EA56156751586BEE8FDCAB54EEE36883" # noqa: E501 elif self._firmware == Firmware.NANOX: - cert_apdu = "010101020102110400000002120100130200021401011604000000002010547275737465645F4E616D655F43414C300200073101043201213321024CCA8FAD496AA5040A00A7EB2F5CC3B85376D88BA147A7D7054A99C64056188734010135010215473045022100E017EA39279846D531D3A7986178B2A2E25ECA27D89C3C75B61FF936C1A5E78E02202C5F6686186A9314A1DCCF9292F9494C3DA4C1568ED020DD7941D60B39A7C95C" # noqa: E501 + cert_apdu = "010101020102110400000002120100130200021401011604000000002010547275737465645F4E616D655F43414C300200093101043201213321024CCA8FAD496AA5040A00A7EB2F5CC3B85376D88BA147A7D7054A99C64056188734010135010215473045022100BCAED6896A3413657F7F936F53FFF5BD7E30498B1109EAB878135F6DD4AAE555022056913EF42F166BEFEEDDB06C1F7AEEDE8712828F37B916E3E6DA7AE0809558E4" # noqa: E501 elif self._firmware == Firmware.STAX: - cert_apdu = "010101020102110400000002120100130200021401011604000000002010547275737465645F4E616D655F43414C300200073101043201213321024CCA8FAD496AA5040A00A7EB2F5CC3B85376D88BA147A7D7054A99C64056188734010135010415473045022100D072546754CEDC1A94C1821A998900C1022D109AFC8FA83D534C1D9193D9EEEC022056906F4A0FDCC7EB5AD37874E556DE4925AD0C654831DB255FDACFAF339AE9B6" # noqa: E501 + cert_apdu = "010101020102110400000002120100130200021401011604000000002010547275737465645F4E616D655F43414C300200093101043201213321024CCA8FAD496AA5040A00A7EB2F5CC3B85376D88BA147A7D7054A99C64056188734010135010415473045022100ABA9D58446EE81EB073DA91941989DD7E133556D58DE2BCBA59E46253DB448B102201DF8AE930A9E318B50576D8922503A5D3EC84C00C332A7C8FF7CD48708751840" # noqa: E501 elif self._firmware == Firmware.FLEX: - cert_apdu = "010101020102110400000002120100130200021401011604000000002010547275737465645F4E616D655F43414C300200073101043201213321024CCA8FAD496AA5040A00A7EB2F5CC3B85376D88BA147A7D7054A99C6405618873401013501051546304402206FB5CBEDAC961D6D64750FC6AFF1C2797B1C6809CC42FAEAA44D15398A3E20D5022042B53D6C0D07703FAC2B2A70864178F82B0AEDC4C451AB438AE7D1883714C5A9" # noqa: E501 + cert_apdu = "010101020102110400000002120100130200021401011604000000002010547275737465645F4E616D655F43414C300200093101043201213321024CCA8FAD496AA5040A00A7EB2F5CC3B85376D88BA147A7D7054A99C6405618873401013501051546304402206DC9F82C53F3B13400D3E343E3C8C81868E8C73B1EF2655D07891064B7AC3166022069A36E4059D75C93E488A5D58C02BCA9C80C081F77B31C5EDCF07F1A500C565A" # noqa: E501 # pylint: enable=line-too-long key_id = 6 key = Key.CAL From 75331a383435a2cb71e18b993f518a857eddbd24 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 28 Jan 2025 14:34:31 +0000 Subject: [PATCH 22/25] [auto-update] Update Ragger snapshots (cherry picked from commit 344f9a3480a221633dea365d0948b90ed7378edb) --- .../snapshots/flex/test_blind_sign/00000.png | Bin 18507 -> 19968 bytes .../flex/test_blind_sign_nonzero/00000.png | Bin 18507 -> 19968 bytes .../flex/test_blind_sign_rejected/00000.png | Bin 18507 -> 19968 bytes .../test_sign_parameter_selector/00006.png | Bin 18507 -> 19968 bytes .../snapshots/stax/test_blind_sign/00000.png | Bin 15903 -> 17111 bytes .../stax/test_blind_sign_nonzero/00000.png | Bin 15903 -> 17111 bytes .../stax/test_blind_sign_rejected/00000.png | Bin 15903 -> 17111 bytes .../test_sign_parameter_selector/00006.png | Bin 15903 -> 17111 bytes 8 files changed, 0 insertions(+), 0 deletions(-) diff --git a/tests/ragger/snapshots/flex/test_blind_sign/00000.png b/tests/ragger/snapshots/flex/test_blind_sign/00000.png index acbb161dfd465dba1fe0b49424f867d887f47c32..039eff0472fe0760b4f2e38b458f53d7cffc164b 100644 GIT binary patch delta 17777 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%0A6qgPww;8Y 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 f)8ih7pMMElClL{08Hul08>ls?IK23OBrtp# diff --git a/tests/ragger/snapshots/flex/test_blind_sign_nonzero/00000.png b/tests/ragger/snapshots/flex/test_blind_sign_nonzero/00000.png index acbb161dfd465dba1fe0b49424f867d887f47c32..039eff0472fe0760b4f2e38b458f53d7cffc164b 100644 GIT binary patch delta 17777 zcmYIwcRXC*7wzao?=?vDE=&;7dx@49f@o1<)QDcj)oTz0LG<25jW&oD(Yp{Ph#tKg zID{d8s--rSq z3h7jKr26SUfVcS=n*s8h4AJ74-#F25joRhC`$LUPnP9vwY>PtMtyP0K2p3W@;D1B$ z`D4KpV8-rR*S`6p^`9aV5ESQ5jWGuq)xGf_N>>72{;!S8ZP_MndZt?m8U8 zKR=KxAHg=+{HSu*gWK}aMF!0*lmU|%@+oY%RCM`&f1j+=^Wgk7Zg)4R*J70;p=|#> z{%l}7PfTFP77r8b{}a(U+xB1A2WKRA4}T)nee?SCy&Tx+j7_`Fonzs??B9 zF}w64czV@NdeL%-JlO@31zVmBn{Qr>61ba~_qu2H{<)t~ij7fp-Y-?Ua7#KBJu2md zeRL8dW&hz#KnH3+1|fJirjZ02diCR+@-pzlJ18=GoX4$^XuWe^2y7=%@t1Sc!tRVm z=G6-_Y)iW55x6XW0^-ZcdXfhANrG9U^L9=pBNW>qvOZZZHyl`ymtk-KEnYvtq^!r( zKjn2Of^(G9Q00}#{$k)HF(fZ?1p=vfmSWS<(UCeBHvJ?z52}?t`bLjRJ#nt2Zo|it zj#K?PmGVNPPgYEvXNnE_Ccy1*{%%6)?xtRnnM&{gDdvK~{K*r9Y}{%~RZO0Rt4sR2 zx0JTUVes8#tUhf6n%U^M5LQ;W7<$ljc5&Zpo79JXQT|=_#uG1RHPdOfmm;hTA)%1K z$CkYXNZanTbF}oJNCWT$KX~WV-W%5A`YMG(*$b*=_0w_%^8jqr;hSKMWs&-h+_b?WD_6zY6*!!2v$1Xau5(CzhCe&HECFz|Xc^zI$CesK8fvovVgd3^Z{ zn6vWJLimK66!p9?2iKIX@)6rnhme80>N!H(PBQX_4$y+AGk>g|ip;ZYCH(WdV|(Et?E4&GxBh%nLo_aEqtCV^Y3 z{zv88hu%|r;U3MeymL2L@e3~b`G1M-vOnd!+aOm5Qk@ICoHy*iUhKQ(SDvl+c}{md zpEAdTdu@e7Yf_D;234s|iGuiK$znh(Sbef|%9;NznN=HZ6*oGWpJ_)f)4#swVLB=C zC$vaA>s;oyJQn1$oO@nj01@guChtQdy>%YOci zek+q*$M29{v?B@ZmgTxK^}9YJbk~(LBg1|@DxxmsAvsA?&;D~EeMta(|180qZcfhp z_+&m=pplLq|EO(yB{*+p1)9^&A=%?}sY9sN2GqxFtQSKj2z_(QmqP*#(jp6gu){-) z6{q&cUnWK~9!Zqr$v{LATshfTc|yE{zMWS=;E2X115vK;wgYoHRz80mkFqmz3_XaF zS2)1X?Jx8$*pZYNU*H&ZBN-rzKs)}l2M#hL>#W?hqQi_$y z)E1ikUEFTt)q209vU;{$tjbF9?yhEVq^9e?m4rGgOpc|QNtp?TY8^XJjLsizemXam zmqi2C>C>+ktfSQcRT-s@aRcC{m@*HSeKI=*DW#sIjI?~EuPbWGqBTt{6-kAqpc zqZML(m-3*Lpzje{ufh_3U^;tqdm9a?+7;2`Oo%uwJmmK^pt;yC_NrWV7&u2fYH{YI z*+U(GtJ)azM@ChTs^66^e1ZzsY=g*=7Ii)eby_em9s7BHvvWG%xa+xSjdhUI#i_UW zhWWg@OygZ%?+1u5o@Pr*JyO(X(v?Z55%=HGUL77OgCo@dLOU^(>@bh=+^B!x(^85}{kS+J+Z^HJl<#VDn2kB%7mhtL1gQ6Z=6On31OoKBcX zaiA%fvYp7mC%vxrbrI{Bg_T+Y%xqMf{%s!Z`fBDTOawm&mvOZa{Y>{)^0I>PlR9nw zS23_YTzY)y90h1O>2pq>fbV?6+h@-_1=(zO$C*eO+a$!2cm#*IiYTq$Mg3+&T44z z=CGREUVji*lGz$O+nUHwBNGp2G8K74-2j zo9U^)Oz*#?eJ@v|r>OIV#>}plIbC6IBU8V^*;^z6cU}q7>Sczo(jDUWy7E`8#$|1C zxXPZ5XnCBmj&%aAQ(BcOE{{?-nlH>9BOBNS9qQ}0|H|hCt(IgM#|A_f*r>si;+o!L zDUv;&Cr_ghaMjI}K9R>t)iYcZidHb*N%Q`Rr&Z!`X{A`PMn3H$aOm2F%LuvyFFo;w ziLyHBIkG_0btQXlrnB4O!=Z(EyOw|=f9gv!ZgKYEo;z3+m^Hb@ zek-n?DC5D5{bYP4dLnhOkURSP1+F6bo7$myTK>zej1RV$%+R+9xtYCZ%=Kcf6659h zXC7_Unr;Qn!en;8AEIx}enB|Y6QNqf8>AF=qsQ9CNp$VB%H*HzR5y2$8xu;ssyrz1 zp>IjxGeGtma)(FyInyN065~~ew-?KJ+>BQ_L2mC&4BW};AEZd6kx7qNJs2pDH3I@4 zYIcU;IzRe`I1Be1>)GG0_K6~e%;30=bqcVb8yOG#7}uo8zGVWN#`kzpZbXaI8~(D> z6

AG@FQ&KuY3Q;68e_?Aa=?B||w!M);Koz-Ex>3LT6l!C`!j@g_(Pi%a)B)RaGG z#b3rs0Qk*`Ux&4mugyq5&u_k`ZifrrBpxIea+<(tR_^yr5aOAPLlP`VQX|55CKF?! z$p4#_%&ta+(%Jr$1Z-XczeS=m{aJ(E_}9`Uio5=BrR-`rw~Gw;1bHHezXUqS0Xbdv zCGDfnRS%BT7EvJn8GMda1Fm8XLn6@9*|V2gq7C)U>xu?9xTHRe!TuGSR zs!w_JI|H0Sq3bUMXVq*ua4}L+wtXZ041?~TSS*evTl1(Toko6G94ozN^DE&(LVhA_ z2L9-68ADh@)FrFd~6I74@}JQvn~Ul4+FRfKy74YYZvnmUI|Ju$EOY|qbarey(epG`AH)}mM3%h zHTQ~|Hr`5{q%A^+13ESasD$WE-Rn4IEOB8iRSWy)f1jMC&AtizzWjD`=j&kYdxZaP zHTq_WY~HnbCp#0y0{WR(Lw-6IyI-otrYa@5z(B z?V9L+HwjI#jTdY&qRbW!G47dFA;Y!?!NW%h6R^QV_DB9VHJP8gK;Ye^onmvHqy~fK zc}7@%7pJhwE-M3CUI~_!ql<3b#L=;b4W>-+^ypZ{r@Quvf+RW@e{GoKBfNvty%!qu zpd~0*4^z$gM<*sa(C6r0-jsNozQQM;x4r5aj_fv9=nUQ6W(PCqp=`z_nYcWj-^v=! zL_(fd$IXa+d8258xk3=%Z>4~ywL4o_ImSs(FAcrm3mXRPC(|@?3L})HRh_K!tR}?G zjV6L~1z^{&$BZw$r4rfIC-r^(=tTt6D|b5#hQ$a^BJ)ft%=&D`o-H)O(SJg6Y@-|?!0>|@O}J~ z91li-h#t7qQ;5u-#tmXNbg!EkMAQ4TGa)%J-u}S6L5JJ&Thr1!6 z=V$~N0eQCOKJq-H>tk*%Ec4npq(A;lc>J=N{!22rmDIm=_Kv8A{7hN>vKl>-=o+Py z(MA52yI@92lTj%srBAeZISp&RhYD99$pUBuf^0hkWPlH2!qXYSid!A6i&a$)XdAUR z%8p;xRc|sIpsNz=Us#Plgepb64pOBGvunIOiWS6Y@yBhg0z)tIPu7_`NK2SrMepHp zstQ9uZ4;1o*Q9w)`)%pc?9QpT)X|5-<+pS#O#RR1{KEFz^z53gAAJb1r8xkAB=$!` zih5sWg;dQ#6^-~qv?jqLGO^KXg5K5qup@<`@@9n2@}J0XfQi2!t!mcB%6UadUHh=p z;c#!DU0}Ts@3R?ZZXhf9QX7qJ1GI8g)}Ah9*9wX0A^= zz8o^YVw=%S$NJ)tz8HO;&29VvVAp!Fcbu^F9Ga%Q%Q?Z>3uFv0Z3gHQS|7Y?jtt-% zb}3@!GW+b(Gxb1IX_>Hl?A;fGL&lx^=v2ou6Aa9onRiU04`jG(lQ^Lg(GLahrH6EC zXuTjZL$JP(JxeOSA`|6q#PeJF0wmk+OQ4o|m!DjU(KH#A17$xfmNVQk z(fHjp-1iQ*L`Hwv^xQr?COQ%qcokzL%54V5TC@gl_RXW162ioH&D(!I#mAmcLVh=> zS5k5}yXv!Vsq$0ZDiIHvv6{>he)vfp+Uin@2luFV`tlMNot}5udmzJPY6weSei~>S z%cxEF<{#$WYPQP7?9lrHg1v^(OA+-KSZ5fAUz^m}JXca`zmaoy{V1i@dYo;X`W7%&nX+wucz` zWWSM0c21eS#^KgOhu&28?-`2>*DlD%NUUWB=M+|`muDIURA~SU5L=_O<72RQFkA=Q zVP%)P(z3WoojoBx$IErpNyXvyDh zMJUF3&(}vZ1h6f*^s8t1{M9YE{?mKJlCqMxQS0mQ?b1-o5^0Ibo6*aRo5qWKq*okz zRA9*9RHw_;CMXvC7mc(}-rO*&p7koyA6Luq4)rbMh>x1lWcc_ly$C^WOy$#lDlu~@ z!aWV2gr1`_XXgHx2#1pJ?j{;6#EXaBEtnH<*p7Ms+DZ4sTPiwl(*X)b)yALP z2gq2CdPg?uteLei{Q-0~cQlCVkMXwJAM0ll7~{t($Vcv+8dHU7Nu6?j5(PNYj4NEDZeA*VOc7@=lbyZ4b7g!*+QAZS zdjR^jLi--E-UNzG%KbczJwytw_Id4#6c`R~67KTZ!3WsSMi>9y$D@Sd*6c-G{;HZx zB<<|ifqr5S392z1jD8)JwY(~d{~0qR z)Z(?BOt2Q$UzG?vS(%W|`(t>-oPFnrZiY#0C$~Di!>bD-Os_yZV%yM}PiMDz4BWcb zGaMUWv>}Q=g98#%kT?*GC0XK0CLLgi0&5)Ogvcqge*!tS?DCXkm&r#LNTyz}Hg z!&&h!as>u!cUpvrOc&&v;pw&fA*_*kc1|X@{mXAbP~;CX9&cn`rWD>WJy*z%EcicN z*z}frSy}Y0pG_~dGh}7%q7&7&TTvc%LbGWPrr_W50_UY{@{w92fnQHr}cTCXd$sYp-cs)=9o zs{0%PYXcdQ_l!h2RKct@qqegi;D)~qC#j0 zgMSK3ClDaWn1srcsiBU}rnU0(KN`bepOMW`BtLQrA3dC+TY_H-nbd0e9WQa`6&fKv z=!QjL4p}KlVe8K}%qJ3E@L?ROYscelAH$Y%vVe_GJm=2lU6&q2vL|kv}jIF?^o6Ljg zhhO?d@iF~~SAJ8X&cOrIB*IdyeY;F<0VNsz@bIxV@Q>OAFrB@2&Uqi>6TkYky26av zUyAwjJEng1#2(jYs{W`ZA(oMfef0C`3*=~b;78h8bN>?jV*#_2iAWle7illkf5b+A zQ%_=Fe#l_BC{@5|^UAjt*XC`>qfx*_CR4U$?VO+<;m2sG9Jlgn>Rt{A-2%(24DRq8)n{;>XBx)P>XZqm?Py-4!ox31L{gJSk0F&qxqSmc>l zedNpvCAP7L<%I`t1GVoH2iPaRzV+dOk=iTDQx~8FQ+j14+}4;%nW=xC^pSl62=wrF zankt{1Ob`s_7o`_hLYWE6sMYxPFt3%feSZhIfB z3DJjlx4`=2^C>zC=2X2;gXs6`o6Z;demR=uG{oc4w$N#)Q}Afh%yRZVz((jwX6YtS zY#)|7JB6EJO_ixM35eXjYqmBL69itT4i>wJVcZ8q>(1tyKFBNyQEGQ-0I+=O_x8N(6sl^|%rGR);=KWc~W zI3*497?;}SC|tsiQE8WD8A-LHzgewby;TsO{jaUdwNk+!qLHbmm0~|iornLP`?U;S z`p4yQ<6|Pjt`3NL&u;*z)+DqLuYq6F*IB0+%)jjKBoLDB>aGh?iq;v3TV{93_kCrJ zGjVhoq9uSfC5y|td2j2X2)1=zET;dC`_@wR=EizeXR&I>F0FrZ>*V?S@9Y^zKYyJU zi8nr5vi!2mIYiH7Ka`<3Bj)evw{XpxD=kISm49!QjIsO-`|%A>>a6v)IHR$v9Uz=u zWj&9+4cMwae5qyr8TY>VSFCfbCH^F@PpvHkgG3~c*KMr6*Zv*OosIwBaI`LurQ(tE z`kt+e&P{a$|MJ}HF%hkc^-hSBO0?v&dNTsz)3*8!kR=NMfCjd-kY8j!Dm+cKt~}3t zgY#5GQE&bN`ZnK)9(y3SIYE;ReKbYqEnt*@zR~VZMDS(5w6(lEYos%0A6qgPww;8Y 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 f)8ih7pMMElClL{08Hul08>ls?IK23OBrtp# diff --git a/tests/ragger/snapshots/flex/test_blind_sign_rejected/00000.png b/tests/ragger/snapshots/flex/test_blind_sign_rejected/00000.png index acbb161dfd465dba1fe0b49424f867d887f47c32..039eff0472fe0760b4f2e38b458f53d7cffc164b 100644 GIT binary patch delta 17777 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%0A6qgPww;8Y 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 f)8ih7pMMElClL{08Hul08>ls?IK23OBrtp# diff --git a/tests/ragger/snapshots/flex/test_sign_parameter_selector/00006.png b/tests/ragger/snapshots/flex/test_sign_parameter_selector/00006.png index acbb161dfd465dba1fe0b49424f867d887f47c32..039eff0472fe0760b4f2e38b458f53d7cffc164b 100644 GIT binary patch delta 17777 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%0A6qgPww;8Y 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 f)8ih7pMMElClL{08Hul08>ls?IK23OBrtp# diff --git a/tests/ragger/snapshots/stax/test_blind_sign/00000.png b/tests/ragger/snapshots/stax/test_blind_sign/00000.png index 9696ae12345b6098c7b397ffe3c35f540de0f477..0463721b10468c6a212697f085f0bed074623082 100644 GIT binary patch literal 17111 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 literal 15903 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 PzM!t6^Q`Kr&71!Qw~1h^ diff --git a/tests/ragger/snapshots/stax/test_blind_sign_nonzero/00000.png b/tests/ragger/snapshots/stax/test_blind_sign_nonzero/00000.png index 9696ae12345b6098c7b397ffe3c35f540de0f477..0463721b10468c6a212697f085f0bed074623082 100644 GIT binary patch literal 17111 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 literal 15903 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 PzM!t6^Q`Kr&71!Qw~1h^ diff --git a/tests/ragger/snapshots/stax/test_blind_sign_rejected/00000.png b/tests/ragger/snapshots/stax/test_blind_sign_rejected/00000.png index 9696ae12345b6098c7b397ffe3c35f540de0f477..0463721b10468c6a212697f085f0bed074623082 100644 GIT binary patch literal 17111 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 literal 15903 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 PzM!t6^Q`Kr&71!Qw~1h^ diff --git a/tests/ragger/snapshots/stax/test_sign_parameter_selector/00006.png b/tests/ragger/snapshots/stax/test_sign_parameter_selector/00006.png index 9696ae12345b6098c7b397ffe3c35f540de0f477..0463721b10468c6a212697f085f0bed074623082 100644 GIT binary patch literal 17111 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 literal 15903 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 PzM!t6^Q`Kr&71!Qw~1h^ From 9c177e9dc9403a64219a01e9b797661d5b411bd9 Mon Sep 17 00:00:00 2001 From: Alexandre Paillier Date: Tue, 28 Jan 2025 16:48:48 +0100 Subject: [PATCH 23/25] Fix for fuzzing false positive with unitialized variables (cherry picked from commit 857a6d7f869c8b056acaa036f565ae7d94493f2a) --- tests/fuzzing/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/fuzzing/CMakeLists.txt b/tests/fuzzing/CMakeLists.txt index 02d603c7e..8ef8e5081 100644 --- a/tests/fuzzing/CMakeLists.txt +++ b/tests/fuzzing/CMakeLists.txt @@ -155,6 +155,7 @@ set(DEFINES HAVE_ENUM_VALUE HAVE_NFT_SUPPORT HAVE_DYNAMIC_NETWORKS + explicit_bzero=bzero # Fix for https://github.com/google/sanitizers/issues/1507 ) add_compile_definitions(${DEFINES}) From 27ee902583f689e7f244dfa7abc49c53563a1333 Mon Sep 17 00:00:00 2001 From: Alexandre Paillier Date: Tue, 28 Jan 2025 17:48:28 +0100 Subject: [PATCH 24/25] Fix fuzzing workflow syntax warnings (cherry picked from commit c5925dc53fc8d11768036ab1664dc786263514a5) --- .github/workflows/cflite_cron.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cflite_cron.yml b/.github/workflows/cflite_cron.yml index 17c1e65a2..440a752f5 100644 --- a/.github/workflows/cflite_cron.yml +++ b/.github/workflows/cflite_cron.yml @@ -28,13 +28,13 @@ jobs: uses: google/clusterfuzzlite/actions/build_fuzzers@v1 with: github-token: ${{ secrets.GITHUB_TOKEN }} - language: c # Change this to the language you are fuzzing. + language: c # Change this to the language you are fuzzing. sanitizer: ${{ matrix.sanitizer }} - name: Run Fuzzers (${{ matrix.mode }} - ${{ matrix.sanitizer }}) id: run uses: google/clusterfuzzlite/actions/run_fuzzers@v1 with: github-token: ${{ secrets.GITHUB_TOKEN }} - fuzz-seconds: 300 # 5 minutes + fuzz-seconds: 300 # 5 minutes mode: ${{ matrix.mode }} sanitizer: ${{ matrix.sanitizer }} From a28266b3cbe9332964621c8a85070feb33c926af Mon Sep 17 00:00:00 2001 From: Alexandre Paillier Date: Wed, 29 Jan 2025 11:22:52 +0100 Subject: [PATCH 25/25] Removed -dev version suffix & updated changelog --- CHANGELOG.md | 28 +++++++++++++++++++++++++++- Makefile | 2 +- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ea0361cc3..f3ec327cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,33 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). -## [1.15.0](../../compare/1.14.0...1.15.0) - 2025-xx-xx +## [1.15.0](../../compare/1.14.0...1.15.0) - 2025-01-30 + +### Added + +- (clone) Harmony +- (network) Sonic +- (network) Soneium +- (network) Swellchain +- (network) Swellchain Testnet +- (network) Soneium Testnet Minato +- (network) Bahamut +- (network) Odyssey Chain +- (network) Lumia +- (network) Harmony ONE S0 +- (network) Harmony ONE S1 + +### Removed + +- (clone) ARTIS tau1 +- (clone) TecraTestnet +- (clone) Volta +- Dynamic networks support from LNS + +### Changed + +- (network) Klaytn Cypress renamed to Kaia Mainnet +- Switched to production PKI key usages ## [1.14.0](../../compare/1.13.0...1.14.0) - 2024-12-19 diff --git a/Makefile b/Makefile index b18b14c96..5fb269659 100644 --- a/Makefile +++ b/Makefile @@ -38,7 +38,7 @@ include ./makefile_conf/chain/$(CHAIN).mk APPVERSION_M = 1 APPVERSION_N = 15 APPVERSION_P = 0 -APPVERSION = $(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P)-dev +APPVERSION = $(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P) # Application source files APP_SOURCE_PATH += src src_features src_plugins