static int create_new_header(struct reenc_ctx *rc, const char *cipher,
			     const char *cipher_mode, const char *uuid,
			     const char *key, int key_size,
			     struct crypt_params_luks1 *params)
{
	struct crypt_device *cd_new = NULL;
	int i, r;

	if ((r = crypt_init(&cd_new, rc->header_file_new)))
		goto out;

	if (opt_random)
		crypt_set_rng_type(cd_new, CRYPT_RNG_RANDOM);
	else if (opt_urandom)
		crypt_set_rng_type(cd_new, CRYPT_RNG_URANDOM);

	if (opt_iteration_time)
		crypt_set_iteration_time(cd_new, opt_iteration_time);

	if ((r = crypt_format(cd_new, CRYPT_LUKS1, cipher, cipher_mode,
			      uuid, key, key_size, params)))
		goto out;
	log_verbose(_("New LUKS header for device %s created.\n"), rc->device);

	for (i = 0; i < MAX_SLOT; i++) {
		if (!rc->p[i].password)
			continue;
		if ((r = crypt_keyslot_add_by_volume_key(cd_new, i,
			NULL, 0, rc->p[i].password, rc->p[i].passwordLen)) < 0)
			goto out;
		log_verbose(_("Activated keyslot %i.\n"), r);
		r = 0;
	}
out:
	crypt_free(cd_new);
	return r;
}
static int format_and_add_keyslots(const char *path)
{
	struct crypt_device *cd;
	struct crypt_params_luks1 params;
	int r;

	/*
	 * crypt_init() call precedes most of operations of cryptsetup API. The call is used
	 * to initialize crypt device context stored in structure referenced by _cd_ in
	 * the example. Second parameter is used to pass underlaying device path.
	 *
	 * Note:
	 * If path refers to a regular file it'll be attached to a first free loop device.
	 * crypt_init() operation fails in case there's no more loop device available.
	 * Also, loop device will have the AUTOCLEAR flag set, so the file loopback will
	 * be detached automatically.
	 */

	r = crypt_init(&cd, path);
	if (r < 0 ) {
		printf("crypt_init() failed for %s.\n", path);
		return r;
	}

	printf("Context is attached to block device %s.\n", crypt_get_device_name(cd));

	/*
	 * So far no data were written on your device. This will change with call of
	 * crypt_format() only if you specify CRYPT_LUKS1 as device type.
	 */
	printf("Device %s will be formatted to LUKS device after 5 seconds.\n"
	       "Press CTRL+C now if you want to cancel this operation.\n", path);
	sleep(5);


	/*
	 * Prepare LUKS format parameters
	 *
	 * hash parameter defines PBKDF2 hash algorithm used in LUKS header.
	 * For compatibility reason we use SHA1 here.
	 */
	params.hash = "sha1";

	/*
	 * data_alignment parameter is relevant only in case of the luks header
	 * and the payload are both stored on same device.
	 *
	 * if you set data_alignment = 0, cryptsetup will autodetect
	 * data_alignment according to underlaying device topology.
	 */
	params.data_alignment = 0;

	/*
	 * data_device parameter defines that no external device
	 * for luks header will be used
	 */
	params.data_device = NULL;

	/*
	 * NULLs for uuid and volume_key means that these attributes will be
	 * generated during crypt_format(). Volume key is generated with respect
	 * to key size parameter passed to function.
	 *
	 * crypt_format() checks device size (LUKS header must fit there).
	 */
	r = crypt_format(cd,		/* crypt context */
			 CRYPT_LUKS1,	/* LUKS1 is standard LUKS header */
			 "aes",		/* used cipher */
			 "xts-plain64",	/* used block mode and IV generator*/
			 NULL,		/* generate UUID */
			 NULL,		/* generate volume key from RNG */
			 256 / 8,	/* 256bit key - here AES-128 in XTS mode, size is in bytes */
			 &params);	/* parameters above */

	if(r < 0) {
		printf("crypt_format() failed on device %s\n", crypt_get_device_name(cd));
		crypt_free(cd);
		return r;
	}

	/*
	 * The device now contains LUKS1 header, but there is
	 * no active keyslot with encrypted volume key yet.
	 */

	/*
	 * cryptt_kesylot_add_* call stores volume_key in encrypted form into keyslot.
	 * Without keyslot you can't manipulate with LUKS device after the context will be freed.
	 *
	 * To create a new keyslot you need to supply the existing one (to get the volume key from) or
	 * you need to supply the volume key.
	 *
	 * After format, we have volume key stored internally in context so add new keyslot
	 * using this internal volume key.
	 */
	r = crypt_keyslot_add_by_volume_key(cd,			/* crypt context */
					    CRYPT_ANY_SLOT,	/* just use first free slot */
					    NULL,		/* use internal volume key */
					    0,			/* unused (size of volume key) */
					    "foo",		/* passphrase - NULL means query*/
					    3);			/* size of passphrase */

	if (r < 0) {
		printf("Adding keyslot failed.\n");
		crypt_free(cd);
		return r;
	}

	printf("The first keyslot is initialized.\n");

	/*
	 * Add another keyslot, now using the first keyslot.
	 * It will decrypt volume key from the first keyslot and creates new one with another passphrase.
	 */
	r = crypt_keyslot_add_by_passphrase(cd,			/* crypt context */
					    CRYPT_ANY_SLOT,	/* just use first free slot */
					    "foo", 3,		/* passphrase for the old keyslot */
					    "bar", 3);		/* passphrase for the new kesylot */
	if (r < 0) {
		printf("Adding keyslot failed.\n");
		crypt_free(cd);
		return r;
	}

	printf("The second keyslot is initialized.\n");

	crypt_free(cd);
	return 0;
}
/* Create fake header for original device */
static int backup_fake_header(struct reenc_ctx *rc)
{
	struct crypt_device *cd_new = NULL;
	struct crypt_params_luks1 params = {0};
	char cipher [MAX_CIPHER_LEN], cipher_mode[MAX_CIPHER_LEN];
	const char *header_file_fake;
	int r;

	log_dbg("Creating fake (cipher_null) header for %s device.",
		(rc->reencrypt_mode == DECRYPT) ? "new" : "original");

	header_file_fake = (rc->reencrypt_mode == DECRYPT) ? rc->header_file_new : rc->header_file_org;

	if (!opt_key_size)
		opt_key_size = DEFAULT_LUKS1_KEYBITS;

	if (opt_cipher) {
		r = crypt_parse_name_and_mode(opt_cipher, cipher, NULL, cipher_mode);
		if (r < 0) {
			log_err(_("No known cipher specification pattern detected.\n"));
			goto out;
		}
	}

	r = create_empty_header(header_file_fake, NULL, MAX_BCK_SECTORS);
	if (r < 0)
		return r;

	params.hash = opt_hash ?: DEFAULT_LUKS1_HASH;
	params.data_alignment = 0;
	params.data_device = rc->device;

	r = crypt_init(&cd_new, header_file_fake);
	if (r < 0)
		return r;

	r = crypt_format(cd_new, CRYPT_LUKS1, "cipher_null", "ecb",
			 NO_UUID, NULL, opt_key_size / 8, &params);
	if (r < 0)
		goto out;

	r = crypt_keyslot_add_by_volume_key(cd_new, rc->keyslot, NULL, 0,
			rc->p[rc->keyslot].password, rc->p[rc->keyslot].passwordLen);
	if (r < 0)
		goto out;

	/* The real header is backup header created in backup_luks_headers() */
	if (rc->reencrypt_mode == DECRYPT)
		goto out;

	r = create_empty_header(rc->header_file_new, rc->header_file_org, 0);
	if (r < 0)
		goto out;

	params.data_alignment = ROUND_SECTOR(opt_reduce_size);
	r = create_new_header(rc,
		opt_cipher ? cipher : DEFAULT_LUKS1_CIPHER,
		opt_cipher ? cipher_mode : DEFAULT_LUKS1_MODE,
		NULL, NULL,
		(opt_key_size ? opt_key_size : DEFAULT_LUKS1_KEYBITS) / 8,
		&params);
out:
	crypt_free(cd_new);
	return r;
}