feat(ble/bluedroid): move Encrypted Advertising Data APIs into the host

Provide esp_ble_ead_encrypt/decrypt in Bluedroid and group the GAP Key
Material characteristic under the same EAD Kconfig menu.
This commit is contained in:
zhiweijian
2026-09-08 16:07:44 +08:00
parent b10ae7f167
commit f5e9e2496a
29 changed files with 423 additions and 841 deletions
+1 -1
View File
@@ -53,7 +53,7 @@ endmenu
choice BT_SMP_CRYPTO_STACK
prompt "SMP cryptographic stack"
depends on (BT_BLE_SMP_ENABLE || BT_SMP_ENABLE || BT_NIMBLE_SECURITY_ENABLE || BT_LE_SECURITY_ENABLE || \
BT_CTRL_BREDR_ENABLE)
BT_CTRL_BREDR_ENABLE || BT_BLE_FEAT_ENC_ADV_DATA)
default BT_SMP_CRYPTO_STACK_TINYCRYPT
help
Select the cryptographic library to use for SMP operations (AES, AES-CMAC, ECDH P-256).
@@ -355,6 +355,12 @@ if(CONFIG_BT_BLE_FEAT_CTE_EN)
)
endif()
if(CONFIG_BT_BLE_FEAT_ENC_ADV_DATA)
list(APPEND bluedroid_host_srcs
"${CMAKE_CURRENT_LIST_DIR}/api/esp_ble_ead.c"
)
endif()
if(CONFIG_BT_BLE_PERIPH_PSEUDO_ADDR_BOND)
list(APPEND bluedroid_host_srcs
"${CMAKE_CURRENT_LIST_DIR}/stack/btm/btm_ble_pseudo.c"
+30 -10
View File
@@ -425,16 +425,6 @@ config BT_GATTS_SECURITY_LEVELS_CHAR
help
Enable LE GATT Security Levels Characteristic
config BT_GATTS_KEY_MATERIAL_CHAR
bool "Enable Encrypted Data Key Material Characteristic"
depends on BT_GATTS_ENABLE
default n
help
Enable the Encrypted Data Key Material characteristic in GAP service.
This characteristic allows advertising data to be decrypted and authenticated
using the key material (session key + IV) as defined in Bluetooth Core
Specification Version 5.4. The characteristic requires encrypted link to read.
menuconfig BT_GATTC_ENABLE
bool "Include GATT client module(GATTC)"
depends on BT_BLE_ENABLED
@@ -653,6 +643,36 @@ config BT_BLE_RPA_SUPPORTED
For other BLE chips, devices support network privacy mode and device privacy mode,
users can switch the two modes according to their own needs. So this option is enabled by default.
menu "Encrypted Advertising Data (EAD)"
depends on BT_BLE_ENABLED
config BT_BLE_FEAT_ENC_ADV_DATA
bool "Encrypted Advertising Data APIs"
default n
help
Enable AES-CCM encrypt and decrypt APIs (esp_ble_ead_encrypt /
esp_ble_ead_decrypt) for advertising payloads, as defined in
Bluetooth Core Specification 5.4. Uses the same cryptographic
stack as SMP (TinyCrypt or mbedTLS).
Enable this alone for a scanner/central that decrypts EAD with a
pre-shared key, or when the peer publishes Key Material over GATT.
config BT_GATTS_KEY_MATERIAL_CHAR
bool "Encrypted Data Key Material Characteristic"
depends on BT_GATTS_ENABLE
select BT_BLE_FEAT_ENC_ADV_DATA
default n
help
Expose session key and IV through the GAP Key Material characteristic
(UUID 0x2B88). A central can read it over an encrypted GATT link and
then decrypt advertising data with esp_ble_ead_decrypt().
Selecting this option also enables Encrypted Advertising Data APIs.
Set the published key with esp_ble_gap_set_key_material().
endmenu
menu "Bluedroid debug option"
config BT_BLUEDROID_MEM_DEBUG
bool "Bluedroid memory debug"
@@ -0,0 +1,416 @@
/*
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include <stdint.h>
#include "esp_ble_ead.h"
#include "esp_random.h"
#include "esp_log.h"
#include "sdkconfig.h"
#if (CONFIG_BT_BLE_FEAT_ENC_ADV_DATA)
#define TAG "BLE_EAD"
#if defined(CONFIG_BT_SMP_CRYPTO_STACK_TINYCRYPT)
#include "tinycrypt/aes.h"
#include "tinycrypt/ccm_mode.h"
#include "tinycrypt/constants.h"
#elif defined(CONFIG_BT_SMP_CRYPTO_STACK_MBEDTLS)
#include "psa/crypto.h"
#else
#error "Please select either CONFIG_BT_SMP_CRYPTO_STACK_TINYCRYPT or CONFIG_BT_SMP_CRYPTO_STACK_MBEDTLS"
#endif
/* Additional Authenticated Data for EAD - EA (Encrypted Advertising) */
static const uint8_t ble_ead_aad[ESP_BLE_EAD_AAD_SIZE] = { 0xEA };
/**
* @brief Generate randomizer with direction bit set
*
* Per Bluetooth Core Spec Supplement v11, Part A 1.23.3:
* The MSB of the Randomizer shall be set to indicate direction
*/
static int ble_ead_generate_randomizer(uint8_t randomizer[ESP_BLE_EAD_RANDOMIZER_SIZE])
{
esp_fill_random(randomizer, ESP_BLE_EAD_RANDOMIZER_SIZE);
randomizer[ESP_BLE_EAD_RANDOMIZER_SIZE - 1] |= (1 << ESP_BLE_EAD_RANDOMIZER_DIRECTION_BIT);
return 0;
}
/**
* @brief Generate nonce from IV and randomizer
*
* Nonce = Randomizer (5 bytes) || IV (8 bytes) = 13 bytes
*/
static int ble_ead_generate_nonce(const uint8_t iv[ESP_BLE_EAD_IV_SIZE],
const uint8_t randomizer[ESP_BLE_EAD_RANDOMIZER_SIZE],
uint8_t nonce[ESP_BLE_EAD_NONCE_SIZE])
{
if (iv == NULL || nonce == NULL) {
return -1;
}
if (randomizer != NULL) {
memcpy(nonce, randomizer, ESP_BLE_EAD_RANDOMIZER_SIZE);
} else {
ble_ead_generate_randomizer(nonce);
}
memcpy(nonce + ESP_BLE_EAD_RANDOMIZER_SIZE, iv, ESP_BLE_EAD_IV_SIZE);
return 0;
}
static int ble_aes_ccm_encrypt(const uint8_t *key, const uint8_t *nonce,
const uint8_t *plaintext, size_t plaintext_len,
const uint8_t *aad, size_t aad_len,
uint8_t *ciphertext, size_t tag_len)
{
#if defined(CONFIG_BT_SMP_CRYPTO_STACK_TINYCRYPT)
struct tc_aes_key_sched_struct sched;
struct tc_ccm_mode_struct ccm_state;
int ret;
if (key == NULL || nonce == NULL || ciphertext == NULL) {
ESP_LOGE(TAG, "Invalid input parameters");
return -1;
}
ret = tc_aes128_set_encrypt_key(&sched, key);
if (ret != TC_CRYPTO_SUCCESS) {
ESP_LOGE(TAG, "tc_aes128_set_encrypt_key failed");
memset(&sched, 0, sizeof(sched));
return -1;
}
ret = tc_ccm_config(&ccm_state, &sched, (uint8_t *)nonce, ESP_BLE_EAD_NONCE_SIZE, tag_len);
if (ret != TC_CRYPTO_SUCCESS) {
ESP_LOGE(TAG, "tc_ccm_config failed");
memset(&sched, 0, sizeof(sched));
memset(&ccm_state, 0, sizeof(ccm_state));
return -1;
}
ret = tc_ccm_generation_encryption(ciphertext, plaintext_len + tag_len,
aad, aad_len,
plaintext, plaintext_len,
&ccm_state);
if (ret != TC_CRYPTO_SUCCESS) {
ESP_LOGE(TAG, "tc_ccm_generation_encryption failed");
memset(&sched, 0, sizeof(sched));
memset(&ccm_state, 0, sizeof(ccm_state));
return -1;
}
memset(&sched, 0, sizeof(sched));
memset(&ccm_state, 0, sizeof(ccm_state));
return 0;
#elif defined(CONFIG_BT_SMP_CRYPTO_STACK_MBEDTLS)
psa_status_t status;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_id_t key_id = 0;
psa_algorithm_t alg = PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, tag_len);
size_t output_length = 0;
if (key == NULL || nonce == NULL || ciphertext == NULL) {
ESP_LOGE(TAG, "Invalid input parameters");
return -1;
}
status = psa_crypto_init();
if (status != PSA_SUCCESS) {
ESP_LOGE(TAG, "psa_crypto_init failed: %d", (int)status);
return -1;
}
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT);
psa_set_key_algorithm(&attributes, alg);
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attributes, ESP_BLE_EAD_KEY_SIZE * 8);
status = psa_import_key(&attributes, key, ESP_BLE_EAD_KEY_SIZE, &key_id);
if (status != PSA_SUCCESS) {
ESP_LOGE(TAG, "psa_import_key failed: %d", (int)status);
psa_reset_key_attributes(&attributes);
return -1;
}
psa_reset_key_attributes(&attributes);
status = psa_aead_encrypt(key_id, alg,
nonce, ESP_BLE_EAD_NONCE_SIZE,
aad, aad_len,
plaintext, plaintext_len,
ciphertext, plaintext_len + tag_len,
&output_length);
if (status != PSA_SUCCESS) {
ESP_LOGE(TAG, "psa_aead_encrypt failed: %d", (int)status);
psa_destroy_key(key_id);
return -1;
}
if (output_length != plaintext_len + tag_len) {
ESP_LOGE(TAG, "psa_aead_encrypt output length mismatch: expected %zu, got %zu",
plaintext_len + tag_len, output_length);
psa_destroy_key(key_id);
return -1;
}
psa_destroy_key(key_id);
return 0;
#endif
}
static int ble_aes_ccm_decrypt(const uint8_t *key, const uint8_t *nonce,
const uint8_t *ciphertext, size_t ciphertext_len,
const uint8_t *aad, size_t aad_len,
uint8_t *plaintext, size_t tag_len,
size_t plaintext_capacity)
{
#if defined(CONFIG_BT_SMP_CRYPTO_STACK_TINYCRYPT)
struct tc_aes_key_sched_struct sched;
struct tc_ccm_mode_struct ccm_state;
int ret;
size_t plaintext_len;
if (key == NULL || nonce == NULL || ciphertext == NULL || plaintext == NULL) {
ESP_LOGE(TAG, "Invalid input parameters");
return -1;
}
if (ciphertext_len < tag_len) {
ESP_LOGE(TAG, "ciphertext_len (%zu) < tag_len (%zu)", ciphertext_len, tag_len);
return -1;
}
plaintext_len = ciphertext_len - tag_len;
if (plaintext_len > plaintext_capacity) {
ESP_LOGE(TAG, "plaintext_len (%zu) > plaintext_capacity (%zu)", plaintext_len, plaintext_capacity);
return -1;
}
ret = tc_aes128_set_encrypt_key(&sched, key);
if (ret != TC_CRYPTO_SUCCESS) {
ESP_LOGE(TAG, "tc_aes128_set_encrypt_key failed");
memset(&sched, 0, sizeof(sched));
return -1;
}
ret = tc_ccm_config(&ccm_state, &sched, (uint8_t *)nonce, ESP_BLE_EAD_NONCE_SIZE, tag_len);
if (ret != TC_CRYPTO_SUCCESS) {
ESP_LOGE(TAG, "tc_ccm_config failed");
memset(&sched, 0, sizeof(sched));
memset(&ccm_state, 0, sizeof(ccm_state));
return -1;
}
ret = tc_ccm_decryption_verification(plaintext, plaintext_len,
aad, aad_len,
(uint8_t *)ciphertext, ciphertext_len,
&ccm_state);
if (ret != TC_CRYPTO_SUCCESS) {
ESP_LOGE(TAG, "tc_ccm_decryption_verification failed");
memset(&sched, 0, sizeof(sched));
memset(&ccm_state, 0, sizeof(ccm_state));
return -1;
}
memset(&sched, 0, sizeof(sched));
memset(&ccm_state, 0, sizeof(ccm_state));
return 0;
#elif defined(CONFIG_BT_SMP_CRYPTO_STACK_MBEDTLS)
psa_status_t status;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_id_t key_id = 0;
psa_algorithm_t alg = PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, tag_len);
size_t output_length = 0;
size_t plaintext_len;
if (key == NULL || nonce == NULL || ciphertext == NULL || plaintext == NULL) {
ESP_LOGE(TAG, "Invalid input parameters");
return -1;
}
if (ciphertext_len < tag_len) {
ESP_LOGE(TAG, "ciphertext_len (%zu) < tag_len (%zu)", ciphertext_len, tag_len);
return -1;
}
plaintext_len = ciphertext_len - tag_len;
if (plaintext_len > plaintext_capacity) {
ESP_LOGE(TAG, "plaintext_len (%zu) > plaintext_capacity (%zu)", plaintext_len, plaintext_capacity);
return -1;
}
status = psa_crypto_init();
if (status != PSA_SUCCESS) {
ESP_LOGE(TAG, "psa_crypto_init failed: %d", (int)status);
return -1;
}
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DECRYPT);
psa_set_key_algorithm(&attributes, alg);
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attributes, ESP_BLE_EAD_KEY_SIZE * 8);
status = psa_import_key(&attributes, key, ESP_BLE_EAD_KEY_SIZE, &key_id);
if (status != PSA_SUCCESS) {
ESP_LOGE(TAG, "psa_import_key failed: %d", (int)status);
psa_reset_key_attributes(&attributes);
return -1;
}
psa_reset_key_attributes(&attributes);
status = psa_aead_decrypt(key_id, alg,
nonce, ESP_BLE_EAD_NONCE_SIZE,
aad, aad_len,
ciphertext, ciphertext_len,
plaintext, plaintext_len,
&output_length);
if (status != PSA_SUCCESS) {
ESP_LOGE(TAG, "psa_aead_decrypt failed: %d", (int)status);
psa_destroy_key(key_id);
return -1;
}
if (output_length != plaintext_len) {
ESP_LOGE(TAG, "psa_aead_decrypt output length mismatch: expected %zu, got %zu",
plaintext_len, output_length);
psa_destroy_key(key_id);
return -1;
}
psa_destroy_key(key_id);
return 0;
#endif
}
esp_err_t esp_ble_ead_encrypt(const uint8_t session_key[ESP_BLE_EAD_KEY_SIZE],
const uint8_t iv[ESP_BLE_EAD_IV_SIZE],
const uint8_t *payload, size_t payload_size,
uint8_t *encrypted_payload)
{
int ret;
uint8_t nonce[ESP_BLE_EAD_NONCE_SIZE];
if (session_key == NULL) {
ESP_LOGE(TAG, "session_key is NULL");
return ESP_ERR_INVALID_ARG;
}
if (iv == NULL) {
ESP_LOGE(TAG, "iv is NULL");
return ESP_ERR_INVALID_ARG;
}
if (payload == NULL && payload_size > 0) {
ESP_LOGE(TAG, "payload is NULL but payload_size > 0");
return ESP_ERR_INVALID_ARG;
}
if (encrypted_payload == NULL) {
ESP_LOGE(TAG, "encrypted_payload is NULL");
return ESP_ERR_INVALID_ARG;
}
/* CSS Part A 1.23.2: plaintext shall consist of one or more AD structures */
if (payload_size == 0) {
ESP_LOGE(TAG, "payload_size is 0");
return ESP_ERR_INVALID_ARG;
}
if (payload_size > SIZE_MAX - (ESP_BLE_EAD_RANDOMIZER_SIZE + ESP_BLE_EAD_MIC_SIZE)) {
ESP_LOGE(TAG, "payload_size too large");
return ESP_ERR_INVALID_ARG;
}
ret = ble_ead_generate_nonce(iv, NULL, nonce);
if (ret != 0) {
return ESP_ERR_INVALID_ARG;
}
memcpy(encrypted_payload, nonce, ESP_BLE_EAD_RANDOMIZER_SIZE);
ret = ble_aes_ccm_encrypt(session_key, nonce,
payload, payload_size,
ble_ead_aad, ESP_BLE_EAD_AAD_SIZE,
&encrypted_payload[ESP_BLE_EAD_RANDOMIZER_SIZE],
ESP_BLE_EAD_MIC_SIZE);
if (ret != 0) {
return ESP_FAIL;
}
return ESP_OK;
}
esp_err_t esp_ble_ead_decrypt(const uint8_t session_key[ESP_BLE_EAD_KEY_SIZE],
const uint8_t iv[ESP_BLE_EAD_IV_SIZE],
const uint8_t *encrypted_payload, size_t encrypted_payload_size,
uint8_t *payload, size_t payload_capacity)
{
int ret;
uint8_t nonce[ESP_BLE_EAD_NONCE_SIZE];
const uint8_t *randomizer;
const uint8_t *ciphertext;
size_t ciphertext_len;
size_t expected_plaintext_len;
if (session_key == NULL) {
ESP_LOGE(TAG, "session_key is NULL");
return ESP_ERR_INVALID_ARG;
}
if (iv == NULL) {
ESP_LOGE(TAG, "iv is NULL");
return ESP_ERR_INVALID_ARG;
}
if (encrypted_payload == NULL) {
ESP_LOGE(TAG, "encrypted_payload is NULL");
return ESP_ERR_INVALID_ARG;
}
if (payload == NULL) {
ESP_LOGE(TAG, "payload is NULL");
return ESP_ERR_INVALID_ARG;
}
/* Randomizer + MIC + at least 1 byte of AD structure */
if (encrypted_payload_size < ESP_BLE_EAD_RANDOMIZER_SIZE + ESP_BLE_EAD_MIC_SIZE + 1) {
ESP_LOGE(TAG, "encrypted_payload_size too small");
return ESP_ERR_INVALID_ARG;
}
expected_plaintext_len = ESP_BLE_EAD_DECRYPTED_PAYLOAD_SIZE(encrypted_payload_size);
if (expected_plaintext_len > payload_capacity) {
ESP_LOGE(TAG, "EAD plaintext length %zu exceeds payload buffer %zu",
expected_plaintext_len, payload_capacity);
return ESP_ERR_INVALID_ARG;
}
randomizer = encrypted_payload;
ciphertext = &encrypted_payload[ESP_BLE_EAD_RANDOMIZER_SIZE];
ciphertext_len = encrypted_payload_size - ESP_BLE_EAD_RANDOMIZER_SIZE;
ret = ble_ead_generate_nonce(iv, randomizer, nonce);
if (ret != 0) {
return ESP_ERR_INVALID_ARG;
}
ret = ble_aes_ccm_decrypt(session_key, nonce,
ciphertext, ciphertext_len,
ble_ead_aad, ESP_BLE_EAD_AAD_SIZE,
payload, ESP_BLE_EAD_MIC_SIZE,
payload_capacity);
if (ret != 0) {
return ESP_FAIL;
}
return ESP_OK;
}
#endif /* CONFIG_BT_BLE_FEAT_ENC_ADV_DATA */
@@ -0,0 +1,122 @@
/*
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __ESP_BLE_EAD_H__
#define __ESP_BLE_EAD_H__
#include <stdint.h>
#include <stddef.h>
#include "esp_err.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief BLE Encrypted Advertising Data (EAD)
*
* Based on Bluetooth Core Specification Version 5.4 and Core Specification
* Supplement v11, Part A 1.23.
*
* Enable CONFIG_BT_BLE_FEAT_ENC_ADV_DATA to compile the encrypt/decrypt APIs.
* A GATT server that publishes the session key should also enable
* CONFIG_BT_GATTS_KEY_MATERIAL_CHAR and call esp_ble_gap_set_key_material().
*/
#define ESP_BLE_EAD_KEY_SIZE 16 /*!< 128-bit session key */
#define ESP_BLE_EAD_IV_SIZE 8 /*!< 64-bit Initialization Vector */
#define ESP_BLE_EAD_RANDOMIZER_SIZE 5 /*!< 40-bit Randomizer */
#define ESP_BLE_EAD_MIC_SIZE 4 /*!< 32-bit Message Integrity Check */
#define ESP_BLE_EAD_NONCE_SIZE 13 /*!< 104-bit Nonce (Randomizer + IV) */
#define ESP_BLE_EAD_AAD_SIZE 1 /*!< Additional Authenticated Data size */
/**
* Direction bit position in Randomizer (MSB of last byte).
* Per Bluetooth Core Spec Supplement v11, Part A 1.23.3.
*/
#define ESP_BLE_EAD_RANDOMIZER_DIRECTION_BIT 7
/**
* @brief Calculate encrypted payload size from plaintext size
*
* Encrypted payload layout: Randomizer || Ciphertext || MIC
*/
#define ESP_BLE_EAD_ENCRYPTED_PAYLOAD_SIZE(payload_size) \
(ESP_BLE_EAD_RANDOMIZER_SIZE + (payload_size) + ESP_BLE_EAD_MIC_SIZE)
/**
* @brief Calculate decrypted payload size from encrypted payload size
*/
#define ESP_BLE_EAD_DECRYPTED_PAYLOAD_SIZE(encrypted_size) \
((encrypted_size) - ESP_BLE_EAD_RANDOMIZER_SIZE - ESP_BLE_EAD_MIC_SIZE)
/**
* @brief Key material structure for EAD
*/
typedef struct {
uint8_t session_key[ESP_BLE_EAD_KEY_SIZE]; /*!< 128-bit session key */
uint8_t iv[ESP_BLE_EAD_IV_SIZE]; /*!< 64-bit Initialization Vector */
} esp_ble_ead_key_material_t;
/**
* @brief Encrypt advertising data using AES-CCM
*
* The resulting data in @p encrypted_payload has the following layout:
* - Randomizer in the first ESP_BLE_EAD_RANDOMIZER_SIZE bytes
* - Encrypted payload of @p payload_size bytes
* - MIC in the last ESP_BLE_EAD_MIC_SIZE bytes
*
* The function must be called each time the RPA is updated or the advertising
* data are modified. @p payload may contain one or more concatenated advertising
* structures (length + type + data).
*
* @param[in] session_key 16-byte session key
* @param[in] iv 8-byte Initialization Vector. Must be changed
* each time the session key changes
* @param[in] payload Plaintext advertising data to encrypt
* @param[in] payload_size Size of plaintext data. Must be greater than 0
* @param[out] encrypted_payload Output buffer for encrypted data.
* Size must be at least ESP_BLE_EAD_ENCRYPTED_PAYLOAD_SIZE(payload_size)
*
* @return
* - ESP_OK: success
* - ESP_ERR_INVALID_ARG: invalid argument
* - ESP_FAIL: encryption failed
*/
esp_err_t esp_ble_ead_encrypt(const uint8_t session_key[ESP_BLE_EAD_KEY_SIZE],
const uint8_t iv[ESP_BLE_EAD_IV_SIZE],
const uint8_t *payload, size_t payload_size,
uint8_t *encrypted_payload);
/**
* @brief Decrypt advertising data using AES-CCM
*
* @param[in] session_key 16-byte session key
* @param[in] iv 8-byte Initialization Vector
* @param[in] encrypted_payload Encrypted advertising data (includes randomizer and MIC).
* This should only contain the advertising data from the
* received advertising structure, neither the length nor the type
* @param[in] encrypted_payload_size Size of encrypted data
* @param[out] payload Output buffer for decrypted data.
* Use ESP_BLE_EAD_DECRYPTED_PAYLOAD_SIZE to get the right size
* @param[in] payload_capacity Size of @p payload in bytes; must be >=
* ESP_BLE_EAD_DECRYPTED_PAYLOAD_SIZE(encrypted_payload_size)
*
* @return
* - ESP_OK: success
* - ESP_ERR_INVALID_ARG: invalid argument
* - ESP_FAIL: decryption or authentication failed
*/
esp_err_t esp_ble_ead_decrypt(const uint8_t session_key[ESP_BLE_EAD_KEY_SIZE],
const uint8_t iv[ESP_BLE_EAD_IV_SIZE],
const uint8_t *encrypted_payload, size_t encrypted_payload_size,
uint8_t *payload, size_t payload_capacity);
#ifdef __cplusplus
}
#endif
#endif /* __ESP_BLE_EAD_H__ */
@@ -364,6 +364,7 @@ typedef enum {
ESP_BLE_AD_TYPE_TRANS_DISC_DATA = 0x26, /* relate to BTM_BLE_AD_TYPE_TRANS_DISC_DATA in stack/btm_ble_api.h */
ESP_BLE_AD_TYPE_LE_SUPPORT_FEATURE = 0x27, /* relate to BTM_BLE_AD_TYPE_LE_SUPPORT_FEATURE in stack/btm_ble_api.h */
ESP_BLE_AD_TYPE_CHAN_MAP_UPDATE = 0x28, /* relate to BTM_BLE_AD_TYPE_CHAN_MAP_UPDATE in stack/btm_ble_api.h */
ESP_BLE_AD_TYPE_ENC_ADV_DATA = 0x31, /* relate to BTM_BLE_AD_TYPE_ENC_ADV_DATA in stack/btm_ble_api.h */
ESP_BLE_AD_MANUFACTURER_SPECIFIC_TYPE = 0xFF, /* relate to BTM_BLE_AD_MANUFACTURER_SPECIFIC_TYPE in stack/btm_ble_api.h */
} esp_ble_adv_data_type;
@@ -3584,7 +3585,10 @@ esp_err_t esp_ble_gap_get_device_name(void);
*
* This function sets the session key and IV that will be exposed
* through the Key Material characteristic (UUID 0x2B88) in the GAP service.
* The Key Material allows central devices to decrypt encrypted advertising data.
* A central can read the characteristic over an encrypted GATT link and
* decrypt Encrypted Advertising Data with esp_ble_ead_decrypt().
* Enabling this API also requires CONFIG_BT_GATTS_KEY_MATERIAL_CHAR,
* which selects CONFIG_BT_BLE_FEAT_ENC_ADV_DATA.
*
* @param[in] session_key - 16-byte (128-bit) session key for AES-CCM encryption
* @param[in] iv - 8-byte (64-bit) initialization vector
@@ -3593,6 +3597,7 @@ esp_err_t esp_ble_gap_get_device_name(void);
* - ESP_OK : success
* - other : failed
*
* @see esp_ble_ead_encrypt, esp_ble_ead_decrypt
*/
esp_err_t esp_ble_gap_set_key_material(const uint8_t session_key[16], const uint8_t iv[8]);
#endif // CONFIG_BT_GATTS_KEY_MATERIAL_CHAR
@@ -359,6 +359,7 @@ typedef UINT32 tBTM_BLE_AD_MASK;
#define BTM_BLE_AD_TYPE_TRANS_DISC_DATA 0x26
#define BTM_BLE_AD_TYPE_LE_SUPPORT_FEATURE 0x27
#define BTM_BLE_AD_TYPE_CHAN_MAP_UPDATE 0x28
#define BTM_BLE_AD_TYPE_ENC_ADV_DATA 0x31
#define BTM_BLE_AD_TYPE_MANU HCI_EIR_MANUFACTURER_SPECIFIC_TYPE /* 0xff */
typedef UINT8 tBTM_BLE_AD_TYPE;