Esempio n. 1
0
static void popu_rsa_pub_key()
{
	printf("  ####   popu_rsa_pub_key   ####\n");

	TEE_Result ret;
	TEE_ObjectHandle rsa_pubkey;
	size_t key_size = 512;
	TEE_Attribute *params;
	size_t param_count = 2;

	ret = TEE_AllocateTransientObject(TEE_TYPE_RSA_PUBLIC_KEY, key_size, &rsa_pubkey);

	if (ret == TEE_ERROR_OUT_OF_MEMORY) {
		printf("Fail: no mem\n");
		goto err;
	}

	if (ret == TEE_ERROR_NOT_SUPPORTED) {
		printf("Fail: no sup\n");
		goto err;
	}

	params = TEE_Malloc(param_count * sizeof(TEE_Attribute), 0);
	if (params == NULL)
		goto err;

	// modulo
	params[0].attributeID = TEE_ATTR_RSA_MODULUS;
	params[0].content.ref.buffer = TEE_Malloc(KEY_IN_BYTES(key_size), 0);
	if (params[0].content.ref.buffer == NULL)
		goto err;
	RAND_bytes(params[0].content.ref.buffer, KEY_IN_BYTES(key_size));
	params[0].content.ref.length = KEY_IN_BYTES(key_size);

	// pub exp
	params[1].attributeID = TEE_ATTR_RSA_PUBLIC_EXPONENT;
	params[1].content.ref.buffer = TEE_Malloc(KEY_IN_BYTES(key_size), 0);
	if (params[1].content.ref.buffer == NULL)
		goto err;
	RAND_bytes(params[1].content.ref.buffer, KEY_IN_BYTES(key_size));
	params[1].content.ref.length = KEY_IN_BYTES(key_size);

	ret = TEE_PopulateTransientObject(rsa_pubkey, params, param_count);

	if (ret != TEE_SUCCESS) {
		printf("Fail: popu\n");
		goto err;
	}

err:
	free_attr(params, param_count);
	free(params);
	TEE_FreeTransientObject(rsa_pubkey);
}
Esempio n. 2
0
void *lws_zalloc(size_t size, const char *reason)
{
	void *ptr = TEE_Malloc(size, TEE_USER_MEM_HINT_NO_FILL_ZERO);
	if (ptr)
		memset(ptr, 0, size);
	return ptr;
}
Esempio n. 3
0
TEE_Result TA_EXPORT TA_OpenSessionEntryPoint(uint32_t paramTypes,
					      TEE_Param params[4],
					      void **sessionContext)
{
	TEE_Result tee_rv = TEE_SUCCESS;

	OT_LOG(LOG_INFO, "Calling the Open session entry point");

	tee_rv = handle_params(paramTypes, params);
	if (tee_rv != TEE_SUCCESS)
		return tee_rv;

	if (storage_test(2))
		return TEE_ERROR_GENERIC;

	if (crypto_test(2))
		return TEE_ERROR_GENERIC;

	if (*sessionContext != NULL) {
		OT_LOG(LOG_ERR, "Session context should be NULL");
		return TEE_ERROR_BAD_PARAMETERS;
	}

	*sessionContext = TEE_Malloc(SIZE_OF_VEC(out_vector), 0);
	if (*sessionContext == NULL) {
		OT_LOG(LOG_ERR, "Can not malloc space for session context");
		return TEE_ERROR_OUT_OF_MEMORY;
	}

	TEE_MemMove(*sessionContext, out_vector, SIZE_OF_VEC(out_vector));

	return tee_rv;
}
Esempio n. 4
0
static TEE_Result unpack_attrs(const uint8_t *buf, size_t blen,
			       TEE_Attribute **attrs, uint32_t *attr_count)
{
	TEE_Result res = TEE_SUCCESS;
	TEE_Attribute *a = NULL;
	const struct attr_packed *ap;
	size_t num_attrs = 0;
	const size_t num_attrs_size = sizeof(uint32_t);

	if (blen == 0)
		goto out;

	if (((uintptr_t)buf & 0x3) != 0 || blen < num_attrs_size)
		return TEE_ERROR_BAD_PARAMETERS;
	num_attrs = *(uint32_t *) (void *)buf;
	if ((blen - num_attrs_size) < (num_attrs * sizeof(*ap)))
		return TEE_ERROR_BAD_PARAMETERS;
	ap = (const struct attr_packed *)(const void *)(buf + num_attrs_size);

	if (num_attrs > 0) {
		size_t n;

		a = TEE_Malloc(num_attrs * sizeof(TEE_Attribute), 0);
		if (!a)
			return TEE_ERROR_OUT_OF_MEMORY;
		for (n = 0; n < num_attrs; n++) {
			uintptr_t p;

			a[n].attributeID = ap[n].id;
#define TEE_ATTR_BIT_VALUE		  (1 << 29)
			if (ap[n].id & TEE_ATTR_BIT_VALUE) {
				a[n].content.value.a = ap[n].a;
				a[n].content.value.b = ap[n].b;
				continue;
			}

			a[n].content.ref.length = ap[n].b;
			p = (uintptr_t)ap[n].a;
			if (p) {
				if ((p + a[n].content.ref.length) > blen) {
					res = TEE_ERROR_BAD_PARAMETERS;
					goto out;
				}
				p += (uintptr_t)buf;
			}
			a[n].content.ref.buffer = (void *)p;
		}
	}

	res = TEE_SUCCESS;
out:
	if (res == TEE_SUCCESS) {
		*attrs = a;
		*attr_count = num_attrs;
	} else {
		TEE_Free(a);
	}
	return res;
}
Esempio n. 5
0
static TEE_Result unpack_attrs(const uint8_t *buf, size_t blen,
			       TEE_Attribute **attrs, uint32_t *attr_count)
{
	TEE_Result res = TEE_SUCCESS;
	TEE_Attribute *a = NULL;
	size_t num_attrs = 0;
	const size_t num_attrs_size = sizeof(uint32_t);

	if (blen == 0)
		goto out;

	if (((uint32_t) buf & 0x3) != 0 || blen < num_attrs_size)
		return TEE_ERROR_BAD_PARAMETERS;
	num_attrs = *(uint32_t *) (void *)buf;
	if ((blen - num_attrs_size) < (num_attrs * sizeof(TEE_Attribute)))
		return TEE_ERROR_BAD_PARAMETERS;

	if (num_attrs > 0) {
		size_t n;

		a = TEE_Malloc(num_attrs * sizeof(TEE_Attribute), 0);
		if (a == NULL)
			return TEE_ERROR_OUT_OF_MEMORY;
		TEE_MemMove(a, buf + num_attrs_size,
			    num_attrs * sizeof(TEE_Attribute));

		for (n = 0; n < num_attrs; n++) {
			uintptr_t p;

#define TEE_ATTR_BIT_VALUE		  (1 << 29)
			if ((a[n].attributeID & TEE_ATTR_BIT_VALUE) != 0)
				continue; /* Only memrefs need to be updated */

			p = (uintptr_t) a[n].content.ref.buffer;
			if (p == 0)
				continue;

			if ((p + a[n].content.ref.length) > blen) {
				res = TEE_ERROR_BAD_PARAMETERS;
				goto out;
			}
			p += (uintptr_t) buf;
			a[n].content.ref.buffer = (void *)p;
		}
	}

	res = TEE_SUCCESS;
out:
	if (res == TEE_SUCCESS) {
		*attrs = a;
		*attr_count = num_attrs;
	} else {
		TEE_Free(a);
	}
	return res;
}
Esempio n. 6
0
/*------------------------------------------------------------
 *
 *  test_BigIntInit
 *
 */
static void test_BigIntInit(void)
{

	TEE_BigInt *a;
	size_t aLen;

	TB_INFO("Testing BigIntInit");

	/* Testing normal allocation and initialization */
	aLen = TEE_BigIntSizeInU32(512);
	a = (TEE_BigInt *) TEE_Malloc(aLen * sizeof(TEE_BigInt), 0);
	TEE_BigIntInit(a, aLen);
	TEE_Free(a);

	/* Testing zero allocation */
	aLen = TEE_BigIntSizeInU32(0);
	a = (TEE_BigInt *) TEE_Malloc(aLen * sizeof(TEE_BigInt), 0);
	TEE_BigIntInit(a, aLen);
	TEE_Free(a);

	/* Testing too large */
	aLen = TEE_BigIntSizeInU32(4096);
	a = (TEE_BigInt *) TEE_Malloc(aLen * sizeof(TEE_BigInt), 0);
	TEE_BigIntInit(a, aLen);
	TEE_Free(a);

	/* Testing boundaries */
	aLen = TEE_BigIntSizeInU32(2048);
	a = (TEE_BigInt *) TEE_Malloc(aLen * sizeof(TEE_BigInt), 0);
	TEE_BigIntInit(a, aLen);
	TEE_Free(a);

	aLen = TEE_BigIntSizeInU32(2049);
	a = (TEE_BigInt *) TEE_Malloc(aLen * sizeof(TEE_BigInt), 0);
	TEE_BigIntInit(a, aLen);
	TEE_Free(a);

}
Esempio n. 7
0
TEE_Result TEE_AllocatePropertyEnumerator(TEE_PropSetHandle *enumerator)
{
	struct prop_enumerator *pe;

	if (enumerator == NULL)
		return TEE_ERROR_BAD_PARAMETERS;

	pe = TEE_Malloc(sizeof(struct prop_enumerator),
			TEE_USER_MEM_HINT_NO_FILL_ZERO);
	if (pe == NULL)
		return TEE_ERROR_OUT_OF_MEMORY;

	*enumerator = (TEE_PropSetHandle) pe;
	TEE_ResetPropertyEnumerator(*enumerator);
	return TEE_SUCCESS;
}
Esempio n. 8
0
void *lws_malloc(size_t size, const char *reason)
{
	return TEE_Malloc(size, TEE_USER_MEM_HINT_NO_FILL_ZERO);
}
Esempio n. 9
0
TEE_Result TEE_AllocateOperation(TEE_OperationHandle *operation,
				 uint32_t algorithm, uint32_t mode,
				 uint32_t maxKeySize)
{
	TEE_Result res;
	TEE_OperationHandle op = TEE_HANDLE_NULL;
	uint32_t handle_state = 0;
	size_t block_size = 1;
	uint32_t req_key_usage;
	bool with_private_key = false;
	bool buffer_two_blocks = false;

	if (!operation)
		TEE_Panic(0);

	if (algorithm == TEE_ALG_AES_XTS)
		handle_state = TEE_HANDLE_FLAG_EXPECT_TWO_KEYS;

	/* Check algorithm max key size */
	switch (algorithm) {
	case TEE_ALG_DSA_SHA1:
		if (maxKeySize < 512)
			return TEE_ERROR_NOT_SUPPORTED;
		if (maxKeySize > 1024)
			return TEE_ERROR_NOT_SUPPORTED;
		if (maxKeySize % 64 != 0)
			return TEE_ERROR_NOT_SUPPORTED;
		break;

	case TEE_ALG_DSA_SHA224:
		if (maxKeySize != 2048)
			return TEE_ERROR_NOT_SUPPORTED;
		break;

	case TEE_ALG_DSA_SHA256:
		if (maxKeySize != 2048 && maxKeySize != 3072)
			return TEE_ERROR_NOT_SUPPORTED;
		break;

	case TEE_ALG_ECDSA_P192:
	case TEE_ALG_ECDH_P192:
		if (maxKeySize != 192)
			return TEE_ERROR_NOT_SUPPORTED;
		break;

	case TEE_ALG_ECDSA_P224:
	case TEE_ALG_ECDH_P224:
		if (maxKeySize != 224)
			return TEE_ERROR_NOT_SUPPORTED;
		break;

	case TEE_ALG_ECDSA_P256:
	case TEE_ALG_ECDH_P256:
		if (maxKeySize != 256)
			return TEE_ERROR_NOT_SUPPORTED;
		break;

	case TEE_ALG_ECDSA_P384:
	case TEE_ALG_ECDH_P384:
		if (maxKeySize != 384)
			return TEE_ERROR_NOT_SUPPORTED;
		break;

	case TEE_ALG_ECDSA_P521:
	case TEE_ALG_ECDH_P521:
		if (maxKeySize != 521)
			return TEE_ERROR_NOT_SUPPORTED;
		break;

	default:
		break;
	}

	/* Check algorithm mode */
	switch (algorithm) {
	case TEE_ALG_AES_CTS:
	case TEE_ALG_AES_XTS:
		buffer_two_blocks = true;
	 /*FALLTHROUGH*/ case TEE_ALG_AES_ECB_NOPAD:
	case TEE_ALG_AES_CBC_NOPAD:
	case TEE_ALG_AES_CTR:
	case TEE_ALG_AES_CCM:
	case TEE_ALG_AES_GCM:
	case TEE_ALG_DES_ECB_NOPAD:
	case TEE_ALG_DES_CBC_NOPAD:
	case TEE_ALG_DES3_ECB_NOPAD:
	case TEE_ALG_DES3_CBC_NOPAD:
		if (TEE_ALG_GET_MAIN_ALG(algorithm) == TEE_MAIN_ALGO_AES)
			block_size = TEE_AES_BLOCK_SIZE;
		else
			block_size = TEE_DES_BLOCK_SIZE;

		if (mode == TEE_MODE_ENCRYPT)
			req_key_usage = TEE_USAGE_ENCRYPT;
		else if (mode == TEE_MODE_DECRYPT)
			req_key_usage = TEE_USAGE_DECRYPT;
		else
			return TEE_ERROR_NOT_SUPPORTED;
		break;

	case TEE_ALG_RSASSA_PKCS1_V1_5_MD5:
	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1:
	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224:
	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256:
	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384:
	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512:
	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1:
	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224:
	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256:
	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384:
	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512:
	case TEE_ALG_DSA_SHA1:
	case TEE_ALG_DSA_SHA224:
	case TEE_ALG_DSA_SHA256:
	case TEE_ALG_ECDSA_P192:
	case TEE_ALG_ECDSA_P224:
	case TEE_ALG_ECDSA_P256:
	case TEE_ALG_ECDSA_P384:
	case TEE_ALG_ECDSA_P521:
		if (mode == TEE_MODE_SIGN) {
			with_private_key = true;
			req_key_usage = TEE_USAGE_SIGN;
		} else if (mode == TEE_MODE_VERIFY) {
			req_key_usage = TEE_USAGE_VERIFY;
		} else {
			return TEE_ERROR_NOT_SUPPORTED;
		}
		break;

	case TEE_ALG_RSAES_PKCS1_V1_5:
	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1:
	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA224:
	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA256:
	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA384:
	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA512:
		if (mode == TEE_MODE_ENCRYPT) {
			req_key_usage = TEE_USAGE_ENCRYPT;
		} else if (mode == TEE_MODE_DECRYPT) {
			with_private_key = true;
			req_key_usage = TEE_USAGE_DECRYPT;
		} else {
			return TEE_ERROR_NOT_SUPPORTED;
		}
		break;

	case TEE_ALG_RSA_NOPAD:
		if (mode == TEE_MODE_ENCRYPT) {
			req_key_usage = TEE_USAGE_ENCRYPT | TEE_USAGE_VERIFY;
		} else if (mode == TEE_MODE_DECRYPT) {
			with_private_key = true;
			req_key_usage = TEE_USAGE_DECRYPT | TEE_USAGE_SIGN;
		} else {
			return TEE_ERROR_NOT_SUPPORTED;
		}
		break;

	case TEE_ALG_DH_DERIVE_SHARED_SECRET:
	case TEE_ALG_ECDH_P192:
	case TEE_ALG_ECDH_P224:
	case TEE_ALG_ECDH_P256:
	case TEE_ALG_ECDH_P384:
	case TEE_ALG_ECDH_P521:
	case TEE_ALG_HKDF_MD5_DERIVE_KEY:
	case TEE_ALG_HKDF_SHA1_DERIVE_KEY:
	case TEE_ALG_HKDF_SHA224_DERIVE_KEY:
	case TEE_ALG_HKDF_SHA256_DERIVE_KEY:
	case TEE_ALG_HKDF_SHA384_DERIVE_KEY:
	case TEE_ALG_HKDF_SHA512_DERIVE_KEY:
	case TEE_ALG_CONCAT_KDF_SHA1_DERIVE_KEY:
	case TEE_ALG_CONCAT_KDF_SHA224_DERIVE_KEY:
	case TEE_ALG_CONCAT_KDF_SHA256_DERIVE_KEY:
	case TEE_ALG_CONCAT_KDF_SHA384_DERIVE_KEY:
	case TEE_ALG_CONCAT_KDF_SHA512_DERIVE_KEY:
	case TEE_ALG_PBKDF2_HMAC_SHA1_DERIVE_KEY:
		if (mode != TEE_MODE_DERIVE)
			return TEE_ERROR_NOT_SUPPORTED;
		with_private_key = true;
		req_key_usage = TEE_USAGE_DERIVE;
		break;

	case TEE_ALG_MD5:
	case TEE_ALG_SHA1:
	case TEE_ALG_SHA224:
	case TEE_ALG_SHA256:
	case TEE_ALG_SHA384:
	case TEE_ALG_SHA512:
		if (mode != TEE_MODE_DIGEST)
			return TEE_ERROR_NOT_SUPPORTED;
		/* v1.1: flags always set for digest operations */
		handle_state |= TEE_HANDLE_FLAG_KEY_SET;
		req_key_usage = 0;
		break;

	case TEE_ALG_DES_CBC_MAC_NOPAD:
	case TEE_ALG_AES_CBC_MAC_NOPAD:
	case TEE_ALG_AES_CBC_MAC_PKCS5:
	case TEE_ALG_AES_CMAC:
	case TEE_ALG_DES_CBC_MAC_PKCS5:
	case TEE_ALG_DES3_CBC_MAC_NOPAD:
	case TEE_ALG_DES3_CBC_MAC_PKCS5:
	case TEE_ALG_HMAC_MD5:
	case TEE_ALG_HMAC_SHA1:
	case TEE_ALG_HMAC_SHA224:
	case TEE_ALG_HMAC_SHA256:
	case TEE_ALG_HMAC_SHA384:
	case TEE_ALG_HMAC_SHA512:
		if (mode != TEE_MODE_MAC)
			return TEE_ERROR_NOT_SUPPORTED;
		req_key_usage = TEE_USAGE_MAC;
		break;

	default:
		return TEE_ERROR_NOT_SUPPORTED;
	}

	op = TEE_Malloc(sizeof(*op), TEE_MALLOC_FILL_ZERO);
	if (!op)
		return TEE_ERROR_OUT_OF_MEMORY;

	op->info.algorithm = algorithm;
	op->info.operationClass = TEE_ALG_GET_CLASS(algorithm);
	op->info.mode = mode;
	op->info.maxKeySize = maxKeySize;
	op->info.requiredKeyUsage = req_key_usage;
	op->info.handleState = handle_state;

	if (block_size > 1) {
		size_t buffer_size = block_size;

		if (buffer_two_blocks)
			buffer_size *= 2;

		op->buffer = TEE_Malloc(buffer_size,
					TEE_USER_MEM_HINT_NO_FILL_ZERO);
		if (op->buffer == NULL) {
			res = TEE_ERROR_OUT_OF_MEMORY;
			goto out;
		}
	}
	op->block_size = block_size;
	op->buffer_two_blocks = buffer_two_blocks;

	if (TEE_ALG_GET_CLASS(algorithm) != TEE_OPERATION_DIGEST) {
		uint32_t mks = maxKeySize;
		TEE_ObjectType key_type = TEE_ALG_GET_KEY_TYPE(algorithm,
						       with_private_key);

		/*
		 * If two keys are expected the max key size is the sum of
		 * the size of both keys.
		 */
		if (op->info.handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS)
			mks /= 2;

		res = TEE_AllocateTransientObject(key_type, mks, &op->key1);
		if (res != TEE_SUCCESS)
			goto out;

		if (op->info.handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) {
			res = TEE_AllocateTransientObject(key_type, mks,
							  &op->key2);
			if (res != TEE_SUCCESS)
				goto out;
		}
	}

	res = utee_cryp_state_alloc(algorithm, mode, (unsigned long)op->key1,
				    (unsigned long)op->key2, &op->state);
	if (res != TEE_SUCCESS)
		goto out;

	/*
	 * Initialize digest operations
	 * Other multi-stage operations initialized w/ TEE_xxxInit functions
	 * Non-applicable on asymmetric operations
	 */
	if (TEE_ALG_GET_CLASS(algorithm) == TEE_OPERATION_DIGEST) {
		res = utee_hash_init(op->state, NULL, 0);
		if (res != TEE_SUCCESS)
			goto out;
		/* v1.1: flags always set for digest operations */
		op->info.handleState |= TEE_HANDLE_FLAG_INITIALIZED;
	}

	op->operationState = TEE_OPERATION_STATE_INITIAL;

	*operation = op;

out:
	if (res != TEE_SUCCESS) {
		if (res != TEE_ERROR_OUT_OF_MEMORY &&
		    res != TEE_ERROR_NOT_SUPPORTED)
			TEE_Panic(0);
		if (op) {
			if (op->state) {
				TEE_FreeOperation(op);
			} else {
				TEE_Free(op->buffer);
				TEE_FreeTransientObject(op->key1);
				TEE_FreeTransientObject(op->key2);
				TEE_Free(op);
			}
		}
	}

	return res;
}
Esempio n. 10
0
static TEE_Result ta_stroage_benchmark_chunk_access_test(uint32_t nCommandID,
		uint32_t param_types, TEE_Param params[4])
{
	TEE_Result res;
	size_t data_size;
	size_t chunk_size;
	TEE_ObjectHandle object = TEE_HANDLE_NULL;
	uint8_t *chunk_buf;
	uint32_t *spent_time_in_ms = &params[2].value.a;
	bool do_verify;

	ASSERT_PARAM_TYPE(param_types, TEE_PARAM_TYPES(
					TEE_PARAM_TYPE_VALUE_INPUT,
					TEE_PARAM_TYPE_VALUE_INPUT,
					TEE_PARAM_TYPE_VALUE_OUTPUT,
					TEE_PARAM_TYPE_NONE));

	data_size = params[0].value.a;
	chunk_size = params[0].value.b;
	do_verify = params[1].value.a;

	if (data_size == 0)
		data_size = DEFAULT_DATA_SIZE;

	if (chunk_size == 0)
		chunk_size = DEFAULT_CHUNK_SIZE;

	IMSG("command id: %u, test data size: %zd, chunk size: %zd\n",
			nCommandID, data_size, chunk_size);

	chunk_buf = TEE_Malloc(chunk_size, TEE_MALLOC_FILL_ZERO);
	if (!chunk_buf) {
		EMSG("Failed to allocate memory");
		res = TEE_ERROR_OUT_OF_MEMORY;
		goto exit;
	}

	fill_buffer(chunk_buf, chunk_size);
	res = prepare_test_file(data_size, chunk_buf, chunk_size);
	if (res != TEE_SUCCESS) {
		EMSG("Failed to create test file, res=0x%08x",
				res);
		goto exit_free_chunk_buf;
	}

	res = TEE_OpenPersistentObject(TEE_STORAGE_PRIVATE,
			filename, sizeof(filename),
			TEE_DATA_FLAG_ACCESS_READ |
			TEE_DATA_FLAG_ACCESS_WRITE |
			TEE_DATA_FLAG_ACCESS_WRITE_META |
			TEE_DATA_FLAG_OVERWRITE,
			&object);
	if (res != TEE_SUCCESS) {
		EMSG("Failed to open persistent object, res=0x%08x",
				res);
		goto exit_remove_object;
	}

	switch (nCommandID) {
	case TA_STORAGE_BENCHMARK_CMD_TEST_READ:
		res = test_read(object, data_size, chunk_buf,
				chunk_size, spent_time_in_ms);
		break;

	case TA_STORAGE_BENCHMARK_CMD_TEST_WRITE:
		res = test_write(object, data_size, chunk_buf,
				chunk_size, spent_time_in_ms);
		break;

	case TA_STORAGE_BENCHMARK_CMD_TEST_REWRITE:
		res = test_rewrite(object, data_size, chunk_buf,
				chunk_size, spent_time_in_ms);
		break;

	default:
		res = TEE_ERROR_BAD_PARAMETERS;
	}

	if (res != TEE_SUCCESS)
		goto exit_remove_object;

	if (do_verify)
		res = verify_file_data(object, data_size,
				chunk_buf, chunk_size);


exit_remove_object:
	TEE_CloseAndDeletePersistentObject1(object);
exit_free_chunk_buf:
	TEE_Free(chunk_buf);
exit:

	return res;
}
Esempio n. 11
0
/**
 * @brief 
 */
void test_storage_api()
{
    uint32_t storageID=TEE_OBJECT_STORAGE_PRIVATE,
             r_flags=TEE_DATA_FLAG_ACCESS_READ,
             w_flags=TEE_DATA_FLAG_ACCESS_WRITE,
             rw_flags=(TEE_DATA_FLAG_ACCESS_READ | TEE_DATA_FLAG_ACCESS_WRITE),
             a_attribute_val=0x00000005,b_attribute_val=0x00000007,
			 pop_ret_val,attribute_cnt=0x00000003,seek_ret_val,open_seek_retval,
			 crt_ret_val,write_ret_val,open_write_retval,read_ret_val,
			 open_read_retval,open_ret_val,open_delete_retval,allocate1_ret_val,
			 allocate2_ret_val,rd_trunc_cnt=0x00000000,open_truncate_retval,
			 trunc_size=0x0000000A,truncate_ret_val,rdtest_truncated_retval,
			 optest_truncated_retval,rdtest_written_retval,
			 optest_written_retval,rd_write_cnt=0x00000000,read_cnt=0x00000000,
			 trunc_cnt=0x00000000,open_rename_retval,de_a,
			 rd_rename_cnt=0x00000000,optest_renamed_retval,rename_ret_val,
			 rdtest_renamed_retval,optest_deleted_retval;

    typedef signed int int32_t;
    int32_t offset=0x00000003;
    size_t objectIDLen=0x00000040,read_size=0x0000000F,rd_trunc_size=0x0000000A,
	   	   rd_write_size=0x0000002C,rd_rename_size=0x0000000C;
    void* open_objectID="/test.dir/test.txt";
	void* rename_objectID="/test.dir/new.txt";
    void* initialData="This a sierraware created sample initial data\n";
    void* create_objectID="/test.dir/crt.txt";
    void* read_objectID="/test.dir/read.txt";
    void* write_objectID="/test.dir/write.txt";
    void* seek_objectID="/test.dir/seek.txt";
    void* delete_objectID="/test.dir/delete.txt";
	void* trunc_objectID="/test.dir/truncate.txt";
    char  wrie_buffer[255]={"This a sierraware created sample test string\n"};
    char  read_buffer[255],rd_trunc_buffer[255],rd_write_buffer[255],
		  rd_rename_buffer[255];
    void* attrsbuffer="This will get populated sometimes in the test fn\n";
    void* p_buffer="And finally we tested GP_INTERNAL_STORAGE APP\n";

    TEE_ObjectHandle crtattributes;
    TEE_ObjectHandle *first_object;
    TEE_ObjectHandle *second_object;

    TEE_Whence whence;
    whence=0x00000000;
	
	sw_printf("-----------Allocating Memory For Create Object--------------\n");
    first_object=(TEE_ObjectHandle*)TEE_Malloc(sizeof(TEE_ObjectHandle),0);
    sw_printf("-------Allocating Memory For Create Object members----------\n");
    allocate1_ret_val=TEE_AllocateTransientObject(TEE_TYPE_AES,0x00000800,
													 first_object);
    sw_printf("the allocate transient function returns value is %x \n", 
			   allocate1_ret_val);

    crt_ret_val=TEE_CreatePersistentObject(storageID,create_objectID,
			objectIDLen,w_flags,crtattributes,initialData,
			(size_t)(sw_strlen((char*)initialData)),first_object);

    sw_printf("The create Persistent object funtion \
returns value is  %x \n \n",crt_ret_val);

    sw_printf("------------Allocating Memory For open Object---------------\n");
    second_object=(TEE_ObjectHandle*)TEE_Malloc(sizeof(TEE_ObjectHandle),0);
	sw_printf("------------Allocating Memory For open Object members-------\n");
    allocate2_ret_val=TEE_AllocateTransientObject(TEE_TYPE_RSA_KEYPAIR,
													 0x00000800,second_object);
    sw_printf("the allocate transient function returns value is %x \n",
			   allocate2_ret_val);

    open_ret_val=TEE_OpenPersistentObject(storageID,open_objectID,objectIDLen,
                                            r_flags,second_object);
    sw_printf("The open Persistent object funtion returns value is %x \n \n",
			   open_ret_val);

    sw_printf("*****Reset the open object***** \n");
    TEE_ResetTransientObject(*second_object);

	open_read_retval=TEE_OpenPersistentObject(storageID,read_objectID,
									objectIDLen,r_flags,second_object);

    sw_printf("The open Persistent object funtion \
returns value is %x \n \n",open_read_retval);

    read_ret_val=TEE_ReadObjectData(*second_object,(void*)&read_buffer,
							read_size,&read_cnt);

    sw_printf("The Read Persistent funtion returns value is %x \n \n",
			   read_ret_val);

    sw_printf("*****Reset the read object***** \n");
    TEE_ResetTransientObject(*second_object);
	
	open_write_retval=TEE_OpenPersistentObject(storageID,write_objectID,
									  objectIDLen,w_flags,second_object);
    sw_printf("The open Persistent object funtion \
returns value is %x \n \n",open_write_retval);

    write_ret_val=TEE_WriteObjectData(*second_object,(void*)&wrie_buffer,
                         (size_t)(sw_strlen((char*)&wrie_buffer)));
    sw_printf("The write Persistent funtion returns value is %x \n \n",
			   write_ret_val);

    sw_printf("*****Reset the write object***** \n");
    TEE_ResetTransientObject(*second_object);

	optest_written_retval=TEE_OpenPersistentObject(storageID,write_objectID,
										objectIDLen,r_flags,second_object);

    sw_printf("The open Persistent object funtion \
returns value is %x \n \n",optest_written_retval);

    rdtest_written_retval=TEE_ReadObjectData(*second_object,
						  (void*)&rd_write_buffer,rd_write_size,
						  &rd_write_cnt);

    sw_printf("The Read Persistent funtion returns value is %x \n \n",
			   rdtest_written_retval);

	sw_printf("******TESTING:write persistent object*******\n");
    if(rdtest_written_retval==1) {
        sw_printf("SUCCESS \n");
    }
    else {
        sw_printf("FAILURE \n");
    }

    sw_printf("*****Reset the read object***** \n");
    TEE_ResetTransientObject(*second_object);

	open_truncate_retval=TEE_OpenPersistentObject(storageID,trunc_objectID,
							objectIDLen,w_flags,second_object);

    sw_printf("The open Persistent object funtion \
returns value is %x \n \n",open_truncate_retval);

	truncate_ret_val=TEE_TruncateObjectData(*second_object,trunc_size);
	sw_printf("The truncate Persistent funtion returns value is %x \n \n",
			   truncate_ret_val);

	sw_printf("*****Reset the truncate object***** \n");
    TEE_ResetTransientObject(*second_object);
	
	optest_truncated_retval=TEE_OpenPersistentObject(storageID,trunc_objectID,
								objectIDLen,r_flags,second_object);

    sw_printf("The open Persistent object funtion \
returns value is %x \n \n",optest_truncated_retval);

    rdtest_truncated_retval=TEE_ReadObjectData(*second_object,
							(void*)&rd_trunc_buffer,rd_trunc_size,
							&rd_trunc_cnt);

    sw_printf("The Read Persistent funtion returns value is %x \n \n",
			   rdtest_truncated_retval);

	sw_printf("******TESTING:truncate persistent object*******\n");
    if(rdtest_truncated_retval==1) {
        sw_printf("SUCCESS \n");
    }
    else {
        sw_printf("FAILS \n");
    }

    sw_printf("*****Reset the read object***** \n");
    TEE_ResetTransientObject(*second_object);

	open_rename_retval=TEE_OpenPersistentObject(storageID,open_objectID,
										objectIDLen,rw_flags,second_object);

    sw_printf("The open Persistent object funtion \
returns value is %x \n \n",open_rename_retval);

	rename_ret_val=TEE_RenamePersistentObject(*second_object,rename_objectID,
												objectIDLen);
    sw_printf("The rename Persistent funtion returns value is %x \n \n",
			   rename_ret_val);

    sw_printf("*****Reset the rename object***** \n");
    TEE_ResetTransientObject(*second_object);

	optest_renamed_retval=TEE_OpenPersistentObject(storageID,rename_objectID,
								objectIDLen,r_flags,second_object);

    sw_printf("The open Persistent object funtion \
returns value is %x \n \n",optest_renamed_retval);

    rdtest_renamed_retval=TEE_ReadObjectData(*second_object,
						   (void*)&rd_rename_buffer,rd_rename_size,
						   &rd_rename_cnt);

    sw_printf("The Read Persistent funtion returns value is %x \n \n",
			   rdtest_renamed_retval);

	sw_printf("******TESTING:rename persistent object*******\n");
    if(rdtest_renamed_retval==1) {
        sw_printf("SUCCESS \n");
    }
    else {
        sw_printf("FAILS \n");
    }

    sw_printf("*****Reset the read object***** \n");
    TEE_ResetTransientObject(*second_object);

    open_seek_retval=TEE_OpenPersistentObject(storageID,seek_objectID,
								   objectIDLen,rw_flags,second_object);

    sw_printf("The open Persistent object funtion \
returns value is %x \n \n",open_seek_retval);

    seek_ret_val=TEE_SeekObjectData(*second_object,offset,whence);
    sw_printf("The seek Persistent funtion returns value is %x \n \n",
			   						seek_ret_val);

    sw_printf("*****Reset the seek object***** \n");
    TEE_ResetTransientObject(*second_object);

    open_delete_retval=TEE_OpenPersistentObject(storageID,delete_objectID,
					   			   objectIDLen,r_flags,second_object);

    sw_printf("The open Persistent object funtion returns value is %x \n",
			   					open_delete_retval);

    TEE_CloseAndDeletePersistentObject(*second_object);
	
	sw_printf("*****Reset the close object***** \n");
    TEE_ResetTransientObject(*second_object);

	optest_deleted_retval=TEE_OpenPersistentObject(storageID,delete_objectID,
									objectIDLen,r_flags,second_object);

    sw_printf("The open Persistent object funtion \
returns value is %x \n \n",optest_deleted_retval);

	sw_printf("******TESTING:close and delete persistent object*******\n");
	if(optest_deleted_retval!=1) {
		sw_printf("SUCCESS \n");
	}
	else {
		sw_printf("FAILS\n");
	}
	
	sw_printf("*****Reset the seek object***** \n");
    TEE_ResetTransientObject(*second_object);

    TEE_Attribute* attref;
    attref=(TEE_Attribute*)TEE_Malloc(sizeof(TEE_Attribute),0);
    TEE_InitRefAttribute(attref,0x00000001,p_buffer,
						(size_t)(sw_strlen((char*)p_buffer)));
    TEE_Free((void*)attref);

	TEE_Attribute* attval;
    attval=(TEE_Attribute*)TEE_Malloc(sizeof(TEE_Attribute),0);
    TEE_InitValueAttribute(attval,0x20000000,a_attribute_val,b_attribute_val);
    TEE_Free((void*)attval);

    TEE_Attribute attributes[3];
	attributes[0].attributeID=0x20000000;
    attributes[0].content.value.a=0x0000000A;
    attributes[0].content.value.b=0x0000000B;

	attributes[1].attributeID=0x00000275;
	attributes[1].content.ref.length=(size_t)(sw_strlen((char*)attrsbuffer));
    attributes[1].content.ref.buffer=TEE_Malloc
		(attributes[1].content.ref.length,0);
    TEE_MemCpy(attributes[1].content.ref.buffer,attrsbuffer,
		(u32)(attributes[1].content.ref.length));

	attributes[2].attributeID=0x23425676;
    attributes[2].content.value.a=0x0000001E;
    attributes[2].content.value.b=0x0000001F;

    pop_ret_val=TEE_PopulateTransientObject(*second_object,attributes,
											attribute_cnt);

	sw_printf("the populate transient function returns value is %x \n",
			   pop_ret_val);
	
	sw_printf("*****Reset the populate object***** \n");
    TEE_ResetTransientObject(*second_object);

    TEE_CopyObjectAttributes(*second_object,*first_object);

	sw_printf("*****free the create object by call TEE_FreeTransientObject \
fn***** \n");
    TEE_FreeTransientObject(*first_object);

    sw_printf("*****free the common object by call TEE_FreeTransientObject \
fn***** \n");
    TEE_FreeTransientObject(*second_object);
    sw_printf("--------------Program Successfully Terminated--------------\n");	
}
Esempio n. 12
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;
}
Esempio n. 13
0
TEE_Result TA_EXPORT TA_InvokeCommandEntryPoint(void *sessionContext, uint32_t commandID,
						uint32_t paramTypes, TEE_Param params[4])
{
	sessionContext = sessionContext;
	paramTypes = paramTypes;

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

	if (commandID == TEST_PERSISTENT) {
		int count = params[0].value.a;
		while (count--)
			ta_storage_test(params[0].value.b);

	} else if (commandID == TEST_MSG) {
		int count2 = params[0].value.a;
		while (count2--) {
			int count = params[0].value.b;
			while (count--)	{
				TEE_Result retVal = TEE_SUCCESS;
				struct com_mgr_invoke_cmd_payload payload, returnPayload;

				payload.size = count;
				payload.data = TEE_Malloc(payload.size, 0);
				TEE_MemFill(payload.data, 0x77, payload.size);

				if (payload.data) {

					retVal = TEE_InvokeMGRCommand(TEE_TIMEOUT_INFINITE,
												  COM_MGR_CMD_ID_TEST_COMM,
												  &payload, &returnPayload);

					if ((retVal == TEE_SUCCESS) &&
					    (returnPayload.size-sizeof(struct com_mgr_invoke_cmd_payload)) == payload.size) {
						bool check = true;
						unsigned int n;
						for (n = 0; n < payload.size && check; n++)	{
							char *s = payload.data;
							char *r = returnPayload.data;
							check = s[n] == r[payload.size-1-n];
						}


						TEE_Free(returnPayload.data);
						if (!check)
							return TEE_ERROR_COMMUNICATION;
					} else if (retVal == TEE_SUCCESS &&
							   returnPayload.size == 0 &&
							   returnPayload.size == payload.size) {
						/* this is ok */
					} else {
						return TEE_ERROR_COMMUNICATION;
					}


					TEE_Free(payload.data);
				}
			}
		}
	} else {
		OT_LOG(LOG_ERR, "Unknow command ID");
	}

	return TEE_SUCCESS;
}
Esempio n. 14
0
int main(int argc, char **argv)
{

	TEE_Result res;
	uint32_t crypt_mode;				// TEE_MODE_ENCRYPT or TEE_MODE_DECRYPT
	unsigned char mess[] =  			\
	"\x01\x23\x45\x67\x89\xAB\xCD\xEF"	\
	"\xFE\xDC\xBA\x98\x76\x54\x32\x10"	\
	"2222222222222222"\
	"5555555555555555"\
	"3333333333333333"\
	"0000000000000000"\
	"7777777777777777"\
	"4444444444444444"\
	"8888888888888888"\
	"6666666666666666"\
	"1111111111111111"\
	"9999999999999999";   
	
	size_t mess_len = 96;				// multiples of Aes algorithm key block_size (block_size of AES is 16 Bytes)

	unsigned char key[] = "\x01\x23\x45\x67\x89\xAB\xCD\xEF\xFE\xDC\xBA\x98\x76\x54\x32\x10"\
						  "\x01\x23\x45\x67\x89\xAB\xCD\xEF\xFE\xDC\xBA\x98\x76\x54\x32\x10"; 
	size_t key_len  = 16;				// 128bits = 16Bytes,  192bits = 24Bytes,  256bits = 32Bytes

	unsigned char IV[] = "\x01\x23\x45\x67\x89\xAB\xCD\xEF\xFE\xDC\xBA\x98\x76\x54\x32\x10"\
						 "\x01\x23\x45\x67\x89\xAB\xCD\xEF\xFE\xDC\xBA\x98\x76\x54\x32\x10"; 
	size_t IV_len = key_len;



	/* [0x01] Init crypt context */
	if(TEE_InitCryptContext() != TEE_SUCCESS) {
		TEE_Printf("[err] TEE_InitCryptContext\n");
		return 0;
	}



	TEE_Printf("\n============================TEE_MODE_ENCRYPT============================\n");
	/* [0x02] Encrypt: aes-128-cbc */
	size_t cipher_len = mess_len;
	void *cipher = TEE_Malloc(cipher_len, 0);
	if(!cipher) {		
		TEE_Printf("[err] TEE_Malloc\n");
		return 0;
	}
	crypt_mode = TEE_MODE_ENCRYPT;
	res  = crypt_cipher_aes_cbc((const void *)mess, mess_len, 
								(const void *)key, key_len, 
								cipher, &cipher_len,
								IV, IV_len,
								crypt_mode);					
	if(res != TEE_SUCCESS) {
		TEE_Printf("[err] crypt_cipher_aes_cbc::TEE_MODE_ENCRYPT\n");
		return 0;
	}	
	if( cipher_len > 0) {
		TEE_Hexdump("crypt_cipher_aes_cbc::plain", mess, mess_len, 16, true);
		TEE_Hexdump("crypt_cipher_aes_cbc::key", key, key_len, 16, true);
		TEE_Hexdump("crypt_cipher_aes_cbc::IV", IV, IV_len, 16, true);
		TEE_Hexdump("crypt_cipher_aes_cbc::cipher", cipher, cipher_len, 16, true);
	}



	TEE_Printf("\n============================TEE_MODE_DECRYPT============================\n");
	/* [0x03] Decrypt : aes-128-cbc  */
	size_t plain_len = cipher_len;
	void *plain      = TEE_Malloc(plain_len, 0);
	if(!plain) {		
		TEE_Printf("[err] TEE_Malloc\n");
		return 0;
	}
	crypt_mode = TEE_MODE_DECRYPT;
	res  = crypt_cipher_aes_cbc((const void *)cipher, cipher_len, 
								(const void *)key, key_len, 
								plain, &plain_len,
								IV, IV_len,
								crypt_mode);					
	if(res != TEE_SUCCESS) {
		TEE_Printf("[err] crypt_cipher_aes_cbc::TEE_MODE_DECRYPT\n");
		return 0;
	}	
	if( plain_len > 0) {
		TEE_Hexdump("crypt_cipher_aes_cbc::cipher", cipher, cipher_len, 16, true);
		TEE_Hexdump("crypt_cipher_aes_cbc::key", key, key_len, 16, true);
		TEE_Hexdump("crypt_cipher_aes_cbc::IV", IV, IV_len, 16, true);
		TEE_Hexdump("crypt_cipher_aes_cbc::plain", plain, plain_len, 16, true);
	}



	/* [0x04] Cleanup crypt context */
	if(TEE_FiniCryptContext() != TEE_SUCCESS) {
		TEE_Printf("[err] TEE_FiniCryptContext\n");
	}


	exit(0);

    return 0;
}
Esempio n. 15
0
TEE_Result TEE_AllocateOperation(TEE_OperationHandle *operation,
				 uint32_t algorithm, uint32_t mode,
				 uint32_t maxKeySize)
{
	TEE_Result res;
	TEE_OperationHandle op = TEE_HANDLE_NULL;
	uint32_t handle_state = 0;
	size_t block_size = 1;
	uint32_t req_key_usage;
	bool with_private_key = false;
	bool buffer_two_blocks = false;

	if (operation == NULL)
		TEE_Panic(0);

	if (algorithm == TEE_ALG_AES_XTS)
		handle_state = TEE_HANDLE_FLAG_EXPECT_TWO_KEYS;

	switch (algorithm) {
	case TEE_ALG_AES_CTS:
	case TEE_ALG_AES_XTS:
		buffer_two_blocks = true;
	 /*FALLTHROUGH*/ case TEE_ALG_AES_ECB_NOPAD:
	case TEE_ALG_AES_CBC_NOPAD:
	case TEE_ALG_AES_CTR:
	case TEE_ALG_AES_CCM:
	case TEE_ALG_AES_GCM:
	case TEE_ALG_DES_ECB_NOPAD:
	case TEE_ALG_DES_CBC_NOPAD:
	case TEE_ALG_DES3_ECB_NOPAD:
	case TEE_ALG_DES3_CBC_NOPAD:
		if (TEE_ALG_GET_MAIN_ALG(algorithm) == TEE_MAIN_ALGO_AES)
			block_size = TEE_AES_BLOCK_SIZE;
		else
			block_size = TEE_DES_BLOCK_SIZE;

		if (mode == TEE_MODE_ENCRYPT)
			req_key_usage = TEE_USAGE_ENCRYPT;
		else if (mode == TEE_MODE_DECRYPT)
			req_key_usage = TEE_USAGE_DECRYPT;
		else
			return TEE_ERROR_NOT_SUPPORTED;
		break;

	case TEE_ALG_RSASSA_PKCS1_V1_5_MD5:
	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1:
	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224:
	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256:
	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384:
	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512:
	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1:
	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224:
	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256:
	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384:
	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512:
	case TEE_ALG_DSA_SHA1:
		if (mode == TEE_MODE_SIGN) {
			with_private_key = true;
			req_key_usage = TEE_USAGE_SIGN;
		} else if (mode == TEE_MODE_VERIFY) {
			req_key_usage = TEE_USAGE_VERIFY;
		} else {
			return TEE_ERROR_NOT_SUPPORTED;
		}
		break;

	case TEE_ALG_RSAES_PKCS1_V1_5:
	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1:
	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA224:
	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA256:
	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA384:
	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA512:
		if (mode == TEE_MODE_ENCRYPT) {
			req_key_usage = TEE_USAGE_ENCRYPT;
		} else if (mode == TEE_MODE_DECRYPT) {
			with_private_key = true;
			req_key_usage = TEE_USAGE_DECRYPT;
		} else {
			return TEE_ERROR_NOT_SUPPORTED;
		}
		break;

	case TEE_ALG_RSA_NOPAD:
		if (mode == TEE_MODE_ENCRYPT) {
			req_key_usage = TEE_USAGE_ENCRYPT | TEE_USAGE_VERIFY;
		} else if (mode == TEE_MODE_DECRYPT) {
			with_private_key = true;
			req_key_usage = TEE_USAGE_DECRYPT | TEE_USAGE_SIGN;
		} else {
			return TEE_ERROR_NOT_SUPPORTED;
		}
		break;

	case TEE_ALG_DH_DERIVE_SHARED_SECRET:
		if (mode != TEE_MODE_DERIVE)
			return TEE_ERROR_NOT_SUPPORTED;
		with_private_key = true;
		req_key_usage = TEE_USAGE_DERIVE;
		break;

	case TEE_ALG_MD5:
	case TEE_ALG_SHA1:
	case TEE_ALG_SHA224:
	case TEE_ALG_SHA256:
	case TEE_ALG_SHA384:
	case TEE_ALG_SHA512:
		if (mode != TEE_MODE_DIGEST)
			return TEE_ERROR_NOT_SUPPORTED;
		handle_state |= TEE_HANDLE_FLAG_KEY_SET;
		req_key_usage = 0;
		break;

	case TEE_ALG_DES_CBC_MAC_NOPAD:
	case TEE_ALG_AES_CBC_MAC_NOPAD:
	case TEE_ALG_AES_CBC_MAC_PKCS5:
	case TEE_ALG_AES_CMAC:
	case TEE_ALG_DES_CBC_MAC_PKCS5:
	case TEE_ALG_DES3_CBC_MAC_NOPAD:
	case TEE_ALG_DES3_CBC_MAC_PKCS5:
	case TEE_ALG_HMAC_MD5:
	case TEE_ALG_HMAC_SHA1:
	case TEE_ALG_HMAC_SHA224:
	case TEE_ALG_HMAC_SHA256:
	case TEE_ALG_HMAC_SHA384:
	case TEE_ALG_HMAC_SHA512:
		if (mode != TEE_MODE_MAC)
			return TEE_ERROR_NOT_SUPPORTED;
		req_key_usage = TEE_USAGE_MAC;
		break;

	default:
		return TEE_ERROR_NOT_SUPPORTED;
	}

	op = TEE_Malloc(sizeof(*op), 0);
	if (op == NULL)
		return TEE_ERROR_OUT_OF_MEMORY;

	op->info.algorithm = algorithm;
	op->info.operationClass = TEE_ALG_GET_CLASS(algorithm);
	op->info.mode = mode;
	op->info.maxKeySize = maxKeySize;
	op->info.requiredKeyUsage = req_key_usage;
	op->info.handleState = handle_state;

	if (block_size > 1) {
		size_t buffer_size = block_size;

		if (buffer_two_blocks)
			buffer_size *= 2;

		op->buffer =
		    TEE_Malloc(buffer_size, TEE_USER_MEM_HINT_NO_FILL_ZERO);
		if (op->buffer == NULL) {
			res = TEE_ERROR_OUT_OF_MEMORY;
			goto out;
		}
	}
	op->block_size = block_size;
	op->buffer_two_blocks = buffer_two_blocks;

	if (TEE_ALG_GET_CLASS(algorithm) != TEE_OPERATION_DIGEST) {
		uint32_t mks = maxKeySize;
		TEE_ObjectType key_type = TEE_ALG_GET_KEY_TYPE(algorithm,
						       with_private_key);

		/*
		 * If two keys are expected the max key size is the sum of
		 * the size of both keys.
		 */
		if (op->info.handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS)
			mks /= 2;

		res = TEE_AllocateTransientObject(key_type, mks, &op->key1);
		if (res != TEE_SUCCESS)
			goto out;

		if ((op->info.handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) !=
		    0) {
			res =
			    TEE_AllocateTransientObject(key_type, mks,
							&op->key2);
			if (res != TEE_SUCCESS)
				goto out;
		}
	}

	res = utee_cryp_state_alloc(algorithm, mode, (uint32_t) op->key1,
				    (uint32_t) op->key2, &op->state);
	if (res != TEE_SUCCESS)
		goto out;

	/* For multi-stage operation do an "init". */
	TEE_ResetOperation(op);
	*operation = op;

out:
	if (res != TEE_SUCCESS) {
		TEE_FreeTransientObject(op->key1);
		TEE_FreeTransientObject(op->key2);
		TEE_FreeOperation(op);
	}

	return res;
}