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(int32_t osAccountId,const SymToken * token,CJson * in,int32_t opCode)356 static int32_t ImportSymTokenToKeyManager(int32_t osAccountId, 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     KeyParams keyParams = { { keyAlias.val, keyAlias.length, true }, false, osAccountId };
387     res = GetLoaderInstance()->importSymmetricKey(&keyParams, &authCodeBuff, purpose, NULL);
388     HcFree(keyAliasVal);
389     if (res != HC_SUCCESS) {
390         LOGE("Failed to import sym token! res: %d", res);
391     } else {
392         LOGI("Import sym token success!");
393     }
394     /* Clear sensitive data: authCode. */
395     (void)memset_s(authCode, DEV_AUTH_AUTH_CODE_SIZE, 0, DEV_AUTH_AUTH_CODE_SIZE);
396     ClearSensitiveStringInJson(in, FIELD_AUTH_CODE);
397     return res;
398 }
399 
DeleteSymTokenFromKeyManager(int32_t osAccountId,const SymToken * token)400 static int32_t DeleteSymTokenFromKeyManager(int32_t osAccountId, const SymToken *token)
401 {
402     uint8_t *keyAliasVal = (uint8_t *)HcMalloc(SHA256_LEN, 0);
403     if (keyAliasVal == NULL) {
404         LOGE("Failed to allocate keyAliasVal memory!");
405         return HC_ERR_ALLOC_MEMORY;
406     }
407     Uint8Buff keyAlias = {
408         .val = keyAliasVal,
409         .length = SHA256_LEN
410     };
411     int32_t res = GenerateKeyAlias(token->userId, token->deviceId, &keyAlias);
412     if (res != HC_SUCCESS) {
413         LOGE("Failed to generate authCode key alias!");
414         HcFree(keyAliasVal);
415         return res;
416     }
417     res = GetLoaderInstance()->deleteKey(&keyAlias, false, osAccountId);
418     HcFree(keyAliasVal);
419     if (res != HC_SUCCESS) {
420         LOGE("Failed to delete sym token! res: %d", res);
421     } else {
422         LOGI("Delete sym token success!");
423     }
424     return res;
425 }
426 
LoadOsSymTokensDb(int32_t osAccountId)427 static void LoadOsSymTokensDb(int32_t osAccountId)
428 {
429     char tokenPath[MAX_DB_PATH_LEN] = { 0 };
430     if (!GetTokensFilePath(osAccountId, tokenPath, MAX_DB_PATH_LEN)) {
431         LOGE("Failed to get token path!");
432         return;
433     }
434     OsSymTokensInfo info;
435     info.osAccountId = osAccountId;
436     info.tokens = CreateSymTokenVec();
437     if (ReadTokensFromFile(&info.tokens, tokenPath) != HC_SUCCESS) {
438         DestroySymTokenVec(&info.tokens);
439         return;
440     }
441     if (g_symTokensDb.pushBackT(&g_symTokensDb, info) == NULL) {
442         LOGE("Failed to push osAccountInfo to database!");
443         ClearSymTokenVec(&info.tokens);
444     }
445     LOGI("Load os account db successfully! [Id]: %d", osAccountId);
446 }
447 
TryMoveDeDataToCe(int32_t osAccountId)448 static void TryMoveDeDataToCe(int32_t osAccountId)
449 {
450     char tokenPathDe[MAX_DB_PATH_LEN] = { 0 };
451     if (!GetTokensFilePathDe(osAccountId, tokenPathDe, MAX_DB_PATH_LEN)) {
452         LOGE("Failed to get de token path!");
453         return;
454     }
455     char tokenPathCe[MAX_DB_PATH_LEN] = { 0 };
456     if (!GetTokensFilePathCe(osAccountId, tokenPathCe, MAX_DB_PATH_LEN)) {
457         LOGE("Failed to get ce token path!");
458         return;
459     }
460     OsSymTokensInfo info;
461     info.osAccountId = osAccountId;
462     info.tokens = CreateSymTokenVec();
463     if (ReadTokensFromFile(&info.tokens, tokenPathCe) == HC_SUCCESS) {
464         LOGI("Ce data exists, no need to move!");
465         ClearSymTokenVec(&info.tokens);
466         return;
467     }
468     ClearSymTokenVec(&info.tokens);
469     info.tokens = CreateSymTokenVec();
470     if (ReadTokensFromFile(&info.tokens, tokenPathDe) != HC_SUCCESS) {
471         LOGI("De data not exists, no need to move!");
472         ClearSymTokenVec(&info.tokens);
473         return;
474     }
475     if (SaveTokensToFile(&info.tokens, tokenPathCe) != HC_SUCCESS) {
476         LOGE("Failed to save tokens to ce file!");
477         ClearSymTokenVec(&info.tokens);
478         return;
479     }
480     ClearSymTokenVec(&info.tokens);
481     info.tokens = CreateSymTokenVec();
482     if (ReadTokensFromFile(&info.tokens, tokenPathCe) != HC_SUCCESS) {
483         LOGE("Failed to read ce file data!");
484         ClearSymTokenVec(&info.tokens);
485         return;
486     }
487     ClearSymTokenVec(&info.tokens);
488     LOGI("Move de data to ce successfully, remove the de file!");
489     HcFileRemove(tokenPathDe);
490 }
491 
RemoveOsSymTokensInfo(int32_t osAccountId)492 static void RemoveOsSymTokensInfo(int32_t osAccountId)
493 {
494     uint32_t index = 0;
495     OsSymTokensInfo *info = NULL;
496     FOR_EACH_HC_VECTOR(g_symTokensDb, index, info) {
497         if (info->osAccountId == osAccountId) {
498             OsSymTokensInfo deleteInfo;
499             HC_VECTOR_POPELEMENT(&g_symTokensDb, &deleteInfo, index);
500             ClearSymTokenVec(&deleteInfo.tokens);
501             return;
502         }
503     }
504 }
505 
LoadOsSymTokensDbCe(int32_t osAccountId)506 static void LoadOsSymTokensDbCe(int32_t osAccountId)
507 {
508     TryMoveDeDataToCe(osAccountId);
509     RemoveOsSymTokensInfo(osAccountId);
510     LoadOsSymTokensDb(osAccountId);
511 }
512 
OnOsAccountUnlocked(int32_t osAccountId)513 static void OnOsAccountUnlocked(int32_t osAccountId)
514 {
515     LOGI("Os account is unlocked, osAccountId: %d", osAccountId);
516     g_dataMutex->lock(g_dataMutex);
517     LoadOsSymTokensDbCe(osAccountId);
518     g_dataMutex->unlock(g_dataMutex);
519 }
520 
OnOsAccountRemoved(int32_t osAccountId)521 static void OnOsAccountRemoved(int32_t osAccountId)
522 {
523     LOGI("Os account is removed, osAccountId: %d", osAccountId);
524     g_dataMutex->lock(g_dataMutex);
525     RemoveOsSymTokensInfo(osAccountId);
526     g_dataMutex->unlock(g_dataMutex);
527 }
528 
IsOsAccountDataLoaded(int32_t osAccountId)529 static bool IsOsAccountDataLoaded(int32_t osAccountId)
530 {
531     uint32_t index = 0;
532     OsSymTokensInfo *info = NULL;
533     FOR_EACH_HC_VECTOR(g_symTokensDb, index, info) {
534         if (info->osAccountId == osAccountId) {
535             return true;
536         }
537     }
538     return false;
539 }
540 
LoadDataIfNotLoaded(int32_t osAccountId)541 static void LoadDataIfNotLoaded(int32_t osAccountId)
542 {
543     if (IsOsAccountDataLoaded(osAccountId)) {
544         return;
545     }
546     LOGI("Data has not been loaded, load it, osAccountId: %d", osAccountId);
547     LoadOsSymTokensDbCe(osAccountId);
548 }
549 
GetTokensInfoByOsAccountId(int32_t osAccountId)550 static OsSymTokensInfo *GetTokensInfoByOsAccountId(int32_t osAccountId)
551 {
552     if (IsOsAccountSupported()) {
553         LoadDataIfNotLoaded(osAccountId);
554     }
555     uint32_t index = 0;
556     OsSymTokensInfo *info = NULL;
557     FOR_EACH_HC_VECTOR(g_symTokensDb, index, info) {
558         if (info->osAccountId == osAccountId) {
559             return info;
560         }
561     }
562     LOGI("Create a new os account database cache! [Id]: %d", osAccountId);
563     OsSymTokensInfo newInfo;
564     newInfo.osAccountId = osAccountId;
565     newInfo.tokens = CreateSymTokenVec();
566     OsSymTokensInfo *returnInfo = g_symTokensDb.pushBackT(&g_symTokensDb, newInfo);
567     if (returnInfo == NULL) {
568         LOGE("Failed to push OsSymTokensInfo to database!");
569         DestroySymTokenVec(&newInfo.tokens);
570     }
571     return returnInfo;
572 }
573 
SaveOsSymTokensDb(int32_t osAccountId)574 static int32_t SaveOsSymTokensDb(int32_t osAccountId)
575 {
576     char tokenPath[MAX_DB_PATH_LEN] = { 0 };
577     if (!GetTokensFilePath(osAccountId, tokenPath, MAX_DB_PATH_LEN)) {
578         LOGE("Failed to get token path!");
579         return HC_ERROR;
580     }
581     OsSymTokensInfo *info = GetTokensInfoByOsAccountId(osAccountId);
582     if (info == NULL) {
583         LOGE("Failed to get tokens by os account id. [OsAccountId]: %d", osAccountId);
584         return HC_ERR_INVALID_PARAMS;
585     }
586     int32_t ret = SaveTokensToFile(&info->tokens, tokenPath);
587     if (ret != HC_SUCCESS) {
588         LOGE("Save tokens to file failed");
589         return ret;
590     }
591     LOGI("Save an os account database successfully! [Id]: %d", osAccountId);
592     return HC_SUCCESS;
593 }
594 
AddSymTokenToVec(int32_t osAccountId,SymToken * token)595 static int32_t AddSymTokenToVec(int32_t osAccountId, SymToken *token)
596 {
597     LOGI("Start to add a token to database!");
598     OsSymTokensInfo *info = GetTokensInfoByOsAccountId(osAccountId);
599     if (info == NULL) {
600         LOGE("Failed to get tokens by os account id. [OsAccountId]: %d", osAccountId);
601         return HC_ERR_INVALID_PARAMS;
602     }
603     SymToken **oldTokenPtr = QueryTokenPtrIfMatch(&info->tokens, token->userId, token->deviceId);
604     if (oldTokenPtr != NULL) {
605         LOGI("Replace an old token successfully!");
606         HcFree(*oldTokenPtr);
607         *oldTokenPtr = token;
608         return HC_SUCCESS;
609     }
610     if (info->tokens.pushBackT(&info->tokens, token) == NULL) {
611         LOGE("Failed to push token to vec!");
612         return HC_ERR_MEMORY_COPY;
613     }
614     LOGI("Add a token to database successfully!");
615     return HC_SUCCESS;
616 }
617 
PopSymTokenFromVec(int32_t osAccountId,const char * userId,const char * deviceId)618 static SymToken *PopSymTokenFromVec(int32_t osAccountId, const char *userId, const char *deviceId)
619 {
620     LOGI("Start to pop token from database!");
621     OsSymTokensInfo *info = GetTokensInfoByOsAccountId(osAccountId);
622     if (info == NULL) {
623         LOGE("Failed to get tokens by os account id. [OsAccountId]: %d", osAccountId);
624         return NULL;
625     }
626     uint32_t index = 0;
627     SymToken **token = NULL;
628     while (index < HC_VECTOR_SIZE(&info->tokens)) {
629         token = info->tokens.getp(&info->tokens, index);
630         if ((token == NULL) || (*token == NULL) || (!IsTokenMatch(*token, userId, deviceId))) {
631             index++;
632             continue;
633         }
634         SymToken *deleteToken = NULL;
635         HC_VECTOR_POPELEMENT(&info->tokens, &deleteToken, index);
636         LOGI("Pop a token from database successfully!");
637         return deleteToken;
638     }
639     LOGE("The token is not found!");
640     return NULL;
641 }
642 
AddToken(int32_t osAccountId,int32_t opCode,CJson * in)643 static int32_t AddToken(int32_t osAccountId, int32_t opCode, CJson *in)
644 {
645     LOGI("[Token]: Add sym token starting ...");
646     if (in == NULL) {
647         LOGE("Invalid params!");
648         return HC_ERR_NULL_PTR;
649     }
650     SymToken *symToken = CreateSymTokenByJson(in);
651     if (symToken == NULL) {
652         LOGE("Failed to create symToken from json!");
653         return HC_ERR_ALLOC_MEMORY;
654     }
655     g_dataMutex->lock(g_dataMutex);
656     int32_t res = AddSymTokenToVec(osAccountId, symToken);
657     if (res != HC_SUCCESS) {
658         g_dataMutex->unlock(g_dataMutex);
659         LOGE("Failed to add sym token to vec");
660         HcFree(symToken);
661         return res;
662     }
663     res = ImportSymTokenToKeyManager(osAccountId, symToken, in, opCode);
664     if (res != HC_SUCCESS) {
665         g_dataMutex->unlock(g_dataMutex);
666         LOGE("Failed to import sym token!");
667         return res;
668     }
669     res = SaveOsSymTokensDb(osAccountId);
670     g_dataMutex->unlock(g_dataMutex);
671     if (res != HC_SUCCESS) {
672         LOGE("Failed to save token to db");
673         return res;
674     }
675     LOGI("[Token]: Add sym token success");
676     return HC_SUCCESS;
677 }
678 
DeleteToken(int32_t osAccountId,const char * userId,const char * deviceId)679 static int32_t DeleteToken(int32_t osAccountId, const char *userId, const char *deviceId)
680 {
681     LOGI("[Token]: Delete sym token starting ...");
682     if ((userId == NULL) || (deviceId == NULL)) {
683         LOGE("Invalid params");
684         return HC_ERR_NULL_PTR;
685     }
686     g_dataMutex->lock(g_dataMutex);
687     SymToken *symToken = PopSymTokenFromVec(osAccountId, userId, deviceId);
688     if (symToken == NULL) {
689         g_dataMutex->unlock(g_dataMutex);
690         return HC_ERR_NULL_PTR;
691     }
692     int32_t res = DeleteSymTokenFromKeyManager(osAccountId, symToken);
693     HcFree(symToken);
694     if (res != HC_SUCCESS) {
695         g_dataMutex->unlock(g_dataMutex);
696         LOGE("Failed to delete sym token!");
697         return res;
698     }
699     res = SaveOsSymTokensDb(osAccountId);
700     g_dataMutex->unlock(g_dataMutex);
701     if (res != HC_SUCCESS) {
702         LOGE("Failed to save token to db, account id is: %d", osAccountId);
703         return res;
704     }
705     LOGI("[Token]: Delete sym token success");
706     return HC_SUCCESS;
707 }
708 
LoadTokenDb(void)709 static void LoadTokenDb(void)
710 {
711     if (IsOsAccountSupported()) {
712         return;
713     }
714     StringVector dbNameVec = CreateStrVector();
715     HcFileGetSubFileName(GetAccountStoragePath(), &dbNameVec);
716     uint32_t index;
717     HcString *dbName = NULL;
718     FOR_EACH_HC_VECTOR(dbNameVec, index, dbName) {
719         int32_t osAccountId;
720         const char *name = StringGet(dbName);
721         if (name == NULL) {
722             continue;
723         }
724         if (strcmp(name, "account_data_sym.dat") == 0) {
725             LoadOsSymTokensDb(DEFAULT_OS_ACCOUNT);
726         } else if (sscanf_s(name, "account_data_sym%d.dat", &osAccountId) == 1) {
727             LoadOsSymTokensDb(osAccountId);
728         }
729     }
730     DestroyStrVector(&dbNameVec);
731 }
732 
ClearSymTokenVec(SymTokenVec * vec)733 void ClearSymTokenVec(SymTokenVec *vec)
734 {
735     uint32_t index;
736     SymToken **token;
737     FOR_EACH_HC_VECTOR(*vec, index, token) {
738         HcFree(*token);
739     }
740     DESTROY_HC_VECTOR(SymTokenVec, vec);
741 }
742 
GetSymTokenManager(void)743 SymTokenManager *GetSymTokenManager(void)
744 {
745     return &g_symTokenManager;
746 }
747 
InitSymTokenManager(void)748 void InitSymTokenManager(void)
749 {
750     if (g_dataMutex == NULL) {
751         g_dataMutex = (HcMutex *)HcMalloc(sizeof(HcMutex), 0);
752         if (g_dataMutex == NULL) {
753             LOGE("Alloc account database mutex failed.");
754             return;
755         }
756         if (InitHcMutex(g_dataMutex) != HC_SUCCESS) {
757             LOGE("Init account mutex failed.");
758             HcFree(g_dataMutex);
759             g_dataMutex = NULL;
760             return;
761         }
762     }
763     g_dataMutex->lock(g_dataMutex);
764     (void)memset_s(&g_symTokenManager, sizeof(SymTokenManager), 0, sizeof(SymTokenManager));
765     g_symTokenManager.addToken = AddToken;
766     g_symTokenManager.deleteToken = DeleteToken;
767     g_symTokenManager.generateKeyAlias = GenerateKeyAlias;
768     g_symTokensDb = CREATE_HC_VECTOR(SymTokensDb);
769     AddOsAccountEventCallback(SYM_TOKEN_DATA_CALLBACK, OnOsAccountUnlocked, OnOsAccountRemoved);
770     LoadTokenDb();
771     g_dataMutex->unlock(g_dataMutex);
772 }
773 
DestroySymTokenManager(void)774 void DestroySymTokenManager(void)
775 {
776     g_dataMutex->lock(g_dataMutex);
777     RemoveOsAccountEventCallback(SYM_TOKEN_DATA_CALLBACK);
778     (void)memset_s(&g_symTokenManager, sizeof(SymTokenManager), 0, sizeof(SymTokenManager));
779     uint32_t index;
780     OsSymTokensInfo *info = NULL;
781     FOR_EACH_HC_VECTOR(g_symTokensDb, index, info) {
782         ClearSymTokenVec(&info->tokens);
783     }
784     DESTROY_HC_VECTOR(SymTokensDb, &g_symTokensDb);
785     g_dataMutex->unlock(g_dataMutex);
786     DestroyHcMutex(g_dataMutex);
787     HcFree(g_dataMutex);
788     g_dataMutex = NULL;
789 }
790