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 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

View file

@ -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,

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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