diff --git a/Locker/Bluetooth.ino b/Locker/Bluetooth.ino index d56311b..9e46859 100644 --- a/Locker/Bluetooth.ino +++ b/Locker/Bluetooth.ino @@ -17,11 +17,12 @@ boolean stateBT() { * CONNECTION TO CLIENT */ void connectBT() { + Serial.println("Pairing..."); btSerial.println(FC(IDd)); reqOp(); resetCount(); connected = true; - Serial.println("Paired"); + Serial.println("Paired!"); } @@ -46,12 +47,12 @@ void disconnectBT() { * false = parse or message error */ boolean readBT() { - Serial.println("Reading..."); - char input[237]; - (btSerial.readStringUntil('\n')).toCharArray(input, 237); + char input[200]; + (btSerial.readStringUntil('\n')).toCharArray(input, 200); int s = strlen(input); - if(s>15 && s<237) { + if(s>15 && s<201) { + Serial.println("Reading..."); delay(100); int block = fromClient(input, s); @@ -61,6 +62,12 @@ boolean readBT() { return false; } +void writeBT(char * output, int size) { + char * enc = encodeMsg(output, size); + btSerial.println(enc); + delete enc; +} + /* * DECREMENT COUNTDOWN diff --git a/Locker/Encryption.ino b/Locker/Encryption.ino index da896d6..a4403a4 100644 --- a/Locker/Encryption.ino +++ b/Locker/Encryption.ino @@ -1,7 +1,7 @@ /* * MESSAGE ENCRYPTION (with AES-128) */ -void encrypt(char * plain, int msgSize) { +void encrypt(char * plain, int msgSize) { randomIV(); aes128_cbc_enc(key, iv, plain, msgSize); } diff --git a/Locker/Locker.ino b/Locker/Locker.ino index 904e5fe..3223228 100644 --- a/Locker/Locker.ino +++ b/Locker/Locker.ino @@ -1,182 +1,227 @@ -#include -#include -#include -#include -#include -#include - -#define FC(string_constant) (reinterpret_cast(string_constant)) -#define BT_PWR A2 // PIN bluetooth power -#define BT_ST A3 // PIN bluetooth state -#define BT_RX A4 // PIN bluetooth reception -#define BT_TX A5 // PIN bluetooth trasmission - -SoftwareSerial btSerial(BT_TX, BT_RX); // Bluetooth serial -boolean connected = false; // Bluetooth state -int countdown = 0; // Bluetooth time - -char const IDd[] PROGMEM = "1234567890device"; // Device id -char N[17]; // Last sent nonce -uint8_t key[] = {0x0c, 0xc0, 0x52, 0xf6, 0x7b, 0xbd, 0x05, 0x0e, 0x75, 0xac, 0x0d, 0x43, 0xf1, 0x0a, 0x8f, 0x35}; -uint8_t iv[16]; - - -/* - * INIT SETUP - */ -void setup() { - pinMode(LED_BUILTIN, OUTPUT); - pinMode(BT_PWR, OUTPUT); - pinMode(BT_ST, INPUT); - digitalWrite(BT_PWR, HIGH); - - unsigned long seed = analogRead(0); - seed += analogRead(0) << 10; - seed += analogRead(0) << 20; - seed += ((analogRead(0) & 0x3) << 30); - randomSeed(seed); - - Serial.begin(9600); - btSerial.begin(4800); - - Serial.println("STARTING"); -} - - -/* - * MAIN - */ -void loop() { - while(stateBT()) { - if(btSerial.available()) { - if(!readBT()) reqOp(); - else resOp(); - } - - waitCount(); - } - - delay(100); -} - - -/* - * GET MESSAGE FROM CLIENT - */ -int fromClient(char * input, int msgSize) { - int decSize = Base64.decodedLength(input, msgSize); - char * decoded = decodeMsg(input, msgSize); - char message[decSize-31]; - uint8_t hmac[32]; - - memcpy(message, decoded, decSize-32); - memcpy(hmac, decoded + (decSize-32), 32); - message[decSize-32] = '\0'; - delete decoded; - - if(memcmp(hmac, hash(message, (decSize-32)), 32) == 0) { - int block = cbcLength(decSize-32-16); - char cipher[block+1]; - - memcpy(iv, message, 16); - memcpy(cipher, message+16, block); - cipher[block] = '\0'; - decrypt(cipher, block); - - memcpy(input, cipher, block+1); - return block; - } - - return 0; -} - - -/* - * SEND MESSAGE TO CLIENT - */ -void toClient(String message) { - int msgSize = message.length(); - int block = cbcLength(msgSize); - for(int i=0; i doc; - doc["IDd"] = FC(IDd); - doc["N1"] = N; - serializeJson(doc, message); - - toClient(message); -} - - -/* - * CHECK OP ACCESS KEY - */ -boolean checkOp(char * otp, int msgSize) { - StaticJsonDocument<120> doc; - DeserializationError error = deserializeJson(doc, otp); - const char * ctr = doc["N1"]; - - if(error || memcmp(ctr, N, 16) != 0) return false; - - ctr = doc["N2"]; - memcpy(N, ctr, 16); - ctr = doc["OP"]; - - Serial.print("Op requested: "); - Serial.println(ctr); - Serial.println("OP DONE!"); - - return true; -} - - -/* - * ANSWER TO OP REQUEST - */ -void resOp() { - String message; - StaticJsonDocument<100> doc; - doc["RES"] = true; - doc["N2"] = N; - newNonce(); - doc["N3"] = N; - serializeJson(doc, message); - - Serial.println("Op response"); - - toClient(message); -} - - -/* - * RANDOM NONCE GENERATION - */ -void newNonce() { - for(int i = 0; i<8; i++) snprintf(N+(i*2), 3, "%02x", random(256)); +#include +#include +#include +#include +#include +#include +#include + +#define FC(string_constant) (reinterpret_cast(string_constant)) +#define BT_PWR A2 // PIN bluetooth power +#define BT_ST A3 // PIN bluetooth state +#define BT_RX A4 // PIN bluetooth reception +#define BT_TX A5 // PIN bluetooth trasmission + +SoftwareSerial btSerial(BT_TX, BT_RX); // Bluetooth serial +boolean connected = false; // Bluetooth state +int countdown = 0; // Bluetooth time +char const IDd[] PROGMEM = "1234567890device"; // Device id + +const struct uECC_Curve_t * curve = uECC_secp192r1(); +uint8_t privKeyDev[] = { 0x02, 0xf2, 0x82, 0x21, 0xfb, 0x3a, 0x22, 0xa4, 0x48, 0x92, 0x8c, 0x44, + 0x99, 0x61, 0x20, 0xfb, 0xf7, 0xbe, 0x2d, 0xa3, 0xf6, 0xcd, 0xc2, 0xe2 }; +uint8_t pubKeySer[] = { 0xdc, 0x27, 0xa5, 0x67, 0x1d, 0xcb, 0x00, 0x0d, 0xc4, 0x1b, 0x99, 0x96, + 0x84, 0x0b, 0xb3, 0xc0, 0x08, 0xe2, 0x91, 0x08, 0xd1, 0x59, 0x49, 0x40, + 0x1f, 0x05, 0x7a, 0x28, 0xe0, 0x46, 0x81, 0x7e, 0xfa, 0xcc, 0x67, 0x90, + 0xf0, 0x5d, 0xef, 0xfd, 0x13, 0x78, 0xf5, 0xaf, 0x2d, 0xd8, 0xa9, 0x21 }; +uint8_t key[16]; +uint8_t iv[16]; + + +/* + * RANDOM CURVE + */ +static int RNG(uint8_t *dest, unsigned size) { + // Use the least-significant bits from the ADC for an unconnected pin (or connected to a source of + // random noise). This can take a long time to generate random data if the result of analogRead(0) + // doesn't change very frequently. + while (size) { + uint8_t val = 0; + for(unsigned i = 0; i < 8; ++i) { + int init = analogRead(0); + int count = 0; + while(analogRead(0) == init) + ++count; + + if(count == 0) + val = (val << 1) | (init & 0x01); + else + val = (val << 1) | (count & 0x01); + } + *dest = val; + ++dest; + --size; + } + + return 1; +} + + +/* + * INIT SETUP + */ +void setup() { + pinMode(BT_PWR, OUTPUT); + pinMode(BT_ST, INPUT); + digitalWrite(BT_PWR, HIGH); + + unsigned long seed = analogRead(0); + seed += analogRead(0) << 10; + seed += analogRead(0) << 20; + seed += ((analogRead(0) & 0x3) << 30); + randomSeed(seed); + uECC_set_rng(&RNG); + + Serial.begin(9600); + btSerial.begin(9600); + Serial.println("STARTED"); +} + + +/* + * MAIN + */ +void loop() { + while(stateBT()) { + if(btSerial.available()) { + if(readBT()) resOp(); + } + + //waitCount(); + } + + delay(100); +} + + +/* + * GET MESSAGE FROM CLIENT + */ +int fromClient(char * input, int msgSize) { + if (msgSize == 20) { + uint8_t pubKeyEph[48]; + uint8_t privKeyEph[24]; + uECC_make_key(pubKeyEph, privKeyEph, curve); + newShared(pubKeySer, privKeyEph); + + char packet[49]; + memcpy(packet, pubKeyEph, 48); + packet[48] = '\0'; + + char * enc = encodeMsg(packet, sizeof(packet)-1); + btSerial.println(enc); + Serial.println("Authorization sent"); + delete enc; + + return 0; + } + + int decSize = Base64.decodedLength(input, msgSize); + char * decoded = decodeMsg(input, msgSize); + int block = 0; + + if(memcmp(decoded + (decSize-32), hash(decoded, decSize-32), 32) == 0) { + block = cbcLength(decSize-32-16); + memcpy(iv, decoded, 16); + decrypt(decoded+16, block); + memcpy(input, decoded+16, block); + input[block] = '\0'; + } + + delete decoded; + return block; +} + + +/* + * SEND MESSAGE TO CLIENT + */ +void toClient(String message) { + int msgSize = message.length(); + int block = cbcLength(msgSize); + for(int i=0; i doc; + DeserializationError error = deserializeJson(doc, aop); + uint8_t pubKeyEph[48]; + const char * ctr = doc["PK"]; + char * decoded = decodeMsg((char *)ctr, 64); + memcpy(pubKeyEph, decoded, 48); + delete decoded; + ctr = doc["OP"]; + + if(!newShared(pubKeyEph, privKeyDev)) return false; + + Serial.println(ctr); + Serial.println("Operation DONE!"); + + return true; +} + + +/* + * ANSWER TO OP REQUEST + */ +void resOp() { + String message; + StaticJsonDocument<16> doc; + doc["RES"] = true; + serializeJson(doc, message); + + Serial.println("Response sent"); + + toClient(message); +} + + +/* + * GENERATE SHARED KEY + */ +boolean newShared(uint8_t * pub, uint8_t * priv) { + uint8_t shared[24]; + if(!uECC_shared_secret(pub, priv, shared, curve)) return false; + + Sha256.init(); + Sha256.write(shared, 24); + memcpy(key, Sha256.result(), 16); + + return true; } diff --git a/README.md b/README.md index ac287ad..0d68493 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,17 @@ # Locker Device The device is an Arduino Uno, with HC-05 Bluetooth module, to simulate a locker, which must be opened or closed if the user is authorized +See https://github.com/DistributedSystemsProject/AuthorizationServer/tree/ECC to understand the used protocol. + +In the MASTER branch there is the version of the server, without the ECC key exchange: https://github.com/DistributedSystemsProject/AuthorizationServer/ + # Requirements Install the external libaries: 1. Base64 from https://github.com/agdl/Base64 2. AES-128 Enc/Dec from https://github.com/DavyLandman/AESLib 3. SHA-256 Hmac from https://github.com/daknuett/cryptosuite2 +4. JSON from https://github.com/bblanchon/ArduinoJson +5. ECC from https://github.com/kmackay/micro-ecc # Usage Connect the Bluetooth module, on these Arduino pins: @@ -14,15 +20,16 @@ Connect the Bluetooth module, on these Arduino pins: - A4 // PIN bluetooth reception - A5 // PIN bluetooth transmission -Run the code on your device - -When the operation is successfull, the code prints the string: -"OP DONE!" -(You can use this software to authorize any operation (open/lock a locker, turn on/off the light...) +Run the code on your device. -It is safe to regenerate the key, before using it +When the operation is successful, the code prints on the Serial Monitor, the following string: +"Operation DONE!" # Other Software Mobile App (React Native iOS/Android): https://github.com/DistributedSystemsProject/MobileApp Authorization Server (Lua + Redis DB): https://github.com/DistributedSystemsProject/AuthorizationServer + +# Known Issues +The code works only with Arduino AVR Boards 1.6.21. If you update to a newer version, the program can't start (only tested with Arduino IDE on Windows 10). + pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy