initial commit

This commit is contained in:
djmil 2024-03-21 22:12:03 +01:00
commit 0c1ec145aa
21 changed files with 1704 additions and 0 deletions

62
Dockerfile Normal file
View File

@ -0,0 +1,62 @@
FROM ubuntu:22.04
ARG DEBIAN_FRONTEND=noninteractive
RUN apt update && apt upgrade -y
RUN apt install -y \
adb \
acpica-tools \
autoconf \
automake \
bc \
bison \
build-essential \
ccache \
cpio \
cscope \
curl \
device-tree-compiler \
e2tools \
expect \
fastboot \
flex \
ftp-upload \
gdisk \
git \
libattr1-dev \
libcap-ng-dev \
libfdt-dev \
libftdi-dev \
libglib2.0-dev \
libgmp3-dev \
libhidapi-dev \
libmpc-dev \
libncurses5-dev \
libpixman-1-dev \
libslirp-dev \
libssl-dev \
libtool \
libusb-1.0-0-dev \
make \
mtools \
netcat \
ninja-build \
python3-cryptography \
python3-pip \
python3-pyelftools \
python3-serial \
python-is-python3 \
rsync \
swig \
unzip \
uuid-dev \
wget \
xdg-utils \
xterm \
xz-utils \
zlib1g-dev
RUN curl https://storage.googleapis.com/git-repo-downloads/repo > /bin/repo && chmod a+x /bin/repo
RUN mkdir /optee
WORKDIR /optee
RUN repo init -u https://github.com/OP-TEE/manifest.git -m qemu_v8.xml && repo sync -j10
WORKDIR /optee/build
RUN make -j2 toolchains
RUN make -j$(nproc) check

82
README.md Normal file
View File

@ -0,0 +1,82 @@
This project provides a simple PoC implementation of a Secure Storage on top of [OP-TEE](https://optee.readthedocs.io/en/latest/general/about.html) TrustZone based technology.
# Main functionality
The project consists of two modules: Trusted Application and Normal World client.
## Trusted Application
1. Generate RSA key pair.
2. Serialize / Deserialize RSA key pair into Secure Storage for use across sessions. Access to multiple RSA key pairs is implemented with help of TAG identifiers.
3. A special run-time provided PIN is used for further RSA key pair protection. Provided PIN is used by Trusted Application to derive SessionKey, which is used for encryption / decryption of RSA key pair matherial stored in Secure Storage.
4. RSA key pair data is never exposed outside of Trusted Application.
5. Assuming that correct PIN is known, Client Application can use RSA key pair TAG to encrypt / decrypt arbitrary data.
## Normal World client application
1. Provides functional demo for APIs exposed by Trusted Application.
# Build instructions
Usually, access to ARM TrustZone powered device is necessary to see GP-TEE based APIs in action. This project benefits heavily from virtualization techniques like Docker and Qemu.
## 1 Prepare build environment
Run `build-docker.sh` script.
This operation might take several hours to finish. It will create Ubuntu based container, will install all necessary build tools and dependancies. Lastly, it will `git clone` OP-TEE repository with ARMv8 build flavour. Check `Dockerfile` for actual list of performed actions.
## 2 Execute build environment
Use `run-docker.sh` script. The script will:
- map src folder `bliq_storage` inside build environment
- use X11 window forwarding technique, to map two `cli` named **Normal World** and **Secure World** from Docker container onto your host OS
If all went well, you will end up inside an instance of Ubuntu dev environment with `cli` interface similar to `root@80e6b6f27bef:/optee/build#`.
### X11 window forwarding
Use [XQuartz](https://www.xquartz.org/) to enable x11 window forwarding on [mac](https://gist.github.com/sorny/969fe55d85c9b0035b0109a31cbcb088).
> [!NOTE] Be ware
> You will always have to run `xhost +` after a restart of X11 as this is not a persistent setting.
## 3 Build and run demo application
Typing `make run` in `/optee/build`. Will start build for Secure and Normal world parts of OP-TEE OS. After successful build `qemu` emulator will be executed. Press `c` to proceed with virtual device execution. On a first run you might need to type `boot` in **Normal World** console to start boot process.
After the boot finishes, use **Normal World** console window to login as `root`. Then simply type `bliq_storage` to execute demo app, which was build directly from sources.
Other OP-TEE [demo applications](https://github.com/linaro-swg/optee_examples) are also available. Use *tab-key* to assist with typing.
# Source code overview
## `bliq_storege\ta`
This folder contains sources for the Trusted Part of `Bliq Storage` application. Check header files to explore high level API exposed by project submodules.
### `bliq_storage_ta.c`
Main entry point for the Trusted Application. Provides high level implementation for the main commands:
- Create Key
- Delete Key
- Check Key
- Encrypt
- Decrypt
It is also worth mentioning, that PIN-derived AES key (which is used for RSA key pair data encryption) lives in Session context, see `TA_OpenSessionEntryPoint()`
### `operations.c`
Handles AES PIN derivation API, as well as AES encryption / decryption functions for RSA key pair protection.
### `key_pair.c`
Incapsulates set of APIs of underlined GP-TEE APIs, necessary for RSA key pair creating and usage as a handy *trunsient* object. It also provides endpoints for RSA key-pair encryption and decryption of arbitrary data.
Two functions `kp_serialize()` and `kp_deserilize()` might be seen as the sole `hard` of an entire project. Since they are used for *storing / re-storing* RSA key pair data* into / from* a flat buffer. The whole application might be seen as a set of *derivative / supportive* operations build *around / on top of* these two functions.
## `bliq_storage/host/main.c`
A simple TZ client application, showcasing communication between Normal World and Trusted World applications. A particular use case implementation of APIs defined by `bliq_storage\ta\include\bliq_storage_ta.h`

17
bliq_storage/Android.mk Normal file
View File

@ -0,0 +1,17 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_CFLAGS += -DANDROID_BUILD
LOCAL_CFLAGS += -Wall
LOCAL_SRC_FILES += host/main.c
LOCAL_C_INCLUDES := $(LOCAL_PATH)/ta/include
LOCAL_SHARED_LIBRARIES := libteec
LOCAL_MODULE := bliq_storage
LOCAL_VENDOR_MODULE := true
LOCAL_MODULE_TAGS := optional
include $(BUILD_EXECUTABLE)
include $(LOCAL_PATH)/ta/Android.mk

View File

@ -0,0 +1,13 @@
project (bliq_storage C)
set (SRC host/main.c)
add_executable (${PROJECT_NAME} ${SRC})
target_include_directories(${PROJECT_NAME}
PRIVATE ta/include
PRIVATE include)
target_link_libraries (${PROJECT_NAME} PRIVATE teec)
install (TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR})

15
bliq_storage/Makefile Normal file
View File

@ -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)" --no-builtin-variables
$(MAKE) -C ta CROSS_COMPILE="$(TA_CROSS_COMPILE)" LDFLAGS=""
.PHONY: clean
clean:
$(MAKE) -C host clean
$(MAKE) -C ta clean

View File

@ -0,0 +1,28 @@
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 = bliq_storage
.PHONY: all
all: $(BINARY)
$(BINARY): $(OBJS)
$(CC) $(LDFLAGS) -o $@ $< $(LDADD)
.PHONY: clean
clean:
rm -f $(OBJS) $(BINARY)
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@

346
bliq_storage/host/main.c Normal file
View File

@ -0,0 +1,346 @@
/*
* 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 <bliq_storage_ta.h>
/* TEE resources */
struct test_ctx {
TEEC_Context ctx;
TEEC_Session sess;
};
void open_tee_session(
struct test_ctx *ctx,
char *pin, size_t pin_len)
{
TEEC_Operation op;
TEEC_UUID uuid = TA_BLIQ_STORAGE_UUID;
uint32_t origin;
TEEC_Result res;
// Set session PIN
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 = pin;
op.params[0].tmpref.size = pin_len;
/* 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, &op, &origin);
if (res != TEEC_SUCCESS)
errx(1, "TEEC_Opensession failed with code 0x%x origin 0x%x",
res, origin);
}
void close_tee_session(struct test_ctx *ctx)
{
TEEC_CloseSession(&ctx->sess);
TEEC_FinalizeContext(&ctx->ctx);
}
TEEC_Result create_key(
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_BLIQ_STORAGE_CMD_CREATE_KEY,
&op, &origin);
switch (res) {
case TEEC_SUCCESS:
break;
default:
printf("Command TA_BLIQ_STORAGE_CMD_CREATE_KEY failed: 0x%x / %u\n", res, origin);
}
return res;
}
TEEC_Result check_key(
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_BLIQ_STORAGE_CMD_CHECK_KEY,
&op, &origin);
switch (res) {
case TEEC_SUCCESS:
case TEEC_ERROR_ITEM_NOT_FOUND:
break;
default:
printf("Command TA_BLIQ_STORAGE_CMD_CHECK_KEY failed: 0x%x / %u\n", res, origin);
}
return res;
}
TEEC_Result delete_key(
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_BLIQ_STORAGE_CMD_DELETE_KEY,
&op, &origin);
switch (res) {
case TEEC_SUCCESS:
case TEEC_ERROR_ITEM_NOT_FOUND:
break;
default:
printf("Command TA_BLIQ_STORAGE_CMD_DELETE_KEY failed: 0x%x / %u\n", res, origin);
}
return res;
}
TEEC_Result encrypt(
struct test_ctx *ctx,
char *id,
char *data, uint32_t data_len,
char *encr, uint32_t *encr_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_MEMREF_TEMP_INOUT,
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;
op.params[2].tmpref.buffer = encr;
op.params[2].tmpref.size = *encr_len;
res = TEEC_InvokeCommand(&ctx->sess,
TA_BLIQ_STORAGE_CMD_ENCRYPT,
&op, &origin);
switch (res) {
case TEEC_SUCCESS:
*encr_len = op.params[2].tmpref.size;
break;
default:
printf("Command TA_BLIQ_STORAGE_CMD_ENCRYPT failed: 0x%x / %u\n", res, origin);
}
return res;
}
TEEC_Result decrypt(
struct test_ctx *ctx,
char *id,
char *encr, uint32_t encr_len,
char *decr, uint32_t *decr_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_MEMREF_TEMP_INOUT,
TEEC_NONE);
op.params[0].tmpref.buffer = id;
op.params[0].tmpref.size = id_len;
op.params[1].tmpref.buffer = encr;
op.params[1].tmpref.size = encr_len;
op.params[2].tmpref.buffer = decr;
op.params[2].tmpref.size = *decr_len;
res = TEEC_InvokeCommand(&ctx->sess,
TA_BLIQ_STORAGE_CMD_DECRYPT,
&op, &origin);
switch (res) {
case TEEC_SUCCESS:
*decr_len = op.params[2].tmpref.size;
break;
default:
printf("Command TA_BLIQ_STORAGE_CMD_DECRYPT failed: 0x%x / %u\n", res, origin);
}
return res;
}
int main(void)
{
struct test_ctx ctx;
char key_id[] = "key#1";
char pin[6] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05}; // used to encrypt/decrypt key
char data[] = "Test string for data encryption";
char encrypted_data[512];
uint32_t encrypted_data_sz = sizeof(encrypted_data);
char decrypted_data[512];
uint32_t decrypted_data_sz = sizeof(decrypted_data);
TEEC_Result res;
printf("Prepare session with the TA\n");
open_tee_session(&ctx, pin, sizeof(pin));
/*
* Check Create , read it, delete it.
*/
printf("\nCheck KeyID \"%s\"\n", key_id);
res = check_key(
&ctx,
key_id);
if (res == TEEC_ERROR_ITEM_NOT_FOUND) {
printf(" - KeyId was not found in TA secure storage, create new one\n");
res = create_key(
&ctx,
key_id);
if (res != TEEC_SUCCESS)
errx(1, "Unexpected status when creating key: 0x%x", res);
printf(" - RSA keypair creation [OK]\n");
printf(" - Run application one more time to test Encrypt / Decrypt APIs..\n");
}
else if (res == TEEC_SUCCESS) {
printf(" - KeyId was found!\n");
printf(" - Test Encrypt / Decrypt APIs..\n");
res = encrypt(
&ctx,
key_id,
data, sizeof(data),
encrypted_data, &encrypted_data_sz);
if (res != TEEC_SUCCESS)
errx(1, "Unexpected status during data encryption: 0x%x", res);
printf(" -- encr_data: [%u] first 4 bytes: %02x:%02x:%02x:%02x\n",
encrypted_data_sz, encrypted_data[0], encrypted_data[1], encrypted_data[2], encrypted_data[3]);
res = decrypt(&ctx, key_id,
encrypted_data, encrypted_data_sz,
decrypted_data, &decrypted_data_sz);
if (res != TEEC_SUCCESS)
errx(1, "Unexpected status during data decryption: 0x%x", res);
printf(" -- orig_data: [%lu] '%s'\n -- decr_data: [%d] '%s'\n",
sizeof(data), data,
decrypted_data_sz, decrypted_data);
printf(" - Encrypt / Decrypt APIs test [ok]\n");
printf(" - Delete RSA keypair from secure storage\n");
res = delete_key(
&ctx,
key_id);
if (res != TEEC_SUCCESS)
errx(1, "Unexpected status during key delition: 0x%x", res);
}
close_tee_session(&ctx);
return 0;
}

View File

@ -0,0 +1,4 @@
LOCAL_PATH := $(call my-dir)
local_module := 0651d840-a91b-4b3f-a222-b68cd195231c.ta
include $(BUILD_OPTEE_MK)

13
bliq_storage/ta/Makefile Normal file
View File

@ -0,0 +1,13 @@
CFG_TEE_TA_LOG_LEVEL ?= 2
CFG_TA_OPTEE_CORE_API_COMPAT_1_1=y
# The UUID for the Trusted Application
BINARY=0651d840-a91b-4b3f-a222-b68cd195231c
-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

View File

@ -0,0 +1,560 @@
#include <inttypes.h>
#include <bliq_storage_ta.h>
#include <tee_internal_api.h>
#include <tee_internal_api_extensions.h>
#include "operations.h"
#include "key_pair.h"
#include <string.h>
static TEE_Result ss_read_object(
char *obj_id, uint32_t obj_id_sz,
void *buff, uint32_t *buff_sz
)
{
TEE_Result res;
TEE_ObjectHandle object = NULL;
TEE_ObjectInfo object_info;
res = TEE_OpenPersistentObject(TEE_STORAGE_PRIVATE,
obj_id, obj_id_sz,
TEE_DATA_FLAG_ACCESS_READ |
TEE_DATA_FLAG_SHARE_READ,
&object);
if (res != TEE_SUCCESS) {
EMSG("[ERR] ss_read_object(): Failed to open persistent object, res=0x%x", res);
goto exit;
}
res = TEE_GetObjectInfo1(
object,
&object_info);
if (res != TEE_SUCCESS) {
EMSG("[ERR] ss_read_object(): Failed to get persistent object ibfo, res=0x%x", res);
goto exit;
}
if (object_info.dataSize > *buff_sz) {
/*
* Provided buffer is too short.
* Return the expected size together with status "short buffer"
*/
*buff_sz = object_info.dataSize;
res = TEE_ERROR_SHORT_BUFFER;
goto exit;
}
res = TEE_ReadObjectData(
object,
buff, object_info.dataSize,
buff_sz);
exit:
if (object)
TEE_CloseObject(object);
return res;
}
static TEE_Result get_key(
Session *session,
char *obj_id, uint32_t obj_id_sz,
TEE_ObjectHandle *kp)
{
TEE_Result res;
char *kp_serialized_buff = NULL;
uint32_t kp_serialized_buff_sz = 2048;
char *kp_decrypted_buff = NULL;
uint32_t kp_decrypted_buff_sz = 2048;
kp_serialized_buff = TEE_Malloc(kp_serialized_buff_sz, 0);
if (!kp_serialized_buff)
return TEE_ERROR_OUT_OF_MEMORY;
res = ss_read_object(
obj_id, obj_id_sz,
kp_serialized_buff, &kp_serialized_buff_sz);
if (res != TEE_SUCCESS) {
EMSG("[ERR]: get_key(%s): Unable to read data from sec store: 0x%x", obj_id, res);
goto exit;
}
kp_decrypted_buff = TEE_Malloc(kp_decrypted_buff_sz, 0);
if (!kp_decrypted_buff)
return TEE_ERROR_OUT_OF_MEMORY;
res = so_decrypt(
session,
kp_serialized_buff, kp_serialized_buff_sz,
kp_decrypted_buff, &kp_decrypted_buff_sz);
if (res != TEE_SUCCESS) {
EMSG("[ERR]: get_key(%s): Unable to decrypt RSA key pair: 0x%x", obj_id, res);
goto exit;
}
res = kp_deserialize(
kp_decrypted_buff, kp_decrypted_buff_sz,
kp);
if (res != TEE_SUCCESS) {
EMSG("[ERR]: get_key(%s): Unable to deserialize RSA key pair: 0x%x", obj_id, res);
goto exit;
}
exit:
TEE_Free(kp_serialized_buff);
TEE_Free(kp_decrypted_buff);
return res;
}
/*
* TA API implementation
*/
static TEE_Result create_key(
Session *session,
uint32_t param_types,
TEE_Param params[4])
{
const uint32_t exp_param_types = TEE_PARAM_TYPES(
TEE_PARAM_TYPE_MEMREF_INPUT,
TEE_PARAM_TYPE_NONE,
TEE_PARAM_TYPE_NONE,
TEE_PARAM_TYPE_NONE);
TEE_ObjectHandle kp = NULL;
TEE_ObjectHandle object;
TEE_Result res;
char *obj_id = NULL;
size_t obj_id_sz;
uint32_t obj_data_flag;
char *kp_serialized_buff = NULL;
uint32_t kp_serialized_buff_sz = 2048;
char *kp_encrypted_buff = NULL;
uint32_t kp_encrypted_buff_sz = 2048;
/*
* Safely get the invocation parameters
*/
if (param_types != exp_param_types)
return TEE_ERROR_BAD_PARAMETERS;
obj_id_sz = params[0].memref.size;
obj_id = TEE_Malloc(obj_id_sz, 0);
if (!obj_id)
return TEE_ERROR_OUT_OF_MEMORY;
TEE_MemMove(obj_id, params[0].memref.buffer, obj_id_sz);
/*
* Generate RSA KeyPair
*/
res = kp_create(&kp);
if (res != TEE_SUCCESS) {
EMSG("Unable to create RSA key pair: 0x%08x", res);
goto exit;
}
/*
* Serialize RSA KeyPair into external buffer
*/
kp_serialized_buff = TEE_Malloc(kp_serialized_buff_sz, 0);
if (!kp_serialized_buff)
return TEE_ERROR_OUT_OF_MEMORY;
res = kp_serialize(
kp,
kp_serialized_buff, &kp_serialized_buff_sz);
if (res != TEE_SUCCESS) {
EMSG("Unable to serialize RSA key pair: 0x%08x", res);
goto exit;
}
/*
* Encrypt serrialized RSA keypair buffer
*/
kp_encrypted_buff = TEE_Malloc(kp_encrypted_buff_sz, 0);
if (!kp_encrypted_buff)
return TEE_ERROR_OUT_OF_MEMORY;
res = so_encrypt(
session,
kp_serialized_buff, kp_serialized_buff_sz,
kp_encrypted_buff, &kp_encrypted_buff_sz);
if (res != TEE_SUCCESS) {
EMSG("Unable to encrypt RSA key pair: 0x%08x", res);
goto exit;
}
/*
* Create object in secure storage and fill it with encrypted RSA keypair
*/
obj_data_flag =
TEE_DATA_FLAG_ACCESS_READ | /* we can later read the oject */
TEE_DATA_FLAG_ACCESS_WRITE | /* we can later write into the object */
TEE_DATA_FLAG_ACCESS_WRITE_META | /* we can later destroy or rename the object */
TEE_DATA_FLAG_OVERWRITE; /* destroy existing object of same ID */
res = TEE_CreatePersistentObject(TEE_STORAGE_PRIVATE,
obj_id, obj_id_sz,
obj_data_flag,
TEE_HANDLE_NULL,
NULL, 0, /* we may not fill it right now */
&object);
if (res != TEE_SUCCESS) {
EMSG("TEE_CreatePersistentObject failed 0x%08x", res);
goto exit;
}
res = TEE_WriteObjectData(
object,
kp_encrypted_buff, kp_encrypted_buff_sz);
if (res != TEE_SUCCESS) {
EMSG("TEE_WriteObjectData failed 0x%08x", res);
TEE_CloseAndDeletePersistentObject1(object);
} else {
TEE_CloseObject(object);
}
exit:
TEE_Free(obj_id);
TEE_Free(kp_serialized_buff);
TEE_Free(kp_encrypted_buff);
if (kp)
TEE_FreeTransientObject(kp);
return res;
}
static TEE_Result check_key(
Session *session,
uint32_t param_types,
TEE_Param params[4])
{
const uint32_t exp_param_types = TEE_PARAM_TYPES(
TEE_PARAM_TYPE_MEMREF_INPUT,
TEE_PARAM_TYPE_NONE,
TEE_PARAM_TYPE_NONE,
TEE_PARAM_TYPE_NONE);
TEE_Result res;
TEE_ObjectHandle kp = NULL;
char *obj_id;
uint32_t obj_id_sz;
/*
* Safely get the invocation parameters
*/
if (param_types != exp_param_types)
return TEE_ERROR_BAD_PARAMETERS;
obj_id_sz = params[0].memref.size;
obj_id = TEE_Malloc(obj_id_sz, 0);
if (!obj_id)
return TEE_ERROR_OUT_OF_MEMORY;
TEE_MemMove(obj_id, params[0].memref.buffer, obj_id_sz);
EMSG("[DBG] check_key(): obj_id '%s'", obj_id);
res = get_key(
session,
obj_id, obj_id_sz,
&kp);
if (res != TEE_SUCCESS) {
EMSG("[ERR] check_key(): Unable to obtain RSA keypair: 0x%x", res);
goto exit;
}
exit:
TEE_Free(obj_id);
if (kp)
TEE_FreeTransientObject(kp);
return res;
}
static TEE_Result delete_key(
uint32_t param_types,
TEE_Param params[4])
{
const uint32_t exp_param_types = TEE_PARAM_TYPES(
TEE_PARAM_TYPE_MEMREF_INPUT,
TEE_PARAM_TYPE_NONE,
TEE_PARAM_TYPE_NONE,
TEE_PARAM_TYPE_NONE);
TEE_ObjectHandle object;
TEE_Result res;
char *obj_id;
size_t obj_id_sz;
/*
* Safely get the invocation parameters
*/
if (param_types != exp_param_types)
return TEE_ERROR_BAD_PARAMETERS;
obj_id_sz = params[0].memref.size;
obj_id = TEE_Malloc(obj_id_sz, 0);
if (!obj_id)
return TEE_ERROR_OUT_OF_MEMORY;
TEE_MemMove(obj_id, params[0].memref.buffer, obj_id_sz);
/*
* Check object exists and delete it
*/
res = TEE_OpenPersistentObject(TEE_STORAGE_PRIVATE,
obj_id, obj_id_sz,
TEE_DATA_FLAG_ACCESS_READ |
TEE_DATA_FLAG_ACCESS_WRITE_META, /* we must be allowed to delete it */
&object);
if (res != TEE_SUCCESS) {
EMSG("[ERR] Unable to open persistent object, res=0x%x", res);
TEE_Free(obj_id);
return res;
}
TEE_CloseAndDeletePersistentObject1(object);
TEE_Free(obj_id);
return res;
}
static TEE_Result encrypt_data(
Session *session,
uint32_t param_types,
TEE_Param params[4])
{
const uint32_t exp_param_types = TEE_PARAM_TYPES(
TEE_PARAM_TYPE_MEMREF_INPUT,
TEE_PARAM_TYPE_MEMREF_INPUT,
TEE_PARAM_TYPE_MEMREF_INOUT,
TEE_PARAM_TYPE_NONE);
TEE_Result res;
TEE_ObjectHandle kp = NULL;
char *obj_id;
uint32_t obj_id_sz;
char *data;
uint32_t data_sz;
char *enc_data;
uint32_t enc_data_sz;
/*
* Safely get the invocation parameters
*/
if (param_types != exp_param_types)
return TEE_ERROR_BAD_PARAMETERS;
obj_id_sz = params[0].memref.size;
obj_id = TEE_Malloc(obj_id_sz, 0);
if (!obj_id)
return TEE_ERROR_OUT_OF_MEMORY;
TEE_MemMove(obj_id, params[0].memref.buffer, obj_id_sz);
EMSG("[DBG] encrypt_data: obj_id '%s'", obj_id);
data_sz = params[1].memref.size;
data = TEE_Malloc(data_sz, 0);
if (!data)
return TEE_ERROR_OUT_OF_MEMORY;
TEE_MemMove(data, params[1].memref.buffer, data_sz);
EMSG("[DBG] encrypt_data: plain_data '%s'", data);
res = get_key(
session,
obj_id, obj_id_sz,
&kp);
if (res != TEE_SUCCESS) {
EMSG("[ERR] encrypt_data(): Unable to obtain RSA keypair: 0x%x", res);
goto exit;
}
// const char msg[] = "hello from kp_encrypt";
// EMSG("[DBG] encrypt_data(): Return hardcoded string");
// TEE_MemMove(params[2].memref.buffer, msg, sizeof(msg));
// params[2].memref.size = sizeof(msg);
// return res;
enc_data = params[2].memref.buffer;
enc_data_sz = params[2].memref.size;
res = kp_encrypt(
kp,
data, data_sz,
enc_data, &enc_data_sz);
if (res != TEE_SUCCESS) {
EMSG("[ERR] encrypt_data(): Unable to encryp data: 0x%x", res);
goto exit;
}
// Encryption [OK]
// update output buffer size
params[2].memref.size = enc_data_sz;
exit:
TEE_Free(obj_id);
TEE_Free(data);
if (kp)
TEE_FreeTransientObject(kp);
return res;
}
static TEE_Result decrypt_data(
Session *session,
uint32_t param_types,
TEE_Param params[4])
{
const uint32_t exp_param_types = TEE_PARAM_TYPES(
TEE_PARAM_TYPE_MEMREF_INPUT,
TEE_PARAM_TYPE_MEMREF_INPUT,
TEE_PARAM_TYPE_MEMREF_INOUT,
TEE_PARAM_TYPE_NONE);
TEE_Result res;
TEE_ObjectHandle kp = NULL;
char *obj_id;
uint32_t obj_id_sz;
char *data;
uint32_t data_sz;
char *dec_data;
uint32_t dec_data_sz;
/*
* Safely get the invocation parameters
*/
if (param_types != exp_param_types)
return TEE_ERROR_BAD_PARAMETERS;
obj_id_sz = params[0].memref.size;
obj_id = TEE_Malloc(obj_id_sz, 0);
if (!obj_id)
return TEE_ERROR_OUT_OF_MEMORY;
TEE_MemMove(obj_id, params[0].memref.buffer, obj_id_sz);
EMSG("[DBG] decrypt_data: obj_id '%s'", obj_id);
data_sz = params[1].memref.size;
data = TEE_Malloc(data_sz, 0);
if (!data)
return TEE_ERROR_OUT_OF_MEMORY;
TEE_MemMove(data, params[1].memref.buffer, data_sz);
res = get_key(
session,
obj_id, obj_id_sz,
&kp);
if (res != TEE_SUCCESS) {
EMSG("[ERR] decrypt_data(): Unable to obtain RSA keypair: 0x%x", res);
goto exit;
}
dec_data = params[2].memref.buffer;
dec_data_sz = params[2].memref.size;
res = kp_decrypt(
kp,
data, data_sz,
dec_data, &dec_data_sz);
if (res != TEE_SUCCESS) {
EMSG("[ERR] decrypt_data(): Unable to decryp data: 0x%x", res);
goto exit;
}
// Decryption [OK]
// update output buffer size
params[2].memref.size = dec_data_sz;
exit:
TEE_Free(obj_id);
TEE_Free(data);
if (kp)
TEE_FreeTransientObject(kp);
return res;
}
TEE_Result TA_CreateEntryPoint(void)
{
/* Nothing to do */
return TEE_SUCCESS;
}
void TA_DestroyEntryPoint(void)
{
/* Nothing to do */
}
TEE_Result TA_OpenSessionEntryPoint(
uint32_t param_types,
TEE_Param params[4],
void **ctx)
{
const uint32_t exp_param_types = TEE_PARAM_TYPES(
TEE_PARAM_TYPE_MEMREF_INPUT,
TEE_PARAM_TYPE_NONE,
TEE_PARAM_TYPE_NONE,
TEE_PARAM_TYPE_NONE);
/*
* Safely get the invocation parameters
*/
if (param_types != exp_param_types)
return TEE_ERROR_BAD_PARAMETERS;
Session *session = TEE_Malloc(sizeof (Session), 0);
if (!session)
return TEE_ERROR_OUT_OF_MEMORY;
char *pin = params[0].memref.buffer;
size_t pin_sz = params[0].memref.size;
*ctx = session;
return so_init(pin, pin_sz, session);
}
void TA_CloseSessionEntryPoint(void *ctx)
{
Session *session = ctx;
if (session == NULL)
return;
so_free(session);
TEE_Free(ctx);
}
TEE_Result TA_InvokeCommandEntryPoint(
void *session,
uint32_t command,
uint32_t param_types,
TEE_Param params[4])
{
switch (command) {
case TA_BLIQ_STORAGE_CMD_CREATE_KEY:
return create_key(session, param_types, params);
case TA_BLIQ_STORAGE_CMD_CHECK_KEY:
return check_key(session, param_types, params);
case TA_BLIQ_STORAGE_CMD_DELETE_KEY:
return delete_key(param_types, params);
case TA_BLIQ_STORAGE_CMD_ENCRYPT:
return encrypt_data(session, param_types, params);
case TA_BLIQ_STORAGE_CMD_DECRYPT:
return decrypt_data(session, param_types, params);
default:
EMSG("Command ID 0x%x is not supported", command);
return TEE_ERROR_NOT_SUPPORTED;
}
}

View File

@ -0,0 +1,59 @@
#ifndef __BLIQ_STORAGE_H__
#define __BLIQ_STORAGE_H__
/* UUID of the trusted application */
#define TA_BLIQ_STORAGE_UUID \
{ 0x0651d840, 0xa91b, 0x4b3f, \
{ 0xa2, 0x22, 0xb6, 0x8c, 0xd1, 0x95, 0x23, 0x1c } }
/*
* TA_BLIQ_STORAGE_CMD_CREATE_KEY - Create RSA key and store it
* in encrypted form (AES pin) inside secure storage file
* param[0] (memref) ID used the identify RSA key
* param[1] unused
* param[2] unused
* param[3] unused
*/
#define TA_BLIQ_STORAGE_CMD_CREATE_KEY 1
/*
* TA_BLIQ_STORAGE_CMD_CHECK_KEY - Check if tagget RSA key pair
* exists and is accessinbel
* param[0] (memref) ID used the identify RSA key
* param[1] unused
* param[2] unused
* param[3] unused
*/
#define TA_BLIQ_STORAGE_CMD_CHECK_KEY 2
/*
* TA_BLIQ_STORAGE_CMD_DELETE - Delete tagget RSA key pair
* param[0] (memref) ID used the identify the persistent object
* param[1] unused
* param[2] unused
* param[3] unused
*/
#define TA_BLIQ_STORAGE_CMD_DELETE_KEY 3
/*
* TA_BLIQ_STORAGE_CMD_ENCRYPT - Encrypt arbitrary string
* with protected RSA KeyPair from secure storage
* param[0] (memref) ID used the identify RSA key
* param[1] (memref) plain data to encrypt
* param[2] (memref) encrypted data
* param[3] unused
*/
#define TA_BLIQ_STORAGE_CMD_ENCRYPT 4
/*
* TA_BLIQ_STORAGE_CMD_DECRYPT - Decrypt previosly encrypted string
* with protected RSA KeyPair from secure storage
* param[0] (memref) ID used the identify RSA key
* param[1] (memref) encrypted data
* param[2] (memref) decrypted data
* param[3] unused
*/
#define TA_BLIQ_STORAGE_CMD_DECRYPT 5
#endif /* __BLIQ_STORAGE_H__ */

263
bliq_storage/ta/key_pair.c Normal file
View File

@ -0,0 +1,263 @@
#include <inttypes.h>
#include "operations.h"
#include "key_pair.h"
static char* storeNext(
TEE_ObjectHandle kp,
uint32_t attribute_id,
char *curr, const char * const end)
{
TEE_Result res;
uint32_t attribute_sz;
if (curr == NULL)
return NULL;
TEE_GetObjectBufferAttribute(kp, attribute_id, NULL, &attribute_sz);
if (curr + sizeof(uint32_t) + attribute_sz > end)
return NULL;
EMSG("[INFO] -->> attr_size %u\n", attribute_sz);
// store attribute size
curr[0] = attribute_sz & 0xFF;
curr[1] = attribute_sz >> 8 & 0xFF;
curr[2] = attribute_sz >> 16 & 0xFF;
curr[3] = attribute_sz >> 24 & 0xFF;
curr += sizeof(uint32_t); // move pointer
res = TEE_GetObjectBufferAttribute(kp, attribute_id, curr, &attribute_sz);
if (res != TEE_SUCCESS)
return NULL;
return curr + attribute_sz;
}
static char* readNext(
TEE_Attribute *key_attr,
uint32_t attribute_id,
char *curr, const char * const end)
{
if (curr > end || curr == NULL)
return NULL;
uint32_t attribute_sz = curr[3] <<24 | curr[2] <<16 | curr[1] <<8 | curr[0];
EMSG("[INFO] <<-- attr_size %u\n", attribute_sz);
curr += sizeof(uint32_t); // move pointer
TEE_InitRefAttribute(key_attr, attribute_id, curr, attribute_sz);
return curr + attribute_sz;
}
TEE_Result kp_create(
TEE_ObjectHandle *kp)
{
const uint32_t key_type = TEE_TYPE_RSA_KEYPAIR;
const uint32_t key_size = 1024; // fast calculations
TEE_Result res;
TEE_ObjectHandle key = NULL;
res = TEE_AllocateTransientObject(
key_type, key_size,
&key);
if (res != TEE_SUCCESS) {
EMSG("[ERR] kp_create: TEE_AllocateTransientObject(%#" PRIx32 ", %" PRId32 "): %#" PRIx32, key_type, key_size, res);
goto exit;
}
res = TEE_GenerateKey(
key, key_size,
NULL, 0);
if (res != TEE_SUCCESS) {
EMSG("[ERR] kp_create: TEE_GenerateKey(%" PRId32 "): %#" PRIx32, key_size, res);
goto exit;
}
*kp = key;
key = NULL;
exit:
if (key)
TEE_FreeTransientObject(key);
return res;
}
TEE_Result kp_serialize(
TEE_ObjectHandle kp,
char *serilized, uint32_t *serilized_sz)
{
char *curr = serilized;
char *end = serilized + *serilized_sz;
curr = storeNext(kp, TEE_ATTR_RSA_MODULUS , curr, end);
curr = storeNext(kp, TEE_ATTR_RSA_PUBLIC_EXPONENT , curr, end);
curr = storeNext(kp, TEE_ATTR_RSA_PRIVATE_EXPONENT, curr, end);
curr = storeNext(kp, TEE_ATTR_RSA_PRIME1 , curr, end);
curr = storeNext(kp, TEE_ATTR_RSA_PRIME2 , curr, end);
curr = storeNext(kp, TEE_ATTR_RSA_EXPONENT1 , curr, end);
curr = storeNext(kp, TEE_ATTR_RSA_EXPONENT2 , curr, end);
curr = storeNext(kp, TEE_ATTR_RSA_COEFFICIENT , curr, end);
if (curr == NULL)
return TEE_ERROR_OVERFLOW;
*serilized_sz = curr - serilized;
return TEE_SUCCESS;
}
TEE_Result kp_deserialize(
char *serilized, uint32_t serilized_sz,
TEE_ObjectHandle *kp)
{
TEE_Result res;
TEE_Attribute key_attr[8];
uint32_t key_attr_count = 8;
TEE_ObjectHandle transient_kp = NULL;
const uint32_t key_type = TEE_TYPE_RSA_KEYPAIR;
const uint32_t key_size = 1024; // fast calculations
char *curr = serilized;
char *curr_end = serilized + serilized_sz;
curr = readNext(&key_attr[0], TEE_ATTR_RSA_MODULUS , curr, curr_end);
curr = readNext(&key_attr[1], TEE_ATTR_RSA_PUBLIC_EXPONENT , curr, curr_end);
curr = readNext(&key_attr[2], TEE_ATTR_RSA_PRIVATE_EXPONENT, curr, curr_end);
curr = readNext(&key_attr[3], TEE_ATTR_RSA_PRIME1 , curr, curr_end);
curr = readNext(&key_attr[4], TEE_ATTR_RSA_PRIME2 , curr, curr_end);
curr = readNext(&key_attr[5], TEE_ATTR_RSA_EXPONENT1 , curr, curr_end);
curr = readNext(&key_attr[6], TEE_ATTR_RSA_EXPONENT2 , curr, curr_end);
curr = readNext(&key_attr[7], TEE_ATTR_RSA_COEFFICIENT , curr, curr_end);
if (curr == NULL) {
res = TEE_ERROR_OVERFLOW;
goto exit;
}
res = TEE_AllocateTransientObject(
key_type, key_size,
&transient_kp);
if (res != TEE_SUCCESS) {
EMSG("[ERR] kp_deserialize(): TEE_AllocateTransientObject(%#" PRIx32 ", %" PRId32 "): %#" PRIx32, key_type, key_size, res);
goto exit;
}
res = TEE_PopulateTransientObject(
transient_kp,
key_attr, key_attr_count);
if (res != TEE_SUCCESS) {
EMSG("[ERR]: kp_deserialize(): TEE_PopulateTransientObject: 0x%x", res);
goto exit;
}
*kp = transient_kp;
transient_kp = NULL;
exit:
if (transient_kp)
TEE_FreeTransientObject(transient_kp);
return res;
}
TEE_Result kp_encrypt(
TEE_ObjectHandle kp,
void *inbuf, uint32_t inbuf_sz,
void *outbuf, uint32_t *outbuf_sz)
{
const uint32_t alg = TEE_ALG_RSAES_PKCS1_V1_5;
TEE_Result res;
TEE_OperationHandle op = NULL;
TEE_ObjectInfo key_info;
res = TEE_GetObjectInfo1(kp, &key_info);
if (res != TEE_SUCCESS) {
EMSG("[ERR] kp_encrypt: TEE_GetObjectInfo1: %#" PRIx32, res);
goto exit;
}
res = TEE_AllocateOperation(
&op,
alg, TEE_MODE_ENCRYPT,
key_info.keySize);
if (res != TEE_SUCCESS) {
EMSG("[ERR] kp_encrypt: TEE_AllocateOperation(TEE_MODE_ENCRYPT, %#" PRIx32 ", %" PRId32 "): %#" PRIx32, alg, key_info.keySize, res);
goto exit;
}
res = TEE_SetOperationKey(op, kp);
if (res != TEE_SUCCESS) {
EMSG("[ERR] kp_encrypt: TEE_SetOperationKey: %#" PRIx32, res);
goto exit;
}
res = TEE_AsymmetricEncrypt(
op,
NULL, 0,
inbuf, inbuf_sz,
outbuf, outbuf_sz);
if (res != TEE_SUCCESS) {
EMSG("[ERR] kp_encrypt: TEE_AsymmetricEncrypt(%u, %u): 0x%x", inbuf_sz, *outbuf_sz, res);
goto exit;
}
exit:
if (op)
TEE_FreeOperation(op);
return res;
}
TEE_Result kp_decrypt(
TEE_ObjectHandle kp,
void *inbuf, uint32_t inbuf_sz,
void *outbuf, uint32_t *outbuf_sz)
{
const uint32_t alg = TEE_ALG_RSAES_PKCS1_V1_5;
TEE_Result res;
TEE_OperationHandle op = NULL;
TEE_ObjectInfo key_info;
res = TEE_GetObjectInfo1(kp, &key_info);
if (res != TEE_SUCCESS) {
EMSG("[ERR] kp_encrypt: TEE_GetObjectInfo1: %#" PRIx32, res);
goto exit;
}
res = TEE_AllocateOperation(
&op,
alg, TEE_MODE_DECRYPT,
key_info.keySize);
if (res != TEE_SUCCESS) {
EMSG("[ERR] kp_encrypt: TEE_AllocateOperation(TEE_MODE_DECRYPT, %#" PRIx32 ", %" PRId32 "): %#" PRIx32, alg, key_info.keySize, res);
goto exit;
}
res = TEE_SetOperationKey(op, kp);
if (res != TEE_SUCCESS) {
EMSG("[ERR] kp_encrypt: TEE_SetOperationKey: %#" PRIx32, res);
goto exit;
}
res = TEE_AsymmetricDecrypt(
op,
NULL, 0,
inbuf, inbuf_sz,
outbuf, outbuf_sz);
if (res != TEE_SUCCESS) {
EMSG("[ERR] kp_encrypt: TEE_AsymmetricEncrypt(%u, %u): 0x%x", inbuf_sz, *outbuf_sz, res);
goto exit;
}
exit:
if (op)
TEE_FreeOperation(op);
return res;
}

View File

@ -0,0 +1,27 @@
#include <tee_internal_api.h>
#ifndef KEY_PAIR_H
#define KEY_PAIR_H
TEE_Result kp_create(
TEE_ObjectHandle *kp);
TEE_Result kp_serialize(
TEE_ObjectHandle kp,
char *serilized, uint32_t *serilized_sz);
TEE_Result kp_deserialize(
char *serilized, uint32_t serilized_sz,
TEE_ObjectHandle *kp);
TEE_Result kp_encrypt(
TEE_ObjectHandle kp,
void *in, uint32_t in_sz,
void *out, uint32_t *out_sz);
TEE_Result kp_decrypt(
TEE_ObjectHandle kp,
void *in, uint32_t in_sz,
void *out, uint32_t *out_sz);
#endif /*KEY_PAIR_H*/

View File

@ -0,0 +1,151 @@
#include <inttypes.h>
#include "operations.h"
char iv[] = {
0x7D, 0x3F, 0x80, 0x6C, 0x35, 0x7E, 0x04, 0xC2,
0x92, 0x4C, 0x67, 0x30, 0xBA, 0xFA, 0xE0, 0xF7};
uint32_t iv_sz = sizeof(iv);
static TEE_Result sha256(
char *in, size_t in_sz,
char *out, uint32_t *out_sz)
{
TEE_Result res;
TEE_OperationHandle hDigest = NULL;
res = TEE_AllocateOperation(
&hDigest,
TEE_ALG_SHA256, TEE_MODE_DIGEST,
0);
if (res != TEE_SUCCESS) {
EMSG("[ERR]: TEE_AllocateOperation: 0x%x", res);
goto exit;
}
res = TEE_DigestDoFinal(
hDigest,
in, in_sz,
out, out_sz);
if (res != TEE_SUCCESS) {
EMSG("[ERR]: TEE_DigestDoFinal: 0x%x", res);
goto exit;
}
exit:
if (hDigest)
TEE_FreeOperation(hDigest);
return res;
}
/*
* Session Operations
*/
TEE_Result so_init(
char *pin, size_t pin_sz,
Session *session)
{
TEE_Result res;
TEE_ObjectHandle hSessionKey = NULL;
TEE_Attribute key_attr = { 0 };
uint32_t key_attr_count = 1;
char key[32]; // 256bit
uint32_t key_sz = sizeof(key);
res = sha256(
pin, pin_sz,
key, &key_sz);
if (res != TEE_SUCCESS) {
EMSG("[ERR]: sha256: %d", res);
goto exit;
}
res = TEE_AllocateTransientObject(
TEE_TYPE_AES, 256,
&hSessionKey);
if (res != TEE_SUCCESS) {
EMSG("[ERR]: SessionKey TEE_AllocateTransientObject: 0x%x", res);
goto exit;
}
TEE_InitRefAttribute(&key_attr, TEE_ATTR_SECRET_VALUE, key, key_sz);
res = TEE_PopulateTransientObject(
hSessionKey,
&key_attr, key_attr_count);
if (res != TEE_SUCCESS) {
EMSG("[ERR]: SessionKey TEE_PopulateTransientObject: 0x%x", res);
goto exit;
}
res = TEE_AllocateOperation(
&session->hSK_encrypt,
TEE_ALG_AES_CTR, TEE_MODE_ENCRYPT, 256);
if (res != TEE_SUCCESS) {
EMSG("[ERR]: SessionKey hSK_encrypt: TEE_AllocateOperation: 0x%x", res);
goto exit;
}
res = TEE_SetOperationKey(
session->hSK_encrypt,
hSessionKey);
if (res != TEE_SUCCESS) {
EMSG("[ERR]: SessionKey TEE_SetOperationKey(sk_encrypt): 0x%x", res);
goto exit;
}
res = TEE_AllocateOperation(
&session->hSK_decrypt,
TEE_ALG_AES_CTR, TEE_MODE_DECRYPT, 256);
if (res != TEE_SUCCESS) {
EMSG("[ERR]: SessionKey hSK_decrypt: TEE_AllocateOperation: 0x%x", res);
goto exit;
}
res = TEE_SetOperationKey(
session->hSK_decrypt,
hSessionKey);
if (res != TEE_SUCCESS) {
EMSG("[ERR]: SessionKey TEE_SetOperationKey(sk_decrypt): 0x%x", res);
goto exit;
}
exit:
if (hSessionKey)
TEE_FreeTransientObject(hSessionKey);
return res;
}
void so_free(
Session *session)
{
TEE_FreeOperation(session->hSK_encrypt);
TEE_FreeOperation(session->hSK_decrypt);
}
TEE_Result so_encrypt(
Session *session,
void *in, uint32_t in_sz,
void *out, uint32_t *out_sz)
{
TEE_CipherInit(session->hSK_encrypt, iv, iv_sz);
return TEE_CipherDoFinal(session->hSK_encrypt,
in, in_sz, // src
out, out_sz); // dest
}
TEE_Result so_decrypt(
Session *session,
void *in, uint32_t in_sz,
void *out, uint32_t *out_sz)
{
TEE_CipherInit(session->hSK_decrypt, iv, iv_sz);
return TEE_CipherDoFinal(session->hSK_decrypt,
in, in_sz, // src
out, out_sz); // dest
}

View File

@ -0,0 +1,28 @@
#include <tee_internal_api.h>
#ifndef OPERATIONS_H
#define OPERATIONS_H
typedef struct {
TEE_OperationHandle hSK_encrypt;
TEE_OperationHandle hSK_decrypt;
} Session;
TEE_Result so_init(
char *pin, size_t pin_sz,
Session *session);
void so_free(
Session *session);
TEE_Result so_encrypt(
Session *session,
void *inbuf, uint32_t inbuf_sz,
void *outbuf, uint32_t *outbuf_sz);
TEE_Result so_decrypt(
Session *session,
void *inbuf, uint32_t inbuf_sz,
void *outbuf, uint32_t *outbuf_sz);
#endif /*OPERATIONS_H*/

2
bliq_storage/ta/sub.mk Normal file
View File

@ -0,0 +1,2 @@
global-incdirs-y += include
srcs-y += bliq_storage_ta.c operations.c key_pair.c

View File

@ -0,0 +1,21 @@
/*
* The name of this file must not be modified
*/
#ifndef USER_TA_HEADER_DEFINES_H
#define USER_TA_HEADER_DEFINES_H
#include <bliq_storage_ta.h>
#define TA_UUID TA_BLIQ_STORAGE_UUID
#define TA_FLAGS (TA_FLAG_EXEC_DDR | TA_FLAG_SINGLE_INSTANCE)
#define TA_STACK_SIZE (2 * 1024)
#define TA_DATA_SIZE (32 * 1024)
#define TA_CURRENT_TA_EXT_PROPERTIES \
{ "gp.ta.description", USER_TA_PROP_TYPE_STRING, \
"A simple secure storage TA for BliQ" }, \
{ "gp.ta.version", USER_TA_PROP_TYPE_U32, &(const uint32_t){ 0x0010 } }
#endif /*USER_TA_HEADER_DEFINES_H*/

4
build-docker.sh Executable file
View File

@ -0,0 +1,4 @@
#!/usr/bin/env bash
set -euxo pipefail
docker build -t op-tee-quemu:latest .

9
run-docker.sh Executable file
View File

@ -0,0 +1,9 @@
#!/usr/bin/env bash
set -euxo pipefail
docker run \
--name op-tee-secstore \
--rm \
-v $(pwd)/bliq_storage:/optee/optee_examples/bliq_storage \
-e DISPLAY=docker.for.mac.host.internal:0 \
-it op-tee-quemu:latest

Binary file not shown.