Skip to content

Revert crypt update PR #5807 #326

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Feb 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 1 addition & 48 deletions libraries/Update/src/Update.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
#include <MD5Builder.h>
#include <functional>
#include "esp_partition.h"
#include "aes/esp_aes.h"

#define UPDATE_ERROR_OK (0)
#define UPDATE_ERROR_WRITE (1)
Expand All @@ -20,23 +19,14 @@
#define UPDATE_ERROR_NO_PARTITION (10)
#define UPDATE_ERROR_BAD_ARGUMENT (11)
#define UPDATE_ERROR_ABORT (12)
#define UPDATE_ERROR_DECRYPT (13)

#define UPDATE_SIZE_UNKNOWN 0xFFFFFFFF

#define U_FLASH 0
#define U_SPIFFS 100
#define U_AUTH 200

#define ENCRYPTED_BLOCK_SIZE 16
#define ENCRYPTED_TWEAK_BLOCK_SIZE 32
#define ENCRYPTED_KEY_SIZE 32

#define U_AES_DECRYPT_NONE 0
#define U_AES_DECRYPT_AUTO 1
#define U_AES_DECRYPT_ON 2
#define U_AES_DECRYPT_MODE_MASK 3
#define U_AES_IMAGE_DECRYPTING_BIT 4
#define ENCRYPTED_BLOCK_SIZE 16

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

/*
Setup decryption configuration
Crypt Key is 32bytes(256bits) block of data, use the same key as used to encrypt image file
Crypt Address, use the same value as used to encrypt image file
Crypt Config, use the same value as used to encrypt image file
Crypt Mode, used to select if image files should be decrypted or not
*/
bool setupCrypt(const uint8_t *cryptKey=0, size_t cryptAddress=0, uint8_t cryptConfig=0xf, int cryptMode=U_AES_DECRYPT_AUTO);

/*
Writes a buffer to the flash and increments the address
Returns the amount written
Expand Down Expand Up @@ -94,26 +75,6 @@ class UpdateClass {
*/
bool end(bool evenIfRemaining = false);

/*
sets AES256 key(32 bytes) used for decrypting image file
*/
bool setCryptKey(const uint8_t *cryptKey);

/*
sets crypt mode used on image files
*/
bool setCryptMode(const int cryptMode);

/*
sets address used for decrypting image file
*/
void setCryptAddress(const size_t cryptAddress){ _cryptAddress = cryptAddress & 0x00fffff0; }

/*
sets crypt config used for decrypting image file
*/
void setCryptConfig(const uint8_t cryptConfig){ _cryptCfg = cryptConfig & 0x0f; }

/*
Aborts the running update
*/
Expand Down Expand Up @@ -204,8 +165,6 @@ class UpdateClass {
private:
void _reset();
void _abort(uint8_t err);
void _cryptKeyTweak(size_t cryptAddress, uint8_t *tweaked_key);
bool _decryptBuffer();
bool _writeBuffer();
bool _verifyHeader(uint8_t data);
bool _verifyEnd();
Expand All @@ -214,8 +173,6 @@ class UpdateClass {


uint8_t _error;
uint8_t *_cryptKey;
uint8_t *_cryptBuffer;
uint8_t *_buffer;
uint8_t *_skipBuffer;
size_t _bufferLen;
Expand All @@ -231,10 +188,6 @@ class UpdateClass {

int _ledPin;
uint8_t _ledOn;

uint8_t _cryptMode;
size_t _cryptAddress;
uint8_t _cryptCfg;
};

#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_UPDATE)
Expand Down
163 changes: 0 additions & 163 deletions libraries/Update/src/Updater.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ static const char * _err2str(uint8_t _error){
return ("Bad Argument");
} else if(_error == UPDATE_ERROR_ABORT){
return ("Aborted");
} else if(_error == UPDATE_ERROR_DECRYPT){
return ("Decryption error");
}
return ("UNKNOWN");
}
Expand Down Expand Up @@ -61,20 +59,14 @@ bool UpdateClass::_enablePartition(const esp_partition_t* partition){

UpdateClass::UpdateClass()
: _error(0)
, _cryptKey(0)
, _cryptBuffer(0)
, _buffer(0)
, _skipBuffer(0)
, _bufferLen(0)
, _size(0)
, _progress_callback(NULL)
, _progress(0)
, _paroffset(0)
, _command(U_FLASH)
, _partition(NULL)
, _cryptMode(U_AES_DECRYPT_AUTO)
, _cryptAddress(0)
, _cryptCfg(0xf)
{
}

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

_cryptBuffer = nullptr;
_buffer = nullptr;
_skipBuffer = nullptr;
_bufferLen = 0;
Expand Down Expand Up @@ -185,48 +176,6 @@ bool UpdateClass::begin(size_t size, int command, int ledPin, uint8_t ledOn, con
return true;
}

bool UpdateClass::setupCrypt(const uint8_t *cryptKey, size_t cryptAddress, uint8_t cryptConfig, int cryptMode){
if(setCryptKey(cryptKey)){
if(setCryptMode(cryptMode)){
setCryptAddress(cryptAddress);
setCryptConfig(cryptConfig);
return true;
}
}
return false;
}

bool UpdateClass::setCryptKey(const uint8_t *cryptKey){
if(!cryptKey){
if (_cryptKey){
delete[] _cryptKey;
_cryptKey = 0;
log_d("AES key unset");
}
return false; //key cleared, no key to decrypt with
}
//initialize
if(!_cryptKey){
_cryptKey = new (std::nothrow) uint8_t[ENCRYPTED_KEY_SIZE];
}
if(!_cryptKey){
log_e("new failed");
return false;
}
memcpy(_cryptKey, cryptKey, ENCRYPTED_KEY_SIZE);
return true;
}

bool UpdateClass::setCryptMode(const int cryptMode){
if(cryptMode >= U_AES_DECRYPT_NONE && cryptMode <= U_AES_DECRYPT_ON){
_cryptMode = cryptMode;
}else{
log_e("bad crypt mode arguement %i", cryptMode);
return false;
}
return true;
}

void UpdateClass::_abort(uint8_t err){
_reset();
_error = err;
Expand All @@ -236,119 +185,7 @@ void UpdateClass::abort(){
_abort(UPDATE_ERROR_ABORT);
}

void UpdateClass::_cryptKeyTweak(size_t cryptAddress, uint8_t *tweaked_key){
memcpy(tweaked_key, _cryptKey, ENCRYPTED_KEY_SIZE );
if(_cryptCfg == 0) return; //no tweaking needed, use crypt key as-is

const uint8_t pattern[] = { 23, 23, 23, 14, 23, 23, 23, 12, 23, 23, 23, 10, 23, 23, 23, 8 };
int pattern_idx = 0;
int key_idx = 0;
int bit_len = 0;
uint32_t tweak = 0;
cryptAddress &= 0x00ffffe0; //bit 23-5
cryptAddress <<= 8; //bit23 shifted to bit31(MSB)
while(pattern_idx < sizeof(pattern)){
tweak = cryptAddress<<(23 - pattern[pattern_idx]); //bit shift for small patterns
// alternative to: tweak = rotl32(tweak,8 - bit_len);
tweak = (tweak<<(8 - bit_len)) | (tweak>>(24 + bit_len)); //rotate to line up with end of previous tweak bits
bit_len += pattern[pattern_idx++] - 4; //add number of bits in next pattern(23-4 = 19bits = 23bit to 5bit)
while(bit_len > 7){
tweaked_key[key_idx++] ^= tweak; //XOR byte
// alternative to: tweak = rotl32(tweak, 8);
tweak = (tweak<<8) | (tweak>>24); //compiler should optimize to use rotate(fast)
bit_len -=8;
}
tweaked_key[key_idx] ^= tweak; //XOR remaining bits, will XOR zeros if no remaining bits
}
if(_cryptCfg == 0xf) return; //return with fully tweaked key

//some of tweaked key bits need to be restore back to crypt key bits
const uint8_t cfg_bits[] = { 67, 65, 63, 61 };
key_idx = 0;
pattern_idx = 0;
while(key_idx < ENCRYPTED_KEY_SIZE){
bit_len += cfg_bits[pattern_idx];
if( (_cryptCfg & (1<<pattern_idx)) == 0 ){ //restore crypt key bits
while(bit_len > 0){
if( bit_len > 7 || ((_cryptCfg & (2<<pattern_idx)) == 0) ){ //restore a crypt key byte
tweaked_key[key_idx] = _cryptKey[key_idx];
}else{ //MSBits restore crypt key bits, LSBits keep as tweaked bits
tweaked_key[key_idx] &= (0xff>>bit_len);
tweaked_key[key_idx] |= (_cryptKey[key_idx] & (~(0xff>>bit_len)) );
}
key_idx++;
bit_len -= 8;
}
}else{ //keep tweaked key bits
while(bit_len > 0){
if( bit_len <8 && ((_cryptCfg & (2<<pattern_idx)) == 0) ){ //MSBits keep as tweaked bits, LSBits restore crypt key bits
tweaked_key[key_idx] &= (~(0xff>>bit_len));
tweaked_key[key_idx] |= (_cryptKey[key_idx] & (0xff>>bit_len));
}
key_idx++;
bit_len -= 8;
}
}
pattern_idx++;
}
}

bool UpdateClass::_decryptBuffer(){
if(!_cryptKey){
log_w("AES key not set");
return false;
}
if(_bufferLen%ENCRYPTED_BLOCK_SIZE !=0 ){
log_e("buffer size error");
return false;
}
if(!_cryptBuffer){
_cryptBuffer = new (std::nothrow) uint8_t[ENCRYPTED_BLOCK_SIZE];
}
if(!_cryptBuffer){
log_e("new failed");
return false;
}
uint8_t tweaked_key[ENCRYPTED_KEY_SIZE]; //tweaked crypt key
int done = 0;

esp_aes_context ctx; //initialize AES
esp_aes_init( &ctx );
while((_bufferLen - done) >= ENCRYPTED_BLOCK_SIZE){
for(int i=0; i < ENCRYPTED_BLOCK_SIZE; i++) _cryptBuffer[(ENCRYPTED_BLOCK_SIZE - 1) - i] = _buffer[i + done]; //reverse order 16 bytes to decrypt
if( ((_cryptAddress + _progress + done) % ENCRYPTED_TWEAK_BLOCK_SIZE) == 0 || done == 0 ){
_cryptKeyTweak(_cryptAddress + _progress + done, tweaked_key); //update tweaked crypt key
if( esp_aes_setkey( &ctx, tweaked_key, 256 ) ){
return false;
}
}
if( esp_aes_crypt_ecb( &ctx, ESP_AES_ENCRYPT, _cryptBuffer, _cryptBuffer ) ){ //use ESP_AES_ENCRYPT to decrypt flash code
return false;
}
for(int i=0; i < ENCRYPTED_BLOCK_SIZE; i++) _buffer[i + done] = _cryptBuffer[(ENCRYPTED_BLOCK_SIZE - 1) - i]; //reverse order 16 bytes from decrypt
done += ENCRYPTED_BLOCK_SIZE;
}
return true;
}

bool UpdateClass::_writeBuffer(){
//first bytes of loading image, check to see if loading image needs decrypting
if(!_progress){
_cryptMode &= U_AES_DECRYPT_MODE_MASK;
if( ( _cryptMode == U_AES_DECRYPT_ON )
|| ((_command == U_FLASH) && (_cryptMode & U_AES_DECRYPT_AUTO) && (_buffer[0] != ESP_IMAGE_HEADER_MAGIC))
){
_cryptMode |= U_AES_IMAGE_DECRYPTING_BIT; //set to decrypt the loading image
log_d("Decrypting OTA Image");
}
}
//check if data in buffer needs decrypting
if( _cryptMode & U_AES_IMAGE_DECRYPTING_BIT ){
if( !_decryptBuffer() ){
_abort(UPDATE_ERROR_DECRYPT);
return false;
}
}
//first bytes of new firmware
uint8_t skip = 0;
if(!_progress && _command == U_FLASH){
Expand Down