hap_crypto.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. #include <string.h>
  2. #include "hap.h"
  3. #include "hap_internal.h"
  4. #include "esp_log.h"
  5. #include "sodium.h"
  6. static const char *TAG = "hap_crypto";
  7. int hap_hkdf_sha512(const uint8_t *salt, size_t salt_len, const uint8_t *ikm,
  8. size_t ikm_len, const uint8_t *info, size_t info_len,
  9. uint8_t *okm, size_t okm_len) {
  10. uint8_t prk[crypto_auth_hmacsha512_BYTES];
  11. crypto_auth_hmacsha512_state state;
  12. if (salt && salt_len > 0) {
  13. crypto_auth_hmacsha512_init(&state, salt, salt_len);
  14. } else {
  15. uint8_t zero_salt[crypto_auth_hmacsha512_BYTES] = {0};
  16. crypto_auth_hmacsha512_init(&state, zero_salt, sizeof(zero_salt));
  17. }
  18. crypto_auth_hmacsha512_update(&state, ikm, ikm_len);
  19. crypto_auth_hmacsha512_final(&state, prk);
  20. uint8_t t[crypto_auth_hmacsha512_BYTES];
  21. uint8_t counter = 1;
  22. size_t t_len = 0;
  23. size_t pos = 0;
  24. while (pos < okm_len) {
  25. crypto_auth_hmacsha512_init(&state, prk, sizeof(prk));
  26. if (t_len > 0) {
  27. crypto_auth_hmacsha512_update(&state, t, t_len);
  28. }
  29. if (info && info_len > 0) {
  30. crypto_auth_hmacsha512_update(&state, info, info_len);
  31. }
  32. crypto_auth_hmacsha512_update(&state, &counter, 1);
  33. crypto_auth_hmacsha512_final(&state, t);
  34. t_len = crypto_auth_hmacsha512_BYTES;
  35. size_t copy_len = okm_len - pos;
  36. if (copy_len > crypto_auth_hmacsha512_BYTES) {
  37. copy_len = crypto_auth_hmacsha512_BYTES;
  38. }
  39. memcpy(okm + pos, t, copy_len);
  40. pos += copy_len;
  41. counter++;
  42. }
  43. sodium_memzero(prk, sizeof(prk));
  44. sodium_memzero(t, sizeof(t));
  45. return 0;
  46. }
  47. esp_err_t hap_derive_audio_key(hap_session_t *session, uint8_t *audio_key,
  48. size_t key_len) {
  49. if (!session || !audio_key || key_len < 16) {
  50. return ESP_ERR_INVALID_ARG;
  51. }
  52. if (!session->session_established) {
  53. ESP_LOGW(TAG, "Cannot derive audio key before session established");
  54. return ESP_ERR_INVALID_STATE;
  55. }
  56. hap_hkdf_sha512((uint8_t *)"Control-Salt", 12, session->shared_secret, 32,
  57. (uint8_t *)"Control-Read-Encryption-Key", 27, audio_key,
  58. key_len);
  59. return ESP_OK;
  60. }
  61. esp_err_t hap_encrypt(hap_session_t *session, const uint8_t *plaintext,
  62. size_t plaintext_len, uint8_t *ciphertext,
  63. size_t *ciphertext_len) {
  64. if (!session->session_established) {
  65. return ESP_ERR_INVALID_STATE;
  66. }
  67. uint8_t nonce[12] = {0};
  68. memcpy(nonce + 4, &session->encrypt_nonce, 8);
  69. unsigned long long ct_len = 0;
  70. crypto_aead_chacha20poly1305_ietf_encrypt(ciphertext, &ct_len, plaintext,
  71. plaintext_len, NULL, 0, NULL, nonce,
  72. session->encrypt_key);
  73. *ciphertext_len = (size_t)ct_len;
  74. session->encrypt_nonce++;
  75. return ESP_OK;
  76. }
  77. esp_err_t hap_decrypt(hap_session_t *session, const uint8_t *ciphertext,
  78. size_t ciphertext_len, uint8_t *plaintext,
  79. size_t *plaintext_len) {
  80. if (!session->session_established) {
  81. return ESP_ERR_INVALID_STATE;
  82. }
  83. uint8_t nonce[12] = {0};
  84. memcpy(nonce + 4, &session->decrypt_nonce, 8);
  85. unsigned long long pt_len = 0;
  86. if (crypto_aead_chacha20poly1305_ietf_decrypt(
  87. plaintext, &pt_len, NULL, ciphertext, ciphertext_len, NULL, 0, nonce,
  88. session->decrypt_key) != 0) {
  89. return ESP_ERR_INVALID_STATE;
  90. }
  91. *plaintext_len = (size_t)pt_len;
  92. session->decrypt_nonce++;
  93. return ESP_OK;
  94. }