int crypt_header_restore(struct crypt_device *cd,
			 const char *requested_type,
			 const char *backup_file)
{
	struct luks_phdr hdr1;
	struct luks2_hdr hdr2;
	int r, version;

	if (requested_type && !isLUKS(requested_type))
		return -EINVAL;

	if (!cd || (cd->type && !isLUKS(cd->type)) || !backup_file)
		return -EINVAL;

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

	log_dbg(cd, "Requested header restore to device %s (%s) from "
		"file %s.", mdata_device_path(cd), requested_type ?: "any type", backup_file);

	version = LUKS2_hdr_version_unlocked(cd, backup_file);
	if (!version ||
	   (requested_type && version == 1 && !isLUKS1(requested_type)) ||
	   (requested_type && version == 2 && !isLUKS2(requested_type))) {
		log_err(cd, _("Header backup file does not contain compatible LUKS header."));
		return -EINVAL;
	}

	memset(&hdr2, 0, sizeof(hdr2));

	if (!cd->type) {
		if (version == 1)
			r = LUKS_hdr_restore(backup_file, &hdr1, cd);
		else
			r = LUKS2_hdr_restore(cd, &hdr2, backup_file);

		crypt_safe_memzero(&hdr1, sizeof(hdr1));
		crypt_safe_memzero(&hdr2, sizeof(hdr2));
	} else if (isLUKS2(cd->type) && (!requested_type || isLUKS2(requested_type))) {
		r = LUKS2_hdr_restore(cd, &cd->u.luks2.hdr, backup_file);
		if (r)
			_luks2_reload(cd);
	} else if (isLUKS1(cd->type) && (!requested_type || isLUKS1(requested_type)))
		r = LUKS_hdr_restore(backup_file, &cd->u.luks1.hdr, cd);
	else
		r = -EINVAL;

	if (!r)
		r = _crypt_load_luks(cd, version == 1 ? CRYPT_LUKS1 : CRYPT_LUKS2, 1, 1);

	return r;
}
int crypt_header_restore(struct crypt_device *cd,
			 const char *requested_type,
			 const char *backup_file)
{
	struct luks_phdr hdr1;
	struct luks2_hdr hdr2;
	int r, version;

	if (requested_type && !isLUKS(requested_type))
		return -EINVAL;

	if (!cd || (cd->type && !isLUKS(cd->type)) || !backup_file)
		return -EINVAL;

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

	log_dbg(cd, "Requested header restore to device %s (%s) from "
		"file %s.", mdata_device_path(cd), requested_type ?: "any type", backup_file);

	version = LUKS2_hdr_version_unlocked(cd, backup_file);
	if (!version ||
	   (requested_type && version == 1 && !isLUKS1(requested_type)) ||
	   (requested_type && version == 2 && !isLUKS2(requested_type))) {
		log_err(cd, _("Header backup file does not contain compatible LUKS header."));
		return -EINVAL;
	}

	memset(&hdr2, 0, sizeof(hdr2));

	if (!cd->type) {
		if (version == 1)
			r = LUKS_hdr_restore(backup_file, &hdr1, cd);
		else
			r = LUKS2_hdr_restore(cd, &hdr2, backup_file);

		crypt_safe_memzero(&hdr1, sizeof(hdr1));
		crypt_safe_memzero(&hdr2, sizeof(hdr2));
	} else if (isLUKS2(cd->type) && (!requested_type || isLUKS2(requested_type))) {
		r = LUKS2_hdr_restore(cd, &cd->u.luks2.hdr, backup_file);
		if (r)
			_luks2_reload(cd);
	} else if (isLUKS1(cd->type) && (!requested_type || isLUKS1(requested_type)))
		r = LUKS_hdr_restore(backup_file, &cd->u.luks1.hdr, cd);
	else
		r = -EINVAL;

	if (!r)
		r = _crypt_load_luks(cd, version == 1 ? CRYPT_LUKS1 : CRYPT_LUKS2, 1, 1);

	return r;
}