Skip to content

Commit e5ccd3b

Browse files
author
unknownconstant
authored
Merge pull request #1 from unknownconstant/pairing
Initial - encrypted read
2 parents be365c9 + 9cde1de commit e5ccd3b

12 files changed

+1305
-84
lines changed

src/ArduinoBLE.h

+1
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,6 @@
2424
#include "BLEProperty.h"
2525
#include "BLEStringCharacteristic.h"
2626
#include "BLETypedCharacteristics.h"
27+
#include "utility/btct.h"
2728

2829
#endif

src/BLEProperty.h

+39-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1818
*/
1919

20+
// #include <stdint.h>
21+
2022
#ifndef _BLE_PROPERTY_H_
2123
#define _BLE_PROPERTY_H_
2224

@@ -26,7 +28,43 @@ enum BLEProperty {
2628
BLEWriteWithoutResponse = 0x04,
2729
BLEWrite = 0x08,
2830
BLENotify = 0x10,
29-
BLEIndicate = 0x20
31+
BLEIndicate = 0x20,
32+
BLEAuth = 1 << 6,
33+
BLEExtProp = 1 << 7,
34+
};
35+
36+
#define ESP_GATT_CHAR_PROP_BIT_BROADCAST (1 << 0) /* 0x01 */ /* relate to BTA_GATT_CHAR_PROP_BIT_BROADCAST in bta/bta_gatt_api.h */
37+
#define ESP_GATT_CHAR_PROP_BIT_READ (1 << 1) /* 0x02 */ /* relate to BTA_GATT_CHAR_PROP_BIT_READ in bta/bta_gatt_api.h */
38+
#define ESP_GATT_CHAR_PROP_BIT_WRITE_NR (1 << 2) /* 0x04 */ /* relate to BTA_GATT_CHAR_PROP_BIT_WRITE_NR in bta/bta_gatt_api.h */
39+
#define ESP_GATT_CHAR_PROP_BIT_WRITE (1 << 3) /* 0x08 */ /* relate to BTA_GATT_CHAR_PROP_BIT_WRITE in bta/bta_gatt_api.h */
40+
#define ESP_GATT_CHAR_PROP_BIT_NOTIFY (1 << 4) /* 0x10 */ /* relate to BTA_GATT_CHAR_PROP_BIT_NOTIFY in bta/bta_gatt_api.h */
41+
#define ESP_GATT_CHAR_PROP_BIT_INDICATE (1 << 5) /* 0x20 */ /* relate to BTA_GATT_CHAR_PROP_BIT_INDICATE in bta/bta_gatt_api.h */
42+
#define ESP_GATT_CHAR_PROP_BIT_AUTH (1 << 6) /* 0x40 */ /* relate to BTA_GATT_CHAR_PROP_BIT_AUTH in bta/bta_gatt_api.h */
43+
#define ESP_GATT_CHAR_PROP_BIT_EXT_PROP (1 << 7) /* 0x80 */ /* relate to BTA_GATT_CHAR_PROP_BIT_EXT_PROP in bta/bta_gatt_api.h */
44+
45+
#define ESP_GATT_PERM_READ (1 << 0) /* bit 0 - 0x0001 */ /* relate to BTA_GATT_PERM_READ in bta/bta_gatt_api.h */
46+
#define ESP_GATT_PERM_READ_ENCRYPTED (1 << 1) /* bit 1 - 0x0002 */ /* relate to BTA_GATT_PERM_READ_ENCRYPTED in bta/bta_gatt_api.h */
47+
#define ESP_GATT_PERM_READ_ENC_MITM (1 << 2) /* bit 2 - 0x0004 */ /* relate to BTA_GATT_PERM_READ_ENC_MITM in bta/bta_gatt_api.h */
48+
#define ESP_GATT_PERM_WRITE (1 << 4) /* bit 4 - 0x0010 */ /* relate to BTA_GATT_PERM_WRITE in bta/bta_gatt_api.h */
49+
#define ESP_GATT_PERM_WRITE_ENCRYPTED (1 << 5) /* bit 5 - 0x0020 */ /* relate to BTA_GATT_PERM_WRITE_ENCRYPTED in bta/bta_gatt_api.h */
50+
#define ESP_GATT_PERM_WRITE_ENC_MITM (1 << 6) /* bit 6 - 0x0040 */ /* relate to BTA_GATT_PERM_WRITE_ENC_MITM in bta/bta_gatt_api.h */
51+
#define ESP_GATT_PERM_WRITE_SIGNED (1 << 7) /* bit 7 - 0x0080 */ /* relate to BTA_GATT_PERM_WRITE_SIGNED in bta/bta_gatt_api.h */
52+
#define ESP_GATT_PERM_WRITE_SIGNED_MITM (1 << 8) /* bit 8 - 0x0100 */ /* relate to BTA_GATT_PERM_WRITE_SIGNED_MITM in bta/bta_gatt_api.h */
53+
#define ESP_GATT_PERM_READ_AUTHORIZATION (1 << 9) /* bit 9 - 0x0200 */
54+
#define ESP_GATT_PERM_WRITE_AUTHORIZATION (1 << 10) /* bit 10 - 0x0400 */
55+
56+
enum BLE_GATT_PERM_ {
57+
READ = 1 << 0,
58+
READ_ENCRYPTED = 1 << 1,
59+
READ_ENC_MITM = 1 << 2,
60+
WRITE = 1 << 4,
61+
WRITE_ENCRYPTED = 1 << 5,
62+
WRITE_ENC_MITM = 1 << 6,
63+
WRITE_SIGNED = 1 << 7,
64+
WRITE_SIGNED_MITM = 1 << 8,
65+
READ_AUTHORIZATION = 1 << 9,
66+
WRITE_AUTHORIZATION = 1 << 10,
3067
};
3168

69+
3270
#endif

src/local/BLELocalDevice.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,10 @@ int BLELocalDevice::begin()
108108
end();
109109
return 0;
110110
}
111+
if (HCI.setLeEventMask(0x00000000000001FF) != 0) {
112+
end();
113+
return 0;
114+
}
111115

112116
uint16_t pktLen;
113117
uint8_t maxPkt;

src/local/BLELocalDevice.h

+2
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ class BLELocalDevice {
8181
virtual void debug(Stream& stream);
8282
virtual void noDebug();
8383

84+
uint8_t BDaddress[6];
85+
8486
protected:
8587
virtual BLEAdvertisingData& getAdvertisingData();
8688
virtual BLEAdvertisingData& getScanResponseData();

src/utility/ATT.cpp

+131-4
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ ATTClass::ATTClass() :
9595
memset(_peers[i].address, 0x00, sizeof(_peers[i].address));
9696
_peers[i].mtu = 23;
9797
_peers[i].device = NULL;
98+
_peers[i].encryption = 0x0;
9899
}
99100

100101
memset(_eventHandlers, 0x00, sizeof(_eventHandlers));
@@ -267,12 +268,22 @@ void ATTClass::handleData(uint16_t connectionHandle, uint8_t dlen, uint8_t data[
267268

268269
uint16_t mtu = this->mtu(connectionHandle);
269270

271+
#ifdef _BLE_TRACE_
272+
Serial.print("data opcode: 0x");
273+
Serial.println(opcode, HEX);
274+
#endif
270275
switch (opcode) {
271276
case ATT_OP_ERROR:
277+
#ifdef _BLE_TRACE_
278+
Serial.println("[Info] data error");
279+
#endif
272280
error(connectionHandle, dlen, data);
273281
break;
274282

275283
case ATT_OP_MTU_REQ:
284+
#ifdef _BLE_TRACE_
285+
Serial.println("MTU");
286+
#endif
276287
mtuReq(connectionHandle, dlen, data);
277288
break;
278289

@@ -281,6 +292,9 @@ void ATTClass::handleData(uint16_t connectionHandle, uint8_t dlen, uint8_t data[
281292
break;
282293

283294
case ATT_OP_FIND_INFO_REQ:
295+
#ifdef _BLE_TRACE_
296+
Serial.println("Find info");
297+
#endif
284298
findInfoReq(connectionHandle, mtu, dlen, data);
285299
break;
286300

@@ -293,6 +307,9 @@ void ATTClass::handleData(uint16_t connectionHandle, uint8_t dlen, uint8_t data[
293307
break;
294308

295309
case ATT_OP_READ_BY_TYPE_REQ:
310+
#ifdef _BLE_TRACE_
311+
Serial.println("By type");
312+
#endif
296313
readByTypeReq(connectionHandle, mtu, dlen, data);
297314
break;
298315

@@ -319,6 +336,9 @@ void ATTClass::handleData(uint16_t connectionHandle, uint8_t dlen, uint8_t data[
319336

320337
case ATT_OP_WRITE_REQ:
321338
case ATT_OP_WRITE_CMD:
339+
#ifdef _BLE_TRACE_
340+
Serial.println("Write req");
341+
#endif
322342
writeReqOrCmd(connectionHandle, mtu, opcode, dlen, data);
323343
break;
324344

@@ -346,6 +366,9 @@ void ATTClass::handleData(uint16_t connectionHandle, uint8_t dlen, uint8_t data[
346366
case ATT_OP_READ_MULTI_REQ:
347367
case ATT_OP_SIGNED_WRITE_CMD:
348368
default:
369+
#ifdef _BLE_TRACE_
370+
Serial.println("[Info] Unhandled dara");
371+
#endif
349372
sendError(connectionHandle, opcode, 0x00, ATT_ECODE_REQ_NOT_SUPP);
350373
break;
351374
}
@@ -398,6 +421,10 @@ void ATTClass::removeConnection(uint16_t handle, uint8_t /*reason*/)
398421
_peers[peerIndex].addressType = 0x00;
399422
memset(_peers[peerIndex].address, 0x00, sizeof(_peers[peerIndex].address));
400423
_peers[peerIndex].mtu = 23;
424+
_peers[peerIndex].encryption = PEER_ENCRYPTION::NO_ENCRYPTION;
425+
_peers[peerIndex].IOCap[0] = 0;
426+
_peers[peerIndex].IOCap[1] = 0;
427+
_peers[peerIndex].IOCap[2] = 0;
401428

402429
if (_peers[peerIndex].device) {
403430
delete _peers[peerIndex].device;
@@ -808,6 +835,14 @@ void ATTClass::readByGroupReq(uint16_t connectionHandle, uint16_t mtu, uint8_t d
808835
uint16_t endHandle;
809836
uint16_t uuid;
810837
} *readByGroupReq = (ReadByGroupReq*)data;
838+
#ifdef _BLE_TRACE_
839+
Serial.print("readByGroupReq: start: 0x");
840+
Serial.println(readByGroupReq->startHandle,HEX);
841+
Serial.print("readByGroupReq: end: 0x");
842+
Serial.println(readByGroupReq->endHandle,HEX);
843+
Serial.print("readByGroupReq: UUID: 0x");
844+
Serial.println(readByGroupReq->uuid,HEX);
845+
#endif
811846

812847
if (dlen != sizeof(ReadByGroupReq) || (readByGroupReq->uuid != BLETypeService && readByGroupReq->uuid != 0x2801)) {
813848
sendError(connectionHandle, ATT_OP_READ_BY_GROUP_REQ, readByGroupReq->startHandle, ATT_ECODE_UNSUPP_GRP_TYPE);
@@ -820,7 +855,10 @@ void ATTClass::readByGroupReq(uint16_t connectionHandle, uint16_t mtu, uint8_t d
820855
response[0] = ATT_OP_READ_BY_GROUP_RESP;
821856
response[1] = 0x00;
822857
responseLength = 2;
823-
858+
#ifdef _BLE_TRACE_
859+
Serial.print("readByGroupReq: attrcount: ");
860+
Serial.println(GATT.attributeCount());
861+
#endif
824862
for (uint16_t i = (readByGroupReq->startHandle - 1); i < GATT.attributeCount() && i <= (readByGroupReq->endHandle - 1); i++) {
825863
BLELocalAttribute* attribute = GATT.attribute(i);
826864

@@ -907,6 +945,8 @@ void ATTClass::readOrReadBlobReq(uint16_t connectionHandle, uint16_t mtu, uint8_
907945
return;
908946
}
909947
}
948+
/// if auth error, hold the response in a buffer.
949+
bool holdResponse = false;
910950

911951
uint16_t handle = *(uint16_t*)data;
912952
uint16_t offset = (opcode == ATT_OP_READ_REQ) ? 0 : *(uint16_t*)&data[sizeof(handle)];
@@ -963,6 +1003,11 @@ void ATTClass::readOrReadBlobReq(uint16_t connectionHandle, uint16_t mtu, uint8_
9631003
sendError(connectionHandle, opcode, handle, ATT_ECODE_READ_NOT_PERM);
9641004
return;
9651005
}
1006+
// If characteristic requires encryption send error & hold response until encrypted
1007+
if ((characteristic->properties() & BLEAuth) > 0 && (getPeerEncryption(connectionHandle) & PEER_ENCRYPTION::ENCRYPTED_AES)==0) {
1008+
holdResponse = true;
1009+
sendError(connectionHandle, opcode, handle, ATT_ECODE_INSUFF_ENC);
1010+
}
9661011

9671012
uint16_t valueLength = characteristic->valueLength();
9681013

@@ -995,8 +1040,12 @@ void ATTClass::readOrReadBlobReq(uint16_t connectionHandle, uint16_t mtu, uint8_
9951040
memcpy(&response[responseLength], descriptor->value() + offset, valueLength);
9961041
responseLength += valueLength;
9971042
}
998-
999-
HCI.sendAclPkt(connectionHandle, ATT_CID, responseLength, response);
1043+
if(holdResponse){
1044+
memcpy(holdBuffer, response, responseLength);
1045+
holdBufferSize = responseLength;
1046+
}else{
1047+
HCI.sendAclPkt(connectionHandle, ATT_CID, responseLength, response);
1048+
}
10001049
}
10011050

10021051
void ATTClass::readResp(uint16_t connectionHandle, uint8_t dlen, uint8_t data[])
@@ -1688,7 +1737,85 @@ void ATTClass::writeCmd(uint16_t connectionHandle, uint16_t handle, const uint8_
16881737
sendReq(connectionHandle, &writeReq, 3 + dataLen, NULL);
16891738
}
16901739

1740+
// Set encryption state for a peer
1741+
int ATTClass::setPeerEncryption(uint16_t connectionHandle, uint8_t encryption){
1742+
for(int i=0; i<ATT_MAX_PEERS; i++){
1743+
if(_peers[i].connectionHandle != connectionHandle){
1744+
continue;
1745+
}
1746+
_peers[i].encryption = encryption;
1747+
return 1;
1748+
}
1749+
return 0;
1750+
}
1751+
// Set the IO capabilities for a peer
1752+
int ATTClass::setPeerIOCap(uint16_t connectionHandle, uint8_t IOCap[3]){
1753+
for(int i=0; i<ATT_MAX_PEERS; i++){
1754+
if(_peers[i].connectionHandle != connectionHandle){
1755+
continue;
1756+
}
1757+
memcpy(_peers[i].IOCap, IOCap, 3);
1758+
return 1;
1759+
}
1760+
return 0;
1761+
}
1762+
// Return the connection handle for the first peer that is requesting encryption
1763+
uint16_t ATTClass::getPeerEncrptingConnectionHandle(){
1764+
for(int i=0; i<ATT_MAX_PEERS; i++){
1765+
if(_peers[i].encryption & PEER_ENCRYPTION::REQUESTED_ENCRYPTION > 0){
1766+
return _peers[i].connectionHandle;
1767+
}
1768+
}
1769+
return ATT_MAX_PEERS + 1;
1770+
}
1771+
// Get the encryption state for a particular peer / connection handle
1772+
uint8_t ATTClass::getPeerEncryption(uint16_t connectionHandle) {
1773+
for(int i=0; i<ATT_MAX_PEERS; i++){
1774+
if(_peers[i].connectionHandle != connectionHandle){continue;}
1775+
return _peers[i].encryption;
1776+
}
1777+
return 0;
1778+
}
1779+
// Get the IOCapabilities for a peer
1780+
int ATTClass::getPeerIOCap(uint16_t connectionHandle, uint8_t IOCap[3]) {
1781+
for(int i=0; i<ATT_MAX_PEERS; i++){
1782+
if(_peers[i].connectionHandle != connectionHandle){continue;}
1783+
// return _peers[i].encryption;
1784+
memcpy(IOCap, _peers[i].IOCap, 3);
1785+
}
1786+
return 0;
1787+
}
1788+
// Get the BD_ADDR for a peer
1789+
int ATTClass::getPeerAddr(uint16_t connectionHandle, uint8_t peerAddr[])
1790+
{
1791+
for(int i=0; i<ATT_MAX_PEERS; i++)
1792+
{
1793+
if(_peers[i].connectionHandle != connectionHandle){continue;}
1794+
memcpy(peerAddr, _peers[i].address,6);
1795+
return 1;
1796+
}
1797+
return 0;
1798+
}
1799+
// Get the BD_ADDR for a peer in the format needed by f6 for pairing.
1800+
int ATTClass::getPeerAddrWithType(uint16_t connectionHandle, uint8_t peerAddr[])
1801+
{
1802+
for(int i=0; i<ATT_MAX_PEERS; i++)
1803+
{
1804+
if(_peers[i].connectionHandle != connectionHandle){continue;}
1805+
for(int k=0; k<6; k++){
1806+
peerAddr[6-k] = _peers[i].address[k];
1807+
}
1808+
if(_peers[i].addressType){
1809+
peerAddr[0] = 0x01;
1810+
}else{
1811+
peerAddr[0] = 0x00;
1812+
}
1813+
return 1;
1814+
}
1815+
return 0;
1816+
}
1817+
16911818
#if !defined(FAKE_ATT)
16921819
ATTClass ATTObj;
16931820
ATTClass& ATT = ATTObj;
1694-
#endif
1821+
#endif

src/utility/ATT.h

+22-1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "BLEDevice.h"
2626

2727
#define ATT_CID 0x0004
28+
#define BLE_CTL 0x0008
2829

2930
#if DM_CONN_MAX
3031
#define ATT_MAX_PEERS DM_CONN_MAX // Mbed + Cordio
@@ -34,6 +35,16 @@
3435
#define ATT_MAX_PEERS 8
3536
#endif
3637

38+
enum PEER_ENCRYPTION {
39+
NO_ENCRYPTION = 0,
40+
REQUESTED_ENCRYPTION = 1 << 0,
41+
SENT_PUBKEY = 1 << 1,
42+
DH_KEY_CALULATED = 1 << 2,
43+
RECEIVED_DH_CHECK = 1 << 3,
44+
SENT_DH_CHECK = 1 << 4,
45+
ENCRYPTED_AES = 1 << 7
46+
};
47+
3748
class BLERemoteDevice;
3849

3950
class ATTClass {
@@ -76,7 +87,15 @@ class ATTClass {
7687
virtual int readReq(uint16_t connectionHandle, uint16_t handle, uint8_t responseBuffer[]);
7788
virtual int writeReq(uint16_t connectionHandle, uint16_t handle, const uint8_t* data, uint8_t dataLen, uint8_t responseBuffer[]);
7889
virtual void writeCmd(uint16_t connectionHandle, uint16_t handle, const uint8_t* data, uint8_t dataLen);
79-
90+
virtual int setPeerEncryption(uint16_t connectionHandle, uint8_t encryption);
91+
uint8_t getPeerEncryption(uint16_t connectionHandle);
92+
uint16_t getPeerEncrptingConnectionHandle();
93+
virtual int getPeerAddr(uint16_t connectionHandle, uint8_t peerAddr[]);
94+
virtual int getPeerAddrWithType(uint16_t connectionHandle, uint8_t peerAddr[]);
95+
virtual int setPeerIOCap(uint16_t connectionHandle, uint8_t IOCap[]);
96+
virtual int getPeerIOCap(uint16_t connectionHandle, uint8_t IOCap[]);
97+
uint8_t holdBuffer[64];
98+
uint8_t holdBufferSize;
8099
private:
81100
virtual void error(uint16_t connectionHandle, uint8_t dlen, uint8_t data[]);
82101
virtual void mtuReq(uint16_t connectionHandle, uint8_t dlen, uint8_t data[]);
@@ -119,6 +138,8 @@ class ATTClass {
119138
uint8_t address[6];
120139
uint16_t mtu;
121140
BLERemoteDevice* device;
141+
uint8_t encryption;
142+
uint8_t IOCap[3];
122143
} _peers[ATT_MAX_PEERS];
123144

124145
volatile bool _cnf;

0 commit comments

Comments
 (0)