Skip to content

Commit

Permalink
Raw access to trusted application secure storage
Browse files Browse the repository at this point in the history
This change provides basics for creating, reading and deleting an
object in a TA secure storage.

The TA implementation shows how to use the GPD TEE Internal Core API
for some basic data persistent object manipulations.

A TA command allows to create an object in the TA secure storage.
A TA command allows to read an object in the TA secure storage.
A TA command allows to delete an object from the TA secure storage.

This example does not cover all the possibilities of secure storage API
provided to TAs: seeking into a object data stream, manipulating
key material objects instead of raw data objects, etc.

Signed-off-by: Etienne Carriere <etienne.carriere@linaro.org>
Acked-by: Jerome Forissier <jerome.forissier@linaro.org>
Acked-by: Jens Wiklander <jens.wiklander@linaro.org>
  • Loading branch information
etienne-lms authored and jenswi-linaro committed Jul 10, 2018
1 parent 1c5d96f commit ae02c09
Show file tree
Hide file tree
Showing 12 changed files with 675 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ hello_world/host/optee_example_hello_world
random/host/optee_example_random
aes/host/optee_example_aes
hotp/host/optee_example_hotp
secure_storage/host/optee_example_secure_storage
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ ciphered data.
* Test application: `optee_example_aes`
* Trusted application UUID: 5dbac793-f574-4871-8ad3-04331ec17f24

Directory **secure_storage/**:
* A Trusted Application to read/write raw data into the
OP-TEE secure storage using the GPD TEE Internal Core API.
* Test application: `optee_example_secure_storage`
* Trusted application UUID: f4e750bb-1437-4fbf-8785-8d3580c34994

## 3. How to build a Trusted Application
[TA basics] documentation presents the basics for implementing and building
an OP-TEE trusted application.
Expand Down
19 changes: 19 additions & 0 deletions secure_storage/Android.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
LOCAL_PATH := $(call my-dir)

OPTEE_CLIENT_EXPORT ?= $(LOCAL_PATH)/../../optee_client/out/export

include $(CLEAR_VARS)
LOCAL_CFLAGS += -DANDROID_BUILD
LOCAL_CFLAGS += -Wall

LOCAL_SRC_FILES += host/main.c

LOCAL_C_INCLUDES := $(LOCAL_PATH)/ta/include \
$(OPTEE_CLIENT_EXPORT)/include

LOCAL_SHARED_LIBRARIES := libteec
LOCAL_MODULE := optee_example_secure_storage
LOCAL_MODULE_TAGS := optional
include $(BUILD_EXECUTABLE)

include $(LOCAL_PATH)/ta/Android.mk
15 changes: 15 additions & 0 deletions secure_storage/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export V ?= 0

# If _HOST or _TA specific compilers are not specified, then use CROSS_COMPILE
HOST_CROSS_COMPILE ?= $(CROSS_COMPILE)
TA_CROSS_COMPILE ?= $(CROSS_COMPILE)

.PHONY: all
all:
$(MAKE) -C host CROSS_COMPILE="$(HOST_CROSS_COMPILE)"
$(MAKE) -C ta CROSS_COMPILE="$(TA_CROSS_COMPILE)"

.PHONY: clean
clean:
$(MAKE) -C host clean
$(MAKE) -C ta clean
25 changes: 25 additions & 0 deletions secure_storage/host/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
CC = $(CROSS_COMPILE)gcc
LD = $(CROSS_COMPILE)ld
AR = $(CROSS_COMPILE)ar
NM = $(CROSS_COMPILE)nm
OBJCOPY = $(CROSS_COMPILE)objcopy
OBJDUMP = $(CROSS_COMPILE)objdump
READELF = $(CROSS_COMPILE)readelf

OBJS = main.o

CFLAGS += -Wall -I../ta/include -I./include
CFLAGS += -I$(TEEC_EXPORT)/include
LDADD += -lteec -L$(TEEC_EXPORT)/lib

BINARY = optee_example_secure_storage

.PHONY: all
all: $(BINARY)

$(BINARY): $(OBJS)
$(CC) -o $@ $< $(LDADD)

.PHONY: clean
clean:
rm -f $(OBJS) $(BINARY)
241 changes: 241 additions & 0 deletions secure_storage/host/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,241 @@
/*
* Copyright (c) 2017, Linaro Limited
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/

#include <err.h>
#include <stdio.h>
#include <string.h>

/* OP-TEE TEE client API (built by optee_client) */
#include <tee_client_api.h>

/* TA API: UUID and command IDs */
#include <secure_storage_ta.h>

/* TEE resources */
struct test_ctx {
TEEC_Context ctx;
TEEC_Session sess;
};

void prepare_tee_session(struct test_ctx *ctx)
{
TEEC_UUID uuid = TA_SECURE_STORAGE_UUID;
uint32_t origin;
TEEC_Result res;

/* Initialize a context connecting us to the TEE */
res = TEEC_InitializeContext(NULL, &ctx->ctx);
if (res != TEEC_SUCCESS)
errx(1, "TEEC_InitializeContext failed with code 0x%x", res);

/* Open a session with the TA */
res = TEEC_OpenSession(&ctx->ctx, &ctx->sess, &uuid,
TEEC_LOGIN_PUBLIC, NULL, NULL, &origin);
if (res != TEEC_SUCCESS)
errx(1, "TEEC_Opensession failed with code 0x%x origin 0x%x",
res, origin);
}

void terminate_tee_session(struct test_ctx *ctx)
{
TEEC_CloseSession(&ctx->sess);
TEEC_FinalizeContext(&ctx->ctx);
}

TEEC_Result read_secure_object(struct test_ctx *ctx, char *id,
char *data, size_t data_len)
{
TEEC_Operation op;
uint32_t origin;
TEEC_Result res;
size_t id_len = strlen(id);

memset(&op, 0, sizeof(op));
op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT,
TEEC_MEMREF_TEMP_OUTPUT,
TEEC_NONE, TEEC_NONE);

op.params[0].tmpref.buffer = id;
op.params[0].tmpref.size = id_len;

op.params[1].tmpref.buffer = data;
op.params[1].tmpref.size = data_len;

res = TEEC_InvokeCommand(&ctx->sess,
TA_SECURE_STORAGE_CMD_READ_RAW,
&op, &origin);
switch (res) {
case TEEC_SUCCESS:
case TEEC_ERROR_SHORT_BUFFER:
case TEEC_ERROR_ITEM_NOT_FOUND:
break;
default:
printf("Command READ_RAW failed: 0x%x / %u\n", res, origin);
}

return res;
}

TEEC_Result write_secure_object(struct test_ctx *ctx, char *id,
char *data, size_t data_len)
{
TEEC_Operation op;
uint32_t origin;
TEEC_Result res;
size_t id_len = strlen(id);

memset(&op, 0, sizeof(op));
op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT,
TEEC_MEMREF_TEMP_INPUT,
TEEC_NONE, TEEC_NONE);

op.params[0].tmpref.buffer = id;
op.params[0].tmpref.size = id_len;

op.params[1].tmpref.buffer = data;
op.params[1].tmpref.size = data_len;

res = TEEC_InvokeCommand(&ctx->sess,
TA_SECURE_STORAGE_CMD_WRITE_RAW,
&op, &origin);
if (res != TEEC_SUCCESS)
printf("Command WRITE_RAW failed: 0x%x / %u\n", res, origin);

switch (res) {
case TEEC_SUCCESS:
break;
default:
printf("Command WRITE_RAW failed: 0x%x / %u\n", res, origin);
}

return res;
}

TEEC_Result delete_secure_object(struct test_ctx *ctx, char *id)
{
TEEC_Operation op;
uint32_t origin;
TEEC_Result res;
size_t id_len = strlen(id);

memset(&op, 0, sizeof(op));
op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT,
TEEC_NONE, TEEC_NONE, TEEC_NONE);

op.params[0].tmpref.buffer = id;
op.params[0].tmpref.size = id_len;

res = TEEC_InvokeCommand(&ctx->sess,
TA_SECURE_STORAGE_CMD_DELETE,
&op, &origin);

switch (res) {
case TEEC_SUCCESS:
case TEEC_ERROR_ITEM_NOT_FOUND:
break;
default:
printf("Command DELETE failed: 0x%x / %u\n", res, origin);
}

return res;
}

#define TEST_OBJECT_SIZE 7000

int main(int argc, char *argv[])
{
struct test_ctx ctx;
char obj1_id[] = "object#1"; /* string identification for the object */
char obj2_id[] = "object#2"; /* string identification for the object */
char obj1_data[TEST_OBJECT_SIZE];
char read_data[TEST_OBJECT_SIZE];
TEEC_Result res;

printf("Prepare session with the TA\n");
prepare_tee_session(&ctx);

/*
* Create object, read it, delete it.
*/
printf("\nTest on object \"%s\"\n", obj1_id);

printf("- Create and load object in the TA secure storage\n");

memset(obj1_data, 0xA1, sizeof(obj1_data));

res = write_secure_object(&ctx, obj1_id,
obj1_data, sizeof(obj1_data));
if (res != TEEC_SUCCESS)
errx(1, "Failed to create an object in the secure storage");

printf("- Read back the object\n");

res = read_secure_object(&ctx, obj1_id,
read_data, sizeof(read_data));
if (res != TEEC_SUCCESS)
errx(1, "Failed to read an object from the secure storage");
if (memcmp(obj1_data, read_data, sizeof(obj1_data)))
errx(1, "Unexpected content found in secure storage");

printf("- Delete the object\n");

res = delete_secure_object(&ctx, obj1_id);
if (res != TEEC_SUCCESS)
errx(1, "Failed to delete the object: 0x%x", res);

/*
* Non volatile storage: create object2 if not found, delete it if found
*/
printf("\nTest on object \"%s\"\n", obj2_id);

res = read_secure_object(&ctx, obj2_id,
read_data, sizeof(read_data));
if (res != TEEC_SUCCESS && res != TEEC_ERROR_ITEM_NOT_FOUND)
errx(1, "Unexpected status when reading an object : 0x%x", res);

if (res == TEEC_ERROR_ITEM_NOT_FOUND) {
char data[] = "This is data stored in the secure storage.\n";

printf("- Object not found in TA secure storage, create it.\n");

res = write_secure_object(&ctx, obj2_id,
data, sizeof(data));
if (res != TEEC_SUCCESS)
errx(1, "Failed to create/load an object");

} else if (res == TEEC_SUCCESS) {
printf("- Object found in TA secure storage, delete it.\n");

res = delete_secure_object(&ctx, obj2_id);
if (res != TEEC_SUCCESS)
errx(1, "Failed to delete an object");
}

printf("\nWe're done, close and release TEE resources\n");
terminate_tee_session(&ctx);
return 0;
}
4 changes: 4 additions & 0 deletions secure_storage/ta/Android.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
LOCAL_PATH := $(call my-dir)

local_module := f4e750bb-1437-4fbf-8785-8d3580c34994.ta
include $(BUILD_OPTEE_MK)
13 changes: 13 additions & 0 deletions secure_storage/ta/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
CFG_TEE_TA_LOG_LEVEL ?= 2
CPPFLAGS += -DCFG_TEE_TA_LOG_LEVEL=$(CFG_TEE_TA_LOG_LEVEL)

# The UUID for the Trusted Application
BINARY=f4e750bb-1437-4fbf-8785-8d3580c34994

-include $(TA_DEV_KIT_DIR)/mk/ta_dev_kit.mk

ifeq ($(wildcard $(TA_DEV_KIT_DIR)/mk/ta_dev_kit.mk), )
clean:
@echo 'Note: $$(TA_DEV_KIT_DIR)/mk/ta_dev_kit.mk not found, cannot clean TA'
@echo 'Note: TA_DEV_KIT_DIR=$(TA_DEV_KIT_DIR)'
endif
Loading

0 comments on commit ae02c09

Please sign in to comment.