1 /*
2 * Copyright (C) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "cred_session_util.h"
17
18 #include "hc_log.h"
19 #include "identity_service.h"
20 #include "device_auth.h"
21 #include "common_defs.h"
22 #include "device_auth_defines.h"
23 #include "hc_types.h"
24 #include "hc_dev_info.h"
25 #include "json_utils.h"
26 #include "alg_defs.h"
27 #include "alg_loader.h"
28 #include "string_util.h"
29 #include "os_account_adapter.h"
30 #include "identity_service_defines.h"
31
AddChannelInfoToContext(int32_t channelType,int64_t channelId,CJson * context)32 static int32_t AddChannelInfoToContext(int32_t channelType, int64_t channelId, CJson *context)
33 {
34 if (AddIntToJson(context, FIELD_CHANNEL_TYPE, channelType) != HC_SUCCESS) {
35 LOGE("add channelType to context fail.");
36 return HC_ERR_JSON_ADD;
37 }
38 if (AddByteToJson(context, FIELD_CHANNEL_ID, (uint8_t *)&channelId, sizeof(int64_t)) != HC_SUCCESS) {
39 LOGE("add channelId to context fail.");
40 return HC_ERR_JSON_ADD;
41 }
42 return HC_SUCCESS;
43 }
44
AddCredIdToContextIfNeeded(CJson * context)45 static int32_t AddCredIdToContextIfNeeded(CJson *context)
46 {
47 CJson *credJson = GetObjFromJson(context, FIELD_CREDENTIAL_OBJ);
48 if (credJson == NULL) {
49 LOGE("Get self credential fail.");
50 return HC_ERR_JSON_GET;
51 }
52 uint8_t credType = ACCOUNT_RELATED;
53 if (GetUint8FromJson(context, FIELD_CRED_TYPE, &credType) != HC_SUCCESS) {
54 LOGE("Get credential type fail.");
55 return HC_ERR_JSON_GET;
56 }
57 if (credType != ACCOUNT_SHARED) {
58 LOGI("No need to add across account credential id to context");
59 return HC_SUCCESS;
60 }
61 const char *credId = GetStringFromJson(context, FIELD_CRED_ID);
62 if (AddStringToJson(context, FIELD_ACROSS_ACCOUNT_CRED_ID, credId) != HC_SUCCESS) {
63 LOGE("add across account credential id to context fail.");
64 return HC_ERR_JSON_ADD;
65 }
66 return HC_SUCCESS;
67 }
68
CheckConfirmationExist(const CJson * context)69 static int32_t CheckConfirmationExist(const CJson *context)
70 {
71 uint32_t confirmation = REQUEST_REJECTED;
72 if (GetUnsignedIntFromJson(context, FIELD_CONFIRMATION, &confirmation) != HC_SUCCESS) {
73 LOGE("Failed to get confimation from json!");
74 return HC_ERR_JSON_GET;
75 }
76 if (confirmation == REQUEST_ACCEPTED) {
77 LOGI("The service accepts this request!");
78 } else {
79 LOGW("The service rejects this request!");
80 }
81 return HC_SUCCESS;
82 }
83
GetAppIdByContext(const CJson * context)84 static const char *GetAppIdByContext(const CJson *context)
85 {
86 const char *pinCode = GetStringFromJson(context, FIELD_PIN_CODE);
87 if (pinCode == NULL) {
88 const CJson *json = GetObjFromJson(context, FIELD_CREDENTIAL_OBJ);
89 if (json == NULL) {
90 LOGE("get self credential info from json fail.");
91 return NULL;
92 }
93 const char *appId = GetStringFromJson(json, FIELD_CRED_OWNER);
94 if (appId == NULL) {
95 LOGE("get appId from json fail.");
96 return NULL;
97 }
98 return appId;
99 }
100 const char *appId = GetStringFromJson(context, FIELD_SERVICE_PKG_NAME);
101 if (appId == NULL) {
102 LOGE("get servicePkgName from json fail.");
103 return NULL;
104 }
105 return appId;
106 }
107
AddUserIdHashHexStringToContext(CJson * context,CJson * credAuthInfo)108 static int32_t AddUserIdHashHexStringToContext(CJson *context, CJson *credAuthInfo)
109 {
110 uint8_t credType = ACCOUNT_UNRELATED;
111 if (GetUint8FromJson(credAuthInfo, FIELD_CRED_TYPE, &credType) != HC_SUCCESS) {
112 LOGE("get int from json failed!");
113 return HC_ERR_JSON_GET;
114 }
115 if (credType == ACCOUNT_UNRELATED) {
116 return HC_SUCCESS;
117 }
118 const char *userId = GetStringFromJson(credAuthInfo, FIELD_USER_ID);
119 if (userId == NULL) {
120 LOGE("Failed to get user ID!");
121 return HC_ERR_JSON_GET;
122 }
123 Uint8Buff userIdBuf = { (uint8_t *)userId, (uint32_t)HcStrlen(userId) };
124 uint8_t userIdHashByte[SHA256_LEN] = { 0 };
125 Uint8Buff userIdHashBuf = { userIdHashByte, sizeof(userIdHashByte) };
126 int32_t res = GetLoaderInstance()->sha256(&userIdBuf, &userIdHashBuf);
127 if (res != HC_SUCCESS) {
128 LOGE("sha256 failed, res:%" LOG_PUB "d", res);
129 return res;
130 }
131 uint32_t userIdHashLen = SHA256_LEN * BYTE_TO_HEX_OPER_LENGTH + 1;
132 char *userIdHash = (char *)HcMalloc(userIdHashLen, 0);
133 if (userIdHash == NULL) {
134 LOGE("malloc userIdHash string failed");
135 return HC_ERR_ALLOC_MEMORY;
136 }
137 res = ByteToHexString(userIdHashByte, SHA256_LEN, userIdHash, userIdHashLen);
138 if (res != HC_SUCCESS) {
139 LOGE("Byte to hexString failed, res:%" LOG_PUB "d", res);
140 HcFree(userIdHash);
141 }
142 //replace userId plain to hash hex string
143 if (AddStringToJson(context, FIELD_USER_ID, userIdHash) != HC_SUCCESS) {
144 LOGE("Failed to add userIdHash");
145 return HC_ERR_JSON_ADD;
146 }
147 HcFree(userIdHash);
148 return res;
149 }
150
QueryAndAddSelfCredToContext(int32_t osAccountId,CJson * context)151 static int32_t QueryAndAddSelfCredToContext(int32_t osAccountId, CJson *context)
152 {
153 const char *credId = GetStringFromJson(context, FIELD_CRED_ID);
154 if (credId == NULL) {
155 LOGE("get self credential id from json fail.");
156 return HC_ERR_JSON_GET;
157 }
158 char *credDataStr = NULL;
159 int32_t ret = QueryCredInfoByCredId(osAccountId, credId, &credDataStr);
160 if (ret != HC_SUCCESS) {
161 LOGE("No credential found.");
162 return ret;
163 }
164 CJson *credDataJson = CreateJsonFromString(credDataStr);
165 HcFree(credDataStr);
166 if (credDataJson == NULL) {
167 LOGE("Faild to create json from string");
168 return HC_ERR_JSON_FAIL;
169 }
170 int32_t res = AddUserIdHashHexStringToContext(context, credDataJson);
171 if (res != HC_SUCCESS) {
172 LOGE("Failed to replace userId plain to hash hex string!");
173 return res;
174 }
175 if (AddObjToJson(context, FIELD_CREDENTIAL_OBJ, credDataJson) != HC_SUCCESS) {
176 LOGE("add local credential object to context fail.");
177 FreeJson(credDataJson);
178 return HC_ERR_JSON_ADD;
179 }
180 FreeJson(credDataJson);
181 return HC_SUCCESS;
182 }
183
CheckIsCredBind(CJson * context)184 static bool CheckIsCredBind(CJson *context)
185 {
186 const char *pinCode = GetStringFromJson(context, FIELD_PIN_CODE);
187 bool isBind = true;
188 if (pinCode == NULL || HcStrlen(pinCode) == 0) {
189 isBind = false;
190 }
191 return isBind;
192 }
193
AddAuthIdToCredContext(CJson * context)194 static int32_t AddAuthIdToCredContext(CJson *context)
195 {
196 const char *authId = GetStringFromJson(context, FIELD_DEVICE_ID);
197 char udid[INPUT_UDID_LEN] = { 0 };
198 if (authId == NULL) {
199 LOGD("No authId is found. The default value is udid!");
200 int32_t res = HcGetUdid((uint8_t *)udid, INPUT_UDID_LEN);
201 if (res != HC_SUCCESS) {
202 LOGE("Failed to get local udid! res: %" LOG_PUB "d", res);
203 return HC_ERR_DB;
204 }
205 authId = udid;
206 }
207 if (AddStringToJson(context, FIELD_AUTH_ID, authId) != HC_SUCCESS) {
208 LOGE("Failed to add authId to params!");
209 return HC_ERR_JSON_FAIL;
210 }
211 return HC_SUCCESS;
212 }
213
BuildClientCredBindContext(int32_t osAccountId,int64_t requestId,CJson * context,const char ** returnAppId)214 static int32_t BuildClientCredBindContext(int32_t osAccountId, int64_t requestId,
215 CJson *context, const char **returnAppId)
216 {
217 const char *appId = GetAppIdByContext(context);
218 if (appId == NULL) {
219 LOGE("get appId fail.");
220 return HC_ERR_JSON_GET;
221 }
222 if (AddBoolToJson(context, FIELD_IS_BIND, true) != HC_SUCCESS) {
223 LOGE("add isBind to context fail.");
224 return HC_ERR_JSON_ADD;
225 }
226 if (AddBoolToJson(context, FIELD_IS_CLIENT, true) != HC_SUCCESS) {
227 LOGE("add isClient to context fail.");
228 return HC_ERR_JSON_ADD;
229 }
230 if (AddBoolToJson(context, FIELD_IS_CRED_AUTH, true) != HC_SUCCESS) {
231 LOGE("add isCredAuth to context fail.");
232 return HC_ERR_JSON_ADD;
233 }
234 if (AddIntToJson(context, FIELD_OS_ACCOUNT_ID, osAccountId) != HC_SUCCESS) {
235 LOGE("add osAccountId to context fail.");
236 return HC_ERR_JSON_ADD;
237 }
238 if (AddInt64StringToJson(context, FIELD_REQUEST_ID, requestId) != HC_SUCCESS) {
239 LOGE("add requestId to context fail.");
240 return HC_ERR_JSON_ADD;
241 }
242 if (AddStringToJson(context, FIELD_APP_ID, appId) != HC_SUCCESS) {
243 LOGE("add appId to context fail.");
244 return HC_ERR_JSON_ADD;
245 }
246 if (AddIntToJson(context, FIELD_OPERATION_CODE, AUTH_FORM_ACCOUNT_UNRELATED) != HC_SUCCESS) {
247 LOGE("add opCode to context fail.");
248 return HC_ERR_JSON_ADD;
249 }
250 if (AddAuthIdToCredContext(context)) {
251 return HC_ERR_JSON_ADD;
252 }
253 *returnAppId = appId;
254 return AddChannelInfoToContext(SERVICE_CHANNEL, DEFAULT_CHANNEL_ID, context);
255 }
256
SetContextOpCode(CJson * context)257 static int32_t SetContextOpCode(CJson *context)
258 {
259 uint8_t credType = ACCOUNT_UNRELATED;
260 if (GetUint8FromJson(context, FIELD_CRED_TYPE, &credType) != HC_SUCCESS) {
261 LOGE("get int from json failed!");
262 return HC_ERR_JSON_GET;
263 }
264 switch (credType) {
265 case ACCOUNT_RELATED:
266 if (AddIntToJson(context, FIELD_OPERATION_CODE, AUTH_FORM_IDENTICAL_ACCOUNT) != HC_SUCCESS) {
267 LOGE("add identical account code to context fail.");
268 return HC_ERR_JSON_ADD;
269 }
270 break;
271 case ACCOUNT_UNRELATED:
272 if (AddIntToJson(context, FIELD_OPERATION_CODE, AUTH_FORM_ACCOUNT_UNRELATED) != HC_SUCCESS) {
273 LOGE("add account unrelated code to context fail.");
274 return HC_ERR_JSON_ADD;
275 }
276 break;
277 case ACCOUNT_SHARED:
278 if (AddIntToJson(context, FIELD_OPERATION_CODE, AUTH_FORM_ACROSS_ACCOUNT) != HC_SUCCESS) {
279 LOGE("add across account code to context fail.");
280 return HC_ERR_JSON_ADD;
281 }
282 break;
283 default:
284 LOGE("unsupport cred type.");
285 return HC_ERR_UNSUPPORTED_OPCODE;
286 }
287 return HC_SUCCESS;
288 }
289
BuildClientCredAuthContext(int32_t osAccountId,int64_t requestId,CJson * context,const char ** returnAppId)290 static int32_t BuildClientCredAuthContext(int32_t osAccountId, int64_t requestId,
291 CJson *context, const char **returnAppId)
292 {
293 int32_t res = QueryAndAddSelfCredToContext(osAccountId, context);
294 if (res != HC_SUCCESS) {
295 return res;
296 }
297 const char *appId = GetAppIdByContext(context);
298 if (appId == NULL) {
299 LOGE("get appId fail.");
300 return HC_ERR_JSON_GET;
301 }
302 if (AddBoolToJson(context, FIELD_IS_BIND, false) != HC_SUCCESS) {
303 LOGE("add isBind to context fail.");
304 return HC_ERR_JSON_ADD;
305 }
306 if (AddBoolToJson(context, FIELD_IS_CLIENT, true) != HC_SUCCESS) {
307 LOGE("add isClient to context fail.");
308 return HC_ERR_JSON_ADD;
309 }
310 if (AddBoolToJson(context, FIELD_IS_CRED_AUTH, true) != HC_SUCCESS) {
311 LOGE("add isCredAuth to context fail.");
312 return HC_ERR_JSON_ADD;
313 }
314 if (AddIntToJson(context, FIELD_OS_ACCOUNT_ID, osAccountId) != HC_SUCCESS) {
315 LOGE("add osAccountId to context fail.");
316 return HC_ERR_JSON_ADD;
317 }
318 if (AddInt64StringToJson(context, FIELD_REQUEST_ID, requestId) != HC_SUCCESS) {
319 LOGE("add requestId to context fail.");
320 return HC_ERR_JSON_ADD;
321 }
322 if (AddStringToJson(context, FIELD_APP_ID, appId) != HC_SUCCESS) {
323 LOGE("add appId to context fail.");
324 return HC_ERR_JSON_ADD;
325 }
326 if (SetContextOpCode(context) != HC_SUCCESS) {
327 LOGE("add opCode to context fail.");
328 return HC_ERR_JSON_ADD;
329 }
330 if (AddCredIdToContextIfNeeded(context) != HC_SUCCESS) {
331 LOGE("add across account credential id to context fail.");
332 return HC_ERR_JSON_ADD;
333 }
334 *returnAppId = appId;
335 return AddChannelInfoToContext(SERVICE_CHANNEL, DEFAULT_CHANNEL_ID, context);
336 }
337
BuildClientCredContext(int32_t osAccountId,int64_t requestId,CJson * context,const char ** returnAppId)338 int32_t BuildClientCredContext(int32_t osAccountId, int64_t requestId, CJson *context, const char **returnAppId)
339 {
340 if (context == NULL) {
341 LOGE("input context is null ptr!");
342 return HC_ERR_INVALID_PARAMS;
343 }
344 if (CheckIsCredBind(context)) {
345 return BuildClientCredBindContext(osAccountId, requestId, context, returnAppId);
346 }
347 return BuildClientCredAuthContext(osAccountId, requestId, context, returnAppId);
348 }
349
AddOsAccountIdToContextIfValid(CJson * context)350 static int32_t AddOsAccountIdToContextIfValid(CJson *context)
351 {
352 int32_t osAccountId = ANY_OS_ACCOUNT;
353 (void)GetIntFromJson(context, FIELD_OS_ACCOUNT_ID, &osAccountId);
354 osAccountId = DevAuthGetRealOsAccountLocalId(osAccountId);
355 LOGI("[OsAccountId]: %" LOG_PUB "d", osAccountId);
356 if (osAccountId == INVALID_OS_ACCOUNT) {
357 return HC_ERR_INVALID_PARAMS;
358 }
359 if (!CheckIsForegroundOsAccountId(osAccountId)) {
360 LOGE("This access is not from the foreground user, rejected it.");
361 return HC_ERR_CROSS_USER_ACCESS;
362 }
363 if (!IsOsAccountUnlocked(osAccountId)) {
364 LOGE("Os account is not unlocked!");
365 return HC_ERR_OS_ACCOUNT_NOT_UNLOCKED;
366 }
367 if (AddIntToJson(context, FIELD_OS_ACCOUNT_ID, osAccountId) != HC_SUCCESS) {
368 LOGE("add operationCode to context fail.");
369 return HC_ERR_JSON_ADD;
370 }
371 return HC_SUCCESS;
372 }
373
BuildServerCredBindContext(int64_t requestId,CJson * context,char ** returnPeerUdid,const char ** returnAppId)374 static int32_t BuildServerCredBindContext(int64_t requestId, CJson *context,
375 char **returnPeerUdid, const char **returnAppId)
376 {
377 int32_t res = CheckConfirmationExist(context);
378 if (res != HC_SUCCESS) {
379 return res;
380 }
381 res = AddOsAccountIdToContextIfValid(context);
382 if (res != HC_SUCCESS) {
383 return res;
384 }
385 if (AddBoolToJson(context, FIELD_IS_BIND, true) != HC_SUCCESS) {
386 LOGE("add isBind to context fail.");
387 return HC_ERR_JSON_ADD;
388 }
389 if (AddBoolToJson(context, FIELD_IS_CLIENT, false) != HC_SUCCESS) {
390 LOGE("add isClient to context fail.");
391 return HC_ERR_JSON_ADD;
392 }
393 const char *appId = GetAppIdByContext(context);
394 if (appId == NULL) {
395 LOGE("get appId Fail.");
396 return HC_ERR_JSON_GET;
397 }
398 if (AddBoolToJson(context, FIELD_IS_CRED_AUTH, true) != HC_SUCCESS) {
399 LOGE("add isCredAuth to context fail.");
400 return HC_ERR_JSON_ADD;
401 }
402 if (AddInt64StringToJson(context, FIELD_REQUEST_ID, requestId) != HC_SUCCESS) {
403 LOGE("add requestId to context fail.");
404 return HC_ERR_JSON_ADD;
405 }
406 if (AddStringToJson(context, FIELD_APP_ID, appId) != HC_SUCCESS) {
407 LOGE("add appId to context fail.");
408 return HC_ERR_JSON_ADD;
409 }
410 if (AddAuthIdToCredContext(context)) {
411 return HC_ERR_JSON_ADD;
412 }
413 *returnAppId = appId;
414 return AddChannelInfoToContext(SERVICE_CHANNEL, DEFAULT_CHANNEL_ID, context);
415 }
416
BuildServerCredAuthContext(int64_t requestId,CJson * context,char ** returnPeerUdid,const char ** returnAppId)417 static int32_t BuildServerCredAuthContext(int64_t requestId, CJson *context,
418 char **returnPeerUdid, const char **returnAppId)
419 {
420 int32_t res = CheckConfirmationExist(context);
421 if (res != HC_SUCCESS) {
422 return res;
423 }
424 res = AddOsAccountIdToContextIfValid(context);
425 if (res != HC_SUCCESS) {
426 return res;
427 }
428 int32_t osAccountId = ANY_OS_ACCOUNT;
429 (void)GetIntFromJson(context, FIELD_OS_ACCOUNT_ID, &osAccountId);
430 if (AddBoolToJson(context, FIELD_IS_BIND, false) != HC_SUCCESS) {
431 LOGE("add isBind to context fail.");
432 return HC_ERR_JSON_ADD;
433 }
434 if (AddBoolToJson(context, FIELD_IS_CLIENT, false) != HC_SUCCESS) {
435 LOGE("add isClient to context fail.");
436 return HC_ERR_JSON_ADD;
437 }
438 if (((res = QueryAndAddSelfCredToContext(osAccountId, context)) != HC_SUCCESS ||
439 (res = AddCredIdToContextIfNeeded(context) != HC_SUCCESS))) {
440 return res;
441 }
442 const char *appId = GetAppIdByContext(context);
443 if (appId == NULL) {
444 LOGE("get appId Fail.");
445 return HC_ERR_JSON_GET;
446 }
447 if (AddBoolToJson(context, FIELD_IS_CRED_AUTH, true) != HC_SUCCESS) {
448 LOGE("add isCredAuth to context fail.");
449 return HC_ERR_JSON_ADD;
450 }
451 if (AddInt64StringToJson(context, FIELD_REQUEST_ID, requestId) != HC_SUCCESS) {
452 LOGE("add requestId to context fail.");
453 return HC_ERR_JSON_ADD;
454 }
455 if (AddStringToJson(context, FIELD_APP_ID, appId) != HC_SUCCESS) {
456 LOGE("add appId to context fail.");
457 return HC_ERR_JSON_ADD;
458 }
459 *returnAppId = appId;
460 return AddChannelInfoToContext(SERVICE_CHANNEL, DEFAULT_CHANNEL_ID, context);
461 }
462
BuildServerCredContext(int64_t requestId,CJson * context,char ** returnPeerUdid,const char ** returnAppId)463 int32_t BuildServerCredContext(int64_t requestId, CJson *context, char **returnPeerUdid, const char **returnAppId)
464 {
465 if (context == NULL) {
466 LOGE("input context is null ptr!");
467 return HC_ERR_INVALID_PARAMS;
468 }
469 if (CheckIsCredBind(context)) {
470 return BuildServerCredBindContext(requestId, context, returnPeerUdid, returnAppId);
471 }
472 return BuildServerCredAuthContext(requestId, context, returnPeerUdid, returnAppId);
473 }
474