1#!/bin/sh
2# shellcheck disable=SC2154
3
4# only run this on systemd systems, we handle the decrypt in mount-zfs.sh in the mount hook otherwise
5[ -e /bin/systemctl ] || [ -e /usr/bin/systemctl ] || return 0
6
7# shellcheck source=zfs-lib.sh.in
8. /lib/dracut-zfs-lib.sh
9
10decode_root_args || return 0
11
12# There is a race between the zpool import and the pre-mount hooks, so we wait for a pool to be imported
13while ! systemctl is-active --quiet zfs-import.target; do
14    systemctl is-failed --quiet zfs-import-cache.service zfs-import-scan.service && return 1
15    sleep 0.1s
16done
17
18BOOTFS="$root"
19if [ "$BOOTFS" = "zfs:AUTO" ]; then
20    BOOTFS="$(zpool get -Ho value bootfs | grep -m1 -vFx -)"
21fi
22
23[ "$(zpool get -Ho value feature@encryption "${BOOTFS%%/*}")" = 'active' ] || return 0
24
25_load_key_cb() {
26    dataset="$1"
27
28    ENCRYPTIONROOT="$(zfs get -Ho value encryptionroot "${dataset}")"
29    [ "${ENCRYPTIONROOT}" = "-" ] && return 0
30
31    [ "$(zfs get -Ho value keystatus "${ENCRYPTIONROOT}")" = "unavailable" ] || return 0
32
33    KEYLOCATION="$(zfs get -Ho value keylocation "${ENCRYPTIONROOT}")"
34    case "${KEYLOCATION%%://*}" in
35        prompt)
36            for _ in 1 2 3; do
37                systemd-ask-password --timeout=0 --no-tty "Encrypted ZFS password for ${dataset}" | zfs load-key "${ENCRYPTIONROOT}" && break
38            done
39            ;;
40        http*)
41            systemctl start network-online.target
42            zfs load-key "${ENCRYPTIONROOT}"
43            ;;
44        file)
45            KEYFILE="${KEYLOCATION#file://}"
46            [ -r "${KEYFILE}" ] || udevadm settle
47            [ -r "${KEYFILE}" ] || {
48                info "ZFS: Waiting for key ${KEYFILE} for ${ENCRYPTIONROOT}..."
49                for _ in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20; do
50                    sleep 0.5s
51                    [ -r "${KEYFILE}" ] && break
52                done
53            }
54            [ -r "${KEYFILE}" ] || warn "ZFS: Key ${KEYFILE} for ${ENCRYPTIONROOT} hasn't appeared. Trying anyway."
55            zfs load-key "${ENCRYPTIONROOT}"
56            ;;
57        *)
58            zfs load-key "${ENCRYPTIONROOT}"
59            ;;
60    esac
61}
62
63_load_key_cb "$BOOTFS"
64for_relevant_root_children "$BOOTFS" _load_key_cb
65