Skip to content

Commit c663798

Browse files
author
unknownconstant
committed
Initial - encrypted read
1 parent 693268d commit c663798

File tree

12 files changed

+1301
-82
lines changed

12 files changed

+1301
-82
lines changed

src/ArduinoBLE.h

Lines changed: 1 addition & 0 deletions
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

Lines changed: 39 additions & 1 deletion
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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,10 @@ int BLELocalDevice::begin()
107107
end();
108108
return 0;
109109
}
110+
if (HCI.setLeEventMask(0x00000000000001FF) != 0) {
111+
end();
112+
return 0;
113+
}
110114

111115
uint16_t pktLen;
112116
uint8_t maxPkt;

src/local/BLELocalDevice.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ class BLELocalDevice {
7474

7575
void debug(Stream& stream);
7676
void noDebug();
77+
uint8_t BDaddress[6];
7778

7879
private:
7980
};

src/utility/ATT.cpp

Lines changed: 129 additions & 3 deletions
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;
@@ -807,6 +834,14 @@ void ATTClass::readByGroupReq(uint16_t connectionHandle, uint16_t mtu, uint8_t d
807834
uint16_t endHandle;
808835
uint16_t uuid;
809836
} *readByGroupReq = (ReadByGroupReq*)data;
837+
#ifdef _BLE_TRACE_
838+
Serial.print("readByGroupReq: start: 0x");
839+
Serial.println(readByGroupReq->startHandle,HEX);
840+
Serial.print("readByGroupReq: end: 0x");
841+
Serial.println(readByGroupReq->endHandle,HEX);
842+
Serial.print("readByGroupReq: UUID: 0x");
843+
Serial.println(readByGroupReq->uuid,HEX);
844+
#endif
810845

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

@@ -906,6 +944,8 @@ void ATTClass::readOrReadBlobReq(uint16_t connectionHandle, uint16_t mtu, uint8_
906944
return;
907945
}
908946
}
947+
/// if auth error, hold the response in a buffer.
948+
bool holdResponse = false;
909949

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

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

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

10011050
void ATTClass::readResp(uint16_t connectionHandle, uint8_t dlen, uint8_t data[])
@@ -1687,4 +1736,81 @@ void ATTClass::writeCmd(uint16_t connectionHandle, uint16_t handle, const uint8_
16871736
sendReq(connectionHandle, &writeReq, 3 + dataLen, NULL);
16881737
}
16891738

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

src/utility/ATT.h

Lines changed: 22 additions & 1 deletion
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 defined(ARDUINO_PORTENTA_H7_M4) || defined(ARDUINO_PORTENTA_H7_M7)
3031
#define ATT_MAX_PEERS 7
@@ -34,6 +35,16 @@
3435
#define ATT_MAX_PEERS 3
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
int readReq(uint16_t connectionHandle, uint16_t handle, uint8_t responseBuffer[]);
7788
int writeReq(uint16_t connectionHandle, uint16_t handle, const uint8_t* data, uint8_t dataLen, uint8_t responseBuffer[]);
7889
void writeCmd(uint16_t connectionHandle, uint16_t handle, const uint8_t* data, uint8_t dataLen);
79-
90+
int setPeerEncryption(uint16_t connectionHandle, uint8_t encryption);
91+
uint8_t getPeerEncryption(uint16_t connectionHandle);
92+
uint16_t getPeerEncrptingConnectionHandle();
93+
int getPeerAddr(uint16_t connectionHandle, uint8_t peerAddr[]);
94+
int getPeerAddrWithType(uint16_t connectionHandle, uint8_t peerAddr[]);
95+
int setPeerIOCap(uint16_t connectionHandle, uint8_t IOCap[]);
96+
int getPeerIOCap(uint16_t connectionHandle, uint8_t IOCap[]);
97+
uint8_t holdBuffer[64];
98+
uint8_t holdBufferSize;
8099
private:
81100
void error(uint16_t connectionHandle, uint8_t dlen, uint8_t data[]);
82101
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)