Compare commits
4 Commits
Author | SHA1 | Date | |
---|---|---|---|
6e53449ff6
|
|||
fbcfdea96b
|
|||
99e408cc8d
|
|||
8fc9e0dcce
|
30
README.md
30
README.md
@@ -1,6 +1,6 @@
|
|||||||
# fido2luks
|
# fido2luks
|
||||||
|
|
||||||
This will allow you to unlock your luks encrypted disk with an fido2 compatable key
|
This will allow you to unlock your luks encrypted disk with an fido2 compatible key
|
||||||
|
|
||||||
Note: This has only been tested under Fedora 30 using a Solo Key
|
Note: This has only been tested under Fedora 30 using a Solo Key
|
||||||
|
|
||||||
@@ -20,10 +20,10 @@ git clone https://github.com/shimunn/fido2luks.git && cd fido2luks
|
|||||||
#Alternativly cargo build --release && sudo cp target/release/fido2luks /usr/bin/
|
#Alternativly cargo build --release && sudo cp target/release/fido2luks /usr/bin/
|
||||||
CARGO_INSTALL_ROOT=/usr sudo -E cargo install -f --path .
|
CARGO_INSTALL_ROOT=/usr sudo -E cargo install -f --path .
|
||||||
|
|
||||||
echo FIDO2LUKS_CREDENTIAL_ID=$(fido2luks credential) >> fido2luks.conf
|
echo FIDO2LUKS_CREDENTIAL_ID=$(fido2luks credential) >> dracut/96luks-2fa/fido2luks.conf
|
||||||
|
|
||||||
set -a
|
set -a
|
||||||
. fido2luks.conf
|
. dracut/96luks-2fa/fido2luks.conf
|
||||||
|
|
||||||
#Repeat for each luks volume
|
#Repeat for each luks volume
|
||||||
sudo -E fido2luks -i add-key /dev/disk/by-uuid/<DISK_UUID>
|
sudo -E fido2luks -i add-key /dev/disk/by-uuid/<DISK_UUID>
|
||||||
@@ -43,14 +43,22 @@ sudo make install
|
|||||||
|
|
||||||
### Grub
|
### Grub
|
||||||
|
|
||||||
Add `rd.luks.2fa=<CREDENTIAL_ID>:<DISK_UUID>` to `GRUB_CMDLINE_LINUX`
|
Add `rd.luks.2fa=<CREDENTIAL_ID>:<DISK_UUID>` to `GRUB_CMDLINE_LINUX` in /etc/default/grub
|
||||||
|
|
||||||
Note: This is only required for your root disk, systemd will try to unlock all other luks partions using the same key if you added it using `fido2luks addkey`
|
Note: This is only required for your root disk, systemd will try to unlock all other luks partions using the same key if you added it using `fido2luks add-key`
|
||||||
|
|
||||||
```
|
```
|
||||||
grub2-mkconfig > /boot/grub2/grub.cfg
|
grub2-mkconfig > /boot/grub2/grub.cfg
|
||||||
```
|
```
|
||||||
|
|
||||||
|
I'd also recommend to copy the executable onto /boot so that it is accessible in case you have to access your disk from a live system
|
||||||
|
|
||||||
|
```
|
||||||
|
mkdir /boot/fido2luks/
|
||||||
|
cp /usr/bin/fido2luks /boot/fido2luks/
|
||||||
|
cp /etc/fido2luks.conf /boot/fido2luks/
|
||||||
|
```
|
||||||
|
|
||||||
## Test
|
## Test
|
||||||
|
|
||||||
Just reboot and see if it works, if thats the case you should remove your old less secure password from your luks header:
|
Just reboot and see if it works, if thats the case you should remove your old less secure password from your luks header:
|
||||||
@@ -61,3 +69,15 @@ cryptsetup luksHeaderBackup /dev/disk/by-uuid/<DISK_UUID> --header-backup-file l
|
|||||||
#There is no turning back if you mess this up, make sure you made a backup
|
#There is no turning back if you mess this up, make sure you made a backup
|
||||||
fido2luks -i add-key --exclusive /dev/disk/by-uuid/<DISK_UUID>
|
fido2luks -i add-key --exclusive /dev/disk/by-uuid/<DISK_UUID>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Removal
|
||||||
|
|
||||||
|
Remove `rd.luks.2fa` from `GRUB_CMDLINE_LINUX` in /etc/default/grub
|
||||||
|
|
||||||
|
```
|
||||||
|
set -a
|
||||||
|
. fido2luks.conf
|
||||||
|
sudo -E fido2luks -i replace-key /dev/disk/by-uuid/<DISK_UUID>
|
||||||
|
|
||||||
|
sudo rm -rf /usr/lib/dracut/modules.d/96luks-2fa /etc/dracut.conf.d/luks-2fa.conf
|
||||||
|
```
|
||||||
|
3
dracut/96luks-2fa/fido2luks.conf
Normal file
3
dracut/96luks-2fa/fido2luks.conf
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
FIDO2LUKS_SALT=Ask
|
||||||
|
FIDO2LUKS_PASSWORD_HELPER=/usr/bin/systemd-ask-password Please enter second factor for LUKS disk encryption
|
||||||
|
|
@@ -32,9 +32,8 @@ generate_service () {
|
|||||||
printf -- "\n\n[Service]"
|
printf -- "\n\n[Service]"
|
||||||
printf -- "\nType=oneshot"
|
printf -- "\nType=oneshot"
|
||||||
printf -- "\nRemainAfterExit=yes"
|
printf -- "\nRemainAfterExit=yes"
|
||||||
|
printf -- "\nEnvironmentFile=%s" "/etc/fido2luks.conf"
|
||||||
printf -- "\nEnvironment=FIDO2LUKS_CREDENTIAL_ID='%s'" "$credential_id"
|
printf -- "\nEnvironment=FIDO2LUKS_CREDENTIAL_ID='%s'" "$credential_id"
|
||||||
printf -- "\nEnvironment=FIDO2LUKS_SALT='%s'" "Ask"
|
|
||||||
printf -- "\nEnvironment=FIDO2LUKS_PASSWORD_HELPER='%s'" "/usr/bin/systemd-ask-password Disk 2fa password"
|
|
||||||
printf -- "\nKeyringMode=%s" "shared"
|
printf -- "\nKeyringMode=%s" "shared"
|
||||||
printf -- "\nExecStartPre=-/usr/bin/plymouth display-message --text \"${CON_MSG}\""
|
printf -- "\nExecStartPre=-/usr/bin/plymouth display-message --text \"${CON_MSG}\""
|
||||||
printf -- "\nExecStartPre=-/bin/bash -c \"while ! ${FIDO2LUKS} connected; do /usr/bin/sleep 1; done\""
|
printf -- "\nExecStartPre=-/bin/bash -c \"while ! ${FIDO2LUKS} connected; do /usr/bin/sleep 1; done\""
|
||||||
|
@@ -18,6 +18,7 @@ depends () {
|
|||||||
install () {
|
install () {
|
||||||
inst "$moddir/luks-2fa-generator.sh" "/etc/systemd/system-generators/luks-2fa-generator.sh"
|
inst "$moddir/luks-2fa-generator.sh" "/etc/systemd/system-generators/luks-2fa-generator.sh"
|
||||||
inst_simple "/usr/bin/fido2luks" "/usr/bin/fido2luks"
|
inst_simple "/usr/bin/fido2luks" "/usr/bin/fido2luks"
|
||||||
|
inst_simple "/etc/fido2luks.conf" "/etc/fido2luks.conf"
|
||||||
inst "$systemdutildir/systemd-cryptsetup"
|
inst "$systemdutildir/systemd-cryptsetup"
|
||||||
mkdir -p "$initdir/luks-2fa"
|
mkdir -p "$initdir/luks-2fa"
|
||||||
|
|
||||||
|
@@ -15,6 +15,7 @@ help:
|
|||||||
install:
|
install:
|
||||||
cp ${MODULE_CONF_D}/${MODULE_CONF} ${DRACUT_CONF_D}/
|
cp ${MODULE_CONF_D}/${MODULE_CONF} ${DRACUT_CONF_D}/
|
||||||
cp -r ${MODULE_DIR} ${DRACUT_MODULES_D}/
|
cp -r ${MODULE_DIR} ${DRACUT_MODULES_D}/
|
||||||
|
cp ${MODULE_DIR}/fido2luks.conf /etc/fido2luks.conf
|
||||||
dracut -fv
|
dracut -fv
|
||||||
clean:
|
clean:
|
||||||
rm ${DRACUT_CONF_D}/${MODULE_CONF}
|
rm ${DRACUT_CONF_D}/${MODULE_CONF}
|
||||||
|
14
src/cli.rs
14
src/cli.rs
@@ -88,8 +88,18 @@ pub struct SecretGeneration {
|
|||||||
/// FIDO credential id, generate using fido2luks credential
|
/// FIDO credential id, generate using fido2luks credential
|
||||||
#[structopt(name = "credential-id", env = "FIDO2LUKS_CREDENTIAL_ID")]
|
#[structopt(name = "credential-id", env = "FIDO2LUKS_CREDENTIAL_ID")]
|
||||||
pub credential_id: String,
|
pub credential_id: String,
|
||||||
/// Salt for secret generation, defaults to Password
|
/// Salt for secret generation, defaults to 'ask'
|
||||||
#[structopt(name = "salt", env = "FIDO2LUKS_SALT", default_value = "Ask")]
|
///
|
||||||
|
/// Options:{n}
|
||||||
|
/// - ask : Promt user using password helper{n}
|
||||||
|
/// - file:<PATH> : Will read <FILE>{n}
|
||||||
|
/// - string:<STRING> : Will use <STRING>, which will be handled like a password provided to the 'ask' option{n}
|
||||||
|
#[structopt(
|
||||||
|
name = "salt",
|
||||||
|
long = "salt",
|
||||||
|
env = "FIDO2LUKS_SALT",
|
||||||
|
default_value = "ask"
|
||||||
|
)]
|
||||||
pub salt: InputSalt,
|
pub salt: InputSalt,
|
||||||
/// Script used to obtain passwords, overridden by --interactive flag
|
/// Script used to obtain passwords, overridden by --interactive flag
|
||||||
#[structopt(
|
#[structopt(
|
||||||
|
@@ -10,11 +10,11 @@ use std::path::PathBuf;
|
|||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum InputSalt {
|
pub enum InputSalt {
|
||||||
AskPassword,
|
AskPassword,
|
||||||
|
String(String),
|
||||||
File { path: PathBuf },
|
File { path: PathBuf },
|
||||||
Both { path: PathBuf },
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for InputSalt {
|
impl Default for InputSalt {
|
||||||
@@ -25,10 +25,14 @@ impl Default for InputSalt {
|
|||||||
|
|
||||||
impl From<&str> for InputSalt {
|
impl From<&str> for InputSalt {
|
||||||
fn from(s: &str) -> Self {
|
fn from(s: &str) -> Self {
|
||||||
if PathBuf::from(s).exists() && s != "Ask" {
|
let mut parts = s.split(":").into_iter();
|
||||||
InputSalt::File { path: s.into() }
|
match parts.next() {
|
||||||
} else {
|
Some("ask") | Some("Ask") => InputSalt::AskPassword,
|
||||||
InputSalt::AskPassword
|
Some("file") => InputSalt::File {
|
||||||
|
path: parts.collect::<Vec<_>>().join(":").into(),
|
||||||
|
},
|
||||||
|
Some("string") => InputSalt::String(parts.collect::<Vec<_>>().join(":")),
|
||||||
|
_ => Self::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -45,8 +49,8 @@ impl fmt::Display for InputSalt {
|
|||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
||||||
f.write_str(&match self {
|
f.write_str(&match self {
|
||||||
InputSalt::AskPassword => "ask".to_string(),
|
InputSalt::AskPassword => "ask".to_string(),
|
||||||
InputSalt::File { path } => path.display().to_string(),
|
InputSalt::String(s) => ["string", s].join(":"),
|
||||||
InputSalt::Both { path } => ["ask", path.display().to_string().as_str()].join(" + "),
|
InputSalt::File { path } => ["file", path.display().to_string().as_str()].join(":"),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -73,10 +77,7 @@ impl InputSalt {
|
|||||||
InputSalt::AskPassword => {
|
InputSalt::AskPassword => {
|
||||||
digest.input(password_helper.obtain()?.as_bytes());
|
digest.input(password_helper.obtain()?.as_bytes());
|
||||||
}
|
}
|
||||||
InputSalt::Both { path } => {
|
InputSalt::String(s) => digest.input(s.as_bytes()),
|
||||||
digest.input(&InputSalt::AskPassword.obtain(password_helper)?);
|
|
||||||
digest.input(&InputSalt::File { path: path.clone() }.obtain(password_helper)?)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
let mut salt = [0u8; 32];
|
let mut salt = [0u8; 32];
|
||||||
digest.result(&mut salt);
|
digest.result(&mut salt);
|
||||||
@@ -148,3 +149,25 @@ impl PasswordHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn input_salt_from_str() {
|
||||||
|
assert_eq!(
|
||||||
|
"file:/tmp/abc".parse::<InputSalt>().unwrap(),
|
||||||
|
InputSalt::File {
|
||||||
|
path: "/tmp/abc".into()
|
||||||
|
}
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
"string:abc".parse::<InputSalt>().unwrap(),
|
||||||
|
InputSalt::String("abc".into())
|
||||||
|
);
|
||||||
|
assert_eq!("ask".parse::<InputSalt>().unwrap(), InputSalt::AskPassword);
|
||||||
|
assert_eq!("lol".parse::<InputSalt>().unwrap(), InputSalt::default());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user