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 "iso_auth_client_task.h"
17 #include "account_module_defines.h"
18 #include "clib_error.h"
19 #include "common_defs.h"
20 #include "device_auth.h"
21 #include "device_auth_defines.h"
22 #include "hc_log.h"
23 #include "hc_types.h"
24 #include "iso_auth_task_common.h"
25 #include "iso_protocol_common.h"
26 #include "protocol_common.h"
27
28 enum {
29 TASK_STATUS_ISO_MAIN_BEGIN = 0,
30 TASK_STATUS_ISO_MAIN_STEP_ONE = 1,
31 TASK_STATUS_ISO_MAIN_STEP_TWO = 2,
32 TASK_STATUS_ISO_MAIN_END = 3,
33 };
34
GetIsoAuthClientType(void)35 static AccountTaskType GetIsoAuthClientType(void)
36 {
37 return TASK_TYPE_ISO_AUTH_CLIENT;
38 }
39
AddBeginDataToJson(const IsoAuthParams * params,CJson * sendToPeer)40 static int32_t AddBeginDataToJson(const IsoAuthParams *params, CJson *sendToPeer)
41 {
42 CJson *data = CreateJson();
43 if (data == NULL) {
44 LOGE("Create data json failed.");
45 return HC_ERR_JSON_CREATE;
46 }
47
48 if (AddByteToJson(data, FIELD_SALT,
49 params->isoBaseParams.randSelf.val, params->isoBaseParams.randSelf.length) != CLIB_SUCCESS) {
50 LOGE("Add saltSelf to json failed.");
51 goto CLEAN_UP;
52 }
53 if (AddByteToJson(data, FIELD_PAYLOAD,
54 params->isoBaseParams.authIdSelf.val, params->isoBaseParams.authIdSelf.length) != CLIB_SUCCESS) {
55 LOGE("Add payloadSelf to json failed.");
56 goto CLEAN_UP;
57 }
58 if (AddByteToJson(data, FIELD_SEED, params->seed, sizeof(params->seed)) != CLIB_SUCCESS) {
59 LOGE("Add seed to json failed.");
60 goto CLEAN_UP;
61 }
62 if (AddObjToJson(sendToPeer, FIELD_DATA, data) != CLIB_SUCCESS) {
63 LOGE("Add data json obj to json failed.");
64 goto CLEAN_UP;
65 }
66
67 FreeJson(data);
68 return HC_SUCCESS;
69 CLEAN_UP:
70 FreeJson(data);
71 return HC_ERR_JSON_ADD;
72 }
73
PackIsoAuthClientBeginMsg(const IsoAuthParams * params,CJson * out)74 static int32_t PackIsoAuthClientBeginMsg(const IsoAuthParams *params, CJson *out)
75 {
76 CJson *sendToPeer = CreateJson();
77 if (sendToPeer == NULL) {
78 LOGE("Create sendToPeer json failed.");
79 return HC_ERR_JSON_CREATE;
80 }
81
82 if (AddIntToJson(sendToPeer, FIELD_AUTH_FORM, params->authForm) != CLIB_SUCCESS) {
83 LOGE("Add authForm to json failed.");
84 goto CLEAN_UP;
85 }
86 if (AddIntToJson(sendToPeer, FIELD_STEP, CMD_ISO_AUTH_MAIN_ONE) != CLIB_SUCCESS) {
87 LOGE("Add step code to json failed.");
88 goto CLEAN_UP;
89 }
90 if (AddIntToJson(sendToPeer, FIELD_CREDENTIAL_TYPE, params->credentialType) != CLIB_SUCCESS) {
91 LOGE("Add credentialType to json failed.");
92 goto CLEAN_UP;
93 }
94 if (AddStringToJson(sendToPeer, FIELD_USER_ID, params->userIdSelf) != CLIB_SUCCESS) {
95 LOGE("Add userIdSelf to json failed.");
96 goto CLEAN_UP;
97 }
98 if (AddByteToJson(sendToPeer, FIELD_DEV_ID, params->devIdSelf.val, params->devIdSelf.length) != CLIB_SUCCESS) {
99 LOGE("Add devIdSelf to json failed.");
100 goto CLEAN_UP;
101 }
102 if (AddStringToJson(sendToPeer, FIELD_DEVICE_ID, params->deviceIdSelf) != CLIB_SUCCESS) {
103 LOGE("Add deviceIdSelf to json failed.");
104 goto CLEAN_UP;
105 }
106
107 if (AddBeginDataToJson(params, sendToPeer) != HC_SUCCESS) {
108 LOGE("AddBeginDataToJson failed.");
109 goto CLEAN_UP;
110 }
111
112 if (AddObjToJson(out, FIELD_SEND_TO_PEER, sendToPeer) != CLIB_SUCCESS) {
113 LOGE("Add sendToPeer to json failed.");
114 goto CLEAN_UP;
115 }
116 FreeJson(sendToPeer);
117 return HC_SUCCESS;
118 CLEAN_UP:
119 FreeJson(sendToPeer);
120 return HC_ERR_JSON_ADD;
121 }
122
AccountAuthGenSeed(IsoAuthParams * params)123 static int32_t AccountAuthGenSeed(IsoAuthParams *params)
124 {
125 Uint8Buff seedBuff = { params->seed, sizeof(params->seed) };
126 int32_t res = params->isoBaseParams.loader->generateRandom(&seedBuff);
127 if (res != HC_SUCCESS) {
128 LOGE("GenerateRandom for seed failed, res: %d.", res);
129 }
130 return res;
131 }
132
IsoAuthClientBegin(TaskBase * task,const CJson * in,CJson * out,int32_t * status)133 static int32_t IsoAuthClientBegin(TaskBase *task, const CJson *in, CJson *out, int32_t *status)
134 {
135 (void)in;
136 if (task->taskStatus != TASK_STATUS_ISO_MAIN_BEGIN) {
137 LOGD("The message is repeated, ignore it, taskStatus: %d.", task->taskStatus);
138 *status = IGNORE_MSG;
139 return HC_SUCCESS;
140 }
141
142 IsoAuthClientTask *innerTask = (IsoAuthClientTask *)task;
143 int32_t ret = IsoClientGenRandom(&innerTask->params.isoBaseParams);
144 if (ret != HC_SUCCESS) {
145 LOGE("IsoClientGenRandom failed, res: %d.", ret);
146 return ret;
147 }
148 ret = AccountAuthGenSeed(&innerTask->params);
149 if (ret != HC_SUCCESS) {
150 LOGE("AccountAuthGenSeed failed, res: %d.", ret);
151 return ret;
152 }
153
154 // Send params to server.
155 ret = PackIsoAuthClientBeginMsg(&innerTask->params, out);
156 if (ret != HC_SUCCESS) {
157 LOGE("PackIsoAuthClientBeginMsg failed, ret: %d.", ret);
158 return ret;
159 }
160
161 innerTask->taskBase.taskStatus = TASK_STATUS_ISO_MAIN_STEP_ONE;
162 *status = CONTINUE;
163 return HC_SUCCESS;
164 }
165
ParseIsoAuthServerGetTokenMsg(IsoAuthParams * params,const CJson * in,Uint8Buff * peerToken)166 static int32_t ParseIsoAuthServerGetTokenMsg(IsoAuthParams *params, const CJson *in, Uint8Buff *peerToken)
167 {
168 const char *userIdPeer = GetStringFromJson(in, FIELD_USER_ID);
169 if (userIdPeer == NULL) {
170 LOGE("Failed to get userIdPeer from input data for client in sym auth.");
171 return HC_ERR_JSON_GET;
172 }
173 if (strcpy_s(params->userIdPeer, DEV_AUTH_USER_ID_SIZE, userIdPeer) != EOK) {
174 LOGE("Copy for userIdPeer failed for client in sym auth.");
175 return HC_ERR_MEMORY_COPY;
176 }
177 if (GetByteFromJson(in, FIELD_SALT, params->isoBaseParams.randPeer.val,
178 params->isoBaseParams.randPeer.length) != CLIB_SUCCESS) {
179 LOGE("Get saltPeer from json failed for client.");
180 return HC_ERR_JSON_GET;
181 }
182 if (GetByteFromJson(in, FIELD_TOKEN, peerToken->val, peerToken->length) != CLIB_SUCCESS) {
183 LOGE("Get peerToken from json failed for client.");
184 return HC_ERR_JSON_GET;
185 }
186 int32_t res = ExtractAndVerifyPayload(params, in);
187 if (res != HC_SUCCESS) {
188 LOGE("ExtractAndVerifyPayload failed for client, res: %d.", res);
189 }
190 return res;
191 }
192
PackIsoAuthClientGetTokenMsg(const IsoAuthParams * params,CJson * out)193 static int32_t PackIsoAuthClientGetTokenMsg(const IsoAuthParams *params, CJson *out)
194 {
195 CJson *sendToPeer = CreateJson();
196 if (sendToPeer == NULL) {
197 LOGE("Create sendToPeer json failed.");
198 return HC_ERR_JSON_CREATE;
199 }
200 CJson *data = CreateJson();
201 if (data == NULL) {
202 LOGE("Create data json failed.");
203 FreeJson(sendToPeer);
204 return HC_ERR_JSON_CREATE;
205 }
206
207 if (AddIntToJson(sendToPeer, FIELD_AUTH_FORM, params->authForm) != CLIB_SUCCESS) {
208 LOGE("Add authForm to json failed.");
209 goto CLEAN_UP;
210 }
211 if (AddIntToJson(sendToPeer, FIELD_STEP, CMD_ISO_AUTH_MAIN_TWO) != CLIB_SUCCESS) {
212 LOGE("Add step code to json failed.");
213 goto CLEAN_UP;
214 }
215 if (AddByteToJson(data, FIELD_TOKEN, params->hmacToken, sizeof(params->hmacToken)) != CLIB_SUCCESS) {
216 LOGE("Add hmacToken to json failed.");
217 goto CLEAN_UP;
218 }
219 if (AddObjToJson(sendToPeer, FIELD_DATA, data) != CLIB_SUCCESS) {
220 LOGE("Add data json obj to json failed.");
221 goto CLEAN_UP;
222 }
223 if (AddObjToJson(out, FIELD_SEND_TO_PEER, sendToPeer) != CLIB_SUCCESS) {
224 LOGE("Add sendToPeer to json failed.");
225 goto CLEAN_UP;
226 }
227 FreeJson(sendToPeer);
228 FreeJson(data);
229 return HC_SUCCESS;
230 CLEAN_UP:
231 FreeJson(sendToPeer);
232 FreeJson(data);
233 return HC_ERR_JSON_ADD;
234 }
235
IsoAuthClientGetToken(TaskBase * task,const CJson * in,CJson * out,int32_t * status)236 static int32_t IsoAuthClientGetToken(TaskBase *task, const CJson *in, CJson *out, int32_t *status)
237 {
238 IsoAuthClientTask *innerTask = (IsoAuthClientTask *)task;
239 if (innerTask->taskBase.taskStatus < TASK_STATUS_ISO_MAIN_STEP_ONE) {
240 LOGE("Message code is not match with task status, taskStatus: %d", innerTask->taskBase.taskStatus);
241 return HC_ERR_BAD_MESSAGE;
242 }
243 if (innerTask->taskBase.taskStatus > TASK_STATUS_ISO_MAIN_STEP_ONE) {
244 LOGI("The message is repeated, ignore it, taskStatus: %d.", innerTask->taskBase.taskStatus);
245 *status = IGNORE_MSG;
246 return HC_SUCCESS;
247 }
248
249 // Receive params from server.
250 uint8_t peerToken[HMAC_TOKEN_SIZE] = { 0 };
251 Uint8Buff peerTokenBuf = { peerToken, HMAC_TOKEN_SIZE };
252 int32_t res = ParseIsoAuthServerGetTokenMsg(&innerTask->params, in, &peerTokenBuf);
253 if (res != HC_SUCCESS) {
254 LOGE("ParseIsoAuthServerGetTokenMsg failed, res: %d.", res);
255 return res;
256 }
257
258 // Get psk and process hmacToken.
259 res = AccountAuthGeneratePsk(&innerTask->params);
260 if (res != HC_SUCCESS) {
261 LOGE("AccountAuthGeneratePsk failed, res: %d.", res);
262 return res;
263 }
264 Uint8Buff selfTokenBuf = { innerTask->params.hmacToken, HMAC_TOKEN_SIZE };
265 res = IsoClientCheckAndGenToken(&(innerTask->params.isoBaseParams), &peerTokenBuf, &selfTokenBuf);
266 if (res != HC_SUCCESS) {
267 LOGE("IsoClientCheckAndGenToken failed, res: %d.", res);
268 return res;
269 }
270
271 // Send params to server.
272 res = PackIsoAuthClientGetTokenMsg(&innerTask->params, out);
273 if (res != HC_SUCCESS) {
274 LOGE("PackIsoAuthClientGetTokenMsg failed, res: %d.", res);
275 return res;
276 }
277
278 innerTask->taskBase.taskStatus = TASK_STATUS_ISO_MAIN_STEP_TWO;
279 *status = CONTINUE;
280 return HC_SUCCESS;
281 }
282
IsoAuthClientGetSessionKey(TaskBase * task,const CJson * in,CJson * out,int32_t * status)283 static int32_t IsoAuthClientGetSessionKey(TaskBase *task, const CJson *in, CJson *out, int32_t *status)
284 {
285 IsoAuthClientTask *innerTask = (IsoAuthClientTask *)task;
286 if (innerTask->taskBase.taskStatus < TASK_STATUS_ISO_MAIN_STEP_TWO) {
287 LOGE("Message code is not match with task status, taskStatus: %d", innerTask->taskBase.taskStatus);
288 return HC_ERR_BAD_MESSAGE;
289 }
290 if (innerTask->taskBase.taskStatus > TASK_STATUS_ISO_MAIN_STEP_TWO) {
291 LOGI("The message is repeated, ignore it, taskStatus: %d", innerTask->taskBase.taskStatus);
292 *status = IGNORE_MSG;
293 return HC_SUCCESS;
294 }
295
296 // Receive params from server.
297 uint8_t authResultHmac[AUTH_RESULT_MAC_SIZE] = { 0 };
298 if (GetByteFromJson(in, FIELD_AUTH_RESULT_MAC, authResultHmac, sizeof(authResultHmac)) != CLIB_SUCCESS) {
299 LOGE("Get authResultHmac from json failed.");
300 return HC_ERR_JSON_GET;
301 }
302
303 // Generate and verify the HMAC, then generate session key.
304 int32_t res = IsoClientGenSessionKey(&(innerTask->params.isoBaseParams), 0, authResultHmac, sizeof(authResultHmac));
305 if (res != HC_SUCCESS) {
306 LOGE("IsoClientGenSessionKey failed, res: %d.", res);
307 return res;
308 }
309
310 res = AuthIsoSendFinalToOut(&innerTask->params, out);
311 if (res != HC_SUCCESS) {
312 LOGE("AuthIsoSendFinalToOut failed, res: %d.", res);
313 return res;
314 }
315
316 innerTask->taskBase.taskStatus = TASK_STATUS_ISO_MAIN_END;
317 *status = FINISH;
318 return HC_SUCCESS;
319 }
320
ProcessClientTask(TaskBase * task,const CJson * in,CJson * out,int32_t * status)321 static int32_t ProcessClientTask(TaskBase *task, const CJson *in, CJson *out, int32_t *status)
322 {
323 int32_t res;
324 if (task->taskStatus == TASK_STATUS_ISO_MAIN_BEGIN) {
325 res = IsoAuthClientBegin(task, in, out, status);
326 if (res != HC_SUCCESS) {
327 LOGE("IsoAuthClientBegin failed, res: %d.", res);
328 }
329 return res;
330 }
331
332 int32_t authStep;
333 if (GetIntFromJson(in, FIELD_STEP, &authStep) != CLIB_SUCCESS) {
334 LOGE("Get message code from json failed.");
335 return HC_ERR_JSON_GET;
336 }
337 switch (authStep) {
338 case RET_ISO_AUTH_FOLLOWER_ONE:
339 res = IsoAuthClientGetToken(task, in, out, status);
340 break;
341 case RET_ISO_AUTH_FOLLOWER_TWO:
342 res = IsoAuthClientGetSessionKey(task, in, out, status);
343 break;
344 default:
345 res = HC_ERR_BAD_MESSAGE;
346 }
347 if (res != HC_SUCCESS) {
348 LOGE("Process iso auth client failed, step: %d, res: %d.", authStep, res);
349 }
350 return res;
351 }
352
DestroyAuthClientAuthTask(TaskBase * task)353 static void DestroyAuthClientAuthTask(TaskBase *task)
354 {
355 if (task == NULL) {
356 return;
357 }
358 IsoAuthClientTask *innerTask = (IsoAuthClientTask *)task;
359 DestroyIsoAuthParams(&(innerTask->params));
360 HcFree(innerTask);
361 }
362
CreateIsoAuthClientTask(const CJson * in,CJson * out,const AccountVersionInfo * verInfo)363 TaskBase *CreateIsoAuthClientTask(const CJson *in, CJson *out, const AccountVersionInfo *verInfo)
364 {
365 if ((in == NULL) || (out == NULL) || (verInfo == NULL)) {
366 LOGE("Params is null for client sym auth.");
367 return NULL;
368 }
369 IsoAuthClientTask *task = (IsoAuthClientTask *)HcMalloc(sizeof(IsoAuthClientTask), 0);
370 if (task == NULL) {
371 LOGE("Malloc for IsoAuthClientTask failed.");
372 return NULL;
373 }
374 task->taskBase.getTaskType = GetIsoAuthClientType;
375 task->taskBase.process = ProcessClientTask;
376 task->taskBase.destroyTask = DestroyAuthClientAuthTask;
377
378 int32_t res = InitIsoAuthParams(in, &(task->params), verInfo);
379 if (res != HC_SUCCESS) {
380 LOGE("InitIsoAuthParams failed, res: %d.", res);
381 DestroyAuthClientAuthTask((TaskBase *)task);
382 return NULL;
383 }
384
385 task->taskBase.taskStatus = TASK_STATUS_ISO_MAIN_BEGIN;
386 return (TaskBase *)task;
387 }
388