1094332d3Sopenharmony_ci/*
2094332d3Sopenharmony_ci * Copyright (c) 2022-2024 Huawei Device Co., Ltd.
3094332d3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4094332d3Sopenharmony_ci * you may not use this file except in compliance with the License.
5094332d3Sopenharmony_ci * You may obtain a copy of the License at
6094332d3Sopenharmony_ci *
7094332d3Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8094332d3Sopenharmony_ci *
9094332d3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10094332d3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11094332d3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12094332d3Sopenharmony_ci * See the License for the specific language governing permissions and
13094332d3Sopenharmony_ci * limitations under the License.
14094332d3Sopenharmony_ci */
15094332d3Sopenharmony_ci
16094332d3Sopenharmony_ci#include "pin_db.h"
17094332d3Sopenharmony_ci
18094332d3Sopenharmony_ci#include "securec.h"
19094332d3Sopenharmony_ci
20094332d3Sopenharmony_ci#include "adaptor_algorithm.h"
21094332d3Sopenharmony_ci#include "adaptor_memory.h"
22094332d3Sopenharmony_ci#include "adaptor_time.h"
23094332d3Sopenharmony_ci#include "defines.h"
24094332d3Sopenharmony_ci#include "file_operator.h"
25094332d3Sopenharmony_ci#include "pin_db_ops.h"
26094332d3Sopenharmony_ci
27094332d3Sopenharmony_ci#define MAX_RANDOM_TIME 10
28094332d3Sopenharmony_ci#define CRYPTO_SUFFIX "_CryptoInfo"
29094332d3Sopenharmony_ci#define SALT_SUFFIX "_salt"
30094332d3Sopenharmony_ci#define SECRET_SUFFIX "_secret"
31094332d3Sopenharmony_ci#define SALT_PREFIX "hkdf_salt"
32094332d3Sopenharmony_ci#define CREDENTIAL_PREFIX "template_encryption_key"
33094332d3Sopenharmony_ci#define DEFAULT_VALUE 1
34094332d3Sopenharmony_ci#define REMAINING_TIMES_FREEZE 1
35094332d3Sopenharmony_ci#define FIRST_ANTI_BRUTE_COUNT 5
36094332d3Sopenharmony_ci#define SECOND_ANTI_BRUTE_COUNT 8
37094332d3Sopenharmony_ci#define THIRD_ANTI_BRUTE_COUNT 11
38094332d3Sopenharmony_ci#define ANTI_BRUTE_COUNT_FREQUENCY 3
39094332d3Sopenharmony_ci#define ONE_MIN_TIME 60
40094332d3Sopenharmony_ci#define TEN_MIN_TIME 600
41094332d3Sopenharmony_ci#define THIRTY_MIN_TIME 1800
42094332d3Sopenharmony_ci#define ONE_HOUR_TIME 3600
43094332d3Sopenharmony_ci#define ONE_DAY_TIME 86400
44094332d3Sopenharmony_ci#define FIRST_EXPONENTIAL_PARA 30
45094332d3Sopenharmony_ci#define SECOND_EXPONENTIAL_PARA 2
46094332d3Sopenharmony_ci#define THIRD_EXPONENTIAL_PARA 10
47094332d3Sopenharmony_ci#define MS_OF_S 1000uLL
48094332d3Sopenharmony_ci#define CONST_PIN_DATA_EXPAND_LEN 92U
49094332d3Sopenharmony_ci#define CONST_CREDENTIAL_PREFIX_LEN 32U
50094332d3Sopenharmony_ci#define CONST_EXPAND_DATA_LEN 128U
51094332d3Sopenharmony_ci#define SOURCE_DATA_LENGTH 97
52094332d3Sopenharmony_ci#define DEVICE_UUID_LENGTH 65
53094332d3Sopenharmony_ci#define SALT_RANDOM_LENGTH 32
54094332d3Sopenharmony_ci
55094332d3Sopenharmony_cistatic PinDbV1 *g_pinDbOp = NULL;
56094332d3Sopenharmony_ci
57094332d3Sopenharmony_cibool LoadPinDb(void)
58094332d3Sopenharmony_ci{
59094332d3Sopenharmony_ci    if (g_pinDbOp != NULL) {
60094332d3Sopenharmony_ci        return true;
61094332d3Sopenharmony_ci    }
62094332d3Sopenharmony_ci    g_pinDbOp = ReadPinDb();
63094332d3Sopenharmony_ci    if (g_pinDbOp == NULL) {
64094332d3Sopenharmony_ci        LOG_ERROR("ReadPinDb fail.");
65094332d3Sopenharmony_ci        return false;
66094332d3Sopenharmony_ci    }
67094332d3Sopenharmony_ci
68094332d3Sopenharmony_ci    LOG_INFO("LoadPinDb succ.");
69094332d3Sopenharmony_ci    return true;
70094332d3Sopenharmony_ci}
71094332d3Sopenharmony_ci
72094332d3Sopenharmony_civoid DestroyPinDb(void)
73094332d3Sopenharmony_ci{
74094332d3Sopenharmony_ci    if (g_pinDbOp == NULL) {
75094332d3Sopenharmony_ci        LOG_INFO("g_pinDbOp is null.");
76094332d3Sopenharmony_ci        return;
77094332d3Sopenharmony_ci    }
78094332d3Sopenharmony_ci
79094332d3Sopenharmony_ci    FreePinDb(&g_pinDbOp);
80094332d3Sopenharmony_ci    LOG_INFO("DestroyPinDb succ.");
81094332d3Sopenharmony_ci}
82094332d3Sopenharmony_ci
83094332d3Sopenharmony_cistatic ResultCode CoverData(const char *fileName, const FileOperator *fileOp)
84094332d3Sopenharmony_ci{
85094332d3Sopenharmony_ci    uint32_t fileLen = 0;
86094332d3Sopenharmony_ci    ResultCode ret = (ResultCode)fileOp->getFileLen(fileName, &fileLen);
87094332d3Sopenharmony_ci    /* The maximum length of the fileName is CONST_PIN_DATA_EXPAND_LEN */
88094332d3Sopenharmony_ci    if (ret != RESULT_SUCCESS) {
89094332d3Sopenharmony_ci        LOG_ERROR("getFileLen fail.");
90094332d3Sopenharmony_ci        return ret;
91094332d3Sopenharmony_ci    }
92094332d3Sopenharmony_ci    if (fileLen > CONST_PIN_DATA_EXPAND_LEN) {
93094332d3Sopenharmony_ci        LOG_ERROR("Filelen is larger than pin data expand len");
94094332d3Sopenharmony_ci        return RESULT_GENERAL_ERROR;
95094332d3Sopenharmony_ci    }
96094332d3Sopenharmony_ci    uint8_t *data = Malloc(fileLen);
97094332d3Sopenharmony_ci    if (data == NULL) {
98094332d3Sopenharmony_ci        LOG_ERROR("no memory.");
99094332d3Sopenharmony_ci        return RESULT_NO_MEMORY;
100094332d3Sopenharmony_ci    }
101094332d3Sopenharmony_ci    (void)memset_s(data, fileLen, 0, fileLen);
102094332d3Sopenharmony_ci    ret = (ResultCode)fileOp->writeFile(fileName, data, fileLen);
103094332d3Sopenharmony_ci    Free(data);
104094332d3Sopenharmony_ci    if (ret != RESULT_SUCCESS) {
105094332d3Sopenharmony_ci        LOG_ERROR("WritePinFile fail.");
106094332d3Sopenharmony_ci        return ret;
107094332d3Sopenharmony_ci    }
108094332d3Sopenharmony_ci
109094332d3Sopenharmony_ci    return RESULT_SUCCESS;
110094332d3Sopenharmony_ci}
111094332d3Sopenharmony_ci
112094332d3Sopenharmony_ci/* This is for example only, Should be implemented in trusted environment. */
113094332d3Sopenharmony_cistatic ResultCode RemovePinFile(const uint64_t templateId, const char *suffix, bool needCover)
114094332d3Sopenharmony_ci{
115094332d3Sopenharmony_ci    FileOperator *fileOp = GetFileOperator(DEFAULT_FILE_OPERATOR);
116094332d3Sopenharmony_ci    if (!IsFileOperatorValid(fileOp)) {
117094332d3Sopenharmony_ci        LOG_ERROR("fileOp invalid.");
118094332d3Sopenharmony_ci        return RESULT_GENERAL_ERROR;
119094332d3Sopenharmony_ci    }
120094332d3Sopenharmony_ci    char fileName[MAX_FILE_NAME_LEN] = {'\0'};
121094332d3Sopenharmony_ci    ResultCode ret = GenerateFileName(templateId, DEFAULT_FILE_HEAD, suffix, fileName, MAX_FILE_NAME_LEN);
122094332d3Sopenharmony_ci    if (ret != RESULT_SUCCESS) {
123094332d3Sopenharmony_ci        LOG_ERROR("GenerateCryptoFileName fail.");
124094332d3Sopenharmony_ci        return RESULT_UNKNOWN;
125094332d3Sopenharmony_ci    }
126094332d3Sopenharmony_ci
127094332d3Sopenharmony_ci    /* Write data zeros before deleting data, In addition to anti-brute-force cracking */
128094332d3Sopenharmony_ci    if (needCover) {
129094332d3Sopenharmony_ci        ret = CoverData(fileName, fileOp);
130094332d3Sopenharmony_ci        if (ret != RESULT_SUCCESS) {
131094332d3Sopenharmony_ci            LOG_ERROR("cover data fail.");
132094332d3Sopenharmony_ci            return RESULT_GENERAL_ERROR;
133094332d3Sopenharmony_ci        }
134094332d3Sopenharmony_ci    }
135094332d3Sopenharmony_ci    if ((ResultCode)fileOp->deleteFile(fileName) != RESULT_SUCCESS) {
136094332d3Sopenharmony_ci        LOG_ERROR("file remove fail.");
137094332d3Sopenharmony_ci        return RESULT_BAD_DEL;
138094332d3Sopenharmony_ci    }
139094332d3Sopenharmony_ci
140094332d3Sopenharmony_ci    LOG_INFO("RemovePinFile succ.");
141094332d3Sopenharmony_ci    return ret;
142094332d3Sopenharmony_ci}
143094332d3Sopenharmony_ci
144094332d3Sopenharmony_cistatic ResultCode RemoveAllFile(uint64_t templateId)
145094332d3Sopenharmony_ci{
146094332d3Sopenharmony_ci    /* This is for example only, Anti-brute-force cracking files must have an anti-rollback zone */
147094332d3Sopenharmony_ci    ResultCode ret = RemovePinFile(templateId, ANTI_BRUTE_SUFFIX, false);
148094332d3Sopenharmony_ci    if (ret != RESULT_SUCCESS) {
149094332d3Sopenharmony_ci        LOG_ERROR("RemovePinAntiBrute fail.");
150094332d3Sopenharmony_ci    }
151094332d3Sopenharmony_ci    ret = RemovePinFile(templateId, CRYPTO_SUFFIX, true);
152094332d3Sopenharmony_ci    if (ret != RESULT_SUCCESS) {
153094332d3Sopenharmony_ci        LOG_ERROR("RemovePinCrypto fail.");
154094332d3Sopenharmony_ci    }
155094332d3Sopenharmony_ci    ret = RemovePinFile(templateId, SALT_SUFFIX, true);
156094332d3Sopenharmony_ci    if (ret != RESULT_SUCCESS) {
157094332d3Sopenharmony_ci        LOG_ERROR("RemovePinSalt fail.");
158094332d3Sopenharmony_ci    }
159094332d3Sopenharmony_ci    ret = RemovePinFile(templateId, SECRET_SUFFIX, true);
160094332d3Sopenharmony_ci    if (ret != RESULT_SUCCESS) {
161094332d3Sopenharmony_ci        LOG_ERROR("RemovePinSecret fail.");
162094332d3Sopenharmony_ci    }
163094332d3Sopenharmony_ci
164094332d3Sopenharmony_ci    LOG_INFO("RemoveAllFile end.");
165094332d3Sopenharmony_ci    return RESULT_SUCCESS;
166094332d3Sopenharmony_ci}
167094332d3Sopenharmony_ci
168094332d3Sopenharmony_cistatic uint64_t GeneratePinTemplateId(void)
169094332d3Sopenharmony_ci{
170094332d3Sopenharmony_ci    for (uint32_t i = 0; i < MAX_RANDOM_TIME; i++) {
171094332d3Sopenharmony_ci        uint64_t templateId = INVALID_TEMPLATE_ID;
172094332d3Sopenharmony_ci        SecureRandom((uint8_t *)&templateId, sizeof(templateId));
173094332d3Sopenharmony_ci        if (templateId == INVALID_TEMPLATE_ID) {
174094332d3Sopenharmony_ci            continue;
175094332d3Sopenharmony_ci        }
176094332d3Sopenharmony_ci        uint32_t j = 0;
177094332d3Sopenharmony_ci        for (; j < g_pinDbOp->pinIndexLen; j++) {
178094332d3Sopenharmony_ci            if (templateId == g_pinDbOp->pinIndex[i].pinInfo.templateId) {
179094332d3Sopenharmony_ci                break;
180094332d3Sopenharmony_ci            }
181094332d3Sopenharmony_ci        }
182094332d3Sopenharmony_ci        if (j == g_pinDbOp->pinIndexLen) {
183094332d3Sopenharmony_ci            return templateId;
184094332d3Sopenharmony_ci        }
185094332d3Sopenharmony_ci    }
186094332d3Sopenharmony_ci    LOG_ERROR("fail generate pin templateid.");
187094332d3Sopenharmony_ci    return INVALID_TEMPLATE_ID;
188094332d3Sopenharmony_ci}
189094332d3Sopenharmony_ci
190094332d3Sopenharmony_cistatic ResultCode DelPin(uint64_t templateId)
191094332d3Sopenharmony_ci{
192094332d3Sopenharmony_ci    /* This is for example only, Should be implemented in trusted environment. */
193094332d3Sopenharmony_ci    ResultCode ret = RemoveAllFile(templateId);
194094332d3Sopenharmony_ci    if (ret != RESULT_SUCCESS) {
195094332d3Sopenharmony_ci        LOG_ERROR("Remove pin file fail.");
196094332d3Sopenharmony_ci        return ret;
197094332d3Sopenharmony_ci    }
198094332d3Sopenharmony_ci
199094332d3Sopenharmony_ci    LOG_INFO("DelPin succ.");
200094332d3Sopenharmony_ci    return RESULT_SUCCESS;
201094332d3Sopenharmony_ci}
202094332d3Sopenharmony_ci
203094332d3Sopenharmony_cistatic ResultCode DelPinInDb(uint32_t index)
204094332d3Sopenharmony_ci{
205094332d3Sopenharmony_ci    uint32_t pinIndexLen = g_pinDbOp->pinIndexLen - 1;
206094332d3Sopenharmony_ci    if (pinIndexLen == 0) {
207094332d3Sopenharmony_ci        (void)memset_s(g_pinDbOp->pinIndex,
208094332d3Sopenharmony_ci            g_pinDbOp->pinIndexLen * sizeof(PinIndexV1), 0, g_pinDbOp->pinIndexLen * sizeof(PinIndexV1));
209094332d3Sopenharmony_ci        Free(g_pinDbOp->pinIndex);
210094332d3Sopenharmony_ci        g_pinDbOp->pinIndex = NULL;
211094332d3Sopenharmony_ci    } else {
212094332d3Sopenharmony_ci        uint32_t size = pinIndexLen * sizeof(PinIndexV1);
213094332d3Sopenharmony_ci        PinIndexV1 *pinIndex = (PinIndexV1 *)Malloc(size);
214094332d3Sopenharmony_ci        if (pinIndex == NULL) {
215094332d3Sopenharmony_ci            LOG_ERROR("PinIndexV1 malloc fail.");
216094332d3Sopenharmony_ci            return RESULT_NO_MEMORY;
217094332d3Sopenharmony_ci        }
218094332d3Sopenharmony_ci        (void)memset_s(pinIndex, size, 0, size);
219094332d3Sopenharmony_ci        for (uint32_t i = 0, j = 0; i < g_pinDbOp->pinIndexLen; i++) {
220094332d3Sopenharmony_ci            if (i != index) {
221094332d3Sopenharmony_ci                pinIndex[j] = g_pinDbOp->pinIndex[i];
222094332d3Sopenharmony_ci                j++;
223094332d3Sopenharmony_ci            }
224094332d3Sopenharmony_ci        }
225094332d3Sopenharmony_ci        (void)memset_s(g_pinDbOp->pinIndex,
226094332d3Sopenharmony_ci            g_pinDbOp->pinIndexLen * sizeof(PinIndexV1), 0, g_pinDbOp->pinIndexLen * sizeof(PinIndexV1));
227094332d3Sopenharmony_ci        Free(g_pinDbOp->pinIndex);
228094332d3Sopenharmony_ci        g_pinDbOp->pinIndex = pinIndex;
229094332d3Sopenharmony_ci    }
230094332d3Sopenharmony_ci    LOG_INFO("%{public}u left after del.", pinIndexLen);
231094332d3Sopenharmony_ci    g_pinDbOp->pinIndexLen = pinIndexLen;
232094332d3Sopenharmony_ci    ResultCode ret = WritePinDb(g_pinDbOp);
233094332d3Sopenharmony_ci    if (ret != RESULT_SUCCESS) {
234094332d3Sopenharmony_ci        LOG_ERROR("WritePinDb fail.");
235094332d3Sopenharmony_ci        return ret;
236094332d3Sopenharmony_ci    }
237094332d3Sopenharmony_ci
238094332d3Sopenharmony_ci    LOG_INFO("DelPinInDb succ.");
239094332d3Sopenharmony_ci    return ret;
240094332d3Sopenharmony_ci}
241094332d3Sopenharmony_ci
242094332d3Sopenharmony_cistatic ResultCode SearchPinIndex(uint64_t templateId, uint32_t *index)
243094332d3Sopenharmony_ci{
244094332d3Sopenharmony_ci    if (!LoadPinDb()) {
245094332d3Sopenharmony_ci        LOG_ERROR("SearchPinIndex load pinDb fail.");
246094332d3Sopenharmony_ci        return RESULT_NEED_INIT;
247094332d3Sopenharmony_ci    }
248094332d3Sopenharmony_ci
249094332d3Sopenharmony_ci    if (g_pinDbOp->pinIndexLen == 0) {
250094332d3Sopenharmony_ci        LOG_ERROR("SearchPinIndex no pin exist.");
251094332d3Sopenharmony_ci        return RESULT_BAD_MATCH;
252094332d3Sopenharmony_ci    }
253094332d3Sopenharmony_ci    for (uint32_t i = 0; i < g_pinDbOp->pinIndexLen; i++) {
254094332d3Sopenharmony_ci        if (g_pinDbOp->pinIndex[i].pinInfo.templateId == templateId) {
255094332d3Sopenharmony_ci            LOG_INFO("SearchPinIndex succ.");
256094332d3Sopenharmony_ci            (*index) = i;
257094332d3Sopenharmony_ci            return RESULT_SUCCESS;
258094332d3Sopenharmony_ci        }
259094332d3Sopenharmony_ci    }
260094332d3Sopenharmony_ci    LOG_ERROR("SearchPinIndex no pin match.");
261094332d3Sopenharmony_ci    return RESULT_BAD_MATCH;
262094332d3Sopenharmony_ci}
263094332d3Sopenharmony_ci
264094332d3Sopenharmony_ciResultCode DelPinById(uint64_t templateId)
265094332d3Sopenharmony_ci{
266094332d3Sopenharmony_ci    uint32_t index = MAX_CRYPTO_INFO_SIZE;
267094332d3Sopenharmony_ci    ResultCode ret = SearchPinIndex(templateId, &index);
268094332d3Sopenharmony_ci    if (ret != RESULT_SUCCESS) {
269094332d3Sopenharmony_ci        return ret;
270094332d3Sopenharmony_ci    }
271094332d3Sopenharmony_ci
272094332d3Sopenharmony_ci    ret = DelPinInDb(index);
273094332d3Sopenharmony_ci    if (ret != RESULT_SUCCESS) {
274094332d3Sopenharmony_ci        LOG_ERROR("DelPinInDb fail.");
275094332d3Sopenharmony_ci        return ret;
276094332d3Sopenharmony_ci    }
277094332d3Sopenharmony_ci
278094332d3Sopenharmony_ci    ret = DelPin(templateId);
279094332d3Sopenharmony_ci    if (ret != RESULT_SUCCESS) {
280094332d3Sopenharmony_ci        LOG_ERROR(" DelPin fail.");
281094332d3Sopenharmony_ci    }
282094332d3Sopenharmony_ci
283094332d3Sopenharmony_ci    LOG_INFO("DelPinById succ.");
284094332d3Sopenharmony_ci    /* ignore pin file remove result, return success when index file remove success */
285094332d3Sopenharmony_ci    return RESULT_SUCCESS;
286094332d3Sopenharmony_ci}
287094332d3Sopenharmony_ci
288094332d3Sopenharmony_cistatic void InitPinInfo(PinInfoV1 *pinInfo, uint64_t templateId, uint64_t subType)
289094332d3Sopenharmony_ci{
290094332d3Sopenharmony_ci    pinInfo->templateId = templateId;
291094332d3Sopenharmony_ci    pinInfo->subType = subType;
292094332d3Sopenharmony_ci    pinInfo->algoVersion = ALGORITHM_VERSION_0;
293094332d3Sopenharmony_ci}
294094332d3Sopenharmony_ci
295094332d3Sopenharmony_cistatic void InitAntiBruteInfo(AntiBruteInfoV0 *info)
296094332d3Sopenharmony_ci{
297094332d3Sopenharmony_ci    info->authErrorCount = INIT_AUTH_ERROR_COUNT;
298094332d3Sopenharmony_ci    info->startFreezeTime = INIT_START_FREEZE_TIMES;
299094332d3Sopenharmony_ci}
300094332d3Sopenharmony_ci
301094332d3Sopenharmony_cistatic void InitPinIndex(PinIndexV1 *pinIndex, uint64_t templateId, uint64_t subType)
302094332d3Sopenharmony_ci{
303094332d3Sopenharmony_ci    InitPinInfo(&(pinIndex->pinInfo), templateId, subType);
304094332d3Sopenharmony_ci    InitAntiBruteInfo(&(pinIndex->antiBruteInfo));
305094332d3Sopenharmony_ci}
306094332d3Sopenharmony_ci
307094332d3Sopenharmony_cistatic ResultCode AddPinInDb(uint64_t templateId, uint64_t subType)
308094332d3Sopenharmony_ci{
309094332d3Sopenharmony_ci    if (g_pinDbOp->pinIndexLen > MAX_CRYPTO_INFO_SIZE - 1) {
310094332d3Sopenharmony_ci        LOG_ERROR("pinIndexLen too large.");
311094332d3Sopenharmony_ci        return RESULT_BAD_PARAM;
312094332d3Sopenharmony_ci    }
313094332d3Sopenharmony_ci    uint32_t size = (g_pinDbOp->pinIndexLen + 1) * sizeof(PinIndexV1);
314094332d3Sopenharmony_ci    PinIndexV1 *pinIndex = (PinIndexV1 *)Malloc(size);
315094332d3Sopenharmony_ci    if (pinIndex == NULL) {
316094332d3Sopenharmony_ci        LOG_ERROR("PinIndexV1 malloc fail.");
317094332d3Sopenharmony_ci        return RESULT_NO_MEMORY;
318094332d3Sopenharmony_ci    }
319094332d3Sopenharmony_ci    (void)memset_s(pinIndex, size, 0, size);
320094332d3Sopenharmony_ci    if (g_pinDbOp->pinIndexLen != 0) {
321094332d3Sopenharmony_ci        if (memcpy_s(pinIndex, size,
322094332d3Sopenharmony_ci            g_pinDbOp->pinIndex, g_pinDbOp->pinIndexLen * sizeof(PinIndexV1)) != EOK) {
323094332d3Sopenharmony_ci            LOG_ERROR("PinIndexV1 copy fail.");
324094332d3Sopenharmony_ci            (void)memset_s(pinIndex, size, 0, size);
325094332d3Sopenharmony_ci            Free(pinIndex);
326094332d3Sopenharmony_ci            return RESULT_NO_MEMORY;
327094332d3Sopenharmony_ci        }
328094332d3Sopenharmony_ci    }
329094332d3Sopenharmony_ci    InitPinIndex(&pinIndex[g_pinDbOp->pinIndexLen], templateId, subType);
330094332d3Sopenharmony_ci    if (g_pinDbOp->pinIndex != NULL) {
331094332d3Sopenharmony_ci        Free(g_pinDbOp->pinIndex);
332094332d3Sopenharmony_ci    }
333094332d3Sopenharmony_ci    g_pinDbOp->pinIndex = pinIndex;
334094332d3Sopenharmony_ci    g_pinDbOp->pinIndexLen++;
335094332d3Sopenharmony_ci    ResultCode ret = WritePinDb(g_pinDbOp);
336094332d3Sopenharmony_ci    if (ret != RESULT_SUCCESS) {
337094332d3Sopenharmony_ci        LOG_ERROR("WritePinDb fail.");
338094332d3Sopenharmony_ci        return ret;
339094332d3Sopenharmony_ci    }
340094332d3Sopenharmony_ci
341094332d3Sopenharmony_ci    LOG_INFO("AddPinInDb succ.");
342094332d3Sopenharmony_ci    return RESULT_SUCCESS;
343094332d3Sopenharmony_ci}
344094332d3Sopenharmony_ci
345094332d3Sopenharmony_cistatic ResultCode WriteAddPinInfo(const Buffer *secret, const Buffer *pinCredentialData, uint8_t *salt,
346094332d3Sopenharmony_ci    uint32_t saltLen, const uint64_t templateId)
347094332d3Sopenharmony_ci{
348094332d3Sopenharmony_ci    ResultCode ret = WritePinFile(pinCredentialData->buf, pinCredentialData->contentSize, templateId, CRYPTO_SUFFIX);
349094332d3Sopenharmony_ci    if (ret != RESULT_SUCCESS) {
350094332d3Sopenharmony_ci        LOG_ERROR("WriteCryptoFile fail.");
351094332d3Sopenharmony_ci        return ret;
352094332d3Sopenharmony_ci    }
353094332d3Sopenharmony_ci
354094332d3Sopenharmony_ci    ret = WritePinFile(salt, saltLen, templateId, SALT_SUFFIX);
355094332d3Sopenharmony_ci    if (ret != RESULT_SUCCESS) {
356094332d3Sopenharmony_ci        LOG_ERROR("WriteSaltFile fail.");
357094332d3Sopenharmony_ci        return ret;
358094332d3Sopenharmony_ci    }
359094332d3Sopenharmony_ci
360094332d3Sopenharmony_ci    ret = WritePinFile(secret->buf, secret->contentSize, templateId, SECRET_SUFFIX);
361094332d3Sopenharmony_ci    if (ret != RESULT_SUCCESS) {
362094332d3Sopenharmony_ci        LOG_ERROR("WriteSecretFile fail.");
363094332d3Sopenharmony_ci        return ret;
364094332d3Sopenharmony_ci    }
365094332d3Sopenharmony_ci    AntiBruteInfoV0 initAntiBrute = {};
366094332d3Sopenharmony_ci    InitAntiBruteInfo(&initAntiBrute);
367094332d3Sopenharmony_ci    ret = WritePinFile((uint8_t *)(&initAntiBrute), sizeof(AntiBruteInfoV0), templateId, ANTI_BRUTE_SUFFIX);
368094332d3Sopenharmony_ci    if (ret != RESULT_SUCCESS) {
369094332d3Sopenharmony_ci        LOG_ERROR("WriteAntiBruteFile fail.");
370094332d3Sopenharmony_ci        return ret;
371094332d3Sopenharmony_ci    }
372094332d3Sopenharmony_ci
373094332d3Sopenharmony_ci    LOG_INFO("WriteAddPinInfo succ.");
374094332d3Sopenharmony_ci    return RESULT_SUCCESS;
375094332d3Sopenharmony_ci}
376094332d3Sopenharmony_ci
377094332d3Sopenharmony_cistatic Buffer *GenerateExpandData(char *str, const uint8_t *data, const uint32_t dataLen)
378094332d3Sopenharmony_ci{
379094332d3Sopenharmony_ci    /* CONST_EXPAND_DATA_LEN is twice the size of dataLen */
380094332d3Sopenharmony_ci    if (dataLen < strlen(str) || dataLen != (CONST_EXPAND_DATA_LEN / 2)) {
381094332d3Sopenharmony_ci        LOG_ERROR("bad param.");
382094332d3Sopenharmony_ci        return NULL;
383094332d3Sopenharmony_ci    }
384094332d3Sopenharmony_ci    Buffer *outBuff = CreateBufferBySize(CONST_EXPAND_DATA_LEN);
385094332d3Sopenharmony_ci    if (!IsBufferValid(outBuff)) {
386094332d3Sopenharmony_ci        LOG_ERROR("create buffer fail.");
387094332d3Sopenharmony_ci        return NULL;
388094332d3Sopenharmony_ci    }
389094332d3Sopenharmony_ci    (void)memset_s(outBuff->buf, outBuff->maxSize, 0, outBuff->maxSize);
390094332d3Sopenharmony_ci    outBuff->contentSize = outBuff->maxSize;
391094332d3Sopenharmony_ci    uint8_t *temp = outBuff->buf;
392094332d3Sopenharmony_ci    if (memcpy_s(temp, outBuff->maxSize, (uint8_t *)str, strlen(str)) != EOK) {
393094332d3Sopenharmony_ci        LOG_ERROR("copy str fail.");
394094332d3Sopenharmony_ci        DestroyBuffer(outBuff);
395094332d3Sopenharmony_ci        return NULL;
396094332d3Sopenharmony_ci    }
397094332d3Sopenharmony_ci
398094332d3Sopenharmony_ci    temp += dataLen;
399094332d3Sopenharmony_ci    if (memcpy_s(temp, outBuff->maxSize - dataLen, data, dataLen) != EOK) {
400094332d3Sopenharmony_ci        LOG_ERROR("copy data fail.");
401094332d3Sopenharmony_ci        DestroyBuffer(outBuff);
402094332d3Sopenharmony_ci        return NULL;
403094332d3Sopenharmony_ci    }
404094332d3Sopenharmony_ci
405094332d3Sopenharmony_ci    return outBuff;
406094332d3Sopenharmony_ci}
407094332d3Sopenharmony_ci
408094332d3Sopenharmony_cistatic ResultCode GenerateRootSecret(const Buffer *deviceKey, const Buffer *pinData, Buffer *outRootSecret)
409094332d3Sopenharmony_ci{
410094332d3Sopenharmony_ci    Buffer *expandData = GenerateExpandData(SALT_PREFIX, pinData->buf, pinData->contentSize);
411094332d3Sopenharmony_ci    if (!IsBufferValid(expandData)) {
412094332d3Sopenharmony_ci        LOG_ERROR("generate expand data fail.");
413094332d3Sopenharmony_ci        return RESULT_GENERAL_ERROR;
414094332d3Sopenharmony_ci    }
415094332d3Sopenharmony_ci
416094332d3Sopenharmony_ci    Buffer *hkdfSalt = Sha256Adaptor(expandData);
417094332d3Sopenharmony_ci    if (!IsBufferValid(hkdfSalt)) {
418094332d3Sopenharmony_ci        LOG_ERROR("generate sha256 fail.");
419094332d3Sopenharmony_ci        DestroyBuffer(expandData);
420094332d3Sopenharmony_ci        return RESULT_GENERAL_ERROR;
421094332d3Sopenharmony_ci    }
422094332d3Sopenharmony_ci    Buffer *rootSecret = Hkdf(hkdfSalt, deviceKey);
423094332d3Sopenharmony_ci    DestroyBuffer(expandData);
424094332d3Sopenharmony_ci    DestroyBuffer(hkdfSalt);
425094332d3Sopenharmony_ci    if (!IsBufferValid(rootSecret)) {
426094332d3Sopenharmony_ci        LOG_ERROR("generate rootSecret fail.");
427094332d3Sopenharmony_ci        return RESULT_GENERAL_ERROR;
428094332d3Sopenharmony_ci    }
429094332d3Sopenharmony_ci    if (memcpy_s(outRootSecret->buf, outRootSecret->maxSize, rootSecret->buf, rootSecret->contentSize) != EOK) {
430094332d3Sopenharmony_ci        LOG_ERROR("copy root secret fail.");
431094332d3Sopenharmony_ci        DestroyBuffer(rootSecret);
432094332d3Sopenharmony_ci        return RESULT_BAD_COPY;
433094332d3Sopenharmony_ci    }
434094332d3Sopenharmony_ci
435094332d3Sopenharmony_ci    outRootSecret->contentSize = rootSecret->contentSize;
436094332d3Sopenharmony_ci    DestroyBuffer(rootSecret);
437094332d3Sopenharmony_ci    return RESULT_SUCCESS;
438094332d3Sopenharmony_ci}
439094332d3Sopenharmony_ci
440094332d3Sopenharmony_cistatic Buffer *GenerateEncryptionKey(const Buffer *deviceKey)
441094332d3Sopenharmony_ci{
442094332d3Sopenharmony_ci    Buffer *keyStrBuffer = CreateBufferBySize(CONST_CREDENTIAL_PREFIX_LEN);
443094332d3Sopenharmony_ci    if (!IsBufferValid(keyStrBuffer)) {
444094332d3Sopenharmony_ci        LOG_ERROR("generate expand data fail.");
445094332d3Sopenharmony_ci        return NULL;
446094332d3Sopenharmony_ci    }
447094332d3Sopenharmony_ci    (void)memset_s(keyStrBuffer->buf, keyStrBuffer->maxSize, 0, keyStrBuffer->maxSize);
448094332d3Sopenharmony_ci    if (memcpy_s(keyStrBuffer->buf, keyStrBuffer->maxSize,
449094332d3Sopenharmony_ci        (uint8_t *)CREDENTIAL_PREFIX, strlen(CREDENTIAL_PREFIX)) != EOK) {
450094332d3Sopenharmony_ci        LOG_ERROR("copy CREDENTIAL_PREFIX fail.");
451094332d3Sopenharmony_ci        DestroyBuffer(keyStrBuffer);
452094332d3Sopenharmony_ci        return NULL;
453094332d3Sopenharmony_ci    }
454094332d3Sopenharmony_ci    keyStrBuffer->contentSize = keyStrBuffer->maxSize;
455094332d3Sopenharmony_ci    Buffer *encryptionKey = Hkdf(keyStrBuffer, deviceKey);
456094332d3Sopenharmony_ci    DestroyBuffer(keyStrBuffer);
457094332d3Sopenharmony_ci    if (!IsBufferValid(encryptionKey)) {
458094332d3Sopenharmony_ci        LOG_ERROR("generate encryptionKey fail.");
459094332d3Sopenharmony_ci        return NULL;
460094332d3Sopenharmony_ci    }
461094332d3Sopenharmony_ci
462094332d3Sopenharmony_ci    return encryptionKey;
463094332d3Sopenharmony_ci}
464094332d3Sopenharmony_ci
465094332d3Sopenharmony_cistatic Buffer *SplicePinCiperInfo(const Buffer *iv, const Buffer *tag, const Buffer *ciphertext)
466094332d3Sopenharmony_ci{
467094332d3Sopenharmony_ci    Buffer *cipherInfo = CreateBufferBySize(iv->contentSize + tag->contentSize + ciphertext->contentSize);
468094332d3Sopenharmony_ci    if (cipherInfo == NULL) {
469094332d3Sopenharmony_ci        LOG_ERROR("create cipherInfo fail");
470094332d3Sopenharmony_ci        return NULL;
471094332d3Sopenharmony_ci    }
472094332d3Sopenharmony_ci    if (memcpy_s(cipherInfo->buf, cipherInfo->maxSize, iv->buf, iv->contentSize) != EOK) {
473094332d3Sopenharmony_ci        LOG_ERROR("failed to copy iv");
474094332d3Sopenharmony_ci        goto ERROR;
475094332d3Sopenharmony_ci    }
476094332d3Sopenharmony_ci    cipherInfo->contentSize += iv->contentSize;
477094332d3Sopenharmony_ci    if (memcpy_s(cipherInfo->buf + cipherInfo->contentSize, cipherInfo->maxSize - cipherInfo->contentSize,
478094332d3Sopenharmony_ci        tag->buf, tag->contentSize) != EOK) {
479094332d3Sopenharmony_ci        LOG_ERROR("failed to copy tag");
480094332d3Sopenharmony_ci        goto ERROR;
481094332d3Sopenharmony_ci    }
482094332d3Sopenharmony_ci    cipherInfo->contentSize += tag->contentSize;
483094332d3Sopenharmony_ci    if (memcpy_s(cipherInfo->buf + cipherInfo->contentSize, cipherInfo->maxSize - cipherInfo->contentSize,
484094332d3Sopenharmony_ci        ciphertext->buf, ciphertext->contentSize) != EOK) {
485094332d3Sopenharmony_ci        LOG_ERROR("failed to copy ciphertext");
486094332d3Sopenharmony_ci        goto ERROR;
487094332d3Sopenharmony_ci    }
488094332d3Sopenharmony_ci    cipherInfo->contentSize += ciphertext->contentSize;
489094332d3Sopenharmony_ci    return cipherInfo;
490094332d3Sopenharmony_ci
491094332d3Sopenharmony_ciERROR:
492094332d3Sopenharmony_ci    DestroyBuffer(cipherInfo);
493094332d3Sopenharmony_ci    return NULL;
494094332d3Sopenharmony_ci}
495094332d3Sopenharmony_ci
496094332d3Sopenharmony_cistatic Buffer *GetPinCiperInfo(Buffer *key, Buffer *pinData)
497094332d3Sopenharmony_ci{
498094332d3Sopenharmony_ci    Buffer *cipherText = NULL;
499094332d3Sopenharmony_ci    Buffer *tag = NULL;
500094332d3Sopenharmony_ci    Buffer *cipherInfo = NULL;
501094332d3Sopenharmony_ci    AesGcmParam param = {};
502094332d3Sopenharmony_ci    param.key = key;
503094332d3Sopenharmony_ci    param.iv = CreateBufferBySize(AES_GCM_256_IV_SIZE);
504094332d3Sopenharmony_ci    if (!IsBufferValid(param.iv)) {
505094332d3Sopenharmony_ci        LOG_ERROR("create iv fail.");
506094332d3Sopenharmony_ci        goto EXIT;
507094332d3Sopenharmony_ci    }
508094332d3Sopenharmony_ci    if (SecureRandom(param.iv->buf, param.iv->maxSize) != RESULT_SUCCESS) {
509094332d3Sopenharmony_ci        LOG_ERROR("random iv fail.");
510094332d3Sopenharmony_ci        goto EXIT;
511094332d3Sopenharmony_ci    }
512094332d3Sopenharmony_ci    param.iv->contentSize = param.iv->maxSize;
513094332d3Sopenharmony_ci    if (AesGcm256Encrypt(pinData, &param, &cipherText, &tag) != RESULT_SUCCESS) {
514094332d3Sopenharmony_ci        LOG_ERROR("AesGcmEncrypt fail.");
515094332d3Sopenharmony_ci        goto EXIT;
516094332d3Sopenharmony_ci    }
517094332d3Sopenharmony_ci
518094332d3Sopenharmony_ci    cipherInfo = SplicePinCiperInfo(param.iv, tag, cipherText);
519094332d3Sopenharmony_ci    if (cipherInfo == NULL) {
520094332d3Sopenharmony_ci        LOG_ERROR("SplicePinCiperInfo fail.");
521094332d3Sopenharmony_ci        goto EXIT;
522094332d3Sopenharmony_ci    }
523094332d3Sopenharmony_ci
524094332d3Sopenharmony_ciEXIT:
525094332d3Sopenharmony_ci    DestroyBuffer(param.iv);
526094332d3Sopenharmony_ci    DestroyBuffer(cipherText);
527094332d3Sopenharmony_ci    DestroyBuffer(tag);
528094332d3Sopenharmony_ci
529094332d3Sopenharmony_ci    return cipherInfo;
530094332d3Sopenharmony_ci}
531094332d3Sopenharmony_ci
532094332d3Sopenharmony_cistatic Buffer *CreateSecretBuffer()
533094332d3Sopenharmony_ci{
534094332d3Sopenharmony_ci    Buffer *secret = CreateBufferBySize(SECRET_SIZE);
535094332d3Sopenharmony_ci    if (!IsBufferValid(secret)) {
536094332d3Sopenharmony_ci        LOG_ERROR("generate buffer fail.");
537094332d3Sopenharmony_ci        return secret;
538094332d3Sopenharmony_ci    }
539094332d3Sopenharmony_ci    if (SecureRandom(secret->buf, secret->maxSize) != RESULT_SUCCESS) {
540094332d3Sopenharmony_ci        LOG_ERROR("generate secure random number fail.");
541094332d3Sopenharmony_ci        DestroyBuffer(secret);
542094332d3Sopenharmony_ci        return NULL;
543094332d3Sopenharmony_ci    }
544094332d3Sopenharmony_ci    secret->contentSize = secret->maxSize;
545094332d3Sopenharmony_ci    return secret;
546094332d3Sopenharmony_ci}
547094332d3Sopenharmony_ci
548094332d3Sopenharmony_cistatic ResultCode ProcessAddPin(const Buffer *deviceKey, const Buffer *secret, PinEnrollParam *pinEnrollParam,
549094332d3Sopenharmony_ci    uint64_t *templateId)
550094332d3Sopenharmony_ci{
551094332d3Sopenharmony_ci    *templateId = GeneratePinTemplateId();
552094332d3Sopenharmony_ci    if (*templateId == INVALID_TEMPLATE_ID) {
553094332d3Sopenharmony_ci        LOG_ERROR("GeneratePinTemplateId fail.");
554094332d3Sopenharmony_ci        return RESULT_GENERAL_ERROR;
555094332d3Sopenharmony_ci    }
556094332d3Sopenharmony_ci
557094332d3Sopenharmony_ci    Buffer *key = GenerateEncryptionKey(deviceKey);
558094332d3Sopenharmony_ci    if (!IsBufferValid(key)) {
559094332d3Sopenharmony_ci        LOG_ERROR("GenerateEncryptionKey fail.");
560094332d3Sopenharmony_ci        return RESULT_GENERAL_ERROR;
561094332d3Sopenharmony_ci    }
562094332d3Sopenharmony_ci    Buffer pinDataBuffer = GetTmpBuffer(pinEnrollParam->pinData, CONST_PIN_DATA_LEN, CONST_PIN_DATA_LEN);
563094332d3Sopenharmony_ci    Buffer *cipherInfo = GetPinCiperInfo(key, &pinDataBuffer);
564094332d3Sopenharmony_ci    DestroyBuffer(key);
565094332d3Sopenharmony_ci    if (cipherInfo == NULL) {
566094332d3Sopenharmony_ci        LOG_ERROR("GetPinCiperInfo fail.");
567094332d3Sopenharmony_ci        return RESULT_GENERAL_ERROR;
568094332d3Sopenharmony_ci    }
569094332d3Sopenharmony_ci
570094332d3Sopenharmony_ci    ResultCode ret = WriteAddPinInfo(secret, cipherInfo, pinEnrollParam->salt, CONST_SALT_LEN, *templateId);
571094332d3Sopenharmony_ci    DestroyBuffer(cipherInfo);
572094332d3Sopenharmony_ci    if (ret != RESULT_SUCCESS) {
573094332d3Sopenharmony_ci        LOG_ERROR("write add pin info fail.");
574094332d3Sopenharmony_ci        (void)RemoveAllFile(*templateId);
575094332d3Sopenharmony_ci        return ret;
576094332d3Sopenharmony_ci    }
577094332d3Sopenharmony_ci
578094332d3Sopenharmony_ci    ret = AddPinInDb(*templateId, pinEnrollParam->subType);
579094332d3Sopenharmony_ci    if (ret != RESULT_SUCCESS) {
580094332d3Sopenharmony_ci        LOG_ERROR("AddPinDb fail.");
581094332d3Sopenharmony_ci        (void)RemoveAllFile(*templateId);
582094332d3Sopenharmony_ci        return ret;
583094332d3Sopenharmony_ci    }
584094332d3Sopenharmony_ci    return ret;
585094332d3Sopenharmony_ci}
586094332d3Sopenharmony_ci
587094332d3Sopenharmony_ci/* This is for example only, Should be implemented in trusted environment. */
588094332d3Sopenharmony_ciResultCode AddPin(PinEnrollParam *pinEnrollParam, uint64_t *templateId, Buffer *outRootSecret)
589094332d3Sopenharmony_ci{
590094332d3Sopenharmony_ci    if (!LoadPinDb()) {
591094332d3Sopenharmony_ci        LOG_ERROR("LoadPinDb fail.");
592094332d3Sopenharmony_ci        return RESULT_NEED_INIT;
593094332d3Sopenharmony_ci    }
594094332d3Sopenharmony_ci    if (pinEnrollParam == NULL || templateId == NULL || !IsBufferValid(outRootSecret)) {
595094332d3Sopenharmony_ci        LOG_ERROR("get invalid params.");
596094332d3Sopenharmony_ci        return RESULT_BAD_PARAM;
597094332d3Sopenharmony_ci    }
598094332d3Sopenharmony_ci    ResultCode ret = RESULT_GENERAL_ERROR;
599094332d3Sopenharmony_ci    Buffer pinCredData = GetTmpBuffer(pinEnrollParam->pinData, CONST_PIN_DATA_LEN, CONST_PIN_DATA_LEN);
600094332d3Sopenharmony_ci    Buffer *secret = CreateSecretBuffer();
601094332d3Sopenharmony_ci    Buffer *deviceKey = NULL;
602094332d3Sopenharmony_ci    if (!IsBufferValid(secret)) {
603094332d3Sopenharmony_ci        LOG_ERROR("generate buffer fail.");
604094332d3Sopenharmony_ci        ret = RESULT_NO_MEMORY;
605094332d3Sopenharmony_ci        goto ERROR;
606094332d3Sopenharmony_ci    }
607094332d3Sopenharmony_ci    deviceKey = DeriveDeviceKey(&pinCredData, secret);
608094332d3Sopenharmony_ci    if (!IsBufferValid(deviceKey)) {
609094332d3Sopenharmony_ci        LOG_ERROR("generate deviceKey fail.");
610094332d3Sopenharmony_ci        ret = RESULT_GENERAL_ERROR;
611094332d3Sopenharmony_ci        goto ERROR;
612094332d3Sopenharmony_ci    }
613094332d3Sopenharmony_ci    ret = GenerateRootSecret(deviceKey, &pinCredData, outRootSecret);
614094332d3Sopenharmony_ci    if (ret != RESULT_SUCCESS) {
615094332d3Sopenharmony_ci        LOG_ERROR("generate rootSecret fail.");
616094332d3Sopenharmony_ci        goto ERROR;
617094332d3Sopenharmony_ci    }
618094332d3Sopenharmony_ci    ret = ProcessAddPin(deviceKey, secret, pinEnrollParam, templateId);
619094332d3Sopenharmony_ci    if (ret != RESULT_SUCCESS) {
620094332d3Sopenharmony_ci        LOG_ERROR("process add pin fail.");
621094332d3Sopenharmony_ci        goto ERROR;
622094332d3Sopenharmony_ci    }
623094332d3Sopenharmony_ci    LOG_INFO("AddPin succ.");
624094332d3Sopenharmony_ci
625094332d3Sopenharmony_ciERROR:
626094332d3Sopenharmony_ci    DestroyBuffer(deviceKey);
627094332d3Sopenharmony_ci    DestroyBuffer(secret);
628094332d3Sopenharmony_ci    return ret;
629094332d3Sopenharmony_ci}
630094332d3Sopenharmony_ci
631094332d3Sopenharmony_ciResultCode DoGetAlgoParameter(uint64_t templateId, uint8_t *salt, uint32_t *saltLen, uint32_t *algoVersion)
632094332d3Sopenharmony_ci{
633094332d3Sopenharmony_ci    if (salt == NULL || saltLen == NULL || templateId == INVALID_TEMPLATE_ID || algoVersion == NULL) {
634094332d3Sopenharmony_ci        LOG_ERROR("get invalid algorithm params.");
635094332d3Sopenharmony_ci        return RESULT_BAD_PARAM;
636094332d3Sopenharmony_ci    }
637094332d3Sopenharmony_ci    if (!LoadPinDb()) {
638094332d3Sopenharmony_ci        LOG_ERROR("LoadPinDb fail.");
639094332d3Sopenharmony_ci        return RESULT_NEED_INIT;
640094332d3Sopenharmony_ci    }
641094332d3Sopenharmony_ci
642094332d3Sopenharmony_ci    uint32_t index = MAX_CRYPTO_INFO_SIZE;
643094332d3Sopenharmony_ci    ResultCode ret = SearchPinIndex(templateId, &index);
644094332d3Sopenharmony_ci    if (ret != RESULT_SUCCESS) {
645094332d3Sopenharmony_ci        return ret;
646094332d3Sopenharmony_ci    }
647094332d3Sopenharmony_ci
648094332d3Sopenharmony_ci    ret = ReadPinFile(salt, *saltLen, templateId, SALT_SUFFIX);
649094332d3Sopenharmony_ci    if (ret != RESULT_SUCCESS) {
650094332d3Sopenharmony_ci        LOG_ERROR("salt file read fail.");
651094332d3Sopenharmony_ci        return ret;
652094332d3Sopenharmony_ci    }
653094332d3Sopenharmony_ci
654094332d3Sopenharmony_ci    *algoVersion = g_pinDbOp->pinIndex[index].pinInfo.algoVersion;
655094332d3Sopenharmony_ci    LOG_INFO("DoGetAlgoParameter succ.");
656094332d3Sopenharmony_ci    return RESULT_SUCCESS;
657094332d3Sopenharmony_ci}
658094332d3Sopenharmony_ci
659094332d3Sopenharmony_cistatic ResultCode GetAntiBruteCountById(uint64_t templateId, uint32_t *count)
660094332d3Sopenharmony_ci{
661094332d3Sopenharmony_ci    uint32_t index = MAX_CRYPTO_INFO_SIZE;
662094332d3Sopenharmony_ci    ResultCode ret = SearchPinIndex(templateId, &index);
663094332d3Sopenharmony_ci    if (ret != RESULT_SUCCESS) {
664094332d3Sopenharmony_ci        return ret;
665094332d3Sopenharmony_ci    }
666094332d3Sopenharmony_ci    *count = g_pinDbOp->pinIndex[index].antiBruteInfo.authErrorCount;
667094332d3Sopenharmony_ci    return RESULT_SUCCESS;
668094332d3Sopenharmony_ci}
669094332d3Sopenharmony_ci
670094332d3Sopenharmony_ciResultCode RefreshAntiBruteInfoToFile(uint64_t templateId)
671094332d3Sopenharmony_ci{
672094332d3Sopenharmony_ci    if (!LoadPinDb()) {
673094332d3Sopenharmony_ci        LOG_ERROR("LoadPinDb fail.");
674094332d3Sopenharmony_ci        return RESULT_NEED_INIT;
675094332d3Sopenharmony_ci    }
676094332d3Sopenharmony_ci    uint32_t index = MAX_CRYPTO_INFO_SIZE;
677094332d3Sopenharmony_ci    ResultCode ret = SearchPinIndex(templateId, &index);
678094332d3Sopenharmony_ci    if (ret != RESULT_SUCCESS) {
679094332d3Sopenharmony_ci        return ret;
680094332d3Sopenharmony_ci    }
681094332d3Sopenharmony_ci    ret = WritePinFile((uint8_t *)(&(g_pinDbOp->pinIndex[index].antiBruteInfo)), sizeof(AntiBruteInfoV0),
682094332d3Sopenharmony_ci        templateId, ANTI_BRUTE_SUFFIX);
683094332d3Sopenharmony_ci    if (ret != RESULT_SUCCESS) {
684094332d3Sopenharmony_ci        LOG_ERROR("write anti brute fail.");
685094332d3Sopenharmony_ci    }
686094332d3Sopenharmony_ci
687094332d3Sopenharmony_ci    return ret;
688094332d3Sopenharmony_ci}
689094332d3Sopenharmony_ci
690094332d3Sopenharmony_cistatic ResultCode SetAntiBruteInfoById(uint64_t templateId, uint32_t count, uint64_t startFreezeTime)
691094332d3Sopenharmony_ci{
692094332d3Sopenharmony_ci    uint32_t index = MAX_CRYPTO_INFO_SIZE;
693094332d3Sopenharmony_ci    ResultCode ret = SearchPinIndex(templateId, &index);
694094332d3Sopenharmony_ci    if (ret != RESULT_SUCCESS) {
695094332d3Sopenharmony_ci        return ret;
696094332d3Sopenharmony_ci    }
697094332d3Sopenharmony_ci    g_pinDbOp->pinIndex[index].antiBruteInfo.authErrorCount = count;
698094332d3Sopenharmony_ci    g_pinDbOp->pinIndex[index].antiBruteInfo.startFreezeTime = startFreezeTime;
699094332d3Sopenharmony_ci    ret = WritePinFile((uint8_t *)(&(g_pinDbOp->pinIndex[index].antiBruteInfo)), sizeof(AntiBruteInfoV0),
700094332d3Sopenharmony_ci        templateId, ANTI_BRUTE_SUFFIX);
701094332d3Sopenharmony_ci    if (ret != RESULT_SUCCESS) {
702094332d3Sopenharmony_ci        LOG_ERROR("write anti brute fail.");
703094332d3Sopenharmony_ci        return ret;
704094332d3Sopenharmony_ci    }
705094332d3Sopenharmony_ci    return ret;
706094332d3Sopenharmony_ci}
707094332d3Sopenharmony_ci
708094332d3Sopenharmony_ciResultCode GetSubType(uint64_t templateId, uint64_t *subType)
709094332d3Sopenharmony_ci{
710094332d3Sopenharmony_ci    if (templateId == INVALID_TEMPLATE_ID) {
711094332d3Sopenharmony_ci        LOG_ERROR("check param fail!");
712094332d3Sopenharmony_ci        return RESULT_BAD_PARAM;
713094332d3Sopenharmony_ci    }
714094332d3Sopenharmony_ci    if (!LoadPinDb()) {
715094332d3Sopenharmony_ci        LOG_ERROR("LoadPinDb fail.");
716094332d3Sopenharmony_ci        return RESULT_NEED_INIT;
717094332d3Sopenharmony_ci    }
718094332d3Sopenharmony_ci
719094332d3Sopenharmony_ci    uint32_t index = MAX_CRYPTO_INFO_SIZE;
720094332d3Sopenharmony_ci    ResultCode ret = SearchPinIndex(templateId, &index);
721094332d3Sopenharmony_ci    if (ret != RESULT_SUCCESS) {
722094332d3Sopenharmony_ci        return ret;
723094332d3Sopenharmony_ci    }
724094332d3Sopenharmony_ci    *subType = g_pinDbOp->pinIndex[index].pinInfo.subType;
725094332d3Sopenharmony_ci
726094332d3Sopenharmony_ci    LOG_INFO("GetSubType succ.");
727094332d3Sopenharmony_ci    return RESULT_SUCCESS;
728094332d3Sopenharmony_ci}
729094332d3Sopenharmony_ci
730094332d3Sopenharmony_ciResultCode GetAntiBruteInfo(uint64_t templateId, uint32_t *authErrorCount, uint64_t *startFreezeTime)
731094332d3Sopenharmony_ci{
732094332d3Sopenharmony_ci    if (authErrorCount == NULL || startFreezeTime == NULL || templateId == INVALID_TEMPLATE_ID) {
733094332d3Sopenharmony_ci        LOG_ERROR("check GetAntiBruteInfo param fail!");
734094332d3Sopenharmony_ci        return RESULT_BAD_PARAM;
735094332d3Sopenharmony_ci    }
736094332d3Sopenharmony_ci    if (!LoadPinDb()) {
737094332d3Sopenharmony_ci        LOG_ERROR("LoadPinDb fail.");
738094332d3Sopenharmony_ci        return RESULT_NEED_INIT;
739094332d3Sopenharmony_ci    }
740094332d3Sopenharmony_ci
741094332d3Sopenharmony_ci    uint32_t index = MAX_CRYPTO_INFO_SIZE;
742094332d3Sopenharmony_ci    ResultCode ret = SearchPinIndex(templateId, &index);
743094332d3Sopenharmony_ci    if (ret != RESULT_SUCCESS) {
744094332d3Sopenharmony_ci        return ret;
745094332d3Sopenharmony_ci    }
746094332d3Sopenharmony_ci    *authErrorCount = g_pinDbOp->pinIndex[index].antiBruteInfo.authErrorCount;
747094332d3Sopenharmony_ci    *startFreezeTime = g_pinDbOp->pinIndex[index].antiBruteInfo.startFreezeTime;
748094332d3Sopenharmony_ci
749094332d3Sopenharmony_ci    LOG_INFO("GetAntiBruteInfo succ.");
750094332d3Sopenharmony_ci    return RESULT_SUCCESS;
751094332d3Sopenharmony_ci}
752094332d3Sopenharmony_ci
753094332d3Sopenharmony_cistatic uint64_t ExponentialFuncTime(uint32_t authErrorCount)
754094332d3Sopenharmony_ci{
755094332d3Sopenharmony_ci    uint32_t ret = DEFAULT_VALUE;
756094332d3Sopenharmony_ci    uint32_t exp = (authErrorCount - FIRST_EXPONENTIAL_PARA) / THIRD_EXPONENTIAL_PARA;
757094332d3Sopenharmony_ci    for (uint32_t index = 0; index < exp; ++index) {
758094332d3Sopenharmony_ci        ret *= SECOND_EXPONENTIAL_PARA;
759094332d3Sopenharmony_ci    }
760094332d3Sopenharmony_ci    return FIRST_EXPONENTIAL_PARA * ret;
761094332d3Sopenharmony_ci}
762094332d3Sopenharmony_ci
763094332d3Sopenharmony_cistatic uint64_t GetWaitTime(uint32_t authErrorCount)
764094332d3Sopenharmony_ci{
765094332d3Sopenharmony_ci    if (authErrorCount < FIRST_ANTI_BRUTE_COUNT) {
766094332d3Sopenharmony_ci        return 0;
767094332d3Sopenharmony_ci    }
768094332d3Sopenharmony_ci    if (authErrorCount < ATTI_BRUTE_FIRST_STAGE) {
769094332d3Sopenharmony_ci        if (authErrorCount == FIRST_ANTI_BRUTE_COUNT) {
770094332d3Sopenharmony_ci            return ONE_MIN_TIME * MS_OF_S;
771094332d3Sopenharmony_ci        }
772094332d3Sopenharmony_ci        if (authErrorCount == SECOND_ANTI_BRUTE_COUNT) {
773094332d3Sopenharmony_ci            return TEN_MIN_TIME * MS_OF_S;
774094332d3Sopenharmony_ci        }
775094332d3Sopenharmony_ci        if (authErrorCount == THIRD_ANTI_BRUTE_COUNT) {
776094332d3Sopenharmony_ci            return THIRTY_MIN_TIME * MS_OF_S;
777094332d3Sopenharmony_ci        }
778094332d3Sopenharmony_ci        if (((authErrorCount - FIRST_ANTI_BRUTE_COUNT) % ANTI_BRUTE_COUNT_FREQUENCY) == 0) {
779094332d3Sopenharmony_ci            return ONE_HOUR_TIME * MS_OF_S;
780094332d3Sopenharmony_ci        }
781094332d3Sopenharmony_ci        return 0;
782094332d3Sopenharmony_ci    }
783094332d3Sopenharmony_ci    if (authErrorCount >= ATTI_BRUTE_SECOND_STAGE) {
784094332d3Sopenharmony_ci        return ONE_DAY_TIME * MS_OF_S;
785094332d3Sopenharmony_ci    }
786094332d3Sopenharmony_ci    return ExponentialFuncTime(authErrorCount) * MS_OF_S;
787094332d3Sopenharmony_ci}
788094332d3Sopenharmony_ci
789094332d3Sopenharmony_ciint32_t GetNextFailLockoutDuration(uint32_t authErrorCount)
790094332d3Sopenharmony_ci{
791094332d3Sopenharmony_ci    if (authErrorCount < FIRST_ANTI_BRUTE_COUNT) {
792094332d3Sopenharmony_ci        return ONE_MIN_TIME * MS_OF_S;
793094332d3Sopenharmony_ci    }
794094332d3Sopenharmony_ci    if (authErrorCount < SECOND_ANTI_BRUTE_COUNT) {
795094332d3Sopenharmony_ci        return TEN_MIN_TIME * MS_OF_S;
796094332d3Sopenharmony_ci    }
797094332d3Sopenharmony_ci    if (authErrorCount < THIRD_ANTI_BRUTE_COUNT) {
798094332d3Sopenharmony_ci        return THIRTY_MIN_TIME * MS_OF_S;
799094332d3Sopenharmony_ci    }
800094332d3Sopenharmony_ci    if (authErrorCount < ATTI_BRUTE_FIRST_STAGE -
801094332d3Sopenharmony_ci        (ATTI_BRUTE_FIRST_STAGE - FIRST_ANTI_BRUTE_COUNT) % ANTI_BRUTE_COUNT_FREQUENCY) {
802094332d3Sopenharmony_ci        return ONE_HOUR_TIME * MS_OF_S;
803094332d3Sopenharmony_ci    }
804094332d3Sopenharmony_ci    if (authErrorCount < ATTI_BRUTE_FIRST_STAGE) {
805094332d3Sopenharmony_ci        return (int32_t)ExponentialFuncTime(ATTI_BRUTE_FIRST_STAGE) * MS_OF_S;
806094332d3Sopenharmony_ci    }
807094332d3Sopenharmony_ci    if (authErrorCount < ATTI_BRUTE_SECOND_STAGE - 1) {
808094332d3Sopenharmony_ci        return (int32_t)ExponentialFuncTime(authErrorCount + 1) * MS_OF_S;
809094332d3Sopenharmony_ci    }
810094332d3Sopenharmony_ci    return ONE_DAY_TIME * MS_OF_S;
811094332d3Sopenharmony_ci}
812094332d3Sopenharmony_ci
813094332d3Sopenharmony_ciResultCode ComputeFreezeTime(uint64_t templateId, uint32_t *freezeTime, uint32_t count, uint64_t startFreezeTime)
814094332d3Sopenharmony_ci{
815094332d3Sopenharmony_ci    if (templateId == INVALID_TEMPLATE_ID || freezeTime == NULL) {
816094332d3Sopenharmony_ci        LOG_ERROR("check ComputeFreezeTime param fail!");
817094332d3Sopenharmony_ci        return RESULT_BAD_PARAM;
818094332d3Sopenharmony_ci    }
819094332d3Sopenharmony_ci    if (!LoadPinDb()) {
820094332d3Sopenharmony_ci        LOG_ERROR("LoadPinDb fail.");
821094332d3Sopenharmony_ci        return RESULT_NEED_INIT;
822094332d3Sopenharmony_ci    }
823094332d3Sopenharmony_ci    uint64_t timeValue = GetRtcTime();
824094332d3Sopenharmony_ci    uint64_t waitTime = GetWaitTime(count);
825094332d3Sopenharmony_ci    if (timeValue >= startFreezeTime) {
826094332d3Sopenharmony_ci        uint64_t usedTime = timeValue - startFreezeTime;
827094332d3Sopenharmony_ci        if (usedTime >= waitTime) {
828094332d3Sopenharmony_ci            *freezeTime = 0;
829094332d3Sopenharmony_ci        } else {
830094332d3Sopenharmony_ci            *freezeTime = (waitTime - usedTime) & 0xffffffff;
831094332d3Sopenharmony_ci        }
832094332d3Sopenharmony_ci    } else {
833094332d3Sopenharmony_ci        /* rtc time is reset, we should update startFreezeTime to timeValue */
834094332d3Sopenharmony_ci        if (SetAntiBruteInfoById(templateId, count, timeValue) != RESULT_SUCCESS) {
835094332d3Sopenharmony_ci            LOG_ERROR("SetAntiBruteInfoById fail.");
836094332d3Sopenharmony_ci            return RESULT_BAD_PARAM;
837094332d3Sopenharmony_ci        }
838094332d3Sopenharmony_ci        *freezeTime = waitTime & 0xffffffff;
839094332d3Sopenharmony_ci    }
840094332d3Sopenharmony_ci
841094332d3Sopenharmony_ci    LOG_INFO("ComputeFreezeTime succ.");
842094332d3Sopenharmony_ci    return RESULT_SUCCESS;
843094332d3Sopenharmony_ci}
844094332d3Sopenharmony_ci
845094332d3Sopenharmony_cistatic uint32_t ComputeRemainingTimes(uint32_t errorCount)
846094332d3Sopenharmony_ci{
847094332d3Sopenharmony_ci    if (errorCount < FIRST_ANTI_BRUTE_COUNT) {
848094332d3Sopenharmony_ci        return FIRST_ANTI_BRUTE_COUNT - errorCount;
849094332d3Sopenharmony_ci    }
850094332d3Sopenharmony_ci    if (errorCount >= ATTI_BRUTE_FIRST_STAGE) {
851094332d3Sopenharmony_ci        return REMAINING_TIMES_FREEZE;
852094332d3Sopenharmony_ci    }
853094332d3Sopenharmony_ci    return ANTI_BRUTE_COUNT_FREQUENCY - (errorCount - FIRST_ANTI_BRUTE_COUNT) % ANTI_BRUTE_COUNT_FREQUENCY;
854094332d3Sopenharmony_ci}
855094332d3Sopenharmony_ci
856094332d3Sopenharmony_ciResultCode GetRemainTimes(uint64_t templateId, uint32_t *remainingAuthTimes, uint32_t authErrorCount)
857094332d3Sopenharmony_ci{
858094332d3Sopenharmony_ci    if (templateId == INVALID_TEMPLATE_ID || remainingAuthTimes == NULL) {
859094332d3Sopenharmony_ci        LOG_ERROR("check GetRemainTimes param fail!");
860094332d3Sopenharmony_ci        return RESULT_BAD_PARAM;
861094332d3Sopenharmony_ci    }
862094332d3Sopenharmony_ci    if (!LoadPinDb()) {
863094332d3Sopenharmony_ci        LOG_ERROR("LoadPinDb fail.");
864094332d3Sopenharmony_ci        return RESULT_NEED_INIT;
865094332d3Sopenharmony_ci    }
866094332d3Sopenharmony_ci    *remainingAuthTimes = ComputeRemainingTimes(authErrorCount);
867094332d3Sopenharmony_ci    return RESULT_SUCCESS;
868094332d3Sopenharmony_ci}
869094332d3Sopenharmony_ci
870094332d3Sopenharmony_cistatic ResultCode ClearAntiBruteInfoById(uint64_t templateId)
871094332d3Sopenharmony_ci{
872094332d3Sopenharmony_ci    uint32_t index = MAX_CRYPTO_INFO_SIZE;
873094332d3Sopenharmony_ci    ResultCode ret = SearchPinIndex(templateId, &index);
874094332d3Sopenharmony_ci    if (ret != RESULT_SUCCESS) {
875094332d3Sopenharmony_ci        return ret;
876094332d3Sopenharmony_ci    }
877094332d3Sopenharmony_ci    InitAntiBruteInfo(&(g_pinDbOp->pinIndex[index].antiBruteInfo));
878094332d3Sopenharmony_ci    return RESULT_SUCCESS;
879094332d3Sopenharmony_ci}
880094332d3Sopenharmony_ci
881094332d3Sopenharmony_cistatic ResultCode UpdateAntiBruteFile(uint64_t templateId, bool authResultSucc)
882094332d3Sopenharmony_ci{
883094332d3Sopenharmony_ci    if (templateId == INVALID_TEMPLATE_ID) {
884094332d3Sopenharmony_ci        LOG_ERROR("check param fail.");
885094332d3Sopenharmony_ci        return RESULT_BAD_PARAM;
886094332d3Sopenharmony_ci    }
887094332d3Sopenharmony_ci
888094332d3Sopenharmony_ci    if (authResultSucc) {
889094332d3Sopenharmony_ci        ResultCode ret = ClearAntiBruteInfoById(templateId);
890094332d3Sopenharmony_ci        if (ret != RESULT_SUCCESS) {
891094332d3Sopenharmony_ci            LOG_ERROR("ClearAntiBruteInfoById fail.");
892094332d3Sopenharmony_ci        }
893094332d3Sopenharmony_ci        return ret;
894094332d3Sopenharmony_ci    }
895094332d3Sopenharmony_ci
896094332d3Sopenharmony_ci    uint64_t nowTime = GetRtcTime();
897094332d3Sopenharmony_ci    uint32_t errorCount = 0;
898094332d3Sopenharmony_ci    ResultCode ret = GetAntiBruteCountById(templateId, &errorCount);
899094332d3Sopenharmony_ci    if (ret != RESULT_SUCCESS) {
900094332d3Sopenharmony_ci        LOG_ERROR("GetAntiBruteCountById fail.");
901094332d3Sopenharmony_ci        return ret;
902094332d3Sopenharmony_ci    }
903094332d3Sopenharmony_ci    if (errorCount < ATTI_BRUTE_SECOND_STAGE) {
904094332d3Sopenharmony_ci        errorCount++;
905094332d3Sopenharmony_ci    }
906094332d3Sopenharmony_ci    ret = SetAntiBruteInfoById(templateId, errorCount, nowTime);
907094332d3Sopenharmony_ci    if (ret != RESULT_SUCCESS) {
908094332d3Sopenharmony_ci        LOG_ERROR("SetAntiBruteInfoById fail.");
909094332d3Sopenharmony_ci    }
910094332d3Sopenharmony_ci    return ret;
911094332d3Sopenharmony_ci}
912094332d3Sopenharmony_ci
913094332d3Sopenharmony_cistatic Buffer *GenerateDecodeCredential(const Buffer *deviceKey, const Buffer *pinData)
914094332d3Sopenharmony_ci{
915094332d3Sopenharmony_ci    if (pinData->contentSize <= AES_GCM_256_IV_SIZE + AES_GCM_256_TAG_SIZE) {
916094332d3Sopenharmony_ci        LOG_ERROR("check pin data cipher info fail");
917094332d3Sopenharmony_ci        return NULL;
918094332d3Sopenharmony_ci    }
919094332d3Sopenharmony_ci
920094332d3Sopenharmony_ci    AesGcmParam param = {};
921094332d3Sopenharmony_ci    Buffer iv = GetTmpBuffer(pinData->buf, AES_GCM_256_IV_SIZE, AES_GCM_256_IV_SIZE);
922094332d3Sopenharmony_ci    param.iv = &iv;
923094332d3Sopenharmony_ci    param.key = GenerateEncryptionKey(deviceKey);
924094332d3Sopenharmony_ci    if (param.key == NULL) {
925094332d3Sopenharmony_ci        LOG_ERROR("GenerateEncryptionKey fail");
926094332d3Sopenharmony_ci        return NULL;
927094332d3Sopenharmony_ci    }
928094332d3Sopenharmony_ci    Buffer tag = GetTmpBuffer(pinData->buf + AES_GCM_256_IV_SIZE, AES_GCM_256_TAG_SIZE, AES_GCM_256_TAG_SIZE);
929094332d3Sopenharmony_ci    uint32_t cipherTextSize = pinData->contentSize - AES_GCM_256_IV_SIZE - AES_GCM_256_TAG_SIZE;
930094332d3Sopenharmony_ci    Buffer cipherText = GetTmpBuffer(
931094332d3Sopenharmony_ci        pinData->buf + AES_GCM_256_IV_SIZE + AES_GCM_256_TAG_SIZE, cipherTextSize, cipherTextSize);
932094332d3Sopenharmony_ci    Buffer *plainText = NULL;
933094332d3Sopenharmony_ci    int32_t result = AesGcm256Decrypt(&cipherText, &param, &tag, &plainText);
934094332d3Sopenharmony_ci    DestroyBuffer(param.key);
935094332d3Sopenharmony_ci    if (result != RESULT_SUCCESS) {
936094332d3Sopenharmony_ci        LOG_ERROR("Aes256GcmDecrypt fail");
937094332d3Sopenharmony_ci        return NULL;
938094332d3Sopenharmony_ci    }
939094332d3Sopenharmony_ci
940094332d3Sopenharmony_ci    return plainText;
941094332d3Sopenharmony_ci}
942094332d3Sopenharmony_ci
943094332d3Sopenharmony_cistatic ResultCode ProcessAuthPin(
944094332d3Sopenharmony_ci    const Buffer *storeData, const Buffer *inputData, uint64_t templateId, Buffer *outRootSecret)
945094332d3Sopenharmony_ci{
946094332d3Sopenharmony_ci    Buffer *secret = CreateBufferBySize(SECRET_SIZE);
947094332d3Sopenharmony_ci    Buffer *deviceKey = NULL;
948094332d3Sopenharmony_ci    Buffer *pinDecodeCredential = NULL;
949094332d3Sopenharmony_ci    ResultCode ret = RESULT_COMPARE_FAIL;
950094332d3Sopenharmony_ci    if (!IsBufferValid(secret)) {
951094332d3Sopenharmony_ci        LOG_ERROR("create buffer fail.");
952094332d3Sopenharmony_ci        goto EXIT;
953094332d3Sopenharmony_ci    }
954094332d3Sopenharmony_ci    if (ReadPinFile(secret->buf, secret->maxSize, templateId, SECRET_SUFFIX) != RESULT_SUCCESS) {
955094332d3Sopenharmony_ci        LOG_ERROR("read pin secret file fail.");
956094332d3Sopenharmony_ci        goto EXIT;
957094332d3Sopenharmony_ci    }
958094332d3Sopenharmony_ci    secret->contentSize = secret->maxSize;
959094332d3Sopenharmony_ci    deviceKey = DeriveDeviceKey(inputData, secret);
960094332d3Sopenharmony_ci    if (!IsBufferValid(deviceKey)) {
961094332d3Sopenharmony_ci        LOG_ERROR("generate deviceKey fail.");
962094332d3Sopenharmony_ci        goto EXIT;
963094332d3Sopenharmony_ci    }
964094332d3Sopenharmony_ci    if ((outRootSecret != NULL) &&
965094332d3Sopenharmony_ci        GenerateRootSecret(deviceKey, inputData, outRootSecret) != RESULT_SUCCESS) {
966094332d3Sopenharmony_ci        LOG_ERROR("generate rootSecret fail.");
967094332d3Sopenharmony_ci        goto EXIT;
968094332d3Sopenharmony_ci    }
969094332d3Sopenharmony_ci    pinDecodeCredential = GenerateDecodeCredential(deviceKey, storeData);
970094332d3Sopenharmony_ci    if (!CheckBufferWithSize(pinDecodeCredential, inputData->contentSize)) {
971094332d3Sopenharmony_ci        LOG_ERROR("generate pinDecodeCredential fail.");
972094332d3Sopenharmony_ci        goto EXIT;
973094332d3Sopenharmony_ci    }
974094332d3Sopenharmony_ci    if (CompareBuffer(inputData, pinDecodeCredential)) {
975094332d3Sopenharmony_ci        LOG_INFO("auth pin success.");
976094332d3Sopenharmony_ci        ret = RESULT_SUCCESS;
977094332d3Sopenharmony_ci        goto EXIT;
978094332d3Sopenharmony_ci    }
979094332d3Sopenharmony_ci    LOG_ERROR("auth pin fail.");
980094332d3Sopenharmony_ci
981094332d3Sopenharmony_ciEXIT:
982094332d3Sopenharmony_ci    DestroyBuffer(pinDecodeCredential);
983094332d3Sopenharmony_ci    DestroyBuffer(deviceKey);
984094332d3Sopenharmony_ci    DestroyBuffer(secret);
985094332d3Sopenharmony_ci    return ret;
986094332d3Sopenharmony_ci}
987094332d3Sopenharmony_ci
988094332d3Sopenharmony_ci/* This is for example only, Should be implemented in trusted environment. */
989094332d3Sopenharmony_ciResultCode AuthPinById(const Buffer *inputPinData, uint64_t templateId, Buffer *outRootSecret, ResultCode *compareRet)
990094332d3Sopenharmony_ci{
991094332d3Sopenharmony_ci    if (!CheckBufferWithSize(inputPinData, CONST_PIN_DATA_LEN) ||
992094332d3Sopenharmony_ci        templateId == INVALID_TEMPLATE_ID || compareRet == NULL) {
993094332d3Sopenharmony_ci        LOG_ERROR("get invalid params.");
994094332d3Sopenharmony_ci        return RESULT_BAD_PARAM;
995094332d3Sopenharmony_ci    }
996094332d3Sopenharmony_ci    if (!LoadPinDb()) {
997094332d3Sopenharmony_ci        LOG_ERROR("LoadPinDb fail.");
998094332d3Sopenharmony_ci        return RESULT_NEED_INIT;
999094332d3Sopenharmony_ci    }
1000094332d3Sopenharmony_ci    *compareRet = RESULT_COMPARE_FAIL;
1001094332d3Sopenharmony_ci    uint32_t index = MAX_CRYPTO_INFO_SIZE;
1002094332d3Sopenharmony_ci    ResultCode ret = SearchPinIndex(templateId, &index);
1003094332d3Sopenharmony_ci    if (ret != RESULT_SUCCESS) {
1004094332d3Sopenharmony_ci        return ret;
1005094332d3Sopenharmony_ci    }
1006094332d3Sopenharmony_ci    /* Update anti-brute-force information with authentication failure first */
1007094332d3Sopenharmony_ci    if (UpdateAntiBruteFile(templateId, false) != RESULT_SUCCESS) {
1008094332d3Sopenharmony_ci        LOG_ERROR("update antiBrute file fail.");
1009094332d3Sopenharmony_ci        return RESULT_GENERAL_ERROR;
1010094332d3Sopenharmony_ci    }
1011094332d3Sopenharmony_ci    Buffer *storeData = CreateBufferBySize(CONST_PIN_DATA_EXPAND_LEN);
1012094332d3Sopenharmony_ci    if (!IsBufferValid(storeData)) {
1013094332d3Sopenharmony_ci        LOG_ERROR("generate storeData fail.");
1014094332d3Sopenharmony_ci        return RESULT_GENERAL_ERROR;
1015094332d3Sopenharmony_ci    }
1016094332d3Sopenharmony_ci    ret = ReadPinFile(storeData->buf, storeData->maxSize, templateId, CRYPTO_SUFFIX);
1017094332d3Sopenharmony_ci    if (ret != RESULT_SUCCESS) {
1018094332d3Sopenharmony_ci        LOG_ERROR("read pin store file fail.");
1019094332d3Sopenharmony_ci        DestroyBuffer(storeData);
1020094332d3Sopenharmony_ci        return RESULT_BAD_READ;
1021094332d3Sopenharmony_ci    }
1022094332d3Sopenharmony_ci    storeData->contentSize = storeData->maxSize;
1023094332d3Sopenharmony_ci    *compareRet = ProcessAuthPin(storeData, inputPinData, templateId, outRootSecret);
1024094332d3Sopenharmony_ci    if ((*compareRet) == RESULT_SUCCESS) {
1025094332d3Sopenharmony_ci        ret = UpdateAntiBruteFile(templateId, true);
1026094332d3Sopenharmony_ci        if (ret != RESULT_SUCCESS) {
1027094332d3Sopenharmony_ci            LOG_ERROR("UpdateAntiBruteFile fail.");
1028094332d3Sopenharmony_ci            goto EXIT;
1029094332d3Sopenharmony_ci        }
1030094332d3Sopenharmony_ci    }
1031094332d3Sopenharmony_ci    LOG_INFO("AuthPinById end.");
1032094332d3Sopenharmony_ci
1033094332d3Sopenharmony_ciEXIT:
1034094332d3Sopenharmony_ci    DestroyBuffer(storeData);
1035094332d3Sopenharmony_ci    return ret;
1036094332d3Sopenharmony_ci}
1037094332d3Sopenharmony_ci
1038094332d3Sopenharmony_cistatic bool FindTemplateIdFromList(uint64_t storeTemplateId, const uint64_t *templateIdList, uint32_t templateIdListLen)
1039094332d3Sopenharmony_ci{
1040094332d3Sopenharmony_ci    for (uint32_t i = 0; i < templateIdListLen; ++i) {
1041094332d3Sopenharmony_ci        if (templateIdList[i] == storeTemplateId) {
1042094332d3Sopenharmony_ci            return true;
1043094332d3Sopenharmony_ci        }
1044094332d3Sopenharmony_ci    }
1045094332d3Sopenharmony_ci
1046094332d3Sopenharmony_ci    return false;
1047094332d3Sopenharmony_ci}
1048094332d3Sopenharmony_ci
1049094332d3Sopenharmony_ciResultCode VerifyTemplateDataPin(const uint64_t *templateIdList, uint32_t templateIdListLen)
1050094332d3Sopenharmony_ci{
1051094332d3Sopenharmony_ci    if (templateIdListLen != 0 && templateIdList == NULL) {
1052094332d3Sopenharmony_ci        LOG_ERROR("templateIdList should be not null, when templateIdListLen is not zero");
1053094332d3Sopenharmony_ci        return RESULT_BAD_PARAM;
1054094332d3Sopenharmony_ci    }
1055094332d3Sopenharmony_ci    if (!LoadPinDb()) {
1056094332d3Sopenharmony_ci        LOG_ERROR("LoadPinDb fail.");
1057094332d3Sopenharmony_ci        return RESULT_NEED_INIT;
1058094332d3Sopenharmony_ci    }
1059094332d3Sopenharmony_ci    uint32_t i = 0;
1060094332d3Sopenharmony_ci    for (; i < g_pinDbOp->pinIndexLen; i++) {
1061094332d3Sopenharmony_ci        if (FindTemplateIdFromList(g_pinDbOp->pinIndex[i].pinInfo.templateId, templateIdList, templateIdListLen)) {
1062094332d3Sopenharmony_ci            continue;
1063094332d3Sopenharmony_ci        }
1064094332d3Sopenharmony_ci        ResultCode ret = DelPinById(g_pinDbOp->pinIndex[i].pinInfo.templateId);
1065094332d3Sopenharmony_ci        if (ret != RESULT_SUCCESS) {
1066094332d3Sopenharmony_ci            LOG_ERROR("delete pin file fail.");
1067094332d3Sopenharmony_ci            return RESULT_BAD_DEL;
1068094332d3Sopenharmony_ci        }
1069094332d3Sopenharmony_ci    }
1070094332d3Sopenharmony_ci    LOG_INFO("VerifyTemplateDataPin succ.");
1071094332d3Sopenharmony_ci    return RESULT_SUCCESS;
1072094332d3Sopenharmony_ci}
1073094332d3Sopenharmony_ci
1074094332d3Sopenharmony_cistatic ResultCode GenerateSalt(uint8_t *algoParameter, uint32_t *algoParameterLength,
1075094332d3Sopenharmony_ci    uint8_t *localDeviceId, uint32_t deviceUuidLength)
1076094332d3Sopenharmony_ci{
1077094332d3Sopenharmony_ci    uint8_t sourceDataTemp[SOURCE_DATA_LENGTH] = { 0 };
1078094332d3Sopenharmony_ci    if (memcpy_s(sourceDataTemp, SOURCE_DATA_LENGTH, localDeviceId, deviceUuidLength) != EOK) {
1079094332d3Sopenharmony_ci        LOG_ERROR("memcpy_s localDeviceId to sourceDataTemp failed");
1080094332d3Sopenharmony_ci        return RESULT_GENERAL_ERROR;
1081094332d3Sopenharmony_ci    }
1082094332d3Sopenharmony_ci    if (SecureRandom(&(sourceDataTemp[deviceUuidLength]), SALT_RANDOM_LENGTH) != RESULT_SUCCESS) {
1083094332d3Sopenharmony_ci        LOG_ERROR("Generate random number failed");
1084094332d3Sopenharmony_ci        return RESULT_GENERAL_ERROR;
1085094332d3Sopenharmony_ci    }
1086094332d3Sopenharmony_ci    Buffer sourceData = GetTmpBuffer(sourceDataTemp, SOURCE_DATA_LENGTH, SOURCE_DATA_LENGTH);
1087094332d3Sopenharmony_ci    if (!IsBufferValid(&sourceData)) {
1088094332d3Sopenharmony_ci        LOG_ERROR("sourceData is invalid");
1089094332d3Sopenharmony_ci        return RESULT_GENERAL_ERROR;
1090094332d3Sopenharmony_ci    }
1091094332d3Sopenharmony_ci    Buffer *resultSha256 = Sha256Adaptor(&sourceData);
1092094332d3Sopenharmony_ci    if (!IsBufferValid(resultSha256)) {
1093094332d3Sopenharmony_ci        LOG_ERROR("result is invalid");
1094094332d3Sopenharmony_ci        return RESULT_GENERAL_ERROR;
1095094332d3Sopenharmony_ci    }
1096094332d3Sopenharmony_ci    if (memcpy_s(algoParameter, *algoParameterLength, resultSha256->buf, resultSha256->contentSize) != EOK) {
1097094332d3Sopenharmony_ci        LOG_ERROR("memcpy_s result to algoParameter failed");
1098094332d3Sopenharmony_ci        DestroyBuffer(resultSha256);
1099094332d3Sopenharmony_ci        return RESULT_GENERAL_ERROR;
1100094332d3Sopenharmony_ci    }
1101094332d3Sopenharmony_ci    *algoParameterLength = resultSha256->contentSize;
1102094332d3Sopenharmony_ci
1103094332d3Sopenharmony_ci    DestroyBuffer(resultSha256);
1104094332d3Sopenharmony_ci    LOG_INFO("GenerateAlgoParameterInner succ");
1105094332d3Sopenharmony_ci    return RESULT_SUCCESS;
1106094332d3Sopenharmony_ci}
1107094332d3Sopenharmony_ci
1108094332d3Sopenharmony_ciResultCode DoGenerateAlgoParameter(uint8_t *algoParameter, uint32_t *algoParameterLength, uint32_t *algoVersion,
1109094332d3Sopenharmony_ci    uint8_t *localDeviceId, uint32_t deviceUuidLength)
1110094332d3Sopenharmony_ci{
1111094332d3Sopenharmony_ci    LOG_INFO("start");
1112094332d3Sopenharmony_ci    if (algoParameter == NULL || algoParameterLength == NULL || localDeviceId == NULL || algoVersion == NULL ||
1113094332d3Sopenharmony_ci        deviceUuidLength != DEVICE_UUID_LENGTH) {
1114094332d3Sopenharmony_ci        LOG_ERROR("bad parameter");
1115094332d3Sopenharmony_ci        return RESULT_BAD_PARAM;
1116094332d3Sopenharmony_ci    }
1117094332d3Sopenharmony_ci    if (!LoadPinDb()) {
1118094332d3Sopenharmony_ci        LOG_ERROR("LoadPinDb fail.");
1119094332d3Sopenharmony_ci        return RESULT_NEED_INIT;
1120094332d3Sopenharmony_ci    }
1121094332d3Sopenharmony_ci
1122094332d3Sopenharmony_ci    if (GenerateSalt(algoParameter, algoParameterLength, localDeviceId, deviceUuidLength) != RESULT_SUCCESS) {
1123094332d3Sopenharmony_ci        LOG_ERROR("Generate salt failed");
1124094332d3Sopenharmony_ci        return RESULT_GENERAL_ERROR;
1125094332d3Sopenharmony_ci    }
1126094332d3Sopenharmony_ci    *algoVersion = ALGORITHM_VERSION_0;
1127094332d3Sopenharmony_ci
1128094332d3Sopenharmony_ci    LOG_INFO("gen algo succ size is [%{public}u] and version is [%{public}u]", *algoParameterLength, *algoVersion);
1129094332d3Sopenharmony_ci    return RESULT_SUCCESS;
1130094332d3Sopenharmony_ci}