cryptnox-sdk-arduino 1.0.0
Arduino library for Cryptnox Hardware Wallet
Loading...
Searching...
No Matches
CryptnoxWallet Class Reference

High-level interface for interacting with a Cryptnox Hardware Wallet over NFC. More...

#include <CryptnoxWallet.h>

Collaboration diagram for CryptnoxWallet:
[legend]

Public Member Functions

 CryptnoxWallet (CW_NfcTransport &driver, CW_Logger &logger, CW_CryptoProvider &crypto, CW_Platform &platform)
 Construct a CryptnoxWallet.
 CryptnoxWallet (const CryptnoxWallet &)=delete
CryptnoxWalletoperator= (const CryptnoxWallet &)=delete
bool begin ()
 Initialize the NFC module via the underlying transport driver.
bool connect (CW_SecureSession &session)
 Connect to the Cryptnox card and establish a secure channel.
bool establishSecureChannel (CW_SecureSession &session)
 Establish a secure channel (SELECT → certificate → ECDH → mutual auth).
void disconnect (CW_SecureSession &session)
 Disconnect and securely clear the session.
bool getCardInfo (CW_SecureSession &session, CW_CardInfo *info=NULL)
 Send a secured GET CARD INFO APDU (0x80FA0000) and optionally decode the owner name/email from the response.
bool verifyPin (CW_SecureSession &session, const uint8_t *pin, uint8_t pinLength)
 Verify the PIN code on the card.
CW_SignResult sign (CW_SignRequest &request)
 Sign a 32-byte digest using a card-resident key.
bool writeUserData (CW_SecureSession &session, uint8_t slot, const uint8_t *data, uint16_t dataLength)
 Write data to a user memory slot, paginating in CW_USER_DATA_PAGE_SIZE chunks.

Static Public Member Functions

static bool parseDerSignature (const uint8_t *der, uint8_t derLength, uint8_t *r, uint8_t &rLength, uint8_t *s, uint8_t &sLength)
 Parse a DER-encoded ECDSA signature to extract raw r and s values.

Private Member Functions

bool isSecureChannelOpen (const CW_SecureSession &session) const
bool printPN532FirmwareVersion ()
bool validateSignRequest (const CW_SignRequest &request, CW_SignResult &result)
void buildSignPayload (const CW_SignRequest &request, uint8_t *data, uint16_t &dataLength)
bool sendSignApdu (CW_SignRequest &request, const uint8_t *data, uint16_t dataLength, uint8_t *derResponse, uint16_t &derLength, CW_SignResult &result)
bool extractRawSignature (const uint8_t *derResponse, uint16_t derLength, CW_SignResult &result)
void debugPrintSignature (const uint8_t *signature)

Private Attributes

CW_Logger_logger
 Logging interface.
CW_Platform_platform
 Platform abstraction (sleep_ms).
CW_SecureChannel _secure
 Owned secure channel.

Detailed Description

High-level interface for interacting with a Cryptnox Hardware Wallet over NFC.

Manages card connection, secure channel establishment (delegated to CW_SecureChannel), PIN verification, transaction signing, user-data writing, and card-info retrieval.

Dependencies are injected by the caller via the constructor. The class itself only talks to the four abstract adapters, keeping the implementation platform-independent.

Typical lifecycle
CryptnoxWallet wallet(transport, logger, crypto, platform);
wallet.begin();
if (wallet.connect(session)) {
wallet.verifyPin(session, pin, pinLen);
wallet.sign(req);
}
wallet.disconnect(session); // mandatory — even on connect() failure
CryptnoxWallet wallet(nfc, serialAdapter, cryptoProvider, platform)
ArduinoPlatform platform
CryptnoxWallet(CW_NfcTransport &driver, CW_Logger &logger, CW_CryptoProvider &crypto, CW_Platform &platform)
Construct a CryptnoxWallet.
Holds cryptographic session state for reentrant secure channel operations.
Definition CW_Defs.h:168
Note
Single-shot use — the class is non-copyable. Reuse the same CryptnoxWallet instance across multiple card sessions; do not construct one per APDU.
Examples
BasicUsage.ino, Connect.ino, Sign.ino, UsdcSigning.ino, and VerifyPin.ino.

Definition at line 160 of file CryptnoxWallet.h.

Constructor & Destructor Documentation

◆ CryptnoxWallet() [1/2]

CryptnoxWallet::CryptnoxWallet ( CW_NfcTransport & driver,
CW_Logger & logger,
CW_CryptoProvider & crypto,
CW_Platform & platform )

Construct a CryptnoxWallet.

Parameters
driverReference to the NFC transport implementation.
loggerReference to the logging implementation.
cryptoReference to the crypto provider implementation.
platformReference to the platform abstraction (for sleep_ms).

Definition at line 27 of file CryptnoxWallet.cpp.

References _logger, _platform, _secure, and platform.

Referenced by CryptnoxWallet(), and operator=().

◆ CryptnoxWallet() [2/2]

CryptnoxWallet::CryptnoxWallet ( const CryptnoxWallet & )
delete

References CryptnoxWallet().

Member Function Documentation

◆ begin()

bool CryptnoxWallet::begin ( )

Initialize the NFC module via the underlying transport driver.

Returns
true if the module was successfully initialised, false otherwise.

Definition at line 36 of file CryptnoxWallet.cpp.

References _secure, and printPN532FirmwareVersion().

◆ buildSignPayload()

◆ connect()

bool CryptnoxWallet::connect ( CW_SecureSession & session)

Connect to the Cryptnox card and establish a secure channel.

Retries the full card activation sequence up to CW_CONNECT_MAX_ATTEMPTS times. On any failure (including transient transport errors) the session is securely wiped before the next attempt so no partial key material can survive a retry (CRIT-04).

Parameters
[out]sessionSecure session to populate with derived keys and IV on success; left zero-wiped on failure.
Returns
true if the secure channel was established and session is ready for use, false otherwise.
Postcondition
On true: session holds valid Kenc / Kmac / IV.
On false: session is zero-wiped.
Warning
Always call disconnect() after this — even on failure — to release the reader for the next card cycle.

Definition at line 44 of file CryptnoxWallet.cpp.

References _logger, _platform, _secure, CW_SecureSession::clear(), CW_CONNECT_MAX_ATTEMPTS, establishSecureChannel(), and F.

◆ debugPrintSignature()

void CryptnoxWallet::debugPrintSignature ( const uint8_t * signature)
private

Definition at line 543 of file CryptnoxWallet.cpp.

References _logger, CW_RAW_SIGNATURE_SIZE, F, and HEX.

Referenced by sign().

◆ disconnect()

void CryptnoxWallet::disconnect ( CW_SecureSession & session)

Disconnect and securely clear the session.

Wipes any session keys and resets the NFC reader so the next card detection cycle starts from a clean state.

Parameters
[in,out]sessionSession to clear. Safe to pass a never-connected or partially-connected session.
Precondition
Must be called at the end of every card-processing iteration — including iterations where connect() failed — otherwise the NFC reader may remain in an unresponsive state.

Definition at line 158 of file CryptnoxWallet.cpp.

References _secure, CW_SecureSession::clear(), and isSecureChannelOpen().

◆ establishSecureChannel()

bool CryptnoxWallet::establishSecureChannel ( CW_SecureSession & session)

Establish a secure channel (SELECT → certificate → ECDH → mutual auth).

Lower-level than connect(): runs the full activation sequence once, without the retry loop. Used internally by connect(); exposed for advanced callers that handle retry policy themselves.

Parameters
[out]sessionSecure session to populate.
Returns
true if mutual authentication succeeded, false if any step of the activation sequence (SELECT, certificate chain verification, ECDH, MAC check) failed.
Warning
All sensitive ephemeral key material is wiped from the stack on every exit path (H-01, M-02).

Definition at line 75 of file CryptnoxWallet.cpp.

References _logger, _secure, CW_CERT_OK, CW_CURVE_SECP256R1, F, HEX, and CW_Utils::secure_wipe().

Referenced by connect().

◆ extractRawSignature()

bool CryptnoxWallet::extractRawSignature ( const uint8_t * derResponse,
uint16_t derLength,
CW_SignResult & result )
private

◆ getCardInfo()

bool CryptnoxWallet::getCardInfo ( CW_SecureSession & session,
CW_CardInfo * info = NULL )

Send a secured GET CARD INFO APDU (0x80FA0000) and optionally decode the owner name/email from the response.

Parameters
[in,out]sessionValid secure session.
[out]infoOptional output. When non-NULL and the call succeeds, populated with the card's owner name and email (ASCII, NUL-terminated).
Returns
true if the secure exchange completed and (when info is non-NULL) parsing the name/email fields succeeded.

Definition at line 165 of file CryptnoxWallet.cpp.

References _logger, _secure, CW_CARD_EMAIL_MAX_LEN, CW_CARD_NAME_MAX_LEN, CW_CardInfo::email, F, isSecureChannelOpen(), CW_CardInfo::name, CW_Utils::safe_memcpy(), and CW_Utils::secure_wipe().

◆ isSecureChannelOpen()

bool CryptnoxWallet::isSecureChannelOpen ( const CW_SecureSession & session) const
private

◆ operator=()

CryptnoxWallet & CryptnoxWallet::operator= ( const CryptnoxWallet & )
delete

References CryptnoxWallet().

◆ parseDerSignature()

bool CryptnoxWallet::parseDerSignature ( const uint8_t * der,
uint8_t derLength,
uint8_t * r,
uint8_t & rLength,
uint8_t * s,
uint8_t & sLength )
static

Parse a DER-encoded ECDSA signature to extract raw r and s values.

Parameters
[in]derDER-encoded signature bytes.
[in]derLengthDER length.
[out]rBuffer for r (at least 33 bytes).
[out]rLengthActual r length written.
[out]sBuffer for s (at least 33 bytes).
[out]sLengthActual s length written.
Returns
true on success, false on malformed DER.

Definition at line 322 of file CryptnoxWallet.cpp.

References CW_DER_TAG_INTEGER, CW_DER_TAG_SEQUENCE, and CW_Utils::safe_memcpy().

Referenced by extractRawSignature().

◆ printPN532FirmwareVersion()

bool CryptnoxWallet::printPN532FirmwareVersion ( )
private

Definition at line 378 of file CryptnoxWallet.cpp.

References _secure.

Referenced by begin().

◆ sendSignApdu()

bool CryptnoxWallet::sendSignApdu ( CW_SignRequest & request,
const uint8_t * data,
uint16_t dataLength,
uint8_t * derResponse,
uint16_t & derLength,
CW_SignResult & result )
private

◆ sign()

CW_SignResult CryptnoxWallet::sign ( CW_SignRequest & request)

Sign a 32-byte digest using a card-resident key.

Builds the SIGN payload (hash || optional BIP32 path || optional PIN), sends it through the secure channel, parses the DER signature returned by the card, and unpacks it into the canonical 64-byte raw form (r[32] || s[32]).

Parameters
[in]requestSign parameters — must reference a valid secure session, a 32-byte hash, the desired key/signature type, and the PIN (unless pinLessMode is set).
Returns
CW_SignResult. On success errorCode is CW_OK and signature holds the 64-byte raw signature. On failure the signature is zeroed and errorCode indicates the cause:
Return values
CW_OKSignature valid.
CW_INVALID_SESSIONSecure channel not open.
CW_SIGN_KEY_TOO_SHORTBad hash buffer / length.
CW_SIGN_NO_KEY_LOADEDCard rejected the SIGN APDU.
CW_SIGN_PIN_INCORRECTPIN length out of range.
CW_SIGN_KEY_TOO_SHORT_WITH_PINLESS_MODEPIN-less mode requested but keyType is not CW_SIGN_PINLESS_K1.
Warning
When pinLessMode is false the request.pin field must be populated. The destructor of CW_SignRequest securely wipes the PIN, but the caller must zero any other copy.

Definition at line 293 of file CryptnoxWallet.cpp.

References buildSignPayload(), CW_HASH_SIZE, CW_MAX_DERIVE_PATH_LENGTH, CW_MAX_PIN_LENGTH, CW_OK, debugPrintSignature(), CW_SignResult::errorCode, extractRawSignature(), CW_Utils::secure_wipe(), sendSignApdu(), CW_SignResult::signature, and validateSignRequest().

◆ validateSignRequest()

◆ verifyPin()

bool CryptnoxWallet::verifyPin ( CW_SecureSession & session,
const uint8_t * pin,
uint8_t pinLength )

Verify the PIN code on the card.

Sends an encrypted VERIFY PIN APDU. The card maintains a try counter: every wrong attempt decrements it, and reaching zero locks the PIN permanently until a successful PUK / re-initialisation flow.

Parameters
[in,out]sessionValid secure session.
[in]pinPIN bytes (ASCII digits, 4–9 characters).
[in]pinLengthLength of the PIN (must be in [CW_MIN_PIN_LENGTH, CW_MAX_PIN_LENGTH]).
Returns
true if the card accepted the PIN, false on wrong PIN, closed or invalid session, length out of range, or transport / MAC failure.
Warning
Each failed attempt decrements the card's PIN counter. Treat a false return as "wrong PIN" only after confirming session validity — a transport glitch should not be retried with a new PIN.

Definition at line 219 of file CryptnoxWallet.cpp.

References _logger, _secure, CW_MAX_PIN_LENGTH, CW_MIN_PIN_LENGTH, F, isSecureChannelOpen(), CW_Utils::safe_memcpy(), and CW_Utils::secure_wipe().

◆ writeUserData()

bool CryptnoxWallet::writeUserData ( CW_SecureSession & session,
uint8_t slot,
const uint8_t * data,
uint16_t dataLength )

Write data to a user memory slot, paginating in CW_USER_DATA_PAGE_SIZE chunks.

Parameters
[in,out]sessionValid secure session.
[in]slotUser data slot index.
[in]dataData to write.
[in]dataLengthTotal bytes to write.
Returns
true if all pages written successfully, false otherwise.

Definition at line 241 of file CryptnoxWallet.cpp.

References _logger, _secure, CW_USER_DATA_PAGE_SIZE, F, and isSecureChannelOpen().

Member Data Documentation

◆ _logger

◆ _platform

CW_Platform& CryptnoxWallet::_platform
private

Platform abstraction (sleep_ms).

Definition at line 329 of file CryptnoxWallet.h.

Referenced by connect(), and CryptnoxWallet().

◆ _secure

CW_SecureChannel CryptnoxWallet::_secure
private

The documentation for this class was generated from the following files: