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