NimBLE: Added support of encrypted advertising data

This commit is contained in:
isha.pardikar@espressif.com
2023-04-27 10:45:36 +05:30
committed by Abhinav Kudnar
parent 4f635e7331
commit 066bfccb8b
21 changed files with 1395 additions and 6 deletions
+41
View File
@@ -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_ */
+132
View File
@@ -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
+42
View File
@@ -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 {
+45
View File
@@ -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)
{
+307
View File
@@ -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
+209
View File
@@ -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
+3
View File
@@ -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" {
+60 -1
View File
@@ -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;
+86 -1
View File
@@ -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)
+79 -3
View File
@@ -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;
+120
View File
@@ -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)
+8
View File
@@ -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)
+8
View File
@@ -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)