Bluetooth: audio: csis: Fix Big Endianness for RSI generation

This changes so that generation of RSI now uses LE arrays instead of
uint32 words. Both input and output of rsi and sih genration now uses
LE. This also fixes the generation of RSI for BE systems, which
wasn't working.

Signed-off-by: Fredrik Danebjer <fredrik@danebjer.com>
This commit is contained in:
Fredrik Danebjer 2023-03-22 07:59:58 +01:00 committed by Carles Cufí
parent 1fa3f71f76
commit 7e416c8ec0
5 changed files with 51 additions and 52 deletions

View file

@ -43,7 +43,7 @@ extern "C" {
#define BT_CSIP_READ_SIRK_REQ_RSP_OOB_ONLY 0x03
/** Size of the Set Identification Resolving Key (SIRK) */
#define BT_CSIP_SET_SIRK_SIZE 16
#define BT_CSIP_SET_SIRK_SIZE 16
/** Size of the Resolvable Set Identifier (RSI) */
#define BT_CSIP_RSI_SIZE 6
@ -199,7 +199,7 @@ void bt_csip_set_member_print_sirk(const struct bt_csip_set_member_svc_inst *svc
* This will generate RSI for given @p svc_inst instance.
*
* @param svc_inst Pointer to the Coordinated Set Identification Service.
* @param rsi Pointer to the 6-octet newly generated RSI data.
* @param rsi Pointer to the 6-octet newly generated RSI data in little-endian.
*
* @return int 0 if on success, errno on error.
*/

View file

@ -25,7 +25,7 @@
LOG_MODULE_REGISTER(bt_csip_crypto, CONFIG_BT_CSIP_SET_MEMBER_CRYPTO_LOG_LEVEL);
#define BT_CSIP_CRYPTO_PADDING_SIZE 13
#define BT_CSIP_R_SIZE 3 /* r is 24 bit / 3 octet */
#define BT_CSIP_PADDED_RAND_SIZE (BT_CSIP_CRYPTO_PADDING_SIZE + BT_CSIP_CRYPTO_PRAND_SIZE)
#define BT_CSIP_R_MASK BIT_MASK(24) /* r is 24 bit / 3 octet */
static int aes_cmac(const uint8_t key[BT_CSIP_CRYPTO_KEY_SIZE],
@ -61,34 +61,27 @@ static void xor_128(const uint8_t a[16], const uint8_t b[16], uint8_t out[16])
}
}
int bt_csip_sih(const uint8_t sirk[BT_CSIP_SET_SIRK_SIZE], uint32_t r,
uint32_t *out)
int bt_csip_sih(const uint8_t sirk[BT_CSIP_SET_SIRK_SIZE], uint8_t r[BT_CSIP_CRYPTO_PRAND_SIZE],
uint8_t out[BT_CSIP_CRYPTO_HASH_SIZE])
{
uint8_t res[16]; /* need to store 128 bit */
uint8_t res[BT_CSIP_PADDED_RAND_SIZE]; /* need to store 128 bit */
int err;
uint8_t sirk_tmp[BT_CSIP_SET_SIRK_SIZE];
if ((r & BIT(23)) || ((r & BIT(22)) == 0)) {
LOG_DBG("Invalid r %0x06x", (uint32_t)(r & BT_CSIP_R_MASK));
if ((r[BT_CSIP_CRYPTO_PRAND_SIZE - 1] & BIT(7)) ||
((r[BT_CSIP_CRYPTO_PRAND_SIZE - 1] & BIT(6)) == 0)) {
LOG_DBG("Invalid r %s", bt_hex(r, BT_CSIP_CRYPTO_PRAND_SIZE));
}
LOG_DBG("SIRK %s", bt_hex(sirk, BT_CSIP_SET_SIRK_SIZE));
LOG_DBG("r 0x%06x", r);
LOG_DBG("r %s", bt_hex(r, BT_CSIP_CRYPTO_PRAND_SIZE));
/* r' = padding || r */
(void)memset(res, 0, BT_CSIP_CRYPTO_PADDING_SIZE);
sys_put_be24(r, res + BT_CSIP_CRYPTO_PADDING_SIZE);
(void)memset(res + BT_CSIP_CRYPTO_PRAND_SIZE, 0, BT_CSIP_CRYPTO_PADDING_SIZE);
memcpy(res, r, BT_CSIP_CRYPTO_PRAND_SIZE);
LOG_DBG("BE: r' %s", bt_hex(res, sizeof(res)));
LOG_DBG("r' %s", bt_hex(res, sizeof(res)));
if (IS_ENABLED(CONFIG_LITTLE_ENDIAN)) {
/* Swap to Big Endian (BE) */
sys_memcpy_swap(sirk_tmp, sirk, BT_CSIP_SET_SIRK_SIZE);
} else {
(void)memcpy(sirk_tmp, sirk, BT_CSIP_SET_SIRK_SIZE);
}
err = bt_encrypt_be(sirk_tmp, res, res);
err = bt_encrypt_le(sirk, res, res);
if (err != 0) {
return err;
@ -101,12 +94,12 @@ int bt_csip_sih(const uint8_t sirk[BT_CSIP_SET_SIRK_SIZE], uint32_t r,
* result of sih.
*/
LOG_DBG("BE: res %s", bt_hex(res, sizeof(res)));
LOG_DBG("res %s", bt_hex(res, sizeof(res)));
/* Result is the lowest 3 bytes */
*out = sys_get_be24(res + 13);
memcpy(out, res, BT_CSIP_CRYPTO_HASH_SIZE);
LOG_DBG("sih 0x%06x", *out);
LOG_DBG("sih %s", bt_hex(out, BT_CSIP_CRYPTO_HASH_SIZE));
return 0;
}

View file

@ -12,6 +12,8 @@
#define BT_CSIP_CRYPTO_KEY_SIZE 16
#define BT_CSIP_CRYPTO_SALT_SIZE 16
#define BT_CSIP_CRYPTO_PRAND_SIZE 3
#define BT_CSIP_CRYPTO_HASH_SIZE 3
/**
* @brief Private Set Unique identifier hash function sih.
@ -20,13 +22,14 @@
* used in RSIs - Used by the Coordinated Set Identification service and
* profile.
*
* @param sirk The 16-byte SIRK
* @param r 3 byte random value
* @param out The 3 byte output buffer
* @param sirk 16 byte LS byte first SIRK
* @param r 3 byte LS byte first random value
* @param out 3 byte LS byte first output buffer
* @return int 0 on success, any other value indicates a failure.
*/
int bt_csip_sih(const uint8_t sirk[BT_CSIP_SET_SIRK_SIZE], uint32_t r,
uint32_t *out);
int bt_csip_sih(const uint8_t sirk[BT_CSIP_SET_SIRK_SIZE],
uint8_t r[BT_CSIP_CRYPTO_PRAND_SIZE],
uint8_t out[BT_CSIP_CRYPTO_HASH_SIZE]);
/**
* @brief SIRK encryption function sef

View file

@ -36,6 +36,7 @@
#include "csip_internal.h"
#include "../host/conn_internal.h"
#include "../host/keys.h"
#include "common/bt_str.h"
#include <zephyr/logging/log.h>
@ -804,22 +805,24 @@ bool bt_csip_set_coordinator_is_set_member(const uint8_t set_sirk[BT_CSIP_SET_SI
if (data->type == BT_DATA_CSIS_RSI &&
data->data_len == BT_CSIP_RSI_SIZE) {
uint8_t err;
uint8_t hash[BT_CSIP_CRYPTO_HASH_SIZE];
uint8_t prand[BT_CSIP_CRYPTO_PRAND_SIZE];
uint8_t calculated_hash[BT_CSIP_CRYPTO_HASH_SIZE];
uint32_t hash = sys_get_le24(data->data);
uint32_t prand = sys_get_le24(data->data + 3);
uint32_t calculated_hash;
memcpy(hash, data->data, BT_CSIP_CRYPTO_HASH_SIZE);
memcpy(prand, data->data + BT_CSIP_CRYPTO_HASH_SIZE, BT_CSIP_CRYPTO_PRAND_SIZE);
LOG_DBG("hash: 0x%06x, prand 0x%06x", hash, prand);
err = bt_csip_sih(set_sirk, prand, &calculated_hash);
LOG_DBG("hash: %s", bt_hex(hash, BT_CSIP_CRYPTO_HASH_SIZE));
LOG_DBG("prand %s", bt_hex(prand, BT_CSIP_CRYPTO_PRAND_SIZE));
err = bt_csip_sih(set_sirk, prand, calculated_hash);
if (err != 0) {
return false;
}
calculated_hash &= 0xffffff;
LOG_DBG("calculated_hash: %s", bt_hex(calculated_hash, BT_CSIP_CRYPTO_HASH_SIZE));
LOG_DBG("hash: %s", bt_hex(hash, BT_CSIP_CRYPTO_HASH_SIZE));
LOG_DBG("calculated_hash: 0x%06x, hash 0x%06x", calculated_hash, hash);
return calculated_hash == hash;
return memcmp(calculated_hash, hash, BT_CSIP_CRYPTO_HASH_SIZE) == 0;
}
return false;

View file

@ -28,8 +28,6 @@
#include "../host/hci_core.h"
#include "../host/keys.h"
#define BT_CSIP_SIH_PRAND_SIZE 3
#define BT_CSIP_SIH_HASH_SIZE 3
#define CSIP_SET_LOCK_TIMER_VALUE K_SECONDS(60)
#include "common/bt_str.h"
@ -173,27 +171,29 @@ static int sirk_encrypt(struct bt_conn *conn,
return 0;
}
static int generate_prand(uint32_t *dest)
static int generate_prand(uint8_t dest[BT_CSIP_CRYPTO_PRAND_SIZE])
{
bool valid = false;
do {
int res;
uint32_t prand;
*dest = 0;
res = bt_rand(dest, BT_CSIP_SIH_PRAND_SIZE);
res = bt_rand(dest, BT_CSIP_CRYPTO_PRAND_SIZE);
if (res != 0) {
return res;
}
/* Validate Prand: Must contain both a 1 and a 0 */
if (*dest != 0 && *dest != 0x3FFFFF) {
prand = sys_get_le24(dest);
if (prand != 0 && prand != 0x3FFFFF) {
valid = true;
}
} while (!valid);
*dest &= 0x3FFFFF;
*dest |= BIT(22); /* bit 23 shall be 0, and bit 22 shall be 1 */
dest[BT_CSIP_CRYPTO_PRAND_SIZE - 1] &= 0x3F;
dest[BT_CSIP_CRYPTO_PRAND_SIZE - 1] |= BIT(6);
return 0;
}
@ -202,14 +202,14 @@ int bt_csip_set_member_generate_rsi(const struct bt_csip_set_member_svc_inst *sv
uint8_t rsi[BT_CSIP_RSI_SIZE])
{
int res = 0;
uint32_t prand;
uint32_t hash;
uint8_t prand[BT_CSIP_CRYPTO_PRAND_SIZE];
uint8_t hash[BT_CSIP_CRYPTO_HASH_SIZE];
if (IS_ENABLED(CONFIG_BT_CSIP_SET_MEMBER_TEST_SAMPLE_DATA)) {
/* prand is from the sample data from A.2 in the CSIS spec */
prand = 0x69f563;
sys_put_le24(0x69f563, prand);
} else {
res = generate_prand(&prand);
res = generate_prand(prand);
if (res != 0) {
LOG_WRN("Could not generate new prand");
@ -217,14 +217,14 @@ int bt_csip_set_member_generate_rsi(const struct bt_csip_set_member_svc_inst *sv
}
}
res = bt_csip_sih(svc_inst->set_sirk.value, prand, &hash);
res = bt_csip_sih(svc_inst->set_sirk.value, prand, hash);
if (res != 0) {
LOG_WRN("Could not generate new RSI");
return res;
}
(void)memcpy(rsi, &hash, BT_CSIP_SIH_HASH_SIZE);
(void)memcpy(rsi + BT_CSIP_SIH_HASH_SIZE, &prand, BT_CSIP_SIH_PRAND_SIZE);
(void)memcpy(rsi, hash, BT_CSIP_CRYPTO_HASH_SIZE);
(void)memcpy(rsi + BT_CSIP_CRYPTO_HASH_SIZE, prand, BT_CSIP_CRYPTO_PRAND_SIZE);
return res;
}