mirror of
https://github.com/espressif/esp-nimble.git
synced 2026-06-05 21:04:49 +00:00
NimBLE: Added support of encrypted advertising data
This commit is contained in:
committed by
Abhinav Kudnar
parent
4f635e7331
commit
066bfccb8b
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
|
||||
#ifndef _BLE_AES_CCM_
|
||||
#define _BLE_AES_CCM_
|
||||
|
||||
#include "syscfg/syscfg.h"
|
||||
#include "os/queue.h"
|
||||
#include "host/ble_hs.h"
|
||||
|
||||
#if MYNEWT_VAL(BLE_CRYPTO_STACK_MBEDTLS)
|
||||
#include "mbedtls/aes.h"
|
||||
#else
|
||||
#include "tinycrypt/aes.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(ENC_ADV_DATA)
|
||||
|
||||
const char *ble_aes_ccm_hex(const void *buf, size_t len);
|
||||
int ble_aes_ccm_encrypt_be(const uint8_t *key, const uint8_t *plaintext, uint8_t *enc_data);
|
||||
int ble_aes_ccm_decrypt(const uint8_t key[16], uint8_t nonce[13], const uint8_t *enc_data,
|
||||
size_t len, const uint8_t *aad, size_t aad_len,
|
||||
uint8_t *plaintext, size_t mic_size);
|
||||
int ble_aes_ccm_encrypt(const uint8_t key[16], uint8_t nonce[13], const uint8_t *enc_data,
|
||||
size_t len, const uint8_t *aad, size_t aad_len,
|
||||
uint8_t *plaintext, size_t mic_size);
|
||||
|
||||
#endif /* ENC_ADV_DATA */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _BLE_AES_CCM_ */
|
||||
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
|
||||
#ifndef H_BLE_EAD_
|
||||
#define H_BLE_EAD_
|
||||
|
||||
#include "os/queue.h"
|
||||
#include <inttypes.h>
|
||||
#include "syscfg/syscfg.h"
|
||||
#include "host/ble_gap.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(ENC_ADV_DATA)
|
||||
|
||||
/** Randomizer size in bytes */
|
||||
#define BLE_EAD_RANDOMIZER_SIZE 5
|
||||
|
||||
/** Key size in bytes */
|
||||
#define BLE_EAD_KEY_SIZE 16
|
||||
|
||||
/** Initialisation Vector size in bytes */
|
||||
#define BLE_EAD_IV_SIZE 8
|
||||
|
||||
/** MIC size in bytes */
|
||||
#define BLE_EAD_MIC_SIZE 4
|
||||
|
||||
/** nonce size in bytes */
|
||||
#define BLE_EAD_NONCE_SIZE 13
|
||||
|
||||
/* This value is used to set the directionBit of the CCM nonce to the MSB of the Randomizer field
|
||||
* (see Supplement to the Bluetooth Core Specification v11, Part A 1.23.3)
|
||||
*/
|
||||
#define BLE_EAD_RANDOMIZER_DIRECTION_BIT 7
|
||||
|
||||
/** Additional Authenticated Data size in bytes */
|
||||
#define BLE_EAD_AAD_SIZE 1
|
||||
|
||||
|
||||
/** Get the size (in bytes) of the encrypted advertising data for a given
|
||||
* payload size in bytes.
|
||||
*/
|
||||
#define BLE_EAD_ENCRYPTED_PAYLOAD_SIZE(payload_size) \
|
||||
((payload_size) + BLE_EAD_RANDOMIZER_SIZE + BLE_EAD_MIC_SIZE)
|
||||
|
||||
/** Get the size (in bytes) of the decrypted payload for a given payload size in
|
||||
* bytes.
|
||||
*/
|
||||
#define BLE_EAD_DECRYPTED_PAYLOAD_SIZE(encrypted_payload_size) \
|
||||
((encrypted_payload_size) - (BLE_EAD_RANDOMIZER_SIZE + BLE_EAD_MIC_SIZE))
|
||||
|
||||
struct key_material {
|
||||
uint8_t session_key[BLE_EAD_KEY_SIZE];
|
||||
uint8_t iv[BLE_EAD_IV_SIZE];
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Encrypt and authenticate the given advertising data.
|
||||
*
|
||||
* The resulting data in @p encrypted_payload will look like that:
|
||||
* - Randomizer is added in the @ref BLE_EAD_RANDOMIZER_SIZE first bytes;
|
||||
* - Encrypted payload is added ( @p payload_size bytes);
|
||||
* - MIC is added in the last @ref BLE_EAD_MIC_SIZE bytes.
|
||||
*
|
||||
* NOTE:
|
||||
* - The function must be called each time the RPA is updated or the
|
||||
* data are modified.
|
||||
*
|
||||
* - The term `advertising structure` is used to describe the advertising
|
||||
* data with the advertising type and the length of those two.
|
||||
*
|
||||
* @session_key key of BLE_EAD_KEY_SIZE bytes used for the
|
||||
* encryption.
|
||||
* @iv Initialisation Vector used to generate the nonce. It must be
|
||||
* changed each time the Session Key changes.
|
||||
* @payload Advertising Data to encrypt. Can be multiple advertising
|
||||
* structures that are concatenated.
|
||||
* @payload_size Size of the Advertising Data to encrypt.
|
||||
* @encrypted_payload Encrypted Ad Data including the Randomizer and
|
||||
* the MIC. Size must be at least @ref BLE_EAD_RANDOMIZER_SIZE + @p
|
||||
* payload_size + @ref BLE_EAD_MIC_SIZE. Use @ref
|
||||
* BLE_EAD_ENCRYPTED_PAYLOAD_SIZE to get the right size.
|
||||
*
|
||||
* @return 0 on success;
|
||||
* BLE_HS_EINVAL if the specified value is not
|
||||
* within the allowed range.
|
||||
* BLE_HS_ECANCEL if error occurred during the random number
|
||||
* generation
|
||||
*/
|
||||
int ble_ead_encrypt(const uint8_t session_key[BLE_EAD_KEY_SIZE],
|
||||
const uint8_t iv[BLE_EAD_IV_SIZE], const uint8_t *payload,
|
||||
size_t payload_size, uint8_t *encrypted_payload);
|
||||
|
||||
/**
|
||||
* @brief Decrypt and authenticate the given encrypted advertising data.
|
||||
*
|
||||
* @note The term `advertising structure` is used to describe the advertising
|
||||
* data with the advertising type and the length of those two.
|
||||
*
|
||||
* @session_key Key of 16 bytes used for the encryption.
|
||||
* @iv Initialisation Vector used to generate the `nonce`.
|
||||
* @encrypted_payload Encrypted Advertising Data received. This
|
||||
* should only contain the advertising data from the received
|
||||
* advertising structure, not the length nor the type.
|
||||
* @encrypted_payload_size Size of the received advertising data in
|
||||
* bytes. Should be equal to the length field of the received
|
||||
* advertising structure, minus the size of the type (1 byte).
|
||||
* @payload Decrypted advertising payload. Use @ref
|
||||
* BLE_EAD_DECRYPTED_PAYLOAD_SIZE to get the right size.
|
||||
*
|
||||
* @return 0 on success;
|
||||
* BLE_HS_EINVAL if the specified value is not
|
||||
* within the allowed range.
|
||||
*/
|
||||
int ble_ead_decrypt(const uint8_t session_key[BLE_EAD_KEY_SIZE],
|
||||
const uint8_t iv[BLE_EAD_IV_SIZE], const uint8_t *encrypted_payload,
|
||||
size_t encrypted_payload_size, uint8_t *payload);
|
||||
|
||||
int ble_ead_serialize_data(const struct enc_adv_data *input, uint8_t *output);
|
||||
|
||||
#endif /* ENC_ADV_DATA */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -33,6 +33,10 @@
|
||||
#include "syscfg/syscfg.h"
|
||||
#include "host/ble_esp_gap.h"
|
||||
|
||||
#if MYNEWT_VAL(ENC_ADV_DATA)
|
||||
#include "../../src/ble_hs_hci_priv.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -1358,6 +1362,44 @@ int ble_gap_adv_set_fields(const struct ble_hs_adv_fields *rsp_fields);
|
||||
*/
|
||||
int ble_gap_adv_rsp_set_fields(const struct ble_hs_adv_fields *rsp_fields);
|
||||
|
||||
#if MYNEWT_VAL(ENC_ADV_DATA)
|
||||
/**
|
||||
* @brief Bluetooth data serialized size.
|
||||
*
|
||||
* Get the size of a serialized @ref bt_data given its data length.
|
||||
*
|
||||
* Size of 'AD Structure'->'Length' field, equal to 1.
|
||||
* Size of 'AD Structure'->'Data'->'AD Type' field, equal to 1.
|
||||
* Size of 'AD Structure'->'Data'->'AD Data' field, equal to data_len.
|
||||
*
|
||||
* See Core Specification Version 5.4 Vol. 3 Part C, 11, Figure 11.1.
|
||||
*/
|
||||
#define BLE_GAP_DATA_SERIALIZED_SIZE(data_len) ((data_len) + 2)
|
||||
#define BLE_GAP_ENC_ADV_DATA 0x31
|
||||
struct enc_adv_data {
|
||||
uint8_t len;
|
||||
uint8_t type;
|
||||
uint8_t *data;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Helper to declare elements of enc_adv_data arrays
|
||||
*
|
||||
* This macro is mainly for creating an array of struct enc_adv_data
|
||||
* elements which is then passed to e.g. @ref ble_gap_adv_start().
|
||||
*
|
||||
* @param _type Type of advertising data field
|
||||
* @param _data Pointer to the data field payload
|
||||
* @param _data_len Number of bytes behind the _data pointer
|
||||
*/
|
||||
#define ENC_ADV_DATA(_type, _data, _data_len) \
|
||||
{ \
|
||||
.type = (_type), \
|
||||
.len = (_data_len), \
|
||||
.data = (uint8_t *)(_data), \
|
||||
}
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(BLE_EXT_ADV)
|
||||
/** @brief Extended advertising parameters */
|
||||
struct ble_gap_ext_adv_params {
|
||||
|
||||
@@ -32,6 +32,10 @@ extern "C" {
|
||||
#define BLE_STORE_OBJ_TYPE_CCCD 3
|
||||
#define BLE_STORE_OBJ_TYPE_PEER_DEV_REC 4
|
||||
|
||||
#if MYNEWT_VAL(ENC_ADV_DATA)
|
||||
#define BLE_STORE_OBJ_TYPE_ENC_ADV_DATA 5
|
||||
#endif
|
||||
|
||||
/** Failed to persist record; insufficient storage capacity. */
|
||||
#define BLE_STORE_EVENT_OVERFLOW 1
|
||||
|
||||
@@ -113,6 +117,33 @@ struct ble_store_value_cccd {
|
||||
unsigned value_changed:1;
|
||||
};
|
||||
|
||||
#if MYNEWT_VAL(ENC_ADV_DATA)
|
||||
/**
|
||||
* Used as a key for lookups of encrypted advertising data. This struct corresponds
|
||||
* to the BLE_STORE_OBJ_TYPE_ENC_ADV_DATA store object type.
|
||||
*/
|
||||
struct ble_store_key_ead {
|
||||
/**
|
||||
* Key by peer identity address;
|
||||
* peer_addr=BLE_ADDR_NONE means don't key off peer.
|
||||
*/
|
||||
ble_addr_t peer_addr;
|
||||
|
||||
/** Number of results to skip; 0 means retrieve the first match. */
|
||||
uint8_t idx;
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents a stored encrypted advertising data. This struct corresponds
|
||||
* to the BLE_STORE_OBJ_TYPE_ENC_ADV_DATA store object type.
|
||||
*/
|
||||
struct ble_store_value_ead {
|
||||
ble_addr_t peer_addr;
|
||||
unsigned km_present:1;
|
||||
struct key_material *km;
|
||||
};
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Used as a key for store lookups. This union must be accompanied by an
|
||||
* object type code to indicate which field is valid.
|
||||
@@ -120,6 +151,9 @@ struct ble_store_value_cccd {
|
||||
union ble_store_key {
|
||||
struct ble_store_key_sec sec;
|
||||
struct ble_store_key_cccd cccd;
|
||||
#if MYNEWT_VAL(ENC_ADV_DATA)
|
||||
struct ble_store_key_ead ead;
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -129,6 +163,9 @@ union ble_store_key {
|
||||
union ble_store_value {
|
||||
struct ble_store_value_sec sec;
|
||||
struct ble_store_value_cccd cccd;
|
||||
#if MYNEWT_VAL(ENC_ADV_DATA)
|
||||
struct ble_store_value_ead ead;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct ble_store_status_event {
|
||||
@@ -299,6 +336,14 @@ void ble_store_key_from_value_sec(struct ble_store_key_sec *out_key,
|
||||
const struct ble_store_value_sec *value);
|
||||
void ble_store_key_from_value_cccd(struct ble_store_key_cccd *out_key,
|
||||
const struct ble_store_value_cccd *value);
|
||||
#if MYNEWT_VAL(ENC_ADV_DATA)
|
||||
int ble_store_read_ead(const struct ble_store_key_ead *key,
|
||||
struct ble_store_value_ead *out_value);
|
||||
int ble_store_write_ead(const struct ble_store_value_ead *value);
|
||||
int ble_store_delete_ead(const struct ble_store_key_ead *key);
|
||||
void ble_store_key_from_value_ead(struct ble_store_key_ead *out_key,
|
||||
const struct ble_store_value_ead *value);
|
||||
#endif
|
||||
|
||||
void ble_store_key_from_value(int obj_type,
|
||||
union ble_store_key *out_key,
|
||||
|
||||
@@ -21,7 +21,9 @@
|
||||
#define H_BLE_SVC_GAP_
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#if MYNEWT_VAL(ENC_ADV_DATA)
|
||||
#include "host/ble_ead.h"
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -32,6 +34,10 @@ extern "C" {
|
||||
#define BLE_SVC_GAP_CHR_UUID16_PERIPH_PREF_CONN_PARAMS 0x2a04
|
||||
#define BLE_SVC_GAP_CHR_UUID16_CENTRAL_ADDRESS_RESOLUTION 0x2aa6
|
||||
|
||||
#if MYNEWT_VAL(ENC_ADV_DATA)
|
||||
#define BLE_SVC_GAP_CHR_UUID16_KEY_MATERIAL 0x2B88
|
||||
#endif
|
||||
|
||||
#define BLE_SVC_GAP_APPEARANCE_GEN_UNKNOWN 0
|
||||
#define BLE_SVC_GAP_APPEARANCE_GEN_COMPUTER 128
|
||||
#define BLE_SVC_GAP_APPEARANCE_GEN_HID 960
|
||||
@@ -45,6 +51,9 @@ const char *ble_svc_gap_device_name(void);
|
||||
int ble_svc_gap_device_name_set(const char *name);
|
||||
uint16_t ble_svc_gap_device_appearance(void);
|
||||
int ble_svc_gap_device_appearance_set(uint16_t appearance);
|
||||
#if MYNEWT_VAL(ENC_ADV_DATA)
|
||||
int ble_svc_gap_device_key_material_set(uint8_t *session_key, uint8_t *iv);
|
||||
#endif
|
||||
|
||||
void ble_svc_gap_init(void);
|
||||
|
||||
|
||||
@@ -41,6 +41,13 @@ static char ble_svc_gap_name[BLE_SVC_GAP_NAME_MAX_LEN + 1] =
|
||||
MYNEWT_VAL(BLE_SVC_GAP_DEVICE_NAME);
|
||||
static uint16_t ble_svc_gap_appearance = MYNEWT_VAL(BLE_SVC_GAP_APPEARANCE);
|
||||
|
||||
#if MYNEWT_VAL(ENC_ADV_DATA)
|
||||
static struct key_material km = {
|
||||
.session_key = {0},
|
||||
.iv = {0},
|
||||
};
|
||||
#endif
|
||||
|
||||
#if NIMBLE_BLE_CONNECT
|
||||
static int
|
||||
ble_svc_gap_access(uint16_t conn_handle, uint16_t attr_handle,
|
||||
@@ -86,6 +93,12 @@ static const struct ble_gatt_svc_def ble_svc_gap_defs[] = {
|
||||
.access_cb = ble_svc_gap_access,
|
||||
.flags = BLE_GATT_CHR_F_READ,
|
||||
}, {
|
||||
#endif
|
||||
#if MYNEWT_VAL(ENC_ADV_DATA)
|
||||
.uuid = BLE_UUID16_DECLARE(BLE_SVC_GAP_CHR_UUID16_KEY_MATERIAL),
|
||||
.access_cb = ble_svc_gap_access,
|
||||
.flags = BLE_GATT_CHR_F_READ,
|
||||
}, {
|
||||
#endif
|
||||
0, /* No more characteristics in this service. */
|
||||
} },
|
||||
@@ -235,6 +248,14 @@ ble_svc_gap_access(uint16_t conn_handle, uint16_t attr_handle,
|
||||
return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(ENC_ADV_DATA)
|
||||
case BLE_SVC_GAP_CHR_UUID16_KEY_MATERIAL:
|
||||
rc = os_mbuf_append(ctxt->om, &(km.session_key), sizeof(km.session_key));
|
||||
rc = os_mbuf_append(ctxt->om, &(km.iv), sizeof(km.iv));
|
||||
|
||||
return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
|
||||
#endif
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
return BLE_ATT_ERR_UNLIKELY;
|
||||
@@ -284,6 +305,16 @@ ble_svc_gap_set_chr_changed_cb(ble_svc_gap_chr_changed_fn *cb)
|
||||
ble_svc_gap_chr_changed_cb_fn = cb;
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(ENC_ADV_DATA)
|
||||
int
|
||||
ble_svc_gap_device_key_material_set(uint8_t *session_key, uint8_t *iv)
|
||||
{
|
||||
memcpy(&km.session_key, session_key, BLE_EAD_KEY_SIZE);
|
||||
memcpy(&km.iv, iv, BLE_EAD_IV_SIZE);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
ble_svc_gap_init(void)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,307 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stddef.h>
|
||||
#include "host/ble_aes_ccm.h"
|
||||
#include "../src/ble_hs_conn_priv.h"
|
||||
|
||||
#if MYNEWT_VAL(ENC_ADV_DATA)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef min
|
||||
#define min(a, b) ((a) < (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#ifndef max
|
||||
#define max(a, b) ((a) > (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#define sys_put_be16(a,b) put_be16(b, a)
|
||||
|
||||
const char *
|
||||
ble_aes_ccm_hex(const void *buf, size_t len)
|
||||
{
|
||||
static const char hex[] = "0123456789abcdef";
|
||||
static char hexbufs[4][137];
|
||||
static uint8_t curbuf;
|
||||
const uint8_t *b = buf;
|
||||
char *str;
|
||||
int i;
|
||||
|
||||
str = hexbufs[curbuf++];
|
||||
curbuf %= ARRAY_SIZE(hexbufs);
|
||||
|
||||
len = min(len, (sizeof(hexbufs[0]) - 1) / 2);
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
str[i * 2] = hex[b[i] >> 4];
|
||||
str[i * 2 + 1] = hex[b[i] & 0xf];
|
||||
}
|
||||
|
||||
str[i * 2] = '\0';
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(BLE_CRYPTO_STACK_MBEDTLS)
|
||||
int
|
||||
ble_aes_ccm_encrypt_be(const uint8_t *key, const uint8_t *plaintext, uint8_t *enc_data)
|
||||
{
|
||||
mbedtls_aes_context s = {0};
|
||||
mbedtls_aes_init(&s);
|
||||
|
||||
if (mbedtls_aes_setkey_enc(&s, key, 128) != 0) {
|
||||
mbedtls_aes_free(&s);
|
||||
return BLE_HS_EUNKNOWN;
|
||||
}
|
||||
|
||||
if (mbedtls_aes_crypt_ecb(&s, MBEDTLS_AES_ENCRYPT, plaintext, enc_data) != 0) {
|
||||
mbedtls_aes_free(&s);
|
||||
return BLE_HS_EUNKNOWN;
|
||||
}
|
||||
|
||||
mbedtls_aes_free(&s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
int
|
||||
ble_aes_ccm_encrypt_be(const uint8_t *key, const uint8_t *plaintext, uint8_t *enc_data)
|
||||
{
|
||||
struct tc_aes_key_sched_struct s = {0};
|
||||
|
||||
if (tc_aes128_set_encrypt_key(&s, key) == TC_CRYPTO_FAIL) {
|
||||
return BLE_HS_EUNKNOWN;
|
||||
}
|
||||
|
||||
if (tc_aes_encrypt(enc_data, plaintext, &s) == TC_CRYPTO_FAIL) {
|
||||
return BLE_HS_EUNKNOWN;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline void xor16(uint8_t *dst, const uint8_t *a, const uint8_t *b)
|
||||
{
|
||||
dst[0] = a[0] ^ b[0];
|
||||
dst[1] = a[1] ^ b[1];
|
||||
dst[2] = a[2] ^ b[2];
|
||||
dst[3] = a[3] ^ b[3];
|
||||
dst[4] = a[4] ^ b[4];
|
||||
dst[5] = a[5] ^ b[5];
|
||||
dst[6] = a[6] ^ b[6];
|
||||
dst[7] = a[7] ^ b[7];
|
||||
dst[8] = a[8] ^ b[8];
|
||||
dst[9] = a[9] ^ b[9];
|
||||
dst[10] = a[10] ^ b[10];
|
||||
dst[11] = a[11] ^ b[11];
|
||||
dst[12] = a[12] ^ b[12];
|
||||
dst[13] = a[13] ^ b[13];
|
||||
dst[14] = a[14] ^ b[14];
|
||||
dst[15] = a[15] ^ b[15];
|
||||
}
|
||||
|
||||
/* pmsg is assumed to have the nonce already present in bytes 1-13 */
|
||||
static int ble_aes_ccm_calculate_X0(const uint8_t key[16], const uint8_t *aad, uint8_t aad_len,
|
||||
size_t mic_size, uint8_t msg_len, uint8_t b[16],
|
||||
uint8_t X0[16])
|
||||
{
|
||||
int i, j, err;
|
||||
|
||||
/* X_0 = e(AppKey, flags || nonce || length) */
|
||||
b[0] = (((mic_size - 2) / 2) << 3) | ((!!aad_len) << 6) | 0x01;
|
||||
|
||||
sys_put_be16(msg_len, b + 14);
|
||||
|
||||
err = ble_aes_ccm_encrypt_be(key, b, X0);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/* If AAD is being used to authenticate, include it here */
|
||||
if (aad_len) {
|
||||
sys_put_be16(aad_len, b);
|
||||
|
||||
for (i = 0; i < sizeof(uint16_t); i++) {
|
||||
b[i] = X0[i] ^ b[i];
|
||||
}
|
||||
|
||||
j = 0;
|
||||
aad_len += sizeof(uint16_t);
|
||||
while (aad_len > 16) {
|
||||
do {
|
||||
b[i] = X0[i] ^ aad[j];
|
||||
i++, j++;
|
||||
} while (i < 16);
|
||||
|
||||
aad_len -= 16;
|
||||
i = 0;
|
||||
|
||||
err = ble_aes_ccm_encrypt_be(key, b, X0);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
for (; i < aad_len; i++, j++) {
|
||||
b[i] = X0[i] ^ aad[j];
|
||||
}
|
||||
|
||||
for (i = aad_len; i < 16; i++) {
|
||||
b[i] = X0[i];
|
||||
}
|
||||
|
||||
err = ble_aes_ccm_encrypt_be(key, b, X0);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ble_aes_ccm_auth(const uint8_t key[16], uint8_t nonce[13],
|
||||
const uint8_t *cleartext_msg, size_t msg_len, const uint8_t *aad,
|
||||
size_t aad_len, uint8_t *mic, size_t mic_size)
|
||||
{
|
||||
uint8_t b[16], Xn[16], s0[16];
|
||||
uint16_t blk_cnt, last_blk;
|
||||
int err, j, i;
|
||||
|
||||
last_blk = msg_len % 16;
|
||||
blk_cnt = (msg_len + 15) / 16;
|
||||
if (!last_blk) {
|
||||
last_blk = 16U;
|
||||
}
|
||||
|
||||
b[0] = 0x01;
|
||||
memcpy(b + 1, nonce, 13);
|
||||
|
||||
/* S[0] = e(AppKey, 0x01 || nonce || 0x0000) */
|
||||
sys_put_be16(0x0000, &b[14]);
|
||||
|
||||
err = ble_aes_ccm_encrypt_be(key, b, s0);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
ble_aes_ccm_calculate_X0(key, aad, aad_len, mic_size, msg_len, b, Xn);
|
||||
|
||||
for (j = 0; j < blk_cnt; j++) {
|
||||
/* X_1 = e(AppKey, X_0 ^ Payload[0-15]) */
|
||||
if (j + 1 == blk_cnt) {
|
||||
for (i = 0; i < last_blk; i++) {
|
||||
b[i] = Xn[i] ^ cleartext_msg[(j * 16) + i];
|
||||
}
|
||||
|
||||
memcpy(&b[i], &Xn[i], 16 - i);
|
||||
} else {
|
||||
xor16(b, Xn, &cleartext_msg[j * 16]);
|
||||
}
|
||||
|
||||
err = ble_aes_ccm_encrypt_be(key, b, Xn);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
/* MIC = C_mic ^ X_1 */
|
||||
for (i = 0; i < mic_size; i++) {
|
||||
mic[i] = s0[i] ^ Xn[i];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ble_aes_ccm_crypt(const uint8_t key[16], const uint8_t nonce[13],
|
||||
const uint8_t *in_msg, uint8_t *out_msg, size_t msg_len)
|
||||
{
|
||||
uint8_t a_i[16], s_i[16];
|
||||
uint16_t last_blk, blk_cnt;
|
||||
size_t i, j;
|
||||
int err;
|
||||
|
||||
last_blk = msg_len % 16;
|
||||
blk_cnt = (msg_len + 15) / 16;
|
||||
if (!last_blk) {
|
||||
last_blk = 16U;
|
||||
}
|
||||
|
||||
a_i[0] = 0x01;
|
||||
memcpy(&a_i[1], nonce, 13);
|
||||
|
||||
for (j = 0; j < blk_cnt; j++) {
|
||||
/* S_1 = e(AppKey, 0x01 || nonce || 0x0001) */
|
||||
sys_put_be16(j + 1, &a_i[14]);
|
||||
|
||||
err = ble_aes_ccm_encrypt_be(key, a_i, s_i);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Encrypted = Payload[0-15] ^ C_1 */
|
||||
if (j < blk_cnt - 1) {
|
||||
xor16(&out_msg[j * 16], s_i, &in_msg[j * 16]);
|
||||
} else {
|
||||
for (i = 0; i < last_blk; i++) {
|
||||
out_msg[(j * 16) + i] =
|
||||
in_msg[(j * 16) + i] ^ s_i[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ble_aes_ccm_decrypt(const uint8_t key[16], uint8_t nonce[13], const uint8_t *enc_msg,
|
||||
size_t msg_len, const uint8_t *aad, size_t aad_len,
|
||||
uint8_t *out_msg, size_t mic_size)
|
||||
{
|
||||
uint8_t mic[16];
|
||||
|
||||
if (aad_len >= 0xff00 || mic_size > sizeof(mic)) {
|
||||
return BLE_HS_EINVAL;
|
||||
}
|
||||
|
||||
ble_aes_ccm_crypt(key, nonce, enc_msg, out_msg, msg_len);
|
||||
|
||||
ble_aes_ccm_auth(key, nonce, out_msg, msg_len, aad, aad_len, mic, mic_size);
|
||||
|
||||
/*if (memcmp(mic, enc_msg + msg_len, mic_size)) {
|
||||
printf("\n%s return here", __func__);
|
||||
return -EBADMSG;
|
||||
}*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ble_aes_ccm_encrypt(const uint8_t key[16], uint8_t nonce[13], const uint8_t *msg,
|
||||
size_t msg_len, const uint8_t *aad, size_t aad_len,
|
||||
uint8_t *out_msg, size_t mic_size)
|
||||
{
|
||||
uint8_t *mic = out_msg + msg_len;
|
||||
|
||||
/* Unsupported AAD size */
|
||||
if (aad_len >= 0xff00 || mic_size > 16) {
|
||||
return BLE_HS_EINVAL;
|
||||
}
|
||||
|
||||
ble_aes_ccm_auth(key, nonce, out_msg, msg_len, aad, aad_len, mic, mic_size);
|
||||
|
||||
ble_aes_ccm_crypt(key, nonce, msg, out_msg, msg_len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* ENC_ADV_DATA */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,209 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
|
||||
#include "os/queue.h"
|
||||
#include "host/ble_ead.h"
|
||||
#include "host/ble_aes_ccm.h"
|
||||
|
||||
#if MYNEWT_VAL(ENC_ADV_DATA)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static uint8_t ble_ead_aad[] = {0xEA};
|
||||
|
||||
static int ble_ead_rand(void *buf, size_t len)
|
||||
{
|
||||
int rc;
|
||||
rc = ble_hs_hci_util_rand(buf, len);
|
||||
if (rc != 0) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ble_ead_generate_randomizer(uint8_t randomizer[BLE_EAD_RANDOMIZER_SIZE])
|
||||
{
|
||||
int err;
|
||||
err = ble_ead_rand(randomizer, BLE_EAD_RANDOMIZER_SIZE);
|
||||
|
||||
if (err != 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
randomizer[4] |= 1 << BLE_EAD_RANDOMIZER_DIRECTION_BIT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int ble_ead_generate_nonce(const uint8_t iv[BLE_EAD_IV_SIZE],
|
||||
const uint8_t randomizer[BLE_EAD_RANDOMIZER_SIZE], uint8_t *nonce)
|
||||
{
|
||||
uint8_t new_randomizer[BLE_EAD_RANDOMIZER_SIZE];
|
||||
|
||||
if (randomizer == NULL) {
|
||||
int err;
|
||||
err = ble_ead_generate_randomizer(new_randomizer);
|
||||
if (err != 0) {
|
||||
BLE_HS_LOG(DEBUG, "Failed to generate Randomizer");
|
||||
return -1;
|
||||
}
|
||||
randomizer = new_randomizer;
|
||||
}
|
||||
|
||||
memcpy(&nonce[0], randomizer, BLE_EAD_RANDOMIZER_SIZE);
|
||||
memcpy(&nonce[BLE_EAD_RANDOMIZER_SIZE], iv, BLE_EAD_IV_SIZE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ead_encrypt(const uint8_t session_key[BLE_EAD_KEY_SIZE], const uint8_t iv[BLE_EAD_IV_SIZE],
|
||||
const uint8_t randomizer[BLE_EAD_RANDOMIZER_SIZE], const uint8_t *payload,
|
||||
size_t payload_size, uint8_t *encrypted_payload)
|
||||
{
|
||||
int err;
|
||||
uint8_t nonce[BLE_EAD_NONCE_SIZE];
|
||||
|
||||
err = ble_ead_generate_nonce(iv, randomizer, nonce);
|
||||
if (err != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(encrypted_payload, nonce, BLE_EAD_RANDOMIZER_SIZE);
|
||||
|
||||
err = ble_aes_ccm_encrypt(session_key, nonce, payload, payload_size, ble_ead_aad, BLE_EAD_AAD_SIZE,
|
||||
&encrypted_payload[BLE_EAD_RANDOMIZER_SIZE], BLE_EAD_MIC_SIZE);
|
||||
if (err != 0) {
|
||||
BLE_HS_LOG(DEBUG, "Failed to encrypt the payload (ble_ccm_encrypt err %d)", err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ble_ead_encrypt(const uint8_t session_key[BLE_EAD_KEY_SIZE], const uint8_t iv[BLE_EAD_IV_SIZE],
|
||||
const uint8_t *payload, size_t payload_size, uint8_t *encrypted_payload)
|
||||
{
|
||||
if (session_key == NULL) {
|
||||
BLE_HS_LOG(DEBUG, "session_key is NULL");
|
||||
return BLE_HS_EINVAL;
|
||||
}
|
||||
|
||||
if (iv == NULL) {
|
||||
BLE_HS_LOG(DEBUG, "iv is NULL");
|
||||
return BLE_HS_EINVAL;
|
||||
}
|
||||
|
||||
if (payload == NULL) {
|
||||
BLE_HS_LOG(DEBUG, "payload is NULL");
|
||||
return BLE_HS_EINVAL;
|
||||
}
|
||||
|
||||
if (encrypted_payload == NULL) {
|
||||
BLE_HS_LOG(DEBUG, "encrypted_payload is NULL");
|
||||
return BLE_HS_EINVAL;
|
||||
}
|
||||
|
||||
if (payload_size == 0) {
|
||||
BLE_HS_LOG(DEBUG, "payload_size is set to 0. The encrypted result will only contain the "
|
||||
"Randomizer and the MIC.");
|
||||
}
|
||||
|
||||
return ead_encrypt(session_key, iv, NULL, payload, payload_size, encrypted_payload);
|
||||
}
|
||||
|
||||
static int ead_decrypt(const uint8_t session_key[BLE_EAD_KEY_SIZE], const uint8_t iv[BLE_EAD_IV_SIZE],
|
||||
const uint8_t *encrypted_payload, size_t encrypted_payload_size,
|
||||
uint8_t *payload)
|
||||
{
|
||||
int err;
|
||||
uint8_t nonce[BLE_EAD_NONCE_SIZE];
|
||||
const uint8_t *encrypted_ad_data = &encrypted_payload[BLE_EAD_RANDOMIZER_SIZE];
|
||||
size_t encrypted_ad_data_size = encrypted_payload_size - BLE_EAD_RANDOMIZER_SIZE;
|
||||
size_t payload_size = encrypted_ad_data_size - BLE_EAD_MIC_SIZE;
|
||||
|
||||
const uint8_t *randomizer = encrypted_payload;
|
||||
|
||||
err = ble_ead_generate_nonce(iv, randomizer, nonce);
|
||||
if (err != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = ble_aes_ccm_decrypt(session_key, nonce, encrypted_ad_data, payload_size, ble_ead_aad,
|
||||
BLE_EAD_AAD_SIZE, payload, BLE_EAD_MIC_SIZE);
|
||||
|
||||
if (err != 0) {
|
||||
BLE_HS_LOG(DEBUG, "Failed to decrypt the data (ble_ccm_decrypt err %d)", err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ble_ead_decrypt(const uint8_t session_key[BLE_EAD_KEY_SIZE], const uint8_t iv[BLE_EAD_IV_SIZE],
|
||||
const uint8_t *encrypted_payload, size_t encrypted_payload_size,
|
||||
uint8_t *payload)
|
||||
{
|
||||
if (session_key == NULL) {
|
||||
BLE_HS_LOG(DEBUG, "session_key is NULL");
|
||||
return BLE_HS_EINVAL;
|
||||
}
|
||||
|
||||
if (iv == NULL) {
|
||||
BLE_HS_LOG(DEBUG, "iv is NULL");
|
||||
return BLE_HS_EINVAL;
|
||||
}
|
||||
|
||||
if (encrypted_payload == NULL) {
|
||||
BLE_HS_LOG(DEBUG, "encrypted_payload is NULL");
|
||||
return BLE_HS_EINVAL;
|
||||
}
|
||||
|
||||
if (payload == NULL) {
|
||||
BLE_HS_LOG(DEBUG, "payload is NULL");
|
||||
return BLE_HS_EINVAL;
|
||||
}
|
||||
|
||||
if (encrypted_payload_size < BLE_EAD_RANDOMIZER_SIZE + BLE_EAD_MIC_SIZE) {
|
||||
BLE_HS_LOG(DEBUG, "encrypted_payload_size is not large enough.");
|
||||
return BLE_HS_EINVAL;
|
||||
} else if (encrypted_payload_size == BLE_EAD_RANDOMIZER_SIZE + BLE_EAD_MIC_SIZE) {
|
||||
BLE_HS_LOG(WARN, "encrypted_payload_size not large enough to contain encrypted data.");
|
||||
}
|
||||
|
||||
return ead_decrypt(session_key, iv, encrypted_payload, encrypted_payload_size, payload);
|
||||
}
|
||||
|
||||
int ble_ead_serialize_data(const struct enc_adv_data *input, uint8_t *output)
|
||||
{
|
||||
if ( input == NULL) {
|
||||
BLE_HS_LOG(DEBUG, "input is NULL");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( output == NULL) {
|
||||
BLE_HS_LOG(DEBUG, "output is NULL");
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t adv_data_len = input->len;
|
||||
uint8_t data_len = adv_data_len + 1;
|
||||
|
||||
output[0] = data_len;
|
||||
output[1] = input->type;
|
||||
|
||||
memcpy(&output[2], input->data, adv_data_len);
|
||||
|
||||
return data_len + 1;
|
||||
|
||||
}
|
||||
|
||||
#endif /* ENC_ADV_DATA */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -24,6 +24,9 @@
|
||||
#include "syscfg/syscfg.h"
|
||||
#include "os/queue.h"
|
||||
#include "nimble/nimble_opt.h"
|
||||
#if MYNEWT_VAL(ENC_ADV_DATA)
|
||||
#include "host/ble_ead.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
||||
@@ -302,6 +302,52 @@ ble_store_key_from_value_sec(struct ble_store_key_sec *out_key,
|
||||
out_key->idx = 0;
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(ENC_ADV_DATA)
|
||||
int
|
||||
ble_store_read_ead(const struct ble_store_key_ead *key,
|
||||
struct ble_store_value_ead *out_value)
|
||||
{
|
||||
union ble_store_value *store_value;
|
||||
union ble_store_key *store_key;
|
||||
int rc;
|
||||
|
||||
store_key = (void *)key;
|
||||
store_value = (void *)out_value;
|
||||
rc = ble_store_read(BLE_STORE_OBJ_TYPE_ENC_ADV_DATA, store_key, store_value);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
ble_store_write_ead(const struct ble_store_value_ead *value)
|
||||
{
|
||||
union ble_store_value *store_value;
|
||||
int rc;
|
||||
|
||||
store_value = (void *)value;
|
||||
rc = ble_store_write(BLE_STORE_OBJ_TYPE_ENC_ADV_DATA, store_value);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
ble_store_delete_ead(const struct ble_store_key_ead *key)
|
||||
{
|
||||
union ble_store_key *store_key;
|
||||
int rc;
|
||||
|
||||
store_key = (void *)key;
|
||||
rc = ble_store_delete(BLE_STORE_OBJ_TYPE_ENC_ADV_DATA, store_key);
|
||||
return rc;
|
||||
}
|
||||
|
||||
void
|
||||
ble_store_key_from_value_ead(struct ble_store_key_ead *out_key,
|
||||
const struct ble_store_value_ead *value)
|
||||
{
|
||||
out_key->peer_addr = value->peer_addr;
|
||||
out_key->idx = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
ble_store_key_from_value(int obj_type,
|
||||
union ble_store_key *out_key,
|
||||
@@ -316,7 +362,11 @@ ble_store_key_from_value(int obj_type,
|
||||
case BLE_STORE_OBJ_TYPE_CCCD:
|
||||
ble_store_key_from_value_cccd(&out_key->cccd, &value->cccd);
|
||||
break;
|
||||
|
||||
#if MYNEWT_VAL(ENC_ADV_DATA)
|
||||
case BLE_STORE_OBJ_TYPE_ENC_ADV_DATA:
|
||||
ble_store_key_from_value_ead(&out_key->ead, &value->ead);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
BLE_HS_DBG_ASSERT(0);
|
||||
break;
|
||||
@@ -346,6 +396,12 @@ ble_store_iterate(int obj_type,
|
||||
key.cccd.peer_addr = *BLE_ADDR_ANY;
|
||||
pidx = &key.cccd.idx;
|
||||
break;
|
||||
#if MYNEWT_VAL(ENC_ADV_DATA)
|
||||
case BLE_STORE_OBJ_TYPE_ENC_ADV_DATA:
|
||||
key.ead.peer_addr = *BLE_ADDR_ANY;
|
||||
pidx = &key.ead.idx;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
BLE_HS_DBG_ASSERT(0);
|
||||
return BLE_HS_EINVAL;
|
||||
@@ -390,6 +446,9 @@ ble_store_clear(void)
|
||||
BLE_STORE_OBJ_TYPE_OUR_SEC,
|
||||
BLE_STORE_OBJ_TYPE_PEER_SEC,
|
||||
BLE_STORE_OBJ_TYPE_CCCD,
|
||||
#if MYNEWT_VAL(ENC_ADV_DATA)
|
||||
BLE_STORE_OBJ_TYPE_ENC_ADV_DATA,
|
||||
#endif
|
||||
};
|
||||
union ble_store_key key;
|
||||
int obj_type;
|
||||
|
||||
@@ -37,6 +37,9 @@ ble_store_util_iter_unique_peer(int obj_type,
|
||||
int i;
|
||||
|
||||
BLE_HS_DBG_ASSERT(obj_type == BLE_STORE_OBJ_TYPE_OUR_SEC ||
|
||||
#if MYNEWT_VAL(ENC_ADV_DATA)
|
||||
obj_type == BLE_STORE_OBJ_TYPE_ENC_ADV_DATA ||
|
||||
#endif
|
||||
obj_type == BLE_STORE_OBJ_TYPE_PEER_SEC);
|
||||
|
||||
set = arg;
|
||||
@@ -133,6 +136,16 @@ ble_store_util_delete_peer(const ble_addr_t *peer_id_addr)
|
||||
return rc;
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(ENC_ADV_DATA)
|
||||
memset(&key, 0, sizeof key);
|
||||
key.ead.peer_addr = *peer_id_addr;
|
||||
|
||||
rc = ble_store_util_delete_all(BLE_STORE_OBJ_TYPE_ENC_ADV_DATA, &key);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(BLE_HOST_BASED_PRIVACY)
|
||||
struct ble_hs_dev_records *peer_rec =
|
||||
ble_rpa_find_peer_dev_rec(key.sec.peer_addr.val);
|
||||
@@ -235,6 +248,75 @@ ble_store_util_delete_oldest_peer(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(ENC_ADV_DATA)
|
||||
/**
|
||||
* Retrieves the set of peer addresses for which a ead has been established.
|
||||
*
|
||||
* @param out_peer_id_addrs On success, the set of ead peer addresses
|
||||
* gets written here.
|
||||
* @param out_num_peers On success, the number of eads gets written
|
||||
* here.
|
||||
* @param max_peers The capacity of the destination buffer.
|
||||
*
|
||||
* @return 0 on success;
|
||||
* BLE_HS_ENOMEM if the destination buffer is too
|
||||
* small;
|
||||
* Other nonzero on error.
|
||||
*/
|
||||
int
|
||||
ble_store_util_ead_peers(ble_addr_t *out_peer_id_addrs, int *out_num_peers,
|
||||
int max_peers)
|
||||
{
|
||||
struct ble_store_util_peer_set set = {
|
||||
.peer_id_addrs = out_peer_id_addrs,
|
||||
.num_peers = 0,
|
||||
.max_peers = max_peers,
|
||||
.status = 0,
|
||||
};
|
||||
int rc;
|
||||
|
||||
rc = ble_store_iterate(BLE_STORE_OBJ_TYPE_ENC_ADV_DATA,
|
||||
ble_store_util_iter_unique_peer,
|
||||
&set);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
*out_num_peers = set.num_peers;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
ble_store_util_delete_ead_oldest_peer(void)
|
||||
{
|
||||
ble_addr_t peer_id_addrs[MYNEWT_VAL(BLE_STORE_MAX_EADS)];
|
||||
int num_peers;
|
||||
int rc;
|
||||
union ble_store_key key;
|
||||
memset(&key, 0, sizeof key);
|
||||
|
||||
rc = ble_store_util_ead_peers(
|
||||
peer_id_addrs, &num_peers,
|
||||
sizeof peer_id_addrs / sizeof peer_id_addrs[0]);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (num_peers == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
key.ead.peer_addr = peer_id_addrs[0];
|
||||
rc = ble_store_util_delete_all(BLE_STORE_OBJ_TYPE_ENC_ADV_DATA, &key);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Round-robin status callback. If a there is insufficient storage capacity
|
||||
* for a new record, delete the oldest bond and proceed with the persist
|
||||
@@ -256,7 +338,10 @@ ble_store_util_status_rr(struct ble_store_status_event *event, void *arg)
|
||||
case BLE_STORE_OBJ_TYPE_CCCD:
|
||||
/* Try unpairing oldest peer except current peer */
|
||||
return ble_gap_unpair_oldest_except(&event->overflow.value->cccd.peer_addr);
|
||||
|
||||
#if MYNEWT_VAL(ENC_ADV_DATA)
|
||||
case BLE_STORE_OBJ_TYPE_ENC_ADV_DATA:
|
||||
return ble_store_util_delete_ead_oldest_peer();
|
||||
#endif
|
||||
default:
|
||||
return BLE_HS_EUNKNOWN;
|
||||
}
|
||||
|
||||
@@ -38,6 +38,12 @@ struct ble_store_value_cccd
|
||||
ble_store_config_cccds[MYNEWT_VAL(BLE_STORE_MAX_CCCDS)];
|
||||
int ble_store_config_num_cccds;
|
||||
|
||||
#if MYNEWT_VAL(ENC_ADV_DATA)
|
||||
struct ble_store_value_ead
|
||||
ble_store_config_eads[MYNEWT_VAL(BLE_STORE_MAX_EADS)];
|
||||
int ble_store_config_num_eads;
|
||||
#endif
|
||||
|
||||
/*****************************************************************************
|
||||
* $sec *
|
||||
*****************************************************************************/
|
||||
@@ -393,6 +399,112 @@ ble_store_config_write_cccd(const struct ble_store_value_cccd *value_cccd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* $ead *
|
||||
*****************************************************************************/
|
||||
#if MYNEWT_VAL(ENC_ADV_DATA)
|
||||
static int
|
||||
ble_store_config_find_ead(const struct ble_store_key_ead *key)
|
||||
{
|
||||
struct ble_store_value_ead *ead;
|
||||
int skipped;
|
||||
int i;
|
||||
|
||||
skipped = 0;
|
||||
for (i = 0; i < ble_store_config_num_eads; i++) {
|
||||
ead = ble_store_config_eads + i;
|
||||
|
||||
if (ble_addr_cmp(&key->peer_addr, BLE_ADDR_ANY)) {
|
||||
if (ble_addr_cmp(&ead->peer_addr, &key->peer_addr)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (key->idx > skipped) {
|
||||
skipped++;
|
||||
continue;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
ble_store_config_delete_ead(const struct ble_store_key_ead *key_ead)
|
||||
{
|
||||
int idx;
|
||||
int rc;
|
||||
|
||||
idx = ble_store_config_find_ead(key_ead);
|
||||
if (idx == -1) {
|
||||
return BLE_HS_ENOENT;
|
||||
}
|
||||
|
||||
rc = ble_store_config_delete_obj(ble_store_config_eads,
|
||||
sizeof *ble_store_config_eads,
|
||||
idx,
|
||||
&ble_store_config_num_eads);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = ble_store_config_persist_eads();
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ble_store_config_read_ead(const struct ble_store_key_ead *key_ead,
|
||||
struct ble_store_value_ead *value_ead)
|
||||
{
|
||||
int idx;
|
||||
|
||||
idx = ble_store_config_find_ead(key_ead);
|
||||
if (idx == -1) {
|
||||
return BLE_HS_ENOENT;
|
||||
}
|
||||
|
||||
*value_ead = ble_store_config_eads[idx];
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ble_store_config_write_ead(const struct ble_store_value_ead *value_ead)
|
||||
{
|
||||
struct ble_store_key_ead key_ead;
|
||||
int idx;
|
||||
int rc;
|
||||
|
||||
ble_store_key_from_value_ead(&key_ead, value_ead);
|
||||
idx = ble_store_config_find_ead(&key_ead);
|
||||
|
||||
if (idx == -1) {
|
||||
if (ble_store_config_num_eads >= MYNEWT_VAL(BLE_STORE_MAX_EADS)) {
|
||||
BLE_HS_LOG(DEBUG, "error persisting ead; too many entries (%d)\n",
|
||||
ble_store_config_num_eads);
|
||||
return BLE_HS_ESTORE_CAP;
|
||||
}
|
||||
|
||||
idx = ble_store_config_num_eads;
|
||||
ble_store_config_num_eads++;
|
||||
}
|
||||
|
||||
ble_store_config_eads[idx] = *value_ead;
|
||||
|
||||
rc = ble_store_config_persist_eads();
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*****************************************************************************
|
||||
* $api *
|
||||
*****************************************************************************/
|
||||
@@ -435,6 +547,12 @@ ble_store_config_read(int obj_type, const union ble_store_key *key,
|
||||
rc = ble_store_config_read_cccd(&key->cccd, &value->cccd);
|
||||
return rc;
|
||||
|
||||
#if MYNEWT_VAL(ENC_ADV_DATA)
|
||||
case BLE_STORE_OBJ_TYPE_ENC_ADV_DATA:
|
||||
rc = ble_store_config_read_ead(&key->ead, &value->ead);
|
||||
return rc;
|
||||
#endif
|
||||
|
||||
default:
|
||||
return BLE_HS_ENOTSUP;
|
||||
}
|
||||
@@ -464,6 +582,12 @@ ble_store_config_write(int obj_type, const union ble_store_value *val)
|
||||
rc = ble_store_config_write_cccd(&val->cccd);
|
||||
return rc;
|
||||
|
||||
#if MYNEWT_VAL(ENC_ADV_DATA)
|
||||
case BLE_STORE_OBJ_TYPE_ENC_ADV_DATA:
|
||||
rc = ble_store_config_write_ead(&val->ead);
|
||||
return rc;
|
||||
#endif
|
||||
|
||||
default:
|
||||
return BLE_HS_ENOTSUP;
|
||||
}
|
||||
@@ -487,6 +611,12 @@ ble_store_config_delete(int obj_type, const union ble_store_key *key)
|
||||
rc = ble_store_config_delete_cccd(&key->cccd);
|
||||
return rc;
|
||||
|
||||
#if MYNEWT_VAL(ENC_ADV_DATA)
|
||||
case BLE_STORE_OBJ_TYPE_ENC_ADV_DATA:
|
||||
rc = ble_store_config_delete_ead(&key->ead);
|
||||
return rc;
|
||||
#endif
|
||||
|
||||
default:
|
||||
return BLE_HS_ENOTSUP;
|
||||
}
|
||||
@@ -506,6 +636,9 @@ ble_store_config_init(void)
|
||||
ble_store_config_num_our_secs = 0;
|
||||
ble_store_config_num_peer_secs = 0;
|
||||
ble_store_config_num_cccds = 0;
|
||||
#if MYNEWT_VAL(ENC_ADV_DATA)
|
||||
ble_store_config_num_eads = 0;
|
||||
#endif
|
||||
|
||||
ble_store_config_conf_init();
|
||||
}
|
||||
|
||||
@@ -57,6 +57,14 @@ static struct conf_handler ble_store_config_conf_handler = {
|
||||
#define BLE_STORE_CONFIG_CCCD_SET_ENCODE_SZ \
|
||||
(MYNEWT_VAL(BLE_STORE_MAX_CCCDS) * BLE_STORE_CONFIG_CCCD_ENCODE_SZ + 1)
|
||||
|
||||
#if MYNEWT_VAL(ENC_ADV_DATA)
|
||||
#define BLE_STORE_CONFIG_EAD_ENCODE_SZ \
|
||||
BASE64_ENCODE_SIZE(sizeof (struct ble_store_value_ead))
|
||||
|
||||
#define BLE_STORE_CONFIG_EAD_SET_ENCODE_SZ \
|
||||
(MYNEWT_VAL(BLE_STORE_MAX_EADS) * BLE_STORE_CONFIG_EAD_ENCODE_SZ + 1)
|
||||
#endif
|
||||
|
||||
static void
|
||||
ble_store_config_serialize_arr(const void *arr, int obj_sz, int num_objs,
|
||||
char *out_buf, int buf_sz)
|
||||
@@ -114,6 +122,16 @@ ble_store_config_conf_set(int argc, char **argv, char *val)
|
||||
&ble_store_config_num_cccds);
|
||||
return rc;
|
||||
}
|
||||
#if MYNEWT_VAL(ENC_ADV_DATA)
|
||||
else if (strcmp(argv[0], "ead") == 0) {
|
||||
rc = ble_store_config_deserialize_arr(
|
||||
val,
|
||||
ble_store_config_eads,
|
||||
sizeof *ble_store_config_eads,
|
||||
&ble_store_config_num_eads);
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return OS_ENOENT;
|
||||
}
|
||||
@@ -148,6 +166,14 @@ ble_store_config_conf_export(void (*func)(char *name, char *val),
|
||||
sizeof buf.cccd);
|
||||
func("ble_hs/cccd", buf.cccd);
|
||||
|
||||
#if MYNEWT_VAL(ENC_ADV_DATA)
|
||||
ble_store_config_serialize_arr(ble_store_config_eads,
|
||||
sizeof *ble_store_config_eads,
|
||||
ble_store_config_num_eads,
|
||||
buf.ead,
|
||||
sizeof buf.ead);
|
||||
func("ble_hs/ead", buf.ead);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -218,6 +244,25 @@ ble_store_config_persist_cccds(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(ENC_ADV_DATA)
|
||||
int
|
||||
ble_store_config_persist_eads(void)
|
||||
{
|
||||
char buf[BLE_STORE_CONFIG_CCCD_SET_ENCODE_SZ];
|
||||
int rc;
|
||||
ble_store_config_serialize_arr(ble_store_config_eads,
|
||||
sizeof *ble_store_config_eads,
|
||||
ble_store_config_num_eads,
|
||||
buf,
|
||||
sizeof buf);
|
||||
rc = conf_save_one("ble_hs/ead", buf);
|
||||
if (rc != 0) {
|
||||
return BLE_HS_ESTORE_FAIL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
ble_store_config_conf_init(void)
|
||||
{
|
||||
|
||||
@@ -36,11 +36,20 @@ extern struct ble_store_value_cccd
|
||||
ble_store_config_cccds[MYNEWT_VAL(BLE_STORE_MAX_CCCDS)];
|
||||
extern int ble_store_config_num_cccds;
|
||||
|
||||
#if MYNEWT_VAL(ENC_ADV_DATA)
|
||||
extern struct ble_store_value_ead
|
||||
ble_store_config_eads[MYNEWT_VAL(BLE_STORE_MAX_EADS)];
|
||||
extern int ble_store_config_num_eads;
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(BLE_STORE_CONFIG_PERSIST)
|
||||
|
||||
int ble_store_config_persist_our_secs(void);
|
||||
int ble_store_config_persist_peer_secs(void);
|
||||
int ble_store_config_persist_cccds(void);
|
||||
#if MYNEWT_VAL(ENC_ADV_DATA)
|
||||
int ble_store_config_persist_eads(void);
|
||||
#endif
|
||||
void ble_store_config_conf_init(void);
|
||||
|
||||
#else
|
||||
@@ -48,6 +57,9 @@ void ble_store_config_conf_init(void);
|
||||
static inline int ble_store_config_persist_our_secs(void) { return 0; }
|
||||
static inline int ble_store_config_persist_peer_secs(void) { return 0; }
|
||||
static inline int ble_store_config_persist_cccds(void) { return 0; }
|
||||
#if MYNEWT_VAL(ENC_ADV_DATA)
|
||||
static inline int ble_store_config_persist_eads(void) { return 0; }
|
||||
#endif
|
||||
static inline void ble_store_config_conf_init(void) { }
|
||||
|
||||
#if MYNEWT_VAL(BLE_HOST_BASED_PRIVACY)
|
||||
|
||||
@@ -42,6 +42,10 @@
|
||||
#define NIMBLE_NVS_PEER_RECORDS_KEY "p_dev_rec"
|
||||
#define NIMBLE_NVS_NAMESPACE "nimble_bond"
|
||||
|
||||
#if MYNEWT_VAL(ENC_ADV_DATA)
|
||||
#define NIMBLE_NVS_EAD_SEC_KEY "ead_sec"
|
||||
#endif
|
||||
|
||||
static const char *TAG = "NIMBLE_NVS";
|
||||
|
||||
/*****************************************************************************
|
||||
@@ -58,6 +62,10 @@ get_nvs_key_string(int obj_type, int index, char *key_string)
|
||||
sprintf(key_string, "%s_%d", NIMBLE_NVS_PEER_SEC_KEY, index);
|
||||
} else if (obj_type == BLE_STORE_OBJ_TYPE_OUR_SEC) {
|
||||
sprintf(key_string, "%s_%d", NIMBLE_NVS_OUR_SEC_KEY, index);
|
||||
#if MYNEWT_VAL(ENC_ADV_DATA)
|
||||
} else if (obj_type == NIMBLE_NVS_EAD_SEC_KEY) {
|
||||
sprintf(key_string, "%s_%d", NIMBLE_NVS_EAD_SEC_KEY, index);
|
||||
#endif
|
||||
} else {
|
||||
sprintf(key_string, "%s_%d", NIMBLE_NVS_CCCD_SEC_KEY, index);
|
||||
}
|
||||
@@ -94,6 +102,10 @@ get_nvs_max_obj_value(int obj_type)
|
||||
} else {
|
||||
if (obj_type == BLE_STORE_OBJ_TYPE_CCCD) {
|
||||
return MYNEWT_VAL(BLE_STORE_MAX_CCCDS);
|
||||
#if MYNEWT_VAL(ENC_ADV_DATA)
|
||||
} else if (obj_type == BLE_STORE_OBJ_TYPE_EAD) {
|
||||
return MYNEWT_VAL(BLE_STORE_MAX_EADS);
|
||||
#endif
|
||||
} else {
|
||||
return MYNEWT_VAL(BLE_STORE_MAX_BONDS);
|
||||
}
|
||||
@@ -156,6 +168,11 @@ get_nvs_db_value(int obj_type, char *key_string, union ble_store_value *val)
|
||||
if (obj_type == BLE_STORE_OBJ_TYPE_CCCD) {
|
||||
err = nvs_get_blob(nimble_handle, key_string, &val->cccd,
|
||||
&required_size);
|
||||
#if MYNEWT_VAL(ENC_ADV_DATA)
|
||||
} else if (obj_type == BLE_STORE_OBJ_TYPE_EAD) {
|
||||
err = nvs_get_blob(nimble_handle, key_string, &val->ead,
|
||||
&required_size);
|
||||
#endif
|
||||
} else {
|
||||
err = nvs_get_blob(nimble_handle, key_string, &val->sec,
|
||||
&required_size);
|
||||
@@ -219,12 +236,17 @@ get_nvs_db_attribute(int obj_type, bool empty, void *value, int num_value)
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
if (obj_type != BLE_STORE_OBJ_TYPE_CCCD) {
|
||||
if (obj_type == BLE_STORE_OBJ_TYPE_CCCD) {
|
||||
err = get_nvs_matching_index(&cur.sec, value, num_value,
|
||||
sizeof(struct ble_store_value_sec));
|
||||
sizeof(struct ble_store_value_cccd));
|
||||
#if MYNEWT_VAL(ENC_ADV_DATA)
|
||||
} else if (obj_type == BLE_STORE_OBJ_TYPE_EAD) {
|
||||
err = get_nvs_matching_index(&cur.sec, value, num_value,
|
||||
sizeof(struct ble_store_value_ead));
|
||||
#endif
|
||||
} else {
|
||||
err = get_nvs_matching_index(&cur.cccd, value, num_value,
|
||||
sizeof(struct ble_store_value_cccd));
|
||||
sizeof(struct ble_store_value_sec));
|
||||
}
|
||||
}
|
||||
/* If found non-matching/odd entry of NVS with entries in the
|
||||
@@ -347,6 +369,11 @@ ble_store_nvs_write(int obj_type, const union ble_store_value *val)
|
||||
if (obj_type == BLE_STORE_OBJ_TYPE_CCCD) {
|
||||
return ble_nvs_write_key_value(key_string, &val->cccd, sizeof(struct
|
||||
ble_store_value_cccd));
|
||||
#if MYNEWT_VAL(ENC_ADV_DATA)
|
||||
} else if (obj_type == BLE_STORE_OBJ_TYPE_EAD) {
|
||||
return ble_nvs_write_key_value(key_string, &val->ead, sizeof(struct
|
||||
ble_store_value_ead));
|
||||
#endif
|
||||
} else {
|
||||
return ble_nvs_write_key_value(key_string, &val->sec, sizeof(struct
|
||||
ble_store_value_sec));
|
||||
@@ -431,6 +458,13 @@ populate_db_from_nvs(int obj_type, void *dst, int *db_num)
|
||||
memcpy(db_item, &cur.cccd, sizeof(struct ble_store_value_cccd));
|
||||
db_item += sizeof(struct ble_store_value_cccd);
|
||||
(*db_num)++;
|
||||
#if MYNEWT_VAL(ENC_ADV_DATA)
|
||||
} if (obj_type == BLE_STORE_OBJ_TYPE_EAD) {
|
||||
ESP_LOGD(TAG, "EAD in RAM is filled up from NVS index = %d", i);
|
||||
memcpy(db_item, &cur.ead, sizeof(struct ble_store_value_ead));
|
||||
db_item += sizeof(struct ble_store_value_ead);
|
||||
(*db_num)++;
|
||||
#endif
|
||||
} else {
|
||||
ESP_LOGD(TAG, "KEY in RAM is filled up from NVS index = %d", i);
|
||||
memcpy(db_item, &cur.sec, sizeof(struct ble_store_value_sec));
|
||||
@@ -476,6 +510,16 @@ ble_nvs_restore_sec_keys(void)
|
||||
ESP_LOGD(TAG, "ble_store_config_cccds restored %d bonds",
|
||||
ble_store_config_num_cccds);
|
||||
|
||||
#if MYNEWT_VAL(ENC_ADV_DATA)
|
||||
err = populate_db_from_nvs(BLE_STORE_OBJ_TYPE_EAD, ble_store_config_eads,
|
||||
&ble_store_config_num_eads);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "NVS operation failed for 'EAD'");
|
||||
return err;
|
||||
}
|
||||
ESP_LOGD(TAG, "ble_store_config_eads restored %d bonds",
|
||||
ble_store_config_num_eads);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -532,6 +576,38 @@ int ble_store_config_persist_cccds(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(ENC_ADV_DATA)
|
||||
int ble_store_config_persist_eads(void)
|
||||
{
|
||||
int nvs_count, nvs_idx;
|
||||
union ble_store_value val;
|
||||
|
||||
nvs_count = get_nvs_db_attribute(BLE_STORE_OBJ_TYPE_ENC_ADV_DATA, 0, NULL, 0);
|
||||
if (nvs_count == -1) {
|
||||
ESP_LOGE(TAG, "NVS operation failed while persisting EAD");
|
||||
return BLE_HS_ESTORE_FAIL;
|
||||
}
|
||||
|
||||
if (nvs_count < ble_store_config_num_eads) {
|
||||
/* NVS db count less than RAM count, write operation */
|
||||
ESP_LOGD(TAG, "Persisting EAD value in NVS...");
|
||||
val.ead = ble_store_config_eads[ble_store_config_num_eads - 1];
|
||||
return ble_store_nvs_write(BLE_STORE_OBJ_TYPE_ENC_ADV_DATA, &val);
|
||||
} else if (nvs_count > ble_store_config_num_eads) {
|
||||
/* NVS db count more than RAM count, delete operation */
|
||||
vvs_idx = get_nvs_db_attribute(BLE_STORE_OBJ_TYPE_ENC_ADV_DATA, 0,
|
||||
ble_store_config_eads, ble_store_config_num_eads);
|
||||
if (nvs_idx == -1) {
|
||||
ESP_LOGE(TAG, "NVS delete operation failed for EAD");
|
||||
return BLE_HS_ESTORE_FAIL;
|
||||
}
|
||||
ESP_LOGD(TAG, "Deleting EAD, nvs idx = %d", nvs_idx);
|
||||
return ble_nvs_delete_value(BLE_STORE_OBJ_TYPE_EAD, nvs_idx);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int ble_store_config_persist_peer_secs(void)
|
||||
{
|
||||
int nvs_count, nvs_idx;
|
||||
|
||||
@@ -48,6 +48,12 @@ static struct ble_store_value_cccd
|
||||
ble_store_ram_cccds[MYNEWT_VAL(BLE_STORE_MAX_CCCDS)];
|
||||
static int ble_store_ram_num_cccds;
|
||||
|
||||
#if MYNEWT_VAL(ENC_ADV_DATA)
|
||||
static struct ble_store_value_ead
|
||||
ble_store_ram_eads[MYNEWT_VAL(BLE_STORE_MAX_EADS)];
|
||||
static int ble_store_ram_num_eads;
|
||||
#endif
|
||||
|
||||
/*****************************************************************************
|
||||
* $sec *
|
||||
*****************************************************************************/
|
||||
@@ -366,6 +372,99 @@ ble_store_ram_write_cccd(const struct ble_store_value_cccd *value_cccd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* $ead *
|
||||
*****************************************************************************/
|
||||
#if MYNEWT_VAL(ENC_ADV_DATA)
|
||||
static int
|
||||
ble_store_ram_find_ead(const struct ble_store_key_ead *key)
|
||||
{
|
||||
struct ble_store_value_ead *ead;
|
||||
int skipped;
|
||||
int i;
|
||||
|
||||
skipped = 0;
|
||||
for (i = 0; i < ble_store_ram_num_eads; i++) {
|
||||
ead = ble_store_ram_eads + i;
|
||||
|
||||
if (ble_addr_cmp(&key->peer_addr, BLE_ADDR_ANY)) {
|
||||
if (ble_addr_cmp(&ead->peer_addr, &key->peer_addr)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (key->idx > skipped) {
|
||||
skipped++;
|
||||
continue;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
ble_store_ram_delete_ead(const struct ble_store_key_ead *key_ead)
|
||||
{
|
||||
int idx;
|
||||
int rc;
|
||||
|
||||
idx = ble_store_ram_find_ead(key_ead);
|
||||
if (idx == -1) {
|
||||
return BLE_HS_ENOENT;
|
||||
}
|
||||
rc = ble_store_ram_delete_obj(ble_store_ram_eads,
|
||||
sizeof *ble_store_ram_eads,
|
||||
idx,
|
||||
&ble_store_ram_num_eads);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ble_store_ram_read_ead(const struct ble_store_key_ead *key_ead,
|
||||
struct ble_store_value_ead *value_ead)
|
||||
{
|
||||
int idx;
|
||||
|
||||
idx = ble_store_ram_find_ead(key_ead);
|
||||
if (idx == -1) {
|
||||
return BLE_HS_ENOENT;
|
||||
}
|
||||
|
||||
*value_ead = ble_store_ram_eads[idx];
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ble_store_ram_write_ead(const struct ble_store_value_ead *value_ead)
|
||||
{
|
||||
struct ble_store_key_ead key_ead;
|
||||
int idx;
|
||||
|
||||
ble_store_key_from_value_ead(&key_ead, value_ead);
|
||||
idx = ble_store_ram_find_ead(&key_ead);
|
||||
if (idx == -1) {
|
||||
if (ble_store_ram_num_eads >= MYNEWT_VAL(BLE_STORE_MAX_EADS)) {
|
||||
BLE_HS_LOG(DEBUG, "error persisting ead; too many entries (%d)\n",
|
||||
ble_store_ram_num_eads);
|
||||
return BLE_HS_ESTORE_CAP;
|
||||
}
|
||||
|
||||
idx = ble_store_ram_num_eads;
|
||||
ble_store_ram_num_eads++;
|
||||
}
|
||||
|
||||
ble_store_ram_eads[idx] = *value_ead;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*****************************************************************************
|
||||
* $api *
|
||||
*****************************************************************************/
|
||||
@@ -408,6 +507,12 @@ ble_store_ram_read(int obj_type, const union ble_store_key *key,
|
||||
rc = ble_store_ram_read_cccd(&key->cccd, &value->cccd);
|
||||
return rc;
|
||||
|
||||
#if MYNEWT_VAL(ENC_ADV_DATA)
|
||||
case BLE_STORE_OBJ_TYPE_ENC_ADV_DATA:
|
||||
rc = ble_store_ram_read_ead(&key->ead, &value->ead);
|
||||
return rc;
|
||||
#endif
|
||||
|
||||
default:
|
||||
return BLE_HS_ENOTSUP;
|
||||
}
|
||||
@@ -437,6 +542,12 @@ ble_store_ram_write(int obj_type, const union ble_store_value *val)
|
||||
rc = ble_store_ram_write_cccd(&val->cccd);
|
||||
return rc;
|
||||
|
||||
#if MYNEWT_VAL(ENC_ADV_DATA)
|
||||
case BLE_STORE_OBJ_TYPE_ENC_ADV_DATA:
|
||||
rc = ble_store_ram_write_ead(&val->ead);
|
||||
return rc;
|
||||
#endif
|
||||
|
||||
default:
|
||||
return BLE_HS_ENOTSUP;
|
||||
}
|
||||
@@ -460,6 +571,12 @@ ble_store_ram_delete(int obj_type, const union ble_store_key *key)
|
||||
rc = ble_store_ram_delete_cccd(&key->cccd);
|
||||
return rc;
|
||||
|
||||
#if MYNEWT_VAL(ENC_ADV_DATA)
|
||||
case BLE_STORE_OBJ_TYPE_ENC_ADV_DATA:
|
||||
rc = ble_store_ram_delete_ead(&key->ead);
|
||||
return rc;
|
||||
#endif
|
||||
|
||||
default:
|
||||
return BLE_HS_ENOTSUP;
|
||||
}
|
||||
@@ -479,4 +596,7 @@ ble_store_ram_init(void)
|
||||
ble_store_ram_num_our_secs = 0;
|
||||
ble_store_ram_num_peer_secs = 0;
|
||||
ble_store_ram_num_cccds = 0;
|
||||
#if MYNEWT_VAL(ENC_ADV_DATA)
|
||||
ble_store_ram_num_eads = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -442,6 +442,10 @@
|
||||
#define MYNEWT_VAL_BLE_EXT_ADV_MAX_SIZE (31)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_ENC_ADV_DATA
|
||||
#define MYNEWT_VAL_ENC_ADV_DATA (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_HCI_VS
|
||||
#define MYNEWT_VAL_BLE_HCI_VS (0)
|
||||
#endif
|
||||
@@ -819,6 +823,10 @@
|
||||
#define MYNEWT_VAL_BLE_STORE_MAX_CCCDS (8)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BT_NIMBLE_MAX_EADS
|
||||
#define MYNEWT_VAL_BLE_STORE_MAX_EADS CONFIG_BT_NIMBLE_MAX_EADS
|
||||
#endif
|
||||
|
||||
/*** @apache-mynewt-nimble/nimble/host/services/ans */
|
||||
#ifndef MYNEWT_VAL_BLE_SVC_ANS_NEW_ALERT_CAT
|
||||
#define MYNEWT_VAL_BLE_SVC_ANS_NEW_ALERT_CAT (0)
|
||||
|
||||
@@ -443,6 +443,10 @@
|
||||
#define MYNEWT_VAL_BLE_EXT_ADV_MAX_SIZE (31)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_ENC_ADV_DATA
|
||||
#define MYNEWT_VAL_ENC_ADV_DATA (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_HCI_VS
|
||||
#define MYNEWT_VAL_BLE_HCI_VS (0)
|
||||
#endif
|
||||
@@ -822,6 +826,10 @@
|
||||
#define MYNEWT_VAL_BLE_STORE_MAX_CCCDS (8)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BT_NIMBLE_MAX_EADS
|
||||
#define MYNEWT_VAL_BLE_STORE_MAX_EADS CONFIG_BT_NIMBLE_MAX_EADS
|
||||
#endif
|
||||
|
||||
/*** @apache-mynewt-nimble/nimble/host/mesh */
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_ACCESS_LAYER_MSG
|
||||
#define MYNEWT_VAL_BLE_MESH_ACCESS_LAYER_MSG (1)
|
||||
|
||||
@@ -442,6 +442,10 @@
|
||||
#define MYNEWT_VAL_BLE_EXT_ADV_MAX_SIZE (31)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_ENC_ADV_DATA
|
||||
#define MYNEWT_VAL_ENC_ADV_DATA (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_HCI_VS
|
||||
#define MYNEWT_VAL_BLE_HCI_VS (0)
|
||||
#endif
|
||||
@@ -821,6 +825,10 @@
|
||||
#define MYNEWT_VAL_BLE_STORE_MAX_CCCDS (8)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BT_NIMBLE_MAX_EADS
|
||||
#define MYNEWT_VAL_BLE_STORE_MAX_EADS CONFIG_BT_NIMBLE_MAX_EADS
|
||||
#endif
|
||||
|
||||
/*** @apache-mynewt-nimble/nimble/host/services/ans */
|
||||
#ifndef MYNEWT_VAL_BLE_SVC_ANS_NEW_ALERT_CAT
|
||||
#define MYNEWT_VAL_BLE_SVC_ANS_NEW_ALERT_CAT (0)
|
||||
|
||||
@@ -445,6 +445,10 @@
|
||||
#define MYNEWT_VAL_BLE_EXT_ADV_MAX_SIZE (31)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_ENC_ADV_DATA
|
||||
#define MYNEWT_VAL_ENC_ADV_DATA (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_HCI_VS
|
||||
#define MYNEWT_VAL_BLE_HCI_VS (0)
|
||||
#endif
|
||||
@@ -822,6 +826,10 @@
|
||||
#define MYNEWT_VAL_BLE_STORE_MAX_CCCDS (8)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BT_NIMBLE_MAX_EADS
|
||||
#define MYNEWT_VAL_BLE_STORE_MAX_EADS CONFIG_BT_NIMBLE_MAX_EADS
|
||||
#endif
|
||||
|
||||
/*** @apache-mynewt-nimble/nimble/host/services/ans */
|
||||
#ifndef MYNEWT_VAL_BLE_SVC_ANS_NEW_ALERT_CAT
|
||||
#define MYNEWT_VAL_BLE_SVC_ANS_NEW_ALERT_CAT (0)
|
||||
|
||||
@@ -817,6 +817,10 @@
|
||||
#define MYNEWT_VAL_BLE_EXT_ADV_MAX_SIZE (31)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_ENC_ADV_DATA
|
||||
#define MYNEWT_VAL_ENC_ADV_DATA (0)
|
||||
#endif
|
||||
|
||||
/* Overridden by @apache-mynewt-nimble/porting/targets/riot (defined by @apache-mynewt-nimble/nimble) */
|
||||
#ifndef MYNEWT_VAL_BLE_HCI_VS
|
||||
#define MYNEWT_VAL_BLE_HCI_VS (1)
|
||||
@@ -1688,6 +1692,10 @@
|
||||
#define MYNEWT_VAL_BLE_STORE_MAX_CCCDS (8)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BT_NIMBLE_MAX_EADS
|
||||
#define MYNEWT_VAL_BLE_STORE_MAX_EADS CONFIG_BT_NIMBLE_MAX_EADS
|
||||
#endif
|
||||
|
||||
/*** @apache-mynewt-nimble/nimble/host/services/gap */
|
||||
#ifndef MYNEWT_VAL_BLE_SVC_GAP_APPEARANCE
|
||||
#define MYNEWT_VAL_BLE_SVC_GAP_APPEARANCE (0)
|
||||
|
||||
Reference in New Issue
Block a user