Compare commits
7 Commits
Author | SHA1 | Date | |
---|---|---|---|
b2e4950db5
|
|||
5496c4e61b
|
|||
51fa26b7d5
|
|||
![]() |
a3696962e8 | ||
![]() |
7e6b33ae7f | ||
b3495c45f3
|
|||
![]() |
17ca487b85 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -6,3 +6,5 @@ fido2luks.bash
|
|||||||
fido2luks.elv
|
fido2luks.elv
|
||||||
fido2luks.fish
|
fido2luks.fish
|
||||||
fido2luks.zsh
|
fido2luks.zsh
|
||||||
|
result
|
||||||
|
result-*
|
||||||
|
41
Cargo.lock
generated
41
Cargo.lock
generated
@@ -100,6 +100,18 @@ version = "1.2.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bstr"
|
||||||
|
version = "0.2.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a40b47ad93e1a5404e6c18dec46b628214fee441c70f4ab5d6942142cc268a3d"
|
||||||
|
dependencies = [
|
||||||
|
"lazy_static",
|
||||||
|
"memchr",
|
||||||
|
"regex-automata",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "byteorder"
|
name = "byteorder"
|
||||||
version = "1.3.4"
|
version = "1.3.4"
|
||||||
@@ -244,6 +256,19 @@ dependencies = [
|
|||||||
"lazy_static",
|
"lazy_static",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "csv"
|
||||||
|
version = "1.1.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1"
|
||||||
|
dependencies = [
|
||||||
|
"bstr",
|
||||||
|
"csv-core",
|
||||||
|
"itoa",
|
||||||
|
"ryu",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "csv-core"
|
name = "csv-core"
|
||||||
version = "0.1.10"
|
version = "0.1.10"
|
||||||
@@ -255,14 +280,14 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ctap_hmac"
|
name = "ctap_hmac"
|
||||||
version = "0.4.2"
|
version = "0.4.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c5fec79b66e3a7bc6a7ace0f4c98f0748892b36d3c5c317fadfce0344fd185dc"
|
checksum = "e9c22d4c95aeeb4e2d41e823912d5460cfa1ebf672363eb97b32fa7c91cab89a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"cbor-codec",
|
"cbor-codec",
|
||||||
"crossbeam",
|
"crossbeam",
|
||||||
"csv-core",
|
"csv",
|
||||||
"derive_builder",
|
"derive_builder",
|
||||||
"failure",
|
"failure",
|
||||||
"failure_derive",
|
"failure_derive",
|
||||||
@@ -271,6 +296,8 @@ dependencies = [
|
|||||||
"rand 0.6.5",
|
"rand 0.6.5",
|
||||||
"ring",
|
"ring",
|
||||||
"rust-crypto",
|
"rust-crypto",
|
||||||
|
"serde",
|
||||||
|
"serde_derive",
|
||||||
"untrusted",
|
"untrusted",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -377,7 +404,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fido2luks"
|
name = "fido2luks"
|
||||||
version = "0.2.15"
|
version = "0.2.19"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ctap_hmac",
|
"ctap_hmac",
|
||||||
"failure",
|
"failure",
|
||||||
@@ -824,6 +851,12 @@ dependencies = [
|
|||||||
"thread_local",
|
"thread_local",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-automata"
|
||||||
|
version = "0.1.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex-syntax"
|
name = "regex-syntax"
|
||||||
version = "0.6.18"
|
version = "0.6.18"
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "fido2luks"
|
name = "fido2luks"
|
||||||
version = "0.2.15"
|
version = "0.2.19"
|
||||||
authors = ["shimunn <shimun@shimun.net>"]
|
authors = ["shimunn <shimun@shimun.net>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
@@ -14,7 +14,7 @@ categories = ["command-line-utilities"]
|
|||||||
license = "MPL-2.0"
|
license = "MPL-2.0"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
ctap_hmac = { version="0.4.2", features = ["request_multiple"] }
|
ctap_hmac = { version="0.4.5", features = ["request_multiple"] }
|
||||||
hex = "0.3.2"
|
hex = "0.3.2"
|
||||||
ring = "0.13.5"
|
ring = "0.13.5"
|
||||||
failure = "0.1.5"
|
failure = "0.1.5"
|
||||||
@@ -26,7 +26,7 @@ serde_derive = "1.0.106"
|
|||||||
serde = "1.0.106"
|
serde = "1.0.106"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
ctap_hmac = { version="0.4.2", features = ["request_multiple"] }
|
ctap_hmac = { version="0.4.5", features = ["request_multiple"] }
|
||||||
hex = "0.3.2"
|
hex = "0.3.2"
|
||||||
ring = "0.13.5"
|
ring = "0.13.5"
|
||||||
failure = "0.1.5"
|
failure = "0.1.5"
|
||||||
|
25
PKGBUILD
25
PKGBUILD
@@ -1,26 +1,37 @@
|
|||||||
# Maintainer: shimunn <shimun@shimun.net>
|
# Maintainer: shimunn <shimun@shimun.net>
|
||||||
pkgname=fido2luks
|
|
||||||
pkgver=0.2.12
|
pkgname=fido2luks-git
|
||||||
|
pkgver=0.2.16.7e6b33a
|
||||||
pkgrel=1
|
pkgrel=1
|
||||||
makedepends=('rust' 'cargo' 'cryptsetup' 'clang')
|
makedepends=('rust' 'cargo' 'cryptsetup' 'clang' 'git')
|
||||||
depends=('cryptsetup')
|
depends=('cryptsetup')
|
||||||
arch=('i686' 'x86_64' 'armv6h' 'armv7h')
|
arch=('i686' 'x86_64' 'armv6h' 'armv7h')
|
||||||
pkgdesc="Decrypt your LUKS partition using a FIDO2 compatible authenticator"
|
pkgdesc="Decrypt your LUKS partition using a FIDO2 compatible authenticator"
|
||||||
url="https://github.com/shimunn/fido2luks"
|
url="https://github.com/shimunn/fido2luks"
|
||||||
license=('MPL-2.0')
|
license=('MPL-2.0')
|
||||||
|
source=('git+https://github.com/shimunn/fido2luks')
|
||||||
|
sha512sums=('SKIP')
|
||||||
|
|
||||||
pkgver() {
|
pkgver() {
|
||||||
|
cd fido2luks
|
||||||
|
|
||||||
# Use tag version if possible otherwise concat project version and git ref
|
# Use tag version if possible otherwise concat project version and git ref
|
||||||
git describe --exact-match --tags HEAD 2> /dev/null || \
|
git describe --exact-match --tags HEAD 2>/dev/null ||
|
||||||
echo "$(cargo pkgid | cut -d'#' -f2).$(git describe --always)"
|
echo "$(cargo pkgid | cut -d'#' -f2).$(git describe --always)"
|
||||||
}
|
}
|
||||||
|
|
||||||
build() {
|
build() {
|
||||||
|
cd fido2luks
|
||||||
cargo build --release --locked --all-features --target-dir=target
|
cargo build --release --locked --all-features --target-dir=target
|
||||||
}
|
}
|
||||||
|
|
||||||
package() {
|
package() {
|
||||||
install -Dm 755 target/release/${pkgname} -t "${pkgdir}/usr/bin"
|
cd fido2luks
|
||||||
install -Dm 755 ../pam_mount/fido2luksmounthelper.sh -t "${pkgdir}/usr/bin"
|
|
||||||
install -Dm 644 ../fido2luks.bash "${pkgdir}/usr/share/bash-completion/completions/fido2luks"
|
install -Dm 755 target/release/fido2luks -t "${pkgdir}/usr/bin"
|
||||||
|
install -Dm 755 pam_mount/fido2luksmounthelper.sh -t "${pkgdir}/usr/bin"
|
||||||
|
install -Dm 644 initcpio/hooks/fido2luks -t "${pkgdir}/usr/lib/initcpio/hooks"
|
||||||
|
install -Dm 644 initcpio/install/fido2luks -t "${pkgdir}/usr/lib/initcpio/install"
|
||||||
|
install -Dm 644 fido2luks.bash "${pkgdir}/usr/share/bash-completion/completions/fido2luks"
|
||||||
|
install -Dm 644 fido2luks.fish -t "${pkgdir}/usr/share/fish/vendor_completions.d"
|
||||||
}
|
}
|
||||||
|
30
README.md
30
README.md
@@ -115,6 +115,36 @@ 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 /etc/fido2luks.conf
|
sudo rm -rf /usr/lib/dracut/modules.d/96luks-2fa /etc/dracut.conf.d/luks-2fa.conf /etc/fido2luks.conf
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Theory of operation
|
||||||
|
|
||||||
|
fido2luks builds on two basic building blocks, LUKS as an abstraction over linux disk encryption and and the FIDO2 extension [`hmac-secret`](https://fidoalliance.org/specs/fido-v2.0-rd-20180702/fido-client-to-authenticator-protocol-v2.0-rd-20180702.html#sctn-hmac-secret-extension).
|
||||||
|
The `hmac-secret` extension allows for an secret to be dervied on the FIDO2 device from two inputs, the user supplied salt/password/keyfile and another secret contained within the FID2 device. The output of the `hmac-secret` function will then be used to decrypt the LUKS header which in turn is used to decrypt the disk.
|
||||||
|
```
|
||||||
|
|
||||||
|
+-------------------------------------------------------------------------------+
|
||||||
|
| |
|
||||||
|
| +-----------------------------------------+ |
|
||||||
|
| | FIDO2 device | |
|
||||||
|
| | | |
|
||||||
|
| | | |
|
||||||
|
+-------+--------+ +------+ | +---------------+ | | +------------------------+
|
||||||
|
| Salt/Password +-> |sha256+------------------------> | | | v | LUKS header |
|
||||||
|
+----------------+ +------+ | | | | | | +---------------+
|
||||||
|
| | | | +--------+ +------------------------+--------> |Disk master key|
|
||||||
|
| | sha256_hmac +---------> | sha256 +-------> | Keyslot 1 | +---------------+
|
||||||
|
+----------------+ | +----------+ | | | +--------+ +------------------------+
|
||||||
|
| FIDO credential+---------------> |Credential| +----> | | | | Keyslot 2 |
|
||||||
|
+----------------+ | |secret | | | | +------------------------+
|
||||||
|
| +----------+ +---------------+ |
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
+-----------------------------------------+
|
||||||
|
|
||||||
|
```
|
||||||
|
Since all these components build upon each other losing or damaging just one of them will render the disk undecryptable, it's threfore of paramount importance to backup the LUKS header and ideally set an backup password
|
||||||
|
or utilise more than one FIDO2 device. Each additional credential and password combination will require it's own LUKS keyslot since the credential secret is randomly generated for each new credential and will thus result
|
||||||
|
in a completly different secret.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
Licensed under
|
Licensed under
|
||||||
|
61
flake.lock
generated
Normal file
61
flake.lock
generated
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"naersk": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1612192764,
|
||||||
|
"narHash": "sha256-7EnLtZQWP6511G1ZPA7FmJlqAr3hWsAYb24tvTvJ/ec=",
|
||||||
|
"owner": "nmattia",
|
||||||
|
"repo": "naersk",
|
||||||
|
"rev": "6e149bfd726a8ebefa415f2d713ba6d942435abd",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nmattia",
|
||||||
|
"repo": "naersk",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1611910458,
|
||||||
|
"narHash": "sha256-//j54S14v9lp3YKizS1WZW3WKwLjGTzvwhHfUAaRBPQ=",
|
||||||
|
"path": "/nix/store/z5g10k571cc5q9yvr0bafzswp0ggawjw-source",
|
||||||
|
"rev": "6e7f25001fe6874f7ae271891f709bbf50a22c45",
|
||||||
|
"type": "path"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"id": "nixpkgs",
|
||||||
|
"type": "indirect"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"naersk": "naersk",
|
||||||
|
"nixpkgs": "nixpkgs",
|
||||||
|
"utils": "utils"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"utils": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1610051610,
|
||||||
|
"narHash": "sha256-U9rPz/usA1/Aohhk7Cmc2gBrEEKRzcW4nwPWMPwja4Y=",
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"rev": "3982c9903e93927c2164caa727cd3f6a0e6d14cc",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
61
flake.nix
Normal file
61
flake.nix
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
{
|
||||||
|
description = "Decrypt your LUKS partition using a FIDO2 compatible authenticator";
|
||||||
|
|
||||||
|
inputs = {
|
||||||
|
utils.url = "github:numtide/flake-utils";
|
||||||
|
naersk = {
|
||||||
|
url = "github:nmattia/naersk";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs = { self, nixpkgs, utils, naersk }:
|
||||||
|
let
|
||||||
|
root = ./.;
|
||||||
|
pname = (builtins.fromTOML (builtins.readFile ./Cargo.toml)).package.name;
|
||||||
|
forPkgs = pkgs:
|
||||||
|
let
|
||||||
|
naersk-lib = naersk.lib."${pkgs.system}";
|
||||||
|
buildInputs = with pkgs; [ cryptsetup ];
|
||||||
|
LIBCLANG_PATH = "${pkgs.clang.cc.lib}/lib";
|
||||||
|
nativeBuildInputs = with pkgs; [
|
||||||
|
pkgconfig
|
||||||
|
clang
|
||||||
|
];
|
||||||
|
in
|
||||||
|
rec {
|
||||||
|
# `nix build`
|
||||||
|
packages.${pname} = naersk-lib.buildPackage {
|
||||||
|
inherit pname root buildInputs nativeBuildInputs LIBCLANG_PATH;
|
||||||
|
};
|
||||||
|
defaultPackage = packages.${pname};
|
||||||
|
|
||||||
|
# `nix run`
|
||||||
|
apps.${pname} = utils.lib.mkApp {
|
||||||
|
drv = packages.${pname};
|
||||||
|
};
|
||||||
|
defaultApp = apps.${pname};
|
||||||
|
|
||||||
|
# `nix flake check`
|
||||||
|
checks = {
|
||||||
|
fmt = with pkgs; runCommandLocal "${pname}-fmt" { buildInputs = [ cargo rustfmt nixpkgs-fmt ]; } ''
|
||||||
|
cd ${root}
|
||||||
|
cargo fmt -- --check
|
||||||
|
nixpkgs-fmt --check *.nix
|
||||||
|
touch $out
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
# `nix develop`
|
||||||
|
devShell = pkgs.mkShell {
|
||||||
|
nativeBuildInputs = with pkgs; [ rustc cargo rustfmt nixpkgs-fmt ] ++ nativeBuildInputs;
|
||||||
|
inherit buildInputs LIBCLANG_PATH;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
forSystem = system: forPkgs nixpkgs.legacyPackages."${system}";
|
||||||
|
in
|
||||||
|
(utils.lib.eachSystem [ "aarch64-linux" "i686-linux" "x86_64-linux" ] forSystem) // {
|
||||||
|
overlay = final: prev: (forPkgs final).packages;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
18
initcpio/Makefile
Normal file
18
initcpio/Makefile
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
.PHONY: install remove
|
||||||
|
|
||||||
|
install:
|
||||||
|
install -Dm644 hooks/fido2luks -t /usr/lib/initcpio/hooks
|
||||||
|
install -Dm644 install/fido2luks -t /usr/lib/initcpio/install
|
||||||
|
ifdef preset
|
||||||
|
mkinitcpio -p $(preset)
|
||||||
|
else
|
||||||
|
mkinitcpio -P
|
||||||
|
endif
|
||||||
|
|
||||||
|
remove:
|
||||||
|
rm /usr/lib/initcpio/{hooks,install}/fido2luks
|
||||||
|
ifdef preset
|
||||||
|
mkinitcpio -p $(preset)
|
||||||
|
else
|
||||||
|
mkinitcpio -P
|
||||||
|
endif
|
52
initcpio/README.md
Normal file
52
initcpio/README.md
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
## fido2luks hook for mkinitcpio (ArchLinux and derivatives)
|
||||||
|
|
||||||
|
> ⚠️ Before proceeding, it is very advised to [backup your existing LUKS2 header](https://wiki.archlinux.org/title/dm-crypt/Device_encryption#Backup_using_cryptsetup) to external storage
|
||||||
|
|
||||||
|
### Setup
|
||||||
|
|
||||||
|
1. Connect your FIDO2 authenticator
|
||||||
|
2. Generate credential id
|
||||||
|
|
||||||
|
```shell
|
||||||
|
fido2luks credential
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Generate salt (random string)
|
||||||
|
|
||||||
|
```shell
|
||||||
|
pwgen 48 1
|
||||||
|
```
|
||||||
|
|
||||||
|
4. Add key to your LUKS2 device
|
||||||
|
|
||||||
|
```shell
|
||||||
|
fido2luks add-key -Pt --salt <salt> <block_device> <credential_id>
|
||||||
|
```
|
||||||
|
|
||||||
|
`-P` - request PIN to unlock the authenticator
|
||||||
|
`-t` - add token (including credential id) to the LUKS2 header
|
||||||
|
`-e` - wipe all other keys
|
||||||
|
|
||||||
|
For the full list of options see `fido2luks add-key --help`
|
||||||
|
|
||||||
|
5. Edit [/etc/fido2luks.conf](/initcpio/fido2luks.conf)
|
||||||
|
|
||||||
|
Keyslot (`FIDO2LUKS_DEVICE_SLOT`) can be obtained from the output of
|
||||||
|
|
||||||
|
```shell
|
||||||
|
cryptsetup luksDump <block_device>
|
||||||
|
```
|
||||||
|
|
||||||
|
6. Add fido2luks hook to /etc/mkinitcpio.conf
|
||||||
|
|
||||||
|
Before or instead of `encrypt` hook, for example:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
HOOKS=(base udev autodetect modconf keyboard block fido2luks filesystems fsck)
|
||||||
|
```
|
||||||
|
|
||||||
|
7. Recreate initial ramdisk
|
||||||
|
|
||||||
|
```shell
|
||||||
|
mkinitcpio -p <preset>
|
||||||
|
```
|
18
initcpio/fido2luks.conf
Normal file
18
initcpio/fido2luks.conf
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# Set credential *ONLY IF* it's not embedded in the LUKS2 header
|
||||||
|
FIDO2LUKS_CREDENTIAL_ID=
|
||||||
|
|
||||||
|
# Encrypted device and its name under /dev/mapper
|
||||||
|
# Can be overridden by `cryptdevice` kernel parameter
|
||||||
|
FIDO2LUKS_DEVICE=
|
||||||
|
FIDO2LUKS_MAPPER_NAME=
|
||||||
|
|
||||||
|
FIDO2LUKS_SALT=string:<salt>
|
||||||
|
|
||||||
|
# Use specific keyslot (ignore all other slots)
|
||||||
|
FIDO2LUKS_DEVICE_SLOT=
|
||||||
|
|
||||||
|
# Await for an authenticator to be connected (in seconds)
|
||||||
|
FIDO2LUKS_DEVICE_AWAIT=
|
||||||
|
|
||||||
|
# Set to 1 if PIN is required to unlock the authenticator
|
||||||
|
FIDO2LUKS_ASK_PIN=
|
55
initcpio/hooks/fido2luks
Normal file
55
initcpio/hooks/fido2luks
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
#!/usr/bin/ash
|
||||||
|
|
||||||
|
run_hook() {
|
||||||
|
modprobe -a -q dm-crypt >/dev/null 2>&1
|
||||||
|
. /etc/fido2luks.conf
|
||||||
|
|
||||||
|
if [ -z "$cryptdevice" ]; then
|
||||||
|
device="$FIDO2LUKS_DEVICE"
|
||||||
|
dmname="$FIDO2LUKS_MAPPER_NAME"
|
||||||
|
else
|
||||||
|
IFS=: read cryptdev dmname _cryptoptions <<EOF
|
||||||
|
$cryptdevice
|
||||||
|
EOF
|
||||||
|
if ! device=$(resolve_device "${cryptdev}" ${rootdelay}); then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
options="--salt $FIDO2LUKS_SALT"
|
||||||
|
|
||||||
|
if [ "$FIDO2LUKS_ASK_PIN" == 1 ]; then
|
||||||
|
options="$options --pin"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$FIDO2LUKS_DEVICE_SLOT" ]; then
|
||||||
|
options="$options --slot $FIDO2LUKS_DEVICE_SLOT"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$FIDO2LUKS_DEVICE_AWAIT" ]; then
|
||||||
|
options="$options --await-dev $FIDO2LUKS_DEVICE_AWAIT"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# HACK: /dev/tty is hardcoded in rpassword, but not accessible from the ramdisk
|
||||||
|
# Temporary link it to /dev/tty1
|
||||||
|
mv /dev/tty /dev/tty.back
|
||||||
|
ln -s /dev/tty1 /dev/tty
|
||||||
|
|
||||||
|
printf "\nAuthentication is required to access the $dmname volume at $device\n"
|
||||||
|
|
||||||
|
if [ -z "$FIDO2LUKS_CREDENTIAL_ID" ]; then
|
||||||
|
fido2luks open-token $device $dmname $options
|
||||||
|
else
|
||||||
|
fido2luks open $device $dmname $FIDO2LUKS_CREDENTIAL_ID $options
|
||||||
|
fi
|
||||||
|
exit_code=$?
|
||||||
|
|
||||||
|
# Restore /dev/tty
|
||||||
|
mv /dev/tty.back /dev/tty
|
||||||
|
|
||||||
|
if [ $exit_code -ne 0 ]; then
|
||||||
|
printf '\n'
|
||||||
|
read -s -p 'Press Enter to continue'
|
||||||
|
printf '\n'
|
||||||
|
fi
|
||||||
|
}
|
31
initcpio/install/fido2luks
Normal file
31
initcpio/install/fido2luks
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
build() {
|
||||||
|
local mod
|
||||||
|
|
||||||
|
add_module dm-crypt
|
||||||
|
add_module dm-integrity
|
||||||
|
if [[ $CRYPTO_MODULES ]]; then
|
||||||
|
for mod in $CRYPTO_MODULES; do
|
||||||
|
add_module "$mod"
|
||||||
|
done
|
||||||
|
else
|
||||||
|
add_all_modules /crypto/
|
||||||
|
fi
|
||||||
|
|
||||||
|
add_binary fido2luks
|
||||||
|
add_binary dmsetup
|
||||||
|
add_file /usr/lib/udev/rules.d/10-dm.rules
|
||||||
|
add_file /usr/lib/udev/rules.d/13-dm-disk.rules
|
||||||
|
add_file /usr/lib/udev/rules.d/95-dm-notify.rules
|
||||||
|
add_file /usr/lib/initcpio/udev/11-dm-initramfs.rules /usr/lib/udev/rules.d/11-dm-initramfs.rules
|
||||||
|
add_file /etc/fido2luks.conf /etc/fido2luks.conf
|
||||||
|
|
||||||
|
add_runscript
|
||||||
|
}
|
||||||
|
|
||||||
|
help() {
|
||||||
|
cat <<HELPEOF
|
||||||
|
This hook allows to decrypt LUKS2 partition using FIDO2 compatible authenticator
|
||||||
|
HELPEOF
|
||||||
|
}
|
26
src/cli.rs
26
src/cli.rs
@@ -71,6 +71,12 @@ pub fn parse_cmdline() -> Args {
|
|||||||
Args::from_args()
|
Args::from_args()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn prompt_interaction(interactive: bool) {
|
||||||
|
if interactive {
|
||||||
|
println!("Authorize using your FIDO device");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn run_cli() -> Fido2LuksResult<()> {
|
pub fn run_cli() -> Fido2LuksResult<()> {
|
||||||
let mut stdout = io::stdout();
|
let mut stdout = io::stdout();
|
||||||
let args = parse_cmdline();
|
let args = parse_cmdline();
|
||||||
@@ -87,7 +93,7 @@ pub fn run_cli() -> Fido2LuksResult<()> {
|
|||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
let cred = make_credential_id(name.as_ref().map(|n| n.as_ref()), pin)?;
|
let cred = make_credential_id(Some(name.as_ref()), pin)?;
|
||||||
println!("{}", hex::encode(&cred.id));
|
println!("{}", hex::encode(&cred.id));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -109,6 +115,7 @@ pub fn run_cli() -> Fido2LuksResult<()> {
|
|||||||
} else {
|
} else {
|
||||||
secret.salt.obtain_sha256(&secret.password_helper)
|
secret.salt.obtain_sha256(&secret.password_helper)
|
||||||
}?;
|
}?;
|
||||||
|
prompt_interaction(interactive);
|
||||||
let (secret, _cred) = derive_secret(
|
let (secret, _cred) = derive_secret(
|
||||||
credentials.ids.0.as_slice(),
|
credentials.ids.0.as_slice(),
|
||||||
&salt,
|
&salt,
|
||||||
@@ -164,23 +171,27 @@ pub fn run_cli() -> Fido2LuksResult<()> {
|
|||||||
} => Ok((util::read_keyfile(file)?, None)),
|
} => Ok((util::read_keyfile(file)?, None)),
|
||||||
OtherSecret {
|
OtherSecret {
|
||||||
fido_device: true, ..
|
fido_device: true, ..
|
||||||
} => Ok(derive_secret(
|
} => {
|
||||||
|
prompt_interaction(interactive);
|
||||||
|
Ok(derive_secret(
|
||||||
&credentials.ids.0,
|
&credentials.ids.0,
|
||||||
&salt(salt_q, verify)?,
|
&salt(salt_q, verify)?,
|
||||||
authenticator.await_time,
|
authenticator.await_time,
|
||||||
pin.as_deref(),
|
pin.as_deref(),
|
||||||
)
|
)
|
||||||
.map(|(secret, cred)| (secret[..].to_vec(), Some(cred)))?),
|
.map(|(secret, cred)| (secret[..].to_vec(), Some(cred)))?)
|
||||||
|
}
|
||||||
_ => Ok((
|
_ => Ok((
|
||||||
util::read_password(salt_q, verify)?.as_bytes().to_vec(),
|
util::read_password(salt_q, verify)?.as_bytes().to_vec(),
|
||||||
None,
|
None,
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let secret = |verify: bool| -> Fido2LuksResult<([u8; 32], FidoCredential)> {
|
let secret = |q: &str, verify: bool| -> Fido2LuksResult<([u8; 32], FidoCredential)> {
|
||||||
|
prompt_interaction(interactive);
|
||||||
derive_secret(
|
derive_secret(
|
||||||
&credentials.ids.0,
|
&credentials.ids.0,
|
||||||
&salt("Password", verify)?,
|
&salt(q, verify)?,
|
||||||
authenticator.await_time,
|
authenticator.await_time,
|
||||||
pin.as_deref(),
|
pin.as_deref(),
|
||||||
)
|
)
|
||||||
@@ -190,7 +201,7 @@ pub fn run_cli() -> Fido2LuksResult<()> {
|
|||||||
match &args.command {
|
match &args.command {
|
||||||
Command::AddKey { exclusive, .. } => {
|
Command::AddKey { exclusive, .. } => {
|
||||||
let (existing_secret, _) = other_secret("Current password", false)?;
|
let (existing_secret, _) = other_secret("Current password", false)?;
|
||||||
let (new_secret, cred) = secret(true)?;
|
let (new_secret, cred) = secret("Password to be added", true)?;
|
||||||
let added_slot = luks_dev.add_key(
|
let added_slot = luks_dev.add_key(
|
||||||
&new_secret,
|
&new_secret,
|
||||||
&existing_secret[..],
|
&existing_secret[..],
|
||||||
@@ -215,7 +226,7 @@ pub fn run_cli() -> Fido2LuksResult<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Command::ReplaceKey { add_password, .. } => {
|
Command::ReplaceKey { add_password, .. } => {
|
||||||
let (existing_secret, _) = secret(false)?;
|
let (existing_secret, _) = secret("Current password", false)?;
|
||||||
let (replacement_secret, cred) = other_secret("Replacement password", true)?;
|
let (replacement_secret, cred) = other_secret("Replacement password", true)?;
|
||||||
let slot = if *add_password {
|
let slot = if *add_password {
|
||||||
luks_dev.add_key(
|
luks_dev.add_key(
|
||||||
@@ -274,6 +285,7 @@ pub fn run_cli() -> Fido2LuksResult<()> {
|
|||||||
|
|
||||||
// Cow shouldn't be necessary
|
// Cow shouldn't be necessary
|
||||||
let secret = |credentials: Cow<'_, Vec<HexEncoded>>| {
|
let secret = |credentials: Cow<'_, Vec<HexEncoded>>| {
|
||||||
|
prompt_interaction(interactive);
|
||||||
derive_secret(
|
derive_secret(
|
||||||
credentials.as_ref(),
|
credentials.as_ref(),
|
||||||
&salt("Password", false)?,
|
&salt("Password", false)?,
|
||||||
|
@@ -236,9 +236,9 @@ pub enum Command {
|
|||||||
Credential {
|
Credential {
|
||||||
#[structopt(flatten)]
|
#[structopt(flatten)]
|
||||||
authenticator: AuthenticatorParameters,
|
authenticator: AuthenticatorParameters,
|
||||||
/// Name to be displayed on the authenticator if it has a display
|
/// Name to be displayed on the authenticator display
|
||||||
#[structopt(env = "FIDO2LUKS_CREDENTIAL_NAME")]
|
#[structopt(env = "FIDO2LUKS_CREDENTIAL_NAME", default_value = "fido2luks")]
|
||||||
name: Option<String>,
|
name: String,
|
||||||
},
|
},
|
||||||
/// Check if an authenticator is connected
|
/// Check if an authenticator is connected
|
||||||
#[structopt(name = "connected")]
|
#[structopt(name = "connected")]
|
||||||
|
Reference in New Issue
Block a user