Starting re-factoring of postPairSetup

This commit is contained in:
Gregg 2023-12-23 21:21:34 -06:00
parent fe3389da3b
commit 66e7fc6654
2 changed files with 79 additions and 85 deletions

View File

@ -220,30 +220,11 @@ void HAPClient::processRequest(){
return; return;
} }
if(!strncmp(body,"POST /pair-setup ",17) && // POST PAIR-SETUP if(!strncmp(body,"POST /pair-setup ",17) && strstr(body,"Content-Type: application/pairing+tlv8")){ // POST PAIR-SETUP
strstr(body,"Content-Type: application/pairing+tlv8") && // check that content is TLV8 postPairSetupURL(content,cLen);
tlv8.unpack(content,cLen)){ // read TLV content
tlv8.print(2); // print TLV records in form "TAG(INT) LENGTH(INT) VALUES(HEX)"
LOG2("------------ END TLVS! ------------\n");
postPairSetupURL(); // process URL
return; return;
} }
// if(!strncmp(body,"POST /pair-verify ",18) && // POST PAIR-VERIFY
// strstr(body,"Content-Type: application/pairing+tlv8") && // check that content is TLV8
// tlv8.unpack(content,cLen)){ // read TLV content
// tlv8.print(2); // print TLV records in form "TAG(INT) LENGTH(INT) VALUES(HEX)"
// tlv8_new.unpack(content,cLen);
// tlv8_new.print();
// LOG2("------------ END TLVS! ------------\n");
//
// postPairVerifyURL(); // process URL
// tlv8_new.clear();
// return;
// }
if(!strncmp(body,"POST /pair-verify ",18) && strstr(body,"Content-Type: application/pairing+tlv8")){ // POST PAIR-VERIFY if(!strncmp(body,"POST /pair-verify ",18) && strstr(body,"Content-Type: application/pairing+tlv8")){ // POST PAIR-VERIFY
postPairVerifyURL(content,cLen); postPairVerifyURL(content,cLen);
return; return;
@ -385,101 +366,114 @@ int HAPClient::unauthorizedError(){
////////////////////////////////////// //////////////////////////////////////
int HAPClient::postPairSetupURL(){ int HAPClient::postPairSetupURL(uint8_t *content, size_t len){
LOG1("In Pair Setup..."); HAPTLV iosTLV;
HAPTLV responseTLV;
HAPTLV subTLV;
int tlvState=tlv8.val(kTLVType_State); iosTLV.unpack(content,len);
char buf[64]; iosTLV.print();
LOG2("------------ END TLVS! ------------\n");
if(tlvState==-1){ // missing STATE TLV LOG2("In Pair Setup #%d (%s)...",conNum,client.remoteIP().toString().c_str());
LOG0("\n*** ERROR: Missing <M#> State TLV\n\n");
auto itState=iosTLV.find(kTLVType_State);
if(itState==iosTLV.end() || (*itState).len!=1){ // missing STATE TLV
LOG0("\n*** ERROR: Missing or invalid <M#> State TLV\n\n");
badRequestError(); // return with 400 error, which closes connection badRequestError(); // return with 400 error, which closes connection
return(0); return(0);
} }
int tlvState=(*itState)[0];
if(nAdminControllers()){ // error: Device already paired (i.e. there is at least one admin Controller). We should not be receiving any requests for Pair-Setup! if(nAdminControllers()){ // error: Device already paired (i.e. there is at least one admin Controller). We should not be receiving any requests for Pair-Setup!
LOG0("\n*** ERROR: Device already paired!\n\n"); LOG0("\n*** ERROR: Device already paired!\n\n");
tlv8.clear(); // clear TLV records responseTLV.add(kTLVType_State,tlvState+1); // set response STATE to requested state+1 (which should match the state that was expected by the controller)
tlv8.val(kTLVType_State,tlvState+1); // set response STATE to requested state+1 (which should match the state that was expected by the controller) responseTLV.add(kTLVType_Error,tagError_Unavailable); // set Error=Unavailable
tlv8.val(kTLVType_Error,tagError_Unavailable); // set Error=Unavailable tlvRespond(responseTLV); // send response to client
tlvRespond(); // send response to client
return(0); return(0);
}; };
sprintf(buf,"Found <M%d>. Expected <M%d>\n",tlvState,pairStatus); LOG2("Found <M%d>. Expected <M%d>.\n",tlvState,pairStatus);
LOG2(buf);
if(tlvState!=pairStatus){ // error: Device is not yet paired, but out-of-sequence pair-setup STATE was received if(tlvState!=pairStatus){ // error: Device is not yet paired, but out-of-sequence pair-setup STATE was received
LOG0("\n*** ERROR: Out-of-Sequence Pair-Setup request!\n\n"); LOG0("\n*** ERROR: Out-of-Sequence Pair-Setup request!\n\n");
tlv8.clear(); // clear TLV records responseTLV.add(kTLVType_State,tlvState+1); // set response STATE to requested state+1 (which should match the state that was expected by the controller)
tlv8.val(kTLVType_State,tlvState+1); // set response STATE to requested state+1 (which should match the state that was expected by the controller) responseTLV.add(kTLVType_Error,tagError_Unknown); // set Error=Unknown (there is no specific error type for out-of-sequence steps)
tlv8.val(kTLVType_Error,tagError_Unknown); // set Error=Unknown (there is no specific error type for out-of-sequence steps) tlvRespond(responseTLV); // send response to client
tlvRespond(); // send response to client
pairStatus=pairState_M1; // reset pairStatus to first step of unpaired accessory (M1) pairStatus=pairState_M1; // reset pairStatus to first step of unpaired accessory (M1)
return(0); return(0);
}; };
switch(tlvState){ // valid and in-sequence Pair-Setup STATE received -- process request! (HAP Section 5.6) switch(tlvState){ // valid and in-sequence Pair-Setup STATE received -- process request! (HAP Section 5.6)
case pairState_M1: // 'SRP Start Request' case pairState_M1:{ // 'SRP Start Request'
if(tlv8.val(kTLVType_Method)!=0){ // error: "Pair Setup" method must always be 0 to indicate setup without MiFi Authentification (HAP Table 5-3) auto itMethod=iosTLV.find(kTLVType_Method);
LOG0("\n*** ERROR: Pair Method not set to 0\n\n");
tlv8.clear(); // clear TLV records if(itMethod==iosTLV.end() || (*itMethod).len!=1 || (*itMethod)[0]!=1){ // error: "Pair Setup" method must always be 0 to indicate setup without MiFi Authentification (HAP Table 5-3)
tlv8.val(kTLVType_State,pairState_M2); // set State=<M2> LOG0("\n*** ERROR: Pair 'Method' missing or not set to 0\n\n");
tlv8.val(kTLVType_Error,tagError_Unavailable); // set Error=Unavailable responseTLV.add(kTLVType_State,pairState_M2); // set State=<M2>
tlvRespond(); // send response to client responseTLV.add(kTLVType_Error,tagError_Unavailable); // set Error=Unavailable
tlvRespond(responseTLV); // send response to client
return(0); return(0);
}; };
tlv8.clear(); auto itPublicKey=responseTLV.add(kTLVType_PublicKey,384,NULL); // create blank PublicKey TLV with space for 384 bytes
tlv8.val(kTLVType_State,pairState_M2); // set State=<M2> auto itSalt=responseTLV.add(kTLVType_Salt,16,NULL); // create blank Salt TLV with space for 16 bytes
srp.createPublicKey(); // create accessory public key from random Pair-Setup code (displayed to user)
srp.loadTLV(kTLVType_PublicKey,&srp.B,384); // load server public key, B
srp.loadTLV(kTLVType_Salt,&srp.s,16); // load salt, s
tlvRespond(); // send response to client
responseTLV.add(kTLVType_State,pairState_M2); // set State=<M2>
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.s,*itSalt,(*itSalt).len); // load Salt, s, into TLV
// srp.loadTLV(*itPublicKey,&srp.B,384); // load server PublicKey, B
// srp.loadTLV(*itSalt,&srp.s,16); // load Salt, s
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);
}
break; break;
case pairState_M3: // 'SRP Verify Request' case pairState_M3:{ // 'SRP Verify Request'
if(!srp.writeTLV(kTLVType_PublicKey,&srp.A) || // try to write TLVs into mpi structures auto itPublicKey=iosTLV.find(kTLVType_PublicKey);
!srp.writeTLV(kTLVType_Proof,&srp.M1)){ auto itClientProof=iosTLV.find(kTLVType_Proof);
if(itPublicKey==iosTLV.end() || (*itPublicKey).len==0 || itClientProof==iosTLV.end() || (*itClientProof).len==0){
LOG0("\n*** ERROR: One or both of the required 'PublicKey' and 'Proof' TLV records for this step is bad or missing\n\n"); LOG0("\n*** ERROR: One or both of the required 'PublicKey' and 'Proof' TLV records for this step is bad or missing\n\n");
tlv8.clear(); // clear TLV records responseTLV.add(kTLVType_State,pairState_M4); // set State=<M4>
tlv8.val(kTLVType_State,pairState_M4); // set State=<M4> responseTLV.add(kTLVType_Error,tagError_Unknown); // set Error=Unknown (there is no specific error type for missing/bad TLV data)
tlv8.val(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(); // send response to client
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(); // create session key, K, from receipt of HAP Client public key, 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
if(!srp.verifyProof()){ // verify proof, M1, received from HAP Client srp.createSessionKey(); // create session key, K, from receipt of client Public Key, A
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");
tlv8.clear(); // clear TLV records responseTLV.add(kTLVType_State,pairState_M4); // set State=<M4>
tlv8.val(kTLVType_State,pairState_M4); // set State=<M4> responseTLV.add(kTLVType_Error,tagError_Authentication); // set Error=Authentication
tlv8.val(kTLVType_Error,tagError_Authentication); // set Error=Authentication tlvRespond(responseTLV); // send response to client
tlvRespond(); // send response to client
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.createProof(); // M1 has been successully verified; now create accessory proof M2 auto itAccProof=responseTLV.add(kTLVType_Proof,64,NULL); // create blank accessory Proof TLV with space for 64 bytes
tlv8.clear(); // clear TLV records
tlv8.val(kTLVType_State,pairState_M4); // set State=<M4>
srp.loadTLV(kTLVType_Proof,&srp.M2,64); // load M2 counter-proof
tlvRespond(); // send response to client
responseTLV.add(kTLVType_State,pairState_M4); // set State=<M4>
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
// srp.loadTLV(kTLVType_Proof,&srp.M2,64); // load accessory Proof, M2, into TLV
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'
@ -664,8 +658,8 @@ int HAPClient::postPairVerifyURL(uint8_t *content, size_t len){
auto itState=iosTLV.find(kTLVType_State); auto itState=iosTLV.find(kTLVType_State);
if(itState==iosTLV.end()){ // missing STATE TLV if(itState==iosTLV.end() || (*itState).len!=1){ // missing STATE TLV
LOG0("\n*** ERROR: Missing <M#> State TLV\n\n"); LOG0("\n*** ERROR: Missing or invalid <M#> State TLV\n\n");
badRequestError(); // return with 400 error, which closes connection badRequestError(); // return with 400 error, which closes connection
return(0); return(0);
} }

View File

@ -134,7 +134,7 @@ struct HAPClient {
// define member methods // define member methods
void processRequest(); // process HAP request void processRequest(); // process HAP request
int postPairSetupURL(); // POST /pair-setup (HAP Section 5.6) int postPairSetupURL(uint8_t *content, size_t len); // POST /pair-setup (HAP Section 5.6)
int postPairVerifyURL(uint8_t *content, size_t len); // POST /pair-verify (HAP Section 5.7) int postPairVerifyURL(uint8_t *content, size_t len); // POST /pair-verify (HAP Section 5.7)
int getAccessoriesURL(); // GET /accessories (HAP Section 6.6) int getAccessoriesURL(); // GET /accessories (HAP Section 6.6)
int postPairingsURL(); // POST /pairings (HAP Sections 5.10-5.12) int postPairingsURL(); // POST /pairings (HAP Sections 5.10-5.12)