Completed refactoring of SRP6A and integration into all steps of Pair-Setup

This commit is contained in:
Gregg 2023-12-28 17:32:17 -06:00
parent 9209cb6b41
commit cd85cc1629
3 changed files with 44 additions and 65 deletions

View File

@ -385,7 +385,7 @@ 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
if(srp==NULL) // create instance of SRP (if not already created) to persist until Pairing is fully complete if(srp==NULL) // create instance of SRP (if not already created) to persist until Pairing-Setup M5 completes
srp=new SRP6A; srp=new SRP6A;
TempBuffer<Verification> verifyData; // retrieve verification data (should already be stored in NVS) TempBuffer<Verification> verifyData; // retrieve verification data (should already be stored in NVS)
@ -416,7 +416,7 @@ int HAPClient::postPairSetupURL(uint8_t *content, size_t len){
pairStatus=pairState_M1; // reset pairStatus to first step of unpaired pairStatus=pairState_M1; // reset pairStatus to first step of unpaired
return(0); return(0);
}; };
srp->createSessionKey(*itPublicKey,(*itPublicKey).len); // create session key, K, from client Public Key, A srp->createSessionKey(*itPublicKey,(*itPublicKey).len); // create session key, K, from client Public Key, A
if(!srp->verifyClientProof(*itClientProof)){ // verify client Proof, M1 if(!srp->verifyClientProof(*itClientProof)){ // verify client Proof, M1
@ -430,19 +430,22 @@ int HAPClient::postPairSetupURL(uint8_t *content, size_t len){
auto itAccProof=responseTLV.add(kTLVType_Proof,64,NULL); // create blank accessory Proof TLV with space for 64 bytes auto itAccProof=responseTLV.add(kTLVType_Proof,64,NULL); // create blank accessory Proof TLV with space for 64 bytes
srp->createAccProof(*itAccProof); // M1 has been successully verified; now create accessory Proof M2 srp->createAccProof(*itAccProof); // M1 has been successully verified; now create accessory Proof M2
tlvRespond(responseTLV); // send response to client tlvRespond(responseTLV); // send response to client
pairStatus=pairState_M5; // set next expected pair-state request from client pairStatus=pairState_M5; // set next expected pair-state request from client
return(1); return(1);
} }
break; break;
case pairState_M5:{ // 'Exchange Request' case pairState_M5:{ // 'Exchange Request'
responseTLV.add(kTLVType_State,pairState_M6); // set State=<M6>
auto itEncryptedData=iosTLV.find(kTLVType_EncryptedData); auto itEncryptedData=iosTLV.find(kTLVType_EncryptedData);
if(iosTLV.len(itEncryptedData)<=0){ if(iosTLV.len(itEncryptedData)<=0){
LOG0("\n*** ERROR: Required 'EncryptedData' TLV record for this step is bad or missing\n\n"); LOG0("\n*** ERROR: Required 'EncryptedData' TLV record for this step is bad or missing\n\n");
responseTLV.add(kTLVType_State,pairState_M6); // set State=<M6>
responseTLV.add(kTLVType_Error,tagError_Unknown); // set Error=Unknown (there is no specific error type for missing/bad TLV data) responseTLV.add(kTLVType_Error,tagError_Unknown); // set Error=Unknown (there is no specific error type for missing/bad TLV data)
tlvRespond(responseTLV); // send response to client tlvRespond(responseTLV); // send response to client
pairStatus=pairState_M1; // reset pairStatus to first step of unpaired pairStatus=pairState_M1; // reset pairStatus to first step of unpaired
@ -457,18 +460,17 @@ int HAPClient::postPairSetupURL(uint8_t *content, size_t len){
// Note the SALT and INFO text fields used by HKDF to create this Session Key are NOT the same as those for creating iosDeviceX. // Note the SALT and INFO text fields used by HKDF to create this Session Key are NOT the same as those for creating iosDeviceX.
// The iosDeviceX HKDF calculations are separate and will be performed further below with the SALT and INFO as specified in the HAP docs. // The iosDeviceX HKDF calculations are separate and will be performed further below with the SALT and INFO as specified in the HAP docs.
TempBuffer<uint8_t> srpSessionKey(crypto_box_PUBLICKEYBYTES); // temporary space - used only in this block TempBuffer<uint8_t> sessionKey(crypto_box_PUBLICKEYBYTES); // temporary space - used only in this block
hkdf.create(srpSessionKey,srp->sharedSecret,64,"Pair-Setup-Encrypt-Salt","Pair-Setup-Encrypt-Info"); // create SessionKey hkdf.create(sessionKey,srp->K,64,"Pair-Setup-Encrypt-Salt","Pair-Setup-Encrypt-Info"); // create SessionKey
LOG2("------- DECRYPTING SUB-TLVS -------\n"); LOG2("------- DECRYPTING SUB-TLVS -------\n");
// use SessionKey to decrypt encryptedData TLV with padded nonce="PS-Msg05" // use SessionKey to decrypt encryptedData TLV with padded nonce="PS-Msg05"
TempBuffer<uint8_t> decrypted((*itEncryptedData).len-crypto_aead_chacha20poly1305_IETF_ABYTES); // temporary storage for decrypted data TempBuffer<uint8_t> decrypted((*itEncryptedData).len-crypto_aead_chacha20poly1305_IETF_ABYTES); // temporary storage for decrypted data
if(crypto_aead_chacha20poly1305_ietf_decrypt(decrypted, NULL, NULL, *itEncryptedData, (*itEncryptedData).len, NULL, 0, (unsigned char *)"\x00\x00\x00\x00PS-Msg05", srpSessionKey)==-1){ if(crypto_aead_chacha20poly1305_ietf_decrypt(decrypted, NULL, NULL, *itEncryptedData, (*itEncryptedData).len, NULL, 0, (unsigned char *)"\x00\x00\x00\x00PS-Msg05", sessionKey)==-1){
LOG0("\n*** ERROR: Exchange-Request Authentication Failed\n\n"); LOG0("\n*** ERROR: Exchange-Request Authentication Failed\n\n");
responseTLV.add(kTLVType_State,pairState_M6); // set State=<M6>
responseTLV.add(kTLVType_Error,tagError_Authentication); // set Error=Authentication responseTLV.add(kTLVType_Error,tagError_Authentication); // set Error=Authentication
tlvRespond(responseTLV); // send response to client tlvRespond(responseTLV); // send response to client
pairStatus=pairState_M1; // reset pairStatus to first step of unpaired pairStatus=pairState_M1; // reset pairStatus to first step of unpaired
@ -486,7 +488,6 @@ int HAPClient::postPairSetupURL(uint8_t *content, size_t len){
if(subTLV.len(itIdentifier)!=hap_controller_IDBYTES || subTLV.len(itSignature)!=crypto_sign_BYTES || subTLV.len(itPublicKey)!=crypto_sign_PUBLICKEYBYTES){ if(subTLV.len(itIdentifier)!=hap_controller_IDBYTES || subTLV.len(itSignature)!=crypto_sign_BYTES || subTLV.len(itPublicKey)!=crypto_sign_PUBLICKEYBYTES){
LOG0("\n*** ERROR: One or more of required 'Identifier,' 'PublicKey,' and 'Signature' TLV records for this step is bad or missing\n\n"); LOG0("\n*** ERROR: One or more of required 'Identifier,' 'PublicKey,' and 'Signature' TLV records for this step is bad or missing\n\n");
responseTLV.add(kTLVType_State,pairState_M6); // set State=<M6>
responseTLV.add(kTLVType_Error,tagError_Unknown); // set Error=Unknown (there is no specific error type for missing/bad TLV data) responseTLV.add(kTLVType_Error,tagError_Unknown); // set Error=Unknown (there is no specific error type for missing/bad TLV data)
tlvRespond(responseTLV); // send response to client tlvRespond(responseTLV); // send response to client
pairStatus=pairState_M1; // reset pairStatus to first step of unpaired pairStatus=pairState_M1; // reset pairStatus to first step of unpaired
@ -499,15 +500,14 @@ int HAPClient::postPairSetupURL(uint8_t *content, size_t len){
// Note that the SALT and INFO text fields now match those in HAP Section 5.6.6.1 // Note that the SALT and INFO text fields now match those in HAP Section 5.6.6.1
TempBuffer<uint8_t> iosDeviceX(32); TempBuffer<uint8_t> iosDeviceX(32);
hkdf.create(iosDeviceX,srp->sharedSecret,64,"Pair-Setup-Controller-Sign-Salt","Pair-Setup-Controller-Sign-Info"); // derive iosDeviceX (32 bytes) from SRP Shared Secret using HKDF hkdf.create(iosDeviceX,srp->K,64,"Pair-Setup-Controller-Sign-Salt","Pair-Setup-Controller-Sign-Info"); // derive iosDeviceX (32 bytes) from SRP Shared Secret using HKDF
// Concatenate iosDeviceX, IOS ID, and IOS PublicKey into iosDeviceInfo // Concatenate iosDeviceX, IOS ID, and IOS PublicKey into iosDeviceInfo
TempBuffer<uint8_t> iosDeviceInfo(iosDeviceX,iosDeviceX.len(),(*itIdentifier).val.get(),(*itIdentifier).len,(*itPublicKey).val.get(),(*itPublicKey).len,NULL); TempBuffer<uint8_t> iosDeviceInfo(iosDeviceX,iosDeviceX.len(),(*itIdentifier).val.get(),(*itIdentifier).len,(*itPublicKey).val.get(),(*itPublicKey).len,NULL);
if(crypto_sign_verify_detached(*itSignature, iosDeviceInfo, iosDeviceInfo.len(), *itPublicKey) != 0){ // verify signature of iosDeviceInfo using iosDeviceLTPK if(crypto_sign_verify_detached(*itSignature, iosDeviceInfo, iosDeviceInfo.len(), *itPublicKey) != 0){ // verify signature of iosDeviceInfo using iosDeviceLTPK
LOG0("\n*** ERROR: LPTK Signature Verification Failed\n\n"); LOG0("\n*** ERROR: LPTK Signature Verification Failed\n\n");
responseTLV.add(kTLVType_State,pairState_M6); // set State=<M6>
responseTLV.add(kTLVType_Error,tagError_Authentication); // set Error=Authentication responseTLV.add(kTLVType_Error,tagError_Authentication); // set Error=Authentication
tlvRespond(responseTLV); // send response to client tlvRespond(responseTLV); // send response to client
pairStatus=pairState_M1; // reset pairStatus to first step of unpaired pairStatus=pairState_M1; // reset pairStatus to first step of unpaired
@ -519,7 +519,7 @@ int HAPClient::postPairSetupURL(uint8_t *content, size_t len){
// Now perform the above steps in reverse to securely transmit the AccessoryLTPK to the Controller (HAP Section 5.6.6.2) // Now perform the above steps in reverse to securely transmit the AccessoryLTPK to the Controller (HAP Section 5.6.6.2)
TempBuffer<uint8_t> accessoryX(32); TempBuffer<uint8_t> accessoryX(32);
hkdf.create(accessoryX,srp->sharedSecret,64,"Pair-Setup-Accessory-Sign-Salt","Pair-Setup-Accessory-Sign-Info"); // derive accessoryX from SRP Shared Secret using HKDF hkdf.create(accessoryX,srp->K,64,"Pair-Setup-Accessory-Sign-Salt","Pair-Setup-Accessory-Sign-Info"); // derive accessoryX from SRP Shared Secret using HKDF
// Concatenate accessoryX, Accessory ID, and Accessory PublicKey into accessoryInfo // Concatenate accessoryX, Accessory ID, and Accessory PublicKey into accessoryInfo
@ -531,28 +531,28 @@ int HAPClient::postPairSetupURL(uint8_t *content, size_t len){
crypto_sign_detached(*itSignature,NULL,accessoryInfo,accessoryInfo.len(),accessory.LTSK); // produce signature of accessoryInfo using AccessoryLTSK (Ed25519 long-term secret key) crypto_sign_detached(*itSignature,NULL,accessoryInfo,accessoryInfo.len(),accessory.LTSK); // produce signature of accessoryInfo using AccessoryLTSK (Ed25519 long-term secret key)
subTLV.add(kTLVType_Identifier,hap_accessory_IDBYTES,accessory.ID); // set Identifier TLV record as accessoryPairingID subTLV.add(kTLVType_Identifier,hap_accessory_IDBYTES,accessory.ID); // set Identifier TLV record as accessoryPairingID
subTLV.add(kTLVType_PublicKey,crypto_sign_PUBLICKEYBYTES,accessory.LTPK); // set PublicKey TLV record as accessoryLTPK subTLV.add(kTLVType_PublicKey,crypto_sign_PUBLICKEYBYTES,accessory.LTPK); // set PublicKey TLV record as accessoryLTPK
LOG2("------- ENCRYPTING SUB-TLVS -------\n"); LOG2("------- ENCRYPTING SUB-TLVS -------\n");
subTLV.print(); subTLV.print();
TempBuffer<uint8_t> subPack(subTLV.pack_size()); // create sub-TLV by packing Identifier, PublicKey and Signature TLV records together TempBuffer<uint8_t> subPack(subTLV.pack_size()); // create sub-TLV by packing Identifier, PublicKey and Signature TLV records together
subTLV.pack(subPack); subTLV.pack(subPack);
// Encrypt the subTLV data using the same SRP Session Key as above with ChaCha20-Poly1305 // Encrypt the subTLV data using the same SRP Session Key as above with ChaCha20-Poly1305
itEncryptedData=responseTLV.add(kTLVType_EncryptedData,subPack.len()+crypto_aead_chacha20poly1305_IETF_ABYTES,NULL); //create blank EncryptedData TLV with space for subTLV + Authentication Tag itEncryptedData=responseTLV.add(kTLVType_EncryptedData,subPack.len()+crypto_aead_chacha20poly1305_IETF_ABYTES,NULL); //create blank EncryptedData TLV with space for subTLV + Authentication Tag
crypto_aead_chacha20poly1305_ietf_encrypt(*itEncryptedData,NULL,subPack,subPack.len(),NULL,0,NULL,(unsigned char *)"\x00\x00\x00\x00PS-Msg06",srpSessionKey); crypto_aead_chacha20poly1305_ietf_encrypt(*itEncryptedData,NULL,subPack,subPack.len(),NULL,0,NULL,(unsigned char *)"\x00\x00\x00\x00PS-Msg06",sessionKey);
LOG2("---------- END SUB-TLVS! ----------\n"); LOG2("---------- END SUB-TLVS! ----------\n");
responseTLV.add(kTLVType_State,pairState_M6); // set State=<M6>
tlvRespond(responseTLV); // send response to client tlvRespond(responseTLV); // send response to client
delete srp; // delete SRP - no longer needed once pairing is completed
mdns_service_txt_item_set("_hap","_tcp","sf","0"); // broadcast new status mdns_service_txt_item_set("_hap","_tcp","sf","0"); // broadcast new status
LOG1("\n*** ACCESSORY PAIRED! ***\n"); LOG1("\n*** ACCESSORY PAIRED! ***\n");

View File

@ -49,10 +49,6 @@ SRP6A::SRP6A(){
mbedtls_mpi_init(&S); mbedtls_mpi_init(&S);
mbedtls_mpi_init(&k); mbedtls_mpi_init(&k);
mbedtls_mpi_init(&u); mbedtls_mpi_init(&u);
mbedtls_mpi_init(&K);
mbedtls_mpi_init(&M1);
mbedtls_mpi_init(&M1V);
mbedtls_mpi_init(&M2);
mbedtls_mpi_init(&_rr); mbedtls_mpi_init(&_rr);
mbedtls_mpi_init(&t1); mbedtls_mpi_init(&t1);
mbedtls_mpi_init(&t2); mbedtls_mpi_init(&t2);
@ -80,10 +76,6 @@ SRP6A::~SRP6A(){
mbedtls_mpi_free(&S); mbedtls_mpi_free(&S);
mbedtls_mpi_free(&k); mbedtls_mpi_free(&k);
mbedtls_mpi_free(&u); mbedtls_mpi_free(&u);
mbedtls_mpi_free(&K);
mbedtls_mpi_free(&M1);
mbedtls_mpi_free(&M1V);
mbedtls_mpi_free(&M2);
mbedtls_mpi_free(&_rr); mbedtls_mpi_free(&_rr);
mbedtls_mpi_free(&t1); mbedtls_mpi_free(&t1);
mbedtls_mpi_free(&t2); mbedtls_mpi_free(&t2);
@ -117,9 +109,10 @@ void SRP6A::createVerifyCode(const char *setupCode, Verification *vData){
// compute v = g^x %N // 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_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,vData->verifyCode,384); // write v into verifyCode mbedtls_mpi_write_binary(&v,vData->verifyCode,384); // write v into verifyCode (padding with initial zeros is less than 384 bytes)
free(icp); free(icp);
} }
////////////////////////////////////// //////////////////////////////////////
@ -147,14 +140,14 @@ void SRP6A::createPublicKey(const Verification *vData, uint8_t *publicKey){
mbedtls_sha512_ret(tBuf,768,tHash,0); // create hash of data mbedtls_sha512_ret(tBuf,768,tHash,0); // create hash of data
mbedtls_mpi_read_binary(&k,tHash,64); // load hash result into k mbedtls_mpi_read_binary(&k,tHash,64); // load hash result into k
// compute B = (kv + g^b) %N // compute B = (k*v + 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
mbedtls_mpi_write_binary(&B,publicKey,384); // write B into publicKey mbedtls_mpi_write_binary(&B,publicKey,384); // write B into publicKey (padding with initial zeros is less than 384 bytes)
} }
@ -169,25 +162,22 @@ void SRP6A::createSessionKey(const uint8_t *publicKey, size_t len){
// compute u = SHA512( PAD(A) | PAD(B) ) // compute u = SHA512( PAD(A) | PAD(B) )
mbedtls_mpi_write_binary(&A,tBuf,384); // write A into first half of staging buffer (will pad to fill 384 bytes) mbedtls_mpi_write_binary(&A,tBuf,384); // write A into first half of staging buffer (padding with initial zeros is less than 384 bytes)
mbedtls_mpi_write_binary(&B,tBuf+384,384); // write B into second half of staging buffer (will pad to fill 384 bytes) mbedtls_mpi_write_binary(&B,tBuf+384,384); // write B into second half of staging buffer (padding with initial zeros is less than 384 bytes)
mbedtls_sha512_ret(tBuf,768,tHash,0); // create hash of data mbedtls_sha512_ret(tBuf,768,tHash,0); // create hash of data
mbedtls_mpi_read_binary(&u,tHash,64); // load hash result into mpi structure u mbedtls_mpi_read_binary(&u,tHash,64); // load hash result into mpi structure u
// compute S = (Av^u)^b %N // compute S = (A * v^u)^b %N
mbedtls_mpi_exp_mod(&t1,&v,&u,&N,&_rr); // t1 = v^u %N mbedtls_mpi_exp_mod(&t1,&v,&u,&N,&_rr); // t1 = v^u %N
mbedtls_mpi_mul_mpi(&t2,&A,&t1); // t2 = A*t1 mbedtls_mpi_mul_mpi(&t2,&A,&t1); // t2 = A*t1
mbedtls_mpi_mod_mpi(&t1,&t2,&N); // t1 = t2 %N (this is needed to reduce size of t2 before next calculation) mbedtls_mpi_mod_mpi(&t1,&t2,&N); // t1 = t2 %N (this is needed to reduce size of t2 before next calculation)
mbedtls_mpi_exp_mod(&S,&t1,&b,&N,&_rr); // S = t1^b %N mbedtls_mpi_exp_mod(&S,&t1,&b,&N,&_rr); // S = t1^b %N
// compute K = SHA512( S ) // compute K = SHA512( PAD(S) )
mbedtls_mpi_write_binary(&S,tBuf,384); // write S into staging buffer (only first half of buffer will be used) mbedtls_mpi_write_binary(&S,tBuf,384); // write S into staging buffer (only first half of buffer will be used)
mbedtls_sha512_ret(tBuf,384,tHash,0); // create hash of data mbedtls_sha512_ret(tBuf,384,K,0); // create hash of data - this is the SRP SHARED SESSION KEY, K
mbedtls_mpi_read_binary(&K,tHash,64); // load hash result into mpi structure K. This is the SRP SHARED SECRET KEY
mbedtls_mpi_write_binary(&K,sharedSecret,64); // store SHARED SECRET in easy-to-use binary (uint8_t) format
} }
@ -199,12 +189,12 @@ int SRP6A::verifyClientProof(const uint8_t *proof){
TempBuffer<uint8_t> tBuf(976); // temporary buffer for staging TempBuffer<uint8_t> tBuf(976); // temporary buffer for staging
TempBuffer<uint8_t> tHash(64); // temporary buffer for storing SHA-512 results TempBuffer<uint8_t> tHash(64); // temporary buffer for storing SHA-512 results
mbedtls_mpi_read_binary(&M1,proof,64); // load client Proof into M1 memcpy(M1,proof,64); // load client Proof into M1
size_t count=0; // total number of bytes for final hash size_t count=0; // total number of bytes for final hash
size_t sLen; size_t sLen;
// compute M1V // compute M1V = SHA512( SHA512(N) xor SHA512(g) | SHA512(I) | s | A | B | K )
mbedtls_mpi_write_binary(&N,tBuf,384); // write N into staging buffer mbedtls_mpi_write_binary(&N,tBuf,384); // write N into staging buffer
mbedtls_sha512_ret(tBuf,384,tHash,0); // create hash of data mbedtls_sha512_ret(tBuf,384,tHash,0); // create hash of data
@ -225,15 +215,12 @@ int SRP6A::verifyClientProof(const uint8_t *proof){
mbedtls_mpi_write_binary(&B,tBuf+count,sLen); // concatenate B to staging buffer. Note B is NOT padded with leading zeros (so may be less than 384 bytes) mbedtls_mpi_write_binary(&B,tBuf+count,sLen); // concatenate B to staging buffer. Note B is NOT padded with leading zeros (so may be less than 384 bytes)
count+=sLen; // increment total bytes written to staging buffer count+=sLen; // increment total bytes written to staging buffer
mbedtls_mpi_write_binary(&K,tBuf+count,64); // concatenate K to staging buffer (should always be 64 bytes since it is a hashed value) memcpy(tBuf+count,K,64); // concatenate K to staging buffer (should always be 64 bytes since it is a hashed value)
count+=64; // final total of bytes written to staging buffer count+=64; // final total of bytes written to staging buffer
mbedtls_sha512_ret(tBuf,count,tHash,0); // create hash of data mbedtls_sha512_ret(tBuf,count,tHash,0); // create hash of data - this is M1V
mbedtls_mpi_read_binary(&M1V,tHash,64); // load hash result into mpi structure M1V
// check that client Proof M1 matches M1V if(!memcmp(M1,tHash,64)) // check that client Proof M1 matches M1V
if(!mbedtls_mpi_cmp_mpi(&M1,&M1V)) // cmp_mpi uses same logic as strcmp: returns 0 if EQUAL, otherwise +/- 1
return(1); // success - proof from HAP Client is verified return(1); // success - proof from HAP Client is verified
return(0); return(0);
@ -243,18 +230,15 @@ int SRP6A::verifyClientProof(const uint8_t *proof){
void SRP6A::createAccProof(uint8_t *proof){ void SRP6A::createAccProof(uint8_t *proof){
uint8_t tBuf[512]; // temporary buffer for staging TempBuffer<uint8_t> tBuf(512); // temporary buffer for staging
// compute M2 = H( A | M1 | K ) // compute M2 = SHA512( A | M1 | K )
mbedtls_mpi_write_binary(&A,tBuf,384); // write A into staging buffer mbedtls_mpi_write_binary(&A,tBuf,384); // write A into staging buffer
mbedtls_mpi_write_binary(&M1,tBuf+384,64); // concatenate M1 (now verified) to staging buffer memcpy(tBuf+384,M1,64); // concatenate M1 (now verified) to staging buffer
mbedtls_mpi_write_binary(&K,tBuf+448,64); // concatenate K to staging buffer memcpy(tBuf+448,K,64); // concatenate K to staging buffer
mbedtls_sha512_ret(tBuf,512,tBuf,0); // create hash of data mbedtls_sha512_ret(tBuf,512,proof,0); // create hash of data writing directly to proof - this is M2
mbedtls_mpi_read_binary(&M2,tBuf,64); // load hash results into mpi structure M2
mbedtls_mpi_write_binary(&M2,proof,64); // write M2 into proof
} }
////////////////////////////////////// //////////////////////////////////////

View File

@ -88,18 +88,13 @@ struct SRP6A {
mbedtls_mpi A; // A - public key RECEIVED from HAP Client (max 384 bytes) mbedtls_mpi A; // A - public key RECEIVED from HAP Client (max 384 bytes)
mbedtls_mpi u; // u = H(PAD(A) | PAB(B)) - "u-factor" (64 bytes) mbedtls_mpi u; // u = H(PAD(A) | PAB(B)) - "u-factor" (64 bytes)
mbedtls_mpi S; // S = (A*v^u)^b %N - SRP shared "premaster" key, based on accessory private key and client public key (max 384 bytes) mbedtls_mpi S; // S = (A*v^u)^b %N - SRP shared "premaster" key, based on accessory private key and client public key (max 384 bytes)
mbedtls_mpi K; // K = H( S ) - SRP SHARED SECRET KEY (64 bytes) uint8_t K[64]; // K = H(S) - SRP SHARED SECRET KEY (64 bytes)
mbedtls_mpi M1; // M1 - proof RECEIVED from HAP Client (64 bytes) uint8_t M1[64]; // M1 - proof RECEIVED from HAP Client (64 bytes)
mbedtls_mpi M1V; // M1V - accessory's independent computation of M1 to verify proof (see code for details of computation) mbedtls_mpi t1; // temp1 - temporary mpi structures for intermediate results
mbedtls_mpi M2; // M2 - accessory's counter-proof to send to HAP Client after M1=M1V has been verified (64 bytes) mbedtls_mpi t2; // temp2 - temporary mpi structures for intermediate results
mbedtls_mpi t3; // temp3 - temporary mpi structures for intermediate results
mbedtls_mpi t1; // temporary mpi structures for intermediate results
mbedtls_mpi t2;
mbedtls_mpi t3;
mbedtls_mpi _rr; // _rr - temporary "helper" for large exponential modulus calculations mbedtls_mpi _rr; // _rr - temporary "helper" for large exponential modulus calculations
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
~SRP6A(); ~SRP6A();