/******************************************************************************* ** ** Function btm_ble_match_random_bda ** ** Description This function match the random address to the appointed device ** record, starting from calculating IRK. If record index exceed ** the maximum record number, matching failed and send callback. ** ** Returns None. ** *******************************************************************************/ static BOOLEAN btm_ble_match_random_bda(UINT16 rec_index) { /* use the 3 MSB of bd address as prand */ tBTM_LE_RANDOM_CB *p_mgnt_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb; UINT8 rand[3]; rand[0] = p_mgnt_cb->random_bda[2]; rand[1] = p_mgnt_cb->random_bda[1]; rand[2] = p_mgnt_cb->random_bda[0]; BTM_TRACE_EVENT("%s rec_index = %d", __func__, rec_index); if (rec_index < BTM_SEC_MAX_DEVICE_RECORDS) { tSMP_ENC output; tBTM_SEC_DEV_REC *p_dev_rec; p_dev_rec = &btm_cb.sec_dev_rec[rec_index]; BTM_TRACE_DEBUG("sec_flags = %02x device_type = %d", p_dev_rec->sec_flags, p_dev_rec->device_type); if ((p_dev_rec->device_type & BT_DEVICE_TYPE_BLE) && (p_dev_rec->ble.key_type & BTM_LE_KEY_PID)) { /* generate X = E irk(R0, R1, R2) and R is random address 3 LSO */ SMP_Encrypt(p_dev_rec->ble.keys.irk, BT_OCTET16_LEN, &rand[0], 3, &output); return btm_ble_proc_resolve_x(&output); } else { // not completed return FALSE; } } else { /* no match found */ btm_ble_resolve_address_cmpl(); return TRUE; } }
/******************************************************************************* ** ** Function btm_gen_resolve_paddr_low ** ** Description This function is called when random address has generate the ** random number base for low 3 byte bd address. ** ** Returns void ** *******************************************************************************/ void btm_gen_resolve_paddr_low(tBTM_RAND_ENC *p) { #if (BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE) tBTM_LE_RANDOM_CB *p_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb; tSMP_ENC output; BTM_TRACE_EVENT ("btm_gen_resolve_paddr_low"); if (p) { p->param_buf[2] &= (~BLE_RESOLVE_ADDR_MASK); p->param_buf[2] |= BLE_RESOLVE_ADDR_MSB; p_cb->private_addr[2] = p->param_buf[0]; p_cb->private_addr[1] = p->param_buf[1]; p_cb->private_addr[0] = p->param_buf[2]; /* encrypt with ur IRK */ if (!SMP_Encrypt(btm_cb.devcb.id_keys.irk, BT_OCTET16_LEN, p->param_buf, 3, &output)) { btm_gen_resolve_paddr_cmpl(NULL); } else { btm_gen_resolve_paddr_cmpl(&output); } } #endif }
/******************************************************************************* ** ** Function smp_genenrate_ltk_cont ** ** Description This function is to calculate LTK = d1(ER, DIV, 0)= e(ER, DIV) ** ** Returns void ** *******************************************************************************/ static void smp_genenrate_ltk_cont(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) { BT_OCTET16 er; tSMP_ENC output; tSMP_STATUS status = SMP_PAIR_FAIL_UNKNOWN; SMP_TRACE_DEBUG0 ("smp_genenrate_ltk_cont "); BTM_GetDeviceEncRoot(er); /* LTK = d1(ER, DIV, 0)= e(ER, DIV)*/ if (!SMP_Encrypt(er, BT_OCTET16_LEN, (UINT8 *)&p_cb->div, sizeof(UINT16), &output)) { SMP_TRACE_ERROR0("smp_genenrate_ltk_cont failed"); 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 btm_ble_addr_resolvable ** ** Description This function checks if a RPA is resolvable by the device key. ** ** Returns TRUE is resolvable; FALSE otherwise. ** *******************************************************************************/ BOOLEAN btm_ble_addr_resolvable (BD_ADDR rpa, tBTM_SEC_DEV_REC *p_dev_rec) { BOOLEAN rt = FALSE; #if (SMP_INCLUDED == TRUE) if (!BTM_BLE_IS_RESOLVE_BDA(rpa)) { return rt; } UINT8 rand[3]; tSMP_ENC output; if ((p_dev_rec->device_type & BT_DEVICE_TYPE_BLE) && (p_dev_rec->ble.key_type & BTM_LE_KEY_PID)) { BTM_TRACE_DEBUG("%s try to resolve", __func__); /* use the 3 MSB of bd address as prand */ rand[0] = rpa[2]; rand[1] = rpa[1]; rand[2] = rpa[0]; /* generate X = E irk(R0, R1, R2) and R is random address 3 LSO */ SMP_Encrypt(p_dev_rec->ble.keys.irk, BT_OCTET16_LEN, &rand[0], 3, &output); rand[0] = rpa[5]; rand[1] = rpa[4]; rand[2] = rpa[3]; if (!memcmp(output.param_buf, &rand[0], 3)) { btm_ble_init_pseudo_addr (p_dev_rec, rpa); rt = TRUE; } } #endif ///SMP_INCLUDED == TRUE return rt; }
/******************************************************************************* ** ** Function smp_calculate_comfirm ** ** Description This function is called to calculate Confirm value. ** ** Returns void ** *******************************************************************************/ void smp_calculate_comfirm (tSMP_CB *p_cb, BT_OCTET16 rand, BD_ADDR bda) { BT_OCTET16 p1; tSMP_ENC output; tSMP_STATUS status = SMP_PAIR_FAIL_UNKNOWN; SMP_TRACE_DEBUG0 ("smp_calculate_comfirm "); /* generate p1 = pres || preq || rat' || iat' */ smp_gen_p1_4_confirm(p_cb, p1); /* p1 = rand XOR p1 */ smp_xor_128(p1, rand); smp_debug_print_nbyte_little_endian ((UINT8 *)p1, (const UINT8 *)"P1' = r XOR p1", 16); /* calculate e(k, r XOR p1), where k = TK */ if (!SMP_Encrypt(p_cb->tk, BT_OCTET16_LEN, p1, BT_OCTET16_LEN, &output)) { SMP_TRACE_ERROR0("smp_generate_csrk failed"); smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &status); } else { smp_calculate_comfirm_cont(p_cb, &output); } }
/******************************************************************************* ** ** 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_generate_stk ** ** Description This function is called to generate STK calculated by running ** AES with the TK value as key and a concatenation of the random ** values. ** ** Returns void ** *******************************************************************************/ void smp_generate_stk (tSMP_CB *p_cb, tSMP_INT_DATA *p_data) { BT_OCTET16 ptext; UINT8 *p = ptext; tSMP_ENC output; tSMP_STATUS status = SMP_PAIR_FAIL_UNKNOWN; SMP_TRACE_DEBUG0 ("smp_generate_stk "); memset(p, 0, BT_OCTET16_LEN); if (p_cb->role == HCI_ROLE_MASTER) { memcpy(p, p_cb->rand, BT_OCTET8_LEN); memcpy(&p[BT_OCTET8_LEN], p_cb->rrand, BT_OCTET8_LEN); } else { memcpy(p, p_cb->rrand, BT_OCTET8_LEN); memcpy(&p[BT_OCTET8_LEN], p_cb->rand, BT_OCTET8_LEN); } /* generate STK = Etk(rand|rrand)*/ if (!SMP_Encrypt( p_cb->tk, BT_OCTET16_LEN, ptext, BT_OCTET16_LEN, &output)) { SMP_TRACE_ERROR0("smp_generate_stk failed"); smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &status); } else { smp_process_stk(p_cb, &output); } }
/******************************************************************************* ** ** Function cmac_generate_subkey ** ** Description This is the function to generate the two subkeys. ** ** Parameters key - CMAC key, expect SRK when used by SMP. ** ** Returns void ** *******************************************************************************/ static BOOLEAN cmac_generate_subkey(BT_OCTET16 key) { BT_OCTET16 z = {0}; BOOLEAN ret = TRUE; tSMP_ENC output; SMP_TRACE_EVENT (" cmac_generate_subkey"); if (SMP_Encrypt(key, BT_OCTET16_LEN, z, BT_OCTET16_LEN, &output)) { cmac_subkey_cont(&output);; } else { ret = FALSE; } return ret; }
/******************************************************************************* ** ** 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, tSMP_INT_DATA *p) { BT_OCTET16 dhk; tSMP_ENC output; tSMP_STATUS status = SMP_PAIR_FAIL_UNKNOWN; SMP_TRACE_DEBUG0 ("smp_generate_y "); BTM_GetDeviceDHK(dhk); if (!SMP_Encrypt(dhk, BT_OCTET16_LEN, p_cb->enc_rand, BT_OCTET8_LEN, &output)) { SMP_TRACE_ERROR0("smp_generate_y failed"); smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &status); } else { smp_process_ediv(p_cb, &output); } }
/******************************************************************************* ** ** Function cmac_aes_k_calculate ** ** Description This function is the calculation of block cipher using AES-128. ** ** Returns void ** *******************************************************************************/ static BOOLEAN cmac_aes_k_calculate(BT_OCTET16 key, UINT8 *p_signature, UINT16 tlen) { tSMP_ENC output; UINT8 i = 1, err = 0; UINT8 x[16] = {0}; UINT8 *p_mac; SMP_TRACE_EVENT ("cmac_aes_k_calculate "); while (i <= cmac_cb.round) { smp_xor_128(&cmac_cb.text[(cmac_cb.round - i)*BT_OCTET16_LEN], x); /* Mi' := Mi (+) X */ if (!SMP_Encrypt(key, BT_OCTET16_LEN, &cmac_cb.text[(cmac_cb.round - i)*BT_OCTET16_LEN], BT_OCTET16_LEN, &output)) { err = 1; break; } memcpy(x, output.param_buf, BT_OCTET16_LEN); i ++; } if (!err) { p_mac = output.param_buf + (BT_OCTET16_LEN - tlen); memcpy(p_signature, p_mac, tlen); SMP_TRACE_DEBUG("tlen = %d p_mac = %d", tlen, p_mac); SMP_TRACE_DEBUG("p_mac[0] = 0x%02x p_mac[1] = 0x%02x p_mac[2] = 0x%02x p_mac[3] = 0x%02x", *p_mac, *(p_mac + 1), *(p_mac + 2), *(p_mac + 3)); SMP_TRACE_DEBUG("p_mac[4] = 0x%02x p_mac[5] = 0x%02x p_mac[6] = 0x%02x p_mac[7] = 0x%02x", *(p_mac + 4), *(p_mac + 5), *(p_mac + 6), *(p_mac + 7)); return TRUE; } else return FALSE; }
/******************************************************************************* ** ** Function smp_calculate_comfirm_cont ** ** Description This function is called when SConfirm/MConfirm is generated ** proceed to send the Confirm request/response to peer device. ** ** Returns void ** *******************************************************************************/ static void smp_calculate_comfirm_cont(tSMP_CB *p_cb, tSMP_ENC *p) { BT_OCTET16 p2; tSMP_ENC output; tSMP_STATUS status = SMP_PAIR_FAIL_UNKNOWN; SMP_TRACE_DEBUG0 ("smp_calculate_comfirm_cont "); #if SMP_DEBUG == TRUE SMP_TRACE_DEBUG0("Confirm step 1 p1' = e(k, r XOR p1) Generated"); smp_debug_print_nbyte_little_endian (p->param_buf, (const UINT8 *)"C1", 16); #endif smp_gen_p2_4_confirm(p_cb, p2); /* calculate p2 = (p1' XOR p2) */ smp_xor_128(p2, p->param_buf); smp_debug_print_nbyte_little_endian ((UINT8 *)p2, (const UINT8 *)"p2' = C1 xor p2", 16); /* calculate: Confirm = E(k, p1' XOR p2) */ if (!SMP_Encrypt(p_cb->tk, BT_OCTET16_LEN, p2, BT_OCTET16_LEN, &output)) { SMP_TRACE_ERROR0("smp_calculate_comfirm_cont failed"); smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &status); } else { switch (p_cb->rand_enc_proc) { case SMP_GEN_CONFIRM: smp_process_confirm(p_cb, &output); break; case SMP_GEN_COMPARE: smp_process_compare(p_cb, &output); break; } } }