From 6e73823eaad2d587598b1dbfa1bf4902cc2cfdeb Mon Sep 17 00:00:00 2001 From: 4rzael Date: Mon, 6 Jan 2025 09:56:00 +0100 Subject: [PATCH 1/7] Encrypted flash now works, but needs some cleaning up --- espflash/src/bin/espflash.rs | 9 ++++- espflash/src/cli/mod.rs | 2 ++ espflash/src/command.rs | 15 ++++++++- espflash/src/connection/reset.rs | 2 ++ espflash/src/elf.rs | 5 +++ espflash/src/flasher/mod.rs | 4 +++ espflash/src/image_format.rs | 6 ++++ espflash/src/targets/esp32.rs | 4 +-- espflash/src/targets/flash_target/esp32.rs | 39 ++++++++++++---------- 9 files changed, 65 insertions(+), 21 deletions(-) diff --git a/espflash/src/bin/espflash.rs b/espflash/src/bin/espflash.rs index f117b9ce..66ed4521 100644 --- a/espflash/src/bin/espflash.rs +++ b/espflash/src/bin/espflash.rs @@ -154,6 +154,8 @@ struct WriteBinArgs { /// Connection configuration #[clap(flatten)] connect_args: ConnectArgs, + #[arg(long)] + encrypt: bool, } fn main() -> Result<()> { @@ -357,7 +359,12 @@ fn write_bin(args: WriteBinArgs, config: &Config) -> Result<()> { let mut buffer = Vec::with_capacity(size.try_into().into_diagnostic()?); f.read_to_end(&mut buffer).into_diagnostic()?; - flasher.write_bin_to_flash(args.addr, &buffer, Some(&mut EspflashProgress::default()))?; + flasher.write_bin_to_flash( + args.addr, + &buffer, + Some(&mut EspflashProgress::default()), + args.encrypt, + )?; Ok(()) } diff --git a/espflash/src/cli/mod.rs b/espflash/src/cli/mod.rs index b4825ce9..bccb56bb 100644 --- a/espflash/src/cli/mod.rs +++ b/espflash/src/cli/mod.rs @@ -159,6 +159,8 @@ pub struct FlashArgs { /// External log processors to use (comma separated executables) #[arg(long, requires = "monitor")] pub processors: Option, + #[arg(long)] + pub encrypt: bool, } /// Operations for partitions tables diff --git a/espflash/src/command.rs b/espflash/src/command.rs index be91e504..10c00aa9 100644 --- a/espflash/src/command.rs +++ b/espflash/src/command.rs @@ -106,6 +106,7 @@ pub enum Command<'a> { block_size: u32, offset: u32, supports_encryption: bool, + perform_encryption: bool, }, FlashData { data: &'a [u8], @@ -163,6 +164,7 @@ pub enum Command<'a> { block_size: u32, offset: u32, supports_encryption: bool, + perform_encryption: bool, }, FlashDeflData { data: &'a [u8], @@ -237,6 +239,7 @@ impl Command<'_> { block_size, offset, supports_encryption, + perform_encryption, } => { begin_command( writer, @@ -245,6 +248,7 @@ impl Command<'_> { block_size, offset, supports_encryption, + perform_encryption, )?; } Command::FlashData { @@ -272,6 +276,7 @@ impl Command<'_> { block_size, offset, supports_encryption, + false, )?; } Command::MemData { @@ -352,6 +357,7 @@ impl Command<'_> { block_size, offset, supports_encryption, + perform_encryption, } => { begin_command( writer, @@ -360,6 +366,7 @@ impl Command<'_> { block_size, offset, supports_encryption, + perform_encryption, )?; } Command::FlashDeflData { @@ -441,7 +448,13 @@ fn begin_command( block_size: u32, offset: u32, supports_encryption: bool, + perform_encryption: bool, ) -> std::io::Result<()> { + assert!( + !(perform_encryption && !supports_encryption), + "Target does not support encryption, yet encryption is requested" + ); + #[derive(Zeroable, Pod, Copy, Clone, Debug)] #[repr(C)] struct BeginParams { @@ -456,7 +469,7 @@ fn begin_command( blocks, block_size, offset, - encrypted: 0, + encrypted: perform_encryption as u32, }; let bytes = bytes_of(¶ms); diff --git a/espflash/src/connection/reset.rs b/espflash/src/connection/reset.rs index 936f232a..ce7b9d7c 100644 --- a/espflash/src/connection/reset.rs +++ b/espflash/src/connection/reset.rs @@ -260,6 +260,7 @@ pub fn soft_reset( block_size: FLASH_WRITE_SIZE.try_into().unwrap(), offset, supports_encryption: false, + perform_encryption: false, }) })?; connection.with_timeout(CommandType::FlashEnd.timeout(), |connection| { @@ -278,6 +279,7 @@ pub fn soft_reset( block_size: FLASH_WRITE_SIZE.try_into().unwrap(), offset, supports_encryption: false, + perform_encryption: false, }) })?; connection.with_timeout(CommandType::FlashEnd.timeout(), |connection| { diff --git a/espflash/src/elf.rs b/espflash/src/elf.rs index 3f0f3e34..52c25b4f 100644 --- a/espflash/src/elf.rs +++ b/espflash/src/elf.rs @@ -237,6 +237,8 @@ pub struct RomSegment<'a> { pub addr: u32, /// Segment data pub data: Cow<'a, [u8]>, + /// Whether the segment shall be encrypted before being writen + pub encrypt: bool, } impl<'a> RomSegment<'a> { @@ -247,15 +249,18 @@ impl<'a> RomSegment<'a> { RomSegment { addr: self.addr, data: Cow::Borrowed(self.data.as_ref()), + encrypt: self.encrypt, } } } impl<'a> From> for RomSegment<'a> { fn from(segment: CodeSegment<'a>) -> Self { + todo!("Remove this conversion, as we cannot easily assume encryption requirements ?"); RomSegment { addr: segment.addr, data: segment.data, + encrypt: false, } } } diff --git a/espflash/src/flasher/mod.rs b/espflash/src/flasher/mod.rs index d57fdf55..5529a3e9 100644 --- a/espflash/src/flasher/mod.rs +++ b/espflash/src/flasher/mod.rs @@ -674,6 +674,7 @@ impl Flasher { RomSegment { addr: text_addr, data: Cow::Borrowed(&text), + encrypt: false, }, &mut None, ) @@ -688,6 +689,7 @@ impl Flasher { RomSegment { addr: data_addr, data: Cow::Borrowed(&data), + encrypt: false, }, &mut None, ) @@ -995,10 +997,12 @@ impl Flasher { addr: u32, data: &[u8], progress: Option<&mut dyn ProgressCallbacks>, + encrypt: bool, ) -> Result<(), Error> { let segment = RomSegment { addr, data: Cow::from(data), + encrypt, }; self.write_bins_to_flash(&[segment], progress)?; diff --git a/espflash/src/image_format.rs b/espflash/src/image_format.rs index 2af83ece..79b81a3d 100644 --- a/espflash/src/image_format.rs +++ b/espflash/src/image_format.rs @@ -269,6 +269,7 @@ impl<'a> IdfBootloaderFormat<'a> { let flash_segment = RomSegment { addr: target_app_partition.offset(), data: Cow::Owned(data), + encrypt: target_app_partition.encrypted(), }; // If the user did not specify a partition offset, we need to assume that the @@ -301,16 +302,21 @@ impl<'a> IdfBootloaderFormat<'a> { let bootloader_segment = RomSegment { addr: self.params.boot_addr, data: Cow::Borrowed(&self.bootloader), + // We use the app encryption setting for bootloader too. + // Am other (better ?) approach might be to check the target Efuses instead. + encrypt: self.flash_segment.encrypt, }; let partition_table_segment = RomSegment { addr: self.partition_table_offset, data: Cow::Owned(self.partition_table.to_bin().unwrap()), + encrypt: false, }; let app_segment = RomSegment { addr: self.flash_segment.addr, data: Cow::Borrowed(&self.flash_segment.data), + encrypt: self.flash_segment.encrypt, }; Box::new( diff --git a/espflash/src/targets/esp32.rs b/espflash/src/targets/esp32.rs index edcfefe2..850274c4 100644 --- a/espflash/src/targets/esp32.rs +++ b/espflash/src/targets/esp32.rs @@ -159,7 +159,7 @@ impl Target for Esp32 { _chip_revision: Option<(u32, u32)>, xtal_freq: XtalFrequency, ) -> Result, Error> { - let booloader: &'static [u8] = match xtal_freq { + let bootloader: &'static [u8] = match xtal_freq { XtalFrequency::_40Mhz => { include_bytes!("../../resources/bootloaders/esp32-bootloader.bin") } @@ -180,7 +180,7 @@ impl Target for Esp32 { 0x3f_0000, 0, FlashFrequency::_40Mhz, - booloader, + bootloader, ); IdfBootloaderFormat::new( diff --git a/espflash/src/targets/flash_target/esp32.rs b/espflash/src/targets/flash_target/esp32.rs index e6088d47..4df8556a 100644 --- a/espflash/src/targets/flash_target/esp32.rs +++ b/espflash/src/targets/flash_target/esp32.rs @@ -164,34 +164,37 @@ impl FlashTarget for Esp32Target { } } - let mut encoder = ZlibEncoder::new(Vec::new(), Compression::best()); - encoder.write_all(&segment.data)?; - let compressed = encoder.finish()?; + // let mut encoder = ZlibEncoder::new(Vec::new(), Compression::best()); + // encoder.write_all(&segment.data)?; + // let compressed = encoder.finish()?; let target = self.chip.into_target(); let flash_write_size = target.flash_write_size(connection)?; - let block_count = compressed.len().div_ceil(flash_write_size); + // let block_count = compressed.len().div_ceil(flash_write_size); + let block_count = segment.data.len().div_ceil(flash_write_size); let erase_count = segment.data.len().div_ceil(FLASH_SECTOR_SIZE); // round up to sector size let erase_size = (erase_count * FLASH_SECTOR_SIZE) as u32; connection.with_timeout( - CommandType::FlashDeflBegin.timeout_for_size(erase_size), + CommandType::FlashBegin.timeout_for_size(erase_size), |connection| { - connection.command(Command::FlashDeflBegin { + connection.command(Command::FlashBegin { size: segment.data.len() as u32, blocks: block_count as u32, block_size: flash_write_size as u32, offset: addr, supports_encryption: self.chip != Chip::Esp32 && !self.use_stub, + perform_encryption: segment.encrypt, })?; Ok(()) }, )?; self.need_deflate_end = true; - let chunks = compressed.chunks(flash_write_size); + let chunks = segment.data.chunks(flash_write_size); + // let chunks = compressed.chunks(flash_write_size); let num_chunks = chunks.len(); if let Some(cb) = progress.as_mut() { @@ -199,19 +202,21 @@ impl FlashTarget for Esp32Target { } // decode the chunks to see how much data the device will have to save - let mut decoder = ZlibDecoder::new(Vec::new()); - let mut decoded_size = 0; + // let mut decoder = ZlibDecoder::new(Vec::new()); + // let mut decoded_size = 0; + // let mut transfered_size = 0; for (i, block) in chunks.enumerate() { - decoder.write_all(block)?; - decoder.flush()?; - let size = decoder.get_ref().len() - decoded_size; - decoded_size = decoder.get_ref().len(); + // decoder.write_all(block)?; + // decoder.flush()?; + let size = segment.data.len() - i * flash_write_size; + // let size = decoder.get_ref().len() - decoded_size; + // decoded_size = decoder.get_ref().len(); connection.with_timeout( - CommandType::FlashDeflData.timeout_for_size(size as u32), + CommandType::FlashData.timeout_for_size(size as u32), |connection| { - connection.command(Command::FlashDeflData { + connection.command(Command::FlashData { sequence: i as u32, pad_to: 0, pad_byte: 0xff, @@ -251,8 +256,8 @@ impl FlashTarget for Esp32Target { fn finish(&mut self, connection: &mut Connection, reboot: bool) -> Result<(), Error> { if self.need_deflate_end { - connection.with_timeout(CommandType::FlashDeflEnd.timeout(), |connection| { - connection.command(Command::FlashDeflEnd { reboot: false }) + connection.with_timeout(CommandType::FlashEnd.timeout(), |connection| { + connection.command(Command::FlashEnd { reboot: false }) })?; } From 4140c45955a3c86c4811f6fbce3984b3964d2554 Mon Sep 17 00:00:00 2001 From: 4rzael Date: Mon, 6 Jan 2025 16:02:12 +0100 Subject: [PATCH 2/7] Flash encryption cleaned up. ELF upload broken --- espflash/src/command.rs | 4 +- espflash/src/flasher/mod.rs | 13 +- espflash/src/image_format.rs | 2 +- espflash/src/targets/flash_target/esp32.rs | 158 ++++++++++++++------- espflash/src/targets/mod.rs | 5 +- 5 files changed, 117 insertions(+), 65 deletions(-) diff --git a/espflash/src/command.rs b/espflash/src/command.rs index 10c00aa9..d269f46b 100644 --- a/espflash/src/command.rs +++ b/espflash/src/command.rs @@ -164,7 +164,6 @@ pub enum Command<'a> { block_size: u32, offset: u32, supports_encryption: bool, - perform_encryption: bool, }, FlashDeflData { data: &'a [u8], @@ -357,7 +356,6 @@ impl Command<'_> { block_size, offset, supports_encryption, - perform_encryption, } => { begin_command( writer, @@ -366,7 +364,7 @@ impl Command<'_> { block_size, offset, supports_encryption, - perform_encryption, + false, // Compression and encryption are mutually exclusive )?; } Command::FlashDeflData { diff --git a/espflash/src/flasher/mod.rs b/espflash/src/flasher/mod.rs index 5529a3e9..5ef6e4f7 100644 --- a/espflash/src/flasher/mod.rs +++ b/espflash/src/flasher/mod.rs @@ -643,9 +643,9 @@ impl Flasher { } pub fn disable_watchdog(&mut self) -> Result<(), Error> { - let mut target = self - .chip - .flash_target(self.spi_params, self.use_stub, false, false); + let mut target = + self.chip + .flash_target(self.spi_params, self.use_stub, false, false, false); target.begin(&mut self.connection).flashing()?; Ok(()) } @@ -1017,9 +1017,10 @@ impl Flasher { segments: &[RomSegment], mut progress: Option<&mut dyn ProgressCallbacks>, ) -> Result<(), Error> { - let mut target = self - .chip - .flash_target(self.spi_params, self.use_stub, false, false); + let encrypt = segments.iter().any(|seg| seg.encrypt); + let mut target = + self.chip + .flash_target(self.spi_params, self.use_stub, false, false, encrypt); target.begin(&mut self.connection).flashing()?; for segment in segments { target.write_segment(&mut self.connection, segment.borrow(), &mut progress)?; diff --git a/espflash/src/image_format.rs b/espflash/src/image_format.rs index 79b81a3d..4d0fd0aa 100644 --- a/espflash/src/image_format.rs +++ b/espflash/src/image_format.rs @@ -303,7 +303,7 @@ impl<'a> IdfBootloaderFormat<'a> { addr: self.params.boot_addr, data: Cow::Borrowed(&self.bootloader), // We use the app encryption setting for bootloader too. - // Am other (better ?) approach might be to check the target Efuses instead. + // An other (better ?) approach might be to check the target Efuses instead. encrypt: self.flash_segment.encrypt, }; diff --git a/espflash/src/targets/flash_target/esp32.rs b/espflash/src/targets/flash_target/esp32.rs index 4df8556a..18480e1b 100644 --- a/espflash/src/targets/flash_target/esp32.rs +++ b/espflash/src/targets/flash_target/esp32.rs @@ -1,9 +1,11 @@ -use std::io::Write; +use std::{borrow::Cow, io::Write}; +use addr2line::object::ReadRef; use flate2::{ write::{ZlibDecoder, ZlibEncoder}, Compression, }; +use libc::segment_command_64; use log::info; use md5::{Digest, Md5}; @@ -28,7 +30,8 @@ pub struct Esp32Target { use_stub: bool, verify: bool, skip: bool, - need_deflate_end: bool, + encrypt: bool, + need_transfer_end: bool, } impl Esp32Target { @@ -38,6 +41,7 @@ impl Esp32Target { use_stub: bool, verify: bool, skip: bool, + encrypt: bool, ) -> Self { Esp32Target { chip, @@ -45,7 +49,8 @@ impl Esp32Target { use_stub, verify, skip, - need_deflate_end: false, + encrypt, + need_transfer_end: false, } } } @@ -164,67 +169,106 @@ impl FlashTarget for Esp32Target { } } - // let mut encoder = ZlibEncoder::new(Vec::new(), Compression::best()); - // encoder.write_all(&segment.data)?; - // let compressed = encoder.finish()?; - let target = self.chip.into_target(); let flash_write_size = target.flash_write_size(connection)?; - // let block_count = compressed.len().div_ceil(flash_write_size); - let block_count = segment.data.len().div_ceil(flash_write_size); let erase_count = segment.data.len().div_ceil(FLASH_SECTOR_SIZE); - - // round up to sector size + // round erase up to sector size let erase_size = (erase_count * FLASH_SECTOR_SIZE) as u32; + let payload: Cow<[u8]> = if self.encrypt { + Cow::Borrowed(&segment.data) + } else { + let mut encoder = ZlibEncoder::new(Vec::new(), Compression::best()); + encoder.write_all(&segment.data)?; + let compressed = encoder.finish()?; + Cow::Owned(compressed) + }; + let block_count = payload.len().div_ceil(flash_write_size); + if self.encrypt { + connection.with_timeout( + CommandType::FlashBegin.timeout_for_size(erase_size), + |connection| { + connection.command(Command::FlashBegin { + size: segment.data.len() as u32, + blocks: block_count as u32, + block_size: flash_write_size as u32, + offset: addr, + supports_encryption: self.chip != Chip::Esp32 && !self.use_stub, + perform_encryption: segment.encrypt, + })?; + Ok(()) + }, + )?; + } else { + connection.with_timeout( + CommandType::FlashDeflBegin.timeout_for_size(erase_size), + |connection| { + connection.command(Command::FlashDeflBegin { + size: segment.data.len() as u32, + blocks: block_count as u32, + block_size: flash_write_size as u32, + offset: addr, + supports_encryption: self.chip != Chip::Esp32 && !self.use_stub, + })?; + Ok(()) + }, + )?; + } + self.need_transfer_end = true; - connection.with_timeout( - CommandType::FlashBegin.timeout_for_size(erase_size), - |connection| { - connection.command(Command::FlashBegin { - size: segment.data.len() as u32, - blocks: block_count as u32, - block_size: flash_write_size as u32, - offset: addr, - supports_encryption: self.chip != Chip::Esp32 && !self.use_stub, - perform_encryption: segment.encrypt, - })?; - Ok(()) - }, - )?; - self.need_deflate_end = true; - - let chunks = segment.data.chunks(flash_write_size); - // let chunks = compressed.chunks(flash_write_size); + let chunks = payload.chunks(flash_write_size); let num_chunks = chunks.len(); if let Some(cb) = progress.as_mut() { cb.init(addr, num_chunks) } - // decode the chunks to see how much data the device will have to save - // let mut decoder = ZlibDecoder::new(Vec::new()); - // let mut decoded_size = 0; - // let mut transfered_size = 0; + // Operation timeout is based on flash operation duration. + // When using compressed transfers, we thus need to deflate to know + // how many bytes will be written / erased, + // and thus how long the timeout will be + let mut decoder = if !self.encrypt { + Some(ZlibDecoder::new(Vec::new())) + } else { + None + }; for (i, block) in chunks.enumerate() { - // decoder.write_all(block)?; - // decoder.flush()?; - let size = segment.data.len() - i * flash_write_size; - // let size = decoder.get_ref().len() - decoded_size; - // decoded_size = decoder.get_ref().len(); + let chunk_size_in_flash = if let Some(decoder) = &mut decoder { + let previous_length = decoder.get_ref().len(); + decoder.write_all(block)?; + decoder.flush()?; + decoder.get_ref().len() - previous_length + } else { + block.len() + }; - connection.with_timeout( - CommandType::FlashData.timeout_for_size(size as u32), - |connection| { - connection.command(Command::FlashData { - sequence: i as u32, - pad_to: 0, - pad_byte: 0xff, - data: block, - })?; - Ok(()) - }, - )?; + if self.encrypt { + connection.with_timeout( + CommandType::FlashData.timeout_for_size(chunk_size_in_flash as u32), + |connection| { + connection.command(Command::FlashData { + sequence: i as u32, + pad_to: 0, + pad_byte: 0xff, + data: block, + })?; + Ok(()) + }, + )?; + } else { + connection.with_timeout( + CommandType::FlashDeflData.timeout_for_size(chunk_size_in_flash as u32), + |connection| { + connection.command(Command::FlashDeflData { + sequence: i as u32, + pad_to: 0, + pad_byte: 0xff, + data: block, + })?; + Ok(()) + }, + )?; + } if let Some(cb) = progress.as_mut() { cb.update(i + 1) @@ -255,10 +299,16 @@ impl FlashTarget for Esp32Target { } fn finish(&mut self, connection: &mut Connection, reboot: bool) -> Result<(), Error> { - if self.need_deflate_end { - connection.with_timeout(CommandType::FlashEnd.timeout(), |connection| { - connection.command(Command::FlashEnd { reboot: false }) - })?; + if self.need_transfer_end { + if self.encrypt { + connection.with_timeout(CommandType::FlashEnd.timeout(), |connection| { + connection.command(Command::FlashEnd { reboot: false }) + })?; + } else { + connection.with_timeout(CommandType::FlashDeflEnd.timeout(), |connection| { + connection.command(Command::FlashDeflEnd { reboot: false }) + })?; + } } if reboot { diff --git a/espflash/src/targets/mod.rs b/espflash/src/targets/mod.rs index 05e5bf9a..5fa1aebf 100644 --- a/espflash/src/targets/mod.rs +++ b/espflash/src/targets/mod.rs @@ -150,8 +150,11 @@ impl Chip { use_stub: bool, verify: bool, skip: bool, + encrypt: bool, ) -> Box { - Box::new(Esp32Target::new(*self, spi_params, use_stub, verify, skip)) + Box::new(Esp32Target::new( + *self, spi_params, use_stub, verify, skip, encrypt, + )) } #[cfg(feature = "serialport")] From 24530ea3eec8b349acdc3b85a0e00083782040b0 Mon Sep 17 00:00:00 2001 From: 4rzael Date: Mon, 6 Jan 2025 16:20:58 +0100 Subject: [PATCH 3/7] I believe everything should be fine. Time to test --- cargo-espflash/src/main.rs | 10 +++++++++- espflash/src/bin/espflash.rs | 10 +++++++++- espflash/src/cli/mod.rs | 2 ++ espflash/src/flasher/mod.rs | 11 ++++++++--- espflash/src/image_format.rs | 3 +-- 5 files changed, 29 insertions(+), 7 deletions(-) diff --git a/cargo-espflash/src/main.rs b/cargo-espflash/src/main.rs index 1c1e3633..f07e5f56 100644 --- a/cargo-espflash/src/main.rs +++ b/cargo-espflash/src/main.rs @@ -190,6 +190,8 @@ struct FlashArgs { connect_args: ConnectArgs, #[clap(flatten)] flash_args: cli::FlashArgs, + #[arg(long)] + encrypt: bool, } #[derive(Debug, Args)] @@ -347,7 +349,13 @@ fn flash(args: FlashArgs, config: &Config) -> Result<()> { )?; } - flash_elf_image(&mut flasher, &elf_data, flash_data, target_xtal_freq)?; + flash_elf_image( + &mut flasher, + &elf_data, + flash_data, + target_xtal_freq, + args.encrypt, + )?; } if args.flash_args.monitor { diff --git a/espflash/src/bin/espflash.rs b/espflash/src/bin/espflash.rs index 66ed4521..078f518f 100644 --- a/espflash/src/bin/espflash.rs +++ b/espflash/src/bin/espflash.rs @@ -127,6 +127,8 @@ struct FlashArgs { flash_args: cli::FlashArgs, /// ELF image to flash image: PathBuf, + #[arg(long)] + encrypt: bool, } #[derive(Debug, Args)] @@ -284,7 +286,13 @@ fn flash(args: FlashArgs, config: &Config) -> Result<()> { )?; } - flash_elf_image(&mut flasher, &elf_data, flash_data, target_xtal_freq)?; + flash_elf_image( + &mut flasher, + &elf_data, + flash_data, + target_xtal_freq, + args.encrypt, + )?; } if args.flash_args.monitor { diff --git a/espflash/src/cli/mod.rs b/espflash/src/cli/mod.rs index bccb56bb..1e2a5f42 100644 --- a/espflash/src/cli/mod.rs +++ b/espflash/src/cli/mod.rs @@ -627,6 +627,7 @@ pub fn flash_elf_image( elf_data: &[u8], flash_data: FlashData, xtal_freq: XtalFrequency, + encrypt: bool, ) -> Result<()> { // Load the ELF data, optionally using the provider bootloader/partition // table/image format, to the device's flash memory. @@ -635,6 +636,7 @@ pub fn flash_elf_image( flash_data, Some(&mut EspflashProgress::default()), xtal_freq, + encrypt, )?; info!("Flashing has completed!"); diff --git a/espflash/src/flasher/mod.rs b/espflash/src/flasher/mod.rs index 5ef6e4f7..138685a5 100644 --- a/espflash/src/flasher/mod.rs +++ b/espflash/src/flasher/mod.rs @@ -955,12 +955,17 @@ impl Flasher { flash_data: FlashData, mut progress: Option<&mut dyn ProgressCallbacks>, xtal_freq: XtalFrequency, + encrypt: bool, ) -> Result<(), Error> { let image = ElfFirmwareImage::try_from(elf_data)?; - let mut target = - self.chip - .flash_target(self.spi_params, self.use_stub, self.verify, self.skip); + let mut target = self.chip.flash_target( + self.spi_params, + self.use_stub, + self.verify, + self.skip, + encrypt, + ); target.begin(&mut self.connection).flashing()?; let chip_revision = Some( diff --git a/espflash/src/image_format.rs b/espflash/src/image_format.rs index 4d0fd0aa..4017954e 100644 --- a/espflash/src/image_format.rs +++ b/espflash/src/image_format.rs @@ -302,8 +302,7 @@ impl<'a> IdfBootloaderFormat<'a> { let bootloader_segment = RomSegment { addr: self.params.boot_addr, data: Cow::Borrowed(&self.bootloader), - // We use the app encryption setting for bootloader too. - // An other (better ?) approach might be to check the target Efuses instead. + // We use the app encryption setting for bootloader too encrypt: self.flash_segment.encrypt, }; From 2e093953da2730f58698f749f3f1cb92d78a333e Mon Sep 17 00:00:00 2001 From: 4rzael Date: Mon, 6 Jan 2025 18:25:16 +0100 Subject: [PATCH 4/7] Updates flash encryption mechanism to work with ELFs --- cargo-espflash/src/main.rs | 10 +++------- espflash/src/bin/espflash.rs | 12 +++--------- espflash/src/cli/mod.rs | 4 ++-- espflash/src/elf.rs | 9 +++------ espflash/src/flasher/mod.rs | 21 ++++++++++++++++++--- espflash/src/image_format.rs | 9 ++++++--- espflash/src/targets/esp32.rs | 1 + espflash/src/targets/esp32c2.rs | 1 + espflash/src/targets/esp32c3.rs | 1 + espflash/src/targets/esp32c6.rs | 1 + espflash/src/targets/esp32h2.rs | 1 + espflash/src/targets/esp32p4.rs | 1 + espflash/src/targets/esp32s2.rs | 1 + espflash/src/targets/esp32s3.rs | 1 + espflash/src/targets/flash_target/esp32.rs | 6 ++---- 15 files changed, 45 insertions(+), 34 deletions(-) diff --git a/cargo-espflash/src/main.rs b/cargo-espflash/src/main.rs index f07e5f56..db9b98d8 100644 --- a/cargo-espflash/src/main.rs +++ b/cargo-espflash/src/main.rs @@ -338,6 +338,7 @@ fn flash(args: FlashArgs, config: &Config) -> Result<()> { config, build_ctx.bootloader_path.as_deref(), build_ctx.partition_table_path.as_deref(), + args.flash_args.encrypt, )?; if args.flash_args.erase_parts.is_some() || args.flash_args.erase_data_parts.is_some() { @@ -349,13 +350,7 @@ fn flash(args: FlashArgs, config: &Config) -> Result<()> { )?; } - flash_elf_image( - &mut flasher, - &elf_data, - flash_data, - target_xtal_freq, - args.encrypt, - )?; + flash_elf_image(&mut flasher, &elf_data, flash_data, target_xtal_freq)?; } if args.flash_args.monitor { @@ -587,6 +582,7 @@ fn save_image(args: SaveImageArgs, config: &Config) -> Result<()> { config, build_ctx.bootloader_path.as_deref(), build_ctx.partition_table_path.as_deref(), + false, // We don't care about encryption when writing a .bin, as it is not stored in there )?; let xtal_freq = args diff --git a/espflash/src/bin/espflash.rs b/espflash/src/bin/espflash.rs index 078f518f..4c6fd34f 100644 --- a/espflash/src/bin/espflash.rs +++ b/espflash/src/bin/espflash.rs @@ -127,8 +127,6 @@ struct FlashArgs { flash_args: cli::FlashArgs, /// ELF image to flash image: PathBuf, - #[arg(long)] - encrypt: bool, } #[derive(Debug, Args)] @@ -275,6 +273,7 @@ fn flash(args: FlashArgs, config: &Config) -> Result<()> { config, None, None, + args.flash_args.encrypt, )?; if args.flash_args.erase_parts.is_some() || args.flash_args.erase_data_parts.is_some() { @@ -286,13 +285,7 @@ fn flash(args: FlashArgs, config: &Config) -> Result<()> { )?; } - flash_elf_image( - &mut flasher, - &elf_data, - flash_data, - target_xtal_freq, - args.encrypt, - )?; + flash_elf_image(&mut flasher, &elf_data, flash_data, target_xtal_freq)?; } if args.flash_args.monitor { @@ -338,6 +331,7 @@ fn save_image(args: SaveImageArgs, config: &Config) -> Result<()> { config, None, None, + false, // We don't care about encryption when writing a .bin, as it is not stored in there )?; let xtal_freq = args diff --git a/espflash/src/cli/mod.rs b/espflash/src/cli/mod.rs index 1e2a5f42..1aa19585 100644 --- a/espflash/src/cli/mod.rs +++ b/espflash/src/cli/mod.rs @@ -627,7 +627,6 @@ pub fn flash_elf_image( elf_data: &[u8], flash_data: FlashData, xtal_freq: XtalFrequency, - encrypt: bool, ) -> Result<()> { // Load the ELF data, optionally using the provider bootloader/partition // table/image format, to the device's flash memory. @@ -636,7 +635,6 @@ pub fn flash_elf_image( flash_data, Some(&mut EspflashProgress::default()), xtal_freq, - encrypt, )?; info!("Flashing has completed!"); @@ -826,6 +824,7 @@ pub fn make_flash_data( config: &Config, default_bootloader: Option<&Path>, default_partition_table: Option<&Path>, + encrypted: bool, ) -> Result { let bootloader = image_args .bootloader @@ -857,6 +856,7 @@ pub fn make_flash_data( image_args.target_app_partition, flash_settings, image_args.min_chip_rev, + encrypted, ) } diff --git a/espflash/src/elf.rs b/espflash/src/elf.rs index 52c25b4f..bd1bee2f 100644 --- a/espflash/src/elf.rs +++ b/espflash/src/elf.rs @@ -252,15 +252,12 @@ impl<'a> RomSegment<'a> { encrypt: self.encrypt, } } -} -impl<'a> From> for RomSegment<'a> { - fn from(segment: CodeSegment<'a>) -> Self { - todo!("Remove this conversion, as we cannot easily assume encryption requirements ?"); + pub fn from_code_segment(segment: &CodeSegment<'a>, encrypt: bool) -> Self { RomSegment { addr: segment.addr, - data: segment.data, - encrypt: false, + data: segment.data.clone(), + encrypt, } } } diff --git a/espflash/src/flasher/mod.rs b/espflash/src/flasher/mod.rs index 138685a5..9bc18055 100644 --- a/espflash/src/flasher/mod.rs +++ b/espflash/src/flasher/mod.rs @@ -300,6 +300,7 @@ pub struct FlashDataBuilder<'a> { target_app_partition: Option, flash_settings: FlashSettings, min_chip_rev: u16, + encryption: bool, } impl Default for FlashDataBuilder<'_> { @@ -311,6 +312,7 @@ impl Default for FlashDataBuilder<'_> { target_app_partition: Default::default(), flash_settings: FlashSettings::default(), min_chip_rev: Default::default(), + encryption: Default::default(), } } } @@ -357,6 +359,12 @@ impl<'a> FlashDataBuilder<'a> { self } + /// Sets the minimum chip revision. + pub fn with_encryption(mut self, encryption: bool) -> Self { + self.encryption = encryption; + self + } + /// Builds a [`FlashData`] object. pub fn build(self) -> Result { FlashData::new( @@ -366,6 +374,7 @@ impl<'a> FlashDataBuilder<'a> { self.target_app_partition, self.flash_settings, self.min_chip_rev, + self.encryption, ) } } @@ -380,6 +389,7 @@ pub struct FlashData { pub target_app_partition: Option, pub flash_settings: FlashSettings, pub min_chip_rev: u16, + pub encrypted: bool, } impl FlashData { @@ -390,6 +400,7 @@ impl FlashData { target_app_partition: Option, flash_settings: FlashSettings, min_chip_rev: u16, + encrypted: bool, ) -> Result { // If the '--bootloader' option is provided, load the binary file at the // specified path. @@ -417,6 +428,7 @@ impl FlashData { target_app_partition, flash_settings, min_chip_rev, + encrypted, }) } } @@ -941,7 +953,11 @@ impl Flasher { for segment in image.ram_segments(self.chip) { target - .write_segment(&mut self.connection, segment.into(), &mut progress) + .write_segment( + &mut self.connection, + RomSegment::from_code_segment(&segment, false), + &mut progress, + ) .flashing()?; } @@ -955,7 +971,6 @@ impl Flasher { flash_data: FlashData, mut progress: Option<&mut dyn ProgressCallbacks>, xtal_freq: XtalFrequency, - encrypt: bool, ) -> Result<(), Error> { let image = ElfFirmwareImage::try_from(elf_data)?; @@ -964,7 +979,7 @@ impl Flasher { self.use_stub, self.verify, self.skip, - encrypt, + flash_data.encrypted, ); target.begin(&mut self.connection).flashing()?; diff --git a/espflash/src/image_format.rs b/espflash/src/image_format.rs index 4017954e..997cf1a2 100644 --- a/espflash/src/image_format.rs +++ b/espflash/src/image_format.rs @@ -124,6 +124,7 @@ impl<'a> IdfBootloaderFormat<'a> { target_app_partition: Option, bootloader: Option>, flash_settings: FlashSettings, + encrypt: bool, ) -> Result { let partition_table = partition_table.unwrap_or_else(|| { params.default_partition_table(flash_settings.size.map(|v| v.size())) @@ -269,7 +270,7 @@ impl<'a> IdfBootloaderFormat<'a> { let flash_segment = RomSegment { addr: target_app_partition.offset(), data: Cow::Owned(data), - encrypt: target_app_partition.encrypted(), + encrypt, }; // If the user did not specify a partition offset, we need to assume that the @@ -299,17 +300,19 @@ impl<'a> IdfBootloaderFormat<'a> { where 'a: 'b, { + // Flash encryption, if enabled, will automatically be enabled for those 3 partitions: + // https://docs.espressif.com/projects/esp-idf/en/v5.4/esp32s3/security/flash-encryption.html#encrypted-partitions + let bootloader_segment = RomSegment { addr: self.params.boot_addr, data: Cow::Borrowed(&self.bootloader), - // We use the app encryption setting for bootloader too encrypt: self.flash_segment.encrypt, }; let partition_table_segment = RomSegment { addr: self.partition_table_offset, data: Cow::Owned(self.partition_table.to_bin().unwrap()), - encrypt: false, + encrypt: self.flash_segment.encrypt, }; let app_segment = RomSegment { diff --git a/espflash/src/targets/esp32.rs b/espflash/src/targets/esp32.rs index 850274c4..a82e384f 100644 --- a/espflash/src/targets/esp32.rs +++ b/espflash/src/targets/esp32.rs @@ -193,6 +193,7 @@ impl Target for Esp32 { flash_data.target_app_partition, flash_data.bootloader, flash_data.flash_settings, + flash_data.encrypted, ) } diff --git a/espflash/src/targets/esp32c2.rs b/espflash/src/targets/esp32c2.rs index a307e318..ce47df17 100644 --- a/espflash/src/targets/esp32c2.rs +++ b/espflash/src/targets/esp32c2.rs @@ -131,6 +131,7 @@ impl Target for Esp32c2 { flash_data.target_app_partition, flash_data.bootloader, flash_data.flash_settings, + flash_data.encrypted, ) } diff --git a/espflash/src/targets/esp32c3.rs b/espflash/src/targets/esp32c3.rs index 31f7cfbf..bbb1ef8f 100644 --- a/espflash/src/targets/esp32c3.rs +++ b/espflash/src/targets/esp32c3.rs @@ -100,6 +100,7 @@ impl Target for Esp32c3 { flash_data.target_app_partition, flash_data.bootloader, flash_data.flash_settings, + flash_data.encrypted, ) } diff --git a/espflash/src/targets/esp32c6.rs b/espflash/src/targets/esp32c6.rs index 082bfcb9..dce86d9c 100644 --- a/espflash/src/targets/esp32c6.rs +++ b/espflash/src/targets/esp32c6.rs @@ -95,6 +95,7 @@ impl Target for Esp32c6 { flash_data.target_app_partition, flash_data.bootloader, flash_data.flash_settings, + flash_data.encrypted, ) } diff --git a/espflash/src/targets/esp32h2.rs b/espflash/src/targets/esp32h2.rs index c0a3ec57..3f7c9dd5 100644 --- a/espflash/src/targets/esp32h2.rs +++ b/espflash/src/targets/esp32h2.rs @@ -102,6 +102,7 @@ impl Target for Esp32h2 { flash_data.target_app_partition, flash_data.bootloader, flash_data.flash_settings, + flash_data.encrypted, ) } diff --git a/espflash/src/targets/esp32p4.rs b/espflash/src/targets/esp32p4.rs index 73b2f5ac..40ca76c7 100644 --- a/espflash/src/targets/esp32p4.rs +++ b/espflash/src/targets/esp32p4.rs @@ -91,6 +91,7 @@ impl Target for Esp32p4 { flash_data.target_app_partition, flash_data.bootloader, flash_data.flash_settings, + flash_data.encrypted, ) } diff --git a/espflash/src/targets/esp32s2.rs b/espflash/src/targets/esp32s2.rs index 804893c3..a66fc8a7 100644 --- a/espflash/src/targets/esp32s2.rs +++ b/espflash/src/targets/esp32s2.rs @@ -169,6 +169,7 @@ impl Target for Esp32s2 { flash_data.target_app_partition, flash_data.bootloader, flash_data.flash_settings, + flash_data.encrypted, ) } diff --git a/espflash/src/targets/esp32s3.rs b/espflash/src/targets/esp32s3.rs index 59798c69..ec0811a2 100644 --- a/espflash/src/targets/esp32s3.rs +++ b/espflash/src/targets/esp32s3.rs @@ -119,6 +119,7 @@ impl Target for Esp32s3 { flash_data.target_app_partition, flash_data.bootloader, flash_data.flash_settings, + flash_data.encrypted, ) } diff --git a/espflash/src/targets/flash_target/esp32.rs b/espflash/src/targets/flash_target/esp32.rs index 18480e1b..636fee3a 100644 --- a/espflash/src/targets/flash_target/esp32.rs +++ b/espflash/src/targets/flash_target/esp32.rs @@ -1,11 +1,9 @@ use std::{borrow::Cow, io::Write}; -use addr2line::object::ReadRef; use flate2::{ write::{ZlibDecoder, ZlibEncoder}, Compression, }; -use libc::segment_command_64; use log::info; use md5::{Digest, Md5}; @@ -149,7 +147,7 @@ impl FlashTarget for Esp32Target { md5_hasher.update(&segment.data); let checksum_md5 = md5_hasher.finalize(); - if self.skip { + if self.skip && !segment.encrypt { let flash_checksum_md5: u128 = connection.with_timeout(CommandType::FlashMd5.timeout(), |connection| { connection @@ -279,7 +277,7 @@ impl FlashTarget for Esp32Target { cb.finish() } - if self.verify { + if self.verify && !segment.encrypt { let flash_checksum_md5: u128 = connection.with_timeout(CommandType::FlashMd5.timeout(), |connection| { connection From 6be91521b2ddc42e93aae1d703b5762d54f8977d Mon Sep 17 00:00:00 2001 From: 4rzael Date: Mon, 6 Jan 2025 18:49:24 +0100 Subject: [PATCH 5/7] Flash encryption: variable renames --- espflash/src/command.rs | 12 ++++++------ espflash/src/connection/reset.rs | 4 ++-- espflash/src/elf.rs | 8 ++++---- espflash/src/flasher/mod.rs | 8 ++++---- espflash/src/image_format.rs | 10 +++++----- espflash/src/targets/flash_target/esp32.rs | 6 +++--- 6 files changed, 24 insertions(+), 24 deletions(-) diff --git a/espflash/src/command.rs b/espflash/src/command.rs index d269f46b..58908c4a 100644 --- a/espflash/src/command.rs +++ b/espflash/src/command.rs @@ -106,7 +106,7 @@ pub enum Command<'a> { block_size: u32, offset: u32, supports_encryption: bool, - perform_encryption: bool, + encrypt: bool, }, FlashData { data: &'a [u8], @@ -238,7 +238,7 @@ impl Command<'_> { block_size, offset, supports_encryption, - perform_encryption, + encrypt, } => { begin_command( writer, @@ -247,7 +247,7 @@ impl Command<'_> { block_size, offset, supports_encryption, - perform_encryption, + encrypt, )?; } Command::FlashData { @@ -446,10 +446,10 @@ fn begin_command( block_size: u32, offset: u32, supports_encryption: bool, - perform_encryption: bool, + encrypt: bool, ) -> std::io::Result<()> { assert!( - !(perform_encryption && !supports_encryption), + !(encrypt && !supports_encryption), "Target does not support encryption, yet encryption is requested" ); @@ -467,7 +467,7 @@ fn begin_command( blocks, block_size, offset, - encrypted: perform_encryption as u32, + encrypted: encrypt as u32, }; let bytes = bytes_of(¶ms); diff --git a/espflash/src/connection/reset.rs b/espflash/src/connection/reset.rs index ce7b9d7c..0581663f 100644 --- a/espflash/src/connection/reset.rs +++ b/espflash/src/connection/reset.rs @@ -260,7 +260,7 @@ pub fn soft_reset( block_size: FLASH_WRITE_SIZE.try_into().unwrap(), offset, supports_encryption: false, - perform_encryption: false, + encrypt: false, }) })?; connection.with_timeout(CommandType::FlashEnd.timeout(), |connection| { @@ -279,7 +279,7 @@ pub fn soft_reset( block_size: FLASH_WRITE_SIZE.try_into().unwrap(), offset, supports_encryption: false, - perform_encryption: false, + encrypt: false, }) })?; connection.with_timeout(CommandType::FlashEnd.timeout(), |connection| { diff --git a/espflash/src/elf.rs b/espflash/src/elf.rs index bd1bee2f..e5d085cc 100644 --- a/espflash/src/elf.rs +++ b/espflash/src/elf.rs @@ -238,7 +238,7 @@ pub struct RomSegment<'a> { /// Segment data pub data: Cow<'a, [u8]>, /// Whether the segment shall be encrypted before being writen - pub encrypt: bool, + pub encrypted: bool, } impl<'a> RomSegment<'a> { @@ -249,15 +249,15 @@ impl<'a> RomSegment<'a> { RomSegment { addr: self.addr, data: Cow::Borrowed(self.data.as_ref()), - encrypt: self.encrypt, + encrypted: self.encrypted, } } - pub fn from_code_segment(segment: &CodeSegment<'a>, encrypt: bool) -> Self { + pub fn from_code_segment(segment: &CodeSegment<'a>, encrypted: bool) -> Self { RomSegment { addr: segment.addr, data: segment.data.clone(), - encrypt, + encrypted, } } } diff --git a/espflash/src/flasher/mod.rs b/espflash/src/flasher/mod.rs index 9bc18055..52cad598 100644 --- a/espflash/src/flasher/mod.rs +++ b/espflash/src/flasher/mod.rs @@ -686,7 +686,7 @@ impl Flasher { RomSegment { addr: text_addr, data: Cow::Borrowed(&text), - encrypt: false, + encrypted: false, }, &mut None, ) @@ -701,7 +701,7 @@ impl Flasher { RomSegment { addr: data_addr, data: Cow::Borrowed(&data), - encrypt: false, + encrypted: false, }, &mut None, ) @@ -1022,7 +1022,7 @@ impl Flasher { let segment = RomSegment { addr, data: Cow::from(data), - encrypt, + encrypted: encrypt, }; self.write_bins_to_flash(&[segment], progress)?; @@ -1037,7 +1037,7 @@ impl Flasher { segments: &[RomSegment], mut progress: Option<&mut dyn ProgressCallbacks>, ) -> Result<(), Error> { - let encrypt = segments.iter().any(|seg| seg.encrypt); + let encrypt = segments.iter().any(|seg| seg.encrypted); let mut target = self.chip .flash_target(self.spi_params, self.use_stub, false, false, encrypt); diff --git a/espflash/src/image_format.rs b/espflash/src/image_format.rs index 997cf1a2..c851cea6 100644 --- a/espflash/src/image_format.rs +++ b/espflash/src/image_format.rs @@ -124,7 +124,7 @@ impl<'a> IdfBootloaderFormat<'a> { target_app_partition: Option, bootloader: Option>, flash_settings: FlashSettings, - encrypt: bool, + encrypted: bool, ) -> Result { let partition_table = partition_table.unwrap_or_else(|| { params.default_partition_table(flash_settings.size.map(|v| v.size())) @@ -270,7 +270,7 @@ impl<'a> IdfBootloaderFormat<'a> { let flash_segment = RomSegment { addr: target_app_partition.offset(), data: Cow::Owned(data), - encrypt, + encrypted, }; // If the user did not specify a partition offset, we need to assume that the @@ -306,19 +306,19 @@ impl<'a> IdfBootloaderFormat<'a> { let bootloader_segment = RomSegment { addr: self.params.boot_addr, data: Cow::Borrowed(&self.bootloader), - encrypt: self.flash_segment.encrypt, + encrypted: self.flash_segment.encrypted, }; let partition_table_segment = RomSegment { addr: self.partition_table_offset, data: Cow::Owned(self.partition_table.to_bin().unwrap()), - encrypt: self.flash_segment.encrypt, + encrypted: self.flash_segment.encrypted, }; let app_segment = RomSegment { addr: self.flash_segment.addr, data: Cow::Borrowed(&self.flash_segment.data), - encrypt: self.flash_segment.encrypt, + encrypted: self.flash_segment.encrypted, }; Box::new( diff --git a/espflash/src/targets/flash_target/esp32.rs b/espflash/src/targets/flash_target/esp32.rs index 636fee3a..c7188fdd 100644 --- a/espflash/src/targets/flash_target/esp32.rs +++ b/espflash/src/targets/flash_target/esp32.rs @@ -147,7 +147,7 @@ impl FlashTarget for Esp32Target { md5_hasher.update(&segment.data); let checksum_md5 = md5_hasher.finalize(); - if self.skip && !segment.encrypt { + if self.skip && !segment.encrypted { let flash_checksum_md5: u128 = connection.with_timeout(CommandType::FlashMd5.timeout(), |connection| { connection @@ -191,7 +191,7 @@ impl FlashTarget for Esp32Target { block_size: flash_write_size as u32, offset: addr, supports_encryption: self.chip != Chip::Esp32 && !self.use_stub, - perform_encryption: segment.encrypt, + encrypt: segment.encrypted, })?; Ok(()) }, @@ -277,7 +277,7 @@ impl FlashTarget for Esp32Target { cb.finish() } - if self.verify && !segment.encrypt { + if self.verify && !segment.encrypted { let flash_checksum_md5: u128 = connection.with_timeout(CommandType::FlashMd5.timeout(), |connection| { connection From 0720906d87b979dd89a9643a26efd9a8397189db Mon Sep 17 00:00:00 2001 From: 4rzael Date: Mon, 6 Jan 2025 19:19:27 +0100 Subject: [PATCH 6/7] Removes an assert --- espflash/src/command.rs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/espflash/src/command.rs b/espflash/src/command.rs index 58908c4a..851369c6 100644 --- a/espflash/src/command.rs +++ b/espflash/src/command.rs @@ -1,6 +1,10 @@ //! Commands to work with a flasher stub running on a target device -use std::{io::Write, mem::size_of, time::Duration}; +use std::{ + io::{ErrorKind, Write}, + mem::size_of, + time::Duration, +}; use bytemuck::{bytes_of, Pod, Zeroable}; use strum::Display; @@ -448,10 +452,12 @@ fn begin_command( supports_encryption: bool, encrypt: bool, ) -> std::io::Result<()> { - assert!( - !(encrypt && !supports_encryption), - "Target does not support encryption, yet encryption is requested" - ); + if encrypt && !supports_encryption { + return Err(std::io::Error::new( + ErrorKind::InvalidInput, + "Target does not support encryption, yet encryption is requested", + )); + } #[derive(Zeroable, Pod, Copy, Clone, Debug)] #[repr(C)] From b7019e8fe4792ca822582cc9ed869a5b11140897 Mon Sep 17 00:00:00 2001 From: 4rzael Date: Mon, 6 Jan 2025 22:22:33 +0100 Subject: [PATCH 7/7] Adds PR to the changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 317605bc..2b185cc9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Support external log-processors (#705) - Make the `libudev` dependency optional with a new - enabled by default - feature: `libudev` (#709) - Address Clippy lints (#710) +- Add support for flash-encryption (#718) ### Changed