/******************************************************************************* ** ** Function gatt_check_enc_req ** ** Description check link security. ** ** Returns TRUE if encrypted, otherwise FALSE. ** *******************************************************************************/ BOOLEAN gatt_security_check_start(tGATT_CLCB *p_clcb) { tGATT_TCB *p_tcb = p_clcb->p_tcb; tGATT_SEC_ACTION gatt_sec_act; tBTM_BLE_SEC_ACT btm_ble_sec_act; BOOLEAN status = TRUE; #if (SMP_INCLUDED == TRUE) tBTM_STATUS btm_status; #endif ///SMP_INCLUDED == TRUE tGATT_SEC_ACTION sec_act_old = gatt_get_sec_act(p_tcb); gatt_sec_act = gatt_determine_sec_act(p_clcb); if (sec_act_old == GATT_SEC_NONE) { gatt_set_sec_act(p_tcb, gatt_sec_act); } switch (gatt_sec_act ) { case GATT_SEC_SIGN_DATA: #if (SMP_INCLUDED == TRUE) GATT_TRACE_DEBUG("gatt_security_check_start: Do data signing"); gatt_sign_data(p_clcb); #endif ///SMP_INCLUDED == TRUE break; case GATT_SEC_ENCRYPT: case GATT_SEC_ENCRYPT_NO_MITM: case GATT_SEC_ENCRYPT_MITM: if (sec_act_old < GATT_SEC_ENCRYPT) { GATT_TRACE_DEBUG("gatt_security_check_start: Encrypt now or key upgreade first"); gatt_convert_sec_action(gatt_sec_act, &btm_ble_sec_act); #if (SMP_INCLUDED == TRUE) btm_status = BTM_SetEncryption(p_tcb->peer_bda, p_tcb->transport , gatt_enc_cmpl_cback, &btm_ble_sec_act); if ( (btm_status != BTM_SUCCESS) && (btm_status != BTM_CMD_STARTED)) { GATT_TRACE_ERROR("gatt_security_check_start BTM_SetEncryption failed btm_status=%d", btm_status); status = FALSE; } #endif ///SMP_INCLUDED == TRUE } if (status) { gatt_add_pending_enc_channel_clcb (p_tcb, p_clcb); } break; case GATT_SEC_ENC_PENDING: gatt_add_pending_enc_channel_clcb (p_tcb, p_clcb); /* wait for link encrypotion to finish */ break; default: gatt_sec_check_complete(TRUE, p_clcb, gatt_sec_act); break; } if (status == FALSE) { gatt_set_sec_act(p_tcb, GATT_SEC_NONE); gatt_set_ch_state(p_tcb, GATT_CH_OPEN); } return status; }
/******************************************************************************* ** ** Function gatt_enc_cmpl_cback ** ** Description link encryption complete callback. ** ** Returns ** *******************************************************************************/ void gatt_enc_cmpl_cback(BD_ADDR bd_addr, tBT_TRANSPORT transport, void *p_ref_data, tBTM_STATUS result) { tGATT_TCB *p_tcb; UINT8 sec_flag; BOOLEAN status = FALSE; tGATT_PENDING_ENC_CLCB *p_buf; UINT16 count; UNUSED(p_ref_data); GATT_TRACE_DEBUG("gatt_enc_cmpl_cback"); if ((p_tcb = gatt_find_tcb_by_addr(bd_addr, transport)) != NULL) { if (gatt_get_sec_act(p_tcb) == GATT_SEC_ENC_PENDING) return; if ((p_buf = (tGATT_PENDING_ENC_CLCB *)GKI_dequeue (&p_tcb->pending_enc_clcb)) != NULL) { if (result == BTM_SUCCESS) { if (gatt_get_sec_act(p_tcb) == GATT_SEC_ENCRYPT_MITM ) { BTM_GetSecurityFlagsByTransport(bd_addr, &sec_flag, transport); if (sec_flag & BTM_SEC_FLAG_LKEY_AUTHED) { status = TRUE; } } else { status = TRUE; } } gatt_sec_check_complete(status , p_buf->p_clcb, p_tcb->sec_act); GKI_freebuf(p_buf); /* start all other pending operation in queue */ count = p_tcb->pending_enc_clcb.count; for (; count > 0; count --) { if ((p_buf = (tGATT_PENDING_ENC_CLCB *)GKI_dequeue (&p_tcb->pending_enc_clcb)) != NULL) { gatt_security_check_start(p_buf->p_clcb); GKI_freebuf(p_buf); } else break; } } else { GATT_TRACE_ERROR("Unknown operation encryption completed"); } } else { GATT_TRACE_ERROR("enc callback for unknown bd_addr"); } }