cryptsetup.c 59.6 KB
Newer Older
1 2 3
/*
 * cryptsetup - setup cryptographic volumes for dm-crypt
 *
Milan Broz's avatar
Milan Broz committed
4
 * Copyright (C) 2004, Jana Saout <jana@saout.de>
5
 * Copyright (C) 2004-2007, Clemens Fruhwirth <clemens@endorphin.org>
Milan Broz's avatar
Milan Broz committed
6 7
 * Copyright (C) 2009-2017, Red Hat, Inc. All rights reserved.
 * Copyright (C) 2009-2017, Milan Broz
8 9 10
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
11 12
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
13 14 15 16 17 18 19 20
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
21
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 23
 */

24 25
#include "cryptsetup.h"

26 27
static const char *opt_cipher = NULL;
static const char *opt_hash = NULL;
28
static int opt_verify_passphrase = 0;
Milan Broz's avatar
Milan Broz committed
29

30
static const char *opt_key_file = NULL;
31
static const char *opt_keyfile_stdin = NULL;
Milan Broz's avatar
Milan Broz committed
32 33 34
static int opt_keyfiles_count = 0;
static const char *opt_keyfiles[MAX_KEYFILES];

35 36 37
static const char *opt_master_key_file = NULL;
static const char *opt_header_backup_file = NULL;
static const char *opt_uuid = NULL;
38
static const char *opt_header_device = NULL;
39
static const char *opt_type = "luks";
40 41 42
static int opt_key_size = 0;
static long opt_keyfile_size = 0;
static long opt_new_keyfile_size = 0;
43 44
static long opt_keyfile_offset = 0;
static long opt_new_keyfile_offset = 0;
45
static int opt_key_slot = CRYPT_ANY_SLOT;
46 47 48
static uint64_t opt_size = 0;
static uint64_t opt_offset = 0;
static uint64_t opt_skip = 0;
49
static int opt_skip_valid = 0;
50 51 52 53 54
static int opt_readonly = 0;
static int opt_version_mode = 0;
static int opt_timeout = 0;
static int opt_tries = 3;
static int opt_align_payload = 0;
55 56
static int opt_random = 0;
static int opt_urandom = 0;
57
static int opt_dump_master_key = 0;
58
static int opt_shared = 0;
59
static int opt_allow_discards = 0;
60 61
static int opt_perf_same_cpu_crypt = 0;
static int opt_perf_submit_from_crypt_cpus = 0;
62
static int opt_test_passphrase = 0;
63 64
static int opt_tcrypt_hidden = 0;
static int opt_tcrypt_system = 0;
65
static int opt_tcrypt_backup = 0;
66
static int opt_veracrypt = 0;
67 68
static int opt_veracrypt_pim = -1;
static int opt_veracrypt_query_pim = 0;
69
static int opt_deferred_remove = 0;
70
//FIXME: check uint32 overflow for long type
71
static const char *opt_pbkdf = NULL;
Milan Broz's avatar
Milan Broz committed
72 73
static long opt_pbkdf_memory = 1024;
static long opt_pbkdf_parallel = 2;
74 75
static long opt_pbkdf_iterations = 0;
static int opt_iteration_time = 0;
76 77 78

static const char **action_argv;
static int action_argc;
79
static const char *null_action_argv[] = {NULL, NULL};
80

81 82 83 84 85 86 87 88
static const char *uuid_or_device_header(const char **data_device)
{
	if (data_device)
		*data_device = opt_header_device ? action_argv[0] : NULL;

	return uuid_or_device(opt_header_device ?: action_argv[0]);
}

89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
static int _verify_passphrase(int def)
{
	/* Batch mode switch off verify - if not overrided by -y */
	if (opt_verify_passphrase)
		def = 1;
	else if (opt_batch_mode)
		def = 0;

	/* Non-tty input doesn't allow verify */
	if (def && !isatty(STDIN_FILENO)) {
		if (opt_verify_passphrase)
			log_err(_("Can't do passphrase verification on non-tty inputs.\n"));
		def = 0;
	}

	return def;
}

107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
static void _set_activation_flags(uint32_t *flags)
{
	if (opt_readonly)
		*flags |= CRYPT_ACTIVATE_READONLY;

	if (opt_allow_discards)
		*flags |= CRYPT_ACTIVATE_ALLOW_DISCARDS;

	if (opt_perf_same_cpu_crypt)
		*flags |= CRYPT_ACTIVATE_SAME_CPU_CRYPT;

	if (opt_perf_submit_from_crypt_cpus)
		*flags |= CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS;
}

122
static int action_open_plain(void)
123
{
124 125 126
	struct crypt_device *cd = NULL;
	char cipher[MAX_CIPHER_LEN], cipher_mode[MAX_CIPHER_LEN];
	struct crypt_params_plain params = {
127
		.hash = opt_hash ?: DEFAULT_PLAIN_HASH,
128
		.skip = opt_skip,
129
		.offset = opt_offset,
130
		.size = opt_size,
131
	};
132
	char *password = NULL;
133
	size_t passwordLen, key_size_max;
134
	size_t key_size = (opt_key_size ?: DEFAULT_PLAIN_KEYBITS) / 8;
135
	uint32_t activate_flags = 0;
136
	int r;
137

138
	r = crypt_parse_name_and_mode(opt_cipher ?: DEFAULT_CIPHER(PLAIN),
139
				      cipher, NULL, cipher_mode);
140
	if (r < 0) {
141
		log_err(_("No known cipher specification pattern detected.\n"));
142 143 144
		goto out;
	}

145
	/* FIXME: temporary hack, no hashing for keyfiles in plain mode */
146
	if (opt_key_file && !tools_is_stdin(opt_key_file)) {
147 148 149 150 151 152 153 154 155
		params.hash = NULL;
		if (!opt_batch_mode && opt_hash)
			log_std(_("WARNING: The --hash parameter is being ignored "
				 "in plain mode with keyfile specified.\n"));
	}

	if (params.hash && !strcmp(params.hash, "plain"))
		params.hash = NULL;

156
	if (!opt_batch_mode && !params.hash && opt_key_file && !tools_is_stdin(opt_key_file) && opt_keyfile_size)
157 158 159
		log_std(_("WARNING: The --keyfile-size option is being ignored, "
			 "the read size is the same as the encryption key size.\n"));

160
	if ((r = crypt_init(&cd, action_argv[0])))
161 162 163 164 165
		goto out;

	r = crypt_format(cd, CRYPT_PLAIN,
			 cipher, cipher_mode,
			 NULL, NULL,
166
			 key_size,
167
			 &params);
168
	check_signal(&r);
169 170 171
	if (r < 0)
		goto out;

172 173 174
	if (opt_shared)
		activate_flags |= CRYPT_ACTIVATE_SHARED;

175
	_set_activation_flags(&activate_flags);
176

177
	if (!tools_is_stdin(opt_key_file)) {
178 179 180 181 182
		/* If no hash, key is read directly, read size is always key_size
		 * (possible opt_keyfile_size is ignored.
		 * If hash is specified, opt_keyfile_size is applied.
		 * The opt_keyfile_offset is applied always.
		 */
183
		key_size_max = params.hash ? (size_t)opt_keyfile_size : key_size;
184
		r = crypt_activate_by_keyfile_offset(cd, action_argv[1],
185 186
			CRYPT_ANY_SLOT, opt_key_file, key_size_max,
			opt_keyfile_offset, activate_flags);
187
	} else {
188
		key_size_max = (opt_key_file && !params.hash) ? key_size : (size_t)opt_keyfile_size;
189
		r = tools_get_key(NULL, &password, &passwordLen,
190
				  opt_keyfile_offset, key_size_max,
191
				  opt_key_file, opt_timeout,
192
				  _verify_passphrase(0), 0, cd);
193 194 195
		if (r < 0)
			goto out;

196
		r = crypt_activate_by_passphrase(cd, action_argv[1],
197
			CRYPT_ANY_SLOT, password, passwordLen, activate_flags);
198
	}
199 200 201 202
out:
	crypt_free(cd);
	crypt_safe_free(password);

203
	return r;
204 205
}

206
static int action_open_loopaes(void)
207 208 209
{
	struct crypt_device *cd = NULL;
	struct crypt_params_loopaes params = {
210
		.hash = opt_hash ?: NULL,
211
		.offset = opt_offset,
212
		.skip = opt_skip_valid ? opt_skip : opt_offset,
213
	};
214
	unsigned int key_size = (opt_key_size ?: DEFAULT_LOOPAES_KEYBITS) / 8;
215
	uint32_t activate_flags = 0;
216 217 218 219 220 221 222
	int r;

	if (!opt_key_file) {
		log_err(_("Option --key-file is required.\n"));
		return -EINVAL;
	}

223
	_set_activation_flags(&activate_flags);
224

225
	if ((r = crypt_init(&cd, action_argv[0])))
226 227
		goto out;

228 229
	r = crypt_format(cd, CRYPT_LOOPAES, opt_cipher ?: DEFAULT_LOOPAES_CIPHER,
			 NULL, NULL, NULL, key_size, &params);
230
	check_signal(&r);
231 232 233
	if (r < 0)
		goto out;

234 235
	r = crypt_activate_by_keyfile_offset(cd, action_argv[1], CRYPT_ANY_SLOT,
				      opt_key_file, opt_keyfile_size,
236
				      opt_keyfile_offset, activate_flags);
237 238 239 240 241 242
out:
	crypt_free(cd);

	return r;
}

243 244 245 246
static int tcrypt_load(struct crypt_device *cd, struct crypt_params_tcrypt *params)
{
	int r, tries = opt_tries, eperm = 0;

247 248 249
	if (opt_keyfile_stdin)
		tries = 1;

250 251
	do {
		/* TCRYPT header is encrypted, get passphrase now */
252
		r = tools_get_key(NULL, CONST_CAST(char**)&params->passphrase,
253
				  &params->passphrase_size, 0, 0, opt_keyfile_stdin, opt_timeout,
254 255 256 257
				 _verify_passphrase(0), 0, cd);
		if (r < 0)
			continue;

258 259
		if (opt_veracrypt_query_pim) {
			char *tmp_pim_nptr = NULL;
260
			char *tmp_pim_end = NULL;
261
			size_t tmp_pim_size = 0;
Milan Broz's avatar
Milan Broz committed
262
			unsigned long long tmp_pim_ull = 0;
263 264 265 266 267 268 269 270

			r = tools_get_key(_("Enter VeraCrypt PIM: "),
					CONST_CAST(char**)&tmp_pim_nptr,
					&tmp_pim_size, 0, 0, opt_keyfile_stdin, opt_timeout,
					_verify_passphrase(0), 0, cd);
			if (r < 0)
				continue;

Milan Broz's avatar
Milan Broz committed
271
			tmp_pim_ull = strtoull(tmp_pim_nptr, &tmp_pim_end, 10);
272
			if (*tmp_pim_nptr == '\0' || !tmp_pim_end || *tmp_pim_end != '\0') {
273 274
				log_err(_("Invalid PIM value: parse error\n"));
				r = -EINVAL;
Milan Broz's avatar
Milan Broz committed
275
			} else if (tmp_pim_ull == 0) {
276 277
				log_err(_("Invalid PIM value: 0\n"));
				r = -EINVAL;
Milan Broz's avatar
Milan Broz committed
278
			} else if (tmp_pim_ull > UINT32_MAX) {
279 280 281 282 283 284 285
				log_err(_("Invalid PIM value: outside of range\n"));
				r = -ERANGE;
			}
			crypt_safe_free(CONST_CAST(char*)tmp_pim_nptr);
			if (r < 0)
				continue;

Milan Broz's avatar
Milan Broz committed
286 287
			params->veracrypt_pim = (uint32_t)tmp_pim_ull;
			crypt_memzero(&tmp_pim_ull, sizeof(tmp_pim_ull));
288 289
		}

290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311
		if (opt_tcrypt_hidden)
			params->flags |= CRYPT_TCRYPT_HIDDEN_HEADER;

		if (opt_tcrypt_system)
			params->flags |= CRYPT_TCRYPT_SYSTEM_HEADER;

		if (opt_tcrypt_backup)
			params->flags |= CRYPT_TCRYPT_BACKUP_HEADER;

		r = crypt_load(cd, CRYPT_TCRYPT, params);

		if (r == -EPERM) {
			log_err(_("No device header detected with this passphrase.\n"));
			eperm = 1;
		}

		if (r < 0) {
			crypt_safe_free(CONST_CAST(char*)params->passphrase);
			params->passphrase = NULL;
			params->passphrase_size = 0;
		}
		check_signal(&r);
312
	} while ((r == -EPERM || r == -ERANGE) && (--tries > 0));
313 314 315 316 317 318 319 320

	/* Report wrong passphrase if at least one try failed */
	if (eperm && r == -EPIPE)
		r = -EPERM;

	return r;
}

321
static int action_open_tcrypt(void)
Milan Broz's avatar
Milan Broz committed
322 323
{
	struct crypt_device *cd = NULL;
Milan Broz's avatar
Milan Broz committed
324 325 326
	struct crypt_params_tcrypt params = {
		.keyfiles = opt_keyfiles,
		.keyfiles_count = opt_keyfiles_count,
327 328
		.flags = CRYPT_TCRYPT_LEGACY_MODES |
			 (opt_veracrypt ? CRYPT_TCRYPT_VERA_MODES : 0),
329
		.veracrypt_pim = (opt_veracrypt_pim > 0) ? opt_veracrypt_pim : 0,
Milan Broz's avatar
Milan Broz committed
330
	};
Milan Broz's avatar
Milan Broz committed
331
	const char *activated_name;
332
	uint32_t activate_flags = 0;
Milan Broz's avatar
Milan Broz committed
333 334 335 336 337 338 339
	int r;

	activated_name = opt_test_passphrase ? NULL : action_argv[1];

	if ((r = crypt_init(&cd, action_argv[0])))
		goto out;

340
	r = tcrypt_load(cd, &params);
Milan Broz's avatar
Milan Broz committed
341 342 343
	if (r < 0)
		goto out;

344
	_set_activation_flags(&activate_flags);
345

346
	if (activated_name)
347
		r = crypt_activate_by_volume_key(cd, activated_name, NULL, 0, activate_flags);
Milan Broz's avatar
Milan Broz committed
348 349 350
out:
	crypt_free(cd);
	crypt_safe_free(CONST_CAST(char*)params.passphrase);
351
	crypt_memzero(&params.veracrypt_pim, sizeof(params.veracrypt_pim));
Milan Broz's avatar
Milan Broz committed
352 353 354
	return r;
}

355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396
static int tcryptDump_with_volume_key(struct crypt_device *cd)
{
	char *vk = NULL;
	size_t vk_size;
	unsigned i;
	int r;

	crypt_set_confirm_callback(cd, yesDialog, NULL);
	if (!yesDialog(
	    _("Header dump with volume key is sensitive information\n"
	      "which allows access to encrypted partition without passphrase.\n"
	      "This dump should be always stored encrypted on safe place."),
	      NULL))
		return -EPERM;

	vk_size = crypt_get_volume_key_size(cd);
	vk = crypt_safe_alloc(vk_size);
	if (!vk)
		return -ENOMEM;

	r = crypt_volume_key_get(cd, CRYPT_ANY_SLOT, vk, &vk_size, NULL, 0);
	if (r < 0)
		goto out;

	log_std("TCRYPT header information for %s\n", crypt_get_device_name(cd));
	log_std("Cipher chain:  \t%s\n", crypt_get_cipher(cd));
	log_std("Cipher mode:   \t%s\n", crypt_get_cipher_mode(cd));
	log_std("Payload offset:\t%d\n", (int)crypt_get_data_offset(cd));
	log_std("MK bits:       \t%d\n", (int)vk_size * 8);
	log_std("MK dump:\t");

	for(i = 0; i < vk_size; i++) {
		if (i && !(i % 16))
			log_std("\n\t\t");
		log_std("%02hhx ", (char)vk[i]);
	}
	log_std("\n");
out:
	crypt_safe_free(vk);
	return r;
}

397
static int action_tcryptDump(void)
Milan Broz's avatar
Milan Broz committed
398 399 400 401 402
{
	struct crypt_device *cd = NULL;
	struct crypt_params_tcrypt params = {
		.keyfiles = opt_keyfiles,
		.keyfiles_count = opt_keyfiles_count,
403 404
		.flags = CRYPT_TCRYPT_LEGACY_MODES |
			 (opt_veracrypt ? CRYPT_TCRYPT_VERA_MODES : 0),
Milan Broz's avatar
Milan Broz committed
405 406 407 408 409 410
	};
	int r;

	if ((r = crypt_init(&cd, action_argv[0])))
		goto out;

411
	r = tcrypt_load(cd, &params);
Milan Broz's avatar
Milan Broz committed
412 413 414
	if (r < 0)
		goto out;

415 416 417 418
	if (opt_dump_master_key)
		r = tcryptDump_with_volume_key(cd);
	else
		r = crypt_dump(cd);
Milan Broz's avatar
Milan Broz committed
419 420 421 422 423 424
out:
	crypt_free(cd);
	crypt_safe_free(CONST_CAST(char*)params.passphrase);
	return r;
}

425
static int action_close(void)
426
{
427
	struct crypt_device *cd = NULL;
428
	crypt_status_info ci;
429
	uint32_t flags = 0;
430 431
	int r;

432 433 434
	if (opt_deferred_remove)
		flags |= CRYPT_DEACTIVATE_DEFERRED;

435 436
	r = crypt_init_by_name(&cd, action_argv[0]);
	if (r == 0)
437
		r = crypt_deactivate_by_name(cd, action_argv[0], flags);
438

439 440 441 442 443 444 445
	if (!r && opt_deferred_remove) {
		ci = crypt_status(cd, action_argv[0]);
		if (ci == CRYPT_ACTIVE || ci == CRYPT_BUSY)
			log_std(_("Device %s is still active and scheduled for deferred removal.\n"),
				  action_argv[0]);
	}

446 447
	crypt_free(cd);
	return r;
448 449
}

450
static int action_resize(void)
451
{
452 453 454
	struct crypt_device *cd = NULL;
	int r;

455
	r = crypt_init_by_name_and_header(&cd, action_argv[0], opt_header_device);
456 457
	if (r == 0)
		r = crypt_resize(cd, action_argv[0], opt_size);
458

459 460
	crypt_free(cd);
	return r;
461 462
}

463
static int action_status(void)
464
{
465 466 467
	crypt_status_info ci;
	struct crypt_active_device cad;
	struct crypt_device *cd = NULL;
468 469
	char *backing_file;
	const char *device;
470 471 472
	int path = 0, r = 0;

	/* perhaps a path, not a dm device name */
473
	if (strchr(action_argv[0], '/'))
474
		path = 1;
475

476 477 478
	ci = crypt_status(NULL, action_argv[0]);
	switch (ci) {
	case CRYPT_INVALID:
479
		r = -EINVAL;
480 481
		break;
	case CRYPT_INACTIVE:
482 483 484 485
		if (path)
			log_std("%s is inactive.\n", action_argv[0]);
		else
			log_std("%s/%s is inactive.\n", crypt_get_dir(), action_argv[0]);
486
		r = -ENODEV;
487 488 489
		break;
	case CRYPT_ACTIVE:
	case CRYPT_BUSY:
490 491 492 493 494 495
		if (path)
			log_std("%s is active%s.\n", action_argv[0],
				ci == CRYPT_BUSY ? " and is in use" : "");
		else
			log_std("%s/%s is active%s.\n", crypt_get_dir(), action_argv[0],
				ci == CRYPT_BUSY ? " and is in use" : "");
496 497

		r = crypt_init_by_name_and_header(&cd, action_argv[0], opt_header_device);
498
		if (r < 0)
499
			goto out;
500

501
		log_std("  type:    %s\n", crypt_get_type(cd) ?: "n/a");
502 503 504 505 506 507 508

		r = crypt_get_active_device(cd, action_argv[0], &cad);
		if (r < 0)
			goto out;

		log_std("  cipher:  %s-%s\n", crypt_get_cipher(cd), crypt_get_cipher_mode(cd));
		log_std("  keysize: %d bits\n", crypt_get_volume_key_size(cd) * 8);
509 510 511 512 513 514 515
		device = crypt_get_device_name(cd);
		log_std("  device:  %s\n", device);
		if (crypt_loop_device(device)) {
			backing_file = crypt_loop_backing_file(device);
			log_std("  loop:    %s\n", backing_file);
			free(backing_file);
		}
516 517 518 519 520 521
		log_std("  offset:  %" PRIu64 " sectors\n", cad.offset);
		log_std("  size:    %" PRIu64 " sectors\n", cad.size);
		if (cad.iv_offset)
			log_std("  skipped: %" PRIu64 " sectors\n", cad.iv_offset);
		log_std("  mode:    %s\n", cad.flags & CRYPT_ACTIVATE_READONLY ?
					   "readonly" : "read/write");
522
		if (cad.flags & (CRYPT_ACTIVATE_ALLOW_DISCARDS|
523
				 CRYPT_ACTIVATE_SAME_CPU_CRYPT|
524 525 526 527 528
				 CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS))
			log_std("  flags:   %s%s%s\n",
				(cad.flags & CRYPT_ACTIVATE_ALLOW_DISCARDS) ? "discards " : "",
				(cad.flags & CRYPT_ACTIVATE_SAME_CPU_CRYPT) ? "same_cpu_crypt " : "",
				(cad.flags & CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS) ? "submit_from_crypt_cpus" : "");
529
	}
530 531
out:
	crypt_free(cd);
532 533
	if (r == -ENOTSUP)
		r = 0;
534 535 536
	return r;
}

537
static int benchmark_callback(uint32_t time_ms, void *usrptr)
538 539 540 541 542 543 544 545 546
{
	struct crypt_pbkdf_type *pbkdf = usrptr;
	int r = 0;

	check_signal(&r);
	if (r)
		log_err("Benchmark interrupted.\n");
	else
		log_dbg("PBKDF benchmark: memory cost = %u, iterations = %u, "
547
			"threads = %u (took %u ms)", pbkdf->max_memory_kb,
548
			pbkdf->iterations, pbkdf->parallel_threads, time_ms);
549 550 551
	return r;
}

Milan Broz's avatar
Milan Broz committed
552
static int action_benchmark_kdf(const char *kdf, const char *hash, size_t key_size)
Milan Broz's avatar
Milan Broz committed
553 554
{
	int r;
Milan Broz's avatar
Milan Broz committed
555
	if (!strcmp(kdf, CRYPT_KDF_PBKDF2)) {
556
		struct crypt_pbkdf_type pbkdf = {
Milan Broz's avatar
Milan Broz committed
557 558 559 560 561 562
			.type = CRYPT_KDF_PBKDF2,
			.hash = hash,
			.time_ms = 1000,
		};

		r = crypt_benchmark_pbkdf(NULL, &pbkdf, "foo", 3, "bar", 3, key_size,
563
					&benchmark_callback, &pbkdf);
Milan Broz's avatar
Milan Broz committed
564 565 566 567
		if (r < 0)
			log_std("PBKDF2-%-9s     N/A\n", hash);
		else
			log_std("PBKDF2-%-9s %7u iterations per second for %zu-bit key\n",
568
				hash, pbkdf.iterations, key_size * 8);
Milan Broz's avatar
Milan Broz committed
569
	} else {
570
		struct crypt_pbkdf_type pbkdf = {
Milan Broz's avatar
Milan Broz committed
571 572 573 574 575 576 577
			.type = kdf,
			.time_ms = opt_iteration_time ?: 800,
			.max_memory_kb = opt_pbkdf_memory,
			.parallel_threads = opt_pbkdf_parallel,
		};

		r = crypt_benchmark_pbkdf(NULL, &pbkdf, "foo", 3,
578 579
			"0123456789abcdef0123456789abcdef", 32,
			key_size, &benchmark_callback, &pbkdf);
Milan Broz's avatar
Milan Broz committed
580 581 582 583 584
		if (r < 0)
			log_std("%-10s N/A\n", kdf);
		else
			log_std("%-10s %4u iterations, %5u memory, "
				"%1u parallel threads (CPUs) for "
585
				"%zu-bit key (requested %u ms time)\n", kdf,
586 587
				pbkdf.iterations, pbkdf.max_memory_kb, pbkdf.parallel_threads,
				key_size * 8, pbkdf.time_ms);
Milan Broz's avatar
Milan Broz committed
588
	}
Milan Broz's avatar
Milan Broz committed
589

Milan Broz's avatar
Milan Broz committed
590 591 592
	return r;
}

593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615
static int benchmark_cipher_loop(const char *cipher, const char *cipher_mode,
				 size_t volume_key_size, size_t iv_size,
				 double *encryption_mbs, double *decryption_mbs)
{
	int r, buffer_size = 1024 * 1024;

	do {
		r = crypt_benchmark(NULL, cipher, cipher_mode,
				    volume_key_size, iv_size, buffer_size,
				    encryption_mbs, decryption_mbs);
		if (r == -ERANGE) {
			if (buffer_size < 1024 * 1024 * 65)
				buffer_size *= 2;
			else {
				log_err(_("Result of benchmark is not reliable.\n"));
				r = -ENOENT;
			}
		}
	} while (r == -ERANGE);

	return r;
}

616
static int action_benchmark(void)
617 618
{
	static struct {
619 620
		const char *cipher;
		const char *mode;
621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637
		size_t key_size;
		size_t iv_size;
	} bciphers[] = {
		{ "aes",     "cbc", 16, 16 },
		{ "serpent", "cbc", 16, 16 },
		{ "twofish", "cbc", 16, 16 },
		{ "aes",     "cbc", 32, 16 },
		{ "serpent", "cbc", 32, 16 },
		{ "twofish", "cbc", 32, 16 },
		{ "aes",     "xts", 32, 16 },
		{ "serpent", "xts", 32, 16 },
		{ "twofish", "xts", 32, 16 },
		{ "aes",     "xts", 64, 16 },
		{ "serpent", "xts", 64, 16 },
		{ "twofish", "xts", 64, 16 },
		{  NULL, NULL, 0, 0 }
	};
638 639 640 641 642 643 644 645 646 647 648 649
	static struct {
		const char *type;
		const char *hash;
	} bkdfs[] = {
		{ CRYPT_KDF_PBKDF2,   "sha1" },
		{ CRYPT_KDF_PBKDF2,   "sha256" },
		{ CRYPT_KDF_PBKDF2,   "sha512" },
		{ CRYPT_KDF_PBKDF2,   "ripemd160" },
		{ CRYPT_KDF_PBKDF2,   "whirlpool" },
		{ CRYPT_KDF_ARGON2I,  NULL },
		{ CRYPT_KDF_ARGON2ID, NULL },
		{ NULL, NULL }
650
	};
651 652
	char cipher[MAX_CIPHER_LEN], cipher_mode[MAX_CIPHER_LEN];
	double enc_mbr = 0, dec_mbr = 0;
Milan Broz's avatar
Milan Broz committed
653
	int key_size = (opt_key_size ?: DEFAULT_PLAIN_KEYBITS) / 8;
654
	int iv_size = 16, skipped = 0;
655 656 657
	char *c;
	int i, r;

658
	log_std(_("# Tests are approximate using memory only (no storage IO).\n"));
659 660 661
	if (opt_pbkdf || opt_hash) {
		if (!opt_pbkdf && opt_hash)
			opt_pbkdf = CRYPT_KDF_PBKDF2;
662
		r = action_benchmark_kdf(opt_pbkdf, opt_hash, key_size);
Milan Broz's avatar
Milan Broz committed
663
	} else if (opt_cipher) {
664 665 666 667 668 669 670 671 672
		r = crypt_parse_name_and_mode(opt_cipher, cipher, NULL, cipher_mode);
		if (r < 0) {
			log_err(_("No known cipher specification pattern detected.\n"));
			return r;
		}
		if ((c  = strchr(cipher_mode, '-')))
			*c = '\0';

		/* FIXME: not really clever :) */
Milan Broz's avatar
Milan Broz committed
673 674 675
		if (strstr(cipher, "des") ||
		    strstr(cipher, "blowfish") ||
		    strstr(cipher, "cast5"))
676 677
			iv_size = 8;

678 679 680
		if (!strcmp(cipher_mode, "ecb"))
			iv_size = 0;

681
		r = benchmark_cipher_loop(cipher, cipher_mode,
Milan Broz's avatar
Milan Broz committed
682
					  key_size, iv_size,
683
					  &enc_mbr, &dec_mbr);
684
		if (!r) {
685 686
			log_std(N_("#     Algorithm | Key |  Encryption |  Decryption\n"));
			log_std("%11s-%s  %4db  %6.1f MiB/s  %6.1f MiB/s\n",
Milan Broz's avatar
Milan Broz committed
687
				cipher, cipher_mode, key_size*8, enc_mbr, dec_mbr);
688
		} else if (r == -ENOENT)
689
			log_err(_("Cipher %s is not available.\n"), opt_cipher);
690
	} else {
691 692
		for (i = 0; bkdfs[i].type; i++) {
			r = action_benchmark_kdf(bkdfs[i].type, bkdfs[i].hash, key_size);
693 694 695 696
			check_signal(&r);
			if (r == -EINTR)
				break;
		}
Milan Broz's avatar
Milan Broz committed
697

698
		for (i = 0; bciphers[i].cipher; i++) {
699
			r = benchmark_cipher_loop(bciphers[i].cipher, bciphers[i].mode,
700
					    bciphers[i].key_size, bciphers[i].iv_size,
701
					    &enc_mbr, &dec_mbr);
702 703
			check_signal(&r);
			if (r == -ENOTSUP || r == -EINTR)
704
				break;
705 706
			if (r == -ENOENT)
				skipped++;
707
			if (i == 0)
708
				log_std(N_("#     Algorithm | Key |  Encryption |  Decryption\n"));
709

710 711 712
			snprintf(cipher, MAX_CIPHER_LEN, "%s-%s",
				 bciphers[i].cipher, bciphers[i].mode);
			if (!r)
713
				log_std("%15s  %4zub  %6.1f MiB/s  %6.1f MiB/s\n",
714 715
					cipher, bciphers[i].key_size*8, enc_mbr, dec_mbr);
			else
716
				log_std("%15s  %4zub %13s %13s\n", cipher,
717 718
					bciphers[i].key_size*8, _("N/A"), _("N/A"));
		}
719
		if (skipped && skipped == i)
720
			r = -ENOTSUP;
721 722
	}

723 724 725 726 727 728
	if (r == -ENOTSUP) {
		log_err(_("Required kernel crypto interface not available.\n"));
#ifdef ENABLE_AF_ALG
		log_err( _("Ensure you have algif_skcipher kernel module loaded.\n"));
#endif
	}
729 730 731
	return r;
}

732 733 734 735
static int _read_mk(const char *file, char **key, int keysize)
{
	int fd;

736
	*key = crypt_safe_alloc(keysize);
737 738 739 740 741
	if (!*key)
		return -ENOMEM;

	fd = open(file, O_RDONLY);
	if (fd == -1) {
742
		log_err(_("Cannot read keyfile %s.\n"), file);
743
		goto fail;
744 745
	}
	if ((read(fd, *key, keysize) != keysize)) {
746
		log_err(_("Cannot read %d bytes from keyfile %s.\n"), keysize, file);
747
		close(fd);
748
		goto fail;
749 750 751
	}
	close(fd);
	return 0;
752 753 754 755
fail:
	crypt_safe_free(*key);
	*key = NULL;
	return -EINVAL;
756 757
}

758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778
static int set_pbkdf_params(struct crypt_device *cd, const char *dev_type)
{
	struct crypt_pbkdf_type pbkdf = {};

	if (!strcmp(dev_type, CRYPT_LUKS1)) {
		if (opt_pbkdf && strcmp(opt_pbkdf, CRYPT_KDF_PBKDF2))
			return -EINVAL;
		pbkdf.type = CRYPT_KDF_PBKDF2;
		pbkdf.hash = opt_hash ?: DEFAULT_LUKS1_HASH;
		pbkdf.time_ms = opt_iteration_time ?: DEFAULT_LUKS1_ITER_TIME;
	} else
		return 0;

	if (opt_pbkdf_iterations) {
		pbkdf.iterations = opt_pbkdf_iterations;
		pbkdf.flags |= CRYPT_PBKDF_NO_BENCHMARK;
	}

	return crypt_set_pbkdf_type(cd, &pbkdf);
}

779
static int action_luksRepair(void)
780 781 782 783 784 785 786 787
{
	struct crypt_device *cd = NULL;
	int r;

	if ((r = crypt_init(&cd, action_argv[0])))
		goto out;

	/* Currently only LUKS1 allows repair */
788
	crypt_set_log_callback(cd, quiet_log, NULL);
789
	r = crypt_load(cd, CRYPT_LUKS1, NULL);
790
	crypt_set_log_callback(cd, tool_log, NULL);
791
	if (r == 0) {
792
		log_verbose(_("No known problems detected for LUKS header.\n"));
793 794 795
		goto out;
	}

796
	r = yesDialog(_("Really try to repair LUKS device header?"),
797 798 799 800 801 802 803 804
		       NULL) ? 0 : -EINVAL;
	if (r == 0)
		r = crypt_repair(cd, CRYPT_LUKS1, NULL);
out:
	crypt_free(cd);
	return r;
}

805
static int action_luksFormat(void)
806 807
{
	int r = -EINVAL, keysize;
808
	const char *header_device;
809 810
	char *msg = NULL, *key = NULL, cipher [MAX_CIPHER_LEN], cipher_mode[MAX_CIPHER_LEN];
	char *password = NULL;
811
	size_t passwordLen;
812 813
	struct crypt_device *cd = NULL;
	struct crypt_params_luks1 params = {
814
		.hash = opt_hash ?: DEFAULT_LUKS1_HASH,
815
		.data_alignment = opt_align_payload,
816
		.data_device = opt_header_device ? action_argv[0] : NULL,
817 818
	};

819 820 821 822
	header_device = opt_header_device ?: action_argv[0];

	if(asprintf(&msg, _("This will overwrite data on %s irrevocably."),
		    header_device) == -1) {
823 824 825 826
		log_err(_("memory allocation error in action_luksFormat"));
		r = -ENOMEM;
		goto out;
	}
827
	r = yesDialog(msg, NULL) ? 0 : -EINVAL;
828
	free(msg);
829
	if (r < 0)
830 831
		goto out;

832
	r = crypt_parse_name_and_mode(opt_cipher ?: DEFAULT_CIPHER(LUKS1),
833
				      cipher, NULL, cipher_mode);
834
	if (r < 0) {
835
		log_err(_("No known cipher specification pattern detected.\n"));
836
		goto out;
837 838
	}

839 840 841 842
	/* Never call pwquality if using null cipher */
	if (tools_is_cipher_null(cipher))
		opt_force_password = 1;

843 844 845
	if ((r = crypt_init(&cd, header_device))) {
		if (opt_header_device)
			log_err(_("Cannot use %s as on-disk header.\n"), header_device);
846
		goto out;
847
	}
848

849 850
	keysize = (opt_key_size ?: DEFAULT_LUKS1_KEYBITS) / 8;

851 852 853 854 855
	if (opt_random)
		crypt_set_rng_type(cd, CRYPT_RNG_RANDOM);
	else if (opt_urandom)
		crypt_set_rng_type(cd, CRYPT_RNG_URANDOM);

856
	r = tools_get_key(NULL, &password, &passwordLen,
857
			  opt_keyfile_offset, opt_keyfile_size, opt_key_file,
858
			  opt_timeout, _verify_passphrase(1), 1, cd);
859
	if (r < 0)
860 861
		goto out;

862 863 864 865
	if (opt_master_key_file) {
		r = _read_mk(opt_master_key_file, &key, keysize);
		if (r < 0)
			goto out;
866
	}
867

868 869 870 871 872 873
	r = set_pbkdf_params(cd, CRYPT_LUKS1);
	if (r) {
		log_err(_("Failed to set pbkdf parameters.\n"));
		goto out;
	}

874 875
	r = crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode,
			 opt_uuid, key, keysize, &params);
876
	check_signal(&r);
877 878
	if (r < 0)
		goto out;
879

880 881 882
	r = crypt_keyslot_add_by_volume_key(cd, opt_key_slot,
					    key, keysize,
					    password, passwordLen);
883 884 885 886
out:
	crypt_free(cd);
	crypt_safe_free(key);
	crypt_safe_free(password);
887

888
	return r;
889 890
}

891
static int action_open_luks(void)
892
{
893
	struct crypt_device *cd = NULL;
894
	const char *data_device, *header_device, *activated_name;
895
	char *key = NULL;
896
	uint32_t activate_flags = 0;
897
	int r, keysize, tries;
898 899
	char *password = NULL;
	size_t passwordLen;
900

901
	header_device = uuid_or_device_header(&data_device);
902

903
	activated_name = opt_test_passphrase ? NULL : action_argv[1];
904

905
	if ((r = crypt_init(&cd, header_device)))
906
		goto out;
907

908 909 910
	if ((r = crypt_load(cd, CRYPT_LUKS1, NULL)))
		goto out;

911 912 913 914
	if (data_device &&
	    (r = crypt_set_data_device(cd, data_device)))
		goto out;

915 916 917 918 919 920
	if (!data_device && (crypt_get_data_offset(cd) < 8)) {
		log_err(_("Reduced data offset is allowed only for detached LUKS header.\n"));
		r = -EINVAL;
		goto out;
	}

921
	_set_activation_flags(&activate_flags);
922

923 924 925 926 927
	if (opt_master_key_file) {
		keysize = crypt_get_volume_key_size(cd);
		r = _read_mk(opt_master_key_file, &key, keysize);
		if (r < 0)
			goto out;
928
		r = crypt_activate_by_volume_key(cd, activated_name,
929
						 key, keysize, activate_flags);
930
	} else {
931 932 933 934 935 936 937
		tries = (opt_key_file && !tools_is_stdin(opt_key_file)) ? 1 : opt_tries;
		do {
			r = tools_get_key(NULL, &password, &passwordLen,
					opt_keyfile_offset, opt_keyfile_size, opt_key_file,
					opt_timeout, _verify_passphrase(0), 0, cd);
			if (r < 0)
				goto out;
938

939 940
			r = crypt_activate_by_passphrase(cd, activated_name,
				opt_key_slot, password, passwordLen, activate_flags);
941
			check_signal(&r);
942 943 944

			crypt_safe_free(password);
			password = NULL;
945
		} while ((r == -EPERM || r == -ERANGE) && (--tries > 0));
946
	}
947
out:
948
	crypt_safe_free(key);
949
	crypt_safe_free(password);
950
	crypt_free(cd);
951
	return r;
952 953
}

954 955
static int verify_keyslot(struct crypt_device *cd, int key_slot,
			  char *msg_last, char *msg_pass,
956 957
			  const char *key_file, int keyfile_offset,
			  int keyfile_size)
958 959 960
{
	crypt_keyslot_info ki;
	char *password = NULL;
961 962
	size_t passwordLen;
	int i, r;
963 964

	ki = crypt_keyslot_status(cd, key_slot);
965 966
	if (ki == CRYPT_SLOT_ACTIVE_LAST && !opt_batch_mode && !key_file &&
	    msg_last && !yesDialog(msg_last, NULL))
967 968
		return -EPERM;

969
	r = tools_get_key(msg_pass, &password, &passwordLen,
970
			  keyfile_offset, keyfile_size, key_file, opt_timeout,
971
			  _verify_passphrase(0), 0, cd);
972 973
	if(r < 0)
		goto out;
974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992

	if (ki == CRYPT_SLOT_ACTIVE_LAST) {
		/* check the last keyslot */
		r = crypt_activate_by_passphrase(cd, NULL, key_slot,
						 password, passwordLen, 0);
	} else {
		/* try all other keyslots */
		for (i = 0; i < crypt_keyslot_max(CRYPT_LUKS1); i++) {
			if (i == key_slot)
				continue;
			ki = crypt_keyslot_status(cd, key_slot);
			if (ki == CRYPT_SLOT_ACTIVE)
			r = crypt_activate_by_passphrase(cd, NULL, i,
							 password, passwordLen, 0);
			if (r == i)
				break;
		}
	}

993 994 995 996
	/* Handle inactive keyslots the same as bad password here */
	if (r == -ENOENT)
		r = -EPERM;

997
	if (r == -EPERM)
998
		log_err(_("No key available with this passphrase.\n"));
999
out:
1000 1001 1002 1003
	crypt_safe_free(password);
	return r;
}

1004
static int action_luksKillSlot(void)
1005
{
1006 1007 1008
	struct crypt_device *cd = NULL;
	int r;

1009
	if ((r = crypt_init(&cd, uuid_or_device_header(NULL))))
1010 1011
		goto out;

1012
	crypt_set_confirm_callback(cd, yesDialog, NULL);
1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024

	if ((r = crypt_load(cd, CRYPT_LUKS1, NULL)))
		goto out;

	switch (crypt_keyslot_status(cd, opt_key_slot)) {
	case CRYPT_SLOT_ACTIVE_LAST:
	case CRYPT_SLOT_ACTIVE:
		log_verbose(_("Key slot %d selected for deletion.\n"), opt_key_slot);
		break;
	case CRYPT_SLOT_INACTIVE:
		log_err(_("Key %d not active. Can't wipe.\n"), opt_key_slot);
	case CRYPT_SLOT_INVALID:
1025
		r = -EINVAL;
1026 1027 1028
		goto out;
	}

1029
	if (!opt_batch_mode || opt_key_file || !isatty(STDIN_FILENO)) {
1030 1031
		r = verify_keyslot(cd, opt_key_slot,
			_("This is the last keyslot. Device will become unusable after purging this key."),
1032
			_("Enter any remaining passphrase: "),
1033
			opt_key_file, opt_keyfile_offset, opt_keyfile_size);
1034 1035 1036 1037 1038 1039

		if (r == -EPIPE && (!opt_key_file || tools_is_stdin(opt_key_file))) {
			log_dbg("Failed read from input, ignoring passphrase.");
			r = 0;
		}

1040 1041 1042
		if (r < 0)
			goto out;
	}
1043

1044 1045 1046
	r = crypt_keyslot_destroy(cd, opt_key_slot);
out:
	crypt_free(cd);
1047
	return r;
1048 1049
}

1050
static int action_luksRemoveKey(void)
1051
{
1052 1053
	struct crypt_device *cd = NULL;
	char *password = NULL;
1054
	size_t passwordLen;
1055 1056
	int r;

1057
	if ((r = crypt_init(&cd, uuid_or_device_header(NULL))))
1058 1059
		goto out;

1060
	crypt_set_confirm_callback(cd, yesDialog, NULL);
1061 1062 1063 1064

	if ((r = crypt_load(cd, CRYPT_LUKS1, NULL)))
		goto out;

1065
	r = tools_get_key(_("Enter passphrase to be deleted: "),
1066
		      &password, &passwordLen,
1067
		      opt_keyfile_offset, opt_keyfile_size, opt_key_file,
1068
		      opt_timeout,
1069
		      _verify_passphrase(0), 0,
1070
		      cd);
1071
	if(r < 0)
1072 1073 1074 1075
		goto out;

	r = crypt_activate_by_passphrase(cd, NULL, CRYPT_ANY_SLOT,
					 password, passwordLen, 0);
1076
	check_signal(&r);
1077 1078 1079 1080 1081 1082 1083
	if (r < 0)
		goto out;

	opt_key_slot = r;
	log_verbose(_("Key slot %d selected for deletion.\n"), opt_key_slot);

	if (crypt_keyslot_status(cd, opt_key_slot) == CRYPT_SLOT_ACTIVE_LAST &&
1084
	    !yesDialog(_("This is the last keyslot. "
1085 1086 1087 1088 1089 1090 1091 1092 1093 1094
			  "Device will become unusable after purging this key."),
			NULL)) {
		r = -EPERM;
		goto out;
	}

	r = crypt_keyslot_destroy(cd, opt_key_slot);
out:
	crypt_safe_free(password);
	crypt_free(cd);
1095
	return r;
1096 1097
}

1098
static int action_luksAddKey(void)
1099
{
Milan Broz's avatar
Milan Broz committed
1100
	int r = -EINVAL, keysize = 0;
1101
	char *key = NULL;
1102
	const char *opt_new_key_file = (action_argc > 1 ? action_argv[1] : NULL);
1103 1104
	char *password = NULL, *password_new = NULL;
	size_t password_size = 0, password_new_size = 0;
1105 1106
	struct crypt_device *cd = NULL;

1107
	if ((r = crypt_init(&cd, uuid_or_device_header(NULL))))
1108 1109
		goto out;

1110
	crypt_set_confirm_callback(cd, yesDialog, NULL);
1111

1112 1113 1114
	if ((r = crypt_load(cd, CRYPT_LUKS1, NULL)))
		goto out;

1115 1116 1117 1118
	/* Never call pwquality if using null cipher */
	if (tools_is_cipher_null(crypt_get_cipher(cd)))
		opt_force_password = 1;

1119
	keysize = crypt_get_volume_key_size(cd);
1120 1121 1122 1123 1124
	r = set_pbkdf_params(cd, crypt_get_type(cd));
	if (r) {
		log_err(_("Failed to set pbkdf parameters.\n"));
		goto out;
	}
1125

1126
	if (opt_master_key_file) {
1127 1128
		r = _read_mk(opt_master_key_file, &key, keysize);
		if (r < 0)
1129
			goto out;
1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145

		r = crypt_volume_key_verify(cd, key, keysize);
		check_signal(&r);
		if (r < 0)
			goto out;

		r = tools_get_key(_("Enter new passphrase for key slot: "),
				  &password_new, &password_new_size,
				  opt_new_keyfile_offset, opt_new_keyfile_size,
				  opt_new_key_file, opt_timeout,
				  _verify_passphrase(1), 1, cd);
		if (r < 0)
			goto out;

		r = crypt_keyslot_add_by_volume_key(cd, opt_key_slot, key, keysize,
						    password_new, password_new_size);
1146 1147
	} else if (opt_key_file && !tools_is_stdin(opt_key_file) &&
		   opt_new_key_file && !tools_is_stdin(opt_new_key_file)) {
1148 1149 1150
		r = crypt_keyslot_add_by_keyfile_offset(cd, opt_key_slot,
			opt_key_file, opt_keyfile_size, opt_keyfile_offset,
			opt_new_key_file, opt_new_keyfile_size, opt_new_keyfile_offset);
1151
	} else {
1152
		r = tools_get_key(_("Enter any existing passphrase: "),
1153 1154
			      &password, &password_size,
			      opt_keyfile_offset, opt_keyfile_size, opt_key_file,
1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167
			      opt_timeout, _verify_passphrase(0), 0, cd);

		if (r < 0)
			goto out;

		/* Check password before asking for new one */
		r = crypt_activate_by_passphrase(cd, NULL, CRYPT_ANY_SLOT,
						 password, password_size, 0);
		check_signal(&r);
		if (r < 0)
			goto out;

		r = tools_get_key(_("Enter new passphrase for key slot: "),
1168 1169 1170
				  &password_new, &password_new_size,
				  opt_new_keyfile_offset, opt_new_keyfile_size, opt_new_key_file,
				  opt_timeout, _verify_passphrase(1), opt_new_key_file ? 0 : 1, cd);
1171 1172 1173
		if (r < 0)
			goto out;

1174
		r = crypt_keyslot_add_by_passphrase(cd, opt_key_slot,
1175 1176
						    password, password_size,
						    password_new, password_new_size);
1177
	}
1178
out:
1179 1180
	crypt_safe_free(password);
	crypt_safe_free(password_new);
1181
	crypt_safe_free(key);
1182
	crypt_free(cd);
1183
	return r;
1184 1185
}

1186
static int action_luksChangeKey(void)
Milan Broz's avatar
Milan Broz committed
1187 1188 1189
{
	const char *opt_new_key_file = (action_argc > 1 ? action_argv[1] : NULL);
	struct crypt_device *cd = NULL;
1190 1191 1192
	char *password = NULL, *password_new = NULL;
	size_t password_size = 0, password_new_size = 0;
	int r;
Milan Broz's avatar
Milan Broz committed
1193

1194
	if ((r = crypt_init(&cd, uuid_or_device_header(NULL))))
Milan Broz's avatar
Milan Broz committed
1195 1196 1197 1198 1199
		goto out;

	if ((r = crypt_load(cd, CRYPT_LUKS1, NULL)))
		goto out;

1200 1201 1202 1203
	/* Never call pwquality if using null cipher */
	if (tools_is_cipher_null(crypt_get_cipher(cd)))
		opt_force_password = 1;

1204 1205 1206 1207 1208
	r = set_pbkdf_params(cd, crypt_get_type(cd));
	if (r) {
		log_err(_("Failed to set pbkdf parameters.\n"));
		goto out;
	}
1209

1210
	r = tools_get_key(_("Enter passphrase to be changed: "),
1211
		      &password, &password_size,
1212
		      opt_keyfile_offset, opt_keyfile_size, opt_key_file,
1213
		      opt_timeout, _verify_passphrase(0), 0, cd);
Milan Broz's avatar
Milan Broz committed
1214 1215 1216
	if (r < 0)
		goto out;

1217 1218 1219
	/* Check password before asking for new one */
	r = crypt_activate_by_passphrase(cd, NULL, opt_key_slot,
					 password, password_size, 0);
1220
	check_signal(&r);
1221
	if (r < 0)
Milan Broz's avatar
Milan Broz committed
1222 1223
		goto out;

1224
	r = tools_get_key(_("Enter new passphrase: "),
1225
			  &password_new, &password_new_size,
1226 1227
			  opt_new_keyfile_offset, opt_new_keyfile_size,
			  opt_new_key_file,
1228
			  opt_timeout, _verify_passphrase(1), 1, cd);
Milan Broz's avatar
Milan Broz committed
1229 1230 1231
	if (r < 0)
		goto out;

1232 1233
	r = crypt_keyslot_change_by_passphrase(cd, opt_key_slot, opt_key_slot,
		password, password_size, password_new, password_new_size);
Milan Broz's avatar
Milan Broz committed
1234 1235
out:
	crypt_safe_free(password);
1236
	crypt_safe_free(password_new);
Milan Broz's avatar
Milan Broz committed
1237 1238 1239 1240
	crypt_free(cd);
	return r;
}

1241
static int action_isLuks(void)