diff options
Diffstat (limited to 'stack/smp/smp_api.c')
-rw-r--r-- | stack/smp/smp_api.c | 299 |
1 files changed, 283 insertions, 16 deletions
diff --git a/stack/smp/smp_api.c b/stack/smp/smp_api.c index 2ebf9538a..4d7b16df9 100644 --- a/stack/smp/smp_api.c +++ b/stack/smp/smp_api.c @@ -35,7 +35,7 @@ #include "hcimsgs.h" #include "btu.h" - + #include "p_256_ecc_pp.h" /******************************************************************************* ** @@ -48,8 +48,6 @@ *******************************************************************************/ void SMP_Init(void) { - - SMP_TRACE_EVENT ("SMP_Init"); memset(&smp_cb, 0, sizeof(tSMP_CB)); #if defined(SMP_INITIAL_TRACE_LEVEL) @@ -57,8 +55,11 @@ void SMP_Init(void) #else smp_cb.trace_level = BT_TRACE_LEVEL_NONE; /* No traces */ #endif + SMP_TRACE_EVENT ("%s", __FUNCTION__); smp_l2cap_if_init(); + /* initialization of P-256 parameters */ + p_256_init_curve(KEY_LENGTH_DWORDS_P256); } @@ -131,8 +132,10 @@ tSMP_STATUS SMP_Pair (BD_ADDR bd_addr) tSMP_CB *p_cb = &smp_cb; UINT8 status = SMP_PAIR_INTERNAL_ERR; - BTM_TRACE_EVENT ("SMP_Pair state=%d flag=0x%x ", p_cb->state, p_cb->flags); - if (p_cb->state != SMP_ST_IDLE || p_cb->flags & SMP_PAIR_FLAGS_WE_STARTED_DD) + SMP_TRACE_EVENT ("%s state=%d br_state=%d flag=0x%x ", + __FUNCTION__, p_cb->state, p_cb->br_state, p_cb->flags); + if (p_cb->state != SMP_STATE_IDLE || p_cb->flags & SMP_PAIR_FLAGS_WE_STARTED_DD || + p_cb->smp_over_br) { /* pending security on going, reject this one */ return SMP_BUSY; @@ -145,7 +148,7 @@ tSMP_STATUS SMP_Pair (BD_ADDR bd_addr) if (!L2CA_ConnectFixedChnl (L2CAP_SMP_CID, bd_addr)) { - SMP_TRACE_ERROR("SMP_Pair: L2C connect fixed channel failed."); + SMP_TRACE_ERROR("%s: L2C connect fixed channel failed.", __FUNCTION__); smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &status); return status; } @@ -154,6 +157,49 @@ tSMP_STATUS SMP_Pair (BD_ADDR bd_addr) } } +/******************************************************************************* +** +** Function SMP_BR_PairWith +** +** Description This function is called to start a SMP pairing over BR/EDR. +** Device support one SMP pairing at one time. +** +** Parameters bd_addr - peer device bd address. +** +** Returns SMP_STARTED if pairing started, otherwise reason for failure. +** +*******************************************************************************/ +tSMP_STATUS SMP_BR_PairWith (BD_ADDR bd_addr) +{ + tSMP_CB *p_cb = &smp_cb; + UINT8 status = SMP_PAIR_INTERNAL_ERR; + + SMP_TRACE_EVENT ("%s state=%d br_state=%d flag=0x%x ", + __func__, p_cb->state, p_cb->br_state, p_cb->flags); + + if (p_cb->state != SMP_STATE_IDLE || + p_cb->smp_over_br || + p_cb->flags & SMP_PAIR_FLAGS_WE_STARTED_DD) + { + /* pending security on going, reject this one */ + return SMP_BUSY; + } + + p_cb->role = HCI_ROLE_MASTER; + p_cb->flags = SMP_PAIR_FLAGS_WE_STARTED_DD; + p_cb->smp_over_br = TRUE; + + memcpy (p_cb->pairing_bda, bd_addr, BD_ADDR_LEN); + + if (!L2CA_ConnectFixedChnl (L2CAP_SMP_BR_CID, bd_addr)) + { + SMP_TRACE_ERROR("%s: L2C connect fixed channel failed.",__FUNCTION__); + smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &status); + return status; + } + + return SMP_STARTED; +} /******************************************************************************* ** @@ -173,7 +219,7 @@ BOOLEAN SMP_PairCancel (BD_ADDR bd_addr) BOOLEAN status = FALSE; BTM_TRACE_EVENT ("SMP_CancelPair state=%d flag=0x%x ", p_cb->state, p_cb->flags); - if ( (p_cb->state != SMP_ST_IDLE) && + if ( (p_cb->state != SMP_STATE_IDLE) && (!memcmp (p_cb->pairing_bda, bd_addr, BD_ADDR_LEN)) ) { p_cb->is_pair_cancel = TRUE; @@ -200,11 +246,27 @@ BOOLEAN SMP_PairCancel (BD_ADDR bd_addr) void SMP_SecurityGrant(BD_ADDR bd_addr, UINT8 res) { SMP_TRACE_EVENT ("SMP_SecurityGrant "); - if (smp_cb.state != SMP_ST_WAIT_APP_RSP || + + if (smp_cb.smp_over_br) + { + if (smp_cb.br_state != SMP_BR_STATE_WAIT_APP_RSP || + smp_cb.cb_evt != SMP_SEC_REQUEST_EVT || + memcmp (smp_cb.pairing_bda, bd_addr, BD_ADDR_LEN)) + { + return; + } + + /* clear the SMP_SEC_REQUEST_EVT event after get grant */ + /* avoid generating duplicate pair request */ + smp_cb.cb_evt = 0; + smp_br_state_machine_event(&smp_cb, SMP_BR_API_SEC_GRANT_EVT, &res); + return; + } + + if (smp_cb.state != SMP_STATE_WAIT_APP_RSP || smp_cb.cb_evt != SMP_SEC_REQUEST_EVT || memcmp (smp_cb.pairing_bda, bd_addr, BD_ADDR_LEN)) return; - /* clear the SMP_SEC_REQUEST_EVT event after get grant */ /* avoid generate duplicate pair request */ smp_cb.cb_evt = 0; @@ -228,7 +290,6 @@ void SMP_PasskeyReply (BD_ADDR bd_addr, UINT8 res, UINT32 passkey) { tSMP_CB *p_cb = & smp_cb; UINT8 failure = SMP_PASSKEY_ENTRY_FAIL; - tBTM_SEC_DEV_REC *p_dev_rec; SMP_TRACE_EVENT ("SMP_PasskeyReply: Key: %d Result:%d", passkey, res); @@ -246,13 +307,12 @@ void SMP_PasskeyReply (BD_ADDR bd_addr, UINT8 res, UINT32 passkey) return; } - if ((p_dev_rec = btm_find_dev (bd_addr)) == NULL) + if (btm_find_dev (bd_addr) == NULL) { SMP_TRACE_ERROR ("SMP_PasskeyReply() - no dev CB"); return; } - if (passkey > BTM_MAX_PASSKEY_VAL || res != SMP_SUCCESS) { SMP_TRACE_WARNING ("SMP_PasskeyReply() - Wrong key len: %d or passkey entry fail", passkey); @@ -260,6 +320,10 @@ void SMP_PasskeyReply (BD_ADDR bd_addr, UINT8 res, UINT32 passkey) smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &failure); } + else if (p_cb->selected_association_model == SMP_MODEL_SEC_CONN_PASSKEY_ENT) + { + smp_sm_event(&smp_cb, SMP_SC_KEY_READY_EVT, &passkey); + } else { smp_convert_string_to_tk(p_cb->tk, passkey); @@ -270,6 +334,56 @@ void SMP_PasskeyReply (BD_ADDR bd_addr, UINT8 res, UINT32 passkey) /******************************************************************************* ** +** Function SMP_ConfirmReply +** +** Description This function is called after Security Manager submitted +** numeric comparison request to the application. +** +** Parameters: bd_addr - Address of the device with which numeric +** comparison was requested +** res - comparison result SMP_SUCCESS if success +** +*******************************************************************************/ +void SMP_ConfirmReply (BD_ADDR bd_addr, UINT8 res) +{ + tSMP_CB *p_cb = & smp_cb; + UINT8 failure = SMP_NUMERIC_COMPAR_FAIL; + + SMP_TRACE_EVENT ("%s: Result:%d", __FUNCTION__, res); + + /* If timeout already expired or has been canceled, ignore the reply */ + if (p_cb->cb_evt != SMP_NC_REQ_EVT) + { + SMP_TRACE_WARNING ("%s() - Wrong State: %d", __FUNCTION__,p_cb->state); + return; + } + + if (memcmp (bd_addr, p_cb->pairing_bda, BD_ADDR_LEN) != 0) + { + SMP_TRACE_ERROR ("%s() - Wrong BD Addr",__FUNCTION__); + return; + } + + if (btm_find_dev (bd_addr) == NULL) + { + SMP_TRACE_ERROR ("%s() - no dev CB",__FUNCTION__); + return; + } + + if (res != SMP_SUCCESS) + { + SMP_TRACE_WARNING ("%s() - Numeric Comparison fails",__FUNCTION__); + /* send pairing failure */ + smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &failure); + } + else + { + smp_sm_event(p_cb, SMP_SC_NC_OK_EVT, NULL); + } +} + +/******************************************************************************* +** ** Function SMP_OobDataReply ** ** Description This function is called to provide the OOB data for @@ -285,13 +399,11 @@ void SMP_OobDataReply(BD_ADDR bd_addr, tSMP_STATUS res, UINT8 len, UINT8 *p_data tSMP_CB *p_cb = & smp_cb; UINT8 failure = SMP_OOB_FAIL; tSMP_KEY key; - UNUSED(bd_addr); - SMP_TRACE_EVENT ("SMP_OobDataReply State: %d res:%d", - smp_cb.state, res); + SMP_TRACE_EVENT ("%s State: %d res:%d", __FUNCTION__, smp_cb.state, res); /* If timeout already expired or has been canceled, ignore the reply */ - if (p_cb->state != SMP_ST_WAIT_APP_RSP || p_cb->cb_evt != SMP_OOB_REQ_EVT) + if (p_cb->state != SMP_STATE_WAIT_APP_RSP || p_cb->cb_evt != SMP_OOB_REQ_EVT) return; if (res != SMP_SUCCESS || len == 0 || !p_data) @@ -314,6 +426,69 @@ void SMP_OobDataReply(BD_ADDR bd_addr, tSMP_STATUS res, UINT8 len, UINT8 *p_data /******************************************************************************* ** +** Function SMP_SecureConnectionOobDataReply +** +** Description This function is called to provide the SC OOB data for +** SMP in response to SMP_SC_OOB_REQ_EVT +** +** Parameters: p_data - pointer to the data +** +*******************************************************************************/ +void SMP_SecureConnectionOobDataReply(UINT8 *p_data) +{ + tSMP_CB *p_cb = &smp_cb; + + UINT8 failure = SMP_OOB_FAIL; + tSMP_SC_OOB_DATA *p_oob = (tSMP_SC_OOB_DATA *) p_data; + if (!p_oob) + { + SMP_TRACE_ERROR("%s received no data",__FUNCTION__); + smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &failure); + return; + } + + SMP_TRACE_EVENT ("%s req_oob_type: %d, loc_oob_data.present: %d, " + "peer_oob_data.present: %d", + __FUNCTION__, p_cb->req_oob_type, p_oob->loc_oob_data.present, + p_oob->peer_oob_data.present); + + if (p_cb->state != SMP_STATE_WAIT_APP_RSP || p_cb->cb_evt != SMP_SC_OOB_REQ_EVT) + return; + + BOOLEAN data_missing = FALSE; + switch (p_cb->req_oob_type) + { + case SMP_OOB_PEER: + if (!p_oob->peer_oob_data.present) + data_missing = TRUE; + break; + case SMP_OOB_LOCAL: + if (!p_oob->loc_oob_data.present) + data_missing = TRUE; + break; + case SMP_OOB_BOTH: + if (!p_oob->loc_oob_data.present || !p_oob->peer_oob_data.present) + data_missing = TRUE; + break; + default: + SMP_TRACE_EVENT ("Unexpected OOB data type requested. Fail OOB"); + data_missing = TRUE; + break; + } + + if (data_missing) + { + smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &failure); + return; + } + + p_cb->sc_oob_data = *p_oob; + + smp_sm_event(&smp_cb, SMP_SC_OOB_DATA_EVT, p_data); +} + +/******************************************************************************* +** ** Function SMP_Encrypt ** ** Description This function is called to encrypt the data with the specified @@ -337,4 +512,96 @@ BOOLEAN SMP_Encrypt (UINT8 *key, UINT8 key_len, status = smp_encrypt_data(key, key_len, plain_text, pt_len, p_out); return status; } + +/******************************************************************************* +** +** Function SMP_KeypressNotification +** +** Description This function is called to notify Security Manager about Keypress Notification. +** +** Parameters: bd_addr Address of the device to send keypress notification to +** value Keypress notification parameter value +** +*******************************************************************************/ +void SMP_KeypressNotification (BD_ADDR bd_addr, UINT8 value) +{ + tSMP_CB *p_cb = &smp_cb; + + SMP_TRACE_EVENT ("%s: Value: %d", __FUNCTION__,value); + + if (memcmp (bd_addr, p_cb->pairing_bda, BD_ADDR_LEN) != 0) + { + SMP_TRACE_ERROR ("%s() - Wrong BD Addr",__FUNCTION__); + return; + } + + if (btm_find_dev (bd_addr) == NULL) + { + SMP_TRACE_ERROR ("%s() - no dev CB",__FUNCTION__); + return; + } + + /* Keypress Notification is used by a device with KeyboardOnly IO capabilities */ + /* during the passkey entry protocol */ + if (p_cb->local_io_capability != SMP_IO_CAP_IN) + { + SMP_TRACE_ERROR ("%s() - wrong local IO capabilities %d", + __FUNCTION__, p_cb->local_io_capability); + return; + } + + if (p_cb->selected_association_model != SMP_MODEL_SEC_CONN_PASSKEY_ENT) + { + SMP_TRACE_ERROR ("%s() - wrong protocol %d", __FUNCTION__, + p_cb->selected_association_model); + return; + } + + smp_sm_event(p_cb, SMP_KEYPRESS_NOTIFICATION_EVENT, &value); +} + +/******************************************************************************* +** +** Function SMP_CreateLocalSecureConnectionsOobData +** +** Description This function is called to start creation of local SC OOB +** data set (tSMP_LOC_OOB_DATA). +** +** Parameters: bd_addr - Address of the device to send OOB data block to +** +** Returns Boolean - TRUE: creation of local SC OOB data set started. +*******************************************************************************/ +BOOLEAN SMP_CreateLocalSecureConnectionsOobData (tBLE_BD_ADDR *addr_to_send_to) +{ + tSMP_CB *p_cb = &smp_cb; + UINT8 *bd_addr; + + if (addr_to_send_to == NULL) + { + SMP_TRACE_ERROR ("%s addr_to_send_to is not provided",__FUNCTION__); + return FALSE; + } + + bd_addr = addr_to_send_to->bda; + + SMP_TRACE_EVENT ("%s addr type: %u, BDA: %08x%04x, state: %u, br_state: %u", + __FUNCTION__, addr_to_send_to->type, + (bd_addr[0]<<24)+(bd_addr[1]<<16)+(bd_addr[2]<<8) + bd_addr[3], + (bd_addr[4]<<8)+bd_addr[5], + p_cb->state, + p_cb->br_state); + + if ((p_cb->state != SMP_STATE_IDLE) || (p_cb->smp_over_br)) + { + SMP_TRACE_WARNING ("%s creation of local OOB data set "\ + "starts only in IDLE state",__FUNCTION__); + return FALSE; + } + + p_cb->sc_oob_data.loc_oob_data.addr_sent_to = *addr_to_send_to; + smp_sm_event(p_cb, SMP_CR_LOC_SC_OOB_DATA_EVT, NULL); + + return TRUE; +} + #endif /* SMP_INCLUDED */ |