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 "mk_agree.h"
17
18 #include "common_defs.h"
19 #include "device_auth.h"
20 #include "device_auth_defines.h"
21 #include "hc_log.h"
22 #include "mk_agree_task.h"
23
24 #define FIELD_EVENT "event"
25 #define FIELD_ERR_CODE "errCode"
26
27 typedef enum {
28 START_EVENT = 0,
29 START_MK_AGREE_REQUEST_EVENT,
30 SEND_MK_AGREE_RESPONSE_EVENT,
31 FAIL_EVENT,
32 UNKNOWN_EVENT
33 } EventEnum;
34
35 typedef enum {
36 CLIENT_INIT_STATE = 0,
37 SERVER_WAIT_REQUEST_STATE,
38 CLIENT_WAIT_RESPONSE_STATE,
39 FINISH_STATE,
40 FAIL_STATE
41 } StateEnum;
42
43 typedef struct {
44 BaseCmd base;
45 MkAgreeTaskBase *task;
46 } MkAgreeCmd;
47
48 typedef struct {
49 int32_t curState;
50 int32_t eventType;
51 int32_t (*stateProcessFunc)(BaseCmd *, const CJson *, CJson **);
52 void (*exceptionHandleFunc)(int32_t, CJson **);
53 int32_t nextState;
54 } CmdStateNode;
55
ProcessMkAgreeError(int32_t errorCode,CJson ** out)56 static void ProcessMkAgreeError(int32_t errorCode, CJson **out)
57 {
58 (void)errorCode;
59 (void)out;
60 }
61
InformPeerError(int32_t errorCode,CJson ** out)62 static void InformPeerError(int32_t errorCode, CJson **out)
63 {
64 CJson *json = CreateJson();
65 if (json == NULL) {
66 LOGE("Failed to create json!");
67 return;
68 }
69 if (AddIntToJson(json, FIELD_EVENT, FAIL_EVENT) != HC_SUCCESS) {
70 LOGE("Failed to add event!");
71 FreeJson(json);
72 return;
73 }
74 if (AddIntToJson(json, FIELD_ERR_CODE, errorCode) != HC_SUCCESS) {
75 LOGE("Failed to add error code!");
76 FreeJson(json);
77 return;
78 }
79 *out = json;
80 return;
81 }
82
ThrowException(BaseCmd * cmd,const CJson * in,CJson ** out)83 static int32_t ThrowException(BaseCmd *cmd, const CJson *in, CJson **out)
84 {
85 LOGI("throw exception.");
86 (void)cmd;
87 (void)in;
88 (void)out;
89 return HC_ERR_UNSUPPORTED_OPCODE;
90 }
91
AddEventByState(const BaseCmd * cmd,CJson * sendData)92 static int32_t AddEventByState(const BaseCmd *cmd, CJson *sendData)
93 {
94 if (cmd->curState == CLIENT_INIT_STATE) {
95 return AddIntToJson(sendData, FIELD_EVENT, START_MK_AGREE_REQUEST_EVENT);
96 } else if (cmd->curState == SERVER_WAIT_REQUEST_STATE) {
97 return AddIntToJson(sendData, FIELD_EVENT, SEND_MK_AGREE_RESPONSE_EVENT);
98 } else {
99 LOGE("Invalid state!");
100 return HC_ERR_INVALID_PARAMS;
101 }
102 }
103
ProcessMkAgreeTask(BaseCmd * cmd,const CJson * in,CJson ** out)104 static int32_t ProcessMkAgreeTask(BaseCmd *cmd, const CJson *in, CJson **out)
105 {
106 LOGI("process mk agree task, current state is: %d", cmd->curState);
107 CJson *sendData = CreateJson();
108 if (sendData == NULL) {
109 LOGE("Failed to create sendData!");
110 return HC_ERR_JSON_CREATE;
111 }
112 MkAgreeCmd *impl = (MkAgreeCmd *)cmd;
113 int32_t res = impl->task->process(impl->task, in, sendData);
114 if (res != HC_SUCCESS) {
115 LOGE("Failed to process mk agree task!");
116 FreeJson(sendData);
117 return res;
118 }
119 if (cmd->curState == CLIENT_WAIT_RESPONSE_STATE) {
120 FreeJson(sendData);
121 return HC_SUCCESS;
122 }
123 CJson *sendToPeer = GetObjFromJson(sendData, FIELD_SEND_TO_PEER);
124 if (sendToPeer == NULL) {
125 LOGE("sendToPeer is null!");
126 FreeJson(sendData);
127 return HC_ERR_JSON_GET;
128 }
129 *out = DuplicateJson(sendToPeer);
130 FreeJson(sendData);
131 if (*out == NULL) {
132 LOGE("Failed to duplicate send data!");
133 return HC_ERR_JSON_FAIL;
134 }
135 res = AddEventByState(cmd, *out);
136 if (res != HC_SUCCESS) {
137 LOGE("Failed to add event!");
138 FreeJson(*out);
139 *out = NULL;
140 return res;
141 }
142 return HC_SUCCESS;
143 }
144
145 static const CmdStateNode STATE_MACHINE[] = {
146 { CLIENT_INIT_STATE, START_EVENT, ProcessMkAgreeTask, InformPeerError, CLIENT_WAIT_RESPONSE_STATE },
147 { SERVER_WAIT_REQUEST_STATE, START_MK_AGREE_REQUEST_EVENT, ProcessMkAgreeTask, InformPeerError, FINISH_STATE },
148 { SERVER_WAIT_REQUEST_STATE, FAIL_EVENT, ThrowException, ProcessMkAgreeError, FAIL_STATE },
149 { CLIENT_WAIT_RESPONSE_STATE, SEND_MK_AGREE_RESPONSE_EVENT, ProcessMkAgreeTask, ProcessMkAgreeError, FINISH_STATE },
150 { CLIENT_WAIT_RESPONSE_STATE, FAIL_EVENT, ThrowException, ProcessMkAgreeError, FAIL_STATE },
151 };
152
DecodeEvent(const CJson * in)153 static int32_t DecodeEvent(const CJson *in)
154 {
155 if (in == NULL) {
156 LOGI("start event.");
157 return START_EVENT;
158 }
159 int32_t event;
160 if (GetIntFromJson(in, FIELD_EVENT, &event) != HC_SUCCESS) {
161 LOGE("Failed to get event from received msg!");
162 return UNKNOWN_EVENT;
163 }
164 if (event < START_EVENT || event > UNKNOWN_EVENT) {
165 LOGE("Invalid event!");
166 return UNKNOWN_EVENT;
167 }
168 return event;
169 }
170
SwitchState(BaseCmd * cmd,const CJson * in,CJson ** out,CmdState * returnState)171 static int32_t SwitchState(BaseCmd *cmd, const CJson *in, CJson **out, CmdState *returnState)
172 {
173 int32_t eventType = DecodeEvent(in);
174 for (uint32_t i = 0; i < sizeof(STATE_MACHINE) / sizeof(STATE_MACHINE[0]); i++) {
175 if ((STATE_MACHINE[i].curState == cmd->curState) && (STATE_MACHINE[i].eventType == eventType)) {
176 int32_t res = STATE_MACHINE[i].stateProcessFunc(cmd, in, out);
177 if (res != HC_SUCCESS) {
178 STATE_MACHINE[i].exceptionHandleFunc(res, out);
179 cmd->curState = cmd->failState;
180 return res;
181 }
182 LOGI("event: %d, curState: %d, nextState: %d", eventType, cmd->curState, STATE_MACHINE[i].nextState);
183 cmd->curState = STATE_MACHINE[i].nextState;
184 *returnState = (cmd->curState == cmd->finishState) ? CMD_STATE_FINISH : CMD_STATE_CONTINUE;
185 return HC_SUCCESS;
186 }
187 }
188 LOGI("Unsupported event type. Ignore process. [Event]: %d, [CurState]: %d", eventType, cmd->curState);
189 return HC_SUCCESS;
190 }
191
StartMkAgreeCmd(BaseCmd * cmd,CJson ** out)192 static int32_t StartMkAgreeCmd(BaseCmd *cmd, CJson **out)
193 {
194 if ((cmd == NULL) || (out == NULL)) {
195 LOGE("Invalid params!");
196 return HC_ERR_INVALID_PARAMS;
197 }
198 if (cmd->curState != cmd->beginState) {
199 LOGE("Invalid state!");
200 return HC_ERR_UNSUPPORTED_OPCODE;
201 }
202 CmdState state;
203 return SwitchState(cmd, NULL, out, &state);
204 }
205
ProcessMkAgreeCmd(BaseCmd * cmd,const CJson * in,CJson ** out,CmdState * returnState)206 static int32_t ProcessMkAgreeCmd(BaseCmd *cmd, const CJson *in, CJson **out, CmdState *returnState)
207 {
208 if ((cmd == NULL) || (in == NULL) || (out == NULL) || (returnState == NULL)) {
209 LOGE("Invalid params.");
210 return HC_ERR_INVALID_PARAMS;
211 }
212 if ((cmd->curState == cmd->finishState) || (cmd->curState == cmd->failState)) {
213 LOGE("Invalid state!");
214 return HC_ERR_UNSUPPORTED_OPCODE;
215 }
216 return SwitchState(cmd, in, out, returnState);
217 }
218
DestroyMkAgreeCmd(BaseCmd * cmd)219 static void DestroyMkAgreeCmd(BaseCmd *cmd)
220 {
221 if (cmd == NULL) {
222 LOGE("cmd is null.");
223 return;
224 }
225 MkAgreeCmd *impl = (MkAgreeCmd *)cmd;
226 if (impl->task != NULL) {
227 impl->task->destroy(impl->task);
228 }
229 HcFree(impl);
230 }
231
InitMkAgreeTask(MkAgreeCmd * cmd,const MkAgreeParams * params,bool isClient)232 static int32_t InitMkAgreeTask(MkAgreeCmd *cmd, const MkAgreeParams *params, bool isClient)
233 {
234 CJson *json = CreateJson();
235 if (json == NULL) {
236 LOGE("Failed to create json param!");
237 return HC_ERR_JSON_CREATE;
238 }
239 if (AddBoolToJson(json, FIELD_IS_CLIENT, isClient) != HC_SUCCESS) {
240 LOGE("Failed to add isClient!");
241 FreeJson(json);
242 return HC_ERR_JSON_ADD;
243 }
244 if (AddIntToJson(json, FIELD_OS_ACCOUNT_ID, params->osAccountId) != HC_SUCCESS) {
245 LOGE("Failed to add osAccountId!");
246 FreeJson(json);
247 return HC_ERR_JSON_ADD;
248 }
249 if (AddStringToJson(json, FIELD_REAL_INFO, params->peerInfo) != HC_SUCCESS) {
250 LOGE("Failed to add peerInfo!");
251 FreeJson(json);
252 return HC_ERR_JSON_ADD;
253 }
254 if (AddStringToJson(json, FIELD_INDEX_KEY, params->pdidIndex) != HC_SUCCESS) {
255 LOGE("Failed to add pdidIndex!");
256 FreeJson(json);
257 return HC_ERR_JSON_ADD;
258 }
259 int32_t res = CreateMkAgreeTask(TASK_TYPE_PAKE, json, &cmd->task);
260 FreeJson(json);
261 if (res != HC_SUCCESS) {
262 LOGE("Failed to create mk agree task!");
263 }
264 return res;
265 }
266
InitMkAgreeCmd(MkAgreeCmd * cmd,const MkAgreeParams * params,bool isClient,int32_t strategy)267 static int32_t InitMkAgreeCmd(MkAgreeCmd *cmd, const MkAgreeParams *params,
268 bool isClient, int32_t strategy)
269 {
270 int32_t res = InitMkAgreeTask(cmd, params, isClient);
271 if (res != HC_SUCCESS) {
272 LOGE("Failed to init mk agree task!");
273 return res;
274 }
275 cmd->base.type = MK_AGREE_CMD_TYPE;
276 cmd->base.strategy = strategy;
277 cmd->base.isCaller = isClient;
278 cmd->base.beginState = isClient ? CLIENT_INIT_STATE : SERVER_WAIT_REQUEST_STATE;
279 cmd->base.finishState = FINISH_STATE;
280 cmd->base.failState = FAIL_STATE;
281 cmd->base.curState = cmd->base.beginState;
282 cmd->base.start = StartMkAgreeCmd;
283 cmd->base.process = ProcessMkAgreeCmd;
284 cmd->base.destroy = DestroyMkAgreeCmd;
285 return HC_SUCCESS;
286 }
287
CreateMkAgreeCmd(const void * baseParams,bool isClient,int32_t strategy)288 BaseCmd *CreateMkAgreeCmd(const void *baseParams, bool isClient, int32_t strategy)
289 {
290 if (baseParams == NULL) {
291 LOGE("Invalid input params!");
292 return NULL;
293 }
294 MkAgreeCmd *cmd = (MkAgreeCmd *)HcMalloc(sizeof(MkAgreeCmd), 0);
295 if (cmd == NULL) {
296 LOGE("Failed to allocate memory for cmd!");
297 return NULL;
298 }
299 const MkAgreeParams *params = (const MkAgreeParams *)baseParams;
300 int32_t res = InitMkAgreeCmd(cmd, params, isClient, strategy);
301 if (res != HC_SUCCESS) {
302 HcFree(cmd);
303 return NULL;
304 }
305 return (BaseCmd *)cmd;
306 }