1 /*
2  * Copyright (c) 2020-2022 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 "distribution.h"
17 #include "securec.h"
18 #include "log.h"
19 #include "pake_client.h"
20 #include "pake_server.h"
21 #include "sts_server.h"
22 #include "exchange_auth_info.h"
23 #include "exchange_auth_info_client.h"
24 #include "add_auth_info.h"
25 #include "remove_auth_info.h"
26 #include "remove_auth_info_client.h"
27 
28 #ifdef DESC
29 #undef DESC
30 #endif
31 #define DESC(...) 1
32 
33 static int32_t proc_pake_response_message(struct hichain *handle, struct header_analysis *nav,
34     struct message *receive, struct message *send);
35 static int32_t proc_exchange_response_message(struct hichain *handle, struct header_analysis *nav,
36     struct message *receive, struct message *send);
37 static int32_t proc_remove_request_message(struct hichain *handle, struct header_analysis *nav,
38     struct message *receive, struct message *send);
39 static int32_t proc_remove_response_message(struct hichain *handle, struct header_analysis *nav,
40     struct message *receive, struct message *send);
41 static int32_t proc_inform_message(struct hichain *handle, struct header_analysis *nav,
42     struct message *receive, struct message *send);
43 static bool check_hichain_state_is_success(struct hichain *hichain, const struct header_analysis *nav);
44 static int32_t get_operation_code(const struct header_analysis *nav, const struct message *receive);
45 static bool is_message_illegal(int32_t operation_code, int32_t modular);
46 static int32_t proc_sts_response_message(struct hichain *handle, struct header_analysis *nav,
47     struct message *receive, struct message *send);
48 
49 typedef int32_t (*proc_message_func)(struct hichain *handle, struct header_analysis *nav,
50     struct message *receive, struct message *send);
51 
52 struct message_code_map {
53     uint32_t code;
54     int32_t modular;
55     bool is_request_msg;
56 };
57 
58 struct distribution_message {
59     int32_t modular;
60     bool is_request_msg;
61     proc_message_func func;
62 };
63 
64 struct check_message_powered {
65     int32_t operation_code;
66     int32_t modular;
67 };
68 
69 static const struct message_code_map G_MESSAGE_CODE_MAP[] = {
70     { PAKE_REQUEST, PAKE_MODULAR, true },
71     { PAKE_CLIENT_CONFIRM, PAKE_MODULAR, true },
72     { EXCHANGE_REQUEST, EXCHANGE_MODULAR, true },
73     { AUTH_START_REQUEST, STS_MODULAR, true },
74     { AUTH_ACK_REQUEST, STS_MODULAR, true },
75     { ADD_AUTHINFO_REQUEST, ADD_MODULAR, true },
76     { REMOVE_AUTHINFO_REQUEST, REMOVE_MODULAR, true },
77     { SEC_CLONE_START_REQUEST, SEC_CLONE_MODULAR, true },
78     { SEC_CLONE_ACK_REQUEST, SEC_CLONE_MODULAR, true },
79     { PAKE_RESPONSE, PAKE_MODULAR, false },
80     { PAKE_SERVER_CONFIRM_RESPONSE, PAKE_MODULAR, false },
81     { EXCHANGE_RESPONSE, EXCHANGE_MODULAR, false },
82     { AUTH_START_RESPONSE, STS_MODULAR, false },
83     { AUTH_ACK_RESPONSE, STS_MODULAR, false },
84     { ADD_AUTHINFO_RESPONSE, ADD_MODULAR, false },
85     { REMOVE_AUTHINFO_RESPONSE, REMOVE_MODULAR, false },
86     { SEC_CLONE_START_RESPONSE, SEC_CLONE_MODULAR, false },
87     { SEC_CLONE_ACK_RESPONSE, SEC_CLONE_MODULAR, false },
88     { INFORM_MESSAGE, INFORM_MODULAR, true }
89 };
90 
91 static const struct distribution_message G_DISTRIBUTION_MESSAGE[] = {
92     { PAKE_MODULAR, false, proc_pake_response_message },
93     { EXCHANGE_MODULAR, false, proc_exchange_response_message },
94     { REMOVE_MODULAR, true, proc_remove_request_message },
95     { INFORM_MODULAR, false, proc_inform_message },
96     { STS_MODULAR, false, proc_sts_response_message },
97     { REMOVE_MODULAR, false, proc_remove_response_message },
98 };
99 
100 #if DESC("interface")
navigate_message(uint32_t message_code)101 struct header_analysis navigate_message(uint32_t message_code)
102 {
103     struct header_analysis nav = { INVALID_MODULAR, 0, 0 };
104 
105     for (uint32_t i = 0; i < sizeof(G_MESSAGE_CODE_MAP) / sizeof(G_MESSAGE_CODE_MAP[0]); i++) {
106         if (G_MESSAGE_CODE_MAP[i].code == message_code) {
107             nav.modular = G_MESSAGE_CODE_MAP[i].modular;
108             nav.msg_type = message_code & 0xf; /* message_code & 0xf get low four bits of message code */
109             nav.is_request_msg = G_MESSAGE_CODE_MAP[i].is_request_msg;
110             break;
111         }
112     }
113     LOGI("Message code %u, nav is %d, %d, %d", message_code, nav.modular, nav.msg_type, nav.is_request_msg);
114     return nav;
115 }
116 
check_message_support(struct hichain * hichain,const struct header_analysis * nav,const struct message * receive)117 int32_t check_message_support(struct hichain *hichain, const struct header_analysis *nav,
118     const struct message *receive)
119 {
120     if (nav->modular == 0) {
121         LOGE("Receive unknow message, message code is 0x%04x", receive->msg_code);
122         return HC_UNKNOW_MESSAGE;
123     }
124 
125     if (!check_hichain_state_is_success(hichain, nav)) {
126         return HC_STATE_ERROR;
127     }
128 
129     int32_t operation_code = get_operation_code(nav, receive);
130     if (operation_code == INVALID_OPERATION_CODE) {
131         return HC_OPERATION_CODE_ERROR;
132     } else if (operation_code == NO_OPERATION_CODE) {
133         /* compare with recorded operation code and verify */
134         if (is_message_illegal(hichain->operation_code, nav->modular)) {
135             LOGE("Operation code is %d, message code is %u, it is inconsistency",
136                 hichain->operation_code, receive->msg_code);
137             return HC_MESSAGE_INCONSISTENCY;
138         }
139     } else {
140         int32_t ret = hichain->cb.confirm_receive_request(&hichain->identity, operation_code);
141         if (ret != 0) {
142             LOGE("Service does not allow response %d", operation_code);
143             return HC_SERVICE_CONFIRM_ERROR;
144         }
145         hichain->operation_code = operation_code;
146     }
147 
148     return HC_OK;
149 }
150 
proc_message(struct hichain * handle,struct header_analysis * nav,struct message * receive,struct message * send)151 int32_t proc_message(struct hichain *handle, struct header_analysis *nav,
152     struct message *receive, struct message *send)
153 {
154     for (uint32_t i = 0; i < sizeof(G_DISTRIBUTION_MESSAGE) / sizeof(G_DISTRIBUTION_MESSAGE[0]); i++) {
155         if ((nav->modular == G_DISTRIBUTION_MESSAGE[i].modular) &&
156             (nav->is_request_msg == G_DISTRIBUTION_MESSAGE[i].is_request_msg)) {
157             int32_t ret = G_DISTRIBUTION_MESSAGE[i].func(handle, nav, receive, send);
158             LOGI("Proc_message return code is %d", ret);
159             return ret;
160         }
161     }
162     return HC_UNKNOW_MESSAGE;
163 }
164 
connect_message(struct hichain * handle,struct header_analysis * nav,struct message * send)165 int32_t connect_message(struct hichain *handle, struct header_analysis *nav, struct message *send)
166 {
167     if (nav->modular != STS_MODULAR && nav->modular != PAKE_MODULAR) {
168         return HC_OK;
169     }
170     if (nav->msg_type != STS_END_MSG) {
171         return HC_OK;
172     }
173     if (nav->is_request_msg) { /* server does not need message connection */
174         return HC_OK;
175     }
176 
177     int32_t ret;
178 
179     switch (handle->operation_code) {
180         case BIND:
181             ret = send_exchange_request(handle, send);
182             LOGI("Client build exchange request message return value is %d", ret);
183             return ret;
184         case AUTHENTICATE:
185             send->msg_code = INVALID_MESSAGE;
186             return HC_OK;
187         case REMOVE_AUTHINFO:
188             ret = send_remove_request(handle, send);
189             LOGI("Client build remove auth info request message return value is %d", ret);
190             return ret;
191         default:
192             return HC_INNER_ERROR;
193     }
194 
195     return HC_OK;
196 }
197 #endif /* DESC */
198 
check_hichain_state_is_success(struct hichain * hichain,const struct header_analysis * nav)199 static bool check_hichain_state_is_success(struct hichain *hichain, const struct header_analysis *nav)
200 {
201     if ((nav->modular == PAKE_MODULAR) || (nav->modular == STS_MODULAR)) {
202         if ((hichain->state != INIT_STATE) && (hichain->state != KEY_AGREEMENT_STATE) &&
203             (hichain->last_state != INIT_STATE) && (hichain->last_state != KEY_AGREEMENT_STATE)) {
204             goto error;
205         }
206     } else {
207         if ((hichain->state != KEY_AGREEMENT_STATE) && (hichain->state != OPERATION_STATE) &&
208             (hichain->last_state != KEY_AGREEMENT_STATE) && (hichain->last_state != OPERATION_STATE)) {
209             goto error;
210         }
211     }
212     return true;
213 
214 error:
215     LOGE("Check hichain state failed, state is %d, message nav is %d-%d-%d", hichain->state, nav->modular,
216         nav->msg_type, nav->is_request_msg);
217     return false;
218 }
219 
get_operation_code(const struct header_analysis * nav,const struct message * receive)220 static int32_t get_operation_code(const struct header_analysis *nav, const struct message *receive)
221 {
222     int32_t operation_code = NO_OPERATION_CODE;
223 
224     LOGI("Receive message had operation code is %d", operation_code);
225     return operation_code;
226 }
227 
is_message_illegal(int32_t operation_code,int32_t modular)228 static bool is_message_illegal(int32_t operation_code, int32_t modular)
229 {
230     struct check_message_powered table[] = { { BIND, PAKE_MODULAR },
231                                              { BIND, EXCHANGE_MODULAR },
232                                              { AUTH_KEY_AGREEMENT, PAKE_MODULAR },
233                                              { UNBIND, STS_MODULAR },
234                                              { UNBIND, REMOVE_MODULAR },
235                                              { AUTHENTICATE, STS_MODULAR },
236                                              { ADD_AUTHINFO, STS_MODULAR },
237                                              { ADD_AUTHINFO, ADD_MODULAR },
238                                              { REMOVE_AUTHINFO, STS_MODULAR },
239                                              { REMOVE_AUTHINFO, REMOVE_MODULAR },
240                                              { SEC_CLONE_OP, STS_MODULAR },
241                                              { SEC_CLONE_OP, SEC_CLONE_MODULAR } };
242 
243     for (uint32_t i = 0; i < sizeof(table) / sizeof(table[0]); i++) {
244         if ((modular == table[i].modular) && (operation_code == table[i].operation_code)) {
245             return false;
246         }
247     }
248     return true;
249 }
250 
251 
252 /* function macro which is not called in functions */
253 #define CUT_EMPTY_FUNC(d_name, handle, nav, receive, send) \
254     { \
255         LOGE("Receive %s message, but do not support %s", (d_name), (d_name)); \
256         (void)(handle); \
257         (void)(nav); \
258         (void)(receive); \
259         (send)->msg_code = INVALID_MESSAGE; \
260         return HC_UNSUPPORT; \
261     }
262 
263 
proc_pake_response_message(struct hichain * handle,struct header_analysis * nav,struct message * receive,struct message * send)264 static int32_t proc_pake_response_message(struct hichain *handle, struct header_analysis *nav,
265     struct message *receive, struct message *send)
266 #if !(defined(_CUT_PAKE_) || defined(_CUT_PAKE_CLIENT_))
267 {
268     DBG_OUT("Object %u proc pake %d response message", pake_client_sn(handle->pake_client), nav->msg_type);
269     int32_t ret;
270 
271     if (nav->msg_type == PAKE_START_MSG) {
272         ret = send_pake_end_request(handle->pake_client, receive, send);
273     } else if (nav->msg_type == PAKE_END_MSG) {
274         ret = receive_pake_end_response(handle->pake_client, receive);
275         if (ret == HC_OK) {
276             handle->cb.set_session_key(&handle->identity, &handle->pake_client->service_key);
277             (void)memset_s(handle->pake_client->service_key.session_key, HC_SESSION_KEY_LEN, 0, HC_SESSION_KEY_LEN);
278         }
279     } else {
280         return HC_UNKNOW_MESSAGE;
281     }
282     return ret;
283 }
284 #else /* _CUT_XXX_ */
285 CUT_EMPTY_FUNC("pake response", handle, nav, receive, send);
286 #endif /* _CUT_XXX_ */
287 
288 
proc_exchange_response_message(struct hichain * handle,struct header_analysis * nav,struct message * receive,struct message * send)289 static int32_t proc_exchange_response_message(struct hichain *handle, struct header_analysis *nav,
290     struct message *receive, struct message *send)
291 #if !(defined(_CUT_PAKE_) || defined(_CUT_PAKE_CLIENT_) || defined(_CUT_EXCHANGE_) || defined(_CUT_EXCHANGE_CLIENT_))
292 {
293     DBG_OUT("Object %u proc exchange auth info response message", pake_client_sn(handle->pake_client));
294     (void)nav;
295     (void)send;
296     int32_t ret = receive_exchange_response(handle, receive);
297 
298     send->msg_code = INVALID_MESSAGE;
299     DBG_OUT("Object %u proc exchange message, error code is %d", pake_client_sn(handle->pake_client), ret);
300     return ret;
301 }
302 #else /* _CUT_XXX_ */
303 CUT_EMPTY_FUNC("exchange response", handle, nav, receive, send);
304 #endif /* _CUT_XXX_ */
305 
306 
proc_sts_response_message(struct hichain * handle,struct header_analysis * nav,struct message * receive,struct message * send)307 static int32_t proc_sts_response_message(struct hichain *handle, struct header_analysis *nav,
308     struct message *receive, struct message *send)
309 #if !(defined(_CUT_STS_) || defined(_CUT_STS_CLIENT_))
310 {
311     DBG_OUT("Object %u proc sts %d response message.", sts_client_sn(handle->sts_client), nav->msg_type);
312     int32_t ret;
313 
314     if (nav->msg_type == STS_START_MSG) {
315         ret = send_sts_end_request(handle->sts_client, receive, send);
316     } else if (nav->msg_type == STS_END_MSG) {
317         ret = receive_sts_end_response(handle->sts_client, receive);
318         if (ret == HC_OK) {
319             handle->cb.set_session_key(&handle->identity, &handle->sts_client->service_key);
320         }
321     } else {
322         return HC_UNKNOW_MESSAGE;
323     }
324     return ret;
325 }
326 #else /* _CUT_XXX_ */
327 CUT_EMPTY_FUNC("sts request", handle, nav, receive, send);
328 #endif /* _CUT_XXX_ */
329 
330 
proc_remove_request_message(struct hichain * handle,struct header_analysis * nav,struct message * receive,struct message * send)331 static int32_t proc_remove_request_message(struct hichain *handle, struct header_analysis *nav,
332     struct message *receive, struct message *send)
333 #if !(defined(_CUT_STS_) || defined(_CUT_STS_SERVER_) || defined(_CUT_REMOVE_) || defined(_CUT_REMOVE_SERVER_))
334 {
335     DBG_OUT("Object %u proc remove auth info request message", sts_server_sn(handle->sts_server));
336     (void)nav;
337     int32_t ret = send_remove_response(handle, receive, send);
338 
339     DBG_OUT("Object %u proc remove auth info message, error code is %d", sts_server_sn(handle->sts_server), ret);
340     return ret;
341 }
342 #else /* _CUT_XXX_ */
343 CUT_EMPTY_FUNC("remove auth info request", handle, nav, receive, send);
344 #endif /* _CUT_XXX_ */
345 
proc_remove_response_message(struct hichain * handle,struct header_analysis * nav,struct message * receive,struct message * send)346 static int32_t proc_remove_response_message(struct hichain *handle, struct header_analysis *nav,
347                                             struct message *receive, struct message *send)
348 #if !(defined(_CUT_STS_) || defined(_CUT_STS_CLIENT_) || defined(_CUT_REMOVE_) || defined(_CUT_REMOVE_CLIENT_))
349 {
350     (void)nav;
351     int32_t ret = receive_remove_response(handle, receive);
352     if (ret != HC_OK) {
353         LOGE("Object %u proc add auth info request message, error code is %d",
354              sts_client_sn(handle->sts_client), ret);
355         return ret;
356     }
357     send->msg_code = INVALID_MESSAGE; /* remove_auth_info receives data and process ends, does not need to send */
358 
359     return HC_OK;
360 }
361 #else /* _CUT_XXX_ */
362 CUT_EMPTY_FUNC("remove auth info response", handle, nav, receive, send);
363 #endif /* _CUT_XXX_ */
364 
365 
proc_inform_message(struct hichain * handle,struct header_analysis * nav,struct message * receive,struct message * send)366 static int32_t proc_inform_message(struct hichain *handle, struct header_analysis *nav, struct message *receive,
367     struct message *send)
368 {
369     (void)handle;
370     (void)nav;
371     (void)receive;
372     send->msg_code = INVALID_MESSAGE;
373     LOGE("Receive inform message");
374     return HC_OK;
375 }
376