static int _crypt_format_integrity(struct crypt_device *cd,
				   const char *uuid,
				   struct crypt_params_integrity *params)
{
	int r;
	uint32_t integrity_tag_size;
	char *integrity = NULL, *journal_integrity = NULL, *journal_crypt = NULL;
	struct volume_key *journal_crypt_key = NULL, *journal_mac_key = NULL;

	if (!params)
		return -EINVAL;

	if (uuid) {
		log_err(cd, _("UUID is not supported for this crypt type."));
		return -EINVAL;
	}

	r = device_check_access(cd, crypt_metadata_device(cd), DEV_EXCL);
	if (r < 0)
		return r;

	/* Wipe first 8 sectors - fs magic numbers etc. */
	r = crypt_wipe_device(cd, crypt_metadata_device(cd), CRYPT_WIPE_ZERO, 0,
			      8 * SECTOR_SIZE, 8 * SECTOR_SIZE, NULL, NULL);
	if (r < 0) {
		log_err(cd, _("Cannot wipe header on device %s."),
			mdata_device_path(cd));
		return r;
	}

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

	if (params->journal_crypt_key) {
		journal_crypt_key = crypt_alloc_volume_key(params->journal_crypt_key_size,
							   params->journal_crypt_key);
		if (!journal_crypt_key)
			return -ENOMEM;
	}

	if (params->journal_integrity_key) {
		journal_mac_key = crypt_alloc_volume_key(params->journal_integrity_key_size,
							 params->journal_integrity_key);
		if (!journal_mac_key) {
			r = -ENOMEM;
			goto out;
		}
	}

	if (params->integrity && !(integrity = strdup(params->integrity))) {
		r = -ENOMEM;
		goto out;
	}
	if (params->journal_integrity && !(journal_integrity = strdup(params->journal_integrity))) {
		r = -ENOMEM;
		goto out;
	}
	if (params->journal_crypt && !(journal_crypt = strdup(params->journal_crypt))) {
		r = -ENOMEM;
		goto out;
	}

	integrity_tag_size = INTEGRITY_hash_tag_size(integrity);
	if (integrity_tag_size > 0 && params->tag_size && integrity_tag_size != params->tag_size)
		log_std(cd, _("WARNING: Requested tag size %d bytes differs from %s size output (%d bytes).\n"),
			params->tag_size, integrity, integrity_tag_size);

	if (params->tag_size)
		integrity_tag_size = params->tag_size;

	cd->u.integrity.journal_crypt_key = journal_crypt_key;
	cd->u.integrity.journal_mac_key = journal_mac_key;
	cd->u.integrity.params.journal_size = params->journal_size;
	cd->u.integrity.params.journal_watermark = params->journal_watermark;
	cd->u.integrity.params.journal_commit_time = params->journal_commit_time;
	cd->u.integrity.params.interleave_sectors = params->interleave_sectors;
	cd->u.integrity.params.buffer_sectors = params->buffer_sectors;
	cd->u.integrity.params.sector_size = params->sector_size;
	cd->u.integrity.params.tag_size = integrity_tag_size;
	cd->u.integrity.params.integrity = integrity;
	cd->u.integrity.params.journal_integrity = journal_integrity;
	cd->u.integrity.params.journal_crypt = journal_crypt;

	r = INTEGRITY_format(cd, params, cd->u.integrity.journal_crypt_key, cd->u.integrity.journal_mac_key);
	if (r)
		log_err(cd, _("Cannot format integrity for device %s."),
			mdata_device_path(cd));
out:
	if (r) {
		crypt_free_volume_key(journal_crypt_key);
		crypt_free_volume_key(journal_mac_key);
		free(integrity);
		free(journal_integrity);
		free(journal_crypt);
	}

	return r;
}
static int _crypt_format_integrity(struct crypt_device *cd,
				   const char *uuid,
				   struct crypt_params_integrity *params)
{
	int r;
	uint32_t integrity_tag_size;
	char *integrity = NULL, *journal_integrity = NULL, *journal_crypt = NULL;
	struct volume_key *journal_crypt_key = NULL, *journal_mac_key = NULL;

	if (!params)
		return -EINVAL;

	if (uuid) {
		log_err(cd, _("UUID is not supported for this crypt type."));
		return -EINVAL;
	}

	r = device_check_access(cd, crypt_metadata_device(cd), DEV_EXCL);
	if (r < 0)
		return r;

	 
	r = crypt_wipe_device(cd, crypt_metadata_device(cd), CRYPT_WIPE_ZERO, 0,
			      8 * SECTOR_SIZE, 8 * SECTOR_SIZE, NULL, NULL);
	if (r < 0) {
		log_err(cd, _("Cannot wipe header on device %s."),
			mdata_device_path(cd));
		return r;
	}

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

	if (params->journal_crypt_key) {
		journal_crypt_key = crypt_alloc_volume_key(params->journal_crypt_key_size,
							   params->journal_crypt_key);
		if (!journal_crypt_key)
			return -ENOMEM;
	}

	if (params->journal_integrity_key) {
		journal_mac_key = crypt_alloc_volume_key(params->journal_integrity_key_size,
							 params->journal_integrity_key);
		if (!journal_mac_key) {
			r = -ENOMEM;
			goto out;
		}
	}

	if (params->integrity && !(integrity = strdup(params->integrity))) {
		r = -ENOMEM;
		goto out;
	}
	if (params->journal_integrity && !(journal_integrity = strdup(params->journal_integrity))) {
		r = -ENOMEM;
		goto out;
	}
	if (params->journal_crypt && !(journal_crypt = strdup(params->journal_crypt))) {
		r = -ENOMEM;
		goto out;
	}

	integrity_tag_size = INTEGRITY_hash_tag_size(integrity);
	if (integrity_tag_size > 0 && params->tag_size && integrity_tag_size != params->tag_size)
		log_std(cd, _("WARNING: Requested tag size %d bytes differs from %s size output (%d bytes).\n"),
			params->tag_size, integrity, integrity_tag_size);

	if (params->tag_size)
		integrity_tag_size = params->tag_size;

	cd->u.integrity.journal_crypt_key = journal_crypt_key;
	cd->u.integrity.journal_mac_key = journal_mac_key;
	cd->u.integrity.params.journal_size = params->journal_size;
	cd->u.integrity.params.journal_watermark = params->journal_watermark;
	cd->u.integrity.params.journal_commit_time = params->journal_commit_time;
	cd->u.integrity.params.interleave_sectors = params->interleave_sectors;
	cd->u.integrity.params.buffer_sectors = params->buffer_sectors;
	cd->u.integrity.params.sector_size = params->sector_size;
	cd->u.integrity.params.tag_size = integrity_tag_size;
	cd->u.integrity.params.integrity = integrity;
	cd->u.integrity.params.journal_integrity = journal_integrity;
	cd->u.integrity.params.journal_crypt = journal_crypt;

	r = INTEGRITY_format(cd, params, cd->u.integrity.journal_crypt_key, cd->u.integrity.journal_mac_key);
	if (r)
		log_err(cd, _("Cannot format integrity for device %s."),
			mdata_device_path(cd));
out:
	if (r) {
		crypt_free_volume_key(journal_crypt_key);
		crypt_free_volume_key(journal_mac_key);
		free(integrity);
		free(journal_integrity);
		free(journal_crypt);
	}

	return r;
}