BLE Application to open a Garage door

Dependencies:   BLE_API Crypto RNG mbed nRF51822

Fork of BLE_LED by Bluetooth Low Energy

Files at this revision

API Documentation at this revision

Comitter:
dgomes
Date:
Tue Aug 25 22:18:21 2015 +0000
Parent:
8:0f145b25ab0b
Child:
10:80850cd6c29e
Commit message:
Mostly Works :)

Changed in this revision

BLE_API.lib Show annotated file Show diff for this revision Revisions of this file
Crypto.lib Show annotated file Show diff for this revision Revisions of this file
GaragemService.h Show annotated file Show diff for this revision Revisions of this file
History.h Show annotated file Show diff for this revision Revisions of this file
LEDService.h Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
nRF51822.lib Show annotated file Show diff for this revision Revisions of this file
--- a/BLE_API.lib	Thu Jul 02 08:44:06 2015 +0000
+++ b/BLE_API.lib	Tue Aug 25 22:18:21 2015 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/teams/Bluetooth-Low-Energy/code/BLE_API/#6884e374e2eb
+http://mbed.org/teams/Bluetooth-Low-Energy/code/BLE_API/#8d316a3271a8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Crypto.lib	Tue Aug 25 22:18:21 2015 +0000
@@ -0,0 +1,1 @@
+http://developer.mbed.org/users/feb11/code/Crypto/#f04410cef037
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GaragemService.h	Tue Aug 25 22:18:21 2015 +0000
@@ -0,0 +1,86 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2006-2013 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __BLE_GARAGEM_SERVICE_H__
+#define __BLE_GARAGEM_SERVICE_H__
+#include "History.h"
+
+#define SHARED_SECRET   "ABRE-TE"
+
+#define GARAGEM_OK                          0
+#define GARAGEM_ERROR_REPETITION_ATTACK     1
+#define GARAGEM_ERROR_WRONG_SHARED_SECRET   2
+
+
+class GaragemService {
+public:
+    const static uint16_t GARAGEM_SERVICE_UUID              = 0x2000;
+    const static uint16_t GARAGEM_CHALLENGE_CHARACTERISTIC_UUID = 0x2001;
+    const static uint16_t GARAGEM_LAST_OPEN_TS_UUID = 0x2002;
+    const static uint16_t GARAGEM_LAST_OPEN_ID_UUID = 0x2003;
+
+    GaragemService(BLE &_ble) :
+        ble(_ble), 
+        GaragemChallenge(GARAGEM_CHALLENGE_CHARACTERISTIC_UUID, (uint8_t *)"INIT"),
+        GaragemLastOpenTS(GARAGEM_LAST_OPEN_TS_UUID, 0),
+        GaragemLastOpenID(GARAGEM_LAST_OPEN_ID_UUID, (uint8_t *)"INIT")
+    {
+        GattCharacteristic *charTable[] = {&GaragemChallenge, &GaragemLastOpenTS, &GaragemLastOpenID};
+        GattService         GaragemService(GARAGEM_SERVICE_UUID, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
+        ble.gattServer().addService(GaragemService);
+    }
+
+    GattAttribute::Handle_t getChallengeHandle() const {
+        return GaragemChallenge.getValueHandle();
+    }
+    
+    int checkMessage(uint8_t *msg) {
+        DBG("WHAT ? %s\r\n", (char *) msg);
+
+        uint64_t token;
+        char syskey[8];
+        memcpy(&token, msg, 8);
+        memcpy(&syskey, &msg[8], 8);
+        DBG("TS=%lu\tID=%c%c%c%c\tSYSKEY=%s\r\n", *((uint32_t *) msg), msg[4], msg[5], msg[6], msg[7], &msg[8]); 
+
+        //check we are not a victim of a repetion attack
+        if(history.last_ts() >= (uint32_t) msg[0]) {
+            DBG("HA HA repetion here...\r\n");
+            return GARAGEM_ERROR_REPETITION_ATTACK;
+        }
+        
+        if (strncmp(syskey,SHARED_SECRET,7)==0) {//TODO MOVE TO 8 CHARS
+            //Save our success
+            history.save(token);
+            ble.gattServer().write(GaragemLastOpenTS.getValueHandle(), (const uint8_t *)&msg[0], 4*sizeof(uint8_t));
+            ble.gattServer().write(GaragemLastOpenID.getValueHandle(), (const uint8_t *)&msg[4], 4*sizeof(uint8_t));
+        
+            return GARAGEM_OK;
+        } else {
+            return GARAGEM_ERROR_WRONG_SHARED_SECRET;
+        }
+    }
+    
+private:
+    BLE   &ble;
+    WriteOnlyArrayGattCharacteristic<uint8_t, 16>  GaragemChallenge;
+    ReadOnlyGattCharacteristic<uint32_t> GaragemLastOpenTS;
+    ReadOnlyArrayGattCharacteristic<uint8_t, 4> GaragemLastOpenID;
+    
+    History<16> history;
+};
+
+#endif /* #ifndef __BLE_GARAGEM_SERVICE_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/History.h	Tue Aug 25 22:18:21 2015 +0000
@@ -0,0 +1,50 @@
+#ifndef HISTORY_H
+#define HISTORY_H
+
+template<uint32_t BufferSize>
+class History {
+public:
+    History() : _head(0) {
+    }
+
+    ~History() {
+    }
+
+    void save(const uint64_t& data) {
+        _pool[_head++] = data;
+        _head %= BufferSize;
+    }
+
+    bool exist(const uint64_t& data) {
+        for(uint32_t i=0; i<BufferSize; i++) {
+            DBG("%llu == %llu\r\n", _pool[i], data);
+            if(_pool[i]==data) {
+                return true;
+            }
+        }
+        return false;
+    }
+    
+    uint64_t last() {
+        uint32_t prev = (_head-1+BufferSize)%BufferSize;
+        return _pool[prev];
+    }
+    
+    uint32_t last_ts() {
+        return (uint32_t) last();
+    }
+
+    /** Reset the buffer
+     *
+     */
+    void reset() {
+        _head = 0;
+    }
+
+private:
+    uint64_t _pool[BufferSize];
+    volatile uint32_t _head;
+};
+
+
+#endif
\ No newline at end of file
--- a/LEDService.h	Thu Jul 02 08:44:06 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-/* mbed Microcontroller Library
- * Copyright (c) 2006-2013 ARM Limited
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef __BLE_LED_SERVICE_H__
-#define __BLE_LED_SERVICE_H__
-
-class LEDService {
-public:
-    const static uint16_t LED_SERVICE_UUID              = 0xA000;
-    const static uint16_t LED_STATE_CHARACTERISTIC_UUID = 0xA001;
-
-    LEDService(BLEDevice &_ble, bool initialValueForLEDCharacteristic) :
-        ble(_ble), ledState(LED_STATE_CHARACTERISTIC_UUID, &initialValueForLEDCharacteristic)
-    {
-        GattCharacteristic *charTable[] = {&ledState};
-        GattService         ledService(LED_SERVICE_UUID, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
-        ble.addService(ledService);
-    }
-
-    GattAttribute::Handle_t getValueHandle() const {
-        return ledState.getValueHandle();
-    }
-
-private:
-    BLEDevice                         &ble;
-    ReadWriteGattCharacteristic<bool>  ledState;
-};
-
-#endif /* #ifndef __BLE_LED_SERVICE_H__ */
--- a/main.cpp	Thu Jul 02 08:44:06 2015 +0000
+++ b/main.cpp	Tue Aug 25 22:18:21 2015 +0000
@@ -13,30 +13,57 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#define DEBUG
+
+#ifndef DEBUG
+    #define DEVICE_SERIAL   0   //disable SERIAL so me can use P0_8 (shared with serial)
+    #define DBG(...)
+#else
+    #define DBG printf
+#endif
 
 #include "mbed.h"
 #include "BLE.h"
-#include "LEDService.h"
+#include "GaragemService.h"
+#include "ble/services/iBeacon.h"
+#include "DeviceInformationService.h"
+
+#include "Crypto.h"
+
+//how-to test:
+//create a string to write to the characteristic
+//openssl enc -aes-128-cbc -K 9734062BA852A049CF5D40593B769014 -iv A2685636521871D02306E2EB8F7027B3 -out /dev/stdout
+#define SHARED_KEY  "figueiredo"
+#define DEVICE_NAME    "Garagem"
+//openssl enc -aes-128-cbc -pass pass:********** -nosalt -P
+uint8_t myKey[16];
+uint8_t iv[16] = { 0xA2, 0x68, 0x56, 0x36, 0x52, 0x18, 0x71, 0xD0, 0x23, 0x06, 0xE2, 0xEB, 0x8F, 0x70, 0x27, 0xB3 };
 
 BLE        ble;
-DigitalOut alivenessLED(LED1);
-DigitalOut actuatedLED(LED2);
+DigitalOut actuatedLED(P0_19);
+Timeout offRelay;
+
+#ifndef DEBUG
+DigitalOut relay(P0_8);
+#endif
+
+static const uint16_t uuid16_list[] = {GaragemService::GARAGEM_SERVICE_UUID};
 
-const static char     DEVICE_NAME[] = "LED";
-static const uint16_t uuid16_list[] = {LEDService::LED_SERVICE_UUID};
+GaragemService *garagemServicePtr;
 
-LEDService *ledServicePtr;
-
+void switchOffRelay()
+{
+    actuatedLED = !actuatedLED;
+    DBG("JA CHEGA...\r\n");
+    #ifndef DEBUG
+    relay = 0;
+    #endif
+}
+    
 void disconnectionCallback(Gap::Handle_t handle, Gap::DisconnectionReason_t reason)
-{
-    ble.gap().startAdvertising();
+{   
+    ble.startAdvertising(); 
 }
-
-void periodicCallback(void)
-{
-    //alivenessLED = !alivenessLED; /* Do blinky on LED1 to indicate system aliveness. */
-}
-
 /**
  * This callback allows the LEDService to receive updates to the ledState Characteristic.
  *
@@ -44,32 +71,74 @@
  *     Information about the characterisitc being updated.
  */
 void onDataWrittenCallback(const GattWriteCallbackParams *params) {
-    if ((params->handle == ledServicePtr->getValueHandle()) && (params->len == 1)) {
-        actuatedLED = *(params->data);
+    DBG("onDataWrittenCallback: handle = %d      len = %d\r\n", params->handle, params->len);
+    
+    if ((params->handle == garagemServicePtr->getChallengeHandle()) && (params->len ==16)) {
+        DBG("onDataWrittenCallback: data = %s\r\n", (char *) (params->data));
+        actuatedLED = !actuatedLED;
+        
+        AES myAES(AES_128, myKey, iv);
+        uint8_t msg[16];
+        myAES.decrypt(msg,(uint8_t *) (params->data),16);
+        
+        if(garagemServicePtr->checkMessage(msg) == GARAGEM_OK) {  
+            #ifndef DEBUG
+            relay = 1;
+            #endif
+            DBG("ABRE-TE SESAMO!\r\n");
+
+            //please cleanup afterwards
+            offRelay.attach(&switchOffRelay, 1.0);
+            
+        } else {
+            DBG("NO SUCH LUCK...\r\n");
+        }
     }
 }
 
 int main(void)
 {
-    alivenessLED = 0;
-    actuatedLED  = 0;
+    DBG("Garagem v0\r\n");
 
-    Ticker ticker;
-    ticker.attach(periodicCallback, 1);
+    //Compute myKey from SHARED_KEY
+    MD5::computeHash(myKey, (uint8_t*) SHARED_KEY, strlen(SHARED_KEY));
+    
+    actuatedLED  = true;
+    #ifndef DEBUG
+    relay = 0;
+    #endif
 
     ble.init();
-    ble.gap().onDisconnection(disconnectionCallback);
+    ble.onDisconnection(disconnectionCallback);
     ble.gattServer().onDataWritten(onDataWrittenCallback);
 
-    bool initialValueForLEDCharacteristic = false;
-    LEDService ledService(ble, initialValueForLEDCharacteristic);
-    ledServicePtr = &ledService;
+     /**
+     * The Beacon payload has the following composition:
+     * 128-Bit / 16byte UUID = E2 0A 39 F4 73 F5 4B C4 A1 2F 17 D1 AD 07 A9 61
+     * Major/Minor  = 0x1122 / 0x3344
+     * Tx Power     = 0xC8 = 200, 2's compliment is 256-200 = (-56dB)
+     *
+     * Note: please remember to calibrate your beacons TX Power for more accurate results.
+     */
+    const uint8_t uuid[] = {0xE2, 0x0A, 0x39, 0xF4, 0x73, 0xF5, 0x4B, 0xC4,
+                            0xA1, 0x2F, 0x17, 0xD1, 0xAD, 0x07, 0xA9, 0x61};
+    uint16_t majorNumber = 3800;
+    uint16_t minorNumber = 1423;
+    uint16_t txPower     = 0xBE;
+    iBeacon ibeacon(ble, uuid, majorNumber, minorNumber, txPower);
+    
+    GaragemService garagemService(ble);
+    garagemServicePtr = &garagemService;
+
+    DeviceInformationService deviceInfo(ble, "diogogomes.com", DEVICE_NAME, "SN1", "hw-rev1", "fw-rev1", "soft-rev1");
 
     /* setup advertising */
     ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
     ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list));
     ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
     ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
+    
+    
     ble.gap().setAdvertisingInterval(1000); /* 1000ms. */
     ble.gap().startAdvertising();
 
--- a/mbed.bld	Thu Jul 02 08:44:06 2015 +0000
+++ b/mbed.bld	Tue Aug 25 22:18:21 2015 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/users/mbed_official/code/mbed/builds/7cff1c4259d7
\ No newline at end of file
+http://mbed.org/users/mbed_official/code/mbed/builds/8ed44a420e5c
\ No newline at end of file
--- a/nRF51822.lib	Thu Jul 02 08:44:06 2015 +0000
+++ b/nRF51822.lib	Tue Aug 25 22:18:21 2015 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/teams/Nordic-Semiconductor/code/nRF51822/#7455428e5ddb
+http://mbed.org/teams/Nordic-Semiconductor/code/nRF51822/#ca9c9c2cfc6a