Initial integration of local SRP6A into Pair Setup
This commit is contained in:
parent
da55b9b6b1
commit
b960c2fdaf
17
src/HAP.cpp
17
src/HAP.cpp
|
|
@ -372,11 +372,12 @@ int HAPClient::postPairSetupURL(uint8_t *content, size_t len){
|
||||||
|
|
||||||
case pairState_M1:{ // 'SRP Start Request'
|
case pairState_M1:{ // 'SRP Start Request'
|
||||||
|
|
||||||
|
responseTLV.add(kTLVType_State,pairState_M2); // set State=<M2>
|
||||||
|
|
||||||
auto itMethod=iosTLV.find(kTLVType_Method);
|
auto itMethod=iosTLV.find(kTLVType_Method);
|
||||||
|
|
||||||
if(iosTLV.len(itMethod)!=1 || (*itMethod)[0]!=0){ // error: "Pair Setup" method must always be 0 to indicate setup without MiFi Authentification (HAP Table 5-3)
|
if(iosTLV.len(itMethod)!=1 || (*itMethod)[0]!=0){ // error: "Pair Setup" method must always be 0 to indicate setup without MiFi Authentification (HAP Table 5-3)
|
||||||
LOG0("\n*** ERROR: Pair 'Method' missing or not set to 0\n\n");
|
LOG0("\n*** ERROR: Pair 'Method' missing or not set to 0\n\n");
|
||||||
responseTLV.add(kTLVType_State,pairState_M2); // set State=<M2>
|
|
||||||
responseTLV.add(kTLVType_Error,tagError_Unavailable); // set Error=Unavailable
|
responseTLV.add(kTLVType_Error,tagError_Unavailable); // set Error=Unavailable
|
||||||
tlvRespond(responseTLV); // send response to client
|
tlvRespond(responseTLV); // send response to client
|
||||||
return(0);
|
return(0);
|
||||||
|
|
@ -385,10 +386,14 @@ int HAPClient::postPairSetupURL(uint8_t *content, size_t len){
|
||||||
auto itPublicKey=responseTLV.add(kTLVType_PublicKey,384,NULL); // create blank PublicKey TLV with space for 384 bytes
|
auto itPublicKey=responseTLV.add(kTLVType_PublicKey,384,NULL); // create blank PublicKey TLV with space for 384 bytes
|
||||||
auto itSalt=responseTLV.add(kTLVType_Salt,16,NULL); // create blank Salt TLV with space for 16 bytes
|
auto itSalt=responseTLV.add(kTLVType_Salt,16,NULL); // create blank Salt TLV with space for 16 bytes
|
||||||
|
|
||||||
responseTLV.add(kTLVType_State,pairState_M2); // set State=<M2>
|
srp=new SRP6A; // create instance of SRP to persist until Pairing is fully complete
|
||||||
srp->createPublicKey(); // create accessory Public Key from Pair-Setup code (displayed to user)
|
TempBuffer<Verification> verifyData; // temporary storage for verification data
|
||||||
mbedtls_mpi_write_binary(&srp->B,*itPublicKey,(*itPublicKey).len); // load server PublicKey, B, into TLV
|
size_t len=sizeof(Verification);
|
||||||
mbedtls_mpi_write_binary(&srp->s,*itSalt,(*itSalt).len); // load Salt, s, into TLV
|
nvs_get_blob(srpNVS,"VERIFYDATA",verifyData.get(),&len); // load verification data (should already be stored in NVS)
|
||||||
|
srp->createPublicKey(verifyData.get()->verifyCode,verifyData.get()->salt); // create accessory Public Key from stored verification data (which was originally derived from Pair-Setup Code)
|
||||||
|
mbedtls_mpi_write_binary(&srp->B,*itPublicKey,(*itPublicKey).len); // write resulting server PublicKey, B, into TLV
|
||||||
|
mbedtls_mpi_write_binary(&srp->s,*itSalt,(*itSalt).len); // write Salt, s, into TLV
|
||||||
|
|
||||||
tlvRespond(responseTLV); // send response to client
|
tlvRespond(responseTLV); // 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
|
||||||
return(1);
|
return(1);
|
||||||
|
|
@ -1655,6 +1660,6 @@ HKDF HAPClient::hkdf;
|
||||||
pairState HAPClient::pairStatus;
|
pairState HAPClient::pairStatus;
|
||||||
Accessory HAPClient::accessory;
|
Accessory HAPClient::accessory;
|
||||||
list<Controller, Mallocator<Controller>> HAPClient::controllerList;
|
list<Controller, Mallocator<Controller>> HAPClient::controllerList;
|
||||||
SRP6A *HAPClient::srp;
|
SRP6A *HAPClient::srp=NULL;
|
||||||
int HAPClient::conNum;
|
int HAPClient::conNum;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1201,12 +1201,12 @@ Span& Span::setPairingCode(const char *s){
|
||||||
}
|
}
|
||||||
|
|
||||||
TempBuffer<Verification> verifyData; // temporary storage for verification data
|
TempBuffer<Verification> verifyData; // temporary storage for verification data
|
||||||
SRP6A *srp=new SRP6A; // create instance of SRP
|
SRP6A *srp=new SRP6A; // create temporary instance of SRP
|
||||||
|
|
||||||
LOG0("\nGenerating SRP verification data for new Setup Code: %.3s-%.2s-%.3s ... ",setupCode,setupCode+3,setupCode+5);
|
LOG0("\nGenerating SRP verification data for new Setup Code: %.3s-%.2s-%.3s ... ",setupCode,setupCode+3,setupCode+5);
|
||||||
|
|
||||||
srp->createVerifyCode(setupCode,verifyData.get()->verifyCode,verifyData.get()->salt); // create verification code with random salt from specified Setup Code
|
srp->createVerifyCode(setupCode,verifyData.get()->verifyCode,verifyData.get()->salt); // create verification code with random salt from specified Setup Code
|
||||||
nvs_set_blob(HAPClient::srpNVS,"VERIFYDATA",&verifyData,sizeof(verifyData)); // update data
|
nvs_set_blob(HAPClient::srpNVS,"VERIFYDATA",verifyData,verifyData.len()); // update data
|
||||||
nvs_commit(HAPClient::srpNVS); // commit to NVS
|
nvs_commit(HAPClient::srpNVS); // commit to NVS
|
||||||
|
|
||||||
LOG0("New Code Saved!\n");
|
LOG0("New Code Saved!\n");
|
||||||
|
|
|
||||||
73
src/SRP.cpp
73
src/SRP.cpp
|
|
@ -36,9 +36,6 @@
|
||||||
|
|
||||||
SRP6A::SRP6A(){
|
SRP6A::SRP6A(){
|
||||||
|
|
||||||
uint8_t tBuf[768]; // temporary buffer for staging
|
|
||||||
uint8_t tHash[64]; // temporary buffer for storing SHA-512 results
|
|
||||||
|
|
||||||
// initialize MPI structures
|
// initialize MPI structures
|
||||||
|
|
||||||
mbedtls_mpi_init(&N);
|
mbedtls_mpi_init(&N);
|
||||||
|
|
@ -61,18 +58,11 @@ SRP6A::SRP6A(){
|
||||||
mbedtls_mpi_init(&t2);
|
mbedtls_mpi_init(&t2);
|
||||||
mbedtls_mpi_init(&t3);
|
mbedtls_mpi_init(&t3);
|
||||||
|
|
||||||
// load N and g into mpi structures
|
// load N and g into MPI structures
|
||||||
|
|
||||||
mbedtls_mpi_read_string(&N,16,N3072);
|
mbedtls_mpi_read_string(&N,16,N3072);
|
||||||
mbedtls_mpi_lset(&g,5);
|
mbedtls_mpi_lset(&g,5);
|
||||||
|
|
||||||
// compute k = SHA512( N | PAD(g) )
|
|
||||||
|
|
||||||
mbedtls_mpi_write_binary(&N,tBuf,384); // write N into first half of staging buffer
|
|
||||||
mbedtls_mpi_write_binary(&g,tBuf+384,384); // write g into second half of staging buffer (fully padded with leading zeros)
|
|
||||||
mbedtls_sha512_ret(tBuf,768,tHash,0); // create hash of data
|
|
||||||
mbedtls_mpi_read_binary(&k,tHash,64); // load hash result into mpi structure k
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////
|
//////////////////////////////////////
|
||||||
|
|
@ -109,8 +99,9 @@ void SRP6A::createVerifyCode(const char *setupCode, uint8_t *verifyCode, uint8_t
|
||||||
TempBuffer<uint8_t> tHash(64); // temporary buffer for storing SHA-512 results
|
TempBuffer<uint8_t> tHash(64); // temporary buffer for storing SHA-512 results
|
||||||
char *icp; // storage for I:P
|
char *icp; // storage for I:P
|
||||||
|
|
||||||
randombytes_buf(salt,16); // generate 16 random bytes using libsodium (which uses the ESP32 hardware-based random number generator)
|
randombytes_buf(salt,16); // generate 16 random bytes for salt
|
||||||
mbedtls_mpi_read_binary(&s,salt,16);
|
mbedtls_mpi_read_binary(&s,salt,16); // load salt into s
|
||||||
|
Serial.printf("*** SALT GENERATION: ");print(&s);
|
||||||
|
|
||||||
asprintf(&icp,"Pair-Setup:%.3s-%.2s-%.3s",setupCode,setupCode+3,setupCode+5);
|
asprintf(&icp,"Pair-Setup:%.3s-%.2s-%.3s",setupCode,setupCode+3,setupCode+5);
|
||||||
|
|
||||||
|
|
@ -119,7 +110,7 @@ void SRP6A::createVerifyCode(const char *setupCode, uint8_t *verifyCode, uint8_t
|
||||||
mbedtls_mpi_write_binary(&s,tBuf,16); // write s into first 16 bytes of staging buffer
|
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((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_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
|
mbedtls_mpi_read_binary(&x,tHash,64); // load hash result into x
|
||||||
|
|
||||||
// compute v = g^x %N
|
// compute v = g^x %N
|
||||||
|
|
||||||
|
|
@ -131,37 +122,54 @@ void SRP6A::createVerifyCode(const char *setupCode, uint8_t *verifyCode, uint8_t
|
||||||
|
|
||||||
//////////////////////////////////////
|
//////////////////////////////////////
|
||||||
|
|
||||||
void SRP6A::loadVerifyCode(uint8_t *verifyCode, uint8_t *salt){
|
//void SRP6A::loadVerifyCode(uint8_t *verifyCode, uint8_t *salt){
|
||||||
|
//
|
||||||
mbedtls_mpi_read_binary(&s,salt,16);
|
// mbedtls_mpi_read_binary(&s,salt,16);
|
||||||
mbedtls_mpi_read_binary(&v,verifyCode,384);
|
// mbedtls_mpi_read_binary(&v,verifyCode,384);
|
||||||
|
//
|
||||||
}
|
//}
|
||||||
|
|
||||||
//////////////////////////////////////
|
//////////////////////////////////////
|
||||||
|
|
||||||
void SRP6A::createPublicKey(){
|
void SRP6A::createPublicKey(const uint8_t *verifyCode, const uint8_t *salt){
|
||||||
|
|
||||||
getPrivateKey(); // create and load b (random 32 bytes)
|
TempBuffer<uint8_t> tBuf(768); // temporary buffer for staging
|
||||||
|
TempBuffer<uint8_t> tHash(64); // temporary buffer for storing SHA-512 results
|
||||||
|
TempBuffer<uint8_t> privateKey(32); // temporary buffer for generating private key random numbers
|
||||||
|
|
||||||
// compute B = kv + g^b %N
|
mbedtls_mpi_read_binary(&s,salt,16); // load salt into s for use in later steps
|
||||||
|
mbedtls_mpi_read_binary(&v,verifyCode,384); // load verifyCode into v for use below
|
||||||
|
|
||||||
|
randombytes_buf(privateKey,32); // generate 32 random bytes for private key
|
||||||
|
mbedtls_mpi_read_binary(&b,privateKey,32); // load private key into b
|
||||||
|
|
||||||
|
// compute k = SHA512( N | PAD(g) )
|
||||||
|
|
||||||
|
mbedtls_mpi_write_binary(&N,tBuf,384); // write N into first half of staging buffer
|
||||||
|
mbedtls_mpi_write_binary(&g,tBuf+384,384); // write g into second half of staging buffer (fully padded with leading zeros)
|
||||||
|
mbedtls_sha512_ret(tBuf,768,tHash,0); // create hash of data
|
||||||
|
mbedtls_mpi_read_binary(&k,tHash,64); // load hash result into k
|
||||||
|
|
||||||
|
// compute B = (kv + g^b) %N
|
||||||
|
|
||||||
mbedtls_mpi_mul_mpi(&t1,&k,&v); // t1 = k*v
|
mbedtls_mpi_mul_mpi(&t1,&k,&v); // t1 = k*v
|
||||||
mbedtls_mpi_exp_mod(&t2,&g,&b,&N,&_rr); // t2 = g^b %N
|
mbedtls_mpi_exp_mod(&t2,&g,&b,&N,&_rr); // t2 = g^b %N
|
||||||
mbedtls_mpi_add_mpi(&t3,&t1,&t2); // t3 = t1 + t2
|
mbedtls_mpi_add_mpi(&t3,&t1,&t2); // t3 = t1 + t2
|
||||||
mbedtls_mpi_mod_mpi(&B,&t3,&N); // B = t3 %N = ACCESSORY PUBLIC KEY
|
mbedtls_mpi_mod_mpi(&B,&t3,&N); // B = t3 %N = ACCESSORY PUBLIC KEY
|
||||||
|
|
||||||
|
print(&s);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////
|
//////////////////////////////////////
|
||||||
|
|
||||||
void SRP6A::getPrivateKey(){
|
//void SRP6A::getPrivateKey(){
|
||||||
|
//
|
||||||
uint8_t privateKey[32];
|
// uint8_t privateKey[32];
|
||||||
|
//
|
||||||
randombytes_buf(privateKey,32); // generate 32 random bytes using libsodium (which uses the ESP32 hardware-based random number generator)
|
// randombytes_buf(privateKey,32); // generate 32 random bytes using libsodium (which uses the ESP32 hardware-based random number generator)
|
||||||
mbedtls_mpi_read_binary(&b,privateKey,32);
|
// mbedtls_mpi_read_binary(&b,privateKey,32);
|
||||||
}
|
//}
|
||||||
|
|
||||||
//////////////////////////////////////
|
//////////////////////////////////////
|
||||||
|
|
||||||
|
|
@ -253,10 +261,7 @@ void SRP6A::createProof(){
|
||||||
|
|
||||||
//////////////////////////////////////
|
//////////////////////////////////////
|
||||||
|
|
||||||
void SRP6A::print(mbedtls_mpi *mpi, int minLogLevel){
|
void SRP6A::print(mbedtls_mpi *mpi){
|
||||||
|
|
||||||
if(homeSpan.getLogLevel()<minLogLevel)
|
|
||||||
return;
|
|
||||||
|
|
||||||
size_t sLen;
|
size_t sLen;
|
||||||
|
|
||||||
|
|
|
||||||
11
src/SRP.h
11
src/SRP.h
|
|
@ -99,16 +99,15 @@ struct SRP6A {
|
||||||
void *operator new(size_t size){return(HS_MALLOC(size));} // override new operator to use PSRAM when available
|
void *operator new(size_t size){return(HS_MALLOC(size));} // override new operator to use PSRAM when available
|
||||||
|
|
||||||
void createVerifyCode(const char *setupCode, uint8_t *verifyCode, uint8_t *salt);
|
void createVerifyCode(const char *setupCode, uint8_t *verifyCode, uint8_t *salt);
|
||||||
void loadVerifyCode(uint8_t *verifyCode, uint8_t *salt);
|
// void loadVerifyCode(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 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
|
void createPublicKey(const uint8_t *verifyCode, const uint8_t *salt); // computes x, v, and B from random s, P, and b
|
||||||
void createPublicKey(); // computes x, v, and B from random s, P, and b
|
|
||||||
void createSessionKey(); // computes u from A and B, and then S from A, v, u, and b
|
void createSessionKey(); // computes u from A and B, and then S from A, v, u, and b
|
||||||
int verifyProof(); // verify M1 SRP6A Proof received from HAP client (return 1 on success, 0 on failure)
|
int verifyProof(); // verify M1 SRP6A Proof received from HAP client (return 1 on success, 0 on failure)
|
||||||
void createProof(); // create M2 server-side SRP6A Proof based on M1 as received from HAP Client
|
void createProof(); // create M2 server-side SRP6A Proof based on M1 as received from HAP Client
|
||||||
|
|
||||||
void print(mbedtls_mpi *mpi, int minLogLevel=0); // prints size of mpi (in bytes), followed by the mpi itself (as a hex charcter string), subject to specified minimum log level
|
void print(mbedtls_mpi *mpi); // prints size of mpi (in bytes), followed by the mpi itself (as a hex charcter string)
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue