| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117 |
- #include <string.h>
- #include "hap.h"
- #include "hap_internal.h"
- #include "esp_log.h"
- #include "sodium.h"
- static const char *TAG = "hap_crypto";
- int hap_hkdf_sha512(const uint8_t *salt, size_t salt_len, const uint8_t *ikm,
- size_t ikm_len, const uint8_t *info, size_t info_len,
- uint8_t *okm, size_t okm_len) {
- uint8_t prk[crypto_auth_hmacsha512_BYTES];
- crypto_auth_hmacsha512_state state;
- if (salt && salt_len > 0) {
- crypto_auth_hmacsha512_init(&state, salt, salt_len);
- } else {
- uint8_t zero_salt[crypto_auth_hmacsha512_BYTES] = {0};
- crypto_auth_hmacsha512_init(&state, zero_salt, sizeof(zero_salt));
- }
- crypto_auth_hmacsha512_update(&state, ikm, ikm_len);
- crypto_auth_hmacsha512_final(&state, prk);
- uint8_t t[crypto_auth_hmacsha512_BYTES];
- uint8_t counter = 1;
- size_t t_len = 0;
- size_t pos = 0;
- while (pos < okm_len) {
- crypto_auth_hmacsha512_init(&state, prk, sizeof(prk));
- if (t_len > 0) {
- crypto_auth_hmacsha512_update(&state, t, t_len);
- }
- if (info && info_len > 0) {
- crypto_auth_hmacsha512_update(&state, info, info_len);
- }
- crypto_auth_hmacsha512_update(&state, &counter, 1);
- crypto_auth_hmacsha512_final(&state, t);
- t_len = crypto_auth_hmacsha512_BYTES;
- size_t copy_len = okm_len - pos;
- if (copy_len > crypto_auth_hmacsha512_BYTES) {
- copy_len = crypto_auth_hmacsha512_BYTES;
- }
- memcpy(okm + pos, t, copy_len);
- pos += copy_len;
- counter++;
- }
- sodium_memzero(prk, sizeof(prk));
- sodium_memzero(t, sizeof(t));
- return 0;
- }
- esp_err_t hap_derive_audio_key(hap_session_t *session, uint8_t *audio_key,
- size_t key_len) {
- if (!session || !audio_key || key_len < 16) {
- return ESP_ERR_INVALID_ARG;
- }
- if (!session->session_established) {
- ESP_LOGW(TAG, "Cannot derive audio key before session established");
- return ESP_ERR_INVALID_STATE;
- }
- hap_hkdf_sha512((uint8_t *)"Control-Salt", 12, session->shared_secret, 32,
- (uint8_t *)"Control-Read-Encryption-Key", 27, audio_key,
- key_len);
- return ESP_OK;
- }
- esp_err_t hap_encrypt(hap_session_t *session, const uint8_t *plaintext,
- size_t plaintext_len, uint8_t *ciphertext,
- size_t *ciphertext_len) {
- if (!session->session_established) {
- return ESP_ERR_INVALID_STATE;
- }
- uint8_t nonce[12] = {0};
- memcpy(nonce + 4, &session->encrypt_nonce, 8);
- unsigned long long ct_len = 0;
- crypto_aead_chacha20poly1305_ietf_encrypt(ciphertext, &ct_len, plaintext,
- plaintext_len, NULL, 0, NULL, nonce,
- session->encrypt_key);
- *ciphertext_len = (size_t)ct_len;
- session->encrypt_nonce++;
- return ESP_OK;
- }
- esp_err_t hap_decrypt(hap_session_t *session, const uint8_t *ciphertext,
- size_t ciphertext_len, uint8_t *plaintext,
- size_t *plaintext_len) {
- if (!session->session_established) {
- return ESP_ERR_INVALID_STATE;
- }
- uint8_t nonce[12] = {0};
- memcpy(nonce + 4, &session->decrypt_nonce, 8);
- unsigned long long pt_len = 0;
- if (crypto_aead_chacha20poly1305_ietf_decrypt(
- plaintext, &pt_len, NULL, ciphertext, ciphertext_len, NULL, 0, nonce,
- session->decrypt_key) != 0) {
- return ESP_ERR_INVALID_STATE;
- }
- *plaintext_len = (size_t)pt_len;
- session->decrypt_nonce++;
- return ESP_OK;
- }
|