diff --git a/Cargo.lock b/Cargo.lock index cd656d7fc81ca1c86298bdedbb1efbbbd52f8328..45617451fbad6bbff3e3103772596eae85fa185e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -337,7 +337,7 @@ checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" [[package]] name = "caprand" version = "0.1.0" -source = "git+https://github.com/mkj/caprand#1204da26c3d60f75ae8f522494415cc18c736888" +source = "git+https://github.com/mkj/caprand#a292401a503b422993ee6052a0f6fd316d6bff5c" dependencies = [ "cortex-m", "critical-section 1.1.1", @@ -346,6 +346,7 @@ dependencies = [ "log", "rand 0.8.5", "rand_chacha 0.3.1", + "rp-pac", "sha2 0.10.7", ] @@ -1071,6 +1072,8 @@ dependencies = [ "critical-section 1.1.1", "defmt", "embedded-hal 0.2.7", + "embedded-hal 1.0.0-alpha.11", + "embedded-hal-async", "futures-util", "heapless", "log", diff --git a/embassy/demos/common/src/menu.rs b/embassy/demos/common/src/menu.rs index 5c4dd5c74794853da117dc0e904bfc9d9119b0d5..f2ac1ae29bd639f98c88e5798b8ec53005ae66e4 100644 --- a/embassy/demos/common/src/menu.rs +++ b/embassy/demos/common/src/menu.rs @@ -317,6 +317,7 @@ where Outcome::CommandProcessed } else if input == 0x03 { // Handling ctrl-c, clear current command + let _ = write!(self.context, "\r"); Outcome::CommandProcessed } else if (input == 0x08) || (input == 0x7F) { // Handling backspace or delete @@ -364,8 +365,8 @@ where }; match outcome { Outcome::CommandProcessed => { + self.prompt(self.used > 0); self.used = 0; - self.prompt(true); } Outcome::NeedMore => {} } diff --git a/embassy/demos/picow/Cargo.toml b/embassy/demos/picow/Cargo.toml index fce77bd8b058a5820e8bf2588a4f5ee9e86c22ab..e14efbe6b0aad8e5e49134eee7b19b4a8f91e4f3 100644 --- a/embassy/demos/picow/Cargo.toml +++ b/embassy/demos/picow/Cargo.toml @@ -17,8 +17,8 @@ cyw43-pio = { version = "0.1.0", optional = true } embassy-net-w5500 = { version = "0.1.0", optional = true } embassy-executor = { version = "0.2", features = ["defmt", "integrated-timers", "executor-thread", "arch-cortex-m", "nightly"] } -embassy-time = { version = "0.1", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-rp = { version = "0.1.0", features = ["defmt", "unstable-traits", "nightly", "unstable-pac"] } +embassy-time = { version = "0.1", features = ["defmt", "defmt-timestamp-uptime", "unstable-traits", "nightly"] } +embassy-rp = { version = "0.1.0", features = ["defmt", "unstable-traits", "nightly", "unstable-pac", "time-driver"] } # embassy-net/nightly is required for asynch::Read/Write on TcpReader/TcpWriter embassy-net = { version = "0.1.0", features = ["tcp", "dhcpv4", "medium-ethernet", "nightly"] } embassy-net-driver = { version = "0.1.0" } diff --git a/embassy/demos/picow/build.rs b/embassy/demos/picow/build.rs index 7b19e112bcf15b4da9d3c3fe5ebc98363b5473a6..b51424e2d5855c1a5d8ce5efb8ab405a59d88d57 100644 --- a/embassy/demos/picow/build.rs +++ b/embassy/demos/picow/build.rs @@ -43,9 +43,9 @@ fn link() { fn git() { let git_rev = Command::new("git") - .args(&["describe", "--always", "--tags", "--dirty=+"]) + .args(["describe", "--always", "--tags", "--dirty=+"]) .output() - .map(|o| String::from_utf8(o.stdout).unwrap().to_string()) + .map(|o| String::from_utf8(o.stdout).unwrap()) .unwrap_or("(unknown)".to_string()); println!("cargo:rustc-env=GIT_REV={git_rev}"); diff --git a/embassy/demos/picow/firmware/43439A0.bin b/embassy/demos/picow/firmware/43439A0.bin index b46b3beff05de7dfcbf41d53a12bf3a74381881b..017375277d77d10e198deb1c668e2e6bb074d869 100755 Binary files a/embassy/demos/picow/firmware/43439A0.bin and b/embassy/demos/picow/firmware/43439A0.bin differ diff --git a/embassy/demos/picow/firmware/43439A0_clm.bin b/embassy/demos/picow/firmware/43439A0_clm.bin index 6e3ba786b2b496ef3d347d8f8150cb433f684692..1fedd753ac255eb8feb4b81a8214d4070a8e414c 100755 Binary files a/embassy/demos/picow/firmware/43439A0_clm.bin and b/embassy/demos/picow/firmware/43439A0_clm.bin differ diff --git a/embassy/demos/picow/firmware/README.md b/embassy/demos/picow/firmware/README.md index 7381fdc56bb2f2f8827f2664f0d3e3018fcbdc5d..db3d9c9cf79eabb68b7f0b4eb1700e88cf494257 100644 --- a/embassy/demos/picow/firmware/README.md +++ b/embassy/demos/picow/firmware/README.md @@ -2,4 +2,8 @@ Firmware obtained from https://github.com/Infineon/wifi-host-driver/tree/master/WiFi_Host_Driver/resources/firmware/COMPONENT_43439 -Licensed under the [Infineon Permissive Binary License](./LICENSE-permissive-binary-license-1.0.txt) \ No newline at end of file +Licensed under the [Infineon Permissive Binary License](./LICENSE-permissive-binary-license-1.0.txt) + +## Changelog + +* 2023-07-28: synced with `ad3bad0` - Update 43439 fw from 7.95.55 ot 7.95.62 diff --git a/embassy/demos/picow/src/flashconfig.rs b/embassy/demos/picow/src/flashconfig.rs index 792142b5ad6aaf8cbfe6c127a23b6535b55fc9a8..2b6e04d46c00689ff14c9ddd2c3d636d8a9da30d 100644 --- a/embassy/demos/picow/src/flashconfig.rs +++ b/embassy/demos/picow/src/flashconfig.rs @@ -12,7 +12,7 @@ pub use { #[cfg(feature = "defmt")] pub use defmt::{debug, info, warn, panic, error, trace}; -use embassy_rp::flash::{Flash, ERASE_SIZE}; +use embassy_rp::flash::{Flash, Async, ERASE_SIZE}; use embassy_rp::peripherals::FLASH; use sha2::Digest; @@ -30,6 +30,8 @@ use demo_common::SSHConfig; const CONFIG_OFFSET: u32 = 0x150000; pub const FLASH_SIZE: usize = 2*1024*1024; +pub(crate) type Fl<'a> = Flash<'a, FLASH, Async, FLASH_SIZE>; + // SSHConfig::CURRENT_VERSION must be bumped if any of this struct changes #[derive(SSHEncode, SSHDecode)] struct FlashConfig<'a> { @@ -50,7 +52,7 @@ fn config_hash(config: &SSHConfig) -> Result<[u8; 32]> { } /// Loads a SSHConfig at startup. Good for persisting hostkeys. -pub fn load_or_create(flash: &mut Flash<'_, FLASH, FLASH_SIZE>) -> Result<SSHConfig> { +pub fn load_or_create(flash: &mut Fl<'_>) -> Result<SSHConfig> { use snafu::Error; match load(flash) { Ok(c) => { @@ -64,7 +66,7 @@ pub fn load_or_create(flash: &mut Flash<'_, FLASH, FLASH_SIZE>) -> Result<SSHCon create(flash) } -pub fn create(flash: &mut Flash<'_, FLASH, FLASH_SIZE>) -> Result<SSHConfig> { +pub fn create(flash: &mut Fl<'_>) -> Result<SSHConfig> { let c = SSHConfig::new()?; if let Err(_) = save(flash, &c) { warn!("Error writing config"); @@ -72,7 +74,7 @@ pub fn create(flash: &mut Flash<'_, FLASH, FLASH_SIZE>) -> Result<SSHConfig> { Ok(c) } -pub fn load(flash: &mut Flash<'_, FLASH, FLASH_SIZE>) -> Result<SSHConfig> { +pub fn load(flash: &mut Fl<'_>) -> Result<SSHConfig> { // let mut buf = [0u8; ERASE_SIZE]; let mut buf = [0u8; FlashConfig::BUF_SIZE]; flash.read(CONFIG_OFFSET, &mut buf).map_err(|_| Error::msg("flash error"))?; @@ -102,7 +104,7 @@ pub fn load(flash: &mut Flash<'_, FLASH, FLASH_SIZE>) -> Result<SSHConfig> { } } -pub fn save(flash: &mut Flash<'_, FLASH, FLASH_SIZE>, config: &SSHConfig) -> Result<()> { +pub fn save(flash: &mut Fl<'_>, config: &SSHConfig) -> Result<()> { let mut buf = [0u8; ERASE_SIZE]; let sc = FlashConfig { version: SSHConfig::CURRENT_VERSION, diff --git a/embassy/demos/picow/src/main.rs b/embassy/demos/picow/src/main.rs index cb4089ac80fa79c88eba2fa29a2381bc8d894fde..b32fad1cce0ff86c7bf64faa09fc855c4060dc1f 100644 --- a/embassy/demos/picow/src/main.rs +++ b/embassy/demos/picow/src/main.rs @@ -16,8 +16,7 @@ use {defmt_rtt as _, panic_probe as _}; use embassy_executor::Spawner; use embassy_futures::select::select; -use embassy_net::Stack; -use embassy_rp::peripherals::FLASH; +use embassy_net::{Stack, HardwareAddress, EthernetAddress}; use embedded_io::asynch::Write as _; use embedded_io::{asynch, Io}; @@ -71,7 +70,7 @@ async fn main(spawner: Spawner) { getrandom::register_custom_getrandom!(caprand::getrandom); // Configuration loaded from flash - let mut flash = embassy_rp::flash::Flash::new(p.FLASH); + let mut flash = flashconfig::Fl::new(p.FLASH, p.DMA_CH2); let config = if option_env!("RESET_CONFIG").is_some() { flashconfig::create(&mut flash).unwrap() @@ -120,7 +119,9 @@ async fn main(spawner: Spawner) { ) .await; - let net_mac = stack.ethernet_address(); + let net_mac = match stack.hardware_address() { + HardwareAddress::Ethernet(EthernetAddress(eth)) => eth, + }; let g = GlobalState { usb_pipe, serial1_pipe, config, flash, watchdog, net_mac }; state = singleton!(g); for _ in 0..NUM_LISTENERS { @@ -137,7 +138,9 @@ async fn main(spawner: Spawner) { ) .await; - let net_mac = stack.ethernet_address(); + let net_mac = match stack.hardware_address() { + HardwareAddress::Ethernet(EthernetAddress(eth)) => eth, + }; let g = GlobalState { usb_pipe, serial1_pipe, config, flash, watchdog, net_mac }; state = singleton!(g); for _ in 0..NUM_LISTENERS { @@ -176,9 +179,7 @@ pub(crate) struct GlobalState { pub serial1_pipe: &'static TakePipe<'static>, pub config: &'static SunsetMutex<SSHConfig>, - pub flash: &'static SunsetMutex< - embassy_rp::flash::Flash<'static, FLASH, { flashconfig::FLASH_SIZE }>, - >, + pub flash: &'static SunsetMutex<flashconfig::Fl<'static>>, pub watchdog: &'static SunsetMutex<embassy_rp::watchdog::Watchdog>, pub net_mac: [u8; 6], diff --git a/embassy/demos/picow/src/w5500.rs b/embassy/demos/picow/src/w5500.rs index 324ebec8ef3c474d7ae9691210d643ef8e68ca50..b1676ed794c5d93d59c44f2796cf2bef01e6eec0 100644 --- a/embassy/demos/picow/src/w5500.rs +++ b/embassy/demos/picow/src/w5500.rs @@ -1,4 +1,4 @@ -// Modified from https://github.com/embassy-rs/cyw43/ +// Modified from https://github.com/embassy-rs/embassy/ // Copyright (c) 2019-2022 Embassy project contributors // MIT or Apache-2.0 license @@ -15,6 +15,7 @@ use embassy_net::{Stack, StackResources}; use embassy_rp::gpio::{Input, Level, Output, Pull}; use embassy_rp::peripherals::*; use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; +use embassy_time::Delay; use embedded_hal_async::spi::ExclusiveDevice; use embassy_net_w5500::*; @@ -30,7 +31,7 @@ use crate::{SSHConfig, SunsetMutex}; async fn ethernet_task( runner: Runner< 'static, - ExclusiveDevice<Spi<'static, SPI0, Async>, Output<'static, PIN_17>>, + ExclusiveDevice<Spi<'static, SPI0, Async>, Output<'static, PIN_17>, Delay>, Input<'static, PIN_21>, Output<'static, PIN_20>, >, @@ -65,7 +66,7 @@ pub(crate) async fn w5500_stack( let (device, runner) = embassy_net_w5500::new( mac_addr, state, - ExclusiveDevice::new(spi, cs), + ExclusiveDevice::new(spi, cs, Delay), w5500_int, w5500_reset, ) diff --git a/embassy/demos/picow/src/wifi.rs b/embassy/demos/picow/src/wifi.rs index a455ffd3134906b37199bda2e87384f1c5277ded..f0492c03f80b25ef5226c526cf3e1ad822c7e505 100644 --- a/embassy/demos/picow/src/wifi.rs +++ b/embassy/demos/picow/src/wifi.rs @@ -16,6 +16,7 @@ pub use defmt::{debug, info, warn, panic, error, trace}; use embassy_rp::gpio::{Level, Output}; use embassy_rp::pio::Pio; use embassy_rp::peripherals::*; +use embassy_rp::bind_interrupts; use embassy_executor::Spawner; use embassy_net::{Stack, StackResources}; @@ -28,6 +29,10 @@ use rand::RngCore; use crate::demo_common::singleton; use crate::{SunsetMutex, SSHConfig}; +bind_interrupts!(struct Irqs { + PIO0_IRQ_0 => embassy_rp::pio::InterruptHandler<PIO0>; +}); + #[embassy_executor::task] async fn wifi_task( runner: cyw43::Runner< @@ -52,7 +57,7 @@ pub(crate) async fn wifi_stack(spawner: &Spawner, let pwr = Output::new(p23, Level::Low); let cs = Output::new(p25, Level::High); - let mut pio = Pio::new(pio0); + let mut pio = Pio::new(pio0, Irqs); let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p24, p29, dma); let state = singleton!(cyw43::State::new()); @@ -115,7 +120,6 @@ async fn net_task(stack: &'static Stack<cyw43::NetDriver<'static>>) -> ! { // Get the WiFi firmware and Country Locale Matrix (CLM) blobs. fn get_fw() -> (&'static [u8], &'static [u8]) { - #[cfg(not(feature = "romfw"))] let (fw, clm) = ( include_bytes!("../firmware/43439A0.bin"), include_bytes!("../firmware/43439A0_clm.bin"), @@ -127,8 +131,8 @@ fn get_fw() -> (&'static [u8], &'static [u8]) { // probe-rs-cli download 43439A0_clm.bin --format bin --chip RP2040 --base-address 0x10140000 #[cfg(feature = "romfw")] let (fw, clm) = ( - unsafe { core::slice::from_raw_parts(0x10100000 as *const u8, 224190) }, - unsafe { core::slice::from_raw_parts(0x10140000 as *const u8, 4752) }, + unsafe { core::slice::from_raw_parts(0x10100000 as *const u8, fw.len()) }, + unsafe { core::slice::from_raw_parts(0x10140000 as *const u8, clm.len()) }, ); (fw, clm) diff --git a/embassy/src/embassy_sunset.rs b/embassy/src/embassy_sunset.rs index 0dc7a715b19574d255b909f9f402b12d05cb0546..1ee2e34cf57857419117074109ed6d87d0753951 100644 --- a/embassy/src/embassy_sunset.rs +++ b/embassy/src/embassy_sunset.rs @@ -67,7 +67,7 @@ impl<'a, C: CliBehaviour, S: ServBehaviour> Inner<'a, C, S> { self.chan_handles[num.0 as usize].as_ref().map(|ch| { (&mut self.runner, ch, &mut self.wakers) }) - .ok_or_else(|| Error::bug()) + .ok_or_else(Error::bug) } } @@ -166,8 +166,8 @@ impl<'a, C: CliBehaviour, S: ServBehaviour> EmbassySunset<'a, C, S> { break } let mut buf = &buf[..l]; - while buf.len() > 0 { - let n = self.input(&buf).await?; + while !buf.is_empty() { + let n = self.input(buf).await?; buf = &buf[n..]; } } @@ -352,7 +352,7 @@ impl<'a, C: CliBehaviour, S: ServBehaviour> EmbassySunset<'a, C, S> { // Attempt to lock .inner let i = self.inner.lock(); pin_mut!(i); - let r = match i.poll(cx) { + match i.poll(cx) { Poll::Ready(mut inner) => { f(&mut inner, cx) } @@ -360,8 +360,7 @@ impl<'a, C: CliBehaviour, S: ServBehaviour> EmbassySunset<'a, C, S> { // .inner lock is busy Poll::Pending } - }; - r + } }) .await } @@ -559,7 +558,7 @@ pub async fn io_buf_copy<R, W>(r: &mut R, w: &mut W) -> Result<()> { loop { let b = r.fill_buf().await?; - if b.len() == 0 { + if b.is_empty() { return sunset::error::ChannelEOF.fail(); } let n = b.len(); @@ -583,7 +582,7 @@ pub async fn io_buf_copy_noreaderror<R, W>(r: &mut R, w: &mut W) -> Result<()> continue; } }; - if b.len() == 0 { + if b.is_empty() { return sunset::error::ChannelEOF.fail(); } let n = b.len(); diff --git a/src/channel.rs b/src/channel.rs index 885677c3292f9f03dcecac2275e98189c3894a11..fd6e5f38f90f6157be09a593d62ef992b80b1e42 100644 --- a/src/channel.rs +++ b/src/channel.rs @@ -163,7 +163,7 @@ impl<C: CliBehaviour, S: ServBehaviour> Channels<C, S> { dt: ChanData, data: &'b [u8], ) -> Result<Packet<'b>> { - debug_assert!(data.len() > 0); + debug_assert!(!data.is_empty()); let ch = self.get_mut(num)?; let send = ch.send.as_mut().trap()?; @@ -330,9 +330,9 @@ impl<C: CliBehaviour, S: ServBehaviour> Channels<C, S> { if matches!(ch.ty, ChanType::Session) { // let the CliBehaviour open a shell etc - let mut opener = SessionOpener::new(&ch, s); + let mut opener = SessionOpener::new(ch, s); let r = b.client()?.session_opened(ch.num(), &mut opener).await; - if let Err(_) = r { + if r.is_err() { trace!("Error from session_opened"); } } @@ -793,10 +793,7 @@ impl Channel { } fn have_recv_eof(&self) -> bool { - match self.state { - ChanState::RecvEof | ChanState::RecvClose => true, - _ => false, - } + matches!(self.state, ChanState::RecvEof | ChanState::RecvClose) } fn is_closed(&self) -> bool { diff --git a/src/cliauth.rs b/src/cliauth.rs index a4c9abbbdca031f5dfc236434cc53014bbe37032..9b279895e55f8839a81a89402f0871dd8382c7f0 100644 --- a/src/cliauth.rs +++ b/src/cliauth.rs @@ -143,6 +143,7 @@ impl CliAuth { &mut self, b: &mut impl CliBehaviour, ) -> Option<Req> { + #[allow(clippy::never_loop)] loop { let k = b.next_authkey().unwrap_or_else(|_| { warn!("Error getting pubkey for auth"); @@ -241,7 +242,7 @@ impl CliAuth { // Sign the packet without the signature let p = last_req.req_packet(&self.username, parse_ctx, None)?; - let new_sig = Self::auth_sig_msg(&key, sess_id, &p, b).await?; + let new_sig = Self::auth_sig_msg(key, sess_id, &p, b).await?; let p = last_req.req_packet(&self.username, parse_ctx, Some(&new_sig))?; s.send(p)?; @@ -306,7 +307,7 @@ impl CliAuth { pub fn success(&mut self, b: &mut impl CliBehaviour) -> Result<()> { // TODO: check current state? Probably just informational self.state = AuthState::Idle; - let _ = b.authenticated(); + b.authenticated(); // TODO errors Ok(()) } diff --git a/src/conn.rs b/src/conn.rs index 1df974325f6389798f0e4ea8801c4891132d2608..ab2c401c39d2e24949478ce5d8c7075070b12e4c 100644 --- a/src/conn.rs +++ b/src/conn.rs @@ -161,10 +161,7 @@ impl<C: CliBehaviour, S: ServBehaviour> Conn<C, S> { } pub(crate) fn initial_sent(&self) -> bool { - match self.state { - ConnState::SendIdent => false, - _ => true, - } + !matches!(self.state, ConnState::SendIdent) } /// Consumes an input payload which is a view into [`traffic::Traffic::rxbuf`]. @@ -188,7 +185,7 @@ impl<C: CliBehaviour, S: ServBehaviour> Conn<C, S> { } Err(e) => { error!("Error decoding packet: {e}"); - return Err(e) + Err(e) } } } diff --git a/src/encrypt.rs b/src/encrypt.rs index 4ddadef659b2085003909fa08ae75e4ebe24e1bd..8d9c0949c00fbe23cf5cdeac2b28e9646277945c 100644 --- a/src/encrypt.rs +++ b/src/encrypt.rs @@ -6,21 +6,24 @@ use { log::{debug, error, info, log, trace, warn}, }; -use core::num::Wrapping; use core::fmt; use core::fmt::Debug; +use core::num::Wrapping; -use aes::{cipher::{BlockSizeUser, KeyIvInit, KeySizeUser, StreamCipher}, Aes256}; -use pretty_hex::PrettyHex; -use zeroize::ZeroizeOnDrop; +use aes::{ + cipher::{BlockSizeUser, KeyIvInit, KeySizeUser, StreamCipher}, + Aes256, +}; use hmac::{Hmac, Mac}; +use pretty_hex::PrettyHex; use sha2::Digest as Sha2DigestForTrait; +use zeroize::ZeroizeOnDrop; use crate::*; use kex::{self, SessId}; +use ssh_chapoly::SSHChaPoly; use sshnames::*; use sshwire::hash_mpint; -use ssh_chapoly::SSHChaPoly; // TODO: check that Ctr32 is sufficient. Should be OK with SSH rekeying. type Aes256Ctr32BE = ctr::Ctr32BE<aes::Aes256>; @@ -79,7 +82,7 @@ impl KeyState { /// Decrypt bytes 4 onwards of the buffer and validate AEAD Tag or MAC. /// Ensures that the packet meets minimum length. - pub fn decrypt<'b>(&mut self, buf: &'b mut [u8]) -> Result<usize, Error> { + pub fn decrypt(&mut self, buf: &mut [u8]) -> Result<usize, Error> { let e = self.keys.decrypt(buf, self.seq_decrypt.0); self.seq_decrypt += 1; e @@ -88,8 +91,10 @@ impl KeyState { /// [`buf`] is the entire output buffer to encrypt in place. /// payload_len is the length of the payload portion /// This is stateful, updating the sequence number. - pub fn encrypt<'b>( - &mut self, payload_len: usize, buf: &'b mut [u8], + pub fn encrypt( + &mut self, + payload_len: usize, + buf: &mut [u8], ) -> Result<usize, Error> { let e = self.keys.encrypt(payload_len, buf, self.seq_encrypt.0); self.seq_encrypt += 1; @@ -149,8 +154,10 @@ impl Keys { } } - pub fn derive(kex_out: kex::KexOutput, - sess_id: &SessId, algos: &kex::Algos, + pub fn derive( + kex_out: kex::KexOutput, + sess_id: &SessId, + algos: &kex::Algos, ) -> Result<Self, Error> { let mut key = [0u8; MAX_KEY_LEN]; let mut iv = [0u8; MAX_IV_LEN]; @@ -222,7 +229,9 @@ impl Keys { /// Whether bytes `buf[4..block_size]` are decrypted depends on the cipher, they may be /// handled later by [`decrypt`]. Bytes `buf[0..4]` may be left unmodified. fn decrypt_first_block( - &mut self, buf: &mut [u8], seq: u32, + &mut self, + buf: &mut [u8], + seq: u32, ) -> Result<usize, Error> { if buf.len() < self.dec.size_block() { return Err(Error::bug()); @@ -279,9 +288,7 @@ impl Keys { match &mut self.dec { DecKey::ChaPoly(k) => { - k.decrypt(seq, data, mac).map_err(|_| { - Error::BadDecrypt - })?; + k.decrypt(seq, data, mac).map_err(|_| Error::BadDecrypt)?; } DecKey::Aes256Ctr(a) => { // safe index, checked data.len() @@ -297,9 +304,7 @@ impl Keys { let mut h = HmacSha256::new_from_slice(&k).trap()?; h.update(&seq.to_be_bytes()); h.update(data); - h.verify_slice(mac).map_err(|_| { - Error::BadDecrypt - })?; + h.verify_slice(mac).map_err(|_| Error::BadDecrypt)?; } } @@ -345,7 +350,10 @@ impl Keys { /// Returns the total length. /// Ensures that the packet meets minimum and other length requirements. fn encrypt( - &mut self, payload_len: usize, buf: &mut [u8], seq: u32, + &mut self, + payload_len: usize, + buf: &mut [u8], + seq: u32, ) -> Result<usize, Error> { let size_block = self.enc.size_block(); let size_integ = self.integ_enc.size_out(); @@ -389,9 +397,7 @@ impl Keys { } match &mut self.enc { - EncKey::ChaPoly(k) => { - k.encrypt(seq, enc, mac).trap()? - } + EncKey::ChaPoly(k) => k.encrypt(seq, enc, mac).trap()?, EncKey::Aes256Ctr(a) => { a.apply_keystream(enc); } @@ -484,7 +490,9 @@ impl Debug for EncKey { impl EncKey { /// Construct a key pub fn from_cipher<'a>( - cipher: &Cipher, key: &'a [u8], iv: &'a [u8], + cipher: &Cipher, + key: &'a [u8], + iv: &'a [u8], ) -> Result<Self, Error> { match cipher { Cipher::ChaPoly => { @@ -534,7 +542,9 @@ impl Debug for DecKey { impl DecKey { /// Construct a key pub fn from_cipher<'a>( - cipher: &Cipher, key: &'a [u8], iv: &'a [u8], + cipher: &Cipher, + key: &'a [u8], + iv: &'a [u8], ) -> Result<Self, Error> { match cipher { Cipher::ChaPoly => { @@ -616,12 +626,10 @@ impl Debug for IntegKey { } impl IntegKey { - pub fn from_integ<'a>(integ: &Integ, key: &'a [u8]) -> Result<Self, Error> { + pub fn from_integ(integ: &Integ, key: &[u8]) -> Result<Self, Error> { match integ { Integ::ChaPoly => Ok(IntegKey::ChaPoly), - Integ::HmacSha256 => { - Ok(IntegKey::HmacSha256(key.try_into().trap()?)) - } + Integ::HmacSha256 => Ok(IntegKey::HmacSha256(key.try_into().trap()?)), } } pub fn size_out(&self) -> usize { @@ -635,17 +643,21 @@ impl IntegKey { #[cfg(test)] mod tests { - use crate::sunsetlog::*; use crate::encrypt::*; - use crate::kex::KexOutput; use crate::error::Error; + use crate::kex::KexOutput; use crate::sshnames::SSH_NAME_CURVE25519; + use crate::sunsetlog::*; #[allow(unused_imports)] use pretty_hex::PrettyHex; use sha2::Sha256; // setting `corrupt` tests that incorrect mac is detected - fn do_roundtrips(keys_enc: &mut KeyState, keys_dec: &mut KeyState, corrupt: bool) { + fn do_roundtrips( + keys_enc: &mut KeyState, + keys_dec: &mut KeyState, + corrupt: bool, + ) { for i in 0usize..80 { let mut v: std::vec::Vec<u8> = (0u8..i as u8 + 60).collect(); let orig_payload = v[SSH_PAYLOAD_START..SSH_PAYLOAD_START + i].to_vec(); @@ -698,33 +710,33 @@ mod tests { // TODO make this combinatorial // order is enc, dec const COMBOS: [(Cipher, Integ, Cipher, Integ); 4] = [ - (Cipher::Aes256Ctr, Integ::HmacSha256, - Cipher::Aes256Ctr, Integ::HmacSha256), - - (Cipher::ChaPoly, Integ::ChaPoly, - Cipher::ChaPoly, Integ::ChaPoly), - - (Cipher::Aes256Ctr, Integ::HmacSha256, - Cipher::ChaPoly, Integ::ChaPoly), - - (Cipher::ChaPoly, Integ::ChaPoly, - Cipher::Aes256Ctr, Integ::HmacSha256), + ( + Cipher::Aes256Ctr, + Integ::HmacSha256, + Cipher::Aes256Ctr, + Integ::HmacSha256, + ), + (Cipher::ChaPoly, Integ::ChaPoly, Cipher::ChaPoly, Integ::ChaPoly), + (Cipher::Aes256Ctr, Integ::HmacSha256, Cipher::ChaPoly, Integ::ChaPoly), + (Cipher::ChaPoly, Integ::ChaPoly, Cipher::Aes256Ctr, Integ::HmacSha256), ]; - COMBOS.iter().map(|(ce, ie, cd, id)| { - Some(kex::Algos { - kex: kex::SharedSecret::from_name(SSH_NAME_CURVE25519).unwrap(), - hostsig: sign::SigType::Ed25519, - cipher_enc: ce.clone(), - cipher_dec: cd.clone(), - integ_enc: ie.clone(), - integ_dec: id.clone(), - discard_next: false, - is_client: false, - send_ext_info: true, + COMBOS + .iter() + .map(|(ce, ie, cd, id)| { + Some(kex::Algos { + kex: kex::SharedSecret::from_name(SSH_NAME_CURVE25519).unwrap(), + hostsig: sign::SigType::Ed25519, + cipher_enc: ce.clone(), + cipher_dec: cd.clone(), + integ_enc: ie.clone(), + integ_dec: id.clone(), + discard_next: false, + is_client: false, + send_ext_info: true, + }) }) - }) - // and plaintext - .chain(core::iter::once(None)) + // and plaintext + .chain(core::iter::once(None)) } #[test] @@ -732,13 +744,17 @@ mod tests { init_test_log(); for mut algos in algo_combos() { - let mut keys_enc = KeyState::new_cleartext(); let mut keys_dec = KeyState::new_cleartext(); if let Some(ref mut algos) = algos { // arbitrary keys - let h = SessId::from_slice(&Sha256::digest("some exchange hash".as_bytes())).unwrap(); - let sess_id = SessId::from_slice(&Sha256::digest("some sessid".as_bytes())).unwrap(); + let h = SessId::from_slice(&Sha256::digest( + "some exchange hash".as_bytes(), + )) + .unwrap(); + let sess_id = + SessId::from_slice(&Sha256::digest("some sessid".as_bytes())) + .unwrap(); let sharedkey = b"hello"; let ko = KexOutput::new_test(sharedkey, &algos, &h); let ko_b = KexOutput::new_test(sharedkey, &algos, &h); @@ -755,7 +771,6 @@ mod tests { trace!("algos dec {algos:?}"); let newkeys_b = Keys::derive(ko_b, &sess_id, &algos).unwrap(); keys_dec.rekey(newkeys_b); - } else { trace!("Trying cleartext"); } @@ -772,12 +787,13 @@ mod tests { fn max_enc_payload() { init_test_log(); for algos in algo_combos() { - let mut keys = KeyState::new_cleartext(); if let Some(algos) = algos { // arbitrary keys - let h = SessId::from_slice(&Sha256::digest(b"some exchange hash")).unwrap(); - let sess_id = SessId::from_slice(&Sha256::digest(b"some sessid")).unwrap(); + let h = SessId::from_slice(&Sha256::digest(b"some exchange hash")) + .unwrap(); + let sess_id = + SessId::from_slice(&Sha256::digest(b"some sessid")).unwrap(); let sharedkey = b"hello"; let ko = KexOutput::new_test(sharedkey, &algos, &h); let newkeys = Keys::derive(ko, &sess_id, &algos).unwrap(); @@ -801,7 +817,7 @@ mod tests { assert!(l >= i.saturating_sub(keys.keys.enc.size_block())); // check a larger payload would bump the packet size - let l = keys.encrypt(p+1, &mut buf).unwrap(); + let l = keys.encrypt(p + 1, &mut buf).unwrap(); assert!(l > i); } } diff --git a/src/ident.rs b/src/ident.rs index 256904143250068b2a6b904343512822211eb9ff..49f28d3cbd35c9a1de5bb6096d09c59ce994eb51 100644 --- a/src/ident.rs +++ b/src/ident.rs @@ -24,7 +24,7 @@ pub(crate) fn write_version(buf: &mut [u8]) -> Result<usize> { b[0] = CR; b[1] = LF; - return Ok(total_len) + Ok(total_len) } /// Parses and stores the remove SSH version string diff --git a/src/kex.rs b/src/kex.rs index f0ed5f0cb8ad9f8f4c5fb93b16d9a5212c9d0b6c..9ae87e4f3113f9ab85fda0989bb39e2a84cc800a 100644 --- a/src/kex.rs +++ b/src/kex.rs @@ -32,23 +32,23 @@ pub type SessId = heapless::Vec<u8, MAX_SESSID>; use pretty_hex::PrettyHex; // TODO this will be configurable. -const fixed_options_kex: &[&'static str] = +const fixed_options_kex: &[&str] = &[SSH_NAME_CURVE25519, SSH_NAME_CURVE25519_LIBSSH]; /// Options that can't be negotiated -const marker_only_kexs: &[&'static str] = +const marker_only_kexs: &[&str] = &[SSH_NAME_EXT_INFO_C, SSH_NAME_EXT_INFO_S, SSH_NAME_KEXGUESS2]; -const fixed_options_hostsig: &[&'static str] = &[ +const fixed_options_hostsig: &[&str] = &[ SSH_NAME_ED25519, #[cfg(feature = "rsa")] SSH_NAME_RSA_SHA256, ]; -const fixed_options_cipher: &[&'static str] = +const fixed_options_cipher: &[&str] = &[SSH_NAME_CHAPOLY, SSH_NAME_AES256_CTR]; -const fixed_options_mac: &[&'static str] = &[SSH_NAME_HMAC_SHA256]; -const fixed_options_comp: &[&'static str] = &[SSH_NAME_NONE]; +const fixed_options_mac: &[&str] = &[SSH_NAME_HMAC_SHA256]; +const fixed_options_comp: &[&str] = &[SSH_NAME_NONE]; pub(crate) struct AlgoConfig { kexs: LocalNames, @@ -193,7 +193,7 @@ impl KexHash { // Hashes a slice, with added u32 length prefix. fn hash_slice(&mut self, v: &[u8]) { - self.hash_ctx.update(&(v.len() as u32).to_be_bytes()); + self.hash_ctx.update((v.len() as u32).to_be_bytes()); self.hash_ctx.update(v); } } @@ -292,7 +292,7 @@ impl Kex { fn make_kexinit<'a>(cookie: &'a KexCookie, conf: &'a AlgoConfig) -> Packet<'a> { packets::KexInit { - cookie: cookie, + cookie, kex: (&conf.kexs).into(), hostsig: (&conf.hostsig).into(), cipher_c2s: (&conf.ciphers).into(), @@ -568,7 +568,7 @@ impl SharedSecret { } // server only. consumes algos and kex_hash - fn handle_kexdhinit<'a>( + fn handle_kexdhinit( algos: &mut Algos, mut kex_hash: KexHash, p: &packets::KexDHInit, s: &mut TrafSend, b: &mut impl ServBehaviour, @@ -666,18 +666,18 @@ impl KexOutput { let (k1, rest) = out.split_at_mut(l); let (k2, _) = rest.split_at_mut(len - l); - let sess_id: &[u8] = &sess_id; + let sess_id: &[u8] = sess_id; let mut hash_ctx = self.partial_hash.clone(); // K || H is already included - hash_ctx.update(&[letter as u8]); + hash_ctx.update([letter as u8]); hash_ctx.update(sess_id); hash_ctx.finalize_into(w.into()); // fill first part k1.copy_from_slice(&w[..k1.len()]); - if k2.len() > 0 { + if !k2.is_empty() { // generate next block K2 = HASH(K || H || K1) let mut hash_ctx = self.partial_hash.clone(); // K || H is already included diff --git a/src/namelist.rs b/src/namelist.rs index f871fac8053eec7e86149965ca30fd9e8a48b9bc..9babd64fb966c90d838732fa7c58f34f8403f8e6 100644 --- a/src/namelist.rs +++ b/src/namelist.rs @@ -190,7 +190,7 @@ impl LocalNames { } pub fn first(&self) -> &str { - if self.0.len() == 0 { + if self.0.is_empty() { "" } else { self.0[0] diff --git a/src/runner.rs b/src/runner.rs index 2df15bf169e0114fd0778bae5f33c554d5e727f2..5f5750177faa7a955119a810cf4ed50a02d2b498 100644 --- a/src/runner.rs +++ b/src/runner.rs @@ -186,8 +186,9 @@ impl<'a, C: CliBehaviour, S: ServBehaviour> Runner<'a, C, S> { return } } - self.input_waker.replace(waker.clone()) - .map(|w| w.wake()); + if let Some(w) = self.input_waker.replace(waker.clone()) { + w.wake() + } } /// Set a waker to be notified when SSH socket output is ready @@ -197,8 +198,9 @@ impl<'a, C: CliBehaviour, S: ServBehaviour> Runner<'a, C, S> { return } } - self.output_waker.replace(waker.clone()) - .map(|w| w.wake()); + if let Some(w) = self.input_waker.replace(waker.clone()) { + w.wake() + } } pub fn close(&mut self) { @@ -232,7 +234,7 @@ impl<'a, C: CliBehaviour, S: ServBehaviour> Runner<'a, C, S> { return error::ChannelEOF.fail() } - if buf.len() == 0 { + if buf.is_empty() { return Ok(0) } diff --git a/src/servauth.rs b/src/servauth.rs index 838d3c96e9d2e52d07c090327513868a4da772b9..d72186fb0c87591e48723daae7bbe61189e2b162 100644 --- a/src/servauth.rs +++ b/src/servauth.rs @@ -39,7 +39,7 @@ impl ServAuth { // TODO: what to do they've already authed? we have to be careful in case // behaviours don't handle it well. - let username = p.username.clone(); + let username = p.username; let inner = async { // even allows "none" auth @@ -142,14 +142,14 @@ impl ServAuth { Err(_) => return false, }; - let msg = auth::AuthSigMsg::new(&p, sess_id); + let msg = auth::AuthSigMsg::new(p, sess_id); match sig_type.verify(&m.pubkey.0, &&msg, sig) { Ok(()) => true, Err(e) => { trace!("sig failed {e}"); false}, } } - fn avail_methods<'f>( + fn avail_methods( &self, user: TextString, b: &mut impl ServBehaviour, diff --git a/src/ssh_chapoly.rs b/src/ssh_chapoly.rs index af70c90486ba4dcd10a235175906b4e4fa7d7cc2..0c333fa99d6f30c7ab85cb72fd4f263d8f004dcb 100644 --- a/src/ssh_chapoly.rs +++ b/src/ssh_chapoly.rs @@ -64,7 +64,7 @@ impl SSHChaPoly { let mut c = Self::cha20(&self.k1, seq); c.apply_keystream(&mut b); trace!("packet_length {:?}", b.hex_dump()); - Ok(u32::from_be_bytes(b.try_into().unwrap())) + Ok(u32::from_be_bytes(b)) } /// Decrypts in-place and validates the MAC. @@ -87,7 +87,7 @@ impl SSHChaPoly { let poly = Poly1305::new((&poly_key).into()); // compute_unpadded() adds the necessary trailing 1 byte when padding output let tag = poly.compute_unpadded(msg); - let good: bool = tag.ct_eq(&msg_tag).into(); + let good: bool = tag.ct_eq(msg_tag).into(); if !good { return Err(Error::BadDecrypt); } diff --git a/src/sshwire.rs b/src/sshwire.rs index 1f5498ad690800ea3566e3b6214c377307b43e74..882f1c19e8eee8c15df750c4ed0debba90e006b3 100644 --- a/src/sshwire.rs +++ b/src/sshwire.rs @@ -246,7 +246,7 @@ impl<'de> SSHSource<'de> for DecodeBytes<'de> { // Hashes a slice to be treated as a mpint. Has u32 length prefix // and an extra 0x00 byte if the MSB is set. pub fn hash_mpint(hash_ctx: &mut dyn SSHWireDigestUpdate, m: &[u8]) { - let pad = m.len() > 0 && (m[0] & 0x80) != 0; + let pad = !m.is_empty() && (m[0] & 0x80) != 0; let l = m.len() as u32 + pad as u32; hash_ctx.digest_update(&l.to_be_bytes()); if pad { @@ -657,7 +657,7 @@ impl<'de, T: SSHDecode<'de>> SSHDecode<'de> for OwnOrBorrow<'_, T> { impl<'a, T> core::borrow::Borrow<T> for OwnOrBorrow<'a, T> { fn borrow(&self) -> &T { match self { - Self::Own(t) => &t, + Self::Own(t) => t, Self::Borrow(t) => t, } } diff --git a/src/traffic.rs b/src/traffic.rs index 8162cd9fe54ea05ca6f60cc2c3776bdb510bc253..5261d41e82c821d20424772a3fbe062d2ad6e016 100644 --- a/src/traffic.rs +++ b/src/traffic.rs @@ -164,7 +164,7 @@ impl<'a> TrafIn<'a> { // Fill the initial block from either Idle with input, // partial initial block if let Some(idx) = match self.state { - RxState::Idle if r.len() > 0 => Some(0), + RxState::Idle if !r.is_empty() => Some(0), RxState::ReadInitial { idx } => Some(idx), _ => None, } { @@ -346,7 +346,7 @@ impl<'a> TrafOut<'a> { } let plen = sshwire::write_ssh(&mut wbuf[SSH_PAYLOAD_START..], &p)?; trace!("Sending {p:?}"); - trace!("new {plen} {:?}", (&wbuf[SSH_PAYLOAD_START..SSH_PAYLOAD_START+plen]).hex_dump()); + trace!("new {plen} {:?}", (wbuf[SSH_PAYLOAD_START..SSH_PAYLOAD_START+plen]).hex_dump()); // Encrypt in place let elen = keys.encrypt(plen, wbuf)?; @@ -356,10 +356,7 @@ impl<'a> TrafOut<'a> { } pub fn is_output_pending(&self) -> bool { - match self.state { - TxState::Write { .. } => true, - _ => false - } + matches!(self.state, TxState::Write { .. }) } /// A simple test if a packet can be sent. `send_allowed` should be used @@ -389,7 +386,7 @@ impl<'a> TrafOut<'a> { return Err(Error::bug()); } - let len = ident::write_version(&mut self.buf)?; + let len = ident::write_version(self.buf)?; self.state = TxState::Write { idx: 0, len }; Ok(()) } @@ -429,7 +426,7 @@ pub(crate) struct TrafSend<'s, 'a> { } impl<'s, 'a> TrafSend<'s, 'a> { - fn new<'f>(out: &'s mut TrafOut<'a>, keys: &'s mut KeyState) -> Self { + fn new(out: &'s mut TrafOut<'a>, keys: &'s mut KeyState) -> Self { Self { out, keys, diff --git a/sshwire-derive/src/lib.rs b/sshwire-derive/src/lib.rs index e509c8e43caca4d38a6b71d9376a68b6b2898c55..88bd0f3f542307f9eda24af00f850dd29720f9aa 100644 --- a/sshwire-derive/src/lib.rs +++ b/sshwire-derive/src/lib.rs @@ -12,12 +12,11 @@ use virtue::parse::{Attribute, AttributeLocation, EnumBody, StructBody}; use virtue::utils::{parse_tagged_attribute, ParsedAttribute}; use virtue::prelude::*; -const ENV_SSHWIRE_DEBUG: &'static str = &"SSHWIRE_DEBUG"; +const ENV_SSHWIRE_DEBUG: &str = "SSHWIRE_DEBUG"; #[proc_macro_derive(SSHEncode, attributes(sshwire))] pub fn derive_encode(input: proc_macro::TokenStream) -> proc_macro::TokenStream { - let r = encode_inner(input).unwrap_or_else(|e| e.into_token_stream()); - r + encode_inner(input).unwrap_or_else(|e| e.into_token_stream()) } #[proc_macro_derive(SSHDecode, attributes(sshwire))] @@ -187,7 +186,7 @@ fn take_field_atts(atts: &[Attribute]) -> Result<Vec<FieldAtt>> { }), }; - if let Some(_) = g.next() { + if g.next().is_some() { Err(Error::Custom { error: "Extra unhandled parts".into(), span: Some(a.tokens.span()), diff --git a/testing/ci.sh b/testing/ci.sh index 160580d279555048cf71580e029e3fcbefaa4314..409e1552fdac15669636717ead2a28bb3672396b 100755 --- a/testing/ci.sh +++ b/testing/ci.sh @@ -62,6 +62,7 @@ cd embassy/demos/picow cargo build --release cargo bloat --release -n 100 | tee "$OUT/picow-bloat.txt" cargo bloat --release --crates | tee "$OUT/picow-bloat-crates.txt" +cargo build --release --no-default-features --features w5500,romfw ) size target/thumbv6m-none-eabi/release/sunset-demo-embassy-picow | tee "$OUT/picow-size.txt"