/** **************************************************************************************** * * @file smpc_api.h * * @brief Header file SMPC API. * * Copyright (C) RivieraWaves 2009-2016 * * **************************************************************************************** */ #ifndef SMPC_API_H_ #define SMPC_API_H_ /** **************************************************************************************** * @addtogroup SMPC_API Task * @ingroup SMPC * @brief Provides a SMP API for controller tasks. * * The SMPC api is responsible for all security protocol and secure connections handling. * * @{ **************************************************************************************** */ /* * INCLUDE FILES **************************************************************************************** */ #include "rwip_config.h" #if (BLE_SMPC) #include "smp_common.h" #include "gap.h" #include "gapc_task.h" #include "l2cc_pdu.h" /* * DEFINES **************************************************************************************** */ /// check if flag is set #define SMPC_IS_FLAG_SET(conidx, flag) ((gapc_env[conidx]->smpc.timer_state & flag) == flag) #define SMPC_TIMER_SET_FLAG(conidx, flag) (gapc_env[conidx]->smpc.timer_state |= flag) #define SMPC_TIMER_UNSET_FLAG(conidx, flag) (gapc_env[conidx]->smpc.timer_state &= ~flag) /** * Timer State Masks */ /// Timeout Timer #define SMPC_TIMER_TIMEOUT_FLAG (0x01) /// Repeated Attempts Timer #define SMPC_TIMER_REP_ATT_FLAG (SMPC_TIMER_TIMEOUT_FLAG << 1) /// Blocked because of SMP Timeout #define SMPC_TIMER_TIMEOUT_BLOCKED_FLAG (SMPC_TIMER_REP_ATT_FLAG << 1) /// SMPC Internal State Code enum smpc_state { SMPC_STATE_RESERVED = 0x00, /******************************************************** * Pairing Procedure ********************************************************/ /**------------------------------------** * Pairing Features Exchange Phase * **------------------------------------**/ /// Is waiting for the pairing response SMPC_PAIRING_RSP_WAIT, /// Is waiting for the pairing features SMPC_PAIRING_FEAT_WAIT, /**------------------------------------** * Legacy (Pre BT 4.2 ) Authentication and Encryption Phase * **------------------------------------**/ /// Is waiting for the TK SMPC_PAIRING_TK_WAIT, /// Is waiting for the TK, peer confirm value has been received SMPC_PAIRING_TK_WAIT_CONF_RCV, /// Calculate the Random Number, part 1 SMPC_PAIRING_GEN_RAND_P1, /// Calculate the Random Number, part 2 SMPC_PAIRING_GEN_RAND_P2, /// The first part of the device's confirm value is being generated SMPC_PAIRING_CFM_P1, //7 /// The device's confirm value is being generated SMPC_PAIRING_CFM_P2, /// The first part of the peer device's confirm value is being generated SMPC_PAIRING_REM_CFM_P1, /// The peer device's confirm value is being generated SMPC_PAIRING_REM_CFM_P2, /// The device is waiting for the confirm value generated by the peer device SMPC_PAIRING_WAIT_CONFIRM, //b /// The device is waiting for the random value generated by the peer device SMPC_PAIRING_WAIT_RAND, /// The STK is being generated SMPC_PAIRING_GEN_STK, #if (SECURE_CONNECTIONS) /**------------------------------------** * Secure Connections (BT 4.2 ) Authentication and Encryption Phase * **------------------------------------**/ SMPC_PAIRING_SC_W4_PEER_PUBLIC_KEY, // Just Works and Numeric Comparison //--------------------------------- // In Just Works/Numeric Comparison - this state is used while // we are waiting for the LL to generate a Rand. SMPC_PAIRING_SC_W4_LOCAL_RAND_N_P1, SMPC_PAIRING_SC_W4_LOCAL_RAND_N_P2, // Used in Slave during F4 while waiting for AES_CMAC SMPC_PAIRING_SC_W4_F4_COMMITMENT_DETERMINATION, // Used in Master to Wait for Peer Commitment Cb SMPC_PAIRING_SC_W4_PEER_COMMITMENT, // Used in Master/Slave to Wait for Random Number From peer. SMPC_PAIRING_SC_W4_PEER_RAND, // Used in Slave to wait for Random Number Na from Master // SMPC_PAIRING_SC_W4_PAIRING_Na, // Used in Master during F4 calculation for Commitment Check SMPC_PAIRING_SC_W4_F4_COMMITMENT_CHECK, // Numeric Comparison // States specific to Secure Commenctions - numeric comparison // Used in both Master/Slave to wait for the AES-CMAC calculation does to calculated the // PassCode for the user. SMPC_PAIRING_SC_W4_G2_AES_CMAC, // Wait for the user to enter Accept/Reject for the Numeric Value SMPC_PAIRING_SC_W4_NC_ACCEPT, // Used in both Master/Slave while waiting for the user Pass Code Confirmation. SMPC_PAIRING_SC_W4_USER_PASSCODE_CONFIRMATION, //----------------------------- // Secure Connections - Passkey //----------------------------- // Used in both Master/Slave while the user is entering the PassKey SMPC_PAIRING_SC_PASSKEY_W4_PASSKEY_RAND, // Used in both Master/Slave while Random numbers Nai,Nbi are being generated. SMPC_PAIRING_SC_PASSKEY_W4_LOCAL_RAND_N_P1, // Used in both Master/Slave while Random numbers Nai,Nbi are being generated. SMPC_PAIRING_SC_PASSKEY_W4_LOCAL_RAND_N_P2, // Used in both Master/Slave while waiting for the commitment value Cai,Cbi from the peer SMPC_PAIRING_SC_PASSKEY_W4_PEER_COMMITMENT, // Used in both Master/Slave while using AES_CMAC during F4 calculation of the commitment SMPC_PAIRING_SC_PASSKEY_W4_F4_COMMITMENT_DETERMINATION, // Used in both Master/Slave while waiting for the random number Nai,Nbi from the peer SMPC_PAIRING_SC_PASSKEY_W4_PEER_RAND, // Used in both Master/Slave while using AES_CMAC during F4 calculation for the commitment check SMPC_PAIRING_SC_PASSKEY_W4_F4_COMMITMENT_CHECK, // OOB SMPC_PAIRING_SC_OOB_W4_LOCAL_RAND_N_P1, SMPC_PAIRING_SC_OOB_W4_LOCAL_RAND_N_P2, SMPC_PAIRING_SC_OOB_W4_LOCAL_RAND_R_P1, SMPC_PAIRING_SC_OOB_W4_LOCAL_RAND_R_P2, SMPC_PAIRING_SC_OOB_W4_F4_COMMITMENT_DETERMINATION, SMPC_PAIRING_SC_OOB_W4_F4_COMMITMENT_CHECK, SMPC_PAIRING_SC_OOB_W4_PEER_RAND, // Wait for OOB data (A,Ca,Ra OR B,Cb,Rb) to be recieved from Peer. SMPC_PAIRING_SC_OOB_W4_OOB_DATA, // Secure Connections Authentication Phase 2 // Wait for the AES_CMACsalt to generate T SMPC_PAIRING_SC_W4_F5_P1, // Wait for the AES_CMAC to generate MACKEY SMPC_PAIRING_SC_W4_F5_P2, // Wait for the AES_CMAC to generate LTK SMPC_PAIRING_SC_W4_F5_P3, // Wait for the AES_CMAC to complete the DHKEY check SMPC_PAIRING_SC_W4_F6_DHKEY_CHECK, // Wait for DHkey_Check from the peer SMPC_PAIRING_SC_W4_PEER_DHKEY_CHECK, SMPC_PAIRING_SC_W4_F6_DHKEY_VERIFICATION, SMPC_PAIRING_SC_W4_DHKEY_KEY_COMPLETE, SMPC_PAIRING_SC_W4_ENCRYPTION_START, SMPC_PAIRING_SC_W4_ENCRYPTION_CHANGE, #endif // (SECURE_CONNECTIONS) /**------------------------------------** * Transport Keys Distribution Phase * **------------------------------------**/ /// Default pairing remote waiting state SMPC_PAIRING_APP_WAIT, /// Is waiting for the LTK from application SMPC_PAIRING_APP_LTK_WAIT, /// Is waiting for the Identity Resolving Key from application SMPC_PAIRING_APP_IRK_WAIT, /// Is waiting for the CSRK from application SMPC_PAIRING_APP_CSRK_WAIT, /// Default pairing remote waiting state SMPC_PAIRING_REM_WAIT, /// Is waiting for the remote LTK SMPC_PAIRING_REM_LTK_WAIT, /// Is waiting for the remote EDIV and Rand Value SMPC_PAIRING_REM_MST_ID_WAIT, /// Is waiting for the remote IRK SMPC_PAIRING_REM_IRK_WAIT, /// Is waiting for the remote BD Address SMPC_PAIRING_REM_BD_ADDR_WAIT, /// Is waiting for the remote CSRK SMPC_PAIRING_REM_CSRK_WAIT, /******************************************************** * Signing Procedure ********************************************************/ /// Generation of L SMPC_SIGN_L_GEN, /// Generation of Ci SMPC_SIGN_Ci_GEN, /******************************************************** * Encryption Procedure (STK or LTK) ********************************************************/ /// Is waiting the change encryption event with LTK SMPC_START_ENC_LTK, /// Is waiting the change encryption event with STK SMPC_START_ENC_STK }; /* * FUNCTION DEFINITION **************************************************************************************** */ #if (BLE_CENTRAL) /** **************************************************************************************** * @brief Handles pairing request from GAP, start the pairing procedure * * @param[in] idx Connection Index * @param[in] pairing Pairing Information * * @return Status of Pairing start **************************************************************************************** */ uint8_t smpc_pairing_start(uint8_t idx, struct gapc_pairing *pairing); #endif // (BLE_CENTRAL) /** **************************************************************************************** * @brief Handles TK exchange part of pairing * * @param[in] idx Connection Index * @param[in] accept True if pairing is accepted, False else * @param[in] tk The TK transmitted by application * * @return status of pairing **************************************************************************************** */ uint8_t smpc_pairing_tk_exch(uint8_t idx, bool accept, struct gap_sec_key *tk); /** **************************************************************************************** * @brief Handles LTK exchange part of pairing * * @param[in] idx Connection Index * @param[in] ltk The LTK transmitted by application * * @return status of pairing **************************************************************************************** */ uint8_t smpc_pairing_ltk_exch(uint8_t idx, struct gapc_ltk* ltk); /** **************************************************************************************** * @brief Handles IRK exchange part of pairing * * @param[in] idx Connection Index * @param[in] irk The IRK transmitted by application * @param[in] identity Device identity address * * @return status of pairing **************************************************************************************** */ uint8_t smpc_pairing_irk_exch(uint8_t idx, struct gap_sec_key* irk, struct gap_bdaddr *identity); /** **************************************************************************************** * @brief Handles CSRK exchange part of pairing * * @param[in] idx Connection Index * @param[in] csrk The CSRK transmitted by application * * @return status of pairing **************************************************************************************** */ uint8_t smpc_pairing_csrk_exch(uint8_t idx, struct gap_sec_key *csrk); #if (SECURE_CONNECTIONS) /** **************************************************************************************** * @brief Handles OOB exchange part of pairing * * @param[in] idx Connection Index * @param[in] accept Accept or Reject the OOB (reject if OOB reception not available on the device) * @param[in] csrk The OOB Confirm and OOB Rand from the peer * * @return status of pairing **************************************************************************************** */ uint8_t smpc_pairing_oob_exch(uint8_t idx, bool accept, struct gapc_oob *oob); /** **************************************************************************************** * @brief Handles Numeric Value Acceptance as part of pairing * * @param[in] idx Connection Index * @param[in] accept Accept or Reject the numeric comparison * * @return status of pairing **************************************************************************************** */ uint8_t smpc_pairing_nc_exch(uint8_t idx,uint8_t accept ); #endif // (SECURE_CONNECTIONS) /** **************************************************************************************** * @brief Handles reception of pairing response information * * @param[in] idx Connection Index * @param[in] accept True if pairing is accepted, False else * @param[in] feat Pairing response feature information * * @return status of pairing **************************************************************************************** */ uint8_t smpc_pairing_rsp(uint8_t idx, bool accept, struct gapc_pairing *feat); #if (BLE_PERIPHERAL) /** **************************************************************************************** * @brief Handles reception of pairing request information * * @param[in] idx Connection Index * @param[in] feat Pairing request feature information **************************************************************************************** */ void smpc_pairing_req_handler(uint8_t idx, struct gapc_pairing *feat); /** **************************************************************************************** * @brief Handles request to send a security request to peer device * * @param[in] idx Connection Index * @param[in] auth Requested Authentication Level * * @return status of the request **************************************************************************************** */ uint8_t smpc_security_req_send(uint8_t idx, uint8_t auth); #endif // (BLE_PERIPHERAL) #if (BLE_CENTRAL) /** **************************************************************************************** * @brief Master requests to start encryption * * @param[in] idx Connection Index * @param[in] ltk LTK information * * @return status of the request **************************************************************************************** */ uint8_t smpc_encrypt_start(uint8_t idx, struct gapc_ltk *ltk); #endif //(BLE_CENTRAL) #if (BLE_PERIPHERAL) /** **************************************************************************************** * @brief Handles reception of encryption request * * @param[in] idx Connection Index * @param[in] ltk LTK to search information **************************************************************************************** */ void smpc_encrypt_start_handler(uint8_t idx, struct gapc_ltk *ltk); /** **************************************************************************************** * @brief Slave respond to peer device encryption request * * @param[in] idx Connection Index * @param[in] accept Accept or not to start encryption * @param[in] ltk LTK information * @param[in] key_size Encryption key size **************************************************************************************** */ void smpc_encrypt_cfm(uint8_t idx, bool accept, struct gap_sec_key *ltk, uint8_t key_size); #endif //(BLE_PERIPHERAL) /** **************************************************************************************** * @brief Request to sign an attribute packet or check signature * * @param[in] idx Connection Index * @param[in] param ATT packet information * * @return status of signature request **************************************************************************************** */ uint8_t smpc_sign_command(uint8_t idx, struct gapc_sign_cmd *param); /** **************************************************************************************** * @brief Continue signature generation or check of an attribute packet after an AES. * * @param[in] idx Connection Index * @param[in] aes_res Result of AES calculation **************************************************************************************** */ void smpc_sign_cont(uint8_t idx, uint8_t* aes_res); /** **************************************************************************************** * @brief Continue generation of rand number for confirm value. * * @param[in] idx Connection Index * @param[in] randnb Generated Random Number **************************************************************************************** */ void smpc_confirm_gen_rand(uint8_t idx, rand_nb_t* randnb); /** **************************************************************************************** * @brief Continue Calculation of Confirm Value or STK after AES. * * @param[in] idx Connection Index * @param[in] aes_res Result of AES calculation **************************************************************************************** */ void smpc_calc_confirm_cont(uint8_t idx, uint8_t* aes_res); /** **************************************************************************************** * @brief Send an KeyPress Notification Event to the Host * * @param[in] idx Connection Index * @param[in] keypress KeyPress Type **************************************************************************************** */ void smpc_key_press_notification_ind(uint8_t idx, uint8_t keypress); /** **************************************************************************************** * @brief Stop the timer used to detect a SMP Timeout * * @param[in] conidx Connection Index **************************************************************************************** */ void smpc_clear_timeout_timer(uint8_t conidx); /** **************************************************************************************** * @brief Handle reception of a SMP PDU sent by the peer device. * * @param[in] conidx Connection Index * @param[in] pdu Unpacked PDU **************************************************************************************** */ void smpc_pdu_recv(uint8_t conidx, struct l2cc_pdu *pdu); /** **************************************************************************************** * @brief Send a SMP PDU to the peer device * * @param[in] conidx Connection Index * @param[in] cmd_code Code of the PDU to send * @param[in] value Unpacked value **************************************************************************************** */ void smpc_pdu_send(uint8_t conidx, uint8_t cmd_code, void *value); /** **************************************************************************************** * @brief Inform the HL that the pairing procedure currently in progress is over. * * @param[in] conidx Connection Index * @param[in] role Current role of the device * @param[in] status Status * @param[in] start_ra_timer Indicate if the repeated attempts timer shall be started in * the case of a pairing failed. **************************************************************************************** */ void smpc_pairing_end(uint8_t conidx, uint8_t role, uint8_t status, bool start_ra_timer); /** **************************************************************************************** * @brief Handle reception of a DH Key from HCI * * @param[in] conidx Connection Index * @param[in] status Indicates if HCI request Succeeded or Failed * @param[in] dh_key Diffie Helman Key - 32 Bytes **************************************************************************************** */ void smpc_handle_dh_key_check_complete(uint8_t conidx,const uint8_t* dh_key); #endif // (BLE_SMPC) #endif //(SMPC_API_H_) /// @} SMPC_API