static int reencrypt_assembly_verification_data(struct crypt_device *cd,
	struct luks2_hdr *hdr,
	struct volume_key *vks,
	struct volume_key **verification_data)
{
	uint8_t *ptr;
	int digest_new, digest_old;
	struct volume_key *data = NULL, *vk_old = NULL, *vk_new = NULL;
	size_t keyslot_data_len, segments_data_len, data_len = 2;

	/* Keys - calculate length */
	digest_new = LUKS2_reencrypt_digest_new(hdr);
	digest_old = LUKS2_reencrypt_digest_old(hdr);

	if (digest_old >= 0) {
		vk_old = crypt_volume_key_by_id(vks, digest_old);
		if (!vk_old)
			return -EINVAL;
		data_len += blob_serialize(vk_old->key, vk_old->keylength, NULL);
	}

	if (digest_new >= 0 && digest_old != digest_new) {
		vk_new = crypt_volume_key_by_id(vks, digest_new);
		if (!vk_new)
			return -EINVAL;
		data_len += blob_serialize(vk_new->key, vk_new->keylength, NULL);
	}

	if (data_len == 2)
		return -EINVAL;

	/* Metadata - calculate length */
	if (!(keyslot_data_len = reenc_keyslot_serialize(hdr, NULL)))
		return -EINVAL;
	data_len += keyslot_data_len;

	if (!(segments_data_len = backup_segments_serialize(hdr, NULL)))
		return -EINVAL;
	data_len += segments_data_len;

	/* Alloc and fill serialization data */
	data = crypt_alloc_volume_key(data_len, NULL);
	if (!data)
		return -ENOMEM;

	ptr = (uint8_t*)data->key;

	/* v2 */
	*ptr++ = 0x76;
	*ptr++ = 0x32;

	if (vk_old)
		ptr += blob_serialize(vk_old->key, vk_old->keylength, ptr);

	if (vk_new)
		ptr += blob_serialize(vk_new->key, vk_new->keylength, ptr);

	if (!reenc_keyslot_serialize(hdr, ptr))
		goto bad;
	ptr += keyslot_data_len;

	if (!backup_segments_serialize(hdr, ptr))
		goto bad;
	ptr += segments_data_len;

	assert((size_t)(ptr - (uint8_t*)data->key) == data_len);

	*verification_data = data;

	return 0;
bad:
	crypt_free_volume_key(data);
	return -EINVAL;
}
static int reencrypt_assembly_verification_data(struct crypt_device *cd,
	struct luks2_hdr *hdr,
	struct volume_key *vks,
	struct volume_key **verification_data)
{
	uint8_t *ptr;
	int digest_new, digest_old;
	struct volume_key *data = NULL, *vk_old = NULL, *vk_new = NULL;
	size_t keyslot_data_len, segments_data_len, data_len = 2;

	 
	digest_new = LUKS2_reencrypt_digest_new(hdr);
	digest_old = LUKS2_reencrypt_digest_old(hdr);

	if (digest_old >= 0) {
		vk_old = crypt_volume_key_by_id(vks, digest_old);
		if (!vk_old)
			return -EINVAL;
		data_len += blob_serialize(vk_old->key, vk_old->keylength, NULL);
	}

	if (digest_new >= 0 && digest_old != digest_new) {
		vk_new = crypt_volume_key_by_id(vks, digest_new);
		if (!vk_new)
			return -EINVAL;
		data_len += blob_serialize(vk_new->key, vk_new->keylength, NULL);
	}

	if (data_len == 2)
		return -EINVAL;

	 
	if (!(keyslot_data_len = reenc_keyslot_serialize(hdr, NULL)))
		return -EINVAL;
	data_len += keyslot_data_len;

	if (!(segments_data_len = backup_segments_serialize(hdr, NULL)))
		return -EINVAL;
	data_len += segments_data_len;

	 
	data = crypt_alloc_volume_key(data_len, NULL);
	if (!data)
		return -ENOMEM;

	ptr = (uint8_t*)data->key;

	 
	*ptr++ = 0x76;
	*ptr++ = 0x32;

	if (vk_old)
		ptr += blob_serialize(vk_old->key, vk_old->keylength, ptr);

	if (vk_new)
		ptr += blob_serialize(vk_new->key, vk_new->keylength, ptr);

	if (!reenc_keyslot_serialize(hdr, ptr))
		goto bad;
	ptr += keyslot_data_len;

	if (!backup_segments_serialize(hdr, ptr))
		goto bad;
	ptr += segments_data_len;

	assert((size_t)(ptr - (uint8_t*)data->key) == data_len);

	*verification_data = data;

	return 0;
bad:
	crypt_free_volume_key(data);
	return -EINVAL;
}