From aa700f94f122d21a879493fa59256cfbaf7387cc Mon Sep 17 00:00:00 2001 From: Gregg Date: Fri, 22 Dec 2023 12:07:26 -0600 Subject: [PATCH] Added new TLV8 class To do: Refactor HAP.cpp to use new TLV8 class --- src/HAP.cpp | 1 + src/HAP.h | 16 +++++ src/TLV8.cpp | 194 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/TLV8.h | 113 ++++++++++++++++++++++++++++++ src/src.ino | 16 +---- 5 files changed, 327 insertions(+), 13 deletions(-) create mode 100644 src/TLV8.cpp create mode 100644 src/TLV8.h diff --git a/src/HAP.cpp b/src/HAP.cpp index 7391aa2..b922e0f 100644 --- a/src/HAP.cpp +++ b/src/HAP.cpp @@ -1744,6 +1744,7 @@ void Nonce::inc(){ // instantiate all static HAP Client structures and data TLV HAPClient::tlv8; +TLV8 HAPClient::tlv8_new{tlvNames}; nvs_handle HAPClient::hapNVS; nvs_handle HAPClient::srpNVS; HKDF HAPClient::hkdf; diff --git a/src/HAP.h b/src/HAP.h index a7c9a1a..b5d79e0 100644 --- a/src/HAP.h +++ b/src/HAP.h @@ -34,6 +34,21 @@ #include "HAPConstants.h" #include "HKDF.h" #include "SRP.h" +#include "TLV8.h" + +const TLV8_names tlvNames[] = { + {kTLVType_Separator,"SEPARATOR"}, + {kTLVType_State,"STATE"}, + {kTLVType_PublicKey,"PUBKEY"}, + {kTLVType_Method,"METHOD"}, + {kTLVType_Salt,"SALT"}, + {kTLVType_Error,"ERROR"}, + {kTLVType_Proof,"PROOF"}, + {kTLVType_EncryptedData,"ENC.DATA"}, + {kTLVType_Signature,"SIGNATURE"}, + {kTLVType_Identifier,"IDENTIFIER"}, + {kTLVType_Permissions,"PERMISSION"} +}; ///////////////////////////////////////////////// // NONCE Structure (HAP used last 64 of 96 bits) @@ -88,6 +103,7 @@ struct HAPClient { 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 diff --git a/src/TLV8.cpp b/src/TLV8.cpp new file mode 100644 index 0000000..421aa0d --- /dev/null +++ b/src/TLV8.cpp @@ -0,0 +1,194 @@ +/********************************************************************************* + * MIT License + * + * Copyright (c) 2020-2023 Gregg E. Berman + * + * https://github.com/HomeSpan/HomeSpan + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + ********************************************************************************/ + +#include "TLV8.h" + +///////////////////////////////////// + +void TLV8::add(uint8_t tag, size_t len, const uint8_t* val){ + + if(!empty() && back().tag==tag) + back().update(len,val); + else + emplace_back(tag,len,val); +} + +///////////////////////////////////// + +TLV8_it TLV8::find(uint8_t tag, TLV8_it it1, TLV8_it it2){ + + auto it=it1; + while(it!=it2 && (*it).tag!=tag) + it++; + return(it); +} + +///////////////////////////////////// + +size_t TLV8::pack_size(TLV8_it it1, TLV8_it it2){ + + size_t nBytes=0; + + while(it1!=it2){ + nBytes+=2+(*it1).len; + if((*it1).len>255) + nBytes+=2*(((*it1).len-1)/255); + it1++; + } + + return(nBytes); +} + +///////////////////////////////////// + +size_t TLV8::pack(uint8_t *buf, size_t bufSize){ + + size_t nBytes=0; + + while(nBytes255) + currentPackLen=255; + *buf++=currentPackLen; + nBytes++; + currentPackPhase=3; + break; + + case 3: + if(currentPackLen==0){ + if(endPackBuf==currentPackBuf){ + currentPackIt++; + currentPackPhase=0; + } else { + currentPackPhase=1; + } + break; + } + + size_t copyBytes=(currentPackLen<(bufSize-nBytes)) ? currentPackLen : (bufSize-nBytes); + memcpy(buf,currentPackBuf,copyBytes); + buf+=copyBytes; + currentPackBuf+=copyBytes; + currentPackLen-=copyBytes; + nBytes+=copyBytes; + break; + } + } + + return(nBytes); +} + +///////////////////////////////////// + +void TLV8::unpack(uint8_t *buf, size_t bufSize){ + + if(empty()) + unpackPhase=0; + + while(bufSize>0){ + switch(unpackPhase){ + + case 0: + unpackTag=*buf++; + bufSize--; + unpackPhase=1; + break; + + case 1: + unpackBytes=*buf++; + bufSize--; + if(unpackBytes==0){ + add(unpackTag); + unpackPhase=0; + } else { + unpackPhase=2; + } + break; + + case 2: + size_t copyBytes=unpackBytes val; + + tlv8_t(uint8_t tag, size_t len, const uint8_t* val) : tag{tag}, len{len} { + if(len>0){ + this->val=std::unique_ptr((uint8_t *)HS_MALLOC(len)); + if(val!=NULL) + memcpy((this->val).get(),val,len); + } + } + + void update(size_t addLen, const uint8_t *addVal){ + if(addLen>0){ + uint8_t *p=val.release(); + p=(uint8_t *)HS_REALLOC(p,len+addLen); + val=std::unique_ptr(p); + if(addVal!=NULL) + memcpy(p+len,addVal,addLen); + len+=addLen; + } + } + +}; + +///////////////////////////////////// + +typedef vector>::iterator TLV8_it; +typedef struct { const uint8_t tag; const char *name; } TLV8_names; + +///////////////////////////////////// + +class TLV8 : public vector> { + + TLV8_it currentPackIt; + TLV8_it endPackIt; + uint8_t *currentPackBuf; + uint8_t *endPackBuf; + int currentPackPhase; + size_t currentPackLen; + + uint8_t unpackTag; + size_t unpackBytes; + int unpackPhase; + + const TLV8_names *names; + + public: + + TLV8(const TLV8_names *names=NULL) : names{names}{}; + + void add(uint8_t tag, size_t len, const uint8_t *val); + void add(uint8_t tag, uint8_t val){add(tag, 1, &val);} + void add(uint8_t tag){add(tag, 0, NULL);} + + TLV8_it find(uint8_t tag, TLV8_it it1, TLV8_it it2); + TLV8_it find(uint8_t tag, TLV8_it it1){return(find(tag, it1, end()));} + TLV8_it find(uint8_t tag){return(find(tag, begin(), end()));} + + size_t pack_size(TLV8_it it1, TLV8_it it2); + size_t pack_size(TLV8_it it1){return(pack_size(it1, it1+1));} + size_t pack_size(){return(pack_size(begin(), end()));} + + void pack_init(TLV8_it it1, TLV8_it it2){currentPackIt=it1; endPackIt=it2; currentPackPhase=0;} + void pack_init(TLV8_it it1){pack_init(it1, it1+1);} + void pack_init(){pack_init(begin(),end());} + + size_t pack(uint8_t *buf, size_t bufSize); + size_t pack(uint8_t *buf){pack_init(); return(pack(buf,pack_size()));} + + const char *getName(uint8_t tag); + + void print(TLV8_it it1, TLV8_it it2); + void print(TLV8_it it1){print(it1, it1+1);} + void print(){print(begin(), end());} + + void unpack(uint8_t *buf, size_t bufSize); + + void wipe(){vector>().swap(*this);} + +}; diff --git a/src/src.ino b/src/src.ino index 03adb89..090e7c4 100644 --- a/src/src.ino +++ b/src/src.ino @@ -25,16 +25,15 @@ * ********************************************************************************/ - #include "HomeSpan.h" +#define MAX_LIGHTS 1 + void setup() { Serial.begin(115200); homeSpan.setLogLevel(2); -// homeSpan.enableWebLog(500,"pool.ntp.org","UTC"); -// homeSpan.setWifiCallback(wifiEstablished); homeSpan.begin(Category::Lighting,"HomeSpan Max"); @@ -42,7 +41,7 @@ void setup() { new Service::AccessoryInformation(); new Characteristic::Identify(); - for(int i=0;i<10;i++){ + for(int i=0;i