Skip to content

Commit

Permalink
switched to xor encryption, added cmds in file browser and webui (pr3…
Browse files Browse the repository at this point in the history
  • Loading branch information
eadmaster committed Aug 30, 2024
1 parent fa239bd commit c11c591
Show file tree
Hide file tree
Showing 12 changed files with 241 additions and 224 deletions.
31 changes: 29 additions & 2 deletions src/core/mykeyboard.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ bool menuPress(int bot) {
bool checkNextPress(){
#if defined (CARDPUTER)
Keyboard.update();
if(Keyboard.isKeyPressed('/') || Keyboard.isKeyPressed('.'))
if(Keyboard.isKeyPressed('.'))
#elif defined(CORE2) || defined(CORE)
M5.update();
if(M5.BtnC.isPressed())
Expand Down Expand Up @@ -108,7 +108,7 @@ bool checkPrevPress() {
if(axp192.GetBtnPress())
#elif defined(CARDPUTER)
Keyboard.update();
if(Keyboard.isKeyPressed(',') || Keyboard.isKeyPressed(';'))
if(Keyboard.isKeyPressed(';'))
#elif defined(CORE2) || defined(CORE)
M5.update();
if(M5.BtnA.isPressed())
Expand Down Expand Up @@ -215,6 +215,33 @@ bool checkAnyKeyPress() {
}

#ifdef CARDPUTER

bool checkNextPagePress(){
Keyboard.update();
if(Keyboard.isKeyPressed('/')) // right arrow
{
if(wakeUpScreen()){
delay(200);
return false;
}
return true;
}
return false;
}

bool checkPrevPagePress() {
Keyboard.update();
if(Keyboard.isKeyPressed(',')) // left arrow
{
if(wakeUpScreen()){
delay(200);
return false;
}
return true;
}
return false;
}

void checkShortcutPress(){
// shortctus to quickly starts apps
Keyboard.update();
Expand Down
2 changes: 2 additions & 0 deletions src/core/mykeyboard.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ bool checkEscPress();
void checkShortcutPress();
int checkNumberShortcutPress();
char checkLetterShortcutPress();
bool checkNextPagePress();
bool checkPrevPagePress();
#endif

bool checkAnyKeyPress();
Expand Down
164 changes: 23 additions & 141 deletions src/core/passwords.cpp
Original file line number Diff line number Diff line change
@@ -1,149 +1,31 @@
#include "mbedtls/aes.h"
#include "mbedtls/md.h"
#include "mbedtls/pkcs5.h"
#include <Arduino.h>

#include <mbedtls/base64.h>
#include <mbedtls/sha256.h>
#include <mbedtls/pkcs5.h>
#include <mbedtls/gcm.h>
#include <mbedtls/error.h> // error code to string conversion

#include <mbedtls/entropy.h> // entropy gathering
#include <mbedtls/ctr_drbg.h> // CSPRNG
#include <mbedtls/error.h> // error code to string conversion
#include <mbedtls/md.h> // hash algorithms
#include <mbedtls/pkcs5.h> // pbkdf2 KDF


const size_t iterations = 1000;
const size_t keyLength = 32;


String generateRandom(int len) {
#include <Arduino.h>
#include <MD5Builder.h>


String xorEncryptDecrypt(const String &input, const String &password) {
uint8_t md5Hash[16];

MD5Builder md5;
md5.begin();
md5.add(password);
md5.calculate();
md5.getBytes(md5Hash); // Store MD5 hash in the output array

String output = input; // Copy input to output for modification
for (size_t i = 0; i < input.length(); i++) {
output[i] = input[i] ^ md5Hash[i % 16]; // XOR each byte with the MD5 hash
}

return output;
}


String aes_encrypt(String& plaintext, const String& password_str) {
// buggy? https://github.com/espressif/arduino-esp32/issues/3719

/*
unsigned char* salt = generateRandom(16).c_str(); // salt size = 16
unsigned char* iv = generateRandom(12).c_str(); // iv size = 12
unsigned char* tag = generateRandom(16).c_str(); // tag size = 16
mbedtls_gcm_context ctx;
mbedtls_gcm_init(&ctx);

mbedtls_gcm_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, key, 256);
mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_ENCRYPT, plaintext_len, iv, 12, ad, 16, plaintext.c_str(), ciphertext, tag);
int ret = mbedtls_gcm_crypt_and_tag(&aes, MBEDTLS_GCM_ENCRYPT, strlen(text), (const unsigned char*) iv, strlen(iv), NULL, NULL, (const unsigned char*) text, (unsigned char*) encrypted, strlen(tag), (unsigned char*) tag);
mbedtls_gcm_free(&ctx);
*/
// WIP
return plaintext;
String encryptString(String& plaintext, const String& password_str) {
return xorEncryptDecrypt(plaintext, password_str);
}


String aes_decrypt(String& encryptedBase64, const String& password_str) {

const char* password = password_str.c_str();
//char mbed_err[MBED_ERR_BUF];
int ret;

// decode base64
size_t decodedLen;
mbedtls_base64_decode(NULL, 0, &decodedLen, (const unsigned char *)encryptedBase64.c_str(), encryptedBase64.length());
unsigned char* decodedData = (unsigned char*)malloc(decodedLen);
memset(decodedData, 0, decodedLen);
mbedtls_base64_decode(decodedData, decodedLen, &decodedLen, (const unsigned char *)encryptedBase64.c_str(), encryptedBase64.length());
if(decodedLen<=44) {
Serial.println("base64 decode error or incomplete file");
return "";
}

unsigned char* salt = decodedData;
unsigned char* iv = decodedData + 16; // salt size = 16
unsigned char* tag = decodedData + 28; // salt+iv size = 16+12
unsigned char* encryptedContent = decodedData + 44; // salt+iv+tag size = 16+12+16
size_t encryptedContentLen = decodedLen - 44;

// Derive key using PBKDF2
unsigned char key[keyLength];
mbedtls_md_context_t md_ctx;
const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);

mbedtls_md_init(&md_ctx);
ret = mbedtls_md_setup(&md_ctx,
md_info,
1); // non-zero implies HMAC is going to be used (0 saves memory, but is less secure)
if (md_info == NULL || ret != 0) {
Serial.println("Hash algorithm setup failed");
Serial.println(ret);
free(decodedData);
//mbedtls_strerror(ret, mbed_err, MBED_ERR_BUF);
//mbedtls_printf( "mbedTLS ERROR: %s\n", mbed_err);
return "";
}

ret = mbedtls_pkcs5_pbkdf2_hmac(
&md_ctx,
(const unsigned char*)password,
strlen(password),
salt,
16, // salt_bytes
iterations,
keyLength,
key
);

mbedtls_md_free(&md_ctx);

if (ret != 0) {
Serial.println("Key derivation failed");
Serial.println(ret);
free(decodedData);
//mbedtls_strerror(ret, mbed_err, MBED_ERR_BUF);
//mbedtls_printf( "mbedTLS ERROR: %s\n", mbed_err);
return "";
}

// Decrypt using AES-GCM
unsigned char decryptedContent[encryptedContentLen] = {0};
mbedtls_gcm_context gcm;
mbedtls_gcm_init(&gcm);

ret = mbedtls_gcm_setkey(&gcm, MBEDTLS_CIPHER_ID_AES, key, keyLength * 8);

if (ret != 0) {
Serial.println("Set Key failed");
free(decodedData);
Serial.println(ret);
//mbedtls_strerror(ret, mbed_err, MBED_ERR_BUF);
//mbedtls_printf( "mbedTLS ERROR: %s\n", mbed_err);
return "";
}

ret = mbedtls_gcm_auth_decrypt(&gcm, encryptedContentLen, iv, 12, NULL, 0, tag, 16, encryptedContent, decryptedContent);
String r = String((char*)decryptedContent);

mbedtls_gcm_free(&gcm);
free(decodedData);
//free(decryptedContent);

if (ret == 0) {
// Successfully decrypted
return(r);
} else {
// Decryption failed
Serial.println("Decryption failed");
Serial.println(ret);
//mbedtls_strerror(ret, mbed_err, MBED_ERR_BUF);
//mbedtls_printf( "mbedTLS ERROR: %s\n", mbed_err);
return("");
}
String decryptString(String& cypertext, const String& password_str) {
return xorEncryptDecrypt(cypertext, password_str);
}
4 changes: 2 additions & 2 deletions src/core/passwords.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@

#include <Arduino.h>

String aes_encrypt(String& plaintext, const String& password_str);
String encryptString(String& plaintext, const String& password_str);

String aes_decrypt(String& encryptedBase64, const String& password_str);
String decryptString(String& cypertext, const String& password_str);
71 changes: 45 additions & 26 deletions src/core/sd_functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -375,28 +375,30 @@ String crc32File(FS &fs, String filepath) {
return(String(s));
}

String readDecryptedAesFile(FS &fs, String filepath) {
String base64enc = readSmallFile(fs, filepath);
//Serial.println(base64enc);
if(base64enc.length() == 0) return "";
String readDecryptedFile(FS &fs, String filepath) {
String cyphertext = readSmallFile(fs, filepath);
if(cyphertext.length() == 0) return "";

if(cachedPassword.length()==0) {
cachedPassword = keyboard("", 32, "password");
if(cachedPassword.length()==0) return ""; // cancelled
}

//Serial.println(cyphertext);
//Serial.println(cachedPassword);

// else try to decrypt
String plaintext = aes_decrypt(base64enc, cachedPassword);
String plaintext = decryptString(cyphertext, cachedPassword);

/*
// check if really plaintext
if(!isValidAscii(plaintext)) {
// invalidate cached password -> will ask again on the next try
cachedPassword = "";
Serial.println("invalid password");
Serial.println(plaintext);
//Serial.println(plaintext);
return "";
}*/
}

// else
return plaintext;
}
Expand Down Expand Up @@ -654,45 +656,44 @@ String loopSD(FS &fs, bool filePicker, String allowed_ext) {
delay(200);
txSubFile(&fs, filepath);
}});
if(filepath.endsWith(".bjs") || filepath.endsWith(".js")) options.insert(options.begin(), {"Run JS Script", [&]() {
if(filepath.endsWith(".bjs") || filepath.endsWith(".js")) options.insert(options.begin(), {"JS Script Run", [&]() {
delay(200);
run_bjs_script_headless(fs, filepath);
}});
#if defined(USB_as_HID)
if(filepath.endsWith(".txt")) {
options.push_back({"BadUSB Run", [&]() {
Kb.begin(); USB.begin();
// TODO: set default keyboard layout
key_input(fs, filepath);
Kb.end();
}});
/*
options.push_back({"USB HID Type", [&]() {
Kb.begin(); USB.begin();
Kb.print(readSmallFile(fs, filepath).c_str()); // buggy?
//String t = readSmallFile(fs, filepath).c_str();
//Kb.write((const uint8_t*) t.c_str(), t.length());
}});*/
String t = readSmallFile(fs, filepath);
displayInfo("Typing");
key_input_from_string(t);
}});
}
if(filepath.endsWith(".aes")) { // aes encrypted files
if(filepath.endsWith(".enc")) { // aes encrypted files
options.insert(options.begin(), {"Decrypt+Type", [&]() {
String plaintext = readDecryptedAesFile(fs, filepath);
if(plaintext.length()==0) return displayError("invalid password"); // file is too big or cannot read, or cancelled
String plaintext = readDecryptedFile(fs, filepath);
if(plaintext.length()==0) // file is too big or cannot read, or cancelled
// else
Kb.begin(); USB.begin();
Kb.print(plaintext.c_str());
key_input_from_string(plaintext);
}});
}
#endif
if(filepath.endsWith(".aes")) { // aes encrypted files
if(filepath.endsWith(".enc")) { // aes encrypted files
options.insert(options.begin(), {"Decrypt+Show", [&]() {
String plaintext = readDecryptedAesFile(fs, filepath);
if(plaintext.length()==0) return; // file is too big or cannot read, or cancelled
// else
String plaintext = readDecryptedFile(fs, filepath);
delay(200);
if(plaintext.length()==0) return displayError("Decryption failed");

//if(plaintext.length()<..)
displaySuccess(plaintext);
while(!checkAnyKeyPress()) delay(100);
// else
// TODO: show in the text viewer

}});
}
#if defined(HAS_NS4168_SPKR)
Expand Down Expand Up @@ -743,6 +744,8 @@ String loopSD(FS &fs, bool filePicker, String allowed_ext) {
}

#ifdef CARDPUTER
if(checkEscPress()) break; // quit

/* TODO: go back 1 level instead of quitting
if(Keyboard.isKeyPressed(KEY_BACKSPACE)) {
// go back 1 level
Expand All @@ -752,7 +755,23 @@ String loopSD(FS &fs, bool filePicker, String allowed_ext) {
redraw=true;
continue;
}*/
if(checkEscPress()) break;

const short PAGE_JUMP_SIZE = 5;
if(checkNextPagePress()) {
index += PAGE_JUMP_SIZE;
if(index>maxFiles) index=maxFiles-1; // check bounds
redraw = true;
continue;
}
if(checkPrevPagePress()) {
index -= PAGE_JUMP_SIZE;
if(index<0) index = 0; // check bounds
redraw = true;
continue;
}

// check letter shortcuts

char pressed_letter = checkLetterShortcutPress();
if(pressed_letter>0) {
//Serial.println(pressed_letter);
Expand Down
2 changes: 1 addition & 1 deletion src/core/sd_functions.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ String md5File(FS &fs, String filepath);

String crc32File(FS &fs, String filepath);

String readDecryptedAesFile(FS &fs, String filepath);
String readDecryptedFile(FS &fs, String filepath);

void readFs(FS fs, String folder, String result[][3], String allowed_ext = "*");

Expand Down
Loading

0 comments on commit c11c591

Please sign in to comment.