int crypt_resume_by_volume_key(struct crypt_device *cd,
	const char *name,
	const char *volume_key,
	size_t volume_key_size)
{
	struct volume_key *vk = NULL;
	int r;

	if (!name || !volume_key)
		return -EINVAL;

	log_dbg(cd, "Resuming volume %s by volume key.", name);

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

	r = dm_status_suspended(cd, name);
	if (r < 0)
		return r;

	if (!r) {
		log_err(cd, _("Volume %s is not suspended."), name);
		return -EINVAL;
	}

	vk = crypt_alloc_volume_key(volume_key_size, volume_key);
	if (!vk)
		return -ENOMEM;

	if (isLUKS1(cd->type))
		r = LUKS_verify_volume_key(&cd->u.luks1.hdr, vk);
	else if (isLUKS2(cd->type))
		r = LUKS2_digest_verify_by_segment(cd, &cd->u.luks2.hdr, CRYPT_DEFAULT_SEGMENT, vk);
	else
		r = -EINVAL;
	if (r == -EPERM || r == -ENOENT)
		log_err(cd, _("Volume key does not match the volume."));

	if (r >= 0)
		r = resume_by_volume_key(cd, vk, name);

	crypt_free_volume_key(vk);
	return r;
}
int crypt_resume_by_volume_key(struct crypt_device *cd,
	const char *name,
	const char *volume_key,
	size_t volume_key_size)
{
	struct volume_key *vk = NULL;
	int r;

	if (!name || !volume_key)
		return -EINVAL;

	log_dbg(cd, "Resuming volume %s by volume key.", name);

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

	r = dm_status_suspended(cd, name);
	if (r < 0)
		return r;

	if (!r) {
		log_err(cd, _("Volume %s is not suspended."), name);
		return -EINVAL;
	}

	vk = crypt_alloc_volume_key(volume_key_size, volume_key);
	if (!vk)
		return -ENOMEM;

	if (isLUKS1(cd->type))
		r = LUKS_verify_volume_key(&cd->u.luks1.hdr, vk);
	else if (isLUKS2(cd->type))
		r = LUKS2_digest_verify_by_segment(cd, &cd->u.luks2.hdr, CRYPT_DEFAULT_SEGMENT, vk);
	else
		r = -EINVAL;
	if (r == -EPERM || r == -ENOENT)
		log_err(cd, _("Volume key does not match the volume."));

	if (r >= 0)
		r = resume_by_volume_key(cd, vk, name);

	crypt_free_volume_key(vk);
	return r;
}