Bluetooth: SMP: Use TinyCrypt for AES CMAC
TinyCrypt provides implementation of AES CMAC so there is not need for internal implementation in SMP code. Change-Id: I15fe0daf8fca8c44b002636983b46502419c57a5 Signed-off-by: Szymon Janc <ext.szymon.janc@tieto.com>
This commit is contained in:
parent
c70c851ded
commit
3ed1a37a41
6 changed files with 27 additions and 172 deletions
|
@ -29,28 +29,21 @@ if BLUETOOTH
|
||||||
config BLUETOOTH_LE
|
config BLUETOOTH_LE
|
||||||
bool "Bluetooth Low Energy (LE) support"
|
bool "Bluetooth Low Energy (LE) support"
|
||||||
default n
|
default n
|
||||||
|
select TINYCRYPT
|
||||||
|
select TINYCRYPT_AES if BLUETOOTH_SMP
|
||||||
|
select TINYCRYPT_AES_CMAC if BLUETOOTH_SMP
|
||||||
|
select TINYCRYPT_SHA256
|
||||||
|
select TINYCRYPT_SHA256_HMAC
|
||||||
|
select TINYCRYPT_SHA256_HMAC_PRNG
|
||||||
help
|
help
|
||||||
This option enables Bluetooth Low Energy (LE) support.
|
This option enables Bluetooth Low Energy (LE) support.
|
||||||
Currently it is mandatory whenever Bluetooth support
|
Currently it is mandatory whenever Bluetooth support
|
||||||
(CONFIG_BLUETOOTH) is enabled.
|
(CONFIG_BLUETOOTH) is enabled.
|
||||||
|
|
||||||
if BLUETOOTH_LE
|
if BLUETOOTH_LE
|
||||||
config BLUETOOTH_TINYCRYPT
|
|
||||||
bool "Use TinyCrypt library"
|
|
||||||
default n
|
|
||||||
select TINYCRYPT
|
|
||||||
select TINYCRYPT_AES if BLUETOOTH_SMP
|
|
||||||
select TINYCRYPT_SHA256
|
|
||||||
select TINYCRYPT_SHA256_HMAC
|
|
||||||
select TINYCRYPT_SHA256_HMAC_PRNG
|
|
||||||
help
|
|
||||||
If this option is set TinyCrypt library is used for Bluetooth
|
|
||||||
cryptographic operations. If not set controller crypto is used.
|
|
||||||
|
|
||||||
config BLUETOOTH_TINYCRYPT_ECC
|
config BLUETOOTH_TINYCRYPT_ECC
|
||||||
bool "Use TinyCrypt library for ECDH"
|
bool "Use TinyCrypt library for ECDH"
|
||||||
default n
|
default n
|
||||||
depends on BLUETOOTH_TINYCRYPT
|
|
||||||
select TINYCRYPT_ECC_DH
|
select TINYCRYPT_ECC_DH
|
||||||
help
|
help
|
||||||
If this option is set TinyCrypt library is also used for LE Secure
|
If this option is set TinyCrypt library is also used for LE Secure
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
#if defined(CONFIG_TINYCRYPT_AES)
|
#if defined(CONFIG_TINYCRYPT_AES)
|
||||||
#include <tinycrypt/aes.h>
|
#include <tinycrypt/aes.h>
|
||||||
#include <tinycrypt/utils.h>
|
#include <tinycrypt/utils.h>
|
||||||
|
#include <tinycrypt/cmac_mode.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(CONFIG_TINYCRYPT_ECC_DH)
|
#if defined(CONFIG_TINYCRYPT_ECC_DH)
|
||||||
|
@ -267,17 +268,6 @@ static const char *h(const void *buf, size_t len)
|
||||||
#define BT_DBG(fmt, ...)
|
#define BT_DBG(fmt, ...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint64_t a;
|
|
||||||
uint64_t b;
|
|
||||||
} uint128_t;
|
|
||||||
|
|
||||||
static void xor_128(const uint128_t *p, const uint128_t *q, uint128_t *r)
|
|
||||||
{
|
|
||||||
r->a = p->a ^ q->a;
|
|
||||||
r->b = p->b ^ q->b;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* swap octets for LE encrypt */
|
/* swap octets for LE encrypt */
|
||||||
static void swap_buf(uint8_t *dst, const uint8_t *src, uint16_t len)
|
static void swap_buf(uint8_t *dst, const uint8_t *src, uint16_t len)
|
||||||
{
|
{
|
||||||
|
@ -389,68 +379,6 @@ static int smp_ah(const uint8_t irk[16], const uint8_t r[3], uint8_t out[3])
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 1 bit left shift */
|
|
||||||
static void array_shift(const uint8_t *in, uint8_t *out)
|
|
||||||
{
|
|
||||||
uint8_t overflow = 0;
|
|
||||||
|
|
||||||
for (int i = 15; i >= 0; i--) {
|
|
||||||
out[i] = in[i] << 1;
|
|
||||||
/* previous byte */
|
|
||||||
out[i] |= overflow;
|
|
||||||
overflow = in[i] & 0x80 ? 1 : 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* CMAC subkey generation algorithm */
|
|
||||||
static int cmac_subkey(const uint8_t *key, uint8_t *k1, uint8_t *k2)
|
|
||||||
{
|
|
||||||
static const uint8_t rb[16] = {
|
|
||||||
[0 ... 14] = 0x00,
|
|
||||||
[15] = 0x87,
|
|
||||||
};
|
|
||||||
uint8_t l[16] = { 0 };
|
|
||||||
int err;
|
|
||||||
|
|
||||||
/* L := AES-128(K, const_Zero) */
|
|
||||||
err = le_encrypt(key, l, l);
|
|
||||||
if (err) {
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
swap_in_place(l, 16);
|
|
||||||
|
|
||||||
BT_DBG("l %s", h(l, 16));
|
|
||||||
|
|
||||||
/* if MSB(L) == 0 K1 = L << 1 */
|
|
||||||
if (!(l[0] & 0x80)) {
|
|
||||||
array_shift(l, k1);
|
|
||||||
/* else K1 = (L << 1) XOR rb */
|
|
||||||
} else {
|
|
||||||
array_shift(l, k1);
|
|
||||||
xor_128((uint128_t *)k1, (uint128_t *)rb, (uint128_t *)k1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* if MSB(K1) == 0 K2 = K1 << 1 */
|
|
||||||
if (!(k1[0] & 0x80)) {
|
|
||||||
array_shift(k1, k2);
|
|
||||||
/* else K2 = (K1 << 1) XOR rb */
|
|
||||||
} else {
|
|
||||||
array_shift(k1, k2);
|
|
||||||
xor_128((uint128_t *)k2, (uint128_t *)rb, (uint128_t *)k2);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* padding(x) = x || 10^i where i is 128 - 8 * r - 1 */
|
|
||||||
static void add_pad(const uint8_t *in, unsigned char *out, int len)
|
|
||||||
{
|
|
||||||
memset(out, 0, 16);
|
|
||||||
memcpy(out, in, len);
|
|
||||||
out[len] = 0x80;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Cypher based Message Authentication Code (CMAC) with AES 128 bit
|
/* Cypher based Message Authentication Code (CMAC) with AES 128 bit
|
||||||
*
|
*
|
||||||
* Input : key ( 128-bit key )
|
* Input : key ( 128-bit key )
|
||||||
|
@ -461,95 +389,22 @@ static void add_pad(const uint8_t *in, unsigned char *out, int len)
|
||||||
static int bt_smp_aes_cmac(const uint8_t *key, const uint8_t *in, size_t len,
|
static int bt_smp_aes_cmac(const uint8_t *key, const uint8_t *in, size_t len,
|
||||||
uint8_t *out)
|
uint8_t *out)
|
||||||
{
|
{
|
||||||
uint8_t k1[16], k2[16], last_block[16], *pad_block = last_block;
|
struct tc_aes_key_sched_struct sched;
|
||||||
uint8_t key_s[16];
|
struct tc_cmac_struct state;
|
||||||
uint8_t *x, *y;
|
|
||||||
uint8_t n, flag;
|
|
||||||
int err;
|
|
||||||
|
|
||||||
swap_buf(key_s, key, 16);
|
if (tc_cmac_setup(&state, key, &sched) == TC_FAIL) {
|
||||||
|
return -EIO;
|
||||||
/* (K1,K2) = Generate_Subkey(K) */
|
|
||||||
err = cmac_subkey(key_s, k1, k2);
|
|
||||||
if (err) {
|
|
||||||
BT_ERR("SMAC subkey generation failed");
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BT_DBG("key %s subkeys k1 %s k2 %s", h(key, 16), h(k1, 16),
|
if (tc_cmac_update(&state, in, len) == TC_FAIL) {
|
||||||
h(k2, 16));
|
return -EIO;
|
||||||
|
|
||||||
/* the number of blocks, n, is calculated, the block length is 16 bytes
|
|
||||||
* n = ceil(len/const_Bsize)
|
|
||||||
*/
|
|
||||||
n = (len + 15) / 16;
|
|
||||||
|
|
||||||
/* check input length, flag indicate completed blocks */
|
|
||||||
if (n == 0) {
|
|
||||||
/* if length is 0, the number of blocks to be processed shall
|
|
||||||
* be 1,and the flag shall be marked as not-complete-block
|
|
||||||
* false
|
|
||||||
*/
|
|
||||||
n = 1;
|
|
||||||
flag = 0;
|
|
||||||
} else {
|
|
||||||
if ((len % 16) == 0) {
|
|
||||||
/* complete blocks */
|
|
||||||
flag = 1;
|
|
||||||
} else {
|
|
||||||
/* last block is not complete */
|
|
||||||
flag = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BT_DBG("len %u n %u flag %u", len, n, flag);
|
if (tc_cmac_final(out, &state) == TC_FAIL) {
|
||||||
|
return -EIO;
|
||||||
/* if flag is true then M_last = M_n XOR K1 */
|
|
||||||
if (flag) {
|
|
||||||
xor_128((uint128_t *)&in[16 * (n - 1)], (uint128_t *)k1,
|
|
||||||
(uint128_t *)last_block);
|
|
||||||
/* else M_last = padding(M_n) XOR K2 */
|
|
||||||
} else {
|
|
||||||
add_pad(&in[16 * (n - 1)], pad_block, len % 16);
|
|
||||||
xor_128((uint128_t *)pad_block, (uint128_t *)k2,
|
|
||||||
(uint128_t *)last_block);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reuse k1 and k2 buffers */
|
return 0;
|
||||||
x = k1;
|
|
||||||
y = k2;
|
|
||||||
|
|
||||||
/* Zeroing x */
|
|
||||||
memset(x, 0, 16);
|
|
||||||
|
|
||||||
/* the basic CBC-MAC is applied to M_1,...,M_{n-1},M_last */
|
|
||||||
for (int i = 0; i < n - 1; i++) {
|
|
||||||
/* Y = X XOR M_i */
|
|
||||||
xor_128((uint128_t *)x, (uint128_t *)&in[i * 16],
|
|
||||||
(uint128_t *)y);
|
|
||||||
|
|
||||||
swap_in_place(y, 16);
|
|
||||||
|
|
||||||
/* X = AES-128(K,Y) */
|
|
||||||
err = le_encrypt(key_s, y, x);
|
|
||||||
if (err) {
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
swap_in_place(x, 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Y = M_last XOR X */
|
|
||||||
xor_128((uint128_t *)x, (uint128_t *)last_block, (uint128_t *)y);
|
|
||||||
|
|
||||||
swap_in_place(y, 16);
|
|
||||||
|
|
||||||
/* T = AES-128(K,Y) */
|
|
||||||
err = le_encrypt(key_s, y, out);
|
|
||||||
|
|
||||||
swap_in_place(out, 16);
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int smp_f4(const uint8_t *u, const uint8_t *v, const uint8_t *x,
|
static int smp_f4(const uint8_t *u, const uint8_t *v, const uint8_t *x,
|
||||||
|
@ -863,6 +718,17 @@ static uint8_t get_encryption_key_size(struct bt_smp *smp)
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(CONFIG_BLUETOOTH_SMP_SC_ONLY)
|
#if !defined(CONFIG_BLUETOOTH_SMP_SC_ONLY)
|
||||||
|
typedef struct {
|
||||||
|
uint64_t a;
|
||||||
|
uint64_t b;
|
||||||
|
} uint128_t;
|
||||||
|
|
||||||
|
static void xor_128(const uint128_t *p, const uint128_t *q, uint128_t *r)
|
||||||
|
{
|
||||||
|
r->a = p->a ^ q->a;
|
||||||
|
r->b = p->b ^ q->b;
|
||||||
|
}
|
||||||
|
|
||||||
static int smp_c1(const uint8_t k[16], const uint8_t r[16],
|
static int smp_c1(const uint8_t k[16], const uint8_t r[16],
|
||||||
const uint8_t preq[7], const uint8_t pres[7],
|
const uint8_t preq[7], const uint8_t pres[7],
|
||||||
const bt_addr_le_t *ia, const bt_addr_le_t *ra,
|
const bt_addr_le_t *ia, const bt_addr_le_t *ra,
|
||||||
|
|
|
@ -3,7 +3,6 @@ CONFIG_BLUETOOTH_LE=y
|
||||||
CONFIG_BLUETOOTH_DEBUG=y
|
CONFIG_BLUETOOTH_DEBUG=y
|
||||||
CONFIG_BLUETOOTH_SMP=y
|
CONFIG_BLUETOOTH_SMP=y
|
||||||
CONFIG_BLUETOOTH_SIGNING=y
|
CONFIG_BLUETOOTH_SIGNING=y
|
||||||
CONFIG_BLUETOOTH_TINYCRYPT=y
|
|
||||||
CONFIG_BLUETOOTH_PERIPHERAL=y
|
CONFIG_BLUETOOTH_PERIPHERAL=y
|
||||||
CONFIG_BLUETOOTH_L2CAP_DYNAMIC_CHANNEL=y
|
CONFIG_BLUETOOTH_L2CAP_DYNAMIC_CHANNEL=y
|
||||||
CONFIG_NETWORKING=y
|
CONFIG_NETWORKING=y
|
||||||
|
|
|
@ -3,6 +3,5 @@ CONFIG_BLUETOOTH_LE=y
|
||||||
CONFIG_BLUETOOTH_DEBUG=y
|
CONFIG_BLUETOOTH_DEBUG=y
|
||||||
CONFIG_BLUETOOTH_SMP=y
|
CONFIG_BLUETOOTH_SMP=y
|
||||||
CONFIG_BLUETOOTH_SIGNING=y
|
CONFIG_BLUETOOTH_SIGNING=y
|
||||||
CONFIG_BLUETOOTH_TINYCRYPT=y
|
|
||||||
CONFIG_BLUETOOTH_PERIPHERAL=y
|
CONFIG_BLUETOOTH_PERIPHERAL=y
|
||||||
CONFIG_BLUETOOTH_GATT_DYNAMIC_DB=y
|
CONFIG_BLUETOOTH_GATT_DYNAMIC_DB=y
|
||||||
|
|
|
@ -2,6 +2,5 @@ CONFIG_BLUETOOTH=y
|
||||||
CONFIG_BLUETOOTH_LE=y
|
CONFIG_BLUETOOTH_LE=y
|
||||||
CONFIG_BLUETOOTH_DEBUG=y
|
CONFIG_BLUETOOTH_DEBUG=y
|
||||||
CONFIG_BLUETOOTH_SMP=y
|
CONFIG_BLUETOOTH_SMP=y
|
||||||
CONFIG_BLUETOOTH_TINYCRYPT=y
|
|
||||||
CONFIG_BLUETOOTH_PERIPHERAL=y
|
CONFIG_BLUETOOTH_PERIPHERAL=y
|
||||||
CONFIG_BLUETOOTH_GATT_DYNAMIC_DB=y
|
CONFIG_BLUETOOTH_GATT_DYNAMIC_DB=y
|
||||||
|
|
|
@ -10,6 +10,5 @@ CONFIG_BLUETOOTH_SMP=y
|
||||||
CONFIG_BLUETOOTH_SIGNING=y
|
CONFIG_BLUETOOTH_SIGNING=y
|
||||||
CONFIG_BLUETOOTH_GATT_CLIENT=y
|
CONFIG_BLUETOOTH_GATT_CLIENT=y
|
||||||
CONFIG_BLUETOOTH_L2CAP_DYNAMIC_CHANNEL=y
|
CONFIG_BLUETOOTH_L2CAP_DYNAMIC_CHANNEL=y
|
||||||
CONFIG_BLUETOOTH_TINYCRYPT=y
|
|
||||||
CONFIG_BLUETOOTH_TINYCRYPT_ECC=y
|
CONFIG_BLUETOOTH_TINYCRYPT_ECC=y
|
||||||
CONFIG_CONSOLE_HANDLER_SHELL=y
|
CONFIG_CONSOLE_HANDLER_SHELL=y
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue