#include #include #include #include #include "operations.h" #include "key_pair.h" #include 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; } }