BLE is now secured to require pairing with PIN

1.2-legacy
geeksville 2020-02-07 20:59:21 -08:00
rodzic 0c0d4025f1
commit 593a6e6f83
6 zmienionych plików z 214 dodań i 88 usunięć

Wyświetl plik

@ -2,11 +2,12 @@
* have node info screen show real info (including distance and heading)
* very occasionally send our position and user packet (if for nothing else so that other nodes update last_seen)
* save our node db on entry to sleep
* make a screen for bluetooth not yet configured
# Medium priority
* only BLE advertise for a short time after the screen is on and button pressed - to save power and prevent people for sniffing for our BT app.
* use https://platformio.org/lib/show/1260/OneButton
* make an about to sleep screen
* make a no bluetooth configured yet screen
* don't send location packets if we haven't moved
@ -107,3 +108,4 @@ until the phone pulls those packets. Ever so often power on bluetooth just so w
* switch to my gui layout manager
* make basic gui. different screens: debug, one page for each user in the user db, last received text message
* make button press cycle between screens
* save our node db on entry to sleep

Wyświetl plik

@ -5,6 +5,7 @@
#include <Arduino.h>
#include <Update.h>
#include "configuration.h"
#include "screen.h"
static BLECharacteristic SWVersionCharacteristic(BLEUUID((uint16_t)ESP_GATT_UUID_SW_VERSION_STR), BLECharacteristic::PROPERTY_READ);
static BLECharacteristic ManufacturerCharacteristic(BLEUUID((uint16_t)ESP_GATT_UUID_MANU_NAME), BLECharacteristic::PROPERTY_READ);
@ -14,7 +15,8 @@ static BLECharacteristic HardwareVersionCharacteristic(BLEUUID((uint16_t) ESP_GA
/**
* Create standard device info service
**/
BLEService *createDeviceInfomationService(BLEServer* server, std::string hwVendor, std::string swVersion) {
BLEService *createDeviceInfomationService(BLEServer *server, std::string hwVendor, std::string swVersion)
{
BLEService *deviceInfoService = server->createService(BLEUUID((uint16_t)ESP_GATT_UUID_DEVICE_INFO_SVC));
/*
@ -38,7 +40,6 @@ BLEService *createDeviceInfomationService(BLEServer* server, std::string hwVendo
// m_manufacturerCharacteristic = m_deviceInfoService->createCharacteristic((uint16_t) 0x2a29, BLECharacteristic::PROPERTY_READ);
// m_manufacturerCharacteristic->setValue(name);
/* add these later?
ESP_GATT_UUID_SYSTEM_ID
*/
@ -49,20 +50,28 @@ BLEService *createDeviceInfomationService(BLEServer* server, std::string hwVendo
bool _BLEClientConnected = false;
class MyServerCallbacks : public BLEServerCallbacks {
void onConnect(BLEServer* pServer) {
class MyServerCallbacks : public BLEServerCallbacks
{
void onConnect(BLEServer *pServer)
{
_BLEClientConnected = true;
};
void onDisconnect(BLEServer* pServer) {
void onDisconnect(BLEServer *pServer)
{
_BLEClientConnected = false;
}
};
// Help routine to add a description to any BLECharacteristic and add it to the service
void addWithDesc(BLEService *service, BLECharacteristic *c, const char *description) {
// We default to require an encrypted BOND for all these these characterstics
void addWithDesc(BLEService *service, BLECharacteristic *c, const char *description)
{
c->setAccessPermissions(ESP_GATT_PERM_READ_ENCRYPTED | ESP_GATT_PERM_WRITE_ENCRYPTED);
BLEDescriptor *desc = new BLEDescriptor(BLEUUID((uint16_t)ESP_GATT_UUID_CHAR_DESCRIPTION), strlen(description) + 1);
assert(desc);
desc->setAccessPermissions(ESP_GATT_PERM_READ_ENCRYPTED | ESP_GATT_PERM_WRITE_ENCRYPTED);
desc->setValue(description);
c->addDescriptor(desc);
service->addCharacteristic(c);
@ -73,7 +82,8 @@ static BLECharacteristic BatteryLevelCharacteristic(BLEUUID((uint16_t) ESP_GATT_
/**
* Create a battery level service
*/
BLEService *createBatteryService(BLEServer* server) {
BLEService *createBatteryService(BLEServer *server)
{
// Create the BLE Service
BLEService *pBattery = server->createService(BLEUUID((uint16_t)0x180F));
@ -87,22 +97,23 @@ BLEService *createBatteryService(BLEServer* server) {
return pBattery;
}
/**
* Update the battery level we are currently telling clients.
* level should be a pct between 0 and 100
*/
void updateBatteryLevel(uint8_t level) {
void updateBatteryLevel(uint8_t level)
{
// Pretend to update battery levels - fixme do elsewhere
BatteryLevelCharacteristic.setValue(&level, 1);
BatteryLevelCharacteristic.notify();
}
void dumpCharacteristic(BLECharacteristic *c) {
void dumpCharacteristic(BLECharacteristic *c)
{
std::string value = c->getValue();
if (value.length() > 0) {
if (value.length() > 0)
{
DEBUG_MSG("New value: ");
for (int i = 0; i < value.length(); i++)
DEBUG_MSG("%c", value[i]);
@ -112,7 +123,8 @@ void dumpCharacteristic(BLECharacteristic *c) {
}
/** converting endianness pull out a 32 bit value */
uint32_t getValue32(BLECharacteristic *c, uint32_t defaultValue) {
uint32_t getValue32(BLECharacteristic *c, uint32_t defaultValue)
{
std::string value = c->getValue();
uint32_t r = defaultValue;
@ -122,9 +134,61 @@ uint32_t getValue32(BLECharacteristic *c, uint32_t defaultValue) {
return r;
}
class MySecurity : public BLESecurityCallbacks
{
BLEServer *initBLE(std::string deviceName, std::string hwVendor, std::string swVersion) {
bool onConfirmPIN(uint32_t pin)
{
Serial.printf("onConfirmPIN %u\n", pin);
return false;
}
uint32_t onPassKeyRequest()
{
Serial.println("onPassKeyRequest");
return 123511; // not used
}
void onPassKeyNotify(uint32_t pass_key)
{
Serial.printf("onPassKeyNotify %u\n", pass_key);
screen_start_bluetooth(pass_key);
}
bool onSecurityRequest()
{
Serial.println("onSecurityRequest");
return true;
}
void onAuthenticationComplete(esp_ble_auth_cmpl_t cmpl)
{
if (cmpl.success)
{
uint16_t length;
esp_ble_gap_get_whitelist_size(&length);
Serial.printf(" onAuthenticationComplete -> success size: %d\n", length);
}
else
{
Serial.printf("onAuthenticationComplete -> fail %d\n", cmpl.fail_reason);
}
// Remove our custom screen
screen_set_frames();
}
};
BLEServer *initBLE(std::string deviceName, std::string hwVendor, std::string swVersion)
{
BLEDevice::init(deviceName);
BLEDevice::setEncryptionLevel(ESP_BLE_SEC_ENCRYPT);
/*
* Required in authentication process to provide displaying and/or input passkey or yes/no butttons confirmation
*/
BLEDevice::setSecurityCallbacks(new MySecurity());
// Create the BLE Server
BLEServer *pServer = BLEDevice::createServer();
pServer->setCallbacks(new MyServerCallbacks());
@ -144,10 +208,16 @@ BLEServer *initBLE(std::string deviceName, std::string hwVendor, std::string swV
// Start advertising
pServer->getAdvertising()->start();
BLESecurity *pSecurity = new BLESecurity();
pSecurity->setCapability(ESP_IO_CAP_OUT);
pSecurity->setAuthenticationMode(ESP_LE_AUTH_REQ_SC_BOND);
pSecurity->setInitEncryptionKey(ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK);
return pServer;
}
// Called from loop
void loopBLE() {
void loopBLE()
{
bluetoothRebootCheck();
}

Wyświetl plik

@ -61,6 +61,7 @@ lib_deps =
ESP8266_SSD1306
AXP202X_Library
SPI
OneButton
CRC32 ; explicitly needed because dependency is missing in the ble ota update lib
Wire ; explicitly needed here because the AXP202 library forgets to add it

Wyświetl plik

@ -31,6 +31,7 @@
#include "MeshService.h"
#include "GPS.h"
#include "screen.h"
#include "NodeDB.h"
#ifdef T_BEAM_V10
#include "axp20x.h"
@ -66,6 +67,8 @@ void doDeepSleep(uint64_t msecToWake)
// Put radio in sleep mode (will still draw power but only 0.2uA)
service.radio.sleep();
nodeDB.saveToDisk();
#ifdef RESET_OLED
digitalWrite(RESET_OLED, 1); // put the display in reset before killing its power
#endif

Wyświetl plik

@ -66,6 +66,26 @@ void drawBootScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x,
ui.disableIndicator();
}
static char btPIN[16] = "888888";
void drawFrameBluetooth(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
{
// Demonstrates the 3 included default sizes. The fonts come from SSD1306Fonts.h file
// Besides the default fonts there will be a program to convert TrueType fonts into this format
display->setTextAlignment(TEXT_ALIGN_CENTER);
display->setFont(ArialMT_Plain_16);
display->drawString(64 + x, 2 + y, "Bluetooth");
display->setFont(ArialMT_Plain_10);
display->drawString(64 + x, SCREEN_HEIGHT - FONT_HEIGHT + y, "Enter this code");
display->setTextAlignment(TEXT_ALIGN_CENTER);
display->setFont(ArialMT_Plain_24);
display->drawString(64 + x, 22 + y, btPIN);
ui.disableIndicator();
}
void drawFrame2(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
{
// Demonstrates the 3 included default sizes. The fonts come from SSD1306Fonts.h file
@ -209,12 +229,13 @@ OverlayCallback overlays[] = {/* msOverlay */};
const int frameCount = sizeof(frames) / sizeof(frames[0]);
const int overlaysCount = sizeof(overlays) / sizeof(overlays[0]);
#if 0
void _screen_header()
{
if (!disp)
return;
#if 0
// Message count
//snprintf(buffer, sizeof(buffer), "#%03d", ttn_get_count() % 1000);
//display->setTextAlignment(TEXT_ALIGN_LEFT);
@ -229,8 +250,8 @@ void _screen_header()
char buffer[10];
display->drawString(display->getWidth() - SATELLITE_IMAGE_WIDTH - 4, 2, itoa(gps.satellites.value(), buffer, 10));
display->drawXbm(display->getWidth() - SATELLITE_IMAGE_WIDTH, 0, SATELLITE_IMAGE_WIDTH, SATELLITE_IMAGE_HEIGHT, SATELLITE_IMAGE);
#endif
}
#endif
void screen_off()
{
@ -259,10 +280,7 @@ static void screen_print(const char *text, uint8_t x, uint8_t y, uint8_t alignme
dispdev.drawString(x, y, text);
}
static void screen_print(const char *text, uint8_t x, uint8_t y)
{
screen_print(text, x, y, TEXT_ALIGN_LEFT);
}
void screen_print(const char *text)
{
@ -317,6 +335,8 @@ void screen_setup()
#endif
}
static bool showingBluetooth;
uint32_t screen_loop()
{
if (!disp)
@ -356,19 +376,43 @@ uint32_t screen_loop()
ui.update();
// Once we finish showing the bootscreen, remove it from the loop
if (showingBootScreen && ui.getUiState()->currentFrame == 1)
if (showingBootScreen && !showingBluetooth && ui.getUiState()->currentFrame == 1)
{
showingBootScreen = false;
ui.setFrames(nonBootFrames, frameCount - 1);
screen_set_frames();
}
// If we are scrolling do 30fps, otherwise just 1 fps (to save CPU)
return (ui.getUiState()->frameState == IN_TRANSITION ? 10 : 500);
}
// Show the bluetooth PIN screen
void screen_start_bluetooth(uint32_t pin) {
static FrameCallback btFrames[] = { drawFrameBluetooth };
snprintf(btPIN, sizeof(btPIN), "%06d", pin);
DEBUG_MSG("showing bluetooth screen\n");
showingBluetooth = true;
//screen_on(); // make sure the screen is not asleep - FIXME, this causes crap to draw on the screen
ui.disableAutoTransition(); // we now require presses
ui.setFrames(btFrames, 1); // Just show the bluetooth frame
// we rely on our main loop to show this screen (because we are invoked deep inside of bluetooth callbacks)
// ui.update(); // manually draw once, because I'm not sure if loop is getting called
}
// restore our regular frame list
void screen_set_frames() {
DEBUG_MSG("showing standard frames\n");
ui.setFrames(nonBootFrames, frameCount - 1);
showingBluetooth = false;
}
/// handle press of the button
void screen_press() {
//screen_start_bluetooth(123456);
// Once the user presses a button, stop auto scrolling between screens
ui.disableAutoTransition(); // we now require presses
ui.nextFrame();

Wyświetl plik

@ -6,3 +6,9 @@ void screen_print(const char * text);
uint32_t screen_loop();
void screen_setup(), screen_on(), screen_off(), screen_press();
// Show the bluetooth PIN screen
void screen_start_bluetooth(uint32_t pin);
// restore our regular frame list
void screen_set_frames();