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