Skip to content

Commit

Permalink
[BREAKING] Asynchronous pin injections for Numeric Comparison and Pas…
Browse files Browse the repository at this point in the history
…sKey Input

* Make NimBLEConnInfo functions const.

* Update callback functions and update client to use new functions.

* Update examples.

* Update migration guide.

---------

Co-authored-by: Casey Smith <[email protected]>
  • Loading branch information
h2zero and csmith-morningstar committed Jun 8, 2024
1 parent 27d3253 commit 643ce46
Show file tree
Hide file tree
Showing 15 changed files with 214 additions and 162 deletions.
17 changes: 11 additions & 6 deletions docs/Migration_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
<br/>

> `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);`
<br/>

> `void onAuthenticationComplete(NimBLEConnInfo& connInfo)`
> `uint32_t onPassKeyDisplay()`
Server callback; should return the passkey (pin) expected from the client.
<br/>

> `void onAuthenticationComplete(const NimBLEConnInfo& connInfo)`
Authentication complete, success or failed information is available from the `NimBLEConnInfo` methods.
<br/>
Expand Down
27 changes: 14 additions & 13 deletions examples/NimBLE_Client/NimBLE_Client.ino
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
};
}
};


Expand Down
4 changes: 2 additions & 2 deletions examples/NimBLE_Secure_Client/NimBLE_Secure_Client.ino
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
12 changes: 6 additions & 6 deletions examples/NimBLE_Server/NimBLE_Server.ino
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down
13 changes: 7 additions & 6 deletions examples/Refactored_original_examples/BLE_client/BLE_client.ino
Original file line number Diff line number Diff line change
Expand Up @@ -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!");
}
/*******************************************************************/
Expand Down
44 changes: 24 additions & 20 deletions examples/Refactored_original_examples/BLE_notify/BLE_notify.ino
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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!");
}
/*******************************************************************/
};

Expand All @@ -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 |
Expand All @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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!");
}
/*******************************************************************/
Expand All @@ -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 |
Expand All @@ -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());
****************************************************/

Expand Down
42 changes: 23 additions & 19 deletions examples/Refactored_original_examples/BLE_uart/BLE_uart.ino
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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 **/
Expand Down Expand Up @@ -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;
Expand All @@ -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!");
}
/*******************************************************************/
Expand Down Expand Up @@ -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
);

Expand Down
Loading

0 comments on commit 643ce46

Please sign in to comment.