1 /*
2 * Copyright (C) 2021 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 "pake_v1_client_protocol_task.h"
17 #include "das_task_common.h"
18 #include "hc_log.h"
19 #include "hc_types.h"
20 #include "pake_message_util.h"
21 #include "pake_v1_protocol_common.h"
22 #include "pake_v1_protocol_task_common.h"
23 #include "pake_task_common.h"
24
25 enum {
26 TASK_STATUS_CLIENT_PAKE_BEGIN = 0,
27 TASK_STATUS_CLIENT_PAKE_REQUEST,
28 TASK_STATUS_CLIENT_PAKE_CONFIRM,
29 TASK_STATUS_CLIENT_PAKE_VERIFY_CONFIRM,
30 };
31
GetTaskType(void)32 static CurTaskType GetTaskType(void)
33 {
34 return TASK_TYPE_PAKE_V1_PROTOCOL;
35 }
36
DestroyPakeV1ProtocolClientTask(struct AsyBaseCurTaskT * task)37 static void DestroyPakeV1ProtocolClientTask(struct AsyBaseCurTaskT *task)
38 {
39 HcFree(task);
40 }
41
PakeRequest(AsyBaseCurTask * task,PakeParams * params,CJson * out,int * status)42 static int PakeRequest(AsyBaseCurTask *task, PakeParams *params, CJson *out, int *status)
43 {
44 if (task->taskStatus != TASK_STATUS_CLIENT_PAKE_BEGIN) {
45 LOGI("The message is repeated, ignore it, status: %d", task->taskStatus);
46 *status = IGNORE_MSG;
47 return HC_SUCCESS;
48 }
49
50 int res = ConstructOutJson(params, out);
51 if (res != HC_SUCCESS) {
52 LOGE("ConstructOutJson failed, res: %d.", res);
53 return res;
54 }
55 CJson *payload = GetObjFromJson(out, FIELD_PAYLOAD);
56 if (payload == NULL) {
57 LOGE("Get payload from json failed.");
58 return HC_ERR_JSON_GET;
59 }
60 res = PackagePakeRequestData(params, payload);
61 if (res != HC_SUCCESS) {
62 LOGE("PackagePakeRequestData failed, res: %d.", res);
63 return res;
64 }
65 // package differentiated data
66 if (params->opCode == AUTHENTICATE || params->opCode == OP_UNBIND) {
67 res = AddByteToJson(payload, FIELD_PEER_AUTH_ID, params->baseParams.idSelf.val,
68 params->baseParams.idSelf.length);
69 if (res != HC_SUCCESS) {
70 LOGE("Add idSelf failed, res: %d.", res);
71 return res;
72 }
73 }
74 if (params->opCode == AUTHENTICATE || params->opCode == OP_UNBIND || params->opCode == AUTH_KEY_AGREEMENT) {
75 res = AddIntToJson(payload, FIELD_KEY_LENGTH, params->returnKey.length);
76 if (res != HC_SUCCESS) {
77 LOGE("Add keyLength failed, res: %d.", res);
78 return res;
79 }
80 }
81
82 task->taskStatus = TASK_STATUS_CLIENT_PAKE_REQUEST;
83 *status = CONTINUE;
84 return res;
85 }
86
ParseMsgForClientConfirm(PakeParams * params,const CJson * in)87 static int ParseMsgForClientConfirm(PakeParams *params, const CJson *in)
88 {
89 int res = ParsePakeResponseMessage(params, in);
90 if (res != HC_SUCCESS) {
91 LOGE("ParsePakeResponseMessage failed, res: %d.", res);
92 return res;
93 }
94 // parse differentiated data
95 res = GetByteFromJson(in, FIELD_CHALLENGE, params->baseParams.challengePeer.val,
96 params->baseParams.challengePeer.length);
97 if (res != HC_SUCCESS) {
98 LOGE("Get challengePeer failed, res: %d.", res);
99 return res;
100 }
101 if (params->opCode == AUTHENTICATE || params->opCode == OP_UNBIND) {
102 res = GetAndCheckAuthIdPeer(in, &(params->baseParams.idSelf), &(params->baseParams.idPeer));
103 if (res != HC_SUCCESS) {
104 LOGE("GetAndCheckAuthIdPeer failed, res: %d.", res);
105 return res;
106 }
107 }
108 return res;
109 }
110
PackageMsgForClientConfirm(PakeParams * params,CJson * out)111 static int PackageMsgForClientConfirm(PakeParams *params, CJson *out)
112 {
113 int res = ConstructOutJson(params, out);
114 if (res != HC_SUCCESS) {
115 LOGE("ConstructOutJson failed, res: %d.", res);
116 return res;
117 }
118 CJson *payload = GetObjFromJson(out, FIELD_PAYLOAD);
119 if (payload == NULL) {
120 LOGE("Get payload from json failed.");
121 return HC_ERR_JSON_GET;
122 }
123 res = PackagePakeClientConfirmData(params, payload);
124 if (res != HC_SUCCESS) {
125 LOGE("PackagePakeClientConfirmData failed, res: %d.", res);
126 return res;
127 }
128 // differentiated data
129 res = AddByteToJson(payload, FIELD_CHALLENGE, params->baseParams.challengeSelf.val,
130 params->baseParams.challengeSelf.length);
131 if (res != HC_SUCCESS) {
132 LOGE("Add challengeSelf failed, res: %d.", res);
133 return res;
134 }
135 return res;
136 }
137
PakeClientConfirm(AsyBaseCurTask * task,PakeParams * params,const CJson * in,CJson * out,int * status)138 static int PakeClientConfirm(AsyBaseCurTask *task, PakeParams *params, const CJson *in, CJson *out, int *status)
139 {
140 int res;
141 if (task->taskStatus < TASK_STATUS_CLIENT_PAKE_REQUEST) {
142 LOGE("Invalid taskStatus: %d", task->taskStatus);
143 return HC_ERR_BAD_MESSAGE;
144 }
145 if (task->taskStatus > TASK_STATUS_CLIENT_PAKE_REQUEST) {
146 LOGI("The message is repeated, ignore it, status: %d", task->taskStatus);
147 *status = IGNORE_MSG;
148 return HC_SUCCESS;
149 }
150
151 res = ParseMsgForClientConfirm(params, in);
152 if (res != HC_SUCCESS) {
153 LOGE("ParseMsgForClientConfirm failed, res: %d.", res);
154 return res;
155 }
156 if (params->isPskSupported && (params->opCode == AUTHENTICATE || params->opCode == OP_UNBIND)) {
157 res = FillPskWithDerivedKeyHex(params);
158 if (res != HC_SUCCESS) {
159 LOGE("FillPskWithDerivedKeyHex failed, res: %x.", res);
160 return res;
161 }
162 }
163
164 // execute
165 res = ClientConfirmPakeV1Protocol(&(params->baseParams));
166 if (res != HC_SUCCESS) {
167 LOGE("ClientConfirmPakeV1Protocol failed, res:%d", res);
168 return res;
169 }
170
171 res = PackageMsgForClientConfirm(params, out);
172 if (res != HC_SUCCESS) {
173 LOGE("PackageMsgForClientConfirm failed, res: %d.", res);
174 return res;
175 }
176
177 task->taskStatus = TASK_STATUS_CLIENT_PAKE_CONFIRM;
178 *status = CONTINUE;
179 return res;
180 }
181
PakeClientVerifyConfirm(AsyBaseCurTask * task,PakeParams * params,const CJson * in,int * status)182 static int PakeClientVerifyConfirm(AsyBaseCurTask *task, PakeParams *params, const CJson *in, int *status)
183 {
184 if (task->taskStatus < TASK_STATUS_CLIENT_PAKE_CONFIRM) {
185 LOGE("Invalid taskStatus: %d", task->taskStatus);
186 return HC_ERR_BAD_MESSAGE;
187 }
188 if (task->taskStatus > TASK_STATUS_CLIENT_PAKE_CONFIRM) {
189 LOGI("The message is repeated, ignore it, status: %d", task->taskStatus);
190 *status = IGNORE_MSG;
191 return HC_SUCCESS;
192 }
193
194 // parse message
195 int res = ParsePakeServerConfirmMessage(params, in);
196 if (res != HC_SUCCESS) {
197 LOGE("ParsePakeServerConfirmMessage failed, res: %d.", res);
198 return res;
199 }
200
201 // execute
202 res = ClientVerifyConfirmPakeV1Protocol(¶ms->baseParams);
203 if (res != HC_SUCCESS) {
204 LOGE("ClientVerifyConfirmPakeV1Protocol failed, res: %d.", res);
205 return res;
206 }
207
208 task->taskStatus = TASK_STATUS_CLIENT_PAKE_VERIFY_CONFIRM;
209 *status = FINISH;
210 return res;
211 }
212
Process(struct AsyBaseCurTaskT * task,PakeParams * params,const CJson * in,CJson * out,int * status)213 static int Process(struct AsyBaseCurTaskT *task, PakeParams *params, const CJson *in, CJson *out, int *status)
214 {
215 int res = HC_SUCCESS;
216 uint32_t step = ProtocolMessageIn(in);
217 if (step == INVALID_MESSAGE) {
218 res = PakeRequest(task, params, out, status);
219 step = 1;
220 goto OUT;
221 }
222
223 step = step + 1; /* when receive peer message code, need to do next step */
224 switch (step) {
225 case STEP_TWO:
226 res = PakeClientConfirm(task, params, in, out, status);
227 break;
228 case STEP_THREE:
229 res = PakeClientVerifyConfirm(task, params, in, status);
230 break;
231 default:
232 res = HC_ERR_BAD_MESSAGE;
233 break;
234 }
235 OUT:
236 if (res != HC_SUCCESS) {
237 LOGE("Process step:%d failed, res: %x.", step, res);
238 return res;
239 }
240 if (step != STEP_THREE) {
241 res = ClientProtocolMessageOut(out, params->opCode, step);
242 if (res != HC_SUCCESS) {
243 LOGE("ClientProtocolMessageOut failed, res: %x.", res);
244 }
245 }
246 return res;
247 }
248
CreatePakeV1ProtocolClientTask(void)249 AsyBaseCurTask *CreatePakeV1ProtocolClientTask(void)
250 {
251 PakeV1ProtocolClientTask *task = (PakeV1ProtocolClientTask *)HcMalloc(sizeof(PakeV1ProtocolClientTask), 0);
252 if (task == NULL) {
253 LOGE("Malloc for PakeV1ProtocolClientTask failed.");
254 return NULL;
255 }
256 task->taskBase.destroyTask = DestroyPakeV1ProtocolClientTask;
257 task->taskBase.process = Process;
258 task->taskBase.taskStatus = TASK_STATUS_CLIENT_PAKE_BEGIN;
259 task->taskBase.getCurTaskType = GetTaskType;
260 return (AsyBaseCurTask *)task;
261 }