From 3ed1a37a4136d640237c038e47fcd37567b5bac4 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Thu, 11 Feb 2016 14:38:32 +0100 Subject: [PATCH] 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 --- net/bluetooth/Kconfig | 19 +-- net/bluetooth/smp.c | 176 +++-------------------- samples/bluetooth/ipsp/prj.conf | 1 - samples/bluetooth/peripheral/prj.conf | 1 - samples/bluetooth/peripheral_hr/prj.conf | 1 - samples/bluetooth/shell/prj_x86.conf | 1 - 6 files changed, 27 insertions(+), 172 deletions(-) diff --git a/net/bluetooth/Kconfig b/net/bluetooth/Kconfig index ddf455e5ab8..4c4db461f46 100644 --- a/net/bluetooth/Kconfig +++ b/net/bluetooth/Kconfig @@ -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 diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 972ecfd6937..dce5f5e40a4 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c @@ -37,6 +37,7 @@ #if defined(CONFIG_TINYCRYPT_AES) #include #include +#include #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, diff --git a/samples/bluetooth/ipsp/prj.conf b/samples/bluetooth/ipsp/prj.conf index aceefc1f536..addbb8262d4 100644 --- a/samples/bluetooth/ipsp/prj.conf +++ b/samples/bluetooth/ipsp/prj.conf @@ -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 diff --git a/samples/bluetooth/peripheral/prj.conf b/samples/bluetooth/peripheral/prj.conf index 98d6d2ff09d..19d0148678b 100644 --- a/samples/bluetooth/peripheral/prj.conf +++ b/samples/bluetooth/peripheral/prj.conf @@ -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 diff --git a/samples/bluetooth/peripheral_hr/prj.conf b/samples/bluetooth/peripheral_hr/prj.conf index 9d1fa5d424c..0738e8b622b 100644 --- a/samples/bluetooth/peripheral_hr/prj.conf +++ b/samples/bluetooth/peripheral_hr/prj.conf @@ -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 diff --git a/samples/bluetooth/shell/prj_x86.conf b/samples/bluetooth/shell/prj_x86.conf index 3f63d9f8c7a..7b2f8802335 100644 --- a/samples/bluetooth/shell/prj_x86.conf +++ b/samples/bluetooth/shell/prj_x86.conf @@ -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