diff --git a/Cargo.lock b/Cargo.lock index 83d70890c3..880db7f100 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11,6 +11,18 @@ dependencies = [ "memchr", ] +[[package]] +name = "argon2" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c3610892ee6e0cbce8ae2700349fcf8f98adb0dbfbee85aec3c9179d29cc072" +dependencies = [ + "base64ct", + "blake2", + "cpufeatures", + "password-hash", +] + [[package]] name = "autocfg" version = "1.4.0" @@ -40,6 +52,15 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" +[[package]] +name = "blake2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" +dependencies = [ + "digest", +] + [[package]] name = "block-buffer" version = "0.10.4" @@ -498,6 +519,7 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" name = "relibc" version = "0.2.5" dependencies = [ + "argon2", "base64ct", "bcrypt-pbkdf", "bitflags", diff --git a/Cargo.toml b/Cargo.toml index 239f8f16f0..18761f273e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -51,6 +51,7 @@ chrono = {version = "0.4", default-features = false, features = ["alloc"]} libm = "0.2" object = { version = "0.36.7", git = "https://gitlab.redox-os.org/andypython/object", default-features = false, features = ["elf", "read_core"] } spin = "0.9.8" +argon2 = "0.5.3" [dependencies.dlmalloc] path = "dlmalloc-rs" diff --git a/src/header/crypt/argon2.rs b/src/header/crypt/argon2.rs new file mode 100644 index 0000000000..87cb641f29 --- /dev/null +++ b/src/header/crypt/argon2.rs @@ -0,0 +1,16 @@ +use alloc::string::{String, ToString}; +use argon2::{ + password_hash::{PasswordHash, PasswordVerifier}, + Argon2, +}; + +pub fn crypt_argon2(key: &str, setting: &str) -> Option { + let hash = PasswordHash::new(setting).ok()?; + let argon2 = Argon2::default(); + + if argon2.verify_password(key.as_bytes(), &hash).is_ok() { + Some(setting.to_string()) + } else { + None + } +} diff --git a/src/header/crypt/mod.rs b/src/header/crypt/mod.rs index 32fe2359b7..b944d34255 100644 --- a/src/header/crypt/mod.rs +++ b/src/header/crypt/mod.rs @@ -19,6 +19,7 @@ use crate::{ platform::{self, types::*}, }; +mod argon2; mod blowfish; mod md5; mod pbkdf2; @@ -26,6 +27,7 @@ mod scrypt; mod sha; use self::{ + argon2::crypt_argon2, blowfish::crypt_blowfish, md5::crypt_md5, pbkdf2::crypt_pbkdf2, @@ -73,21 +75,22 @@ pub unsafe extern "C" fn crypt_r( let setting = unsafe { CStr::from_ptr(setting) } .to_str() .expect("setting must be utf-8"); - let setting_bytes = setting.as_bytes(); - let encoded = if setting_bytes[0] == b'$' && setting_bytes[1] != 0 && setting_bytes[2] != 0 { - if setting_bytes[1] == b'1' && setting_bytes[2] == b'$' { + let encoded = if setting.starts_with('$') { + if setting.starts_with("$1$") { crypt_md5(key, setting) - } else if setting_bytes[1] == b'2' && setting_bytes[3] == b'$' { + } else if setting.starts_with("$2") && setting.as_bytes().get(3) == Some(&b'$') { crypt_blowfish(key, setting) - } else if setting_bytes[1] == b'5' && setting_bytes[2] == b'$' { + } else if setting.starts_with("$5$") { crypt_sha(key, setting, Sha256) - } else if setting_bytes[1] == b'6' && setting_bytes[2] == b'$' { + } else if setting.starts_with("$6$") { crypt_sha(key, setting, Sha512) - } else if setting_bytes[1] == b'7' && setting_bytes[2] == b'$' { + } else if setting.starts_with("$7$") { crypt_scrypt(key, setting) - } else if setting_bytes[1] == b'8' && setting_bytes[2] == b'$' { + } else if setting.starts_with("$8$") { crypt_pbkdf2(key, setting) + } else if setting.starts_with("$argon2") { + crypt_argon2(key, setting) } else { platform::ERRNO.set(EINVAL); return ptr::null_mut();