diff --git a/Cargo.toml b/Cargo.toml index f1d9cb5..3d19332 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fido2luks" -version = "0.2.1" +version = "0.2.2" authors = ["shimunn "] edition = "2018" @@ -15,7 +15,7 @@ license-file = "LICENSE" [dependencies] #ctap = "0.1.0" -ctap_hmac = "0.1.1" +ctap_hmac = "0.2.1" cryptsetup-rs = "0.2.1" libcryptsetup-sys = "0.1.2" diff --git a/src/cli.rs b/src/cli.rs index ac7c24a..761eb33 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -70,10 +70,6 @@ pub fn add_password_to_luks( Ok(slot) } -pub fn authenticator_connected() -> Fido2LuksResult { - Ok(!device::get_devices()?.is_empty()) -} - #[derive(Debug, StructOpt)] pub struct Args { /// Request passwords via Stdin instead of using the password helper diff --git a/src/device.rs b/src/device.rs index c574fdc..30aca2c 100644 --- a/src/device.rs +++ b/src/device.rs @@ -1,11 +1,39 @@ use crate::error::*; +use crate::util::sha256; use ctap::{ self, extensions::hmac::{FidoHmacCredential, HmacExtension}, - FidoDevice, FidoError, FidoErrorKind, + AuthenticatorOptions, FidoDevice, FidoError, FidoErrorKind, PublicKeyCredentialRpEntity, + PublicKeyCredentialUserEntity, }; +const RP_ID: &'static str = "fido2luks"; + +fn authenticator_options() -> Option { + Some(AuthenticatorOptions { + uv: false, //TODO: should get this from config + rk: true, + }) +} + +fn authenticator_rp() -> PublicKeyCredentialRpEntity<'static> { + PublicKeyCredentialRpEntity { + id: RP_ID, + name: None, + icon: None, + } +} + +fn authenticator_user() -> PublicKeyCredentialUserEntity<'static> { + PublicKeyCredentialUserEntity { + id: &[0u8], + name: "", + icon: None, + display_name: None, + } +} + pub fn make_credential_id() -> Fido2LuksResult { let mut errs = Vec::new(); match get_devices()? { @@ -13,7 +41,13 @@ pub fn make_credential_id() -> Fido2LuksResult { devs => { for mut dev in devs.into_iter() { match dev - .make_credential("fido2luks", &[0u8], "", &[0u8; 32]) + .make_hmac_credential_full( + authenticator_rp(), + authenticator_user(), + &[0u8; 32], + &[], + authenticator_options(), + ) .map(|cred| cred.into()) { //TODO: make credentials device specific @@ -33,16 +67,16 @@ pub fn make_credential_id() -> Fido2LuksResult { pub fn perform_challenge(credential_id: &str, salt: &[u8; 32]) -> Fido2LuksResult<[u8; 32]> { let cred = FidoHmacCredential { id: hex::decode(credential_id).unwrap(), - rp_id: "hmac".to_string(), + rp_id: RP_ID.to_string(), }; let mut errs = Vec::new(); match get_devices()? { ref devs if devs.is_empty() => Err(Fido2LuksError::NoAuthenticatorError)?, devs => { for mut dev in devs.into_iter() { - match dev.hmac_challange(&cred, &salt[..]) { + match dev.get_hmac_assertion(&cred, &sha256(&[&salt[..]]), None, None) { Ok(secret) => { - return Ok(secret); + return Ok(secret.0); } Err(e) => { errs.push(e); diff --git a/src/main.rs b/src/main.rs index e7ac839..050fc8f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,9 +7,8 @@ use crate::device::*; use crate::error::*; use cryptsetup_rs as luks; use cryptsetup_rs::Luks1CryptDevice; -use ring::digest; -use std::io::{self}; +use std::io; use std::path::PathBuf; use std::process::exit; @@ -26,12 +25,7 @@ fn open_container(device: &PathBuf, name: &str, secret: &[u8; 32]) -> Fido2LuksR } fn assemble_secret(hmac_result: &[u8], salt: &[u8]) -> [u8; 32] { - let mut digest = digest::Context::new(&digest::SHA256); - digest.update(salt); - digest.update(hmac_result); - let mut secret = [0u8; 32]; - secret.as_mut().copy_from_slice(digest.finish().as_ref()); - secret + util::sha256(&[salt, hmac_result]) } fn main() -> Fido2LuksResult<()> { diff --git a/src/util.rs b/src/util.rs index 516cd35..e7366d0 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,8 +1,19 @@ use crate::error::*; +use ring::digest; use std::fs::File; use std::io::Read; use std::path::PathBuf; +pub fn sha256<'a>(messages: &[&[u8]]) -> [u8; 32] { + let mut digest = digest::Context::new(&digest::SHA256); + for m in messages.iter() { + digest.update(m); + } + let mut secret = [0u8; 32]; + secret.as_mut().copy_from_slice(digest.finish().as_ref()); + secret +} + pub fn read_password(q: &str, verify: bool) -> Fido2LuksResult { match rpassword::read_password_from_tty(Some(&[q, ": "].join("")))? { ref pass