I created this repository as a basic example of how to get WolfSSL working on the Raspberry Pi Pico. This project can be built either from the CLI, as described in step 3, or with the VSCode RPi Pico extension. The resulting testwolfcrypt binary will test wolfcrypt's functionality (shocking) and output the return value over USB UART.
You need to have the Raspberry Pi Pico SDK GitHub repository and the WolfSSL Github Repository somewhere on your system. You also need the ARM compiler (gcc-arm-none-eabi) and CMake installed. I mean, it would be pretty impressive if you haven't had those installed at this point.
In the original project, you'd do this by typing something like export WOLFSSL_ROOT=/path/to/wolfssl/source in your terminal. I found that it's cleaner to set these in CMakeLists.txt instead; just update the two lines at the top of CMakeLists with the appropriate paths:
set(ENV{PICO_SDK_PATH} "/Users/bsquared/pico/pico-sdk")
set(ENV{WOLFSSL_ROOT} "/Users/bsquared/bwsi/pico/wolfssl")
You must go into your WolfSSL library to define your own RNG function. In the root directory, navigate to ./wolfcrypt/src/random.c. Add the following import to the top:
#include <pico/rand.h>
(This will resolve because of the ${PICO_SDK_PATH}/src/rp2_common/pico_rand/include include path in CMakeLists.txt)
Then add the following function around line 3710:
#elif defined(CUSTOM_RAND_GENERATE_BLOCK)
extern int wc_pico_rng_gen_block(byte* output, word32 sz)
{
uint64_t rand64;
while (sz > 0) {
word32 len = sizeof(rand64);
if (sz < len)
len = sz;
/* Get one random 64-bit int from hw RNG */
rand64 = get_rand_64();
XMEMCPY(output, &rand, len);
output += len;
sz -= len;
}
return 0;
}
To generate the buildsystem and build the project, run cmake and make:
$ cd RPi-Pico-Example
$ mkdir build
$ cd build
$ cmake -DPICO_BOARD=pico2_w -DPICO_PLATFORM=rp2350 ..
$ make
Tip
Use make -j4 to spread the compiling process across 4 cores of your CPU, speeding up the build.
Note
You shouldn't need these, but the original project had the following CMake options available:
PICO_BOARD- A full list of boards for this option can be found here, just ignore the ".h" at the end.USE_UART- Output to UART instead of USB, for the Pi Debug Probe.USE_WIFI,WIFI_SSID,WIFI_PASSWORD,TEST_TCP_SERVER_IPare also all options, but I doubt the functionality of WiFi & TCP/IP.
Hold the boot button and plug the Pico into your computer. You can then
drag/drop a .uf2 to the Pico. It will stop becoming a USB mass storage device
and run immediately once the upload is complete.
Alternatively, use picotool load -f <path-to-uf2> to force the Pico into BOOTSEL mode and load the firmware.
Because we have not set USE_UART, once rebooted the USB port will turn into an
"Abstract Control Module" serial port. This means our board is visible as the familiar
/dev/ttyACM0 or /dev/tty.usbmodemXXXX. The baud rate of this port
is 115200.
Either use minicom (minicom -b 115200 -o -D /dev/tty...) or VSCode's built-in serial monitor to communicate with the board.
If all tests pass, the Pico will output "End: 0".
You can use your CMakeLists.txt to tell VSCode's IntelliSense what your include paths are.
For example, in ${WOLFSSL_ROOT}/wolfcrypt/src/random.c, you might notice that VSCode can not resolve the #include <pico/rand.h> line. To remedy this, I added a line to CMakeLists that will export a compile_commands.json file: set(CMAKE_EXPORT_COMPILE_COMMANDS ON).
This file can then be inputted into your .vscode/c_cpp_properties.json file using a custom configuration. By doing this, VSCode IntelliSense will use that compile_commands.json to find files for your include statements.
{
"configurations": [
{
"name": "CMake",
"compileCommands": "${config:cmake.buildDirectory}/compile_commands.json"
}
],
"version": 4
}
Surprisingly, WolfSSL does include a bit of documentation about using the library on the Pico. This can be found in your WolfSSL directory, at wolfcrypt/src/port/pi_pico/README.md.
Let's say you have this bootloader.c script from the attack phase that has the following WolfSSL imports:
// Cryptography Imports
#include "wolfssl/wolfcrypt/settings.h"
#include "wolfssl/wolfcrypt/aes.h"
#include "wolfssl/wolfcrypt/sha.h"
#include "wolfssl/wolfcrypt/rsa.h"
Your CMakeLists should include these modules when your compiling your new bootloader target:
add_executable(bootloader
src/bootloader.c
)
# Include WolfSSL during linking phase
target_link_libraries(bootloader
wolfssl
pico_stdlib
pico_rand
)
# Include WolfSSL in include path
target_include_directories(bootloader PRIVATE ${WOLFSSL_ROOT})
Now, in your bootloader.c, you can import WolfSSL modules like normal!
#include "wolfssl/wolfcrypt/settings.h"
#include "wolfssl/wolfcrypt/aes.h"
...etc
best of luck
- ben b