/******************************************************************************* ** ** 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"); } }
/******************************************************************************* ** ** Function gatt_get_link_encrypt_status ** ** Description This routine get the encryption status of the specified link ** ** ** Returns tGATT_STATUS link encryption status ** *******************************************************************************/ tGATT_STATUS gatt_get_link_encrypt_status(tGATT_TCB *p_tcb) { tGATT_STATUS encrypt_status = GATT_NOT_ENCRYPTED; UINT8 sec_flag = 0; BTM_GetSecurityFlagsByTransport(p_tcb->peer_bda, &sec_flag, p_tcb->transport); if ((sec_flag & BTM_SEC_FLAG_ENCRYPTED) && (sec_flag & BTM_SEC_FLAG_LKEY_KNOWN)) { encrypt_status = GATT_ENCRYPED_NO_MITM; if (sec_flag & BTM_SEC_FLAG_LKEY_AUTHED) { encrypt_status = GATT_ENCRYPED_MITM; } } GATT_TRACE_DEBUG("gatt_get_link_encrypt_status status=0x%x", encrypt_status); return encrypt_status ; }
/******************************************************************************* ** ** Function gatt_determine_sec_act ** ** Description This routine determine the security action based on auth_request and ** current link status ** ** Returns tGATT_SEC_ACTION security action ** *******************************************************************************/ tGATT_SEC_ACTION gatt_determine_sec_act(tGATT_CLCB *p_clcb ) { tGATT_SEC_ACTION act = GATT_SEC_OK; UINT8 sec_flag; tGATT_TCB *p_tcb = p_clcb->p_tcb; tGATT_AUTH_REQ auth_req = p_clcb->auth_req; BOOLEAN is_link_encrypted = FALSE; BOOLEAN is_link_key_known = FALSE; BOOLEAN is_key_mitm = FALSE; #if (SMP_INCLUDED == TRUE) UINT8 key_type; tBTM_BLE_SEC_REQ_ACT sec_act = BTM_LE_SEC_NONE; #endif ///SMP_INCLUDED == TRUE if (auth_req == GATT_AUTH_REQ_NONE ) { return act; } BTM_GetSecurityFlagsByTransport(p_tcb->peer_bda, &sec_flag, p_clcb->p_tcb->transport); #if (SMP_INCLUDED == TRUE) btm_ble_link_sec_check(p_tcb->peer_bda, auth_req, &sec_act); #endif ///SMP_INCLUDED == TRUE /* if a encryption is pending, need to wait */ if ( #if (SMP_INCLUDED == TRUE) sec_act == BTM_BLE_SEC_REQ_ACT_DISCARD && #endif ///SMP_INCLUDED == TRUE auth_req != GATT_AUTH_REQ_NONE) { return GATT_SEC_ENC_PENDING; } if (sec_flag & (BTM_SEC_FLAG_ENCRYPTED | BTM_SEC_FLAG_LKEY_KNOWN)) { if (sec_flag & BTM_SEC_FLAG_ENCRYPTED) { is_link_encrypted = TRUE; } is_link_key_known = TRUE; if (sec_flag & BTM_SEC_FLAG_LKEY_AUTHED) { is_key_mitm = TRUE; } } /* first check link key upgrade required or not */ switch (auth_req) { case GATT_AUTH_REQ_MITM: case GATT_AUTH_REQ_SIGNED_MITM: if (!is_key_mitm) { act = GATT_SEC_ENCRYPT_MITM; } break; case GATT_AUTH_REQ_NO_MITM: case GATT_AUTH_REQ_SIGNED_NO_MITM: if (!is_link_key_known) { act = GATT_SEC_ENCRYPT_NO_MITM; } break; default: break; } /* now check link needs to be encrypted or not if the link key upgrade is not required */ if (act == GATT_SEC_OK) { if (p_tcb->transport == BT_TRANSPORT_LE && (p_clcb->operation == GATTC_OPTYPE_WRITE) && (p_clcb->op_subtype == GATT_WRITE_NO_RSP)) { /* this is a write command request check data signing required or not */ if (!is_link_encrypted) { #if (SMP_INCLUDED == TRUE) btm_ble_get_enc_key_type(p_tcb->peer_bda, &key_type); #endif ///SMP_INCLUDED == TRUE if ( #if (SMP_INCLUDED == TRUE) (key_type & BTM_LE_KEY_LCSRK) && #endif ///SMP_INCLUDED == TRUE ((auth_req == GATT_AUTH_REQ_SIGNED_NO_MITM) || (auth_req == GATT_AUTH_REQ_SIGNED_MITM))) { act = GATT_SEC_SIGN_DATA; } else { act = GATT_SEC_ENCRYPT; } } } else { if (!is_link_encrypted) { act = GATT_SEC_ENCRYPT; } } } return act ; }