8000 Introduced BLE security by chegewara · Pull Request #293 · nkolban/esp32-snippets · GitHub
[go: up one dir, main page]

Skip to content

Introduced BLE security #293

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 18, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 20 additions & 7 deletions cpp_utils/BLECharacteristic.cpp
8000
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ void BLECharacteristic::executeCreate(BLEService* pService) {
esp_err_t errRc = ::esp_ble_gatts_add_char(
m_pService->getHandle(),
getUUID().getNative(),
static_cast<esp_gatt_perm_t>(ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE),
static_cast<esp_gatt_perm_t>(m_permissions),
getProperties(),
//&value,
nullptr,
Expand Down Expand Up @@ -163,6 +163,9 @@ uint16_t BLECharacteristic::getHandle() {
return m_handle;
} // getHandle

void BLECharacteristic::setAccessPermissions(esp_gatt_perm_t perm) {
m_permissions = perm;
}

esp_gatt_char_prop_t BLECharacteristic::getProperties() {
return m_properties;
Expand Down Expand Up @@ -348,29 +351,34 @@ void BLECharacteristic::handleGATTServerEvent(
// The following code has deliberately not been factored to make it fewer statements because this would cloud the
// the logic flow comprehension.
//
uint16_t maxOffset = m_mtu - 1;
if (m_mtu > 512)
maxOffset = 512;
ESP_LOGI(LOG_TAG, "%d", m_mtu);
ESP_LOGI(LOG_TAG, "%d", maxOffset);
if (param->read.need_rsp) {
ESP_LOGD(LOG_TAG, "Sending a response (esp_ble_gatts_send_response)");
esp_gatt_rsp_t rsp;
std::string value = m_value.getValue();
if (param->read.is_long) {
if (value.length() - m_value.getReadOffset() < 22) {
if (value.length() - m_value.getReadOffset() < maxOffset) {
// This is the last in the chain
rsp.attr_value.len = value.length() - m_value.getReadOffset();
rsp.attr_value.offset = m_value.getReadOffset();
memcpy(rsp.attr_value.value, value.data() + rsp.attr_value.offset, rsp.attr_value.len);
m_value.setReadOffset(0);
} else {
// There will be more to come.
rsp.attr_value.len = 22;
rsp.attr_value.len = maxOffset;
rsp.attr_value.offset = m_value.getReadOffset();
memcpy(rsp.attr_value.value, value.data() + rsp.attr_value.offset, rsp.attr_value.len);
m_value.setReadOffset(rsp.attr_value.offset + 22);
m_value.setReadOffset(rsp.attr_value.offset + maxOffset);
}
} else {
if (value.length() > 21) {
if (value.length()+1 > maxOffset) {
// Too big for a single shot entry.
m_value.setReadOffset(22);
rsp.attr_value.len = 22;
m_value.setReadOffset(maxOffset);
rsp.attr_value.len = maxOffset;
rsp.attr_value.offset = 0;
memcpy(rsp.attr_value.value, value.data(), rsp.attr_value.len);
} else {
Expand Down Expand Up @@ -412,13 +420,18 @@ void BLECharacteristic::handleGATTServerEvent(
}

case ESP_GATTS_CONNECT_EVT:
m_mtu = 23;
m_semaphoreConfEvt.give();
break;

case ESP_GATTS_DISCONNECT_EVT:
m_semaphoreConfEvt.give();
break;

case ESP_GATTS_MTU_EVT :
m_mtu = param->mtu.mtu;
break;

default: {
break;
} // default
Expand Down
4 changes: 4 additions & 0 deletions cpp_utils/BLECharacteristic.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <map>
#include "BLEUUID.h"
#include <esp_gatts_api.h>
#include <esp_gap_ble_api.h>
#include "BLEDescriptor.h"
#include "BLEValue.h"
#include "FreeRTOS.h"
Expand Down Expand Up @@ -78,6 +79,7 @@ class BLECharacteristic {
void setWriteNoResponseProperty(bool value);
std::string toString();
uint16_t getHandle();
void setAccessPermissions(esp_gatt_perm_t perm);

static const uint32_t PROPERTY_READ = 1<<0;
static const uint32_t PROPERTY_WRITE = 1<<1;
Expand All @@ -100,6 +102,8 @@ class BLECharacteristic {
BLECharacteristicCallbacks* m_pCallbacks;
BLEService* m_pService;
BLEValue m_value;
esp_gatt_perm_t m_permissions = ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE;
uint16_t m_mtu = 23;

void handleGATTServerEvent(
esp_gatts_cb_event_t event,
Expand Down
50 changes: 50 additions & 0 deletions cpp_utils/BLEClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,14 @@ void BLEClient::gattClientEventHandler(
break;
} // ESP_GATTC_DISCONNECT_EVT

case ESP_GATTS_CONNECT_EVT: {
//m_connId = param->connect.conn_id; // Save the connection id.
if(m_securityLevel){
esp_ble_set_encryption(evtParam->connect.remote_bda, m_securityLevel);
//memcpy(m_remote_bda, param->connect.remote_bda, sizeof(m_remote_bda));
}
break;
} // ESP_GATTS_CONNECT_EVT

//
// ESP_GATTC_OPEN_EVT
Expand Down Expand Up @@ -411,6 +419,41 @@ void BLEClient::handleGAPEvent(
break;
} // ESP_GAP_BLE_READ_RSSI_COMPLETE_EVT

case ESP_GAP_BLE_PASSKEY_REQ_EVT: /* passkey request event */
ESP_LOGI(LOG_TAG, "ESP_GAP_BLE_PASSKEY_REQ_EVT: ");
// esp_log_buffer_hex(LOG_TAG, m_remote_bda, sizeof(m_remote_bda));
assert(m_securityCallbacks!=nullptr);
// esp_ble_passkey_reply(m_remote_bda, true, m_securityCallbacks->onPassKeyRequest());
break;

/*
* TODO should we add white/black list comparison?
*/
case ESP_GAP_BLE_SEC_REQ_EVT:
/* send the positive(true) security response to the peer device to accept the security request.
If not accept the security request, should sent the security response with negative(false) accept value*/
if(m_securityCallbacks!=nullptr)
esp_ble_gap_security_rsp(param->ble_security.ble_req.bd_addr, m_securityCallbacks->onSecurityRequest());
else
esp_ble_gap_security_rsp(param->ble_security.ble_req.bd_addr, false);
break;
/*
*
*/
case ESP_GAP_BLE_PASSKEY_NOTIF_EVT: ///the app will receive this evt when the IO has Output capability and the peer device IO has Input capability.
///show the passkey number to the user to input it in the peer deivce.
if(m_securityCallbacks!=nullptr)
m_securityCallbacks->onPassKeyNotify(param->ble_security.key_notif.passkey);
break;
case ESP_GAP_BLE_KEY_EVT:
//shows the ble key info share with peer device to the user.
ESP_LOGI(LOG_TAG, "key type = %s", BLESecurity::esp_key_type_to_str(param->ble_security.ble_key.key_type));
break;
case ESP_GAP_BLE_AUTH_CMPL_EVT:
if(m_securityCallbacks!=nullptr)
m_securityCallbacks->onAuthenticationComplete(param->ble_security.auth_cmpl);
break;

default:
break;
}
Expand Down Expand Up @@ -448,6 +491,13 @@ void BLEClient::setValue(BLEUUID serviceUUID, BLEUUID characteristicUUID, std::s
ESP_LOGD(LOG_TAG, "<< setValue");
} // setValue

void BLEClient::setEncryptionLevel(esp_ble_sec_act_t level) {
m_securityLevel = level;
}

void BLEClient::setSecurityCallbacks(BLESecurityCallbacks* callbacks) {
m_securityCallbacks = callbacks;
}

/**
* @brief Return a string representation of this client.
Expand Down
4 changes: 4 additions & 0 deletions cpp_utils/BLEClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ class BLEClient {

void setClientCallbacks(BLEClientCallbacks *pClientCallbacks);
void setValue(BLEUUID serviceUUID, BLEUUID characteristicUUID, std::string value); // Set the value of a given characteristic at a given service.
void setEncryptionLevel(esp_ble_sec_act_t level);
void setSecurityCallbacks(BLESecurityCallbacks* pCallbacks);

std::string toString(); // Return a string representation of this client.

Expand Down Expand Up @@ -80,6 +82,8 @@ class BLEClient {
FreeRTOS::Semaphore m_semaphoreRssiCmplEvt = FreeRTOS::Semaphore("RssiCmplEvt");
std::map<std::string, BLERemoteService*> m_servicesMap;
void clearServices(); // Clear any existing services.
esp_ble_sec_act_t m_securityLevel = (esp_ble_sec_act_t)0;
BLESecurityCallbacks* m_securityCallbacks = 0;

}; // class BLEDevice

Expand Down
91 changes: 91 additions & 0 deletions cpp_utils/BLESecurity.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
* BLESecurity.cpp
*
* Created on: Dec 17, 2017
* Author: chegewara
*/

#include <BLESecurity.h>

BLESecurity::BLESecurity() {
}

BLESecurity::~BLESecurity() {
}
/*
* @brief Set requested authentication mode
*/
void BLESecurity::setAuthenticationMode(esp_ble_auth_req_t auth_req) {
m_authReq = auth_req;
esp_ble_gap_set_security_param(ESP_BLE_SM_AUTHEN_REQ_MODE, &m_authReq, sizeof(uint8_t)); // <--- setup requested authentication mode
}
/*
* @brief Set our device IO capability to let end user perform authorization
* either by displaying or entering generated 6-digits pin code
*/
void BLESecurity::setCapability(esp_ble_io_cap_t iocap) {
m_iocap = iocap;
esp_ble_gap_set_security_param(ESP_BLE_SM_IOCAP_MODE, &iocap, sizeof(uint8_t));
}
/*
* @brief Init encryption key by server
* @param key_size is value between 7 and 16
*/
void BLESecurity::setInitEncryptionKey(uint8_t init_key, uint8_t key_size) {
m_initKey = init_key;
m_keySize = key_size;
esp_ble_gap_set_security_param(ESP_BLE_SM_SET_INIT_KEY, &m_initKey, sizeof(uint8_t));
esp_ble_gap_set_security_param(ESP_BLE_SM_MAX_KEY_SIZE, &key_size, sizeof(uint8_t)); // <--- setup encryption key max size
}

/*
* @brief Init encryption key by client
* @param key_size is value between 7 and 16
*/
void BLESecurity::setRespEncryptionKey(uint8_t resp_key, uint8_t key_size) {
m_respKey = resp_key;
m_keySize = key_size;
esp_ble_gap_set_security_param(ESP_BLE_SM_SET_RSP_KEY, &m_respKey, sizeof(uint8_t));
esp_ble_gap_set_security_param(ESP_BLE_SM_MAX_KEY_SIZE, &key_size, sizeof(uint8_t)); // <--- setup encryption key max size
}
/*
* @brief Debug function to display what keys are exchanged by peers
*/
char* BLESecurity::esp_key_type_to_str(esp_ble_key_type_t key_type)
{
char *key_str = NULL;
switch(key_type) {
case ESP_LE_KEY_NONE:
key_str = (char*)"ESP_LE_KEY_NONE";
break;
case ESP_LE_KEY_PENC:
key_str = (char*)"ESP_LE_KEY_PENC";
break;
case ESP_LE_KEY_PID:
key_str = (char*)"ESP_LE_KEY_PID";
break;
case ESP_LE_KEY_PCSRK:
key_str = (char*)"ESP_LE_KEY_PCSRK";
break;
case ESP_LE_KEY_PLK:
key_str = (char*)"ESP_LE_KEY_PLK";
break;
case ESP_LE_KEY_LLK:
key_str = (char*)"ESP_LE_KEY_LLK";
break;
case ESP_LE_KEY_LENC:
key_str = (char*)"ESP_LE_KEY_LENC";
break;
case ESP_LE_KEY_LID:
key_str = (char*)"ESP_LE_KEY_LID";
break;
case ESP_LE_KEY_LCSRK:
key_str = (char*)"ESP_LE_KEY_LCSRK";
break;
default:
key_str = (char*)"INVALID BLE KEY TYPE";
break;

}
return key_str;
}
60 changes: 60 additions & 0 deletions cpp_utils/BLESecurity.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* BLESecurity.h
*
* Created on: Dec 17, 2017
* Author: chegewara
*/

#ifndef COMPONENTS_CPP_UTILS_BLESECURITY_H_
#define COMPONENTS_CPP_UTILS_BLESECURITY_H_
#include <esp_gap_ble_api.h>

class BLESecurity {
public:
BLESecurity();
virtual ~BLESecurity();
void setAuthenticationMode(esp_ble_auth_req_t auth_req);
void setCapability(esp_ble_io_cap_t iocap);
void setInitEncryptionKey(uint8_t init_key, uint8_t key_size = 16);
void setRespEncryptionKey(uint8_t resp_key, uint8_t key_size = 16);
static char* esp_key_type_to_str(esp_ble_key_type_t key_type);

private:
esp_ble_auth_req_t m_authReq;
esp_ble_io_cap_t m_iocap;
uint8_t m_initKey;
uint8_t m_respKey;
uint8_t m_keySize;
};

/*
* @brief Callbacks to handle GAP events related to authorization
*/
class BLESecurityCallbacks {
public:
virtual ~BLESecurityCallbacks() {};

/*
* @brief Its request from peer device to input authentication pin code displayed on peer device.
* It requires that our device is capable to input 6-digits code by end user
* @return Return 6-digits integer value from input device
*/
virtual uint32_t onPassKeyRequest() = 0;
/*
* @brief Provide us 6-digits code to perform authentication.
* It requires that our device is capable to display this code to end user
* @param
*/
virtual void onPassKeyNotify(uint32_t pass_key);
/*
* @brief Here we can make decision if we want to let negotiate authorization with peer device or not
* return Return true if we accept this peer device request
*/
virtual bool onSecurityRequest();
/*
* Provide us information when authentication process is completed
*/
virtual void onAuthenticationComplete(esp_ble_auth_cmpl_t);
};

#endif /* COMPONENTS_CPP_UTILS_BLESECURITY_H_ */
Loading
0