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_server_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_SERVER_BIND_EXCHANGE_BEGIN = 0,
24 TASK_STATUS_SERVER_BIND_EXCHANGE_START,
25 TASK_STATUS_SERVER_BIND_EXCHANGE_RESPONSE,
26 };
27
GetTaskType(void)28 static CurTaskType GetTaskType(void)
29 {
30 return TASK_TYPE_BIND_STANDARD_EXCHANGE;
31 }
32
ExchangeStart(AsyBaseCurTask * task,PakeParams * params,CJson * out,int * status)33 static int ExchangeStart(AsyBaseCurTask *task, PakeParams *params, CJson *out, int *status)
34 {
35 int res = HC_SUCCESS;
36 if (task->taskStatus != TASK_STATUS_SERVER_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
42 if (params->baseParams.challengeSelf.val == NULL) {
43 res = GenerateSelfChallenge(params);
44 if (res != HC_SUCCESS) {
45 LOGE("GenerateSelfChallenge failed");
46 return res;
47 }
48 CJson *payload = GetObjFromJson(out, FIELD_PAYLOAD);
49 if (payload == NULL) {
50 LOGE("Get payload failed.");
51 return HC_ERR_JSON_GET;
52 }
53 if (AddByteToJson(payload, FIELD_CHALLENGE,
54 params->baseParams.challengeSelf.val, params->baseParams.challengeSelf.length) != HC_SUCCESS) {
55 LOGE("Failed to add self challenge to payload.");
56 return HC_ERR_JSON_ADD;
57 }
58 }
59
60 task->taskStatus = TASK_STATUS_SERVER_BIND_EXCHANGE_START;
61 *status = CONTINUE;
62 return res;
63 }
64
ExchangeResponse(AsyBaseCurTask * task,PakeParams * params,const CJson * in,CJson * out,int * status)65 static int ExchangeResponse(AsyBaseCurTask *task, PakeParams *params, const CJson *in, CJson *out, int *status)
66 {
67 int res = HC_SUCCESS;
68 CJson *data = NULL;
69 CJson *sendToPeer = NULL;
70
71 if (task->taskStatus < TASK_STATUS_SERVER_BIND_EXCHANGE_START) {
72 return HC_ERR_BAD_MESSAGE;
73 }
74 if (task->taskStatus > TASK_STATUS_SERVER_BIND_EXCHANGE_START) {
75 LOGI("The message is repeated, ignore it, status: %d", task->taskStatus);
76 *status = IGNORE_MSG;
77 return HC_SUCCESS;
78 }
79
80 StandardBindExchangeServerTask *realTask = (StandardBindExchangeServerTask *)task;
81
82 // parse message
83 /*
84 * If failing to get userTypePeer, use the default value(DEVICE_TYPE_ACCESSORY),
85 * which was assigned at initialization.
86 */
87 (void)GetIntFromJson(in, FIELD_PEER_USER_TYPE, &(params->userTypePeer));
88 if (params->baseParams.challengePeer.val == NULL) {
89 GOTO_ERR_AND_SET_RET(GetPeerChallenge(params, in), res);
90 }
91 GOTO_ERR_AND_SET_RET(ParseNonceAndCipherFromJson(&(realTask->params.nonce), &(realTask->params.exInfoCipher),
92 in, FIELD_EX_AUTH_INFO), res);
93
94 // execute
95 res = ServerResponseStandardBindExchange(params, &(realTask->params));
96 if (res != HC_SUCCESS) {
97 LOGE("ServerResponseStandardBindExchange failed");
98 return res;
99 }
100
101 sendToPeer = CreateJson();
102 if (sendToPeer == NULL) {
103 res = HC_ERR_ALLOC_MEMORY;
104 goto ERR;
105 }
106 GOTO_ERR_AND_SET_RET(AddIntToJson(sendToPeer, FIELD_MESSAGE, PAKE_BIND_EXCHANGE_RESPONSE), res);
107 data = CreateJson();
108 if (data == NULL) {
109 res = HC_ERR_ALLOC_MEMORY;
110 goto ERR;
111 }
112 GOTO_ERR_AND_SET_RET(PackageNonceAndCipherToJson(&(realTask->params.nonce), &(realTask->params.exInfoCipher),
113 data, FIELD_EX_AUTH_INFO), res);
114 GOTO_ERR_AND_SET_RET(AddIntToJson(data, FIELD_PEER_USER_TYPE, params->userType), res);
115 GOTO_ERR_AND_SET_RET(AddObjToJson(sendToPeer, "payload", data), res);
116 GOTO_ERR_AND_SET_RET(AddObjToJson(out, FIELD_SEND_TO_PEER, sendToPeer), res);
117
118 task->taskStatus = TASK_STATUS_SERVER_BIND_EXCHANGE_RESPONSE;
119 *status = FINISH;
120 ERR:
121 FreeJson(data);
122 FreeJson(sendToPeer);
123 return res;
124 }
125
Process(struct AsyBaseCurTaskT * task,PakeParams * params,const CJson * in,CJson * out,int * status)126 static int Process(struct AsyBaseCurTaskT *task, PakeParams *params, const CJson *in, CJson *out, int *status)
127 {
128 int res;
129 if (task->taskStatus == TASK_STATUS_SERVER_BIND_EXCHANGE_BEGIN) {
130 res = ExchangeStart(task, params, out, status);
131 if (res != HC_SUCCESS) {
132 goto ERR;
133 }
134 return res;
135 }
136
137 int message = 0;
138 res = GetIntFromJson(in, "message", &message);
139 if (res != HC_SUCCESS) {
140 goto ERR;
141 }
142
143 switch (message) {
144 case PAKE_BIND_EXCHANGE_REQUEST:
145 res = ExchangeResponse(task, params, in, out, status);
146 break;
147 default:
148 res = HC_ERR_INVALID_PARAMS;
149 break;
150 }
151 if (res != HC_SUCCESS) {
152 goto ERR;
153 }
154 return res;
155 ERR:
156 FreeAndCleanKey(&(params->baseParams.sessionKey));
157 return res;
158 }
159
DestroyStandardBindExchangeServerTask(struct AsyBaseCurTaskT * task)160 static void DestroyStandardBindExchangeServerTask(struct AsyBaseCurTaskT *task)
161 {
162 StandardBindExchangeServerTask *innerTask = (StandardBindExchangeServerTask *)task;
163 if (innerTask == NULL) {
164 return;
165 }
166
167 DestroyStandardBindExchangeParams(&(innerTask->params));
168 HcFree(innerTask);
169 }
170
CreateStandardBindExchangeServerTask(void)171 AsyBaseCurTask *CreateStandardBindExchangeServerTask(void)
172 {
173 StandardBindExchangeServerTask *task =
174 (StandardBindExchangeServerTask *)HcMalloc(sizeof(StandardBindExchangeServerTask), 0);
175 if (task == NULL) {
176 return NULL;
177 }
178 task->taskBase.destroyTask = DestroyStandardBindExchangeServerTask;
179 task->taskBase.process = Process;
180 task->taskBase.taskStatus = TASK_STATUS_SERVER_BIND_EXCHANGE_BEGIN;
181 task->taskBase.getCurTaskType = GetTaskType;
182
183 int res = InitStandardBindExchangeParams(&(task->params));
184 if (res != 0) {
185 DestroyStandardBindExchangeServerTask((struct AsyBaseCurTaskT *)task);
186 return NULL;
187 }
188
189 return (AsyBaseCurTask *)task;
190 }
191
192