/******************************************************************************* ** ** Function smp_compute_csrk ** ** Description This function is called to calculate CSRK ** ** ** Returns void ** *******************************************************************************/ void smp_compute_csrk(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) { BT_OCTET16 er; UINT8 buffer[4]; /* for (r || DIV) r=1*/ UINT16 r=1; UINT8 *p=buffer; tSMP_ENC output; tSMP_STATUS status = SMP_PAIR_FAIL_UNKNOWN; SMP_TRACE_DEBUG1 ("smp_compute_csrk div=%x", p_cb->div); BTM_GetDeviceEncRoot(er); /* CSRK = d1(ER, DIV, 1) */ UINT16_TO_STREAM(p, p_cb->div); UINT16_TO_STREAM(p, r); if (!SMP_Encrypt(er, BT_OCTET16_LEN, buffer, 4, &output)) { SMP_TRACE_ERROR0("smp_generate_csrk failed"); smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &status); } else { memcpy((void *)p_cb->csrk, output.param_buf, BT_OCTET16_LEN); smp_send_csrk_info(p_cb, 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(tBTM_RAND_ENC *p) { tSMP_CB *p_cb = &smp_cb; UINT8 *pp = p->param_buf; UINT8 failure = SMP_PAIR_FAIL_UNKNOWN; UINT8 state = p_cb->rand_enc_proc & ~0x80; SMP_TRACE_DEBUG1 ("smp_rand_back state=0x%x", state); if (p && p->status == HCI_SUCCESS) { switch (state) { case SMP_GEN_SRAND_MRAND: memcpy((void *)p_cb->rand, p->param_buf, p->param_len); smp_genenrate_rand_cont(p_cb, NULL); break; case SMP_GEN_SRAND_MRAND_CONT: memcpy((void *)&p_cb->rand[8], p->param_buf, p->param_len); smp_genenrate_confirm(p_cb, NULL); break; case SMP_GEN_DIV_LTK: STREAM_TO_UINT16(p_cb->div, pp); smp_genenrate_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, p); break; case SMP_GEN_RAND_V: memcpy(p_cb->enc_rand, p->param_buf, BT_OCTET8_LEN); smp_generate_y(p_cb, NULL); break; } return; } SMP_TRACE_ERROR1("smp_rand_back Key generation failed: (%d)", p_cb->rand_enc_proc); smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &failure); }
/******************************************************************************* ** Function smp_set_state ** Returns None *******************************************************************************/ void smp_set_state(tSMP_STATE state) { if (state < SMP_ST_MAX) { SMP_TRACE_DEBUG4( "State change: %s(%d) ==> %s(%d)", smp_get_state_name(smp_cb.state), smp_cb.state, smp_get_state_name(state), state ); smp_cb.state = state; } else { SMP_TRACE_DEBUG1("smp_set_state invalid state =%d", state ); } }
/******************************************************************************* ** ** Function smp_sm_event ** ** Description Handle events to the state machine. It looks up the entry ** in the smp_entry_table array. ** If it is a valid entry, it gets the state table.Set the next state, ** if not NULL state.Execute the action function according to the ** state table. If the state returned by action function is not NULL ** state, adjust the new state to the returned state.If (api_evt != MAX), ** call callback function. ** ** Returns void. ** *******************************************************************************/ void smp_sm_event(tSMP_CB *p_cb, tSMP_EVENT event, void *p_data) { UINT8 curr_state = p_cb->state; tSMP_SM_TBL state_table; UINT8 action, entry, i; tSMP_ENTRY_TBL entry_table = smp_entry_table[p_cb->role]; SMP_TRACE_EVENT0("main smp_sm_event"); if (curr_state >= SMP_ST_MAX) { SMP_TRACE_DEBUG1( "Invalid state: %d", curr_state) ; return; } SMP_TRACE_DEBUG5( "SMP Role: %s State: [%s (%d)], Event: [%s (%d)]",\ (p_cb->role == 0x01) ?"Slave" : "Master", smp_get_state_name( p_cb->state), p_cb->state, smp_get_event_name(event), event) ; /* look up the state table for the current state */ /* lookup entry /w event & curr_state */ /* If entry is ignore, return. * Otherwise, get state table (according to curr_state or all_state) */ if ( (entry = entry_table[event - 1][curr_state]) != SMP_SM_IGNORE ) { if (entry & SMP_ALL_TBL_MASK) { entry &= ~SMP_ALL_TBL_MASK; state_table = smp_all_table; } else state_table = smp_state_table[curr_state][p_cb->role]; } else { SMP_TRACE_DEBUG4( "Ignore event [%s (%d)] in state [%s (%d)]", smp_get_event_name(event), event, smp_get_state_name(curr_state), curr_state); return; } /* Get possible next state from state table. */ smp_set_state(state_table[entry-1][SMP_SME_NEXT_STATE]); /* If action is not ignore, clear param, exec action and get next state. * The action function may set the Param for cback. * Depending on param, call cback or free buffer. */ /* execute action */ /* execute action functions */ for (i = 0; i < SMP_NUM_ACTIONS; i++) { if ((action = state_table[entry-1][i]) != SMP_SM_NO_ACTION) { (*smp_sm_action[action])(p_cb, (tSMP_INT_DATA *)p_data); } else { break; } } SMP_TRACE_DEBUG1( "result state = %s", smp_get_state_name( p_cb->state ) ) ; }
/******************************************************************************* ** ** Function smp_sm_event ** ** Description Handle events to the state machine. It looks up the entry ** in the smp_entry_table array. ** If it is a valid entry, it gets the state table.Set the next state, ** if not NULL state.Execute the action function according to the ** state table. If the state returned by action function is not NULL ** state, adjust the new state to the returned state.If (api_evt != MAX), ** call callback function. ** ** Returns void. ** *******************************************************************************/ void smp_sm_event(tSMP_CB *p_cb, tSMP_EVENT event, void *p_data) { UINT8 curr_state = p_cb->state; tSMP_SM_TBL state_table; UINT8 action, entry, i; tSMP_ENTRY_TBL entry_table = smp_entry_table[p_cb->role]; SMP_TRACE_EVENT0("main smp_sm_event"); if (curr_state >= SMP_ST_MAX) { SMP_TRACE_DEBUG1( "Invalid state: %d", curr_state) ; return; } SMP_TRACE_DEBUG5( "SMP Role: %s State: [%s (%d)], Event: [%s (%d)]",\ (p_cb->role == 0x01) ?"Slave" : "Master", smp_get_state_name( p_cb->state), p_cb->state, smp_get_event_name(event), event) ; /* look up the state table for the current state */ /* lookup entry /w event & curr_state */ /* If entry is ignore, return. * Otherwise, get state table (according to curr_state or all_state) */ if ((event < SMP_MAX_EVT) && ( (entry = entry_table[event - 1][curr_state]) != SMP_SM_IGNORE )) { if (entry & SMP_ALL_TBL_MASK) { entry &= ~SMP_ALL_TBL_MASK; state_table = smp_all_table; } else state_table = smp_state_table[curr_state][p_cb->role]; } else { #ifdef BLUETOOTH_RTK if(event == SMP_MASTER_ID_EVT && p_cb->state == SMP_ST_ENC_PENDING) { SMP_TRACE_EVENT1("need to pending event(%d) until SMP_BOND_REQ_EVT", event); master_id_pending.pending = TRUE; master_id_pending.p_cb = p_cb; master_id_pending.event = event; master_id_pending.p_data = GKI_getbuf(sizeof(BT_OCTET16)+sizeof(BT_OCTET8)); memcpy(master_id_pending.p_data, p_data, sizeof(BT_OCTET16)+sizeof(BT_OCTET8)); } else if(event == SMP_ENCRPTION_INFO_EVT && p_cb->state == SMP_ST_ENC_PENDING) { SMP_TRACE_EVENT1("need to pending event(%d) until SMP_BOND_REQ_EVT", event); enc_info_pending.pending = TRUE; enc_info_pending.p_cb = p_cb; enc_info_pending.event = event; enc_info_pending.p_data = GKI_getbuf(sizeof(BT_OCTET16)); memcpy(enc_info_pending.p_data, p_data, sizeof(BT_OCTET16)); } else #endif SMP_TRACE_DEBUG4( "Ignore event [%s (%d)] in state [%s (%d)]", smp_get_event_name(event), event, smp_get_state_name(curr_state), curr_state); return; } /* Get possible next state from state table. */ smp_set_state(state_table[entry-1][SMP_SME_NEXT_STATE]); /* If action is not ignore, clear param, exec action and get next state. * The action function may set the Param for cback. * Depending on param, call cback or free buffer. */ /* execute action */ /* execute action functions */ for (i = 0; i < SMP_NUM_ACTIONS; i++) { if ((action = state_table[entry-1][i]) != SMP_SM_NO_ACTION) { (*smp_sm_action[action])(p_cb, (tSMP_INT_DATA *)p_data); } else { break; } } SMP_TRACE_DEBUG1( "result state = %s", smp_get_state_name( p_cb->state ) ) ; #ifdef BLUETOOTH_RTK if(event == SMP_BOND_REQ_EVT && enc_info_pending.pending == TRUE) { SMP_TRACE_EVENT0("to process pending event SMP_ENCRPTION_INFO_EVT"); smp_sm_event(enc_info_pending.p_cb, enc_info_pending.event, enc_info_pending.p_data); enc_info_pending.pending = FALSE; GKI_freebuf(enc_info_pending.p_data); } if(event == SMP_BOND_REQ_EVT && master_id_pending.pending == TRUE) { SMP_TRACE_EVENT0("to process pending event SMP_ID_INFO_EVT"); smp_sm_event(master_id_pending.p_cb, master_id_pending.event, master_id_pending.p_data); master_id_pending.pending = FALSE; GKI_freebuf(master_id_pending.p_data); } if(event == SMP_L2CAP_CONN_EVT && p_cb->state == SMP_ST_IDLE) { SMP_TRACE_EVENT0("clean enc_info_pending"); memset(&enc_info_pending, 0 , sizeof(enc_info_pending)); memset(&master_id_pending, 0 , sizeof(master_id_pending)); } #endif }