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 "standard_client_bind_exchange_task.h"
17 #include "hc_log.h"
18 #include "hc_types.h"
19 #include "protocol_common.h"
20 #include "standard_exchange_message_util.h"
21 
22 enum {
23     TASK_STATUS_CLIENT_BIND_EXCHANGE_BEGIN = 0,
24     TASK_STATUS_CLIENT_BIND_EXCHANGE_REQUEST,
25     TASK_STATUS_CLIENT_BIND_EXCHANGE_CONFIRM,
26 };
27 
GetTaskType(void)28 static CurTaskType GetTaskType(void)
29 {
30     return TASK_TYPE_BIND_STANDARD_EXCHANGE;
31 }
32 
ExchangeRequest(AsyBaseCurTask * task,PakeParams * params,const CJson * in,CJson * out,int * status)33 static int ExchangeRequest(AsyBaseCurTask *task, PakeParams *params, const CJson *in, CJson *out, int *status)
34 {
35     int res;
36     if (task->taskStatus != TASK_STATUS_CLIENT_BIND_EXCHANGE_BEGIN) {
37         LOGI("The message is repeated, ignore it, status: %d", task->taskStatus);
38         *status = IGNORE_MSG;
39         return HC_SUCCESS;
40     }
41     StandardBindExchangeClientTask *realTask = (StandardBindExchangeClientTask *)task;
42     CJson *data = CreateJson();
43     if (data == NULL) {
44         return HC_ERR_ALLOC_MEMORY;
45     }
46     CJson *sendToPeer = CreateJson();
47     if (sendToPeer == NULL) {
48         res = HC_ERR_ALLOC_MEMORY;
49         goto ERR;
50     }
51 
52     // parse message
53     if (params->baseParams.challengePeer.val == NULL) {
54         GOTO_ERR_AND_SET_RET(GetPeerChallenge(params, in), res);
55         GOTO_ERR_AND_SET_RET(GenerateSelfChallenge(params), res);
56         GOTO_ERR_AND_SET_RET(AddByteToJson(data, FIELD_CHALLENGE, params->baseParams.challengeSelf.val,
57             params->baseParams.challengeSelf.length), res);
58     }
59 
60     // execute
61     GOTO_ERR_AND_SET_RET(ClientRequestStandardBindExchange(params, &(realTask->params)), res);
62 
63     // package message
64     GOTO_ERR_AND_SET_RET(AddIntToJson(sendToPeer, FIELD_MESSAGE, PAKE_BIND_EXCHANGE_REQUEST), res);
65     GOTO_ERR_AND_SET_RET(PackageNonceAndCipherToJson(&(realTask->params.nonce), &(realTask->params.exInfoCipher),
66         data, FIELD_EX_AUTH_INFO), res);
67     GOTO_ERR_AND_SET_RET(AddIntToJson(data, FIELD_PEER_USER_TYPE, params->userType), res);
68     GOTO_ERR_AND_SET_RET(AddObjToJson(sendToPeer, FIELD_PAYLOAD, data), res);
69     GOTO_ERR_AND_SET_RET(AddObjToJson(out, FIELD_SEND_TO_PEER, sendToPeer), res);
70 
71     task->taskStatus = TASK_STATUS_CLIENT_BIND_EXCHANGE_REQUEST;
72     *status = CONTINUE;
73 ERR:
74     FreeJson(data);
75     FreeJson(sendToPeer);
76     return res;
77 }
78 
ExchangeConfirm(AsyBaseCurTask * task,PakeParams * params,const CJson * in,int * status)79 static int ExchangeConfirm(AsyBaseCurTask *task, PakeParams *params, const CJson *in, int *status)
80 {
81     if (task->taskStatus < TASK_STATUS_CLIENT_BIND_EXCHANGE_REQUEST) {
82         LOGE("Invalid taskStatus: %d", task->taskStatus);
83         return HC_ERR_BAD_MESSAGE;
84     }
85     if (task->taskStatus > TASK_STATUS_CLIENT_BIND_EXCHANGE_REQUEST) {
86         LOGI("The message is repeated, ignore it, status: %d", task->taskStatus);
87         *status = IGNORE_MSG;
88         return HC_SUCCESS;
89     }
90 
91     StandardBindExchangeClientTask *realTask = (StandardBindExchangeClientTask *)task;
92 
93     // parse message
94     (void)GetIntFromJson(in, FIELD_PEER_USER_TYPE, &(params->userTypePeer));
95     int res = ParseNonceAndCipherFromJson(&(realTask->params.nonce),
96         &(realTask->params.exInfoCipher), in, FIELD_EX_AUTH_INFO);
97     if (res != HC_SUCCESS) {
98         LOGE("ParseNonceAndCipherFromJson failed");
99         return res;
100     }
101 
102     // execute
103     res = ClientConfirmStandardBindExchange(params, &(realTask->params));
104     if (res != HC_SUCCESS) {
105         LOGE("ClientConfirmStandardBindExchange failed");
106         return res;
107     }
108 
109     task->taskStatus = TASK_STATUS_CLIENT_BIND_EXCHANGE_CONFIRM;
110     *status = FINISH;
111     return res;
112 }
113 
Process(struct AsyBaseCurTaskT * task,PakeParams * params,const CJson * in,CJson * out,int * status)114 static int Process(struct AsyBaseCurTaskT *task, PakeParams *params, const CJson *in, CJson *out, int *status)
115 {
116     int res = HC_SUCCESS;
117     if (task->taskStatus == TASK_STATUS_CLIENT_BIND_EXCHANGE_BEGIN) {
118         res = ExchangeRequest(task, params, in, out, status);
119         if (res != HC_SUCCESS) {
120             goto ERR;
121         }
122         return res;
123     }
124 
125     int message = 0;
126     res = GetIntFromJson(in, "message", &message);
127     if (res != HC_SUCCESS) {
128         goto ERR;
129     }
130 
131     switch (message) {
132         case PAKE_BIND_EXCHANGE_RESPONSE:
133             res = ExchangeConfirm(task, params, in, status);
134             break;
135         default:
136             res = HC_ERR_INVALID_PARAMS;
137             break;
138     }
139     if (res != HC_SUCCESS) {
140         goto ERR;
141     }
142     return res;
143 ERR:
144     FreeAndCleanKey(&(params->baseParams.sessionKey));
145     return res;
146 }
147 
DestroyStandardBindExchangeClientTask(struct AsyBaseCurTaskT * task)148 static void DestroyStandardBindExchangeClientTask(struct AsyBaseCurTaskT *task)
149 {
150     StandardBindExchangeClientTask *innerTask = (StandardBindExchangeClientTask *)task;
151     if (innerTask == NULL) {
152         return;
153     }
154 
155     DestroyStandardBindExchangeParams(&(innerTask->params));
156     HcFree(innerTask);
157 }
158 
CreateStandardBindExchangeClientTask(void)159 AsyBaseCurTask *CreateStandardBindExchangeClientTask(void)
160 {
161     StandardBindExchangeClientTask *task =
162         (StandardBindExchangeClientTask *)HcMalloc(sizeof(StandardBindExchangeClientTask), 0);
163     if (task == NULL) {
164         return NULL;
165     }
166     task->taskBase.destroyTask = DestroyStandardBindExchangeClientTask;
167     task->taskBase.process = Process;
168     task->taskBase.taskStatus = TASK_STATUS_CLIENT_BIND_EXCHANGE_BEGIN;
169     task->taskBase.getCurTaskType = GetTaskType;
170 
171     int res = InitStandardBindExchangeParams(&(task->params));
172     if (res != HC_SUCCESS) {
173         DestroyStandardBindExchangeClientTask((struct AsyBaseCurTaskT *)task);
174         return NULL;
175     }
176 
177     return (AsyBaseCurTask *)task;
178 }
179