1 /*
2 * Copyright (C) 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 "compatible_auth_sub_session.h"
17
18 #include "compatible_auth_sub_session_common.h"
19 #include "compatible_auth_sub_session_util.h"
20 #include "dev_auth_module_manager.h"
21 #include "hc_log.h"
22 #include "hc_types.h"
23 #include "hitrace_adapter.h"
24
CheckInputAuthParams(const CJson * authParam)25 static int32_t CheckInputAuthParams(const CJson *authParam)
26 {
27 int32_t keyLen = DEFAULT_RETURN_KEY_LENGTH;
28 (void)GetIntFromJson(authParam, FIELD_KEY_LENGTH, &keyLen);
29 if ((keyLen < MIN_KEY_LENGTH) || (keyLen > MAX_KEY_LENGTH)) {
30 LOGE("The key length is invalid!");
31 return HC_ERR_INVALID_PARAMS;
32 }
33 if (GetStringFromJson(authParam, FIELD_SERVICE_PKG_NAME) == NULL) {
34 LOGE("Failed to get servicePkgName!");
35 return HC_ERR_JSON_GET;
36 }
37 return HC_SUCCESS;
38 }
39
CreateClientAuthSubSessionInner(int32_t osAccountId,CJson * jsonParams,const DeviceAuthCallback * callback,CompatibleBaseSubSession ** session)40 static int32_t CreateClientAuthSubSessionInner(int32_t osAccountId, CJson *jsonParams,
41 const DeviceAuthCallback *callback, CompatibleBaseSubSession **session)
42 {
43 ParamsVecForAuth authParamsVec;
44 CreateAuthParamsList(&authParamsVec);
45 int32_t res = GetAuthParamsVec(osAccountId, jsonParams, &authParamsVec);
46 if (res != HC_SUCCESS) {
47 LOGW("Failed to get auth param list!");
48 DestroyAuthParamsList(&authParamsVec);
49 return res;
50 }
51 if (authParamsVec.size(&authParamsVec) == 0) {
52 LOGE("Empty auth params list!");
53 DestroyAuthParamsList(&authParamsVec);
54 return HC_ERR_NO_CANDIDATE_GROUP;
55 }
56 CompatibleAuthSubSession *subSession = (CompatibleAuthSubSession *)HcMalloc(sizeof(CompatibleAuthSubSession), 0);
57 if (subSession == NULL) {
58 LOGE("Failed to allocate memory for session!");
59 DestroyAuthParamsList(&authParamsVec);
60 return HC_ERR_ALLOC_MEMORY;
61 }
62 subSession->base.type = TYPE_CLIENT_AUTH_SUB_SESSION;
63 subSession->base.callback = callback;
64 subSession->base.appId = GetDuplicatePkgName(jsonParams);
65 subSession->currentIndex = 0;
66 subSession->paramsList = authParamsVec;
67 subSession->base.status = STATUS_INITIAL;
68 *session = (CompatibleBaseSubSession *)subSession;
69
70 return HC_SUCCESS;
71 }
72
CheckAcceptRequest(const CJson * context)73 static int32_t CheckAcceptRequest(const CJson *context)
74 {
75 uint32_t confirmation = REQUEST_REJECTED;
76 (void)GetUnsignedIntFromJson(context, FIELD_CONFIRMATION, &confirmation);
77 if (confirmation != REQUEST_ACCEPTED) {
78 LOGE("The service rejects this request!");
79 return HC_ERR_REQ_REJECTED;
80 }
81 LOGI("The service accepts this request!");
82 return HC_SUCCESS;
83 }
84
GetAuthInfoForServer(CJson * dataFromClient,ParamsVecForAuth * authParamsVec)85 static int32_t GetAuthInfoForServer(CJson *dataFromClient, ParamsVecForAuth *authParamsVec)
86 {
87 int32_t res = CheckAcceptRequest(dataFromClient);
88 if (res != HC_SUCCESS) {
89 return res;
90 }
91 int32_t authForm = AUTH_FORM_INVALID_TYPE;
92 if (GetIntFromJson(dataFromClient, FIELD_AUTH_FORM, &authForm) != HC_SUCCESS) {
93 LOGE("Failed to get auth form!");
94 return HC_ERR_JSON_GET;
95 }
96 int32_t groupAuthType = GetAuthType(authForm);
97 BaseGroupAuth *groupAuthHandle = GetGroupAuth(groupAuthType);
98 if (groupAuthHandle == NULL) {
99 LOGE("Failed to get group auth handle!");
100 return HC_ERR_NOT_SUPPORT;
101 }
102 return groupAuthHandle->getAuthParamsVecForServer(dataFromClient, authParamsVec);
103 }
104
IsPeerGroupAuthError(const CJson * in)105 static bool IsPeerGroupAuthError(const CJson *in)
106 {
107 int32_t groupErrMsg = 0;
108 if (GetIntFromJson(in, FIELD_GROUP_ERROR_MSG, &groupErrMsg) != HC_SUCCESS) {
109 return false;
110 }
111 return true;
112 }
113
HandlePeerAuthError(CompatibleAuthSubSession * session)114 static int32_t HandlePeerAuthError(CompatibleAuthSubSession *session)
115 {
116 if (AuthOnNextGroupIfExist(session) != HC_SUCCESS) {
117 LOGE("Failed to auth on next group!");
118 return HC_ERR_PEER_ERROR;
119 }
120 return HC_SUCCESS;
121 }
122
ProcessClientAuthTaskInner(CompatibleAuthSubSession * session,int32_t moduleType,CJson * in,CJson * out,int32_t * status)123 static int32_t ProcessClientAuthTaskInner(CompatibleAuthSubSession *session, int32_t moduleType, CJson *in,
124 CJson *out, int32_t *status)
125 {
126 CJson *paramInSession = (session->paramsList).get(&(session->paramsList), session->currentIndex);
127 if (paramInSession == NULL) {
128 LOGE("Failed to get param in session!");
129 return HC_ERR_NULL_PTR;
130 }
131 DEV_AUTH_START_TRACE(TRACE_TAG_PROCESS_AUTH_TASK);
132 int32_t res = ProcessTask(session->base.curTaskId, in, out, status, moduleType);
133 DEV_AUTH_FINISH_TRACE();
134 DeleteItemFromJson(in, FIELD_PAYLOAD);
135 if (res != HC_SUCCESS) {
136 LOGW("Failed to process client auth task, try to auth on next group!");
137 DestroyTask(session->base.curTaskId, moduleType);
138 return ProcessClientAuthError(session, out);
139 }
140 return HandleAuthTaskStatus(session, out, *status, false);
141 }
142
ProcessDeviceLevel(const CJson * receiveData,CJson * authParam)143 static void ProcessDeviceLevel(const CJson *receiveData, CJson *authParam)
144 {
145 bool receiveLevel = false;
146 bool authLevel = false;
147 (void)GetBoolFromJson(receiveData, FIELD_IS_DEVICE_LEVEL, &receiveLevel);
148 (void)GetBoolFromJson(authParam, FIELD_IS_DEVICE_LEVEL, &authLevel);
149 if (AddBoolToJson(authParam, FIELD_IS_DEVICE_LEVEL, receiveLevel && authLevel) != HC_SUCCESS) {
150 LOGE("Failed to add device level to auth param!");
151 }
152 }
153
ProcessClientAuthTask(CompatibleAuthSubSession * session,CJson * receivedData,int32_t * status)154 static int32_t ProcessClientAuthTask(CompatibleAuthSubSession *session, CJson *receivedData, int32_t *status)
155 {
156 CJson *paramInSession = (session->paramsList).get(&(session->paramsList), session->currentIndex);
157 if (paramInSession == NULL) {
158 LOGE("Failed to get param in session!");
159 return HC_ERR_NULL_PTR;
160 }
161 ProcessDeviceLevel(receivedData, paramInSession);
162
163 if (IsPeerGroupAuthError(receivedData)) {
164 return HandlePeerAuthError(session);
165 }
166
167 CJson *out = CreateJson();
168 if (out == NULL) {
169 LOGE("Failed to create json for out!");
170 NotifyPeerAuthError(paramInSession, session->base.callback);
171 return HC_ERR_JSON_CREATE;
172 }
173 int32_t res = ProcessClientAuthTaskInner(session, GetAuthModuleType(paramInSession), receivedData, out, status);
174 ClearSensitiveStringInJson(out, FIELD_SESSION_KEY);
175 FreeJson(out);
176 if (res == FINISH) {
177 LOGI("End process client authSession.");
178 }
179 return res;
180 }
181
GenerateClientFirstMsg(CompatibleAuthSubSession * session,CJson * out,CJson ** sendData)182 static int32_t GenerateClientFirstMsg(CompatibleAuthSubSession *session, CJson *out, CJson **sendData)
183 {
184 *sendData = DetachItemFromJson(out, FIELD_SEND_TO_PEER);
185 if (*sendData == NULL) {
186 LOGE("The transmit data to peer is null!");
187 return HC_ERR_JSON_GET;
188 }
189 int32_t res = AddGroupAuthTransmitData(session, true, *sendData);
190 if (res != HC_SUCCESS) {
191 FreeJson(*sendData);
192 *sendData = NULL;
193 }
194 return res;
195 }
196
CreateAndProcessClientAuthTask(CompatibleAuthSubSession * session,CJson ** sendData,int32_t * status)197 static int32_t CreateAndProcessClientAuthTask(CompatibleAuthSubSession *session, CJson **sendData, int32_t *status)
198 {
199 CJson *paramInSession = (session->paramsList).get(&(session->paramsList), session->currentIndex);
200 if (paramInSession == NULL) {
201 LOGE("Failed to get param in session!");
202 return HC_ERR_NULL_PTR;
203 }
204 CJson *out = CreateJson();
205 if (out == NULL) {
206 LOGE("Failed to create json!");
207 return HC_ERR_JSON_CREATE;
208 }
209 int32_t res = CreateAndProcessAuthTask(session, paramInSession, out, status);
210 if (res != HC_SUCCESS) {
211 LOGW("Failed to create and process client auth task, try to auth on next group!");
212 res = ProcessClientAuthError(session, out);
213 FreeJson(out);
214 return res;
215 }
216 res = GenerateClientFirstMsg(session, out, sendData);
217 FreeJson(out);
218 return res;
219 }
220
ProcessServerAuthTaskInner(CompatibleAuthSubSession * session,int32_t moduleType,CJson * in,CJson * out,int32_t * status)221 static int32_t ProcessServerAuthTaskInner(CompatibleAuthSubSession *session, int32_t moduleType,
222 CJson *in, CJson *out, int32_t *status)
223 {
224 CJson *paramInSession = (session->paramsList).get(&(session->paramsList), session->currentIndex);
225 if (paramInSession == NULL) {
226 LOGE("The json data in session is null!");
227 return HC_ERR_NULL_PTR;
228 }
229 DEV_AUTH_START_TRACE(TRACE_TAG_PROCESS_AUTH_TASK);
230 int32_t res = ProcessTask(session->base.curTaskId, in, out, status, moduleType);
231 DEV_AUTH_FINISH_TRACE();
232 DeleteItemFromJson(in, FIELD_PAYLOAD);
233 if (res != HC_SUCCESS) {
234 ProcessServerAuthError(session, out);
235 return res;
236 }
237 return HandleAuthTaskStatus(session, out, *status, false);
238 }
239
ProcessServerAuthTask(CompatibleAuthSubSession * session,CJson * receivedData,int32_t * status)240 static int32_t ProcessServerAuthTask(CompatibleAuthSubSession *session, CJson *receivedData, int32_t *status)
241 {
242 CJson *paramInSession = (session->paramsList).get(&(session->paramsList), session->currentIndex);
243 if (paramInSession == NULL) {
244 LOGE("Failed to get param in session!");
245 return HC_ERR_NULL_PTR;
246 }
247 if (IsPeerGroupAuthError(receivedData)) {
248 LOGE("Peer group auth error happened, stop the server auth session!");
249 return HC_ERR_PEER_ERROR;
250 }
251 CJson *out = CreateJson();
252 if (out == NULL) {
253 LOGE("Failed to create json for out!");
254 NotifyPeerAuthError(paramInSession, session->base.callback);
255 return HC_ERR_JSON_CREATE;
256 }
257 int32_t moduleType = GetAuthModuleType(paramInSession);
258 int32_t res = ProcessServerAuthTaskInner(session, moduleType, receivedData, out, status);
259 FreeJson(out);
260 if (res == FINISH) {
261 LOGI("finish process server authSession.");
262 }
263 return res;
264 }
265
CreateAndProcessServerAuthTask(CompatibleAuthSubSession * session,CJson * receivedData,int32_t * status)266 static int32_t CreateAndProcessServerAuthTask(CompatibleAuthSubSession *session, CJson *receivedData, int32_t *status)
267 {
268 CJson *paramInSession = (session->paramsList).get(&(session->paramsList), session->currentIndex);
269 if (paramInSession == NULL) {
270 LOGE("The json data in session is null!");
271 return HC_ERR_NULL_PTR;
272 }
273 ProcessDeviceLevel(receivedData, paramInSession);
274 CJson *out = CreateJson();
275 if (out == NULL) {
276 LOGE("Failed to create json!");
277 NotifyPeerAuthError(receivedData, session->base.callback);
278 return HC_ERR_JSON_CREATE;
279 }
280 int32_t res = CreateAndProcessAuthTask(session, paramInSession, out, status);
281 if (res != HC_SUCCESS) {
282 ProcessServerAuthError(session, out);
283 FreeJson(out);
284 return res;
285 }
286 res = HandleAuthTaskStatus(session, out, *status, false);
287 FreeJson(out);
288 return res;
289 }
290
CreateClientAuthSubSession(CJson * jsonParams,const DeviceAuthCallback * callback,CompatibleBaseSubSession ** session)291 int32_t CreateClientAuthSubSession(CJson *jsonParams, const DeviceAuthCallback *callback,
292 CompatibleBaseSubSession **session)
293 {
294 int32_t res = CheckInputAuthParams(jsonParams);
295 if (res != HC_SUCCESS) {
296 LOGE("Invalid input params!");
297 return res;
298 }
299 if (AddIntToJson(jsonParams, FIELD_OPERATION_CODE, AUTHENTICATE) != HC_SUCCESS) {
300 LOGE("Failed to add operation code to json!");
301 return HC_ERR_JSON_ADD;
302 }
303 int32_t osAccountId = INVALID_OS_ACCOUNT;
304 if (GetIntFromJson(jsonParams, FIELD_OS_ACCOUNT_ID, &osAccountId) != HC_SUCCESS) {
305 LOGE("Failed to get osAccountId from params!");
306 return HC_ERR_JSON_GET;
307 }
308 return CreateClientAuthSubSessionInner(osAccountId, jsonParams, callback, session);
309 }
310
CreateServerAuthSubSession(CJson * jsonParams,const DeviceAuthCallback * callback,CompatibleBaseSubSession ** session)311 int32_t CreateServerAuthSubSession(CJson *jsonParams, const DeviceAuthCallback *callback,
312 CompatibleBaseSubSession **session)
313 {
314 ParamsVecForAuth authVec;
315 CreateAuthParamsList(&authVec);
316 int32_t res = GetAuthInfoForServer(jsonParams, &authVec);
317 ClearCachedData(jsonParams);
318 if (res != HC_SUCCESS) {
319 LOGE("Failed to add auth param for server!");
320 DestroyAuthParamsList(&authVec);
321 NotifyPeerAuthError(jsonParams, callback);
322 return res;
323 }
324 if (authVec.size(&authVec) == 0) {
325 LOGE("Empty auth params list!");
326 DestroyAuthParamsList(&authVec);
327 NotifyPeerAuthError(jsonParams, callback);
328 return HC_ERR_NO_CANDIDATE_GROUP;
329 }
330 CompatibleAuthSubSession *subSession = (CompatibleAuthSubSession *)HcMalloc(sizeof(CompatibleAuthSubSession), 0);
331 if (subSession == NULL) {
332 LOGE("Failed to malloc memory for session!");
333 DestroyAuthParamsList(&authVec);
334 NotifyPeerAuthError(jsonParams, callback);
335 return HC_ERR_ALLOC_MEMORY;
336 }
337
338 subSession->base.type = TYPE_SERVER_AUTH_SUB_SESSION;
339 subSession->base.callback = callback;
340 subSession->base.appId = GetDuplicatePkgName(jsonParams);
341 subSession->currentIndex = 0;
342 subSession->paramsList = authVec;
343 subSession->base.status = STATUS_INITIAL;
344 *session = (CompatibleBaseSubSession *)subSession;
345
346 return HC_SUCCESS;
347 }
348
ProcessClientAuthSubSession(CompatibleBaseSubSession * session,CJson * in,CJson ** out,int32_t * status)349 int32_t ProcessClientAuthSubSession(CompatibleBaseSubSession *session, CJson *in, CJson **out, int32_t *status)
350 {
351 CompatibleAuthSubSession *subSession = (CompatibleAuthSubSession *)session;
352 if (session->status == STATUS_PROCESSING) {
353 return ProcessClientAuthTask(subSession, in, status);
354 } else {
355 session->status = STATUS_PROCESSING;
356 return CreateAndProcessClientAuthTask(subSession, out, status);
357 }
358 }
359
ProcessServerAuthSubSession(CompatibleBaseSubSession * session,CJson * in,int32_t * status)360 int32_t ProcessServerAuthSubSession(CompatibleBaseSubSession *session, CJson *in, int32_t *status)
361 {
362 CompatibleAuthSubSession *subSession = (CompatibleAuthSubSession *)session;
363 if (session->status == STATUS_PROCESSING) {
364 return ProcessServerAuthTask(subSession, in, status);
365 } else {
366 session->status = STATUS_PROCESSING;
367 return CreateAndProcessServerAuthTask(subSession, in, status);
368 }
369 }
370
DestroyCompatibleAuthSubSession(CompatibleBaseSubSession * session)371 void DestroyCompatibleAuthSubSession(CompatibleBaseSubSession *session)
372 {
373 if (session == NULL) {
374 return;
375 }
376 CompatibleAuthSubSession *realSession = (CompatibleAuthSubSession *)session;
377 HcFree(realSession->base.appId);
378 realSession->base.appId = NULL;
379 CJson *paramInSession = (realSession->paramsList).get(&(realSession->paramsList), realSession->currentIndex);
380 if (paramInSession == NULL) {
381 LOGE("The json param in session is null!");
382 return;
383 }
384 DestroyTask(realSession->base.curTaskId, GetAuthModuleType(paramInSession));
385
386 uint32_t index;
387 void **paramsData = NULL;
388 FOR_EACH_HC_VECTOR(realSession->paramsList, index, paramsData) {
389 FreeJson((CJson *)*paramsData);
390 }
391 DestroyAuthParamsList(&(realSession->paramsList));
392 HcFree(realSession);
393 }