Ejemplo n.º 1
0
TEE_Result syscall_se_channel_get_select_resp(unsigned long channel_handle,
			void *resp, uint64_t *resp_len)
{
	TEE_Result ret;
	struct tee_se_channel *c = tee_svc_uref_to_kaddr(channel_handle);
	struct tee_ta_session *sess;
	struct tee_se_service *service;
	struct resp_apdu *resp_apdu;
	size_t kresp_len;
	uint64_t uresp_len;

	ret = tee_ta_get_current_session(&sess);
	if (ret != TEE_SUCCESS)
		return ret;

	service = to_user_ta_ctx(sess->ctx)->se_service;
	if (!tee_se_service_is_channel_valid(service, c))
		return TEE_ERROR_BAD_PARAMETERS;

	ret = tee_svc_copy_from_user(&uresp_len, resp_len, sizeof(size_t));
	if (ret != TEE_SUCCESS)
		return TEE_ERROR_BAD_PARAMETERS;

	ret = tee_se_channel_get_select_response(c, &resp_apdu);
	if (ret != TEE_SUCCESS)
		return ret;

	kresp_len = apdu_get_length(to_apdu_base(resp_apdu));
	if (uresp_len < kresp_len)
		return TEE_ERROR_SHORT_BUFFER;

	ret = tee_svc_copy_to_user(resp,
			apdu_get_data(to_apdu_base(resp_apdu)), kresp_len);
	if (ret != TEE_SUCCESS)
		return ret;

	uresp_len = kresp_len;
	ret = tee_svc_copy_to_user(resp_len, &uresp_len, sizeof(*resp_len));
	if (ret != TEE_SUCCESS)
		return ret;

	return TEE_SUCCESS;
}
Ejemplo n.º 2
0
static TEE_Result internal_manage_channel(struct tee_se_session *s,
		bool open_ops, int *channel_id)
{
	struct cmd_apdu *cmd;
	struct resp_apdu *resp;
	TEE_Result ret;
	size_t tx_buf_len = 0, rx_buf_len = 1;

	uint8_t open_flag = (open_ops) ? OPEN_CHANNEL : CLOSE_CHANNEL;
	uint8_t channel_flag =
		(open_flag == OPEN_CHANNEL) ? OPEN_NEXT_AVAILABLE : *channel_id;

	assert(s);

	cmd = alloc_cmd_apdu(ISO7816_CLA, MANAGE_CHANNEL_CMD, open_flag,
			channel_flag, tx_buf_len, rx_buf_len, NULL);

	resp = alloc_resp_apdu(rx_buf_len);

	ret = tee_se_session_transmit(s, cmd, resp);
	if (ret != TEE_SUCCESS) {
		EMSG("exchange apdu failed: %d", ret);
		return ret;
	}

	if (resp->sw1 == CMD_OK_SW1 && resp->sw2 == CMD_OK_SW2) {
		if (open_ops)
			*channel_id = resp->base.data_buf[0];
		ret = TEE_SUCCESS;
	} else {
		EMSG("operation failed, sw1:%02X, sw2:%02X",
				resp->sw1, resp->sw2);
		ret = TEE_ERROR_NOT_SUPPORTED;
	}

	apdu_release(to_apdu_base(cmd));
	apdu_release(to_apdu_base(resp));

	return ret;
}
Ejemplo n.º 3
0
static TEE_Result internal_select(struct tee_se_channel *c,
		struct tee_se_aid *aid, int select_ops)
{
	struct cmd_apdu *cmd;
	struct resp_apdu *resp;
	struct tee_se_session *s;
	TEE_Result ret;
	TEE_SEReaderProperties prop;
	size_t rx_buf_len = 0;
	int channel_id;
	uint8_t cla_channel;

	assert(c);

	s = tee_se_channel_get_session(c);
	channel_id = tee_se_channel_get_id(c);

	if (channel_id >= MAX_LOGICAL_CHANNEL)
		panic("invalid channel id");

	cla_channel = iso7816_get_cla_channel(channel_id);
	if (select_ops == FIRST_OR_ONLY_OCCURRENCE) {
		assert(aid);
		cmd = alloc_cmd_apdu(ISO7816_CLA | cla_channel,
				SELECT_CMD, SELECT_BY_AID,
				select_ops, aid->length,
				rx_buf_len, aid->aid);
	} else {
		cmd = alloc_cmd_apdu(ISO7816_CLA | cla_channel,
				SELECT_CMD, SELECT_BY_AID,
				select_ops, 0, rx_buf_len, NULL);
	}

	resp = alloc_resp_apdu(rx_buf_len);

	ret = tee_se_session_transmit(s, cmd, resp);
	if (ret != TEE_SUCCESS) {
		EMSG("exchange apdu failed: %d", ret);
		return ret;
	}

	tee_se_reader_get_properties(s->reader_proxy, &prop);
	if (prop.selectResponseEnable)
		tee_se_channel_set_select_response(c, resp);
	if (aid)
		tee_se_channel_set_aid(c, aid);

	if (resp->sw1 == CMD_OK_SW1 && resp->sw2 == CMD_OK_SW2) {
		ret = TEE_SUCCESS;
	} else {
		EMSG("operation failed, sw1:%02X, sw2:%02X",
				resp->sw1, resp->sw2);
		if (resp->sw1 == 0x6A && resp->sw2 == 0x83)
			ret = TEE_ERROR_ITEM_NOT_FOUND;
		else
			ret = TEE_ERROR_NOT_SUPPORTED;
	}

	apdu_release(to_apdu_base(cmd));
	apdu_release(to_apdu_base(resp));

	return ret;
}
Ejemplo n.º 4
0
TEE_Result syscall_se_channel_transmit(unsigned long channel_handle,
			void *cmd, unsigned long cmd_len, void *resp,
			uint64_t *resp_len)
{
	TEE_Result ret;
	struct tee_se_channel *c = tee_svc_uref_to_kaddr(channel_handle);
	struct tee_ta_session *sess;
	struct tee_se_service *service;
	struct cmd_apdu *cmd_apdu;
	struct resp_apdu *resp_apdu;
	void *kcmd_buf;
	uint64_t kresp_len;

	ret = tee_ta_get_current_session(&sess);
	if (ret != TEE_SUCCESS)
		return ret;

	service = to_user_ta_ctx(sess->ctx)->se_service;
	if (!tee_se_service_is_channel_valid(service, c))
		return TEE_ERROR_BAD_PARAMETERS;

	ret = tee_svc_copy_from_user(&kresp_len, resp_len, sizeof(kresp_len));
	if (ret != TEE_SUCCESS)
		return ret;

	kcmd_buf = malloc(cmd_len);
	if (kcmd_buf == NULL)
		return TEE_ERROR_OUT_OF_MEMORY;

	ret = tee_svc_copy_from_user(kcmd_buf, cmd, cmd_len);
	if (ret != TEE_SUCCESS)
		goto err_free_cmd_buf;

	cmd_apdu =
		alloc_cmd_apdu_from_buf(kcmd_buf, cmd_len);
	if (cmd_apdu == NULL)
		goto err_free_cmd_buf;

	kresp_len -= 2; /* reserve space for SW1 and SW2 */
	resp_apdu = alloc_resp_apdu(kresp_len);
	if (resp_apdu == NULL)
		goto err_free_cmd_apdu;

	ret = tee_se_channel_transmit(c, cmd_apdu, resp_apdu);
	if (ret != TEE_SUCCESS)
		goto err_free_resp_apdu;

	kresp_len = apdu_get_length(to_apdu_base(resp_apdu));
	ret = tee_svc_copy_to_user(resp_len, &kresp_len, sizeof(*resp_len));
	if (ret != TEE_SUCCESS)
		goto err_free_resp_apdu;

	ret = tee_svc_copy_to_user(resp, resp_apdu_get_data(resp_apdu),
				   kresp_len);
	if (ret != TEE_SUCCESS)
		goto err_free_resp_apdu;

	apdu_release(to_apdu_base(resp_apdu));
	apdu_release(to_apdu_base(cmd_apdu));
	free(kcmd_buf);

	return TEE_SUCCESS;

err_free_resp_apdu:
	apdu_release(to_apdu_base(resp_apdu));
err_free_cmd_apdu:
	apdu_release(to_apdu_base(cmd_apdu));
err_free_cmd_buf:
	free(kcmd_buf);
	return ret;
}