Example #1
0
static TEE_Result read_rb_idx(uint32_t pt, TEE_Param params[TEE_NUM_PARAMS])
{
	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
						TEE_PARAM_TYPE_VALUE_OUTPUT,
						TEE_PARAM_TYPE_NONE,
						TEE_PARAM_TYPE_NONE);
	size_t slot_offset;
	uint64_t idx;
	uint32_t count;
	TEE_Result res;
	TEE_ObjectHandle h;

	if (pt != exp_pt)
		return TEE_ERROR_BAD_PARAMETERS;

	res = get_slot_offset(params[0].value.a, &slot_offset);
	if (res)
		return res;

	res = open_rb_state(DEFAULT_LOCK_STATE, &h);
	if (res)
		return res;

	res = TEE_SeekObjectData(h, slot_offset, TEE_DATA_SEEK_SET);
	if (res)
		goto out;

	res =  TEE_ReadObjectData(h, &idx, sizeof(idx), &count);
	if (res)
		goto out;
	if (count != sizeof(idx)) {
		idx = 0; /* Not yet written slots are reported as 0 */

		if (count) {
			/*
			 * Somehow the file didn't even hold a complete
			 * slot index entry.  Write it as 0.
			 */
			res = TEE_SeekObjectData(h, slot_offset,
						 TEE_DATA_SEEK_SET);
			if (res)
				goto out;
			res = TEE_WriteObjectData(h, &idx, sizeof(idx));
			if (res)
				goto out;
		}
	}

	params[1].value.a = idx >> 32;
	params[1].value.b = idx;
out:
	TEE_CloseObject(h);
	return res;
}
Example #2
0
static TEE_Result write_rb_idx(uint32_t pt, TEE_Param params[TEE_NUM_PARAMS])
{
	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
						TEE_PARAM_TYPE_VALUE_INPUT,
						TEE_PARAM_TYPE_NONE,
						TEE_PARAM_TYPE_NONE);
	size_t slot_offset;
	uint64_t widx;
	uint64_t idx;
	uint32_t count;
	TEE_Result res;
	TEE_ObjectHandle h;

	if (pt != exp_pt)
		return TEE_ERROR_BAD_PARAMETERS;

	res = get_slot_offset(params[0].value.a, &slot_offset);
	if (res)
		return res;
	widx = ((uint64_t)params[1].value.a << 32) | params[1].value.b;

	res = open_rb_state(DEFAULT_LOCK_STATE, &h);
	if (res)
		return res;

	res = TEE_SeekObjectData(h, slot_offset, TEE_DATA_SEEK_SET);
	if (res)
		goto out;

	res =  TEE_ReadObjectData(h, &idx, sizeof(idx), &count);
	if (res)
		goto out;
	if (count != sizeof(idx))
		idx = 0; /* Not yet written slots are reported as 0 */

	if (widx < idx) {
		res = TEE_ERROR_SECURITY;
		goto out;
	}

	res = TEE_SeekObjectData(h, slot_offset, TEE_DATA_SEEK_SET);
	if (res)
		goto out;

	res = TEE_WriteObjectData(h, &widx, sizeof(widx));
out:
	TEE_CloseObject(h);
	return res;
}
Example #3
0
static void __attribute__((unused)) pri_obj_data(TEE_ObjectHandle object)
{
	void *data = NULL;
	TEE_ObjectInfo info;
	uint32_t cur_pos;
	TEE_Result ret;
	uint32_t count = 0;

	if (object == NULL)
		return;

	TEE_GetObjectInfo(object, &info);

	data = calloc(1, info.dataSize);
	if (data == NULL) {
		printf("Fail: pri_obj_data(mem)\n");
	}

	cur_pos = info.dataPosition;

	ret = TEE_SeekObjectData(object, 0, TEE_DATA_SEEK_SET);
	if (ret != TEE_SUCCESS) {
		printf("Fail: pri_obj_data(seek beginning)\n");
		goto err;
	}

	ret = TEE_ReadObjectData(object, data, info.dataSize, &count);
	if (ret != TEE_SUCCESS || count != info.dataSize) {
		printf("Fail: pri_obj_data(read)\n");
		goto err;
	}

	ret = TEE_SeekObjectData(object, cur_pos, TEE_DATA_SEEK_SET);
	if (ret != TEE_SUCCESS) {
		printf("Fail: pri_obj_data(set back prev pos)\n");
		goto err;
	}

	pri_void_buf(data, info.dataSize);

err:
	free(data);
}
Example #4
0
static void pure_data_obj_and_truncate_and_write()
{
	printf("  ####   pure_data_obj_and_truncate_and_write   ####\n");

	TEE_Result ret;
	TEE_ObjectHandle handler;
	char objID[] = "56c5d1b260704de30fe7af67e5b9327613abebe6172a2b4e949d84b8e561e2fb";
	size_t objID_len = 64;
	uint32_t flags = 0xffffffff ^ TEE_DATA_FLAG_EXCLUSIVE;
	void * init_data;
	size_t init_data_len = 10;
	void *write_data = NULL;
	size_t write_data_size = 10;

	init_data = malloc(init_data_len);
	if (init_data == NULL)
		goto err;
	RAND_bytes(init_data, init_data_len);

	write_data = calloc(1, write_data_size);
	if (write_data == NULL)
		goto err;
	RAND_bytes(write_data, write_data_size);

	ret = TEE_CreatePersistentObject(TEE_STORAGE_PRIVATE, (void *)objID, objID_len,
					 flags, NULL, init_data, init_data_len, &handler);
	if (ret != TEE_SUCCESS) {
		printf("Fail: per creation\n");
		goto err;
	}

	TEE_TruncateObjectData(handler, 20);

	ret = TEE_SeekObjectData(handler, 5, TEE_DATA_SEEK_SET);
	if (ret != TEE_SUCCESS) {
		printf("Fail: per seek\n");
		goto err;
	}

	ret = TEE_WriteObjectData(handler, write_data, write_data_size);
	if (ret != TEE_SUCCESS) {
		printf("Fail: per write\n");
		goto err;
	}

err:
	TEE_CloseAndDeletePersistentObject(handler);
	free(init_data);
	free(write_data);
}
Example #5
0
static TEE_Result get_counter_value(uint64_t *mem_data)
{
	TEE_ObjectHandle counter;
	TEE_Result ret;
	uint64_t previous_value = 0, next_value = 0;
	uint32_t bytes_read;

	/* Open the object here if it exists */
	ret = TEE_OpenPersistentObject(TEE_STORAGE_PRIVATE, &object_id, sizeof(object_id),
				       TEE_DATA_FLAG_ACCESS_READ | TEE_DATA_FLAG_ACCESS_WRITE,
				       &counter);
	if (ret != TEE_SUCCESS) {
		OT_LOG(LOG_ERR, "TEE_OpenPersistentObject failed: 0x%x", ret);
	} else {
		OT_LOG(LOG_ERR, "TEE_OpenPersistentObject succesful");

		ret = TEE_ReadObjectData(counter, (void *)&previous_value, sizeof(uint64_t),
					 &bytes_read);
		if (ret != TEE_SUCCESS) {
			OT_LOG(LOG_ERR, "TEE_ReadObjectData failed: 0x%x", ret);
			goto end_ctr;
		}

		*mem_data = previous_value;

		/* Increment the value */
		next_value = ++previous_value;

		OT_LOG(LOG_ERR, "New counter value: %d", (int)next_value);

		/* Set data position back to the start of object */
		ret = TEE_SeekObjectData(counter, 0, TEE_DATA_SEEK_SET);
		if (ret != TEE_SUCCESS) {
			OT_LOG(LOG_ERR, "TEE_SeekObjectData failed: 0x%x", ret);
			goto end_ctr;
		}

		/* Write the new counter value back to the persistent object */
		ret = TEE_WriteObjectData(counter, (void *)&next_value, sizeof(uint64_t));
		if (ret != TEE_SUCCESS)
			OT_LOG(LOG_ERR, "TEE_WriteObjectData failed: 0x%x\n", ret);
	}

end_ctr:
	TEE_CloseObject(counter);
	return ret;
}
Example #6
0
static TEE_Result verify_file_data(TEE_ObjectHandle object, size_t data_size,
		uint8_t *chunk_buf, size_t chunk_size)
{
	TEE_Result res;
	size_t tmp_data_size = data_size;

	res = TEE_SeekObjectData(object, 0, TEE_DATA_SEEK_SET);
	if (res != TEE_SUCCESS) {
		EMSG("Failed to seek to offset 0");
		goto exit;
	}

	TEE_MemFill(chunk_buf, 0, chunk_size);

	tmp_data_size = data_size;
	while (tmp_data_size > 0) {
		uint32_t read_bytes = 0;

		res = TEE_ReadObjectData(object, chunk_buf, chunk_size,
				&read_bytes);
		if (res != TEE_SUCCESS) {
			EMSG("Failed to read data, res=0x%08x", res);
			goto exit;
		}

		if (read_bytes != chunk_size) {
			EMSG("Data size not match");
			res = TEE_ERROR_CORRUPT_OBJECT;
			goto exit;
		}

		res = verify_buffer(chunk_buf, chunk_size);
		if (res != TEE_SUCCESS) {
			EMSG("Verify data failed, res=0x%08x", res);
			goto exit;
		}

		tmp_data_size -= chunk_size;
	}

exit:
	return res;
}
Example #7
0
TEE_Result ta_storage_cmd_seek(uint32_t param_types, TEE_Param params[4])
{
	TEE_Result res;
	TEE_ObjectInfo info;
	TEE_ObjectHandle o = VAL2HANDLE(params[0].value.a);

	ASSERT_PARAM_TYPE(TEE_PARAM_TYPES
			  (TEE_PARAM_TYPE_VALUE_INPUT,
			   TEE_PARAM_TYPE_VALUE_INOUT, TEE_PARAM_TYPE_NONE,
			   TEE_PARAM_TYPE_NONE));

	res = TEE_SeekObjectData(o, params[0].value.b, params[1].value.a);
	if (res != TEE_SUCCESS)
		return res;
	res = TEE_GetObjectInfo1(o, &info);

	params[1].value.b = info.dataPosition;

	return res;
}
Example #8
0
static TEE_Result test_rewrite(TEE_ObjectHandle object, size_t data_size,
		uint8_t *chunk_buf, size_t chunk_size,
		uint32_t *spent_time_in_ms)
{
	TEE_Time start_time, stop_time;
	size_t remain_bytes = data_size;
	TEE_Result res = TEE_SUCCESS;
	uint32_t read_bytes = 0;

	TEE_GetSystemTime(&start_time);

	while (remain_bytes) {
		size_t write_size;
		int32_t negative_chunk_size;

		if (remain_bytes < chunk_size)
			write_size = remain_bytes;
		else
			write_size = chunk_size;
		negative_chunk_size = -(int32_t)write_size;

		/* Read a chunk */
		res = TEE_ReadObjectData(object, chunk_buf, write_size,
				&read_bytes);
		if (res != TEE_SUCCESS) {
			EMSG("Failed to read data, res=0x%08x", res);
			goto exit;
		}

		if (read_bytes != write_size) {
			EMSG("Partial data read, bytes=%u", read_bytes);
			res = TEE_ERROR_CORRUPT_OBJECT;
			goto exit;
		}

		/* Seek to the position before read */
		res = TEE_SeekObjectData(object, negative_chunk_size,
				TEE_DATA_SEEK_CUR);
		if (res != TEE_SUCCESS) {
			EMSG("Failed to seek to previous offset");
			goto exit;
		}

		/* Write a chunk*/
		res = TEE_WriteObjectData(object, chunk_buf, write_size);
		if (res != TEE_SUCCESS) {
			EMSG("Failed to write data, res=0x%08x", res);
			goto exit;
		}

		remain_bytes -= write_size;
	}

	TEE_GetSystemTime(&stop_time);

	*spent_time_in_ms = get_delta_time_in_ms(start_time, stop_time);

	IMSG("start: %u.%u(s), stop: %u.%u(s), delta: %u(ms)",
			start_time.seconds, start_time.millis,
			stop_time.seconds, stop_time.millis,
			*spent_time_in_ms);

exit:
	return res;
}
/**
 * @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");	
}
Example #10
0
static void data_stream_write_read()
{
	printf("  ####   data_stream_write_read   ####\n");

	TEE_Result ret;
	TEE_ObjectHandle handler;
	TEE_ObjectHandle per_han;
	size_t key_size = 512;
	char objID[] = "56c5d1b260704de30fe7af67e5b9327613abebe6172a2b4e949d84b8e561e2fb";
	size_t objID_len = 64;
	uint32_t flags = 0xffffffff ^ TEE_DATA_FLAG_EXCLUSIVE;
	void *write_data = NULL;
	void *read_data = NULL;
	size_t data_size = 50;
	uint32_t count = 0;


	write_data = calloc(1, data_size);
	if (write_data == NULL)
		goto err;
	read_data = calloc(1, data_size);
	if (read_data == NULL)
		goto err;

	/* gen random data */
	RAND_bytes(write_data, data_size);

	ret = TEE_AllocateTransientObject(TEE_TYPE_RSA_KEYPAIR, key_size, &handler);

	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;
	}

	ret = TEE_GenerateKey(handler, key_size, NULL, 0);

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

	ret = TEE_CreatePersistentObject(TEE_STORAGE_PRIVATE, (void *)objID, objID_len,
					 flags, handler, NULL, 0, &per_han);

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

	ret = TEE_WriteObjectData(per_han, write_data, data_size);
	if (ret != TEE_SUCCESS) {
		printf("Fail: per write\n");
		goto err;
	}

	ret = TEE_SeekObjectData(per_han, 0, TEE_DATA_SEEK_SET);
	if (ret != TEE_SUCCESS) {
		printf("Fail: per seek\n");
		goto err;
	}

	ret = TEE_ReadObjectData(per_han, read_data, data_size, &count);
	if (ret != TEE_SUCCESS) {
		printf("Fail: per read\n");
		goto err;
	}

err:
	TEE_CloseAndDeletePersistentObject(per_han);
	TEE_CloseObject(handler);
	free(write_data);
	free(read_data);
}