diff options
Diffstat (limited to 'modules/luksroot.nix')
| -rw-r--r-- | modules/luksroot.nix | 1089 |
1 files changed, 0 insertions, 1089 deletions
diff --git a/modules/luksroot.nix b/modules/luksroot.nix deleted file mode 100644 index 52de2c40..00000000 --- a/modules/luksroot.nix +++ /dev/null | |||
| @@ -1,1089 +0,0 @@ | |||
| 1 | { config, lib, pkgs, ... }: | ||
| 2 | |||
| 3 | with lib; | ||
| 4 | |||
| 5 | let | ||
| 6 | luks = config.boot.initrd.luks; | ||
| 7 | kernelPackages = config.boot.kernelPackages; | ||
| 8 | |||
| 9 | commonFunctions = '' | ||
| 10 | die() { | ||
| 11 | echo "$@" >&2 | ||
| 12 | exit 1 | ||
| 13 | } | ||
| 14 | |||
| 15 | dev_exist() { | ||
| 16 | local target="$1" | ||
| 17 | if [ -e $target ]; then | ||
| 18 | return 0 | ||
| 19 | else | ||
| 20 | local uuid=$(echo -n $target | sed -e 's,UUID=\(.*\),\1,g') | ||
| 21 | blkid --uuid $uuid >/dev/null | ||
| 22 | return $? | ||
| 23 | fi | ||
| 24 | } | ||
| 25 | |||
| 26 | wait_target() { | ||
| 27 | local name="$1" | ||
| 28 | local target="$2" | ||
| 29 | local secs="''${3:-10}" | ||
| 30 | local desc="''${4:-$name $target to appear}" | ||
| 31 | |||
| 32 | if ! dev_exist $target; then | ||
| 33 | echo -n "Waiting $secs seconds for $desc..." | ||
| 34 | local success=false; | ||
| 35 | for try in $(seq $secs); do | ||
| 36 | echo -n "." | ||
| 37 | sleep 1 | ||
| 38 | if dev_exist $target; then | ||
| 39 | success=true | ||
| 40 | break | ||
| 41 | fi | ||
| 42 | done | ||
| 43 | if [ $success == true ]; then | ||
| 44 | echo " - success"; | ||
| 45 | return 0 | ||
| 46 | else | ||
| 47 | echo " - failure"; | ||
| 48 | return 1 | ||
| 49 | fi | ||
| 50 | fi | ||
| 51 | return 0 | ||
| 52 | } | ||
| 53 | |||
| 54 | wait_yubikey() { | ||
| 55 | local secs="''${1:-10}" | ||
| 56 | |||
| 57 | ykinfo -v 1>/dev/null 2>&1 | ||
| 58 | if [ $? != 0 ]; then | ||
| 59 | echo -n "Waiting $secs seconds for YubiKey to appear..." | ||
| 60 | local success=false | ||
| 61 | for try in $(seq $secs); do | ||
| 62 | echo -n . | ||
| 63 | sleep 1 | ||
| 64 | ykinfo -v 1>/dev/null 2>&1 | ||
| 65 | if [ $? == 0 ]; then | ||
| 66 | success=true | ||
| 67 | break | ||
| 68 | fi | ||
| 69 | done | ||
| 70 | if [ $success == true ]; then | ||
| 71 | echo " - success"; | ||
| 72 | return 0 | ||
| 73 | else | ||
| 74 | echo " - failure"; | ||
| 75 | return 1 | ||
| 76 | fi | ||
| 77 | fi | ||
| 78 | return 0 | ||
| 79 | } | ||
| 80 | |||
| 81 | wait_gpgcard() { | ||
| 82 | local secs="''${1:-10}" | ||
| 83 | |||
| 84 | gpg --card-status > /dev/null 2> /dev/null | ||
| 85 | if [ $? != 0 ]; then | ||
| 86 | echo -n "Waiting $secs seconds for GPG Card to appear" | ||
| 87 | local success=false | ||
| 88 | for try in $(seq $secs); do | ||
| 89 | echo -n . | ||
| 90 | sleep 1 | ||
| 91 | gpg --card-status > /dev/null 2> /dev/null | ||
| 92 | if [ $? == 0 ]; then | ||
| 93 | success=true | ||
| 94 | break | ||
| 95 | fi | ||
| 96 | done | ||
| 97 | if [ $success == true ]; then | ||
| 98 | echo " - success"; | ||
| 99 | return 0 | ||
| 100 | else | ||
| 101 | echo " - failure"; | ||
| 102 | return 1 | ||
| 103 | fi | ||
| 104 | fi | ||
| 105 | return 0 | ||
| 106 | } | ||
| 107 | ''; | ||
| 108 | |||
| 109 | preCommands = '' | ||
| 110 | # A place to store crypto things | ||
| 111 | |||
| 112 | # A ramfs is used here to ensure that the file used to update | ||
| 113 | # the key slot with cryptsetup will never get swapped out. | ||
| 114 | # Warning: Do NOT replace with tmpfs! | ||
| 115 | mkdir -p /crypt-ramfs | ||
| 116 | mount -t ramfs none /crypt-ramfs | ||
| 117 | |||
| 118 | # Cryptsetup locking directory | ||
| 119 | mkdir -p /run/cryptsetup | ||
| 120 | |||
| 121 | # For YubiKey salt storage | ||
| 122 | mkdir -p /crypt-storage | ||
| 123 | |||
| 124 | ${optionalString luks.gpgSupport '' | ||
| 125 | export GPG_TTY=$(tty) | ||
| 126 | export GNUPGHOME=/crypt-ramfs/.gnupg | ||
| 127 | |||
| 128 | gpg-agent --daemon --scdaemon-program $out/bin/scdaemon > /dev/null 2> /dev/null | ||
| 129 | ''} | ||
| 130 | |||
| 131 | # Disable all input echo for the whole stage. We could use read -s | ||
| 132 | # instead but that would ocasionally leak characters between read | ||
| 133 | # invocations. | ||
| 134 | stty -echo | ||
| 135 | ''; | ||
| 136 | |||
| 137 | postCommands = '' | ||
| 138 | stty echo | ||
| 139 | umount /crypt-storage 2>/dev/null | ||
| 140 | umount /crypt-ramfs 2>/dev/null | ||
| 141 | ''; | ||
| 142 | |||
| 143 | openCommand = name': { name, device, header, keyFile, keyFileSize, keyFileOffset, allowDiscards, bypassWorkqueues, yubikey, gpgCard, fido2, clevis, dmi, fallbackToPassword, preOpenCommands, postOpenCommands, ... }: assert name' == name; | ||
| 144 | let | ||
| 145 | csopen = "cryptsetup luksOpen ${device} ${name}" | ||
| 146 | + optionalString allowDiscards " --allow-discards" | ||
| 147 | + optionalString bypassWorkqueues " --perf-no_read_workqueue --perf-no_write_workqueue" | ||
| 148 | + optionalString (header != null) " --header=${header}"; | ||
| 149 | cschange = "cryptsetup luksChangeKey ${device} ${optionalString (header != null) "--header=${header}"}"; | ||
| 150 | in '' | ||
| 151 | # Wait for luksRoot (and optionally keyFile and/or header) to appear, e.g. | ||
| 152 | # if on a USB drive. | ||
| 153 | wait_target "device" ${device} || die "${device} is unavailable" | ||
| 154 | |||
| 155 | ${optionalString (header != null) '' | ||
| 156 | wait_target "header" ${header} || die "${header} is unavailable" | ||
| 157 | ''} | ||
| 158 | |||
| 159 | do_open_passphrase() { | ||
| 160 | local passphrase | ||
| 161 | |||
| 162 | while true; do | ||
| 163 | echo -n "Passphrase for ${device}: " | ||
| 164 | passphrase= | ||
| 165 | while true; do | ||
| 166 | if [ -e /crypt-ramfs/passphrase ]; then | ||
| 167 | echo "reused" | ||
| 168 | passphrase=$(cat /crypt-ramfs/passphrase) | ||
| 169 | break | ||
| 170 | else | ||
| 171 | # ask cryptsetup-askpass | ||
| 172 | echo -n "${device}" > /crypt-ramfs/device | ||
| 173 | |||
| 174 | # and try reading it from /dev/console with a timeout | ||
| 175 | IFS= read -t 1 -r passphrase | ||
| 176 | if [ -n "$passphrase" ]; then | ||
| 177 | ${if luks.reusePassphrases then '' | ||
| 178 | # remember it for the next device | ||
| 179 | echo -n "$passphrase" > /crypt-ramfs/passphrase | ||
| 180 | '' else '' | ||
| 181 | # Don't save it to ramfs. We are very paranoid | ||
| 182 | ''} | ||
| 183 | echo | ||
| 184 | break | ||
| 185 | fi | ||
| 186 | fi | ||
| 187 | done | ||
| 188 | echo -n "Verifying passphrase for ${device}..." | ||
| 189 | echo -n "$passphrase" | ${csopen} --key-file=- | ||
| 190 | if [ $? == 0 ]; then | ||
| 191 | echo " - success" | ||
| 192 | ${if luks.reusePassphrases then '' | ||
| 193 | # we don't rm here because we might reuse it for the next device | ||
| 194 | '' else '' | ||
| 195 | rm -f /crypt-ramfs/passphrase | ||
| 196 | ''} | ||
| 197 | break | ||
| 198 | else | ||
| 199 | echo " - failure" | ||
| 200 | # ask for a different one | ||
| 201 | rm -f /crypt-ramfs/passphrase | ||
| 202 | fi | ||
| 203 | done | ||
| 204 | } | ||
| 205 | |||
| 206 | # LUKS | ||
| 207 | open_normally() { | ||
| 208 | ${if (keyFile != null) then '' | ||
| 209 | if wait_target "key file" ${keyFile}; then | ||
| 210 | ${csopen} --key-file=${keyFile} \ | ||
| 211 | ${optionalString (keyFileSize != null) "--keyfile-size=${toString keyFileSize}"} \ | ||
| 212 | ${optionalString (keyFileOffset != null) "--keyfile-offset=${toString keyFileOffset}"} | ||
| 213 | else | ||
| 214 | ${if fallbackToPassword then "echo" else "die"} "${keyFile} is unavailable" | ||
| 215 | echo " - failing back to interactive password prompt" | ||
| 216 | do_open_passphrase | ||
| 217 | fi | ||
| 218 | '' else '' | ||
| 219 | do_open_passphrase | ||
| 220 | ''} | ||
| 221 | } | ||
| 222 | |||
| 223 | ${optionalString (luks.yubikeySupport && (yubikey != null)) '' | ||
| 224 | # YubiKey | ||
| 225 | rbtohex() { | ||
| 226 | ( od -An -vtx1 | tr -d ' \n' ) | ||
| 227 | } | ||
| 228 | |||
| 229 | hextorb() { | ||
| 230 | ( tr '[:lower:]' '[:upper:]' | sed -e 's/\([0-9A-F]\{2\}\)/\\\\\\x\1/gI' | xargs printf ) | ||
| 231 | } | ||
| 232 | |||
| 233 | do_open_yubikey() { | ||
| 234 | # Make all of these local to this function | ||
| 235 | # to prevent their values being leaked | ||
| 236 | local salt | ||
| 237 | local iterations | ||
| 238 | local k_user | ||
| 239 | local challenge | ||
| 240 | local response | ||
| 241 | local k_luks | ||
| 242 | local opened | ||
| 243 | local new_salt | ||
| 244 | local new_iterations | ||
| 245 | local new_challenge | ||
| 246 | local new_response | ||
| 247 | local new_k_luks | ||
| 248 | |||
| 249 | mount -t ${yubikey.storage.fsType} ${yubikey.storage.device} /crypt-storage || \ | ||
| 250 | die "Failed to mount YubiKey salt storage device" | ||
| 251 | |||
| 252 | salt="$(cat /crypt-storage${yubikey.storage.path} | sed -n 1p | tr -d '\n')" | ||
| 253 | iterations="$(cat /crypt-storage${yubikey.storage.path} | sed -n 2p | tr -d '\n')" | ||
| 254 | challenge="$(echo -n $salt | openssl-wrap dgst -binary -sha512 | rbtohex)" | ||
| 255 | response="$(ykchalresp -${toString yubikey.slot} -x $challenge 2>/dev/null)" | ||
| 256 | |||
| 257 | for try in $(seq 3); do | ||
| 258 | ${optionalString yubikey.twoFactor '' | ||
| 259 | echo -n "Enter two-factor passphrase: " | ||
| 260 | k_user= | ||
| 261 | while true; do | ||
| 262 | if [ -e /crypt-ramfs/passphrase ]; then | ||
| 263 | echo "reused" | ||
| 264 | k_user=$(cat /crypt-ramfs/passphrase) | ||
| 265 | break | ||
| 266 | else | ||
| 267 | # Try reading it from /dev/console with a timeout | ||
| 268 | IFS= read -t 1 -r k_user | ||
| 269 | if [ -n "$k_user" ]; then | ||
| 270 | ${if luks.reusePassphrases then '' | ||
| 271 | # Remember it for the next device | ||
| 272 | echo -n "$k_user" > /crypt-ramfs/passphrase | ||
| 273 | '' else '' | ||
| 274 | # Don't save it to ramfs. We are very paranoid | ||
| 275 | ''} | ||
| 276 | echo | ||
| 277 | break | ||
| 278 | fi | ||
| 279 | fi | ||
| 280 | done | ||
| 281 | ''} | ||
| 282 | |||
| 283 | if [ ! -z "$k_user" ]; then | ||
| 284 | k_luks="$(echo -n $k_user | pbkdf2-sha512 ${toString yubikey.keyLength} $iterations $response | rbtohex)" | ||
| 285 | else | ||
| 286 | k_luks="$(echo | pbkdf2-sha512 ${toString yubikey.keyLength} $iterations $response | rbtohex)" | ||
| 287 | fi | ||
| 288 | |||
| 289 | echo -n "$k_luks" | hextorb | ${csopen} --key-file=- | ||
| 290 | |||
| 291 | if [ $? == 0 ]; then | ||
| 292 | opened=true | ||
| 293 | ${if luks.reusePassphrases then '' | ||
| 294 | # We don't rm here because we might reuse it for the next device | ||
| 295 | '' else '' | ||
| 296 | rm -f /crypt-ramfs/passphrase | ||
| 297 | ''} | ||
| 298 | break | ||
| 299 | else | ||
| 300 | opened=false | ||
| 301 | echo "Authentication failed!" | ||
| 302 | fi | ||
| 303 | done | ||
| 304 | |||
| 305 | [ "$opened" == false ] && die "Maximum authentication errors reached" | ||
| 306 | |||
| 307 | echo -n "Gathering entropy for new salt (please enter random keys to generate entropy if this blocks for long)..." | ||
| 308 | for i in $(seq ${toString yubikey.saltLength}); do | ||
| 309 | byte="$(dd if=/dev/random bs=1 count=1 2>/dev/null | rbtohex)"; | ||
| 310 | new_salt="$new_salt$byte"; | ||
| 311 | echo -n . | ||
| 312 | done; | ||
| 313 | echo "ok" | ||
| 314 | |||
| 315 | new_iterations="$iterations" | ||
| 316 | ${optionalString (yubikey.iterationStep > 0) '' | ||
| 317 | new_iterations="$(($new_iterations + ${toString yubikey.iterationStep}))" | ||
| 318 | ''} | ||
| 319 | |||
| 320 | new_challenge="$(echo -n $new_salt | openssl-wrap dgst -binary -sha512 | rbtohex)" | ||
| 321 | |||
| 322 | new_response="$(ykchalresp -${toString yubikey.slot} -x $new_challenge 2>/dev/null)" | ||
| 323 | |||
| 324 | if [ ! -z "$k_user" ]; then | ||
| 325 | new_k_luks="$(echo -n $k_user | pbkdf2-sha512 ${toString yubikey.keyLength} $new_iterations $new_response | rbtohex)" | ||
| 326 | else | ||
| 327 | new_k_luks="$(echo | pbkdf2-sha512 ${toString yubikey.keyLength} $new_iterations $new_response | rbtohex)" | ||
| 328 | fi | ||
| 329 | |||
| 330 | echo -n "$new_k_luks" | hextorb > /crypt-ramfs/new_key | ||
| 331 | echo -n "$k_luks" | hextorb | ${cschange} --key-file=- /crypt-ramfs/new_key | ||
| 332 | |||
| 333 | if [ $? == 0 ]; then | ||
| 334 | echo -ne "$new_salt\n$new_iterations" > /crypt-storage${yubikey.storage.path} | ||
| 335 | else | ||
| 336 | echo "Warning: Could not update LUKS key, current challenge persists!" | ||
| 337 | fi | ||
| 338 | |||
| 339 | rm -f /crypt-ramfs/new_key | ||
| 340 | umount /crypt-storage | ||
| 341 | } | ||
| 342 | |||
| 343 | open_with_hardware() { | ||
| 344 | if wait_yubikey ${toString yubikey.gracePeriod}; then | ||
| 345 | do_open_yubikey | ||
| 346 | else | ||
| 347 | echo "No YubiKey found, falling back to non-YubiKey open procedure" | ||
| 348 | open_normally | ||
| 349 | fi | ||
| 350 | } | ||
| 351 | ''} | ||
| 352 | |||
| 353 | ${optionalString (luks.gpgSupport && (gpgCard != null)) '' | ||
| 354 | |||
| 355 | do_open_gpg_card() { | ||
| 356 | # Make all of these local to this function | ||
| 357 | # to prevent their values being leaked | ||
| 358 | local pin | ||
| 359 | local opened | ||
| 360 | |||
| 361 | gpg --import /gpg-keys/${device}/pubkey.asc > /dev/null 2> /dev/null | ||
| 362 | |||
| 363 | gpg --card-status > /dev/null 2> /dev/null | ||
| 364 | |||
| 365 | for try in $(seq 3); do | ||
| 366 | echo -n "PIN for GPG Card associated with device ${device}: " | ||
| 367 | pin= | ||
| 368 | while true; do | ||
| 369 | if [ -e /crypt-ramfs/passphrase ]; then | ||
| 370 | echo "reused" | ||
| 371 | pin=$(cat /crypt-ramfs/passphrase) | ||
| 372 | break | ||
| 373 | else | ||
| 374 | # and try reading it from /dev/console with a timeout | ||
| 375 | IFS= read -t 1 -r pin | ||
| 376 | if [ -n "$pin" ]; then | ||
| 377 | ${if luks.reusePassphrases then '' | ||
| 378 | # remember it for the next device | ||
| 379 | echo -n "$pin" > /crypt-ramfs/passphrase | ||
| 380 | '' else '' | ||
| 381 | # Don't save it to ramfs. We are very paranoid | ||
| 382 | ''} | ||
| 383 | echo | ||
| 384 | break | ||
| 385 | fi | ||
| 386 | fi | ||
| 387 | done | ||
| 388 | echo -n "Verifying passphrase for ${device}..." | ||
| 389 | echo -n "$pin" | gpg -q --batch --passphrase-fd 0 --pinentry-mode loopback -d /gpg-keys/${device}/cryptkey.gpg 2> /dev/null | ${csopen} --key-file=- > /dev/null 2> /dev/null | ||
| 390 | if [ $? == 0 ]; then | ||
| 391 | echo " - success" | ||
| 392 | ${if luks.reusePassphrases then '' | ||
| 393 | # we don't rm here because we might reuse it for the next device | ||
| 394 | '' else '' | ||
| 395 | rm -f /crypt-ramfs/passphrase | ||
| 396 | ''} | ||
| 397 | break | ||
| 398 | else | ||
| 399 | echo " - failure" | ||
| 400 | # ask for a different one | ||
| 401 | rm -f /crypt-ramfs/passphrase | ||
| 402 | fi | ||
| 403 | done | ||
| 404 | |||
| 405 | [ "$opened" == false ] && die "Maximum authentication errors reached" | ||
| 406 | } | ||
| 407 | |||
| 408 | open_with_hardware() { | ||
| 409 | if wait_gpgcard ${toString gpgCard.gracePeriod}; then | ||
| 410 | do_open_gpg_card | ||
| 411 | else | ||
| 412 | echo "No GPG Card found, falling back to normal open procedure" | ||
| 413 | open_normally | ||
| 414 | fi | ||
| 415 | } | ||
| 416 | ''} | ||
| 417 | |||
| 418 | ${optionalString (luks.fido2Support && (fido2.credential != null)) '' | ||
| 419 | |||
| 420 | open_with_hardware() { | ||
| 421 | local passsphrase | ||
| 422 | |||
| 423 | ${if fido2.passwordLess then '' | ||
| 424 | export passphrase="" | ||
| 425 | '' else '' | ||
| 426 | read -rsp "FIDO2 salt for ${device}: " passphrase | ||
| 427 | echo | ||
| 428 | ''} | ||
| 429 | ${optionalString (lib.versionOlder kernelPackages.kernel.version "5.4") '' | ||
| 430 | echo "On systems with Linux Kernel < 5.4, it might take a while to initialize the CRNG, you might want to use linuxPackages_latest." | ||
| 431 | echo "Please move your mouse to create needed randomness." | ||
| 432 | ''} | ||
| 433 | echo "Waiting for your FIDO2 device..." | ||
| 434 | fido2luks open ${device} ${name} ${fido2.credential} --await-dev ${toString fido2.gracePeriod} --salt string:$passphrase | ||
| 435 | if [ $? -ne 0 ]; then | ||
| 436 | echo "No FIDO2 key found, falling back to normal open procedure" | ||
| 437 | open_normally | ||
| 438 | fi | ||
| 439 | } | ||
| 440 | ''} | ||
| 441 | |||
| 442 | ${optionalString (luks.clevisSupport && clevis) '' | ||
| 443 | |||
| 444 | open_with_hardware() { | ||
| 445 | mkdir -p /crypt-ramfs/clevis | ||
| 446 | |||
| 447 | TMPDIR=/crypt-ramfs/clevis clevis luks unlock -d ${device} -n ${name} | ||
| 448 | |||
| 449 | if [ $? -ne 0 ]; then | ||
| 450 | echo "Unlocking with clevis failed, falling back to normal open procedure" | ||
| 451 | open_normally | ||
| 452 | fi | ||
| 453 | } | ||
| 454 | |||
| 455 | ''} | ||
| 456 | |||
| 457 | ${optionalString (luks.dmiSupport && dmi) '' | ||
| 458 | |||
| 459 | open_with_hardware() { | ||
| 460 | dmidecode -s system-uuid > /crypt-ramfs/passphrase | ||
| 461 | |||
| 462 | ${csopen} --key-file=- < /crypt-ramfs/passphrase > /dev/null 2> /dev/null | ||
| 463 | |||
| 464 | if [ $? -ne 0 ]; then | ||
| 465 | echo "Unlocking with system-uuid failed, falling back to normal open procedure" | ||
| 466 | rm -f /crypt-ramfs/passphrase | ||
| 467 | open_normally | ||
| 468 | ${optionalString (!luks.reusePassphrases) '' | ||
| 469 | else | ||
| 470 | rm -f /crypt-ramfs/passphrase | ||
| 471 | ''} | ||
| 472 | fi | ||
| 473 | } | ||
| 474 | |||
| 475 | ''} | ||
| 476 | |||
| 477 | # commands to run right before we mount our device | ||
| 478 | ${preOpenCommands} | ||
| 479 | |||
| 480 | ${if (luks.yubikeySupport && (yubikey != null)) || (luks.gpgSupport && (gpgCard != null)) || (luks.fido2Support && (fido2.credential != null)) || (luks.clevisSupport && clevis) || (luks.dmiSupport && dmi) then '' | ||
| 481 | open_with_hardware | ||
| 482 | '' else '' | ||
| 483 | open_normally | ||
| 484 | ''} | ||
| 485 | |||
| 486 | # commands to run right after we mounted our device | ||
| 487 | ${postOpenCommands} | ||
| 488 | ''; | ||
| 489 | |||
| 490 | askPass = pkgs.writeScriptBin "cryptsetup-askpass" '' | ||
| 491 | #!/bin/sh | ||
| 492 | |||
| 493 | ${commonFunctions} | ||
| 494 | |||
| 495 | while true; do | ||
| 496 | wait_target "luks" /crypt-ramfs/device 10 "LUKS to request a passphrase" || die "Passphrase is not requested now" | ||
| 497 | device=$(cat /crypt-ramfs/device) | ||
| 498 | |||
| 499 | echo -n "Passphrase for $device: " | ||
| 500 | IFS= read -rs passphrase | ||
| 501 | echo | ||
| 502 | |||
| 503 | rm /crypt-ramfs/device | ||
| 504 | echo -n "$passphrase" > /crypt-ramfs/passphrase | ||
| 505 | done | ||
| 506 | ''; | ||
| 507 | |||
| 508 | preLVM = filterAttrs (n: v: v.preLVM) luks.devices; | ||
| 509 | postLVM = filterAttrs (n: v: !v.preLVM) luks.devices; | ||
| 510 | |||
| 511 | in | ||
| 512 | { | ||
| 513 | disabledModules = [ "system/boot/luksroot.nix" ]; | ||
| 514 | |||
| 515 | imports = [ | ||
| 516 | (mkRemovedOptionModule [ "boot" "initrd" "luks" "enable" ] "") | ||
| 517 | ]; | ||
| 518 | |||
| 519 | options = { | ||
| 520 | |||
| 521 | boot.initrd.luks.mitigateDMAAttacks = mkOption { | ||
| 522 | type = types.bool; | ||
| 523 | default = true; | ||
| 524 | description = '' | ||
| 525 | Unless enabled, encryption keys can be easily recovered by an attacker with physical | ||
| 526 | access to any machine with PCMCIA, ExpressCard, ThunderBolt or FireWire port. | ||
| 527 | More information is available at <link xlink:href="http://en.wikipedia.org/wiki/DMA_attack"/>. | ||
| 528 | |||
| 529 | This option blacklists FireWire drivers, but doesn't remove them. You can manually | ||
| 530 | load the drivers if you need to use a FireWire device, but don't forget to unload them! | ||
| 531 | ''; | ||
| 532 | }; | ||
| 533 | |||
| 534 | boot.initrd.luks.cryptoModules = mkOption { | ||
| 535 | type = types.listOf types.str; | ||
| 536 | default = | ||
| 537 | [ "aes" "aes_generic" "blowfish" "twofish" | ||
| 538 | "serpent" "cbc" "xts" "lrw" "sha1" "sha256" "sha512" | ||
| 539 | "af_alg" "algif_skcipher" | ||
| 540 | ]; | ||
| 541 | description = '' | ||
| 542 | A list of cryptographic kernel modules needed to decrypt the root device(s). | ||
| 543 | The default includes all common modules. | ||
| 544 | ''; | ||
| 545 | }; | ||
| 546 | |||
| 547 | boot.initrd.luks.forceLuksSupportInInitrd = mkOption { | ||
| 548 | type = types.bool; | ||
| 549 | default = false; | ||
| 550 | internal = true; | ||
| 551 | description = '' | ||
| 552 | Whether to configure luks support in the initrd, when no luks | ||
| 553 | devices are configured. | ||
| 554 | ''; | ||
| 555 | }; | ||
| 556 | |||
| 557 | boot.initrd.luks.reusePassphrases = mkOption { | ||
| 558 | type = types.bool; | ||
| 559 | default = true; | ||
| 560 | description = '' | ||
| 561 | When opening a new LUKS device try reusing last successful | ||
| 562 | passphrase. | ||
| 563 | |||
| 564 | Useful for mounting a number of devices that use the same | ||
| 565 | passphrase without retyping it several times. | ||
| 566 | |||
| 567 | Such setup can be useful if you use <command>cryptsetup | ||
| 568 | luksSuspend</command>. Different LUKS devices will still have | ||
| 569 | different master keys even when using the same passphrase. | ||
| 570 | ''; | ||
| 571 | }; | ||
| 572 | |||
| 573 | boot.initrd.luks.devices = mkOption { | ||
| 574 | default = { }; | ||
| 575 | example = { luksroot.device = "/dev/disk/by-uuid/430e9eff-d852-4f68-aa3b-2fa3599ebe08"; }; | ||
| 576 | description = '' | ||
| 577 | The encrypted disk that should be opened before the root | ||
| 578 | filesystem is mounted. Both LVM-over-LUKS and LUKS-over-LVM | ||
| 579 | setups are supported. The unencrypted devices can be accessed as | ||
| 580 | <filename>/dev/mapper/<replaceable>name</replaceable></filename>. | ||
| 581 | ''; | ||
| 582 | |||
| 583 | type = with types; attrsOf (submodule ( | ||
| 584 | { name, ... }: { options = { | ||
| 585 | |||
| 586 | name = mkOption { | ||
| 587 | visible = false; | ||
| 588 | default = name; | ||
| 589 | example = "luksroot"; | ||
| 590 | type = types.str; | ||
| 591 | description = "Name of the unencrypted device in <filename>/dev/mapper</filename>."; | ||
| 592 | }; | ||
| 593 | |||
| 594 | device = mkOption { | ||
| 595 | example = "/dev/disk/by-uuid/430e9eff-d852-4f68-aa3b-2fa3599ebe08"; | ||
| 596 | type = types.str; | ||
| 597 | description = "Path of the underlying encrypted block device."; | ||
| 598 | }; | ||
| 599 | |||
| 600 | header = mkOption { | ||
| 601 | default = null; | ||
| 602 | example = "/root/header.img"; | ||
| 603 | type = types.nullOr types.str; | ||
| 604 | description = '' | ||
| 605 | The name of the file or block device that | ||
| 606 | should be used as header for the encrypted device. | ||
| 607 | ''; | ||
| 608 | }; | ||
| 609 | |||
| 610 | keyFile = mkOption { | ||
| 611 | default = null; | ||
| 612 | example = "/dev/sdb1"; | ||
| 613 | type = types.nullOr types.str; | ||
| 614 | description = '' | ||
| 615 | The name of the file (can be a raw device or a partition) that | ||
| 616 | should be used as the decryption key for the encrypted device. If | ||
| 617 | not specified, you will be prompted for a passphrase instead. | ||
| 618 | ''; | ||
| 619 | }; | ||
| 620 | |||
| 621 | keyFileSize = mkOption { | ||
| 622 | default = null; | ||
| 623 | example = 4096; | ||
| 624 | type = types.nullOr types.int; | ||
| 625 | description = '' | ||
| 626 | The size of the key file. Use this if only the beginning of the | ||
| 627 | key file should be used as a key (often the case if a raw device | ||
| 628 | or partition is used as key file). If not specified, the whole | ||
| 629 | <literal>keyFile</literal> will be used decryption, instead of just | ||
| 630 | the first <literal>keyFileSize</literal> bytes. | ||
| 631 | ''; | ||
| 632 | }; | ||
| 633 | |||
| 634 | keyFileOffset = mkOption { | ||
| 635 | default = null; | ||
| 636 | example = 4096; | ||
| 637 | type = types.nullOr types.int; | ||
| 638 | description = '' | ||
| 639 | The offset of the key file. Use this in combination with | ||
| 640 | <literal>keyFileSize</literal> to use part of a file as key file | ||
| 641 | (often the case if a raw device or partition is used as a key file). | ||
| 642 | If not specified, the key begins at the first byte of | ||
| 643 | <literal>keyFile</literal>. | ||
| 644 | ''; | ||
| 645 | }; | ||
| 646 | |||
| 647 | # FIXME: get rid of this option. | ||
| 648 | preLVM = mkOption { | ||
| 649 | default = true; | ||
| 650 | type = types.bool; | ||
| 651 | description = "Whether the luksOpen will be attempted before LVM scan or after it."; | ||
| 652 | }; | ||
| 653 | |||
| 654 | allowDiscards = mkOption { | ||
| 655 | default = false; | ||
| 656 | type = types.bool; | ||
| 657 | description = '' | ||
| 658 | Whether to allow TRIM requests to the underlying device. This option | ||
| 659 | has security implications; please read the LUKS documentation before | ||
| 660 | activating it. | ||
| 661 | ''; | ||
| 662 | }; | ||
| 663 | |||
| 664 | bypassWorkqueues = mkOption { | ||
| 665 | default = false; | ||
| 666 | type = types.bool; | ||
| 667 | description = '' | ||
| 668 | Whether to bypass dm-crypt's internal read and write workqueues. | ||
| 669 | Enabling this should improve performance on SSDs; see | ||
| 670 | <link xlink:href="https://wiki.archlinux.org/index.php/Dm-crypt/Specialties#Disable_workqueue_for_increased_solid_state_drive_(SSD)_performance">here</link> | ||
| 671 | for more information. Needs Linux 5.9 or later. | ||
| 672 | ''; | ||
| 673 | }; | ||
| 674 | |||
| 675 | fallbackToPassword = mkOption { | ||
| 676 | default = false; | ||
| 677 | type = types.bool; | ||
| 678 | description = '' | ||
| 679 | Whether to fallback to interactive passphrase prompt if the keyfile | ||
| 680 | cannot be found. This will prevent unattended boot should the keyfile | ||
| 681 | go missing. | ||
| 682 | ''; | ||
| 683 | }; | ||
| 684 | |||
| 685 | gpgCard = mkOption { | ||
| 686 | default = null; | ||
| 687 | description = '' | ||
| 688 | The option to use this LUKS device with a GPG encrypted luks password by the GPG Smartcard. | ||
| 689 | If null (the default), GPG-Smartcard will be disabled for this device. | ||
| 690 | ''; | ||
| 691 | |||
| 692 | type = with types; nullOr (submodule { | ||
| 693 | options = { | ||
| 694 | gracePeriod = mkOption { | ||
| 695 | default = 10; | ||
| 696 | type = types.int; | ||
| 697 | description = "Time in seconds to wait for the GPG Smartcard."; | ||
| 698 | }; | ||
| 699 | |||
| 700 | encryptedPass = mkOption { | ||
| 701 | default = ""; | ||
| 702 | type = types.path; | ||
| 703 | description = "Path to the GPG encrypted passphrase."; | ||
| 704 | }; | ||
| 705 | |||
| 706 | publicKey = mkOption { | ||
| 707 | default = ""; | ||
| 708 | type = types.path; | ||
| 709 | description = "Path to the Public Key."; | ||
| 710 | }; | ||
| 711 | }; | ||
| 712 | }); | ||
| 713 | }; | ||
| 714 | |||
| 715 | fido2 = { | ||
| 716 | credential = mkOption { | ||
| 717 | default = null; | ||
| 718 | example = "f1d00200d8dc783f7fb1e10ace8da27f8312d72692abfca2f7e4960a73f48e82e1f7571f6ebfcee9fb434f9886ccc8fcc52a6614d8d2"; | ||
| 719 | type = types.nullOr types.str; | ||
| 720 | description = "The FIDO2 credential ID."; | ||
| 721 | }; | ||
| 722 | |||
| 723 | gracePeriod = mkOption { | ||
| 724 | default = 10; | ||
| 725 | type = types.int; | ||
| 726 | description = "Time in seconds to wait for the FIDO2 key."; | ||
| 727 | }; | ||
| 728 | |||
| 729 | passwordLess = mkOption { | ||
| 730 | default = false; | ||
| 731 | type = types.bool; | ||
| 732 | description = '' | ||
| 733 | Defines whatever to use an empty string as a default salt. | ||
| 734 | |||
| 735 | Enable only when your device is PIN protected, such as <link xlink:href="https://trezor.io/">Trezor</link>. | ||
| 736 | ''; | ||
| 737 | }; | ||
| 738 | }; | ||
| 739 | |||
| 740 | yubikey = mkOption { | ||
| 741 | default = null; | ||
| 742 | description = '' | ||
| 743 | The options to use for this LUKS device in YubiKey-PBA. | ||
| 744 | If null (the default), YubiKey-PBA will be disabled for this device. | ||
| 745 | ''; | ||
| 746 | |||
| 747 | type = with types; nullOr (submodule { | ||
| 748 | options = { | ||
| 749 | twoFactor = mkOption { | ||
| 750 | default = true; | ||
| 751 | type = types.bool; | ||
| 752 | description = "Whether to use a passphrase and a YubiKey (true), or only a YubiKey (false)."; | ||
| 753 | }; | ||
| 754 | |||
| 755 | slot = mkOption { | ||
| 756 | default = 2; | ||
| 757 | type = types.int; | ||
| 758 | description = "Which slot on the YubiKey to challenge."; | ||
| 759 | }; | ||
| 760 | |||
| 761 | saltLength = mkOption { | ||
| 762 | default = 16; | ||
| 763 | type = types.int; | ||
| 764 | description = "Length of the new salt in byte (64 is the effective maximum)."; | ||
| 765 | }; | ||
| 766 | |||
| 767 | keyLength = mkOption { | ||
| 768 | default = 64; | ||
| 769 | type = types.int; | ||
| 770 | description = "Length of the LUKS slot key derived with PBKDF2 in byte."; | ||
| 771 | }; | ||
| 772 | |||
| 773 | iterationStep = mkOption { | ||
| 774 | default = 0; | ||
| 775 | type = types.int; | ||
| 776 | description = "How much the iteration count for PBKDF2 is increased at each successful authentication."; | ||
| 777 | }; | ||
| 778 | |||
| 779 | gracePeriod = mkOption { | ||
| 780 | default = 10; | ||
| 781 | type = types.int; | ||
| 782 | description = "Time in seconds to wait for the YubiKey."; | ||
| 783 | }; | ||
| 784 | |||
| 785 | /* TODO: Add to the documentation of the current module: | ||
| 786 | |||
| 787 | Options related to the storing the salt. | ||
| 788 | */ | ||
| 789 | storage = { | ||
| 790 | device = mkOption { | ||
| 791 | default = "/dev/sda1"; | ||
| 792 | type = types.path; | ||
| 793 | description = '' | ||
| 794 | An unencrypted device that will temporarily be mounted in stage-1. | ||
| 795 | Must contain the current salt to create the challenge for this LUKS device. | ||
| 796 | ''; | ||
| 797 | }; | ||
| 798 | |||
| 799 | fsType = mkOption { | ||
| 800 | default = "vfat"; | ||
| 801 | type = types.str; | ||
| 802 | description = "The filesystem of the unencrypted device."; | ||
| 803 | }; | ||
| 804 | |||
| 805 | path = mkOption { | ||
| 806 | default = "/crypt-storage/default"; | ||
| 807 | type = types.str; | ||
| 808 | description = '' | ||
| 809 | Absolute path of the salt on the unencrypted device with | ||
| 810 | that device's root directory as "/". | ||
| 811 | ''; | ||
| 812 | }; | ||
| 813 | }; | ||
| 814 | }; | ||
| 815 | }); | ||
| 816 | }; | ||
| 817 | |||
| 818 | clevis = mkOption { | ||
| 819 | type = types.bool; | ||
| 820 | default = false; | ||
| 821 | description = '' | ||
| 822 | Unlock device via clevis (e.g. with a tpm) | ||
| 823 | ''; | ||
| 824 | }; | ||
| 825 | |||
| 826 | dmi = mkOption { | ||
| 827 | type = types.bool; | ||
| 828 | default = false; | ||
| 829 | description = '' | ||
| 830 | Unlock device via system-uuid (via dmidecode) | ||
| 831 | ''; | ||
| 832 | }; | ||
| 833 | |||
| 834 | preOpenCommands = mkOption { | ||
| 835 | type = types.lines; | ||
| 836 | default = ""; | ||
| 837 | example = '' | ||
| 838 | mkdir -p /tmp/persistent | ||
| 839 | mount -t zfs rpool/safe/persistent /tmp/persistent | ||
| 840 | ''; | ||
| 841 | description = '' | ||
| 842 | Commands that should be run right before we try to mount our LUKS device. | ||
| 843 | This can be useful, if the keys needed to open the drive is on another partion. | ||
| 844 | ''; | ||
| 845 | }; | ||
| 846 | |||
| 847 | postOpenCommands = mkOption { | ||
| 848 | type = types.lines; | ||
| 849 | default = ""; | ||
| 850 | example = '' | ||
| 851 | umount /tmp/persistent | ||
| 852 | ''; | ||
| 853 | description = '' | ||
| 854 | Commands that should be run right after we have mounted our LUKS device. | ||
| 855 | ''; | ||
| 856 | }; | ||
| 857 | }; | ||
| 858 | })); | ||
| 859 | }; | ||
| 860 | |||
| 861 | boot.initrd.luks.gpgSupport = mkOption { | ||
| 862 | default = false; | ||
| 863 | type = types.bool; | ||
| 864 | description = '' | ||
| 865 | Enables support for authenticating with a GPG encrypted password. | ||
| 866 | ''; | ||
| 867 | }; | ||
| 868 | |||
| 869 | boot.initrd.luks.yubikeySupport = mkOption { | ||
| 870 | default = false; | ||
| 871 | type = types.bool; | ||
| 872 | description = '' | ||
| 873 | Enables support for authenticating with a YubiKey on LUKS devices. | ||
| 874 | See the NixOS wiki for information on how to properly setup a LUKS device | ||
| 875 | and a YubiKey to work with this feature. | ||
| 876 | ''; | ||
| 877 | }; | ||
| 878 | |||
| 879 | boot.initrd.luks.fido2Support = mkOption { | ||
| 880 | default = false; | ||
| 881 | type = types.bool; | ||
| 882 | description = '' | ||
| 883 | Enables support for authenticating with FIDO2 devices. | ||
| 884 | ''; | ||
| 885 | }; | ||
| 886 | |||
| 887 | boot.initrd.luks.clevisSupport = mkOption { | ||
| 888 | default = false; | ||
| 889 | type = types.bool; | ||
| 890 | description = '' | ||
| 891 | Enables support for unlocking luks volumes via clevis (e.g. with a tpm) | ||
| 892 | ''; | ||
| 893 | }; | ||
| 894 | |||
| 895 | boot.initrd.luks.dmiSupport = mkOption { | ||
| 896 | default = false; | ||
| 897 | type = types.bool; | ||
| 898 | description = '' | ||
| 899 | Enables support for unlocking luks volumes via system-uuid (via dmidecode) | ||
| 900 | ''; | ||
| 901 | }; | ||
| 902 | |||
| 903 | }; | ||
| 904 | |||
| 905 | config = mkIf (luks.devices != {} || luks.forceLuksSupportInInitrd) { | ||
| 906 | |||
| 907 | assertions = | ||
| 908 | [ { assertion = !(luks.gpgSupport && luks.yubikeySupport); | ||
| 909 | message = "YubiKey and GPG Card may not be used at the same time."; | ||
| 910 | } | ||
| 911 | |||
| 912 | { assertion = !(luks.gpgSupport && luks.fido2Support); | ||
| 913 | message = "FIDO2 and GPG Card may not be used at the same time."; | ||
| 914 | } | ||
| 915 | |||
| 916 | { assertion = !(luks.gpgSupport && luks.clevisSupport); | ||
| 917 | message = "Clevis and GPG Card may not be used at the same time."; | ||
| 918 | } | ||
| 919 | |||
| 920 | { assertion = !(luks.gpgSupport && luks.dmiSupport); | ||
| 921 | message = "DMI and GPG Card may not be used at the same time."; | ||
| 922 | } | ||
| 923 | |||
| 924 | { assertion = !(luks.fido2Support && luks.yubikeySupport); | ||
| 925 | message = "FIDO2 and YubiKey may not be used at the same time."; | ||
| 926 | } | ||
| 927 | |||
| 928 | { assertion = !(luks.fido2Support && luks.clevisSupport); | ||
| 929 | message = "FIDO2 and Clevis may not be used at the same time."; | ||
| 930 | } | ||
| 931 | |||
| 932 | { assertion = !(luks.fido2Support && luks.dmiSupport); | ||
| 933 | message = "FIDO2 and DMI may not be used at the same time."; | ||
| 934 | } | ||
| 935 | |||
| 936 | { assertion = !(luks.yubikeySupport && luks.clevisSupport); | ||
| 937 | message = "Clevis and YubiKey may not be used at the same time."; | ||
| 938 | } | ||
| 939 | |||
| 940 | { assertion = !(luks.yubikeySupport && luks.dmiSupport); | ||
| 941 | message = "DMI and YubiKey may not be used at the same time."; | ||
| 942 | } | ||
| 943 | |||
| 944 | ]; | ||
| 945 | |||
| 946 | # actually, sbp2 driver is the one enabling the DMA attack, but this needs to be tested | ||
| 947 | boot.blacklistedKernelModules = optionals luks.mitigateDMAAttacks | ||
| 948 | ["firewire_ohci" "firewire_core" "firewire_sbp2"]; | ||
| 949 | |||
| 950 | # Some modules that may be needed for mounting anything ciphered | ||
| 951 | boot.initrd.availableKernelModules = [ "dm_mod" "dm_crypt" "cryptd" "input_leds" ] | ||
| 952 | ++ luks.cryptoModules | ||
| 953 | # workaround until https://marc.info/?l=linux-crypto-vger&m=148783562211457&w=4 is merged | ||
| 954 | # remove once 'modprobe --show-depends xts' shows ecb as a dependency | ||
| 955 | ++ (if builtins.elem "xts" luks.cryptoModules then ["ecb"] else []); | ||
| 956 | |||
| 957 | # copy the cryptsetup binary and it's dependencies | ||
| 958 | boot.initrd.extraUtilsCommands = | ||
| 959 | let | ||
| 960 | extraUtils = config.system.build.extraUtils; | ||
| 961 | |||
| 962 | ipkgs = pkgs.appendOverlays [ | ||
| 963 | (final: prev: { | ||
| 964 | tpm2-tss = prev.tpm2-tss.overrideAttrs (oldAttrs: { | ||
| 965 | doCheck = false; | ||
| 966 | patches = []; | ||
| 967 | postPatch = '' | ||
| 968 | patchShebangs script | ||
| 969 | ''; | ||
| 970 | configureFlags = []; | ||
| 971 | }); | ||
| 972 | }) | ||
| 973 | ]; | ||
| 974 | in '' | ||
| 975 | copy_bin_and_libs ${pkgs.cryptsetup}/bin/cryptsetup | ||
| 976 | copy_bin_and_libs ${askPass}/bin/cryptsetup-askpass | ||
| 977 | sed -i s,/bin/sh,$out/bin/sh, $out/bin/cryptsetup-askpass | ||
| 978 | |||
| 979 | ${optionalString luks.yubikeySupport '' | ||
| 980 | copy_bin_and_libs ${pkgs.yubikey-personalization}/bin/ykchalresp | ||
| 981 | copy_bin_and_libs ${pkgs.yubikey-personalization}/bin/ykinfo | ||
| 982 | copy_bin_and_libs ${pkgs.openssl.bin}/bin/openssl | ||
| 983 | |||
| 984 | cc -O3 -I${pkgs.openssl.dev}/include -L${pkgs.openssl.out}/lib ${./pbkdf2-sha512.c} -o pbkdf2-sha512 -lcrypto | ||
| 985 | strip -s pbkdf2-sha512 | ||
| 986 | copy_bin_and_libs pbkdf2-sha512 | ||
| 987 | |||
| 988 | mkdir -p $out/etc/ssl | ||
| 989 | cp -pdv ${pkgs.openssl.out}/etc/ssl/openssl.cnf $out/etc/ssl | ||
| 990 | |||
| 991 | cat > $out/bin/openssl-wrap <<EOF | ||
| 992 | #!$out/bin/sh | ||
| 993 | export OPENSSL_CONF=$out/etc/ssl/openssl.cnf | ||
| 994 | $out/bin/openssl "\$@" | ||
| 995 | EOF | ||
| 996 | chmod +x $out/bin/openssl-wrap | ||
| 997 | ''} | ||
| 998 | |||
| 999 | ${optionalString luks.fido2Support '' | ||
| 1000 | copy_bin_and_libs ${pkgs.fido2luks}/bin/fido2luks | ||
| 1001 | ''} | ||
| 1002 | |||
| 1003 | |||
| 1004 | ${optionalString luks.gpgSupport '' | ||
| 1005 | copy_bin_and_libs ${pkgs.gnupg}/bin/gpg | ||
| 1006 | copy_bin_and_libs ${pkgs.gnupg}/bin/gpg-agent | ||
| 1007 | copy_bin_and_libs ${pkgs.gnupg}/libexec/scdaemon | ||
| 1008 | |||
| 1009 | ${concatMapStringsSep "\n" (x: | ||
| 1010 | if x.gpgCard != null then | ||
| 1011 | '' | ||
| 1012 | mkdir -p $out/secrets/gpg-keys/${x.device} | ||
| 1013 | cp -a ${x.gpgCard.encryptedPass} $out/secrets/gpg-keys/${x.device}/cryptkey.gpg | ||
| 1014 | cp -a ${x.gpgCard.publicKey} $out/secrets/gpg-keys/${x.device}/pubkey.asc | ||
| 1015 | '' | ||
| 1016 | else "" | ||
| 1017 | ) (attrValues luks.devices) | ||
| 1018 | } | ||
| 1019 | ''} | ||
| 1020 | |||
| 1021 | ${optionalString luks.clevisSupport '' | ||
| 1022 | for bin in ${ipkgs.tpm2-tools}/bin/* ${ipkgs.jose}/bin/* ${ipkgs.libpwquality}/bin/*; do | ||
| 1023 | if [ -L $bin ]; then | ||
| 1024 | cp -v $bin $out/bin | ||
| 1025 | else | ||
| 1026 | copy_bin_and_libs $bin | ||
| 1027 | fi | ||
| 1028 | done | ||
| 1029 | |||
| 1030 | copy_bin_and_libs ${ipkgs.bash}/bin/bash | ||
| 1031 | for bin in ${ipkgs.clevis}/bin/* ${ipkgs.clevis}/bin/.*; do | ||
| 1032 | [ -f $bin -o -L $bin ] || continue | ||
| 1033 | |||
| 1034 | substitute $bin $out/bin/$(basename $bin) \ | ||
| 1035 | --replace ${ipkgs.bash}/bin $out/bin \ | ||
| 1036 | --replace ${ipkgs.clevis}/bin $out/bin \ | ||
| 1037 | --replace ${ipkgs.tpm2-tools}/bin $out/bin \ | ||
| 1038 | --replace ${ipkgs.jose}/bin $out/bin \ | ||
| 1039 | --replace ${ipkgs.libpwquality}/bin $out/bin \ | ||
| 1040 | --replace ${ipkgs.coreutils}/bin $out/bin | ||
| 1041 | |||
| 1042 | [ -x $bin ] && chmod +x $out/bin/$(basename $bin) | ||
| 1043 | done | ||
| 1044 | |||
| 1045 | for lib in ${ipkgs.tpm2-tss}/lib/*.so*; do | ||
| 1046 | if [ -f $lib ]; then | ||
| 1047 | patchelf --output $out/lib/$(basename $lib) $lib \ | ||
| 1048 | --set-rpath $out/lib | ||
| 1049 | else | ||
| 1050 | cp -pdv $lib $out/lib | ||
| 1051 | fi | ||
| 1052 | done | ||
| 1053 | ''} | ||
| 1054 | |||
| 1055 | ${optionalString luks.dmiSupport '' | ||
| 1056 | copy_bin_and_libs ${pkgs.dmidecode}/bin/dmidecode | ||
| 1057 | ''} | ||
| 1058 | ''; | ||
| 1059 | |||
| 1060 | boot.initrd.extraUtilsCommandsTest = '' | ||
| 1061 | $out/bin/cryptsetup --version | ||
| 1062 | ${optionalString luks.yubikeySupport '' | ||
| 1063 | $out/bin/ykchalresp -V | ||
| 1064 | $out/bin/ykinfo -V | ||
| 1065 | $out/bin/openssl-wrap version | ||
| 1066 | ''} | ||
| 1067 | ${optionalString luks.gpgSupport '' | ||
| 1068 | $out/bin/gpg --version | ||
| 1069 | $out/bin/gpg-agent --version | ||
| 1070 | $out/bin/scdaemon --version | ||
| 1071 | ''} | ||
| 1072 | ${optionalString luks.fido2Support '' | ||
| 1073 | $out/bin/fido2luks --version | ||
| 1074 | ''} | ||
| 1075 | ${optionalString luks.clevisSupport '' | ||
| 1076 | $out/bin/jose alg | ||
| 1077 | ''} | ||
| 1078 | ${optionalString luks.dmiSupport '' | ||
| 1079 | $out/bin/dmidecode --version | ||
| 1080 | ''} | ||
| 1081 | ''; | ||
| 1082 | |||
| 1083 | boot.initrd.preFailCommands = postCommands; | ||
| 1084 | boot.initrd.preLVMCommands = commonFunctions + preCommands + concatStrings (mapAttrsToList openCommand preLVM) + postCommands; | ||
| 1085 | boot.initrd.postDeviceCommands = commonFunctions + preCommands + concatStrings (mapAttrsToList openCommand postLVM) + postCommands; | ||
| 1086 | |||
| 1087 | environment.systemPackages = [ pkgs.cryptsetup ]; | ||
| 1088 | }; | ||
| 1089 | } | ||
