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:
Szymon Janc 2016-02-11 14:38:32 +01:00 committed by Gerrit Code Review
commit 3ed1a37a41
6 changed files with 27 additions and 172 deletions

View file

@ -29,28 +29,21 @@ if BLUETOOTH
config BLUETOOTH_LE
bool "Bluetooth Low Energy (LE) support"
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
This option enables Bluetooth Low Energy (LE) support.
Currently it is mandatory whenever Bluetooth support
(CONFIG_BLUETOOTH) is enabled.
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
bool "Use TinyCrypt library for ECDH"
default n
depends on BLUETOOTH_TINYCRYPT
select TINYCRYPT_ECC_DH
help
If this option is set TinyCrypt library is also used for LE Secure

View file

@ -37,6 +37,7 @@
#if defined(CONFIG_TINYCRYPT_AES)
#include <tinycrypt/aes.h>
#include <tinycrypt/utils.h>
#include <tinycrypt/cmac_mode.h>
#endif
#if defined(CONFIG_TINYCRYPT_ECC_DH)
@ -267,17 +268,6 @@ static const char *h(const void *buf, size_t len)
#define BT_DBG(fmt, ...)
#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 */
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;
}
/* 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
*
* 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,
uint8_t *out)
{
uint8_t k1[16], k2[16], last_block[16], *pad_block = last_block;
uint8_t key_s[16];
uint8_t *x, *y;
uint8_t n, flag;
int err;
struct tc_aes_key_sched_struct sched;
struct tc_cmac_struct state;
swap_buf(key_s, key, 16);
/* (K1,K2) = Generate_Subkey(K) */
err = cmac_subkey(key_s, k1, k2);
if (err) {
BT_ERR("SMAC subkey generation failed");
return err;
if (tc_cmac_setup(&state, key, &sched) == TC_FAIL) {
return -EIO;
}
BT_DBG("key %s subkeys k1 %s k2 %s", h(key, 16), h(k1, 16),
h(k2, 16));
/* 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;
}
if (tc_cmac_update(&state, in, len) == TC_FAIL) {
return -EIO;
}
BT_DBG("len %u n %u flag %u", len, n, flag);
/* 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);
if (tc_cmac_final(out, &state) == TC_FAIL) {
return -EIO;
}
/* Reuse k1 and k2 buffers */
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;
return 0;
}
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)
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],
const uint8_t preq[7], const uint8_t pres[7],
const bt_addr_le_t *ia, const bt_addr_le_t *ra,

View file

@ -3,7 +3,6 @@ CONFIG_BLUETOOTH_LE=y
CONFIG_BLUETOOTH_DEBUG=y
CONFIG_BLUETOOTH_SMP=y
CONFIG_BLUETOOTH_SIGNING=y
CONFIG_BLUETOOTH_TINYCRYPT=y
CONFIG_BLUETOOTH_PERIPHERAL=y
CONFIG_BLUETOOTH_L2CAP_DYNAMIC_CHANNEL=y
CONFIG_NETWORKING=y

View file

@ -3,6 +3,5 @@ CONFIG_BLUETOOTH_LE=y
CONFIG_BLUETOOTH_DEBUG=y
CONFIG_BLUETOOTH_SMP=y
CONFIG_BLUETOOTH_SIGNING=y
CONFIG_BLUETOOTH_TINYCRYPT=y
CONFIG_BLUETOOTH_PERIPHERAL=y
CONFIG_BLUETOOTH_GATT_DYNAMIC_DB=y

View file

@ -2,6 +2,5 @@ CONFIG_BLUETOOTH=y
CONFIG_BLUETOOTH_LE=y
CONFIG_BLUETOOTH_DEBUG=y
CONFIG_BLUETOOTH_SMP=y
CONFIG_BLUETOOTH_TINYCRYPT=y
CONFIG_BLUETOOTH_PERIPHERAL=y
CONFIG_BLUETOOTH_GATT_DYNAMIC_DB=y

View file

@ -10,6 +10,5 @@ CONFIG_BLUETOOTH_SMP=y
CONFIG_BLUETOOTH_SIGNING=y
CONFIG_BLUETOOTH_GATT_CLIENT=y
CONFIG_BLUETOOTH_L2CAP_DYNAMIC_CHANNEL=y
CONFIG_BLUETOOTH_TINYCRYPT=y
CONFIG_BLUETOOTH_TINYCRYPT_ECC=y
CONFIG_CONSOLE_HANDLER_SHELL=y