int crypt_keyslot_add_by_keyfile_device_offset(struct crypt_device *cd,
	int keyslot,
	const char *keyfile,
	size_t keyfile_size,
	uint64_t keyfile_offset,
	const char *new_keyfile,
	size_t new_keyfile_size,
	uint64_t new_keyfile_offset)
{
	int digest, r, active_slots;
	size_t passwordLen, new_passwordLen;
	struct luks2_keyslot_params params;
	char *password = NULL, *new_password = NULL;
	struct volume_key *vk = NULL;

	if (!keyfile || !new_keyfile)
		return -EINVAL;

	log_dbg(cd, "Adding new keyslot, existing keyfile %s, new keyfile %s.",
		keyfile, new_keyfile);

	if ((r = onlyLUKS(cd)))
		return r;

	r = keyslot_verify_or_find_empty(cd, &keyslot);
	if (r)
		return r;

	if (isLUKS1(cd->type))
		active_slots = LUKS_keyslot_active_count(&cd->u.luks1.hdr);
	else
		active_slots = LUKS2_keyslot_active_count(&cd->u.luks2.hdr, CRYPT_DEFAULT_SEGMENT);
	if (active_slots == 0) {
		/* No slots used, try to use pre-generated key in header */
		if (cd->volume_key) {
			vk = crypt_alloc_volume_key(cd->volume_key->keylength, cd->volume_key->key);
			r = vk ? 0 : -ENOMEM;
		} else {
			log_err(cd, _("Cannot add key slot, all slots disabled and no volume key provided."));
			return -EINVAL;
		}
	} else {
		r = crypt_keyfile_device_read(cd, keyfile,
				       &password, &passwordLen,
				       keyfile_offset, keyfile_size, 0);
		if (r < 0)
			goto out;

		if (isLUKS1(cd->type))
			r = LUKS_open_key_with_hdr(CRYPT_ANY_SLOT, password, passwordLen,
						   &cd->u.luks1.hdr, &vk, cd);
		else
			r = LUKS2_keyslot_open(cd, CRYPT_ANY_SLOT, CRYPT_DEFAULT_SEGMENT, password, passwordLen, &vk);
	}

	if (r < 0)
		goto out;

	r = crypt_keyfile_device_read(cd, new_keyfile,
			       &new_password, &new_passwordLen,
			       new_keyfile_offset, new_keyfile_size, 0);
	if (r < 0)
		goto out;

	if (isLUKS1(cd->type))
		r = LUKS_set_key(keyslot, new_password, new_passwordLen,
				 &cd->u.luks1.hdr, vk, cd);
	else {
		r = LUKS2_digest_verify_by_segment(cd, &cd->u.luks2.hdr, CRYPT_DEFAULT_SEGMENT, vk);
		digest = r;

		if (r >= 0)
			r = LUKS2_keyslot_params_default(cd, &cd->u.luks2.hdr, &params);

		if (r >= 0)
			r = LUKS2_digest_assign(cd, &cd->u.luks2.hdr, keyslot, digest, 1, 0);

		if (r >= 0)
			r = LUKS2_keyslot_store(cd,  &cd->u.luks2.hdr, keyslot,
						new_password, new_passwordLen, vk, &params);
	}
out:
	crypt_safe_free(password);
	crypt_safe_free(new_password);
	crypt_free_volume_key(vk);
	if (r < 0) {
		_luks2_reload(cd);
		return r;
	}
	return keyslot;
}
int crypt_keyslot_add_by_keyfile_device_offset(struct crypt_device *cd,
	int keyslot,
	const char *keyfile,
	size_t keyfile_size,
	uint64_t keyfile_offset,
	const char *new_keyfile,
	size_t new_keyfile_size,
	uint64_t new_keyfile_offset)
{
	int digest, r, active_slots;
	size_t passwordLen, new_passwordLen;
	struct luks2_keyslot_params params;
	char *password = NULL, *new_password = NULL;
	struct volume_key *vk = NULL;

	if (!keyfile || !new_keyfile)
		return -EINVAL;

	log_dbg(cd, "Adding new keyslot, existing keyfile %s, new keyfile %s.",
		keyfile, new_keyfile);

	if ((r = onlyLUKS(cd)))
		return r;

	r = keyslot_verify_or_find_empty(cd, &keyslot);
	if (r)
		return r;

	if (isLUKS1(cd->type))
		active_slots = LUKS_keyslot_active_count(&cd->u.luks1.hdr);
	else
		active_slots = LUKS2_keyslot_active_count(&cd->u.luks2.hdr, CRYPT_DEFAULT_SEGMENT);
	if (active_slots == 0) {
		 
		if (cd->volume_key) {
			vk = crypt_alloc_volume_key(cd->volume_key->keylength, cd->volume_key->key);
			r = vk ? 0 : -ENOMEM;
		} else {
			log_err(cd, _("Cannot add key slot, all slots disabled and no volume key provided."));
			return -EINVAL;
		}
	} else {
		r = crypt_keyfile_device_read(cd, keyfile,
				       &password, &passwordLen,
				       keyfile_offset, keyfile_size, 0);
		if (r < 0)
			goto out;

		if (isLUKS1(cd->type))
			r = LUKS_open_key_with_hdr(CRYPT_ANY_SLOT, password, passwordLen,
						   &cd->u.luks1.hdr, &vk, cd);
		else
			r = LUKS2_keyslot_open(cd, CRYPT_ANY_SLOT, CRYPT_DEFAULT_SEGMENT, password, passwordLen, &vk);
	}

	if (r < 0)
		goto out;

	r = crypt_keyfile_device_read(cd, new_keyfile,
			       &new_password, &new_passwordLen,
			       new_keyfile_offset, new_keyfile_size, 0);
	if (r < 0)
		goto out;

	if (isLUKS1(cd->type))
		r = LUKS_set_key(keyslot, new_password, new_passwordLen,
				 &cd->u.luks1.hdr, vk, cd);
	else {
		r = LUKS2_digest_verify_by_segment(cd, &cd->u.luks2.hdr, CRYPT_DEFAULT_SEGMENT, vk);
		digest = r;

		if (r >= 0)
			r = LUKS2_keyslot_params_default(cd, &cd->u.luks2.hdr, &params);

		if (r >= 0)
			r = LUKS2_digest_assign(cd, &cd->u.luks2.hdr, keyslot, digest, 1, 0);

		if (r >= 0)
			r = LUKS2_keyslot_store(cd,  &cd->u.luks2.hdr, keyslot,
						new_password, new_passwordLen, vk, &params);
	}
out:
	crypt_safe_free(password);
	crypt_safe_free(new_password);
	crypt_free_volume_key(vk);
	if (r < 0) {
		_luks2_reload(cd);
		return r;
	}
	return keyslot;
}