aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOndrej Kozina <okozina@redhat.com>2023-12-01 15:23:35 +0100
committerMilan Broz <gmazyland@gmail.com>2023-12-04 19:02:11 +0000
commitb869822c8b1efef36be24287498583b0c8b8ed2a (patch)
treefa8c22030ff8ba93070f0230ed11de9a932c313a
parent2d080580bd615ccbbb97859e885723f6aae7cd65 (diff)
downloadcryptsetup-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-ReleaseNotes1
-rw-r--r--lib/luks2/hw_opal/hw_opal.c21
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)