9
9
#include " spi_flash_mmap.h"
10
10
#include " esp_ota_ops.h"
11
11
#include " esp_image_format.h"
12
+ #ifndef UPDATE_NOCRYPT
13
+ #include " mbedtls/aes.h"
14
+ #endif /* UPDATE_NOCRYPT */
12
15
13
16
static const char *_err2str (uint8_t _error) {
14
17
if (_error == UPDATE_ERROR_OK) {
@@ -37,6 +40,10 @@ static const char *_err2str(uint8_t _error) {
37
40
return (" Bad Argument" );
38
41
} else if (_error == UPDATE_ERROR_ABORT) {
39
42
return (" Aborted" );
43
+ #ifndef UPDATE_NOCRYPT
44
+ } else if (_error == UPDATE_ERROR_DECRYPT) {
45
+ return (" Decryption error" );
46
+ #endif /* UPDATE_NOCRYPT */
40
47
}
41
48
return (" UNKNOWN" );
42
49
}
@@ -64,7 +71,15 @@ bool UpdateClass::_enablePartition(const esp_partition_t *partition) {
64
71
}
65
72
66
73
UpdateClass::UpdateClass ()
67
- : _error(0 ), _buffer(0 ), _bufferLen(0 ), _size(0 ), _progress_callback(NULL ), _progress(0 ), _paroffset(0 ), _command(U_FLASH), _partition(NULL ) {}
74
+ : _error (0 ),
75
+ #ifndef UPDATE_NOCRYPT
76
+ _cryptKey (0 ), _cryptBuffer (0 ),
77
+ #endif /* UPDATE_NOCRYPT */
78
+ _buffer (0 ), _skipBuffer (0 ), _bufferLen (0 ), _size (0 ), _progress_callback (NULL ), _progress (0 ), _paroffset (0 ), _command (U_FLASH), _partition (NULL )
79
+ #ifndef UPDATE_NOCRYPT
80
+ , _cryptMode (U_AES_DECRYPT_AUTO), _cryptAddress (0 ), _cryptCfg (0xf )
81
+ #endif /* UPDATE_NOCRYPT */
82
+ {}
68
83
69
84
UpdateClass &UpdateClass::onProgress (THandlerFunction_Progress fn) {
70
85
_progress_callback = fn;
@@ -79,6 +94,9 @@ void UpdateClass::_reset() {
79
94
delete[] _skipBuffer;
80
95
}
81
96
97
+ #ifndef UPDATE_NOCRYPT
98
+ _cryptBuffer = nullptr ;
99
+ #endif /* UPDATE_NOCRYPT */
82
100
_buffer = nullptr ;
83
101
_skipBuffer = nullptr ;
84
102
_bufferLen = 0 ;
@@ -170,6 +188,50 @@ bool UpdateClass::begin(size_t size, int command, int ledPin, uint8_t ledOn, con
170
188
return true ;
171
189
}
172
190
191
+ #ifndef UPDATE_NOCRYPT
192
+ bool UpdateClass::setupCrypt (const uint8_t *cryptKey, size_t cryptAddress, uint8_t cryptConfig, int cryptMode) {
193
+ if (setCryptKey (cryptKey)) {
194
+ if (setCryptMode (cryptMode)) {
195
+ setCryptAddress (cryptAddress);
196
+ setCryptConfig (cryptConfig);
197
+ return true ;
198
+ }
199
+ }
200
+ return false ;
201
+ }
202
+
203
+ bool UpdateClass::setCryptKey (const uint8_t *cryptKey) {
204
+ if (!cryptKey) {
205
+ if (_cryptKey) {
206
+ delete[] _cryptKey;
207
+ _cryptKey = 0 ;
208
+ log_d (" AES key unset" );
209
+ }
210
+ return false ; // key cleared, no key to decrypt with
211
+ }
212
+ // initialize
213
+ if (!_cryptKey) {
214
+ _cryptKey = new (std::nothrow) uint8_t [ENCRYPTED_KEY_SIZE];
215
+ }
216
+ if (!_cryptKey) {
217
+ log_e (" new failed" );
218
+ return false ;
219
+ }
220
+ memcpy (_cryptKey, cryptKey, ENCRYPTED_KEY_SIZE);
221
+ return true ;
222
+ }
223
+
224
+ bool UpdateClass::setCryptMode (const int cryptMode) {
225
+ if (cryptMode >= U_AES_DECRYPT_NONE && cryptMode <= U_AES_DECRYPT_ON) {
226
+ _cryptMode = cryptMode;
227
+ } else {
228
+ log_e (" bad crypt mode argument %i" , cryptMode);
229
+ return false ;
230
+ }
231
+ return true ;
232
+ }
233
+ #endif /* UPDATE_NOCRYPT */
234
+
173
235
void UpdateClass::_abort (uint8_t err) {
174
236
_reset ();
175
237
_error = err;
@@ -179,7 +241,144 @@ void UpdateClass::abort() {
179
241
_abort (UPDATE_ERROR_ABORT);
180
242
}
181
243
244
+ #ifndef UPDATE_NOCRYPT
245
+ void UpdateClass::_cryptKeyTweak (size_t cryptAddress, uint8_t *tweaked_key) {
246
+ memcpy (tweaked_key, _cryptKey, ENCRYPTED_KEY_SIZE);
247
+ if (_cryptCfg == 0 ) {
248
+ return ; // no tweaking needed, use crypt key as-is
249
+ }
250
+
251
+ const uint8_t pattern[] = {23 , 23 , 23 , 14 , 23 , 23 , 23 , 12 , 23 , 23 , 23 , 10 , 23 , 23 , 23 , 8 };
252
+ int pattern_idx = 0 ;
253
+ int key_idx = 0 ;
254
+ int bit_len = 0 ;
255
+ uint32_t tweak = 0 ;
256
+ cryptAddress &= 0x00ffffe0 ; // bit 23-5
257
+ cryptAddress <<= 8 ; // bit23 shifted to bit31(MSB)
258
+ while (pattern_idx < sizeof (pattern)) {
259
+ tweak = cryptAddress << (23 - pattern[pattern_idx]); // bit shift for small patterns
260
+ // alternative to: tweak = rotl32(tweak,8 - bit_len);
261
+ tweak = (tweak << (8 - bit_len)) | (tweak >> (24 + bit_len)); // rotate to line up with end of previous tweak bits
262
+ bit_len += pattern[pattern_idx++] - 4 ; // add number of bits in next pattern(23-4 = 19bits = 23bit to 5bit)
263
+ while (bit_len > 7 ) {
264
+ tweaked_key[key_idx++] ^= tweak; // XOR byte
265
+ // alternative to: tweak = rotl32(tweak, 8);
266
+ tweak = (tweak << 8 ) | (tweak >> 24 ); // compiler should optimize to use rotate(fast)
267
+ bit_len -= 8 ;
268
+ }
269
+ tweaked_key[key_idx] ^= tweak; // XOR remaining bits, will XOR zeros if no remaining bits
270
+ }
271
+ if (_cryptCfg == 0xf ) {
272
+ return ; // return with fully tweaked key
273
+ }
274
+
275
+ // some of tweaked key bits need to be restore back to crypt key bits
276
+ const uint8_t cfg_bits[] = {67 , 65 , 63 , 61 };
277
+ key_idx = 0 ;
278
+ pattern_idx = 0 ;
279
+ while (key_idx < ENCRYPTED_KEY_SIZE) {
280
+ bit_len += cfg_bits[pattern_idx];
281
+ if ((_cryptCfg & (1 << pattern_idx)) == 0 ) { // restore crypt key bits
282
+ while (bit_len > 0 ) {
283
+ if (bit_len > 7 || ((_cryptCfg & (2 << pattern_idx)) == 0 )) { // restore a crypt key byte
284
+ tweaked_key[key_idx] = _cryptKey[key_idx];
285
+ } else { // MSBits restore crypt key bits, LSBits keep as tweaked bits
286
+ tweaked_key[key_idx] &= (0xff >> bit_len);
287
+ tweaked_key[key_idx] |= (_cryptKey[key_idx] & (~(0xff >> bit_len)));
288
+ }
289
+ key_idx++;
290
+ bit_len -= 8 ;
291
+ }
292
+ } else { // keep tweaked key bits
293
+ while (bit_len > 0 ) {
294
+ if (bit_len < 8 && ((_cryptCfg & (2 << pattern_idx)) == 0 )) { // MSBits keep as tweaked bits, LSBits restore crypt key bits
295
+ tweaked_key[key_idx] &= (~(0xff >> bit_len));
296
+ tweaked_key[key_idx] |= (_cryptKey[key_idx] & (0xff >> bit_len));
297
+ }
298
+ key_idx++;
299
+ bit_len -= 8 ;
300
+ }
301
+ }
302
+ pattern_idx++;
303
+ }
304
+ }
305
+
306
+ bool UpdateClass::_decryptBuffer () {
307
+ if (!_cryptKey) {
308
+ log_w (" AES key not set" );
309
+ return false ;
310
+ }
311
+ if (_bufferLen % ENCRYPTED_BLOCK_SIZE != 0 ) {
312
+ log_e (" buffer size error" );
313
+ return false ;
314
+ }
315
+ if (!_cryptBuffer) {
316
+ _cryptBuffer = new (std::nothrow) uint8_t [ENCRYPTED_BLOCK_SIZE];
317
+ }
318
+ if (!_cryptBuffer) {
319
+ log_e (" new failed" );
320
+ return false ;
321
+ }
322
+ uint8_t tweaked_key[ENCRYPTED_KEY_SIZE]; // tweaked crypt key
323
+ int done = 0 ;
324
+
325
+ /*
326
+ Mbedtls functions will be replaced with esp_aes functions when hardware acceleration is available
327
+
328
+ To Do:
329
+ Replace mbedtls for the cases where there's no hardware acceleration
330
+ */
331
+
332
+ mbedtls_aes_context ctx; // initialize AES
333
+ mbedtls_aes_init (&ctx);
334
+ while ((_bufferLen - done) >= ENCRYPTED_BLOCK_SIZE) {
335
+ for (int i = 0 ; i < ENCRYPTED_BLOCK_SIZE; i++) {
336
+ _cryptBuffer[(ENCRYPTED_BLOCK_SIZE - 1 ) - i] = _buffer[i + done]; // reverse order 16 bytes to decrypt
337
+ }
338
+ if (((_cryptAddress + _progress + done) % ENCRYPTED_TWEAK_BLOCK_SIZE) == 0 || done == 0 ) {
339
+ _cryptKeyTweak (_cryptAddress + _progress + done, tweaked_key); // update tweaked crypt key
340
+ if (mbedtls_aes_setkey_enc (&ctx, tweaked_key, 256 )) {
341
+ return false ;
342
+ }
343
+ if (mbedtls_aes_setkey_dec (&ctx, tweaked_key, 256 )) {
344
+ return false ;
345
+ }
346
+ }
347
+ if (mbedtls_aes_crypt_ecb (&ctx, MBEDTLS_AES_ENCRYPT, _cryptBuffer, _cryptBuffer)) { // use MBEDTLS_AES_ENCRYPT to decrypt flash code
348
+ return false ;
349
+ }
350
+ for (int i = 0 ; i < ENCRYPTED_BLOCK_SIZE; i++) {
351
+ _buffer[i + done] = _cryptBuffer[(ENCRYPTED_BLOCK_SIZE - 1 ) - i]; // reverse order 16 bytes from decrypt
352
+ }
353
+ done += ENCRYPTED_BLOCK_SIZE;
354
+ }
355
+ return true ;
356
+ }
357
+ #endif /* UPDATE_NOCRYPT */
358
+
182
359
bool UpdateClass::_writeBuffer () {
360
+ #ifndef UPDATE_NOCRYPT
361
+ // first bytes of loading image, check to see if loading image needs decrypting
362
+ if (!_progress) {
363
+ _cryptMode &= U_AES_DECRYPT_MODE_MASK;
364
+ if ((_cryptMode == U_AES_DECRYPT_ON) || ((_command == U_FLASH) && (_cryptMode & U_AES_DECRYPT_AUTO) && (_buffer[0 ] != ESP_IMAGE_HEADER_MAGIC))) {
365
+ _cryptMode |= U_AES_IMAGE_DECRYPTING_BIT; // set to decrypt the loading image
366
+ log_d (" Decrypting OTA Image" );
367
+ }
368
+ }
369
+
370
+ if (!_target_md5_decrypted) {
371
+ _md5.add (_buffer, _bufferLen);
372
+ }
373
+
374
+ // check if data in buffer needs decrypting
375
+ if (_cryptMode & U_AES_IMAGE_DECRYPTING_BIT) {
376
+ if (!_decryptBuffer ()) {
377
+ _abort (UPDATE_ERROR_DECRYPT);
378
+ return false ;
379
+ }
380
+ }
381
+ #endif /* UPDATE_NOCRYPT */
183
382
// first bytes of new firmware
184
383
uint8_t skip = 0 ;
185
384
if (!_progress && _command == U_FLASH) {
@@ -229,7 +428,13 @@ bool UpdateClass::_writeBuffer() {
229
428
if (!_progress && _command == U_FLASH) {
230
429
_buffer[0 ] = ESP_IMAGE_HEADER_MAGIC;
231
430
}
232
- _md5.add (_buffer, _bufferLen);
431
+ #ifndef UPDATE_NOCRYPT
432
+ if (_target_md5_decrypted) {
433
+ #endif /* UPDATE_NOCRYPT */
434
+ _md5.add (_buffer, _bufferLen);
435
+ #ifndef UPDATE_NOCRYPT
436
+ }
437
+ #endif /* UPDATE_NOCRYPT */
233
438
_progress += _bufferLen;
234
439
_bufferLen = 0 ;
235
440
if (_progress_callback) {
@@ -271,12 +476,19 @@ bool UpdateClass::_verifyEnd() {
271
476
return false ;
272
477
}
273
478
274
- bool UpdateClass::setMD5 (const char *expected_md5) {
479
+ bool UpdateClass::setMD5 (const char *expected_md5
480
+ #ifndef UPDATE_NOCRYPT
481
+ ,bool calc_post_decryption
482
+ #endif /* UPDATE_NOCRYPT */
483
+ ) {
275
484
if (strlen (expected_md5) != 32 ) {
276
485
return false ;
277
486
}
278
487
_target_md5 = expected_md5;
279
488
_target_md5.toLowerCase ();
489
+ #ifndef UPDATE_NOCRYPT
490
+ _target_md5_decrypted = calc_post_decryption;
491
+ #endif /* UPDATE_NOCRYPT */
280
492
return true ;
281
493
}
282
494
@@ -349,10 +561,16 @@ size_t UpdateClass::writeStream(Stream &data) {
349
561
return 0 ;
350
562
}
351
563
352
- if (!_verifyHeader (data.peek ())) {
353
- _reset ();
354
- return 0 ;
564
+ #ifndef UPDATE_NOCRYPT
565
+ if (_command == U_FLASH && !_cryptMode) {
566
+ #endif /* UPDATE_NOCRYPT */
567
+ if (!_verifyHeader (data.peek ())) {
568
+ _reset ();
569
+ return 0 ;
570
+ }
571
+ #ifndef UPDATE_NOCRYPT
355
572
}
573
+ #endif /* UPDATE_NOCRYPT */
356
574
357
575
if (_ledPin != -1 ) {
358
576
pinMode (_ledPin, OUTPUT);
0 commit comments