OSDN Git Service

smp_keys simplification
authorJakub Pawlowski <jpawlowski@google.com>
Fri, 24 Feb 2017 18:57:57 +0000 (10:57 -0800)
committerAndre Eisenbach <eisenbach@google.com>
Wed, 8 Mar 2017 18:22:24 +0000 (18:22 +0000)
Test: manual
Change-Id: Ia38604d496b8ae50934c42b68f2424afd1c6320c

stack/smp/smp_int.h
stack/smp/smp_keys.cc

index c3e1df4..3d6f4f7 100644 (file)
@@ -205,25 +205,6 @@ enum {
 };
 typedef uint8_t tSMP_BR_STATE;
 
-/* random and encrption activity state */
-enum {
-  SMP_GEN_COMPARE = 1,
-  SMP_GEN_CONFIRM,
-
-  SMP_GEN_DIV_LTK,
-  SMP_GEN_DIV_CSRK,
-  SMP_GEN_RAND_V,
-  SMP_GEN_TK,
-  SMP_GEN_SRAND_MRAND,
-  SMP_GEN_SRAND_MRAND_CONT,
-  SMP_GENERATE_PRIVATE_KEY_0_7,
-  SMP_GENERATE_PRIVATE_KEY_8_15,
-  SMP_GENERATE_PRIVATE_KEY_16_23,
-  SMP_GENERATE_PRIVATE_KEY_24_31,
-  SMP_GEN_NONCE_0_7,
-  SMP_GEN_NONCE_8_15
-};
-
 enum {
   SMP_KEY_TYPE_TK,
   SMP_KEY_TYPE_CFM,
@@ -338,7 +319,6 @@ typedef struct {
   BT_OCTET16 csrk; /* storage for local CSRK */
   uint16_t ediv;
   BT_OCTET8 enc_rand;
-  uint8_t rand_enc_proc_state;
   uint8_t addr_type;
   BD_ADDR local_bda;
   bool is_pair_cancel;
index a7d56e5..4154fcf 100644 (file)
@@ -45,19 +45,10 @@ using base::Bind;
 #define SMP_MAX_ENC_REPEAT 3
 #endif
 
-static void smp_rand_back(BT_OCTET8 rand);
-static void smp_generate_confirm(tSMP_CB* p_cb, tSMP_INT_DATA* p_data);
-static void smp_generate_ltk_cont(tSMP_CB* p_cb, tSMP_INT_DATA* p_data);
-static void smp_generate_y(tSMP_CB* p_cb, tSMP_INT_DATA* p);
-static void smp_generate_rand_vector(tSMP_CB* p_cb, tSMP_INT_DATA* p);
 static void smp_process_stk(tSMP_CB* p_cb, tSMP_ENC* p);
-static void smp_process_ediv(tSMP_CB* p_cb, tSMP_ENC* p);
 static bool smp_calculate_legacy_short_term_key(tSMP_CB* p_cb,
                                                 tSMP_ENC* output);
-static void smp_continue_private_key_creation(tSMP_CB* p_cb, BT_OCTET8 rand);
 static void smp_process_private_key(tSMP_CB* p_cb);
-static void smp_finish_nonce_generation(tSMP_CB* p_cb);
-static void smp_process_new_nonce(tSMP_CB* p_cb);
 
 #define SMP_PASSKEY_MASK 0xfff00000
 
@@ -172,23 +163,6 @@ bool smp_encrypt_data(uint8_t* key, uint8_t key_len, uint8_t* plain_text,
 
 /*******************************************************************************
  *
- * Function         smp_generate_passkey
- *
- * Description      This function is called to generate passkey.
- *
- * Returns          void
- *
- ******************************************************************************/
-void smp_generate_passkey(tSMP_CB* p_cb, UNUSED_ATTR tSMP_INT_DATA* p_data) {
-  SMP_TRACE_DEBUG("%s", __func__);
-  p_cb->rand_enc_proc_state = SMP_GEN_TK;
-
-  /* generate MRand or SRand */
-  btsnd_hcic_ble_rand(Bind(&smp_rand_back));
-}
-
-/*******************************************************************************
- *
  * Function         smp_proc_passkey
  *
  * Description      This function is called to process a passkey.
@@ -230,6 +204,21 @@ void smp_proc_passkey(tSMP_CB* p_cb, BT_OCTET8 rand) {
 
 /*******************************************************************************
  *
+ * Function         smp_generate_passkey
+ *
+ * Description      This function is called to generate passkey.
+ *
+ * Returns          void
+ *
+ ******************************************************************************/
+void smp_generate_passkey(tSMP_CB* p_cb, UNUSED_ATTR tSMP_INT_DATA* p_data) {
+  SMP_TRACE_DEBUG("%s", __func__);
+  /* generate MRand or SRand */
+  btsnd_hcic_ble_rand(Bind(&smp_proc_passkey, p_cb));
+}
+
+/*******************************************************************************
+ *
  * Function         smp_generate_stk
  *
  * Description      This function is called to generate STK calculated by
@@ -260,91 +249,10 @@ void smp_generate_stk(tSMP_CB* p_cb, UNUSED_ATTR tSMP_INT_DATA* p_data) {
   smp_process_stk(p_cb, &output);
 }
 
-/*******************************************************************************
- *
- * Function         smp_generate_srand_mrand_confirm
- *
- * Description      This function is called to start the second pairing phase by
- *                  start generating random number.
- *
- *
- * Returns          void
- *
- ******************************************************************************/
-void smp_generate_srand_mrand_confirm(tSMP_CB* p_cb,
-                                      UNUSED_ATTR tSMP_INT_DATA* p_data) {
-  SMP_TRACE_DEBUG("%s", __func__);
-  p_cb->rand_enc_proc_state = SMP_GEN_SRAND_MRAND;
-  /* generate MRand or SRand */
-  btsnd_hcic_ble_rand(Bind(&smp_rand_back));
-}
-
-/*******************************************************************************
- *
- * Function         smp_generate_rand_cont
- *
- * Description      This function is called to generate another 64 bits random
- *                  for MRand or Srand.
- *
- * Returns          void
- *
- ******************************************************************************/
-void smp_generate_rand_cont(tSMP_CB* p_cb, UNUSED_ATTR tSMP_INT_DATA* p_data) {
-  SMP_TRACE_DEBUG("%s", __func__);
-  p_cb->rand_enc_proc_state = SMP_GEN_SRAND_MRAND_CONT;
-  /* generate 64 MSB of MRand or SRand */
-  btsnd_hcic_ble_rand(Bind(&smp_rand_back));
-}
-
-/*******************************************************************************
- *
- * Function         smp_generate_ltk
- *
- * Description      This function is called:
- *                  - in legacy pairing - to calculate LTK, starting with DIV
- *                    generation;
- *                  - in LE Secure Connections pairing over LE transport - to
- *                    process LTK already generated to encrypt LE link;
- *                  - in LE Secure Connections pairing over BR/EDR transport -
- *                    to start BR/EDR Link Key processing.
- *
- * Returns          void
- *
- ******************************************************************************/
-void smp_generate_ltk(tSMP_CB* p_cb, UNUSED_ATTR tSMP_INT_DATA* p_data) {
-  bool div_status;
-  SMP_TRACE_DEBUG("%s", __func__);
-  if (smp_get_br_state() == SMP_BR_STATE_BOND_PENDING) {
-    smp_br_process_link_key(p_cb, NULL);
-    return;
-  } else if (p_cb->le_secure_connections_mode_is_used) {
-    smp_process_secure_connection_long_term_key();
-    return;
-  }
-
-  div_status = btm_get_local_div(p_cb->pairing_bda, &p_cb->div);
-
-  if (div_status) {
-    smp_generate_ltk_cont(p_cb, NULL);
-  } else {
-    SMP_TRACE_DEBUG("Generate DIV for LTK");
-    p_cb->rand_enc_proc_state = SMP_GEN_DIV_LTK;
-    /* generate MRand or SRand */
-    btsnd_hcic_ble_rand(Bind(&smp_rand_back));
-  }
-}
-
-/*******************************************************************************
- *
- * Function         smp_compute_csrk
- *
- * Description      This function is called to calculate CSRK
- *
- *
- * Returns          void
- *
- ******************************************************************************/
-void smp_compute_csrk(tSMP_CB* p_cb, UNUSED_ATTR tSMP_INT_DATA* p_data) {
+/**
+ * This function is called to calculate CSRK
+ */
+void smp_compute_csrk(uint16_t div, tSMP_CB* p_cb) {
   BT_OCTET16 er;
   uint8_t buffer[4]; /* for (r || DIV)  r=1*/
   uint16_t r = 1;
@@ -352,7 +260,9 @@ void smp_compute_csrk(tSMP_CB* p_cb, UNUSED_ATTR tSMP_INT_DATA* p_data) {
   tSMP_ENC output;
   tSMP_STATUS status = SMP_PAIR_FAIL_UNKNOWN;
 
-  SMP_TRACE_DEBUG("smp_compute_csrk div=%x", p_cb->div);
+  p_cb->div = div;
+
+  SMP_TRACE_DEBUG("%s: div=%x", __func__, p_cb->div);
   BTM_GetDeviceEncRoot(er);
   /* CSRK = d1(ER, DIV, 1) */
   UINT16_TO_STREAM(p, p_cb->div);
@@ -371,17 +281,9 @@ void smp_compute_csrk(tSMP_CB* p_cb, UNUSED_ATTR tSMP_INT_DATA* p_data) {
   }
 }
 
-/*******************************************************************************
- *
- * Function         smp_generate_csrk
- *
- * Description      This function is called to calculate CSRK, starting with DIV
- *                  generation.
- *
- *
- * Returns          void
- *
- ******************************************************************************/
+/**
+ * This function is called to calculate CSRK, starting with DIV generation.
+ */
 void smp_generate_csrk(tSMP_CB* p_cb, UNUSED_ATTR tSMP_INT_DATA* p_data) {
   bool div_status;
 
@@ -389,11 +291,16 @@ void smp_generate_csrk(tSMP_CB* p_cb, UNUSED_ATTR tSMP_INT_DATA* p_data) {
 
   div_status = btm_get_local_div(p_cb->pairing_bda, &p_cb->div);
   if (div_status) {
-    smp_compute_csrk(p_cb, NULL);
+    smp_compute_csrk(p_cb->div, p_cb);
   } else {
     SMP_TRACE_DEBUG("Generate DIV for CSRK");
-    p_cb->rand_enc_proc_state = SMP_GEN_DIV_CSRK;
-    btsnd_hcic_ble_rand(Bind(&smp_rand_back));
+    btsnd_hcic_ble_rand(Bind(
+        [](tSMP_CB* p_cb, BT_OCTET8 rand) {
+          uint16_t div;
+          STREAM_TO_UINT16(div, rand);
+          smp_compute_csrk(div, p_cb);
+        },
+        p_cb));
   }
 }
 
@@ -567,10 +474,8 @@ tSMP_STATUS smp_calculate_comfirm(tSMP_CB* p_cb, BT_OCTET16 rand,
  * Returns          void
  *
  ******************************************************************************/
-static void smp_generate_confirm(tSMP_CB* p_cb,
-                                 UNUSED_ATTR tSMP_INT_DATA* p_data) {
+static void smp_generate_confirm(tSMP_CB* p_cb) {
   SMP_TRACE_DEBUG("%s", __func__);
-  p_cb->rand_enc_proc_state = SMP_GEN_CONFIRM;
   smp_debug_print_nbyte_little_endian((uint8_t*)p_cb->rand, "local_rand", 16);
   tSMP_ENC output;
   tSMP_STATUS status = smp_calculate_comfirm(p_cb, p_cb->rand, &output);
@@ -589,6 +494,36 @@ static void smp_generate_confirm(tSMP_CB* p_cb,
 
 /*******************************************************************************
  *
+ * Function         smp_generate_srand_mrand_confirm
+ *
+ * Description      This function is called to start the second pairing phase by
+ *                  start generating random number.
+ *
+ *
+ * Returns          void
+ *
+ ******************************************************************************/
+void smp_generate_srand_mrand_confirm(tSMP_CB* p_cb,
+                                      UNUSED_ATTR tSMP_INT_DATA* p_data) {
+  SMP_TRACE_DEBUG("%s", __func__);
+  /* generate MRand or SRand */
+  btsnd_hcic_ble_rand(Bind(
+      [](tSMP_CB* p_cb, BT_OCTET8 rand) {
+        memcpy((void*)p_cb->rand, rand, 8);
+
+        /* generate 64 MSB of MRand or SRand */
+        btsnd_hcic_ble_rand(Bind(
+            [](tSMP_CB* p_cb, BT_OCTET8 rand) {
+              memcpy((void*)&p_cb->rand[8], rand, BT_OCTET8_LEN);
+              smp_generate_confirm(p_cb);
+            },
+            p_cb));
+      },
+      p_cb));
+}
+
+/*******************************************************************************
+ *
  * Function         smp_generate_compare
  *
  * Description      This function is called when random number (MRand or SRand)
@@ -601,7 +536,6 @@ static void smp_generate_confirm(tSMP_CB* p_cb,
  ******************************************************************************/
 void smp_generate_compare(tSMP_CB* p_cb, UNUSED_ATTR tSMP_INT_DATA* p_data) {
   SMP_TRACE_DEBUG("smp_generate_compare ");
-  p_cb->rand_enc_proc_state = SMP_GEN_COMPARE;
   smp_debug_print_nbyte_little_endian((uint8_t*)p_cb->rrand, "peer rand", 16);
   tSMP_ENC output;
   tSMP_STATUS status = smp_calculate_comfirm(p_cb, p_cb->rrand, &output);
@@ -642,107 +576,116 @@ static void smp_process_stk(tSMP_CB* p_cb, tSMP_ENC* p) {
   smp_sm_event(p_cb, SMP_KEY_READY_EVT, &key);
 }
 
-/*******************************************************************************
- *
- * Function         smp_generate_ltk_cont
- *
- * Description      Calculate LTK = d1(ER, DIV, 0)= e(ER, DIV)
- *
- * Returns          void
- *
- ******************************************************************************/
-static void smp_generate_ltk_cont(tSMP_CB* p_cb,
-                                  UNUSED_ATTR tSMP_INT_DATA* p_data) {
-  BT_OCTET16 er;
+/**
+ * This function is to calculate EDIV = Y xor DIV
+ */
+static void smp_process_ediv(tSMP_CB* p_cb, tSMP_ENC* p) {
+  tSMP_KEY key;
+  uint8_t* pp = p->param_buf;
+  uint16_t y;
+
+  SMP_TRACE_DEBUG("smp_process_ediv ");
+  STREAM_TO_UINT16(y, pp);
+
+  /* EDIV = Y xor DIV */
+  p_cb->ediv = p_cb->div ^ y;
+  /* send LTK ready */
+  SMP_TRACE_ERROR("LTK ready");
+  key.key_type = SMP_KEY_TYPE_LTK;
+  key.p_data = p->param_buf;
+
+  smp_sm_event(p_cb, SMP_KEY_READY_EVT, &key);
+}
+
+/**
+ * This function is to proceed generate Y = E(DHK, Rand)
+ */
+static void smp_generate_y(tSMP_CB* p_cb, BT_OCTET8 rand) {
+  SMP_TRACE_DEBUG("%s ", __func__);
+
+  BT_OCTET16 dhk;
+  BTM_GetDeviceDHK(dhk);
+
+  memcpy(p_cb->enc_rand, rand, BT_OCTET8_LEN);
   tSMP_ENC output;
-  tSMP_STATUS status = SMP_PAIR_FAIL_UNKNOWN;
+  if (!SMP_Encrypt(dhk, BT_OCTET16_LEN, rand, BT_OCTET8_LEN, &output)) {
+    SMP_TRACE_ERROR("%s failed", __func__);
+    tSMP_STATUS status = SMP_PAIR_FAIL_UNKNOWN;
+    smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &status);
+  } else {
+    smp_process_ediv(p_cb, &output);
+  }
+}
+
+/**
+ * Calculate LTK = d1(ER, DIV, 0)= e(ER, DIV)
+ */
+static void smp_generate_ltk_cont(uint16_t div, tSMP_CB* p_cb) {
+  p_cb->div = div;
 
   SMP_TRACE_DEBUG("%s", __func__);
+  BT_OCTET16 er;
   BTM_GetDeviceEncRoot(er);
 
+  tSMP_ENC output;
   /* LTK = d1(ER, DIV, 0)= e(ER, DIV)*/
   if (!SMP_Encrypt(er, BT_OCTET16_LEN, (uint8_t*)&p_cb->div, sizeof(uint16_t),
                    &output)) {
     SMP_TRACE_ERROR("%s failed", __func__);
+    tSMP_STATUS status = SMP_PAIR_FAIL_UNKNOWN;
     smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &status);
   } else {
     /* mask the LTK */
     smp_mask_enc_key(p_cb->loc_enc_size, output.param_buf);
     memcpy((void*)p_cb->ltk, output.param_buf, BT_OCTET16_LEN);
-    smp_generate_rand_vector(p_cb, NULL);
-  }
-}
 
-/*******************************************************************************
- *
- * Function         smp_generate_y
- *
- * Description      This function is to proceed generate Y = E(DHK, Rand)
- *
- * Returns          void
- *
- ******************************************************************************/
-static void smp_generate_y(tSMP_CB* p_cb, UNUSED_ATTR tSMP_INT_DATA* p) {
-  BT_OCTET16 dhk;
-  tSMP_ENC output;
-  tSMP_STATUS status = SMP_PAIR_FAIL_UNKNOWN;
-
-  SMP_TRACE_DEBUG("smp_generate_y ");
-  BTM_GetDeviceDHK(dhk);
-
-  if (!SMP_Encrypt(dhk, BT_OCTET16_LEN, p_cb->enc_rand, BT_OCTET8_LEN,
-                   &output)) {
-    SMP_TRACE_ERROR("smp_generate_y failed");
-    smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &status);
-  } else {
-    smp_process_ediv(p_cb, &output);
+    /* generate EDIV and rand now */
+    btsnd_hcic_ble_rand(Bind(&smp_generate_y, p_cb));
   }
 }
 
 /*******************************************************************************
  *
- * Function         smp_generate_rand_vector
+ * Function         smp_generate_ltk
  *
- * Description      This function is called when an LTK is generated, send state
- *                  machine event to SMP.
+ * Description      This function is called:
+ *                  - in legacy pairing - to calculate LTK, starting with DIV
+ *                    generation;
+ *                  - in LE Secure Connections pairing over LE transport - to
+ *                    process LTK already generated to encrypt LE link;
+ *                  - in LE Secure Connections pairing over BR/EDR transport -
+ *                    to start BR/EDR Link Key processing.
  *
  * Returns          void
  *
  ******************************************************************************/
-static void smp_generate_rand_vector(tSMP_CB* p_cb,
-                                     UNUSED_ATTR tSMP_INT_DATA* p) {
-  /* generate EDIV and rand now */
-  /* generate random vector */
-  SMP_TRACE_DEBUG("smp_generate_rand_vector ");
-  p_cb->rand_enc_proc_state = SMP_GEN_RAND_V;
-  btsnd_hcic_ble_rand(Bind(&smp_rand_back));
-}
+void smp_generate_ltk(tSMP_CB* p_cb, UNUSED_ATTR tSMP_INT_DATA* p_data) {
+  SMP_TRACE_DEBUG("%s", __func__);
 
-/*******************************************************************************
- *
- * Function         smp_process_ediv
- *
- * Description      This function is to calculate EDIV = Y xor DIV
- *
- * Returns          void
- *
- ******************************************************************************/
-static void smp_process_ediv(tSMP_CB* p_cb, tSMP_ENC* p) {
-  tSMP_KEY key;
-  uint8_t* pp = p->param_buf;
-  uint16_t y;
+  if (smp_get_br_state() == SMP_BR_STATE_BOND_PENDING) {
+    smp_br_process_link_key(p_cb, NULL);
+    return;
+  } else if (p_cb->le_secure_connections_mode_is_used) {
+    smp_process_secure_connection_long_term_key();
+    return;
+  }
 
-  SMP_TRACE_DEBUG("smp_process_ediv ");
-  STREAM_TO_UINT16(y, pp);
+  bool div_status = btm_get_local_div(p_cb->pairing_bda, &p_cb->div);
 
-  /* EDIV = Y xor DIV */
-  p_cb->ediv = p_cb->div ^ y;
-  /* send LTK ready */
-  SMP_TRACE_ERROR("LTK ready");
-  key.key_type = SMP_KEY_TYPE_LTK;
-  key.p_data = p->param_buf;
+  if (div_status) {
+    smp_generate_ltk_cont(p_cb->div, p_cb);
+  } else {
+    SMP_TRACE_DEBUG("%s: Generate DIV for LTK", __func__);
 
-  smp_sm_event(p_cb, SMP_KEY_READY_EVT, &key);
+    /* generate MRand or SRand */
+    btsnd_hcic_ble_rand(Bind(
+        [](tSMP_CB* p_cb, BT_OCTET8 rand) {
+          uint16_t div;
+          STREAM_TO_UINT16(div, rand);
+          smp_generate_ltk_cont(div, p_cb);
+        },
+        p_cb));
+  }
 }
 
 /*******************************************************************************
@@ -755,10 +698,10 @@ static void smp_process_ediv(tSMP_CB* p_cb, tSMP_ENC* p) {
  *
  ******************************************************************************/
 bool smp_calculate_legacy_short_term_key(tSMP_CB* p_cb, tSMP_ENC* output) {
+  SMP_TRACE_DEBUG("%s", __func__);
+
   BT_OCTET16 ptext;
   uint8_t* p = ptext;
-
-  SMP_TRACE_DEBUG("%s", __func__);
   memset(p, 0, BT_OCTET16_LEN);
   if (p_cb->role == HCI_ROLE_MASTER) {
     memcpy(p, p_cb->rand, BT_OCTET8_LEN);
@@ -768,9 +711,8 @@ bool smp_calculate_legacy_short_term_key(tSMP_CB* p_cb, tSMP_ENC* output) {
     memcpy(&p[BT_OCTET8_LEN], p_cb->rand, BT_OCTET8_LEN);
   }
 
-  bool encrypted;
   /* generate STK = Etk(rand|rrand)*/
-  encrypted =
+  bool encrypted =
       SMP_Encrypt(p_cb->tk, BT_OCTET16_LEN, ptext, BT_OCTET16_LEN, output);
   if (!encrypted) {
     SMP_TRACE_ERROR("%s failed", __func__);
@@ -792,8 +734,29 @@ bool smp_calculate_legacy_short_term_key(tSMP_CB* p_cb, tSMP_ENC* output) {
  ******************************************************************************/
 void smp_create_private_key(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
   SMP_TRACE_DEBUG("%s", __func__);
-  p_cb->rand_enc_proc_state = SMP_GENERATE_PRIVATE_KEY_0_7;
-  btsnd_hcic_ble_rand(Bind(&smp_rand_back));
+
+  btsnd_hcic_ble_rand(Bind(
+      [](tSMP_CB* p_cb, BT_OCTET8 rand) {
+        memcpy((void*)p_cb->private_key, rand, BT_OCTET8_LEN);
+        btsnd_hcic_ble_rand(Bind(
+            [](tSMP_CB* p_cb, BT_OCTET8 rand) {
+              memcpy((void*)&p_cb->private_key[8], rand, BT_OCTET8_LEN);
+              btsnd_hcic_ble_rand(Bind(
+                  [](tSMP_CB* p_cb, BT_OCTET8 rand) {
+                    memcpy((void*)&p_cb->private_key[16], rand, BT_OCTET8_LEN);
+                    btsnd_hcic_ble_rand(Bind(
+                        [](tSMP_CB* p_cb, BT_OCTET8 rand) {
+                          memcpy((void*)&p_cb->private_key[24], rand,
+                                 BT_OCTET8_LEN);
+                          smp_process_private_key(p_cb);
+                        },
+                        p_cb));
+                  },
+                  p_cb));
+            },
+            p_cb));
+      },
+      p_cb));
 }
 
 /*******************************************************************************
@@ -834,50 +797,6 @@ void smp_use_oob_private_key(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
 
 /*******************************************************************************
  *
- * Function         smp_continue_private_key_creation
- *
- * Description      This function is used to continue private key creation.
- *
- * Returns          void
- *
- ******************************************************************************/
-void smp_continue_private_key_creation(tSMP_CB* p_cb, BT_OCTET8 rand) {
-  uint8_t state = p_cb->rand_enc_proc_state & ~0x80;
-  SMP_TRACE_DEBUG("%s state=0x%x", __func__, state);
-
-  switch (state) {
-    case SMP_GENERATE_PRIVATE_KEY_0_7:
-      memcpy((void*)p_cb->private_key, rand, 8);
-      p_cb->rand_enc_proc_state = SMP_GENERATE_PRIVATE_KEY_8_15;
-      btsnd_hcic_ble_rand(Bind(&smp_rand_back));
-      break;
-
-    case SMP_GENERATE_PRIVATE_KEY_8_15:
-      memcpy((void*)&p_cb->private_key[8], rand, 8);
-      p_cb->rand_enc_proc_state = SMP_GENERATE_PRIVATE_KEY_16_23;
-      btsnd_hcic_ble_rand(Bind(&smp_rand_back));
-      break;
-
-    case SMP_GENERATE_PRIVATE_KEY_16_23:
-      memcpy((void*)&p_cb->private_key[16], rand, 8);
-      p_cb->rand_enc_proc_state = SMP_GENERATE_PRIVATE_KEY_24_31;
-      btsnd_hcic_ble_rand(Bind(&smp_rand_back));
-      break;
-
-    case SMP_GENERATE_PRIVATE_KEY_24_31:
-      memcpy((void*)&p_cb->private_key[24], rand, 8);
-      smp_process_private_key(p_cb);
-      break;
-
-    default:
-      break;
-  }
-
-  return;
-}
-
-/*******************************************************************************
- *
  * Function         smp_process_private_key
  *
  * Description      This function processes private key.
@@ -1930,111 +1849,22 @@ bool smp_calculate_h6(uint8_t* w, uint8_t* keyid, uint8_t* c) {
   return ret;
 }
 
-/*******************************************************************************
- *
- * Function         smp_start_nonce_generation
- *
- * Description      This function starts nonce generation.
- *
- * Returns          void
- *
- ******************************************************************************/
+/**
+ * This function generates nonce.
+ */
 void smp_start_nonce_generation(tSMP_CB* p_cb) {
   SMP_TRACE_DEBUG("%s", __func__);
-  p_cb->rand_enc_proc_state = SMP_GEN_NONCE_0_7;
-  btsnd_hcic_ble_rand(Bind(&smp_rand_back));
-}
-
-/*******************************************************************************
- *
- * Function         smp_finish_nonce_generation
- *
- * Description      This function finishes nonce generation.
- *
- * Returns          void
- *
- ******************************************************************************/
-void smp_finish_nonce_generation(tSMP_CB* p_cb) {
-  SMP_TRACE_DEBUG("%s", __func__);
-  p_cb->rand_enc_proc_state = SMP_GEN_NONCE_8_15;
-  btsnd_hcic_ble_rand(Bind(&smp_rand_back));
-}
-
-/*******************************************************************************
- *
- * Function         smp_process_new_nonce
- *
- * Description      This function notifies SM that it has new nonce.
- *
- * Returns          void
- *
- ******************************************************************************/
-void smp_process_new_nonce(tSMP_CB* p_cb) {
-  SMP_TRACE_DEBUG("%s round %d", __func__, p_cb->round);
-  smp_sm_event(p_cb, SMP_HAVE_LOC_NONCE_EVT, NULL);
-}
-
-/*******************************************************************************
- *
- * Function         smp_rand_back
- *
- * Description      This function is to process the rand command finished,
- *                  process the random/encrypted number for further action.
- *
- * Returns          void
- *
- ******************************************************************************/
-static void smp_rand_back(BT_OCTET8 rand) {
-  tSMP_CB* p_cb = &smp_cb;
-  uint8_t* pp = rand;
-  uint8_t state = p_cb->rand_enc_proc_state & ~0x80;
-
-  SMP_TRACE_DEBUG("%s state=0x%x", __func__, state);
-  switch (state) {
-    case SMP_GEN_SRAND_MRAND:
-      memcpy((void*)p_cb->rand, rand, 8);
-      smp_generate_rand_cont(p_cb, NULL);
-      break;
-
-    case SMP_GEN_SRAND_MRAND_CONT:
-      memcpy((void*)&p_cb->rand[8], rand, 8);
-      smp_generate_confirm(p_cb, NULL);
-      break;
-
-    case SMP_GEN_DIV_LTK:
-      STREAM_TO_UINT16(p_cb->div, pp);
-      smp_generate_ltk_cont(p_cb, NULL);
-      break;
-
-    case SMP_GEN_DIV_CSRK:
-      STREAM_TO_UINT16(p_cb->div, pp);
-      smp_compute_csrk(p_cb, NULL);
-      break;
-
-    case SMP_GEN_TK:
-      smp_proc_passkey(p_cb, rand);
-      break;
-
-    case SMP_GEN_RAND_V:
-      memcpy(p_cb->enc_rand, rand, BT_OCTET8_LEN);
-      smp_generate_y(p_cb, NULL);
-      break;
-
-    case SMP_GENERATE_PRIVATE_KEY_0_7:
-    case SMP_GENERATE_PRIVATE_KEY_8_15:
-    case SMP_GENERATE_PRIVATE_KEY_16_23:
-    case SMP_GENERATE_PRIVATE_KEY_24_31:
-      smp_continue_private_key_creation(p_cb, rand);
-      break;
-
-    case SMP_GEN_NONCE_0_7:
-      memcpy((void*)p_cb->rand, rand, 8);
-      smp_finish_nonce_generation(p_cb);
-      break;
-
-    case SMP_GEN_NONCE_8_15:
-      memcpy((void*)&p_cb->rand[8], rand, 8);
-      smp_process_new_nonce(p_cb);
-      break;
-  }
+  btsnd_hcic_ble_rand(Bind(
+      [](tSMP_CB* p_cb, BT_OCTET8 rand) {
+        memcpy((void*)p_cb->rand, rand, BT_OCTET8_LEN);
+        btsnd_hcic_ble_rand(Bind(
+            [](tSMP_CB* p_cb, BT_OCTET8 rand) {
+              memcpy((void*)&p_cb->rand[8], rand, BT_OCTET8_LEN);
+              SMP_TRACE_DEBUG("%s round %d", __func__, p_cb->round);
+              /* notifies SM that it has new nonce. */
+              smp_sm_event(p_cb, SMP_HAVE_LOC_NONCE_EVT, NULL);
+            },
+            p_cb));
+      },
+      p_cb));
 }