26#include "freertos/FreeRTOS.h"
27#include "freertos/task.h"
28#include "freertos/event_groups.h"
29#include "driver/spi_master.h"
36#include "CryptnoxWallet.h"
57#define SPI_MAX_TRANSFER_SZ 4096
58#define SPI_PIN_UNUSED (-1)
64#define PN532_I2C_PORT 0
69#define PN532_I2C_HZ 100000U
72static const char *
const TAG =
"basic_usage";
77#define WIFI_CONNECTED_BIT BIT0
78#define WIFI_FAIL_BIT BIT1
96 int32_t event_id,
void *event_data)
100 if ((event_base == WIFI_EVENT) && (event_id == WIFI_EVENT_STA_START)) {
102 }
else if ((event_base == WIFI_EVENT) &&
103 (event_id == WIFI_EVENT_STA_DISCONNECTED)) {
110 }
else if ((event_base == IP_EVENT) && (event_id == IP_EVENT_STA_GOT_IP)) {
134 ESP_ERROR_CHECK(esp_netif_init());
135 ESP_ERROR_CHECK(esp_event_loop_create_default());
136 (void)esp_netif_create_default_wifi_sta();
137 wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
138 ESP_ERROR_CHECK(esp_wifi_init(&cfg));
139 esp_event_handler_instance_t h_any;
140 esp_event_handler_instance_t h_ip;
141 ESP_ERROR_CHECK(esp_event_handler_instance_register(
143 ESP_ERROR_CHECK(esp_event_handler_instance_register(
145 wifi_config_t wifi_cfg;
146 (void)memset(&wifi_cfg, 0,
sizeof(wifi_cfg));
147 (void)strncpy((
char *)wifi_cfg.sta.ssid,
WIFI_SSID,
148 sizeof(wifi_cfg.sta.ssid) - 1U);
150 sizeof(wifi_cfg.sta.password) - 1U);
151 wifi_cfg.sta.threshold.authmode = WIFI_AUTH_WPA2_PSK;
152 ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
153 ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_cfg));
154 ESP_ERROR_CHECK(esp_wifi_start());
160 ESP_LOGI(
TAG,
"WiFi connected");
162 ESP_LOGW(
TAG,
"WiFi connect failed — TRNG entropy may be reduced");
164 (void)esp_event_handler_instance_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, h_ip);
165 (void)esp_event_handler_instance_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, h_any);
194 bool keep_running =
true;
196 while (keep_running) {
198 CW_SecureSession session{};
200 if (!wallet.connect(session)) {
201 ESP_LOGW(
TAG,
"Card not detected — hold card to reader");
206 ESP_LOGI(
TAG,
"Card connected and secure channel established");
211 ESP_LOGI(
TAG,
"Signing test hash...");
213 uint8_t testHash[CW_HASH_SIZE];
214 (void)memset(testHash, 0x01,
sizeof(testHash));
219 CW_SignRequest signRequest(session,
221 CW_SIGN_SIG_ECDSA_LOW_S,
223 signRequest.hash = testHash;
224 signRequest.hashLength =
static_cast<uint8_t
>(CW_HASH_SIZE);
225 (void)CW_Utils::safe_memcpy(signRequest.pin,
sizeof(signRequest.pin),
228 CW_SignResult signResult = wallet.sign(signRequest);
230 if (signResult.errorCode == CW_OK) {
231 ESP_LOGI(
TAG,
"Signature received (64 bytes raw r||s)");
234 ESP_LOG_BUFFER_HEX_LEVEL(
TAG,
235 &signResult.signature[CW_SIG_R_OFFSET], 8U, ESP_LOG_INFO);
237 ESP_LOG_BUFFER_HEX_LEVEL(
TAG,
238 &signResult.signature[CW_SIG_S_OFFSET], 8U, ESP_LOG_INFO);
240 ESP_LOGI(
TAG,
"Card processed successfully");
242 }
else if (signResult.errorCode == CW_SIGN_PIN_INCORRECT) {
246 ESP_LOGE(
TAG,
"Wrong PIN — halting to protect retry counter");
247 CW_Utils::secure_wipe(testHash,
sizeof(testHash));
248 CW_Utils::secure_wipe(signResult.signature,
sizeof(signResult.signature));
249 wallet.disconnect(session);
250 keep_running =
false;
254 ESP_LOGE(
TAG,
"Sign failed: errorCode = 0x%02X",
255 static_cast<unsigned int>(signResult.errorCode));
259 CW_Utils::secure_wipe(testHash,
sizeof(testHash));
260 CW_Utils::secure_wipe(signResult.signature,
sizeof(signResult.signature));
263 wallet.disconnect(session);
286 esp_err_t nvs_ret = nvs_flash_init();
287 if ((nvs_ret == ESP_ERR_NVS_NO_FREE_PAGES) ||
288 (nvs_ret == ESP_ERR_NVS_NEW_VERSION_FOUND)) {
289 ESP_ERROR_CHECK(nvs_flash_erase());
290 nvs_ret = nvs_flash_init();
292 ESP_ERROR_CHECK(nvs_ret);
299 spi_bus_config_t buscfg = {};
306 ESP_ERROR_CHECK(spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_CH_AUTO));
324 esp_err_t nfc_ret =
pn532_init(&nfc, &nfc_cfg);
325 if (nfc_ret != ESP_OK) {
326 ESP_LOGE(
TAG,
"PN532 init failed — check wiring and interface selection");
331 (void)logger.
begin(115200UL);
336 CryptnoxWallet wallet(nfcTransport, logger, cryptoProvider, platform);
338 if (!wallet.begin()) {
339 ESP_LOGE(
TAG,
"Wallet init failed (SAMConfig)");
346 ESP_LOGI(
TAG,
"Ready — hold Cryptnox card to reader");
static const size_t DEFAULT_PIN_LEN
void app_main(void)
ESP-IDF application entry point.
static EventGroupHandle_t s_wifi_event_group
#define SPI_MAX_TRANSFER_SZ
static void run_basic_usage_loop(CryptnoxWallet &wallet)
Main application loop: connect, sign a test hash, wipe buffers, disconnect.
static const uint32_t LOOP_DELAY_MS
static const uint8_t DEFAULT_PIN[]
Demo PIN — replace with the PIN used during card initialisation.
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.
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.
bool printFirmwareVersion() override
Query and log the PN532 firmware version.
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
pn532_transport_t transport
Opaque-like runtime state for a single PN532 instance.