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 "iso_client_protocol_task.h"
17 #include "common_defs.h"
18 #include "das_task_common.h"
19 #include "hc_log.h"
20 #include "hc_types.h"
21 #include "iso_protocol_common.h"
22 #include "iso_task_common.h"
23
24 enum {
25 TASK_STATUS_BEGIN = 0,
26 TASK_STATUS_SERVER_RES_TOKEN,
27 TASK_STATUS_GEN_SESSION_KEY,
28 TASK_STATUS_FINAL,
29 };
30
GetTaskType(void)31 static CurTaskType GetTaskType(void)
32 {
33 return TASK_TYPE_ISO_PROTOCOL;
34 }
35
DestroyProtocolClientTask(struct SymBaseCurTaskT * task)36 static void DestroyProtocolClientTask(struct SymBaseCurTaskT *task)
37 {
38 HcFree(task);
39 }
40
IsoClientStartPackData(CJson * out,const IsoParams * params)41 static int IsoClientStartPackData(CJson *out, const IsoParams *params)
42 {
43 int res;
44 CJson *payload = NULL;
45 CJson *sendToPeer = NULL;
46 payload = CreateJson();
47 if (payload == NULL) {
48 LOGE("Create payload json failed.");
49 res = HC_ERR_JSON_CREATE;
50 goto ERR;
51 }
52 sendToPeer = CreateJson();
53 if (sendToPeer == NULL) {
54 LOGE("Create sendToPeer json failed.");
55 res = HC_ERR_JSON_CREATE;
56 goto ERR;
57 }
58 GOTO_ERR_AND_SET_RET(AddIntToJson(sendToPeer, FIELD_AUTH_FORM, AUTH_FORM_ACCOUNT_UNRELATED), res);
59
60 GOTO_ERR_AND_SET_RET(AddByteToJson(payload, FIELD_ISO_SALT, params->baseParams.randSelf.val,
61 params->baseParams.randSelf.length), res);
62 GOTO_ERR_AND_SET_RET(AddByteToJson(payload, FIELD_PEER_AUTH_ID, params->baseParams.authIdSelf.val,
63 params->baseParams.authIdSelf.length), res);
64 GOTO_ERR_AND_SET_RET(AddIntToJson(payload, FIELD_OPERATION_CODE, params->opCode), res);
65 GOTO_ERR_AND_SET_RET(AddByteToJson(payload, FIELD_SEED, params->seed.val, params->seed.length), res);
66 GOTO_ERR_AND_SET_RET(AddIntToJson(payload, FIELD_PEER_USER_TYPE, params->selfUserType), res);
67 if (params->opCode == AUTHENTICATE || params->opCode == OP_UNBIND) {
68 GOTO_ERR_AND_SET_RET(AddStringToJson(payload, FIELD_PKG_NAME, params->packageName), res);
69 GOTO_ERR_AND_SET_RET(AddStringToJson(payload, FIELD_SERVICE_TYPE, params->serviceType), res);
70 GOTO_ERR_AND_SET_RET(AddIntToJson(payload, FIELD_KEY_LENGTH, params->keyLen), res);
71 }
72 GOTO_ERR_AND_SET_RET(AddObjToJson(sendToPeer, FIELD_PAYLOAD, payload), res);
73 GOTO_ERR_AND_SET_RET(AddObjToJson(out, FIELD_SEND_TO_PEER, sendToPeer), res);
74 ERR:
75 FreeJson(payload);
76 FreeJson(sendToPeer);
77 return res;
78 }
79
IsoClientStart(SymBaseCurTask * task,IsoParams * params,CJson * out,int32_t * status)80 static int IsoClientStart(SymBaseCurTask *task, IsoParams *params, CJson *out, int32_t *status)
81 {
82 if (task->taskStatus != TASK_STATUS_BEGIN) {
83 LOGI("The message is repeated, ignore it, status: %d", task->taskStatus);
84 *status = IGNORE_MSG;
85 return HC_SUCCESS;
86 }
87 int res = IsoClientGenRandom(¶ms->baseParams);
88 if (res != 0) {
89 LOGE("IsoClientGenRandom failed, res: %x.", res);
90 return res;
91 }
92 res = GenerateSeed(params);
93 if (res != 0) {
94 LOGE("GenerateSeed failed, res: %x.", res);
95 return res;
96 }
97 res = IsoClientStartPackData(out, params);
98 if (res != 0) {
99 LOGE("IsoClientStartPackData failed, res: %x.", res);
100 return res;
101 }
102 task->taskStatus = TASK_STATUS_SERVER_RES_TOKEN;
103 *status = CONTINUE;
104 return res;
105 }
106
PackDataForCalToken(const IsoParams * params,const Uint8Buff * selfTokenBuf,CJson * out)107 static int PackDataForCalToken(const IsoParams *params, const Uint8Buff *selfTokenBuf, CJson *out)
108 {
109 int res;
110 CJson *payload = NULL;
111 CJson *sendToPeer = NULL;
112
113 sendToPeer = CreateJson();
114 if (sendToPeer == NULL) {
115 LOGE("Create sendToPeer json failed.");
116 res = HC_ERR_JSON_CREATE;
117 goto ERR;
118 }
119 payload = CreateJson();
120 if (payload == NULL) {
121 LOGE("Create payload json failed.");
122 res = HC_ERR_JSON_CREATE;
123 goto ERR;
124 }
125
126 GOTO_ERR_AND_SET_RET(AddIntToJson(sendToPeer, FIELD_AUTH_FORM, AUTH_FORM_ACCOUNT_UNRELATED), res);
127 GOTO_ERR_AND_SET_RET(AddByteToJson(payload, FIELD_PEER_AUTH_ID, params->baseParams.authIdSelf.val,
128 params->baseParams.authIdSelf.length), res);
129 GOTO_ERR_AND_SET_RET(AddByteToJson(payload, FIELD_TOKEN, selfTokenBuf->val, selfTokenBuf->length), res);
130 GOTO_ERR_AND_SET_RET(AddObjToJson(sendToPeer, FIELD_PAYLOAD, payload), res);
131 GOTO_ERR_AND_SET_RET(AddObjToJson(out, FIELD_SEND_TO_PEER, sendToPeer), res);
132 ERR:
133 FreeJson(payload);
134 FreeJson(sendToPeer);
135 return res;
136 }
137
ParseServerStartMessage(IsoParams * params,const CJson * in,Uint8Buff * peerToken)138 static int ParseServerStartMessage(IsoParams *params, const CJson *in, Uint8Buff *peerToken)
139 {
140 if (params->opCode == OP_BIND) {
141 RETURN_IF_ERR(GetAuthIdPeerFromPayload(in, &(params->baseParams.authIdSelf), &(params->baseParams.authIdPeer)));
142 } else {
143 RETURN_IF_ERR(GetAndCheckAuthIdPeer(in, &(params->baseParams.authIdSelf), &(params->baseParams.authIdPeer)));
144 }
145 RETURN_IF_ERR(GetByteFromJson(in, FIELD_ISO_SALT, params->baseParams.randPeer.val,
146 params->baseParams.randPeer.length));
147 RETURN_IF_ERR(GetByteFromJson(in, FIELD_TOKEN, peerToken->val, peerToken->length));
148 RETURN_IF_ERR(GetIntFromJson(in, FIELD_PEER_USER_TYPE, &(params->peerUserType)));
149 return HC_SUCCESS;
150 }
151
CalculateTokenClient(SymBaseCurTask * task,IsoParams * params,const CJson * in,CJson * out,int32_t * status)152 static int CalculateTokenClient(SymBaseCurTask *task, IsoParams *params, const CJson *in, CJson *out, int32_t *status)
153 {
154 int res;
155 if (task->taskStatus < TASK_STATUS_SERVER_RES_TOKEN) {
156 LOGE("Invalid taskStatus: %d", task->taskStatus);
157 return HC_ERR_BAD_MESSAGE;
158 }
159
160 if (task->taskStatus > TASK_STATUS_SERVER_RES_TOKEN) {
161 LOGI("The message is repeated, ignore it, status: %d", task->taskStatus);
162 *status = IGNORE_MSG;
163 return HC_SUCCESS;
164 }
165
166 // parse message
167 uint8_t peerToken[ISO_TOKEN_LEN] = { 0 };
168 Uint8Buff peerTokenBuf = { peerToken, ISO_TOKEN_LEN };
169
170 uint8_t selfToken[ISO_TOKEN_LEN] = { 0 };
171 Uint8Buff selfTokenBuf = { selfToken, ISO_TOKEN_LEN };
172
173 res = ParseServerStartMessage(params, in, &peerTokenBuf);
174 if (res != 0) {
175 LOGE("ParseServerStartMessage failed, res: %x.", res);
176 return res;
177 }
178 res = GeneratePsk(in, params);
179 if (res != 0) {
180 LOGE("GeneratePsk failed, res: %x.", res);
181 return res;
182 }
183
184 // execute
185 res = IsoClientCheckAndGenToken(¶ms->baseParams, &peerTokenBuf, &selfTokenBuf);
186 if (res != HC_SUCCESS) {
187 LOGE("IsoClientCheckAndGenToken failed, res: %x.", res);
188 return res;
189 }
190
191 // package message
192 res = PackDataForCalToken(params, &selfTokenBuf, out);
193 if (res != 0) {
194 LOGE("PackDataForCalToken failed, res: %d", res);
195 return res;
196 }
197 task->taskStatus = TASK_STATUS_GEN_SESSION_KEY;
198 *status = CONTINUE;
199 return res;
200 }
201
GenerateSessionKey(SymBaseCurTask * task,IsoParams * params,const CJson * in,int32_t * status)202 static int GenerateSessionKey(SymBaseCurTask *task, IsoParams *params, const CJson *in, int32_t *status)
203 {
204 if (task->taskStatus < TASK_STATUS_GEN_SESSION_KEY) {
205 LOGE("Invalid taskStatus: %d", task->taskStatus);
206 return HC_ERR_BAD_MESSAGE;
207 }
208
209 if (task->taskStatus > TASK_STATUS_GEN_SESSION_KEY) {
210 LOGI("The message is repeated, ignore it, status: %d", task->taskStatus);
211 *status = IGNORE_MSG;
212 return HC_SUCCESS;
213 }
214
215 uint8_t *hmac = (uint8_t *)HcMalloc(HMAC_LEN, 0);
216 if (hmac == NULL) {
217 LOGE("Malloc for hmac failed.");
218 return HC_ERR_ALLOC_MEMORY;
219 }
220 int res;
221 if (GetByteFromJson(in, FIELD_RETURN_CODE_MAC, hmac, HMAC_LEN) != 0) {
222 LOGE("Get hmac from json failed.");
223 res = HC_ERR_JSON_GET;
224 goto ERR;
225 }
226
227 // execute
228 res = IsoClientGenSessionKey(¶ms->baseParams, 0, hmac, HMAC_LEN);
229 if (res != 0) {
230 LOGE("IsoClientGenSessionKey failed, res: %x.", res);
231 goto ERR;
232 }
233
234 task->taskStatus = TASK_STATUS_FINAL;
235 *status = FINISH;
236 ERR:
237 HcFree(hmac);
238 return res;
239 }
240
Process(struct SymBaseCurTaskT * task,IsoParams * params,const CJson * in,CJson * out,int32_t * status)241 static int Process(struct SymBaseCurTaskT *task, IsoParams *params, const CJson *in, CJson *out, int32_t *status)
242 {
243 int res;
244 uint32_t step = ProtocolMessageIn(in);
245 if (step == INVALID_MESSAGE) {
246 res = IsoClientStart(task, params, out, status);
247 step = STEP_ONE;
248 goto OUT_FUNC;
249 }
250
251 step = step + 1; /* when receive peer message code, need to do next step */
252 switch (step) {
253 case STEP_TWO:
254 res = CalculateTokenClient(task, params, in, out, status);
255 break;
256 case STEP_THREE:
257 res = GenerateSessionKey(task, params, in, status);
258 break;
259 default:
260 res = HC_ERR_BAD_MESSAGE;
261 break;
262 }
263 OUT_FUNC:
264 if (res != HC_SUCCESS) {
265 LOGE("Process step:%d failed, res: %x.", step, res);
266 return res;
267 }
268 if (step != STEP_THREE) {
269 res = ClientProtocolMessageOut(out, params->opCode, step);
270 if (res != HC_SUCCESS) {
271 LOGE("ClientProtocolMessageOut failed, res: %x.", res);
272 }
273 }
274 return res;
275 }
276
CreateProtocolClientTask(void)277 SymBaseCurTask *CreateProtocolClientTask(void)
278 {
279 IsoProtocolClientTask *task = (IsoProtocolClientTask *)HcMalloc(sizeof(IsoProtocolClientTask), 0);
280 if (task == NULL) {
281 LOGE("Malloc for IsoProtocolClientTask failed.");
282 return NULL;
283 }
284 task->taskBase.destroyTask = DestroyProtocolClientTask;
285 task->taskBase.process = Process;
286 task->taskBase.getCurTaskType = GetTaskType;
287 return (SymBaseCurTask *)task;
288 }
289