Start re-working SRP6A's use in Pair-Setup to make it local instead of global

This commit is contained in:
Gregg 2023-12-27 14:31:22 -06:00
parent beef66eec0
commit da55b9b6b1
8 changed files with 133 additions and 91 deletions

View File

@ -36,7 +36,7 @@
void HAPClient::init(){ void HAPClient::init(){
size_t len; // not used but required to read blobs from NVS size_t len; // not used but required to read blobs from NVS
nvs_open("SRP",NVS_READWRITE,&srpNVS); // open SRP data namespace in NVS nvs_open("SRP",NVS_READWRITE,&srpNVS); // open SRP data namespace in NVS
nvs_open("HAP",NVS_READWRITE,&hapNVS); // open HAP data namespace in NVS nvs_open("HAP",NVS_READWRITE,&hapNVS); // open HAP data namespace in NVS
@ -48,37 +48,20 @@ void HAPClient::init(){
homeSpan.spanOTA.setPassword(DEFAULT_OTA_PASSWORD); // ...use default password homeSpan.spanOTA.setPassword(DEFAULT_OTA_PASSWORD); // ...use default password
} }
} }
if(nvs_get_blob(srpNVS,"VERIFYDATA",NULL,&len)) // if Pair-Setup verification code data not found in NVS
homeSpan.setPairingCode(DEFAULT_SETUP_CODE); // create and save verification from using Pairing Setup Code
if(strlen(homeSpan.pairingCodeCommand)){ // load verification setup code if provided if(!strlen(homeSpan.qrID)){ // is Setup ID has not been specified in sketch
homeSpan.processSerialCommand(homeSpan.pairingCodeCommand); // if load failed due to invalid code, the logic below still runs and will pick up previous code or use the default one if(!nvs_get_str(hapNVS,"SETUPID",NULL,&len)){ // check for saved value
} nvs_get_str(hapNVS,"SETUPID",homeSpan.qrID,&len); // retrieve data
struct { // temporary structure to hold SRP verification code and salt stored in NVS
uint8_t salt[16];
uint8_t verifyCode[384];
} verifyData;
if(!nvs_get_blob(srpNVS,"VERIFYDATA",NULL,&len)){ // if found verification code data in NVS
nvs_get_blob(srpNVS,"VERIFYDATA",&verifyData,&len); // retrieve data
srp.loadVerifyCode(verifyData.verifyCode,verifyData.salt); // load verification code and salt into SRP structure
} else {
LOG0("Generating SRP verification data for default Setup Code: %.3s-%.2s-%.3s\n",homeSpan.defaultSetupCode,homeSpan.defaultSetupCode+3,homeSpan.defaultSetupCode+5);
srp.createVerifyCode(homeSpan.defaultSetupCode,verifyData.verifyCode,verifyData.salt); // create verification code from default Setup Code and random salt
nvs_set_blob(srpNVS,"VERIFYDATA",&verifyData,sizeof(verifyData)); // update data
nvs_commit(srpNVS); // commit to NVS
LOG0("Setup Payload for Optional QR Code: %s\n\n",homeSpan.qrCode.get(atoi(homeSpan.defaultSetupCode),homeSpan.qrID,atoi(homeSpan.category)));
}
if(!strlen(homeSpan.qrID)){ // Setup ID has not been specified in sketch
if(!nvs_get_str(hapNVS,"SETUPID",NULL,&len)){ // check for saved value
nvs_get_str(hapNVS,"SETUPID",homeSpan.qrID,&len); // retrieve data
} else { } else {
sprintf(homeSpan.qrID,"%s",DEFAULT_QR_ID); // use default sprintf(homeSpan.qrID,"%s",DEFAULT_QR_ID); // use default
} }
} }
if(!nvs_get_blob(hapNVS,"ACCESSORY",NULL,&len)){ // if found long-term Accessory data in NVS if(!nvs_get_blob(hapNVS,"ACCESSORY",NULL,&len)){ // if found long-term Accessory data in NVS
nvs_get_blob(hapNVS,"ACCESSORY",&accessory,&len); // retrieve data nvs_get_blob(hapNVS,"ACCESSORY",&accessory,&len); // retrieve data
} else { } else {
LOG0("Generating new random Accessory ID and Long-Term Ed25519 Signature Keys...\n\n"); LOG0("Generating new random Accessory ID and Long-Term Ed25519 Signature Keys...\n\n");
uint8_t buf[6]; uint8_t buf[6];
@ -91,13 +74,13 @@ void HAPClient::init(){
memcpy(accessory.ID,cBuf,17); // copy into Accessory ID for permanent storage memcpy(accessory.ID,cBuf,17); // copy into Accessory ID for permanent storage
crypto_sign_keypair(accessory.LTPK,accessory.LTSK); // generate new random set of keys using libsodium public-key signature crypto_sign_keypair(accessory.LTPK,accessory.LTSK); // generate new random set of keys using libsodium public-key signature
nvs_set_blob(hapNVS,"ACCESSORY",&accessory,sizeof(accessory)); // update data nvs_set_blob(hapNVS,"ACCESSORY",&accessory,sizeof(accessory)); // update data
nvs_commit(hapNVS); // commit to NVS nvs_commit(hapNVS); // commit to NVS
} }
if(!nvs_get_blob(hapNVS,"CONTROLLERS",NULL,&len)){ // if found long-term Controller Pairings data from NVS if(!nvs_get_blob(hapNVS,"CONTROLLERS",NULL,&len)){ // if found long-term Controller Pairings data from NVS
TempBuffer<Controller> tBuf(len/sizeof(Controller)); TempBuffer<Controller> tBuf(len/sizeof(Controller));
nvs_get_blob(hapNVS,"CONTROLLERS",tBuf,&len); // retrieve data nvs_get_blob(hapNVS,"CONTROLLERS",tBuf,&len); // retrieve data
for(int i=0;i<tBuf.size();i++){ for(int i=0;i<tBuf.size();i++){
if(tBuf[i].allocated) if(tBuf[i].allocated)
controllerList.push_back(tBuf[i]); controllerList.push_back(tBuf[i]);
@ -403,9 +386,9 @@ int HAPClient::postPairSetupURL(uint8_t *content, size_t len){
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> responseTLV.add(kTLVType_State,pairState_M2); // set State=<M2>
srp.createPublicKey(); // create accessory Public Key from Pair-Setup code (displayed to user) srp->createPublicKey(); // create accessory Public Key from Pair-Setup code (displayed to user)
mbedtls_mpi_write_binary(&srp.B,*itPublicKey,(*itPublicKey).len); // load server PublicKey, B, into TLV mbedtls_mpi_write_binary(&srp->B,*itPublicKey,(*itPublicKey).len); // load server PublicKey, B, into TLV
mbedtls_mpi_write_binary(&srp.s,*itSalt,(*itSalt).len); // load Salt, s, into TLV mbedtls_mpi_write_binary(&srp->s,*itSalt,(*itSalt).len); // load 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);
@ -426,12 +409,12 @@ int HAPClient::postPairSetupURL(uint8_t *content, size_t len){
return(0); return(0);
}; };
mbedtls_mpi_read_binary(&srp.A,*itPublicKey,(*itPublicKey).len); // load client PublicKey TLV into A mbedtls_mpi_read_binary(&srp->A,*itPublicKey,(*itPublicKey).len); // load client PublicKey TLV into A
mbedtls_mpi_read_binary(&srp.M1,*itClientProof,(*itClientProof).len); // load client Proof TLV into M1 mbedtls_mpi_read_binary(&srp->M1,*itClientProof,(*itClientProof).len); // load client Proof TLV into M1
srp.createSessionKey(); // create session key, K, from receipt of client Public Key, A srp->createSessionKey(); // create session key, K, from receipt of client Public Key, A
if(!srp.verifyProof()){ // verify client Proof, M1 if(!srp->verifyProof()){ // verify client Proof, M1
LOG0("\n*** ERROR: SRP Proof Verification Failed\n\n"); LOG0("\n*** ERROR: SRP Proof Verification Failed\n\n");
responseTLV.add(kTLVType_State,pairState_M4); // set State=<M4> responseTLV.add(kTLVType_State,pairState_M4); // set State=<M4>
responseTLV.add(kTLVType_Error,tagError_Authentication); // set Error=Authentication responseTLV.add(kTLVType_Error,tagError_Authentication); // set Error=Authentication
@ -443,8 +426,8 @@ 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
responseTLV.add(kTLVType_State,pairState_M4); // set State=<M4> responseTLV.add(kTLVType_State,pairState_M4); // set State=<M4>
srp.createProof(); // M1 has been successully verified; now create accessory proof M2 srp->createProof(); // M1 has been successully verified; now create accessory proof M2
mbedtls_mpi_write_binary(&srp.M2,*itAccProof,(*itAccProof).len); // load accessory Proof, M2, into TLV mbedtls_mpi_write_binary(&srp->M2,*itAccProof,(*itAccProof).len); // load accessory Proof, M2, into TLV
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);
@ -473,7 +456,7 @@ int HAPClient::postPairSetupURL(uint8_t *content, size_t len){
// 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> srpSessionKey(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(srpSessionKey,srp->sharedSecret,64,"Pair-Setup-Encrypt-Salt","Pair-Setup-Encrypt-Info"); // create SessionKey
LOG2("------- DECRYPTING SUB-TLVS -------\n"); LOG2("------- DECRYPTING SUB-TLVS -------\n");
@ -514,7 +497,7 @@ 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->sharedSecret,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
@ -534,7 +517,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->sharedSecret,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
@ -1672,6 +1655,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;
int HAPClient::conNum; int HAPClient::conNum;

View File

@ -52,6 +52,14 @@ const TLV8_names HAP_Names[] = {
#define hap_controller_IDBYTES 36 #define hap_controller_IDBYTES 36
#define hap_accessory_IDBYTES 17 #define hap_accessory_IDBYTES 17
/////////////////////////////////////////////////
// Pair-Setup Code Verification Data and Salt
struct Verification {
uint8_t salt[16];
uint8_t verifyCode[384];
};
///////////////////////////////////////////////// /////////////////////////////////////////////////
// NONCE Structure (HAP used last 64 of 96 bits) // NONCE Structure (HAP used last 64 of 96 bits)
@ -108,7 +116,7 @@ struct HAPClient {
static nvs_handle srpNVS; // handle for non-volatile-storage of SRP data static nvs_handle srpNVS; // handle for non-volatile-storage of SRP data
static HKDF hkdf; // generates (and stores) HKDF-SHA-512 32-byte keys derived from an inputKey of arbitrary length, a salt string, and an info string static HKDF hkdf; // generates (and stores) HKDF-SHA-512 32-byte keys derived from an inputKey of arbitrary length, a salt string, and an info string
static pairState pairStatus; // tracks pair-setup status static pairState pairStatus; // tracks pair-setup status
static SRP6A srp; // stores all SRP-6A keys used for Pair-Setup static SRP6A *srp; // stores all SRP-6A keys used for Pair-Setup (must persist through multiple calls to Pair-Setup)
static Accessory accessory; // Accessory ID and Ed25519 public and secret keys- permanently stored static Accessory accessory; // Accessory ID and Ed25519 public and secret keys- permanently stored
static list<Controller, Mallocator<Controller>> controllerList; // linked-list of Paired Controller IDs and ED25519 long-term public keys - permanently stored static list<Controller, Mallocator<Controller>> controllerList; // linked-list of Paired Controller IDs and ED25519 long-term public keys - permanently stored
static int conNum; // connection number - used to keep track of per-connection EV notifications static int conNum; // connection number - used to keep track of per-connection EV notifications

View File

@ -674,31 +674,8 @@ void Span::processSerialCommand(const char *c){
break; break;
case 'S': { case 'S': {
char setupCode[10];
struct { // temporary structure to hold SRP verification code and salt stored in NVS setPairingCode(c+1);
uint8_t salt[16];
uint8_t verifyCode[384];
} verifyData;
sscanf(c+1," %9[0-9]",setupCode);
if(strlen(setupCode)!=8){
LOG0("\n*** Invalid request to change Setup Code. Code must be exactly 8 digits.\n\n");
} else
if(!network.allowedCode(setupCode)){
LOG0("\n*** Invalid request to change Setup Code. Code too simple.\n\n");
} else {
LOG0("\nGenerating SRP verification data for new Setup Code: %.3s-%.2s-%.3s ... ",setupCode,setupCode+3,setupCode+5);
HAPClient::srp.createVerifyCode(setupCode,verifyData.verifyCode,verifyData.salt); // create verification code from default Setup Code and random salt
nvs_set_blob(HAPClient::srpNVS,"VERIFYDATA",&verifyData,sizeof(verifyData)); // update data
nvs_commit(HAPClient::srpNVS); // commit to NVS
LOG0("New Code Saved!\n");
LOG0("Setup Payload for Optional QR Code: %s\n\n",qrCode.get(atoi(setupCode),qrID,atoi(category)));
}
} }
break; break;
@ -1207,6 +1184,40 @@ const char* Span::statusString(HS_STATUS s){
/////////////////////////////// ///////////////////////////////
Span& Span::setPairingCode(const char *s){
char setupCode[10];
sscanf(s," %9[0-9]",setupCode);
if(strlen(setupCode)!=8){
LOG0("\n*** Invalid request to change Setup Code. Code must be exactly 8 digits.\n\n");
return(*this);
}
if(!network.allowedCode(setupCode)){
LOG0("\n*** Invalid request to change Setup Code. Code too simple.\n\n");
return(*this);
}
TempBuffer<Verification> verifyData; // temporary storage for verification data
SRP6A *srp=new SRP6A; // create instance of SRP
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
nvs_set_blob(HAPClient::srpNVS,"VERIFYDATA",&verifyData,sizeof(verifyData)); // update data
nvs_commit(HAPClient::srpNVS); // commit to NVS
LOG0("New Code Saved!\n");
LOG0("Setup Payload for Optional QR Code: %s\n\n",qrCode.get(atoi(setupCode),qrID,atoi(category)));
delete srp;
return(*this);
}
///////////////////////////////
Span& Span::setWifiCredentials(const char *ssid, const char *pwd){ Span& Span::setWifiCredentials(const char *ssid, const char *pwd){
sprintf(network.wifiData.ssid,"%.*s",MAX_SSID,ssid); sprintf(network.wifiData.ssid,"%.*s",MAX_SSID,ssid);
sprintf(network.wifiData.pwd,"%.*s",MAX_PWD,pwd); sprintf(network.wifiData.pwd,"%.*s",MAX_PWD,pwd);

View File

@ -364,7 +364,7 @@ class Span{
Span& setStatusCallback(void (*f)(HS_STATUS status)){statusCallback=f;return(*this);} // sets an optional user-defined function to call when HomeSpan status changes Span& setStatusCallback(void (*f)(HS_STATUS status)){statusCallback=f;return(*this);} // sets an optional user-defined function to call when HomeSpan status changes
const char* statusString(HS_STATUS s); // returns char string for HomeSpan status change messages const char* statusString(HS_STATUS s); // returns char string for HomeSpan status change messages
Span& setPairingCode(const char *s){sprintf(pairingCodeCommand,"S %9s",s);return(*this);} // sets the Pairing Code - use is NOT recommended. Use 'S' from CLI instead Span& setPairingCode(const char *s); // {sprintf(pairingCodeCommand,"S %9s",s);return(*this);} // sets the Pairing Code - use is NOT recommended. Use 'S' from CLI instead
void deleteStoredValues(){processSerialCommand("V");} // deletes stored Characteristic values from NVS void deleteStoredValues(){processSerialCommand("V");} // deletes stored Characteristic values from NVS
int enableOTA(boolean auth=true, boolean safeLoad=true){return(spanOTA.init(auth, safeLoad, NULL));} // enables Over-the-Air updates, with (auth=true) or without (auth=false) authorization password int enableOTA(boolean auth=true, boolean safeLoad=true){return(spanOTA.init(auth, safeLoad, NULL));} // enables Over-the-Air updates, with (auth=true) or without (auth=false) authorization password

View File

@ -39,19 +39,6 @@ SRP6A::SRP6A(){
uint8_t tBuf[768]; // temporary buffer for staging uint8_t tBuf[768]; // temporary buffer for staging
uint8_t tHash[64]; // temporary buffer for storing SHA-512 results uint8_t tHash[64]; // temporary buffer for storing SHA-512 results
char N3072[]="FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74"
"020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437"
"4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF05"
"98DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB"
"9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"
"E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718"
"3995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33"
"A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7"
"ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864"
"D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E2"
"08E24FA074E5AB3143DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF";
// initialize MPI structures // initialize MPI structures
mbedtls_mpi_init(&N); mbedtls_mpi_init(&N);
@ -85,21 +72,47 @@ SRP6A::SRP6A(){
mbedtls_mpi_write_binary(&g,tBuf+384,384); // write g into second half of staging buffer (fully padded with leading zeros) 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_sha512_ret(tBuf,768,tHash,0); // create hash of data
mbedtls_mpi_read_binary(&k,tHash,64); // load hash result into mpi structure k mbedtls_mpi_read_binary(&k,tHash,64); // load hash result into mpi structure k
}
//////////////////////////////////////
SRP6A::~SRP6A(){
mbedtls_mpi_free(&N);
mbedtls_mpi_free(&g);
mbedtls_mpi_free(&s);
mbedtls_mpi_free(&x);
mbedtls_mpi_free(&v);
mbedtls_mpi_free(&A);
mbedtls_mpi_free(&b);
mbedtls_mpi_free(&B);
mbedtls_mpi_free(&S);
mbedtls_mpi_free(&k);
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(&t1);
mbedtls_mpi_free(&t2);
mbedtls_mpi_free(&t3);
} }
////////////////////////////////////// //////////////////////////////////////
void SRP6A::createVerifyCode(const char *setupCode, uint8_t *verifyCode, uint8_t *salt){ void SRP6A::createVerifyCode(const char *setupCode, uint8_t *verifyCode, uint8_t *salt){
uint8_t tBuf[80]; // temporary buffer for staging TempBuffer<uint8_t> tBuf(80); // temporary buffer for staging
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[22]; // 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 using libsodium (which uses the ESP32 hardware-based random number generator)
mbedtls_mpi_read_binary(&s,salt,16); mbedtls_mpi_read_binary(&s,salt,16);
sprintf(icp,"Pair-Setup:%.3s-%.2s-%.3s",setupCode,setupCode+3,setupCode+5); asprintf(&icp,"Pair-Setup:%.3s-%.2s-%.3s",setupCode,setupCode+3,setupCode+5);
// compute x = SHA512( s | SHA512( I | ":" | P ) ) // compute x = SHA512( s | SHA512( I | ":" | P ) )
@ -112,7 +125,8 @@ void SRP6A::createVerifyCode(const char *setupCode, uint8_t *verifyCode, uint8_t
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,verifyCode,384); // write v into verifyCode mbedtls_mpi_write_binary(&v,verifyCode,384); // write v into verifyCode
free(icp);
} }
////////////////////////////////////// //////////////////////////////////////

View File

@ -31,7 +31,17 @@
#include <mbedtls/bignum.h> #include <mbedtls/bignum.h>
#include <mbedtls/base64.h> #include <mbedtls/base64.h>
#include "HAPConstants.h" #if defined(BOARD_HAS_PSRAM)
#define HS_MALLOC ps_malloc
#define HS_CALLOC ps_calloc
#define HS_REALLOC ps_realloc
#define ps_new(X) new(ps_malloc(sizeof(X)))X
#else
#define HS_MALLOC malloc
#define HS_CALLOC calloc
#define HS_REALLOC realloc
#define ps_new(X) new X
#endif
///////////////////////////////////////////////// /////////////////////////////////////////////////
// SRP-6A Structure from RFC 5054 (Nov 2007) // SRP-6A Structure from RFC 5054 (Nov 2007)
@ -41,6 +51,19 @@
// I = SRP-6A username, defined by HAP to be the word "Pair-Setup" // I = SRP-6A username, defined by HAP to be the word "Pair-Setup"
// P = SRP-6A password, defined to be equal to the accessory's 8-digit setup code in the format "XXX-XX-XXX" // P = SRP-6A password, defined to be equal to the accessory's 8-digit setup code in the format "XXX-XX-XXX"
const char N3072[]="FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74"
"020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437"
"4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF05"
"98DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB"
"9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"
"E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718"
"3995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33"
"A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7"
"ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864"
"D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E2"
"08E24FA074E5AB3143DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF";
struct SRP6A { struct SRP6A {
mbedtls_mpi N; // N - 3072-bit Group pre-defined prime used for all SRP-6A calculations (384 bytes) mbedtls_mpi N; // N - 3072-bit Group pre-defined prime used for all SRP-6A calculations (384 bytes)
@ -71,6 +94,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
~SRP6A();
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);

View File

@ -59,7 +59,7 @@ class TempBuffer {
public: public:
TempBuffer(size_t _nElements) : nElements(_nElements) { TempBuffer(size_t _nElements=1) : nElements(_nElements) {
buf=(bufType *)HS_MALLOC(nElements*sizeof(bufType)); buf=(bufType *)HS_MALLOC(nElements*sizeof(bufType));
if(buf==NULL){ if(buf==NULL){
Serial.printf("\n\n*** FATAL ERROR: Requested allocation of %d bytes failed. Program Halting.\n\n",nElements*sizeof(bufType)); Serial.printf("\n\n*** FATAL ERROR: Requested allocation of %d bytes failed. Program Halting.\n\n",nElements*sizeof(bufType));

View File

@ -33,7 +33,7 @@ void setup() {
Serial.begin(115200); Serial.begin(115200);
homeSpan.setLogLevel(2); homeSpan.setLogLevel(2); // .setPairingCode("33344456");
homeSpan.begin(Category::Lighting,"HomeSpan Max"); homeSpan.begin(Category::Lighting,"HomeSpan Max");