From 2b590cbc81d10435a25d70f4f9311192dad68357 Mon Sep 17 00:00:00 2001 From: eadmaster <925171+eadmaster@users.noreply.github.com> Date: Tue, 20 Aug 2024 12:13:21 +0200 Subject: [PATCH 1/4] headless fixes (#107), added some serial cmds (#64), initial encrypted files support (#123) --- platformio.ini | 29 ++-- src/core/globals.h | 2 + src/core/passwords.cpp | 38 +++++ src/core/passwords.h | 2 + src/core/sd_functions.cpp | 156 ++++++++++++++++-- src/core/sd_functions.h | 6 +- src/core/serialcmds.cpp | 315 +++++++++++++++++++++++++++++++++---- src/main.cpp | 1 + src/modules/ir/ir_read.cpp | 27 +++- src/modules/ir/ir_read.h | 5 +- src/modules/rf/rf.cpp | 106 +++++++------ src/modules/rf/rf.h | 4 +- 12 files changed, 584 insertions(+), 107 deletions(-) create mode 100644 src/core/passwords.cpp create mode 100644 src/core/passwords.h diff --git a/platformio.ini b/platformio.ini index 52cb85dc..60b2e6de 100644 --- a/platformio.ini +++ b/platformio.ini @@ -30,8 +30,16 @@ build_flags = -DEEPROMSIZE=128 -DLH=8 -DLW=6 - -DCONFIG_FILE='"/config.conf"' + -DCONFIG_FILE='"/bruce.conf"' -w + !echo '-DGIT_COMMIT_HASH=\\"'$(git describe --always --dirty)'\\"' + ; rtl_433_ESP flags https://github.com/NorthernMan54/rtl_433_ESP/blob/main/example/OOK_Receiver/platformio.ini + ;-DOOK_MODULATION=true ; False is FSK, True is OOK + ;-DRF_CC1101="CC1101" + ;-DRF_MODULE_GDO0=9 ; CC1101 pin GDO0 + ;-DRF_MODULE_GDO2=14 ; CC1101 pin GDO2 + ;-DRF_MODULE_GDO2=RADIOLIB_NC ; CC1101 pin GDO2 + ;-DRF_MODULE_INIT_STATUS=true lib_deps = WireGuard-ESP32 @@ -53,6 +61,7 @@ lib_deps = ;lsatan/SmartRC-CC1101-Driver-Lib@^2.5.7 SmartRC-CC1101-Driver-Lib=https://github.com/bmorcelli/SmartRC-CC1101-Driver-Lib/archive/refs/heads/Bruce.zip h2zero/NimBLE-Arduino@^1.4.0 + ;https://github.com/eadmaster/rtl_433_ESP [env:m5stack-cplus2] platform = espressif32 @@ -320,14 +329,14 @@ build_flags = ;Radio Frequency (one pin modules) pin setting -DRF_TX_PINS='{ {"M5 RF433T", GROVE_SDA}, {"Groove W", GROVE_SCL}, {"GROVE Y", GROVE_SDA}}' -DRF_RX_PINS='{ {"M5 RF433R", GROVE_SCL}, {"Groove W", GROVE_SCL}, {"GROVE Y", GROVE_SDA}}' - ; connection pins using microSD sniffer module https://www.sparkfun.com/products/9419 https://docs.m5stack.com/en/core/Cardputer - -DUSE_CC1101_VIA_SPI - -DCC1101_GDO0_PIN=GROVE_SDA - -DCC1101_SS_PIN=GROVE_SCL ; chip select - -DCC1101_MOSI_PIN=14 - -DCC1101_SCK_PIN=40 - -DCC1101_MISO_PIN=39 - ;-DCC1101_GDO2_PIN=-1 + ; connection pins using microSD sniffer module https://www.sparkfun.com/products/9419 https://docs.m5stack.com/en/core/Cardputer + -DUSE_CC1101_VIA_SPI + -DCC1101_GDO0_PIN=GROVE_SDA ; 2 + -DCC1101_SS_PIN=GROVE_SCL ; 1 = chip select + -DCC1101_MOSI_PIN=14 ; CMD on SDsniffer + -DCC1101_SCK_PIN=40 ; CLK on SDsniffer + -DCC1101_MISO_PIN=39 ; DAT0 on SDsniffer + ;-DCC1101_GDO2_PIN=-1 ;Screen Setup -DHAS_SCREEN=1 @@ -741,7 +750,7 @@ build_flags = ; grove pins ; defaults from https://github.com/espressif/arduino-esp32/blob/master/variants/esp32s3/pins_arduino.h -DGROVE_SDA=8 ; default RF TX pin - -DGROVE_SCL=9 ; default IR/RF RX pin + -DGROVE_SCL=46 ; default IR/RF RX pin ;-DALLOW_ALL_GPIO_FOR_IR_RF=1 ; Set this option to make use of all GPIOs, from 1 to 44 to be chosen, except TFT and SD pins ; ir led pin diff --git a/src/core/globals.h b/src/core/globals.h index 2fd686c9..e081258f 100644 --- a/src/core/globals.h +++ b/src/core/globals.h @@ -109,6 +109,8 @@ extern int RfModule; extern float RfFreq; +extern String cachedPassword; + // Screen sleep control variables extern unsigned long previousMillis; extern bool isSleeping; diff --git a/src/core/passwords.cpp b/src/core/passwords.cpp new file mode 100644 index 00000000..6a95570a --- /dev/null +++ b/src/core/passwords.cpp @@ -0,0 +1,38 @@ +#include "mbedtls/aes.h" +#include "mbedtls/md.h" +#include "mbedtls/pkcs5.h" +#include + + +String aes_decrypt(uint8_t* inputData, size_t fileSize, const String& password_str) { + // generate key, iv, salt + const char *password = password_str.c_str(); + unsigned char key[32]; + unsigned char iv[16]; + unsigned char salt[8] = { /* The salt used by OpenSSL during encryption */ }; + + mbedtls_md_context_t md_ctx; + mbedtls_md_init(&md_ctx); + mbedtls_md_setup(&md_ctx, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 1); + + // Derive key and IV using PBKDF2 + mbedtls_pkcs5_pbkdf2_hmac(&md_ctx, (unsigned char*)password, strlen(password), salt, 8, 10000, 32, key); + mbedtls_pkcs5_pbkdf2_hmac(&md_ctx, (unsigned char*)password, strlen(password), salt, 8, 10000, 16, iv); + + mbedtls_md_free(&md_ctx); + + unsigned char *outputData = new unsigned char[fileSize]; + mbedtls_aes_context aes; + mbedtls_aes_init(&aes); + mbedtls_aes_setkey_dec(&aes, key, 256); + + mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_DECRYPT, fileSize, iv, inputData, outputData); + + mbedtls_aes_free(&aes); + + // Convert the decrypted data to a string + String decryptedText = String(outputData, fileSize); + free(outputData); + + return decryptedText; +} diff --git a/src/core/passwords.h b/src/core/passwords.h new file mode 100644 index 00000000..b7240a0c --- /dev/null +++ b/src/core/passwords.h @@ -0,0 +1,2 @@ + +String aes_decrypt(uint8_t* inputData, size_t fileSize, const String& password_str); \ No newline at end of file diff --git a/src/core/sd_functions.cpp b/src/core/sd_functions.cpp index db85fe63..a57a0882 100644 --- a/src/core/sd_functions.cpp +++ b/src/core/sd_functions.cpp @@ -3,10 +3,12 @@ #include "sd_functions.h" #include "mykeyboard.h" // usinf keyboard when calling rename #include "display.h" // using displayRedStripe as error msg +#include "passwords.h" #include "modules/others/audio.h" #include "modules/rf/rf.h" #include "modules/ir/TV-B-Gone.h" #include "modules/others/bad_usb.h" +#include "modules/others/qrcode_menu.h" struct FilePage { int pageIndex; @@ -284,6 +286,111 @@ String readLineFromFile(File myFile) { return line; } + +/*************************************************************************************** +** Function name: readSmallFile +** Description: read a small (<3KB) file and return its contents as a single string +** on any error returns an empty string +***************************************************************************************/ +String readSmallFile(FS &fs, String filepath) { + String fileContent = ""; + File file; + + file = fs.open(filepath, FILE_READ); + if (!file) return ""; + + size_t fileSize = file.size(); + if(fileSize > 1024*3) { // 3K is the max + displayError("File is too big"); + Serial.println("File is too big"); + return ""; + } + + fileContent = file.readString(); + + file.close(); + return fileContent; +} + +/*************************************************************************************** +** Function name: getFileSize +** Description: get a file size without opening +***************************************************************************************/ +size_t getFileSize(FS &fs, String filepath) { + if(&fs == &SD) filepath = "/sd" + filepath; + else if(&fs == &LittleFS) filepath = "/littlefs" + filepath; + else return 0; // not found + struct stat st; + memset(&st, 0, sizeof(struct stat)); + if (stat(filepath.c_str(), &st) != 0) return 0; // stat error + // else + return st.st_size; +} + +bool is_valid_ascii(const String &text) { + for (int i = 0; i < text.length(); i++) { + char c = text[i]; + // Check if the character is within the printable ASCII range or is a newline/carriage return + if (!(c >= 32 && c <= 126) && c != 10 && c != 13) { + return false; // Invalid character found + } + } + return true; // All characters are valid +} + +String readDecryptedAesFile(FS &fs, String filepath) { + File file; + + file = fs.open(filepath, FILE_READ); + if (!file) return ""; + + size_t fileSize = file.size(); + if(fileSize > 1024*3) { // 3K is the max + displayError("File is too big"); + return ""; + } + + char buffer[fileSize]; + size_t bytesRead = file.readBytes(buffer, fileSize); + //Serial.print("fileSize:"); + //Serial.println(fileSize); + //Serial.println(bytesRead); + + /* + // read the whole file with a single call + char buffer[fileSize + 1]; + size_t bytesRead = file.readBytes(buffer, fileSize); + buffer[bytesRead] = '\0'; // Null-terminate the string + return String(buffer); + */ + + if (bytesRead==0) { + Serial.println("empty cypherText"); + return ""; + } + // else + + if(cachedPassword.length()==0) { + cachedPassword = keyboard("", 32, "password"); + if(cachedPassword.length()==0) return ""; // cancelled + } + + // else try to decrypt + String plaintext = aes_decrypt((uint8_t*)buffer, bytesRead, cachedPassword); + + // check if really plaintext + if(!is_valid_ascii(plaintext)) { + // invalidate cached password -> will ask again on the next try + cachedPassword = ""; + Serial.println("invalid password"); + Serial.println(plaintext); + return ""; + } + // else + return plaintext; +} + + /*************************************************************************************** ** Function name: sortList ** Description: sort files for name @@ -434,16 +541,14 @@ String loopSD(FS &fs, bool filePicker, String allowed_ext) { closeSdCard(); setupSdCard(); bool exit = false; + returnToMenu=true; // make sure menu is redrawn when quitting in any point readFs(fs, Folder, fileList, allowed_ext); for(int i=0; i