• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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: %" LOG_PUB "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: %" LOG_PUB "d, curState: %" LOG_PUB "d, nextState: %" LOG_PUB "d", eventType,
183                 cmd->curState, STATE_MACHINE[i].nextState);
184             cmd->curState = STATE_MACHINE[i].nextState;
185             *returnState = (cmd->curState == cmd->finishState) ? CMD_STATE_FINISH : CMD_STATE_CONTINUE;
186             return HC_SUCCESS;
187         }
188     }
189     LOGI("Unsupported event type. Ignore process. [Event]: %" LOG_PUB "d, [CurState]: %" LOG_PUB "d",
190         eventType, cmd->curState);
191     return HC_SUCCESS;
192 }
193 
StartMkAgreeCmd(BaseCmd * cmd,CJson ** out)194 static int32_t StartMkAgreeCmd(BaseCmd *cmd, CJson **out)
195 {
196     if ((cmd == NULL) || (out == NULL)) {
197         LOGE("Invalid params!");
198         return HC_ERR_INVALID_PARAMS;
199     }
200     if (cmd->curState != cmd->beginState) {
201         LOGE("Invalid state!");
202         return HC_ERR_UNSUPPORTED_OPCODE;
203     }
204     CmdState state;
205     return SwitchState(cmd, NULL, out, &state);
206 }
207 
ProcessMkAgreeCmd(BaseCmd * cmd,const CJson * in,CJson ** out,CmdState * returnState)208 static int32_t ProcessMkAgreeCmd(BaseCmd *cmd, const CJson *in, CJson **out, CmdState *returnState)
209 {
210     if ((cmd == NULL) || (in == NULL) || (out == NULL) || (returnState == NULL)) {
211         LOGE("Invalid params.");
212         return HC_ERR_INVALID_PARAMS;
213     }
214     if ((cmd->curState == cmd->finishState) || (cmd->curState == cmd->failState)) {
215         LOGE("Invalid state!");
216         return HC_ERR_UNSUPPORTED_OPCODE;
217     }
218     return SwitchState(cmd, in, out, returnState);
219 }
220 
DestroyMkAgreeCmd(BaseCmd * cmd)221 static void DestroyMkAgreeCmd(BaseCmd *cmd)
222 {
223     if (cmd == NULL) {
224         LOGE("cmd is null.");
225         return;
226     }
227     MkAgreeCmd *impl = (MkAgreeCmd *)cmd;
228     if (impl->task != NULL) {
229         impl->task->destroy(impl->task);
230     }
231     HcFree(impl);
232 }
233 
InitMkAgreeTask(MkAgreeCmd * cmd,const MkAgreeParams * params,bool isClient)234 static int32_t InitMkAgreeTask(MkAgreeCmd *cmd, const MkAgreeParams *params, bool isClient)
235 {
236     CJson *json = CreateJson();
237     if (json == NULL) {
238         LOGE("Failed to create json param!");
239         return HC_ERR_JSON_CREATE;
240     }
241     if (AddBoolToJson(json, FIELD_IS_CLIENT, isClient) != HC_SUCCESS) {
242         LOGE("Failed to add isClient!");
243         FreeJson(json);
244         return HC_ERR_JSON_ADD;
245     }
246     if (AddIntToJson(json, FIELD_OS_ACCOUNT_ID, params->osAccountId) != HC_SUCCESS) {
247         LOGE("Failed to add osAccountId!");
248         FreeJson(json);
249         return HC_ERR_JSON_ADD;
250     }
251     if (AddStringToJson(json, FIELD_REAL_INFO, params->peerInfo) != HC_SUCCESS) {
252         LOGE("Failed to add peerInfo!");
253         FreeJson(json);
254         return HC_ERR_JSON_ADD;
255     }
256     if (AddStringToJson(json, FIELD_INDEX_KEY, params->pdidIndex) != HC_SUCCESS) {
257         LOGE("Failed to add pdidIndex!");
258         FreeJson(json);
259         return HC_ERR_JSON_ADD;
260     }
261     int32_t res = CreateMkAgreeTask(TASK_TYPE_PAKE, json, &cmd->task);
262     FreeJson(json);
263     if (res != HC_SUCCESS) {
264         LOGE("Failed to create mk agree task!");
265     }
266     return res;
267 }
268 
InitMkAgreeCmd(MkAgreeCmd * cmd,const MkAgreeParams * params,bool isClient,int32_t strategy)269 static int32_t InitMkAgreeCmd(MkAgreeCmd *cmd, const MkAgreeParams *params,
270     bool isClient, int32_t strategy)
271 {
272     int32_t res = InitMkAgreeTask(cmd, params, isClient);
273     if (res != HC_SUCCESS) {
274         LOGE("Failed to init mk agree task!");
275         return res;
276     }
277     cmd->base.type = MK_AGREE_CMD_TYPE;
278     cmd->base.strategy = strategy;
279     cmd->base.isCaller = isClient;
280     cmd->base.beginState = isClient ? CLIENT_INIT_STATE : SERVER_WAIT_REQUEST_STATE;
281     cmd->base.finishState = FINISH_STATE;
282     cmd->base.failState = FAIL_STATE;
283     cmd->base.curState = cmd->base.beginState;
284     cmd->base.start = StartMkAgreeCmd;
285     cmd->base.process = ProcessMkAgreeCmd;
286     cmd->base.destroy = DestroyMkAgreeCmd;
287     return HC_SUCCESS;
288 }
289 
CreateMkAgreeCmd(const void * baseParams,bool isClient,int32_t strategy)290 BaseCmd *CreateMkAgreeCmd(const void *baseParams, bool isClient, int32_t strategy)
291 {
292     if (baseParams == NULL) {
293         LOGE("Invalid input params!");
294         return NULL;
295     }
296     MkAgreeCmd *cmd = (MkAgreeCmd *)HcMalloc(sizeof(MkAgreeCmd), 0);
297     if (cmd == NULL) {
298         LOGE("Failed to allocate memory for cmd!");
299         return NULL;
300     }
301     const MkAgreeParams *params = (const MkAgreeParams *)baseParams;
302     int32_t res = InitMkAgreeCmd(cmd, params, isClient, strategy);
303     if (res != HC_SUCCESS) {
304         HcFree(cmd);
305         return NULL;
306     }
307     return (BaseCmd *)cmd;
308 }