Update HAPClient::sendEncrypted() to send individual frames to save memory

Rather than use a large temporary buffer to store all encrypted frames to transmit all at once, each encrypted frame is transmitted as soon as created, which means the temporary buffer only needs to be large enough to store a single encrypted frame.

For a device with a large number of Accessories, this can save 15-20 KB of temporary storage, allowing for more Accessories.

Note this change does not reduce the size of the unencrypted message that is initially produced and can also be quite large.  Potential for future project.
This commit is contained in:
Gregg 2023-11-11 10:26:25 -06:00
parent c1834fb301
commit ae60a84855
1 changed files with 14 additions and 20 deletions

View File

@ -1463,25 +1463,21 @@ void HAPClient::sendEncrypted(char *body, uint8_t *dataBuf, int dataLen){
int bodyLen=strlen(body); int bodyLen=strlen(body);
int count=0;
unsigned long long nBytes; unsigned long long nBytes;
int totalBytes=2+bodyLen+16; // 2-byte AAD + bodyLen + 16-byte authentication tag int maxFrameSize=bodyLen>dataLen?bodyLen:dataLen; // set maxFrameSize to greater of bodyLen or dataLen
totalBytes+=(dataLen/FRAME_SIZE)*(2+FRAME_SIZE+16); // number of full frames * size of full frame with 2-byte AAD + 16-byte authentication tag if(maxFrameSize>FRAME_SIZE) // cap maxFrameSize by FRAME_SIZE (HAP restriction)
maxFrameSize=FRAME_SIZE;
if(dataLen%FRAME_SIZE) // if there is a residual last partial frame TempBuffer <uint8_t> tBuf(2+maxFrameSize+16); // 2-byte AAD + encrytped data + 16-byte authentication tag
totalBytes+=2+dataLen%FRAME_SIZE+16; // 2-byte AAD + residual of last partial frame + 16-byte authentication tag
TempBuffer <uint8_t> tBuf(totalBytes); tBuf.get()[0]=bodyLen%256; // store number of bytes in first frame that encrypts the Body (AAD bytes)
tBuf.get()[1]=bodyLen/256;
tBuf.get()[count]=bodyLen%256; // store number of bytes in first frame that encrypts the Body (AAD bytes) crypto_aead_chacha20poly1305_ietf_encrypt(tBuf.get()+2,&nBytes,(uint8_t *)body,bodyLen,tBuf.get(),2,NULL,a2cNonce.get(),a2cKey); // encrypt the Body with authentication tag appended
tBuf.get()[count+1]=bodyLen/256;
crypto_aead_chacha20poly1305_ietf_encrypt(tBuf.get()+count+2,&nBytes,(uint8_t *)body,bodyLen,tBuf.get()+count,2,NULL,a2cNonce.get(),a2cKey); // encrypt the Body with authentication tag appended client.write(tBuf.get(),nBytes+2); // transmit encrypted frame
a2cNonce.inc(); // increment nonce
a2cNonce.inc(); // increment nonce
count+=2+bodyLen+16; // increment count by 2-byte AAD record + length of Body + 16-byte authentication tag
for(int i=0;i<dataLen;i+=FRAME_SIZE){ // encrypt FRAME_SIZE number of bytes in dataBuf in sequential frames for(int i=0;i<dataLen;i+=FRAME_SIZE){ // encrypt FRAME_SIZE number of bytes in dataBuf in sequential frames
@ -1490,18 +1486,16 @@ void HAPClient::sendEncrypted(char *body, uint8_t *dataBuf, int dataLen){
if(n>FRAME_SIZE) // maximum number of bytes to encrypt=FRAME_SIZE if(n>FRAME_SIZE) // maximum number of bytes to encrypt=FRAME_SIZE
n=FRAME_SIZE; n=FRAME_SIZE;
tBuf.get()[count]=n%256; // store number of bytes that encrypts this frame (AAD bytes) tBuf.get()[0]=n%256; // store number of bytes that encrypts this frame (AAD bytes)
tBuf.get()[count+1]=n/256; tBuf.get()[1]=n/256;
crypto_aead_chacha20poly1305_ietf_encrypt(tBuf.get()+count+2,&nBytes,dataBuf+i,n,tBuf.get()+count,2,NULL,a2cNonce.get(),a2cKey); // encrypt the next portion of dataBuf with authentication tag appended crypto_aead_chacha20poly1305_ietf_encrypt(tBuf.get()+2,&nBytes,dataBuf+i,n,tBuf.get(),2,NULL,a2cNonce.get(),a2cKey); // encrypt the next portion of dataBuf with authentication tag appended
a2cNonce.inc(); // increment nonce client.write(tBuf.get(),nBytes+2); // transmit encrypted frame
a2cNonce.inc(); // increment nonce
count+=2+n+16; // increment count by 2-byte AAD record + length of JSON + 16-byte authentication tag
} }
client.write(tBuf.get(),count); // transmit all encrypted frames to Client
LOG2("-------- SENT ENCRYPTED! --------\n"); LOG2("-------- SENT ENCRYPTED! --------\n");
} // sendEncrypted } // sendEncrypted