diff --git a/esphome/components/bthome_mithermometer/bthome_ble.cpp b/esphome/components/bthome_mithermometer/bthome_ble.cpp index 2b73d8735c7..32278dbfbd4 100644 --- a/esphome/components/bthome_mithermometer/bthome_ble.cpp +++ b/esphome/components/bthome_mithermometer/bthome_ble.cpp @@ -10,7 +10,12 @@ #ifdef USE_ESP32 +#include +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0) +#include +#else #include "mbedtls/ccm.h" +#endif namespace esphome { namespace bthome_mithermometer { @@ -196,6 +201,37 @@ bool BTHomeMiThermometer::decrypt_bthome_payload_(const std::vector &da const uint8_t *ciphertext = data.data() + 1; const uint8_t *mic = data.data() + data.size() - BTHOME_MIC_SIZE; +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0) + // PSA AEAD expects ciphertext + tag concatenated + // BLE advertisement max payload is 31 bytes, so this is always sufficient + static constexpr size_t MAX_CT_WITH_TAG = 32; + uint8_t ct_with_tag[MAX_CT_WITH_TAG]; + size_t ct_with_tag_size = ciphertext_size + BTHOME_MIC_SIZE; + memcpy(ct_with_tag, ciphertext, ciphertext_size); + memcpy(ct_with_tag + ciphertext_size, mic, BTHOME_MIC_SIZE); + + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_set_key_type(&attributes, PSA_KEY_TYPE_AES); + psa_set_key_bits(&attributes, BTHOME_BINDKEY_SIZE * 8); + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DECRYPT); + psa_set_key_algorithm(&attributes, PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, BTHOME_MIC_SIZE)); + + mbedtls_svc_key_id_t key_id; + if (psa_import_key(&attributes, this->bindkey_, BTHOME_BINDKEY_SIZE, &key_id) != PSA_SUCCESS) { + ESP_LOGVV(TAG, "psa_import_key() failed."); + return false; + } + + size_t plaintext_length; + psa_status_t status = psa_aead_decrypt(key_id, PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, BTHOME_MIC_SIZE), + nonce.data(), nonce.size(), nullptr, 0, ct_with_tag, ct_with_tag_size, + payload.data(), ciphertext_size, &plaintext_length); + psa_destroy_key(key_id); + if (status != PSA_SUCCESS || plaintext_length != ciphertext_size) { + ESP_LOGVV(TAG, "BTHome decryption failed."); + return false; + } +#else mbedtls_ccm_context ctx; mbedtls_ccm_init(&ctx); @@ -213,6 +249,7 @@ bool BTHomeMiThermometer::decrypt_bthome_payload_(const std::vector &da ESP_LOGVV(TAG, "BTHome decryption failed (ret=%d).", ret); return false; } +#endif return true; } diff --git a/esphome/components/xiaomi_ble/xiaomi_ble.cpp b/esphome/components/xiaomi_ble/xiaomi_ble.cpp index 97a660f0e3a..2c1611d0c7d 100644 --- a/esphome/components/xiaomi_ble/xiaomi_ble.cpp +++ b/esphome/components/xiaomi_ble/xiaomi_ble.cpp @@ -5,7 +5,12 @@ #ifdef USE_ESP32 #include +#include +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0) +#include +#else #include "mbedtls/ccm.h" +#endif namespace esphome { namespace xiaomi_ble { @@ -314,6 +319,32 @@ bool decrypt_xiaomi_payload(std::vector &raw, const uint8_t *bindkey, c memcpy(vector.iv + 6, v + 2, 3); // sensor type (2) + packet id (1) memcpy(vector.iv + 9, v + raw.size() - 7, 3); // payload counter +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0) + // PSA AEAD expects ciphertext + tag concatenated + uint8_t ct_with_tag[sizeof(vector.ciphertext) + sizeof(vector.tag)]; + memcpy(ct_with_tag, vector.ciphertext, vector.datasize); + memcpy(ct_with_tag + vector.datasize, vector.tag, vector.tagsize); + size_t ct_with_tag_size = vector.datasize + vector.tagsize; + + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_set_key_type(&attributes, PSA_KEY_TYPE_AES); + psa_set_key_bits(&attributes, vector.keysize * 8); + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DECRYPT); + psa_set_key_algorithm(&attributes, PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, vector.tagsize)); + + mbedtls_svc_key_id_t key_id; + if (psa_import_key(&attributes, vector.key, vector.keysize, &key_id) != PSA_SUCCESS) { + ESP_LOGVV(TAG, "decrypt_xiaomi_payload(): psa_import_key() failed."); + return false; + } + + size_t plaintext_length; + psa_status_t status = psa_aead_decrypt(key_id, PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, vector.tagsize), + vector.iv, vector.ivsize, vector.authdata, vector.authsize, ct_with_tag, + ct_with_tag_size, vector.plaintext, vector.datasize, &plaintext_length); + psa_destroy_key(key_id); + bool decrypt_ok = (status == PSA_SUCCESS && plaintext_length == vector.datasize); +#else mbedtls_ccm_context ctx; mbedtls_ccm_init(&ctx); @@ -326,7 +357,11 @@ bool decrypt_xiaomi_payload(std::vector &raw, const uint8_t *bindkey, c ret = mbedtls_ccm_auth_decrypt(&ctx, vector.datasize, vector.iv, vector.ivsize, vector.authdata, vector.authsize, vector.ciphertext, vector.plaintext, vector.tag, vector.tagsize); - if (ret) { + mbedtls_ccm_free(&ctx); + bool decrypt_ok = (ret == 0); +#endif + + if (!decrypt_ok) { uint8_t mac_address[6] = {0}; memcpy(mac_address, mac_reverse + 5, 1); memcpy(mac_address + 1, mac_reverse + 4, 1); @@ -346,7 +381,6 @@ bool decrypt_xiaomi_payload(std::vector &raw, const uint8_t *bindkey, c ESP_LOGVV(TAG, " Iv : %s", format_hex_pretty_to(hex_buf, vector.iv, vector.ivsize)); ESP_LOGVV(TAG, " Cipher : %s", format_hex_pretty_to(hex_buf, vector.ciphertext, vector.datasize)); ESP_LOGVV(TAG, " Tag : %s", format_hex_pretty_to(hex_buf, vector.tag, vector.tagsize)); - mbedtls_ccm_free(&ctx); return false; } @@ -367,7 +401,6 @@ bool decrypt_xiaomi_payload(std::vector &raw, const uint8_t *bindkey, c ESP_LOGVV(TAG, " Plaintext : %s, Packet : %d", format_hex_pretty_to(hex_buf, raw.data() + cipher_pos, vector.datasize), static_cast(raw[4])); - mbedtls_ccm_free(&ctx); return true; }