diff --git a/src/HAP.cpp b/src/HAP.cpp index d6ee651..b87b7b7 100644 --- a/src/HAP.cpp +++ b/src/HAP.cpp @@ -38,9 +38,6 @@ void HAPClient::init(){ size_t len; // not used but required to read blobs from NVS - nvs_open("SRP",NVS_READWRITE,&srpNVS); // open SRP data namespace in NVS - nvs_open("HAP",NVS_READWRITE,&hapNVS); // open HAP data namespace in NVS - if(strlen(homeSpan.spanOTA.otaPwd)==0){ // OTA password has not been specified in sketch if(!nvs_get_str(homeSpan.otaNVS,"OTADATA",NULL,&len)){ // if found OTA data in NVS... nvs_get_str(homeSpan.otaNVS,"OTADATA",homeSpan.spanOTA.otaPwd,&len); // ...retrieve data. @@ -49,9 +46,6 @@ void HAPClient::init(){ } } - if(nvs_get_blob(srpNVS,"VERIFYDATA",NULL,&len)) // if Pair-Setup verification code data not found in NVS - homeSpan.setPairingCode(DEFAULT_SETUP_CODE); // create and save verification from using Pairing Setup Code - if(!strlen(homeSpan.qrID)){ // if Setup ID has not been specified in sketch if(!nvs_get_str(hapNVS,"SETUPID",NULL,&len)){ // check for saved value nvs_get_str(hapNVS,"SETUPID",homeSpan.qrID,&len); // retrieve data @@ -59,6 +53,9 @@ void HAPClient::init(){ sprintf(homeSpan.qrID,"%s",DEFAULT_QR_ID); // use default } } + + if(nvs_get_blob(homeSpan.srpNVS,"VERIFYDATA",NULL,&len)) // if Pair-Setup verification code data not found in NVS + homeSpan.setPairingCode(DEFAULT_SETUP_CODE,false); // create and save verification from default Pairing Setup Code if(!nvs_get_blob(hapNVS,"ACCESSORY",NULL,&len)){ // if found long-term Accessory data in NVS nvs_get_blob(hapNVS,"ACCESSORY",&accessory,&len); // retrieve data @@ -316,6 +313,8 @@ int HAPClient::unauthorizedError(){ int HAPClient::postPairSetupURL(uint8_t *content, size_t len){ + static SRP6A *srp=NULL; // must persist across multiple calls to postPairSetupURL + HAPTLV iosTLV; HAPTLV responseTLV; HAPTLV subTLV; @@ -378,7 +377,7 @@ int HAPClient::postPairSetupURL(uint8_t *content, size_t len){ TempBuffer verifyData; // retrieve verification data (should already be stored in NVS) size_t len=verifyData.len(); - nvs_get_blob(srpNVS,"VERIFYDATA",verifyData,&len); + nvs_get_blob(homeSpan.srpNVS,"VERIFYDATA",verifyData,&len); responseTLV.add(kTLVType_Salt,16,verifyData.get()->salt); // write Salt from verification data into TLV @@ -542,6 +541,7 @@ int HAPClient::postPairSetupURL(uint8_t *content, size_t len){ tlvRespond(responseTLV); // send response to client delete srp; // delete SRP - no longer needed once pairing is completed + srp=NULL; // reset to NULL mdns_service_txt_item_set("_hap","_tcp","sf","0"); // broadcast new status @@ -1691,11 +1691,10 @@ void HapOut::HapStreamBuffer::printFormatted(char *buf, size_t nChars, size_t ns // instantiate all static HAP Client structures and data nvs_handle HAPClient::hapNVS; -nvs_handle HAPClient::srpNVS; HKDF HAPClient::hkdf; pairState HAPClient::pairStatus; Accessory HAPClient::accessory; list> HAPClient::controllerList; -SRP6A *HAPClient::srp=NULL; +//SRP6A *HAPClient::srp=NULL; int HAPClient::conNum; diff --git a/src/HAP.h b/src/HAP.h index bbf6feb..cdf176a 100644 --- a/src/HAP.h +++ b/src/HAP.h @@ -106,10 +106,9 @@ struct HAPClient { static const int MAX_ACCESSORIES=150; // maximum number of allowed Accessories (HAP limit=150) static nvs_handle hapNVS; // handle for non-volatile-storage of HAP data - static nvs_handle srpNVS; // handle for non-volatile-storage of SRP data static HKDF hkdf; // generates (and stores) HKDF-SHA-512 32-byte keys derived from an inputKey of arbitrary length, a salt string, and an info string static pairState pairStatus; // tracks pair-setup status - static SRP6A *srp; // stores all SRP-6A keys used for Pair-Setup (must persist through multiple calls to Pair-Setup) +// static SRP6A *srp; // stores all SRP-6A keys used for Pair-Setup (must persist through multiple calls to Pair-Setup) static Accessory accessory; // Accessory ID and Ed25519 public and secret keys- permanently stored static list> controllerList; // linked-list of Paired Controller IDs and ED25519 long-term public keys - permanently stored static int conNum; // connection number - used to keep track of per-connection EV notifications diff --git a/src/HomeSpan.cpp b/src/HomeSpan.cpp index f521c18..2b57ce7 100644 --- a/src/HomeSpan.cpp +++ b/src/HomeSpan.cpp @@ -45,15 +45,35 @@ const __attribute__((section(".rodata_custom_desc"))) SpanPartition spanPartitio using namespace Utils; -HapOut hapOut; // Specialized output stream that can both print to serial monitor and encrypt/transmit to HAP Clients with minimal memory usage (global-scope) +HapOut hapOut; // Specialized output stream that can both print to serial monitor and encrypt/transmit to HAP Clients with minimal memory usage (global-scoped variable) HAPClient **hap; // HAP Client structure containing HTTP client connections, parsing routines, and state variables (global-scoped variable) Span homeSpan; // HAP Attributes database and all related control functions for this Accessory (global-scoped variable) -HapCharacteristics hapChars; // Instantiation of all HAP Characteristics (used to create SpanCharacteristics) +HapCharacteristics hapChars; // Instantiation of all HAP Characteristics used to create SpanCharacteristics (global-scoped variable) /////////////////////////////// // Span // /////////////////////////////// +Span::Span(){ + + nvs_flash_init(); // initialize non-volatile-storage partition in flash + + nvs_open("CHAR",NVS_READWRITE,&charNVS); // open Characteristic data namespace in NVS + nvs_open("WIFI",NVS_READWRITE,&wifiNVS); // open WIFI data namespace in NVS + nvs_open("OTA",NVS_READWRITE,&otaNVS); // open OTA data namespace in NVS + + nvs_open("SRP",NVS_READWRITE,&srpNVS); // open SRP data namespace in NVS + nvs_open("HAP",NVS_READWRITE,&HAPClient::hapNVS); // open HAP data namespace in NVS + + nvs_get_u8(wifiNVS,"REBOOTS",&rebootCount); + rebootCount++; + nvs_set_u8(wifiNVS,"REBOOTS",rebootCount); + nvs_commit(wifiNVS); + +} + +/////////////////////////////// + void Span::begin(Category catID, const char *displayName, const char *hostNameBase, const char *modelName){ loopTaskHandle=xTaskGetCurrentTaskHandle(); // a roundabout way of getting the current task handle @@ -67,7 +87,7 @@ void Span::begin(Category catID, const char *displayName, const char *hostNameBa statusLED=new Blinker(statusDevice,autoOffLED); // create Status LED, even is statusDevice is NULL - esp_task_wdt_delete(xTaskGetIdleTaskHandleForCPU(0)); // required to avoid watchdog timeout messages from ESP32-C3 + esp_task_wdt_delete(xTaskGetIdleTaskHandleForCPU(0)); // required to avoid watchdog timeout messages from ESP32-C3 if(requestedMaxCon verifyData; // temporary storage for verification data SRP6A *srp=new SRP6A; // create temporary instance of SRP + + if(!progCall) + LOG0("\nGenerating new SRP verification data for Setup Code: %.3s-%.2s-%.3s ... ",setupCode,setupCode+3,setupCode+5); + + srp->createVerifyCode(setupCode,verifyData); // create random salt and compute verification code from specified Setup Code + nvs_set_blob(srpNVS,"VERIFYDATA",verifyData,verifyData.len()); // update data + nvs_commit(srpNVS); // commit to NVS - LOG0("\nGenerating SRP verification data for new Setup Code: %.3s-%.2s-%.3s ... ",setupCode,setupCode+3,setupCode+5); - - srp->createVerifyCode(setupCode,verifyData); // create random salt and compute verification code from specified Setup Code - nvs_set_blob(HAPClient::srpNVS,"VERIFYDATA",verifyData,verifyData.len()); // update data - nvs_commit(HAPClient::srpNVS); // commit to NVS - - LOG0("New Code Saved!\n"); - LOG0("Setup Payload for Optional QR Code: %s\n\n",qrCode.get(atoi(setupCode),qrID,atoi(category))); + if(!progCall) + LOG0("New Code Saved!\nSetup Payload for Optional QR Code: %s\n\n",qrCode.get(atoi(setupCode),qrID,atoi(category))); delete srp; return(*this); diff --git a/src/HomeSpan.h b/src/HomeSpan.h index 201bcdd..7ab6f06 100644 --- a/src/HomeSpan.h +++ b/src/HomeSpan.h @@ -215,9 +215,6 @@ class Span{ boolean isBridge=true; // flag indicating whether device is configured as a bridge (i.e. first Accessory contains nothing but AccessoryInformation and HAPProtocolInformation) HapQR qrCode; // optional QR Code to use for pairing const char *sketchVersion="n/a"; // version of the sketch - nvs_handle charNVS; // handle for non-volatile-storage of Characteristics data - nvs_handle wifiNVS=0; // handle for non-volatile-storage of WiFi data - nvs_handle otaNVS; // handle for non-volatile storage of OTA data char pairingCodeCommand[12]=""; // user-specified Pairing Code - only needed if Pairing Setup Code is specified in sketch using setPairingCode() String lastClientIP="0.0.0.0"; // IP address of last client accessing device through encrypted channel boolean newCode; // flag indicating new application code has been loaded (based on keeping track of app SHA256) @@ -225,6 +222,11 @@ class Span{ uint8_t rebootCount=0; // counts number of times device was rebooted (used in optional Reboot callback) uint32_t rebootCallbackTime; // length of time to wait (in milliseconds) before calling optional Reboot callback + nvs_handle charNVS; // handle for non-volatile-storage of Characteristics data + nvs_handle wifiNVS=0; // handle for non-volatile-storage of WiFi data + nvs_handle otaNVS; // handle for non-volatile storage of OTA data + nvs_handle srpNVS; // handle for non-volatile storage of SRP data + int connected=0; // WiFi connection status (increments upon each connect and disconnect) unsigned long waitTime=60000; // time to wait (in milliseconds) between WiFi connection attempts unsigned long alarmConnect=0; // time after which WiFi connection attempt should be tried again @@ -291,6 +293,8 @@ class Span{ public: + Span(); // constructor + void begin(Category catID=DEFAULT_CATEGORY, const char *displayName=DEFAULT_DISPLAY_NAME, const char *hostNameBase=DEFAULT_HOST_NAME, @@ -342,7 +346,7 @@ class Span{ Span& setWifiCredentials(const char *ssid, const char *pwd); // sets WiFi Credentials Span& setStatusCallback(void (*f)(HS_STATUS status)){statusCallback=f;return(*this);} // sets an optional user-defined function to call when HomeSpan status changes const char* statusString(HS_STATUS s); // returns char string for HomeSpan status change messages - Span& setPairingCode(const char *s); // sets the Pairing Code - use is NOT recommended. Use 'S' from CLI instead + Span& setPairingCode(const char *s, boolean progCall=true); // sets the Pairing Code - use is NOT recommended. Use 'S' from CLI instead void deleteStoredValues(){processSerialCommand("V");} // deletes stored Characteristic values from NVS int enableOTA(boolean auth=true, boolean safeLoad=true){return(spanOTA.init(auth, safeLoad, NULL));} // enables Over-the-Air updates, with (auth=true) or without (auth=false) authorization password diff --git a/src/src.ino b/src/src.ino index 1db723a..2909559 100644 --- a/src/src.ino +++ b/src/src.ino @@ -27,7 +27,7 @@ #include "HomeSpan.h" -#define MAX_LIGHTS 2 +#define MAX_LIGHTS 1 void setup() { @@ -35,6 +35,7 @@ void setup() { homeSpan.setLogLevel(2); homeSpan.enableWebLog(50,"pool.ntp.org","UTC",NULL); + homeSpan.setPairingCode("12345670"); // homeSpan.enableWebLog(50,"pool.ntp.org","UTC","myStatus"); // homeSpan.enableWebLog(50,NULL,NULL,NULL);