• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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