Skip to content

Commit

Permalink
nimble: Added support of encrypted advertising data
Browse files Browse the repository at this point in the history
  • Loading branch information
IshaESP committed May 23, 2023
1 parent 550d5a7 commit a468059
Show file tree
Hide file tree
Showing 22 changed files with 1,252 additions and 2 deletions.
41 changes: 41 additions & 0 deletions nimble/host/include/host/ble_aes_ccm.h
Original file line number Diff line number Diff line change
@@ -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(BLE_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 changes: 132 additions & 0 deletions nimble/host/include/host/ble_ead.h
Original file line number Diff line number Diff line change
@@ -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(BLE_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 changes: 42 additions & 0 deletions nimble/host/include/host/ble_gap.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@
#include "host/ble_hs_adv.h"
#include "syscfg/syscfg.h"

#if MYNEWT_VAL(BLE_ENC_ADV_DATA)
#include "../../src/ble_hs_hci_priv.h"
#endif

#ifdef __cplusplus
extern "C" {
#endif
Expand Down Expand Up @@ -1261,6 +1265,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(BLE_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 {
Expand Down
48 changes: 47 additions & 1 deletion nimble/host/include/host/ble_store.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ extern "C" {
#define BLE_STORE_OBJ_TYPE_PEER_SEC 2
#define BLE_STORE_OBJ_TYPE_CCCD 3

#if MYNEWT_VAL(BLE_ENC_ADV_DATA)
#define BLE_STORE_OBJ_TYPE_ENC_ADV_DATA 4
#endif

/** Failed to persist record; insufficient storage capacity. */
#define BLE_STORE_EVENT_OVERFLOW 1

Expand Down Expand Up @@ -112,13 +116,44 @@ struct ble_store_value_cccd {
unsigned value_changed:1;
};

#if MYNEWT_VAL(BLE_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.
*/
union ble_store_key {
struct ble_store_key_sec sec;
struct ble_store_key_cccd cccd;
#if MYNEWT_VAL(BLE_ENC_ADV_DATA)
struct ble_store_key_ead ead;
#endif

};

/**
Expand All @@ -128,6 +163,10 @@ union ble_store_key {
union ble_store_value {
struct ble_store_value_sec sec;
struct ble_store_value_cccd cccd;
#if MYNEWT_VAL(BLE_ENC_ADV_DATA)
struct ble_store_value_ead ead;
#endif

};

struct ble_store_status_event {
Expand Down Expand Up @@ -298,7 +337,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(BLE_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,
const union ble_store_value *value);
Expand Down
12 changes: 11 additions & 1 deletion nimble/host/services/gap/include/services/gap/ble_svc_gap.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@
#define H_BLE_SVC_GAP_

#include <inttypes.h>

#include "syscfg/syscfg.h"
#if MYNEWT_VAL(BLE_ENC_ADV_DATA)
#include "host/ble_ead.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
Expand All @@ -32,6 +35,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(BLE_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
Expand All @@ -45,6 +52,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(BLE_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);

Expand Down

0 comments on commit a468059

Please sign in to comment.