Something went wrong. Try again.
A fork of https://github.com/crosspoint-reader/crosspoint-reader
Something went wrong. Try again.
5.2 kB · 174 lines
C++
at master
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175#include "WifiCredentialStore.h"
#include <HalStorage.h>#include <JsonSettingsIO.h>#include <Logging.h>#include <ObfuscationUtils.h>#include <Serialization.h>
// Initialize the static instanceWifiCredentialStore WifiCredentialStore::instance;
namespace {// File format version (for binary migration)constexpr uint8_t WIFI_FILE_VERSION = 2;
// File pathsconstexpr char WIFI_FILE_BIN[] = "/.crosspoint/wifi.bin";constexpr char WIFI_FILE_JSON[] = "/.crosspoint/wifi.json";constexpr char WIFI_FILE_BAK[] = "/.crosspoint/wifi.bin.bak";
// Legacy obfuscation key - "CrossPoint" in ASCII (only used for binary migration)constexpr uint8_t LEGACY_OBFUSCATION_KEY[] = {0x43, 0x72, 0x6F, 0x73, 0x73, 0x50, 0x6F, 0x69, 0x6E, 0x74};constexpr size_t LEGACY_KEY_LENGTH = sizeof(LEGACY_OBFUSCATION_KEY);
void legacyDeobfuscate(std::string& data) { for (size_t i = 0; i < data.size(); i++) { data[i] ^= LEGACY_OBFUSCATION_KEY[i % LEGACY_KEY_LENGTH]; }}} // namespace
bool WifiCredentialStore::saveToFile() const { Storage.mkdir("/.crosspoint"); return JsonSettingsIO::saveWifi(*this, WIFI_FILE_JSON);}
bool WifiCredentialStore::loadFromFile() { // Try JSON first if (Storage.exists(WIFI_FILE_JSON)) { String json = Storage.readFile(WIFI_FILE_JSON); if (!json.isEmpty()) { bool resave = false; bool result = JsonSettingsIO::loadWifi(*this, json.c_str(), &resave); if (result && resave) { LOG_DBG("WCS", "Resaving JSON with obfuscated passwords"); saveToFile(); } return result; } }
// Fall back to binary migration if (Storage.exists(WIFI_FILE_BIN)) { if (loadFromBinaryFile()) { if (saveToFile()) { Storage.rename(WIFI_FILE_BIN, WIFI_FILE_BAK); LOG_DBG("WCS", "Migrated wifi.bin to wifi.json"); return true; } else { LOG_ERR("WCS", "Failed to save wifi during migration"); return false; } } }
return false;}
bool WifiCredentialStore::loadFromBinaryFile() { FsFile file; if (!Storage.openFileForRead("WCS", WIFI_FILE_BIN, file)) { return false; }
uint8_t version; serialization::readPod(file, version); if (version > WIFI_FILE_VERSION) { LOG_DBG("WCS", "Unknown file version: %u", version); return false; }
if (version >= 2) { serialization::readString(file, lastConnectedSsid); } else { lastConnectedSsid.clear(); }
uint8_t count; serialization::readPod(file, count);
credentials.clear(); for (uint8_t i = 0; i < count && i < MAX_NETWORKS; i++) { WifiCredential cred; serialization::readString(file, cred.ssid); serialization::readString(file, cred.password); legacyDeobfuscate(cred.password); credentials.push_back(cred); }
// LOG_DBG("WCS", "Loaded %zu WiFi credentials from binary file", credentials.size()); return true;}
bool WifiCredentialStore::addCredential(const std::string& ssid, const std::string& password) { // Check if this SSID already exists and update it const auto cred = find_if(credentials.begin(), credentials.end(), [&ssid](const WifiCredential& cred) { return cred.ssid == ssid; }); if (cred != credentials.end()) { cred->password = password; LOG_DBG("WCS", "Updated credentials for: %s", ssid.c_str()); return saveToFile(); }
// Check if we've reached the limit if (credentials.size() >= MAX_NETWORKS) { LOG_DBG("WCS", "Cannot add more networks, limit of %zu reached", MAX_NETWORKS); return false; }
// Add new credential credentials.push_back({ssid, password}); LOG_DBG("WCS", "Added credentials for: %s", ssid.c_str()); return saveToFile();}
bool WifiCredentialStore::removeCredential(const std::string& ssid) { const auto cred = find_if(credentials.begin(), credentials.end(), [&ssid](const WifiCredential& cred) { return cred.ssid == ssid; }); if (cred != credentials.end()) { credentials.erase(cred); LOG_DBG("WCS", "Removed credentials for: %s", ssid.c_str()); if (ssid == lastConnectedSsid) { clearLastConnectedSsid(); } return saveToFile(); } return false; // Not found}
const WifiCredential* WifiCredentialStore::findCredential(const std::string& ssid) const { const auto cred = find_if(credentials.begin(), credentials.end(), [&ssid](const WifiCredential& cred) { return cred.ssid == ssid; });
if (cred != credentials.end()) { return &*cred; }
return nullptr;}
bool WifiCredentialStore::hasSavedCredential(const std::string& ssid) const { return findCredential(ssid) != nullptr; }
void WifiCredentialStore::setLastConnectedSsid(const std::string& ssid) { if (lastConnectedSsid != ssid) { lastConnectedSsid = ssid; saveToFile(); }}
const std::string& WifiCredentialStore::getLastConnectedSsid() const { return lastConnectedSsid; }
void WifiCredentialStore::clearLastConnectedSsid() { if (!lastConnectedSsid.empty()) { lastConnectedSsid.clear(); saveToFile(); }}
void WifiCredentialStore::clearAll() { credentials.clear(); lastConnectedSsid.clear(); saveToFile(); LOG_DBG("WCS", "Cleared all WiFi credentials");}