Minimal Cryptnox ESP32 example: sign a 32-byte hash on the secp256k1 curve.
Minimal Cryptnox ESP32 example: sign a 32-byte hash on the secp256k1 curve.Wiring & prerequisites:
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "driver/spi_master.h"
#include "esp_log.h"
#include "esp_wifi.h"
#include "esp_netif.h"
#include "esp_event.h"
#include "nvs_flash.h"
#include "CryptnoxWallet.h"
#include "config.h"
#define SPI_MOSI 11
#define SPI_MISO 13
#define SPI_SCLK 12
#define SPI_MAX_TRANSFER_SZ 4096
#define SPI_PIN_UNUSED (-1)
#define NFC_CS 10
static const char *
const TAG =
"sign";
#define WIFI_CONNECTED_BIT BIT0
#define WIFI_FAIL_BIT BIT1
int32_t event_id, void *event_data)
{
(void)arg;
(void)event_data;
if ((event_base == WIFI_EVENT) && (event_id == WIFI_EVENT_STA_START)) {
esp_wifi_connect();
} else if ((event_base == WIFI_EVENT) &&
(event_id == WIFI_EVENT_STA_DISCONNECTED)) {
esp_wifi_connect();
} else {
}
} else if ((event_base == IP_EVENT) && (event_id == IP_EVENT_STA_GOT_IP)) {
} else {
}
}
{
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
(void)esp_netif_create_default_wifi_sta();
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
esp_event_handler_instance_t h_any;
esp_event_handler_instance_t h_ip;
ESP_ERROR_CHECK(esp_event_handler_instance_register(
ESP_ERROR_CHECK(esp_event_handler_instance_register(
wifi_config_t wifi_cfg;
(void)memset(&wifi_cfg, 0, sizeof(wifi_cfg));
(void)strncpy((
char *)wifi_cfg.sta.ssid,
WIFI_SSID,
sizeof(wifi_cfg.sta.ssid) - 1U);
sizeof(wifi_cfg.sta.password) - 1U);
wifi_cfg.sta.threshold.authmode = WIFI_AUTH_WPA2_PSK;
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_cfg));
ESP_ERROR_CHECK(esp_wifi_start());
pdFALSE, pdFALSE,
ESP_LOGI(
TAG,
"WiFi connected");
} else {
ESP_LOGW(
TAG,
"WiFi connect failed — TRNG entropy may be reduced");
}
(void)esp_event_handler_instance_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, h_ip);
(void)esp_event_handler_instance_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, h_any);
}
{
static const uint8_t TEST_HASH[CW_HASH_SIZE] = {
0x01U, 0x01U, 0x01U, 0x01U, 0x01U, 0x01U, 0x01U, 0x01U,
0x01U, 0x01U, 0x01U, 0x01U, 0x01U, 0x01U, 0x01U, 0x01U,
0x01U, 0x01U, 0x01U, 0x01U, 0x01U, 0x01U, 0x01U, 0x01U,
0x01U, 0x01U, 0x01U, 0x01U, 0x01U, 0x01U, 0x01U, 0x01U,
};
static const uint8_t DEMO_PIN[CW_MAX_PIN_LENGTH] = {
'0', '0', '0', '0', '0', '0', '0', '0', '0'
};
bool keep_running = true;
while (keep_running) {
CW_SecureSession session{};
bool connected = wallet.connect(session);
if (!connected) {
ESP_LOGW(
TAG,
"Card not detected");
}
if (connected) {
CW_SignRequest req(session,
CW_SIGN_CURR_K1,
CW_SIGN_SIG_ECDSA_LOW_S,
CW_SIGN_WITH_PIN);
req.hash = TEST_HASH;
req.hashLength = static_cast<uint8_t>(CW_HASH_SIZE);
(void)CW_Utils::safe_memcpy(req.pin, sizeof(req.pin),
DEMO_PIN, CW_MAX_PIN_LENGTH);
CW_SignResult result = wallet.sign(req);
if (result.errorCode == CW_OK) {
ESP_LOGI(
TAG,
"Sign OK - r:");
ESP_LOG_BUFFER_HEX_LEVEL(
TAG, &result.signature[CW_SIG_R_OFFSET],
CW_HASH_SIZE, ESP_LOG_INFO);
ESP_LOG_BUFFER_HEX_LEVEL(
TAG, &result.signature[CW_SIG_S_OFFSET],
CW_HASH_SIZE, ESP_LOG_INFO);
} else if (result.errorCode == CW_SIGN_PIN_INCORRECT) {
ESP_LOGE(
TAG,
"Wrong PIN — halting to protect retry counter");
keep_running = false;
} else {
ESP_LOGE(
TAG,
"Sign failed: 0x%02X",
static_cast<unsigned int>(result.errorCode));
}
}
wallet.disconnect(session);
if (keep_running) {
}
}
while (true) {
}
}
{
esp_err_t nvs_ret = nvs_flash_init();
if ((nvs_ret == ESP_ERR_NVS_NO_FREE_PAGES) ||
(nvs_ret == ESP_ERR_NVS_NEW_VERSION_FOUND)) {
ESP_ERROR_CHECK(nvs_flash_erase());
nvs_ret = nvs_flash_init();
}
ESP_ERROR_CHECK(nvs_ret);
spi_bus_config_t buscfg = {};
ESP_ERROR_CHECK(spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_CH_AUTO));
if (nfc_ret == ESP_OK) {
(void)logger.
begin(115200UL);
CryptnoxWallet wallet(nfcTransport, logger, cryptoProvider, platform);
if (wallet.begin()) {
} else {
ESP_LOGE(
TAG,
"Wallet init failed");
}
} else {
ESP_LOGE(
TAG,
"PN532 init failed");
}
}
void app_main(void)
ESP-IDF application entry point.
static EventGroupHandle_t s_wifi_event_group
#define SPI_MAX_TRANSFER_SZ
static const uint32_t LOOP_DELAY_MS
static void wifi_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data)
FreeRTOS event handler driving the Wi-Fi station state machine.
#define WIFI_CONNECTED_BIT
static void wifi_start(void)
Initialise Wi-Fi station mode and block until connected or timeout.
CW_Logger implementation that writes to ESP32 UART0 via printf.
CW_NfcTransport adapter wrapping the ESP-IDF PN532 NFC driver.
static void run_sign_loop(CryptnoxWallet &wallet)
Main application loop: connect, sign a test hash, and disconnect.
CW_CryptoProvider backed by mbedTLS and the ESP32 hardware TRNG.
CW_Logger backed by ESP32 UART0.
bool begin(unsigned long baudRate=115200UL) override
Initialise UART0 at the given baud rate.
CW_NfcTransport implementation backed by the ESP-IDF PN532 driver.
CW_CryptoProvider implementation for ESP32 using mbedTLS and the hardware TRNG.
static const char *const TAG
esp_err_t pn532_init(pn532_t *dev, const pn532_config_t *config)
Initialise the PN532 and bring it to a ready state.
Low-level PN532 NFC controller driver for ESP-IDF (SPI and I²C).
Compile-time configuration passed to pn532_init.
spi_host_device_t spi_host
Opaque-like runtime state for a single PN532 instance.