Skip to content

Commit e252873

Browse files
Use 2nd stack for update signature verification (#7149)
* Use 2nd stack for update signature verification Fixes #7145 When doing a signed update, the signature calculation can use a lot of stack, so move it silently to the BearSSL second stack. Also fix a memory leak of signature-bytes found by @JiriBilek * Reset state on any error condition in Updater::end
1 parent afb9921 commit e252873

File tree

3 files changed

+33
-4
lines changed

3 files changed

+33
-4
lines changed

cores/esp8266/Updater.cpp

+15-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "Updater.h"
22
#include "eboot_command.h"
33
#include <esp8266_peri.h>
4+
#include "StackThunk.h"
45

56
//#define DEBUG_UPDATER Serial
67

@@ -40,6 +41,14 @@ UpdaterClass::UpdaterClass()
4041
{
4142
#if ARDUINO_SIGNING
4243
installSignature(&esp8266::updaterSigningHash, &esp8266::updaterSigningVerifier);
44+
stack_thunk_add_ref();
45+
#endif
46+
}
47+
48+
UpdaterClass::~UpdaterClass()
49+
{
50+
#if ARDUINO_SIGNING
51+
stack_thunk_del_ref();
4352
#endif
4453
}
4554

@@ -199,14 +208,14 @@ bool UpdaterClass::end(bool evenIfRemaining){
199208
#ifdef DEBUG_UPDATER
200209
DEBUG_UPDATER.println(F("no update"));
201210
#endif
211+
_reset();
202212
return false;
203213
}
204214

205215
if(hasError() || (!isFinished() && !evenIfRemaining)){
206216
#ifdef DEBUG_UPDATER
207217
DEBUG_UPDATER.printf_P(PSTR("premature end: res:%u, pos:%zu/%zu\n"), getError(), progress(), _size);
208218
#endif
209-
210219
_reset();
211220
return false;
212221
}
@@ -226,6 +235,7 @@ bool UpdaterClass::end(bool evenIfRemaining){
226235
#endif
227236
if (sigLen != _verify->length()) {
228237
_setError(UPDATE_ERROR_SIGN);
238+
_reset();
229239
return false;
230240
}
231241

@@ -251,6 +261,7 @@ bool UpdaterClass::end(bool evenIfRemaining){
251261
uint8_t *sig = (uint8_t*)malloc(sigLen);
252262
if (!sig) {
253263
_setError(UPDATE_ERROR_SIGN);
264+
_reset();
254265
return false;
255266
}
256267
ESP.flashRead(_startAddress + binSize, (uint32_t *)sig, sigLen);
@@ -262,9 +273,12 @@ bool UpdaterClass::end(bool evenIfRemaining){
262273
DEBUG_UPDATER.printf("\n");
263274
#endif
264275
if (!_verify->verify(_hash, (void *)sig, sigLen)) {
276+
free(sig);
265277
_setError(UPDATE_ERROR_SIGN);
278+
_reset();
266279
return false;
267280
}
281+
free(sig);
268282
#ifdef DEBUG_UPDATER
269283
DEBUG_UPDATER.printf_P(PSTR("[Updater] Signature matches\n"));
270284
#endif

cores/esp8266/Updater.h

+1
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ class UpdaterClass {
5353
typedef std::function<void(size_t, size_t)> THandlerFunction_Progress;
5454

5555
UpdaterClass();
56+
~UpdaterClass();
5657

5758
/* Optionally add a cryptographic signature verification hash and method */
5859
void installSignature(UpdaterHashClass *hash, UpdaterVerifyClass *verify) { _hash = hash; _verify = verify; }

libraries/ESP8266WiFi/src/BearSSLHelpers.cpp

+17-3
Original file line numberDiff line numberDiff line change
@@ -870,9 +870,9 @@ uint32_t SigningVerifier::length()
870870
}
871871
}
872872

873-
bool SigningVerifier::verify(UpdaterHashClass *hash, const void *signature, uint32_t signatureLen) {
874-
if (!_pubKey || !hash || !signature || signatureLen != length()) return false;
875-
873+
// We need to use the 2nd stack to do a verification, so do the thunk
874+
// directly inside the class function for ease of use.
875+
extern "C" bool SigningVerifier_verify(PublicKey *_pubKey, UpdaterHashClass *hash, const void *signature, uint32_t signatureLen) {
876876
if (_pubKey->isRSA()) {
877877
bool ret;
878878
unsigned char vrf[hash->len()];
@@ -890,6 +890,20 @@ bool SigningVerifier::verify(UpdaterHashClass *hash, const void *signature, uint
890890
}
891891
};
892892

893+
#if !CORE_MOCK
894+
make_stack_thunk(SigningVerifier_verify);
895+
extern "C" bool thunk_SigningVerifier_verify(PublicKey *_pubKey, UpdaterHashClass *hash, const void *signature, uint32_t signatureLen);
896+
#endif
897+
898+
bool SigningVerifier::verify(UpdaterHashClass *hash, const void *signature, uint32_t signatureLen) {
899+
if (!_pubKey || !hash || !signature || signatureLen != length()) return false;
900+
#if !CORE_MOCK
901+
return thunk_SigningVerifier_verify(_pubKey, hash, signature, signatureLen);
902+
#else
903+
return SigningVerifier_verify(_pubKey, hash, signature, signatureLen);
904+
#endif
905+
}
906+
893907
#if !CORE_MOCK
894908

895909
// Second stack thunked helpers

0 commit comments

Comments
 (0)