73 lines
2.6 KiB
C
73 lines
2.6 KiB
C
/*
|
|
* handshake.h — BLE Challenge-Response Authentication Protocol
|
|
*
|
|
* Protocol flow:
|
|
* 1. Device sends: {"response_type":"handshake_challenge","content":{"challenge":"<base64(R)>"}}
|
|
* 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 <stdint.h>
|
|
#include <stddef.h>
|
|
|
|
#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 */
|