diff --git a/configure.ac b/configure.ac index b6dc6d358..bb11a926d 100644 --- a/configure.ac +++ b/configure.ac @@ -2852,6 +2852,39 @@ AC_ARG_WITH([cryptoauthlib], ] ) + +# TropicSquare TROPIC01 +# Example: "./configure --with-tropic01=/home/pi/libtropic" +ENABLED_TROPIC01="no" +trylibtropicdir="" +AC_ARG_WITH([tropic01], + [AS_HELP_STRING([--with-tropic01=PATH],[PATH to install (default /usr/)])], + [ + AC_MSG_CHECKING([for libtropic]) + if test "x$withval" != "xno" ; then + trylibtropicdir=$withval + fi + if test "x$withval" = "xyes" ; then + trylibtropicdir="libtropic" + fi + if test -e $trylibtropicdir/build/libtropic.a + then + LIB_STATIC_ADD="$LIB_STATIC_ADD $trylibtropicdir/build/libtropic.a" + LIB_STATIC_ADD="$LIB_STATIC_ADD $trylibtropicdir/build/trezor_crypto/libtrezor_crypto.a" + AM_CFLAGS="$AM_CFLAGS -I$trylibtropicdir/include" + else + ENABLED_TROPIC01="no" + AC_MSG_ERROR([Could not find libtropic - TropicSquare library]) + fi + enable_shared=no + enable_static=yes + ENABLED_TROPIC01="yes" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_TROPIC01" + AC_MSG_RESULT([yes]) + ] +) + + # NXP SE050 # Example: "./configure --with-se050=/home/pi/simw_top" ENABLED_SE050="no" @@ -10705,6 +10738,7 @@ AM_CONDITIONAL([BUILD_QNXCAAM],[test "x$ENABLED_CAAM_QNX" = "xyes"]) AM_CONDITIONAL([BUILD_IOTSAFE],[test "x$ENABLED_IOTSAFE" = "xyes"]) AM_CONDITIONAL([BUILD_IOTSAFE_HWRNG],[test "x$ENABLED_IOTSAFE_HWRNG" = "xyes"]) AM_CONDITIONAL([BUILD_SE050],[test "x$ENABLED_SE050" = "xyes"]) +AM_CONDITIONAL([BUILD_TROPIC01],[test "x$ENABLED_TROPIC01" = "xyes"]) AM_CONDITIONAL([BUILD_KDF],[test "x$ENABLED_KDF" = "xyes"]) AM_CONDITIONAL([BUILD_HMAC],[test "x$ENABLED_HMAC" = "xyes"]) AM_CONDITIONAL([BUILD_ERROR_STRINGS],[test "x$ENABLED_ERROR_STRINGS" = "xyes"]) @@ -11233,6 +11267,7 @@ echo " * i.MX CAAM: $ENABLED_CAAM" echo " * IoT-Safe: $ENABLED_IOTSAFE" echo " * IoT-Safe HWRNG: $ENABLED_IOTSAFE_HWRNG" echo " * NXP SE050: $ENABLED_SE050" +echo " * TROPIC01: $ENABLED_TROPIC01" echo " * Maxim Integrated MAXQ10XX: $ENABLED_MAXQ10XX" echo " * PSA: $ENABLED_PSA" echo " * System CA certs: $ENABLED_SYS_CA_CERTS" diff --git a/wolfcrypt/src/include.am b/wolfcrypt/src/include.am index 151245120..7d44a3663 100644 --- a/wolfcrypt/src/include.am +++ b/wolfcrypt/src/include.am @@ -105,6 +105,8 @@ EXTRA_DIST += wolfcrypt/src/port/ti/ti-aes.c \ wolfcrypt/src/port/st/README.md \ wolfcrypt/src/port/st/STM32MP13.md \ wolfcrypt/src/port/st/STM32MP25.md \ + wolfcrypt/src/port/tropicsquare/tropic01.c \ + wolfcrypt/src/port/tropicsquare/README.md \ wolfcrypt/src/port/af_alg/afalg_aes.c \ wolfcrypt/src/port/af_alg/afalg_hash.c \ wolfcrypt/src/port/kcapi/kcapi_aes.c \ @@ -221,6 +223,10 @@ if BUILD_SE050 src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/nxp/se050_port.c endif +if BUILD_TROPIC01 +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/tropicsquare/tropic01.c +endif + if BUILD_PSA src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/psa/psa.c src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/psa/psa_hash.c diff --git a/wolfcrypt/src/port/tropicsquare/README.md b/wolfcrypt/src/port/tropicsquare/README.md new file mode 100644 index 000000000..4b1df37ad --- /dev/null +++ b/wolfcrypt/src/port/tropicsquare/README.md @@ -0,0 +1,232 @@ +# wolfSSL TROPIC01 Secure Element Integration Guide + +![wolfSSL+TROPIC01](https://img.shields.io/badge/wolfSSL-TROPIC01-blue) + + +Integration guide for using Tropic Square's TROPIC01 secure element with wolfSSL/wolfCrypt cryptography library. + +## Table of Contents +- [wolfSSL TROPIC01 Secure Element Integration Guide](#wolfssl-tropic01-secure-element-integration-guide) + - [Table of Contents](#table-of-contents) + - [TROPIC01 Secure Element with an open architecture](#tropic01-secure-element-with-an-open-architecture) + - [Hardware Overview](#hardware-overview) + - [TROPIC01 Specifications](#tropic01-specifications) + - [Available Evaluation and Development Kits](#available-evaluation-and-development-kits) + - [Get samples](#get-samples) + - [Build Configuration](#build-configuration) + - [Pre-requirements](#pre-requirements) + - [Keys installation](#keys-installation) + - [Build TROPIC01 SDK (libtropic)](#build-tropic01-sdk-libtropic) + - [Build wolfSSL](#build-wolfssl) + - [Build test application](#build-test-application) + +## TROPIC01 Secure Element with an open architecture + +The TROPIC01 secure element is built with tamper-proof technology and advanced attack countermeasures to ensure robust asset protection, securing electronic devices against a wide range of potential attacks. It securely supplies and stores the cryptographic keys of embedded solutions. +The TROPIC01 datasheet is available via [this link](https://github.com/tropicsquare/tropic01/blob/main/doc/datasheet/ODD_tropic01_datasheet_revA6.pdf) + +## Hardware Overview + +### TROPIC01 Specifications +- **Crypto Accelerators**: + - Elliptic curve cryptography + - Ed25519 EdDSA signing + - P-256 ECDSA signing + - Diffie-Hellman X25519 key exchange + - Keccak-based PIN authentication engine +- **Tamper Resistance**: + - Voltage glitch detector + - Temperature detector + - Electromagnetic pulse detector + - Laser detector + - Active shield +- **Interface to Host MCU/MPU**: + - SPI + - Encrypted channel with forward secrecy +- **Entropy Source**: + - Physically Unclonable Function (PUF) + - True Random Number Generator (TRNG) + +### Available Evaluation and Development Kits +- USB Stick with TROPIC01 ([here](https://github.com/tropicsquare/tropic01?tab=readme-ov-file#usb-stick-with-tropic01)) +- Raspberry PI shield ([here](https://github.com/tropicsquare/tropic01?tab=readme-ov-file#rpi-shield-ts1501)) +- Arduino shield ([here](https://github.com/tropicsquare/tropic01?tab=readme-ov-file#arduino-shield-ts14)) + +### Get samples +To get samples and DevKits, please fill in [this form](https://tropicsquare.com/tropic01-samples#form) + +## Build Configuration + +### Pre-requirements +1. Get one of the targeted hardware platforms. For example, Linux PC + TROPIC01 USB stick or Raspberry PI 3/4/5 + TROPIC01 RPI shield +2. Install toolchain (incl. compiler or cross-compiler). For example, GNU Toolchain (gcc) or ARM cross-compiling toolchain (armv8-rpi3-linux-gnueabihf) +3. Install CMake and Autotools +4. Install Git + + Some guidelines for RPi are available [here](https://earthly.dev/blog/cross-compiling-raspberry-pi/) + +Also, for Raspberry PI, there are a few more steps: + +1. In raspi-config go to "Interface Options" and enable SPI +2. Install wiringPI: + +```sh +$ wget https://github.com/WiringPi/WiringPi/releases/download/3.14/wiringpi_3.14_arm64.deb +$ sudo apt install ./wiringpi_3.14_arm64.deb +``` + +### Keys installation + +For the integration with wolfSSL, there are a few pre-defined slots for the secure keys storage (the slots mapping might be changed in tropic01.h): +```sh +TROPIC01_AES_KEY_RMEM_SLOT 0 // slot in R-memory for AES key +TROPIC01_AES_IV_RMEM_SLOT 1 // slot in R-memory for AES IV +TROPIC01_ED25519_PUB_RMEM_SLOT_DEFAULT 2 // slot in R-memory for ED25519 Public key +TROPIC01_ED25519_PRIV_RMEM_SLOT_DEFAULT 3 //slot in R-memory for ED25519 Private key +TROPIC01_ED25519_ECC_SLOT_DEFAULT 1 // slot in ECC keys storage for both public and private keys +PAIRING_KEY_SLOT_INDEX_0 0 //pairing keys slot +``` +All R-memory based keys must be pre-provisioned in the TROPIC01 Secure Element separately. For example, it might be done with the libtropic-util tool available [here] (https://github.com/tropicsquare/libtropic-util) + +### Build TROPIC01 SDK (libtropic) + +wolfSSL uses the "TROPIC01 SDK" (aka libtropic) to interface with TROPIC01. This SDK can be cloned from the TropicSquare GitHub https://github.com/tropicsquare/libtropic + +Once the repo was downloaded, please follow [this guideline](https://github.com/tropicsquare/libtropic/blob/master/docs/index.md#integration-examples) on how to configure and build TROPIC01 SDK + +Or run the following commands: +```sh + $ git clone https://github.com/tropicsquare/libtropic.git + $ cd libtropic + $ mkdir build && cd build + $ cmake -DLT_USE_TREZOR_CRYPTO=1 .. + $ make +``` + +### Build wolfSSL +1. Clone wolfSSL from the wolfSSL GitHub (https://github.com/wolfSSL/wolfssl) + +2. Make sure that the version of wolfSSL supports TROPIC01 - check if the folder wolfssl/wolfcrypt/src/port/tropicsquare exists + +3. To compile wolfSSL with TROPIC01 support using Autoconf/configure: + +```sh +$ cd wolfssl +$ ./autogen.sh +$ ./configure --with-tropic01=PATH --enable-cryptocb --enable-static --disable-crypttests --disable-examples --disable-shared --enable-ed25519 +$ make +$ sudo make install +``` +where PATH is an absolute path to the libtropic folder, for example + + --with-tropic01=/home/pi/git/libtropic + +For the debugging output, add + + --enable-debug + +### Build test application + +The test application for Raspberry Shield and USB stick can be cloned from the TropicSquare GitHub https://github.com/tropicsquare/tropic01-wolfssl-test + +To build and run the test application, please run the following commands + +```sh +$ git clone git@github.com:tropicsquare/tropic01-wolfssl-test.git +$ cd tropic01-wolfssl-test +``` +If necessary, open and edit the Makefile in this folder + +Set correct values for CC and LIBTROPIC_DIR variables, for example: + + CC = gcc + + LIBTROPIC_DIR = /home/pi/git/libtropic + +Then run the following commands to build and run the test application for the USB stick: + +```sh +$ make +$ ./lt-wolfssl-test +``` +or for Raspberry PI shield (make sure you fulfill all prerequisites first): + + +```sh +$ make RPI_SPI=1 +$ ./lt-wolfssl-test +``` + +In case of success, the output of the test application should look like this: + +```sh +wolfSSL Crypto Callback Test Application +======================================== +wolfSSL Entering wolfCrypt_Init +TROPIC01: Crypto device initialized successfully +wolfCrypt initialized successfully +Registering crypto callback with device ID 481111... +Crypto callback registered successfully +RNG_HEALTH_TEST_CHECK_SIZE = 128 +sizeof(seedB_data) = 128 +TROPIC01: CryptoCB: SEED generation request (52 bytes) +TROPIC01: GetRandom: Requesting 52 bytes +TROPIC01: GetRandom: Completed with ret=0 +TROPIC01: CryptoCB: RNG generation request (32 bytes) +TROPIC01: GetRandom: Requesting 32 bytes +TROPIC01: GetRandom: Completed with ret=0 +Generated 32 random bytes: +94F589E8 9C59B5A2 C8426FB6 9C548623 +358551CE 07238D37 EBF7FEE5 42BEB299 + +RNG test completed successfully + +AES test starting: +TROPIC01: CryptoCB: AES request +TROPIC01: Get AES Key: Retrieving key from slot 1 +TROPIC01: Get AES Key: Key retrieved successfully +Plain message: +01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 +Encrypted message: +89 44 11 3E 2E 07 52 9C CB 5F B1 70 7E 9C 42 D6 +AES test completed successfully + +ED25519 COMPREHENSIVE TESTING SUITE + +=== Ed25519 Key Generation Test === +✓ Ed25519 key structure initialized successfully +TROPIC01: CryptoCB: RNG generation request (32 bytes) +TROPIC01: GetRandom: Requesting 32 bytes +TROPIC01: GetRandom: Completed with ret=0 +✓ Ed25519 key pair generated successfully +Generated Public Key (32 bytes): +5D28BB98 AF86844E 5C2D48B6 473EA116 +0A98B568 3313915D 1565C540 AA3EB250 +✓ Ed25519 key generation test completed successfully + +=== Ed25519 Message Signing Test === +DEV_ID: 481111 +TROPIC01: CryptoCB: RNG generation request (64 bytes) +TROPIC01: GetRandom: Requesting 64 bytes +TROPIC01: GetRandom: Completed with ret=0 +Test Message (64 bytes): +000CD9C2 0FA2E218 67737744 4550F217 +5082408B 9F21F92B 06A570C4 C18AA073 +1B23836F 1CDC760B 7242F8A7 83B8EC9A +BF9E6D84 2E605AA1 0A168E88 FDEF38DA +TROPIC01: CryptoCB: ED25519 signing request +TROPIC01: Get ECC Key: Retrieving key from slot 3 +TROPIC01: Get ECC Key: Key retrieved successfully +✓ Message signed successfully +Signature length: 64 bytes +Generated Signature (64 bytes): +AE4B42CF 46F8F369 4F559390 0EDDA701 +A73A562B 3D03F429 8706309D 63E2120B +82B2A91F 6D7A7519 0CD62215 CABE3183 +433F4125 2CC017EB BD1E59A1 4A22CC09 +✓ Ed25519 message signing test completed successfully +wolfSSL Entering wolfCrypt_Cleanup +``` + + + diff --git a/wolfcrypt/src/port/tropicsquare/tropic01.c b/wolfcrypt/src/port/tropicsquare/tropic01.c new file mode 100644 index 000000000..cd58db1e6 --- /dev/null +++ b/wolfcrypt/src/port/tropicsquare/tropic01.c @@ -0,0 +1,525 @@ +/* tropic01.c + * + * Copyright (C) 2006-2025 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL 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. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + * +*/ + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#ifdef WOLFSSL_TROPIC01 + +#include +#include +#include +#include +#include + +#include + +static Tropic01CryptoDevCtx g_ctx = {0}; +static lt_handle_t g_h; + +/* Pairing keys for TROPIC01 (use Tropic01_SetPairingKeys() to set them)*/ +static byte pk_index = PAIRING_KEY_SLOT_INDEX_0; +static byte sh0priv[32] = {0}; +static byte sh0pub[32] = {0}; + +/* + * TROPIC01 hardware RNG implementation + */ +static int Tropic01_GetRandom(byte* out, word32 sz) +{ + int ret = 0; + WOLFSSL_MSG_EX("TROPIC01: GetRandom: Requesting %u bytes", sz); + + if (out == NULL || sz == 0) + return BAD_FUNC_ARG; + + + /* Call TROPIC01 TRNG API to get random data */ + + ret = lt_random_get(&g_h, out, sz); + if (ret != LT_OK) { + WOLFSSL_MSG_EX("TROPIC01: GetKey: Failed to retrieve key, ret=%d", ret); + return WC_HW_E; + } + + WOLFSSL_MSG_EX("TROPIC01: GetRandom: Completed with ret=%d", ret); + return 0; +} + +#if defined(HAVE_ED25519) && defined(HAVE_ED25519_MAKE_KEY) +/* + * TROPIC01 ECC keys generation implementation + */ +static int Tropic01_GenerateKeyED25519(byte* pubkey, int keySlot, word32 sz) +{ + lt_ret_t ret = 0; + + WOLFSSL_MSG_EX("TROPIC01: GenerateKeyED25519: Requesting %u bytes", sz); + + if (pubkey == NULL || sz != 32) + return BAD_FUNC_ARG; + + ret = lt_ecc_key_erase(&g_h, keySlot); + if (ret != LT_OK) { + WOLFSSL_MSG_EX("TROPIC01: GetKey: Failed to erase key, ret=%d", ret); + return WC_HW_E; + } + + ret = lt_ecc_key_generate(&g_h, keySlot, CURVE_ED25519); + if (ret != LT_OK) { + WOLFSSL_MSG_EX("TROPIC01: GetKey: Failed to generate key, ret=%d", ret); + return WC_HW_E; + } + lt_ecc_curve_type_t curve = CURVE_ED25519; + ecc_key_origin_t origin = CURVE_GENERATED; + ret = lt_ecc_key_read(&g_h, keySlot, pubkey, sz, &curve, &origin); + if (ret != LT_OK) { + WOLFSSL_MSG_EX("TROPIC01: GetKey: Failed to read pub key, ret=%d", ret); + return WC_HW_E; + } + + WOLFSSL_MSG_EX("TROPIC01: GenerateKeyED25519: Completed with ret=%d", ret); + + return 0; +} +#endif + +/* + * Retrieve the AES key from the secure R memory of TROPIC01 + */ + +static int Tropic01_GetKeyAES(byte* aesKey, int keySlot, word32 keySz) +{ + + lt_ret_t rett; + WOLFSSL_MSG_EX( + "TROPIC01: Get AES Key: Retrieving key from slot %d", + keySlot + ); + + if (aesKey == NULL || keySlot < 0 || keySlot >= 511) + return BAD_FUNC_ARG; + + + /* Check key size */ + if (keySz != 16 && keySz != 24 && keySz != 32) { + WOLFSSL_MSG_EX( + "TROPIC01: Get AES Key: Unsupported key size %u", + keySz + ); + return BAD_FUNC_ARG; + } + + /* Retrieve key from TROPIC01 */ + + rett = lt_r_mem_data_read(&g_h, keySlot, aesKey, keySz); + if (rett != LT_OK) { + WOLFSSL_MSG_EX( + "TROPIC01: Get AES Key: Failed to retrieve key, ret=%d", + rett + ); + return WC_HW_E; + } + + + WOLFSSL_MSG_EX("TROPIC01: Get AES Key: Key retrieved successfully"); + return 0; +} + +/* + * Retrieve the ECC key from the secure R memory of TROPIC01 + */ +static int Tropic01_GetKeyECC(byte* ecckey, int keySlot, word32 keySz) +{ + + lt_ret_t rett; + WOLFSSL_MSG_EX( + "TROPIC01: Get ECC Key: Retrieving key from slot %d", + keySlot + ); + + if (ecckey == NULL || keySlot < 0 || keySlot >= 511) + return BAD_FUNC_ARG; + + + /* Check key size */ + if (keySz != 16 && keySz != 24 && keySz != 32) { + WOLFSSL_MSG_EX( + "TROPIC01: Get ECC Key: Unsupported key size %u", + keySz + ); + return BAD_FUNC_ARG; + } + + /* Retrieve key from TROPIC01 */ + + rett = lt_r_mem_data_read(&g_h, keySlot, (byte*)ecckey, keySz); + if (rett != LT_OK) { + WOLFSSL_MSG_EX( + "TROPIC01: Get ECC Key: Failed to retrieve key, ret=%d", + rett + ); + return WC_HW_E; + } + + + WOLFSSL_MSG_EX("TROPIC01: Get ECC Key: Key retrieved successfully"); + return 0; +} + +/** + * Crypto Callback function for TROPIC01 + */ +int Tropic01_CryptoCb(int devId, wc_CryptoInfo* info, void* ctx) +{ + int ret = CRYPTOCB_UNAVAILABLE; + byte lt_key[TROPIC01_AES_MAX_KEY_SIZE] = {0}; + byte lt_iv[TROPIC01_AES_MAX_KEY_SIZE] = {0}; + + if (info == NULL) + return BAD_FUNC_ARG; + (void)ctx; + + if (g_ctx.initialized == 0) { + WOLFSSL_MSG("TROPIC01: CryptoCB: Device not initialized"); + return CRYPTOCB_UNAVAILABLE; + } + switch (info->algo_type) { + case WC_ALGO_TYPE_RNG: + WOLFSSL_MSG_EX( + "TROPIC01: CryptoCB: RNG generation request (%u bytes)", + info->rng.sz + ); + ret = Tropic01_GetRandom(info->rng.out, info->rng.sz); + break; + case WC_ALGO_TYPE_SEED: + WOLFSSL_MSG_EX( + "TROPIC01: CryptoCB: SEED generation request (%u bytes)", + info->seed.sz + ); + ret = Tropic01_GetRandom(info->seed.seed, info->seed.sz); + break; + case WC_ALGO_TYPE_PK: +#ifdef HAVE_ED25519 + #ifdef HAVE_ED25519_MAKE_KEY + if (info->pk.type == WC_PK_TYPE_ED25519_KEYGEN) { + WOLFSSL_MSG("TROPIC01: CryptoCB: ED25519 key generation request"); + ret = Tropic01_GenerateKeyED25519( + info->pk.ed25519kg.key->p, + TROPIC01_ED25519_ECC_SLOT_DEFAULT, + info->pk.ed25519kg.size); + } + #endif /* HAVE_ED25519_MAKE_KEY */ + #ifdef HAVE_ED25519_SIGN + if (info->pk.type == WC_PK_TYPE_ED25519_SIGN) { + + WOLFSSL_MSG("TROPIC01: CryptoCB: ED25519 signing request"); + /* retrieve private key from TROPIC01 secure R memory */ + ret = Tropic01_GetKeyECC( + info->pk.ed25519sign.key->k, + TROPIC01_ED25519_PRIV_RMEM_SLOT_DEFAULT, + TROPIC01_ED25519_PRIV_KEY_SIZE); + if (ret != 0) { + WOLFSSL_MSG_EX( + "TROPIC01: CryptoCB: Failed to get ED25519 PRIVkey,ret=%d", + ret); + return ret; + } + ret = Tropic01_GetKeyECC( + info->pk.ed25519sign.key->p, + TROPIC01_ED25519_PUB_RMEM_SLOT_DEFAULT, + TROPIC01_ED25519_PUB_KEY_SIZE); + if (ret != 0) { + WOLFSSL_MSG_EX( + "TROPIC01: CryptoCB: Failed to get ED25519 PUBkey,ret=%d", + ret); + return ret; + } + /* set devId to invalid, so software is used */ + info->pk.ed25519sign.key->devId = INVALID_DEVID; + info->pk.ed25519sign.key->privKeySet = 1; + info->pk.ed25519sign.key->pubKeySet = 1; + ret = wc_ed25519_sign_msg( + info->pk.ed25519sign.in, info->pk.ed25519sign.inLen, + info->pk.ed25519sign.out, info->pk.ed25519sign.outLen, + info->pk.ed25519sign.key); + + /* reset devId */ + info->pk.ed25519sign.key->devId = devId; + } + #endif /* HAVE_ED25519_SIGN */ + #ifdef HAVE_ED25519_VERIFY + if (info->pk.type == WC_PK_TYPE_ED25519_VERIFY) { + WOLFSSL_MSG("TROPIC01: CryptoCB: ED25519 verification request"); + /* retrieve public key from TROPIC01 secure R memory */ + ret = Tropic01_GetKeyECC( + info->pk.ed25519verify.key->p, + TROPIC01_ED25519_PUB_RMEM_SLOT_DEFAULT, + TROPIC01_ED25519_PUB_KEY_SIZE); + if (ret != 0) { + WOLFSSL_MSG_EX( + "TROPIC01: CryptoCB: Failed to get ED25519 key, ret=%d", + ret); + return ret; + } + + /* set devId to invalid, so software is used */ + info->pk.ed25519verify.key->devId = INVALID_DEVID; + info->pk.ed25519verify.key->pubKeySet = 1; + ret = wc_ed25519_verify_msg( + info->pk.ed25519verify.sig, info->pk.ed25519verify.sigLen, + info->pk.ed25519verify.msg, info->pk.ed25519verify.msgLen, + info->pk.ed25519verify.res, info->pk.ed25519verify.key); + + /* reset devId */ + info->pk.ed25519verify.key->devId = devId; + } + #endif /* HAVE_ED25519_VERIFY */ +#endif /* HAVE_ED25519 */ + break; + case WC_ALGO_TYPE_CIPHER: + WOLFSSL_MSG("TROPIC01: CryptoCB: AES request "); + +#if !defined(NO_AES) + #ifdef HAVE_AESGCM + if (info->cipher.type == WC_CIPHER_AES_GCM) { + ret = Tropic01_GetKeyAES( + lt_key, + TROPIC01_AES_KEY_RMEM_SLOT, + TROPIC01_AES_MAX_KEY_SIZE); + if (ret != 0) { + WOLFSSL_MSG_EX( + "TROPIC01: CryptoCB: Failed to get AES key,ret=%d", + ret); + return ret; + } + ret = Tropic01_GetKeyAES( + lt_iv, + TROPIC01_AES_IV_RMEM_SLOT, + TROPIC01_AES_MAX_KEY_SIZE); + if (ret != 0) { + WOLFSSL_MSG_EX( + "TROPIC01: CryptoCB: Failed to get AES IV, ret=%d", + ret); + return ret; + } + if (info->cipher.enc) { + ret = wc_AesSetKey(info->cipher.aesgcm_enc.aes, lt_key, + WC_AES_BLOCK_SIZE, lt_iv, AES_ENCRYPTION); + if (ret != 0) { + WOLFSSL_MSG_EX( + "TROPIC01: CryptoCB: Failed to set AES key, ret=%d", + ret); + return ret; + } + /* set devId to invalid, so software is used */ + info->cipher.aesgcm_enc.aes->devId = INVALID_DEVID; + ret = wc_AesGcmEncrypt( + info->cipher.aesgcm_enc.aes, + info->cipher.aesgcm_enc.out, + info->cipher.aesgcm_enc.in, + info->cipher.aesgcm_enc.sz, + info->cipher.aesgcm_enc.iv, + info->cipher.aesgcm_enc.ivSz, + info->cipher.aesgcm_enc.authTag, + info->cipher.aesgcm_enc.authTagSz, + info->cipher.aesgcm_enc.authIn, + info->cipher.aesgcm_enc.authInSz); + + /* reset devId */ + info->cipher.aesgcm_enc.aes->devId = devId; + } + else { + + ret = wc_AesSetKey(info->cipher.aesgcm_dec.aes, lt_key, + WC_AES_BLOCK_SIZE, lt_iv, AES_DECRYPTION); + if (ret != 0) { + WOLFSSL_MSG_EX( + "TROPIC01: CryptoCB: Failed to set AES key, ret=%d", + ret); + return ret; + } + /* set devId to invalid, so software is used */ + info->cipher.aesgcm_dec.aes->devId = INVALID_DEVID; + ret = wc_AesGcmDecrypt( + info->cipher.aesgcm_dec.aes, + info->cipher.aesgcm_dec.out, + info->cipher.aesgcm_dec.in, + info->cipher.aesgcm_dec.sz, + info->cipher.aesgcm_dec.iv, + info->cipher.aesgcm_dec.ivSz, + info->cipher.aesgcm_dec.authTag, + info->cipher.aesgcm_dec.authTagSz, + info->cipher.aesgcm_dec.authIn, + info->cipher.aesgcm_dec.authInSz); + + /* reset devId */ + info->cipher.aesgcm_dec.aes->devId = devId; + } + } +#endif /* HAVE_AESGCM */ + #ifdef HAVE_AES_CBC + if (info->cipher.type == WC_CIPHER_AES_CBC) { + ret = Tropic01_GetKeyAES( + lt_key, + TROPIC01_AES_KEY_RMEM_SLOT, + TROPIC01_AES_MAX_KEY_SIZE); + if (ret != 0) { + WOLFSSL_MSG_EX( + "TROPIC01: CryptoCB: Failed to get AES key,ret=%d", ret); + return ret; + } + ret = Tropic01_GetKeyAES( + lt_iv, + TROPIC01_AES_IV_RMEM_SLOT, + TROPIC01_AES_MAX_KEY_SIZE); + if (ret != 0) { + WOLFSSL_MSG_EX( + "TROPIC01: CryptoCB: Failed to get AES IV, ret=%d", ret); + return ret; + } + if (info->cipher.enc) { + ret = wc_AesSetKey(info->cipher.aescbc.aes, lt_key, + WC_AES_BLOCK_SIZE, lt_iv, AES_ENCRYPTION); + if (ret != 0) { + WOLFSSL_MSG_EX( + "TROPIC01: CryptoCB: Failed to set AES key, ret=%d", + ret); + return ret; + } + /* set devId to invalid, so software is used */ + info->cipher.aescbc.aes->devId = INVALID_DEVID; + ret = wc_AesCbcEncrypt( + info->cipher.aescbc.aes, + info->cipher.aescbc.out, + info->cipher.aescbc.in, + info->cipher.aescbc.sz); + + /* reset devId */ + info->cipher.aescbc.aes->devId = devId; + } + else { + + ret = wc_AesSetKey(info->cipher.aescbc.aes, lt_key, + WC_AES_BLOCK_SIZE, lt_iv, AES_DECRYPTION); + if (ret != 0) { + WOLFSSL_MSG_EX( + "TROPIC01: CryptoCB: Failed to set AES key, ret=%d", + ret); + return ret; + } + /* set devId to invalid, so software is used */ + info->cipher.aescbc.aes->devId = INVALID_DEVID; + ret = wc_AesCbcDecrypt( + info->cipher.aescbc.aes, + info->cipher.aescbc.out, + info->cipher.aescbc.in, + info->cipher.aescbc.sz); + + /* reset devId */ + info->cipher.aescbc.aes->devId = devId; + } + } + #endif /* HAVE_AES_CBC */ +#endif /* !NO_AES */ + break; + + default: + + break; + } + + return ret; +} +/* Set TROPIC01 pairing keys */ +int Tropic01_SetPairingKeys(int kIndex, const byte* kPub, const byte* kPriv) +{ + int i; + + if (kPub == NULL || kPriv == NULL || kIndex < 0 || kIndex > 3) { + WOLFSSL_MSG_EX("TROPIC01: SetPairingKeys: Invalid arguments"); + return BAD_FUNC_ARG; + } + + WOLFSSL_MSG_EX( + "TROPIC01: SetPairingKeys: Setting pairing key in slot %d", + kIndex); + + for (i = 0; i < TROPIC01_PAIRING_KEY_SIZE; i++) { + + sh0priv[i] = kPriv[i]; + sh0pub[i] = kPub[i]; + } + + WOLFSSL_MSG("TROPIC01: SetPairingKeys: Pairing key set successfully"); + WOLFSSL_MSG_EX( + "TROPIC01: sh0priv: %02X %02X %02X %02X ...", + kPriv[0], kPriv[1], kPriv[2], kPriv[3]); + WOLFSSL_MSG_EX( + "TROPIC01: sh0pub: %02X %02X %02X %02X ...", + kPub[0], kPub[1], kPub[2], kPub[3]); + return 0; +} + +int Tropic01_Init(void) +{ + lt_ret_t ret; + + g_ctx.initialized = 0; + ret = lt_init(&g_h); + if (ret != LT_OK) { + WOLFSSL_MSG_EX("TROPIC01: lt_init failed with a code %d", ret); + return WC_HW_E; + } + ret = verify_chip_and_start_secure_session(&g_h, sh0priv, sh0pub, pk_index); + if (ret != LT_OK) { + WOLFSSL_MSG_EX("TROPIC01: secure session failed with a code %d", ret); + lt_deinit(&g_h); + return WC_HW_E; + } + g_ctx.initialized = 1; + WOLFSSL_MSG("TROPIC01: Crypto device initialized successfully"); + + return 0; +} + +int Tropic01_Deinit(void) +{ + lt_ret_t ret; + + if (g_ctx.initialized) { + ret = lt_deinit(&g_h); + if (ret != LT_OK) { + WOLFSSL_MSG_EX("TROPIC01: lt_deinit failed with a code %d", ret); + return WC_HW_E; + } + g_ctx.initialized = 0; + WOLFSSL_MSG("TROPIC01: Crypto device deinitialized successfully"); + } + + return 0; +} + +#endif /* WOLFSSL_TROPIC01 */ diff --git a/wolfcrypt/src/wc_port.c b/wolfcrypt/src/wc_port.c index 6abc118b5..1d4ba2158 100644 --- a/wolfcrypt/src/wc_port.c +++ b/wolfcrypt/src/wc_port.c @@ -69,6 +69,10 @@ #include #endif +#if defined(WOLFSSL_TROPIC01) + #include +#endif + #if (defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)) \ && !defined(WOLFCRYPT_ONLY) #include @@ -294,7 +298,13 @@ int wolfCrypt_Init(void) #if defined(WOLFSSL_STSAFEA100) stsafe_interface_init(); #endif - + #if defined(WOLFSSL_TROPIC01) + ret = Tropic01_Init(); + if (ret != 0) { + WOLFSSL_MSG("Tropic01 init failed"); + return ret; + } + #endif #if defined(WOLFSSL_PSOC6_CRYPTO) ret = psoc6_crypto_port_init(); if (ret != 0) { @@ -514,6 +524,9 @@ int wolfCrypt_Cleanup(void) #ifdef WOLFSSL_SILABS_SE_ACCEL ret = sl_se_deinit(); #endif + #if defined(WOLFSSL_TROPIC01) + Tropic01_Deinit(); + #endif #if defined(WOLFSSL_RENESAS_TSIP) tsip_Close(); #endif diff --git a/wolfssl/wolfcrypt/include.am b/wolfssl/wolfcrypt/include.am index f6fadde7f..bf798d366 100644 --- a/wolfssl/wolfcrypt/include.am +++ b/wolfssl/wolfcrypt/include.am @@ -109,6 +109,7 @@ noinst_HEADERS+= \ wolfssl/wolfcrypt/port/silabs/silabs_random.h \ wolfssl/wolfcrypt/port/st/stm32.h \ wolfssl/wolfcrypt/port/st/stsafe.h \ + wolfssl/wolfcrypt/port/tropicsquare/tropic01.h \ wolfssl/wolfcrypt/port/Espressif/esp-sdk-lib.h \ wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h \ wolfssl/wolfcrypt/port/Espressif/esp_crt_bundle.h \ @@ -229,6 +230,10 @@ if BUILD_SE050 nobase_include_HEADERS+= wolfssl/wolfcrypt/port/nxp/se050_port.h endif +if BUILD_TROPIC01 +nobase_include_HEADERS+= wolfssl/wolfcrypt/port/tropicsquare/tropic01.h +endif + if BUILD_MAXQ10XX nobase_include_HEADERS+= wolfssl/wolfcrypt/port/maxim/maxq10xx.h endif diff --git a/wolfssl/wolfcrypt/port/tropicsquare/tropic01.h b/wolfssl/wolfcrypt/port/tropicsquare/tropic01.h new file mode 100644 index 000000000..8bdb740c6 --- /dev/null +++ b/wolfssl/wolfcrypt/port/tropicsquare/tropic01.h @@ -0,0 +1,106 @@ +/* tropic01.h + * + * Copyright (C) 2006-2025 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL 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. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#ifndef _WOLFPORT_TROPIC01_H_ +#define _WOLFPORT_TROPIC01_H_ + +#include +#include +#include +#include + +#ifdef WOLF_CRYPTO_CB +#include +#endif + + +#ifdef WOLFSSL_TROPIC01 + +/* The TROPIC01 interface layer */ +/* Please contact wolfSSL for the TROPIC01 port files */ +#define LT_USE_TREZOR_CRYPTO 1 +#define LT_HELPERS + +#include +#include + + +#ifdef WOLF_CRYPTO_CB + +/* Device ID that's unique and valid (not INVALID_DEVID -2) */ +#define WOLF_TROPIC01_DEVID 0x75757 /* TROPIC01 ID*/ + + +#define TROPIC01_AES_MAX_KEY_SIZE 32 +#define TROPIC01_PAIRING_KEY_SIZE 32 +#define TROPIC01_ED25519_PRIV_KEY_SIZE 32 +#define TROPIC01_ED25519_PUB_KEY_SIZE 32 + +/* R-Memory slots allocation */ +#ifndef TROPIC01_AES_KEY_RMEM_SLOT +#define TROPIC01_AES_KEY_RMEM_SLOT 0 +#endif /* TROPIC01_AES_KEY_RMEM_SLOT */ + +#ifndef TROPIC01_AES_IV_RMEM_SLOT +#define TROPIC01_AES_IV_RMEM_SLOT 1 +#endif /* TROPIC01_AES_IV_RMEM_SLOT */ + +#ifndef TROPIC01_ED25519_PUB_RMEM_SLOT_DEFAULT +#define TROPIC01_ED25519_PUB_RMEM_SLOT_DEFAULT 2 +#endif /* TROPIC01_ED25519_PUB_RMEM_SLOT_DEFAULT */ + +#ifndef TROPIC01_ED25519_PRIV_RMEM_SLOT_DEFAULT +#define TROPIC01_ED25519_PRIV_RMEM_SLOT_DEFAULT 3 +#endif /* TROPIC01_ED25519_PRIV_RMEM_SLOT_DEFAULT */ + +#ifndef TROPIC01_ED25519_ECC_SLOT_DEFAULT +#define TROPIC01_ED25519_ECC_SLOT_DEFAULT 1 +#endif /* TROPIC01_ED25519_ECC_SLOT_DEFAULT */ + +#ifndef PAIRING_KEY_SLOT_INDEX_0 +#define PAIRING_KEY_SLOT_INDEX_0 0 +#endif /* PAIRING_KEY_SLOT_INDEX_0 */ + +typedef struct { + int keySlot; /* Slot ID in TROPIC01 secure memory */ + word32 keySize; /* Size of the key in bytes (16, 24, or 32) */ + byte keyType; /* Type of key (e.g., AES_CBC, AES_GCM) */ + byte isValid; /* Flag indicating if this reference is valid */ +} Tropic01KeyRef; + +/* Context for TROPIC01 secure element */ +typedef struct { + int initialized; +} Tropic01CryptoDevCtx; + + +WOLFSSL_API int Tropic01_Init(void); +WOLFSSL_API int Tropic01_Deinit(void); +WOLFSSL_API int Tropic01_SetPairingKeys( + int kIndex, const byte* kPub, const byte* kPriv); +WOLFSSL_API int Tropic01_CryptoCb(int devId, wc_CryptoInfo* info, void* ctx); + + +#endif /* WOLF_CRYPTO_CB */ + +#endif /* WOLFSSL_TROPIC01*/ + +#endif /* _WOLFPORT_TROPIC01_H_ */