The dice-rolls method was relatively complex and somewhat biased
(~2.4% biased toward 1-4 on each roll due to modulo bias).
Just pick a line from the dictionary at random. Using all 32 bits of
entropy to pick a line once distributes the modulo bias so it is only
0.000003% biased toward the first 1263 words.
Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
Signed-off-by: Thierry Laurion <insurgo@riseup.net>
Signed-off-by: Thierry Laurion <insurgo@riseup.net>
works:
- oem and user mode passphrase generation
- qrcode
missing:
- unattended
- luks reencryption + passphrase change for OEM mode (only input to be provided) with SINGLE passphrase when in unattended mode
- same for user reownership when previously OEM reset unattended
Signed-off-by: Thierry Laurion <insurgo@riseup.net>
Nothing uses it for the moment, needs to be called from recovery shell: bash, source /etc/functions. generate_passphrase
- parses dictionary to check how many dice rolls needed on first entry, defaults to EFF short list v2 (bigger words easier to remember, 4 dices roll instead of 5)
- defaults to using initrd/etc/diceware_dictionnaries/eff_short_wordlist_2_0.txt, parametrable
- make sure format of dictionary is 'digit word' and fail early otherwise: we expect EFF diceware format dictionaries
- enforces max length of 256 chars, parametrable, reduces number of words to fit if not override
- enforces default 3 words passphrase, parametrable
- enforces captialization of first letter, lowercase parametrable
- read multiple bytes from /dev/urandom to fit number of dice rolls
Unrelated: uniformize format of file
Signed-off-by: Thierry Laurion <insurgo@riseup.net>
Mitigate misunderstands and show GPG User/Admin PIN counts until proper output exists under hotp_verification info to reduce global confusion
Add TODO under initrd/bin/seal-hotpkey to not foget to fix output since now outputting counter of 8 for Admin PIN which makes no sense at all under hotp_verification 1.6 https://github.com/Nitrokey/nitrokey-hotp-verification/issues/38
Signed-off-by: Thierry Laurion <insurgo@riseup.net>
- fi misplaced
- rework reencryption loop
- added verbose output on TPM DUK key addition when LUKS container can be unlocked with DRK
Current state, left todo for future work:
TPM DUK:
- TPM DUK setup on defautl boot reuses /boot/kexec_key_devices.txt if present
- If not, list all LUKS partitions, asks user for selection and makes sure LUKS passphrase can unlock all
- Works on both LUKSv1 and LUKSv2 containers, reusing OS installer settings (Heads doesn't enforce better then OS installer LUKS parameters)
LUKS passphrase change/LUKS reencryption:
- Reuses /boot/kexec_key_devices.txt if existing
- If not, prompts for LUKS passphase, list all LUKS containers not being USB based and attempt to unlock all those, listing only the ones successfully unlocked
- Prompts user to reuse found unlockable LUKS partitions with LUKS passphrase, caches and reuse in other LUKS operations (passphrase change as well from oem factory reset/re-ownership)
- Deals properly with LUKSv1/LUKSv2/multiple LUKS containers and reencrypt/passphrase changes them all if accepted, otherwise asks user to select individual LUKS container
Tested on luksv1,luksv2, btrfs under luks (2x containers) and TPM DUK setup up to booting OS. All good
TODO:
- LUKS passphrase check is done multiple times across TPM DUK, reencryption and luks passphrase. Could refactor to change this, but since this op is done only one reencrypt+passphrase change) upon hardare reception from OEM, I stopped caring here.
Signed-off-by: Thierry Laurion <insurgo@riseup.net>
- cache/reuse that passphrase, used afterward to find which LUKS keyslot contains the DRK, which is used to direct reencryption, also reused for passphrase change.
- refactoring detection + testing of prompted LUKS passphrase for discovered LUKS containers that can be unlocked with same passphrase to prompt user for selection
TODO: remove duplicate luks passphrase unlocking volumes functions for the moment
Signed-off-by: Thierry Laurion <insurgo@riseup.net>
This reverts commit 20e9392b97c9ed42b85ae930a163131997640a44.
To test this PR without reencryption, just 'git revert' this commit
Signed-off-by: Thierry Laurion <insurgo@riseup.net>
cryptsetup2 2.6.1 is a new release that supports reencryption of Q4.2 release LUKS2 volumes created at installation.
This is a critical feature for the Qubes OS 4.2 release for added data at rest protection
Cryptsetup 2.6.x internal changes:
- Argon2 used externally and internally: requires a lot of RAM and CPU to derivate passphrase to key validated in key slots.
- This is used to rate limit efficiently bruteforcing of LUKS key slots, requiring each offline brute force attempt to consume ~15-30 seconds per attempt
- OF course, strong passphrases are still recommended, but bruteforcing LUKSv2 containers with Argon2 would require immense time, ram and CPU even to bruteforce low entropy passphrase/PINs.
- passphrase change doesn't permit LUKS key slot specification anymore: key slot rotates (new one consusumed per op: then old one wiped internally. EG: LUKS key slot 1 created, then 0 deleted)
- reencryption doesn't permit old call arguments. No more direct-io; inadmissively slow through AIO (async) calls, need workarounds for good enough perfs (arguments + newer kernel with cloudfare fixes in tree)
cryptsetup 2.6.1 requires:
- lvm2 2.03.23, which is also included in this PR.
- requires libaio, which is also included in this PR (could be hacked out but deep dependency at first sight: left in)
- requires util-linux 2.39
- patches for reproducible builds are included for above 3 packages.
luks-functions was updated to support the new cryptsetup2 version calls/changes
- reencryption happen in direct-io, offline mode and without locking, requiring linux 5.10.9+ to bypass linux queues
- from tests, this is best for performance and reliability in single-user mode
- LUKS container ops now validate Disk Recovery Key (DRK) passphrase prior and DRK key slot prior of going forward if needed, failing early.
- Heads don't expect DRK to be in static key slot anymore, and finds the DRK key slot dynamically.
- If reencrytipn/passphrase change: make sure all LUKS containers on same block device can be unlocked with same DRK
- Reencryption: requires to know which key slot to reencrypt.
- Find LUKS key slot that unlocks with DRK passphrase unlock prior of reencrypt call
- Passphrase change: no slot can be passed, but key slot of DRK rotates.
kexec-seal-key
- TPM LUKS Disk Unlock Key key slots have changed to be set in max slots per LUKS version (LUKSv1:7 /LUKSv2: 31)
- If key slot != default LUKS version's keyslot outside of DRK key slot: prompt the user before wiping that key slot, otherwise wipe automatically
- This takes for granted that the DRK key slot alone is needed on the system and Heads controls the LUKS key slots.
- If user has something else going on, ie: Using USB Security dongle + TPM DUK, then the user will need to say no when wiping keys.
- It was suggested to leave LUKS key slots outside of DRK alone, but then: what to do when all key slots would be used?
- Alternative implementation could be to only prompt users to wipe keyslots other then DRK when key slots are all used (LUKSv1: 0-7, LUKSv2: 0-31)
- But then cleanup would need to happen prior of operations (LUKS passphrase change, TPM DUK setup) and could be problematic.
- LUKS containers now checked to be same LUKS version prior of permitting to set TPM DUK and will refuse to go forward of different versions.
TODO:
- async (AIO) calls are not used. direct-io is used instead. libaio could be hacked out
- this could be subject to future work
Notes:
- time to deprecated legacy boards the do not enough space for the new space requirements
- x230-legacy, x230-legacy-flash, x230-hotp-legacy
- t430-legacy, t430-legacy-flash, t430-hotp-legacy already deprecated
Unrelated:
- typos fixes found along the way
Signed-off-by: Thierry Laurion <insurgo@riseup.net>
cbfs-init: remove temp files, measure direct cbfs output, extend PCR with proper introspection tracing
flash.sh: do not die but go to recovery if flashrom fails, cosmetic fix for warning given to user
kexec-insert-key: extend PCR with proper introspection tracing
kexec-select-boot: extend PCR with proper introspection tracing
kexec-measure-luks: extend PCR with proper introspection tracing
tpmr: Add missing TRACE_FUNC, fix comments, extend give hash that was extended to tpm call in DEBUG, fix TPM startsession unsuppressed output still present
ash_functions: extend PCR with proper introspection tracing
insmod: DEBUG info more pertinent, extend PCR with proper introspection tracing
Signed-off-by: Thierry Laurion <insurgo@riseup.net>
PureOS ISOs still are not detach-signed and it is misleading that there
is a key here. Remove it, we'll add it when the ISOs are signed.
Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
Log the board and version when entering the recovery shell. Extract
the firmware version logic from init.
Currently this is the only way to get the debug log. If we add a way
from the GUI, we may want to log the board and version somewhere else
too.
Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
LOG() is added to log to the log only (not kmsg, more verbose than
TRACE).
DO_WITH_DEBUG only captures stdout/stderr to the log with LOG().
kexec-boot silences stderr from kexec, we don't want it on the console.
No need to repeat the kexec command when asking in debug to continue
boot, it's no longer hidden behind verbose output from kexec.
Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
`eval "$kexeccmd"` should become `DO_WITH_DEBUG eval "$kexeccmd"` when
adding DO_WITH_DEBUG, command invocation is still the same, still needs
eval.
Restore DO_WITH_DEBUG in front of kexec-parse-boot that had been
removed.
Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
"$1 err:" looked like an error, but often there's output on stderr
that's diagnostic (like kexec -d). "$1 stderr:" is clearer.
Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
DO_WITH_DEBUG traces command exit status (if failed), stdout/stderr (if
not empty), and PATH (if command was not found). The caller still
observes the exit status, and stdout/stderr still go to the caller as
well.
This way, DO_WITH_DEBUG can be inserted anywhere with minimal spam in
the logs and without affecting the script.
Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
Otherwise we get ehci-pci and xhci_hcd kernel messages in dmesg debug AFTER "Verifying presence of GPG card" which explains why dongle might not be found in time and fails in oem-factory-reset
Fixes https://github.com/Nitrokey/heads/issues/48
Signed-off-by: Thierry Laurion <insurgo@riseup.net>
All boards with CONFIG_LINUX_USB=y ship ehci-* and xhci-*, they are
not controlled by CONFIG_LINUX_USB_COMPANION_CONTROLLER. Always
insert them when initializing USB. Fixes commit 35de2348
Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
When testing a possible boot device, detect its partition type and
skip grub, LUKS, and LVM partitions. These aren't mountable as /boot,
this silences spurious exFAT errors.
In detect_boot_device, skip testing CONFIG_BOOT_DEV a second time if it
is found as a block device. This avoids doubling any errors shown from
checking this device, no sense trying it twice.
Refactor some logic to avoid duplication - extract
device_has_partitions and use it in detect_boot_device, extract
mount_possible_boot_device and use it instead of duplicating the logic.
Move find_lvm_vg_name() to /etc/functions.
Avoid mixing up similarly-named devices like 'nvme0n1'/'nvme0n10' or
'sda'/'sdaa' - it's probably unlikely that many devices will appear,
but looking for partitions in '/sys/class/block/<device>/' instead of
'/dev/' would avoid any collisions.
Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
Exception: scripts sourcing/calls within etc/ash_functions continues to use old TRACE functions until we switch to bash completely getting rid of ash.
This would mean getting rid of legacy boards (flash + legacy boards which do not have enough space for bash in flash boards) once and for all.
Signed-off-by: Thierry Laurion <insurgo@riseup.net>