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(&params->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(&params->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(&params->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