Added SHA-384 hash computation to HapOut

Hashing of entire database is now done piecemeal within HapOut, preventing the need to load the entire database into a large buffer just to obtain a unique hash.

Modified updateDatabase() to use HapOut.getHash()
This commit is contained in:
Gregg 2023-12-31 09:36:19 -06:00
parent f2cb880e4e
commit 1f13906a25
4 changed files with 29 additions and 36 deletions

View File

@ -913,24 +913,6 @@ int HAPClient::getAccessoriesURL(){
LOG2("\n-------- SENT ENCRYPTED! --------\n"); LOG2("\n-------- SENT ENCRYPTED! --------\n");
// int nBytes = homeSpan.sprintfAttributes(NULL); // get size of HAP attributes JSON
// TempBuffer<char> jBuf(nBytes+1);
// homeSpan.sprintfAttributes(jBuf); // create JSON database (will need to re-cast to uint8_t* below)
// char *body;
// asprintf(&body,"HTTP/1.1 200 OK\r\nContent-Type: application/hap+json\r\nContent-Length: %d\r\n\r\n",nBytes);
// LOG2("\n>>>>>>>>>> ");
// LOG2(client.remoteIP());
// LOG2(" >>>>>>>>>>\n");
// LOG2(body);
// LOG2(jBuf.get());
// LOG2("\n");
// sendEncrypted(body,(uint8_t *)jBuf.get(),nBytes);
// free(body);
return(1); return(1);
} // getAccessories } // getAccessories
@ -1650,6 +1632,12 @@ HapOut::HapStreamBuffer::HapStreamBuffer(){
buffer=(char *)HS_MALLOC(bufSize+1); // add 1 for adding null terminator when printing text buffer=(char *)HS_MALLOC(bufSize+1); // add 1 for adding null terminator when printing text
encBuf=(uint8_t *)HS_MALLOC(bufSize+18); // 2-byte AAD + encrypted data + 16-byte authentication tag encBuf=(uint8_t *)HS_MALLOC(bufSize+18); // 2-byte AAD + encrypted data + 16-byte authentication tag
hash=(uint8_t *)HS_MALLOC(48); // space for SHA-384 hash output
ctx = (mbedtls_sha512_context *)HS_MALLOC(sizeof(mbedtls_sha512_context)); // space for hash context
mbedtls_sha512_init(ctx); // initialize context
mbedtls_sha512_starts_ret(ctx,1); // start SHA-384 hash (note second argument=1)
setp(buffer, buffer+bufSize-1); setp(buffer, buffer+bufSize-1);
} }
@ -1670,7 +1658,7 @@ void HapOut::HapStreamBuffer::flushBuffer(){
byteCount+=num; byteCount+=num;
if(logLevel<=homeSpan.getLogLevel()){ if(logLevel<=homeSpan.getLogLevel()){
buffer[num]='\0'; buffer[num]='\0'; // add null terminator but DO NOT increment num (we don't want terminator considered as part of buffer)
Serial.print(buffer); Serial.print(buffer);
} }
@ -1687,11 +1675,12 @@ void HapOut::HapStreamBuffer::flushBuffer(){
hapClient->client.write(encBuf,num+18); // transmit encrypted frame hapClient->client.write(encBuf,num+18); // transmit encrypted frame
hapClient->a2cNonce.inc(); // increment nonce hapClient->a2cNonce.inc(); // increment nonce
} }
delay(1); delay(1);
} }
pbump(-num); mbedtls_sha512_update_ret(ctx,(uint8_t *)buffer,num); // update hash
pbump(-num); // reset buffer pointers
} }
////////////////////////////////////// //////////////////////////////////////
@ -1718,6 +1707,9 @@ int HapOut::HapStreamBuffer::sync(){
enablePrettyPrint=false; enablePrettyPrint=false;
byteCount=0; byteCount=0;
mbedtls_sha512_finish_ret(ctx,hash); // finish SHA-384 and store hash
mbedtls_sha512_starts_ret(ctx,1); // re-start hash for next time
return(0); return(0);
} }

View File

@ -195,6 +195,8 @@ class HapOut : public std::ostream {
int logLevel=255; // default is NOT to print anything int logLevel=255; // default is NOT to print anything
boolean enablePrettyPrint=false; boolean enablePrettyPrint=false;
size_t byteCount=0; size_t byteCount=0;
uint8_t *hash;
mbedtls_sha512_context *ctx;
void flushBuffer(); void flushBuffer();
int_type overflow(int_type c) override; int_type overflow(int_type c) override;
@ -215,6 +217,7 @@ class HapOut : public std::ostream {
HapOut& setLogLevel(int logLevel){hapBuffer.logLevel=logLevel;return(*this);} HapOut& setLogLevel(int logLevel){hapBuffer.logLevel=logLevel;return(*this);}
HapOut& prettyPrint(){hapBuffer.enablePrettyPrint=true;hapBuffer.logLevel=0;return(*this);} HapOut& prettyPrint(){hapBuffer.enablePrettyPrint=true;hapBuffer.logLevel=0;return(*this);}
uint8_t *getHash(){return(hapBuffer.hash);}
size_t getSize(){return(hapBuffer.getSize());} size_t getSize(){return(hapBuffer.getSize());}
}; };

View File

@ -1619,15 +1619,13 @@ int Span::sprintfAttributes(char **ids, int numIDs, int flags, char *cBuf){
boolean Span::updateDatabase(boolean updateMDNS){ boolean Span::updateDatabase(boolean updateMDNS){
uint8_t tHash[48]; printfAttributes(GET_META|GET_PERMS|GET_TYPE|GET_DESC); // stream attributes database, which automtically produces a SHA-384 hash
TempBuffer<char> tBuf(sprintfAttributes(NULL,GET_META|GET_PERMS|GET_TYPE|GET_DESC)+1); hapOut.flush();
sprintfAttributes(tBuf,GET_META|GET_PERMS|GET_TYPE|GET_DESC);
mbedtls_sha512_ret((uint8_t *)tBuf.get(),tBuf.len(),tHash,1); // create SHA-384 hash of JSON (can be any hash - just looking for a unique key)
boolean changed=false; boolean changed=false;
if(memcmp(tHash,hapConfig.hashCode,48)){ // if hash code of current HAP database does not match stored hash code if(memcmp(hapOut.getHash(),hapConfig.hashCode,48)){ // if hash code of current HAP database does not match stored hash code
memcpy(hapConfig.hashCode,tHash,48); // update stored hash code memcpy(hapConfig.hashCode,hapOut.getHash(),48); // update stored hash code
hapConfig.configNumber++; // increment configuration number hapConfig.configNumber++; // increment configuration number
if(hapConfig.configNumber==65536) // reached max value if(hapConfig.configNumber==65536) // reached max value
hapConfig.configNumber=1; // reset to 1 hapConfig.configNumber=1; // reset to 1

View File

@ -27,13 +27,13 @@
#include "HomeSpan.h" #include "HomeSpan.h"
#define MAX_LIGHTS 3 #define MAX_LIGHTS 4
void setup() { void setup() {
Serial.begin(115200); Serial.begin(115200);
homeSpan.setLogLevel(2); homeSpan.setLogLevel(0);
homeSpan.enableWebLog(200); homeSpan.enableWebLog(200);
homeSpan.begin(Category::Lighting,"HomeSpan Max"); homeSpan.begin(Category::Lighting,"HomeSpan Max");