diff --git a/docs/Migration_guide.md b/docs/Migration_guide.md index b6551902..d1fcee8a 100644 --- a/docs/Migration_guide.md +++ b/docs/Migration_guide.md @@ -383,18 +383,23 @@ The security callback methods are now incorporated in the `NimBLEServerCallbacks The callback methods are: -> `bool onConfirmPIN(uint32_t pin)` +> `bool onConfirmPIN(const NimBLEConnInfo& connInfo, uint32_t pin)` -Receives the pin when using numeric comparison authentication, `return true;` to accept. +Receives the pin when using numeric comparison authentication. +Call `NimBLEDevice::injectConfirmPIN(connInfo, true);` to accept or `NimBLEDevice::injectConfirmPIN(connInfo, false);` to reject.
-> `uint32_t onPassKeyRequest()` +> `void onPassKeyEntry(const NimBLEConnInfo& connInfo)` -For server callback; return the passkey expected from the client. -For client callback; return the passkey to send to the server. +Client callback; client should respond with the passkey (pin) by calling `NimBLEDevice::injectPassKey(connInfo, 123456);`
-> `void onAuthenticationComplete(NimBLEConnInfo& connInfo)` +> `uint32_t onPassKeyDisplay()` + +Server callback; should return the passkey (pin) expected from the client. +
+ +> `void onAuthenticationComplete(const NimBLEConnInfo& connInfo)` Authentication complete, success or failed information is available from the `NimBLEConnInfo` methods.
diff --git a/examples/NimBLE_Client/NimBLE_Client.ino b/examples/NimBLE_Client/NimBLE_Client.ino index ea34b827..7b6f8712 100644 --- a/examples/NimBLE_Client/NimBLE_Client.ino +++ b/examples/NimBLE_Client/NimBLE_Client.ino @@ -56,28 +56,29 @@ class ClientCallbacks : public NimBLEClientCallbacks { /********************* Security handled here ********************** ****** Note: these are the same return values as defaults ********/ - uint32_t onPassKeyRequest(){ - Serial.println("Client Passkey Request"); - /** return the passkey to send to the server */ - return 123456; + void onPassKeyEntry(const NimBLEConnInfo& connInfo){ + Serial.println("Server Passkey Entry"); + /** This should prompt the user to enter the passkey displayed + * on the peer device. + */ + NimBLEDevice::injectPassKey(connInfo, 123456); }; - bool onConfirmPIN(uint32_t pass_key){ - Serial.print("The passkey YES/NO number: "); - Serial.println(pass_key); - /** Return false if passkeys don't match. */ - return true; + void onConfirmPIN(const NimBLEConnInfo& connInfo, uint32_t pass_key){ + Serial.print("The passkey YES/NO number: ");Serial.println(pass_key); + /** Inject false if passkeys don't match. */ + NimBLEDevice::injectConfirmPIN(connInfo, true); }; - /** Pairing process complete, we can check the results in NimBLEConnInfo */ - void onAuthenticationComplete(NimBLEConnInfo& connInfo){ + /** Pairing process complete, we can check the results in connInfo */ + void onAuthenticationComplete(const NimBLEConnInfo& connInfo){ if(!connInfo.isEncrypted()) { Serial.println("Encrypt connection failed - disconnecting"); - /** Find the client with the connection handle provided in connInfo */ + /** Find the client with the connection handle provided in desc */ NimBLEDevice::getClientByID(connInfo.getConnHandle())->disconnect(); return; } - }; + } }; diff --git a/examples/NimBLE_Secure_Client/NimBLE_Secure_Client.ino b/examples/NimBLE_Secure_Client/NimBLE_Secure_Client.ino index c1c54951..d45c700c 100644 --- a/examples/NimBLE_Secure_Client/NimBLE_Secure_Client.ino +++ b/examples/NimBLE_Secure_Client/NimBLE_Secure_Client.ino @@ -12,9 +12,9 @@ class ClientCallbacks : public NimBLEClientCallbacks { - uint32_t onPassKeyRequest() + uint32_t onPassKeyEntry() { - Serial.println("Client Passkey Request"); + Serial.println("Client Passkey Entry"); /** return the passkey to send to the server */ /** Change this to be different from NimBLE_Secure_Server if you want to test what happens on key mismatch */ return 123456; diff --git a/examples/NimBLE_Server/NimBLE_Server.ino b/examples/NimBLE_Server/NimBLE_Server.ino index eb9b8263..85616346 100644 --- a/examples/NimBLE_Server/NimBLE_Server.ino +++ b/examples/NimBLE_Server/NimBLE_Server.ino @@ -37,21 +37,21 @@ class ServerCallbacks: public NimBLEServerCallbacks { /********************* Security handled here ********************** ****** Note: these are the same return values as defaults ********/ - uint32_t onPassKeyRequest(){ - Serial.println("Server Passkey Request"); + uint32_t onPassKeyDisplay() { + Serial.println("Server Passkey Display"); /** This should return a random 6 digit number for security * or make your own static passkey as done here. */ return 123456; }; - bool onConfirmPIN(uint32_t pass_key){ + void onConfirmPIN(const NimBLEConnInfo& connInfo, uint32_t pass_key) { Serial.print("The passkey YES/NO number: ");Serial.println(pass_key); - /** Return false if passkeys don't match. */ - return true; + /** Inject false if passkeys don't match. */ + NimBLEDevice::injectConfirmPIN(connInfo, true); }; - void onAuthenticationComplete(NimBLEConnInfo& connInfo){ + void onAuthenticationComplete(const NimBLEConnInfo& connInfo) { /** Check that encryption was successful, if not we disconnect the client */ if(!connInfo.isEncrypted()) { NimBLEDevice::getServer()->disconnect(connInfo.getConnHandle()); diff --git a/examples/Refactored_original_examples/BLE_client/BLE_client.ino b/examples/Refactored_original_examples/BLE_client/BLE_client.ino index 58d6a3f7..4cd79620 100644 --- a/examples/Refactored_original_examples/BLE_client/BLE_client.ino +++ b/examples/Refactored_original_examples/BLE_client/BLE_client.ino @@ -51,16 +51,17 @@ class MyClientCallback : public BLEClientCallbacks { } /***************** New - Security handled here ******************** ****** Note: these are the same return values as defaults ********/ - uint32_t onPassKeyRequest(){ - Serial.println("Client PassKeyRequest"); - return 123456; + void onPassKeyEntry() { + Serial.println("Client PassKey Entry"); + NimBLEDevice::injectPassKey(connInfo, 123456); } - bool onConfirmPIN(uint32_t pass_key){ + + void onConfirmPIN(const BLEConnInfo& connInfo, uint32_t pass_key) { Serial.print("The passkey YES/NO number: ");Serial.println(pass_key); - return true; + NimBLEDevice::injectConfirmPIN(connInfo, true); } - void onAuthenticationComplete(BLEConnInfo& connInfo){ + void onAuthenticationComplete(const BLEConnInfo& connInfo){ Serial.println("Starting BLE work!"); } /*******************************************************************/ diff --git a/examples/Refactored_original_examples/BLE_notify/BLE_notify.ino b/examples/Refactored_original_examples/BLE_notify/BLE_notify.ino index 3582bc85..876b7d11 100644 --- a/examples/Refactored_original_examples/BLE_notify/BLE_notify.ino +++ b/examples/Refactored_original_examples/BLE_notify/BLE_notify.ino @@ -43,7 +43,7 @@ uint32_t value = 0; #define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8" /** None of these are required as they will be handled by the library with defaults. ** - ** Remove as you see fit for your needs */ + ** Remove as you see fit for your needs */ class MyServerCallbacks: public BLEServerCallbacks { void onConnect(BLEServer* pServer, BLEConnInfo& connInfo) { deviceConnected = true; @@ -54,19 +54,23 @@ class MyServerCallbacks: public BLEServerCallbacks { } /***************** New - Security handled here ******************** ****** Note: these are the same return values as defaults ********/ - uint32_t onPassKeyRequest(){ - Serial.println("Server PassKeyRequest"); - return 123456; - } - - bool onConfirmPIN(uint32_t pass_key){ - Serial.print("The passkey YES/NO number: ");Serial.println(pass_key); - return true; - } - - void onAuthenticationComplete(BLEConnInfo& connInfo){ - Serial.println("Starting BLE work!"); - } + uint32_t onPassKeyDisplay() { + Serial.println("Server Passkey Display"); + /** This should return a random 6 digit number for security + * or make your own static passkey as done here. + */ + return 123456; + } + + void onConfirmPIN(const BLEConnInfo& connInfo, uint32_t pass_key) { + Serial.print("The passkey YES/NO number: ");Serial.println(pass_key); + /** Inject false if passkeys don't match. */ + NimBLEDevice::injectConfirmPIN(connInfo, true); + } + + void onAuthenticationComplete(const BLEConnInfo& connInfo) { + Serial.println("Starting BLE work!"); + } /*******************************************************************/ }; @@ -87,13 +91,13 @@ void setup() { // Create a BLE Characteristic pCharacteristic = pService->createCharacteristic( CHARACTERISTIC_UUID, - /******* Enum Type NIMBLE_PROPERTY now ******* + /******* Enum Type NIMBLE_PROPERTY now ******* BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_NOTIFY | BLECharacteristic::PROPERTY_INDICATE ); - **********************************************/ + **********************************************/ NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::NOTIFY | @@ -102,11 +106,11 @@ void setup() { // https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.descriptor.gatt.client_characteristic_configuration.xml // Create a BLE Descriptor - /*************************************************** - NOTE: DO NOT create a 2902 descriptor. - it will be created automatically if notifications + /*************************************************** + NOTE: DO NOT create a 2902 descriptor. + it will be created automatically if notifications or indications are enabled on a characteristic. - + pCharacteristic->addDescriptor(new BLE2902()); ****************************************************/ // Start the service diff --git a/examples/Refactored_original_examples/BLE_server_multiconnect/BLE_server_multiconnect.ino b/examples/Refactored_original_examples/BLE_server_multiconnect/BLE_server_multiconnect.ino index 22c02859..44daf00e 100644 --- a/examples/Refactored_original_examples/BLE_server_multiconnect/BLE_server_multiconnect.ino +++ b/examples/Refactored_original_examples/BLE_server_multiconnect/BLE_server_multiconnect.ino @@ -44,7 +44,7 @@ uint32_t value = 0; /** None of these are required as they will be handled by the library with defaults. ** - ** Remove as you see fit for your needs */ + ** Remove as you see fit for your needs */ class MyServerCallbacks: public BLEServerCallbacks { void onConnect(BLEServer* pServer, BLEConnInfo& connInfo) { deviceConnected = true; @@ -56,17 +56,21 @@ class MyServerCallbacks: public BLEServerCallbacks { } /***************** New - Security handled here ******************** ****** Note: these are the same return values as defaults ********/ - uint32_t onPassKeyRequest(){ - Serial.println("Server PassKeyRequest"); - return 123456; + uint32_t onPassKeyDisplay() { + Serial.println("Server Passkey Display"); + /** This should return a random 6 digit number for security + * or make your own static passkey as done here. + */ + return 123456; } - bool onConfirmPIN(uint32_t pass_key){ + void onConfirmPIN(const BLEConnInfo& connInfo, uint32_t pass_key) { Serial.print("The passkey YES/NO number: ");Serial.println(pass_key); - return true; + /** Inject false if passkeys don't match. */ + NimBLEDevice::injectConfirmPIN(connInfo, true); } - void onAuthenticationComplete(BLEConnInfo& connInfo){ + void onAuthenticationComplete(const BLEConnInfo& connInfo) { Serial.println("Starting BLE work!"); } /*******************************************************************/ @@ -90,13 +94,13 @@ void setup() { // Create a BLE Characteristic pCharacteristic = pService->createCharacteristic( CHARACTERISTIC_UUID, - /******* Enum Type NIMBLE_PROPERTY now ******* + /******* Enum Type NIMBLE_PROPERTY now ******* BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_NOTIFY | BLECharacteristic::PROPERTY_INDICATE ); - **********************************************/ + **********************************************/ NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::NOTIFY | @@ -105,11 +109,11 @@ void setup() { // https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.descriptor.gatt.client_characteristic_configuration.xml // Create a BLE Descriptor - /*************************************************** - NOTE: DO NOT create a 2902 descriptor - it will be created automatically if notifications + /*************************************************** + NOTE: DO NOT create a 2902 descriptor + it will be created automatically if notifications or indications are enabled on a characteristic. - + pCharacteristic->addDescriptor(new BLE2902()); ****************************************************/ diff --git a/examples/Refactored_original_examples/BLE_uart/BLE_uart.ino b/examples/Refactored_original_examples/BLE_uart/BLE_uart.ino index 260b30a4..a609952e 100644 --- a/examples/Refactored_original_examples/BLE_uart/BLE_uart.ino +++ b/examples/Refactored_original_examples/BLE_uart/BLE_uart.ino @@ -5,7 +5,7 @@ Create a BLE server that, once we receive a connection, will send periodic notifications. The service advertises itself as: 6E400001-B5A3-F393-E0A9-E50E24DCCA9E - Has a characteristic of: 6E400002-B5A3-F393-E0A9-E50E24DCCA9E - used for receiving data with "WRITE" + Has a characteristic of: 6E400002-B5A3-F393-E0A9-E50E24DCCA9E - used for receiving data with "WRITE" Has a characteristic of: 6E400003-B5A3-F393-E0A9-E50E24DCCA9E - used to send data with "NOTIFY" The design of creating the BLE server is: @@ -17,7 +17,7 @@ 6. Start advertising. In this example rxValue is the data received (only accessible inside that function). - And txValue is the data to be sent, in this example just a byte incremented every second. + And txValue is the data to be sent, in this example just a byte incremented every second. */ /** NimBLE differences highlighted in comment blocks **/ @@ -45,7 +45,7 @@ uint8_t txValue = 0; /** None of these are required as they will be handled by the library with defaults. ** - ** Remove as you see fit for your needs */ + ** Remove as you see fit for your needs */ class MyServerCallbacks: public BLEServerCallbacks { void onConnect(BLEServer* pServer, BLEConnInfo& connInfo) { deviceConnected = true; @@ -56,17 +56,21 @@ class MyServerCallbacks: public BLEServerCallbacks { } /***************** New - Security handled here ******************** ****** Note: these are the same return values as defaults ********/ - uint32_t onPassKeyRequest(){ - Serial.println("Server PassKeyRequest"); - return 123456; + uint32_t onPassKeyDisplay() { + Serial.println("Server Passkey Display"); + /** This should return a random 6 digit number for security + * or make your own static passkey as done here. + */ + return 123456; } - bool onConfirmPIN(uint32_t pass_key){ + void onConfirmPIN(const BLEConnInfo& connInfo, uint32_t pass_key) { Serial.print("The passkey YES/NO number: ");Serial.println(pass_key); - return true; + /** Inject false if passkeys don't match. */ + NimBLEDevice::injectConfirmPIN(connInfo, true); } - void onAuthenticationComplete(BLEConnInfo& connInfo){ + void onAuthenticationComplete(const BLEConnInfo& connInfo) { Serial.println("Starting BLE work!"); } /*******************************************************************/ @@ -105,27 +109,27 @@ void setup() { // Create a BLE Characteristic pTxCharacteristic = pService->createCharacteristic( CHARACTERISTIC_UUID_TX, - /******* Enum Type NIMBLE_PROPERTY now ******* + /******* Enum Type NIMBLE_PROPERTY now ******* BLECharacteristic::PROPERTY_NOTIFY ); - **********************************************/ + **********************************************/ NIMBLE_PROPERTY::NOTIFY ); - - /*************************************************** - NOTE: DO NOT create a 2902 descriptor - it will be created automatically if notifications + + /*************************************************** + NOTE: DO NOT create a 2902 descriptor + it will be created automatically if notifications or indications are enabled on a characteristic. - + pCharacteristic->addDescriptor(new BLE2902()); - ****************************************************/ + ****************************************************/ BLECharacteristic * pRxCharacteristic = pService->createCharacteristic( CHARACTERISTIC_UUID_RX, - /******* Enum Type NIMBLE_PROPERTY now ******* + /******* Enum Type NIMBLE_PROPERTY now ******* BLECharacteristic::PROPERTY_WRITE ); - *********************************************/ + *********************************************/ NIMBLE_PROPERTY::WRITE ); diff --git a/src/NimBLEClient.cpp b/src/NimBLEClient.cpp index 996b7590..ceed193f 100644 --- a/src/NimBLEClient.cpp +++ b/src/NimBLEClient.cpp @@ -1171,7 +1171,11 @@ int NimBLEClient::handleGapEvent(struct ble_gap_event *event, void *arg) { { NimBLEConnInfo peerInfo; rc = ble_gap_conn_find(event->enc_change.conn_handle, &peerInfo.m_desc); - assert(rc == 0); + if (rc != 0) { + NIMBLE_LOGE(LOG_TAG, "Connection info not found"); + rc = 0; + break; + } if (event->enc_change.status == (BLE_HS_ERR_HCI_BASE + BLE_ERR_PINKEY_MISSING)) { // Key is missing, try deleting. @@ -1203,20 +1207,17 @@ int NimBLEClient::handleGapEvent(struct ble_gap_event *event, void *arg) { if(pClient->m_conn_id != event->passkey.conn_handle) return 0; - if (event->passkey.params.action == BLE_SM_IOACT_DISP) { - pkey.action = event->passkey.params.action; - pkey.passkey = NimBLEDevice::m_passkey; // This is the passkey to be entered on peer - rc = ble_sm_inject_io(event->passkey.conn_handle, &pkey); - NIMBLE_LOGD(LOG_TAG, "ble_sm_inject_io result: %d", rc); + NimBLEConnInfo peerInfo; + rc = ble_gap_conn_find(event->passkey.conn_handle, &peerInfo.m_desc); + if (rc != 0) { + NIMBLE_LOGE(LOG_TAG, "Connection info not found"); + rc = 0; + break; + } - } else if (event->passkey.params.action == BLE_SM_IOACT_NUMCMP) { + if (event->passkey.params.action == BLE_SM_IOACT_NUMCMP) { NIMBLE_LOGD(LOG_TAG, "Passkey on device's display: %" PRIu32, event->passkey.params.numcmp); - pkey.action = event->passkey.params.action; - pkey.numcmp_accept = pClient->m_pClientCallbacks->onConfirmPIN(event->passkey.params.numcmp); - - rc = ble_sm_inject_io(event->passkey.conn_handle, &pkey); - NIMBLE_LOGD(LOG_TAG, "ble_sm_inject_io result: %d", rc); - + pClient->m_pClientCallbacks->onConfirmPIN(peerInfo, event->passkey.params.numcmp); //TODO: Handle out of band pairing } else if (event->passkey.params.action == BLE_SM_IOACT_OOB) { static uint8_t tem_oob[16] = {0}; @@ -1229,12 +1230,7 @@ int NimBLEClient::handleGapEvent(struct ble_gap_event *event, void *arg) { //////// } else if (event->passkey.params.action == BLE_SM_IOACT_INPUT) { NIMBLE_LOGD(LOG_TAG, "Enter the passkey"); - pkey.action = event->passkey.params.action; - pkey.passkey = pClient->m_pClientCallbacks->onPassKeyRequest(); - - rc = ble_sm_inject_io(event->passkey.conn_handle, &pkey); - NIMBLE_LOGD(LOG_TAG, "ble_sm_inject_io result: %d", rc); - + pClient->m_pClientCallbacks->onPassKeyEntry(peerInfo); } else if (event->passkey.params.action == BLE_SM_IOACT_NONE) { NIMBLE_LOGD(LOG_TAG, "No passkey action required"); } @@ -1321,17 +1317,18 @@ bool NimBLEClientCallbacks::onConnParamsUpdateRequest(NimBLEClient* pClient, con return true; } -uint32_t NimBLEClientCallbacks::onPassKeyRequest(){ - NIMBLE_LOGD("NimBLEClientCallbacks", "onPassKeyRequest: default: 123456"); - return 123456; -} +void NimBLEClientCallbacks::onPassKeyEntry(const NimBLEConnInfo& connInfo){ + NIMBLE_LOGD("NimBLEClientCallbacks", "onPassKeyEntry: default: 123456"); + NimBLEDevice::injectPassKey(connInfo, 123456); +} //onPassKeyEntry -void NimBLEClientCallbacks::onAuthenticationComplete(NimBLEConnInfo& peerInfo){ +void NimBLEClientCallbacks::onAuthenticationComplete(const NimBLEConnInfo& connInfo){ NIMBLE_LOGD("NimBLEClientCallbacks", "onAuthenticationComplete: default"); } -bool NimBLEClientCallbacks::onConfirmPIN(uint32_t pin){ + +void NimBLEClientCallbacks::onConfirmPIN(const NimBLEConnInfo& connInfo, uint32_t pin){ NIMBLE_LOGD("NimBLEClientCallbacks", "onConfirmPIN: default: true"); - return true; + NimBLEDevice::injectConfirmPIN(connInfo, true); } #endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */ diff --git a/src/NimBLEClient.h b/src/NimBLEClient.h index 03061987..52f389e3 100644 --- a/src/NimBLEClient.h +++ b/src/NimBLEClient.h @@ -147,23 +147,23 @@ class NimBLEClientCallbacks { /** * @brief Called when server requests a passkey for pairing. - * @return The passkey to be sent to the server. + * @param [in] connInfo A reference to a NimBLEConnInfo instance containing the peer info. */ - virtual uint32_t onPassKeyRequest(); + virtual void onPassKeyEntry(const NimBLEConnInfo& connInfo); /** * @brief Called when the pairing procedure is complete. * @param [in] connInfo A reference to a NimBLEConnInfo instance containing the peer info.\n * This can be used to check the status of the connection encryption/pairing. */ - virtual void onAuthenticationComplete(NimBLEConnInfo& connInfo); + virtual void onAuthenticationComplete(const NimBLEConnInfo& connInfo); /** * @brief Called when using numeric comparision for pairing. + * @param [in] connInfo A reference to a NimBLEConnInfo instance containing the peer info. * @param [in] pin The pin to compare with the server. - * @return True to accept the pin. */ - virtual bool onConfirmPIN(uint32_t pin); + virtual void onConfirmPIN(const NimBLEConnInfo& connInfo, uint32_t pin); }; #endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */ diff --git a/src/NimBLEConnInfo.h b/src/NimBLEConnInfo.h index c764c246..6b451275 100644 --- a/src/NimBLEConnInfo.h +++ b/src/NimBLEConnInfo.h @@ -13,44 +13,44 @@ friend class NimBLECharacteristic; friend class NimBLEDescriptor; ble_gap_conn_desc m_desc; - NimBLEConnInfo() { m_desc = {}; } - NimBLEConnInfo(ble_gap_conn_desc desc) { m_desc = desc; } + NimBLEConnInfo() { m_desc = {}; } + NimBLEConnInfo(ble_gap_conn_desc desc) { m_desc = desc; } public: /** @brief Gets the over-the-air address of the connected peer */ - NimBLEAddress getAddress() { return NimBLEAddress(m_desc.peer_ota_addr); } + NimBLEAddress getAddress() const { return NimBLEAddress(m_desc.peer_ota_addr); } /** @brief Gets the ID address of the connected peer */ - NimBLEAddress getIdAddress() { return NimBLEAddress(m_desc.peer_id_addr); } + NimBLEAddress getIdAddress() const { return NimBLEAddress(m_desc.peer_id_addr); } /** @brief Gets the connection handle of the connected peer */ - uint16_t getConnHandle() { return m_desc.conn_handle; } + uint16_t getConnHandle() const { return m_desc.conn_handle; } /** @brief Gets the connection interval for this connection (in 1.25ms units) */ - uint16_t getConnInterval() { return m_desc.conn_itvl; } + uint16_t getConnInterval() const { return m_desc.conn_itvl; } /** @brief Gets the supervision timeout for this connection (in 10ms units) */ - uint16_t getConnTimeout() { return m_desc.supervision_timeout; } + uint16_t getConnTimeout() const { return m_desc.supervision_timeout; } /** @brief Gets the allowable latency for this connection (unit = number of intervals) */ - uint16_t getConnLatency() { return m_desc.conn_latency; } + uint16_t getConnLatency() const { return m_desc.conn_latency; } /** @brief Gets the maximum transmission unit size for this connection (in bytes) */ - uint16_t getMTU() { return ble_att_mtu(m_desc.conn_handle); } + uint16_t getMTU() const { return ble_att_mtu(m_desc.conn_handle); } /** @brief Check if we are in the master role in this connection */ - bool isMaster() { return (m_desc.role == BLE_GAP_ROLE_MASTER); } + bool isMaster() const { return (m_desc.role == BLE_GAP_ROLE_MASTER); } /** @brief Check if we are in the slave role in this connection */ - bool isSlave() { return (m_desc.role == BLE_GAP_ROLE_SLAVE); } + bool isSlave() const { return (m_desc.role == BLE_GAP_ROLE_SLAVE); } /** @brief Check if we are connected to a bonded peer */ - bool isBonded() { return (m_desc.sec_state.bonded == 1); } + bool isBonded() const { return (m_desc.sec_state.bonded == 1); } /** @brief Check if the connection in encrypted */ - bool isEncrypted() { return (m_desc.sec_state.encrypted == 1); } + bool isEncrypted() const { return (m_desc.sec_state.encrypted == 1); } /** @brief Check if the the connection has been authenticated */ - bool isAuthenticated() { return (m_desc.sec_state.authenticated == 1); } + bool isAuthenticated() const { return (m_desc.sec_state.authenticated == 1); } /** @brief Gets the key size used to encrypt the connection */ uint8_t getSecKeySize() { return m_desc.sec_state.key_size; } diff --git a/src/NimBLEDevice.cpp b/src/NimBLEDevice.cpp index 3e260cf0..42449530 100644 --- a/src/NimBLEDevice.cpp +++ b/src/NimBLEDevice.cpp @@ -23,7 +23,9 @@ # include "esp_bt.h" # include "nvs_flash.h" # if defined(CONFIG_NIMBLE_CPP_IDF) -# include "esp_nimble_hci.h" +# if (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0) || CONFIG_BT_NIMBLE_LEGACY_VHCI_ENABLE) +# include "esp_nimble_hci.h" +# endif # include "nimble/nimble_port.h" # include "nimble/nimble_port_freertos.h" # include "host/ble_hs.h" @@ -1154,6 +1156,43 @@ int NimBLEDevice::startSecurity(uint16_t conn_id) { } // startSecurity +/** + * @brief Inject the provided passkey into the Security Manager + * @param [in] peerInfo Connection information for the peer + * @param [in] pin The 6-digit pin to inject + * @return true if the passkey was injected successfully. + */ +bool NimBLEDevice::injectPassKey(const NimBLEConnInfo& peerInfo, uint32_t pin) { + int rc = 0; + struct ble_sm_io pkey = {0,0}; + + pkey.action = BLE_SM_IOACT_INPUT; + pkey.passkey = pin; + + rc = ble_sm_inject_io(peerInfo.getConnHandle(), &pkey); + NIMBLE_LOGD(LOG_TAG, "BLE_SM_IOACT_INPUT; ble_sm_inject_io result: %d", rc); + return rc == 0; +} + + +/** + * @brief Inject the provided numeric comparison response into the Security Manager + * @param [in] peerInfo Connection information for the peer + * @param [in] accept Whether the user confirmed or declined the comparison + */ +bool NimBLEDevice::injectConfirmPIN(const NimBLEConnInfo& peerInfo, bool accept) { + int rc = 0; + struct ble_sm_io pkey = {0,0}; + + pkey.action = BLE_SM_IOACT_NUMCMP; + pkey.numcmp_accept = accept; + + rc = ble_sm_inject_io(peerInfo.getConnHandle(), &pkey); + NIMBLE_LOGD(LOG_TAG, "BLE_SM_IOACT_NUMCMP; ble_sm_inject_io result: %d", rc); + return rc == 0; +} + + /** * @brief Check if the device address is on our ignore list. * @param [in] address The address to look for. diff --git a/src/NimBLEDevice.h b/src/NimBLEDevice.h index 4fdb25de..64bd4ed3 100644 --- a/src/NimBLEDevice.h +++ b/src/NimBLEDevice.h @@ -136,6 +136,8 @@ class NimBLEDevice { static void setSecurityPasskey(uint32_t pin); static uint32_t getSecurityPasskey(); static int startSecurity(uint16_t conn_id); + static bool injectConfirmPIN(const NimBLEConnInfo& peerInfo, bool accept); + static bool injectPassKey(const NimBLEConnInfo& peerInfo, uint32_t pin); static int setMTU(uint16_t mtu); static uint16_t getMTU(); static bool isIgnored(const NimBLEAddress &address); diff --git a/src/NimBLEServer.cpp b/src/NimBLEServer.cpp index daa5f235..243ac246 100644 --- a/src/NimBLEServer.cpp +++ b/src/NimBLEServer.cpp @@ -263,6 +263,7 @@ void NimBLEServer::advertiseOnDisconnect(bool aod) { } // advertiseOnDisconnect #endif + /** * @brief Return the number of connected clients. * @return The number of connected clients. @@ -528,19 +529,20 @@ int NimBLEServer::handleGapEvent(struct ble_gap_event *event, void *arg) { // if the (static)passkey is the default, check the callback for custom value // both values default to the same. if(pkey.passkey == 123456) { - pkey.passkey = pServer->m_pServerCallbacks->onPassKeyRequest(); + pkey.passkey = pServer->m_pServerCallbacks->onPassKeyDisplay(); } rc = ble_sm_inject_io(event->passkey.conn_handle, &pkey); NIMBLE_LOGD(LOG_TAG, "BLE_SM_IOACT_DISP; ble_sm_inject_io result: %d", rc); } else if (event->passkey.params.action == BLE_SM_IOACT_NUMCMP) { NIMBLE_LOGD(LOG_TAG, "Passkey on device's display: %" PRIu32, event->passkey.params.numcmp); - pkey.action = event->passkey.params.action; - pkey.numcmp_accept = pServer->m_pServerCallbacks->onConfirmPIN(event->passkey.params.numcmp); - rc = ble_sm_inject_io(event->passkey.conn_handle, &pkey); - NIMBLE_LOGD(LOG_TAG, "BLE_SM_IOACT_NUMCMP; ble_sm_inject_io result: %d", rc); + rc = ble_gap_conn_find(event->passkey.conn_handle, &peerInfo.m_desc); + if(rc != 0) { + return BLE_ATT_ERR_INVALID_HANDLE; + } + pServer->m_pServerCallbacks->onConfirmPIN(peerInfo, event->passkey.params.numcmp); //TODO: Handle out of band pairing } else if (event->passkey.params.action == BLE_SM_IOACT_OOB) { static uint8_t tem_oob[16] = {0}; @@ -551,14 +553,6 @@ int NimBLEServer::handleGapEvent(struct ble_gap_event *event, void *arg) { rc = ble_sm_inject_io(event->passkey.conn_handle, &pkey); NIMBLE_LOGD(LOG_TAG, "BLE_SM_IOACT_OOB; ble_sm_inject_io result: %d", rc); ////////////////////////////////// - } else if (event->passkey.params.action == BLE_SM_IOACT_INPUT) { - NIMBLE_LOGD(LOG_TAG, "Enter the passkey"); - pkey.action = event->passkey.params.action; - pkey.passkey = pServer->m_pServerCallbacks->onPassKeyRequest(); - - rc = ble_sm_inject_io(event->passkey.conn_handle, &pkey); - NIMBLE_LOGD(LOG_TAG, "BLE_SM_IOACT_INPUT; ble_sm_inject_io result: %d", rc); - } else if (event->passkey.params.action == BLE_SM_IOACT_NONE) { NIMBLE_LOGD(LOG_TAG, "No passkey action required"); } @@ -851,18 +845,18 @@ void NimBLEServerCallbacks::onMTUChange(uint16_t MTU, NimBLEConnInfo& connInfo) NIMBLE_LOGD("NimBLEServerCallbacks", "onMTUChange(): Default"); } // onMTUChange -uint32_t NimBLEServerCallbacks::onPassKeyRequest(){ - NIMBLE_LOGD("NimBLEServerCallbacks", "onPassKeyRequest: default: 123456"); +uint32_t NimBLEServerCallbacks::onPassKeyDisplay(){ + NIMBLE_LOGD("NimBLEServerCallbacks", "onPassKeyDisplay: default: 123456"); return 123456; -} //onPassKeyRequest +} //onPassKeyDisplay -void NimBLEServerCallbacks::onAuthenticationComplete(NimBLEConnInfo& connInfo){ - NIMBLE_LOGD("NimBLEServerCallbacks", "onAuthenticationComplete: default"); -} // onAuthenticationComplete - -bool NimBLEServerCallbacks::onConfirmPIN(uint32_t pin){ +void NimBLEServerCallbacks::onConfirmPIN(const NimBLEConnInfo& connInfo, uint32_t pin){ NIMBLE_LOGD("NimBLEServerCallbacks", "onConfirmPIN: default: true"); - return true; + NimBLEDevice::injectConfirmPIN(connInfo, true); } // onConfirmPIN +void NimBLEServerCallbacks::onAuthenticationComplete(const NimBLEConnInfo& connInfo){ + NIMBLE_LOGD("NimBLEServerCallbacks", "onAuthenticationComplete: default"); +} // onAuthenticationComplete + #endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */ diff --git a/src/NimBLEServer.h b/src/NimBLEServer.h index ea56ed73..5e635df7 100644 --- a/src/NimBLEServer.h +++ b/src/NimBLEServer.h @@ -152,24 +152,25 @@ class NimBLEServerCallbacks { virtual void onMTUChange(uint16_t MTU, NimBLEConnInfo& connInfo); /** - * @brief Called when a client requests a passkey for pairing. + * @brief Called when a client requests a passkey for pairing (display). * @return The passkey to be sent to the client. */ - virtual uint32_t onPassKeyRequest(); + virtual uint32_t onPassKeyDisplay(); /** - * @brief Called when the pairing procedure is complete. + * @brief Called when using numeric comparision for pairing. * @param [in] connInfo A reference to a NimBLEConnInfo instance with information - * about the peer connection parameters. + * Should be passed back to NimBLEDevice::injectConfirmPIN + * @param [in] pin The pin to compare with the client. */ - virtual void onAuthenticationComplete(NimBLEConnInfo& connInfo); + virtual void onConfirmPIN(const NimBLEConnInfo& connInfo, uint32_t pin); /** - * @brief Called when using numeric comparision for pairing. - * @param [in] pin The pin to compare with the client. - * @return True to accept the pin. + * @brief Called when the pairing procedure is complete. + * @param [in] connInfo A reference to a NimBLEConnInfo instance with information + * about the peer connection parameters. */ - virtual bool onConfirmPIN(uint32_t pin); + virtual void onAuthenticationComplete(const NimBLEConnInfo& connInfo); }; // NimBLEServerCallbacks #endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */