int reenc_keyslot_alloc(struct crypt_device *cd,
	struct luks2_hdr *hdr,
	int keyslot,
	const struct crypt_params_reencrypt *params)
{
	int r;
	json_object *jobj_keyslots, *jobj_keyslot, *jobj_area;
	uint64_t area_offset, area_length;

	log_dbg(cd, "Allocating reencrypt keyslot %d.", keyslot);

	if (keyslot < 0 || keyslot >= LUKS2_KEYSLOTS_MAX)
		return -ENOMEM;

	if (!json_object_object_get_ex(hdr->jobj, "keyslots", &jobj_keyslots))
		return -EINVAL;

	/* encryption doesn't require area (we shift data and backup will be available) */
	if (!params->data_shift) {
		r = LUKS2_find_area_max_gap(cd, hdr, &area_offset, &area_length);
		if (r < 0)
			return r;
	} else { /* we can't have keyslot w/o area...bug? */
		r = LUKS2_find_area_gap(cd, hdr, 1, &area_offset, &area_length);
		if (r < 0)
			return r;
	}

	jobj_keyslot = json_object_new_object();
	if (!jobj_keyslot)
		return -ENOMEM;

	jobj_area = json_object_new_object();

	if (params->data_shift) {
		json_object_object_add(jobj_area, "type", json_object_new_string("datashift"));
		json_object_object_add(jobj_area, "shift_size", crypt_jobj_new_uint64(params->data_shift << SECTOR_SHIFT));
	} else
		/* except data shift protection, initial setting is irrelevant. Type can be changed during reencryption */
		json_object_object_add(jobj_area, "type", json_object_new_string("none"));

	json_object_object_add(jobj_area, "offset", crypt_jobj_new_uint64(area_offset));
	json_object_object_add(jobj_area, "size", crypt_jobj_new_uint64(area_length));

	json_object_object_add(jobj_keyslot, "type", json_object_new_string("reencrypt"));
	json_object_object_add(jobj_keyslot, "key_size", json_object_new_int(1)); /* useless but mandatory */
	json_object_object_add(jobj_keyslot, "mode", json_object_new_string(crypt_reencrypt_mode_to_str(params->mode)));
	if (params->direction == CRYPT_REENCRYPT_FORWARD)
		json_object_object_add(jobj_keyslot, "direction", json_object_new_string("forward"));
	else if (params->direction == CRYPT_REENCRYPT_BACKWARD)
		json_object_object_add(jobj_keyslot, "direction", json_object_new_string("backward"));
	else
		return -EINVAL;

	json_object_object_add(jobj_keyslot, "area", jobj_area);

	json_object_object_add_by_uint(jobj_keyslots, keyslot, jobj_keyslot);
	if (LUKS2_check_json_size(cd, hdr)) {
		log_dbg(cd, "New keyslot too large to fit in free metadata space.");
		json_object_object_del_by_uint(jobj_keyslots, keyslot);
		return -ENOSPC;
	}

	JSON_DBG(cd, hdr->jobj, "JSON:");

	return 0;
}
int reenc_keyslot_alloc(struct crypt_device *cd,
	struct luks2_hdr *hdr,
	int keyslot,
	const struct crypt_params_reencrypt *params)
{
	int r;
	json_object *jobj_keyslots, *jobj_keyslot, *jobj_area;
	uint64_t area_offset, area_length;

	log_dbg(cd, "Allocating reencrypt keyslot %d.", keyslot);

	if (keyslot < 0 || keyslot >= LUKS2_KEYSLOTS_MAX)
		return -ENOMEM;

	if (!json_object_object_get_ex(hdr->jobj, "keyslots", &jobj_keyslots))
		return -EINVAL;

	 
	if (!params->data_shift) {
		r = LUKS2_find_area_max_gap(cd, hdr, &area_offset, &area_length);
		if (r < 0)
			return r;
	} else {  
		r = LUKS2_find_area_gap(cd, hdr, 1, &area_offset, &area_length);
		if (r < 0)
			return r;
	}

	jobj_keyslot = json_object_new_object();
	if (!jobj_keyslot)
		return -ENOMEM;

	jobj_area = json_object_new_object();

	if (params->data_shift) {
		json_object_object_add(jobj_area, "type", json_object_new_string("datashift"));
		json_object_object_add(jobj_area, "shift_size", crypt_jobj_new_uint64(params->data_shift << SECTOR_SHIFT));
	} else
		 
		json_object_object_add(jobj_area, "type", json_object_new_string("none"));

	json_object_object_add(jobj_area, "offset", crypt_jobj_new_uint64(area_offset));
	json_object_object_add(jobj_area, "size", crypt_jobj_new_uint64(area_length));

	json_object_object_add(jobj_keyslot, "type", json_object_new_string("reencrypt"));
	json_object_object_add(jobj_keyslot, "key_size", json_object_new_int(1));  
	json_object_object_add(jobj_keyslot, "mode", json_object_new_string(crypt_reencrypt_mode_to_str(params->mode)));
	if (params->direction == CRYPT_REENCRYPT_FORWARD)
		json_object_object_add(jobj_keyslot, "direction", json_object_new_string("forward"));
	else if (params->direction == CRYPT_REENCRYPT_BACKWARD)
		json_object_object_add(jobj_keyslot, "direction", json_object_new_string("backward"));
	else
		return -EINVAL;

	json_object_object_add(jobj_keyslot, "area", jobj_area);

	json_object_object_add_by_uint(jobj_keyslots, keyslot, jobj_keyslot);
	if (LUKS2_check_json_size(cd, hdr)) {
		log_dbg(cd, "New keyslot too large to fit in free metadata space.");
		json_object_object_del_by_uint(jobj_keyslots, keyslot);
		return -ENOSPC;
	}

	JSON_DBG(cd, hdr->jobj, "JSON:");

	return 0;
}