diff options
Diffstat (limited to '')
-rw-r--r-- | lib/luks2/hw_opal/hw_opal.c | 26 | ||||
-rw-r--r-- | lib/luks2/hw_opal/hw_opal.h | 5 | ||||
-rw-r--r-- | lib/setup.c | 10 |
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, §or_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); } |