Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 3f549d3

Browse files
Test IDF call
1 parent 8af12a5 commit 3f549d3

File tree

7 files changed

+512
-0
lines changed

7 files changed

+512
-0
lines changed
Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
1+
/*
2+
Secure client with static passkey
3+
4+
This example demonstrates how to create a secure BLE client that connects to
5+
a secure BLE server using a static passkey without prompting the user.
6+
The client will automatically use the same passkey (123456) as the server.
7+
8+
This client is designed to work with the Server_secure_static_passkey example.
9+
10+
Note that ESP32 uses Bluedroid by default and the other SoCs use NimBLE.
11+
Bluedroid initiates security on-connect, while NimBLE initiates security on-demand.
12+
This means that in NimBLE you can read the unsecure characteristic without entering
13+
the passkey. This is not possible in Bluedroid.
14+
15+
Also, the SoC stores the authentication info in the NVS memory. After a successful
16+
connection it is possible that a passkey change will be ineffective.
17+
To avoid this, clear the memory of the SoC's between security tests.
18+
19+
Based on examples from Neil Kolban and h2zero.
20+
Created by lucasssvaz.
21+
*/
22+
23+
#include "BLEDevice.h"
24+
#include "BLESecurity.h"
25+
26+
// The remote service we wish to connect to.
27+
static BLEUUID serviceUUID("4fafc201-1fb5-459e-8fcc-c5c9c331914b");
28+
// The characteristics of the remote service we are interested in.
29+
static BLEUUID unsecureCharUUID("beb5483e-36e1-4688-b7f5-ea07361b26a8");
30+
static BLEUUID secureCharUUID("ff1d2614-e2d6-4c87-9154-6625d39ca7f8");
31+
32+
// This must match the server's passkey
33+
#define CLIENT_PIN 123456
34+
35+
static boolean doConnect = false;
36+
static boolean connected = false;
37+
static boolean doScan = false;
38+
static BLERemoteCharacteristic *pRemoteUnsecureCharacteristic;
39+
static BLERemoteCharacteristic *pRemoteSecureCharacteristic;
40+
static BLEAdvertisedDevice *myDevice;
41+
42+
// Callback function to handle notifications
43+
static void notifyCallback(BLERemoteCharacteristic *pBLERemoteCharacteristic, uint8_t *pData, size_t length, bool isNotify) {
44+
Serial.print("Notify callback for characteristic ");
45+
Serial.print(pBLERemoteCharacteristic->getUUID().toString().c_str());
46+
Serial.print(" of data length ");
47+
Serial.println(length);
48+
Serial.print("data: ");
49+
Serial.write(pData, length);
50+
Serial.println();
51+
}
52+
53+
class MyClientCallback : public BLEClientCallbacks {
54+
void onConnect(BLEClient *pclient) {
55+
Serial.println("Connected to secure server");
56+
}
57+
58+
void onDisconnect(BLEClient *pclient) {
59+
connected = false;
60+
Serial.println("Disconnected from server");
61+
}
62+
};
63+
64+
bool connectToServer() {
65+
Serial.print("Forming a secure connection to ");
66+
Serial.println(myDevice->getAddress().toString().c_str());
67+
68+
BLEClient *pClient = BLEDevice::createClient();
69+
Serial.println(" - Created client");
70+
71+
pClient->setClientCallbacks(new MyClientCallback());
72+
73+
// Connect to the remote BLE Server.
74+
pClient->connect(myDevice);
75+
Serial.println(" - Connected to server");
76+
77+
// Set MTU to maximum for better performance
78+
pClient->setMTU(517);
79+
80+
// Obtain a reference to the service we are after in the remote BLE server.
81+
BLERemoteService *pRemoteService = pClient->getService(serviceUUID);
82+
if (pRemoteService == nullptr) {
83+
Serial.print("Failed to find our service UUID: ");
84+
Serial.println(serviceUUID.toString().c_str());
85+
pClient->disconnect();
86+
return false;
87+
}
88+
Serial.println(" - Found our service");
89+
90+
// Obtain a reference to the unsecure characteristic
91+
pRemoteUnsecureCharacteristic = pRemoteService->getCharacteristic(unsecureCharUUID);
92+
if (pRemoteUnsecureCharacteristic == nullptr) {
93+
Serial.print("Failed to find unsecure characteristic UUID: ");
94+
Serial.println(unsecureCharUUID.toString().c_str());
95+
pClient->disconnect();
96+
return false;
97+
}
98+
Serial.println(" - Found unsecure characteristic");
99+
100+
// Obtain a reference to the secure characteristic
101+
pRemoteSecureCharacteristic = pRemoteService->getCharacteristic(secureCharUUID);
102+
if (pRemoteSecureCharacteristic == nullptr) {
103+
Serial.print("Failed to find secure characteristic UUID: ");
104+
Serial.println(secureCharUUID.toString().c_str());
105+
pClient->disconnect();
106+
return false;
107+
}
108+
Serial.println(" - Found secure characteristic");
109+
110+
// Read the value of the unsecure characteristic (should work without authentication)
111+
if (pRemoteUnsecureCharacteristic->canRead()) {
112+
String value = pRemoteUnsecureCharacteristic->readValue();
113+
Serial.print("Unsecure characteristic value: ");
114+
Serial.println(value.c_str());
115+
}
116+
117+
// For Bluedroid, we need to set the authentication request type for the secure characteristic
118+
// This is not needed for NimBLE and will be ignored.
119+
pRemoteSecureCharacteristic->setAuth(ESP_GATT_AUTH_REQ_MITM);
120+
121+
// Try to read the secure characteristic (this will trigger security negotiation in NimBLE)
122+
if (pRemoteSecureCharacteristic->canRead()) {
123+
Serial.println("Attempting to read secure characteristic...");
124+
String value = pRemoteSecureCharacteristic->readValue();
125+
Serial.print("Secure characteristic value: ");
126+
Serial.println(value.c_str());
127+
}
128+
129+
// Register for notifications on both characteristics if they support it
130+
if (pRemoteUnsecureCharacteristic->canNotify()) {
131+
pRemoteUnsecureCharacteristic->registerForNotify(notifyCallback);
132+
Serial.println(" - Registered for unsecure characteristic notifications");
133+
}
134+
135+
if (pRemoteSecureCharacteristic->canNotify()) {
136+
pRemoteSecureCharacteristic->registerForNotify(notifyCallback);
137+
Serial.println(" - Registered for secure characteristic notifications");
138+
}
139+
140+
connected = true;
141+
return true;
142+
}
143+
144+
/**
145+
* Scan for BLE servers and find the first one that advertises the service we are looking for.
146+
*/
147+
class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks {
148+
/**
149+
* Called for each advertising BLE server.
150+
*/
151+
void onResult(BLEAdvertisedDevice advertisedDevice) {
152+
Serial.print("BLE Advertised Device found: ");
153+
Serial.println(advertisedDevice.toString().c_str());
154+
155+
// We have found a device, let us now see if it contains the service we are looking for.
156+
if (advertisedDevice.haveServiceUUID() && advertisedDevice.isAdvertisingService(serviceUUID)) {
157+
Serial.println("Found our secure server!");
158+
BLEDevice::getScan()->stop();
159+
myDevice = new BLEAdvertisedDevice(advertisedDevice);
160+
doConnect = true;
161+
doScan = true;
162+
}
163+
}
164+
};
165+
166+
void setup() {
167+
Serial.begin(115200);
168+
Serial.println("Starting Secure BLE Client application...");
169+
170+
BLEDevice::init("Secure BLE Client");
171+
172+
// Set up security with the same passkey as the server
173+
BLESecurity *pSecurity = new BLESecurity();
174+
175+
// Set security parameters
176+
// Deafult parameters:
177+
// - IO capability is set to NONE
178+
// - Initiator and responder key distribution flags are set to both encryption and identity keys.
179+
// - Passkey is set to BLE_SM_DEFAULT_PASSKEY (123456). It will warn if you don't change it.
180+
// - Max key size is set to 16 bytes
181+
182+
// Set the same static passkey as the server
183+
// The first argument defines if the passkey is static or random.
184+
// The second argument is the passkey (ignored when using a random passkey).
185+
pSecurity->setPassKey(true, CLIENT_PIN);
186+
187+
// Set authentication mode to match server requirements
188+
// Enable bonding, with MITM and secure connection
189+
pSecurity->setAuthenticationMode(true, true, true);
190+
191+
// Retrieve a Scanner and set the callback we want to use to be informed when we
192+
// have detected a new device. Specify that we want active scanning and start the
193+
// scan to run for 5 seconds.
194+
BLEScan *pBLEScan = BLEDevice::getScan();
195+
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
196+
pBLEScan->setInterval(1349);
197+
pBLEScan->setWindow(449);
198+
pBLEScan->setActiveScan(true);
199+
pBLEScan->start(5, false);
200+
}
201+
202+
void loop() {
203+
// If the flag "doConnect" is true then we have scanned for and found the desired
204+
// BLE Server with which we wish to connect. Now we connect to it.
205+
if (doConnect == true) {
206+
if (connectToServer()) {
207+
Serial.println("We are now connected to the secure BLE Server.");
208+
} else {
209+
Serial.println("We have failed to connect to the server; there is nothing more we will do.");
210+
}
211+
doConnect = false;
212+
}
213+
214+
// If we are connected to a peer BLE Server, demonstrate secure communication
215+
if (connected) {
216+
// Write to the unsecure characteristic
217+
String unsecureValue = "Client time: " + String(millis() / 1000);
218+
if (pRemoteUnsecureCharacteristic->canWrite()) {
219+
pRemoteUnsecureCharacteristic->writeValue(unsecureValue.c_str(), unsecureValue.length());
220+
Serial.println("Wrote to unsecure characteristic: " + unsecureValue);
221+
}
222+
223+
// Write to the secure characteristic
224+
String secureValue = "Secure client time: " + String(millis() / 1000);
225+
if (pRemoteSecureCharacteristic->canWrite()) {
226+
pRemoteSecureCharacteristic->writeValue(secureValue.c_str(), secureValue.length());
227+
Serial.println("Wrote to secure characteristic: " + secureValue);
228+
}
229+
} else if (doScan) {
230+
// Restart scanning if we're disconnected
231+
BLEDevice::getScan()->start(0);
232+
}
233+
234+
delay(2000); // Delay 2 seconds between loops
235+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"fqbn_append": "PartitionScheme=huge_app",
3+
"requires": [
4+
"CONFIG_SOC_BLE_SUPPORTED=y"
5+
]
6+
}
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
/*
2+
BLE Server Authorization Test
3+
4+
This example demonstrates how to use authorization in both NimBLE and Bluedroid.
5+
The server creates a service with two characteristics:
6+
- One characteristic that requires read/write authorization
7+
- One characteristic that does not require authorization
8+
9+
When authorization is required, the server will call the onAuthorizationRequest callback.
10+
This example shows a simple authorization logic that accepts requests from connection handle 0
11+
and rejects requests from all other connection handles.
12+
13+
In a real application, you would implement more sophisticated authorization logic
14+
based on your security requirements.
15+
16+
This example works with both NimBLE and Bluedroid implementations.
17+
18+
Created by lucasssvaz.
19+
*/
20+
21+
#include <BLEDevice.h>
22+
#include <BLEUtils.h>
23+
#include <BLEServer.h>
24+
#include <BLESecurity.h>
25+
#include <string>
26+
27+
#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
28+
#define OPEN_CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
29+
#define AUTHORIZED_CHARACTERISTIC_UUID "ff1d2614-e2d6-4c87-9154-6625d39ca7f8"
30+
31+
class MySecurityCallbacks : public BLESecurityCallbacks {
32+
public:
33+
bool onAuthorizationRequest(uint16_t connHandle, uint16_t attrHandle, bool isRead) override {
34+
Serial.printf("Authorization request: conn_handle=%d, attr_handle=%d, is_read=%s\n",
35+
connHandle, attrHandle, isRead ? "true" : "false");
36+
37+
// Simple authorization logic: allow only connection handle 0
38+
// In a real application, you would implement more sophisticated logic
39+
bool authorized = (connHandle == 0);
40+
41+
Serial.printf("Authorization %s for connection handle %d\n",
42+
authorized ? "granted" : "denied", connHandle);
43+
44+
return authorized;
45+
}
46+
};
47+
48+
class MyCharacteristicCallbacks : public BLECharacteristicCallbacks {
49+
void onWrite(BLECharacteristic* pCharacteristic) override {
50+
String value = pCharacteristic->getValue();
51+
Serial.printf("Characteristic written: UUID=%s, value=%s\n",
52+
pCharacteristic->getUUID().toString().c_str(), value.c_str());
53+
}
54+
55+
void onRead(BLECharacteristic* pCharacteristic) override {
56+
Serial.printf("Characteristic read: UUID=%s\n",
57+
pCharacteristic->getUUID().toString().c_str());
58+
}
59+
};
60+
61+
void setup() {
62+
Serial.begin(115200);
63+
Serial.println("Starting BLE Authorization Test Server!");
64+
65+
Serial.printf("Using BLE stack: %s\n", BLEDevice::getBLEStackString());
66+
67+
BLEDevice::init("Authorization Test Server");
68+
69+
// Set security callbacks
70+
BLEDevice::setSecurityCallbacks(new MySecurityCallbacks());
71+
72+
// Create the BLE Server
73+
BLEServer* pServer = BLEDevice::createServer();
74+
75+
// Create the BLE Service
76+
BLEService* pService = pServer->createService(SERVICE_UUID);
77+
78+
// Create open characteristic (no authorization required)
79+
BLECharacteristic* pOpenCharacteristic = pService->createCharacteristic(
80+
OPEN_CHARACTERISTIC_UUID,
81+
BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE
82+
);
83+
pOpenCharacteristic->setCallbacks(new MyCharacteristicCallbacks());
84+
pOpenCharacteristic->setValue("Open characteristic - no authorization required");
85+
86+
// Create authorized characteristic (authorization required for read/write)
87+
BLECharacteristic* pAuthorizedCharacteristic = pService->createCharacteristic(
88+
AUTHORIZED_CHARACTERISTIC_UUID,
89+
BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE
90+
);
91+
pAuthorizedCharacteristic->setCallbacks(new MyCharacteristicCallbacks());
92+
pAuthorizedCharacteristic->setValue("Authorized characteristic - authorization required");
93+
94+
// Set authorization permissions for the authorized characteristic
95+
#if defined(CONFIG_BLUEDROID_ENABLED)
96+
pAuthorizedCharacteristic->setAccessPermissions(ESP_GATT_PERM_READ_AUTHORIZATION | ESP_GATT_PERM_WRITE_AUTHORIZATION);
97+
Serial.println("Bluedroid: Set authorization permissions using setAccessPermissions()");
98+
#endif
99+
100+
#if defined(CONFIG_NIMBLE_ENABLED)
101+
// In NimBLE, authorization is controlled by the characteristic properties
102+
// The PROPERTY_READ_AUTHOR and PROPERTY_WRITE_AUTHOR flags trigger authorization
103+
pAuthorizedCharacteristic = pService->createCharacteristic(
104+
AUTHORIZED_CHARACTERISTIC_UUID,
105+
BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE |
106+
BLECharacteristic::PROPERTY_READ_AUTHOR | BLECharacteristic::PROPERTY_WRITE_AUTHOR
107+
);
108+
pAuthorizedCharacteristic->setCallbacks(new MyCharacteristicCallbacks());
109+
pAuthorizedCharacteristic->setValue("Authorized characteristic - authorization required");
110+
Serial.println("NimBLE: Set authorization permissions using PROPERTY_READ_AUTHOR and PROPERTY_WRITE_AUTHOR");
111+
#endif
112+
113+
// Start the service
114+
pService->start();
115+
116+
// Start advertising
117+
BLEAdvertising* pAdvertising = BLEDevice::getAdvertising();
118+
pAdvertising->addServiceUUID(SERVICE_UUID);
119+
pAdvertising->setScanResponse(false);
120+
pAdvertising->setMinPreferred(0x0); // Set value to 0x00 to not advertise this parameter
121+
122+
BLEDevice::startAdvertising();
123+
Serial.println("Waiting for client connection to test authorization...");
124+
Serial.println();
125+
Serial.println("Connect with a BLE client and try to:");
126+
Serial.println("1. Read/write the open characteristic (should work without authorization)");
127+
Serial.println("2. Read/write the authorized characteristic (will trigger authorization callback)");
128+
Serial.println();
129+
}
130+
131+
void loop() {
132+
// put your main code here, to run repeatedly:
133+
delay(2000);
134+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"targets": [
3+
"esp32",
4+
"esp32s3",
5+
"esp32c3",
6+
"esp32c6",
7+
"esp32h2"
8+
]
9+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /