/*
* LUKS - Linux Unified Key Setup v2, keyslot handling
*
- * Copyright (C) 2015-2021 Red Hat, Inc. All rights reserved.
- * Copyright (C) 2015-2021 Milan Broz
+ * Copyright (C) 2015-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2015-2023 Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
};
static const keyslot_handler
-*LUKS2_keyslot_handler_type(struct crypt_device *cd, const char *type)
+*LUKS2_keyslot_handler_type(const char *type)
{
int i;
if (!json_object_object_get_ex(jobj1, "type", &jobj2))
return NULL;
- return LUKS2_keyslot_handler_type(cd, json_object_get_string(jobj2));
+ return LUKS2_keyslot_handler_type(json_object_get_string(jobj2));
}
-int LUKS2_keyslot_find_empty(struct luks2_hdr *hdr)
+int LUKS2_keyslot_find_empty(struct crypt_device *cd, struct luks2_hdr *hdr, size_t keylength)
{
int i;
for (i = 0; i < LUKS2_KEYSLOTS_MAX; i++)
if (!LUKS2_get_keyslot_jobj(hdr, i))
- return i;
+ break;
+
+ if (i == LUKS2_KEYSLOTS_MAX)
+ return -EINVAL;
- return -EINVAL;
+ /* Check also there is a space for the key in keyslots area */
+ if (keylength && LUKS2_find_area_gap(cd, hdr, keylength, NULL, NULL) < 0)
+ return -ENOSPC;
+
+ return i;
}
/* Check if a keyslot is assigned to specific segment */
if (r == -ENOMEM)
log_err(cd, _("Not enough available memory to open a keyslot."));
- else if (r != -EPERM)
+ else if (r != -EPERM && r != -ENOENT)
log_err(cd, _("Keyslot open failed."));
}
return r;
if (r < 0) {
if (r == -ENOMEM)
log_err(cd, _("Not enough available memory to open a keyslot."));
- else if (r != -EPERM)
+ else if (r != -EPERM && r != -ENOENT)
log_err(cd, _("Keyslot open failed."));
}
return r;
}
-int LUKS2_keyslot_reencrypt_allocate(struct crypt_device *cd,
- struct luks2_hdr *hdr,
- int keyslot,
- const struct crypt_params_reencrypt *params)
-{
- const keyslot_handler *h;
- int r;
-
- if (keyslot == CRYPT_ANY_SLOT)
- return -EINVAL;
-
- /* FIXME: find keyslot by type */
- h = LUKS2_keyslot_handler_type(cd, "reencrypt");
- if (!h)
- return -EINVAL;
-
- r = reenc_keyslot_alloc(cd, hdr, keyslot, params);
- if (r < 0)
- return r;
-
- r = LUKS2_keyslot_priority_set(cd, hdr, keyslot, CRYPT_SLOT_PRIORITY_IGNORE, 0);
- if (r < 0)
- return r;
-
- r = h->validate(cd, LUKS2_get_keyslot_jobj(hdr, keyslot));
- if (r) {
- log_dbg(cd, "Keyslot validation failed.");
- return r;
- }
-
- return 0;
-}
-
int LUKS2_keyslot_reencrypt_store(struct crypt_device *cd,
struct luks2_hdr *hdr,
int keyslot,
if (!LUKS2_get_keyslot_jobj(hdr, keyslot)) {
/* Try to allocate default and empty keyslot type */
- h = LUKS2_keyslot_handler_type(cd, "luks2");
+ h = LUKS2_keyslot_handler_type("luks2");
if (!h)
return -EINVAL;
return h->dump(cd, keyslot);
}
-crypt_keyslot_priority LUKS2_keyslot_priority_get(struct crypt_device *cd,
- struct luks2_hdr *hdr, int keyslot)
+crypt_keyslot_priority LUKS2_keyslot_priority_get(struct luks2_hdr *hdr, int keyslot)
{
json_object *jobj_keyslot, *jobj_priority;
int placeholder_keyslot_alloc(struct crypt_device *cd,
int keyslot,
uint64_t area_offset,
- uint64_t area_length,
- size_t volume_key_len)
+ uint64_t area_length)
{
struct luks2_hdr *hdr;
json_object *jobj_keyslots, *jobj_keyslot, *jobj_area;
json_object_object_foreach(jobj_keyslots, slot, val) {
keyslot = atoi(slot);
json_object_object_get_ex(val, "type", &jobj_type);
- h = LUKS2_keyslot_handler_type(cd, json_object_get_string(jobj_type));
+ h = LUKS2_keyslot_handler_type(json_object_get_string(jobj_type));
if (!h)
continue;
if (h->validate && h->validate(cd, val)) {
return -EINVAL;
}
- if (!(reqs & CRYPT_REQUIREMENT_ONLINE_REENCRYPT) && reencrypt_count) {
+ if (reencrypt_count && !LUKS2_reencrypt_requirement_candidate(&dummy)) {
log_dbg(cd, "Missing reencryption requirement flag.");
return -EINVAL;
}
!json_object_is_type(jobj_type, json_type_string))
continue;
- h = LUKS2_keyslot_handler_type(cd, json_object_get_string(jobj_type));
+ h = LUKS2_keyslot_handler_type(json_object_get_string(jobj_type));
if (h && h->repair)
- h->repair(cd, val);
+ h->repair(val);
}
}
return -ENOENT;
}
+
+/* assumes valid header, it does not move references in tokens/digests etc! */
+int LUKS2_keyslot_swap(struct crypt_device *cd, struct luks2_hdr *hdr,
+ int keyslot, int keyslot2)
+{
+ json_object *jobj_keyslots, *jobj_keyslot, *jobj_keyslot2;
+ int r;
+
+ if (!json_object_object_get_ex(hdr->jobj, "keyslots", &jobj_keyslots))
+ return -EINVAL;
+
+ jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, keyslot);
+ if (!jobj_keyslot)
+ return -EINVAL;
+
+ jobj_keyslot2 = LUKS2_get_keyslot_jobj(hdr, keyslot2);
+ if (!jobj_keyslot2)
+ return -EINVAL;
+
+ /* This transfer owner of object, no need for json_object_put */
+ json_object_get(jobj_keyslot);
+ json_object_get(jobj_keyslot2);
+
+ json_object_object_del_by_uint(jobj_keyslots, keyslot);
+ r = json_object_object_add_by_uint(jobj_keyslots, keyslot, jobj_keyslot2);
+ if (r < 0) {
+ log_dbg(cd, "Failed to swap keyslot %d.", keyslot);
+ return r;
+ }
+
+ json_object_object_del_by_uint(jobj_keyslots, keyslot2);
+ r = json_object_object_add_by_uint(jobj_keyslots, keyslot2, jobj_keyslot);
+ if (r < 0)
+ log_dbg(cd, "Failed to swap keyslot2 %d.", keyslot2);
+
+ return r;
+}