/* * handshake.h — BLE Challenge-Response Authentication Protocol * * Protocol flow: * 1. Device sends: {"response_type":"handshake_challenge","content":{"challenge":""}} * 2. iPad computes: SHA256(R || Key) and replies with base64 of the digest * 3. Device verifies and sends: {"response_type":"handshake_confirm","content":{"status":"success"|"failed"}} * * Key derivation: SHA256("29C310F5") → first 16 bytes XOR 0x5A */ #ifndef HANDSHAKE_H #define HANDSHAKE_H #include #include #define HANDSHAKE_KEY_LEN 16 #define HANDSHAKE_KN_STR "29C310F5"//"48872dc21ede" /* test vector; restore to "29C310F5" after verification */ #define HANDSHAKE_R_LEN 16 #define HANDSHAKE_TIMEOUT_SEC 5 typedef enum { HS_STATE_IDLE = 0, HS_STATE_WAIT_RESPONSE, HS_STATE_SUCCESS, HS_STATE_FAILED } handshake_state_t; typedef struct { handshake_state_t state; uint8_t key[HANDSHAKE_KEY_LEN]; uint8_t R[HANDSHAKE_R_LEN]; } handshake_ctx_t; /* Derive the 16-byte handshake key: SHA256(HANDSHAKE_KN_STR)[0..15] XOR 0x5A */ void handshake_derive_key(uint8_t out_key[HANDSHAKE_KEY_LEN]); /* Print key bytes to stdout as space-separated hex (e.g., "58 48 c8 ff ...") */ void handshake_print_key(const uint8_t key[HANDSHAKE_KEY_LEN]); /* Initialise ctx: derive key, set state=IDLE, zero R */ void handshake_init(handshake_ctx_t *ctx); /* Generate random R, set state=WAIT_RESPONSE, write JSON to out_json_buf. * Returns 0 on success, -1 on error. */ int handshake_build_challenge(handshake_ctx_t *ctx, char *out_json_buf, size_t buf_size); /* Validate iPad response JSON (must contain "response" field with base64 value). * Returns 1: success (state→SUCCESS) * 0: wrong answer (state→FAILED) * -1: malformed JSON * -2: timeout */ int handshake_process_response(handshake_ctx_t *ctx, const char *json_str); /* Build confirm JSON. success=1 → {"status":"success"}; success=0 → {"status":"failed","reason":"..."} * reason_str may be NULL (defaults to "invalid_response"). * Returns 0. */ int handshake_build_confirm(handshake_ctx_t *ctx, int success, const char *reason_str, char *out_json_buf, size_t buf_size); /* Reset state to IDLE, zero R (key is retained) */ void handshake_reset(handshake_ctx_t *ctx); /* Return current state */ handshake_state_t handshake_get_state(const handshake_ctx_t *ctx); /* Return 1 if WAIT_RESPONSE and timeout expired, else 0 */ int handshake_check_timeout(handshake_ctx_t *ctx); #endif /* HANDSHAKE_H */