diff --git a/Cargo.toml b/Cargo.toml index 1671524..4099dbb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,6 +26,23 @@ members = [ "crates/tests", ] +[workspace.lints.clippy] +all = { level = "deny", priority = -1 } +pedantic = { level = "warn", priority = -1 } + +# used often in tests +wildcard_imports = { level = "allow"} + +# annoying +must_use_candidate = "allow" +return_self_not_must_use = "allow" + +# sometimes i like the logical flow of keeping things in an "else" +redundant_else = "allow" + +# i hate using `.unwrap_or_else(|| keyfork_bug::bug!())` +expect_fun_call = "allow" + [workspace.dependencies] # Keyfork dependencies @@ -84,4 +101,3 @@ debug = true [profile.dev.package.keyfork-qrcode] opt-level = 3 debug = true - diff --git a/clippy.toml b/clippy.toml new file mode 100644 index 0000000..adf8594 --- /dev/null +++ b/clippy.toml @@ -0,0 +1 @@ +doc-valid-idents = ["OpenPGP", ".."] diff --git a/crates/daemon/keyforkd-client/Cargo.toml b/crates/daemon/keyforkd-client/Cargo.toml index 99ae439..8c11e26 100644 --- a/crates/daemon/keyforkd-client/Cargo.toml +++ b/crates/daemon/keyforkd-client/Cargo.toml @@ -4,6 +4,9 @@ version = "0.2.2" edition = "2021" license = "MIT" +[lints] +workspace = true + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [features] diff --git a/crates/daemon/keyforkd-client/src/lib.rs b/crates/daemon/keyforkd-client/src/lib.rs index f8fefbe..4bb17e8 100644 --- a/crates/daemon/keyforkd-client/src/lib.rs +++ b/crates/daemon/keyforkd-client/src/lib.rs @@ -26,7 +26,7 @@ //! //! ### Request: Derive Key //! -//! The client creates a derivation path of at least two indices and requests a derived XPrv +//! The client creates a derivation path of at least two indices and requests a derived `XPrv` //! (Extended Private Key) from the server. //! //! ```rust @@ -68,7 +68,7 @@ //! ## Extended Private Keys //! //! Keyfork doesn't need to be continuously called once a key has been derived. Once an Extended -//! Private Key (often shortened to "XPrv") has been created, further derivations can be performed. +//! Private Key (often shortened to `XPrv`) has been created, further derivations can be performed. //! The tests for this library ensure that all levels of Keyfork derivation beyond the required two //! will be derived similarly between the server and the client. //! @@ -117,7 +117,7 @@ //! //! ## Testing Infrastructure //! -//! In tests, the `keyforkd::test_util` module and TestPrivateKeys can be used. These provide +//! In tests, the `keyforkd::test_util` module and `TestPrivateKeys` can be used. These provide //! useful utilities for writing tests that interact with the Keyfork Server without needing to //! manually create the server for the purpose of the test. The `run_test` method can be used to //! run a test, which can handle both returning errors and correctly translating panics (though, @@ -199,6 +199,10 @@ pub enum Error { #[error("Socket was unable to connect to {1}: {0} (make sure keyforkd is running)")] Connect(std::io::Error, PathBuf), + /// The path of the derived key was of an invalid length. + #[error("Derived key path is of invalid length")] + InvalidPathLength(#[from] std::num::TryFromIntError), + /// Data could not be written to, or read from, the socket. #[error("Could not write to or from the socket: {0}")] Io(#[from] std::io::Error), @@ -237,19 +241,15 @@ pub fn get_socket() -> Result { .filter(|(key, _)| ["XDG_RUNTIME_DIR", "KEYFORKD_SOCKET_PATH"].contains(&key.as_str())) .collect::>(); let mut socket_path: PathBuf; - #[allow(clippy::single_match_else)] - match socket_vars.get("KEYFORKD_SOCKET_PATH") { - Some(occupied) => { - socket_path = PathBuf::from(occupied); - } - None => { - socket_path = PathBuf::from( - socket_vars - .get("XDG_RUNTIME_DIR") - .ok_or(Error::EnvVarsNotFound)?, - ); - socket_path.extend(["keyforkd", "keyforkd.sock"]); - } + if let Some(occupied) = socket_vars.get("KEYFORKD_SOCKET_PATH") { + socket_path = PathBuf::from(occupied); + } else { + socket_path = PathBuf::from( + socket_vars + .get("XDG_RUNTIME_DIR") + .ok_or(Error::EnvVarsNotFound)?, + ); + socket_path.extend(["keyforkd", "keyforkd.sock"]); } UnixStream::connect(&socket_path).map_err(|e| Error::Connect(e, socket_path)) } @@ -266,7 +266,7 @@ pub struct Client { impl Client { /// Create a new client from a given already-connected [`UnixStream`]. This function is - /// provided in case a specific UnixStream has to be used; otherwise, + /// provided in case a specific `UnixStream` has to be used; otherwise, /// [`Client::discover_socket`] should be preferred. /// /// # Examples @@ -344,7 +344,7 @@ impl Client { return Err(Error::InvalidResponse); } - let depth = path.len() as u8; + let depth = u8::try_from(path.len())?; ExtendedPrivateKey::from_parts(&d.data, depth, d.chain_code) .map_err(|_| Error::InvalidKey) } diff --git a/crates/daemon/keyforkd-models/Cargo.toml b/crates/daemon/keyforkd-models/Cargo.toml index 861613c..a67d9ff 100644 --- a/crates/daemon/keyforkd-models/Cargo.toml +++ b/crates/daemon/keyforkd-models/Cargo.toml @@ -4,6 +4,9 @@ version = "0.2.0" edition = "2021" license = "MIT" +[lints] +workspace = true + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] diff --git a/crates/daemon/keyforkd/Cargo.toml b/crates/daemon/keyforkd/Cargo.toml index 3893370..74d61d2 100644 --- a/crates/daemon/keyforkd/Cargo.toml +++ b/crates/daemon/keyforkd/Cargo.toml @@ -4,6 +4,9 @@ version = "0.1.4" edition = "2021" license = "AGPL-3.0-only" +[lints] +workspace = true + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [features] diff --git a/crates/daemon/keyforkd/src/lib.rs b/crates/daemon/keyforkd/src/lib.rs index 123c63c..1f069f3 100644 --- a/crates/daemon/keyforkd/src/lib.rs +++ b/crates/daemon/keyforkd/src/lib.rs @@ -89,27 +89,23 @@ pub async fn start_and_run_server(mnemonic: Mnemonic) -> Result<(), Box>(); - let mut runtime_path: PathBuf; - #[allow(clippy::single_match_else)] - match runtime_vars.get("KEYFORKD_SOCKET_PATH") { - Some(occupied) => { - runtime_path = PathBuf::from(occupied); + let runtime_path = if let Some(occupied) = runtime_vars.get("KEYFORKD_SOCKET_PATH") { + PathBuf::from(occupied) + } else { + let mut runtime_path = PathBuf::from( + runtime_vars + .get("XDG_RUNTIME_DIR") + .ok_or(KeyforkdError::NoSocketPath)?, + ); + runtime_path.push("keyforkd"); + #[cfg(feature = "tracing")] + debug!("ensuring directory exists: {}", runtime_path.display()); + if !runtime_path.is_dir() { + tokio::fs::create_dir(&runtime_path).await?; } - None => { - runtime_path = PathBuf::from( - runtime_vars - .get("XDG_RUNTIME_DIR") - .ok_or(KeyforkdError::NoSocketPath)?, - ); - runtime_path.push("keyforkd"); - #[cfg(feature = "tracing")] - debug!("ensuring directory exists: {}", runtime_path.display()); - if !runtime_path.is_dir() { - tokio::fs::create_dir(&runtime_path).await?; - } - runtime_path.push("keyforkd.sock"); - } - } + runtime_path.push("keyforkd.sock"); + runtime_path + }; #[cfg(feature = "tracing")] debug!( diff --git a/crates/daemon/keyforkd/src/server.rs b/crates/daemon/keyforkd/src/server.rs index 780b1aa..3c428f3 100644 --- a/crates/daemon/keyforkd/src/server.rs +++ b/crates/daemon/keyforkd/src/server.rs @@ -49,7 +49,8 @@ impl IsDisconnect for EncodeError { } impl UnixServer { - /// Bind a socket to the given `address` and create a [`UnixServer`]. This function also creates a ctrl_c handler to automatically clean up the socket file. + /// Bind a socket to the given `address` and create a [`UnixServer`]. This function also + /// creates a `ctrl_c` handler to automatically clean up the socket file. /// /// # Errors /// This function may return an error if the socket can't be bound. diff --git a/crates/daemon/keyforkd/src/service.rs b/crates/daemon/keyforkd/src/service.rs index 1e3205f..98931bb 100644 --- a/crates/daemon/keyforkd/src/service.rs +++ b/crates/daemon/keyforkd/src/service.rs @@ -174,7 +174,7 @@ mod tests { } } - #[should_panic] + #[should_panic(expected = "InvalidDerivationLength(0)")] #[tokio::test] async fn errors_on_no_path() { let tests = [( @@ -200,7 +200,7 @@ mod tests { } } - #[should_panic] + #[should_panic(expected = "InvalidDerivationLength(1)")] #[tokio::test] async fn errors_on_short_path() { let tests = [( diff --git a/crates/daemon/keyforkd/src/test_util.rs b/crates/daemon/keyforkd/src/test_util.rs index cebaaf2..5b6b62d 100644 --- a/crates/daemon/keyforkd/src/test_util.rs +++ b/crates/daemon/keyforkd/src/test_util.rs @@ -89,7 +89,7 @@ where .expect(bug!("couldn't send server start signal")); let service = ServiceBuilder::new() .layer(middleware::BincodeLayer::new()) - .service(Keyforkd::new(seed.to_vec())); + .service(Keyforkd::new(seed.clone())); server .run(service) .await diff --git a/crates/derive/keyfork-derive-age/Cargo.toml b/crates/derive/keyfork-derive-age/Cargo.toml index 6d76f30..4cf8d04 100644 --- a/crates/derive/keyfork-derive-age/Cargo.toml +++ b/crates/derive/keyfork-derive-age/Cargo.toml @@ -4,6 +4,9 @@ version = "0.1.0" edition = "2021" license = "AGPL-3.0-only" +[lints] +workspace = true + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] diff --git a/crates/derive/keyfork-derive-key/Cargo.toml b/crates/derive/keyfork-derive-key/Cargo.toml index 53613bd..da8c544 100644 --- a/crates/derive/keyfork-derive-key/Cargo.toml +++ b/crates/derive/keyfork-derive-key/Cargo.toml @@ -4,6 +4,9 @@ version = "0.1.2" edition = "2021" license = "AGPL-3.0-only" +[lints] +workspace = true + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] diff --git a/crates/derive/keyfork-derive-openpgp/Cargo.toml b/crates/derive/keyfork-derive-openpgp/Cargo.toml index 61477f4..b8c80ca 100644 --- a/crates/derive/keyfork-derive-openpgp/Cargo.toml +++ b/crates/derive/keyfork-derive-openpgp/Cargo.toml @@ -4,6 +4,9 @@ version = "0.1.5" edition = "2021" license = "AGPL-3.0-only" +[lints] +workspace = true + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [features] default = ["bin"] diff --git a/crates/derive/keyfork-derive-openpgp/src/lib.rs b/crates/derive/keyfork-derive-openpgp/src/lib.rs index 2804d02..3641d3f 100644 --- a/crates/derive/keyfork-derive-openpgp/src/lib.rs +++ b/crates/derive/keyfork-derive-openpgp/src/lib.rs @@ -74,7 +74,7 @@ pub type Result = std::result::Result; /// /// # Errors /// The function may error for any condition mentioned in [`Error`]. -pub fn derive(xprv: XPrv, keys: &[KeyFlags], userid: &UserID) -> Result { +pub fn derive(xprv: &XPrv, keys: &[KeyFlags], userid: &UserID) -> Result { let primary_key_flags = match keys.first() { Some(kf) if kf.for_certification() => kf, _ => return Err(Error::NotCert), diff --git a/crates/derive/keyfork-derive-openpgp/src/main.rs b/crates/derive/keyfork-derive-openpgp/src/main.rs index 4bc61d2..efa872e 100644 --- a/crates/derive/keyfork-derive-openpgp/src/main.rs +++ b/crates/derive/keyfork-derive-openpgp/src/main.rs @@ -120,7 +120,7 @@ fn run() -> Result<(), Box> { .map(|kt| kt.inner().clone()) .collect::>(); - let cert = keyfork_derive_openpgp::derive(derived_xprv, subkeys.as_slice(), &default_userid)?; + let cert = keyfork_derive_openpgp::derive(&derived_xprv, subkeys.as_slice(), &default_userid)?; let mut w = Writer::new(std::io::stdout(), Kind::SecretKey)?; diff --git a/crates/derive/keyfork-derive-path-data/Cargo.toml b/crates/derive/keyfork-derive-path-data/Cargo.toml index 55d6f48..20e129b 100644 --- a/crates/derive/keyfork-derive-path-data/Cargo.toml +++ b/crates/derive/keyfork-derive-path-data/Cargo.toml @@ -4,6 +4,9 @@ version = "0.1.3" edition = "2021" license = "MIT" +[lints] +workspace = true + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] diff --git a/crates/derive/keyfork-derive-path-data/src/lib.rs b/crates/derive/keyfork-derive-path-data/src/lib.rs index 2bde030..dab3d04 100644 --- a/crates/derive/keyfork-derive-path-data/src/lib.rs +++ b/crates/derive/keyfork-derive-path-data/src/lib.rs @@ -2,7 +2,7 @@ #![allow(clippy::unreadable_literal)] -use once_cell::sync::Lazy; +use std::sync::LazyLock; use keyfork_derive_util::{DerivationIndex, DerivationPath}; @@ -11,7 +11,7 @@ pub mod paths { use super::*; /// The default derivation path for OpenPGP. - pub static OPENPGP: Lazy = Lazy::new(|| { + pub static OPENPGP: LazyLock = LazyLock::new(|| { DerivationPath::default().chain_push(DerivationIndex::new_unchecked( u32::from_be_bytes(*b"\x00pgp"), true, @@ -19,7 +19,7 @@ pub mod paths { }); /// The derivation path for OpenPGP certificates used for sharding. - pub static OPENPGP_SHARD: Lazy = Lazy::new(|| { + pub static OPENPGP_SHARD: LazyLock = LazyLock::new(|| { DerivationPath::default() .chain_push(DerivationIndex::new_unchecked( u32::from_be_bytes(*b"\x00pgp"), @@ -32,7 +32,7 @@ pub mod paths { }); /// The derivation path for OpenPGP certificates used for disaster recovery. - pub static OPENPGP_DISASTER_RECOVERY: Lazy = Lazy::new(|| { + pub static OPENPGP_DISASTER_RECOVERY: LazyLock = LazyLock::new(|| { DerivationPath::default() .chain_push(DerivationIndex::new_unchecked( u32::from_be_bytes(*b"\x00pgp"), diff --git a/crates/derive/keyfork-derive-util/Cargo.toml b/crates/derive/keyfork-derive-util/Cargo.toml index 097b606..67b6916 100644 --- a/crates/derive/keyfork-derive-util/Cargo.toml +++ b/crates/derive/keyfork-derive-util/Cargo.toml @@ -4,6 +4,9 @@ version = "0.2.2" edition = "2021" license = "MIT" +[lints] +workspace = true + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [features] diff --git a/crates/derive/keyfork-derive-util/src/extended_key/private_key.rs b/crates/derive/keyfork-derive-util/src/extended_key/private_key.rs index 1ca905f..f4e928b 100644 --- a/crates/derive/keyfork-derive-util/src/extended_key/private_key.rs +++ b/crates/derive/keyfork-derive-util/src/extended_key/private_key.rs @@ -52,7 +52,7 @@ pub struct VariableLengthSeed<'a> { } impl<'a> VariableLengthSeed<'a> { - /// Create a new VariableLengthSeed. + /// Create a new `VariableLengthSeed`. /// /// # Examples /// ```rust @@ -167,6 +167,7 @@ where /// # b"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; /// let xprv = ExtendedPrivateKey::::new(*seed); /// ``` + #[allow(clippy::needless_pass_by_value)] pub fn new(seed: impl as_private_key::AsPrivateKey) -> Result { Self::new_internal(seed.as_private_key()) } diff --git a/crates/derive/keyfork-derive-util/src/index.rs b/crates/derive/keyfork-derive-util/src/index.rs index 98f688e..3746292 100644 --- a/crates/derive/keyfork-derive-util/src/index.rs +++ b/crates/derive/keyfork-derive-util/src/index.rs @@ -117,7 +117,7 @@ mod tests { use std::str::FromStr; #[test] - #[should_panic] + #[should_panic(expected = "IndexTooLarge")] fn fails_on_high_index() { DerivationIndex::new(0x8000_0001, false).unwrap(); } @@ -163,7 +163,7 @@ mod tests { } #[test] - #[should_panic] + #[should_panic(expected = "IndexTooLarge")] fn from_str_fails_on_high_index() { DerivationIndex::from_str(&0x8000_0001u32.to_string()).unwrap(); } diff --git a/crates/derive/keyfork-derive-util/src/lib.rs b/crates/derive/keyfork-derive-util/src/lib.rs index b55b64e..defc13a 100644 --- a/crates/derive/keyfork-derive-util/src/lib.rs +++ b/crates/derive/keyfork-derive-util/src/lib.rs @@ -1,4 +1,4 @@ -#![allow(clippy::module_name_repetitions, clippy::must_use_candidate)] +#![allow(clippy::module_name_repetitions)] #![doc = include_str!("../README.md")] pub mod extended_key; diff --git a/crates/derive/keyfork-derive-util/src/path.rs b/crates/derive/keyfork-derive-util/src/path.rs index 3241e82..e500447 100644 --- a/crates/derive/keyfork-derive-util/src/path.rs +++ b/crates/derive/keyfork-derive-util/src/path.rs @@ -11,7 +11,7 @@ pub enum Error { /// The path could not be parsed due to a bad prefix. Paths must be in the format: /// - /// m [/ index [']]+ + /// `m [/ index [']]+` /// /// The prefix for the path must be `m`, and all indices must be integers between 0 and /// 2^31. @@ -35,8 +35,8 @@ impl DerivationPath { self.path.iter() } - /// The amount of segments in the DerivationPath. For consistency, a [`usize`] is returned, but - /// BIP-0032 dictates that the depth should be no larger than `255`, [`u8::MAX`]. + /// The amount of segments in the [`DerivationPath`]. For consistency, a [`usize`] is returned, + /// but BIP-0032 dictates that the depth should be no larger than `255`, [`u8::MAX`]. pub fn len(&self) -> usize { self.path.len() } @@ -134,7 +134,7 @@ mod tests { use std::str::FromStr; #[test] - #[should_panic] + #[should_panic(expected = "UnknownPathPrefix")] fn requires_master_path() { DerivationPath::from_str("1234/5678'").unwrap(); } diff --git a/crates/derive/keyfork-derive-util/src/public_key.rs b/crates/derive/keyfork-derive-util/src/public_key.rs index 23ae69c..22a043b 100644 --- a/crates/derive/keyfork-derive-util/src/public_key.rs +++ b/crates/derive/keyfork-derive-util/src/public_key.rs @@ -156,7 +156,7 @@ pub struct TestPublicKey { } impl TestPublicKey { - /// Create a new TestPublicKey from the given bytes. + /// Create a new [`TestPublicKey`] from the given bytes. #[allow(dead_code)] pub fn from_bytes(b: &[u8]) -> Self { Self { diff --git a/crates/derive/keyfork-derive-util/src/tests.rs b/crates/derive/keyfork-derive-util/src/tests.rs index aa1a087..7d12fcd 100644 --- a/crates/derive/keyfork-derive-util/src/tests.rs +++ b/crates/derive/keyfork-derive-util/src/tests.rs @@ -102,7 +102,7 @@ fn ed25519() { #[cfg(feature = "ed25519")] #[test] -#[should_panic] +#[should_panic(expected = "HardenedDerivationRequired")] fn panics_with_unhardened_derivation() { use ed25519_dalek::SigningKey; @@ -114,7 +114,7 @@ fn panics_with_unhardened_derivation() { #[cfg(feature = "ed25519")] #[test] -#[should_panic] +#[should_panic(expected = "Depth")] fn panics_at_depth() { use ed25519_dalek::SigningKey; diff --git a/crates/keyfork-shard/Cargo.toml b/crates/keyfork-shard/Cargo.toml index 4e727e5..e967180 100644 --- a/crates/keyfork-shard/Cargo.toml +++ b/crates/keyfork-shard/Cargo.toml @@ -4,6 +4,9 @@ version = "0.3.4" edition = "2021" license = "AGPL-3.0-only" +[lints] +workspace = true + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [features] diff --git a/crates/keyfork-shard/src/bin/keyfork-shard-remote.rs b/crates/keyfork-shard/src/bin/keyfork-shard-remote.rs index c9b1aa9..6a67372 100644 --- a/crates/keyfork-shard/src/bin/keyfork-shard-remote.rs +++ b/crates/keyfork-shard/src/bin/keyfork-shard-remote.rs @@ -13,7 +13,7 @@ fn run() -> Result<()> { match args.as_slice() { [] => (), _ => panic!("Usage: {program_name}"), - }; + } let mut bytes = vec![]; remote_decrypt(&mut bytes)?; diff --git a/crates/keyfork-shard/src/lib.rs b/crates/keyfork-shard/src/lib.rs index 5fdf606..5abc0bd 100644 --- a/crates/keyfork-shard/src/lib.rs +++ b/crates/keyfork-shard/src/lib.rs @@ -1,5 +1,4 @@ #![doc = include_str!("../README.md")] -#![allow(clippy::expect_fun_call)] use std::{ io::{Read, Write}, @@ -92,9 +91,10 @@ pub trait KeyDiscovery { /// # Errors /// The method may return an error if private keys could not be loaded from the given /// discovery mechanism. Keys may exist off-system (such as with smartcards), in which case the - /// PrivateKeyData type of the asssociated format should be either `()` (if the keys may never - /// exist on-system) or an empty container (such as an empty Vec); in either case, this method - /// _must not_ return an error if keys are accessible but can't be transferred into memory. + /// `PrivateKeyData` type of the asssociated format should be either `()` (if the keys may + /// never exist on-system) or an empty container (such as an empty Vec); in either case, this + /// method _must not_ return an error if keys are accessible but can't be transferred into + /// memory. fn discover_private_keys(&self) -> Result; } @@ -121,8 +121,8 @@ pub trait Format { /// Format a header containing necessary metadata. Such metadata contains a version byte, a /// threshold byte, a public version of the [`Format::SigningKey`], and the public keys used to /// encrypt shards. The public keys must be kept _in order_ to the encrypted shards. Keyfork - /// will use the same key_data for both, ensuring an iteration of this method will match with - /// iterations in methods called later. + /// will use the same `key_data` for both, ensuring an iteration of this method will match + /// with iterations in methods called later. /// /// # Errors /// The method may return an error if encryption to any of the public keys fails. @@ -263,6 +263,7 @@ pub trait Format { /// The method may return an error if a share can't be decrypted. The method will not return an /// error if the camera is inaccessible or if a hardware error is encountered while scanning a /// QR code; instead, a mnemonic prompt will be used. + #[allow(clippy::too_many_lines)] fn decrypt_one_shard_for_transport( &self, private_key_discovery: Option>, @@ -326,41 +327,27 @@ pub trait Format { if choice == RetryScanMnemonic::Continue { break; } - }; + } } } // if QR code scanning failed or was unavailable, read from a set of mnemonics - let their_pubkey = match pubkey_data { - Some(pubkey) => pubkey, - None => { - let validator = MnemonicValidator { - word_length: Some(WordLength::Count(24)), - }; - let mut prompt = prompt.lock().expect(bug!(POISONED_MUTEX)); - prompt_validated_wordlist::( - &mut **prompt, - QRCODE_COULDNT_READ, - 3, - &*validator.to_fn(), - )? - .as_bytes() - .try_into() - .map_err(|_| InvalidData)? - /* - prompt - .lock() - .expect(bug!(POISONED_MUTEX)) - .prompt_validated_wordlist::( - QRCODE_COULDNT_READ, - 3, - validator.to_fn(), - )? - .as_bytes() - .try_into() - .map_err(|_| InvalidData)? - */ - } + let their_pubkey = if let Some(pubkey) = pubkey_data { + pubkey + } else { + let validator = MnemonicValidator { + word_length: Some(WordLength::Count(24)), + }; + let mut prompt = prompt.lock().expect(bug!(POISONED_MUTEX)); + prompt_validated_wordlist::( + &mut **prompt, + QRCODE_COULDNT_READ, + 3, + &*validator.to_fn(), + )? + .as_bytes() + .try_into() + .map_err(|_| InvalidData)? }; // create our shared key @@ -401,7 +388,6 @@ pub trait Format { // NOTE: Previous versions of Keyfork Shard would modify the padding bytes to avoid // duplicate mnemonic words. This version does not include that, and instead uses a // repeated length byte. - #[allow(clippy::cast_possible_truncation)] let mut plaintext_bytes = [u8::try_from(payload.len()).expect(bug!( "previously asserted length must be < {PLAINTEXT_LENGTH}", PLAINTEXT_LENGTH = PLAINTEXT_LENGTH @@ -481,11 +467,11 @@ pub trait Format { "must have less than u8::MAX public keys" ); assert_eq!( - max, - public_keys.len() as u8, + max as usize, + public_keys.len(), "max must be equal to amount of public keys" ); - let max = public_keys.len() as u8; + let max = u8::try_from(public_keys.len()).expect(bug!("invalid max: {max}", max = max)); assert!(max >= threshold, "threshold must not exceed max keys"); let header = self.format_encrypted_header(&signing_key, &public_keys, threshold)?; @@ -547,6 +533,7 @@ static QRCODE_TIMEOUT: LazyLock = LazyLock::new(|| { /// # Panics /// The function may panic if it is given payloads generated using a version of Keyfork that is /// incompatible with the currently running version. +#[allow(clippy::too_many_lines)] pub fn remote_decrypt(w: &mut impl Write) -> Result<(), Box> { let mut pm = keyfork_prompt::default_handler()?; @@ -627,30 +614,29 @@ pub fn remote_decrypt(w: &mut impl Write) -> Result<(), Box (pubkey, payload), - _ => { - let validator = MnemonicSetValidator { - word_lengths: [24, 39], - }; + let (pubkey, payload) = if let Some((pubkey, payload)) = pubkey_data.zip(payload_data) { + (pubkey, payload) + } else { + let validator = MnemonicSetValidator { + word_lengths: [24, 39], + }; - let [pubkey_mnemonic, payload_mnemonic] = prompt_validated_wordlist::( - &mut *pm, - QRCODE_COULDNT_READ, - 3, - &*validator.to_fn(), - )?; - let pubkey = pubkey_mnemonic - .as_bytes() - .try_into() - .map_err(|_| InvalidData)?; - let payload = payload_mnemonic.to_bytes(); - (pubkey, payload) - } + let [pubkey_mnemonic, payload_mnemonic] = prompt_validated_wordlist::( + &mut *pm, + QRCODE_COULDNT_READ, + 3, + &*validator.to_fn(), + )?; + let pubkey = pubkey_mnemonic + .as_bytes() + .try_into() + .map_err(|_| InvalidData)?; + let payload = payload_mnemonic.to_bytes(); + (pubkey, payload) }; assert_eq!( @@ -677,16 +663,13 @@ pub fn remote_decrypt(w: &mut impl Write) -> Result<(), Box { - // Must be > 0 to start loop, can't go lower - *n -= 1; - } - None => { - // NOTE: Should always be >= 1, < 256 due to Shamir constraints - threshold = payload[1]; - let _ = iter_count.insert(threshold - 1); - } + if let Some(n) = &mut iter_count { + // Must be > 0 to start loop, can't go lower + *n -= 1; + } else { + // NOTE: Should always be >= 1, < 256 due to Shamir constraints + threshold = payload[1]; + let _ = iter_count.insert(threshold - 1); } let payload_len = payload.last().expect(bug!("payload should not be empty")); diff --git a/crates/keyfork-shard/src/openpgp.rs b/crates/keyfork-shard/src/openpgp.rs index b43f654..76bf4bb 100644 --- a/crates/keyfork-shard/src/openpgp.rs +++ b/crates/keyfork-shard/src/openpgp.rs @@ -1,7 +1,5 @@ //! OpenPGP Shard functionality. -#![allow(clippy::expect_fun_call)] - use std::{ collections::HashMap, io::{Read, Write}, @@ -94,7 +92,7 @@ pub struct EncryptedMessage { } impl EncryptedMessage { - /// Create a new EncryptedMessage from known parts. + /// Create a new [`EncryptedMessage`] from known parts. pub fn new(pkesks: &mut Vec, seip: SEIP) -> Self { Self { pkesks: std::mem::take(pkesks), @@ -160,7 +158,7 @@ impl EncryptedMessage { /// Decrypt the message with a Sequoia policy and decryptor. /// /// This method creates a container containing the packets and passes the serialized container - /// to a DecryptorBuilder, which is used to decrypt the message. + /// to a `DecryptorBuilder`, which is used to decrypt the message. /// /// # Errors /// The method may return an error if it is unable to rebuild the message to decrypt or if it @@ -265,7 +263,7 @@ impl Format for OpenPGP { .derive_path(&path) .expect(bug!("valid derivation")); keyfork_derive_openpgp::derive( - xprv, + &xprv, &[KeyFlags::empty().set_certification().set_signing()], &userid, ) @@ -450,8 +448,8 @@ impl Format for OpenPGP { // We don't want to invalidate someone's keys just because the old sig expired. let policy = NullPolicy::new(); - let mut keyring = Keyring::new(private_keys.unwrap_or_default(), prompt.clone())?; - let mut manager = SmartcardManager::new(prompt.clone())?; + let mut keyring = Keyring::new(private_keys.unwrap_or_default(), prompt.clone()); + let mut manager = SmartcardManager::new(prompt.clone()); let mut encrypted_messages = encrypted_data.iter(); @@ -482,9 +480,9 @@ impl Format for OpenPGP { let left_from_threshold = threshold as usize - decrypted_messages.len(); if left_from_threshold > 0 { - #[allow(clippy::cast_possible_truncation)] let new_messages = decrypt_with_manager( - left_from_threshold as u8, + u8::try_from(left_from_threshold) + .expect(bug!("threshold too large: {}", left_from_threshold)), &mut messages, &certs, &policy, @@ -509,8 +507,8 @@ impl Format for OpenPGP { ) -> std::result::Result<(Share, u8), Self::Error> { let policy = NullPolicy::new(); - let mut keyring = Keyring::new(private_keys.unwrap_or_default(), prompt.clone())?; - let mut manager = SmartcardManager::new(prompt.clone())?; + let mut keyring = Keyring::new(private_keys.unwrap_or_default(), prompt.clone()); + let mut manager = SmartcardManager::new(prompt.clone()); let mut encrypted_messages = encrypted_data.iter(); @@ -557,8 +555,8 @@ impl Format for OpenPGP { prompt: Rc>>, ) -> std::result::Result<(u8, Vec), Self::Error> { let policy = NullPolicy::new(); - let mut keyring = Keyring::new(private_keys.unwrap_or_default(), prompt.clone())?; - let mut manager = SmartcardManager::new(prompt.clone())?; + let mut keyring = Keyring::new(private_keys.unwrap_or_default(), prompt.clone()); + let mut manager = SmartcardManager::new(prompt.clone()); let mut encrypted_messages = encrypted_data.iter(); let metadata = encrypted_messages diff --git a/crates/keyfork-shard/src/openpgp/keyring.rs b/crates/keyfork-shard/src/openpgp/keyring.rs index 7657eb9..1a13a63 100644 --- a/crates/keyfork-shard/src/openpgp/keyring.rs +++ b/crates/keyfork-shard/src/openpgp/keyring.rs @@ -1,5 +1,3 @@ -#![allow(clippy::expect_fun_call)] - use std::{rc::Rc, sync::Mutex}; use keyfork_bug::{bug, POISONED_MUTEX}; @@ -25,8 +23,6 @@ pub enum Error { Prompt(#[from] PromptError), } -pub type Result = std::result::Result; - pub struct Keyring { full_certs: Vec, root: Option, @@ -34,12 +30,12 @@ pub struct Keyring { } impl Keyring { - pub fn new(certs: impl AsRef<[Cert]>, p: Rc>>) -> Result { - Ok(Self { + pub fn new(certs: impl AsRef<[Cert]>, p: Rc>>) -> Self { + Self { full_certs: certs.as_ref().to_vec(), - root: Default::default(), + root: Option::default(), pm: p, - }) + } } pub fn is_empty(&self) -> bool { diff --git a/crates/keyfork-shard/src/openpgp/smartcard.rs b/crates/keyfork-shard/src/openpgp/smartcard.rs index bf6c835..b377a74 100644 --- a/crates/keyfork-shard/src/openpgp/smartcard.rs +++ b/crates/keyfork-shard/src/openpgp/smartcard.rs @@ -1,5 +1,3 @@ -#![allow(clippy::expect_fun_call)] - use std::{ collections::{HashMap, HashSet}, rc::Rc, @@ -81,13 +79,13 @@ pub struct SmartcardManager { } impl SmartcardManager { - pub fn new(p: Rc>>) -> Result { - Ok(Self { + pub fn new(p: Rc>>) -> Self { + Self { current_card: None, root: None, pm: p, - pin_cache: Default::default(), - }) + pin_cache: HashMap::default(), + } } // Sets the root cert, returning the old cert @@ -177,10 +175,9 @@ impl SmartcardManager { impl VerificationHelper for &mut SmartcardManager { fn get_certs(&mut self, ids: &[openpgp::KeyHandle]) -> openpgp::Result> { - #[allow(clippy::flat_map_option)] Ok(ids .iter() - .flat_map(|kh| self.root.as_ref().filter(|cert| cert.key_handle() == *kh)) + .filter_map(|kh| self.root.as_ref().filter(|cert| cert.key_handle() == *kh)) .cloned() .collect()) } @@ -281,8 +278,7 @@ impl DecryptionHelper for &mut SmartcardManager { let temp_pin = prompt_validated_passphrase(&mut **prompt, &message, 3, &pin_validator)?; let verification_status = transaction.verify_user_pin(temp_pin.as_str().trim()); match verification_status { - #[allow(clippy::ignored_unit_patterns)] - Ok(_) => { + Ok(()) => { self.pin_cache.insert(fp.clone(), temp_pin.clone()); pin.replace(temp_pin); } diff --git a/crates/keyfork/Cargo.toml b/crates/keyfork/Cargo.toml index ca972d3..cc78fbe 100644 --- a/crates/keyfork/Cargo.toml +++ b/crates/keyfork/Cargo.toml @@ -4,6 +4,9 @@ version = "0.3.3" edition = "2021" license = "AGPL-3.0-only" +[lints] +workspace = true + [features] default = [ "completion", diff --git a/crates/keyfork/src/clap_ext.rs b/crates/keyfork/src/clap_ext.rs index c9ab671..e41589d 100644 --- a/crates/keyfork/src/clap_ext.rs +++ b/crates/keyfork/src/clap_ext.rs @@ -43,7 +43,7 @@ impl FromStr for Options { fn from_str(s: &str) -> Result { if s.is_empty() { - return Ok(Default::default()); + return Ok(Self::default()); } let values = s .split(',') diff --git a/crates/keyfork/src/cli/derive.rs b/crates/keyfork/src/cli/derive.rs index e161dc2..5376c73 100644 --- a/crates/keyfork/src/cli/derive.rs +++ b/crates/keyfork/src/cli/derive.rs @@ -26,9 +26,9 @@ pub trait Deriver { fn derivation_path(&self) -> DerivationPath; - fn derive_with_xprv(&self, writer: OptWrite, xprv: XPrv) -> Result<()>; + fn derive_with_xprv(&self, writer: OptWrite, xprv: &XPrv) -> Result<()>; - fn derive_public_with_xprv(&self, writer: OptWrite, xprv: XPrv) -> Result<()>; + fn derive_public_with_xprv(&self, writer: OptWrite, xprv: &XPrv) -> Result<()>; } #[derive(Subcommand, Clone, Debug)] @@ -170,9 +170,9 @@ impl DeriveSubcommands { let xprv = Client::discover_socket()? .request_xprv::<::Prv>(&path.chain_push(account))?; if is_public { - opgp.derive_public_with_xprv(writer, xprv) + opgp.derive_public_with_xprv(writer, &xprv) } else { - opgp.derive_with_xprv(writer, xprv) + opgp.derive_with_xprv(writer, &xprv) } } DeriveSubcommands::Key(key) => { @@ -180,9 +180,9 @@ impl DeriveSubcommands { let xprv = Client::discover_socket()? .request_xprv::<::Prv>(&path.chain_push(account))?; if is_public { - key.derive_public_with_xprv(writer, xprv) + key.derive_public_with_xprv(writer, &xprv) } else { - key.derive_with_xprv(writer, xprv) + key.derive_with_xprv(writer, &xprv) } } } @@ -190,7 +190,7 @@ impl DeriveSubcommands { } impl OpenPGP { - fn cert_from_xprv(&self, xprv: keyfork_derive_openpgp::XPrv) -> Result { + fn cert_from_xprv(&self, xprv: &keyfork_derive_openpgp::XPrv) -> Result { let subkeys = vec![ KeyFlags::empty().set_certification(), KeyFlags::empty().set_signing(), @@ -213,15 +213,12 @@ impl Deriver for OpenPGP { self.derivation_path.derivation_path() } - fn derive_with_xprv(&self, writer: OptWrite, xprv: XPrv) -> Result<()> { + fn derive_with_xprv(&self, writer: OptWrite, xprv: &XPrv) -> Result<()> { let cert = self.cert_from_xprv(xprv)?; - let writer = match writer { - Some(w) => w, - None => { - let path = PathBuf::from(cert.fingerprint().to_string()).with_extension("asc"); - let file = create(&path)?; - Box::new(file) - } + let writer = if let Some(writer) = writer { writer } else { + let path = PathBuf::from(cert.fingerprint().to_string()).with_extension("asc"); + let file = create(&path)?; + Box::new(file) }; let mut writer = Writer::new(writer, Kind::SecretKey)?; for packet in cert.as_tsk().into_packets() { @@ -231,15 +228,12 @@ impl Deriver for OpenPGP { Ok(()) } - fn derive_public_with_xprv(&self, writer: OptWrite, xprv: XPrv) -> Result<()> { + fn derive_public_with_xprv(&self, writer: OptWrite, xprv: &XPrv) -> Result<()> { let cert = self.cert_from_xprv(xprv)?; - let writer = match writer { - Some(w) => w, - None => { - let path = PathBuf::from(cert.fingerprint().to_string()).with_extension("asc"); - let file = create(&path)?; - Box::new(file) - } + let writer = if let Some(writer) = writer { writer } else { + let path = PathBuf::from(cert.fingerprint().to_string()).with_extension("asc"); + let file = create(&path)?; + Box::new(file) }; let mut writer = Writer::new(writer, Kind::PublicKey)?; for packet in cert.into_packets2() { @@ -259,7 +253,7 @@ impl Deriver for Key { DerivationPath::default().chain_push(self.slug.0.clone()) } - fn derive_with_xprv(&self, writer: OptWrite, xprv: XPrv) -> Result<()> { + fn derive_with_xprv(&self, writer: OptWrite, xprv: &XPrv) -> Result<()> { let (formatted, ext) = match self.format { KeyFormat::Hex => (smex::encode(xprv.private_key().to_bytes()), "hex"), KeyFormat::Base64 => { @@ -278,7 +272,7 @@ impl Deriver for Key { Ok(()) } - fn derive_public_with_xprv(&self, writer: OptWrite, xprv: XPrv) -> Result<()> { + fn derive_public_with_xprv(&self, writer: OptWrite, xprv: &XPrv) -> Result<()> { let (formatted, ext) = match self.format { KeyFormat::Hex => (smex::encode(xprv.public_key().to_bytes()), "hex"), KeyFormat::Base64 => { diff --git a/crates/keyfork/src/cli/mnemonic.rs b/crates/keyfork/src/cli/mnemonic.rs index c589ecf..ce4b6e1 100644 --- a/crates/keyfork/src/cli/mnemonic.rs +++ b/crates/keyfork/src/cli/mnemonic.rs @@ -7,7 +7,7 @@ use crate::{clap_ext::*, config, openpgp_card::factory_reset_current_card}; use card_backend_pcsc::PcscBackend; use clap::{builder::PossibleValue, Parser, Subcommand, ValueEnum}; use std::{ - collections::HashMap, + collections::{HashMap, HashSet}, fmt::Display, fs::File, io::{IsTerminal, Write}, @@ -164,7 +164,7 @@ pub enum Error { MissingOption(&'static str), } -fn context_stub<'a>(path: &'a Path) -> impl Fn(std::io::Error) -> Error + 'a { +fn context_stub(path: &Path) -> impl Fn(std::io::Error) -> Error + use<'_> { |e| Error::IOContext(e, path.to_path_buf()) } @@ -227,13 +227,13 @@ pub enum MnemonicSubcommands { /// /// The following additional arguments are available: /// - /// * threshold, m: the minimum amount of shares required to reconstitute the shard. By + /// * `threshold`, m: the minimum amount of shares required to reconstitute the shard. By /// default, this is the amount of certificates provided. /// - /// * max, n: the maximum amount of shares. When provided, this is used to ensure the + /// * `max`, n: the maximum amount of shares. When provided, this is used to ensure the /// certificate count is correct. This is required when using `threshold` or `m`. /// - /// * output: the file to write the generated Shardfile to. By default, assuming the + /// * `output`: the file to write the generated Shardfile to. By default, assuming the /// certificate input is `input.asc`, the generated Shardfile would be written to /// `input.shard.asc`. #[arg(long)] @@ -256,13 +256,13 @@ pub enum MnemonicSubcommands { /// /// The following additional arguments are required: /// - /// * threshold, m: the minimum amount of shares required to reconstitute the shard. + /// * `threshold`, m: the minimum amount of shares required to reconstitute the shard. /// - /// * max, n: the maximum amount of shares. + /// * `max`, n: the maximum amount of shares. /// - /// * cards_per_shard: the amount of OpenPGP smartcards to provision per shardholder. + /// * `cards_per_shard`: the amount of OpenPGP smartcards to provision per shardholder. /// - /// * cert_output: the file to write all generated OpenPGP certificates to; if not + /// * `cert_output`: the file to write all generated OpenPGP certificates to; if not /// provided, files will be automatically generated for each certificate. #[arg(long)] shard_to_self: Option>, @@ -302,24 +302,23 @@ fn determine_valid_output_path>( mid_ext: &str, optional_path: Option, ) -> PathBuf { - match optional_path { - Some(p) => p.as_ref().to_path_buf(), - None => { - let extension = match path.extension() { - Some(ext) => format!("{mid_ext}.{ext}", ext = ext.to_string_lossy()), - None => format!("{mid_ext}.asc"), - }; - path.with_extension(extension) - } + if let Some(p) = optional_path { + p.as_ref().to_path_buf() + } else { + let extension = match path.extension() { + Some(ext) => format!("{mid_ext}.{ext}", ext = ext.to_string_lossy()), + None => format!("{mid_ext}.asc"), + }; + path.with_extension(extension) } } fn is_extension_armored(path: &Path) -> bool { match path.extension().and_then(|s| s.to_str()) { - Some("pgp") | Some("gpg") => false, + Some("pgp" | "gpg") => false, Some("asc") => true, _ => { - eprintln!("unable to determine whether to armor file: {path:?}"); + eprintln!("unable to determine whether to armor file: {path}", path = path.display()); eprintln!("use .gpg, .pgp, or .asc extension, or `armor=true`"); eprintln!("defaulting to armored"); true @@ -394,8 +393,11 @@ fn do_encrypt_to_self( .clone() .chain_push(account); - let cert = - keyfork_derive_openpgp::derive(xprv.derive_path(&derivation_path)?, &subkeys, &userid)?; + let cert = keyfork_derive_openpgp::derive( + &xprv.derive_path(&derivation_path)?, + &subkeys, + &userid, + )?; certs.push(cert); } @@ -458,12 +460,9 @@ fn do_shard( return Err(MissingThresholdOrMax.into()); } - let (threshold, max) = match threshold.zip(max) { - Some(t) => t, - None => { - let len = u8::try_from(certs.len())?; - (len, len) - } + let (threshold, max) = if let Some(t) = threshold.zip(max) { t } else { + let len = u8::try_from(certs.len())?; + (len, len) }; let openpgp = keyfork_shard::openpgp::OpenPGP; @@ -550,7 +549,7 @@ fn derive_key(seed: [u8; 64], index: u8) -> Result { *metadata = Some(config.clone()); } - }; + } provision .provisioner_name - .provision_with_mnemonic(mnemonic, provisioner)?; + .provision_with_mnemonic(mnemonic, &provisioner)?; } Ok(()) @@ -772,11 +771,11 @@ fn do_derive( use keyfork_derive_openpgp::XPrv; let root_xprv = XPrv::new(mnemonic.generate_seed(None))?; let account = DerivationIndex::new(*account_id, true)?; - let derived = root_xprv.derive_path(&opgp.derivation_path().chain_push(account))?; + let derived_key = root_xprv.derive_path(&opgp.derivation_path().chain_push(account))?; if *public { - opgp.derive_public_with_xprv(writer, derived)?; + opgp.derive_public_with_xprv(writer, &derived_key)?; } else { - opgp.derive_with_xprv(writer, derived)?; + opgp.derive_with_xprv(writer, &derived_key)?; } } derive::Derive { @@ -790,11 +789,11 @@ fn do_derive( use keyfork_derive_openpgp::XPrv; let root_xprv = XPrv::new(mnemonic.generate_seed(None))?; let account = DerivationIndex::new(*account_id, true)?; - let derived = root_xprv.derive_path(&key.derivation_path().chain_push(account))?; + let derived_key = root_xprv.derive_path(&key.derivation_path().chain_push(account))?; if *public { - key.derive_public_with_xprv(writer, derived)?; + key.derive_public_with_xprv(writer, &derived_key)?; } else { - key.derive_with_xprv(writer, derived)?; + key.derive_with_xprv(writer, &derived_key)?; } } } @@ -802,6 +801,7 @@ fn do_derive( } impl MnemonicSubcommands { + #[allow(clippy::too_many_lines)] pub fn handle( &self, _m: &Mnemonic, @@ -831,13 +831,13 @@ impl MnemonicSubcommands { // * Sharding to existing, usable keys // * Sharding to newly provisioned keys let mut will_print_mnemonic = - encrypt_to.is_none() || encrypt_to.as_ref().is_some_and(|e| e.is_empty()); + encrypt_to.is_none() || encrypt_to.as_ref().is_some_and(Vec::is_empty); will_print_mnemonic = will_print_mnemonic && (encrypt_to_self.as_ref().is_none() || provision.as_ref().is_none()); will_print_mnemonic = will_print_mnemonic && shard_to.is_none() - || shard_to.as_ref().is_some_and(|s| s.is_empty()); + || shard_to.as_ref().is_some_and(Vec::is_empty); will_print_mnemonic = will_print_mnemonic && shard.is_none() - || shard.as_ref().is_some_and(|s| s.is_empty()); + || shard.as_ref().is_some_and(Vec::is_empty); will_print_mnemonic = will_print_mnemonic && shard_to_self.is_none(); let mnemonic = source.handle(size)?; @@ -859,7 +859,7 @@ impl MnemonicSubcommands { } if let Some(encrypt_to_self) = encrypt_to_self { - let mut accounts: std::collections::HashSet = Default::default(); + let mut accounts: HashSet = HashSet::default(); if let Some(provision::Provision { provisioner_name: provision::Provisioner::OpenPGPCard(_), account_id, @@ -938,7 +938,7 @@ impl MnemonicSubcommands { } if will_print_mnemonic { - println!("{}", mnemonic); + println!("{mnemonic}"); } Ok(()) } diff --git a/crates/keyfork/src/cli/provision/mod.rs b/crates/keyfork/src/cli/provision/mod.rs index 13738a1..222e1bb 100644 --- a/crates/keyfork/src/cli/provision/mod.rs +++ b/crates/keyfork/src/cli/provision/mod.rs @@ -38,7 +38,7 @@ impl Provisioner { pub fn provision( &self, - provisioner: config::Provisioner, + provisioner: &config::Provisioner, ) -> Result<(), Box> { match self { Provisioner::OpenPGPCard(o) => { @@ -49,7 +49,7 @@ impl Provisioner { .chain_push(account_index); let mut client = keyforkd_client::Client::discover_socket()?; let xprv: XPrv = client.request_xprv(&path)?; - o.provision(xprv, provisioner) + o.provision(&xprv, provisioner) } Provisioner::Shard(s) => { type Prv = ::PrivateKey; @@ -59,7 +59,7 @@ impl Provisioner { .chain_push(account_index); let mut client = keyforkd_client::Client::discover_socket()?; let xprv: XPrv = client.request_xprv(&path)?; - s.provision(xprv, provisioner) + s.provision(&xprv, provisioner) } } } @@ -67,7 +67,7 @@ impl Provisioner { pub fn provision_with_mnemonic( &self, mnemonic: &keyfork_mnemonic::Mnemonic, - provisioner: config::Provisioner, + provisioner: &config::Provisioner, ) -> Result<(), Box> { match self { Provisioner::OpenPGPCard(o) => { @@ -77,7 +77,7 @@ impl Provisioner { let path = ::derivation_prefix() .chain_push(account_index); let xprv = XPrv::new(mnemonic.generate_seed(None))?.derive_path(&path)?; - o.provision(xprv, provisioner) + o.provision(&xprv, provisioner) } Provisioner::Shard(s) => { type Prv = ::PrivateKey; @@ -86,7 +86,7 @@ impl Provisioner { let path = ::derivation_prefix() .chain_push(account_index); let xprv = XPrv::new(mnemonic.generate_seed(None))?.derive_path(&path)?; - s.provision(xprv, provisioner) + s.provision(&xprv, provisioner) } } } @@ -132,8 +132,8 @@ trait ProvisionExec { /// Derive a key and deploy it to a target. fn provision( &self, - xprv: keyfork_derive_util::ExtendedPrivateKey, - p: config::Provisioner, + xprv: &keyfork_derive_util::ExtendedPrivateKey, + p: &config::Provisioner, ) -> Result<(), Box>; } @@ -189,7 +189,7 @@ impl TryFrom for config::Provisioner { Ok(Self { account: value.account_id, identifier: value.identifier.ok_or(MissingField("identifier"))?, - metadata: Default::default(), + metadata: Option::default(), }) } } @@ -210,21 +210,20 @@ impl Provision { } } None => { - let provisioner_with_identifier = match self.identifier { - Some(_) => self.clone(), - None => { - let identifiers = self.provisioner_name.discover()?; - let [id] = &identifiers[..] else { - panic!("invalid amount of identifiers; pass --identifier"); - }; - Self { - identifier: Some(id.0.clone()), - ..self.clone() - } + let provisioner_with_identifier = if self.identifier.is_some() { + self.clone() + } else { + let identifiers = self.provisioner_name.discover()?; + let [id] = &identifiers[..] else { + panic!("invalid amount of identifiers; pass --identifier"); + }; + Self { + identifier: Some(id.0.clone()), + ..self.clone() } }; let config = config::Provisioner::try_from(provisioner_with_identifier)?; - self.provisioner_name.provision(config)?; + self.provisioner_name.provision(&config)?; } } Ok(()) diff --git a/crates/keyfork/src/cli/provision/openpgp.rs b/crates/keyfork/src/cli/provision/openpgp.rs index d45dbbd..ec51fd2 100644 --- a/crates/keyfork/src/cli/provision/openpgp.rs +++ b/crates/keyfork/src/cli/provision/openpgp.rs @@ -39,8 +39,8 @@ fn discover_cards() -> Result> { } fn provision_card( - provisioner: config::Provisioner, - xprv: XPrv, + provisioner: &config::Provisioner, + xprv: &XPrv, ) -> Result<(), Box> { let mut pm = default_handler()?; @@ -59,23 +59,24 @@ fn provision_card( Some(userid) => UserID::from(userid.as_str()), None => UserID::from("Keyfork-Provisioned Key"), }; - let cert = keyfork_derive_openpgp::derive(xprv.clone(), &subkeys, &userid)?; + let cert = keyfork_derive_openpgp::derive(xprv, &subkeys, &userid)?; if !provisioner .metadata .as_ref() .is_some_and(|m| m.contains_key("_skip_cert_output")) { - let cert_output = match provisioner.metadata.as_ref().and_then(|m| m.get("output")) { - Some(cert_output) => PathBuf::from(cert_output), - None => { - let path = PathBuf::from(cert.fingerprint().to_string()).with_extension("asc"); - eprintln!( - "Writing OpenPGP certificate to: {path}", - path = path.display() - ); - path - } + let cert_output = if let Some(cert_output) = + provisioner.metadata.as_ref().and_then(|m| m.get("output")) + { + PathBuf::from(cert_output) + } else { + let path = PathBuf::from(cert.fingerprint().to_string()).with_extension("asc"); + eprintln!( + "Writing OpenPGP certificate to: {path}", + path = path.display() + ); + path }; let cert_output_file = std::fs::File::create(cert_output)?; @@ -124,8 +125,8 @@ impl ProvisionExec for OpenPGPCard { fn provision( &self, - xprv: XPrv, - provisioner: config::Provisioner, + xprv: &XPrv, + provisioner: &config::Provisioner, ) -> Result<(), Box> { provision_card(provisioner, xprv) } @@ -147,8 +148,8 @@ impl ProvisionExec for Shard { fn provision( &self, - xprv: XPrv, - provisioner: config::Provisioner, + xprv: &XPrv, + provisioner: &config::Provisioner, ) -> Result<(), Box> { provision_card(provisioner, xprv) } diff --git a/crates/keyfork/src/openpgp_card.rs b/crates/keyfork/src/openpgp_card.rs index 2811985..7d8b718 100644 --- a/crates/keyfork/src/openpgp_card.rs +++ b/crates/keyfork/src/openpgp_card.rs @@ -34,11 +34,10 @@ pub fn get_new_pins( 3, &user_pin_validator, )?; - if user_pin != validated_user_pin { - pm.prompt_message(Message::Text("User PINs did not match. Retrying.".into()))?; - } else { + if user_pin == validated_user_pin { break user_pin; } + pm.prompt_message(Message::Text("User PINs did not match. Retrying.".into()))?; }; let admin_pin = loop { @@ -54,11 +53,10 @@ pub fn get_new_pins( 3, &admin_pin_validator, )?; - if admin_pin != validated_admin_pin { - pm.prompt_message(Message::Text("Admin PINs did not match. Retrying.".into()))?; - } else { + if admin_pin == validated_admin_pin { break admin_pin; } + pm.prompt_message(Message::Text("Admin PINs did not match. Retrying.".into()))?; }; Ok((user_pin, admin_pin)) diff --git a/crates/qrcode/keyfork-qrcode/Cargo.toml b/crates/qrcode/keyfork-qrcode/Cargo.toml index d4b96f4..2ed3ed6 100644 --- a/crates/qrcode/keyfork-qrcode/Cargo.toml +++ b/crates/qrcode/keyfork-qrcode/Cargo.toml @@ -5,6 +5,9 @@ repository = "https://git.distrust.co/public/keyfork" edition = "2021" license = "MIT" +[lints] +workspace = true + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [features] diff --git a/crates/qrcode/keyfork-qrcode/src/lib.rs b/crates/qrcode/keyfork-qrcode/src/lib.rs index c70e62e..71c9cba 100644 --- a/crates/qrcode/keyfork-qrcode/src/lib.rs +++ b/crates/qrcode/keyfork-qrcode/src/lib.rs @@ -1,7 +1,5 @@ //! Encoding and decoding QR codes. -#![allow(clippy::expect_fun_call)] - use keyfork_bug as bug; use bug::POISONED_MUTEX; @@ -39,10 +37,10 @@ pub enum QRCodeScanError { /// The camera could not load the requested format. #[error("Camera could not use {expected} format, instead used {actual}")] CameraGaveBadFormat { - /// The expected format, in FourCC format. + /// The expected format, in `FourCC` format. expected: String, - /// The actual format, in FourCC format. + /// The actual format, in `FourCC` format. actual: String, }, @@ -165,7 +163,7 @@ mod rqrr { } } -#[allow(dead_code)] +#[allow(dead_code, clippy::cast_precision_loss)] fn dbg_elapsed(count: u64, instant: Instant) { let elapsed = instant.elapsed().as_secs(); let framerate = count as f64 / elapsed as f64; diff --git a/crates/qrcode/keyfork-zbar-sys/Cargo.toml b/crates/qrcode/keyfork-zbar-sys/Cargo.toml index b57d98e..4a00e1e 100644 --- a/crates/qrcode/keyfork-zbar-sys/Cargo.toml +++ b/crates/qrcode/keyfork-zbar-sys/Cargo.toml @@ -5,6 +5,9 @@ repository = "https://git.distrust.co/public/keyfork" edition = "2021" license = "MIT" +[lints] +workspace = true + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] diff --git a/crates/qrcode/keyfork-zbar-sys/src/lib.rs b/crates/qrcode/keyfork-zbar-sys/src/lib.rs index 8314f30..93e9228 100644 --- a/crates/qrcode/keyfork-zbar-sys/src/lib.rs +++ b/crates/qrcode/keyfork-zbar-sys/src/lib.rs @@ -1,4 +1,5 @@ #![allow(non_upper_case_globals, non_camel_case_types, non_snake_case)] #![allow(missing_docs)] +#![allow(clippy::unreadable_literal, clippy::pub_underscore_fields)] include!(concat!(env!("OUT_DIR"), "/bindings.rs")); diff --git a/crates/qrcode/keyfork-zbar/Cargo.toml b/crates/qrcode/keyfork-zbar/Cargo.toml index d1cd920..214d77f 100644 --- a/crates/qrcode/keyfork-zbar/Cargo.toml +++ b/crates/qrcode/keyfork-zbar/Cargo.toml @@ -5,6 +5,9 @@ repository = "https://git.distrust.co/public/keyfork" edition = "2021" license = "MIT" +[lints] +workspace = true + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [features] diff --git a/crates/qrcode/keyfork-zbar/src/image.rs b/crates/qrcode/keyfork-zbar/src/image.rs index 2a2b6bc..936051a 100644 --- a/crates/qrcode/keyfork-zbar/src/image.rs +++ b/crates/qrcode/keyfork-zbar/src/image.rs @@ -20,16 +20,13 @@ impl Image { /// Link: [`sys::zbar_image_set_format`] /// - /// A FourCC code can be given in the format: + /// A `FourCC` code can be given in the format: /// /// ```rust,ignore /// self.set_format(b"Y800") /// ``` pub(crate) fn set_format(&mut self, fourcc: &[u8; 4]) { - let fourcc: u64 = fourcc[0] as u64 - | ((fourcc[1] as u64) << 8) - | ((fourcc[2] as u64) << 16) - | ((fourcc[3] as u64) << 24); + let fourcc = std::os::raw::c_ulong::from(u32::from_le_bytes(*fourcc)); unsafe { sys::zbar_image_set_format(self.inner, fourcc) } } @@ -43,7 +40,7 @@ impl Image { /// Accepts raw data in the configured format. See: [`Image::set_format`] fn set_data(&mut self, data: Vec) { unsafe { - sys::zbar_image_set_data(self.inner, data.as_ptr().cast(), data.len() as u64, None) + sys::zbar_image_set_data(self.inner, data.as_ptr().cast(), data.len() as u64, None); } // keep data in self to avoid use after free when data goes out of scope let _ = self.inner_data.insert(data); diff --git a/crates/qrcode/keyfork-zbar/src/image_scanner.rs b/crates/qrcode/keyfork-zbar/src/image_scanner.rs index 1c4663a..cdb8c87 100644 --- a/crates/qrcode/keyfork-zbar/src/image_scanner.rs +++ b/crates/qrcode/keyfork-zbar/src/image_scanner.rs @@ -22,7 +22,7 @@ pub struct ImageScanner { } impl ImageScanner { - /// create a new ImageScanner. + /// Create a new `ImageScanner`. /// /// Link: [`sys::zbar_image_scanner_create`] pub fn new() -> Self { @@ -31,7 +31,7 @@ impl ImageScanner { } } - /// Set a configuration option for the ImageScanner. + /// Set a configuration option. /// /// Link: [`sys::zbar_image_scanner_set_config`] /// @@ -67,7 +67,7 @@ impl ImageScanner { let symbol_data = unsafe { sys::zbar_symbol_get_data(symbol) }; let symbol_data_len = unsafe { sys::zbar_symbol_get_data_length(symbol) }; let symbol_slice = unsafe { - std::slice::from_raw_parts(symbol_data as *const u8, symbol_data_len as usize) + std::slice::from_raw_parts(symbol_data.cast::(), symbol_data_len as usize) }; result.push(Symbol::new(symbol_type, symbol_slice)); symbol = unsafe { sys::zbar_symbol_next(symbol) }; diff --git a/crates/qrcode/keyfork-zbar/src/symbol.rs b/crates/qrcode/keyfork-zbar/src/symbol.rs index 92cea20..7bd8d19 100644 --- a/crates/qrcode/keyfork-zbar/src/symbol.rs +++ b/crates/qrcode/keyfork-zbar/src/symbol.rs @@ -1,5 +1,7 @@ //! A Symbol represents some form of encoded data. +#![allow(clippy::used_underscore_binding)] + use super::sys; /// The type of symbol (i.e. what type of barcode or QR code). diff --git a/crates/tests/Cargo.toml b/crates/tests/Cargo.toml index 92d9fc6..ba863a7 100644 --- a/crates/tests/Cargo.toml +++ b/crates/tests/Cargo.toml @@ -5,6 +5,9 @@ edition = "2021" publish = false license = "MIT" +[lints] +workspace = true + [dependencies] assert_cmd = "2.0.16" keyforkd = { workspace = true, features = ["default"] } diff --git a/crates/tests/src/keyfork/derive/openpgp.rs b/crates/tests/src/keyfork/derive/openpgp.rs index a677b9a..eeca3c6 100644 --- a/crates/tests/src/keyfork/derive/openpgp.rs +++ b/crates/tests/src/keyfork/derive/openpgp.rs @@ -52,7 +52,5 @@ fn test() { key.alive().expect("is live after being generated"); key.parts_into_secret().expect("has secret keys"); } - if !key_formats.is_empty() { - panic!("remaining key formats: {key_formats:?}"); - } + assert!(key_formats.is_empty(), "remaining key formats: {key_formats:?}"); } diff --git a/crates/util/keyfork-bin/Cargo.toml b/crates/util/keyfork-bin/Cargo.toml index 22b332e..c2f8c1f 100644 --- a/crates/util/keyfork-bin/Cargo.toml +++ b/crates/util/keyfork-bin/Cargo.toml @@ -4,6 +4,9 @@ version = "0.1.0" edition = "2021" license = "MIT" +[lints] +workspace = true + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] diff --git a/crates/util/keyfork-bin/src/lib.rs b/crates/util/keyfork-bin/src/lib.rs index 765eded..03b3fe4 100644 --- a/crates/util/keyfork-bin/src/lib.rs +++ b/crates/util/keyfork-bin/src/lib.rs @@ -45,6 +45,7 @@ use std::process::ExitCode; /// A result that may contain any error. pub type ProcessResult = Result>; +#[allow(clippy::needless_pass_by_value)] fn report_err(e: Box) { eprintln!("Unable to run command: {e}"); let mut source = e.source(); diff --git a/crates/util/keyfork-bug/Cargo.toml b/crates/util/keyfork-bug/Cargo.toml index 4946ade..46a894f 100644 --- a/crates/util/keyfork-bug/Cargo.toml +++ b/crates/util/keyfork-bug/Cargo.toml @@ -4,6 +4,9 @@ version = "0.1.1" edition = "2021" license = "MIT" +[lints] +workspace = true + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] diff --git a/crates/util/keyfork-crossterm/Cargo.toml b/crates/util/keyfork-crossterm/Cargo.toml index 451f0bc..6dd170e 100644 --- a/crates/util/keyfork-crossterm/Cargo.toml +++ b/crates/util/keyfork-crossterm/Cargo.toml @@ -14,6 +14,9 @@ edition = "2021" rust-version = "1.58.0" # categories = ["command-line-interface", "command-line-utilities"] +[lints] +workspace = true + # [lib] # name = "crossterm" # path = "src/lib.rs" diff --git a/crates/util/keyfork-crossterm/examples/interactive-demo/Cargo.toml b/crates/util/keyfork-crossterm/examples/interactive-demo/Cargo.toml index f7a5134..ddb511a 100644 --- a/crates/util/keyfork-crossterm/examples/interactive-demo/Cargo.toml +++ b/crates/util/keyfork-crossterm/examples/interactive-demo/Cargo.toml @@ -10,4 +10,4 @@ readme = "README.md" publish = false [dependencies] -crossterm = { path = "../../" } \ No newline at end of file +crossterm = { path = "../../" } diff --git a/crates/util/keyfork-crossterm/src/event/filter.rs b/crates/util/keyfork-crossterm/src/event/filter.rs index f78730d..2a594ae 100644 --- a/crates/util/keyfork-crossterm/src/event/filter.rs +++ b/crates/util/keyfork-crossterm/src/event/filter.rs @@ -61,6 +61,7 @@ impl Filter for EventFilter { } } +#[allow(dead_code)] #[derive(Debug, Clone)] pub(crate) struct InternalEventFilter; diff --git a/crates/util/keyfork-crossterm/src/lib.rs b/crates/util/keyfork-crossterm/src/lib.rs index 8af994d..4bcafcf 100644 --- a/crates/util/keyfork-crossterm/src/lib.rs +++ b/crates/util/keyfork-crossterm/src/lib.rs @@ -1,5 +1,6 @@ #![allow(missing_docs, clippy::missing_errors_doc, clippy::missing_panics_doc)] #![deny(unused_imports, unused_must_use)] +#![allow(clippy::pedantic, clippy::all, unexpected_cfgs)] //! # Cross-platform Terminal Manipulation Library //! diff --git a/crates/util/keyfork-crossterm/src/style/attributes.rs b/crates/util/keyfork-crossterm/src/style/attributes.rs index aa481c3..83dea3e 100644 --- a/crates/util/keyfork-crossterm/src/style/attributes.rs +++ b/crates/util/keyfork-crossterm/src/style/attributes.rs @@ -140,8 +140,11 @@ mod tests { #[test] fn test_attributes_const() { - const ATTRIBUTES: Attributes = Attributes::none().with(Attribute::Bold).with(Attribute::Italic).without(Attribute::Bold); - assert!(!ATTRIBUTES.has(Attribute::Bold)); - assert!(ATTRIBUTES.has(Attribute::Italic)); + const ATTRIBUTES: Attributes = Attributes::none() + .with(Attribute::Bold) + .with(Attribute::Italic) + .without(Attribute::Bold); + assert!(!ATTRIBUTES.has(Attribute::Bold)); + assert!(ATTRIBUTES.has(Attribute::Italic)); } } diff --git a/crates/util/keyfork-crossterm/src/terminal.rs b/crates/util/keyfork-crossterm/src/terminal.rs index 24872c4..bfd87fe 100644 --- a/crates/util/keyfork-crossterm/src/terminal.rs +++ b/crates/util/keyfork-crossterm/src/terminal.rs @@ -108,7 +108,10 @@ pub struct FdTerminal { stored_termios: Option, } -impl From for FdTerminal where T: os::fd::AsRawFd { +impl From for FdTerminal +where + T: os::fd::AsRawFd, +{ fn from(value: T) -> Self { Self { fd: value.as_raw_fd(), diff --git a/crates/util/keyfork-entropy/Cargo.toml b/crates/util/keyfork-entropy/Cargo.toml index 8960ffa..3b19c1e 100644 --- a/crates/util/keyfork-entropy/Cargo.toml +++ b/crates/util/keyfork-entropy/Cargo.toml @@ -4,6 +4,9 @@ version = "0.1.2" edition = "2021" license = "MIT" +[lints] +workspace = true + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [features] diff --git a/crates/util/keyfork-frame/Cargo.toml b/crates/util/keyfork-frame/Cargo.toml index 6623488..561bb87 100644 --- a/crates/util/keyfork-frame/Cargo.toml +++ b/crates/util/keyfork-frame/Cargo.toml @@ -4,6 +4,9 @@ version = "0.1.0" edition = "2021" license = "MIT" +[lints] +workspace = true + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [features] diff --git a/crates/util/keyfork-mnemonic/Cargo.toml b/crates/util/keyfork-mnemonic/Cargo.toml index 4a939c2..5466a9f 100644 --- a/crates/util/keyfork-mnemonic/Cargo.toml +++ b/crates/util/keyfork-mnemonic/Cargo.toml @@ -6,6 +6,9 @@ repository = "https://git.distrust.co/public/keyfork" edition = "2021" license = "MIT" +[lints] +workspace = true + [features] default = ["bin"] bin = ["smex"] diff --git a/crates/util/keyfork-mnemonic/src/lib.rs b/crates/util/keyfork-mnemonic/src/lib.rs index 077688c..8e9e65e 100644 --- a/crates/util/keyfork-mnemonic/src/lib.rs +++ b/crates/util/keyfork-mnemonic/src/lib.rs @@ -382,12 +382,12 @@ where /// A clone of the internal representation of the decoded data. pub fn to_bytes(&self) -> Vec { - self.data.to_vec() + self.data.clone() } /// A clone of the internal representation of the decoded data. pub fn to_vec(&self) -> Vec { - self.data.to_vec() + self.data.clone() } /// Conver the Mnemonic into the internal representation of the decoded data. @@ -421,8 +421,8 @@ where /// Create a BIP-0032 seed from the provided data and an optional passphrase. /// /// # Panics - /// The function may panic if the HmacSha512 function returns an error. The only error the - /// HmacSha512 function should return is an invalid length, which should not be possible. + /// The function may panic if the `HmacSha512` function returns an error. The only error the + /// `HmacSha512` function should return is an invalid length, which should not be possible. pub fn generate_seed<'a>(&self, passphrase: impl Into>) -> [u8; 64] { let passphrase = passphrase.into(); @@ -605,7 +605,7 @@ mod tests { } #[test] - #[should_panic] + #[should_panic(expected = "bytes.len() <= 1024")] fn fails_over_8192_bits() { let entropy = &mut [0u8; 1024 + 4]; let mut random = std::fs::File::open("/dev/urandom").unwrap(); @@ -614,7 +614,7 @@ mod tests { } #[test] - #[should_panic] + #[should_panic(expected = "bytes.len() % 4 == 0")] fn fails_over_invalid_size() { let entropy = &mut [0u8; 255]; let mut random = std::fs::File::open("/dev/urandom").unwrap(); diff --git a/crates/util/keyfork-prompt/Cargo.toml b/crates/util/keyfork-prompt/Cargo.toml index 6a92975..9973a65 100644 --- a/crates/util/keyfork-prompt/Cargo.toml +++ b/crates/util/keyfork-prompt/Cargo.toml @@ -6,6 +6,9 @@ repository = "https://git.distrust.co/public/keyfork" edition = "2021" license = "MIT" +[lints] +workspace = true + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [features] diff --git a/crates/util/keyfork-prompt/src/headless.rs b/crates/util/keyfork-prompt/src/headless.rs index c3287d2..5d9dee3 100644 --- a/crates/util/keyfork-prompt/src/headless.rs +++ b/crates/util/keyfork-prompt/src/headless.rs @@ -60,11 +60,7 @@ impl PromptHandler for Headless { fn prompt_message(&mut self, prompt: Message) -> Result<()> { match prompt { - Message::Text(s) => { - writeln!(&mut self.stderr, "{s}")?; - self.stderr.flush()?; - } - Message::Data(s) => { + Message::Text(s) | Message::Data(s) => { writeln!(&mut self.stderr, "{s}")?; self.stderr.flush()?; } diff --git a/crates/util/keyfork-prompt/src/terminal.rs b/crates/util/keyfork-prompt/src/terminal.rs index 648f383..85531eb 100644 --- a/crates/util/keyfork-prompt/src/terminal.rs +++ b/crates/util/keyfork-prompt/src/terminal.rs @@ -106,7 +106,7 @@ where } fn consume(&mut self, amt: usize) { - self.read.consume(amt) + self.read.consume(amt); } } @@ -155,6 +155,7 @@ where } /// A handler for a terminal. +#[allow(clippy::struct_field_names)] pub struct Terminal { read: BufReader, write: W, @@ -259,8 +260,11 @@ where let printable_space = (cols as usize) - prefix_length; input.len() - (printable_space - 1) }; + terminal - .queue(cursor::MoveToColumn(prefix_length as u16))? + .queue(cursor::MoveToColumn( + u16::try_from(prefix_length).unwrap_or(u16::MAX), + ))? .queue(terminal::Clear(terminal::ClearType::UntilNewLine))? .queue(Print(&input[printable_start..]))? .flush()?; @@ -388,9 +392,7 @@ where } Err(Error::Validation( retries, - last_error - .map(|e| e.to_string()) - .unwrap_or_else(|| "Unknown".to_string()), + last_error.map_or_else(|| "Unknown".to_string(), |e| e.to_string()), )) } @@ -480,10 +482,9 @@ where let usable_space = cols as usize - prefix_length - 1; - #[allow(clippy::cast_possible_truncation)] terminal .queue(cursor::MoveToColumn( - std::cmp::min(u16::MAX as usize, prefix_length) as u16, + u16::try_from(prefix_length).unwrap_or(u16::MAX), ))? .queue(terminal::Clear(terminal::ClearType::UntilNewLine))? .flush()?; @@ -551,9 +552,7 @@ where } Err(Error::Validation( retries, - last_error - .map(|e| e.to_string()) - .unwrap_or_else(|| "Unknown".to_string()), + last_error.map_or_else(|| "Unknown".to_string(), |e| e.to_string()), )) } @@ -632,8 +631,7 @@ where for line in text.lines() { let mut written_chars = 0; for word in line.split_whitespace() { - #[allow(clippy::cast_possible_truncation)] - let len = std::cmp::min(u16::MAX as usize, word.len()) as u16; + let len = u16::try_from(word.len()).unwrap_or(u16::MAX); written_chars += len + 1; if written_chars > cols { terminal.queue(cursor::MoveToNextLine(1))?; diff --git a/crates/util/keyfork-prompt/src/validators.rs b/crates/util/keyfork-prompt/src/validators.rs index 589ab47..1a24767 100644 --- a/crates/util/keyfork-prompt/src/validators.rs +++ b/crates/util/keyfork-prompt/src/validators.rs @@ -1,6 +1,7 @@ //! Validator and parser types. #![allow(clippy::type_complexity)] + use std::ops::RangeInclusive; /// A trait to create validator functions. @@ -93,7 +94,7 @@ impl Validator for SecurePinValidator { last_char = ch as i32; } let mut chars = s.chars().collect::>(); - chars.sort(); + chars.sort_unstable(); chars.dedup(); if !ignore_repeated_characters { // SAFETY: the amount of characters can't have _increased_ since deduping @@ -202,19 +203,16 @@ pub mod mnemonic { fn to_fn(&self) -> Box Result>> { let word_length = self.word_length.clone(); - Box::new(move |s: String| match word_length.as_ref() { - Some(wl) => { - let count = s.split_whitespace().count(); - if !wl.matches(count) { - return Err(Box::new(Self::Error::InvalidLength(count, wl.clone()))); - } - let m = Mnemonic::from_str(&s)?; - Ok(m) - } - None => { - let m = Mnemonic::from_str(&s)?; - Ok(m) + Box::new(move |s: String| if let Some(wl) = word_length.as_ref() { + let count = s.split_whitespace().count(); + if !wl.matches(count) { + return Err(Box::new(Self::Error::InvalidLength(count, wl.clone()))); } + let m = Mnemonic::from_str(&s)?; + Ok(m) + } else { + let m = Mnemonic::from_str(&s)?; + Ok(m) }) } } diff --git a/crates/util/keyfork-slip10-test-data/Cargo.toml b/crates/util/keyfork-slip10-test-data/Cargo.toml index 20c0116..75e94fe 100644 --- a/crates/util/keyfork-slip10-test-data/Cargo.toml +++ b/crates/util/keyfork-slip10-test-data/Cargo.toml @@ -4,5 +4,8 @@ version = "0.1.0" edition = "2021" license = "MIT" +[lints] +workspace = true + [dependencies] smex = { workspace = true } diff --git a/crates/util/smex/Cargo.toml b/crates/util/smex/Cargo.toml index 8ff4ce1..dd12b47 100644 --- a/crates/util/smex/Cargo.toml +++ b/crates/util/smex/Cargo.toml @@ -4,6 +4,9 @@ version = "0.1.0" edition = "2021" license = "MIT" +[lints] +workspace = true + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies]