Skip to content
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

Adds support for flash encryption #718

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
4 changes: 4 additions & 0 deletions cargo-espflash/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,8 @@ struct FlashArgs {
connect_args: ConnectArgs,
#[clap(flatten)]
flash_args: cli::FlashArgs,
#[arg(long)]
encrypt: bool,
}

#[derive(Debug, Args)]
Expand Down Expand Up @@ -336,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() {
Expand Down Expand Up @@ -579,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
Expand Down
11 changes: 10 additions & 1 deletion espflash/src/bin/espflash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,8 @@ struct WriteBinArgs {
/// Connection configuration
#[clap(flatten)]
connect_args: ConnectArgs,
#[arg(long)]
encrypt: bool,
}

fn main() -> Result<()> {
Expand Down Expand Up @@ -271,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() {
Expand Down Expand Up @@ -328,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
Expand Down Expand Up @@ -357,7 +361,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(())
}
4 changes: 4 additions & 0 deletions espflash/src/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,8 @@ pub struct FlashArgs {
/// External log processors to use (comma separated executables)
#[arg(long, requires = "monitor")]
pub processors: Option<String>,
#[arg(long)]
pub encrypt: bool,
}

/// Operations for partitions tables
Expand Down Expand Up @@ -822,6 +824,7 @@ pub fn make_flash_data(
config: &Config,
default_bootloader: Option<&Path>,
default_partition_table: Option<&Path>,
encrypted: bool,
) -> Result<FlashData, Error> {
let bootloader = image_args
.bootloader
Expand Down Expand Up @@ -853,6 +856,7 @@ pub fn make_flash_data(
image_args.target_app_partition,
flash_settings,
image_args.min_chip_rev,
encrypted,
)
}

Expand Down
21 changes: 19 additions & 2 deletions espflash/src/command.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -106,6 +110,7 @@ pub enum Command<'a> {
block_size: u32,
offset: u32,
supports_encryption: bool,
encrypt: bool,
},
FlashData {
data: &'a [u8],
Expand Down Expand Up @@ -237,6 +242,7 @@ impl Command<'_> {
block_size,
offset,
supports_encryption,
encrypt,
} => {
begin_command(
writer,
Expand All @@ -245,6 +251,7 @@ impl Command<'_> {
block_size,
offset,
supports_encryption,
encrypt,
)?;
}
Command::FlashData {
Expand Down Expand Up @@ -272,6 +279,7 @@ impl Command<'_> {
block_size,
offset,
supports_encryption,
false,
)?;
}
Command::MemData {
Expand Down Expand Up @@ -360,6 +368,7 @@ impl Command<'_> {
block_size,
offset,
supports_encryption,
false, // Compression and encryption are mutually exclusive
)?;
}
Command::FlashDeflData {
Expand Down Expand Up @@ -441,7 +450,15 @@ fn begin_command<W: Write>(
block_size: u32,
offset: u32,
supports_encryption: bool,
encrypt: bool,
) -> std::io::Result<()> {
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)]
struct BeginParams {
Expand All @@ -456,7 +473,7 @@ fn begin_command<W: Write>(
blocks,
block_size,
offset,
encrypted: 0,
encrypted: encrypt as u32,
};

let bytes = bytes_of(&params);
Expand Down
2 changes: 2 additions & 0 deletions espflash/src/connection/reset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,7 @@ pub fn soft_reset(
block_size: FLASH_WRITE_SIZE.try_into().unwrap(),
offset,
supports_encryption: false,
encrypt: false,
})
})?;
connection.with_timeout(CommandType::FlashEnd.timeout(), |connection| {
Expand All @@ -278,6 +279,7 @@ pub fn soft_reset(
block_size: FLASH_WRITE_SIZE.try_into().unwrap(),
offset,
supports_encryption: false,
encrypt: false,
})
})?;
connection.with_timeout(CommandType::FlashEnd.timeout(), |connection| {
Expand Down
10 changes: 6 additions & 4 deletions espflash/src/elf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 encrypted: bool,
}

impl<'a> RomSegment<'a> {
Expand All @@ -247,15 +249,15 @@ impl<'a> RomSegment<'a> {
RomSegment {
addr: self.addr,
data: Cow::Borrowed(self.data.as_ref()),
encrypted: self.encrypted,
}
}
}

impl<'a> From<CodeSegment<'a>> for RomSegment<'a> {
fn from(segment: CodeSegment<'a>) -> Self {
pub fn from_code_segment(segment: &CodeSegment<'a>, encrypted: bool) -> Self {
RomSegment {
addr: segment.addr,
data: segment.data,
data: segment.data.clone(),
encrypted,
}
}
}
45 changes: 35 additions & 10 deletions espflash/src/flasher/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,7 @@ pub struct FlashDataBuilder<'a> {
target_app_partition: Option<String>,
flash_settings: FlashSettings,
min_chip_rev: u16,
encryption: bool,
}

impl Default for FlashDataBuilder<'_> {
Expand All @@ -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(),
}
}
}
Expand Down Expand Up @@ -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, Error> {
FlashData::new(
Expand All @@ -366,6 +374,7 @@ impl<'a> FlashDataBuilder<'a> {
self.target_app_partition,
self.flash_settings,
self.min_chip_rev,
self.encryption,
)
}
}
Expand All @@ -380,6 +389,7 @@ pub struct FlashData {
pub target_app_partition: Option<String>,
pub flash_settings: FlashSettings,
pub min_chip_rev: u16,
pub encrypted: bool,
}

impl FlashData {
Expand All @@ -390,6 +400,7 @@ impl FlashData {
target_app_partition: Option<String>,
flash_settings: FlashSettings,
min_chip_rev: u16,
encrypted: bool,
) -> Result<Self, Error> {
// If the '--bootloader' option is provided, load the binary file at the
// specified path.
Expand Down Expand Up @@ -417,6 +428,7 @@ impl FlashData {
target_app_partition,
flash_settings,
min_chip_rev,
encrypted,
})
}
}
Expand Down Expand Up @@ -643,9 +655,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(())
}
Expand Down Expand Up @@ -674,6 +686,7 @@ impl Flasher {
RomSegment {
addr: text_addr,
data: Cow::Borrowed(&text),
encrypted: false,
},
&mut None,
)
Expand All @@ -688,6 +701,7 @@ impl Flasher {
RomSegment {
addr: data_addr,
data: Cow::Borrowed(&data),
encrypted: false,
},
&mut None,
)
Expand Down Expand Up @@ -939,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()?;
}

Expand All @@ -956,9 +974,13 @@ impl Flasher {
) -> 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,
flash_data.encrypted,
);
target.begin(&mut self.connection).flashing()?;

let chip_revision = Some(
Expand Down Expand Up @@ -995,10 +1017,12 @@ impl Flasher {
addr: u32,
data: &[u8],
progress: Option<&mut dyn ProgressCallbacks>,
encrypt: bool,
) -> Result<(), Error> {
let segment = RomSegment {
addr,
data: Cow::from(data),
encrypted: encrypt,
};
self.write_bins_to_flash(&[segment], progress)?;

Expand All @@ -1013,9 +1037,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.encrypted);
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)?;
Expand Down
Loading
Loading