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