• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "pin_db.h"
17 
18 #include "securec.h"
19 
20 #include "adaptor_algorithm.h"
21 #include "adaptor_memory.h"
22 #include "adaptor_time.h"
23 #include "defines.h"
24 #include "file_operator.h"
25 #include "pin_db_ops.h"
26 
27 #define MAX_RANDOM_TIME 10
28 #define CRYPTO_SUFFIX "_CryptoInfo"
29 #define SALT_SUFFIX "_salt"
30 #define SECRET_SUFFIX "_secret"
31 #define SALT_PREFIX "hkdf_salt"
32 #define CREDENTIAL_PREFIX "template_encryption_key"
33 #define DEFAULT_VALUE 1
34 #define REMAINING_TIMES_FREEZE 1
35 #define FIRST_ANTI_BRUTE_COUNT 5
36 #define SECOND_ANTI_BRUTE_COUNT 8
37 #define THIRD_ANTI_BRUTE_COUNT 11
38 #define ANTI_BRUTE_COUNT_FREQUENCY 3
39 #define ONE_MIN_TIME 60
40 #define TEN_MIN_TIME 600
41 #define THIRTY_MIN_TIME 1800
42 #define ONE_HOUR_TIME 3600
43 #define ONE_DAY_TIME 86400
44 #define FIRST_EXPONENTIAL_PARA 30
45 #define SECOND_EXPONENTIAL_PARA 2
46 #define THIRD_EXPONENTIAL_PARA 10
47 #define MS_OF_S 1000uLL
48 #define CONST_PIN_DATA_EXPAND_LEN 92U
49 #define CONST_CREDENTIAL_PREFIX_LEN 32U
50 #define CONST_EXPAND_DATA_LEN 128U
51 #define SOURCE_DATA_LENGTH 97
52 #define DEVICE_UUID_LENGTH 65
53 #define SALT_RANDOM_LENGTH 32
54 
55 static PinDbV1 *g_pinDbOp = NULL;
56 static AbandonCacheParam *g_abandonCacheParam = NULL;
57 
LoadPinDb(void)58 bool LoadPinDb(void)
59 {
60     if (g_pinDbOp != NULL) {
61         return true;
62     }
63     g_pinDbOp = ReadPinDb();
64     if (g_pinDbOp == NULL) {
65         LOG_ERROR("ReadPinDb fail.");
66         return false;
67     }
68 
69     LOG_INFO("LoadPinDb succ.");
70     return true;
71 }
72 
DestroyPinDb(void)73 void DestroyPinDb(void)
74 {
75     if (g_pinDbOp == NULL) {
76         LOG_INFO("g_pinDbOp is null.");
77         return;
78     }
79 
80     FreePinDb(&g_pinDbOp);
81     DestroyAbandonParam();
82     LOG_INFO("DestroyPinDb succ.");
83 }
84 
CoverData(const char * fileName,const FileOperator * fileOp)85 static ResultCode CoverData(const char *fileName, const FileOperator *fileOp)
86 {
87     uint32_t fileLen = 0;
88     ResultCode ret = (ResultCode)fileOp->getFileLen(fileName, &fileLen);
89     /* The maximum length of the fileName is CONST_PIN_DATA_EXPAND_LEN */
90     if (ret != RESULT_SUCCESS) {
91         LOG_ERROR("getFileLen fail.");
92         return ret;
93     }
94     if (fileLen > CONST_PIN_DATA_EXPAND_LEN) {
95         LOG_ERROR("Filelen is larger than pin data expand len");
96         return RESULT_GENERAL_ERROR;
97     }
98     uint8_t *data = Malloc(fileLen);
99     if (data == NULL) {
100         LOG_ERROR("no memory.");
101         return RESULT_NO_MEMORY;
102     }
103     (void)memset_s(data, fileLen, 0, fileLen);
104     ret = (ResultCode)fileOp->writeFile(fileName, data, fileLen);
105     Free(data);
106     if (ret != RESULT_SUCCESS) {
107         LOG_ERROR("WritePinFile fail.");
108         return ret;
109     }
110 
111     return RESULT_SUCCESS;
112 }
113 
114 /* This is for example only, Should be implemented in trusted environment. */
RemovePinFile(const uint64_t templateId,const char * suffix,bool needCover)115 static ResultCode RemovePinFile(const uint64_t templateId, const char *suffix, bool needCover)
116 {
117     FileOperator *fileOp = GetFileOperator(DEFAULT_FILE_OPERATOR);
118     if (!IsFileOperatorValid(fileOp)) {
119         LOG_ERROR("fileOp invalid.");
120         return RESULT_GENERAL_ERROR;
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("GenerateCryptoFileName fail.");
126         return RESULT_UNKNOWN;
127     }
128 
129     /* Write data zeros before deleting data, In addition to anti-brute-force cracking */
130     if (needCover) {
131         ret = CoverData(fileName, fileOp);
132         if (ret != RESULT_SUCCESS) {
133             LOG_ERROR("cover data fail.");
134             return RESULT_GENERAL_ERROR;
135         }
136     }
137     if ((ResultCode)fileOp->deleteFile(fileName) != RESULT_SUCCESS) {
138         LOG_ERROR("file remove fail.");
139         return RESULT_BAD_DEL;
140     }
141 
142     LOG_INFO("RemovePinFile succ.");
143     return ret;
144 }
145 
RemoveAllFile(uint64_t templateId)146 static ResultCode RemoveAllFile(uint64_t templateId)
147 {
148     /* This is for example only, Anti-brute-force cracking files must have an anti-rollback zone */
149     ResultCode ret = RemovePinFile(templateId, ANTI_BRUTE_SUFFIX, false);
150     if (ret != RESULT_SUCCESS) {
151         LOG_ERROR("RemovePinAntiBrute fail.");
152     }
153     ret = RemovePinFile(templateId, CRYPTO_SUFFIX, true);
154     if (ret != RESULT_SUCCESS) {
155         LOG_ERROR("RemovePinCrypto fail.");
156     }
157     ret = RemovePinFile(templateId, SALT_SUFFIX, true);
158     if (ret != RESULT_SUCCESS) {
159         LOG_ERROR("RemovePinSalt fail.");
160     }
161     ret = RemovePinFile(templateId, SECRET_SUFFIX, true);
162     if (ret != RESULT_SUCCESS) {
163         LOG_ERROR("RemovePinSecret fail.");
164     }
165     ret = RemovePinFile(templateId, ROOTSECRET_CRYPTO_SUFFIX, true);
166     if (ret != RESULT_SUCCESS) {
167         LOG_ERROR("RemovePinSecret fail.");
168     }
169 
170     LOG_INFO("RemoveAllFile end.");
171     return RESULT_SUCCESS;
172 }
173 
GeneratePinTemplateId(void)174 static uint64_t GeneratePinTemplateId(void)
175 {
176     for (uint32_t i = 0; i < MAX_RANDOM_TIME; i++) {
177         uint64_t templateId = INVALID_TEMPLATE_ID;
178         SecureRandom((uint8_t *)&templateId, sizeof(templateId));
179         if (templateId == INVALID_TEMPLATE_ID) {
180             continue;
181         }
182         uint32_t j = 0;
183         for (; j < g_pinDbOp->pinIndexLen; j++) {
184             if (templateId == g_pinDbOp->pinIndex[j].pinInfo.templateId) {
185                 break;
186             }
187         }
188         if (j == g_pinDbOp->pinIndexLen) {
189             return templateId;
190         }
191     }
192     LOG_ERROR("fail generate pin templateid.");
193     return INVALID_TEMPLATE_ID;
194 }
195 
DelPin(uint64_t templateId)196 static ResultCode DelPin(uint64_t templateId)
197 {
198     /* This is for example only, Should be implemented in trusted environment. */
199     ResultCode ret = RemoveAllFile(templateId);
200     if (ret != RESULT_SUCCESS) {
201         LOG_ERROR("Remove pin file fail.");
202         return ret;
203     }
204 
205     LOG_INFO("DelPin succ.");
206     return RESULT_SUCCESS;
207 }
208 
DelPinInDb(uint32_t index)209 static ResultCode DelPinInDb(uint32_t index)
210 {
211     uint32_t pinIndexLen = g_pinDbOp->pinIndexLen - 1;
212     if (pinIndexLen == 0) {
213         (void)memset_s(g_pinDbOp->pinIndex,
214             g_pinDbOp->pinIndexLen * sizeof(PinIndexV1), 0, g_pinDbOp->pinIndexLen * sizeof(PinIndexV1));
215         Free(g_pinDbOp->pinIndex);
216         g_pinDbOp->pinIndex = NULL;
217     } else {
218         uint32_t size = pinIndexLen * sizeof(PinIndexV1);
219         PinIndexV1 *pinIndex = (PinIndexV1 *)Malloc(size);
220         if (pinIndex == NULL) {
221             LOG_ERROR("PinIndexV1 malloc fail.");
222             return RESULT_NO_MEMORY;
223         }
224         (void)memset_s(pinIndex, size, 0, size);
225         for (uint32_t i = 0, j = 0; i < g_pinDbOp->pinIndexLen; i++) {
226             if (i != index) {
227                 pinIndex[j] = g_pinDbOp->pinIndex[i];
228                 j++;
229             }
230         }
231         (void)memset_s(g_pinDbOp->pinIndex,
232             g_pinDbOp->pinIndexLen * sizeof(PinIndexV1), 0, g_pinDbOp->pinIndexLen * sizeof(PinIndexV1));
233         Free(g_pinDbOp->pinIndex);
234         g_pinDbOp->pinIndex = pinIndex;
235     }
236     LOG_INFO("%{public}u left after del.", pinIndexLen);
237     g_pinDbOp->pinIndexLen = pinIndexLen;
238     ResultCode ret = WritePinDb(g_pinDbOp);
239     if (ret != RESULT_SUCCESS) {
240         LOG_ERROR("WritePinDb fail.");
241         return ret;
242     }
243 
244     LOG_INFO("DelPinInDb succ.");
245     return ret;
246 }
247 
SearchPinIndex(uint64_t templateId,uint32_t * index)248 static ResultCode SearchPinIndex(uint64_t templateId, uint32_t *index)
249 {
250     if (!LoadPinDb()) {
251         LOG_ERROR("SearchPinIndex load pinDb fail.");
252         return RESULT_NEED_INIT;
253     }
254 
255     if (g_pinDbOp->pinIndexLen == 0) {
256         LOG_ERROR("SearchPinIndex no pin exist.");
257         return RESULT_BAD_MATCH;
258     }
259     for (uint32_t i = 0; i < g_pinDbOp->pinIndexLen; i++) {
260         if (g_pinDbOp->pinIndex[i].pinInfo.templateId == templateId) {
261             LOG_INFO("SearchPinIndex succ.");
262             (*index) = i;
263             return RESULT_SUCCESS;
264         }
265     }
266     LOG_ERROR("SearchPinIndex no pin match.");
267     return RESULT_BAD_MATCH;
268 }
269 
DelPinById(uint64_t templateId)270 ResultCode DelPinById(uint64_t templateId)
271 {
272     uint32_t index = MAX_CRYPTO_INFO_SIZE;
273     ResultCode ret = SearchPinIndex(templateId, &index);
274     if (ret != RESULT_SUCCESS) {
275         return ret;
276     }
277 
278     ret = DelPinInDb(index);
279     if (ret != RESULT_SUCCESS) {
280         LOG_ERROR("DelPinInDb fail.");
281         return ret;
282     }
283 
284     ret = DelPin(templateId);
285     if (ret != RESULT_SUCCESS) {
286         LOG_ERROR(" DelPin fail.");
287         return ret;
288     }
289 
290     ret = ReWriteRootSecretFile(templateId);
291     if (ret != RESULT_SUCCESS) {
292         LOG_ERROR(" ReWriteRootSecretFile fail.");
293         return ret;
294     }
295     LOG_INFO("DelPinById succ.");
296     /* ignore pin file remove result, return success when index file remove success */
297     return RESULT_SUCCESS;
298 }
299 
InitPinInfo(PinInfo * pinInfo,uint64_t templateId,uint64_t subType,uint32_t pinLength)300 static void InitPinInfo(PinInfo *pinInfo, uint64_t templateId, uint64_t subType, uint32_t pinLength)
301 {
302     pinInfo->templateId = templateId;
303     pinInfo->subType = subType;
304     pinInfo->algoVersion = ALGORITHM_VERSION_0;
305     pinInfo->pinLength = pinLength;
306 }
307 
InitAntiBruteInfo(AntiBruteInfoV0 * info)308 static void InitAntiBruteInfo(AntiBruteInfoV0 *info)
309 {
310     info->authErrorCount = INIT_AUTH_ERROR_COUNT;
311     info->startFreezeTime = INIT_START_FREEZE_TIMES;
312 }
313 
InitPinIndex(PinIndex * pinIndex,uint64_t templateId,uint64_t subType,uint32_t pinLength)314 static void InitPinIndex(PinIndex *pinIndex, uint64_t templateId, uint64_t subType, uint32_t pinLength)
315 {
316     InitPinInfo(&(pinIndex->pinInfo), templateId, subType, pinLength);
317     InitAntiBruteInfo(&(pinIndex->antiBruteInfo));
318 }
319 
AddPinInDb(uint64_t templateId,uint64_t subType,uint32_t pinLength)320 static ResultCode AddPinInDb(uint64_t templateId, uint64_t subType, uint32_t pinLength)
321 {
322     if (g_pinDbOp->pinIndexLen > MAX_CRYPTO_INFO_SIZE - 1) {
323         LOG_ERROR("pinIndexLen too large.");
324         return RESULT_BAD_PARAM;
325     }
326     uint32_t size = (g_pinDbOp->pinIndexLen + 1) * sizeof(PinIndexV1);
327     PinIndexV1 *pinIndex = (PinIndexV1 *)Malloc(size);
328     if (pinIndex == NULL) {
329         LOG_ERROR("PinIndexV1 malloc fail.");
330         return RESULT_NO_MEMORY;
331     }
332     (void)memset_s(pinIndex, size, 0, size);
333     if (g_pinDbOp->pinIndexLen != 0) {
334         if (memcpy_s(pinIndex, size,
335             g_pinDbOp->pinIndex, g_pinDbOp->pinIndexLen * sizeof(PinIndexV1)) != EOK) {
336             LOG_ERROR("PinIndexV1 copy fail.");
337             (void)memset_s(pinIndex, size, 0, size);
338             Free(pinIndex);
339             return RESULT_NO_MEMORY;
340         }
341     }
342     InitPinIndex(&pinIndex[g_pinDbOp->pinIndexLen], templateId, subType, pinLength);
343     if (g_pinDbOp->pinIndex != NULL) {
344         Free(g_pinDbOp->pinIndex);
345     }
346     g_pinDbOp->pinIndex = pinIndex;
347     g_pinDbOp->pinIndexLen++;
348     ResultCode ret = WritePinDb(g_pinDbOp);
349     if (ret != RESULT_SUCCESS) {
350         LOG_ERROR("WritePinDb fail.");
351         return ret;
352     }
353 
354     LOG_INFO("AddPinInDb succ.");
355     return RESULT_SUCCESS;
356 }
357 
WriteAddPinInfo(const Buffer * secret,const Buffer * pinCredentialData,uint8_t * salt,uint32_t saltLen,const uint64_t templateId)358 static ResultCode WriteAddPinInfo(const Buffer *secret, const Buffer *pinCredentialData, uint8_t *salt,
359     uint32_t saltLen, const uint64_t templateId)
360 {
361     ResultCode ret = WritePinFile(pinCredentialData->buf, pinCredentialData->contentSize, templateId, CRYPTO_SUFFIX);
362     if (ret != RESULT_SUCCESS) {
363         LOG_ERROR("WriteCryptoFile fail.");
364         return ret;
365     }
366 
367     ret = WritePinFile(salt, saltLen, templateId, SALT_SUFFIX);
368     if (ret != RESULT_SUCCESS) {
369         LOG_ERROR("WriteSaltFile fail.");
370         return ret;
371     }
372 
373     ret = WritePinFile(secret->buf, secret->contentSize, templateId, SECRET_SUFFIX);
374     if (ret != RESULT_SUCCESS) {
375         LOG_ERROR("WriteSecretFile fail.");
376         return ret;
377     }
378     AntiBruteInfoV0 initAntiBrute = {};
379     InitAntiBruteInfo(&initAntiBrute);
380     ret = WritePinFile((uint8_t *)(&initAntiBrute), sizeof(AntiBruteInfoV0), templateId, ANTI_BRUTE_SUFFIX);
381     if (ret != RESULT_SUCCESS) {
382         LOG_ERROR("WriteAntiBruteFile fail.");
383         return ret;
384     }
385 
386     LOG_INFO("WriteAddPinInfo succ.");
387     return RESULT_SUCCESS;
388 }
389 
GenerateExpandData(char * str,const uint8_t * data,const uint32_t dataLen)390 static Buffer *GenerateExpandData(char *str, const uint8_t *data, const uint32_t dataLen)
391 {
392     /* CONST_EXPAND_DATA_LEN is twice the size of dataLen */
393     int32_t multiple = 2;
394     if (dataLen < strlen(str) || dataLen != (CONST_EXPAND_DATA_LEN / multiple)) {
395         LOG_ERROR("bad param.");
396         return NULL;
397     }
398     Buffer *outBuff = CreateBufferBySize(CONST_EXPAND_DATA_LEN);
399     if (!IsBufferValid(outBuff)) {
400         LOG_ERROR("create buffer fail.");
401         return NULL;
402     }
403     (void)memset_s(outBuff->buf, outBuff->maxSize, 0, outBuff->maxSize);
404     outBuff->contentSize = outBuff->maxSize;
405     uint8_t *temp = outBuff->buf;
406     if (memcpy_s(temp, outBuff->maxSize, (uint8_t *)str, strlen(str)) != EOK) {
407         LOG_ERROR("copy str fail.");
408         DestroyBuffer(outBuff);
409         return NULL;
410     }
411 
412     temp += dataLen;
413     if (memcpy_s(temp, outBuff->maxSize - dataLen, data, dataLen) != EOK) {
414         LOG_ERROR("copy data fail.");
415         DestroyBuffer(outBuff);
416         return NULL;
417     }
418 
419     return outBuff;
420 }
421 
GenerateRootSecret(const Buffer * deviceKey,const Buffer * pinData,Buffer * outRootSecret)422 static ResultCode GenerateRootSecret(const Buffer *deviceKey, const Buffer *pinData, Buffer *outRootSecret)
423 {
424     Buffer *expandData = GenerateExpandData(SALT_PREFIX, pinData->buf, pinData->contentSize);
425     if (!IsBufferValid(expandData)) {
426         LOG_ERROR("generate expand data fail.");
427         return RESULT_GENERAL_ERROR;
428     }
429 
430     Buffer *hkdfSalt = Sha256Adaptor(expandData);
431     if (!IsBufferValid(hkdfSalt)) {
432         LOG_ERROR("generate sha256 fail.");
433         DestroyBuffer(expandData);
434         return RESULT_GENERAL_ERROR;
435     }
436     Buffer *rootSecret = Hkdf(hkdfSalt, deviceKey);
437     DestroyBuffer(expandData);
438     DestroyBuffer(hkdfSalt);
439     if (!IsBufferValid(rootSecret)) {
440         LOG_ERROR("generate rootSecret fail.");
441         return RESULT_GENERAL_ERROR;
442     }
443     if (memcpy_s(outRootSecret->buf, outRootSecret->maxSize, rootSecret->buf, rootSecret->contentSize) != EOK) {
444         LOG_ERROR("copy root secret fail.");
445         DestroyBuffer(rootSecret);
446         return RESULT_BAD_COPY;
447     }
448 
449     outRootSecret->contentSize = rootSecret->contentSize;
450     DestroyBuffer(rootSecret);
451     return RESULT_SUCCESS;
452 }
453 
GenerateEncryptionKey(const Buffer * deviceKey)454 static Buffer *GenerateEncryptionKey(const Buffer *deviceKey)
455 {
456     Buffer *keyStrBuffer = CreateBufferBySize(CONST_CREDENTIAL_PREFIX_LEN);
457     if (!IsBufferValid(keyStrBuffer)) {
458         LOG_ERROR("generate expand data fail.");
459         return NULL;
460     }
461     (void)memset_s(keyStrBuffer->buf, keyStrBuffer->maxSize, 0, keyStrBuffer->maxSize);
462     if (memcpy_s(keyStrBuffer->buf, keyStrBuffer->maxSize,
463         (uint8_t *)CREDENTIAL_PREFIX, strlen(CREDENTIAL_PREFIX)) != EOK) {
464         LOG_ERROR("copy CREDENTIAL_PREFIX fail.");
465         DestroyBuffer(keyStrBuffer);
466         return NULL;
467     }
468     keyStrBuffer->contentSize = keyStrBuffer->maxSize;
469     Buffer *encryptionKey = Hkdf(keyStrBuffer, deviceKey);
470     DestroyBuffer(keyStrBuffer);
471     if (!IsBufferValid(encryptionKey)) {
472         LOG_ERROR("generate encryptionKey fail.");
473         return NULL;
474     }
475 
476     return encryptionKey;
477 }
478 
SplicePinCiperInfo(const Buffer * iv,const Buffer * tag,const Buffer * ciphertext)479 static Buffer *SplicePinCiperInfo(const Buffer *iv, const Buffer *tag, const Buffer *ciphertext)
480 {
481     Buffer *cipherInfo = CreateBufferBySize(iv->contentSize + tag->contentSize + ciphertext->contentSize);
482     if (cipherInfo == NULL) {
483         LOG_ERROR("create cipherInfo fail");
484         return NULL;
485     }
486     if (memcpy_s(cipherInfo->buf, cipherInfo->maxSize, iv->buf, iv->contentSize) != EOK) {
487         LOG_ERROR("failed to copy iv");
488         goto ERROR;
489     }
490     cipherInfo->contentSize += iv->contentSize;
491     if (memcpy_s(cipherInfo->buf + cipherInfo->contentSize, cipherInfo->maxSize - cipherInfo->contentSize,
492         tag->buf, tag->contentSize) != EOK) {
493         LOG_ERROR("failed to copy tag");
494         goto ERROR;
495     }
496     cipherInfo->contentSize += tag->contentSize;
497     if (memcpy_s(cipherInfo->buf + cipherInfo->contentSize, cipherInfo->maxSize - cipherInfo->contentSize,
498         ciphertext->buf, ciphertext->contentSize) != EOK) {
499         LOG_ERROR("failed to copy ciphertext");
500         goto ERROR;
501     }
502     cipherInfo->contentSize += ciphertext->contentSize;
503     return cipherInfo;
504 
505 ERROR:
506     DestroyBuffer(cipherInfo);
507     return NULL;
508 }
509 
GetPinCiperInfo(Buffer * key,Buffer * pinData)510 static Buffer *GetPinCiperInfo(Buffer *key, Buffer *pinData)
511 {
512     Buffer *cipherText = NULL;
513     Buffer *tag = NULL;
514     Buffer *cipherInfo = NULL;
515     AesGcmParam param = {};
516     param.key = key;
517     param.iv = CreateBufferBySize(AES_GCM_256_IV_SIZE);
518     if (!IsBufferValid(param.iv)) {
519         LOG_ERROR("create iv fail.");
520         goto EXIT;
521     }
522     if (SecureRandom(param.iv->buf, param.iv->maxSize) != RESULT_SUCCESS) {
523         LOG_ERROR("random iv fail.");
524         goto EXIT;
525     }
526     param.iv->contentSize = param.iv->maxSize;
527     if (AesGcm256Encrypt(pinData, &param, &cipherText, &tag) != RESULT_SUCCESS) {
528         LOG_ERROR("AesGcmEncrypt fail.");
529         goto EXIT;
530     }
531 
532     cipherInfo = SplicePinCiperInfo(param.iv, tag, cipherText);
533     if (cipherInfo == NULL) {
534         LOG_ERROR("SplicePinCiperInfo fail.");
535         goto EXIT;
536     }
537 
538 EXIT:
539     DestroyBuffer(param.iv);
540     DestroyBuffer(cipherText);
541     DestroyBuffer(tag);
542 
543     return cipherInfo;
544 }
545 
CreateSecretBuffer()546 static Buffer *CreateSecretBuffer()
547 {
548     Buffer *secret = CreateBufferBySize(SECRET_SIZE);
549     if (!IsBufferValid(secret)) {
550         LOG_ERROR("generate buffer fail.");
551         return secret;
552     }
553     if (SecureRandom(secret->buf, secret->maxSize) != RESULT_SUCCESS) {
554         LOG_ERROR("generate secure random number fail.");
555         DestroyBuffer(secret);
556         return NULL;
557     }
558     secret->contentSize = secret->maxSize;
559     return secret;
560 }
561 
ProcessAddPin(const Buffer * deviceKey,const Buffer * secret,PinEnrollParam * pinEnrollParam,uint64_t * templateId)562 static ResultCode ProcessAddPin(const Buffer *deviceKey, const Buffer *secret, PinEnrollParam *pinEnrollParam,
563     uint64_t *templateId)
564 {
565     *templateId = GeneratePinTemplateId();
566     if (*templateId == INVALID_TEMPLATE_ID) {
567         LOG_ERROR("GeneratePinTemplateId fail.");
568         return RESULT_GENERAL_ERROR;
569     }
570 
571     Buffer *key = GenerateEncryptionKey(deviceKey);
572     if (!IsBufferValid(key)) {
573         LOG_ERROR("GenerateEncryptionKey fail.");
574         return RESULT_GENERAL_ERROR;
575     }
576     Buffer pinDataBuffer = GetTmpBuffer(pinEnrollParam->pinData, CONST_PIN_DATA_LEN, CONST_PIN_DATA_LEN);
577     Buffer *cipherInfo = GetPinCiperInfo(key, &pinDataBuffer);
578     DestroyBuffer(key);
579     if (cipherInfo == NULL) {
580         LOG_ERROR("GetPinCiperInfo fail.");
581         return RESULT_GENERAL_ERROR;
582     }
583 
584     ResultCode ret = WriteAddPinInfo(secret, cipherInfo, pinEnrollParam->salt, CONST_SALT_LEN, *templateId);
585     DestroyBuffer(cipherInfo);
586     if (ret != RESULT_SUCCESS) {
587         LOG_ERROR("write add pin info fail.");
588         (void)RemoveAllFile(*templateId);
589         return ret;
590     }
591 
592     ret = AddPinInDb(*templateId, pinEnrollParam->subType, pinEnrollParam->pinLength);
593     if (ret != RESULT_SUCCESS) {
594         LOG_ERROR("AddPinDb fail.");
595         (void)RemoveAllFile(*templateId);
596         return ret;
597     }
598     return ret;
599 }
600 
UpdatePinLength(uint64_t templateId,uint32_t pinLength)601 static ResultCode UpdatePinLength(uint64_t templateId, uint32_t pinLength)
602 {
603     LOG_INFO("start UpdatePinLength");
604     if (templateId == INVALID_TEMPLATE_ID) {
605         LOG_ERROR("check param fail.");
606         return RESULT_BAD_PARAM;
607     }
608 
609     uint32_t index = MAX_CRYPTO_INFO_SIZE;
610     ResultCode ret = SearchPinIndex(templateId, &index);
611     if (ret != RESULT_SUCCESS) {
612         return ret;
613     }
614     uint32_t currentPinLength = g_pinDbOp->pinIndex[index].pinInfo.pinLength;
615     LOG_INFO("currentPinLength : %{public}u, inputPinLength : %{public}u", currentPinLength, pinLength);
616     if (currentPinLength == pinLength) {
617         return RESULT_SUCCESS;
618     }
619     g_pinDbOp->pinIndex[index].pinInfo.pinLength = pinLength;
620     ret = WritePinDb(g_pinDbOp);
621     if (ret != RESULT_SUCCESS) {
622         LOG_ERROR("WritePinDb fail.");
623         return ret;
624     }
625     LOG_INFO("end UpdatePinLength");
626     return ret;
627 }
628 
629 /* This is for example only, Should be implemented in trusted environment. */
AddPin(PinEnrollParam * pinEnrollParam,uint64_t * templateId,Buffer * outRootSecret)630 ResultCode AddPin(PinEnrollParam *pinEnrollParam, uint64_t *templateId, Buffer *outRootSecret)
631 {
632     if (!LoadPinDb()) {
633         LOG_ERROR("LoadPinDb fail.");
634         return RESULT_NEED_INIT;
635     }
636     if (pinEnrollParam == NULL || templateId == NULL || !IsBufferValid(outRootSecret)) {
637         LOG_ERROR("get invalid params.");
638         return RESULT_BAD_PARAM;
639     }
640     ResultCode ret = RESULT_GENERAL_ERROR;
641     Buffer pinCredData = GetTmpBuffer(pinEnrollParam->pinData, CONST_PIN_DATA_LEN, CONST_PIN_DATA_LEN);
642     Buffer *secret = CreateSecretBuffer();
643     Buffer *deviceKey = NULL;
644     if (!IsBufferValid(secret)) {
645         LOG_ERROR("generate buffer fail.");
646         ret = RESULT_NO_MEMORY;
647         goto ERROR;
648     }
649     deviceKey = DeriveDeviceKey(&pinCredData, secret);
650     if (!IsBufferValid(deviceKey)) {
651         LOG_ERROR("generate deviceKey fail.");
652         ret = RESULT_GENERAL_ERROR;
653         goto ERROR;
654     }
655     ret = GenerateRootSecret(deviceKey, &pinCredData, outRootSecret);
656     if (ret != RESULT_SUCCESS) {
657         LOG_ERROR("generate rootSecret fail.");
658         goto ERROR;
659     }
660     ret = ProcessAddPin(deviceKey, secret, pinEnrollParam, templateId);
661     if (ret != RESULT_SUCCESS) {
662         LOG_ERROR("process add pin fail.");
663         goto ERROR;
664     }
665     LOG_INFO("AddPin succ.");
666 
667 ERROR:
668     DestroyBuffer(deviceKey);
669     DestroyBuffer(secret);
670     return ret;
671 }
672 
DoGetAlgoParameter(uint64_t templateId,uint8_t * salt,uint32_t * saltLen,uint32_t * algoVersion)673 ResultCode DoGetAlgoParameter(uint64_t templateId, uint8_t *salt, uint32_t *saltLen, uint32_t *algoVersion)
674 {
675     if (salt == NULL || saltLen == NULL || templateId == INVALID_TEMPLATE_ID || algoVersion == NULL) {
676         LOG_ERROR("get invalid algorithm params.");
677         return RESULT_BAD_PARAM;
678     }
679     if (!LoadPinDb()) {
680         LOG_ERROR("LoadPinDb fail.");
681         return RESULT_NEED_INIT;
682     }
683 
684     uint32_t index = MAX_CRYPTO_INFO_SIZE;
685     ResultCode ret = SearchPinIndex(templateId, &index);
686     if (ret != RESULT_SUCCESS) {
687         return ret;
688     }
689 
690     ret = ReadPinFile(salt, *saltLen, templateId, SALT_SUFFIX);
691     if (ret != RESULT_SUCCESS) {
692         LOG_ERROR("salt file read fail.");
693         return ret;
694     }
695 
696     *algoVersion = g_pinDbOp->pinIndex[index].pinInfo.algoVersion;
697     LOG_INFO("DoGetAlgoParameter succ.");
698     return RESULT_SUCCESS;
699 }
700 
GetAntiBruteCountById(uint64_t templateId,uint32_t * count)701 static ResultCode GetAntiBruteCountById(uint64_t templateId, uint32_t *count)
702 {
703     uint32_t index = MAX_CRYPTO_INFO_SIZE;
704     ResultCode ret = SearchPinIndex(templateId, &index);
705     if (ret != RESULT_SUCCESS) {
706         return ret;
707     }
708     *count = g_pinDbOp->pinIndex[index].antiBruteInfo.authErrorCount;
709     return RESULT_SUCCESS;
710 }
711 
RefreshAntiBruteInfoToFile(uint64_t templateId)712 ResultCode RefreshAntiBruteInfoToFile(uint64_t templateId)
713 {
714     if (!LoadPinDb()) {
715         LOG_ERROR("LoadPinDb fail.");
716         return RESULT_NEED_INIT;
717     }
718     uint32_t index = MAX_CRYPTO_INFO_SIZE;
719     ResultCode ret = SearchPinIndex(templateId, &index);
720     if (ret != RESULT_SUCCESS) {
721         return ret;
722     }
723     ret = WritePinFile((uint8_t *)(&(g_pinDbOp->pinIndex[index].antiBruteInfo)), sizeof(AntiBruteInfoV0),
724         templateId, ANTI_BRUTE_SUFFIX);
725     if (ret != RESULT_SUCCESS) {
726         LOG_ERROR("write anti brute fail.");
727     }
728 
729     return ret;
730 }
731 
SetAntiBruteInfoById(uint64_t templateId,uint32_t count,uint64_t startFreezeTime)732 static ResultCode SetAntiBruteInfoById(uint64_t templateId, uint32_t count, uint64_t startFreezeTime)
733 {
734     uint32_t index = MAX_CRYPTO_INFO_SIZE;
735     ResultCode ret = SearchPinIndex(templateId, &index);
736     if (ret != RESULT_SUCCESS) {
737         return ret;
738     }
739     g_pinDbOp->pinIndex[index].antiBruteInfo.authErrorCount = count;
740     g_pinDbOp->pinIndex[index].antiBruteInfo.startFreezeTime = startFreezeTime;
741     ret = WritePinFile((uint8_t *)(&(g_pinDbOp->pinIndex[index].antiBruteInfo)), sizeof(AntiBruteInfoV0),
742         templateId, ANTI_BRUTE_SUFFIX);
743     if (ret != RESULT_SUCCESS) {
744         LOG_ERROR("write anti brute fail.");
745         return ret;
746     }
747     return ret;
748 }
749 
GetSubType(uint64_t templateId,uint64_t * subType)750 ResultCode GetSubType(uint64_t templateId, uint64_t *subType)
751 {
752     if (templateId == INVALID_TEMPLATE_ID) {
753         LOG_ERROR("check param fail!");
754         return RESULT_BAD_PARAM;
755     }
756     if (!LoadPinDb()) {
757         LOG_ERROR("LoadPinDb fail.");
758         return RESULT_NEED_INIT;
759     }
760 
761     uint32_t index = MAX_CRYPTO_INFO_SIZE;
762     ResultCode ret = SearchPinIndex(templateId, &index);
763     if (ret != RESULT_SUCCESS) {
764         return ret;
765     }
766     *subType = g_pinDbOp->pinIndex[index].pinInfo.subType;
767 
768     LOG_INFO("GetSubType succ.");
769     return RESULT_SUCCESS;
770 }
771 
GetAntiBruteInfo(uint64_t templateId,uint32_t * authErrorCount,uint64_t * startFreezeTime)772 ResultCode GetAntiBruteInfo(uint64_t templateId, uint32_t *authErrorCount, uint64_t *startFreezeTime)
773 {
774     if (authErrorCount == NULL || startFreezeTime == NULL || templateId == INVALID_TEMPLATE_ID) {
775         LOG_ERROR("check GetAntiBruteInfo param fail!");
776         return RESULT_BAD_PARAM;
777     }
778     if (!LoadPinDb()) {
779         LOG_ERROR("LoadPinDb fail.");
780         return RESULT_NEED_INIT;
781     }
782 
783     uint32_t index = MAX_CRYPTO_INFO_SIZE;
784     ResultCode ret = SearchPinIndex(templateId, &index);
785     if (ret != RESULT_SUCCESS) {
786         return ret;
787     }
788     *authErrorCount = g_pinDbOp->pinIndex[index].antiBruteInfo.authErrorCount;
789     *startFreezeTime = g_pinDbOp->pinIndex[index].antiBruteInfo.startFreezeTime;
790 
791     LOG_INFO("GetAntiBruteInfo succ.");
792     return RESULT_SUCCESS;
793 }
794 
ExponentialFuncTime(uint32_t authErrorCount)795 static uint64_t ExponentialFuncTime(uint32_t authErrorCount)
796 {
797     uint32_t ret = DEFAULT_VALUE;
798     uint32_t exp = (authErrorCount - FIRST_EXPONENTIAL_PARA) / THIRD_EXPONENTIAL_PARA;
799     for (uint32_t index = 0; index < exp; ++index) {
800         ret *= SECOND_EXPONENTIAL_PARA;
801     }
802     return FIRST_EXPONENTIAL_PARA * ret;
803 }
804 
GetWaitTime(uint32_t authErrorCount)805 static uint64_t GetWaitTime(uint32_t authErrorCount)
806 {
807     if (authErrorCount < FIRST_ANTI_BRUTE_COUNT) {
808         return 0;
809     }
810     if (authErrorCount < ATTI_BRUTE_FIRST_STAGE) {
811         if (authErrorCount == FIRST_ANTI_BRUTE_COUNT) {
812             return ONE_MIN_TIME * MS_OF_S;
813         }
814         if (authErrorCount == SECOND_ANTI_BRUTE_COUNT) {
815             return TEN_MIN_TIME * MS_OF_S;
816         }
817         if (authErrorCount == THIRD_ANTI_BRUTE_COUNT) {
818             return THIRTY_MIN_TIME * MS_OF_S;
819         }
820         if (((authErrorCount - FIRST_ANTI_BRUTE_COUNT) % ANTI_BRUTE_COUNT_FREQUENCY) == 0) {
821             return ONE_HOUR_TIME * MS_OF_S;
822         }
823         return 0;
824     }
825     if (authErrorCount >= ATTI_BRUTE_SECOND_STAGE) {
826         return ONE_DAY_TIME * MS_OF_S;
827     }
828     return ExponentialFuncTime(authErrorCount) * MS_OF_S;
829 }
830 
GetNextFailLockoutDuration(uint32_t authErrorCount)831 int32_t GetNextFailLockoutDuration(uint32_t authErrorCount)
832 {
833     if (authErrorCount < FIRST_ANTI_BRUTE_COUNT) {
834         return ONE_MIN_TIME * MS_OF_S;
835     }
836     if (authErrorCount < SECOND_ANTI_BRUTE_COUNT) {
837         return TEN_MIN_TIME * MS_OF_S;
838     }
839     if (authErrorCount < THIRD_ANTI_BRUTE_COUNT) {
840         return THIRTY_MIN_TIME * MS_OF_S;
841     }
842     if (authErrorCount < ATTI_BRUTE_FIRST_STAGE -
843         (ATTI_BRUTE_FIRST_STAGE - FIRST_ANTI_BRUTE_COUNT) % ANTI_BRUTE_COUNT_FREQUENCY) {
844         return ONE_HOUR_TIME * MS_OF_S;
845     }
846     if (authErrorCount < ATTI_BRUTE_FIRST_STAGE) {
847         return (int32_t)ExponentialFuncTime(ATTI_BRUTE_FIRST_STAGE) * MS_OF_S;
848     }
849     if (authErrorCount < ATTI_BRUTE_SECOND_STAGE - 1) {
850         return (int32_t)ExponentialFuncTime(authErrorCount + 1) * MS_OF_S;
851     }
852     return ONE_DAY_TIME * MS_OF_S;
853 }
854 
ComputeFreezeTime(uint64_t templateId,uint32_t * freezeTime,uint32_t count,uint64_t startFreezeTime)855 ResultCode ComputeFreezeTime(uint64_t templateId, uint32_t *freezeTime, uint32_t count, uint64_t startFreezeTime)
856 {
857     if (templateId == INVALID_TEMPLATE_ID || freezeTime == NULL) {
858         LOG_ERROR("check ComputeFreezeTime param fail!");
859         return RESULT_BAD_PARAM;
860     }
861     if (!LoadPinDb()) {
862         LOG_ERROR("LoadPinDb fail.");
863         return RESULT_NEED_INIT;
864     }
865     uint64_t timeValue = GetRtcTime();
866     uint64_t waitTime = GetWaitTime(count);
867     if (timeValue >= startFreezeTime) {
868         uint64_t usedTime = timeValue - startFreezeTime;
869         if (usedTime >= waitTime) {
870             *freezeTime = 0;
871         } else {
872             *freezeTime = (waitTime - usedTime) & 0xffffffff;
873         }
874     } else {
875         /* rtc time is reset, we should update startFreezeTime to timeValue */
876         if (SetAntiBruteInfoById(templateId, count, timeValue) != RESULT_SUCCESS) {
877             LOG_ERROR("SetAntiBruteInfoById fail.");
878             return RESULT_BAD_PARAM;
879         }
880         *freezeTime = waitTime & 0xffffffff;
881     }
882 
883     LOG_INFO("ComputeFreezeTime succ.");
884     return RESULT_SUCCESS;
885 }
886 
ComputeRemainingTimes(uint32_t errorCount)887 static uint32_t ComputeRemainingTimes(uint32_t errorCount)
888 {
889     if (errorCount < FIRST_ANTI_BRUTE_COUNT) {
890         return FIRST_ANTI_BRUTE_COUNT - errorCount;
891     }
892     if (errorCount >= ATTI_BRUTE_FIRST_STAGE) {
893         return REMAINING_TIMES_FREEZE;
894     }
895     return ANTI_BRUTE_COUNT_FREQUENCY - (errorCount - FIRST_ANTI_BRUTE_COUNT) % ANTI_BRUTE_COUNT_FREQUENCY;
896 }
897 
GetRemainTimes(uint64_t templateId,uint32_t * remainingAuthTimes,uint32_t authErrorCount)898 ResultCode GetRemainTimes(uint64_t templateId, uint32_t *remainingAuthTimes, uint32_t authErrorCount)
899 {
900     if (templateId == INVALID_TEMPLATE_ID || remainingAuthTimes == NULL) {
901         LOG_ERROR("check GetRemainTimes param fail!");
902         return RESULT_BAD_PARAM;
903     }
904     if (!LoadPinDb()) {
905         LOG_ERROR("LoadPinDb fail.");
906         return RESULT_NEED_INIT;
907     }
908     *remainingAuthTimes = ComputeRemainingTimes(authErrorCount);
909     return RESULT_SUCCESS;
910 }
911 
ClearAntiBruteInfoById(uint64_t templateId)912 static ResultCode ClearAntiBruteInfoById(uint64_t templateId)
913 {
914     uint32_t index = MAX_CRYPTO_INFO_SIZE;
915     ResultCode ret = SearchPinIndex(templateId, &index);
916     if (ret != RESULT_SUCCESS) {
917         return ret;
918     }
919     InitAntiBruteInfo(&(g_pinDbOp->pinIndex[index].antiBruteInfo));
920     return RESULT_SUCCESS;
921 }
922 
UpdateAntiBruteFile(uint64_t templateId,bool authResultSucc)923 static ResultCode UpdateAntiBruteFile(uint64_t templateId, bool authResultSucc)
924 {
925     if (templateId == INVALID_TEMPLATE_ID) {
926         LOG_ERROR("check param fail.");
927         return RESULT_BAD_PARAM;
928     }
929 
930     if (authResultSucc) {
931         ResultCode ret = ClearAntiBruteInfoById(templateId);
932         if (ret != RESULT_SUCCESS) {
933             LOG_ERROR("ClearAntiBruteInfoById fail.");
934         }
935         return ret;
936     }
937 
938     uint64_t nowTime = GetRtcTime();
939     uint32_t errorCount = 0;
940     ResultCode ret = GetAntiBruteCountById(templateId, &errorCount);
941     if (ret != RESULT_SUCCESS) {
942         LOG_ERROR("GetAntiBruteCountById fail.");
943         return ret;
944     }
945     if (errorCount < ATTI_BRUTE_SECOND_STAGE) {
946         errorCount++;
947     }
948     ret = SetAntiBruteInfoById(templateId, errorCount, nowTime);
949     if (ret != RESULT_SUCCESS) {
950         LOG_ERROR("SetAntiBruteInfoById fail.");
951     }
952     return ret;
953 }
954 
GenerateDecodeCredential(const Buffer * deviceKey,const Buffer * pinData)955 static Buffer *GenerateDecodeCredential(const Buffer *deviceKey, const Buffer *pinData)
956 {
957     if (pinData->contentSize <= AES_GCM_256_IV_SIZE + AES_GCM_256_TAG_SIZE) {
958         LOG_ERROR("check pin data cipher info fail");
959         return NULL;
960     }
961 
962     AesGcmParam param = {};
963     Buffer iv = GetTmpBuffer(pinData->buf, AES_GCM_256_IV_SIZE, AES_GCM_256_IV_SIZE);
964     param.iv = &iv;
965     param.key = GenerateEncryptionKey(deviceKey);
966     if (param.key == NULL) {
967         LOG_ERROR("GenerateEncryptionKey fail");
968         return NULL;
969     }
970     Buffer tag = GetTmpBuffer(pinData->buf + AES_GCM_256_IV_SIZE, AES_GCM_256_TAG_SIZE, AES_GCM_256_TAG_SIZE);
971     uint32_t cipherTextSize = pinData->contentSize - AES_GCM_256_IV_SIZE - AES_GCM_256_TAG_SIZE;
972     Buffer cipherText = GetTmpBuffer(
973         pinData->buf + AES_GCM_256_IV_SIZE + AES_GCM_256_TAG_SIZE, cipherTextSize, cipherTextSize);
974     Buffer *plainText = NULL;
975     int32_t result = AesGcm256Decrypt(&cipherText, &param, &tag, &plainText);
976     DestroyBuffer(param.key);
977     if (result != RESULT_SUCCESS) {
978         LOG_ERROR("Aes256GcmDecrypt fail");
979         return NULL;
980     }
981 
982     return plainText;
983 }
984 
ProcessAuthPin(const Buffer * storeData,const Buffer * inputData,uint64_t templateId,Buffer * outRootSecret)985 static ResultCode ProcessAuthPin(
986     const Buffer *storeData, const Buffer *inputData, uint64_t templateId, Buffer *outRootSecret)
987 {
988     Buffer *secret = CreateBufferBySize(SECRET_SIZE);
989     Buffer *deviceKey = NULL;
990     Buffer *pinDecodeCredential = NULL;
991     ResultCode ret = RESULT_COMPARE_FAIL;
992     if (!IsBufferValid(secret)) {
993         LOG_ERROR("create buffer fail.");
994         goto EXIT;
995     }
996     if (ReadPinFile(secret->buf, secret->maxSize, templateId, SECRET_SUFFIX) != RESULT_SUCCESS) {
997         LOG_ERROR("read pin secret file fail.");
998         goto EXIT;
999     }
1000     secret->contentSize = secret->maxSize;
1001     deviceKey = DeriveDeviceKey(inputData, secret);
1002     if (!IsBufferValid(deviceKey)) {
1003         LOG_ERROR("generate deviceKey fail.");
1004         goto EXIT;
1005     }
1006     if ((outRootSecret != NULL) &&
1007         GenerateRootSecret(deviceKey, inputData, outRootSecret) != RESULT_SUCCESS) {
1008         LOG_ERROR("generate rootSecret fail.");
1009         goto EXIT;
1010     }
1011     pinDecodeCredential = GenerateDecodeCredential(deviceKey, storeData);
1012     if (!CheckBufferWithSize(pinDecodeCredential, inputData->contentSize)) {
1013         LOG_ERROR("generate pinDecodeCredential fail.");
1014         goto EXIT;
1015     }
1016     if (CompareBuffer(inputData, pinDecodeCredential)) {
1017         LOG_INFO("auth pin success.");
1018         ret = RESULT_SUCCESS;
1019         goto EXIT;
1020     }
1021     LOG_ERROR("auth pin fail.");
1022 
1023 EXIT:
1024     DestroyBuffer(pinDecodeCredential);
1025     DestroyBuffer(deviceKey);
1026     DestroyBuffer(secret);
1027     return ret;
1028 }
1029 
1030 /* This is for example only, Should be implemented in trusted environment. */
AuthPinById(const Buffer * inputPinData,uint64_t templateId,uint32_t pinLength,Buffer * outRootSecret,ResultCode * compareRet)1031 ResultCode AuthPinById(const Buffer *inputPinData, uint64_t templateId, uint32_t pinLength, Buffer *outRootSecret,
1032     ResultCode *compareRet)
1033 {
1034     if (!CheckBufferWithSize(inputPinData, CONST_PIN_DATA_LEN) ||
1035         templateId == INVALID_TEMPLATE_ID || compareRet == NULL) {
1036         LOG_ERROR("get invalid params.");
1037         return RESULT_BAD_PARAM;
1038     }
1039     if (!LoadPinDb()) {
1040         LOG_ERROR("LoadPinDb fail.");
1041         return RESULT_NEED_INIT;
1042     }
1043     *compareRet = RESULT_COMPARE_FAIL;
1044     uint32_t index = MAX_CRYPTO_INFO_SIZE;
1045     ResultCode ret = SearchPinIndex(templateId, &index);
1046     if (ret != RESULT_SUCCESS) {
1047         return ret;
1048     }
1049     /* Update anti-brute-force information with authentication failure first */
1050     if (UpdateAntiBruteFile(templateId, false) != RESULT_SUCCESS) {
1051         LOG_ERROR("update antiBrute file fail.");
1052         return RESULT_GENERAL_ERROR;
1053     }
1054     Buffer *storeData = CreateBufferBySize(CONST_PIN_DATA_EXPAND_LEN);
1055     if (!IsBufferValid(storeData)) {
1056         LOG_ERROR("generate storeData fail.");
1057         return RESULT_GENERAL_ERROR;
1058     }
1059     ret = ReadPinFile(storeData->buf, storeData->maxSize, templateId, CRYPTO_SUFFIX);
1060     if (ret != RESULT_SUCCESS) {
1061         LOG_ERROR("read pin store file fail.");
1062         DestroyBuffer(storeData);
1063         return RESULT_BAD_READ;
1064     }
1065     storeData->contentSize = storeData->maxSize;
1066     *compareRet = ProcessAuthPin(storeData, inputPinData, templateId, outRootSecret);
1067     if ((*compareRet) == RESULT_SUCCESS) {
1068         ret = UpdateAntiBruteFile(templateId, true);
1069         if (ret != RESULT_SUCCESS) {
1070             LOG_ERROR("UpdateAntiBruteFile fail.");
1071             goto EXIT;
1072         }
1073         ret = UpdatePinLength(templateId, pinLength);
1074         if (ret != RESULT_SUCCESS) {
1075             LOG_ERROR("UpdatePinLength fail.");
1076             goto EXIT;
1077         }
1078     }
1079     LOG_INFO("AuthPinById end.");
1080 
1081 EXIT:
1082     DestroyBuffer(storeData);
1083     return ret;
1084 }
1085 
FindTemplateIdFromList(uint64_t storeTemplateId,const uint64_t * templateIdList,uint32_t templateIdListLen)1086 static bool FindTemplateIdFromList(uint64_t storeTemplateId, const uint64_t *templateIdList, uint32_t templateIdListLen)
1087 {
1088     for (uint32_t i = 0; i < templateIdListLen; ++i) {
1089         if (templateIdList[i] == storeTemplateId) {
1090             return true;
1091         }
1092     }
1093 
1094     return false;
1095 }
1096 
VerifyTemplateDataPin(const uint64_t * templateIdList,uint32_t templateIdListLen)1097 ResultCode VerifyTemplateDataPin(const uint64_t *templateIdList, uint32_t templateIdListLen)
1098 {
1099     if (templateIdListLen != 0 && templateIdList == NULL) {
1100         LOG_ERROR("templateIdList should be not null, when templateIdListLen is not zero");
1101         return RESULT_BAD_PARAM;
1102     }
1103     if (!LoadPinDb()) {
1104         LOG_ERROR("LoadPinDb fail.");
1105         return RESULT_NEED_INIT;
1106     }
1107     uint32_t i = 0;
1108     for (; i < g_pinDbOp->pinIndexLen; i++) {
1109         if (FindTemplateIdFromList(g_pinDbOp->pinIndex[i].pinInfo.templateId, templateIdList, templateIdListLen)) {
1110             continue;
1111         }
1112         ResultCode ret = DelPinById(g_pinDbOp->pinIndex[i].pinInfo.templateId);
1113         if (ret != RESULT_SUCCESS) {
1114             LOG_ERROR("delete pin file fail.");
1115             return RESULT_BAD_DEL;
1116         }
1117     }
1118     LOG_INFO("VerifyTemplateDataPin succ.");
1119     return RESULT_SUCCESS;
1120 }
1121 
GenerateSalt(uint8_t * algoParameter,uint32_t * algoParameterLength,uint8_t * localDeviceId,uint32_t deviceUuidLength)1122 static ResultCode GenerateSalt(uint8_t *algoParameter, uint32_t *algoParameterLength,
1123     uint8_t *localDeviceId, uint32_t deviceUuidLength)
1124 {
1125     uint8_t sourceDataTemp[SOURCE_DATA_LENGTH] = { 0 };
1126     if (memcpy_s(sourceDataTemp, SOURCE_DATA_LENGTH, localDeviceId, deviceUuidLength) != EOK) {
1127         LOG_ERROR("memcpy_s localDeviceId to sourceDataTemp failed");
1128         return RESULT_GENERAL_ERROR;
1129     }
1130     if (SecureRandom(&(sourceDataTemp[deviceUuidLength]), SALT_RANDOM_LENGTH) != RESULT_SUCCESS) {
1131         LOG_ERROR("Generate random number failed");
1132         return RESULT_GENERAL_ERROR;
1133     }
1134     Buffer sourceData = GetTmpBuffer(sourceDataTemp, SOURCE_DATA_LENGTH, SOURCE_DATA_LENGTH);
1135     if (!IsBufferValid(&sourceData)) {
1136         LOG_ERROR("sourceData is invalid");
1137         return RESULT_GENERAL_ERROR;
1138     }
1139     Buffer *resultSha256 = Sha256Adaptor(&sourceData);
1140     if (!IsBufferValid(resultSha256)) {
1141         LOG_ERROR("result is invalid");
1142         return RESULT_GENERAL_ERROR;
1143     }
1144     if (memcpy_s(algoParameter, *algoParameterLength, resultSha256->buf, resultSha256->contentSize) != EOK) {
1145         LOG_ERROR("memcpy_s result to algoParameter failed");
1146         DestroyBuffer(resultSha256);
1147         return RESULT_GENERAL_ERROR;
1148     }
1149     *algoParameterLength = resultSha256->contentSize;
1150 
1151     DestroyBuffer(resultSha256);
1152     LOG_INFO("GenerateAlgoParameterInner succ");
1153     return RESULT_SUCCESS;
1154 }
1155 
DoGenerateAlgoParameter(uint8_t * algoParameter,uint32_t * algoParameterLength,uint32_t * algoVersion,uint8_t * localDeviceId,uint32_t deviceUuidLength)1156 ResultCode DoGenerateAlgoParameter(uint8_t *algoParameter, uint32_t *algoParameterLength, uint32_t *algoVersion,
1157     uint8_t *localDeviceId, uint32_t deviceUuidLength)
1158 {
1159     LOG_INFO("start");
1160     if (algoParameter == NULL || algoParameterLength == NULL || localDeviceId == NULL || algoVersion == NULL ||
1161         deviceUuidLength != DEVICE_UUID_LENGTH) {
1162         LOG_ERROR("bad parameter");
1163         return RESULT_BAD_PARAM;
1164     }
1165     if (!LoadPinDb()) {
1166         LOG_ERROR("LoadPinDb fail.");
1167         return RESULT_NEED_INIT;
1168     }
1169 
1170     if (GenerateSalt(algoParameter, algoParameterLength, localDeviceId, deviceUuidLength) != RESULT_SUCCESS) {
1171         LOG_ERROR("Generate salt failed");
1172         return RESULT_GENERAL_ERROR;
1173     }
1174     *algoVersion = ALGORITHM_VERSION_0;
1175 
1176     LOG_INFO("gen algo succ size is [%{public}u] and version is [%{public}u]", *algoParameterLength, *algoVersion);
1177     return RESULT_SUCCESS;
1178 }
1179 
DestroyAbandonParam(void)1180 void DestroyAbandonParam(void)
1181 {
1182     LOG_INFO("start");
1183     if (g_abandonCacheParam == NULL) {
1184         return;
1185     }
1186     DestroyBuffer(g_abandonCacheParam->newRootSecret);
1187     Free(g_abandonCacheParam);
1188     g_abandonCacheParam = NULL;
1189     return;
1190 }
1191 
CacheAbandonParam(uint64_t oldTemplateId,uint64_t curTemplateId,uint64_t newTemplateId,Buffer * ciperInfo)1192 static ResultCode CacheAbandonParam(uint64_t oldTemplateId, uint64_t curTemplateId, uint64_t newTemplateId,
1193     Buffer *ciperInfo)
1194 {
1195     LOG_INFO("oldTemplateId:0x%{public}x, curTemplateId:0x%{public}x, newTemplateId:0x%{public}x",
1196         (uint16_t)oldTemplateId, (uint16_t)curTemplateId, (uint16_t)newTemplateId);
1197     DestroyAbandonParam();
1198     AbandonCacheParam *cacheParam = (AbandonCacheParam *)Malloc(sizeof(AbandonCacheParam));
1199     if (cacheParam == NULL) {
1200         LOG_ERROR("no memory");
1201         return RESULT_NO_MEMORY;
1202     }
1203     (void)memset_s(cacheParam, sizeof(AbandonCacheParam), 0, sizeof(AbandonCacheParam));
1204     cacheParam->oldTemplateId = oldTemplateId;
1205     cacheParam->curTemplateId = curTemplateId;
1206     cacheParam->newTemplateId = newTemplateId;
1207     cacheParam->newRootSecret = CreateBufferByData(ciperInfo->buf, ciperInfo->contentSize);
1208     if (cacheParam->newRootSecret == NULL) {
1209         LOG_ERROR("no memory");
1210         Free(cacheParam);
1211         return RESULT_NO_MEMORY;
1212     }
1213     g_abandonCacheParam = cacheParam;
1214     return RESULT_SUCCESS;
1215 }
1216 
WriteRootSecretFile(uint64_t templateId,uint64_t newTemplateId,Buffer * ciperInfo)1217 ResultCode WriteRootSecretFile(uint64_t templateId, uint64_t newTemplateId, Buffer *ciperInfo)
1218 {
1219     LOG_INFO("templateId:0x%{public}x, newTemplateId:0x%{public}x", (uint16_t)templateId, (uint16_t)newTemplateId);
1220     if (!IsBufferValid(ciperInfo)) {
1221         LOG_ERROR("bad param");
1222         return RESULT_BAD_PARAM;
1223     }
1224     Buffer *buffer = CreateBufferBySize(sizeof(uint64_t) + ciperInfo->contentSize);
1225     if (buffer == NULL) {
1226         LOG_ERROR("no memory");
1227         return RESULT_NO_MEMORY;
1228     }
1229     if (memcpy_s(buffer->buf, sizeof(uint64_t), &newTemplateId, sizeof(uint64_t)) != EOK) {
1230         LOG_ERROR("copy templateId fialed");
1231         DestroyBuffer(buffer);
1232         return RESULT_BAD_COPY;
1233     }
1234     buffer->contentSize += sizeof(uint64_t);
1235     if (memcpy_s(buffer->buf + sizeof(uint64_t), ciperInfo->contentSize, ciperInfo->buf,
1236         ciperInfo->contentSize) != EOK) {
1237         LOG_ERROR("copy rootSecret fialed");
1238         DestroyBuffer(buffer);
1239         return RESULT_BAD_COPY;
1240     }
1241     buffer->contentSize += ciperInfo->contentSize;
1242     ResultCode ret = WritePinFile(buffer->buf, buffer->contentSize, templateId, ROOTSECRET_CRYPTO_SUFFIX);
1243     if (ret != RESULT_SUCCESS) {
1244         LOG_ERROR("WritePinFile fail.");
1245         DestroyBuffer(buffer);
1246         return ret;
1247     }
1248     DestroyBuffer(buffer);
1249     return RESULT_SUCCESS;
1250 }
1251 
ReadRootSecretFile(uint64_t templateId,uint64_t * newTemplateId,Buffer ** ciperInfo)1252 ResultCode ReadRootSecretFile(uint64_t templateId, uint64_t *newTemplateId, Buffer **ciperInfo)
1253 {
1254     LOG_INFO("templateId:0x%{public}x", (uint16_t)templateId);
1255     uint32_t ciperInfoLen = AES_GCM_256_IV_SIZE + AES_GCM_256_TAG_SIZE + ROOT_SECRET_LEN;
1256     Buffer *buffer = CreateBufferBySize(sizeof(uint64_t) + ciperInfoLen);
1257     if (buffer == NULL) {
1258         LOG_ERROR("no memory");
1259         return RESULT_NO_MEMORY;
1260     }
1261 
1262     ResultCode ret = ReadPinFile(buffer->buf, buffer->maxSize, templateId, ROOTSECRET_CRYPTO_SUFFIX);
1263     if (ret != RESULT_SUCCESS) {
1264         LOG_ERROR("ReadPinFile fail");
1265         DestroyBuffer(buffer);
1266         return ret;
1267     }
1268     buffer->contentSize = sizeof(uint64_t) + ciperInfoLen;
1269     if (memcpy_s(newTemplateId, sizeof(uint64_t), buffer->buf, sizeof(uint64_t)) != EOK) {
1270         LOG_ERROR("copy templateId fialed");
1271         DestroyBuffer(buffer);
1272         return RESULT_BAD_COPY;
1273     }
1274 
1275     *ciperInfo = CreateBufferBySize(ciperInfoLen);
1276     if (*ciperInfo == NULL) {
1277         LOG_ERROR("no memory");
1278         DestroyBuffer(buffer);
1279         return RESULT_NO_MEMORY;
1280     }
1281     if (memcpy_s((*ciperInfo)->buf, ciperInfoLen, buffer->buf + sizeof(uint64_t), ciperInfoLen) != EOK) {
1282         LOG_ERROR("copy rootSecret fialed");
1283         DestroyBuffer(buffer);
1284         DestroyBuffer(*ciperInfo);
1285         return RESULT_BAD_COPY;
1286     }
1287     (*ciperInfo)->contentSize = ciperInfoLen;
1288     DestroyBuffer(buffer);
1289     return RESULT_SUCCESS;
1290 }
1291 
ReWriteRootSecretFile(uint64_t templateId)1292 ResultCode ReWriteRootSecretFile(uint64_t templateId)
1293 {
1294     LOG_INFO("templateId:0x%{public}x", (uint16_t)templateId);
1295     if (g_abandonCacheParam == NULL || templateId != g_abandonCacheParam->curTemplateId) {
1296         LOG_INFO("g_abandonCacheParam is null or templateId is not same");
1297         return RESULT_SUCCESS;
1298     }
1299 
1300     ResultCode ret = WriteRootSecretFile(g_abandonCacheParam->oldTemplateId, g_abandonCacheParam->newTemplateId,
1301         g_abandonCacheParam->newRootSecret);
1302     if (ret != RESULT_SUCCESS) {
1303         LOG_ERROR("WriteRootSecretFile fail, ret:%{public}u", ret);
1304         return ret;
1305     }
1306     DestroyAbandonParam();
1307     return RESULT_SUCCESS;
1308 }
1309 
GetRootSecretCipherInfo(Buffer * oldRootSecret,Buffer * newRootSecret)1310 Buffer *GetRootSecretCipherInfo(Buffer *oldRootSecret, Buffer *newRootSecret)
1311 {
1312     if (!IsBufferValid(oldRootSecret) || !IsBufferValid(newRootSecret)) {
1313         LOG_ERROR("invalid param.");
1314         return NULL;
1315     }
1316 
1317     Buffer *cipherText = NULL;
1318     Buffer *tag = NULL;
1319     Buffer *cipherInfo = NULL;
1320     AesGcmParam param = {};
1321     param.key = oldRootSecret;
1322     param.iv = CreateBufferBySize(AES_GCM_256_IV_SIZE);
1323     if (!IsBufferValid(param.iv)) {
1324         LOG_ERROR("create iv fail.");
1325         goto EXIT;
1326     }
1327     if (SecureRandom(param.iv->buf, param.iv->maxSize) != RESULT_SUCCESS) {
1328         LOG_ERROR("random iv fail.");
1329         goto EXIT;
1330     }
1331     param.iv->contentSize = param.iv->maxSize;
1332     if (AesGcm256Encrypt(newRootSecret, &param, &cipherText, &tag) != RESULT_SUCCESS) {
1333         LOG_ERROR("AesGcmEncrypt fail.");
1334         goto EXIT;
1335     }
1336     cipherInfo = SplicePinCiperInfo(param.iv, tag, cipherText);
1337     if (cipherInfo == NULL) {
1338         LOG_ERROR("SplicePinCiperInfo fail.");
1339         goto EXIT;
1340     }
1341 
1342 EXIT:
1343     DestroyBuffer(param.iv);
1344     DestroyBuffer(cipherText);
1345     DestroyBuffer(tag);
1346     return cipherInfo;
1347 }
1348 
GetRootSecretPlainInfo(Buffer * oldRootSecret,const Buffer * cipherInfo)1349 Buffer *GetRootSecretPlainInfo(Buffer *oldRootSecret, const Buffer *cipherInfo)
1350 {
1351     if (!IsBufferValid(oldRootSecret) || !IsBufferValid(cipherInfo)) {
1352         LOG_ERROR("invalid param.");
1353         return NULL;
1354     }
1355 
1356     if (cipherInfo->contentSize < AES_GCM_256_IV_SIZE + AES_GCM_256_TAG_SIZE + ROOT_SECRET_LEN) {
1357         LOG_ERROR("check cipher info fail.");
1358         return NULL;
1359     }
1360 
1361     AesGcmParam param = {};
1362     Buffer iv = GetTmpBuffer(cipherInfo->buf, AES_GCM_256_IV_SIZE, AES_GCM_256_IV_SIZE);
1363     param.iv = &iv;
1364     param.key = oldRootSecret;
1365     Buffer tag = GetTmpBuffer(cipherInfo->buf + AES_GCM_256_IV_SIZE, AES_GCM_256_TAG_SIZE, AES_GCM_256_TAG_SIZE);
1366     uint32_t cipherTextSize = cipherInfo->contentSize - AES_GCM_256_IV_SIZE - AES_GCM_256_TAG_SIZE;
1367     Buffer cipherText = GetTmpBuffer(
1368         cipherInfo->buf + AES_GCM_256_IV_SIZE + AES_GCM_256_TAG_SIZE, cipherTextSize, cipherTextSize);
1369     Buffer *plainText = NULL;
1370     int32_t result = AesGcm256Decrypt(&cipherText, &param, &tag, &plainText);
1371     if (result != RESULT_SUCCESS) {
1372         LOG_ERROR("Aes256GcmDecrypt fail");
1373         return NULL;
1374     }
1375 
1376     return plainText;
1377 }
1378 
1379 /* This is for example only, Should be implemented in trusted environment. */
Abandon(uint64_t oldTemplateId,uint64_t newTemplateId,Buffer * oldRootSecret,Buffer * newRootSecret)1380 ResultCode Abandon(uint64_t oldTemplateId, uint64_t newTemplateId, Buffer *oldRootSecret, Buffer *newRootSecret)
1381 {
1382     LOG_INFO("oldTemplateId:0x%{public}x, newTemplateId:0x%{public}x",
1383         (uint16_t)oldTemplateId, (uint16_t)newTemplateId);
1384     if (!IsBufferValid(oldRootSecret) || !IsBufferValid(newRootSecret)) {
1385         LOG_ERROR("get invalid params.");
1386         return RESULT_BAD_PARAM;
1387     }
1388 
1389     uint32_t index = MAX_CRYPTO_INFO_SIZE;
1390     ResultCode ret = SearchPinIndex(oldTemplateId, &index);
1391     if (ret != RESULT_SUCCESS) {
1392         LOG_ERROR("get invalid params.");
1393         return ret;
1394     }
1395 
1396     Buffer *cipherInfo = GetRootSecretCipherInfo(oldRootSecret, newRootSecret);
1397     if (cipherInfo == NULL) {
1398         LOG_ERROR("GetRootSecretCipherInfo fail.");
1399         return RESULT_GENERAL_ERROR;
1400     }
1401 
1402     Buffer *oldCipherInfo = NULL;
1403     uint64_t curTemplateId = 0;
1404     ret = ReadRootSecretFile(oldTemplateId, &curTemplateId, &oldCipherInfo);
1405     if (ret == RESULT_SUCCESS) {
1406         ret = CacheAbandonParam(oldTemplateId, curTemplateId, newTemplateId, cipherInfo);
1407         if (ret != RESULT_SUCCESS) {
1408             LOG_ERROR("CacheAbandonParam fail, ret:%{public}u", ret);
1409             goto EXIT;
1410         }
1411     } else {
1412         ret = WriteRootSecretFile(oldTemplateId, newTemplateId, cipherInfo);
1413         if (ret != RESULT_SUCCESS) {
1414             LOG_ERROR("WriteRootSecretFile fail.");
1415             goto EXIT;
1416         }
1417     }
1418 
1419     LOG_INFO("Abandon success");
1420 EXIT:
1421     DestroyBuffer(oldCipherInfo);
1422     DestroyBuffer(cipherInfo);
1423     return ret;
1424 }
1425 
GenerateDecodeRootSecret(uint64_t templateId,Buffer * oldRootSecret)1426 Buffer *GenerateDecodeRootSecret(uint64_t templateId, Buffer *oldRootSecret)
1427 {
1428     LOG_INFO("templateId:0x%{public}x", (uint16_t)templateId);
1429     if (!IsBufferValid(oldRootSecret)) {
1430         LOG_ERROR("bad param.");
1431         return NULL;
1432     }
1433 
1434     Buffer *rootSecretPlain = NULL;
1435     Buffer *cipherInfo = NULL;
1436     uint64_t newTemplateId = 0;
1437     ResultCode ret = ReadRootSecretFile(templateId, &newTemplateId, &cipherInfo);
1438     if (ret != RESULT_SUCCESS) {
1439         LOG_ERROR("ReadRootSecretFile fail");
1440         goto EXIT;
1441     }
1442 
1443     rootSecretPlain = GetRootSecretPlainInfo(oldRootSecret, cipherInfo);
1444     if (!IsBufferValid(rootSecretPlain)) {
1445         LOG_ERROR("rootSecretPlain is invalid.");
1446         goto EXIT;
1447     }
1448     LOG_INFO("GenerateDecodeRootSecret success");
1449 EXIT:
1450     DestroyBuffer(cipherInfo);
1451     return rootSecretPlain;
1452 }
1453 
GetCredentialLength(uint64_t templateId,uint32_t * credentialLength)1454 ResultCode GetCredentialLength(uint64_t templateId, uint32_t *credentialLength)
1455 {
1456     if (templateId == INVALID_TEMPLATE_ID || credentialLength == NULL) {
1457         LOG_ERROR("check param fail!");
1458         return RESULT_BAD_PARAM;
1459     }
1460     if (!LoadPinDb()) {
1461         LOG_ERROR("LoadPinDb fail.");
1462         return RESULT_NEED_INIT;
1463     }
1464 
1465     uint32_t index = MAX_CRYPTO_INFO_SIZE;
1466     ResultCode ret = SearchPinIndex(templateId, &index);
1467     if (ret != RESULT_SUCCESS) {
1468         LOG_ERROR("SearchPinIndex no pin exist.");
1469         return ret;
1470     }
1471     *credentialLength = g_pinDbOp->pinIndex[index].pinInfo.pinLength;
1472 
1473     LOG_INFO("GetCredentialLength succ.");
1474     return RESULT_SUCCESS;
1475 }
1476 
1477 /* This is for example only, Should be implemented in trusted environment. */
RestartLockoutDurationByUserId(int32_t userId)1478 ResultCode RestartLockoutDurationByUserId(int32_t userId)
1479 {
1480     // Example implementation, This will restart lockout duration for all users.
1481     LOG_INFO("start");
1482     (void)userId;
1483     if (!LoadPinDb()) {
1484         LOG_ERROR("load pinDb fail.");
1485         return RESULT_NEED_INIT;
1486     }
1487     if (g_pinDbOp->pinIndexLen == 0) {
1488         LOG_ERROR("SearchPinIndex no pin exist.");
1489         return RESULT_BAD_MATCH;
1490     }
1491 
1492     uint32_t errorCount = 0;
1493     uint64_t templateId = 0;
1494     uint64_t startFreezeTime = 0;
1495     uint32_t freezeTime = 0;
1496     ResultCode ret = RESULT_GENERAL_ERROR;
1497     bool anyLockoutRestart = false;
1498     for (uint32_t index = 0; index < g_pinDbOp->pinIndexLen; index++) {
1499         errorCount = g_pinDbOp->pinIndex[index].antiBruteInfo.authErrorCount;
1500         templateId = g_pinDbOp->pinIndex[index].pinInfo.templateId;
1501         startFreezeTime = g_pinDbOp->pinIndex[index].antiBruteInfo.startFreezeTime;
1502         freezeTime = 0;
1503         ret = ComputeFreezeTime(templateId, &freezeTime, errorCount, startFreezeTime);
1504         if (ret != RESULT_SUCCESS) {
1505             LOG_ERROR("ComputeFreezeTime fail.");
1506             return ret;
1507         }
1508         if (freezeTime != 0) {
1509             uint64_t nowTime = GetRtcTime();
1510             ret = SetAntiBruteInfoById(templateId, errorCount, nowTime);
1511             if (ret != RESULT_SUCCESS) {
1512                 LOG_ERROR("SetAntiBruteInfoById fail.");
1513                 return ret;
1514             }
1515             anyLockoutRestart = true;
1516             LOG_INFO("restart lockout duration success.");
1517         }
1518     }
1519     if (anyLockoutRestart) {
1520         return RESULT_SUCCESS;
1521     }
1522     return RESULT_GENERAL_ERROR;
1523 }