diff --git a/.clang-format b/.clang-format new file mode 100644 index 00000000..949c869c --- /dev/null +++ b/.clang-format @@ -0,0 +1,10 @@ +BasedOnStyle: Google +IndentWidth: 4 +ColumnLimit: 125 +DerivePointerAlignment: false +PointerAlignment: Right +AllowShortFunctionsOnASingleLine: None +AlignConsecutiveMacros: + Enabled: true + AcrossEmptyLines: true + AcrossComments: false diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 00000000..75f10ca4 --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,23 @@ +Checks: "-*, + clang-diagnostic-*, + clang-analyzer-*, + cppcoreguidelines-init-variables, + google-runtime-int, + google-readability-avoid-underscore-in-googletest-name, + misc-*, + performance-*, + portability-*, + readability-*, + -misc-no-recursion, + -readability-function-cognitive-complexity + -readability-magic-numbers" +WarningsAsErrors: "*" +CheckOptions: + - key: readability-identifier-length.MinimumVariableNameLength + value: 2 + - key: readability-identifier-length.MinimumParameterNameLength + value: 2 + - key: readability-identifier-length.MinimumLoopCounterNameLength + value: 1 + - key: readability-magic-numbers.IgnorePowersOf2IntegerValues + value: true diff --git a/.github/workflows/check_version.yml b/.github/workflows/check_version.yml index 871d5fcc..c25b54b1 100644 --- a/.github/workflows/check_version.yml +++ b/.github/workflows/check_version.yml @@ -7,7 +7,7 @@ on: - main - develop - master # for safety reasons - - dev # for safety reasons + # - dev # for safety reasons jobs: configure: diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 166b5f30..a3765510 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -2,27 +2,34 @@ name: Lint and format 💅 on: workflow_dispatch: - # push: - # pull_request: - # branches: - # - main - # - develop + push: + pull_request: + branches: + - main + - develop + - master # for safety reasons + - dev # for safety reasons jobs: lint: - runs-on: ubuntu-latest + runs-on: ${{ github.repository_owner == 'zondax' && 'zondax-runners' || 'ubuntu-latest' }} container: ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder-legacy:latest steps: - uses: actions/checkout@v4 with: submodules: recursive - name: Add missing deps + env: + DEBIAN_FRONTEND: noninteractive run: | - DEBIAN_FRONTEND=noninteractive apt-get update apt-get install -y bear sudo - name: Generate compilation database run: bear -- make -j BOLOS_SDK="$NANOSP_SDK" + - name: Setup python + uses: actions/setup-python@v5 + with: + python-version: "3.11" - name: Lint and format 💅 uses: cpp-linter/cpp-linter-action@v2 id: linter diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 2df9ea0b..532d4591 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -57,6 +57,10 @@ jobs: run: | cd ./app/rust cargo clippy --all-targets --features "clippy" + - name: cargo fmt + run: | + cd ./app/rust + cargo fmt build_ledger: needs: configure @@ -264,3 +268,84 @@ jobs: tag_name: ${{ steps.flex.outputs.tag_name }} draft: false prerelease: false + + fuzzing: + name: fuzzing + runs-on: ${{ github.repository_owner == 'zondax' && 'zondax-runners' || 'ubuntu-latest' }} + container: + image: rust:latest + steps: + - uses: actions/checkout@v3 + + # Install only the additional dependencies needed for honggfuzz + - name: Install system dependencies + run: | + apt-get update && apt-get install -y \ + binutils-dev \ + libunwind-dev \ + libblocksruntime-dev \ + liblzma-dev + + - name: Install honggfuzz + run: cargo install honggfuzz + + - name: Generate corpus + run: | + cd app/hfuzz-parser/corpus + cargo run + + # Different fuzzing durations based on trigger + - name: Quick fuzz (PR) + if: github.event_name == 'push' + run: | + cd app/hfuzz-parser + timeout --preserve-status 5m cargo hfuzz run transaction ../hfuzz_corpus/ + + - name: Medium fuzz (main) + if: github.event_name == 'pull_request' + run: | + cd app/hfuzz-parser + timeout --preserve-status 15m cargo hfuzz run transaction ../hfuzz_corpus/ + + - name: Extended fuzz (weekly) + if: github.event_name == 'schedule' + run: | + cd app/hfuzz-parser + timeout --preserve-status 30m cargo hfuzz run transaction ../hfuzz_corpus/ + + - name: Check for crashes + run: | + if ls app/hfuzz-parser/hfuzz_workspace/transaction/SIGABRT.PC.* 1> /dev/null 2>&1; then + echo "::error::Crashes found during fuzzing!" + exit 1 + fi + + - name: Upload crash artifacts + if: failure() + uses: actions/upload-artifact@v3 + with: + name: crash-reports + path: | + app/hfuzz-parser/hfuzz_workspace/transaction/SIGABRT.PC.* + app/hfuzz-parser/hfuzz_workspace/transaction/HONGGFUZZ.REPORT.TXT + app/hfuzz-parser/hfuzz_workspace/transaction/input/ + + - name: Cache corpus + uses: actions/cache@v3 + with: + path: app/hfuzz_corpus + key: ${{ runner.os }}-fuzz-corpus-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-fuzz-corpus- + + - name: Notify on failure + if: failure() + uses: actions/github-script@v6 + with: + script: | + github.rest.issues.create({ + owner: context.repo.owner, + repo: context.repo.repo, + title: 'Fuzzing found crashes', + body: 'Fuzzing job failed. Check the artifacts in the workflow run.' + }) diff --git a/.gitignore b/.gitignore index fa117508..925727ff 100644 --- a/.gitignore +++ b/.gitignore @@ -90,5 +90,6 @@ app/output/*.sha256 app/pkg/* app/rust/.cargo/.package-cache-mutate +app/hfuzz_corpus diff --git a/Makefile b/Makefile index b4767ca6..cdfa1480 100644 --- a/Makefile +++ b/Makefile @@ -45,7 +45,8 @@ prod: make PRODUCTION_BUILD=1 rust_fuzz: - cd app/hfuzz-parser/ && cargo hfuzz run transaction + cd app/hfuzz-parser/corpus/ && cargo run + cd app/hfuzz-parser/ && cargo hfuzz run transaction app/hfuzz_corpus diff --git a/app/FUZZING.md b/app/FUZZING.md index 44323d37..5f2d097d 100644 --- a/app/FUZZING.md +++ b/app/FUZZING.md @@ -35,6 +35,13 @@ cargo hfuzz run-debug transaction hfuzz_workspace/*/*.fuzz ``` -This will deploy a gdb console with a backtrace with the first crash +To opt to use _gdb_ instead of `lldb`, you can configure it before running the debugger with: + +```bash +export HFUZZ_DEBUGGER="rust-gdb" + +``` + +This will deploy a **gdb** console with a backtrace with the first crash _note_: There could be more than one _.fuzz_ file. diff --git a/app/hfuzz-parser/Cargo.lock b/app/hfuzz-parser/Cargo.lock index 349e182f..23bb266a 100644 --- a/app/hfuzz-parser/Cargo.lock +++ b/app/hfuzz-parser/Cargo.lock @@ -41,6 +41,12 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + [[package]] name = "block-buffer" version = "0.9.0" @@ -150,12 +156,32 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +[[package]] +name = "lexical-core" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6607c62aa161d23d17a9072cc5da0be67cdfc89d3afb1e8d9c842bebc2525ffe" +dependencies = [ + "arrayvec", + "bitflags", + "cfg-if", + "libm", + "ryu", + "static_assertions", +] + [[package]] name = "libc" version = "0.2.157" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "374af5f94e54fa97cf75e945cce8a6b201e88a1a07e688b47dfd2a59c66dbd86" +[[package]] +name = "libm" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" + [[package]] name = "lock_api" version = "0.4.12" @@ -241,6 +267,7 @@ dependencies = [ "arrayvec", "base64", "hex", + "lexical-core", "no-std-compat", "nom", "numtoa", @@ -335,6 +362,12 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + [[package]] name = "syn" version = "2.0.75" diff --git a/app/hfuzz-parser/corpus/Cargo.lock b/app/hfuzz-parser/corpus/Cargo.lock new file mode 100644 index 00000000..a3eb7a5b --- /dev/null +++ b/app/hfuzz-parser/corpus/Cargo.lock @@ -0,0 +1,16 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "corpus-generator" +version = "0.1.0" +dependencies = [ + "hex", +] + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" diff --git a/app/hfuzz-parser/corpus/Cargo.toml b/app/hfuzz-parser/corpus/Cargo.toml new file mode 100644 index 00000000..2970ea09 --- /dev/null +++ b/app/hfuzz-parser/corpus/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "corpus-generator" +version = "0.1.0" +edition = "2021" + +[dependencies] +hex = "0.4.3" diff --git a/app/hfuzz-parser/corpus/src/main.rs b/app/hfuzz-parser/corpus/src/main.rs new file mode 100644 index 00000000..4c3c208e --- /dev/null +++ b/app/hfuzz-parser/corpus/src/main.rs @@ -0,0 +1,46 @@ +use hex::decode; +use std::fs; + +fn generate_corpus() -> Result<(), std::io::Error> { + let corpus_dir = "../../hfuzz_corpus"; + fs::create_dir_all(corpus_dir)?; + + // Contract call with 20 args + let contract_call = "0000000001040097432af9a5c04675136b8c2badfbfe9bf17fa804000000000000003500000000000003e800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003020000000300021697432af9a5c04675136b8c2badfbfe9bf17fa8040100000000000000640003167c5f674a8fd08efa61dd9b11121e046dd2c892730a756e6976322d636f72650500000000000000010103167c5f674a8fd08efa61dd9b11121e046dd2c892730a756e6976322d636f7265167c5f674a8fd08efa61dd9b11121e046dd2c892730b76656c61722d746f6b656e0576656c6172030000000000000b3f02167c5f674a8fd08efa61dd9b11121e046dd2c8927311706174682d6170706c795f76315f325f30056170706c79000000180b000000010c0000000601610d0000000175016206167c5f674a8fd08efa61dd9b11121e046dd2c892730976656c61722d73747801630100000000000000000000000000000015016406167c5f674a8fd08efa61dd9b11121e046dd2c892730477737478016506167c5f674a8fd08efa61dd9b11121e046dd2c892730b76656c61722d746f6b656e01660401000000000000000000000000000000640a06167c5f674a8fd08efa61dd9b11121e046dd2c8927304777374780a06167c5f674a8fd08efa61dd9b11121e046dd2c892730b76656c61722d746f6b656e0909090a06167c5f674a8fd08efa61dd9b11121e046dd2c8927312756e6976322d73686172652d6665652d746f09090909090909090909090909090909"; + + // Swap transaction + let swap = "000000000104009ef3889fd070159edcd8ef88a0ec87cea1592c83000000000000000000000000000f42400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000302000000060002169ef3889fd070159edcd8ef88a0ec87cea1592c830100000000000027100003167c5f674a8fd08efa61dd9b11121e046dd2c892730a756e6976322d636f72650300000000000000000103167c5f674a8fd08efa61dd9b11121e046dd2c892730a756e6976322d636f7265168c5e2f8d25627d6edebeb6d10fa3300f5acc8441086c6f6e67636f696e086c6f6e67636f696e0300000000000000000103167c5f674a8fd08efa61dd9b11121e046dd2c892730a756e6976322d636f7265168c5e2f8d25627d6edebeb6d10fa3300f5acc8441086c6f6e67636f696e086c6f6e67636f696e0300000000000000000102169ef3889fd070159edcd8ef88a0ec87cea1592c83168c5e2f8d25627d6edebeb6d10fa3300f5acc8441086c6f6e67636f696e086c6f6e67636f696e030000000000000000010316402da2c079e5d31d58b9cfc7286d1b1eb2f7834e0f616d6d2d7661756c742d76322d303116402da2c079e5d31d58b9cfc7286d1b1eb2f7834e0a746f6b656e2d616c657804616c65780300000000011c908a02162ec1a2dc2904ebc8b408598116c75e42c51afa2617726f757465722d76656c61722d616c65782d762d312d320d737761702d68656c7065722d6100000007010000000000000000000000000000271001000000000000000000000000011c908a040c00000002016106167c5f674a8fd08efa61dd9b11121e046dd2c892730477737478016206168c5e2f8d25627d6edebeb6d10fa3300f5acc8441086c6f6e67636f696e06167c5f674a8fd08efa61dd9b11121e046dd2c8927312756e6976322d73686172652d6665652d746f0c0000000201610616402da2c079e5d31d58b9cfc7286d1b1eb2f7834e0b746f6b656e2d776c6f6e6701620616402da2c079e5d31d58b9cfc7286d1b1eb2f7834e0a746f6b656e2d616c65780c0000000101610100000000000000000000000005f5e100"; + + // Versioned smart contract + let versioned_contract = "8080000000040060dbb32efe0c56e1d418c020f4cb71c556b6a60d0000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000301000000000602107468656e2d677265656e2d6d61636177000004cf3b3b2068656c6c6f2d776f726c6420636f6e74726163740a0a28646566696e652d636f6e7374616e742073656e6465722027535a324a365a593438475631455a35563256355242394d5036365357383650594b4b51394836445052290a28646566696e652d636f6e7374616e7420726563697069656e742027534d324a365a593438475631455a35563256355242394d5036365357383650594b4b51565838583047290a0a28646566696e652d66756e6769626c652d746f6b656e206e6f76656c2d746f6b656e2d3139290a2866742d6d696e743f206e6f76656c2d746f6b656e2d3139207531322073656e646572290a2866742d7472616e736665723f206e6f76656c2d746f6b656e2d31392075322073656e64657220726563697069656e74290a0a28646566696e652d6e6f6e2d66756e6769626c652d746f6b656e2068656c6c6f2d6e66742075696e74290a0a286e66742d6d696e743f2068656c6c6f2d6e66742075312073656e646572290a286e66742d6d696e743f2068656c6c6f2d6e66742075322073656e646572290a286e66742d7472616e736665723f2068656c6c6f2d6e66742075312073656e64657220726563697069656e74290a0a28646566696e652d7075626c69632028746573742d656d69742d6576656e74290a202028626567696e0a20202020287072696e7420224576656e74212048656c6c6f20776f726c64220a20202020286f6b207531290a2020290a290a0a28626567696e2028746573742d656d69742d6576656e7429290a0a28646566696e652d7075626c69632028746573742d6576656e742d7479706573290a202028626567696e0a2020202028756e777261702d70616e6963202866742d6d696e743f206e6f76656c2d746f6b656e2d313920753320726563697069656e7429290a2020202028756e777261702d70616e696320286e66742d6d696e743f2068656c6c6f2d6e667420753220726563697069656e7429290a2020202028756e777261702d70616e696320287374782d7472616e736665723f207536302074782d73656e6465722027535a324a365a593438475631455a35563256355242394d5036365357383650594b4b5139483644505229290a2020202028756e777261702d70616e696320287374782d6275726e3f207532302074782d73656e64657229290a20202020286f6b207531290a2020290a290a0a28646566696e652d6d61702073746f7265207b206b65793a20286275666620333229207d207b2076616c75653a20286275666620333229207d290a0a28646566696e652d7075626c696320286765742d76616c756520286b65792028627566662033322929290a202028626567696e0a20202020286d6174636820286d61702d6765743f2073746f7265207b206b65793a206b6579207d290a202020202020656e74727920286f6b20286765742076616c756520656e74727929290a202020202020286572722030290a20202020290a2020290a290a0a28646566696e652d7075626c696320287365742d76616c756520286b65792028627566662033322929202876616c75652028627566662033322929290a202028626567696e0a20202020286d61702d7365742073746f7265207b206b65793a206b6579207d207b2076616c75653a2076616c7565207d290a20202020286f6b207531290a2020290a290a"; // truncated for brevity + + // With 7 post conditions + let multi_post_conditions = "808000000004002d89de56fd4db19741957831926e9ba96cf04158000000000000000300000000000000000001b019126ffa434bd7c816b3e1daa3163e322aae6cde06585d22d46286570e4a491eecc2dcd214a42eae62584ddbe8a96382ff1f34edb4ecedeab0a6b6b1e07d2003020000000701031a2d89de56fd4db19741957831926e9ba96cf041580b68656c6c6f2d776f726c641a2d89de56fd4db19741957831926e9ba96cf041580b68656c6c6f2d776f726c640a737461636b61726f6f73010000000000000064000103000000000000007c01031a2d89de56fd4db19741957831926e9ba96cf041580b68656c6c6f2d776f726c641a2d89de56fd4db19741957831926e9ba96cf041580b68656c6c6f2d776f726c640a737461636b61726f6f7303000000000000006400010300000000000000f701031a2d89de56fd4db19741957831926e9ba96cf041580b68656c6c6f2d776f726c641a2d89de56fd4db19741957831926e9ba96cf041580b68656c6c6f2d776f726c640a737461636b61726f6f73050000000000000064000103000000000000017202031a2d89de56fd4db19741957831926e9ba96cf041580b68656c6c6f2d776f726c641a2d89de56fd4db19741957831926e9ba96cf041580b68656c6c6f2d776f726c64056e616d657302000000040000006410021a2d89de56fd4db19741957831926e9ba96cf041580b68656c6c6f2d776f726c640f73656e642d737461636b61726f6f7300000001051a3b471808467d33eec688b7a7a75f06aad921ba6e"; + + // With fungible post conditions + let fungible_post_conditions = "808000000004003b471808467d33eec688b7a7a75f06aad921ba6e000000000000000100000000000000000000134ab418c3422c600bfeffb1a322b78edab12961fdea48f34cbbb4eae42a4a53401bf2a0d680e819028276cfa13c672a8031ddd17b46fda70a037fefb20e9e9203020000000101021a3b471808467d33eec688b7a7a75f06aad921ba6e1a2d89de56fd4db19741957831926e9ba96cf041580b68656c6c6f2d776f726c640a737461636b61726f6f73030000000000000064021a2d89de56fd4db19741957831926e9ba96cf041580b68656c6c6f2d776f726c6414757365722d73656e642d737461636b61726f6f7300000001051a2d89de56fd4db19741957831926e9ba96cf04158"; + + // Token transfer + let token_transfer = "8080000000040156da933238491425e460d335d3af8e04fd3e59970000000000000000000000000000000000000001020164b3d6fc5f1ac5093343f4b48dcfda73d85dbfccec276418e71fc928acc412fc62525e67103bee36df5e7ed07b73b668a27ab3703ce2d018a98a161c46bdcac2000203020000000000051abaa6de6c1badf30afa816e2c66db3125034facab00000000002625a06d756c746973696720747800000000000000000000000000000000000000000000006f7a42ccdce26688916ef6c182001fd1c703941c1224a9845ee54db9918acf67000164b3d6fc5f1ac5093343f4b48dcfda73d85dbfccec276418e71fc928acc412fc62525e67103bee36df5e7ed07b73b668a27ab3703ce2d018a98a161c46bdcac2"; + + // Write each transaction type to a separate file + let transactions = [ + ("contract_call", contract_call), + ("swap", swap), + ("versioned_contract", versioned_contract), + ("multi_post_conditions", multi_post_conditions), + ("fungible_post_conditions", fungible_post_conditions), + ("token_transfer", token_transfer), + ]; + + for (name, hex_str) in transactions { + let bytes = decode(hex_str).expect("Invalid hex string"); + fs::write(format!("{}/{}_{}", corpus_dir, name, bytes.len()), bytes)?; + } + + Ok(()) +} + +fn main() { + generate_corpus().expect("Failed to generate corpus"); +} diff --git a/app/rust/Cargo.toml b/app/rust/Cargo.toml index 1f0e96cf..6d53f0a5 100644 --- a/app/rust/Cargo.toml +++ b/app/rust/Cargo.toml @@ -41,15 +41,6 @@ serde = { version = "1.0", features = ["derive"] } sha2 = { version = "0.9.1" } base64 = { version = "0.13.0" } - -[target.'cfg(fuzzing)'.dependencies] -no-std-compat = { version = "0.4.1", features = ["std"] } -sha2 = { version = "0.9.1" } -hex = { version = "0.4" } -serde-json-core = { version = "0.4.0", features = ["std"] } -serde = { version = "1.0", features = ["derive"] } -base64 = { version = "0.13.0" } - [profile.release] lto = false codegen-units = 1 diff --git a/app/rust/native/Cargo.toml b/app/rust/native/Cargo.toml index 550d0ac8..82593d9d 100644 --- a/app/rust/native/Cargo.toml +++ b/app/rust/native/Cargo.toml @@ -21,6 +21,7 @@ hex = { version = "0.4", default-features = false } serde = { version = "1.0", default-features = false, features = ["derive"] } serde-json-core = { version = "0.4.0", features = ["std"] } nom = { version = "7.1.2", default-features = false } +lexical-core = { version = "0.7", features = ["libm"] } [dependencies.arrayvec] @@ -39,11 +40,13 @@ base64 = { version = "0.13.0" } [target.'cfg(fuzzing)'.dependencies] -sha2 = { version = "0.9.1" } no-std-compat = { version = "0.4.1", features = ["std"] } +sha2 = { version = "0.9.1" } hex = { version = "0.4" } +serde-json-core = { version = "0.4.0", features = ["std"] } serde = { version = "1.0", features = ["derive"] } base64 = { version = "0.13.0" } +lexical-core = { version = "0.7", features = ["libm"] } [profile.release] lto = false diff --git a/app/rust/src/parser/post_conditions.rs b/app/rust/src/parser/post_conditions.rs index 2f108237..fb3df585 100644 --- a/app/rust/src/parser/post_conditions.rs +++ b/app/rust/src/parser/post_conditions.rs @@ -83,26 +83,31 @@ impl<'a> TransactionPostCondition<'a> { } pub fn read_as_bytes(bytes: &'a [u8]) -> nom::IResult<&[u8], &[u8], ParserError> { - let cond_type = le_u8(bytes)?; - let (raw, _) = PostConditionPrincipal::read_as_bytes(cond_type.0)?; - let mut len = bytes.len() - raw.len(); - len += match PostConditionType::try_from(cond_type.1)? { + let rem = bytes; + let (rem, cond_type) = le_u8(rem)?; + let (mut rem, _) = PostConditionPrincipal::read_as_bytes(rem)?; + + match PostConditionType::try_from(cond_type)? { PostConditionType::Stx => { // We take 9-bytes which comprises the 8-byte amount + 1-byte fungible code - 9usize + let (raw, _) = take(9usize)(rem)?; + rem = raw; } PostConditionType::FungibleToken => { - let (_, asset) = AssetInfo::read_as_bytes(raw)?; + let (raw, _) = AssetInfo::read_as_bytes(rem)?; // We take 9-bytes which containf the 8-byte amount + 1-byte fungible code - asset.len() + 9 + let (raw, _) = take(9usize)(raw)?; + rem = raw; } PostConditionType::NonFungibleToken => { - let (asset_raw, asset) = AssetInfo::read_as_bytes(raw)?; - let value_len = Value::value_len::(asset_raw)?; - asset.len() + value_len + 1 + let (asset_raw, _) = AssetInfo::read_as_bytes(rem)?; + let (raw, _) = Value::from_bytes::(asset_raw)?; + let (raw, _) = take(1usize)(raw)?; + rem = raw; } }; crate::check_canary!(); + let len = bytes.len() - rem.len(); take(len)(bytes) } diff --git a/app/rust/src/parser/transaction.rs b/app/rust/src/parser/transaction.rs index 2867d710..268a4af8 100644 --- a/app/rust/src/parser/transaction.rs +++ b/app/rust/src/parser/transaction.rs @@ -1,8 +1,8 @@ use core::fmt::Write; use nom::{ - branch::permutation, bytes::complete::take, number::complete::{be_u32, le_u8}, + sequence::tuple, }; use crate::{ @@ -211,7 +211,7 @@ impl<'a> Transaction<'a> { } pub fn from_bytes(bytes: &'a [u8]) -> Result { - match permutation(( + match tuple(( TransactionVersion::from_bytes, be_u32, TransactionAuth::from_bytes, diff --git a/app/rust/src/parser/transaction_payload/arguments.rs b/app/rust/src/parser/transaction_payload/arguments.rs index e4375ec9..0a5ac67c 100644 --- a/app/rust/src/parser/transaction_payload/arguments.rs +++ b/app/rust/src/parser/transaction_payload/arguments.rs @@ -1,14 +1,14 @@ use nom::{bytes::complete::take, number::complete::be_u32}; use crate::{ - check_canary, is_expert_mode, + check_canary, parser::{ParserError, Value, TX_DEPTH_LIMIT}, }; // The number of contract call arguments we can handle. // this can be adjusted, but keep in mind that higher values could // hit stack overflows issues. -pub const MAX_NUM_ARGS: u32 = 10; +// pub const MAX_NUM_ARGS: u32 = 30; #[repr(C)] #[derive(Clone, PartialEq)] @@ -22,9 +22,13 @@ impl<'a> Arguments<'a> { let (mut rem, num_args) = be_u32::<_, ParserError>(bytes)?; - if num_args > MAX_NUM_ARGS && !is_expert_mode() { - return Err(ParserError::InvalidTransactionPayload.into()); - } + // Remove this check, this does not affect memory consumption + // and allow user to sign streamline contract calls that in practice have + // more that 30 arguments, for example swap transactions. + // see: https://github.com/Zondax/ledger-stacks/issues/176 + // if num_args > MAX_NUM_ARGS && !is_expert_mode() { + // return Err(ParserError::InvalidTransactionPayload.into()); + // } // Parse all arguments so we can be sure that at runtime when each // argument is retrieved it does not crashes diff --git a/app/rust/src/parser/tx_post_conditions.rs b/app/rust/src/parser/tx_post_conditions.rs index f1cd8c8c..28b828ad 100644 --- a/app/rust/src/parser/tx_post_conditions.rs +++ b/app/rust/src/parser/tx_post_conditions.rs @@ -1,8 +1,5 @@ use arrayvec::ArrayVec; -use nom::{ - combinator::iterator, - number::complete::{be_u32, le_u8}, -}; +use nom::number::complete::{be_u32, le_u8}; use crate::{bolos::c_zemu_log_stack, check_canary, parser::TransactionPostCondition}; @@ -51,28 +48,73 @@ impl<'a> PostConditions<'a> { #[inline(never)] pub fn from_bytes(bytes: &'a [u8]) -> nom::IResult<&[u8], Self, ParserError> { let (raw, len) = be_u32::<_, ParserError>(bytes)?; + let conditions_len = len as usize; - if len > NUM_SUPPORTED_POST_CONDITIONS as u32 { + // Validate length + if conditions_len > NUM_SUPPORTED_POST_CONDITIONS { return Err(nom::Err::Error(ParserError::ValueOutOfRange)); } + let mut conditions: ArrayVec<[&'a [u8]; NUM_SUPPORTED_POST_CONDITIONS]> = ArrayVec::new(); - let mut iter = iterator(raw, TransactionPostCondition::read_as_bytes); - iter.take(len as _).enumerate().for_each(|i| { - conditions.push(i.1); - }); - let res = iter.finish()?; - let num_items = Self::get_num_items(&conditions[..len as usize]); + let mut current_input = raw; + + // Safely iterate exactly len times + for _ in 0..conditions_len { + match TransactionPostCondition::read_as_bytes(current_input) { + Ok((remaining, item)) => { + current_input = remaining; + // Safe push with error handling + if conditions.try_push(item).is_err() { + return Err(nom::Err::Error(ParserError::ValueOutOfRange)); + } + } + Err(e) => return Err(e), + } + } + + if conditions.len() != conditions_len { + return Err(nom::Err::Error(ParserError::ValueOutOfRange)); + } + + let num_items = Self::get_num_items(&conditions); check_canary!(); + + let num_conditions = conditions.len(); + Ok(( - res.0, + current_input, Self { conditions, num_items, current_idx: 0, - num_conditions: len as usize, + num_conditions, }, )) } + // pub fn from_bytes(bytes: &'a [u8]) -> nom::IResult<&[u8], Self, ParserError> { + // let (raw, len) = be_u32::<_, ParserError>(bytes)?; + // + // if len > NUM_SUPPORTED_POST_CONDITIONS as u32 { + // return Err(nom::Err::Error(ParserError::ValueOutOfRange)); + // } + // let mut conditions: ArrayVec<[&'a [u8]; NUM_SUPPORTED_POST_CONDITIONS]> = ArrayVec::new(); + // let mut iter = iterator(raw, TransactionPostCondition::read_as_bytes); + // iter.take(len as _).enumerate().for_each(|i| { + // conditions.push(i.1); + // }); + // let res = iter.finish()?; + // let num_items = Self::get_num_items(&conditions[..len as usize]); + // check_canary!(); + // Ok(( + // res.0, + // Self { + // conditions, + // num_items, + // current_idx: 0, + // num_conditions: len as usize, + // }, + // )) + // } pub fn get_num_items(conditions: &[&[u8]]) -> u8 { conditions diff --git a/app/src/addr.c b/app/src/addr.c index 118e06b8..7bb07db8 100644 --- a/app/src/addr.c +++ b/app/src/addr.c @@ -1,26 +1,27 @@ /******************************************************************************* -* (c) 2020 Zondax GmbH -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * (c) 2020 Zondax GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #include + +#include "app_mode.h" #include "coin.h" +#include "crypto.h" #include "zxerror.h" -#include "zxmacros.h" #include "zxformat.h" -#include "app_mode.h" -#include "crypto.h" +#include "zxmacros.h" zxerr_t addr_getNumItems(uint8_t *num_items) { zemu_log_stack("addr_getNumItems"); @@ -31,15 +32,13 @@ zxerr_t addr_getNumItems(uint8_t *num_items) { return zxerr_ok; } -zxerr_t addr_getItem(int8_t displayIdx, - char *outKey, uint16_t outKeyLen, - char *outVal, uint16_t outValLen, - uint8_t pageIdx, uint8_t *pageCount) { +zxerr_t addr_getItem(int8_t displayIdx, char *outKey, uint16_t outKeyLen, char *outVal, uint16_t outValLen, uint8_t pageIdx, + uint8_t *pageCount) { zemu_log_stack("addr_getItem"); switch (displayIdx) { case 0: snprintf(outKey, outKeyLen, "Address"); - pageString(outVal, outValLen, (char *) (G_io_apdu_buffer + VIEW_ADDRESS_OFFSET_SECP256K1), pageIdx, pageCount); + pageString(outVal, outValLen, (char *)(G_io_apdu_buffer + VIEW_ADDRESS_OFFSET_SECP256K1), pageIdx, pageCount); return zxerr_ok; case 1: { if (!app_mode_expert()) { diff --git a/app/src/addr.h b/app/src/addr.h index 01406719..2aaf3acb 100644 --- a/app/src/addr.h +++ b/app/src/addr.h @@ -1,32 +1,32 @@ /******************************************************************************* -* (c) 2020 Zondax GmbH -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * (c) 2020 Zondax GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #pragma once #ifdef __cplusplus extern "C" { #endif +#include +#include "zxerror.h" /// Return the number of items in the address view zxerr_t addr_getNumItems(uint8_t *num_items); /// Gets an specific item from the address view (including paging) -zxerr_t addr_getItem(int8_t displayIdx, - char *outKey, uint16_t outKeyLen, - char *outValue, uint16_t outValueLen, +zxerr_t addr_getItem(int8_t displayIdx, char *outKey, uint16_t outKeyLen, char *outValue, uint16_t outValueLen, uint8_t pageIdx, uint8_t *pageCount); #ifdef __cplusplus diff --git a/app/src/apdu_handler.c b/app/src/apdu_handler.c index 5736e561..7a054206 100644 --- a/app/src/apdu_handler.c +++ b/app/src/apdu_handler.c @@ -1,51 +1,48 @@ /******************************************************************************* -* (c) 2018, 2019 Zondax GmbH -* (c) 2016 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * (c) 2018, 2019 Zondax GmbH + * (c) 2016 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ -#include "app_main.h" - -#include -#include #include +#include +#include -#include "view.h" #include "actions.h" -#include "tx.h" #include "addr.h" -#include "crypto.h" +#include "app_main.h" #include "coin.h" -#include "zxmacros.h" +#include "crypto.h" +#include "tx.h" +#include "view.h" #include "view_internal.h" +#include "zxmacros.h" static bool tx_initialized = false; __Z_INLINE void extractHDPath(uint32_t rx, uint32_t offset, uint32_t path_len) { - if ((rx - offset) < sizeof(uint32_t) * path_len) { - THROW(APDU_CODE_WRONG_LENGTH); + THROW(APDU_CODE_WRONG_LENGTH); } MEMCPY(hdPath, G_io_apdu_buffer + offset, sizeof(uint32_t) * path_len); hdPath_len = path_len; } - - __Z_INLINE bool process_chunk(uint32_t rx) { - const uint8_t payloadType = G_io_apdu_buffer[OFFSET_PAYLOAD_TYPE]; + uint8_t payloadType = 0; + payloadType = G_io_apdu_buffer[OFFSET_PAYLOAD_TYPE]; if (rx < OFFSET_DATA) { THROW(APDU_CODE_WRONG_LENGTH); @@ -55,8 +52,7 @@ __Z_INLINE bool process_chunk(uint32_t rx) { THROW(APDU_CODE_INVALIDP1P2); } - - uint32_t added; + uint32_t added = 0; switch (payloadType) { case 0: tx_initialize(); @@ -89,33 +85,29 @@ __Z_INLINE bool process_chunk(uint32_t rx) { } __Z_INLINE void extract_default_path(uint32_t rx, uint32_t offset) { - extractHDPath(rx, offset, HDPATH_LEN_DEFAULT); // validate - bool mainnet = hdPath[0] == HDPATH_0_DEFAULT && - hdPath[1] == HDPATH_1_DEFAULT; + bool mainnet = false; + mainnet = hdPath[0] == HDPATH_0_DEFAULT && hdPath[1] == HDPATH_1_DEFAULT; mainnet |= (hdPath[0] == HDPATH_0_ALTERNATIVE); - const bool testnet = hdPath[0] == HDPATH_0_TESTNET && - hdPath[1] == HDPATH_1_TESTNET; + bool testnet = false; + testnet = hdPath[0] == HDPATH_0_TESTNET && hdPath[1] == HDPATH_1_TESTNET; - if (!mainnet && !testnet) + if (!mainnet && !testnet) { THROW(APDU_CODE_DATA_INVALID); - + } } __Z_INLINE void extract_identity_path(uint32_t rx, uint32_t offset) { - extractHDPath(rx, offset, HDPATH_LEN_AUTH); // validate - const bool identity_path = hdPath[0] == HDPATH_0_AUTH && - hdPath[1] == HDPATH_1_AUTH; - if (!identity_path) - THROW(APDU_CODE_DATA_INVALID); - + bool identity_path = false; + identity_path = hdPath[0] == HDPATH_0_AUTH && hdPath[1] == HDPATH_1_AUTH; + if (!identity_path) THROW(APDU_CODE_DATA_INVALID); } __Z_INLINE void handle_getversion(volatile uint32_t *flags, volatile uint32_t *tx, uint32_t rx) { @@ -143,12 +135,15 @@ __Z_INLINE void handle_getversion(volatile uint32_t *flags, volatile uint32_t *t __Z_INLINE void handleGetAddrSecp256K1(volatile uint32_t *flags, volatile uint32_t *tx, uint32_t rx) { extract_default_path(rx, OFFSET_DATA); - uint8_t requireConfirmation = G_io_apdu_buffer[OFFSET_P1]; - uint8_t network = G_io_apdu_buffer[OFFSET_P2]; + uint8_t requireConfirmation = 0; + uint8_t network = 0; + requireConfirmation = G_io_apdu_buffer[OFFSET_P1]; + network = G_io_apdu_buffer[OFFSET_P2]; // Set the address version - if (!set_network_version(network)) + if (!set_network_version(network)) { return THROW(APDU_CODE_DATA_INVALID); + } if (requireConfirmation) { app_fill_address(addr_secp256k1); @@ -194,7 +189,6 @@ __Z_INLINE void SignSecp256K1(volatile uint32_t *flags, volatile uint32_t *tx, u *flags |= IO_ASYNCH_REPLY; } - __Z_INLINE void handleSignSecp256K1(volatile uint32_t *flags, volatile uint32_t *tx, uint32_t rx) { // check first for the expected path at initialization if (G_io_apdu_buffer[OFFSET_PAYLOAD_TYPE] == 0) { @@ -216,10 +210,8 @@ __Z_INLINE void handleSignJwtSecp256K1(volatile uint32_t *flags, volatile uint32 void handleApdu(volatile uint32_t *flags, volatile uint32_t *tx, uint32_t rx) { uint16_t sw = 0; - BEGIN_TRY - { - TRY - { + BEGIN_TRY { + TRY { if (G_io_apdu_buffer[OFFSET_CLA] != CLA) { THROW(APDU_CODE_CLA_NOT_SUPPORTED); } @@ -270,27 +262,24 @@ void handleApdu(volatile uint32_t *flags, volatile uint32_t *tx, uint32_t rx) { THROW(APDU_CODE_INS_NOT_SUPPORTED); } } - CATCH(EXCEPTION_IO_RESET) - { + CATCH(EXCEPTION_IO_RESET) { THROW(EXCEPTION_IO_RESET); } - CATCH_OTHER(e) - { - switch (e & 0xF000) { + CATCH_OTHER(err) { + switch (err & 0xF000) { case 0x6000: case APDU_CODE_OK: - sw = e; + sw = err; break; default: - sw = 0x6800 | (e & 0x7FF); + sw = 0x6800 | (err & 0x7FF); break; } G_io_apdu_buffer[*tx] = sw >> 8; G_io_apdu_buffer[*tx + 1] = sw; *tx += 2; } - FINALLY - { + FINALLY { } } END_TRY; diff --git a/app/src/c_api/rust.c b/app/src/c_api/rust.c index 4712ef3d..574c4cbb 100644 --- a/app/src/c_api/rust.c +++ b/app/src/c_api/rust.c @@ -1,9 +1,9 @@ #include -#include #include -#include "os.h" -#include "cx.h" +#include +#include "cx.h" +#include "os.h" uint16_t fp_uint64_to_str(char *out, uint16_t outLen, const uint64_t value, uint8_t decimals) { return fpuint64_to_str(out, outLen, value, decimals); diff --git a/app/src/coin.h b/app/src/coin.h index 3c283720..b01fbff0 100644 --- a/app/src/coin.h +++ b/app/src/coin.h @@ -1,18 +1,18 @@ /******************************************************************************* -* (c) 2020 Zondax GmbH -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * (c) 2020 Zondax GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #pragma once #if defined(APP_STANDARD) diff --git a/app/src/coin_standard.h b/app/src/coin_standard.h index 4817baa9..2de9fabd 100644 --- a/app/src/coin_standard.h +++ b/app/src/coin_standard.h @@ -1,30 +1,30 @@ /******************************************************************************* -* (c) 2019 Zondax GmbH -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * (c) 2019 Zondax GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #pragma once #ifdef __cplusplus extern "C" { #endif -#include #include +#include -#define CLA 0x09 +#define CLA 0x09 -#define HDPATH_LEN_DEFAULT 5 +#define HDPATH_LEN_DEFAULT 5 // support m/888'/0'/ path #define HDPATH_LEN_AUTH 3 @@ -37,40 +37,40 @@ extern "C" { #define HDPATH_0_AUTH (0x80000000u | 888) #define HDPATH_1_AUTH (0x80000000u | 0) -#define HDPATH_0_ALTERNATIVE (0x80000000u | 5757) +#define HDPATH_0_ALTERNATIVE (0x80000000u | 5757) #define HDPATH_0_TESTNET (0x80000000u | 0x2cu) #define HDPATH_1_TESTNET (0x80000000u | 0x1u) // compressed key -#define PK_LEN_SECP256K1 33u +#define PK_LEN_SECP256K1 33u typedef enum { addr_secp256k1 = 0, } address_kind_e; -#define VIEW_ADDRESS_OFFSET_SECP256K1 PK_LEN_SECP256K1 -#define VIEW_ADDRESS_ITEM_COUNT 2 -#define VIEW_ADDRESS_LAST_PAGE_DEFAULT 255 +#define VIEW_ADDRESS_OFFSET_SECP256K1 PK_LEN_SECP256K1 +#define VIEW_ADDRESS_ITEM_COUNT 2 +#define VIEW_ADDRESS_LAST_PAGE_DEFAULT 255 -#define MENU_MAIN_APP_LINE1 "Stacks" -#define MENU_MAIN_APP_LINE2 "Ready" -#define APPVERSION_LINE1 "Stacks" -#define APPVERSION_LINE2 ("v" APPVERSION) +#define MENU_MAIN_APP_LINE1 "Stacks" +#define MENU_MAIN_APP_LINE2 "Ready" +#define APPVERSION_LINE1 "Stacks" +#define APPVERSION_LINE2 ("v" APPVERSION) -#define COIN_SECRET_REQUIRED_CLICKS 0 -#define MENU_MAIN_APP_LINE2_SECRET "??????" +#define COIN_SECRET_REQUIRED_CLICKS 0 +#define MENU_MAIN_APP_LINE2_SECRET "??????" -#define CRYPTO_BLOB_SKIP_BYTES 0 +#define CRYPTO_BLOB_SKIP_BYTES 0 -#define COIN_VERSION_MAINNET_SINGLESIG 22 -#define COIN_VERSION_TESTNET_SINGLESIG 26 +#define COIN_VERSION_MAINNET_SINGLESIG 22 +#define COIN_VERSION_TESTNET_SINGLESIG 26 -#define INS_GET_VERSION 0x00 -#define INS_GET_ADDR_SECP256K1 0x01 -#define INS_SIGN_SECP256K1 0x02 -#define INS_GET_AUTH_PUBKEY 0x03 -#define SIGN_JWT_SECP256K1 0x04 +#define INS_GET_VERSION 0x00 +#define INS_GET_ADDR_SECP256K1 0x01 +#define INS_SIGN_SECP256K1 0x02 +#define INS_GET_AUTH_PUBKEY 0x03 +#define SIGN_JWT_SECP256K1 0x04 #ifdef __cplusplus } diff --git a/app/src/common/actions.c b/app/src/common/actions.c index 8f065911..60b1e0d2 100644 --- a/app/src/common/actions.c +++ b/app/src/common/actions.c @@ -1,19 +1,19 @@ /******************************************************************************* -* (c) 2016 Ledger -* (c) 2019 Zondax GmbH -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * (c) 2016 Ledger + * (c) 2019 Zondax GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #include "actions.h" diff --git a/app/src/common/actions.h b/app/src/common/actions.h index 93051fde..77190d8d 100644 --- a/app/src/common/actions.h +++ b/app/src/common/actions.h @@ -1,30 +1,31 @@ /******************************************************************************* -* (c) 2019 Zondax GmbH -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * (c) 2019 Zondax GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #pragma once +#include #include -#include "zxmacros.h" + +#include "apdu_codes.h" +#include "coin.h" #include "crypto.h" #include "cx.h" +#include "sha512.h" #include "tx.h" -#include "apdu_codes.h" -#include -#include "coin.h" #include "zxformat.h" -#include "sha512.h" +#include "zxmacros.h" // The initial tx hash is done in 3 blocks // this is the length in bytes of the first block @@ -67,10 +68,10 @@ extern uint8_t action_addr_len; // helper function to get the presig_hash of the transaction being signed -__Z_INLINE zxerr_t get_presig_hash(uint8_t* hash, uint16_t hashLen); +__Z_INLINE zxerr_t get_presig_hash(uint8_t *hash, uint16_t hashLen); // Helper function that appends the transaction auth_type, fee and nonce getting the hash of the result -__Z_INLINE zxerr_t append_fee_nonce_auth_hash(uint8_t* input_hash, uint16_t input_hashLen, uint8_t* hash, uint16_t hashLen); +__Z_INLINE zxerr_t append_fee_nonce_auth_hash(uint8_t *input_hash, uint16_t input_hashLen, uint8_t *hash, uint16_t hashLen); // Helper function to compute post_sighash from pre_sighash // Updates `hash` in place @@ -81,8 +82,8 @@ __Z_INLINE zxerr_t compute_post_sig_hash(uint8_t *hash, uint16_t hash_len, uint8 __Z_INLINE zxerr_t compute_sig_hash_chain(uint8_t *hash, uint16_t hash_len); __Z_INLINE void app_sign() { - uint8_t presig_hash[CX_SHA256_SIZE]; - uint8_t post_sighash_data[POST_SIGNHASH_DATA_LEN]; + uint8_t presig_hash[CX_SHA256_SIZE] = {0}; + uint8_t post_sighash_data[POST_SIGNHASH_DATA_LEN] = {0}; zxerr_t err = zxerr_ok; const uint8_t transaction_type = tx_get_transaction_type(); @@ -97,33 +98,32 @@ __Z_INLINE void app_sign() { // Validate post_sig_hashes of previous signers uint8_t hash_mode = -1; err = tx_hash_mode(&hash_mode); - if (err != zxerr_ok) { - zemu_log_stack("Error getting HashMode\n"); - } - else switch (hash_mode) { - case 0x00: // P2PKH - case 0x02: // P2WPKH - // Singlesig - // Shouldn't be here! - zemu_log_stack("HashMode is not multisig\n"); - err = zxerr_unknown; - break; - case 0x01: // P2SH sequential - case 0x03: // P2WSH sequential - // Sequential multisig - // Need to compute sighashes of all previous signers - err = compute_sig_hash_chain(presig_hash, CX_SHA256_SIZE); - break; - case 0x05: // PWSH non-sequential - case 0x07: // P2WSH non-sequential - // Non-sequential multisig - // No need to do anything - err = zxerr_ok; - break; - default: - zemu_log_stack("Invalid HashMode\n"); - err = zxerr_unknown; - break; + if (err == zxerr_ok) { + switch (hash_mode) { + case 0x00: // P2PKH + case 0x02: // P2WPKH + // Singlesig + // Shouldn't be here! + zemu_log_stack("HashMode is not multisig\n"); + err = zxerr_unknown; + break; + case 0x01: // P2SH sequential + case 0x03: // P2WSH sequential + // Sequential multisig + // Need to compute sighashes of all previous signers + err = compute_sig_hash_chain(presig_hash, CX_SHA256_SIZE); + break; + case 0x05: // PWSH non-sequential + case 0x07: // P2WSH non-sequential + // Non-sequential multisig + // No need to do anything + err = zxerr_ok; + break; + default: + zemu_log_stack("Invalid HashMode\n"); + err = zxerr_unknown; + break; + } } } @@ -136,7 +136,7 @@ __Z_INLINE void app_sign() { // Take "ownership" of the memory used by the transaction parser tx_reset_state(); - uint16_t replyLen; + uint16_t replyLen = 0; err = crypto_sign(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE - 3, presig_hash, CX_SHA256_SIZE, &replyLen); if (err != zxerr_ok) { set_code(G_io_apdu_buffer, 0, APDU_CODE_SIGN_VERIFY_ERROR); @@ -153,7 +153,7 @@ __Z_INLINE void app_sign() { post_sighash_data[CX_SHA256_SIZE] = 0x00; // Now get the post_sighash from the data and write it down to the first 32-byte of the G_io_apdu_buffer - uint8_t hash_temp[SHA512_DIGEST_LENGTH]; + uint8_t hash_temp[SHA512_DIGEST_LENGTH] = {0}; // Now get the presig_hash sha512_256_ctx ctx; @@ -170,7 +170,6 @@ __Z_INLINE void app_sign() { SHA512_256_finish(&ctx, hash_temp); memcpy(G_io_apdu_buffer, hash_temp, CX_SHA256_SIZE); break; - } case Message: case Jwt: @@ -179,7 +178,7 @@ __Z_INLINE void app_sign() { // which is the hash that is signed allowing for easy signature verification memcpy(G_io_apdu_buffer, presig_hash, CX_SHA256_SIZE); break; - } + } default: { set_code(G_io_apdu_buffer, 0, APDU_CODE_SIGN_VERIFY_ERROR); io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, 2); @@ -236,7 +235,6 @@ __Z_INLINE uint8_t app_fill_auth_pubkey(address_kind_e kind) { return action_addr_len; } - __Z_INLINE void app_reply_address() { set_code(G_io_apdu_buffer, action_addr_len, APDU_CODE_OK); io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, action_addr_len + 2); @@ -249,7 +247,7 @@ __Z_INLINE void app_reply_error() { __Z_INLINE zxerr_t compute_post_sig_hash(uint8_t *hash, uint16_t hash_len, uint8_t *signer_data, uint16_t signer_data_len) { uint16_t expected_signer_data_len = 1 + PREVIOUS_SIGNER_SIG_LEN; - if ( (hash_len != CX_SHA256_SIZE) || (signer_data_len != expected_signer_data_len)) { + if ((hash_len != CX_SHA256_SIZE) || (signer_data_len != expected_signer_data_len)) { return zxerr_no_data; } @@ -273,7 +271,7 @@ __Z_INLINE zxerr_t compute_sig_hash_chain(uint8_t *hash, uint16_t hash_len) { // 1-byte pubkey type(compressed/uncompressed) // 65-byte previous signer signature(vrs) - uint8_t previous_signer_data[1 + PREVIOUS_SIGNER_SIG_LEN]; + uint8_t previous_signer_data[1 + PREVIOUS_SIGNER_SIG_LEN] = {0}; memset(previous_signer_data, 0, sizeof(previous_signer_data)); uint32_t num_fields = tx_num_multisig_fields(); @@ -325,7 +323,7 @@ __Z_INLINE zxerr_t compute_sig_hash_chain(uint8_t *hash, uint16_t hash_len) { return zxerr_ok; } -__Z_INLINE zxerr_t get_presig_hash(uint8_t* hash, uint16_t hashLen) { +__Z_INLINE zxerr_t get_presig_hash(uint8_t *hash, uint16_t hashLen) { zemu_log_stack("computing presig_hash"); uint8_t tx_auth[INITIAL_SIGHASH_AUTH_LEN]; @@ -343,47 +341,46 @@ __Z_INLINE zxerr_t get_presig_hash(uint8_t* hash, uint16_t hashLen) { const uint16_t data_len = tx_get_buffer_length() - CRYPTO_BLOB_SKIP_BYTES; switch (tx_typ) { - case Transaction: { - // Before hashing the transaction the auth field should be cleared - // and the sponsor set to signing sentinel. - uint16_t auth_len = 0; - auth_len = tx_presig_hash_data(tx_auth, INITIAL_SIGHASH_AUTH_LEN); - // prepare the last transaction block to be hashed - SHA512_256_update(&ctx, data, TRANSACTION_FIRST_BLOCK_LEN); - SHA512_256_update(&ctx, tx_auth, auth_len); - uint8_t *last_block = NULL; - uint8_t **last_block_ptr = &last_block; - - uint16_t last_block_len = tx_last_tx_block(last_block_ptr); - if (last_block == NULL || last_block_len == 0) { - return zxerr_no_data; + case Transaction: { + // Before hashing the transaction the auth field should be cleared + // and the sponsor set to signing sentinel. + uint16_t auth_len = 0; + auth_len = tx_presig_hash_data(tx_auth, INITIAL_SIGHASH_AUTH_LEN); + // prepare the last transaction block to be hashed + SHA512_256_update(&ctx, data, TRANSACTION_FIRST_BLOCK_LEN); + SHA512_256_update(&ctx, tx_auth, auth_len); + uint8_t *last_block = NULL; + uint8_t **last_block_ptr = &last_block; + + uint16_t last_block_len = tx_last_tx_block(last_block_ptr); + if (last_block == NULL || last_block_len == 0) { + return zxerr_no_data; + } + + SHA512_256_update(&ctx, last_block, last_block_len); + SHA512_256_finish(&ctx, hash_temp); + return append_fee_nonce_auth_hash(hash_temp, CX_SHA256_SIZE, hash, hashLen); } - - SHA512_256_update(&ctx, last_block, last_block_len); - SHA512_256_finish(&ctx, hash_temp); - return append_fee_nonce_auth_hash(hash_temp, CX_SHA256_SIZE, hash, hashLen); - } - case Message: - case Jwt: { - // we have byteString or JWT messages. The hash is the same for both types - cx_hash_sha256(data, data_len, hash, CX_SHA256_SIZE); - return zxerr_ok; - } - // special case is delegated to the rust side - case StructuredMsg: { - return tx_structured_msg_hash(hash, CX_SHA256_SIZE); - } - default: - return zxerr_no_data; + case Message: + case Jwt: { + // we have byteString or JWT messages. The hash is the same for both types + cx_hash_sha256(data, data_len, hash, CX_SHA256_SIZE); + return zxerr_ok; + } + // special case is delegated to the rust side + case StructuredMsg: { + return tx_structured_msg_hash(hash, CX_SHA256_SIZE); + } + default: + return zxerr_no_data; } } -__Z_INLINE zxerr_t append_fee_nonce_auth_hash(uint8_t* input_hash, uint16_t input_hashLen, uint8_t* hash, uint16_t hashLen) { - uint8_t presig_data[PRESIG_DATA_LEN]; +__Z_INLINE zxerr_t append_fee_nonce_auth_hash(uint8_t *input_hash, uint16_t input_hashLen, uint8_t *hash, uint16_t hashLen) { + uint8_t presig_data[PRESIG_DATA_LEN] = {0}; // uint8_t hash_temp[SHA512_DIGEST_LENGTH]; - if ( input_hashLen != CX_SHA256_SIZE ) - return zxerr_no_data; + if (input_hashLen != CX_SHA256_SIZE) return zxerr_no_data; memcpy(presig_data, input_hash, input_hashLen); @@ -391,8 +388,7 @@ __Z_INLINE zxerr_t append_fee_nonce_auth_hash(uint8_t* input_hash, uint16_t inpu uint8_t idx = CX_SHA256_SIZE; // append the tx auth type - if (tx_auth_flag(&presig_data[idx++]) != zxerr_ok) - return zxerr_no_data; + if (tx_auth_flag(&presig_data[idx++]) != zxerr_ok) return zxerr_no_data; // append the 8-byte transaction fee idx += tx_fee(&presig_data[idx], 8); @@ -400,8 +396,7 @@ __Z_INLINE zxerr_t append_fee_nonce_auth_hash(uint8_t* input_hash, uint16_t inpu // append the 8-byte transaction nonce idx += tx_nonce(&presig_data[idx], 8); - if (hashLen < CX_SHA256_SIZE || idx != PRESIG_DATA_LEN) - return zxerr_no_data; + if (hashLen < CX_SHA256_SIZE || idx != PRESIG_DATA_LEN) return zxerr_no_data; // Now get the hash sha512_256_ctx ctx; @@ -411,4 +406,3 @@ __Z_INLINE zxerr_t append_fee_nonce_auth_hash(uint8_t* input_hash, uint16_t inpu SHA512_256_finish(&ctx, hash); return zxerr_ok; } - diff --git a/app/src/common/main.c b/app/src/common/main.c index 87150f07..ed443c4a 100644 --- a/app/src/common/main.c +++ b/app/src/common/main.c @@ -1,43 +1,40 @@ /******************************************************************************* -* (c) 2016 Ledger -* (c) 2018, 2019 Zondax GmbH -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * (c) 2016 Ledger + * (c) 2018, 2019 Zondax GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ +#include + #include "app_main.h" #include "view.h" -#include - -__attribute__((section(".boot"))) int -main(void) { +__attribute__((section(".boot"))) int main(void) { // exit critical section __asm volatile("cpsie i"); view_init(); os_boot(); - BEGIN_TRY - { - TRY - { + BEGIN_TRY { + TRY { app_init(); app_main(); } - CATCH_OTHER(e) - {} - FINALLY - {} + CATCH_OTHER(e) { + } + FINALLY { + } } END_TRY; } diff --git a/app/src/common/tx.c b/app/src/common/tx.c index 71cfb52b..b624ad7c 100644 --- a/app/src/common/tx.c +++ b/app/src/common/tx.c @@ -15,17 +15,19 @@ ********************************************************************************/ #include "tx.h" + +#include + #include "apdu_codes.h" #include "buffering.h" #include "parser.h" -#include #include "zxmacros.h" #if defined(TARGET_NANOX) || defined(TARGET_NANOS2) || defined(TARGET_STAX) || defined(TARGET_FLEX) -#define RAM_BUFFER_SIZE 8192 +#define RAM_BUFFER_SIZE 8192 #define FLASH_BUFFER_SIZE (85 * 1024) #elif defined(TARGET_NANOS) -#define RAM_BUFFER_SIZE 0 +#define RAM_BUFFER_SIZE 0 #define FLASH_BUFFER_SIZE 8192 #endif @@ -33,8 +35,7 @@ uint8_t ram_buffer[RAM_BUFFER_SIZE]; // Flash -typedef struct -{ +typedef struct { uint8_t buffer[FLASH_BUFFER_SIZE]; } storage_t; @@ -45,199 +46,163 @@ storage_t NV_CONST N_appdata_impl __attribute__((aligned(64))); static parser_context_t ctx_parsed_tx; -void tx_initialize() -{ - buffering_init( - ram_buffer, - sizeof(ram_buffer), - (uint8_t *)N_appdata.buffer, - sizeof(N_appdata.buffer)); +void tx_initialize() { + buffering_init(ram_buffer, sizeof(ram_buffer), (uint8_t *)N_appdata.buffer, sizeof(N_appdata.buffer)); } -void tx_reset() -{ +void tx_reset() { buffering_reset(); } -void tx_reset_state() -{ +void tx_reset_state() { parser_resetState(); } -uint32_t tx_append(unsigned char *buffer, uint32_t length) -{ +uint32_t tx_append(unsigned char *buffer, uint32_t length) { return buffering_append(buffer, length); } -uint32_t tx_get_buffer_length() -{ +uint32_t tx_get_buffer_length() { return buffering_get_buffer()->pos; } -uint8_t *tx_get_buffer() -{ +uint8_t *tx_get_buffer() { return buffering_get_buffer()->data; } -const char *tx_parse() -{ - uint8_t err = parser_parse( - &ctx_parsed_tx, - tx_get_buffer(), - tx_get_buffer_length()); +const char *tx_parse() { + uint8_t err = parser_parse(&ctx_parsed_tx, tx_get_buffer(), tx_get_buffer_length()); - if (err != parser_ok) - { + if (err != parser_ok) { return parser_getErrorDescription(err); } err = parser_validate(&ctx_parsed_tx); CHECK_APP_CANARY() - if (err != parser_ok) - { + if (err != parser_ok) { return parser_getErrorDescription(err); } return NULL; } -zxerr_t tx_getNumItems(uint8_t *num_items) -{ +zxerr_t tx_getNumItems(uint8_t *num_items) { parser_error_t err = parser_getNumItems(&ctx_parsed_tx, num_items); - if (err != parser_ok) - { + if (err != parser_ok) { return zxerr_no_data; } return zxerr_ok; } -zxerr_t tx_getItem(int8_t displayIdx, - char *outKey, uint16_t outKeyLen, - char *outVal, uint16_t outValLen, - uint8_t pageIdx, uint8_t *pageCount) -{ +zxerr_t tx_getItem(int8_t displayIdx, char *outKey, uint16_t outKeyLen, char *outVal, uint16_t outValLen, uint8_t pageIdx, + uint8_t *pageCount) { uint8_t numItems = 0; CHECK_ZXERR(tx_getNumItems(&numItems)) - if (displayIdx < 0 || displayIdx > numItems) - { + if (displayIdx < 0 || displayIdx > numItems) { return zxerr_no_data; } - parser_error_t err = parser_getItem(&ctx_parsed_tx, - displayIdx, - outKey, outKeyLen, - outVal, outValLen, - pageIdx, pageCount); + parser_error_t err = + parser_getItem(&ctx_parsed_tx, displayIdx, outKey, outKeyLen, outVal, outValLen, pageIdx, pageCount); // Convert error codes - if (err == parser_no_data || - err == parser_display_idx_out_of_range || - err == parser_display_page_out_of_range) + if (err == parser_no_data || err == parser_display_idx_out_of_range || err == parser_display_page_out_of_range) return zxerr_no_data; - if (err != parser_ok) + if (err != parser_ok) { return zxerr_unknown; + } return zxerr_ok; } -zxerr_t tx_auth_flag(uint8_t *flag) -{ - if (parser_tx_auth_flag(flag) != parser_ok) - return zxerr_unknown; +zxerr_t tx_auth_flag(uint8_t *flag) { + if (parser_tx_auth_flag(flag) != parser_ok) return zxerr_unknown; return zxerr_ok; } -uint8_t tx_fee(uint8_t *fee, uint16_t fee_len) -{ +uint8_t tx_fee(uint8_t *fee, uint16_t fee_len) { return parser_tx_fee(fee, fee_len); } -uint8_t tx_nonce(uint8_t *nonce, uint16_t nonce_len) -{ +uint8_t tx_nonce(uint8_t *nonce, uint16_t nonce_len) { return parser_tx_nonce(nonce, nonce_len); } -uint16_t tx_presig_hash_data(uint8_t *buf, uint16_t bufLen) -{ +uint16_t tx_presig_hash_data(uint8_t *buf, uint16_t bufLen) { return parser_presig_hash_data(buf, bufLen); } -uint16_t tx_last_tx_block(uint8_t **last_tx_block) -{ +uint16_t tx_last_tx_block(uint8_t **last_tx_block) { return parser_last_transaction_block(last_tx_block); } -int8_t tx_is_multisig() -{ +int8_t tx_is_multisig() { return parser_is_transaction_multisig(); } -zxerr_t tx_hash_mode(uint8_t *hash_mode) -{ +zxerr_t tx_hash_mode(uint8_t *hash_mode) { parser_error_t err = parser_hash_mode(hash_mode); // Convert error codes - if (err == parser_no_data) + if (err == parser_no_data) { return zxerr_no_data; + } - if (err != parser_ok) + if (err != parser_ok) { return zxerr_unknown; + } return zxerr_ok; } -uint16_t tx_previous_signer_data(uint8_t **data) -{ +uint16_t tx_previous_signer_data(uint8_t **data) { return parser_previous_signer_data(data); } -uint32_t tx_num_multisig_fields() -{ +uint32_t tx_num_multisig_fields() { return parser_num_multisig_fields(); } -zxerr_t tx_get_multisig_field(uint32_t index, uint8_t *id, uint8_t **data) -{ +zxerr_t tx_get_multisig_field(uint32_t index, uint8_t *id, uint8_t **data) { parser_error_t err = parser_get_multisig_field(index, id, data); // Convert error codes - if (err == parser_no_data) + if (err == parser_no_data) { return zxerr_no_data; + } - if (err != parser_ok) + if (err != parser_ok) { return zxerr_unknown; + } return zxerr_ok; } -transaction_type_t tx_get_transaction_type() -{ +transaction_type_t tx_get_transaction_type() { return parser_get_transaction_type(); } -zxerr_t tx_structured_msg_hash(uint8_t *out, uint16_t out_len) -{ +zxerr_t tx_structured_msg_hash(uint8_t *out, uint16_t out_len) { return parser_structured_msg_hash(out, out_len); } -uint16_t get_error_message(char *out, uint16_t outLen, parser_error_t error_code) -{ +uint16_t get_error_message(char *out, uint16_t outLen, parser_error_t error_code) { const char *error_message = parser_getErrorDescription(error_code); - if (error_message == NULL || outLen == 0) - { + if (error_message == NULL || outLen == 0) { return 0; } uint16_t len = strlen(error_message); - if (outLen < len) + if (outLen < len) { return 0; + } memcpy(out, error_message, len); diff --git a/app/src/common/tx.h b/app/src/common/tx.h index ff8ff986..ff61d754 100644 --- a/app/src/common/tx.h +++ b/app/src/common/tx.h @@ -1,24 +1,24 @@ /******************************************************************************* -* (c) 2019 Zondax GmbH -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * (c) 2019 Zondax GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #pragma once -#include "os.h" #include "coin.h" -#include "zxerror.h" +#include "os.h" #include "parser_common.h" +#include "zxerror.h" void tx_initialize(); @@ -51,9 +51,7 @@ const char *tx_parse(); zxerr_t tx_getNumItems(uint8_t *num_items); /// Gets an specific item from the transaction (including paging) -zxerr_t tx_getItem(int8_t displayIdx, - char *outKey, uint16_t outKeyLen, - char *outValue, uint16_t outValueLen, +zxerr_t tx_getItem(int8_t displayIdx, char *outKey, uint16_t outKeyLen, char *outValue, uint16_t outValueLen, uint8_t pageIdx, uint8_t *pageCount); // Gets the transaction authorization type @@ -81,7 +79,7 @@ uint8_t tx_nonce(uint8_t *nonce, uint16_t nonce_len); uint16_t tx_presig_hash_data(uint8_t *buf, uint16_t bufLen); // Gets a pointer to the last block in the transaction and returns its lenght -uint16_t tx_last_tx_block(uint8_t ** last_tx_block); +uint16_t tx_last_tx_block(uint8_t **last_tx_block); // Gets the pointer to the previous signer signature and required data // for signing a multisig transaction diff --git a/app/src/crypto.c b/app/src/crypto.c index 55203d20..036dfc6c 100644 --- a/app/src/crypto.c +++ b/app/src/crypto.c @@ -1,26 +1,27 @@ /******************************************************************************* -* (c) 2019 Zondax GmbH -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * (c) 2019 Zondax GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #include "crypto.h" -#include "sha512.h" + #include "coin.h" -#include "zxmacros.h" -#include "zxformat.h" -#include "rslib.h" #include "cx_errors.h" +#include "rslib.h" +#include "sha512.h" +#include "zxformat.h" +#include "zxmacros.h" uint8_t version; @@ -28,21 +29,20 @@ uint32_t hdPath[HDPATH_LEN_DEFAULT]; uint32_t hdPath_len; bool isTestnet() { - return hdPath[0] == HDPATH_0_TESTNET && - hdPath[1] == HDPATH_1_TESTNET; + return hdPath[0] == HDPATH_0_TESTNET && hdPath[1] == HDPATH_1_TESTNET; } #include "cx.h" bool ripemd160(uint8_t *in, uint16_t inLen, uint8_t *out) { cx_ripemd160_t rip160; - if( cx_ripemd160_init_no_throw(&rip160) == CX_OK && + if (cx_ripemd160_init_no_throw(&rip160) == CX_OK && cx_hash_no_throw(&rip160.header, CX_LAST, in, inLen, out, CX_RIPEMD160_SIZE) == CX_OK) { return true; - } else { - MEMZERO(out, CX_RIPEMD160_SIZE); - return false; } + + MEMZERO(out, CX_RIPEMD160_SIZE); + return false; } typedef struct { @@ -50,14 +50,13 @@ typedef struct { uint8_t address[50]; } __attribute__((packed)) answer_t; -#define VERSION_SIZE 1 +#define VERSION_SIZE 1 typedef struct { uint8_t hash_sha256[CX_SHA256_SIZE]; uint8_t hash_ripe[CX_RIPEMD160_SIZE]; } __attribute__((packed)) address_temp_t; - bool is_valid_network_version(uint8_t ver); // Set the network version to be used when getting the address from @@ -72,9 +71,11 @@ bool set_network_version(uint8_t network) { } bool is_valid_network_version(uint8_t ver) { - switch(ver) { - case COIN_VERSION_TESTNET_SINGLESIG: break; - case COIN_VERSION_MAINNET_SINGLESIG: break; + switch (ver) { + case COIN_VERSION_TESTNET_SINGLESIG: + break; + case COIN_VERSION_MAINNET_SINGLESIG: + break; default: { return false; } @@ -88,21 +89,22 @@ uint16_t crypto_fillAddress_secp256k1(uint8_t *buffer, uint16_t buffer_len) { } MEMZERO(buffer, buffer_len); - answer_t *const answer = (answer_t *) buffer; + answer_t *const answer = (answer_t *)buffer; - if(crypto_extractPublicKey(hdPath, HDPATH_LEN_DEFAULT, answer->publicKey, sizeof_field(answer_t, publicKey)) != zxerr_ok) { + if (crypto_extractPublicKey(hdPath, HDPATH_LEN_DEFAULT, answer->publicKey, sizeof_field(answer_t, publicKey)) != + zxerr_ok) { return 0; } address_temp_t address_temp; - if(!crypto_extractPublicKeyHash(address_temp.hash_ripe, CX_RIPEMD160_SIZE)) { + if (!crypto_extractPublicKeyHash(address_temp.hash_ripe, CX_RIPEMD160_SIZE)) { return 0; } - size_t outLen = sizeof_field(answer_t, address); - if ( !is_valid_network_version(version) ) - version = COIN_VERSION_MAINNET_SINGLESIG; + size_t outLen = 0; + outLen = sizeof_field(answer_t, address); + if (!is_valid_network_version(version)) version = COIN_VERSION_MAINNET_SINGLESIG; outLen = rs_c32_address(address_temp.hash_ripe, version, answer->address, outLen); return PK_LEN_SECP256K1 + outLen; @@ -114,16 +116,15 @@ uint16_t crypto_fillAuthkey_secp256k1(uint8_t *buffer, uint16_t buffer_len) { } MEMZERO(buffer, buffer_len); - answer_t *const answer = (answer_t *) buffer; + answer_t *const answer = (answer_t *)buffer; - if(crypto_extractPublicKey(hdPath, HDPATH_LEN_AUTH, answer->publicKey, sizeof_field(answer_t, publicKey)) != zxerr_ok) { + if (crypto_extractPublicKey(hdPath, HDPATH_LEN_AUTH, answer->publicKey, sizeof_field(answer_t, publicKey)) != zxerr_ok) { return 0; } return PK_LEN_SECP256K1; } - zxerr_t crypto_extractPublicKey(const uint32_t *path, uint32_t path_len, uint8_t *pubKey, uint16_t pubKeyLen) { cx_ecfp_public_key_t cx_publicKey; cx_ecfp_private_key_t cx_privateKey; @@ -135,10 +136,7 @@ zxerr_t crypto_extractPublicKey(const uint32_t *path, uint32_t path_len, uint8_t } zxerr_t error = zxerr_unknown; - CATCH_CXERROR(os_derive_bip32_no_throw(CX_CURVE_256K1, - path, - path_len, - privateKeyData, NULL)); + CATCH_CXERROR(os_derive_bip32_no_throw(CX_CURVE_256K1, path, path_len, privateKeyData, NULL)); CATCH_CXERROR(cx_ecfp_init_private_key_no_throw(CX_CURVE_256K1, privateKeyData, 32, &cx_privateKey)); CATCH_CXERROR(cx_ecfp_init_public_key_no_throw(CX_CURVE_256K1, NULL, 0, &cx_publicKey)); @@ -162,12 +160,12 @@ zxerr_t crypto_extractPublicKey(const uint32_t *path, uint32_t path_len, uint8_t } bool crypto_extractPublicKeyHash(uint8_t *pubKeyHash, uint16_t pubKeyLen) { - - if (pubKeyLen < CX_RIPEMD160_SIZE || pubKeyHash == NULL) + if (pubKeyLen < CX_RIPEMD160_SIZE || pubKeyHash == NULL) { return false; + } // gets the raw public key - uint8_t publicKey[PK_LEN_SECP256K1]; + uint8_t publicKey[PK_LEN_SECP256K1] = {0}; if (crypto_extractPublicKey(hdPath, HDPATH_LEN_DEFAULT, publicKey, PK_LEN_SECP256K1) != zxerr_ok) { return false; @@ -177,7 +175,7 @@ bool crypto_extractPublicKeyHash(uint8_t *pubKeyHash, uint16_t pubKeyLen) { { zemu_log("pubKey: ***"); char buffer[PK_LEN_SECP256K1 * 3]; - array_to_hexstr(buffer, PK_LEN_SECP256K1 * 3, publicKey, PK_LEN_SECP256K1 ); + array_to_hexstr(buffer, PK_LEN_SECP256K1 * 3, publicKey, PK_LEN_SECP256K1); zemu_log(buffer); zemu_log("\n"); } @@ -187,7 +185,7 @@ bool crypto_extractPublicKeyHash(uint8_t *pubKeyHash, uint16_t pubKeyLen) { address_temp_t address_temp; cx_hash_sha256(publicKey, PK_LEN_SECP256K1, address_temp.hash_sha256, CX_SHA256_SIZE); - return ripemd160(address_temp.hash_sha256, CX_SHA256_SIZE, pubKeyHash); // RIPEMD-160 + return ripemd160(address_temp.hash_sha256, CX_SHA256_SIZE, pubKeyHash); // RIPEMD-160 } typedef struct { @@ -202,61 +200,51 @@ typedef struct { } __attribute__((packed)) signature_t; -zxerr_t crypto_sign(uint8_t *buffer, uint16_t signatureMaxlen, const uint8_t *message, uint16_t messageLen, uint16_t *sigSize) { +zxerr_t crypto_sign(uint8_t *buffer, uint16_t signatureMaxlen, const uint8_t *message, uint16_t messageLen, + uint16_t *sigSize) { if (signatureMaxlen < sizeof_field(signature_t, der_signature)) { return zxerr_buffer_too_small; } - *sigSize=0; + *sigSize = 0; if (messageLen != CX_SHA256_SIZE) { return zxerr_out_of_bounds; } - #ifdef APP_TESTING - char tmpBuff[65] = {0}; - array_to_hexstr(tmpBuff, sizeof(tmpBuff), message, CX_SHA256_SIZE); - ZEMU_LOGF(100, "Digest: *** %s\n", tmpBuff) - #endif +#ifdef APP_TESTING + char tmpBuff[65] = {0}; + array_to_hexstr(tmpBuff, sizeof(tmpBuff), message, CX_SHA256_SIZE); + ZEMU_LOGF(100, "Digest: *** %s\n", tmpBuff) +#endif cx_ecfp_private_key_t cx_privateKey; - uint8_t privateKeyData[SK_LEN_25519]; + uint8_t privateKeyData[SK_LEN_25519] = {0}; unsigned int info = 0; - signature_t *const signature = (signature_t *) buffer; + signature_t *const signature = (signature_t *)buffer; zxerr_t zxerr = zxerr_unknown; - CATCH_CXERROR(os_derive_bip32_no_throw(CX_CURVE_256K1, - hdPath, - hdPath_len, - privateKeyData, NULL)); + CATCH_CXERROR(os_derive_bip32_no_throw(CX_CURVE_256K1, hdPath, hdPath_len, privateKeyData, NULL)); CATCH_CXERROR(cx_ecfp_init_private_key_no_throw(CX_CURVE_256K1, privateKeyData, 32, &cx_privateKey)); // Sign - size_t signatureLength = sizeof_field(signature_t, der_signature); - CATCH_CXERROR(cx_ecdsa_sign_no_throw(&cx_privateKey, - CX_RND_RFC6979 | CX_LAST, - CX_SHA256, - message, - CX_SHA256_SIZE, - signature->der_signature, - &signatureLength, - &info)); + size_t signatureLength = 0; + signatureLength = sizeof_field(signature_t, der_signature); + CATCH_CXERROR(cx_ecdsa_sign_no_throw(&cx_privateKey, CX_RND_RFC6979 | CX_LAST, CX_SHA256, message, CX_SHA256_SIZE, + signature->der_signature, &signatureLength, &info)); zxerr = zxerr_ok; - err_convert_e err = convertDERtoRSV(signature->der_signature, info, signature->r, signature->s, &signature->v); + err_convert_e err = convertDERtoRSV(signature->der_signature, info, signature->r, signature->s, &signature->v); if (err != no_error) { return zxerr_encoding_failed; } // return actual size using value from signatureLength - *sigSize = sizeof_field(signature_t, r) + - sizeof_field(signature_t, s) + - sizeof_field(signature_t, v) + - sizeof_field(signature_t, post_sighash) + - signatureLength; + *sigSize = sizeof_field(signature_t, r) + sizeof_field(signature_t, s) + sizeof_field(signature_t, v) + + sizeof_field(signature_t, post_sighash) + signatureLength; catch_cx_error: MEMZERO(&cx_privateKey, sizeof(cx_privateKey)); diff --git a/app/src/crypto.h b/app/src/crypto.h index b0e4acfb..de6cfaa4 100644 --- a/app/src/crypto.h +++ b/app/src/crypto.h @@ -1,18 +1,18 @@ /******************************************************************************* -* (c) 2019 Zondax GmbH -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * (c) 2019 Zondax GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #pragma once @@ -20,13 +20,14 @@ extern "C" { #endif +#include +#include #include + #include "coin.h" -#include -#include #include "zxerror.h" -#define CHECKSUM_LENGTH 4 +#define CHECKSUM_LENGTH 4 extern uint32_t hdPath[HDPATH_LEN_DEFAULT]; extern uint32_t hdPath_len; @@ -46,10 +47,7 @@ bool crypto_extractPublicKeyHash(uint8_t *pubKey, uint16_t pubKeyLen); uint16_t crypto_fillAddress_secp256k1(uint8_t *buffer, uint16_t bufferLen); uint16_t crypto_fillAuthkey_secp256k1(uint8_t *buffer, uint16_t bufferLen); -zxerr_t crypto_sign(uint8_t *buffer, - uint16_t signatureMaxlen, - const uint8_t *message, - uint16_t messageLen, +zxerr_t crypto_sign(uint8_t *buffer, uint16_t signatureMaxlen, const uint8_t *message, uint16_t messageLen, uint16_t *sigSize); #ifdef __cplusplus diff --git a/app/src/parser.c b/app/src/parser.c index ed7e9ae9..a33e3cb1 100644 --- a/app/src/parser.c +++ b/app/src/parser.c @@ -1,24 +1,26 @@ /******************************************************************************* -* (c) 2019 Zondax GmbH -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * (c) 2019 Zondax GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ + +#include "parser.h" #include #include -#include "parser_txdef.h" -#include "parser.h" + #include "coin.h" +#include "parser_txdef.h" #include "rslib.h" static zxerr_t parser_allocate(); @@ -40,8 +42,8 @@ parser_error_t parser_parse(parser_context_t *ctx, const uint8_t *data, size_t d return parser_context_unexpected_size; } - if(parser_allocate() != zxerr_ok) { - return parser_init_context_empty ; + if (parser_allocate() != zxerr_ok) { + return parser_init_context_empty; } parser_error_t err = _read(ctx, &parser_state); @@ -49,18 +51,17 @@ parser_error_t parser_parse(parser_context_t *ctx, const uint8_t *data, size_t d } parser_error_t parser_validate(const parser_context_t *ctx) { - - uint8_t pubKeyHash[CX_RIPEMD160_SIZE]; + uint8_t pubKeyHash[CX_RIPEMD160_SIZE] = {0}; crypto_extractPublicKeyHash(pubKeyHash, CX_RIPEMD160_SIZE); // Checks if the data being processed is a transaction and if so, verify this device is allowed to sign this transaction - if ( parser_get_transaction_type() == Transaction ) { - if (_check_pubkey_hash(&parser_state, pubKeyHash, CX_RIPEMD160_SIZE) != parser_ok) - return parser_invalid_auth_type; + if (parser_get_transaction_type() == Transaction) { + if (_check_pubkey_hash(&parser_state, pubKeyHash, CX_RIPEMD160_SIZE) != parser_ok) { + return parser_invalid_auth_type; + } } - uint8_t numItems = 0; CHECK_PARSER_ERR(parser_getNumItems(ctx, &numItems)); @@ -79,18 +80,15 @@ parser_error_t parser_getNumItems(const parser_context_t *ctx, uint8_t *num_item return _getNumItems(ctx, &parser_state, num_items); } -parser_error_t parser_getItem(const parser_context_t *ctx, - uint16_t displayIdx, - char *outKey, uint16_t outKeyLen, - char *outVal, uint16_t outValLen, - uint8_t pageIdx, uint8_t *pageCount) { +parser_error_t parser_getItem(const parser_context_t *ctx, uint16_t displayIdx, char *outKey, uint16_t outKeyLen, + char *outVal, uint16_t outValLen, uint8_t pageIdx, uint8_t *pageCount) { MEMZERO(outKey, outKeyLen); MEMZERO(outVal, outValLen); snprintf(outKey, outKeyLen, "?"); snprintf(outVal, outValLen, "?"); *pageCount = 0; - uint8_t numItems; + uint8_t numItems = 0; CHECK_PARSER_ERR(parser_getNumItems(ctx, &numItems)) CHECK_APP_CANARY() @@ -142,7 +140,7 @@ uint16_t parser_previous_signer_data(uint8_t **data) { return _previous_signer_data(&parser_state, data); } -zxerr_t parser_structured_msg_hash(uint8_t *out, uint16_t out_len){ +zxerr_t parser_structured_msg_hash(uint8_t *out, uint16_t out_len) { if (_structured_msg_hash(&parser_state, out, out_len) != parser_ok) { return zxerr_buffer_too_small; } @@ -153,10 +151,10 @@ zxerr_t parser_allocate() { if (parser_state.len % 4 != 0) { parser_state.len += parser_state.len % 4; } - if(parser_state.len > PARSER_BUFFER_SIZE) { + if (parser_state.len > PARSER_BUFFER_SIZE) { return zxerr_buffer_too_small; } - if(parser_state.state != NULL) { + if (parser_state.state != NULL) { return zxerr_unknown; } @@ -166,7 +164,7 @@ zxerr_t parser_allocate() { } zxerr_t parser_deallocate() { - if(parser_state.state == NULL) { + if (parser_state.state == NULL) { return zxerr_unknown; } parser_state.len = 0; @@ -178,7 +176,7 @@ void parser_resetState() { parser_deallocate(); } -transaction_type_t parser_get_transaction_type(){ +transaction_type_t parser_get_transaction_type() { return _transaction_type(&parser_state); } diff --git a/app/src/parser.h b/app/src/parser.h index 44bd28a6..0bfc6615 100644 --- a/app/src/parser.h +++ b/app/src/parser.h @@ -1,18 +1,18 @@ /******************************************************************************* -* (c) 2019 Zondax GmbH -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * (c) 2019 Zondax GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #pragma once @@ -20,18 +20,16 @@ extern "C" { #endif +#include "crypto.h" +#include "hexutils.h" #include "parser_common.h" #include "parser_txdef.h" -#include "hexutils.h" -#include "crypto.h" extern parser_tx_t parser_state; const char *parser_getErrorDescription(parser_error_t err); //// parses a tx buffer -parser_error_t parser_parse(parser_context_t *ctx, - const uint8_t *data, - size_t dataLen); +parser_error_t parser_parse(parser_context_t *ctx, const uint8_t *data, size_t dataLen); //// verifies tx fields parser_error_t parser_validate(const parser_context_t *ctx); @@ -40,12 +38,8 @@ parser_error_t parser_validate(const parser_context_t *ctx); parser_error_t parser_getNumItems(const parser_context_t *ctx, uint8_t *num_items); // retrieves a readable output for each field / page -parser_error_t parser_getItem(const parser_context_t *ctx, - uint16_t displayIdx, - char *outKey, uint16_t outKeyLen, - char *outValue, uint16_t outValueLen, - uint8_t pageIdx, uint8_t *pageCount); - +parser_error_t parser_getItem(const parser_context_t *ctx, uint16_t displayIdx, char *outKey, uint16_t outKeyLen, + char *outVal, uint16_t outValLen, uint8_t pageIdx, uint8_t *pageCount); /// Gets the transaction authorization type parser_error_t parser_tx_auth_flag(uint8_t *flag); @@ -63,7 +57,7 @@ uint16_t parser_presig_hash_data(uint8_t *buf, uint16_t bufLen); // When signing the full transaction, The transaction hash has to be done in blocks. // this function returns a pointer to the last transaction block and its lenght -uint16_t parser_last_transaction_block(uint8_t ** last_tx_block); +uint16_t parser_last_transaction_block(uint8_t **last_block); // Returns 1 if the transaction is multisig, 0 otherwise int8_t parser_is_transaction_multisig(); diff --git a/app/src/parser_common.h b/app/src/parser_common.h index ae6f1c6d..b9799b79 100644 --- a/app/src/parser_common.h +++ b/app/src/parser_common.h @@ -1,30 +1,32 @@ /******************************************************************************* -* (c) 2019 Zondax GmbH -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * (c) 2019 Zondax GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #pragma once #ifdef __cplusplus extern "C" { #endif -#include #include +#include -#define CHECK_PARSER_ERR(CALL) { \ - parser_error_t err = CALL; \ - if (err!=parser_ok) return err;} +#define CHECK_PARSER_ERR(CALL) \ + { \ + parser_error_t err = CALL; \ + if (err != parser_ok) return err; \ + } typedef enum { // Generic errors @@ -84,14 +86,7 @@ typedef struct { uint16_t offset; } parser_context_t; -typedef enum _TransactionType { - Transaction, - Message, - Jwt, - StructuredMsg, - Invalid -} transaction_type_t; - +typedef enum _TransactionType { Transaction, Message, Jwt, StructuredMsg, Invalid } transaction_type_t; #ifdef __cplusplus } diff --git a/app/src/parser_txdef.h b/app/src/parser_txdef.h index 15fce689..34954643 100644 --- a/app/src/parser_txdef.h +++ b/app/src/parser_txdef.h @@ -1,18 +1,18 @@ /******************************************************************************* -* (c) 2020 Zondax GmbH -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * (c) 2020 Zondax GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #pragma once #include @@ -22,8 +22,8 @@ extern "C" { #endif -#include #include +#include typedef struct { uint8_t *state;