summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/luks2/hw_opal/hw_opal.c26
-rw-r--r--lib/luks2/hw_opal/hw_opal.h5
-rw-r--r--lib/setup.c10
3 files changed, 26 insertions, 15 deletions
diff --git a/lib/luks2/hw_opal/hw_opal.c b/lib/luks2/hw_opal/hw_opal.c
index 31ef87e..cd63aad 100644
--- a/lib/luks2/hw_opal/hw_opal.c
+++ b/lib/luks2/hw_opal/hw_opal.c
@@ -405,8 +405,9 @@ static int opal_enabled(struct crypt_device *cd, struct device *dev)
int opal_setup_ranges(struct crypt_device *cd,
struct device *dev,
const struct volume_key *vk,
- uint64_t range_start,
- uint64_t range_length,
+ uint64_t range_start_blocks,
+ uint64_t range_length_blocks,
+ uint32_t opal_block_bytes,
uint32_t segment_number,
const void *admin_key,
size_t admin_key_len)
@@ -423,10 +424,15 @@ int opal_setup_ranges(struct crypt_device *cd,
assert(vk);
assert(admin_key);
assert(vk->keylength <= OPAL_KEY_MAX);
+ assert(opal_block_bytes >= SECTOR_SIZE);
if (admin_key_len > OPAL_KEY_MAX)
return -EINVAL;
+ if (((UINT64_MAX / opal_block_bytes) < range_start_blocks) ||
+ ((UINT64_MAX / opal_block_bytes) < range_length_blocks))
+ return -EINVAL;
+
fd = device_open(cd, dev, O_RDONLY);
if (fd < 0)
return -EIO;
@@ -604,8 +610,8 @@ int opal_setup_ranges(struct crypt_device *cd,
goto out;
}
*setup = (struct opal_user_lr_setup) {
- .range_start = range_start,
- .range_length = range_length,
+ .range_start = range_start_blocks,
+ .range_length = range_length_blocks,
/* Some drives do not enable Locking Ranges on setup. This have some
* interesting consequences: Lock command called later below will pass,
* but locking range will _not_ be locked at all.
@@ -658,9 +664,10 @@ int opal_setup_ranges(struct crypt_device *cd,
}
/* Double check the locking range is locked and the ranges are set up as configured */
- r = opal_range_check_attributes_fd(cd, fd, segment_number, vk, &range_start,
- &range_length, &(bool) {true}, &(bool){true},
- NULL, NULL);
+ r = opal_range_check_attributes_fd(cd, fd, segment_number, vk,
+ &(uint64_t) {range_start_blocks * opal_block_bytes / SECTOR_SIZE},
+ &(uint64_t) {range_length_blocks * opal_block_bytes / SECTOR_SIZE},
+ &(bool) {true}, &(bool){true}, NULL, NULL);
out:
crypt_safe_free(activate);
crypt_safe_free(user_session);
@@ -1011,8 +1018,9 @@ void opal_exclusive_unlock(struct crypt_device *cd, struct crypt_lock_handle *op
int opal_setup_ranges(struct crypt_device *cd,
struct device *dev,
const struct volume_key *vk,
- uint64_t range_start,
- uint64_t range_length,
+ uint64_t range_start_blocks,
+ uint64_t range_length_blocks,
+ uint32_t opal_block_bytes,
uint32_t segment_number,
const void *admin_key,
size_t admin_key_len)
diff --git a/lib/luks2/hw_opal/hw_opal.h b/lib/luks2/hw_opal/hw_opal.h
index f1823bf..66bfe16 100644
--- a/lib/luks2/hw_opal/hw_opal.h
+++ b/lib/luks2/hw_opal/hw_opal.h
@@ -29,8 +29,9 @@ struct crypt_lock_handle;
int opal_setup_ranges(struct crypt_device *cd,
struct device *dev,
const struct volume_key *vk,
- uint64_t range_start,
- uint64_t range_length,
+ uint64_t range_start_blocks,
+ uint64_t range_length_blocks,
+ uint32_t opal_block_bytes,
uint32_t segment_number,
const void *admin_key,
size_t admin_key_len);
diff --git a/lib/setup.c b/lib/setup.c
index ff84292..70b2cee 100644
--- a/lib/setup.c
+++ b/lib/setup.c
@@ -2496,7 +2496,7 @@ int crypt_format_luks2_opal(struct crypt_device *cd,
(device_size_bytes - range_size_bytes) / SECTOR_SIZE);
if (cipher) {
- r = LUKS2_check_encryption_sector(cd, device_size_bytes, data_offset_bytes, sector_size,
+ r = LUKS2_check_encryption_sector(cd, range_size_bytes, data_offset_bytes, sector_size,
sector_size_autodetect, integrity == NULL,
&sector_size);
if (r < 0)
@@ -2517,7 +2517,7 @@ int crypt_format_luks2_opal(struct crypt_device *cd,
sector_size,
data_offset_bytes,
metadata_size_bytes, keyslots_size_bytes,
- device_size_bytes,
+ range_size_bytes,
opal_segment_number,
opal_params->user_key_size);
if (r < 0)
@@ -2556,7 +2556,8 @@ int crypt_format_luks2_opal(struct crypt_device *cd,
r = opal_setup_ranges(cd, crypt_data_device(cd), user_key ?: cd->volume_key,
range_offset_blocks, range_size_bytes / opal_block_bytes,
- opal_segment_number, opal_params->admin_key, opal_params->admin_key_size);
+ opal_block_bytes, opal_segment_number,
+ opal_params->admin_key, opal_params->admin_key_size);
if (r < 0) {
if (r == -EPERM)
log_err(cd, _("Incorrect OPAL Admin key."));
@@ -5327,7 +5328,8 @@ static int _activate_luks2_by_volume_key(struct crypt_device *cd,
}
r = _open_and_activate_reencrypt_device_by_vk(cd, &cd->u.luks2.hdr, name, vk, flags);
} else {
- assert(crypt_volume_key_get_id(vk) == LUKS2_digest_by_segment(&cd->u.luks2.hdr, CRYPT_DEFAULT_SEGMENT));
+ /* hw-opal data segment type does not require volume key for activation */
+ assert(!vk || crypt_volume_key_get_id(vk) == LUKS2_digest_by_segment(&cd->u.luks2.hdr, CRYPT_DEFAULT_SEGMENT));
r = LUKS2_activate(cd, name, vk, external_key, flags);
}