diff --git a/Cargo.toml b/Cargo.toml index 61916f6..361ba7a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -82,5 +82,3 @@ simplelog = { version = "0.12", features = ["test"] } [patch.crates-io] -# needed for Default WakerRegistration, https://github.com/embassy-rs/embassy/commit/14a2d1524080593f7795fe14950a3f0ee6e2b409 -embassy-sync = { git = "https://github.com/embassy-rs/embassy", rev = "e1eac15c429f88b1176109d6ce42185e2774ac86" } diff --git a/async/Cargo.toml b/async/Cargo.toml index 39b2929..39020ea 100644 --- a/async/Cargo.toml +++ b/async/Cargo.toml @@ -16,7 +16,7 @@ argh = "0.1" ssh-key = { version = "0.5", default-features = false, features = [ "std"] } -embassy-sync = { version = "0.1.0" } +embassy-sync = { version = "0.2.0" } embassy-futures = { version = "0.1.0" } # async feature requires nightly for async fn in trait diff --git a/async/src/known_hosts.rs b/async/src/known_hosts.rs index eb7a166..2fe063a 100644 --- a/async/src/known_hosts.rs +++ b/async/src/known_hosts.rs @@ -100,7 +100,7 @@ pub fn check_known_hosts_file( let known_key = match OpenSSHKey::from_openssh(&lk) { Ok(k) => k, Err(e) => { - warn!("Unparsed key for {} on line {}:{}", host, p.display(), line); + warn!("Unparsed key for \"{}\" on line {}:{}", host, p.display(), line); trace!("{e:?}"); continue; } diff --git a/embassy/Cargo.toml b/embassy/Cargo.toml index 586ce67..d90a643 100644 --- a/embassy/Cargo.toml +++ b/embassy/Cargo.toml @@ -4,7 +4,7 @@ version = "0.2.0-alpha" edition = "2021" [dependencies] -embassy-sync = { version = "0.1.0" } +embassy-sync = { version = "0.2.0" } embassy-futures = { version = "0.1.0" } embedded-io = { version = "0.4", features = ["async"] } atomic-polyfill = "1.0" diff --git a/embassy/demos/common/Cargo.toml b/embassy/demos/common/Cargo.toml new file mode 100644 index 0000000..7b68009 --- /dev/null +++ b/embassy/demos/common/Cargo.toml @@ -0,0 +1,29 @@ +[package] +name = "sunset-demo-embassy-common" +description = "Shared code for Sunset demos" +version = "0.1.0" +edition = "2021" + +[workspace] +# blank + +[dependencies] +sunset-embassy = { path = "../../" } +sunset = { path = "../../.." } +sunset-sshwire-derive = { version = "0.1", path = "../../../sshwire-derive" } + +embassy-sync = { version = "0.2.0" } +embassy-net = { version = "0.1.0", features = ["tcp", "dhcpv4", "medium-ethernet", "nightly"] } +embassy-net-driver = { version = "0.1.0" } +embassy-futures = { version = "0.1.0" } + +heapless = "0.7.15" +menu = "0.3" +embedded-io = { version = "0.4", features = ["async"] } + +defmt = { version = "0.3", optional = true } +log = { version = "0.4", optional = true } + +[features] +defmt = ["dep:defmt", "embassy-net/defmt", "embedded-io/defmt"] +log = ["dep:log", "embassy-net/log"] diff --git a/embassy/demos/common/README.md b/embassy/demos/common/README.md index 225de75..89ced50 100644 --- a/embassy/demos/common/README.md +++ b/embassy/demos/common/README.md @@ -1,4 +1,3 @@ # Embassy demos common -The [picow](../picow) and [std](../std) demos share this common code. -Currently not a full crate, just source modules included. +The [picow](../picow) and [std](../std) demos share this common code. diff --git a/embassy/demos/common/src/config.rs b/embassy/demos/common/src/config.rs new file mode 100644 index 0000000..1cb6ec5 --- /dev/null +++ b/embassy/demos/common/src/config.rs @@ -0,0 +1,108 @@ +#[allow(unused_imports)] +use { + sunset::error::{Error, Result, TrapBug}, +}; + +#[allow(unused_imports)] +#[cfg(not(feature = "defmt"))] +use { + log::{debug, error, info, log, trace, warn}, +}; + +#[allow(unused)] +#[cfg(feature = "defmt")] +use defmt::{debug, info, warn, panic, error, trace}; + +use heapless::String; + +use sunset_sshwire_derive::*; +use sunset::sshwire; +use sunset::sshwire::{BinString, SSHEncode, SSHDecode, WireResult, SSHSource, SSHSink, WireError}; + +use sunset::{SignKey, KeyType}; + +// Be sure to bump picow flash_config::CURRENT_VERSION +// if this struct changes (or encode/decode impls). +#[derive(Debug)] +pub struct SSHConfig { + pub hostkey: SignKey, + /// login password + pub pw_hash: Option<[u8; 32]>, + /// SSID + pub wifi_net: String<32>, + /// WPA2 passphrase. None is Open network. + pub wifi_pw: Option<String<63>>, +} + +impl SSHConfig { + /// Creates a new config with default parameters. + /// + /// Will only fail on RNG failure. + pub fn new() -> Result<Self> { + let hostkey = SignKey::generate(KeyType::Ed25519, None)?; + + let wifi_net = option_env!("WIFI_NETWORK").unwrap_or("guest").into(); + let wifi_pw = option_env!("WIFI_PASSWORD").map(|p| p.into()); + Ok(SSHConfig { + hostkey, + pw_hash: None, + wifi_net, + wifi_pw, + }) + } +} + +// a private encoding specific to demo config, not SSH defined. +fn enc_signkey(k: &SignKey, s: &mut dyn SSHSink) -> WireResult<()> { + // need to add a variant field if we support more key types. + match k { + SignKey::Ed25519(seed) => seed.enc(s), + _ => Err(WireError::UnknownVariant), + } +} + +fn dec_signkey<'de, S>(s: &mut S) -> WireResult<SignKey> where S: SSHSource<'de> { + Ok(SignKey::Ed25519(SSHDecode::dec(s)?)) +} + +impl SSHEncode for SSHConfig { + fn enc(&self, s: &mut dyn SSHSink) -> WireResult<()> { + enc_signkey(&self.hostkey, s)?; + self.pw_hash.is_some().enc(s)?; + self.pw_hash.enc(s)?; + + self.wifi_net.as_str().enc(s)?; + + self.wifi_pw.is_some().enc(s)?; + if let Some(ref p) = self.wifi_pw { + p.as_str().enc(s)?; + } + Ok(()) + } +} + +impl<'de> SSHDecode<'de> for SSHConfig { + fn dec<S>(s: &mut S) -> WireResult<Self> where S: SSHSource<'de> { + let hostkey = dec_signkey(s)?; + + let have_pw_hash = bool::dec(s)?; + let pw_hash = have_pw_hash.then(|| SSHDecode::dec(s)).transpose()?; + + let wifi_net = <&str>::dec(s)?.into(); + let have_wifi_pw = bool::dec(s)?; + + let wifi_pw = have_wifi_pw.then(|| { + let p: &str = SSHDecode::dec(s)?; + Ok(p.into()) + }) + .transpose()?; + Ok(Self { + hostkey, + pw_hash, + wifi_net, + wifi_pw, + }) + } +} + + diff --git a/embassy/demos/common/demo_menu.rs b/embassy/demos/common/src/demo_menu.rs similarity index 99% rename from embassy/demos/common/demo_menu.rs rename to embassy/demos/common/src/demo_menu.rs index 80373f0..81c69c5 100644 --- a/embassy/demos/common/demo_menu.rs +++ b/embassy/demos/common/src/demo_menu.rs @@ -1,5 +1,5 @@ use menu::*; -pub use super::BufOutput; +pub use crate::server::BufOutput; use core::fmt::Write; // from menu crate examples/simple.rs diff --git a/embassy/demos/common/src/lib.rs b/embassy/demos/common/src/lib.rs new file mode 100644 index 0000000..d30e7b1 --- /dev/null +++ b/embassy/demos/common/src/lib.rs @@ -0,0 +1,13 @@ +#![no_std] + +#![feature(type_alias_impl_trait)] +#![feature(async_fn_in_trait)] +// #![allow(incomplete_features)] + +mod config; +mod server; + +pub mod demo_menu; + +pub use server::{Shell, listener}; +pub use config::SSHConfig; diff --git a/embassy/demos/common/server.rs b/embassy/demos/common/src/server.rs similarity index 92% rename from embassy/demos/common/server.rs rename to embassy/demos/common/src/server.rs index 310bffb..5c3d64f 100644 --- a/embassy/demos/common/server.rs +++ b/embassy/demos/common/src/server.rs @@ -21,30 +21,26 @@ use embedded_io::asynch; use sunset::*; use sunset_embassy::SSHServer; -// TODO move -pub mod demo_menu; - +use crate::SSHConfig; + +// #[macro_export] +// macro_rules! singleton { +// ($val:expr) => {{ +// type T = impl Sized; +// static STATIC_CELL: StaticCell<T> = StaticCell::new(); +// STATIC_CELL.init($val) +// }}; +// } #[macro_export] macro_rules! singleton { ($val:expr) => {{ type T = impl Sized; static STATIC_CELL: StaticCell<T> = StaticCell::new(); - STATIC_CELL.init($val) + let (x,) = STATIC_CELL.init(($val,)); + x }}; } -pub struct SSHConfig { - keys: [SignKey; 1], -} - -impl SSHConfig { - pub fn new() -> Result<Self> { - let keys = [SignKey::generate(KeyType::Ed25519, None)?]; - Ok(Self { - keys - }) - } -} // common entry point pub async fn listener<D: Driver, S: Shell>(stack: &'static Stack<D>, config: &SSHConfig) -> ! { @@ -106,6 +102,9 @@ async fn session<S: Shell>(socket: &mut TcpSocket<'_>, config: &SSHConfig) -> su struct DemoServer<'a, S: Shell> { config: &'a SSHConfig, + // references config + hostkeys: [&'a SignKey; 1], + handle: Option<ChanHandle>, sess: Option<ChanNum>, @@ -120,13 +119,14 @@ impl<'a, S: Shell> DemoServer<'a, S> { sess: None, config, shell, + hostkeys: [&config.hostkey], }) } } impl<'a, S: Shell> ServBehaviour for DemoServer<'a, S> { - fn hostkeys(&mut self) -> BhResult<&[SignKey]> { - Ok(&self.config.keys) + fn hostkeys(&mut self) -> BhResult<&[&SignKey]> { + Ok(&self.hostkeys) } fn auth_unchallenged(&mut self, username: TextString) -> bool { diff --git a/embassy/demos/picow/Cargo.lock b/embassy/demos/picow/Cargo.lock index 6200bf3..222f779 100644 --- a/embassy/demos/picow/Cargo.lock +++ b/embassy/demos/picow/Cargo.lock @@ -101,6 +101,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "az" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b7e4c2464d97fe331d41de9d5db0def0a96f4d823b8b32a2efd503578988973" + [[package]] name = "bare-metal" version = "0.2.5" @@ -152,6 +158,12 @@ dependencies = [ "generic-array 0.14.6", ] +[[package]] +name = "bytemuck" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea" + [[package]] name = "byteorder" version = "1.4.3" @@ -303,7 +315,7 @@ dependencies = [ [[package]] name = "cyw43" version = "0.1.0" -source = "git+https://github.com/embassy-rs/cyw43/?rev=46efce6ea2d4280d5e8e1eaece53269a94fb4847#46efce6ea2d4280d5e8e1eaece53269a94fb4847" +source = "git+https://github.com/embassy-rs/cyw43/?rev=c19de2984751ba6fa2972ee66cfa2a6310d5f0c1#c19de2984751ba6fa2972ee66cfa2a6310d5f0c1" dependencies = [ "atomic-polyfill 0.1.11", "cortex-m", @@ -311,8 +323,8 @@ dependencies = [ "defmt", "embassy-futures", "embassy-net-driver-channel", - "embassy-sync", - "embassy-time", + "embassy-sync 0.1.0", + "embassy-time 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "embedded-hal 1.0.0-alpha.10", "futures", "num_enum", @@ -321,7 +333,7 @@ dependencies = [ [[package]] name = "cyw43-pio" version = "0.1.0" -source = "git+https://github.com/embassy-rs/cyw43/?rev=46efce6ea2d4280d5e8e1eaece53269a94fb4847#46efce6ea2d4280d5e8e1eaece53269a94fb4847" +source = "git+https://github.com/embassy-rs/cyw43/?rev=c19de2984751ba6fa2972ee66cfa2a6310d5f0c1#c19de2984751ba6fa2972ee66cfa2a6310d5f0c1" dependencies = [ "cyw43", "defmt", @@ -466,7 +478,7 @@ checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" [[package]] name = "embassy-cortex-m" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=5a03b2e9e802626127038cff5634795f576f1c69#5a03b2e9e802626127038cff5634795f576f1c69" +source = "git+https://github.com/embassy-rs/embassy?rev=3e730aa8b06401003202bf9e21a9c83ec6b21b0e#3e730aa8b06401003202bf9e21a9c83ec6b21b0e" dependencies = [ "atomic-polyfill 1.0.1", "cfg-if", @@ -475,15 +487,15 @@ dependencies = [ "embassy-executor", "embassy-hal-common", "embassy-macros", - "embassy-sync", + "embassy-sync 0.2.0 (git+https://github.com/embassy-rs/embassy?rev=3e730aa8b06401003202bf9e21a9c83ec6b21b0e)", ] [[package]] name = "embassy-embedded-hal" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=5a03b2e9e802626127038cff5634795f576f1c69#5a03b2e9e802626127038cff5634795f576f1c69" +source = "git+https://github.com/embassy-rs/embassy?rev=3e730aa8b06401003202bf9e21a9c83ec6b21b0e#3e730aa8b06401003202bf9e21a9c83ec6b21b0e" dependencies = [ - "embassy-sync", + "embassy-sync 0.2.0 (git+https://github.com/embassy-rs/embassy?rev=3e730aa8b06401003202bf9e21a9c83ec6b21b0e)", "embedded-hal 0.2.7", "embedded-hal 1.0.0-alpha.10", "embedded-hal-async", @@ -494,15 +506,15 @@ dependencies = [ [[package]] name = "embassy-executor" -version = "0.1.1" -source = "git+https://github.com/embassy-rs/embassy?rev=5a03b2e9e802626127038cff5634795f576f1c69#5a03b2e9e802626127038cff5634795f576f1c69" +version = "0.2.0" +source = "git+https://github.com/embassy-rs/embassy?rev=3e730aa8b06401003202bf9e21a9c83ec6b21b0e#3e730aa8b06401003202bf9e21a9c83ec6b21b0e" dependencies = [ "atomic-polyfill 1.0.1", "cortex-m", "critical-section 1.1.1", "defmt", "embassy-macros", - "embassy-time", + "embassy-time 0.1.1 (git+https://github.com/embassy-rs/embassy?rev=3e730aa8b06401003202bf9e21a9c83ec6b21b0e)", "futures-util", "static_cell", ] @@ -510,12 +522,12 @@ dependencies = [ [[package]] name = "embassy-futures" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=5a03b2e9e802626127038cff5634795f576f1c69#5a03b2e9e802626127038cff5634795f576f1c69" +source = "git+https://github.com/embassy-rs/embassy?rev=3e730aa8b06401003202bf9e21a9c83ec6b21b0e#3e730aa8b06401003202bf9e21a9c83ec6b21b0e" [[package]] name = "embassy-hal-common" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=5a03b2e9e802626127038cff5634795f576f1c69#5a03b2e9e802626127038cff5634795f576f1c69" +source = "git+https://github.com/embassy-rs/embassy?rev=3e730aa8b06401003202bf9e21a9c83ec6b21b0e#3e730aa8b06401003202bf9e21a9c83ec6b21b0e" dependencies = [ "defmt", "num-traits", @@ -523,8 +535,8 @@ dependencies = [ [[package]] name = "embassy-macros" -version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=5a03b2e9e802626127038cff5634795f576f1c69#5a03b2e9e802626127038cff5634795f576f1c69" +version = "0.2.0" +source = "git+https://github.com/embassy-rs/embassy?rev=3e730aa8b06401003202bf9e21a9c83ec6b21b0e#3e730aa8b06401003202bf9e21a9c83ec6b21b0e" dependencies = [ "darling", "proc-macro2", @@ -535,7 +547,7 @@ dependencies = [ [[package]] name = "embassy-net" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=5a03b2e9e802626127038cff5634795f576f1c69#5a03b2e9e802626127038cff5634795f576f1c69" +source = "git+https://github.com/embassy-rs/embassy?rev=3e730aa8b06401003202bf9e21a9c83ec6b21b0e#3e730aa8b06401003202bf9e21a9c83ec6b21b0e" dependencies = [ "as-slice 0.2.1", "atomic-polyfill 1.0.1", @@ -543,9 +555,9 @@ dependencies = [ "defmt", "embassy-hal-common", "embassy-net-driver", - "embassy-sync", - "embassy-time", - "embedded-io", + "embassy-sync 0.2.0 (git+https://github.com/embassy-rs/embassy?rev=3e730aa8b06401003202bf9e21a9c83ec6b21b0e)", + "embassy-time 0.1.1 (git+https://github.com/embassy-rs/embassy?rev=3e730aa8b06401003202bf9e21a9c83ec6b21b0e)", + "embedded-io 0.4.0", "embedded-nal-async", "futures", "generic-array 0.14.6", @@ -558,7 +570,7 @@ dependencies = [ [[package]] name = "embassy-net-driver" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=5a03b2e9e802626127038cff5634795f576f1c69#5a03b2e9e802626127038cff5634795f576f1c69" +source = "git+https://github.com/embassy-rs/embassy?rev=3e730aa8b06401003202bf9e21a9c83ec6b21b0e#3e730aa8b06401003202bf9e21a9c83ec6b21b0e" dependencies = [ "defmt", ] @@ -566,17 +578,17 @@ dependencies = [ [[package]] name = "embassy-net-driver-channel" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=5a03b2e9e802626127038cff5634795f576f1c69#5a03b2e9e802626127038cff5634795f576f1c69" +source = "git+https://github.com/embassy-rs/embassy?rev=3e730aa8b06401003202bf9e21a9c83ec6b21b0e#3e730aa8b06401003202bf9e21a9c83ec6b21b0e" dependencies = [ "embassy-futures", "embassy-net-driver", - "embassy-sync", + "embassy-sync 0.2.0 (git+https://github.com/embassy-rs/embassy?rev=3e730aa8b06401003202bf9e21a9c83ec6b21b0e)", ] [[package]] name = "embassy-rp" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=5a03b2e9e802626127038cff5634795f576f1c69#5a03b2e9e802626127038cff5634795f576f1c69" +source = "git+https://github.com/embassy-rs/embassy?rev=3e730aa8b06401003202bf9e21a9c83ec6b21b0e#3e730aa8b06401003202bf9e21a9c83ec6b21b0e" dependencies = [ "atomic-polyfill 1.0.1", "cfg-if", @@ -589,46 +601,87 @@ dependencies = [ "embassy-executor", "embassy-futures", "embassy-hal-common", - "embassy-sync", - "embassy-time", + "embassy-sync 0.2.0 (git+https://github.com/embassy-rs/embassy?rev=3e730aa8b06401003202bf9e21a9c83ec6b21b0e)", + "embassy-time 0.1.1 (git+https://github.com/embassy-rs/embassy?rev=3e730aa8b06401003202bf9e21a9c83ec6b21b0e)", "embassy-usb-driver", "embedded-hal 0.2.7", "embedded-hal 1.0.0-alpha.10", "embedded-hal-async", "embedded-hal-nb", - "embedded-io", + "embedded-io 0.4.0", "embedded-storage", + "fixed", "futures", "nb 1.0.0", "paste", "pio", "pio-proc", "rand_core", - "rp2040-pac2", + "rp-pac", ] [[package]] name = "embassy-sync" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=5a03b2e9e802626127038cff5634795f576f1c69#5a03b2e9e802626127038cff5634795f576f1c69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6ea38e6ea5d0361d087680f786c19a1454becb06174790280534a3be05ed839" +dependencies = [ + "atomic-polyfill 1.0.1", + "cfg-if", + "critical-section 1.1.1", + "embedded-io 0.3.1", + "futures-util", + "heapless", +] + +[[package]] +name = "embassy-sync" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0dad296a6f70bfdc32ef52442a31f98c28e1608893c1cecc9b6f419bab005a0" dependencies = [ "cfg-if", "critical-section 1.1.1", - "embedded-io", + "embedded-io 0.4.0", + "futures-util", + "heapless", +] + +[[package]] +name = "embassy-sync" +version = "0.2.0" +source = "git+https://github.com/embassy-rs/embassy?rev=3e730aa8b06401003202bf9e21a9c83ec6b21b0e#3e730aa8b06401003202bf9e21a9c83ec6b21b0e" +dependencies = [ + "cfg-if", + "critical-section 1.1.1", + "embedded-io 0.4.0", "futures-util", "heapless", ] [[package]] name = "embassy-time" -version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=5a03b2e9e802626127038cff5634795f576f1c69#5a03b2e9e802626127038cff5634795f576f1c69" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd403e218939bba4a1fe4b58c6f81bf0818852bdd824147f95e6dc4ff4166ac4" dependencies = [ "atomic-polyfill 1.0.1", "cfg-if", "critical-section 1.1.1", "defmt", - "embassy-sync", + "embedded-hal 0.2.7", + "futures-util", + "heapless", +] + +[[package]] +name = "embassy-time" +version = "0.1.1" +source = "git+https://github.com/embassy-rs/embassy?rev=3e730aa8b06401003202bf9e21a9c83ec6b21b0e#3e730aa8b06401003202bf9e21a9c83ec6b21b0e" +dependencies = [ + "atomic-polyfill 1.0.1", + "cfg-if", + "critical-section 1.1.1", "embedded-hal 0.2.7", "futures-util", "heapless", @@ -637,7 +690,7 @@ dependencies = [ [[package]] name = "embassy-usb-driver" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=5a03b2e9e802626127038cff5634795f576f1c69#5a03b2e9e802626127038cff5634795f576f1c69" +source = "git+https://github.com/embassy-rs/embassy?rev=3e730aa8b06401003202bf9e21a9c83ec6b21b0e#3e730aa8b06401003202bf9e21a9c83ec6b21b0e" dependencies = [ "defmt", ] @@ -677,6 +730,12 @@ dependencies = [ "nb 1.0.0", ] +[[package]] +name = "embedded-io" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33dfba9e6c113f2fd8537c943780a7345945e66c86972e356b1152e19481bcf5" + [[package]] name = "embedded-io" version = "0.4.0" @@ -703,7 +762,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "27ce84f518ca912777ec143db235f4d615e3bf8d4e46d507d6ef12daf5b1df98" dependencies = [ - "embedded-io", + "embedded-io 0.4.0", "embedded-nal", "heapless", "no-std-net 0.6.0", @@ -754,6 +813,18 @@ dependencies = [ "libc", ] +[[package]] +name = "fixed" +version = "1.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79386fdcec5e0fde91b1a6a5bcd89677d1f9304f7f986b154a1b9109038854d9" +dependencies = [ + "az", + "bytemuck", + "half", + "typenum", +] + [[package]] name = "fixedbitset" version = "0.4.2" @@ -878,6 +949,15 @@ dependencies = [ "wasi", ] +[[package]] +name = "half" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02b4af3693f1b705df946e9fe5631932443781d0aabb423b62fcd4d73f6d2fd0" +dependencies = [ + "crunchy", +] + [[package]] name = "hash32" version = "0.2.1" @@ -1402,9 +1482,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] -name = "rp2040-pac2" -version = "0.1.0" -source = "git+https://github.com/embassy-rs/rp2040-pac2?rev=017e3c9007b2d3b6965f0d85b5bf8ce3fa6d7364#017e3c9007b2d3b6965f0d85b5bf8ce3fa6d7364" +name = "rp-pac" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75de4bf19a348bd73e49e0476b74a1a19c305de1289c87a7f5049f939246c927" dependencies = [ "cortex-m", "cortex-m-rt", @@ -1615,7 +1696,7 @@ dependencies = [ "cipher", "ctr", "digest", - "embedded-io", + "embedded-io 0.4.0", "futures", "getrandom", "heapless", @@ -1634,6 +1715,23 @@ dependencies = [ "zeroize", ] +[[package]] +name = "sunset-demo-embassy-common" +version = "0.1.0" +dependencies = [ + "defmt", + "embassy-futures", + "embassy-net", + "embassy-net-driver", + "embassy-sync 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "embedded-io 0.4.0", + "heapless", + "menu", + "sunset", + "sunset-embassy", + "sunset-sshwire-derive", +] + [[package]] name = "sunset-demo-embassy-picow" version = "0.1.0" @@ -1652,11 +1750,11 @@ dependencies = [ "embassy-net", "embassy-net-driver", "embassy-rp", - "embassy-sync", - "embassy-time", + "embassy-sync 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "embassy-time 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "embedded-hal 1.0.0-alpha.10", "embedded-hal-async", - "embedded-io", + "embedded-io 0.4.0", "getrandom", "heapless", "menu", @@ -1666,7 +1764,9 @@ dependencies = [ "sha2", "static_cell", "sunset", + "sunset-demo-embassy-common", "sunset-embassy", + "sunset-sshwire-derive", ] [[package]] @@ -1675,8 +1775,8 @@ version = "0.2.0-alpha" dependencies = [ "atomic-polyfill 1.0.1", "embassy-futures", - "embassy-sync", - "embedded-io", + "embassy-sync 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "embedded-io 0.4.0", "log", "pin-utils", "sunset", diff --git a/embassy/demos/picow/Cargo.toml b/embassy/demos/picow/Cargo.toml index 6e6dbf3..0fa6a12 100644 --- a/embassy/demos/picow/Cargo.toml +++ b/embassy/demos/picow/Cargo.toml @@ -7,16 +7,21 @@ edition = "2021" # blank [dependencies] -cyw43 = { git = "https://github.com/embassy-rs/cyw43/", rev = "46efce6ea2d4280d5e8e1eaece53269a94fb4847", features = ["defmt"]} -cyw43-pio = { git = "https://github.com/embassy-rs/cyw43/", rev = "46efce6ea2d4280d5e8e1eaece53269a94fb4847" } +sunset-embassy = { path = "../../" } +sunset = { path = "../../.." } +sunset-sshwire-derive = { version = "0.1", path = "../../../sshwire-derive" } +sunset-demo-embassy-common= { path = "../common", features = ["defmt"] } + +cyw43 = { git = "https://github.com/embassy-rs/cyw43/", rev = "c19de2984751ba6fa2972ee66cfa2a6310d5f0c1", features = ["defmt"]} +cyw43-pio = { git = "https://github.com/embassy-rs/cyw43/", rev = "c19de2984751ba6fa2972ee66cfa2a6310d5f0c1" } # cyw43 = { path = "/home/matt/3rd/rs/cyw43", features = ["defmt"]} -embassy-executor = { version = "0.1.0", features = ["defmt", "integrated-timers", "executor-thread", "arch-cortex-m"] } -embassy-time = { version = "0.1.0", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-rp = { version = "0.1.0", features = ["defmt", "unstable-traits", "nightly", "unstable-pac", "pio"] } +embassy-executor = { version = "0.2", features = ["defmt", "integrated-timers", "executor-thread", "arch-cortex-m"] } +embassy-time = { version = "0.1", features = ["defmt", "defmt-timestamp-uptime"] } +embassy-rp = { version = "0.1.0", features = ["defmt", "unstable-traits", "nightly", "unstable-pac"] } # embassy-net/nightly is required for asynch::Read/Write on TcpReader/TcpWriter -embassy-net = { version = "0.1.0", features = ["tcp", "dhcpv4", "medium-ethernet", "nightly", "defmt"] } +embassy-net = { version = "0.1.0", features = ["tcp", "dhcpv4", "medium-ethernet", "nightly"] } embassy-net-driver = { version = "0.1.0" } -embassy-sync = { version = "0.1.0" } +embassy-sync = { version = "0.2.0" } embassy-futures = { version = "0.1.0" } atomic-polyfill = "0.1.5" static_cell = "1.0" @@ -33,8 +38,6 @@ embedded-hal-async = { version = "0.2.0-alpha.1" } embedded-io = { version = "0.4", features = ["async", "defmt"] } heapless = "0.7.15" -sunset-embassy = { path = "../../" } -sunset = { path = "../../.." } getrandom = { version = "0.2", default-features = false, features = ["custom"]} pin-utils = "0.1" @@ -47,7 +50,7 @@ rand = { version = "0.8", default-features = false, features = ["getrandom"] } sha2 = { version = "0.10", default-features = false } [features] -default = ["defmt"] +default = ["defmt", "sunset-demo-embassy-common/defmt"] defmt = [] # Use cyw43 firmware already on flash. This saves time when developing. @@ -56,15 +59,13 @@ defmt = [] romfw = [] [patch.crates-io] -embassy-executor = { git = "https://github.com/embassy-rs/embassy", rev = "5a03b2e9e802626127038cff5634795f576f1c69" } -embassy-time = { git = "https://github.com/embassy-rs/embassy", rev = "5a03b2e9e802626127038cff5634795f576f1c69" } -embassy-futures = { git = "https://github.com/embassy-rs/embassy", rev = "5a03b2e9e802626127038cff5634795f576f1c69" } -embassy-sync = { git = "https://github.com/embassy-rs/embassy", rev = "5a03b2e9e802626127038cff5634795f576f1c69" } -embassy-rp = { git = "https://github.com/embassy-rs/embassy", rev = "5a03b2e9e802626127038cff5634795f576f1c69" } -embassy-net = { git = "https://github.com/embassy-rs/embassy", rev = "5a03b2e9e802626127038cff5634795f576f1c69" } +embassy-executor = { git = "https://github.com/embassy-rs/embassy", rev = "3e730aa8b06401003202bf9e21a9c83ec6b21b0e" } +embassy-futures = { git = "https://github.com/embassy-rs/embassy", rev = "3e730aa8b06401003202bf9e21a9c83ec6b21b0e" } +embassy-rp = { git = "https://github.com/embassy-rs/embassy", rev = "3e730aa8b06401003202bf9e21a9c83ec6b21b0e" } +embassy-net = { git = "https://github.com/embassy-rs/embassy", rev = "3e730aa8b06401003202bf9e21a9c83ec6b21b0e" } # for cyw43 -embassy-net-driver-channel = { git = "https://github.com/embassy-rs/embassy", rev = "5a03b2e9e802626127038cff5634795f576f1c69" } -embassy-net-driver = { git = "https://github.com/embassy-rs/embassy", rev = "5a03b2e9e802626127038cff5634795f576f1c69" } +embassy-net-driver-channel = { git = "https://github.com/embassy-rs/embassy", rev = "3e730aa8b06401003202bf9e21a9c83ec6b21b0e" } +embassy-net-driver = { git = "https://github.com/embassy-rs/embassy", rev = "3e730aa8b06401003202bf9e21a9c83ec6b21b0e" } [profile.dev] debug = 2 diff --git a/embassy/demos/picow/src/flash_config.rs b/embassy/demos/picow/src/flash_config.rs new file mode 100644 index 0000000..0b3828c --- /dev/null +++ b/embassy/demos/picow/src/flash_config.rs @@ -0,0 +1,102 @@ +#[allow(unused_imports)] +use { + sunset::error::{Error, Result, TrapBug}, +}; + +use defmt::{debug, info, warn, error, trace}; + +use embassy_rp::flash::{Flash, ERASE_SIZE, FLASH_BASE}; +use embassy_rp::peripherals::FLASH; + +use sha2::Digest; + +use core::borrow::Borrow; + +use sunset_sshwire_derive::*; +use sunset::sshwire; +use sunset::sshwire::{BinString, SSHEncode, SSHDecode, WireResult, SSHSource, SSHSink, WireError}; +use sunset::sshwire::OwnOrBorrow; + +use crate::demo_common::SSHConfig; + +// bump this when the format changes +const CURRENT_VERSION: u8 = 1; + +// TODO: unify offsets with wifi's romfw feature +const CONFIG_OFFSET: u32 = 0x150000; +const FLASH_SIZE: usize = 2*1024*1024; + +#[derive(SSHEncode, SSHDecode)] +struct FlashConfig<'a> { + version: u8, + config: OwnOrBorrow<'a, SSHConfig>, + /// sha256 hash of config + hash: [u8; 32], +} + +fn config_hash(config: &SSHConfig) -> Result<[u8; 32]> { + let mut h = sha2::Sha256::new(); + sshwire::hash_ser(&mut h, config, None)?; + Ok(h.finalize().into()) +} + +/// Loads a SSHConfig at startup. Good for persisting hostkeys. +pub fn load_or_create(flash: &mut Flash<'_, FLASH, FLASH_SIZE>) -> Result<SSHConfig> { + let c = load(flash); + match load(flash) { + Ok(c) => { + info!("Good existing config"); + return Ok(c) + } + Err(c) => info!("Existing config bad, making new"), + } + + let c = SSHConfig::new()?; + if let Err(e) = save(flash, &c) { + warn!("Error writing config"); + } + Ok(c) +} + +pub fn load(flash: &mut Flash<'_, FLASH, FLASH_SIZE>) -> Result<SSHConfig> { + let mut buf = [0u8; ERASE_SIZE]; + flash.read(CONFIG_OFFSET, &mut buf).map_err(|_| Error::msg("flash error"))?; + let s: FlashConfig = sshwire::read_ssh(&buf, None)?; + + if s.version != CURRENT_VERSION { + return Err(Error::msg("wrong config version")) + } + + let calc_hash = config_hash(s.config.borrow())?; + if calc_hash != s.hash { + return Err(Error::msg("bad config hash")) + } + + if let OwnOrBorrow::Own(c) = s.config { + Ok(c) + } else { + // OK panic - OwnOrBorrow always decodes to Own variant + panic!() + } +} + +pub fn save(flash: &mut Flash<'_, FLASH, FLASH_SIZE>, config: &SSHConfig) -> Result<()> { + let mut buf = [0u8; ERASE_SIZE]; + let sc = FlashConfig { + version: CURRENT_VERSION, + config: OwnOrBorrow::Borrow(&config), + hash: config_hash(&config)?, + }; + sshwire::write_ssh(&mut buf, &sc)?; + trace!("flash erase"); + flash.erase(CONFIG_OFFSET, CONFIG_OFFSET + ERASE_SIZE as u32) + .map_err(|_| Error::msg("flash erase error"))?; + + trace!("flash write"); + flash.write(CONFIG_OFFSET, &buf) + .map_err(|_| Error::msg("flash write error"))?; + + trace!("save done"); + Ok(()) +} + diff --git a/embassy/demos/picow/src/main.rs b/embassy/demos/picow/src/main.rs index acb0b39..3e3a547 100644 --- a/embassy/demos/picow/src/main.rs +++ b/embassy/demos/picow/src/main.rs @@ -2,8 +2,7 @@ #![no_main] #![feature(type_alias_impl_trait)] #![feature(async_fn_in_trait)] -#![allow(incomplete_features)] -//#![feature(impl_trait_in_assoc_type)] +// #![allow(incomplete_features)] use defmt::*; use embassy_executor::Spawner; @@ -21,10 +20,11 @@ use embassy_sync::blocking_mutex::raw::NoopRawMutex; use sunset::*; use sunset_embassy::SSHServer; +pub(crate) use sunset_demo_embassy_common as demo_common; +use crate::demo_common::singleton; + +mod flash_config; mod wifi; -#[path = "../../common/server.rs"] -#[macro_use] -mod demo_common; use demo_common::{SSHConfig, demo_menu, Shell}; @@ -46,16 +46,24 @@ async fn main(spawner: Spawner) { caprand::setup(&mut p.PIN_10).unwrap(); getrandom::register_custom_getrandom!(caprand::getrandom); + let mut flash = embassy_rp::flash::Flash::new(p.FLASH); + + let config = flash_config::load_or_create(&mut flash).unwrap(); + + let ssh_config = &*singleton!( + config + ); + let (_, sm, _, _, _) = p.PIO0.split(); + let wifi_net = ssh_config.wifi_net.as_str(); + let wifi_pw = ssh_config.wifi_pw.as_ref().map(|p| p.as_str()); + // spawn the wifi stack - let stack = wifi::wifi_stack(&spawner, p.PIN_23, p.PIN_24, p.PIN_25, p.PIN_29, p.DMA_CH0, sm).await; + let stack = wifi::wifi_stack(&spawner, p.PIN_23, p.PIN_24, p.PIN_25, p.PIN_29, p.DMA_CH0, sm, + wifi_net, wifi_pw).await; let stack = &*singleton!(stack); unwrap!(spawner.spawn(net_task(&stack))); - let ssh_config = &*singleton!( - demo_common::SSHConfig::new().unwrap() - ); - for _ in 0..NUM_LISTENERS { spawner.spawn(listener(&stack, &ssh_config)).unwrap(); } diff --git a/embassy/demos/picow/src/wifi.rs b/embassy/demos/picow/src/wifi.rs index bc7246d..e01c537 100644 --- a/embassy/demos/picow/src/wifi.rs +++ b/embassy/demos/picow/src/wifi.rs @@ -15,7 +15,7 @@ use static_cell::StaticCell; use rand::rngs::OsRng; use rand::RngCore; -use crate::singleton; +use crate::demo_common::singleton; #[embassy_executor::task] async fn wifi_task( @@ -32,6 +32,7 @@ async fn wifi_task( pub(crate) async fn wifi_stack(spawner: &Spawner, p23: PIN_23, p24: PIN_24, p25: PIN_25, p29: PIN_29, dma: DMA_CH0, sm: PioStateMachineInstance<Pio0, Sm0>, + wifi_net: &str, wpa_password: Option<&str>, ) -> embassy_net::Stack<cyw43::NetDriver<'static>> { @@ -46,14 +47,13 @@ pub(crate) async fn wifi_stack(spawner: &Spawner, spawner.spawn(wifi_task(runner)).unwrap(); control.init(clm).await; - // control.set_power_management(cyw43::PowerManagementMode::PowerSave).await; + // the default is PowerSave + control.set_power_management(cyw43::PowerManagementMode::Performance).await; - let net = option_env!("WIFI_NETWORK").unwrap_or("guest"); - let pw = option_env!("WIFI_PASSWORD"); - if let Some(pw) = pw { - control.join_wpa2(net, pw).await; + if let Some(pw) = wpa_password { + control.join_wpa2(wifi_net, pw).await; } else { - control.join_open(net).await; + control.join_open(wifi_net).await; } let config = embassy_net::Config::Dhcp(Default::default()); diff --git a/embassy/demos/std/Cargo.lock b/embassy/demos/std/Cargo.lock index 48d2caf..cbbcd40 100644 --- a/embassy/demos/std/Cargo.lock +++ b/embassy/demos/std/Cargo.lock @@ -305,7 +305,7 @@ dependencies = [ "cfg-if", "critical-section", "embassy-macros", - "embassy-time", + "embassy-time 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "futures-util", "log", "static_cell", @@ -314,12 +314,12 @@ dependencies = [ [[package]] name = "embassy-futures" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=5a03b2e9e802626127038cff5634795f576f1c69#5a03b2e9e802626127038cff5634795f576f1c69" +source = "git+https://github.com/embassy-rs/embassy?rev=3e730aa8b06401003202bf9e21a9c83ec6b21b0e#3e730aa8b06401003202bf9e21a9c83ec6b21b0e" [[package]] name = "embassy-hal-common" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=5a03b2e9e802626127038cff5634795f576f1c69#5a03b2e9e802626127038cff5634795f576f1c69" +source = "git+https://github.com/embassy-rs/embassy?rev=3e730aa8b06401003202bf9e21a9c83ec6b21b0e#3e730aa8b06401003202bf9e21a9c83ec6b21b0e" dependencies = [ "num-traits", ] @@ -339,15 +339,15 @@ dependencies = [ [[package]] name = "embassy-net" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=5a03b2e9e802626127038cff5634795f576f1c69#5a03b2e9e802626127038cff5634795f576f1c69" +source = "git+https://github.com/embassy-rs/embassy?rev=3e730aa8b06401003202bf9e21a9c83ec6b21b0e#3e730aa8b06401003202bf9e21a9c83ec6b21b0e" dependencies = [ "as-slice 0.2.1", "atomic-polyfill 1.0.1", "atomic-pool", "embassy-hal-common", "embassy-net-driver", - "embassy-sync", - "embassy-time", + "embassy-sync 0.2.0 (git+https://github.com/embassy-rs/embassy?rev=3e730aa8b06401003202bf9e21a9c83ec6b21b0e)", + "embassy-time 0.1.1 (git+https://github.com/embassy-rs/embassy?rev=3e730aa8b06401003202bf9e21a9c83ec6b21b0e)", "embedded-io", "embedded-nal-async", "futures", @@ -362,12 +362,25 @@ dependencies = [ [[package]] name = "embassy-net-driver" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=5a03b2e9e802626127038cff5634795f576f1c69#5a03b2e9e802626127038cff5634795f576f1c69" +source = "git+https://github.com/embassy-rs/embassy?rev=3e730aa8b06401003202bf9e21a9c83ec6b21b0e#3e730aa8b06401003202bf9e21a9c83ec6b21b0e" [[package]] name = "embassy-sync" -version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=5a03b2e9e802626127038cff5634795f576f1c69#5a03b2e9e802626127038cff5634795f576f1c69" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0dad296a6f70bfdc32ef52442a31f98c28e1608893c1cecc9b6f419bab005a0" +dependencies = [ + "cfg-if", + "critical-section", + "embedded-io", + "futures-util", + "heapless", +] + +[[package]] +name = "embassy-sync" +version = "0.2.0" +source = "git+https://github.com/embassy-rs/embassy?rev=3e730aa8b06401003202bf9e21a9c83ec6b21b0e#3e730aa8b06401003202bf9e21a9c83ec6b21b0e" dependencies = [ "cfg-if", "critical-section", @@ -378,19 +391,32 @@ dependencies = [ [[package]] name = "embassy-time" -version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=5a03b2e9e802626127038cff5634795f576f1c69#5a03b2e9e802626127038cff5634795f576f1c69" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd403e218939bba4a1fe4b58c6f81bf0818852bdd824147f95e6dc4ff4166ac4" dependencies = [ "atomic-polyfill 1.0.1", "cfg-if", "critical-section", - "embassy-sync", "embedded-hal 0.2.7", "futures-util", "heapless", "log", ] +[[package]] +name = "embassy-time" +version = "0.1.1" +source = "git+https://github.com/embassy-rs/embassy?rev=3e730aa8b06401003202bf9e21a9c83ec6b21b0e#3e730aa8b06401003202bf9e21a9c83ec6b21b0e" +dependencies = [ + "atomic-polyfill 1.0.1", + "cfg-if", + "critical-section", + "embedded-hal 0.2.7", + "futures-util", + "heapless", +] + [[package]] name = "embedded-hal" version = "0.2.7" @@ -1053,6 +1079,23 @@ dependencies = [ "zeroize", ] +[[package]] +name = "sunset-demo-embassy-common" +version = "0.1.0" +dependencies = [ + "embassy-futures", + "embassy-net", + "embassy-net-driver", + "embassy-sync 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "embedded-io", + "heapless", + "log", + "menu", + "sunset", + "sunset-embassy", + "sunset-sshwire-derive", +] + [[package]] name = "sunset-demo-embassy-std" version = "0.1.0" @@ -1064,8 +1107,8 @@ dependencies = [ "embassy-futures", "embassy-net", "embassy-net-driver", - "embassy-sync", - "embassy-time", + "embassy-sync 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "embassy-time 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "embedded-hal 1.0.0-alpha.9", "embedded-hal-async", "embedded-io", @@ -1078,6 +1121,7 @@ dependencies = [ "sha2", "static_cell", "sunset", + "sunset-demo-embassy-common", "sunset-embassy", ] @@ -1087,7 +1131,7 @@ version = "0.2.0-alpha" dependencies = [ "atomic-polyfill 1.0.1", "embassy-futures", - "embassy-sync", + "embassy-sync 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "embedded-io", "log", "pin-utils", @@ -1308,8 +1352,3 @@ dependencies = [ "syn", "synstructure", ] - -[[patch.unused]] -name = "embassy-executor" -version = "0.1.1" -source = "git+https://github.com/embassy-rs/embassy?rev=5a03b2e9e802626127038cff5634795f576f1c69#5a03b2e9e802626127038cff5634795f576f1c69" diff --git a/embassy/demos/std/Cargo.toml b/embassy/demos/std/Cargo.toml index ef3dd5e..af7cf4a 100644 --- a/embassy/demos/std/Cargo.toml +++ b/embassy/demos/std/Cargo.toml @@ -7,12 +7,12 @@ edition = "2021" # blank [dependencies] -embassy-executor = { version = "0.1.0", features = ["log", "std", "nightly", "integrated-timers"] } -embassy-time = { version = "0.1.0", features = ["log", "std"] } +embassy-executor = { version = "0.1.0", default-features=false, features = ["log", "std", "nightly", "integrated-timers"] } +embassy-time = { version = "0.1", default-features=false, features = ["log", "std"] } # embassy-net/nightly is required for asynch::Read/Write on TcpReader/TcpWriter -embassy-net = { version = "0.1.0", features = ["log", "tcp", "dhcpv4", "medium-ethernet", "nightly"] } +embassy-net = { version = "0.1.0", features = ["tcp", "dhcpv4", "medium-ethernet", "nightly"] } embassy-net-driver = { version = "0.1.0" } -embassy-sync = { version = "0.1.0" } +embassy-sync = { version = "0.2.0" } embassy-futures = { version = "0.1.0" } atomic-polyfill = "0.1.5" static_cell = "1.0" @@ -22,7 +22,7 @@ env_logger = "0.9.0" embedded-hal-1 = { package = "embedded-hal", version = "1.0.0-alpha.8" } embedded-hal-async = { version = "0.1.0-alpha.2" } -embedded-io = { version = "0.4", features = ["async"] } +embedded-io = { version = "0.4", default-features=false, features = ["async"] } heapless = "0.7.15" # for tuntap @@ -33,19 +33,17 @@ menu = "0.3" sunset-embassy = { path = "../../" } sunset = { path = "../../.." } +sunset-demo-embassy-common= { path = "../common", features = ["log"] } critical-section = "1.1" rand = { version = "0.8", default-features = false, features = ["getrandom"] } sha2 = { version = "0.10", default-features = false } [patch.crates-io] -embassy-executor = { git = "https://github.com/embassy-rs/embassy", rev = "5a03b2e9e802626127038cff5634795f576f1c69" } -embassy-time = { git = "https://github.com/embassy-rs/embassy", rev = "5a03b2e9e802626127038cff5634795f576f1c69" } -embassy-futures = { git = "https://github.com/embassy-rs/embassy", rev = "5a03b2e9e802626127038cff5634795f576f1c69" } -embassy-sync = { git = "https://github.com/embassy-rs/embassy", rev = "5a03b2e9e802626127038cff5634795f576f1c69" } -embassy-net = { git = "https://github.com/embassy-rs/embassy", rev = "5a03b2e9e802626127038cff5634795f576f1c69" } +embassy-futures = { git = "https://github.com/embassy-rs/embassy", rev = "3e730aa8b06401003202bf9e21a9c83ec6b21b0e" } +embassy-net = { git = "https://github.com/embassy-rs/embassy", rev = "3e730aa8b06401003202bf9e21a9c83ec6b21b0e" } # for tuntap -embassy-net-driver = { git = "https://github.com/embassy-rs/embassy", rev = "5a03b2e9e802626127038cff5634795f576f1c69" } +embassy-net-driver = { git = "https://github.com/embassy-rs/embassy", rev = "3e730aa8b06401003202bf9e21a9c83ec6b21b0e" } [profile.dev] debug = 2 diff --git a/embassy/demos/std/src/main.rs b/embassy/demos/std/src/main.rs index 06d9d4b..43a5f5f 100644 --- a/embassy/demos/std/src/main.rs +++ b/embassy/demos/std/src/main.rs @@ -25,10 +25,10 @@ use sunset::*; use sunset_embassy::SSHServer; mod tuntap; -#[path = "../../common/server.rs"] -mod demo_common; +pub(crate) use sunset_demo_embassy_common as demo_common; +use crate::demo_common::singleton; -use demo_common::{SSHConfig, demo_menu, Shell, BufOutput}; +use demo_common::{SSHConfig, demo_menu, Shell}; const NUM_LISTENERS: usize = 2; // +1 for dhcp @@ -62,7 +62,7 @@ async fn main_task(spawner: Spawner) { spawner.spawn(net_task(stack)).unwrap(); let ssh_config = &*singleton!( - demo_common::SSHConfig::new().unwrap() + SSHConfig::new().unwrap() ); for _ in 0..NUM_LISTENERS { @@ -90,7 +90,7 @@ impl Shell for DemoShell { let mut stdio = serv.stdio(chan_handle).await?; let mut menu_buf = [0u8; 64]; - let menu_out = BufOutput::default(); + let menu_out = demo_menu::BufOutput::default(); let mut menu = MenuRunner::new(&demo_menu::ROOT_MENU, &mut menu_buf, menu_out); diff --git a/src/behaviour.rs b/src/behaviour.rs index 3e17703..207f818 100644 --- a/src/behaviour.rs +++ b/src/behaviour.rs @@ -203,7 +203,8 @@ pub trait ServBehaviour { // then later request a single key. // Also could make it take a closure to call with the key, lets it just // be loaded on the stack rather than kept in memory for the whole lifetime. - fn hostkeys(&mut self) -> BhResult<&[sign::SignKey]>; + // TODO: a slice of references is a bit awkward? + fn hostkeys(&mut self) -> BhResult<&[&sign::SignKey]>; #[allow(unused)] // TODO: or return a slice of enums @@ -313,7 +314,7 @@ impl CliBehaviour for UnusedCli { #[derive(Debug)] pub struct UnusedServ; impl ServBehaviour for UnusedServ { - fn hostkeys(&mut self) -> BhResult<&[sign::SignKey]> { + fn hostkeys(&mut self) -> BhResult<&[&sign::SignKey]> { unreachable!() } fn open_session(&mut self, chan: ChanHandle) -> channel::ChanOpened { diff --git a/src/kex.rs b/src/kex.rs index 4ba22af..6c523eb 100644 --- a/src/kex.rs +++ b/src/kex.rs @@ -785,12 +785,12 @@ mod tests { sshwire::packet_from_bytes(&out_buf[..l], &ctx).unwrap() } - struct TestServBehaviour { - keys: Vec<SignKey>, + struct TestServBehaviour<'a> { + keys: Vec<&'a SignKey>, } - impl ServBehaviour for TestServBehaviour { - fn hostkeys(&mut self) -> BhResult<&[SignKey]> { + impl<'a> ServBehaviour for TestServBehaviour<'a> { + fn hostkeys(&mut self) -> BhResult<&[&'a SignKey]> { Ok(self.keys.as_slice()) } @@ -908,6 +908,7 @@ mod tests { let mut keys = vec![]; keys.push(crate::SignKey::generate(crate::KeyType::Ed25519, None).unwrap()); + let keys: Vec<&SignKey> = keys.iter().collect(); let mut sb = TestServBehaviour { keys, }; diff --git a/src/packets.rs b/src/packets.rs index dc31909..a5a16a3 100644 --- a/src/packets.rs +++ b/src/packets.rs @@ -298,7 +298,7 @@ pub struct UserauthBanner<'a> { #[sshwire(variant_prefix)] pub enum PubKey<'a> { #[sshwire(variant = SSH_NAME_ED25519)] - Ed25519(Ed25519PubKey<'a>), + Ed25519(Ed25519PubKey), #[cfg(feature = "rsa")] #[sshwire(variant = SSH_NAME_RSA)] @@ -344,8 +344,7 @@ impl TryFrom<&PubKey<'_>> for ssh_key::PublicKey { fn try_from(k: &PubKey) -> Result<Self> { match k { PubKey::Ed25519(e) => { - let eb: &[u8; 32] = e.key.0.try_into().map_err(|_| Error::BadKey)?; - Ok(ssh_key::public::Ed25519PublicKey(*eb).into()) + Ok(ssh_key::public::Ed25519PublicKey(e.key.0).into()) } #[cfg(feature = "rsa")] @@ -363,15 +362,14 @@ impl TryFrom<&PubKey<'_>> for ssh_key::PublicKey { } #[derive(Debug, Clone, PartialEq, SSHEncode, SSHDecode)] -pub struct Ed25519PubKey<'a> { - pub key: BinString<'a>, +pub struct Ed25519PubKey { + pub key: Blob<[u8; 32]>, } -impl TryFrom<&Ed25519PubKey<'_>> for salty::PublicKey { +impl TryFrom<&Ed25519PubKey> for salty::PublicKey { type Error = Error; fn try_from(k: &Ed25519PubKey) -> Result<Self> { - let b: [u8; 32] = k.key.0.try_into().map_err(|_| Error::BadKey)?; - (&b).try_into().map_err(|_| Error::BadKey) + Ok((&k.key.0).try_into().map_err(|_| Error::BadKey)?) } } @@ -1102,7 +1100,7 @@ mod tests { method: AuthMethod::PubKey(MethodPubKey { sig_algo: "something", pubkey: Blob(PubKey::Ed25519( - Ed25519PubKey { key: BinString(b"zzzz") } + Ed25519PubKey { key: Blob([3u8; 32]) } )), sig: Some(Blob(Signature::Ed25519(Ed25519Sig { sig: BinString(b"sighere") diff --git a/src/sign.rs b/src/sign.rs index f748f0d..ef00bb0 100644 --- a/src/sign.rs +++ b/src/sign.rs @@ -14,7 +14,7 @@ use crate::*; use packets::ParseContext; use sshnames::*; use packets::{PubKey, Signature, Ed25519PubKey}; -use sshwire::{BinString, SSHEncode}; +use sshwire::{BinString, SSHEncode, Blob}; use pretty_hex::PrettyHex; @@ -79,7 +79,7 @@ impl SigType { match (self, pubkey, sig) { (SigType::Ed25519, PubKey::Ed25519(k), Signature::Ed25519(s)) => { - let k: &[u8; 32] = k.key.0.try_into().map_err(|_| Error::BadKey)?; + let k: &[u8; 32] = &k.key.0; let k: salty::PublicKey = k.try_into().map_err(|_| Error::BadKey)?; let s: &[u8; 64] = s.sig.0.try_into().map_err(|_| Error::BadSig)?; let s: salty::Signature = s.into(); @@ -170,8 +170,8 @@ pub enum KeyType { /// or potentially send the signing requests to an SSH agent or other entity. #[derive(ZeroizeOnDrop)] pub enum SignKey { - // TODO bloat: this is an expanded keypair, we should store the raw bytes - Ed25519(salty::Keypair), + // 32 byte seed value is the private key + Ed25519([u8; 32]), #[zeroize(skip)] AgentEd25519(salty::PublicKey), @@ -194,8 +194,8 @@ impl SignKey { return Err(Error::msg("Bad key size")); } let mut seed = [0u8; 32]; - random::fill_random(seed.as_mut_slice())?; - Ok(Self::Ed25519((&seed).into())) + random::fill_random(&mut seed)?; + Ok(Self::Ed25519(seed)) }, #[cfg(feature = "rsa")] @@ -220,11 +220,14 @@ impl SignKey { pub fn pubkey(&self) -> PubKey { match self { - SignKey::Ed25519(k) => PubKey::Ed25519(Ed25519PubKey - { key: BinString(k.public.as_bytes()) } ), + SignKey::Ed25519(seed) => { + let k = salty::Keypair::from(seed); + PubKey::Ed25519(Ed25519PubKey + { key: Blob(k.public.as_bytes().clone()) } ) + }, SignKey::AgentEd25519(pk) => PubKey::Ed25519(Ed25519PubKey - { key: BinString(pk.as_bytes()) } ), + { key: Blob(pk.as_bytes().clone()) } ), #[cfg(feature = "rsa")] @@ -277,7 +280,8 @@ impl SignKey { pub(crate) fn sign(&self, msg: &impl SSHEncode, parse_ctx: Option<&ParseContext>) -> Result<OwnedSig> { let sig: OwnedSig = match self { - SignKey::Ed25519(k) => { + SignKey::Ed25519(seed) => { + let k = salty::Keypair::from(seed); let sig = k.sign_parts(|h| { sshwire::hash_ser(h, msg, parse_ctx).map_err(|_| salty::Error::ContextTooLong) }) @@ -349,11 +353,7 @@ impl TryFrom<ssh_key::PrivateKey> for SignKey { fn try_from(k: ssh_key::PrivateKey) -> Result<Self> { match k.key_data() { ssh_key::private::KeypairData::Ed25519(k) => { - let key = salty::Keypair { - secret: (&k.private.to_bytes()).into(), - public: (&k.public.0).try_into().map_err(|_| Error::BadKey)?, - }; - Ok(SignKey::Ed25519(key)) + Ok(SignKey::Ed25519(k.private.to_bytes())) } #[cfg(feature = "rsa")] diff --git a/src/sshwire.rs b/src/sshwire.rs index aaaabe4..1d4b60e 100644 --- a/src/sshwire.rs +++ b/src/sshwire.rs @@ -162,6 +162,8 @@ pub fn hash_ser_length(hash_ctx: &mut impl DigestUpdate, } /// Hashes the SSH wire format representation of `value` +/// +/// Will only fail if `value.enc()` can return an error. pub fn hash_ser(hash_ctx: &mut impl DigestUpdate, value: &dyn SSHEncode, parse_ctx: Option<&ParseContext>, @@ -383,6 +385,7 @@ impl<'de> SSHDecode<'de> for TextString<'de> { } /// A wrapper for a `u32` length prefixed data structure `B`, such as a public key blob +#[derive(PartialEq, Clone)] pub struct Blob<B>(pub B); impl<B> AsRef<B> for Blob<B> { @@ -391,12 +394,6 @@ impl<B> AsRef<B> for Blob<B> { } } -impl<B: Clone> Clone for Blob<B> { - fn clone(&self) -> Self { - Blob(self.0.clone()) - } -} - impl<B: SSHEncode + Debug> Debug for Blob<B> { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { if let Ok(len) = sshwire::length_enc(&self.0) { @@ -479,6 +476,12 @@ impl<const N: usize> SSHEncode for &[u8; N] { } } +impl<const N: usize> SSHEncode for [u8; N] { + fn enc(&self, s: &mut dyn SSHSink) -> WireResult<()> { + s.push(self.as_slice()) + } +} + impl SSHEncode for &str { fn enc(&self, s: &mut dyn SSHSink) -> WireResult<()> { let v = self.as_bytes(); @@ -567,6 +570,14 @@ impl<'de, const N: usize> SSHDecode<'de> for &'de [u8; N] { } } +impl<'de, const N: usize> SSHDecode<'de> for [u8; N] { + fn dec<S>(s: &mut S) -> WireResult<Self> + where S: SSHSource<'de> { + // OK unwrap: take() fails if the length is short + Ok(s.take(N)?.try_into().unwrap()) + } +} + /// Like `digest::DynDigest` but simpler. /// /// Doesn't have any optional methods that depend on `alloc`. @@ -623,6 +634,37 @@ impl<'de> SSHDecode<'de> for rsa::BigUint { } } +// TODO: is there already something like this? +pub enum OwnOrBorrow<'a, T> { + Own(T), + Borrow(&'a T), +} + +impl<T: SSHEncode> SSHEncode for OwnOrBorrow<'_, T> { + fn enc(&self, s: &mut dyn SSHSink) -> WireResult<()> { + match self { + Self::Own(t) => t.enc(s), + Self::Borrow(t) => t.enc(s), + } + } +} + +impl<'de, T: SSHDecode<'de>> SSHDecode<'de> for OwnOrBorrow<'_, T> { + fn dec<S>(s: &mut S) -> WireResult<Self> where S: SSHSource<'de> { + Ok(Self::Own(T::dec(s)?)) + } +} + +impl<'a, T> core::borrow::Borrow<T> for OwnOrBorrow<'a, T> { + fn borrow(&self) -> &T { + match self { + Self::Own(t) => &t, + Self::Borrow(t) => t, + } + } +} + + #[cfg(test)] pub(crate) mod tests { use crate::*; @@ -709,7 +751,7 @@ pub(crate) mod tests { let p = Userauth60::PkOk(UserauthPkOk { algo: "ed25519", key: Blob(PubKey::Ed25519(Ed25519PubKey { - key: BinString(&[0x11, 0x22, 0x33]), + key: Blob([0x11; 32]), })), }).into(); ctx.cli_auth_type = Some(auth::AuthType::PubKey);