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