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");
|
||||
|
||||
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=<M2>
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
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(){
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
|
|
|||
Loading…
Reference in New Issue