From d09da6b9a84c5407bddc1fe0a286159a742d662d Mon Sep 17 00:00:00 2001 From: "matthias.ringwald@gmail.com" Date: Tue, 12 Nov 2013 22:36:13 +0000 Subject: [PATCH] use aes128 engine for dhk, y, ediv, ltk calculation after bonding --- example/libusb/ble_server.c | 133 ++++++++++++++++++++++++++++++------ 1 file changed, 111 insertions(+), 22 deletions(-) diff --git a/example/libusb/ble_server.c b/example/libusb/ble_server.c index b01221ca8..b0945345d 100644 --- a/example/libusb/ble_server.c +++ b/example/libusb/ble_server.c @@ -131,6 +131,16 @@ typedef enum { SM_STATE_PH3_GET_DIV, SM_STATE_PH3_W4_DIV, + SM_STATE_PH3_DHK_GET_ENC, + SM_STATE_PH3_DHK_W4_ENC, + + SM_STATE_PH3_Y_GET_ENC, + SM_STATE_PH3_Y_W4_ENC, + + SM_STATE_PH3_LTK_GET_ENC, + SM_STATE_PH3_LTK_W4_ENC, + + } security_manager_state_t; static att_connection_t att_connection; @@ -149,7 +159,7 @@ static key_t sm_persistent_irk; // derived from sm_persistent_er -// data to send to aes128 crypto engine +// data to send to aes128 crypto engine, see sm_aes128_set_key and sm_aes128_set_plaintext static key_t sm_aes128_key; static key_t sm_aes128_plaintext; @@ -188,8 +198,9 @@ static key_t sm_s_random; static key_t sm_s_confirm; static key_t sm_stk; -static uint8_t sm_pairing_failed_reason = 0; +static uint8_t sm_pairing_failed_reason = 0; static uint16_t sm_s_div; +static uint16_t sm_s_y; // key distribution, slave sends static key_t sm_s_ltk; @@ -242,28 +253,54 @@ static inline void swap56(uint8_t src[7], uint8_t dst[7]){ dst[6 - i] = src[i]; } -static void sm_d1(key_t k, uint16_t d, uint16_t r, key_t d1){ +static void print_key(const char * name, key_t key){ + printf("%-6s ", name); + hexdump(key, 16); +} + +static void print_hex16(const char * name, uint16_t value){ + printf("%-6s 0x%04x\n", name, value); +} + +static inline void sm_aes128_set_key(key_t key){ + memcpy(sm_aes128_key, key, 16); +} + +static inline void sm_aes128_set_plaintext(key_t plaintext){ + memcpy(sm_aes128_plaintext, plaintext, 16); +} + +static void sm_d1_d_prime(uint16_t d, uint16_t r, key_t d1_prime){ // d'= padding || r || d - key_t d1_prime; memset(d1_prime, 0, 16); net_store_16(d1_prime, 12, r); net_store_16(d1_prime, 14, d); +} + +static void sm_d1(key_t k, uint16_t d, uint16_t r, key_t d1){ + key_t d1_prime; + sm_d1_d_prime(d, r, d1_prime); // d1(k,d,r) = e(k, d'), unsigned long rk[RKLENGTH(KEYBITS)]; int nrounds = rijndaelSetupEncrypt(rk, &k[0], KEYBITS); rijndaelEncrypt(rk, nrounds, d1_prime, d1); } -static uint16_t sm_dm(key_t k, uint8_t r[8]){ +static void sm_dm_r_prime(uint8_t r[8], key_t r_prime){ // r’ = padding || r - key_t r_prime; memset(r_prime, 0, 16); memcpy(&r_prime[8], r, 8); +} + +static uint16_t sm_dm(key_t k, uint8_t r[8]){ + key_t r_prime; + sm_dm_r_prime(r, r_prime); // dm(k, r) = e(k, r’) dm(k, r) = e(k, r’) key_t dm128; unsigned long rk[RKLENGTH(KEYBITS)]; int nrounds = rijndaelSetupEncrypt(rk, &k[0], KEYBITS); rijndaelEncrypt(rk, nrounds, r_prime, dm128); + uint16_t dm = READ_NET_16(dm128, 14); return dm; } @@ -504,6 +541,9 @@ static void sm_run(void){ case SM_STATE_C1_GET_ENC_C: case SM_STATE_C1_GET_ENC_D: case SM_STATE_CALC_STK: + case SM_STATE_PH3_DHK_GET_ENC: + case SM_STATE_PH3_Y_GET_ENC: + case SM_STATE_PH3_LTK_GET_ENC: { key_t key_flipped, plaintext_flipped; swap128(sm_aes128_key, key_flipped); @@ -663,7 +703,7 @@ static void sm_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *pac // use aes128 engine // calculate m_confirm using aes128 engine - step 1 - memcpy(sm_aes128_key, sm_tk, 16); + sm_aes128_set_key(sm_tk); sm_c1_t1(sm_m_random, sm_preq, sm_pres, sm_m_addr_type, sm_s_addr_type, sm_aes128_plaintext); sm_state_responding = SM_STATE_C1_GET_ENC_C; break; @@ -800,21 +840,22 @@ static void packet_handler (void * connection, uint8_t packet_type, uint16_t cha key_t sm_stk; sm_s1(sm_tk, sm_s_random, sm_m_random, sm_stk); - memcpy(sm_aes128_key, sm_tk, 16); + sm_aes128_set_key(sm_tk); sm_s1_r_prime(sm_s_random, sm_m_random, sm_aes128_plaintext); - sm_state_responding = SM_STATE_CALC_STK; - - // key_t sm_stk_flipped; - // swap128(sm_stk, sm_stk_flipped); - // hci_send_cmd(&hci_le_long_term_key_request_reply, READ_BT_16(packet, 3), sm_stk_flipped); - // sm_state_responding = SM_STATE_W4_CONNECTION_ENCRYPTED; break; } // re-establish previously used LTK using Rand and EDIV log_info("recalculating LTK"); memcpy(sm_s_rand, &packet[5], 8); sm_s_ediv = READ_BT_16(packet, 13); + + // dhk = d1(IR, 1, 0) - enc + // y = dm(dhk, rand) - enc + // div = y xor ediv + // ltk = d1(ER, div, 0) - enc + + // sm_div depends on sm_y, dhk, sm_dm, sm_dm_r_prime, sm_d1, ir, sm_d1_d_prime sm_s_div = sm_div(sm_persistent_dhk, sm_s_rand, sm_s_ediv); sm_ltk(sm_persistent_er, sm_s_div, sm_s_ltk); hci_send_cmd(&hci_le_long_term_key_request_reply, READ_BT_16(packet, 3), sm_s_ltk); @@ -862,7 +903,7 @@ static void packet_handler (void * connection, uint8_t packet_type, uint16_t cha case SM_STATE_C1_W4_ENC_A: case SM_STATE_C1_W4_ENC_C: { - memcpy(sm_aes128_key, sm_tk, 16); + sm_aes128_set_key(sm_tk); key_t t2; swap128(&packet[6], t2); sm_c1_t3(t2, sm_m_address, sm_s_address, sm_aes128_plaintext); @@ -902,6 +943,40 @@ static void packet_handler (void * connection, uint8_t packet_type, uint16_t cha hexdump(sm_stk, 16); sm_state_responding = SM_STATE_SEND_STK; break; + case SM_STATE_PH3_DHK_W4_ENC: + swap128(&packet[6], sm_persistent_dhk); + printf("dhk "); + hexdump(sm_persistent_dhk, 16); + // PH3B2 - calculate Y from - enc + // Y = dm(DHK, Rand) + sm_aes128_set_key(sm_persistent_dhk); + sm_dm_r_prime(sm_s_rand, sm_aes128_plaintext); + sm_state_responding = SM_STATE_PH3_Y_GET_ENC; + break; + case SM_STATE_PH3_Y_W4_ENC:{ + key_t y128; + swap128(&packet[6], y128); + sm_s_y = READ_NET_16(y128, 14); + printf("y 0x%04x\n", sm_s_y); + // PH3B3 - calculate EDIV + sm_s_ediv = sm_s_y ^ sm_s_div; + printf("ediv 0x%04x\n", sm_s_ediv); + // PH3B4 - calculate LTK - enc + // LTK = d1(ER, DIV, 0)) + sm_aes128_set_key(sm_persistent_er); + sm_d1_d_prime(sm_s_div, 0, sm_aes128_plaintext); + sm_state_responding = SM_STATE_PH3_LTK_GET_ENC; + break; + } + case SM_STATE_PH3_LTK_W4_ENC: + swap128(&packet[6], sm_s_ltk); + printf("ltk "); + hexdump(sm_s_ltk, 16); + // distribute keys + sm_distribute_keys(); + // done + sm_state_responding = SM_STATE_IDLE; + break; default: break; } @@ -921,7 +996,7 @@ static void packet_handler (void * connection, uint8_t packet_type, uint16_t cha // sm_state_responding = SM_STATE_C1_SEND; // calculate s_confirm using aes128 engine - step 1 - memcpy(sm_aes128_key, sm_tk, 16); + sm_aes128_set_key(sm_tk); sm_c1_t1(sm_s_random, sm_preq, sm_pres, sm_m_addr_type, sm_s_addr_type, sm_aes128_plaintext); sm_state_responding = SM_STATE_C1_GET_ENC_A; break; @@ -933,15 +1008,26 @@ static void packet_handler (void * connection, uint8_t packet_type, uint16_t cha // use 16 bit from random value as div sm_s_div = READ_NET_16(packet, 6); - // done - sm_state_responding = SM_STATE_IDLE; + // PLAN + // PH3B1 - calculate DHK from IR - enc + // PH3B2 - calculate Y from - enc + // PH3B3 - calculate EDIV + // PH3B4 - calculate LTK - enc - // calculate EDIV and LTK + // DHK = d1(IR, 3, 0) + sm_aes128_set_key(sm_persistent_ir); + sm_d1_d_prime(3, 0, sm_aes128_plaintext); + sm_state_responding = SM_STATE_PH3_DHK_GET_ENC; + + // // calculate EDIV and LTK sm_s_ediv = sm_ediv(sm_persistent_dhk, sm_s_rand, sm_s_div); sm_ltk(sm_persistent_er, sm_s_div, sm_s_ltk); - - // distribute keys - sm_distribute_keys(); + print_key("ltk", sm_s_ltk); + print_hex16("ediv", sm_s_ediv); + // // distribute keys + // sm_distribute_keys(); + // // done + // sm_state_responding = SM_STATE_IDLE; break; default: @@ -999,6 +1085,9 @@ void setup(void){ att_set_write_callback(att_write_callback); att_dump_attributes(); att_connection.mtu = 27; + + // setup SM + sm_init(); } int main(void)