Skip to content

feat: libtropic compatible with RP2040 and RP2350 MCUs (rpi-pico).#464

Open
Caza20 wants to merge 9 commits intotropicsquare:developfrom
Caza20:feat/rpi-pico
Open

feat: libtropic compatible with RP2040 and RP2350 MCUs (rpi-pico).#464
Caza20 wants to merge 9 commits intotropicsquare:developfrom
Caza20:feat/rpi-pico

Conversation

@Caza20
Copy link

@Caza20 Caza20 commented Feb 9, 2026

Description

This Pull Request adds support for RP2040 and RP2350 MCUs to the libtropic library.

The implementation introduces the required HAL functionality for Raspberry Pi Pico–class devices by adding new platform-specific code under hal/rpi-pico. These changes enable libtropic to run correctly on RP2040 and RP2350 microcontrollers.

These MCUs works with the trezor_crypto library.

This work was motivated by a real-world use case: at Wuard, we developed a basic HSM using an RP2350 MCU together with the Tropic01 secure element. More information here
The goal is to make this setup accessible to makers and developers, with easy programming and integration via PlatformIO.

These changes allow libtropic to be used on low-cost, widely available MCUs while preserving compatibility with the existing architecture.

Reference related issues or tickets: Issue #458 and PR #459


Type of Change

Select the type(s) that best describe your change:

  • 🐛 Bug fix
  • [ x ] ✨ New feature
  • 🧹 Code cleanup or refactoring
  • 📝 Documentation update
  • [ x ] 🔧 Build system or toolchain update
  • 🔒 Security improvement
  • Other (please describe):

Checklist

Before submitting, please confirm that you have completed the following:

  • [ x ] I opened the Pull Request to the develop branch
  • [ x ] I followed the project's code guidelines
  • I formatted the code using clang-format with the recommended configuration
  • I updated the changelog, or this change does not require it (e.g., internal or non-functional update)
  • [ x ] The project builds without errors or warnings
  • [ x ] I have verified the functionality against the hardware/model as applicable
  • [ x ] I have ensured that public APIs remain backward compatible (if applicable)
  • [ x ] This PR is ready for review by maintainers (no WIP commits left) and marked as Ready for Review

Optional Checks

You can enable optional CI jobs by checking following boxes. For example, coverage job is useful when modifying or implementing new tests.

  • Measure Test Coverage

Notes for Reviewers

  • Platform-specific code is isolated under hal/rpi-pico.

  • Changes were tested on real hardware using RP2040 and RP2350 MCUs.

  • The primary target use case is integration with PlatformIO and maker-oriented projects.

@Caza20
Copy link
Author

Caza20 commented Feb 9, 2026

However, something needs to be modified in the CMakeLists.txt file of cal/trezor_crypto. Because as it is, I get this error when compiling:

Linking .pio/build/pico/firmware.elf
/home/caza/.platformio/packages/toolchain-rp2040-earlephilhower/bin/../lib/gcc/arm-none-eabi/14.3.0/../../../../arm-none-eabi/bin/ld: .pio/build/pico/lib_tropic_cal/lt_trezor_crypto_aesgcm.c.o: in function `lt_aesgcm_encrypt_init':
lt_trezor_crypto_aesgcm.c:(.text.lt_aesgcm_encrypt_init+0xa): undefined reference to `gcm_init_and_key'
/home/caza/.platformio/packages/toolchain-rp2040-earlephilhower/bin/../lib/gcc/arm-none-eabi/14.3.0/../../../../arm-none-eabi/bin/ld: .pio/build/pico/lib_tropic_cal/lt_trezor_crypto_aesgcm.c.o: in function `lt_aesgcm_decrypt_init':
lt_trezor_crypto_aesgcm.c:(.text.lt_aesgcm_decrypt_init+0xe): undefined reference to `gcm_init_and_key'
/home/caza/.platformio/packages/toolchain-rp2040-earlephilhower/bin/../lib/gcc/arm-none-eabi/14.3.0/../../../../arm-none-eabi/bin/ld: .pio/build/pico/lib_tropic_cal/lt_trezor_crypto_aesgcm.c.o: in function `lt_aesgcm_encrypt':
lt_trezor_crypto_aesgcm.c:(.text.lt_aesgcm_encrypt+0x3c): undefined reference to `gcm_encrypt_message'
/home/caza/.platformio/packages/toolchain-rp2040-earlephilhower/bin/../lib/gcc/arm-none-eabi/14.3.0/../../../../arm-none-eabi/bin/ld: .pio/build/pico/lib_tropic_cal/lt_trezor_crypto_aesgcm.c.o: in function `lt_aesgcm_decrypt':
lt_trezor_crypto_aesgcm.c:(.text.lt_aesgcm_decrypt+0x42): undefined reference to `gcm_decrypt_message'
/home/caza/.platformio/packages/toolchain-rp2040-earlephilhower/bin/../lib/gcc/arm-none-eabi/14.3.0/../../../../arm-none-eabi/bin/ld: .pio/build/pico/lib_tropic_cal/lt_trezor_crypto_aesgcm.c.o: in function `lt_aesgcm_encrypt_deinit':
lt_trezor_crypto_aesgcm.c:(.text.lt_aesgcm_encrypt_deinit+0x2): undefined reference to `gcm_end'
/home/caza/.platformio/packages/toolchain-rp2040-earlephilhower/bin/../lib/gcc/arm-none-eabi/14.3.0/../../../../arm-none-eabi/bin/ld: .pio/build/pico/lib_tropic_cal/lt_trezor_crypto_aesgcm.c.o: in function `lt_aesgcm_decrypt_deinit':
lt_trezor_crypto_aesgcm.c:(.text.lt_aesgcm_decrypt_deinit+0x6): undefined reference to `gcm_end'
/home/caza/.platformio/packages/toolchain-rp2040-earlephilhower/bin/../lib/gcc/arm-none-eabi/14.3.0/../../../../arm-none-eabi/bin/ld: .pio/build/pico/lib_tropic_cal/lt_trezor_crypto_hmac_sha256.c.o: in function `lt_hmac_sha256':
lt_trezor_crypto_hmac_sha256.c:(.text.lt_hmac_sha256+0x6): undefined reference to `hmac_sha256'
/home/caza/.platformio/packages/toolchain-rp2040-earlephilhower/bin/../lib/gcc/arm-none-eabi/14.3.0/../../../../arm-none-eabi/bin/ld: .pio/build/pico/lib_tropic_cal/lt_trezor_crypto_sha256.c.o: in function `lt_sha256_start':
lt_trezor_crypto_sha256.c:(.text.lt_sha256_start+0xe): undefined reference to `hasher_InitParam'
/home/caza/.platformio/packages/toolchain-rp2040-earlephilhower/bin/../lib/gcc/arm-none-eabi/14.3.0/../../../../arm-none-eabi/bin/ld: .pio/build/pico/lib_tropic_cal/lt_trezor_crypto_sha256.c.o: in function `lt_sha256_update':
lt_trezor_crypto_sha256.c:(.text.lt_sha256_update+0x8): undefined reference to `hasher_Update'
/home/caza/.platformio/packages/toolchain-rp2040-earlephilhower/bin/../lib/gcc/arm-none-eabi/14.3.0/../../../../arm-none-eabi/bin/ld: .pio/build/pico/lib_tropic_cal/lt_trezor_crypto_sha256.c.o: in function `lt_sha256_finish':
lt_trezor_crypto_sha256.c:(.text.lt_sha256_finish+0x8): undefined reference to `hasher_Final'
/home/caza/.platformio/packages/toolchain-rp2040-earlephilhower/bin/../lib/gcc/arm-none-eabi/14.3.0/../../../../arm-none-eabi/bin/ld: .pio/build/pico/lib_tropic_cal/lt_trezor_crypto_x25519.c.o: in function `lt_X25519':
lt_trezor_crypto_x25519.c:(.text.lt_X25519+0xa): undefined reference to `curve25519_scalarmult'
/home/caza/.platformio/packages/toolchain-rp2040-earlephilhower/bin/../lib/gcc/arm-none-eabi/14.3.0/../../../../arm-none-eabi/bin/ld: .pio/build/pico/lib_tropic_cal/lt_trezor_crypto_x25519.c.o: in function `lt_X25519_scalarmult':
lt_trezor_crypto_x25519.c:(.text.lt_X25519_scalarmult+0x8): undefined reference to `curve25519_scalarmult_basepoint'
collect2: error: ld returned 1 exit status
*** [.pio/build/pico/firmware.elf] Error 1
================================================================== [FAILED] Took 51.20 seconds ============================

But if you modify the CMakeLists.txt file of the original libtropic by adding the code below, it works!

##################################################
# =========================
# Trezor Crypto (embedded subset)
# =========================

set(TREZOR_CRYPTO_SRC
    # --- AES / GCM ---
    vendor/trezor_crypto/aes/aesgcm.c
    vendor/trezor_crypto/aes/aesccm.c
    vendor/trezor_crypto/aes/aescrypt.c
    vendor/trezor_crypto/aes/aes_modes.c
    vendor/trezor_crypto/aes/aestab.c
    vendor/trezor_crypto/aes/aeskey.c
    vendor/trezor_crypto/aes/gf128mul.c

    vendor/trezor_crypto/hasher.c
    vendor/trezor_crypto/blake256.c
    vendor/trezor_crypto/blake2b.c
    vendor/trezor_crypto/groestl.c
    vendor/trezor_crypto/sha2.c
    vendor/trezor_crypto/sha3.c
    vendor/trezor_crypto/ripemd160.c
    vendor/trezor_crypto/memzero.c
    vendor/trezor_crypto/hmac.c

    # --- Curve25519 ---
    vendor/trezor_crypto/ed25519-donna/curve25519-donna-32bit.c
    vendor/trezor_crypto/ed25519-donna/curve25519-donna-helpers.c
    vendor/trezor_crypto/ed25519-donna/ed25519-donna-impl-base.c
    vendor/trezor_crypto/ed25519-donna/ed25519.c

    # --- Ed25519 ---
    vendor/trezor_crypto/ed25519-donna/ed25519-keccak.c
    vendor/trezor_crypto/ed25519-donna/ed25519-sha3.c
    vendor/trezor_crypto/ed25519-donna/modm-donna-32bit.c
    vendor/trezor_crypto/ed25519-donna/curve25519-donna-scalarmult-base.c

    vendor/trezor_crypto/ed25519-donna/ed25519-donna-32bit-tables.c
    vendor/trezor_crypto/ed25519-donna/ed25519-donna-basepoint-table.c

    vendor/trezor_crypto/rand.c
    vendor/trezor_crypto/ecdsa.c
    vendor/trezor_crypto/nist256p1.c
    vendor/trezor_crypto/bignum.c
    vendor/trezor_crypto/rfc6979.c
    vendor/trezor_crypto/address.c
    vendor/trezor_crypto/base58.c
    vendor/trezor_crypto/secp256k1.c
    vendor/trezor_crypto/hmac_drbg.c
)

target_sources(tropic PRIVATE
    ${TREZOR_CRYPTO_SRC}
)

target_include_directories(tropic PRIVATE
    vendor/trezor_crypto
    vendor/trezor_crypto/aes
    vendor/trezor_crypto/ed25519-donna
)

target_compile_definitions(tropic PRIVATE
    LT_USE_TREZOR_CRYPTO
    AES_VAR
    USE_INSECURE_PRNG
)

Am I doing something wrong?

Copy link
Contributor

@medexs medexs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, thanks for the contribution!

Please, take a look at the comments below.

Regarding the Crypto Abstraction Layer (CAL), the approach is different in Libtropic (all details are in the documentation) and in our libtropic-arduino repository, which seems you are using. Unfortunately, we didn't explain how to handle different CALs in libtropic-arduino, for which we apologize. We assumed that libtropic-arduino will be used for hobby projects only and that MbedTLS CAL, which is used by default there, along with the Arduino HAL, will be sufficient enough. If you can provide us with more information about your project and perhaps some links to the source code, it will be easier for us to help you navigate through these issues. However, please keep in mind that our main focus is on the Libtropic repository, so the support for the libtropic-arduino will have a lower priority. That leads us to a question - have you thought about using Libtropic in a native CMake project without PlatformIO? We are asking because Libtropic in a native CMake project simplifies a lot of things the libtropic-arduino does in not very clear ways (thus your confusion with the Trezor Crypto CAL, which is understandable and sort of a pitfall of the libtropic-arduino project).

If you find some issues or have some more contributions, feel free to send us a PR. If you would like to continue with this discussion, reach us via our support portal.

}
#endif

extern "C" int lt_port_log(const char *format, ...)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the only function that depends on Arduino.h, thus making the HAL harder to integrate into native projects that use only the Pico SDK or standard libraries. Would it be possible to rewrite this function so it does not depend on Arduino.h?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have modified the function to be compatible with both the Arduino SDK and the Pico SDK.

We designed it to use the Raspberry Pi Pico on PlatformIO with the Arduino framework.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the updated version with #ifdef ARDUINO. However, we would like this HAL to be written purely in C (with .c suffix instead of the current .cpp), with no mentions of Arduino API, so people can use it in native project utilizing only the Pico SDK. That means removing the code guarded by #ifdef ARDUINO, include of Arduino.h and renaming the file so it has the .c suffix.

We understand that for your use case, you might need the HAL to use both Arduino API and Pico SDK. However, this is a very specific use case which would not fit in with our other HALs. But a pure Pico SDK HAL (which this HAL can be) would be really appreciated!

@Caza20
Copy link
Author

Caza20 commented Feb 17, 2026

Thank you for showing me the modifications needed. I have corrected them and updated the repository.

Regarding CAL integration, the Rpi Pico does not support MbedTLS (or at least I have not been able to get it working). This is different with the ESP32, which already has it embedded. That is why it is necessary to be able to use the Trezor_crypto CAL for it to work.

At Wuard, we have developed an HSM module specifically for makers that uses a Tropic01 chip and an Rpi Pico. Here is the link to the firmware for you to see. That firmware works without problems (but it uses the trezor_crypto CAL by modifying the main CMakeLists.txt file; unfortunately, I couldn't find another way).

On libtropic-arduino, I have added a pull request so that the Tropic01 can be used with the Rpi Pico using PlatformIO and the Arduino framework (very popular in the maker community).

I look forward to your comments, and if any further modifications are needed, please don't hesitate to let me know and I will gladly make them.

@Caza20 Caza20 requested a review from medexs February 18, 2026 18:48
Copy link
Contributor

@medexs medexs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, thanks for the suggested fixes. There is still one more thing with the lt_port_log function - see the comment below.

Regarding the CAL integration and the other PR into our libtropic-arduino repository - I will provide more information about that in this other PR.

Thank you for the cooperation and interest, we really appreciate it!

}
#endif

extern "C" int lt_port_log(const char *format, ...)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the updated version with #ifdef ARDUINO. However, we would like this HAL to be written purely in C (with .c suffix instead of the current .cpp), with no mentions of Arduino API, so people can use it in native project utilizing only the Pico SDK. That means removing the code guarded by #ifdef ARDUINO, include of Arduino.h and renaming the file so it has the .c suffix.

We understand that for your use case, you might need the HAL to use both Arduino API and Pico SDK. However, this is a very specific use case which would not fit in with our other HALs. But a pure Pico SDK HAL (which this HAL can be) would be really appreciated!

@Caza20
Copy link
Author

Caza20 commented Feb 24, 2026

@medexs , I have uploaded the changes you requested. I hope everything is okay!
I look forward to your feedback, and if there is anything else that needs changing, I would be happy to do it!

Thanks. Best regards!

@Caza20 Caza20 requested a review from medexs February 24, 2026 18:28
@medexs
Copy link
Contributor

medexs commented Feb 25, 2026

Hi @Caza20 , thank you very much!

However, there is one last thing - I ran our actions on this PR and clang-format action failed for both of the C files. Could you please fix the formatting? We provide instructions on how to do that in our Contributing guideline.

I also have one question - both files say the HAL is compatible with RP2040, but do you think it will also work with RP2350?

Again, thanks for the great cooperation!

@Caza20
Copy link
Author

Caza20 commented Feb 25, 2026

@medexs , I made the formatting changes using clang-format. I apologize for that; I should have done it before uploading.

I think everything is okay now. Let me know if anything needs to be modified.

The code works for both the RP2040 (Rpi Pico) and the RP2350 (Rpi Pico 2).

I look forward to your feedback. Thanks. Regards.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants