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