1 /*
2 * Copyright (c) 2022 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 "pin_db.h"
17 #include <inttypes.h>
18 #include "adaptor_algorithm.h"
19 #include "adaptor_memory.h"
20 #include "adaptor_time.h"
21 #include "defines.h"
22 #include "file_operator.h"
23 #include "securec.h"
24
25 static PinDb g_pinDbOp = {CURRENT_VERSION, 0, NULL, false};
26
GetDataFromBuf(uint8_t ** src,uint32_t * srcLen,uint8_t * dest,uint32_t destLen)27 static ResultCode GetDataFromBuf(uint8_t **src, uint32_t *srcLen, uint8_t *dest, uint32_t destLen)
28 {
29 if (destLen > *srcLen) {
30 LOG_ERROR("bad len.");
31 return RESULT_BAD_PARAM;
32 }
33 if (memcpy_s(dest, destLen, *src, destLen) != EOK) {
34 LOG_ERROR("copy fail.");
35 return RESULT_BAD_COPY;
36 }
37
38 *src = *src + destLen;
39 *srcLen = *srcLen - destLen;
40 return RESULT_SUCCESS;
41 }
42
CopyDataToBuf(uint8_t * data,uint32_t dataLen,uint8_t ** buf,uint32_t * bufLen)43 static ResultCode CopyDataToBuf(uint8_t *data, uint32_t dataLen, uint8_t **buf, uint32_t *bufLen)
44 {
45 if (memcpy_s(*buf, *bufLen, data, dataLen) != EOK) {
46 LOG_ERROR("CopyFileName fail.");
47 return RESULT_BAD_COPY;
48 }
49
50 *buf = *buf + dataLen;
51 *bufLen = *bufLen - dataLen;
52 return RESULT_SUCCESS;
53 }
54
GenerateFileName(uint64_t templateId,const char * prefix,const char * suffix,char * fileName,uint32_t fileNameLen)55 static ResultCode GenerateFileName(uint64_t templateId, const char *prefix, const char *suffix,
56 char *fileName, uint32_t fileNameLen)
57 {
58 if (memset_s(fileName, fileNameLen, 0, fileNameLen) != EOK) {
59 return RESULT_PIN_FAIL;
60 }
61 char *buf = fileName;
62 uint32_t bufLen = fileNameLen;
63 if (CopyDataToBuf((uint8_t *)prefix, strlen(prefix), (uint8_t **)&buf, &bufLen) != RESULT_SUCCESS) {
64 LOG_ERROR("copy prefix fail.");
65 return RESULT_BAD_COPY;
66 }
67 char templateIdStr[MAX_UINT_LEN] = {'\0'};
68 if (snprintf_s(templateIdStr, MAX_UINT_LEN, MAX_UINT_LEN - 1, "%" PRIu64, templateId) < 0) {
69 LOG_ERROR("templateIdStr error.");
70 return RESULT_UNKNOWN;
71 }
72 if (CopyDataToBuf((uint8_t *)templateIdStr, strlen(templateIdStr), (uint8_t **)&buf, &bufLen) != RESULT_SUCCESS) {
73 LOG_ERROR("copy templateIdStr fail.");
74 return RESULT_BAD_COPY;
75 }
76 if (CopyDataToBuf((uint8_t *)suffix, strlen(suffix), (uint8_t **)&buf, &bufLen) != RESULT_SUCCESS) {
77 LOG_ERROR("copy suffix fail.");
78 return RESULT_BAD_COPY;
79 }
80 if (bufLen == 0) {
81 LOG_ERROR("no space for endl.");
82 return RESULT_BAD_COPY;
83 }
84
85 LOG_INFO("GenerateFileName succ.");
86 return RESULT_SUCCESS;
87 }
88
89 /* This is for example only, Should be implemented in trusted environment. */
ReadPinFile(uint8_t * data,uint32_t dataLen,uint64_t templateId,const char * suffix)90 static ResultCode ReadPinFile(uint8_t *data, uint32_t dataLen, uint64_t templateId, const char *suffix)
91 {
92 FileOperator *fileOp = GetFileOperator(DEFAULT_FILE_OPERATOR);
93 if (!IsFileOperatorValid(fileOp)) {
94 LOG_ERROR("fileOp invalid.");
95 return RESULT_GENERAL_ERROR;
96 }
97
98 char fileName[MAX_FILE_NAME_LEN] = {'\0'};
99 ResultCode ret = GenerateFileName(templateId, DEFAULT_FILE_HEAD, suffix, fileName, MAX_FILE_NAME_LEN);
100 if (ret != RESULT_SUCCESS) {
101 LOG_ERROR("ReadPinFile Generate Pin FileName fail.");
102 return RESULT_GENERAL_ERROR;
103 }
104 ret = (ResultCode)fileOp->readFile(fileName, data, dataLen);
105 if (ret != RESULT_SUCCESS) {
106 LOG_ERROR("read pin file fail.");
107 return ret;
108 }
109
110 return RESULT_SUCCESS;
111 }
112
113 /* This is for example only, Should be implemented in trusted environment. */
WritePinFile(const uint8_t * data,uint32_t dataLen,uint64_t templateId,const char * suffix)114 static ResultCode WritePinFile(const uint8_t *data, uint32_t dataLen, uint64_t templateId, const char *suffix)
115 {
116 FileOperator *fileOp = GetFileOperator(DEFAULT_FILE_OPERATOR);
117 if (!IsFileOperatorValid(fileOp)) {
118 LOG_ERROR("fileOp invalid.");
119 return RESULT_GENERAL_ERROR;
120 }
121
122 char fileName[MAX_FILE_NAME_LEN] = {'\0'};
123 ResultCode ret = GenerateFileName(templateId, DEFAULT_FILE_HEAD, suffix, fileName, MAX_FILE_NAME_LEN);
124 if (ret != RESULT_SUCCESS) {
125 LOG_ERROR("WritePinFile Generate Pin FileName fail.");
126 return RESULT_GENERAL_ERROR;
127 }
128 ret = (ResultCode)fileOp->writeFile(fileName, data, dataLen);
129 if (ret != RESULT_SUCCESS) {
130 LOG_ERROR("WritePinFile fail.");
131 return ret;
132 }
133 LOG_INFO("WritePinFile succ.");
134
135 return RESULT_SUCCESS;
136 }
137
GetPinIndex(uint8_t * data,uint32_t dataLen)138 static ResultCode GetPinIndex(uint8_t *data, uint32_t dataLen)
139 {
140 if (sizeof(PinInfo) * g_pinDbOp.pinIndexLen != dataLen) {
141 LOG_ERROR("bad data length.");
142 return RESULT_GENERAL_ERROR;
143 }
144 g_pinDbOp.pinIndex = (PinIndex *)Malloc(sizeof(PinIndex) * g_pinDbOp.pinIndexLen);
145 if (g_pinDbOp.pinIndex == NULL) {
146 LOG_ERROR("pinIndex malloc fail.");
147 return RESULT_NO_MEMORY;
148 }
149 uint8_t *temp = data;
150 uint32_t tempLen = dataLen;
151 for (uint32_t i = 0; i < g_pinDbOp.pinIndexLen; i++) {
152 if (GetDataFromBuf(&temp, &tempLen, (uint8_t *)(&(g_pinDbOp.pinIndex[i].pinInfo)),
153 sizeof(g_pinDbOp.pinIndex[i].pinInfo)) != RESULT_SUCCESS) {
154 LOG_ERROR("read pinInfo fail.");
155 Free(g_pinDbOp.pinIndex);
156 g_pinDbOp.pinIndex = NULL;
157 return RESULT_BAD_READ;
158 }
159 if (ReadPinFile((uint8_t *)(&(g_pinDbOp.pinIndex[i].antiBruteInfo)),
160 sizeof(g_pinDbOp.pinIndex[i].antiBruteInfo),
161 g_pinDbOp.pinIndex[i].pinInfo.templateId, ANTI_BRUTE_SUFFIX) != RESULT_SUCCESS) {
162 LOG_ERROR("read AntiBruteInfo fail.");
163 Free(g_pinDbOp.pinIndex);
164 g_pinDbOp.pinIndex = NULL;
165 return RESULT_BAD_READ;
166 }
167 }
168 return RESULT_SUCCESS;
169 }
170
UnpackPinDb(uint8_t * data,uint32_t dataLen)171 static ResultCode UnpackPinDb(uint8_t *data, uint32_t dataLen)
172 {
173 if (data == NULL || dataLen == 0) {
174 LOG_ERROR("param is invalid.");
175 return RESULT_BAD_PARAM;
176 }
177
178 uint8_t *temp = data;
179 uint32_t tempLen = dataLen;
180 if (GetDataFromBuf(&temp, &tempLen, (uint8_t *)(&(g_pinDbOp.version)),
181 sizeof(g_pinDbOp.version)) != RESULT_SUCCESS) {
182 LOG_ERROR("read version fail.");
183 goto ERROR;
184 }
185 if (GetDataFromBuf(&temp, &tempLen, (uint8_t *)(&(g_pinDbOp.pinIndexLen)),
186 sizeof(g_pinDbOp.pinIndexLen)) != RESULT_SUCCESS) {
187 LOG_ERROR("read pinIndexLen fail.");
188 goto ERROR;
189 }
190 if (g_pinDbOp.pinIndexLen > MAX_CRYPTO_INFO_SIZE) {
191 LOG_ERROR("pinIndexLen too large.");
192 goto ERROR;
193 }
194 if (g_pinDbOp.pinIndexLen == 0) {
195 g_pinDbOp.pinIndex = NULL;
196 return RESULT_SUCCESS;
197 }
198 if (GetPinIndex(temp, tempLen) != RESULT_SUCCESS) {
199 LOG_ERROR("GetPinIndex fail.");
200 goto ERROR;
201 }
202 return RESULT_SUCCESS;
203
204 ERROR:
205 DestroyPinDb();
206 return RESULT_BAD_READ;
207 }
208
LoadPinDb(void)209 static ResultCode LoadPinDb(void)
210 {
211 if (g_pinDbOp.isLoaded) {
212 return RESULT_SUCCESS;
213 }
214 FileOperator *fileOp = GetFileOperator(DEFAULT_FILE_OPERATOR);
215 if (!IsFileOperatorValid(fileOp)) {
216 LOG_ERROR("fileOp invalid.");
217 return RESULT_GENERAL_ERROR;
218 }
219
220 if (!fileOp->isFileExist(PIN_INDEX_NAME)) {
221 g_pinDbOp.isLoaded = true;
222 return RESULT_SUCCESS;
223 }
224
225 uint32_t dataLen = 0;
226 ResultCode ret = (ResultCode)(fileOp->getFileLen(PIN_INDEX_NAME, &dataLen));
227 if (ret != RESULT_SUCCESS) {
228 LOG_ERROR("get filelen failed");
229 return RESULT_BAD_READ;
230 }
231
232 uint8_t *data = Malloc(dataLen);
233 if (data == NULL) {
234 LOG_ERROR("malloc data failed");
235 return RESULT_GENERAL_ERROR;
236 }
237 ret = (ResultCode)fileOp->readFile(PIN_INDEX_NAME, data, dataLen);
238 if (ret != RESULT_SUCCESS) {
239 LOG_ERROR("read_parcel_from_file failed.");
240 goto EXIT;
241 }
242
243 ret = UnpackPinDb(data, dataLen);
244 if (ret != RESULT_SUCCESS) {
245 LOG_ERROR("unpack db failed.");
246 goto EXIT;
247 }
248 g_pinDbOp.isLoaded = true;
249 LOG_INFO("LoadPinDb succ.");
250
251 EXIT:
252 (void)memset_s(data, dataLen, 0, dataLen);
253 Free(data);
254 return ret;
255 }
256
InitPinDb(void)257 void InitPinDb(void)
258 {
259 ResultCode ret = LoadPinDb();
260 if (ret != RESULT_SUCCESS) {
261 LOG_ERROR("LoadPinDb fail.");
262 return;
263 }
264 LOG_INFO("InitPinDb succ.");
265 }
266
DestroyPinDb(void)267 void DestroyPinDb(void)
268 {
269 if (g_pinDbOp.pinIndex != NULL) {
270 Free(g_pinDbOp.pinIndex);
271 }
272 g_pinDbOp.version = CURRENT_VERSION;
273 g_pinDbOp.pinIndexLen = 0;
274 g_pinDbOp.pinIndex = NULL;
275 g_pinDbOp.isLoaded = false;
276 LOG_INFO("DestroyPinDb succ.");
277 }
278
CoverData(const char * fileName,const FileOperator * fileOp)279 static ResultCode CoverData(const char *fileName, const FileOperator *fileOp)
280 {
281 uint32_t fileLen = 0;
282 ResultCode ret = (ResultCode)fileOp->getFileLen(fileName, &fileLen);
283 /* The maximum length of the fileName is CONST_PIN_DATA_EXPAND_LEN */
284 if (ret != RESULT_SUCCESS) {
285 LOG_ERROR("getFileLen fail.");
286 return ret;
287 }
288 if (fileLen > CONST_PIN_DATA_EXPAND_LEN) {
289 LOG_ERROR("Filelen is larger than pin data expand len");
290 return RESULT_GENERAL_ERROR;
291 }
292 uint8_t *data = Malloc(fileLen);
293 if (data == NULL) {
294 LOG_ERROR("no memory.");
295 return RESULT_NO_MEMORY;
296 }
297 (void)memset_s(data, fileLen, 0, fileLen);
298 ret = (ResultCode)fileOp->writeFile(fileName, data, fileLen);
299 Free(data);
300 if (ret != RESULT_SUCCESS) {
301 LOG_ERROR("WritePinFile fail.");
302 return ret;
303 }
304
305 return RESULT_SUCCESS;
306 }
307
308 /* This is for example only, Should be implemented in trusted environment. */
RemovePinFile(const uint64_t templateId,const char * suffix,bool needCover)309 static ResultCode RemovePinFile(const uint64_t templateId, const char *suffix, bool needCover)
310 {
311 FileOperator *fileOp = GetFileOperator(DEFAULT_FILE_OPERATOR);
312 if (!IsFileOperatorValid(fileOp)) {
313 LOG_ERROR("fileOp invalid.");
314 return RESULT_GENERAL_ERROR;
315 }
316 char fileName[MAX_FILE_NAME_LEN] = {'\0'};
317 ResultCode ret = GenerateFileName(templateId, DEFAULT_FILE_HEAD, suffix, fileName, MAX_FILE_NAME_LEN);
318 if (ret != RESULT_SUCCESS) {
319 LOG_ERROR("GenerateCryptoFileName fail.");
320 return RESULT_UNKNOWN;
321 }
322
323 /* Write data zeros before deleting data, In addition to anti-brute-force cracking */
324 if (needCover) {
325 ret = CoverData(fileName, fileOp);
326 if (ret != RESULT_SUCCESS) {
327 LOG_ERROR("cover data fail.");
328 return RESULT_GENERAL_ERROR;
329 }
330 }
331 if ((ResultCode)fileOp->deleteFile(fileName) != RESULT_SUCCESS) {
332 LOG_ERROR("file remove fail.");
333 return RESULT_BAD_DEL;
334 }
335
336 LOG_INFO("RemovePinFile succ.");
337 return ret;
338 }
339
RemoveAllFile(uint64_t templateId)340 static ResultCode RemoveAllFile(uint64_t templateId)
341 {
342 /* This is for example only, Anti-brute-force cracking files must have an anti-rollback zone */
343 ResultCode ret = RemovePinFile(templateId, ANTI_BRUTE_SUFFIX, false);
344 if (ret != RESULT_SUCCESS) {
345 LOG_ERROR("RemovePinAntiBrute fail.");
346 }
347 ret = RemovePinFile(templateId, CRYPTO_SUFFIX, true);
348 if (ret != RESULT_SUCCESS) {
349 LOG_ERROR("RemovePinCrypto fail.");
350 return ret;
351 }
352 ret = RemovePinFile(templateId, SALT_SUFFIX, true);
353 if (ret != RESULT_SUCCESS) {
354 LOG_ERROR("RemovePinSalt fail.");
355 }
356 ret = RemovePinFile(templateId, SECRET_SUFFIX, true);
357 if (ret != RESULT_SUCCESS) {
358 LOG_ERROR("RemovePinSecret fail.");
359 }
360
361 LOG_INFO("RemoveAllFile succ.");
362 return RESULT_SUCCESS;
363 }
364
GeneratePinTemplateId(void)365 static uint64_t GeneratePinTemplateId(void)
366 {
367 for (uint32_t i = 0; i < MAX_RANDOM_TIME; i++) {
368 uint64_t templateId = INVALID_TEMPLATE_ID;
369 SecureRandom((uint8_t *)&templateId, sizeof(templateId));
370 if (templateId == INVALID_TEMPLATE_ID) {
371 continue;
372 }
373 uint32_t j = 0;
374 for (; j < g_pinDbOp.pinIndexLen; j++) {
375 if (templateId == g_pinDbOp.pinIndex[i].pinInfo.templateId) {
376 break;
377 }
378 }
379 if (j == g_pinDbOp.pinIndexLen) {
380 return templateId;
381 }
382 }
383 LOG_ERROR("fail generate pin templateid.");
384 return INVALID_TEMPLATE_ID;
385 }
386
SearchPinById(uint64_t templateId)387 static uint32_t SearchPinById(uint64_t templateId)
388 {
389 if (g_pinDbOp.pinIndexLen == 0) {
390 LOG_ERROR("no pin exist.");
391 return MAX_CRYPTO_INFO_SIZE;
392 }
393 for (uint32_t index = 0; index < g_pinDbOp.pinIndexLen; index++) {
394 if (g_pinDbOp.pinIndex[index].pinInfo.templateId == templateId) {
395 LOG_INFO("SearchPinById succ.");
396 return index;
397 }
398 }
399 LOG_ERROR("no pin match.");
400 return MAX_CRYPTO_INFO_SIZE;
401 }
402
DelPin(uint32_t index)403 static ResultCode DelPin(uint32_t index)
404 {
405 /* This is for example only, Should be implemented in trusted environment. */
406 ResultCode ret = RemoveAllFile(g_pinDbOp.pinIndex[index].pinInfo.templateId);
407 if (ret != RESULT_SUCCESS) {
408 LOG_ERROR("Remove pin file fail.");
409 return ret;
410 }
411
412 LOG_INFO("DelPin succ.");
413 return RESULT_SUCCESS;
414 }
415
IsPinDbValid(PinDb * pinDb)416 static bool IsPinDbValid(PinDb *pinDb)
417 {
418 if (pinDb == NULL) {
419 return false;
420 }
421 if (pinDb->version != CURRENT_VERSION) {
422 return false;
423 }
424 if ((pinDb->pinIndexLen == 0) && (pinDb->pinIndex != NULL)) {
425 return false;
426 }
427 if ((pinDb->pinIndexLen != 0) && (pinDb->pinIndex == NULL)) {
428 return false;
429 }
430 if (pinDb->pinIndexLen > MAX_CRYPTO_INFO_SIZE) {
431 return false;
432 }
433 return true;
434 }
435
GetBufFromData(uint8_t * src,uint32_t srcLen,uint8_t ** dest,uint32_t * destLen)436 static ResultCode GetBufFromData(uint8_t *src, uint32_t srcLen, uint8_t **dest, uint32_t *destLen)
437 {
438 if (srcLen > *destLen) {
439 LOG_ERROR("bad len.");
440 return RESULT_BAD_PARAM;
441 }
442 if (memcpy_s(*dest, *destLen, src, srcLen) != EOK) {
443 LOG_ERROR("copy fail.");
444 return RESULT_BAD_COPY;
445 }
446
447 *dest = *dest + srcLen;
448 *destLen = *destLen - srcLen;
449 return RESULT_SUCCESS;
450 }
451
WritePinInfo(uint8_t * data,uint32_t dataLen)452 static ResultCode WritePinInfo(uint8_t *data, uint32_t dataLen)
453 {
454 if (g_pinDbOp.pinIndexLen == 0) {
455 return RESULT_SUCCESS;
456 }
457 uint8_t *temp = data;
458 uint32_t tempLen = dataLen;
459 for (uint32_t i = 0; i < g_pinDbOp.pinIndexLen; i++) {
460 if (GetBufFromData((uint8_t *)(&(g_pinDbOp.pinIndex[i].pinInfo)), sizeof(g_pinDbOp.pinIndex[i].pinInfo),
461 &temp, &tempLen) != RESULT_SUCCESS) {
462 LOG_ERROR("write pin info fail.");
463 return RESULT_BAD_WRITE;
464 }
465 }
466 return RESULT_SUCCESS;
467 }
468
WritePinDb(void)469 static ResultCode WritePinDb(void)
470 {
471 if (!IsPinDbValid(&g_pinDbOp)) {
472 LOG_ERROR("get invalid params.");
473 return RESULT_BAD_PARAM;
474 }
475 ResultCode ret = RESULT_SUCCESS;
476 FileOperator *fileOp = GetFileOperator(DEFAULT_FILE_OPERATOR);
477 if (!IsFileOperatorValid(fileOp)) {
478 LOG_ERROR("fileOp invalid.");
479 return RESULT_GENERAL_ERROR;
480 }
481
482 uint32_t dataLen = sizeof(PinInfo) * g_pinDbOp.pinIndexLen + sizeof(uint32_t) * PIN_DB_TWO_PARAMS;
483 uint8_t *data = Malloc(dataLen);
484 if (data == NULL) {
485 LOG_ERROR("malloc data fail.");
486 return RESULT_GENERAL_ERROR;
487 }
488 uint8_t *temp = data;
489 uint32_t tempLen = dataLen;
490 if (GetBufFromData((uint8_t *)(&(g_pinDbOp.version)), sizeof(g_pinDbOp.version),
491 &temp, &tempLen)!= RESULT_SUCCESS) {
492 ret = RESULT_BAD_WRITE;
493 goto ERROR;
494 }
495
496 if (GetBufFromData((uint8_t *)(&(g_pinDbOp.pinIndexLen)), sizeof(g_pinDbOp.pinIndexLen),
497 &temp, &tempLen) != RESULT_SUCCESS) {
498 ret = RESULT_BAD_WRITE;
499 goto ERROR;
500 }
501 ret = WritePinInfo(temp, tempLen);
502 if (ret != RESULT_SUCCESS) {
503 LOG_ERROR("WritePinInfo failed.");
504 goto ERROR;
505 }
506
507 if ((ResultCode)fileOp->writeFile(PIN_INDEX_NAME, data, dataLen) != RESULT_SUCCESS) {
508 LOG_ERROR("write_parcel_into_file failed.");
509 ret = RESULT_BAD_WRITE;
510 goto ERROR;
511 }
512 LOG_INFO("WritePinDb succ.");
513
514 ERROR:
515 (void)memset_s(data, dataLen, 0, dataLen);
516 Free(data);
517 return ret;
518 }
519
DelPinInDb(uint32_t index)520 static ResultCode DelPinInDb(uint32_t index)
521 {
522 uint32_t pinIndexLen = g_pinDbOp.pinIndexLen - 1;
523 if (pinIndexLen == 0) {
524 (void)memset_s(g_pinDbOp.pinIndex,
525 g_pinDbOp.pinIndexLen * sizeof(PinIndex), 0, g_pinDbOp.pinIndexLen * sizeof(PinIndex));
526 Free(g_pinDbOp.pinIndex);
527 g_pinDbOp.pinIndex = NULL;
528 } else {
529 uint32_t size = pinIndexLen * sizeof(PinIndex);
530 PinIndex *pinIndex = (PinIndex *)Malloc(size);
531 if (pinIndex == NULL) {
532 LOG_ERROR("PinIndex malloc fail.");
533 return RESULT_NO_MEMORY;
534 }
535 (void)memset_s(pinIndex, size, 0, size);
536 for (uint32_t i = 0, j = 0; i < g_pinDbOp.pinIndexLen; i++) {
537 if (i != index) {
538 pinIndex[j] = g_pinDbOp.pinIndex[i];
539 j++;
540 }
541 }
542 (void)memset_s(g_pinDbOp.pinIndex,
543 g_pinDbOp.pinIndexLen * sizeof(PinIndex), 0, g_pinDbOp.pinIndexLen * sizeof(PinIndex));
544 Free(g_pinDbOp.pinIndex);
545 g_pinDbOp.pinIndex = pinIndex;
546 }
547 g_pinDbOp.pinIndexLen = pinIndexLen;
548 ResultCode ret = WritePinDb();
549 if (ret != RESULT_SUCCESS) {
550 LOG_ERROR("WritePinDb fail.");
551 }
552
553 LOG_INFO("DelPinInDb succ.");
554 return ret;
555 }
556
DelPinById(uint64_t templateId)557 ResultCode DelPinById(uint64_t templateId)
558 {
559 ResultCode ret = LoadPinDb();
560 if (ret != RESULT_SUCCESS) {
561 LOG_ERROR("LoadPinDb fail.");
562 return ret;
563 }
564 uint32_t index = SearchPinById(templateId);
565 if (index == MAX_CRYPTO_INFO_SIZE) {
566 LOG_ERROR("no pin match.");
567 return RESULT_BAD_MATCH;
568 }
569
570 ret = DelPin(index);
571 if (ret != RESULT_SUCCESS) {
572 LOG_ERROR(" DelPin fail.");
573 return ret;
574 }
575 ret = DelPinInDb(index);
576 if (ret != RESULT_SUCCESS) {
577 LOG_ERROR("DelPinInDb fail.");
578 return ret;
579 }
580 LOG_INFO("DelPinById succ.");
581 /* ignore index file remove result, return success when crypto file remove success */
582 return ret;
583 }
584
InitPinInfo(PinInfo * pinInfo,uint64_t templateId,uint64_t subType)585 static void InitPinInfo(PinInfo *pinInfo, uint64_t templateId, uint64_t subType)
586 {
587 pinInfo->templateId = templateId;
588 pinInfo->subType = subType;
589 }
590
InitAntiBruteInfo(AntiBruteInfo * info)591 static void InitAntiBruteInfo(AntiBruteInfo *info)
592 {
593 info->authErrorCount = INIT_AUTH_ERROR_COUNT;
594 info->startFreezeTime = INIT_START_FREEZE_TIMES;
595 }
596
InitPinIndex(PinIndex * pinIndex,uint64_t templateId,uint64_t subType)597 static void InitPinIndex(PinIndex *pinIndex, uint64_t templateId, uint64_t subType)
598 {
599 InitPinInfo(&(pinIndex->pinInfo), templateId, subType);
600 InitAntiBruteInfo(&(pinIndex->antiBruteInfo));
601 }
602
AddPinInDb(uint64_t templateId,uint64_t subType)603 static ResultCode AddPinInDb(uint64_t templateId, uint64_t subType)
604 {
605 if (g_pinDbOp.pinIndexLen > MAX_CRYPTO_INFO_SIZE - 1) {
606 LOG_ERROR("pinIndexLen too large.");
607 return RESULT_BAD_PARAM;
608 }
609 uint32_t size = (g_pinDbOp.pinIndexLen + 1) * sizeof(PinIndex);
610 PinIndex *pinIndex = (PinIndex *)Malloc(size);
611 if (pinIndex == NULL) {
612 LOG_ERROR("PinIndex malloc fail.");
613 return RESULT_NO_MEMORY;
614 }
615 (void)memset_s(pinIndex, size, 0, size);
616 if (g_pinDbOp.pinIndexLen != 0) {
617 if (memcpy_s(pinIndex, size,
618 g_pinDbOp.pinIndex, g_pinDbOp.pinIndexLen * sizeof(PinIndex)) != EOK) {
619 LOG_ERROR("PinIndex copy fail.");
620 (void)memset_s(pinIndex, size, 0, size);
621 Free(pinIndex);
622 return RESULT_NO_MEMORY;
623 }
624 }
625 InitPinIndex(&pinIndex[g_pinDbOp.pinIndexLen], templateId, subType);
626 if (g_pinDbOp.pinIndex != NULL) {
627 Free(g_pinDbOp.pinIndex);
628 }
629 g_pinDbOp.pinIndex = pinIndex;
630 g_pinDbOp.pinIndexLen++;
631 ResultCode ret = WritePinDb();
632 if (ret != RESULT_SUCCESS) {
633 LOG_ERROR("WritePinDb fail.");
634 return ret;
635 }
636
637 LOG_INFO("AddPinInDb succ.");
638 return RESULT_SUCCESS;
639 }
640
RefreshPinDb(uint64_t * templateId,uint64_t subType)641 static ResultCode RefreshPinDb(uint64_t *templateId, uint64_t subType)
642 {
643 ResultCode ret = LoadPinDb();
644 if (ret != RESULT_SUCCESS) {
645 LOG_ERROR("LoadPinDb fail.");
646 return ret;
647 }
648 *templateId = GeneratePinTemplateId();
649 if (*templateId == INVALID_TEMPLATE_ID) {
650 LOG_ERROR("GeneratePinTemplateId fail.");
651 return RESULT_UNKNOWN;
652 }
653 ret = AddPinInDb(*templateId, subType);
654 if (ret != RESULT_SUCCESS) {
655 LOG_ERROR("AddPinDb fail.");
656 return ret;
657 }
658
659 LOG_INFO("RefreshPinDb succ.");
660 return RESULT_SUCCESS;
661 }
662
WriteAddPinInfo(const Buffer * secret,const Buffer * pinCredentialData,uint8_t * salt,uint32_t saltLen,const uint64_t templateId)663 static ResultCode WriteAddPinInfo(const Buffer *secret, const Buffer *pinCredentialData, uint8_t *salt,
664 uint32_t saltLen, const uint64_t templateId)
665 {
666 ResultCode ret = WritePinFile(pinCredentialData->buf, pinCredentialData->contentSize, templateId, CRYPTO_SUFFIX);
667 if (ret != RESULT_SUCCESS) {
668 LOG_ERROR("WriteCryptoFile fail.");
669 return ret;
670 }
671
672 ret = WritePinFile(salt, saltLen, templateId, SALT_SUFFIX);
673 if (ret != RESULT_SUCCESS) {
674 LOG_ERROR("WriteSaltFile fail.");
675 return ret;
676 }
677
678 ret = WritePinFile(secret->buf, secret->contentSize, templateId, SECRET_SUFFIX);
679 if (ret != RESULT_SUCCESS) {
680 LOG_ERROR("WriteSecretFile fail.");
681 return ret;
682 }
683 AntiBruteInfo initAntiBrute = {};
684 InitAntiBruteInfo(&initAntiBrute);
685 ret = WritePinFile((uint8_t *)&initAntiBrute, sizeof(AntiBruteInfo), templateId, ANTI_BRUTE_SUFFIX);
686 if (ret != RESULT_SUCCESS) {
687 LOG_ERROR("WriteAntiBruteFile fail.");
688 return ret;
689 }
690
691 LOG_INFO("WriteAddPinInfo succ.");
692 return RESULT_SUCCESS;
693 }
694
GenerateExpandData(char * str,const uint8_t * data,const uint32_t dataLen)695 static Buffer *GenerateExpandData(char *str, const uint8_t *data, const uint32_t dataLen)
696 {
697 /* CONST_EXPAND_DATA_LEN is twice the size of dataLen */
698 if (dataLen < strlen(str) || dataLen != (CONST_EXPAND_DATA_LEN / 2)) {
699 LOG_ERROR("bad param.");
700 return NULL;
701 }
702 Buffer *outBuff = CreateBufferBySize(CONST_EXPAND_DATA_LEN);
703 if (!IsBufferValid(outBuff)) {
704 LOG_ERROR("create buffer fail.");
705 return NULL;
706 }
707 (void)memset_s(outBuff->buf, outBuff->maxSize, 0, outBuff->maxSize);
708 outBuff->contentSize = outBuff->maxSize;
709 uint8_t *temp = outBuff->buf;
710 if (memcpy_s(temp, outBuff->maxSize, (uint8_t *)str, strlen(str)) != EOK) {
711 LOG_ERROR("copy str fail.");
712 DestoryBuffer(outBuff);
713 return NULL;
714 }
715
716 temp += dataLen;
717 if (memcpy_s(temp, outBuff->maxSize - dataLen, data, dataLen) != EOK) {
718 LOG_ERROR("copy data fail.");
719 DestoryBuffer(outBuff);
720 return NULL;
721 }
722
723 return outBuff;
724 }
725
GenerateRootSecret(const Buffer * deviceKey,const Buffer * pinData,Buffer * outRootSecret)726 static ResultCode GenerateRootSecret(const Buffer *deviceKey, const Buffer *pinData, Buffer *outRootSecret)
727 {
728 Buffer *expandData = GenerateExpandData(SALT_PREFIX, pinData->buf, pinData->contentSize);
729 if (!IsBufferValid(expandData)) {
730 LOG_ERROR("generate expand data fail.");
731 return RESULT_GENERAL_ERROR;
732 }
733
734 Buffer *hkdfSalt = Sha256Adaptor(expandData);
735 if (!IsBufferValid(hkdfSalt)) {
736 LOG_ERROR("generate sha256 fail.");
737 DestoryBuffer(expandData);
738 return RESULT_GENERAL_ERROR;
739 }
740 Buffer *rootSecret = Hkdf(hkdfSalt, deviceKey);
741 DestoryBuffer(expandData);
742 DestoryBuffer(hkdfSalt);
743 if (!IsBufferValid(rootSecret)) {
744 LOG_ERROR("generate rootSecret fail.");
745 return RESULT_GENERAL_ERROR;
746 }
747 if (memcpy_s(outRootSecret->buf, outRootSecret->maxSize, rootSecret->buf, rootSecret->contentSize) != EOK) {
748 LOG_ERROR("copy root secret fail.");
749 DestoryBuffer(rootSecret);
750 return RESULT_BAD_COPY;
751 }
752
753 outRootSecret->contentSize = rootSecret->contentSize;
754 DestoryBuffer(rootSecret);
755 return RESULT_SUCCESS;
756 }
757
GenerateEncryptionKey(const Buffer * deviceKey)758 static Buffer *GenerateEncryptionKey(const Buffer *deviceKey)
759 {
760 Buffer *keyStrBuffer = CreateBufferBySize(CONST_CREDENTIAL_PREFIX_LEN);
761 if (!IsBufferValid(keyStrBuffer)) {
762 LOG_ERROR("generate expand data fail.");
763 return NULL;
764 }
765 (void)memset_s(keyStrBuffer->buf, keyStrBuffer->maxSize, 0, keyStrBuffer->maxSize);
766 if (memcpy_s(keyStrBuffer->buf, keyStrBuffer->maxSize,
767 (uint8_t *)CREDENTIAL_PREFIX, strlen(CREDENTIAL_PREFIX)) != EOK) {
768 LOG_ERROR("copy CREDENTIAL_PREFIX fail.");
769 DestoryBuffer(keyStrBuffer);
770 return NULL;
771 }
772 keyStrBuffer->contentSize = keyStrBuffer->maxSize;
773 Buffer *encryptionKey = Hkdf(keyStrBuffer, deviceKey);
774 DestoryBuffer(keyStrBuffer);
775 if (!IsBufferValid(encryptionKey)) {
776 LOG_ERROR("generate encryptionKey fail.");
777 return NULL;
778 }
779
780 return encryptionKey;
781 }
782
ProcessAddPin(const Buffer * deviceKey,const Buffer * secret,PinEnrollParam * pinEnrollParam,uint64_t templateId)783 static ResultCode ProcessAddPin(const Buffer *deviceKey, const Buffer *secret, PinEnrollParam *pinEnrollParam,
784 uint64_t templateId)
785 {
786 Buffer *encryptionKey = GenerateEncryptionKey(deviceKey);
787 if (!IsBufferValid(encryptionKey)) {
788 LOG_ERROR("generate encryptionKey fail.");
789 return RESULT_GENERAL_ERROR;
790 }
791 Buffer *pinDataBuffer = CreateBufferByData(pinEnrollParam->pinData, CONST_PIN_DATA_LEN);
792 if (!IsBufferValid(pinDataBuffer)) {
793 LOG_ERROR("generate pinDataBuffer fail.");
794 DestoryBuffer(encryptionKey);
795 return RESULT_GENERAL_ERROR;
796 }
797 Buffer *pinCredCiphertext = Aes256GcmEncryptNoPadding(pinDataBuffer, encryptionKey);
798 if (!IsBufferValid(pinCredCiphertext)) {
799 LOG_ERROR("generate pinCredCiphertext fail.");
800 DestoryBuffer(encryptionKey);
801 DestoryBuffer(pinDataBuffer);
802 return RESULT_GENERAL_ERROR;
803 }
804
805 ResultCode ret = WriteAddPinInfo(secret, pinCredCiphertext, pinEnrollParam->salt, CONST_SALT_LEN, templateId);
806 DestoryBuffer(encryptionKey);
807 DestoryBuffer(pinDataBuffer);
808 DestoryBuffer(pinCredCiphertext);
809 if (ret != RESULT_SUCCESS) {
810 LOG_ERROR("write add pin info fail.");
811 }
812
813 return ret;
814 }
815
816 /* This is for example only, Should be implemented in trusted environment. */
AddPin(PinEnrollParam * pinEnrollParam,uint64_t * templateId,Buffer * outRootSecret)817 ResultCode AddPin(PinEnrollParam *pinEnrollParam, uint64_t *templateId, Buffer *outRootSecret)
818 {
819 if (pinEnrollParam == NULL || templateId == NULL || !IsBufferValid(outRootSecret)) {
820 LOG_ERROR("get invalid params.");
821 return RESULT_BAD_PARAM;
822 }
823 ResultCode ret = RefreshPinDb(templateId, pinEnrollParam->subType);
824 if (ret != RESULT_SUCCESS) {
825 LOG_ERROR("refresh pinDb fail.");
826 return ret;
827 }
828 Buffer *pinCredData = CreateBufferByData(pinEnrollParam->pinData, CONST_PIN_DATA_LEN);
829 Buffer *secret = CreateBufferBySize(SECRET_SIZE);
830 Buffer *deviceKey = NULL;
831 if (!IsBufferValid(pinCredData) || !IsBufferValid(secret)) {
832 LOG_ERROR("generate buffer fail.");
833 ret = RESULT_NO_MEMORY;
834 goto ERROR;
835 }
836 if (SecureRandom(secret->buf, secret->maxSize) != RESULT_SUCCESS) {
837 LOG_ERROR("generate secure random number fail.");
838 ret = RESULT_GENERAL_ERROR;
839 goto ERROR;
840 }
841 secret->contentSize = secret->maxSize;
842 deviceKey = DeriveDeviceKey(pinCredData, secret);
843 if (!IsBufferValid(deviceKey)) {
844 LOG_ERROR("generate deviceKey fail.");
845 ret = RESULT_GENERAL_ERROR;
846 goto ERROR;
847 }
848 ret = GenerateRootSecret(deviceKey, pinCredData, outRootSecret);
849 if (ret != RESULT_SUCCESS) {
850 LOG_ERROR("generate rootSecret fail.");
851 goto ERROR;
852 }
853 ret = ProcessAddPin(deviceKey, secret, pinEnrollParam, *templateId);
854 if (ret != RESULT_SUCCESS) {
855 LOG_ERROR("process add pin fail.");
856 goto ERROR;
857 }
858 LOG_INFO("AddPin succ.");
859
860 ERROR:
861 DestoryBuffer(deviceKey);
862 DestoryBuffer(secret);
863 DestoryBuffer(pinCredData);
864 return ret;
865 }
866
DoGetSalt(uint64_t templateId,uint8_t * salt,uint32_t * saltLen)867 ResultCode DoGetSalt(uint64_t templateId, uint8_t *salt, uint32_t *saltLen)
868 {
869 if (salt == NULL || saltLen == NULL || templateId == INVALID_TEMPLATE_ID) {
870 LOG_ERROR("get invalid salt params.");
871 return RESULT_BAD_PARAM;
872 }
873
874 uint32_t index = SearchPinById(templateId);
875 if (index == MAX_CRYPTO_INFO_SIZE) {
876 LOG_ERROR(" no pin match.");
877 return RESULT_BAD_MATCH;
878 }
879
880 ResultCode ret = ReadPinFile(salt, *saltLen, templateId, SALT_SUFFIX);
881 if (ret != RESULT_SUCCESS) {
882 LOG_ERROR("salt file read fail.");
883 return ret;
884 }
885 LOG_INFO("DoGetSalt succ.");
886 return RESULT_SUCCESS;
887 }
888
GetAntiBruteCountById(uint64_t templateId,uint32_t * count)889 static ResultCode GetAntiBruteCountById(uint64_t templateId, uint32_t *count)
890 {
891 ResultCode ret = LoadPinDb();
892 if (ret != RESULT_SUCCESS) {
893 LOG_ERROR("LoadPinDb fail.");
894 return ret;
895 }
896
897 uint32_t index = SearchPinById(templateId);
898 if (index == MAX_CRYPTO_INFO_SIZE) {
899 LOG_ERROR("no pin index match.");
900 return RESULT_BAD_MATCH;
901 }
902 *count = g_pinDbOp.pinIndex[index].antiBruteInfo.authErrorCount;
903 return RESULT_SUCCESS;
904 }
905
RefreshAntiBruteInfoToFile(uint64_t templateId)906 ResultCode RefreshAntiBruteInfoToFile(uint64_t templateId)
907 {
908 ResultCode ret = LoadPinDb();
909 if (ret != RESULT_SUCCESS) {
910 LOG_ERROR("LoadPinDb fail.");
911 return ret;
912 }
913 uint32_t index = SearchPinById(templateId);
914 if (index == MAX_CRYPTO_INFO_SIZE) {
915 LOG_ERROR(" no pin match.");
916 return RESULT_BAD_MATCH;
917 }
918 ret = WritePinFile((uint8_t *)(&(g_pinDbOp.pinIndex[index].antiBruteInfo)), sizeof(AntiBruteInfo),
919 templateId, ANTI_BRUTE_SUFFIX);
920 if (ret != RESULT_SUCCESS) {
921 LOG_ERROR("write anti brute fail.");
922 }
923
924 return ret;
925 }
926
SetAntiBruteInfoById(uint64_t templateId,uint32_t count,uint64_t startFreezeTime)927 static ResultCode SetAntiBruteInfoById(uint64_t templateId, uint32_t count, uint64_t startFreezeTime)
928 {
929 ResultCode ret = LoadPinDb();
930 if (ret != RESULT_SUCCESS) {
931 LOG_ERROR("LoadPinDb fail.");
932 return ret;
933 }
934
935 uint32_t index = SearchPinById(templateId);
936 if (index == MAX_CRYPTO_INFO_SIZE) {
937 LOG_ERROR(" no pin match.");
938 return RESULT_BAD_MATCH;
939 }
940 g_pinDbOp.pinIndex[index].antiBruteInfo.authErrorCount = count;
941 g_pinDbOp.pinIndex[index].antiBruteInfo.startFreezeTime = startFreezeTime;
942 ret = WritePinFile((uint8_t *)(&(g_pinDbOp.pinIndex[index].antiBruteInfo)), sizeof(AntiBruteInfo),
943 templateId, ANTI_BRUTE_SUFFIX);
944 if (ret != RESULT_SUCCESS) {
945 LOG_ERROR("write anti brute fail.");
946 return ret;
947 }
948 return ret;
949 }
950
GetSubType(uint64_t templateId,uint64_t * subType)951 ResultCode GetSubType(uint64_t templateId, uint64_t *subType)
952 {
953 if (templateId == INVALID_TEMPLATE_ID) {
954 LOG_ERROR("check param fail!");
955 return RESULT_BAD_PARAM;
956 }
957
958 uint32_t index = SearchPinById(templateId);
959 if (index == MAX_CRYPTO_INFO_SIZE) {
960 LOG_ERROR("no pin match.");
961 return RESULT_BAD_MATCH;
962 }
963 *subType = g_pinDbOp.pinIndex[index].pinInfo.subType;
964
965 LOG_INFO("GetSubType succ.");
966 return RESULT_SUCCESS;
967 }
968
GetAntiBruteInfo(uint64_t templateId,uint32_t * authErrorCount,uint64_t * startFreezeTime)969 ResultCode GetAntiBruteInfo(uint64_t templateId, uint32_t *authErrorCount, uint64_t *startFreezeTime)
970 {
971 if (authErrorCount == NULL || startFreezeTime == NULL || templateId == INVALID_TEMPLATE_ID) {
972 LOG_ERROR("check GetAntiBruteInfo param fail!");
973 return RESULT_BAD_PARAM;
974 }
975
976 uint32_t index = SearchPinById(templateId);
977 if (index == MAX_CRYPTO_INFO_SIZE) {
978 LOG_ERROR("no pin match.");
979 return RESULT_BAD_MATCH;
980 }
981 *authErrorCount = g_pinDbOp.pinIndex[index].antiBruteInfo.authErrorCount;
982 *startFreezeTime = g_pinDbOp.pinIndex[index].antiBruteInfo.startFreezeTime;
983
984 LOG_INFO("GetAntiBruteInfo succ.");
985 return RESULT_SUCCESS;
986 }
987
ExponentialFuncTime(uint32_t authErrorCount)988 static uint64_t ExponentialFuncTime(uint32_t authErrorCount)
989 {
990 uint32_t ret = DEFAULT_VALUE;
991 uint32_t exp = (authErrorCount - FIRST_EXPONENTIAL_PARA) / THIRD_EXPONENTIAL_PARA;
992 for (uint32_t index = 0; index < exp; ++index) {
993 ret *= SECOND_EXPONENTIAL_PARA;
994 }
995 return FIRST_EXPONENTIAL_PARA * ret;
996 }
997
GetWaitTime(uint32_t authErrorCount)998 static uint64_t GetWaitTime(uint32_t authErrorCount)
999 {
1000 if (authErrorCount < FIRST_ANTI_BRUTE_COUNT) {
1001 return 0;
1002 }
1003 if (authErrorCount < ATTI_BRUTE_FIRST_STAGE) {
1004 if (authErrorCount == FIRST_ANTI_BRUTE_COUNT) {
1005 return ONE_MIN_TIME * MS_OF_S;
1006 }
1007 if (authErrorCount == SECOND_ANTI_BRUTE_COUNT) {
1008 return TEN_MIN_TIME * MS_OF_S;
1009 }
1010 if (authErrorCount == THIRD_ANTI_BRUTE_COUNT) {
1011 return THIRTY_MIN_TIME * MS_OF_S;
1012 }
1013 if (((authErrorCount - FIRST_ANTI_BRUTE_COUNT) % ANTI_BRUTE_COUNT_FREQUENCY) == 0) {
1014 return ONE_HOUR_TIME * MS_OF_S;
1015 }
1016 return 0;
1017 }
1018 if (authErrorCount > ATTI_BRUTE_SECOND_STAGE) {
1019 return ONE_DAY_TIME * MS_OF_S;
1020 }
1021 return ExponentialFuncTime(authErrorCount) * MS_OF_S;
1022 }
1023
ComputeFreezeTime(uint64_t templateId,uint32_t * freezeTime,uint32_t count,uint64_t startFreezeTime)1024 ResultCode ComputeFreezeTime(uint64_t templateId, uint32_t *freezeTime, uint32_t count, uint64_t startFreezeTime)
1025 {
1026 if (templateId == INVALID_TEMPLATE_ID || freezeTime == NULL) {
1027 LOG_ERROR("check ComputeFreezeTime param fail!");
1028 return RESULT_BAD_PARAM;
1029 }
1030 uint64_t timeValue = GetRtcTime();
1031 uint64_t waitTime = GetWaitTime(count);
1032 if (timeValue >= startFreezeTime) {
1033 uint64_t usedTime = timeValue - startFreezeTime;
1034 if (usedTime >= waitTime) {
1035 *freezeTime = 0;
1036 } else {
1037 *freezeTime = (waitTime - usedTime) & 0xffffffff;
1038 }
1039 } else {
1040 /* rtc time is reset, we should update startFreezeTime to timeValue */
1041 if (SetAntiBruteInfoById(templateId, count, timeValue) != RESULT_SUCCESS) {
1042 LOG_ERROR("SetAntiBruteInfoById fail.");
1043 return RESULT_BAD_PARAM;
1044 }
1045 *freezeTime = waitTime & 0xffffffff;
1046 }
1047
1048 LOG_INFO("ComputeFreezeTime succ.");
1049 return RESULT_SUCCESS;
1050 }
1051
ComputeRemainingTimes(uint32_t errorCount)1052 static uint32_t ComputeRemainingTimes(uint32_t errorCount)
1053 {
1054 if (errorCount < FIRST_ANTI_BRUTE_COUNT) {
1055 return FIRST_ANTI_BRUTE_COUNT - errorCount;
1056 }
1057 if (errorCount >= ATTI_BRUTE_FIRST_STAGE) {
1058 return REMAINING_TIMES_FREEZE;
1059 }
1060 return ANTI_BRUTE_COUNT_FREQUENCY - (errorCount - FIRST_ANTI_BRUTE_COUNT) % ANTI_BRUTE_COUNT_FREQUENCY;
1061 }
1062
GetRemainTimes(uint64_t templateId,uint32_t * remainingAuthTimes,uint32_t authErrorCount)1063 ResultCode GetRemainTimes(uint64_t templateId, uint32_t *remainingAuthTimes, uint32_t authErrorCount)
1064 {
1065 if (templateId == INVALID_TEMPLATE_ID || remainingAuthTimes == NULL) {
1066 LOG_ERROR("check GetRemainTimes param fail!");
1067 return RESULT_BAD_PARAM;
1068 }
1069 *remainingAuthTimes = ComputeRemainingTimes(authErrorCount);
1070 return RESULT_SUCCESS;
1071 }
1072
ClearAntiBruteInfoById(uint64_t templateId)1073 static ResultCode ClearAntiBruteInfoById(uint64_t templateId)
1074 {
1075 uint32_t index = SearchPinById(templateId);
1076 if (index == MAX_CRYPTO_INFO_SIZE) {
1077 LOG_ERROR(" no pin match.");
1078 return RESULT_BAD_MATCH;
1079 }
1080 InitAntiBruteInfo(&(g_pinDbOp.pinIndex[index].antiBruteInfo));
1081 return RESULT_SUCCESS;
1082 }
1083
UpdateAntiBruteFile(uint64_t templateId,bool authResultSucc)1084 static ResultCode UpdateAntiBruteFile(uint64_t templateId, bool authResultSucc)
1085 {
1086 if (templateId == INVALID_TEMPLATE_ID) {
1087 LOG_ERROR("check param fail.");
1088 return RESULT_BAD_PARAM;
1089 }
1090
1091 if (authResultSucc) {
1092 ResultCode ret = ClearAntiBruteInfoById(templateId);
1093 if (ret != RESULT_SUCCESS) {
1094 LOG_ERROR("ClearAntiBruteInfoById fail.");
1095 }
1096 return ret;
1097 }
1098
1099 uint64_t nowTime = GetRtcTime();
1100 uint32_t errorCount = 0;
1101 ResultCode ret = GetAntiBruteCountById(templateId, &errorCount);
1102 if (ret != RESULT_SUCCESS) {
1103 LOG_ERROR("GetAntiBruteCountById fail.");
1104 return ret;
1105 }
1106 if (errorCount < ATTI_BRUTE_SECOND_STAGE) {
1107 errorCount++;
1108 }
1109 ret = SetAntiBruteInfoById(templateId, errorCount, nowTime);
1110 if (ret != RESULT_SUCCESS) {
1111 LOG_ERROR("SetAntiBruteInfoById fail.");
1112 }
1113 return ret;
1114 }
1115
GenerateDecodeCredential(const Buffer * deviceKey,const Buffer * pinData)1116 static Buffer *GenerateDecodeCredential(const Buffer *deviceKey, const Buffer *pinData)
1117 {
1118 Buffer *encryptionKey = GenerateEncryptionKey(deviceKey);
1119 if (!IsBufferValid(encryptionKey)) {
1120 LOG_ERROR("generate encryptionKey fail.");
1121 return NULL;
1122 }
1123
1124 Buffer *pinDecodeCredential = Aes256GcmDecryptNoPadding(pinData, encryptionKey);
1125 DestoryBuffer(encryptionKey);
1126 if (!IsBufferValid(pinDecodeCredential)) {
1127 LOG_ERROR("generate pinDeCredCiphertext fail.");
1128 return NULL;
1129 }
1130
1131 return pinDecodeCredential;
1132 }
1133
ProcessAuthPin(const Buffer * storeData,const uint8_t * inputData,const uint32_t inputDataLen,uint64_t templateId,Buffer * outRootSecret)1134 static ResultCode ProcessAuthPin(const Buffer *storeData, const uint8_t *inputData, const uint32_t inputDataLen,
1135 uint64_t templateId, Buffer *outRootSecret)
1136 {
1137 Buffer *pinCredData = CreateBufferByData(inputData, inputDataLen);
1138 Buffer *secret = CreateBufferBySize(SECRET_SIZE);
1139 Buffer *deviceKey = NULL;
1140 Buffer *pinDecodeCredential = NULL;
1141 ResultCode ret = RESULT_COMPARE_FAIL;
1142 if (!IsBufferValid(pinCredData) || !IsBufferValid(secret)) {
1143 LOG_ERROR("create buffer fail.");
1144 goto EXIT;
1145 }
1146 if (ReadPinFile(secret->buf, secret->maxSize, templateId, SECRET_SUFFIX) != RESULT_SUCCESS) {
1147 LOG_ERROR("read pin secret file fail.");
1148 goto EXIT;
1149 }
1150 secret->contentSize = secret->maxSize;
1151 deviceKey = DeriveDeviceKey(pinCredData, secret);
1152 if (!IsBufferValid(deviceKey)) {
1153 LOG_ERROR("generate deviceKey fail.");
1154 goto EXIT;
1155 }
1156 if (GenerateRootSecret(deviceKey, pinCredData, outRootSecret) != RESULT_SUCCESS) {
1157 LOG_ERROR("generate rootSecret fail.");
1158 goto EXIT;
1159 }
1160 pinDecodeCredential = GenerateDecodeCredential(deviceKey, storeData);
1161 if (!CheckBufferWithSize(pinDecodeCredential, inputDataLen)) {
1162 LOG_ERROR("generate pinDecodeCredential fail.");
1163 goto EXIT;
1164 }
1165 if (memcmp(inputData, pinDecodeCredential->buf, inputDataLen) == 0) {
1166 LOG_INFO("auth pin success.");
1167 ret = RESULT_SUCCESS;
1168 goto EXIT;
1169 }
1170 LOG_ERROR("auth pin fail.");
1171
1172 EXIT:
1173 DestoryBuffer(pinDecodeCredential);
1174 DestoryBuffer(deviceKey);
1175 DestoryBuffer(secret);
1176 DestoryBuffer(pinCredData);
1177 return ret;
1178 }
1179
1180 /* This is for example only, Should be implemented in trusted environment. */
AuthPinById(const uint8_t * inputData,const uint32_t inputDataLen,uint64_t templateId,Buffer * outRootSecret,ResultCode * compareRet)1181 ResultCode AuthPinById(const uint8_t *inputData, const uint32_t inputDataLen, uint64_t templateId,
1182 Buffer *outRootSecret, ResultCode *compareRet)
1183 {
1184 if (inputData == NULL || inputDataLen != CONST_PIN_DATA_LEN || templateId == INVALID_TEMPLATE_ID ||
1185 !IsBufferValid(outRootSecret) || compareRet == NULL) {
1186 LOG_ERROR("get invalid params.");
1187 return RESULT_BAD_PARAM;
1188 }
1189 *compareRet = RESULT_COMPARE_FAIL;
1190 if (SearchPinById(templateId) == MAX_CRYPTO_INFO_SIZE) {
1191 LOG_ERROR("no pin match.");
1192 return RESULT_BAD_MATCH;
1193 }
1194 /* Update anti-brute-force information with authentication failure first */
1195 if (UpdateAntiBruteFile(templateId, false) != RESULT_SUCCESS) {
1196 LOG_ERROR("update antiBrute file fail.");
1197 return RESULT_GENERAL_ERROR;
1198 }
1199 Buffer *storeData = CreateBufferBySize(CONST_PIN_DATA_EXPAND_LEN);
1200 if (!IsBufferValid(storeData)) {
1201 LOG_ERROR("generate storeData fail.");
1202 return RESULT_GENERAL_ERROR;
1203 }
1204 ResultCode ret = ReadPinFile(storeData->buf, storeData->maxSize, templateId, CRYPTO_SUFFIX);
1205 if (ret != RESULT_SUCCESS) {
1206 LOG_ERROR("read pin store file fail.");
1207 DestoryBuffer(storeData);
1208 return RESULT_BAD_READ;
1209 }
1210 storeData->contentSize = storeData->maxSize;
1211 *compareRet = ProcessAuthPin(storeData, inputData, inputDataLen, templateId, outRootSecret);
1212 if ((*compareRet) == RESULT_SUCCESS) {
1213 ret = UpdateAntiBruteFile(templateId, true);
1214 if (ret != RESULT_SUCCESS) {
1215 LOG_ERROR("UpdateAntiBruteFile fail.");
1216 goto EXIT;
1217 }
1218 }
1219 LOG_INFO("AuthPinById end.");
1220
1221 EXIT:
1222 DestoryBuffer(storeData);
1223 return ret;
1224 }
1225
FindTemplateIdFromList(uint64_t storeTemplateId,const uint64_t * templateIdList,uint32_t templateIdListLen)1226 static bool FindTemplateIdFromList(uint64_t storeTemplateId, const uint64_t *templateIdList, uint32_t templateIdListLen)
1227 {
1228 for (uint32_t i = 0; i < templateIdListLen; ++i) {
1229 if (templateIdList[i] == storeTemplateId) {
1230 return true;
1231 }
1232 }
1233
1234 return false;
1235 }
1236
VerifyTemplateDataPin(const uint64_t * templateIdList,uint32_t templateIdListLen)1237 ResultCode VerifyTemplateDataPin(const uint64_t *templateIdList, uint32_t templateIdListLen)
1238 {
1239 if (templateIdListLen != 0 && templateIdList == NULL) {
1240 LOG_ERROR("templateIdList should be not null, when templateIdListLen is not zero");
1241 return RESULT_BAD_PARAM;
1242 }
1243 uint32_t i = 0;
1244 for (; i < g_pinDbOp.pinIndexLen; i++) {
1245 if (FindTemplateIdFromList(g_pinDbOp.pinIndex[i].pinInfo.templateId, templateIdList, templateIdListLen)) {
1246 continue;
1247 }
1248 ResultCode ret = DelPinById(g_pinDbOp.pinIndex[i].pinInfo.templateId);
1249 if (ret != RESULT_SUCCESS) {
1250 LOG_ERROR("delete pin file fail.");
1251 return RESULT_BAD_DEL;
1252 }
1253 }
1254 LOG_INFO("VerifyTemplateDataPin succ.");
1255 return RESULT_SUCCESS;
1256 }
1257