Adding Custom Magic Cookie to OTA Partition
Will prevent uploading a non-HomeSpan sketch via OTA to an existing HomeSpan device.
This commit is contained in:
parent
7ddbfd55cc
commit
2f1044b013
|
|
@ -41,6 +41,7 @@ void HAPClient::init(){
|
||||||
nvs_open("SRP",NVS_READWRITE,&srpNVS); // open SRP data namespace in NVS
|
nvs_open("SRP",NVS_READWRITE,&srpNVS); // open SRP data namespace in NVS
|
||||||
nvs_open("HAP",NVS_READWRITE,&hapNVS); // open HAP data namespace in NVS
|
nvs_open("HAP",NVS_READWRITE,&hapNVS); // open HAP data namespace in NVS
|
||||||
nvs_open("OTA",NVS_READWRITE,&otaNVS); // open OTA data namespace in NVS
|
nvs_open("OTA",NVS_READWRITE,&otaNVS); // open OTA data namespace in NVS
|
||||||
|
nvs_open("STATE",NVS_READWRITE,&stateNVS); // open STATE data namespace in NVS
|
||||||
|
|
||||||
if(!nvs_get_str(otaNVS,"OTADATA",NULL,&len)){ // if found OTA data in NVS
|
if(!nvs_get_str(otaNVS,"OTADATA",NULL,&len)){ // if found OTA data in NVS
|
||||||
nvs_get_str(otaNVS,"OTADATA",homeSpan.otaPwd,&len); // retrieve data
|
nvs_get_str(otaNVS,"OTADATA",homeSpan.otaPwd,&len); // retrieve data
|
||||||
|
|
@ -1750,6 +1751,7 @@ TLV<kTLVType,10> HAPClient::tlv8;
|
||||||
nvs_handle HAPClient::hapNVS;
|
nvs_handle HAPClient::hapNVS;
|
||||||
nvs_handle HAPClient::srpNVS;
|
nvs_handle HAPClient::srpNVS;
|
||||||
nvs_handle HAPClient::otaNVS;
|
nvs_handle HAPClient::otaNVS;
|
||||||
|
nvs_handle HAPClient::stateNVS;
|
||||||
uint8_t HAPClient::httpBuf[MAX_HTTP+1];
|
uint8_t HAPClient::httpBuf[MAX_HTTP+1];
|
||||||
HKDF HAPClient::hkdf;
|
HKDF HAPClient::hkdf;
|
||||||
pairState HAPClient::pairStatus;
|
pairState HAPClient::pairStatus;
|
||||||
|
|
|
||||||
|
|
@ -81,6 +81,7 @@ struct HAPClient {
|
||||||
static nvs_handle hapNVS; // handle for non-volatile-storage of HAP data
|
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 nvs_handle srpNVS; // handle for non-volatile-storage of SRP data
|
||||||
static nvs_handle otaNVS; // handle for non-volatile-storage of OTA data
|
static nvs_handle otaNVS; // handle for non-volatile-storage of OTA data
|
||||||
|
static nvs_handle stateNVS; // handle for non-volatile-storage of HomeSpan STATE data
|
||||||
static uint8_t httpBuf[MAX_HTTP+1]; // buffer to store HTTP messages (+1 to leave room for storing an extra 'overflow' character)
|
static uint8_t httpBuf[MAX_HTTP+1]; // buffer to store HTTP messages (+1 to leave room for storing an extra 'overflow' character)
|
||||||
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
|
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
|
||||||
static pairState pairStatus; // tracks pair-setup status
|
static pairState pairStatus; // tracks pair-setup status
|
||||||
|
|
|
||||||
149
src/HomeSpan.cpp
149
src/HomeSpan.cpp
|
|
@ -29,22 +29,22 @@
|
||||||
#include <nvs_flash.h>
|
#include <nvs_flash.h>
|
||||||
#include <sodium.h>
|
#include <sodium.h>
|
||||||
#include <WiFi.h>
|
#include <WiFi.h>
|
||||||
#include <ArduinoOTA.h>
|
|
||||||
#include <esp_ota_ops.h>
|
|
||||||
#include <driver/ledc.h>
|
#include <driver/ledc.h>
|
||||||
#include <mbedtls/version.h>
|
#include <mbedtls/version.h>
|
||||||
#include <esp_task_wdt.h>
|
#include <esp_task_wdt.h>
|
||||||
#include <esp_sntp.h>
|
#include <esp_sntp.h>
|
||||||
|
#include <esp_ota_ops.h>
|
||||||
|
|
||||||
#include "HomeSpan.h"
|
#include "HomeSpan.h"
|
||||||
#include "HAP.h"
|
#include "HAP.h"
|
||||||
|
|
||||||
|
const __attribute__((section(".rodata_custom_desc"))) SpanPartition spanPartition = {HOMESPAN_MAGIC_COOKIE};
|
||||||
|
|
||||||
using namespace Utils;
|
using namespace Utils;
|
||||||
|
|
||||||
HAPClient **hap; // HAP Client structure containing HTTP client connections, parsing routines, and state variables (global-scoped variable)
|
HAPClient **hap; // HAP Client structure containing HTTP client connections, parsing routines, and state variables (global-scoped variable)
|
||||||
Span homeSpan; // HAP Attributes database and all related control functions for this Accessory (global-scoped variable)
|
Span homeSpan; // HAP Attributes database and all related control functions for this Accessory (global-scoped variable)
|
||||||
HapCharacteristics hapChars; // Instantiation of all HAP Characteristics (used to create SpanCharacteristics)
|
HapCharacteristics hapChars; // Instantiation of all HAP Characteristics (used to create SpanCharacteristics)
|
||||||
int otaPercent; // local variable to keep track of %progress when OTA is loading new sketch
|
|
||||||
|
|
||||||
///////////////////////////////
|
///////////////////////////////
|
||||||
// Span //
|
// Span //
|
||||||
|
|
@ -136,10 +136,34 @@ void Span::begin(Category catID, const char *displayName, const char *hostNameBa
|
||||||
Serial.print(" ");
|
Serial.print(" ");
|
||||||
Serial.print(__TIME__);
|
Serial.print(__TIME__);
|
||||||
|
|
||||||
|
esp_ota_img_states_t otaState;
|
||||||
|
esp_ota_get_state_partition(esp_ota_get_running_partition(),&otaState);
|
||||||
|
Serial.printf("\nPartition: %s (%X)",esp_ota_get_running_partition()->label,otaState);
|
||||||
|
Serial.printf("\nMagic Cookie: %s",spanPartition.magicCookie);
|
||||||
|
|
||||||
|
esp_app_desc_t appDesc;
|
||||||
|
esp_ota_get_partition_description(esp_ota_get_running_partition(),&appDesc);
|
||||||
|
|
||||||
|
char newDesc[256];
|
||||||
|
esp_partition_read(esp_ota_get_running_partition(), sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t) + sizeof(esp_app_desc_t), newDesc, sizeof(newDesc));
|
||||||
|
|
||||||
|
Serial.println();
|
||||||
|
Serial.println(appDesc.version);
|
||||||
|
Serial.println(appDesc.project_name);
|
||||||
|
Serial.println(appDesc.time);
|
||||||
|
Serial.println(appDesc.date);
|
||||||
|
Serial.println(appDesc.idf_ver);
|
||||||
|
if(strlen(spanPartition.magicCookie))
|
||||||
|
{Serial.println("HI\n");
|
||||||
|
}
|
||||||
|
Serial.println(newDesc);
|
||||||
|
|
||||||
|
|
||||||
Serial.print("\n\nDevice Name: ");
|
Serial.print("\n\nDevice Name: ");
|
||||||
Serial.print(displayName);
|
Serial.print(displayName);
|
||||||
Serial.print("\n\n");
|
Serial.print("\n\n");
|
||||||
|
|
||||||
|
|
||||||
} // begin
|
} // begin
|
||||||
|
|
||||||
///////////////////////////////
|
///////////////////////////////
|
||||||
|
|
@ -525,41 +549,47 @@ void Span::checkConnect(){
|
||||||
if(otaAuth)
|
if(otaAuth)
|
||||||
ArduinoOTA.setPasswordHash(otaPwd);
|
ArduinoOTA.setPasswordHash(otaPwd);
|
||||||
|
|
||||||
ArduinoOTA
|
ArduinoOTA.onStart(spanOTA.start).onEnd(spanOTA.end).onProgress(spanOTA.progress).onError(spanOTA.error);
|
||||||
.onStart([]() {
|
|
||||||
Serial.printf("\n*** Current Partition: %s\n*** New Partition: %s\n*** OTA Starting..",
|
// ArduinoOTA
|
||||||
esp_ota_get_running_partition()->label,esp_ota_get_next_update_partition(NULL)->label);
|
// .onStart([]() {
|
||||||
otaPercent=-10;
|
// Serial.printf("\n*** Current Partition: %s\n*** New Partition: %s\n*** OTA Starting..",
|
||||||
homeSpan.statusLED.start(LED_OTA_STARTED);
|
// esp_ota_get_running_partition()->label,esp_ota_get_next_update_partition(NULL)->label);
|
||||||
})
|
// otaPercent=-10;
|
||||||
.onEnd([]() {
|
// homeSpan.statusLED.start(LED_OTA_STARTED);
|
||||||
Serial.printf(" DONE! Rebooting...\n");
|
// })
|
||||||
homeSpan.statusLED.off();
|
// .onEnd([]() {
|
||||||
})
|
// Serial.printf(" DONE! Rebooting...\n");
|
||||||
.onProgress([](unsigned int progress, unsigned int total) {
|
// char newDesc[256];
|
||||||
int percent=progress*100/total;
|
// esp_partition_read(esp_ota_get_next_update_partition(NULL), sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t) + sizeof(esp_app_desc_t), newDesc, sizeof(newDesc));
|
||||||
if(percent/10 != otaPercent/10){
|
// Serial.printf("Found: %s\n",newDesc);
|
||||||
otaPercent=percent;
|
// homeSpan.statusLED.off();
|
||||||
Serial.printf("%d%%..",progress*100/total);
|
// })
|
||||||
}
|
// .onProgress([](unsigned int progress, unsigned int total) {
|
||||||
})
|
// int percent=progress*100/total;
|
||||||
.onError([](ota_error_t error) {
|
// if(percent/10 != otaPercent/10){
|
||||||
Serial.printf("*** OTA Error[%u]: ", error);
|
// otaPercent=percent;
|
||||||
if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed\n");
|
// Serial.printf("%d%%..",progress*100/total);
|
||||||
else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed\n");
|
// if(progress*100/total>20){
|
||||||
else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed\n");
|
// Serial.println("BAD!!\n");
|
||||||
else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed\n");
|
// Update.abort();
|
||||||
else if (error == OTA_END_ERROR) Serial.println("End Failed\n");
|
// }
|
||||||
});
|
// }
|
||||||
|
// })
|
||||||
|
// .onError([](ota_error_t error) {
|
||||||
|
// Serial.printf("*** OTA Error[%u]: ", error);
|
||||||
|
// if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed\n");
|
||||||
|
// else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed\n");
|
||||||
|
// else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed\n");
|
||||||
|
// else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed\n");
|
||||||
|
// else if (error == OTA_END_ERROR) Serial.println("End Failed\n");
|
||||||
|
// });
|
||||||
|
|
||||||
ArduinoOTA.begin();
|
ArduinoOTA.begin();
|
||||||
Serial.print("Starting OTA Server: ");
|
Serial.print("Starting OTA Server: ");
|
||||||
Serial.print(displayName);
|
Serial.print(displayName);
|
||||||
Serial.print(" at ");
|
Serial.print(" at ");
|
||||||
Serial.print(WiFi.localIP());
|
Serial.print(WiFi.localIP());
|
||||||
esp_ota_img_states_t otaState;
|
|
||||||
esp_ota_get_state_partition(esp_ota_get_running_partition(),&otaState);
|
|
||||||
// Serial.printf("\nPartition: %s State: %X",esp_ota_get_running_partition()->label,otaState);
|
|
||||||
Serial.print("\nAuthorization Password: ");
|
Serial.print("\nAuthorization Password: ");
|
||||||
Serial.print(otaAuth?"Enabled\n\n":"DISABLED!\n\n");
|
Serial.print(otaAuth?"Enabled\n\n":"DISABLED!\n\n");
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1996,3 +2026,58 @@ void SpanWebLog::addLog(const char *fmt, ...){
|
||||||
if(homeSpan.logLevel>0)
|
if(homeSpan.logLevel>0)
|
||||||
Serial.printf("WEBLOG: %s\n",log[index].message);
|
Serial.printf("WEBLOG: %s\n",log[index].message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///////////////////////////////
|
||||||
|
// SpanOTA //
|
||||||
|
///////////////////////////////
|
||||||
|
|
||||||
|
void SpanOTA::start(){
|
||||||
|
Serial.printf("\n*** Current Partition: %s\n*** New Partition: %s\n*** OTA Starting..",
|
||||||
|
esp_ota_get_running_partition()->label,esp_ota_get_next_update_partition(NULL)->label);
|
||||||
|
otaPercent=0;
|
||||||
|
homeSpan.statusLED.start(LED_OTA_STARTED);
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////
|
||||||
|
|
||||||
|
void SpanOTA::end(){
|
||||||
|
Serial.printf(" DONE! Rebooting...\n");
|
||||||
|
// char newDesc[256];
|
||||||
|
SpanPartition newSpanPartition;
|
||||||
|
esp_partition_read(esp_ota_get_next_update_partition(NULL), sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t) + sizeof(esp_app_desc_t), &newSpanPartition, sizeof(newSpanPartition));
|
||||||
|
Serial.printf("Found: %s\n",newSpanPartition.magicCookie);
|
||||||
|
homeSpan.statusLED.off();
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////
|
||||||
|
|
||||||
|
void SpanOTA::progress(uint32_t progress, uint32_t total){
|
||||||
|
int percent=progress*100/total;
|
||||||
|
if(percent/10 != otaPercent/10){
|
||||||
|
otaPercent=percent;
|
||||||
|
Serial.printf("%d%%..",progress*100/total);
|
||||||
|
if(progress*100/total>20){
|
||||||
|
Serial.println("BAD!!\n");
|
||||||
|
// Update.abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////
|
||||||
|
|
||||||
|
void SpanOTA::error(ota_error_t err){
|
||||||
|
Serial.printf("*** OTA Error[%u]: ", err);
|
||||||
|
if (err == OTA_AUTH_ERROR) Serial.println("Auth Failed\n");
|
||||||
|
else if (err == OTA_BEGIN_ERROR) Serial.println("Begin Failed\n");
|
||||||
|
else if (err == OTA_CONNECT_ERROR) Serial.println("Connect Failed\n");
|
||||||
|
else if (err == OTA_RECEIVE_ERROR) Serial.println("Receive Failed\n");
|
||||||
|
else if (err == OTA_END_ERROR) Serial.println("End Failed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////
|
||||||
|
|
||||||
|
int SpanOTA::otaPercent;
|
||||||
|
boolean SpanOTA::verified;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <nvs.h>
|
#include <nvs.h>
|
||||||
|
#include <ArduinoOTA.h>
|
||||||
|
|
||||||
#include "Settings.h"
|
#include "Settings.h"
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
|
|
@ -71,12 +72,18 @@ struct SpanRange;
|
||||||
struct SpanBuf;
|
struct SpanBuf;
|
||||||
struct SpanButton;
|
struct SpanButton;
|
||||||
struct SpanUserCommand;
|
struct SpanUserCommand;
|
||||||
struct SpanWebLog;
|
|
||||||
|
|
||||||
extern Span homeSpan;
|
extern Span homeSpan;
|
||||||
|
|
||||||
///////////////////////////////
|
///////////////////////////////
|
||||||
|
|
||||||
|
struct SpanPartition{
|
||||||
|
char magicCookie[32];
|
||||||
|
uint8_t reserved[224];
|
||||||
|
};
|
||||||
|
|
||||||
|
///////////////////////////////
|
||||||
|
|
||||||
struct SpanConfig{
|
struct SpanConfig{
|
||||||
int configNumber=0; // configuration number - broadcast as Bonjour "c#" (computed automatically)
|
int configNumber=0; // configuration number - broadcast as Bonjour "c#" (computed automatically)
|
||||||
uint8_t hashCode[48]={0}; // SHA-384 hash of Span Database stored as a form of unique "signature" to know when to update the config number upon changes
|
uint8_t hashCode[48]={0}; // SHA-384 hash of Span Database stored as a form of unique "signature" to know when to update the config number upon changes
|
||||||
|
|
@ -120,6 +127,17 @@ struct SpanWebLog{ // optional web status/log data
|
||||||
|
|
||||||
///////////////////////////////
|
///////////////////////////////
|
||||||
|
|
||||||
|
struct SpanOTA{ // manages OTA process
|
||||||
|
static int otaPercent;
|
||||||
|
static boolean verified;
|
||||||
|
static void start();
|
||||||
|
static void end();
|
||||||
|
static void progress(uint32_t progress, uint32_t total);
|
||||||
|
static void error(ota_error_t err);
|
||||||
|
};
|
||||||
|
|
||||||
|
///////////////////////////////
|
||||||
|
|
||||||
struct Span{
|
struct Span{
|
||||||
|
|
||||||
const char *displayName; // display name for this device - broadcast as part of Bonjour MDNS
|
const char *displayName; // display name for this device - broadcast as part of Bonjour MDNS
|
||||||
|
|
@ -158,6 +176,7 @@ struct Span{
|
||||||
boolean otaEnabled=false; // enables Over-the-Air ("OTA") updates
|
boolean otaEnabled=false; // enables Over-the-Air ("OTA") updates
|
||||||
char otaPwd[33]; // MD5 Hash of OTA password, represented as a string of hexidecimal characters
|
char otaPwd[33]; // MD5 Hash of OTA password, represented as a string of hexidecimal characters
|
||||||
boolean otaAuth; // OTA requires password when set to true
|
boolean otaAuth; // OTA requires password when set to true
|
||||||
|
boolean otaDownload=false; // set to true in NVS if last download was via OTA
|
||||||
void (*wifiCallback)()=NULL; // optional callback function to invoke once WiFi connectivity is established
|
void (*wifiCallback)()=NULL; // optional callback function to invoke once WiFi connectivity is established
|
||||||
void (*pairCallback)(boolean isPaired)=NULL; // optional callback function to invoke when pairing is established (true) or lost (false)
|
void (*pairCallback)(boolean isPaired)=NULL; // optional callback function to invoke when pairing is established (true) or lost (false)
|
||||||
boolean autoStartAPEnabled=false; // enables auto start-up of Access Point when WiFi Credentials not found
|
boolean autoStartAPEnabled=false; // enables auto start-up of Access Point when WiFi Credentials not found
|
||||||
|
|
@ -169,6 +188,7 @@ struct Span{
|
||||||
Network network; // configures WiFi and Setup Code via either serial monitor or temporary Access Point
|
Network network; // configures WiFi and Setup Code via either serial monitor or temporary Access Point
|
||||||
SpanWebLog webLog; // optional web status/log
|
SpanWebLog webLog; // optional web status/log
|
||||||
|
|
||||||
|
SpanOTA spanOTA; // manages OTA process
|
||||||
SpanConfig hapConfig; // track configuration changes to the HAP Accessory database; used to increment the configuration number (c#) when changes found
|
SpanConfig hapConfig; // track configuration changes to the HAP Accessory database; used to increment the configuration number (c#) when changes found
|
||||||
vector<SpanAccessory *> Accessories; // vector of pointers to all Accessories
|
vector<SpanAccessory *> Accessories; // vector of pointers to all Accessories
|
||||||
vector<SpanService *> Loops; // vector of pointer to all Services that have over-ridden loop() methods
|
vector<SpanService *> Loops; // vector of pointer to all Services that have over-ridden loop() methods
|
||||||
|
|
|
||||||
|
|
@ -83,6 +83,11 @@
|
||||||
|
|
||||||
#define DEFAULT_WEBLOG_URL "status" // change with optional fourth argument in homeSpan.enableWebLog()
|
#define DEFAULT_WEBLOG_URL "status" // change with optional fourth argument in homeSpan.enableWebLog()
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////
|
||||||
|
// OTA PARTITION INFO //
|
||||||
|
|
||||||
|
#define HOMESPAN_MAGIC_COOKIE "HomeSpanMagicCookie"
|
||||||
|
|
||||||
/////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////
|
||||||
// STATUS LED SETTINGS //
|
// STATUS LED SETTINGS //
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue