hap_pair_verify.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. #include <string.h>
  2. #include "hap.h"
  3. #include "hap_internal.h"
  4. #include "tlv8.h"
  5. #include "esp_log.h"
  6. #include "esp_mac.h"
  7. #include "mbedtls/aes.h"
  8. #include "sodium.h"
  9. static const char *TAG = "hap_verify";
  10. esp_err_t hap_pair_verify_m1(hap_session_t *session, const uint8_t *input,
  11. size_t input_len, uint8_t *output,
  12. size_t output_capacity, size_t *output_len) {
  13. size_t state_len = 0;
  14. const uint8_t *state =
  15. tlv8_find(input, input_len, TLV_TYPE_STATE, &state_len);
  16. if (!state || state_len != 1 || state[0] != PAIR_VERIFY_STATE_M1) {
  17. ESP_LOGE(TAG, "Invalid M1 state");
  18. return ESP_ERR_INVALID_ARG;
  19. }
  20. size_t client_pk_len = 0;
  21. const uint8_t *client_pk =
  22. tlv8_find(input, input_len, TLV_TYPE_PUBLIC_KEY, &client_pk_len);
  23. if (!client_pk || client_pk_len != HAP_X25519_KEY_SIZE) {
  24. ESP_LOGE(TAG, "Invalid M1 public key");
  25. return ESP_ERR_INVALID_ARG;
  26. }
  27. memcpy(session->client_public_key, client_pk, HAP_X25519_KEY_SIZE);
  28. if (crypto_scalarmult(session->shared_secret, session->session_secret_key,
  29. session->client_public_key) != 0) {
  30. ESP_LOGE(TAG, "X25519 key exchange failed");
  31. return ESP_FAIL;
  32. }
  33. uint8_t mac[6];
  34. esp_read_mac(mac, ESP_MAC_WIFI_STA);
  35. char device_id[18];
  36. snprintf(device_id, sizeof(device_id), "%02X:%02X:%02X:%02X:%02X:%02X",
  37. mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
  38. size_t device_id_len = 17;
  39. uint8_t accessory_info[128];
  40. size_t accessory_info_len = 0;
  41. memcpy(accessory_info + accessory_info_len, session->session_public_key,
  42. HAP_X25519_KEY_SIZE);
  43. accessory_info_len += HAP_X25519_KEY_SIZE;
  44. memcpy(accessory_info + accessory_info_len, device_id, device_id_len);
  45. accessory_info_len += device_id_len;
  46. memcpy(accessory_info + accessory_info_len, session->client_public_key,
  47. HAP_X25519_KEY_SIZE);
  48. accessory_info_len += HAP_X25519_KEY_SIZE;
  49. uint8_t signature[crypto_sign_BYTES];
  50. crypto_sign_detached(signature, NULL, accessory_info, accessory_info_len,
  51. session->device_secret_key);
  52. uint8_t sub_tlv[256];
  53. tlv8_encoder_t sub_enc;
  54. tlv8_encoder_init(&sub_enc, sub_tlv, sizeof(sub_tlv));
  55. tlv8_encode(&sub_enc, TLV_TYPE_IDENTIFIER, (const uint8_t *)device_id,
  56. device_id_len);
  57. tlv8_encode(&sub_enc, TLV_TYPE_SIGNATURE, signature, crypto_sign_BYTES);
  58. uint8_t session_key[32];
  59. hap_hkdf_sha512((uint8_t *)"Pair-Verify-Encrypt-Salt", 24,
  60. session->shared_secret, HAP_X25519_KEY_SIZE,
  61. (uint8_t *)"Pair-Verify-Encrypt-Info", 24, session_key, 32);
  62. uint8_t nonce[12] = {0, 0, 0, 0, 'P', 'V', '-', 'M', 's', 'g', '0', '2'};
  63. uint8_t encrypted[256 + crypto_aead_chacha20poly1305_ietf_ABYTES];
  64. unsigned long long encrypted_len = 0;
  65. crypto_aead_chacha20poly1305_ietf_encrypt(encrypted, &encrypted_len, sub_tlv,
  66. tlv8_encoder_size(&sub_enc), NULL,
  67. 0, NULL, nonce, session_key);
  68. tlv8_encoder_t enc;
  69. tlv8_encoder_init(&enc, output, output_capacity);
  70. tlv8_encode_byte(&enc, TLV_TYPE_STATE, PAIR_VERIFY_STATE_M2);
  71. tlv8_encode(&enc, TLV_TYPE_PUBLIC_KEY, session->session_public_key,
  72. HAP_X25519_KEY_SIZE);
  73. tlv8_encode(&enc, TLV_TYPE_ENCRYPTED_DATA, encrypted, (size_t)encrypted_len);
  74. *output_len = tlv8_encoder_size(&enc);
  75. session->pair_verify_state = PAIR_VERIFY_STATE_M2;
  76. memcpy(session->encrypt_key, session_key, sizeof(session_key));
  77. return ESP_OK;
  78. }
  79. esp_err_t hap_pair_verify_m3(hap_session_t *session, const uint8_t *input,
  80. size_t input_len, uint8_t *output,
  81. size_t output_capacity, size_t *output_len) {
  82. size_t state_len = 0;
  83. const uint8_t *state =
  84. tlv8_find(input, input_len, TLV_TYPE_STATE, &state_len);
  85. if (!state || state_len != 1 || state[0] != PAIR_VERIFY_STATE_M3) {
  86. ESP_LOGE(TAG, "Invalid M3 state");
  87. return ESP_ERR_INVALID_ARG;
  88. }
  89. uint8_t encrypted[512];
  90. size_t encrypted_len = 0;
  91. if (!tlv8_decode_concat(input, input_len, TLV_TYPE_ENCRYPTED_DATA, encrypted,
  92. sizeof(encrypted), &encrypted_len)) {
  93. ESP_LOGE(TAG, "Missing M3 encrypted data");
  94. return ESP_ERR_INVALID_ARG;
  95. }
  96. uint8_t nonce[12] = {0, 0, 0, 0, 'P', 'V', '-', 'M', 's', 'g', '0', '3'};
  97. uint8_t decrypted[512];
  98. unsigned long long decrypted_len = 0;
  99. if (crypto_aead_chacha20poly1305_ietf_decrypt(
  100. decrypted, &decrypted_len, NULL, encrypted, encrypted_len, NULL, 0,
  101. nonce, session->encrypt_key) != 0) {
  102. ESP_LOGE(TAG, "M3 decryption failed");
  103. tlv8_encoder_t enc;
  104. tlv8_encoder_init(&enc, output, output_capacity);
  105. tlv8_encode_byte(&enc, TLV_TYPE_STATE, PAIR_VERIFY_STATE_M4);
  106. tlv8_encode_byte(&enc, TLV_TYPE_ERROR, TLV_ERROR_AUTHENTICATION);
  107. *output_len = tlv8_encoder_size(&enc);
  108. return ESP_ERR_INVALID_STATE;
  109. }
  110. hap_hkdf_sha512((uint8_t *)"Control-Salt", 12, session->shared_secret,
  111. HAP_X25519_KEY_SIZE, (uint8_t *)"Control-Read-Encryption-Key",
  112. 27, session->encrypt_key, 32);
  113. hap_hkdf_sha512((uint8_t *)"Control-Salt", 12, session->shared_secret,
  114. HAP_X25519_KEY_SIZE,
  115. (uint8_t *)"Control-Write-Encryption-Key", 28,
  116. session->decrypt_key, 32);
  117. tlv8_encoder_t enc;
  118. tlv8_encoder_init(&enc, output, output_capacity);
  119. tlv8_encode_byte(&enc, TLV_TYPE_STATE, PAIR_VERIFY_STATE_M4);
  120. *output_len = tlv8_encoder_size(&enc);
  121. session->pair_verify_state = PAIR_VERIFY_STATE_M4;
  122. session->session_established = true;
  123. return ESP_OK;
  124. }
  125. esp_err_t hap_pair_verify_m1_raw(hap_session_t *session, const uint8_t *input,
  126. size_t input_len, uint8_t *output,
  127. size_t output_capacity, size_t *output_len) {
  128. const uint8_t *client_epk;
  129. if (input_len >= 68) {
  130. client_epk = input + 4;
  131. } else if (input_len >= 64) {
  132. client_epk = input;
  133. } else if (input_len >= 32) {
  134. client_epk = input;
  135. } else {
  136. ESP_LOGE(TAG, "Input too short for pair-verify: %zu", input_len);
  137. return ESP_ERR_INVALID_ARG;
  138. }
  139. memcpy(session->client_public_key, client_epk, HAP_X25519_KEY_SIZE);
  140. if (crypto_scalarmult(session->shared_secret, session->session_secret_key,
  141. session->client_public_key) != 0) {
  142. ESP_LOGE(TAG, "X25519 key exchange failed");
  143. return ESP_FAIL;
  144. }
  145. uint8_t aes_key[16];
  146. uint8_t aes_iv[16];
  147. {
  148. crypto_hash_sha512_state state;
  149. uint8_t hash[64];
  150. crypto_hash_sha512_init(&state);
  151. crypto_hash_sha512_update(&state, (const uint8_t *)"Pair-Verify-AES-Key",
  152. 19);
  153. crypto_hash_sha512_update(&state, session->shared_secret, 32);
  154. crypto_hash_sha512_final(&state, hash);
  155. memcpy(aes_key, hash, sizeof(aes_key));
  156. }
  157. {
  158. crypto_hash_sha512_state state;
  159. uint8_t hash[64];
  160. crypto_hash_sha512_init(&state);
  161. crypto_hash_sha512_update(&state, (const uint8_t *)"Pair-Verify-AES-IV",
  162. 18);
  163. crypto_hash_sha512_update(&state, session->shared_secret, 32);
  164. crypto_hash_sha512_final(&state, hash);
  165. memcpy(aes_iv, hash, sizeof(aes_iv));
  166. }
  167. uint8_t signed_data[64];
  168. memcpy(signed_data, session->session_public_key, 32);
  169. memcpy(signed_data + 32, session->client_public_key, 32);
  170. uint8_t signature[64];
  171. crypto_sign_detached(signature, NULL, signed_data, sizeof(signed_data),
  172. session->device_secret_key);
  173. if (output_capacity < 96) {
  174. ESP_LOGE(TAG, "Output buffer too small for M2 (need 96, have %zu)",
  175. output_capacity);
  176. return ESP_ERR_NO_MEM;
  177. }
  178. memcpy(output, session->session_public_key, 32);
  179. mbedtls_aes_context aes_ctx;
  180. mbedtls_aes_init(&aes_ctx);
  181. mbedtls_aes_setkey_enc(&aes_ctx, aes_key, 128);
  182. uint8_t stream_block[16] = {0};
  183. size_t nc_off = 0;
  184. uint8_t nonce_counter[16];
  185. memcpy(nonce_counter, aes_iv, sizeof(nonce_counter));
  186. mbedtls_aes_crypt_ctr(&aes_ctx, sizeof(signature), &nc_off, nonce_counter,
  187. stream_block, signature, output + 32);
  188. mbedtls_aes_free(&aes_ctx);
  189. *output_len = 96;
  190. session->pair_verify_state = PAIR_VERIFY_STATE_M2;
  191. memcpy(session->encrypt_key, aes_key, sizeof(aes_key));
  192. memcpy(session->decrypt_key, aes_iv, sizeof(aes_iv));
  193. return ESP_OK;
  194. }
  195. esp_err_t hap_pair_verify_m3_raw(hap_session_t *session, const uint8_t *input,
  196. size_t input_len, uint8_t *output,
  197. size_t output_capacity, size_t *output_len) {
  198. (void)output_capacity;
  199. const uint8_t *encrypted_sig;
  200. if (input_len >= 68) {
  201. encrypted_sig = input + 4;
  202. } else if (input_len >= 64) {
  203. encrypted_sig = input;
  204. } else {
  205. ESP_LOGE(TAG, "Input too short for M3: %zu", input_len);
  206. return ESP_ERR_INVALID_ARG;
  207. }
  208. uint8_t aes_key[16];
  209. uint8_t aes_iv[16];
  210. {
  211. crypto_hash_sha512_state state;
  212. uint8_t hash[64];
  213. crypto_hash_sha512_init(&state);
  214. crypto_hash_sha512_update(&state, (const uint8_t *)"Pair-Verify-AES-Key",
  215. 19);
  216. crypto_hash_sha512_update(&state, session->shared_secret, 32);
  217. crypto_hash_sha512_final(&state, hash);
  218. memcpy(aes_key, hash, sizeof(aes_key));
  219. }
  220. {
  221. crypto_hash_sha512_state state;
  222. uint8_t hash[64];
  223. crypto_hash_sha512_init(&state);
  224. crypto_hash_sha512_update(&state, (const uint8_t *)"Pair-Verify-AES-IV",
  225. 18);
  226. crypto_hash_sha512_update(&state, session->shared_secret, 32);
  227. crypto_hash_sha512_final(&state, hash);
  228. memcpy(aes_iv, hash, sizeof(aes_iv));
  229. }
  230. uint8_t client_signature[64];
  231. mbedtls_aes_context aes_ctx;
  232. mbedtls_aes_init(&aes_ctx);
  233. mbedtls_aes_setkey_enc(&aes_ctx, aes_key, 128);
  234. uint8_t stream_block[16] = {0};
  235. size_t nc_off = 0;
  236. uint8_t nonce_counter[16];
  237. memcpy(nonce_counter, aes_iv, sizeof(nonce_counter));
  238. mbedtls_aes_crypt_ctr(&aes_ctx, sizeof(client_signature), &nc_off,
  239. nonce_counter, stream_block, encrypted_sig,
  240. client_signature);
  241. mbedtls_aes_free(&aes_ctx);
  242. ESP_LOGW(TAG, "Skipping signature verification (transient pairing)");
  243. hap_hkdf_sha512((uint8_t *)"Control-Salt", 12, session->shared_secret,
  244. HAP_X25519_KEY_SIZE, (uint8_t *)"Control-Read-Encryption-Key",
  245. 27, session->decrypt_key, 32);
  246. hap_hkdf_sha512((uint8_t *)"Control-Salt", 12, session->shared_secret,
  247. HAP_X25519_KEY_SIZE,
  248. (uint8_t *)"Control-Write-Encryption-Key", 28,
  249. session->encrypt_key, 32);
  250. session->encrypt_nonce = 0;
  251. session->decrypt_nonce = 0;
  252. *output_len = 0;
  253. session->pair_verify_state = PAIR_VERIFY_STATE_M4;
  254. session->session_established = true;
  255. return ESP_OK;
  256. }