#include "em_common.h"

static void em_request_make_header(em_header_info *header, const char *type, const char *version)
{
	if (header == NULL || type == NULL)
		return;

	memcpy(header->prefix, EM_MAGIC_HEADER_PREFIX, EM_LEN_HEADER_FIELD);
	memcpy(header->type, type, EM_LEN_HEADER_FIELD);
	memcpy(header->version, version, EM_LEN_HEADER_VERSION);
}

int em_request_token(uint8_t *message, uint32_t *len_message, uint64_t *flags, uint8_t *did, em_keeping_item *keep,
		     const uint8_t *imei, const uint8_t *model_name, const uint8_t *otp, const uint8_t *single_id,
		     const uint16_t *modes, const uint16_t len_mode, const uint8_t *date)
{
	int ret;

	uint16_t i = 0;

	em_header_info header = {0,};
	em_default_meta meta = {0,};
	em_default_element elem = {0,};

	uint32_t offset = 0, offset_base = 0, pos_set = 0;
	uint32_t len_header = 0, num_of_data = 0;
	uint16_t elem_buf = 0;

	EM_CHECK_NULL(__func__, EM_ERR_EM_REQUEST_TOKEN, message, len_message, flags, did, keep, imei, model_name, otp,
		      single_id, modes, date);

	em_request_make_header(&header, EM_MAGIC_TYPE_TOKEN_REQUEST, EM_MAGIC_PACKET_VERSION2);
	memcpy(message, &header, sizeof(em_header_info));
	offset += (uint32_t)sizeof(em_header_info);

	pos_set = (uint32_t)(offset + sizeof(uint32_t));

	len_header = (uint32_t)(sizeof(em_header_info) + sizeof(uint32_t) + (sizeof(uint32_t) * 5));
	memcpy(message + offset, &len_header, sizeof(uint32_t));
	offset += (uint32_t)(sizeof(uint32_t) + (sizeof(uint32_t) * 5));

	memcpy(message + pos_set, &offset, sizeof(uint32_t)); // Token Offset;
	pos_set += (uint32_t)sizeof(uint32_t);

	// Token Information
	offset_base = offset;
	offset += (uint32_t)sizeof(em_default_meta);

	elem.type = EM_TYPE_INFO_TOKE_ID;
	elem.len = EM_LEN_TOKEN_ID;
	memcpy(message + offset, &elem, sizeof(em_default_element));
	offset += (uint32_t)sizeof(em_default_element);
	offset += EM_LEN_TOKEN_ID;
	num_of_data++;

	elem.type = EM_TYPE_INFO_TOKE_UNIQUE_INFO;
	elem.len = 0;
	memcpy(message + offset, &elem, sizeof(em_default_element));
	offset += (uint32_t)sizeof(em_default_element);
	num_of_data++;

	elem.type = EM_TYPE_INFO_TOKE_NUM_DEVICES;
	elem.len = sizeof(uint16_t);
	memcpy(message + offset, &elem, sizeof(em_default_element));
	offset += (uint32_t)sizeof(em_default_element);
	elem_buf = 1;
	memcpy(message + offset, &elem_buf, sizeof(uint16_t));
	offset += (uint32_t)sizeof(uint16_t);
	num_of_data++;

	memcpy(meta.magic, EM_MAGIC_TOKEN, strlen(EM_MAGIC_TOKEN));
	meta.len = offset - offset_base - sizeof(em_default_meta);
	meta.num_of_data = num_of_data;
	memcpy(message + offset_base, &meta, sizeof(em_default_meta));

	// Device Information
	memcpy(message + pos_set, &offset, sizeof(uint32_t));
	pos_set += (uint32_t)sizeof(uint32_t);

	offset_base = offset;
	num_of_data = elem_buf = 0;
	offset += (uint32_t)sizeof(em_default_meta);

	if (strlen((const char *)model_name) > EM_LEN_MODEL_NAME) {
		LOGE("model name isn't normal(%u)\n", (uint32_t)strlen((const char *)model_name));
		ret = EM_ERR_EM_REQUEST_TOKEN_MODEL_NAME;
		goto out;
	}

	elem.type = EM_TYPE_INFO_DEVI_MODEL_NAME;
	elem.len = strlen((const char *)model_name);
	memcpy(message + offset, &elem, sizeof(em_default_element));
	offset += (uint32_t)sizeof(em_default_element);
	memcpy(message + offset, model_name, elem.len);
	offset += elem.len;
	num_of_data++;
	memcpy(keep->model_name, model_name, elem.len);

	elem.type = EM_TYPE_INFO_DEVI_DID;
	elem.len = EM_LEN_DID;
	memcpy(message + offset, &elem, sizeof(em_default_element));
	offset += (uint32_t)sizeof(em_default_element);
	memcpy(message + offset, did, EM_LEN_DID);
	offset += elem.len;
	num_of_data++;

	elem.type = EM_TYPE_INFO_DEVI_IMEI;
	elem.len = EM_LEN_IMEI;
	memcpy(message + offset, &elem, sizeof(em_default_element));
	offset += (uint32_t)sizeof(em_default_element);

	if (!(flags[0] & EM_FLAGS_0_EXIST_IMEI)) {
		memset(message + offset, EM_MAGIC_PADDING, EM_LEN_IMEI);
	} else {
		memcpy(message + offset, imei, EM_LEN_IMEI);
	}
	offset += elem.len;
	num_of_data++;

	memcpy(meta.magic, EM_MAGIC_TOKEN_DEVICE, strlen(EM_MAGIC_TOKEN_DEVICE));
	meta.len = offset - offset_base - (uint32_t)sizeof(em_default_meta);
	meta.num_of_data = num_of_data;
	memcpy(message + offset_base, &meta, sizeof(em_default_meta));

	// Issuer Information
	memcpy(message + pos_set, &offset, sizeof(uint32_t));
	pos_set += (uint32_t)sizeof(uint32_t);

	offset_base = offset;
	num_of_data = elem_buf = 0;
	offset += (uint32_t)sizeof(em_default_meta);

	if (strlen((const char *)single_id) > EM_LEN_SINGLE_ID) {
		LOGE("single id isn't normal(%u)\n", (uint32_t)strlen((const char *)single_id));
		ret = EM_ERR_EM_REQUEST_TOKEN_SINGLE_ID;
		goto out;
	}

	elem.type = EM_TYPE_INFO_ISSU_SINGLE_ID;
	elem.len = strlen((const char *)single_id);
	memcpy(message + offset, &elem, sizeof(em_default_element));
	offset += (uint32_t)sizeof(em_default_element);
	memcpy(message + offset, single_id, elem.len);
	offset += elem.len;
	num_of_data++;
	memcpy(keep->single_id, single_id, elem.len);

	memcpy(keep->otp, otp, EM_LEN_OTP);
	elem.type = EM_TYPE_INFO_ISSU_OTP;
	elem.len = EM_LEN_OTP;
	memcpy(message + offset, &elem, sizeof(em_default_element));
	offset += (uint32_t)sizeof(em_default_element);
	memcpy(message + offset, otp, elem.len);
	offset += elem.len;
	num_of_data++;

	elem.type = EM_TYPE_INFO_ISSU_NONCE;
	elem.len = EM_LEN_NONCE;
	memcpy(message + offset, &elem, sizeof(em_default_element));
	offset += (uint32_t)sizeof(em_default_element);
	ret = em_get_random(keep->nonce, EM_LEN_NONCE);
	if (ret != EM_LEN_NONCE) {
		LOGE("Failed to generate nonce (0x%08x)\n", ret);
		ret = EM_ERR_EM_REQUEST_TOKEN_NONCE;
		goto out;
	}
	memcpy(message + offset, keep->nonce, elem.len);
	offset += elem.len;
	num_of_data++;

	memcpy(meta.magic, EM_MAGIC_TOKEN_ISSUER, strlen(EM_MAGIC_TOKEN_ISSUER));
	meta.len = offset - offset_base - (uint32_t)sizeof(em_default_meta);
	meta.num_of_data = num_of_data;
	memcpy(message + offset_base, &meta, sizeof(em_default_meta));

	// Mode Information
	memcpy(message + pos_set, &offset, sizeof(uint32_t));
	pos_set += (uint32_t)sizeof(uint32_t);

	offset_base = offset;
	num_of_data = elem_buf = 0;

	if (len_mode > EM_LEN_MAX_MODE) {
		LOGE("Exceeds the number of modes you can request at a time(%d)\n", len_mode);
		ret = EM_ERR_EM_REQUEST_TOKEN_MODE;
		goto out;
	}

	memcpy(meta.magic, EM_MAGIC_TOKEN_MODE, strlen(EM_MAGIC_TOKEN_MODE));
	meta.len = len_mode * (uint32_t)sizeof(em_default_element);
	meta.num_of_data = len_mode;
	memcpy(message + offset_base, &meta, sizeof(em_default_meta));
	offset += (uint32_t)sizeof(em_default_meta);

	elem.len = 0;
	for (i = 0; i < len_mode; i++) {
		elem.type = modes[i];
		memcpy(message + offset, &elem, sizeof(em_default_element));
		offset += (uint32_t)sizeof(em_default_element);
	}

	// Validation Information
	memcpy(message + pos_set, &offset, sizeof(uint32_t));
	pos_set += (uint32_t)sizeof(uint32_t);

	offset_base = offset;
	num_of_data = elem_buf = 0;
	offset += (uint32_t)sizeof(em_default_meta);

	memcpy(keep->date, date, EM_LEN_DATE);
	elem.type = EM_TYPE_INFO_VALI_EXPIRY_DATE;
	elem.len = EM_LEN_DATE;
	memcpy(message + offset, &elem, sizeof(em_default_element));
	offset += (uint32_t)sizeof(em_default_element);
	memcpy(message + offset, keep->date, elem.len);
	offset += elem.len;
	num_of_data++;

	memcpy(meta.magic, EM_MAGIC_TOKEN_VALIDATE, strlen(EM_MAGIC_TOKEN_VALIDATE));
	meta.len = offset - offset_base - (uint32_t)sizeof(em_default_meta);
	meta.num_of_data = num_of_data;
	memcpy(message + offset_base, &meta, sizeof(em_default_meta));

	*len_message = offset;

	flags[1] |= EM_FLAGS_1_EXIST_RETURN_MESSAGE;
	flags[1] |= EM_FLAGS_1_EXIST_RETURN_KEEPING_ITEM;
	ret = EM_SUCCESS;
out:
	return ret;
}

void em_update_req_time_msg(uint8_t *msg, uint32_t *msg_index, const uint8_t *input, const uint32_t input_size,
			   const uint8_t *delem, const uint32_t max_size, const uint32_t input_max_size)
{
	int ret = EM_SUCCESS;

	EM_CHECK_NULL(__func__, EM_ERR_EM_UPDATE_REQ_TIME_MSG, msg, msg_index, input, delem);

	if (input_size > input_max_size) {
		LOGE("input buffer isn't normal(%u/%u)\n", input_size, input_max_size);
		ret = EM_ERR_EM_UPDATE_REQ_TIME_MSG_INVALID_INPUT;
		goto out;
	}

	if (*msg_index + input_size + strlen(EM_MAGIC_ESS_TOKENIZER) > max_size) {
		LOGE("%s/%s\n", msg, input);
		ret = EM_ERR_EM_UPDATE_REQ_TIME_MSG_INVALID_INPUT;
		goto out;
	}

	memcpy(msg + *msg_index, input, input_size);
	*msg_index += input_size;

	memcpy(msg + *msg_index, delem, 1);
	*msg_index += 1;

out:
	if (ret != EM_SUCCESS)
		LOGE("Failed to update msg (%08x)\n", ret);

	return;
}

int em_request_time(uint8_t *message, uint32_t *len_message, em_context *ctx)
{
	int ret;
	uint32_t offset = 0, len_edate = 0;
	uint32_t idx_msg = 0, idx_mode_msg = 0, len_mode = 0, i = 0;

	char uid[EM_LEN_CERT_UID + 1] = {0,};
	char str_tmp[EM_LEN_TOKEN_MODE_STRING + 1] = {0,};
	uint8_t msg_data[EM_LEN_MSG_DATA] = {0,};
	uint8_t *msg = NULL;
	uint8_t mode_msg[EM_LEN_TOKEN_MODE_INFORMATION] = {0,};
	uint8_t tss[EM_LEN_TSS] = {0,};
	uint8_t activated[EM_LEN_ACTIVATED] = {0,};
	uint8_t expiry_date[EM_LEN_DATE + EM_LEN_PRIORITY_TIME + 2] = {0,};
	char unique_number[EM_LEN_UNIQUE + 1] = {0,};

	em_header_info header = {0,};

	msg = (uint8_t *)em_calloc(EM_LEN_REQUEST_TIME_MSG, 1);
	EM_CHECK_NULL(__func__, EM_ERR_EM_REQUEST_TIME, message, len_message, ctx, ctx->parsed_token, msg);

	em_request_make_header(&header, EM_MAGIC_TYPE_TIME_REQUEST, EM_MAGIC_PACKET_VERSION4);

	memcpy(message, &header, sizeof(em_header_info));
	offset += (uint32_t)sizeof(em_header_info);

	ret = em_get_random(ctx->keep.nonce, EM_LEN_NONCE);
	if (ret != EM_LEN_NONCE) {
		LOGE("Failed to generate nonce(0x%08x)\n", ret);
		ret = EM_ERR_EM_REQUEST_TIME_NONCE;
		goto out;
	}

	memcpy(message + offset, ctx->keep.nonce, EM_LEN_NONCE);
	offset += EM_LEN_NONCE;

	em_snprintf((char *)tss, em_get_digit_count(ctx->tss) + 1, "%d", ctx->tss);
	em_snprintf((char *)activated, em_get_digit_count(ctx->activated) + 1, "%d", ctx->activated);

	em_update_req_time_msg(msg, &idx_msg, ctx->did, EM_LEN_DID, (uint8_t *)EM_MAGIC_ESS_TOKENIZER,
						   EM_LEN_REQUEST_TIME_MSG, EM_LEN_DID);

	em_update_req_time_msg(msg, &idx_msg, ctx->parsed_token->token.id, EM_LEN_TOKEN_ID,
						   (uint8_t *)EM_MAGIC_ESS_TOKENIZER, EM_LEN_REQUEST_TIME_MSG, EM_LEN_TOKEN_ID);

	em_update_req_time_msg(msg, &idx_msg, ctx->model_name, strlen((const char *)ctx->model_name),
						   (uint8_t *)EM_MAGIC_ESS_TOKENIZER, EM_LEN_REQUEST_TIME_MSG, EM_LEN_MODEL_NAME);
	em_update_req_time_msg(msg, &idx_msg, ctx->imei, strlen((const char *)ctx->imei),
						   (uint8_t *)EM_MAGIC_ESS_TOKENIZER, EM_LEN_REQUEST_TIME_MSG, EM_LEN_IMEI);
	em_update_req_time_msg(msg, &idx_msg, ctx->fuse, strlen((const char *)ctx->fuse),
						   (uint8_t *)EM_MAGIC_ESS_TOKENIZER, EM_LEN_REQUEST_TIME_MSG, EM_LEN_FUSE);
	em_update_req_time_msg(msg, &idx_msg, ctx->smsn, strlen((const char *)ctx->smsn),
						   (uint8_t *)EM_MAGIC_ESS_TOKENIZER, EM_LEN_REQUEST_TIME_MSG, EM_LEN_SMSN);
	em_update_req_time_msg(msg, &idx_msg, ctx->openday, strlen((const char *)ctx->openday),
						   (uint8_t *)EM_MAGIC_ESS_TOKENIZER, EM_LEN_REQUEST_TIME_MSG, EM_LEN_OPENDAY);
	em_update_req_time_msg(msg, &idx_msg, tss, strlen((const char *)tss), (uint8_t *)EM_MAGIC_ESS_TOKENIZER,
						   EM_LEN_REQUEST_TIME_MSG, EM_LEN_TSS);
	em_update_req_time_msg(msg, &idx_msg, activated, strlen((const char *)activated),
						   (uint8_t *)EM_MAGIC_ESS_TOKENIZER, EM_LEN_REQUEST_TIME_MSG, EM_LEN_ACTIVATED);

	if (ctx->parsed_token->mode.num_of_modes > EM_LEN_MAX_MODE) {
		LOGE("num of modes(%u) is bigger than max(%u)\n", ctx->parsed_token->mode.num_of_modes, EM_LEN_MAX_MODE);
		ret = EM_ERR_EM_REQUEST_TIME_MODE;
		goto out;
	}

	for (i = 0; i < ctx->parsed_token->mode.num_of_modes; i++) {
		em_itoa_for_mode(ctx->parsed_token->mode.mode[i], str_tmp);
		len_mode = strlen(str_tmp);
		if (len_mode > EM_LEN_TOKEN_MODE_STRING) {
			LOGE("Mode length isn't normal(%u)\n", len_mode);
			ret = EM_ERR_EM_REQUEST_TIME_M_LEN;
			goto out;
		}

		if (idx_mode_msg + len_mode + 1 > EM_LEN_TOKEN_MODE_INFORMATION) {
			LOGE("buf isn't enough(%u)\n", len_mode);
			LOGE("%s/%s\n", str_tmp, mode_msg);
			ret = EM_ERR_EM_REQUEST_TIME_BUF;
			goto out;
		}
		memcpy(mode_msg + idx_mode_msg, str_tmp, len_mode);
		if (i != (uint32_t)(ctx->parsed_token->mode.num_of_modes - 1)) {
			mode_msg[idx_mode_msg + len_mode] = '|';
			idx_mode_msg += len_mode + 1;
		}
	}
	em_update_req_time_msg(msg, &idx_msg, mode_msg, idx_mode_msg + len_mode, (uint8_t *)EM_MAGIC_ESS_TOKENIZER,
						   EM_LEN_REQUEST_TIME_MSG, EM_LEN_TOKEN_MODE_INFORMATION);

	if (strlen((const char *)ctx->parsed_token->issuer.single_id) > EM_LEN_SINGLE_ID) {
		LOGI("Invalid length of issuer id\n");
		ret = EM_ERR_EM_REQUEST_TIME_INVAILD_ISSUER_ID;
		goto out;
	}

	if (strlen((const char *)ctx->parsed_token->issuer.single_id) != 0) {
		em_update_req_time_msg(msg, &idx_msg, (uint8_t *)ctx->parsed_token->issuer.single_id,
							   (uint32_t)strlen((const char *)ctx->parsed_token->issuer.single_id),
							   (uint8_t *)EM_MAGIC_ESS_TOKENIZER, EM_LEN_REQUEST_TIME_MSG, EM_LEN_SINGLE_ID);
	} else {
		em_update_req_time_msg(msg, &idx_msg, (uint8_t *)"UNKNOWN", 7, (uint8_t *)EM_MAGIC_ESS_TOKENIZER,
							   EM_LEN_REQUEST_TIME_MSG, EM_LEN_SINGLE_ID);
	}

	memcpy(expiry_date, (const char *)ctx->parsed_token->validity.expiry_date, EM_LEN_DATE);
	len_edate = (uint32_t)EM_LEN_DATE;
	expiry_date[len_edate] = ',';
	len_edate += 1;

#ifdef EMLITE
	if (!(ctx->flags[0] & EM_FLAGS_0_EXIST_PRIORITY_TIME)) {
		memcpy(expiry_date + len_edate, EM_MAGIC_PRIORITY_NONE, strlen(EM_MAGIC_PRIORITY_NONE));
		len_edate += strlen(EM_MAGIC_PRIORITY_NONE);
	} else {
		memcpy(expiry_date + len_edate, ctx->priority, EM_LEN_PRIORITY_TIME);
		len_edate += EM_LEN_PRIORITY_TIME;
	}
#else
	ret = em_esi_get_item(ctx->esi, EM_TYPE_ESI_ITEM_PRIORITY_TIME, ctx->priority, EM_LEN_PRIORITY_TIME);
	if (ret != EM_SUCCESS) {
		LOGE("Failed to get priority time (0x%08x)\n", ret);
		memcpy(expiry_date + len_edate, EM_MAGIC_PRIORITY_NONE, strlen(EM_MAGIC_PRIORITY_NONE));
		len_edate += strlen(EM_MAGIC_PRIORITY_NONE);
	} else {
		memcpy(expiry_date + len_edate, ctx->priority, EM_LEN_PRIORITY_TIME);
		len_edate += EM_LEN_PRIORITY_TIME;
	}
#endif /* EMLITE */
	em_update_req_time_msg(msg, &idx_msg, expiry_date, len_edate,
						   (uint8_t *)EM_MAGIC_ESS_TOKENIZER, EM_LEN_REQUEST_TIME_MSG,
						    EM_LEN_DATE + EM_LEN_PRIORITY_TIME + 2);

	ret = em_crypto_get_subject_from_cert(ctx->parsed_token->integrity.cert, ctx->parsed_token->integrity.len_cert,
										  EM_CERT_SUBJECT_UID, uid, sizeof(uid));
	if (ret != EM_SUCCESS) {
		LOGE("Failed to get uid from cert(0x%08x)\n", ret);
		goto out;
	}

	for (i = 0; i < strlen(uid); i++) {
		if (uid[i] == ':')
			uid[i] = ',';
	}
	em_update_req_time_msg(msg, &idx_msg, (uint8_t *)uid, strlen(uid),
						   (uint8_t *)EM_MAGIC_ESS_TOKENIZER, EM_LEN_REQUEST_TIME_MSG, EM_LEN_CERT_UID);

	em_update_req_time_msg(msg, &idx_msg, ctx->osversion, EM_LEN_OSVERSION,
						   (uint8_t *)EM_MAGIC_ESS_TOKENIZER, EM_LEN_REQUEST_TIME_MSG, EM_LEN_OSVERSION);
	em_update_req_time_msg(msg, &idx_msg, ctx->swversion, strlen((const char *)ctx->swversion),
						   (uint8_t *)EM_MAGIC_ESS_TOKENIZER, EM_LEN_REQUEST_TIME_MSG, EM_LEN_SWVERSION);
	em_update_req_time_msg(msg, &idx_msg, ctx->blversion, strlen((const char *)ctx->blversion),
						   (uint8_t *)EM_MAGIC_ESS_TOKENIZER, EM_LEN_REQUEST_TIME_MSG, EM_LEN_BLVERSION);
	em_update_req_time_msg(msg, &idx_msg, ctx->omc_id, strlen((const char *)ctx->omc_id),
						   (uint8_t *)EM_MAGIC_ESS_TOKENIZER, EM_LEN_REQUEST_TIME_MSG, EM_LEN_OMC_ID);
	remove_spaces((const char *)ctx->serial, unique_number);
	memcpy(msg + idx_msg, unique_number, strlen(unique_number));
	idx_msg += strlen(unique_number);

	memcpy(msg_data, &idx_msg, EM_LEN_MSG_DATA);

	memcpy(message + offset, msg_data, EM_LEN_MSG_DATA);
	offset += EM_LEN_MSG_DATA;

	memcpy(message + offset, msg, idx_msg);
	offset += idx_msg;

	*len_message = offset;

	ctx->flags[1] |= EM_FLAGS_1_EXIST_RETURN_MESSAGE | EM_FLAGS_1_EXIST_RETURN_KEEPING_ITEM;

	ret = EM_SUCCESS;
out:
	if (msg) {
		em_free(msg);
		msg = NULL;
	}

	return ret;
}

int em_request_recovery(em_context *ctx)
{
	int ret;
	uint8_t *packet = NULL;
	uint32_t offset = 0;

	em_header_info header = {0,};

	EM_CHECK_NULL(__func__, EM_ERR_EM_REQUEST_RECOVERY, ctx);

	if (!(ctx->flags[0] & EM_FLAGS_0_EXIST_DID) || em_is_all_zero(ctx->did, EM_LEN_DID) == EM_SUCCESS) {
		LOGE("Please check flags and did\n");
		ret = EM_ERR_EM_REQUEST_RECOVERY_DID;
		goto out;
	}

	packet = ctx->message;

	em_request_make_header(&header, EM_MAGIC_TYPE_RECOVERY_REQUEST, EM_MAGIC_PACKET_VERSION2);

	memcpy(packet, &header, sizeof(em_header_info));
	offset += (uint32_t)sizeof(em_header_info);

	ret = em_get_random(ctx->keep.nonce, EM_LEN_NONCE);
	if (ret != EM_LEN_NONCE) {
		LOGE("Failed to get nonce(0x%08x)\n", ret);
		ret = EM_ERR_EM_REQUEST_RECOVERY_NONCE;
		goto out;
	}

	if (strlen((const char *)ctx->single_id) > EM_LEN_SINGLE_ID) {
		LOGE("single_id size is abnormal(%u)\n", (uint32_t)strlen((const char *)ctx->single_id));
		ret = EM_ERR_EM_REQUEST_TOKEN_SINGLE_ID;
		goto out;
	}

	memcpy(packet + offset, ctx->single_id, strlen((const char *)ctx->single_id));
	offset += 40;

	memcpy(packet + offset, ctx->otp, EM_LEN_OTP);
	offset += EM_LEN_OTP;

	memcpy(packet + offset, ctx->did, EM_LEN_DID);
	offset += EM_LEN_DID;

	memcpy(packet + offset, ctx->keep.nonce, EM_LEN_NONCE);
	offset += EM_LEN_NONCE;

	ctx->len_message = offset;
	LOGI("Success to make RecoveryITL req msg!(%u)\n", offset);

	ctx->flags[1] |= EM_FLAGS_1_EXIST_RETURN_KEEPING_ITEM | EM_FLAGS_1_EXIST_RETURN_MESSAGE;

	ret = EM_SUCCESS;
out:
	return ret;
}
