Skip to content

Commit fb2b817

Browse files
author
unknownconstant
committed
Merge branch 'master' into secure-random
2 parents d9fb4bc + 283038f commit fb2b817

File tree

10 files changed

+292
-131
lines changed

10 files changed

+292
-131
lines changed

examples/Peripheral/EncryptedBatteryMonitor/EncryptedBatteryMonitor.ino

+48-19
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,14 @@
1818
#include <ArduinoBLE.h>
1919

2020

21+
#define PAIR_BUTTON D3 // button for pairing
22+
#define PAIR_LED 24 // LED used to signal pairing
23+
#define PAIR_LED_ON LOW // Blue LED on Nano BLE has inverted logic
24+
#define PAIR_INTERVAL 30000 // interval for pairing after button press in ms
25+
26+
#define CTRL_LED LED_BUILTIN
27+
28+
2129
// BLE Battery Service
2230
BLEService batteryService("180F");
2331

@@ -31,13 +39,17 @@ BLEStringCharacteristic stringcharacteristic("183E", BLERead | BLEWrite, 31);
3139
BLEUnsignedCharCharacteristic secretValue("2a3F", BLERead | BLEWrite | BLEEncryption);
3240

3341
int oldBatteryLevel = 0; // last battery level reading from analog input
34-
long previousMillis = 0; // last time the battery level was checked, in ms
42+
unsigned long previousMillis = 0; // last time the battery level was checked, in ms
43+
unsigned long pairingStarted = 0; // pairing start time when button is pressed
44+
bool wasConnected = 0;
3545

3646
void setup() {
3747
Serial.begin(9600); // initialize serial communication
3848
while (!Serial);
3949

40-
pinMode(LED_BUILTIN, OUTPUT); // initialize the built-in LED pin to indicate when a central is connected
50+
pinMode(CTRL_LED, OUTPUT); // initialize the built-in LED pin to indicate when a central is connected
51+
pinMode(PAIR_LED, OUTPUT);
52+
pinMode(PAIR_BUTTON, INPUT_PULLUP);
4153

4254

4355
Serial.println("Serial connected");
@@ -145,6 +157,9 @@ void setup() {
145157
secretValue.writeValue(0);
146158

147159
delay(1000);
160+
161+
// prevent pairing until button is pressed (will show a pairing rejected message)
162+
BLE.setPairable(false);
148163

149164
/* Start advertising BLE. It will start continuously transmitting BLE
150165
advertising packets and will be visible to remote BLE central devices
@@ -169,30 +184,44 @@ void loop() {
169184
// wait for a BLE central
170185
BLEDevice central = BLE.central();
171186

187+
188+
// If button is pressed, allow pairing for 30 sec
189+
if (!BLE.pairable() && digitalRead(PAIR_BUTTON) == LOW){
190+
pairingStarted = millis();
191+
BLE.setPairable(Pairable::ONCE);
192+
Serial.println("Accepting pairing for 30s");
193+
} else if (BLE.pairable() && millis() > pairingStarted + PAIR_INTERVAL){
194+
BLE.setPairable(false);
195+
Serial.println("No longer accepting pairing");
196+
}
197+
// Make LED blink while pairing is allowed
198+
digitalWrite(PAIR_LED, (BLE.pairable() ? (millis()%400)<200 : BLE.paired()) ? PAIR_LED_ON : !PAIR_LED_ON);
199+
200+
172201
// if a central is connected to the peripheral:
173-
if (central) {
174-
Serial.print("Connected to central: ");
175-
// print the central's BT address:
176-
Serial.println(central.address());
202+
if (central && central.connected()) {
203+
if (!wasConnected){
204+
wasConnected = true;
205+
Serial.print("Connected to central: ");
206+
// print the central's BT address:
207+
Serial.println(central.address());
208+
}
177209

178210
// check the battery level every 200ms
179211
// while the central is connected:
180-
while (central.connected()) {
181-
long currentMillis = millis();
182-
// if 200ms have passed, check the battery level:
183-
if (currentMillis - previousMillis >= 1000) {
184-
previousMillis = currentMillis;
185-
updateBatteryLevel();
186-
if(secretValue.value()>0){
187-
digitalWrite(13,HIGH);
188-
}else{
189-
digitalWrite(13,LOW);
190-
}
191-
}
212+
long currentMillis = millis();
213+
// if 200ms have passed, check the battery level:
214+
if (currentMillis - previousMillis >= 1000) {
215+
previousMillis = currentMillis;
216+
updateBatteryLevel();
217+
digitalWrite(CTRL_LED, secretValue.value()>0 ? HIGH : LOW);
192218
}
219+
} else if (wasConnected){
220+
wasConnected = false;
193221
Serial.print("Disconnected from central: ");
194222
Serial.println(central.address());
195223
}
224+
196225
}
197226

198227
void updateBatteryLevel() {
@@ -208,4 +237,4 @@ void updateBatteryLevel() {
208237
batteryLevelChar.writeValue(batteryLevel); // and update the battery level characteristic
209238
oldBatteryLevel = batteryLevel; // save the level for next comparison
210239
}
211-
}
240+
}

keywords.txt

+3
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,12 @@ setEventHandler KEYWORD2
7777
setAdvertisingInterval KEYWORD2
7878
setConnectionInterval KEYWORD2
7979
setConnectable KEYWORD2
80+
setPairable KEYWORD2
8081
setTimeout KEYWORD2
8182
debug KEYWORD2
8283
noDebug KEYWORD2
84+
pairable KEYWORD2
85+
paired KEYWORD2
8386

8487
properties KEYWORD2
8588
valueSize KEYWORD2

src/local/BLELocalDevice.cpp

+26
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,16 @@ bool BLELocalDevice::connected() const
214214
return ATT.connected();
215215
}
216216

217+
/*
218+
* Whether there is at least one paired device
219+
*/
220+
bool BLELocalDevice::paired()
221+
{
222+
HCI.poll();
223+
224+
return ATT.paired();
225+
}
226+
217227
bool BLELocalDevice::disconnect()
218228
{
219229
return ATT.disconnect();
@@ -395,6 +405,22 @@ void BLELocalDevice::setTimeout(unsigned long timeout)
395405
ATT.setTimeout(timeout);
396406
}
397407

408+
/*
409+
* Control whether pairing is allowed or rejected
410+
* Use true/false or the Pairable enum
411+
*/
412+
void BLELocalDevice::setPairable(uint8_t pairable)
413+
{
414+
L2CAPSignaling.setPairingEnabled(pairable);
415+
}
416+
417+
/*
418+
* Whether pairing is currently allowed
419+
*/
420+
bool BLELocalDevice::pairable()
421+
{
422+
return L2CAPSignaling.isPairingEnabled();
423+
}
398424

399425
void BLELocalDevice::setGetIRKs(int (*getIRKs)(uint8_t* nIRKs, uint8_t** BADDR_type, uint8_t*** BADDRs, uint8_t*** IRKs)){
400426
HCI._getIRKs = getIRKs;

src/local/BLELocalDevice.h

+10
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@
2424
#include "BLEService.h"
2525
#include "BLEAdvertisingData.h"
2626

27+
enum Pairable {
28+
NO = 0,
29+
YES = 1,
30+
ONCE = 2,
31+
};
32+
2733
class BLELocalDevice {
2834
public:
2935
BLELocalDevice();
@@ -80,6 +86,10 @@ class BLELocalDevice {
8086

8187
virtual void debug(Stream& stream);
8288
virtual void noDebug();
89+
90+
virtual void setPairable(uint8_t pairable);
91+
virtual bool pairable();
92+
virtual bool paired();
8393

8494
// address - The mac to store
8595
// IRK - The IRK to store with this mac

src/utility/ATT.cpp

+26
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,32 @@ bool ATTClass::connected(uint16_t handle) const
497497
return false;
498498
}
499499

500+
/*
501+
* Return true if any of the known devices is paired (peer encrypted)
502+
* Does not check if the paired device is also connected
503+
*/
504+
bool ATTClass::paired() const
505+
{
506+
for(int i=0; i<ATT_MAX_PEERS; i++){
507+
if((_peers[i].encryption & PEER_ENCRYPTION::ENCRYPTED_AES) > 0){
508+
return true;
509+
}
510+
}
511+
return false;
512+
}
513+
514+
/*
515+
* Return true if the specified device is paired (peer encrypted)
516+
*/
517+
bool ATTClass::paired(uint16_t handle) const
518+
{
519+
for(int i=0; i<ATT_MAX_PEERS; i++){
520+
if(_peers[i].connectionHandle != handle){continue;}
521+
return (_peers[i].encryption & PEER_ENCRYPTION::ENCRYPTED_AES) > 0;
522+
}
523+
return false; // unknown handle
524+
}
525+
500526
uint16_t ATTClass::mtu(uint16_t handle) const
501527
{
502528
for (int i = 0; i < ATT_MAX_PEERS; i++) {

src/utility/ATT.h

+2
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ class ATTClass {
7575
virtual bool connected() const;
7676
virtual bool connected(uint8_t addressType, const uint8_t address[6]) const;
7777
virtual bool connected(uint16_t handle) const;
78+
virtual bool paired() const;
79+
virtual bool paired(uint16_t handle) const;
7880
virtual uint16_t mtu(uint16_t handle) const;
7981

8082
virtual bool disconnect();

src/utility/HCI.cpp

+12-4
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
#include "bitDescriptions.h"
2727
// #define _BLE_TRACE_
2828

29+
//#define _BLE_TRACE_
30+
2931
#define HCI_COMMAND_PKT 0x01
3032
#define HCI_ACLDATA_PKT 0x02
3133
#define HCI_EVENT_PKT 0x04
@@ -1350,23 +1352,29 @@ void HCIClass::handleEventPkt(uint8_t /*plen*/, uint8_t pdata[])
13501352
break;
13511353
}
13521354

1353-
uint8_t encryption = ATT.getPeerEncryption(connectionHandle);
13541355

13551356
for(int i=0; i<32; i++) DHKey[31-i] = evtLeDHKeyComplete->DHKey[i];
13561357

13571358
#ifdef _BLE_TRACE_
13581359
Serial.println("Stored our DHKey:");
13591360
btct.printBytes(DHKey,32);
13601361
#endif
1361-
encryption |= PEER_ENCRYPTION::DH_KEY_CALULATED;
1362+
uint8_t encryption = ATT.getPeerEncryption(connectionHandle) | PEER_ENCRYPTION::DH_KEY_CALULATED;
13621363
ATT.setPeerEncryption(connectionHandle, encryption);
1364+
1365+
if((encryption & PEER_ENCRYPTION::RECEIVED_DH_CHECK) > 0){
13631366
#ifdef _BLE_TRACE_
1364-
if(encryption | PEER_ENCRYPTION::RECEIVED_DH_CHECK){
1365-
Serial.println("Recieved DHKey check already so calculate f5, f6.");
1367+
Serial.println("Recieved DHKey check already so calculate f5, f6 now.");
1368+
#endif
1369+
L2CAPSignaling.smCalculateLTKandConfirm(connectionHandle, HCI.remoteDHKeyCheckBuffer);
1370+
13661371
}else{
1372+
#ifdef _BLE_TRACE_
13671373
Serial.println("Waiting on other DHKey check before calculating.");
1374+
#endif
13681375
}
13691376
}else{
1377+
#ifdef _BLE_TRACE_
13701378
Serial.print("Key generation error: 0x");
13711379
Serial.println(evtLeDHKeyComplete->status, HEX);
13721380
#endif

src/utility/HCI.h

+3
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
#include <Arduino.h>
2424
#include "bitDescriptions.h"
2525

26+
#include "L2CAPSignaling.h"
27+
2628
#define OGF_LINK_CTL 0x01
2729
#define OGF_HOST_CTL 0x03
2830
#define OGF_INFO_PARAM 0x04
@@ -117,6 +119,7 @@ class HCIClass {
117119
// TODO: Send command be private again & use ATT implementation of send command within ATT.
118120
virtual int sendCommand(uint16_t opcode, uint8_t plen = 0, void* parameters = NULL);
119121
uint8_t remotePublicKeyBuffer[64];
122+
uint8_t remoteDHKeyCheckBuffer[16];
120123
uint8_t Na[16];
121124
uint8_t Nb[16];
122125
uint8_t DHKey[32];

0 commit comments

Comments
 (0)