test: Bluetooth: tester: Add support for EAD peripheral
Added three functions to support the EAD peripheral:
- Setting and storing key materials for EAD
- Encrypting data for EAD advertisements
- Decrypting data from EAD advertisements
Signed-off-by: Petri Pitkanen <petri.pitkanen@silabs.com>
This commit is contained in:
committed by
Chris Friedt
parent
47abb0c65d
commit
f04d0196de
@@ -393,6 +393,37 @@ struct btp_gap_set_rpa_timeout_cmd {
|
||||
uint16_t rpa_timeout;
|
||||
} __packed;
|
||||
|
||||
#define BTP_GAP_EAD_SET_KEY_MATERIAL_KEY_SIZE 16
|
||||
#define BTP_GAP_EAD_SET_KEY_MATERIAL_IV_SIZE 8
|
||||
#define BTP_GAP_EAD_MAX_DATA_LEN 255
|
||||
#define BTP_GAP_EAD_SET_KEY_MATERIAL 0x31
|
||||
struct btp_gap_ead_set_key_material_cmd {
|
||||
uint8_t session_key[BTP_GAP_EAD_SET_KEY_MATERIAL_KEY_SIZE];
|
||||
uint8_t initialization_vector[BTP_GAP_EAD_SET_KEY_MATERIAL_IV_SIZE];
|
||||
} __packed;
|
||||
|
||||
#define BTP_GAP_EAD_ENCRYPT_ADV_DATA 0x32
|
||||
struct btp_gap_ead_encrypt_adv_data_cmd {
|
||||
uint8_t adv_data_len;
|
||||
uint8_t adv_data[];
|
||||
} __packed;
|
||||
|
||||
struct btp_gap_ead_encrypt_adv_data_rp {
|
||||
uint8_t encrypted_data_len;
|
||||
uint8_t encrypted_data[];
|
||||
} __packed;
|
||||
|
||||
#define BTP_GAP_EAD_DECRYPT_ADV_DATA 0x33
|
||||
struct btp_gap_ead_decrypt_adv_data_cmd {
|
||||
uint8_t encrypted_data_len;
|
||||
uint8_t encrypted_data[];
|
||||
} __packed;
|
||||
|
||||
struct btp_gap_decrypt_ead_adv_data_rp {
|
||||
uint8_t decrypted_data_len;
|
||||
uint8_t decrypted_data[];
|
||||
} __packed;
|
||||
|
||||
/* events */
|
||||
#define BTP_GAP_EV_NEW_SETTINGS 0x80
|
||||
struct btp_gap_new_settings_ev {
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <zephyr/bluetooth/gap.h>
|
||||
#include <zephyr/bluetooth/hci_types.h>
|
||||
#include <zephyr/bluetooth/uuid.h>
|
||||
#include <zephyr/bluetooth/ead.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/sys/atomic.h>
|
||||
#include <zephyr/sys/util.h>
|
||||
@@ -2831,6 +2832,85 @@ static uint8_t bis_broadcast(const void *cmd, uint16_t cmd_len, void *rsp, uint1
|
||||
}
|
||||
#endif /* defined(CONFIG_BT_ISO_BROADCASTER) */
|
||||
|
||||
#if defined(CONFIG_BT_EAD)
|
||||
static struct ead_key_materials_s {
|
||||
uint8_t session_key[BTP_GAP_EAD_SET_KEY_MATERIAL_KEY_SIZE];
|
||||
uint8_t initialization_vector[BTP_GAP_EAD_SET_KEY_MATERIAL_IV_SIZE];
|
||||
} ead_key_materials;
|
||||
|
||||
/*
|
||||
* This command to be used by both central and peripheral.
|
||||
* central side should get key material by reading them from the peripheral
|
||||
* gatt database. Obviously key materials can be shared OOB as well.
|
||||
*/
|
||||
static uint8_t ead_set_key_material(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len)
|
||||
{
|
||||
const struct btp_gap_ead_set_key_material_cmd *cp = cmd;
|
||||
|
||||
(void)memcpy(ead_key_materials.session_key, cp->session_key,
|
||||
sizeof(ead_key_materials.session_key));
|
||||
(void)memcpy(ead_key_materials.initialization_vector, cp->initialization_vector,
|
||||
sizeof(ead_key_materials.initialization_vector));
|
||||
|
||||
return BTP_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static uint8_t ead_encrypt_data(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len)
|
||||
{
|
||||
const struct btp_gap_ead_encrypt_adv_data_cmd *cp = cmd;
|
||||
struct btp_gap_ead_encrypt_adv_data_rp *rp = rsp;
|
||||
int err;
|
||||
size_t encrypted_size;
|
||||
|
||||
if ((cmd_len < sizeof(*cp)) || (cmd_len != sizeof(*cp) + cp->adv_data_len)) {
|
||||
return BTP_STATUS_FAILED;
|
||||
}
|
||||
|
||||
encrypted_size = BT_EAD_ENCRYPTED_PAYLOAD_SIZE(cp->adv_data_len);
|
||||
if (encrypted_size > BTP_GAP_EAD_MAX_DATA_LEN) {
|
||||
LOG_ERR("Plain text data length exceeds max supported");
|
||||
return BTP_STATUS_FAILED;
|
||||
}
|
||||
|
||||
err = bt_ead_encrypt(ead_key_materials.session_key, ead_key_materials.initialization_vector,
|
||||
cp->adv_data, cp->adv_data_len, rp->encrypted_data);
|
||||
|
||||
if (err < 0) {
|
||||
LOG_ERR("Failed to encrypt data: %d", err);
|
||||
return BTP_STATUS_FAILED;
|
||||
}
|
||||
|
||||
rp->encrypted_data_len = encrypted_size;
|
||||
*rsp_len = sizeof(*rp) + rp->encrypted_data_len;
|
||||
|
||||
return BTP_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static uint8_t ead_decrypt_data(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len)
|
||||
{
|
||||
const struct btp_gap_ead_decrypt_adv_data_cmd *cp = cmd;
|
||||
struct btp_gap_decrypt_ead_adv_data_rp *rp = rsp;
|
||||
int err;
|
||||
|
||||
if ((cmd_len < sizeof(*cp)) || (cmd_len != sizeof(*cp) + cp->encrypted_data_len)) {
|
||||
return BTP_STATUS_FAILED;
|
||||
}
|
||||
|
||||
err = bt_ead_decrypt(ead_key_materials.session_key, ead_key_materials.initialization_vector,
|
||||
cp->encrypted_data, cp->encrypted_data_len, rp->decrypted_data);
|
||||
|
||||
if (err < 0) {
|
||||
LOG_ERR("Failed to decrypt data: %d", err);
|
||||
return BTP_STATUS_FAILED;
|
||||
}
|
||||
|
||||
rp->decrypted_data_len = BT_EAD_DECRYPTED_PAYLOAD_SIZE(cp->encrypted_data_len);
|
||||
*rsp_len = sizeof(*rp) + rp->decrypted_data_len;
|
||||
|
||||
return BTP_STATUS_SUCCESS;
|
||||
}
|
||||
#endif /* defined(CONFIG_BT_EAD) */
|
||||
|
||||
static const struct btp_handler handlers[] = {
|
||||
{
|
||||
.opcode = BTP_GAP_READ_SUPPORTED_COMMANDS,
|
||||
@@ -3045,6 +3125,23 @@ static const struct btp_handler handlers[] = {
|
||||
.func = bis_broadcast,
|
||||
},
|
||||
#endif /* defined(CONFIG_BT_ISO_BROADCASTER) */
|
||||
#if defined(CONFIG_BT_EAD)
|
||||
{
|
||||
.opcode = BTP_GAP_EAD_SET_KEY_MATERIAL,
|
||||
.expect_len = sizeof(struct btp_gap_ead_set_key_material_cmd),
|
||||
.func = ead_set_key_material,
|
||||
},
|
||||
{
|
||||
.opcode = BTP_GAP_EAD_ENCRYPT_ADV_DATA,
|
||||
.expect_len = BTP_HANDLER_LENGTH_VARIABLE,
|
||||
.func = ead_encrypt_data,
|
||||
},
|
||||
{
|
||||
.opcode = BTP_GAP_EAD_DECRYPT_ADV_DATA,
|
||||
.expect_len = BTP_HANDLER_LENGTH_VARIABLE,
|
||||
.func = ead_decrypt_data,
|
||||
},
|
||||
#endif /* defined(CONFIG_BT_EAD) */
|
||||
};
|
||||
|
||||
uint8_t tester_init_gap(void)
|
||||
|
||||
Reference in New Issue
Block a user