Skip to content

Commit

Permalink
refactor storage encryption
Browse files Browse the repository at this point in the history
  • Loading branch information
tcsullivan committed May 11, 2024
1 parent 018ed78 commit b626f4e
Show file tree
Hide file tree
Showing 8 changed files with 74 additions and 81 deletions.
2 changes: 1 addition & 1 deletion noisemeter-device/UUID/UUID.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ void UUID::generate()
}


char * UUID::toCharArray()
const char * UUID::toCharArray() const
{
// if (_upperCase)
// {
Expand Down
4 changes: 2 additions & 2 deletions noisemeter-device/UUID/UUID.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,11 @@ class UUID : public Printable
* Make a UUID string
* @return String representation of UUID
*/
char * toCharArray();
const char * toCharArray() const;
/**
* Implicit conversion to a String object.
*/
operator String() {
operator String() const {
return toCharArray();
}

Expand Down
4 changes: 2 additions & 2 deletions noisemeter-device/config.h.example
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
#ifndef CONFIG_H
#define CONFIG_H

// Uncomment to print passkey over serial (for debugging).
//#define STORAGE_SHOW_PASSKEY
// Uncomment to print credentials over serial (for debugging).
//#define STORAGE_SHOW_CREDENTIALS

// Define only *one* of the follwoing board options.
// If using PlatformIO, the selected 'env' will override this selection.
Expand Down
25 changes: 7 additions & 18 deletions noisemeter-device/noisemeter-device.ino
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
#include "certs.h"
#include "secret.h"
#include "spl-meter.h"
#include "secret-store.h"
#include "storage.h"
#include "ota-update.h"
#include "UUID/UUID.h"
Expand Down Expand Up @@ -151,7 +150,10 @@ void setup() {
SERIAL.println(buildDeviceId());
SERIAL.println("Initializing...");

Creds.begin();
Creds.begin(buildDeviceId());
#ifdef STORAGE_SHOW_CREDENTIALS
SERIAL.println(Creds);
#endif

SPL.initMicrophone();
packets.emplace_front();
Expand Down Expand Up @@ -299,9 +301,8 @@ void printReadingToConsole(double reading) {
void saveNetworkCreds(WebServer& httpServer) {
// Confirm that the form was actually submitted.
if (httpServer.hasArg("ssid") && httpServer.hasArg("psk")) {
const auto id = String(buildDeviceId());
const auto ssid = Secret::encrypt(id, httpServer.arg("ssid"));
const auto psk = Secret::encrypt(id, httpServer.arg("psk"));
const auto ssid = httpServer.arg("ssid");
const auto psk = httpServer.arg("psk");

// Confirm that the given credentials will fit in the allocated EEPROM space.
if (!ssid.isEmpty() && Creds.canStore(ssid) && Creds.canStore(psk)) {
Expand All @@ -326,20 +327,8 @@ UUID buildDeviceId()

int tryWifiConnection()
{
//const auto ssid = Creds.get(Storage::Entry::SSID);

//if (ssid.isEmpty())
// return -1;

//SERIAL.print("Ready to connect to ");
//SERIAL.println(ssid);

const auto ssid = Creds.get(Storage::Entry::SSID);
const auto psk = Creds.get(Storage::Entry::Passkey);

WiFi.mode(WIFI_STA);
const auto id = String(buildDeviceId());
const auto stat = WiFi.begin(Secret::decrypt(id, ssid).c_str(), Secret::decrypt(id, psk).c_str());
const auto stat = WiFi.begin(Creds.get(Storage::Entry::SSID).c_str(), Creds.get(Storage::Entry::Passkey).c_str());
if (stat == WL_CONNECT_FAILED)
return -1;

Expand Down
50 changes: 18 additions & 32 deletions noisemeter-device/secret-store.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,75 +14,61 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "board.h"
#include "secret-store.h"
#include "board.h"

#if defined(BOARD_ESP32_PCB)

#include <esp_hmac.h>
#include <mbedtls/aes.h>

constexpr static unsigned BITS = 256; // do not change

namespace Secret {

String encrypt(String key, String in)
void SecretStore::encrypt(const char *in, uint8_t *out, unsigned N) const noexcept
{
mbedtls_aes_context aes;
mbedtls_aes_init(&aes);

const auto kb = key.c_str();
const auto kl = key.length();
String k (key);
{
uint8_t hmac[BITS / 8];
esp_hmac_calculate(HMAC_KEY0, kb, kl, hmac);
esp_hmac_calculate(HMAC_KEY0, k.c_str(), k.length(), hmac);
mbedtls_aes_setkey_enc(&aes, hmac, BITS);
}

char out[in.length()];
mbedtls_aes_crypt_ecb(&aes, MBEDTLS_AES_ENCRYPT,
reinterpret_cast<const uint8_t *>(in.c_str()),
reinterpret_cast<uint8_t *>(out));
return out;
uint8_t iv[16];
mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_ENCRYPT, N, iv,
reinterpret_cast<const uint8_t *>(in), out);
}

String decrypt(String key, String in)
void SecretStore::decrypt(const uint8_t *in, char *out, unsigned N) const noexcept
{
mbedtls_aes_context aes;
mbedtls_aes_init(&aes);

const auto kb = key.c_str();
const auto kl = key.length();
String k (key);
{
uint8_t hmac[BITS / 8];
esp_hmac_calculate(HMAC_KEY0, kb, kl, hmac);
esp_hmac_calculate(HMAC_KEY0, k.c_str(), k.length(), hmac);
mbedtls_aes_setkey_dec(&aes, hmac, BITS);
}

char out[in.length()];
mbedtls_aes_crypt_ecb(&aes, MBEDTLS_AES_DECRYPT,
reinterpret_cast<const uint8_t *>(in.c_str()),
reinterpret_cast<uint8_t *>(out));
return out;
uint8_t iv[16];
mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_DECRYPT, N, iv,
in, reinterpret_cast<uint8_t *>(out));
}

} // namespace Secret

#else // !defined(BOARD_ESP32_PCB)

namespace Secret {
#include <algorithm>

String encrypt([[maybe_unused]] String key, String in)
void SecretStore::encrypt(const char *in, uint8_t *out, unsigned N) const noexcept
{
return in;
std::copy(in, in + N, out);
}

String decrypt([[maybe_unused]] String key, String in)
void SecretStore::decrypt(const uint8_t *in, char *out, unsigned N) const noexcept
{
return in;
std::copy(in, in + N, out);
}

} // namespace Secret

#endif // defined(BOARD_ESP32_PCB)

33 changes: 18 additions & 15 deletions noisemeter-device/secret-store.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,28 +19,31 @@
#ifndef SECRET_STORE_H
#define SECRET_STORE_H

#include <WString.h>
#include "UUID/UUID.h"

namespace Secret
struct SecretStore
{
UUID key;

/**
* Encrypts the given string with the given key.
* Uses the HMAC peripheral to modify the key in a secure way.
* @param key Key to use for encryption.
* @param in String of data to be encrypted.
* @return The encrypted string.
* Securely encrypts the given string.
* @param in Pointer to `len` bytes of input data.
* @param out Pre-allocated buffer to store encrypted output.
* @param len Number of bytes to process.
*/
String encrypt(String key, String in);
void encrypt(const char *in, uint8_t *out, unsigned int len) const noexcept;

/**
* Decrypts the given string with the given key.
* Uses the HMAC peripheral to modify the key in a secure way.
* @param key Key to use for decryption.
* @param in String of data to be decrypted.
* @return The decrypted string.
* Securely decrypts the given string.
* @param in Pointer to `len` bytes of input data.
* @param out Pre-allocated buffer to store decrypted output.
* @param len Number of bytes to process.
*/
String decrypt(String key, String in);
}
void decrypt(const uint8_t *in, char *out, unsigned int len) const noexcept;

private:
constexpr static unsigned BITS = 256; // do not change
};

#endif // SECRET_STORE_H

25 changes: 16 additions & 9 deletions noisemeter-device/storage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,18 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "storage.h"

#include <Arduino.h>
#include <CRC32.h>

#include <algorithm>
#include <array>

void Storage::begin() noexcept
void Storage::begin(UUID key)
{
secret.key = key;

EEPROMClass::begin(addrOf(Entry::TotalSize));
delay(2000); // Ensure the eeprom peripheral has enough time to initialize.
}
Expand Down Expand Up @@ -50,16 +53,20 @@ void Storage::clear() noexcept

String Storage::get(Entry entry) const noexcept
{
if (entry != Entry::Checksum)
return String(_data + addrOf(entry), StringSize - 1);
else
if (entry != Entry::Checksum) {
std::array<char, StringSize> buf;
secret.decrypt(_data + addrOf(entry), buf.data(), StringSize);
return buf.data();
} else {
return {};
}
}

void Storage::set(Entry entry, String str) noexcept
{
if (entry != Entry::Checksum && canStore(str))
writeBytes(addrOf(entry), str.begin(), StringSize);
if (entry != Entry::Checksum && canStore(str)) {
secret.encrypt(str.c_str(), _data + addrOf(entry), StringSize);
}
}

void Storage::commit() noexcept
Expand All @@ -69,15 +76,15 @@ void Storage::commit() noexcept
EEPROMClass::commit();
}

#ifdef STORAGE_SHOW_CREDENTIALS
Storage::operator String() const noexcept
{
return String() +
"SSID \"" + get(Entry::SSID) +
#ifdef STORAGE_SHOW_PASSKEY
"\" Passkey \"" + get(Entry::Passkey) +
#endif
'\"';
}
#endif

uint32_t Storage::calculateChecksum() const noexcept
{
Expand Down
12 changes: 10 additions & 2 deletions noisemeter-device/storage.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
#ifndef STORAGE_H
#define STORAGE_H

#include "secret-store.h"

#include <EEPROM.h>

#include <cstdint>
Expand All @@ -42,9 +44,10 @@ class Storage : protected EEPROMClass
};

/**
* Prepares flash memory for access.
* Initializes the instance and prepares flash memory for access.
* @param key Key (i.e. seed) to use for encryption
*/
void begin() noexcept;
void begin(UUID key);

/**
* Validates the stored settings against the stored checksum.
Expand Down Expand Up @@ -83,12 +86,17 @@ class Storage : protected EEPROMClass
*/
void commit() noexcept;

#ifdef STORAGE_SHOW_CREDENTIALS
/**
* Returns a string describing the stored settings.
*/
operator String() const noexcept;
#endif

private:
/** Encryption instance. */
SecretStore secret;

/**
* Calculates a CRC32 checksum of all stored settings.
* @return The checksum for the stored settings
Expand Down

0 comments on commit b626f4e

Please sign in to comment.