Skip to content

Commit 22c3df0

Browse files
authored
Revert "Revert crypt update PR espressif#5807 (#326)"
This reverts commit a5fe8e6.
1 parent a5fe8e6 commit 22c3df0

File tree

2 files changed

+211
-1
lines changed

2 files changed

+211
-1
lines changed

Diff for: libraries/Update/src/Update.h

+48-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <MD5Builder.h>
66
#include <functional>
77
#include "esp_partition.h"
8+
#include "aes/esp_aes.h"
89

910
#define UPDATE_ERROR_OK (0)
1011
#define UPDATE_ERROR_WRITE (1)
@@ -19,14 +20,23 @@
1920
#define UPDATE_ERROR_NO_PARTITION (10)
2021
#define UPDATE_ERROR_BAD_ARGUMENT (11)
2122
#define UPDATE_ERROR_ABORT (12)
23+
#define UPDATE_ERROR_DECRYPT (13)
2224

2325
#define UPDATE_SIZE_UNKNOWN 0xFFFFFFFF
2426

2527
#define U_FLASH 0
2628
#define U_SPIFFS 100
2729
#define U_AUTH 200
2830

29-
#define ENCRYPTED_BLOCK_SIZE 16
31+
#define ENCRYPTED_BLOCK_SIZE 16
32+
#define ENCRYPTED_TWEAK_BLOCK_SIZE 32
33+
#define ENCRYPTED_KEY_SIZE 32
34+
35+
#define U_AES_DECRYPT_NONE 0
36+
#define U_AES_DECRYPT_AUTO 1
37+
#define U_AES_DECRYPT_ON 2
38+
#define U_AES_DECRYPT_MODE_MASK 3
39+
#define U_AES_IMAGE_DECRYPTING_BIT 4
3040

3141
#define SPI_SECTORS_PER_BLOCK 16 // usually large erase block is 32k/64k
3242
#define SPI_FLASH_BLOCK_SIZE (SPI_SECTORS_PER_BLOCK*SPI_FLASH_SEC_SIZE)
@@ -48,6 +58,15 @@ class UpdateClass {
4858
*/
4959
bool begin(size_t size=UPDATE_SIZE_UNKNOWN, int command = U_FLASH, int ledPin = -1, uint8_t ledOn = LOW, const char *label = NULL);
5060

61+
/*
62+
Setup decryption configuration
63+
Crypt Key is 32bytes(256bits) block of data, use the same key as used to encrypt image file
64+
Crypt Address, use the same value as used to encrypt image file
65+
Crypt Config, use the same value as used to encrypt image file
66+
Crypt Mode, used to select if image files should be decrypted or not
67+
*/
68+
bool setupCrypt(const uint8_t *cryptKey=0, size_t cryptAddress=0, uint8_t cryptConfig=0xf, int cryptMode=U_AES_DECRYPT_AUTO);
69+
5170
/*
5271
Writes a buffer to the flash and increments the address
5372
Returns the amount written
@@ -75,6 +94,26 @@ class UpdateClass {
7594
*/
7695
bool end(bool evenIfRemaining = false);
7796

97+
/*
98+
sets AES256 key(32 bytes) used for decrypting image file
99+
*/
100+
bool setCryptKey(const uint8_t *cryptKey);
101+
102+
/*
103+
sets crypt mode used on image files
104+
*/
105+
bool setCryptMode(const int cryptMode);
106+
107+
/*
108+
sets address used for decrypting image file
109+
*/
110+
void setCryptAddress(const size_t cryptAddress){ _cryptAddress = cryptAddress & 0x00fffff0; }
111+
112+
/*
113+
sets crypt config used for decrypting image file
114+
*/
115+
void setCryptConfig(const uint8_t cryptConfig){ _cryptCfg = cryptConfig & 0x0f; }
116+
78117
/*
79118
Aborts the running update
80119
*/
@@ -165,6 +204,8 @@ class UpdateClass {
165204
private:
166205
void _reset();
167206
void _abort(uint8_t err);
207+
void _cryptKeyTweak(size_t cryptAddress, uint8_t *tweaked_key);
208+
bool _decryptBuffer();
168209
bool _writeBuffer();
169210
bool _verifyHeader(uint8_t data);
170211
bool _verifyEnd();
@@ -173,6 +214,8 @@ class UpdateClass {
173214

174215

175216
uint8_t _error;
217+
uint8_t *_cryptKey;
218+
uint8_t *_cryptBuffer;
176219
uint8_t *_buffer;
177220
uint8_t *_skipBuffer;
178221
size_t _bufferLen;
@@ -188,6 +231,10 @@ class UpdateClass {
188231

189232
int _ledPin;
190233
uint8_t _ledOn;
234+
235+
uint8_t _cryptMode;
236+
size_t _cryptAddress;
237+
uint8_t _cryptCfg;
191238
};
192239

193240
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_UPDATE)

Diff for: libraries/Update/src/Updater.cpp

+163
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ static const char * _err2str(uint8_t _error){
3131
return ("Bad Argument");
3232
} else if(_error == UPDATE_ERROR_ABORT){
3333
return ("Aborted");
34+
} else if(_error == UPDATE_ERROR_DECRYPT){
35+
return ("Decryption error");
3436
}
3537
return ("UNKNOWN");
3638
}
@@ -59,14 +61,20 @@ bool UpdateClass::_enablePartition(const esp_partition_t* partition){
5961

6062
UpdateClass::UpdateClass()
6163
: _error(0)
64+
, _cryptKey(0)
65+
, _cryptBuffer(0)
6266
, _buffer(0)
67+
, _skipBuffer(0)
6368
, _bufferLen(0)
6469
, _size(0)
6570
, _progress_callback(NULL)
6671
, _progress(0)
6772
, _paroffset(0)
6873
, _command(U_FLASH)
6974
, _partition(NULL)
75+
, _cryptMode(U_AES_DECRYPT_AUTO)
76+
, _cryptAddress(0)
77+
, _cryptCfg(0xf)
7078
{
7179
}
7280

@@ -83,6 +91,7 @@ void UpdateClass::_reset() {
8391
delete[] _skipBuffer;
8492
}
8593

94+
_cryptBuffer = nullptr;
8695
_buffer = nullptr;
8796
_skipBuffer = nullptr;
8897
_bufferLen = 0;
@@ -176,6 +185,48 @@ bool UpdateClass::begin(size_t size, int command, int ledPin, uint8_t ledOn, con
176185
return true;
177186
}
178187

188+
bool UpdateClass::setupCrypt(const uint8_t *cryptKey, size_t cryptAddress, uint8_t cryptConfig, int cryptMode){
189+
if(setCryptKey(cryptKey)){
190+
if(setCryptMode(cryptMode)){
191+
setCryptAddress(cryptAddress);
192+
setCryptConfig(cryptConfig);
193+
return true;
194+
}
195+
}
196+
return false;
197+
}
198+
199+
bool UpdateClass::setCryptKey(const uint8_t *cryptKey){
200+
if(!cryptKey){
201+
if (_cryptKey){
202+
delete[] _cryptKey;
203+
_cryptKey = 0;
204+
log_d("AES key unset");
205+
}
206+
return false; //key cleared, no key to decrypt with
207+
}
208+
//initialize
209+
if(!_cryptKey){
210+
_cryptKey = new (std::nothrow) uint8_t[ENCRYPTED_KEY_SIZE];
211+
}
212+
if(!_cryptKey){
213+
log_e("new failed");
214+
return false;
215+
}
216+
memcpy(_cryptKey, cryptKey, ENCRYPTED_KEY_SIZE);
217+
return true;
218+
}
219+
220+
bool UpdateClass::setCryptMode(const int cryptMode){
221+
if(cryptMode >= U_AES_DECRYPT_NONE && cryptMode <= U_AES_DECRYPT_ON){
222+
_cryptMode = cryptMode;
223+
}else{
224+
log_e("bad crypt mode arguement %i", cryptMode);
225+
return false;
226+
}
227+
return true;
228+
}
229+
179230
void UpdateClass::_abort(uint8_t err){
180231
_reset();
181232
_error = err;
@@ -185,7 +236,119 @@ void UpdateClass::abort(){
185236
_abort(UPDATE_ERROR_ABORT);
186237
}
187238

239+
void UpdateClass::_cryptKeyTweak(size_t cryptAddress, uint8_t *tweaked_key){
240+
memcpy(tweaked_key, _cryptKey, ENCRYPTED_KEY_SIZE );
241+
if(_cryptCfg == 0) return; //no tweaking needed, use crypt key as-is
242+
243+
const uint8_t pattern[] = { 23, 23, 23, 14, 23, 23, 23, 12, 23, 23, 23, 10, 23, 23, 23, 8 };
244+
int pattern_idx = 0;
245+
int key_idx = 0;
246+
int bit_len = 0;
247+
uint32_t tweak = 0;
248+
cryptAddress &= 0x00ffffe0; //bit 23-5
249+
cryptAddress <<= 8; //bit23 shifted to bit31(MSB)
250+
while(pattern_idx < sizeof(pattern)){
251+
tweak = cryptAddress<<(23 - pattern[pattern_idx]); //bit shift for small patterns
252+
// alternative to: tweak = rotl32(tweak,8 - bit_len);
253+
tweak = (tweak<<(8 - bit_len)) | (tweak>>(24 + bit_len)); //rotate to line up with end of previous tweak bits
254+
bit_len += pattern[pattern_idx++] - 4; //add number of bits in next pattern(23-4 = 19bits = 23bit to 5bit)
255+
while(bit_len > 7){
256+
tweaked_key[key_idx++] ^= tweak; //XOR byte
257+
// alternative to: tweak = rotl32(tweak, 8);
258+
tweak = (tweak<<8) | (tweak>>24); //compiler should optimize to use rotate(fast)
259+
bit_len -=8;
260+
}
261+
tweaked_key[key_idx] ^= tweak; //XOR remaining bits, will XOR zeros if no remaining bits
262+
}
263+
if(_cryptCfg == 0xf) return; //return with fully tweaked key
264+
265+
//some of tweaked key bits need to be restore back to crypt key bits
266+
const uint8_t cfg_bits[] = { 67, 65, 63, 61 };
267+
key_idx = 0;
268+
pattern_idx = 0;
269+
while(key_idx < ENCRYPTED_KEY_SIZE){
270+
bit_len += cfg_bits[pattern_idx];
271+
if( (_cryptCfg & (1<<pattern_idx)) == 0 ){ //restore crypt key bits
272+
while(bit_len > 0){
273+
if( bit_len > 7 || ((_cryptCfg & (2<<pattern_idx)) == 0) ){ //restore a crypt key byte
274+
tweaked_key[key_idx] = _cryptKey[key_idx];
275+
}else{ //MSBits restore crypt key bits, LSBits keep as tweaked bits
276+
tweaked_key[key_idx] &= (0xff>>bit_len);
277+
tweaked_key[key_idx] |= (_cryptKey[key_idx] & (~(0xff>>bit_len)) );
278+
}
279+
key_idx++;
280+
bit_len -= 8;
281+
}
282+
}else{ //keep tweaked key bits
283+
while(bit_len > 0){
284+
if( bit_len <8 && ((_cryptCfg & (2<<pattern_idx)) == 0) ){ //MSBits keep as tweaked bits, LSBits restore crypt key bits
285+
tweaked_key[key_idx] &= (~(0xff>>bit_len));
286+
tweaked_key[key_idx] |= (_cryptKey[key_idx] & (0xff>>bit_len));
287+
}
288+
key_idx++;
289+
bit_len -= 8;
290+
}
291+
}
292+
pattern_idx++;
293+
}
294+
}
295+
296+
bool UpdateClass::_decryptBuffer(){
297+
if(!_cryptKey){
298+
log_w("AES key not set");
299+
return false;
300+
}
301+
if(_bufferLen%ENCRYPTED_BLOCK_SIZE !=0 ){
302+
log_e("buffer size error");
303+
return false;
304+
}
305+
if(!_cryptBuffer){
306+
_cryptBuffer = new (std::nothrow) uint8_t[ENCRYPTED_BLOCK_SIZE];
307+
}
308+
if(!_cryptBuffer){
309+
log_e("new failed");
310+
return false;
311+
}
312+
uint8_t tweaked_key[ENCRYPTED_KEY_SIZE]; //tweaked crypt key
313+
int done = 0;
314+
315+
esp_aes_context ctx; //initialize AES
316+
esp_aes_init( &ctx );
317+
while((_bufferLen - done) >= ENCRYPTED_BLOCK_SIZE){
318+
for(int i=0; i < ENCRYPTED_BLOCK_SIZE; i++) _cryptBuffer[(ENCRYPTED_BLOCK_SIZE - 1) - i] = _buffer[i + done]; //reverse order 16 bytes to decrypt
319+
if( ((_cryptAddress + _progress + done) % ENCRYPTED_TWEAK_BLOCK_SIZE) == 0 || done == 0 ){
320+
_cryptKeyTweak(_cryptAddress + _progress + done, tweaked_key); //update tweaked crypt key
321+
if( esp_aes_setkey( &ctx, tweaked_key, 256 ) ){
322+
return false;
323+
}
324+
}
325+
if( esp_aes_crypt_ecb( &ctx, ESP_AES_ENCRYPT, _cryptBuffer, _cryptBuffer ) ){ //use ESP_AES_ENCRYPT to decrypt flash code
326+
return false;
327+
}
328+
for(int i=0; i < ENCRYPTED_BLOCK_SIZE; i++) _buffer[i + done] = _cryptBuffer[(ENCRYPTED_BLOCK_SIZE - 1) - i]; //reverse order 16 bytes from decrypt
329+
done += ENCRYPTED_BLOCK_SIZE;
330+
}
331+
return true;
332+
}
333+
188334
bool UpdateClass::_writeBuffer(){
335+
//first bytes of loading image, check to see if loading image needs decrypting
336+
if(!_progress){
337+
_cryptMode &= U_AES_DECRYPT_MODE_MASK;
338+
if( ( _cryptMode == U_AES_DECRYPT_ON )
339+
|| ((_command == U_FLASH) && (_cryptMode & U_AES_DECRYPT_AUTO) && (_buffer[0] != ESP_IMAGE_HEADER_MAGIC))
340+
){
341+
_cryptMode |= U_AES_IMAGE_DECRYPTING_BIT; //set to decrypt the loading image
342+
log_d("Decrypting OTA Image");
343+
}
344+
}
345+
//check if data in buffer needs decrypting
346+
if( _cryptMode & U_AES_IMAGE_DECRYPTING_BIT ){
347+
if( !_decryptBuffer() ){
348+
_abort(UPDATE_ERROR_DECRYPT);
349+
return false;
350+
}
351+
}
189352
//first bytes of new firmware
190353
uint8_t skip = 0;
191354
if(!_progress && _command == U_FLASH){

0 commit comments

Comments
 (0)