First version with SendEncryptedContext
This commit is contained in:
parent
3d955be629
commit
3cd8f8469a
30
src/HAP.cpp
30
src/HAP.cpp
|
|
@ -851,7 +851,6 @@ int HAPClient::getAccessoriesURL(){
|
||||||
unauthorizedError();
|
unauthorizedError();
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG1("In Get Accessories #");
|
LOG1("In Get Accessories #");
|
||||||
LOG1(conNum);
|
LOG1(conNum);
|
||||||
LOG1(" (");
|
LOG1(" (");
|
||||||
|
|
@ -859,22 +858,27 @@ int HAPClient::getAccessoriesURL(){
|
||||||
LOG1(")...\n");
|
LOG1(")...\n");
|
||||||
|
|
||||||
int nBytes = homeSpan.sprintfAttributes(NULL); // get size of HAP attributes JSON
|
int nBytes = homeSpan.sprintfAttributes(NULL); // get size of HAP attributes JSON
|
||||||
TempBuffer <char> jBuf(nBytes+1,"HAPClient::getAccessoriesURL");
|
|
||||||
homeSpan.sprintfAttributes(jBuf.get()); // create JSON database (will need to re-cast to uint8_t* below)
|
|
||||||
|
|
||||||
char *body;
|
// TempBuffer <char> jBuf(nBytes+1,"HAPClient::getAccessoriesURL");
|
||||||
asprintf(&body,"HTTP/1.1 200 OK\r\nContent-Type: application/hap+json\r\nContent-Length: %d\r\n\r\n",nBytes);
|
// homeSpan.sprintfAttributes(jBuf.get()); // create JSON database (will need to re-cast to uint8_t* below)
|
||||||
|
|
||||||
LOG2("\n>>>>>>>>>> ");
|
// char *body;
|
||||||
LOG2(client.remoteIP());
|
// 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(body);
|
|
||||||
LOG2(jBuf.get());
|
|
||||||
LOG2("\n");
|
|
||||||
|
|
||||||
sendEncrypted(body,(uint8_t *)jBuf.get(),nBytes);
|
// LOG2("\n>>>>>>>>>> ");
|
||||||
free(body);
|
// LOG2(client.remoteIP());
|
||||||
|
// LOG2(" >>>>>>>>>>\n");
|
||||||
|
// LOG2(body);
|
||||||
|
// LOG2(jBuf.get());
|
||||||
|
// LOG2("\n");
|
||||||
|
|
||||||
|
// sendEncrypted(body,(uint8_t *)jBuf.get(),nBytes);
|
||||||
|
// free(body);
|
||||||
|
|
||||||
|
|
||||||
|
SendEncryptedContext context(*this);
|
||||||
|
context.printf("HTTP/1.1 200 OK\r\nContent-Type: application/hap+json\r\nContent-Length: %d\r\n\r\n",nBytes);
|
||||||
|
homeSpan.sprintfAttributes(NULL, GET_VALUE|GET_META|GET_PERMS|GET_TYPE|GET_DESC, &context);
|
||||||
return(1);
|
return(1);
|
||||||
|
|
||||||
} // getAccessories
|
} // getAccessories
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@
|
||||||
|
|
||||||
#include "HomeSpan.h"
|
#include "HomeSpan.h"
|
||||||
#include "HAP.h"
|
#include "HAP.h"
|
||||||
|
#include "SendEncryptedContext.h"
|
||||||
|
|
||||||
const __attribute__((section(".rodata_custom_desc"))) SpanPartition spanPartition = {HOMESPAN_MAGIC_COOKIE,0};
|
const __attribute__((section(".rodata_custom_desc"))) SpanPartition spanPartition = {HOMESPAN_MAGIC_COOKIE,0};
|
||||||
|
|
||||||
|
|
@ -1227,19 +1228,33 @@ Span& Span::setWifiCredentials(const char *ssid, const char *pwd){
|
||||||
|
|
||||||
///////////////////////////////
|
///////////////////////////////
|
||||||
|
|
||||||
int Span::sprintfAttributes(char *cBuf, int flags){
|
int Span::sprintfAttributes(char *cBuf, int flags, SendEncryptedContext* sendEncryptedContext){
|
||||||
|
|
||||||
int nBytes=0;
|
int nBytes=0;
|
||||||
|
|
||||||
nBytes+=snprintf(cBuf,cBuf?64:0,"{\"accessories\":[");
|
nBytes+=snprintf(cBuf,cBuf?64:0,"{\"accessories\":[");
|
||||||
|
if (sendEncryptedContext != NULL)
|
||||||
|
sendEncryptedContext->print("{\"accessories\":[");
|
||||||
|
|
||||||
for(int i=0;i<Accessories.size();i++){
|
for(int i=0;i<Accessories.size();i++){
|
||||||
nBytes+=Accessories[i]->sprintfAttributes(cBuf?(cBuf+nBytes):NULL,flags);
|
SpanAccessory* accessory=Accessories[i];
|
||||||
if(i+1<Accessories.size())
|
int accessoryBytes=accessory->sprintfAttributes(cBuf?(cBuf+nBytes):NULL,flags);
|
||||||
nBytes+=snprintf(cBuf?(cBuf+nBytes):NULL,cBuf?64:0,",");
|
nBytes+= accessoryBytes;
|
||||||
|
if (sendEncryptedContext != NULL)
|
||||||
|
{
|
||||||
|
char* buffer = sendEncryptedContext->reserveStringBuffer(accessoryBytes);
|
||||||
|
accessory->sprintfAttributes(buffer, flags);
|
||||||
|
}
|
||||||
|
if(i+1<Accessories.size())
|
||||||
|
{
|
||||||
|
nBytes+=snprintf(cBuf?(cBuf+nBytes):NULL,cBuf?64:0,",");
|
||||||
|
if (sendEncryptedContext != NULL)
|
||||||
|
sendEncryptedContext->print(",");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nBytes+=snprintf(cBuf?(cBuf+nBytes):NULL,cBuf?64:0,"]}");
|
nBytes+=snprintf(cBuf?(cBuf+nBytes):NULL,cBuf?64:0,"]}");
|
||||||
|
if (sendEncryptedContext != NULL)
|
||||||
|
sendEncryptedContext->print("]}");
|
||||||
return(nBytes);
|
return(nBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,7 @@
|
||||||
#include "extras/Pixel.h"
|
#include "extras/Pixel.h"
|
||||||
#include "Settings.h"
|
#include "Settings.h"
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
|
#include "SendEncryptedContext.h"
|
||||||
#include "Network.h"
|
#include "Network.h"
|
||||||
#include "HAPConstants.h"
|
#include "HAPConstants.h"
|
||||||
#include "HapQR.h"
|
#include "HapQR.h"
|
||||||
|
|
@ -268,7 +269,7 @@ class Span{
|
||||||
void resetStatus(); // resets statusLED and calls statusCallback based on current HomeSpan status
|
void resetStatus(); // resets statusLED and calls statusCallback based on current HomeSpan status
|
||||||
void reboot(); // reboots device
|
void reboot(); // reboots device
|
||||||
|
|
||||||
int sprintfAttributes(char *cBuf, int flags=GET_VALUE|GET_META|GET_PERMS|GET_TYPE|GET_DESC); // prints Attributes JSON database into buf, unless buf=NULL; return number of characters printed, excluding null terminator
|
int sprintfAttributes(char *cBuf, int flags=GET_VALUE|GET_META|GET_PERMS|GET_TYPE|GET_DESC, SendEncryptedContext* sendEncryptedContext = nullptr); // prints Attributes JSON database into buf, unless buf=NULL; return number of characters printed, excluding null terminator
|
||||||
|
|
||||||
void prettyPrint(char *buf, int nsp=2, int minLogLevel=0); // print arbitrary JSON from buf to serial monitor, formatted with indentions of 'nsp' spaces, subject to specified minimum log level
|
void prettyPrint(char *buf, int nsp=2, int minLogLevel=0); // print arbitrary JSON from buf to serial monitor, formatted with indentions of 'nsp' spaces, subject to specified minimum log level
|
||||||
SpanCharacteristic *find(uint32_t aid, int iid); // return Characteristic with matching aid and iid (else NULL if not found)
|
SpanCharacteristic *find(uint32_t aid, int iid); // return Characteristic with matching aid and iid (else NULL if not found)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,116 @@
|
||||||
|
/*********************************************************************************
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020-2023 Michael Geramb
|
||||||
|
*
|
||||||
|
* 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 <Arduino.h>
|
||||||
|
#include "SendEncryptedContext.h"
|
||||||
|
#include "HomeSpan.h"
|
||||||
|
#include "HAP.h"
|
||||||
|
#include "Settings.h"
|
||||||
|
#include <sodium.h>
|
||||||
|
|
||||||
|
SendEncryptedContext::SendEncryptedContext(HAPClient& hapClient)
|
||||||
|
: hapClient(hapClient),
|
||||||
|
stringBuffer(FRAME_SIZE + 1, "SendEncryptedContext dataBuffer"),
|
||||||
|
sendBuffer(FRAME_SIZE + 2 + 16, "SendEncryptedContext sendBuffer") // FRAME_SIZE + AAD + Auth
|
||||||
|
{
|
||||||
|
LOG2("\n>>>>>>>>>> ");
|
||||||
|
LOG2(hapClient.client.remoteIP());
|
||||||
|
LOG2(" >>>>>>>>>>\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void SendEncryptedContext::printf(const char* format, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, format);
|
||||||
|
int len = vsnprintf(NULL, 0, format, ap);
|
||||||
|
char* buffer = reserveStringBuffer(len);
|
||||||
|
vsnprintf(buffer, len + 1, format, ap); // the reserved buffer is one byte larger because it contains the terminating '\0'
|
||||||
|
LOG2(buffer);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SendEncryptedContext::print(const char* text)
|
||||||
|
{
|
||||||
|
auto len = strlen(text);
|
||||||
|
auto buffer = reserveStringBuffer(len);
|
||||||
|
memcpy(buffer, text, len);
|
||||||
|
LOG2(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
char* SendEncryptedContext::reserveStringBuffer(int stringLength)
|
||||||
|
{
|
||||||
|
int requiredNewBufferLength = stringLength + 1; // reserve buffer for characters and string terminator '\0'
|
||||||
|
if (stringBuffer.len() - usedStringLength < requiredNewBufferLength)
|
||||||
|
{
|
||||||
|
// to less memory, send first exitsting buffer
|
||||||
|
if (usedStringLength > 0)
|
||||||
|
{
|
||||||
|
sendEncrypted(stringBuffer.get(), usedStringLength);
|
||||||
|
usedStringLength = 0;
|
||||||
|
}
|
||||||
|
// Check if still more memory is needed
|
||||||
|
if (stringBuffer.len() < requiredNewBufferLength)
|
||||||
|
stringBuffer = TempBuffer<char>(requiredNewBufferLength, "SendEncryptedContext::reserveMemory");
|
||||||
|
}
|
||||||
|
int alreadyInUse = usedStringLength;
|
||||||
|
usedStringLength += stringLength;
|
||||||
|
char* result = stringBuffer.get() + alreadyInUse;
|
||||||
|
result[stringLength] = '\0'; // add string terminator
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SendEncryptedContext::sendEncrypted(const char* buffer, int length)
|
||||||
|
{
|
||||||
|
if (length == 0)
|
||||||
|
return;
|
||||||
|
sentLength += length;
|
||||||
|
LOG2(buffer);
|
||||||
|
|
||||||
|
for(int i=0;i<length;i+=FRAME_SIZE){ // encrypt FRAME_SIZE number of bytes in dataBuf in sequential frames
|
||||||
|
|
||||||
|
int n=length-i; // number of bytes remaining
|
||||||
|
|
||||||
|
if(n>FRAME_SIZE) // maximum number of bytes to encrypt=FRAME_SIZE
|
||||||
|
n=FRAME_SIZE;
|
||||||
|
|
||||||
|
sendBuffer.get()[0]=n%256; // store number of bytes that encrypts this frame (AAD bytes)
|
||||||
|
sendBuffer.get()[1]=n/256;
|
||||||
|
|
||||||
|
unsigned long long nBytes;
|
||||||
|
crypto_aead_chacha20poly1305_ietf_encrypt(sendBuffer.get()+2,&nBytes, (uint8_t*) buffer+i,n,sendBuffer.get(),2,NULL,hapClient.a2cNonce.get(),hapClient.a2cKey); // encrypt the next portion of dataBuf with authentication tag appended
|
||||||
|
|
||||||
|
hapClient.client.write(sendBuffer.get(),nBytes+2); // transmit encrypted frame
|
||||||
|
hapClient.a2cNonce.inc(); // increment nonce
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SendEncryptedContext::~SendEncryptedContext()
|
||||||
|
{
|
||||||
|
if (usedStringLength > 0)
|
||||||
|
sendEncrypted(stringBuffer.get(), usedStringLength);
|
||||||
|
LOG2("-------- SENT ENCRYPTED! --------\n");
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
/*********************************************************************************
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020-2023 Michael Geramb
|
||||||
|
*
|
||||||
|
* 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 "Utils.h"
|
||||||
|
|
||||||
|
struct HAPClient;
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////
|
||||||
|
// SendEncryptedContext class
|
||||||
|
// Write encrypted data as response to a web call
|
||||||
|
|
||||||
|
class SendEncryptedContext
|
||||||
|
{
|
||||||
|
const int FRAME_SIZE=1024; // number of bytes to use in each ChaCha20-Poly1305 encrypted frame when sending encrypted JSON content to Client
|
||||||
|
|
||||||
|
TempBuffer<char> stringBuffer;
|
||||||
|
int usedStringLength = 0;
|
||||||
|
int sentLength = 0;
|
||||||
|
HAPClient& hapClient;
|
||||||
|
TempBuffer<uint8_t> sendBuffer;
|
||||||
|
public:
|
||||||
|
SendEncryptedContext(HAPClient& hapClient);
|
||||||
|
~SendEncryptedContext();
|
||||||
|
|
||||||
|
void printf(const char* format, ...);
|
||||||
|
void print(const char* text);
|
||||||
|
char* reserveStringBuffer(int stringLength);
|
||||||
|
private:
|
||||||
|
void sendEncrypted(const char* buffer, int length);
|
||||||
|
};
|
||||||
Loading…
Reference in New Issue