custom-tee-storage/bliq_storage/host/main.c

347 lines
8.2 KiB
C
Raw Permalink Normal View History

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