From b950581f020faa6e0693d05c01a0038eea9fddb1 Mon Sep 17 00:00:00 2001 From: Ariel Mendelzon Date: Sat, 25 Jan 2025 08:48:42 +1300 Subject: [PATCH] Common modules linking approach change (#283) - Renamed hal/common to hal/common_linked - Moved HAL common modules in x86 to common_linked - Added HAL ledger symlinks to common_linked - Added HAL x86 symlinks to common_linked - Removed HAL sgx trusted symlinks to x86 - Added HAL sgx trusted symlinks to common_linked - Moved bip32 tests from x86 to common_linked - Moved endian tests from x86 to common_linked - Moved hmac_sha512 tests from x86 to common_linked - Moved keccak256 tests from x86 to common_linked - Added common test artifacts to common_linked - Renamed common to common_linked in CI workflow - Incidentally fixed compiler warning in Ledger UI onboarding test case - Removed unused test helpers --- .github/workflows/run-tests.yml | 2 +- firmware/src/hal/common_linked/src/bip32.c | 267 ++++++++++++ firmware/src/hal/common_linked/src/bip32.h | 65 +++ .../src/communication.c | 0 firmware/src/hal/common_linked/src/endian.c | 77 ++++ firmware/src/hal/common_linked/src/endian.h | 72 ++++ .../src/hal/common_linked/src/exceptions.c | 51 +++ firmware/src/hal/common_linked/src/hash.c | 84 ++++ .../src/hal/common_linked/src/hmac_sha512.c | 397 +++++++++++++++++ .../src/hal/common_linked/src/hmac_sha512.h | 77 ++++ .../src/hal/common_linked/src/keccak256.c | 267 ++++++++++++ .../src/hal/common_linked/src/keccak256.h | 81 ++++ .../{common => common_linked}/src/sha256.c | 0 .../{common => common_linked}/src/sha256.h | 0 .../test/bip32/Makefile | 0 .../test/bip32/test_bip32.c | 0 .../test/bip32/test_bip32_derivation.c | 0 .../{common => common_linked}/test/common.mk | 0 .../hal/common_linked/test/common/common.mk | 35 ++ .../src/hal/common_linked/test/common/log.c | 48 +++ .../test/common/test_helpers.c | 0 .../test/common/test_helpers.h | 0 .../test/endian/Makefile | 0 .../test/endian/test_endian.c | 0 .../test/hmac_sha512/HMAC.rsp | 0 .../test/hmac_sha512/Makefile | 0 .../test/hmac_sha512/test_hmac_sha512.c | 0 .../test/keccak256/Makefile | 0 .../test/keccak256/test_keccak256.c | 0 .../{common => common_linked}/test/run-all.sh | 2 +- .../test/sha256/Makefile | 0 .../test/sha256/test_sha256.c | 0 firmware/src/hal/ledger/src/communication.c | 2 +- firmware/src/hal/ledger/src/sha256.c | 2 +- firmware/src/hal/ledger/src/sha256.h | 2 +- firmware/src/hal/sgx/src/trusted/bip32.c | 2 +- firmware/src/hal/sgx/src/trusted/bip32.h | 2 +- .../src/hal/sgx/src/trusted/communication.c | 2 +- firmware/src/hal/sgx/src/trusted/endian.c | 2 +- firmware/src/hal/sgx/src/trusted/endian.h | 2 +- firmware/src/hal/sgx/src/trusted/exceptions.c | 2 +- firmware/src/hal/sgx/src/trusted/hash.c | 2 +- .../src/hal/sgx/src/trusted/hmac_sha512.c | 2 +- .../src/hal/sgx/src/trusted/hmac_sha512.h | 2 +- firmware/src/hal/sgx/src/trusted/keccak256.c | 2 +- firmware/src/hal/sgx/src/trusted/keccak256.h | 2 +- firmware/src/hal/sgx/src/trusted/sha256.c | 2 +- firmware/src/hal/sgx/src/trusted/sha256.h | 2 +- firmware/src/hal/x86/src/bip32.c | 268 +----------- firmware/src/hal/x86/src/bip32.h | 66 +-- firmware/src/hal/x86/src/communication.c | 2 +- firmware/src/hal/x86/src/endian.c | 78 +--- firmware/src/hal/x86/src/endian.h | 73 +--- firmware/src/hal/x86/src/exceptions.c | 52 +-- firmware/src/hal/x86/src/hash.c | 85 +--- firmware/src/hal/x86/src/hmac_sha512.c | 398 +----------------- firmware/src/hal/x86/src/hmac_sha512.h | 78 +--- firmware/src/hal/x86/src/keccak256.c | 268 +----------- firmware/src/hal/x86/src/keccak256.h | 82 +--- firmware/src/hal/x86/src/sha256.c | 2 +- firmware/src/hal/x86/src/sha256.h | 2 +- firmware/src/hal/x86/test/run-all.sh | 2 +- .../src/ledger/ui/test/onboard/test_onboard.c | 2 +- 63 files changed, 1554 insertions(+), 1461 deletions(-) create mode 100644 firmware/src/hal/common_linked/src/bip32.c create mode 100644 firmware/src/hal/common_linked/src/bip32.h rename firmware/src/hal/{common => common_linked}/src/communication.c (100%) create mode 100644 firmware/src/hal/common_linked/src/endian.c create mode 100644 firmware/src/hal/common_linked/src/endian.h create mode 100644 firmware/src/hal/common_linked/src/exceptions.c create mode 100644 firmware/src/hal/common_linked/src/hash.c create mode 100644 firmware/src/hal/common_linked/src/hmac_sha512.c create mode 100644 firmware/src/hal/common_linked/src/hmac_sha512.h create mode 100644 firmware/src/hal/common_linked/src/keccak256.c create mode 100644 firmware/src/hal/common_linked/src/keccak256.h rename firmware/src/hal/{common => common_linked}/src/sha256.c (100%) rename firmware/src/hal/{common => common_linked}/src/sha256.h (100%) rename firmware/src/hal/{x86 => common_linked}/test/bip32/Makefile (100%) rename firmware/src/hal/{x86 => common_linked}/test/bip32/test_bip32.c (100%) rename firmware/src/hal/{x86 => common_linked}/test/bip32/test_bip32_derivation.c (100%) rename firmware/src/hal/{common => common_linked}/test/common.mk (100%) create mode 100644 firmware/src/hal/common_linked/test/common/common.mk create mode 100644 firmware/src/hal/common_linked/test/common/log.c rename firmware/src/hal/{x86 => common_linked}/test/common/test_helpers.c (100%) rename firmware/src/hal/{x86 => common_linked}/test/common/test_helpers.h (100%) rename firmware/src/hal/{x86 => common_linked}/test/endian/Makefile (100%) rename firmware/src/hal/{x86 => common_linked}/test/endian/test_endian.c (100%) rename firmware/src/hal/{x86 => common_linked}/test/hmac_sha512/HMAC.rsp (100%) rename firmware/src/hal/{x86 => common_linked}/test/hmac_sha512/Makefile (100%) rename firmware/src/hal/{x86 => common_linked}/test/hmac_sha512/test_hmac_sha512.c (100%) rename firmware/src/hal/{x86 => common_linked}/test/keccak256/Makefile (100%) rename firmware/src/hal/{x86 => common_linked}/test/keccak256/test_keccak256.c (100%) rename firmware/src/hal/{common => common_linked}/test/run-all.sh (90%) rename firmware/src/hal/{common => common_linked}/test/sha256/Makefile (100%) rename firmware/src/hal/{common => common_linked}/test/sha256/test_sha256.c (100%) mode change 100644 => 120000 firmware/src/hal/x86/src/bip32.c mode change 100644 => 120000 firmware/src/hal/x86/src/bip32.h mode change 100644 => 120000 firmware/src/hal/x86/src/endian.c mode change 100644 => 120000 firmware/src/hal/x86/src/endian.h mode change 100644 => 120000 firmware/src/hal/x86/src/exceptions.c mode change 100644 => 120000 firmware/src/hal/x86/src/hash.c mode change 100644 => 120000 firmware/src/hal/x86/src/hmac_sha512.c mode change 100644 => 120000 firmware/src/hal/x86/src/hmac_sha512.h mode change 100644 => 120000 firmware/src/hal/x86/src/keccak256.c mode change 100644 => 120000 firmware/src/hal/x86/src/keccak256.h diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index f30ddb74..5e4d9375 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -27,7 +27,7 @@ jobs: run: firmware/test/test-all - name: Firmware HAL's common unit tests - run: firmware/src/hal/common/test/run-all.sh + run: firmware/src/hal/common_linked/test/run-all.sh - name: Firmware HAL's x86 unit tests run: firmware/src/hal/x86/test/run-all.sh diff --git a/firmware/src/hal/common_linked/src/bip32.c b/firmware/src/hal/common_linked/src/bip32.c new file mode 100644 index 00000000..e3c25545 --- /dev/null +++ b/firmware/src/hal/common_linked/src/bip32.c @@ -0,0 +1,267 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2021 RSK Labs Ltd + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "bip32.h" +#include "hal/constants.h" +#include "hal/log.h" +#include "hmac_sha512.h" +#include "endian.h" +#include "bigdigits.h" +#include "bigdigits_helper.h" + +#include +#include +#include +#include +#include + +#define BIP32_PREFIX "m/" +#define MIN_PATH_LENGTH (strlen("m/0/0/0/0/0")) +#define MAX_PART_DECIMAL_DIGITS 10 +#define EXPECTED_PARTS BIP32_PATH_NUMPARTS +#define NODE_LENGTH 64 + +#ifdef DEBUG_BIP32 +#define DEBUG_LOG(...) LOG(__VA_ARGS__) +#else +#define DEBUG_LOG(...) +#endif + +static const uint8_t secp256k1_order[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xfe, 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, + 0xa0, 0x3b, 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x41}; + +static secp256k1_context* sp_ctx = NULL; + +size_t bip32_parse_path(const char* path, uint8_t* out) { + size_t pos, start, pathlen; + int parts; + int index; + bool number; + char indexstr[MAX_PART_DECIMAL_DIGITS + 1]; + uint32_t indexint; + + if (strlen(path) < MIN_PATH_LENGTH) { + DEBUG_LOG("BIP32 path too short: %s\n", path); + return 0; + } + + if (strncmp(path, BIP32_PREFIX, strlen(BIP32_PREFIX))) { + DEBUG_LOG("Bad prefix for path: %s\n", path); + return 0; + } + + parts = 0; + pathlen = strlen(path); + pos = strlen(BIP32_PREFIX); + start = pos; + index = 0; + number = true; + while (pos < pathlen) { + if (number && path[pos] >= '0' && path[pos] <= '9') { + pos++; + if (pos - start > MAX_PART_DECIMAL_DIGITS) { + DEBUG_LOG("Path part %d too long for path: %s\n", parts, path); + return 0; + } + } else if (number && path[pos] == '\'') { + number = false; + index = 0x80000000; + pos++; + } else if (path[pos] != '/') { + DEBUG_LOG( + "Unexpected path character: %c for path %s\n", path[pos], path); + return 0; + } + + if (pos == pathlen || path[pos] == '/') { + // Compute the index + memcpy(indexstr, path + start, pos - start); + indexstr[pos - start] = '\0'; + indexint = (uint32_t)atol(indexstr); + if (indexint >= 0x80000000) { + DEBUG_LOG("Path part %d needs to be between 0 and 2^31-1 for " + "path: %s\n", + parts, + path); + return 0; + } + index += indexint; + // Output the index in LE + for (int i = 0; i < (int)sizeof(uint32_t); i++) { + out[1 + (parts * sizeof(uint32_t)) + i] = + (index >> (8 * i)) & 0xFF; + } + // Next! + parts++; + index = 0; + number = true; + start = ++pos; + if (parts == EXPECTED_PARTS) { + if (pos < pathlen) { + DEBUG_LOG("Path has too many parts: %s\n", path); + return 0; + } + out[0] = (char)parts; + return 1 + parts * sizeof(uint32_t); + } + } + } + + DEBUG_LOG("Unexpected code path reached for path: %s\n", path); + return 0; +} + +/** + * Following portion taken from + * https://github.com/someone42/hardware-bitcoin-wallet @ + * 102c300d994712484c3c028b215f90a6f99d6155 and adapted for use with + * the powHSM HAL by RootstockLabs. LICENSE transcribed below. + */ + +/* + Copyright (c) 2011-2012 someone42 + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER 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. +*/ + +#define PRIVATE_KEY_DIGITS (PRIVATE_KEY_LENGTH / sizeof(DIGIT_T)) + +static void seed_to_node(uint8_t* master_node, + const uint8_t* seed, + const unsigned int seed_length) { + hmac_sha512( + master_node, (const uint8_t*)"Bitcoin seed", 12, seed, seed_length); +} + +bool bip32_derive_private(uint8_t* out, + const uint8_t* seed, + const unsigned int seed_length, + const uint32_t* path, + const unsigned int path_length) { + uint8_t current_node[NODE_LENGTH]; + uint8_t temp[NODE_LENGTH]; + DIGIT_T tempbig_a[PRIVATE_KEY_DIGITS + 1], + tempbig_b[PRIVATE_KEY_DIGITS + 1]; + DIGIT_T tempbig_c[PRIVATE_KEY_DIGITS + 1], + tempbig_d[PRIVATE_KEY_DIGITS + 1]; + uint8_t hmac_data[1 + 32 + 4]; // prefix + private key + i + secp256k1_pubkey pubkey; + size_t pubkey_serialised_size; + + // Init the secp256k1 context + if (!sp_ctx) + sp_ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN); + + // Compute the master node from the seed + seed_to_node(current_node, seed, seed_length); + + for (unsigned int i = 0; i < path_length; i++) { + if (path[i] & 0x80000000) { + // Hardened derivation. + hmac_data[0] = 0x00; + memcpy(&hmac_data[1], current_node, 32); + } else { + // Non-hardened derivation. + if (!secp256k1_ec_pubkey_create(sp_ctx, &pubkey, current_node)) { + DEBUG_LOG("Error deriving public key from private key\n"); + return false; + } + + pubkey_serialised_size = PUBKEY_CMP_LENGTH; + secp256k1_ec_pubkey_serialize(sp_ctx, + hmac_data, + &pubkey_serialised_size, + &pubkey, + SECP256K1_EC_COMPRESSED); + + if (pubkey_serialised_size != PUBKEY_CMP_LENGTH) { + DEBUG_LOG("Unexpected serialised public key size\n"); + return false; + } + } + write_uint32_be(&hmac_data[33], path[i]); + + // Need to write to temp here (instead of current_node) because part of + // current_node is used as the key. + hmac_sha512(temp, ¤t_node[32], 32, hmac_data, sizeof(hmac_data)); + + // First 32 bytes of temp = I_L. Compute k_i + if (!secp256k1_ec_seckey_verify(sp_ctx, temp)) { + DEBUG_LOG( + "Overflow during derivation, use a different one (I_L)\n"); + return false; + } + parse_bigint_be(temp, 32, tempbig_a, PRIVATE_KEY_DIGITS + 1); + + if (!secp256k1_ec_seckey_verify(sp_ctx, current_node)) { + DEBUG_LOG("Invalid key during derivation, use a different path " + "(invalid k_par)\n"); + return false; + } + parse_bigint_be(current_node, 32, tempbig_b, PRIVATE_KEY_DIGITS + 1); + + mpAdd(tempbig_a, tempbig_a, tempbig_b, PRIVATE_KEY_DIGITS + 1); + parse_bigint_be(secp256k1_order, 32, tempbig_b, PRIVATE_KEY_DIGITS + 1); + mpDivide(tempbig_d, + tempbig_c, + tempbig_a, + PRIVATE_KEY_DIGITS + 1, + tempbig_b, + PRIVATE_KEY_DIGITS + 1); + dump_bigint_be(current_node, tempbig_c, PRIVATE_KEY_DIGITS); + if (!secp256k1_ec_seckey_verify(sp_ctx, current_node)) { + DEBUG_LOG( + "Invalid derived key, use a different path (invalid k_i)\n"); + return false; + } + + // Last 32 bytes = I_R = c_i + memcpy(¤t_node[32], &temp[32], 32); + } + memcpy(out, current_node, 32); + return true; // success +} diff --git a/firmware/src/hal/common_linked/src/bip32.h b/firmware/src/hal/common_linked/src/bip32.h new file mode 100644 index 00000000..a80bafef --- /dev/null +++ b/firmware/src/hal/common_linked/src/bip32.h @@ -0,0 +1,65 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2021 RSK Labs Ltd + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef __HAL_BIP32_H +#define __HAL_BIP32_H + +#include +#include +#include + +#include "hal/constants.h" + +#define BIP32_PATH_PART_LENGTH (sizeof(uint32_t)) +#define BIP32_PATH_LENGTH (1 + BIP32_PATH_NUMPARTS * BIP32_PATH_PART_LENGTH) + +/** + * @brief Parse the given string representation of a bip32 path + * into binary format + * + * @param path the bip32 path as string + * @param out the destination buffer for the parsed path + * + * @returns the size of the parsed path in bytes, or zero in case of error + */ +size_t bip32_parse_path(const char* path, uint8_t* out); + +/** + * @brief Derive a private key from the given seed and bip32 path + * + * @param out the destination buffer for the derived key + * @param seed the seed to use for derivation + * @param seed_length the seed length in bytes + * @param path the bip32 path + * @param path_length the bip32 path length in derivation steps + * + * @returns whether derivation succeeded + */ +bool bip32_derive_private(uint8_t* out, + const uint8_t* seed, + const unsigned int seed_length, + const uint32_t* path, + const unsigned int path_length); + +#endif // __HAL_BIP32_H diff --git a/firmware/src/hal/common/src/communication.c b/firmware/src/hal/common_linked/src/communication.c similarity index 100% rename from firmware/src/hal/common/src/communication.c rename to firmware/src/hal/common_linked/src/communication.c diff --git a/firmware/src/hal/common_linked/src/endian.c b/firmware/src/hal/common_linked/src/endian.c new file mode 100644 index 00000000..2d72da7f --- /dev/null +++ b/firmware/src/hal/common_linked/src/endian.c @@ -0,0 +1,77 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2021 RSK Labs Ltd + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +/** + * Taken from https://github.com/someone42/hardware-bitcoin-wallet @ + * 102c300d994712484c3c028b215f90a6f99d6155 and adapted for use with + * the powHSM HAL by RootstockLabs. LICENSE transcribed below. + */ + +/* + Copyright (c) 2011-2012 someone42 + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER 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. +*/ + +/** \file endian.c + * + * \brief Contains functions which perform endian-specific type conversion. + * + * This file is licensed as described by the file LICENCE. + */ + +#include "endian.h" + +/** Write 32 bit unsigned integer into a byte array in big-endian format. + * \param out The destination byte array. This must have space for at + * least 4 bytes. + * \param in The source integer. + */ +void write_uint32_be(uint8_t *out, uint32_t in) { + out[0] = (uint8_t)(in >> 24); + out[1] = (uint8_t)(in >> 16); + out[2] = (uint8_t)(in >> 8); + out[3] = (uint8_t)in; +} diff --git a/firmware/src/hal/common_linked/src/endian.h b/firmware/src/hal/common_linked/src/endian.h new file mode 100644 index 00000000..7e982d81 --- /dev/null +++ b/firmware/src/hal/common_linked/src/endian.h @@ -0,0 +1,72 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2021 RSK Labs Ltd + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +/** + * Taken from https://github.com/someone42/hardware-bitcoin-wallet @ + * 102c300d994712484c3c028b215f90a6f99d6155 and adapted for use with + * the powHSM HAL by RootstockLabs. LICENSE transcribed below. + */ + +/* + Copyright (c) 2011-2012 someone42 + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER 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. +*/ + +#ifndef __HAL_ENDIAN_H +#define __HAL_ENDIAN_H + +#include + +/** + * @brief Dump the given 32-bit unsigned integer + * into the given buffer as big-endian + * + * @param out the destination buffer + * @param in the unsigned integer to dump + */ +void write_uint32_be(uint8_t *out, uint32_t in); + +#endif // #ifndef __HAL_ENDIAN_H diff --git a/firmware/src/hal/common_linked/src/exceptions.c b/firmware/src/hal/common_linked/src/exceptions.c new file mode 100644 index 00000000..e114bbba --- /dev/null +++ b/firmware/src/hal/common_linked/src/exceptions.c @@ -0,0 +1,51 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2021 RSK Labs Ltd + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +/***************************************************************************** + * Ledger Nano S - Secure firmware + * (c) 2016, 2017 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************/ + +/** + * Modified try...catch exception implementation (taken from nanos-secure-sdk) + * (https://github.com/LedgerHQ/nanos-secure-sdk/blob/nanos-1314/include/os.h) + */ + +#include "hal/exceptions.h" + +static try_context_t G_try_last_open_context_var; + +try_context_t* G_try_last_open_context = &G_try_last_open_context_var; diff --git a/firmware/src/hal/common_linked/src/hash.c b/firmware/src/hal/common_linked/src/hash.c new file mode 100644 index 00000000..4dff8843 --- /dev/null +++ b/firmware/src/hal/common_linked/src/hash.c @@ -0,0 +1,84 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2021 RSK Labs Ltd + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "hal/hash.h" + +// *** sha256 *** +bool hash_sha256_init(hash_sha256_ctx_t* ctx) { + sha256_init(ctx); + return true; +} + +bool hash_sha256_update(hash_sha256_ctx_t* ctx, + const uint8_t* data, + size_t len) { + sha256_update(ctx, data, len); + return true; +} + +bool hash_sha256_final(hash_sha256_ctx_t* ctx, uint8_t* out_hash) { + sha256_final(ctx, out_hash); + return true; +} + +// *** sha256 with midstate support *** +bool hash_sha256_ms_init(hash_sha256_ms_ctx_t* ctx) { + sha256_init(ctx); + return true; +} + +bool hash_sha256_ms_midstate(hash_sha256_ms_ctx_t* ctx, uint8_t* midstate) { + sha256_midstate(ctx, midstate); + return true; +} + +bool hash_sha256_ms_update(hash_sha256_ms_ctx_t* ctx, + const uint8_t* data, + size_t len) { + sha256_update(ctx, data, len); + return true; +} + +bool hash_sha256_ms_final(hash_sha256_ms_ctx_t* ctx, uint8_t* out_hash) { + sha256_final(ctx, out_hash); + return true; +} + +// *** keccak256 *** +bool hash_keccak256_init(hash_keccak256_ctx_t* ctx) { + keccak_init(ctx); + return true; +} + +bool hash_keccak256_update(hash_keccak256_ctx_t* ctx, + const uint8_t* data, + size_t len) { + keccak_update(ctx, data, len); + return true; +} + +bool hash_keccak256_final(hash_keccak256_ctx_t* ctx, uint8_t* out_hash) { + keccak_final(ctx, out_hash); + return true; +} \ No newline at end of file diff --git a/firmware/src/hal/common_linked/src/hmac_sha512.c b/firmware/src/hal/common_linked/src/hmac_sha512.c new file mode 100644 index 00000000..aaf9a121 --- /dev/null +++ b/firmware/src/hal/common_linked/src/hmac_sha512.c @@ -0,0 +1,397 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2021 RSK Labs Ltd + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +/** + * Taken from https://github.com/someone42/hardware-bitcoin-wallet @ + * 102c300d994712484c3c028b215f90a6f99d6155 and adapted for use with + * the powHSM HAL by RootstockLabs. LICENSE transcribed below. + */ + +/* + Copyright (c) 2011-2012 someone42 + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER 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. +*/ + +/** \file hmac_sha512.c + * + * \brief Calculates HMAC-SHA512 hashes. + * + * This file contains an implementation of SHA-512, as well as a wrapper + * around the SHA-512 implementation which converts it into a keyed + * message authentication code. + * + * The SHA-512 implementation is based on the formulae and pseudo-code in + * FIPS PUB 180-4. The HMAC wrapper is based on the pseudo-code in + * FIPS PUB 198. + * + * Since SHA-512 is based on 64 bit operations, the code in sha256.c and + * hash.c cannot be re-used here, despite the essentially identical structure + * of SHA-256 and SHA-512. + */ + +#include "endian.h" +#include "hmac_sha512.h" + +#include +#include +#include +#include + +/** Get maximum of a and b. + * \warning Do not use this if the evaluation of a and b has side effects. + */ +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) +/** Get minimum of a and b. + * \warning Do not use this if the evaluation of a and b has side effects. + */ +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) + +#define NOINLINE + +#define PROGMEM +/** Use this to access #PROGMEM lookup tables which have dword (32 bit) + * entries. For example, normally you would use `r = dword_table[i];` but + * for a #PROGMEM table, use `r = LOOKUP_DWORD(dword_table[i]);`. */ +#define LOOKUP_DWORD(x) (x) +/** Use this to access #PROGMEM lookup tables which have byte (8 bit) + * entries. For example, normally you would use `r = byte_table[i];` but + * for a #PROGMEM table, use `r = LOOKUP_BYTE(byte_table[i]);`. */ +#define LOOKUP_BYTE(x) (x) +/** Use this to access #PROGMEM lookup tables which have qword (64 bit) + * entries. For example, normally you would use `r = qword_table[i];` but + * for a #PROGMEM table, use `r = LOOKUP_QWORD(qword_table[i]);`. */ +#define LOOKUP_QWORD(x) (x) + +/** Container for 64 bit hash state. */ +typedef struct HashState64Struct { + /** Where final hash value will be placed. */ + uint64_t h[8]; + /** Current index into HashState64#m, ranges from 0 to 15. */ + uint8_t index_m; + /** Current byte within (64 bit) double word of HashState64#m. 0 = most + * significant byte, 7 = least significant byte. */ + uint8_t byte_position_m; + /** 1024 bit message buffer. */ + uint64_t m[16]; + /** Total length of message; updated as bytes are written. */ + uint32_t message_length; +} HashState64; + +/** Constants for SHA-512. See section 4.2.3 of FIPS PUB 180-4. */ +static const uint64_t k[80] PROGMEM = { + 0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, + 0xe9b5dba58189dbbc, 0x3956c25bf348b538, 0x59f111f1b605d019, + 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, 0xd807aa98a3030242, + 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2, + 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235, + 0xc19bf174cf692694, 0xe49b69c19ef14ad2, 0xefbe4786384f25e3, + 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65, 0x2de92c6f592b0275, + 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5, + 0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f, + 0xbf597fc7beef0ee4, 0xc6e00bf33da88fc2, 0xd5a79147930aa725, + 0x06ca6351e003826f, 0x142929670a0e6e70, 0x27b70a8546d22ffc, + 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df, + 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, + 0x92722c851482353b, 0xa2bfe8a14cf10364, 0xa81a664bbc423001, + 0xc24b8b70d0f89791, 0xc76c51a30654be30, 0xd192e819d6ef5218, + 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8, + 0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99, + 0x34b0bcb5e19b48a8, 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, + 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3, 0x748f82ee5defb2fc, + 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec, + 0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, + 0xc67178f2e372532b, 0xca273eceea26619c, 0xd186b8c721c0c207, + 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, 0x06f067aa72176fba, + 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b, + 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, + 0x431d67c49c100d4c, 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, + 0x5fcb6fab3ad6faec, 0x6c44198c4a475817}; + +/** 64 bit rotate right. + * \param x The integer to rotate right. + * \param n Number of times to rotate right. + * \return The rotated integer. + */ +static uint64_t rotateRight(const uint64_t x, const uint8_t n) { + return (x >> n) | (x << (64 - n)); +} + +/** Function defined as (4.8) in section 4.1.3 of FIPS PUB 180-4. + * \param x First input integer. + * \param y Second input integer. + * \param z Third input integer. + * \return Non-linear combination of x, y and z. + */ +static uint64_t ch(const uint64_t x, const uint64_t y, const uint64_t z) { + return (x & y) ^ ((~x) & z); +} + +/** Function defined as (4.9) in section 4.1.3 of FIPS PUB 180-4. + * \param x First input integer. + * \param y Second input integer. + * \param z Third input integer. + * \return Non-linear combination of x, y and z. + */ +static uint64_t maj(const uint64_t x, const uint64_t y, const uint64_t z) { + return (x & y) ^ (x & z) ^ (y & z); +} + +/** Function defined as (4.10) in section 4.1.3 of FIPS PUB 180-4. + * \param x Input integer. + * \return Transformed integer. + */ +static uint64_t bigSigma0(const uint64_t x) { + return rotateRight(x, 28) ^ rotateRight(x, 34) ^ rotateRight(x, 39); +} + +/** Function defined as (4.11) in section 4.1.3 of FIPS PUB 180-4. + * \param x Input integer. + * \return Transformed integer. + */ +static uint64_t bigSigma1(const uint64_t x) { + return rotateRight(x, 14) ^ rotateRight(x, 18) ^ rotateRight(x, 41); +} + +/** Function defined as (4.12) in section 4.1.3 of FIPS PUB 180-4. + * \param x Input integer. + * \return Transformed integer. + */ +static uint64_t littleSigma0(const uint64_t x) { + return rotateRight(x, 1) ^ rotateRight(x, 8) ^ (x >> 7); +} + +/** Function defined as (4.13) in section 4.1.3 of FIPS PUB 180-4. + * \param x Input integer. + * \return Transformed integer. + */ +static uint64_t littleSigma1(const uint64_t x) { + return rotateRight(x, 19) ^ rotateRight(x, 61) ^ (x >> 6); +} + +/** Update hash value based on the contents of a full message buffer. + * This implements the pseudo-code in section 6.4.2 of FIPS PUB 180-4. + * \param hs64 The 64 bit hash state to update. + */ +static void sha512Block(HashState64 *hs64) { + uint64_t a, b, c, d, e, f, g, h; + uint64_t t1, t2; + uint8_t t; + uint64_t w[80]; + + for (t = 0; t < 16; t++) { + w[t] = hs64->m[t]; + } + for (t = 16; t < 80; t++) { + w[t] = littleSigma1(w[t - 2]) + w[t - 7] + littleSigma0(w[t - 15]) + + w[t - 16]; + } + a = hs64->h[0]; + b = hs64->h[1]; + c = hs64->h[2]; + d = hs64->h[3]; + e = hs64->h[4]; + f = hs64->h[5]; + g = hs64->h[6]; + h = hs64->h[7]; + for (t = 0; t < 80; t++) { + t1 = h + bigSigma1(e) + ch(e, f, g) + LOOKUP_QWORD(k[t]) + w[t]; + t2 = bigSigma0(a) + maj(a, b, c); + h = g; + g = f; + f = e; + e = d + t1; + d = c; + c = b; + b = a; + a = t1 + t2; + } + hs64->h[0] += a; + hs64->h[1] += b; + hs64->h[2] += c; + hs64->h[3] += d; + hs64->h[4] += e; + hs64->h[5] += f; + hs64->h[6] += g; + hs64->h[7] += h; +} + +/** Clear the message buffer. + * \param hs64 The 64 bit hash state to act on. + */ +static void clearM(HashState64 *hs64) { + hs64->index_m = 0; + hs64->byte_position_m = 0; + memset(hs64->m, 0, sizeof(hs64->m)); +} + +/** Begin calculating hash for new message. + * See section 5.3.5 of FIPS PUB 180-4. + * \param hs64 The 64 bit hash state to initialise. + */ +static void sha512Begin(HashState64 *hs64) { + hs64->message_length = 0; + hs64->h[0] = 0x6a09e667f3bcc908; + hs64->h[1] = 0xbb67ae8584caa73b; + hs64->h[2] = 0x3c6ef372fe94f82b; + hs64->h[3] = 0xa54ff53a5f1d36f1; + hs64->h[4] = 0x510e527fade682d1; + hs64->h[5] = 0x9b05688c2b3e6c1f; + hs64->h[6] = 0x1f83d9abfb41bd6b; + hs64->h[7] = 0x5be0cd19137e2179; + clearM(hs64); +} + +/** Add one more byte to the message buffer and call sha512Block() + * if the message buffer is full. + * \param hs64 The 64 bit hash state to act on. + * \param byte The byte to add. + */ +static void sha512WriteByte(HashState64 *hs64, const uint8_t byte) { + unsigned int pos; + unsigned int shift_amount; + + hs64->message_length++; + pos = (unsigned int)(7 - hs64->byte_position_m); + shift_amount = pos << 3; + hs64->m[hs64->index_m] |= ((uint64_t)byte << shift_amount); + + if (hs64->byte_position_m == 7) { + hs64->index_m++; + } + hs64->byte_position_m = (uint8_t)((hs64->byte_position_m + 1) & 7); + if (hs64->index_m == 16) { + sha512Block(hs64); + clearM(hs64); + } +} + +/** Finalise the hashing of a message by writing appropriate padding and + * length bytes, then write the hash value into a byte array. + * \param out A byte array where the final SHA-512 hash value will be written + * into. This must have space for #SHA512_HASH_LENGTH bytes. + * \param hs64 The 64 bit hash state to act on. + */ +static void sha512Finish(uint8_t *out, HashState64 *hs64) { + uint32_t length_bits; + uint8_t i; + uint8_t buffer[16]; + + // Subsequent calls to sha512WriteByte() will keep incrementing + // message_length, so the calculation of length (in bits) must be + // done before padding. + length_bits = hs64->message_length << 3; + + // Pad using a 1 bit followed by enough 0 bits to get the message buffer + // to exactly 896 bits full. + sha512WriteByte(hs64, (uint8_t)0x80); + while ((hs64->index_m != 14) || (hs64->byte_position_m != 0)) { + sha512WriteByte(hs64, 0); + } + // Write 128 bit length (in bits). + memset(buffer, 0, 16); + write_uint32_be(&(buffer[12]), length_bits); + for (i = 0; i < 16; i++) { + sha512WriteByte(hs64, buffer[i]); + } + for (i = 0; i < 8; i++) { + write_uint32_be(&(out[i * 8]), (uint32_t)(hs64->h[i] >> 32)); + write_uint32_be(&(out[i * 8 + 4]), (uint32_t)hs64->h[i]); + } +} + +/** Calculate a 64 byte HMAC of an arbitrary message and key using SHA-512 as + * the hash function. + * The code in here is based on the description in section 5 + * ("HMAC SPECIFICATION") of FIPS PUB 198. + * \param out A byte array where the HMAC-SHA512 hash value will be written. + * This must have space for #SHA512_HASH_LENGTH bytes. + * \param key A byte array containing the key to use in the HMAC-SHA512 + * calculation. The key can be of any length. + * \param key_length The length, in bytes, of the key. + * \param text A byte array containing the message to use in the HMAC-SHA512 + * calculation. The message can be of any length. + * \param text_length The length, in bytes, of the message. + */ +void hmac_sha512(uint8_t *out, + const uint8_t *key, + const unsigned int key_length, + const uint8_t *text, + const unsigned int text_length) { + unsigned int i; + uint8_t hash[SHA512_HASH_LENGTH]; + uint8_t padded_key[128]; + HashState64 hs64; + + // Determine key. + memset(padded_key, 0, sizeof(padded_key)); + if (key_length <= sizeof(padded_key)) { + memcpy(padded_key, key, key_length); + } else { + sha512Begin(&hs64); + for (i = 0; i < key_length; i++) { + sha512WriteByte(&hs64, key[i]); + } + sha512Finish(padded_key, &hs64); + } + // Calculate hash = H((K_0 XOR ipad) || text). + sha512Begin(&hs64); + for (i = 0; i < sizeof(padded_key); i++) { + sha512WriteByte(&hs64, (uint8_t)(padded_key[i] ^ 0x36)); + } + for (i = 0; i < text_length; i++) { + sha512WriteByte(&hs64, text[i]); + } + sha512Finish(hash, &hs64); + // Calculate H((K_0 XOR opad) || hash). + sha512Begin(&hs64); + for (i = 0; i < sizeof(padded_key); i++) { + sha512WriteByte(&hs64, (uint8_t)(padded_key[i] ^ 0x5c)); + } + for (i = 0; i < sizeof(hash); i++) { + sha512WriteByte(&hs64, hash[i]); + } + sha512Finish(out, &hs64); +} diff --git a/firmware/src/hal/common_linked/src/hmac_sha512.h b/firmware/src/hal/common_linked/src/hmac_sha512.h new file mode 100644 index 00000000..6b6fb586 --- /dev/null +++ b/firmware/src/hal/common_linked/src/hmac_sha512.h @@ -0,0 +1,77 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2021 RSK Labs Ltd + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +/** + * Taken from https://github.com/someone42/hardware-bitcoin-wallet @ + * 102c300d994712484c3c028b215f90a6f99d6155 and adapted for use with + * the powHSM HAL by RootstockLabs. LICENSE transcribed below. + */ + +/* + Copyright (c) 2011-2012 someone42 + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER 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. +*/ + +/** \file hmac_sha512.h + * + * \brief Describes constants and functions exported by hmac_sha512.c. + */ + +#ifndef __HMAC_SHA512_H +#define __HMAC_SHA512_H + +#include + +/** Number of bytes a SHA-512 hash requires. */ +#define SHA512_HASH_LENGTH 64 + +extern void hmac_sha512(uint8_t *out, + const uint8_t *key, + const unsigned int key_length, + const uint8_t *text, + const unsigned int text_length); + +#endif // #ifndef __HMAC_SHA512_H diff --git a/firmware/src/hal/common_linked/src/keccak256.c b/firmware/src/hal/common_linked/src/keccak256.c new file mode 100644 index 00000000..e5084372 --- /dev/null +++ b/firmware/src/hal/common_linked/src/keccak256.c @@ -0,0 +1,267 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2021 RSK Labs Ltd + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +/** + * Third party library taken from: + * https://github.com/firefly/wallet/blob/29adeaf7029142063b7a6878e049efd4c6534982/source/libs/ethers/src/keccak256.c + */ + +/* sha3 - an implementation of Secure Hash Algorithm 3 (Keccak). + * based on the + * The Keccak SHA-3 submission. Submission to NIST (Round 3), 2011 + * by Guido Bertoni, Joan Daemen, Michaël Peeters and Gilles Van Assche + * + * Copyright: 2013 Aleksey Kravchenko + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. Use this program at your own risk! + */ + +#include "keccak256.h" + +//#include + +#include +#include + +#define BLOCK_SIZE ((1600 - 256 * 2) / 8) + +#define I64(x) x##LL +#define ROTL64(qword, n) ((qword) << (n) ^ ((qword) >> (64 - (n)))) +#define le2me_64(x) (x) +#define IS_ALIGNED_64(p) (0 == (7 & ((const char*)(p) - (const char*)0))) +#define me64_to_le_str(to, from, length) memcpy((to), (from), (length)) + +/* constants */ + +//const uint8_t round_constant_info[] PROGMEM = { +//const uint8_t constants[] PROGMEM = { +const uint8_t constants[] = { + + 1, 26, 94, 112, 31, 33, 121, 85, 14, 12, 53, 38, 63, 79, 93, 83, 82, 72, 22, 102, 121, 88, 33, 116, +//}; + +//const uint8_t pi_transform[] PROGMEM = { + 1, 6, 9, 22, 14, 20, 2, 12, 13, 19, 23, 15, 4, 24, 21, 8, 16, 5, 3, 18, 17, 11, 7, 10, +//}; + +//const uint8_t rhoTransforms[] PROGMEM = { + 1, 62, 28, 27, 36, 44, 6, 55, 20, 3, 10, 43, 25, 39, 41, 45, 15, 21, 8, 18, 2, 61, 56, 14, +}; + +#define TYPE_ROUND_INFO 0 +#define TYPE_PI_TRANSFORM 24 +#define TYPE_RHO_TRANSFORM 48 + +uint8_t getConstant(uint8_t type, uint8_t index) { + return constants[type + index]; +} + +static uint64_t get_round_constant(uint8_t round) { + uint64_t result = 0; + + uint8_t roundInfo = getConstant(TYPE_ROUND_INFO, round); + if (roundInfo & (1 << 6)) { result |= ((uint64_t)1 << 63); } + if (roundInfo & (1 << 5)) { result |= ((uint64_t)1 << 31); } + if (roundInfo & (1 << 4)) { result |= ((uint64_t)1 << 15); } + if (roundInfo & (1 << 3)) { result |= ((uint64_t)1 << 7); } + if (roundInfo & (1 << 2)) { result |= ((uint64_t)1 << 3); } + if (roundInfo & (1 << 1)) { result |= ((uint64_t)1 << 1); } + if (roundInfo & (1 << 0)) { result |= ((uint64_t)1 << 0); } + + return result; +} + + +/* Initializing a sha3 context for given number of output bits */ +void keccak_init(SHA3_CTX *ctx) { + /* NB: The Keccak capacity parameter = bits * 2 */ + + memset(ctx, 0, sizeof(SHA3_CTX)); +} + +/* Keccak theta() transformation */ +static void keccak_theta(uint64_t *A) { + uint64_t C[5], D[5]; + + for (uint8_t i = 0; i < 5; i++) { + C[i] = A[i]; + for (uint8_t j = 5; j < 25; j += 5) { C[i] ^= A[i + j]; } + } + + for (uint8_t i = 0; i < 5; i++) { + D[i] = ROTL64(C[(i + 1) % 5], 1) ^ C[(i + 4) % 5]; + } + + for (uint8_t i = 0; i < 5; i++) { + //for (uint8_t j = 0; j < 25; j += 5) { + for (uint8_t j = 0; j < 25; j += 5) { A[i + j] ^= D[i]; } + } +} + + +/* Keccak pi() transformation */ +static void keccak_pi(uint64_t *A) { + uint64_t A1 = A[1]; + for (uint8_t i = 1; i < 24; i++) { + A[getConstant(TYPE_PI_TRANSFORM, i - 1)] = A[getConstant(TYPE_PI_TRANSFORM, i)]; + } + A[10] = A1; + /* note: A[ 0] is left as is */ +} + +/* +ketch uses 30084 bytes (93%) of program storage space. Maximum is 32256 bytes. +Global variables use 743 bytes (36%) of dynamic memory, leaving 1305 bytes for local variables. Maximum is 2048 bytes. + +*/ +/* Keccak chi() transformation */ +static void keccak_chi(uint64_t *A) { + for (uint8_t i = 0; i < 25; i += 5) { + uint64_t A0 = A[0 + i], A1 = A[1 + i]; + A[0 + i] ^= ~A1 & A[2 + i]; + A[1 + i] ^= ~A[2 + i] & A[3 + i]; + A[2 + i] ^= ~A[3 + i] & A[4 + i]; + A[3 + i] ^= ~A[4 + i] & A0; + A[4 + i] ^= ~A0 & A1; + } +} + + +static void sha3_permutation(uint64_t *state) { + for (uint8_t round = 0; round < 24; round++) { + keccak_theta(state); + + /* apply Keccak rho() transformation */ + for (uint8_t i = 1; i < 25; i++) { + state[i] = ROTL64(state[i], getConstant(TYPE_RHO_TRANSFORM, i - 1)); + } + + keccak_pi(state); + keccak_chi(state); + + /* apply iota(state, round) */ + *state ^= get_round_constant(round); + } +} + +/** + * The core transformation. Process the specified block of data. + * + * @param hash the algorithm state + * @param block the message block to process + * @param block_size the size of the processed block in bytes + */ +static void sha3_process_block(uint64_t hash[25], const uint64_t *block) { + for (uint8_t i = 0; i < 17; i++) { + hash[i] ^= le2me_64(block[i]); + } + + /* make a permutation of the hash */ + sha3_permutation(hash); +} + +//#define SHA3_FINALIZED 0x80000000 +//#define SHA3_FINALIZED 0x8000 + +/** + * Calculate message hash. + * Can be called repeatedly with chunks of the message to be hashed. + * + * @param ctx the algorithm context containing current hashing state + * @param msg message chunk + * @param size length of the message chunk + */ +void keccak_update(SHA3_CTX *ctx, const unsigned char *msg, uint16_t size) +{ + uint16_t idx = (uint16_t)ctx->rest; + + //if (ctx->rest & SHA3_FINALIZED) return; /* too late for additional input */ + ctx->rest = (unsigned)((ctx->rest + size) % BLOCK_SIZE); + + /* fill partial block */ + if (idx) { + uint16_t left = BLOCK_SIZE - idx; + memcpy((char*)ctx->message + idx, msg, (size < left ? size : left)); + if (size < left) return; + + /* process partial block */ + sha3_process_block(ctx->hash, ctx->message); + msg += left; + size -= left; + } + + while (size >= BLOCK_SIZE) { + uint64_t* aligned_message_block; + if (IS_ALIGNED_64(msg)) { + // the most common case is processing of an already aligned message without copying it + aligned_message_block = (uint64_t*)(void*)msg; + } else { + memcpy(ctx->message, msg, BLOCK_SIZE); + aligned_message_block = ctx->message; + } + + sha3_process_block(ctx->hash, aligned_message_block); + msg += BLOCK_SIZE; + size -= BLOCK_SIZE; + } + + if (size) { + memcpy(ctx->message, msg, size); /* save leftovers */ + } +} + +/** +* Store calculated hash into the given array. +* +* @param ctx the algorithm context containing current hashing state +* @param result calculated hash in binary form +*/ +void keccak_final(SHA3_CTX *ctx, unsigned char* result) +{ + uint16_t digest_length = 100 - BLOCK_SIZE / 2; + +// if (!(ctx->rest & SHA3_FINALIZED)) { + /* clear the rest of the data queue */ + memset((char*)ctx->message + ctx->rest, 0, BLOCK_SIZE - ctx->rest); + ((char*)ctx->message)[ctx->rest] |= 0x01; + ((char*)ctx->message)[BLOCK_SIZE - 1] |= 0x80; + + /* process final block */ + sha3_process_block(ctx->hash, ctx->message); +// ctx->rest = SHA3_FINALIZED; /* mark context as finalized */ +// } + + if (result) { + me64_to_le_str(result, ctx->hash, digest_length); + } +} diff --git a/firmware/src/hal/common_linked/src/keccak256.h b/firmware/src/hal/common_linked/src/keccak256.h new file mode 100644 index 00000000..c2d15d7b --- /dev/null +++ b/firmware/src/hal/common_linked/src/keccak256.h @@ -0,0 +1,81 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2021 RSK Labs Ltd + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +/** + * Third party library taken from: + * https://github.com/firefly/wallet/blob/29adeaf7029142063b7a6878e049efd4c6534982/source/libs/ethers/src/keccak256.h + */ + +/* sha3 - an implementation of Secure Hash Algorithm 3 (Keccak). + * based on the + * The Keccak SHA-3 submission. Submission to NIST (Round 3), 2011 + * by Guido Bertoni, Joan Daemen, Michaël Peeters and Gilles Van Assche + * + * Copyright: 2013 Aleksey Kravchenko + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. Use this program at your own risk! + */ + +#ifndef __KECCAK256_H_ +#define __KECCAK256_H_ + +#include + +#define sha3_max_permutation_size 25 +#define sha3_max_rate_in_qwords 24 + +typedef struct SHA3_CTX { + /* 1600 bits algorithm hashing state */ + uint64_t hash[sha3_max_permutation_size]; + /* 1536-bit buffer for leftovers */ + uint64_t message[sha3_max_rate_in_qwords]; + /* count of bytes in the message[] buffer */ + uint16_t rest; +} SHA3_CTX; + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +void keccak_init(SHA3_CTX *ctx); +void keccak_update(SHA3_CTX *ctx, const unsigned char *msg, uint16_t size); +void keccak_final(SHA3_CTX *ctx, unsigned char* result); + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __KECCAK256_H_ */ diff --git a/firmware/src/hal/common/src/sha256.c b/firmware/src/hal/common_linked/src/sha256.c similarity index 100% rename from firmware/src/hal/common/src/sha256.c rename to firmware/src/hal/common_linked/src/sha256.c diff --git a/firmware/src/hal/common/src/sha256.h b/firmware/src/hal/common_linked/src/sha256.h similarity index 100% rename from firmware/src/hal/common/src/sha256.h rename to firmware/src/hal/common_linked/src/sha256.h diff --git a/firmware/src/hal/x86/test/bip32/Makefile b/firmware/src/hal/common_linked/test/bip32/Makefile similarity index 100% rename from firmware/src/hal/x86/test/bip32/Makefile rename to firmware/src/hal/common_linked/test/bip32/Makefile diff --git a/firmware/src/hal/x86/test/bip32/test_bip32.c b/firmware/src/hal/common_linked/test/bip32/test_bip32.c similarity index 100% rename from firmware/src/hal/x86/test/bip32/test_bip32.c rename to firmware/src/hal/common_linked/test/bip32/test_bip32.c diff --git a/firmware/src/hal/x86/test/bip32/test_bip32_derivation.c b/firmware/src/hal/common_linked/test/bip32/test_bip32_derivation.c similarity index 100% rename from firmware/src/hal/x86/test/bip32/test_bip32_derivation.c rename to firmware/src/hal/common_linked/test/bip32/test_bip32_derivation.c diff --git a/firmware/src/hal/common/test/common.mk b/firmware/src/hal/common_linked/test/common.mk similarity index 100% rename from firmware/src/hal/common/test/common.mk rename to firmware/src/hal/common_linked/test/common.mk diff --git a/firmware/src/hal/common_linked/test/common/common.mk b/firmware/src/hal/common_linked/test/common/common.mk new file mode 100644 index 00000000..dfca01be --- /dev/null +++ b/firmware/src/hal/common_linked/test/common/common.mk @@ -0,0 +1,35 @@ +# The MIT License (MIT) +# +# Copyright (c) 2021 RSK Labs Ltd +# +# Permission is hereby granted, free of charge, to any person obtaining a copy of +# this software and associated documentation files (the "Software"), to deal in +# the Software without restriction, including without limitation the rights to +# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +# of the Software, and to permit persons to whom the Software is furnished to do +# so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +INCDIR = ../../../include +COMMONTESTDIR = ../common +COMMLINKEDSRCDIR = ../../src +COMMONSRCDIR = ../../../../common/src +SRCDIR = $(COMMLINKEDSRCDIR):$(COMMONSRCDIR):$(COMMONTESTDIR) +CFLAGS = -iquote $(INCDIR) -iquote $(COMMONTESTDIR) -iquote $(COMMLINKEDSRCDIR) -iquote $(COMMONSRCDIR) +CFLAGS += -DHSM_PLATFORM_X86 + +include ../../../../../coverage/coverage.mk + +CFLAGS += $(COVFLAGS) + +VPATH += $(SRCDIR):$(INCDIR):$(COMMONTESTDIR) diff --git a/firmware/src/hal/common_linked/test/common/log.c b/firmware/src/hal/common_linked/test/common/log.c new file mode 100644 index 00000000..93c2dda4 --- /dev/null +++ b/firmware/src/hal/common_linked/test/common/log.c @@ -0,0 +1,48 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2021 RSK Labs Ltd + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include +#include + +void LOG(const char *format, ...) { + va_list args; + va_start(args, format); + + vprintf(format, args); + + va_end(args); +} + +void LOG_HEX(const char *prefix, const void *buffer, const size_t size) { + printf("%s ", prefix); + if (size > 0) { + printf("0x"); + for (unsigned int i = 0; i < size; i++) { + printf("%02x", ((unsigned char *)buffer)[i]); + } + } else { + printf("EMPTY"); + } + printf("\n"); +} diff --git a/firmware/src/hal/x86/test/common/test_helpers.c b/firmware/src/hal/common_linked/test/common/test_helpers.c similarity index 100% rename from firmware/src/hal/x86/test/common/test_helpers.c rename to firmware/src/hal/common_linked/test/common/test_helpers.c diff --git a/firmware/src/hal/x86/test/common/test_helpers.h b/firmware/src/hal/common_linked/test/common/test_helpers.h similarity index 100% rename from firmware/src/hal/x86/test/common/test_helpers.h rename to firmware/src/hal/common_linked/test/common/test_helpers.h diff --git a/firmware/src/hal/x86/test/endian/Makefile b/firmware/src/hal/common_linked/test/endian/Makefile similarity index 100% rename from firmware/src/hal/x86/test/endian/Makefile rename to firmware/src/hal/common_linked/test/endian/Makefile diff --git a/firmware/src/hal/x86/test/endian/test_endian.c b/firmware/src/hal/common_linked/test/endian/test_endian.c similarity index 100% rename from firmware/src/hal/x86/test/endian/test_endian.c rename to firmware/src/hal/common_linked/test/endian/test_endian.c diff --git a/firmware/src/hal/x86/test/hmac_sha512/HMAC.rsp b/firmware/src/hal/common_linked/test/hmac_sha512/HMAC.rsp similarity index 100% rename from firmware/src/hal/x86/test/hmac_sha512/HMAC.rsp rename to firmware/src/hal/common_linked/test/hmac_sha512/HMAC.rsp diff --git a/firmware/src/hal/x86/test/hmac_sha512/Makefile b/firmware/src/hal/common_linked/test/hmac_sha512/Makefile similarity index 100% rename from firmware/src/hal/x86/test/hmac_sha512/Makefile rename to firmware/src/hal/common_linked/test/hmac_sha512/Makefile diff --git a/firmware/src/hal/x86/test/hmac_sha512/test_hmac_sha512.c b/firmware/src/hal/common_linked/test/hmac_sha512/test_hmac_sha512.c similarity index 100% rename from firmware/src/hal/x86/test/hmac_sha512/test_hmac_sha512.c rename to firmware/src/hal/common_linked/test/hmac_sha512/test_hmac_sha512.c diff --git a/firmware/src/hal/x86/test/keccak256/Makefile b/firmware/src/hal/common_linked/test/keccak256/Makefile similarity index 100% rename from firmware/src/hal/x86/test/keccak256/Makefile rename to firmware/src/hal/common_linked/test/keccak256/Makefile diff --git a/firmware/src/hal/x86/test/keccak256/test_keccak256.c b/firmware/src/hal/common_linked/test/keccak256/test_keccak256.c similarity index 100% rename from firmware/src/hal/x86/test/keccak256/test_keccak256.c rename to firmware/src/hal/common_linked/test/keccak256/test_keccak256.c diff --git a/firmware/src/hal/common/test/run-all.sh b/firmware/src/hal/common_linked/test/run-all.sh similarity index 90% rename from firmware/src/hal/common/test/run-all.sh rename to firmware/src/hal/common_linked/test/run-all.sh index 650caf44..9daa6222 100755 --- a/firmware/src/hal/common/test/run-all.sh +++ b/firmware/src/hal/common_linked/test/run-all.sh @@ -2,7 +2,7 @@ if [[ $1 == "exec" ]]; then BASEDIR=$(realpath $(dirname $0)) - TESTDIRS="sha256" + TESTDIRS="bip32 endian hmac_sha512 keccak256 sha256" for d in $TESTDIRS; do echo "******************************" echo "Testing $d..." diff --git a/firmware/src/hal/common/test/sha256/Makefile b/firmware/src/hal/common_linked/test/sha256/Makefile similarity index 100% rename from firmware/src/hal/common/test/sha256/Makefile rename to firmware/src/hal/common_linked/test/sha256/Makefile diff --git a/firmware/src/hal/common/test/sha256/test_sha256.c b/firmware/src/hal/common_linked/test/sha256/test_sha256.c similarity index 100% rename from firmware/src/hal/common/test/sha256/test_sha256.c rename to firmware/src/hal/common_linked/test/sha256/test_sha256.c diff --git a/firmware/src/hal/ledger/src/communication.c b/firmware/src/hal/ledger/src/communication.c index 6b73fb84..4b1f6e65 120000 --- a/firmware/src/hal/ledger/src/communication.c +++ b/firmware/src/hal/ledger/src/communication.c @@ -1 +1 @@ -../../x86/src/communication.c \ No newline at end of file +../../common_linked/src/communication.c \ No newline at end of file diff --git a/firmware/src/hal/ledger/src/sha256.c b/firmware/src/hal/ledger/src/sha256.c index ceea83a9..dd0468a1 120000 --- a/firmware/src/hal/ledger/src/sha256.c +++ b/firmware/src/hal/ledger/src/sha256.c @@ -1 +1 @@ -../../common/src/sha256.c \ No newline at end of file +../../common_linked/src/sha256.c \ No newline at end of file diff --git a/firmware/src/hal/ledger/src/sha256.h b/firmware/src/hal/ledger/src/sha256.h index acd90f89..d920bc5d 120000 --- a/firmware/src/hal/ledger/src/sha256.h +++ b/firmware/src/hal/ledger/src/sha256.h @@ -1 +1 @@ -../../common/src/sha256.h \ No newline at end of file +../../common_linked/src/sha256.h \ No newline at end of file diff --git a/firmware/src/hal/sgx/src/trusted/bip32.c b/firmware/src/hal/sgx/src/trusted/bip32.c index 6bb570cb..ee83e826 120000 --- a/firmware/src/hal/sgx/src/trusted/bip32.c +++ b/firmware/src/hal/sgx/src/trusted/bip32.c @@ -1 +1 @@ -../../../x86/src/bip32.c \ No newline at end of file +../../../common_linked/src/bip32.c \ No newline at end of file diff --git a/firmware/src/hal/sgx/src/trusted/bip32.h b/firmware/src/hal/sgx/src/trusted/bip32.h index b57dfb7d..1ec296f4 120000 --- a/firmware/src/hal/sgx/src/trusted/bip32.h +++ b/firmware/src/hal/sgx/src/trusted/bip32.h @@ -1 +1 @@ -../../../x86/src/bip32.h \ No newline at end of file +../../../common_linked/src/bip32.h \ No newline at end of file diff --git a/firmware/src/hal/sgx/src/trusted/communication.c b/firmware/src/hal/sgx/src/trusted/communication.c index 096d96b1..31cefe27 120000 --- a/firmware/src/hal/sgx/src/trusted/communication.c +++ b/firmware/src/hal/sgx/src/trusted/communication.c @@ -1 +1 @@ -../../../x86/src/communication.c \ No newline at end of file +../../../common_linked/src/communication.c \ No newline at end of file diff --git a/firmware/src/hal/sgx/src/trusted/endian.c b/firmware/src/hal/sgx/src/trusted/endian.c index 153fd780..c54d7327 120000 --- a/firmware/src/hal/sgx/src/trusted/endian.c +++ b/firmware/src/hal/sgx/src/trusted/endian.c @@ -1 +1 @@ -../../../x86/src/endian.c \ No newline at end of file +../../../common_linked/src/endian.c \ No newline at end of file diff --git a/firmware/src/hal/sgx/src/trusted/endian.h b/firmware/src/hal/sgx/src/trusted/endian.h index 213c0feb..e7f29bb9 120000 --- a/firmware/src/hal/sgx/src/trusted/endian.h +++ b/firmware/src/hal/sgx/src/trusted/endian.h @@ -1 +1 @@ -../../../x86/src/endian.h \ No newline at end of file +../../../common_linked/src/endian.h \ No newline at end of file diff --git a/firmware/src/hal/sgx/src/trusted/exceptions.c b/firmware/src/hal/sgx/src/trusted/exceptions.c index e5affcf0..36375b7e 120000 --- a/firmware/src/hal/sgx/src/trusted/exceptions.c +++ b/firmware/src/hal/sgx/src/trusted/exceptions.c @@ -1 +1 @@ -../../../x86/src/exceptions.c \ No newline at end of file +../../../common_linked/src/exceptions.c \ No newline at end of file diff --git a/firmware/src/hal/sgx/src/trusted/hash.c b/firmware/src/hal/sgx/src/trusted/hash.c index 095bbd93..c954a334 120000 --- a/firmware/src/hal/sgx/src/trusted/hash.c +++ b/firmware/src/hal/sgx/src/trusted/hash.c @@ -1 +1 @@ -../../../x86/src/hash.c \ No newline at end of file +../../../common_linked/src/hash.c \ No newline at end of file diff --git a/firmware/src/hal/sgx/src/trusted/hmac_sha512.c b/firmware/src/hal/sgx/src/trusted/hmac_sha512.c index 5e2c42e7..8e1d7f90 120000 --- a/firmware/src/hal/sgx/src/trusted/hmac_sha512.c +++ b/firmware/src/hal/sgx/src/trusted/hmac_sha512.c @@ -1 +1 @@ -../../../x86/src/hmac_sha512.c \ No newline at end of file +../../../common_linked/src/hmac_sha512.c \ No newline at end of file diff --git a/firmware/src/hal/sgx/src/trusted/hmac_sha512.h b/firmware/src/hal/sgx/src/trusted/hmac_sha512.h index c4a537a5..4826b688 120000 --- a/firmware/src/hal/sgx/src/trusted/hmac_sha512.h +++ b/firmware/src/hal/sgx/src/trusted/hmac_sha512.h @@ -1 +1 @@ -../../../x86/src/hmac_sha512.h \ No newline at end of file +../../../common_linked/src/hmac_sha512.h \ No newline at end of file diff --git a/firmware/src/hal/sgx/src/trusted/keccak256.c b/firmware/src/hal/sgx/src/trusted/keccak256.c index a7432b9e..ae2ca286 120000 --- a/firmware/src/hal/sgx/src/trusted/keccak256.c +++ b/firmware/src/hal/sgx/src/trusted/keccak256.c @@ -1 +1 @@ -../../../x86/src/keccak256.c \ No newline at end of file +../../../common_linked/src/keccak256.c \ No newline at end of file diff --git a/firmware/src/hal/sgx/src/trusted/keccak256.h b/firmware/src/hal/sgx/src/trusted/keccak256.h index 52e5a8c8..f22beee3 120000 --- a/firmware/src/hal/sgx/src/trusted/keccak256.h +++ b/firmware/src/hal/sgx/src/trusted/keccak256.h @@ -1 +1 @@ -../../../x86/src/keccak256.h \ No newline at end of file +../../../common_linked/src/keccak256.h \ No newline at end of file diff --git a/firmware/src/hal/sgx/src/trusted/sha256.c b/firmware/src/hal/sgx/src/trusted/sha256.c index 4feddbd1..e47d7497 120000 --- a/firmware/src/hal/sgx/src/trusted/sha256.c +++ b/firmware/src/hal/sgx/src/trusted/sha256.c @@ -1 +1 @@ -../../../common/src/sha256.c \ No newline at end of file +../../../common_linked/src/sha256.c \ No newline at end of file diff --git a/firmware/src/hal/sgx/src/trusted/sha256.h b/firmware/src/hal/sgx/src/trusted/sha256.h index b7a70b63..ffb49089 120000 --- a/firmware/src/hal/sgx/src/trusted/sha256.h +++ b/firmware/src/hal/sgx/src/trusted/sha256.h @@ -1 +1 @@ -../../../common/src/sha256.h \ No newline at end of file +../../../common_linked/src/sha256.h \ No newline at end of file diff --git a/firmware/src/hal/x86/src/bip32.c b/firmware/src/hal/x86/src/bip32.c deleted file mode 100644 index e3c25545..00000000 --- a/firmware/src/hal/x86/src/bip32.c +++ /dev/null @@ -1,267 +0,0 @@ -/** - * The MIT License (MIT) - * - * Copyright (c) 2021 RSK Labs Ltd - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "bip32.h" -#include "hal/constants.h" -#include "hal/log.h" -#include "hmac_sha512.h" -#include "endian.h" -#include "bigdigits.h" -#include "bigdigits_helper.h" - -#include -#include -#include -#include -#include - -#define BIP32_PREFIX "m/" -#define MIN_PATH_LENGTH (strlen("m/0/0/0/0/0")) -#define MAX_PART_DECIMAL_DIGITS 10 -#define EXPECTED_PARTS BIP32_PATH_NUMPARTS -#define NODE_LENGTH 64 - -#ifdef DEBUG_BIP32 -#define DEBUG_LOG(...) LOG(__VA_ARGS__) -#else -#define DEBUG_LOG(...) -#endif - -static const uint8_t secp256k1_order[] = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfe, 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, - 0xa0, 0x3b, 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x41}; - -static secp256k1_context* sp_ctx = NULL; - -size_t bip32_parse_path(const char* path, uint8_t* out) { - size_t pos, start, pathlen; - int parts; - int index; - bool number; - char indexstr[MAX_PART_DECIMAL_DIGITS + 1]; - uint32_t indexint; - - if (strlen(path) < MIN_PATH_LENGTH) { - DEBUG_LOG("BIP32 path too short: %s\n", path); - return 0; - } - - if (strncmp(path, BIP32_PREFIX, strlen(BIP32_PREFIX))) { - DEBUG_LOG("Bad prefix for path: %s\n", path); - return 0; - } - - parts = 0; - pathlen = strlen(path); - pos = strlen(BIP32_PREFIX); - start = pos; - index = 0; - number = true; - while (pos < pathlen) { - if (number && path[pos] >= '0' && path[pos] <= '9') { - pos++; - if (pos - start > MAX_PART_DECIMAL_DIGITS) { - DEBUG_LOG("Path part %d too long for path: %s\n", parts, path); - return 0; - } - } else if (number && path[pos] == '\'') { - number = false; - index = 0x80000000; - pos++; - } else if (path[pos] != '/') { - DEBUG_LOG( - "Unexpected path character: %c for path %s\n", path[pos], path); - return 0; - } - - if (pos == pathlen || path[pos] == '/') { - // Compute the index - memcpy(indexstr, path + start, pos - start); - indexstr[pos - start] = '\0'; - indexint = (uint32_t)atol(indexstr); - if (indexint >= 0x80000000) { - DEBUG_LOG("Path part %d needs to be between 0 and 2^31-1 for " - "path: %s\n", - parts, - path); - return 0; - } - index += indexint; - // Output the index in LE - for (int i = 0; i < (int)sizeof(uint32_t); i++) { - out[1 + (parts * sizeof(uint32_t)) + i] = - (index >> (8 * i)) & 0xFF; - } - // Next! - parts++; - index = 0; - number = true; - start = ++pos; - if (parts == EXPECTED_PARTS) { - if (pos < pathlen) { - DEBUG_LOG("Path has too many parts: %s\n", path); - return 0; - } - out[0] = (char)parts; - return 1 + parts * sizeof(uint32_t); - } - } - } - - DEBUG_LOG("Unexpected code path reached for path: %s\n", path); - return 0; -} - -/** - * Following portion taken from - * https://github.com/someone42/hardware-bitcoin-wallet @ - * 102c300d994712484c3c028b215f90a6f99d6155 and adapted for use with - * the powHSM HAL by RootstockLabs. LICENSE transcribed below. - */ - -/* - Copyright (c) 2011-2012 someone42 - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER 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. -*/ - -#define PRIVATE_KEY_DIGITS (PRIVATE_KEY_LENGTH / sizeof(DIGIT_T)) - -static void seed_to_node(uint8_t* master_node, - const uint8_t* seed, - const unsigned int seed_length) { - hmac_sha512( - master_node, (const uint8_t*)"Bitcoin seed", 12, seed, seed_length); -} - -bool bip32_derive_private(uint8_t* out, - const uint8_t* seed, - const unsigned int seed_length, - const uint32_t* path, - const unsigned int path_length) { - uint8_t current_node[NODE_LENGTH]; - uint8_t temp[NODE_LENGTH]; - DIGIT_T tempbig_a[PRIVATE_KEY_DIGITS + 1], - tempbig_b[PRIVATE_KEY_DIGITS + 1]; - DIGIT_T tempbig_c[PRIVATE_KEY_DIGITS + 1], - tempbig_d[PRIVATE_KEY_DIGITS + 1]; - uint8_t hmac_data[1 + 32 + 4]; // prefix + private key + i - secp256k1_pubkey pubkey; - size_t pubkey_serialised_size; - - // Init the secp256k1 context - if (!sp_ctx) - sp_ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN); - - // Compute the master node from the seed - seed_to_node(current_node, seed, seed_length); - - for (unsigned int i = 0; i < path_length; i++) { - if (path[i] & 0x80000000) { - // Hardened derivation. - hmac_data[0] = 0x00; - memcpy(&hmac_data[1], current_node, 32); - } else { - // Non-hardened derivation. - if (!secp256k1_ec_pubkey_create(sp_ctx, &pubkey, current_node)) { - DEBUG_LOG("Error deriving public key from private key\n"); - return false; - } - - pubkey_serialised_size = PUBKEY_CMP_LENGTH; - secp256k1_ec_pubkey_serialize(sp_ctx, - hmac_data, - &pubkey_serialised_size, - &pubkey, - SECP256K1_EC_COMPRESSED); - - if (pubkey_serialised_size != PUBKEY_CMP_LENGTH) { - DEBUG_LOG("Unexpected serialised public key size\n"); - return false; - } - } - write_uint32_be(&hmac_data[33], path[i]); - - // Need to write to temp here (instead of current_node) because part of - // current_node is used as the key. - hmac_sha512(temp, ¤t_node[32], 32, hmac_data, sizeof(hmac_data)); - - // First 32 bytes of temp = I_L. Compute k_i - if (!secp256k1_ec_seckey_verify(sp_ctx, temp)) { - DEBUG_LOG( - "Overflow during derivation, use a different one (I_L)\n"); - return false; - } - parse_bigint_be(temp, 32, tempbig_a, PRIVATE_KEY_DIGITS + 1); - - if (!secp256k1_ec_seckey_verify(sp_ctx, current_node)) { - DEBUG_LOG("Invalid key during derivation, use a different path " - "(invalid k_par)\n"); - return false; - } - parse_bigint_be(current_node, 32, tempbig_b, PRIVATE_KEY_DIGITS + 1); - - mpAdd(tempbig_a, tempbig_a, tempbig_b, PRIVATE_KEY_DIGITS + 1); - parse_bigint_be(secp256k1_order, 32, tempbig_b, PRIVATE_KEY_DIGITS + 1); - mpDivide(tempbig_d, - tempbig_c, - tempbig_a, - PRIVATE_KEY_DIGITS + 1, - tempbig_b, - PRIVATE_KEY_DIGITS + 1); - dump_bigint_be(current_node, tempbig_c, PRIVATE_KEY_DIGITS); - if (!secp256k1_ec_seckey_verify(sp_ctx, current_node)) { - DEBUG_LOG( - "Invalid derived key, use a different path (invalid k_i)\n"); - return false; - } - - // Last 32 bytes = I_R = c_i - memcpy(¤t_node[32], &temp[32], 32); - } - memcpy(out, current_node, 32); - return true; // success -} diff --git a/firmware/src/hal/x86/src/bip32.c b/firmware/src/hal/x86/src/bip32.c new file mode 120000 index 00000000..947a5aa7 --- /dev/null +++ b/firmware/src/hal/x86/src/bip32.c @@ -0,0 +1 @@ +../../common_linked/src/bip32.c \ No newline at end of file diff --git a/firmware/src/hal/x86/src/bip32.h b/firmware/src/hal/x86/src/bip32.h deleted file mode 100644 index a80bafef..00000000 --- a/firmware/src/hal/x86/src/bip32.h +++ /dev/null @@ -1,65 +0,0 @@ -/** - * The MIT License (MIT) - * - * Copyright (c) 2021 RSK Labs Ltd - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef __HAL_BIP32_H -#define __HAL_BIP32_H - -#include -#include -#include - -#include "hal/constants.h" - -#define BIP32_PATH_PART_LENGTH (sizeof(uint32_t)) -#define BIP32_PATH_LENGTH (1 + BIP32_PATH_NUMPARTS * BIP32_PATH_PART_LENGTH) - -/** - * @brief Parse the given string representation of a bip32 path - * into binary format - * - * @param path the bip32 path as string - * @param out the destination buffer for the parsed path - * - * @returns the size of the parsed path in bytes, or zero in case of error - */ -size_t bip32_parse_path(const char* path, uint8_t* out); - -/** - * @brief Derive a private key from the given seed and bip32 path - * - * @param out the destination buffer for the derived key - * @param seed the seed to use for derivation - * @param seed_length the seed length in bytes - * @param path the bip32 path - * @param path_length the bip32 path length in derivation steps - * - * @returns whether derivation succeeded - */ -bool bip32_derive_private(uint8_t* out, - const uint8_t* seed, - const unsigned int seed_length, - const uint32_t* path, - const unsigned int path_length); - -#endif // __HAL_BIP32_H diff --git a/firmware/src/hal/x86/src/bip32.h b/firmware/src/hal/x86/src/bip32.h new file mode 120000 index 00000000..58a4439e --- /dev/null +++ b/firmware/src/hal/x86/src/bip32.h @@ -0,0 +1 @@ +../../common_linked/src/bip32.h \ No newline at end of file diff --git a/firmware/src/hal/x86/src/communication.c b/firmware/src/hal/x86/src/communication.c index 2bf128f3..4b1f6e65 120000 --- a/firmware/src/hal/x86/src/communication.c +++ b/firmware/src/hal/x86/src/communication.c @@ -1 +1 @@ -../../common/src/communication.c \ No newline at end of file +../../common_linked/src/communication.c \ No newline at end of file diff --git a/firmware/src/hal/x86/src/endian.c b/firmware/src/hal/x86/src/endian.c deleted file mode 100644 index 2d72da7f..00000000 --- a/firmware/src/hal/x86/src/endian.c +++ /dev/null @@ -1,77 +0,0 @@ -/** - * The MIT License (MIT) - * - * Copyright (c) 2021 RSK Labs Ltd - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -/** - * Taken from https://github.com/someone42/hardware-bitcoin-wallet @ - * 102c300d994712484c3c028b215f90a6f99d6155 and adapted for use with - * the powHSM HAL by RootstockLabs. LICENSE transcribed below. - */ - -/* - Copyright (c) 2011-2012 someone42 - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER 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. -*/ - -/** \file endian.c - * - * \brief Contains functions which perform endian-specific type conversion. - * - * This file is licensed as described by the file LICENCE. - */ - -#include "endian.h" - -/** Write 32 bit unsigned integer into a byte array in big-endian format. - * \param out The destination byte array. This must have space for at - * least 4 bytes. - * \param in The source integer. - */ -void write_uint32_be(uint8_t *out, uint32_t in) { - out[0] = (uint8_t)(in >> 24); - out[1] = (uint8_t)(in >> 16); - out[2] = (uint8_t)(in >> 8); - out[3] = (uint8_t)in; -} diff --git a/firmware/src/hal/x86/src/endian.c b/firmware/src/hal/x86/src/endian.c new file mode 120000 index 00000000..c2de33db --- /dev/null +++ b/firmware/src/hal/x86/src/endian.c @@ -0,0 +1 @@ +../../common_linked/src/endian.c \ No newline at end of file diff --git a/firmware/src/hal/x86/src/endian.h b/firmware/src/hal/x86/src/endian.h deleted file mode 100644 index 7e982d81..00000000 --- a/firmware/src/hal/x86/src/endian.h +++ /dev/null @@ -1,72 +0,0 @@ -/** - * The MIT License (MIT) - * - * Copyright (c) 2021 RSK Labs Ltd - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -/** - * Taken from https://github.com/someone42/hardware-bitcoin-wallet @ - * 102c300d994712484c3c028b215f90a6f99d6155 and adapted for use with - * the powHSM HAL by RootstockLabs. LICENSE transcribed below. - */ - -/* - Copyright (c) 2011-2012 someone42 - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER 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. -*/ - -#ifndef __HAL_ENDIAN_H -#define __HAL_ENDIAN_H - -#include - -/** - * @brief Dump the given 32-bit unsigned integer - * into the given buffer as big-endian - * - * @param out the destination buffer - * @param in the unsigned integer to dump - */ -void write_uint32_be(uint8_t *out, uint32_t in); - -#endif // #ifndef __HAL_ENDIAN_H diff --git a/firmware/src/hal/x86/src/endian.h b/firmware/src/hal/x86/src/endian.h new file mode 120000 index 00000000..6acd73d1 --- /dev/null +++ b/firmware/src/hal/x86/src/endian.h @@ -0,0 +1 @@ +../../common_linked/src/endian.h \ No newline at end of file diff --git a/firmware/src/hal/x86/src/exceptions.c b/firmware/src/hal/x86/src/exceptions.c deleted file mode 100644 index e114bbba..00000000 --- a/firmware/src/hal/x86/src/exceptions.c +++ /dev/null @@ -1,51 +0,0 @@ -/** - * The MIT License (MIT) - * - * Copyright (c) 2021 RSK Labs Ltd - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -/***************************************************************************** - * Ledger Nano S - Secure firmware - * (c) 2016, 2017 Ledger - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - ******************************************************************************/ - -/** - * Modified try...catch exception implementation (taken from nanos-secure-sdk) - * (https://github.com/LedgerHQ/nanos-secure-sdk/blob/nanos-1314/include/os.h) - */ - -#include "hal/exceptions.h" - -static try_context_t G_try_last_open_context_var; - -try_context_t* G_try_last_open_context = &G_try_last_open_context_var; diff --git a/firmware/src/hal/x86/src/exceptions.c b/firmware/src/hal/x86/src/exceptions.c new file mode 120000 index 00000000..6b087387 --- /dev/null +++ b/firmware/src/hal/x86/src/exceptions.c @@ -0,0 +1 @@ +../../common_linked/src/exceptions.c \ No newline at end of file diff --git a/firmware/src/hal/x86/src/hash.c b/firmware/src/hal/x86/src/hash.c deleted file mode 100644 index 4dff8843..00000000 --- a/firmware/src/hal/x86/src/hash.c +++ /dev/null @@ -1,84 +0,0 @@ -/** - * The MIT License (MIT) - * - * Copyright (c) 2021 RSK Labs Ltd - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "hal/hash.h" - -// *** sha256 *** -bool hash_sha256_init(hash_sha256_ctx_t* ctx) { - sha256_init(ctx); - return true; -} - -bool hash_sha256_update(hash_sha256_ctx_t* ctx, - const uint8_t* data, - size_t len) { - sha256_update(ctx, data, len); - return true; -} - -bool hash_sha256_final(hash_sha256_ctx_t* ctx, uint8_t* out_hash) { - sha256_final(ctx, out_hash); - return true; -} - -// *** sha256 with midstate support *** -bool hash_sha256_ms_init(hash_sha256_ms_ctx_t* ctx) { - sha256_init(ctx); - return true; -} - -bool hash_sha256_ms_midstate(hash_sha256_ms_ctx_t* ctx, uint8_t* midstate) { - sha256_midstate(ctx, midstate); - return true; -} - -bool hash_sha256_ms_update(hash_sha256_ms_ctx_t* ctx, - const uint8_t* data, - size_t len) { - sha256_update(ctx, data, len); - return true; -} - -bool hash_sha256_ms_final(hash_sha256_ms_ctx_t* ctx, uint8_t* out_hash) { - sha256_final(ctx, out_hash); - return true; -} - -// *** keccak256 *** -bool hash_keccak256_init(hash_keccak256_ctx_t* ctx) { - keccak_init(ctx); - return true; -} - -bool hash_keccak256_update(hash_keccak256_ctx_t* ctx, - const uint8_t* data, - size_t len) { - keccak_update(ctx, data, len); - return true; -} - -bool hash_keccak256_final(hash_keccak256_ctx_t* ctx, uint8_t* out_hash) { - keccak_final(ctx, out_hash); - return true; -} \ No newline at end of file diff --git a/firmware/src/hal/x86/src/hash.c b/firmware/src/hal/x86/src/hash.c new file mode 120000 index 00000000..3bbd5a33 --- /dev/null +++ b/firmware/src/hal/x86/src/hash.c @@ -0,0 +1 @@ +../../common_linked/src/hash.c \ No newline at end of file diff --git a/firmware/src/hal/x86/src/hmac_sha512.c b/firmware/src/hal/x86/src/hmac_sha512.c deleted file mode 100644 index aaf9a121..00000000 --- a/firmware/src/hal/x86/src/hmac_sha512.c +++ /dev/null @@ -1,397 +0,0 @@ -/** - * The MIT License (MIT) - * - * Copyright (c) 2021 RSK Labs Ltd - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -/** - * Taken from https://github.com/someone42/hardware-bitcoin-wallet @ - * 102c300d994712484c3c028b215f90a6f99d6155 and adapted for use with - * the powHSM HAL by RootstockLabs. LICENSE transcribed below. - */ - -/* - Copyright (c) 2011-2012 someone42 - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER 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. -*/ - -/** \file hmac_sha512.c - * - * \brief Calculates HMAC-SHA512 hashes. - * - * This file contains an implementation of SHA-512, as well as a wrapper - * around the SHA-512 implementation which converts it into a keyed - * message authentication code. - * - * The SHA-512 implementation is based on the formulae and pseudo-code in - * FIPS PUB 180-4. The HMAC wrapper is based on the pseudo-code in - * FIPS PUB 198. - * - * Since SHA-512 is based on 64 bit operations, the code in sha256.c and - * hash.c cannot be re-used here, despite the essentially identical structure - * of SHA-256 and SHA-512. - */ - -#include "endian.h" -#include "hmac_sha512.h" - -#include -#include -#include -#include - -/** Get maximum of a and b. - * \warning Do not use this if the evaluation of a and b has side effects. - */ -#define MAX(a, b) (((a) > (b)) ? (a) : (b)) -/** Get minimum of a and b. - * \warning Do not use this if the evaluation of a and b has side effects. - */ -#define MIN(a, b) (((a) < (b)) ? (a) : (b)) - -#define NOINLINE - -#define PROGMEM -/** Use this to access #PROGMEM lookup tables which have dword (32 bit) - * entries. For example, normally you would use `r = dword_table[i];` but - * for a #PROGMEM table, use `r = LOOKUP_DWORD(dword_table[i]);`. */ -#define LOOKUP_DWORD(x) (x) -/** Use this to access #PROGMEM lookup tables which have byte (8 bit) - * entries. For example, normally you would use `r = byte_table[i];` but - * for a #PROGMEM table, use `r = LOOKUP_BYTE(byte_table[i]);`. */ -#define LOOKUP_BYTE(x) (x) -/** Use this to access #PROGMEM lookup tables which have qword (64 bit) - * entries. For example, normally you would use `r = qword_table[i];` but - * for a #PROGMEM table, use `r = LOOKUP_QWORD(qword_table[i]);`. */ -#define LOOKUP_QWORD(x) (x) - -/** Container for 64 bit hash state. */ -typedef struct HashState64Struct { - /** Where final hash value will be placed. */ - uint64_t h[8]; - /** Current index into HashState64#m, ranges from 0 to 15. */ - uint8_t index_m; - /** Current byte within (64 bit) double word of HashState64#m. 0 = most - * significant byte, 7 = least significant byte. */ - uint8_t byte_position_m; - /** 1024 bit message buffer. */ - uint64_t m[16]; - /** Total length of message; updated as bytes are written. */ - uint32_t message_length; -} HashState64; - -/** Constants for SHA-512. See section 4.2.3 of FIPS PUB 180-4. */ -static const uint64_t k[80] PROGMEM = { - 0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, - 0xe9b5dba58189dbbc, 0x3956c25bf348b538, 0x59f111f1b605d019, - 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, 0xd807aa98a3030242, - 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2, - 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235, - 0xc19bf174cf692694, 0xe49b69c19ef14ad2, 0xefbe4786384f25e3, - 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65, 0x2de92c6f592b0275, - 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5, - 0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f, - 0xbf597fc7beef0ee4, 0xc6e00bf33da88fc2, 0xd5a79147930aa725, - 0x06ca6351e003826f, 0x142929670a0e6e70, 0x27b70a8546d22ffc, - 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df, - 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, - 0x92722c851482353b, 0xa2bfe8a14cf10364, 0xa81a664bbc423001, - 0xc24b8b70d0f89791, 0xc76c51a30654be30, 0xd192e819d6ef5218, - 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8, - 0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99, - 0x34b0bcb5e19b48a8, 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, - 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3, 0x748f82ee5defb2fc, - 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec, - 0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, - 0xc67178f2e372532b, 0xca273eceea26619c, 0xd186b8c721c0c207, - 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, 0x06f067aa72176fba, - 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b, - 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, - 0x431d67c49c100d4c, 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, - 0x5fcb6fab3ad6faec, 0x6c44198c4a475817}; - -/** 64 bit rotate right. - * \param x The integer to rotate right. - * \param n Number of times to rotate right. - * \return The rotated integer. - */ -static uint64_t rotateRight(const uint64_t x, const uint8_t n) { - return (x >> n) | (x << (64 - n)); -} - -/** Function defined as (4.8) in section 4.1.3 of FIPS PUB 180-4. - * \param x First input integer. - * \param y Second input integer. - * \param z Third input integer. - * \return Non-linear combination of x, y and z. - */ -static uint64_t ch(const uint64_t x, const uint64_t y, const uint64_t z) { - return (x & y) ^ ((~x) & z); -} - -/** Function defined as (4.9) in section 4.1.3 of FIPS PUB 180-4. - * \param x First input integer. - * \param y Second input integer. - * \param z Third input integer. - * \return Non-linear combination of x, y and z. - */ -static uint64_t maj(const uint64_t x, const uint64_t y, const uint64_t z) { - return (x & y) ^ (x & z) ^ (y & z); -} - -/** Function defined as (4.10) in section 4.1.3 of FIPS PUB 180-4. - * \param x Input integer. - * \return Transformed integer. - */ -static uint64_t bigSigma0(const uint64_t x) { - return rotateRight(x, 28) ^ rotateRight(x, 34) ^ rotateRight(x, 39); -} - -/** Function defined as (4.11) in section 4.1.3 of FIPS PUB 180-4. - * \param x Input integer. - * \return Transformed integer. - */ -static uint64_t bigSigma1(const uint64_t x) { - return rotateRight(x, 14) ^ rotateRight(x, 18) ^ rotateRight(x, 41); -} - -/** Function defined as (4.12) in section 4.1.3 of FIPS PUB 180-4. - * \param x Input integer. - * \return Transformed integer. - */ -static uint64_t littleSigma0(const uint64_t x) { - return rotateRight(x, 1) ^ rotateRight(x, 8) ^ (x >> 7); -} - -/** Function defined as (4.13) in section 4.1.3 of FIPS PUB 180-4. - * \param x Input integer. - * \return Transformed integer. - */ -static uint64_t littleSigma1(const uint64_t x) { - return rotateRight(x, 19) ^ rotateRight(x, 61) ^ (x >> 6); -} - -/** Update hash value based on the contents of a full message buffer. - * This implements the pseudo-code in section 6.4.2 of FIPS PUB 180-4. - * \param hs64 The 64 bit hash state to update. - */ -static void sha512Block(HashState64 *hs64) { - uint64_t a, b, c, d, e, f, g, h; - uint64_t t1, t2; - uint8_t t; - uint64_t w[80]; - - for (t = 0; t < 16; t++) { - w[t] = hs64->m[t]; - } - for (t = 16; t < 80; t++) { - w[t] = littleSigma1(w[t - 2]) + w[t - 7] + littleSigma0(w[t - 15]) + - w[t - 16]; - } - a = hs64->h[0]; - b = hs64->h[1]; - c = hs64->h[2]; - d = hs64->h[3]; - e = hs64->h[4]; - f = hs64->h[5]; - g = hs64->h[6]; - h = hs64->h[7]; - for (t = 0; t < 80; t++) { - t1 = h + bigSigma1(e) + ch(e, f, g) + LOOKUP_QWORD(k[t]) + w[t]; - t2 = bigSigma0(a) + maj(a, b, c); - h = g; - g = f; - f = e; - e = d + t1; - d = c; - c = b; - b = a; - a = t1 + t2; - } - hs64->h[0] += a; - hs64->h[1] += b; - hs64->h[2] += c; - hs64->h[3] += d; - hs64->h[4] += e; - hs64->h[5] += f; - hs64->h[6] += g; - hs64->h[7] += h; -} - -/** Clear the message buffer. - * \param hs64 The 64 bit hash state to act on. - */ -static void clearM(HashState64 *hs64) { - hs64->index_m = 0; - hs64->byte_position_m = 0; - memset(hs64->m, 0, sizeof(hs64->m)); -} - -/** Begin calculating hash for new message. - * See section 5.3.5 of FIPS PUB 180-4. - * \param hs64 The 64 bit hash state to initialise. - */ -static void sha512Begin(HashState64 *hs64) { - hs64->message_length = 0; - hs64->h[0] = 0x6a09e667f3bcc908; - hs64->h[1] = 0xbb67ae8584caa73b; - hs64->h[2] = 0x3c6ef372fe94f82b; - hs64->h[3] = 0xa54ff53a5f1d36f1; - hs64->h[4] = 0x510e527fade682d1; - hs64->h[5] = 0x9b05688c2b3e6c1f; - hs64->h[6] = 0x1f83d9abfb41bd6b; - hs64->h[7] = 0x5be0cd19137e2179; - clearM(hs64); -} - -/** Add one more byte to the message buffer and call sha512Block() - * if the message buffer is full. - * \param hs64 The 64 bit hash state to act on. - * \param byte The byte to add. - */ -static void sha512WriteByte(HashState64 *hs64, const uint8_t byte) { - unsigned int pos; - unsigned int shift_amount; - - hs64->message_length++; - pos = (unsigned int)(7 - hs64->byte_position_m); - shift_amount = pos << 3; - hs64->m[hs64->index_m] |= ((uint64_t)byte << shift_amount); - - if (hs64->byte_position_m == 7) { - hs64->index_m++; - } - hs64->byte_position_m = (uint8_t)((hs64->byte_position_m + 1) & 7); - if (hs64->index_m == 16) { - sha512Block(hs64); - clearM(hs64); - } -} - -/** Finalise the hashing of a message by writing appropriate padding and - * length bytes, then write the hash value into a byte array. - * \param out A byte array where the final SHA-512 hash value will be written - * into. This must have space for #SHA512_HASH_LENGTH bytes. - * \param hs64 The 64 bit hash state to act on. - */ -static void sha512Finish(uint8_t *out, HashState64 *hs64) { - uint32_t length_bits; - uint8_t i; - uint8_t buffer[16]; - - // Subsequent calls to sha512WriteByte() will keep incrementing - // message_length, so the calculation of length (in bits) must be - // done before padding. - length_bits = hs64->message_length << 3; - - // Pad using a 1 bit followed by enough 0 bits to get the message buffer - // to exactly 896 bits full. - sha512WriteByte(hs64, (uint8_t)0x80); - while ((hs64->index_m != 14) || (hs64->byte_position_m != 0)) { - sha512WriteByte(hs64, 0); - } - // Write 128 bit length (in bits). - memset(buffer, 0, 16); - write_uint32_be(&(buffer[12]), length_bits); - for (i = 0; i < 16; i++) { - sha512WriteByte(hs64, buffer[i]); - } - for (i = 0; i < 8; i++) { - write_uint32_be(&(out[i * 8]), (uint32_t)(hs64->h[i] >> 32)); - write_uint32_be(&(out[i * 8 + 4]), (uint32_t)hs64->h[i]); - } -} - -/** Calculate a 64 byte HMAC of an arbitrary message and key using SHA-512 as - * the hash function. - * The code in here is based on the description in section 5 - * ("HMAC SPECIFICATION") of FIPS PUB 198. - * \param out A byte array where the HMAC-SHA512 hash value will be written. - * This must have space for #SHA512_HASH_LENGTH bytes. - * \param key A byte array containing the key to use in the HMAC-SHA512 - * calculation. The key can be of any length. - * \param key_length The length, in bytes, of the key. - * \param text A byte array containing the message to use in the HMAC-SHA512 - * calculation. The message can be of any length. - * \param text_length The length, in bytes, of the message. - */ -void hmac_sha512(uint8_t *out, - const uint8_t *key, - const unsigned int key_length, - const uint8_t *text, - const unsigned int text_length) { - unsigned int i; - uint8_t hash[SHA512_HASH_LENGTH]; - uint8_t padded_key[128]; - HashState64 hs64; - - // Determine key. - memset(padded_key, 0, sizeof(padded_key)); - if (key_length <= sizeof(padded_key)) { - memcpy(padded_key, key, key_length); - } else { - sha512Begin(&hs64); - for (i = 0; i < key_length; i++) { - sha512WriteByte(&hs64, key[i]); - } - sha512Finish(padded_key, &hs64); - } - // Calculate hash = H((K_0 XOR ipad) || text). - sha512Begin(&hs64); - for (i = 0; i < sizeof(padded_key); i++) { - sha512WriteByte(&hs64, (uint8_t)(padded_key[i] ^ 0x36)); - } - for (i = 0; i < text_length; i++) { - sha512WriteByte(&hs64, text[i]); - } - sha512Finish(hash, &hs64); - // Calculate H((K_0 XOR opad) || hash). - sha512Begin(&hs64); - for (i = 0; i < sizeof(padded_key); i++) { - sha512WriteByte(&hs64, (uint8_t)(padded_key[i] ^ 0x5c)); - } - for (i = 0; i < sizeof(hash); i++) { - sha512WriteByte(&hs64, hash[i]); - } - sha512Finish(out, &hs64); -} diff --git a/firmware/src/hal/x86/src/hmac_sha512.c b/firmware/src/hal/x86/src/hmac_sha512.c new file mode 120000 index 00000000..4582d35e --- /dev/null +++ b/firmware/src/hal/x86/src/hmac_sha512.c @@ -0,0 +1 @@ +../../common_linked/src/hmac_sha512.c \ No newline at end of file diff --git a/firmware/src/hal/x86/src/hmac_sha512.h b/firmware/src/hal/x86/src/hmac_sha512.h deleted file mode 100644 index 6b6fb586..00000000 --- a/firmware/src/hal/x86/src/hmac_sha512.h +++ /dev/null @@ -1,77 +0,0 @@ -/** - * The MIT License (MIT) - * - * Copyright (c) 2021 RSK Labs Ltd - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -/** - * Taken from https://github.com/someone42/hardware-bitcoin-wallet @ - * 102c300d994712484c3c028b215f90a6f99d6155 and adapted for use with - * the powHSM HAL by RootstockLabs. LICENSE transcribed below. - */ - -/* - Copyright (c) 2011-2012 someone42 - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER 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. -*/ - -/** \file hmac_sha512.h - * - * \brief Describes constants and functions exported by hmac_sha512.c. - */ - -#ifndef __HMAC_SHA512_H -#define __HMAC_SHA512_H - -#include - -/** Number of bytes a SHA-512 hash requires. */ -#define SHA512_HASH_LENGTH 64 - -extern void hmac_sha512(uint8_t *out, - const uint8_t *key, - const unsigned int key_length, - const uint8_t *text, - const unsigned int text_length); - -#endif // #ifndef __HMAC_SHA512_H diff --git a/firmware/src/hal/x86/src/hmac_sha512.h b/firmware/src/hal/x86/src/hmac_sha512.h new file mode 120000 index 00000000..e36d261d --- /dev/null +++ b/firmware/src/hal/x86/src/hmac_sha512.h @@ -0,0 +1 @@ +../../common_linked/src/hmac_sha512.h \ No newline at end of file diff --git a/firmware/src/hal/x86/src/keccak256.c b/firmware/src/hal/x86/src/keccak256.c deleted file mode 100644 index e5084372..00000000 --- a/firmware/src/hal/x86/src/keccak256.c +++ /dev/null @@ -1,267 +0,0 @@ -/** - * The MIT License (MIT) - * - * Copyright (c) 2021 RSK Labs Ltd - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -/** - * Third party library taken from: - * https://github.com/firefly/wallet/blob/29adeaf7029142063b7a6878e049efd4c6534982/source/libs/ethers/src/keccak256.c - */ - -/* sha3 - an implementation of Secure Hash Algorithm 3 (Keccak). - * based on the - * The Keccak SHA-3 submission. Submission to NIST (Round 3), 2011 - * by Guido Bertoni, Joan Daemen, Michaël Peeters and Gilles Van Assche - * - * Copyright: 2013 Aleksey Kravchenko - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. Use this program at your own risk! - */ - -#include "keccak256.h" - -//#include - -#include -#include - -#define BLOCK_SIZE ((1600 - 256 * 2) / 8) - -#define I64(x) x##LL -#define ROTL64(qword, n) ((qword) << (n) ^ ((qword) >> (64 - (n)))) -#define le2me_64(x) (x) -#define IS_ALIGNED_64(p) (0 == (7 & ((const char*)(p) - (const char*)0))) -#define me64_to_le_str(to, from, length) memcpy((to), (from), (length)) - -/* constants */ - -//const uint8_t round_constant_info[] PROGMEM = { -//const uint8_t constants[] PROGMEM = { -const uint8_t constants[] = { - - 1, 26, 94, 112, 31, 33, 121, 85, 14, 12, 53, 38, 63, 79, 93, 83, 82, 72, 22, 102, 121, 88, 33, 116, -//}; - -//const uint8_t pi_transform[] PROGMEM = { - 1, 6, 9, 22, 14, 20, 2, 12, 13, 19, 23, 15, 4, 24, 21, 8, 16, 5, 3, 18, 17, 11, 7, 10, -//}; - -//const uint8_t rhoTransforms[] PROGMEM = { - 1, 62, 28, 27, 36, 44, 6, 55, 20, 3, 10, 43, 25, 39, 41, 45, 15, 21, 8, 18, 2, 61, 56, 14, -}; - -#define TYPE_ROUND_INFO 0 -#define TYPE_PI_TRANSFORM 24 -#define TYPE_RHO_TRANSFORM 48 - -uint8_t getConstant(uint8_t type, uint8_t index) { - return constants[type + index]; -} - -static uint64_t get_round_constant(uint8_t round) { - uint64_t result = 0; - - uint8_t roundInfo = getConstant(TYPE_ROUND_INFO, round); - if (roundInfo & (1 << 6)) { result |= ((uint64_t)1 << 63); } - if (roundInfo & (1 << 5)) { result |= ((uint64_t)1 << 31); } - if (roundInfo & (1 << 4)) { result |= ((uint64_t)1 << 15); } - if (roundInfo & (1 << 3)) { result |= ((uint64_t)1 << 7); } - if (roundInfo & (1 << 2)) { result |= ((uint64_t)1 << 3); } - if (roundInfo & (1 << 1)) { result |= ((uint64_t)1 << 1); } - if (roundInfo & (1 << 0)) { result |= ((uint64_t)1 << 0); } - - return result; -} - - -/* Initializing a sha3 context for given number of output bits */ -void keccak_init(SHA3_CTX *ctx) { - /* NB: The Keccak capacity parameter = bits * 2 */ - - memset(ctx, 0, sizeof(SHA3_CTX)); -} - -/* Keccak theta() transformation */ -static void keccak_theta(uint64_t *A) { - uint64_t C[5], D[5]; - - for (uint8_t i = 0; i < 5; i++) { - C[i] = A[i]; - for (uint8_t j = 5; j < 25; j += 5) { C[i] ^= A[i + j]; } - } - - for (uint8_t i = 0; i < 5; i++) { - D[i] = ROTL64(C[(i + 1) % 5], 1) ^ C[(i + 4) % 5]; - } - - for (uint8_t i = 0; i < 5; i++) { - //for (uint8_t j = 0; j < 25; j += 5) { - for (uint8_t j = 0; j < 25; j += 5) { A[i + j] ^= D[i]; } - } -} - - -/* Keccak pi() transformation */ -static void keccak_pi(uint64_t *A) { - uint64_t A1 = A[1]; - for (uint8_t i = 1; i < 24; i++) { - A[getConstant(TYPE_PI_TRANSFORM, i - 1)] = A[getConstant(TYPE_PI_TRANSFORM, i)]; - } - A[10] = A1; - /* note: A[ 0] is left as is */ -} - -/* -ketch uses 30084 bytes (93%) of program storage space. Maximum is 32256 bytes. -Global variables use 743 bytes (36%) of dynamic memory, leaving 1305 bytes for local variables. Maximum is 2048 bytes. - -*/ -/* Keccak chi() transformation */ -static void keccak_chi(uint64_t *A) { - for (uint8_t i = 0; i < 25; i += 5) { - uint64_t A0 = A[0 + i], A1 = A[1 + i]; - A[0 + i] ^= ~A1 & A[2 + i]; - A[1 + i] ^= ~A[2 + i] & A[3 + i]; - A[2 + i] ^= ~A[3 + i] & A[4 + i]; - A[3 + i] ^= ~A[4 + i] & A0; - A[4 + i] ^= ~A0 & A1; - } -} - - -static void sha3_permutation(uint64_t *state) { - for (uint8_t round = 0; round < 24; round++) { - keccak_theta(state); - - /* apply Keccak rho() transformation */ - for (uint8_t i = 1; i < 25; i++) { - state[i] = ROTL64(state[i], getConstant(TYPE_RHO_TRANSFORM, i - 1)); - } - - keccak_pi(state); - keccak_chi(state); - - /* apply iota(state, round) */ - *state ^= get_round_constant(round); - } -} - -/** - * The core transformation. Process the specified block of data. - * - * @param hash the algorithm state - * @param block the message block to process - * @param block_size the size of the processed block in bytes - */ -static void sha3_process_block(uint64_t hash[25], const uint64_t *block) { - for (uint8_t i = 0; i < 17; i++) { - hash[i] ^= le2me_64(block[i]); - } - - /* make a permutation of the hash */ - sha3_permutation(hash); -} - -//#define SHA3_FINALIZED 0x80000000 -//#define SHA3_FINALIZED 0x8000 - -/** - * Calculate message hash. - * Can be called repeatedly with chunks of the message to be hashed. - * - * @param ctx the algorithm context containing current hashing state - * @param msg message chunk - * @param size length of the message chunk - */ -void keccak_update(SHA3_CTX *ctx, const unsigned char *msg, uint16_t size) -{ - uint16_t idx = (uint16_t)ctx->rest; - - //if (ctx->rest & SHA3_FINALIZED) return; /* too late for additional input */ - ctx->rest = (unsigned)((ctx->rest + size) % BLOCK_SIZE); - - /* fill partial block */ - if (idx) { - uint16_t left = BLOCK_SIZE - idx; - memcpy((char*)ctx->message + idx, msg, (size < left ? size : left)); - if (size < left) return; - - /* process partial block */ - sha3_process_block(ctx->hash, ctx->message); - msg += left; - size -= left; - } - - while (size >= BLOCK_SIZE) { - uint64_t* aligned_message_block; - if (IS_ALIGNED_64(msg)) { - // the most common case is processing of an already aligned message without copying it - aligned_message_block = (uint64_t*)(void*)msg; - } else { - memcpy(ctx->message, msg, BLOCK_SIZE); - aligned_message_block = ctx->message; - } - - sha3_process_block(ctx->hash, aligned_message_block); - msg += BLOCK_SIZE; - size -= BLOCK_SIZE; - } - - if (size) { - memcpy(ctx->message, msg, size); /* save leftovers */ - } -} - -/** -* Store calculated hash into the given array. -* -* @param ctx the algorithm context containing current hashing state -* @param result calculated hash in binary form -*/ -void keccak_final(SHA3_CTX *ctx, unsigned char* result) -{ - uint16_t digest_length = 100 - BLOCK_SIZE / 2; - -// if (!(ctx->rest & SHA3_FINALIZED)) { - /* clear the rest of the data queue */ - memset((char*)ctx->message + ctx->rest, 0, BLOCK_SIZE - ctx->rest); - ((char*)ctx->message)[ctx->rest] |= 0x01; - ((char*)ctx->message)[BLOCK_SIZE - 1] |= 0x80; - - /* process final block */ - sha3_process_block(ctx->hash, ctx->message); -// ctx->rest = SHA3_FINALIZED; /* mark context as finalized */ -// } - - if (result) { - me64_to_le_str(result, ctx->hash, digest_length); - } -} diff --git a/firmware/src/hal/x86/src/keccak256.c b/firmware/src/hal/x86/src/keccak256.c new file mode 120000 index 00000000..06fef5f0 --- /dev/null +++ b/firmware/src/hal/x86/src/keccak256.c @@ -0,0 +1 @@ +../../common_linked/src/keccak256.c \ No newline at end of file diff --git a/firmware/src/hal/x86/src/keccak256.h b/firmware/src/hal/x86/src/keccak256.h deleted file mode 100644 index c2d15d7b..00000000 --- a/firmware/src/hal/x86/src/keccak256.h +++ /dev/null @@ -1,81 +0,0 @@ -/** - * The MIT License (MIT) - * - * Copyright (c) 2021 RSK Labs Ltd - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -/** - * Third party library taken from: - * https://github.com/firefly/wallet/blob/29adeaf7029142063b7a6878e049efd4c6534982/source/libs/ethers/src/keccak256.h - */ - -/* sha3 - an implementation of Secure Hash Algorithm 3 (Keccak). - * based on the - * The Keccak SHA-3 submission. Submission to NIST (Round 3), 2011 - * by Guido Bertoni, Joan Daemen, Michaël Peeters and Gilles Van Assche - * - * Copyright: 2013 Aleksey Kravchenko - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. Use this program at your own risk! - */ - -#ifndef __KECCAK256_H_ -#define __KECCAK256_H_ - -#include - -#define sha3_max_permutation_size 25 -#define sha3_max_rate_in_qwords 24 - -typedef struct SHA3_CTX { - /* 1600 bits algorithm hashing state */ - uint64_t hash[sha3_max_permutation_size]; - /* 1536-bit buffer for leftovers */ - uint64_t message[sha3_max_rate_in_qwords]; - /* count of bytes in the message[] buffer */ - uint16_t rest; -} SHA3_CTX; - - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - - -void keccak_init(SHA3_CTX *ctx); -void keccak_update(SHA3_CTX *ctx, const unsigned char *msg, uint16_t size); -void keccak_final(SHA3_CTX *ctx, unsigned char* result); - - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __KECCAK256_H_ */ diff --git a/firmware/src/hal/x86/src/keccak256.h b/firmware/src/hal/x86/src/keccak256.h new file mode 120000 index 00000000..19f06fef --- /dev/null +++ b/firmware/src/hal/x86/src/keccak256.h @@ -0,0 +1 @@ +../../common_linked/src/keccak256.h \ No newline at end of file diff --git a/firmware/src/hal/x86/src/sha256.c b/firmware/src/hal/x86/src/sha256.c index ceea83a9..dd0468a1 120000 --- a/firmware/src/hal/x86/src/sha256.c +++ b/firmware/src/hal/x86/src/sha256.c @@ -1 +1 @@ -../../common/src/sha256.c \ No newline at end of file +../../common_linked/src/sha256.c \ No newline at end of file diff --git a/firmware/src/hal/x86/src/sha256.h b/firmware/src/hal/x86/src/sha256.h index acd90f89..d920bc5d 120000 --- a/firmware/src/hal/x86/src/sha256.h +++ b/firmware/src/hal/x86/src/sha256.h @@ -1 +1 @@ -../../common/src/sha256.h \ No newline at end of file +../../common_linked/src/sha256.h \ No newline at end of file diff --git a/firmware/src/hal/x86/test/run-all.sh b/firmware/src/hal/x86/test/run-all.sh index 0628d598..758444e3 100755 --- a/firmware/src/hal/x86/test/run-all.sh +++ b/firmware/src/hal/x86/test/run-all.sh @@ -2,7 +2,7 @@ if [[ $1 == "exec" ]]; then BASEDIR=$(realpath $(dirname $0)) - TESTDIRS="bip32 endian hmac_sha256 hmac_sha512 keccak256" + TESTDIRS="hmac_sha256" for d in $TESTDIRS; do echo "******************************" echo "Testing $d..." diff --git a/firmware/src/ledger/ui/test/onboard/test_onboard.c b/firmware/src/ledger/ui/test/onboard/test_onboard.c index bcc8e555..4ac5f64c 100644 --- a/firmware/src/ledger/ui/test/onboard/test_onboard.c +++ b/firmware/src/ledger/ui/test/onboard/test_onboard.c @@ -206,7 +206,7 @@ void test_set_host_seed() { 0xfd, 0x4b, 0x6d, 0xcd, 0xc0, 0x62, 0x61, 0x53, 0x03, 0xf0, 0xef, 0x03, 0xce, 0x84, 0x15, 0xd3}; unsigned int rx = 4; - for (int i = 0; i < strlen(host_seed); i++) { + for (int i = 0; i < sizeof(host_seed) / sizeof(host_seed[0]); i++) { SET_APDU_AT(2, i); SET_APDU_AT(3, host_seed[i]); assert(0 == set_host_seed(rx, &onboard_ctx));