Ejemplo n.º 1
0
static TEE_Result get_benchmark_memref(uint32_t type,
				TEE_Param p[TEE_NUM_PARAMS])
{
	if ((TEE_PARAM_TYPE_GET(type, 0) != TEE_PARAM_TYPE_VALUE_OUTPUT) ||
		(TEE_PARAM_TYPE_GET(type, 1) != TEE_PARAM_TYPE_NONE) ||
		(TEE_PARAM_TYPE_GET(type, 2) != TEE_PARAM_TYPE_NONE) ||
		(TEE_PARAM_TYPE_GET(type, 3) != TEE_PARAM_TYPE_NONE)) {
		return TEE_ERROR_BAD_PARAMETERS;
	}

	mutex_lock(&bench_reg_mu);

	DMSG(TA_PRINT_PREFIX "Sending back timestamp buffer paddr = %p",
		(void *)virt_to_phys((void *)bench_ts_global));

	if (bench_ts_global) {
		p[0].value.a = virt_to_phys((void *)bench_ts_global);
		p[0].value.b = bench_ts_size;
	} else {
		p[0].value.a = 0;
		p[0].value.b = 0;
	}

	mutex_unlock(&bench_reg_mu);

	return TEE_SUCCESS;
}
Ejemplo n.º 2
0
static TEE_Result check_recv_params(uint32_t paramTypes,
				    TEE_Param *params)
{
	uint32_t i;

	/* Check parameter type */
	if (TEE_PARAM_TYPE_GET(paramTypes, 0) != TEE_PARAM_TYPE_VALUE_INOUT) {
		OT_LOG(LOG_ERR, "Expected value inout type as index 0 parameter");
		return TEE_ERROR_BAD_PARAMETERS;
	}

	if (TEE_PARAM_TYPE_GET(paramTypes, 1) != TEE_PARAM_TYPE_MEMREF_INOUT ||
	    TEE_PARAM_TYPE_GET(paramTypes, 2) != TEE_PARAM_TYPE_MEMREF_INOUT ||
	    TEE_PARAM_TYPE_GET(paramTypes, 3) != TEE_PARAM_TYPE_MEMREF_INOUT) {
		OT_LOG(LOG_ERR, "Expected buffer inout type as index 1,2,3 parameter");
		return TEE_ERROR_BAD_PARAMETERS;
	}

	/* Param 0 */
	if (params[0].value.a != IN_VALUE_A) {
		OT_LOG(LOG_ERR, "Not expected parameter at 0 (value a)");
		return TEE_ERROR_BAD_PARAMETERS;
	}

	if (params[0].value.b != IN_VALUE_B) {
		OT_LOG(LOG_ERR, "Not expected parameter at 0 (value b)");
		return TEE_ERROR_BAD_PARAMETERS;
	}

	/* Param 1 & 2 */
	for (i = 1; i < 3; i++) {

		if (SIZE_OF_VEC(in_vector) != params[i].memref.size) {
			OT_LOG(LOG_ERR, "Not expected parameter at %u (wrong buffer length)", i);
			return TEE_ERROR_BAD_PARAMETERS;
		}

		if (TEE_MemCompare(in_vector, params[1].memref.buffer, params[1].memref.size)) {
			OT_LOG(LOG_ERR, "Not expected parameter at %u (wrong data)", i);
			return TEE_ERROR_BAD_PARAMETERS;
		}
	}

	/* Param 3, just length */
	if (RAND_BUFFER_SIZE != params[3].memref.size) {
		OT_LOG(LOG_ERR, "Not expected parameter at 3 (wrong buffer length)");
		return TEE_ERROR_BAD_PARAMETERS;
	}

	return TEE_SUCCESS;
}
Ejemplo n.º 3
0
void __utee_to_param(TEE_Param params[TEE_NUM_PARAMS],
			uint32_t *param_types, const struct utee_params *up)
{
	size_t n;
	uint32_t types = up->types;

	for (n = 0; n < TEE_NUM_PARAMS; n++) {
		uintptr_t a = up->vals[n * 2];
		uintptr_t b = up->vals[n * 2 + 1];

		switch (TEE_PARAM_TYPE_GET(types, n)) {
		case TEE_PARAM_TYPE_VALUE_INPUT:
		case TEE_PARAM_TYPE_VALUE_OUTPUT:
		case TEE_PARAM_TYPE_VALUE_INOUT:
			params[n].value.a = a;
			params[n].value.b = b;
			break;
		case TEE_PARAM_TYPE_MEMREF_INPUT:
		case TEE_PARAM_TYPE_MEMREF_OUTPUT:
		case TEE_PARAM_TYPE_MEMREF_INOUT:
			params[n].memref.buffer = (void *)a;
			params[n].memref.size = b;
			break;
		default:
			break;
		}
	}

	if (param_types)
		*param_types = types;
}
Ejemplo n.º 4
0
void __utee_from_param(struct utee_params *up, uint32_t param_types,
			const TEE_Param params[TEE_NUM_PARAMS])
{
	size_t n;

	up->types = param_types;
	for (n = 0; n < TEE_NUM_PARAMS; n++) {
		switch (TEE_PARAM_TYPE_GET(param_types, n)) {
		case TEE_PARAM_TYPE_VALUE_INPUT:
		case TEE_PARAM_TYPE_VALUE_OUTPUT:
		case TEE_PARAM_TYPE_VALUE_INOUT:
			up->vals[n * 2] = params[n].value.a;
			up->vals[n * 2 + 1] = params[n].value.b;
			break;
		case TEE_PARAM_TYPE_MEMREF_INPUT:
		case TEE_PARAM_TYPE_MEMREF_OUTPUT:
		case TEE_PARAM_TYPE_MEMREF_INOUT:
			up->vals[n * 2] = (uintptr_t)params[n].memref.buffer;
			up->vals[n * 2 + 1] = params[n].memref.size;
			break;
		default:
			up->vals[n * 2] = 0;
			up->vals[n * 2 + 1] = 0;
			break;
		}
	}
}
Ejemplo n.º 5
0
TEE_Result TA_EXPORT TA_InvokeCommandEntryPoint(void *sessionContext, uint32_t commandID,
						uint32_t paramTypes, TEE_Param params[4])
{
	TEEC_Result ret = TEEC_SUCCESS;
	sessionContext = sessionContext;

	OT_LOG(LOG_DEBUG, "Calling the Invoke command entry point");

	switch (commandID) {
	case CMD_GET_CTR:
		OT_LOG(LOG_DEBUG, "Command: GetCounter");

		/* Check parameter type */
		if (TEE_PARAM_TYPE_GET(paramTypes, 0) != TEE_PARAM_TYPE_MEMREF_INOUT) {
			OT_LOG(LOG_ERR, "Expected buffer input type as index 0 parameter");
			ret = TEE_ERROR_BAD_PARAMETERS;
			goto end;
		}

		ret = get_counter_value((uint64_t *)(params[0].memref.buffer));
		break;

	default:
		OT_LOG(LOG_ERR, "Unknown command");
		break;
	}

end:
	return ret;
}
Ejemplo n.º 6
0
static TEE_Result get_global(uint32_t param_types, TEE_Param params[4])
{
    int i;

    /* Param 0 is a memref, input/output */
    if (TEE_PARAM_TYPE_VALUE_OUTPUT != TEE_PARAM_TYPE_GET(param_types, 0))
        return TEE_ERROR_BAD_PARAMETERS;

    /* Other parameters must be of type TEE_PARAM_TYPE_NONE */
    for (i = 1; i < 4; i++) {
        if (TEE_PARAM_TYPE_NONE != TEE_PARAM_TYPE_GET(param_types, i))
            return TEE_ERROR_BAD_PARAMETERS;
    }

    params[0].value.a = _globalvalue;
    return TEE_SUCCESS;
}
Ejemplo n.º 7
0
static uint32_t tee_mmu_get_io_size(const struct tee_ta_param *param)
{
	uint32_t i;
	uint32_t res = 0;

	for (i = 0; i < 4; i++) {
		uint32_t param_type = TEE_PARAM_TYPE_GET(param->types, i);

		if ((param_type == TEE_PARAM_TYPE_MEMREF_INPUT ||
		     param_type == TEE_PARAM_TYPE_MEMREF_OUTPUT ||
		     param_type == TEE_PARAM_TYPE_MEMREF_INOUT) &&
		    param->params[i].memref.size != 0) {
			res +=
			    ((((uint32_t) param->params[i].memref.
			       buffer & SECTION_MASK) +
			      param->params[i].memref.size) >> SECTION_SHIFT) +
			    1;
		}
	}
Ejemplo n.º 8
0
/**
 * tee_ta_verify_param() - check that the 4 "params" match security
 */
TEE_Result tee_ta_verify_param(struct tee_ta_session *sess,
			       struct tee_ta_param *param)
{
	tee_paddr_t p;
	size_t l;
	int n;

	for (n = 0; n < TEE_NUM_PARAMS; n++) {
		switch (TEE_PARAM_TYPE_GET(param->types, n)) {
		case TEE_PARAM_TYPE_MEMREF_OUTPUT:
		case TEE_PARAM_TYPE_MEMREF_INOUT:
		case TEE_PARAM_TYPE_MEMREF_INPUT:

			if (param->param_attr[n] & TEE_MATTR_VIRTUAL) {
				p = virt_to_phys(
					param->params[n].memref.buffer);
				if (!p)
					return TEE_ERROR_SECURITY;
			} else {
				p = (tee_paddr_t)param->params[n].memref.buffer;
			}
			l = param->params[n].memref.size;

			if (core_pbuf_is(CORE_MEM_NSEC_SHM, p, l))
				break;
			if ((sess->ctx->flags & TA_FLAG_UNSAFE_NW_PARAMS) &&
				core_pbuf_is(CORE_MEM_MULTPURPOSE, p, l))
				break;
			if ((sess->clnt_id.login == TEE_LOGIN_TRUSTED_APP) &&
				core_pbuf_is(CORE_MEM_TA_RAM, p, l))
				break;

			return TEE_ERROR_SECURITY;
		default:
			break;
		}
	}
	return TEE_SUCCESS;
}
Ejemplo n.º 9
0
TEE_Result tee_compat_param_new_to_old(const struct tee_ta_param *param,
				       TEE_Operation *op)
{
	size_t n;

	op->flags = 0;
	for (n = 0; n < 4; n++) {
		switch (TEE_PARAM_TYPE_GET(param->types, n)) {
		case TEE_PARAM_TYPE_NONE:
			continue;

		case TEE_PARAM_TYPE_VALUE_INPUT:
		case TEE_PARAM_TYPE_VALUE_OUTPUT:
		case TEE_PARAM_TYPE_VALUE_INOUT:
			return TEE_ERROR_BAD_PARAMETERS; /* Not supported */

		case TEE_PARAM_TYPE_MEMREF_INPUT:
			op->memRefs[n].flags = TEE_MEM_INPUT;
			break;

		case TEE_PARAM_TYPE_MEMREF_OUTPUT:
			op->memRefs[n].flags = TEE_MEM_OUTPUT;
			break;

		case TEE_PARAM_TYPE_MEMREF_INOUT:
			op->memRefs[n].flags = TEE_MEM_INPUT | TEE_MEM_OUTPUT;
			break;

		default:
			return TEE_ERROR_BAD_PARAMETERS; /* Not supported */
		}

		op->flags |= 1 << n;
		op->memRefs[n].buffer = param->params[n].memref.buffer;
		op->memRefs[n].size = param->params[n].memref.size;
	}

	return TEE_SUCCESS;
}
Ejemplo n.º 10
0
/*
 * tee_mmu_map - alloc and fill mmu mapping table for a user TA (uTA).
 *
 * param - Contains the physical addr of the input buffers
 *         Returns logical addresses
 *
 * Allocate a table to store the N first section entries of the MMU L1 table
 * used to map the target user TA, and clear table to 0.
 * Load mapping for the TA stack_heap area, code area and params area (params
 * are the 4 GP TEE TA invoke parameters buffer).
 */
TEE_Result tee_mmu_map(struct tee_ta_ctx *ctx, struct tee_ta_param *param)
{
	TEE_Result res = TEE_SUCCESS;
	paddr_t pa = 0;
	uintptr_t smem;
	size_t n;

	TEE_ASSERT((ctx->flags & TA_FLAG_EXEC_DDR) != 0);

	res = tee_mmu_umap_init(ctx->mmu);
	if (res != TEE_SUCCESS)
		goto exit;

	/*
	 * Map stack
	 */
	smem = tee_mm_get_smem(ctx->mm_stack);
	if (core_va2pa((void *)smem, &pa)) {
		res = TEE_ERROR_SECURITY;
		goto exit;
	}
	tee_mmu_umap_set_pa(ctx->mmu->table + TEE_MMU_UMAP_HEAP_STACK_IDX,
			    CORE_MMU_USER_CODE_SIZE,
			    pa, tee_mm_get_bytes(ctx->mm_stack),
			    TEE_MMU_UDATA_ATTR | TEE_MMU_UCACHE_DEFAULT_ATTR);

	/*
	 * Map code
	 */
	smem = tee_mm_get_smem(ctx->mm);
	if (core_va2pa((void *)smem, &pa)) {
		res = TEE_ERROR_SECURITY;
		goto exit;
	}
	tee_mmu_umap_set_pa(ctx->mmu->table + TEE_MMU_UMAP_CODE_IDX,
			    CORE_MMU_USER_CODE_SIZE,
			    pa, tee_mm_get_bytes(ctx->mm),
			    TEE_MMU_UCODE_ATTR | TEE_MMU_UCACHE_DEFAULT_ATTR);


	for (n = 0; n < 4; n++) {
		uint32_t param_type = TEE_PARAM_TYPE_GET(param->types, n);
		TEE_Param *p = &param->params[n];
		uint32_t attr = TEE_MMU_UDATA_ATTR;

		if (param_type != TEE_PARAM_TYPE_MEMREF_INPUT &&
		    param_type != TEE_PARAM_TYPE_MEMREF_OUTPUT &&
		    param_type != TEE_PARAM_TYPE_MEMREF_INOUT)
			continue;
		if (p->memref.size == 0)
			continue;

		if (tee_pbuf_is_non_sec(p->memref.buffer, p->memref.size))
			attr &= ~TEE_MATTR_SECURE;

		if (param->param_attr[n] & TEESMC_ATTR_CACHE_I_WRITE_THR)
			attr |= TEE_MATTR_I_WRITE_THR;
		if (param->param_attr[n] & TEESMC_ATTR_CACHE_I_WRITE_BACK)
			attr |= TEE_MATTR_I_WRITE_BACK;
		if (param->param_attr[n] & TEESMC_ATTR_CACHE_O_WRITE_THR)
			attr |= TEE_MATTR_O_WRITE_THR;
		if (param->param_attr[n] & TEESMC_ATTR_CACHE_O_WRITE_BACK)
			attr |= TEE_MATTR_O_WRITE_BACK;


		res = tee_mmu_umap_add_param(ctx->mmu,
				(paddr_t)p->memref.buffer, p->memref.size,
				attr);
		if (res != TEE_SUCCESS)
			goto exit;
	}

	res = tee_mmu_umap_set_vas(ctx->mmu);
	if (res != TEE_SUCCESS)
		goto exit;

	for (n = 0; n < 4; n++) {
		uint32_t param_type = TEE_PARAM_TYPE_GET(param->types, n);
		TEE_Param *p = &param->params[n];

		if (param_type != TEE_PARAM_TYPE_MEMREF_INPUT &&
		    param_type != TEE_PARAM_TYPE_MEMREF_OUTPUT &&
		    param_type != TEE_PARAM_TYPE_MEMREF_INOUT)
			continue;
		if (p->memref.size == 0)
			continue;

		res = tee_mmu_user_pa2va(ctx, (paddr_t)p->memref.buffer,
					 &p->memref.buffer);
		if (res != TEE_SUCCESS)
			goto exit;
	}

	ctx->mmu->ta_private_vmem_start = ctx->mmu->table[0].va;

	n = TEE_MMU_UMAP_MAX_ENTRIES;
	do {
		n--;
	} while (n && !ctx->mmu->table[n].size);
	ctx->mmu->ta_private_vmem_end = ctx->mmu->table[n].va +
					ctx->mmu->table[n].size;

exit:
	if (res != TEE_SUCCESS)
		tee_mmu_umap_clear(ctx->mmu);

	return res;
}
Ejemplo n.º 11
0
/*
 * Supported tests on parameters
 * (I, J, K, L refer to param index)
 *
 * Case 1: command parameters type are: 1 in/out value, 3 empty.
 *         => process outI.a = inI.a + inI.b
 * Case 2: command parameters type are: 3 input value, 1 output value
 *         => process = outI.a = inJ.a + inK.a + inL.a
 * Case 3: command parameters type are: 1 in/out memref, 3 empty.
 *         => process = outI[0] = sum(inI[0..len-1])
 */
static TEE_Result test_entry_params(uint32_t type, TEE_Param p[4])
{
	size_t i;
	uint8_t d8, *in;

	/* case 1a: 1 input/output value argument */
	if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_VALUE_INOUT) &&
		(TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_NONE) &&
		(TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_NONE) &&
		(TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_NONE)) {
		p[0].value.a = p[0].value.a + p[0].value.b;
		return TEE_SUCCESS;
	}
	/* case 1b: 1 input/output value argument */
	if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_NONE) &&
		(TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_VALUE_INOUT) &&
		(TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_NONE) &&
		(TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_NONE)) {
		p[1].value.a = p[1].value.a + p[1].value.b;
		return TEE_SUCCESS;
	}
	/* case 1c: 1 input/output value argument */
	if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_NONE) &&
		(TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_NONE) &&
		(TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_VALUE_INOUT) &&
		(TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_NONE)) {
		p[2].value.a = p[2].value.a + p[2].value.b;
		return TEE_SUCCESS;
	}
	/* case 1d: 1 input/output value argument */
	if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_NONE) &&
		(TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_NONE) &&
		(TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_NONE) &&
		(TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_VALUE_INOUT)) {
		p[3].value.a = p[3].value.a + p[3].value.b;
		return TEE_SUCCESS;
	}

	/* case 2a: 3 input value arguments, 1 output value argument */
	if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_VALUE_OUTPUT) &&
		(TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_VALUE_INPUT) &&
		(TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_VALUE_INPUT) &&
		(TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_VALUE_INPUT)) {
		p[0].value.a = p[1].value.a + p[2].value.a + p[3].value.a;
		p[0].value.b = p[1].value.b + p[2].value.b + p[3].value.b;
		return TEE_SUCCESS;
	}
	/* case 2a: 3 input value arguments, 1 output value argument */
	if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_VALUE_INPUT) &&
		(TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_VALUE_OUTPUT) &&
		(TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_VALUE_INPUT) &&
		(TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_VALUE_INPUT)) {
		p[1].value.a = p[0].value.a + p[2].value.a + p[3].value.a;
		p[1].value.b = p[0].value.b + p[2].value.b + p[3].value.b;
		return TEE_SUCCESS;
	}
	/* case 2a: 3 input value arguments, 1 output value argument */
	if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_VALUE_INPUT) &&
		(TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_VALUE_INPUT) &&
		(TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_VALUE_OUTPUT) &&
		(TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_VALUE_INPUT)) {
		p[2].value.a = p[0].value.a + p[1].value.a + p[3].value.a;
		p[2].value.b = p[0].value.b + p[1].value.b + p[3].value.b;
		return TEE_SUCCESS;
	}
	/* case 2a: 3 input value arguments, 1 output value argument */
	if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_VALUE_INPUT) &&
		(TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_VALUE_INPUT) &&
		(TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_VALUE_INPUT) &&
		(TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_VALUE_OUTPUT)) {
		p[3].value.a = p[0].value.a + p[1].value.a + p[2].value.a;
		p[3].value.b = p[0].value.b + p[1].value.b + p[2].value.b;
		return TEE_SUCCESS;
	}

	DMSG("expect memref params: 0x%X/%d - 0x%X/%d - 0x%X/%d - 0x%X/%d",
			p[0].memref.buffer, p[0].memref.size,
			p[1].memref.buffer, p[1].memref.size,
			p[2].memref.buffer, p[2].memref.size,
			p[3].memref.buffer, p[3].memref.size);

	/* case 3a: 1 in/out memref argument */
	if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_MEMREF_INOUT) &&
		(TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_NONE) &&
		(TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_NONE) &&
		(TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_NONE)) {
		in = (uint8_t *)p[0].memref.buffer;
		d8 = 0;
		for (i = 0; i < p[0].memref.size; i++)
			d8 += in[i];
		*(uint8_t *)p[0].memref.buffer = d8;
		return TEE_SUCCESS;
	}
	/* case 3b: 1 in/out memref argument */
	if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_NONE) &&
		(TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_MEMREF_INOUT) &&
		(TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_NONE) &&
		(TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_NONE)) {
		in = (uint8_t *)p[1].memref.buffer;
		d8 = 0;
		for (i = 0; i < p[1].memref.size; i++)
			d8 += in[i];
		*(uint8_t *)p[1].memref.buffer = d8;
		return TEE_SUCCESS;
	}
	/* case 3c: 1 in/out memref argument */
	if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_NONE) &&
		(TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_NONE) &&
		(TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_MEMREF_INOUT) &&
		(TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_NONE)) {
		in = (uint8_t *)p[2].memref.buffer;
		d8 = 0;
		for (i = 0; i < p[2].memref.size; i++)
			d8 += in[i];
		*(uint8_t *)p[2].memref.buffer = d8;
		return TEE_SUCCESS;
	}
	/* case 3d: 1 in/out memref argument */
	if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_NONE) &&
		(TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_NONE) &&
		(TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_NONE) &&
		(TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_MEMREF_INOUT)) {
		in = (uint8_t *)p[3].memref.buffer;
		d8 = 0;
		for (i = 0; i < p[3].memref.size; i++)
			d8 += in[i];
		*(uint8_t *)p[3].memref.buffer = d8;
		return TEE_SUCCESS;
	}

	EMSG("unexpected parameters");
	return TEE_ERROR_BAD_PARAMETERS;
}
Ejemplo n.º 12
0
TEE_Result tee_mmu_map_param(struct user_ta_ctx *utc,
		struct tee_ta_param *param)
{
	TEE_Result res = TEE_SUCCESS;
	size_t n;

	/* Clear all the param entries as they can hold old information */
	memset(utc->mmu->table + TEE_MMU_UMAP_PARAM_IDX, 0,
		(TEE_MMU_UMAP_MAX_ENTRIES - TEE_MMU_UMAP_PARAM_IDX) *
		sizeof(struct tee_mmap_region));

	for (n = 0; n < 4; n++) {
		uint32_t param_type = TEE_PARAM_TYPE_GET(param->types, n);
		TEE_Param *p = &param->params[n];
		uint32_t attr = TEE_MMU_UDATA_ATTR;

		if (param_type != TEE_PARAM_TYPE_MEMREF_INPUT &&
		    param_type != TEE_PARAM_TYPE_MEMREF_OUTPUT &&
		    param_type != TEE_PARAM_TYPE_MEMREF_INOUT)
			continue;
		
		if(param_type == TEE_PARAM_TYPE_MEMREF_INPUT)
			attr = TEE_MMU_UDATA_RATTR;
		if (p->memref.size == 0)
			continue;

		if (tee_pbuf_is_non_sec(p->memref.buffer, p->memref.size))
			attr &= ~TEE_MATTR_SECURE;

		if (param->param_attr[n] == OPTEE_SMC_SHM_CACHED)
			attr |= TEE_MATTR_CACHE_CACHED << TEE_MATTR_CACHE_SHIFT;
		else
			attr |= TEE_MATTR_CACHE_NONCACHE <<
				TEE_MATTR_CACHE_SHIFT;

		res = tee_mmu_umap_add_param(utc->mmu,
				(paddr_t)p->memref.buffer, p->memref.size,
				attr);
		if (res != TEE_SUCCESS)
			return res;
	}

	res = tee_mmu_umap_set_vas(utc->mmu);
	if (res != TEE_SUCCESS)
		return res;

	for (n = 0; n < 4; n++) {
		uint32_t param_type = TEE_PARAM_TYPE_GET(param->types, n);
		TEE_Param *p = &param->params[n];

		if (param_type != TEE_PARAM_TYPE_MEMREF_INPUT &&
		    param_type != TEE_PARAM_TYPE_MEMREF_OUTPUT &&
		    param_type != TEE_PARAM_TYPE_MEMREF_INOUT)
			continue;
		if (p->memref.size == 0)
			continue;

		res = tee_mmu_user_pa2va_helper(utc, (paddr_t)p->memref.buffer,
					 &p->memref.buffer);
		if (res != TEE_SUCCESS)
			return res;
	}

	utc->mmu->ta_private_vmem_start = utc->mmu->table[0].va;

	n = TEE_MMU_UMAP_MAX_ENTRIES;
	do {
		n--;
	} while (n && !utc->mmu->table[n].size);
	utc->mmu->ta_private_vmem_end = utc->mmu->table[n].va +
					utc->mmu->table[n].size;

	return check_pgt_avail(utc->mmu->ta_private_vmem_start,
			       utc->mmu->ta_private_vmem_end);
}
Ejemplo n.º 13
0
/*
 * Back from execution of service: update parameters passed from TA:
 * If some parameters were memory references:
 * - either the memref was temporary: copy back data and update size
 * - or it was the original TA memref: update only the size value.
 */
static TEE_Result tee_svc_update_out_param(
		struct tee_ta_session *sess,
		struct tee_ta_session *called_sess,
		struct tee_ta_param *param,
		tee_paddr_t tmp_buf_pa[TEE_NUM_PARAMS],
		TEE_Param params[TEE_NUM_PARAMS])
{
	size_t n;
	bool have_private_mem_map = (called_sess == NULL) ||
		(called_sess->ctx->static_ta != NULL) ||
		((called_sess->ctx->flags & TA_FLAG_USER_MODE) != 0);

	tee_ta_set_current_session(sess);

	for (n = 0; n < TEE_NUM_PARAMS; n++) {
		switch (TEE_PARAM_TYPE_GET(param->types, n)) {
		case TEE_PARAM_TYPE_MEMREF_OUTPUT:
		case TEE_PARAM_TYPE_MEMREF_INOUT:

			/* outside TA private => memref is valid, update size */
			if (!tee_mmu_is_vbuf_inside_ta_private(sess->ctx,
					(uintptr_t)params[n].memref.buffer,
					param->params[n].memref.size)) {
				params[n].memref.size =
					param->params[n].memref.size;
				break;
			}

			/*
			 * If we called a kernel TA the parameters are in shared
			 * memory and no copy is needed.
			 */
			if (have_private_mem_map &&
			    param->params[n].memref.size <=
			    params[n].memref.size) {
				uint8_t *src = 0;
				TEE_Result res;

				/* FIXME: TA_RAM is already mapped ! */
				res = tee_mmu_kmap(tmp_buf_pa[n],
					param->params[n].memref.size, &src);
				if (res != TEE_SUCCESS)
					return TEE_ERROR_GENERIC;

				res = tee_svc_copy_to_user(sess,
							 params[n].memref.
							 buffer, src,
							 param->params[n].
							 memref.size);
				if (res != TEE_SUCCESS)
					return res;
				tee_mmu_kunmap(src,
					       param->params[n].memref.size);

			}
			params[n].memref.size = param->params[n].memref.size;
			break;

		case TEE_PARAM_TYPE_VALUE_OUTPUT:
		case TEE_PARAM_TYPE_VALUE_INOUT:
			params[n].value = param->params[n].value;
			break;

		default:
			continue;
		}
	}

	return TEE_SUCCESS;
}
Ejemplo n.º 14
0
/*
 * TA invokes some TA with parameter.
 * If some parameters are memory references:
 * - either the memref is inside TA private RAM: TA is not allowed to expose
 *   its private RAM: use a temporary memory buffer and copy the data.
 * - or the memref is not in the TA private RAM:
 *   - if the memref was mapped to the TA, TA is allowed to expose it.
 *   - if so, converts memref virtual address into a physical address.
 */
static TEE_Result tee_svc_copy_param(struct tee_ta_session *sess,
				     struct tee_ta_session *called_sess,
				     uint32_t param_types,
				     TEE_Param params[TEE_NUM_PARAMS],
				     struct tee_ta_param *param,
				     tee_paddr_t tmp_buf_pa[TEE_NUM_PARAMS],
				     tee_mm_entry_t **mm)
{
	size_t n;
	TEE_Result res;
	size_t req_mem = 0;
	size_t s;
	uint8_t *dst = 0;
	tee_paddr_t dst_pa, src_pa = 0;
	bool ta_private_memref[TEE_NUM_PARAMS];

	param->types = param_types;
	if (params == NULL) {
		if (param->types != 0)
			return TEE_ERROR_BAD_PARAMETERS;
		memset(param->params, 0, sizeof(param->params));
	} else {
		tee_svc_copy_from_user(sess, param->params, params,
				       sizeof(param->params));
	}

	if ((called_sess != NULL) &&
		(called_sess->ctx->static_ta == NULL) &&
		(called_sess->ctx->flags & TA_FLAG_USER_MODE) == 0) {
		/*
		 * kernel TA, borrow the mapping of the calling
		 * during this call.
		 */
		called_sess->calling_sess = sess;
		return TEE_SUCCESS;
	}

	for (n = 0; n < TEE_NUM_PARAMS; n++) {

		ta_private_memref[n] = false;

		switch (TEE_PARAM_TYPE_GET(param->types, n)) {
		case TEE_PARAM_TYPE_MEMREF_INPUT:
		case TEE_PARAM_TYPE_MEMREF_OUTPUT:
		case TEE_PARAM_TYPE_MEMREF_INOUT:
			if (param->params[n].memref.buffer == NULL) {
				if (param->params[n].memref.size != 0)
					return TEE_ERROR_BAD_PARAMETERS;
				break;
			}
			/* uTA cannot expose its private memory */
			if (tee_mmu_is_vbuf_inside_ta_private(sess->ctx,
				    (uintptr_t)param->params[n].memref.buffer,
				    param->params[n].memref.size)) {

				s = TEE_ROUNDUP(param->params[n].memref.size,
						sizeof(uint32_t));
				/* Check overflow */
				if (req_mem + s < req_mem)
					return TEE_ERROR_BAD_PARAMETERS;
				req_mem += s;
				ta_private_memref[n] = true;
				break;
			}
			if (!tee_mmu_is_vbuf_outside_ta_private(sess->ctx,
				    (uintptr_t)param->params[n].memref.buffer,
				    param->params[n].memref.size))
				return TEE_ERROR_BAD_PARAMETERS;

			if (tee_mmu_user_va2pa(sess->ctx,
					(void *)param->params[n].memref.buffer,
					(void **)&src_pa) != TEE_SUCCESS)
				return TEE_ERROR_BAD_PARAMETERS;

			param->param_attr[n] = tee_mmu_user_get_cache_attr(
				sess->ctx,
				(void *)param->params[n].memref.buffer);

			param->params[n].memref.buffer = (void *)src_pa;
			break;

		default:
			break;
		}
	}

	if (req_mem == 0)
		return TEE_SUCCESS;

	/* Allocate section in secure DDR */
	*mm = tee_mm_alloc(&tee_mm_sec_ddr, req_mem);
	if (*mm == NULL) {
		DMSG("tee_mm_alloc TEE_ERROR_GENERIC");
		return TEE_ERROR_GENERIC;
	}

	/* Get the virtual address for the section in secure DDR */
	res = tee_mmu_kmap(tee_mm_get_smem(*mm), req_mem, &dst);
	if (res != TEE_SUCCESS)
		return res;
	dst_pa = tee_mm_get_smem(*mm);

	for (n = 0; n < 4; n++) {

		if (ta_private_memref[n] == false)
			continue;

		s = TEE_ROUNDUP(param->params[n].memref.size, sizeof(uint32_t));

		switch (TEE_PARAM_TYPE_GET(param->types, n)) {
		case TEE_PARAM_TYPE_MEMREF_INPUT:
		case TEE_PARAM_TYPE_MEMREF_INOUT:
			if (param->params[n].memref.buffer != NULL) {
				res = tee_svc_copy_from_user(sess, dst,
							     param->params[n].
							     memref.buffer,
							     param->params[n].
							     memref.size);
				if (res != TEE_SUCCESS)
					return res;

				param->param_attr[n] =
					tee_mmu_kmap_get_cache_attr(dst);
				param->params[n].memref.buffer = (void *)dst_pa;
				tmp_buf_pa[n] = dst_pa;
				dst += s;
				dst_pa += s;
			}
			break;

		case TEE_PARAM_TYPE_MEMREF_OUTPUT:
			if (param->params[n].memref.buffer != NULL) {
				param->param_attr[n] =
					tee_mmu_kmap_get_cache_attr(dst);
				param->params[n].memref.buffer = (void *)dst_pa;
				tmp_buf_pa[n] = dst_pa;
				dst += s;
				dst_pa += s;
			}
			break;

		default:
			continue;
		}
	}

	tee_mmu_kunmap(dst, req_mem);

	return TEE_SUCCESS;
}
Ejemplo n.º 15
0
static TEE_Result rpc_call_cryp(bool sec_mem, uint32_t nParamTypes,
				TEE_Param pParams[4], uint32_t cmd)
{
	TEE_TASessionHandle cryp_session;
	TEE_Result res;
	uint32_t origin;
	TEE_Param params[4];
	size_t n;

	uint32_t types =
	    TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE,
			    TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE);

	TEE_MemFill(params, 0, sizeof(TEE_Param) * 4);

	res = TEE_OpenTASession(&cryp_uuid, 0, types, params, &cryp_session,
				&origin);

	if (res != TEE_SUCCESS) {
		EMSG("rpc_sha256 - TEE_OpenTASession returned 0x%x\n",
		     (unsigned int)res);
		return res;
	}

	types = nParamTypes;
	if (sec_mem) {
		TEE_MemFill(params, 0, sizeof(params));
		for (n = 0; n < 4; n++) {
			switch (TEE_PARAM_TYPE_GET(types, n)) {
			case TEE_PARAM_TYPE_VALUE_INPUT:
			case TEE_PARAM_TYPE_VALUE_INOUT:
				params[n].value = pParams[n].value;
				break;

			case TEE_PARAM_TYPE_MEMREF_INPUT:
			case TEE_PARAM_TYPE_MEMREF_OUTPUT:
			case TEE_PARAM_TYPE_MEMREF_INOUT:
				params[n].memref.buffer =
					TEE_Malloc(pParams[n].memref.size, 0);
				if (!params[n].memref.buffer)
					TEE_Panic(0);
				params[n].memref.size = pParams[n].memref.size;
				if (TEE_PARAM_TYPE_GET(types, n) !=
				    TEE_PARAM_TYPE_MEMREF_OUTPUT)
					TEE_MemMove(params[n].memref.buffer,
						    pParams[n].memref.buffer,
						    pParams[n].memref.size);
				break;
			default:
				break;
			}
		}
	} else {
		TEE_MemMove(params, pParams, sizeof(params));
	}

	res = TEE_InvokeTACommand(cryp_session, 0, cmd, types, params, &origin);
	if (res != TEE_SUCCESS) {
		EMSG("rpc_call_cryp - TEE_InvokeTACommand returned 0x%x\n",
		     (unsigned int)res);
	}

	TEE_CloseTASession(cryp_session);

	if (sec_mem) {
		for (n = 0; n < 4; n++) {
			switch (TEE_PARAM_TYPE_GET(types, n)) {
			case TEE_PARAM_TYPE_VALUE_INOUT:
			case TEE_PARAM_TYPE_VALUE_OUTPUT:
				pParams[n].value = params[n].value;
				break;

			case TEE_PARAM_TYPE_MEMREF_INPUT:
			case TEE_PARAM_TYPE_MEMREF_OUTPUT:
			case TEE_PARAM_TYPE_MEMREF_INOUT:
				if (TEE_PARAM_TYPE_GET(types, n) !=
				    TEE_PARAM_TYPE_MEMREF_INPUT)
					TEE_MemMove(pParams[n].memref.buffer,
						    params[n].memref.buffer,
						    params[n].memref.size);
				pParams[n].memref.size = params[n].memref.size;
				TEE_Free(params[n].memref.buffer);
				break;
			default:
				break;
			}
		}

	}

	return res;
}
Ejemplo n.º 16
0
static TEE_Result alloc_benchmark_buffer(uint32_t type,
				TEE_Param p[TEE_NUM_PARAMS])
{
	TEE_Result res;

	if ((TEE_PARAM_TYPE_GET(type, 0) != TEE_PARAM_TYPE_VALUE_INOUT) ||
		(TEE_PARAM_TYPE_GET(type, 1) != TEE_PARAM_TYPE_VALUE_INPUT) ||
		(TEE_PARAM_TYPE_GET(type, 2) != TEE_PARAM_TYPE_NONE) ||
		(TEE_PARAM_TYPE_GET(type, 3) != TEE_PARAM_TYPE_NONE)) {
		return TEE_ERROR_BAD_PARAMETERS;
	}

	mutex_lock(&bench_reg_mu);

	/* Check if we have already registered buffer */
	if (bench_ts_global) {
		EMSG(TA_PRINT_PREFIX
			"timestamp buffer was already registered");
		mutex_unlock(&bench_reg_mu);
		return TEE_ERROR_BAD_STATE;
	}

	bench_ts_size = sizeof(struct tee_ts_global) +
		p[1].value.a * sizeof(struct tee_ts_cpu_buf);
	if (!bench_ts_size) {
		EMSG(TA_PRINT_PREFIX
			"invalid timestamp buffer size");
		mutex_unlock(&bench_reg_mu);
		return TEE_ERROR_BAD_STATE;
	}

	bench_mobj = thread_rpc_alloc_global_payload(bench_ts_size);
	if (!bench_mobj) {
		EMSG(TA_PRINT_PREFIX
			"can't create mobj for timestamp buffer");
		mutex_unlock(&bench_reg_mu);
		return TEE_ERROR_OUT_OF_MEMORY;
	}

	bench_ts_global = (struct tee_ts_global *)mobj_get_va(bench_mobj, 0);
	if (!bench_ts_global) {
		thread_rpc_free_global_payload(bench_mobj);
		bench_mobj = NULL;

		mutex_unlock(&bench_reg_mu);
		return TEE_ERROR_BAD_STATE;
	}

	memset((void *)bench_ts_global, 0, bench_ts_size);
	bench_ts_global->cores = p[1].value.a;

	DMSG(TA_PRINT_PREFIX
		"allocated timestamp buffer, addr = %p",
		(void *)bench_ts_global);

	mutex_unlock(&bench_reg_mu);

	/* Send back to the optee linux kernel module */
	res = rpc_reg_global_buf(OPTEE_MSG_RPC_CMD_BENCH_REG_NEW,
			virt_to_phys((void *)bench_ts_global),
			bench_ts_size);

	p[0].value.a = virt_to_phys((void *)bench_ts_global);
	p[0].value.b = bench_ts_size;

	return res;
}