diff --git a/src/HAP.cpp b/src/HAP.cpp index 62091ec..efb88d4 100644 --- a/src/HAP.cpp +++ b/src/HAP.cpp @@ -13,6 +13,34 @@ void HAPClient::init(){ Serial.print("\n"); + nvs_handle srpHandle; + + struct { // temporary structure to hold SRP verification code and salt stored in NVS + uint8_t salt[16]; + uint8_t verifyCode[384]; + } verifyData; + + nvs_open("SRP",NVS_READWRITE,&srpHandle); // open SRP data namespace in NVS + + if(!nvs_get_blob(srpHandle,"VERIFYDATA",NULL,&len)){ // if found verification code data in NVS + nvs_get_blob(srpHandle,"VERIFYDATA",&verifyData,&len); // retrieve data +// Serial.print("Found SRP Verification Data\n\n"); +// hexPrintRow(verifyData.salt,16); Serial.print("\n"); +// hexPrintRow(verifyData.verifyCode,384); Serial.print("\n"); + } else { + char c[128]; + sprintf(c,"Generating SRP verification data for default Setup Code: %.3s-%.2s-%.3s\n\n",homeSpan.defaultSetupCode,homeSpan.defaultSetupCode+3,homeSpan.defaultSetupCode+5); + Serial.print(c); + srp.createVerifyCode(homeSpan.defaultSetupCode,verifyData.verifyCode,verifyData.salt); // create verification code from default Setup Code and random salt + nvs_set_blob(srpHandle,"VERIFYDATA",&verifyData,sizeof(verifyData)); // update data + nvs_commit(srpHandle); // commit to NVS + +// hexPrintRow(verifyData.salt,16); Serial.print("\n"); +// hexPrintRow(verifyData.verifyCode,384); Serial.print("\n"); + } + + nvs_close(srpHandle); + nvs_open("HAP",NVS_READWRITE,&nvsHandle); // open HAP data namespace in NVS if(!nvs_get_blob(nvsHandle,"ACCESSORY",NULL,&len)){ // if found long-term Accessory data in NVS @@ -52,7 +80,7 @@ void HAPClient::init(){ printControllers(); - tlv8.create(kTLVType_State,1,"STATE"); // define each the actual TLV records needed for the implementation of HAP; one for each kTLVType needed (HAP Table 5-6) + tlv8.create(kTLVType_State,1,"STATE"); // define the actual TLV records needed for the implementation of HAP; one for each kTLVType needed (HAP Table 5-6) tlv8.create(kTLVType_PublicKey,384,"PUBKEY"); tlv8.create(kTLVType_Method,1,"METHOD"); tlv8.create(kTLVType_Salt,16,"SALT"); @@ -384,8 +412,8 @@ int HAPClient::postPairSetupURL(){ tlv8.clear(); tlv8.val(kTLVType_State,pairState_M2); // set State= srp.createPublicKey(); // create accessory public key from random Pair-Setup code (displayed to user) - srp.loadTLV(kTLVType_PublicKey,&srp.B); // load server public key, B (MUST MAKE THIS A LIVE CALCULATION TO GENERATE RANDOM SET-UP CODE) - srp.loadTLV(kTLVType_Salt,&srp.s); // load salt, s (MUST MAKE THIS RANDOM AS WELL) + srp.loadTLV(kTLVType_PublicKey,&srp.B); // load server public key, B + srp.loadTLV(kTLVType_Salt,&srp.s); // load salt, s tlvRespond(); // send response to client pairStatus=pairState_M3; // set next expected pair-state request from client diff --git a/src/HomeSpan.cpp b/src/HomeSpan.cpp index a243f4b..29e2c07 100644 --- a/src/HomeSpan.cpp +++ b/src/HomeSpan.cpp @@ -53,7 +53,7 @@ void Span::begin(Category catID, char *displayName, char *hostNameBase, char *mo if(!digitalRead(resetPin)){ // factory reset pin is low upon start-up nvs_flash_erase(); // erase NVS storage - Serial.print("** FACTORY RESET PIN LOW! ALL STORED DATA ERASED **\n"); + Serial.print("** FACTORY RESET PIN LOW! ALL STORED DATA ERASED **\n\n"); statusLED.start(100); delay(5000); Serial.print("Re-starting...\n\n"); diff --git a/src/HomeSpan.h b/src/HomeSpan.h index 0427094..675e186 100644 --- a/src/HomeSpan.h +++ b/src/HomeSpan.h @@ -48,6 +48,7 @@ struct Span{ char *modelName; // model name of this device - broadcast as Bonjour field "md" char category[3]=""; // category ID of primary accessory - broadcast as Bonjour field "ci" (HAP Section 13) unsigned long snapTime; // current time (in millis) snapped before entering Service loops() or updates() + char *defaultSetupCode="46637726"; // default Setup Code upon factory reset; user will change to desired code when configuring network int resetPin=21; // drive this pin low to "factory" reset NVS data on start-up int resetPressed=0; // tracks pressing of reset button diff --git a/src/SRP.cpp b/src/SRP.cpp index 605aacd..1ee58cf 100644 --- a/src/SRP.cpp +++ b/src/SRP.cpp @@ -62,6 +62,33 @@ SRP6A::SRP6A(){ ////////////////////////////////////// +void SRP6A::createVerifyCode(const char *setupCode, uint8_t *verifyCode, uint8_t *salt){ + + uint8_t tBuf[80]; // temporary buffer for staging + uint8_t tHash[64]; // temporary buffer for storing SHA-512 results + char icp[22]; // storage for I:P + + randombytes_buf(salt,16); // generate 16 random bytes using libsodium (which uses the ESP32 hardware-based random number generator) + mbedtls_mpi_read_binary(&s,salt,16); + + sprintf(icp,"Pair-Setup:%.3s-%.2s-%.3s",setupCode,setupCode+3,setupCode+5); + + // compute x = SHA512( s | SHA512( I | ":" | P ) ) + + mbedtls_mpi_write_binary(&s,tBuf,16); // write s into first 16 bytes of staging buffer + mbedtls_sha512_ret((uint8_t *)icp,strlen(icp),tBuf+16,0); // create hash of username:password and write into last 64 bytes of staging buffer + mbedtls_sha512_ret(tBuf,80,tHash,0); // create second hash of salted, hashed username:password + mbedtls_mpi_read_binary(&x,tHash,64); // load hash result into mpi structure x + + // compute v = g^x % N + + mbedtls_mpi_exp_mod(&v,&g,&x,&N,&_rr); // create verifier, v (_rr is an internal "helper" structure that mbedtls uses to speed up subsequent exponential calculations) + mbedtls_mpi_write_binary(&v,verifyCode,384); // write v into verifyCode + +} + +////////////////////////////////////// + void SRP6A::createPublicKey(){ uint8_t tBuf[80]; // temporary buffer for staging diff --git a/src/SRP.h b/src/SRP.h index cdc608f..04c1dff 100644 --- a/src/SRP.h +++ b/src/SRP.h @@ -40,6 +40,9 @@ struct SRP6A { uint8_t sharedSecret[64]; // permanent storage for binary version of SHARED SECRET KEY for ease of use upstream SRP6A(); // initializes N, G, and computes k + + void createVerifyCode(const char *setupCode, uint8_t *verifyCode, uint8_t *salt); + void getSalt(); // generates and stores random 16-byte salt, s void getPrivateKey(); // generates and stores random 32-byte private key, b void getSetupCode(char *c); // generates and displays random 8-digit Pair-Setup code, P, in format XXX-XX-XXX