From fe3389da3b051cba6de13fa8638800b00b8e68e2 Mon Sep 17 00:00:00 2001 From: Gregg Date: Sat, 23 Dec 2023 15:59:04 -0600 Subject: [PATCH] Preparing for re-factoring postPairSetup --- src/HAP.cpp | 71 ++++++++++++++++++++++------------------------------- src/HAP.h | 27 ++++++++++---------- 2 files changed, 43 insertions(+), 55 deletions(-) diff --git a/src/HAP.cpp b/src/HAP.cpp index 2964eca..41976af 100644 --- a/src/HAP.cpp +++ b/src/HAP.cpp @@ -224,12 +224,9 @@ void HAPClient::processRequest(){ 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"); postPairSetupURL(); // process URL - tlv8_new.clear(); return; } @@ -256,12 +253,9 @@ void HAPClient::processRequest(){ 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"); postPairingsURL(); // process URL - tlv8_new.clear(); return; } @@ -670,7 +664,7 @@ int HAPClient::postPairVerifyURL(uint8_t *content, size_t len){ auto itState=iosTLV.find(kTLVType_State); - if(itState==iosTLV.end()){ // missing STATE TLV + if(itState==iosTLV.end()){ // missing STATE TLV LOG0("\n*** ERROR: Missing State TLV\n\n"); badRequestError(); // return with 400 error, which closes connection return(0); @@ -680,9 +674,9 @@ int HAPClient::postPairVerifyURL(uint8_t *content, size_t len){ if(!nAdminControllers()){ // error: Device not yet paired - we should not be receiving any requests for Pair-Verify! LOG0("\n*** ERROR: Device not yet paired!\n\n"); - responseTLV.add(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 - tlvRespond(responseTLV); // send response to client + responseTLV.add(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 + tlvRespond(responseTLV); // send response to client return(0); }; @@ -690,7 +684,7 @@ int HAPClient::postPairVerifyURL(uint8_t *content, size_t len){ switch(tlvState){ // Pair-Verify STATE received -- process request! (HAP Section 5.7) - case pairState_M1:{ // 'Verify Start Request' + case pairState_M1:{ // 'Verify Start Request' auto itPublicKey=iosTLV.find(kTLVType_PublicKey); @@ -698,15 +692,14 @@ int HAPClient::postPairVerifyURL(uint8_t *content, size_t len){ LOG0("\n*** ERROR: Required 'PublicKey' TLV record for this step is bad or missing\n\n"); responseTLV.add(kTLVType_State,pairState_M2); // set State= 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 return(0); } - uint8_t secretCurveKey[32]; // Accessory's secret key for Curve25519 encryption (32 bytes). Ephemeral usage - created below and used only in this block + uint8_t secretCurveKey[32]; // Accessory's secret key for Curve25519 encryption (32 bytes). Ephemeral usage - created below and used only in this block + crypto_box_keypair(publicCurveKey,secretCurveKey); // generate Curve25519 public key pair (will persist until end of verification process) - crypto_box_keypair(publicCurveKey,secretCurveKey); // generate Curve25519 public key pair (will persist until end of verification process) - - memcpy(iosCurveKey,*itPublicKey,32); // save iosCurveKey (will persist until end of verification process) + memcpy(iosCurveKey,*itPublicKey,32); // save iosCurveKey (will persist until end of verification process) crypto_scalarmult_curve25519(sharedCurveKey,secretCurveKey,iosCurveKey); // generate (and persist) Pair Verify SharedSecret CurveKey from Accessory's Curve25519 secret key and Controller's Curve25519 public key (32 bytes) @@ -716,11 +709,11 @@ int HAPClient::postPairVerifyURL(uint8_t *content, size_t len){ memcpy(accessoryInfo+32,accessory.ID,17); // +accessoryPairingID memcpy(accessoryInfo+49,iosCurveKey,32); // +Controller's Curve25519 public key - auto itSignature=subTLV.add(kTLVType_Signature,64,NULL); //create blank Signature TLV with space for 64 bytes + auto itSignature=subTLV.add(kTLVType_Signature,64,NULL); //create blank Signature TLV with space for 64 bytes 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,17,accessory.ID); // set Identifier TLV record as accessoryPairingID + subTLV.add(kTLVType_Identifier,17,accessory.ID); // set Identifier TLV record as accessoryPairingID LOG2("------- ENCRYPTING SUB-TLVS -------\n"); @@ -731,9 +724,9 @@ int HAPClient::postPairVerifyURL(uint8_t *content, size_t len){ // create SessionKey from Curve25519 SharedSecret using HKDF-SHA-512, then encrypt subTLV data with SessionKey using ChaCha20-Poly1305. Output stored in EncryptedData TLV - hkdf.create(sessionKey,sharedCurveKey,32,"Pair-Verify-Encrypt-Salt","Pair-Verify-Encrypt-Info"); // create SessionKey (32 bytes) + hkdf.create(sessionKey,sharedCurveKey,32,"Pair-Verify-Encrypt-Salt","Pair-Verify-Encrypt-Info"); // create SessionKey (32 bytes) - auto itEncryptedData=responseTLV.add(kTLVType_EncryptedData,subPack.len()+crypto_aead_chacha20poly1305_IETF_ABYTES,NULL); //create blank EncryptedData TLV with space for subTLV + Authentication Tag + auto 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\x00PV-Msg02",sessionKey); @@ -742,7 +735,7 @@ int HAPClient::postPairVerifyURL(uint8_t *content, size_t len){ responseTLV.add(kTLVType_State,pairState_M2); // set State= responseTLV.add(kTLVType_PublicKey,32,publicCurveKey); // set PublicKey to Accessory's Curve25519 public key - tlvRespond(responseTLV); // send response to client + tlvRespond(responseTLV); // send response to client } break; @@ -752,9 +745,9 @@ int HAPClient::postPairVerifyURL(uint8_t *content, size_t len){ if(itEncryptedData==iosTLV.end() || (*itEncryptedData).len==0){ LOG0("\n*** ERROR: Required 'EncryptedData' TLV record for this step is bad or missing\n\n"); - responseTLV.add(kTLVType_State,pairState_M4); // set State= + responseTLV.add(kTLVType_State,pairState_M4); // set State= 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 return(0); }; @@ -768,9 +761,9 @@ int HAPClient::postPairVerifyURL(uint8_t *content, size_t len){ (unsigned char *)"\x00\x00\x00\x00PV-Msg03", sessionKey)==-1){ LOG0("\n*** ERROR: Verify Authentication Failed\n\n"); - responseTLV.add(kTLVType_State,pairState_M4); // set State= + responseTLV.add(kTLVType_State,pairState_M4); // set State= responseTLV.add(kTLVType_Error,tagError_Authentication); // set Error=Authentication - tlvRespond(responseTLV); // send response to client + tlvRespond(responseTLV); // send response to client return(0); } @@ -785,21 +778,21 @@ int HAPClient::postPairVerifyURL(uint8_t *content, size_t len){ if(itIdentifier==subTLV.end() || (*itIdentifier).len!=36 || itSignature==subTLV.end() || (*itSignature).len!=crypto_sign_BYTES){ LOG0("\n*** ERROR: One or more of required 'Identifier,' and 'Signature' TLV records for this step is bad or missing\n\n"); - responseTLV.add(kTLVType_State,pairState_M4); // set State= + responseTLV.add(kTLVType_State,pairState_M4); // set State= 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 return(0); } - Controller *tPair; // temporary pointer to Controller + Controller *tPair; // temporary pointer to Controller if(!(tPair=findController((*itIdentifier).val.get()))){ LOG0("\n*** ERROR: Unrecognized Controller ID: "); charPrintRow((*itIdentifier).val.get(),36,2); LOG0("\n\n"); - responseTLV.add(kTLVType_State,pairState_M4); // set State= + responseTLV.add(kTLVType_State,pairState_M4); // set State= responseTLV.add(kTLVType_Error,tagError_Authentication); // set Error=Authentication - tlvRespond(responseTLV); // send response to client + tlvRespond(responseTLV); // send response to client return(0); } @@ -815,14 +808,14 @@ int HAPClient::postPairVerifyURL(uint8_t *content, size_t len){ if(crypto_sign_verify_detached((*itSignature).val.get(), iosDeviceInfo, iosDeviceInfo.len(), tPair->LTPK) != 0){ // verify signature of iosDeviceInfo using iosDeviceLTPK LOG0("\n*** ERROR: LPTK Signature Verification Failed\n\n"); - responseTLV.add(kTLVType_State,pairState_M4); // set State= + responseTLV.add(kTLVType_State,pairState_M4); // set State= responseTLV.add(kTLVType_Error,tagError_Authentication); // set Error=Authentication - tlvRespond(responseTLV); // send response to client + tlvRespond(responseTLV); // send response to client return(0); } - responseTLV.add(kTLVType_State,pairState_M4); // set State= - tlvRespond(responseTLV); // send response to client (unencrypted since cPair=NULL) + responseTLV.add(kTLVType_State,pairState_M4); // set State= + tlvRespond(responseTLV); // send response to client (unencrypted since cPair=NULL) cPair=tPair; // save Controller for this connection slot - connection is now verified and should be encrypted going forward @@ -1426,11 +1419,8 @@ void HAPClient::tlvRespond(TLV8 &tlv8){ void HAPClient::tlvRespond(){ -// TempBuffer tBuf(tlv8.pack(NULL)); // create buffer to hold TLV data -// tlv8.pack(tBuf); // pack TLV records into buffer - - TempBuffer tBuf(tlv8_new.pack_size()); // create buffer to hold TLV data - tlv8_new.pack(tBuf); // pack TLV records into buffer + TempBuffer tBuf(tlv8.pack(NULL)); // create buffer to hold TLV data + tlv8.pack(tBuf); // pack TLV records into buffer char *body; asprintf(&body,"HTTP/1.1 200 OK\r\nContent-Type: application/pairing+tlv8\r\nContent-Length: %d\r\n\r\n",tBuf.len()); // create Body with Content Length = size of TLV data @@ -1439,7 +1429,7 @@ void HAPClient::tlvRespond(){ LOG2(client.remoteIP()); LOG2(" >>>>>>>>>>\n"); LOG2(body); - tlv8_new.print(); + tlv8.print(2); if(!cPair){ // unverified, unencrypted session client.print(body); @@ -1772,7 +1762,6 @@ void Nonce::inc(){ // instantiate all static HAP Client structures and data TLV HAPClient::tlv8; -TLV8 HAPClient::tlv8_new{tlvNames,11}; nvs_handle HAPClient::hapNVS; nvs_handle HAPClient::srpNVS; HKDF HAPClient::hkdf; diff --git a/src/HAP.h b/src/HAP.h index 40c13f8..86b6990 100644 --- a/src/HAP.h +++ b/src/HAP.h @@ -36,7 +36,7 @@ #include "SRP.h" #include "TLV8.h" -const TLV8_names tlvNames[] = { +const TLV8_names HAP_Names[] = { {kTLVType_Separator,"*SEPARATOR"}, {kTLVType_State,"*STATE"}, {kTLVType_PublicKey,"*PUBKEY"}, @@ -102,16 +102,15 @@ struct HAPClient { static const int MAX_CONTROLLERS=16; // maximum number of paired controllers (HAP requires at least 16) static const int MAX_ACCESSORIES=150; // maximum number of allowed Accessories (HAP limit=150) - static TLV tlv8; // TLV8 structure (HAP Section 14.1) with space for 11 TLV records of type kTLVType (HAP Table 5-6) - static TLV8 tlv8_new; // TLV8 structure (HAP Section 14.1) with space for 11 TLV records of type kTLVType (HAP Table 5-6) - static nvs_handle hapNVS; // handle for non-volatile-storage of HAP 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 pairState pairStatus; // tracks pair-setup status - static SRP6A srp; // stores all SRP-6A keys used for Pair-Setup - static Accessory accessory; // Accessory ID and Ed25519 public and secret keys- permanently stored - static list> 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 TLV tlv8; // TLV8 structure (HAP Section 14.1) with space for 11 TLV records of type kTLVType (HAP Table 5-6) + static nvs_handle hapNVS; // handle for non-volatile-storage of HAP 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 pairState pairStatus; // tracks pair-setup status + static SRP6A srp; // stores all SRP-6A keys used for Pair-Setup + static Accessory accessory; // Accessory ID and Ed25519 public and secret keys- permanently stored + static list> 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 // individual structures and data defined for each Hap Client connection @@ -155,7 +154,7 @@ struct HAPClient { // define static methods - static void init(); // initialize HAP after start-up + static void init(); // initialize HAP after start-up static void hexPrintColumn(uint8_t *buf, int n, int minLogLevel=0); // prints 'n' bytes of *buf as HEX, one byte per row, subject to specified minimum log level static void hexPrintRow(uint8_t *buf, int n, int minLogLevel=0); // prints 'n' bytes of *buf as HEX, all on one row, subject to specified minimum log level @@ -173,9 +172,9 @@ struct HAPClient { static void checkTimedWrites(); // checks for expired Timed Write PIDs, and clears any found (HAP Section 6.7.2.4) static void eventNotify(SpanBuf *pObj, int nObj, int ignoreClient=-1); // transmits EVENT Notifications for nObj SpanBuf objects, pObj, with optional flag to ignore a specific client - class HAPTLV : public TLV8 { + class HAPTLV : public TLV8 { // dedicated class for HAP TLV8 records public: - HAPTLV() : TLV8(tlvNames,11){} + HAPTLV() : TLV8(HAP_Names,11){} }; };