1 /*
2 * Copyright (C) 2022 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 "account_task_main.h"
17 #include "alg_defs.h"
18 #include "alg_loader.h"
19 #include "common_defs.h"
20 #include "device_auth.h"
21 #include "device_auth_defines.h"
22 #include "clib_error.h"
23 #include "hc_log.h"
24 #include "json_utils.h"
25 #include "account_version_util.h"
26
AccountSendErrMsgToSelf(CJson * out,int32_t errCode)27 static void AccountSendErrMsgToSelf(CJson *out, int32_t errCode)
28 {
29 CJson *sendToSelf = CreateJson();
30 if (sendToSelf == NULL) {
31 LOGE("Create sendToSelf json failed.");
32 return;
33 }
34 if (AddIntToJson(sendToSelf, FIELD_ERROR_CODE, errCode) != CLIB_SUCCESS) {
35 LOGE("Add errCode to self json failed.");
36 FreeJson(sendToSelf);
37 return;
38 }
39 if (AddObjToJson(out, FIELD_SEND_TO_SELF, sendToSelf) != CLIB_SUCCESS) {
40 LOGE("Add sendToSelf obj to out json failed.");
41 FreeJson(sendToSelf);
42 return;
43 }
44 FreeJson(sendToSelf);
45 }
46
AccountSendErrMsgToOut(CJson * out,int32_t opCode,int32_t errCode)47 static void AccountSendErrMsgToOut(CJson *out, int32_t opCode, int32_t errCode)
48 {
49 CJson *sendToSelf = CreateJson();
50 if (sendToSelf == NULL) {
51 LOGE("Create sendToSelf json failed.");
52 return;
53 }
54 CJson *sendToPeer = CreateJson();
55 if (sendToPeer == NULL) {
56 LOGE("Create sendToPeer json failed.");
57 FreeJson(sendToSelf);
58 return;
59 }
60 if (opCode == OP_BIND) {
61 if (AddIntToJson(sendToPeer, FIELD_MESSAGE, ERR_MSG) != CLIB_SUCCESS) {
62 LOGE("Failed to add error message to json for bind.");
63 goto CLEAN_UP;
64 }
65 } else {
66 if (AddIntToJson(sendToPeer, FIELD_STEP, ERR_MSG) != CLIB_SUCCESS) {
67 LOGE("Failed to add error message to json for auth.");
68 goto CLEAN_UP;
69 }
70 }
71 if (AddIntToJson(sendToPeer, FIELD_ERROR_CODE, errCode) != CLIB_SUCCESS) {
72 LOGE("Add errCode to json failed.");
73 goto CLEAN_UP;
74 }
75 if (AddIntToJson(sendToSelf, FIELD_AUTH_FORM, ACCOUNT_MODULE) != CLIB_SUCCESS) {
76 LOGE("Add auth form to json failed.");
77 goto CLEAN_UP;
78 }
79 if (AddObjToJson(out, FIELD_SEND_TO_PEER, sendToPeer) != CLIB_SUCCESS) {
80 LOGE("Add sendToPeer to json failed.");
81 goto CLEAN_UP;
82 }
83 if (AddObjToJson(out, FIELD_SEND_TO_SELF, sendToSelf) != CLIB_SUCCESS) {
84 LOGE("Add sendToSelf to json failed.");
85 goto CLEAN_UP;
86 }
87
88 CLEAN_UP:
89 FreeJson(sendToPeer);
90 FreeJson(sendToSelf);
91 return;
92 }
93
DestroyTaskT(AccountTask * task)94 static void DestroyTaskT(AccountTask *task)
95 {
96 if (task == NULL) {
97 return;
98 }
99 if (task->subTask != NULL) {
100 task->subTask->destroyTask(task->subTask);
101 }
102 HcFree(task);
103 }
104
IsPeerErrMessage(const CJson * in)105 static bool IsPeerErrMessage(const CJson *in)
106 {
107 int32_t res = 0;
108 int32_t message = 0;
109 if ((GetIntFromJson(in, FIELD_MESSAGE, &message) != CLIB_SUCCESS) &&
110 (GetIntFromJson(in, FIELD_STEP, &message) != CLIB_SUCCESS)) {
111 LOGD("There is no message code."); // The first message of the client has no message code
112 return false;
113 }
114 if (message != ERR_MSG) {
115 return false;
116 }
117
118 if (GetIntFromJson(in, FIELD_ERROR_CODE, &res) != CLIB_SUCCESS) {
119 LOGE("Get peer error code failed.");
120 }
121 LOGE("Receive error message from peer, errCode: %x.", res);
122 return true;
123 }
124
MapSubTaskTypeToOpCode(AccountTaskType subTaskType)125 static int32_t MapSubTaskTypeToOpCode(AccountTaskType subTaskType)
126 {
127 if (subTaskType >= TASK_TYPE_PAKE_V2_AUTH_CLIENT && subTaskType <= TASK_TYPE_ISO_AUTH_SERVER) {
128 return AUTHENTICATE;
129 }
130 return CODE_NULL;
131 }
132
ProcessTaskT(AccountTask * task,const CJson * in,CJson * out,int32_t * status)133 static int32_t ProcessTaskT(AccountTask *task, const CJson *in, CJson *out, int32_t *status)
134 {
135 if (IsPeerErrMessage(in)) {
136 AccountSendErrMsgToSelf(out, HC_ERR_PEER_ERROR);
137 return HC_ERR_PEER_ERROR;
138 }
139 int32_t res = task->subTask->process(task->subTask, in, out, status);
140 if (res != HC_SUCCESS) {
141 LOGE("Process subTask failed, res: %x.", res);
142 int32_t operationCode = MapSubTaskTypeToOpCode(task->subTask->getTaskType());
143 AccountSendErrMsgToOut(out, operationCode, res);
144 }
145 return res;
146 }
147
NegotiateAndCreateSubTask(AccountTask * task,const CJson * in,CJson * out)148 static int32_t NegotiateAndCreateSubTask(AccountTask *task, const CJson *in, CJson *out)
149 {
150 int32_t operationCode = 0;
151 int32_t credentialType = INVALID_CRED;
152 if (GetIntFromJson(in, FIELD_OPERATION_CODE, &operationCode) != CLIB_SUCCESS) {
153 LOGE("Get operationCode from json failed.");
154 return HC_ERR_JSON_GET;
155 }
156 if (GetIntFromJson(in, FIELD_CREDENTIAL_TYPE, &credentialType) != CLIB_SUCCESS) {
157 LOGE("Failed to get credential type from input data.");
158 return HC_ERR_JSON_GET;
159 }
160 const AccountVersionInfo *verInfo = GetNegotiatedVersionInfo(operationCode, credentialType);
161 if (verInfo == NULL) {
162 LOGE("Get Negotiated versionInfo failed.");
163 return HC_ERR_UNSUPPORTED_VERSION;
164 }
165 task->subTask = verInfo->createTask(in, out, verInfo);
166 if (task->subTask == NULL) {
167 LOGE("Create sub task failed.");
168 return HC_ERR_ALLOC_MEMORY;
169 }
170 task->versionStatus = VERSION_CONFIRMED;
171 return HC_SUCCESS;
172 }
173
AccountSendCreateError(const CJson * in,CJson * out,int32_t errCode)174 static void AccountSendCreateError(const CJson *in, CJson *out, int32_t errCode)
175 {
176 bool isClient = false;
177 if (GetBoolFromJson(in, FIELD_IS_CLIENT, &isClient) != CLIB_SUCCESS) {
178 LOGE("Get isClient from json failed.");
179 }
180 if (isClient) {
181 AccountSendErrMsgToSelf(out, errCode);
182 return;
183 }
184 int32_t operationCode = CODE_NULL;
185 if (GetIntFromJson(in, FIELD_OPERATION_CODE, &operationCode) != CLIB_SUCCESS) {
186 LOGE("Get operationCode from json failed.");
187 } else {
188 AccountSendErrMsgToOut(out, operationCode, errCode);
189 }
190 }
191
CreateAccountTaskT(int32_t * taskId,const CJson * in,CJson * out)192 AccountTask *CreateAccountTaskT(int32_t *taskId, const CJson *in, CJson *out)
193 {
194 int32_t res;
195 AccountTask *task = (AccountTask *)HcMalloc(sizeof(AccountTask), 0);
196 if (task == NULL) {
197 LOGE("Malloc for account related task failed.");
198 res = HC_ERR_ALLOC_MEMORY;
199 goto ERR;
200 }
201 task->destroyTask = DestroyTaskT;
202 task->processTask = ProcessTaskT;
203 task->versionStatus = VERSION_INITIAL;
204 Uint8Buff taskIdBuf = { (uint8_t *)taskId, sizeof(int32_t) };
205 res = GetLoaderInstance()->generateRandom(&taskIdBuf);
206 if (res != HC_SUCCESS) {
207 LOGE("Generate taskId failed, res: %d.", res);
208 goto ERR;
209 }
210 task->taskId = *taskId;
211 res = NegotiateAndCreateSubTask(task, in, out);
212 if (res != HC_SUCCESS) {
213 LOGE("NegotiateAndCreateSubTask failed, res: %d.", res);
214 goto ERR;
215 }
216 return task;
217 ERR:
218 AccountSendCreateError(in, out, res);
219 DestroyTaskT(task);
220 return NULL;
221 }
222