|
Packit |
94f725 |
/*
|
|
Packit |
94f725 |
* LUKS - Linux Unified Key Setup v2, LUKS2 header format code
|
|
Packit |
94f725 |
*
|
|
Packit |
94f725 |
* Copyright (C) 2015-2020 Red Hat, Inc. All rights reserved.
|
|
Packit |
94f725 |
* Copyright (C) 2015-2020 Milan Broz
|
|
Packit |
94f725 |
*
|
|
Packit |
94f725 |
* This program is free software; you can redistribute it and/or
|
|
Packit |
94f725 |
* modify it under the terms of the GNU General Public License
|
|
Packit |
94f725 |
* as published by the Free Software Foundation; either version 2
|
|
Packit |
94f725 |
* of the License, or (at your option) any later version.
|
|
Packit |
94f725 |
*
|
|
Packit |
94f725 |
* This program is distributed in the hope that it will be useful,
|
|
Packit |
94f725 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
94f725 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit |
94f725 |
* GNU General Public License for more details.
|
|
Packit |
94f725 |
*
|
|
Packit |
94f725 |
* You should have received a copy of the GNU General Public License
|
|
Packit |
94f725 |
* along with this program; if not, write to the Free Software
|
|
Packit |
94f725 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
Packit |
94f725 |
*/
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
#include "luks2_internal.h"
|
|
Packit |
94f725 |
#include <uuid/uuid.h>
|
|
Packit |
94f725 |
#include <assert.h>
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
struct area {
|
|
Packit |
94f725 |
uint64_t offset;
|
|
Packit |
94f725 |
uint64_t length;
|
|
Packit |
94f725 |
};
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
static size_t get_area_size(size_t keylength)
|
|
Packit |
94f725 |
{
|
|
Packit |
94f725 |
//FIXME: calculate this properly, for now it is AF_split_sectors
|
|
Packit |
94f725 |
return size_round_up(keylength * 4000, 4096);
|
|
Packit |
94f725 |
}
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
static size_t get_min_offset(struct luks2_hdr *hdr)
|
|
Packit |
94f725 |
{
|
|
Packit |
94f725 |
return 2 * hdr->hdr_size;
|
|
Packit |
94f725 |
}
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
static size_t get_max_offset(struct luks2_hdr *hdr)
|
|
Packit |
94f725 |
{
|
|
Packit |
94f725 |
return LUKS2_hdr_and_areas_size(hdr->jobj);
|
|
Packit |
94f725 |
}
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
int LUKS2_find_area_max_gap(struct crypt_device *cd, struct luks2_hdr *hdr,
|
|
Packit |
94f725 |
uint64_t *area_offset, uint64_t *area_length)
|
|
Packit |
94f725 |
{
|
|
Packit |
94f725 |
struct area areas[LUKS2_KEYSLOTS_MAX], sorted_areas[LUKS2_KEYSLOTS_MAX+1] = {};
|
|
Packit |
94f725 |
int i, j, k, area_i;
|
|
Packit |
94f725 |
size_t valid_offset, offset, length;
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
/* fill area offset + length table */
|
|
Packit |
94f725 |
for (i = 0; i < LUKS2_KEYSLOTS_MAX; i++) {
|
|
Packit |
94f725 |
if (!LUKS2_keyslot_area(hdr, i, &areas[i].offset, &areas[i].length))
|
|
Packit |
94f725 |
continue;
|
|
Packit |
94f725 |
areas[i].length = 0;
|
|
Packit |
94f725 |
areas[i].offset = 0;
|
|
Packit |
94f725 |
}
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
/* sort table */
|
|
Packit |
94f725 |
k = 0; /* index in sorted table */
|
|
Packit |
94f725 |
for (i = 0; i < LUKS2_KEYSLOTS_MAX; i++) {
|
|
Packit |
94f725 |
offset = get_max_offset(hdr) ?: UINT64_MAX;
|
|
Packit |
94f725 |
area_i = -1;
|
|
Packit |
94f725 |
/* search for the smallest offset in table */
|
|
Packit |
94f725 |
for (j = 0; j < LUKS2_KEYSLOTS_MAX; j++)
|
|
Packit |
94f725 |
if (areas[j].offset && areas[j].offset <= offset) {
|
|
Packit |
94f725 |
area_i = j;
|
|
Packit |
94f725 |
offset = areas[j].offset;
|
|
Packit |
94f725 |
}
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
if (area_i >= 0) {
|
|
Packit |
94f725 |
sorted_areas[k].length = areas[area_i].length;
|
|
Packit |
94f725 |
sorted_areas[k].offset = areas[area_i].offset;
|
|
Packit |
94f725 |
areas[area_i].length = 0;
|
|
Packit |
94f725 |
areas[area_i].offset = 0;
|
|
Packit |
94f725 |
k++;
|
|
Packit |
94f725 |
}
|
|
Packit |
94f725 |
}
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
sorted_areas[LUKS2_KEYSLOTS_MAX].offset = get_max_offset(hdr);
|
|
Packit |
94f725 |
sorted_areas[LUKS2_KEYSLOTS_MAX].length = 1;
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
/* search for the gap we can use */
|
|
Packit |
94f725 |
length = valid_offset = 0;
|
|
Packit |
94f725 |
offset = get_min_offset(hdr);
|
|
Packit |
94f725 |
for (i = 0; i < LUKS2_KEYSLOTS_MAX+1; i++) {
|
|
Packit |
94f725 |
/* skip empty */
|
|
Packit |
94f725 |
if (sorted_areas[i].offset == 0 || sorted_areas[i].length == 0)
|
|
Packit |
94f725 |
continue;
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
/* found bigger gap than the last one */
|
|
Packit |
94f725 |
if ((offset < sorted_areas[i].offset) && (sorted_areas[i].offset - offset) > length) {
|
|
Packit |
94f725 |
length = sorted_areas[i].offset - offset;
|
|
Packit |
94f725 |
valid_offset = offset;
|
|
Packit |
94f725 |
}
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
/* move beyond allocated area */
|
|
Packit |
94f725 |
offset = sorted_areas[i].offset + sorted_areas[i].length;
|
|
Packit |
94f725 |
}
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
/* this search 'algorithm' does not work with unaligned areas */
|
|
Packit |
94f725 |
assert(length == size_round_up(length, 4096));
|
|
Packit |
94f725 |
assert(valid_offset == size_round_up(valid_offset, 4096));
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
if (!length) {
|
|
Packit |
94f725 |
log_dbg(cd, "Not enough space in header keyslot area.");
|
|
Packit |
94f725 |
return -EINVAL;
|
|
Packit |
94f725 |
}
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
log_dbg(cd, "Found largest free area %zu -> %zu", valid_offset, length + valid_offset);
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
*area_offset = valid_offset;
|
|
Packit |
94f725 |
*area_length = length;
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
return 0;
|
|
Packit |
94f725 |
}
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
int LUKS2_find_area_gap(struct crypt_device *cd, struct luks2_hdr *hdr,
|
|
Packit |
94f725 |
size_t keylength, uint64_t *area_offset, uint64_t *area_length)
|
|
Packit |
94f725 |
{
|
|
Packit |
94f725 |
struct area areas[LUKS2_KEYSLOTS_MAX], sorted_areas[LUKS2_KEYSLOTS_MAX] = {};
|
|
Packit |
94f725 |
int i, j, k, area_i;
|
|
Packit |
94f725 |
size_t offset, length;
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
/* fill area offset + length table */
|
|
Packit |
94f725 |
for (i = 0; i < LUKS2_KEYSLOTS_MAX; i++) {
|
|
Packit |
94f725 |
if (!LUKS2_keyslot_area(hdr, i, &areas[i].offset, &areas[i].length))
|
|
Packit |
94f725 |
continue;
|
|
Packit |
94f725 |
areas[i].length = 0;
|
|
Packit |
94f725 |
areas[i].offset = 0;
|
|
Packit |
94f725 |
}
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
/* sort table */
|
|
Packit |
94f725 |
k = 0; /* index in sorted table */
|
|
Packit |
94f725 |
for (i = 0; i < LUKS2_KEYSLOTS_MAX; i++) {
|
|
Packit |
94f725 |
offset = get_max_offset(hdr) ?: UINT64_MAX;
|
|
Packit |
94f725 |
area_i = -1;
|
|
Packit |
94f725 |
/* search for the smallest offset in table */
|
|
Packit |
94f725 |
for (j = 0; j < LUKS2_KEYSLOTS_MAX; j++)
|
|
Packit |
94f725 |
if (areas[j].offset && areas[j].offset <= offset) {
|
|
Packit |
94f725 |
area_i = j;
|
|
Packit |
94f725 |
offset = areas[j].offset;
|
|
Packit |
94f725 |
}
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
if (area_i >= 0) {
|
|
Packit |
94f725 |
sorted_areas[k].length = areas[area_i].length;
|
|
Packit |
94f725 |
sorted_areas[k].offset = areas[area_i].offset;
|
|
Packit |
94f725 |
areas[area_i].length = 0;
|
|
Packit |
94f725 |
areas[area_i].offset = 0;
|
|
Packit |
94f725 |
k++;
|
|
Packit |
94f725 |
}
|
|
Packit |
94f725 |
}
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
/* search for the gap we can use */
|
|
Packit |
94f725 |
offset = get_min_offset(hdr);
|
|
Packit |
94f725 |
length = get_area_size(keylength);
|
|
Packit |
94f725 |
for (i = 0; i < LUKS2_KEYSLOTS_MAX; i++) {
|
|
Packit |
94f725 |
/* skip empty */
|
|
Packit |
94f725 |
if (sorted_areas[i].offset == 0 || sorted_areas[i].length == 0)
|
|
Packit |
94f725 |
continue;
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
/* enough space before the used area */
|
|
Packit |
94f725 |
if ((offset < sorted_areas[i].offset) && ((offset + length) <= sorted_areas[i].offset))
|
|
Packit |
94f725 |
break;
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
/* both offset and length are already aligned to 4096 bytes */
|
|
Packit |
94f725 |
offset = sorted_areas[i].offset + sorted_areas[i].length;
|
|
Packit |
94f725 |
}
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
if ((offset + length) > get_max_offset(hdr)) {
|
|
Packit |
94f725 |
log_dbg(cd, "Not enough space in header keyslot area.");
|
|
Packit |
94f725 |
return -EINVAL;
|
|
Packit |
94f725 |
}
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
log_dbg(cd, "Found area %zu -> %zu", offset, length + offset);
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
*area_offset = offset;
|
|
Packit |
94f725 |
*area_length = length;
|
|
Packit |
94f725 |
return 0;
|
|
Packit |
94f725 |
}
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
int LUKS2_check_metadata_area_size(uint64_t metadata_size)
|
|
Packit |
94f725 |
{
|
|
Packit |
94f725 |
/* see LUKS2_HDR2_OFFSETS */
|
|
Packit |
94f725 |
return (metadata_size != 0x004000 &&
|
|
Packit |
94f725 |
metadata_size != 0x008000 && metadata_size != 0x010000 &&
|
|
Packit |
94f725 |
metadata_size != 0x020000 && metadata_size != 0x040000 &&
|
|
Packit |
94f725 |
metadata_size != 0x080000 && metadata_size != 0x100000 &&
|
|
Packit |
94f725 |
metadata_size != 0x200000 && metadata_size != 0x400000);
|
|
Packit |
94f725 |
}
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
int LUKS2_check_keyslots_area_size(uint64_t keyslots_size)
|
|
Packit |
94f725 |
{
|
|
Packit |
94f725 |
return (MISALIGNED_4K(keyslots_size) ||
|
|
Packit |
94f725 |
keyslots_size > LUKS2_MAX_KEYSLOTS_SIZE);
|
|
Packit |
94f725 |
}
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
int LUKS2_generate_hdr(
|
|
Packit |
94f725 |
struct crypt_device *cd,
|
|
Packit |
94f725 |
struct luks2_hdr *hdr,
|
|
Packit |
94f725 |
const struct volume_key *vk,
|
|
Packit |
94f725 |
const char *cipherName,
|
|
Packit |
94f725 |
const char *cipherMode,
|
|
Packit |
94f725 |
const char *integrity,
|
|
Packit |
94f725 |
const char *uuid,
|
|
Packit |
94f725 |
unsigned int sector_size, /* in bytes */
|
|
Packit |
94f725 |
uint64_t data_offset, /* in bytes */
|
|
Packit |
94f725 |
uint64_t align_offset, /* in bytes */
|
|
Packit |
94f725 |
uint64_t required_alignment,
|
|
Packit |
94f725 |
uint64_t metadata_size,
|
|
Packit |
94f725 |
uint64_t keyslots_size)
|
|
Packit |
94f725 |
{
|
|
Packit |
94f725 |
struct json_object *jobj_segment, *jobj_integrity, *jobj_keyslots, *jobj_segments, *jobj_config;
|
|
Packit |
94f725 |
char cipher[128];
|
|
Packit |
94f725 |
uuid_t partitionUuid;
|
|
Packit |
94f725 |
int digest;
|
|
Packit |
94f725 |
uint64_t mdev_size;
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
if (!metadata_size)
|
|
Packit |
94f725 |
metadata_size = LUKS2_HDR_16K_LEN;
|
|
Packit |
94f725 |
hdr->hdr_size = metadata_size;
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
if (data_offset && data_offset < get_min_offset(hdr)) {
|
|
Packit |
94f725 |
log_err(cd, _("Requested data offset is too small."));
|
|
Packit |
94f725 |
return -EINVAL;
|
|
Packit |
94f725 |
}
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
/* Increase keyslot size according to data offset */
|
|
Packit |
94f725 |
if (!keyslots_size && data_offset)
|
|
Packit |
94f725 |
keyslots_size = data_offset - get_min_offset(hdr);
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
/* keyslots size has to be 4 KiB aligned */
|
|
Packit |
94f725 |
keyslots_size -= (keyslots_size % 4096);
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
if (keyslots_size > LUKS2_MAX_KEYSLOTS_SIZE)
|
|
Packit |
94f725 |
keyslots_size = LUKS2_MAX_KEYSLOTS_SIZE;
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
if (!keyslots_size) {
|
|
Packit |
94f725 |
assert(LUKS2_DEFAULT_HDR_SIZE > 2 * LUKS2_HDR_OFFSET_MAX);
|
|
Packit |
94f725 |
keyslots_size = LUKS2_DEFAULT_HDR_SIZE - get_min_offset(hdr);
|
|
Packit |
94f725 |
/* Decrease keyslots_size due to metadata device being too small */
|
|
Packit |
94f725 |
if (!device_size(crypt_metadata_device(cd), &mdev_size) &&
|
|
Packit |
94f725 |
((keyslots_size + get_min_offset(hdr)) > mdev_size) &&
|
|
Packit |
94f725 |
device_fallocate(crypt_metadata_device(cd), keyslots_size + get_min_offset(hdr)))
|
|
Packit |
94f725 |
keyslots_size = mdev_size - get_min_offset(hdr);
|
|
Packit |
94f725 |
}
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
/* Decrease keyslots_size if we have smaller data_offset */
|
|
Packit |
94f725 |
if (data_offset && (keyslots_size + get_min_offset(hdr)) > data_offset) {
|
|
Packit |
94f725 |
keyslots_size = data_offset - get_min_offset(hdr);
|
|
Packit |
94f725 |
log_dbg(cd, "Decreasing keyslot area size to %" PRIu64
|
|
Packit |
94f725 |
" bytes due to the requested data offset %"
|
|
Packit |
94f725 |
PRIu64 " bytes.", keyslots_size, data_offset);
|
|
Packit |
94f725 |
}
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
/* Data offset has priority */
|
|
Packit |
94f725 |
if (!data_offset && required_alignment) {
|
|
Packit |
94f725 |
data_offset = size_round_up(get_min_offset(hdr) + keyslots_size,
|
|
Packit |
94f725 |
(size_t)required_alignment);
|
|
Packit |
94f725 |
data_offset += align_offset;
|
|
Packit |
94f725 |
}
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
log_dbg(cd, "Formatting LUKS2 with JSON metadata area %" PRIu64
|
|
Packit |
94f725 |
" bytes and keyslots area %" PRIu64 " bytes.",
|
|
Packit |
94f725 |
metadata_size - LUKS2_HDR_BIN_LEN, keyslots_size);
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
if (keyslots_size < (LUKS2_HDR_OFFSET_MAX - 2*LUKS2_HDR_16K_LEN))
|
|
Packit |
94f725 |
log_std(cd, _("WARNING: keyslots area (%" PRIu64 " bytes) is very small,"
|
|
Packit |
94f725 |
" available LUKS2 keyslot count is very limited.\n"),
|
|
Packit |
94f725 |
keyslots_size);
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
hdr->seqid = 1;
|
|
Packit |
94f725 |
hdr->version = 2;
|
|
Packit |
94f725 |
memset(hdr->label, 0, LUKS2_LABEL_L);
|
|
Packit |
94f725 |
strcpy(hdr->checksum_alg, "sha256");
|
|
Packit |
94f725 |
crypt_random_get(cd, (char*)hdr->salt1, LUKS2_SALT_L, CRYPT_RND_SALT);
|
|
Packit |
94f725 |
crypt_random_get(cd, (char*)hdr->salt2, LUKS2_SALT_L, CRYPT_RND_SALT);
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
if (uuid && uuid_parse(uuid, partitionUuid) == -1) {
|
|
Packit |
94f725 |
log_err(cd, _("Wrong LUKS UUID format provided."));
|
|
Packit |
94f725 |
return -EINVAL;
|
|
Packit |
94f725 |
}
|
|
Packit |
94f725 |
if (!uuid)
|
|
Packit |
94f725 |
uuid_generate(partitionUuid);
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
uuid_unparse(partitionUuid, hdr->uuid);
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
if (*cipherMode != '\0')
|
|
Packit |
94f725 |
snprintf(cipher, sizeof(cipher), "%s-%s", cipherName, cipherMode);
|
|
Packit |
94f725 |
else
|
|
Packit |
94f725 |
snprintf(cipher, sizeof(cipher), "%s", cipherName);
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
hdr->jobj = json_object_new_object();
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
jobj_keyslots = json_object_new_object();
|
|
Packit |
94f725 |
json_object_object_add(hdr->jobj, "keyslots", jobj_keyslots);
|
|
Packit |
94f725 |
json_object_object_add(hdr->jobj, "tokens", json_object_new_object());
|
|
Packit |
94f725 |
jobj_segments = json_object_new_object();
|
|
Packit |
94f725 |
json_object_object_add(hdr->jobj, "segments", jobj_segments);
|
|
Packit |
94f725 |
json_object_object_add(hdr->jobj, "digests", json_object_new_object());
|
|
Packit |
94f725 |
jobj_config = json_object_new_object();
|
|
Packit |
94f725 |
json_object_object_add(hdr->jobj, "config", jobj_config);
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
digest = LUKS2_digest_create(cd, "pbkdf2", hdr, vk);
|
|
Packit |
94f725 |
if (digest < 0)
|
|
Packit |
94f725 |
goto err;
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
if (LUKS2_digest_segment_assign(cd, hdr, 0, digest, 1, 0) < 0)
|
|
Packit |
94f725 |
goto err;
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
jobj_segment = json_segment_create_crypt(data_offset, 0, NULL, cipher, sector_size, 0);
|
|
Packit |
94f725 |
if (!jobj_segment)
|
|
Packit |
94f725 |
goto err;
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
if (integrity) {
|
|
Packit |
94f725 |
jobj_integrity = json_object_new_object();
|
|
Packit |
94f725 |
json_object_object_add(jobj_integrity, "type", json_object_new_string(integrity));
|
|
Packit |
94f725 |
json_object_object_add(jobj_integrity, "journal_encryption", json_object_new_string("none"));
|
|
Packit |
94f725 |
json_object_object_add(jobj_integrity, "journal_integrity", json_object_new_string("none"));
|
|
Packit |
94f725 |
json_object_object_add(jobj_segment, "integrity", jobj_integrity);
|
|
Packit |
94f725 |
}
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
json_object_object_add_by_uint(jobj_segments, 0, jobj_segment);
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
json_object_object_add(jobj_config, "json_size", crypt_jobj_new_uint64(metadata_size - LUKS2_HDR_BIN_LEN));
|
|
Packit |
94f725 |
json_object_object_add(jobj_config, "keyslots_size", crypt_jobj_new_uint64(keyslots_size));
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
JSON_DBG(cd, hdr->jobj, "Header JSON:");
|
|
Packit |
94f725 |
return 0;
|
|
Packit |
94f725 |
err:
|
|
Packit |
94f725 |
json_object_put(hdr->jobj);
|
|
Packit |
94f725 |
hdr->jobj = NULL;
|
|
Packit |
94f725 |
return -EINVAL;
|
|
Packit |
94f725 |
}
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
int LUKS2_wipe_header_areas(struct crypt_device *cd,
|
|
Packit |
94f725 |
struct luks2_hdr *hdr)
|
|
Packit |
94f725 |
{
|
|
Packit |
94f725 |
int r;
|
|
Packit |
94f725 |
uint64_t offset, length;
|
|
Packit |
94f725 |
size_t wipe_block;
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
/* Wipe complete header, keyslots and padding areas with zeroes. */
|
|
Packit |
94f725 |
offset = 0;
|
|
Packit |
94f725 |
length = LUKS2_get_data_offset(hdr) * SECTOR_SIZE;
|
|
Packit |
94f725 |
wipe_block = 1024 * 1024;
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
if (LUKS2_hdr_validate(cd, hdr->jobj, hdr->hdr_size - LUKS2_HDR_BIN_LEN))
|
|
Packit |
94f725 |
return -EINVAL;
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
/* On detached header wipe at least the first 4k */
|
|
Packit |
94f725 |
if (length == 0) {
|
|
Packit |
94f725 |
length = 4096;
|
|
Packit |
94f725 |
wipe_block = 4096;
|
|
Packit |
94f725 |
}
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
log_dbg(cd, "Wiping LUKS areas (0x%06" PRIx64 " - 0x%06" PRIx64") with zeroes.",
|
|
Packit |
94f725 |
offset, length + offset);
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
r = crypt_wipe_device(cd, crypt_metadata_device(cd), CRYPT_WIPE_ZERO,
|
|
Packit |
94f725 |
offset, length, wipe_block, NULL, NULL);
|
|
Packit |
94f725 |
if (r < 0)
|
|
Packit |
94f725 |
return r;
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
/* Wipe keyslot area */
|
|
Packit |
94f725 |
wipe_block = 1024 * 1024;
|
|
Packit |
94f725 |
offset = get_min_offset(hdr);
|
|
Packit |
94f725 |
length = LUKS2_keyslots_size(hdr->jobj);
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
log_dbg(cd, "Wiping keyslots area (0x%06" PRIx64 " - 0x%06" PRIx64") with random data.",
|
|
Packit |
94f725 |
offset, length + offset);
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
return crypt_wipe_device(cd, crypt_metadata_device(cd), CRYPT_WIPE_RANDOM,
|
|
Packit |
94f725 |
offset, length, wipe_block, NULL, NULL);
|
|
Packit |
94f725 |
}
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
/* FIXME: what if user wanted to keep original keyslots size? */
|
|
Packit |
94f725 |
int LUKS2_set_keyslots_size(struct crypt_device *cd,
|
|
Packit |
94f725 |
struct luks2_hdr *hdr,
|
|
Packit |
94f725 |
uint64_t data_offset)
|
|
Packit |
94f725 |
{
|
|
Packit |
94f725 |
json_object *jobj_config;
|
|
Packit |
94f725 |
uint64_t keyslots_size;
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
if (data_offset < get_min_offset(hdr))
|
|
Packit |
94f725 |
return 1;
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
keyslots_size = data_offset - get_min_offset(hdr);
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
/* keep keyslots_size reasonable for custom data alignments */
|
|
Packit |
94f725 |
if (keyslots_size > LUKS2_MAX_KEYSLOTS_SIZE)
|
|
Packit |
94f725 |
keyslots_size = LUKS2_MAX_KEYSLOTS_SIZE;
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
/* keyslots size has to be 4 KiB aligned */
|
|
Packit |
94f725 |
keyslots_size -= (keyslots_size % 4096);
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
if (!json_object_object_get_ex(hdr->jobj, "config", &jobj_config))
|
|
Packit |
94f725 |
return 1;
|
|
Packit |
94f725 |
|
|
Packit |
94f725 |
json_object_object_add(jobj_config, "keyslots_size", crypt_jobj_new_uint64(keyslots_size));
|
|
Packit |
94f725 |
return 0;
|
|
Packit |
94f725 |
}
|