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