diff --git a/.github/workflows/formatting/rust/action.yml b/.github/workflows/formatting/rust/action.yml index 15ee3319..92d076d8 100644 --- a/.github/workflows/formatting/rust/action.yml +++ b/.github/workflows/formatting/rust/action.yml @@ -11,6 +11,7 @@ runs: shell: bash run: | rustup update + rustup target add wasm32-unknown-unknown - name: Check Format working-directory: ./ @@ -21,3 +22,15 @@ runs: working-directory: ./ shell: bash run: cargo clippy --workspace --all-targets -- -D warnings + + - name: Check Clippy (fuzz feature) + working-directory: ./ + shell: bash + run: cargo clippy --all-targets --features fuzz -- -D warnings + + # The wbindgen deps live under [target.wasm32-unknown-unknown.dependencies], + # so this feature only resolves against the wasm target. + - name: Check Clippy (wasm bindings) + working-directory: ./ + shell: bash + run: cargo clippy --target wasm32-unknown-unknown --features wbindgen --all-targets -- -D warnings diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index 6aeaa0f2..093254b6 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -20,163 +20,286 @@ features = ["fuzz"] [[bin]] name = "ciphertext_deserialization" path = "fuzz_targets/ciphertext/ciphertext_deserialization.rs" +test = false +doc = false +bench = false [[bin]] name = "encrypt" path = "fuzz_targets/ciphertext/encrypt.rs" +test = false +doc = false +bench = false [[bin]] name = "encrypt_asymmetric" path = "fuzz_targets/ciphertext/encrypt_asymmetric.rs" +test = false +doc = false +bench = false [[bin]] name = "decrypt" path = "fuzz_targets/ciphertext/decrypt.rs" +test = false +doc = false +bench = false [[bin]] name = "decrypt_asymmetric" path = "fuzz_targets/ciphertext/decrypt_asymmetric.rs" +test = false +doc = false +bench = false [[bin]] name = "password_hash_deserialization" path = "fuzz_targets/password_hash/password_hash_deserialization.rs" +test = false +doc = false +bench = false [[bin]] name = "public_key_deserialization" path = "fuzz_targets/key/public_key_deserialization.rs" +test = false +doc = false +bench = false [[bin]] name = "private_key_deserialization" path = "fuzz_targets/key/private_key_deserialization.rs" +test = false +doc = false +bench = false [[bin]] name = "argon2parameters_deserialization" path = "fuzz_targets/key/argon2parameters_deserialization.rs" +test = false +doc = false +bench = false [[bin]] name = "mix_key_exchange" path = "fuzz_targets/key/mix_key_exchange.rs" +test = false +doc = false +bench = false [[bin]] name = "share_deserialization" path = "fuzz_targets/secret_sharing/share_deserialization.rs" +test = false +doc = false +bench = false [[bin]] name = "generate_shared_key" path = "fuzz_targets/secret_sharing/generate_shared_key.rs" +test = false +doc = false +bench = false [[bin]] name = "join_shares" path = "fuzz_targets/secret_sharing/join_shares.rs" +test = false +doc = false +bench = false [[bin]] name = "generate_key" path = "fuzz_targets/utils/generate_key.rs" +test = false +doc = false +bench = false [[bin]] name = "derive_key" path = "fuzz_targets/utils/derive_key.rs" +test = false +doc = false +bench = false [[bin]] name = "validate_header" path = "fuzz_targets/utils/validate_header.rs" +test = false +doc = false +bench = false [[bin]] name = "base64_encode" path = "fuzz_targets/utils/base64_encode.rs" +test = false +doc = false +bench = false [[bin]] name = "base64_encode_url" path = "fuzz_targets/utils/base64_encode_url.rs" +test = false +doc = false +bench = false [[bin]] name = "base64_decode" path = "fuzz_targets/utils/base64_decode.rs" +test = false +doc = false +bench = false [[bin]] name = "base64_decode_url" path = "fuzz_targets/utils/base64_decode_url.rs" +test = false +doc = false +bench = false [[bin]] name = "derive_key_argon2" path = "fuzz_targets/utils/derive_key_argon2.rs" +test = false +doc = false +bench = false [[bin]] name = "scrypt_simple" path = "fuzz_targets/utils/scrypt_simple.rs" +test = false +doc = false +bench = false [[bin]] name = "signature_deserialization" path = "fuzz_targets/signature/signature_deserialization.rs" +test = false +doc = false +bench = false [[bin]] name = "sign" path = "fuzz_targets/signature/sign.rs" +test = false +doc = false +bench = false [[bin]] name = "verify" path = "fuzz_targets/signature/verify.rs" +test = false +doc = false +bench = false [[bin]] name = "signing_keypair_deserialization" path = "fuzz_targets/signing_key/signing_keypair_deserialization.rs" +test = false +doc = false +bench = false [[bin]] name = "signing_public_key_deserialization" path = "fuzz_targets/signing_key/signing_public_key_deserialization.rs" +test = false +doc = false +bench = false [[bin]] name = "online_ciphertext_header_deserialization" path = "fuzz_targets/online_ciphertext/header_deserialization.rs" +test = false +doc = false +bench = false [[bin]] name = "online_encrypt_symmetric" path = "fuzz_targets/online_ciphertext/encrypt_symmetric.rs" +test = false +doc = false +bench = false [[bin]] name = "online_encrypt_asymmetric" path = "fuzz_targets/online_ciphertext/encrypt_asymmetric.rs" +test = false +doc = false +bench = false [[bin]] name = "online_decrypt_symmetric" path = "fuzz_targets/online_ciphertext/decrypt_symmetric.rs" +test = false +doc = false +bench = false [[bin]] name = "online_decrypt_asymmetric" path = "fuzz_targets/online_ciphertext/decrypt_asymmetric.rs" +test = false +doc = false +bench = false [[bin]] name = "encrypt_with_aad" path = "fuzz_targets/ciphertext/encrypt_with_aad.rs" +test = false +doc = false +bench = false [[bin]] name = "decrypt_with_aad" path = "fuzz_targets/ciphertext/decrypt_with_aad.rs" +test = false +doc = false +bench = false [[bin]] name = "encrypt_asymmetric_with_aad" path = "fuzz_targets/ciphertext/encrypt_asymmetric_with_aad.rs" +test = false +doc = false +bench = false [[bin]] name = "decrypt_asymmetric_with_aad" path = "fuzz_targets/ciphertext/decrypt_asymmetric_with_aad.rs" +test = false +doc = false +bench = false [[bin]] name = "generate_keypair" path = "fuzz_targets/key/generate_keypair.rs" +test = false +doc = false +bench = false [[bin]] name = "constant_time_equals" path = "fuzz_targets/utils/constant_time_equals.rs" +test = false +doc = false +bench = false [[bin]] name = "kdf_encrypted_data_deserialization" path = "fuzz_targets/derive_encrypt/kdf_encrypted_data_deserialization.rs" +test = false +doc = false +bench = false [[bin]] name = "derivation_parameters_deserialization" path = "fuzz_targets/key_derivation/derivation_parameters_deserialization.rs" +test = false +doc = false +bench = false [[bin]] name = "decrypt_with_password" path = "fuzz_targets/derive_encrypt/decrypt_with_password.rs" +test = false +doc = false +bench = false diff --git a/src/error.rs b/src/error.rs index 08b607f1..9b049669 100644 --- a/src/error.rs +++ b/src/error.rs @@ -10,17 +10,6 @@ use hmac::digest::MacError; pub type Result = std::result::Result; -// Doesn't work because Result is a type alias, keeping the commented code just in case we revisit someday -// impl From> for Result -// where E: Into { -// fn from(value: std::result::Result) -> Self { -// match value { -// Ok(t) => Ok(t), -// Err(e) => Err(e.into()), -// } -// } -// } - /// This crate's error type. #[derive(Debug, IntoStaticStr, thiserror::Error)] pub enum Error { diff --git a/src/password_hash/password_hash_v1.rs b/src/password_hash/password_hash_v1.rs index bf9c9830..5086d8c3 100644 --- a/src/password_hash/password_hash_v1.rs +++ b/src/password_hash/password_hash_v1.rs @@ -85,7 +85,8 @@ impl PasswordHashV1 { // Generate hash let mut hash = [0u8; 32]; - let _ = pbkdf2::>(pass, &salt, iterations, &mut hash); + pbkdf2::>(pass, &salt, iterations, &mut hash) + .expect("HMAC-SHA256 accepts keys of any length, so this cannot fail"); Ok(PasswordHashV1 { iterations, @@ -96,7 +97,8 @@ impl PasswordHashV1 { pub fn verify_password(&self, pass: &[u8]) -> bool { let mut res = Zeroizing::new(vec![0u8; 32]); - let _ = pbkdf2::>(pass, &self.salt, self.iterations, &mut res); + pbkdf2::>(pass, &self.salt, self.iterations, &mut res) + .expect("HMAC-SHA256 accepts keys of any length, so this cannot fail"); res.ct_eq(&self.hash).into() } diff --git a/src/utils.rs b/src/utils.rs index df294086..170da938 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -73,7 +73,8 @@ pub(crate) fn random_bytes() -> Result> { /// ``` pub fn derive_key_pbkdf2(key: &[u8], salt: &[u8], iterations: u32, length: usize) -> Vec { let mut new_key = vec![0u8; length]; - let _ = pbkdf2::>(key, salt, iterations, &mut new_key); + pbkdf2::>(key, salt, iterations, &mut new_key) + .expect("HMAC-SHA256 accepts keys of any length, so this cannot fail"); new_key } @@ -103,16 +104,20 @@ pub fn derive_key_argon2(key: &[u8], parameters: &Argon2Parameters) -> Result` = encrypt(b"test", &key, CiphertextVersion::Latest).unwrap().into(); +/// let key = generate_key(32).expect("generate key shouldn't fail"); +/// let ciphertext: Vec = encrypt(b"test", &key, CiphertextVersion::Latest) +/// .expect("encryption shouldn't fail") +/// .into(); /// -/// assert!(validate_header(&ciphertext, DataType::Ciphertext); -/// assert!(!validate_header(&ciphertext, DataType::PasswordHash); -/// assert!(!validate_header(&key, DataType::Ciphertext); +/// assert!(validate_header(&ciphertext, DataType::Ciphertext)); +/// assert!(!validate_header(&ciphertext, DataType::PasswordHash)); +/// assert!(!validate_header(&key, DataType::Ciphertext)); +/// ``` pub fn validate_header(data: &[u8], data_type: DataType) -> bool { use super::ciphertext::Ciphertext; use super::derive_encrypt::KdfEncryptedData; diff --git a/src/wasm.rs b/src/wasm.rs index 22a70e15..970d0147 100644 --- a/src/wasm.rs +++ b/src/wasm.rs @@ -189,9 +189,9 @@ pub fn encrypt( version: Option, ) -> Result, JsValue> { Ok(ciphertext::encrypt_with_aad( - &data, - &key, - &aad.unwrap_or(Vec::new()), + data, + key, + &aad.unwrap_or_default(), version.unwrap_or(CiphertextVersion::Latest), )? .into()) @@ -205,9 +205,9 @@ pub fn encrypt_asymmetric( version: Option, ) -> Result, JsValue> { Ok(ciphertext::encrypt_asymmetric_with_aad( - &data, + data, &public_key, - &aad.unwrap_or(Vec::new()), + &aad.unwrap_or_default(), version.unwrap_or(CiphertextVersion::Latest), )? .into()) @@ -216,7 +216,7 @@ pub fn encrypt_asymmetric( #[wasm_bindgen] pub fn decrypt(data: &[u8], key: &[u8], aad: Option>) -> Result, JsValue> { let data_blob = Ciphertext::try_from(data)?; - Ok(data_blob.decrypt_with_aad(&key, &aad.unwrap_or(Vec::new()))?) + Ok(data_blob.decrypt_with_aad(key, &aad.unwrap_or_default())?) } #[wasm_bindgen(js_name = "decryptAsymmetric")] @@ -226,7 +226,7 @@ pub fn decrypt_asymmetric( aad: Option>, ) -> Result, JsValue> { let data_blob = Ciphertext::try_from(data)?; - Ok(data_blob.decrypt_asymmetric_with_aad(&private_key, &aad.unwrap_or(Vec::new()))?) + Ok(data_blob.decrypt_asymmetric_with_aad(&private_key, &aad.unwrap_or_default())?) } #[wasm_bindgen(js_name = "hashPassword")] @@ -235,7 +235,7 @@ pub fn hash_password( version: Option, ) -> Result, JsValue> { Ok( - password_hash::hash_password(&password, version.unwrap_or(PasswordHashVersion::Latest))? + password_hash::hash_password(password, version.unwrap_or(PasswordHashVersion::Latest))? .into(), ) } @@ -249,7 +249,7 @@ pub fn hash_password_with_params(password: &[u8], params: &[u8]) -> Result Result { let password_hash = PasswordHash::try_from(hash)?; - Ok(password_hash.verify_password(&password)) + Ok(password_hash.verify_password(password)) } #[wasm_bindgen(js_name = "generateKeyPair")] @@ -303,7 +303,7 @@ pub fn decrypt_with_secret_key( #[wasm_bindgen(js_name = "generateSigningKeyPair")] pub fn generate_signing_keypair(version: Option) -> SigningKeyPair { - signing_key::generate_signing_keypair(version.unwrap_or(SigningKeyVersion::Latest)).into() + signing_key::generate_signing_keypair(version.unwrap_or(SigningKeyVersion::Latest)) } #[wasm_bindgen(js_name = "mixKeyExchange")] diff --git a/tests/web.rs b/tests/web.rs index 22d84792..3ef216fc 100644 --- a/tests/web.rs +++ b/tests/web.rs @@ -60,7 +60,7 @@ cfg_if! { assert_eq!(decoded.as_slice(), plain.as_bytes()); let encoded_no_pad = "VGhJczFzYVRlc1Q"; - let decoded_no_pad = wasm::base64decode(&encoded_no_pad).unwrap(); + let decoded_no_pad = wasm::base64decode(encoded_no_pad).unwrap(); assert_eq!(decoded_no_pad.as_slice(), plain.as_bytes()); }