Skip to content

Commit

Permalink
Add fingerprint functionality to guivm
Browse files Browse the repository at this point in the history
- module with qemu rules, required packages and services, and polkit/pam configs; conditionally applied to guivmExtraModules
- allows ghaf user to enroll and verify fingerprints
- works with swaylock, sudo, systemctl
- swaylock works with password w/o fingerprint, when fp is enrolled it allows either password or fp. To use fp auth, press Enter and then do fp auth

Further work required:
- persistent fingerprint data storage required
- proper integration with login manager (when ready)
- potential enrollment application
- swaylock bugs have been observed (some even w/o fingerprint)

Signed-off-by: Manuel Bluhm <manuel@ssrc.tii.ae>
  • Loading branch information
mbssrc committed Apr 4, 2024
1 parent 16f0d25 commit d3455e8
Show file tree
Hide file tree
Showing 8 changed files with 182 additions and 33 deletions.
6 changes: 3 additions & 3 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 16 additions & 10 deletions modules/desktop/graphics/launchers.nix
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,22 @@
...
}: let
toDesktop = elem:
if !builtins.pathExists elem.icon
then throw "The icon's path ${elem.icon} doesn't exist"
else
makeDesktopItem {
inherit (elem) name icon;
genericName = elem.name;
desktopName = elem.name;
comment = "Secured Ghaf Application";
exec = elem.path;
};
(makeDesktopItem {
inherit (elem) name icon;
genericName = elem.name;
desktopName = elem.name;
comment = "Secured Ghaf Application";
exec = elem.path;
})
.overrideAttrs (prevAttrs: {
checkPhase =
prevAttrs.checkPhase
+ ''
# Check that the icon's path exists
[[ -f "${elem.icon}" ]] || (echo "The icon's path ${elem.icon} doesn't exist" && exit 1)
'';
});
in
pkgs.symlinkJoin {
name = "ghaf-desktop-entries";
Expand Down
1 change: 1 addition & 0 deletions modules/hardware/lenovo-x1/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@
{
imports = [
./definitions
./modules/fprint.nix
];
}
94 changes: 94 additions & 0 deletions modules/hardware/lenovo-x1/modules/fprint.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Copyright 2022-2024 TII (SSRC) and the Ghaf contributors
# SPDX-License-Identifier: Apache-2.0
{
config,
lib,
pkgs,
...
}: let
cfg = config.ghaf.hardware.fprint;
in
with lib; {
options.ghaf.hardware.fprint = {
enable = mkEnableOption "Enable fingerprint reader support";
qemuExtraArgs = mkOption {
type = types.listOf types.str;
default = [];
description = ''
Extra arguments to pass to Qemu when enabling the fingerprint reader.
This is useful for passing USB device information to Qemu.
'';
};
extraConfigurations = mkOption {
type = types.attrsOf types.anything;
default = {};
description = ''
Extra configurations to enable when enabling the fingerprint reader.
This is useful for enabling services and packages related to the fingerprint reader.
'';
};
};

config = mkIf cfg.enable {
ghaf.hardware.fprint = {
qemuExtraArgs = [
# Fingerprint reader
"-device"
"qemu-xhci"
"-device"
"usb-host,hostbus=3,hostport=6"
];

extraConfigurations = {
# Enable service and package for fingerprint reader
services.fprintd.enable = true;
environment.systemPackages = with pkgs; [fprintd];

# Enable polkit and add rules
ghaf.systemd.withPolkit = true;
security = {
polkit = {
enable = true;
debug = true;
# Polkit rules for fingerprint reader
extraConfig = ''
// Allow user to verify fingerprints
polkit.addRule(function(action, subject) {
if (action.id == "net.reactivated.fprint.device.verify" &&
subject.user == "ghaf") {
return polkit.Result.YES;
}
});
// Allow user to enroll fingerprints
polkit.addRule(function(action, subject) {
if (action.id == "net.reactivated.fprint.device.enroll" &&
subject.user == "ghaf") {
return polkit.Result.YES;
}
});
'';
};
# PAM rules for swaylock fingerprint reader
pam.services = {
swaylock.text = ''
# Account management.
account required pam_unix.so
# Authentication management.
auth sufficient pam_unix.so likeauth try_first_pass
auth sufficient ${pkgs.fprintd}/lib/security/pam_fprintd.so
auth required pam_deny.so
# Password management.
password sufficient pam_unix.so nullok sha512
# Session management.
session required pam_env.so conffile=/etc/pam/environment readenv=0
session required pam_unix.so
'';
};
};
};
};
};
}
42 changes: 42 additions & 0 deletions overlays/cross-compilation/chromium/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Copyright 2023-2024 TII (SSRC) and the Ghaf contributors
# SPDX-License-Identifier: Apache-2.0
#
# Chromium & Electron cross-compilation fixes
#
{
final,
prev,
}: let
inherit (builtins) map;
inherit (final.lib) pipe;
opusWithCustomModes = final.pkgsBuildBuild.libopus.override {
withCustomModes = true;
};
opusWithCustomModes' = final.pkgsBuildTarget.libopus.override {
withCustomModes = true;
};
replace = needle: replacement: haystack:
map (each:
if each == needle
then replacement
else each)
haystack;
in
prev.chromium.overrideAttrs (oa: {
passthru =
oa.passthru
// {
mkDerivation = fun:
oa.passthru.mkDerivation (finalAttrs:
{
depsBuildBuild = pipe finalAttrs.depsBuildBuild [
(replace (final.libpng.override {apngSupport = false;}) (final.pkgsBuildBuild.libpng.override {apngSupport = false;}))
(replace final.zlib final.pkgsBuildBuild.zlib)
(replace opusWithCustomModes opusWithCustomModes')
];
buildInputs = replace opusWithCustomModes' opusWithCustomModes finalAttrs.buildInputs;
env = finalAttrs.env // {NIX_DEBUG = "1";};
}
// fun finalAttrs);
};
})
1 change: 1 addition & 0 deletions overlays/cross-compilation/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
# This overlay is for specific fixes needed only to enable cross-compilation.
#
(final: prev: {
chromium = import ./chromium {inherit prev final;};
edk2 = import ./edk2 {inherit final prev;};
element-desktop = import ./element-desktop {inherit prev;};
jbig2dec = import ./jbig2dec {inherit prev;};
Expand Down
1 change: 1 addition & 0 deletions targets/lenovo-x1/everything.nix
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
hardware.x86_64.common.enable = true;
hardware.generation = generation;
hardware.tpm2.enable = true;
hardware.fprint.enable = true;

# Kernel hardening
host.kernel.hardening.enable = false;
Expand Down
44 changes: 24 additions & 20 deletions targets/lenovo-x1/guivmExtraModules.nix
Original file line number Diff line number Diff line change
Expand Up @@ -136,24 +136,28 @@
# Early KMS needed for GNOME to work inside GuiVM
boot.initrd.kernelModules = ["i915"];

microvm.qemu.extraArgs = [
# Lenovo X1 Lid button
"-device"
"button"
# Lenovo X1 battery
"-device"
"battery"
# Lenovo X1 AC adapter
"-device"
"acad"
# Connect sound device to hosts pulseaudio socket
"-audiodev"
"pa,id=pa1,server=unix:/run/pulse/native"
];
microvm.qemu.extraArgs =
[
# Lenovo X1 Lid button
"-device"
"button"
# Lenovo X1 battery
"-device"
"battery"
# Lenovo X1 AC adapter
"-device"
"acad"
# Connect sound device to hosts pulseaudio socket
"-audiodev"
"pa,id=pa1,server=unix:/run/pulse/native"
]
++ lib.optionals configH.ghaf.hardware.fprint.enable configH.ghaf.hardware.fprint.qemuExtraArgs;
};
in [
./sshkeys.nix
guivmPCIPassthroughModule
guivmVirtioInputHostEvdevModule
guivmExtraConfigurations
]
in
[
./sshkeys.nix
guivmPCIPassthroughModule
guivmVirtioInputHostEvdevModule
guivmExtraConfigurations
]
++ lib.optionals configH.ghaf.hardware.fprint.enable [configH.ghaf.hardware.fprint.extraConfigurations]

0 comments on commit d3455e8

Please sign in to comment.