diff options
author | Ondrej Kozina <okozina@redhat.com> | 2023-12-01 15:23:35 +0100 |
---|---|---|
committer | Milan Broz <gmazyland@gmail.com> | 2023-12-04 19:02:11 +0000 |
commit | b869822c8b1efef36be24287498583b0c8b8ed2a (patch) | |
tree | fa8c22030ff8ba93070f0230ed11de9a932c313a | |
parent | 2d080580bd615ccbbb97859e885723f6aae7cd65 (diff) | |
download | cryptsetup-b869822c8b1efef36be24287498583b0c8b8ed2a.tar.gz |
opal: erase key cached in kernel when LR gets locked.
It affects only HW OPAL locking range KEK.
After unlocking opal locking range we cache the key in kernel
so that we do not have to pass the key again for locking the
range later (the OPAL std requires key for lock command).
Unfortunately the key remains cached in kernel even after we
lock the range on purpose during crypt_deactivate* or crypt_suspend.
This had 2 side effects:
1) key remained in system memory even though the LUKS device was
inactive (and all keys should be erased from memory).
2) when system gets suspended the locking range got automatically
unlocked later after system resume because the key caching is used
primarly to automatically unlock locking ranges that got locked
after system suspend (due to power cut off on storage device).
Since kernel does not directly support dropping cached keys we achieve
that by overwritting the original key structure with empty one.
-rw-r--r-- | docs/v2.7.0-rc0-ReleaseNotes | 1 | ||||
-rw-r--r-- | lib/luks2/hw_opal/hw_opal.c | 21 |
2 files changed, 15 insertions, 7 deletions
diff --git a/docs/v2.7.0-rc0-ReleaseNotes b/docs/v2.7.0-rc0-ReleaseNotes index aafe91d3..31162417 100644 --- a/docs/v2.7.0-rc0-ReleaseNotes +++ b/docs/v2.7.0-rc0-ReleaseNotes @@ -63,7 +63,6 @@ Changes since version 2.6.1 - compatibility among OPAL-enabled drives is often very problematic, specifically for older drives. Many drives have bugs in the firmware that make the Linux kernel interface unusable. - - unlocking key for OPAL remains in memory even after luksSuspend - if you forget the OPAL admin password, the only way to recover is the full drive factory reset through the PSID key (usually printed on the drive itself) that wipes all data on the drive (not only the diff --git a/lib/luks2/hw_opal/hw_opal.c b/lib/luks2/hw_opal/hw_opal.c index aac065a0..27068d20 100644 --- a/lib/luks2/hw_opal/hw_opal.c +++ b/lib/luks2/hw_opal/hw_opal.c @@ -687,15 +687,24 @@ static int opal_lock_unlock(struct crypt_device *cd, /* If we are unlocking, also tell the kernel to automatically unlock when resuming * from suspend, otherwise the drive will be locked and everything will go up in flames. * Also set the flag to allow locking without having to pass the key again. - * But do not error out if this fails, as the device will already be unlocked. */ - if (!lock) { + * But do not error out if this fails, as the device will already be unlocked. + * + * On a lock path we have to overwrite the cached key from kernel otherwise the locking range + * gets unlocked automatically after system resume even when cryptsetup previously locked it + * on purpose (crypt_deactivate* or crypt_suspend) + */ + if (!lock) unlock.flags = OPAL_SAVE_FOR_LOCK; - r = opal_ioctl(cd, fd, IOC_OPAL_SAVE, &unlock); - if (r != OPAL_STATUS_SUCCESS) { + + r = opal_ioctl(cd, fd, IOC_OPAL_SAVE, &unlock); + if (r != OPAL_STATUS_SUCCESS) { + if (!lock) log_std(cd, "Failed to prepare OPAL device '%s' for sleep resume, be aware before suspending: %s", crypt_get_device_name(cd), opal_status_to_string(r)); - r = 0; - } + else + log_std(cd, "Failed to erase OPAL key for device '%s' from kernel: %s", + crypt_get_device_name(cd), opal_status_to_string(r)); + r = 0; } out: if (!lock) |