From a50f0d8c578684ee8029036cfc547e927a0b4ea0 Mon Sep 17 00:00:00 2001
From: "matthias.ringwald"
 <matthias.ringwald@1a0a8af8-31b5-11de-8e0c-53a27eea117e>
Date: Thu, 12 Jun 2014 13:38:17 +0000
Subject: [PATCH] track aes128 state and use of sm_aes128_plaintext var

---
 ble/sm.c | 68 +++++++++++++++++++++++++++++++-------------------------
 1 file changed, 38 insertions(+), 30 deletions(-)

diff --git a/ble/sm.c b/ble/sm.c
index a0878cb4e..7a46cbe82 100644
--- a/ble/sm.c
+++ b/ble/sm.c
@@ -163,6 +163,11 @@ typedef enum {
     SM_USER_RESPONSE_DECLINE
 } sm_user_response_t;
 
+typedef enum {
+    SM_AES128_IDLE,
+    SM_AES128_PLAINTEXT_SET,
+    SM_AES128_ACTIVE
+} sm_aes128_state_t;
 //
 // GLOBAL DATA
 //
@@ -217,8 +222,8 @@ static uint8_t  sm_pairing_failed_reason = 0;
 static timer_source_t sm_timeout;
 
 // data to send to aes128 crypto engine, see sm_aes128_set_key and sm_aes128_set_plaintext
-static sm_key_t   sm_aes128_plaintext;
-static uint8_t    sm_aes128_active;
+static sm_key_t             sm_aes128_plaintext;
+static sm_aes128_state_t    sm_aes128_state;
 
 // generation method and temporary key for STK - STK is stored in sm_s_ltk
 static stk_generation_method_t sm_stk_generation_method;
@@ -392,9 +397,9 @@ static void gap_random_address_update_stop(){
     run_loop_remove_timer(&gap_random_address_update_timer);
 }
 
-// asserts: sm_aes128_active == 0, hci_can_send_command == 1
+// pre: sm_aes128_state != SM_AES128_ACTIVE, hci_can_send_command == 1
 static void sm_aes128_start(sm_key_t key, sm_key_t plaintext){
-    sm_aes128_active = 1;
+    sm_aes128_state = SM_AES128_ACTIVE;
     sm_key_t key_flipped, plaintext_flipped;
     swap128(key, key_flipped);
     swap128(plaintext, plaintext_flipped);
@@ -747,11 +752,13 @@ static void sm_run(void){
     if (!hci_can_send_packet_now_using_packet_buffer(HCI_COMMAND_DATA_PACKET)) return;
     if (!l2cap_can_send_connectionless_packet_now()) return;
 
+    sm_key_t plaintext;
+
     // distributed key generation
     switch (dkg_state){
         case DKG_CALC_IRK:
             // already busy?
-            if (sm_aes128_active) break;
+            if (sm_aes128_state == SM_AES128_ACTIVE) break;
             {
             // IRK = d1(IR, 1, 0)
             sm_key_t d1_prime;
@@ -761,7 +768,7 @@ static void sm_run(void){
             }
         case DKG_CALC_DHK:
             // already busy?
-            if (sm_aes128_active) break;
+            if (sm_aes128_state == SM_AES128_ACTIVE) break;
             {
             // DHK = d1(IR, 3, 0)
             sm_key_t d1_prime;
@@ -782,7 +789,7 @@ static void sm_run(void){
             return;
         case RAU_GET_ENC:
             // already busy?
-            if (sm_aes128_active) break;
+            if (sm_aes128_state == SM_AES128_ACTIVE) break;
             {
             sm_key_t r_prime;
             sm_ah_r_prime(sm_random_address, r_prime);
@@ -823,7 +830,7 @@ static void sm_run(void){
                 continue;
             }
 
-            if (sm_aes128_active) break;
+            if (sm_aes128_state == SM_AES128_ACTIVE) break;
 
             printf("Central Device Lookup: calculate AH\n");
             print_key("IRK", irk);
@@ -848,7 +855,7 @@ static void sm_run(void){
         case CMAC_CALC_MI:
         case CMAC_CALC_MLAST:
             // already busy?
-            if (sm_aes128_active) break;
+            if (sm_aes128_state == SM_AES128_ACTIVE) break;
             sm_cmac_handle_aes_engine_ready();
             return;
         default:
@@ -953,7 +960,7 @@ static void sm_run(void){
         case SM_STATE_PH2_C1_GET_ENC_B:
         case SM_STATE_PH2_C1_GET_ENC_D:
             // already busy?
-            if (sm_aes128_active) break;
+            if (sm_aes128_state == SM_AES128_ACTIVE) break;
             sm_aes128_start(sm_tk, sm_aes128_plaintext);
             sm_state_responding_next_state();
             return;
@@ -961,42 +968,42 @@ static void sm_run(void){
         case SM_STATE_PH3_LTK_GET_ENC:
         case SM_STATE_PH4_LTK_GET_ENC:
             // already busy?
-            if (sm_aes128_active) break;
+            if (sm_aes128_state == SM_AES128_ACTIVE) break;
             sm_aes128_start(sm_persistent_er, sm_aes128_plaintext);
             sm_state_responding_next_state();
             return;
 
         case SM_STATE_PH2_C1_GET_ENC_C:
             // already busy?
-            if (sm_aes128_active) break;
+            if (sm_aes128_state == SM_AES128_ACTIVE) break;
             // calculate m_confirm using aes128 engine - step 1
-            sm_c1_t1(sm_m_random, sm_m_preq, sm_s_pres, sm_m_addr_type, sm_s_addr_type, sm_aes128_plaintext);
-            sm_aes128_start(sm_tk, sm_aes128_plaintext);
+            sm_c1_t1(sm_m_random, sm_m_preq, sm_s_pres, sm_m_addr_type, sm_s_addr_type, plaintext);
+            sm_aes128_start(sm_tk, plaintext);
             sm_state_responding_next_state();
             break;
         case SM_STATE_PH2_C1_GET_ENC_A:
             // already busy?
-            if (sm_aes128_active) break;
+            if (sm_aes128_state == SM_AES128_ACTIVE) break;
             // calculate s_confirm using aes128 engine - step 1
-            sm_c1_t1(sm_s_random, sm_m_preq, sm_s_pres, sm_m_addr_type, sm_s_addr_type, sm_aes128_plaintext);
-            sm_aes128_start(sm_tk, sm_aes128_plaintext);
+            sm_c1_t1(sm_s_random, sm_m_preq, sm_s_pres, sm_m_addr_type, sm_s_addr_type, plaintext);
+            sm_aes128_start(sm_tk, plaintext);
             sm_state_responding_next_state();
             break;
         case SM_STATE_PH2_CALC_STK:
             // already busy?
-            if (sm_aes128_active) break;
+            if (sm_aes128_state == SM_AES128_ACTIVE) break;
             // calculate STK
-            sm_s1_r_prime(sm_s_random, sm_m_random, sm_aes128_plaintext);
-            sm_aes128_start(sm_tk, sm_aes128_plaintext);
+            sm_s1_r_prime(sm_s_random, sm_m_random, plaintext);
+            sm_aes128_start(sm_tk, plaintext);
             sm_state_responding_next_state();
             break;
         case SM_STATE_PH3_Y_GET_ENC:
             // already busy?
-            if (sm_aes128_active) break;
+            if (sm_aes128_state == SM_AES128_ACTIVE) break;
             // PH3B2 - calculate Y from      - enc
             // Y = dm(DHK, Rand)
-            sm_dm_r_prime(sm_s_rand, sm_aes128_plaintext);
-            sm_aes128_start(sm_persistent_dhk, sm_aes128_plaintext);
+            sm_dm_r_prime(sm_s_rand, plaintext);
+            sm_aes128_start(sm_persistent_dhk, plaintext);
             sm_state_responding_next_state();
             return;
         case SM_STATE_PH2_C1_SEND_PAIRING_CONFIRM: {
@@ -1024,11 +1031,11 @@ static void sm_run(void){
         }
         case SM_STATE_PH4_Y_GET_ENC:
             // already busy?
-            if (sm_aes128_active) break;
+            if (sm_aes128_state == SM_AES128_ACTIVE) break;
             log_info("LTK Request: recalculating with ediv 0x%04x", sm_s_ediv);
             // Y = dm(DHK, Rand)
-            sm_dm_r_prime(sm_s_rand, sm_aes128_plaintext);
-            sm_aes128_start(sm_persistent_dhk, sm_aes128_plaintext);
+            sm_dm_r_prime(sm_s_rand, plaintext);
+            sm_aes128_start(sm_persistent_dhk, plaintext);
             sm_state_responding_next_state();
             return;
 
@@ -1097,7 +1104,7 @@ static void sm_run(void){
 // note: aes engine is ready as we just got the aes result, also, sm_aes128_plaintext and sm_aes128_key can be set again 
 static void sm_handle_encryption_result(uint8_t * data){
 
-    sm_aes128_active = 0;
+    sm_aes128_state = SM_AES128_IDLE;
 
     if (sm_central_ah_calculation_active){
         sm_central_ah_calculation_active = 0;
@@ -1208,6 +1215,7 @@ static void sm_handle_encryption_result(uint8_t * data){
             // PH3B4 - calculate LTK         - enc
             // LTK = d1(ER, DIV, 0))
             sm_d1_d_prime(sm_s_div, 0, sm_aes128_plaintext);
+            sm_aes128_state = SM_AES128_PLAINTEXT_SET;
             sm_state_responding = SM_STATE_PH3_LTK_GET_ENC;
             return;
         }
@@ -1222,6 +1230,7 @@ static void sm_handle_encryption_result(uint8_t * data){
             // PH3B4 - calculate LTK         - enc
             // LTK = d1(ER, DIV, 0))
             sm_d1_d_prime(sm_s_div, 0, sm_aes128_plaintext);
+            sm_aes128_state = SM_AES128_PLAINTEXT_SET;
             sm_state_responding = SM_STATE_PH4_LTK_GET_ENC;
             return;
         }
@@ -1706,10 +1715,9 @@ void sm_init(){
                                        | SM_STK_GENERATION_METHOD_PASSKEY;
     sm_max_encryption_key_size = 16;
     sm_min_encryption_key_size = 7;
-    sm_aes128_active = 0;
     
-    sm_cmac_state = CMAC_IDLE;
-
+    sm_cmac_state  = CMAC_IDLE;
+    sm_aes128_state = SM_AES128_IDLE;
     sm_central_device_test = -1;    // no private address to resolve yet
     sm_central_ah_calculation_active = 0;