setup.c 118 KB
Newer Older
1 2 3
/*
 * libcryptsetup - cryptsetup library
 *
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-2018, Red Hat, Inc. All rights reserved.
 * Copyright (C) 2009-2018, 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 26
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
27
#include <stdarg.h>
28
#include <sys/utsname.h>
29 30 31 32 33
#include <fcntl.h>
#include <errno.h>

#include "libcryptsetup.h"
#include "luks.h"
Milan Broz's avatar
Milan Broz committed
34
#include "luks2.h"
35
#include "loopaes.h"
36
#include "verity.h"
Milan Broz's avatar
Milan Broz committed
37
#include "tcrypt.h"
38
#include "integrity.h"
39 40
#include "internal.h"

Milan Broz's avatar
Milan Broz committed
41 42 43
#define CRYPT_CD_UNRESTRICTED	(1 << 0)
#define CRYPT_CD_QUIET		(1 << 1)

44
struct crypt_device {
45 46
	char *type;

Milan Broz's avatar
Milan Broz committed
47 48
	struct device *device;
	struct device *metadata_device;
49

50
	struct volume_key *volume_key;
51
	int rng_type;
Milan Broz's avatar
Milan Broz committed
52 53 54
	struct crypt_pbkdf_type pbkdf;

	/* global context scope settings */
55
	unsigned key_in_keyring:1;
56

57 58
	uint64_t data_offset;

59
	// FIXME: private binary headers and access it properly
60 61
	// through sub-library (LUKS1, TCRYPT)

62 63 64 65
	union {
	struct { /* used in CRYPT_LUKS1 */
		struct luks_phdr hdr;
	} luks1;
Milan Broz's avatar
Milan Broz committed
66 67
	struct { /* used in CRYPT_LUKS2 */
		struct luks2_hdr hdr;
68 69
		char cipher[MAX_CIPHER_LEN];	  /* only for compatibility */
		char cipher_mode[MAX_CIPHER_LEN]; /* only for compatibility */
Milan Broz's avatar
Milan Broz committed
70
	} luks2;
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
	struct { /* used in CRYPT_PLAIN */
		struct crypt_params_plain hdr;
		char *cipher;
		char *cipher_mode;
		unsigned int key_size;
	} plain;
	struct { /* used in CRYPT_LOOPAES */
		struct crypt_params_loopaes hdr;
		char *cipher;
		char *cipher_mode;
		unsigned int key_size;
	} loopaes;
	struct { /* used in CRYPT_VERITY */
		struct crypt_params_verity hdr;
		char *root_hash;
		unsigned int root_hash_size;
		char *uuid;
88
		struct device *fec_device;
89 90 91 92 93
	} verity;
	struct { /* used in CRYPT_TCRYPT */
		struct crypt_params_tcrypt params;
		struct tcrypt_phdr hdr;
	} tcrypt;
94 95 96 97 98
	struct { /* used in CRYPT_INTEGRITY */
		struct crypt_params_integrity params;
		struct volume_key *journal_mac_key;
		struct volume_key *journal_crypt_key;
	} integrity;
99 100 101 102 103 104
	struct { /* used if initialized without header by name */
		char *active_name;
		/* buffers, must refresh from kernel on every query */
		char cipher[MAX_CIPHER_LEN];
		char cipher_mode[MAX_CIPHER_LEN];
		unsigned int key_size;
105
		unsigned int veracrypt_pim;
106
	} none;
107
	} u;
Milan Broz's avatar
Milan Broz committed
108

109
	/* callbacks definitions */
110
	void (*log)(int level, const char *msg, void *usrptr);
111
	void *log_usrptr;
112 113
	int (*confirm)(const char *msg, void *usrptr);
	void *confirm_usrptr;
114
};
115

116 117 118
/* Just to suppress redundant messages about crypto backend */
static int _crypto_logged = 0;

119
/* Log helper */
120
static void (*_default_log)(int level, const char *msg, void *usrptr) = NULL;
121 122
static int _debug_level = 0;

123 124 125
/* Library can do metadata locking  */
static int _metadata_locking = 1;

126 127 128 129 130 131
/* Library scope detection for kernel keyring support */
static int _kernel_keyring_supported;

/* Library allowed to use kernel keyring for loading VK in kernel crypto layer */
static int _vk_via_keyring = 1;

132 133 134 135 136
void crypt_set_debug_level(int level)
{
	_debug_level = level;
}

137
int crypt_get_debug_level(void)
138 139 140 141
{
	return _debug_level;
}

142 143
void crypt_log(struct crypt_device *cd, int level, const char *msg)
{
Milan Broz's avatar
Milan Broz committed
144 145
	if (!msg)
		return;
146 147 148 149

	if (level < _debug_level)
		return;

150 151 152 153
	if (cd && cd->log)
		cd->log(level, msg, cd->log_usrptr);
	else if (_default_log)
		_default_log(level, msg, NULL);
154 155 156
	/* Default to stdout/stderr if there is no callback. */
	else
		fprintf(level == CRYPT_LOG_ERROR ? stderr : stdout, "%s", msg);
157 158
}

159
__attribute__((format(printf, 5, 6)))
160
void logger(struct crypt_device *cd, int level, const char *file,
161 162
	    int line, const char *format, ...)
{
163
	va_list argp;
164
	char target[LOG_MAX_LEN + 2];
165

166
	va_start(argp, format);
167

168
	if (vsnprintf(&target[0], LOG_MAX_LEN, format, argp) > 0 ) {
169 170 171 172 173
		/* All verbose and error messages in tools end with EOL. */
		if (level == CRYPT_LOG_VERBOSE || level == CRYPT_LOG_ERROR)
			strncat(target, "\n", LOG_MAX_LEN);

		crypt_log(cd, level, target);
174
	}
175 176

	va_end(argp);
177 178
}

Milan Broz's avatar
Milan Broz committed
179 180 181 182 183
static const char *mdata_device_path(struct crypt_device *cd)
{
	return device_path(cd->metadata_device ?: cd->device);
}

184 185 186 187 188
static const char *data_device_path(struct crypt_device *cd)
{
	return device_path(cd->device);
}

Milan Broz's avatar
Milan Broz committed
189 190
/* internal only */
struct device *crypt_metadata_device(struct crypt_device *cd)
191 192 193 194
{
	return cd->metadata_device ?: cd->device;
}

Milan Broz's avatar
Milan Broz committed
195 196 197 198 199
struct device *crypt_data_device(struct crypt_device *cd)
{
	return cd->device;
}

200
int init_crypto(struct crypt_device *ctx)
201
{
202
	struct utsname uts;
203 204 205 206
	int r;

	r = crypt_random_init(ctx);
	if (r < 0) {
207
		log_err(ctx, _("Cannot initialize crypto RNG backend."));
208 209 210
		return r;
	}

211
	r = crypt_backend_init(ctx);
212
	if (r < 0)
213
		log_err(ctx, _("Cannot initialize crypto backend."));
214

215
	if (!r && !_crypto_logged) {
216
		log_dbg(ctx, "Crypto backend (%s) initialized in cryptsetup library version %s.",
217
			crypt_backend_version(), PACKAGE_VERSION);
218
		if (!uname(&uts))
219
			log_dbg(ctx, "Detected kernel %s %s %s.",
220 221 222 223
				uts.sysname, uts.release, uts.machine);
		_crypto_logged = 1;
	}

224 225 226
	return r;
}

227 228 229
static int process_key(struct crypt_device *cd, const char *hash_name,
		       size_t key_size, const char *pass, size_t passLen,
		       struct volume_key **vk)
230
{
231
	int r;
232 233

	if (!key_size)
234 235 236 237 238
		return -EINVAL;

	*vk = crypt_alloc_volume_key(key_size, NULL);
	if (!*vk)
		return -ENOMEM;
239

240
	if (hash_name) {
241
		r = crypt_plain_hash(cd, hash_name, (*vk)->key, key_size, pass, passLen);
242 243
		if (r < 0) {
			if (r == -ENOENT)
244
				log_err(cd, _("Hash algorithm %s not supported."),
245 246
					hash_name);
			else
247
				log_err(cd, _("Key processing error (using hash %s)."),
248
					hash_name);
249 250 251
			crypt_free_volume_key(*vk);
			*vk = NULL;
			return -EINVAL;
252
		}
253
	} else if (passLen > key_size) {
254
		memcpy((*vk)->key, pass, key_size);
255
	} else {
256
		memcpy((*vk)->key, pass, passLen);
257 258
	}

259
	return 0;
260 261
}

262 263 264 265 266
static int isPLAIN(const char *type)
{
	return (type && !strcmp(CRYPT_PLAIN, type));
}

Milan Broz's avatar
Milan Broz committed
267
static int isLUKS1(const char *type)
268 269 270 271
{
	return (type && !strcmp(CRYPT_LUKS1, type));
}

Milan Broz's avatar
Milan Broz committed
272 273 274 275 276 277 278 279 280 281
static int isLUKS2(const char *type)
{
	return (type && !strcmp(CRYPT_LUKS2, type));
}

static int isLUKS(const char *type)
{
	return (isLUKS2(type) || isLUKS1(type));
}

282 283 284 285 286
static int isLOOPAES(const char *type)
{
	return (type && !strcmp(CRYPT_LOOPAES, type));
}

287 288 289 290 291
static int isVERITY(const char *type)
{
	return (type && !strcmp(CRYPT_VERITY, type));
}

Milan Broz's avatar
Milan Broz committed
292 293 294 295 296
static int isTCRYPT(const char *type)
{
	return (type && !strcmp(CRYPT_TCRYPT, type));
}

297 298 299 300 301
static int isINTEGRITY(const char *type)
{
	return (type && !strcmp(CRYPT_INTEGRITY, type));
}

Milan Broz's avatar
Milan Broz committed
302
static int _onlyLUKS(struct crypt_device *cd, uint32_t cdflags)
Milan Broz's avatar
Milan Broz committed
303 304 305 306
{
	int r = 0;

	if (cd && !cd->type) {
Milan Broz's avatar
Milan Broz committed
307
		if (!(cdflags & CRYPT_CD_QUIET))
308
			log_err(cd, _("Cannot determine device type. Incompatible activation of device?"));
Milan Broz's avatar
Milan Broz committed
309 310
		r = -EINVAL;
	}
Milan Broz's avatar
Milan Broz committed
311

Milan Broz's avatar
Milan Broz committed
312
	if (!cd || !isLUKS(cd->type)) {
Milan Broz's avatar
Milan Broz committed
313
		if (!(cdflags & CRYPT_CD_QUIET))
314
			log_err(cd, _("This operation is supported only for LUKS device."));
Milan Broz's avatar
Milan Broz committed
315 316 317
		r = -EINVAL;
	}

318
	if (r || (cdflags & CRYPT_CD_UNRESTRICTED) || isLUKS1(cd->type))
Milan Broz's avatar
Milan Broz committed
319 320
		return r;

321
	return LUKS2_unmet_requirements(cd, &cd->u.luks2.hdr, 0, cdflags & CRYPT_CD_QUIET);
Milan Broz's avatar
Milan Broz committed
322 323
}

Milan Broz's avatar
Milan Broz committed
324 325 326 327 328 329 330 331 332 333 334
static int onlyLUKS(struct crypt_device *cd)
{
	return _onlyLUKS(cd, 0);
}

static int _onlyLUKS2(struct crypt_device *cd, uint32_t cdflags)
{
	int r = 0;

	if (cd && !cd->type) {
		if (!(cdflags & CRYPT_CD_QUIET))
335
			log_err(cd, _("Cannot determine device type. Incompatible activation of device?"));
Milan Broz's avatar
Milan Broz committed
336 337 338 339 340
		r = -EINVAL;
	}

	if (!cd || !isLUKS2(cd->type)) {
		if (!(cdflags & CRYPT_CD_QUIET))
341
			log_err(cd, _("This operation is supported only for LUKS2 device."));
Milan Broz's avatar
Milan Broz committed
342 343 344 345 346 347
		r = -EINVAL;
	}

	if (r || (cdflags & CRYPT_CD_UNRESTRICTED))
		return r;

348
	return LUKS2_unmet_requirements(cd, &cd->u.luks2.hdr, 0, cdflags & CRYPT_CD_QUIET);
Milan Broz's avatar
Milan Broz committed
349 350 351 352 353 354 355
}

static int onlyLUKS2(struct crypt_device *cd)
{
	return _onlyLUKS2(cd, 0);
}

356 357 358 359 360 361 362 363
static void crypt_set_null_type(struct crypt_device *cd)
{
	if (!cd->type)
		return;

	free(cd->type);
	cd->type = NULL;
	cd->u.none.active_name = NULL;
364
	cd->data_offset = 0;
365
}
Milan Broz's avatar
Milan Broz committed
366

367 368 369 370 371 372 373 374 375
static void crypt_reset_null_type(struct crypt_device *cd)
{
	if (cd->type)
		return;

	free(cd->u.none.active_name);
	cd->u.none.active_name = NULL;
}

376
/* keyslot helpers */
377 378
static int keyslot_verify_or_find_empty(struct crypt_device *cd, int *keyslot)
{
Milan Broz's avatar
Milan Broz committed
379 380
	crypt_keyslot_info ki;

381
	if (*keyslot == CRYPT_ANY_SLOT) {
Milan Broz's avatar
Milan Broz committed
382 383 384
		if (isLUKS1(cd->type))
			*keyslot = LUKS_keyslot_find_empty(&cd->u.luks1.hdr);
		else
385
			*keyslot = LUKS2_keyslot_find_empty(&cd->u.luks2.hdr, "luks2");
386
		if (*keyslot < 0) {
387
			log_err(cd, _("All key slots full."));
388 389 390 391
			return -EINVAL;
		}
	}

Milan Broz's avatar
Milan Broz committed
392 393 394 395 396
	if (isLUKS1(cd->type))
		ki = LUKS_keyslot_info(&cd->u.luks1.hdr, *keyslot);
	else
		ki = LUKS2_keyslot_info(&cd->u.luks2.hdr, *keyslot);
	switch (ki) {
397
		case CRYPT_SLOT_INVALID:
398
			log_err(cd, _("Key slot %d is invalid, please select between 0 and %d."),
399 400
				*keyslot, LUKS_NUMKEYS - 1);
			return -EINVAL;
401
		case CRYPT_SLOT_INACTIVE:
402 403
			break;
		default:
404
			log_err(cd, _("Key slot %d is full, please select another one."),
405 406 407 408
				*keyslot);
			return -EINVAL;
	}

409
	log_dbg(cd, "Selected keyslot %d.", *keyslot);
410 411 412
	return 0;
}

413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442
/*
 * compares UUIDs returned by device-mapper (striped by cryptsetup) and uuid in header
 */
static int crypt_uuid_cmp(const char *dm_uuid, const char *hdr_uuid)
{
	int i, j;
	char *str;

	if (!dm_uuid || !hdr_uuid)
		return -EINVAL;

	str = strchr(dm_uuid, '-');
	if (!str)
		return -EINVAL;

	for (i = 0, j = 1; hdr_uuid[i]; i++) {
		if (hdr_uuid[i] == '-')
			continue;

		if (!str[j] || str[j] == '-')
			return -EINVAL;

		if (str[j] != hdr_uuid[i])
			return -EINVAL;
		j++;
	}

	return 0;
}

443 444 445 446 447 448
/*
 * compares type of active device to provided string (only if there is no explicit type)
 */
static int crypt_uuid_type_cmp(struct crypt_device *cd, const char *type)
{
	struct crypt_dm_active_device dmd = {};
449 450
	size_t len;
	int r;
451 452 453 454 455

	/* Must user header-on-disk if we know type here */
	if (cd->type || !cd->u.none.active_name)
		return -EINVAL;

456
	log_dbg(cd, "Checking if active device %s without header has UUID type %s.",
457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472
		cd->u.none.active_name, type);

	r = dm_query_device(cd, cd->u.none.active_name, DM_ACTIVE_UUID, &dmd);
	if (r < 0)
		return r;

	r = -ENODEV;
	len = strlen(type);
	if (dmd.uuid && strlen(dmd.uuid) > len &&
	    !strncmp(dmd.uuid, type, len) && dmd.uuid[len] == '-')
		r = 0;

	free(CONST_CAST(void*)dmd.uuid);
	return r;
}

473 474 475 476 477
int PLAIN_activate(struct crypt_device *cd,
		     const char *name,
		     struct volume_key *vk,
		     uint64_t size,
		     uint32_t flags)
478
{
479
	int r;
480
	char *dm_cipher = NULL;
481
	enum devcheck device_check;
482
	struct crypt_dm_active_device dmd = {
483
		.target = DM_CRYPT,
484
		.size   = size,
485
		.flags  = flags,
Milan Broz's avatar
Milan Broz committed
486
		.data_device = crypt_data_device(cd),
487 488 489 490 491
		.u.crypt  = {
			.cipher = NULL,
			.vk     = vk,
			.offset = crypt_get_data_offset(cd),
			.iv_offset = crypt_get_iv_offset(cd),
492
			.sector_size = crypt_get_sector_size(cd),
493
		}
494 495
	};

496 497 498 499 500
	if (dmd.flags & CRYPT_ACTIVATE_SHARED)
		device_check = DEV_SHARED;
	else
		device_check = DEV_EXCL;

Milan Broz's avatar
Milan Broz committed
501 502
	r = device_block_adjust(cd, dmd.data_device, device_check,
				dmd.u.crypt.offset, &dmd.size, &dmd.flags);
503 504 505
	if (r)
		return r;

506 507 508 509 510
	if (crypt_get_cipher_mode(cd))
		r = asprintf(&dm_cipher, "%s-%s", crypt_get_cipher(cd), crypt_get_cipher_mode(cd));
	else
		r = asprintf(&dm_cipher, "%s", crypt_get_cipher(cd));
	if (r < 0)
511 512
		return -ENOMEM;

513
	dmd.u.crypt.cipher = dm_cipher;
514
	log_dbg(cd, "Trying to activate PLAIN device %s using cipher %s.",
515
		name, dmd.u.crypt.cipher);
516

Milan Broz's avatar
Milan Broz committed
517
	r = dm_create_device(cd, name, CRYPT_PLAIN, &dmd, 0);
518

519
	free(dm_cipher);
520 521 522
	return r;
}

523 524 525 526 527 528 529 530
int crypt_confirm(struct crypt_device *cd, const char *msg)
{
	if (!cd || !cd->confirm)
		return 1;
	else
		return cd->confirm(msg, cd->confirm_usrptr);
}

531
void crypt_set_log_callback(struct crypt_device *cd,
532
	void (*log)(int level, const char *msg, void *usrptr),
533 534
	void *usrptr)
{
535 536 537 538 539 540
	if (!cd)
		_default_log = log;
	else {
		cd->log = log;
		cd->log_usrptr = usrptr;
	}
541 542 543 544 545 546
}

void crypt_set_confirm_callback(struct crypt_device *cd,
	int (*confirm)(const char *msg, void *usrptr),
	void *usrptr)
{
Milan Broz's avatar
Milan Broz committed
547 548 549 550
	if (cd) {
		cd->confirm = confirm;
		cd->confirm_usrptr = usrptr;
	}
551 552
}

553 554
const char *crypt_get_dir(void)
{
555
	return dm_get_dir();
556
}
557 558 559 560

int crypt_init(struct crypt_device **cd, const char *device)
{
	struct crypt_device *h = NULL;
561
	int r;
562 563 564 565

	if (!cd)
		return -EINVAL;

566
	log_dbg(NULL, "Allocating context for crypt device %s.", device ?: "(none)");
567 568 569 570 571

	if (!(h = malloc(sizeof(struct crypt_device))))
		return -ENOMEM;

	memset(h, 0, sizeof(*h));
572

573
	r = device_alloc(NULL, &h->device, device);
574
	if (r < 0)
575
		goto bad;
576

577
	dm_backend_init(NULL);
578

579
	h->rng_type = crypt_random_default_key_rng();
Milan Broz's avatar
Milan Broz committed
580

581 582
	*cd = h;
	return 0;
583
bad:
584
	device_free(NULL, h->device);
585 586
	free(h);
	return r;
587 588
}

589 590 591 592 593
static int crypt_check_data_device_size(struct crypt_device *cd)
{
	int r;
	uint64_t size, size_min;

594
	/* Check data device size, require at least header or one sector */
595
	size_min = crypt_get_data_offset(cd) << SECTOR_SHIFT ?: SECTOR_SIZE;
596

Milan Broz's avatar
Milan Broz committed
597
	r = device_size(cd->device, &size);
598 599 600 601
	if (r < 0)
		return r;

	if (size < size_min) {
602
		log_err(cd, _("Header detected but device %s is too small."),
Milan Broz's avatar
Milan Broz committed
603
			device_path(cd->device));
604 605 606 607 608 609
		return -EINVAL;
	}

	return r;
}

610
static int _crypt_set_data_device(struct crypt_device *cd, const char *device)
611
{
Milan Broz's avatar
Milan Broz committed
612 613
	struct device *dev = NULL;
	int r;
614

615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632
	r = device_alloc(cd, &dev, device);
	if (r < 0)
		return r;

	if (!cd->metadata_device) {
		cd->metadata_device = cd->device;
	} else
		device_free(cd, cd->device);

	cd->device = dev;

	return crypt_check_data_device_size(cd);
}

int crypt_set_data_device(struct crypt_device *cd, const char *device)
{
	/* metadata device must be set */
	if (!cd || !cd->device || !device)
Milan Broz's avatar
Milan Broz committed
633 634
		return -EINVAL;

635
	log_dbg(cd, "Setting ciphertext data device to %s.", device ?: "(none)");
636

637 638
	if (!isLUKS1(cd->type) && !isLUKS2(cd->type) && !isVERITY(cd->type) &&
	    !isINTEGRITY(cd->type)) {
639
		log_err(cd, _("This operation is not supported for this device type."));
640 641 642
		return  -EINVAL;
	}

643 644 645 646 647 648 649 650
	return _crypt_set_data_device(cd, device);
}

int crypt_init_data_device(struct crypt_device **cd, const char *device, const char *data_device)
{
	int r;

	if (!cd)
651 652
		return -EINVAL;

653 654
	r = crypt_init(cd, device);
	if (r || !data_device)
655 656
		return r;

657 658 659 660
	log_dbg(NULL, "Setting ciphertext data device to %s.", data_device ?: "(none)");
	r = _crypt_set_data_device(*cd, data_device);
	if (r)
		crypt_free(*cd);
661

662
	return r;
663 664
}

665

666 667
/* internal only */
struct crypt_pbkdf_type *crypt_get_pbkdf(struct crypt_device *cd)
668
{
669
	return &cd->pbkdf;
670 671 672 673 674
}

/*
 * crypt_load() helpers
 */
675
static int _crypt_load_luks2(struct crypt_device *cd, int reload, int repair)
676 677
{
	int r;
678
	char *type = NULL;
Milan Broz's avatar
Milan Broz committed
679
	struct luks2_hdr hdr2 = {};
680

681
	log_dbg(cd, "%soading LUKS2 header (repair %sabled).", reload ? "Rel" : "L", repair ? "en" : "dis");
Milan Broz's avatar
Milan Broz committed
682

683
	r = LUKS2_hdr_read(cd, &hdr2, repair);
Milan Broz's avatar
Milan Broz committed
684
	if (r)
685 686
		return r;

Milan Broz's avatar
Milan Broz committed
687 688 689 690 691
	if (!reload && !(type = strdup(CRYPT_LUKS2))) {
		r = -ENOMEM;
		goto out;
	}

692
	if (verify_pbkdf_params(cd, &cd->pbkdf)) {
Milan Broz's avatar
Milan Broz committed
693
		r = init_pbkdf_type(cd, NULL, CRYPT_LUKS2);
694
		if (r)
Milan Broz's avatar
Milan Broz committed
695
			goto out;
696 697
	}

698
	if (reload)
699
		LUKS2_hdr_free(cd, &cd->u.luks2.hdr);
700
	else
Milan Broz's avatar
Milan Broz committed
701 702
		cd->type = type;

703
	r = 0;
Milan Broz's avatar
Milan Broz committed
704 705 706 707 708
	memcpy(&cd->u.luks2.hdr, &hdr2, sizeof(hdr2));

out:
	if (r) {
		free(type);
709
		LUKS2_hdr_free(cd, &hdr2);
Milan Broz's avatar
Milan Broz committed
710 711 712 713 714 715 716 717 718 719 720 721
	}
	/* FIXME: why? */
	crypt_memzero(&hdr2, sizeof(hdr2));

	return r;
}

static void _luks2_reload(struct crypt_device *cd)
{
	if (!cd || !isLUKS2(cd->type))
		return;

722
	(void) _crypt_load_luks2(cd, 1, 0);
Milan Broz's avatar
Milan Broz committed
723 724 725 726 727 728 729 730 731
}

static int _crypt_load_luks(struct crypt_device *cd, const char *requested_type,
			    int require_header, int repair)
{
	struct luks_phdr hdr = {};
	int r, version = 0;

	r = init_crypto(cd);
732 733 734
	if (r < 0)
		return r;

Milan Broz's avatar
Milan Broz committed
735 736
	/* This will return 0 if primary LUKS2 header is damaged */
	if (!requested_type)
737
		version = LUKS2_hdr_version_unlocked(cd, NULL);
Milan Broz's avatar
Milan Broz committed
738 739 740

	if (isLUKS1(requested_type) || version == 1) {
		if (cd->type && isLUKS2(cd->type)) {
741
			log_dbg(cd, "Context is already initialised to type %s", cd->type);
Milan Broz's avatar
Milan Broz committed
742
			return -EINVAL;
743
		}
Milan Broz's avatar
Milan Broz committed
744

Milan Broz's avatar
Milan Broz committed
745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772
		if (verify_pbkdf_params(cd, &cd->pbkdf)) {
			r = init_pbkdf_type(cd, NULL, CRYPT_LUKS1);
			if (r)
				return r;
		}

		r = LUKS_read_phdr(&hdr, require_header, repair, cd);
		if (r)
			goto out;

		if (!cd->type && !(cd->type = strdup(CRYPT_LUKS1))) {
			r = -ENOMEM;
			goto out;
		}

		/* Set hash to the same as in the loaded header */
		if (!cd->pbkdf.hash || strcmp(cd->pbkdf.hash, hdr.hashSpec)) {
			free(CONST_CAST(void*)cd->pbkdf.hash);
			cd->pbkdf.hash = strdup(hdr.hashSpec);
			if (!cd->pbkdf.hash) {
				r = -ENOMEM;
				goto out;
			}
		}

		memcpy(&cd->u.luks1.hdr, &hdr, sizeof(hdr));
	} else if (isLUKS2(requested_type) || version == 2 || version == 0) {
		if (cd->type && isLUKS1(cd->type)) {
773
			log_dbg(cd, "Context is already initialised to type %s", cd->type);
Milan Broz's avatar
Milan Broz committed
774 775
			return -EINVAL;
		}
776

777 778 779 780 781 782 783 784
		/*
		 * Current LUKS2 repair just overrides blkid probes
		 * and perform auto-recovery if possible. This is safe
		 * unless future LUKS2 repair code do something more
		 * sophisticated. In such case we would need to check
		 * for LUKS2 requirements and decide if it's safe to
		 * perform repair.
		 */
785
		r =  _crypt_load_luks2(cd, cd->type != NULL, repair);
786 787 788
	} else {
		if (version > 2)
			log_err(cd, _("Unsupported LUKS version %d."), version);
Milan Broz's avatar
Milan Broz committed
789
		r = -EINVAL;
790
	}
Milan Broz's avatar
Milan Broz committed
791 792
out:
	crypt_memzero(&hdr, sizeof(hdr));
793 794 795 796

	return r;
}

Milan Broz's avatar
Milan Broz committed
797 798 799 800
static int _crypt_load_tcrypt(struct crypt_device *cd, struct crypt_params_tcrypt *params)
{
	int r;

801 802 803
	if (!params)
		return -EINVAL;

804 805 806 807 808
	if (cd->metadata_device) {
		log_err(cd, _("Detached metadata device is not supported for this crypt type."));
		return -EINVAL;
	}

Milan Broz's avatar
Milan Broz committed
809 810 811 812
	r = init_crypto(cd);
	if (r < 0)
		return r;

813
	memcpy(&cd->u.tcrypt.params, params, sizeof(*params));
Milan Broz's avatar
Milan Broz committed
814

815
	r = TCRYPT_read_phdr(cd, &cd->u.tcrypt.hdr, &cd->u.tcrypt.params);
Milan Broz's avatar
Milan Broz committed
816

817 818 819 820
	cd->u.tcrypt.params.passphrase = NULL;
	cd->u.tcrypt.params.passphrase_size = 0;
	cd->u.tcrypt.params.keyfiles = NULL;
	cd->u.tcrypt.params.keyfiles_count = 0;
821
	cd->u.tcrypt.params.veracrypt_pim = 0;
Milan Broz's avatar
Milan Broz committed
822

Milan Broz's avatar
Milan Broz committed
823 824 825 826 827 828 829 830 831
	if (r < 0)
		return r;

	if (!cd->type && !(cd->type = strdup(CRYPT_TCRYPT)))
		return -ENOMEM;

	return r;
}

832 833 834 835 836 837 838 839 840
static int _crypt_load_verity(struct crypt_device *cd, struct crypt_params_verity *params)
{
	int r;
	size_t sb_offset = 0;

	r = init_crypto(cd);
	if (r < 0)
		return r;

841
	if (params && params->flags & CRYPT_VERITY_NO_HEADER)
842 843
		return -EINVAL;

844 845 846
	if (params)
		sb_offset = params->hash_area_offset;

847
	r = VERITY_read_sb(cd, sb_offset, &cd->u.verity.uuid, &cd->u.verity.hdr);
848 849 850
	if (r < 0)
		return r;

851 852 853 854 855 856 857 858 859
	//FIXME: use crypt_free
	if (!cd->type && !(cd->type = strdup(CRYPT_VERITY))) {
		free(CONST_CAST(void*)cd->u.verity.hdr.hash_name);
		free(CONST_CAST(void*)cd->u.verity.hdr.salt);
		free(cd->u.verity.uuid);
		crypt_memzero(&cd->u.verity.hdr, sizeof(cd->u.verity.hdr));
		return -ENOMEM;
	}

860
	if (params)
861
		cd->u.verity.hdr.flags = params->flags;
862

863
	/* Hash availability checked in sb load */
864 865
	cd->u.verity.root_hash_size = crypt_hash_size(cd->u.verity.hdr.hash_name);
	if (cd->u.verity.root_hash_size > 4096)
866
		return -EINVAL;
867

Milan Broz's avatar
Milan Broz committed
868 869 870 871
	if (params && params->data_device &&
	    (r = crypt_set_data_device(cd, params->data_device)) < 0)
		return r;

872
	if (params && params->fec_device) {
873
		r = device_alloc(cd, &cd->u.verity.fec_device, params->fec_device);
874 875 876 877 878
		if (r < 0)
			return r;
		cd->u.verity.hdr.fec_area_offset = params->fec_area_offset;
		cd->u.verity.hdr.fec_roots = params->fec_roots;
	}
879

880 881 882
	return r;
}

883 884 885 886 887 888 889 890 891 892 893 894 895
static int _crypt_load_integrity(struct crypt_device *cd,
				 struct crypt_params_integrity *params)
{
	int r;

	r = init_crypto(cd);
	if (r < 0)
		return r;

	r = INTEGRITY_read_sb(cd, &cd->u.integrity.params);
	if (r < 0)
		return r;

896 897
	// FIXME: add checks for fields in integrity sb vs params

898 899 900 901 902 903 904
	if (params) {
		cd->u.integrity.params.journal_watermark = params->journal_watermark;
		cd->u.integrity.params.journal_commit_time = params->journal_commit_time;
		cd->u.integrity.params.buffer_sectors = params->buffer_sectors;
		// FIXME: check ENOMEM
		if (params->integrity)
			cd->u.integrity.params.integrity = strdup(params->integrity);
905
		cd->u.integrity.params.integrity_key_size = params->integrity_key_size;
906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934
		if (params->journal_integrity)
			cd->u.integrity.params.journal_integrity = strdup(params->journal_integrity);
		if (params->journal_crypt)
			cd->u.integrity.params.journal_crypt = strdup(params->journal_crypt);

		if (params->journal_crypt_key) {
			cd->u.integrity.journal_crypt_key =
				crypt_alloc_volume_key(params->journal_crypt_key_size,
						       params->journal_crypt_key);
			if (!cd->u.integrity.journal_crypt_key)
				return -ENOMEM;
		}
		if (params->journal_integrity_key) {
			cd->u.integrity.journal_mac_key =
				crypt_alloc_volume_key(params->journal_integrity_key_size,
						       params->journal_integrity_key);
			if (!cd->u.integrity.journal_mac_key)
				return -ENOMEM;
		}
	}

	if (!cd->type && !(cd->type = strdup(CRYPT_INTEGRITY))) {
		free(CONST_CAST(void*)cd->u.integrity.params.integrity);
		return -ENOMEM;
	}

	return 0;
}

935 936 937 938 939 940
int crypt_load(struct crypt_device *cd,
	       const char *requested_type,
	       void *params)
{
	int r;

Milan Broz's avatar
Milan Broz committed
941 942 943
	if (!cd)
		return -EINVAL;

944
	log_dbg(cd, "Trying to load %s crypt type from device %s.",
945 946 947 948 949 950
		requested_type ?: "any", mdata_device_path(cd) ?: "(none)");

	if (!crypt_metadata_device(cd))
		return -EINVAL;

	crypt_reset_null_type(cd);
951
	cd->data_offset = 0;
952

Milan Broz's avatar
Milan Broz committed
953 954
	if (!requested_type || isLUKS1(requested_type) || isLUKS2(requested_type)) {
		if (cd->type && !isLUKS1(cd->type) && !isLUKS2(cd->type)) {
955
			log_dbg(cd, "Context is already initialised to type %s", cd->type);
956 957 958
			return -EINVAL;
		}

Milan Broz's avatar
Milan Broz committed
959
		r = _crypt_load_luks(cd, requested_type, 1, 0);
960 961
	} else if (isVERITY(requested_type)) {
		if (cd->type && !isVERITY(cd->type)) {
962
			log_dbg(cd, "Context is already initialised to type %s", cd->type);
963 964 965 966 967
			return -EINVAL;
		}
		r = _crypt_load_verity(cd, params);
	} else if (isTCRYPT(requested_type)) {
		if (cd->type && !isTCRYPT(cd->type)) {
968
			log_dbg(cd, "Context is already initialised to type %s", cd->type);
969 970 971 972 973
			return -EINVAL;
		}
		r = _crypt_load_tcrypt(cd, params);
	} else if (isINTEGRITY(requested_type)) {
		if (cd->type && !isINTEGRITY(cd->type)) {
974
			log_dbg(cd, "Context is already initialised to type %s", cd->type);
975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000
			return -EINVAL;
		}
		r = _crypt_load_integrity(cd, params);
	} else
		return -EINVAL;

	return r;
}

/*
 * crypt_init() helpers
 */
static int _init_by_name_crypt_none(struct crypt_device *cd)
{
	struct crypt_dm_active_device dmd = {};
	int r;

	if (cd->type || !cd->u.none.active_name)
		return -EINVAL;

	r = dm_query_device(cd, cd->u.none.active_name,
			DM_ACTIVE_CRYPT_CIPHER |
			DM_ACTIVE_CRYPT_KEYSIZE, &dmd);
	if (r >= 0)
		r = crypt_parse_name_and_mode(dmd.u.crypt.cipher,
					      cd->u.none.cipher, NULL,
1001
					      cd->u.none.cipher_mode);
1002 1003 1004 1005 1006 1007

	if (!r)
		cd->u.none.key_size = dmd.u.crypt.vk->keylength;

	crypt_free_volume_key(dmd.u.crypt.vk);
	free(CONST_CAST(void*)dmd.u.crypt.cipher);
Milan Broz's avatar
Milan Broz committed
1008
	free(CONST_CAST(void*)dmd.u.crypt.integrity);
1009 1010 1011
	return r;
}

Milan Broz's avatar
Milan Broz committed
1012 1013
static const char *LUKS_UUID(struct crypt_device *cd)
{
1014 1015 1016
	if (!cd)
		return NULL;
	else if (isLUKS1(cd->type))
Milan Broz's avatar
Milan Broz committed
1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030
		return cd->u.luks1.hdr.uuid;
	else if (isLUKS2(cd->type))
		return cd->u.luks2.hdr.uuid;

	return NULL;
}

static void crypt_free_type(struct crypt_device *cd)
{
	if (isPLAIN(cd->type)) {
		free(CONST_CAST(void*)cd->u.plain.hdr.hash);
		free(cd->u.plain.cipher);
		free(cd->u.plain.cipher_mode);
	} else if (isLUKS2(cd->type)) {
1031
		LUKS2_hdr_free(cd, &cd->u.luks2.hdr);
Milan Broz's avatar
Milan Broz committed
1032 1033 1034 1035 1036
	} else if (isLOOPAES(cd->type)) {
		free(CONST_CAST(void*)cd->u.loopaes.hdr.hash);
		free(cd->u.loopaes.cipher);
	} else if (isVERITY(cd->type)) {
		free(CONST_CAST(void*)cd->u.verity.hdr.hash_name);
1037 1038 1039
		free(CONST_CAST(void*)cd->u.verity.hdr.data_device);
		free(CONST_CAST(void*)cd->u.verity.hdr.hash_device);
		free(CONST_CAST(void*)cd->u.verity.hdr.fec_device);
Milan Broz's avatar
Milan Broz committed
1040 1041 1042
		free(CONST_CAST(void*)cd->u.verity.hdr.salt);
		free(cd->u.verity.root_hash);
		free(cd->u.verity.uuid);
1043
		device_free(cd, cd->u.verity.fec_device);
Milan Broz's avatar
Milan Broz committed
1044 1045 1046 1047 1048 1049 1050 1051
	} else if (isINTEGRITY(cd->type)) {
		free(CONST_CAST(void*)cd->u.integrity.params.integrity);
		free(CONST_CAST(void*)cd->u.integrity.params.journal_integrity);
		free(CONST_CAST(void*)cd->u.integrity.params.journal_crypt);
		crypt_free_volume_key(cd->u.integrity.journal_crypt_key);
		crypt_free_volume_key(cd->u.integrity.journal_mac_key);
	} else if (!cd->type) {
		free(cd->u.none.active_name);
Milan Broz's avatar
Milan Broz committed
1052
		cd->u.none.active_name = NULL;
Milan Broz's avatar
Milan Broz committed
1053 1054 1055 1056 1057
	}

	crypt_set_null_type(cd);
}

1058 1059
static int _init_by_name_crypt(struct crypt_device *cd, const char *name)
{
Milan Broz's avatar
Milan Broz committed
1060
	struct crypt_dm_active_device dmd = {}, dmdi = {};
1061
	char cipher[MAX_CIPHER_LEN], cipher_mode[MAX_CIPHER_LEN];
Milan Broz's avatar
Milan Broz committed
1062
	const char *namei;
1063 1064
	int key_nums, r;

Milan Broz's avatar
Milan Broz committed
1065 1066 1067 1068 1069
	r = dm_query_device(cd, name,
			DM_ACTIVE_DEVICE |
			DM_ACTIVE_UUID |
			DM_ACTIVE_CRYPT_CIPHER |
			DM_ACTIVE_CRYPT_KEYSIZE, &dmd);
1070 1071
	if (r < 0)
		goto out;
Milan Broz's avatar
Milan Broz committed
1072 1073

	r = crypt_parse_name_and_mode(dmd.u.crypt.cipher, cipher,
1074
				      &key_nums, cipher_mode);
Milan Broz's avatar
Milan Broz committed
1075
	if (r < 0) {
1076
		log_dbg(cd, "Cannot parse cipher and mode from active device.");
Milan Broz's avatar
Milan Broz committed
1077 1078 1079 1080 1081 1082 1083 1084
		goto out;
	}

	if (dmd.u.crypt.integrity && (namei = device_dm_name(dmd.data_device))) {
		r = dm_query_device(cd, namei, DM_ACTIVE_DEVICE, &dmdi);
		if (r < 0)
			goto out;
		if (dmdi.target == DM_INTEGRITY && !cd->metadata_device) {
1085
			device_free(cd, cd->device);
Milan Broz's avatar
Milan Broz committed
1086 1087
			cd->device = dmdi.data_device;
		} else
1088
			device_free(cd, dmdi.data_device);
Milan Broz's avatar
Milan Broz committed
1089
	}
1090 1091

	if (isPLAIN(cd->type)) {
1092 1093 1094
		cd->u.plain.hdr.hash = NULL; /* no way to get this */
		cd->u.plain.hdr.offset = dmd.u.crypt.offset;
		cd->u.plain.hdr.skip = dmd.u.crypt.iv_offset;
1095
		cd->u.plain.hdr.sector_size = dmd.u.crypt.sector_size;
1096
		cd->u.plain.key_size = dmd.u.crypt.vk->keylength;
Milan Broz's avatar
Milan Broz committed
1097 1098
		cd->u.plain.cipher = strdup(cipher);
		cd->u.plain.cipher_mode = strdup(cipher_mode);
1099
	} else if (isLOOPAES(cd->type)) {
1100
		cd->u.loopaes.hdr.offset = dmd.u.crypt.offset;
Milan Broz's avatar
Milan Broz committed
1101 1102 1103 1104 1105 1106 1107
		cd->u.loopaes.cipher = strdup(cipher);
		cd->u.loopaes.cipher_mode = strdup(cipher_mode);
		/* version 3 uses last key for IV */
		if (dmd.u.crypt.vk->keylength % key_nums)
			key_nums++;
		cd->u.loopaes.key_size = dmd.u.crypt.vk->keylength / key_nums;
	} else if (isLUKS1(cd->type) || isLUKS2(cd->type)) {
Milan Broz's avatar
Milan Broz committed
1108
		if (crypt_metadata_device(cd)) {
Milan Broz's avatar
Milan Broz committed
1109
			r = _crypt_load_luks(cd, cd->type, 0, 0);
1110
			if (r < 0) {
1111
				log_dbg(cd, "LUKS device header does not match active device.");
1112
				crypt_set_null_type(cd);
1113 1114 1115 1116
				r = 0;
				goto out;
			}
			/* check whether UUIDs match each other */
Milan Broz's avatar
Milan Broz committed
1117
			r = crypt_uuid_cmp(dmd.uuid, LUKS_UUID(cd));
1118
			if (r < 0) {
1119
				log_dbg(cd, "LUKS device header uuid: %s mismatches DM returned uuid %s",
Milan Broz's avatar
Milan Broz committed
1120 1121
					LUKS_UUID(cd), dmd.uuid);
				crypt_free_type(cd);
1122
				r = 0;
Milan Broz's avatar
Milan Broz committed
1123
				goto out;
1124
			}
1125
		} else {
1126
			log_dbg(cd, "LUKS device header not available.");
1127
			crypt_set_null_type(cd);
1128
			r = 0;
1129
		}
1130
	} else if (isTCRYPT(cd->type)) {
1131
		r = TCRYPT_init_by_name(cd, name, &dmd, &cd->device,
1132
					&cd->u.tcrypt.params, &cd->u.tcrypt.hdr);
1133 1134 1135
	}
out:
	crypt_free_volume_key(dmd.u.crypt.vk);
1136
	device_free(cd, dmd.data_device);
1137
	free(CONST_CAST(void*)dmd.u.crypt.cipher);
Milan Broz's avatar
Milan Broz committed
1138
	free(CONST_CAST(void*)dmd.u.crypt.integrity);
1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149
	free(CONST_CAST(void*)dmd.uuid);
	return r;
}

static int _init_by_name_verity(struct crypt_device *cd, const char *name)
{
	struct crypt_params_verity params = {};
	struct crypt_dm_active_device dmd = {
		.target = DM_VERITY,
		.u.verity.vp = &params,
	};
1150
	int r, verity_type = 0;
1151

Milan Broz's avatar
Milan Broz committed
1152 1153 1154 1155
	r = dm_query_device(cd, name,
				DM_ACTIVE_DEVICE |
				DM_ACTIVE_VERITY_HASH_DEVICE |
				DM_ACTIVE_VERITY_PARAMS, &dmd);
1156 1157
	if (r < 0)
		goto out;
1158 1159
	if (r > 0)
		r = 0;
1160 1161

	if (isVERITY(cd->type)) {
1162
		cd->u.verity.uuid = NULL; // FIXME
1163 1164 1165 1166 1167 1168 1169 1170 1171 1172
		cd->u.verity.hdr.flags = CRYPT_VERITY_NO_HEADER; //FIXME
		cd->u.verity.hdr.data_size = params.data_size;
		cd->u.verity.root_hash_size = dmd.u.verity.root_hash_size;
		cd->u.verity.root_hash = NULL;
		cd->u.verity.hdr.hash_name = params.hash_name;
		cd->u.verity.hdr.data_device = NULL;
		cd->u.verity.hdr.hash_device = NULL;
		cd->u.verity.hdr.data_block_size = params.data_block_size;
		cd->u.verity.hdr.hash_block_size = params.hash_block_size;
		cd->u.verity.hdr.hash_area_offset = dmd.u.verity.hash_offset;
1173
		cd->u.verity.hdr.fec_area_offset = dmd.u.verity.fec_offset;
1174 1175 1176 1177
		cd->u.verity.hdr.hash_type = params.hash_type;
		cd->u.verity.hdr.flags = params.flags;
		cd->u.verity.hdr.salt_size = params.salt_size;
		cd->u.verity.hdr.salt = params.salt;
1178 1179 1180
		cd->u.verity.hdr.fec_device = params.fec_device;
		cd->u.verity.hdr.fec_roots = params.fec_roots;
		cd->u.verity.fec_device = dmd.u.verity.fec_device;
Milan Broz's avatar
Milan Broz committed
1181
		cd->metadata_device = dmd.u.verity.hash_device;
1182
		verity_type = 1;
1183 1184
	}
out:
1185 1186 1187 1188
	if (!verity_type) {
		free(CONST_CAST(void*)params.hash_name);
		free(CONST_CAST(void*)params.salt);
		free(CONST_CAST(void*)params.fec_device);
1189
	}
1190
	device_free(cd, dmd.data_device);
1191 1192 1193
	return r;
}

1194 1195 1196 1197 1198
static int _init_by_name_integrity(struct crypt_device *cd, const char *name)
{
	struct crypt_dm_active_device dmd = {
		.target = DM_INTEGRITY,
	};
1199
	int r, integrity_type = 0;
1200 1201 1202

	r = dm_query_device(cd, name, DM_ACTIVE_DEVICE |
				      DM_ACTIVE_CRYPT_KEY |
1203 1204
				      DM_ACTIVE_CRYPT_KEYSIZE |
				      DM_ACTIVE_INTEGRITY_PARAMS, &dmd);
1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218
	if (r < 0)
		goto out;
	if (r > 0)
		r = 0;

	if (isINTEGRITY(cd->type)) {
		cd->u.integrity.params.tag_size = dmd.u.integrity.tag_size;
		cd->u.integrity.params.sector_size = dmd.u.integrity.sector_size;
		cd->u.integrity.params.journal_size = dmd.u.integrity.journal_size;
		cd->u.integrity.params.journal_watermark = dmd.u.integrity.journal_watermark;
		cd->u.integrity.params.journal_commit_time = dmd.u.integrity.journal_commit_time;
		cd->u.integrity.params.interleave_sectors = dmd.u.integrity.interleave_sectors;
		cd->u.integrity.params.buffer_sectors = dmd.u.integrity.buffer_sectors;
		cd->u.integrity.params.integrity = dmd.u.integrity.integrity;
1219 1220 1221
		cd->u.integrity.params.journal_integrity = dmd.u.integrity.journal_integrity;
		cd->u.integrity.params.journal_crypt = dmd.u.integrity.journal_crypt;

1222 1223 1224 1225 1226 1227
		if (dmd.u.integrity.vk)
			cd->u.integrity.params.integrity_key_size = dmd.u.integrity.vk->keylength;
		if (dmd.u.integrity.journal_integrity_key)
			cd->u.integrity.params.journal_integrity_key_size = dmd.u.integrity.journal_integrity_key->keylength;
		if (dmd.u.integrity.journal_crypt_key)
			cd->u.integrity.params.integrity_key_size = dmd.u.integrity.journal_crypt_key->keylength;
1228 1229 1230

		cd->metadata_device = dmd.u.integrity.meta_device;

1231
		integrity_type = 1;
1232 1233
	}
out:
1234 1235 1236 1237 1238
	if (!integrity_type) {
		free(CONST_CAST(void*)dmd.u.integrity.integrity);
		free(CONST_CAST(void*)dmd.u.integrity.journal_integrity);
		free(CONST_CAST(void*)dmd.u.integrity.journal_crypt);
	}
1239
	crypt_free_volume_key(dmd.u.integrity.vk);
1240 1241
	crypt_free_volume_key(dmd.u.integrity.journal_integrity_key);
	crypt_free_volume_key(dmd.u.integrity.journal_crypt_key);
1242
	device_free(cd, dmd.data_device);
1243 1244 1245
	return r;
}

1246 1247 1248
int crypt_init_by_name_and_header(struct crypt_device **cd,
				  const char *name,
				  const char *header_device)
1249 1250
{
	crypt_status_info ci;
Milan Broz's avatar
Milan Broz committed
1251
	struct crypt_dm_active_device dmd = {};
1252
	int r;
1253

Milan Broz's avatar
Milan Broz committed
1254
	if (!cd || !name)
1255 1256
		return -EINVAL;

1257
	log_dbg(NULL, "Allocating crypt device context by device %s.", name);
1258 1259

	ci = crypt_status(NULL, name);
1260
	if (ci == CRYPT_INVALID)
1261 1262
		return -ENODEV;

1263
	if (ci < CRYPT_ACTIVE) {
1264
		log_err(NULL, _("Device %s is not active."), name);
1265
		return -ENODEV;
1266 1267
	}

Milan Broz's avatar
Milan Broz committed
1268
	r = dm_query_device(NULL, name, DM_ACTIVE_DEVICE | DM_ACTIVE_UUID, &dmd);
1269 1270
	if (r < 0)
		goto out;
1271

1272
	*cd = NULL;
1273 1274 1275 1276

	if (header_device) {
		r = crypt_init(cd, header_device);
	} else {
Milan Broz's avatar
Milan Broz committed
1277
		r = crypt_init(cd, device_path(dmd.data_device));
1278 1279

		/* Underlying device disappeared but mapping still active */
1280
		if (!dmd.data_device || r == -ENOTBLK)
1281
			log_verbose(NULL, _("Underlying device for crypt device %s disappeared."),
1282 1283 1284 1285
				    name);

		/* Underlying device is not readable but crypt mapping exists */
		if (r == -ENOTBLK) {
1286
			device_free(NULL, dmd.data_device);
1287
			dmd.data_device = NULL;
1288 1289
			r = crypt_init(cd, NULL);
		}
1290 1291
	}

1292 1293
	if (r < 0)
		goto out;
1294

1295 1296 1297 1298 1299 1300 1301
	if (dmd.uuid) {
		if (!strncmp(CRYPT_PLAIN, dmd.uuid, sizeof(CRYPT_PLAIN)-1))
			(*cd)->type = strdup(CRYPT_PLAIN);
		else if (!strncmp(CRYPT_LOOPAES, dmd.uuid, sizeof(CRYPT_LOOPAES)-1))
			(*cd)->type = strdup(CRYPT_LOOPAES);
		else if (!strncmp(CRYPT_LUKS1, dmd.uuid, sizeof(CRYPT_LUKS1)-1))
			(*cd)->type = strdup(CRYPT_LUKS1);
Milan Broz's avatar
Milan Broz committed
1302 1303
		else if (!strncmp(CRYPT_LUKS2, dmd.uuid, sizeof(CRYPT_LUKS2)-1))
			(*cd)->type = strdup(CRYPT_LUKS2);
1304 1305
		else if (!strncmp(CRYPT_VERITY, dmd.uuid, sizeof(CRYPT_VERITY)-1))
			(*cd)->type = strdup(CRYPT_VERITY);
1306 1307
		else if (!strncmp(CRYPT_TCRYPT, dmd.