Added new TLV8 class

To do: Refactor HAP.cpp to use new TLV8 class
This commit is contained in:
Gregg 2023-12-22 12:07:26 -06:00
parent e715d670e3
commit aa700f94f1
5 changed files with 327 additions and 13 deletions

View File

@ -1744,6 +1744,7 @@ void Nonce::inc(){
// instantiate all static HAP Client structures and data
TLV<kTLVType,11> HAPClient::tlv8;
TLV8 HAPClient::tlv8_new{tlvNames};
nvs_handle HAPClient::hapNVS;
nvs_handle HAPClient::srpNVS;
HKDF HAPClient::hkdf;

View File

@ -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<kTLVType,11> 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

194
src/TLV8.cpp Normal file
View File

@ -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(nBytes<bufSize && currentPackIt!=endPackIt){
switch(currentPackPhase){
case 0:
currentPackBuf=(*currentPackIt).val.get();
endPackBuf=(*currentPackIt).val.get()+(*currentPackIt).len;
currentPackPhase=1;
break;
case 1:
*buf++=(*currentPackIt).tag;
nBytes++;
currentPackPhase=2;
break;
case 2:
currentPackLen=endPackBuf-currentPackBuf;
if(currentPackLen>255)
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<bufSize ? unpackBytes : bufSize;
add(unpackTag,copyBytes,buf);
buf+=copyBytes;
unpackBytes-=copyBytes;
bufSize-=copyBytes;
if(unpackBytes==0)
unpackPhase=0;
break;
}
}
}
/////////////////////////////////////
const char *TLV8::getName(uint8_t tag){
if(names==NULL)
return(NULL);
for(int i=0;i<sizeof(names);i++){
if(names[i].tag==tag)
return(names[i].name);
}
return(NULL);
}
/////////////////////////////////////
void TLV8::print(TLV8_it it1, TLV8_it it2){
while(it1!=it2){
const char *name=getName((*it1).tag);
if(name)
Serial.printf("%s",name);
else
Serial.printf("%d",(*it1).tag);
Serial.printf("(%d) ",(*it1).len);
for(int i=0;i<(*it1).len;i++)
Serial.printf("%02X",(*it1).val.get()[i]);
Serial.printf("\n");
it1++;
}
}
/////////////////////////////////////

113
src/TLV8.h Normal file
View File

@ -0,0 +1,113 @@
/*********************************************************************************
* 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.
*
********************************************************************************/
#pragma once
#include "HomeSpan.h"
struct tlv8_t {
uint8_t tag;
size_t len;
std::unique_ptr<uint8_t> 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>((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<uint8_t>(p);
if(addVal!=NULL)
memcpy(p+len,addVal,addLen);
len+=addLen;
}
}
};
/////////////////////////////////////
typedef vector<tlv8_t, Mallocator<tlv8_t>>::iterator TLV8_it;
typedef struct { const uint8_t tag; const char *name; } TLV8_names;
/////////////////////////////////////
class TLV8 : public vector<tlv8_t, Mallocator<tlv8_t>> {
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<tlv8_t, Mallocator<tlv8_t>>().swap(*this);}
};

View File

@ -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<MAX_LIGHTS;i++){
new SpanAccessory();
new Service::AccessoryInformation();
new Characteristic::Identify();
@ -67,12 +66,3 @@ void loop(){
}
//////////////////////////////////////
void wifiEstablished(){
for(int i=0;i<600;i++){
WEBLOG("Here is a lot of log file text that should take up a lot of space: %d",i);
delay(30);
}
}