561 lines
12 KiB
C
561 lines
12 KiB
C
#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;
|
|
}
|
|
}
|