diff --git a/noisemeter-device/UUID/UUID.cpp b/noisemeter-device/UUID/UUID.cpp
index ac1e4e3..56e56ff 100644
--- a/noisemeter-device/UUID/UUID.cpp
+++ b/noisemeter-device/UUID/UUID.cpp
@@ -75,7 +75,7 @@ void UUID::generate()
}
-char * UUID::toCharArray()
+const char * UUID::toCharArray() const
{
// if (_upperCase)
// {
diff --git a/noisemeter-device/UUID/UUID.h b/noisemeter-device/UUID/UUID.h
index 8b15704..0895ca2 100644
--- a/noisemeter-device/UUID/UUID.h
+++ b/noisemeter-device/UUID/UUID.h
@@ -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();
}
diff --git a/noisemeter-device/config.h.example b/noisemeter-device/config.h.example
index 2ec53a8..4584af3 100644
--- a/noisemeter-device/config.h.example
+++ b/noisemeter-device/config.h.example
@@ -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.
diff --git a/noisemeter-device/noisemeter-device.ino b/noisemeter-device/noisemeter-device.ino
index 66ae3f7..a4ef60d 100644
--- a/noisemeter-device/noisemeter-device.ino
+++ b/noisemeter-device/noisemeter-device.ino
@@ -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"
@@ -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();
@@ -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)) {
@@ -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;
diff --git a/noisemeter-device/secret-store.cpp b/noisemeter-device/secret-store.cpp
index 4cdf479..012e70e 100644
--- a/noisemeter-device/secret-store.cpp
+++ b/noisemeter-device/secret-store.cpp
@@ -14,75 +14,61 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-#include "board.h"
#include "secret-store.h"
+#include "board.h"
#if defined(BOARD_ESP32_PCB)
#include
#include
-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(in.c_str()),
- reinterpret_cast(out));
- return out;
+ uint8_t iv[16];
+ mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_ENCRYPT, N, iv,
+ reinterpret_cast(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(in.c_str()),
- reinterpret_cast(out));
- return out;
+ uint8_t iv[16];
+ mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_DECRYPT, N, iv,
+ in, reinterpret_cast(out));
}
-} // namespace Secret
-
#else // !defined(BOARD_ESP32_PCB)
-namespace Secret {
+#include
-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)
diff --git a/noisemeter-device/secret-store.h b/noisemeter-device/secret-store.h
index 54e7c2e..4bed509 100644
--- a/noisemeter-device/secret-store.h
+++ b/noisemeter-device/secret-store.h
@@ -19,28 +19,31 @@
#ifndef SECRET_STORE_H
#define SECRET_STORE_H
-#include
+#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
diff --git a/noisemeter-device/storage.cpp b/noisemeter-device/storage.cpp
index 3c18154..2d99aef 100644
--- a/noisemeter-device/storage.cpp
+++ b/noisemeter-device/storage.cpp
@@ -14,15 +14,18 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
+#include "config.h"
#include "storage.h"
#include
#include
-#include
+#include
-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.
}
@@ -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 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
@@ -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
{
diff --git a/noisemeter-device/storage.h b/noisemeter-device/storage.h
index 1d597ca..dc3f9d4 100644
--- a/noisemeter-device/storage.h
+++ b/noisemeter-device/storage.h
@@ -19,6 +19,8 @@
#ifndef STORAGE_H
#define STORAGE_H
+#include "secret-store.h"
+
#include
#include
@@ -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.
@@ -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