blob: 2bf990ac14278819e8c82149ea4fc6209e2d335f [file] [log] [blame]
/*
* Copyright (c) 2016, 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>
/* For the UUID (found in the TA's h-file(s)) */
#include <hello_world_ta.h>
#include <string.h>
static const TEEC_UUID cryptoTEEAPP =
{
0x3E93632E, 0xA710, 0x469E,
{ 0xAC, 0xC8, 0x5E, 0xDF, 0x8C, 0x85, 0x90, 0xE1 }
};
#define CMD_ENCRYPT_INIT 1
#define CMD_ENCRYPT_UPDATE 2
#define CMD_ENCRYPT_FINAL 3
#define CMD_DIGEST_INIT 4
#define CMD_DIGEST_UPDATE 5
#define CMD_DIGEST_FINAL 6
TEEC_Result libraryFunction(uint8_t const * inputBuffer, uint32_t inputSize, uint8_t* outputBuffer, uint32_t outputSize, uint8_t* digestBuffer)
{
/* Allocate TEE Client structures on the stack. */
TEEC_Context context;
TEEC_Session session;
TEEC_Operation operation;
TEEC_Result result;
TEEC_SharedMemory commsSM;
TEEC_SharedMemory inputSM;
TEEC_SharedMemory outputSM;
uint8_t* ivPtr;
result = TEEC_InitializeContext(NULL, &context);
if (result != TEEC_SUCCESS)
{
goto cleanup1;
}
/* ========================================================================
Open session with TEE application
======================================================================== */
/* Open a Session with the TEE application. */
result = TEEC_OpenSession(&context, &session, &cryptoTEEAPP, TEEC_LOGIN_USER,NULL, NULL, NULL);
if (result != TEEC_SUCCESS)
{
goto cleanup2;
}
commsSM.size = 20;
commsSM.flags = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT;
result = TEEC_AllocateSharedMemory(&context, &commsSM);
if (result != TEEC_SUCCESS)
{
goto cleanup3;
}
/* Bulk input buffer. */
inputSM.size = inputSize;
inputSM.flags = TEEC_MEM_INPUT;
/* Use TEE Client API to register the underlying memory buffer. */
inputSM.buffer = (uint8_t*)inputBuffer;
result = TEEC_RegisterSharedMemory(&context, &inputSM);
if (result != TEEC_SUCCESS)
{
goto cleanup4;
}
outputSM.size = outputSize;
outputSM.flags = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT;
outputSM.buffer = outputBuffer;
/* Use TEE Client API to register the underlying memory buffer. */
result = TEEC_RegisterSharedMemory(&context, &outputSM);
if (result != TEEC_SUCCESS)
{
goto cleanup5;
}
/* ========================================================================
Perform cryptographic operation initialization commands
======================================================================== */
/* Start the encrypt operation within the TEE application. */
operation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_MEMREF_PARTIAL_INPUT, TEEC_NONE, TEEC_NONE);
/* Write key ID (example uses key ID = 1) in parameter #1 */
operation.params[0].value.a = 1;
operation.params[1].memref.parent = &commsSM;
operation.params[1].memref.offset = 0;
operation.params[1].memref.size = 16;
/* Write IV (example uses an IV of all zeros) in to Memory buffer. */
ivPtr = (uint8_t*)commsSM.buffer;
memset(ivPtr, 0, 16);
/* Start the encrypt operation within the TEE application. */
result = TEEC_InvokeCommand(&session, CMD_ENCRYPT_INIT, &operation,NULL);
if (result != TEEC_SUCCESS)
{
goto cleanup6;
}
/* Start the digest operation within the TEE application. */
result = TEEC_InvokeCommand(&session, CMD_DIGEST_INIT, NULL, NULL);
if (result != TEEC_SUCCESS)
{
goto cleanup6;
}
result = TEEC_InvokeCommand(&session, CMD_ENCRYPT_FINAL, NULL, NULL);
if (result != TEEC_SUCCESS)
{
goto cleanup6;
}
operation.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_PARTIAL_OUTPUT, TEEC_NONE, TEEC_NONE, TEEC_NONE);
operation.params[0].memref.parent = &commsSM;
operation.params[0].memref.offset = 0;
operation.params[0].memref.size = 20;
result = TEEC_InvokeCommand(&session, CMD_DIGEST_FINAL,&operation,NULL);
if (result != TEEC_SUCCESS)
{
goto cleanup6;
}
/* Transfer digest in to user buffer. */
memcpy(digestBuffer, commsSM.buffer, 20);
/* ========================================================================
Tidyup resources
======================================================================== */
cleanup6:
TEEC_ReleaseSharedMemory(&outputSM);
cleanup5:
TEEC_ReleaseSharedMemory(&inputSM);
cleanup4:
TEEC_ReleaseSharedMemory(&commsSM);
cleanup3:
TEEC_CloseSession(&session);
cleanup2:
TEEC_FinalizeContext(&context);
cleanup1:
return result;
}
int main(void)
{
TEEC_Result res;
TEEC_Context ctx;
TEEC_Session sess;
TEEC_Operation op;
TEEC_UUID uuid = TA_HELLO_WORLD_UUID;
uint32_t err_origin;
/* Initialize a context connecting us to the TEE */
res = TEEC_InitializeContext(NULL, &ctx);
if (res != TEEC_SUCCESS)
errx(1, "TEEC_InitializeContext failed with code 0x%x", res);
/*
* Open a session to the "hello world" TA, the TA will print "hello
* world!" in the log when the session is created.
*/
res = TEEC_OpenSession(&ctx, &sess, &uuid,
TEEC_LOGIN_PUBLIC, NULL, NULL, &err_origin);
if (res != TEEC_SUCCESS)
errx(1, "TEEC_Opensession failed with code 0x%x origin 0x%x",
res, err_origin);
/*
* Execute a function in the TA by invoking it, in this case
* we're incrementing a number.
*
* The value of command ID part and how the parameters are
* interpreted is part of the interface provided by the TA.
*/
/* Clear the TEEC_Operation struct */
memset(&op, 0, sizeof(op));
/*
* Prepare the argument. Pass a value in the first parameter,
* the remaining three parameters are unused.
*/
op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_NONE,
TEEC_NONE, TEEC_NONE);
op.params[0].value.a = 42;
/*
* TA_HELLO_WORLD_CMD_INC_VALUE is the actual function in the TA to be
* called.
*/
printf("Invoking TA to increment %d\n", op.params[0].value.a);
res = TEEC_InvokeCommand(&sess, TA_HELLO_WORLD_CMD_INC_VALUE, &op,
&err_origin);
if (res != TEEC_SUCCESS)
errx(1, "TEEC_InvokeCommand failed with code 0x%x origin 0x%x",
res, err_origin);
printf("TA incremented value to %d\n", op.params[0].value.a);
/*
* We're done with the TA, close the session and
* destroy the context.
*
* The TA will print "Goodbye!" in the log when the
* session is closed.
*/
TEEC_CloseSession(&sess);
TEEC_FinalizeContext(&ctx);
return 0;
}