• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022-2025 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 "sym_token_manager.h"
17 
18 #include "alg_defs.h"
19 #include "alg_loader.h"
20 #include "common_defs.h"
21 #include "hc_dev_info.h"
22 #include "hal_error.h"
23 #include "hc_file.h"
24 #include "hc_log.h"
25 #include "hc_mutex.h"
26 #include "hc_types.h"
27 #include "os_account_adapter.h"
28 #include "security_label_adapter.h"
29 #include "string_util.h"
30 
31 IMPLEMENT_HC_VECTOR(SymTokenVec, SymToken*, 1)
32 
33 typedef struct {
34     int32_t osAccountId;
35     SymTokenVec tokens;
36 } OsSymTokensInfo;
37 
38 DECLARE_HC_VECTOR(SymTokensDb, OsSymTokensInfo)
39 IMPLEMENT_HC_VECTOR(SymTokensDb, OsSymTokensInfo, 1)
40 
41 #define FIELD_SYM_TOKENS "symTokens"
42 
43 #define MAX_DB_PATH_LEN 256
44 
45 SymTokenManager g_symTokenManager;
46 
47 static SymTokensDb g_symTokensDb;
48 static HcMutex *g_dataMutex;
49 
IsTokenMatch(const SymToken * token,const char * userId,const char * deviceId)50 static bool IsTokenMatch(const SymToken *token, const char *userId, const char *deviceId)
51 {
52     if (userId == NULL) {
53         LOGE("userId is null!");
54         return false;
55     }
56     if (deviceId == NULL) {
57         LOGE("deviceId is null!");
58         return false;
59     }
60     return (IsStrEqual(userId, token->userId)) && (IsStrEqual(deviceId, token->deviceId));
61 }
62 
GetTokensFilePathCe(int32_t osAccountId,char * tokenPath,uint32_t pathBufferLen)63 static bool GetTokensFilePathCe(int32_t osAccountId, char *tokenPath, uint32_t pathBufferLen)
64 {
65     const char *beginPath = GetStorageDirPathCe();
66     if (beginPath == NULL) {
67         LOGE("Failed to get the storage path!");
68         return false;
69     }
70     if (sprintf_s(tokenPath, pathBufferLen, "%s/%d/deviceauth/account/account_data_sym.dat",
71         beginPath, osAccountId) <= 0) {
72         LOGE("Failed to generate token path!");
73         return false;
74     }
75     return true;
76 }
77 
GetTokensFilePathDe(int32_t osAccountId,char * tokenPath,uint32_t pathBufferLen)78 static bool GetTokensFilePathDe(int32_t osAccountId, char *tokenPath, uint32_t pathBufferLen)
79 {
80     const char *beginPath = GetAccountStoragePath();
81     if (beginPath == NULL) {
82         LOGE("Failed to get the account storage path!");
83         return false;
84     }
85     int32_t writeByteNum;
86     if (osAccountId == DEFAULT_OS_ACCOUNT) {
87         writeByteNum = sprintf_s(tokenPath, pathBufferLen, "%s/account_data_sym.dat", beginPath);
88     } else {
89         writeByteNum = sprintf_s(tokenPath, pathBufferLen, "%s/account_data_sym%d.dat", beginPath, osAccountId);
90     }
91     if (writeByteNum <= 0) {
92         LOGE("sprintf_s fail!");
93         return false;
94     }
95     return true;
96 }
97 
GetTokensFilePath(int32_t osAccountId,char * tokenPath,uint32_t pathBufferLen)98 static bool GetTokensFilePath(int32_t osAccountId, char *tokenPath, uint32_t pathBufferLen)
99 {
100     if (IsOsAccountSupported()) {
101         return GetTokensFilePathCe(osAccountId, tokenPath, pathBufferLen);
102     } else {
103         return GetTokensFilePathDe(osAccountId, tokenPath, pathBufferLen);
104     }
105 }
106 
CreateSymTokenByJson(const CJson * tokenJson)107 static SymToken *CreateSymTokenByJson(const CJson *tokenJson)
108 {
109     SymToken *token = (SymToken *)HcMalloc(sizeof(SymToken), 0);
110     if (token == NULL) {
111         LOGE("Failed to allocate token memory!");
112         return NULL;
113     }
114     const char *userId = GetStringFromJson(tokenJson, FIELD_USER_ID);
115     if (userId == NULL) {
116         LOGE("Failed to get userId from json!");
117         HcFree(token);
118         return NULL;
119     }
120     const char *deviceId = GetStringFromJson(tokenJson, FIELD_DEVICE_ID);
121     if (deviceId == NULL) {
122         LOGE("Failed to get deviceId from json!");
123         HcFree(token);
124         return NULL;
125     }
126     if (strcpy_s(token->userId, DEV_AUTH_USER_ID_SIZE, userId) != EOK) {
127         LOGE("Failed to copy userId!");
128         HcFree(token);
129         return NULL;
130     }
131     if (strcpy_s(token->deviceId, DEV_AUTH_DEVICE_ID_SIZE, deviceId) != EOK) {
132         LOGE("Failed to copy deviceId!");
133         HcFree(token);
134         return NULL;
135     }
136     return token;
137 }
138 
CreateTokensFromJson(CJson * tokensJson,SymTokenVec * vec)139 static int32_t CreateTokensFromJson(CJson *tokensJson, SymTokenVec *vec)
140 {
141     CJson *symTokensJson = GetObjFromJson(tokensJson, FIELD_SYM_TOKENS);
142     if (symTokensJson == NULL) {
143         LOGE("Failed to get symTokensJson from json!");
144         return HC_ERR_JSON_GET;
145     }
146     int32_t tokenNum = GetItemNum(symTokensJson);
147     if (tokenNum <= 0) {
148         LOGE("No token found.");
149         return HC_ERR_JSON_GET;
150     }
151     for (int32_t i = 0; i < tokenNum; i++) {
152         CJson *tokenJson = GetItemFromArray(symTokensJson, i);
153         if (tokenJson == NULL) {
154             LOGE("Token json is null");
155             ClearSymTokenVec(vec);
156             return HC_ERR_JSON_GET;
157         }
158         SymToken *symToken = CreateSymTokenByJson(tokenJson);
159         if (symToken == NULL) {
160             LOGE("Failed to create symToken from json!");
161             ClearSymTokenVec(vec);
162             return HC_ERR_ALLOC_MEMORY;
163         }
164         if (vec->pushBackT(vec, symToken) == NULL) {
165             LOGE("Failed to push symToken to vec");
166             HcFree(symToken);
167             ClearSymTokenVec(vec);
168             return HC_ERR_MEMORY_COPY;
169         }
170     }
171     return HC_SUCCESS;
172 }
173 
ReadTokensFromFile(SymTokenVec * vec,const char * tokenPath)174 static int32_t ReadTokensFromFile(SymTokenVec *vec, const char *tokenPath)
175 {
176     if (vec == NULL) {
177         LOGE("Input token vec is null.");
178         return HC_ERR_NULL_PTR;
179     }
180     FileHandle file = { 0 };
181     int32_t ret = HcFileOpen(tokenPath, MODE_FILE_READ, &file);
182     if (ret != HC_SUCCESS) {
183         LOGE("Open token file failed.");
184         return ret;
185     }
186     SetSecurityLabel(tokenPath, SECURITY_LABEL_S2);
187     int32_t fileSize = HcFileSize(file);
188     if (fileSize <= 0) {
189         LOGE("file size stat failed.");
190         HcFileClose(file);
191         return HC_ERROR;
192     }
193     char *fileData = (char *)HcMalloc(fileSize, 0);
194     if (fileData == NULL) {
195         LOGE("Malloc file data failed.");
196         HcFileClose(file);
197         return HC_ERR_ALLOC_MEMORY;
198     }
199     if (HcFileRead(file, fileData, fileSize) != fileSize) {
200         LOGE("Read file failed.");
201         HcFileClose(file);
202         HcFree(fileData);
203         return HC_ERROR;
204     }
205     HcFileClose(file);
206     CJson *readJsonFile = CreateJsonFromString(fileData);
207     HcFree(fileData);
208     if (readJsonFile == NULL) {
209         LOGE("fileData parse failed");
210         return HC_ERR_JSON_CREATE;
211     }
212     ret = CreateTokensFromJson(readJsonFile, vec);
213     FreeJson(readJsonFile);
214     if (ret != HC_SUCCESS) {
215         LOGE("Failed to create tokens from json");
216     }
217     return ret;
218 }
219 
WriteTokensJsonToFile(CJson * tokensJson,const char * tokenPath)220 static int32_t WriteTokensJsonToFile(CJson *tokensJson, const char *tokenPath)
221 {
222     char *storeJsonString = PackJsonToString(tokensJson);
223     if (storeJsonString == NULL) {
224         LOGE("Pack stored json to string failed.");
225         return HC_ERR_PACKAGE_JSON_TO_STRING_FAIL;
226     }
227     FileHandle file = { 0 };
228     int32_t ret = HcFileOpen(tokenPath, MODE_FILE_WRITE, &file);
229     if (ret != HC_SUCCESS) {
230         LOGE("Open token file failed.");
231         FreeJsonString(storeJsonString);
232         return ret;
233     }
234     SetSecurityLabel(tokenPath, SECURITY_LABEL_S2);
235     int32_t fileSize = (int32_t)(HcStrlen(storeJsonString) + 1);
236     if (HcFileWrite(file, storeJsonString, fileSize) != fileSize) {
237         LOGE("Failed to write token array to file.");
238         ret = HC_ERR_FILE;
239     }
240     FreeJsonString(storeJsonString);
241     HcFileClose(file);
242     return ret;
243 }
244 
GenerateJsonFromToken(const SymToken * token,CJson * tokenJson)245 static int32_t GenerateJsonFromToken(const SymToken *token, CJson *tokenJson)
246 {
247     if (AddStringToJson(tokenJson, FIELD_USER_ID, token->userId) != HC_SUCCESS) {
248         LOGE("Failed to add userId to json!");
249         return HC_ERR_JSON_ADD;
250     }
251     if (AddStringToJson(tokenJson, FIELD_DEVICE_ID, token->deviceId) != HC_SUCCESS) {
252         LOGE("Failed to add deviceId to json!");
253         return HC_ERR_JSON_ADD;
254     }
255     return HC_SUCCESS;
256 }
257 
SaveTokensToFile(const SymTokenVec * vec,const char * tokenPath)258 static int32_t SaveTokensToFile(const SymTokenVec *vec, const char *tokenPath)
259 {
260     CJson *symTokensJson = CreateJsonArray();
261     if (symTokensJson == NULL) {
262         LOGE("Create json failed when save tokens to file.");
263         return HC_ERR_JSON_CREATE;
264     }
265     int32_t ret;
266     uint32_t index;
267     SymToken **token;
268     FOR_EACH_HC_VECTOR(*vec, index, token) {
269         CJson *tokenJson = CreateJson();
270         if (tokenJson == NULL) {
271             LOGE("Create token json failed.");
272             FreeJson(symTokensJson);
273             return HC_ERR_JSON_CREATE;
274         }
275         ret = GenerateJsonFromToken(*token, tokenJson);
276         if (ret != HC_SUCCESS) {
277             LOGE("Generate json from token failed");
278             FreeJson(tokenJson);
279             FreeJson(symTokensJson);
280             return ret;
281         }
282         if (AddObjToArray(symTokensJson, tokenJson) != HC_SUCCESS) {
283             LOGE("Add token json to array failed");
284             FreeJson(tokenJson);
285             FreeJson(symTokensJson);
286             return HC_ERR_JSON_ADD;
287         }
288     }
289     CJson *allTokensJson = CreateJson();
290     if (allTokensJson == NULL) {
291         LOGE("Failed to allocate tokensJson memory!");
292         FreeJson(symTokensJson);
293         return HC_ERR_JSON_CREATE;
294     }
295     if (AddObjToJson(allTokensJson, FIELD_SYM_TOKENS, symTokensJson) != HC_SUCCESS) {
296         LOGE("Failed to add symTokensJson to json!");
297         FreeJson(symTokensJson);
298         FreeJson(allTokensJson);
299         return HC_ERR_JSON_ADD;
300     }
301     FreeJson(symTokensJson);
302     ret = WriteTokensJsonToFile(allTokensJson, tokenPath);
303     FreeJson(allTokensJson);
304     return ret;
305 }
306 
QueryTokenPtrIfMatch(const SymTokenVec * vec,const char * userId,const char * deviceId)307 static SymToken **QueryTokenPtrIfMatch(const SymTokenVec *vec, const char *userId, const char *deviceId)
308 {
309     uint32_t index;
310     SymToken **token;
311     FOR_EACH_HC_VECTOR(*vec, index, token) {
312         if (token == NULL) {
313             continue;
314         }
315         if (IsTokenMatch(*token, userId, deviceId)) {
316             return token;
317         }
318     }
319     return NULL;
320 }
321 
GenerateKeyAlias(const char * userId,const char * deviceId,Uint8Buff * keyAlias)322 static int32_t GenerateKeyAlias(const char *userId, const char *deviceId, Uint8Buff *keyAlias)
323 {
324     if ((userId == NULL) || (deviceId == NULL) || (keyAlias == NULL)) {
325         LOGE("Invalid input params");
326         return HC_ERR_NULL_PTR;
327     }
328     /* KeyAlias = sha256(userId + deviceId + tag). */
329     const char *authCodeTag = "authCode";
330     uint32_t authCodeTagLen = HcStrlen(authCodeTag);
331     uint32_t userIdLen = HcStrlen(userId);
332     uint32_t deviceIdLen = HcStrlen(deviceId);
333     uint32_t aliasLen = authCodeTagLen + userIdLen + deviceIdLen;
334     uint8_t *aliasVal = (uint8_t *)HcMalloc(aliasLen, 0);
335     if (aliasVal == NULL) {
336         LOGE("Failed to malloc for self key aliasStr.");
337         return HC_ERR_ALLOC_MEMORY;
338     }
339     Uint8Buff oriAliasBuff = {
340         aliasVal,
341         aliasLen
342     };
343     if (memcpy_s(oriAliasBuff.val, oriAliasBuff.length, userId, userIdLen) != EOK) {
344         LOGE("Failed to copy userId.");
345         HcFree(aliasVal);
346         return HC_ERR_MEMORY_COPY;
347     }
348     if (memcpy_s(oriAliasBuff.val + userIdLen, oriAliasBuff.length - userIdLen, deviceId, deviceIdLen) != EOK) {
349         LOGE("Failed to copy deviceId.");
350         HcFree(aliasVal);
351         return HC_ERR_MEMORY_COPY;
352     }
353     if (memcpy_s(oriAliasBuff.val + userIdLen + deviceIdLen,
354         oriAliasBuff.length - userIdLen - deviceIdLen, authCodeTag, authCodeTagLen) != EOK) {
355         LOGE("Failed to copy authCodeTag.");
356         HcFree(aliasVal);
357         return HC_ERR_MEMORY_COPY;
358     }
359     int32_t res = GetLoaderInstance()->sha256(&oriAliasBuff, keyAlias);
360     HcFree(aliasVal);
361     if (res != HAL_SUCCESS) {
362         LOGE("Compute authCode alias hash failed");
363     }
364     return res;
365 }
366 
ImportSymTokenToKeyManager(int32_t osAccountId,const SymToken * token,CJson * in,int32_t opCode)367 static int32_t ImportSymTokenToKeyManager(int32_t osAccountId, const SymToken *token, CJson *in, int32_t opCode)
368 {
369     uint8_t authCode[DEV_AUTH_AUTH_CODE_SIZE] = { 0 };
370     if (GetByteFromJson(in, FIELD_AUTH_CODE, authCode, DEV_AUTH_AUTH_CODE_SIZE) != HC_SUCCESS) {
371         LOGE("Failed to get authCode from json!");
372         return HC_ERR_JSON_GET;
373     }
374     uint8_t *keyAliasVal = (uint8_t *)HcMalloc(SHA256_LEN, 0);
375     if (keyAliasVal == NULL) {
376         LOGE("Failed to allocate keyAliasVal memory!");
377         return HC_ERR_ALLOC_MEMORY;
378     }
379     Uint8Buff keyAlias = {
380         .val = keyAliasVal,
381         .length = SHA256_LEN
382     };
383     Uint8Buff authCodeBuff = {
384         .val = authCode,
385         .length = DEV_AUTH_AUTH_CODE_SIZE
386     };
387     int32_t res = GenerateKeyAlias(token->userId, token->deviceId, &keyAlias);
388     if (res != HC_SUCCESS) {
389         LOGE("Failed to generate authCode key alias!");
390         HcFree(keyAliasVal);
391         return res;
392     }
393     KeyPurpose purpose = KEY_PURPOSE_DERIVE;
394     if (opCode == IMPORT_TRUSTED_CREDENTIALS) {
395         purpose = KEY_PURPOSE_MAC;
396     }
397     KeyParams keyParams = { { keyAlias.val, keyAlias.length, true }, false, osAccountId };
398     res = GetLoaderInstance()->importSymmetricKey(&keyParams, &authCodeBuff, purpose, NULL);
399     HcFree(keyAliasVal);
400     if (res != HC_SUCCESS) {
401         LOGE("Failed to import sym token! res: %" LOG_PUB "d", res);
402     } else {
403         LOGI("Import sym token success!");
404     }
405     /* Clear sensitive data: authCode. */
406     (void)memset_s(authCode, DEV_AUTH_AUTH_CODE_SIZE, 0, DEV_AUTH_AUTH_CODE_SIZE);
407     ClearSensitiveStringInJson(in, FIELD_AUTH_CODE);
408     return res;
409 }
410 
DeleteSymTokenFromKeyManager(int32_t osAccountId,const SymToken * token)411 static int32_t DeleteSymTokenFromKeyManager(int32_t osAccountId, const SymToken *token)
412 {
413     uint8_t *keyAliasVal = (uint8_t *)HcMalloc(SHA256_LEN, 0);
414     if (keyAliasVal == NULL) {
415         LOGE("Failed to allocate keyAliasVal memory!");
416         return HC_ERR_ALLOC_MEMORY;
417     }
418     Uint8Buff keyAlias = {
419         .val = keyAliasVal,
420         .length = SHA256_LEN
421     };
422     int32_t res = GenerateKeyAlias(token->userId, token->deviceId, &keyAlias);
423     if (res != HC_SUCCESS) {
424         LOGE("Failed to generate authCode key alias!");
425         HcFree(keyAliasVal);
426         return res;
427     }
428     res = GetLoaderInstance()->deleteKey(&keyAlias, false, osAccountId);
429     HcFree(keyAliasVal);
430     if (res != HC_SUCCESS) {
431         LOGE("Failed to delete sym token! res: %" LOG_PUB "d", res);
432     } else {
433         LOGI("Delete sym token success!");
434     }
435     return res;
436 }
437 
LoadOsSymTokensDb(int32_t osAccountId)438 static void LoadOsSymTokensDb(int32_t osAccountId)
439 {
440     char tokenPath[MAX_DB_PATH_LEN] = { 0 };
441     if (!GetTokensFilePath(osAccountId, tokenPath, MAX_DB_PATH_LEN)) {
442         LOGE("Failed to get token path!");
443         return;
444     }
445     OsSymTokensInfo info;
446     info.osAccountId = osAccountId;
447     info.tokens = CreateSymTokenVec();
448     if (ReadTokensFromFile(&info.tokens, tokenPath) != HC_SUCCESS) {
449         DestroySymTokenVec(&info.tokens);
450         return;
451     }
452     if (g_symTokensDb.pushBackT(&g_symTokensDb, info) == NULL) {
453         LOGE("Failed to push osAccountInfo to database!");
454         ClearSymTokenVec(&info.tokens);
455     }
456     LOGI("Load os account db successfully! [Id]: %" LOG_PUB "d", osAccountId);
457 }
458 
TryMoveDeDataToCe(int32_t osAccountId)459 static void TryMoveDeDataToCe(int32_t osAccountId)
460 {
461     char tokenPathDe[MAX_DB_PATH_LEN] = { 0 };
462     if (!GetTokensFilePathDe(osAccountId, tokenPathDe, MAX_DB_PATH_LEN)) {
463         LOGE("Failed to get de token path!");
464         return;
465     }
466     char tokenPathCe[MAX_DB_PATH_LEN] = { 0 };
467     if (!GetTokensFilePathCe(osAccountId, tokenPathCe, MAX_DB_PATH_LEN)) {
468         LOGE("Failed to get ce token path!");
469         return;
470     }
471     OsSymTokensInfo info;
472     info.osAccountId = osAccountId;
473     info.tokens = CreateSymTokenVec();
474     if (ReadTokensFromFile(&info.tokens, tokenPathCe) == HC_SUCCESS) {
475         LOGI("Ce data exists, no need to move!");
476         ClearSymTokenVec(&info.tokens);
477         return;
478     }
479     ClearSymTokenVec(&info.tokens);
480     info.tokens = CreateSymTokenVec();
481     if (ReadTokensFromFile(&info.tokens, tokenPathDe) != HC_SUCCESS) {
482         LOGI("De data not exists, no need to move!");
483         ClearSymTokenVec(&info.tokens);
484         return;
485     }
486     if (SaveTokensToFile(&info.tokens, tokenPathCe) != HC_SUCCESS) {
487         LOGE("Failed to save tokens to ce file!");
488         ClearSymTokenVec(&info.tokens);
489         return;
490     }
491     ClearSymTokenVec(&info.tokens);
492     info.tokens = CreateSymTokenVec();
493     if (ReadTokensFromFile(&info.tokens, tokenPathCe) != HC_SUCCESS) {
494         LOGE("Failed to read ce file data!");
495         ClearSymTokenVec(&info.tokens);
496         return;
497     }
498     ClearSymTokenVec(&info.tokens);
499     LOGI("Move de data to ce successfully, remove the de file!");
500     HcFileRemove(tokenPathDe);
501 }
502 
RemoveOsSymTokensInfo(int32_t osAccountId)503 static void RemoveOsSymTokensInfo(int32_t osAccountId)
504 {
505     uint32_t index = 0;
506     OsSymTokensInfo *info = NULL;
507     FOR_EACH_HC_VECTOR(g_symTokensDb, index, info) {
508         if (info->osAccountId == osAccountId) {
509             OsSymTokensInfo deleteInfo;
510             HC_VECTOR_POPELEMENT(&g_symTokensDb, &deleteInfo, index);
511             ClearSymTokenVec(&deleteInfo.tokens);
512             return;
513         }
514     }
515 }
516 
LoadOsSymTokensDbCe(int32_t osAccountId)517 static void LoadOsSymTokensDbCe(int32_t osAccountId)
518 {
519     TryMoveDeDataToCe(osAccountId);
520     RemoveOsSymTokensInfo(osAccountId);
521     LoadOsSymTokensDb(osAccountId);
522 }
523 
OnOsAccountUnlocked(int32_t osAccountId)524 static void OnOsAccountUnlocked(int32_t osAccountId)
525 {
526     LOGI("Os account is unlocked, osAccountId: %" LOG_PUB "d", osAccountId);
527     (void)LockHcMutex(g_dataMutex);
528     LoadOsSymTokensDbCe(osAccountId);
529     UnlockHcMutex(g_dataMutex);
530 }
531 
OnOsAccountRemoved(int32_t osAccountId)532 static void OnOsAccountRemoved(int32_t osAccountId)
533 {
534     LOGI("Os account is removed, osAccountId: %" LOG_PUB "d", osAccountId);
535     (void)LockHcMutex(g_dataMutex);
536     RemoveOsSymTokensInfo(osAccountId);
537     UnlockHcMutex(g_dataMutex);
538 }
539 
IsOsAccountSymTokenDataLoaded(int32_t osAccountId)540 static bool IsOsAccountSymTokenDataLoaded(int32_t osAccountId)
541 {
542     uint32_t index = 0;
543     OsSymTokensInfo *info = NULL;
544     FOR_EACH_HC_VECTOR(g_symTokensDb, index, info) {
545         if (info->osAccountId == osAccountId) {
546             return true;
547         }
548     }
549     return false;
550 }
551 
LoadDataIfNotLoaded(int32_t osAccountId)552 static void LoadDataIfNotLoaded(int32_t osAccountId)
553 {
554     if (IsOsAccountSymTokenDataLoaded(osAccountId)) {
555         return;
556     }
557     LOGI("Data has not been loaded, load it, osAccountId: %" LOG_PUB "d", osAccountId);
558     LoadOsSymTokensDbCe(osAccountId);
559 }
560 
GetTokensInfoByOsAccountId(int32_t osAccountId)561 static OsSymTokensInfo *GetTokensInfoByOsAccountId(int32_t osAccountId)
562 {
563     if (IsOsAccountSupported()) {
564         LoadDataIfNotLoaded(osAccountId);
565     }
566     uint32_t index = 0;
567     OsSymTokensInfo *info = NULL;
568     FOR_EACH_HC_VECTOR(g_symTokensDb, index, info) {
569         if (info->osAccountId == osAccountId) {
570             return info;
571         }
572     }
573     LOGI("Create a new os account database cache! [Id]: %" LOG_PUB "d", osAccountId);
574     OsSymTokensInfo newInfo;
575     newInfo.osAccountId = osAccountId;
576     newInfo.tokens = CreateSymTokenVec();
577     OsSymTokensInfo *returnInfo = g_symTokensDb.pushBackT(&g_symTokensDb, newInfo);
578     if (returnInfo == NULL) {
579         LOGE("Failed to push OsSymTokensInfo to database!");
580         DestroySymTokenVec(&newInfo.tokens);
581     }
582     return returnInfo;
583 }
584 
SaveOsSymTokensDb(int32_t osAccountId)585 static int32_t SaveOsSymTokensDb(int32_t osAccountId)
586 {
587     char tokenPath[MAX_DB_PATH_LEN] = { 0 };
588     if (!GetTokensFilePath(osAccountId, tokenPath, MAX_DB_PATH_LEN)) {
589         LOGE("Failed to get token path!");
590         return HC_ERROR;
591     }
592     OsSymTokensInfo *info = GetTokensInfoByOsAccountId(osAccountId);
593     if (info == NULL) {
594         LOGE("Failed to get tokens by os account id. [OsAccountId]: %" LOG_PUB "d", osAccountId);
595         return HC_ERR_INVALID_PARAMS;
596     }
597     int32_t ret = SaveTokensToFile(&info->tokens, tokenPath);
598     if (ret != HC_SUCCESS) {
599         LOGE("Save tokens to file failed");
600         return ret;
601     }
602     LOGI("Save an os account database successfully! [Id]: %" LOG_PUB "d", osAccountId);
603     return HC_SUCCESS;
604 }
605 
AddSymTokenToVec(int32_t osAccountId,SymToken * token)606 static int32_t AddSymTokenToVec(int32_t osAccountId, SymToken *token)
607 {
608     LOGI("Start to add a token to database!");
609     OsSymTokensInfo *info = GetTokensInfoByOsAccountId(osAccountId);
610     if (info == NULL) {
611         LOGE("Failed to get tokens by os account id. [OsAccountId]: %" LOG_PUB "d", osAccountId);
612         return HC_ERR_INVALID_PARAMS;
613     }
614     SymToken **oldTokenPtr = QueryTokenPtrIfMatch(&info->tokens, token->userId, token->deviceId);
615     if (oldTokenPtr != NULL) {
616         LOGI("Replace an old token successfully!");
617         HcFree(*oldTokenPtr);
618         *oldTokenPtr = token;
619         return HC_SUCCESS;
620     }
621     if (info->tokens.pushBackT(&info->tokens, token) == NULL) {
622         LOGE("Failed to push token to vec!");
623         return HC_ERR_MEMORY_COPY;
624     }
625     LOGI("Add a token to database successfully!");
626     return HC_SUCCESS;
627 }
628 
PopSymTokenFromVec(int32_t osAccountId,const char * userId,const char * deviceId)629 static SymToken *PopSymTokenFromVec(int32_t osAccountId, const char *userId, const char *deviceId)
630 {
631     LOGI("Start to pop token from database!");
632     OsSymTokensInfo *info = GetTokensInfoByOsAccountId(osAccountId);
633     if (info == NULL) {
634         LOGE("Failed to get tokens by os account id. [OsAccountId]: %" LOG_PUB "d", osAccountId);
635         return NULL;
636     }
637     uint32_t index = 0;
638     SymToken **token = NULL;
639     while (index < HC_VECTOR_SIZE(&info->tokens)) {
640         token = info->tokens.getp(&info->tokens, index);
641         if ((token == NULL) || (*token == NULL) || (!IsTokenMatch(*token, userId, deviceId))) {
642             index++;
643             continue;
644         }
645         SymToken *deleteToken = NULL;
646         HC_VECTOR_POPELEMENT(&info->tokens, &deleteToken, index);
647         LOGI("Pop a token from database successfully!");
648         return deleteToken;
649     }
650     LOGE("The token is not found!");
651     return NULL;
652 }
653 
AddToken(int32_t osAccountId,int32_t opCode,CJson * in)654 static int32_t AddToken(int32_t osAccountId, int32_t opCode, CJson *in)
655 {
656     LOGI("[Token]: Add sym token starting ...");
657     if (in == NULL) {
658         LOGE("Invalid params!");
659         return HC_ERR_NULL_PTR;
660     }
661     SymToken *symToken = CreateSymTokenByJson(in);
662     if (symToken == NULL) {
663         LOGE("Failed to create symToken from json!");
664         return HC_ERR_ALLOC_MEMORY;
665     }
666     (void)LockHcMutex(g_dataMutex);
667     int32_t res = AddSymTokenToVec(osAccountId, symToken);
668     if (res != HC_SUCCESS) {
669         UnlockHcMutex(g_dataMutex);
670         LOGE("Failed to add sym token to vec");
671         HcFree(symToken);
672         return res;
673     }
674     res = ImportSymTokenToKeyManager(osAccountId, symToken, in, opCode);
675     if (res != HC_SUCCESS) {
676         UnlockHcMutex(g_dataMutex);
677         LOGE("Failed to import sym token!");
678         return res;
679     }
680     res = SaveOsSymTokensDb(osAccountId);
681     UnlockHcMutex(g_dataMutex);
682     if (res != HC_SUCCESS) {
683         LOGE("Failed to save token to db");
684         return res;
685     }
686     LOGI("[Token]: Add sym token success");
687     return HC_SUCCESS;
688 }
689 
DeleteToken(int32_t osAccountId,const char * userId,const char * deviceId)690 static int32_t DeleteToken(int32_t osAccountId, const char *userId, const char *deviceId)
691 {
692     LOGI("[Token]: Delete sym token starting ...");
693     if ((userId == NULL) || (deviceId == NULL)) {
694         LOGE("Invalid params");
695         return HC_ERR_NULL_PTR;
696     }
697     (void)LockHcMutex(g_dataMutex);
698     SymToken *symToken = PopSymTokenFromVec(osAccountId, userId, deviceId);
699     if (symToken == NULL) {
700         UnlockHcMutex(g_dataMutex);
701         return HC_ERR_NULL_PTR;
702     }
703     int32_t res = DeleteSymTokenFromKeyManager(osAccountId, symToken);
704     HcFree(symToken);
705     if (res != HC_SUCCESS) {
706         UnlockHcMutex(g_dataMutex);
707         LOGE("Failed to delete sym token!");
708         return res;
709     }
710     res = SaveOsSymTokensDb(osAccountId);
711     UnlockHcMutex(g_dataMutex);
712     if (res != HC_SUCCESS) {
713         LOGE("Failed to save token to db, account id is: %" LOG_PUB "d", osAccountId);
714         return res;
715     }
716     LOGI("[Token]: Delete sym token success");
717     return HC_SUCCESS;
718 }
719 
LoadTokenDb(void)720 static void LoadTokenDb(void)
721 {
722     if (IsOsAccountSupported()) {
723         return;
724     }
725     StringVector dbNameVec = CreateStrVector();
726     HcFileGetSubFileName(GetAccountStoragePath(), &dbNameVec);
727     uint32_t index;
728     HcString *dbName = NULL;
729     FOR_EACH_HC_VECTOR(dbNameVec, index, dbName) {
730         int32_t osAccountId;
731         const char *name = StringGet(dbName);
732         if (name == NULL) {
733             continue;
734         }
735         if (IsStrEqual(name, "account_data_sym.dat")) {
736             LoadOsSymTokensDb(DEFAULT_OS_ACCOUNT);
737         } else if (sscanf_s(name, "account_data_sym%d.dat", &osAccountId) == 1) {
738             LoadOsSymTokensDb(osAccountId);
739         }
740     }
741     DestroyStrVector(&dbNameVec);
742 }
743 
ClearSymTokenVec(SymTokenVec * vec)744 void ClearSymTokenVec(SymTokenVec *vec)
745 {
746     uint32_t index;
747     SymToken **token;
748     FOR_EACH_HC_VECTOR(*vec, index, token) {
749         HcFree(*token);
750     }
751     DESTROY_HC_VECTOR(SymTokenVec, vec);
752 }
753 
GetSymTokenManager(void)754 SymTokenManager *GetSymTokenManager(void)
755 {
756     return &g_symTokenManager;
757 }
758 
InitSymTokenManager(void)759 void InitSymTokenManager(void)
760 {
761     if (g_dataMutex == NULL) {
762         g_dataMutex = (HcMutex *)HcMalloc(sizeof(HcMutex), 0);
763         if (g_dataMutex == NULL) {
764             LOGE("Alloc account database mutex failed.");
765             return;
766         }
767         if (InitHcMutex(g_dataMutex, false) != HC_SUCCESS) {
768             LOGE("Init account mutex failed.");
769             HcFree(g_dataMutex);
770             g_dataMutex = NULL;
771             return;
772         }
773     }
774     (void)LockHcMutex(g_dataMutex);
775     (void)memset_s(&g_symTokenManager, sizeof(SymTokenManager), 0, sizeof(SymTokenManager));
776     g_symTokenManager.addToken = AddToken;
777     g_symTokenManager.deleteToken = DeleteToken;
778     g_symTokenManager.generateKeyAlias = GenerateKeyAlias;
779     g_symTokensDb = CREATE_HC_VECTOR(SymTokensDb);
780     AddOsAccountEventCallback(SYM_TOKEN_DATA_CALLBACK, OnOsAccountUnlocked, OnOsAccountRemoved);
781     LoadTokenDb();
782     UnlockHcMutex(g_dataMutex);
783 }
784 
DestroySymTokenManager(void)785 void DestroySymTokenManager(void)
786 {
787     (void)LockHcMutex(g_dataMutex);
788     RemoveOsAccountEventCallback(SYM_TOKEN_DATA_CALLBACK);
789     (void)memset_s(&g_symTokenManager, sizeof(SymTokenManager), 0, sizeof(SymTokenManager));
790     uint32_t index;
791     OsSymTokensInfo *info = NULL;
792     FOR_EACH_HC_VECTOR(g_symTokensDb, index, info) {
793         ClearSymTokenVec(&info->tokens);
794     }
795     DESTROY_HC_VECTOR(SymTokensDb, &g_symTokensDb);
796     UnlockHcMutex(g_dataMutex);
797     DestroyHcMutex(g_dataMutex);
798     HcFree(g_dataMutex);
799     g_dataMutex = NULL;
800 }
801