126 lines
2.8 KiB
C
126 lines
2.8 KiB
C
/**
|
|
* @file rpa.c
|
|
* Resolvable Private Address Generation and Resolution
|
|
*/
|
|
|
|
/*
|
|
* Copyright (c) 2017 Nordic Semiconductor ASA
|
|
* Copyright (c) 2015-2016 Intel Corporation
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include <zephyr.h>
|
|
#include <stddef.h>
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
|
|
#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_RPA)
|
|
#define LOG_MODULE_NAME bt_rpa
|
|
#include "common/log.h"
|
|
|
|
#include <bluetooth/crypto.h>
|
|
|
|
#if defined(CONFIG_BT_CTLR) && defined(CONFIG_BT_HOST_CRYPTO)
|
|
#include "../controller/util/util.h"
|
|
#include "../controller/hal/ecb.h"
|
|
#endif /* defined(CONFIG_BT_CTLR) && defined(CONFIG_BT_HOST_CRYPTO) */
|
|
|
|
#if defined(CONFIG_BT_PRIVACY) || defined(CONFIG_BT_CTLR_PRIVACY)
|
|
static int internal_rand(void *buf, size_t len)
|
|
{
|
|
/* Force using controller rand function. */
|
|
#if defined(CONFIG_BT_CTLR) && defined(CONFIG_BT_HOST_CRYPTO)
|
|
return lll_csrand_get(buf, len);
|
|
#else
|
|
return bt_rand(buf, len);
|
|
#endif
|
|
}
|
|
#endif /* defined(CONFIG_BT_PRIVACY) || defined(CONFIG_BT_CTLR_PRIVACY) */
|
|
|
|
static int internal_encrypt_le(const uint8_t key[16], const uint8_t plaintext[16],
|
|
uint8_t enc_data[16])
|
|
{
|
|
/* Force using controller encrypt function if supported. */
|
|
#if defined(CONFIG_BT_CTLR) && defined(CONFIG_BT_HOST_CRYPTO) && \
|
|
defined(CONFIG_BT_CTLR_LE_ENC)
|
|
ecb_encrypt(key, plaintext, enc_data, NULL);
|
|
return 0;
|
|
#else
|
|
return bt_encrypt_le(key, plaintext, enc_data);
|
|
#endif
|
|
}
|
|
|
|
static int ah(const uint8_t irk[16], const uint8_t r[3], uint8_t out[3])
|
|
{
|
|
uint8_t res[16];
|
|
int err;
|
|
|
|
BT_DBG("irk %s", bt_hex(irk, 16));
|
|
BT_DBG("r %s", bt_hex(r, 3));
|
|
|
|
/* r' = padding || r */
|
|
memcpy(res, r, 3);
|
|
(void)memset(res + 3, 0, 13);
|
|
|
|
err = internal_encrypt_le(irk, res, res);
|
|
if (err) {
|
|
return err;
|
|
}
|
|
|
|
/* The output of the random address function ah is:
|
|
* ah(h, r) = e(k, r') mod 2^24
|
|
* The output of the security function e is then truncated to 24 bits
|
|
* by taking the least significant 24 bits of the output of e as the
|
|
* result of ah.
|
|
*/
|
|
memcpy(out, res, 3);
|
|
|
|
return 0;
|
|
}
|
|
|
|
#if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_CTLR_PRIVACY)
|
|
bool bt_rpa_irk_matches(const uint8_t irk[16], const bt_addr_t *addr)
|
|
{
|
|
uint8_t hash[3];
|
|
int err;
|
|
|
|
BT_DBG("IRK %s bdaddr %s", bt_hex(irk, 16), bt_addr_str(addr));
|
|
|
|
err = ah(irk, addr->val + 3, hash);
|
|
if (err) {
|
|
return false;
|
|
}
|
|
|
|
return !memcmp(addr->val, hash, 3);
|
|
}
|
|
#endif
|
|
|
|
#if defined(CONFIG_BT_PRIVACY) || defined(CONFIG_BT_CTLR_PRIVACY)
|
|
int bt_rpa_create(const uint8_t irk[16], bt_addr_t *rpa)
|
|
{
|
|
int err;
|
|
|
|
err = internal_rand(rpa->val + 3, 3);
|
|
if (err) {
|
|
return err;
|
|
}
|
|
|
|
BT_ADDR_SET_RPA(rpa);
|
|
|
|
err = ah(irk, rpa->val + 3, rpa->val);
|
|
if (err) {
|
|
return err;
|
|
}
|
|
|
|
BT_DBG("Created RPA %s", bt_addr_str((bt_addr_t *)rpa->val));
|
|
|
|
return 0;
|
|
}
|
|
#else
|
|
int bt_rpa_create(const uint8_t irk[16], bt_addr_t *rpa)
|
|
{
|
|
return -ENOTSUP;
|
|
}
|
|
#endif /* CONFIG_BT_PRIVACY */
|