Skip to content

Commit 0cf87a4

Browse files
onikombroz
authored andcommitted
Add support for --decrypt init by keyslot contexts.
1 parent cf29d51 commit 0cf87a4

1 file changed

Lines changed: 123 additions & 44 deletions

File tree

src/utils_reencrypt.c

Lines changed: 123 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -35,24 +35,6 @@ static void _set_reencryption_flags(uint32_t *flags)
3535
*flags |= CRYPT_REENCRYPT_RESUME_ONLY;
3636
}
3737

38-
static int reencrypt_check_passphrase(struct crypt_device *cd,
39-
int keyslot,
40-
const char *passphrase,
41-
size_t passphrase_len)
42-
{
43-
int r;
44-
45-
assert(cd);
46-
47-
r = crypt_activate_by_passphrase(cd, NULL, keyslot,
48-
passphrase, passphrase_len, 0);
49-
check_signal(&r);
50-
tools_passphrase_msg(r);
51-
tools_keyslot_msg(r, UNLOCKED);
52-
53-
return r;
54-
}
55-
5638
static int set_keyslot_params(struct crypt_device *cd, int keyslot)
5739
{
5840
const char *cipher;
@@ -266,6 +248,114 @@ static int reencrypt_hint_force_offline_reencrypt(const char *data_device)
266248
return 0;
267249
}
268250

251+
/* libcryptsetup API does not provide function to get old volume key size directly */
252+
static int reencrypt_get_decrypt_volume_key_size(struct crypt_device *cd, int keyslot)
253+
{
254+
int i;
255+
crypt_keyslot_info ki;
256+
257+
if (keyslot != CRYPT_ANY_SLOT) {
258+
ki = crypt_keyslot_status(cd, keyslot);
259+
if (ki == CRYPT_SLOT_INVALID)
260+
return -EINVAL;
261+
if (ki != CRYPT_SLOT_ACTIVE && ki != CRYPT_SLOT_ACTIVE_LAST)
262+
return -ENOENT;
263+
264+
return crypt_keyslot_get_key_size(cd, keyslot);
265+
}
266+
267+
for (i = 0; i < crypt_keyslot_max(CRYPT_LUKS2); i++) {
268+
switch (crypt_keyslot_status(cd, keyslot)) {
269+
case CRYPT_SLOT_INACTIVE:
270+
case CRYPT_SLOT_UNBOUND:
271+
break;
272+
case CRYPT_SLOT_ACTIVE:
273+
case CRYPT_SLOT_ACTIVE_LAST:
274+
return crypt_keyslot_get_key_size(cd, keyslot);
275+
default:
276+
return -EINVAL;
277+
}
278+
}
279+
280+
return -ENOENT;
281+
}
282+
283+
static int reencrypt_single_key_unlock(struct crypt_device *cd,
284+
const struct crypt_params_reencrypt *params,
285+
struct crypt_keyslot_context **r_kc)
286+
{
287+
int r, tries, keysize = 0;
288+
struct crypt_keyslot_context *kc = NULL, *dummy = NULL;
289+
290+
assert(params);
291+
assert(r_kc);
292+
293+
if (ARG_SET(OPT_KEY_SIZE_ID))
294+
keysize = ARG_UINT32(OPT_KEY_SIZE_ID) / 8;
295+
296+
if (ARG_SET(OPT_VOLUME_KEY_FILE_ID) || ARG_SET(OPT_VOLUME_KEY_KEYRING_ID)) {
297+
if (!keysize && params->mode == CRYPT_REENCRYPT_DECRYPT)
298+
keysize = reencrypt_get_decrypt_volume_key_size(cd, ARG_INT32(OPT_KEY_SLOT_ID));
299+
else if (!keysize && params->mode == CRYPT_REENCRYPT_ENCRYPT)
300+
keysize = crypt_get_volume_key_size(cd);
301+
302+
if (keysize <= 0 && !ARG_SET(OPT_VOLUME_KEY_KEYRING_ID)) {
303+
log_err(_("Cannot determine volume key size for LUKS without keyslots, please use --key-size option."));
304+
return -EINVAL;
305+
}
306+
307+
r = luks_init_keyslot_contexts_by_volume_keys(cd, ARG_STR(OPT_VOLUME_KEY_FILE_ID),
308+
NULL /* unused */,
309+
keysize,
310+
0 /* unused */,
311+
ARG_STR(OPT_VOLUME_KEY_KEYRING_ID),
312+
NULL /* unused */,
313+
&kc, &dummy);
314+
if (r < 0)
315+
goto out;
316+
r = crypt_activate_by_keyslot_context(cd, NULL, ARG_INT32(OPT_KEY_SLOT_ID),
317+
kc, CRYPT_ANY_SLOT, NULL, 0);
318+
} else {
319+
r = luks_try_token_unlock(cd, ARG_INT32(OPT_KEY_SLOT_ID),
320+
ARG_INT32(OPT_TOKEN_ID_ID), NULL,
321+
ARG_STR(OPT_TOKEN_TYPE_ID), 0,
322+
set_tries_tty(false), true,
323+
ARG_SET(OPT_TOKEN_ONLY_ID) || ARG_SET(OPT_TOKEN_ID_ID) || ARG_SET(OPT_TOKEN_TYPE_ID),
324+
&kc);
325+
326+
if (r >= 0 || quit || ARG_SET(OPT_TOKEN_ONLY_ID))
327+
goto out;
328+
329+
r = -ENOENT;
330+
331+
tries = set_tries_tty(true);
332+
do {
333+
crypt_keyslot_context_free(kc);
334+
kc = NULL;
335+
r = luks_init_keyslot_context(cd, NULL, verify_passphrase(0), false, &kc);
336+
if (r < 0)
337+
goto out;
338+
339+
r = crypt_activate_by_keyslot_context(cd, NULL, ARG_INT32(OPT_KEY_SLOT_ID),
340+
kc, CRYPT_ANY_SLOT, NULL, 0);
341+
342+
tools_keyslot_msg(r, UNLOCKED);
343+
tools_passphrase_msg(r);
344+
check_signal(&r);
345+
} while ((r == -EPERM || r == -ERANGE) && (--tries > 0));
346+
}
347+
348+
out:
349+
if (r >= 0)
350+
*r_kc = kc;
351+
else
352+
crypt_keyslot_context_free(kc);
353+
354+
crypt_keyslot_context_free(dummy); /* unused */
355+
356+
return r;
357+
}
358+
269359
static int reencrypt_luks2_load(struct crypt_device *cd, const char *data_device)
270360
{
271361
char *msg;
@@ -732,9 +822,8 @@ static int decrypt_luks2_datashift_init(struct crypt_device **cd,
732822
const char *expheader)
733823
{
734824
int fd, r;
735-
size_t passwordLen;
736825
struct stat hdr_st;
737-
char *msg, *data_device, *active_name = NULL, *password = NULL;
826+
char *msg, *data_device, *active_name = NULL;
738827
bool remove_header = false;
739828
struct crypt_params_reencrypt params = {
740829
.mode = CRYPT_REENCRYPT_DECRYPT,
@@ -745,6 +834,7 @@ static int decrypt_luks2_datashift_init(struct crypt_device **cd,
745834
.max_hotzone_size = ARG_UINT64(OPT_HOTZONE_SIZE_ID) / SECTOR_SIZE,
746835
.flags = CRYPT_REENCRYPT_MOVE_FIRST_SEGMENT
747836
};
837+
struct crypt_keyslot_context *kc = NULL;
748838

749839
assert(expheader);
750840
assert(cd && *cd);
@@ -775,14 +865,7 @@ static int decrypt_luks2_datashift_init(struct crypt_device **cd,
775865
if (r < 0)
776866
goto out;
777867

778-
r = tools_get_key(NULL, &password, &passwordLen,
779-
ARG_UINT64(OPT_KEYFILE_OFFSET_ID), ARG_UINT32(OPT_KEYFILE_SIZE_ID),
780-
ARG_STR(OPT_KEY_FILE_ID), ARG_UINT32(OPT_TIMEOUT_ID),
781-
verify_passphrase(0), 0, *cd);
782-
if (r < 0)
783-
goto out;
784-
785-
r = reencrypt_check_passphrase(*cd, ARG_INT32(OPT_KEY_SLOT_ID), password, passwordLen);
868+
r = reencrypt_single_key_unlock(*cd, &params, &kc);
786869
if (r < 0)
787870
goto out;
788871

@@ -844,9 +927,9 @@ static int decrypt_luks2_datashift_init(struct crypt_device **cd,
844927

845928
remove_header = false;
846929

847-
r = crypt_reencrypt_init_by_passphrase(*cd, active_name, password,
848-
passwordLen, ARG_INT32(OPT_KEY_SLOT_ID), CRYPT_ANY_SLOT,
849-
NULL, NULL, &params);
930+
r = crypt_reencrypt_init_by_keyslot_context(*cd, active_name, kc, NULL,
931+
ARG_INT32(OPT_KEY_SLOT_ID),
932+
CRYPT_ANY_SLOT, NULL, NULL, &params);
850933

851934
if (r < 0 && crypt_reencrypt_status(*cd, NULL) == CRYPT_REENCRYPT_NONE) {
852935
/* if restore is successful we can remove header backup */
@@ -856,7 +939,7 @@ static int decrypt_luks2_datashift_init(struct crypt_device **cd,
856939
out:
857940
free(active_name);
858941
free(data_device);
859-
crypt_safe_free(password);
942+
crypt_keyslot_context_free(kc);
860943

861944
if (r < 0 && !remove_header && !stat(expheader, &hdr_st) && S_ISREG(hdr_st.st_mode))
862945
log_err(_("Reencryption initialization failed. Header backup is available in %s."),
@@ -870,8 +953,7 @@ static int decrypt_luks2_datashift_init(struct crypt_device **cd,
870953
static int decrypt_luks2_init(struct crypt_device *cd, const char *data_device)
871954
{
872955
int r;
873-
size_t passwordLen;
874-
char *active_name = NULL, *password = NULL;
956+
char *active_name = NULL;
875957
struct crypt_params_reencrypt params = {
876958
.mode = CRYPT_REENCRYPT_DECRYPT,
877959
.direction = data_shift > 0 ? CRYPT_REENCRYPT_FORWARD : CRYPT_REENCRYPT_BACKWARD,
@@ -881,6 +963,7 @@ static int decrypt_luks2_init(struct crypt_device *cd, const char *data_device)
881963
.device_size = ARG_UINT64(OPT_DEVICE_SIZE_ID) / SECTOR_SIZE,
882964
.max_hotzone_size = ARG_UINT64(OPT_HOTZONE_SIZE_ID) / SECTOR_SIZE,
883965
};
966+
struct crypt_keyslot_context *kc = NULL;
884967

885968
if (!luks2_reencrypt_eligible(cd))
886969
return -EINVAL;
@@ -897,25 +980,21 @@ static int decrypt_luks2_init(struct crypt_device *cd, const char *data_device)
897980

898981
_set_reencryption_flags(&params.flags);
899982

900-
r = tools_get_key(NULL, &password, &passwordLen,
901-
ARG_UINT64(OPT_KEYFILE_OFFSET_ID), ARG_UINT32(OPT_KEYFILE_SIZE_ID), ARG_STR(OPT_KEY_FILE_ID),
902-
ARG_UINT32(OPT_TIMEOUT_ID), verify_passphrase(0), 0, cd);
903-
if (r < 0)
904-
return r;
905-
906-
r = reencrypt_check_passphrase(cd, ARG_INT32(OPT_KEY_SLOT_ID), password, passwordLen);
983+
r = reencrypt_single_key_unlock(cd, &params, &kc);
907984
if (r < 0)
908985
goto out;
909986

910987
if (!ARG_SET(OPT_FORCE_OFFLINE_REENCRYPT_ID))
911988
r = reencrypt_get_active_name(cd, data_device, &active_name);
912989
if (r >= 0)
913-
r = crypt_reencrypt_init_by_passphrase(cd, active_name, password,
914-
passwordLen, ARG_INT32(OPT_KEY_SLOT_ID), CRYPT_ANY_SLOT, NULL, NULL, &params);
990+
r = crypt_reencrypt_init_by_keyslot_context(cd, active_name, kc, NULL,
991+
ARG_INT32(OPT_KEY_SLOT_ID),
992+
CRYPT_ANY_SLOT, NULL, NULL,
993+
&params);
915994

916995
out:
917996
free(active_name);
918-
crypt_safe_free(password);
997+
crypt_keyslot_context_free(kc);
919998
return r;
920999
}
9211000

0 commit comments

Comments
 (0)