Skip to content

Commit feefebb

Browse files
Merge pull request #132 from gb88/master
Force SPIFFS Update and custom key length
2 parents 2bbc9cb + e067a61 commit feefebb

File tree

2 files changed

+67
-19
lines changed

2 files changed

+67
-19
lines changed

src/esp32FOTA.cpp

Lines changed: 56 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@
4141
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
4242
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
4343

44-
#define FW_SIGNATURE_LENGTH 512
4544

4645

4746
static int64_t getHTTPStream( esp32FOTA* fota, int partition );
@@ -181,13 +180,14 @@ void esp32FOTA::setConfig( FOTAConfig_t cfg )
181180
_cfg.use_device_id = cfg.use_device_id;
182181
_cfg.root_ca = cfg.root_ca;
183182
_cfg.pub_key = cfg.pub_key;
183+
_cfg.signature_len = cfg.signature_len;
184184
}
185185

186186

187187
void esp32FOTA::printConfig( FOTAConfig_t *cfg )
188188
{
189189
if( cfg == nullptr ) cfg = &_cfg;
190-
log_d("Name: %s\nManifest URL:%s\nSemantic Version: %d.%d.%d\nCheck Sig: %s\nUnsafe: %s\nUse Device ID: %s\nRootCA: %s\nPubKey: %s\n",
190+
log_d("Name: %s\nManifest URL:%s\nSemantic Version: %d.%d.%d\nCheck Sig: %s\nUnsafe: %s\nUse Device ID: %s\nRootCA: %s\nPubKey: %s\nSignatureLen: %d\n",
191191
cfg->name ? cfg->name : "None",
192192
cfg->manifest_url ? cfg->manifest_url : "None",
193193
cfg->sem.ver()->major,
@@ -197,11 +197,17 @@ void esp32FOTA::printConfig( FOTAConfig_t *cfg )
197197
cfg->unsafe ?"true":"false",
198198
cfg->use_device_id ?"true":"false",
199199
cfg->root_ca ?"true":"false",
200-
cfg->pub_key ?"true":"false"
200+
cfg->pub_key ?"true":"false",
201+
cfg->signature_len
201202
);
202203
}
203204

204205

206+
void esp32FOTA::setSignatureLen( size_t len )
207+
{
208+
_cfg.signature_len = len;
209+
}
210+
205211

206212
void esp32FOTA::setCertFileSystem( fs::FS *cert_filesystem )
207213
{
@@ -327,7 +333,7 @@ bool esp32FOTA::validate_sig( const esp_partition_t* partition, unsigned char *s
327333
}
328334
mbedtls_md_finish( &rsa, hash );
329335

330-
ret = mbedtls_pk_verify( &pk, MBEDTLS_MD_SHA256, hash, mdinfo->size, (unsigned char*)signature, FW_SIGNATURE_LENGTH );
336+
ret = mbedtls_pk_verify( &pk, MBEDTLS_MD_SHA256, hash, mdinfo->size, (unsigned char*)signature, _cfg.signature_len );
331337

332338
free( hash );
333339
mbedtls_md_free( &rsa );
@@ -467,6 +473,27 @@ bool esp32FOTA::execOTA()
467473
return ret;
468474
}
469475

476+
// OTA Logic
477+
bool esp32FOTA::execSPIFFSOTA()
478+
{
479+
bool ret;
480+
setupStream();
481+
482+
if( !_flashFileSystemUrl.isEmpty() ) { // a data partition was specified in the json manifest, handle the spiffs partition first
483+
if( _fs ) { // Possible risk of overwriting certs and signatures, cancel flashing!
484+
log_e("Cowardly refusing to overwrite U_SPIFFS with %s. Use setCertFileSystem(nullptr) along with setPubKey()/setCAPem() to enable this feature.", _flashFileSystemUrl);
485+
return false;
486+
} else {
487+
log_i("Will check if U_SPIFFS needs updating");
488+
ret = execOTA( U_SPIFFS, false );
489+
}
490+
} else {
491+
log_i("This update is for U_FLASH only");
492+
}
493+
stopStream();
494+
return ret;
495+
}
496+
470497

471498
bool esp32FOTA::execOTA( int partition, bool restart_after )
472499
{
@@ -513,11 +540,11 @@ bool esp32FOTA::execOTA( int partition, bool restart_after )
513540
log_e("Compressed && signed image is not (yet) supported");
514541
return false;
515542
}
516-
if( updateSize == UPDATE_SIZE_UNKNOWN || updateSize <= FW_SIGNATURE_LENGTH ) {
543+
if( updateSize == UPDATE_SIZE_UNKNOWN || updateSize <= _cfg.signature_len ) {
517544
log_e("Malformed signature+fw combo");
518545
return false;
519546
}
520-
updateSize -= FW_SIGNATURE_LENGTH;
547+
updateSize -= _cfg.signature_len;
521548
}
522549

523550
// If using compression, the size is implicitely unknown
@@ -541,9 +568,9 @@ bool esp32FOTA::execOTA( int partition, bool restart_after )
541568
});
542569
}
543570

544-
unsigned char signature[FW_SIGNATURE_LENGTH];
571+
unsigned char* signature = new unsigned char[_cfg.signature_len];
545572
if( _cfg.check_sig ) {
546-
_stream->readBytes( signature, FW_SIGNATURE_LENGTH );
573+
_stream->readBytes( signature, _cfg.signature_len );
547574
}
548575

549576
log_i("Begin %s OTA. This may take 2 - 5 mins to complete. Things might be quiet for a while.. Patience!", partition==U_FLASH?"Firmware":"Filesystem");
@@ -560,11 +587,13 @@ bool esp32FOTA::execOTA( int partition, bool restart_after )
560587
} else {
561588
log_e("Written only : %d/%d Premature end of stream?", written, updateSize);
562589
F_abort();
590+
delete[] signature;
563591
return false;
564592
}
565593

566594
if (!F_UpdateEnd()) {
567595
log_e("An Update Error Occurred. Error #: %s", F_Update.getError());
596+
delete[] signature;
568597
return false;
569598
}
570599

@@ -582,6 +611,7 @@ bool esp32FOTA::execOTA( int partition, bool restart_after )
582611
if( !_target_partition ) {
583612
log_e("Can't access partition #%d to check signature!", partition);
584613
if( onUpdateCheckFail ) onUpdateCheckFail( partition, CHECK_SIG_ERROR_PARTITION_NOT_FOUND );
614+
delete[] signature;
585615
return false;
586616
}
587617

@@ -601,6 +631,7 @@ bool esp32FOTA::execOTA( int partition, bool restart_after )
601631
}
602632

603633
if( !validate_sig( _target_partition, signature, updateSize ) ) {
634+
delete[] signature;
604635
// erase partition
605636
esp_partition_erase_range( _target_partition, _target_partition->address, _target_partition->size );
606637

@@ -613,6 +644,7 @@ bool esp32FOTA::execOTA( int partition, bool restart_after )
613644
}
614645
return false;
615646
} else {
647+
delete[] signature;
616648
log_d("Signature check successful!");
617649
if( partition == U_FLASH ) {
618650
// Set updated partition as bootable now that it's been verified
@@ -844,39 +876,48 @@ String esp32FOTA::getDeviceID()
844876

845877

846878
// Force a firmware update regardless on current version
847-
void esp32FOTA::forceUpdate(const char* firmwareURL, bool validate )
879+
bool esp32FOTA::forceUpdate(const char* firmwareURL, bool validate )
848880
{
849881
_firmwareUrl = firmwareURL;
850882
_cfg.check_sig = validate;
851-
execOTA();
883+
return execOTA();
884+
}
885+
886+
// Force a firmware update regardless on current version
887+
bool esp32FOTA::forceUpdateSPIFFS(const char* firmwareURL, bool validate )
888+
{
889+
_firmwareUrl = firmwareURL;
890+
_flashFileSystemUrl = firmwareURL;
891+
_cfg.check_sig = validate;
892+
return execSPIFFSOTA();
852893
}
853894

854895

855-
void esp32FOTA::forceUpdate(const char* firmwareHost, uint16_t firmwarePort, const char* firmwarePath, bool validate )
896+
bool esp32FOTA::forceUpdate(const char* firmwareHost, uint16_t firmwarePort, const char* firmwarePath, bool validate )
856897
{
857898
static String firmwareURL("http");
858899
if ( firmwarePort == 443 || firmwarePort == 4433 ) firmwareURL += "s";
859900
firmwareURL += String(firmwareHost);
860901
firmwareURL += ":";
861902
firmwareURL += String(firmwarePort);
862903
firmwareURL += firmwarePath;
863-
forceUpdate( firmwareURL.c_str(), validate );
904+
return forceUpdate( firmwareURL.c_str(), validate );
864905
}
865906

866907

867-
void esp32FOTA::forceUpdate(bool validate )
908+
bool esp32FOTA::forceUpdate(bool validate )
868909
{
869910
// Forces an update from a manifest, ignoring the version check
870911
if(!execHTTPcheck()) {
871912
if (!_firmwareUrl) {
872913
// execHTTPcheck returns false when the manifest is malformed or when the version isn't
873914
// an upgrade. If _firmwareUrl isn't set we can't force an upgrade.
874915
log_e("forceUpdate called, but unable to get _firmwareUrl from manifest via execHTTPcheck.");
875-
return;
916+
return false;
876917
}
877918
}
878919
_cfg.check_sig = validate;
879-
execOTA();
920+
return execOTA();
880921
}
881922

882923

src/esp32FOTA.hpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ extern "C" {
147147
#define F_writeStream() F_Update.writeStream(*_stream);
148148
#endif
149149

150-
150+
#define FW_SIGNATURE_LENGTH 512
151151

152152
struct SemverClass
153153
{
@@ -211,6 +211,7 @@ struct FOTAConfig_t
211211
bool use_device_id { false };
212212
CryptoAsset* root_ca { nullptr };
213213
CryptoAsset* pub_key { nullptr };
214+
size_t signature_len {FW_SIGNATURE_LENGTH};
214215
FOTAConfig_t() = default;
215216
};
216217

@@ -242,13 +243,16 @@ class esp32FOTA
242243
template <typename T> void setPubKey( T* asset ) { _cfg.pub_key = (CryptoAsset*)asset; _cfg.check_sig = true; }
243244
template <typename T> void setRootCA( T* asset ) { _cfg.root_ca = (CryptoAsset*)asset; _cfg.unsafe = false; }
244245

245-
void forceUpdate(const char* firmwareHost, uint16_t firmwarePort, const char* firmwarePath, bool validate );
246-
void forceUpdate(const char* firmwareURL, bool validate );
247-
void forceUpdate(bool validate );
246+
bool forceUpdate(const char* firmwareHost, uint16_t firmwarePort, const char* firmwarePath, bool validate );
247+
bool forceUpdate(const char* firmwareURL, bool validate );
248+
bool forceUpdate(bool validate );
249+
250+
bool forceUpdateSPIFFS(const char* firmwareURL, bool validate );
248251

249252
void handle();
250253

251254
bool execOTA();
255+
bool execSPIFFSOTA();
252256
bool execOTA( int partition, bool restart_after = true );
253257
bool execHTTPcheck();
254258

@@ -265,6 +269,9 @@ class esp32FOTA
265269
// use this to set "Authorization: Basic" or other specific headers to be sent with the queries
266270
void setExtraHTTPHeader( String name, String value ) { extraHTTPHeaders[name] = value; }
267271

272+
// set the signature len
273+
void setSignatureLen( size_t len );
274+
268275
// /!\ Only use this to change filesystem for **default** RootCA and PubKey paths.
269276
// Otherwise use setPubKey() and setRootCA()
270277
void setCertFileSystem( fs::FS *cert_filesystem = nullptr );

0 commit comments

Comments
 (0)