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, ¶m, &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, ¶m, &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, ¶m, &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, ¶m, &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 }