1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "collector_func.h"
17
18 #include "securec.h"
19
20 #include "adaptor_log.h"
21 #include "adaptor_memory.h"
22 #include "attribute.h"
23 #include "buffer.h"
24
25 typedef enum CollectorState {
26 COLLECTOR_STATE_INIT = 0,
27 COLLECTOR_STATE_WAIT_ACK = 1,
28 COLLECTOR_STATE_WAIT_PIN = 2,
29 COLLECTOR_STATE_FINISH = 3,
30 } CollectorState;
31
32 typedef struct CollectorSchedule {
33 uint64_t scheduleId;
34 uint64_t timeStamp;
35 Buffer *selfUdid;
36 Buffer *peerUdid;
37 Buffer *peerPubKey;
38 Buffer *challenge;
39 Buffer *salt;
40 CollectorState state;
41 } CollectorSchedule;
42
43 static KeyPair *g_keyPair = NULL;
44 static Buffer *g_fwkPubKey = NULL;
45 static CollectorSchedule *g_collectorSchedule = NULL;
46
47 /* This is for example only, Should be implemented in trusted environment. */
GenerateCollectorKeyPair(void)48 int32_t GenerateCollectorKeyPair(void)
49 {
50 DestroyKeyPair(g_keyPair);
51 g_keyPair = GenerateEd25519KeyPair();
52 if (g_keyPair == NULL) {
53 LOG_ERROR("GenerateCollectorKeyPair fail");
54 return RESULT_GENERAL_ERROR;
55 }
56 LOG_INFO("GenerateCollectorKeyPair success");
57 return RESULT_SUCCESS;
58 }
59
DestroyCollectorKeyPair(void)60 void DestroyCollectorKeyPair(void)
61 {
62 LOG_INFO("DestroyCollectorKeyPair");
63 DestroyKeyPair(g_keyPair);
64 g_keyPair = NULL;
65 }
66
67 /* This is for example only, Should be implemented in trusted environment. */
DoGetCollectorExecutorInfo(PinExecutorInfo * pinExecutorInfo)68 int32_t DoGetCollectorExecutorInfo(PinExecutorInfo *pinExecutorInfo)
69 {
70 if (pinExecutorInfo == NULL) {
71 LOG_ERROR("check param fail!");
72 return RESULT_BAD_PARAM;
73 }
74 if (!IsEd25519KeyPairValid(g_keyPair)) {
75 LOG_ERROR("key pair not init!");
76 return RESULT_NEED_INIT;
77 }
78 uint32_t pubKeyLen = ED25519_FIX_PUBKEY_BUFFER_SIZE;
79 if (GetBufferData(g_keyPair->pubKey, pinExecutorInfo->pubKey, &pubKeyLen) != RESULT_SUCCESS) {
80 LOG_ERROR("GetBufferData fail!");
81 return RESULT_UNKNOWN;
82 }
83 pinExecutorInfo->esl = PIN_EXECUTOR_SECURITY_LEVEL;
84 pinExecutorInfo->maxTemplateAcl = PIN_CAPABILITY_LEVEL;
85 return RESULT_SUCCESS;
86 }
87
DoSetCollectorFwkParam(const uint8_t * fwkPubKey,uint32_t fwkPubKeySize)88 int32_t DoSetCollectorFwkParam(const uint8_t *fwkPubKey, uint32_t fwkPubKeySize)
89 {
90 if ((fwkPubKey == NULL) || (fwkPubKeySize != ED25519_FIX_PUBKEY_BUFFER_SIZE)) {
91 LOG_ERROR("DoSetCollectorFwkParam check param fail!");
92 return RESULT_BAD_PARAM;
93 }
94 DestroyBuffer(g_fwkPubKey);
95 g_fwkPubKey = CreateBufferByData(fwkPubKey, fwkPubKeySize);
96 if (g_fwkPubKey == NULL) {
97 LOG_ERROR("DoSetCollectorFwkParam create fwkPubKey fail!");
98 return RESULT_NO_MEMORY;
99 }
100 return RESULT_SUCCESS;
101 }
102
DestroyCollectorSchedule(void)103 static void DestroyCollectorSchedule(void)
104 {
105 if (g_collectorSchedule == NULL) {
106 return;
107 }
108 DestroyBuffer(g_collectorSchedule->selfUdid);
109 DestroyBuffer(g_collectorSchedule->peerUdid);
110 DestroyBuffer(g_collectorSchedule->peerPubKey);
111 DestroyBuffer(g_collectorSchedule->challenge);
112 DestroyBuffer(g_collectorSchedule->salt);
113 Free(g_collectorSchedule);
114 g_collectorSchedule= NULL;
115 }
116
GetCollectInfoFromSchedule(uint64_t scheduleId,const uint8_t * extraInfo,uint32_t extraInfoSize)117 static int32_t GetCollectInfoFromSchedule(uint64_t scheduleId, const uint8_t *extraInfo, uint32_t extraInfoSize)
118 {
119 Attribute *attribute = NULL;
120 int32_t result = VerifyAndGetDataAttribute(scheduleId, &attribute, g_fwkPubKey, extraInfo, extraInfoSize);
121 IF_TRUE_LOGE_AND_RETURN_VAL(result != RESULT_SUCCESS, result);
122
123 result = RESULT_GENERAL_ERROR;
124 g_collectorSchedule->selfUdid = GetBufferFromAttribute(attribute, ATTR_LOCAL_UDID, CONST_FWK_UDID_SIZE);
125 if (g_collectorSchedule->selfUdid == NULL) {
126 LOG_ERROR("get self udid fail!");
127 goto EXIT;
128 }
129 g_collectorSchedule->peerUdid = GetBufferFromAttribute(attribute, ATTR_PEER_UDID, CONST_FWK_UDID_SIZE);
130 if (g_collectorSchedule->peerUdid == NULL) {
131 LOG_ERROR("get peer udid fail!");
132 goto EXIT;
133 }
134 g_collectorSchedule->peerPubKey = GetBufferFromAttribute(
135 attribute, ATTR_PUBLIC_KEY, ED25519_FIX_PUBKEY_BUFFER_SIZE);
136 if (g_collectorSchedule->peerPubKey == NULL) {
137 LOG_ERROR("get peer public key fail!");
138 goto EXIT;
139 }
140 g_collectorSchedule->challenge = GetBufferFromAttribute(attribute, ATTR_CHALLENGE, CONST_CHALLENGE_LEN);
141 if (g_collectorSchedule->challenge == NULL) {
142 LOG_ERROR("get challenge fail!");
143 goto EXIT;
144 }
145
146 result = RESULT_SUCCESS;
147
148 EXIT:
149 FreeAttribute(&attribute);
150 return result;
151 }
152
InitCollectorSchedule(uint64_t scheduleId)153 static bool InitCollectorSchedule(uint64_t scheduleId)
154 {
155 g_collectorSchedule = Malloc(sizeof(CollectorSchedule));
156 if (g_collectorSchedule == NULL) {
157 LOG_ERROR("malloc CollectorSchedule fail!");
158 return false;
159 }
160 (void)memset_s(g_collectorSchedule, sizeof(CollectorSchedule), 0, sizeof(CollectorSchedule));
161 g_collectorSchedule->scheduleId = scheduleId;
162 return true;
163 }
164
DoCollect(uint64_t scheduleId,const uint8_t * extraInfo,uint32_t extraInfoSize,uint8_t * msg,uint32_t * msgSize)165 int32_t DoCollect(
166 uint64_t scheduleId, const uint8_t *extraInfo, uint32_t extraInfoSize, uint8_t *msg, uint32_t *msgSize)
167 {
168 LOG_INFO("DoCollect start %{public}x", (uint16_t)scheduleId);
169 if ((extraInfo == NULL) || (extraInfoSize == 0) || (extraInfoSize > MAX_EXECUTOR_MSG_LEN) ||
170 (msg == NULL) || (msgSize == NULL) || ((*msgSize) == 0)) {
171 LOG_ERROR("check param fail!");
172 return RESULT_BAD_PARAM;
173 }
174 DestroyCollectorSchedule();
175 if (!InitCollectorSchedule(scheduleId)) {
176 LOG_ERROR("InitCollectorSchedule fail!");
177 return RESULT_GENERAL_ERROR;
178 }
179
180 int32_t result = GetCollectInfoFromSchedule(scheduleId, extraInfo, extraInfoSize);
181 if (result != RESULT_SUCCESS) {
182 LOG_ERROR("GetCollectInfoFromSchedule fail!");
183 goto ERROR;
184 }
185
186 Attribute *attribute = GetAttributeDataBase(g_collectorSchedule->scheduleId, REMOTE_PIN_COLLECTOR_SYNC);
187 if (attribute == NULL) {
188 LOG_ERROR("GetAttributeDataBase fail!");
189 result = RESULT_GENERAL_ERROR;
190 goto ERROR;
191 }
192
193 result = FormatTlvMsg(attribute, g_keyPair, msg, msgSize);
194 FreeAttribute(&attribute);
195 if (result != RESULT_SUCCESS) {
196 LOG_ERROR("FormatTlvMsg fail!");
197 goto ERROR;
198 }
199 g_collectorSchedule->state = COLLECTOR_STATE_WAIT_ACK;
200 return RESULT_SUCCESS;
201
202 ERROR:
203 DestroyCollectorSchedule();
204 return result;
205 }
206
DoCancelCollect()207 int32_t DoCancelCollect()
208 {
209 LOG_INFO("DoCancelCollect start");
210 DestroyCollectorSchedule();
211 return RESULT_SUCCESS;
212 }
213
CheckCurrentSchedule(uint64_t scheduleId,CollectorState state)214 static bool CheckCurrentSchedule(uint64_t scheduleId, CollectorState state)
215 {
216 if (g_collectorSchedule == NULL) {
217 LOG_ERROR("schedule not exist");
218 return false;
219 }
220 if (g_collectorSchedule->scheduleId != scheduleId) {
221 LOG_ERROR("schedule:%{public}x not match current:%{public}x",
222 (uint16_t)scheduleId, (uint16_t)(g_collectorSchedule->scheduleId));
223 return false;
224 }
225 if (g_collectorSchedule->state != state) {
226 LOG_ERROR("state:%{public}d not match current:%{public}d", state, g_collectorSchedule->state);
227 return false;
228 }
229 return true;
230 }
231
GetAlgoParam(const Attribute * data,AlgoParamOut * algoParam)232 static int32_t GetAlgoParam(const Attribute *data, AlgoParamOut *algoParam)
233 {
234 int32_t result = GetAttributeUint64(data, ATTR_PIN_SUB_TYPE, &(algoParam->subType));
235 if (result != RESULT_SUCCESS) {
236 LOG_ERROR("get sub type fail");
237 return result;
238 }
239 result = GetAttributeUint32(data, PIN_ATTR_ALGO_VERSION, &(algoParam->algoVersion));
240 if (result != RESULT_SUCCESS) {
241 LOG_ERROR("get algo version fail");
242 return result;
243 }
244 Uint8Array uint8Array = {
245 .data = algoParam->algoParameter,
246 .len = sizeof(algoParam->algoParameter),
247 };
248 result = GetAttributeUint8Array(data, PIN_ATTR_ALGO_PARAM, &uint8Array);
249 if (result != RESULT_SUCCESS) {
250 LOG_ERROR("get algo param fail");
251 return result;
252 }
253 if (uint8Array.len != sizeof(algoParam->algoParameter)) {
254 LOG_ERROR("get algo param fail");
255 return RESULT_GENERAL_ERROR;
256 }
257 if (memcpy_s(algoParam->challenge, sizeof(algoParam->challenge),
258 g_collectorSchedule->challenge->buf, g_collectorSchedule->challenge->contentSize) != EOK) {
259 LOG_ERROR("copy challenge fail");
260 return RESULT_GENERAL_ERROR;
261 }
262 return RESULT_SUCCESS;
263 }
264
DoSendMessageToCollector(uint64_t scheduleId,const uint8_t * msg,uint32_t msgSize,AlgoParamOut * algoParam)265 int32_t DoSendMessageToCollector(uint64_t scheduleId, const uint8_t *msg, uint32_t msgSize, AlgoParamOut *algoParam)
266 {
267 LOG_INFO("SendMessageToCollector start schedule:%{public}x", (uint16_t)scheduleId);
268 if (!CheckCurrentSchedule(scheduleId, COLLECTOR_STATE_WAIT_ACK) ||
269 (msg == NULL) || (msgSize == 0) || (algoParam == NULL)) {
270 LOG_ERROR("check param fail!");
271 return RESULT_BAD_PARAM;
272 }
273 Attribute *data = NULL;
274 int32_t result = VerifyAndGetDataAttribute(scheduleId, &data, g_collectorSchedule->peerPubKey, msg, msgSize);
275 if (result != RESULT_SUCCESS) {
276 LOG_ERROR("VerifyAndGetDataAttribute fail");
277 return result;
278 }
279
280 result = CheckAttributeDataBase(
281 data, g_collectorSchedule->scheduleId, REMOTE_PIN_VERIFIER_ACK, &(g_collectorSchedule->timeStamp));
282 if (result != RESULT_SUCCESS) {
283 LOG_ERROR("CheckAttributeDataBase fail");
284 goto EXIT;
285 }
286
287 g_collectorSchedule->salt = GetBufferFromAttribute(data, PIN_ATTR_KEK_SALT, CONST_KEK_SALT_SIZE);
288 if (g_collectorSchedule->salt == NULL) {
289 LOG_ERROR("get kek salt fail");
290 result = RESULT_GENERAL_ERROR;
291 goto EXIT;
292 }
293
294 result = GetAlgoParam(data, algoParam);
295 if (result != RESULT_SUCCESS) {
296 LOG_ERROR("GetAlgoParam fail");
297 goto EXIT;
298 }
299
300 g_collectorSchedule->state = COLLECTOR_STATE_WAIT_PIN;
301
302 EXIT:
303 FreeAttribute(&data);
304 return result;
305 }
306
DestroyAesGcmParam(AesGcmParam * aesGcmParam)307 static void DestroyAesGcmParam(AesGcmParam *aesGcmParam)
308 {
309 DestroyBuffer(aesGcmParam->key);
310 aesGcmParam->key = NULL;
311 DestroyBuffer(aesGcmParam->iv);
312 aesGcmParam->iv = NULL;
313 DestroyBuffer(aesGcmParam->aad);
314 aesGcmParam->aad = NULL;
315 }
316
GetAesGcmParam(AesGcmParam * aesGcmParam)317 static bool GetAesGcmParam(AesGcmParam *aesGcmParam)
318 {
319 (void)memset_s(aesGcmParam, sizeof(AesGcmParam), 0, sizeof(AesGcmParam));
320 aesGcmParam->aad = CreateBufferByData((const uint8_t *)CONST_KEK_AAD, CONST_KEK_AAD_SIZE);
321 if (aesGcmParam->aad == NULL) {
322 LOG_ERROR("create aad buffer fail");
323 goto ERROR;
324 }
325 aesGcmParam->iv = CreateBufferBySize(AES_GCM_256_IV_SIZE);
326 if (aesGcmParam->iv == NULL) {
327 LOG_ERROR("create iv buffer fail");
328 goto ERROR;
329 }
330 if (SecureRandom(aesGcmParam->iv->buf, aesGcmParam->iv->maxSize) != RESULT_SUCCESS) {
331 LOG_ERROR("SecureRandom iv fail");
332 goto ERROR;
333 }
334 aesGcmParam->iv->contentSize = aesGcmParam->iv->maxSize;
335 if (GetDistributeKey(g_collectorSchedule->peerUdid, g_collectorSchedule->salt, &(aesGcmParam->key)) !=
336 RESULT_SUCCESS) {
337 LOG_ERROR("GetDistributeKey fail");
338 goto ERROR;
339 }
340 return true;
341
342 ERROR:
343 DestroyAesGcmParam(aesGcmParam);
344 return false;
345 }
346
SetEncryptParam(Attribute * attribute,uint8_t * pinData,uint32_t pinDataSize)347 static int32_t SetEncryptParam(Attribute *attribute, uint8_t *pinData, uint32_t pinDataSize)
348 {
349 AesGcmParam aesGcmParam = {};
350 if (!GetAesGcmParam(&aesGcmParam)) {
351 LOG_ERROR("GetAesGcmParam fail");
352 return RESULT_GENERAL_ERROR;
353 }
354 Buffer plainText = GetTmpBuffer(pinData, pinDataSize, pinDataSize);
355 Buffer *cipherText = NULL;
356 Buffer *tag = NULL;
357 int32_t result = AesGcm256Encrypt(&plainText, &aesGcmParam, &cipherText, &tag);
358 if (result != RESULT_SUCCESS) {
359 LOG_ERROR("AesGcm256Encrypt fail");
360 goto EXIT;
361 }
362 result = SetBufferToAttribute(attribute, PIN_ATTR_KEK_IV, aesGcmParam.iv);
363 if (result != RESULT_SUCCESS) {
364 LOG_ERROR("set attribute iv fail");
365 goto EXIT;
366 }
367 result = SetBufferToAttribute(attribute, PIN_ATTR_KEK_SECRET, cipherText);
368 if (result != RESULT_SUCCESS) {
369 LOG_ERROR("set attribute secret fail");
370 goto EXIT;
371 }
372 result = SetBufferToAttribute(attribute, PIN_ATTR_KEK_TAG, tag);
373 if (result != RESULT_SUCCESS) {
374 LOG_ERROR("set attribute tag fail");
375 goto EXIT;
376 }
377
378 EXIT:
379 DestroyAesGcmParam(&aesGcmParam);
380 DestroyBuffer(cipherText);
381 DestroyBuffer(tag);
382 return result;
383 }
384
DoSetDataToCollector(uint64_t scheduleId,uint8_t * pinData,uint32_t pinDataSize,uint8_t * msg,uint32_t * msgSize)385 int32_t DoSetDataToCollector(
386 uint64_t scheduleId, uint8_t *pinData, uint32_t pinDataSize, uint8_t *msg, uint32_t *msgSize)
387 {
388 LOG_INFO("DoSetDataToCollector start schedule:%{public}x", (uint16_t)scheduleId);
389 int32_t result = RESULT_BAD_PARAM;
390 Attribute *attribute = NULL;
391 if (!CheckCurrentSchedule(scheduleId, COLLECTOR_STATE_WAIT_PIN) ||
392 (pinData == NULL) || (pinDataSize != CONST_PIN_DATA_LEN) || (msg == NULL) || ((*msgSize) == 0)) {
393 LOG_ERROR("check param fail!");
394 goto EXIT;
395 }
396
397 attribute = GetAttributeDataBase(scheduleId, REMOTE_PIN_COLLECTOR_ACK);
398 if (attribute == NULL) {
399 LOG_ERROR("GetAttributeDataBase fail");
400 result = RESULT_GENERAL_ERROR;
401 goto EXIT;
402 }
403 result = SetEncryptParam(attribute, pinData, pinDataSize);
404 if (result != RESULT_SUCCESS) {
405 LOG_ERROR("SetEncryptParam fail");
406 goto EXIT;
407 }
408 result = FormatTlvMsg(attribute, g_keyPair, msg, msgSize);
409 if (result != RESULT_SUCCESS) {
410 LOG_ERROR("FormatTlvMsg fail");
411 goto EXIT;
412 }
413
414 g_collectorSchedule->state = COLLECTOR_STATE_FINISH;
415
416 EXIT:
417 if ((pinData != NULL) && (pinDataSize != 0)) {
418 (void)memset_s(pinData, pinDataSize, 0, pinDataSize);
419 }
420 FreeAttribute(&attribute);
421 return result;
422 }
423