Skip to content

Commit

Permalink
Implement Validating, Decrypting, and Encrypting MION firmware files (#…
Browse files Browse the repository at this point in the history
…17)

* wip: decrypting/re-encrypting firmware

* upgrade to hyper 1.0 (aka reqwest), clippy

* update windows handle type changes with new versions

* implement mion firmware parsing

this implements the actual base interfaces for managing MION FW
files. We can now decrypt, re-encrypt, and properly checksum/validate
any firmware images that would have been uploaded to a MION device.

also fixed some formatting nits

* fix last broken isize cast

* fix up some error message documentation
  • Loading branch information
Mythra authored Nov 25, 2024
1 parent 4d338be commit 533a149
Show file tree
Hide file tree
Showing 24 changed files with 2,137 additions and 701 deletions.
1,823 changes: 1,409 additions & 414 deletions Cargo.lock

Large diffs are not rendered by default.

13 changes: 6 additions & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,22 @@ members = [
resolver = "2"

[workspace.dependencies]
bytes = "^1.6.0"
bytes = "^1.8.0"
fnv = "^1.0.7"
mac_address = "^1.1.5"
mac_address = "^1.1.7"
miette = { version = "^7.2.0", features = ["fancy"] }
network-interface = "^1.1.2"
once_cell = "^1.19.0"
time = "^0.3.34"
network-interface = "^2.0.0"
time = "^0.3.36"
tracing = { version = "^0.1.40", features = ["valuable"] }
tokio = { version = "^1.37.0", features = ["full", "tracing"] }
tokio = { version = "^1.41.1", features = ["full", "tracing"] }
valuable = { version = "^0.1.0", features = ["derive"] }

[workspace.package]
authors = ["Cynthia <[email protected]>"]
edition = "2021"
license = "MIT"
repository = "https://github.com/rem-verse/sprig"
version = "0.0.6"
version = "0.0.7"

[profile.release]
codegen-units = 1
Expand Down
5 changes: 2 additions & 3 deletions cmd/bridgectl/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,12 @@ publish = false

[dependencies]
cat-dev = { path = "../../pkg/cat-dev" }
clap = { version = "^4.5.4", features = ["color", "derive", "env", "error-context", "help", "suggestions", "unicode", "usage", "wrap_help"] }
clap = { version = "^4.5.21", features = ["color", "derive", "env", "error-context", "help", "suggestions", "unicode", "usage", "wrap_help"] }
fnv.workspace = true
log = { path = "../../pkg/log" }
mac_address.workspace = true
miette.workspace = true
once_cell.workspace = true
terminal_size = "^0.3.0"
terminal_size = "^0.4.0"
tokio.workspace = true
tracing.workspace = true
valuable.workspace = true
Expand Down
125 changes: 63 additions & 62 deletions cmd/bridgectl/src/commands/argv_helpers/bridge_target.rs
Original file line number Diff line number Diff line change
Expand Up @@ -447,76 +447,77 @@ async fn target_search_flags(
target_flags: TargetBridgeFlags,
positional_argument: Option<&str>,
) -> bool {
let (find_by, extra_ip_filter, extra_name_filter, used_arg) =
if target_flags.specified_bridge_search_flag() {
if target_flags.search_for_mac_raw().is_some() {
if let Some(mac) = target_flags.search_for_mac() {
(
MIONFindBy::MacAddress(mac),
target_flags.search_for_ip(),
target_flags.search_for_name(),
false,
)
let (find_by, extra_ip_filter, extra_name_filter, used_arg) = if target_flags
.specified_bridge_search_flag()
{
if target_flags.search_for_mac_raw().is_some() {
if let Some(mac) = target_flags.search_for_mac() {
(
MIONFindBy::MacAddress(mac),
target_flags.search_for_ip(),
target_flags.search_for_name(),
false,
)
} else {
if SHOULD_LOG_JSON() {
warn!(
id = "bridgectl::argv::mac_flag_invalid",
mac_flag = ?target_flags.search_for_mac_raw(),
"Mac Flag is not a valid MAC Address, will not be used, and will exit if no other filters present."
);
} else {
if SHOULD_LOG_JSON() {
warn!(
id = "bridgectl::argv::mac_flag_invalid",
mac_flag = ?target_flags.search_for_mac_raw(),
"Mac Flag is not a valid MAC Address, will not be used, and will exit if no other filters present."
);
} else {
warn!(
mac_flag = ?target_flags.search_for_mac_raw(),
"Mac Flag is not a valid MAC Address, will not be used, and will exit if no other filters present."
);
}
warn!(
mac_flag = ?target_flags.search_for_mac_raw(),
"Mac Flag is not a valid MAC Address, will not be used, and will exit if no other filters present."
);
}

if target_flags.search_for_ip().is_none()
&& target_flags.search_for_name().is_none()
{
std::process::exit(ARGV_NO_BRIDGE_SPECIFIED);
} else {
if let Some(ip) = target_flags.search_for_ip() {
let mut static_ip_opt = TARGETED_BRIDGE_IP.write().await;
_ = static_ip_opt.insert(ip);
}
if let Some(name) = target_flags.search_for_name() {
let mut static_name_opt = TARGETED_BRIDGE_NAME.write().await;
_ = static_name_opt.insert(name.to_owned());
}
return false;
if target_flags.search_for_ip().is_none()
&& target_flags.search_for_name().is_none()
{
std::process::exit(ARGV_NO_BRIDGE_SPECIFIED);
} else {
if let Some(ip) = target_flags.search_for_ip() {
let mut static_ip_opt = TARGETED_BRIDGE_IP.write().await;
_ = static_ip_opt.insert(ip);
}
if let Some(name) = target_flags.search_for_name() {
let mut static_name_opt = TARGETED_BRIDGE_NAME.write().await;
_ = static_name_opt.insert(name.to_owned());
}
return false;
}
} else {
if let Some(ip) = target_flags.search_for_ip() {
let mut static_ip_opt = TARGETED_BRIDGE_IP.write().await;
_ = static_ip_opt.insert(ip);
}
if let Some(name) = target_flags.search_for_name() {
let mut static_name_opt = TARGETED_BRIDGE_NAME.write().await;
_ = static_name_opt.insert(name.to_owned());
}
return false;
}
} else {
let argument = positional_argument.expect(
"internal_error: target_search_flags() called when no search flags were specified",
);
if let Some(ip) = target_flags.search_for_ip() {
let mut static_ip_opt = TARGETED_BRIDGE_IP.write().await;
_ = static_ip_opt.insert(ip);
}
if let Some(name) = target_flags.search_for_name() {
let mut static_name_opt = TARGETED_BRIDGE_NAME.write().await;
_ = static_name_opt.insert(name.to_owned());
}
return false;
}
} else {
let argument = positional_argument.expect(
"internal_error: target_search_flags() called when no search flags were specified",
);

match MIONFindBy::from(argument.to_owned()) {
MIONFindBy::Ip(ip) => {
let mut static_ip_opt = TARGETED_BRIDGE_IP.write().await;
_ = static_ip_opt.insert(ip);
return true;
}
MIONFindBy::MacAddress(mac) => (MIONFindBy::MacAddress(mac), None, None, true),
MIONFindBy::Name(name) => {
let mut static_name_opt = TARGETED_BRIDGE_NAME.write().await;
_ = static_name_opt.insert(name);
return true;
}
match MIONFindBy::from(argument.to_owned()) {
MIONFindBy::Ip(ip) => {
let mut static_ip_opt = TARGETED_BRIDGE_IP.write().await;
_ = static_ip_opt.insert(ip);
return true;
}
MIONFindBy::MacAddress(mac) => (MIONFindBy::MacAddress(mac), None, None, true),
MIONFindBy::Name(name) => {
let mut static_name_opt = TARGETED_BRIDGE_NAME.write().await;
_ = static_name_opt.insert(name);
return true;
}
};
}
};

do_scan_initial(find_by, extra_ip_filter, extra_name_filter, used_arg).await
}
Expand Down
25 changes: 13 additions & 12 deletions cmd/bridgectl/src/knobs/env.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
//! The list of environment variables that influence behavior for `bridgectl`.
use once_cell::sync::Lazy;
use std::{
env::{var as env_var, var_os as env_var_os},
net::Ipv4Addr,
path::PathBuf,
sync::LazyLock,
time::Duration,
};
use tracing::warn;
Expand All @@ -14,43 +14,44 @@ use tracing::warn;
/// Environment Variable Name: `BRIDGECTL_OUTPUT_JSON`
/// Expected Values: ("1" or "0"), and ("true" or "false")
/// Type: Boolean
pub static USE_JSON_OUTPUT: Lazy<bool> =
Lazy::new(|| env_var("BRIDGECTL_OUTPUT_JSON").map_or(false, |var| var == "1" || var == "true"));
pub static USE_JSON_OUTPUT: LazyLock<bool> = LazyLock::new(|| {
env_var("BRIDGECTL_OUTPUT_JSON").map_or(false, |var| var == "1" || var == "true")
});

/// A way of specifying the path to the `bridge_env.ini` file if it's not in
/// a standard location.
///
/// Environment Variable Name: `BRIDGECTL_BRIDGE_ENV_PATH`
/// Expected Values: A Path
/// Type: [`PathBuf`]
pub static BRIDGE_HOST_STATE_PATH: Lazy<Option<PathBuf>> =
Lazy::new(|| env_var_os("BRIDGECTL_BRIDGE_ENV_PATH").map(PathBuf::from));
pub static BRIDGE_HOST_STATE_PATH: LazyLock<Option<PathBuf>> =
LazyLock::new(|| env_var_os("BRIDGECTL_BRIDGE_ENV_PATH").map(PathBuf::from));

/// A way of specifying the serial port to read logs from so you don't have to
/// pass it in over a CLI flag.
///
/// Environment Variable Name: `BRIDGECTL_SERIAL_PORT`
/// Expected Values: `COM1`/`COM2`/etc. on Windows, `/dev/tty` on Linux.
/// Type: [`PathBuf`]
pub static BRIDGECTL_SERIAL_PORT: Lazy<Option<PathBuf>> =
Lazy::new(|| env_var_os("BRIDGECTL_SERIAL_PORT").map(PathBuf::from));
pub static BRIDGECTL_SERIAL_PORT: LazyLock<Option<PathBuf>> =
LazyLock::new(|| env_var_os("BRIDGECTL_SERIAL_PORT").map(PathBuf::from));

/// Set by `cafe`/`cafex`/`mochiato`, a way of specifying the bridge to
/// connect too.
///
/// Environment Variable Name: `BRIDGE_CURRENT_NAME`
/// Expected Values: Empty, or a String of a valid bridge name.
/// Type: String
pub static BRIDGE_CURRENT_NAME: Lazy<Option<String>> =
Lazy::new(|| env_var("BRIDGE_CURRENT_NAME").ok());
pub static BRIDGE_CURRENT_NAME: LazyLock<Option<String>> =
LazyLock::new(|| env_var("BRIDGE_CURRENT_NAME").ok());

/// Set by `cafe`/`cafex`/`mochiato`, a way of specifying the bridge to
/// connect too.
///
/// Environment Variable Name: `BRIDGE_CURRENT_IP_ADDRESS`
/// Expected Values: Empty, or a String of a valid bridge ip address.
/// Type: [`Ipv4Addr`]
pub static BRIDGE_CURRENT_IP_ADDRESS: Lazy<Option<Ipv4Addr>> = Lazy::new(|| {
pub static BRIDGE_CURRENT_IP_ADDRESS: LazyLock<Option<Ipv4Addr>> = LazyLock::new(|| {
env_var("BRIDGE_CURRENT_IP_ADDRESS").ok().and_then(|val| {
match val.parse::<Ipv4Addr>() {
Ok(val) => Some(val),
Expand All @@ -68,7 +69,7 @@ pub static BRIDGE_CURRENT_IP_ADDRESS: Lazy<Option<Ipv4Addr>> = Lazy::new(|| {
/// Environment Variable Name: `BRIDGE_SCAN_TIMEOUT_SECONDS`
/// Expected Values: Empty, or a number of seconds.
/// Type: [`u64`]
pub static BRIDGE_SCAN_TIMEOUT: Lazy<Option<Duration>> = Lazy::new(|| {
pub static BRIDGE_SCAN_TIMEOUT: LazyLock<Option<Duration>> = LazyLock::new(|| {
env_var("BRIDGE_SCAN_TIMEOUT_SECONDS").ok().and_then(|val| {
match val.parse::<u64>() {
Ok(val) => Some(Duration::from_secs(val)),
Expand All @@ -91,7 +92,7 @@ pub static BRIDGE_SCAN_TIMEOUT: Lazy<Option<Duration>> = Lazy::new(|| {
/// Environment Variable Name: `BRIDGE_CONTROL_PORT_OVERRIDE`
/// Expected Values: Empty, or a port number (0-65536).
/// Type: [`u16`]
pub static BRIDGE_CONTROL_PORT: Lazy<Option<u16>> = Lazy::new(|| {
pub static BRIDGE_CONTROL_PORT: LazyLock<Option<u16>> = LazyLock::new(|| {
env_var("BRIDGE_CONTROL_PORT_OVERRIDE").ok().and_then(|val| {
match val.parse::<u16>() {
Ok(val) => Some(val),
Expand Down
23 changes: 12 additions & 11 deletions pkg/cat-dev/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,22 @@ repository.workspace = true
version.workspace = true

[dependencies]
aes = "^0.8.4"
bytes.workspace = true
configparser = "^3.0.4"
# Keep us equal with tonic, which is pulled in through tokio console in `log`.
hyper = { version = "^0.14.28", features = ["http1", "client", "runtime", "stream"] }
cipher = { version = "^0.4.4", features = ["alloc", "block-padding"] }
configparser = "^3.1.0"
ecb = "^0.1.2"
fnv.workspace = true
futures = "^0.3.30"
local-ip-address = "^0.6.1"
futures = "^0.3.31"
local-ip-address = "^0.6.3"
mac_address.workspace = true
miette.workspace = true
network-interface.workspace = true
pin-project-lite = "^0.2.14"
serde = "^1.0.197"
pin-project-lite = "^0.2.15"
reqwest = "^0.12.9"
serde = "^1.0.214"
serde_urlencoded = "^0.7.1"
thiserror = "^1.0.58"
thiserror = "^2.0.3"
tracing.workspace = true
tokio.workspace = true
valuable.workspace = true
Expand All @@ -30,11 +32,10 @@ valuable.workspace = true
libc = "^0.2"

[target.'cfg(target_os = "windows")'.dependencies]
windows = { version = "^0.54.0", default-features = false, features=["Win32_Devices_Communication", "Win32_Networking_WinSock", "Win32_Security", "Win32_Storage_FileSystem", "Win32_System_IO", "Win32_System_Registry", "Win32_System_Threading"] }
windows = { version = "^0.58.0", default-features = false, features=["Win32_Devices_Communication", "Win32_Networking_WinSock", "Win32_Security", "Win32_Storage_FileSystem", "Win32_System_IO", "Win32_System_Registry", "Win32_System_Threading"] }

[dev-dependencies]
once_cell.workspace = true
tempfile = "^3.10.1"
tempfile = "^3.14.0"

[package.metadata.docs.rs]
rustc-args = ["--cfg", "tokio_unstable", "--cfg", "tracing_unstable"]
Expand Down
Loading

0 comments on commit 533a149

Please sign in to comment.