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