1 /*
2 * Copyright (c) 2017, Linaro Limited
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 #include <err.h>
29 #include <stdio.h>
30 #include <string.h>
31
32 /* OP-TEE TEE client API (built by optee_client) */
33 #include <tee_client_api.h>
34
35 /* For the UUID (found in the TA's h-file(s)) */
36 #include <aes_ta.h>
37
38 #define AES_TEST_BUFFER_SIZE 4096
39 #define AES_TEST_KEY_SIZE 16
40 #define AES_BLOCK_SIZE 16
41
42 #define DECODE 0
43 #define ENCODE 1
44
45 /* TEE resources */
46 struct test_ctx {
47 TEEC_Context ctx;
48 TEEC_Session sess;
49 };
50
prepare_tee_session(struct test_ctx * ctx)51 void prepare_tee_session(struct test_ctx *ctx)
52 {
53 TEEC_UUID uuid = TA_AES_UUID;
54 uint32_t origin;
55 TEEC_Result res;
56
57 /* Initialize a context connecting us to the TEE */
58 res = TEEC_InitializeContext(NULL, &ctx->ctx);
59 if (res != TEEC_SUCCESS)
60 errx(1, "TEEC_InitializeContext failed with code 0x%x", res);
61
62 /* Open a session with the TA */
63 res = TEEC_OpenSession(&ctx->ctx, &ctx->sess, &uuid,
64 TEEC_LOGIN_PUBLIC, NULL, NULL, &origin);
65 if (res != TEEC_SUCCESS)
66 errx(1, "TEEC_Opensession failed with code 0x%x origin 0x%x",
67 res, origin);
68 }
69
terminate_tee_session(struct test_ctx * ctx)70 void terminate_tee_session(struct test_ctx *ctx)
71 {
72 TEEC_CloseSession(&ctx->sess);
73 TEEC_FinalizeContext(&ctx->ctx);
74 }
75
prepare_aes(struct test_ctx * ctx,int encode)76 void prepare_aes(struct test_ctx *ctx, int encode)
77 {
78 TEEC_Operation op;
79 uint32_t origin;
80 TEEC_Result res;
81
82 memset(&op, 0, sizeof(op));
83 op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT,
84 TEEC_VALUE_INPUT,
85 TEEC_VALUE_INPUT,
86 TEEC_NONE);
87
88 op.params[0].value.a = TA_AES_ALGO_CTR;
89 op.params[1].value.a = TA_AES_SIZE_128BIT;
90 op.params[2].value.a = encode ? TA_AES_MODE_ENCODE :
91 TA_AES_MODE_DECODE;
92
93 res = TEEC_InvokeCommand(&ctx->sess, TA_AES_CMD_PREPARE,
94 &op, &origin);
95 if (res != TEEC_SUCCESS)
96 errx(1, "TEEC_InvokeCommand(PREPARE) failed 0x%x origin 0x%x",
97 res, origin);
98 }
99
set_key(struct test_ctx * ctx,char * key,size_t key_sz)100 void set_key(struct test_ctx *ctx, char *key, size_t key_sz)
101 {
102 TEEC_Operation op;
103 uint32_t origin;
104 TEEC_Result res;
105
106 memset(&op, 0, sizeof(op));
107 op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT,
108 TEEC_NONE, TEEC_NONE, TEEC_NONE);
109
110 op.params[0].tmpref.buffer = key;
111 op.params[0].tmpref.size = key_sz;
112
113 res = TEEC_InvokeCommand(&ctx->sess, TA_AES_CMD_SET_KEY,
114 &op, &origin);
115 if (res != TEEC_SUCCESS)
116 errx(1, "TEEC_InvokeCommand(SET_KEY) failed 0x%x origin 0x%x",
117 res, origin);
118 }
119
set_iv(struct test_ctx * ctx,char * iv,size_t iv_sz)120 void set_iv(struct test_ctx *ctx, char *iv, size_t iv_sz)
121 {
122 TEEC_Operation op;
123 uint32_t origin;
124 TEEC_Result res;
125
126 memset(&op, 0, sizeof(op));
127 op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT,
128 TEEC_NONE, TEEC_NONE, TEEC_NONE);
129 op.params[0].tmpref.buffer = iv;
130 op.params[0].tmpref.size = iv_sz;
131
132 res = TEEC_InvokeCommand(&ctx->sess, TA_AES_CMD_SET_IV,
133 &op, &origin);
134 if (res != TEEC_SUCCESS)
135 errx(1, "TEEC_InvokeCommand(SET_IV) failed 0x%x origin 0x%x",
136 res, origin);
137 }
138
cipher_buffer(struct test_ctx * ctx,char * in,char * out,size_t sz)139 void cipher_buffer(struct test_ctx *ctx, char *in, char *out, size_t sz)
140 {
141 TEEC_Operation op;
142 uint32_t origin;
143 TEEC_Result res;
144
145 memset(&op, 0, sizeof(op));
146 op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT,
147 TEEC_MEMREF_TEMP_OUTPUT,
148 TEEC_NONE, TEEC_NONE);
149 op.params[0].tmpref.buffer = in;
150 op.params[0].tmpref.size = sz;
151 op.params[1].tmpref.buffer = out;
152 op.params[1].tmpref.size = sz;
153
154 res = TEEC_InvokeCommand(&ctx->sess, TA_AES_CMD_CIPHER,
155 &op, &origin);
156 if (res != TEEC_SUCCESS)
157 errx(1, "TEEC_InvokeCommand(CIPHER) failed 0x%x origin 0x%x",
158 res, origin);
159 }
160
main(void)161 int main(void)
162 {
163 struct test_ctx ctx;
164 char key[AES_TEST_KEY_SIZE];
165 char iv[AES_BLOCK_SIZE];
166 char clear[AES_TEST_BUFFER_SIZE];
167 char ciph[AES_TEST_BUFFER_SIZE];
168 char temp[AES_TEST_BUFFER_SIZE];
169
170 printf("Prepare session with the TA\n");
171 prepare_tee_session(&ctx);
172
173 printf("Prepare encode operation\n");
174 prepare_aes(&ctx, ENCODE);
175
176 printf("Load key in TA\n");
177 memset(key, 0xa5, sizeof(key)); /* Load some dummy value */
178 set_key(&ctx, key, AES_TEST_KEY_SIZE);
179
180 printf("Reset ciphering operation in TA (provides the initial vector)\n");
181 memset(iv, 0, sizeof(iv)); /* Load some dummy value */
182 set_iv(&ctx, iv, AES_BLOCK_SIZE);
183
184 printf("Encode buffer from TA\n");
185 memset(clear, 0x5a, sizeof(clear)); /* Load some dummy value */
186 cipher_buffer(&ctx, clear, ciph, AES_TEST_BUFFER_SIZE);
187
188 printf("Prepare decode operation\n");
189 prepare_aes(&ctx, DECODE);
190
191 printf("Load key in TA\n");
192 memset(key, 0xa5, sizeof(key)); /* Load some dummy value */
193 set_key(&ctx, key, AES_TEST_KEY_SIZE);
194
195 printf("Reset ciphering operation in TA (provides the initial vector)\n");
196 memset(iv, 0, sizeof(iv)); /* Load some dummy value */
197 set_iv(&ctx, iv, AES_BLOCK_SIZE);
198
199 printf("Decode buffer from TA\n");
200 cipher_buffer(&ctx, ciph, temp, AES_TEST_BUFFER_SIZE);
201
202 /* Check decoded is the clear content */
203 if (memcmp(clear, temp, AES_TEST_BUFFER_SIZE))
204 printf("Clear text and decoded text differ => ERROR\n");
205 else
206 printf("Clear text and decoded text match\n");
207
208 terminate_tee_session(&ctx);
209 return 0;
210 }
211