diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..ee1a34d --- /dev/null +++ b/.clang-format @@ -0,0 +1,19 @@ +--- +BasedOnStyle: Google +IndentWidth: 4 +--- +Language: Cpp +ColumnLimit: 100 +PointerAlignment: Right +AlignAfterOpenBracket: Align +AlignConsecutiveMacros: false +AllowAllParametersOfDeclarationOnNextLine: false +SortIncludes: false +SpaceAfterCStyleCast: true +AllowShortCaseLabelsOnASingleLine: false +AllowAllArgumentsOnNextLine: false +AllowShortBlocksOnASingleLine: Never +AllowShortFunctionsOnASingleLine: None +BinPackArguments: false +BinPackParameters: false +--- diff --git a/.github/workflows/build_and_functional_tests.yml b/.github/workflows/build_and_functional_tests.yml new file mode 100644 index 0000000..4748d92 --- /dev/null +++ b/.github/workflows/build_and_functional_tests.yml @@ -0,0 +1,80 @@ +name: Build and run functional tests using ragger + +# This workflow will build the app and then run functional tests using the Ragger framework upon Speculos emulation. +# It calls a reusable workflow developed by Ledger's internal developer team to build the application and upload the +# resulting binaries. +# It then calls another reusable workflow to run the Ragger tests on the compiled application binary. +# +# While this workflow is optional, having functional testing on your application is mandatory and this workflow and +# tooling environment is meant to be easy to use and adapt after forking your application + +on: + workflow_dispatch: + push: + branches: + - master + - main + - develop + pull_request: + +jobs: + build_application: + name: Build application + uses: LedgerHQ/ledger-app-workflows/.github/workflows/reusable_build.yml@v1 + with: + upload_app_binaries_artifact: "compiled_app_binaries" + + ragger_tests: + name: Run ragger tests + needs: build_application + uses: LedgerHQ/ledger-app-workflows/.github/workflows/reusable_ragger_tests.yml@v1 + with: + download_app_binaries_artifact: "compiled_app_binaries" + + job_e2e_tests: + name: E2E tests + needs: build_application + runs-on: ubuntu-latest + timeout-minutes: 10 + + container: + image: ghcr.io/ledgerhq/speculos:latest + options: --entrypoint /bin/bash + + steps: + - name: Install dependencies + run: apt update && apt install -qy openjdk-17-jdk-headless git + + - name: Download app binary + uses: actions/download-artifact@v3 + with: + name: "compiled_app_binaries" + path: /tmp/app/build/ + + - name: Run speculos in the background + run: | + /speculos/speculos.py --display headless --seed "opinion change copy struggle town cigar input kit school patient execute bird bundle option canvas defense hover poverty skill donkey pottery infant sense orchard" /tmp/app/build/nanos/bin/app.elf 2>/tmp/speculos.log & + echo $! >/tmp/speculos.pid + + - name: Run tests with Ardor node + run: | + git clone --branch ledger-tests https://sargue@bitbucket.org/sargue/ardor-ledger-test.git /ardor + cd /ardor + ./run-unit-tests.sh com.jelurida.ardor.integration.wallet.ledger.application.LedgerSpeculosSuite + + - name: Kill speculos + run: kill -9 $(cat /tmp/speculos.pid) + + - name: Upload Speculos log + uses: actions/upload-artifact@v3 + if: failure() + with: + name: speculos-log + path: /tmp/speculos.log + + - name: Upload Ardor log + uses: actions/upload-artifact@v3 + if: failure() + with: + name: ardor-log + path: /ardor/logs/ardor.0.log diff --git a/.github/workflows/ci-workflow.yml b/.github/workflows/ci-workflow.yml deleted file mode 100644 index e6e156c..0000000 --- a/.github/workflows/ci-workflow.yml +++ /dev/null @@ -1,111 +0,0 @@ -name: Compilation & tests - -on: [push, pull_request] - -jobs: - job_build_debug: - name: Build debug - runs-on: ubuntu-latest - - container: - image: ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder:latest - - steps: - - name: Clone - uses: actions/checkout@v2 - - - name: Build - run: make DEBUG=1 - - - name: Upload app binary - uses: actions/upload-artifact@v2 - with: - name: app-bin - path: bin - - job_unit_test: - name: Unit test - needs: job_build_debug - runs-on: ubuntu-latest - - container: - image: ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder:latest - - steps: - - name: Clone - uses: actions/checkout@v2 - - - name: Build and run unit tests - run: | - cd tests - cmake -Bbuild -H. && make -C build && make -C build test - - job_clang_scan_build: - name: Clang scan-build - needs: job_build_debug - runs-on: ubuntu-latest - - container: - image: ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder:latest - - steps: - - name: Clone - uses: actions/checkout@v2 - - - name: Run static analyzer - run: | - make clean - scan-build --use-cc=clang -analyze-headers -enable-checker security -enable-checker unix -enable-checker valist -o scan-build --status-bugs make default - - job_functional_test: - name: Functional test - needs: job_build_debug - runs-on: ubuntu-latest - - container: - image: ghcr.io/ledgerhq/speculos:latest - options: --entrypoint /bin/bash - - steps: - - name: Install dependencies - run: apt update && apt install -qy openjdk-11-jdk-headless git - - - name: Download app binary - uses: actions/download-artifact@v2 - with: - name: app-bin - path: /tmp/app - - - name: Run speculos in the background - run: | - /speculos/speculos.py --display headless --seed "opinion change copy struggle town cigar input kit school patient execute bird bundle option canvas defense hover poverty skill donkey pottery infant sense orchard" /tmp/app/app.elf 2>/tmp/speculos.log & - echo $! >/tmp/speculos.pid - -# The ardor-ledger-test repository is a temporary solution until the next version is made public with the Speculos driver - - name: Install and compile Ardor - run: | - git clone https://sargue@bitbucket.org/sargue/ardor-ledger-test.git /ardor - cd /ardor - ./compile.sh --skip-desktop - - - name: Run tests - run: | - cd /ardor - ./run-unit-tests.sh com.jelurida.ardor.integration.wallet.ledger.application.ArdorAppBridgeHeadlessTest - - - name: Kill speculos - run: kill -9 $(cat /tmp/speculos.pid) - - - name: Upload Speculos log - uses: actions/upload-artifact@v2 - if: failure() - with: - name: speculos-log - path: /tmp/speculos.log - - - name: Upload Ardor log - uses: actions/upload-artifact@v2 - if: failure() - with: - name: ardor-log - path: /ardor/logs/ardor.0.log diff --git a/.github/workflows/codeql_checks.yml b/.github/workflows/codeql_checks.yml new file mode 100644 index 0000000..e4fef79 --- /dev/null +++ b/.github/workflows/codeql_checks.yml @@ -0,0 +1,44 @@ +name: "CodeQL" + +on: + workflow_dispatch: + push: + branches: + - master + - main + - develop + pull_request: + # Excluded path: add the paths you want to ignore instead of deleting the workflow + paths-ignore: + - '.github/workflows/*.yml' + - 'tests/*' + +jobs: + analyse: + name: Analyse + strategy: + matrix: + sdk: [ "$NANOS_SDK", "$NANOX_SDK", "$NANOSP_SDK", "$STAX_SDK" ] + #'cpp' covers C and C++ + language: [ 'cpp' ] + runs-on: ubuntu-latest + container: + image: ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder-legacy:latest + + steps: + - name: Clone + uses: actions/checkout@v3 + + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: ${{ matrix.language }} + queries: security-and-quality + + # CodeQL will create the database during the compilation + - name: Build + run: | + make BOLOS_SDK=${{ matrix.sdk }} + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 \ No newline at end of file diff --git a/.github/workflows/coding_style_checks.yml b/.github/workflows/coding_style_checks.yml new file mode 100644 index 0000000..6be2786 --- /dev/null +++ b/.github/workflows/coding_style_checks.yml @@ -0,0 +1,25 @@ +name: Run coding style check through reusable workflow + +# This workflow will run linting checks to ensure a level of uniformization among all Ledger applications. +# +# The presence of this workflow is mandatory as a minimal level of linting is required. +# You are however free to modify the content of the .clang-format file and thus the coding style of your application. +# We simply ask you to not diverge too much from the linting of the Boilerplate application. + +on: + workflow_dispatch: + push: + branches: + - master + - main + - develop + pull_request: + +jobs: + check_linting: + name: Check linting using the reusable workflow + uses: LedgerHQ/ledger-app-workflows/.github/workflows/reusable_lint.yml@v1 + with: + source: './src' + extensions: 'h,c' + version: 11 diff --git a/.github/workflows/guidelines_enforcer.yml b/.github/workflows/guidelines_enforcer.yml new file mode 100644 index 0000000..fdaf9f2 --- /dev/null +++ b/.github/workflows/guidelines_enforcer.yml @@ -0,0 +1,23 @@ +name: Ensure compliance with Ledger guidelines + +# This workflow is mandatory in all applications +# It calls a reusable workflow guidelines_enforcer developed by Ledger's internal developer team. +# The successful completion of the reusable workflow is a mandatory step for an app to be available on the Ledger +# application store. +# +# More information on the guidelines can be found in the repository: +# LedgerHQ/ledger-app-workflows/ + +on: + workflow_dispatch: + push: + branches: + - master + - main + - develop + pull_request: + +jobs: + guidelines_enforcer: + name: Call Ledger guidelines_enforcer + uses: LedgerHQ/ledger-app-workflows/.github/workflows/reusable_guidelines_enforcer.yml@v1 diff --git a/.gitignore b/.gitignore index 22c9c07..4d75612 100644 --- a/.gitignore +++ b/.gitignore @@ -2,11 +2,15 @@ bin/ debug/ dep/ obj/ +build/ src/glyphs\.c src/glyphs\.h usbtool/ -src/txnTypeLists.c .vscode/ output-scan-build/ tests/build/ -scan-build/ \ No newline at end of file +scan-build/ +.history/ +tests/__pycache__/ +tests/snapshots-tmp/ +.venv/ \ No newline at end of file diff --git a/LICENSE b/LICENSE index edfd62d..02bc710 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,5 @@ Copyright 2019-2020 Haim Bender +Copyright 2021-2023 Jelurida IP B.V. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/Makefile b/Makefile index 4432873..471b5a2 100755 --- a/Makefile +++ b/Makefile @@ -2,6 +2,7 @@ # Ledger App # (c) 2017 Ledger # (c) 2019 Haim Bender +# (c) 2021-2023 Jelurida IP B.V. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -16,10 +17,8 @@ # limitations under the License. #******************************************************************************* -#Defines -DEVEL = 0#This means we are in DEBUG mode, change this up when releasing in production - -#####################################3 +# Enabling DEBUG flag will enable PRINTF and disable optimizations +DEBUG ?= 0 ifeq ($(BOLOS_SDK),) $(error Environment variable BOLOS_SDK is not set) @@ -27,176 +26,44 @@ endif include $(BOLOS_SDK)/Makefile.defines -ifndef COIN -COIN=ardor -endif - -ifeq ($(COIN),ardor) - APPNAME = Ardor - DEFINES += "PATH_PREFIX={44|0x80000000,16754|0x80000000}" - PATH_PREFIX = "44'/16754'" - DEFINES += APP_PREFIX=\"ARDOR-\" - - ifeq ($(TARGET_NAME),TARGET_NANOS) - ICONNAME = ArdorIconNanoS.gif - else - ICONNAME = ArdorIconNanoX.gif - endif -else ifeq ($(COIN),nxt) - APPNAME = NXT - DEFINES += "PATH_PREFIX={44|0x80000000,29|0x80000000}" - PATH_PREFIX = "44'/29'" - DEFINES += APP_PREFIX=\"NXT-\" - - ifeq ($(TARGET_NAME),TARGET_NANOS) - ICONNAME = NXTIconNanoS.gif - else - ICONNAME = NXTIconNanoX.gif - endif -else - $(error /!\ Coin "$(COIN)" not in list of allowed variants! Type "make listvariants" for variants list. Build non-default variant with "make COIN=") -endif -$(info Building $(APPNAME) app...) - -############ -# Platform # -############ - -#This inits the SDK_SOURCE_PATH variable, moving this will screw up the build, because the next if does += -SDK_SOURCE_PATH = lib_stusb lib_stusb_impl lib_u2f lib_ux -APP_LOAD_PARAMS = --curve ed25519 $(COMMON_LOAD_PARAMS) - -# Ledger: add the "Pending security review" disclaimer -APP_LOAD_PARAMS += --tlvraw 9F:01 -DEFINES += HAVE_PENDING_REVIEW_SCREEN - -ifeq ($(TARGET_NAME),TARGET_NANOX) - SDK_SOURCE_PATH += lib_blewbxx lib_blewbxx_impl - # The --appFlags param gives permision to open bluetooth - APP_LOAD_PARAMS += --appFlags 0x0200 - DEFINES += HAVE_BLE BLE_COMMAND_TIMEOUT_MS=2000 - DEFINES += HAVE_BLE_APDU # basic ledger apdu transport over BLE -endif - -ifeq ($(TARGET_NAME),TARGET_NANOS) - # Since we don't have bluetooth in NanoS we set --appFlags to 0 - APP_LOAD_PARAMS += --appFlags 0x0000 - DEFINES += IO_SEPROXYHAL_BUFFER_SIZE_B=128 -else - DEFINES += IO_SEPROXYHAL_BUFFER_SIZE_B=300 - DEFINES += HAVE_GLO096 - DEFINES += BAGL_WIDTH=128 BAGL_HEIGHT=64 - DEFINES += HAVE_BAGL_ELLIPSIS # long label truncation feature - DEFINES += HAVE_BAGL_FONT_OPEN_SANS_REGULAR_11PX - DEFINES += HAVE_BAGL_FONT_OPEN_SANS_EXTRABOLD_11PX - DEFINES += HAVE_BAGL_FONT_OPEN_SANS_LIGHT_16PX -endif - -DEFINES += HAVE_UX_FLOW - +APPNAME = Ardor APPVERSION_M = 1 -APPVERSION_N = 0 -APPVERSION_P = 4 +APPVERSION_N = 1 +APPVERSION_P = 0 DEFINES += APPVERSION_M=$(APPVERSION_M) DEFINES += APPVERSION_N=$(APPVERSION_N) DEFINES += APPVERSION_P=$(APPVERSION_P) -APPVERSION = $(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P) - - - -# The --path argument here restricts which BIP32 paths the app is allowed to derive. -APP_LOAD_PARAMS += --path $(PATH_PREFIX) -APP_SOURCE_PATH = src - -DEFINES += HAVE_BAGL HAVE_SPRINTF HAVE_BOLOS_APP_STACK_CANARY OS_IO_SEPROXYHAL -DEFINES += HAVE_IO_USB HAVE_L4_USBLIB IO_USB_MAX_ENDPOINTS=6 IO_HID_EP_LENGTH=64 HAVE_USB_APDU -DEFINES += LEDGER_MAJOR_VERSION=$(APPVERSION_M) LEDGER_MINOR_VERSION=$(APPVERSION_N) LEDGER_PATCH_VERSION=$(APPVERSION_P) TCS_LOADER_PATCH_VERSION=0 -DEFINES += APPVERSION=\"$(APPVERSION)\" +APPVERSION = $(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P) -# U2F -DEFINES += HAVE_U2F HAVE_IO_U2F -DEFINES += U2F_PROXY_MAGIC=\"ARD\" -DEFINES += USB_SEGMENT_SIZE=64 -DEFINES += BLE_SEGMENT_SIZE=32 #max MTU, min 20 +VARIANT_PARAM = COIN +VARIANT_VALUES = ardor +DEFINES += "PATH_PREFIX={44|0x80000000,16754|0x80000000}" +PATH_PREFIX = "44'/16754'" +DEFINES += APP_PREFIX=\"ARDOR-\" -WEBUSB_URL = https://www.ledger.com/pages/supported-crypto-assets #todo swap this to some jelurida web site -DEFINES += HAVE_WEBUSB WEBUSB_URL_SIZE_B=$(shell echo -n $(WEBUSB_URL) | wc -c) WEBUSB_URL=$(shell echo -n $(WEBUSB_URL) | sed -e "s/./\\\'\0\\\',/g") +ICON_NANOS = icons/ArdorIconNanoS.gif +ICON_NANOX = icons/ArdorIconNanoX.gif +ICON_NANOSP = icons/ArdorIconNanoX.gif +ICON_STAX = icons/ArdorIcon32px.gif -DEFINES += BLAKE_SDK +ENABLE_NBGL_QRCODE = 1 -# Enabling debug PRINTF -ifeq ($(DEVEL), 1) - DEFINES += DEVEL HAVE_PRINTF - ifeq ($(TARGET_NAME),TARGET_NANOS) - DEFINES += PRINTF=screen_printf - else - DEFINES += PRINTF=mcu_usb_printf - endif -else - DEFINES += PRINTF\(...\)= -endif - -AUTOGEN_SRC := src/txnTypeLists.c -AUTOGEN_OBJ := $(AUTOGEN_SRC:src/%.c=obj/%.o) - -SOURCE_FILES += $(AUTOGEN_SRC) - -.PHONY: realclean clean +CURVE_APP_LOAD_PARAMS = ed25519 +PATH_APP_LOAD_PARAMS = $(PATH_PREFIX) -all: default +ENABLE_BLUETOOTH = 1 -$(AUTOGEN_OBJ): src/authAndSignTxn.c $(AUTOGEN_SRC) +APP_SOURCE_PATH += src -$(AUTOGEN_SRC): createTxnTypes.py txtypes.txt - python ./createTxnTypes.py > $@ +GEN_TX_TYPE_LIST_SRC := src/txnTypeLists.c -load: all - python -m ledgerblue.loadApp $(APP_LOAD_PARAMS) - -delete: - python -m ledgerblue.deleteApp $(COMMON_DELETE_PARAMS) +$(GEN_TX_TYPE_LIST_SRC): createTxnTypes.py txtypes.txt + python3 ./createTxnTypes.py > $@ +.PHONY: realclean realclean: clean - rm -f $(AUTOGEN_SRC) - - -############## -# Compiler # -############## -ifneq ($(BOLOS_ENV),) -$(info BOLOS_ENV=$(BOLOS_ENV)) -CLANGPATH := $(BOLOS_ENV)/clang-arm-fropi/bin/ -GCCPATH := $(BOLOS_ENV)/gcc-arm-none-eabi-5_3-2016q1/bin/ -else -$(info BOLOS_ENV is not set: falling back to CLANGPATH and GCCPATH) -endif -ifeq ($(CLANGPATH),) -$(info CLANGPATH is not set: clang will be used from PATH) -endif -ifeq ($(GCCPATH),) -$(info GCCPATH is not set: arm-none-eabi-* will be used from PATH) -endif - -CC := $(CLANGPATH)clang -CFLAGS += -O3 -Os - -AS := $(GCCPATH)arm-none-eabi-gcc -LD := $(GCCPATH)arm-none-eabi-gcc -LDFLAGS += -O3 -Os -LDLIBS += -lm -lgcc -lc - -################## -# Dependencies # -################## - -# import rules to compile glyphs -include $(BOLOS_SDK)/Makefile.glyphs -# import generic rules from the sdk -include $(BOLOS_SDK)/Makefile.rules - -dep/%.d: %.c Makefile + rm -f $(GEN_TX_TYPE_LIST_SRC) -listvariants: - @echo VARIANTS COIN ardor +include $(BOLOS_SDK)/Makefile.standard_app diff --git a/NXTIconNanoS.gif b/NXTIconNanoS.gif deleted file mode 100644 index b869727..0000000 Binary files a/NXTIconNanoS.gif and /dev/null differ diff --git a/NXTIconNanoX.gif b/NXTIconNanoX.gif deleted file mode 100644 index a6d1cde..0000000 Binary files a/NXTIconNanoX.gif and /dev/null differ diff --git a/README.md b/README.md index 2540abf..918b8e6 100644 --- a/README.md +++ b/README.md @@ -17,15 +17,38 @@ Then you can switch to this repository and launch the `ledger-app-builder` docke $ docker run --rm -ti -v "$(realpath .):/app" ledger-app-builder:latest root@656be163fe84:/app# make -### Unit test +### Functional tests -Unit tests are under the `tests` directory. You can build and run them with the following commands: +Functional tests are written using the Ragger framework. The tests are located in the `tests` folder. - cd tests - cmake -Bbuild -H. && make -C build - CTEST_OUTPUT_ON_FAILURE=1 make -C build clean test +#### Install ragger and dependencies -To clean the tests build just delete the `tests/build` directory. + pip install --extra-index-url https://test.pypi.org/simple/ -r requirements.txt + sudo apt-get update && sudo apt-get install qemu-user-static + +#### Run tests + +To run all tests just issue the following command: + + pytest --device all -v --tb=short tests/ + +Please note you need all the different versions compiled. You can compile them all by running the helper script `./make-all` inside the docker build image. + +### End to end tests + +End to end tests are run from an Ardor node and the Speculos emulator. The Ardor node has some unit tests that use the Speculos emulator to test the Ledger app. Those tests also use the Speculos API to assert screen texts and send button press commands. + +These tests require Docker (or a local Speculos installation) and Java 8 or newer. + +To run the tests you need to build the app, load it into the Speculos emulator and run the tests from the Ardor node. + +1. Build the Ledger app. +2. Run the app on the Speculos emulator using Docker. As an alternative you can use a locally installed Speculos emulator. In this case you will need to run the emulator on port 9999 and the API server on port 5000. The following command will run the emulator on Docker: + + docker run --rm -it -v $(pwd):/speculos/apps -p 9999:9999 -p 5000:5000 ghcr.io/ledgerhq/speculos --display headless --seed "opinion change copy struggle town cigar input kit school patient execute bird bundle option canvas defense hover poverty skill donkey pottery infant sense orchard" --model nanos apps/bin/app.elf + +3. Clone the Ardor node repository with the Ledger unit tests: `git clone https://sargue@bitbucket.org/sargue/ardor-ledger-test.git` +4. Run tests: `./run-unit-tests.sh com.jelurida.ardor.integration.wallet.ledger.application.LedgerSpeculosSuite` ### Enable Log Messages @@ -67,15 +90,6 @@ The project uses Github Actions to run the Clang static analyzer and the unit te The CI is configured on the `.github/workflows/ci-workflow.yml` with inspiration from the [`app-boilerplate`](/~https://github.com/LedgerHQ/app-boilerplate) and the [`app-xrp`](/~https://github.com/LedgerHQ/app-xrp). -### State Cleaning - -Since we use a union data type for command handlers state (`states_t` in `ardor.h`) to save memory, make sure to **clear this state** -to avoid some attack vectors. - -This is done by passing `true` in the `isLastCommandDifferent` parameter of the handler function. In this case the handler has to clear the state before using it. - -In addition state must be cleared whenever we get an error in a handler function which manages state. - ### More Code Design Do not include project header files inside other project header files to prevent complicating the dependencies. @@ -92,8 +106,8 @@ Changes to the `txtypes.txt` should be picked up by the make process and a new ` ### Code Flow -The code flow starts at ardor_main (`main.c`) which uses a global try/catch to prevent the app from crashing on error. -The code loops on io_exchange waiting for the next command buffer, then calling the appropriate handler function implemented in the different .c files. +The code flow starts at `app_main` which uses a global try/catch to prevent the app from crashing on error. +The code loops on `io_recv_command` waiting for the next command buffer, then calling the appropriate handler function implemented in the different .c files. ## APDU Protocol @@ -141,7 +155,7 @@ All return values for functions should be checked in every function. ## Key Derivation Algorithm -Ardor signatures are based on the EC-KCDSA over Curve25519 algorithm which is not supported natively by Ledger. +Ardor signatures are based on a custom variant of the EC-KCDSA over Curve25519 algorithm which is not supported natively by Ledger. To support standard BIP32 key derivation we implemented curve conversion for Ardor using the protocol [Yaffe-Bender HD key derivation for EC-KCDSA](https://www.jelurida.com/sites/default/files/kcdsa.pdf), it's a derivation scheme that rides on top of the BIP32-Ed25519 HD key derivation scheme. @@ -157,7 +171,7 @@ Let's refer to `CLAMP(SHA512(privateKey)[:32])` as KL The derivation composition flow for path P is: -1. os_perso_derive_node_bip32 derives KLKR and chaincode for P using SLIP10 initialization on 512 bits master seed from bip39/bip32 24 words +1. os_derive_bip32_no_throw derives KLKR and chaincode for P using SLIP10 initialization on 512 bits master seed from bip39/bip32 24 words 2. Derive PublicKeyED25519 using cx_eddsa_get_public_key and KL, the point is encoded as 65 bytes 0x04 XBigEndian YBigEndian 3. PubleyKeyED25519YLE = convert(YBigEndian) - just reverse the bytes 4. PublicKeyCurve25519X = morph(PublicKeyEED25519YLE) @@ -176,4 +190,6 @@ Extra Notes: * [This repo](/~https://github.com/LedgerHQ/orakolo) implements SLIP10 master seed generation and BIP32 HD EdDSA key derivation in python for reference, [this clone](/~https://github.com/haimbender/orakolo) also implements master public key derivation for BIP32 EdDSA -* Curve25519 and ED25519 curves don't really look like curves, they are just a cloud of points +* Signing is using the formula `s * (x - h) mod order25519`. This differs from a standard +implementation of EC-KCDSA (`s * (x - h ⊕ r)`). In this custom variant, `h` is calculated as +`H(m || r)` , where `r = [k]G and k = H(m || sk)`. diff --git a/createTxnTypes.py b/createTxnTypes.py index 73dd8a2..a252afb 100644 --- a/createTxnTypes.py +++ b/createTxnTypes.py @@ -1,16 +1,20 @@ -appendageParseFunctionDict = {0x000b : 4, 0x00fc: 4, 0x0102: 7} +appendageParseFunctionDict = {0x000b : 4, 0x00fc: 4, 0x0202: 5, 0x0302: 5, 0x0102: 7} def main(): with open("txtypes.txt", "r") as f: - out = '//This is an auto generated file by createTxnTypes.py\n\n\n\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include "config.h"\n#include "ardor.h"\n\nconst txnType TXN_TYPES[] = {' + out = '// This is an auto generated file by createTxnTypes.py\n\n' + out += '#include \n#include "ardor.h"\n\n' + varDeclaration = 'const txnType TXN_TYPES[] = {' + out += varDeclaration lines = f.readlines() + indent = None for line in lines: txtype, txSubType, name = line.split(',') @@ -19,7 +23,13 @@ def main(): parseFunction = appendageParseFunctionDict.get(txSubType * 256 + txtype , 0) - out += '{' + '0x{:02x}{:02x},"{}",{}'.format(txSubType, txtype, name.rstrip(), parseFunction) + '},\n' + # indent from the second line with len(varDeclaration) spaces + if indent is None: + indent = '' + else: + indent = ' ' * len(varDeclaration) + + out += indent + '{' + '0x{:02x}{:02x}, "{}", {}'.format(txSubType, txtype, name.rstrip(), parseFunction) + '},\n' print(out[0:-2] + "};") diff --git a/glyphs/ArdorIcon64px.gif b/glyphs/ArdorIcon64px.gif new file mode 100644 index 0000000..c8751dc Binary files /dev/null and b/glyphs/ArdorIcon64px.gif differ diff --git a/glyphs/icon_back.gif b/glyphs/icon_back.gif deleted file mode 100644 index a2a7e6d..0000000 Binary files a/glyphs/icon_back.gif and /dev/null differ diff --git a/glyphs/icon_crossmark.gif b/glyphs/icon_crossmark.gif deleted file mode 100644 index 2dcf9d9..0000000 Binary files a/glyphs/icon_crossmark.gif and /dev/null differ diff --git a/glyphs/icon_dashboard.gif b/glyphs/icon_dashboard.gif deleted file mode 100644 index 5c30551..0000000 Binary files a/glyphs/icon_dashboard.gif and /dev/null differ diff --git a/glyphs/icon_eye.gif b/glyphs/icon_eye.gif deleted file mode 100644 index df4bb82..0000000 Binary files a/glyphs/icon_eye.gif and /dev/null differ diff --git a/glyphs/icon_validate_14.gif b/glyphs/icon_validate_14.gif deleted file mode 100644 index ccb5cab..0000000 Binary files a/glyphs/icon_validate_14.gif and /dev/null differ diff --git a/glyphs/icon_warning.gif b/glyphs/icon_warning.gif deleted file mode 100644 index 08bd4a7..0000000 Binary files a/glyphs/icon_warning.gif and /dev/null differ diff --git a/icons/ArdorIcon32px.gif b/icons/ArdorIcon32px.gif new file mode 100644 index 0000000..6cc0ea6 Binary files /dev/null and b/icons/ArdorIcon32px.gif differ diff --git a/ArdorIconNanoS.gif b/icons/ArdorIconNanoS.gif similarity index 100% rename from ArdorIconNanoS.gif rename to icons/ArdorIconNanoS.gif diff --git a/ArdorIconNanoX.gif b/icons/ArdorIconNanoX.gif similarity index 100% rename from ArdorIconNanoX.gif rename to icons/ArdorIconNanoX.gif diff --git a/ledger_app.toml b/ledger_app.toml new file mode 100644 index 0000000..376e254 --- /dev/null +++ b/ledger_app.toml @@ -0,0 +1,7 @@ +[app] +build_directory = "./" +sdk = "C" +devices = ["nanos", "nanox", "nanos+", "stax"] + +[tests] +pytest_directory = "./tests/" \ No newline at end of file diff --git a/make-all b/make-all new file mode 100755 index 0000000..c68f932 --- /dev/null +++ b/make-all @@ -0,0 +1,5 @@ +make clean +make BOLOS_SDK=$NANOS_SDK +make BOLOS_SDK=$NANOX_SDK +make BOLOS_SDK=$NANOSP_SDK +make BOLOS_SDK=$STAX_SDK \ No newline at end of file diff --git a/nanos_1.gif b/nanos_1.gif deleted file mode 100644 index 3332de3..0000000 Binary files a/nanos_1.gif and /dev/null differ diff --git a/src/aes/aes-cbc.c b/src/aes/aes-cbc.c deleted file mode 100644 index 5d63cb0..0000000 --- a/src/aes/aes-cbc.c +++ /dev/null @@ -1,129 +0,0 @@ -//needed - -/* - * AES-128 CBC - * - * Copyright (c) 2003-2007, Jouni Malinen - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#include "os.h" - -#include "aes.h" - -/** - * aes_128_cbc_encrypt - AES-128 CBC encryption - * @key: Encryption key - * @iv: Encryption IV for CBC mode (16 bytes) - * @data: Data to encrypt in-place - * @data_len: Length of data in bytes (must be divisible by 16) - * Returns: 0 on success, -1 on failure - */ -int aes_128_cbc_encrypt(const aes_uchar *key, const aes_uchar *iv, aes_uchar *data, size_t data_len) -{ - void *ctx; - aes_uchar cbc[AES_BLOCK_SIZE]; - aes_uchar *pos = data; - size_t i, j, blocks; - - ctx = aes_encrypt_init(key, 16); - if (ctx == NULL) - return -1; - memcpy(cbc, iv, AES_BLOCK_SIZE); - - blocks = data_len / AES_BLOCK_SIZE; - for (i = 0; i < blocks; i++) { - for (j = 0; j < AES_BLOCK_SIZE; j++) - cbc[j] ^= pos[j]; - aes_encrypt(ctx, cbc, cbc); - memcpy(pos, cbc, AES_BLOCK_SIZE); - pos += AES_BLOCK_SIZE; - } - aes_encrypt_deinit(ctx); - return 0; -} - - -int aes_256_cbc_encrypt(const aes_uchar *key, const aes_uchar *iv, aes_uchar *data, size_t data_len) -{ - void *ctx; - aes_uchar cbc[AES_BLOCK_SIZE]; - aes_uchar *pos = data; - size_t i, j, blocks; - - ctx = aes_encrypt_init(key, 32); - if (ctx == NULL) - return -1; - memcpy(cbc, iv, AES_BLOCK_SIZE); - - blocks = data_len / AES_BLOCK_SIZE; - for (i = 0; i < blocks; i++) { - for (j = 0; j < AES_BLOCK_SIZE; j++) - cbc[j] ^= pos[j]; - aes_encrypt(ctx, cbc, cbc); - memcpy(pos, cbc, AES_BLOCK_SIZE); - pos += AES_BLOCK_SIZE; - } - aes_encrypt_deinit(ctx); - return 0; -} - -/** - * aes_128_cbc_decrypt - AES-128 CBC decryption - * @key: Decryption key - * @iv: Decryption IV for CBC mode (16 bytes) - * @data: Data to decrypt in-place - * @data_len: Length of data in bytes (must be divisible by 16) - * Returns: 0 on success, -1 on failure - */ -int aes_128_cbc_decrypt(const aes_uchar *key, const aes_uchar *iv, aes_uchar *data, size_t data_len) -{ - void *ctx; - aes_uchar cbc[AES_BLOCK_SIZE], tmp[AES_BLOCK_SIZE]; - aes_uchar *pos = data; - size_t i, j, blocks; - - ctx = aes_decrypt_init(key, 16); - if (ctx == NULL) - return -1; - memcpy(cbc, iv, AES_BLOCK_SIZE); - - blocks = data_len / AES_BLOCK_SIZE; - for (i = 0; i < blocks; i++) { - memcpy(tmp, pos, AES_BLOCK_SIZE); - aes_decrypt(ctx, pos, pos); - for (j = 0; j < AES_BLOCK_SIZE; j++) - pos[j] ^= cbc[j]; - memcpy(cbc, tmp, AES_BLOCK_SIZE); - pos += AES_BLOCK_SIZE; - } - aes_decrypt_deinit(ctx); - return 0; -} - -int aes_256_cbc_decrypt(const aes_uchar *key, const aes_uchar *iv, aes_uchar *data, size_t data_len) -{ - void *ctx; - aes_uchar cbc[AES_BLOCK_SIZE], tmp[AES_BLOCK_SIZE]; - aes_uchar *pos = data; - size_t i, j, blocks; - - ctx = aes_decrypt_init(key, 32); - if (ctx == NULL) - return -1; - memcpy(cbc, iv, AES_BLOCK_SIZE); - - blocks = data_len / AES_BLOCK_SIZE; - for (i = 0; i < blocks; i++) { - memcpy(tmp, pos, AES_BLOCK_SIZE); - aes_decrypt(ctx, pos, pos); - for (j = 0; j < AES_BLOCK_SIZE; j++) - pos[j] ^= cbc[j]; - memcpy(cbc, tmp, AES_BLOCK_SIZE); - pos += AES_BLOCK_SIZE; - } - aes_decrypt_deinit(ctx); - return 0; -} diff --git a/src/aes/aes-ccm.c b/src/aes/aes-ccm.c deleted file mode 100644 index c0cd0d5..0000000 --- a/src/aes/aes-ccm.c +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Counter with CBC-MAC (CCM) with AES - * - * Copyright (c) 2010-2012, Jouni Malinen - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#include -#include "aes.h" - - -static void xor_aes_block(aes_uchar *dst, const aes_uchar *src) -{ - aes_uint *d = (aes_uint *) dst; - aes_uint *s = (aes_uint *) src; - *d++ ^= *s++; - *d++ ^= *s++; - *d++ ^= *s++; - *d++ ^= *s++; -} - - -static void aes_ccm_auth_start(void *aes, size_t M, size_t L, const aes_uchar *nonce, - const aes_uchar *aad, size_t aad_len, size_t plain_len, - aes_uchar *x) -{ - aes_uchar aad_buf[2 * AES_BLOCK_SIZE]; - aes_uchar b[AES_BLOCK_SIZE]; - - /* Authentication */ - /* B_0: Flags | Nonce N | l(m) */ - b[0] = aad_len ? 0x40 : 0 /* Adata */; - b[0] |= (((M - 2) / 2) /* M' */ << 3); - b[0] |= (L - 1) /* L' */; - memcpy(&b[1], nonce, 15 - L); - AES_PUT_BE16(&b[AES_BLOCK_SIZE - L], plain_len); - - aes_hexdump_key(MSG_EXCESSIVE, "CCM B_0", b, AES_BLOCK_SIZE); - aes_encrypt(aes, b, x); /* X_1 = E(K, B_0) */ - - if (!aad_len) - return; - - AES_PUT_BE16(aad_buf, aad_len); - memcpy(aad_buf + 2, aad, aad_len); - memset(aad_buf + 2 + aad_len, 0, sizeof(aad_buf) - 2 - aad_len); - - xor_aes_block(aad_buf, x); - aes_encrypt(aes, aad_buf, x); /* X_2 = E(K, X_1 XOR B_1) */ - - if (aad_len > AES_BLOCK_SIZE - 2) { - xor_aes_block(&aad_buf[AES_BLOCK_SIZE], x); - /* X_3 = E(K, X_2 XOR B_2) */ - aes_encrypt(aes, &aad_buf[AES_BLOCK_SIZE], x); - } -} - - -static void aes_ccm_auth(void *aes, const aes_uchar *data, size_t len, aes_uchar *x) -{ - size_t last = len % AES_BLOCK_SIZE; - size_t i; - - for (i = 0; i < len / AES_BLOCK_SIZE; i++) { - /* X_i+1 = E(K, X_i XOR B_i) */ - xor_aes_block(x, data); - data += AES_BLOCK_SIZE; - aes_encrypt(aes, x, x); - } - if (last) { - /* XOR zero-padded last block */ - for (i = 0; i < last; i++) - x[i] ^= *data++; - aes_encrypt(aes, x, x); - } -} - - -static void aes_ccm_encr_start(size_t L, const aes_uchar *nonce, aes_uchar *a) -{ - /* A_i = Flags | Nonce N | Counter i */ - a[0] = L - 1; /* Flags = L' */ - memcpy(&a[1], nonce, 15 - L); -} - - -static void aes_ccm_encr(void *aes, const aes_uchar *in, size_t len, aes_uchar *out, - aes_uchar *a) -{ - size_t last = len % AES_BLOCK_SIZE; - size_t i; - - /* crypt = msg XOR (S_1 | S_2 | ... | S_n) */ - for (i = 1; i <= len / AES_BLOCK_SIZE; i++) { - AES_PUT_BE16(&a[AES_BLOCK_SIZE - 2], i); - /* S_i = E(K, A_i) */ - aes_encrypt(aes, a, out); - xor_aes_block(out, in); - out += AES_BLOCK_SIZE; - in += AES_BLOCK_SIZE; - } - if (last) { - AES_PUT_BE16(&a[AES_BLOCK_SIZE - 2], i); - aes_encrypt(aes, a, out); - /* XOR zero-padded last block */ - for (i = 0; i < last; i++) - *out++ ^= *in++; - } -} - - -static void aes_ccm_encr_auth(void *aes, size_t M, aes_uchar *x, aes_uchar *a, aes_uchar *auth) -{ - size_t i; - aes_uchar tmp[AES_BLOCK_SIZE]; - - aes_hexdump_key(MSG_EXCESSIVE, "CCM T", x, M); - /* U = T XOR S_0; S_0 = E(K, A_0) */ - AES_PUT_BE16(&a[AES_BLOCK_SIZE - 2], 0); - aes_encrypt(aes, a, tmp); - for (i = 0; i < M; i++) - auth[i] = x[i] ^ tmp[i]; - aes_hexdump_key(MSG_EXCESSIVE, "CCM U", auth, M); -} - - -static void aes_ccm_decr_auth(void *aes, size_t M, aes_uchar *a, const aes_uchar *auth, aes_uchar *t) -{ - size_t i; - aes_uchar tmp[AES_BLOCK_SIZE]; - - aes_hexdump_key(MSG_EXCESSIVE, "CCM U", auth, M); - /* U = T XOR S_0; S_0 = E(K, A_0) */ - AES_PUT_BE16(&a[AES_BLOCK_SIZE - 2], 0); - aes_encrypt(aes, a, tmp); - for (i = 0; i < M; i++) - t[i] = auth[i] ^ tmp[i]; - aes_hexdump_key(MSG_EXCESSIVE, "CCM T", t, M); -} - - -/* AES-CCM with fixed L=2 and aad_len <= 30 assumption */ -int aes_ccm_ae(const aes_uchar *key, size_t key_len, const aes_uchar *nonce, - size_t M, const aes_uchar *plain, size_t plain_len, - const aes_uchar *aad, size_t aad_len, aes_uchar *crypt, aes_uchar *auth) -{ - const size_t L = 2; - void *aes; - aes_uchar x[AES_BLOCK_SIZE], a[AES_BLOCK_SIZE]; - - if (aad_len > 30 || M > AES_BLOCK_SIZE) - return -1; - - aes = aes_encrypt_init(key, key_len); - if (aes == NULL) - return -1; - - aes_ccm_auth_start(aes, M, L, nonce, aad, aad_len, plain_len, x); - aes_ccm_auth(aes, plain, plain_len, x); - - /* Encryption */ - aes_ccm_encr_start(L, nonce, a); - aes_ccm_encr(aes, plain, plain_len, crypt, a); - aes_ccm_encr_auth(aes, M, x, a, auth); - - aes_encrypt_deinit(aes); - - return 0; -} - - -/* AES-CCM with fixed L=2 and aad_len <= 30 assumption */ -int aes_ccm_ad(const aes_uchar *key, size_t key_len, const aes_uchar *nonce, - size_t M, const aes_uchar *crypt, size_t crypt_len, - const aes_uchar *aad, size_t aad_len, const aes_uchar *auth, aes_uchar *plain) -{ - const size_t L = 2; - void *aes; - aes_uchar x[AES_BLOCK_SIZE], a[AES_BLOCK_SIZE]; - aes_uchar t[AES_BLOCK_SIZE]; - - if (aad_len > 30 || M > AES_BLOCK_SIZE) - return -1; - - aes = aes_encrypt_init(key, key_len); - if (aes == NULL) - return -1; - - /* Decryption */ - aes_ccm_encr_start(L, nonce, a); - aes_ccm_decr_auth(aes, M, a, auth, t); - - /* plaintext = msg XOR (S_1 | S_2 | ... | S_n) */ - aes_ccm_encr(aes, crypt, crypt_len, plain, a); - - aes_ccm_auth_start(aes, M, L, nonce, aad, aad_len, crypt_len, x); - aes_ccm_auth(aes, plain, crypt_len, x); - - aes_encrypt_deinit(aes); - - if (memcmp(x, t, M) != 0) { - aes_printf(MSG_EXCESSIVE, "CCM: Auth mismatch"); - return -1; - } - - return 0; -} diff --git a/src/aes/aes-common.h b/src/aes/aes-common.h deleted file mode 100644 index dad83b7..0000000 --- a/src/aes/aes-common.h +++ /dev/null @@ -1,258 +0,0 @@ -/* - * aes-common.h - * - * Copyright (c) 2014, Michael Clark - * - * derived from wpa_supplicant - * Copyright (c) 2002-2013, Jouni Malinen - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#ifndef AES_COMMON_H -#define AES_COMMON_H - -#include -#include -#include -#include -#include - - -/* integer types */ - -typedef unsigned char aes_uchar; -typedef unsigned short aes_ushort; -typedef unsigned int aes_uint; -typedef unsigned long long aes_ulong; -typedef signed char aes_char; -typedef signed short aes_short; -typedef signed int aes_int; -typedef signed long long aes_long; - - -/* byte order */ - -#if defined(__linux__) || defined(__GLIBC__) -#include -#include -#endif /* defined(__linux__) || defined(__GLIBC__) */ - -#if defined(__FreeBSD__) || defined(__NetBSD__) || \ - defined(__DragonFly__) || defined(__OpenBSD__) -#include -#include -#define __BYTE_ORDER _BYTE_ORDER -#define __LITTLE_ENDIAN _LITTLE_ENDIAN -#define __BIG_ENDIAN _BIG_ENDIAN -#endif /* defined(__FreeBSD__) || defined(__NetBSD__) || - * defined(__DragonFly__) || defined(__OpenBSD__) */ - -#ifdef sun -#include -#define __LITTLE_ENDIAN 1234 -#define __BIG_ENDIAN 4321 -#ifdef _LITTLE_ENDIAN -#define __BYTE_ORDER __LITTLE_ENDIAN -#else -#define __BYTE_ORDER __BIG_ENDIAN -#endif -#endif - -#ifdef _MSC_VER -#define inline __inline -#define __LITTLE_ENDIAN 1234 -#define __BIG_ENDIAN 4321 -#define __BYTE_ORDER __LITTLE_ENDIAN -#endif /* _MSC_VER */ - -#ifdef __APPLE__ -#include -#include -#define __BYTE_ORDER BYTE_ORDER -#define __LITTLE_ENDIAN LITTLE_ENDIAN -#define __BIG_ENDIAN BIG_ENDIAN -#endif /* __APPLE__ */ - - -/* byte swap macros */ - -#ifndef bswap_16 -#define bswap_16(a) ((((aes_ushort) (a) & 0xff00) >> 8) | \ - (((aes_ushort) (a) & 0x00ff) << 8)) -#endif - -#ifndef bswap_32 -#if defined __GNUC__ -#define bswap_32(a) __builtin_bswap32(a) -#else -#define bswap_32(a) ((((aes_uint) (a) & 0xff000000) >> 24) | \ - (((aes_uint) (a) & 0x00ff0000) >> 8) | \ - (((aes_uint) (a) & 0x0000ff00) << 8) | \ - (((aes_uint) (a) & 0x000000ff) << 24)) -#endif -#endif - -#ifndef bswap_64 -#if defined __GNUC__ -#define bswap_64(a) __builtin_bswap64(a) -#else -#define bswap_64(a) ((((aes_ulong) (a) & 0xff00000000000000ull) >> 56) | \ - (((aes_ulong) (a) & 0x00ff000000000000ull) >> 40) | \ - (((aes_ulong) (a) & 0x0000ff0000000000ull) >> 24) | \ - (((aes_ulong) (a) & 0x000000ff00000000ull) >> 8) | \ - (((aes_ulong) (a) & 0x00000000ff000000ull) << 8) | \ - (((aes_ulong) (a) & 0x0000000000ff0000ull) << 24) | \ - (((aes_ulong) (a) & 0x000000000000ff00ull) << 40) | \ - (((aes_ulong) (a) & 0x00000000000000ffull) << 56)) -#endif -#endif - - -#if __BYTE_ORDER == __LITTLE_ENDIAN -#define __ENDIAN_LITTLE__ 1 /* OpenCL */ -#define le_to_host16(n) (n) -#define host_to_le16(n) (n) -#define be_to_host16(n) bswap_16(n) -#define host_to_be16(n) bswap_16(n) -#define le_to_host32(n) (n) -#define host_to_le32(n) (n) -#define be_to_host32(n) bswap_32(n) -#define host_to_be32(n) bswap_32(n) -#define le_to_host64(n) (n) -#define host_to_le64(n) (n) -#define be_to_host64(n) bswap_64(n) -#define host_to_be64(n) bswap_64(n) -#elif __BYTE_ORDER == __BIG_ENDIAN -#define le_to_host16(n) bswap_16(n) -#define host_to_le16(n) bswap_16(n) -#define be_to_host16(n) (n) -#define host_to_be16(n) (n) -#define le_to_host32(n) bswap_32(n) -#define host_to_le32(n) bswap_32(n) -#define be_to_host32(n) (n) -#define host_to_be32(n) (n) -#define le_to_host64(n) bswap_64(n) -#define host_to_le64(n) bswap_64(n) -#define be_to_host64(n) (n) -#define host_to_be64(n) (n) -#else -#error Could not determine CPU byte order -#endif - - -/* unaligned memory accesses */ - -static inline aes_ushort AES_GET_BE16(const aes_uchar *a) -{ - return (a[0] << 8) | a[1]; -} - -static inline void AES_PUT_BE16(aes_uchar *a, aes_ushort val) -{ - a[0] = val >> 8; - a[1] = val & 0xff; -} - -static inline aes_ushort AES_GET_LE16(const aes_uchar *a) -{ - return (a[1] << 8) | a[0]; -} - -static inline void AES_PUT_LE16(aes_uchar *a, aes_ushort val) -{ - a[1] = val >> 8; - a[0] = val & 0xff; -} - -static inline aes_uint AES_GET_BE24(const aes_uchar *a) -{ - return (a[0] << 16) | (a[1] << 8) | a[2]; -} - -static inline void AES_PUT_BE24(aes_uchar *a, aes_uint val) -{ - a[0] = (val >> 16) & 0xff; - a[1] = (val >> 8) & 0xff; - a[2] = val & 0xff; -} - -static inline aes_uint AES_GET_BE32(const aes_uchar *a) -{ - return (a[0] << 24) | (a[1] << 16) | (a[2] << 8) | a[3]; -} - -static inline void AES_PUT_BE32(aes_uchar *a, aes_uint val) -{ - a[0] = (val >> 24) & 0xff; - a[1] = (val >> 16) & 0xff; - a[2] = (val >> 8) & 0xff; - a[3] = val & 0xff; -} - -static inline aes_uint AES_GET_LE32(const aes_uchar *a) -{ - return (a[3] << 24) | (a[2] << 16) | (a[1] << 8) | a[0]; -} - -static inline void AES_PUT_LE32(aes_uchar *a, aes_uint val) -{ - a[3] = (val >> 24) & 0xff; - a[2] = (val >> 16) & 0xff; - a[1] = (val >> 8) & 0xff; - a[0] = val & 0xff; -} - -static inline aes_ulong AES_GET_BE64(const aes_uchar *a) -{ - return (((aes_ulong) a[0]) << 56) | (((aes_ulong) a[1]) << 48) | - (((aes_ulong) a[2]) << 40) | (((aes_ulong) a[3]) << 32) | - (((aes_ulong) a[4]) << 24) | (((aes_ulong) a[5]) << 16) | - (((aes_ulong) a[6]) << 8) | ((aes_ulong) a[7]); -} - -static inline void AES_PUT_BE64(aes_uchar *a, aes_ulong val) -{ - a[0] = val >> 56; - a[1] = val >> 48; - a[2] = val >> 40; - a[3] = val >> 32; - a[4] = val >> 24; - a[5] = val >> 16; - a[6] = val >> 8; - a[7] = val & 0xff; -} - -static inline aes_ulong AES_GET_LE64(const aes_uchar *a) -{ - return (((aes_ulong) a[7]) << 56) | (((aes_ulong) a[6]) << 48) | - (((aes_ulong) a[5]) << 40) | (((aes_ulong) a[4]) << 32) | - (((aes_ulong) a[3]) << 24) | (((aes_ulong) a[2]) << 16) | - (((aes_ulong) a[1]) << 8) | ((aes_ulong) a[0]); -} - -static inline void AES_PUT_LE64(aes_uchar *a, aes_ulong val) -{ - a[7] = val >> 56; - a[6] = val >> 48; - a[5] = val >> 40; - a[4] = val >> 32; - a[3] = val >> 24; - a[2] = val >> 16; - a[1] = val >> 8; - a[0] = val & 0xff; -} - - -/* function attribute macros */ - -#ifndef AES_WARN_UNUSED_RESULT -#if defined __GNUC__ -#define AES_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__)) -#else -#define AES_WARN_UNUSED_RESULT -#endif /* __GNUC__ */ -#endif /* AES_WARN_UNUSED_RESULT */ - -#endif /* AES_COMMON_H */ diff --git a/src/aes/aes-ctr.c b/src/aes/aes-ctr.c deleted file mode 100644 index 866ee34..0000000 --- a/src/aes/aes-ctr.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * AES-128 CTR - * - * Copyright (c) 2003-2007, Jouni Malinen - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#include -#include "aes.h" - -/** - * aes_128_ctr_encrypt - AES-128 CTR mode encryption - * @key: Key for encryption (16 bytes) - * @nonce: Nonce for counter mode (16 bytes) - * @data: Data to encrypt in-place - * @data_len: Length of data in bytes - * Returns: 0 on success, -1 on failure - */ -int aes_128_ctr_encrypt(const aes_uchar *key, const aes_uchar *nonce, - aes_uchar *data, size_t data_len) -{ - void *ctx; - size_t j, len, left = data_len; - int i; - aes_uchar *pos = data; - aes_uchar counter[AES_BLOCK_SIZE], buf[AES_BLOCK_SIZE]; - - ctx = aes_encrypt_init(key, 16); - if (ctx == NULL) - return -1; - memcpy(counter, nonce, AES_BLOCK_SIZE); - - while (left > 0) { - aes_encrypt(ctx, counter, buf); - - len = (left < AES_BLOCK_SIZE) ? left : AES_BLOCK_SIZE; - for (j = 0; j < len; j++) - pos[j] ^= buf[j]; - pos += len; - left -= len; - - for (i = AES_BLOCK_SIZE - 1; i >= 0; i--) { - counter[i]++; - if (counter[i]) - break; - } - } - aes_encrypt_deinit(ctx); - return 0; -} diff --git a/src/aes/aes-debug.h b/src/aes/aes-debug.h deleted file mode 100644 index 9fb2ecc..0000000 --- a/src/aes/aes-debug.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * aes-debug.h - * - * derived from wpa_supplicant - * Copyright (c) 2002-2013, Jouni Malinen - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#ifndef AES_DEBUG_H -#define AES_DEBUG_H - -/* gettimeofday */ - -#if defined(_MSC_VER) || ( defined(__WIN32__) && !defined(__CYGWIN__)) - -struct timezone -{ - int tz_minuteswest; /* minutes west of Greenwich */ - int tz_dsttime; /* type of dst correction */ -}; - -struct timeval { - int tv_sec; - int tv_usec; -}; - -extern int gettimeofday(struct timeval *tv, struct timezone *tz); - -#else -#include -#endif - -/* Debugging function - conditional printf and hex dump */ - -enum { - MSG_EXCESSIVE, MSG_MSGDUMP, MSG_DEBUG, MSG_INFO, MSG_WARNING, MSG_ERROR -}; - -extern int aes_debug_level; -extern int aes_debug_show_keys; -extern int aes_debug_timestamp; - -#ifndef AES_DEBUG - -#define aes_debug_print_timestamp() do { } while (0) -#define aes_printf(args...) do { } while (0) -#define aes_hexdump(l,t,b,le) do { } while (0) -#define aes_hexdump_buf(l,t,b) do { } while (0) -#define aes_hexdump_key(l,t,b,le) do { } while (0) -#define aes_hexdump_buf_key(l,t,b) do { } while (0) -#define aes_hexdump_ascii(l,t,b,le) do { } while (0) -#define aes_hexdump_ascii_key(l,t,b,le) do { } while (0) -#define aes_dbg(args...) do { } while (0) - -#else - -/** - * aes_debug_printf_timestamp - Print timestamp for debug output - * - * This function prints a timestamp in seconds_from_1970.microsoconds - * format if debug output has been configured to include timestamps in debug - * messages. - */ -void aes_debug_print_timestamp(void); - -/** - * aes_printf - conditional printf - * @level: priority level (MSG_*) of the message - * @fmt: printf format string, followed by optional arguments - * - * This function is used to print conditional debugging and error messages. The - * output may be directed to stdout, stderr, and/or syslog based on - * configuration. - * - * Note: New line '\n' is added to the end of the text when printing to stdout. - */ -void aes_printf(int level, const char *fmt, ...) __attribute__ ((format (printf, (2), (3)))); - -/** - * aes_hexdump - conditional hex dump - * @level: priority level (MSG_*) of the message - * @title: title of for the message - * @buf: data buffer to be dumped - * @len: length of the buf - * - * This function is used to print conditional debugging and error messages. The - * output may be directed to stdout, stderr, and/or syslog based on - * configuration. The contents of buf is printed out has hex dump. - */ -void aes_hexdump(int level, const char *title, const void *buf, size_t len); - -/** - * aes_hexdump_key - conditional hex dump, hide keys - * @level: priority level (MSG_*) of the message - * @title: title of for the message - * @buf: data buffer to be dumped - * @len: length of the buf - * - * This function is used to print conditional debugging and error messages. The - * output may be directed to stdout, stderr, and/or syslog based on - * configuration. The contents of buf is printed out has hex dump. This works - * like aes_hexdump(), but by default, does not include secret keys (passwords, - * etc.) in debug output. - */ -void aes_hexdump_key(int level, const char *title, const void *buf, size_t len); - -/** - * aes_hexdump_ascii - conditional hex dump - * @level: priority level (MSG_*) of the message - * @title: title of for the message - * @buf: data buffer to be dumped - * @len: length of the buf - * - * This function is used to print conditional debugging and error messages. The - * output may be directed to stdout, stderr, and/or syslog based on - * configuration. The contents of buf is printed out has hex dump with both - * the hex numbers and ASCII characters (for printable range) are shown. 16 - * bytes per line will be shown. - */ -void aes_hexdump_ascii(int level, const char *title, const void *buf, - size_t len); - -/** - * aes_hexdump_ascii_key - conditional hex dump, hide keys - * @level: priority level (MSG_*) of the message - * @title: title of for the message - * @buf: data buffer to be dumped - * @len: length of the buf - * - * This function is used to print conditional debugging and error messages. The - * output may be directed to stdout, stderr, and/or syslog based on - * configuration. The contents of buf is printed out has hex dump with both - * the hex numbers and ASCII characters (for printable range) are shown. 16 - * bytes per line will be shown. This works like aes_hexdump_ascii(), but by - * default, does not include secret keys (passwords, etc.) in debug output. - */ -void aes_hexdump_ascii_key(int level, const char *title, const void *buf, - size_t len); - -#endif /* AES_DEBUG_STDOUT */ - -#endif /* AES_DEBUG_H */ diff --git a/src/aes/aes-encblock.c b/src/aes/aes-encblock.c deleted file mode 100644 index 86f1ed9..0000000 --- a/src/aes/aes-encblock.c +++ /dev/null @@ -1,28 +0,0 @@ -/* - * AES encrypt_block - * - * Copyright (c) 2003-2007, Jouni Malinen - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#include "aes.h" - -/** - * aes_128_encrypt_block - Perform one AES 128-bit block operation - * @key: Key for AES - * @in: Input data (16 bytes) - * @out: Output of the AES block operation (16 bytes) - * Returns: 0 on success, -1 on failure - */ -int aes_128_encrypt_block(const aes_uchar *key, const aes_uchar *in, aes_uchar *out) -{ - void *ctx; - ctx = aes_encrypt_init(key, 16); - if (ctx == NULL) - return -1; - aes_encrypt(ctx, in, out); - aes_encrypt_deinit(ctx); - return 0; -} diff --git a/src/aes/aes-gcm.c b/src/aes/aes-gcm.c deleted file mode 100644 index 73f7b59..0000000 --- a/src/aes/aes-gcm.c +++ /dev/null @@ -1,322 +0,0 @@ -/* - * Galois/Counter Mode (GCM) and GMAC with AES - * - * Copyright (c) 2012, Jouni Malinen - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#include -#include "aes.h" - -static void inc32(aes_uchar *block) -{ - aes_uint val; - val = AES_GET_BE32(block + AES_BLOCK_SIZE - 4); - val++; - AES_PUT_BE32(block + AES_BLOCK_SIZE - 4, val); -} - - -static void xor_block(aes_uchar *dst, const aes_uchar *src) -{ - aes_uint *d = (aes_uint *) dst; - aes_uint *s = (aes_uint *) src; - *d++ ^= *s++; - *d++ ^= *s++; - *d++ ^= *s++; - *d++ ^= *s++; -} - - -static void shift_right_block(aes_uchar *v) -{ - aes_uint val; - - val = AES_GET_BE32(v + 12); - val >>= 1; - if (v[11] & 0x01) - val |= 0x80000000; - AES_PUT_BE32(v + 12, val); - - val = AES_GET_BE32(v + 8); - val >>= 1; - if (v[7] & 0x01) - val |= 0x80000000; - AES_PUT_BE32(v + 8, val); - - val = AES_GET_BE32(v + 4); - val >>= 1; - if (v[3] & 0x01) - val |= 0x80000000; - AES_PUT_BE32(v + 4, val); - - val = AES_GET_BE32(v); - val >>= 1; - AES_PUT_BE32(v, val); -} - - -/* Multiplication in GF(2^128) */ -static void gf_mult(const aes_uchar *x, const aes_uchar *y, aes_uchar *z) -{ - aes_uchar v[16]; - int i, j; - - memset(z, 0, 16); /* Z_0 = 0^128 */ - memcpy(v, y, 16); /* V_0 = Y */ - - for (i = 0; i < 16; i++) { - for (j = 0; j < 8; j++) { - if (x[i] & 1 << (7 - j)) { - /* Z_(i + 1) = Z_i XOR V_i */ - xor_block(z, v); - } else { - /* Z_(i + 1) = Z_i */ - } - - if (v[15] & 0x01) { - /* V_(i + 1) = (V_i >> 1) XOR R */ - shift_right_block(v); - /* R = 11100001 || 0^120 */ - v[0] ^= 0xe1; - } else { - /* V_(i + 1) = V_i >> 1 */ - shift_right_block(v); - } - } - } -} - - -static void ghash_start(aes_uchar *y) -{ - /* Y_0 = 0^128 */ - memset(y, 0, 16); -} - - -static void ghash(const aes_uchar *h, const aes_uchar *x, size_t xlen, aes_uchar *y) -{ - size_t m, i; - const aes_uchar *xpos = x; - aes_uchar tmp[16]; - - m = xlen / 16; - - for (i = 0; i < m; i++) { - /* Y_i = (Y^(i-1) XOR X_i) dot H */ - xor_block(y, xpos); - xpos += 16; - - /* dot operation: - * multiplication operation for binary Galois (finite) field of - * 2^128 elements */ - gf_mult(y, h, tmp); - memcpy(y, tmp, 16); - } - - if (x + xlen > xpos) { - /* Add zero padded last block */ - size_t last = x + xlen - xpos; - memcpy(tmp, xpos, last); - memset(tmp + last, 0, sizeof(tmp) - last); - - /* Y_i = (Y^(i-1) XOR X_i) dot H */ - xor_block(y, tmp); - - /* dot operation: - * multiplication operation for binary Galois (finite) field of - * 2^128 elements */ - gf_mult(y, h, tmp); - memcpy(y, tmp, 16); - } - - /* Return Y_m */ -} - - -static void aes_gctr(void *aes, const aes_uchar *icb, const aes_uchar *x, size_t xlen, aes_uchar *y) -{ - size_t i, n, last; - aes_uchar cb[AES_BLOCK_SIZE], tmp[AES_BLOCK_SIZE]; - const aes_uchar *xpos = x; - aes_uchar *ypos = y; - - if (xlen == 0) - return; - - n = xlen / 16; - - memcpy(cb, icb, AES_BLOCK_SIZE); - /* Full blocks */ - for (i = 0; i < n; i++) { - aes_encrypt(aes, cb, ypos); - xor_block(ypos, xpos); - xpos += AES_BLOCK_SIZE; - ypos += AES_BLOCK_SIZE; - inc32(cb); - } - - last = x + xlen - xpos; - if (last) { - /* Last, partial block */ - aes_encrypt(aes, cb, tmp); - for (i = 0; i < last; i++) - *ypos++ = *xpos++ ^ tmp[i]; - } -} - - -static void * aes_gcm_init_hash_subkey(const aes_uchar *key, size_t key_len, aes_uchar *H) -{ - void *aes; - - aes = aes_encrypt_init(key, key_len); - if (aes == NULL) - return NULL; - - /* Generate hash subkey H = AES_K(0^128) */ - memset(H, 0, AES_BLOCK_SIZE); - aes_encrypt(aes, H, H); - aes_hexdump_key(MSG_EXCESSIVE, "Hash subkey H for GHASH", H, AES_BLOCK_SIZE); - return aes; -} - - -static void aes_gcm_prepare_j0(const aes_uchar *iv, size_t iv_len, const aes_uchar *H, aes_uchar *J0) -{ - aes_uchar len_buf[16]; - - if (iv_len == 12) { - /* Prepare block J_0 = IV || 0^31 || 1 [len(IV) = 96] */ - memcpy(J0, iv, iv_len); - memset(J0 + iv_len, 0, AES_BLOCK_SIZE - iv_len); - J0[AES_BLOCK_SIZE - 1] = 0x01; - } else { - /* - * s = 128 * ceil(len(IV)/128) - len(IV) - * J_0 = GHASH_H(IV || 0^(s+64) || [len(IV)]_64) - */ - ghash_start(J0); - ghash(H, iv, iv_len, J0); - AES_PUT_BE64(len_buf, 0); - AES_PUT_BE64(len_buf + 8, iv_len * 8); - ghash(H, len_buf, sizeof(len_buf), J0); - } -} - - -static void aes_gcm_gctr(void *aes, const aes_uchar *J0, const aes_uchar *in, size_t len, - aes_uchar *out) -{ - aes_uchar J0inc[AES_BLOCK_SIZE]; - - if (len == 0) - return; - - memcpy(J0inc, J0, AES_BLOCK_SIZE); - inc32(J0inc); - aes_gctr(aes, J0inc, in, len, out); -} - - -static void aes_gcm_ghash(const aes_uchar *H, const aes_uchar *aad, size_t aad_len, - const aes_uchar *crypt, size_t crypt_len, aes_uchar *S) -{ - aes_uchar len_buf[16]; - - /* - * u = 128 * ceil[len(C)/128] - len(C) - * v = 128 * ceil[len(A)/128] - len(A) - * S = GHASH_H(A || 0^v || C || 0^u || [len(A)]64 || [len(C)]64) - * (i.e., zero padded to block size A || C and lengths of each in bits) - */ - ghash_start(S); - ghash(H, aad, aad_len, S); - ghash(H, crypt, crypt_len, S); - AES_PUT_BE64(len_buf, aad_len * 8); - AES_PUT_BE64(len_buf + 8, crypt_len * 8); - ghash(H, len_buf, sizeof(len_buf), S); - - aes_hexdump_key(MSG_EXCESSIVE, "S = GHASH_H(...)", S, 16); -} - - -/** - * aes_gcm_ae - GCM-AE_K(IV, P, A) - */ -int aes_gcm_ae(const aes_uchar *key, size_t key_len, const aes_uchar *iv, size_t iv_len, - const aes_uchar *plain, size_t plain_len, - const aes_uchar *aad, size_t aad_len, aes_uchar *crypt, aes_uchar *tag) -{ - aes_uchar H[AES_BLOCK_SIZE]; - aes_uchar J0[AES_BLOCK_SIZE]; - aes_uchar S[16]; - void *aes; - - aes = aes_gcm_init_hash_subkey(key, key_len, H); - if (aes == NULL) - return -1; - - aes_gcm_prepare_j0(iv, iv_len, H, J0); - - /* C = GCTR_K(inc_32(J_0), P) */ - aes_gcm_gctr(aes, J0, plain, plain_len, crypt); - - aes_gcm_ghash(H, aad, aad_len, crypt, plain_len, S); - - /* T = MSB_t(GCTR_K(J_0, S)) */ - aes_gctr(aes, J0, S, sizeof(S), tag); - - /* Return (C, T) */ - - aes_encrypt_deinit(aes); - - return 0; -} - - -/** - * aes_gcm_ad - GCM-AD_K(IV, C, A, T) - */ -int aes_gcm_ad(const aes_uchar *key, size_t key_len, const aes_uchar *iv, size_t iv_len, - const aes_uchar *crypt, size_t crypt_len, - const aes_uchar *aad, size_t aad_len, const aes_uchar *tag, aes_uchar *plain) -{ - aes_uchar H[AES_BLOCK_SIZE]; - aes_uchar J0[AES_BLOCK_SIZE]; - aes_uchar S[16], T[16]; - void *aes; - - aes = aes_gcm_init_hash_subkey(key, key_len, H); - if (aes == NULL) - return -1; - - aes_gcm_prepare_j0(iv, iv_len, H, J0); - - /* P = GCTR_K(inc_32(J_0), C) */ - aes_gcm_gctr(aes, J0, crypt, crypt_len, plain); - - aes_gcm_ghash(H, aad, aad_len, crypt, crypt_len, S); - - /* T' = MSB_t(GCTR_K(J_0, S)) */ - aes_gctr(aes, J0, S, sizeof(S), T); - - aes_encrypt_deinit(aes); - - if (memcmp(tag, T, 16) != 0) { - aes_printf(MSG_EXCESSIVE, "GCM: Tag mismatch"); - return -1; - } - - return 0; -} - - -int aes_gmac(const aes_uchar *key, size_t key_len, const aes_uchar *iv, size_t iv_len, - const aes_uchar *aad, size_t aad_len, aes_uchar *tag) -{ - return aes_gcm_ae(key, key_len, iv, iv_len, NULL, 0, aad, aad_len, NULL, tag); -} diff --git a/src/aes/aes-internal-dec.c b/src/aes/aes-internal-dec.c deleted file mode 100644 index 1d5af1e..0000000 --- a/src/aes/aes-internal-dec.c +++ /dev/null @@ -1,173 +0,0 @@ -/* - * AES (Rijndael) cipher - decrypt - * - * Modifications to public domain implementation: - * - cleanup - * - use C pre-processor to make it easier to change S table access - * - added option (AES_SMALL_TABLES) for reducing code size by about 8 kB at - * cost of reduced throughput (quite small difference on Pentium 4, - * 10-25% when using -O1 or -O2 optimization) - * - * Copyright (c) 2003-2012, Jouni Malinen - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#include -#include - -#include "aes.h" -#include "aes-internal.h" - -/** - * Expand the cipher key into the decryption key schedule. - * - * @return the number of rounds for the given cipher key size. - */ -int aes_rijndael_key_setup_dec(aes_uint rk[], const aes_uchar cipherKey[], size_t keyBits) -{ - int Nr, i, j; - aes_uint temp; - - /* expand the cipher key: */ - Nr = aes_rijndael_key_setup_enc(rk, cipherKey, keyBits); - if (Nr < 0) - return Nr; - /* invert the order of the round keys: */ - for (i = 0, j = 4*Nr; i < j; i += 4, j -= 4) { - temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp; - temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp; - temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp; - temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp; - } - /* apply the inverse MixColumn transform to all round keys but the - * first and the last: */ - for (i = 1; i < Nr; i++) { - rk += 4; - for (j = 0; j < 4; j++) { - rk[j] = TD0_(TE4((rk[j] >> 24) )) ^ - TD1_(TE4((rk[j] >> 16) & 0xff)) ^ - TD2_(TE4((rk[j] >> 8) & 0xff)) ^ - TD3_(TE4((rk[j] ) & 0xff)); - } - } - - return Nr; -} - -void aes_rijndael_decrypt(const aes_uint rk[], int Nr, const aes_uchar ct[16], aes_uchar pt[16]) -{ - aes_uint s0, s1, s2, s3, t0, t1, t2, t3; -#ifndef AES_FULL_UNROLL - int r; -#endif /* AES_FULL_UNROLL */ - - /* - * map byte array block to cipher state - * and add initial round key: - */ - s0 = GETU32(ct ) ^ rk[0]; - s1 = GETU32(ct + 4) ^ rk[1]; - s2 = GETU32(ct + 8) ^ rk[2]; - s3 = GETU32(ct + 12) ^ rk[3]; - -#define ROUND(i,d,s) \ -d##0 = TD0(s##0) ^ TD1(s##3) ^ TD2(s##2) ^ TD3(s##1) ^ rk[4 * i]; \ -d##1 = TD0(s##1) ^ TD1(s##0) ^ TD2(s##3) ^ TD3(s##2) ^ rk[4 * i + 1]; \ -d##2 = TD0(s##2) ^ TD1(s##1) ^ TD2(s##0) ^ TD3(s##3) ^ rk[4 * i + 2]; \ -d##3 = TD0(s##3) ^ TD1(s##2) ^ TD2(s##1) ^ TD3(s##0) ^ rk[4 * i + 3] - -#ifdef AES_FULL_UNROLL - - ROUND(1,t,s); - ROUND(2,s,t); - ROUND(3,t,s); - ROUND(4,s,t); - ROUND(5,t,s); - ROUND(6,s,t); - ROUND(7,t,s); - ROUND(8,s,t); - ROUND(9,t,s); - if (Nr > 10) { - ROUND(10,s,t); - ROUND(11,t,s); - if (Nr > 12) { - ROUND(12,s,t); - ROUND(13,t,s); - } - } - - rk += Nr << 2; - -#else - - /* Nr - 1 full rounds: */ - r = Nr >> 1; - for (;;) { - ROUND(1,t,s); - rk += 8; - if (--r == 0) - break; - ROUND(0,s,t); - } - -#endif /* AES_FULL_UNROLL */ - -#undef ROUND - - /* - * apply last round and - * map cipher state to byte array block: - */ - s0 = TD41(t0) ^ TD42(t3) ^ TD43(t2) ^ TD44(t1) ^ rk[0]; - PUTU32(pt , s0); - s1 = TD41(t1) ^ TD42(t0) ^ TD43(t3) ^ TD44(t2) ^ rk[1]; - PUTU32(pt + 4, s1); - s2 = TD41(t2) ^ TD42(t1) ^ TD43(t0) ^ TD44(t3) ^ rk[2]; - PUTU32(pt + 8, s2); - s3 = TD41(t3) ^ TD42(t2) ^ TD43(t1) ^ TD44(t0) ^ rk[3]; - PUTU32(pt + 12, s3); -} - - -/* AES decrypt interface - -Function bellow rewriten to aes_decrypt_init_fixed that takes an external buffer to hold the key - -void * aes_decrypt_init(const aes_uchar *key, size_t len) -{ - aes_uint rk[AES_PRIV_SIZE]; - int res; - - res = aes_rijndael_key_setup_dec(rk, key, len * 8); - if (res < 0) { - return NULL; - } - rk[AES_PRIV_NR_POS] = res; - return rk; -} -*/ - -bool aes_decrypt_init_fixed(const aes_uchar *key, size_t len, aes_uint * rk) -{ - int res = aes_rijndael_key_setup_dec(rk, key, len * 8); - - if (res < 0) - return false; - - rk[AES_PRIV_NR_POS] = res; - - return true; -} - -void aes_decrypt(void *ctx, const aes_uchar *crypt, aes_uchar *plain) -{ - aes_uint *rk = ctx; - aes_rijndael_decrypt(ctx, rk[AES_PRIV_NR_POS], crypt, plain); -} - -void aes_decrypt_deinit(void *ctx) -{ - memset(ctx, 0, AES_PRIV_SIZE); -} diff --git a/src/aes/aes-internal-enc.c b/src/aes/aes-internal-enc.c deleted file mode 100644 index 76a44b0..0000000 --- a/src/aes/aes-internal-enc.c +++ /dev/null @@ -1,214 +0,0 @@ -//needed - -/* - * AES (Rijndael) cipher - encrypt - * - * Modifications to public domain implementation: - * - cleanup - * - use C pre-processor to make it easier to change S table access - * - added option (AES_SMALL_TABLES) for reducing code size by about 8 kB at - * cost of reduced throughput (quite small difference on Pentium 4, - * 10-25% when using -O1 or -O2 optimization) - * - * Copyright (c) 2003-2012, Jouni Malinen - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#include -#include - -#include "aes.h" -#include "aes-internal.h" - -/** - * Expand the cipher key into the encryption key schedule. - * - * @return the number of rounds for the given cipher key size. - */ -int aes_rijndael_key_setup_enc(aes_uint rk[], const aes_uchar cipherKey[], size_t keyBits) -{ - int i; - aes_uint temp; - - rk[0] = GETU32(cipherKey ); - rk[1] = GETU32(cipherKey + 4); - rk[2] = GETU32(cipherKey + 8); - rk[3] = GETU32(cipherKey + 12); - - if (keyBits == 128) { - for (i = 0; i < 10; i++) { - temp = rk[3]; - rk[4] = rk[0] ^ TE421(temp) ^ TE432(temp) ^ - TE443(temp) ^ TE414(temp) ^ RCON(i); - rk[5] = rk[1] ^ rk[4]; - rk[6] = rk[2] ^ rk[5]; - rk[7] = rk[3] ^ rk[6]; - rk += 4; - } - return 10; - } - - rk[4] = GETU32(cipherKey + 16); - rk[5] = GETU32(cipherKey + 20); - - if (keyBits == 192) { - for (i = 0; i < 8; i++) { - temp = rk[5]; - rk[6] = rk[0] ^ TE421(temp) ^ TE432(temp) ^ - TE443(temp) ^ TE414(temp) ^ RCON(i); - rk[7] = rk[1] ^ rk[6]; - rk[8] = rk[2] ^ rk[7]; - rk[9] = rk[3] ^ rk[8]; - if (i == 7) - return 12; - rk[10] = rk[4] ^ rk[9]; - rk[11] = rk[5] ^ rk[10]; - rk += 6; - } - } - - rk[6] = GETU32(cipherKey + 24); - rk[7] = GETU32(cipherKey + 28); - - if (keyBits == 256) { - for (i = 0; i < 7; i++) { - temp = rk[7]; - rk[8] = rk[0] ^ TE421(temp) ^ TE432(temp) ^ - TE443(temp) ^ TE414(temp) ^ RCON(i); - rk[9] = rk[1] ^ rk[8]; - rk[10] = rk[2] ^ rk[9]; - rk[11] = rk[3] ^ rk[10]; - if (i == 6) - return 14; - temp = rk[11]; - rk[12] = rk[4] ^ TE411(temp) ^ TE422(temp) ^ - TE433(temp) ^ TE444(temp); - rk[13] = rk[5] ^ rk[12]; - rk[14] = rk[6] ^ rk[13]; - rk[15] = rk[7] ^ rk[14]; - rk += 8; - } - } - - return -1; -} - -void aes_rijndael_encrypt(const aes_uint rk[], int Nr, const aes_uchar pt[16], aes_uchar ct[16]) -{ - aes_uint s0, s1, s2, s3, t0, t1, t2, t3; -#ifndef AES_FULL_UNROLL - int r; -#endif /* AES_FULL_UNROLL */ - - /* - * map byte array block to cipher state - * and add initial round key: - */ - s0 = GETU32(pt ) ^ rk[0]; - s1 = GETU32(pt + 4) ^ rk[1]; - s2 = GETU32(pt + 8) ^ rk[2]; - s3 = GETU32(pt + 12) ^ rk[3]; - -#define ROUND(i,d,s) \ -d##0 = TE0(s##0) ^ TE1(s##1) ^ TE2(s##2) ^ TE3(s##3) ^ rk[4 * i]; \ -d##1 = TE0(s##1) ^ TE1(s##2) ^ TE2(s##3) ^ TE3(s##0) ^ rk[4 * i + 1]; \ -d##2 = TE0(s##2) ^ TE1(s##3) ^ TE2(s##0) ^ TE3(s##1) ^ rk[4 * i + 2]; \ -d##3 = TE0(s##3) ^ TE1(s##0) ^ TE2(s##1) ^ TE3(s##2) ^ rk[4 * i + 3] - -#ifdef AES_FULL_UNROLL - - ROUND(1,t,s); - ROUND(2,s,t); - ROUND(3,t,s); - ROUND(4,s,t); - ROUND(5,t,s); - ROUND(6,s,t); - ROUND(7,t,s); - ROUND(8,s,t); - ROUND(9,t,s); - if (Nr > 10) { - ROUND(10,s,t); - ROUND(11,t,s); - if (Nr > 12) { - ROUND(12,s,t); - ROUND(13,t,s); - } - } - - rk += Nr << 2; - -#else - - /* Nr - 1 full rounds: */ - r = Nr >> 1; - for (;;) { - ROUND(1,t,s); - rk += 8; - if (--r == 0) - break; - ROUND(0,s,t); - } - -#endif /* AES_FULL_UNROLL */ - -#undef ROUND - - /* - * apply last round and - * map cipher state to byte array block: - */ - s0 = TE41(t0) ^ TE42(t1) ^ TE43(t2) ^ TE44(t3) ^ rk[0]; - PUTU32(ct , s0); - s1 = TE41(t1) ^ TE42(t2) ^ TE43(t3) ^ TE44(t0) ^ rk[1]; - PUTU32(ct + 4, s1); - s2 = TE41(t2) ^ TE42(t3) ^ TE43(t0) ^ TE44(t1) ^ rk[2]; - PUTU32(ct + 8, s2); - s3 = TE41(t3) ^ TE42(t0) ^ TE43(t1) ^ TE44(t2) ^ rk[3]; - PUTU32(ct + 12, s3); -} - - -/* AES encrypt interface */ -/* rewritern to aes_encrypt_init_fixed that takes an external buffer -void * aes_encrypt_init(const aes_uchar *key, size_t len) -{ - aes_uint *rk[AES_PRIV_SIZE]; - int res; - res = aes_rijndael_key_setup_enc(rk, key, len * 8); - - if (res < 0) - return NULL; - - rk[AES_PRIV_NR_POS] = res; - return rk; -} - -*/ - -//returns true iff success -bool aes_encrypt_init_fixed(const aes_uchar *key, size_t len, aes_uint *rk) -{ - int res = aes_rijndael_key_setup_enc(rk, key, len * 8); - - if (res < 0) - return false; - - rk[AES_PRIV_NR_POS] = res; - return true; -} - - -void aes_encrypt(void *ctx, const aes_uchar *plain, aes_uchar *crypt) -{ - aes_uint *rk = ctx; - aes_rijndael_encrypt(ctx, rk[AES_PRIV_NR_POS], plain, crypt); -} - - -void aes_encrypt_deinit(void *ctx) -{ - memset(ctx, 0, AES_PRIV_SIZE); -} - diff --git a/src/aes/aes-internal.c b/src/aes/aes-internal.c deleted file mode 100644 index cf8dbc1..0000000 --- a/src/aes/aes-internal.c +++ /dev/null @@ -1,768 +0,0 @@ -/* - * AES (Rijndael) cipher - * - * Modifications to public domain implementation: - * - cleanup - * - use C pre-processor to make it easier to change S table access - * - added option (AES_SMALL_TABLES) for reducing code size by about 8 kB at - * cost of reduced throughput (quite small difference on Pentium 4, - * 10-25% when using -O1 or -O2 optimization) - * - * Copyright (c) 2003-2012, Jouni Malinen - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#include "aes.h" -#include "aes-internal.h" - -/* - * rijndael-alg-fst.c - * - * @version 3.0 (December 2000) - * - * Optimised ANSI C code for the Rijndael cipher (now AES) - * - * @author Vincent Rijmen - * @author Antoon Bosselaers - * @author Paulo Barreto - * - * This code is hereby placed in the public domain. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE - * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - - -/* -Te0[x] = S [x].[02, 01, 01, 03]; -Te1[x] = S [x].[03, 02, 01, 01]; -Te2[x] = S [x].[01, 03, 02, 01]; -Te3[x] = S [x].[01, 01, 03, 02]; -Te4[x] = S [x].[01, 01, 01, 01]; - -Td0[x] = Si[x].[0e, 09, 0d, 0b]; -Td1[x] = Si[x].[0b, 0e, 09, 0d]; -Td2[x] = Si[x].[0d, 0b, 0e, 09]; -Td3[x] = Si[x].[09, 0d, 0b, 0e]; -Td4[x] = Si[x].[01, 01, 01, 01]; -*/ - -const aes_uint Te0[256] = { - 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU, - 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U, - 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU, - 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU, - 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U, - 0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU, - 0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU, - 0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU, - 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU, - 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU, - 0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U, - 0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU, - 0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU, - 0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U, - 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU, - 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU, - 0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU, - 0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU, - 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU, - 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U, - 0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU, - 0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU, - 0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU, - 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU, - 0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U, - 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U, - 0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U, - 0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U, - 0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU, - 0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U, - 0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U, - 0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU, - 0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU, - 0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U, - 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U, - 0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U, - 0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU, - 0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U, - 0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU, - 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U, - 0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU, - 0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U, - 0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U, - 0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU, - 0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U, - 0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U, - 0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U, - 0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U, - 0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U, - 0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U, - 0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U, - 0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U, - 0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU, - 0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U, - 0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U, - 0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U, - 0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U, - 0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U, - 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U, - 0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU, - 0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U, - 0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U, - 0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U, - 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU, -}; -#ifndef AES_SMALL_TABLES -const aes_uint Te1[256] = { - 0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU, - 0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U, - 0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU, - 0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U, - 0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU, - 0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U, - 0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU, - 0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U, - 0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U, - 0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU, - 0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U, - 0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U, - 0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U, - 0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU, - 0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U, - 0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U, - 0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU, - 0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U, - 0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U, - 0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U, - 0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU, - 0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU, - 0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U, - 0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU, - 0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU, - 0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U, - 0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU, - 0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U, - 0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU, - 0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U, - 0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U, - 0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U, - 0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU, - 0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U, - 0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU, - 0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U, - 0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU, - 0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U, - 0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U, - 0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU, - 0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU, - 0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU, - 0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U, - 0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U, - 0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU, - 0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U, - 0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU, - 0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U, - 0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU, - 0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U, - 0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU, - 0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU, - 0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U, - 0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU, - 0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U, - 0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU, - 0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U, - 0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U, - 0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U, - 0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU, - 0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU, - 0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U, - 0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU, - 0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U, -}; -const aes_uint Te2[256] = { - 0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU, - 0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U, - 0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU, - 0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U, - 0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU, - 0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U, - 0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU, - 0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U, - 0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U, - 0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU, - 0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U, - 0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U, - 0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U, - 0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU, - 0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U, - 0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U, - 0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU, - 0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U, - 0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U, - 0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U, - 0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU, - 0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU, - 0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U, - 0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU, - 0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU, - 0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U, - 0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU, - 0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U, - 0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU, - 0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U, - 0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U, - 0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U, - 0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU, - 0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U, - 0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU, - 0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U, - 0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU, - 0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U, - 0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U, - 0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU, - 0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU, - 0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU, - 0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U, - 0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U, - 0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU, - 0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U, - 0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU, - 0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U, - 0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU, - 0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U, - 0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU, - 0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU, - 0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U, - 0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU, - 0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U, - 0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU, - 0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U, - 0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U, - 0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U, - 0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU, - 0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU, - 0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U, - 0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU, - 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U, -}; -const aes_uint Te3[256] = { - 0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U, - 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U, - 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U, - 0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU, - 0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU, - 0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU, - 0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U, - 0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU, - 0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU, - 0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U, - 0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U, - 0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU, - 0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU, - 0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU, - 0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU, - 0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU, - 0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U, - 0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU, - 0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU, - 0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U, - 0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U, - 0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U, - 0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U, - 0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U, - 0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU, - 0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U, - 0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU, - 0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU, - 0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U, - 0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U, - 0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U, - 0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU, - 0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U, - 0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU, - 0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU, - 0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U, - 0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U, - 0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU, - 0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U, - 0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU, - 0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U, - 0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U, - 0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U, - 0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U, - 0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU, - 0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U, - 0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU, - 0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U, - 0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU, - 0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U, - 0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU, - 0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU, - 0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU, - 0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU, - 0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U, - 0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U, - 0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U, - 0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U, - 0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U, - 0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U, - 0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU, - 0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U, - 0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU, - 0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU, -}; -const aes_uint Te4[256] = { - 0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU, - 0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U, - 0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU, - 0xfefefefeU, 0xd7d7d7d7U, 0xababababU, 0x76767676U, - 0xcacacacaU, 0x82828282U, 0xc9c9c9c9U, 0x7d7d7d7dU, - 0xfafafafaU, 0x59595959U, 0x47474747U, 0xf0f0f0f0U, - 0xadadadadU, 0xd4d4d4d4U, 0xa2a2a2a2U, 0xafafafafU, - 0x9c9c9c9cU, 0xa4a4a4a4U, 0x72727272U, 0xc0c0c0c0U, - 0xb7b7b7b7U, 0xfdfdfdfdU, 0x93939393U, 0x26262626U, - 0x36363636U, 0x3f3f3f3fU, 0xf7f7f7f7U, 0xccccccccU, - 0x34343434U, 0xa5a5a5a5U, 0xe5e5e5e5U, 0xf1f1f1f1U, - 0x71717171U, 0xd8d8d8d8U, 0x31313131U, 0x15151515U, - 0x04040404U, 0xc7c7c7c7U, 0x23232323U, 0xc3c3c3c3U, - 0x18181818U, 0x96969696U, 0x05050505U, 0x9a9a9a9aU, - 0x07070707U, 0x12121212U, 0x80808080U, 0xe2e2e2e2U, - 0xebebebebU, 0x27272727U, 0xb2b2b2b2U, 0x75757575U, - 0x09090909U, 0x83838383U, 0x2c2c2c2cU, 0x1a1a1a1aU, - 0x1b1b1b1bU, 0x6e6e6e6eU, 0x5a5a5a5aU, 0xa0a0a0a0U, - 0x52525252U, 0x3b3b3b3bU, 0xd6d6d6d6U, 0xb3b3b3b3U, - 0x29292929U, 0xe3e3e3e3U, 0x2f2f2f2fU, 0x84848484U, - 0x53535353U, 0xd1d1d1d1U, 0x00000000U, 0xededededU, - 0x20202020U, 0xfcfcfcfcU, 0xb1b1b1b1U, 0x5b5b5b5bU, - 0x6a6a6a6aU, 0xcbcbcbcbU, 0xbebebebeU, 0x39393939U, - 0x4a4a4a4aU, 0x4c4c4c4cU, 0x58585858U, 0xcfcfcfcfU, - 0xd0d0d0d0U, 0xefefefefU, 0xaaaaaaaaU, 0xfbfbfbfbU, - 0x43434343U, 0x4d4d4d4dU, 0x33333333U, 0x85858585U, - 0x45454545U, 0xf9f9f9f9U, 0x02020202U, 0x7f7f7f7fU, - 0x50505050U, 0x3c3c3c3cU, 0x9f9f9f9fU, 0xa8a8a8a8U, - 0x51515151U, 0xa3a3a3a3U, 0x40404040U, 0x8f8f8f8fU, - 0x92929292U, 0x9d9d9d9dU, 0x38383838U, 0xf5f5f5f5U, - 0xbcbcbcbcU, 0xb6b6b6b6U, 0xdadadadaU, 0x21212121U, - 0x10101010U, 0xffffffffU, 0xf3f3f3f3U, 0xd2d2d2d2U, - 0xcdcdcdcdU, 0x0c0c0c0cU, 0x13131313U, 0xececececU, - 0x5f5f5f5fU, 0x97979797U, 0x44444444U, 0x17171717U, - 0xc4c4c4c4U, 0xa7a7a7a7U, 0x7e7e7e7eU, 0x3d3d3d3dU, - 0x64646464U, 0x5d5d5d5dU, 0x19191919U, 0x73737373U, - 0x60606060U, 0x81818181U, 0x4f4f4f4fU, 0xdcdcdcdcU, - 0x22222222U, 0x2a2a2a2aU, 0x90909090U, 0x88888888U, - 0x46464646U, 0xeeeeeeeeU, 0xb8b8b8b8U, 0x14141414U, - 0xdedededeU, 0x5e5e5e5eU, 0x0b0b0b0bU, 0xdbdbdbdbU, - 0xe0e0e0e0U, 0x32323232U, 0x3a3a3a3aU, 0x0a0a0a0aU, - 0x49494949U, 0x06060606U, 0x24242424U, 0x5c5c5c5cU, - 0xc2c2c2c2U, 0xd3d3d3d3U, 0xacacacacU, 0x62626262U, - 0x91919191U, 0x95959595U, 0xe4e4e4e4U, 0x79797979U, - 0xe7e7e7e7U, 0xc8c8c8c8U, 0x37373737U, 0x6d6d6d6dU, - 0x8d8d8d8dU, 0xd5d5d5d5U, 0x4e4e4e4eU, 0xa9a9a9a9U, - 0x6c6c6c6cU, 0x56565656U, 0xf4f4f4f4U, 0xeaeaeaeaU, - 0x65656565U, 0x7a7a7a7aU, 0xaeaeaeaeU, 0x08080808U, - 0xbabababaU, 0x78787878U, 0x25252525U, 0x2e2e2e2eU, - 0x1c1c1c1cU, 0xa6a6a6a6U, 0xb4b4b4b4U, 0xc6c6c6c6U, - 0xe8e8e8e8U, 0xddddddddU, 0x74747474U, 0x1f1f1f1fU, - 0x4b4b4b4bU, 0xbdbdbdbdU, 0x8b8b8b8bU, 0x8a8a8a8aU, - 0x70707070U, 0x3e3e3e3eU, 0xb5b5b5b5U, 0x66666666U, - 0x48484848U, 0x03030303U, 0xf6f6f6f6U, 0x0e0e0e0eU, - 0x61616161U, 0x35353535U, 0x57575757U, 0xb9b9b9b9U, - 0x86868686U, 0xc1c1c1c1U, 0x1d1d1d1dU, 0x9e9e9e9eU, - 0xe1e1e1e1U, 0xf8f8f8f8U, 0x98989898U, 0x11111111U, - 0x69696969U, 0xd9d9d9d9U, 0x8e8e8e8eU, 0x94949494U, - 0x9b9b9b9bU, 0x1e1e1e1eU, 0x87878787U, 0xe9e9e9e9U, - 0xcecececeU, 0x55555555U, 0x28282828U, 0xdfdfdfdfU, - 0x8c8c8c8cU, 0xa1a1a1a1U, 0x89898989U, 0x0d0d0d0dU, - 0xbfbfbfbfU, 0xe6e6e6e6U, 0x42424242U, 0x68686868U, - 0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU, - 0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U, -}; -#endif /* AES_SMALL_TABLES */ -const aes_uint Td0[256] = { - 0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U, - 0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U, - 0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U, - 0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU, - 0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U, - 0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U, - 0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU, - 0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U, - 0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU, - 0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U, - 0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U, - 0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U, - 0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U, - 0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU, - 0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U, - 0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU, - 0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U, - 0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU, - 0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U, - 0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U, - 0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U, - 0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU, - 0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U, - 0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU, - 0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U, - 0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU, - 0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U, - 0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU, - 0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU, - 0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U, - 0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU, - 0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U, - 0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU, - 0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U, - 0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U, - 0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U, - 0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU, - 0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U, - 0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U, - 0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU, - 0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U, - 0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U, - 0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U, - 0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U, - 0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U, - 0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU, - 0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U, - 0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U, - 0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U, - 0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U, - 0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U, - 0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU, - 0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU, - 0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU, - 0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU, - 0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U, - 0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U, - 0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU, - 0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU, - 0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U, - 0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU, - 0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U, - 0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U, - 0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U, -}; -#ifndef AES_SMALL_TABLES -const aes_uint Td1[256] = { - 0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU, - 0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U, - 0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU, - 0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U, - 0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U, - 0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U, - 0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U, - 0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U, - 0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U, - 0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU, - 0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU, - 0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU, - 0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U, - 0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU, - 0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U, - 0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U, - 0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U, - 0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU, - 0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU, - 0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U, - 0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU, - 0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U, - 0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU, - 0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU, - 0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U, - 0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U, - 0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U, - 0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU, - 0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U, - 0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU, - 0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U, - 0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U, - 0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U, - 0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU, - 0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U, - 0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U, - 0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U, - 0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U, - 0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U, - 0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U, - 0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU, - 0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU, - 0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U, - 0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU, - 0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U, - 0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU, - 0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU, - 0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U, - 0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU, - 0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U, - 0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U, - 0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U, - 0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U, - 0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U, - 0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U, - 0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U, - 0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU, - 0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U, - 0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U, - 0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU, - 0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U, - 0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U, - 0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U, - 0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U, -}; -const aes_uint Td2[256] = { - 0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U, - 0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U, - 0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U, - 0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U, - 0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU, - 0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U, - 0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U, - 0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U, - 0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U, - 0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU, - 0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U, - 0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U, - 0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU, - 0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U, - 0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U, - 0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U, - 0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U, - 0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U, - 0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U, - 0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU, - 0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U, - 0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U, - 0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U, - 0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U, - 0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U, - 0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU, - 0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU, - 0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U, - 0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU, - 0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U, - 0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU, - 0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU, - 0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU, - 0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU, - 0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U, - 0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U, - 0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U, - 0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U, - 0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U, - 0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U, - 0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U, - 0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU, - 0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU, - 0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U, - 0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U, - 0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU, - 0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU, - 0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U, - 0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U, - 0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U, - 0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U, - 0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U, - 0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U, - 0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U, - 0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU, - 0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U, - 0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U, - 0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U, - 0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U, - 0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U, - 0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U, - 0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU, - 0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U, - 0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U, -}; -const aes_uint Td3[256] = { - 0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU, - 0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU, - 0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U, - 0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U, - 0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU, - 0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU, - 0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U, - 0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU, - 0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U, - 0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU, - 0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U, - 0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U, - 0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U, - 0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U, - 0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U, - 0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU, - 0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU, - 0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U, - 0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U, - 0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU, - 0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU, - 0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U, - 0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U, - 0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U, - 0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U, - 0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU, - 0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U, - 0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U, - 0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU, - 0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU, - 0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U, - 0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U, - 0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U, - 0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU, - 0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U, - 0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U, - 0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U, - 0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U, - 0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U, - 0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U, - 0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U, - 0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU, - 0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U, - 0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U, - 0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU, - 0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU, - 0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U, - 0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU, - 0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U, - 0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U, - 0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U, - 0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U, - 0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U, - 0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U, - 0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU, - 0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU, - 0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU, - 0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU, - 0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U, - 0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U, - 0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U, - 0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU, - 0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U, - 0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U, -}; -const aes_uint Td4[256] = { - 0x52525252U, 0x09090909U, 0x6a6a6a6aU, 0xd5d5d5d5U, - 0x30303030U, 0x36363636U, 0xa5a5a5a5U, 0x38383838U, - 0xbfbfbfbfU, 0x40404040U, 0xa3a3a3a3U, 0x9e9e9e9eU, - 0x81818181U, 0xf3f3f3f3U, 0xd7d7d7d7U, 0xfbfbfbfbU, - 0x7c7c7c7cU, 0xe3e3e3e3U, 0x39393939U, 0x82828282U, - 0x9b9b9b9bU, 0x2f2f2f2fU, 0xffffffffU, 0x87878787U, - 0x34343434U, 0x8e8e8e8eU, 0x43434343U, 0x44444444U, - 0xc4c4c4c4U, 0xdedededeU, 0xe9e9e9e9U, 0xcbcbcbcbU, - 0x54545454U, 0x7b7b7b7bU, 0x94949494U, 0x32323232U, - 0xa6a6a6a6U, 0xc2c2c2c2U, 0x23232323U, 0x3d3d3d3dU, - 0xeeeeeeeeU, 0x4c4c4c4cU, 0x95959595U, 0x0b0b0b0bU, - 0x42424242U, 0xfafafafaU, 0xc3c3c3c3U, 0x4e4e4e4eU, - 0x08080808U, 0x2e2e2e2eU, 0xa1a1a1a1U, 0x66666666U, - 0x28282828U, 0xd9d9d9d9U, 0x24242424U, 0xb2b2b2b2U, - 0x76767676U, 0x5b5b5b5bU, 0xa2a2a2a2U, 0x49494949U, - 0x6d6d6d6dU, 0x8b8b8b8bU, 0xd1d1d1d1U, 0x25252525U, - 0x72727272U, 0xf8f8f8f8U, 0xf6f6f6f6U, 0x64646464U, - 0x86868686U, 0x68686868U, 0x98989898U, 0x16161616U, - 0xd4d4d4d4U, 0xa4a4a4a4U, 0x5c5c5c5cU, 0xccccccccU, - 0x5d5d5d5dU, 0x65656565U, 0xb6b6b6b6U, 0x92929292U, - 0x6c6c6c6cU, 0x70707070U, 0x48484848U, 0x50505050U, - 0xfdfdfdfdU, 0xededededU, 0xb9b9b9b9U, 0xdadadadaU, - 0x5e5e5e5eU, 0x15151515U, 0x46464646U, 0x57575757U, - 0xa7a7a7a7U, 0x8d8d8d8dU, 0x9d9d9d9dU, 0x84848484U, - 0x90909090U, 0xd8d8d8d8U, 0xababababU, 0x00000000U, - 0x8c8c8c8cU, 0xbcbcbcbcU, 0xd3d3d3d3U, 0x0a0a0a0aU, - 0xf7f7f7f7U, 0xe4e4e4e4U, 0x58585858U, 0x05050505U, - 0xb8b8b8b8U, 0xb3b3b3b3U, 0x45454545U, 0x06060606U, - 0xd0d0d0d0U, 0x2c2c2c2cU, 0x1e1e1e1eU, 0x8f8f8f8fU, - 0xcacacacaU, 0x3f3f3f3fU, 0x0f0f0f0fU, 0x02020202U, - 0xc1c1c1c1U, 0xafafafafU, 0xbdbdbdbdU, 0x03030303U, - 0x01010101U, 0x13131313U, 0x8a8a8a8aU, 0x6b6b6b6bU, - 0x3a3a3a3aU, 0x91919191U, 0x11111111U, 0x41414141U, - 0x4f4f4f4fU, 0x67676767U, 0xdcdcdcdcU, 0xeaeaeaeaU, - 0x97979797U, 0xf2f2f2f2U, 0xcfcfcfcfU, 0xcecececeU, - 0xf0f0f0f0U, 0xb4b4b4b4U, 0xe6e6e6e6U, 0x73737373U, - 0x96969696U, 0xacacacacU, 0x74747474U, 0x22222222U, - 0xe7e7e7e7U, 0xadadadadU, 0x35353535U, 0x85858585U, - 0xe2e2e2e2U, 0xf9f9f9f9U, 0x37373737U, 0xe8e8e8e8U, - 0x1c1c1c1cU, 0x75757575U, 0xdfdfdfdfU, 0x6e6e6e6eU, - 0x47474747U, 0xf1f1f1f1U, 0x1a1a1a1aU, 0x71717171U, - 0x1d1d1d1dU, 0x29292929U, 0xc5c5c5c5U, 0x89898989U, - 0x6f6f6f6fU, 0xb7b7b7b7U, 0x62626262U, 0x0e0e0e0eU, - 0xaaaaaaaaU, 0x18181818U, 0xbebebebeU, 0x1b1b1b1bU, - 0xfcfcfcfcU, 0x56565656U, 0x3e3e3e3eU, 0x4b4b4b4bU, - 0xc6c6c6c6U, 0xd2d2d2d2U, 0x79797979U, 0x20202020U, - 0x9a9a9a9aU, 0xdbdbdbdbU, 0xc0c0c0c0U, 0xfefefefeU, - 0x78787878U, 0xcdcdcdcdU, 0x5a5a5a5aU, 0xf4f4f4f4U, - 0x1f1f1f1fU, 0xddddddddU, 0xa8a8a8a8U, 0x33333333U, - 0x88888888U, 0x07070707U, 0xc7c7c7c7U, 0x31313131U, - 0xb1b1b1b1U, 0x12121212U, 0x10101010U, 0x59595959U, - 0x27272727U, 0x80808080U, 0xececececU, 0x5f5f5f5fU, - 0x60606060U, 0x51515151U, 0x7f7f7f7fU, 0xa9a9a9a9U, - 0x19191919U, 0xb5b5b5b5U, 0x4a4a4a4aU, 0x0d0d0d0dU, - 0x2d2d2d2dU, 0xe5e5e5e5U, 0x7a7a7a7aU, 0x9f9f9f9fU, - 0x93939393U, 0xc9c9c9c9U, 0x9c9c9c9cU, 0xefefefefU, - 0xa0a0a0a0U, 0xe0e0e0e0U, 0x3b3b3b3bU, 0x4d4d4d4dU, - 0xaeaeaeaeU, 0x2a2a2a2aU, 0xf5f5f5f5U, 0xb0b0b0b0U, - 0xc8c8c8c8U, 0xebebebebU, 0xbbbbbbbbU, 0x3c3c3c3cU, - 0x83838383U, 0x53535353U, 0x99999999U, 0x61616161U, - 0x17171717U, 0x2b2b2b2bU, 0x04040404U, 0x7e7e7e7eU, - 0xbabababaU, 0x77777777U, 0xd6d6d6d6U, 0x26262626U, - 0xe1e1e1e1U, 0x69696969U, 0x14141414U, 0x63636363U, - 0x55555555U, 0x21212121U, 0x0c0c0c0cU, 0x7d7d7d7dU, -}; -const aes_uint rcon[] = { - 0x01000000, 0x02000000, 0x04000000, 0x08000000, - 0x10000000, 0x20000000, 0x40000000, 0x80000000, - 0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ -}; -#else /* AES_SMALL_TABLES */ -const aes_uchar Td4s[256] = { - 0x52U, 0x09U, 0x6aU, 0xd5U, 0x30U, 0x36U, 0xa5U, 0x38U, - 0xbfU, 0x40U, 0xa3U, 0x9eU, 0x81U, 0xf3U, 0xd7U, 0xfbU, - 0x7cU, 0xe3U, 0x39U, 0x82U, 0x9bU, 0x2fU, 0xffU, 0x87U, - 0x34U, 0x8eU, 0x43U, 0x44U, 0xc4U, 0xdeU, 0xe9U, 0xcbU, - 0x54U, 0x7bU, 0x94U, 0x32U, 0xa6U, 0xc2U, 0x23U, 0x3dU, - 0xeeU, 0x4cU, 0x95U, 0x0bU, 0x42U, 0xfaU, 0xc3U, 0x4eU, - 0x08U, 0x2eU, 0xa1U, 0x66U, 0x28U, 0xd9U, 0x24U, 0xb2U, - 0x76U, 0x5bU, 0xa2U, 0x49U, 0x6dU, 0x8bU, 0xd1U, 0x25U, - 0x72U, 0xf8U, 0xf6U, 0x64U, 0x86U, 0x68U, 0x98U, 0x16U, - 0xd4U, 0xa4U, 0x5cU, 0xccU, 0x5dU, 0x65U, 0xb6U, 0x92U, - 0x6cU, 0x70U, 0x48U, 0x50U, 0xfdU, 0xedU, 0xb9U, 0xdaU, - 0x5eU, 0x15U, 0x46U, 0x57U, 0xa7U, 0x8dU, 0x9dU, 0x84U, - 0x90U, 0xd8U, 0xabU, 0x00U, 0x8cU, 0xbcU, 0xd3U, 0x0aU, - 0xf7U, 0xe4U, 0x58U, 0x05U, 0xb8U, 0xb3U, 0x45U, 0x06U, - 0xd0U, 0x2cU, 0x1eU, 0x8fU, 0xcaU, 0x3fU, 0x0fU, 0x02U, - 0xc1U, 0xafU, 0xbdU, 0x03U, 0x01U, 0x13U, 0x8aU, 0x6bU, - 0x3aU, 0x91U, 0x11U, 0x41U, 0x4fU, 0x67U, 0xdcU, 0xeaU, - 0x97U, 0xf2U, 0xcfU, 0xceU, 0xf0U, 0xb4U, 0xe6U, 0x73U, - 0x96U, 0xacU, 0x74U, 0x22U, 0xe7U, 0xadU, 0x35U, 0x85U, - 0xe2U, 0xf9U, 0x37U, 0xe8U, 0x1cU, 0x75U, 0xdfU, 0x6eU, - 0x47U, 0xf1U, 0x1aU, 0x71U, 0x1dU, 0x29U, 0xc5U, 0x89U, - 0x6fU, 0xb7U, 0x62U, 0x0eU, 0xaaU, 0x18U, 0xbeU, 0x1bU, - 0xfcU, 0x56U, 0x3eU, 0x4bU, 0xc6U, 0xd2U, 0x79U, 0x20U, - 0x9aU, 0xdbU, 0xc0U, 0xfeU, 0x78U, 0xcdU, 0x5aU, 0xf4U, - 0x1fU, 0xddU, 0xa8U, 0x33U, 0x88U, 0x07U, 0xc7U, 0x31U, - 0xb1U, 0x12U, 0x10U, 0x59U, 0x27U, 0x80U, 0xecU, 0x5fU, - 0x60U, 0x51U, 0x7fU, 0xa9U, 0x19U, 0xb5U, 0x4aU, 0x0dU, - 0x2dU, 0xe5U, 0x7aU, 0x9fU, 0x93U, 0xc9U, 0x9cU, 0xefU, - 0xa0U, 0xe0U, 0x3bU, 0x4dU, 0xaeU, 0x2aU, 0xf5U, 0xb0U, - 0xc8U, 0xebU, 0xbbU, 0x3cU, 0x83U, 0x53U, 0x99U, 0x61U, - 0x17U, 0x2bU, 0x04U, 0x7eU, 0xbaU, 0x77U, 0xd6U, 0x26U, - 0xe1U, 0x69U, 0x14U, 0x63U, 0x55U, 0x21U, 0x0cU, 0x7dU, -}; -const aes_uchar rcons[] = { - 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36 - /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ -}; -#endif /* AES_SMALL_TABLES */ diff --git a/src/aes/aes-internal.h b/src/aes/aes-internal.h deleted file mode 100644 index fd1ccc6..0000000 --- a/src/aes/aes-internal.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - * AES (Rijndael) cipher - * Copyright (c) 2003-2012, Jouni Malinen - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#ifndef AES_INTERNAL_H -#define AES_INTERNAL_H - -extern const aes_uint Te0[256]; -extern const aes_uint Te1[256]; -extern const aes_uint Te2[256]; -extern const aes_uint Te3[256]; -extern const aes_uint Te4[256]; -extern const aes_uint Td0[256]; -extern const aes_uint Td1[256]; -extern const aes_uint Td2[256]; -extern const aes_uint Td3[256]; -extern const aes_uint Td4[256]; -extern const aes_uint rcon[10]; -extern const aes_uchar Td4s[256]; -extern const aes_uchar rcons[10]; - -#ifndef AES_SMALL_TABLES - -#define RCON(i) rcon[(i)] - -#define TE0(i) Te0[((i) >> 24) & 0xff] -#define TE1(i) Te1[((i) >> 16) & 0xff] -#define TE2(i) Te2[((i) >> 8) & 0xff] -#define TE3(i) Te3[(i) & 0xff] -#define TE41(i) (Te4[((i) >> 24) & 0xff] & 0xff000000) -#define TE42(i) (Te4[((i) >> 16) & 0xff] & 0x00ff0000) -#define TE43(i) (Te4[((i) >> 8) & 0xff] & 0x0000ff00) -#define TE44(i) (Te4[(i) & 0xff] & 0x000000ff) -#define TE421(i) (Te4[((i) >> 16) & 0xff] & 0xff000000) -#define TE432(i) (Te4[((i) >> 8) & 0xff] & 0x00ff0000) -#define TE443(i) (Te4[(i) & 0xff] & 0x0000ff00) -#define TE414(i) (Te4[((i) >> 24) & 0xff] & 0x000000ff) -#define TE411(i) (Te4[((i) >> 24) & 0xff] & 0xff000000) -#define TE422(i) (Te4[((i) >> 16) & 0xff] & 0x00ff0000) -#define TE433(i) (Te4[((i) >> 8) & 0xff] & 0x0000ff00) -#define TE444(i) (Te4[(i) & 0xff] & 0x000000ff) -#define TE4(i) (Te4[(i)] & 0x000000ff) - -#define TD0(i) Td0[((i) >> 24) & 0xff] -#define TD1(i) Td1[((i) >> 16) & 0xff] -#define TD2(i) Td2[((i) >> 8) & 0xff] -#define TD3(i) Td3[(i) & 0xff] -#define TD41(i) (Td4[((i) >> 24) & 0xff] & 0xff000000) -#define TD42(i) (Td4[((i) >> 16) & 0xff] & 0x00ff0000) -#define TD43(i) (Td4[((i) >> 8) & 0xff] & 0x0000ff00) -#define TD44(i) (Td4[(i) & 0xff] & 0x000000ff) -#define TD0_(i) Td0[(i) & 0xff] -#define TD1_(i) Td1[(i) & 0xff] -#define TD2_(i) Td2[(i) & 0xff] -#define TD3_(i) Td3[(i) & 0xff] - -#else /* AES_SMALL_TABLES */ - -#define RCON(i) (rcons[(i)] << 24) - -static inline aes_uint rotr(aes_uint val, int bits) -{ - return (val >> bits) | (val << (32 - bits)); -} - -#define TE0(i) Te0[((i) >> 24) & 0xff] -#define TE1(i) rotr(Te0[((i) >> 16) & 0xff], 8) -#define TE2(i) rotr(Te0[((i) >> 8) & 0xff], 16) -#define TE3(i) rotr(Te0[(i) & 0xff], 24) -#define TE41(i) ((Te0[((i) >> 24) & 0xff] << 8) & 0xff000000) -#define TE42(i) (Te0[((i) >> 16) & 0xff] & 0x00ff0000) -#define TE43(i) (Te0[((i) >> 8) & 0xff] & 0x0000ff00) -#define TE44(i) ((Te0[(i) & 0xff] >> 8) & 0x000000ff) -#define TE421(i) ((Te0[((i) >> 16) & 0xff] << 8) & 0xff000000) -#define TE432(i) (Te0[((i) >> 8) & 0xff] & 0x00ff0000) -#define TE443(i) (Te0[(i) & 0xff] & 0x0000ff00) -#define TE414(i) ((Te0[((i) >> 24) & 0xff] >> 8) & 0x000000ff) -#define TE411(i) ((Te0[((i) >> 24) & 0xff] << 8) & 0xff000000) -#define TE422(i) (Te0[((i) >> 16) & 0xff] & 0x00ff0000) -#define TE433(i) (Te0[((i) >> 8) & 0xff] & 0x0000ff00) -#define TE444(i) ((Te0[(i) & 0xff] >> 8) & 0x000000ff) -#define TE4(i) ((Te0[(i)] >> 8) & 0x000000ff) - -#define TD0(i) Td0[((i) >> 24) & 0xff] -#define TD1(i) rotr(Td0[((i) >> 16) & 0xff], 8) -#define TD2(i) rotr(Td0[((i) >> 8) & 0xff], 16) -#define TD3(i) rotr(Td0[(i) & 0xff], 24) -#define TD41(i) (Td4s[((i) >> 24) & 0xff] << 24) -#define TD42(i) (Td4s[((i) >> 16) & 0xff] << 16) -#define TD43(i) (Td4s[((i) >> 8) & 0xff] << 8) -#define TD44(i) (Td4s[(i) & 0xff]) -#define TD0_(i) Td0[(i) & 0xff] -#define TD1_(i) rotr(Td0[(i) & 0xff], 8) -#define TD2_(i) rotr(Td0[(i) & 0xff], 16) -#define TD3_(i) rotr(Td0[(i) & 0xff], 24) - -#endif /* AES_SMALL_TABLES */ - -#define GETU32(pt) (((aes_uint)(pt)[0] << 24) ^ \ - ((aes_uint)(pt)[1] << 16) ^ \ - ((aes_uint)(pt)[2] << 8) ^ \ - ((aes_uint)(pt)[3])) -#define PUTU32(ct, st) { \ - (ct)[0] = (aes_uchar)((st) >> 24); \ - (ct)[1] = (aes_uchar)((st) >> 16); \ - (ct)[2] = (aes_uchar)((st) >> 8); \ - (ct)[3] = (aes_uchar)(st); } - -#define AES_PRIV_SIZE (4 * 4 * 15 + 4) -#define AES_PRIV_NR_POS (4 * 15) - -void aes_rijndael_encrypt(const aes_uint rk[], int Nr, const aes_uchar pt[16], aes_uchar ct[16]); -void aes_rijndael_decrypt(const aes_uint rk[], int Nr, const aes_uchar ct[16], aes_uchar pt[16]); -int aes_rijndael_key_setup_dec(aes_uint rk[], const aes_uchar cipherKey[], size_t keyBits); -int aes_rijndael_key_setup_enc(aes_uint rk[], const aes_uchar cipherKey[], size_t keyBits); - -#endif /* AES_I_H */ diff --git a/src/aes/aes-omac1.c b/src/aes/aes-omac1.c deleted file mode 100644 index 443ebfa..0000000 --- a/src/aes/aes-omac1.c +++ /dev/null @@ -1,114 +0,0 @@ -/* - * One-key CBC MAC (OMAC1) hash with AES-128 - * - * Copyright (c) 2003-2007, Jouni Malinen - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#include "aes.h" - -static void gf_mulx(aes_uchar *pad) -{ - int i, carry; - - carry = pad[0] & 0x80; - for (i = 0; i < AES_BLOCK_SIZE - 1; i++) - pad[i] = (pad[i] << 1) | (pad[i + 1] >> 7); - pad[AES_BLOCK_SIZE - 1] <<= 1; - if (carry) - pad[AES_BLOCK_SIZE - 1] ^= 0x87; -} - - -/** - * omac1_aes_128_vector - One-Key CBC MAC (OMAC1) hash with AES-128 - * @key: 128-bit key for the hash operation - * @num_elem: Number of elements in the data vector - * @addr: Pointers to the data areas - * @len: Lengths of the data blocks - * @mac: Buffer for MAC (128 bits, i.e., 16 bytes) - * Returns: 0 on success, -1 on failure - * - * This is a mode for using block cipher (AES in this case) for authentication. - * OMAC1 was standardized with the name CMAC by NIST in a Special Publication - * (SP) 800-38B. - */ -int omac1_aes_128_vector(const aes_uchar *key, size_t num_elem, - const aes_uchar *addr[], const size_t *len, aes_uchar *mac) -{ - void *ctx; - aes_uchar cbc[AES_BLOCK_SIZE], pad[AES_BLOCK_SIZE]; - const aes_uchar *pos, *end; - size_t i, e, left, total_len; - - ctx = aes_encrypt_init(key, 16); - if (ctx == NULL) - return -1; - memset(cbc, 0, AES_BLOCK_SIZE); - - total_len = 0; - for (e = 0; e < num_elem; e++) - total_len += len[e]; - left = total_len; - - e = 0; - pos = addr[0]; - end = pos + len[0]; - - while (left >= AES_BLOCK_SIZE) { - for (i = 0; i < AES_BLOCK_SIZE; i++) { - cbc[i] ^= *pos++; - if (pos >= end) { - e++; - pos = addr[e]; - end = pos + len[e]; - } - } - if (left > AES_BLOCK_SIZE) - aes_encrypt(ctx, cbc, cbc); - left -= AES_BLOCK_SIZE; - } - - memset(pad, 0, AES_BLOCK_SIZE); - aes_encrypt(ctx, pad, pad); - gf_mulx(pad); - - if (left || total_len == 0) { - for (i = 0; i < left; i++) { - cbc[i] ^= *pos++; - if (pos >= end) { - e++; - pos = addr[e]; - end = pos + len[e]; - } - } - cbc[left] ^= 0x80; - gf_mulx(pad); - } - - for (i = 0; i < AES_BLOCK_SIZE; i++) - pad[i] ^= cbc[i]; - aes_encrypt(ctx, pad, mac); - aes_encrypt_deinit(ctx); - return 0; -} - - -/** - * omac1_aes_128 - One-Key CBC MAC (OMAC1) hash with AES-128 (aka AES-CMAC) - * @key: 128-bit key for the hash operation - * @data: Data buffer for which a MAC is determined - * @data_len: Length of data buffer in bytes - * @mac: Buffer for MAC (128 bits, i.e., 16 bytes) - * Returns: 0 on success, -1 on failure - * - * This is a mode for using block cipher (AES in this case) for authentication. - * OMAC1 was standardized with the name CMAC by NIST in a Special Publication - * (SP) 800-38B. - */ -int omac1_aes_128(const aes_uchar *key, const aes_uchar *data, size_t data_len, aes_uchar *mac) -{ - return omac1_aes_128_vector(key, 1, &data, &data_len, mac); -} diff --git a/src/aes/aes-unwrap.c b/src/aes/aes-unwrap.c deleted file mode 100644 index 3f0dc3d..0000000 --- a/src/aes/aes-unwrap.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * AES key unwrap (128-bit KEK, RFC3394) - * - * Copyright (c) 2003-2007, Jouni Malinen - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#include -#include "aes.h" - -/** - * aes_unwrap - Unwrap key with AES Key Wrap Algorithm (128-bit KEK) (RFC3394) - * @kek: Key encryption key (KEK) - * @n: Length of the plaintext key in 64-bit units; e.g., 2 = 128-bit = 16 - * bytes - * @cipher: Wrapped key to be unwrapped, (n + 1) * 64 bits - * @plain: Plaintext key, n * 64 bits - * Returns: 0 on success, -1 on failure (e.g., integrity verification failed) - */ -int aes_unwrap(const aes_uchar *kek, int n, const aes_uchar *cipher, aes_uchar *plain) -{ - aes_uchar a[8], *r, b[16]; - int i, j; - void *ctx; - - /* 1) Initialize variables. */ - memcpy(a, cipher, 8); - r = plain; - memcpy(r, cipher + 8, 8 * n); - - ctx = aes_decrypt_init(kek, 16); - if (ctx == NULL) - return -1; - - /* 2) Compute intermediate values. - * For j = 5 to 0 - * For i = n to 1 - * B = AES-1(K, (A ^ t) | R[i]) where t = n*j+i - * A = MSB(64, B) - * R[i] = LSB(64, B) - */ - for (j = 5; j >= 0; j--) { - r = plain + (n - 1) * 8; - for (i = n; i >= 1; i--) { - memcpy(b, a, 8); - b[7] ^= n * j + i; - - memcpy(b + 8, r, 8); - aes_decrypt(ctx, b, b); - memcpy(a, b, 8); - memcpy(r, b + 8, 8); - r -= 8; - } - } - aes_decrypt_deinit(ctx); - - /* 3) Output results. - * - * These are already in @plain due to the location of temporary - * variables. Just verify that the IV matches with the expected value. - */ - for (i = 0; i < 8; i++) { - if (a[i] != 0xa6) - return -1; - } - - return 0; -} diff --git a/src/aes/aes-wrap.c b/src/aes/aes-wrap.c deleted file mode 100644 index 4c5a98e..0000000 --- a/src/aes/aes-wrap.c +++ /dev/null @@ -1,67 +0,0 @@ -/* - * AES Key Wrap Algorithm (128-bit KEK) (RFC3394) - * - * Copyright (c) 2003-2007, Jouni Malinen - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#include -#include "aes.h" - -/** - * aes_wrap - Wrap keys with AES Key Wrap Algorithm (128-bit KEK) (RFC3394) - * @kek: 16-octet Key encryption key (KEK) - * @n: Length of the plaintext key in 64-bit units; e.g., 2 = 128-bit = 16 - * bytes - * @plain: Plaintext key to be wrapped, n * 64 bits - * @cipher: Wrapped key, (n + 1) * 64 bits - * Returns: 0 on success, -1 on failure - */ -int aes_wrap(const aes_uchar *kek, int n, const aes_uchar *plain, aes_uchar *cipher) -{ - aes_uchar *a, *r, b[16]; - int i, j; - void *ctx; - - a = cipher; - r = cipher + 8; - - /* 1) Initialize variables. */ - memset(a, 0xa6, 8); - memcpy(r, plain, 8 * n); - - ctx = aes_encrypt_init(kek, 16); - if (ctx == NULL) - return -1; - - /* 2) Calculate intermediate values. - * For j = 0 to 5 - * For i=1 to n - * B = AES(K, A | R[i]) - * A = MSB(64, B) ^ t where t = (n*j)+i - * R[i] = LSB(64, B) - */ - for (j = 0; j <= 5; j++) { - r = cipher + 8; - for (i = 1; i <= n; i++) { - memcpy(b, a, 8); - memcpy(b + 8, r, 8); - aes_encrypt(ctx, b, b); - memcpy(a, b, 8); - a[7] ^= n * j + i; - memcpy(r, b + 8, 8); - r += 8; - } - } - aes_encrypt_deinit(ctx); - - /* 3) Output the results. - * - * These are already in @cipher due to the location of temporary - * variables. - */ - - return 0; -} diff --git a/src/aes/aes.h b/src/aes/aes.h deleted file mode 100644 index fa8a541..0000000 --- a/src/aes/aes.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * AES functions - * Copyright (c) 2003-2006, Jouni Malinen - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#ifndef AES_H -#define AES_H - -#ifdef __cplusplus -extern "C" { -#endif - -#define AES_FULL_UNROLL -#define AES_SMALL_TABLES -#define AES_BLOCK_SIZE 16 - -#include "aes-common.h" -#include "aes-internal.h" -#include "aes-debug.h" - -void * aes_encrypt_init(const aes_uchar *key, size_t len); -void aes_encrypt(void *ctx, const aes_uchar *plain, aes_uchar *crypt); -void aes_encrypt_deinit(void *ctx); -void * aes_decrypt_init(const aes_uchar *key, size_t len); -void aes_decrypt(void *ctx, const aes_uchar *crypt, aes_uchar *plain); -void aes_decrypt_deinit(void *ctx); - -int AES_WARN_UNUSED_RESULT aes_wrap(const aes_uchar *kek, int n, const aes_uchar *plain, aes_uchar *cipher); -int AES_WARN_UNUSED_RESULT aes_unwrap(const aes_uchar *kek, int n, const aes_uchar *cipher, aes_uchar *plain); -int AES_WARN_UNUSED_RESULT omac1_aes_128_vector(const aes_uchar *key, size_t num_elem, - const aes_uchar *addr[], const size_t *len, - aes_uchar *mac); -int AES_WARN_UNUSED_RESULT omac1_aes_128(const aes_uchar *key, const aes_uchar *data, size_t data_len, - aes_uchar *mac); -int AES_WARN_UNUSED_RESULT aes_128_encrypt_block(const aes_uchar *key, const aes_uchar *in, aes_uchar *out); -int AES_WARN_UNUSED_RESULT aes_128_ctr_encrypt(const aes_uchar *key, const aes_uchar *nonce, - aes_uchar *data, size_t data_len); -int AES_WARN_UNUSED_RESULT aes_128_eax_encrypt(const aes_uchar *key, - const aes_uchar *nonce, size_t nonce_len, - const aes_uchar *hdr, size_t hdr_len, - aes_uchar *data, size_t data_len, aes_uchar *tag); -int AES_WARN_UNUSED_RESULT aes_128_eax_decrypt(const aes_uchar *key, - const aes_uchar *nonce, size_t nonce_len, - const aes_uchar *hdr, size_t hdr_len, - aes_uchar *data, size_t data_len, const aes_uchar *tag); -int AES_WARN_UNUSED_RESULT aes_128_cbc_encrypt(const aes_uchar *key, const aes_uchar *iv, aes_uchar *data, - size_t data_len); -int AES_WARN_UNUSED_RESULT aes_128_cbc_decrypt(const aes_uchar *key, const aes_uchar *iv, aes_uchar *data, - size_t data_len); -int AES_WARN_UNUSED_RESULT aes_gcm_ae(const aes_uchar *key, size_t key_len, - const aes_uchar *iv, size_t iv_len, - const aes_uchar *plain, size_t plain_len, - const aes_uchar *aad, size_t aad_len, - aes_uchar *crypt, aes_uchar *tag); -int AES_WARN_UNUSED_RESULT aes_gcm_ad(const aes_uchar *key, size_t key_len, - const aes_uchar *iv, size_t iv_len, - const aes_uchar *crypt, size_t crypt_len, - const aes_uchar *aad, size_t aad_len, const aes_uchar *tag, - aes_uchar *plain); -int AES_WARN_UNUSED_RESULT aes_gmac(const aes_uchar *key, size_t key_len, - const aes_uchar *iv, size_t iv_len, - const aes_uchar *aad, size_t aad_len, aes_uchar *tag); -int AES_WARN_UNUSED_RESULT aes_ccm_ae(const aes_uchar *key, size_t key_len, const aes_uchar *nonce, - size_t M, const aes_uchar *plain, size_t plain_len, - const aes_uchar *aad, size_t aad_len, aes_uchar *crypt, aes_uchar *auth); -int AES_WARN_UNUSED_RESULT aes_ccm_ad(const aes_uchar *key, size_t key_len, const aes_uchar *nonce, - size_t M, const aes_uchar *crypt, size_t crypt_len, - const aes_uchar *aad, size_t aad_len, const aes_uchar *auth, - aes_uchar *plain); - -#ifdef __cplusplus -} -#endif - -#endif /* AES_H */ diff --git a/src/app_main.c b/src/app_main.c new file mode 100644 index 0000000..1731ef6 --- /dev/null +++ b/src/app_main.c @@ -0,0 +1,178 @@ +/******************************************************************************* + * + * (c) 2016 Ledger + * (c) 2018 Nebulous + * (c) 2019 Haim Bender + * (c) 2021-2023 Jelurida IP B.V. + * + * + * 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 + +#include "parser.h" // command_t, apdu_parser +#include "io.h" // io_init, io_recv_command + +#include "config.h" +#include "ardor.h" +#include "returnValues.h" +#include "ui/menu.h" +#include "io_helper.h" + +// The APDU protocol uses a single-byte instruction code (INS) to specify +// which command should be executed. We'll use this code to dispatch on a +// table of function pointers. +#define INS_GET_VERSION 0x01 +#define INS_AUTH_SIGN_TXN 0x03 +#define INS_ENCRYPT_DECRYPT_MSG 0x04 +#define INS_SHOW_ADDRESS 0x05 +#define INS_GET_PUBLIC_KEY_AND_CHAIN_CODE 0x06 +#define INS_SIGN_TOKEN 0x07 + +// This is the function signature for a command handler +typedef int handler_fn_t(const command_t* const cmd); + +handler_fn_t getVersionHandler; +handler_fn_t authAndSignTxnHandler; +handler_fn_t encryptDecryptMessageHandler; +handler_fn_t showAddressHandler; +handler_fn_t getPublicKeyAndChainCodeHandler; +handler_fn_t signTokenMessageHandler; + +// function translate command ID to function PTR +static handler_fn_t* lookupHandler(uint8_t ins) { + switch (ins) { + case INS_GET_VERSION: + return getVersionHandler; + case INS_AUTH_SIGN_TXN: + return authAndSignTxnHandler; + case INS_ENCRYPT_DECRYPT_MSG: + return encryptDecryptMessageHandler; + case INS_SHOW_ADDRESS: + return showAddressHandler; + case INS_GET_PUBLIC_KEY_AND_CHAIN_CODE: + return getPublicKeyAndChainCodeHandler; + case INS_SIGN_TOKEN: + return signTokenMessageHandler; + default: + return NULL; + } +} + +static void nv_storage_init() { + if (N_storage.initialized != true) { + internalStorage_t storage; + storage.settings.allowBlindSigning = false; + storage.initialized = true; + nvm_write((void*) &N_storage, (void*) &storage, sizeof(internalStorage_t)); + } +} + +// This is the main loop that reads and writes APDUs. It receives request +// APDUs from the computer, looks up the corresponding command handler, and +// calls it on the APDU payload. +void app_main(void) { + PRINTF("app_main, sizeof(state) = %d\n", sizeof(state)); + + // Length of APDU command received in G_io_apdu_buffer + volatile int input_len = 0; + + // Structured APDU command + command_t cmd; + + io_init(); + nv_storage_init(); + ui_menu_main(); + + // this is used to clean state if we change command types + volatile uint8_t lastCmdNumber = 0; + + for (;;) { + BEGIN_TRY { + TRY { + // Reset structured APDU command + explicit_bzero(&cmd, sizeof(cmd)); + + // Receive command bytes in G_io_apdu_buffer + input_len = io_recv_command(); + if (input_len < 0) { + CLOSE_TRY; + return; + } + + // Parse APDU command from G_io_apdu_buffer + if (!apdu_parser(&cmd, G_io_apdu_buffer, input_len)) { + PRINTF("=> /!\\ BAD LENGTH: %.*H\n", input_len, G_io_apdu_buffer); + io_send_return1(R_WRONG_DATA_LENGTH); + CLOSE_TRY; + continue; + } + + PRINTF("=> CLA=%02X | INS=%02X | P1=%02X | P2=%02X | Lc=%02X | CData=%.*H\n", + cmd.cla, + cmd.ins, + cmd.p1, + cmd.p2, + cmd.lc, + cmd.lc, + cmd.data); + + // Malformed APDU. + if (cmd.cla != CLA) { + lastCmdNumber = 0; // forces the next handler call to clean the state + io_send_return1(R_BAD_CLA); + CLOSE_TRY; + continue; + } + + // Lookup and call the requested command handler. + handler_fn_t* handlerFn = lookupHandler(cmd.ins); + if (!handlerFn) { + lastCmdNumber = 0; // forces the next handler call to clean the state + io_send_return1(R_UNKOWN_CMD); + CLOSE_TRY; + continue; + } + + PRINTF("canary check %d last command number %d\n", check_canary(), lastCmdNumber); + + if (lastCmdNumber != cmd.ins) { + // last command was different, clean state + cleanState(); + } + + if (handlerFn(&cmd) < 0) { + lastCmdNumber = 0; // forces the next handler call to clean the state + CLOSE_TRY; + continue; + } + + lastCmdNumber = cmd.ins; + } + CATCH(EXCEPTION_IO_RESET) { + THROW(EXCEPTION_IO_RESET); // lastCmdNumber will be zero'd when app_main will be + // called again + } + CATCH_OTHER(e) { + lastCmdNumber = 0; + io_send_return3(R_EXCEPTION, e >> 8, e & 0xFF); + } + FINALLY { + // intentionally blank + } + } + END_TRY; + } +} diff --git a/src/ardor.c b/src/ardor.c index b66d416..c36a1ad 100644 --- a/src/ardor.c +++ b/src/ardor.c @@ -1,26 +1,27 @@ /******************************************************************************* -* (c) 2019 Haim Bender -* -* -* 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 Haim Bender + * (c) 2021-2023 Jelurida IP B.V. + * + * + * 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 +#include #include #include -#include #include "curve25519_i64.h" #include "returnValues.h" @@ -28,206 +29,397 @@ #include "ardor.h" - - - -//the global state +// the global state states_t state; +// persistent storage: app settings +const internalStorage_t N_storage_real; + +void cleanState() { + explicit_bzero(&state, sizeof(state)); +} -//self explanatory -//output must point to buffer of 32 bytes in size -void sha256TwoBuffers(const uint8_t * const bufferTohash1, const uint16_t sizeOfBuffer1, const uint8_t * const bufferTohash2, const uint16_t sizeOfBuffer2, uint8_t * const output) { +// SHA-256 of two buffers, the output is the hash of the concatenation of the two buffers +//@param[in] bufferTohash1 - first buffer to hash +//@param[in] sizeOfBuffer1 - size of first buffer to hash +//@param[in] bufferTohash2 - second buffer to hash +//@param[in] sizeOfBuffer2 - size of second buffer to hash +//@param[out] output - 32 byte buffer to hold the hash +// return crypto library error code (CX_OK if success) +static cx_err_t sha256TwoBuffers(const uint8_t *const bufferTohash1, + const uint16_t sizeOfBuffer1, + const uint8_t *const bufferTohash2, + const uint16_t sizeOfBuffer2, + uint8_t *const output) { cx_sha256_t shaContext; - memset(output, 0, 32); - cx_sha256_init(&shaContext); //return value has no info + explicit_bzero(output, 32); + cx_err_t rc = cx_sha256_init_no_throw(&shaContext); // return value has no info + if (rc != CX_OK) { + return rc; + } - cx_hash(&shaContext.header, 0, bufferTohash1, sizeOfBuffer1, output, 32); + rc = cx_hash_no_throw(&shaContext.header, 0, bufferTohash1, sizeOfBuffer1, output, 32); + if (rc != CX_OK) { + return rc; + } - if (0 != bufferTohash2) - cx_hash(&shaContext.header, 0, bufferTohash2, sizeOfBuffer2, output, 32); - - cx_hash(&shaContext.header, CX_LAST, 0, 0, output, 32); -} + if (bufferTohash2 != 0) { + rc = cx_hash_no_throw(&shaContext.header, 0, bufferTohash2, sizeOfBuffer2, output, 32); + if (rc != CX_OK) { + return rc; + } + } -//self explanatory -//output must point to buffer of 32 bytes in size -void sha256Buffer(const uint8_t * const bufferTohash, const uint16_t sizeOfBuffer, uint8_t * const output) { - sha256TwoBuffers(bufferTohash, sizeOfBuffer, 0, 0, output); + return cx_hash_no_throw(&shaContext.header, CX_LAST, 0, 0, output, 32); } -//This is the EC-KCDSA siging implementation -//@param in: keySeedBfr should point to a 32 byte keyseed (privateKey ^ -1) - note this function can edit keySeedBfr in the process -//@parma in: msgSha256 should point to a 32 byte sha256 of the message we are signing -//@param out: sig should point to 64 bytes allocated to hold the signiture of the message -void signMsg(uint8_t * const keySeedBfr, const uint8_t * const msgSha256, uint8_t * const sig) { +// SHA-256 of a single buffer +//@param[in] in - buffer to hash +//@param[in] len - length of buffer to hash +//@param[out] out - 32 byte buffer to hold the hash +// return crypto library error code (CX_OK if success) +static cx_err_t sha256Buffer(const uint8_t *const in, const uint16_t len, uint8_t *const out) { + return sha256TwoBuffers(in, len, 0, 0, out); +} - uint8_t publicKeyX[32], privateKey[32]; memset(publicKeyX, 0, sizeof(publicKeyX)); memset(privateKey, 0, sizeof(privateKey)); +// This is the EC-KCDSA siging implementation +//@param[in] keySeedBfr should point to a 32 byte keyseed (privateKey ^ -1) - note this function can +// edit keySeedBfr in the process +//@param[in] msgSha256 should point to a 32 byte sha256 of the message we are signing +//@param[out] sig should point to 64 bytes allocated to hold the signiture of the message +// return crypto library error code (CX_OK if success) +cx_err_t signMsg(uint8_t *const keySeedBfr, const uint8_t *const msgSha256, uint8_t *const sig) { + uint8_t publicKeyX[32], privateKey[32]; + explicit_bzero(publicKeyX, sizeof(publicKeyX)); + explicit_bzero(privateKey, sizeof(privateKey)); keygen25519(publicKeyX, privateKey, keySeedBfr); - uint8_t x[32]; memset(x, 0, sizeof(x)); + uint8_t x[32]; + explicit_bzero(x, sizeof(x)); - sha256TwoBuffers(msgSha256, 32, privateKey, sizeof(privateKey), x); + cx_err_t err = sha256TwoBuffers(msgSha256, 32, privateKey, sizeof(privateKey), x); + if (err != CX_OK) { + return err; + } - uint8_t Y[32]; memset(Y, 0, sizeof(Y)); + uint8_t Y[32]; + explicit_bzero(Y, sizeof(Y)); keygen25519(Y, 0, x); - uint8_t h[32]; memset(h, 0, sizeof(h)); + uint8_t h[32]; + explicit_bzero(h, sizeof(h)); - sha256TwoBuffers(msgSha256, 32, Y, sizeof(Y), h); + err = sha256TwoBuffers(msgSha256, 32, Y, sizeof(Y), h); + if (err != CX_OK) { + return err; + } memmove(sig + 32, h, 32); sign25519(sig, h, x, privateKey); -} + // clean buffers + explicit_bzero(privateKey, sizeof(privateKey)); + explicit_bzero(x, sizeof(x)); + explicit_bzero(Y, sizeof(Y)); + explicit_bzero(h, sizeof(h)); -//from curveConversion.C -void morph25519_e2m(uint8_t *montgomery, const uint8_t *y); + return CX_OK; +} +// from curveConversion.C +void morph25519_e2m(uint8_t *montgomery, const uint8_t *y); -//this function derives an ardor keeyseed (privatekey ^ -1), public key, ed255119 public key and chaincode -//For more info on how this derivation works, please read the readme -//@param in: derivationPath - a BIP42 derivation path, must be at least of length MIN_DERIVATION_PATH_LENGTH -//@param in: derivationPathLengthInUints32 - kinda what it says it is -//@param optional out: keySeedBfrOut - 32 byte EC-KCDSA keyseed for the derivation path -//@param optional out: publicKeyCurveXout - 32 byte EC-KCDSA public key for the derivation path -//@param optional out: publicKeyEd25519YLEWithXParityOut - 32 byte ED255119 public key for the derivation path (used for debuging), with the MSB as X's parity -//@param optional out: chainCodeOut - the 32 byte ED255119 derivation chaincode, used for external master public key derivation -//@param out: exceptionOut - iff the return code is R_EXCEPTION => exceptionOut will be filled with the Nano exception code +// Derives an ardor keyseed (privatekey ^ -1), public key, ed255119 public key and chaincode. +// For more info on how this derivation works, please read the readme. +//@param[in] derivationPath a BIP42 derivation path, must be at least of length +// MIN_DERIVATION_PATH_LENGTH +//@param[in] derivationPathLengthInUints32 - kinda what it says it is +//@param[out] keySeedBfrOut (optional) 32 byte EC-KCDSA keyseed for the derivation path +//@param[out] publicKeyCurveXout (optional) 32 byte EC-KCDSA public key for the derivation path +//@param[out] publicKeyEd25519YLEWithXParityOut (optional) 32 byte ED255119 public key for the +// derivation path (used for debuging), with the MSB as X's parity +//@param[out] chainCodeOut (optional) the 32 byte ED255119 derivation chaincode, used for external +// master public key derivation +//@param[out] exceptionOut iff the return code is R_KEY_DERIVATION_EX => exceptionOut will be filled +// with error code (type cx_err_t, just the 16 LSBs) //@returns: regular return values -uint8_t ardorKeys(const uint8_t * const derivationPath, const uint8_t derivationPathLengthInUints32, - uint8_t * const keySeedBfrOut, uint8_t * const publicKeyCurveXout, uint8_t * const publicKeyEd25519YLEWithXParityOut, uint8_t * const chainCodeOut, uint16_t * const exceptionOut) { - - uint8_t publicKeyYLE[32]; memset(publicKeyYLE, 0, sizeof(publicKeyYLE)); //declaring here although used later, so it can be acessable to the finally statement - uint8_t KLKR[64]; memset(KLKR, 0, sizeof(KLKR)); - struct cx_ecfp_256_private_key_s privateKey; //Don't need to init, since the ->d is copied into from some other palce, this key is 32 bytes in size - - uint32_t bipPrefix[] = PATH_PREFIX; //defined in Makefile - - if ((MIN_DERIVATION_LENGTH > derivationPathLengthInUints32) || (MAX_DERIVATION_LENGTH < derivationPathLengthInUints32)) +uint8_t ardorKeys(const uint8_t *const derivationPath, + const uint8_t derivationPathLengthInUints32, + uint8_t *const keySeedBfrOut, + uint8_t *const publicKeyCurveXout, + uint8_t *const publicKeyEd25519YLEWithXParityOut, + uint8_t *const chainCodeOut, + uint16_t *const exceptionOut) { + uint32_t bipPrefix[] = PATH_PREFIX; // defined in Makefile + + if (derivationPathLengthInUints32 < MIN_DERIVATION_LENGTH || + (derivationPathLengthInUints32 > MAX_DERIVATION_LENGTH)) return R_WRONG_SIZE_ERR; - //os_perso_derive_node_bip32 doesn't accept derivation paths located on the input buffer, so we make a local stack copy - uint32_t copiedDerivationPath[MAX_DERIVATION_LENGTH]; memset(copiedDerivationPath, 0, sizeof(copiedDerivationPath)); + // os_derive_bip32_no_throw doesn't accept derivation paths located on the input buffer, so we + // make a local stack copy + uint32_t copiedDerivationPath[MAX_DERIVATION_LENGTH]; + explicit_bzero(copiedDerivationPath, sizeof(copiedDerivationPath)); memmove(copiedDerivationPath, derivationPath, derivationPathLengthInUints32 * sizeof(uint32_t)); for (uint8_t i = 0; i < sizeof(bipPrefix) / sizeof(bipPrefix[0]); i++) { - if (copiedDerivationPath[i] != bipPrefix[i]) + if (bipPrefix[i] != copiedDerivationPath[i]) { return R_WRONG_DERIVATION_PATH_HEADER; + } } - BEGIN_TRY { - TRY { - os_perso_derive_node_bip32(CX_CURVE_Ed25519, copiedDerivationPath, derivationPathLengthInUints32, KLKR, chainCodeOut); - - // weird custom initilization, code copied from Cardano's EdDSA implementaion - privateKey.curve = CX_CURVE_Ed25519; - privateKey.d_len = 64; //don't know why the length is 64 instead of 32, it just works - memmove(privateKey.d, KLKR, 32); //Copy just the KL part - - //KL is the keeyseed, KR is used for key derivation - if (0 != keySeedBfrOut) { - //memmove(keySeedBfrOut, KLKR, 64); used for testing - DO NOT COMMIT THIS LINE! DO NOT COMMIT THIS LINE!, most functions expect a 32 private key and they will get stack overwtite - memmove(keySeedBfrOut, KLKR, 32); - } - - if ((0 != publicKeyCurveXout) || (0 != publicKeyEd25519YLEWithXParityOut)) { - - cx_ecfp_public_key_t publicKey; - cx_ecfp_init_public_key(CX_CURVE_Ed25519, 0, 0, &publicKey); - - //This should return A = KL * B - B is the generator point in ED25519 - //So publicKey.W = 04 Ax Ay in BE - cx_eddsa_get_public_key( - &privateKey, - CX_SHA512, - &publicKey, - NULL, 0, NULL, 0); - - // copy public key from big endian to little endian - for (uint8_t i = 0; i < sizeof(publicKeyYLE); i++) - publicKeyYLE[i] = publicKey.W[64 - i]; - - if (0 != publicKeyCurveXout) - morph25519_e2m(publicKeyCurveXout, publicKeyYLE); - - //We encode the pairty of X into the MSB of Y, since it's never used because of the feild size - //This allows us to compress X,Y into 32 bytes - if ((publicKey.W[32] & 1) != 0) - publicKeyYLE[31] |= 0x80; - - if (0 != publicKeyEd25519YLEWithXParityOut) - memmove(publicKeyEd25519YLEWithXParityOut, publicKeyYLE, 32); - } - } - CATCH_OTHER(exception) { - *exceptionOut = exception; - return R_KEY_DERIVATION_EX; - } - FINALLY { - memset(privateKey.d, 0, privateKey.d_len); - memset(KLKR, 0, sizeof(KLKR)); - memset(publicKeyYLE, 0, sizeof(publicKeyYLE)); - } + uint8_t KLKR[64]; + explicit_bzero(KLKR, sizeof(KLKR)); + cx_err_t ret = os_derive_bip32_no_throw(CX_CURVE_Ed25519, + copiedDerivationPath, + derivationPathLengthInUints32, + KLKR, + chainCodeOut); + if (ret != CX_OK) { + explicit_bzero(KLKR, sizeof(KLKR)); + *exceptionOut = (uint16_t) ret; + return R_KEY_DERIVATION_EX; + } + + // weird custom initilization, code copied from Cardano's EdDSA implementaion + struct cx_ecfp_256_extended_private_key_s privateKey; + privateKey.curve = CX_CURVE_Ed25519; + privateKey.d_len = 64; + memmove(privateKey.d, KLKR, 64); + + // KL is the keyseed, KR is used for key derivation + if (keySeedBfrOut != 0) { + memmove(keySeedBfrOut, KLKR, 32); + } + + if ((publicKeyCurveXout != 0) || (publicKeyEd25519YLEWithXParityOut != 0)) { + cx_ecfp_public_key_t publicKey; + ret = cx_ecfp_init_public_key_no_throw(CX_CURVE_Ed25519, 0, 0, &publicKey); + if (ret != CX_OK) { + explicit_bzero(privateKey.d, sizeof(privateKey.d)); + explicit_bzero(KLKR, sizeof(KLKR)); + *exceptionOut = (uint16_t) ret; + return R_KEY_DERIVATION_EX; + } + + // This should return A = KL * B (B is the generator point in ED25519) + // So publicKey.W = 04 Ax Ay in BE + ret = + cx_eddsa_get_public_key_no_throw((const struct cx_ecfp_256_private_key_s *) &privateKey, + CX_SHA512, + &publicKey, + NULL, + 0, + NULL, + 0); + if (ret != CX_OK) { + explicit_bzero(privateKey.d, sizeof(privateKey.d)); + explicit_bzero(KLKR, sizeof(KLKR)); + *exceptionOut = (uint16_t) ret; + return R_KEY_DERIVATION_EX; } - END_TRY; - + + // copy public key from big endian to little endian + uint8_t publicKeyYLE[32]; + explicit_bzero(publicKeyYLE, sizeof(publicKeyYLE)); + for (uint8_t i = 0; i < sizeof(publicKeyYLE); i++) { + publicKeyYLE[i] = publicKey.W[64 - i]; + } + + if (publicKeyCurveXout != 0) { + morph25519_e2m(publicKeyCurveXout, publicKeyYLE); + } + + // We encode the parity of X into the MSB of Y, since it's never used because of the field + // size This allows us to compress X,Y into 32 bytes + if ((publicKey.W[32] & 1) != 0) { + publicKeyYLE[31] |= 0x80; + } + + if (publicKeyEd25519YLEWithXParityOut != 0) { + memmove(publicKeyEd25519YLEWithXParityOut, publicKeyYLE, 32); + } + + explicit_bzero(publicKeyYLE, sizeof(publicKeyYLE)); + } + + explicit_bzero(privateKey.d, sizeof(privateKey.d)); + explicit_bzero(KLKR, sizeof(KLKR)); + return R_SUCCESS; } -//Creates a shared AES encryption key one the matches the key related to the derivation path, the target public key and the nonce +// Creates a shared AES encryption key one the matches the key related to the derivation path, the +// target public key and the nonce //@param derivationPath - the derivation path //@param derivationPathLengthInUints32 - kinda clear what this is //@param targetPublicKey - the 32 byte public key -uint8_t getSharedEncryptionKey(const uint8_t * const derivationPath, const uint8_t derivationPathLengthInUints32, const uint8_t* const targetPublicKey, - const uint8_t * const nonce, uint16_t * const exceptionOut, uint8_t * const aesKeyOut) { - - uint8_t keySeed[32]; memset(keySeed, 0, sizeof(keySeed)); - - uint8_t ret = ardorKeys(derivationPath, derivationPathLengthInUints32, keySeed, 0, 0, 0, exceptionOut); - - if (R_SUCCESS != ret) +uint8_t getSharedEncryptionKey(const uint8_t *const derivationPath, + const uint8_t derivationPathLengthInUints32, + const uint8_t *const targetPublicKey, + const uint8_t *const nonce, + uint16_t *const exceptionOut, + uint8_t *const aesKeyOut) { + uint8_t keySeed[32]; + explicit_bzero(keySeed, sizeof(keySeed)); + + uint8_t ret = + ardorKeys(derivationPath, derivationPathLengthInUints32, keySeed, 0, 0, 0, exceptionOut); + + if (ret != R_SUCCESS) { return ret; + } - uint8_t sharedKey[32]; memset(sharedKey, 0, sizeof(sharedKey)); - + uint8_t sharedKey[32]; + explicit_bzero(sharedKey, sizeof(sharedKey)); - curve25519(sharedKey, keySeed, targetPublicKey); //should use only the first 32 bytes of keyseed - - for (uint8_t i = 0; i < sizeof(sharedKey); i++) + curve25519(sharedKey, keySeed, targetPublicKey); // should use only the first + // 32 bytes of keySeed + for (uint8_t i = 0; i < sizeof(sharedKey); i++) { sharedKey[i] ^= nonce[i]; + } - sha256Buffer(sharedKey, sizeof(sharedKey), aesKeyOut); + if (sha256Buffer(sharedKey, sizeof(sharedKey), aesKeyOut) != CX_OK) { + return R_CXLIB_ERROR; + } + + // clean up buffers + explicit_bzero(keySeed, sizeof(keySeed)); + explicit_bzero(sharedKey, sizeof(sharedKey)); return R_SUCCESS; } -//param: publicKey should point to a 32 byte public key buffer -//returns: a 64bit public key id, used later with reedsolomon to create Ardor/NXT addresses -uint64_t publicKeyToId(const uint8_t * const publicKey) { - - uint8_t tempSha[32]; - sha256Buffer(publicKey, 32, tempSha); - - return ((((uint64_t) tempSha[7]) << 56) | - (((uint64_t) tempSha[6]) << 48) | - (((uint64_t) tempSha[5]) << 40) | - (((uint64_t) tempSha[4]) << 32) | - (((uint64_t) tempSha[3]) << 24) | - (((uint64_t) tempSha[2]) << 16) | - (((uint64_t) tempSha[1]) << 8) | - (((uint64_t) tempSha[0] ))); +// Computes the 64bit account id from a given public key +//@param publicKey - the 32 byte public key +//@param accountIdOut - pointer to store the computed account ID +cx_err_t publicKeyToId(const uint8_t *const publicKey, uint64_t *const accountIdOut) { + uint8_t hashOut[32]; + cx_err_t err = sha256Buffer(publicKey, 32, hashOut); + if (err != CX_OK) { + return err; + } + + // Extract the account ID from the first 8 bytes of the hash + // Assuming little-endian architecture + *accountIdOut = *((uint64_t *) hashOut); + + return CX_OK; +} + +/** + * Checks if the given derivation path length is valid. + * A valid length is a multiple of 4 bytes (sizeof(uint32_t)) and within the range of + * MIN_DERIVATION_LENGTH and MAX_DERIVATION_LENGTH (inclusive). + * + * @param length The length of the derivation path in bytes. + * @return true if the length is valid, false otherwise. + */ +bool isValidDerivationPathLength(uint8_t length) { + return length >= MIN_DERIVATION_LENGTH * sizeof(uint32_t) && + length <= MAX_DERIVATION_LENGTH * sizeof(uint32_t) && length % sizeof(uint32_t) == 0; +} + +// returns the chain name for a given chainId +char *chainName(const uint8_t chainId) { + return (char *) PIC(((chainType *) PIC(&CHAINS[chainId - 1]))->name); +} + +// the amount of digits on the right of the decimal dot for each chain +uint8_t chainNumDecimalsBeforePoint(const uint8_t chainId) { + return ((chainType *) PIC(&CHAINS[chainId - 1]))->numDecimalsBeforePoint; +} + +// this function formats amounts into string and most importantly add the dot where it's supposed to +// be the way this is works is that amounts ints and then the dot is added after +// chainNumDecimalsBeforePoint() digits from right to left for example, if the amount is 4200000000 +// and we are in the Ardor chain in which chainNumDecimalsBeforePoint() is 8 then the formated +// amount will be "42" for 4210100000 it will be 42.101 +//@param outputString - does what it says +//@param maxOutputLength - does what it says +//@param numberToFormat - the input number to format, isn't const cuz we play with it in order to +// format the number +//@param numDigitsBeforeDecimal - read first paragraph for info +//@returns 0 iff some kind of error happend, else the length of the output string including the null +// terminator +uint8_t formatAmount(char *const outputString, + const uint16_t maxOutputLength, + uint64_t numberToFormat, + const uint8_t numDigitsBeforeDecimal) { + uint16_t outputIndex = 0; + bool wasANumberWritten = false; + bool isDotWritten = false; + uint8_t numberIndex = 0; + + while (true) { + uint8_t modulo = numberToFormat % 10; + numberToFormat -= modulo; + numberToFormat /= 10; + + if (numberIndex == numDigitsBeforeDecimal) { + if (wasANumberWritten && (!isDotWritten) && (numDigitsBeforeDecimal != 0)) { + isDotWritten = true; + outputString[outputIndex++] = '.'; + } + + wasANumberWritten = true; + } + + if (0 != modulo) { + wasANumberWritten = true; + } + + if (wasANumberWritten || (numDigitsBeforeDecimal == 0)) { + outputString[outputIndex++] = '0' + modulo; + } + + if (outputIndex >= maxOutputLength) { + return 0; + } + + if ((numberToFormat == 0) && (numberIndex >= numDigitsBeforeDecimal)) { + break; + } + + numberIndex++; + } + + // reverse the string since we are creating it from left to right, and numbers are right to left + for (uint16_t i = 0; i < outputIndex - 1 - i; i++) { + uint8_t temp = outputString[i]; + outputString[i] = outputString[outputIndex - i - 1]; + outputString[outputIndex - i - 1] = temp; + } + + outputString[outputIndex] = 0; + return outputIndex + 1; } +// like formatAmount but also appends the chain (token) name +uint8_t formatChainAmount(char *const out, + const uint16_t maxLength, + uint64_t amount, + const uint8_t chainId) { + uint8_t ret = formatAmount(out, maxLength, amount, chainNumDecimalsBeforePoint(chainId)); + if (ret == 0) { + return 0; + } + + // append an space and the chain name + snprintf(out + ret - 1, maxLength - ret - 1, " %s", chainName(chainId)); + + return ret + strlen(chainName(chainId)) + 1; +} -//app_stack_canary is defined by the link script to be at the start of the user data or end of the stack, something like that -//so if there is a stack overflow then it will be overwriten, this is how check_canary() works. -//make sure HAVE_BOLOS_APP_STACK_CANARY is defined in the makefile, so that the OS code will init it and check against it every io_exchange call -//if the canary is not the same, and if not, it will throw +// app_stack_canary is defined by the link script to be at the start of the user data or end of the +// stack, something like that so if there is a stack overflow then it will be overwriten, this is +// how check_canary() works. make sure HAVE_BOLOS_APP_STACK_CANARY is defined in the makefile, so +// that the OS code will init it and check against it every io_exchange call if the canary is not +// the same, and if not, it will throw extern unsigned int app_stack_canary; diff --git a/src/ardor.h b/src/ardor.h index 2d6e15b..b2b3c97 100644 --- a/src/ardor.h +++ b/src/ardor.h @@ -1,128 +1,203 @@ /******************************************************************************* -* (c) 2019 Haim Bender -* -* -* 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 "ux.h" + * (c) 2019 Haim Bender + * (c) 2021-2023 Jelurida IP B.V. + * + * + * 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 "cx.h" #include "os.h" +#include "config.h" -#if defined(TARGET_NANOS) - unsigned int makeTextGoAround_preprocessor(bagl_element_t * const element); -#endif - -uint64_t publicKeyToId(const uint8_t * const publicKey); -uint8_t ardorKeys(const uint8_t * const derivationPath, const uint8_t derivationPathLengthInUints32, - uint8_t * const keySeedBfrOut, uint8_t * const publicKeyCurveXout, uint8_t * const publicKeyEd25519YLEWithXParityOut, uint8_t * const chainCodeOut, uint16_t * const exceptionOut); +cx_err_t publicKeyToId(const uint8_t* const publicKey, uint64_t* const accountIdOut); -void signMsg(uint8_t * const keySeedBfr, const uint8_t * const msgSha256, uint8_t * const sig); +uint8_t ardorKeys(const uint8_t* const derivationPath, + const uint8_t derivationPathLengthInUints32, + uint8_t* const keySeedBfrOut, + uint8_t* const publicKeyCurveXout, + uint8_t* const publicKeyEd25519YLEWithXParityOut, + uint8_t* const chainCodeOut, + uint16_t* const exceptionOut); -void ui_idle(); -bool check_canary(); +bool isValidDerivationPathLength(uint8_t derivationPathLengthInUints32); -uint8_t getSharedEncryptionKey(const uint8_t * const derivationPath, const uint8_t derivationPathLengthInUints32, const uint8_t* const targetPublicKey, - const uint8_t * const nonce, uint16_t * const exceptionOut, uint8_t * const aesKeyOut); +char* chainName(const uint8_t chainId); +cx_err_t signMsg(uint8_t* const keySeedBfr, const uint8_t* const msgSha256, uint8_t* const sig); -//This is the state object that authAndSignTxn uses -typedef struct { +bool check_canary(); - bool txnPassedAutherization; //This most important bool, means the user confirmed the txn content via the dialog and we can sign the current TXN +uint8_t getSharedEncryptionKey(const uint8_t* const derivationPath, + const uint8_t derivationPathLengthInUints32, + const uint8_t* const targetPublicKey, + const uint8_t* const nonce, + uint16_t* const exceptionOut, + uint8_t* const aesKeyOut); - uint8_t readBuffer[512]; //This is where unparsed temp buffer data is kept, since we do streamed parsing we have to have it here - uint16_t readBufferEndPos; //Index of the last byte in readBuffer - uint16_t readBufferReadOffset; //Index of the first byte in readBuffer - uint16_t numBytesRead; //The total number of bytes parsed up until now +// the amount of digits on the right of the decimal dot for each chain +uint8_t chainNumDecimalsBeforePoint(const uint8_t chainId); - uint8_t functionStack[FUNCTION_STACK_SIZE]; //This is stack of all the function that have yet to parse the TXN, the C handler file explains this process in more detail - uint8_t numFunctionsOnStack; //Is what it says +uint8_t formatAmount(char* const outputString, + const uint16_t maxOutputLength, + uint64_t numberToFormat, + const uint8_t numDigitsBeforeDecimal); - bool isClean; //If the state was just initilized +uint8_t formatChainAmount(char* const out, + const uint16_t maxLength, + uint64_t amount, + const uint8_t chainId); - cx_sha256_t hashstate; //The state of the hash for the txn buffer +void cleanState(); - uint32_t chainId; //What it says it is - uint16_t txnTypeAndSubType; //What it says it is - uint8_t txnTypeIndex; //txnTypeAndSubType's index in TXN_TYPES +// define max text sizes for the different UI screens - uint64_t recipientId; //the recipient address ID - uint64_t amount; //the amount to be sent in the txn, note that every chain parses this number differently, it dives this number by some 10^X - uint64_t fee; //What it says it is - //What it says it is +// 9,223,372,036,854,775,807 is the biggest number you can hold in uint64 + the dot + null +#define MAX_FEE_TEXT_SIZE 21 +#define MAX_CHAIN_AND_TXN_TYPE_TEXT_SIZE 60 +#define MAX_WINDOWS 3 // Additional windows, depending on the txn type +#define MAX_WINDOW_TITLE_SIZE 20 // The longest string is price per (chain name here) +#define MAX_WINDOW_TEXT_SIZE 31 // MAX(Ardor arddress = 27, feeText + chainName) +// this should allow displaying the names for up to three types, otherwise we show a bitmap +#define MAX_APPENDAGES_TEXT_SIZE 60 - int32_t attachmentTempInt32Num1, attachmentTempInt32Num2; //Different attachments parse in different ways, they all need space in state, so this is how it's defined - int64_t attachmentTempInt64Num1, attachmentTempInt64Num2, attachmentTempInt64Num3; +enum authTxnStates { AUTH_STATE_INIT, AUTH_STATE_PARSING, AUTH_STATE_USER_AUTHORIZED }; - uint16_t txnSizeBytes; //The decalred Txn size +// This is the state object that authAndSignTxn uses +typedef struct { + enum authTxnStates state; + bool requiresBlindSigning; // This is true if the TX is a blind signing TX + + uint8_t readBuffer[512]; // This is where unparsed temp buffer data is kept, since we do + // streamed parsing we have to have it here + uint16_t readBufferEndPos; // Index of the last byte in readBuffer + uint16_t readBufferReadOffset; // Index of the first byte in readBuffer + uint16_t numBytesRead; // The total number of bytes parsed up until now + + uint8_t functionStack[FUNCTION_STACK_SIZE]; // This is stack of all the function that have yet + // to parse the TXN, the C handler file explains + // this process in more detail + uint8_t numFunctionsOnStack; + + cx_sha256_t hashstate; // The state of the hash for the txn buffer + + uint32_t chainId; + uint16_t txnTypeAndSubType; + uint8_t txnTypeIndex; // txnTypeAndSubType's index in TXN_TYPES + + uint64_t recipientId; // the recipient address ID + uint64_t amount; // the amount to be sent in the txn, note that every chain parses this number + // differently, it divides this number by some 10^X + uint64_t fee; + + // Different attachments have different payloads. Each transaction type & subtype have + // a specific attachment. We use a union to define each supported attachment to preserve storage + union { + struct { + uint32_t chainId; + uint32_t exchangeChainId; + uint64_t quantityQNT; + uint64_t priceNQT; + } coinExchange; + struct { + uint64_t assetId; + uint64_t quantityQNT; + uint64_t priceNQT; + } assetOrderPlacement; + struct { + uint64_t assetId; + uint64_t quantityQNT; + } assetTransfer; + } attachment; + + uint16_t txnSizeBytes; // The declared Txn size + + char feeText[MAX_FEE_TEXT_SIZE]; + char chainAndTxnTypeText[MAX_CHAIN_AND_TXN_TYPE_TEXT_SIZE]; + // additional UI screens, depending on the txn type + char windowTitles[MAX_WINDOWS][MAX_WINDOW_TITLE_SIZE]; + char windowTexts[MAX_WINDOWS][MAX_WINDOW_TEXT_SIZE]; + char appendagesText[MAX_APPENDAGES_TEXT_SIZE]; +} authTxn_t; +#define MAX_CHUNK_SIZE_ENCRYPT 224 - char feeText[21]; //9,223,372,036,854,775,807 is the biggest number you can hold in uint64 + the dot + null terminator means the longest text is 20 - char chainAndTxnTypeText[60]; //Aproximation of size - char optionalWindow1Title[9]; //MAX("Amount","Asset Id") - char optionalWindow1Text[31]; //same as fee text + name of the chain + space - char optionalWindow2Title[20]; //The longest string is price per (some chain name here) - char optionalWindow2Text[31]; //MAX(Ardor arddress = 27, feeText + chainName) - char optionalWindow3Title[10]; //MAX("Recipient") - char optionalWindow3Text[28]; //MAX(Ardor arddress = 27) - char appendagesText[60]; //this should allow displaying the names for up to three types, otherwise we show a bitmap - uint8_t uiFlowBitfeild; //This is a bit feild for selecting the right UI flow +// State for the encryptDecrypt handler +typedef struct { + uint8_t mode; // Modes are described in the .C file + uint8_t cbc[CX_AES_BLOCK_SIZE]; // Something to do with AES state + cx_aes_key_t aesKey; // This is the encryption key + uint8_t buffer[MAX_CHUNK_SIZE_ENCRYPT + 1]; // +1 for R_SUCCESS at position 0 +} encryptionState_t; -} authTxn_t; +enum signTokenStates { SIGN_TOKEN_UNINIT, SIGN_TOKEN_INIT, SIGN_TOKEN_BYTES_RECEIVED }; -//State for the encryptDecrypt handler -typedef struct { - uint8_t mode; //Modes are described in the .C file - uint8_t cbc[16]; //Something to do with AES state - unsigned int ctx[(4 * 4 * 15 + 4) / sizeof(unsigned int)]; //This is the encryption key, unsigned int is the type it uses aes_uint * -} encyptionState_t; +// 100-byte token consists of a 32-byte public key, a 4-byte timestamp, and a 64-byte signature +#define TOKEN_SIZE (1 + PUBLIC_KEY_SIZE + TIMESTAMP_SIZE + SIGNATURE_SIZE) -//State of the sign token handler +// State of the sign token handler typedef struct { - uint8_t mode; //Modes descrived in the .C file - cx_sha256_t sha256; //The state of the token hash + enum signTokenStates state; // The state of the handler + cx_sha256_t sha256; // The state of the token hash + uint32_t timestamp; // The timestamp of the token + uint8_t derivationPathLengthInUints32; // The length of the derivation path + uint8_t* ptrDerivationPath; // The derivation path + uint8_t token[TOKEN_SIZE]; // The 1 byte response code + token } signTokenState_t; -//This is the union states type, the actual object is defined in ardor.c -typedef union { - encyptionState_t encryption; +// This is the states type, the actual object is defined in ardor.c +typedef struct { + encryptionState_t encryption; authTxn_t txnAuth; - signTokenState_t tokenCreation; + signTokenState_t tokenSign; } states_t; -//declared in ardor.c +// declared in ardor.c extern states_t state; -//used to list txn types +// Settings +typedef struct { + bool allowBlindSigning; +} settings_t; + +typedef struct internalStorage_t { + settings_t settings; + bool initialized; +} internalStorage_t; + +extern const internalStorage_t N_storage_real; +#define N_storage (*(volatile internalStorage_t*) PIC(&N_storage_real)) + +// used to list txn types typedef struct { uint16_t id; - char * name; + const char* name; uint8_t attachmentParsingFunctionNumber; } txnType; - -//These to are automaticly generated by createTxnTypes.py into src/txnTypeLists.c +// These to are automaticly generated by createTxnTypes.py into src/txnTypeLists.c extern const txnType TXN_TYPES[]; extern const uint8_t LEN_TXN_TYPES; // These are the offsets of various parts of a request APDU packet. INS // identifies the requested command (see above), and P1 and P2 are parameters // to the command. -#define CLA 0xE0 -#define OFFSET_CLA 0x00 -#define OFFSET_INS 0x01 -#define OFFSET_P1 0x02 -#define OFFSET_P2 0x03 -#define OFFSET_LC 0x04 +#define CLA 0xE0 +#define OFFSET_CLA 0x00 +#define OFFSET_INS 0x01 +#define OFFSET_P1 0x02 +#define OFFSET_P2 0x03 +#define OFFSET_LC 0x04 #define OFFSET_CDATA 0x05 diff --git a/src/authAndSignTxn.c b/src/authAndSignTxn.c index 772756d..7080216 100644 --- a/src/authAndSignTxn.c +++ b/src/authAndSignTxn.c @@ -1,75 +1,79 @@ /******************************************************************************* -* (c) 2019 Haim Bender -* -* -* 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 Haim Bender + * (c) 2021-2023 Jelurida IP B.V. + * + * + * 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 -#include - -#include -#include -#include "ux.h" +#include "io.h" // io_send* +#include "parser.h" // command_t #include "glyphs.h" #include "returnValues.h" #include "config.h" #include "ardor.h" - +#include "reedSolomon.h" +#include "transactionParser.h" +#include "ui/menu.h" +#include "ui/display.h" +#include "io_helper.h" // io_send_return* #define P1_INIT 1 #define P1_CONTINUE 2 #define P1_SIGN 3 - -// This is the code that parses the txn for signing, it parses streamed txn bytes into the state object while hashing the bytes to be signed later, -// displays a dialog of screens which contain the parsed txn bytes from the state, -// It solves 2 no trivial problems -// 1 - Allowing txn bytes to be parsed from a stream of bytes (this is very hard, since we don't have a lot memory, so we need to parse bytes and forget about them) -// 2 - txn's very in length depending on type, so the same bytes are sometimes not parsed into the same place, so it has to be dynamic about parsing +#define MODE_P1_MASK 0b00000011 +#define TX_SIZE_P1_MASK 0b11111100 +#define TX_SIZE_P1_SHIFT 6 + +// This is the code that parses the txn for signing, it parses streamed tx bytes into the state +// object while hashing the bytes to be signed later, displays a dialog of screens which contain the +// parsed txn bytes from the state. It solves 2 no trivial problems: +// 1 - Allowing txn bytes to be parsed from a stream of bytes (this is very hard, since we don't +// have a lot memory, so we need to parse bytes and forget about them) +// 2 - txn's very in length depending on type, so the same bytes are sometimes not parsed into the +// same place, so it has to be dynamic about parsing // // // The way these problems are solved is by the following flow: // // The function stack is initiated with an index reference to parseMainTxnData -// +// // // authAndSignTxnHandlerHelper is called with some of the txn bytes // => addToReadBuffer is called adds these bytes to the read buffer -// => parseFromStack is called, which calls the first parse function on the stack which is parseMainTxnData +// => parseTransaction is called, +// which calls the first parse function on the stack which is parseMainTxnData // => parseMainTxnData trys to pull 142 bytes from the buffer // if there is are 142 bytes there: -// parseMainTxnData parses the main txn bytes and then adds more functions to parse stack depending on the appendages +// parseMainTxnData parses the main txn bytes and then adds more functions to parse stack +// depending on the appendages // else // R_SEND_MORE_BYTES is trickled down by the function to be sent to back to the client -// -// and so on the process goes until the stack of functions is empty and there are no more bytes in the read buffer -// if the parsing goes well without errors => setScreenTexts(); is called which sets up the labels and first screen of the autherization dialog -// => showScreen(); make the first screen apeare setting and sets ui_auth_button() to be the button callback for the dialog => -// pressing on the right does state.txnAuth.dialogScreenIndex++; if it reaches the end number then the txn is autherized for signing and state.txnAuth.txnPassedAutherization is set to true -// pressing left does state.txnAuth.dialogScreenIndex--; and if it gets to a negative number it will be interpretate as a txn rejection => initTxnAuthState() -// will be called and R_REJECT will be returned to client - +// +// And so on the process goes until the stack of functions is empty and there are no more bytes in +// the read buffer. If the parsing goes well without errors => setScreenTexts(); is called which +// sets up the labels and first screen of the authorization dialog. // API: // // -// The mode is encoded in the first 2 bits of the p1 parameter and the size of the txn should be ((p1 & 0b11111100) << 6) + p2 -// you only need to pass the size when calling P1_INIT +// The mode is encoded in the first 2 bits of the p1 parameter and the size of the txn should +// be ((p1 & 0b11111100) << 6) + p2 you only need to pass the size when calling P1_INIT // // P1: P1_INIT: // dataBuffer: txn bytes //you can send all of your bytes here if you want @@ -82,755 +86,157 @@ // dataBuffer: derivaiton path (uint32) * some length // returns: 1 bytes status | 64 byte signiture +static void initTxnAuthState() { + cleanState(); -//This function cleans the txnAuth part of the state, its important to call it before starting to load a txn -//also whenever there is an error you should call it so that no one can exploit an error state for some sort of attack, -//the cleaner the state is, the better, allways clean when you can -void initTxnAuthState() { - - state.txnAuth.txnSizeBytes = 0; - state.txnAuth.numBytesRead = 0; - - memset(state.txnAuth.functionStack, 0, sizeof(state.txnAuth.functionStack)); - state.txnAuth.functionStack[0] = 1; //Add the first parse function on the stack - state.txnAuth.functionStack[1] = 2; //The appendages parse function + state.txnAuth.functionStack[0] = PARSE_FN_MAIN; // Add the first parse function on the stack + state.txnAuth.functionStack[1] = PARSE_FN_APPENDAGES_FLAGS; // The appendages parse function state.txnAuth.numFunctionsOnStack = 2; - state.txnAuth.txnPassedAutherization = false; - state.txnAuth.isClean = true; - cx_sha256_init(&state.txnAuth.hashstate); - - memset(state.txnAuth.readBuffer, 0, sizeof(state.txnAuth.readBuffer)); - state.txnAuth.readBufferReadOffset = 0; - state.txnAuth.readBufferEndPos = 0; - - state.txnAuth.chainId = 0; - state.txnAuth.txnTypeAndSubType = 0; - state.txnAuth.txnTypeIndex = 0; - state.txnAuth.recipientId = 0; - state.txnAuth.amount = 0; - - state.txnAuth.attachmentTempInt32Num1 = 0; - state.txnAuth.attachmentTempInt32Num2 = 0; - state.txnAuth.attachmentTempInt64Num1 = 0; - state.txnAuth.attachmentTempInt64Num2 = 0; - state.txnAuth.attachmentTempInt64Num3 = 0; - - memset(state.txnAuth.feeText, 0, sizeof(state.txnAuth.feeText)); - memset(state.txnAuth.chainAndTxnTypeText, 0, sizeof(state.txnAuth.chainAndTxnTypeText)); - memset(state.txnAuth.optionalWindow1Title, 0, sizeof(state.txnAuth.optionalWindow1Title)); - memset(state.txnAuth.optionalWindow1Text, 0, sizeof(state.txnAuth.optionalWindow1Text)); - memset(state.txnAuth.optionalWindow2Title, 0, sizeof(state.txnAuth.optionalWindow2Title)); - memset(state.txnAuth.optionalWindow2Text, 0, sizeof(state.txnAuth.optionalWindow2Text)); - memset(state.txnAuth.optionalWindow3Title, 0, sizeof(state.txnAuth.optionalWindow3Title)); - memset(state.txnAuth.optionalWindow3Text, 0, sizeof(state.txnAuth.optionalWindow3Text)); - memset(state.txnAuth.appendagesText, 0, sizeof(state.txnAuth.appendagesText)); - - state.txnAuth.uiFlowBitfeild = 0; -} - - -//Does what it says -txnType * txnTypeAtIndex(const uint8_t index) { - //Because static memory is weird and might be reclocated in ledger we have to use the PIC macro in order to access it - return (txnType*)PIC(&TXN_TYPES[index]); } -//does what it says -char * txnTypeNameAtIndex(const uint8_t index) { - //Because static memory is weird and might be reclocated in ledger we have to use the PIC macro in order to access it - return (char*)PIC(((txnType*)PIC(&TXN_TYPES[index]))->name); -} - -//does what is says -char * chainName(const uint8_t chainId) { - //Because static memory is weird and might be reclocated in ledger we have to use the PIC macro in order to access it - return (char*)PIC(((chainType*)PIC(&CHAINS[chainId - 1]))->name); -} - -char * appendageTypeName(const uint8_t index) { - return (char*)PIC(((appendageType*)PIC(&APPENDAGE_TYPES[index]))->name); -} - -//the amount of digits on the right of the decimal dot for each chain -uint8_t chainNumDecimalsBeforePoint(const uint8_t chainId) { - //Because static memory is weird and might be reclocated in ledger we have to use the PIC macro in order to access it - return ((chainType*)PIC(&CHAINS[chainId - 1]))->numDecimalsBeforePoint; -} - - -//this function formats amounts into string and most importantly add the dot where it's supposed to be -//the way this is works is that amounts ints and then the dot is added after chainNumDecimalsBeforePoint() digits from right to left -//for example, if the amount is 4200000000 and we are in the Ardor chain in which chainNumDecimalsBeforePoint() is 8 then the formated amount will be "42" -//for 4210100000 it will be 42.101 - -//@param outputString - does what it says -//@param maxOutputLength - does what it says -//@param numberToFormat - the input number to format, isn't const cuz we play with it in order to format the number -//@param numDigitsBeforeDecimal - read first paragraph for info -//@returns 0 iff some kind of error happend, else the length of the output string including the null terminator -uint8_t formatAmount(char * const outputString, const uint16_t maxOutputLength, uint64_t numberToFormat, const uint8_t numDigitsBeforeDecimal) { - - uint16_t outputIndex = 0; - bool wasANumberWritten = false; - bool isDotWritten = false; - uint8_t numberIndex = 0; - - - while (42) { - - uint8_t modulo = numberToFormat % 10; - numberToFormat -= modulo; - numberToFormat /= 10; - - if (numDigitsBeforeDecimal == numberIndex) { - if (wasANumberWritten && (!isDotWritten) && (0 != numDigitsBeforeDecimal)) { - isDotWritten = true; - outputString[outputIndex++] = '.'; - } - - wasANumberWritten = true; - } - - if (0 != modulo) - wasANumberWritten = true; - - if (wasANumberWritten || (0 == numDigitsBeforeDecimal)) - outputString[outputIndex++] = '0' + modulo; - - if (outputIndex >= maxOutputLength) - return 0; - - if ((0 == numberToFormat) && (numDigitsBeforeDecimal <= numberIndex)) - break; - - numberIndex++; - - } - - - //reverse the string since we are creating it from left to right, and numbers are right to left - for (uint16_t i = 0; i < outputIndex - 1 - i; i++) { - uint8_t temp = outputString[i]; - outputString[i] = outputString[outputIndex - i - 1]; - outputString[outputIndex - i - 1] = temp; - } - - outputString[outputIndex] = 0; - return outputIndex + 1; +static int cleanAndReturn(uint8_t ret) { + cleanState(); + return io_send_return1(ret); } -//defined in readSolomon.c -void reedSolomonEncode(const uint64_t inp, const char * output); - -//Accept click callback -unsigned int txn_autherized(const bagl_element_t *e) { - UNUSED(e); - - state.txnAuth.txnPassedAutherization = true; - G_io_apdu_buffer[0] = R_SUCCESS; - G_io_apdu_buffer[1] = R_FINISHED; - G_io_apdu_buffer[2] = 0x90; - G_io_apdu_buffer[3] = 0x00; - io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, 4); - - ui_idle(); // redraw ui - return 0; // DO NOT REDRAW THE BUTTON +// Accept click callback +void signTransactionConfirm() { + state.txnAuth.state = AUTH_STATE_USER_AUTHORIZED; + io_send_return2(R_SUCCESS, R_FINISHED); } -//Canceled click callback -unsigned int txn_canceled(const bagl_element_t *e) { - UNUSED(e); - - initTxnAuthState(); - - G_io_apdu_buffer[0] = R_SUCCESS; - G_io_apdu_buffer[1] = R_REJECT; - G_io_apdu_buffer[2] = 0x90; - G_io_apdu_buffer[3] = 0x00; - io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, 4); - - ui_idle(); // redraw ui - return 0; // DO NOT REDRAW THE BUTTON +// Canceled click callback +void signTransactionCancel() { + cleanState(); + io_send_return2(R_SUCCESS, R_REJECT); } -//Defenition of the UI for the handler -UX_STEP_NOCB(aasFlowPage1, - pnn, - { - &C_icon_eye, - "Authorize", - "transaction", - }); -UX_STEP_NOCB(aasFlowPage2, - bnnn_paging, - { - .title = "Chain&TxnType", - .text = state.txnAuth.chainAndTxnTypeText, - }); - -UX_STEP_NOCB(aasFlowOptional1, - bnnn_paging, - { - .title = state.txnAuth.optionalWindow1Title, - .text = state.txnAuth.optionalWindow1Text, - }); -UX_STEP_NOCB(aasFlowOptional2, - bnnn_paging, - { - .title = state.txnAuth.optionalWindow2Title, - .text = state.txnAuth.optionalWindow2Text, - }); -UX_STEP_NOCB(aasFlowOptional3, - bnnn_paging, - { - .title = state.txnAuth.optionalWindow3Title, - .text = state.txnAuth.optionalWindow3Text, - }); -UX_STEP_NOCB(aasFlowAppendages, - bnnn_paging, - { - .title = "Appendages", - .text = state.txnAuth.appendagesText, - }); -UX_STEP_NOCB(aasFlowPage3, - bnnn_paging, - { - .title = "Fees", - .text = state.txnAuth.feeText, - }); -UX_STEP_VALID(aasFlowPage4, - pbb, - txn_autherized(NULL), - { - &C_icon_validate_14, - "Accept", - "and send", - }); -UX_STEP_VALID(aasFlowPage5, - pb, - txn_canceled(NULL), - { - &C_icon_crossmark, - "Reject", - }); - -UX_FLOW(ux_flow_000, - &aasFlowPage1, - &aasFlowPage2, - &aasFlowPage3, - &aasFlowPage4, - &aasFlowPage5 -); - -UX_FLOW(ux_flow_001, - &aasFlowPage1, - &aasFlowPage2, - &aasFlowAppendages, - &aasFlowPage3, - &aasFlowPage4, - &aasFlowPage5 -); - -UX_FLOW(ux_flow_010, - &aasFlowPage1, - &aasFlowPage2, - &aasFlowOptional1, - &aasFlowOptional2, - &aasFlowPage3, - &aasFlowPage4, - &aasFlowPage5 -); - -UX_FLOW(ux_flow_011, - &aasFlowPage1, - &aasFlowPage2, - &aasFlowOptional1, - &aasFlowOptional2, - &aasFlowAppendages, - &aasFlowPage3, - &aasFlowPage4, - &aasFlowPage5 -); - -UX_FLOW(ux_flow_110, - &aasFlowPage1, - &aasFlowPage2, - &aasFlowOptional1, - &aasFlowOptional2, - &aasFlowOptional3, - &aasFlowPage3, - &aasFlowPage4, - &aasFlowPage5 -); - -UX_FLOW(ux_flow_111, - &aasFlowPage1, - &aasFlowPage2, - &aasFlowOptional1, - &aasFlowOptional2, - &aasFlowOptional3, - &aasFlowAppendages, - &aasFlowPage3, - &aasFlowPage4, - &aasFlowPage5 -); - -//Just switches between based of the uiFlowBitfeild -static void showScreen() { - - if(0 == G_ux.stack_count) - ux_stack_push(); - - switch (state.txnAuth.uiFlowBitfeild) { - - case 0x00: - ux_flow_init(0, ux_flow_000, NULL); - break; - case 0x01: - ux_flow_init(0, ux_flow_001, NULL); - break; - case 0x02: - ux_flow_init(0, ux_flow_010, NULL); - break; - case 0x03: - ux_flow_init(0, ux_flow_011, NULL); - break; - case 0x06: - ux_flow_init(0, ux_flow_110, NULL); - break; - case 0x07: - ux_flow_init(0, ux_flow_111, NULL); - break; - } +/** + * Sets the title and text for one of the optional windows in the transaction authorization screen. + * The title is a regular text, the text is formatted as an integer. + * + * @param windowIndex The index of the window to print the amount for. + * @param title The title to display for the window. + * @param amount The amount to display in the window text. + */ +static void printWindowAmount(uint8_t windowIndex, const char* title, uint64_t amount) { + snprintf(state.txnAuth.windowTitles[windowIndex], + sizeof(state.txnAuth.windowTitles[windowIndex]), + "%s", + title); + formatAmount(state.txnAuth.windowTexts[windowIndex], + sizeof(state.txnAuth.windowTexts[windowIndex]), + amount, + 0); } -//This function formats trxn data into text memebers of the state which the UI flow will read from -//Returns: Success iff everything is good, otherwise probably some kind of formating error -uint8_t setScreenTexts() { - - uint8_t ret = 0; - - if (LEN_TXN_TYPES > state.txnAuth.txnTypeIndex) { - - switch (state.txnAuth.txnTypeAndSubType) { - - //note: you have to write the type and subtype in reverse, because of little endian buffer representation an big endian C code representation - - case 0x0000: //OrdinaryPayment - case 0x00fe: //FxtPayment - - state.txnAuth.uiFlowBitfeild |= 2; //turn on the second bit for optional 1 & 2 - - snprintf(state.txnAuth.optionalWindow1Title, sizeof(state.txnAuth.optionalWindow1Title), "Amount"); - - if (0 == formatAmount(state.txnAuth.optionalWindow1Text, sizeof(state.txnAuth.optionalWindow1Text), state.txnAuth.amount, chainNumDecimalsBeforePoint(state.txnAuth.chainId))) - return R_FORMAT_AMOUNT_ERR; - - snprintf(state.txnAuth.optionalWindow2Title, sizeof(state.txnAuth.optionalWindow2Title), "Recipient"); - snprintf(state.txnAuth.optionalWindow2Text, sizeof(state.txnAuth.optionalWindow2Text), APP_PREFIX); - reedSolomonEncode(state.txnAuth.recipientId, state.txnAuth.optionalWindow2Text + strlen(state.txnAuth.optionalWindow2Text)); - - break; - - case 0x00fc: //FxtCoinExchangeOrderIssue - case 0x000b: //CoinExchangeOrderIssue - - state.txnAuth.uiFlowBitfeild |= 2; //turn on the second bit for optional 1 & 2 - - - snprintf(state.txnAuth.optionalWindow1Title, sizeof(state.txnAuth.optionalWindow1Title), "Amount"); +static uint8_t setPaymentsScreenTexts() { + snprintf(state.txnAuth.windowTitles[0], sizeof(state.txnAuth.windowTitles[0]), "Amount"); - ret = formatAmount(state.txnAuth.optionalWindow1Text, sizeof(state.txnAuth.optionalWindow1Text), state.txnAuth.attachmentTempInt64Num1, chainNumDecimalsBeforePoint(state.txnAuth.attachmentTempInt32Num2)); - - if (0 == ret) - return R_FORMAT_AMOUNT_ERR; - - //note: the existence of chainName(state.txnAuth.attachmentTempInt32Num2) was already checked in the parsing function - snprintf(state.txnAuth.optionalWindow1Text + ret - 1, sizeof(state.txnAuth.optionalWindow1Text) - ret - 1, " %s", chainName(state.txnAuth.attachmentTempInt32Num2)); - - //note: the existence of chainName(state.txnAuth.attachmentTempInt32Num2) was already checked in the parsing function - snprintf(state.txnAuth.optionalWindow2Title, sizeof(state.txnAuth.optionalWindow2Title), "Price per %s", chainName(state.txnAuth.attachmentTempInt32Num2)); - ret = formatAmount(state.txnAuth.optionalWindow2Text, sizeof(state.txnAuth.optionalWindow2Text), state.txnAuth.attachmentTempInt64Num2, chainNumDecimalsBeforePoint(state.txnAuth.attachmentTempInt32Num1)); - - if (0 == ret) - return R_FORMAT_AMOUNT_ERR; - - //note: the existence of chainName(state.txnAuth.attachmentTempInt32Num1) was already checked in the parsing function - snprintf(state.txnAuth.optionalWindow2Text + ret - 1, sizeof(state.txnAuth.optionalWindow2Text) - ret - 1, " %s", chainName(state.txnAuth.attachmentTempInt32Num1)); - - break; - - case 0x0102: // Asset Transfer - - state.txnAuth.uiFlowBitfeild |= 6; // turn bits 2&3 for all three optional screens - - snprintf(state.txnAuth.optionalWindow1Title, sizeof(state.txnAuth.optionalWindow1Title), "Asset Id"); - formatAmount(state.txnAuth.optionalWindow1Text, sizeof(state.txnAuth.optionalWindow1Text), state.txnAuth.attachmentTempInt64Num1, 0); - - snprintf(state.txnAuth.optionalWindow2Title, sizeof(state.txnAuth.optionalWindow2Title), "Quantity QNT"); - formatAmount(state.txnAuth.optionalWindow2Text, sizeof(state.txnAuth.optionalWindow2Text), state.txnAuth.attachmentTempInt64Num2, 0); - - snprintf(state.txnAuth.optionalWindow3Title, sizeof(state.txnAuth.optionalWindow3Title), "Recipient"); - snprintf(state.txnAuth.optionalWindow3Text, sizeof(state.txnAuth.optionalWindow3Text), APP_PREFIX); - reedSolomonEncode(state.txnAuth.recipientId, state.txnAuth.optionalWindow3Text + strlen(state.txnAuth.optionalWindow3Text)); - break; - } + uint8_t ret = formatChainAmount(state.txnAuth.windowTexts[0], + sizeof(state.txnAuth.windowTexts[0]), + state.txnAuth.amount, + state.txnAuth.chainId); + if (ret == 0) { + return R_FORMAT_AMOUNT_ERR; } - return R_SUCCESS; -} - -//Does what is says -uint8_t addToFunctionStack(const uint8_t functionNum) { - if (sizeof(state.txnAuth.functionStack) == state.txnAuth.numFunctionsOnStack) - return R_FUNCTION_STACK_FULL; - - state.txnAuth.functionStack[state.txnAuth.numFunctionsOnStack++] = functionNum; + snprintf(state.txnAuth.windowTitles[1], sizeof(state.txnAuth.windowTitles[1]), "Recipient"); + snprintf(state.txnAuth.windowTexts[1], sizeof(state.txnAuth.windowTexts[1]), APP_PREFIX); + reedSolomonEncode(state.txnAuth.recipientId, + state.txnAuth.windowTexts[1] + strlen(state.txnAuth.windowTexts[1])); return R_SUCCESS; } -//Takes bytes away from the buffer, returns 0 if there aren't enough bytes -uint8_t * readFromBuffer(const uint8_t size) { - - if (state.txnAuth.readBufferEndPos - state.txnAuth.readBufferReadOffset < size) - return 0; - - uint8_t * ret = state.txnAuth.readBuffer + state.txnAuth.readBufferReadOffset; - state.txnAuth.readBufferReadOffset += size; - state.txnAuth.numBytesRead += size; - - return ret; -} - -//This is the main parse function, it parses the main txn body and adds more function to the parse stack if needed -uint8_t parseMainTxnData() { - - uint8_t * ptr = readFromBuffer(145); - - if (0 == ptr) - return R_SEND_MORE_BYTES; - - memmove(&(state.txnAuth.chainId), ptr, sizeof(state.txnAuth.chainId)); - - ptr += sizeof(state.txnAuth.chainId); +static uint8_t setCoinExchangeScreenTexts() { + snprintf(state.txnAuth.windowTitles[0], sizeof(state.txnAuth.windowTitles[0]), "Amount"); - if ((0 == state.txnAuth.chainId) || (NUM_CHAINS < state.txnAuth.chainId)) //note: we do +1 here because ardor start with index 1 - return R_BAD_CHAIN_ID_ERR; + uint8_t ret = formatAmount( + state.txnAuth.windowTexts[0], + sizeof(state.txnAuth.windowTexts[0]), + state.txnAuth.attachment.coinExchange.quantityQNT, + chainNumDecimalsBeforePoint(state.txnAuth.attachment.coinExchange.exchangeChainId)); - - memmove(&(state.txnAuth.txnTypeAndSubType), ptr, sizeof(state.txnAuth.txnTypeAndSubType)); - - ptr += sizeof(state.txnAuth.txnTypeAndSubType); - - txnType * currentTxnType = 0; - - for (state.txnAuth.txnTypeIndex = 0; state.txnAuth.txnTypeIndex < LEN_TXN_TYPES; state.txnAuth.txnTypeIndex++) { - - currentTxnType = txnTypeAtIndex(state.txnAuth.txnTypeIndex); - - if (currentTxnType->id == state.txnAuth.txnTypeAndSubType) - break; + if (ret == 0) { + return R_FORMAT_AMOUNT_ERR; } - if (LEN_TXN_TYPES > state.txnAuth.txnTypeIndex) //goto check if the index in range before accessing the array - if (0 != currentTxnType->attachmentParsingFunctionNumber) - addToFunctionStack(currentTxnType->attachmentParsingFunctionNumber); - - if (LEN_TXN_TYPES > state.txnAuth.txnTypeIndex) { - snprintf(state.txnAuth.chainAndTxnTypeText, sizeof(state.txnAuth.chainAndTxnTypeText), "%s\n%s", chainName(state.txnAuth.chainId), txnTypeNameAtIndex(state.txnAuth.txnTypeIndex)); - } else { - snprintf(state.txnAuth.chainAndTxnTypeText, sizeof(state.txnAuth.chainAndTxnTypeText), "%s\nUnknownTxnType", chainName(state.txnAuth.chainId)); - } - - if (SUPPORTED_TXN_VERSION != *((uint8_t*)ptr)) - return R_WRONG_VERSION_ERR; - - ptr += sizeof(uint8_t); - - ptr += 4; // Skip the timestamp - ptr += 2; // Skip the deadline - ptr += 32; // Skip the sender publickey + // the existence of the chainId and exchangeId chains was already checked in transactionParser.c - memmove(&(state.txnAuth.recipientId), ptr, sizeof(state.txnAuth.recipientId)); - ptr += sizeof(state.txnAuth.recipientId); + snprintf(state.txnAuth.windowTexts[0] + ret - 1, + sizeof(state.txnAuth.windowTexts[0]) - ret - 1, + " %s", + chainName(state.txnAuth.attachment.coinExchange.exchangeChainId)); - memmove(&(state.txnAuth.amount), ptr, sizeof(state.txnAuth.amount)); - ptr += sizeof(state.txnAuth.amount); + snprintf(state.txnAuth.windowTitles[1], + sizeof(state.txnAuth.windowTitles[1]), + "Price per %s", + chainName(state.txnAuth.attachment.coinExchange.exchangeChainId)); + ret = formatAmount(state.txnAuth.windowTexts[1], + sizeof(state.txnAuth.windowTexts[1]), + state.txnAuth.attachment.coinExchange.priceNQT, + chainNumDecimalsBeforePoint(state.txnAuth.attachment.coinExchange.chainId)); - uint64_t fee = 0; - memmove(&fee, ptr, sizeof(fee)); - - uint8_t ret = formatAmount(state.txnAuth.feeText, sizeof(state.txnAuth.feeText), fee, chainNumDecimalsBeforePoint(state.txnAuth.chainId)); - - if (0 == ret) - return R_FORMAT_FEE_ERR; - - snprintf(state.txnAuth.feeText + ret - 1, sizeof(state.txnAuth.feeText) - ret - 1, " %s", chainName(state.txnAuth.chainId)); - - /* Comment unnecessary pointer movement over the last fields. Keeping for future reference. - ptr += sizeof(uint64_t); - - ptr += 64; //Skip the sig - ptr += 4; //Skip the block height - ptr += 8; //Skip the block Id - */ - - addToFunctionStack(6); - - return R_SUCCESS; -} - -//Parses a txn reference, by just skiping over the bytes :) -uint8_t parseReferencedTxn() { - - if (0 == readFromBuffer(sizeof(uint32_t) + 32)) - return R_SEND_MORE_BYTES; - - return R_SUCCESS; -} - -/** - * Parses the appendage type flag and prepares the text to show the user. - * This function is added to the function stack on init. - * - * Current known appendages types: - * MessageAppendix = 1 - * EncryptedMessageAppendix = 2 - * EncryptToSelfMessageAppendix = 4 - * PrunablePlainMessageAppendix = 8 - * PrunableEncryptedMessageAppendix = 16 - * PublicKeyAnnouncementAppendix = 32 - * PhasingAppendix = 64 - */ -uint8_t parseAppendagesFlags() { - - uint8_t * ptr = readFromBuffer(sizeof(uint32_t)); - - if (0 == ptr) - return R_SEND_MORE_BYTES; - - uint32_t appendages = 0; - - memmove(&appendages, ptr, sizeof(appendages)); - - if (0 != appendages) { - state.txnAuth.uiFlowBitfeild |= 1; //turn on the first bit - - // fallback to hex string if we found unknown appendages - if (appendages >= 1 << NUM_APPENDAGE_TYPES) { - snprintf(state.txnAuth.appendagesText, sizeof(state.txnAuth.appendagesText), "0x%08X", appendages); - } else { - char * ptr = state.txnAuth.appendagesText; - size_t free = sizeof(state.txnAuth.appendagesText); - for (uint8_t j = 0; j < NUM_APPENDAGE_TYPES; j++) { - if ((appendages & 1 << j) != 0) { - size_t len = strlen(appendageTypeName(j)); - - // special case: not enough space to show the text for all appendages, revert to bitmap - if (len + 2 > free) { // +2 for separator and null terminator - for (uint8_t i = 0; i < NUM_APPENDAGE_TYPES; i++) { - state.txnAuth.appendagesText[i] = (appendages & 1 << i) != 0 ? '1' + i : '_'; - } - state.txnAuth.appendagesText[NUM_APPENDAGE_TYPES] = '\0'; - return R_SUCCESS; - } - - snprintf(ptr, free, ptr == state.txnAuth.appendagesText ? "%s" : "\n%s", appendageTypeName(j)); - ptr += ptr == state.txnAuth.appendagesText ? len : len + 1; - free -= ptr == state.txnAuth.appendagesText ? len : len + 1; - } - } - } - } - - return R_SUCCESS; -} - -//Parses all the bytes until the endof the txn, since we don't parse the specifics of all the types, sometimes this is needed -uint8_t parseIngoreBytesUntilTheEnd() { - while (state.txnAuth.numBytesRead != state.txnAuth.txnSizeBytes) { - if (0 == readFromBuffer(1)) - return R_SEND_MORE_BYTES; + if (ret == 0) { + return R_FORMAT_AMOUNT_ERR; } - return R_SUCCESS; -} - -//Parses a specific type of attachment -uint8_t parseFxtCoinExchangeOrderIssueOrCoinExchangeOrderIssueAttachment() { - - state.txnAuth.attachmentTempInt32Num1 = 0; //chaidId - state.txnAuth.attachmentTempInt32Num2 = 0; //exchangeChain - state.txnAuth.attachmentTempInt64Num1 = 0; //quantity - state.txnAuth.attachmentTempInt64Num2 = 0; //price - - uint8_t * ptr = readFromBuffer(sizeof(uint8_t) + sizeof(state.txnAuth.attachmentTempInt32Num1) * 2 + sizeof(state.txnAuth.attachmentTempInt64Num1) * 2); - if (0 == ptr) - return R_SEND_MORE_BYTES; - - if (1 != *ptr) - return R_UNSUPPORTED_ATTACHMENT_VERSION; - - ptr += 1; - - memmove(&state.txnAuth.attachmentTempInt32Num1, ptr, sizeof(state.txnAuth.attachmentTempInt32Num1)); - ptr += sizeof(state.txnAuth.attachmentTempInt32Num1); - - if (NUM_CHAINS < state.txnAuth.attachmentTempInt32Num1) - return R_BAD_CHAIN_ID_ERR; - - memmove(&state.txnAuth.attachmentTempInt32Num2, ptr, sizeof(state.txnAuth.attachmentTempInt32Num2)); - ptr += sizeof(state.txnAuth.attachmentTempInt32Num2); - - if (NUM_CHAINS < state.txnAuth.attachmentTempInt32Num2) - return R_BAD_CHAIN_ID_ERR; - - memmove(&state.txnAuth.attachmentTempInt64Num1, ptr, sizeof(state.txnAuth.attachmentTempInt64Num1)); - ptr += sizeof(state.txnAuth.attachmentTempInt64Num1); - - memmove(&state.txnAuth.attachmentTempInt64Num2, ptr, sizeof(state.txnAuth.attachmentTempInt64Num2)); + snprintf(state.txnAuth.windowTexts[1] + ret - 1, + sizeof(state.txnAuth.windowTexts[1]) - ret - 1, + " %s", + chainName(state.txnAuth.attachment.coinExchange.chainId)); return R_SUCCESS; } -//Parses a specific type of attachment -uint8_t parseAskOrderPlacementAttachment() { - - state.txnAuth.attachmentTempInt64Num1 = 0; - state.txnAuth.attachmentTempInt64Num2 = 0; - state.txnAuth.attachmentTempInt64Num3 = 0; - - uint8_t * ptr = readFromBuffer(sizeof(state.txnAuth.attachmentTempInt64Num1) * 3); - if (0 == ptr) - return R_SEND_MORE_BYTES; - - memmove(&state.txnAuth.attachmentTempInt64Num1, ptr, sizeof(state.txnAuth.attachmentTempInt64Num1)); - ptr += sizeof(state.txnAuth.attachmentTempInt64Num1); - - memmove(&state.txnAuth.attachmentTempInt64Num2, ptr, sizeof(state.txnAuth.attachmentTempInt64Num2)); - ptr += sizeof(state.txnAuth.attachmentTempInt64Num2); - - memmove(&state.txnAuth.attachmentTempInt64Num3, ptr, sizeof(state.txnAuth.attachmentTempInt64Num3)); - - return R_SUCCESS; -} - -uint8_t parseAssetTransferAttachment() { - - state.txnAuth.attachmentTempInt64Num1 = 0; //asset id - state.txnAuth.attachmentTempInt64Num2 = 0; //quantity - - uint8_t * ptr = readFromBuffer(sizeof(state.txnAuth.attachmentTempInt64Num1) * 2); - if (0 == ptr) - return R_SEND_MORE_BYTES; - - if (1 != *ptr) - return R_UNSUPPORTED_ATTACHMENT_VERSION; - - ptr += 1; //skip version byte - - memmove(&state.txnAuth.attachmentTempInt64Num1, ptr, sizeof(state.txnAuth.attachmentTempInt64Num1)); - ptr += sizeof(state.txnAuth.attachmentTempInt64Num1); - - memmove(&state.txnAuth.attachmentTempInt64Num2, ptr, sizeof(state.txnAuth.attachmentTempInt64Num2)); - +static uint8_t setAssetOrderScreenTexts() { + printWindowAmount(0, "Asset Id", state.txnAuth.attachment.assetOrderPlacement.assetId); + printWindowAmount(1, "Quantity QNT", state.txnAuth.attachment.assetOrderPlacement.quantityQNT); + printWindowAmount(2, "Price NQT", state.txnAuth.attachment.assetOrderPlacement.priceNQT); return R_SUCCESS; } -//Addes bytes to the read buffer -//@param newData: ptr to the data -//@param numBytes: number of bytes in the data -//return R_SUCCESS on success, R_NO_SPACE_BUFFER_TOO_SMALL othereize -uint8_t addToReadBuffer(const uint8_t * const newData, const uint8_t numBytes) { - - for (uint8_t i = 0; i < state.txnAuth.readBufferEndPos - state.txnAuth.readBufferReadOffset; i++) - state.txnAuth.readBuffer[i] = state.txnAuth.readBuffer[i + state.txnAuth.readBufferReadOffset]; +static uint8_t setAssetTransferScreenTexts() { + printWindowAmount(0, "Asset Id", state.txnAuth.attachment.assetTransfer.assetId); + printWindowAmount(1, "Quantity QNT", state.txnAuth.attachment.assetTransfer.quantityQNT); - memset(state.txnAuth.readBuffer + state.txnAuth.readBufferEndPos - state.txnAuth.readBufferReadOffset, 0, state.txnAuth.readBufferReadOffset); //set to 0, just for saftey - - state.txnAuth.readBufferEndPos -= state.txnAuth.readBufferReadOffset; - state.txnAuth.readBufferReadOffset = 0; - - if (state.txnAuth.readBufferEndPos + numBytes > sizeof(state.txnAuth.readBuffer)) - return R_NO_SPACE_BUFFER_TOO_SMALL; - - cx_hash(&state.txnAuth.hashstate.header, 0, newData, numBytes, 0, 0); - - memcpy(state.txnAuth.readBuffer + state.txnAuth.readBufferEndPos, newData, numBytes); - state.txnAuth.readBufferEndPos += numBytes; + snprintf(state.txnAuth.windowTitles[2], sizeof(state.txnAuth.windowTitles[2]), "Recipient"); + snprintf(state.txnAuth.windowTexts[2], sizeof(state.txnAuth.windowTexts[2]), APP_PREFIX); + reedSolomonEncode(state.txnAuth.recipientId, + state.txnAuth.windowTexts[2] + strlen(state.txnAuth.windowTexts[2])); return R_SUCCESS; } -//Since we can't store function pointers in the functionstack, we store number and then call the following function -//to make a call to the corresponding function -uint8_t callFunctionNumber(const uint8_t functionNum) { - - switch (functionNum) { - case 1: - return parseMainTxnData(); - case 2: - return parseAppendagesFlags(); - case 3: - return parseReferencedTxn(); - case 4: - return parseFxtCoinExchangeOrderIssueOrCoinExchangeOrderIssueAttachment(); - case 5: - return parseAskOrderPlacementAttachment(); - case 6: - return parseIngoreBytesUntilTheEnd(); - case 7: - return parseAssetTransferAttachment(); - } - - return R_PARSE_FUNCTION_NOT_FOUND; -} - -//This function manages the parsing of the readBuffer with functionStack functions -//If there aren't enough bytes in the read buffer it returns R_SEND_MORE_BYTES -//which will be sent back to the user -uint8_t parseFromStack() { - - while (true) { - - if (0 == state.txnAuth.numFunctionsOnStack) { - - if (state.txnAuth.readBufferEndPos != state.txnAuth.readBufferReadOffset) - return R_NOT_ALL_BYTES_READ; - - uint8_t ret = setScreenTexts(); +// This function formats trxn data into text memebers of the state which the UI flow will read from +// Returns: Success iff everything is good, otherwise probably some kind of formating error +uint8_t setScreenTexts() { + if (state.txnAuth.txnTypeIndex < LEN_TXN_TYPES) { + switch (state.txnAuth.txnTypeAndSubType) { + case TX_TYPE_ORDINARY_PAYMENT: + case TX_TYPE_FXT_PAYMENT: + return setPaymentsScreenTexts(); - if (R_SUCCESS != ret) - return ret; + case TX_TYPE_FXT_COIN_EXCHANGE_ORDER_ISSUE: + case TX_TYPE_COIN_EXCHANGE_ORDER_ISSUE: + return setCoinExchangeScreenTexts(); - showScreen(); + case TX_TYPE_ASK_ORDER_PLACEMENT: + case TX_TYPE_BID_ORDER_PLACEMENT: + return setAssetOrderScreenTexts(); - return R_SHOW_DISPLAY; + case TX_TYPE_ASSET_TRANSFER: + return setAssetTransferScreenTexts(); } - - uint8_t ret = callFunctionNumber(state.txnAuth.functionStack[0]); - - if (R_SEND_MORE_BYTES == ret) - return ret; - - uint8_t tempBuffer[FUNCTION_STACK_SIZE - 1]; - memmove(tempBuffer, state.txnAuth.functionStack + 1, sizeof(tempBuffer)); - memmove(state.txnAuth.functionStack, tempBuffer, sizeof(tempBuffer)); - state.txnAuth.functionStack[sizeof(state.txnAuth.functionStack) - 1] = 0; - state.txnAuth.numFunctionsOnStack--; - - if (R_SUCCESS == ret) - continue; - - return ret; } -} + return R_SUCCESS; +} -//This is the function used to sign the hash of the txn +// This is the function used to sign the hash of the txn //@param txnSha256 - ptr to 32 byte sha256 of the txn //@param derivationPath - ptr to the derivation path buffer //@param derivationPathLengthInUints32 - length of the derivation path buffer @@ -838,149 +244,129 @@ uint8_t parseFromStack() { //@param outException out - ptr to where to write the exception if it happends //@returns R_SUCCESS iff success else the appropriate error code is returned -uint8_t signTxn(const uint8_t * const derivationPath, const uint8_t derivationPathLengthInUints32, - uint8_t * const destBuffer, uint16_t * const outException) { - - uint8_t keySeed[32]; memset(keySeed, 0, sizeof(keySeed)); +uint8_t signTxn(const uint8_t* const derivationPath, + const uint8_t derivationPathLengthInUints32, + uint8_t* const destBuffer, + uint16_t* const outException) { + uint8_t keySeed[32]; + explicit_bzero(keySeed, sizeof(keySeed)); uint8_t ret = 0; - if (R_SUCCESS != (ret = ardorKeys(derivationPath, derivationPathLengthInUints32, keySeed, 0, 0, 0, outException))) { - memset(keySeed, 0, sizeof(keySeed)); + ret = ardorKeys(derivationPath, derivationPathLengthInUints32, keySeed, 0, 0, 0, outException); + if (ret != R_SUCCESS) { + explicit_bzero(keySeed, sizeof(keySeed)); return ret; } - uint8_t finalTxnSha256[32]; - cx_hash(&state.txnAuth.hashstate.header, CX_LAST, 0, 0, finalTxnSha256, sizeof(finalTxnSha256)); + uint8_t txHash[32]; + cx_err_t err = + cx_hash_no_throw(&state.txnAuth.hashstate.header, CX_LAST, 0, 0, txHash, sizeof(txHash)); + if (err != CX_OK) { + return R_CXLIB_ERROR; + } + + // sign msg should only use the first 32 bytes of keyseed + err = signMsg(keySeed, txHash, destBuffer); + if (err != CX_OK) { + return R_CXLIB_ERROR; + } - //sign msg should only use the first 32 bytes of keyseed - signMsg(keySeed, finalTxnSha256, destBuffer); //is a void function, no ret value to check against - - memset(finalTxnSha256, 0, sizeof(finalTxnSha256)); //for security - memset(keySeed, 0, sizeof(keySeed)); + // clean buffers + explicit_bzero(txHash, sizeof(txHash)); + explicit_bzero(keySeed, sizeof(keySeed)); return R_SUCCESS; } -//This is the main command handler, it checks that params are in the right size, -//and manages calls to initTxnAuthState(), signTxn(), addToReadBuffer(), parseFromStack() +//// HANDLER MAIN FUNCTIONS -//Since this is a callback function, and this handler manages state, it's this function's reposibility to call initTxnAuthState -//Every time we get some sort of an error -void authAndSignTxnHandlerHelper(const uint8_t p1, const uint8_t p2, const uint8_t * const dataBuffer, const uint8_t dataLength, - uint8_t * const flags, uint8_t * const tx, const bool isLastCommandDifferent) { +static int p1InitContinueCommon(const command_t* const cmd) { + state.txnAuth.state = AUTH_STATE_PARSING; - if (dataLength < 1) { - initTxnAuthState(); - G_io_apdu_buffer[(*tx)++] = R_WRONG_SIZE_ERR; - return; - } + uint8_t ret = addToReadBuffer(cmd->data, cmd->lc); + if (ret != R_SUCCESS) { + return cleanAndReturn(ret); + } - if (P1_SIGN == (p1 & 0x03)) { + ret = parseTransaction(&setScreenTexts); - if (isLastCommandDifferent) { - initTxnAuthState(); - G_io_apdu_buffer[(*tx)++] = R_TXN_UNAUTHORIZED; - return; - } + if (ret == R_SHOW_DISPLAY) { + signTransactionScreen(); + return 0; + } - uint8_t derivationParamLengthInBytes = dataLength; - - if ((MIN_DERIVATION_LENGTH * sizeof(uint32_t) > dataLength) || (MAX_DERIVATION_LENGTH * sizeof(uint32_t) < dataLength) || (0 != derivationParamLengthInBytes % sizeof(uint32_t))) { - initTxnAuthState(); - G_io_apdu_buffer[(*tx)++] = R_WRONG_SIZE_ERR; - return; - } + if ((ret != R_SEND_MORE_BYTES) && (ret != R_FINISHED)) { + cleanState(); + } - if (!state.txnAuth.txnPassedAutherization) { - initTxnAuthState(); - G_io_apdu_buffer[(*tx)++] = R_TXN_UNAUTHORIZED; - return; - } + return io_send_return2(R_SUCCESS, ret); +} - uint16_t exception = 0; +static int p1InitHandler(const command_t* const cmd) { + initTxnAuthState(); - G_io_apdu_buffer[(*tx)++] = R_SUCCESS; + state.txnAuth.txnSizeBytes = ((cmd->p1 & TX_SIZE_P1_MASK) << TX_SIZE_P1_SHIFT) + cmd->p2; - uint8_t ret = signTxn(dataBuffer, derivationParamLengthInBytes / 4, G_io_apdu_buffer + 1, &exception); + if (state.txnAuth.txnSizeBytes < BASE_TRANSACTION_SIZE) { + return io_send_response_pointer(&(const uint8_t){R_TXN_SIZE_TOO_SMALL}, 1, SW_OK); + } - initTxnAuthState(); + return p1InitContinueCommon(cmd); +} - if (R_SUCCESS == ret) { - *tx += 64; - } else { - *tx -= 1; - G_io_apdu_buffer[(*tx)++] = ret; +static int p1ContinueHandler(const command_t* const cmd) { + if (state.txnAuth.state == AUTH_STATE_USER_AUTHORIZED) { + return cleanAndReturn(R_NOT_ALL_BYTES_USED); + } - if (R_KEY_DERIVATION_EX == ret) { - G_io_apdu_buffer[(*tx)++] = exception >> 8; - G_io_apdu_buffer[(*tx)++] = exception & 0xFF; - } - } - } else if ((P1_INIT == (p1 & 0x03)) || (P1_CONTINUE == (p1 & 0x03))) { - - if (P1_INIT != (p1 & 0x03)) { - - if (isLastCommandDifferent) { - initTxnAuthState(); - G_io_apdu_buffer[(*tx)++] = R_ERR_NO_INIT_CANT_CONTINUE; - return; - } - - if (state.txnAuth.txnPassedAutherization) { - initTxnAuthState(); - G_io_apdu_buffer[(*tx)++] = R_NOT_ALL_BYTES_USED; - return; - } - - if (state.txnAuth.isClean) { - initTxnAuthState(); - G_io_apdu_buffer[(*tx)++] = R_ERR_NO_INIT_CANT_CONTINUE; - return; - } - } else { - initTxnAuthState(); - - state.txnAuth.txnSizeBytes = ((p1 & 0b11111100) << 6) + p2; - - if (145 > state.txnAuth.txnSizeBytes) { - G_io_apdu_buffer[(*tx)++] = R_TXN_SIZE_TOO_SMALL; - return; - } - } + if (state.txnAuth.state == AUTH_STATE_INIT) { + return cleanAndReturn(R_ERR_NO_INIT_CANT_CONTINUE); + } - state.txnAuth.isClean = false; + return p1InitContinueCommon(cmd); +} - uint8_t ret = addToReadBuffer(dataBuffer, dataLength); +static int p1SignHandler(const command_t* const cmd) { + if (state.txnAuth.state != AUTH_STATE_USER_AUTHORIZED) { + return cleanAndReturn(R_TXN_UNAUTHORIZED); + } - if (R_SUCCESS != ret) { - G_io_apdu_buffer[(*tx)++] = ret; - return; - } + // dataLength is the derivation path length in bytes + if (!isValidDerivationPathLength(cmd->lc)) { + return cleanAndReturn(R_WRONG_SIZE_ERR); + } - ret = parseFromStack(); + uint16_t exception = 0; + uint8_t buffer[1 + SIGNATURE_SIZE]; + buffer[0] = R_SUCCESS; + uint8_t ret = signTxn(cmd->data, cmd->lc / 4, buffer + 1, &exception); - if (!((R_SEND_MORE_BYTES == ret) || (R_FINISHED == ret) || (R_SHOW_DISPLAY == ret))) - initTxnAuthState(); + cleanState(); - if (R_SHOW_DISPLAY == ret) { - *flags |= IO_ASYNCH_REPLY; - } else { - G_io_apdu_buffer[(*tx)++] = R_SUCCESS; - G_io_apdu_buffer[(*tx)++] = ret; - } + if (ret == R_SUCCESS) { + return io_send_response_pointer(buffer, sizeof(buffer), SW_OK); + } else if (ret == R_KEY_DERIVATION_EX) { + return io_send_return3(ret, exception >> 8, exception & 0xFF); } else { - G_io_apdu_buffer[(*tx)++] = R_UNKNOWN_CMD_PARAM_ERR; + return io_send_return1(ret); } } -void authAndSignTxnHandler(const uint8_t p1, const uint8_t p2, const uint8_t * const dataBuffer, const uint8_t dataLength, - uint8_t * const flags, uint8_t * const tx, const bool isLastCommandDifferent) { - - authAndSignTxnHandlerHelper(p1, p2, dataBuffer, dataLength, flags, tx, isLastCommandDifferent); - - if (0 == ((*flags) & IO_ASYNCH_REPLY)) { - G_io_apdu_buffer[(*tx)++] = 0x90; - G_io_apdu_buffer[(*tx)++] = 0x00; +// This is the main command handler, it checks that params are in the right size, +// and manages calls to initTxnAuthState(), signTxn(), addToReadBuffer(), parseTransaction() +// Since this is a callback function, and this handler manages state, it's this function's +// reposibility to call initTxnAuthState Every time we get some sort of an error +int authAndSignTxnHandler(const command_t* const cmd) { + if (cmd->lc < 1) { + return cleanAndReturn(R_WRONG_SIZE_ERR); + } else if ((cmd->p1 & MODE_P1_MASK) == P1_INIT) { + return p1InitHandler(cmd); + } else if ((cmd->p1 & MODE_P1_MASK) == P1_CONTINUE) { + return p1ContinueHandler(cmd); + } else if ((cmd->p1 & MODE_P1_MASK) == P1_SIGN) { + return p1SignHandler(cmd); + } else { + return io_send_return1(R_UNKNOWN_CMD_PARAM_ERR); } } diff --git a/src/config.c b/src/config.c index 83b833c..eabf136 100644 --- a/src/config.c +++ b/src/config.c @@ -1,29 +1,50 @@ - - -//This file holds most of the CONSTANTS used in the APP -//TXN_TYPES is configured in txnTypesList.c, it's there cuz the list is auto-generated from some other java file in order to sync between projects +/******************************************************************************* + * (c) 2019 Haim Bender + * (c) 2021-2023 Jelurida IP B.V. + * + * + * 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. + ********************************************************************************/ + +// This file holds most of the CONSTANTS used in the APP +// TXN_TYPES is configured in txnTypesList.c, it's there cuz the list is auto-generated from some +// other java file in order to sync between projects #include #include #include "config.h" - -//This configures the supported chain types, chainId, name and amount of decimals to the right of the point -const chainType CHAINS[] = {{0x00000001, "Ardor", 8}, {0x00000002, "Ignis", 8}, {0x00000003, "AEUR", 4}, {0x00000004, "BITS", 8}, {0x00000005, "MPG", 8}, {0x00000006, "GPS", 4}}; +// This configures the supported chain types, chainId, name and amount of decimals to the right of +// the point +// Some chains are no longer supported, but are kept here as the array index is used in the code +const chainType CHAINS[] = {{0x00000001, "ARDR", 8}, + {0x00000002, "IGNIS", 8}, + {0x00000003, "AEUR", 4}, // no longer used + {0x00000004, "BITS", 8}, + {0x00000005, "MPG", 8}, // no longer used + {0x00000006, "GPS", 4}}; const uint8_t NUM_CHAINS = sizeof(CHAINS) / sizeof(CHAINS[0]); const uint8_t SUPPORTED_TXN_VERSION = 1; -const appendageType APPENDAGE_TYPES[] = { - {"Message"}, - {"EncryptedMsg"}, - {"NoteToSelf"}, - {"PrunableMessage"}, - {"PrunableEncMsg"}, - {"PublicKeyAnnoun"}, - {"Phasing"} -}; +const appendageType APPENDAGE_TYPES[] = {{"Message"}, + {"EncryptedMsg"}, + {"NoteToSelf"}, + {"PrunableMessage"}, + {"PrunableEncMsg"}, + {"PublicKeyAnnoun"}, + {"Phasing"}}; const uint8_t NUM_APPENDAGE_TYPES = sizeof(APPENDAGE_TYPES) / sizeof(APPENDAGE_TYPES[0]); const uint8_t ARDOR_SPECIAL_IDENTIFIER[] = {0xba, 0xbe, 0x00}; diff --git a/src/config.h b/src/config.h index 089bec7..e775650 100644 --- a/src/config.h +++ b/src/config.h @@ -1,16 +1,34 @@ +/******************************************************************************* + * (c) 2019 Haim Bender + * (c) 2021-2023 Jelurida IP B.V. + * + * + * 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 - -//This is the header for different types of consts and configurations, the actual values are set in config.c +// This is the header for different types of consts and configurations, the actual values are set in +// config.c typedef struct { uint32_t chainId; - char * name; + const char* name; uint8_t numDecimalsBeforePoint; } chainType; typedef struct { - char * name; + const char* name; } appendageType; extern const chainType CHAINS[]; @@ -25,10 +43,25 @@ extern const uint8_t ARDOR_SPECIAL_IDENTIFIER_LEN; extern const uint16_t VERSION; extern const uint8_t VERSION_FLAGS; +#define ARRAY_COUNT(array) (sizeof(array) / sizeof(array[0])) -//must make this a define instead of static const, because some array declirations are dependant on this size #define MIN_DERIVATION_LENGTH 3 #define MAX_DERIVATION_LENGTH 20 +#define PUBLIC_KEY_SIZE 32 +#define SIGNATURE_SIZE 64 +#define TIMESTAMP_SIZE 4 + #define FUNCTION_STACK_SIZE 30 -#define IV_SIZE 16 +#define BASE_TRANSACTION_SIZE 145 + +// transaction types and subtypes definition +// note: you have to write the type and subtype in reverse, because of little endian buffer +// representation an big endian C code representation +#define TX_TYPE_ORDINARY_PAYMENT 0x0000 +#define TX_TYPE_FXT_PAYMENT 0x00fe +#define TX_TYPE_FXT_COIN_EXCHANGE_ORDER_ISSUE 0x00fc +#define TX_TYPE_COIN_EXCHANGE_ORDER_ISSUE 0x000b +#define TX_TYPE_ASK_ORDER_PLACEMENT 0x0202 +#define TX_TYPE_BID_ORDER_PLACEMENT 0x0302 +#define TX_TYPE_ASSET_TRANSFER 0x0102 diff --git a/src/curve25519_i64.c b/src/curve25519_i64.c index 263e3e7..04ab9a8 100644 --- a/src/curve25519_i64.c +++ b/src/curve25519_i64.c @@ -9,7 +9,6 @@ #include #include "curve25519_i64.h" - typedef int32_t i25519[10]; typedef const int32_t *i25519ptr; typedef const uint8_t *srcptr; @@ -18,71 +17,84 @@ typedef uint8_t *dstptr; typedef struct expstep expstep; struct expstep { - unsigned nsqr; - unsigned muli; + unsigned nsqr; + unsigned muli; }; - /********************* constants *********************/ -const k25519 -zero25519 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, -prime25519 = { 237, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 127 }, -order25519 = { 237, 211, 245, 92, 26, 99, 18, 88, 214, 156, 247, 162, 222, 249, - 222, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16 }; +const k25519 zero25519 = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + prime25519 = {237, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 127}, + order25519 = {237, 211, 245, 92, 26, 99, 18, 88, 214, 156, 247, + 162, 222, 249, 222, 20, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 16}; /* smallest multiple of the order that's >= 2^255 */ -static const k25519 -order_times_8 = { 104, 159, 174, 231, 210, 24, 147, 192, 178, 230, 188, 23, - 245, 206, 247, 166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128 }; +static const k25519 order_times_8 = {104, 159, 174, 231, 210, 24, 147, 192, 178, 230, 188, + 23, 245, 206, 247, 166, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 128}; /* constants 2Gy and 1/(2Gy) */ -static const i25519 -base_2y = { 39999547, 18689728, 59995525, 1648697, 57546132, - 24010086, 19059592, 5425144, 63499247, 16420658 }, -base_r2y = { 5744, 8160848, 4790893, 13779497, 35730846, - 12541209, 49101323, 30047407, 40071253, 6226132 }; - +static const i25519 base_2y = {39999547, + 18689728, + 59995525, + 1648697, + 57546132, + 24010086, + 19059592, + 5425144, + 63499247, + 16420658}, + base_r2y = {5744, + 8160848, + 4790893, + 13779497, + 35730846, + 12541209, + 49101323, + 30047407, + 40071253, + 6226132}; /********************* radix 2^8 math *********************/ static void cpy32(k25519 d, const k25519 s) { - int i; - for (i = 0; i < 32; i++) - d[i] = s[i]; + int i; + for (i = 0; i < 32; i++) { + d[i] = s[i]; + } } /* p[m..n+m-1] = q[m..n+m-1] + z * x */ /* n is the size of x */ /* n+m is the size of p and q */ -static inline -int mula_small(dstptr p, srcptr q, unsigned m, srcptr x, unsigned n, int z) { - int v = 0; - unsigned i; - for (i = 0; i < n; i++) { - p[i+m] = v += q[i+m] + z * x[i]; - v >>= 8; - } - return v; +static inline int mula_small(dstptr p, srcptr q, unsigned m, srcptr x, unsigned n, int z) { + int v = 0; + unsigned i; + for (i = 0; i < n; i++) { + p[i + m] = v += q[i + m] + z * x[i]; + v >>= 8; + } + return v; } /* p += x * y * z where z is a small integer * x is size 32, y is size t, p is size 32+t * y is allowed to overlap with p+32 if you don't care about the upper half */ static int mula32(dstptr p, srcptr x, srcptr y, unsigned t, int z) { - const unsigned n = 31; - int w = 0; - unsigned i; - for (i = 0; i < t; i++) { - int zy = z * y[i]; - p[i+n] = w += mula_small(p,p, i, x, n, zy) + p[i+n] + zy * x[n]; - w >>= 8; - } - p[i+n] += w; - return w >> 8; + const unsigned n = 31; + int w = 0; + unsigned i; + for (i = 0; i < t; i++) { + int zy = z * y[i]; + p[i + n] = w += mula_small(p, p, i, x, n, zy) + p[i + n] + zy * x[n]; + w >>= 8; + } + p[i + n] += w; + return w >> 8; } /* divide r (size n) by d (size t), returning quotient q and remainder r @@ -91,30 +103,30 @@ static int mula32(dstptr p, srcptr x, srcptr y, unsigned t, int z) { * requires that r[-1] and d[-1] are valid memory locations * q may overlap with r+t */ static void divmod(dstptr q, dstptr r, int n, srcptr d, int t) { - int rn = 0; - int dt = ((d[t - 1] & 0xFF) << 8); - if (t > 1) { - dt |= (d[t - 2] & 0xFF); - } - while (n-- >= t) { - int z = (rn << 16) | ((r[n] & 0xFF) << 8); - if (n > 0) { - z |= (r[n - 1] & 0xFF); + int rn = 0; + int dt = ((d[t - 1] & 0xFF) << 8); + if (t > 1) { + dt |= (d[t - 2] & 0xFF); } - z /= dt; - rn += mula_small(r, r, n - t + 1, d, t, -z); - q[n - t + 1] = ((z + rn) & 0xFF); /* rn is 0 or -1 (underflow) */ - mula_small(r, r, n - t + 1, d, t, -rn); - rn = (r[n] & 0xFF); - r[n] = 0; - } - r[t - 1] = rn; + while (n-- >= t) { + int z = (rn << 16) | ((r[n] & 0xFF) << 8); + if (n > 0) { + z |= (r[n - 1] & 0xFF); + } + z /= dt; + rn += mula_small(r, r, n - t + 1, d, t, -z); + q[n - t + 1] = ((z + rn) & 0xFF); /* rn is 0 or -1 (underflow) */ + mula_small(r, r, n - t + 1, d, t, -rn); + rn = (r[n] & 0xFF); + r[n] = 0; + } + r[t - 1] = rn; } static inline unsigned numsize(srcptr x, unsigned n) { - while (n-- && !x[n]) - ; - return n+1; + while (n-- && !x[n]) + ; + return n + 1; } /* Returns x if a contains the gcd, y if b. @@ -123,36 +135,39 @@ static inline unsigned numsize(srcptr x, unsigned n) { * x and y must have 64 bytes space for temporary use. * requires that a[-1] and b[-1] are valid memory locations */ static dstptr egcd32(dstptr x, dstptr y, dstptr a, dstptr b) { - int an, bn = 32, qn, i; - for (i = 0; i < 32; i++) - x[i] = y[i] = 0; - x[0] = 1; - an = numsize(a, 32); - if (an == 0) - return y; /* division by zero */ - uint8_t temp[31] = { 0 }; - while (42) { - qn = bn - an + 1; - divmod(temp, b, bn, a, an); - bn = numsize(b, bn); - if (bn == 0) - return x; - mula32(y, x, temp, qn, -1); - - qn = an - bn + 1; - divmod(temp, a, an, b, bn); - an = numsize(a, an); - if (an == 0) - return y; - mula32(x, y, temp, qn, -1); - } + int an, bn = 32, qn, i; + for (i = 0; i < 32; i++) { + x[i] = y[i] = 0; + } + x[0] = 1; + an = numsize(a, 32); + if (an == 0) { + return y; /* division by zero */ + } + uint8_t temp[31] = {0}; + while (42) { + qn = bn - an + 1; + divmod(temp, b, bn, a, an); + bn = numsize(b, bn); + if (bn == 0) { + return x; + } + mula32(y, x, temp, qn, -1); + + qn = an - bn + 1; + divmod(temp, a, an, b, bn); + an = numsize(a, an); + if (an == 0) { + return y; + } + mula32(x, y, temp, qn, -1); + } } /********************* radix 2^25.5 GF(2^255-19) math *********************/ -#define P25 33554431 /* (1 << 25) - 1 */ -#define P26 67108863 /* (1 << 26) - 1 */ - +#define P25 33554431 /* (1 << 25) - 1 */ +#define P26 67108863 /* (1 << 26) - 1 */ /* debugging code */ @@ -182,342 +197,363 @@ static void check_reduced(const char *where, const i25519 x) { #define check_reduced(w, x) #endif - /* convenience macros */ #define M(i) ((uint32_t) m[i]) #define X(i) ((int64_t) x[i]) -#define m64(arg1,arg2) ((int64_t) (arg1) * (arg2)) - +#define m64(arg1, arg2) ((int64_t)(arg1) * (arg2)) /* Convert to internal format from little-endian byte format */ static void unpack25519(i25519 x, const k25519 m) { - x[0] = M( 0) | M( 1)<<8 | M( 2)<<16 | (M( 3)& 3)<<24; - x[1] = (M( 3)&~ 3)>>2 | M( 4)<<6 | M( 5)<<14 | (M( 6)& 7)<<22; - x[2] = (M( 6)&~ 7)>>3 | M( 7)<<5 | M( 8)<<13 | (M( 9)&31)<<21; - x[3] = (M( 9)&~31)>>5 | M(10)<<3 | M(11)<<11 | (M(12)&63)<<19; - x[4] = (M(12)&~63)>>6 | M(13)<<2 | M(14)<<10 | M(15) <<18; - x[5] = M(16) | M(17)<<8 | M(18)<<16 | (M(19)& 1)<<24; - x[6] = (M(19)&~ 1)>>1 | M(20)<<7 | M(21)<<15 | (M(22)& 7)<<23; - x[7] = (M(22)&~ 7)>>3 | M(23)<<5 | M(24)<<13 | (M(25)&15)<<21; - x[8] = (M(25)&~15)>>4 | M(26)<<4 | M(27)<<12 | (M(28)&63)<<20; - x[9] = (M(28)&~63)>>6 | M(29)<<2 | M(30)<<10 | M(31) <<18; - check_reduced("unpack output", x); + // clang-format off + x[0] = M( 0) | M( 1)<<8 | M( 2)<<16 | (M( 3)& 3)<<24; + x[1] = (M( 3)&~ 3)>>2 | M( 4)<<6 | M( 5)<<14 | (M( 6)& 7)<<22; + x[2] = (M( 6)&~ 7)>>3 | M( 7)<<5 | M( 8)<<13 | (M( 9)&31)<<21; + x[3] = (M( 9)&~31)>>5 | M(10)<<3 | M(11)<<11 | (M(12)&63)<<19; + x[4] = (M(12)&~63)>>6 | M(13)<<2 | M(14)<<10 | M(15) <<18; + x[5] = M(16) | M(17)<<8 | M(18)<<16 | (M(19)& 1)<<24; + x[6] = (M(19)&~ 1)>>1 | M(20)<<7 | M(21)<<15 | (M(22)& 7)<<23; + x[7] = (M(22)&~ 7)>>3 | M(23)<<5 | M(24)<<13 | (M(25)&15)<<21; + x[8] = (M(25)&~15)>>4 | M(26)<<4 | M(27)<<12 | (M(28)&63)<<20; + x[9] = (M(28)&~63)>>6 | M(29)<<2 | M(30)<<10 | M(31) <<18; + // clang-format on + check_reduced("unpack output", x); } - /* Check if reduced-form input >= 2^255-19 */ static inline int is_overflow(const i25519 x) { - return ((x[0] > P26-19) & ((x[1] & x[3] & x[5] & x[7] & x[9]) == P25) & - ((x[2] & x[4] & x[6] & x[8]) == P26) - ) | (x[9] > P25); + return ((x[0] > P26 - 19) & ((x[1] & x[3] & x[5] & x[7] & x[9]) == P25) & + ((x[2] & x[4] & x[6] & x[8]) == P26)) | + (x[9] > P25); } - /* Convert from internal format to little-endian byte format. The * number must be in a reduced form which is output by the following ops: * unpack, mul, sqr * set -- if input in range 0 .. P25 * If you're unsure if the number is reduced, first multiply it by 1. */ static void pack25519(const i25519 x, k25519 m) { - int32_t ld = 0, ud = 0; - int64_t t; - check_reduced("pack input", x); - ld = is_overflow(x) - (x[9] < 0); - ud = ld * -(P25+1); - ld *= 19; - t = ld + X(0) + (X(1) << 26); - m[ 0] = t; m[ 1] = t >> 8; m[ 2] = t >> 16; m[ 3] = t >> 24; - t = (t >> 32) + (X(2) << 19); - m[ 4] = t; m[ 5] = t >> 8; m[ 6] = t >> 16; m[ 7] = t >> 24; - t = (t >> 32) + (X(3) << 13); - m[ 8] = t; m[ 9] = t >> 8; m[10] = t >> 16; m[11] = t >> 24; - t = (t >> 32) + (X(4) << 6); - m[12] = t; m[13] = t >> 8; m[14] = t >> 16; m[15] = t >> 24; - t = (t >> 32) + X(5) + (X(6) << 25); - m[16] = t; m[17] = t >> 8; m[18] = t >> 16; m[19] = t >> 24; - t = (t >> 32) + (X(7) << 19); - m[20] = t; m[21] = t >> 8; m[22] = t >> 16; m[23] = t >> 24; - t = (t >> 32) + (X(8) << 12); - m[24] = t; m[25] = t >> 8; m[26] = t >> 16; m[27] = t >> 24; - t = (t >> 32) + ((X(9) + ud) << 6); - m[28] = t; m[29] = t >> 8; m[30] = t >> 16; m[31] = t >> 24; + int32_t ld = 0, ud = 0; + int64_t t; + check_reduced("pack input", x); + ld = is_overflow(x) - (x[9] < 0); + ud = ld * -(P25 + 1); + ld *= 19; + t = ld + X(0) + (X(1) << 26); + m[0] = t; + m[1] = t >> 8; + m[2] = t >> 16; + m[3] = t >> 24; + t = (t >> 32) + (X(2) << 19); + m[4] = t; + m[5] = t >> 8; + m[6] = t >> 16; + m[7] = t >> 24; + t = (t >> 32) + (X(3) << 13); + m[8] = t; + m[9] = t >> 8; + m[10] = t >> 16; + m[11] = t >> 24; + t = (t >> 32) + (X(4) << 6); + m[12] = t; + m[13] = t >> 8; + m[14] = t >> 16; + m[15] = t >> 24; + t = (t >> 32) + X(5) + (X(6) << 25); + m[16] = t; + m[17] = t >> 8; + m[18] = t >> 16; + m[19] = t >> 24; + t = (t >> 32) + (X(7) << 19); + m[20] = t; + m[21] = t >> 8; + m[22] = t >> 16; + m[23] = t >> 24; + t = (t >> 32) + (X(8) << 12); + m[24] = t; + m[25] = t >> 8; + m[26] = t >> 16; + m[27] = t >> 24; + t = (t >> 32) + ((X(9) + ud) << 6); + m[28] = t; + m[29] = t >> 8; + m[30] = t >> 16; + m[31] = t >> 24; } /* Copy a number */ static void cpy25519(i25519 out, const i25519 in) { - int i; - for (i = 0; i < 10; i++) - out[i] = in[i]; + int i; + for (i = 0; i < 10; i++) { + out[i] = in[i]; + } } /* Set a number to value, which must be in range -185861411 .. 185861411 */ static void set25519(i25519 out, const int32_t in) { - int i; - out[0] = in; - for (i = 1; i < 10; i++) - out[i] = 0; + int i; + out[0] = in; + for (i = 1; i < 10; i++) { + out[i] = 0; + } } /* Add/subtract two numbers. The inputs must be in reduced form, and the * output isn't, so to do another addition or subtraction on the output, * first multiply it by one to reduce it. */ static void add25519(i25519 xy, const i25519 x, const i25519 y) { - xy[0] = x[0] + y[0]; xy[1] = x[1] + y[1]; - xy[2] = x[2] + y[2]; xy[3] = x[3] + y[3]; - xy[4] = x[4] + y[4]; xy[5] = x[5] + y[5]; - xy[6] = x[6] + y[6]; xy[7] = x[7] + y[7]; - xy[8] = x[8] + y[8]; xy[9] = x[9] + y[9]; + xy[0] = x[0] + y[0]; + xy[1] = x[1] + y[1]; + xy[2] = x[2] + y[2]; + xy[3] = x[3] + y[3]; + xy[4] = x[4] + y[4]; + xy[5] = x[5] + y[5]; + xy[6] = x[6] + y[6]; + xy[7] = x[7] + y[7]; + xy[8] = x[8] + y[8]; + xy[9] = x[9] + y[9]; } static void sub25519(i25519 xy, const i25519 x, const i25519 y) { - xy[0] = x[0] - y[0]; xy[1] = x[1] - y[1]; - xy[2] = x[2] - y[2]; xy[3] = x[3] - y[3]; - xy[4] = x[4] - y[4]; xy[5] = x[5] - y[5]; - xy[6] = x[6] - y[6]; xy[7] = x[7] - y[7]; - xy[8] = x[8] - y[8]; xy[9] = x[9] - y[9]; + xy[0] = x[0] - y[0]; + xy[1] = x[1] - y[1]; + xy[2] = x[2] - y[2]; + xy[3] = x[3] - y[3]; + xy[4] = x[4] - y[4]; + xy[5] = x[5] - y[5]; + xy[6] = x[6] - y[6]; + xy[7] = x[7] - y[7]; + xy[8] = x[8] - y[8]; + xy[9] = x[9] - y[9]; } /* Multiply a number by a small integer in range -185861411 .. 185861411. * The output is in reduced form, the input x need not be. x and xy may point * to the same buffer. */ static i25519ptr mul25519small(i25519 xy, const i25519 x, const int32_t y) { - register int64_t t; - check_nonred("mul small x input", x); - check_range("mul small y input", y, -185861411, 185861411); - t = m64(x[8],y); - xy[8] = t & ((1 << 26) - 1); - t = (t >> 26) + m64(x[9],y); - xy[9] = t & ((1 << 25) - 1); - t = 19 * (t >> 25) + m64(x[0],y); - xy[0] = t & ((1 << 26) - 1); - t = (t >> 26) + m64(x[1],y); - xy[1] = t & ((1 << 25) - 1); - t = (t >> 25) + m64(x[2],y); - xy[2] = t & ((1 << 26) - 1); - t = (t >> 26) + m64(x[3],y); - xy[3] = t & ((1 << 25) - 1); - t = (t >> 25) + m64(x[4],y); - xy[4] = t & ((1 << 26) - 1); - t = (t >> 26) + m64(x[5],y); - xy[5] = t & ((1 << 25) - 1); - t = (t >> 25) + m64(x[6],y); - xy[6] = t & ((1 << 26) - 1); - t = (t >> 26) + m64(x[7],y); - xy[7] = t & ((1 << 25) - 1); - t = (t >> 25) + xy[8]; - xy[8] = t & ((1 << 26) - 1); - xy[9] += (int32_t)(t >> 26); - check_reduced("mul small output", xy); - return xy; + register int64_t t; + check_nonred("mul small x input", x); + check_range("mul small y input", y, -185861411, 185861411); + t = m64(x[8], y); + xy[8] = t & ((1 << 26) - 1); + t = (t >> 26) + m64(x[9], y); + xy[9] = t & ((1 << 25) - 1); + t = 19 * (t >> 25) + m64(x[0], y); + xy[0] = t & ((1 << 26) - 1); + t = (t >> 26) + m64(x[1], y); + xy[1] = t & ((1 << 25) - 1); + t = (t >> 25) + m64(x[2], y); + xy[2] = t & ((1 << 26) - 1); + t = (t >> 26) + m64(x[3], y); + xy[3] = t & ((1 << 25) - 1); + t = (t >> 25) + m64(x[4], y); + xy[4] = t & ((1 << 26) - 1); + t = (t >> 26) + m64(x[5], y); + xy[5] = t & ((1 << 25) - 1); + t = (t >> 25) + m64(x[6], y); + xy[6] = t & ((1 << 26) - 1); + t = (t >> 26) + m64(x[7], y); + xy[7] = t & ((1 << 25) - 1); + t = (t >> 25) + xy[8]; + xy[8] = t & ((1 << 26) - 1); + xy[9] += (int32_t)(t >> 26); + check_reduced("mul small output", xy); + return xy; } /* Multiply two numbers. The output is in reduced form, the inputs need not * be. */ static i25519ptr mul25519(i25519 xy, const i25519 x, const i25519 y) { - register int64_t t; - check_nonred("mul input x", x); - check_nonred("mul input y", y); - t = m64(x[0],y[8]) + m64(x[2],y[6]) + m64(x[4],y[4]) + m64(x[6],y[2]) + - m64(x[8],y[0]) + 2 * (m64(x[1],y[7]) + m64(x[3],y[5]) + - m64(x[5],y[3]) + m64(x[7],y[1])) + 38 * - m64(x[9],y[9]); - xy[8] = t & ((1 << 26) - 1); - t = (t >> 26) + m64(x[0],y[9]) + m64(x[1],y[8]) + m64(x[2],y[7]) + - m64(x[3],y[6]) + m64(x[4],y[5]) + m64(x[5],y[4]) + - m64(x[6],y[3]) + m64(x[7],y[2]) + m64(x[8],y[1]) + - m64(x[9],y[0]); - xy[9] = t & ((1 << 25) - 1); - t = m64(x[0],y[0]) + 19 * ((t >> 25) + m64(x[2],y[8]) + m64(x[4],y[6]) - + m64(x[6],y[4]) + m64(x[8],y[2])) + 38 * - (m64(x[1],y[9]) + m64(x[3],y[7]) + m64(x[5],y[5]) + - m64(x[7],y[3]) + m64(x[9],y[1])); - xy[0] = t & ((1 << 26) - 1); - t = (t >> 26) + m64(x[0],y[1]) + m64(x[1],y[0]) + 19 * (m64(x[2],y[9]) - + m64(x[3],y[8]) + m64(x[4],y[7]) + m64(x[5],y[6]) + - m64(x[6],y[5]) + m64(x[7],y[4]) + m64(x[8],y[3]) + - m64(x[9],y[2])); - xy[1] = t & ((1 << 25) - 1); - t = (t >> 25) + m64(x[0],y[2]) + m64(x[2],y[0]) + 19 * (m64(x[4],y[8]) - + m64(x[6],y[6]) + m64(x[8],y[4])) + 2 * m64(x[1],y[1]) - + 38 * (m64(x[3],y[9]) + m64(x[5],y[7]) + - m64(x[7],y[5]) + m64(x[9],y[3])); - xy[2] = t & ((1 << 26) - 1); - t = (t >> 26) + m64(x[0],y[3]) + m64(x[1],y[2]) + m64(x[2],y[1]) + - m64(x[3],y[0]) + 19 * (m64(x[4],y[9]) + m64(x[5],y[8]) + - m64(x[6],y[7]) + m64(x[7],y[6]) + - m64(x[8],y[5]) + m64(x[9],y[4])); - xy[3] = t & ((1 << 25) - 1); - t = (t >> 25) + m64(x[0],y[4]) + m64(x[2],y[2]) + m64(x[4],y[0]) + 19 * - (m64(x[6],y[8]) + m64(x[8],y[6])) + 2 * (m64(x[1],y[3]) + - m64(x[3],y[1])) + 38 * - (m64(x[5],y[9]) + m64(x[7],y[7]) + m64(x[9],y[5])); - xy[4] = t & ((1 << 26) - 1); - t = (t >> 26) + m64(x[0],y[5]) + m64(x[1],y[4]) + m64(x[2],y[3]) + - m64(x[3],y[2]) + m64(x[4],y[1]) + m64(x[5],y[0]) + 19 * - (m64(x[6],y[9]) + m64(x[7],y[8]) + m64(x[8],y[7]) + - m64(x[9],y[6])); - xy[5] = t & ((1 << 25) - 1); - t = (t >> 25) + m64(x[0],y[6]) + m64(x[2],y[4]) + m64(x[4],y[2]) + - m64(x[6],y[0]) + 19 * m64(x[8],y[8]) + 2 * (m64(x[1],y[5]) + - m64(x[3],y[3]) + m64(x[5],y[1])) + 38 * - (m64(x[7],y[9]) + m64(x[9],y[7])); - xy[6] = t & ((1 << 26) - 1); - t = (t >> 26) + m64(x[0],y[7]) + m64(x[1],y[6]) + m64(x[2],y[5]) + - m64(x[3],y[4]) + m64(x[4],y[3]) + m64(x[5],y[2]) + - m64(x[6],y[1]) + m64(x[7],y[0]) + 19 * (m64(x[8],y[9]) + - m64(x[9],y[8])); - xy[7] = t & ((1 << 25) - 1); - t = (t >> 25) + xy[8]; - xy[8] = t & ((1 << 26) - 1); - xy[9] += (int32_t)(t >> 26); - check_reduced("mul output", xy); - return xy; + register int64_t t; + check_nonred("mul input x", x); + check_nonred("mul input y", y); + t = m64(x[0], y[8]) + m64(x[2], y[6]) + m64(x[4], y[4]) + m64(x[6], y[2]) + m64(x[8], y[0]) + + 2 * (m64(x[1], y[7]) + m64(x[3], y[5]) + m64(x[5], y[3]) + m64(x[7], y[1])) + + 38 * m64(x[9], y[9]); + xy[8] = t & ((1 << 26) - 1); + t = (t >> 26) + m64(x[0], y[9]) + m64(x[1], y[8]) + m64(x[2], y[7]) + m64(x[3], y[6]) + + m64(x[4], y[5]) + m64(x[5], y[4]) + m64(x[6], y[3]) + m64(x[7], y[2]) + m64(x[8], y[1]) + + m64(x[9], y[0]); + xy[9] = t & ((1 << 25) - 1); + t = m64(x[0], y[0]) + + 19 * ((t >> 25) + m64(x[2], y[8]) + m64(x[4], y[6]) + m64(x[6], y[4]) + m64(x[8], y[2])) + + 38 * (m64(x[1], y[9]) + m64(x[3], y[7]) + m64(x[5], y[5]) + m64(x[7], y[3]) + + m64(x[9], y[1])); + xy[0] = t & ((1 << 26) - 1); + t = (t >> 26) + m64(x[0], y[1]) + m64(x[1], y[0]) + + 19 * (m64(x[2], y[9]) + m64(x[3], y[8]) + m64(x[4], y[7]) + m64(x[5], y[6]) + + m64(x[6], y[5]) + m64(x[7], y[4]) + m64(x[8], y[3]) + m64(x[9], y[2])); + xy[1] = t & ((1 << 25) - 1); + t = (t >> 25) + m64(x[0], y[2]) + m64(x[2], y[0]) + + 19 * (m64(x[4], y[8]) + m64(x[6], y[6]) + m64(x[8], y[4])) + 2 * m64(x[1], y[1]) + + 38 * (m64(x[3], y[9]) + m64(x[5], y[7]) + m64(x[7], y[5]) + m64(x[9], y[3])); + xy[2] = t & ((1 << 26) - 1); + t = (t >> 26) + m64(x[0], y[3]) + m64(x[1], y[2]) + m64(x[2], y[1]) + m64(x[3], y[0]) + + 19 * (m64(x[4], y[9]) + m64(x[5], y[8]) + m64(x[6], y[7]) + m64(x[7], y[6]) + + m64(x[8], y[5]) + m64(x[9], y[4])); + xy[3] = t & ((1 << 25) - 1); + t = (t >> 25) + m64(x[0], y[4]) + m64(x[2], y[2]) + m64(x[4], y[0]) + + 19 * (m64(x[6], y[8]) + m64(x[8], y[6])) + 2 * (m64(x[1], y[3]) + m64(x[3], y[1])) + + 38 * (m64(x[5], y[9]) + m64(x[7], y[7]) + m64(x[9], y[5])); + xy[4] = t & ((1 << 26) - 1); + t = (t >> 26) + m64(x[0], y[5]) + m64(x[1], y[4]) + m64(x[2], y[3]) + m64(x[3], y[2]) + + m64(x[4], y[1]) + m64(x[5], y[0]) + + 19 * (m64(x[6], y[9]) + m64(x[7], y[8]) + m64(x[8], y[7]) + m64(x[9], y[6])); + xy[5] = t & ((1 << 25) - 1); + t = (t >> 25) + m64(x[0], y[6]) + m64(x[2], y[4]) + m64(x[4], y[2]) + m64(x[6], y[0]) + + 19 * m64(x[8], y[8]) + 2 * (m64(x[1], y[5]) + m64(x[3], y[3]) + m64(x[5], y[1])) + + 38 * (m64(x[7], y[9]) + m64(x[9], y[7])); + xy[6] = t & ((1 << 26) - 1); + t = (t >> 26) + m64(x[0], y[7]) + m64(x[1], y[6]) + m64(x[2], y[5]) + m64(x[3], y[4]) + + m64(x[4], y[3]) + m64(x[5], y[2]) + m64(x[6], y[1]) + m64(x[7], y[0]) + + 19 * (m64(x[8], y[9]) + m64(x[9], y[8])); + xy[7] = t & ((1 << 25) - 1); + t = (t >> 25) + xy[8]; + xy[8] = t & ((1 << 26) - 1); + xy[9] += (int32_t)(t >> 26); + check_reduced("mul output", xy); + return xy; } /* Square a number. Optimization of mul25519(x2, x, x) */ static i25519ptr sqr25519(i25519 x2, const i25519 x) { - register int64_t t; - check_nonred("sqr input", x); - t = m64(x[4],x[4]) + 2 * (m64(x[0],x[8]) + m64(x[2],x[6])) + 38 * - m64(x[9],x[9]) + 4 * (m64(x[1],x[7]) + m64(x[3],x[5])); - x2[8] = t & ((1 << 26) - 1); - t = (t >> 26) + 2 * (m64(x[0],x[9]) + m64(x[1],x[8]) + m64(x[2],x[7]) + - m64(x[3],x[6]) + m64(x[4],x[5])); - x2[9] = t & ((1 << 25) - 1); - t = 19 * (t >> 25) + m64(x[0],x[0]) + 38 * (m64(x[2],x[8]) + - m64(x[4],x[6]) + m64(x[5],x[5])) + 76 * (m64(x[1],x[9]) - + m64(x[3],x[7])); - x2[0] = t & ((1 << 26) - 1); - t = (t >> 26) + 2 * m64(x[0],x[1]) + 38 * (m64(x[2],x[9]) + - m64(x[3],x[8]) + m64(x[4],x[7]) + m64(x[5],x[6])); - x2[1] = t & ((1 << 25) - 1); - t = (t >> 25) + 19 * m64(x[6],x[6]) + 2 * (m64(x[0],x[2]) + - m64(x[1],x[1])) + 38 * m64(x[4],x[8]) + 76 * - (m64(x[3],x[9]) + m64(x[5],x[7])); - x2[2] = t & ((1 << 26) - 1); - t = (t >> 26) + 2 * (m64(x[0],x[3]) + m64(x[1],x[2])) + 38 * - (m64(x[4],x[9]) + m64(x[5],x[8]) + m64(x[6],x[7])); - x2[3] = t & ((1 << 25) - 1); - t = (t >> 25) + m64(x[2],x[2]) + 2 * m64(x[0],x[4]) + 38 * - (m64(x[6],x[8]) + m64(x[7],x[7])) + 4 * m64(x[1],x[3]) + 76 * - m64(x[5],x[9]); - x2[4] = t & ((1 << 26) - 1); - t = (t >> 26) + 2 * (m64(x[0],x[5]) + m64(x[1],x[4]) + m64(x[2],x[3])) - + 38 * (m64(x[6],x[9]) + m64(x[7],x[8])); - x2[5] = t & ((1 << 25) - 1); - t = (t >> 25) + 19 * m64(x[8],x[8]) + 2 * (m64(x[0],x[6]) + - m64(x[2],x[4]) + m64(x[3],x[3])) + 4 * m64(x[1],x[5]) + - 76 * m64(x[7],x[9]); - x2[6] = t & ((1 << 26) - 1); - t = (t >> 26) + 2 * (m64(x[0],x[7]) + m64(x[1],x[6]) + m64(x[2],x[5]) + - m64(x[3],x[4])) + 38 * m64(x[8],x[9]); - x2[7] = t & ((1 << 25) - 1); - t = (t >> 25) + x2[8]; - x2[8] = t & ((1 << 26) - 1); - x2[9] += (t >> 26); - check_reduced("sqr output", x2); - return x2; + register int64_t t; + check_nonred("sqr input", x); + t = m64(x[4], x[4]) + 2 * (m64(x[0], x[8]) + m64(x[2], x[6])) + 38 * m64(x[9], x[9]) + + 4 * (m64(x[1], x[7]) + m64(x[3], x[5])); + x2[8] = t & ((1 << 26) - 1); + t = (t >> 26) + 2 * (m64(x[0], x[9]) + m64(x[1], x[8]) + m64(x[2], x[7]) + m64(x[3], x[6]) + + m64(x[4], x[5])); + x2[9] = t & ((1 << 25) - 1); + t = 19 * (t >> 25) + m64(x[0], x[0]) + + 38 * (m64(x[2], x[8]) + m64(x[4], x[6]) + m64(x[5], x[5])) + + 76 * (m64(x[1], x[9]) + m64(x[3], x[7])); + x2[0] = t & ((1 << 26) - 1); + t = (t >> 26) + 2 * m64(x[0], x[1]) + + 38 * (m64(x[2], x[9]) + m64(x[3], x[8]) + m64(x[4], x[7]) + m64(x[5], x[6])); + x2[1] = t & ((1 << 25) - 1); + t = (t >> 25) + 19 * m64(x[6], x[6]) + 2 * (m64(x[0], x[2]) + m64(x[1], x[1])) + + 38 * m64(x[4], x[8]) + 76 * (m64(x[3], x[9]) + m64(x[5], x[7])); + x2[2] = t & ((1 << 26) - 1); + t = (t >> 26) + 2 * (m64(x[0], x[3]) + m64(x[1], x[2])) + + 38 * (m64(x[4], x[9]) + m64(x[5], x[8]) + m64(x[6], x[7])); + x2[3] = t & ((1 << 25) - 1); + t = (t >> 25) + m64(x[2], x[2]) + 2 * m64(x[0], x[4]) + + 38 * (m64(x[6], x[8]) + m64(x[7], x[7])) + 4 * m64(x[1], x[3]) + 76 * m64(x[5], x[9]); + x2[4] = t & ((1 << 26) - 1); + t = (t >> 26) + 2 * (m64(x[0], x[5]) + m64(x[1], x[4]) + m64(x[2], x[3])) + + 38 * (m64(x[6], x[9]) + m64(x[7], x[8])); + x2[5] = t & ((1 << 25) - 1); + t = (t >> 25) + 19 * m64(x[8], x[8]) + + 2 * (m64(x[0], x[6]) + m64(x[2], x[4]) + m64(x[3], x[3])) + 4 * m64(x[1], x[5]) + + 76 * m64(x[7], x[9]); + x2[6] = t & ((1 << 26) - 1); + t = (t >> 26) + 2 * (m64(x[0], x[7]) + m64(x[1], x[6]) + m64(x[2], x[5]) + m64(x[3], x[4])) + + 38 * m64(x[8], x[9]); + x2[7] = t & ((1 << 25) - 1); + t = (t >> 25) + x2[8]; + x2[8] = t & ((1 << 26) - 1); + x2[9] += (t >> 26); + check_reduced("sqr output", x2); + return x2; } /* Calculates a reciprocal. The output is in reduced form, the inputs need not * be. Simply calculates y = x^(p-2) so it's not too fast. */ /* When sqrtassist is true, it instead calculates y = x^((p-5)/8) */ static void recip25519(i25519 y, const i25519 x, int sqrtassist) { - i25519 t0, t1, t2, t3, t4; - int i; - /* the chain for x^(2^255-21) is straight from djb's implementation */ - sqr25519(t1, x); /* 2 == 2 * 1 */ - sqr25519(t2, t1); /* 4 == 2 * 2 */ - sqr25519(t0, t2); /* 8 == 2 * 4 */ - mul25519(t2, t0, x); /* 9 == 8 + 1 */ - mul25519(t0, t2, t1); /* 11 == 9 + 2 */ - sqr25519(t1, t0); /* 22 == 2 * 11 */ - mul25519(t3, t1, t2); /* 31 == 22 + 9 - == 2^5 - 2^0 */ - sqr25519(t1, t3); /* 2^6 - 2^1 */ - sqr25519(t2, t1); /* 2^7 - 2^2 */ - sqr25519(t1, t2); /* 2^8 - 2^3 */ - sqr25519(t2, t1); /* 2^9 - 2^4 */ - sqr25519(t1, t2); /* 2^10 - 2^5 */ - mul25519(t2, t1, t3); /* 2^10 - 2^0 */ - sqr25519(t1, t2); /* 2^11 - 2^1 */ - sqr25519(t3, t1); /* 2^12 - 2^2 */ - for (i = 1; i < 5; i++) { - sqr25519(t1, t3); - sqr25519(t3, t1); - } /* t3 */ /* 2^20 - 2^10 */ - mul25519(t1, t3, t2); /* 2^20 - 2^0 */ - sqr25519(t3, t1); /* 2^21 - 2^1 */ - sqr25519(t4, t3); /* 2^22 - 2^2 */ - for (i = 1; i < 10; i++) { - sqr25519(t3, t4); - sqr25519(t4, t3); - } /* t4 */ /* 2^40 - 2^20 */ - mul25519(t3, t4, t1); /* 2^40 - 2^0 */ - for (i = 0; i < 5; i++) { - sqr25519(t1, t3); - sqr25519(t3, t1); - } /* t3 */ /* 2^50 - 2^10 */ - mul25519(t1, t3, t2); /* 2^50 - 2^0 */ - sqr25519(t2, t1); /* 2^51 - 2^1 */ - sqr25519(t3, t2); /* 2^52 - 2^2 */ - for (i = 1; i < 25; i++) { - sqr25519(t2, t3); - sqr25519(t3, t2); - } /* t3 */ /* 2^100 - 2^50 */ - mul25519(t2, t3, t1); /* 2^100 - 2^0 */ - sqr25519(t3, t2); /* 2^101 - 2^1 */ - sqr25519(t4, t3); /* 2^102 - 2^2 */ - for (i = 1; i < 50; i++) { - sqr25519(t3, t4); - sqr25519(t4, t3); - } /* t4 */ /* 2^200 - 2^100 */ - mul25519(t3, t4, t2); /* 2^200 - 2^0 */ - for (i = 0; i < 25; i++) { - sqr25519(t4, t3); - sqr25519(t3, t4); - } /* t3 */ /* 2^250 - 2^50 */ - mul25519(t2, t3, t1); /* 2^250 - 2^0 */ - sqr25519(t1, t2); /* 2^251 - 2^1 */ - sqr25519(t2, t1); /* 2^252 - 2^2 */ - if (sqrtassist) { - mul25519(y, x, t2); /* 2^252 - 3 */ - } else { - sqr25519(t1, t2); /* 2^253 - 2^3 */ - sqr25519(t2, t1); /* 2^254 - 2^4 */ - sqr25519(t1, t2); /* 2^255 - 2^5 */ - mul25519(y, t1, t0); /* 2^255 - 21 */ - } + i25519 t0, t1, t2, t3, t4; + int i; + /* the chain for x^(2^255-21) is straight from djb's implementation */ + sqr25519(t1, x); /* 2 == 2 * 1 */ + sqr25519(t2, t1); /* 4 == 2 * 2 */ + sqr25519(t0, t2); /* 8 == 2 * 4 */ + mul25519(t2, t0, x); /* 9 == 8 + 1 */ + mul25519(t0, t2, t1); /* 11 == 9 + 2 */ + sqr25519(t1, t0); /* 22 == 2 * 11 */ + mul25519(t3, t1, t2); /* 31 == 22 + 9 + == 2^5 - 2^0 */ + sqr25519(t1, t3); /* 2^6 - 2^1 */ + sqr25519(t2, t1); /* 2^7 - 2^2 */ + sqr25519(t1, t2); /* 2^8 - 2^3 */ + sqr25519(t2, t1); /* 2^9 - 2^4 */ + sqr25519(t1, t2); /* 2^10 - 2^5 */ + mul25519(t2, t1, t3); /* 2^10 - 2^0 */ + sqr25519(t1, t2); /* 2^11 - 2^1 */ + sqr25519(t3, t1); /* 2^12 - 2^2 */ + for (i = 1; i < 5; i++) { + sqr25519(t1, t3); + sqr25519(t3, t1); + } /* t3 */ /* 2^20 - 2^10 */ + mul25519(t1, t3, t2); /* 2^20 - 2^0 */ + sqr25519(t3, t1); /* 2^21 - 2^1 */ + sqr25519(t4, t3); /* 2^22 - 2^2 */ + for (i = 1; i < 10; i++) { + sqr25519(t3, t4); + sqr25519(t4, t3); + } /* t4 */ /* 2^40 - 2^20 */ + mul25519(t3, t4, t1); /* 2^40 - 2^0 */ + for (i = 0; i < 5; i++) { + sqr25519(t1, t3); + sqr25519(t3, t1); + } /* t3 */ /* 2^50 - 2^10 */ + mul25519(t1, t3, t2); /* 2^50 - 2^0 */ + sqr25519(t2, t1); /* 2^51 - 2^1 */ + sqr25519(t3, t2); /* 2^52 - 2^2 */ + for (i = 1; i < 25; i++) { + sqr25519(t2, t3); + sqr25519(t3, t2); + } /* t3 */ /* 2^100 - 2^50 */ + mul25519(t2, t3, t1); /* 2^100 - 2^0 */ + sqr25519(t3, t2); /* 2^101 - 2^1 */ + sqr25519(t4, t3); /* 2^102 - 2^2 */ + for (i = 1; i < 50; i++) { + sqr25519(t3, t4); + sqr25519(t4, t3); + } /* t4 */ /* 2^200 - 2^100 */ + mul25519(t3, t4, t2); /* 2^200 - 2^0 */ + for (i = 0; i < 25; i++) { + sqr25519(t4, t3); + sqr25519(t3, t4); + } /* t3 */ /* 2^250 - 2^50 */ + mul25519(t2, t3, t1); /* 2^250 - 2^0 */ + sqr25519(t1, t2); /* 2^251 - 2^1 */ + sqr25519(t2, t1); /* 2^252 - 2^2 */ + if (sqrtassist) { + mul25519(y, x, t2); /* 2^252 - 3 */ + } else { + sqr25519(t1, t2); /* 2^253 - 2^3 */ + sqr25519(t2, t1); /* 2^254 - 2^4 */ + sqr25519(t1, t2); /* 2^255 - 2^5 */ + mul25519(y, t1, t0); /* 2^255 - 21 */ + } } /* checks if x is "negative", requires reduced input */ static inline int is_negative(i25519 x) { - return (is_overflow(x) | (x[9] < 0)) ^ (x[0] & 1); + return (is_overflow(x) | (x[9] < 0)) ^ (x[0] & 1); } /* a square root */ static void sqrt25519(i25519 x, const i25519 u) { - i25519 v, t1, t2; - add25519(t1, u, u); /* t1 = 2u */ - recip25519(v, t1, 1); /* v = (2u)^((p-5)/8) */ - sqr25519(x, v); /* x = v^2 */ - mul25519(t2, t1, x); /* t2 = 2uv^2 */ - t2[0]--; /* t2 = 2uv^2-1 */ - mul25519(t1, v, t2); /* t1 = v(2uv^2-1) */ - mul25519(x, u, t1); /* x = uv(2uv^2-1) */ + i25519 v, t1, t2; + add25519(t1, u, u); /* t1 = 2u */ + recip25519(v, t1, 1); /* v = (2u)^((p-5)/8) */ + sqr25519(x, v); /* x = v^2 */ + mul25519(t2, t1, x); /* t2 = 2uv^2 */ + t2[0]--; /* t2 = 2uv^2-1 */ + mul25519(t1, v, t2); /* t1 = v(2uv^2-1) */ + mul25519(x, u, t1); /* x = uv(2uv^2-1) */ } - /********************* Elliptic curve *********************/ /* y^2 = x^3 + 486662 x^2 + x over GF(2^255-19) */ - /* t1 = ax + az * t2 = ax - az */ static inline void mont_prep(i25519 t1, i25519 t2, i25519 ax, i25519 az) { - add25519(t1, ax, az); - sub25519(t2, ax, az); + add25519(t1, ax, az); + sub25519(t2, ax, az); } /* A = P + Q where @@ -526,262 +562,266 @@ static inline void mont_prep(i25519 t1, i25519 t2, i25519 ax, i25519 az) { * X(Q) = (t3+t4)/(t3-t4) * X(P-Q) = dx * clobbers t1 and t2, preserves t3 and t4 */ -static inline void mont_add(i25519 t1, i25519 t2, i25519 t3, i25519 t4, - i25519 ax, i25519 az, const i25519 dx) { - mul25519(ax, t2, t3); - mul25519(az, t1, t4); - add25519(t1, ax, az); - sub25519(t2, ax, az); - sqr25519(ax, t1); - sqr25519(t1, t2); - mul25519(az, t1, dx); +static inline void +mont_add(i25519 t1, i25519 t2, i25519 t3, i25519 t4, i25519 ax, i25519 az, const i25519 dx) { + mul25519(ax, t2, t3); + mul25519(az, t1, t4); + add25519(t1, ax, az); + sub25519(t2, ax, az); + sqr25519(ax, t1); + sqr25519(t1, t2); + mul25519(az, t1, dx); } /* B = 2 * Q where * X(B) = bx/bz * X(Q) = (t3+t4)/(t3-t4) * clobbers t1 and t2, preserves t3 and t4 */ -static inline void mont_dbl(i25519 t1, i25519 t2, i25519 t3, i25519 t4, - i25519 bx, i25519 bz) { - sqr25519(t1, t3); - sqr25519(t2, t4); - mul25519(bx, t1, t2); - sub25519(t2, t1, t2); - mul25519small(bz, t2, 121665); - add25519(t1, t1, bz); - mul25519(bz, t1, t2); +static inline void mont_dbl(i25519 t1, i25519 t2, i25519 t3, i25519 t4, i25519 bx, i25519 bz) { + sqr25519(t1, t3); + sqr25519(t2, t4); + mul25519(bx, t1, t2); + sub25519(t2, t1, t2); + mul25519small(bz, t2, 121665); + add25519(t1, t1, bz); + mul25519(bz, t1, t2); } /* Y^2 = X^3 + 486662 X^2 + X * t is a temporary */ static inline void x_to_y2(i25519 t, i25519 y2, const i25519 x) { - sqr25519(t, x); - mul25519small(y2, x, 486662); - add25519(t, t, y2); - t[0]++; - mul25519(y2, t, x); + sqr25519(t, x); + mul25519small(y2, x, 486662); + add25519(t, t, y2); + t[0]++; + mul25519(y2, t, x); } /* P = kG and s = sign(P)/k */ void core25519(k25519 Px, k25519 s, const k25519 k, const k25519 Gx) { - i25519 dx, x[2], z[2], t1, t2, t3, t4; - unsigned i, j; - - /* unpack the base */ - if (Gx) - unpack25519(dx, Gx); - else - set25519(dx, 9); - - /* 0G = point-at-infinity */ - set25519(x[0], 1); - set25519(z[0], 0); - - /* 1G = G */ - cpy25519(x[1], dx); - set25519(z[1], 1); - - for (i = 32; i--; ) { - for (j = 8; j--; ) { - /* swap arguments depending on bit */ - const int bit1 = k[i] >> j & 1; - const int bit0 = ~k[i] >> j & 1; - int32_t *const ax = x[bit0]; - int32_t *const az = z[bit0]; - int32_t *const bx = x[bit1]; - int32_t *const bz = z[bit1]; - - /* a' = a + b */ - /* b' = 2 b */ - mont_prep(t1, t2, ax, az); - mont_prep(t3, t4, bx, bz); - mont_add(t1, t2, t3, t4, ax, az, dx); - mont_dbl(t1, t2, t3, t4, bx, bz); + i25519 dx, x[2], z[2], t1, t2, t3, t4; + unsigned i, j; + + /* unpack the base */ + if (Gx) { + unpack25519(dx, Gx); + } else { + set25519(dx, 9); + } + + /* 0G = point-at-infinity */ + set25519(x[0], 1); + set25519(z[0], 0); + + /* 1G = G */ + cpy25519(x[1], dx); + set25519(z[1], 1); + + for (i = 32; i--;) { + for (j = 8; j--;) { + /* swap arguments depending on bit */ + const int bit1 = k[i] >> j & 1; + const int bit0 = ~k[i] >> j & 1; + int32_t *const ax = x[bit0]; + int32_t *const az = z[bit0]; + int32_t *const bx = x[bit1]; + int32_t *const bz = z[bit1]; + + /* a' = a + b */ + /* b' = 2 b */ + mont_prep(t1, t2, ax, az); + mont_prep(t3, t4, bx, bz); + mont_add(t1, t2, t3, t4, ax, az, dx); + mont_dbl(t1, t2, t3, t4, bx, bz); + } + } + + recip25519(t1, z[0], 0); + mul25519(dx, x[0], t1); + pack25519(dx, Px); + + /* calculate s such that s abs(P) = G .. assumes G is std base point */ + if (s) { + x_to_y2(t2, t1, dx); /* t1 = Py^2 */ + recip25519(t3, z[1], 0); /* where Q=P+G ... */ + mul25519(t2, x[1], t3); /* t2 = Qx */ + add25519(t2, t2, dx); /* t2 = Qx + Px */ + t2[0] += 9 + 486662; /* t2 = Qx + Px + Gx + 486662 */ + dx[0] -= 9; /* dx = Px - Gx */ + sqr25519(t3, dx); /* t3 = (Px - Gx)^2 */ + mul25519(dx, t2, t3); /* dx = t2 (Px - Gx)^2 */ + sub25519(dx, dx, t1); /* dx = t2 (Px - Gx)^2 - Py^2 */ + dx[0] -= 39420360; /* dx = t2 (Px - Gx)^2 - Py^2 - Gy^2 */ + mul25519(t1, dx, base_r2y); /* t1 = -Py */ + if (is_negative(t1)) { /* sign is 1, so just copy */ + cpy32(s, k); + } else { /* sign is -1, so negate */ + mula_small(s, order_times_8, 0, k, 32, -1); + } + + /* reduce s mod q + * (is this needed? do it just in case, it's fast anyway) */ + divmod((dstptr) t1, s, 32, order25519, 32); + + /* take reciprocal of s mod q */ + cpy32((dstptr) t1, order25519); + cpy32(s, egcd32((dstptr) x, (dstptr) z, s, (dstptr) t1)); + if ((int8_t) s[31] < 0) { + mula_small(s, s, 0, order25519, 32, 1); + } } - } - - recip25519(t1, z[0], 0); - mul25519(dx, x[0], t1); - pack25519(dx, Px); - - /* calculate s such that s abs(P) = G .. assumes G is std base point */ - if (s) { - x_to_y2(t2, t1, dx); /* t1 = Py^2 */ - recip25519(t3, z[1], 0); /* where Q=P+G ... */ - mul25519(t2, x[1], t3); /* t2 = Qx */ - add25519(t2, t2, dx); /* t2 = Qx + Px */ - t2[0] += 9 + 486662; /* t2 = Qx + Px + Gx + 486662 */ - dx[0] -= 9; /* dx = Px - Gx */ - sqr25519(t3, dx); /* t3 = (Px - Gx)^2 */ - mul25519(dx, t2, t3); /* dx = t2 (Px - Gx)^2 */ - sub25519(dx, dx, t1); /* dx = t2 (Px - Gx)^2 - Py^2 */ - dx[0] -= 39420360; /* dx = t2 (Px - Gx)^2 - Py^2 - Gy^2 */ - mul25519(t1, dx, base_r2y); /* t1 = -Py */ - if (is_negative(t1)) /* sign is 1, so just copy */ - cpy32(s, k); - else /* sign is -1, so negate */ - mula_small(s, order_times_8, 0, k, 32, -1); - - /* reduce s mod q - * (is this needed? do it just in case, it's fast anyway) */ - divmod((dstptr) t1, s, 32, order25519, 32); - - /* take reciprocal of s mod q */ - cpy32((dstptr) t1, order25519); - cpy32(s, egcd32((dstptr) x, (dstptr) z, s, (dstptr) t1)); - if ((int8_t) s[31] < 0) - mula_small(s, s, 0, order25519, 32, 1); - } } void clamp25519(priv25519 k) { - k[31] &= 0x7F; - k[31] |= 0x40; - k[ 0] &= 0xF8; + k[31] &= 0x7F; + k[31] |= 0x40; + k[0] &= 0xF8; } void keygen25519(pub25519 P, spriv25519 s, priv25519 k) { - clamp25519(k); - core25519(P, s, k, NULL); + clamp25519(k); + core25519(P, s, k, NULL); } void curve25519(sec25519 Z, const priv25519 k, const pub25519 P) { - core25519(Z, NULL, k, P); + core25519(Z, NULL, k, P); } -/* v = (x - h) s mod q */ -//note: this function screws with of the parameters... +/* + * sign25519 - Custom variant of deterministic EC-KCDSA signature algorithm. + * + * This function implements a custom variant of deterministic EC-KCDSA signature + * algorithm, where the formula used is s * (x - h) mod order25519. This differs + * from a standard implementation of EC-KCDSA (s * (x - h ⊕ r)). In this custom + * variant, h is calculated as H(m || r), where r = [k]G and k = H(m || sk). + */ int sign25519(k25519 v, const k25519 h, const priv25519 x, const spriv25519 s) { - uint8_t tmp[65]; - unsigned w; - int i; - k25519 h1, x1; - - cpy32(h1, h); - cpy32(x1, x); + uint8_t tmp[65]; + unsigned w; + int i; + k25519 h1, x1; - memset(tmp, 0, 32); - divmod(tmp, h1, 32, order25519, 32); + cpy32(h1, h); + cpy32(x1, x); - memset(tmp, 0, 32); - divmod(tmp, x1, 32, order25519, 32); + explicit_bzero(tmp, 32); + divmod(tmp, h1, 32, order25519, 32); - memset(v, 0, 32); + explicit_bzero(tmp, 32); + divmod(tmp, x1, 32, order25519, 32); - mula_small(v, x1, 0, h1, 32, -1); - mula_small(v, v, 0, order25519, 32, (15-(int8_t) v[31])/16); + explicit_bzero(v, 32); - memset(tmp, 0, sizeof(tmp)); + mula_small(v, x1, 0, h1, 32, -1); + mula_small(v, v, 0, order25519, 32, (15 - (int8_t) v[31]) / 16); - mula32(tmp, v, s, 32, 1); - divmod(tmp+32, tmp, 64, order25519, 32); + explicit_bzero(tmp, sizeof(tmp)); + mula32(tmp, v, s, 32, 1); + divmod(tmp + 32, tmp, 64, order25519, 32); - for (w = 0, i = 0; i < 32; i++) - w |= v[i] = tmp[i]; + for (w = 0, i = 0; i < 32; i++) { + w |= v[i] = tmp[i]; + } - return w != 0; + return w != 0; } /* Y = v abs(P) + h G */ void verify25519(pub25519 Y, const k25519 v, const k25519 h, const pub25519 P) { - k25519 d; - i25519 p[2], s[2], yx[3], yz[3], t1[3], t2[3]; - unsigned vi = 0, hi = 0, di = 0, nvh, i, j, k; - - /* set p[0] to G and p[1] to P */ - - set25519(p[0], 9); - unpack25519(p[1], P); - - /* set s[0] to P+G and s[1] to P-G */ - - /* s[0] = (Py^2 + Gy^2 - 2 Py Gy)/(Px - Gx)^2 - Px - Gx - 486662 */ - /* s[1] = (Py^2 + Gy^2 + 2 Py Gy)/(Px - Gx)^2 - Px - Gx - 486662 */ - - x_to_y2(t1[0], t2[0], p[1]); /* t2[0] = Py^2 */ - sqrt25519(t1[0], t2[0]); /* t1[0] = Py or -Py */ - j = is_negative(t1[0]); /* ... check which */ - t2[0][0] += 39420360; /* t2[0] = Py^2 + Gy^2 */ - mul25519(t2[1], base_2y, t1[0]);/* t2[1] = 2 Py Gy or -2 Py Gy */ - sub25519(t1[j], t2[0], t2[1]); /* t1[0] = Py^2 + Gy^2 - 2 Py Gy */ - add25519(t1[1-j], t2[0], t2[1]);/* t1[1] = Py^2 + Gy^2 + 2 Py Gy */ - cpy25519(t2[0], p[1]); /* t2[0] = Px */ - t2[0][0] -= 9; /* t2[0] = Px - Gx */ - sqr25519(t2[1], t2[0]); /* t2[1] = (Px - Gx)^2 */ - recip25519(t2[0], t2[1], 0); /* t2[0] = 1/(Px - Gx)^2 */ - mul25519(s[0], t1[0], t2[0]); /* s[0] = t1[0]/(Px - Gx)^2 */ - sub25519(s[0], s[0], p[1]); /* s[0] = t1[0]/(Px - Gx)^2 - Px */ - s[0][0] -= 9 + 486662; /* s[0] = X(P+G) */ - mul25519(s[1], t1[1], t2[0]); /* s[1] = t1[1]/(Px - Gx)^2 */ - sub25519(s[1], s[1], p[1]); /* s[1] = t1[1]/(Px - Gx)^2 - Px */ - s[1][0] -= 9 + 486662; /* s[1] = X(P-G) */ - mul25519small(s[0], s[0], 1); /* reduce s[0] */ - mul25519small(s[1], s[1], 1); /* reduce s[1] */ - - - /* prepare the chain */ - for (i = 0; i < 32; i++) { - vi = (vi >> 8) ^ v[i] ^ (v[i] << 1); - hi = (hi >> 8) ^ h[i] ^ (h[i] << 1); - nvh = ~(vi ^ hi); - di = (nvh & (di & 0x80) >> 7) ^ vi; - di ^= nvh & (di & 0x01) << 1; - di ^= nvh & (di & 0x02) << 1; - di ^= nvh & (di & 0x04) << 1; - di ^= nvh & (di & 0x08) << 1; - di ^= nvh & (di & 0x10) << 1; - di ^= nvh & (di & 0x20) << 1; - di ^= nvh & (di & 0x40) << 1; - d[i] = di; - } - - di = ((nvh & (di & 0x80) << 1) ^ vi) >> 8; - - /* initialize state */ - set25519(yx[0], 1); - cpy25519(yx[1], p[di]); - cpy25519(yx[2], s[0]); - set25519(yz[0], 0); - set25519(yz[1], 1); - set25519(yz[2], 1); - - /* y[0] is (even)P + (even)G - * y[1] is (even)P + (odd)G if current d-bit is 0 - * y[1] is (odd)P + (even)G if current d-bit is 1 - * y[2] is (odd)P + (odd)G - */ - - vi = 0; - hi = 0; - - /* and go for it! */ - for (i = 32; i--; ) { - vi = (vi << 8) | v[i]; - hi = (hi << 8) | h[i]; - di = (di << 8) | d[i]; - - for (j = 8; j--; ) { - mont_prep(t1[0], t2[0], yx[0], yz[0]); - mont_prep(t1[1], t2[1], yx[1], yz[1]); - mont_prep(t1[2], t2[2], yx[2], yz[2]); - - k = ((vi ^ vi >> 1) >> j & 1) - + ((hi ^ hi >> 1) >> j & 1); - mont_dbl(yx[2], yz[2], t1[k], t2[k], yx[0], yz[0]); - - k = (di >> j & 2) ^ ((di >> j & 1) << 1); - mont_add(t1[1], t2[1], t1[k], t2[k], yx[1], yz[1], - p[di >> j & 1]); - - mont_add(t1[2], t2[2], t1[0], t2[0], yx[2], yz[2], - s[((vi ^ hi) >> j & 2) >> 1]); + k25519 d; + i25519 p[2], s[2], yx[3], yz[3], t1[3], t2[3]; + unsigned vi = 0, hi = 0, di = 0, nvh, i, j, k; + + /* set p[0] to G and p[1] to P */ + + set25519(p[0], 9); + unpack25519(p[1], P); + + /* set s[0] to P+G and s[1] to P-G */ + + /* s[0] = (Py^2 + Gy^2 - 2 Py Gy)/(Px - Gx)^2 - Px - Gx - 486662 */ + /* s[1] = (Py^2 + Gy^2 + 2 Py Gy)/(Px - Gx)^2 - Px - Gx - 486662 */ + + x_to_y2(t1[0], t2[0], p[1]); /* t2[0] = Py^2 */ + sqrt25519(t1[0], t2[0]); /* t1[0] = Py or -Py */ + j = is_negative(t1[0]); /* ... check which */ + t2[0][0] += 39420360; /* t2[0] = Py^2 + Gy^2 */ + mul25519(t2[1], base_2y, t1[0]); /* t2[1] = 2 Py Gy or -2 Py Gy */ + sub25519(t1[j], t2[0], t2[1]); /* t1[0] = Py^2 + Gy^2 - 2 Py Gy */ + add25519(t1[1 - j], t2[0], t2[1]); /* t1[1] = Py^2 + Gy^2 + 2 Py Gy */ + cpy25519(t2[0], p[1]); /* t2[0] = Px */ + t2[0][0] -= 9; /* t2[0] = Px - Gx */ + sqr25519(t2[1], t2[0]); /* t2[1] = (Px - Gx)^2 */ + recip25519(t2[0], t2[1], 0); /* t2[0] = 1/(Px - Gx)^2 */ + mul25519(s[0], t1[0], t2[0]); /* s[0] = t1[0]/(Px - Gx)^2 */ + sub25519(s[0], s[0], p[1]); /* s[0] = t1[0]/(Px - Gx)^2 - Px */ + s[0][0] -= 9 + 486662; /* s[0] = X(P+G) */ + mul25519(s[1], t1[1], t2[0]); /* s[1] = t1[1]/(Px - Gx)^2 */ + sub25519(s[1], s[1], p[1]); /* s[1] = t1[1]/(Px - Gx)^2 - Px */ + s[1][0] -= 9 + 486662; /* s[1] = X(P-G) */ + mul25519small(s[0], s[0], 1); /* reduce s[0] */ + mul25519small(s[1], s[1], 1); /* reduce s[1] */ + + /* prepare the chain */ + for (i = 0; i < 32; i++) { + vi = (vi >> 8) ^ v[i] ^ (v[i] << 1); + hi = (hi >> 8) ^ h[i] ^ (h[i] << 1); + nvh = ~(vi ^ hi); + di = (nvh & (di & 0x80) >> 7) ^ vi; + di ^= nvh & (di & 0x01) << 1; + di ^= nvh & (di & 0x02) << 1; + di ^= nvh & (di & 0x04) << 1; + di ^= nvh & (di & 0x08) << 1; + di ^= nvh & (di & 0x10) << 1; + di ^= nvh & (di & 0x20) << 1; + di ^= nvh & (di & 0x40) << 1; + d[i] = di; } - } - - k = (vi & 1) + (hi & 1); - recip25519(t1[0], yz[k], 0); - mul25519(t1[1], yx[k], t1[0]); - - pack25519(t1[1], Y); + + di = ((nvh & (di & 0x80) << 1) ^ vi) >> 8; + + /* initialize state */ + set25519(yx[0], 1); + cpy25519(yx[1], p[di]); + cpy25519(yx[2], s[0]); + set25519(yz[0], 0); + set25519(yz[1], 1); + set25519(yz[2], 1); + + /* y[0] is (even)P + (even)G + * y[1] is (even)P + (odd)G if current d-bit is 0 + * y[1] is (odd)P + (even)G if current d-bit is 1 + * y[2] is (odd)P + (odd)G + */ + + vi = 0; + hi = 0; + + /* and go for it! */ + for (i = 32; i--;) { + vi = (vi << 8) | v[i]; + hi = (hi << 8) | h[i]; + di = (di << 8) | d[i]; + + for (j = 8; j--;) { + mont_prep(t1[0], t2[0], yx[0], yz[0]); + mont_prep(t1[1], t2[1], yx[1], yz[1]); + mont_prep(t1[2], t2[2], yx[2], yz[2]); + + k = ((vi ^ vi >> 1) >> j & 1) + ((hi ^ hi >> 1) >> j & 1); + mont_dbl(yx[2], yz[2], t1[k], t2[k], yx[0], yz[0]); + + k = (di >> j & 2) ^ ((di >> j & 1) << 1); + mont_add(t1[1], t2[1], t1[k], t2[k], yx[1], yz[1], p[di >> j & 1]); + + mont_add(t1[2], t2[2], t1[0], t2[0], yx[2], yz[2], s[((vi ^ hi) >> j & 2) >> 1]); + } + } + + k = (vi & 1) + (hi & 1); + recip25519(t1[0], yz[k], 0); + mul25519(t1[1], yx[k], t1[0]); + + pack25519(t1[1], Y); } \ No newline at end of file diff --git a/src/curve25519_i64.h b/src/curve25519_i64.h index c899508..534cfbb 100644 --- a/src/curve25519_i64.h +++ b/src/curve25519_i64.h @@ -1,6 +1,6 @@ /* Modified by mko. - + */ /* Generic 64-bit integer implementation of Curve25519 ECDH * Written by Matthijs van Duin, 200608242056 @@ -9,24 +9,23 @@ * Based on work by Daniel J Bernstein, http://cr.yp.to/ecdh.html */ +#pragma once + #include typedef unsigned char k25519[32]; /* any type of key */ extern const k25519 zero25519; /* 0 */ -extern const k25519 prime25519; /* the prime 2^255-19 */ -extern const k25519 order25519; /* group order (a prime near 2^252+2^124) */ +extern const k25519 prime25519; /* the prime 2^255-19 */ +extern const k25519 order25519; /* group order (a prime near 2^252+2^124) */ - -typedef k25519 pub25519; /* public key */ +typedef k25519 pub25519; /* public key */ typedef k25519 priv25519; /* private key (for key agreement) */ -typedef k25519 spriv25519; /* private key for signing */ -typedef k25519 sec25519; /* shared secret */ - +typedef k25519 spriv25519; /* private key for signing */ +typedef k25519 sec25519; /* shared secret */ /********* KEY AGREEMENT *********/ - /* internal function - do not use directly */ void core25519(k25519 P, spriv25519 s, const priv25519 k, const k25519 G); @@ -55,7 +54,6 @@ void curve25519(sec25519 Z, const priv25519 k, const pub25519 P); /********* DIGITAL SIGNATURES *********/ - /* deterministic EC-KCDSA * * s is the private key for signing @@ -91,7 +89,6 @@ void curve25519(sec25519 Z, const priv25519 k, const pub25519 P); * parallel to) hashing the message. */ - /* Signature generation primitive, calculates (x-h)s mod q * v [out] signature value * h [in] signature hash (of message, signature pub key, and context data) @@ -101,7 +98,6 @@ void curve25519(sec25519 Z, const priv25519 k, const pub25519 P); */ int sign25519(k25519 v, const k25519 h, const priv25519 x, const spriv25519 s); - /* Signature verification primitive, calculates Y = vP + hG * Y [out] signature public key * v [in] signature value diff --git a/src/curveConversion.c b/src/curveConversion.c index f6356fe..beaae04 100644 --- a/src/curveConversion.c +++ b/src/curveConversion.c @@ -5,357 +5,335 @@ * This file is in the public domain. */ - #include #include -#define F25519_SIZE 32 +#define F25519_SIZE 32 extern const uint8_t f25519_zero[F25519_SIZE]; extern const uint8_t f25519_one[F25519_SIZE]; - /* Copy two points */ -static inline void f25519_copy(uint8_t *x, const uint8_t *a) -{ - memcpy(x, a, F25519_SIZE); +static inline void f25519_copy(uint8_t *x, const uint8_t *a) { + memcpy(x, a, F25519_SIZE); } - const uint8_t f25519_zero[F25519_SIZE] = {0}; const uint8_t f25519_one[F25519_SIZE] = {1}; -void f25519_load(uint8_t *x, uint32_t c) -{ - unsigned int i; +void f25519_load(uint8_t *x, uint32_t c) { + unsigned int i; - for (i = 0; i < sizeof(c); i++) { - x[i] = c; - c >>= 8; - } + for (i = 0; i < sizeof(c); i++) { + x[i] = c; + c >>= 8; + } - for (; i < F25519_SIZE; i++) - x[i] = 0; + for (; i < F25519_SIZE; i++) { + x[i] = 0; + } } -void f25519_select(uint8_t *dst, - const uint8_t *zero, const uint8_t *one, - uint8_t condition) -{ - const uint8_t mask = -condition; - int i; +void f25519_select(uint8_t *dst, const uint8_t *zero, const uint8_t *one, uint8_t condition) { + const uint8_t mask = -condition; + int i; - for (i = 0; i < F25519_SIZE; i++) - dst[i] = zero[i] ^ (mask & (one[i] ^ zero[i])); + for (i = 0; i < F25519_SIZE; i++) { + dst[i] = zero[i] ^ (mask & (one[i] ^ zero[i])); + } } -void f25519_normalize(uint8_t *x) -{ - uint8_t minusp[F25519_SIZE]; - uint16_t c; - int i; - - /* Reduce using 2^255 = 19 mod p */ - c = (x[31] >> 7) * 19; - x[31] &= 127; - - for (i = 0; i < F25519_SIZE; i++) { - c += x[i]; - x[i] = c; - c >>= 8; - } - - /* The number is now less than 2^255 + 18, and therefore less than - * 2p. Try subtracting p, and conditionally load the subtracted - * value if underflow did not occur. - */ - c = 19; - - for (i = 0; i + 1 < F25519_SIZE; i++) { - c += x[i]; - minusp[i] = c; - c >>= 8; - } - - c += ((uint16_t)x[i]) - 128; - minusp[31] = c; - - /* Load x-p if no underflow */ - f25519_select(x, minusp, x, (c >> 15) & 1); +void f25519_normalize(uint8_t *x) { + uint8_t minusp[F25519_SIZE]; + uint16_t c; + int i; + + /* Reduce using 2^255 = 19 mod p */ + c = (x[31] >> 7) * 19; + x[31] &= 127; + + for (i = 0; i < F25519_SIZE; i++) { + c += x[i]; + x[i] = c; + c >>= 8; + } + + /* The number is now less than 2^255 + 18, and therefore less than + * 2p. Try subtracting p, and conditionally load the subtracted + * value if underflow did not occur. + */ + c = 19; + + for (i = 0; i + 1 < F25519_SIZE; i++) { + c += x[i]; + minusp[i] = c; + c >>= 8; + } + + c += ((uint16_t) x[i]) - 128; + minusp[31] = c; + + /* Load x-p if no underflow */ + f25519_select(x, minusp, x, (c >> 15) & 1); } -uint8_t f25519_eq(const uint8_t *x, const uint8_t *y) -{ - uint8_t sum = 0; - int i; +uint8_t f25519_eq(const uint8_t *x, const uint8_t *y) { + uint8_t sum = 0; + int i; - for (i = 0; i < F25519_SIZE; i++) - sum |= x[i] ^ y[i]; + for (i = 0; i < F25519_SIZE; i++) { + sum |= x[i] ^ y[i]; + } - sum |= (sum >> 4); - sum |= (sum >> 2); - sum |= (sum >> 1); + sum |= (sum >> 4); + sum |= (sum >> 2); + sum |= (sum >> 1); - return (sum ^ 1) & 1; + return (sum ^ 1) & 1; } -void f25519_add(uint8_t *r, const uint8_t *a, const uint8_t *b) -{ - uint16_t c = 0; - int i; - - /* Add */ - for (i = 0; i < F25519_SIZE; i++) { - c >>= 8; - c += ((uint16_t)a[i]) + ((uint16_t)b[i]); - r[i] = c; - } - - /* Reduce with 2^255 = 19 mod p */ - r[31] &= 127; - c = (c >> 7) * 19; - - for (i = 0; i < F25519_SIZE; i++) { - c += r[i]; - r[i] = c; - c >>= 8; - } +void f25519_add(uint8_t *r, const uint8_t *a, const uint8_t *b) { + uint16_t c = 0; + int i; + + /* Add */ + for (i = 0; i < F25519_SIZE; i++) { + c >>= 8; + c += ((uint16_t) a[i]) + ((uint16_t) b[i]); + r[i] = c; + } + + /* Reduce with 2^255 = 19 mod p */ + r[31] &= 127; + c = (c >> 7) * 19; + + for (i = 0; i < F25519_SIZE; i++) { + c += r[i]; + r[i] = c; + c >>= 8; + } } -void f25519_sub(uint8_t *r, const uint8_t *a, const uint8_t *b) -{ - uint32_t c = 0; - int i; - - /* Calculate a + 2p - b, to avoid underflow */ - c = 218; - for (i = 0; i + 1 < F25519_SIZE; i++) { - c += 65280 + ((uint32_t)a[i]) - ((uint32_t)b[i]); - r[i] = c; - c >>= 8; - } - - c += ((uint32_t)a[31]) - ((uint32_t)b[31]); - r[31] = c & 127; - c = (c >> 7) * 19; - - for (i = 0; i < F25519_SIZE; i++) { - c += r[i]; - r[i] = c; - c >>= 8; - } +void f25519_sub(uint8_t *r, const uint8_t *a, const uint8_t *b) { + uint32_t c = 0; + int i; + + /* Calculate a + 2p - b, to avoid underflow */ + c = 218; + for (i = 0; i + 1 < F25519_SIZE; i++) { + c += 65280 + ((uint32_t) a[i]) - ((uint32_t) b[i]); + r[i] = c; + c >>= 8; + } + + c += ((uint32_t) a[31]) - ((uint32_t) b[31]); + r[31] = c & 127; + c = (c >> 7) * 19; + + for (i = 0; i < F25519_SIZE; i++) { + c += r[i]; + r[i] = c; + c >>= 8; + } } -void f25519_neg(uint8_t *r, const uint8_t *a) -{ - uint32_t c = 0; - int i; - - /* Calculate 2p - a, to avoid underflow */ - c = 218; - for (i = 0; i + 1 < F25519_SIZE; i++) { - c += 65280 - ((uint32_t)a[i]); - r[i] = c; - c >>= 8; - } - - c -= ((uint32_t)a[31]); - r[31] = c & 127; - c = (c >> 7) * 19; - - for (i = 0; i < F25519_SIZE; i++) { - c += r[i]; - r[i] = c; - c >>= 8; - } +void f25519_neg(uint8_t *r, const uint8_t *a) { + uint32_t c = 0; + int i; + + /* Calculate 2p - a, to avoid underflow */ + c = 218; + for (i = 0; i + 1 < F25519_SIZE; i++) { + c += 65280 - ((uint32_t) a[i]); + r[i] = c; + c >>= 8; + } + + c -= ((uint32_t) a[31]); + r[31] = c & 127; + c = (c >> 7) * 19; + + for (i = 0; i < F25519_SIZE; i++) { + c += r[i]; + r[i] = c; + c >>= 8; + } } -void f25519_mul__distinct(uint8_t *r, const uint8_t *a, const uint8_t *b) -{ - uint32_t c = 0; - int i; +void f25519_mul__distinct(uint8_t *r, const uint8_t *a, const uint8_t *b) { + uint32_t c = 0; + int i; - for (i = 0; i < F25519_SIZE; i++) { - int j; + for (i = 0; i < F25519_SIZE; i++) { + int j; - c >>= 8; - for (j = 0; j <= i; j++) - c += ((uint32_t)a[j]) * ((uint32_t)b[i - j]); + c >>= 8; + for (j = 0; j <= i; j++) { + c += ((uint32_t) a[j]) * ((uint32_t) b[i - j]); + } - for (; j < F25519_SIZE; j++) - c += ((uint32_t)a[j]) * - ((uint32_t)b[i + F25519_SIZE - j]) * 38; + for (; j < F25519_SIZE; j++) { + c += ((uint32_t) a[j]) * ((uint32_t) b[i + F25519_SIZE - j]) * 38; + } - r[i] = c; - } + r[i] = c; + } - r[31] &= 127; - c = (c >> 7) * 19; + r[31] &= 127; + c = (c >> 7) * 19; - for (i = 0; i < F25519_SIZE; i++) { - c += r[i]; - r[i] = c; - c >>= 8; - } + for (i = 0; i < F25519_SIZE; i++) { + c += r[i]; + r[i] = c; + c >>= 8; + } } -void f25519_mul(uint8_t *r, const uint8_t *a, const uint8_t *b) -{ - uint8_t tmp[F25519_SIZE]; +void f25519_mul(uint8_t *r, const uint8_t *a, const uint8_t *b) { + uint8_t tmp[F25519_SIZE]; - f25519_mul__distinct(tmp, a, b); - f25519_copy(r, tmp); + f25519_mul__distinct(tmp, a, b); + f25519_copy(r, tmp); } -void f25519_mul_c(uint8_t *r, const uint8_t *a, uint32_t b) -{ - uint32_t c = 0; - int i; - - for (i = 0; i < F25519_SIZE; i++) { - c >>= 8; - c += b * ((uint32_t)a[i]); - r[i] = c; - } - - r[31] &= 127; - c >>= 7; - c *= 19; - - for (i = 0; i < F25519_SIZE; i++) { - c += r[i]; - r[i] = c; - c >>= 8; - } +void f25519_mul_c(uint8_t *r, const uint8_t *a, uint32_t b) { + uint32_t c = 0; + int i; + + for (i = 0; i < F25519_SIZE; i++) { + c >>= 8; + c += b * ((uint32_t) a[i]); + r[i] = c; + } + + r[31] &= 127; + c >>= 7; + c *= 19; + + for (i = 0; i < F25519_SIZE; i++) { + c += r[i]; + r[i] = c; + c >>= 8; + } } -void f25519_inv__distinct(uint8_t *r, const uint8_t *x) -{ - uint8_t s[F25519_SIZE]; - int i; - - /* This is a prime field, so by Fermat's little theorem: - * - * x^(p-1) = 1 mod p - * - * Therefore, raise to (p-2) = 2^255-21 to get a multiplicative - * inverse. - * - * This is a 255-bit binary number with the digits: - * - * 11111111... 01011 - * - * We compute the result by the usual binary chain, but - * alternate between keeping the accumulator in r and s, so as - * to avoid copying temporaries. - */ - - /* 1 1 */ - f25519_mul__distinct(s, x, x); - f25519_mul__distinct(r, s, x); - - /* 1 x 248 */ - for (i = 0; i < 248; i++) { - f25519_mul__distinct(s, r, r); - f25519_mul__distinct(r, s, x); - } - - /* 0 */ - f25519_mul__distinct(s, r, r); - - /* 1 */ - f25519_mul__distinct(r, s, s); - f25519_mul__distinct(s, r, x); - - /* 0 */ - f25519_mul__distinct(r, s, s); - - /* 1 */ - f25519_mul__distinct(s, r, r); - f25519_mul__distinct(r, s, x); - - /* 1 */ - f25519_mul__distinct(s, r, r); - f25519_mul__distinct(r, s, x); +void f25519_inv__distinct(uint8_t *r, const uint8_t *x) { + uint8_t s[F25519_SIZE]; + int i; + + /* This is a prime field, so by Fermat's little theorem: + * + * x^(p-1) = 1 mod p + * + * Therefore, raise to (p-2) = 2^255-21 to get a multiplicative + * inverse. + * + * This is a 255-bit binary number with the digits: + * + * 11111111... 01011 + * + * We compute the result by the usual binary chain, but + * alternate between keeping the accumulator in r and s, so as + * to avoid copying temporaries. + */ + + /* 1 1 */ + f25519_mul__distinct(s, x, x); + f25519_mul__distinct(r, s, x); + + /* 1 x 248 */ + for (i = 0; i < 248; i++) { + f25519_mul__distinct(s, r, r); + f25519_mul__distinct(r, s, x); + } + + /* 0 */ + f25519_mul__distinct(s, r, r); + + /* 1 */ + f25519_mul__distinct(r, s, s); + f25519_mul__distinct(s, r, x); + + /* 0 */ + f25519_mul__distinct(r, s, s); + + /* 1 */ + f25519_mul__distinct(s, r, r); + f25519_mul__distinct(r, s, x); + + /* 1 */ + f25519_mul__distinct(s, r, r); + f25519_mul__distinct(r, s, x); } -void f25519_inv(uint8_t *r, const uint8_t *x) -{ - uint8_t tmp[F25519_SIZE]; +void f25519_inv(uint8_t *r, const uint8_t *x) { + uint8_t tmp[F25519_SIZE]; - f25519_inv__distinct(tmp, x); - f25519_copy(r, tmp); + f25519_inv__distinct(tmp, x); + f25519_copy(r, tmp); } /* Raise x to the power of (p-5)/8 = 2^252-3, using s for temporary * storage. */ -static void exp2523(uint8_t *r, const uint8_t *x, uint8_t *s) -{ - int i; - - /* This number is a 252-bit number with the binary expansion: - * - * 111111... 01 - */ - - /* 1 1 */ - f25519_mul__distinct(r, x, x); - f25519_mul__distinct(s, r, x); - - /* 1 x 248 */ - for (i = 0; i < 248; i++) { - f25519_mul__distinct(r, s, s); - f25519_mul__distinct(s, r, x); - } - - /* 0 */ - f25519_mul__distinct(r, s, s); - - /* 1 */ - f25519_mul__distinct(s, r, r); - f25519_mul__distinct(r, s, x); +static void exp2523(uint8_t *r, const uint8_t *x, uint8_t *s) { + int i; + + /* This number is a 252-bit number with the binary expansion: + * + * 111111... 01 + */ + + /* 1 1 */ + f25519_mul__distinct(r, x, x); + f25519_mul__distinct(s, r, x); + + /* 1 x 248 */ + for (i = 0; i < 248; i++) { + f25519_mul__distinct(r, s, s); + f25519_mul__distinct(s, r, x); + } + + /* 0 */ + f25519_mul__distinct(r, s, s); + + /* 1 */ + f25519_mul__distinct(s, r, r); + f25519_mul__distinct(r, s, x); } -void f25519_sqrt(uint8_t *r, const uint8_t *a) -{ - uint8_t v[F25519_SIZE]; - uint8_t i[F25519_SIZE]; - uint8_t x[F25519_SIZE]; - uint8_t y[F25519_SIZE]; - - /* v = (2a)^((p-5)/8) [x = 2a] */ - f25519_mul_c(x, a, 2); - exp2523(v, x, y); - - /* i = 2av^2 - 1 */ - f25519_mul__distinct(y, v, v); - f25519_mul__distinct(i, x, y); - f25519_load(y, 1); - f25519_sub(i, i, y); - - /* r = avi */ - f25519_mul__distinct(x, v, a); - f25519_mul__distinct(r, x, i); +void f25519_sqrt(uint8_t *r, const uint8_t *a) { + uint8_t v[F25519_SIZE]; + uint8_t i[F25519_SIZE]; + uint8_t x[F25519_SIZE]; + uint8_t y[F25519_SIZE]; + + /* v = (2a)^((p-5)/8) [x = 2a] */ + f25519_mul_c(x, a, 2); + exp2523(v, x, y); + + /* i = 2av^2 - 1 */ + f25519_mul__distinct(y, v, v); + f25519_mul__distinct(i, x, y); + f25519_load(y, 1); + f25519_sub(i, i, y); + + /* r = avi */ + f25519_mul__distinct(x, v, a); + f25519_mul__distinct(r, x, i); } - /* Convert an Edwards Y to a Montgomery X (Edwards X is not used). * Resulting coordinate is normalized. */ +void morph25519_e2m(uint8_t *montgomery, const uint8_t *y) { + uint8_t yplus[F25519_SIZE]; + uint8_t yminus[F25519_SIZE]; - - -void morph25519_e2m(uint8_t *montgomery, const uint8_t *y) -{ - uint8_t yplus[F25519_SIZE]; - uint8_t yminus[F25519_SIZE]; - - f25519_sub(yplus, f25519_one, y); - f25519_inv__distinct(yminus, yplus); - f25519_add(yplus, f25519_one, y); - f25519_mul__distinct(montgomery, yplus, yminus); - f25519_normalize(montgomery); + f25519_sub(yplus, f25519_one, y); + f25519_inv__distinct(yminus, yplus); + f25519_add(yplus, f25519_one, y); + f25519_mul__distinct(montgomery, yplus, yminus); + f25519_normalize(montgomery); } - diff --git a/src/encryptDecryptMsg.c b/src/encryptDecryptMsg.c index 2a1fb75..905343c 100644 --- a/src/encryptDecryptMsg.c +++ b/src/encryptDecryptMsg.c @@ -1,45 +1,47 @@ /******************************************************************************* -* (c) 2019 Haim Bender -* -* -* 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 Haim Bender + * (c) 2021-2023 Jelurida IP B.V. + * + * + * 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 +#include #include -#include -#include "ux.h" - -#include "aes/aes.h" +#include "io.h" // io_send* +#include "parser.h" // command_t #include "returnValues.h" #include "config.h" #include "ardor.h" +#include "io_helper.h" +#define P1_INIT_ENCRYPT 1 +#define P1_INIT_DECRYPT_HIDE_SHARED_KEY 2 +#define P1_INIT_DECRYPT_SHOW_SHARED_KEY 3 +#define P1_AES_ENCRYPT_DECRYPT 4 -#define P1_INIT_ENCRYPT 1 -#define P1_INIT_DECRYPT_HIDE_SHARED_KEY 2 -#define P1_INIT_DECRYPT_SHOW_SHARED_KEY 3 -#define P1_AES_ENCRYPT_DECRYPT 4 - +#define NONCE_LENGTH 32 +#define IV_LENGTH 16 /* - This command allows the client to encrypt and decrypt messages that are assigned to some foreign public key and nonce - First you need to call the right INIT function, you have 3 choices. After that you call P1_AES_ENCRYPT_DECRYPT as many times as you need + This command allows the client to encrypt and decrypt messages that are assigned to some foreign + public key. First you need to call the right INIT function, you have 3 choices. After + that you call P1_AES_ENCRYPT_DECRYPT as many times as you need API: @@ -48,186 +50,175 @@ returns: 1 byte status | nonce (on success) | IV P1: P1_INIT_DECRYPT_HIDE_SHARED_KEY: - dataBuffer: derivaiton path (uint32) * some length | second party public key | nonce | IV + dataBuffer: derivation path (uint32) * some length | second party public key | nonce | IV returns: 1 byte status P1: P1_INIT_DECRYPT_SHOW_SHARED_KEY: - dataBuffer: derivaiton path (uint32) * some length | second party public key | nonce | IV + dataBuffer: derivation path (uint32) * some length | second party public key | nonce | IV returns: 1 byte status | sharedkey 32 bytes P1_AES_ENCRYPT_DECRYPT: - dataBuffer: buffer (224 max size) should be in modulu of 16 + dataBuffer: buffer (224 max size) should be in modulo 16 returns: 1 bytes status | encrypted / decrypted buffer (same size as input) */ -void cleanEncryptionState() { - state.encryption.mode = 0; +static int cleanAndReturn(uint8_t ret) { + cleanState(); + return io_send_return1(ret); } +static bool getDerivationLength(const uint8_t p1, + const uint8_t dataLength, + uint8_t* derivationLength) { + int16_t derivationLengthSigned = 0; -//declerations of all AES functions, not including the h file to avoid mess of types -bool aes_decrypt_init_fixed(const aes_uchar *key, size_t len, aes_uint * rk); -void aes_decrypt(void *ctx, const aes_uchar *crypt, aes_uchar *plain); -bool aes_encrypt_init_fixed(const aes_uchar *key, size_t len, aes_uint *rk); -void aes_encrypt(void *ctx, const aes_uchar *plain, aes_uchar *crypt); - - -//Since this is a callback function, and the handler manages state, it's this function's reposibility to clean the state -//Every time we get some sort of an error -void encryptDecryptMessageHandlerHelper(const uint8_t p1, const uint8_t p2, const uint8_t * const dataBuffer, const uint8_t dataLength, - uint8_t * const flags, uint8_t * const tx, const bool isLastCommandDifferent) { - - UNUSED(p2); - UNUSED(flags); - - if (isLastCommandDifferent) - cleanEncryptionState(); - - if ((P1_INIT_ENCRYPT == p1) || (P1_INIT_DECRYPT_HIDE_SHARED_KEY == p1) || (P1_INIT_DECRYPT_SHOW_SHARED_KEY == p1)) { - - if (0 != dataLength % sizeof(uint32_t)) { - cleanEncryptionState(); - G_io_apdu_buffer[(*tx)++] = R_WRONG_SIZE_ERR; - return; - } + if (p1 == P1_INIT_ENCRYPT) { + // no underflow because the type is signed + derivationLengthSigned = (dataLength - PUBLIC_KEY_SIZE) / sizeof(uint32_t); + } else { + derivationLengthSigned = + (dataLength - PUBLIC_KEY_SIZE - NONCE_LENGTH - IV_LENGTH) / sizeof(uint32_t); + } - int16_t derivationLengthSigned = 0; + if ((derivationLengthSigned < MIN_DERIVATION_LENGTH) || + (derivationLengthSigned > MAX_DERIVATION_LENGTH)) { + return false; + } - if (P1_INIT_ENCRYPT == p1) - derivationLengthSigned = (dataLength - 32) / sizeof(uint32_t); //no underflow because type is signed - else - derivationLengthSigned = (dataLength - 32 * 2 - 16) / sizeof(uint32_t); + *derivationLength = (uint8_t) derivationLengthSigned; // cast is ok, because of the check above + return true; +} - if ((MIN_DERIVATION_LENGTH > derivationLengthSigned) || (MAX_DERIVATION_LENGTH < derivationLengthSigned)) { - cleanEncryptionState(); - G_io_apdu_buffer[(*tx)++] = R_WRONG_SIZE_ERR; - return; - } +static int initHandler(const command_t* const cmd) { + if (cmd->lc % sizeof(uint32_t) != 0) { + return cleanAndReturn(R_WRONG_SIZE_ERR); + } - uint8_t derivationLength = derivationLengthSigned; //cast is ok, because if the check above + if (cmd->lc > MAX_CHUNK_SIZE_ENCRYPT) { + return cleanAndReturn(R_NO_SPACE_BUFFER_TOO_SMALL); + } - uint8_t nonce[32]; - const uint8_t * noncePtr = dataBuffer + derivationLength * sizeof(uint32_t) + 32; + uint8_t derivationLength = 0; + if (!getDerivationLength(cmd->p1, cmd->lc, &derivationLength)) { + return cleanAndReturn(R_WRONG_SIZE_ERR); + } - if (P1_INIT_ENCRYPT == p1) { - cx_rng(nonce, sizeof(nonce)); - noncePtr = nonce; //if we are decrypting then we are using from the command - } + uint8_t nonce[NONCE_LENGTH]; + const uint8_t* noncePtr = cmd->data + derivationLength * sizeof(uint32_t) + PUBLIC_KEY_SIZE; - uint16_t exceptionOut = 0; - uint8_t encryptionKey[32]; - - uint8_t ret = getSharedEncryptionKey(dataBuffer, derivationLength, dataBuffer + derivationLength * sizeof(uint32_t), noncePtr, &exceptionOut, encryptionKey); - - if (R_KEY_DERIVATION_EX == ret) { - cleanEncryptionState(); - G_io_apdu_buffer[0] = ret; - G_io_apdu_buffer[1] = exceptionOut >> 8; - G_io_apdu_buffer[2] = exceptionOut & 0xFF; - *tx = 3; - return; - } else if (R_SUCCESS != ret) { - cleanEncryptionState(); - G_io_apdu_buffer[0] = ret; - *tx = 1; - return; - } + if (cmd->p1 == P1_INIT_ENCRYPT) { + cx_trng_get_random_data(nonce, sizeof(nonce)); + noncePtr = nonce; // if we are decrypting then we are using from the command + } - if (P1_INIT_ENCRYPT == p1) { - if (!aes_encrypt_init_fixed(encryptionKey, 32, state.encryption.ctx)) { - cleanEncryptionState(); - G_io_apdu_buffer[0] = R_AES_ERROR; - *tx = 1; - return; - } - } else { - if (!aes_decrypt_init_fixed(encryptionKey, 32, state.encryption.ctx)) { - cleanEncryptionState(); - G_io_apdu_buffer[0] = R_AES_ERROR; - *tx = 1; - return; - } + uint16_t exceptionOut = 0; + uint8_t encryptionKey[32]; + + uint8_t ret = getSharedEncryptionKey(cmd->data, + derivationLength, + cmd->data + derivationLength * sizeof(uint32_t), + noncePtr, + &exceptionOut, + encryptionKey); + + if (ret == R_KEY_DERIVATION_EX) { + cleanState(); + explicit_bzero(encryptionKey, sizeof(encryptionKey)); // cleaning the key from memory + return io_send_return3(ret, exceptionOut >> 8, exceptionOut & 0xFF); + } else if (ret != R_SUCCESS) { + explicit_bzero(encryptionKey, sizeof(encryptionKey)); // cleaning the key from memory + return cleanAndReturn(ret); + } - memcpy(state.encryption.cbc, dataBuffer + dataLength - sizeof(state.encryption.cbc), sizeof(state.encryption.cbc)); //Copying the IV into the CBC - } - - state.encryption.mode = p1; - G_io_apdu_buffer[(*tx)++] = R_SUCCESS; - - if (P1_INIT_ENCRYPT == p1) { - memcpy(G_io_apdu_buffer + *tx, nonce, sizeof(nonce)); - *tx+= 32; - cx_rng(state.encryption.cbc, sizeof(state.encryption.cbc)); //The IV is stored in the CVC - memcpy(G_io_apdu_buffer + *tx, state.encryption.cbc, sizeof(state.encryption.cbc)); - *tx+= sizeof(state.encryption.cbc); - } else if (P1_INIT_DECRYPT_SHOW_SHARED_KEY == p1) { - memcpy(G_io_apdu_buffer + *tx, encryptionKey, sizeof(encryptionKey)); - *tx+= 32; - } + if (cx_aes_init_key_no_throw(encryptionKey, sizeof(encryptionKey), &state.encryption.aesKey) != + CX_OK) { + return cleanAndReturn(R_AES_ERROR); + } + if (cmd->p1 != P1_INIT_ENCRYPT) { + // Copying the IV into the CBC + memcpy(state.encryption.cbc, + cmd->data + cmd->lc - sizeof(state.encryption.cbc), + sizeof(state.encryption.cbc)); + } - } else if (P1_AES_ENCRYPT_DECRYPT == p1) { + state.encryption.mode = cmd->p1; + state.encryption.buffer[0] = R_SUCCESS; + size_t bufferSize = 1; + + if (cmd->p1 == P1_INIT_ENCRYPT) { + memcpy(state.encryption.buffer + bufferSize, nonce, sizeof(nonce)); + bufferSize += sizeof(nonce); + // The IV is stored in the CBC + cx_trng_get_random_data(state.encryption.cbc, sizeof(state.encryption.cbc)); + memcpy(state.encryption.buffer + bufferSize, + state.encryption.cbc, + sizeof(state.encryption.cbc)); + bufferSize += sizeof(state.encryption.cbc); + } else if (cmd->p1 == P1_INIT_DECRYPT_SHOW_SHARED_KEY) { + memcpy(state.encryption.buffer + bufferSize, encryptionKey, sizeof(encryptionKey)); + bufferSize += sizeof(encryptionKey); + } - if (isLastCommandDifferent) { - cleanEncryptionState(); - G_io_apdu_buffer[(*tx)++] = R_NO_SETUP; - return; - } + explicit_bzero(encryptionKey, sizeof(encryptionKey)); // cleaning the key from memory + return io_send_response_pointer(state.encryption.buffer, bufferSize, SW_OK); +} - if ((P1_INIT_ENCRYPT != state.encryption.mode) && (P1_INIT_DECRYPT_HIDE_SHARED_KEY != state.encryption.mode) && - (P1_INIT_DECRYPT_SHOW_SHARED_KEY != state.encryption.mode)) - { - cleanEncryptionState(); - G_io_apdu_buffer[(*tx)++] = R_NO_SETUP; - return; - } +static int aesEncryptDecryptHandler(const command_t* const cmd) { + if ((state.encryption.mode != P1_INIT_ENCRYPT) && + (state.encryption.mode != P1_INIT_DECRYPT_HIDE_SHARED_KEY) && + (state.encryption.mode != P1_INIT_DECRYPT_SHOW_SHARED_KEY)) { + return cleanAndReturn(R_NO_SETUP); + } - if (0 != dataLength % 16) { - cleanEncryptionState(); - G_io_apdu_buffer[(*tx)++] = R_WRONG_SIZE_MODULO_ERR; - return; - } + if (cmd->lc % CX_AES_BLOCK_SIZE != 0) { + return cleanAndReturn(R_WRONG_SIZE_MODULO_ERR); + } - uint8_t * pos = G_io_apdu_buffer + OFFSET_CDATA; - uint8_t tmp[AES_BLOCK_SIZE]; + if (cmd->data == 0) { + return cleanAndReturn(R_NOT_ALL_BYTES_READ); + } - while (pos < dataBuffer + dataLength) { - if (P1_INIT_ENCRYPT == state.encryption.mode) { //if we are doing encryption: + uint8_t* inPtr = cmd->data; + uint8_t* outPtr = state.encryption.buffer + 1; + state.encryption.buffer[0] = R_SUCCESS; - for (uint8_t j = 0; j < AES_BLOCK_SIZE; j++) - state.encryption.cbc[j] ^= pos[j]; + uint8_t* cbc = state.encryption.cbc; // Temporary variable + while (inPtr < cmd->data + cmd->lc) { + if (state.encryption.mode == P1_INIT_ENCRYPT) { // if we are doing encryption + for (uint8_t j = 0; j < CX_AES_BLOCK_SIZE; j++) { + cbc[j] ^= inPtr[j]; + } - aes_encrypt(state.encryption.ctx, state.encryption.cbc, state.encryption.cbc); - memcpy(pos, state.encryption.cbc, AES_BLOCK_SIZE); - } else { - memcpy(tmp, pos, AES_BLOCK_SIZE); - aes_decrypt(state.encryption.ctx, pos, pos); - for (uint8_t j = 0; j < AES_BLOCK_SIZE; j++) - pos[j] ^= state.encryption.cbc[j]; + if (cx_aes_enc_block(&state.encryption.aesKey, cbc, cbc) != CX_OK) { + return cleanAndReturn(R_CXLIB_ERROR); + } + memcpy(outPtr, cbc, CX_AES_BLOCK_SIZE); + } else { + if (cx_aes_dec_block(&state.encryption.aesKey, inPtr, outPtr) != CX_OK) { + return cleanAndReturn(R_CXLIB_ERROR); + } - memcpy(state.encryption.cbc, tmp, AES_BLOCK_SIZE); + for (uint8_t j = 0; j < CX_AES_BLOCK_SIZE; j++) { + outPtr[j] ^= cbc[j]; } - pos += AES_BLOCK_SIZE; + memcpy(cbc, inPtr, CX_AES_BLOCK_SIZE); } - - *tx = 1 + dataLength; - - for (uint8_t i = 0; i < dataLength; i++) - G_io_apdu_buffer[i+1] = G_io_apdu_buffer[OFFSET_CDATA + i]; - - G_io_apdu_buffer[0] = R_SUCCESS; - - } else { - cleanEncryptionState(); - G_io_apdu_buffer[(*tx)++] = R_UNKOWN_CMD; + inPtr += CX_AES_BLOCK_SIZE; + outPtr += CX_AES_BLOCK_SIZE; } + return io_send_response_pointer(state.encryption.buffer, cmd->lc + 1, SW_OK); } -void encryptDecryptMessageHandler(const uint8_t p1, const uint8_t p2, const uint8_t * const dataBuffer, const uint8_t dataLength, - uint8_t * const flags, uint8_t * const tx, const bool isLastCommandDifferent) { - - encryptDecryptMessageHandlerHelper(p1, p2, dataBuffer, dataLength, flags, tx, isLastCommandDifferent); - - G_io_apdu_buffer[(*tx)++] = 0x90; - G_io_apdu_buffer[(*tx)++] = 0x00; +// Since this is a callback function, and the handler manages state, it's this function's +// reposibility to clean the state Every time we get some sort of an error +int encryptDecryptMessageHandler(const command_t* const cmd) { + if ((cmd->p1 == P1_INIT_ENCRYPT) || (cmd->p1 == P1_INIT_DECRYPT_HIDE_SHARED_KEY) || + (cmd->p1 == P1_INIT_DECRYPT_SHOW_SHARED_KEY)) { + return initHandler(cmd); + } else if (cmd->p1 == P1_AES_ENCRYPT_DECRYPT) { + return aesEncryptDecryptHandler(cmd); + } else { + return cleanAndReturn(R_UNKOWN_CMD); + } } diff --git a/src/getPublicKeyAndChaincode.c b/src/getPublicKeyAndChaincode.c index 7d2cd64..e8a04f1 100644 --- a/src/getPublicKeyAndChaincode.c +++ b/src/getPublicKeyAndChaincode.c @@ -1,37 +1,39 @@ /******************************************************************************* -* (c) 2019 Haim Bender -* -* -* 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 Haim Bender + * (c) 2021-2023 Jelurida IP B.V. + * + * + * 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 +#include -#include -#include -#include "ux.h" +#include "parser.h" // command_t +#include "io.h" // io_send* #include "returnValues.h" #include "config.h" #include "ardor.h" +#include "io_helper.h" -#define P1_GET_PUBLIC_KEY 1 -#define P1_GET_PUBLIC_KEY_CHAIN_CODE_AND_ED_PUBLIC_KEY 2 - +#define P1_GET_PUBLIC_KEY 1 +#define P1_GET_PUBLIC_KEY_CHAIN_CODE_AND_ED_PUBLIC_KEY 2 /* - This command allows the client to the EC-KCDSA public key, chain code and ED25519 public key for a requested derivation path + This command allows the client to the EC-KCDSA public key, chain code and ED25519 public key for + a requested derivation path API: @@ -45,70 +47,40 @@ */ - - -void getPublicKeyAndChainCodeHandlerHelper(const uint8_t p1, const uint8_t p2, const uint8_t * const dataBuffer, const uint8_t dataLength, - uint8_t * const flags, uint8_t * const tx) { - - UNUSED(p2); UNUSED(flags); - - if ((P1_GET_PUBLIC_KEY != p1) && (P1_GET_PUBLIC_KEY_CHAIN_CODE_AND_ED_PUBLIC_KEY != p1)) { - G_io_apdu_buffer[(*tx)++] = R_UNKNOWN_CMD_PARAM_ERR; - return; +#define BUFFER_R_SUCESS_OFFSET 0 +#define BUFFER_PUBLIC_KEY_CURVE_OFFSET 1 +#define BUFFER_PUBLIC_KEY_ED25519_OFFSET 33 +#define BUFFER_CHAIN_CODE_OFFSET 65 +#define BUFFER_SIZE 97 // 1 R_SUCCESS + 32 publicKeyCurve + 32 publicKeyEd25519YLE + 32 chainCode +#define REDUCED_RESPONSE_SIZE 33 // 1 R_SUCCESS + 32 publicKeyCurve + +int getPublicKeyAndChainCodeHandler(const command_t* const cmd) { + if ((cmd->p1 != P1_GET_PUBLIC_KEY) && + (cmd->p1 != P1_GET_PUBLIC_KEY_CHAIN_CODE_AND_ED_PUBLIC_KEY)) { + return io_send_return1(R_UNKNOWN_CMD_PARAM_ERR); } - if ((MIN_DERIVATION_LENGTH * sizeof(uint32_t) > dataLength) || (MAX_DERIVATION_LENGTH * sizeof(uint32_t) < dataLength)) { - G_io_apdu_buffer[(*tx)++] = R_WRONG_SIZE_ERR; - return; + if (!isValidDerivationPathLength(cmd->lc)) { + return io_send_return1(R_WRONG_SIZE_ERR); } - uint8_t derivationParamLengthInBytes = dataLength; - - if (0 != derivationParamLengthInBytes % sizeof(uint32_t)) { - G_io_apdu_buffer[(*tx)++] = R_UNKNOWN_CMD_PARAM_ERR; - return; - } - - uint8_t publicKeyEd25519YLE[32]; - uint8_t publicKeyCurve[32]; - uint8_t chainCode[32]; - //uint8_t K[64]; //DO NOT COMMIT THIS LINE!!! DO NOT COMMIT THIS LINE!!!!, used for testing only, to send the privatekey to the client, private key should never be released + // Instead of having 3 buffers for the public keys and chain code we use one buffer that + // we will directly send as an APDU, instead of having to copy the data to the APDU buffer. + uint8_t buffer[BUFFER_SIZE]; uint16_t exception = 0; - uint8_t ret = ardorKeys(dataBuffer, derivationParamLengthInBytes / sizeof(uint32_t), 0, publicKeyCurve, publicKeyEd25519YLE, chainCode, &exception); - //uint8_t ret = ardorKeys(derivationPathCpy, derivationParamLengthInBytes / sizeof(uint32_t), K, publicKeyCurve, publicKeyEd25519YLE, chainCode, &exception); //DO NOT COMMIT THIS LINE!!! DO NOT COMMIT THIS LINE!!!!, used for testing only, to send the privatekey to the client, private key should never be released - - G_io_apdu_buffer[(*tx)++] = ret; + uint8_t ret = ardorKeys(cmd->data, + cmd->lc / sizeof(uint32_t), + 0, + buffer + BUFFER_PUBLIC_KEY_CURVE_OFFSET, + buffer + BUFFER_PUBLIC_KEY_ED25519_OFFSET, + buffer + BUFFER_CHAIN_CODE_OFFSET, + &exception); - if (R_SUCCESS == ret) { - - memmove(G_io_apdu_buffer + *tx, publicKeyCurve, sizeof(publicKeyCurve)); - *tx += sizeof(publicKeyCurve); - - if (P1_GET_PUBLIC_KEY_CHAIN_CODE_AND_ED_PUBLIC_KEY == p1) { - memmove(G_io_apdu_buffer + *tx, publicKeyEd25519YLE, sizeof(publicKeyEd25519YLE)); - *tx += sizeof(publicKeyEd25519YLE); - - memmove(G_io_apdu_buffer + *tx, chainCode, sizeof(chainCode)); - *tx += sizeof(chainCode); - - //memmove(G_io_apdu_buffer + *tx, K, sizeof(K)); //DO NOT COMMIT THIS LINE!!! DO NOT COMMIT THIS LINE!!!!, used for testing only, to send the privatekey to the client, private key should never be released - //*tx += sizeof(K); //DO NOT COMMIT THIS LINE!!! DO NOT COMMIT THIS LINE!!!!, used for testing only, to send the privatekey to the client, private key should never be released - } - - } else if (R_KEY_DERIVATION_EX == ret) { - G_io_apdu_buffer[(*tx)++] = exception >> 8; - G_io_apdu_buffer[(*tx)++] = exception & 0xFF; + if (ret != R_SUCCESS) { + return io_send_return3(ret, exception >> 8, exception & 0xFF); } -} - -void getPublicKeyAndChainCodeHandler(const uint8_t p1, const uint8_t p2, const uint8_t * const dataBuffer, const uint8_t dataLength, - uint8_t * const flags, uint8_t * const tx, const bool isLastCommandDifferent) { - - UNUSED(isLastCommandDifferent); //there is no state to manage, so there's nothing to do with this parameter - - getPublicKeyAndChainCodeHandlerHelper(p1, p2, dataBuffer, dataLength, flags, tx); - - G_io_apdu_buffer[(*tx)++] = 0x90; - G_io_apdu_buffer[(*tx)++] = 0x00; + buffer[0] = R_SUCCESS; + size_t responseSize = cmd->p1 == P1_GET_PUBLIC_KEY ? REDUCED_RESPONSE_SIZE : BUFFER_SIZE; + return io_send_response_pointer(buffer, responseSize, SW_OK); } diff --git a/src/getVersion.c b/src/getVersion.c index 23a21d7..5755ee0 100644 --- a/src/getVersion.c +++ b/src/getVersion.c @@ -1,42 +1,44 @@ /******************************************************************************* -* (c) 2019 Haim Bender -* -* -* 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 Haim Bender + * (c) 2021-2023 Jelurida IP B.V. + * + * + * 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 -#include #include +#include -#include "config.h" - -//function that returns the version, in order to see if this is actually the ardor app -//returns VERSION 2 bytes | FLAGS 1 byte | ARDOR_SPECIAL_IDENTIFIER 3 bytes -void getVersionHandler(const uint8_t p1, const uint8_t p2, const uint8_t * const dataBuffer, const uint8_t dataLength, - uint8_t * const flags, uint8_t * const tx, const bool isLastCommandDifferent) { +#include "io.h" // io_send* +#include "parser.h" // command_t +#include "os_helpers.h" // UNUSED - UNUSED(p1); UNUSED(p2); UNUSED(dataBuffer); UNUSED(dataLength); UNUSED(flags); UNUSED(isLastCommandDifferent); - - G_io_apdu_buffer[(*tx)++] = APPVERSION_M; - G_io_apdu_buffer[(*tx)++] = APPVERSION_N; - G_io_apdu_buffer[(*tx)++] = APPVERSION_P; - G_io_apdu_buffer[(*tx)++] = VERSION_FLAGS; +#include "config.h" +#include "returnValues.h" - memmove(G_io_apdu_buffer + (*tx), ARDOR_SPECIAL_IDENTIFIER, ARDOR_SPECIAL_IDENTIFIER_LEN); - *tx += ARDOR_SPECIAL_IDENTIFIER_LEN; +// function that returns the version, in order to see if this is actually the ardor app +// returns VERSION 3 bytes | FLAGS 1 byte | ARDOR_SPECIAL_IDENTIFIER 3 bytes +int getVersionHandler(const command_t *const cmd) { + UNUSED(cmd); - G_io_apdu_buffer[(*tx)++] = 0x90; - G_io_apdu_buffer[(*tx)++] = 0x00; + uint8_t data[7]; + data[0] = APPVERSION_M; + data[1] = APPVERSION_N; + data[2] = APPVERSION_P; + data[3] = VERSION_FLAGS; + memmove(data + 4, ARDOR_SPECIAL_IDENTIFIER, ARDOR_SPECIAL_IDENTIFIER_LEN); + return io_send_response_pointer((const uint8_t *) data, + 4 + ARDOR_SPECIAL_IDENTIFIER_LEN, + SW_OK); } diff --git a/src/io_helper.c b/src/io_helper.c new file mode 100644 index 0000000..aa9aea7 --- /dev/null +++ b/src/io_helper.c @@ -0,0 +1,18 @@ +#include "io_helper.h" +#include "io.h" // io_send_response_pointer + +#define SW_OK 0x9000 + +int io_send_return1(uint8_t ret) { + return io_send_response_pointer(&(const uint8_t){ret}, 1, SW_OK); +} + +int io_send_return2(uint8_t byte1, uint8_t byte2) { + return io_send_response_pointer((const uint8_t *) &(const uint8_t[2]){byte1, byte2}, 2, SW_OK); +} + +int io_send_return3(uint8_t byte1, uint8_t byte2, uint8_t byte3) { + return io_send_response_pointer((const uint8_t *) &(const uint8_t[3]){byte1, byte2, byte3}, + 3, + SW_OK); +} \ No newline at end of file diff --git a/src/io_helper.h b/src/io_helper.h new file mode 100644 index 0000000..99af674 --- /dev/null +++ b/src/io_helper.h @@ -0,0 +1,7 @@ +#pragma once + +#include + +int io_send_return1(uint8_t ret); +int io_send_return2(uint8_t byte1, uint8_t byte2); +int io_send_return3(uint8_t byte1, uint8_t byte2, uint8_t byte3); \ No newline at end of file diff --git a/src/main.c b/src/main.c deleted file mode 100644 index ab1e701..0000000 --- a/src/main.c +++ /dev/null @@ -1,374 +0,0 @@ -/******************************************************************************* -* -* (c) 2016 Ledger -* (c) 2018 Nebulous -* (c) 2019 Haim Bender -* -* -* 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 -#include -#include "glyphs.h" -#include "ux.h" - -#include "config.h" -#include "ardor.h" -#include "returnValues.h" - -ux_state_t G_ux; -bolos_ux_params_t G_ux_params; - -UX_STEP_NOCB( - ux_idle_flow_1_step, - bn, - { - "Application", - "is ready", - }); -UX_STEP_NOCB( - ux_idle_flow_2_step, - bn, - { - "Version", - APPVERSION, - }); -UX_STEP_VALID( - ux_idle_flow_3_step, - pb, - os_sched_exit(-1), - { - &C_icon_dashboard, - "Quit", - }); -const ux_flow_step_t * const ux_idle_flow [] = { - &ux_idle_flow_1_step, - &ux_idle_flow_2_step, - &ux_idle_flow_3_step, - FLOW_END_STEP, -}; - - -// ui_idle displays the main menu. Note that your app isn't required to use a -// menu as its idle screen; you can define your own completely custom screen. -void ui_idle() { - // reserve a display stack slot if none yet - if(G_ux.stack_count == 0) { - ux_stack_push(); - } - ux_flow_init(0, ux_idle_flow, NULL); -} - - -// The APDU protocol uses a single-byte instruction code (INS) to specify -// which command should be executed. We'll use this code to dispatch on a -// table of function pointers. -#define INS_GET_VERSION 0x01 -#define INS_AUTH_SIGN_TXN 0x03 -#define INS_ENCRYPT_DECRYPT_MSG 0x04 -#define INS_SHOW_ADDRESS 0x05 -#define INS_GET_PUBLIC_KEY_AND_CHAIN_CODE 0x06 -#define INS_SIGN_TOKEN 0x07 - -// This is the function signature for a command handler. 'flags' and 'tx' are -// out-parameters that will control the behavior of the next io_exchange call -typedef void handler_fn_t(const uint8_t p1, const uint8_t p2, const uint8_t *dataBuffer, const uint16_t dataLength, uint8_t * const flags, uint8_t * const tx, const bool isLastCommandDifferent); - -handler_fn_t getVersionHandler; -handler_fn_t authAndSignTxnHandler; -handler_fn_t encryptDecryptMessageHandler; -handler_fn_t showAddressHandler; -handler_fn_t getPublicKeyAndChainCodeHandler; -handler_fn_t signTokenMessageHandler; - -//function translate command ID to function PTR -static handler_fn_t* lookupHandler(uint8_t ins) { - switch (ins) { - case INS_GET_VERSION: return getVersionHandler; - case INS_AUTH_SIGN_TXN: return authAndSignTxnHandler; - case INS_ENCRYPT_DECRYPT_MSG: return encryptDecryptMessageHandler; - case INS_SHOW_ADDRESS: return showAddressHandler; - case INS_GET_PUBLIC_KEY_AND_CHAIN_CODE: return getPublicKeyAndChainCodeHandler; - case INS_SIGN_TOKEN: return signTokenMessageHandler; - default: return NULL; - } -} - - -//thit is used to clean state if we change command types -uint8_t lastCmdNumber = 0; - - -//Does what it says, in return buffers the first byte is the return code, 0 is sucess allways -//and all the buffer have 0x90,0x00 at the end, even on errors -void fillBufferWithAnswerAndEnding(const uint8_t answer, uint8_t * const tx) { - if (0 == tx) { - G_io_apdu_buffer[0] = answer; - G_io_apdu_buffer[1] = 0x90; - G_io_apdu_buffer[2] = 0x00; - } else { - G_io_apdu_buffer[(*tx)++] = answer; - G_io_apdu_buffer[(*tx)++] = 0x90; - G_io_apdu_buffer[(*tx)++] = 0x00; - } -} - - - - -// This is the main loop that reads and writes APDUs. It receives request -// APDUs from the computer, looks up the corresponding command handler, and -// calls it on the APDU payload. Then it loops around and calls io_exchange -// again. The handler may set the 'flags' and 'tx' variables, which affect the -// subsequent io_exchange call. The handler may also throw an exception, which -// will be caught, converted to an error code, appended to the response APDU, -// and sent in the next io_exchange call. -static void ardor_main(void) { - - lastCmdNumber = 0; - - uint8_t rx = 0; - uint8_t tx = 0; - uint8_t flags = 0; - - // Exchange APDUs until EXCEPTION_IO_RESET is thrown. - for (;;) { - // The Ledger SDK implements a form of exception handling. In addition - // to explicit THROWs in user code, syscalls (prefixed with os_ or - // cx_) may also throw exceptions. - // - // This TRY block serves to catch any thrown exceptions - // and convert them to response codes, which are then sent in APDUs. - // However, EXCEPTION_IO_RESET will be re-thrown and caught by the - // "true" main function defined at the bottom of this file. - - - BEGIN_TRY { - TRY { - rx = tx; - tx = 0; // ensure no race in CATCH_OTHER if io_exchange throws an error - - rx = io_exchange(CHANNEL_APDU | flags, rx); - flags = 0; - - // No APDU received; trigger a reset. - if (rx == 0) { - THROW(EXCEPTION_IO_RESET); //lastCmdNumber will be zero'd when ardor_main will be called again - } - // Malformed APDU. - if (CLA != G_io_apdu_buffer[OFFSET_CLA]) { - lastCmdNumber = 0; //forces the next handler call to clean the state - fillBufferWithAnswerAndEnding(R_BAD_CLA, &tx); - continue; - } - - // Lookup and call the requested command handler. - handler_fn_t *handlerFn = lookupHandler(G_io_apdu_buffer[OFFSET_INS]); - if (!handlerFn) { - lastCmdNumber = 0; //force the next handler call to clean the state - fillBufferWithAnswerAndEnding(R_UNKOWN_CMD, &tx); - continue; - } - - PRINTF("\n canery check %d last command number %d \n", check_canary(), lastCmdNumber); - - uint8_t lastCommandSaver = G_io_apdu_buffer[OFFSET_INS]; //the handler is going to write over the buffer, so the command needs to be put aside - - handlerFn(G_io_apdu_buffer[OFFSET_P1], G_io_apdu_buffer[OFFSET_P2], - G_io_apdu_buffer + OFFSET_CDATA, G_io_apdu_buffer[OFFSET_LC], &flags, &tx, G_io_apdu_buffer[OFFSET_INS] != lastCmdNumber); - - lastCmdNumber = lastCommandSaver; - } - CATCH(EXCEPTION_IO_RESET) { - THROW(EXCEPTION_IO_RESET); //lastCmdNumber will be zero'd when ardor_main will be called again - } - CATCH_OTHER(e) { - - //just to make sure there is no hacking going on - //reset all the states - lastCmdNumber = 0; - - tx = 0; - flags = 0; - - G_io_apdu_buffer[tx++] = R_EXCEPTION; - G_io_apdu_buffer[tx++] = e >> 8; - fillBufferWithAnswerAndEnding(e & 0xFF, &tx); - } - FINALLY { - } - } - END_TRY; - } -} - - -// Everything below this point is Ledger magic. And the magic isn't well- -// documented, so if you want to understand it, you'll need to read the -// source, which you can find in the nanos-secure-sdk repo. Fortunately, you -// don't need to understand any of this in order to write an app. -// -// Next, we'll look at how the various commands are implemented. We'll start -// with the sizeofmplest command, signHash.c. - -// override point, but nothing more to do -void io_seproxyhal_display(const bagl_element_t *element) { - io_seproxyhal_display_default((bagl_element_t *)element); -} - -unsigned char G_io_seproxyhal_spi_buffer[IO_SEPROXYHAL_BUFFER_SIZE_B]; - -unsigned char io_event(unsigned char channel) { - - UNUSED(channel); - - // can't have more than one tag in the reply, not supported yet. - switch (G_io_seproxyhal_spi_buffer[0]) { - case SEPROXYHAL_TAG_FINGER_EVENT: - UX_FINGER_EVENT(G_io_seproxyhal_spi_buffer); - break; - - case SEPROXYHAL_TAG_BUTTON_PUSH_EVENT: - UX_BUTTON_PUSH_EVENT(G_io_seproxyhal_spi_buffer); - break; - -#ifdef HAVE_BLE - // Make automatically discoverable again when disconnected - case SEPROXYHAL_TAG_BLE_CONNECTION_EVENT: - if (G_io_seproxyhal_spi_buffer[3] == 0) { - // TODO : cleaner reset sequence - // first disable BLE before turning it off - G_io_seproxyhal_spi_buffer[0] = SEPROXYHAL_TAG_BLE_RADIO_POWER; - G_io_seproxyhal_spi_buffer[1] = 0; - G_io_seproxyhal_spi_buffer[2] = 1; - G_io_seproxyhal_spi_buffer[3] = 0; - io_seproxyhal_spi_send(G_io_seproxyhal_spi_buffer, 4); - // send BLE power on (default parameters) - G_io_seproxyhal_spi_buffer[0] = SEPROXYHAL_TAG_BLE_RADIO_POWER; - G_io_seproxyhal_spi_buffer[1] = 0; - G_io_seproxyhal_spi_buffer[2] = 1; - G_io_seproxyhal_spi_buffer[3] = 3; // ble on & advertise - io_seproxyhal_spi_send(G_io_seproxyhal_spi_buffer, 5); - } - break; -#endif - - case SEPROXYHAL_TAG_STATUS_EVENT: - if (G_io_apdu_media == IO_APDU_MEDIA_USB_HID && - !(U4BE(G_io_seproxyhal_spi_buffer, 3) & - SEPROXYHAL_TAG_STATUS_EVENT_FLAG_USB_POWERED)) { - THROW(EXCEPTION_IO_RESET); - } - UX_DEFAULT_EVENT(); - break; - - case SEPROXYHAL_TAG_DISPLAY_PROCESSED_EVENT: - UX_DISPLAYED_EVENT({}); - break; - - case SEPROXYHAL_TAG_TICKER_EVENT: - UX_TICKER_EVENT(G_io_seproxyhal_spi_buffer, {}); - break; - - default: - UX_DEFAULT_EVENT(); - break; - } - - // close the event if not done previously (by a display or whatever) - if (!io_seproxyhal_spi_is_status_sent()) { - io_seproxyhal_general_status(); - } - - // command has been processed, DO NOT reset the current APDU transport - return 1; -} - -unsigned short io_exchange_al(unsigned char channel, unsigned short tx_len) { - switch (channel & ~(IO_FLAGS)) { - case CHANNEL_KEYBOARD: - break; - // multiplexed io exchange over a SPI channel and TLV encapsulated protocol - case CHANNEL_SPI: - if (tx_len) { - io_seproxyhal_spi_send(G_io_apdu_buffer, tx_len); - if (channel & IO_RESET_AFTER_REPLIED) { - reset(); - } - return 0; // nothing received from the master so far (it's a tx transaction) - } else { - return io_seproxyhal_spi_recv(G_io_apdu_buffer, sizeof(G_io_apdu_buffer), 0); - } - default: - THROW(INVALID_PARAMETER); - } - return 0; -} - -static void app_exit(void) { - BEGIN_TRY_L(exit) { - TRY_L(exit) { - os_sched_exit(-1); - } - FINALLY_L(exit) { - } - } - END_TRY_L(exit); -} - -__attribute__((section(".boot"))) int main(void) { - // exit critical section - __asm volatile("cpsie i"); - - for (;;) { - UX_INIT(); - os_boot(); - BEGIN_TRY { - TRY { - io_seproxyhal_init(); - #ifdef TARGET_NANOX - // grab the current plane mode setting - G_io_app.plane_mode = os_setting_get(OS_SETTING_PLANEMODE, NULL, 0); - #endif // TARGET_NANOX - USB_power(0); - USB_power(1); - ui_idle(); - - PRINTF("aasdasd ardor"); - - - #ifdef HAVE_BLE - BLE_power(0, NULL); - BLE_power(1, "Nano X"); - #endif // HAVE_BLE - - ardor_main(); - - } - CATCH(EXCEPTION_IO_RESET) { - // reset IO and UX before continuing - continue; - } - CATCH_ALL { - break; - } - FINALLY { - } - } - END_TRY; - } - app_exit(); - return 0; -} diff --git a/src/reedSolomon.c b/src/reedSolomon.c index 8b19a41..a63f8ef 100644 --- a/src/reedSolomon.c +++ b/src/reedSolomon.c @@ -1,54 +1,53 @@ /******************************************************************************* -* (c) 2019 Haim Bender -* -* -* 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 Haim Bender + * (c) 2021-2023 Jelurida IP B.V. + * + * + * 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 - #define BASE_32_LENGTH 13 #define BASE_10_LENGTH 20 #define CODEWORD_LENGTH 17 static const uint8_t codeword_map[] = {3, 2, 1, 0, 7, 6, 5, 4, 13, 14, 15, 16, 12, 8, 9, 10, 11}; static const char alphabet[] = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ"; -static const uint8_t gexp[] = {1, 2, 4, 8, 16, 5, 10, 20, 13, 26, 17, 7, 14, 28, 29, 31, 27, 19, 3, 6, 12, 24, 21, 15, 30, 25, 23, 11, 22, 9, 18, 1}; -static const uint8_t glog[] = {0, 0, 1, 18, 2, 5, 19, 11, 3, 29, 6, 27, 20, 8, 12, 23, 4, 10, 30, 17, 7, 22, 28, 26, 21, 25, 9, 16, 13, 14, 24, 15}; - +static const uint8_t gexp[] = {1, 2, 4, 8, 16, 5, 10, 20, 13, 26, 17, 7, 14, 28, 29, 31, + 27, 19, 3, 6, 12, 24, 21, 15, 30, 25, 23, 11, 22, 9, 18, 1}; +static const uint8_t glog[] = {0, 0, 1, 18, 2, 5, 19, 11, 3, 29, 6, 27, 20, 8, 12, 23, + 4, 10, 30, 17, 7, 22, 28, 26, 21, 25, 9, 16, 13, 14, 24, 15}; uint8_t gmult(const uint8_t a, const uint8_t b) { - - if ((0 == a) || (0 == b)) { + if ((a == 0) || (b == 0)) { return 0; } - uint8_t idx = ((*(uint8_t*)PIC(&glog[a])) + (*(uint8_t*)PIC(&glog[b]))) % 31; - return (*(uint8_t*)PIC(&gexp[idx])); + uint8_t idx = ((*(uint8_t*) PIC(&glog[a])) + (*(uint8_t*) PIC(&glog[b]))) % 31; + return (*(uint8_t*) PIC(&gexp[idx])); } //@inp in - the buffer to encode, it's not const, cuz it's edited while converting //@output out - output should be of length 21; -void reedSolomonEncode(uint64_t inp, char * const output) { - +void reedSolomonEncode(uint64_t inp, char* const output) { uint8_t plain_string_32[CODEWORD_LENGTH]; - memset(plain_string_32, 0, CODEWORD_LENGTH); + explicit_bzero(plain_string_32, CODEWORD_LENGTH); uint8_t index = 0; - while (0 != inp) { + while (inp != 0) { uint8_t ret = inp % 32; plain_string_32[index++] = ret; inp -= ret; @@ -57,12 +56,11 @@ void reedSolomonEncode(uint64_t inp, char * const output) { uint8_t p[] = {0, 0, 0, 0}; for (int8_t i = BASE_32_LENGTH - 1; i >= 0; i--) { - uint8_t fb = plain_string_32[i] ^ p[3]; p[3] = p[2] ^ gmult(30, fb); p[2] = p[1] ^ gmult(6, fb); p[1] = p[0] ^ gmult(9, fb); - p[0] = gmult(17, fb); + p[0] = gmult(17, fb); } memcpy(plain_string_32 + BASE_32_LENGTH, p, CODEWORD_LENGTH - BASE_32_LENGTH); @@ -70,9 +68,9 @@ void reedSolomonEncode(uint64_t inp, char * const output) { uint8_t stringIndex = 0; for (uint8_t i = 0; i < 17; i++) { - uint8_t codework_index = (*(uint8_t*)PIC(&codeword_map[i])); + uint8_t codework_index = (*(uint8_t*) PIC(&codeword_map[i])); uint8_t alphabet_index = plain_string_32[codework_index]; - output[stringIndex++] = (*(uint8_t*)PIC(&alphabet[alphabet_index])); + output[stringIndex++] = (*(uint8_t*) PIC(&alphabet[alphabet_index])); if ((i & 3) == 3 && i < 13) { output[stringIndex++] = '-'; @@ -81,4 +79,3 @@ void reedSolomonEncode(uint64_t inp, char * const output) { output[stringIndex++] = 0; } - diff --git a/src/reedSolomon.h b/src/reedSolomon.h index e1b59dc..5638418 100644 --- a/src/reedSolomon.h +++ b/src/reedSolomon.h @@ -1,22 +1,25 @@ /******************************************************************************* -* (c) 2021 Jelurida IP B.V. -* -* -* 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 Haim Bender + * (c) 2021-2023 Jelurida IP B.V. + * + * + * 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 //@inp in - the buffer to encode, it's not const, cuz it's edited while converting //@output out - output should be of length 21; -void reedSolomonEncode(uint64_t inp, char * const output); +void reedSolomonEncode(uint64_t inp, char* const output); \ No newline at end of file diff --git a/src/returnValues.h b/src/returnValues.h index f2089cc..61a5ab5 100644 --- a/src/returnValues.h +++ b/src/returnValues.h @@ -1,52 +1,59 @@ /******************************************************************************* -* (c) 2019 Haim Bender -* -* -* 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 Haim Bender + * (c) 2021-2023 Jelurida IP B.V. + * + * + * 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 + +#define SW_OK 0x9000 enum returnValues { - R_SUCCESS = 0, - R_REJECT = 1, - R_BAD_CLA = 2, - R_UNKOWN_CMD = 3, - R_FUNCTION_STACK_FULL = 4, - R_NO_SPACE_BUFFER_TOO_SMALL = 5, - R_PARSE_FUNCTION_NOT_FOUND = 6, - R_NOT_ALL_BYTES_READ = 7, - R_FINISHED = 8, - R_WRONG_DERIVATION_PATH_HEADER = 10, - R_KEY_DERIVATION_EX = 11, - R_FORMAT_AMOUNT_ERR = 12, - R_FORMAT_FEE_ERR = 13, - R_SHOW_DISPLAY = 14, - R_SEND_MORE_BYTES = 15, - R_UNSUPPORTED_APPENDAGE = 16, - R_BAD_CHAIN_ID_ERR = 17, - R_WRONG_VERSION_ERR = 18, - R_WRONG_SIZE_ERR = 19, - R_ERR_NO_INIT_CANT_CONTINUE = 20, - R_NOT_ALL_BYTES_USED = 21, - R_TXN_UNAUTHORIZED = 22, - R_UNKNOWN_CMD_PARAM_ERR = 23, - R_BAD_NUM_KEYS = 24, - R_EXCEPTION = 25, - R_DATA_BUFFER_TOO_BIG = 27, - R_WRONG_SIZE_MODULO_ERR = 28, - R_UNSUPPORTED_ATTACHMENT_VERSION = 29, - R_TXN_SIZE_TOO_SMALL = 30, - R_AES_ERROR = 31, - R_NO_SETUP = 32, - R_NOT_ENOUGH_DERIVATION_INDEXES = 33, - R_WRONG_STATE = 34 + R_SUCCESS = 0, + R_REJECT = 1, + R_BAD_CLA = 2, + R_UNKOWN_CMD = 3, + R_FUNCTION_STACK_FULL = 4, + R_NO_SPACE_BUFFER_TOO_SMALL = 5, + R_PARSE_FUNCTION_NOT_FOUND = 6, + R_NOT_ALL_BYTES_READ = 7, + R_FINISHED = 8, + R_WRONG_DATA_LENGTH = 9, + R_WRONG_DERIVATION_PATH_HEADER = 10, + R_KEY_DERIVATION_EX = 11, + R_FORMAT_AMOUNT_ERR = 12, + R_FORMAT_FEE_ERR = 13, + R_SHOW_DISPLAY = 14, + R_SEND_MORE_BYTES = 15, + R_UNSUPPORTED_APPENDAGE = 16, + R_BAD_CHAIN_ID_ERR = 17, + R_WRONG_VERSION_ERR = 18, + R_WRONG_SIZE_ERR = 19, + R_ERR_NO_INIT_CANT_CONTINUE = 20, + R_NOT_ALL_BYTES_USED = 21, + R_TXN_UNAUTHORIZED = 22, + R_UNKNOWN_CMD_PARAM_ERR = 23, + R_BAD_NUM_KEYS = 24, + R_EXCEPTION = 25, + R_DATA_BUFFER_TOO_BIG = 27, + R_WRONG_SIZE_MODULO_ERR = 28, + R_UNSUPPORTED_ATTACHMENT_VERSION = 29, + R_TXN_SIZE_TOO_SMALL = 30, + R_AES_ERROR = 31, + R_NO_SETUP = 32, + R_NOT_ENOUGH_DERIVATION_INDEXES = 33, + R_WRONG_STATE = 34, + R_CXLIB_ERROR = 35 }; \ No newline at end of file diff --git a/src/settings.c b/src/settings.c new file mode 100644 index 0000000..ede96b0 --- /dev/null +++ b/src/settings.c @@ -0,0 +1,6 @@ +#include "ardor.h" +#include "stdbool.h" + +void settings_set_allow_blind_signing(bool value) { + nvm_write((void*) &N_storage.settings.allowBlindSigning, &value, sizeof(value)); +} \ No newline at end of file diff --git a/src/settings.h b/src/settings.h new file mode 100644 index 0000000..7fbb7ea --- /dev/null +++ b/src/settings.h @@ -0,0 +1,5 @@ +#pragma once + +#include "stdbool.h" + +void settings_set_allow_blind_signing(bool value); \ No newline at end of file diff --git a/src/showAddress.c b/src/showAddress.c index c58c12d..409ce29 100644 --- a/src/showAddress.c +++ b/src/showAddress.c @@ -1,131 +1,67 @@ /******************************************************************************* -* (c) 2019 Haim Bender -* -* -* 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 Haim Bender + * (c) 2021-2023 Jelurida IP B.V. + * + * + * 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 +#include #include -#include -#include "ux.h" +#include "parser.h" // command_t #include "returnValues.h" #include "config.h" #include "ardor.h" +#include "ui/menu.h" +#include "ui/display.h" +#include "io_helper.h" // io_send_return* - -//done button callback -unsigned int doneButton(const bagl_element_t *e) { - - UNUSED(e); - - G_io_apdu_buffer[0] = R_SUCCESS; - G_io_apdu_buffer[1] = 0x90; - G_io_apdu_buffer[2] = 0x00; - io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, 3); - - ui_idle(); // redraw ui - return 0; // DO NOT REDRAW THE BUTTON +void showAddressConfirm(void) { + io_send_return1(R_SUCCESS); + ui_menu_main(); } -//Defenition of the UI for this handler -char screenContent[27]; -UX_STEP_VALID(saFlowPage1, - bnnn_paging, - doneButton(NULL), - { - .title = "Your Address", - .text = screenContent, - }); -UX_STEP_VALID(saFlowPage2, - pb, - doneButton(NULL), - { - &C_icon_validate_14, - "Done" - }); -UX_FLOW(saFlow, - &saFlowPage1, - &saFlowPage2 -); - -void showScreen() { - if(0 == G_ux.stack_count) - ux_stack_push(); - - ux_flow_init(0, saFlow, NULL); +void showAddressCancel(void) { + io_send_return1(R_REJECT); + ui_menu_main(); } -//defined in reedSolomon.c -void reedSolomonEncode(const uint64_t inp, char * const output); - -void showAddressHandlerHelper(const uint8_t p1, const uint8_t p2, const uint8_t * const dataBuffer, const uint8_t dataLength, - uint8_t * const flags, uint8_t * const tx) { - - UNUSED(p1); UNUSED(p2); UNUSED(flags); - - if ((MIN_DERIVATION_LENGTH * sizeof(uint32_t) > dataLength) || (MAX_DERIVATION_LENGTH * sizeof(uint32_t) < dataLength)) { - G_io_apdu_buffer[(*tx)++] = R_WRONG_SIZE_ERR; - return; +int showAddressHandler(const command_t* const cmd) { + if (!isValidDerivationPathLength(cmd->lc)) { + return io_send_return1(R_WRONG_SIZE_ERR); } - uint8_t derivationParamLengthInBytes = dataLength; - - if (0 != derivationParamLengthInBytes % sizeof(uint32_t)) { - G_io_apdu_buffer[(*tx)++] = R_UNKNOWN_CMD_PARAM_ERR; - return; - } - - G_io_apdu_buffer[(*tx)++] = R_SUCCESS; - uint16_t exception = 0; - - uint8_t publicKey[32]; memset(publicKey, 0, sizeof(publicKey)); - - uint8_t ret = ardorKeys(dataBuffer, derivationParamLengthInBytes / sizeof(uint32_t), 0, publicKey, 0, 0, &exception); //derivationParamLengthInBytes should devied by 4, it's checked above - - if (R_SUCCESS == ret) { - memset(screenContent, 0, sizeof(screenContent)); - snprintf(screenContent, sizeof(screenContent), APP_PREFIX); - reedSolomonEncode(publicKeyToId(publicKey), screenContent + strlen(screenContent)); - showScreen(); - *flags |= IO_ASYNCH_REPLY; - } else if (R_KEY_DERIVATION_EX == ret) { - G_io_apdu_buffer[0] = ret; - G_io_apdu_buffer[1] = exception >> 8; - G_io_apdu_buffer[2] = exception & 0xFF; - *tx = 3; - return; + uint8_t publicKey[PUBLIC_KEY_SIZE]; + explicit_bzero(publicKey, sizeof(publicKey)); + + // cmd->lc (derivationParamLengthInBytes) should be multiple of 4, it's checked above + uint8_t ret = ardorKeys(cmd->data, cmd->lc / sizeof(uint32_t), 0, publicKey, 0, 0, &exception); + + if (ret == R_SUCCESS) { + uint64_t accountId; + if (publicKeyToId(publicKey, &accountId) != CX_OK) { + return io_send_return1(R_CXLIB_ERROR); + } + showAddressScreen(accountId); + return 0; + } else if (ret == R_KEY_DERIVATION_EX) { + return io_send_return3(ret, exception >> 8, exception & 0xFF); } else { - G_io_apdu_buffer[0] = ret; - *tx = 1; - return; - } -} - -void showAddressHandler(const uint8_t p1, const uint8_t p2, const uint8_t * const dataBuffer, const uint8_t dataLength, - uint8_t * const flags, uint8_t * const tx, const bool isLastCommandDifferent) { - - UNUSED(isLastCommandDifferent); - - showAddressHandlerHelper(p1, p2, dataBuffer, dataLength, flags, tx); - - if (0 == ((*flags) & IO_ASYNCH_REPLY)) { - G_io_apdu_buffer[(*tx)++] = 0x90; - G_io_apdu_buffer[(*tx)++] = 0x00; + return io_send_return2(R_SUCCESS, ret); } } diff --git a/src/signToken.c b/src/signToken.c index b9a2f72..1cbea47 100644 --- a/src/signToken.c +++ b/src/signToken.c @@ -1,41 +1,38 @@ /******************************************************************************* -* (c) 2019 Haim Bender -* -* -* 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 Haim Bender + * (c) 2021-2023 Jelurida IP B.V. + * + * + * 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 +#include -#include -#include -#include "ux.h" - -#include "aes/aes.h" +#include "io.h" // io_send* +#include "parser.h" // command_t #include "returnValues.h" #include "config.h" #include "ardor.h" +#include "ui/menu.h" +#include "ui/display.h" +#include "io_helper.h" -#define P1_INIT 0 -#define P1_MSG_BYTES 1 -#define P1_SIGN 2 - -#define STATE_INVAILD 0 -#define STATE_MODE_INITED 1 -#define STATE_BYTES_RECIEVED 2 +#define P1_INIT 0 +#define P1_MSG_BYTES 1 +#define P1_SIGN 2 /* modes: @@ -48,204 +45,164 @@ returns: 1 byte status P1_SIGN: - dataBuffer: timestamp (4 bytes) | derivaiton path (uint32) * some length | + dataBuffer: timestamp (4 bytes) | derivation path (uint32) * some length | returns: 1 byte status | token 100 bytes 100-byte token consists of a 32-byte public key, a 4-byte timestamp, and a 64-byte signature */ -//does what it says :) -void cleanTokenCreationState() { - state.tokenCreation.mode = STATE_INVAILD; +static int cleanAndReturn(uint8_t ret) { + cleanState(); + return io_send_return1(ret); } -// UI callbacks -unsigned int txn_authorized(const bagl_element_t *e) { - UNUSED(e); - - uint8_t *dataBuffer = G_io_apdu_buffer + OFFSET_CDATA; - uint8_t dataLength = G_io_apdu_buffer[OFFSET_LC]; - uint8_t derivationPathLengthInUints32 = (dataLength - 4) / sizeof(uint32_t); - uint8_t tx = 0; +// UI callback defined in ui/display.h +void signTokenConfirm() { uint16_t exception = 0; - uint32_t timestamp = 0; - uint8_t keySeed[32]; memset(keySeed, 0, sizeof(keySeed)); - - //gotta do some space reuse - uint8_t publicKeyAndFinalHash[32]; memset(publicKeyAndFinalHash, 0, sizeof(publicKeyAndFinalHash)); - uint8_t ret = ardorKeys(dataBuffer + sizeof(timestamp), derivationPathLengthInUints32, keySeed, publicKeyAndFinalHash, 0, 0, &exception); - - if (R_SUCCESS != ret) { - cleanTokenCreationState(); - - G_io_apdu_buffer[tx++] = ret; - - if (R_KEY_DERIVATION_EX == ret) { - G_io_apdu_buffer[tx++] = exception >> 8; - G_io_apdu_buffer[tx++] = exception & 0xFF; - } - } else { - memcpy(×tamp, dataBuffer, sizeof(timestamp)); - - G_io_apdu_buffer[tx++] = R_SUCCESS; - - cx_hash(&state.tokenCreation.sha256.header, 0, publicKeyAndFinalHash, sizeof(publicKeyAndFinalHash), 0, 0); //adding the public key to the hash - - //also make a copy to the output buffer, because of how a token is constructed - memcpy(G_io_apdu_buffer + tx, publicKeyAndFinalHash, sizeof(publicKeyAndFinalHash)); - tx += sizeof(publicKeyAndFinalHash); - - cx_hash(&state.tokenCreation.sha256.header, 0, (uint8_t*)×tamp, sizeof(timestamp), 0, 0); //adding the timestamp to the hash - - memcpy(G_io_apdu_buffer + tx, ×tamp, sizeof(timestamp)); - tx += sizeof(timestamp); - - cx_hash(&state.tokenCreation.sha256.header, CX_LAST, 0, 0, publicKeyAndFinalHash, sizeof(publicKeyAndFinalHash)); + uint8_t keySeed[32]; + explicit_bzero(keySeed, sizeof(keySeed)); + + // gotta do some space reuse + uint8_t publicKeyAndFinalHash[32]; + explicit_bzero(publicKeyAndFinalHash, sizeof(publicKeyAndFinalHash)); + uint8_t ret = ardorKeys(state.tokenSign.ptrDerivationPath, + state.tokenSign.derivationPathLengthInUints32, + keySeed, + publicKeyAndFinalHash, + 0, + 0, + &exception); + + if (ret != R_SUCCESS) { + cleanState(); + io_send_return3(ret, exception >> 8, exception & 0xFF); + return; + } - signMsg(keySeed, publicKeyAndFinalHash, G_io_apdu_buffer + tx); //is a void function, no ret value to check against - memset(keySeed, 0, sizeof(keySeed)); + state.tokenSign.token[0] = R_SUCCESS; + size_t offset = 1; + + cx_err_t err; + // adding the public key to the hash + err = cx_hash_no_throw(&state.tokenSign.sha256.header, + 0, + publicKeyAndFinalHash, + sizeof(publicKeyAndFinalHash), + 0, + 0); + if (err != CX_OK) { + cleanAndReturn(R_CXLIB_ERROR); + return; + } - tx += 64; + // also make a copy to the output buffer, because of how a token is constructed + memcpy(state.tokenSign.token + offset, publicKeyAndFinalHash, sizeof(publicKeyAndFinalHash)); + offset += sizeof(publicKeyAndFinalHash); + + // adding the timestamp to the hash + err = cx_hash_no_throw(&state.tokenSign.sha256.header, + 0, + (uint8_t*) &state.tokenSign.timestamp, + sizeof(state.tokenSign.timestamp), + 0, + 0); + if (err != CX_OK) { + cleanAndReturn(R_CXLIB_ERROR); + return; + } - G_io_apdu_buffer[tx++] = 0x90; - G_io_apdu_buffer[tx++] = 0x00; + memcpy(state.tokenSign.token + offset, + &state.tokenSign.timestamp, + sizeof(state.tokenSign.timestamp)); + offset += sizeof(state.tokenSign.timestamp); + + err = cx_hash_no_throw(&state.tokenSign.sha256.header, + CX_LAST, + 0, + 0, + publicKeyAndFinalHash, + sizeof(publicKeyAndFinalHash)); + if (err != CX_OK) { + cleanAndReturn(R_CXLIB_ERROR); + return; } - cleanTokenCreationState(); + err = signMsg(keySeed, publicKeyAndFinalHash, state.tokenSign.token + offset); + if (err != CX_OK) { + cleanAndReturn(R_CXLIB_ERROR); + return; + } + explicit_bzero(keySeed, sizeof(keySeed)); - io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, tx); - - ui_idle(); // redraw ui - return 0; // DO NOT REDRAW THE BUTTON + io_send_response_pointer(state.tokenSign.token, sizeof(state.tokenSign.token), SW_OK); + cleanState(); } -unsigned int txn_cancelled(const bagl_element_t *e) { - UNUSED(e); - - cleanTokenCreationState(); - - G_io_apdu_buffer[0] = R_SUCCESS; - G_io_apdu_buffer[1] = R_REJECT; - G_io_apdu_buffer[2] = 0x90; - G_io_apdu_buffer[3] = 0x00; - io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, 4); - - ui_idle(); // redraw ui - return 0; // DO NOT REDRAW THE BUTTON +// UI callback defined in ui/display.h +void signTokenCancel() { + cleanState(); + io_send_return2(R_SUCCESS, R_REJECT); } -// UI definitions -UX_STEP_CB(stFlowPage1, - pb, - txn_authorized(NULL), - { - &C_icon_validate_14, - "Sign token", - }); - -UX_STEP_CB(stFlowPage2, - pb, - txn_cancelled(NULL), - { - &C_icon_crossmark, - "Reject", - }); -UX_FLOW(stFlow, - &stFlowPage1, - &stFlowPage2); - -void showSignTokenScreen() { - if(0 == G_ux.stack_count) - ux_stack_push(); - - ux_flow_init(0, stFlow, NULL); +static int p1TokenInitHandler() { + cleanState(); + state.tokenSign.state = SIGN_TOKEN_INIT; + cx_sha256_init(&state.tokenSign.sha256); + return io_send_return1(R_SUCCESS); } -//Since this is a callback function, and this handler manages state, it's this function's reposibility to clear the state -//Every time we get some sort of an error -void signTokenMessageHandlerHelper(const uint8_t p1, const uint8_t p2, const uint8_t * const dataBuffer, const uint8_t dataLength, - uint8_t * const flags, uint8_t * const tx, const bool isLastCommandDifferent) { - - UNUSED(p2); - UNUSED(flags); - - if (isLastCommandDifferent) - cleanTokenCreationState(); - - switch(p1) { - - case P1_INIT: - cleanTokenCreationState(); - state.tokenCreation.mode = STATE_MODE_INITED; - cx_sha256_init(&state.tokenCreation.sha256); - G_io_apdu_buffer[(*tx)++] = R_SUCCESS; - break; - - case P1_MSG_BYTES: - - if (isLastCommandDifferent || (STATE_INVAILD == state.tokenCreation.mode)) { - cleanTokenCreationState(); - G_io_apdu_buffer[(*tx)++] = R_WRONG_STATE; - break; - } - - state.tokenCreation.mode = STATE_BYTES_RECIEVED; - - cx_hash(&state.tokenCreation.sha256.header, 0, dataBuffer, dataLength, 0, 0); - - G_io_apdu_buffer[(*tx)++] = R_SUCCESS; - break; - - case P1_SIGN: +static int p1TokenMsgBytesHandler(const command_t* const cmd) { + if (state.tokenSign.state == SIGN_TOKEN_UNINIT) { + return cleanAndReturn(R_WRONG_STATE); + } - if (isLastCommandDifferent || (STATE_BYTES_RECIEVED != state.tokenCreation.mode)) { - cleanTokenCreationState(); - G_io_apdu_buffer[(*tx)++] = R_WRONG_STATE; - break; - } + state.tokenSign.state = SIGN_TOKEN_BYTES_RECEIVED; - if (dataLength < 4) { - cleanTokenCreationState(); - G_io_apdu_buffer[(*tx)++] = R_WRONG_SIZE_ERR; - break; - } + if (cx_hash_no_throw(&state.tokenSign.sha256.header, 0, cmd->data, cmd->lc, 0, 0) != CX_OK) { + return cleanAndReturn(R_CXLIB_ERROR); + } - if (0 != (dataLength - 4) % sizeof(uint32_t)) { - cleanTokenCreationState(); - G_io_apdu_buffer[(*tx)++] = R_WRONG_SIZE_MODULO_ERR; - break; - } + return io_send_return1(R_SUCCESS); +} - //underflow was checked against above above - uint8_t derivationPathLengthInUints32 = (dataLength - 4) / sizeof(uint32_t); +static int p1TokenSignHandler(const command_t* const cmd) { + if (state.tokenSign.state != SIGN_TOKEN_BYTES_RECEIVED) { + return cleanAndReturn(R_WRONG_STATE); + } - if ((MIN_DERIVATION_LENGTH > derivationPathLengthInUints32) || (MAX_DERIVATION_LENGTH < derivationPathLengthInUints32)) { - cleanTokenCreationState(); - G_io_apdu_buffer[(*tx)++] = R_WRONG_SIZE_ERR; - break; - } + if (cmd->lc < 4) { + return cleanAndReturn(R_WRONG_SIZE_ERR); + } - showSignTokenScreen(); - *flags |= IO_ASYNCH_REPLY; + if ((cmd->lc - 4) % sizeof(uint32_t) != 0) { + return cleanAndReturn(R_WRONG_SIZE_MODULO_ERR); + } - break; - - default: + // underflow was checked against above above + state.tokenSign.derivationPathLengthInUints32 = (cmd->lc - 4) / sizeof(uint32_t); - cleanTokenCreationState(); - G_io_apdu_buffer[(*tx)++] = R_UNKNOWN_CMD_PARAM_ERR; - break; + if ((state.tokenSign.derivationPathLengthInUints32 < MIN_DERIVATION_LENGTH) || + (state.tokenSign.derivationPathLengthInUints32 > MAX_DERIVATION_LENGTH)) { + return cleanAndReturn(R_WRONG_SIZE_ERR); } -} + memcpy(&state.tokenSign.timestamp, cmd->data, sizeof(state.tokenSign.timestamp)); + state.tokenSign.ptrDerivationPath = cmd->data + sizeof(state.tokenSign.timestamp); -void signTokenMessageHandler(const uint8_t p1, const uint8_t p2, const uint8_t * const dataBuffer, const uint8_t dataLength, - uint8_t * const flags, uint8_t * const tx, const bool isLastCommandDifferent) { + signTokenScreen(); + return 0; +} - signTokenMessageHandlerHelper(p1, p2, dataBuffer, dataLength, flags, tx, isLastCommandDifferent); - - if (0 == ((*flags) & IO_ASYNCH_REPLY)) { - G_io_apdu_buffer[(*tx)++] = 0x90; - G_io_apdu_buffer[(*tx)++] = 0x00; +// Since this is a callback function, and this handler manages state, it's this function's +// reposibility to clear the state Every time we get some sort of an error +int signTokenMessageHandler(const command_t* const cmd) { + if (cmd->p1 == P1_INIT) { + return p1TokenInitHandler(); + } else if (cmd->p1 == P1_MSG_BYTES) { + return p1TokenMsgBytesHandler(cmd); + } else if (cmd->p1 == P1_SIGN) { + return p1TokenSignHandler(cmd); + } else { + return cleanAndReturn(R_UNKNOWN_CMD_PARAM_ERR); } } diff --git a/src/transactionParser.c b/src/transactionParser.c new file mode 100644 index 0000000..163b863 --- /dev/null +++ b/src/transactionParser.c @@ -0,0 +1,481 @@ +/******************************************************************************* + * (c) 2019 Haim Bender + * (c) 2021-2023 Jelurida IP B.V. + * + * + * 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 "ardor.h" +#include "returnValues.h" +#include "transactionParser.h" + +#define TX_TIMESTAMP_DEADLINE 2 + +// returns the txn type at the given index +static txnType* txnTypeAtIndex(const uint8_t index) { + return (txnType*) PIC(&TXN_TYPES[index]); +} + +// returns the txn type name at the given index +static char* txnTypeNameAtIndex(const uint8_t index) { + return (char*) PIC(((txnType*) PIC(&TXN_TYPES[index]))->name); +} + +/** + * Returns the index of the transaction type in the array of transaction types. + * + * @param txnTypeAndSubType The transaction type and subtype combined into a single uint16_t value. + * @return The index of the transaction type in the array of transaction types. + */ +static uint8_t getTransactionTypeIndex(uint16_t txnTypeAndSubType) { + uint8_t index = 0; + while (index < LEN_TXN_TYPES) { + if (txnTypeAtIndex(index)->id == txnTypeAndSubType) { + break; + } + index++; + } + return index; +} + +/** + * Checks if the given transaction type is a payment transaction type. + * + * @param txTypeAndSub The transaction type and subtype to check. + * @return true if the transaction type is a payment transaction type, false otherwise. + */ +static bool isPaymentTxType(uint16_t txTypeAndSub) { + return txTypeAndSub == TX_TYPE_ORDINARY_PAYMENT || txTypeAndSub == TX_TYPE_FXT_PAYMENT; +} + +static char* appendageTypeName(const uint8_t index) { + return (char*) PIC(((appendageType*) PIC(&APPENDAGE_TYPES[index]))->name); +} + +// note: ardor chain index starts with index 1 +static bool isValidChainId(uint32_t chainId) { + return chainId > 0 && chainId <= NUM_CHAINS; +} + +// adds a parsing function to the top of the stack +static uint8_t addToFunctionStack(const uint8_t functionNum) { + if (state.txnAuth.numFunctionsOnStack == sizeof(state.txnAuth.functionStack)) { + return R_FUNCTION_STACK_FULL; + } + + state.txnAuth.functionStack[state.txnAuth.numFunctionsOnStack++] = functionNum; + + return R_SUCCESS; +} + +// Takes bytes away from the buffer, returns 0 if there aren't enough bytes +static uint8_t* readFromBuffer(const uint8_t size) { + if (size > state.txnAuth.readBufferEndPos - state.txnAuth.readBufferReadOffset) { + return 0; + } + + uint8_t* ret = state.txnAuth.readBuffer + state.txnAuth.readBufferReadOffset; + state.txnAuth.readBufferReadOffset += size; + state.txnAuth.numBytesRead += size; + + return ret; +} + +/** + * @brief Prints the transaction type text. + * + * This function prints the transaction type text consisting on the the chain name and the + * transaction type name. + * In case of unknown transactions it prints "UnknownTxnType" and signals blind signing. + * + * @return void + */ +static void printTxnTypeText() { + if (state.txnAuth.txnTypeIndex < LEN_TXN_TYPES) { + snprintf(state.txnAuth.chainAndTxnTypeText, + sizeof(state.txnAuth.chainAndTxnTypeText), + "%s\n%s", + chainName(state.txnAuth.chainId), + txnTypeNameAtIndex(state.txnAuth.txnTypeIndex)); + } else { + snprintf(state.txnAuth.chainAndTxnTypeText, + sizeof(state.txnAuth.chainAndTxnTypeText), + "%s\nUnknownTxnType", + chainName(state.txnAuth.chainId)); + state.txnAuth.requiresBlindSigning = true; + } +} + +/** + * Formats and prints the fee amount and chain name (which acts as token name) to the state. + * + * @param fee The fee amount to be formatted and printed. + * @return Returns true if the fee text was successfully printed, false otherwise. + */ +static bool printFeeText(uint64_t fee) { + uint8_t ret = formatAmount(state.txnAuth.feeText, + sizeof(state.txnAuth.feeText), + fee, + chainNumDecimalsBeforePoint(state.txnAuth.chainId)); + + if (ret == 0) { + return false; + } + + snprintf(state.txnAuth.feeText + ret - 1, + sizeof(state.txnAuth.feeText) - ret - 1, + " %s", + chainName(state.txnAuth.chainId)); + + return true; +} + +// PARSE_FN_MAIN 1 +// This is the main parse function, it parses the main tx body and adds more functions to the parse +// stack if needed +static uint8_t parseMainTxnData() { + uint8_t* ptr = readFromBuffer(BASE_TRANSACTION_SIZE); + + if (ptr == 0) { + return R_SEND_MORE_BYTES; + } + + memmove(&(state.txnAuth.chainId), ptr, sizeof(state.txnAuth.chainId)); + + ptr += sizeof(state.txnAuth.chainId); + + if (!isValidChainId(state.txnAuth.chainId)) { + return R_BAD_CHAIN_ID_ERR; + } + + memmove(&(state.txnAuth.txnTypeAndSubType), ptr, sizeof(state.txnAuth.txnTypeAndSubType)); + + ptr += sizeof(state.txnAuth.txnTypeAndSubType); + + state.txnAuth.txnTypeIndex = getTransactionTypeIndex(state.txnAuth.txnTypeAndSubType); + txnType* txType = + state.txnAuth.txnTypeIndex < LEN_TXN_TYPES ? txnTypeAtIndex(state.txnAuth.txnTypeIndex) : 0; + + if (state.txnAuth.txnTypeIndex < LEN_TXN_TYPES && + txType->attachmentParsingFunctionNumber != 0) { + addToFunctionStack(txType->attachmentParsingFunctionNumber); + } + + // general blind signing check, functions without specific parsing are marked as blind signing + // except payments which don't require special parsing + if (state.txnAuth.txnTypeIndex >= LEN_TXN_TYPES || + (txType->attachmentParsingFunctionNumber == 0 && + !isPaymentTxType(state.txnAuth.txnTypeAndSubType))) { + state.txnAuth.requiresBlindSigning = true; + } + + printTxnTypeText(); + + if (*((uint8_t*) ptr) != SUPPORTED_TXN_VERSION) { + return R_WRONG_VERSION_ERR; + } + ptr += sizeof(uint8_t); // version + + ptr += TIMESTAMP_SIZE; // Skip the timestamp + ptr += TX_TIMESTAMP_DEADLINE; // Skip the deadline + ptr += PUBLIC_KEY_SIZE; // Skip the sender publickey + + memmove(&(state.txnAuth.recipientId), ptr, sizeof(state.txnAuth.recipientId)); + ptr += sizeof(state.txnAuth.recipientId); + + memmove(&(state.txnAuth.amount), ptr, sizeof(state.txnAuth.amount)); + ptr += sizeof(state.txnAuth.amount); + + uint64_t fee = 0; + memmove(&fee, ptr, sizeof(fee)); + if (!printFeeText(fee)) { + return R_FORMAT_FEE_ERR; + } + + addToFunctionStack(PARSE_FN_IGNORE_BYTES_UNTIL_THE_END); + + return R_SUCCESS; +} + +// PARSE_FN_APPENDAGES_FLAGS 2 +/** + * Parses the appendage type flag and prepares the text to show the user. + * This function is added to the function stack on init. + * + * Current known appendages types: + * MessageAppendix = 1 + * EncryptedMessageAppendix = 2 + * EncryptToSelfMessageAppendix = 4 + * PrunablePlainMessageAppendix = 8 + * PrunableEncryptedMessageAppendix = 16 + * PublicKeyAnnouncementAppendix = 32 + * PhasingAppendix = 64 + */ +static uint8_t parseAppendagesFlags() { + uint8_t* buffPtr = readFromBuffer(sizeof(uint32_t)); + + if (buffPtr == 0) { + return R_SEND_MORE_BYTES; + } + + uint32_t appendages = 0; + + memmove(&appendages, buffPtr, sizeof(appendages)); + + if (appendages != 0) { + state.txnAuth.requiresBlindSigning = true; + + // fallback to hex string if we found unknown appendages + if (appendages >= 1 << NUM_APPENDAGE_TYPES) { + snprintf(state.txnAuth.appendagesText, + sizeof(state.txnAuth.appendagesText), + "0x%08X", + appendages); + } else { + char* ptr = state.txnAuth.appendagesText; + size_t free = sizeof(state.txnAuth.appendagesText); + for (uint8_t j = 0; j < NUM_APPENDAGE_TYPES; j++) { + if ((appendages & 1 << j) != 0) { + size_t len = strlen(appendageTypeName(j)); + + // special case: not enough space to show the text for all appendages, revert to + // bitmap + if (len + 2 > free) { // +2 for separator and null terminator + int limit = MIN(NUM_APPENDAGE_TYPES, free - 1); // security audit + for (uint8_t i = 0; i < limit; i++) { + state.txnAuth.appendagesText[i] = + (appendages & 1 << i) != 0 ? '1' + i : '_'; + } + state.txnAuth.appendagesText[limit] = '\0'; + return R_SUCCESS; + } + + snprintf(ptr, + free, + ptr == state.txnAuth.appendagesText ? "%s" : "\n%s", + appendageTypeName(j)); + ptr += ptr == state.txnAuth.appendagesText ? len : len + 1; + free -= ptr == state.txnAuth.appendagesText ? len : len + 1; + } + } + } + } + + return R_SUCCESS; +} + +// PARSE_FN_FXT_COIN_EXCHANGE_ORDER_ISSUE_OR_COIN_EXCHANGE_ORDER_ISSUE_ATTACHMENT 4 +// Parses a specific type of attachment +static uint8_t parseFxtCoinExchangeOrderIssueOrCoinExchangeOrderIssueAttachment() { + uint32_t chainId = 0; // chainId + uint32_t exchangeChainId = 0; // exchangeChain + uint64_t quantityQNT = 0; // quantity + uint64_t priceNQT = 0; // price + + uint8_t* ptr = readFromBuffer(sizeof(uint8_t) + sizeof(state.txnAuth.attachment.coinExchange)); + if (ptr == 0) { + return R_SEND_MORE_BYTES; + } + + if (*ptr != 1) { + return R_UNSUPPORTED_ATTACHMENT_VERSION; + } + + ptr += 1; // skip version byte + + memmove(&chainId, ptr, sizeof(chainId)); + ptr += sizeof(chainId); + + if (!isValidChainId(chainId)) { + return R_BAD_CHAIN_ID_ERR; + } + + memmove(&exchangeChainId, ptr, sizeof(exchangeChainId)); + ptr += sizeof(exchangeChainId); + + if (!isValidChainId(exchangeChainId)) { + return R_BAD_CHAIN_ID_ERR; + } + + memmove(&quantityQNT, ptr, sizeof(quantityQNT)); + ptr += sizeof(quantityQNT); + + memmove(&priceNQT, ptr, sizeof(priceNQT)); + + state.txnAuth.attachment.coinExchange.chainId = chainId; + state.txnAuth.attachment.coinExchange.exchangeChainId = exchangeChainId; + state.txnAuth.attachment.coinExchange.quantityQNT = quantityQNT; + state.txnAuth.attachment.coinExchange.priceNQT = priceNQT; + return R_SUCCESS; +} + +// PARSE_FN_ASSET_ORDER_PLACEMENT_ATTACHMENT 5 +// Parses a specific type of attachment +static uint8_t parseAssetOrderPlacementAttachment() { + uint64_t assetId = 0; // assetId + uint64_t quantityQNT = 0; // quantityQNT + uint64_t priceNQT = 0; // priceNQT + + uint8_t* ptr = + readFromBuffer(sizeof(uint8_t) + sizeof(state.txnAuth.attachment.assetOrderPlacement)); + if (ptr == 0) { + return R_SEND_MORE_BYTES; + } + + ptr += 1; // skip version byte + + memmove(&assetId, ptr, sizeof(assetId)); + ptr += sizeof(assetId); + + memmove(&quantityQNT, ptr, sizeof(quantityQNT)); + ptr += sizeof(quantityQNT); + + memmove(&priceNQT, ptr, sizeof(priceNQT)); + + state.txnAuth.attachment.assetOrderPlacement.assetId = assetId; + state.txnAuth.attachment.assetOrderPlacement.quantityQNT = quantityQNT; + state.txnAuth.attachment.assetOrderPlacement.priceNQT = priceNQT; + return R_SUCCESS; +} + +// PARSE_FN_IGNORE_BYTES_UNTIL_THE_END 6 +// Parses all the bytes until the endof the txn, since we don't parse the specifics of all the +// types, sometimes this is needed +static uint8_t parseIgnoreBytesUntilTheEnd() { + while (state.txnAuth.numBytesRead != state.txnAuth.txnSizeBytes) { + uint8_t* ptr = readFromBuffer(1); + if (ptr == 0) { + return R_SEND_MORE_BYTES; + } + if (*ptr != 0) { + state.txnAuth.requiresBlindSigning = true; + } + } + + return R_SUCCESS; +} + +// PARSE_FN_ASSET_TRANSFER_ATTACHMENT 7 +static uint8_t parseAssetTransferAttachment() { + uint64_t assetId; // asset id + uint64_t quantityQNT; // quantity + + uint8_t* ptr = readFromBuffer(sizeof(uint8_t) + sizeof(state.txnAuth.attachment.assetTransfer)); + if (ptr == 0) { + return R_SEND_MORE_BYTES; + } + + if (*ptr != 1) { + return R_UNSUPPORTED_ATTACHMENT_VERSION; + } + + ptr += 1; // skip version byte + + memmove(&assetId, ptr, sizeof(assetId)); + ptr += sizeof(assetId); + + memmove(&quantityQNT, ptr, sizeof(quantityQNT)); + + state.txnAuth.attachment.assetTransfer.assetId = assetId; + state.txnAuth.attachment.assetTransfer.quantityQNT = quantityQNT; + return R_SUCCESS; +} + +// Addes bytes to the read buffer +//@param newData: ptr to the data +//@param numBytes: number of bytes in the data +// return the return value from returnValues.h (R_SUCCESS on success) +uint8_t addToReadBuffer(const uint8_t* const newData, const uint8_t numBytes) { + uint16_t offset = state.txnAuth.readBufferReadOffset; + for (uint16_t i = 0; i < state.txnAuth.readBufferEndPos - offset; i++) { + state.txnAuth.readBuffer[i] = state.txnAuth.readBuffer[i + offset]; + } + + explicit_bzero(state.txnAuth.readBuffer + state.txnAuth.readBufferEndPos - offset, offset); + + state.txnAuth.readBufferEndPos -= offset; + state.txnAuth.readBufferReadOffset = 0; + + if (state.txnAuth.readBufferEndPos + numBytes > sizeof(state.txnAuth.readBuffer)) { + return R_NO_SPACE_BUFFER_TOO_SMALL; + } + + cx_err_t ret = cx_hash_no_throw(&state.txnAuth.hashstate.header, 0, newData, numBytes, 0, 0); + if (ret != CX_OK) { + return R_CXLIB_ERROR; + } + + memcpy(state.txnAuth.readBuffer + state.txnAuth.readBufferEndPos, newData, numBytes); + state.txnAuth.readBufferEndPos += numBytes; + + return R_SUCCESS; +} + +// Since we can't store function pointers in the functionstack, we store number and then call the +// following function to make a call to the corresponding function +static uint8_t callFunctionNumber(const uint8_t functionNum) { + switch (functionNum) { + case PARSE_FN_MAIN: + return parseMainTxnData(); + case PARSE_FN_APPENDAGES_FLAGS: + return parseAppendagesFlags(); + case PARSE_FN_FXT_COIN_EXCHANGE_ORDER_ISSUE_OR_COIN_EXCHANGE_ORDER_ISSUE_ATTACHMENT: + return parseFxtCoinExchangeOrderIssueOrCoinExchangeOrderIssueAttachment(); + case PARSE_FN_ASSET_ORDER_PLACEMENT_ATTACHMENT: + return parseAssetOrderPlacementAttachment(); + case PARSE_FN_IGNORE_BYTES_UNTIL_THE_END: + return parseIgnoreBytesUntilTheEnd(); + case PARSE_FN_ASSET_TRANSFER_ATTACHMENT: + return parseAssetTransferAttachment(); + } + + return R_PARSE_FUNCTION_NOT_FOUND; +} + +// This function manages the parsing of the readBuffer with functionStack functions +// If there aren't enough bytes in the read buffer it returns R_SEND_MORE_BYTES +// which will be sent back to the user +uint8_t parseTransaction(uint8_t (*setScreenTexts)()) { + uint8_t ret = R_SUCCESS; + while (ret == R_SUCCESS) { + if (state.txnAuth.numFunctionsOnStack == 0) { + if (state.txnAuth.readBufferEndPos != state.txnAuth.readBufferReadOffset) { + return R_NOT_ALL_BYTES_READ; + } + + ret = (*setScreenTexts)(); + + if (ret != R_SUCCESS) { + return ret; + } + + return R_SHOW_DISPLAY; + } + + ret = callFunctionNumber(state.txnAuth.functionStack[0]); + + if (ret == R_SEND_MORE_BYTES) { + return ret; + } + + uint8_t tempBuffer[FUNCTION_STACK_SIZE - 1]; + memmove(tempBuffer, state.txnAuth.functionStack + 1, sizeof(tempBuffer)); + memmove(state.txnAuth.functionStack, tempBuffer, sizeof(tempBuffer)); + state.txnAuth.functionStack[sizeof(state.txnAuth.functionStack) - 1] = 0; + state.txnAuth.numFunctionsOnStack--; + } + return ret; +} diff --git a/src/transactionParser.h b/src/transactionParser.h new file mode 100644 index 0000000..1742211 --- /dev/null +++ b/src/transactionParser.h @@ -0,0 +1,38 @@ +/******************************************************************************* + * (c) 2019 Haim Bender + * (c) 2021-2023 Jelurida IP B.V. + * + * + * 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 "ardor.h" + +#define PARSE_FN_MAIN 1 +#define PARSE_FN_APPENDAGES_FLAGS 2 +#define PARSE_FN_FXT_COIN_EXCHANGE_ORDER_ISSUE_OR_COIN_EXCHANGE_ORDER_ISSUE_ATTACHMENT 4 +#define PARSE_FN_ASSET_ORDER_PLACEMENT_ATTACHMENT 5 +#define PARSE_FN_IGNORE_BYTES_UNTIL_THE_END 6 +#define PARSE_FN_ASSET_TRANSFER_ATTACHMENT 7 + +// Added bytes to the read buffer +//@param newData: ptr to the data +//@param numBytes: number of bytes in the data +// return R_SUCCESS on success, R_NO_SPACE_BUFFER_TOO_SMALL othereize +uint8_t addToReadBuffer(const uint8_t* const newData, const uint8_t numBytes); + +// Parses the tx from the read buffer using the parse functions from state.txnAuth.functionStack +// If there aren't enough bytes in the read buffer it returns R_SEND_MORE_BYTES +uint8_t parseTransaction(uint8_t (*setScreenTexts)()); \ No newline at end of file diff --git a/src/txnTypeLists.c b/src/txnTypeLists.c new file mode 100644 index 0000000..67f233b --- /dev/null +++ b/src/txnTypeLists.c @@ -0,0 +1,67 @@ +// This is an auto generated file by createTxnTypes.py + +#include +#include "ardor.h" + +const txnType TXN_TYPES[] = {{0x00fc, "Issue Exchange Order", 4}, + {0x01fc, "Cancel Exchange Order", 0}, + {0x00fd, "Lease Forging Balance", 0}, + {0x00fe, "Make Payment", 0}, + {0x00ff, "Child Chain Block", 0}, + {0x0000, "Make Payment", 0}, + {0x0001, "Send Message", 0}, + {0x0002, "Issue Asset", 0}, + {0x0102, "Transfer Asset", 7}, + {0x0202, "Place Ask Order", 5}, + {0x0302, "Place Bid Order", 5}, + {0x0402, "Cancel Ask Order", 0}, + {0x0502, "Cancel Bid Order", 0}, + {0x0602, "Pay Dividends", 0}, + {0x0702, "Delete Asset Shares", 0}, + {0x0802, "Increase Asset Shares", 0}, + {0x0902, "Set Asset Control", 0}, + {0x0a02, "Set Asset Property", 0}, + {0x0b02, "Delete Asset Property", 0}, + {0x0003, "Marketplace Listing", 0}, + {0x0103, "Marketplace Delisting", 0}, + {0x0203, "Marketplace Price Change", 0}, + {0x0303, "Marketplace Quantity Change", 0}, + {0x0403, "Marketplace Purchase", 0}, + {0x0503, "Marketplace Delivery", 0}, + {0x0603, "Marketplace Feedback", 0}, + {0x0703, "Marketplace Refund", 0}, + {0x0004, "Set Phasing Only", 0}, + {0x0005, "Issue Currency", 0}, + {0x0105, "Increase Currency Reserve", 0}, + {0x0205, "Claim Currency Reserve", 0}, + {0x0305, "Transfer Currency", 0}, + {0x0405, "Publish Currency Exchange Offer", 0}, + {0x0505, "Buy Currency", 0}, + {0x0605, "Sell Currency", 0}, + {0x0705, "Mint Currency", 0}, + {0x0805, "Delete Currency", 0}, + {0x0006, "Data Cloud Upload", 0}, + {0x0007, "Create Shuffling", 0}, + {0x0107, "Shuffling Registration", 0}, + {0x0207, "Shuffling Processing", 0}, + {0x0307, "Shuffling Recipients", 0}, + {0x0407, "Shuffling Verification", 0}, + {0x0507, "Cancel Shuffling", 0}, + {0x0008, "Set Alias", 0}, + {0x0108, "Sell Alias", 0}, + {0x0208, "Buy Alias", 0}, + {0x0308, "Delete Alias", 0}, + {0x0009, "Create Poll", 0}, + {0x0109, "Cast Vote", 0}, + {0x0209, "Cast Phasing Vote", 0}, + {0x000a, "Set Account Info", 0}, + {0x010a, "Set Account Property", 0}, + {0x020a, "Delete Account Property", 0}, + {0x000b, "Issue Exchange Order", 4}, + {0x010b, "Cancel Exchange Order", 0}, + {0x000c, "Set Contract Reference", 0}, + {0x010c, "Delete Contract Reference", 0}, + {0x000d, "Add Chain Permission", 0}, + {0x010d, "Remove Chain Permission", 0}}; + +const uint8_t LEN_TXN_TYPES = 60; diff --git a/src/ui/blind_sign_bagl.c b/src/ui/blind_sign_bagl.c new file mode 100644 index 0000000..e6a3662 --- /dev/null +++ b/src/ui/blind_sign_bagl.c @@ -0,0 +1,35 @@ +#ifdef HAVE_BAGL + +#include "blind_sign_bagl.h" +#include "ux.h" + +callback_void_t bsNotEnabledCallback; + +static void blindSigningNotEnabledCallback() { + bsNotEnabledCallback(); +} + +#ifdef TARGET_NANOS + +UX_STEP_CB(ux_step_blind_signing_not_enabled, + bnnn_paging, + blindSigningNotEnabledCallback(), + {"ERROR", "Blind signing must be enabled on Settings"}); +UX_FLOW(ux_flow_blind_signing_not_enabled, &ux_step_blind_signing_not_enabled); + +#else + +UX_STEP_CB(ux_step_blind_signing_not_enabled, + pnn, + blindSigningNotEnabledCallback(), + {&C_icon_crossmark, "Blind signing must be", "enabled on Settings"}); +UX_FLOW(ux_flow_blind_signing_not_enabled, &ux_step_blind_signing_not_enabled); + +#endif + +void blindSigningNotEnabledScreen(callback_void_t callback) { + bsNotEnabledCallback = callback; + ux_flow_init(0, ux_flow_blind_signing_not_enabled, NULL); +} + +#endif \ No newline at end of file diff --git a/src/ui/blind_sign_bagl.h b/src/ui/blind_sign_bagl.h new file mode 100644 index 0000000..e5ec11a --- /dev/null +++ b/src/ui/blind_sign_bagl.h @@ -0,0 +1,9 @@ +#pragma once + +#ifdef HAVE_BAGL + +typedef void (*callback_void_t)(void); + +void blindSigningNotEnabledScreen(callback_void_t callback); + +#endif \ No newline at end of file diff --git a/src/ui/blind_sign_nbgl.c b/src/ui/blind_sign_nbgl.c new file mode 100644 index 0000000..fa8146d --- /dev/null +++ b/src/ui/blind_sign_nbgl.c @@ -0,0 +1,72 @@ +#ifdef HAVE_NBGL + +#include "ardor.h" +#include "glyph_symbols.h" +#include "settings.h" + +#include "nbgl_use_case.h" + +struct use_case_review_ctx_s { + const nbgl_icon_details_t *icon; + const char *review_title; + const char *review_sub_title; + const char *reject_text; + nbgl_callback_t continue_callback; + nbgl_callback_t reject_callback; +}; + +static struct use_case_review_ctx_s blind_sign_ctx; + +static void blind_sign_continue() { + nbgl_useCaseReviewStart(blind_sign_ctx.icon, + blind_sign_ctx.review_title, + blind_sign_ctx.review_sub_title, + blind_sign_ctx.reject_text, + blind_sign_ctx.continue_callback, + blind_sign_ctx.reject_callback); +} + +static void blind_sign_info() { + nbgl_useCaseReviewStart(&C_round_warning_64px, + "Blind Signing", + "This operation cannot be\nsecurely interpreted by\nLedger Stax. It " + "might put your\nassets at risk.", + blind_sign_ctx.reject_text, + blind_sign_continue, + blind_sign_ctx.reject_callback); +} + +static void blind_sign_choice(bool enable) { + if (enable) { + settings_set_allow_blind_signing(true); + nbgl_useCaseStatus("BLIND SIGNING\nENABLED", true, blind_sign_info); + } else { + blind_sign_ctx.reject_callback(); + } +} + +void nbgl_useCaseReviewBlindSign(const nbgl_icon_details_t *icon, + const char *review_title, + const char *review_sub_title, + const char *reject_text, + nbgl_callback_t continue_callback, + nbgl_callback_t reject_callback) { + blind_sign_ctx.icon = icon; + blind_sign_ctx.review_title = review_title; + blind_sign_ctx.review_sub_title = review_sub_title; + blind_sign_ctx.reject_text = reject_text; + blind_sign_ctx.continue_callback = continue_callback; + blind_sign_ctx.reject_callback = reject_callback; + if (N_storage.settings.allowBlindSigning) { + blind_sign_info(); + } else { + nbgl_useCaseChoice(&C_round_warning_64px, + "Enable blind signing to\nauthorize this\noperation", + NULL, + "Enable blind signing", + reject_text, + blind_sign_choice); + } +} + +#endif \ No newline at end of file diff --git a/src/ui/blind_sign_nbgl.h b/src/ui/blind_sign_nbgl.h new file mode 100644 index 0000000..b7588a6 --- /dev/null +++ b/src/ui/blind_sign_nbgl.h @@ -0,0 +1,21 @@ +#pragma once + +#ifdef HAVE_NBGL + +#include "nbgl_use_case.h" + +typedef void (*nbgl_useCaseReview_t)(const nbgl_icon_details_t *icon, + const char *review_title, + const char *review_sub_title, + const char *reject_text, + nbgl_callback_t continue_callback, + nbgl_callback_t reject_callback); + +void nbgl_useCaseReviewBlindSign(const nbgl_icon_details_t *icon, + const char *review_title, + const char *review_sub_title, + const char *reject_text, + nbgl_callback_t continue_callback, + nbgl_callback_t reject_callback); + +#endif \ No newline at end of file diff --git a/src/ui/display.h b/src/ui/display.h new file mode 100644 index 0000000..9e53f8e --- /dev/null +++ b/src/ui/display.h @@ -0,0 +1,33 @@ +#pragma once + +#include // uint64_t + +///////// show address UI ////////// + +void showAddressScreen(const uint64_t accountId); + +// callback for when the user accepts the address +void showAddressConfirm(void); + +// callback for when the user cancels the address display +void showAddressCancel(void); + +///////// sign token UI ////////// + +void signTokenScreen(); + +// callback for when the user signs the token +void signTokenConfirm(void); + +// callback for when the user cancels the token signing +void signTokenCancel(void); + +///////// sign transaction UI ////////// + +void signTransactionScreen(); + +// callback for when the user signs the transaction +void signTransactionConfirm(void); + +// callback for when the user cancels the transaction signing +void signTransactionCancel(void); \ No newline at end of file diff --git a/src/ui/glyph_symbols.h b/src/ui/glyph_symbols.h new file mode 100644 index 0000000..3541202 --- /dev/null +++ b/src/ui/glyph_symbols.h @@ -0,0 +1,12 @@ +// used only to avoid VSCode warnings, as it doesn't find those definitions by itself + +#pragma once + +#ifdef HAVE_NBGL + +#include "nbgl_types.h" + +extern const nbgl_icon_details_t C_ArdorIcon64px; +extern const nbgl_icon_details_t C_round_warning_64px; + +#endif \ No newline at end of file diff --git a/src/ui/menu.h b/src/ui/menu.h new file mode 100644 index 0000000..84c33c1 --- /dev/null +++ b/src/ui/menu.h @@ -0,0 +1,6 @@ +#pragma once + +/** + * Show main menu (ready screen, version, quit). + */ +void ui_menu_main(void); \ No newline at end of file diff --git a/src/ui/menu_bagl.c b/src/ui/menu_bagl.c new file mode 100644 index 0000000..4a5d51a --- /dev/null +++ b/src/ui/menu_bagl.c @@ -0,0 +1,125 @@ +#ifdef HAVE_BAGL + +#include "ux.h" +#include "menu.h" +#include "glyphs.h" +#include "ardor.h" + +////////////////////////////////////////////////////////////////////// +static const char* allow_blind_sign_data_getter(unsigned int idx); +static void allow_blind_sign_data_selector(unsigned int idx); + +////////////////////////////////////////////////////////////////////////////////////// +// Settings menu: + +enum SettingsMenuOption { + SettingsMenuOptionAllowBlindSign, + // back must remain last + SettingsMenuOptionBack +}; + +static unsigned int settings_submenu_option_index(enum SettingsMenuOption settings_menu_option) { + if (settings_menu_option == SettingsMenuOptionAllowBlindSign) { + return (unsigned int) settings_menu_option; + } else { + return 0; + } +} + +const char* const settings_submenu_getter_values[] = { + "Allow blind signing", + "Back", +}; + +static const char* settings_submenu_getter(unsigned int idx) { + if (idx < ARRAYLEN(settings_submenu_getter_values)) { + return settings_submenu_getter_values[idx]; + } + return NULL; +} + +static void settings_submenu_selector(unsigned int idx) { + if (idx == 0) { + ux_menulist_init_select(0, + allow_blind_sign_data_getter, + allow_blind_sign_data_selector, + N_storage.settings.allowBlindSigning); + } else { + ui_menu_main(); + } +} + +////////////////////////////////////////////////////////////////////////////////////// +// Allow blind signing submenu + +static void allow_blind_sign_data_change(bool blind_sign) { + nvm_write((void*) &N_storage.settings.allowBlindSigning, &blind_sign, sizeof(blind_sign)); +} + +const char* const no_yes_data_getter_values[] = {"No", "Yes", "Back"}; + +static const char* allow_blind_sign_data_getter(unsigned int idx) { + if (idx < ARRAYLEN(no_yes_data_getter_values)) { + return no_yes_data_getter_values[idx]; + } + return NULL; +} + +static void allow_blind_sign_data_selector(unsigned int idx) { + switch (idx) { + case 0: + allow_blind_sign_data_change(false); + break; + case 1: + allow_blind_sign_data_change(true); + break; + default: + break; + } + unsigned int select_item = settings_submenu_option_index(SettingsMenuOptionAllowBlindSign); + ux_menulist_init_select(0, settings_submenu_getter, settings_submenu_selector, select_item); +} + +////////////////////////////////////////////////////////////////////// + +UX_STEP_NOCB(ux_idle_flow_1_step, + bn, + { + "Application", + "is ready", + }); +UX_STEP_CB(ux_idle_flow_2_step, + pb, + ux_menulist_init(0, settings_submenu_getter, settings_submenu_selector), + { + &C_icon_coggle, + "Settings", + }); +UX_STEP_NOCB(ux_idle_flow_3_step, + bn, + { + "Version", + APPVERSION, + }); +UX_STEP_CB(ux_idle_flow_4_step, + pb, + os_sched_exit(-1), + { + &C_icon_dashboard, + "Quit", + }); +UX_FLOW(ux_idle_flow, + &ux_idle_flow_1_step, + &ux_idle_flow_2_step, + &ux_idle_flow_3_step, + &ux_idle_flow_4_step); + +void ui_menu_main() { + // reserve a display stack slot if none yet + if (G_ux.stack_count == 0) { + ux_stack_push(); + } + ux_flow_init(0, ux_idle_flow, NULL); +} + +#endif \ No newline at end of file diff --git a/src/ui/menu_nbgl.c b/src/ui/menu_nbgl.c new file mode 100644 index 0000000..41d37bd --- /dev/null +++ b/src/ui/menu_nbgl.c @@ -0,0 +1,84 @@ +#ifdef HAVE_NBGL + +#include "menu.h" +#include "glyphs.h" +#include "nbgl_use_case.h" +#include "os.h" +#include "ardor.h" +#include "settings.h" +#include "glyph_symbols.h" + +void app_quit(void) { + // exit app here + os_sched_exit(-1); +} + +/////////////////////////////////////////////////////////////////////////// +// Settings menu: + +static const char* const INFO_TYPES[] = {"Version", "Developer"}; +static const char* const INFO_CONTENTS[] = {APPVERSION, "Jelurida"}; + +enum { + BLIND_SIGNING_IDX = 0, + NB_SETTINGS, +}; +static nbgl_layoutSwitch_t G_switches[NB_SETTINGS]; + +enum { + BLIND_SIGNING_TOKEN = FIRST_USER_TOKEN, +}; + +#define SETTINGS_PAGE_NUMBER 2 +static bool settings_nav_callback(uint8_t page, nbgl_pageContent_t* content) { + if (page == 0) { + content->type = INFOS_LIST; + content->infosList.nbInfos = ARRAY_COUNT(INFO_TYPES); + content->infosList.infoTypes = INFO_TYPES; + content->infosList.infoContents = INFO_CONTENTS; + } else if (page == 1) { + // Read again the NVM as the value might have changed following a user touch + if (N_storage.settings.allowBlindSigning == false) { + G_switches[BLIND_SIGNING_IDX].initState = OFF_STATE; + } else { + G_switches[BLIND_SIGNING_IDX].initState = ON_STATE; + } + content->type = SWITCHES_LIST; + content->switchesList.nbSwitches = NB_SETTINGS; + content->switchesList.switches = G_switches; + } else { + return false; + } + return true; +} + +static void settings_controls_callback(int token, uint8_t index) { + UNUSED(index); + if (token == BLIND_SIGNING_TOKEN) { + // Write in NVM the opposite of what the current toggle is + settings_set_allow_blind_signing(G_switches[BLIND_SIGNING_IDX].initState != ON_STATE); + } +} + +static void ui_menu_settings() { + G_switches[BLIND_SIGNING_IDX].text = "Blind signing"; + G_switches[BLIND_SIGNING_IDX].subText = "Enable blind signing"; + G_switches[BLIND_SIGNING_IDX].token = BLIND_SIGNING_TOKEN; + G_switches[BLIND_SIGNING_IDX].tuneId = TUNE_TAP_CASUAL; + + nbgl_useCaseSettings(APPNAME " settings", + 0, + SETTINGS_PAGE_NUMBER, + false, + ui_menu_main, + settings_nav_callback, + settings_controls_callback); +} + +/////////////////////////////////////////////////////////////////////////// + +void ui_menu_main(void) { + nbgl_useCaseHome(APPNAME, &C_ArdorIcon64px, NULL, true, ui_menu_settings, app_quit); +} + +#endif \ No newline at end of file diff --git a/src/ui/show_address_bagl.c b/src/ui/show_address_bagl.c new file mode 100644 index 0000000..6bd7d53 --- /dev/null +++ b/src/ui/show_address_bagl.c @@ -0,0 +1,33 @@ +#ifdef HAVE_BAGL + +#include + +#include "ux.h" +#include "display.h" +#include "reedSolomon.h" + +char screenContent[27]; + +UX_STEP_CB(saFlowPage1, + bnnn_paging, + showAddressConfirm(), + { + .title = "Your Address", + .text = screenContent, + }); +UX_STEP_CB(saFlowPage2, pb, showAddressConfirm(), {&C_icon_validate_14, "Done"}); +UX_FLOW(saFlow, &saFlowPage1, &saFlowPage2); + +void showAddressScreen(const uint64_t accountId) { + explicit_bzero(screenContent, sizeof(screenContent)); + snprintf(screenContent, sizeof(screenContent), APP_PREFIX); + reedSolomonEncode(accountId, screenContent + strlen(screenContent)); + + if (0 == G_ux.stack_count) { + ux_stack_push(); + } + + ux_flow_init(0, saFlow, NULL); +} + +#endif \ No newline at end of file diff --git a/src/ui/show_address_nbgl.c b/src/ui/show_address_nbgl.c new file mode 100644 index 0000000..8153c69 --- /dev/null +++ b/src/ui/show_address_nbgl.c @@ -0,0 +1,46 @@ +#ifdef HAVE_NBGL + +#include // memset + +#include "menu.h" +#include "display.h" +#include "glyphs.h" +#include "nbgl_use_case.h" +#include "reedSolomon.h" + +static char rsAddress[27]; + +static void confirm_address_approval(void) { + nbgl_useCaseStatus("ADDRESS\nVERIFIED", true, showAddressConfirm); +} + +static void confirm_address_rejection(void) { + nbgl_useCaseStatus("Address verification\ncancelled", false, showAddressCancel); +} + +static void reviewChoice(bool confirm) { + if (confirm) { + confirm_address_approval(); + } else { + confirm_address_rejection(); + } +} + +static void continueReview(void) { + nbgl_useCaseAddressConfirmation(rsAddress, reviewChoice); +} + +void showAddressScreen(const uint64_t accountId) { + explicit_bzero(rsAddress, sizeof(rsAddress)); + snprintf(rsAddress, sizeof(rsAddress), APP_PREFIX); + reedSolomonEncode(accountId, rsAddress + strlen(rsAddress)); + + nbgl_useCaseReviewStart(&C_ArdorIcon64px, + "Verify Ardor address", + NULL, + "Cancel", + continueReview, + confirm_address_rejection); +} + +#endif \ No newline at end of file diff --git a/src/ui/sign_token_bagl.c b/src/ui/sign_token_bagl.c new file mode 100644 index 0000000..edd0b88 --- /dev/null +++ b/src/ui/sign_token_bagl.c @@ -0,0 +1,50 @@ +#ifdef HAVE_BAGL + +#include "ux.h" +#include "display.h" +#include "menu.h" +#include "ardor.h" +#include "blind_sign_bagl.h" + +static void signTokenConfirmation() { + signTokenConfirm(); + ui_menu_main(); +} + +static void signTokenCancellation() { + signTokenCancel(); + ui_menu_main(); +} + +UX_STEP_NOCB(stBlindSignWarning, + pnn, + { + &C_icon_warning, + "Blind", + "Signing", + }); +UX_STEP_CB(stFlowPage1, + pb, + signTokenConfirmation(), + { + &C_icon_validate_14, + "Sign token", + }); +UX_STEP_CB(stFlowPage2, + pb, + signTokenCancellation(), + { + &C_icon_crossmark, + "Reject", + }); +UX_FLOW(stFlow, &stBlindSignWarning, &stFlowPage1, &stFlowPage2); + +void signTokenScreen() { + if (N_storage.settings.allowBlindSigning) { + ux_flow_init(0, stFlow, NULL); + } else { + blindSigningNotEnabledScreen(signTokenCancellation); + } +} + +#endif \ No newline at end of file diff --git a/src/ui/sign_token_nbgl.c b/src/ui/sign_token_nbgl.c new file mode 100644 index 0000000..0c7524c --- /dev/null +++ b/src/ui/sign_token_nbgl.c @@ -0,0 +1,52 @@ +#ifdef HAVE_NBGL + +#include "display.h" +#include "nbgl_use_case.h" +#include "glyphs.h" +#include "menu.h" +#include "glyph_symbols.h" +#include "blind_sign_nbgl.h" + +static void signTokenConfirmation() { + signTokenConfirm(); + nbgl_useCaseStatus("TOKEN SIGNED", true, ui_menu_main); +} + +static void signTokenCancellation() { + signTokenCancel(); + nbgl_useCaseStatus("Token signature\ncancelled", false, ui_menu_main); +} + +static void reviewChoice(bool confirm) { + if (confirm) { + signTokenConfirmation(); + } else { + signTokenCancellation(); + } +} + +static void reviewContinue() { + nbgl_layoutTagValueList_t pairList = {.nbMaxLinesForValue = 0, .nbPairs = 0, .pairs = NULL}; + + nbgl_pageInfoLongPress_t infoLongPress = {.icon = &C_ArdorIcon64px, + .text = "Sign token", + .longPressText = "Hold to sign"}; + + nbgl_useCaseStaticReview(&pairList, &infoLongPress, "Cancel", reviewChoice); +} + +static void askSignatureRejectionConfirmation(void) { + // display a choice to confirm/cancel rejection + nbgl_useCaseConfirm("Reject signature?", NULL, "Yes, Reject", "Go back", signTokenCancellation); +} + +void signTokenScreen() { + nbgl_useCaseReviewBlindSign(&C_ArdorIcon64px, + "Token signature", + NULL, + "Reject", + reviewContinue, + askSignatureRejectionConfirmation); +} + +#endif \ No newline at end of file diff --git a/src/ui/sign_tx_bagl.c b/src/ui/sign_tx_bagl.c new file mode 100644 index 0000000..fd0cfe0 --- /dev/null +++ b/src/ui/sign_tx_bagl.c @@ -0,0 +1,129 @@ +#ifdef HAVE_BAGL + +#include "ux.h" +#include "display.h" +#include "menu.h" +#include "ardor.h" +#include "blind_sign_bagl.h" + +static void signTxConfirmation() { + signTransactionConfirm(); + ui_menu_main(); +} + +static void signTxCancellation() { + signTransactionCancel(); + ui_menu_main(); +} + +#define MAX_NUM_STEPS 10 + +const ux_flow_step_t *ux_tx_flow[MAX_NUM_STEPS + 1]; + +UX_STEP_NOCB(ux_tx_initial, + pnn, + { + &C_icon_eye, + "Authorize", + "transaction", + }); +UX_STEP_NOCB(ux_tx_blind_signing_warning, + pnn, + { + &C_icon_warning, + "Blind", + "Signing", + }); +UX_STEP_NOCB(ux_tx_chain, + bnnn_paging, + { + .title = "Chain&TxnType", + .text = state.txnAuth.chainAndTxnTypeText, + }); +UX_STEP_NOCB(ux_tx_window0, + bnnn_paging, + { + .title = state.txnAuth.windowTitles[0], + .text = state.txnAuth.windowTexts[0], + }); +UX_STEP_NOCB(ux_tx_window1, + bnnn_paging, + { + .title = state.txnAuth.windowTitles[1], + .text = state.txnAuth.windowTexts[1], + }); +UX_STEP_NOCB(ux_tx_window2, + bnnn_paging, + { + .title = state.txnAuth.windowTitles[2], + .text = state.txnAuth.windowTexts[2], + }); +UX_STEP_NOCB(ux_tx_appendages, + bnnn_paging, + { + .title = "Appendages", + .text = state.txnAuth.appendagesText, + }); +UX_STEP_NOCB(ux_tx_fee, + bnnn_paging, + { + .title = "Fees", + .text = state.txnAuth.feeText, + }); +UX_STEP_CB(ux_tx_accept, + pbb, + signTxConfirmation(), + { + &C_icon_validate_14, + "Accept", + "and send", + }); +UX_STEP_CB(ux_tx_reject, + pb, + signTxCancellation(), + { + &C_icon_crossmark, + "Reject", + }); + +void signTransactionScreen() { + if (state.txnAuth.requiresBlindSigning && !N_storage.settings.allowBlindSigning) { + blindSigningNotEnabledScreen(signTxCancellation); + return; + } + + uint8_t index = 0; + + ux_tx_flow[index++] = &ux_tx_initial; + + if (state.txnAuth.requiresBlindSigning) { + ux_tx_flow[index++] = &ux_tx_blind_signing_warning; + } + + ux_tx_flow[index++] = &ux_tx_chain; + + if (*state.txnAuth.windowTitles[0] != 0) { + ux_tx_flow[index++] = &ux_tx_window0; + } + + if (*state.txnAuth.windowTitles[1] != 0) { + ux_tx_flow[index++] = &ux_tx_window1; + } + + if (*state.txnAuth.windowTitles[2] != 0) { + ux_tx_flow[index++] = &ux_tx_window2; + } + + if (*state.txnAuth.appendagesText != 0) { + ux_tx_flow[index++] = &ux_tx_appendages; + } + + ux_tx_flow[index++] = &ux_tx_fee; + ux_tx_flow[index++] = &ux_tx_accept; + ux_tx_flow[index++] = &ux_tx_reject; + + ux_tx_flow[index++] = FLOW_END_STEP; + ux_flow_init(0, ux_tx_flow, NULL); +} + +#endif \ No newline at end of file diff --git a/src/ui/sign_tx_ngbl.c b/src/ui/sign_tx_ngbl.c new file mode 100644 index 0000000..c7b1311 --- /dev/null +++ b/src/ui/sign_tx_ngbl.c @@ -0,0 +1,81 @@ +#ifdef HAVE_NBGL + +#include "display.h" +#include "nbgl_use_case.h" +#include "ardor.h" +#include "glyphs.h" +#include "menu.h" +#include "glyph_symbols.h" +#include "blind_sign_nbgl.h" + +static void signTxConfirmation() { + signTransactionConfirm(); + nbgl_useCaseStatus("TRANSACTION\nSIGNED", true, ui_menu_main); +} + +static void signTxCancellation() { + signTransactionCancel(); + nbgl_useCaseStatus("Transaction\nrejected", false, ui_menu_main); +} + +static void askTransactionRejectionConfirmation(void) { + // display a choice to confirm/cancel rejection + nbgl_useCaseConfirm("Reject transaction?", + NULL, + "Yes, Reject", + "Go back to transaction", + signTxCancellation); +} + +// called when long press button on 3rd page is long-touched or when reject footer is touched +static void reviewChoice(bool confirm) { + if (confirm) { + signTxConfirmation(); + } else { + askTransactionRejectionConfirmation(); + } +} + +static nbgl_layoutTagValue_t pairs[6]; +static nbgl_layoutTagValueList_t pairList; + +static void reviewContinue() { + int i = 0; + pairs[i].item = "Chain&TxnType"; + pairs[i++].value = state.txnAuth.chainAndTxnTypeText; + for (int j = 0; j < MAX_WINDOWS; j++) { + if (*state.txnAuth.windowTitles[j] != 0) { + pairs[i].item = state.txnAuth.windowTitles[j]; + pairs[i++].value = state.txnAuth.windowTexts[j]; + } + } + if (*state.txnAuth.appendagesText != 0) { + pairs[i].item = "Appendages"; + pairs[i++].value = state.txnAuth.appendagesText; + } + pairs[i].item = "Fees"; + pairs[i++].value = state.txnAuth.feeText; + + pairList.nbMaxLinesForValue = 0; + pairList.nbPairs = i; + pairList.pairs = pairs; + + nbgl_pageInfoLongPress_t infoLongPress = {.icon = &C_ArdorIcon64px, + .text = "Sign transaction?", + .longPressText = "Hold to sign"}; + PRINTF("nbgl_useCaseStaticReview\n"); + nbgl_useCaseStaticReview(&pairList, &infoLongPress, "Reject transaction", reviewChoice); +} + +void signTransactionScreen() { + nbgl_useCaseReview_t useCaseReview = + state.txnAuth.requiresBlindSigning ? nbgl_useCaseReviewBlindSign : nbgl_useCaseReviewStart; + useCaseReview(&C_ArdorIcon64px, + "Review transaction", + NULL, + "Reject transaction", + reviewContinue, + askTransactionRejectionConfirmation); +} + +#endif \ No newline at end of file diff --git a/src/uxI.h b/src/uxI.h deleted file mode 100644 index 7d6fb83..0000000 --- a/src/uxI.h +++ /dev/null @@ -1,32 +0,0 @@ - -#if defined(TARGET_NANOS) -// ux is a magic global variable implicitly referenced by the UX_ macros. Apps -// should never need to reference it directly. - extern ux_state_t ux; -#endif - -// These are helper macros for defining UI elements. There are four basic UI -// elements: the background, which is a black rectangle that fills the whole -// screen; icons on the left and right sides of the screen, typically used for -// navigation or approval; and text, which can be anywhere. The UI_TEXT macro -// uses Open Sans Regular 11px, which I've found to be adequate for all text -// elements; if other fonts are desired, I suggest defining a separate macro -// for each of them (e.g. UI_TEXT_BOLD). -// -// In the event that you want to define your own UI elements from scratch, -// you'll want to read include/bagl.h and include/os_io_seproxyhal.h in the -// nanos-secure-sdk repo to learn what each of the fields are used for. -#define UI_BACKGROUND() {{BAGL_RECTANGLE,0,0,0,128,32,0,0,BAGL_FILL,0,0xFFFFFF,0,0},NULL,0,0,0,NULL,NULL,NULL} -#define UI_ICON_LEFT(userid, glyph) {{BAGL_ICON,userid,3,12,7,7,0,0,0,0xFFFFFF,0,0,glyph},NULL,0,0,0,NULL,NULL,NULL} -#define UI_ICON_RIGHT(userid, glyph) {{BAGL_ICON,userid,117,13,8,6,0,0,0,0xFFFFFF,0,0,glyph},NULL,0,0,0,NULL,NULL,NULL} -#define UI_TEXT(userid, x, y, w, text) {{BAGL_LABELINE,userid,x,y,w,12,0,0,0,0xFFFFFF,0,BAGL_FONT_OPEN_SANS_REGULAR_11px|BAGL_FONT_ALIGNMENT_CENTER,0},(char *)text,0,0,0,NULL,NULL,NULL} - - -// ui_idle displays the main menu screen. Command handlers should call ui_idle -// when they finish. -void ui_idle(void); - - - -//Added for text scroll -#define UI_NANOS_TEXT_SCROLL(userid, x, y, w, text) {{BAGL_LABELINE,userid,x,y,w,12,0x80|10,0,0,0xFFFFFF,0,BAGL_FONT_OPEN_SANS_REGULAR_11px|BAGL_FONT_ALIGNMENT_CENTER,26},(char *)text,0,0,0,NULL,NULL,NULL} diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt deleted file mode 100644 index ad1cdc6..0000000 --- a/tests/CMakeLists.txt +++ /dev/null @@ -1,24 +0,0 @@ -cmake_minimum_required(VERSION 3.10) -project(ardor_unit_tests C) - -include(CTest) -enable_testing() - -set(CMAKE_C_STANDARD 11) -set(CMAKE_C_STANDARD_REQUIRED True) -set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wall -pedantic -g -O0 --coverage") - -add_compile_definitions(TEST) - -include_directories(include/ ../src) - -add_library(ardor - ../src/reedSolomon.c - ../src/reedSolomon.h -) - -add_executable(test_reedSolomon src/test_reedSolomon.c) - -target_link_libraries(test_reedSolomon PUBLIC ardor cmocka) - -add_test(test_reedSolomon test_reedSolomon) diff --git a/tests/ardor_command_sender.py b/tests/ardor_command_sender.py new file mode 100644 index 0000000..31b6803 --- /dev/null +++ b/tests/ardor_command_sender.py @@ -0,0 +1,94 @@ +from contextlib import contextmanager +from typing import Generator, List, Optional +from ragger.backend.interface import BackendInterface, RAPDU +from constants import CLA, RESPONSE_SUFFIX, R_SUCCESS, R_TXN_UNAUTHORIZED +from bip_utils import Bip32Utils + +INS_AUTH_SIGN_TXN = 0x03 +TX_P1_INIT = 0x01 +TX_P1_CONTINUE = 0x02 +TX_P1_SIGN = 0x03 + +INS_SHOW_ADDRESS = 0x05 + +INS_SIGN_TOKEN = 0x07 +TK_P1_INIT = 0x00 +TK_P1_MSG_BYTES = 0x01 +TK_P1_SIGN = 0x02 + +CHUNK_SIZE = 128 +SIGNATURE_LENGTH = 64 + +def split_message(message: bytes, max_size: int) -> List[bytes]: + return [message[x:x + max_size] for x in range(0, len(message), max_size)] + +def pack_derivation_path(derivation_path: str) -> bytes: + split = derivation_path.split("/") + + if split[0] != "m": + raise ValueError("Error master expected") + + path_bytes: bytes = b'' + for value in split[1:]: + if value == "": + raise ValueError(f'Error missing value in split list "{split}"') + if value.endswith('\''): + path_bytes += Bip32Utils.HardenIndex(int(value[:-1])).to_bytes(4, byteorder='little') + else: + path_bytes += int(value).to_bytes(4, byteorder='little') + return path_bytes + + +class ArdorCommandSender: + def __init__(self, backend: BackendInterface) -> None: + self.backend = backend + + @contextmanager + def load_tx(self, transaction: bytes) -> Generator[None, None, None]: + messages = split_message(transaction, CHUNK_SIZE) + self.backend.exchange(cla=CLA, + ins=INS_AUTH_SIGN_TXN, + p1=((len(transaction) & 0b0011111100000000) >> 6) | TX_P1_INIT, + p2=len(transaction) & 0xff, + data=messages[0]) + + for msg in messages[1:-1]: + self.backend.exchange(cla=CLA, ins=INS_AUTH_SIGN_TXN, p1=TX_P1_CONTINUE, p2=0, data=msg) + + with self.backend.exchange_async(cla=CLA, ins=INS_AUTH_SIGN_TXN, p1=TX_P1_CONTINUE, p2=0, data=messages[-1]) as response: + yield response + + def get_async_response(self) -> Optional[RAPDU]: + return self.backend.last_async_response + + def sign_tx(self, path: str) -> RAPDU: + rapdu = self.backend.exchange(cla=CLA, ins=INS_AUTH_SIGN_TXN, p1=TX_P1_SIGN, data=pack_derivation_path(path)) + assert rapdu is not None + assert rapdu.status == RESPONSE_SUFFIX + assert len(rapdu.data) == 1 + SIGNATURE_LENGTH + assert rapdu.data[0] == R_SUCCESS + return rapdu.data[1:] + + def sign_tx_reject(self, path: str): + rapdu = self.backend.exchange(cla=CLA, ins=INS_AUTH_SIGN_TXN, p1=TX_P1_SIGN, data=pack_derivation_path(path)) + assert rapdu is not None + assert rapdu.status == RESPONSE_SUFFIX + assert len(rapdu.data) == 1 + assert rapdu.data[0] == R_TXN_UNAUTHORIZED + + @contextmanager + def show_address(self, path: str) -> Generator[None, None, None]: + with self.backend.exchange_async(cla=CLA, ins=INS_SHOW_ADDRESS, data=pack_derivation_path(path)) as response: + yield response + + def sign_token_init(self) -> RAPDU: + return self.backend.exchange(cla=CLA, ins=INS_SIGN_TOKEN, p1=TK_P1_INIT) + + def sign_token_send_bytes(self, data: bytes) -> RAPDU: + return self.backend.exchange(cla=CLA, ins=INS_SIGN_TOKEN, p1=TK_P1_MSG_BYTES, data=data) + + @contextmanager + def sign_token_sign(self, path: str, timestamp: int) -> Generator[None, None, None]: + with self.backend.exchange_async(cla=CLA, ins=INS_SIGN_TOKEN, p1=TK_P1_SIGN, + data=timestamp.to_bytes(4, byteorder='little') + pack_derivation_path(path)) as response: + yield response \ No newline at end of file diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..e8bf2ba --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,11 @@ +# This line includes the default `Ragger` configuration. +# It can be modified to suit local needs +from ragger.conftest import configuration + +configuration.OPTIONAL.CUSTOM_SEED = "opinion change copy struggle town cigar input kit school patient execute bird bundle option canvas defense hover poverty skill donkey pottery infant sense orchard" + +# This line will be interpreted by `pytest` which will load the code from the +# given modules, in this case `ragger.conftest.base_conftest`. +# This module will define several fixtures, parametrized will the fields of +# `configuration.OPTIONAL` variable. +pytest_plugins = ("ragger.conftest.base_conftest", ) \ No newline at end of file diff --git a/tests/constants.py b/tests/constants.py new file mode 100644 index 0000000..b74c205 --- /dev/null +++ b/tests/constants.py @@ -0,0 +1,15 @@ +from pathlib import Path + +ROOT_SCREENSHOT_PATH = Path(__file__).resolve().parent + +PATH_STR_0 = "m/44'/16754'/0'/1'/0" +PATH_STR_1 = "m/44'/16754'/0'/1'/1" +PATH_STR_3 = "m/44'/16754'/0'/1'/3" +PUBLIC_KEY_0 = "6e0983e578fab84ab29c209182a8eff30a186fa84211da55a6a29fcc2b7e4a20" +PUBLIC_KEY_3 = "d585765b070966ab2873f64ee629dcbb02f427f0c111dc08dba801b28f95127f" + +CLA = 0xE0 +R_SUCCESS = 0 +R_REJECT = 1 +R_TXN_UNAUTHORIZED = 22 +RESPONSE_SUFFIX = 0x9000 diff --git a/tests/include/os.h b/tests/include/os.h deleted file mode 100644 index f25cb49..0000000 --- a/tests/include/os.h +++ /dev/null @@ -1,25 +0,0 @@ -/******************************************************************************* -* (c) 2021 Jelurida IP B.V. -* -* -* 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 -#include - -#define PIC(x) (x) \ No newline at end of file diff --git a/tests/requirements.txt b/tests/requirements.txt new file mode 100644 index 0000000..7e4aa4f --- /dev/null +++ b/tests/requirements.txt @@ -0,0 +1,3 @@ +pytest +speculos +ragger[speculos] \ No newline at end of file diff --git a/tests/snapshots/nanos/test_ardor_coin_exchange/00000.png b/tests/snapshots/nanos/test_ardor_coin_exchange/00000.png new file mode 100644 index 0000000..92e0646 Binary files /dev/null and b/tests/snapshots/nanos/test_ardor_coin_exchange/00000.png differ diff --git a/tests/snapshots/nanos/test_ardor_coin_exchange/00001.png b/tests/snapshots/nanos/test_ardor_coin_exchange/00001.png new file mode 100644 index 0000000..e544746 Binary files /dev/null and b/tests/snapshots/nanos/test_ardor_coin_exchange/00001.png differ diff --git a/tests/snapshots/nanos/test_ardor_coin_exchange/00002.png b/tests/snapshots/nanos/test_ardor_coin_exchange/00002.png new file mode 100644 index 0000000..e5b1bfb Binary files /dev/null and b/tests/snapshots/nanos/test_ardor_coin_exchange/00002.png differ diff --git a/tests/snapshots/nanos/test_ardor_coin_exchange/00003.png b/tests/snapshots/nanos/test_ardor_coin_exchange/00003.png new file mode 100644 index 0000000..cd440b4 Binary files /dev/null and b/tests/snapshots/nanos/test_ardor_coin_exchange/00003.png differ diff --git a/tests/snapshots/nanos/test_ardor_coin_exchange/00004.png b/tests/snapshots/nanos/test_ardor_coin_exchange/00004.png new file mode 100644 index 0000000..a7fc2ac Binary files /dev/null and b/tests/snapshots/nanos/test_ardor_coin_exchange/00004.png differ diff --git a/tests/snapshots/nanos/test_ardor_coin_exchange/00005.png b/tests/snapshots/nanos/test_ardor_coin_exchange/00005.png new file mode 100644 index 0000000..05e1559 Binary files /dev/null and b/tests/snapshots/nanos/test_ardor_coin_exchange/00005.png differ diff --git a/tests/snapshots/nanos/test_ardor_coin_exchange/00006.png b/tests/snapshots/nanos/test_ardor_coin_exchange/00006.png new file mode 100644 index 0000000..1c9156c Binary files /dev/null and b/tests/snapshots/nanos/test_ardor_coin_exchange/00006.png differ diff --git a/tests/snapshots/nanos/test_ardor_coin_exchange/00007.png b/tests/snapshots/nanos/test_ardor_coin_exchange/00007.png new file mode 100644 index 0000000..535bfc4 Binary files /dev/null and b/tests/snapshots/nanos/test_ardor_coin_exchange/00007.png differ diff --git a/tests/snapshots/nanos/test_asset_transfer/00000.png b/tests/snapshots/nanos/test_asset_transfer/00000.png new file mode 100644 index 0000000..92e0646 Binary files /dev/null and b/tests/snapshots/nanos/test_asset_transfer/00000.png differ diff --git a/tests/snapshots/nanos/test_asset_transfer/00001.png b/tests/snapshots/nanos/test_asset_transfer/00001.png new file mode 100644 index 0000000..dad25d6 Binary files /dev/null and b/tests/snapshots/nanos/test_asset_transfer/00001.png differ diff --git a/tests/snapshots/nanos/test_asset_transfer/00002.png b/tests/snapshots/nanos/test_asset_transfer/00002.png new file mode 100644 index 0000000..d7be70d Binary files /dev/null and b/tests/snapshots/nanos/test_asset_transfer/00002.png differ diff --git a/tests/snapshots/nanos/test_asset_transfer/00003.png b/tests/snapshots/nanos/test_asset_transfer/00003.png new file mode 100644 index 0000000..01e7478 Binary files /dev/null and b/tests/snapshots/nanos/test_asset_transfer/00003.png differ diff --git a/tests/snapshots/nanos/test_asset_transfer/00004.png b/tests/snapshots/nanos/test_asset_transfer/00004.png new file mode 100644 index 0000000..0461827 Binary files /dev/null and b/tests/snapshots/nanos/test_asset_transfer/00004.png differ diff --git a/tests/snapshots/nanos/test_asset_transfer/00005.png b/tests/snapshots/nanos/test_asset_transfer/00005.png new file mode 100644 index 0000000..6f483cb Binary files /dev/null and b/tests/snapshots/nanos/test_asset_transfer/00005.png differ diff --git a/tests/snapshots/nanos/test_asset_transfer/00006.png b/tests/snapshots/nanos/test_asset_transfer/00006.png new file mode 100644 index 0000000..1e49227 Binary files /dev/null and b/tests/snapshots/nanos/test_asset_transfer/00006.png differ diff --git a/tests/snapshots/nanos/test_asset_transfer/00007.png b/tests/snapshots/nanos/test_asset_transfer/00007.png new file mode 100644 index 0000000..71d40af Binary files /dev/null and b/tests/snapshots/nanos/test_asset_transfer/00007.png differ diff --git a/tests/snapshots/nanos/test_asset_transfer/00008.png b/tests/snapshots/nanos/test_asset_transfer/00008.png new file mode 100644 index 0000000..fce5fba Binary files /dev/null and b/tests/snapshots/nanos/test_asset_transfer/00008.png differ diff --git a/tests/snapshots/nanos/test_asset_transfer/00009.png b/tests/snapshots/nanos/test_asset_transfer/00009.png new file mode 100644 index 0000000..1c9156c Binary files /dev/null and b/tests/snapshots/nanos/test_asset_transfer/00009.png differ diff --git a/tests/snapshots/nanos/test_asset_transfer/00010.png b/tests/snapshots/nanos/test_asset_transfer/00010.png new file mode 100644 index 0000000..535bfc4 Binary files /dev/null and b/tests/snapshots/nanos/test_asset_transfer/00010.png differ diff --git a/tests/snapshots/nanos/test_coin_exchange/00000.png b/tests/snapshots/nanos/test_coin_exchange/00000.png new file mode 100644 index 0000000..92e0646 Binary files /dev/null and b/tests/snapshots/nanos/test_coin_exchange/00000.png differ diff --git a/tests/snapshots/nanos/test_coin_exchange/00001.png b/tests/snapshots/nanos/test_coin_exchange/00001.png new file mode 100644 index 0000000..dad25d6 Binary files /dev/null and b/tests/snapshots/nanos/test_coin_exchange/00001.png differ diff --git a/tests/snapshots/nanos/test_coin_exchange/00002.png b/tests/snapshots/nanos/test_coin_exchange/00002.png new file mode 100644 index 0000000..e5b1bfb Binary files /dev/null and b/tests/snapshots/nanos/test_coin_exchange/00002.png differ diff --git a/tests/snapshots/nanos/test_coin_exchange/00003.png b/tests/snapshots/nanos/test_coin_exchange/00003.png new file mode 100644 index 0000000..37881cc Binary files /dev/null and b/tests/snapshots/nanos/test_coin_exchange/00003.png differ diff --git a/tests/snapshots/nanos/test_coin_exchange/00004.png b/tests/snapshots/nanos/test_coin_exchange/00004.png new file mode 100644 index 0000000..2d3d260 Binary files /dev/null and b/tests/snapshots/nanos/test_coin_exchange/00004.png differ diff --git a/tests/snapshots/nanos/test_coin_exchange/00005.png b/tests/snapshots/nanos/test_coin_exchange/00005.png new file mode 100644 index 0000000..fce5fba Binary files /dev/null and b/tests/snapshots/nanos/test_coin_exchange/00005.png differ diff --git a/tests/snapshots/nanos/test_coin_exchange/00006.png b/tests/snapshots/nanos/test_coin_exchange/00006.png new file mode 100644 index 0000000..1c9156c Binary files /dev/null and b/tests/snapshots/nanos/test_coin_exchange/00006.png differ diff --git a/tests/snapshots/nanos/test_coin_exchange/00007.png b/tests/snapshots/nanos/test_coin_exchange/00007.png new file mode 100644 index 0000000..535bfc4 Binary files /dev/null and b/tests/snapshots/nanos/test_coin_exchange/00007.png differ diff --git a/tests/snapshots/nanos/test_place_asset_exchange_order/00000.png b/tests/snapshots/nanos/test_place_asset_exchange_order/00000.png new file mode 100644 index 0000000..92e0646 Binary files /dev/null and b/tests/snapshots/nanos/test_place_asset_exchange_order/00000.png differ diff --git a/tests/snapshots/nanos/test_place_asset_exchange_order/00001.png b/tests/snapshots/nanos/test_place_asset_exchange_order/00001.png new file mode 100644 index 0000000..dad25d6 Binary files /dev/null and b/tests/snapshots/nanos/test_place_asset_exchange_order/00001.png differ diff --git a/tests/snapshots/nanos/test_place_asset_exchange_order/00002.png b/tests/snapshots/nanos/test_place_asset_exchange_order/00002.png new file mode 100644 index 0000000..8ade71f Binary files /dev/null and b/tests/snapshots/nanos/test_place_asset_exchange_order/00002.png differ diff --git a/tests/snapshots/nanos/test_place_asset_exchange_order/00003.png b/tests/snapshots/nanos/test_place_asset_exchange_order/00003.png new file mode 100644 index 0000000..5b560e6 Binary files /dev/null and b/tests/snapshots/nanos/test_place_asset_exchange_order/00003.png differ diff --git a/tests/snapshots/nanos/test_place_asset_exchange_order/00004.png b/tests/snapshots/nanos/test_place_asset_exchange_order/00004.png new file mode 100644 index 0000000..e36cc6d Binary files /dev/null and b/tests/snapshots/nanos/test_place_asset_exchange_order/00004.png differ diff --git a/tests/snapshots/nanos/test_place_asset_exchange_order/00005.png b/tests/snapshots/nanos/test_place_asset_exchange_order/00005.png new file mode 100644 index 0000000..6ad676e Binary files /dev/null and b/tests/snapshots/nanos/test_place_asset_exchange_order/00005.png differ diff --git a/tests/snapshots/nanos/test_place_asset_exchange_order/00006.png b/tests/snapshots/nanos/test_place_asset_exchange_order/00006.png new file mode 100644 index 0000000..bb42b50 Binary files /dev/null and b/tests/snapshots/nanos/test_place_asset_exchange_order/00006.png differ diff --git a/tests/snapshots/nanos/test_place_asset_exchange_order/00007.png b/tests/snapshots/nanos/test_place_asset_exchange_order/00007.png new file mode 100644 index 0000000..1b16314 Binary files /dev/null and b/tests/snapshots/nanos/test_place_asset_exchange_order/00007.png differ diff --git a/tests/snapshots/nanos/test_place_asset_exchange_order/00008.png b/tests/snapshots/nanos/test_place_asset_exchange_order/00008.png new file mode 100644 index 0000000..1c9156c Binary files /dev/null and b/tests/snapshots/nanos/test_place_asset_exchange_order/00008.png differ diff --git a/tests/snapshots/nanos/test_place_asset_exchange_order/00009.png b/tests/snapshots/nanos/test_place_asset_exchange_order/00009.png new file mode 100644 index 0000000..535bfc4 Binary files /dev/null and b/tests/snapshots/nanos/test_place_asset_exchange_order/00009.png differ diff --git a/tests/snapshots/nanos/test_send_ardr/00000.png b/tests/snapshots/nanos/test_send_ardr/00000.png new file mode 100644 index 0000000..92e0646 Binary files /dev/null and b/tests/snapshots/nanos/test_send_ardr/00000.png differ diff --git a/tests/snapshots/nanos/test_send_ardr/00001.png b/tests/snapshots/nanos/test_send_ardr/00001.png new file mode 100644 index 0000000..e544746 Binary files /dev/null and b/tests/snapshots/nanos/test_send_ardr/00001.png differ diff --git a/tests/snapshots/nanos/test_send_ardr/00002.png b/tests/snapshots/nanos/test_send_ardr/00002.png new file mode 100644 index 0000000..bd292e1 Binary files /dev/null and b/tests/snapshots/nanos/test_send_ardr/00002.png differ diff --git a/tests/snapshots/nanos/test_send_ardr/00003.png b/tests/snapshots/nanos/test_send_ardr/00003.png new file mode 100644 index 0000000..8bce185 Binary files /dev/null and b/tests/snapshots/nanos/test_send_ardr/00003.png differ diff --git a/tests/snapshots/nanos/test_send_ardr/00004.png b/tests/snapshots/nanos/test_send_ardr/00004.png new file mode 100644 index 0000000..3bcfc1a Binary files /dev/null and b/tests/snapshots/nanos/test_send_ardr/00004.png differ diff --git a/tests/snapshots/nanos/test_send_ardr/00005.png b/tests/snapshots/nanos/test_send_ardr/00005.png new file mode 100644 index 0000000..d28eec7 Binary files /dev/null and b/tests/snapshots/nanos/test_send_ardr/00005.png differ diff --git a/tests/snapshots/nanos/test_send_ardr/00006.png b/tests/snapshots/nanos/test_send_ardr/00006.png new file mode 100644 index 0000000..4994dc2 Binary files /dev/null and b/tests/snapshots/nanos/test_send_ardr/00006.png differ diff --git a/tests/snapshots/nanos/test_send_ardr/00007.png b/tests/snapshots/nanos/test_send_ardr/00007.png new file mode 100644 index 0000000..1c9156c Binary files /dev/null and b/tests/snapshots/nanos/test_send_ardr/00007.png differ diff --git a/tests/snapshots/nanos/test_send_ardr/00008.png b/tests/snapshots/nanos/test_send_ardr/00008.png new file mode 100644 index 0000000..535bfc4 Binary files /dev/null and b/tests/snapshots/nanos/test_send_ardr/00008.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_4_attachments/00000.png b/tests/snapshots/nanos/test_send_ignis_4_attachments/00000.png new file mode 100644 index 0000000..92e0646 Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_4_attachments/00000.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_4_attachments/00001.png b/tests/snapshots/nanos/test_send_ignis_4_attachments/00001.png new file mode 100644 index 0000000..2fcd73a Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_4_attachments/00001.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_4_attachments/00002.png b/tests/snapshots/nanos/test_send_ignis_4_attachments/00002.png new file mode 100644 index 0000000..dad25d6 Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_4_attachments/00002.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_4_attachments/00003.png b/tests/snapshots/nanos/test_send_ignis_4_attachments/00003.png new file mode 100644 index 0000000..bd292e1 Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_4_attachments/00003.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_4_attachments/00004.png b/tests/snapshots/nanos/test_send_ignis_4_attachments/00004.png new file mode 100644 index 0000000..b96dbe8 Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_4_attachments/00004.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_4_attachments/00005.png b/tests/snapshots/nanos/test_send_ignis_4_attachments/00005.png new file mode 100644 index 0000000..a12f7ce Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_4_attachments/00005.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_4_attachments/00006.png b/tests/snapshots/nanos/test_send_ignis_4_attachments/00006.png new file mode 100644 index 0000000..e243d4a Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_4_attachments/00006.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_4_attachments/00007.png b/tests/snapshots/nanos/test_send_ignis_4_attachments/00007.png new file mode 100644 index 0000000..ca24cfa Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_4_attachments/00007.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_4_attachments/00008.png b/tests/snapshots/nanos/test_send_ignis_4_attachments/00008.png new file mode 100644 index 0000000..115293c Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_4_attachments/00008.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_4_attachments/00009.png b/tests/snapshots/nanos/test_send_ignis_4_attachments/00009.png new file mode 100644 index 0000000..feabdd3 Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_4_attachments/00009.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_4_attachments/00010.png b/tests/snapshots/nanos/test_send_ignis_4_attachments/00010.png new file mode 100644 index 0000000..b39818e Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_4_attachments/00010.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_4_attachments/00011.png b/tests/snapshots/nanos/test_send_ignis_4_attachments/00011.png new file mode 100644 index 0000000..5e1f623 Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_4_attachments/00011.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_4_attachments/00012.png b/tests/snapshots/nanos/test_send_ignis_4_attachments/00012.png new file mode 100644 index 0000000..1c9156c Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_4_attachments/00012.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_4_attachments/00013.png b/tests/snapshots/nanos/test_send_ignis_4_attachments/00013.png new file mode 100644 index 0000000..535bfc4 Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_4_attachments/00013.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_blind_accept/00000.png b/tests/snapshots/nanos/test_send_ignis_blind_accept/00000.png new file mode 100644 index 0000000..92e0646 Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_blind_accept/00000.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_blind_accept/00001.png b/tests/snapshots/nanos/test_send_ignis_blind_accept/00001.png new file mode 100644 index 0000000..2fcd73a Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_blind_accept/00001.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_blind_accept/00002.png b/tests/snapshots/nanos/test_send_ignis_blind_accept/00002.png new file mode 100644 index 0000000..dad25d6 Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_blind_accept/00002.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_blind_accept/00003.png b/tests/snapshots/nanos/test_send_ignis_blind_accept/00003.png new file mode 100644 index 0000000..bd292e1 Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_blind_accept/00003.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_blind_accept/00004.png b/tests/snapshots/nanos/test_send_ignis_blind_accept/00004.png new file mode 100644 index 0000000..7292921 Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_blind_accept/00004.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_blind_accept/00005.png b/tests/snapshots/nanos/test_send_ignis_blind_accept/00005.png new file mode 100644 index 0000000..8a90eb4 Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_blind_accept/00005.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_blind_accept/00006.png b/tests/snapshots/nanos/test_send_ignis_blind_accept/00006.png new file mode 100644 index 0000000..29aee80 Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_blind_accept/00006.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_blind_accept/00007.png b/tests/snapshots/nanos/test_send_ignis_blind_accept/00007.png new file mode 100644 index 0000000..6a398f9 Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_blind_accept/00007.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_blind_accept/00008.png b/tests/snapshots/nanos/test_send_ignis_blind_accept/00008.png new file mode 100644 index 0000000..f88f8d3 Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_blind_accept/00008.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_blind_accept/00009.png b/tests/snapshots/nanos/test_send_ignis_blind_accept/00009.png new file mode 100644 index 0000000..1c9156c Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_blind_accept/00009.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_blind_accept/00010.png b/tests/snapshots/nanos/test_send_ignis_blind_accept/00010.png new file mode 100644 index 0000000..535bfc4 Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_blind_accept/00010.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_blind_reject/00000.png b/tests/snapshots/nanos/test_send_ignis_blind_reject/00000.png new file mode 100644 index 0000000..e2d0b1d Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_blind_reject/00000.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_blind_reject/00001.png b/tests/snapshots/nanos/test_send_ignis_blind_reject/00001.png new file mode 100644 index 0000000..6d8deaa Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_blind_reject/00001.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_blind_reject/00002.png b/tests/snapshots/nanos/test_send_ignis_blind_reject/00002.png new file mode 100644 index 0000000..535bfc4 Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_blind_reject/00002.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_blind_reject_tx/00000.png b/tests/snapshots/nanos/test_send_ignis_blind_reject_tx/00000.png new file mode 100644 index 0000000..92e0646 Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_blind_reject_tx/00000.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_blind_reject_tx/00001.png b/tests/snapshots/nanos/test_send_ignis_blind_reject_tx/00001.png new file mode 100644 index 0000000..2fcd73a Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_blind_reject_tx/00001.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_blind_reject_tx/00002.png b/tests/snapshots/nanos/test_send_ignis_blind_reject_tx/00002.png new file mode 100644 index 0000000..dad25d6 Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_blind_reject_tx/00002.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_blind_reject_tx/00003.png b/tests/snapshots/nanos/test_send_ignis_blind_reject_tx/00003.png new file mode 100644 index 0000000..bd292e1 Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_blind_reject_tx/00003.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_blind_reject_tx/00004.png b/tests/snapshots/nanos/test_send_ignis_blind_reject_tx/00004.png new file mode 100644 index 0000000..7292921 Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_blind_reject_tx/00004.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_blind_reject_tx/00005.png b/tests/snapshots/nanos/test_send_ignis_blind_reject_tx/00005.png new file mode 100644 index 0000000..8a90eb4 Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_blind_reject_tx/00005.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_blind_reject_tx/00006.png b/tests/snapshots/nanos/test_send_ignis_blind_reject_tx/00006.png new file mode 100644 index 0000000..29aee80 Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_blind_reject_tx/00006.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_blind_reject_tx/00007.png b/tests/snapshots/nanos/test_send_ignis_blind_reject_tx/00007.png new file mode 100644 index 0000000..6a398f9 Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_blind_reject_tx/00007.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_blind_reject_tx/00008.png b/tests/snapshots/nanos/test_send_ignis_blind_reject_tx/00008.png new file mode 100644 index 0000000..f88f8d3 Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_blind_reject_tx/00008.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_blind_reject_tx/00009.png b/tests/snapshots/nanos/test_send_ignis_blind_reject_tx/00009.png new file mode 100644 index 0000000..1c9156c Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_blind_reject_tx/00009.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_blind_reject_tx/00010.png b/tests/snapshots/nanos/test_send_ignis_blind_reject_tx/00010.png new file mode 100644 index 0000000..9c7e704 Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_blind_reject_tx/00010.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_blind_reject_tx/00011.png b/tests/snapshots/nanos/test_send_ignis_blind_reject_tx/00011.png new file mode 100644 index 0000000..535bfc4 Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_blind_reject_tx/00011.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_referenced_tx/00000.png b/tests/snapshots/nanos/test_send_ignis_referenced_tx/00000.png new file mode 100644 index 0000000..92e0646 Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_referenced_tx/00000.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_referenced_tx/00001.png b/tests/snapshots/nanos/test_send_ignis_referenced_tx/00001.png new file mode 100644 index 0000000..2fcd73a Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_referenced_tx/00001.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_referenced_tx/00002.png b/tests/snapshots/nanos/test_send_ignis_referenced_tx/00002.png new file mode 100644 index 0000000..dad25d6 Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_referenced_tx/00002.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_referenced_tx/00003.png b/tests/snapshots/nanos/test_send_ignis_referenced_tx/00003.png new file mode 100644 index 0000000..bd292e1 Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_referenced_tx/00003.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_referenced_tx/00004.png b/tests/snapshots/nanos/test_send_ignis_referenced_tx/00004.png new file mode 100644 index 0000000..d729393 Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_referenced_tx/00004.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_referenced_tx/00005.png b/tests/snapshots/nanos/test_send_ignis_referenced_tx/00005.png new file mode 100644 index 0000000..8a90eb4 Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_referenced_tx/00005.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_referenced_tx/00006.png b/tests/snapshots/nanos/test_send_ignis_referenced_tx/00006.png new file mode 100644 index 0000000..29aee80 Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_referenced_tx/00006.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_referenced_tx/00007.png b/tests/snapshots/nanos/test_send_ignis_referenced_tx/00007.png new file mode 100644 index 0000000..78032ff Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_referenced_tx/00007.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_referenced_tx/00008.png b/tests/snapshots/nanos/test_send_ignis_referenced_tx/00008.png new file mode 100644 index 0000000..1c9156c Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_referenced_tx/00008.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_referenced_tx/00009.png b/tests/snapshots/nanos/test_send_ignis_referenced_tx/00009.png new file mode 100644 index 0000000..535bfc4 Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_referenced_tx/00009.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_tx/00000.png b/tests/snapshots/nanos/test_send_ignis_tx/00000.png new file mode 100644 index 0000000..92e0646 Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_tx/00000.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_tx/00001.png b/tests/snapshots/nanos/test_send_ignis_tx/00001.png new file mode 100644 index 0000000..dad25d6 Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_tx/00001.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_tx/00002.png b/tests/snapshots/nanos/test_send_ignis_tx/00002.png new file mode 100644 index 0000000..bd292e1 Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_tx/00002.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_tx/00003.png b/tests/snapshots/nanos/test_send_ignis_tx/00003.png new file mode 100644 index 0000000..e10b361 Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_tx/00003.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_tx/00004.png b/tests/snapshots/nanos/test_send_ignis_tx/00004.png new file mode 100644 index 0000000..1e49227 Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_tx/00004.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_tx/00005.png b/tests/snapshots/nanos/test_send_ignis_tx/00005.png new file mode 100644 index 0000000..71d40af Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_tx/00005.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_tx/00006.png b/tests/snapshots/nanos/test_send_ignis_tx/00006.png new file mode 100644 index 0000000..fce5fba Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_tx/00006.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_tx/00007.png b/tests/snapshots/nanos/test_send_ignis_tx/00007.png new file mode 100644 index 0000000..1c9156c Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_tx/00007.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_tx/00008.png b/tests/snapshots/nanos/test_send_ignis_tx/00008.png new file mode 100644 index 0000000..535bfc4 Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_tx/00008.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_tx_reject/00000.png b/tests/snapshots/nanos/test_send_ignis_tx_reject/00000.png new file mode 100644 index 0000000..92e0646 Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_tx_reject/00000.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_tx_reject/00001.png b/tests/snapshots/nanos/test_send_ignis_tx_reject/00001.png new file mode 100644 index 0000000..dad25d6 Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_tx_reject/00001.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_tx_reject/00002.png b/tests/snapshots/nanos/test_send_ignis_tx_reject/00002.png new file mode 100644 index 0000000..bd292e1 Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_tx_reject/00002.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_tx_reject/00003.png b/tests/snapshots/nanos/test_send_ignis_tx_reject/00003.png new file mode 100644 index 0000000..e10b361 Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_tx_reject/00003.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_tx_reject/00004.png b/tests/snapshots/nanos/test_send_ignis_tx_reject/00004.png new file mode 100644 index 0000000..1e49227 Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_tx_reject/00004.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_tx_reject/00005.png b/tests/snapshots/nanos/test_send_ignis_tx_reject/00005.png new file mode 100644 index 0000000..71d40af Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_tx_reject/00005.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_tx_reject/00006.png b/tests/snapshots/nanos/test_send_ignis_tx_reject/00006.png new file mode 100644 index 0000000..fce5fba Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_tx_reject/00006.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_tx_reject/00007.png b/tests/snapshots/nanos/test_send_ignis_tx_reject/00007.png new file mode 100644 index 0000000..1c9156c Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_tx_reject/00007.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_tx_reject/00008.png b/tests/snapshots/nanos/test_send_ignis_tx_reject/00008.png new file mode 100644 index 0000000..9c7e704 Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_tx_reject/00008.png differ diff --git a/tests/snapshots/nanos/test_send_ignis_tx_reject/00009.png b/tests/snapshots/nanos/test_send_ignis_tx_reject/00009.png new file mode 100644 index 0000000..535bfc4 Binary files /dev/null and b/tests/snapshots/nanos/test_send_ignis_tx_reject/00009.png differ diff --git a/tests/snapshots/nanos/test_show_address0/00000.png b/tests/snapshots/nanos/test_show_address0/00000.png new file mode 100644 index 0000000..92b3e3f Binary files /dev/null and b/tests/snapshots/nanos/test_show_address0/00000.png differ diff --git a/tests/snapshots/nanos/test_show_address0/00001.png b/tests/snapshots/nanos/test_show_address0/00001.png new file mode 100644 index 0000000..478bf8d Binary files /dev/null and b/tests/snapshots/nanos/test_show_address0/00001.png differ diff --git a/tests/snapshots/nanos/test_show_address0/00002.png b/tests/snapshots/nanos/test_show_address0/00002.png new file mode 100644 index 0000000..703ebcf Binary files /dev/null and b/tests/snapshots/nanos/test_show_address0/00002.png differ diff --git a/tests/snapshots/nanos/test_show_address0/00003.png b/tests/snapshots/nanos/test_show_address0/00003.png new file mode 100644 index 0000000..535bfc4 Binary files /dev/null and b/tests/snapshots/nanos/test_show_address0/00003.png differ diff --git a/tests/snapshots/nanos/test_show_address3/00000.png b/tests/snapshots/nanos/test_show_address3/00000.png new file mode 100644 index 0000000..130050f Binary files /dev/null and b/tests/snapshots/nanos/test_show_address3/00000.png differ diff --git a/tests/snapshots/nanos/test_show_address3/00001.png b/tests/snapshots/nanos/test_show_address3/00001.png new file mode 100644 index 0000000..ef2ba4a Binary files /dev/null and b/tests/snapshots/nanos/test_show_address3/00001.png differ diff --git a/tests/snapshots/nanos/test_show_address3/00002.png b/tests/snapshots/nanos/test_show_address3/00002.png new file mode 100644 index 0000000..703ebcf Binary files /dev/null and b/tests/snapshots/nanos/test_show_address3/00002.png differ diff --git a/tests/snapshots/nanos/test_show_address3/00003.png b/tests/snapshots/nanos/test_show_address3/00003.png new file mode 100644 index 0000000..535bfc4 Binary files /dev/null and b/tests/snapshots/nanos/test_show_address3/00003.png differ diff --git a/tests/snapshots/nanos/test_sign_token/00000.png b/tests/snapshots/nanos/test_sign_token/00000.png new file mode 100644 index 0000000..02a8b7a Binary files /dev/null and b/tests/snapshots/nanos/test_sign_token/00000.png differ diff --git a/tests/snapshots/nanos/test_sign_token/00001.png b/tests/snapshots/nanos/test_sign_token/00001.png new file mode 100644 index 0000000..134cae9 Binary files /dev/null and b/tests/snapshots/nanos/test_sign_token/00001.png differ diff --git a/tests/snapshots/nanos/test_sign_token/00002.png b/tests/snapshots/nanos/test_sign_token/00002.png new file mode 100644 index 0000000..535bfc4 Binary files /dev/null and b/tests/snapshots/nanos/test_sign_token/00002.png differ diff --git a/tests/snapshots/nanos/test_sign_token_reject_blind/00000.png b/tests/snapshots/nanos/test_sign_token_reject_blind/00000.png new file mode 100644 index 0000000..e2d0b1d Binary files /dev/null and b/tests/snapshots/nanos/test_sign_token_reject_blind/00000.png differ diff --git a/tests/snapshots/nanos/test_sign_token_reject_blind/00001.png b/tests/snapshots/nanos/test_sign_token_reject_blind/00001.png new file mode 100644 index 0000000..6d8deaa Binary files /dev/null and b/tests/snapshots/nanos/test_sign_token_reject_blind/00001.png differ diff --git a/tests/snapshots/nanos/test_sign_token_reject_blind/00002.png b/tests/snapshots/nanos/test_sign_token_reject_blind/00002.png new file mode 100644 index 0000000..535bfc4 Binary files /dev/null and b/tests/snapshots/nanos/test_sign_token_reject_blind/00002.png differ diff --git a/tests/snapshots/nanos/test_sign_token_reject_tx/00000.png b/tests/snapshots/nanos/test_sign_token_reject_tx/00000.png new file mode 100644 index 0000000..02a8b7a Binary files /dev/null and b/tests/snapshots/nanos/test_sign_token_reject_tx/00000.png differ diff --git a/tests/snapshots/nanos/test_sign_token_reject_tx/00001.png b/tests/snapshots/nanos/test_sign_token_reject_tx/00001.png new file mode 100644 index 0000000..134cae9 Binary files /dev/null and b/tests/snapshots/nanos/test_sign_token_reject_tx/00001.png differ diff --git a/tests/snapshots/nanos/test_sign_token_reject_tx/00002.png b/tests/snapshots/nanos/test_sign_token_reject_tx/00002.png new file mode 100644 index 0000000..9c7e704 Binary files /dev/null and b/tests/snapshots/nanos/test_sign_token_reject_tx/00002.png differ diff --git a/tests/snapshots/nanos/test_sign_token_reject_tx/00003.png b/tests/snapshots/nanos/test_sign_token_reject_tx/00003.png new file mode 100644 index 0000000..535bfc4 Binary files /dev/null and b/tests/snapshots/nanos/test_sign_token_reject_tx/00003.png differ diff --git a/tests/snapshots/nanosp/test_ardor_coin_exchange/00000.png b/tests/snapshots/nanosp/test_ardor_coin_exchange/00000.png new file mode 100644 index 0000000..4d95254 Binary files /dev/null and b/tests/snapshots/nanosp/test_ardor_coin_exchange/00000.png differ diff --git a/tests/snapshots/nanosp/test_ardor_coin_exchange/00001.png b/tests/snapshots/nanosp/test_ardor_coin_exchange/00001.png new file mode 100644 index 0000000..ebabab3 Binary files /dev/null and b/tests/snapshots/nanosp/test_ardor_coin_exchange/00001.png differ diff --git a/tests/snapshots/nanosp/test_ardor_coin_exchange/00002.png b/tests/snapshots/nanosp/test_ardor_coin_exchange/00002.png new file mode 100644 index 0000000..67974b7 Binary files /dev/null and b/tests/snapshots/nanosp/test_ardor_coin_exchange/00002.png differ diff --git a/tests/snapshots/nanosp/test_ardor_coin_exchange/00003.png b/tests/snapshots/nanosp/test_ardor_coin_exchange/00003.png new file mode 100644 index 0000000..1fa0f41 Binary files /dev/null and b/tests/snapshots/nanosp/test_ardor_coin_exchange/00003.png differ diff --git a/tests/snapshots/nanosp/test_ardor_coin_exchange/00004.png b/tests/snapshots/nanosp/test_ardor_coin_exchange/00004.png new file mode 100644 index 0000000..cb6e727 Binary files /dev/null and b/tests/snapshots/nanosp/test_ardor_coin_exchange/00004.png differ diff --git a/tests/snapshots/nanosp/test_ardor_coin_exchange/00005.png b/tests/snapshots/nanosp/test_ardor_coin_exchange/00005.png new file mode 100644 index 0000000..570ce28 Binary files /dev/null and b/tests/snapshots/nanosp/test_ardor_coin_exchange/00005.png differ diff --git a/tests/snapshots/nanosp/test_ardor_coin_exchange/00006.png b/tests/snapshots/nanosp/test_ardor_coin_exchange/00006.png new file mode 100644 index 0000000..7f4cb4b Binary files /dev/null and b/tests/snapshots/nanosp/test_ardor_coin_exchange/00006.png differ diff --git a/tests/snapshots/nanosp/test_asset_transfer/00000.png b/tests/snapshots/nanosp/test_asset_transfer/00000.png new file mode 100644 index 0000000..4d95254 Binary files /dev/null and b/tests/snapshots/nanosp/test_asset_transfer/00000.png differ diff --git a/tests/snapshots/nanosp/test_asset_transfer/00001.png b/tests/snapshots/nanosp/test_asset_transfer/00001.png new file mode 100644 index 0000000..7c7f273 Binary files /dev/null and b/tests/snapshots/nanosp/test_asset_transfer/00001.png differ diff --git a/tests/snapshots/nanosp/test_asset_transfer/00002.png b/tests/snapshots/nanosp/test_asset_transfer/00002.png new file mode 100644 index 0000000..a6d43b7 Binary files /dev/null and b/tests/snapshots/nanosp/test_asset_transfer/00002.png differ diff --git a/tests/snapshots/nanosp/test_asset_transfer/00003.png b/tests/snapshots/nanosp/test_asset_transfer/00003.png new file mode 100644 index 0000000..6ee7038 Binary files /dev/null and b/tests/snapshots/nanosp/test_asset_transfer/00003.png differ diff --git a/tests/snapshots/nanosp/test_asset_transfer/00004.png b/tests/snapshots/nanosp/test_asset_transfer/00004.png new file mode 100644 index 0000000..3484bf8 Binary files /dev/null and b/tests/snapshots/nanosp/test_asset_transfer/00004.png differ diff --git a/tests/snapshots/nanosp/test_asset_transfer/00005.png b/tests/snapshots/nanosp/test_asset_transfer/00005.png new file mode 100644 index 0000000..eb2612a Binary files /dev/null and b/tests/snapshots/nanosp/test_asset_transfer/00005.png differ diff --git a/tests/snapshots/nanosp/test_asset_transfer/00006.png b/tests/snapshots/nanosp/test_asset_transfer/00006.png new file mode 100644 index 0000000..570ce28 Binary files /dev/null and b/tests/snapshots/nanosp/test_asset_transfer/00006.png differ diff --git a/tests/snapshots/nanosp/test_asset_transfer/00007.png b/tests/snapshots/nanosp/test_asset_transfer/00007.png new file mode 100644 index 0000000..7f4cb4b Binary files /dev/null and b/tests/snapshots/nanosp/test_asset_transfer/00007.png differ diff --git a/tests/snapshots/nanosp/test_coin_exchange/00000.png b/tests/snapshots/nanosp/test_coin_exchange/00000.png new file mode 100644 index 0000000..4d95254 Binary files /dev/null and b/tests/snapshots/nanosp/test_coin_exchange/00000.png differ diff --git a/tests/snapshots/nanosp/test_coin_exchange/00001.png b/tests/snapshots/nanosp/test_coin_exchange/00001.png new file mode 100644 index 0000000..c72b188 Binary files /dev/null and b/tests/snapshots/nanosp/test_coin_exchange/00001.png differ diff --git a/tests/snapshots/nanosp/test_coin_exchange/00002.png b/tests/snapshots/nanosp/test_coin_exchange/00002.png new file mode 100644 index 0000000..4c34f8d Binary files /dev/null and b/tests/snapshots/nanosp/test_coin_exchange/00002.png differ diff --git a/tests/snapshots/nanosp/test_coin_exchange/00003.png b/tests/snapshots/nanosp/test_coin_exchange/00003.png new file mode 100644 index 0000000..a4fbf13 Binary files /dev/null and b/tests/snapshots/nanosp/test_coin_exchange/00003.png differ diff --git a/tests/snapshots/nanosp/test_coin_exchange/00004.png b/tests/snapshots/nanosp/test_coin_exchange/00004.png new file mode 100644 index 0000000..eb2612a Binary files /dev/null and b/tests/snapshots/nanosp/test_coin_exchange/00004.png differ diff --git a/tests/snapshots/nanosp/test_coin_exchange/00005.png b/tests/snapshots/nanosp/test_coin_exchange/00005.png new file mode 100644 index 0000000..570ce28 Binary files /dev/null and b/tests/snapshots/nanosp/test_coin_exchange/00005.png differ diff --git a/tests/snapshots/nanosp/test_coin_exchange/00006.png b/tests/snapshots/nanosp/test_coin_exchange/00006.png new file mode 100644 index 0000000..7f4cb4b Binary files /dev/null and b/tests/snapshots/nanosp/test_coin_exchange/00006.png differ diff --git a/tests/snapshots/nanosp/test_place_asset_exchange_order/00000.png b/tests/snapshots/nanosp/test_place_asset_exchange_order/00000.png new file mode 100644 index 0000000..4d95254 Binary files /dev/null and b/tests/snapshots/nanosp/test_place_asset_exchange_order/00000.png differ diff --git a/tests/snapshots/nanosp/test_place_asset_exchange_order/00001.png b/tests/snapshots/nanosp/test_place_asset_exchange_order/00001.png new file mode 100644 index 0000000..63e940a Binary files /dev/null and b/tests/snapshots/nanosp/test_place_asset_exchange_order/00001.png differ diff --git a/tests/snapshots/nanosp/test_place_asset_exchange_order/00002.png b/tests/snapshots/nanosp/test_place_asset_exchange_order/00002.png new file mode 100644 index 0000000..a993863 Binary files /dev/null and b/tests/snapshots/nanosp/test_place_asset_exchange_order/00002.png differ diff --git a/tests/snapshots/nanosp/test_place_asset_exchange_order/00003.png b/tests/snapshots/nanosp/test_place_asset_exchange_order/00003.png new file mode 100644 index 0000000..4bdda37 Binary files /dev/null and b/tests/snapshots/nanosp/test_place_asset_exchange_order/00003.png differ diff --git a/tests/snapshots/nanosp/test_place_asset_exchange_order/00004.png b/tests/snapshots/nanosp/test_place_asset_exchange_order/00004.png new file mode 100644 index 0000000..4769f29 Binary files /dev/null and b/tests/snapshots/nanosp/test_place_asset_exchange_order/00004.png differ diff --git a/tests/snapshots/nanosp/test_place_asset_exchange_order/00005.png b/tests/snapshots/nanosp/test_place_asset_exchange_order/00005.png new file mode 100644 index 0000000..e66f7ff Binary files /dev/null and b/tests/snapshots/nanosp/test_place_asset_exchange_order/00005.png differ diff --git a/tests/snapshots/nanosp/test_place_asset_exchange_order/00006.png b/tests/snapshots/nanosp/test_place_asset_exchange_order/00006.png new file mode 100644 index 0000000..570ce28 Binary files /dev/null and b/tests/snapshots/nanosp/test_place_asset_exchange_order/00006.png differ diff --git a/tests/snapshots/nanosp/test_place_asset_exchange_order/00007.png b/tests/snapshots/nanosp/test_place_asset_exchange_order/00007.png new file mode 100644 index 0000000..7f4cb4b Binary files /dev/null and b/tests/snapshots/nanosp/test_place_asset_exchange_order/00007.png differ diff --git a/tests/snapshots/nanosp/test_send_ardr/00000.png b/tests/snapshots/nanosp/test_send_ardr/00000.png new file mode 100644 index 0000000..4d95254 Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ardr/00000.png differ diff --git a/tests/snapshots/nanosp/test_send_ardr/00001.png b/tests/snapshots/nanosp/test_send_ardr/00001.png new file mode 100644 index 0000000..6cea68b Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ardr/00001.png differ diff --git a/tests/snapshots/nanosp/test_send_ardr/00002.png b/tests/snapshots/nanosp/test_send_ardr/00002.png new file mode 100644 index 0000000..d7a907d Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ardr/00002.png differ diff --git a/tests/snapshots/nanosp/test_send_ardr/00003.png b/tests/snapshots/nanosp/test_send_ardr/00003.png new file mode 100644 index 0000000..f05d5e4 Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ardr/00003.png differ diff --git a/tests/snapshots/nanosp/test_send_ardr/00004.png b/tests/snapshots/nanosp/test_send_ardr/00004.png new file mode 100644 index 0000000..ff0c5b0 Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ardr/00004.png differ diff --git a/tests/snapshots/nanosp/test_send_ardr/00005.png b/tests/snapshots/nanosp/test_send_ardr/00005.png new file mode 100644 index 0000000..570ce28 Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ardr/00005.png differ diff --git a/tests/snapshots/nanosp/test_send_ardr/00006.png b/tests/snapshots/nanosp/test_send_ardr/00006.png new file mode 100644 index 0000000..7f4cb4b Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ardr/00006.png differ diff --git a/tests/snapshots/nanosp/test_send_ignis_4_attachments/00000.png b/tests/snapshots/nanosp/test_send_ignis_4_attachments/00000.png new file mode 100644 index 0000000..4d95254 Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ignis_4_attachments/00000.png differ diff --git a/tests/snapshots/nanosp/test_send_ignis_4_attachments/00001.png b/tests/snapshots/nanosp/test_send_ignis_4_attachments/00001.png new file mode 100644 index 0000000..2134773 Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ignis_4_attachments/00001.png differ diff --git a/tests/snapshots/nanosp/test_send_ignis_4_attachments/00002.png b/tests/snapshots/nanosp/test_send_ignis_4_attachments/00002.png new file mode 100644 index 0000000..4c8fee2 Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ignis_4_attachments/00002.png differ diff --git a/tests/snapshots/nanosp/test_send_ignis_4_attachments/00003.png b/tests/snapshots/nanosp/test_send_ignis_4_attachments/00003.png new file mode 100644 index 0000000..0af81e5 Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ignis_4_attachments/00003.png differ diff --git a/tests/snapshots/nanosp/test_send_ignis_4_attachments/00004.png b/tests/snapshots/nanosp/test_send_ignis_4_attachments/00004.png new file mode 100644 index 0000000..ef6d716 Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ignis_4_attachments/00004.png differ diff --git a/tests/snapshots/nanosp/test_send_ignis_4_attachments/00005.png b/tests/snapshots/nanosp/test_send_ignis_4_attachments/00005.png new file mode 100644 index 0000000..46a8b4e Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ignis_4_attachments/00005.png differ diff --git a/tests/snapshots/nanosp/test_send_ignis_4_attachments/00006.png b/tests/snapshots/nanosp/test_send_ignis_4_attachments/00006.png new file mode 100644 index 0000000..54758bd Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ignis_4_attachments/00006.png differ diff --git a/tests/snapshots/nanosp/test_send_ignis_4_attachments/00007.png b/tests/snapshots/nanosp/test_send_ignis_4_attachments/00007.png new file mode 100644 index 0000000..d76c7df Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ignis_4_attachments/00007.png differ diff --git a/tests/snapshots/nanosp/test_send_ignis_4_attachments/00008.png b/tests/snapshots/nanosp/test_send_ignis_4_attachments/00008.png new file mode 100644 index 0000000..570ce28 Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ignis_4_attachments/00008.png differ diff --git a/tests/snapshots/nanosp/test_send_ignis_4_attachments/00009.png b/tests/snapshots/nanosp/test_send_ignis_4_attachments/00009.png new file mode 100644 index 0000000..7f4cb4b Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ignis_4_attachments/00009.png differ diff --git a/tests/snapshots/nanosp/test_send_ignis_blind_accept/00000.png b/tests/snapshots/nanosp/test_send_ignis_blind_accept/00000.png new file mode 100644 index 0000000..4d95254 Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ignis_blind_accept/00000.png differ diff --git a/tests/snapshots/nanosp/test_send_ignis_blind_accept/00001.png b/tests/snapshots/nanosp/test_send_ignis_blind_accept/00001.png new file mode 100644 index 0000000..2134773 Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ignis_blind_accept/00001.png differ diff --git a/tests/snapshots/nanosp/test_send_ignis_blind_accept/00002.png b/tests/snapshots/nanosp/test_send_ignis_blind_accept/00002.png new file mode 100644 index 0000000..4c8fee2 Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ignis_blind_accept/00002.png differ diff --git a/tests/snapshots/nanosp/test_send_ignis_blind_accept/00003.png b/tests/snapshots/nanosp/test_send_ignis_blind_accept/00003.png new file mode 100644 index 0000000..803b430 Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ignis_blind_accept/00003.png differ diff --git a/tests/snapshots/nanosp/test_send_ignis_blind_accept/00004.png b/tests/snapshots/nanosp/test_send_ignis_blind_accept/00004.png new file mode 100644 index 0000000..8fcb909 Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ignis_blind_accept/00004.png differ diff --git a/tests/snapshots/nanosp/test_send_ignis_blind_accept/00005.png b/tests/snapshots/nanosp/test_send_ignis_blind_accept/00005.png new file mode 100644 index 0000000..5aa015b Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ignis_blind_accept/00005.png differ diff --git a/tests/snapshots/nanosp/test_send_ignis_blind_accept/00006.png b/tests/snapshots/nanosp/test_send_ignis_blind_accept/00006.png new file mode 100644 index 0000000..a1455d0 Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ignis_blind_accept/00006.png differ diff --git a/tests/snapshots/nanosp/test_send_ignis_blind_accept/00007.png b/tests/snapshots/nanosp/test_send_ignis_blind_accept/00007.png new file mode 100644 index 0000000..570ce28 Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ignis_blind_accept/00007.png differ diff --git a/tests/snapshots/nanosp/test_send_ignis_blind_accept/00008.png b/tests/snapshots/nanosp/test_send_ignis_blind_accept/00008.png new file mode 100644 index 0000000..7f4cb4b Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ignis_blind_accept/00008.png differ diff --git a/tests/snapshots/nanosp/test_send_ignis_blind_reject/00000.png b/tests/snapshots/nanosp/test_send_ignis_blind_reject/00000.png new file mode 100644 index 0000000..e005703 Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ignis_blind_reject/00000.png differ diff --git a/tests/snapshots/nanosp/test_send_ignis_blind_reject/00001.png b/tests/snapshots/nanosp/test_send_ignis_blind_reject/00001.png new file mode 100644 index 0000000..7f4cb4b Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ignis_blind_reject/00001.png differ diff --git a/tests/snapshots/nanosp/test_send_ignis_blind_reject_tx/00000.png b/tests/snapshots/nanosp/test_send_ignis_blind_reject_tx/00000.png new file mode 100644 index 0000000..4d95254 Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ignis_blind_reject_tx/00000.png differ diff --git a/tests/snapshots/nanosp/test_send_ignis_blind_reject_tx/00001.png b/tests/snapshots/nanosp/test_send_ignis_blind_reject_tx/00001.png new file mode 100644 index 0000000..2134773 Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ignis_blind_reject_tx/00001.png differ diff --git a/tests/snapshots/nanosp/test_send_ignis_blind_reject_tx/00002.png b/tests/snapshots/nanosp/test_send_ignis_blind_reject_tx/00002.png new file mode 100644 index 0000000..4c8fee2 Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ignis_blind_reject_tx/00002.png differ diff --git a/tests/snapshots/nanosp/test_send_ignis_blind_reject_tx/00003.png b/tests/snapshots/nanosp/test_send_ignis_blind_reject_tx/00003.png new file mode 100644 index 0000000..803b430 Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ignis_blind_reject_tx/00003.png differ diff --git a/tests/snapshots/nanosp/test_send_ignis_blind_reject_tx/00004.png b/tests/snapshots/nanosp/test_send_ignis_blind_reject_tx/00004.png new file mode 100644 index 0000000..8fcb909 Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ignis_blind_reject_tx/00004.png differ diff --git a/tests/snapshots/nanosp/test_send_ignis_blind_reject_tx/00005.png b/tests/snapshots/nanosp/test_send_ignis_blind_reject_tx/00005.png new file mode 100644 index 0000000..5aa015b Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ignis_blind_reject_tx/00005.png differ diff --git a/tests/snapshots/nanosp/test_send_ignis_blind_reject_tx/00006.png b/tests/snapshots/nanosp/test_send_ignis_blind_reject_tx/00006.png new file mode 100644 index 0000000..a1455d0 Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ignis_blind_reject_tx/00006.png differ diff --git a/tests/snapshots/nanosp/test_send_ignis_blind_reject_tx/00007.png b/tests/snapshots/nanosp/test_send_ignis_blind_reject_tx/00007.png new file mode 100644 index 0000000..570ce28 Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ignis_blind_reject_tx/00007.png differ diff --git a/tests/snapshots/nanosp/test_send_ignis_blind_reject_tx/00008.png b/tests/snapshots/nanosp/test_send_ignis_blind_reject_tx/00008.png new file mode 100644 index 0000000..c922246 Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ignis_blind_reject_tx/00008.png differ diff --git a/tests/snapshots/nanosp/test_send_ignis_blind_reject_tx/00009.png b/tests/snapshots/nanosp/test_send_ignis_blind_reject_tx/00009.png new file mode 100644 index 0000000..7f4cb4b Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ignis_blind_reject_tx/00009.png differ diff --git a/tests/snapshots/nanosp/test_send_ignis_referenced_tx/00000.png b/tests/snapshots/nanosp/test_send_ignis_referenced_tx/00000.png new file mode 100644 index 0000000..4d95254 Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ignis_referenced_tx/00000.png differ diff --git a/tests/snapshots/nanosp/test_send_ignis_referenced_tx/00001.png b/tests/snapshots/nanosp/test_send_ignis_referenced_tx/00001.png new file mode 100644 index 0000000..2134773 Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ignis_referenced_tx/00001.png differ diff --git a/tests/snapshots/nanosp/test_send_ignis_referenced_tx/00002.png b/tests/snapshots/nanosp/test_send_ignis_referenced_tx/00002.png new file mode 100644 index 0000000..4c8fee2 Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ignis_referenced_tx/00002.png differ diff --git a/tests/snapshots/nanosp/test_send_ignis_referenced_tx/00003.png b/tests/snapshots/nanosp/test_send_ignis_referenced_tx/00003.png new file mode 100644 index 0000000..b45c880 Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ignis_referenced_tx/00003.png differ diff --git a/tests/snapshots/nanosp/test_send_ignis_referenced_tx/00004.png b/tests/snapshots/nanosp/test_send_ignis_referenced_tx/00004.png new file mode 100644 index 0000000..8fcb909 Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ignis_referenced_tx/00004.png differ diff --git a/tests/snapshots/nanosp/test_send_ignis_referenced_tx/00005.png b/tests/snapshots/nanosp/test_send_ignis_referenced_tx/00005.png new file mode 100644 index 0000000..5f11d43 Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ignis_referenced_tx/00005.png differ diff --git a/tests/snapshots/nanosp/test_send_ignis_referenced_tx/00006.png b/tests/snapshots/nanosp/test_send_ignis_referenced_tx/00006.png new file mode 100644 index 0000000..570ce28 Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ignis_referenced_tx/00006.png differ diff --git a/tests/snapshots/nanosp/test_send_ignis_referenced_tx/00007.png b/tests/snapshots/nanosp/test_send_ignis_referenced_tx/00007.png new file mode 100644 index 0000000..7f4cb4b Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ignis_referenced_tx/00007.png differ diff --git a/tests/snapshots/nanosp/test_send_ignis_tx/00000.png b/tests/snapshots/nanosp/test_send_ignis_tx/00000.png new file mode 100644 index 0000000..4d95254 Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ignis_tx/00000.png differ diff --git a/tests/snapshots/nanosp/test_send_ignis_tx/00001.png b/tests/snapshots/nanosp/test_send_ignis_tx/00001.png new file mode 100644 index 0000000..4c8fee2 Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ignis_tx/00001.png differ diff --git a/tests/snapshots/nanosp/test_send_ignis_tx/00002.png b/tests/snapshots/nanosp/test_send_ignis_tx/00002.png new file mode 100644 index 0000000..34fa3d0 Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ignis_tx/00002.png differ diff --git a/tests/snapshots/nanosp/test_send_ignis_tx/00003.png b/tests/snapshots/nanosp/test_send_ignis_tx/00003.png new file mode 100644 index 0000000..3484bf8 Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ignis_tx/00003.png differ diff --git a/tests/snapshots/nanosp/test_send_ignis_tx/00004.png b/tests/snapshots/nanosp/test_send_ignis_tx/00004.png new file mode 100644 index 0000000..eb2612a Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ignis_tx/00004.png differ diff --git a/tests/snapshots/nanosp/test_send_ignis_tx/00005.png b/tests/snapshots/nanosp/test_send_ignis_tx/00005.png new file mode 100644 index 0000000..570ce28 Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ignis_tx/00005.png differ diff --git a/tests/snapshots/nanosp/test_send_ignis_tx/00006.png b/tests/snapshots/nanosp/test_send_ignis_tx/00006.png new file mode 100644 index 0000000..7f4cb4b Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ignis_tx/00006.png differ diff --git a/tests/snapshots/nanosp/test_send_ignis_tx_reject/00000.png b/tests/snapshots/nanosp/test_send_ignis_tx_reject/00000.png new file mode 100644 index 0000000..4d95254 Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ignis_tx_reject/00000.png differ diff --git a/tests/snapshots/nanosp/test_send_ignis_tx_reject/00001.png b/tests/snapshots/nanosp/test_send_ignis_tx_reject/00001.png new file mode 100644 index 0000000..4c8fee2 Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ignis_tx_reject/00001.png differ diff --git a/tests/snapshots/nanosp/test_send_ignis_tx_reject/00002.png b/tests/snapshots/nanosp/test_send_ignis_tx_reject/00002.png new file mode 100644 index 0000000..34fa3d0 Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ignis_tx_reject/00002.png differ diff --git a/tests/snapshots/nanosp/test_send_ignis_tx_reject/00003.png b/tests/snapshots/nanosp/test_send_ignis_tx_reject/00003.png new file mode 100644 index 0000000..3484bf8 Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ignis_tx_reject/00003.png differ diff --git a/tests/snapshots/nanosp/test_send_ignis_tx_reject/00004.png b/tests/snapshots/nanosp/test_send_ignis_tx_reject/00004.png new file mode 100644 index 0000000..eb2612a Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ignis_tx_reject/00004.png differ diff --git a/tests/snapshots/nanosp/test_send_ignis_tx_reject/00005.png b/tests/snapshots/nanosp/test_send_ignis_tx_reject/00005.png new file mode 100644 index 0000000..570ce28 Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ignis_tx_reject/00005.png differ diff --git a/tests/snapshots/nanosp/test_send_ignis_tx_reject/00006.png b/tests/snapshots/nanosp/test_send_ignis_tx_reject/00006.png new file mode 100644 index 0000000..c922246 Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ignis_tx_reject/00006.png differ diff --git a/tests/snapshots/nanosp/test_send_ignis_tx_reject/00007.png b/tests/snapshots/nanosp/test_send_ignis_tx_reject/00007.png new file mode 100644 index 0000000..7f4cb4b Binary files /dev/null and b/tests/snapshots/nanosp/test_send_ignis_tx_reject/00007.png differ diff --git a/tests/snapshots/nanosp/test_show_address0/00000.png b/tests/snapshots/nanosp/test_show_address0/00000.png new file mode 100644 index 0000000..ac9f95c Binary files /dev/null and b/tests/snapshots/nanosp/test_show_address0/00000.png differ diff --git a/tests/snapshots/nanosp/test_show_address0/00001.png b/tests/snapshots/nanosp/test_show_address0/00001.png new file mode 100644 index 0000000..884b9be Binary files /dev/null and b/tests/snapshots/nanosp/test_show_address0/00001.png differ diff --git a/tests/snapshots/nanosp/test_show_address0/00002.png b/tests/snapshots/nanosp/test_show_address0/00002.png new file mode 100644 index 0000000..7f4cb4b Binary files /dev/null and b/tests/snapshots/nanosp/test_show_address0/00002.png differ diff --git a/tests/snapshots/nanosp/test_show_address3/00000.png b/tests/snapshots/nanosp/test_show_address3/00000.png new file mode 100644 index 0000000..03a72c4 Binary files /dev/null and b/tests/snapshots/nanosp/test_show_address3/00000.png differ diff --git a/tests/snapshots/nanosp/test_show_address3/00001.png b/tests/snapshots/nanosp/test_show_address3/00001.png new file mode 100644 index 0000000..884b9be Binary files /dev/null and b/tests/snapshots/nanosp/test_show_address3/00001.png differ diff --git a/tests/snapshots/nanosp/test_show_address3/00002.png b/tests/snapshots/nanosp/test_show_address3/00002.png new file mode 100644 index 0000000..7f4cb4b Binary files /dev/null and b/tests/snapshots/nanosp/test_show_address3/00002.png differ diff --git a/tests/snapshots/nanosp/test_sign_token/00000.png b/tests/snapshots/nanosp/test_sign_token/00000.png new file mode 100644 index 0000000..a328c45 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_token/00000.png differ diff --git a/tests/snapshots/nanosp/test_sign_token/00001.png b/tests/snapshots/nanosp/test_sign_token/00001.png new file mode 100644 index 0000000..af714ca Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_token/00001.png differ diff --git a/tests/snapshots/nanosp/test_sign_token/00002.png b/tests/snapshots/nanosp/test_sign_token/00002.png new file mode 100644 index 0000000..7f4cb4b Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_token/00002.png differ diff --git a/tests/snapshots/nanosp/test_sign_token_reject_blind/00000.png b/tests/snapshots/nanosp/test_sign_token_reject_blind/00000.png new file mode 100644 index 0000000..e005703 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_token_reject_blind/00000.png differ diff --git a/tests/snapshots/nanosp/test_sign_token_reject_blind/00001.png b/tests/snapshots/nanosp/test_sign_token_reject_blind/00001.png new file mode 100644 index 0000000..7f4cb4b Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_token_reject_blind/00001.png differ diff --git a/tests/snapshots/nanosp/test_sign_token_reject_tx/00000.png b/tests/snapshots/nanosp/test_sign_token_reject_tx/00000.png new file mode 100644 index 0000000..a328c45 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_token_reject_tx/00000.png differ diff --git a/tests/snapshots/nanosp/test_sign_token_reject_tx/00001.png b/tests/snapshots/nanosp/test_sign_token_reject_tx/00001.png new file mode 100644 index 0000000..af714ca Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_token_reject_tx/00001.png differ diff --git a/tests/snapshots/nanosp/test_sign_token_reject_tx/00002.png b/tests/snapshots/nanosp/test_sign_token_reject_tx/00002.png new file mode 100644 index 0000000..c922246 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_token_reject_tx/00002.png differ diff --git a/tests/snapshots/nanosp/test_sign_token_reject_tx/00003.png b/tests/snapshots/nanosp/test_sign_token_reject_tx/00003.png new file mode 100644 index 0000000..7f4cb4b Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_token_reject_tx/00003.png differ diff --git a/tests/snapshots/nanox/test_ardor_coin_exchange/00000.png b/tests/snapshots/nanox/test_ardor_coin_exchange/00000.png new file mode 100644 index 0000000..4d95254 Binary files /dev/null and b/tests/snapshots/nanox/test_ardor_coin_exchange/00000.png differ diff --git a/tests/snapshots/nanox/test_ardor_coin_exchange/00001.png b/tests/snapshots/nanox/test_ardor_coin_exchange/00001.png new file mode 100644 index 0000000..ebabab3 Binary files /dev/null and b/tests/snapshots/nanox/test_ardor_coin_exchange/00001.png differ diff --git a/tests/snapshots/nanox/test_ardor_coin_exchange/00002.png b/tests/snapshots/nanox/test_ardor_coin_exchange/00002.png new file mode 100644 index 0000000..67974b7 Binary files /dev/null and b/tests/snapshots/nanox/test_ardor_coin_exchange/00002.png differ diff --git a/tests/snapshots/nanox/test_ardor_coin_exchange/00003.png b/tests/snapshots/nanox/test_ardor_coin_exchange/00003.png new file mode 100644 index 0000000..fe7d00c Binary files /dev/null and b/tests/snapshots/nanox/test_ardor_coin_exchange/00003.png differ diff --git a/tests/snapshots/nanox/test_ardor_coin_exchange/00004.png b/tests/snapshots/nanox/test_ardor_coin_exchange/00004.png new file mode 100644 index 0000000..cb6e727 Binary files /dev/null and b/tests/snapshots/nanox/test_ardor_coin_exchange/00004.png differ diff --git a/tests/snapshots/nanox/test_ardor_coin_exchange/00005.png b/tests/snapshots/nanox/test_ardor_coin_exchange/00005.png new file mode 100644 index 0000000..570ce28 Binary files /dev/null and b/tests/snapshots/nanox/test_ardor_coin_exchange/00005.png differ diff --git a/tests/snapshots/nanox/test_ardor_coin_exchange/00006.png b/tests/snapshots/nanox/test_ardor_coin_exchange/00006.png new file mode 100644 index 0000000..b9f1953 Binary files /dev/null and b/tests/snapshots/nanox/test_ardor_coin_exchange/00006.png differ diff --git a/tests/snapshots/nanox/test_asset_transfer/00000.png b/tests/snapshots/nanox/test_asset_transfer/00000.png new file mode 100644 index 0000000..4d95254 Binary files /dev/null and b/tests/snapshots/nanox/test_asset_transfer/00000.png differ diff --git a/tests/snapshots/nanox/test_asset_transfer/00001.png b/tests/snapshots/nanox/test_asset_transfer/00001.png new file mode 100644 index 0000000..7c7f273 Binary files /dev/null and b/tests/snapshots/nanox/test_asset_transfer/00001.png differ diff --git a/tests/snapshots/nanox/test_asset_transfer/00002.png b/tests/snapshots/nanox/test_asset_transfer/00002.png new file mode 100644 index 0000000..6870161 Binary files /dev/null and b/tests/snapshots/nanox/test_asset_transfer/00002.png differ diff --git a/tests/snapshots/nanox/test_asset_transfer/00003.png b/tests/snapshots/nanox/test_asset_transfer/00003.png new file mode 100644 index 0000000..6ee7038 Binary files /dev/null and b/tests/snapshots/nanox/test_asset_transfer/00003.png differ diff --git a/tests/snapshots/nanox/test_asset_transfer/00004.png b/tests/snapshots/nanox/test_asset_transfer/00004.png new file mode 100644 index 0000000..3484bf8 Binary files /dev/null and b/tests/snapshots/nanox/test_asset_transfer/00004.png differ diff --git a/tests/snapshots/nanox/test_asset_transfer/00005.png b/tests/snapshots/nanox/test_asset_transfer/00005.png new file mode 100644 index 0000000..eb2612a Binary files /dev/null and b/tests/snapshots/nanox/test_asset_transfer/00005.png differ diff --git a/tests/snapshots/nanox/test_asset_transfer/00006.png b/tests/snapshots/nanox/test_asset_transfer/00006.png new file mode 100644 index 0000000..570ce28 Binary files /dev/null and b/tests/snapshots/nanox/test_asset_transfer/00006.png differ diff --git a/tests/snapshots/nanox/test_asset_transfer/00007.png b/tests/snapshots/nanox/test_asset_transfer/00007.png new file mode 100644 index 0000000..b9f1953 Binary files /dev/null and b/tests/snapshots/nanox/test_asset_transfer/00007.png differ diff --git a/tests/snapshots/nanox/test_coin_exchange/00000.png b/tests/snapshots/nanox/test_coin_exchange/00000.png new file mode 100644 index 0000000..4d95254 Binary files /dev/null and b/tests/snapshots/nanox/test_coin_exchange/00000.png differ diff --git a/tests/snapshots/nanox/test_coin_exchange/00001.png b/tests/snapshots/nanox/test_coin_exchange/00001.png new file mode 100644 index 0000000..c72b188 Binary files /dev/null and b/tests/snapshots/nanox/test_coin_exchange/00001.png differ diff --git a/tests/snapshots/nanox/test_coin_exchange/00002.png b/tests/snapshots/nanox/test_coin_exchange/00002.png new file mode 100644 index 0000000..4c34f8d Binary files /dev/null and b/tests/snapshots/nanox/test_coin_exchange/00002.png differ diff --git a/tests/snapshots/nanox/test_coin_exchange/00003.png b/tests/snapshots/nanox/test_coin_exchange/00003.png new file mode 100644 index 0000000..7b7b930 Binary files /dev/null and b/tests/snapshots/nanox/test_coin_exchange/00003.png differ diff --git a/tests/snapshots/nanox/test_coin_exchange/00004.png b/tests/snapshots/nanox/test_coin_exchange/00004.png new file mode 100644 index 0000000..eb2612a Binary files /dev/null and b/tests/snapshots/nanox/test_coin_exchange/00004.png differ diff --git a/tests/snapshots/nanox/test_coin_exchange/00005.png b/tests/snapshots/nanox/test_coin_exchange/00005.png new file mode 100644 index 0000000..570ce28 Binary files /dev/null and b/tests/snapshots/nanox/test_coin_exchange/00005.png differ diff --git a/tests/snapshots/nanox/test_coin_exchange/00006.png b/tests/snapshots/nanox/test_coin_exchange/00006.png new file mode 100644 index 0000000..b9f1953 Binary files /dev/null and b/tests/snapshots/nanox/test_coin_exchange/00006.png differ diff --git a/tests/snapshots/nanox/test_place_asset_exchange_order/00000.png b/tests/snapshots/nanox/test_place_asset_exchange_order/00000.png new file mode 100644 index 0000000..4d95254 Binary files /dev/null and b/tests/snapshots/nanox/test_place_asset_exchange_order/00000.png differ diff --git a/tests/snapshots/nanox/test_place_asset_exchange_order/00001.png b/tests/snapshots/nanox/test_place_asset_exchange_order/00001.png new file mode 100644 index 0000000..63e940a Binary files /dev/null and b/tests/snapshots/nanox/test_place_asset_exchange_order/00001.png differ diff --git a/tests/snapshots/nanox/test_place_asset_exchange_order/00002.png b/tests/snapshots/nanox/test_place_asset_exchange_order/00002.png new file mode 100644 index 0000000..3ec5766 Binary files /dev/null and b/tests/snapshots/nanox/test_place_asset_exchange_order/00002.png differ diff --git a/tests/snapshots/nanox/test_place_asset_exchange_order/00003.png b/tests/snapshots/nanox/test_place_asset_exchange_order/00003.png new file mode 100644 index 0000000..4bdda37 Binary files /dev/null and b/tests/snapshots/nanox/test_place_asset_exchange_order/00003.png differ diff --git a/tests/snapshots/nanox/test_place_asset_exchange_order/00004.png b/tests/snapshots/nanox/test_place_asset_exchange_order/00004.png new file mode 100644 index 0000000..4769f29 Binary files /dev/null and b/tests/snapshots/nanox/test_place_asset_exchange_order/00004.png differ diff --git a/tests/snapshots/nanox/test_place_asset_exchange_order/00005.png b/tests/snapshots/nanox/test_place_asset_exchange_order/00005.png new file mode 100644 index 0000000..e66f7ff Binary files /dev/null and b/tests/snapshots/nanox/test_place_asset_exchange_order/00005.png differ diff --git a/tests/snapshots/nanox/test_place_asset_exchange_order/00006.png b/tests/snapshots/nanox/test_place_asset_exchange_order/00006.png new file mode 100644 index 0000000..570ce28 Binary files /dev/null and b/tests/snapshots/nanox/test_place_asset_exchange_order/00006.png differ diff --git a/tests/snapshots/nanox/test_place_asset_exchange_order/00007.png b/tests/snapshots/nanox/test_place_asset_exchange_order/00007.png new file mode 100644 index 0000000..b9f1953 Binary files /dev/null and b/tests/snapshots/nanox/test_place_asset_exchange_order/00007.png differ diff --git a/tests/snapshots/nanox/test_send_ardr/00000.png b/tests/snapshots/nanox/test_send_ardr/00000.png new file mode 100644 index 0000000..4d95254 Binary files /dev/null and b/tests/snapshots/nanox/test_send_ardr/00000.png differ diff --git a/tests/snapshots/nanox/test_send_ardr/00001.png b/tests/snapshots/nanox/test_send_ardr/00001.png new file mode 100644 index 0000000..6cea68b Binary files /dev/null and b/tests/snapshots/nanox/test_send_ardr/00001.png differ diff --git a/tests/snapshots/nanox/test_send_ardr/00002.png b/tests/snapshots/nanox/test_send_ardr/00002.png new file mode 100644 index 0000000..d7a907d Binary files /dev/null and b/tests/snapshots/nanox/test_send_ardr/00002.png differ diff --git a/tests/snapshots/nanox/test_send_ardr/00003.png b/tests/snapshots/nanox/test_send_ardr/00003.png new file mode 100644 index 0000000..ccae02b Binary files /dev/null and b/tests/snapshots/nanox/test_send_ardr/00003.png differ diff --git a/tests/snapshots/nanox/test_send_ardr/00004.png b/tests/snapshots/nanox/test_send_ardr/00004.png new file mode 100644 index 0000000..ff0c5b0 Binary files /dev/null and b/tests/snapshots/nanox/test_send_ardr/00004.png differ diff --git a/tests/snapshots/nanox/test_send_ardr/00005.png b/tests/snapshots/nanox/test_send_ardr/00005.png new file mode 100644 index 0000000..570ce28 Binary files /dev/null and b/tests/snapshots/nanox/test_send_ardr/00005.png differ diff --git a/tests/snapshots/nanox/test_send_ardr/00006.png b/tests/snapshots/nanox/test_send_ardr/00006.png new file mode 100644 index 0000000..b9f1953 Binary files /dev/null and b/tests/snapshots/nanox/test_send_ardr/00006.png differ diff --git a/tests/snapshots/nanox/test_send_ignis_4_attachments/00000.png b/tests/snapshots/nanox/test_send_ignis_4_attachments/00000.png new file mode 100644 index 0000000..4d95254 Binary files /dev/null and b/tests/snapshots/nanox/test_send_ignis_4_attachments/00000.png differ diff --git a/tests/snapshots/nanox/test_send_ignis_4_attachments/00001.png b/tests/snapshots/nanox/test_send_ignis_4_attachments/00001.png new file mode 100644 index 0000000..2134773 Binary files /dev/null and b/tests/snapshots/nanox/test_send_ignis_4_attachments/00001.png differ diff --git a/tests/snapshots/nanox/test_send_ignis_4_attachments/00002.png b/tests/snapshots/nanox/test_send_ignis_4_attachments/00002.png new file mode 100644 index 0000000..4c8fee2 Binary files /dev/null and b/tests/snapshots/nanox/test_send_ignis_4_attachments/00002.png differ diff --git a/tests/snapshots/nanox/test_send_ignis_4_attachments/00003.png b/tests/snapshots/nanox/test_send_ignis_4_attachments/00003.png new file mode 100644 index 0000000..0af81e5 Binary files /dev/null and b/tests/snapshots/nanox/test_send_ignis_4_attachments/00003.png differ diff --git a/tests/snapshots/nanox/test_send_ignis_4_attachments/00004.png b/tests/snapshots/nanox/test_send_ignis_4_attachments/00004.png new file mode 100644 index 0000000..a7987c9 Binary files /dev/null and b/tests/snapshots/nanox/test_send_ignis_4_attachments/00004.png differ diff --git a/tests/snapshots/nanox/test_send_ignis_4_attachments/00005.png b/tests/snapshots/nanox/test_send_ignis_4_attachments/00005.png new file mode 100644 index 0000000..bcdb84b Binary files /dev/null and b/tests/snapshots/nanox/test_send_ignis_4_attachments/00005.png differ diff --git a/tests/snapshots/nanox/test_send_ignis_4_attachments/00006.png b/tests/snapshots/nanox/test_send_ignis_4_attachments/00006.png new file mode 100644 index 0000000..29233b0 Binary files /dev/null and b/tests/snapshots/nanox/test_send_ignis_4_attachments/00006.png differ diff --git a/tests/snapshots/nanox/test_send_ignis_4_attachments/00007.png b/tests/snapshots/nanox/test_send_ignis_4_attachments/00007.png new file mode 100644 index 0000000..d76c7df Binary files /dev/null and b/tests/snapshots/nanox/test_send_ignis_4_attachments/00007.png differ diff --git a/tests/snapshots/nanox/test_send_ignis_4_attachments/00008.png b/tests/snapshots/nanox/test_send_ignis_4_attachments/00008.png new file mode 100644 index 0000000..570ce28 Binary files /dev/null and b/tests/snapshots/nanox/test_send_ignis_4_attachments/00008.png differ diff --git a/tests/snapshots/nanox/test_send_ignis_4_attachments/00009.png b/tests/snapshots/nanox/test_send_ignis_4_attachments/00009.png new file mode 100644 index 0000000..b9f1953 Binary files /dev/null and b/tests/snapshots/nanox/test_send_ignis_4_attachments/00009.png differ diff --git a/tests/snapshots/nanox/test_send_ignis_blind_accept/00000.png b/tests/snapshots/nanox/test_send_ignis_blind_accept/00000.png new file mode 100644 index 0000000..4d95254 Binary files /dev/null and b/tests/snapshots/nanox/test_send_ignis_blind_accept/00000.png differ diff --git a/tests/snapshots/nanox/test_send_ignis_blind_accept/00001.png b/tests/snapshots/nanox/test_send_ignis_blind_accept/00001.png new file mode 100644 index 0000000..2134773 Binary files /dev/null and b/tests/snapshots/nanox/test_send_ignis_blind_accept/00001.png differ diff --git a/tests/snapshots/nanox/test_send_ignis_blind_accept/00002.png b/tests/snapshots/nanox/test_send_ignis_blind_accept/00002.png new file mode 100644 index 0000000..4c8fee2 Binary files /dev/null and b/tests/snapshots/nanox/test_send_ignis_blind_accept/00002.png differ diff --git a/tests/snapshots/nanox/test_send_ignis_blind_accept/00003.png b/tests/snapshots/nanox/test_send_ignis_blind_accept/00003.png new file mode 100644 index 0000000..803b430 Binary files /dev/null and b/tests/snapshots/nanox/test_send_ignis_blind_accept/00003.png differ diff --git a/tests/snapshots/nanox/test_send_ignis_blind_accept/00004.png b/tests/snapshots/nanox/test_send_ignis_blind_accept/00004.png new file mode 100644 index 0000000..8fcb909 Binary files /dev/null and b/tests/snapshots/nanox/test_send_ignis_blind_accept/00004.png differ diff --git a/tests/snapshots/nanox/test_send_ignis_blind_accept/00005.png b/tests/snapshots/nanox/test_send_ignis_blind_accept/00005.png new file mode 100644 index 0000000..5aa015b Binary files /dev/null and b/tests/snapshots/nanox/test_send_ignis_blind_accept/00005.png differ diff --git a/tests/snapshots/nanox/test_send_ignis_blind_accept/00006.png b/tests/snapshots/nanox/test_send_ignis_blind_accept/00006.png new file mode 100644 index 0000000..a1455d0 Binary files /dev/null and b/tests/snapshots/nanox/test_send_ignis_blind_accept/00006.png differ diff --git a/tests/snapshots/nanox/test_send_ignis_blind_accept/00007.png b/tests/snapshots/nanox/test_send_ignis_blind_accept/00007.png new file mode 100644 index 0000000..570ce28 Binary files /dev/null and b/tests/snapshots/nanox/test_send_ignis_blind_accept/00007.png differ diff --git a/tests/snapshots/nanox/test_send_ignis_blind_accept/00008.png b/tests/snapshots/nanox/test_send_ignis_blind_accept/00008.png new file mode 100644 index 0000000..b9f1953 Binary files /dev/null and b/tests/snapshots/nanox/test_send_ignis_blind_accept/00008.png differ diff --git a/tests/snapshots/nanox/test_send_ignis_blind_reject/00000.png b/tests/snapshots/nanox/test_send_ignis_blind_reject/00000.png new file mode 100644 index 0000000..df10ee9 Binary files /dev/null and b/tests/snapshots/nanox/test_send_ignis_blind_reject/00000.png differ diff --git a/tests/snapshots/nanox/test_send_ignis_blind_reject/00001.png b/tests/snapshots/nanox/test_send_ignis_blind_reject/00001.png new file mode 100644 index 0000000..b9f1953 Binary files /dev/null and b/tests/snapshots/nanox/test_send_ignis_blind_reject/00001.png differ diff --git a/tests/snapshots/nanox/test_send_ignis_blind_reject_tx/00000.png b/tests/snapshots/nanox/test_send_ignis_blind_reject_tx/00000.png new file mode 100644 index 0000000..4d95254 Binary files /dev/null and b/tests/snapshots/nanox/test_send_ignis_blind_reject_tx/00000.png differ diff --git a/tests/snapshots/nanox/test_send_ignis_blind_reject_tx/00001.png b/tests/snapshots/nanox/test_send_ignis_blind_reject_tx/00001.png new file mode 100644 index 0000000..2134773 Binary files /dev/null and b/tests/snapshots/nanox/test_send_ignis_blind_reject_tx/00001.png differ diff --git a/tests/snapshots/nanox/test_send_ignis_blind_reject_tx/00002.png b/tests/snapshots/nanox/test_send_ignis_blind_reject_tx/00002.png new file mode 100644 index 0000000..4c8fee2 Binary files /dev/null and b/tests/snapshots/nanox/test_send_ignis_blind_reject_tx/00002.png differ diff --git a/tests/snapshots/nanox/test_send_ignis_blind_reject_tx/00003.png b/tests/snapshots/nanox/test_send_ignis_blind_reject_tx/00003.png new file mode 100644 index 0000000..803b430 Binary files /dev/null and b/tests/snapshots/nanox/test_send_ignis_blind_reject_tx/00003.png differ diff --git a/tests/snapshots/nanox/test_send_ignis_blind_reject_tx/00004.png b/tests/snapshots/nanox/test_send_ignis_blind_reject_tx/00004.png new file mode 100644 index 0000000..8fcb909 Binary files /dev/null and b/tests/snapshots/nanox/test_send_ignis_blind_reject_tx/00004.png differ diff --git a/tests/snapshots/nanox/test_send_ignis_blind_reject_tx/00005.png b/tests/snapshots/nanox/test_send_ignis_blind_reject_tx/00005.png new file mode 100644 index 0000000..5aa015b Binary files /dev/null and b/tests/snapshots/nanox/test_send_ignis_blind_reject_tx/00005.png differ diff --git a/tests/snapshots/nanox/test_send_ignis_blind_reject_tx/00006.png b/tests/snapshots/nanox/test_send_ignis_blind_reject_tx/00006.png new file mode 100644 index 0000000..a1455d0 Binary files /dev/null and b/tests/snapshots/nanox/test_send_ignis_blind_reject_tx/00006.png differ diff --git a/tests/snapshots/nanox/test_send_ignis_blind_reject_tx/00007.png b/tests/snapshots/nanox/test_send_ignis_blind_reject_tx/00007.png new file mode 100644 index 0000000..570ce28 Binary files /dev/null and b/tests/snapshots/nanox/test_send_ignis_blind_reject_tx/00007.png differ diff --git a/tests/snapshots/nanox/test_send_ignis_blind_reject_tx/00008.png b/tests/snapshots/nanox/test_send_ignis_blind_reject_tx/00008.png new file mode 100644 index 0000000..e90cd9d Binary files /dev/null and b/tests/snapshots/nanox/test_send_ignis_blind_reject_tx/00008.png differ diff --git a/tests/snapshots/nanox/test_send_ignis_blind_reject_tx/00009.png b/tests/snapshots/nanox/test_send_ignis_blind_reject_tx/00009.png new file mode 100644 index 0000000..b9f1953 Binary files /dev/null and b/tests/snapshots/nanox/test_send_ignis_blind_reject_tx/00009.png differ diff --git a/tests/snapshots/nanox/test_send_ignis_referenced_tx/00000.png b/tests/snapshots/nanox/test_send_ignis_referenced_tx/00000.png new file mode 100644 index 0000000..4d95254 Binary files /dev/null and b/tests/snapshots/nanox/test_send_ignis_referenced_tx/00000.png differ diff --git a/tests/snapshots/nanox/test_send_ignis_referenced_tx/00001.png b/tests/snapshots/nanox/test_send_ignis_referenced_tx/00001.png new file mode 100644 index 0000000..2134773 Binary files /dev/null and b/tests/snapshots/nanox/test_send_ignis_referenced_tx/00001.png differ diff --git a/tests/snapshots/nanox/test_send_ignis_referenced_tx/00002.png b/tests/snapshots/nanox/test_send_ignis_referenced_tx/00002.png new file mode 100644 index 0000000..4c8fee2 Binary files /dev/null and b/tests/snapshots/nanox/test_send_ignis_referenced_tx/00002.png differ diff --git a/tests/snapshots/nanox/test_send_ignis_referenced_tx/00003.png b/tests/snapshots/nanox/test_send_ignis_referenced_tx/00003.png new file mode 100644 index 0000000..b45c880 Binary files /dev/null and b/tests/snapshots/nanox/test_send_ignis_referenced_tx/00003.png differ diff --git a/tests/snapshots/nanox/test_send_ignis_referenced_tx/00004.png b/tests/snapshots/nanox/test_send_ignis_referenced_tx/00004.png new file mode 100644 index 0000000..8fcb909 Binary files /dev/null and b/tests/snapshots/nanox/test_send_ignis_referenced_tx/00004.png differ diff --git a/tests/snapshots/nanox/test_send_ignis_referenced_tx/00005.png b/tests/snapshots/nanox/test_send_ignis_referenced_tx/00005.png new file mode 100644 index 0000000..5f11d43 Binary files /dev/null and b/tests/snapshots/nanox/test_send_ignis_referenced_tx/00005.png differ diff --git a/tests/snapshots/nanox/test_send_ignis_referenced_tx/00006.png b/tests/snapshots/nanox/test_send_ignis_referenced_tx/00006.png new file mode 100644 index 0000000..570ce28 Binary files /dev/null and b/tests/snapshots/nanox/test_send_ignis_referenced_tx/00006.png differ diff --git a/tests/snapshots/nanox/test_send_ignis_referenced_tx/00007.png b/tests/snapshots/nanox/test_send_ignis_referenced_tx/00007.png new file mode 100644 index 0000000..b9f1953 Binary files /dev/null and b/tests/snapshots/nanox/test_send_ignis_referenced_tx/00007.png differ diff --git a/tests/snapshots/nanox/test_send_ignis_tx/00000.png b/tests/snapshots/nanox/test_send_ignis_tx/00000.png new file mode 100644 index 0000000..4d95254 Binary files /dev/null and b/tests/snapshots/nanox/test_send_ignis_tx/00000.png differ diff --git a/tests/snapshots/nanox/test_send_ignis_tx/00001.png b/tests/snapshots/nanox/test_send_ignis_tx/00001.png new file mode 100644 index 0000000..4c8fee2 Binary files /dev/null and b/tests/snapshots/nanox/test_send_ignis_tx/00001.png differ diff --git a/tests/snapshots/nanox/test_send_ignis_tx/00002.png b/tests/snapshots/nanox/test_send_ignis_tx/00002.png new file mode 100644 index 0000000..34fa3d0 Binary files /dev/null and b/tests/snapshots/nanox/test_send_ignis_tx/00002.png differ diff --git a/tests/snapshots/nanox/test_send_ignis_tx/00003.png b/tests/snapshots/nanox/test_send_ignis_tx/00003.png new file mode 100644 index 0000000..3484bf8 Binary files /dev/null and b/tests/snapshots/nanox/test_send_ignis_tx/00003.png differ diff --git a/tests/snapshots/nanox/test_send_ignis_tx/00004.png b/tests/snapshots/nanox/test_send_ignis_tx/00004.png new file mode 100644 index 0000000..eb2612a Binary files /dev/null and b/tests/snapshots/nanox/test_send_ignis_tx/00004.png differ diff --git a/tests/snapshots/nanox/test_send_ignis_tx/00005.png b/tests/snapshots/nanox/test_send_ignis_tx/00005.png new file mode 100644 index 0000000..570ce28 Binary files /dev/null and b/tests/snapshots/nanox/test_send_ignis_tx/00005.png differ diff --git a/tests/snapshots/nanox/test_send_ignis_tx/00006.png b/tests/snapshots/nanox/test_send_ignis_tx/00006.png new file mode 100644 index 0000000..b9f1953 Binary files /dev/null and b/tests/snapshots/nanox/test_send_ignis_tx/00006.png differ diff --git a/tests/snapshots/nanox/test_send_ignis_tx_reject/00000.png b/tests/snapshots/nanox/test_send_ignis_tx_reject/00000.png new file mode 100644 index 0000000..4d95254 Binary files /dev/null and b/tests/snapshots/nanox/test_send_ignis_tx_reject/00000.png differ diff --git a/tests/snapshots/nanox/test_send_ignis_tx_reject/00001.png b/tests/snapshots/nanox/test_send_ignis_tx_reject/00001.png new file mode 100644 index 0000000..4c8fee2 Binary files /dev/null and b/tests/snapshots/nanox/test_send_ignis_tx_reject/00001.png differ diff --git a/tests/snapshots/nanox/test_send_ignis_tx_reject/00002.png b/tests/snapshots/nanox/test_send_ignis_tx_reject/00002.png new file mode 100644 index 0000000..34fa3d0 Binary files /dev/null and b/tests/snapshots/nanox/test_send_ignis_tx_reject/00002.png differ diff --git a/tests/snapshots/nanox/test_send_ignis_tx_reject/00003.png b/tests/snapshots/nanox/test_send_ignis_tx_reject/00003.png new file mode 100644 index 0000000..3484bf8 Binary files /dev/null and b/tests/snapshots/nanox/test_send_ignis_tx_reject/00003.png differ diff --git a/tests/snapshots/nanox/test_send_ignis_tx_reject/00004.png b/tests/snapshots/nanox/test_send_ignis_tx_reject/00004.png new file mode 100644 index 0000000..eb2612a Binary files /dev/null and b/tests/snapshots/nanox/test_send_ignis_tx_reject/00004.png differ diff --git a/tests/snapshots/nanox/test_send_ignis_tx_reject/00005.png b/tests/snapshots/nanox/test_send_ignis_tx_reject/00005.png new file mode 100644 index 0000000..570ce28 Binary files /dev/null and b/tests/snapshots/nanox/test_send_ignis_tx_reject/00005.png differ diff --git a/tests/snapshots/nanox/test_send_ignis_tx_reject/00006.png b/tests/snapshots/nanox/test_send_ignis_tx_reject/00006.png new file mode 100644 index 0000000..e90cd9d Binary files /dev/null and b/tests/snapshots/nanox/test_send_ignis_tx_reject/00006.png differ diff --git a/tests/snapshots/nanox/test_send_ignis_tx_reject/00007.png b/tests/snapshots/nanox/test_send_ignis_tx_reject/00007.png new file mode 100644 index 0000000..b9f1953 Binary files /dev/null and b/tests/snapshots/nanox/test_send_ignis_tx_reject/00007.png differ diff --git a/tests/snapshots/nanox/test_show_address0/00000.png b/tests/snapshots/nanox/test_show_address0/00000.png new file mode 100644 index 0000000..4e075bd Binary files /dev/null and b/tests/snapshots/nanox/test_show_address0/00000.png differ diff --git a/tests/snapshots/nanox/test_show_address0/00001.png b/tests/snapshots/nanox/test_show_address0/00001.png new file mode 100644 index 0000000..884b9be Binary files /dev/null and b/tests/snapshots/nanox/test_show_address0/00001.png differ diff --git a/tests/snapshots/nanox/test_show_address0/00002.png b/tests/snapshots/nanox/test_show_address0/00002.png new file mode 100644 index 0000000..b9f1953 Binary files /dev/null and b/tests/snapshots/nanox/test_show_address0/00002.png differ diff --git a/tests/snapshots/nanox/test_show_address3/00000.png b/tests/snapshots/nanox/test_show_address3/00000.png new file mode 100644 index 0000000..8c357c1 Binary files /dev/null and b/tests/snapshots/nanox/test_show_address3/00000.png differ diff --git a/tests/snapshots/nanox/test_show_address3/00001.png b/tests/snapshots/nanox/test_show_address3/00001.png new file mode 100644 index 0000000..884b9be Binary files /dev/null and b/tests/snapshots/nanox/test_show_address3/00001.png differ diff --git a/tests/snapshots/nanox/test_show_address3/00002.png b/tests/snapshots/nanox/test_show_address3/00002.png new file mode 100644 index 0000000..b9f1953 Binary files /dev/null and b/tests/snapshots/nanox/test_show_address3/00002.png differ diff --git a/tests/snapshots/nanox/test_sign_token/00000.png b/tests/snapshots/nanox/test_sign_token/00000.png new file mode 100644 index 0000000..a328c45 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_token/00000.png differ diff --git a/tests/snapshots/nanox/test_sign_token/00001.png b/tests/snapshots/nanox/test_sign_token/00001.png new file mode 100644 index 0000000..56088e6 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_token/00001.png differ diff --git a/tests/snapshots/nanox/test_sign_token/00002.png b/tests/snapshots/nanox/test_sign_token/00002.png new file mode 100644 index 0000000..b9f1953 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_token/00002.png differ diff --git a/tests/snapshots/nanox/test_sign_token_reject_blind/00000.png b/tests/snapshots/nanox/test_sign_token_reject_blind/00000.png new file mode 100644 index 0000000..df10ee9 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_token_reject_blind/00000.png differ diff --git a/tests/snapshots/nanox/test_sign_token_reject_blind/00001.png b/tests/snapshots/nanox/test_sign_token_reject_blind/00001.png new file mode 100644 index 0000000..b9f1953 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_token_reject_blind/00001.png differ diff --git a/tests/snapshots/nanox/test_sign_token_reject_tx/00000.png b/tests/snapshots/nanox/test_sign_token_reject_tx/00000.png new file mode 100644 index 0000000..a328c45 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_token_reject_tx/00000.png differ diff --git a/tests/snapshots/nanox/test_sign_token_reject_tx/00001.png b/tests/snapshots/nanox/test_sign_token_reject_tx/00001.png new file mode 100644 index 0000000..56088e6 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_token_reject_tx/00001.png differ diff --git a/tests/snapshots/nanox/test_sign_token_reject_tx/00002.png b/tests/snapshots/nanox/test_sign_token_reject_tx/00002.png new file mode 100644 index 0000000..e90cd9d Binary files /dev/null and b/tests/snapshots/nanox/test_sign_token_reject_tx/00002.png differ diff --git a/tests/snapshots/nanox/test_sign_token_reject_tx/00003.png b/tests/snapshots/nanox/test_sign_token_reject_tx/00003.png new file mode 100644 index 0000000..b9f1953 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_token_reject_tx/00003.png differ diff --git a/tests/snapshots/stax/test_ardor_coin_exchange/00000.png b/tests/snapshots/stax/test_ardor_coin_exchange/00000.png new file mode 100644 index 0000000..24bbb11 Binary files /dev/null and b/tests/snapshots/stax/test_ardor_coin_exchange/00000.png differ diff --git a/tests/snapshots/stax/test_ardor_coin_exchange/00001.png b/tests/snapshots/stax/test_ardor_coin_exchange/00001.png new file mode 100644 index 0000000..71292e9 Binary files /dev/null and b/tests/snapshots/stax/test_ardor_coin_exchange/00001.png differ diff --git a/tests/snapshots/stax/test_ardor_coin_exchange/00002.png b/tests/snapshots/stax/test_ardor_coin_exchange/00002.png new file mode 100644 index 0000000..21a6202 Binary files /dev/null and b/tests/snapshots/stax/test_ardor_coin_exchange/00002.png differ diff --git a/tests/snapshots/stax/test_ardor_coin_exchange/00003.png b/tests/snapshots/stax/test_ardor_coin_exchange/00003.png new file mode 100644 index 0000000..cd2f527 Binary files /dev/null and b/tests/snapshots/stax/test_ardor_coin_exchange/00003.png differ diff --git a/tests/snapshots/stax/test_ardor_coin_exchange/00004.png b/tests/snapshots/stax/test_ardor_coin_exchange/00004.png new file mode 100644 index 0000000..bb69650 Binary files /dev/null and b/tests/snapshots/stax/test_ardor_coin_exchange/00004.png differ diff --git a/tests/snapshots/stax/test_asset_transfer/00000.png b/tests/snapshots/stax/test_asset_transfer/00000.png new file mode 100644 index 0000000..24bbb11 Binary files /dev/null and b/tests/snapshots/stax/test_asset_transfer/00000.png differ diff --git a/tests/snapshots/stax/test_asset_transfer/00001.png b/tests/snapshots/stax/test_asset_transfer/00001.png new file mode 100644 index 0000000..0bc5353 Binary files /dev/null and b/tests/snapshots/stax/test_asset_transfer/00001.png differ diff --git a/tests/snapshots/stax/test_asset_transfer/00002.png b/tests/snapshots/stax/test_asset_transfer/00002.png new file mode 100644 index 0000000..ec9842a Binary files /dev/null and b/tests/snapshots/stax/test_asset_transfer/00002.png differ diff --git a/tests/snapshots/stax/test_asset_transfer/00003.png b/tests/snapshots/stax/test_asset_transfer/00003.png new file mode 100644 index 0000000..2d7b9bd Binary files /dev/null and b/tests/snapshots/stax/test_asset_transfer/00003.png differ diff --git a/tests/snapshots/stax/test_asset_transfer/00004.png b/tests/snapshots/stax/test_asset_transfer/00004.png new file mode 100644 index 0000000..cd2f527 Binary files /dev/null and b/tests/snapshots/stax/test_asset_transfer/00004.png differ diff --git a/tests/snapshots/stax/test_asset_transfer/00005.png b/tests/snapshots/stax/test_asset_transfer/00005.png new file mode 100644 index 0000000..bb69650 Binary files /dev/null and b/tests/snapshots/stax/test_asset_transfer/00005.png differ diff --git a/tests/snapshots/stax/test_coin_exchange/00000.png b/tests/snapshots/stax/test_coin_exchange/00000.png new file mode 100644 index 0000000..24bbb11 Binary files /dev/null and b/tests/snapshots/stax/test_coin_exchange/00000.png differ diff --git a/tests/snapshots/stax/test_coin_exchange/00001.png b/tests/snapshots/stax/test_coin_exchange/00001.png new file mode 100644 index 0000000..361c603 Binary files /dev/null and b/tests/snapshots/stax/test_coin_exchange/00001.png differ diff --git a/tests/snapshots/stax/test_coin_exchange/00002.png b/tests/snapshots/stax/test_coin_exchange/00002.png new file mode 100644 index 0000000..21a6202 Binary files /dev/null and b/tests/snapshots/stax/test_coin_exchange/00002.png differ diff --git a/tests/snapshots/stax/test_coin_exchange/00003.png b/tests/snapshots/stax/test_coin_exchange/00003.png new file mode 100644 index 0000000..cd2f527 Binary files /dev/null and b/tests/snapshots/stax/test_coin_exchange/00003.png differ diff --git a/tests/snapshots/stax/test_coin_exchange/00004.png b/tests/snapshots/stax/test_coin_exchange/00004.png new file mode 100644 index 0000000..bb69650 Binary files /dev/null and b/tests/snapshots/stax/test_coin_exchange/00004.png differ diff --git a/tests/snapshots/stax/test_place_asset_exchange_order/00000.png b/tests/snapshots/stax/test_place_asset_exchange_order/00000.png new file mode 100644 index 0000000..24bbb11 Binary files /dev/null and b/tests/snapshots/stax/test_place_asset_exchange_order/00000.png differ diff --git a/tests/snapshots/stax/test_place_asset_exchange_order/00001.png b/tests/snapshots/stax/test_place_asset_exchange_order/00001.png new file mode 100644 index 0000000..6eb63a7 Binary files /dev/null and b/tests/snapshots/stax/test_place_asset_exchange_order/00001.png differ diff --git a/tests/snapshots/stax/test_place_asset_exchange_order/00002.png b/tests/snapshots/stax/test_place_asset_exchange_order/00002.png new file mode 100644 index 0000000..b0446db Binary files /dev/null and b/tests/snapshots/stax/test_place_asset_exchange_order/00002.png differ diff --git a/tests/snapshots/stax/test_place_asset_exchange_order/00003.png b/tests/snapshots/stax/test_place_asset_exchange_order/00003.png new file mode 100644 index 0000000..2d7b9bd Binary files /dev/null and b/tests/snapshots/stax/test_place_asset_exchange_order/00003.png differ diff --git a/tests/snapshots/stax/test_place_asset_exchange_order/00004.png b/tests/snapshots/stax/test_place_asset_exchange_order/00004.png new file mode 100644 index 0000000..cd2f527 Binary files /dev/null and b/tests/snapshots/stax/test_place_asset_exchange_order/00004.png differ diff --git a/tests/snapshots/stax/test_place_asset_exchange_order/00005.png b/tests/snapshots/stax/test_place_asset_exchange_order/00005.png new file mode 100644 index 0000000..bb69650 Binary files /dev/null and b/tests/snapshots/stax/test_place_asset_exchange_order/00005.png differ diff --git a/tests/snapshots/stax/test_send_ardr/00000.png b/tests/snapshots/stax/test_send_ardr/00000.png new file mode 100644 index 0000000..24bbb11 Binary files /dev/null and b/tests/snapshots/stax/test_send_ardr/00000.png differ diff --git a/tests/snapshots/stax/test_send_ardr/00001.png b/tests/snapshots/stax/test_send_ardr/00001.png new file mode 100644 index 0000000..62f649f Binary files /dev/null and b/tests/snapshots/stax/test_send_ardr/00001.png differ diff --git a/tests/snapshots/stax/test_send_ardr/00002.png b/tests/snapshots/stax/test_send_ardr/00002.png new file mode 100644 index 0000000..fc28e07 Binary files /dev/null and b/tests/snapshots/stax/test_send_ardr/00002.png differ diff --git a/tests/snapshots/stax/test_send_ardr/00003.png b/tests/snapshots/stax/test_send_ardr/00003.png new file mode 100644 index 0000000..2d7b9bd Binary files /dev/null and b/tests/snapshots/stax/test_send_ardr/00003.png differ diff --git a/tests/snapshots/stax/test_send_ardr/00004.png b/tests/snapshots/stax/test_send_ardr/00004.png new file mode 100644 index 0000000..cd2f527 Binary files /dev/null and b/tests/snapshots/stax/test_send_ardr/00004.png differ diff --git a/tests/snapshots/stax/test_send_ardr/00005.png b/tests/snapshots/stax/test_send_ardr/00005.png new file mode 100644 index 0000000..bb69650 Binary files /dev/null and b/tests/snapshots/stax/test_send_ardr/00005.png differ diff --git a/tests/snapshots/stax/test_send_ignis_4_attachments/00000.png b/tests/snapshots/stax/test_send_ignis_4_attachments/00000.png new file mode 100644 index 0000000..2519750 Binary files /dev/null and b/tests/snapshots/stax/test_send_ignis_4_attachments/00000.png differ diff --git a/tests/snapshots/stax/test_send_ignis_4_attachments/00001.png b/tests/snapshots/stax/test_send_ignis_4_attachments/00001.png new file mode 100644 index 0000000..279acd5 Binary files /dev/null and b/tests/snapshots/stax/test_send_ignis_4_attachments/00001.png differ diff --git a/tests/snapshots/stax/test_send_ignis_4_attachments/00002.png b/tests/snapshots/stax/test_send_ignis_4_attachments/00002.png new file mode 100644 index 0000000..8e4bb54 Binary files /dev/null and b/tests/snapshots/stax/test_send_ignis_4_attachments/00002.png differ diff --git a/tests/snapshots/stax/test_send_ignis_4_attachments/00003.png b/tests/snapshots/stax/test_send_ignis_4_attachments/00003.png new file mode 100644 index 0000000..24bbb11 Binary files /dev/null and b/tests/snapshots/stax/test_send_ignis_4_attachments/00003.png differ diff --git a/tests/snapshots/stax/test_send_ignis_4_attachments/00004.png b/tests/snapshots/stax/test_send_ignis_4_attachments/00004.png new file mode 100644 index 0000000..b65ff38 Binary files /dev/null and b/tests/snapshots/stax/test_send_ignis_4_attachments/00004.png differ diff --git a/tests/snapshots/stax/test_send_ignis_4_attachments/00005.png b/tests/snapshots/stax/test_send_ignis_4_attachments/00005.png new file mode 100644 index 0000000..53dee93 Binary files /dev/null and b/tests/snapshots/stax/test_send_ignis_4_attachments/00005.png differ diff --git a/tests/snapshots/stax/test_send_ignis_4_attachments/00006.png b/tests/snapshots/stax/test_send_ignis_4_attachments/00006.png new file mode 100644 index 0000000..2d7b9bd Binary files /dev/null and b/tests/snapshots/stax/test_send_ignis_4_attachments/00006.png differ diff --git a/tests/snapshots/stax/test_send_ignis_4_attachments/00007.png b/tests/snapshots/stax/test_send_ignis_4_attachments/00007.png new file mode 100644 index 0000000..cd2f527 Binary files /dev/null and b/tests/snapshots/stax/test_send_ignis_4_attachments/00007.png differ diff --git a/tests/snapshots/stax/test_send_ignis_4_attachments/00008.png b/tests/snapshots/stax/test_send_ignis_4_attachments/00008.png new file mode 100644 index 0000000..bb69650 Binary files /dev/null and b/tests/snapshots/stax/test_send_ignis_4_attachments/00008.png differ diff --git a/tests/snapshots/stax/test_send_ignis_blind_accept/00000.png b/tests/snapshots/stax/test_send_ignis_blind_accept/00000.png new file mode 100644 index 0000000..2519750 Binary files /dev/null and b/tests/snapshots/stax/test_send_ignis_blind_accept/00000.png differ diff --git a/tests/snapshots/stax/test_send_ignis_blind_accept/00001.png b/tests/snapshots/stax/test_send_ignis_blind_accept/00001.png new file mode 100644 index 0000000..279acd5 Binary files /dev/null and b/tests/snapshots/stax/test_send_ignis_blind_accept/00001.png differ diff --git a/tests/snapshots/stax/test_send_ignis_blind_accept/00002.png b/tests/snapshots/stax/test_send_ignis_blind_accept/00002.png new file mode 100644 index 0000000..8e4bb54 Binary files /dev/null and b/tests/snapshots/stax/test_send_ignis_blind_accept/00002.png differ diff --git a/tests/snapshots/stax/test_send_ignis_blind_accept/00003.png b/tests/snapshots/stax/test_send_ignis_blind_accept/00003.png new file mode 100644 index 0000000..24bbb11 Binary files /dev/null and b/tests/snapshots/stax/test_send_ignis_blind_accept/00003.png differ diff --git a/tests/snapshots/stax/test_send_ignis_blind_accept/00004.png b/tests/snapshots/stax/test_send_ignis_blind_accept/00004.png new file mode 100644 index 0000000..ba0b081 Binary files /dev/null and b/tests/snapshots/stax/test_send_ignis_blind_accept/00004.png differ diff --git a/tests/snapshots/stax/test_send_ignis_blind_accept/00005.png b/tests/snapshots/stax/test_send_ignis_blind_accept/00005.png new file mode 100644 index 0000000..f402fc5 Binary files /dev/null and b/tests/snapshots/stax/test_send_ignis_blind_accept/00005.png differ diff --git a/tests/snapshots/stax/test_send_ignis_blind_accept/00006.png b/tests/snapshots/stax/test_send_ignis_blind_accept/00006.png new file mode 100644 index 0000000..2d7b9bd Binary files /dev/null and b/tests/snapshots/stax/test_send_ignis_blind_accept/00006.png differ diff --git a/tests/snapshots/stax/test_send_ignis_blind_accept/00007.png b/tests/snapshots/stax/test_send_ignis_blind_accept/00007.png new file mode 100644 index 0000000..cd2f527 Binary files /dev/null and b/tests/snapshots/stax/test_send_ignis_blind_accept/00007.png differ diff --git a/tests/snapshots/stax/test_send_ignis_blind_accept/00008.png b/tests/snapshots/stax/test_send_ignis_blind_accept/00008.png new file mode 100644 index 0000000..bb69650 Binary files /dev/null and b/tests/snapshots/stax/test_send_ignis_blind_accept/00008.png differ diff --git a/tests/snapshots/stax/test_send_ignis_blind_reject/00000.png b/tests/snapshots/stax/test_send_ignis_blind_reject/00000.png new file mode 100644 index 0000000..2519750 Binary files /dev/null and b/tests/snapshots/stax/test_send_ignis_blind_reject/00000.png differ diff --git a/tests/snapshots/stax/test_send_ignis_blind_reject/00001.png b/tests/snapshots/stax/test_send_ignis_blind_reject/00001.png new file mode 100644 index 0000000..babad98 Binary files /dev/null and b/tests/snapshots/stax/test_send_ignis_blind_reject/00001.png differ diff --git a/tests/snapshots/stax/test_send_ignis_blind_reject/00002.png b/tests/snapshots/stax/test_send_ignis_blind_reject/00002.png new file mode 100644 index 0000000..17d33d6 Binary files /dev/null and b/tests/snapshots/stax/test_send_ignis_blind_reject/00002.png differ diff --git a/tests/snapshots/stax/test_send_ignis_blind_reject/00003.png b/tests/snapshots/stax/test_send_ignis_blind_reject/00003.png new file mode 100644 index 0000000..bb69650 Binary files /dev/null and b/tests/snapshots/stax/test_send_ignis_blind_reject/00003.png differ diff --git a/tests/snapshots/stax/test_send_ignis_blind_reject_tx/00000.png b/tests/snapshots/stax/test_send_ignis_blind_reject_tx/00000.png new file mode 100644 index 0000000..2519750 Binary files /dev/null and b/tests/snapshots/stax/test_send_ignis_blind_reject_tx/00000.png differ diff --git a/tests/snapshots/stax/test_send_ignis_blind_reject_tx/00001.png b/tests/snapshots/stax/test_send_ignis_blind_reject_tx/00001.png new file mode 100644 index 0000000..279acd5 Binary files /dev/null and b/tests/snapshots/stax/test_send_ignis_blind_reject_tx/00001.png differ diff --git a/tests/snapshots/stax/test_send_ignis_blind_reject_tx/00002.png b/tests/snapshots/stax/test_send_ignis_blind_reject_tx/00002.png new file mode 100644 index 0000000..8e4bb54 Binary files /dev/null and b/tests/snapshots/stax/test_send_ignis_blind_reject_tx/00002.png differ diff --git a/tests/snapshots/stax/test_send_ignis_blind_reject_tx/00003.png b/tests/snapshots/stax/test_send_ignis_blind_reject_tx/00003.png new file mode 100644 index 0000000..24bbb11 Binary files /dev/null and b/tests/snapshots/stax/test_send_ignis_blind_reject_tx/00003.png differ diff --git a/tests/snapshots/stax/test_send_ignis_blind_reject_tx/00004.png b/tests/snapshots/stax/test_send_ignis_blind_reject_tx/00004.png new file mode 100644 index 0000000..ba0b081 Binary files /dev/null and b/tests/snapshots/stax/test_send_ignis_blind_reject_tx/00004.png differ diff --git a/tests/snapshots/stax/test_send_ignis_blind_reject_tx/00005.png b/tests/snapshots/stax/test_send_ignis_blind_reject_tx/00005.png new file mode 100644 index 0000000..f402fc5 Binary files /dev/null and b/tests/snapshots/stax/test_send_ignis_blind_reject_tx/00005.png differ diff --git a/tests/snapshots/stax/test_send_ignis_blind_reject_tx/00006.png b/tests/snapshots/stax/test_send_ignis_blind_reject_tx/00006.png new file mode 100644 index 0000000..2d7b9bd Binary files /dev/null and b/tests/snapshots/stax/test_send_ignis_blind_reject_tx/00006.png differ diff --git a/tests/snapshots/stax/test_send_ignis_blind_reject_tx/00007.png b/tests/snapshots/stax/test_send_ignis_blind_reject_tx/00007.png new file mode 100644 index 0000000..babad98 Binary files /dev/null and b/tests/snapshots/stax/test_send_ignis_blind_reject_tx/00007.png differ diff --git a/tests/snapshots/stax/test_send_ignis_blind_reject_tx/00008.png b/tests/snapshots/stax/test_send_ignis_blind_reject_tx/00008.png new file mode 100644 index 0000000..17d33d6 Binary files /dev/null and b/tests/snapshots/stax/test_send_ignis_blind_reject_tx/00008.png differ diff --git a/tests/snapshots/stax/test_send_ignis_blind_reject_tx/00009.png b/tests/snapshots/stax/test_send_ignis_blind_reject_tx/00009.png new file mode 100644 index 0000000..bb69650 Binary files /dev/null and b/tests/snapshots/stax/test_send_ignis_blind_reject_tx/00009.png differ diff --git a/tests/snapshots/stax/test_send_ignis_referenced_tx/00000.png b/tests/snapshots/stax/test_send_ignis_referenced_tx/00000.png new file mode 100644 index 0000000..2519750 Binary files /dev/null and b/tests/snapshots/stax/test_send_ignis_referenced_tx/00000.png differ diff --git a/tests/snapshots/stax/test_send_ignis_referenced_tx/00001.png b/tests/snapshots/stax/test_send_ignis_referenced_tx/00001.png new file mode 100644 index 0000000..279acd5 Binary files /dev/null and b/tests/snapshots/stax/test_send_ignis_referenced_tx/00001.png differ diff --git a/tests/snapshots/stax/test_send_ignis_referenced_tx/00002.png b/tests/snapshots/stax/test_send_ignis_referenced_tx/00002.png new file mode 100644 index 0000000..8e4bb54 Binary files /dev/null and b/tests/snapshots/stax/test_send_ignis_referenced_tx/00002.png differ diff --git a/tests/snapshots/stax/test_send_ignis_referenced_tx/00003.png b/tests/snapshots/stax/test_send_ignis_referenced_tx/00003.png new file mode 100644 index 0000000..24bbb11 Binary files /dev/null and b/tests/snapshots/stax/test_send_ignis_referenced_tx/00003.png differ diff --git a/tests/snapshots/stax/test_send_ignis_referenced_tx/00004.png b/tests/snapshots/stax/test_send_ignis_referenced_tx/00004.png new file mode 100644 index 0000000..e745352 Binary files /dev/null and b/tests/snapshots/stax/test_send_ignis_referenced_tx/00004.png differ diff --git a/tests/snapshots/stax/test_send_ignis_referenced_tx/00005.png b/tests/snapshots/stax/test_send_ignis_referenced_tx/00005.png new file mode 100644 index 0000000..fc255b1 Binary files /dev/null and b/tests/snapshots/stax/test_send_ignis_referenced_tx/00005.png differ diff --git a/tests/snapshots/stax/test_send_ignis_referenced_tx/00006.png b/tests/snapshots/stax/test_send_ignis_referenced_tx/00006.png new file mode 100644 index 0000000..2d7b9bd Binary files /dev/null and b/tests/snapshots/stax/test_send_ignis_referenced_tx/00006.png differ diff --git a/tests/snapshots/stax/test_send_ignis_referenced_tx/00007.png b/tests/snapshots/stax/test_send_ignis_referenced_tx/00007.png new file mode 100644 index 0000000..cd2f527 Binary files /dev/null and b/tests/snapshots/stax/test_send_ignis_referenced_tx/00007.png differ diff --git a/tests/snapshots/stax/test_send_ignis_referenced_tx/00008.png b/tests/snapshots/stax/test_send_ignis_referenced_tx/00008.png new file mode 100644 index 0000000..bb69650 Binary files /dev/null and b/tests/snapshots/stax/test_send_ignis_referenced_tx/00008.png differ diff --git a/tests/snapshots/stax/test_send_ignis_tx/00000.png b/tests/snapshots/stax/test_send_ignis_tx/00000.png new file mode 100644 index 0000000..24bbb11 Binary files /dev/null and b/tests/snapshots/stax/test_send_ignis_tx/00000.png differ diff --git a/tests/snapshots/stax/test_send_ignis_tx/00001.png b/tests/snapshots/stax/test_send_ignis_tx/00001.png new file mode 100644 index 0000000..e10c98a Binary files /dev/null and b/tests/snapshots/stax/test_send_ignis_tx/00001.png differ diff --git a/tests/snapshots/stax/test_send_ignis_tx/00002.png b/tests/snapshots/stax/test_send_ignis_tx/00002.png new file mode 100644 index 0000000..76923a8 Binary files /dev/null and b/tests/snapshots/stax/test_send_ignis_tx/00002.png differ diff --git a/tests/snapshots/stax/test_send_ignis_tx/00003.png b/tests/snapshots/stax/test_send_ignis_tx/00003.png new file mode 100644 index 0000000..2d7b9bd Binary files /dev/null and b/tests/snapshots/stax/test_send_ignis_tx/00003.png differ diff --git a/tests/snapshots/stax/test_send_ignis_tx/00004.png b/tests/snapshots/stax/test_send_ignis_tx/00004.png new file mode 100644 index 0000000..cd2f527 Binary files /dev/null and b/tests/snapshots/stax/test_send_ignis_tx/00004.png differ diff --git a/tests/snapshots/stax/test_send_ignis_tx/00005.png b/tests/snapshots/stax/test_send_ignis_tx/00005.png new file mode 100644 index 0000000..bb69650 Binary files /dev/null and b/tests/snapshots/stax/test_send_ignis_tx/00005.png differ diff --git a/tests/snapshots/stax/test_send_ignis_tx_reject/00000.png b/tests/snapshots/stax/test_send_ignis_tx_reject/00000.png new file mode 100644 index 0000000..24bbb11 Binary files /dev/null and b/tests/snapshots/stax/test_send_ignis_tx_reject/00000.png differ diff --git a/tests/snapshots/stax/test_send_ignis_tx_reject/00001.png b/tests/snapshots/stax/test_send_ignis_tx_reject/00001.png new file mode 100644 index 0000000..e10c98a Binary files /dev/null and b/tests/snapshots/stax/test_send_ignis_tx_reject/00001.png differ diff --git a/tests/snapshots/stax/test_send_ignis_tx_reject/00002.png b/tests/snapshots/stax/test_send_ignis_tx_reject/00002.png new file mode 100644 index 0000000..76923a8 Binary files /dev/null and b/tests/snapshots/stax/test_send_ignis_tx_reject/00002.png differ diff --git a/tests/snapshots/stax/test_send_ignis_tx_reject/00003.png b/tests/snapshots/stax/test_send_ignis_tx_reject/00003.png new file mode 100644 index 0000000..2d7b9bd Binary files /dev/null and b/tests/snapshots/stax/test_send_ignis_tx_reject/00003.png differ diff --git a/tests/snapshots/stax/test_send_ignis_tx_reject/00004.png b/tests/snapshots/stax/test_send_ignis_tx_reject/00004.png new file mode 100644 index 0000000..babad98 Binary files /dev/null and b/tests/snapshots/stax/test_send_ignis_tx_reject/00004.png differ diff --git a/tests/snapshots/stax/test_send_ignis_tx_reject/00005.png b/tests/snapshots/stax/test_send_ignis_tx_reject/00005.png new file mode 100644 index 0000000..17d33d6 Binary files /dev/null and b/tests/snapshots/stax/test_send_ignis_tx_reject/00005.png differ diff --git a/tests/snapshots/stax/test_send_ignis_tx_reject/00006.png b/tests/snapshots/stax/test_send_ignis_tx_reject/00006.png new file mode 100644 index 0000000..bb69650 Binary files /dev/null and b/tests/snapshots/stax/test_send_ignis_tx_reject/00006.png differ diff --git a/tests/snapshots/stax/test_show_address0/00000.png b/tests/snapshots/stax/test_show_address0/00000.png new file mode 100644 index 0000000..ab4d4d3 Binary files /dev/null and b/tests/snapshots/stax/test_show_address0/00000.png differ diff --git a/tests/snapshots/stax/test_show_address0/00001.png b/tests/snapshots/stax/test_show_address0/00001.png new file mode 100644 index 0000000..e052294 Binary files /dev/null and b/tests/snapshots/stax/test_show_address0/00001.png differ diff --git a/tests/snapshots/stax/test_show_address0/00002.png b/tests/snapshots/stax/test_show_address0/00002.png new file mode 100644 index 0000000..f59899e Binary files /dev/null and b/tests/snapshots/stax/test_show_address0/00002.png differ diff --git a/tests/snapshots/stax/test_show_address3/00000.png b/tests/snapshots/stax/test_show_address3/00000.png new file mode 100644 index 0000000..ab4d4d3 Binary files /dev/null and b/tests/snapshots/stax/test_show_address3/00000.png differ diff --git a/tests/snapshots/stax/test_show_address3/00001.png b/tests/snapshots/stax/test_show_address3/00001.png new file mode 100644 index 0000000..171c7cd Binary files /dev/null and b/tests/snapshots/stax/test_show_address3/00001.png differ diff --git a/tests/snapshots/stax/test_show_address3/00002.png b/tests/snapshots/stax/test_show_address3/00002.png new file mode 100644 index 0000000..f59899e Binary files /dev/null and b/tests/snapshots/stax/test_show_address3/00002.png differ diff --git a/tests/snapshots/stax/test_sign_token/00000.png b/tests/snapshots/stax/test_sign_token/00000.png new file mode 100644 index 0000000..cb9ce2d Binary files /dev/null and b/tests/snapshots/stax/test_sign_token/00000.png differ diff --git a/tests/snapshots/stax/test_sign_token/00001.png b/tests/snapshots/stax/test_sign_token/00001.png new file mode 100644 index 0000000..279acd5 Binary files /dev/null and b/tests/snapshots/stax/test_sign_token/00001.png differ diff --git a/tests/snapshots/stax/test_sign_token/00002.png b/tests/snapshots/stax/test_sign_token/00002.png new file mode 100644 index 0000000..6222cb1 Binary files /dev/null and b/tests/snapshots/stax/test_sign_token/00002.png differ diff --git a/tests/snapshots/stax/test_sign_token/00003.png b/tests/snapshots/stax/test_sign_token/00003.png new file mode 100644 index 0000000..b4e4976 Binary files /dev/null and b/tests/snapshots/stax/test_sign_token/00003.png differ diff --git a/tests/snapshots/stax/test_sign_token/00004.png b/tests/snapshots/stax/test_sign_token/00004.png new file mode 100644 index 0000000..ddfc7f3 Binary files /dev/null and b/tests/snapshots/stax/test_sign_token/00004.png differ diff --git a/tests/snapshots/stax/test_sign_token/00005.png b/tests/snapshots/stax/test_sign_token/00005.png new file mode 100644 index 0000000..4c02206 Binary files /dev/null and b/tests/snapshots/stax/test_sign_token/00005.png differ diff --git a/tests/snapshots/stax/test_sign_token/00006.png b/tests/snapshots/stax/test_sign_token/00006.png new file mode 100644 index 0000000..bb69650 Binary files /dev/null and b/tests/snapshots/stax/test_sign_token/00006.png differ diff --git a/tests/snapshots/stax/test_sign_token_reject_blind/00000.png b/tests/snapshots/stax/test_sign_token_reject_blind/00000.png new file mode 100644 index 0000000..cb9ce2d Binary files /dev/null and b/tests/snapshots/stax/test_sign_token_reject_blind/00000.png differ diff --git a/tests/snapshots/stax/test_sign_token_reject_blind/00001.png b/tests/snapshots/stax/test_sign_token_reject_blind/00001.png new file mode 100644 index 0000000..df6511a Binary files /dev/null and b/tests/snapshots/stax/test_sign_token_reject_blind/00001.png differ diff --git a/tests/snapshots/stax/test_sign_token_reject_blind/00002.png b/tests/snapshots/stax/test_sign_token_reject_blind/00002.png new file mode 100644 index 0000000..08575ad Binary files /dev/null and b/tests/snapshots/stax/test_sign_token_reject_blind/00002.png differ diff --git a/tests/snapshots/stax/test_sign_token_reject_blind/00003.png b/tests/snapshots/stax/test_sign_token_reject_blind/00003.png new file mode 100644 index 0000000..bb69650 Binary files /dev/null and b/tests/snapshots/stax/test_sign_token_reject_blind/00003.png differ diff --git a/tests/snapshots/stax/test_sign_token_reject_tx/00000.png b/tests/snapshots/stax/test_sign_token_reject_tx/00000.png new file mode 100644 index 0000000..cb9ce2d Binary files /dev/null and b/tests/snapshots/stax/test_sign_token_reject_tx/00000.png differ diff --git a/tests/snapshots/stax/test_sign_token_reject_tx/00001.png b/tests/snapshots/stax/test_sign_token_reject_tx/00001.png new file mode 100644 index 0000000..279acd5 Binary files /dev/null and b/tests/snapshots/stax/test_sign_token_reject_tx/00001.png differ diff --git a/tests/snapshots/stax/test_sign_token_reject_tx/00002.png b/tests/snapshots/stax/test_sign_token_reject_tx/00002.png new file mode 100644 index 0000000..6222cb1 Binary files /dev/null and b/tests/snapshots/stax/test_sign_token_reject_tx/00002.png differ diff --git a/tests/snapshots/stax/test_sign_token_reject_tx/00003.png b/tests/snapshots/stax/test_sign_token_reject_tx/00003.png new file mode 100644 index 0000000..b4e4976 Binary files /dev/null and b/tests/snapshots/stax/test_sign_token_reject_tx/00003.png differ diff --git a/tests/snapshots/stax/test_sign_token_reject_tx/00004.png b/tests/snapshots/stax/test_sign_token_reject_tx/00004.png new file mode 100644 index 0000000..ddfc7f3 Binary files /dev/null and b/tests/snapshots/stax/test_sign_token_reject_tx/00004.png differ diff --git a/tests/snapshots/stax/test_sign_token_reject_tx/00005.png b/tests/snapshots/stax/test_sign_token_reject_tx/00005.png new file mode 100644 index 0000000..08575ad Binary files /dev/null and b/tests/snapshots/stax/test_sign_token_reject_tx/00005.png differ diff --git a/tests/snapshots/stax/test_sign_token_reject_tx/00006.png b/tests/snapshots/stax/test_sign_token_reject_tx/00006.png new file mode 100644 index 0000000..bb69650 Binary files /dev/null and b/tests/snapshots/stax/test_sign_token_reject_tx/00006.png differ diff --git a/tests/src/test_reedSolomon.c b/tests/src/test_reedSolomon.c deleted file mode 100644 index 3fe0247..0000000 --- a/tests/src/test_reedSolomon.c +++ /dev/null @@ -1,78 +0,0 @@ -/******************************************************************************* -* (c) 2021 Jelurida IP B.V. -* -* -* 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 -#include -#include -#include -#include - -#include <../../src/reedSolomon.h> -#include - -struct testvector_t { int64_t account_id; char account_rs[20]; }; - -struct testvector_t testvectors[] = { - {8264278205416377583L, "K59H-9RMF-64CY-9X6E7"}, - {8301188658053077183L, "4Q7Z-5BEE-F5JZ-9ZXE8"}, - {1798923958688893959L, "GM29-TWRT-M5CK-3HSXK"}, - {6899983965971136120L, "MHMS-VHZT-W5CY-7CFJZ"}, - {1629938923029941274L, "JM2U-U4AE-G7WF-3NP9F"}, - {6474206656034063375L, "4K2H-NVHQ-7WXY-72AQM"}, - {1691406066100673814L, "Y9AQ-VE8F-U9SY-3NAYG"}, - {2992669254877342352L, "6UNJ-UMFM-Z525-4S24M"}, - {43918951749449909L, "XY7P-3R8Y-26FC-2A293"}, - {9129355674909631300L, "YSU6-MRRL-NSC4-9WHEX"}, - {0L, "2222-2222-2222-22222"}, - {1L, "2223-2222-KB8Y-22222"}, - {10L, "222C-2222-VJTL-22222"}, - {100L, "2256-2222-QFKF-22222"}, - {1000L, "22ZA-2222-ZK43-22222"}, - {10000L, "2BSJ-2222-KC3Y-22222"}, - {100000L, "53P2-2222-SQQW-22222"}, - {1000000L, "YJL2-2222-ZZPC-22222"}, - {10000000L, "K7N2-222B-FVFG-22222"}, - {100000000L, "DSA2-224Z-849U-22222"}, - {1000000000L, "PLJ2-22XT-DVNG-22222"}, - {10000000000L, "RT22-2BC2-SMPD-22222"}, - {100000000000L, "FU22-4X69-74VX-22222"}, - {1000000000000L, "C622-X5CC-EMM8-22222"}, - {10000000000000L, "7A22-5399-RNFK-2B222"}, - {100000000000000L, "NJ22-YEA9-KWDV-2U422"}, - {1000000000000000L, "F222-HULE-NWMS-2FW22"}, - {10000000000000000L, "4222-YBRW-T4XW-28WA2"}, - {100000000000000000L, "N222-H3GS-QPZD-27US4"}, - {1000000000000000000L, "A222-QGMQ-WDH2-2Q7SV"}}; - -static void test_reedSolomonEncode(void **state) { - char out[21]; - - int n = sizeof(testvectors) / sizeof(struct testvector_t); - for(int i = 0; i < n; i++) { - reedSolomonEncode(testvectors[i].account_id, out); - assert_string_equal(testvectors[i].account_rs, out); - } -} - -int main(void) { - const struct CMUnitTest tests[] = { - cmocka_unit_test(test_reedSolomonEncode) - }; - - return cmocka_run_group_tests(tests, NULL, NULL); -} \ No newline at end of file diff --git a/tests/test_auth_sign_tx.py b/tests/test_auth_sign_tx.py new file mode 100644 index 0000000..00c53f4 --- /dev/null +++ b/tests/test_auth_sign_tx.py @@ -0,0 +1,202 @@ +from constants import RESPONSE_SUFFIX, R_SUCCESS, ROOT_SCREENSHOT_PATH, PATH_STR_0, PATH_STR_1 +from ragger.navigator import NavInsID +from ardor_command_sender import ArdorCommandSender +from utils import enable_blind_signing + +RET_VAL_TRANSACTION_ACCEPTED = 8 # R_FINISHED +RET_VAL_TRANSACTION_REJECTED = 1 # R_REJECT + +# +# HOW TO ADD A NEW TEST +# +# To get the unsigned bytes of a transaction, you can use the Ardor wallet API. +# Send the transaction to the wallet API, and then use the "getTransactionBytes" API call. + +def _sign_tx_test(backend, navigator, unsigned_bytes_hex: str, expected_signature: str, test_name: str, instructions, signing_account = PATH_STR_0): + tx_bytes = bytes.fromhex(unsigned_bytes_hex) + client = ArdorCommandSender(backend) + with client.load_tx(tx_bytes): + navigator.navigate_and_compare(ROOT_SCREENSHOT_PATH, test_name, instructions) + + rapdu = client.get_async_response() + assert rapdu is not None + assert rapdu.status == RESPONSE_SUFFIX + assert len(rapdu.data) == 2 + assert rapdu.data[0] == R_SUCCESS + assert rapdu.data[1] == RET_VAL_TRANSACTION_ACCEPTED + + signature = client.sign_tx(signing_account) + assert signature.hex() == expected_signature + +def _sign_tx_reject(backend, navigator, unsigned_bytes_hex: str, test_name: str, instructions): + tx_bytes = bytes.fromhex(unsigned_bytes_hex) + client = ArdorCommandSender(backend) + with client.load_tx(tx_bytes): + navigator.navigate_and_compare(ROOT_SCREENSHOT_PATH, test_name, instructions) + + rapdu = client.get_async_response() + assert rapdu is not None + assert rapdu.status == RESPONSE_SUFFIX + assert len(rapdu.data) == 2 + assert rapdu.data[0] == R_SUCCESS + assert rapdu.data[1] == RET_VAL_TRANSACTION_REJECTED + + client.sign_tx_reject(PATH_STR_0) + +def get_nano_instructions(firmware, nanos_screens: int, nanoxsp_screens: int): + if firmware.device == 'nanos': + return [NavInsID.RIGHT_CLICK] * nanos_screens + [NavInsID.BOTH_CLICK] + elif firmware.device == 'nanox' or firmware.device == 'nanosp': + return [NavInsID.RIGHT_CLICK] * nanoxsp_screens + [NavInsID.BOTH_CLICK] + else: + assert False + +def get_stax_instructions(num_taps: int): + return [NavInsID.USE_CASE_REVIEW_TAP] * num_taps + [NavInsID.USE_CASE_REVIEW_CONFIRM, NavInsID.USE_CASE_STATUS_DISMISS] + +def test_send_ignis_tx(backend, navigator, firmware): + tx_bytes = "020000000000011d98fe090f006e0983e578fab84ab29c209182a8eff30a186fa84211da55a6a29fcc2b7e4a20eb6d36651b82d0eb00c2eb0b0000000000e1f505000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000191ee15a5fb74d1200000000000000000000000000000000000000000000000000000000000000000000000000000000" + expected_signature = "ad92efeb45e2d0866b22a20ad3bbc75b3fbcd63a32b451665857815598d13800404feca2d6f33730fae127ce89a2213e06afb9e8dbb44e06c7514cb56475e642" + if firmware.device == 'stax': + instructions = get_stax_instructions(3) + else: + instructions = get_nano_instructions(firmware, 7, 5) + _sign_tx_test(backend, navigator, tx_bytes, expected_signature, "test_send_ignis_tx", instructions) + +def test_send_ignis_tx_reject(backend, navigator, firmware): + tx_bytes = "020000000000011d98fe090f006e0983e578fab84ab29c209182a8eff30a186fa84211da55a6a29fcc2b7e4a20eb6d36651b82d0eb00c2eb0b0000000000e1f505000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000191ee15a5fb74d1200000000000000000000000000000000000000000000000000000000000000000000000000000000" + if firmware.device == 'stax': + instructions = [NavInsID.USE_CASE_REVIEW_TAP] * 3 + [NavInsID.USE_CASE_REVIEW_REJECT, NavInsID.USE_CASE_CHOICE_CONFIRM, NavInsID.USE_CASE_STATUS_DISMISS] + else: + instructions = get_nano_instructions(firmware, 8, 6) + _sign_tx_reject(backend, navigator, tx_bytes, "test_send_ignis_tx_reject", instructions) + +def test_send_ardr(backend, navigator, firmware): + tx_bytes = "01000000fe0001f944910a0f00a45834eef72000e08093cb1e23d9c873a9acea0a893bb02738bf8328ba1d076533ece497d15c7f343090b7000000000000e1f5050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0149e00d5eabea116ebc95800000000" + expected_signature = "65ee18432849dc797092287436cfb849f1ddf0f288c79f3cb99cb4dc754bac0c1e7dc2f5b6e1cc6542750954d2a5f0572a7fe721bd0bbf9d60f9336a85818ca4" + if firmware.device == 'stax': + instructions = get_stax_instructions(3) + else: + instructions = get_nano_instructions(firmware, 7, 5) + _sign_tx_test(backend, navigator, tx_bytes, expected_signature, "test_send_ardr", instructions, PATH_STR_1) + +def test_send_ignis_blind_accept(backend, navigator, firmware): + tx_bytes = "02000000000001887b9a0a0f00a45834eef72000e08093cb1e23d9c873a9acea0a893bb02738bf8328ba1d0765d33f5982ba1e78e080bf76080000000080f0fa020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0149e00d5eabea116ebc958080000000100d66f3134953b76b64b9ceae03fd2a2d858c7b73b7a50eeb901fb489ec387442c000000000000000000000000000000000000000000000000000000000000000000000000" + expected_signature = "c7c184571ab5515a20d2cff3d25ce58968ca37e6c63ef1b9817f9a7a4caca403071b9e7493aaea299a692d230efa5f367976d886f9c48e1abd091fd148b095c3" + if firmware.device == 'stax': + instructions = [NavInsID.USE_CASE_CHOICE_CONFIRM, # confirm enable blind signing + NavInsID.USE_CASE_STATUS_DISMISS, # dismiss confirmation screen + NavInsID.USE_CASE_REVIEW_TAP, # ack blind signing operation + NavInsID.USE_CASE_REVIEW_TAP, # ack tx signing operation + NavInsID.USE_CASE_REVIEW_TAP, # chain, amount, recipient + NavInsID.USE_CASE_REVIEW_TAP, # fees + NavInsID.USE_CASE_REVIEW_CONFIRM, # confirm tx signing operation + NavInsID.USE_CASE_STATUS_DISMISS] # dismiss confirmation screen + else: + enable_blind_signing(navigator) + instructions = get_nano_instructions(firmware, 9, 7) + _sign_tx_test(backend, navigator, tx_bytes, expected_signature, "test_send_ignis_blind_accept", + instructions, PATH_STR_1) + +def test_send_ignis_blind_reject(backend, navigator, firmware): + tx_bytes = "02000000000001887b9a0a0f00a45834eef72000e08093cb1e23d9c873a9acea0a893bb02738bf8328ba1d0765d33f5982ba1e78e080bf76080000000080f0fa020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0149e00d5eabea116ebc958080000000100d66f3134953b76b64b9ceae03fd2a2d858c7b73b7a50eeb901fb489ec387442c000000000000000000000000000000000000000000000000000000000000000000000000" + if firmware.device == 'stax': + instructions = [NavInsID.USE_CASE_CHOICE_REJECT, # reject blind signing + NavInsID.USE_CASE_CHOICE_CONFIRM, # confirm operation rejection + NavInsID.USE_CASE_STATUS_DISMISS] # dismiss confirmation screen + elif firmware.device == 'nanos': + instructions = [NavInsID.RIGHT_CLICK, NavInsID.BOTH_CLICK] + else: + instructions = [NavInsID.BOTH_CLICK] + _sign_tx_reject(backend, navigator, tx_bytes, "test_send_ignis_blind_reject", instructions) + +def test_send_ignis_blind_reject_tx(backend, navigator, firmware): + tx_bytes = "02000000000001887b9a0a0f00a45834eef72000e08093cb1e23d9c873a9acea0a893bb02738bf8328ba1d0765d33f5982ba1e78e080bf76080000000080f0fa020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0149e00d5eabea116ebc958080000000100d66f3134953b76b64b9ceae03fd2a2d858c7b73b7a50eeb901fb489ec387442c000000000000000000000000000000000000000000000000000000000000000000000000" + if firmware.device == 'stax': + instructions = [NavInsID.USE_CASE_CHOICE_CONFIRM, # confirm enable blind signing + NavInsID.USE_CASE_STATUS_DISMISS, # dismiss confirmation screen + NavInsID.USE_CASE_REVIEW_TAP, # ack blind signing operation + NavInsID.USE_CASE_REVIEW_TAP, # ack tx signing operation + NavInsID.USE_CASE_REVIEW_TAP, # chain, amount, recipient + NavInsID.USE_CASE_REVIEW_TAP, # fees + NavInsID.USE_CASE_REVIEW_REJECT, # reject tx signing operation + NavInsID.USE_CASE_CHOICE_CONFIRM, # ack rejection + NavInsID.USE_CASE_STATUS_DISMISS] # dismiss confirmation screen + else: + enable_blind_signing(navigator) + instructions = get_nano_instructions(firmware, 10, 8) + _sign_tx_reject(backend, navigator, tx_bytes, "test_send_ignis_blind_reject_tx", instructions) + +def test_ardor_coin_exchange(backend, navigator, firmware): + tx_bytes = "01000000fc0001ca81050a0f006e0983e578fab84ab29c209182a8eff30a186fa84211da55a6a29fcc2b7e4a200000000000000000000000000000000080f0fa02000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000191ee15a5fb74d12000000000101000000020000000084d7170000000080f0fa0200000000" + expected_signature = "c21135e4b982ff3af00185cab80f9aba1c5eaba8d2d9867e841123d3c2c17c0bb2bc3bc769e6714844751c105be64622f94efec668ca41d09b1524e3ee421747" + if firmware.device == 'stax': + instructions = get_stax_instructions(2) + else: + instructions = get_nano_instructions(firmware, 6, 5) + _sign_tx_test(backend, navigator, tx_bytes, expected_signature, "test_ardor_coin_exchange", instructions) + +def test_coin_exchange(backend, navigator, firmware): + tx_bytes = "020000000b0001a089050a0f006e0983e578fab84ab29c209182a8eff30a186fa84211da55a6a29fcc2b7e4a200000000000000000000000000000000000e1f505000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000191ee15a5fb74d120000000001020000000400000000c2eb0b0000000080d1f00800000000000000000000000000000000000000000000000000000000000000000000000000000000" + expected_signature = "26d36905267146675fc76c4ccac52242d0b8afc60007485386448f2bd1031c04f9819069ce6331248a55745643a2f2e4211d08cba0d50ba2de0284bca6125541" + if firmware.device == 'stax': + instructions = get_stax_instructions(2) + else: + instructions = get_nano_instructions(firmware, 6, 5) + _sign_tx_test(backend, navigator, tx_bytes, expected_signature, "test_coin_exchange", instructions) + +def test_asset_transfer(backend, navigator, firmware): + tx_bytes = "02000000020101ee8e050a0f006e0983e578fab84ab29c209182a8eff30a186fa84211da55a6a29fcc2b7e4a20eb6d36651b82d0eb000000000000000000e1f505000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000191ee15a5fb74d1200000000013ba0719534c294dcd007000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + expected_signature = "76aaddf7af7fc01f5dc925b3755e7c46072b13ce9a7d46c232711aaa932c6306b437fa833bee1535a0dadb34a8d1f6b5e2131a39086d4ccb80e5eceb028624e0" + if firmware.device == 'stax': + instructions = get_stax_instructions(3) + else: + instructions = get_nano_instructions(firmware, 9, 6) + _sign_tx_test(backend, navigator, tx_bytes, expected_signature, "test_asset_transfer", instructions) + +def test_send_ignis_4_attachments(backend, navigator, firmware): + tx_bytes = "020000000000018b07ef0a0f006e0983e578fab84ab29c209182a8eff30a186fa84211da55a6a29fcc2b7e4a20627a6c6937f5eaca00b108190000000000f8590d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0149e00d5eabea116ebc9586c0000000103300089e13a97c49b577a2e602d6ee422eebb37426af6f636fea77ef9968d0b6d890ef6744230f7c030975dc2b45cbdef080c8915cea2345e8cf14822ce90f6c994fe83e0ed79c1f7c0c88f5c694fac0e9d8d0100e7c3eb4eab23682b7e07aa780f63fe3986b326013c49c978cdc4e2b5d8b4e06301e288f39fdad8a465c30c8d9839e707718f4fde871c265cca5b6fea5938a4f91e012b2dd800000100000000000000000000000000000002d33f5982ba1e78e033ece497d15c7f34000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + expected_signature = "3552aaa5cdbf592f21eeee08480c06bb4f634f2b65f9947118623ea2c871bf074316566b2b7a27d8ed3e9f1b61aa6143ff4a2dbe3d16518d9056f0a97a64c053" + if firmware.device == 'stax': + instructions = [NavInsID.USE_CASE_CHOICE_CONFIRM, # confirm enable blind signing + NavInsID.USE_CASE_STATUS_DISMISS, # dismiss confirmation screen + NavInsID.USE_CASE_REVIEW_TAP, # ack blind signing operation + NavInsID.USE_CASE_REVIEW_TAP, # ack tx signing operation + NavInsID.USE_CASE_REVIEW_TAP, # chain, amount, recipient + NavInsID.USE_CASE_REVIEW_TAP, # fees + NavInsID.USE_CASE_REVIEW_CONFIRM, # confirm tx signing operation + NavInsID.USE_CASE_STATUS_DISMISS] # dismiss confirmation screen + else: + enable_blind_signing(navigator) + instructions = get_nano_instructions(firmware, 12, 8) + _sign_tx_test(backend, navigator, tx_bytes, expected_signature, "test_send_ignis_4_attachments", + instructions, PATH_STR_0) + +def test_send_ignis_referenced_tx(backend, navigator, firmware): + tx_bytes = "020000000000018d82f50a0f006e0983e578fab84ab29c209182a8eff30a186fa84211da55a6a29fcc2b7e4a20d33f5982ba1e78e000e1f50500000000a0bb0d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0149e00d5eabea116ebc95800000000020000008ab143bb8f366c938034bfeda9504625a0e5196eed5f2f19ef7388b2c28b0970" + expected_signature = "150f88bcb590b76a181bd8a0b02551e47a6c6b48445270ad1717353c87bafb07e5058a49212d0c66c89766f089e7af1fa6a4f6d66704ffccd65eeb1bac135fd0" + if firmware.device == 'stax': + instructions = [NavInsID.USE_CASE_CHOICE_CONFIRM, # confirm enable blind signing + NavInsID.USE_CASE_STATUS_DISMISS, # dismiss confirmation screen + NavInsID.USE_CASE_REVIEW_TAP, # ack blind signing operation + NavInsID.USE_CASE_REVIEW_TAP, # ack tx signing operation + NavInsID.USE_CASE_REVIEW_TAP, # chain, amount, recipient + NavInsID.USE_CASE_REVIEW_TAP, # fees + NavInsID.USE_CASE_REVIEW_CONFIRM, # confirm tx signing operation + NavInsID.USE_CASE_STATUS_DISMISS] # dismiss confirmation screen + else: + enable_blind_signing(navigator) + instructions = get_nano_instructions(firmware, 8, 6) + _sign_tx_test(backend, navigator, tx_bytes, expected_signature, "test_send_ignis_referenced_tx", + instructions, PATH_STR_0) + +def test_place_asset_exchange_order(backend, navigator, firmware): + tx_bytes = "02000000020201169bf50a0f006e0983e578fab84ab29c209182a8eff30a186fa84211da55a6a29fcc2b7e4a200000000000000000000000000000000080841e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0149e00d5eabea116ebc9580000000001813b83eafc58a13a030000000000000080de800200000000000000000000000000000000000000000000000000000000000000000000000000000000" + expected_signature = "2d0fcf25e6afb2015bde4f0d90d75cfeb718dbd80ef35d1adfca95d0b5e69c030349eb41a877bb0ca005ef2e67221d4592b3bc87c22cd3ee35c9c7092eed5055" + if firmware.device == 'stax': + instructions = get_stax_instructions(3) + else: + enable_blind_signing(navigator) + instructions = get_nano_instructions(firmware, 8, 6) + _sign_tx_test(backend, navigator, tx_bytes, expected_signature, "test_place_asset_exchange_order", + instructions, PATH_STR_0) \ No newline at end of file diff --git a/tests/test_encrypt_decrypt_message.py b/tests/test_encrypt_decrypt_message.py new file mode 100644 index 0000000..c5a1bb2 --- /dev/null +++ b/tests/test_encrypt_decrypt_message.py @@ -0,0 +1,120 @@ +from constants import CLA, RESPONSE_SUFFIX, PATH_STR_0, PATH_STR_3, PUBLIC_KEY_0, PUBLIC_KEY_3, R_SUCCESS +from ardor_command_sender import pack_derivation_path + +INS_ENCRYPT_DECRYPT_MSG = 0x04 +P1_ENCRYPTION_SETUP = 0x01 +P1_ENCRYPTION_DECRYPT_AND_HIDE_SHARED_KEY = 0x02 +P1_ENCRYPTION_DECRYPT_AND_RETURN_SHARED_KEY = 0x03 +P1_ENCRYPTION_PROCESS_DATA = 0x04 +MAX_BUFFER_SIZE = 224 + +def test_encrypt_decrypt_short_message(backend): + msg = "It was a bright cold day in April, and the clocks were striking thirteen." + + # pad message to modulus 16 + padded_msg = msg + " " * (16 - len(msg) % 16) + + rapdu = backend.exchange(cla=CLA, ins=INS_ENCRYPT_DECRYPT_MSG, p1=P1_ENCRYPTION_SETUP, data=pack_derivation_path(PATH_STR_0) + bytes.fromhex(PUBLIC_KEY_3)) + assert rapdu is not None + assert rapdu.status == RESPONSE_SUFFIX + assert rapdu.data[0] == R_SUCCESS + assert len(rapdu.data) == 1 + 32 + 16 # 1 byte return value, 32 bytes nonce, 16 bytes IV + nonce = rapdu.data[1:33] + iv = rapdu.data[33:] + + rapdu = backend.exchange(cla=CLA, ins=INS_ENCRYPT_DECRYPT_MSG, p1=P1_ENCRYPTION_PROCESS_DATA, data=padded_msg.encode()) + assert rapdu is not None + assert rapdu.status == RESPONSE_SUFFIX + assert rapdu.data[0] == R_SUCCESS + assert len(rapdu.data) == 1 + len(padded_msg) # 1 byte return value, encrypted message + encrypted_msg = rapdu.data[1:] + + assert encrypted_msg != padded_msg.encode() + + # now decrypt the message and check that it is the same as the original + rapdu = backend.exchange(cla=CLA, ins=INS_ENCRYPT_DECRYPT_MSG, p1=P1_ENCRYPTION_DECRYPT_AND_HIDE_SHARED_KEY, + data=pack_derivation_path(PATH_STR_3) + bytes.fromhex(PUBLIC_KEY_0) + nonce + iv) + assert rapdu is not None + assert rapdu.status == RESPONSE_SUFFIX + assert rapdu.data[0] == R_SUCCESS + assert len(rapdu.data) == 1 + + rapdu = backend.exchange(cla=CLA, ins=INS_ENCRYPT_DECRYPT_MSG, p1=P1_ENCRYPTION_PROCESS_DATA, data=encrypted_msg) + assert rapdu is not None + assert rapdu.status == RESPONSE_SUFFIX + assert rapdu.data[0] == R_SUCCESS + assert len(rapdu.data) == 1 + len(padded_msg) # 1 byte return value, decrypted message + decrypted_msg = rapdu.data[1:] + + assert decrypted_msg == padded_msg.encode() + +def test_encrypt_decrypt_long_message(backend): + msg = "It was a bright cold day in April, and the clocks were striking thirteen." * 100 + + # pad message to modulus 16 + padded_msg = msg + " " * (16 - len(msg) % 16) + + rapdu = backend.exchange(cla=CLA, ins=INS_ENCRYPT_DECRYPT_MSG, p1=P1_ENCRYPTION_SETUP, data=pack_derivation_path(PATH_STR_0) + bytes.fromhex(PUBLIC_KEY_3)) + assert rapdu is not None + assert rapdu.status == RESPONSE_SUFFIX + assert rapdu.data[0] == R_SUCCESS + assert len(rapdu.data) == 1 + 32 + 16 # 1 byte return value, 32 bytes nonce, 16 bytes IV + nonce = rapdu.data[1:33] + iv = rapdu.data[33:] + + # now send the message in chunks of max 224 bytes + encrypted_msg = b"" + for i in range(0, len(padded_msg), MAX_BUFFER_SIZE): + rapdu = backend.exchange(cla=CLA, ins=INS_ENCRYPT_DECRYPT_MSG, p1=P1_ENCRYPTION_PROCESS_DATA, data=padded_msg[i:i+224].encode()) + assert rapdu is not None + assert rapdu.status == RESPONSE_SUFFIX + assert rapdu.data[0] == R_SUCCESS + assert len(rapdu.data) == 1 + len(padded_msg[i:i+MAX_BUFFER_SIZE]) + encrypted_msg += rapdu.data[1:] + + assert encrypted_msg != padded_msg.encode() + + # now decrypt the message and check that it is the same as the original + rapdu = backend.exchange(cla=CLA, ins=INS_ENCRYPT_DECRYPT_MSG, p1=P1_ENCRYPTION_DECRYPT_AND_HIDE_SHARED_KEY, + data=pack_derivation_path(PATH_STR_3) + bytes.fromhex(PUBLIC_KEY_0) + nonce + iv) + assert rapdu is not None + assert rapdu.status == RESPONSE_SUFFIX + assert rapdu.data[0] == R_SUCCESS + assert len(rapdu.data) == 1 + + # now send the encrypted message in chunks of max 224 bytes + decrypted_msg = b"" + for i in range(0, len(encrypted_msg), MAX_BUFFER_SIZE): + rapdu = backend.exchange(cla=CLA, ins=INS_ENCRYPT_DECRYPT_MSG, p1=P1_ENCRYPTION_PROCESS_DATA, data=encrypted_msg[i:i+MAX_BUFFER_SIZE]) + assert rapdu is not None + assert rapdu.status == RESPONSE_SUFFIX + assert rapdu.data[0] == R_SUCCESS + assert len(rapdu.data) == 1 + len(encrypted_msg[i:i+MAX_BUFFER_SIZE]) + decrypted_msg += rapdu.data[1:] + + assert decrypted_msg == padded_msg.encode() + +def test_decrypt(backend): + encrypted_msg = bytes.fromhex("9799e0ff979fea62d80d5ddb1804af6b9104859ab8a29e3aabb63e2bb2b1aeaa931c39e42b9e3876598144914f11033ff6bfaecb1a938cd4e406180608d149d9b1c707610d4461695c49ecbf0871f53e") + nonce = bytes.fromhex("431ce6e00da428caa074d6ef315f89e2e85d7569b545bbbcad451f3ca4e81ee7") + iv = bytes.fromhex("0404c712a8efdc4863b2379411c176f9") + + rapdu = backend.exchange(cla=CLA, ins=INS_ENCRYPT_DECRYPT_MSG, p1=P1_ENCRYPTION_DECRYPT_AND_HIDE_SHARED_KEY, + data=pack_derivation_path(PATH_STR_3) + bytes.fromhex(PUBLIC_KEY_0) + nonce + iv) + assert rapdu is not None + assert rapdu.status == RESPONSE_SUFFIX + assert rapdu.data[0] == R_SUCCESS + assert len(rapdu.data) == 1 + + # now send the encrypted message in chunks of max 224 bytes + decrypted_msg = b"" + for i in range(0, len(encrypted_msg), MAX_BUFFER_SIZE): + rapdu = backend.exchange(cla=CLA, ins=INS_ENCRYPT_DECRYPT_MSG, p1=P1_ENCRYPTION_PROCESS_DATA, data=encrypted_msg[i:i+MAX_BUFFER_SIZE]) + assert rapdu is not None + assert rapdu.status == RESPONSE_SUFFIX + assert rapdu.data[0] == R_SUCCESS + assert len(rapdu.data) == 1 + len(encrypted_msg[i:i+MAX_BUFFER_SIZE]) + decrypted_msg += rapdu.data[1:] + + msg = "It was a bright cold day in April, and the clocks were striking thirteen. " + assert decrypted_msg.decode() == msg \ No newline at end of file diff --git a/tests/test_get_public_key.py b/tests/test_get_public_key.py new file mode 100644 index 0000000..dfc4c7b --- /dev/null +++ b/tests/test_get_public_key.py @@ -0,0 +1,21 @@ +from constants import CLA, RESPONSE_SUFFIX, PATH_STR_0, PATH_STR_3, PUBLIC_KEY_0, PUBLIC_KEY_3, R_SUCCESS +from ardor_command_sender import pack_derivation_path + +INS_GET_PUBLIC_KEY_AND_CHAIN_CODE = 0x06 +P1 = 0x01 + +def test_get_public_key0(backend): + rapdu = backend.exchange(cla=CLA, ins=INS_GET_PUBLIC_KEY_AND_CHAIN_CODE, p1=P1, data=pack_derivation_path(PATH_STR_0)) + assert rapdu is not None + assert rapdu.status == RESPONSE_SUFFIX + assert len(rapdu.data) == 1 + 32 # 1 byte return value, 32 bytes public key + assert rapdu.data[0] == R_SUCCESS + assert rapdu.data[1:].hex() == PUBLIC_KEY_0 + +def test_get_public_key3(backend): + rapdu = backend.exchange(cla=CLA, ins=INS_GET_PUBLIC_KEY_AND_CHAIN_CODE, p1=P1, data=pack_derivation_path(PATH_STR_3)) + assert rapdu is not None + assert rapdu.status == RESPONSE_SUFFIX + assert len(rapdu.data) == 1 + 32 # 1 byte return value, 32 bytes public key + assert rapdu.data[0] == R_SUCCESS + assert rapdu.data[1:].hex() == PUBLIC_KEY_3 diff --git a/tests/test_get_version.py b/tests/test_get_version.py new file mode 100644 index 0000000..1934b26 --- /dev/null +++ b/tests/test_get_version.py @@ -0,0 +1,8 @@ +from constants import CLA, RESPONSE_SUFFIX + +INS_GET_VERSION = 0x01 + +def test_get_version(backend): + rapdu = backend.exchange(cla=CLA, ins=INS_GET_VERSION) + assert rapdu.status == RESPONSE_SUFFIX + assert rapdu.data.hex() == "01010000babe00" \ No newline at end of file diff --git a/tests/test_show_address.py b/tests/test_show_address.py new file mode 100644 index 0000000..837e62b --- /dev/null +++ b/tests/test_show_address.py @@ -0,0 +1,23 @@ +from ardor_command_sender import ArdorCommandSender +from constants import PATH_STR_0, ROOT_SCREENSHOT_PATH, PATH_STR_3 +from ragger.navigator import NavInsID + +def show_address_test(backend, navigator, firmware, path, test_name): + if firmware.device == 'nanos': + instructions=[NavInsID.RIGHT_CLICK] * 2 + [NavInsID.BOTH_CLICK] + elif firmware.device == 'nanox' or firmware.device == 'nanosp': + instructions=[NavInsID.RIGHT_CLICK] * 1 + [NavInsID.BOTH_CLICK] + elif firmware.device == 'stax': + instructions=[NavInsID.USE_CASE_ADDRESS_CONFIRMATION_TAP, NavInsID.USE_CASE_ADDRESS_CONFIRMATION_CONFIRM] + else: + assert False + + client = ArdorCommandSender(backend) + with client.show_address(path): + navigator.navigate_and_compare(ROOT_SCREENSHOT_PATH, test_name, instructions) + +def test_show_address0(backend, navigator, firmware): + show_address_test(backend, navigator, firmware, PATH_STR_0, "test_show_address0") + +def test_show_address3(backend, navigator, firmware): + show_address_test(backend, navigator, firmware, PATH_STR_3, "test_show_address3") \ No newline at end of file diff --git a/tests/test_sign_token.py b/tests/test_sign_token.py new file mode 100644 index 0000000..935201e --- /dev/null +++ b/tests/test_sign_token.py @@ -0,0 +1,99 @@ +from ardor_command_sender import ArdorCommandSender +from constants import PATH_STR_0, R_SUCCESS, RESPONSE_SUFFIX, ROOT_SCREENSHOT_PATH, R_REJECT +from utils import enable_blind_signing + +from ragger.navigator import NavInsID + +def _send_token_for_signing(backend) -> ArdorCommandSender: + msg = "Token Data" + + client = ArdorCommandSender(backend) + rapdu = client.sign_token_init() + assert rapdu is not None + assert rapdu.status == RESPONSE_SUFFIX + assert len(rapdu.data) == 1 + assert rapdu.data[0] == R_SUCCESS + + rapdu = client.sign_token_send_bytes(msg.encode()) + assert rapdu is not None + assert rapdu.status == RESPONSE_SUFFIX + assert len(rapdu.data) == 1 + assert rapdu.data[0] == R_SUCCESS + return client + +def test_sign_token(backend, navigator, firmware): + timestamp = 167772040 + expected_token = "6e0983e578fab84ab29c209182a8eff30a186fa84211da55a6a29fcc2b7e4a2088ffff094b85d2d6ba9b42993f8d1cf585cd64d09be0632e1f303e3142a4421296683f055a1f816e7e414bf51389416659ff6ff32beee4b08d5d1ce299f43a448f6b9fb0" + + client = _send_token_for_signing(backend) + + if firmware.device == 'stax': + instructions = [NavInsID.USE_CASE_CHOICE_CONFIRM, # confirm enable blind signing + NavInsID.USE_CASE_STATUS_DISMISS, # dismiss confirmation screen + NavInsID.USE_CASE_REVIEW_TAP, # ack blind signing operation + NavInsID.USE_CASE_REVIEW_TAP, # ack token signing operation + NavInsID.USE_CASE_REVIEW_CONFIRM, # confirm token signing operation + NavInsID.USE_CASE_STATUS_DISMISS] # dismiss confirmation screen + else: + enable_blind_signing(navigator) + instructions = [NavInsID.RIGHT_CLICK, NavInsID.BOTH_CLICK] + + with client.sign_token_sign(PATH_STR_0, timestamp): + navigator.navigate_and_compare(ROOT_SCREENSHOT_PATH, "test_sign_token", instructions) + + rapdu = client.get_async_response() + assert rapdu is not None + assert rapdu.status == RESPONSE_SUFFIX + assert len(rapdu.data) == 1 + 100 + assert rapdu.data[0] == R_SUCCESS + assert rapdu.data[1:].hex() == expected_token + +def test_sign_token_reject_blind(backend, navigator, firmware): + timestamp = 167772040 + + client = _send_token_for_signing(backend) + + if firmware.device == 'stax': + instructions = [NavInsID.USE_CASE_CHOICE_REJECT, # reject blind signing + NavInsID.USE_CASE_CHOICE_CONFIRM, # confirm operation rejection + NavInsID.USE_CASE_STATUS_DISMISS] # dismiss confirmation screen + elif firmware.device == 'nanos': + instructions = [NavInsID.RIGHT_CLICK, NavInsID.BOTH_CLICK] + else: + instructions = [NavInsID.BOTH_CLICK] + + with client.sign_token_sign(PATH_STR_0, timestamp): + navigator.navigate_and_compare(ROOT_SCREENSHOT_PATH, "test_sign_token_reject_blind", instructions) + + rapdu = client.get_async_response() + assert rapdu is not None + assert rapdu.status == RESPONSE_SUFFIX + assert len(rapdu.data) == 2 + assert rapdu.data[0] == R_SUCCESS + assert rapdu.data[1] == R_REJECT + +def test_sign_token_reject_tx(backend, navigator, firmware): + timestamp = 167772040 + + client = _send_token_for_signing(backend) + + if firmware.device == 'stax': + instructions = [NavInsID.USE_CASE_CHOICE_CONFIRM, # confirm enable blind signing + NavInsID.USE_CASE_STATUS_DISMISS, # dismiss confirmation screen + NavInsID.USE_CASE_REVIEW_TAP, # ack blind signing operation + NavInsID.USE_CASE_REVIEW_TAP, # ack token signing operation + NavInsID.USE_CASE_CHOICE_REJECT, # reject token signing operation + NavInsID.USE_CASE_STATUS_DISMISS] # dismiss confirmation screen + else: + enable_blind_signing(navigator) + instructions = [NavInsID.RIGHT_CLICK, NavInsID.RIGHT_CLICK, NavInsID.BOTH_CLICK] + + with client.sign_token_sign(PATH_STR_0, timestamp): + navigator.navigate_and_compare(ROOT_SCREENSHOT_PATH, "test_sign_token_reject_tx", instructions) + + rapdu = client.get_async_response() + assert rapdu is not None + assert rapdu.status == RESPONSE_SUFFIX + assert len(rapdu.data) == 2 + assert rapdu.data[0] == R_SUCCESS + assert rapdu.data[1] == R_REJECT \ No newline at end of file diff --git a/tests/utils.py b/tests/utils.py new file mode 100644 index 0000000..9b051bb --- /dev/null +++ b/tests/utils.py @@ -0,0 +1,6 @@ +from ragger.navigator import NavInsID + +def enable_blind_signing(navigator): + navigator.navigate([NavInsID.RIGHT_CLICK, NavInsID.BOTH_CLICK, NavInsID.BOTH_CLICK, + NavInsID.RIGHT_CLICK, NavInsID.BOTH_CLICK, NavInsID.RIGHT_CLICK, + NavInsID.BOTH_CLICK], screen_change_before_first_instruction=False) \ No newline at end of file