TLS support for private keys on ESP32

This commit is contained in:
Stephan Hadinger 2021-03-30 19:17:03 +02:00
parent d010e16ab6
commit c524124e1e
2 changed files with 44 additions and 2 deletions

View File

@ -260,6 +260,7 @@ const uint16_t LOG_BUFFER_SIZE = 4000; // Max number of characters in lo
#define TASM_FILE_SETTINGS_LKG "/.settings.lkg" // Last Known Good Settings binary blob
#define TASM_FILE_DRIVER "/.drvset%03d"
#define TASM_FILE_SENSOR "/.snsset%03d"
#define TASM_FILE_TLSKEY "/tlskey" // TLS private key
#define TASM_FILE_ZIGBEE "/zb" // Zigbee settings blob as used by CC2530 on ESP32
#define TASM_FILE_AUTOEXEC "/autoexec.bat" // Commands executed after restart
#define TASM_FILE_CONFIG "/config.sys" // Settings executed after restart

View File

@ -1138,16 +1138,21 @@ void CmndStateRetain(void) {
\*********************************************************************************************/
#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT)
#ifdef ESP32
static uint8_t * tls_spi_start = nullptr;
const static size_t tls_spi_len = 0x0400; // 1kb blocs
const static size_t tls_block_offset = 0x0000; // don't need offset in FS
#else
// const static uint16_t tls_spi_start_sector = EEPROM_LOCATION + 4; // 0xXXFF
// const static uint8_t* tls_spi_start = (uint8_t*) ((tls_spi_start_sector * SPI_FLASH_SEC_SIZE) + 0x40200000); // 0x40XFF000
const static uint16_t tls_spi_start_sector = 0xFF; // Force last bank of first MB
const static uint8_t* tls_spi_start = (uint8_t*) 0x402FF000; // 0x402FF000
const static size_t tls_spi_len = 0x1000; // 4kb blocs
const static size_t tls_block_offset = 0x0400;
#endif
const static size_t tls_block_len = 0x0400; // 1kb
const static size_t tls_obj_store_offset = tls_block_offset + sizeof(tls_dir_t);
inline void TlsEraseBuffer(uint8_t *buffer) {
memset(buffer + tls_block_offset, 0xFF, tls_block_len);
}
@ -1166,6 +1171,22 @@ static br_x509_certificate CHAIN[] = {
// load a copy of the tls_dir from flash into ram
// and calculate the appropriate data structures for AWS_IoT_Private_Key and AWS_IoT_Client_Certificate
void loadTlsDir(void) {
#ifdef ESP32
// We load the file in RAM and use it as if it was in Flash. The buffer is never deallocated once we loaded TLS keys
AWS_IoT_Private_Key = nullptr;
AWS_IoT_Client_Certificate = nullptr;
if (TfsFileExists(TASM_FILE_TLSKEY)) {
if (tls_spi_start == nullptr){
tls_spi_start = (uint8_t*) malloc(tls_block_len);
if (tls_spi_start == nullptr) {
return;
}
}
TfsLoadFile(TASM_FILE_TLSKEY, tls_spi_start, tls_block_len);
} else {
return; // file does not exist, do nothing
}
#endif
memcpy_P(&tls_dir, tls_spi_start + tls_block_offset, sizeof(tls_dir));
// calculate the addresses for Key and Cert in Flash
@ -1204,7 +1225,11 @@ void CmndTlsKey(void) {
AddLog(LOG_LEVEL_ERROR, ALLOCATE_ERROR);
return;
}
memcpy_P(spi_buffer, tls_spi_start, tls_spi_len);
if (tls_spi_start != nullptr) { // safeguard for ESP32
memcpy_P(spi_buffer, tls_spi_start, tls_spi_len);
} else {
memset(spi_buffer, 0, tls_spi_len); // safeguard for ESP32, removed by compiler for ESP8266
}
// remove any white space from the base64
RemoveSpace(XdrvMailbox.data);
@ -1229,10 +1254,17 @@ void CmndTlsKey(void) {
// address of writable tls_dir in buffer
tls_dir_write = (tls_dir_t*) (spi_buffer + tls_block_offset);
bool save_file = false; // for ESP32, do we need to write file
if (1 == XdrvMailbox.index) {
// Try to write Private key
// Start by erasing all
#ifdef ESP32
if (TfsFileExists(TASM_FILE_TLSKEY)) {
TfsDeleteFile(TASM_FILE_TLSKEY); // delete file
}
#else
TlsEraseBuffer(spi_buffer); // Erase any previously stored data
#endif
if (bin_len > 0) {
if (bin_len != 32) {
// no private key was previously stored, abort
@ -1246,6 +1278,7 @@ void CmndTlsKey(void) {
entry->start = 0;
entry->len = bin_len;
memcpy(spi_buffer + tls_obj_store_offset + entry->start, bin_buf, entry->len);
save_file = true;
} else {
// if lenght is zero, simply erase this SPI flash area
}
@ -1270,11 +1303,18 @@ void CmndTlsKey(void) {
entry->start = (tls_dir_write->entry[0].start + tls_dir_write->entry[0].len + 3) & ~0x03; // align to 4 bytes boundary
entry->len = bin_len;
memcpy(spi_buffer + tls_obj_store_offset + entry->start, bin_buf, entry->len);
save_file = true;
}
#ifdef ESP32
if (save_file) {
TfsSaveFile(TASM_FILE_TLSKEY, spi_buffer, tls_spi_len);
}
#else
if (ESP.flashEraseSector(tls_spi_start_sector)) {
ESP.flashWrite(tls_spi_start_sector * SPI_FLASH_SEC_SIZE, (uint32_t*) spi_buffer, SPI_FLASH_SEC_SIZE);
}
#endif
free(spi_buffer);
free(bin_buf);
}
@ -1295,6 +1335,7 @@ uint32_t bswap32(uint32_t x) {
((x >> 24) & 0x000000ff );
}
void CmndTlsDump(void) {
if (tls_spi_start == nullptr) { return; } // safeguard for ESP32, removed by compiler for ESP8266
uint32_t start = (uint32_t)tls_spi_start + tls_block_offset;
uint32_t end = start + tls_block_len -1;
for (uint32_t pos = start; pos < end; pos += 0x10) {