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 "pake_v2_auth_client_task.h"
17 #include "common_defs.h"
18 #include "device_auth_defines.h"
19 #include "hc_types.h"
20 #include "hc_log.h"
21 #include "string_util.h"
22 #include "protocol_common.h"
23 #include "account_module.h"
24 #include "account_version_util.h"
25 #include "pake_v2_auth_task_common.h"
26 #include "pake_v2_protocol_common.h"
27
28 enum {
29 TASK_STATUS_PAKE_MAIN_BEGIN = 0,
30 TASK_STATUS_PAKE_MAIN_STEP_ONE = 1,
31 TASK_STATUS_PAKE_MAIN_STEP_TWO = 2,
32 TASK_STATUS_PAKE_MAIN_END = 3,
33 };
34
GetPakeV2AuthClientType(void)35 static AccountTaskType GetPakeV2AuthClientType(void)
36 {
37 return TASK_TYPE_PAKE_V2_AUTH_CLIENT;
38 }
39
AsyAuthClientStepOne(TaskBase * task,const CJson * in,CJson * out,int32_t * status)40 static int32_t AsyAuthClientStepOne(TaskBase *task, const CJson *in, CJson *out, int32_t *status)
41 {
42 PakeV2AuthClientTask *innerTask = (PakeV2AuthClientTask *)task;
43 CJson *sendToPeer = CreateJson();
44 if (sendToPeer == NULL) {
45 LOGE("Failed to create sendToPeer json.");
46 return HC_ERR_JSON_CREATE;
47 }
48 CJson *data = CreateJson();
49 if (data == NULL) {
50 LOGE("Failed to create data json.");
51 FreeJson(sendToPeer);
52 return HC_ERR_JSON_CREATE;
53 }
54
55 GOTO_IF_ERR(GetIntFromJson(in, FIELD_AUTH_FORM, &innerTask->params.authForm));
56 GOTO_IF_ERR(GetIntFromJson(in, FIELD_CREDENTIAL_TYPE, &innerTask->params.credentialType));
57
58 GOTO_IF_ERR(AddIntToJson(sendToPeer, FIELD_AUTH_FORM, innerTask->params.authForm));
59 GOTO_IF_ERR(AddStringToJson(sendToPeer, FIELD_USER_ID, (const char *)innerTask->params.userIdSelf));
60 GOTO_IF_ERR(AddIntToJson(sendToPeer, FIELD_STEP, CMD_PAKE_AUTH_MAIN_ONE));
61 GOTO_IF_ERR(AddStringToJson(sendToPeer, FIELD_DEVICE_ID, (const char *)innerTask->params.deviceIdSelf.val));
62 GOTO_IF_ERR(AddStringToJson(sendToPeer, FIELD_DEV_ID, (const char *)innerTask->params.devIdSelf.val));
63
64 GOTO_IF_ERR(AddIntToJson(data, FIELD_AUTH_KEY_ALG_ENCODE, ALG_ECC));
65 GOTO_IF_ERR(AddIntToJson(data, FIELD_CREDENTIAL_TYPE, innerTask->params.credentialType));
66 GOTO_IF_ERR(AddStringToJson(data, FIELD_AUTH_PK_INFO, (const char *)innerTask->params.pkInfoSelf.val));
67 GOTO_IF_ERR(AddByteToJson(data, FIELD_AUTH_PK_INFO_SIGN, innerTask->params.pkInfoSignSelf.val,
68 innerTask->params.pkInfoSignSelf.length));
69 GOTO_IF_ERR(AddObjToJson(sendToPeer, FIELD_DATA, data));
70 GOTO_IF_ERR(AddObjToJson(out, FIELD_SEND_TO_PEER, sendToPeer));
71 innerTask->taskBase.taskStatus = TASK_STATUS_PAKE_MAIN_STEP_ONE;
72 *status = CONTINUE;
73 FreeJson(sendToPeer);
74 FreeJson(data);
75 return HC_SUCCESS;
76 ERR:
77 LOGE("Client step one failed.");
78 FreeJson(sendToPeer);
79 FreeJson(data);
80 return HC_ERR_AUTH_INTERNAL;
81 }
82
DealAsyStepTwoData(PakeV2AuthClientTask * task)83 static int32_t DealAsyStepTwoData(PakeV2AuthClientTask *task)
84 {
85 if (ExtractPakeSelfId(&task->params) != HC_SUCCESS) {
86 LOGE("ExtractPakeSelfId failed for client.");
87 return HC_ERR_AUTH_INTERNAL;
88 }
89 if (VerifyPkSignPeer(&task->params) != HC_SUCCESS) {
90 LOGE("VerifyPkSignPeer failed for client.");
91 return HC_ERR_ACCOUNT_VERIFY_PK_SIGN;
92 }
93 if (GenerateEcdhSharedKey(&task->params) != HC_SUCCESS) {
94 LOGE("Generate ecdh shared key failed for client.");
95 return HC_ERR_ACCOUNT_ECDH_FAIL;
96 }
97 if (ClientConfirmPakeV2Protocol(&task->params.pakeParams)) {
98 LOGE("ClientConfirmPakeV2Protocol failed.");
99 return HC_ERR_CLIENT_CONFIRM_PROTOCOL;
100 }
101 return HC_SUCCESS;
102 }
103
PrepareAsyClientStepTwoData(const PakeV2AuthClientTask * innerTask,CJson * out)104 static int32_t PrepareAsyClientStepTwoData(const PakeV2AuthClientTask *innerTask, CJson *out)
105 {
106 CJson *sendToPeer = CreateJson();
107 if (sendToPeer == NULL) {
108 LOGE("Create sendToPeer json NULL.");
109 return HC_ERR_JSON_CREATE;
110 }
111 CJson *data = CreateJson();
112 if (data == NULL) {
113 LOGE("Create data json NULL.");
114 FreeJson(sendToPeer);
115 return HC_ERR_JSON_CREATE;
116 }
117 int32_t ret = HC_SUCCESS;
118 GOTO_ERR_AND_SET_RET(AddIntToJson(sendToPeer, FIELD_AUTH_FORM, innerTask->params.authForm), ret);
119 GOTO_ERR_AND_SET_RET(AddIntToJson(sendToPeer, FIELD_STEP, CMD_PAKE_AUTH_MAIN_TWO), ret);
120 GOTO_ERR_AND_SET_RET(AddByteToJson(data, FIELD_KCF_DATA, innerTask->params.pakeParams.kcfData.val,
121 innerTask->params.pakeParams.kcfData.length), ret);
122 GOTO_ERR_AND_SET_RET(AddStringToJson(data, FIELD_DEVICE_ID,
123 (const char *)innerTask->params.deviceIdSelf.val), ret);
124 GOTO_ERR_AND_SET_RET(AddByteToJson(data, FIELD_EPK, innerTask->params.pakeParams.epkSelf.val,
125 innerTask->params.pakeParams.epkSelf.length), ret);
126 GOTO_ERR_AND_SET_RET(AddObjToJson(sendToPeer, FIELD_DATA, data), ret);
127 GOTO_ERR_AND_SET_RET(AddObjToJson(out, FIELD_SEND_TO_PEER, sendToPeer), ret);
128 ERR:
129 FreeJson(sendToPeer);
130 FreeJson(data);
131 return ret;
132 }
133
AsyAuthClientStepTwo(TaskBase * task,const CJson * in,CJson * out,int32_t * status)134 static int32_t AsyAuthClientStepTwo(TaskBase *task, const CJson *in, CJson *out, int32_t *status)
135 {
136 PakeV2AuthClientTask *innerTask = (PakeV2AuthClientTask *)task;
137 if (innerTask->taskBase.taskStatus != TASK_STATUS_PAKE_MAIN_STEP_ONE) {
138 LOGE("Client step two status error.");
139 return HC_ERR_AUTH_STATUS;
140 }
141 const char *userIdPeer = GetStringFromJson(in, FIELD_USER_ID);
142 uint32_t userIdPeerLen = HcStrlen(userIdPeer) + 1;
143 if (userIdPeer == NULL || userIdPeerLen > DEV_AUTH_USER_ID_SIZE) {
144 LOGE("Payload not contain peer userId or userId len is invalid.");
145 return HC_ERR_BAD_MESSAGE;
146 }
147 GOTO_IF_ERR(strcpy_s((char *)innerTask->params.userIdPeer, userIdPeerLen, userIdPeer));
148 GOTO_IF_ERR(GetPkInfoPeer(&innerTask->params, in));
149 GOTO_IF_ERR(ExtractPeerDeviceId(&innerTask->params, in));
150 GOTO_IF_ERR(ExtractPeerDevId(&innerTask->params, in));
151 GOTO_IF_ERR(ExtractPakePeerId(&innerTask->params, in));
152 GOTO_IF_ERR(GetByteFromJson(in, FIELD_AUTH_PK_INFO_SIGN, innerTask->params.pkInfoSignPeer.val,
153 innerTask->params.pkInfoSignPeer.length));
154 const char *pkInfoSignPeerStr = GetStringFromJson(in, FIELD_AUTH_PK_INFO_SIGN);
155 if (pkInfoSignPeerStr == NULL) {
156 LOGE("pkInfoSignPeer in client is null.");
157 return HC_ERR_NULL_PTR;
158 }
159 innerTask->params.pkInfoSignPeer.length = HcStrlen(pkInfoSignPeerStr) / BYTE_TO_HEX_OPER_LENGTH;
160 GOTO_IF_ERR(GetByteFromJson(in, FIELD_SALT, innerTask->params.pakeParams.salt.val,
161 innerTask->params.pakeParams.salt.length));
162 GOTO_IF_ERR(GetByteFromJson(in, FIELD_EPK, innerTask->params.pakeParams.epkPeer.val,
163 innerTask->params.pakeParams.epkPeer.length));
164
165 GOTO_IF_ERR(DealAsyStepTwoData(innerTask));
166
167 GOTO_IF_ERR(PrepareAsyClientStepTwoData(innerTask, out));
168
169 innerTask->taskBase.taskStatus = TASK_STATUS_PAKE_MAIN_STEP_TWO;
170 *status = CONTINUE;
171 return HC_SUCCESS;
172 ERR:
173 LOGE("Client step two failed");
174 return HC_ERR_AUTH_INTERNAL;
175 }
176
DealAsyStepThreeData(PakeAuthParams * params)177 static int32_t DealAsyStepThreeData(PakeAuthParams *params)
178 {
179 int32_t res = ClientVerifyConfirmPakeV2Protocol(¶ms->pakeParams);
180 if (res != HC_SUCCESS) {
181 LOGE("Client Verify ConfirmPakeV2Protocol failed.");
182 }
183 return res;
184 }
185
SendFinalToOut(PakeV2AuthClientTask * task,CJson * out)186 static int32_t SendFinalToOut(PakeV2AuthClientTask *task, CJson *out)
187 {
188 CJson *sendToSelf = CreateJson();
189 if (sendToSelf == NULL) {
190 LOGE("Create sendToSelf json NULL.");
191 return HC_ERR_JSON_CREATE;
192 }
193 GOTO_IF_ERR(AddStringToJson(sendToSelf, FIELD_USER_ID, (const char *)task->params.userIdPeer));
194 GOTO_IF_ERR(AddByteToJson(sendToSelf,
195 FIELD_SESSION_KEY, task->params.pakeParams.sessionKey.val, task->params.pakeParams.sessionKey.length));
196 GOTO_IF_ERR(AddStringToJson(sendToSelf, FIELD_DEVICE_ID, (const char *)task->params.deviceIdSelf.val));
197 GOTO_IF_ERR(AddStringToJson(sendToSelf, FIELD_DEV_ID, (const char *)task->params.devIdPeer.val));
198 GOTO_IF_ERR(AddIntToJson(sendToSelf, FIELD_CREDENTIAL_TYPE, ASYMMETRIC_CRED));
199
200 GOTO_IF_ERR(AddObjToJson(out, FIELD_SEND_TO_SELF, sendToSelf));
201 FreeJson(sendToSelf);
202 FreeAndCleanKey(&task->params.pakeParams.sessionKey);
203 return HC_SUCCESS;
204 ERR:
205 FreeAndCleanKey(&task->params.pakeParams.sessionKey);
206 FreeJson(sendToSelf);
207 LOGE("SendFinalToOut failed");
208 return HC_ERR_AUTH_INTERNAL;
209 }
210
AsyAuthClientStepThree(TaskBase * task,const CJson * in,CJson * out,int32_t * status)211 static int32_t AsyAuthClientStepThree(TaskBase *task, const CJson *in, CJson *out, int32_t *status)
212 {
213 PakeV2AuthClientTask *innerTask = (PakeV2AuthClientTask *)task;
214 if (innerTask->taskBase.taskStatus != TASK_STATUS_PAKE_MAIN_STEP_TWO) {
215 LOGE("Client step three status error.");
216 return HC_ERR_AUTH_STATUS;
217 }
218 GOTO_IF_ERR(GetByteFromJson(in, FIELD_KCF_DATA,
219 innerTask->params.pakeParams.kcfDataPeer.val, innerTask->params.pakeParams.kcfDataPeer.length));
220 GOTO_IF_ERR(DealAsyStepThreeData(&innerTask->params));
221 GOTO_IF_ERR(SendFinalToOut(innerTask, out));
222 innerTask->taskBase.taskStatus = TASK_STATUS_PAKE_MAIN_END;
223 *status = FINISH;
224 return HC_SUCCESS;
225 ERR:
226 LOGE("Client step three failed");
227 return HC_ERR_AUTH_INTERNAL;
228 }
229
ProcessClientTask(TaskBase * task,const CJson * in,CJson * out,int32_t * status)230 static int32_t ProcessClientTask(TaskBase *task, const CJson *in, CJson *out, int32_t *status)
231 {
232 LOGI("Start process client pake v2 auth task.");
233 if (task == NULL || in == NULL || out == NULL || status == NULL) {
234 LOGE("ProcessClientTask in params NULL.");
235 return HC_ERR_INVALID_PARAMS;
236 }
237
238 if (task->taskStatus == TASK_STATUS_PAKE_MAIN_BEGIN) {
239 return AsyAuthClientStepOne(task, in, out, status);
240 }
241 int32_t step = 0; // step comes from opposite device
242 if (GetIntFromJson(in, FIELD_STEP, &step) != HC_SUCCESS) {
243 LOGE("Get no auth step.");
244 return HC_ERR_JSON_GET;
245 }
246 int32_t res;
247 switch (step) {
248 case RET_PAKE_AUTH_FOLLOWER_ONE: // the step name of the opposite
249 res = AsyAuthClientStepTwo(task, in, out, status);
250 break;
251 case RET_PAKE_AUTH_FOLLOWER_TWO:
252 res = AsyAuthClientStepThree(task, in, out, status);
253 break;
254 case ERR_MSG:
255 return HC_ERR_PEER_ERROR;
256 default:
257 res = HC_ERR_BAD_MESSAGE;
258 break;
259 }
260 if (res != HC_SUCCESS) {
261 LOGE("error occurred and send error");
262 return res;
263 }
264 LOGI("End process client, step = %d", step);
265 return HC_SUCCESS;
266 }
267
DestroyAuthClientAuthTask(TaskBase * task)268 static void DestroyAuthClientAuthTask(TaskBase *task)
269 {
270 if (task == NULL) {
271 LOGD("Task is NULL");
272 return;
273 }
274 PakeV2AuthClientTask *innerTask = (PakeV2AuthClientTask *)task;
275 DestroyPakeAuthParams(&(innerTask->params));
276 HcFree(innerTask);
277 }
278
CreatePakeV2AuthClientTask(const CJson * in,CJson * out,const AccountVersionInfo * verInfo)279 TaskBase *CreatePakeV2AuthClientTask(const CJson *in, CJson *out, const AccountVersionInfo *verInfo)
280 {
281 if (in == NULL || out == NULL || verInfo == NULL) {
282 LOGE("Params is null for create client pake v2 auth task.");
283 return NULL;
284 }
285 PakeV2AuthClientTask *taskParams = (PakeV2AuthClientTask *)HcMalloc(sizeof(PakeV2AuthClientTask), 0);
286 if (taskParams == NULL) {
287 LOGE("Malloc for PakeV2AuthClientTask failed.");
288 return NULL;
289 }
290 taskParams->taskBase.getTaskType = GetPakeV2AuthClientType;
291 taskParams->taskBase.destroyTask = DestroyAuthClientAuthTask;
292 taskParams->taskBase.process = ProcessClientTask;
293 int32_t res = InitPakeAuthParams(in, &(taskParams->params), verInfo);
294 if (res != HC_SUCCESS) {
295 DestroyAuthClientAuthTask((TaskBase *)taskParams);
296 LOGE("InitPakeAuthParams failed");
297 return NULL;
298 }
299
300 taskParams->taskBase.taskStatus = TASK_STATUS_PAKE_MAIN_BEGIN;
301 return (TaskBase *)taskParams;
302 }