cryptnox-sdk-arduino 1.0.0
Arduino library for Cryptnox Hardware Wallet
Loading...
Searching...
No Matches
BasicUsage.ino
Go to the documentation of this file.
1/*
2 * SPDX-License-Identifier: LGPL-3.0-or-later
3 * Copyright (c) 2026 Cryptnox SA
4 */
5
17
18#include <CryptnoxWallet.h>
19
20/* ============================================================================
21 * 1. Interface Selection
22 * --------------------------------------------------------------------------
23 * Uncomment exactly ONE of the two lines below to choose the PN532 interface.
24 * ========================================================================= */
25#define USE_SPI
26// #define USE_I2C
27
28/* ============================================================================
29 * 2. Pin Configuration
30 * ========================================================================= */
31#if defined(USE_SPI)
32
33#include <SPI.h>
34
39#define PN532_SS (10U)
40
41/* PRODUCTION NOTE (LOW-03): ArduinoLoggerAdapter streams all log output over
42 * USB-CDC Serial, which is visible to any attached host process. For firmware
43 * that is shipped to end-users, replace the two lines below with:
44 * NullLoggerAdapter serialAdapter;
45 * and remove the serialAdapter.begin() call in setup(). NullLoggerAdapter is
46 * a no-op and incurs zero code-size or runtime overhead. */
49
50#elif defined(USE_I2C)
51
52#include <Wire.h>
53
58#define PN532_IRQ (2U)
59
64#define PN532_RST (3U)
65
66/* PRODUCTION NOTE (LOW-03): see comment in the USE_SPI block above. */
68PN532Adapter nfc(serialAdapter, PN532_IRQ, PN532_RST, &Wire);
69
70#else
71#error "Please define USE_SPI or USE_I2C to select the PN532 interface."
72#endif
73
75#define DEFAULT_PIN "000000000"
76#define DEFAULT_PIN_LEN (sizeof(DEFAULT_PIN) - 1U)
77
81
88void setup() {
89 serialAdapter.begin(115200);
90
91 /* Arduino R4: Wait 1s to get Serial ready */
92 delay(1000);
93
94#if defined(USE_SPI)
95 /* Initialize SPI bus */
96 SPI.begin();
97#elif defined(USE_I2C)
98 /* Initialize I2C bus */
99 Wire.begin();
100#endif
101
102 /* Initialize the PN532 module — halt on failure to avoid silent errors */
103 if (!wallet.begin()) {
104 serialAdapter.println(F("PN532 init failed"));
105 while(1);
106 }
107}
108
117void loop() {
118
119 /* Step 1: Connect to card and establish secure channel */
120 CW_SecureSession session;
121 if (wallet.connect(session)) {
122 serialAdapter.println(F("Card connected and secure channel established"));
123
124 /* Step 2: Sign a test hash (32 bytes of 0x01 for demo purposes) */
125 /* NOTE: Card must have a seed loaded (via Python SDK: card.generate_seed(pin) */
126 /* or card.load_seed(seed, pin)) before signing will work. */
127 serialAdapter.println(F("Signing test hash..."));
128 uint8_t testHash[CW_HASH_SIZE];
129 memset(testHash, 0x01, sizeof(testHash));
130
131 /* Build sign request per CW_SignRequest API.
132 * PIN is included in the sign data payload for authentication.
133 * Alternatively, call verifyPin() first and omit the PIN here. */
135 signRequest.hash = testHash;
136 signRequest.hashLength = sizeof(testHash);
137 /* Set PIN (must match the PIN used during card.init()) */
138 CW_Utils::safe_memcpy(signRequest.pin, sizeof(signRequest.pin),
139 reinterpret_cast<const uint8_t*>(DEFAULT_PIN), DEFAULT_PIN_LEN);
140
141 CW_SignResult signResult = wallet.sign(signRequest);
142
143 if (signResult.errorCode == CW_OK) {
144 serialAdapter.println(F("Signature received (64 bytes raw r||s)"));
145
146 /* Print first 8 bytes of R and S for quick visual check */
147 serialAdapter.print(F(" R[0..7]: "));
148 for (uint8_t i = CW_SIG_R_OFFSET; i < CW_SIG_R_OFFSET + 8U; i++) {
149 if (signResult.signature[i] < 0x10U) serialAdapter.print(F("0"));
150 serialAdapter.print(signResult.signature[i], HEX);
151 serialAdapter.print(F(" "));
152 }
153 serialAdapter.println();
154 serialAdapter.print(F(" S[0..7]: "));
155 for (uint8_t i = CW_SIG_S_OFFSET; i < CW_SIG_S_OFFSET + 8U; i++) {
156 if (signResult.signature[i] < 0x10U) serialAdapter.print(F("0"));
157 serialAdapter.print(signResult.signature[i], HEX);
158 serialAdapter.print(F(" "));
159 }
160 serialAdapter.println();
161 serialAdapter.println(F("Card processed successfully"));
162 } else {
163 serialAdapter.print(F("Sign failed, errorCode: 0x"));
164 serialAdapter.println(signResult.errorCode, HEX);
165 }
166
167 /* Securely wipe sensitive buffers */
168 CW_Utils::secure_wipe(testHash, sizeof(testHash));
169 CW_Utils::secure_wipe(signResult.signature, sizeof(signResult.signature));
170 }
171
172 /* Always disconnect to reset reader for next card detection */
173 wallet.disconnect(session);
174
175 /* Wait before next iteration */
176 delay(1000);
177}
#define DEFAULT_PIN
Default PIN code (ASCII digits). Must match the PIN used during card.init().
void setup()
Arduino setup function.
CryptnoxWallet wallet(nfc, serialAdapter, cryptoProvider, platform)
#define PN532_SS
SPI slave select (CS) pin for the PN532 module.
PN532Adapter nfc(serialAdapter, PN532_SS, &SPI)
#define DEFAULT_PIN_LEN
ArduinoLoggerAdapter serialAdapter
ArduinoPlatform platform
ArduinoCryptoProvider cryptoProvider
void loop()
Arduino main loop.
#define CW_SIG_R_OFFSET
Definition CW_Defs.h:116
#define CW_HASH_SIZE
Definition CW_Defs.h:108
#define CW_OK
Definition CW_Defs.h:80
#define CW_SIGN_WITH_PIN
Definition CW_Defs.h:92
#define CW_SIGN_CURR_K1
Definition CW_Defs.h:85
#define CW_SIGN_SIG_ECDSA_LOW_S
Definition CW_Defs.h:96
#define CW_SIG_S_OFFSET
Definition CW_Defs.h:117
CW_CryptoProvider implementation for the Arduino UNO R4 (RA4M1).
CW_Logger implementation wrapping Arduino's HardwareSerial.
CW_Platform implementation using Arduino's blocking delay().
static bool safe_memcpy(uint8_t *dst, size_t dstSize, const uint8_t *src, size_t count)
Safe memcpy — validates pointers, sizes, and checks for overlap.
Definition CW_Utils.cpp:50
static void secure_wipe(uint8_t *buf, size_t len)
Securely zero a buffer, guaranteed not to be optimised away.
Definition CW_Utils.cpp:37
High-level interface for interacting with a Cryptnox Hardware Wallet over NFC.
CW_NfcTransport implementation over the Adafruit_PN532 driver.
#define F(string_literal)
#define HEX
Holds cryptographic session state for reentrant secure channel operations.
Definition CW_Defs.h:168
Request parameters for CryptnoxWallet::sign.
const uint8_t * hash
uint8_t pin[CW_MAX_PIN_LENGTH]
Result of CryptnoxWallet::sign.
uint8_t signature[CW_RAW_SIGNATURE_SIZE]