Created SRP6A:createVerifyCode()
This generates an SRP verification code from a setupCode and randomly-generated salt. Function creates the salt internally and returns both the resulting verification code and salt that was used. These are stored in NVS permanently. Next Step: create SRP6A:loadVerifycode()
This commit is contained in:
parent
b0307c9ab0
commit
446679abab
34
src/HAP.cpp
34
src/HAP.cpp
|
|
@ -13,6 +13,34 @@ void HAPClient::init(){
|
||||||
|
|
||||||
Serial.print("\n");
|
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
|
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
|
if(!nvs_get_blob(nvsHandle,"ACCESSORY",NULL,&len)){ // if found long-term Accessory data in NVS
|
||||||
|
|
@ -52,7 +80,7 @@ void HAPClient::init(){
|
||||||
|
|
||||||
printControllers();
|
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_PublicKey,384,"PUBKEY");
|
||||||
tlv8.create(kTLVType_Method,1,"METHOD");
|
tlv8.create(kTLVType_Method,1,"METHOD");
|
||||||
tlv8.create(kTLVType_Salt,16,"SALT");
|
tlv8.create(kTLVType_Salt,16,"SALT");
|
||||||
|
|
@ -384,8 +412,8 @@ int HAPClient::postPairSetupURL(){
|
||||||
tlv8.clear();
|
tlv8.clear();
|
||||||
tlv8.val(kTLVType_State,pairState_M2); // set State=<M2>
|
tlv8.val(kTLVType_State,pairState_M2); // set State=<M2>
|
||||||
srp.createPublicKey(); // create accessory public key from random Pair-Setup code (displayed to user)
|
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_PublicKey,&srp.B); // load server public key, B
|
||||||
srp.loadTLV(kTLVType_Salt,&srp.s); // load salt, s (MUST MAKE THIS RANDOM AS WELL)
|
srp.loadTLV(kTLVType_Salt,&srp.s); // load salt, s
|
||||||
tlvRespond(); // send response to client
|
tlvRespond(); // send response to client
|
||||||
|
|
||||||
pairStatus=pairState_M3; // set next expected pair-state request from client
|
pairStatus=pairState_M3; // set next expected pair-state request from client
|
||||||
|
|
|
||||||
|
|
@ -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
|
if(!digitalRead(resetPin)){ // factory reset pin is low upon start-up
|
||||||
nvs_flash_erase(); // erase NVS storage
|
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);
|
statusLED.start(100);
|
||||||
delay(5000);
|
delay(5000);
|
||||||
Serial.print("Re-starting...\n\n");
|
Serial.print("Re-starting...\n\n");
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,7 @@ struct Span{
|
||||||
char *modelName; // model name of this device - broadcast as Bonjour field "md"
|
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)
|
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()
|
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 resetPin=21; // drive this pin low to "factory" reset NVS data on start-up
|
||||||
int resetPressed=0; // tracks pressing of reset button
|
int resetPressed=0; // tracks pressing of reset button
|
||||||
|
|
|
||||||
27
src/SRP.cpp
27
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(){
|
void SRP6A::createPublicKey(){
|
||||||
|
|
||||||
uint8_t tBuf[80]; // temporary buffer for staging
|
uint8_t tBuf[80]; // temporary buffer for staging
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,9 @@ struct SRP6A {
|
||||||
uint8_t sharedSecret[64]; // permanent storage for binary version of SHARED SECRET KEY for ease of use upstream
|
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
|
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 getSalt(); // generates and stores random 16-byte salt, s
|
||||||
void getPrivateKey(); // generates and stores random 32-byte private key, b
|
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
|
void getSetupCode(char *c); // generates and displays random 8-digit Pair-Setup code, P, in format XXX-XX-XXX
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue