custom-tee-storage/bliq_storage/ta/bliq_storage_ta.c

561 lines
12 KiB
C
Raw Permalink Normal View History

2024-03-21 22:12:03 +01:00
#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;
}
}