1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3 * Copyright (c) 2019, Linaro Limited
4 */
5
6 #include <pta_system.h>
7 #include <string.h>
8 #include <tee_internal_api.h>
9
10 #include "derive_key_taf.h"
11
12 #define TA_DERIVED_KEY_MIN_SIZE 16
13 #define TA_DERIVED_KEY_MAX_SIZE 32
14 #define TA_DERIVED_EXTRA_DATA_MAX_SIZE 1024
15
16 static const TEE_UUID system_uuid = PTA_SYSTEM_UUID;
17
18 /*
19 * Helper function that just derives a key.
20 */
derive_unique_key(TEE_TASessionHandle session,uint8_t * key,uint16_t key_size,uint8_t * extra,uint16_t extra_size)21 static TEE_Result derive_unique_key(TEE_TASessionHandle session,
22 uint8_t *key, uint16_t key_size,
23 uint8_t *extra, uint16_t extra_size)
24 {
25 TEE_Param params[TEE_NUM_PARAMS] = { 0 };
26 TEE_Result res = TEE_ERROR_GENERIC;
27 uint32_t ret_origin = 0;
28 uint32_t param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
29 TEE_PARAM_TYPE_MEMREF_OUTPUT,
30 TEE_PARAM_TYPE_NONE,
31 TEE_PARAM_TYPE_NONE);
32 if (extra && extra_size > 0) {
33 params[0].memref.buffer = extra;
34 params[0].memref.size = extra_size;
35 }
36
37 params[1].memref.buffer = key;
38 params[1].memref.size = key_size;
39
40 res = TEE_InvokeTACommand(session, TEE_TIMEOUT_INFINITE,
41 PTA_SYSTEM_DERIVE_TA_UNIQUE_KEY,
42 param_types, params, &ret_origin);
43 if (res != TEE_SUCCESS)
44 EMSG("Failure when calling PTA_SYSTEM_DERIVE_TA_UNIQUE_KEY");
45
46 return res;
47 }
48
derive_ta_unique_key_test(uint32_t param_types,TEE_Param params[TEE_NUM_PARAMS]__unused)49 TEE_Result derive_ta_unique_key_test(uint32_t param_types,
50 TEE_Param params[TEE_NUM_PARAMS] __unused)
51 {
52 size_t i = 0;
53 TEE_Result res_final = TEE_SUCCESS;
54 TEE_Result res = TEE_ERROR_GENERIC;
55 TEE_TASessionHandle session = TEE_HANDLE_NULL;
56 uint8_t big_key[64] = { };
57 uint8_t extra_key_data[] = { "My dummy data" };
58 uint8_t key1[32] = { };
59 uint8_t key2[32] = { };
60 uint32_t ret_origin = 0;
61
62 if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE,
63 TEE_PARAM_TYPE_NONE,
64 TEE_PARAM_TYPE_NONE,
65 TEE_PARAM_TYPE_NONE))
66 return TEE_ERROR_BAD_PARAMETERS;
67
68 res = TEE_OpenTASession(&system_uuid, TEE_TIMEOUT_INFINITE, 0, NULL,
69 &session, &ret_origin);
70
71 if (res != TEE_SUCCESS)
72 return res;
73
74 /*
75 * Testing for successful calls to the PTA and that two calls with same
76 * input data generates the same output data (keys).
77 */
78 res = derive_unique_key(session, key1, sizeof(key1), NULL, 0);
79 if (res != TEE_SUCCESS)
80 res_final = TEE_ERROR_GENERIC;
81
82 res = derive_unique_key(session, key2, sizeof(key2), NULL, 0);
83 if (res != TEE_SUCCESS)
84 res_final = TEE_ERROR_GENERIC;
85
86 if (TEE_MemCompare(key1, key2, sizeof(key1)) != 0)
87 res_final = TEE_ERROR_GENERIC;
88
89 TEE_MemFill(key1, 0, sizeof(key1));
90 TEE_MemFill(key2, 0, sizeof(key2));
91
92 /*
93 * Testing for successful calls to the PTA and that two calls with same
94 * input data generates the same output data (keys). Here we are using
95 * extra data also.
96 */
97 res = derive_unique_key(session, key1, sizeof(key1), extra_key_data,
98 sizeof(extra_key_data));
99 if (res != TEE_SUCCESS)
100 res_final = TEE_ERROR_GENERIC;
101
102 res = derive_unique_key(session, key2, sizeof(key2), extra_key_data,
103 sizeof(extra_key_data));
104 if (res != TEE_SUCCESS)
105 res_final = TEE_ERROR_GENERIC;
106
107 if (TEE_MemCompare(key1, key2, sizeof(key1)) != 0)
108 res_final = TEE_ERROR_GENERIC;
109
110 TEE_MemFill(key1, 0, sizeof(key1));
111 TEE_MemFill(key2, 0, sizeof(key2));
112
113 /*
114 * Testing for successful calls to the PTA and that two calls with
115 * different input data do not generate the same output data (keys). We
116 * do that by using one key with and one key without extra data.
117 */
118 res = derive_unique_key(session, key1, sizeof(key1), extra_key_data,
119 sizeof(extra_key_data));
120 if (res != TEE_SUCCESS)
121 res_final = TEE_ERROR_GENERIC;
122
123 res = derive_unique_key(session, key2, sizeof(key2), NULL, 0);
124 if (res != TEE_SUCCESS)
125 res_final = TEE_ERROR_GENERIC;
126
127 /* They should not be equal */
128 if (TEE_MemCompare(key1, key2, sizeof(key1)) == 0)
129 res_final = TEE_ERROR_GENERIC;
130
131 TEE_MemFill(key1, 0, sizeof(key1));
132 TEE_MemFill(key2, 0, sizeof(key2));
133
134 /*
135 * Testing limits for extra data size (if this would success, then we
136 * would overwrite the buffer extra_key_data also).
137 */
138 res = derive_unique_key(session, key1, sizeof(key1), extra_key_data,
139 TA_DERIVED_EXTRA_DATA_MAX_SIZE + 1);
140 /* This shall fail */
141 if (res == TEE_SUCCESS)
142 res_final = TEE_ERROR_GENERIC;
143
144 TEE_MemFill(key1, 0, sizeof(key1));
145
146 /* Testing limits. */
147 for (i = 0; i < sizeof(big_key); i++) {
148 uint8_t *extra = NULL;
149 uint8_t extra_size = 0;
150
151 TEE_MemFill(big_key, 0, sizeof(big_key));
152
153 /* Alternate between using and not using extra data. */
154 if (i % 2) {
155 extra = extra_key_data;
156 extra_size = sizeof(extra_key_data);
157 }
158
159 res = derive_unique_key(session, big_key, i, extra, extra_size);
160 if (i < TA_DERIVED_KEY_MIN_SIZE) {
161 if (res != TEE_SUCCESS)
162 continue;
163
164 EMSG("Small key test iteration %zu failed", i);
165 res_final = TEE_ERROR_GENERIC;
166 break;
167 }
168
169 if (i > TA_DERIVED_KEY_MAX_SIZE) {
170 if (res != TEE_SUCCESS)
171 continue;
172
173 EMSG("Big key test iteration %zu failed", i);
174 res_final = TEE_ERROR_GENERIC;
175 break;
176 }
177
178 if (res != TEE_SUCCESS) {
179 res_final = TEE_ERROR_GENERIC;
180 break;
181 }
182 }
183
184 TEE_CloseTASession(session);
185
186 return res_final;
187 }
188
derive_ta_unique_key_test_shm(uint32_t param_types,TEE_Param params[TEE_NUM_PARAMS])189 TEE_Result derive_ta_unique_key_test_shm(uint32_t param_types,
190 TEE_Param params[TEE_NUM_PARAMS])
191 {
192 TEE_Result res = TEE_ERROR_GENERIC;
193 TEE_TASessionHandle session = TEE_HANDLE_NULL;
194 uint32_t ret_origin = 0;
195
196 if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
197 TEE_PARAM_TYPE_MEMREF_OUTPUT,
198 TEE_PARAM_TYPE_NONE,
199 TEE_PARAM_TYPE_NONE))
200 return TEE_ERROR_BAD_PARAMETERS;
201
202 res = TEE_OpenTASession(&system_uuid, TEE_TIMEOUT_INFINITE, 0, NULL,
203 &session, &ret_origin);
204
205 if (res != TEE_SUCCESS)
206 return res;
207
208 /*
209 * Testing for unsuccessful calls to the PTA. They should be
210 * unsuccessful since we are using an out buffer coming from normal
211 * world.
212 */
213 res = TEE_InvokeTACommand(session, TEE_TIMEOUT_INFINITE,
214 PTA_SYSTEM_DERIVE_TA_UNIQUE_KEY,
215 param_types, params, &ret_origin);
216 TEE_CloseTASession(session);
217
218 return res;
219 }
220