Quellcode durchsuchen

Merge branch 'bugfix/bt_bluedroid_same_public_key_attack_v3.3' into 'release/v3.3'

Bluedroid: Fixes for some Bluetooth vulnerabilities. (v3.3)

See merge request espressif/esp-idf!11767
Jiang Jiang Jian vor 5 Jahren
Ursprung
Commit
777c8bbd44

+ 1300 - 0
components/bt/host/bluedroid/api/include/api/esp_gap_ble_api.h

@@ -0,0 +1,1300 @@
+// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef __ESP_GAP_BLE_API_H__
+#define __ESP_GAP_BLE_API_H__
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#include "esp_err.h"
+#include "esp_bt_defs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**@{
+ * BLE_ADV_DATA_FLAG data flag bit definition used for advertising data flag
+ */
+#define ESP_BLE_ADV_FLAG_LIMIT_DISC         (0x01 << 0)
+#define ESP_BLE_ADV_FLAG_GEN_DISC           (0x01 << 1)
+#define ESP_BLE_ADV_FLAG_BREDR_NOT_SPT      (0x01 << 2)
+#define ESP_BLE_ADV_FLAG_DMT_CONTROLLER_SPT (0x01 << 3)
+#define ESP_BLE_ADV_FLAG_DMT_HOST_SPT       (0x01 << 4)
+#define ESP_BLE_ADV_FLAG_NON_LIMIT_DISC     (0x00 )
+/**
+ * @}
+ */
+
+/* relate to BTM_LE_KEY_xxx in stack/btm_api.h */
+#define ESP_LE_KEY_NONE                    0                                                                         /* relate to BTM_LE_KEY_NONE in stack/btm_api.h */
+#define ESP_LE_KEY_PENC                    (1 << 0)   /*!< encryption key, encryption information of peer device */  /* relate to BTM_LE_KEY_PENC in stack/btm_api.h */
+#define ESP_LE_KEY_PID                     (1 << 1)   /*!< identity key of the peer device */                        /* relate to BTM_LE_KEY_PID in stack/btm_api.h */
+#define ESP_LE_KEY_PCSRK                   (1 << 2)   /*!< peer SRK */                                               /* relate to BTM_LE_KEY_PCSRK in stack/btm_api.h */
+#define ESP_LE_KEY_PLK                     (1 << 3)   /*!< Link key*/                                                /* relate to BTM_LE_KEY_PLK in stack/btm_api.h */
+#define ESP_LE_KEY_LLK                     (ESP_LE_KEY_PLK << 4)                                                     /* relate to BTM_LE_KEY_LLK in stack/btm_api.h */
+#define ESP_LE_KEY_LENC                    (ESP_LE_KEY_PENC << 4)   /*!< master role security information:div */     /* relate to BTM_LE_KEY_LENC in stack/btm_api.h */
+#define ESP_LE_KEY_LID                     (ESP_LE_KEY_PID << 4)    /*!< master device ID key */                     /* relate to BTM_LE_KEY_LID in stack/btm_api.h */
+#define ESP_LE_KEY_LCSRK                   (ESP_LE_KEY_PCSRK << 4)  /*!< local CSRK has been deliver to peer */      /* relate to BTM_LE_KEY_LCSRK in stack/btm_api.h */
+typedef uint8_t esp_ble_key_type_t;
+
+/* relate to BTM_LE_AUTH_xxx in stack/btm_api.h */
+#define ESP_LE_AUTH_NO_BOND                 0x00                                     /*!< 0*/                     /* relate to BTM_LE_AUTH_NO_BOND in stack/btm_api.h */
+#define ESP_LE_AUTH_BOND                    0x01                                     /*!< 1 << 0 */               /* relate to BTM_LE_AUTH_BOND in stack/btm_api.h */
+#define ESP_LE_AUTH_REQ_MITM                (1 << 2)                                 /*!< 1 << 2 */               /* relate to BTM_LE_AUTH_REQ_MITM in stack/btm_api.h */
+#define ESP_LE_AUTH_REQ_BOND_MITM           (ESP_LE_AUTH_BOND | ESP_LE_AUTH_REQ_MITM)/*!< 0101*/
+#define ESP_LE_AUTH_REQ_SC_ONLY             (1 << 3)                                 /*!< 1 << 3 */               /* relate to BTM_LE_AUTH_REQ_SC_ONLY in stack/btm_api.h */
+#define ESP_LE_AUTH_REQ_SC_BOND             (ESP_LE_AUTH_BOND | ESP_LE_AUTH_REQ_SC_ONLY)            /*!< 1001 */  /* relate to BTM_LE_AUTH_REQ_SC_BOND in stack/btm_api.h */
+#define ESP_LE_AUTH_REQ_SC_MITM             (ESP_LE_AUTH_REQ_MITM | ESP_LE_AUTH_REQ_SC_ONLY)        /*!< 1100 */  /* relate to BTM_LE_AUTH_REQ_SC_MITM in stack/btm_api.h */
+#define ESP_LE_AUTH_REQ_SC_MITM_BOND        (ESP_LE_AUTH_REQ_MITM | ESP_LE_AUTH_REQ_SC_ONLY | ESP_LE_AUTH_BOND)   /*!< 1101 */  /* relate to BTM_LE_AUTH_REQ_SC_MITM_BOND in stack/btm_api.h */
+typedef uint8_t   esp_ble_auth_req_t;         /*!< combination of the above bit pattern */
+
+#define ESP_BLE_ONLY_ACCEPT_SPECIFIED_AUTH_DISABLE 0
+#define ESP_BLE_ONLY_ACCEPT_SPECIFIED_AUTH_ENABLE  1
+
+#define ESP_BLE_OOB_DISABLE 0
+#define ESP_BLE_OOB_ENABLE  1
+
+/* relate to BTM_IO_CAP_xxx in stack/btm_api.h */
+#define ESP_IO_CAP_OUT                      0   /*!< DisplayOnly */         /* relate to BTM_IO_CAP_OUT in stack/btm_api.h */
+#define ESP_IO_CAP_IO                       1   /*!< DisplayYesNo */        /* relate to BTM_IO_CAP_IO in stack/btm_api.h */
+#define ESP_IO_CAP_IN                       2   /*!< KeyboardOnly */        /* relate to BTM_IO_CAP_IN in stack/btm_api.h */
+#define ESP_IO_CAP_NONE                     3   /*!< NoInputNoOutput */     /* relate to BTM_IO_CAP_NONE in stack/btm_api.h */
+#define ESP_IO_CAP_KBDISP                   4   /*!< Keyboard display */    /* relate to BTM_IO_CAP_KBDISP in stack/btm_api.h */
+
+#define ESP_BLE_APPEARANCE_UNKNOWN                 0x0000 /* relate to BTM_BLE_APPEARANCE_UNKNOWN in stack/btm_ble_api.h */
+#define ESP_BLE_APPEARANCE_GENERIC_PHONE           0x0040 /* relate to BTM_BLE_APPEARANCE_GENERIC_PHONE in stack/btm_ble_api.h */
+#define ESP_BLE_APPEARANCE_GENERIC_COMPUTER        0x0080 /* relate to BTM_BLE_APPEARANCE_GENERIC_COMPUTER in stack/btm_ble_api.h */
+#define ESP_BLE_APPEARANCE_GENERIC_WATCH           0x00C0 /* relate to BTM_BLE_APPEARANCE_GENERIC_WATCH in stack/btm_ble_api.h */
+#define ESP_BLE_APPEARANCE_SPORTS_WATCH            0x00C1 /* relate to BTM_BLE_APPEARANCE_SPORTS_WATCH in stack/btm_ble_api.h */
+#define ESP_BLE_APPEARANCE_GENERIC_CLOCK           0x0100 /* relate to BTM_BLE_APPEARANCE_GENERIC_CLOCK in stack/btm_ble_api.h */
+#define ESP_BLE_APPEARANCE_GENERIC_DISPLAY         0x0140 /* relate to BTM_BLE_APPEARANCE_GENERIC_DISPLAY in stack/btm_ble_api.h */
+#define ESP_BLE_APPEARANCE_GENERIC_REMOTE          0x0180 /* relate to BTM_BLE_APPEARANCE_GENERIC_REMOTE in stack/btm_ble_api.h */
+#define ESP_BLE_APPEARANCE_GENERIC_EYEGLASSES      0x01C0 /* relate to BTM_BLE_APPEARANCE_GENERIC_EYEGLASSES in stack/btm_ble_api.h */
+#define ESP_BLE_APPEARANCE_GENERIC_TAG             0x0200 /* relate to BTM_BLE_APPEARANCE_GENERIC_TAG in stack/btm_ble_api.h */
+#define ESP_BLE_APPEARANCE_GENERIC_KEYRING         0x0240 /* relate to BTM_BLE_APPEARANCE_GENERIC_KEYRING in stack/btm_ble_api.h */
+#define ESP_BLE_APPEARANCE_GENERIC_MEDIA_PLAYER    0x0280 /* relate to BTM_BLE_APPEARANCE_GENERIC_MEDIA_PLAYER in stack/btm_ble_api.h */
+#define ESP_BLE_APPEARANCE_GENERIC_BARCODE_SCANNER 0x02C0 /* relate to BTM_BLE_APPEARANCE_GENERIC_BARCODE_SCANNER in stack/btm_ble_api.h */
+#define ESP_BLE_APPEARANCE_GENERIC_THERMOMETER     0x0300 /* relate to BTM_BLE_APPEARANCE_GENERIC_THERMOMETER in stack/btm_ble_api.h */
+#define ESP_BLE_APPEARANCE_THERMOMETER_EAR         0x0301 /* relate to BTM_BLE_APPEARANCE_THERMOMETER_EAR in stack/btm_ble_api.h */
+#define ESP_BLE_APPEARANCE_GENERIC_HEART_RATE      0x0340 /* relate to BTM_BLE_APPEARANCE_GENERIC_HEART_RATE in stack/btm_ble_api.h */
+#define ESP_BLE_APPEARANCE_HEART_RATE_BELT         0x0341 /* relate to BTM_BLE_APPEARANCE_HEART_RATE_BELT in stack/btm_ble_api.h */
+#define ESP_BLE_APPEARANCE_GENERIC_BLOOD_PRESSURE  0x0380 /* relate to BTM_BLE_APPEARANCE_GENERIC_BLOOD_PRESSURE in stack/btm_ble_api.h */
+#define ESP_BLE_APPEARANCE_BLOOD_PRESSURE_ARM      0x0381 /* relate to BTM_BLE_APPEARANCE_BLOOD_PRESSURE_ARM in stack/btm_ble_api.h */
+#define ESP_BLE_APPEARANCE_BLOOD_PRESSURE_WRIST    0x0382 /* relate to BTM_BLE_APPEARANCE_BLOOD_PRESSURE_WRIST in stack/btm_ble_api.h */
+#define ESP_BLE_APPEARANCE_GENERIC_HID             0x03C0 /* relate to BTM_BLE_APPEARANCE_GENERIC_HID in stack/btm_ble_api.h */
+#define ESP_BLE_APPEARANCE_HID_KEYBOARD            0x03C1 /* relate to BTM_BLE_APPEARANCE_HID_KEYBOARD in stack/btm_ble_api.h */
+#define ESP_BLE_APPEARANCE_HID_MOUSE               0x03C2 /* relate to BTM_BLE_APPEARANCE_HID_MOUSE in stack/btm_ble_api.h */
+#define ESP_BLE_APPEARANCE_HID_JOYSTICK            0x03C3 /* relate to BTM_BLE_APPEARANCE_HID_JOYSTICK in stack/btm_ble_api.h */
+#define ESP_BLE_APPEARANCE_HID_GAMEPAD             0x03C4 /* relate to BTM_BLE_APPEARANCE_HID_GAMEPAD in stack/btm_ble_api.h */
+#define ESP_BLE_APPEARANCE_HID_DIGITIZER_TABLET    0x03C5 /* relate to BTM_BLE_APPEARANCE_HID_DIGITIZER_TABLET in stack/btm_ble_api.h */
+#define ESP_BLE_APPEARANCE_HID_CARD_READER         0x03C6 /* relate to BTM_BLE_APPEARANCE_HID_CARD_READER in stack/btm_ble_api.h */
+#define ESP_BLE_APPEARANCE_HID_DIGITAL_PEN         0x03C7 /* relate to BTM_BLE_APPEARANCE_HID_DIGITAL_PEN in stack/btm_ble_api.h */
+#define ESP_BLE_APPEARANCE_HID_BARCODE_SCANNER     0x03C8 /* relate to BTM_BLE_APPEARANCE_HID_BARCODE_SCANNER in stack/btm_ble_api.h */
+#define ESP_BLE_APPEARANCE_GENERIC_GLUCOSE         0x0400 /* relate to BTM_BLE_APPEARANCE_GENERIC_GLUCOSE in stack/btm_ble_api.h */
+#define ESP_BLE_APPEARANCE_GENERIC_WALKING         0x0440 /* relate to BTM_BLE_APPEARANCE_GENERIC_WALKING in stack/btm_ble_api.h */
+#define ESP_BLE_APPEARANCE_WALKING_IN_SHOE         0x0441 /* relate to BTM_BLE_APPEARANCE_WALKING_IN_SHOE in stack/btm_ble_api.h */
+#define ESP_BLE_APPEARANCE_WALKING_ON_SHOE         0x0442 /* relate to BTM_BLE_APPEARANCE_WALKING_ON_SHOE in stack/btm_ble_api.h */
+#define ESP_BLE_APPEARANCE_WALKING_ON_HIP          0x0443 /* relate to BTM_BLE_APPEARANCE_WALKING_ON_HIP in stack/btm_ble_api.h */
+#define ESP_BLE_APPEARANCE_GENERIC_CYCLING         0x0480 /* relate to BTM_BLE_APPEARANCE_GENERIC_CYCLING in stack/btm_ble_api.h */
+#define ESP_BLE_APPEARANCE_CYCLING_COMPUTER        0x0481 /* relate to BTM_BLE_APPEARANCE_CYCLING_COMPUTER in stack/btm_ble_api.h */
+#define ESP_BLE_APPEARANCE_CYCLING_SPEED           0x0482 /* relate to BTM_BLE_APPEARANCE_CYCLING_SPEED in stack/btm_ble_api.h */
+#define ESP_BLE_APPEARANCE_CYCLING_CADENCE         0x0483 /* relate to BTM_BLE_APPEARANCE_CYCLING_CADENCE in stack/btm_ble_api.h */
+#define ESP_BLE_APPEARANCE_CYCLING_POWER           0x0484 /* relate to BTM_BLE_APPEARANCE_CYCLING_POWER in stack/btm_ble_api.h */
+#define ESP_BLE_APPEARANCE_CYCLING_SPEED_CADENCE   0x0485 /* relate to BTM_BLE_APPEARANCE_CYCLING_SPEED_CADENCE in stack/btm_ble_api.h */
+#define ESP_BLE_APPEARANCE_GENERIC_PULSE_OXIMETER  0x0C40 /* relate to BTM_BLE_APPEARANCE_GENERIC_PULSE_OXIMETER in stack/btm_ble_api.h */
+#define ESP_BLE_APPEARANCE_PULSE_OXIMETER_FINGERTIP 0x0C41 /* relate to BTM_BLE_APPEARANCE_PULSE_OXIMETER_FINGERTIP in stack/btm_ble_api.h */
+#define ESP_BLE_APPEARANCE_PULSE_OXIMETER_WRIST    0x0C42 /* relate to BTM_BLE_APPEARANCE_PULSE_OXIMETER_WRIST in stack/btm_ble_api.h */
+#define ESP_BLE_APPEARANCE_GENERIC_WEIGHT          0x0C80 /* relate to BTM_BLE_APPEARANCE_GENERIC_WEIGHT in stack/btm_ble_api.h */
+#define ESP_BLE_APPEARANCE_GENERIC_PERSONAL_MOBILITY_DEVICE    0x0CC0 /* relate to BTM_BLE_APPEARANCE_GENERIC_PERSONAL_MOBILITY_DEVICE in stack/btm_ble_api.h */
+#define ESP_BLE_APPEARANCE_POWERED_WHEELCHAIR                  0x0CC1 /* relate to BTM_BLE_APPEARANCE_POWERED_WHEELCHAIR in stack/btm_ble_api.h */
+#define ESP_BLE_APPEARANCE_MOBILITY_SCOOTER                    0x0CC2 /* relate to BTM_BLE_APPEARANCE_MOBILITY_SCOOTER in stack/btm_ble_api.h */
+#define ESP_BLE_APPEARANCE_GENERIC_CONTINUOUS_GLUCOSE_MONITOR  0x0D00 /* relate to BTM_BLE_APPEARANCE_GENERIC_CONTINUOUS_GLUCOSE_MONITOR in stack/btm_ble_api.h */
+#define ESP_BLE_APPEARANCE_GENERIC_INSULIN_PUMP                0x0D40 /* relate to BTM_BLE_APPEARANCE_GENERIC_INSULIN_PUMP in stack/btm_ble_api.h */
+#define ESP_BLE_APPEARANCE_INSULIN_PUMP_DURABLE_PUMP           0x0D41 /* relate to BTM_BLE_APPEARANCE_INSULIN_PUMP_DURABLE_PUMP in stack/btm_ble_api.h */
+#define ESP_BLE_APPEARANCE_INSULIN_PUMP_PATCH_PUMP             0x0D44 /* relate to BTM_BLE_APPEARANCE_INSULIN_PUMP_PATCH_PUMP in stack/btm_ble_api.h */
+#define ESP_BLE_APPEARANCE_INSULIN_PEN                         0x0D48 /* relate to BTM_BLE_APPEARANCE_INSULIN_PEN in stack/btm_ble_api.h */
+#define ESP_BLE_APPEARANCE_GENERIC_MEDICATION_DELIVERY         0x0D80 /* relate to BTM_BLE_APPEARANCE_GENERIC_MEDICATION_DELIVERY in stack/btm_ble_api.h */
+#define ESP_BLE_APPEARANCE_GENERIC_OUTDOOR_SPORTS  0x1440             /* relate to BTM_BLE_APPEARANCE_GENERIC_OUTDOOR_SPORTS in stack/btm_ble_api.h */
+#define ESP_BLE_APPEARANCE_OUTDOOR_SPORTS_LOCATION 0x1441             /* relate to BTM_BLE_APPEARANCE_OUTDOOR_SPORTS_LOCATION in stack/btm_ble_api.h */
+#define ESP_BLE_APPEARANCE_OUTDOOR_SPORTS_LOCATION_AND_NAV     0x1442 /* relate to BTM_BLE_APPEARANCE_OUTDOOR_SPORTS_LOCATION_AND_NAV in stack/btm_ble_api.h */
+#define ESP_BLE_APPEARANCE_OUTDOOR_SPORTS_LOCATION_POD         0x1443 /* relate to BTM_BLE_APPEARANCE_OUTDOOR_SPORTS_LOCATION_POD in stack/btm_ble_api.h */
+#define ESP_BLE_APPEARANCE_OUTDOOR_SPORTS_LOCATION_POD_AND_NAV 0x1444 /* relate to BTM_BLE_APPEARANCE_OUTDOOR_SPORTS_LOCATION_POD_AND_NAV in stack/btm_ble_api.h */
+
+typedef uint8_t esp_ble_io_cap_t;               /*!< combination of the io capability */
+
+/// GAP BLE callback event type
+typedef enum {
+    ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT        = 0,       /*!< When advertising data set complete, the event comes */
+    ESP_GAP_BLE_SCAN_RSP_DATA_SET_COMPLETE_EVT,             /*!< When scan response data set complete, the event comes */
+    ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT,                /*!< When scan parameters set complete, the event comes */
+    ESP_GAP_BLE_SCAN_RESULT_EVT,                            /*!< When one scan result ready, the event comes each time */
+    ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT,              /*!< When raw advertising data set complete, the event comes */
+    ESP_GAP_BLE_SCAN_RSP_DATA_RAW_SET_COMPLETE_EVT,         /*!< When raw advertising data set complete, the event comes */
+    ESP_GAP_BLE_ADV_START_COMPLETE_EVT,                     /*!< When start advertising complete, the event comes */
+    ESP_GAP_BLE_SCAN_START_COMPLETE_EVT,                    /*!< When start scan complete, the event comes */
+    ESP_GAP_BLE_AUTH_CMPL_EVT,                              /* Authentication complete indication. */
+    ESP_GAP_BLE_KEY_EVT,                                    /* BLE  key event for peer device keys */
+    ESP_GAP_BLE_SEC_REQ_EVT,                                /* BLE  security request */
+    ESP_GAP_BLE_PASSKEY_NOTIF_EVT,                          /* passkey notification event */
+    ESP_GAP_BLE_PASSKEY_REQ_EVT,                            /* passkey request event */
+    ESP_GAP_BLE_OOB_REQ_EVT,                                /* OOB request event */
+    ESP_GAP_BLE_LOCAL_IR_EVT,                               /* BLE local IR event */
+    ESP_GAP_BLE_LOCAL_ER_EVT,                               /* BLE local ER event */
+    ESP_GAP_BLE_NC_REQ_EVT,                                 /* Numeric Comparison request event */
+    ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT,                      /*!< When stop adv complete, the event comes */
+    ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT,                     /*!< When stop scan complete, the event comes */
+    ESP_GAP_BLE_SET_STATIC_RAND_ADDR_EVT,                   /*!< When set the static rand address complete, the event comes */
+    ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT,                     /*!< When update connection parameters complete, the event comes */
+    ESP_GAP_BLE_SET_PKT_LENGTH_COMPLETE_EVT,                /*!< When set pkt length complete, the event comes */
+    ESP_GAP_BLE_SET_LOCAL_PRIVACY_COMPLETE_EVT,             /*!< When  Enable/disable privacy on the local device complete, the event comes */
+    ESP_GAP_BLE_REMOVE_BOND_DEV_COMPLETE_EVT,               /*!< When remove the bond device complete, the event comes */
+    ESP_GAP_BLE_CLEAR_BOND_DEV_COMPLETE_EVT,                /*!< When clear the bond device clear complete, the event comes */
+    ESP_GAP_BLE_GET_BOND_DEV_COMPLETE_EVT,                  /*!< When get the bond device list complete, the event comes */
+    ESP_GAP_BLE_READ_RSSI_COMPLETE_EVT,                     /*!< When read the rssi complete, the event comes */
+    ESP_GAP_BLE_UPDATE_WHITELIST_COMPLETE_EVT,              /*!< When add or remove whitelist complete, the event comes */
+    ESP_GAP_BLE_UPDATE_DUPLICATE_EXCEPTIONAL_LIST_COMPLETE_EVT,  /*!< When update duplicate exceptional list complete, the event comes */
+    ESP_GAP_BLE_EVT_MAX,
+} esp_gap_ble_cb_event_t;
+/// This is the old name, just for backwards compatibility
+#define ESP_GAP_BLE_ADD_WHITELIST_COMPLETE_EVT ESP_GAP_BLE_UPDATE_WHITELIST_COMPLETE_EVT
+
+/// Advertising data maximum length
+#define ESP_BLE_ADV_DATA_LEN_MAX               31
+/// Scan response data maximum length
+#define ESP_BLE_SCAN_RSP_DATA_LEN_MAX          31
+
+/* relate to BTM_BLE_AD_TYPE_xxx in stack/btm_ble_api.h */
+/// The type of advertising data(not adv_type)
+typedef enum {
+    ESP_BLE_AD_TYPE_FLAG                     = 0x01,    /* relate to BTM_BLE_AD_TYPE_FLAG in stack/btm_ble_api.h */
+    ESP_BLE_AD_TYPE_16SRV_PART               = 0x02,    /* relate to BTM_BLE_AD_TYPE_16SRV_PART in stack/btm_ble_api.h */
+    ESP_BLE_AD_TYPE_16SRV_CMPL               = 0x03,    /* relate to BTM_BLE_AD_TYPE_16SRV_CMPL in stack/btm_ble_api.h */
+    ESP_BLE_AD_TYPE_32SRV_PART               = 0x04,    /* relate to BTM_BLE_AD_TYPE_32SRV_PART in stack/btm_ble_api.h */
+    ESP_BLE_AD_TYPE_32SRV_CMPL               = 0x05,    /* relate to BTM_BLE_AD_TYPE_32SRV_CMPL in stack/btm_ble_api.h */
+    ESP_BLE_AD_TYPE_128SRV_PART              = 0x06,    /* relate to BTM_BLE_AD_TYPE_128SRV_PART in stack/btm_ble_api.h */
+    ESP_BLE_AD_TYPE_128SRV_CMPL              = 0x07,    /* relate to BTM_BLE_AD_TYPE_128SRV_CMPL in stack/btm_ble_api.h */
+    ESP_BLE_AD_TYPE_NAME_SHORT               = 0x08,    /* relate to BTM_BLE_AD_TYPE_NAME_SHORT in stack/btm_ble_api.h */
+    ESP_BLE_AD_TYPE_NAME_CMPL                = 0x09,    /* relate to BTM_BLE_AD_TYPE_NAME_CMPL in stack/btm_ble_api.h */
+    ESP_BLE_AD_TYPE_TX_PWR                   = 0x0A,    /* relate to BTM_BLE_AD_TYPE_TX_PWR in stack/btm_ble_api.h */
+    ESP_BLE_AD_TYPE_DEV_CLASS                = 0x0D,    /* relate to BTM_BLE_AD_TYPE_DEV_CLASS in stack/btm_ble_api.h */
+    ESP_BLE_AD_TYPE_SM_TK                    = 0x10,    /* relate to BTM_BLE_AD_TYPE_SM_TK in stack/btm_ble_api.h */
+    ESP_BLE_AD_TYPE_SM_OOB_FLAG              = 0x11,    /* relate to BTM_BLE_AD_TYPE_SM_OOB_FLAG in stack/btm_ble_api.h */
+    ESP_BLE_AD_TYPE_INT_RANGE                = 0x12,    /* relate to BTM_BLE_AD_TYPE_INT_RANGE in stack/btm_ble_api.h */
+    ESP_BLE_AD_TYPE_SOL_SRV_UUID             = 0x14,    /* relate to BTM_BLE_AD_TYPE_SOL_SRV_UUID in stack/btm_ble_api.h */
+    ESP_BLE_AD_TYPE_128SOL_SRV_UUID          = 0x15,    /* relate to BTM_BLE_AD_TYPE_128SOL_SRV_UUID in stack/btm_ble_api.h */
+    ESP_BLE_AD_TYPE_SERVICE_DATA             = 0x16,    /* relate to BTM_BLE_AD_TYPE_SERVICE_DATA in stack/btm_ble_api.h */
+    ESP_BLE_AD_TYPE_PUBLIC_TARGET            = 0x17,    /* relate to BTM_BLE_AD_TYPE_PUBLIC_TARGET in stack/btm_ble_api.h */
+    ESP_BLE_AD_TYPE_RANDOM_TARGET            = 0x18,    /* relate to BTM_BLE_AD_TYPE_RANDOM_TARGET in stack/btm_ble_api.h */
+    ESP_BLE_AD_TYPE_APPEARANCE               = 0x19,    /* relate to BTM_BLE_AD_TYPE_APPEARANCE in stack/btm_ble_api.h */
+    ESP_BLE_AD_TYPE_ADV_INT                  = 0x1A,    /* relate to BTM_BLE_AD_TYPE_ADV_INT in stack/btm_ble_api.h */
+    ESP_BLE_AD_TYPE_LE_DEV_ADDR              = 0x1b,    /* relate to BTM_BLE_AD_TYPE_LE_DEV_ADDR in stack/btm_ble_api.h */
+    ESP_BLE_AD_TYPE_LE_ROLE                  = 0x1c,    /* relate to BTM_BLE_AD_TYPE_LE_ROLE in stack/btm_ble_api.h */
+    ESP_BLE_AD_TYPE_SPAIR_C256               = 0x1d,    /* relate to BTM_BLE_AD_TYPE_SPAIR_C256 in stack/btm_ble_api.h */
+    ESP_BLE_AD_TYPE_SPAIR_R256               = 0x1e,    /* relate to BTM_BLE_AD_TYPE_SPAIR_R256 in stack/btm_ble_api.h */
+    ESP_BLE_AD_TYPE_32SOL_SRV_UUID           = 0x1f,    /* relate to BTM_BLE_AD_TYPE_32SOL_SRV_UUID in stack/btm_ble_api.h */
+    ESP_BLE_AD_TYPE_32SERVICE_DATA           = 0x20,    /* relate to BTM_BLE_AD_TYPE_32SERVICE_DATA in stack/btm_ble_api.h */
+    ESP_BLE_AD_TYPE_128SERVICE_DATA          = 0x21,    /* relate to BTM_BLE_AD_TYPE_128SERVICE_DATA in stack/btm_ble_api.h */
+    ESP_BLE_AD_TYPE_LE_SECURE_CONFIRM        = 0x22,    /* relate to BTM_BLE_AD_TYPE_LE_SECURE_CONFIRM in stack/btm_ble_api.h */
+    ESP_BLE_AD_TYPE_LE_SECURE_RANDOM         = 0x23,    /* relate to BTM_BLE_AD_TYPE_LE_SECURE_RANDOM in stack/btm_ble_api.h */
+    ESP_BLE_AD_TYPE_URI                      = 0x24,    /* relate to BTM_BLE_AD_TYPE_URI in stack/btm_ble_api.h */
+    ESP_BLE_AD_TYPE_INDOOR_POSITION          = 0x25,    /* relate to BTM_BLE_AD_TYPE_INDOOR_POSITION in stack/btm_ble_api.h */
+    ESP_BLE_AD_TYPE_TRANS_DISC_DATA          = 0x26,    /* relate to BTM_BLE_AD_TYPE_TRANS_DISC_DATA in stack/btm_ble_api.h */
+    ESP_BLE_AD_TYPE_LE_SUPPORT_FEATURE       = 0x27,    /* relate to BTM_BLE_AD_TYPE_LE_SUPPORT_FEATURE in stack/btm_ble_api.h */
+    ESP_BLE_AD_TYPE_CHAN_MAP_UPDATE          = 0x28,    /* relate to BTM_BLE_AD_TYPE_CHAN_MAP_UPDATE in stack/btm_ble_api.h */
+    ESP_BLE_AD_MANUFACTURER_SPECIFIC_TYPE    = 0xFF,    /* relate to BTM_BLE_AD_MANUFACTURER_SPECIFIC_TYPE in stack/btm_ble_api.h */
+} esp_ble_adv_data_type;
+
+/// Advertising mode
+typedef enum {
+    ADV_TYPE_IND                = 0x00,
+    ADV_TYPE_DIRECT_IND_HIGH    = 0x01,
+    ADV_TYPE_SCAN_IND           = 0x02,
+    ADV_TYPE_NONCONN_IND        = 0x03,
+    ADV_TYPE_DIRECT_IND_LOW     = 0x04,
+} esp_ble_adv_type_t;
+
+/// Advertising channel mask
+typedef enum {
+    ADV_CHNL_37     = 0x01,
+    ADV_CHNL_38     = 0x02,
+    ADV_CHNL_39     = 0x04,
+    ADV_CHNL_ALL    = 0x07,
+} esp_ble_adv_channel_t;
+
+typedef enum {
+    ///Allow both scan and connection requests from anyone
+    ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY  = 0x00,
+    ///Allow both scan req from White List devices only and connection req from anyone
+    ADV_FILTER_ALLOW_SCAN_WLST_CON_ANY,
+    ///Allow both scan req from anyone and connection req from White List devices only
+    ADV_FILTER_ALLOW_SCAN_ANY_CON_WLST,
+    ///Allow scan and connection requests from White List devices only
+    ADV_FILTER_ALLOW_SCAN_WLST_CON_WLST,
+    ///Enumeration end value for advertising filter policy value check
+} esp_ble_adv_filter_t;
+
+
+/* relate to BTA_DM_BLE_SEC_xxx in bta/bta_api.h */
+typedef enum {
+    ESP_BLE_SEC_ENCRYPT = 1,            /* relate to BTA_DM_BLE_SEC_ENCRYPT in bta/bta_api.h. If the device has already
+                                           bonded, the stack will used LTK to encrypt with the remote device directly.
+                                           Else if the device hasn't bonded, the stack will used the default authentication request
+                                           used the esp_ble_gap_set_security_param function set by the user. */
+    ESP_BLE_SEC_ENCRYPT_NO_MITM,        /* relate to BTA_DM_BLE_SEC_ENCRYPT_NO_MITM in bta/bta_api.h. If the device has already
+                                           bonded, the stack will check the LTK Whether the authentication request has been met, if met, used the LTK
+                                           to encrypt with the remote device directly, else Re-pair with the remote device.
+                                           Else if the device hasn't bonded, the stack will used NO MITM authentication request in the current link instead of
+                                           used the authreq in the esp_ble_gap_set_security_param function set by the user. */
+    ESP_BLE_SEC_ENCRYPT_MITM,           /* relate to BTA_DM_BLE_SEC_ENCRYPT_MITM in bta/bta_api.h. If the device has already
+                                           bonded, the stack will check the LTK Whether the authentication request has been met, if met, used the LTK
+                                           to encrypt with the remote device directly, else Re-pair with the remote device.
+                                           Else if the device hasn't bonded, the stack will used MITM authentication request in the current link instead of
+                                           used the authreq in the esp_ble_gap_set_security_param function set by the user. */
+}esp_ble_sec_act_t;
+
+typedef enum {
+    ESP_BLE_SM_PASSKEY = 0,
+    /* Authentication requirements of local device */
+    ESP_BLE_SM_AUTHEN_REQ_MODE,
+    /* The IO capability of local device */
+    ESP_BLE_SM_IOCAP_MODE,
+    /* Initiator Key Distribution/Generation */
+    ESP_BLE_SM_SET_INIT_KEY,
+    /* Responder Key Distribution/Generation */
+    ESP_BLE_SM_SET_RSP_KEY,
+    /* Maximum Encryption key size to support */
+    ESP_BLE_SM_MAX_KEY_SIZE,
+    /* Minimum Encryption key size requirement from Peer */
+    ESP_BLE_SM_MIN_KEY_SIZE,
+    /* Set static Passkey */
+    ESP_BLE_SM_SET_STATIC_PASSKEY,
+    /* Reset static Passkey */
+    ESP_BLE_SM_CLEAR_STATIC_PASSKEY,
+    /* Accept only specified SMP Authentication requirement */
+    ESP_BLE_SM_ONLY_ACCEPT_SPECIFIED_SEC_AUTH,
+    /* Enable/Disable OOB support */
+    ESP_BLE_SM_OOB_SUPPORT,
+    /* Appl encryption key size */
+    ESP_BLE_APP_ENC_KEY_SIZE,
+    ESP_BLE_SM_MAX_PARAM,
+} esp_ble_sm_param_t;
+
+/// Advertising parameters
+typedef struct {
+    uint16_t                adv_int_min;        /*!< Minimum advertising interval for
+                                                  undirected and low duty cycle directed advertising.
+                                                  Range: 0x0020 to 0x4000 Default: N = 0x0800 (1.28 second)
+                                                  Time = N * 0.625 msec Time Range: 20 ms to 10.24 sec */
+    uint16_t                adv_int_max;        /*!< Maximum advertising interval for
+                                                  undirected and low duty cycle directed advertising.
+                                                  Range: 0x0020 to 0x4000 Default: N = 0x0800 (1.28 second)
+                                                  Time = N * 0.625 msec Time Range: 20 ms to 10.24 sec Advertising max interval */
+    esp_ble_adv_type_t      adv_type;           /*!< Advertising type */
+    esp_ble_addr_type_t     own_addr_type;      /*!< Owner bluetooth device address type */
+    esp_bd_addr_t           peer_addr;          /*!< Peer device bluetooth device address */
+    esp_ble_addr_type_t     peer_addr_type;     /*!< Peer device bluetooth device address type, only support public address type and random address type */
+    esp_ble_adv_channel_t   channel_map;        /*!< Advertising channel map */
+    esp_ble_adv_filter_t    adv_filter_policy;  /*!< Advertising filter policy */
+} esp_ble_adv_params_t;
+
+/// Advertising data content, according to "Supplement to the Bluetooth Core Specification"
+typedef struct {
+    bool                    set_scan_rsp;           /*!< Set this advertising data as scan response or not*/
+    bool                    include_name;           /*!< Advertising data include device name or not */
+    bool                    include_txpower;        /*!< Advertising data include TX power */
+    int                     min_interval;           /*!< Advertising data show slave preferred connection min interval.
+                                                    The connection interval in the following manner:
+                                                    connIntervalmin = Conn_Interval_Min * 1.25 ms
+                                                    Conn_Interval_Min range: 0x0006 to 0x0C80
+                                                    Value of 0xFFFF indicates no specific minimum.
+                                                    Values not defined above are reserved for future use.*/
+
+    int                     max_interval;           /*!< Advertising data show slave preferred connection max interval.
+                                                    The connection interval in the following manner:
+                                                    connIntervalmax = Conn_Interval_Max * 1.25 ms
+                                                    Conn_Interval_Max range: 0x0006 to 0x0C80
+                                                    Conn_Interval_Max shall be equal to or greater than the Conn_Interval_Min.
+                                                    Value of 0xFFFF indicates no specific maximum.
+                                                    Values not defined above are reserved for future use.*/
+
+    int                     appearance;             /*!< External appearance of device */
+    uint16_t                manufacturer_len;       /*!< Manufacturer data length */
+    uint8_t                 *p_manufacturer_data;   /*!< Manufacturer data point */
+    uint16_t                service_data_len;       /*!< Service data length */
+    uint8_t                 *p_service_data;        /*!< Service data point */
+    uint16_t                service_uuid_len;       /*!< Service uuid length */
+    uint8_t                 *p_service_uuid;        /*!< Service uuid array point */
+    uint8_t                 flag;                   /*!< Advertising flag of discovery mode, see BLE_ADV_DATA_FLAG detail */
+} esp_ble_adv_data_t;
+
+/// Ble scan type
+typedef enum {
+    BLE_SCAN_TYPE_PASSIVE   =   0x0,            /*!< Passive scan */
+    BLE_SCAN_TYPE_ACTIVE    =   0x1,            /*!< Active scan */
+} esp_ble_scan_type_t;
+
+/// Ble scan filter type
+typedef enum {
+    BLE_SCAN_FILTER_ALLOW_ALL           = 0x0,  /*!< Accept all :
+                                                  1. advertisement packets except directed advertising packets not addressed to this device (default). */
+    BLE_SCAN_FILTER_ALLOW_ONLY_WLST     = 0x1,  /*!< Accept only :
+                                                  1. advertisement packets from devices where the advertiser’s address is in the White list.
+                                                  2. Directed advertising packets which are not addressed for this device shall be ignored. */
+    BLE_SCAN_FILTER_ALLOW_UND_RPA_DIR   = 0x2,  /*!< Accept all :
+                                                  1. undirected advertisement packets, and
+                                                  2. directed advertising packets where the initiator address is a resolvable private address, and
+                                                  3. directed advertising packets addressed to this device. */
+    BLE_SCAN_FILTER_ALLOW_WLIST_PRA_DIR = 0x3,  /*!< Accept all :
+                                                  1. advertisement packets from devices where the advertiser’s address is in the White list, and
+                                                  2. directed advertising packets where the initiator address is a resolvable private address, and
+                                                  3. directed advertising packets addressed to this device.*/
+} esp_ble_scan_filter_t;
+
+/// Ble scan duplicate type
+typedef enum {
+    BLE_SCAN_DUPLICATE_DISABLE           = 0x0,  /*!< the Link Layer should generate advertising reports to the host for each packet received */
+    BLE_SCAN_DUPLICATE_ENABLE            = 0x1,  /*!< the Link Layer should filter out duplicate advertising reports to the Host */
+    BLE_SCAN_DUPLICATE_MAX               = 0x2,  /*!< 0x02 – 0xFF, Reserved for future use */
+} esp_ble_scan_duplicate_t;
+
+/// Ble scan parameters
+typedef struct {
+    esp_ble_scan_type_t     scan_type;              /*!< Scan type */
+    esp_ble_addr_type_t     own_addr_type;          /*!< Owner address type */
+    esp_ble_scan_filter_t   scan_filter_policy;     /*!< Scan filter policy */
+    uint16_t                scan_interval;          /*!< Scan interval. This is defined as the time interval from
+                                                      when the Controller started its last LE scan until it begins the subsequent LE scan.
+                                                      Range: 0x0004 to 0x4000 Default: 0x0010 (10 ms)
+                                                      Time = N * 0.625 msec
+                                                      Time Range: 2.5 msec to 10.24 seconds*/
+    uint16_t                scan_window;            /*!< Scan window. The duration of the LE scan. LE_Scan_Window
+                                                      shall be less than or equal to LE_Scan_Interval
+                                                      Range: 0x0004 to 0x4000 Default: 0x0010 (10 ms)
+                                                      Time = N * 0.625 msec
+                                                      Time Range: 2.5 msec to 10240 msec */
+    esp_ble_scan_duplicate_t  scan_duplicate;       /*!< The Scan_Duplicates parameter controls whether the Link Layer should filter out
+                                                        duplicate advertising reports (BLE_SCAN_DUPLICATE_ENABLE) to the Host, or if the Link Layer should generate
+                                                        advertising reports for each packet received */
+} esp_ble_scan_params_t;
+
+/// connection parameters information
+typedef struct {
+    uint16_t             interval;                  /*!< connection interval */
+    uint16_t             latency;                   /*!< Slave latency for the connection in number of connection events. Range: 0x0000 to 0x01F3 */
+    uint16_t             timeout;                   /*!< Supervision timeout for the LE Link. Range: 0x000A to 0x0C80.
+                                                      Mandatory Range: 0x000A to 0x0C80 Time = N * 10 msec
+                                                      Time Range: 100 msec to 32 seconds */
+} esp_gap_conn_params_t;
+
+/// Connection update parameters
+typedef struct {
+    esp_bd_addr_t bda;                              /*!< Bluetooth device address */
+    uint16_t min_int;                               /*!< Min connection interval */
+    uint16_t max_int;                               /*!< Max connection interval */
+    uint16_t latency;                               /*!< Slave latency for the connection in number of connection events. Range: 0x0000 to 0x01F3 */
+    uint16_t timeout;                               /*!< Supervision timeout for the LE Link. Range: 0x000A to 0x0C80.
+                                                      Mandatory Range: 0x000A to 0x0C80 Time = N * 10 msec
+                                                      Time Range: 100 msec to 32 seconds */
+} esp_ble_conn_update_params_t;
+
+/**
+* @brief BLE pkt date length keys
+*/
+typedef struct
+{
+    uint16_t rx_len;                   /*!< pkt rx data length value */
+    uint16_t tx_len;                   /*!< pkt tx data length value */
+}esp_ble_pkt_data_length_params_t;
+
+/**
+* @brief BLE encryption keys
+*/
+typedef struct
+{
+    esp_bt_octet16_t     ltk;          /*!< The long term key*/
+    esp_bt_octet8_t      rand;         /*!< The random number*/
+    uint16_t             ediv;         /*!< The ediv value*/
+    uint8_t              sec_level;    /*!< The security level of the security link*/
+    uint8_t              key_size;     /*!< The key size(7~16) of the security link*/
+} esp_ble_penc_keys_t;                 /*!< The key type*/
+
+/**
+* @brief  BLE CSRK keys
+*/
+typedef struct
+{
+    uint32_t            counter;      /*!< The counter */
+    esp_bt_octet16_t    csrk;         /*!< The csrk key */
+    uint8_t             sec_level;    /*!< The security level */
+} esp_ble_pcsrk_keys_t;               /*!< The pcsrk key type */
+
+/**
+* @brief  BLE pid keys
+*/
+typedef struct
+{
+    esp_bt_octet16_t          irk;           /*!< The irk value */
+    esp_ble_addr_type_t       addr_type;     /*!< The address type */
+    esp_bd_addr_t             static_addr;   /*!< The static address */
+} esp_ble_pid_keys_t;                        /*!< The pid key type */
+
+/**
+* @brief  BLE Encryption reproduction keys
+*/
+typedef struct
+{
+    esp_bt_octet16_t  ltk;                  /*!< The long term key */
+    uint16_t          div;                  /*!< The div value */
+    uint8_t           key_size;             /*!< The key size of the security link */
+    uint8_t           sec_level;            /*!< The security level of the security link */
+} esp_ble_lenc_keys_t;                      /*!< The  key type */
+
+/**
+* @brief  BLE SRK keys
+*/
+typedef struct
+{
+    uint32_t          counter;              /*!< The counter value */
+    uint16_t          div;                  /*!< The div value */
+    uint8_t           sec_level;            /*!< The security level of the security link */
+    esp_bt_octet16_t  csrk;                 /*!< The csrk key value */
+} esp_ble_lcsrk_keys;                       /*!< The csrk key type */
+
+/**
+* @brief  Structure associated with ESP_KEY_NOTIF_EVT
+*/
+typedef struct
+{
+    esp_bd_addr_t  bd_addr;        /*!< peer address */
+    uint32_t       passkey;        /*!< the numeric value for comparison. If just_works, do not show this number to UI */
+} esp_ble_sec_key_notif_t;         /*!< BLE key notify type*/
+
+/**
+* @brief  Structure of the security request
+*/
+typedef struct
+{
+    esp_bd_addr_t  bd_addr;        /*!< peer address */
+} esp_ble_sec_req_t;               /*!< BLE security request type*/
+
+/**
+* @brief  union type of the security key value
+*/
+typedef union
+{
+    esp_ble_penc_keys_t   penc_key;       /*!< received peer encryption key */
+    esp_ble_pcsrk_keys_t  pcsrk_key;      /*!< received peer device SRK */
+    esp_ble_pid_keys_t    pid_key;        /*!< peer device ID key */
+    esp_ble_lenc_keys_t   lenc_key;       /*!< local encryption reproduction keys LTK = = d1(ER,DIV,0)*/
+    esp_ble_lcsrk_keys    lcsrk_key;      /*!< local device CSRK = d1(ER,DIV,1)*/
+} esp_ble_key_value_t;                    /*!< ble key value type*/
+
+/**
+* @brief  struct type of the bond key information value
+*/
+typedef struct
+{
+    esp_ble_key_mask_t    key_mask;       /*!< the key mask to indicate witch key is present */
+    esp_ble_penc_keys_t   penc_key;       /*!< received peer encryption key */
+    esp_ble_pcsrk_keys_t  pcsrk_key;      /*!< received peer device SRK */
+    esp_ble_pid_keys_t    pid_key;        /*!< peer device ID key */
+} esp_ble_bond_key_info_t;                /*!< ble bond key information value type */
+
+/**
+* @brief  struct type of the bond device value
+*/
+typedef struct
+{
+    esp_bd_addr_t  bd_addr;               /*!< peer address */
+    esp_ble_bond_key_info_t bond_key;     /*!< the bond key information */
+} esp_ble_bond_dev_t;                     /*!< the ble bond device type */
+
+
+/**
+* @brief  union type of the security key value
+*/
+typedef struct
+{
+    esp_bd_addr_t               bd_addr;        /*!< peer address */
+    esp_ble_key_type_t          key_type;       /*!< key type of the security link */
+    esp_ble_key_value_t         p_key_value;    /*!< the pointer to the key value */
+} esp_ble_key_t;                                /*!< the union to the ble key value type*/
+
+/**
+* @brief  structure type of the ble local id keys value
+*/
+typedef struct {
+    esp_bt_octet16_t       ir;                  /*!< the 16 bits of the ir value */
+    esp_bt_octet16_t       irk;                 /*!< the 16 bits of the ir key value */
+    esp_bt_octet16_t       dhk;                 /*!< the 16 bits of the dh key value */
+} esp_ble_local_id_keys_t;                      /*!< the structure of the ble local id keys value type*/
+
+
+/**
+  * @brief Structure associated with ESP_AUTH_CMPL_EVT
+  */
+typedef struct
+{
+    esp_bd_addr_t         bd_addr;               /*!< BD address peer device. */
+    bool                  key_present;           /*!< Valid link key value in key element */
+    esp_link_key          key;                   /*!< Link key associated with peer device. */
+    uint8_t               key_type;              /*!< The type of Link Key */
+    bool                  success;               /*!< TRUE of authentication succeeded, FALSE if failed. */
+    uint8_t               fail_reason;           /*!< The HCI reason/error code for when success=FALSE */
+    esp_ble_addr_type_t   addr_type;             /*!< Peer device address type */
+    esp_bt_dev_type_t     dev_type;              /*!< Device type */
+    esp_ble_auth_req_t    auth_mode;             /*!< authentication mode */
+} esp_ble_auth_cmpl_t;                           /*!< The ble authentication complete cb type */
+
+/**
+  * @brief union associated with ble security
+  */
+typedef union
+{
+    esp_ble_sec_key_notif_t    key_notif;      /*!< passkey notification */
+    esp_ble_sec_req_t          ble_req;        /*!< BLE SMP related request */
+    esp_ble_key_t              ble_key;        /*!< BLE SMP keys used when pairing */
+    esp_ble_local_id_keys_t    ble_id_keys;    /*!< BLE IR event */
+    esp_ble_auth_cmpl_t        auth_cmpl;      /*!< Authentication complete indication. */
+} esp_ble_sec_t;                               /*!< BLE security type */
+
+/// Sub Event of ESP_GAP_BLE_SCAN_RESULT_EVT
+typedef enum {
+    ESP_GAP_SEARCH_INQ_RES_EVT             = 0,      /*!< Inquiry result for a peer device. */
+    ESP_GAP_SEARCH_INQ_CMPL_EVT            = 1,      /*!< Inquiry complete. */
+    ESP_GAP_SEARCH_DISC_RES_EVT            = 2,      /*!< Discovery result for a peer device. */
+    ESP_GAP_SEARCH_DISC_BLE_RES_EVT        = 3,      /*!< Discovery result for BLE GATT based service on a peer device. */
+    ESP_GAP_SEARCH_DISC_CMPL_EVT           = 4,      /*!< Discovery complete. */
+    ESP_GAP_SEARCH_DI_DISC_CMPL_EVT        = 5,      /*!< Discovery complete. */
+    ESP_GAP_SEARCH_SEARCH_CANCEL_CMPL_EVT  = 6,      /*!< Search cancelled */
+    ESP_GAP_SEARCH_INQ_DISCARD_NUM_EVT     = 7,      /*!< The number of pkt discarded by flow control */
+} esp_gap_search_evt_t;
+
+/**
+ * @brief Ble scan result event type, to indicate the
+ *        result is scan response or advertising data or other
+ */
+typedef enum {
+    ESP_BLE_EVT_CONN_ADV         = 0x00,        /*!< Connectable undirected advertising (ADV_IND) */
+    ESP_BLE_EVT_CONN_DIR_ADV     = 0x01,        /*!< Connectable directed advertising (ADV_DIRECT_IND) */
+    ESP_BLE_EVT_DISC_ADV         = 0x02,        /*!< Scannable undirected advertising (ADV_SCAN_IND) */
+    ESP_BLE_EVT_NON_CONN_ADV     = 0x03,        /*!< Non connectable undirected advertising (ADV_NONCONN_IND) */
+    ESP_BLE_EVT_SCAN_RSP         = 0x04,        /*!< Scan Response (SCAN_RSP) */
+} esp_ble_evt_type_t;
+
+typedef enum{
+    ESP_BLE_WHITELIST_REMOVE     = 0X00,    /*!< remove mac from whitelist */
+    ESP_BLE_WHITELIST_ADD        = 0X01,    /*!< add address to whitelist */
+}esp_ble_wl_opration_t;
+
+typedef enum {
+    ESP_BLE_DUPLICATE_EXCEPTIONAL_LIST_ADD      = 0,  /*!< Add device info into duplicate scan exceptional list */
+    ESP_BLE_DUPLICATE_EXCEPTIONAL_LIST_REMOVE,        /*!< Remove device info from duplicate scan exceptional list */
+    ESP_BLE_DUPLICATE_EXCEPTIONAL_LIST_CLEAN,         /*!< Clean duplicate scan exceptional list */
+} esp_bt_duplicate_exceptional_subcode_type_t;
+
+#define BLE_BIT(n) (1UL<<(n))
+
+typedef enum {
+    ESP_BLE_DUPLICATE_SCAN_EXCEPTIONAL_INFO_ADV_ADDR       = 0,  /*!< BLE advertising address , device info will be added into ESP_BLE_DUPLICATE_SCAN_EXCEPTIONAL_ADDR_LIST */
+    ESP_BLE_DUPLICATE_SCAN_EXCEPTIONAL_INFO_MESH_LINK_ID,        /*!< BLE mesh link ID, it is for BLE mesh, device info will be added into ESP_BLE_DUPLICATE_SCAN_EXCEPTIONAL_MESH_LINK_ID_LIST */
+    ESP_BLE_DUPLICATE_SCAN_EXCEPTIONAL_INFO_MESH_BEACON_TYPE,    /*!< BLE mesh beacon AD type, the format is | Len | 0x2B | Beacon Type | Beacon Data | */
+    ESP_BLE_DUPLICATE_SCAN_EXCEPTIONAL_INFO_MESH_PROV_SRV_ADV,   /*!< BLE mesh provisioning service uuid, the format is | 0x02 | 0x01 | flags | 0x03 | 0x03 | 0x1827 | .... |` */
+    ESP_BLE_DUPLICATE_SCAN_EXCEPTIONAL_INFO_MESH_PROXY_SRV_ADV,  /*!< BLE mesh adv with proxy service uuid, the format is | 0x02 | 0x01 | flags | 0x03 | 0x03 | 0x1828 | .... |` */
+} esp_ble_duplicate_exceptional_info_type_t;
+
+typedef enum {
+    ESP_BLE_DUPLICATE_SCAN_EXCEPTIONAL_ADDR_LIST                  = BLE_BIT(0),             /*!< duplicate scan exceptional addr list */
+    ESP_BLE_DUPLICATE_SCAN_EXCEPTIONAL_MESH_LINK_ID_LIST          = BLE_BIT(1),             /*!< duplicate scan exceptional mesh link ID list */
+    ESP_BLE_DUPLICATE_SCAN_EXCEPTIONAL_MESH_BEACON_TYPE_LIST      = BLE_BIT(2),             /*!< duplicate scan exceptional mesh beacon type list */
+    ESP_BLE_DUPLICATE_SCAN_EXCEPTIONAL_MESH_PROV_SRV_ADV_LIST     = BLE_BIT(3),             /*!< duplicate scan exceptional mesh adv with provisioning service uuid */
+    ESP_BLE_DUPLICATE_SCAN_EXCEPTIONAL_MESH_PROXY_SRV_ADV_LIST    = BLE_BIT(4),             /*!< duplicate scan exceptional mesh adv with provisioning service uuid */
+    ESP_BLE_DUPLICATE_SCAN_EXCEPTIONAL_ALL_LIST                   = 0xFFFF,                 /*!< duplicate scan exceptional all list */
+} esp_duplicate_scan_exceptional_list_type_t;
+
+typedef uint8_t esp_duplicate_info_t[ESP_BD_ADDR_LEN];
+
+/**
+ * @brief Gap callback parameters union
+ */
+typedef union {
+    /**
+     * @brief ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT
+     */
+    struct ble_adv_data_cmpl_evt_param {
+        esp_bt_status_t status;                     /*!< Indicate the set advertising data operation success status */
+    } adv_data_cmpl;                                /*!< Event parameter of ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT */
+    /**
+     * @brief ESP_GAP_BLE_SCAN_RSP_DATA_SET_COMPLETE_EVT
+     */
+    struct ble_scan_rsp_data_cmpl_evt_param {
+        esp_bt_status_t status;                     /*!< Indicate the set scan response data operation success status */
+    } scan_rsp_data_cmpl;                           /*!< Event parameter of ESP_GAP_BLE_SCAN_RSP_DATA_SET_COMPLETE_EVT */
+    /**
+     * @brief ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT
+     */
+    struct ble_scan_param_cmpl_evt_param {
+        esp_bt_status_t status;                     /*!< Indicate the set scan param operation success status */
+    } scan_param_cmpl;                              /*!< Event parameter of ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT */
+    /**
+     * @brief ESP_GAP_BLE_SCAN_RESULT_EVT
+     */
+    struct ble_scan_result_evt_param {
+        esp_gap_search_evt_t search_evt;            /*!< Search event type */
+        esp_bd_addr_t bda;                          /*!< Bluetooth device address which has been searched */
+        esp_bt_dev_type_t dev_type;                 /*!< Device type */
+        esp_ble_addr_type_t ble_addr_type;          /*!< Ble device address type */
+        esp_ble_evt_type_t ble_evt_type;            /*!< Ble scan result event type */
+        int rssi;                                   /*!< Searched device's RSSI */
+        uint8_t  ble_adv[ESP_BLE_ADV_DATA_LEN_MAX + ESP_BLE_SCAN_RSP_DATA_LEN_MAX];     /*!< Received EIR */
+        int flag;                                   /*!< Advertising data flag bit */
+        int num_resps;                              /*!< Scan result number */
+        uint8_t adv_data_len;                       /*!< Adv data length */
+        uint8_t scan_rsp_len;                       /*!< Scan response length */
+        uint32_t num_dis;                          /*!< The number of discard packets */
+    } scan_rst;                                     /*!< Event parameter of ESP_GAP_BLE_SCAN_RESULT_EVT */
+    /**
+     * @brief ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT
+     */
+    struct ble_adv_data_raw_cmpl_evt_param {
+        esp_bt_status_t status;                     /*!< Indicate the set raw advertising data operation success status */
+    } adv_data_raw_cmpl;                            /*!< Event parameter of ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT */
+    /**
+     * @brief ESP_GAP_BLE_SCAN_RSP_DATA_RAW_SET_COMPLETE_EVT
+     */
+    struct ble_scan_rsp_data_raw_cmpl_evt_param {
+        esp_bt_status_t status;                     /*!< Indicate the set raw advertising data operation success status */
+    } scan_rsp_data_raw_cmpl;                       /*!< Event parameter of ESP_GAP_BLE_SCAN_RSP_DATA_RAW_SET_COMPLETE_EVT */
+    /**
+     * @brief ESP_GAP_BLE_ADV_START_COMPLETE_EVT
+     */
+    struct ble_adv_start_cmpl_evt_param {
+        esp_bt_status_t status;                     /*!< Indicate advertising start operation success status */
+    } adv_start_cmpl;                               /*!< Event parameter of ESP_GAP_BLE_ADV_START_COMPLETE_EVT */
+    /**
+     * @brief ESP_GAP_BLE_SCAN_START_COMPLETE_EVT
+     */
+    struct ble_scan_start_cmpl_evt_param {
+        esp_bt_status_t status;                     /*!< Indicate scan start operation success status */
+    } scan_start_cmpl;                              /*!< Event parameter of ESP_GAP_BLE_SCAN_START_COMPLETE_EVT */
+
+    esp_ble_sec_t ble_security;                     /*!< ble gap security union type */
+    /**
+     * @brief ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT
+     */
+    struct ble_scan_stop_cmpl_evt_param {
+        esp_bt_status_t status;                     /*!< Indicate scan stop operation success status */
+    } scan_stop_cmpl;                               /*!< Event parameter of ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT */
+    /**
+     * @brief ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT
+     */
+    struct ble_adv_stop_cmpl_evt_param {
+        esp_bt_status_t status;                     /*!< Indicate adv stop operation success status */
+    } adv_stop_cmpl;                                /*!< Event parameter of ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT */
+    /**
+     * @brief ESP_GAP_BLE_SET_STATIC_RAND_ADDR_EVT
+     */
+    struct ble_set_rand_cmpl_evt_param {
+        esp_bt_status_t status;                     /*!< Indicate set static rand address operation success status */
+    } set_rand_addr_cmpl;                           /*!< Event parameter of ESP_GAP_BLE_SET_STATIC_RAND_ADDR_EVT */
+    /**
+     * @brief ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT
+     */
+    struct ble_update_conn_params_evt_param {
+        esp_bt_status_t status;                    /*!< Indicate update connection parameters success status */
+        esp_bd_addr_t bda;                         /*!< Bluetooth device address */
+        uint16_t min_int;                          /*!< Min connection interval */
+        uint16_t max_int;                          /*!< Max connection interval */
+        uint16_t latency;                          /*!< Slave latency for the connection in number of connection events. Range: 0x0000 to 0x01F3 */
+        uint16_t conn_int;                         /*!< Current connection interval */
+        uint16_t timeout;                          /*!< Supervision timeout for the LE Link. Range: 0x000A to 0x0C80.
+                                                     Mandatory Range: 0x000A to 0x0C80 Time = N * 10 msec */
+    }update_conn_params;                           /*!< Event parameter of ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT */
+    /**
+     * @brief ESP_GAP_BLE_SET_PKT_LENGTH_COMPLETE_EVT
+     */
+    struct ble_pkt_data_length_cmpl_evt_param {
+        esp_bt_status_t status;                     /*!< Indicate the set pkt data length operation success status */
+        esp_ble_pkt_data_length_params_t params;    /*!<  pkt data length value */
+    } pkt_data_lenth_cmpl;                          /*!< Event parameter of ESP_GAP_BLE_SET_PKT_LENGTH_COMPLETE_EVT */
+    /**
+     * @brief ESP_GAP_BLE_SET_LOCAL_PRIVACY_COMPLETE_EVT
+     */
+    struct ble_local_privacy_cmpl_evt_param {
+        esp_bt_status_t status;                     /*!< Indicate the set local privacy operation success status */
+    } local_privacy_cmpl;                           /*!< Event parameter of ESP_GAP_BLE_SET_LOCAL_PRIVACY_COMPLETE_EVT */
+    /**
+     * @brief ESP_GAP_BLE_REMOVE_BOND_DEV_COMPLETE_EVT
+     */
+    struct ble_remove_bond_dev_cmpl_evt_param {
+        esp_bt_status_t status;                     /*!< Indicate the remove bond device operation success status */
+        esp_bd_addr_t bd_addr;                      /*!< The device address which has been remove from the bond list */
+    }remove_bond_dev_cmpl;                          /*!< Event parameter of ESP_GAP_BLE_REMOVE_BOND_DEV_COMPLETE_EVT */
+    /**
+     * @brief ESP_GAP_BLE_CLEAR_BOND_DEV_COMPLETE_EVT
+     */
+    struct ble_clear_bond_dev_cmpl_evt_param {
+        esp_bt_status_t status;                     /*!< Indicate the clear bond device operation success status */
+    }clear_bond_dev_cmpl;                           /*!< Event parameter of ESP_GAP_BLE_CLEAR_BOND_DEV_COMPLETE_EVT */
+    /**
+     * @brief ESP_GAP_BLE_GET_BOND_DEV_COMPLETE_EVT
+     */
+    struct ble_get_bond_dev_cmpl_evt_param {
+        esp_bt_status_t status;                     /*!< Indicate the get bond device operation success status */
+        uint8_t dev_num;                            /*!< Indicate the get number device in the bond list */
+        esp_ble_bond_dev_t *bond_dev;               /*!< the pointer to the bond device Structure */
+    }get_bond_dev_cmpl;                             /*!< Event parameter of ESP_GAP_BLE_GET_BOND_DEV_COMPLETE_EVT */
+    /**
+     * @brief ESP_GAP_BLE_READ_RSSI_COMPLETE_EVT
+     */
+    struct ble_read_rssi_cmpl_evt_param {
+        esp_bt_status_t status;                     /*!< Indicate the read adv tx power operation success status */
+        int8_t rssi;                                /*!< The ble remote device rssi value, the range is from -127 to 20, the unit is dbm,
+                                                         if the RSSI cannot be read, the RSSI metric shall be set to 127. */
+        esp_bd_addr_t remote_addr;                  /*!< The remote device address */
+    } read_rssi_cmpl;                               /*!< Event parameter of ESP_GAP_BLE_READ_RSSI_COMPLETE_EVT */
+    /**
+     * @brief ESP_GAP_BLE_UPDATE_WHITELIST_COMPLETE_EVT
+     */
+    struct ble_update_whitelist_cmpl_evt_param {
+        esp_bt_status_t status;                     /*!< Indicate the add or remove whitelist operation success status */
+        esp_ble_wl_opration_t wl_opration;          /*!< The value is ESP_BLE_WHITELIST_ADD if add address to whitelist operation success, ESP_BLE_WHITELIST_REMOVE if remove address from the whitelist operation success */
+    } update_whitelist_cmpl;                        /*!< Event parameter of ESP_GAP_BLE_UPDATE_WHITELIST_COMPLETE_EVT */
+    /**
+     * @brief ESP_GAP_BLE_UPDATE_DUPLICATE_EXCEPTIONAL_LIST_COMPLETE_EVT
+     */
+    struct ble_update_duplicate_exceptional_list_cmpl_evt_param {
+        esp_bt_status_t status;                     /*!< Indicate update duplicate scan exceptional list operation success status */
+        uint8_t         subcode;                    /*!< Define in esp_bt_duplicate_exceptional_subcode_type_t */
+        uint16_t         length;                     /*!< The length of device_info */
+        esp_duplicate_info_t device_info;           /*!< device information, when subcode is ESP_BLE_DUPLICATE_EXCEPTIONAL_LIST_CLEAN, the value is invalid */
+    } update_duplicate_exceptional_list_cmpl;       /*!< Event parameter of ESP_GAP_BLE_UPDATE_DUPLICATE_EXCEPTIONAL_LIST_COMPLETE_EVT */
+} esp_ble_gap_cb_param_t;
+
+/**
+ * @brief GAP callback function type
+ * @param event : Event type
+ * @param param : Point to callback parameter, currently is union type
+ */
+typedef void (* esp_gap_ble_cb_t)(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param);
+
+/**
+ * @brief           This function is called to occur gap event, such as scan result
+ *
+ * @param[in]       callback: callback function
+ *
+ * @return
+ *                  - ESP_OK : success
+ *                  - other  : failed
+ *
+ */
+esp_err_t esp_ble_gap_register_callback(esp_gap_ble_cb_t callback);
+
+
+/**
+ * @brief           This function is called to override the BTA default ADV parameters.
+ *
+ * @param[in]       adv_data: Pointer to User defined ADV data structure. This
+ *                  memory space can not be freed until callback of config_adv_data
+ *                  is received.
+ *
+ * @return
+ *                  - ESP_OK : success
+ *                  - other  : failed
+ *
+ */
+esp_err_t esp_ble_gap_config_adv_data (esp_ble_adv_data_t *adv_data);
+
+
+
+/**
+ * @brief           This function is called to set scan parameters
+ *
+ * @param[in]       scan_params: Pointer to User defined scan_params data structure. This
+ *                  memory space can not be freed until callback of set_scan_params
+ *
+ * @return
+ *                  - ESP_OK : success
+ *                  - other  : failed
+ *
+ */
+esp_err_t esp_ble_gap_set_scan_params(esp_ble_scan_params_t *scan_params);
+
+
+/**
+ * @brief           This procedure keep the device scanning the peer device which advertising on the air
+ *
+ * @param[in]       duration: Keeping the scanning time, the unit is second.
+ *
+ * @return
+ *                  - ESP_OK : success
+ *                  - other  : failed
+ *
+ */
+esp_err_t esp_ble_gap_start_scanning(uint32_t duration);
+
+
+/**
+ * @brief          This function call to stop the device scanning the peer device which advertising on the air
+ * @return
+ *                 - ESP_OK : success
+ *                  - other  : failed
+ *
+ */
+esp_err_t esp_ble_gap_stop_scanning(void);
+
+/**
+ * @brief           This function is called to start advertising.
+ *
+ * @param[in]       adv_params: pointer to User defined adv_params data structure.
+
+ * @return
+ *                  - ESP_OK : success
+ *                  - other  : failed
+ *
+ */
+esp_err_t esp_ble_gap_start_advertising (esp_ble_adv_params_t *adv_params);
+
+
+
+/**
+ * @brief           This function is called to stop advertising.
+ *
+ * @return
+ *                  - ESP_OK : success
+ *                  - other  : failed
+ *
+ */
+esp_err_t esp_ble_gap_stop_advertising(void);
+
+
+
+/**
+ * @brief           Update connection parameters, can only be used when connection is up.
+ *
+ * @param[in]       params   -  connection update parameters
+ *
+ * @return
+ *                  - ESP_OK : success
+ *                  - other  : failed
+ *
+ */
+esp_err_t esp_ble_gap_update_conn_params(esp_ble_conn_update_params_t *params);
+
+
+/**
+ * @brief           This function is to set maximum LE data packet size
+ *
+ * @return
+ *                  - ESP_OK : success
+ *                  - other  : failed
+ *
+ */
+esp_err_t esp_ble_gap_set_pkt_data_len(esp_bd_addr_t remote_device, uint16_t tx_data_length);
+
+/**
+ * @brief           This function sets the static Random Address and Non-Resolvable Private Address for the application
+ *
+ * @param[in]       rand_addr: the random address which should be setting
+ *
+ * @return
+ *                  - ESP_OK : success
+ *                  - other  : failed
+ *
+ */
+esp_err_t esp_ble_gap_set_rand_addr(esp_bd_addr_t rand_addr);
+
+/**
+ * @brief           This function clears the random address for the application
+ *
+ * @return
+ *                  - ESP_OK : success
+ *                  - other  : failed
+ *
+ */
+esp_err_t esp_ble_gap_clear_rand_addr(void);
+
+
+
+/**
+ * @brief           Enable/disable privacy on the local device
+ *
+ * @param[in]       privacy_enable   - enable/disable privacy on remote device.
+ *
+ * @return
+ *                  - ESP_OK : success
+ *                  - other  : failed
+ *
+ */
+esp_err_t esp_ble_gap_config_local_privacy (bool privacy_enable);
+
+/**
+ * @brief           set local gap appearance icon
+ *
+ *
+ * @param[in]       icon   - External appearance value, these values are defined by the Bluetooth SIG, please refer to
+ *                  https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.gap.appearance.xml
+ *
+ * @return
+ *                  - ESP_OK : success
+ *                  - other  : failed
+ *
+ */
+esp_err_t esp_ble_gap_config_local_icon (uint16_t icon);
+
+/**
+* @brief            Add or remove device from white list
+*
+* @param[in]        add_remove: the value is true if added the ble device to the white list, and false remove to the white list.
+* @param[in]        remote_bda: the remote device address add/remove from the white list.
+* @param[in]        wl_addr_type: whitelist address type
+* @return
+*                     - ESP_OK : success
+*                     - other  : failed
+*
+*/
+esp_err_t esp_ble_gap_update_whitelist(bool add_remove, esp_bd_addr_t remote_bda, esp_ble_wl_addr_type_t wl_addr_type);
+
+/**
+* @brief            Get the whitelist size in the controller
+*
+* @param[out]       length: the white list length.
+* @return
+*                     - ESP_OK : success
+*                     - other  : failed
+*
+*/
+esp_err_t esp_ble_gap_get_whitelist_size(uint16_t *length);
+
+/**
+* @brief            This function is called to set the preferred connection
+*                   parameters when default connection parameter is not desired before connecting.
+*                   This API can only be used in the master role.
+*
+* @param[in]        bd_addr: BD address of the peripheral
+* @param[in]        min_conn_int: minimum preferred connection interval
+* @param[in]        max_conn_int: maximum preferred connection interval
+* @param[in]        slave_latency: preferred slave latency
+* @param[in]        supervision_tout: preferred supervision timeout
+*
+* @return
+*                   - ESP_OK : success
+*                   - other  : failed
+*
+*/
+esp_err_t esp_ble_gap_set_prefer_conn_params(esp_bd_addr_t bd_addr,
+                                                                 uint16_t min_conn_int, uint16_t max_conn_int,
+                                                                 uint16_t slave_latency, uint16_t supervision_tout);
+
+/**
+ * @brief           Set device name to the local device
+ *
+ * @param[in]       name   -  device name.
+ *
+ * @return
+ *                  - ESP_OK : success
+ *                  - other  : failed
+ *
+ */
+esp_err_t esp_ble_gap_set_device_name(const char *name);
+
+/**
+ * @brief          This function is called to get local used address and adress type.
+ *                 uint8_t *esp_bt_dev_get_address(void) get the public address
+ *
+ * @param[in]       local_used_addr - current local used ble address (six bytes)
+ * @param[in]       addr_type   - ble address type
+ *
+ * @return          - ESP_OK : success
+ *                  - other  : failed
+ *
+ */
+esp_err_t esp_ble_gap_get_local_used_addr(esp_bd_addr_t local_used_addr, uint8_t * addr_type);
+/**
+ * @brief          This function is called to get ADV data for a specific type.
+ *
+ * @param[in]       adv_data - pointer of ADV data which to be resolved
+ * @param[in]       type   - finding ADV data type
+ * @param[out]      length - return the length of ADV data not including type
+ *
+ * @return          pointer of ADV data
+ *
+ */
+uint8_t *esp_ble_resolve_adv_data(uint8_t *adv_data, uint8_t type, uint8_t *length);
+
+/**
+ * @brief           This function is called to set raw advertising data. User need to fill
+ *                  ADV data by self.
+ *
+ * @param[in]       raw_data : raw advertising data
+ * @param[in]       raw_data_len : raw advertising data length , less than 31 bytes
+ *
+ * @return
+ *                  - ESP_OK : success
+ *                  - other  : failed
+ *
+ */
+esp_err_t esp_ble_gap_config_adv_data_raw(uint8_t *raw_data, uint32_t raw_data_len);
+
+/**
+ * @brief           This function is called to set raw scan response data. User need to fill
+ *                  scan response data by self.
+ *
+ * @param[in]       raw_data : raw scan response data
+ * @param[in]       raw_data_len : raw scan response data length , less than 31 bytes
+ *
+ * @return
+ *                  - ESP_OK : success
+ *                  - other  : failed
+ */
+esp_err_t esp_ble_gap_config_scan_rsp_data_raw(uint8_t *raw_data, uint32_t raw_data_len);
+
+/**
+ * @brief           This function is called to read the RSSI of remote device.
+ *                  The address of link policy results are returned in the gap callback function with
+ *                  ESP_GAP_BLE_READ_RSSI_COMPLETE_EVT event.
+ *
+ * @param[in]       remote_addr : The remote connection device address.
+ *
+ * @return
+ *                  - ESP_OK : success
+ *                  - other  : failed
+ */
+esp_err_t esp_ble_gap_read_rssi(esp_bd_addr_t remote_addr);
+
+/**
+ * @brief           This function is called to add a device info into the duplicate scan exceptional list.
+ *
+ *
+ * @param[in]       type: device info type, it is defined in esp_ble_duplicate_exceptional_info_type_t
+ *                  when type is MESH_BEACON_TYPE, MESH_PROV_SRV_ADV or MESH_PROXY_SRV_ADV , device_info is invalid.
+ * @param[in]       device_info: the device information.
+ * @return
+ *                  - ESP_OK : success
+ *                  - other  : failed
+ */
+esp_err_t esp_ble_gap_add_duplicate_scan_exceptional_device(esp_ble_duplicate_exceptional_info_type_t type, esp_duplicate_info_t device_info);
+
+/**
+ * @brief           This function is called to remove a device info from the duplicate scan exceptional list.
+ *
+ *
+ * @param[in]       type: device info type, it is defined in esp_ble_duplicate_exceptional_info_type_t
+ *                  when type is MESH_BEACON_TYPE, MESH_PROV_SRV_ADV or MESH_PROXY_SRV_ADV , device_info is invalid.
+ * @param[in]       device_info: the device information.
+ * @return
+ *                  - ESP_OK : success
+ *                  - other  : failed
+ */
+esp_err_t esp_ble_gap_remove_duplicate_scan_exceptional_device(esp_ble_duplicate_exceptional_info_type_t type, esp_duplicate_info_t device_info);
+
+/**
+ * @brief           This function is called to clean the duplicate scan exceptional list.
+ *                  This API will delete all device information in the duplicate scan exceptional list.
+ *
+ *
+ * @param[in]       list_type: duplicate scan exceptional list type, the value can be one or more of esp_duplicate_scan_exceptional_list_type_t.
+ *
+ * @return
+ *                  - ESP_OK : success
+ *                  - other  : failed
+ */
+esp_err_t esp_ble_gap_clean_duplicate_scan_exceptional_list(esp_duplicate_scan_exceptional_list_type_t list_type);
+
+#if (SMP_INCLUDED == TRUE)
+/**
+* @brief             Set a GAP security parameter value. Overrides the default value.
+*
+*                    Secure connection is highly recommended to avoid some major
+*                    vulnerabilities like 'Impersonation in the Pin Pairing Protocol'
+*                    (CVE-2020-26555) and 'Authentication of the LE Legacy Pairing
+*                    Protocol'.
+*
+*                    To accept only `secure connection mode`, it is necessary do as following:
+*
+*                    1. Set bit `ESP_LE_AUTH_REQ_SC_ONLY` (`param_type` is
+*                    `ESP_BLE_SM_AUTHEN_REQ_MODE`), bit `ESP_LE_AUTH_BOND` and bit
+*                    `ESP_LE_AUTH_REQ_MITM` is optional as required.
+*
+*                    2. Set to `ESP_BLE_ONLY_ACCEPT_SPECIFIED_AUTH_ENABLE` (`param_type` is
+*                    `ESP_BLE_SM_ONLY_ACCEPT_SPECIFIED_SEC_AUTH`).
+*
+* @param[in]       param_type : the type of the param which to be set
+* @param[in]       value  : the param value
+* @param[in]       len : the length of the param value
+*
+* @return            - ESP_OK : success
+*                       - other  : failed
+*
+*/
+esp_err_t esp_ble_gap_set_security_param(esp_ble_sm_param_t param_type,
+                                         void *value, uint8_t len);
+
+/**
+* @brief             Grant security request access.
+*
+* @param[in]       bd_addr : BD address of the peer
+* @param[in]       accept  :  accept the security request or not
+*
+* @return            - ESP_OK : success
+*                    - other  : failed
+*
+*/
+esp_err_t esp_ble_gap_security_rsp(esp_bd_addr_t bd_addr,  bool accept);
+
+
+/**
+* @brief             Set a gap parameter value. Use this function to change
+*                    the default GAP parameter values.
+*
+* @param[in]       bd_addr : the address of the peer device need to encryption
+* @param[in]       sec_act  : This is the security action to indicate
+*                                   what kind of BLE security level is required for
+*                                   the BLE link if the BLE is supported
+*
+* @return            - ESP_OK : success
+*                       - other  : failed
+*
+*/
+esp_err_t esp_ble_set_encryption(esp_bd_addr_t bd_addr, esp_ble_sec_act_t sec_act);
+
+/**
+* @brief          Reply the key value to the peer device in the legacy connection stage.
+*
+* @param[in]      bd_addr : BD address of the peer
+* @param[in]      accept : passkey entry successful or declined.
+* @param[in]      passkey : passkey value, must be a 6 digit number,
+*                                     can be lead by 0.
+*
+* @return            - ESP_OK : success
+*                  - other  : failed
+*
+*/
+esp_err_t esp_ble_passkey_reply(esp_bd_addr_t bd_addr, bool accept, uint32_t passkey);
+
+
+/**
+* @brief           Reply the confirm value to the peer device in the secure connection stage.
+*
+* @param[in]       bd_addr : BD address of the peer device
+* @param[in]       accept : numbers to compare are the same or different.
+*
+* @return            - ESP_OK : success
+*                       - other  : failed
+*
+*/
+esp_err_t esp_ble_confirm_reply(esp_bd_addr_t bd_addr, bool accept);
+
+/**
+* @brief           Removes a device from the security database list of
+*                  peer device. It manages unpairing event while connected.
+*
+* @param[in]       bd_addr : BD address of the peer device
+*
+* @return            - ESP_OK : success
+*                       - other  : failed
+*
+*/
+esp_err_t esp_ble_remove_bond_device(esp_bd_addr_t bd_addr);
+
+/**
+* @brief           Get the device number from the security database list of peer device.
+*                  It will return the device bonded number immediately.
+*
+* @return          - >= 0 : bonded devices number.
+*                  - ESP_FAIL  : failed
+*
+*/
+int esp_ble_get_bond_device_num(void);
+
+
+/**
+* @brief           Get the device from the security database list of peer device.
+*                  It will return the device bonded information immediately.
+* @param[inout]    dev_num: Indicate the dev_list array(buffer) size as input.
+*                           If dev_num is large enough, it means the actual number as output.
+*                           Suggest that dev_num value equal to esp_ble_get_bond_device_num().
+*
+* @param[out]      dev_list: an array(buffer) of `esp_ble_bond_dev_t` type. Use for storing the bonded devices address.
+*                            The dev_list should be allocated by who call this API.
+* @return          - ESP_OK : success
+*                  - other  : failed
+*
+*/
+esp_err_t esp_ble_get_bond_device_list(int *dev_num, esp_ble_bond_dev_t *dev_list);
+
+/**
+* @brief           This function is called to provide the OOB data for
+*                  SMP in response to ESP_GAP_BLE_OOB_REQ_EVT
+*
+* @param[in]       bd_addr: BD address of the peer device.
+* @param[in]       TK: TK value, the TK value shall be a 128-bit random number
+* @param[in]       len: length of tk, should always be 128-bit
+*
+* @return          - ESP_OK : success
+*                  - other  : failed
+*
+*/
+esp_err_t esp_ble_oob_req_reply(esp_bd_addr_t bd_addr, uint8_t *TK, uint8_t len);
+
+#endif /* #if (SMP_INCLUDED == TRUE) */
+
+/**
+* @brief           This function is to disconnect the physical connection of the peer device
+*                  gattc may have multiple virtual GATT server connections when multiple app_id registered.
+*                  esp_ble_gattc_close (esp_gatt_if_t gattc_if, uint16_t conn_id) only close one virtual GATT server connection.
+*                  if there exist other virtual GATT server connections, it does not disconnect the physical connection.
+*                  esp_ble_gap_disconnect(esp_bd_addr_t remote_device) disconnect the physical connection directly.
+*
+*
+*
+* @param[in]       remote_device : BD address of the peer device
+*
+* @return            - ESP_OK : success
+*                    - other  : failed
+*
+*/
+esp_err_t esp_ble_gap_disconnect(esp_bd_addr_t remote_device);
+
+/**
+* @brief           This function is called to read the connection
+*                  parameters information of the device
+*
+* @param[in]       bd_addr: BD address of the peer device.
+* @param[out]      conn_params: the connection parameters information
+*
+* @return          - ESP_OK : success
+*                  - other  : failed
+*
+*/
+esp_err_t esp_ble_get_current_conn_params(esp_bd_addr_t bd_addr, esp_gap_conn_params_t *conn_params);
+
+/**
+* @brief           This function is called to authorized a link after Authentication(MITM protection)
+*
+* @param[in]       bd_addr: BD address of the peer device.
+* @param[out]      authorize: Authorized the link or not.
+*
+* @return          - ESP_OK : success
+*                  - other  : failed
+*
+*/
+esp_err_t esp_gap_ble_set_authorization(esp_bd_addr_t bd_addr, bool authorize);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ESP_GAP_BLE_API_H__ */

+ 2187 - 0
components/bt/host/bluedroid/stack/smp/smp_act.c

@@ -0,0 +1,2187 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at:
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ ******************************************************************************/
+
+#include <string.h>
+#include "device/interop.h"
+#include "common/bt_target.h"
+#include "btm_int.h"
+#include "stack/l2c_api.h"
+#include "smp_int.h"
+#include "p_256_ecc_pp.h"
+//#include "utils/include/bt_utils.h"
+
+#if SMP_INCLUDED == TRUE
+const UINT8 smp_association_table[2][SMP_IO_CAP_MAX][SMP_IO_CAP_MAX] = {
+    /* initiator */
+    {   {SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_PASSKEY,   SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_PASSKEY}, /* Display Only */
+        {SMP_MODEL_ENCRYPTION_ONLY,  SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_PASSKEY, SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_PASSKEY}, /* SMP_CAP_IO = 1 */
+        {SMP_MODEL_KEY_NOTIF, SMP_MODEL_KEY_NOTIF,  SMP_MODEL_PASSKEY,   SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_KEY_NOTIF}, /* keyboard only */
+        {SMP_MODEL_ENCRYPTION_ONLY,  SMP_MODEL_ENCRYPTION_ONLY,   SMP_MODEL_ENCRYPTION_ONLY,  SMP_MODEL_ENCRYPTION_ONLY,    SMP_MODEL_ENCRYPTION_ONLY},/* No Input No Output */
+        {SMP_MODEL_KEY_NOTIF, SMP_MODEL_KEY_NOTIF,  SMP_MODEL_PASSKEY,   SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_KEY_NOTIF}
+    }, /* keyboard display */
+    /* responder */
+    {   {SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_ENCRYPTION_ONLY,   SMP_MODEL_KEY_NOTIF, SMP_MODEL_ENCRYPTION_ONLY,    SMP_MODEL_KEY_NOTIF}, /* Display Only */
+        {SMP_MODEL_ENCRYPTION_ONLY,  SMP_MODEL_ENCRYPTION_ONLY,   SMP_MODEL_KEY_NOTIF,   SMP_MODEL_ENCRYPTION_ONLY,    SMP_MODEL_KEY_NOTIF}, /* SMP_CAP_IO = 1 */
+        {SMP_MODEL_PASSKEY,   SMP_MODEL_PASSKEY,    SMP_MODEL_PASSKEY,   SMP_MODEL_ENCRYPTION_ONLY,    SMP_MODEL_PASSKEY}, /* keyboard only */
+        {SMP_MODEL_ENCRYPTION_ONLY,  SMP_MODEL_ENCRYPTION_ONLY,   SMP_MODEL_ENCRYPTION_ONLY,  SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_ENCRYPTION_ONLY},/* No Input No Output */
+        {SMP_MODEL_PASSKEY,   SMP_MODEL_PASSKEY,    SMP_MODEL_KEY_NOTIF, SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_PASSKEY}
+    } /* keyboard display */
+    /* display only */    /*SMP_CAP_IO = 1 */  /* keyboard only */   /* No InputOutput */  /* keyboard display */
+};
+
+#define SMP_KEY_DIST_TYPE_MAX       4
+const tSMP_ACT smp_distribute_act [] = {
+#if (BLE_INCLUDED == TRUE)
+    smp_generate_ltk,
+    smp_send_id_info,
+    smp_generate_csrk,
+    smp_set_derive_link_key
+#else
+    NULL,
+    NULL,
+    NULL,
+    NULL
+#endif  ///BLE_INCLUDED == TRUE
+};
+
+extern UINT8 bta_dm_co_ble_get_accept_auth_enable(void);
+extern UINT8 bta_dm_co_ble_get_auth_req(void);
+
+static bool lmp_version_below(BD_ADDR bda, uint8_t version)
+{
+    tACL_CONN *acl = btm_bda_to_acl(bda, BT_TRANSPORT_LE);
+    if (acl == NULL || acl->lmp_version == 0) {
+        SMP_TRACE_WARNING("%s cannot retrieve LMP version...", __func__);
+        return false;
+    }
+    SMP_TRACE_DEBUG("%s LMP version %d < %d", __func__, acl->lmp_version, version);
+    return acl->lmp_version < version;
+}
+
+/*******************************************************************************
+** Function         smp_update_key_mask
+** Description      This function updates the key mask for sending or receiving.
+*******************************************************************************/
+static void smp_update_key_mask (tSMP_CB *p_cb, UINT8 key_type, BOOLEAN recv)
+{
+    SMP_TRACE_DEBUG("%s before update role=%d recv=%d local_i_key = %02x, local_r_key = %02x\n",
+                    __func__, p_cb->role, recv, p_cb->local_i_key, p_cb->local_r_key);
+
+    if (((p_cb->le_secure_connections_mode_is_used) ||
+            (p_cb->smp_over_br)) &&
+            ((key_type == SMP_SEC_KEY_TYPE_ENC) || (key_type == SMP_SEC_KEY_TYPE_LK))) {
+        /* in LE SC mode LTK, CSRK and BR/EDR LK are derived locally instead of
+        ** being exchanged with the peer */
+        p_cb->local_i_key &= ~key_type;
+        p_cb->local_r_key &= ~key_type;
+    } else if (p_cb->role == HCI_ROLE_SLAVE) {
+        if (recv) {
+            p_cb->local_i_key &= ~key_type;
+        } else {
+            p_cb->local_r_key &= ~key_type;
+        }
+    } else {
+        if (recv) {
+            p_cb->local_r_key &= ~key_type;
+        } else {
+            p_cb->local_i_key &= ~key_type;
+        }
+    }
+
+    SMP_TRACE_DEBUG("updated local_i_key = %02x, local_r_key = %02x\n", p_cb->local_i_key,
+                    p_cb->local_r_key);
+}
+
+/*******************************************************************************
+** Function     smp_send_app_cback
+** Description  notifies application about the events the application is interested in
+*******************************************************************************/
+void smp_send_app_cback(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    tSMP_EVT_DATA   cb_data;
+    tSMP_STATUS callback_rc;
+    SMP_TRACE_DEBUG("%s p_cb->cb_evt=%d\n", __func__, p_cb->cb_evt);
+    if (p_cb->p_callback && p_cb->cb_evt != 0) {
+        switch (p_cb->cb_evt) {
+        case SMP_IO_CAP_REQ_EVT:
+            cb_data.io_req.auth_req = p_cb->peer_auth_req;
+            cb_data.io_req.oob_data = SMP_OOB_NONE;
+            cb_data.io_req.io_cap = SMP_DEFAULT_IO_CAPS;
+            cb_data.io_req.max_key_size = SMP_MAX_ENC_KEY_SIZE;
+            cb_data.io_req.init_keys = p_cb->local_i_key ;
+            cb_data.io_req.resp_keys = p_cb->local_r_key ;
+            SMP_TRACE_DEBUG ( "io_cap = %d", cb_data.io_req.io_cap);
+            break;
+
+        case SMP_NC_REQ_EVT:
+            cb_data.passkey = p_data->passkey;
+            break;
+        case SMP_SC_OOB_REQ_EVT:
+            cb_data.req_oob_type = p_data->req_oob_type;
+            break;
+        case SMP_SC_LOC_OOB_DATA_UP_EVT:
+            cb_data.loc_oob_data = p_cb->sc_oob_data.loc_oob_data;
+            break;
+
+        case SMP_BR_KEYS_REQ_EVT:
+            cb_data.io_req.auth_req = 0;
+            cb_data.io_req.oob_data = SMP_OOB_NONE;
+            cb_data.io_req.io_cap = 0;
+            cb_data.io_req.max_key_size = SMP_MAX_ENC_KEY_SIZE;
+            cb_data.io_req.init_keys = SMP_BR_SEC_DEFAULT_KEY;
+            cb_data.io_req.resp_keys = SMP_BR_SEC_DEFAULT_KEY;
+            break;
+
+        default:
+            break;
+        }
+
+        callback_rc = (*p_cb->p_callback)(p_cb->cb_evt, p_cb->pairing_bda, &cb_data);
+
+        SMP_TRACE_DEBUG("callback_rc=%d  p_cb->cb_evt=%d\n", callback_rc, p_cb->cb_evt );
+
+        if (callback_rc == SMP_SUCCESS) {
+            switch (p_cb->cb_evt) {
+            case SMP_IO_CAP_REQ_EVT:
+                p_cb->loc_auth_req   = cb_data.io_req.auth_req;
+                p_cb->local_io_capability  = cb_data.io_req.io_cap;
+                p_cb->loc_oob_flag = cb_data.io_req.oob_data;
+                p_cb->loc_enc_size = cb_data.io_req.max_key_size;
+                p_cb->local_i_key = cb_data.io_req.init_keys;
+                p_cb->local_r_key = cb_data.io_req.resp_keys;
+
+                if (!(p_cb->loc_auth_req & SMP_AUTH_BOND)) {
+                    SMP_TRACE_WARNING ("Non bonding: No keys will be exchanged");
+                    p_cb->local_i_key = 0;
+                    p_cb->local_r_key = 0;
+                }
+
+                SMP_TRACE_DEBUG ("rcvd auth_req: 0x%02x, io_cap: %d \
+                        loc_oob_flag: %d loc_enc_size: %d,"
+                                    "local_i_key: 0x%02x, local_r_key: 0x%02x\n",
+                                    p_cb->loc_auth_req, p_cb->local_io_capability, p_cb->loc_oob_flag,
+                                    p_cb->loc_enc_size, p_cb->local_i_key, p_cb->local_r_key);
+
+                p_cb->secure_connections_only_mode_required =
+                    (btm_cb.security_mode == BTM_SEC_MODE_SC) ? TRUE : FALSE;
+
+                if (p_cb->secure_connections_only_mode_required) {
+                    p_cb->loc_auth_req |= SMP_SC_SUPPORT_BIT;
+                }
+
+                if (!(p_cb->loc_auth_req & SMP_SC_SUPPORT_BIT)
+                        || lmp_version_below(p_cb->pairing_bda, HCI_PROTO_VERSION_4_2)
+                        || interop_match(INTEROP_DISABLE_LE_SECURE_CONNECTIONS,
+                                         (const bt_bdaddr_t *)&p_cb->pairing_bda)) {
+                    p_cb->loc_auth_req &= ~SMP_KP_SUPPORT_BIT;
+                    p_cb->local_i_key &= ~SMP_SEC_KEY_TYPE_LK;
+                    p_cb->local_r_key &= ~SMP_SEC_KEY_TYPE_LK;
+                }
+
+                SMP_TRACE_DEBUG("set auth_req: 0x%02x, local_i_key: 0x%02x, local_r_key: 0x%02x\n",
+                                  p_cb->loc_auth_req, p_cb->local_i_key, p_cb->local_r_key);
+
+                smp_sm_event(p_cb, SMP_IO_RSP_EVT, NULL);
+                break;
+#if (CLASSIC_BT_INCLUDED == TRUE)
+            case SMP_BR_KEYS_REQ_EVT:
+                p_cb->loc_enc_size = cb_data.io_req.max_key_size;
+                p_cb->local_i_key = cb_data.io_req.init_keys;
+                p_cb->local_r_key = cb_data.io_req.resp_keys;
+
+                p_cb->local_i_key &= ~SMP_SEC_KEY_TYPE_LK;
+                p_cb->local_r_key &= ~SMP_SEC_KEY_TYPE_LK;
+
+                SMP_TRACE_WARNING ( "for SMP over BR max_key_size: 0x%02x,\
+                        local_i_key: 0x%02x, local_r_key: 0x%02x\n",
+                                    p_cb->loc_enc_size, p_cb->local_i_key, p_cb->local_r_key);
+
+                smp_br_state_machine_event(p_cb, SMP_BR_KEYS_RSP_EVT, NULL);
+                break;
+#endif  ///CLASSIC_BT_INCLUDED == TRUE
+            }
+        }
+    }
+
+    if (!p_cb->cb_evt && p_cb->discard_sec_req) {
+        p_cb->discard_sec_req = FALSE;
+        smp_sm_event(p_cb, SMP_DISCARD_SEC_REQ_EVT, NULL);
+    }
+
+    SMP_TRACE_DEBUG("%s return\n", __func__);
+}
+
+/*******************************************************************************
+** Function     smp_send_pair_fail
+** Description  pairing failure to peer device if needed.
+*******************************************************************************/
+void smp_send_pair_fail(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    p_cb->status = *(UINT8 *)p_data;
+    p_cb->failure = *(UINT8 *)p_data;
+
+    SMP_TRACE_DEBUG("%s status=%d failure=%d ", __func__, p_cb->status, p_cb->failure);
+
+    if (p_cb->status <= SMP_MAX_FAIL_RSN_PER_SPEC && p_cb->status != SMP_SUCCESS) {
+        smp_send_cmd(SMP_OPCODE_PAIRING_FAILED, p_cb);
+        p_cb->wait_for_authorization_complete = TRUE;
+    }
+}
+
+/*******************************************************************************
+** Function     smp_send_pair_req
+** Description  actions related to sending pairing request
+*******************************************************************************/
+void smp_send_pair_req(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    SMP_TRACE_DEBUG("%s\n", __func__);
+
+#if (BLE_INCLUDED == TRUE)
+    tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (p_cb->pairing_bda);
+    /* erase all keys when master sends pairing req*/
+    if (p_dev_rec) {
+        btm_sec_clear_ble_keys(p_dev_rec);
+    }
+#endif  ///BLE_INCLUDED == TRUE
+    /* do not manipulate the key, let app decide,
+       leave out to BTM to mandate key distribution for bonding case */
+    smp_send_cmd(SMP_OPCODE_PAIRING_REQ, p_cb);
+}
+
+/*******************************************************************************
+** Function     smp_send_pair_rsp
+** Description  actions related to sending pairing response
+*******************************************************************************/
+void smp_send_pair_rsp(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    SMP_TRACE_DEBUG("%s\n", __func__);
+
+#if (BLE_INCLUDED == TRUE)
+    p_cb->local_i_key &= p_cb->peer_i_key;
+    p_cb->local_r_key &= p_cb->peer_r_key;
+
+    if (smp_send_cmd (SMP_OPCODE_PAIRING_RSP, p_cb)) {
+        if (p_cb->selected_association_model == SMP_MODEL_SEC_CONN_OOB) {
+            smp_use_oob_private_key(p_cb, NULL);
+        } else {
+            smp_decide_association_model(p_cb, NULL);
+        }
+    }
+#endif  ///BLE_INCLUDED == TRUE
+}
+
+/*******************************************************************************
+** Function     smp_send_confirm
+** Description  send confirmation to the peer
+*******************************************************************************/
+void smp_send_confirm(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    SMP_TRACE_DEBUG("%s\n", __func__);
+    smp_send_cmd(SMP_OPCODE_CONFIRM, p_cb);
+}
+
+#if 0 //Unused
+/*******************************************************************************
+** Function     smp_send_init
+** Description  process pairing initializer to slave device
+*******************************************************************************/
+void smp_send_init(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    SMP_TRACE_DEBUG("%s\n", __func__);
+    smp_send_cmd(SMP_OPCODE_INIT, p_cb);
+}
+#endif
+
+/*******************************************************************************
+** Function     smp_send_rand
+** Description  send pairing random to the peer
+*******************************************************************************/
+void smp_send_rand(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    SMP_TRACE_DEBUG("%s\n", __func__);
+    smp_send_cmd(SMP_OPCODE_RAND, p_cb);
+}
+
+/*******************************************************************************
+** Function     smp_send_pair_public_key
+** Description  send pairing public key command to the peer
+*******************************************************************************/
+void smp_send_pair_public_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    SMP_TRACE_DEBUG("%s\n", __func__);
+    smp_send_cmd(SMP_OPCODE_PAIR_PUBLIC_KEY, p_cb);
+}
+
+/*******************************************************************************
+** Function     SMP_SEND_COMMITMENT
+** Description send commitment command to the peer
+*******************************************************************************/
+void smp_send_commitment(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    SMP_TRACE_DEBUG("%s", __func__);
+    smp_send_cmd(SMP_OPCODE_PAIR_COMMITM, p_cb);
+}
+
+/*******************************************************************************
+** Function     smp_send_dhkey_check
+** Description send DHKey Check command to the peer
+*******************************************************************************/
+void smp_send_dhkey_check(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    SMP_TRACE_DEBUG("%s", __func__);
+    smp_send_cmd(SMP_OPCODE_PAIR_DHKEY_CHECK, p_cb);
+}
+
+/*******************************************************************************
+** Function     smp_send_keypress_notification
+** Description send Keypress Notification command to the peer
+*******************************************************************************/
+void smp_send_keypress_notification(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    p_cb->local_keypress_notification = *(UINT8 *) p_data;
+    smp_send_cmd(SMP_OPCODE_PAIR_KEYPR_NOTIF, p_cb);
+}
+
+/*******************************************************************************
+** Function     smp_send_enc_info
+** Description  send encryption information command.
+*******************************************************************************/
+void smp_send_enc_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    tBTM_LE_LENC_KEYS   le_key;
+
+    SMP_TRACE_DEBUG("%s p_cb->loc_enc_size = %d\n", __func__, p_cb->loc_enc_size);
+    smp_update_key_mask (p_cb, SMP_SEC_KEY_TYPE_ENC, FALSE);
+
+    smp_send_cmd(SMP_OPCODE_ENCRYPT_INFO, p_cb);
+    smp_send_cmd(SMP_OPCODE_MASTER_ID, p_cb);
+
+    /* save the DIV and key size information when acting as slave device */
+    memcpy(le_key.ltk, p_cb->ltk, BT_OCTET16_LEN);
+    le_key.div =  p_cb->div;
+    le_key.key_size = p_cb->loc_enc_size;
+    le_key.sec_level = p_cb->sec_level;
+
+#if (BLE_INCLUDED == TRUE)
+    if ((p_cb->peer_auth_req & SMP_AUTH_BOND) && (p_cb->loc_auth_req & SMP_AUTH_BOND)) {
+        btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_LENC,
+                            (tBTM_LE_KEY_VALUE *)&le_key, TRUE);
+    }
+
+    SMP_TRACE_DEBUG ("%s\n", __func__);
+
+    smp_key_distribution(p_cb, NULL);
+#endif  ///BLE_INCLUDED == TRUE
+}
+
+/*******************************************************************************
+** Function     smp_send_id_info
+** Description  send ID information command.
+*******************************************************************************/
+void smp_send_id_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    SMP_TRACE_DEBUG("%s\n", __func__);
+    smp_update_key_mask (p_cb, SMP_SEC_KEY_TYPE_ID, FALSE);
+
+    smp_send_cmd(SMP_OPCODE_IDENTITY_INFO, p_cb);
+    smp_send_cmd(SMP_OPCODE_ID_ADDR, p_cb);
+
+#if (BLE_INCLUDED == TRUE)
+    tBTM_LE_KEY_VALUE   le_key;
+    if ((p_cb->peer_auth_req & SMP_AUTH_BOND) && (p_cb->loc_auth_req & SMP_AUTH_BOND)) {
+        btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_LID,
+                            &le_key, TRUE);
+    }
+#endif  ///BLE_INCLUDED == TRUE
+
+    smp_key_distribution_by_transport(p_cb, NULL);
+}
+
+#if (BLE_INCLUDED == TRUE)
+/*******************************************************************************
+** Function     smp_send_csrk_info
+** Description  send CSRK command.
+*******************************************************************************/
+void smp_send_csrk_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    tBTM_LE_LCSRK_KEYS  key;
+    SMP_TRACE_DEBUG("%s\n", __func__);
+    smp_update_key_mask (p_cb, SMP_SEC_KEY_TYPE_CSRK, FALSE);
+
+    if (smp_send_cmd(SMP_OPCODE_SIGN_INFO, p_cb)) {
+        key.div = p_cb->div;
+        key.sec_level = p_cb->sec_level;
+        key.counter = 0; /* initialize the local counter */
+        memcpy (key.csrk, p_cb->csrk, BT_OCTET16_LEN);
+        btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_LCSRK, (tBTM_LE_KEY_VALUE *)&key, TRUE);
+    }
+
+    smp_key_distribution_by_transport(p_cb, NULL);
+}
+
+/*******************************************************************************
+** Function     smp_send_ltk_reply
+** Description  send LTK reply
+*******************************************************************************/
+void smp_send_ltk_reply(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    SMP_TRACE_DEBUG("%s", __func__);
+    /* send stk as LTK response */
+    btm_ble_ltk_request_reply(p_cb->pairing_bda, TRUE, p_data->key.p_data);
+}
+
+/*******************************************************************************
+** Function     smp_proc_sec_req
+** Description  process security request.
+*******************************************************************************/
+void smp_proc_sec_req(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    tBTM_LE_AUTH_REQ auth_req = *(tBTM_LE_AUTH_REQ *)p_data;
+    tBTM_BLE_SEC_REQ_ACT sec_req_act;
+    UINT8 reason;
+
+    SMP_TRACE_DEBUG("%s auth_req=0x%x", __func__, auth_req);
+
+    p_cb->cb_evt = 0;
+    btm_ble_link_sec_check(p_cb->pairing_bda, auth_req,  &sec_req_act);
+
+    SMP_TRACE_DEBUG("%s sec_req_act=0x%x", __func__, sec_req_act);
+
+    switch (sec_req_act) {
+    case  BTM_BLE_SEC_REQ_ACT_ENCRYPT:
+        SMP_TRACE_DEBUG("%s BTM_BLE_SEC_REQ_ACT_ENCRYPT", __func__);
+        smp_sm_event(p_cb, SMP_ENC_REQ_EVT, NULL);
+        break;
+
+    case BTM_BLE_SEC_REQ_ACT_PAIR:
+        p_cb->secure_connections_only_mode_required =
+            (btm_cb.security_mode == BTM_SEC_MODE_SC) ? TRUE : FALSE;
+
+        /* respond to non SC pairing request as failure in SC only mode */
+        if (p_cb->secure_connections_only_mode_required &&
+                (auth_req & SMP_SC_SUPPORT_BIT) == 0) {
+            reason = SMP_PAIR_AUTH_FAIL;
+            smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+        } else {
+            /* initialize local i/r key to be default keys */
+            p_cb->peer_auth_req = auth_req;
+            p_cb->local_r_key = p_cb->local_i_key = SMP_SEC_DEFAULT_KEY ;
+            p_cb->cb_evt = SMP_SEC_REQUEST_EVT;
+        }
+        break;
+
+    case BTM_BLE_SEC_REQ_ACT_DISCARD:
+        p_cb->discard_sec_req = TRUE;
+        break;
+
+    default:
+        /* do nothing */
+        break;
+    }
+}
+#endif  ///BLE_INCLUDED == TRUE
+
+/*******************************************************************************
+** Function     smp_proc_sec_grant
+** Description  process security grant.
+*******************************************************************************/
+void smp_proc_sec_grant(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    UINT8 res = *(UINT8 *)p_data;
+    SMP_TRACE_DEBUG("%s", __func__);
+    if (res != SMP_SUCCESS) {
+        smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, p_data);
+    } else { /*otherwise, start pairing */
+        /* send IO request callback */
+        p_cb->cb_evt = SMP_IO_CAP_REQ_EVT;
+    }
+}
+
+/*******************************************************************************
+** Function     smp_proc_pair_fail
+** Description  process pairing failure from peer device
+*******************************************************************************/
+void smp_proc_pair_fail(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    SMP_TRACE_DEBUG("%s", __func__);
+    p_cb->status = *(UINT8 *)p_data;
+}
+
+/*******************************************************************************
+** Function     smp_get_auth_mode
+** Description  Get the SMP pairing auth mode
+*******************************************************************************/
+uint16_t smp_get_auth_mode (tSMP_ASSO_MODEL model)
+{
+    SMP_TRACE_DEBUG("%s model %d", __func__, model);
+    uint16_t auth = 0;
+    if (model == SMP_MODEL_ENCRYPTION_ONLY || model == SMP_MODEL_SEC_CONN_JUSTWORKS) {
+        //No MITM
+        if(model == SMP_MODEL_SEC_CONN_JUSTWORKS) {
+            //SC SMP_SC_SUPPORT_BIT
+            auth |=  SMP_SC_SUPPORT_BIT;
+        }
+    } else if (model <= SMP_MODEL_KEY_NOTIF) {
+        //NO SC, MITM
+        auth |= SMP_AUTH_YN_BIT;
+    } else if (model <= SMP_MODEL_SEC_CONN_OOB) {
+        //SC, MITM
+        auth |= SMP_SC_SUPPORT_BIT;
+        auth |= SMP_AUTH_YN_BIT;
+    } else {
+        auth = 0;
+    }
+    return auth;
+}
+
+#if (BLE_INCLUDED == TRUE)
+/*******************************************************************************
+** Function     smp_proc_pair_cmd
+** Description  Process the SMP pairing request/response from peer device
+*******************************************************************************/
+void smp_proc_pair_cmd(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    UINT8   *p = (UINT8 *)p_data;
+    UINT8   reason = SMP_ENC_KEY_SIZE;
+    tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (p_cb->pairing_bda);
+
+    SMP_TRACE_DEBUG("%s\n", __func__);
+    /* erase all keys if it is slave proc pairing req*/
+    if (p_dev_rec && (p_cb->role == HCI_ROLE_SLAVE)) {
+        btm_sec_clear_ble_keys(p_dev_rec);
+    }
+
+    p_cb->flags |= SMP_PAIR_FLAG_ENC_AFTER_PAIR;
+
+    STREAM_TO_UINT8(p_cb->peer_io_caps, p);
+    STREAM_TO_UINT8(p_cb->peer_oob_flag, p);
+    STREAM_TO_UINT8(p_cb->peer_auth_req, p);
+    STREAM_TO_UINT8(p_cb->peer_enc_size, p);
+    STREAM_TO_UINT8(p_cb->peer_i_key, p);
+    STREAM_TO_UINT8(p_cb->peer_r_key, p);
+
+    if (smp_command_has_invalid_parameters(p_cb)) {
+        reason = SMP_INVALID_PARAMETERS;
+        smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+        return;
+    }
+    p_cb->accept_specified_sec_auth = bta_dm_co_ble_get_accept_auth_enable();
+    p_cb->origin_loc_auth_req = bta_dm_co_ble_get_auth_req();
+    if (p_cb->role == HCI_ROLE_SLAVE) {
+        if (!(p_cb->flags & SMP_PAIR_FLAGS_WE_STARTED_DD)) {
+            /* peer (master) started pairing sending Pairing Request */
+            p_cb->local_i_key = p_cb->peer_i_key;
+            p_cb->local_r_key = p_cb->peer_r_key;
+
+            p_cb->cb_evt = SMP_SEC_REQUEST_EVT;
+        } else { /* update local i/r key according to pairing request */
+            /* pairing started with this side (slave) sending Security Request */
+            p_cb->local_i_key &= p_cb->peer_i_key;
+            p_cb->local_r_key &= p_cb->peer_r_key;
+            p_cb->selected_association_model = smp_select_association_model(p_cb);
+
+            if (p_cb->secure_connections_only_mode_required &&
+                    (!(p_cb->le_secure_connections_mode_is_used) ||
+                     (p_cb->selected_association_model == SMP_MODEL_SEC_CONN_JUSTWORKS))) {
+                SMP_TRACE_ERROR("%s pairing failed - slave requires secure connection only mode",
+                                __func__);
+                reason = SMP_PAIR_AUTH_FAIL;
+                smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+                return;
+            }
+            uint16_t auth = smp_get_auth_mode(p_cb->selected_association_model);
+            if(p_cb->peer_auth_req & p_cb->loc_auth_req & SMP_AUTH_GEN_BOND) {
+                auth |= SMP_AUTH_GEN_BOND;
+            }
+            p_cb->auth_mode = auth;
+            if (p_cb->accept_specified_sec_auth) {
+                if ((auth & p_cb->origin_loc_auth_req) != p_cb->origin_loc_auth_req ) {
+                    SMP_TRACE_ERROR("%s pairing failed - slave requires auth is 0x%x but peer auth is 0x%x local auth is 0x%x",
+                                    __func__, p_cb->origin_loc_auth_req, p_cb->peer_auth_req, p_cb->loc_auth_req);
+                    if (BTM_IsAclConnectionUp(p_cb->pairing_bda, BT_TRANSPORT_LE)) {
+                        btm_remove_acl (p_cb->pairing_bda, BT_TRANSPORT_LE);
+                    }
+                    reason = SMP_PAIR_AUTH_FAIL;
+                    smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+                    return;
+                }
+            }
+
+            if (p_cb->selected_association_model == SMP_MODEL_SEC_CONN_OOB) {
+                if (smp_request_oob_data(p_cb)) {
+                    return;
+                }
+            } else {
+                smp_send_pair_rsp(p_cb, NULL);
+            }
+        }
+    } else { /* Master receives pairing response */
+        p_cb->selected_association_model = smp_select_association_model(p_cb);
+
+        if (p_cb->secure_connections_only_mode_required &&
+                (!(p_cb->le_secure_connections_mode_is_used) ||
+                 (p_cb->selected_association_model == SMP_MODEL_SEC_CONN_JUSTWORKS))) {
+            SMP_TRACE_ERROR ("Master requires secure connection only mode \
+                but it can't be provided -> Master fails pairing");
+            reason = SMP_PAIR_AUTH_FAIL;
+            smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+            return;
+        }
+
+        uint16_t auth = smp_get_auth_mode(p_cb->selected_association_model);
+        if(p_cb->peer_auth_req & p_cb->loc_auth_req & SMP_AUTH_GEN_BOND) {
+            auth |= SMP_AUTH_GEN_BOND;
+        }
+        p_cb->auth_mode = auth;
+        if (p_cb->accept_specified_sec_auth) {
+            if ((auth & p_cb->origin_loc_auth_req) != p_cb->origin_loc_auth_req ) {
+                SMP_TRACE_ERROR("%s pairing failed - master requires auth is 0x%x but peer auth is 0x%x local auth is 0x%x",
+                                    __func__, p_cb->origin_loc_auth_req, p_cb->peer_auth_req, p_cb->loc_auth_req);
+                if (BTM_IsAclConnectionUp(p_cb->pairing_bda, BT_TRANSPORT_LE)) {
+                    btm_remove_acl (p_cb->pairing_bda, BT_TRANSPORT_LE);
+                }
+                reason = SMP_PAIR_AUTH_FAIL;
+                smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+                return;
+            }
+        }
+
+        if (p_cb->selected_association_model == SMP_MODEL_SEC_CONN_OOB) {
+            if (smp_request_oob_data(p_cb)) {
+                return;
+            }
+        } else {
+            smp_decide_association_model(p_cb, NULL);
+        }
+    }
+}
+#endif  ///BLE_INCLUDED == TRUE
+
+/*******************************************************************************
+** Function     smp_proc_confirm
+** Description  process pairing confirm from peer device
+*******************************************************************************/
+void smp_proc_confirm(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    UINT8 *p = (UINT8 *)p_data;
+    UINT8 reason = SMP_INVALID_PARAMETERS;
+
+    SMP_TRACE_DEBUG("%s\n", __func__);
+
+    if (smp_command_has_invalid_parameters(p_cb)) {
+        smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+        return;
+    }
+
+    if (p != NULL) {
+        /* save the SConfirm for comparison later */
+        STREAM_TO_ARRAY(p_cb->rconfirm, p, BT_OCTET16_LEN);
+    }
+
+    p_cb->flags |= SMP_PAIR_FLAGS_CMD_CONFIRM;
+}
+
+#if 0 //Unused
+/*******************************************************************************
+** Function     smp_proc_init
+** Description  process pairing initializer from peer device
+*******************************************************************************/
+void smp_proc_init(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    UINT8 *p = (UINT8 *)p_data;
+    UINT8 reason = SMP_INVALID_PARAMETERS;
+
+    SMP_TRACE_DEBUG("%s", __func__);
+
+    if (smp_command_has_invalid_parameters(p_cb)) {
+        smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+        return;
+    }
+
+    /* save the SRand for comparison */
+    STREAM_TO_ARRAY(p_cb->rrand, p, BT_OCTET16_LEN);
+}
+#endif
+
+/*******************************************************************************
+** Function     smp_proc_rand
+** Description  process pairing random (nonce) from peer device
+*******************************************************************************/
+void smp_proc_rand(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    UINT8 *p = (UINT8 *)p_data;
+    UINT8 reason = SMP_INVALID_PARAMETERS;
+
+    SMP_TRACE_DEBUG("%s\n", __func__);
+
+    if (smp_command_has_invalid_parameters(p_cb)) {
+        smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+        return;
+    }
+
+    /* save the SRand for comparison */
+    STREAM_TO_ARRAY(p_cb->rrand, p, BT_OCTET16_LEN);
+}
+
+/*******************************************************************************
+** Function     smp_process_pairing_public_key
+** Description  process pairing public key command from the peer device
+**              - saves the peer public key;
+**              - sets the flag indicating that the peer public key is received;
+**              - calls smp_wait_for_both_public_keys(...).
+**
+*******************************************************************************/
+void smp_process_pairing_public_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    UINT8 *p = (UINT8 *)p_data;
+    UINT8 reason = SMP_INVALID_PARAMETERS;
+
+    SMP_TRACE_DEBUG("%s", __func__);
+
+    if (smp_command_has_invalid_parameters(p_cb)) {
+        smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+        return;
+    }
+
+    STREAM_TO_ARRAY(p_cb->peer_publ_key.x, p, BT_OCTET32_LEN);
+    STREAM_TO_ARRAY(p_cb->peer_publ_key.y, p, BT_OCTET32_LEN);
+
+    /* Check if the peer device's and own public key are not same. If they are same then
+     * return pairing fail. This check is needed to avoid 'Impersonation in Passkey entry
+     * protocol' vulnerability (CVE-2020-26558).*/
+    if ((memcmp(p_cb->loc_publ_key.x, p_cb->peer_publ_key.x, sizeof(BT_OCTET32)) == 0) &&
+        (memcmp(p_cb->loc_publ_key.y, p_cb->peer_publ_key.y, sizeof(BT_OCTET32)) == 0)) {
+        p_cb->status = SMP_PAIR_AUTH_FAIL;
+        p_cb->failure = SMP_PAIR_AUTH_FAIL;
+        reason = SMP_PAIR_AUTH_FAIL;
+        SMP_TRACE_ERROR("%s, Peer and own device cannot have same public key.", __func__);
+        smp_sm_event(p_cb, SMP_PAIRING_FAILED_EVT, &reason);
+        return ;
+    }
+    /* In order to prevent the x and y coordinates of the public key from being modified,
+       we need to check whether the x and y coordinates are on the given elliptic curve. */
+    if (!ECC_CheckPointIsInElliCur_P256((Point *)&p_cb->peer_publ_key)) {
+        SMP_TRACE_ERROR("%s, Invalid Public key.", __func__);
+        smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+    }
+    p_cb->flags |= SMP_PAIR_FLAG_HAVE_PEER_PUBL_KEY;
+
+    smp_wait_for_both_public_keys(p_cb, NULL);
+}
+
+/*******************************************************************************
+** Function     smp_process_pairing_commitment
+** Description  process pairing commitment from peer device
+*******************************************************************************/
+void smp_process_pairing_commitment(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    UINT8 *p = (UINT8 *)p_data;
+    UINT8 reason = SMP_INVALID_PARAMETERS;
+
+    SMP_TRACE_DEBUG("%s", __func__);
+
+    if (smp_command_has_invalid_parameters(p_cb)) {
+        smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+        return;
+    }
+
+    p_cb->flags |= SMP_PAIR_FLAG_HAVE_PEER_COMM;
+
+    if (p != NULL) {
+        STREAM_TO_ARRAY(p_cb->remote_commitment, p, BT_OCTET16_LEN);
+    }
+}
+
+/*******************************************************************************
+** Function     smp_process_dhkey_check
+** Description  process DHKey Check from peer device
+*******************************************************************************/
+void smp_process_dhkey_check(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    UINT8 *p = (UINT8 *)p_data;
+    UINT8 reason = SMP_INVALID_PARAMETERS;
+
+    SMP_TRACE_DEBUG("%s", __func__);
+
+    if (smp_command_has_invalid_parameters(p_cb)) {
+        smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+        return;
+    }
+
+    if (p != NULL) {
+        STREAM_TO_ARRAY(p_cb->remote_dhkey_check, p, BT_OCTET16_LEN);
+    }
+
+    p_cb->flags |= SMP_PAIR_FLAG_HAVE_PEER_DHK_CHK;
+}
+
+/*******************************************************************************
+** Function     smp_process_keypress_notification
+** Description  process pairing keypress notification from peer device
+*******************************************************************************/
+void smp_process_keypress_notification(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    UINT8 *p = (UINT8 *)p_data;
+    UINT8 reason = SMP_INVALID_PARAMETERS;
+
+    SMP_TRACE_DEBUG("%s", __func__);
+    p_cb->status = *(UINT8 *)p_data;
+
+    if (smp_command_has_invalid_parameters(p_cb)) {
+        smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+        return;
+    }
+
+    if (p != NULL) {
+        STREAM_TO_UINT8(p_cb->peer_keypress_notification, p);
+    } else {
+        p_cb->peer_keypress_notification = BTM_SP_KEY_OUT_OF_RANGE;
+    }
+    p_cb->cb_evt = SMP_PEER_KEYPR_NOT_EVT;
+}
+
+#if (CLASSIC_BT_INCLUDED == TRUE)
+/*******************************************************************************
+** Function     smp_br_process_pairing_command
+** Description  Process the SMP pairing request/response from peer device via
+**              BR/EDR transport.
+*******************************************************************************/
+void smp_br_process_pairing_command(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    UINT8   *p = (UINT8 *)p_data;
+    UINT8   reason = SMP_ENC_KEY_SIZE;
+    tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (p_cb->pairing_bda);
+
+    SMP_TRACE_DEBUG("%s", __func__);
+    /* rejecting BR pairing request over non-SC BR link */
+    if (!p_dev_rec->new_encryption_key_is_p256 && p_cb->role == HCI_ROLE_SLAVE) {
+        reason = SMP_XTRANS_DERIVE_NOT_ALLOW;
+        smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &reason);
+        return;
+    }
+
+#if (BLE_INCLUDED == TRUE)
+    /* erase all keys if it is slave proc pairing req*/
+    if (p_dev_rec && (p_cb->role == HCI_ROLE_SLAVE)) {
+        btm_sec_clear_ble_keys(p_dev_rec);
+    }
+#endif  ///BLE_INCLUDED == TRUE
+
+    p_cb->flags |= SMP_PAIR_FLAG_ENC_AFTER_PAIR;
+
+    STREAM_TO_UINT8(p_cb->peer_io_caps, p);
+    STREAM_TO_UINT8(p_cb->peer_oob_flag, p);
+    STREAM_TO_UINT8(p_cb->peer_auth_req, p);
+    STREAM_TO_UINT8(p_cb->peer_enc_size, p);
+    STREAM_TO_UINT8(p_cb->peer_i_key, p);
+    STREAM_TO_UINT8(p_cb->peer_r_key, p);
+
+    if (smp_command_has_invalid_parameters(p_cb)) {
+        reason = SMP_INVALID_PARAMETERS;
+        smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &reason);
+        return;
+    }
+
+    /* peer (master) started pairing sending Pairing Request */
+    /* or being master device always use received i/r key as keys to distribute */
+    p_cb->local_i_key = p_cb->peer_i_key;
+    p_cb->local_r_key = p_cb->peer_r_key;
+
+    if (p_cb->role == HCI_ROLE_SLAVE) {
+        p_dev_rec->new_encryption_key_is_p256 = FALSE;
+        /* shortcut to skip Security Grant step */
+        p_cb->cb_evt = SMP_BR_KEYS_REQ_EVT;
+    } else { /* Master receives pairing response */
+        SMP_TRACE_DEBUG("%s master rcvs valid PAIRING RESPONSE."
+                        " Supposed to move to key distribution phase. ", __func__);
+    }
+
+    /* auth_req received via BR/EDR SM channel is set to 0,
+       but everything derived/exchanged has to be saved */
+    p_cb->peer_auth_req |= SMP_AUTH_BOND;
+    p_cb->loc_auth_req |= SMP_AUTH_BOND;
+}
+
+/*******************************************************************************
+** Function     smp_br_process_security_grant
+** Description  process security grant in case of pairing over BR/EDR transport.
+*******************************************************************************/
+void smp_br_process_security_grant(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    UINT8 res = *(UINT8 *)p_data;
+    SMP_TRACE_DEBUG("%s", __func__);
+    if (res != SMP_SUCCESS) {
+        smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, p_data);
+    } else { /*otherwise, start pairing */
+        /* send IO request callback */
+        p_cb->cb_evt = SMP_BR_KEYS_REQ_EVT;
+    }
+}
+
+/*******************************************************************************
+** Function     smp_br_check_authorization_request
+** Description  sets the SMP kes to be derived/distribute over BR/EDR transport
+**              before starting the distribution/derivation
+*******************************************************************************/
+void smp_br_check_authorization_request(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    UINT8 reason = SMP_SUCCESS;
+
+    SMP_TRACE_DEBUG("%s rcvs i_keys=0x%x r_keys=0x%x "
+                    "(i-initiator r-responder)", __FUNCTION__, p_cb->local_i_key,
+                    p_cb->local_r_key);
+
+    /* In LE SC mode LK field is ignored when BR/EDR transport is used */
+    p_cb->local_i_key &= ~SMP_SEC_KEY_TYPE_LK;
+    p_cb->local_r_key &= ~SMP_SEC_KEY_TYPE_LK;
+
+    /* In LE SC mode only IRK, IAI, CSRK are exchanged with the peer.
+    ** Set local_r_key on master to expect only these keys. */
+    if (p_cb->role == HCI_ROLE_MASTER) {
+        p_cb->local_r_key &= (SMP_SEC_KEY_TYPE_ID | SMP_SEC_KEY_TYPE_CSRK);
+    }
+
+    SMP_TRACE_DEBUG("%s rcvs upgrades: i_keys=0x%x r_keys=0x%x "
+                    "(i-initiator r-responder)", __FUNCTION__, p_cb->local_i_key,
+                    p_cb->local_r_key);
+
+    if (/*((p_cb->peer_auth_req & SMP_AUTH_BOND) ||
+            (p_cb->loc_auth_req & SMP_AUTH_BOND)) &&*/
+        (p_cb->local_i_key || p_cb->local_r_key)) {
+        smp_br_state_machine_event(p_cb, SMP_BR_BOND_REQ_EVT, NULL);
+
+        /* if no peer key is expected, start master key distribution */
+        if (p_cb->role == HCI_ROLE_MASTER && p_cb->local_r_key == 0) {
+            smp_key_distribution_by_transport(p_cb, NULL);
+        }
+    } else {
+        smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &reason);
+    }
+}
+
+/*******************************************************************************
+** Function     smp_br_select_next_key
+** Description  selects the next key to derive/send when BR/EDR transport is
+**              used.
+*******************************************************************************/
+void smp_br_select_next_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    UINT8   reason = SMP_SUCCESS;
+    SMP_TRACE_DEBUG("%s role=%d (0-master) r_keys=0x%x i_keys=0x%x",
+                    __func__, p_cb->role, p_cb->local_r_key, p_cb->local_i_key);
+
+    if (p_cb->role == HCI_ROLE_SLAVE ||
+            (!p_cb->local_r_key && p_cb->role == HCI_ROLE_MASTER)) {
+        smp_key_pick_key(p_cb, p_data);
+    }
+
+    if (!p_cb->local_i_key && !p_cb->local_r_key) {
+        /* state check to prevent re-entrance */
+        if (smp_get_br_state() == SMP_BR_STATE_BOND_PENDING) {
+            if (p_cb->total_tx_unacked == 0) {
+                smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &reason);
+            } else {
+                p_cb->wait_for_authorization_complete = TRUE;
+            }
+        }
+    }
+}
+#endif  ///CLASSIC_BT_INCLUDED == TRUE
+
+#if (BLE_INCLUDED == TRUE)
+/*******************************************************************************
+** Function     smp_proc_enc_info
+** Description  process encryption information from peer device
+*******************************************************************************/
+void smp_proc_enc_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    UINT8   *p = (UINT8 *)p_data;
+
+    SMP_TRACE_DEBUG("%s\n", __func__);
+    STREAM_TO_ARRAY(p_cb->ltk, p, BT_OCTET16_LEN);
+
+    smp_key_distribution(p_cb, NULL);
+}
+#endif  ///BLE_INCLUDED == TRUE
+
+/*******************************************************************************
+** Function     smp_proc_master_id
+** Description  process master ID from slave device
+*******************************************************************************/
+void smp_proc_master_id(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    UINT8   *p = (UINT8 *)p_data;
+    tBTM_LE_PENC_KEYS   le_key;
+
+    SMP_TRACE_DEBUG("%s\np_cb->peer_auth_req = %d,p_cb->loc_auth_req= %d\n", __func__,
+                    p_cb->peer_auth_req, p_cb->loc_auth_req);
+    smp_update_key_mask (p_cb, SMP_SEC_KEY_TYPE_ENC, TRUE);
+
+    STREAM_TO_UINT16(le_key.ediv, p);
+    STREAM_TO_ARRAY(le_key.rand, p, BT_OCTET8_LEN );
+
+    /* store the encryption keys from peer device */
+    memcpy(le_key.ltk, p_cb->ltk, BT_OCTET16_LEN);
+    le_key.sec_level = p_cb->sec_level;
+    le_key.key_size  = p_cb->loc_enc_size;
+
+#if (BLE_INCLUDED == TRUE)
+    if ((p_cb->peer_auth_req & SMP_AUTH_BOND) && (p_cb->loc_auth_req & SMP_AUTH_BOND)) {
+        btm_sec_save_le_key(p_cb->pairing_bda,
+                            BTM_LE_KEY_PENC,
+                            (tBTM_LE_KEY_VALUE *)&le_key, TRUE);
+    }
+
+    smp_key_distribution(p_cb, NULL);
+#endif  ///BLE_INCLUDED == TRUE
+}
+
+/*******************************************************************************
+** Function     smp_proc_enc_info
+** Description  process identity information from peer device
+*******************************************************************************/
+void smp_proc_id_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    UINT8   *p = (UINT8 *)p_data;
+
+    SMP_TRACE_DEBUG("%s", __func__);
+    STREAM_TO_ARRAY (p_cb->tk, p, BT_OCTET16_LEN);   /* reuse TK for IRK */
+    smp_key_distribution_by_transport(p_cb, NULL);
+}
+
+/*******************************************************************************
+** Function     smp_proc_id_addr
+** Description  process identity address from peer device
+*******************************************************************************/
+void smp_proc_id_addr(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    UINT8   *p = (UINT8 *)p_data;
+    tBTM_LE_PID_KEYS    pid_key;
+
+    SMP_TRACE_DEBUG("%s", __func__);
+    smp_update_key_mask (p_cb, SMP_SEC_KEY_TYPE_ID, TRUE);
+
+    STREAM_TO_UINT8(pid_key.addr_type, p);
+    STREAM_TO_BDADDR(pid_key.static_addr, p);
+    memcpy(pid_key.irk, p_cb->tk, BT_OCTET16_LEN);
+
+    /* to use as BD_ADDR for lk derived from ltk */
+    p_cb->id_addr_rcvd = TRUE;
+    p_cb->id_addr_type = pid_key.addr_type;
+    memcpy(p_cb->id_addr, pid_key.static_addr, BD_ADDR_LEN);
+
+#if (BLE_INCLUDED == TRUE)
+    /* store the ID key from peer device */
+    if ((p_cb->peer_auth_req & SMP_AUTH_BOND) && (p_cb->loc_auth_req & SMP_AUTH_BOND)) {
+        btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_PID,
+                            (tBTM_LE_KEY_VALUE *)&pid_key, TRUE);
+    }
+#endif  ///BLE_INCLUDED == TRUE
+
+    smp_key_distribution_by_transport(p_cb, NULL);
+}
+
+/*******************************************************************************
+** Function     smp_proc_srk_info
+** Description  process security information from peer device
+*******************************************************************************/
+void smp_proc_srk_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+#if (BLE_INCLUDED == TRUE)
+    tBTM_LE_PCSRK_KEYS   le_key;
+
+    SMP_TRACE_DEBUG("%s", __func__);
+    smp_update_key_mask (p_cb, SMP_SEC_KEY_TYPE_CSRK, TRUE);
+
+    /* save CSRK to security record */
+    le_key.sec_level = p_cb->sec_level;
+    memcpy (le_key.csrk, p_data, BT_OCTET16_LEN);   /* get peer CSRK */
+    le_key.counter = 0; /* initialize the peer counter */
+
+    if ((p_cb->peer_auth_req & SMP_AUTH_BOND) && (p_cb->loc_auth_req & SMP_AUTH_BOND)) {
+        btm_sec_save_le_key(p_cb->pairing_bda,
+                            BTM_LE_KEY_PCSRK,
+                            (tBTM_LE_KEY_VALUE *)&le_key, TRUE);
+    }
+
+#endif  ///BLE_INCLUDED == TRUE
+    smp_key_distribution_by_transport(p_cb, NULL);
+}
+
+/*******************************************************************************
+** Function     smp_proc_compare
+** Description  process compare value
+*******************************************************************************/
+void smp_proc_compare(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    UINT8   reason;
+
+    SMP_TRACE_DEBUG("%s\n", __func__);
+    if (!memcmp(p_cb->rconfirm, p_data->key.p_data, BT_OCTET16_LEN)) {
+        /* compare the max encryption key size, and save the smaller one for the link */
+        if ( p_cb->peer_enc_size < p_cb->loc_enc_size) {
+            p_cb->loc_enc_size = p_cb->peer_enc_size;
+        }
+
+        if (p_cb->role == HCI_ROLE_SLAVE) {
+            smp_sm_event(p_cb, SMP_RAND_EVT, NULL);
+        } else {
+            /* master device always use received i/r key as keys to distribute */
+            p_cb->local_i_key = p_cb->peer_i_key;
+            p_cb->local_r_key = p_cb->peer_r_key;
+
+            smp_sm_event(p_cb, SMP_ENC_REQ_EVT, NULL);
+        }
+
+    } else {
+        reason = p_cb->failure = SMP_CONFIRM_VALUE_ERR;
+        smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+    }
+}
+
+#if (BLE_INCLUDED == TRUE)
+/*******************************************************************************
+** Function     smp_proc_sl_key
+** Description  process key ready events.
+*******************************************************************************/
+void smp_proc_sl_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    UINT8 key_type = p_data->key.key_type;
+
+    SMP_TRACE_DEBUG("%s\n", __func__);
+    if (key_type == SMP_KEY_TYPE_TK) {
+        smp_generate_srand_mrand_confirm(p_cb, NULL);
+    } else if (key_type == SMP_KEY_TYPE_CFM) {
+        smp_set_state(SMP_STATE_WAIT_CONFIRM);
+
+        if (p_cb->flags & SMP_PAIR_FLAGS_CMD_CONFIRM) {
+            smp_sm_event(p_cb, SMP_CONFIRM_EVT, NULL);
+        }
+    }
+}
+
+/*******************************************************************************
+** Function     smp_start_enc
+** Description  start encryption
+*******************************************************************************/
+void smp_start_enc(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    tBTM_STATUS cmd;
+    UINT8 reason = SMP_ENC_FAIL;
+
+    SMP_TRACE_DEBUG("%s\n", __func__);
+    if (p_data != NULL) {
+        cmd = btm_ble_start_encrypt(p_cb->pairing_bda, TRUE, p_data->key.p_data);
+    } else {
+        cmd = btm_ble_start_encrypt(p_cb->pairing_bda, FALSE, NULL);
+    }
+
+    if (cmd != BTM_CMD_STARTED && cmd != BTM_BUSY) {
+        smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+    }
+}
+#endif  ///BLE_INCLUDED == TRUE
+
+/*******************************************************************************
+** Function     smp_proc_discard
+** Description   processing for discard security request
+*******************************************************************************/
+void smp_proc_discard(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    SMP_TRACE_DEBUG("%s\n", __func__);
+    if (!(p_cb->flags & SMP_PAIR_FLAGS_WE_STARTED_DD)) {
+        smp_reset_control_value(p_cb);
+    }
+}
+
+/*******************************************************************************
+** Function     smp_enc_cmpl
+** Description   encryption success
+*******************************************************************************/
+void smp_enc_cmpl(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    UINT8 enc_enable = *(UINT8 *)p_data;
+    UINT8 reason = enc_enable ? SMP_SUCCESS : SMP_ENC_FAIL;
+
+    SMP_TRACE_DEBUG("%s\n", __func__);
+    smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+}
+
+/*******************************************************************************
+** Function     smp_check_auth_req
+** Description  check authentication request
+*******************************************************************************/
+void smp_check_auth_req(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    UINT8 enc_enable = *(UINT8 *)p_data;
+    UINT8 reason = enc_enable ? SMP_SUCCESS : SMP_ENC_FAIL;
+
+    SMP_TRACE_DEBUG("%s rcvs enc_enable=%d i_keys=0x%x r_keys=0x%x "
+                    "(i-initiator r-responder)\n",
+                    __func__, enc_enable, p_cb->local_i_key, p_cb->local_r_key);
+    if (enc_enable == 1) {
+        if (p_cb->le_secure_connections_mode_is_used) {
+            /* In LE SC mode LTK is used instead of STK and has to be always saved */
+            p_cb->local_i_key |= SMP_SEC_KEY_TYPE_ENC;
+            p_cb->local_r_key |= SMP_SEC_KEY_TYPE_ENC;
+
+            /* In LE SC mode LK is derived from LTK only if both sides request it */
+            if (!(p_cb->local_i_key & SMP_SEC_KEY_TYPE_LK) ||
+                    !(p_cb->local_r_key & SMP_SEC_KEY_TYPE_LK)) {
+                p_cb->local_i_key &= ~SMP_SEC_KEY_TYPE_LK;
+                p_cb->local_r_key &= ~SMP_SEC_KEY_TYPE_LK;
+            }
+
+            /* In LE SC mode only IRK, IAI, CSRK are exchanged with the peer.
+            ** Set local_r_key on master to expect only these keys.
+            */
+            if (p_cb->role == HCI_ROLE_MASTER) {
+                p_cb->local_r_key &= (SMP_SEC_KEY_TYPE_ID | SMP_SEC_KEY_TYPE_CSRK);
+            }
+        } else {
+            /* in legacy mode derivation of BR/EDR LK is not supported */
+            p_cb->local_i_key &= ~SMP_SEC_KEY_TYPE_LK;
+            p_cb->local_r_key &= ~SMP_SEC_KEY_TYPE_LK;
+        }
+        SMP_TRACE_DEBUG("%s rcvs upgrades: i_keys=0x%x r_keys=0x%x "
+                        "(i-initiator r-responder)\n",
+                        __func__, p_cb->local_i_key, p_cb->local_r_key);
+
+        if (/*((p_cb->peer_auth_req & SMP_AUTH_BOND) ||
+             (p_cb->loc_auth_req & SMP_AUTH_BOND)) &&*/
+            (p_cb->local_i_key || p_cb->local_r_key)) {
+            smp_sm_event(p_cb, SMP_BOND_REQ_EVT, NULL);
+        } else {
+            smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+        }
+    } else if (enc_enable == 0) {
+        /* if failed for encryption after pairing, send callback */
+        if (p_cb->flags & SMP_PAIR_FLAG_ENC_AFTER_PAIR) {
+            smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+        }
+        /* if enc failed for old security information */
+        /* if master device, clean up and abck to idle; slave device do nothing */
+        else if (p_cb->role == HCI_ROLE_MASTER) {
+            smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+        }
+    }
+}
+
+/*******************************************************************************
+** Function     smp_key_pick_key
+** Description  Pick a key distribution function based on the key mask.
+*******************************************************************************/
+void smp_key_pick_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    UINT8   key_to_dist = (p_cb->role == HCI_ROLE_SLAVE) ? p_cb->local_r_key : p_cb->local_i_key;
+    UINT8   i = 0;
+
+    SMP_TRACE_DEBUG("%s key_to_dist=0x%x\n", __func__, key_to_dist);
+    while (i < SMP_KEY_DIST_TYPE_MAX) {
+        SMP_TRACE_DEBUG("key to send = %02x, i = %d\n",  key_to_dist, i);
+
+        if (key_to_dist & (1 << i) && smp_distribute_act[i] != NULL) {
+            SMP_TRACE_DEBUG("smp_distribute_act[%d]\n", i);
+            (* smp_distribute_act[i])(p_cb, p_data);
+            break;
+        }
+        i ++;
+    }
+}
+
+#if (BLE_INCLUDED == TRUE)
+/*******************************************************************************
+** Function     smp_key_distribution
+** Description  start key distribution if required.
+*******************************************************************************/
+void smp_key_distribution(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    UINT8   reason = SMP_SUCCESS;
+    SMP_TRACE_DEBUG("\n%s role=%d (0-master) r_keys=0x%x i_keys=0x%x\n",
+                    __func__, p_cb->role, p_cb->local_r_key, p_cb->local_i_key);
+
+    if (p_cb->role == HCI_ROLE_SLAVE ||
+            (!p_cb->local_r_key && p_cb->role == HCI_ROLE_MASTER)) {
+        smp_key_pick_key(p_cb, p_data);
+    }
+
+    if (!p_cb->local_i_key && !p_cb->local_r_key) {
+        /* state check to prevent re-entrant */
+        if (smp_get_state() == SMP_STATE_BOND_PENDING) {
+            if (p_cb->derive_lk) {
+                smp_derive_link_key_from_long_term_key(p_cb, NULL);
+                p_cb->derive_lk = FALSE;
+            }
+
+            if (p_cb->total_tx_unacked == 0) {
+                smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+            } else {
+                p_cb->wait_for_authorization_complete = TRUE;
+            }
+        }
+    }
+}
+
+/*******************************************************************************
+** Function         smp_decide_association_model
+** Description      This function is called to select assoc model to be used for
+**                  STK generation and to start STK generation process.
+**
+*******************************************************************************/
+void smp_decide_association_model(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    UINT8   failure = SMP_UNKNOWN_IO_CAP;
+    UINT8 int_evt = 0;
+    tSMP_KEY key;
+    tSMP_INT_DATA   *p = NULL;
+
+    SMP_TRACE_DEBUG("%s Association Model = %d\n", __func__, p_cb->selected_association_model);
+
+    switch (p_cb->selected_association_model) {
+    case SMP_MODEL_ENCRYPTION_ONLY:  /* TK = 0, go calculate Confirm */
+        p_cb->sec_level = SMP_SEC_UNAUTHENTICATE;
+        SMP_TRACE_EVENT ("p_cb->sec_level =%d (SMP_SEC_UNAUTHENTICATE) \n", p_cb->sec_level );
+
+        key.key_type = SMP_KEY_TYPE_TK;
+        key.p_data = p_cb->tk;
+        p = (tSMP_INT_DATA *)&key;
+
+        memset(p_cb->tk, 0, BT_OCTET16_LEN);
+        /* TK, ready  */
+        int_evt = SMP_KEY_READY_EVT;
+        break;
+
+    case SMP_MODEL_PASSKEY:
+        p_cb->sec_level = SMP_SEC_AUTHENTICATED;
+        SMP_TRACE_EVENT ("p_cb->sec_level =%d (SMP_SEC_AUTHENTICATED) \n", p_cb->sec_level );
+
+        p_cb->cb_evt = SMP_PASSKEY_REQ_EVT;
+        int_evt = SMP_TK_REQ_EVT;
+        break;
+
+    case SMP_MODEL_OOB:
+        SMP_TRACE_ERROR ("Association Model = SMP_MODEL_OOB\n");
+        p_cb->sec_level = SMP_SEC_AUTHENTICATED;
+        SMP_TRACE_EVENT ("p_cb->sec_level =%d (SMP_SEC_AUTHENTICATED) \n", p_cb->sec_level );
+
+        p_cb->cb_evt = SMP_OOB_REQ_EVT;
+        int_evt = SMP_TK_REQ_EVT;
+        break;
+
+    case SMP_MODEL_KEY_NOTIF:
+        p_cb->sec_level = SMP_SEC_AUTHENTICATED;
+        SMP_TRACE_DEBUG("Need to generate Passkey\n");
+
+        /* generate passkey and notify application */
+        smp_generate_passkey(p_cb, NULL);
+        break;
+
+    case SMP_MODEL_SEC_CONN_JUSTWORKS:
+    case SMP_MODEL_SEC_CONN_NUM_COMP:
+    case SMP_MODEL_SEC_CONN_PASSKEY_ENT:
+    case SMP_MODEL_SEC_CONN_PASSKEY_DISP:
+    case SMP_MODEL_SEC_CONN_OOB:
+        int_evt = SMP_PUBL_KEY_EXCH_REQ_EVT;
+        break;
+
+    case SMP_MODEL_OUT_OF_RANGE:
+        SMP_TRACE_ERROR("Association Model = SMP_MODEL_OUT_OF_RANGE (failed)\n");
+        p = (tSMP_INT_DATA *)&failure;
+        int_evt = SMP_AUTH_CMPL_EVT;
+        break;
+
+    default:
+        SMP_TRACE_ERROR("Association Model = %d (SOMETHING IS WRONG WITH THE CODE)\n",
+                        p_cb->selected_association_model);
+        p = (tSMP_INT_DATA *)&failure;
+        int_evt = SMP_AUTH_CMPL_EVT;
+    }
+
+    SMP_TRACE_EVENT ("sec_level=%d \n", p_cb->sec_level );
+    if (int_evt) {
+        smp_sm_event(p_cb, int_evt, p);
+    }
+}
+
+/*******************************************************************************
+** Function     smp_process_io_response
+** Description  process IO response for a slave device.
+*******************************************************************************/
+void smp_process_io_response(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    uint8_t reason = SMP_PAIR_AUTH_FAIL;
+    SMP_TRACE_DEBUG("%s\n", __func__);
+    if (p_cb->flags & SMP_PAIR_FLAGS_WE_STARTED_DD) {
+        /* pairing started by local (slave) Security Request */
+        smp_set_state(SMP_STATE_SEC_REQ_PENDING);
+        smp_send_cmd(SMP_OPCODE_SEC_REQ, p_cb);
+    } else { /* plan to send pairing respond */
+        /* pairing started by peer (master) Pairing Request */
+        p_cb->selected_association_model = smp_select_association_model(p_cb);
+
+        if (p_cb->secure_connections_only_mode_required &&
+                (!(p_cb->le_secure_connections_mode_is_used) ||
+                 (p_cb->selected_association_model == SMP_MODEL_SEC_CONN_JUSTWORKS))) {
+            SMP_TRACE_ERROR ("Slave requires secure connection only mode \
+                              but it can't be provided -> Slave fails pairing\n");
+            smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+            return;
+        }
+        uint16_t auth = smp_get_auth_mode(p_cb->selected_association_model);
+        if(p_cb->peer_auth_req & p_cb->loc_auth_req & SMP_AUTH_GEN_BOND) {
+            auth |= SMP_AUTH_GEN_BOND;
+        }
+        p_cb->auth_mode = auth;
+        if (p_cb->accept_specified_sec_auth) {
+            if ((auth & p_cb->origin_loc_auth_req) != p_cb->origin_loc_auth_req ) {
+                SMP_TRACE_ERROR("pairing failed - slave requires auth is 0x%x but peer auth is 0x%x local auth is 0x%x",
+                                    p_cb->origin_loc_auth_req, p_cb->peer_auth_req, p_cb->loc_auth_req);
+                if (BTM_IsAclConnectionUp(p_cb->pairing_bda, BT_TRANSPORT_LE)) {
+                    btm_remove_acl (p_cb->pairing_bda, BT_TRANSPORT_LE);
+                }
+                reason = SMP_PAIR_AUTH_FAIL;
+                smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+                return;
+            }
+        }
+
+        if (p_cb->selected_association_model == SMP_MODEL_SEC_CONN_OOB) {
+            if (smp_request_oob_data(p_cb)) {
+                return;
+            }
+        }
+        smp_send_pair_rsp(p_cb, NULL);
+    }
+}
+#endif  ///BLE_INCLUDED == TRUE
+
+/*******************************************************************************
+** Function     smp_br_process_slave_keys_response
+** Description  process application keys response for a slave device
+**              (BR/EDR transport).
+*******************************************************************************/
+void smp_br_process_slave_keys_response(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    smp_br_send_pair_response(p_cb, NULL);
+}
+
+/*******************************************************************************
+** Function     smp_br_send_pair_response
+** Description  actions related to sending pairing response over BR/EDR transport.
+*******************************************************************************/
+void smp_br_send_pair_response(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    SMP_TRACE_DEBUG("%s\n", __func__);
+
+    p_cb->local_i_key &= p_cb->peer_i_key;
+    p_cb->local_r_key &= p_cb->peer_r_key;
+
+    smp_send_cmd (SMP_OPCODE_PAIRING_RSP, p_cb);
+}
+
+/*******************************************************************************
+** Function         smp_pairing_cmpl
+** Description      This function is called to send the pairing complete callback
+**                  and remove the connection if needed.
+*******************************************************************************/
+void smp_pairing_cmpl(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    if (p_cb->total_tx_unacked == 0) {
+        /* process the pairing complete */
+        smp_proc_pairing_cmpl(p_cb);
+    }
+}
+
+/*******************************************************************************
+** Function         smp_pair_terminate
+** Description      This function is called to send the pairing complete callback
+**                  and remove the connection if needed.
+*******************************************************************************/
+void smp_pair_terminate(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    SMP_TRACE_DEBUG("%s\n", __func__);
+    p_cb->status = SMP_CONN_TOUT;
+    smp_proc_pairing_cmpl(p_cb);
+}
+
+/*******************************************************************************
+** Function         smp_idle_terminate
+** Description      This function calledin idle state to determine to send authentication
+**                  complete or not.
+*******************************************************************************/
+void smp_idle_terminate(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    if (p_cb->flags & SMP_PAIR_FLAGS_WE_STARTED_DD) {
+        SMP_TRACE_DEBUG("Pairing terminated at IDLE state.\n");
+        p_cb->status = SMP_FAIL;
+        smp_proc_pairing_cmpl(p_cb);
+    }
+}
+
+#if (BLE_INCLUDED == TRUE)
+/*******************************************************************************
+** Function     smp_fast_conn_param
+** Description  apply default connection parameter for pairing process
+*******************************************************************************/
+void smp_fast_conn_param(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    if(p_cb->role == BTM_ROLE_MASTER) {
+        L2CA_EnableUpdateBleConnParams(p_cb->pairing_bda, FALSE);
+    }
+#if (SMP_SLAVE_CON_PARAMS_UPD_ENABLE == TRUE)
+    else {
+        tBTM_SEC_DEV_REC    *p_rec = btm_find_dev (p_cb->pairing_bda);
+        if(p_rec && p_rec->ble.skip_update_conn_param) {
+            //do nothing
+            return;
+        }
+        /* Disable L2CAP connection parameter updates while bonding since
+        some peripherals are not able to revert to fast connection parameters
+        during the start of service discovery. Connection paramter updates
+        get enabled again once service discovery completes. */
+        L2CA_EnableUpdateBleConnParams(p_cb->pairing_bda, FALSE);
+    }
+#endif
+}
+
+/*******************************************************************************
+** Function     smp_both_have_public_keys
+** Description  The function is called when both local and peer public keys are
+**              saved.
+**              Actions:
+**              - invokes DHKey computation;
+**              - on slave side invokes sending local public key to the peer.
+**              - invokes SC phase 1 process.
+*******************************************************************************/
+void smp_both_have_public_keys(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    SMP_TRACE_DEBUG("%s\n", __func__);
+
+    /* invokes DHKey computation */
+    smp_compute_dhkey(p_cb);
+
+    /* on slave side invokes sending local public key to the peer */
+    if (p_cb->role == HCI_ROLE_SLAVE) {
+        smp_send_pair_public_key(p_cb, NULL);
+    }
+
+    smp_sm_event(p_cb, SMP_SC_DHKEY_CMPLT_EVT, NULL);
+}
+
+/*******************************************************************************
+** Function     smp_start_secure_connection_phase1
+** Description  The function starts Secure Connection phase1 i.e. invokes initialization of Secure Connection
+**              phase 1 parameters and starts building/sending to the peer
+**              messages appropriate for the role and association model.
+*******************************************************************************/
+void smp_start_secure_connection_phase1(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    SMP_TRACE_DEBUG("%s\n", __func__);
+
+    if (p_cb->selected_association_model == SMP_MODEL_SEC_CONN_JUSTWORKS) {
+        p_cb->sec_level = SMP_SEC_UNAUTHENTICATE;
+        SMP_TRACE_EVENT ("p_cb->sec_level =%d (SMP_SEC_UNAUTHENTICATE)\n ", p_cb->sec_level );
+    } else {
+        p_cb->sec_level = SMP_SEC_AUTHENTICATED;
+        SMP_TRACE_EVENT ("p_cb->sec_level =%d (SMP_SEC_AUTHENTICATED)\n ", p_cb->sec_level );
+    }
+
+    switch (p_cb->selected_association_model) {
+    case SMP_MODEL_SEC_CONN_JUSTWORKS:
+    case SMP_MODEL_SEC_CONN_NUM_COMP:
+        memset(p_cb->local_random, 0, BT_OCTET16_LEN);
+        smp_start_nonce_generation(p_cb);
+        break;
+    case SMP_MODEL_SEC_CONN_PASSKEY_ENT:
+        /* user has to provide passkey */
+        p_cb->cb_evt = SMP_PASSKEY_REQ_EVT;
+        smp_sm_event(p_cb, SMP_TK_REQ_EVT, NULL);
+        break;
+    case SMP_MODEL_SEC_CONN_PASSKEY_DISP:
+        /* passkey has to be provided to user */
+        SMP_TRACE_DEBUG("Need to generate SC Passkey\n");
+        smp_generate_passkey(p_cb, NULL);
+        break;
+    case SMP_MODEL_SEC_CONN_OOB:
+        /* use the available OOB information */
+        smp_process_secure_connection_oob_data(p_cb, NULL);
+        break;
+    default:
+        SMP_TRACE_ERROR ("Association Model = %d is not used in LE SC\n",
+                         p_cb->selected_association_model);
+        break;
+    }
+}
+
+/*******************************************************************************
+** Function     smp_process_local_nonce
+** Description  The function processes new local nonce.
+**
+** Note         It is supposed to be called in SC phase1.
+*******************************************************************************/
+void smp_process_local_nonce(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    SMP_TRACE_DEBUG("%s\n", __func__);
+
+    switch (p_cb->selected_association_model) {
+    case SMP_MODEL_SEC_CONN_JUSTWORKS:
+    case SMP_MODEL_SEC_CONN_NUM_COMP:
+        if (p_cb->role == HCI_ROLE_SLAVE) {
+            /* slave calculates and sends local commitment */
+            smp_calculate_local_commitment(p_cb);
+            smp_send_commitment(p_cb, NULL);
+            /* slave has to wait for peer nonce */
+            smp_set_state(SMP_STATE_WAIT_NONCE);
+        } else { /* i.e. master */
+            if (p_cb->flags & SMP_PAIR_FLAG_HAVE_PEER_COMM) {
+                /* slave commitment is already received, send local nonce, wait for remote nonce*/
+                SMP_TRACE_DEBUG("master in assoc mode = %d \
+                    already rcvd slave commitment - race condition\n",
+                                p_cb->selected_association_model);
+                p_cb->flags &= ~SMP_PAIR_FLAG_HAVE_PEER_COMM;
+                smp_send_rand(p_cb, NULL);
+                smp_set_state(SMP_STATE_WAIT_NONCE);
+            }
+        }
+        break;
+    case SMP_MODEL_SEC_CONN_PASSKEY_ENT:
+    case SMP_MODEL_SEC_CONN_PASSKEY_DISP:
+        smp_calculate_local_commitment(p_cb);
+
+        if (p_cb->role == HCI_ROLE_MASTER) {
+            smp_send_commitment(p_cb, NULL);
+        } else { /* slave */
+            if (p_cb->flags & SMP_PAIR_FLAG_HAVE_PEER_COMM) {
+                /* master commitment is already received */
+                smp_send_commitment(p_cb, NULL);
+                smp_set_state(SMP_STATE_WAIT_NONCE);
+            }
+        }
+        break;
+    case SMP_MODEL_SEC_CONN_OOB:
+        if (p_cb->role == HCI_ROLE_MASTER) {
+            smp_send_rand(p_cb, NULL);
+        }
+
+        smp_set_state(SMP_STATE_WAIT_NONCE);
+        break;
+    default:
+        SMP_TRACE_ERROR ("Association Model = %d is not used in LE SC\n",
+                         p_cb->selected_association_model);
+        break;
+    }
+}
+
+/*******************************************************************************
+** Function     smp_process_peer_nonce
+** Description  The function processes newly received and saved in CB peer nonce.
+**              The actions depend on the selected association model and the role.
+**
+** Note         It is supposed to be called in SC phase1.
+*******************************************************************************/
+void smp_process_peer_nonce(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    UINT8   reason;
+
+    SMP_TRACE_DEBUG("%s start \n", __func__);
+
+    switch (p_cb->selected_association_model) {
+    case SMP_MODEL_SEC_CONN_JUSTWORKS:
+    case SMP_MODEL_SEC_CONN_NUM_COMP:
+        /* in these models only master receives commitment */
+        if (p_cb->role == HCI_ROLE_MASTER) {
+            if (!smp_check_commitment(p_cb)) {
+                reason = p_cb->failure = SMP_CONFIRM_VALUE_ERR;
+                smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+                break;
+            }
+        } else {
+            /* slave sends local nonce */
+            smp_send_rand(p_cb, NULL);
+        }
+
+        if (p_cb->selected_association_model == SMP_MODEL_SEC_CONN_JUSTWORKS) {
+            /* go directly to phase 2 */
+            smp_sm_event(p_cb, SMP_SC_PHASE1_CMPLT_EVT, NULL);
+        } else { /* numeric comparison */
+            smp_set_state(SMP_STATE_WAIT_NONCE);
+            smp_sm_event(p_cb, SMP_SC_CALC_NC_EVT, NULL);
+        }
+        break;
+    case SMP_MODEL_SEC_CONN_PASSKEY_ENT:
+    case SMP_MODEL_SEC_CONN_PASSKEY_DISP:
+        if (!smp_check_commitment(p_cb)) {
+            reason = p_cb->failure = SMP_CONFIRM_VALUE_ERR;
+            smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+            break;
+        }
+
+        if (p_cb->role == HCI_ROLE_SLAVE) {
+            smp_send_rand(p_cb, NULL);
+        }
+
+        if (++p_cb->round < 20) {
+            smp_set_state(SMP_STATE_SEC_CONN_PHS1_START);
+            p_cb->flags &= ~SMP_PAIR_FLAG_HAVE_PEER_COMM;
+            smp_start_nonce_generation(p_cb);
+            break;
+        }
+
+        smp_sm_event(p_cb, SMP_SC_PHASE1_CMPLT_EVT, NULL);
+        break;
+    case SMP_MODEL_SEC_CONN_OOB:
+        if (p_cb->role == HCI_ROLE_SLAVE) {
+            smp_send_rand(p_cb, NULL);
+        }
+
+        smp_sm_event(p_cb, SMP_SC_PHASE1_CMPLT_EVT, NULL);
+        break;
+    default:
+        SMP_TRACE_ERROR ("Association Model = %d is not used in LE SC\n",
+                         p_cb->selected_association_model);
+        break;
+    }
+
+    SMP_TRACE_DEBUG("%s end\n ", __FUNCTION__);
+}
+#endif  ///BLE_INCLUDED == TRUE
+
+/*******************************************************************************
+** Function     smp_match_dhkey_checks
+** Description  checks if the calculated peer DHKey Check value is the same as
+**              received from the peer DHKey check value.
+*******************************************************************************/
+void smp_match_dhkey_checks(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    UINT8 reason = SMP_DHKEY_CHK_FAIL;
+
+    SMP_TRACE_DEBUG("%s\n", __func__);
+
+    if (memcmp(p_data->key.p_data, p_cb->remote_dhkey_check, BT_OCTET16_LEN)) {
+        SMP_TRACE_WARNING ("dhkey checks do no match\n");
+        p_cb->failure = reason;
+        smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+        return;
+    }
+
+    SMP_TRACE_EVENT ("dhkey checks match\n");
+
+    /* compare the max encryption key size, and save the smaller one for the link */
+    if (p_cb->peer_enc_size < p_cb->loc_enc_size) {
+        p_cb->loc_enc_size = p_cb->peer_enc_size;
+    }
+
+    if (p_cb->role == HCI_ROLE_SLAVE) {
+        smp_sm_event(p_cb, SMP_PAIR_DHKEY_CHCK_EVT, NULL);
+    } else {
+        /* master device always use received i/r key as keys to distribute */
+        p_cb->local_i_key = p_cb->peer_i_key;
+        p_cb->local_r_key = p_cb->peer_r_key;
+        smp_sm_event(p_cb, SMP_ENC_REQ_EVT, NULL);
+    }
+}
+
+/*******************************************************************************
+** Function     smp_move_to_secure_connections_phase2
+** Description  Signal State Machine to start SC phase 2 initialization (to
+**              compute local DHKey Check value).
+**
+** Note         SM is supposed to be in the state SMP_STATE_SEC_CONN_PHS2_START.
+*******************************************************************************/
+void smp_move_to_secure_connections_phase2(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    SMP_TRACE_DEBUG("%s\n", __func__);
+    smp_sm_event(p_cb, SMP_SC_PHASE1_CMPLT_EVT, NULL);
+}
+
+/*******************************************************************************
+** Function     smp_phase_2_dhkey_checks_are_present
+** Description  generates event if dhkey check from the peer is already received.
+**
+** Note         It is supposed to be used on slave to prevent race condition.
+**              It is supposed to be called after slave dhkey check is calculated.
+*******************************************************************************/
+void smp_phase_2_dhkey_checks_are_present(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    SMP_TRACE_DEBUG("%s\n", __func__);
+
+    if (p_cb->flags & SMP_PAIR_FLAG_HAVE_PEER_DHK_CHK) {
+        smp_sm_event(p_cb, SMP_SC_2_DHCK_CHKS_PRES_EVT, NULL);
+    }
+}
+
+/*******************************************************************************
+** Function     smp_wait_for_both_public_keys
+** Description  generates SMP_BOTH_PUBL_KEYS_RCVD_EVT event when both local and master
+**              public keys are available.
+**
+** Note         on the slave it is used to prevent race condition.
+**
+*******************************************************************************/
+void smp_wait_for_both_public_keys(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    SMP_TRACE_DEBUG("%s\n", __func__);
+
+    if ((p_cb->flags & SMP_PAIR_FLAG_HAVE_PEER_PUBL_KEY) &&
+            (p_cb->flags & SMP_PAIR_FLAG_HAVE_LOCAL_PUBL_KEY)) {
+        if ((p_cb->role == HCI_ROLE_SLAVE) &&
+                ((p_cb->req_oob_type == SMP_OOB_LOCAL) || (p_cb->req_oob_type == SMP_OOB_BOTH))) {
+            smp_set_state(SMP_STATE_PUBLIC_KEY_EXCH);
+        }
+        smp_sm_event(p_cb, SMP_BOTH_PUBL_KEYS_RCVD_EVT, NULL);
+    }
+}
+
+#if (BLE_INCLUDED == TRUE)
+/*******************************************************************************
+** Function     smp_start_passkey_verification
+** Description  Starts SC passkey entry verification.
+*******************************************************************************/
+void smp_start_passkey_verification(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    UINT8 *p = NULL;
+
+    SMP_TRACE_DEBUG("%s\n", __func__);
+    p = p_cb->local_random;
+    UINT32_TO_STREAM(p, p_data->passkey);
+
+    p = p_cb->peer_random;
+    UINT32_TO_STREAM(p, p_data->passkey);
+
+    p_cb->round = 0;
+    smp_start_nonce_generation(p_cb);
+}
+
+/*******************************************************************************
+** Function     smp_process_secure_connection_oob_data
+** Description  Processes local/peer SC OOB data received from somewhere.
+*******************************************************************************/
+void smp_process_secure_connection_oob_data(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    SMP_TRACE_DEBUG("%s\n", __func__);
+
+    tSMP_SC_OOB_DATA *p_sc_oob_data = &p_cb->sc_oob_data;
+    if (p_sc_oob_data->loc_oob_data.present) {
+        memcpy(p_cb->local_random, p_sc_oob_data->loc_oob_data.randomizer,
+               sizeof(p_cb->local_random));
+    } else {
+        SMP_TRACE_EVENT ("local OOB randomizer is absent\n");
+        memset(p_cb->local_random, 0, sizeof (p_cb->local_random));
+    }
+
+    if (!p_sc_oob_data->peer_oob_data.present) {
+        SMP_TRACE_EVENT ("peer OOB data is absent\n");
+        memset(p_cb->peer_random, 0, sizeof (p_cb->peer_random));
+    } else {
+        memcpy(p_cb->peer_random, p_sc_oob_data->peer_oob_data.randomizer,
+               sizeof(p_cb->peer_random));
+        memcpy(p_cb->remote_commitment, p_sc_oob_data->peer_oob_data.commitment,
+               sizeof(p_cb->remote_commitment));
+
+        UINT8 reason = SMP_CONFIRM_VALUE_ERR;
+        /* check commitment */
+        if (!smp_check_commitment(p_cb)) {
+            p_cb->failure = reason;
+            smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+            return;
+        }
+
+        if (p_cb->peer_oob_flag != SMP_OOB_PRESENT) {
+            /* the peer doesn't have local randomiser */
+            SMP_TRACE_EVENT ("peer didn't receive local OOB data, set local randomizer to 0\n");
+            memset(p_cb->local_random, 0, sizeof (p_cb->local_random));
+        }
+    }
+
+    print128(p_cb->local_random, (const UINT8 *)"local OOB randomizer");
+    print128(p_cb->peer_random, (const UINT8 *)"peer OOB randomizer");
+    smp_start_nonce_generation(p_cb);
+}
+
+/*******************************************************************************
+** Function     smp_set_local_oob_keys
+** Description  Saves calculated private/public keys in sc_oob_data.loc_oob_data,
+**              starts nonce generation
+**              (to be saved in sc_oob_data.loc_oob_data.randomizer).
+*******************************************************************************/
+void smp_set_local_oob_keys(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    SMP_TRACE_DEBUG("%s\n", __func__);
+
+    memcpy(p_cb->sc_oob_data.loc_oob_data.private_key_used, p_cb->private_key,
+           BT_OCTET32_LEN);
+    p_cb->sc_oob_data.loc_oob_data.publ_key_used = p_cb->loc_publ_key;
+    smp_start_nonce_generation(p_cb);
+}
+
+/*******************************************************************************
+** Function     smp_set_local_oob_random_commitment
+** Description  Saves calculated randomizer and commitment in sc_oob_data.loc_oob_data,
+**              passes sc_oob_data.loc_oob_data up for safekeeping.
+*******************************************************************************/
+void smp_set_local_oob_random_commitment(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    SMP_TRACE_DEBUG("%s\n", __func__);
+    memcpy(p_cb->sc_oob_data.loc_oob_data.randomizer, p_cb->rand,
+           BT_OCTET16_LEN);
+
+    smp_calculate_f4(p_cb->sc_oob_data.loc_oob_data.publ_key_used.x,
+                     p_cb->sc_oob_data.loc_oob_data.publ_key_used.x,
+                     p_cb->sc_oob_data.loc_oob_data.randomizer, 0,
+                     p_cb->sc_oob_data.loc_oob_data.commitment);
+
+#if SMP_DEBUG == TRUE
+    UINT8   *p_print = NULL;
+    SMP_TRACE_DEBUG("local SC OOB data set:\n");
+    p_print = (UINT8 *) &p_cb->sc_oob_data.loc_oob_data.addr_sent_to;
+    smp_debug_print_nbyte_little_endian (p_print, (const UINT8 *)"addr_sent_to",
+                                         sizeof(tBLE_BD_ADDR));
+    p_print = (UINT8 *) &p_cb->sc_oob_data.loc_oob_data.private_key_used;
+    smp_debug_print_nbyte_little_endian (p_print, (const UINT8 *)"private_key_used",
+                                         BT_OCTET32_LEN);
+    p_print = (UINT8 *) &p_cb->sc_oob_data.loc_oob_data.publ_key_used.x;
+    smp_debug_print_nbyte_little_endian (p_print, (const UINT8 *)"publ_key_used.x",
+                                         BT_OCTET32_LEN);
+    p_print = (UINT8 *) &p_cb->sc_oob_data.loc_oob_data.publ_key_used.y;
+    smp_debug_print_nbyte_little_endian (p_print, (const UINT8 *)"publ_key_used.y",
+                                         BT_OCTET32_LEN);
+    p_print = (UINT8 *) &p_cb->sc_oob_data.loc_oob_data.randomizer;
+    smp_debug_print_nbyte_little_endian (p_print, (const UINT8 *)"randomizer",
+                                         BT_OCTET16_LEN);
+    p_print = (UINT8 *) &p_cb->sc_oob_data.loc_oob_data.commitment;
+    smp_debug_print_nbyte_little_endian (p_print, (const UINT8 *) "commitment",
+                                         BT_OCTET16_LEN);
+    SMP_TRACE_DEBUG("");
+#endif
+
+    /* pass created OOB data up */
+    p_cb->cb_evt = SMP_SC_LOC_OOB_DATA_UP_EVT;
+    smp_send_app_cback(p_cb, NULL);
+
+    smp_cb_cleanup(p_cb);
+}
+
+/*******************************************************************************
+**
+** Function         smp_link_encrypted
+**
+** Description      This function is called when link is encrypted and notified to
+**                  slave device. Proceed to to send LTK, DIV and ER to master if
+**                  bonding the devices.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void smp_link_encrypted(BD_ADDR bda, UINT8 encr_enable)
+{
+    tSMP_CB *p_cb = &smp_cb;
+    tBTM_SEC_DEV_REC  *p_dev_rec = btm_find_dev (bda);
+    SMP_TRACE_DEBUG("%s encr_enable=%d\n", __func__, encr_enable);
+
+    if (memcmp(&smp_cb.pairing_bda[0], bda, BD_ADDR_LEN) == 0) {
+        /* encryption completed with STK, remmeber the key size now, could be overwite
+        *  when key exchange happens                                        */
+        if (p_cb->loc_enc_size != 0 && encr_enable) {
+            /* update the link encryption key size if a SMP pairing just performed */
+            btm_ble_update_sec_key_size(bda, p_cb->loc_enc_size);
+        }
+
+        smp_sm_event(&smp_cb, SMP_ENCRYPTED_EVT, &encr_enable);
+    } else if (p_dev_rec && !p_dev_rec->role_master && !p_dev_rec->enc_init_by_we ){
+        /*
+        if enc_init_by_we is false, it means that client initiates encryption before slave calls esp_ble_set_encryption()
+        we need initiate pairing_bda and p_cb->role then encryption, for example iPhones
+        */
+        memcpy(&smp_cb.pairing_bda[0], bda, BD_ADDR_LEN);
+        p_cb->state = SMP_STATE_ENCRYPTION_PENDING;
+        p_cb->role = HCI_ROLE_SLAVE;
+        p_dev_rec->enc_init_by_we = FALSE;
+        smp_sm_event(&smp_cb, SMP_ENCRYPTED_EVT, &encr_enable);
+    } else if (p_dev_rec && p_dev_rec->role_master && p_dev_rec->enc_init_by_we){
+        memcpy(&smp_cb.pairing_bda[0], bda, BD_ADDR_LEN);
+        p_cb->state = SMP_STATE_ENCRYPTION_PENDING;
+        p_cb->role = HCI_ROLE_MASTER;
+        p_dev_rec->enc_init_by_we = FALSE;
+        smp_sm_event(&smp_cb, SMP_ENCRYPTED_EVT, &encr_enable);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         smp_proc_ltk_request
+**
+** Description      This function is called when LTK request is received from
+**                  controller.
+**
+** Returns          void
+**
+*******************************************************************************/
+BOOLEAN smp_proc_ltk_request(BD_ADDR bda)
+{
+    SMP_TRACE_DEBUG("%s state = %d\n",  __func__, smp_cb.state);
+    BOOLEAN match = FALSE;
+
+    if (!memcmp(bda, smp_cb.pairing_bda, BD_ADDR_LEN)) {
+        match = TRUE;
+    } else {
+        BD_ADDR dummy_bda = {0};
+        tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev(bda);
+        if (p_dev_rec != NULL &&
+                0 == memcmp(p_dev_rec->ble.pseudo_addr, smp_cb.pairing_bda, BD_ADDR_LEN) &&
+                0 != memcmp(p_dev_rec->ble.pseudo_addr, dummy_bda, BD_ADDR_LEN)) {
+            match = TRUE;
+        }
+    }
+
+    if (match && smp_cb.state == SMP_STATE_ENCRYPTION_PENDING) {
+        smp_sm_event(&smp_cb, SMP_ENC_REQ_EVT, NULL);
+        return TRUE;
+    }
+
+    return FALSE;
+}
+
+/*******************************************************************************
+**
+** Function         smp_process_secure_connection_long_term_key
+**
+** Description      This function is called to process SC LTK.
+**                  SC LTK is calculated and used instead of STK.
+**                  Here SC LTK is saved in BLE DB.
+**
+** Returns          void
+**
+*******************************************************************************/
+void smp_process_secure_connection_long_term_key(void)
+{
+    tSMP_CB     *p_cb = &smp_cb;
+
+    SMP_TRACE_DEBUG("%s\n", __func__);
+    smp_save_secure_connections_long_term_key(p_cb);
+
+    smp_update_key_mask (p_cb, SMP_SEC_KEY_TYPE_ENC, FALSE);
+    smp_key_distribution(p_cb, NULL);
+}
+
+/*******************************************************************************
+**
+** Function         smp_set_derive_link_key
+**
+** Description      This function is called to set flag that indicates that
+**                  BR/EDR LK has to be derived from LTK after all keys are
+**                  distributed.
+**
+** Returns          void
+**
+*******************************************************************************/
+void smp_set_derive_link_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    SMP_TRACE_DEBUG ("%s\n", __func__);
+    p_cb->derive_lk = TRUE;
+    smp_update_key_mask (p_cb, SMP_SEC_KEY_TYPE_LK, FALSE);
+    smp_key_distribution(p_cb, NULL);
+}
+
+/*******************************************************************************
+**
+** Function         smp_derive_link_key_from_long_term_key
+**
+** Description      This function is called to derive BR/EDR LK from LTK.
+**
+** Returns          void
+**
+*******************************************************************************/
+void smp_derive_link_key_from_long_term_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    tSMP_STATUS status = SMP_PAIR_FAIL_UNKNOWN;
+
+    SMP_TRACE_DEBUG("%s\n", __func__);
+    if (!smp_calculate_link_key_from_long_term_key(p_cb)) {
+        SMP_TRACE_ERROR("%s failed\n", __FUNCTION__);
+        smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &status);
+        return;
+    }
+}
+#endif  ///BLE_INCLUDED == TRUE
+
+#if (CLASSIC_BT_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function         smp_br_process_link_key
+**
+** Description      This function is called to process BR/EDR LK:
+**                  - to derive SMP LTK from BR/EDR LK;
+*8                  - to save SMP LTK.
+**
+** Returns          void
+**
+*******************************************************************************/
+void smp_br_process_link_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    tSMP_STATUS status = SMP_PAIR_FAIL_UNKNOWN;
+
+    SMP_TRACE_DEBUG("%s\n", __func__);
+    if (!smp_calculate_long_term_key_from_link_key(p_cb)) {
+        SMP_TRACE_ERROR ("%s failed\n", __FUNCTION__);
+        smp_sm_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &status);
+        return;
+    }
+
+    SMP_TRACE_DEBUG("%s: LTK derivation from LK successfully completed\n", __FUNCTION__);
+    smp_save_secure_connections_long_term_key(p_cb);
+    smp_update_key_mask (p_cb, SMP_SEC_KEY_TYPE_ENC, FALSE);
+    smp_br_select_next_key(p_cb, NULL);
+}
+#endif  ///CLASSIC_BT_INCLUDED == TRUE
+
+/*******************************************************************************
+** Function     smp_key_distribution_by_transport
+** Description  depending on the transport used at the moment calls either
+**              smp_key_distribution(...) or smp_br_key_distribution(...).
+*******************************************************************************/
+void smp_key_distribution_by_transport(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    SMP_TRACE_DEBUG("%s\n", __func__);
+    if (p_cb->smp_over_br) {
+#if (CLASSIC_BT_INCLUDED == TRUE)
+        smp_br_select_next_key(p_cb, NULL);
+#endif  ///CLASSIC_BT_INCLUDED == TRUE
+    } else {
+#if (BLE_INCLUDED == TRUE)
+        smp_key_distribution(p_cb, NULL);
+#endif  ///BLE_INCLUDED == TRUE
+    }
+}
+
+/*******************************************************************************
+** Function         smp_br_pairing_complete
+** Description      This function is called to send the pairing complete callback
+**                  and remove the connection if needed.
+*******************************************************************************/
+void smp_br_pairing_complete(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    SMP_TRACE_DEBUG("%s\n", __func__);
+
+    if (p_cb->total_tx_unacked == 0) {
+        /* process the pairing complete */
+        smp_proc_pairing_cmpl(p_cb);
+    }
+}
+
+#endif