175 std::vector<uint8_t> &payload)
const {
176 if (data.size() <= 1 + BTHOME_COUNTER_SIZE + BTHOME_MIC_SIZE) {
177 ESP_LOGVV(TAG,
"Encrypted BTHome payload too short: %zu", data.size());
181 const size_t ciphertext_size = data.size() - 1 - BTHOME_COUNTER_SIZE - BTHOME_MIC_SIZE;
182 payload.resize(ciphertext_size);
184 std::array<uint8_t, MAC_ADDRESS_SIZE> mac{};
185 for (
size_t i = 0; i < MAC_ADDRESS_SIZE; i++) {
186 mac[i] = (source_address >> ((MAC_ADDRESS_SIZE - 1 - i) * 8)) & 0xFF;
189 std::array<uint8_t, BTHOME_NONCE_SIZE> nonce{};
190 memcpy(nonce.data(), mac.data(), mac.size());
194 memcpy(nonce.data() + 9, &data[data.size() - BTHOME_COUNTER_SIZE - BTHOME_MIC_SIZE], BTHOME_COUNTER_SIZE);
196 const uint8_t *ciphertext = data.data() + 1;
197 const uint8_t *mic = data.data() + data.size() - BTHOME_MIC_SIZE;
199 mbedtls_ccm_context ctx;
200 mbedtls_ccm_init(&ctx);
202 int ret = mbedtls_ccm_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, this->
bindkey_, BTHOME_BINDKEY_SIZE * 8);
204 ESP_LOGVV(TAG,
"mbedtls_ccm_setkey() failed.");
205 mbedtls_ccm_free(&ctx);
209 ret = mbedtls_ccm_auth_decrypt(&ctx, ciphertext_size, nonce.data(), nonce.size(),
nullptr, 0, ciphertext,
210 payload.data(), mic, BTHOME_MIC_SIZE);
211 mbedtls_ccm_free(&ctx);
213 ESP_LOGVV(TAG,
"BTHome decryption failed (ret=%d).", ret);
225 const auto &data = service_data.
data;
226 if (data.size() < 2) {
227 ESP_LOGVV(TAG,
"BTHome data too short: %zu", data.size());
231 const uint8_t adv_info = data[0];
232 const bool is_encrypted = adv_info & 0x01;
233 const bool mac_included = adv_info & 0x02;
234 const bool is_trigger_based = adv_info & 0x04;
235 const uint8_t version = (adv_info >> 5) & 0x07;
237 if (version != 0x02) {
238 ESP_LOGVV(TAG,
"Unsupported BTHome version %u", version);
243 bool address_matches = source_address == this->
address_;
244 if (!is_encrypted && mac_included && data.size() >= 7) {
245 uint64_t advertised_address = 0;
246 for (
int i = 5; i >= 0; i--) {
247 advertised_address = (advertised_address << 8) | data[1 + i];
249 address_matches = address_matches || advertised_address == this->
address_;
253 if (address_matches) {
254 char addr_buf[MAC_ADDRESS_PRETTY_BUFFER_SIZE];
255 ESP_LOGE(TAG,
"Encrypted BTHome frame received but no bindkey configured for %s",
262 if (address_matches) {
263 char addr_buf[MAC_ADDRESS_PRETTY_BUFFER_SIZE];
264 ESP_LOGE(TAG,
"Unencrypted BTHome frame received with bindkey configured for %s",
269 std::vector<uint8_t> decrypted_payload;
270 const uint8_t *payload =
nullptr;
275 char addr_buf[MAC_ADDRESS_PRETTY_BUFFER_SIZE];
276 ESP_LOGVV(TAG,
"Failed to decrypt BTHome frame from %s", device.
address_str_to(addr_buf));
279 payload = decrypted_payload.data();
282 payload = data.data() + 1;
288 ESP_LOGVV(TAG,
"BTHome payload missing MAC address");
292 for (
int i = 5; i >= 0; i--) {
293 source_address = (source_address << 8) | payload[i];
299 char addr_buf[MAC_ADDRESS_PRETTY_BUFFER_SIZE];
300 if (source_address != this->
address_) {
301 ESP_LOGVV(TAG,
"BTHome frame from unexpected device %s", format_mac_address(addr_buf, source_address));
306 ESP_LOGVV(TAG,
"BTHome payload empty after header");
310 bool reported =
false;
312 uint8_t last_type = 0;
315 const uint8_t obj_type = payload[offset++];
316 size_t value_length = 0;
317 bool has_length_byte = obj_type == 0x53;
319 if (has_length_byte) {
323 value_length = payload[offset++];
325 if (!get_bthome_value_length(obj_type, value_length)) {
326 ESP_LOGVV(TAG,
"Unknown BTHome object 0x%02X", obj_type);
331 if (value_length == 0) {
336 ESP_LOGVV(TAG,
"BTHome object length exceeds payload");
340 const uint8_t *value = &payload[offset];
341 offset += value_length;
343 if (obj_type < last_type) {
344 ESP_LOGVV(TAG,
"BTHome objects not in ascending order");
346 last_type = obj_type;
350 const uint8_t packet_id = value[0];
394 ESP_LOGD(TAG,
"BTHome data%sfrom %s", is_trigger_based ?
" (triggered) " :
" ", device.
address_str_to(addr_buf));