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_unbind_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_UNBIND_EXCHANGE_BEGIN = 0,
24 TASK_STATUS_CLIENT_UNBIND_EXCHANGE_REQUEST,
25 TASK_STATUS_CLIENT_UNBIND_EXCHANGE_CONFIRM,
26 };
27
GetTaskType(void)28 static CurTaskType GetTaskType(void)
29 {
30 return TASK_TYPE_UNBIND_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_UNBIND_EXCHANGE_BEGIN) {
37 LOGI("The message is repeated, ignore it, status: %d", task->taskStatus);
38 *status = IGNORE_MSG;
39 return HC_SUCCESS;
40 }
41 StandardUnbindExchangeClientTask *realTask = (StandardUnbindExchangeClientTask *)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 res = ClientRequestStandardUnbindExchange(params, &(realTask->params));
62 if (res != HC_SUCCESS) {
63 LOGE("ClientRequestStandardUnbindExchange failed");
64 goto ERR;
65 }
66
67 // package message
68 GOTO_ERR_AND_SET_RET(AddIntToJson(sendToPeer, FIELD_MESSAGE, PAKE_UNBIND_EXCHANGE_REQUEST), res);
69 GOTO_ERR_AND_SET_RET(PackageNonceAndCipherToJson(&(realTask->params.nonce), &(realTask->params.exRmvCipher),
70 data, FIELD_RMV_AUTH_INFO), res);
71 GOTO_ERR_AND_SET_RET(AddObjToJson(sendToPeer, FIELD_PAYLOAD, data), res);
72 GOTO_ERR_AND_SET_RET(AddObjToJson(out, FIELD_SEND_TO_PEER, sendToPeer), res);
73
74 task->taskStatus = TASK_STATUS_CLIENT_UNBIND_EXCHANGE_REQUEST;
75 *status = CONTINUE;
76 ERR:
77 FreeJson(data);
78 FreeJson(sendToPeer);
79 return res;
80 }
81
ExchangeConfirm(AsyBaseCurTask * task,PakeParams * params,const CJson * in,int * status)82 static int ExchangeConfirm(AsyBaseCurTask *task, PakeParams *params, const CJson *in, int *status)
83 {
84 if (task->taskStatus < TASK_STATUS_CLIENT_UNBIND_EXCHANGE_REQUEST) {
85 LOGE("task status failed");
86 return HC_ERR_BAD_MESSAGE;
87 }
88
89 if (task->taskStatus > TASK_STATUS_CLIENT_UNBIND_EXCHANGE_REQUEST) {
90 LOGI("The message is repeated, ignore it, status: %d", task->taskStatus);
91 *status = IGNORE_MSG;
92 return HC_SUCCESS;
93 }
94
95 StandardUnbindExchangeClientTask *realTask = (StandardUnbindExchangeClientTask *)task;
96
97 // parse message
98 int res = ParseNonceAndCipherFromJson(&(realTask->params.nonce), &(realTask->params.resultCipher),
99 in, FIELD_RMV_RETURN);
100 if (res != HC_SUCCESS) {
101 LOGE("ParseNonceAndCipherFromJson failed");
102 return res;
103 }
104
105 // execute
106 res = ClientConfirmStandardUnbindExchange(params, &(realTask->params));
107 if (res != HC_SUCCESS) {
108 LOGE("ClientRequestStandardUnbindExchange failed");
109 return res;
110 }
111
112 task->taskStatus = TASK_STATUS_CLIENT_UNBIND_EXCHANGE_CONFIRM;
113 *status = FINISH;
114 return res;
115 }
116
Process(struct AsyBaseCurTaskT * task,PakeParams * params,const CJson * in,CJson * out,int * status)117 static int Process(struct AsyBaseCurTaskT *task, PakeParams *params, const CJson *in, CJson *out, int *status)
118 {
119 int res;
120 if (task->taskStatus == TASK_STATUS_CLIENT_UNBIND_EXCHANGE_BEGIN) {
121 res = ExchangeRequest(task, params, in, out, status);
122 if (res != HC_SUCCESS) {
123 goto ERR;
124 }
125 return res;
126 }
127
128 int message = 0;
129 res = GetIntFromJson(in, "message", &message);
130 if (res != HC_SUCCESS) {
131 goto ERR;
132 }
133
134 switch (message) {
135 case PAKE_UNBIND_EXCHANGE_RESPONSE:
136 res = ExchangeConfirm(task, params, in, status);
137 break;
138 default:
139 res = HC_ERR_INVALID_PARAMS;
140 break;
141 }
142 if (res != HC_SUCCESS) {
143 goto ERR;
144 }
145 return res;
146 ERR:
147 FreeAndCleanKey(&(params->baseParams.sessionKey));
148 return res;
149 }
150
DestroyStandardUnbindExchangeClientTask(struct AsyBaseCurTaskT * task)151 static void DestroyStandardUnbindExchangeClientTask(struct AsyBaseCurTaskT *task)
152 {
153 StandardUnbindExchangeClientTask *innerTask = (StandardUnbindExchangeClientTask *)task;
154 if (innerTask == NULL) {
155 return;
156 }
157
158 DestroyStandardUnbindExchangeParams(&(innerTask->params));
159 HcFree(innerTask);
160 }
161
CreateStandardUnbindExchangeClientTask(void)162 AsyBaseCurTask *CreateStandardUnbindExchangeClientTask(void)
163 {
164 StandardUnbindExchangeClientTask *task =
165 (StandardUnbindExchangeClientTask *)HcMalloc(sizeof(StandardUnbindExchangeClientTask), 0);
166 if (task == NULL) {
167 return NULL;
168 }
169 task->taskBase.destroyTask = DestroyStandardUnbindExchangeClientTask;
170 task->taskBase.process = Process;
171 task->taskBase.taskStatus = TASK_STATUS_CLIENT_UNBIND_EXCHANGE_BEGIN;
172 task->taskBase.getCurTaskType = GetTaskType;
173
174 int res = InitStandardUnbindExchangeParams(&(task->params));
175 if (res != HC_SUCCESS) {
176 DestroyStandardUnbindExchangeClientTask((struct AsyBaseCurTaskT *)task);
177 return NULL;
178 }
179
180 return (AsyBaseCurTask *)task;
181 }