From 30300b7591014343229ca1b182036fd0dd3024c4 Mon Sep 17 00:00:00 2001 From: mamingshuai Date: Wed, 2 Jun 2021 00:43:15 +0800 Subject: [PATCH] update OpenHarmony 2.0 Canary --- .gitattributes | 15 + BUILD.gn | 41 + LICENSE | 0 README.md | 183 +- README_zh.md | 183 +- deviceauth_env.gni | 18 + figures/en-us_deviceauth_architecture.png | Bin 0 -> 38443 bytes figures/icon-caution.gif | Bin 0 -> 580 bytes figures/zh-cn_deviceauth_architecture.png | Bin 0 -> 143774 bytes frameworks/deviceauth_lite/source/hichain.c | 0 .../source/key_agreement/sts_server.h | 0 frameworks/inc/ipc_adapt.h | 97 + frameworks/inc/ipc_callback_proxy.h | 34 + frameworks/inc/ipc_callback_stub.h | 34 + frameworks/inc/ipc_dev_auth_proxy.h | 56 + frameworks/inc/ipc_dev_auth_stub.h | 62 + frameworks/inc/ipc_iface.h | 43 + frameworks/inc/ipc_sdk.h | 105 + frameworks/inc/ipc_service.h | 26 + frameworks/src/deviceauth_service.rc | 21 + frameworks/src/ipc_adapt.cpp | 1477 ++++++++++ frameworks/src/ipc_callback_proxy.cpp | 50 + frameworks/src/ipc_callback_stub.cpp | 74 + frameworks/src/ipc_dev_auth_proxy.cpp | 148 + frameworks/src/ipc_dev_auth_stub.cpp | 298 ++ frameworks/src/ipc_sdk.c | 2125 ++++++++++++++ frameworks/src/ipc_service.c | 1327 +++++++++ hals/BUILD.gn | 94 + hals/deviceauth_hals.gni | 30 + hals/inc/common/alg_defs.h | 151 + hals/inc/common/alg_loader.h | 23 + hals/inc/common/common_util.h | 56 + hals/inc/common/hc_error.h | 45 + hals/inc/common/hc_parcel.h | 88 + hals/inc/common/hc_string.h | 100 + hals/inc/common/hc_task_thread.h | 46 + hals/inc/common/hc_tlv_parser.h | 313 +++ hals/inc/common/hc_vector.h | 172 ++ hals/inc/common/huks_adapter.h | 81 + hals/inc/common/json_utils.h | 98 + hals/inc/dev_info/3516/hc_dev_info.h | 43 + hals/inc/dev_info/watch/hc_dev_info.h | 36 + hals/inc/linux/crypto_hash_to_point.h | 32 + hals/inc/linux/hc_condition.h | 45 + hals/inc/linux/hc_file.h | 49 + hals/inc/linux/hc_init_protection.h | 33 + hals/inc/linux/hc_log.h | 43 + hals/inc/linux/hc_mutex.h | 38 + hals/inc/linux/hc_thread.h | 51 + hals/inc/linux/hc_time.h | 37 + hals/inc/linux/hc_types.h | 46 + hals/inc/liteos/hc_condition.h | 34 + hals/inc/liteos/hc_file.h | 41 + hals/inc/liteos/hc_init_protection.h | 33 + hals/inc/liteos/hc_log.h | 25 + hals/inc/liteos/hc_mutex.h | 31 + hals/inc/liteos/hc_thread.h | 44 + hals/inc/liteos/hc_time.h | 30 + hals/inc/liteos/hc_types.h | 37 + hals/src/common/alg_loader.c | 22 + hals/src/common/common_util.c | 94 + hals/src/common/hc_parcel.c | 557 ++++ hals/src/common/hc_string.c | 175 ++ hals/src/common/hc_task_thread.c | 149 + hals/src/common/hc_tlv_parser.c | 476 ++++ hals/src/common/json_utils.c | 551 ++++ hals/src/dev_info/3516/hc_dev_info.c | 44 + hals/src/dev_info/watch/hc_dev_info.c | 52 + hals/src/linux/L2/crypto_hash_to_point.c | 382 +++ hals/src/linux/L2/huks_adapter.c | 1172 ++++++++ hals/src/linux/hc_condition.c | 166 ++ hals/src/linux/hc_file.c | 201 ++ hals/src/linux/hc_init_protection.c | 45 + hals/src/linux/hc_mutex.c | 62 + hals/src/linux/hc_thread.c | 154 + hals/src/linux/hc_time.c | 57 + hals/src/linux/hc_types.c | 56 + hals/src/liteos/L0/hc_init_protection.c | 89 + hals/src/liteos/L0/huks_adapter.c | 554 ++++ hals/src/liteos/L1/hc_init_protection.c | 46 + hals/src/liteos/hc_condition.c | 58 + hals/src/liteos/hc_file.c | 215 ++ hals/src/liteos/hc_mutex.c | 54 + hals/src/liteos/hc_thread.c | 143 + hals/src/liteos/hc_time.c | 49 + hals/src/liteos/hc_types.c | 51 + interfaces/innerkits/device_auth.h | 166 ++ interfaces/innerkits/device_auth_defines.h | 136 + ohos.build | 19 + services/BUILD.gn | 125 + .../inc/broadcast_manager/broadcast_manager.h | 39 + .../inc/callback_manager/callback_manager.h | 31 + .../inc/channel_manager/channel_manager.h | 38 + .../soft_bus_channel/soft_bus_channel.h | 38 + services/common/inc/common_defs.h | 242 ++ services/common/inc/data_base/database.h | 121 + .../common/inc/data_base/database_manager.h | 107 + .../src/broadcast_manager/broadcast_manager.c | 395 +++ .../broadcast_manager_mock.c | 53 + .../src/callback_manager/callback_manager.c | 97 + .../src/channel_manager/channel_manager.c | 212 ++ .../soft_bus_channel/soft_bus_channel.c | 243 ++ .../soft_bus_channel_mock.c | 41 + .../common/src/data_base/database_manager.c | 2466 +++++++++++++++++ services/device_auth.c | 1780 ++++++++++++ services/deviceauth.gni | 149 + .../account_related_group_auth.h | 34 + .../account_unrelated_group_auth.h | 31 + services/group_auth/inc/base_group_auth.h | 35 + .../inc/group_auth_common_defines.h | 34 + services/group_auth/inc/group_auth_manager.h | 28 + .../account_related_group_auth_mock.c | 21 + .../account_unrelated_group_auth.c | 447 +++ .../account_unrelated_group_auth_mock.c | 21 + .../group_auth_manager/group_auth_manager.c | 94 + .../group_auth_manager_lite.c | 92 + .../account_related_group_common.h | 26 + .../account_related_group_manager.h | 33 + .../account_related/across_account_group.h | 30 + .../account_related/identical_account_group.h | 30 + .../account_unrelated_group_manager.h | 38 + .../account_unrelated/peer_to_peer_group.h | 37 + services/group_manager/inc/base_group.h | 26 + services/group_manager/inc/group_common.h | 64 + services/group_manager/inc/group_manager.h | 65 + .../account_related_group_manager_mock.c | 33 + .../across_account_group_mock.c | 37 + .../identical_account_group_mock.c | 26 + .../account_unrelated_group_manager.c | 162 ++ .../account_unrelated_group_manager_mock.c | 33 + .../peer_to_peer_group/peer_to_peer_group.c | 852 ++++++ .../peer_to_peer_group_mock.c | 26 + .../src/group_manager/group_common.c | 519 ++++ .../src/group_manager/group_manager.c | 929 +++++++ .../group_manager_mock/group_manager_mock.c | 38 + .../module/inc/das_module/base_sub_task.h | 32 + services/module/inc/das_module/das_common.h | 37 + services/module/inc/das_module/das_module.h | 33 + .../inc/das_module/das_module_defines.h | 91 + .../module/inc/das_module/das_version_util.h | 45 + .../das_module/iso_task/iso_base_cur_task.h | 62 + .../inc/das_module/iso_task/iso_client_task.h | 30 + .../iso_client_protocol_task.h | 27 + .../iso_server_protocol_task.h | 27 + .../inc/das_module/iso_task/iso_server_task.h | 30 + .../inc/das_module/iso_task/iso_task_common.h | 36 + .../inc/das_module/iso_task/iso_task_main.h | 27 + .../iso_client_bind_exchange_task.h | 28 + .../iso_client_unbind_exchange_task.h | 27 + .../iso_server_bind_exchange_task.h | 27 + .../iso_server_unbind_exchange_task.h | 27 + .../pake_task/common_standard_bind_exchange.h | 42 + .../common_standard_unbind_exchange.h | 42 + .../pake_task/das_asy_token_manager.h | 31 + .../new_pake_client_protocol_task.h | 27 + .../new_pake_task/new_pake_client_task.h | 31 + .../new_pake_protocol_task_common.h | 25 + .../new_pake_server_protocol_task.h | 27 + .../new_pake_task/new_pake_server_task.h | 31 + .../new_pake_task/new_pake_task_main.h | 26 + .../das_module/pake_task/pake_base_cur_task.h | 46 + .../das_module/pake_task/pake_message_util.h | 32 + .../pake_task/pake_client_protocol_task.h | 27 + .../pake_task/pake_task/pake_client_task.h | 31 + .../pake_task/pake_protocol_task_common.h | 25 + .../pake_task/pake_server_protocol_task.h | 27 + .../pake_task/pake_task/pake_server_task.h | 31 + .../pake_task/pake_task/pake_task_main.h | 26 + .../das_module/pake_task/pake_task_common.h | 27 + .../standard_client_bind_exchange_task.h | 29 + .../standard_client_unbind_exchange_task.h | 29 + .../standard_exchange_message_util.h | 29 + .../standard_server_bind_exchange_task.h | 29 + .../standard_server_unbind_exchange_task.h | 29 + services/module/inc/das_module/task_main.h | 43 + services/module/inc/dev_auth_module_manager.h | 50 + services/module/inc/module_common.h | 23 + .../iso_protocol/iso_protocol_common.h | 45 + .../new_pake_protocol_common.h | 32 + .../new_pake_protocol/new_pake_protocol_dl.h | 27 + .../new_pake_protocol/new_pake_protocol_ec.h | 27 + .../inc/protocol/pake_protocol/pake_defs.h | 71 + .../pake_protocol/pake_protocol_common.h | 32 + .../pake_protocol/pake_protocol_dl.h | 27 + .../pake_protocol/pake_protocol_ec.h | 27 + .../module/inc/protocol/protocol_common.h | 42 + services/module/inc/tcis_module/auth_common.h | 104 + services/module/inc/tcis_module/task_base.h | 37 + .../tcis_auth_token_manager.h | 90 + services/module/inc/tcis_module/tcis_module.h | 57 + .../inc/tcis_module/tcis_module_defines.h | 57 + services/module/inc/version_util.h | 39 + services/module/src/das_module/das_common.c | 421 +++ services/module/src/das_module/das_module.c | 129 + .../module/src/das_module/das_version_util.c | 177 ++ .../src/das_module/iso_task/iso_client_task.c | 142 + .../iso_client_protocol_task.c | 298 ++ .../iso_server_protocol_task.c | 246 ++ .../src/das_module/iso_task/iso_server_task.c | 161 ++ .../src/das_module/iso_task/iso_task_common.c | 633 +++++ .../src/das_module/iso_task/iso_task_main.c | 103 + .../iso_client_bind_exchange_task.c | 252 ++ .../iso_client_unbind_exchange_task.c | 216 ++ .../iso_server_bind_exchange_task.c | 262 ++ .../iso_server_unbind_exchange_task.c | 196 ++ .../iso_task_mock/iso_task_main_mock.c | 34 + .../new_pake_task_main_mock.c | 28 + .../das_module/pake_task/pake_message_util.c | 205 ++ .../pake_task/pake_task/pake_client_task.c | 170 ++ .../pake_client_protocol_task.c | 273 ++ .../pake_protocol_task_common.c | 100 + .../pake_server_protocol_task.c | 232 ++ .../pake_task/pake_task/pake_server_task.c | 169 ++ .../pake_task/pake_task/pake_task_main.c | 43 + .../das_module/pake_task/pake_task_common.c | 383 +++ .../pake_task_mock/pake_task_main_mock.c | 28 + .../common_standard_bind_exchange.c | 533 ++++ .../common_standard_unbind_exchange.c | 334 +++ .../das_asy_token_manager.c | 173 ++ .../standard_client_bind_exchange_task.c | 181 ++ .../standard_client_unbind_exchange_task.c | 178 ++ .../standard_exchange_message_util.c | 125 + .../standard_server_bind_exchange_task.c | 188 ++ .../standard_server_unbind_exchange_task.c | 186 ++ .../standard_exchange_task_mock.c | 45 + services/module/src/das_module/task_main.c | 532 ++++ .../src/das_module_mock/das_module_mock.c | 26 + services/module/src/dev_auth_module_manager.c | 349 +++ services/module/src/module_common.c | 37 + .../iso_protocol/iso_protocol_common.c | 247 ++ .../new_pake_protocol_dl_mock.c | 41 + .../new_pake_protocol_ec_mock.c | 40 + .../pake_protocol/pake_protocol_common.c | 400 +++ .../pake_protocol_dl/pake_protocol_dl.c | 133 + .../pake_protocol_dl_mock.c | 40 + .../pake_protocol_ec/pake_protocol_ec.c | 118 + .../pake_protocol_ec_mock.c | 40 + .../module/src/protocol/protocol_common.c | 30 + .../src/tcis_module_mock/tcis_module_mock.c | 26 + services/module/src/version_util.c | 148 + .../inc/auth_session/auth_session_client.h | 23 + .../inc/auth_session/auth_session_common.h | 38 + .../inc/auth_session/auth_session_server.h | 28 + .../inc/auth_session/auth_session_util.h | 29 + .../session/inc/auth_session_common_defines.h | 43 + .../session/inc/auth_session_common_util.h | 27 + .../auth_session_client_lite.h | 23 + .../auth_session_common_lite.h | 39 + .../auth_session_server_lite.h | 23 + services/session/inc/base_session.h | 46 + .../inc/bind_session/bind_session_client.h | 23 + .../inc/bind_session/bind_session_common.h | 52 + .../inc/bind_session/bind_session_server.h | 23 + .../bind_session_client_lite.h | 23 + .../bind_session_common_lite.h | 42 + .../bind_session_server_lite.h | 23 + .../key_agree_session_client.h | 23 + .../key_agree_session_common.h | 42 + .../key_agree_session_server.h | 23 + services/session/inc/session_common.h | 23 + services/session/inc/session_manager.h | 38 + .../src/auth_session/auth_session_client.c | 218 ++ .../src/auth_session/auth_session_common.c | 831 ++++++ .../src/auth_session/auth_session_server.c | 311 +++ .../src/auth_session/auth_session_util.c | 111 + .../session/src/auth_session_common_util.c | 131 + .../auth_session_client_lite.c | 76 + .../auth_session_common_lite.c | 373 +++ .../auth_session_server_lite.c | 180 ++ .../auth_session_client_lite_mock.c | 25 + .../auth_session_server_lite_mock.c | 25 + .../auth_session_client_mock.c | 25 + .../auth_session_server_mock.c | 25 + .../src/bind_session/bind_session_client.c | 198 ++ .../src/bind_session/bind_session_common.c | 1387 +++++++++ .../src/bind_session/bind_session_server.c | 494 ++++ .../bind_session_client_lite.c | 106 + .../bind_session_common_lite.c | 351 +++ .../bind_session_server_lite.c | 192 ++ .../bind_session_client_lite_mock.c | 25 + .../bind_session_server_lite_mock.c | 25 + .../bind_session_client_mock.c | 25 + .../bind_session_server_mock.c | 25 + .../key_agree_session_client_mock.c | 25 + .../key_agree_session_server_mock.c | 25 + services/session/src/session_common.c | 28 + services/session/src/session_manager.c | 349 +++ test/unittest/deviceauth/BUILD.gn | 64 + .../include/deviceauth_standard_test.h | 108 + .../deviceauth/include/deviceauth_test_mock.h | 26 + .../source/deviceauth_standard_test.cpp | 1524 ++++++++++ .../source/deviceauth_test_mock.cpp | 47 + 292 files changed, 43544 insertions(+), 86 deletions(-) create mode 100644 .gitattributes create mode 100644 BUILD.gn mode change 100755 => 100644 LICENSE create mode 100644 deviceauth_env.gni create mode 100755 figures/en-us_deviceauth_architecture.png create mode 100755 figures/icon-caution.gif create mode 100755 figures/zh-cn_deviceauth_architecture.png mode change 100644 => 100755 frameworks/deviceauth_lite/source/hichain.c mode change 100644 => 100755 frameworks/deviceauth_lite/source/key_agreement/sts_server.h create mode 100644 frameworks/inc/ipc_adapt.h create mode 100644 frameworks/inc/ipc_callback_proxy.h create mode 100644 frameworks/inc/ipc_callback_stub.h create mode 100644 frameworks/inc/ipc_dev_auth_proxy.h create mode 100644 frameworks/inc/ipc_dev_auth_stub.h create mode 100644 frameworks/inc/ipc_iface.h create mode 100644 frameworks/inc/ipc_sdk.h create mode 100644 frameworks/inc/ipc_service.h create mode 100644 frameworks/src/deviceauth_service.rc create mode 100644 frameworks/src/ipc_adapt.cpp create mode 100644 frameworks/src/ipc_callback_proxy.cpp create mode 100644 frameworks/src/ipc_callback_stub.cpp create mode 100644 frameworks/src/ipc_dev_auth_proxy.cpp create mode 100644 frameworks/src/ipc_dev_auth_stub.cpp create mode 100644 frameworks/src/ipc_sdk.c create mode 100644 frameworks/src/ipc_service.c create mode 100644 hals/BUILD.gn create mode 100644 hals/deviceauth_hals.gni create mode 100644 hals/inc/common/alg_defs.h create mode 100644 hals/inc/common/alg_loader.h create mode 100755 hals/inc/common/common_util.h create mode 100755 hals/inc/common/hc_error.h create mode 100755 hals/inc/common/hc_parcel.h create mode 100755 hals/inc/common/hc_string.h create mode 100644 hals/inc/common/hc_task_thread.h create mode 100755 hals/inc/common/hc_tlv_parser.h create mode 100755 hals/inc/common/hc_vector.h create mode 100644 hals/inc/common/huks_adapter.h create mode 100644 hals/inc/common/json_utils.h create mode 100644 hals/inc/dev_info/3516/hc_dev_info.h create mode 100644 hals/inc/dev_info/watch/hc_dev_info.h create mode 100644 hals/inc/linux/crypto_hash_to_point.h create mode 100755 hals/inc/linux/hc_condition.h create mode 100644 hals/inc/linux/hc_file.h create mode 100644 hals/inc/linux/hc_init_protection.h create mode 100644 hals/inc/linux/hc_log.h create mode 100755 hals/inc/linux/hc_mutex.h create mode 100755 hals/inc/linux/hc_thread.h create mode 100644 hals/inc/linux/hc_time.h create mode 100755 hals/inc/linux/hc_types.h create mode 100755 hals/inc/liteos/hc_condition.h create mode 100755 hals/inc/liteos/hc_file.h create mode 100644 hals/inc/liteos/hc_init_protection.h create mode 100755 hals/inc/liteos/hc_log.h create mode 100755 hals/inc/liteos/hc_mutex.h create mode 100755 hals/inc/liteos/hc_thread.h create mode 100755 hals/inc/liteos/hc_time.h create mode 100755 hals/inc/liteos/hc_types.h create mode 100644 hals/src/common/alg_loader.c create mode 100755 hals/src/common/common_util.c create mode 100755 hals/src/common/hc_parcel.c create mode 100644 hals/src/common/hc_string.c create mode 100755 hals/src/common/hc_task_thread.c create mode 100755 hals/src/common/hc_tlv_parser.c create mode 100755 hals/src/common/json_utils.c create mode 100755 hals/src/dev_info/3516/hc_dev_info.c create mode 100755 hals/src/dev_info/watch/hc_dev_info.c create mode 100644 hals/src/linux/L2/crypto_hash_to_point.c create mode 100644 hals/src/linux/L2/huks_adapter.c create mode 100644 hals/src/linux/hc_condition.c create mode 100644 hals/src/linux/hc_file.c create mode 100755 hals/src/linux/hc_init_protection.c create mode 100644 hals/src/linux/hc_mutex.c create mode 100644 hals/src/linux/hc_thread.c create mode 100755 hals/src/linux/hc_time.c create mode 100755 hals/src/linux/hc_types.c create mode 100755 hals/src/liteos/L0/hc_init_protection.c create mode 100755 hals/src/liteos/L0/huks_adapter.c create mode 100755 hals/src/liteos/L1/hc_init_protection.c create mode 100644 hals/src/liteos/hc_condition.c create mode 100755 hals/src/liteos/hc_file.c create mode 100644 hals/src/liteos/hc_mutex.c create mode 100644 hals/src/liteos/hc_thread.c create mode 100755 hals/src/liteos/hc_time.c create mode 100755 hals/src/liteos/hc_types.c create mode 100755 interfaces/innerkits/device_auth.h create mode 100755 interfaces/innerkits/device_auth_defines.h create mode 100755 ohos.build create mode 100644 services/BUILD.gn create mode 100644 services/common/inc/broadcast_manager/broadcast_manager.h create mode 100644 services/common/inc/callback_manager/callback_manager.h create mode 100644 services/common/inc/channel_manager/channel_manager.h create mode 100644 services/common/inc/channel_manager/soft_bus_channel/soft_bus_channel.h create mode 100644 services/common/inc/common_defs.h create mode 100644 services/common/inc/data_base/database.h create mode 100644 services/common/inc/data_base/database_manager.h create mode 100644 services/common/src/broadcast_manager/broadcast_manager.c create mode 100644 services/common/src/broadcast_manager_mock/broadcast_manager_mock.c create mode 100644 services/common/src/callback_manager/callback_manager.c create mode 100644 services/common/src/channel_manager/channel_manager.c create mode 100644 services/common/src/channel_manager/soft_bus_channel/soft_bus_channel.c create mode 100755 services/common/src/channel_manager/soft_bus_channel_mock/soft_bus_channel_mock.c create mode 100644 services/common/src/data_base/database_manager.c create mode 100755 services/device_auth.c create mode 100644 services/deviceauth.gni create mode 100644 services/group_auth/inc/account_related_group_auth/account_related_group_auth.h create mode 100644 services/group_auth/inc/account_unrelated_group_auth/account_unrelated_group_auth.h create mode 100644 services/group_auth/inc/base_group_auth.h create mode 100644 services/group_auth/inc/group_auth_common_defines.h create mode 100644 services/group_auth/inc/group_auth_manager.h create mode 100644 services/group_auth/src/group_auth_manager/account_related_group_auth_mock/account_related_group_auth_mock.c create mode 100644 services/group_auth/src/group_auth_manager/account_unrelated_group_auth/account_unrelated_group_auth.c create mode 100644 services/group_auth/src/group_auth_manager/account_unrelated_group_auth_mock/account_unrelated_group_auth_mock.c create mode 100644 services/group_auth/src/group_auth_manager/group_auth_manager.c create mode 100644 services/group_auth/src/group_auth_manager_lite/group_auth_manager_lite.c create mode 100644 services/group_manager/inc/account_related/account_related_group_common.h create mode 100644 services/group_manager/inc/account_related/account_related_group_manager.h create mode 100644 services/group_manager/inc/account_related/across_account_group.h create mode 100644 services/group_manager/inc/account_related/identical_account_group.h create mode 100644 services/group_manager/inc/account_unrelated/account_unrelated_group_manager.h create mode 100644 services/group_manager/inc/account_unrelated/peer_to_peer_group.h create mode 100644 services/group_manager/inc/base_group.h create mode 100755 services/group_manager/inc/group_common.h create mode 100644 services/group_manager/inc/group_manager.h create mode 100644 services/group_manager/src/group_manager/account_related/account_related_group_manager_mock/account_related_group_manager_mock.c create mode 100644 services/group_manager/src/group_manager/account_related/across_account_group_mock/across_account_group_mock.c create mode 100644 services/group_manager/src/group_manager/account_related/identical_account_group_mock/identical_account_group_mock.c create mode 100644 services/group_manager/src/group_manager/account_unrelated/account_unrelated_group_manager/account_unrelated_group_manager.c create mode 100644 services/group_manager/src/group_manager/account_unrelated/account_unrelated_group_manager_mock/account_unrelated_group_manager_mock.c create mode 100755 services/group_manager/src/group_manager/account_unrelated/peer_to_peer_group/peer_to_peer_group.c create mode 100644 services/group_manager/src/group_manager/account_unrelated/peer_to_peer_group_mock/peer_to_peer_group_mock.c create mode 100755 services/group_manager/src/group_manager/group_common.c create mode 100644 services/group_manager/src/group_manager/group_manager.c create mode 100644 services/group_manager/src/group_manager_mock/group_manager_mock.c create mode 100644 services/module/inc/das_module/base_sub_task.h create mode 100644 services/module/inc/das_module/das_common.h create mode 100644 services/module/inc/das_module/das_module.h create mode 100644 services/module/inc/das_module/das_module_defines.h create mode 100644 services/module/inc/das_module/das_version_util.h create mode 100644 services/module/inc/das_module/iso_task/iso_base_cur_task.h create mode 100644 services/module/inc/das_module/iso_task/iso_client_task.h create mode 100644 services/module/inc/das_module/iso_task/iso_protocol_task/iso_client_protocol_task.h create mode 100644 services/module/inc/das_module/iso_task/iso_protocol_task/iso_server_protocol_task.h create mode 100644 services/module/inc/das_module/iso_task/iso_server_task.h create mode 100644 services/module/inc/das_module/iso_task/iso_task_common.h create mode 100644 services/module/inc/das_module/iso_task/iso_task_main.h create mode 100644 services/module/inc/das_module/iso_task/lite_exchange_task/iso_client_bind_exchange_task.h create mode 100644 services/module/inc/das_module/iso_task/lite_exchange_task/iso_client_unbind_exchange_task.h create mode 100644 services/module/inc/das_module/iso_task/lite_exchange_task/iso_server_bind_exchange_task.h create mode 100644 services/module/inc/das_module/iso_task/lite_exchange_task/iso_server_unbind_exchange_task.h create mode 100644 services/module/inc/das_module/pake_task/common_standard_bind_exchange.h create mode 100644 services/module/inc/das_module/pake_task/common_standard_unbind_exchange.h create mode 100644 services/module/inc/das_module/pake_task/das_asy_token_manager.h create mode 100644 services/module/inc/das_module/pake_task/new_pake_task/new_pake_client_protocol_task.h create mode 100644 services/module/inc/das_module/pake_task/new_pake_task/new_pake_client_task.h create mode 100644 services/module/inc/das_module/pake_task/new_pake_task/new_pake_protocol_task_common.h create mode 100644 services/module/inc/das_module/pake_task/new_pake_task/new_pake_server_protocol_task.h create mode 100644 services/module/inc/das_module/pake_task/new_pake_task/new_pake_server_task.h create mode 100644 services/module/inc/das_module/pake_task/new_pake_task/new_pake_task_main.h create mode 100644 services/module/inc/das_module/pake_task/pake_base_cur_task.h create mode 100644 services/module/inc/das_module/pake_task/pake_message_util.h create mode 100644 services/module/inc/das_module/pake_task/pake_task/pake_client_protocol_task.h create mode 100644 services/module/inc/das_module/pake_task/pake_task/pake_client_task.h create mode 100644 services/module/inc/das_module/pake_task/pake_task/pake_protocol_task_common.h create mode 100644 services/module/inc/das_module/pake_task/pake_task/pake_server_protocol_task.h create mode 100644 services/module/inc/das_module/pake_task/pake_task/pake_server_task.h create mode 100644 services/module/inc/das_module/pake_task/pake_task/pake_task_main.h create mode 100644 services/module/inc/das_module/pake_task/pake_task_common.h create mode 100644 services/module/inc/das_module/pake_task/standard_client_bind_exchange_task.h create mode 100644 services/module/inc/das_module/pake_task/standard_client_unbind_exchange_task.h create mode 100644 services/module/inc/das_module/pake_task/standard_exchange_message_util.h create mode 100644 services/module/inc/das_module/pake_task/standard_server_bind_exchange_task.h create mode 100644 services/module/inc/das_module/pake_task/standard_server_unbind_exchange_task.h create mode 100644 services/module/inc/das_module/task_main.h create mode 100644 services/module/inc/dev_auth_module_manager.h create mode 100644 services/module/inc/module_common.h create mode 100644 services/module/inc/protocol/iso_protocol/iso_protocol_common.h create mode 100644 services/module/inc/protocol/pake_protocol/new_pake_protocol/new_pake_protocol_common.h create mode 100644 services/module/inc/protocol/pake_protocol/new_pake_protocol/new_pake_protocol_dl.h create mode 100644 services/module/inc/protocol/pake_protocol/new_pake_protocol/new_pake_protocol_ec.h create mode 100644 services/module/inc/protocol/pake_protocol/pake_defs.h create mode 100644 services/module/inc/protocol/pake_protocol/pake_protocol/pake_protocol_common.h create mode 100644 services/module/inc/protocol/pake_protocol/pake_protocol/pake_protocol_dl.h create mode 100644 services/module/inc/protocol/pake_protocol/pake_protocol/pake_protocol_ec.h create mode 100644 services/module/inc/protocol/protocol_common.h create mode 100644 services/module/inc/tcis_module/auth_common.h create mode 100644 services/module/inc/tcis_module/task_base.h create mode 100644 services/module/inc/tcis_module/tcis_auth_token_manager/tcis_auth_token_manager.h create mode 100644 services/module/inc/tcis_module/tcis_module.h create mode 100644 services/module/inc/tcis_module/tcis_module_defines.h create mode 100644 services/module/inc/version_util.h create mode 100644 services/module/src/das_module/das_common.c create mode 100644 services/module/src/das_module/das_module.c create mode 100644 services/module/src/das_module/das_version_util.c create mode 100644 services/module/src/das_module/iso_task/iso_client_task.c create mode 100644 services/module/src/das_module/iso_task/iso_protocol_task/iso_client_protocol_task.c create mode 100644 services/module/src/das_module/iso_task/iso_protocol_task/iso_server_protocol_task.c create mode 100644 services/module/src/das_module/iso_task/iso_server_task.c create mode 100755 services/module/src/das_module/iso_task/iso_task_common.c create mode 100644 services/module/src/das_module/iso_task/iso_task_main.c create mode 100644 services/module/src/das_module/iso_task/lite_exchange_task/iso_client_bind_exchange_task.c create mode 100644 services/module/src/das_module/iso_task/lite_exchange_task/iso_client_unbind_exchange_task.c create mode 100644 services/module/src/das_module/iso_task/lite_exchange_task/iso_server_bind_exchange_task.c create mode 100644 services/module/src/das_module/iso_task/lite_exchange_task/iso_server_unbind_exchange_task.c create mode 100644 services/module/src/das_module/iso_task_mock/iso_task_main_mock.c create mode 100644 services/module/src/das_module/pake_task/new_pake_task_mock/new_pake_task_main_mock.c create mode 100644 services/module/src/das_module/pake_task/pake_message_util.c create mode 100644 services/module/src/das_module/pake_task/pake_task/pake_client_task.c create mode 100755 services/module/src/das_module/pake_task/pake_task/pake_protocol_task/pake_client_protocol_task.c create mode 100644 services/module/src/das_module/pake_task/pake_task/pake_protocol_task/pake_protocol_task_common.c create mode 100755 services/module/src/das_module/pake_task/pake_task/pake_protocol_task/pake_server_protocol_task.c create mode 100644 services/module/src/das_module/pake_task/pake_task/pake_server_task.c create mode 100644 services/module/src/das_module/pake_task/pake_task/pake_task_main.c create mode 100644 services/module/src/das_module/pake_task/pake_task_common.c create mode 100644 services/module/src/das_module/pake_task/pake_task_mock/pake_task_main_mock.c create mode 100644 services/module/src/das_module/pake_task/standard_exchange_task/common_standard_bind_exchange.c create mode 100644 services/module/src/das_module/pake_task/standard_exchange_task/common_standard_unbind_exchange.c create mode 100644 services/module/src/das_module/pake_task/standard_exchange_task/das_asy_token_manager.c create mode 100644 services/module/src/das_module/pake_task/standard_exchange_task/standard_client_bind_exchange_task.c create mode 100644 services/module/src/das_module/pake_task/standard_exchange_task/standard_client_unbind_exchange_task.c create mode 100644 services/module/src/das_module/pake_task/standard_exchange_task/standard_exchange_message_util.c create mode 100644 services/module/src/das_module/pake_task/standard_exchange_task/standard_server_bind_exchange_task.c create mode 100644 services/module/src/das_module/pake_task/standard_exchange_task/standard_server_unbind_exchange_task.c create mode 100644 services/module/src/das_module/pake_task/standard_exchange_task_mock/standard_exchange_task_mock.c create mode 100644 services/module/src/das_module/task_main.c create mode 100644 services/module/src/das_module_mock/das_module_mock.c create mode 100644 services/module/src/dev_auth_module_manager.c create mode 100644 services/module/src/module_common.c create mode 100644 services/module/src/protocol/iso_protocol/iso_protocol_common.c create mode 100644 services/module/src/protocol/new_pake_protocol/new_pake_protocol_dl_mock/new_pake_protocol_dl_mock.c create mode 100644 services/module/src/protocol/new_pake_protocol/new_pake_protocol_ec_mock/new_pake_protocol_ec_mock.c create mode 100644 services/module/src/protocol/pake_protocol/pake_protocol_common.c create mode 100644 services/module/src/protocol/pake_protocol/pake_protocol_dl/pake_protocol_dl.c create mode 100644 services/module/src/protocol/pake_protocol/pake_protocol_dl_mock/pake_protocol_dl_mock.c create mode 100644 services/module/src/protocol/pake_protocol/pake_protocol_ec/pake_protocol_ec.c create mode 100644 services/module/src/protocol/pake_protocol/pake_protocol_ec_mock/pake_protocol_ec_mock.c create mode 100644 services/module/src/protocol/protocol_common.c create mode 100644 services/module/src/tcis_module_mock/tcis_module_mock.c create mode 100644 services/module/src/version_util.c create mode 100644 services/session/inc/auth_session/auth_session_client.h create mode 100644 services/session/inc/auth_session/auth_session_common.h create mode 100644 services/session/inc/auth_session/auth_session_server.h create mode 100644 services/session/inc/auth_session/auth_session_util.h create mode 100644 services/session/inc/auth_session_common_defines.h create mode 100644 services/session/inc/auth_session_common_util.h create mode 100644 services/session/inc/auth_session_lite/auth_session_client_lite.h create mode 100644 services/session/inc/auth_session_lite/auth_session_common_lite.h create mode 100644 services/session/inc/auth_session_lite/auth_session_server_lite.h create mode 100644 services/session/inc/base_session.h create mode 100644 services/session/inc/bind_session/bind_session_client.h create mode 100644 services/session/inc/bind_session/bind_session_common.h create mode 100644 services/session/inc/bind_session/bind_session_server.h create mode 100644 services/session/inc/bind_session_lite/bind_session_client_lite.h create mode 100644 services/session/inc/bind_session_lite/bind_session_common_lite.h create mode 100644 services/session/inc/bind_session_lite/bind_session_server_lite.h create mode 100644 services/session/inc/key_agree_session/key_agree_session_client.h create mode 100644 services/session/inc/key_agree_session/key_agree_session_common.h create mode 100644 services/session/inc/key_agree_session/key_agree_session_server.h create mode 100644 services/session/inc/session_common.h create mode 100644 services/session/inc/session_manager.h create mode 100644 services/session/src/auth_session/auth_session_client.c create mode 100644 services/session/src/auth_session/auth_session_common.c create mode 100644 services/session/src/auth_session/auth_session_server.c create mode 100644 services/session/src/auth_session/auth_session_util.c create mode 100644 services/session/src/auth_session_common_util.c create mode 100644 services/session/src/auth_session_lite/auth_session_client_lite.c create mode 100644 services/session/src/auth_session_lite/auth_session_common_lite.c create mode 100644 services/session/src/auth_session_lite/auth_session_server_lite.c create mode 100644 services/session/src/auth_session_lite_mock/auth_session_client_lite_mock.c create mode 100644 services/session/src/auth_session_lite_mock/auth_session_server_lite_mock.c create mode 100644 services/session/src/auth_session_mock/auth_session_client_mock.c create mode 100644 services/session/src/auth_session_mock/auth_session_server_mock.c create mode 100644 services/session/src/bind_session/bind_session_client.c create mode 100644 services/session/src/bind_session/bind_session_common.c create mode 100644 services/session/src/bind_session/bind_session_server.c create mode 100644 services/session/src/bind_session_lite/bind_session_client_lite.c create mode 100644 services/session/src/bind_session_lite/bind_session_common_lite.c create mode 100644 services/session/src/bind_session_lite/bind_session_server_lite.c create mode 100644 services/session/src/bind_session_lite_mock/bind_session_client_lite_mock.c create mode 100644 services/session/src/bind_session_lite_mock/bind_session_server_lite_mock.c create mode 100644 services/session/src/bind_session_mock/bind_session_client_mock.c create mode 100644 services/session/src/bind_session_mock/bind_session_server_mock.c create mode 100644 services/session/src/key_agree_session_mock/key_agree_session_client_mock.c create mode 100644 services/session/src/key_agree_session_mock/key_agree_session_server_mock.c create mode 100755 services/session/src/session_common.c create mode 100644 services/session/src/session_manager.c create mode 100644 test/unittest/deviceauth/BUILD.gn create mode 100644 test/unittest/deviceauth/include/deviceauth_standard_test.h create mode 100644 test/unittest/deviceauth/include/deviceauth_test_mock.h create mode 100644 test/unittest/deviceauth/source/deviceauth_standard_test.cpp create mode 100644 test/unittest/deviceauth/source/deviceauth_test_mock.cpp diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..51c63e2 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,15 @@ +*.tgz filter=lfs diff=lfs merge=lfs -text +*.trp filter=lfs diff=lfs merge=lfs -text +*.apk filter=lfs diff=lfs merge=lfs -text +*.jar filter=lfs diff=lfs merge=lfs -text +*.mp4 filter=lfs diff=lfs merge=lfs -text +*.zip filter=lfs diff=lfs merge=lfs -text +*.asm filter=lfs diff=lfs merge=lfs -text +*.8svn filter=lfs diff=lfs merge=lfs -text +*.9svn filter=lfs diff=lfs merge=lfs -text +*.dylib filter=lfs diff=lfs merge=lfs -text +*.exe filter=lfs diff=lfs merge=lfs -text +*.a filter=lfs diff=lfs merge=lfs -text +*.so filter=lfs diff=lfs merge=lfs -text +*.bin filter=lfs diff=lfs merge=lfs -text +*.dll filter=lfs diff=lfs merge=lfs -text diff --git a/BUILD.gn b/BUILD.gn new file mode 100644 index 0000000..ab36496 --- /dev/null +++ b/BUILD.gn @@ -0,0 +1,41 @@ +# Copyright (C) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("deviceauth_env.gni") +import("hals/deviceauth_hals.gni") + +group("deviceauth_build") { + deps = [ + "${hals_path}:${hal_module_name}", + "services:deviceauth", + ] +} + +group("deviceauth_service_build") { + deps = [ + "${hals_path}:${hal_module_name}", + "services:deviceauth_service", + ] +} + +group("deviceauth_sdk_build") { + deps = [ + "${hals_path}:${hal_module_name}", + "services:deviceauth_sdk", + ] +} + +group("deviceauth_test_build") { + testonly = true + deps = [ "test/unittest/deviceauth:deviceauth_llt" ] +} diff --git a/LICENSE b/LICENSE old mode 100755 new mode 100644 diff --git a/README.md b/README.md index 937cb92..fdb312d 100755 --- a/README.md +++ b/README.md @@ -1,43 +1,140 @@ -# Introduction - -- **Device interconnection security** - -To securely transmit user data between devices, the device authentication module provides the capabilities of establishing and verifying trust relationships between devices. This document describes how an IoT controller and an IoT device establish and verify a trust relationship. - -- **IoT device interconnection security** - -The device authentication module allows an IoT controller \(such as a smartphone and tablet\) and an IoT device \(such as a smart home device and wearable\) to establish and verify a P2P trust relationship with each other, without requiring login to the IoT controller and IoT device using the same account. Based on the trust relationship, the IoT controller and IoT device can transmit encrypted user data through a secure P2P connection. - -- **IoT controller identifier** - -When a P2P trust relationship is established between the IoT controller and IoT device, a public/private key pair is generated based on the elliptic curve cryptography \(ECC\) and serves as the identifier of the IoT controller. The IoT controller may connect to multiple IoT devices. The device authentication module generates different identifiers for the IoT controller to isolate its connections to different IoT devices. - -- **IoT device identifier** - -The IoT device identifier is also a public/private key pair generated based on the ECC when a P2P trust relationship is established between the IoT controller and IoT device. The private key is stored on the IoT device. Each time the device is restored to factory settings, the public/private key pair will be reset. - -The preceding identifiers are used for secure communications between the IoT controller and IoT device. - -- **P2P trust relationship establishment and verification** - -When an IoT controller and an IoT device establish a P2P trust relationship, they exchange identifiers. - -During this process, the user needs to enter the personal identification number \(PIN\) or any other information provided by the IoT device on the IoT controller. Typically, a PIN is dynamically generated if the IoT device has a screen, or preset by the manufacturer if the IoT device does not have a screen. A PIN can be a number consisting of six digits or a QR code. After the user enters the PIN, the IoT controller and IoT device invoke the device authentication service to perform authentication and session key exchange based on the password authenticated key exchange \(PAKE\) protocol, and use the session key to exchange the public keys of their identifiers. - -When the IoT controller and IoT device communicate with each other after establishing a trust relationship, they exchange public keys of their identifiers and verify the trust relationship by checking whether they have stored the identity information of each other. Based on their public/private key pairs, the IoT controller and IoT device exchange keys and establish a secure communications channel for transmitting encrypted data. - -# Directory Structure - -``` -base/security -├── deviceauth -│ ├── frameworks -│ │ └── deviceauth_lite # Device authentication implementation -│ └── interfaces -│ └── innerkits -│ └── deviceauth_lite # Device authentication APIs -``` - -# Repositories Involved - -deviceauth +# deviceauth + +- [Introduction](#section11660541593) +- [Directory Structure](#section161941989596) +- [Usage](#section1312121216216) + - [Available APIs](#section1551164914237) + +- [Repositories Involved](#section1371113476307) + +## Introduction + +The device authentication module belongs to the security subsystem of OpenHarmony. It manages the entire lifecycle of trust relationships between devices, including establishment, maintenance, use, and cancellation, and implements authentication and secure session key exchange between trusted devices. It provides basic capabilities for trusted interconnections between devices that run OpenHarmony. + +The device authentication module provides the following capabilities: + +- Device trust relationship management: manages the establishment, maintenance, and cancellation of trust relationships between devices in a unified manner; allows the isolation and controllable sharing of trust relationships created by different services. +- Device trust relationship authentication: authenticates trust relationships between devices, allows trusted devices to exchange secure session keys with each other, and sets up connections between trusted devices through the DSoftBus. + +The device authentication module consists of three submodules: device group management, device group authentication, and account-irrelevant P2P device authentication. The following figure shows the logical architecture of the device authentication module. + +**Figure 1** Architecture of the device authentication module + + +![](figures/en-us_deviceauth_architecture.png) + +In the architecture: + +- Device group management: allows you to manage the trust relationships between the local device and other devices created by different services in a unified manner, create trust relationships between devices using the provided APIs, create an account-irrelevant device group, add trusted devices to the group, and create a trust relationship between isolated devices. +- Device group authentication: allows devices to authenticate the trust relationships that have been established between them and exchange session keys. +- Account-irrelevant P2P device authentication: allows two devices to establish a trust relationship based on a shared secret, and exchange a session key for secure communication based on the trusted relationship. + +## Directory Structure + +``` +/base/security/deviceauth +├── frameworks # Device authentication framework code +├── hals # HAL code for the tool library +│ ├── inc # Tool library header files +│ └── src # Tool library source files +├── interfaces # APIs exposed externally +└── services # Device authentication services + ├── common # Common code + ├── group_auth # Device group authentication + ├── group_manager # Device group management + ├── module # Authenticator module (including the account-irrelevant P2P device authenticator) + └── session # Scheduling and session management module +``` + +## Usage + +### Available APIs + +The device group management sub-module abstracts trust relationships established by different services between devices into trust groups and provides unified APIs for creating, deleting, and querying groups. The device group authentication sub-module provides trusted device authentication and end-to-end session key exchange based on the trust groups. + +**Table 1** APIs in DeviceGroupManager + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

API

+

Description

+

const DeviceGroupManager *GetGmInstance()

+

Obtains a DeviceGroupManager instance.

+

int32_t RegCallback(const char *appId, const DeviceAuthCallback *callback)

+

Registers a callback.

+

int32_t CreateGroup(int64_t requestId, const char *appId, const char *createParams)

+

Creates a group of trusted devices.

+

int32_t DeleteGroup(int64_t requestId, const char *appId, const char *disbandParams)

+

Deletes a group of trusted devices.

+

int32_t AddMemberToGroup(int64_t requestId, const char *appId, const char *addParams)

+

Adds a member to a specified group.

+

int32_t DeleteMemberFromGroup(int64_t requestId, const char *appId, const char *deleteParams);

+

Deletes a member from a specified group.

+

int32_t ProcessData(int64_t requestId, const uint8_t *data, uint32_t dataLen)

+

Processes data that is bound or unbound.

+

int32_t GetGroupInfo(const char *appId, const char *queryParams, char **returnGroupVec, uint32_t *groupNum)

+

Obtains information about a trusted group of devices.

+
+ +**Table 2** APIs in GroupAuthManager + + + + + + + + + + + + + + + + +

API

+

Description

+

const GroupAuthManager *GetGaInstance()

+

Obtains a GroupAuthManager instance.

+

int32_t AuthDevice(int64_t authReqId, const char *authParams, const DeviceAuthCallback *gaCallback)

+

Authenticates a peer device.

+

int32_t ProcessData(int64_t authReqId, const uint8_t *data, uint32_t dataLen,

+

const DeviceAuthCallback *gaCallback)

+

Processes authentication data.

+
+ +## Repositories Involved + +**Security subsystem** + +security\_deviceauth + diff --git a/README_zh.md b/README_zh.md index 19aac8b..23a5192 100755 --- a/README_zh.md +++ b/README_zh.md @@ -1,43 +1,140 @@ -# 简介 - -- **设备互联安全性** - -为实现用户数据在多个终端设备间的安全流转,设备认证组件提供将用户多个设备安全连接起来的能力,这种能力体现在设备间信任关系建立和设备通信时信任关系验证两个阶段。本文档主要描述IoT设备可信互联场景中主控设备与IoT设备建立、验证信任关系的实现。 - -- **IoT设备互联安全** - -设备认证提供了IoT主控设备(手机、平板等)与IoT配件设备(如智能家居、智能穿戴等)间建立并验证帐号无关点对点信任关系的能力。具备这种信任关系的设备在通信连接时可搭建安全的连接通道,实现用户数据的端到端加密传输。 - -- **IoT主控设备的身份标识** - -IoT主控设备在与配件设备建立点对点信任关系时,会生成椭圆曲线公私钥对作为本设备的身份标识;IoT主控设备上可能存在多种IoT设备互联业务,设备认证组件将针对不同的IoT设备互联业务为主控设备生成不同的身份标识,形成不同业务间的隔离。 - -- **IoT配件设备的身份标识** - -IoT配件设备同样会在与主控设备建立点对点信任关系时,生成椭圆曲线公私钥对作为本设备的身份标识;其中私钥不出IoT设备,设备每次恢复出厂设置时,会重置该公私钥对。 - -上述的身份标识用于IoT主控设备与IoT配件设备间的安全通信,下面将描述基于身份标识的帐号无关点对点信任关系建立与验证的实现。 - -- **设备间点对点信任关系的建立与验证** - -IoT主控设备和IoT配件建立帐号无关点对点信任关系的过程,实际上是相互交换身份标识的过程。 - -在信任关系建立过程中,用户需要在主控设备上输入配件设备提供的PIN码(或其他形式的共享信息)。典型的PIN码呈现形式为:对于有屏幕的设备,该PIN码动态生成;对于没有屏幕的设备,该PIN码由设备生产厂家预置并打印在设备上;PIN码的格式,可以是一个用户可读的6位数字,也可以是一个二维码。在用户完成PIN码输入后,主控设备和配件设备将调用设备认证服务基于PAKE协议完成认证会话密钥协商,并基于该会话密钥,安全的交换各自身份公钥。 - -当建立过信任关系的主控设备与配件设备间进行通信时,双方将相互交换身份公钥,并通过检查本地是否存储对端身份信息的方式确认对端与本设备的信任关系。进一步地,基于双方的身份公私钥对,通信对端设备可以基于STS协议进行密钥协商并建立安全通信通道,支撑设备间通信数据的端到端加密传输。 - -# 目录 - -``` -base/security -├── deviceauth -│ ├── frameworks -│ │ └── deviceauth_lite 设备授权实现 -│ └── interfaces -│ └── innerkits -│ └── deviceauth_lite 设备授权接口 -``` - -# 相关仓 - -deviceauth +# 设备认证 + +- [简介](#section11660541593) +- [目录](#section161941989596) +- [说明](#section1312121216216) + - [接口说明](#section1551164914237) + +- [相关仓](#section1371113476307) + +## 简介 + +在OpenHarmony中,设备认证模块作为安全子系统的子模块,负责设备间可信关系的建立、维护、使用、撤销等全生命周期的管理,实现可信设备间的互信认证和安全会话密钥协商,是搭载OpenHarmony的设备进行可信互联的基础平台能力。 + +设备认证模块当前提供如下功能: + +- 设备互信关系管理功能:统一管理设备互信关系的建立、维护、撤销过程;支持各个业务创建的设备互信关系的隔离和可控共享。 +- 设备互信关系认证功能:提供认证设备间互信关系、进行安全会话密钥协商的能力,支持分布式软总线实现互信设备间的组网。 + +为实现上述功能,设备认证模块当前包含设备群组管理、设备群组认证和帐号无关点对点认证三个子模块,其部署逻辑如下图: + +**图 1** 子系统架构图 + + +![](figures/zh-cn_deviceauth_architecture.png) + +其中, + +- 设备群组管理服务:统一管理不同业务建立的本设备与其他设备间的互信关系,并对外提供设备互信关系的创建入口 ,完成信任建立后创建帐号无关设备群组,并将信任对象设备添加进群组;OpenHarmony上各业务可独立创建相互隔离的设备间可信关系。 +- 设备群组认证服务:支持已建立可信关系的设备间完成互信关系的认证及会话密钥的协商。 +- 帐号无关点对点设备认证:提供设备间基于共享秘密建立一对一互信关系的功能,并支持基于这种互信关系的认证密钥协商。 + +## 目录 + +``` +/base/security/deviceauth +├── frameworks # 设备认证框架层代码 +├── hals # 平台相关工具库抽象层 +│ ├── inc # 工具库头文件 +│ └── src # 工具库源文件 +├── interfaces # 对外接口目录 +└── services # 设备认证服务层代码 + ├── common # 公共代码库 + ├── group_auth # 设备群组认证模块 + ├── group_manager # 设备群组管理模块 + ├── module # 认证器模块(包括帐号无关点对点设备认证器) + └── session # 调度及会话管理模块 +``` + +## 说明 + +### 接口说明 + +设备认证组件中,设备群组管理服务负责将不同业务建立的设备间可信关系抽象成一个个可信群组,对外提供统一的接口,包含群组创建、删除、查询等功能;设备群组认证服务基于已经建立过可信关系的设备群组,提供设备可信认证与端到端会话密钥协商功能。 + +**表 1** 设备群组管理服务提供的API接口\(DeviceGroupManager\)功能介绍 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

接口名

+

描述

+

const DeviceGroupManager *GetGmInstance()

+

获取设备群组管理的实例。

+

int32_t RegCallback(const char *appId, const DeviceAuthCallback *callback)

+

注册业务的监听回调。

+

int32_t CreateGroup(int64_t requestId, const char *appId, const char *createParams)

+

创建一个可信设备群组。

+

int32_t DeleteGroup(int64_t requestId, const char *appId, const char *disbandParams)

+

删除一个可信设备群组。

+

int32_t AddMemberToGroup(int64_t requestId, const char *appId, const char *addParams)

+

添加成员到指定群组ID的可信设备群组。

+

int32_t DeleteMemberFromGroup(int64_t requestId, const char *appId, const char *deleteParams);

+

从指定可信设备群组里删除可信成员。

+

int32_t ProcessData(int64_t requestId, const uint8_t *data, uint32_t dataLen)

+

处理绑定或者解绑的数据。

+

int32_t GetGroupInfo(const char *appId, const char *queryParams, char **returnGroupVec, uint32_t *groupNum)

+

查询可信设备群组信息。

+
+ +**表 2** 设备群组认证模块提供的API接口\(GroupAuthManager\)功能介绍 + + + + + + + + + + + + + + + + +

接口名

+

描述

+

const GroupAuthManager *GetGaInstance()

+

获取设备群组认证的实例。

+

int32_t AuthDevice(int64_t authReqId, const char *authParams, const DeviceAuthCallback *gaCallback)

+

认证对端是否是可信设备。

+

int32_t ProcessData(int64_t authReqId, const uint8_t *data, uint32_t dataLen,

+

const DeviceAuthCallback *gaCallback)

+

处理认证的数据。

+
+ +## 相关仓 + +**安全子系统** + +security\_deviceauth + diff --git a/deviceauth_env.gni b/deviceauth_env.gni new file mode 100644 index 0000000..f6a843c --- /dev/null +++ b/deviceauth_env.gni @@ -0,0 +1,18 @@ +# Copyright (C) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +deviceauth_path = "//base/security/deviceauth" +hals_path = "${deviceauth_path}/hals" +innerkits_path = "${deviceauth_path}/interfaces/innerkits" +frameworks_path = "${deviceauth_path}/frameworks" +services_path = "${deviceauth_path}/services" diff --git a/figures/en-us_deviceauth_architecture.png b/figures/en-us_deviceauth_architecture.png new file mode 100755 index 0000000000000000000000000000000000000000..d8151b00772740e1cc7d2bd533d4ad96cefc1a9f GIT binary patch literal 38443 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 literal 0 HcmV?d00001 diff --git a/figures/zh-cn_deviceauth_architecture.png b/figures/zh-cn_deviceauth_architecture.png new file mode 100755 index 0000000000000000000000000000000000000000..4acf9ae0159ed3f2b36f9114f6605aa0a114cf84 GIT binary patch literal 143774 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 z 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�=$1vZu=+fI;dMA7e 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 U==eEGh5sB=)KJKfGr94<0BK% +#include +#include "device_auth.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define MAX_REQUEST_PARAMS_NUM 8 +#define CB_TYPE_DEV_AUTH 1 +#define CB_TYPE_TMP_DEV_AUTH 2 +#define CB_TYPE_LISTENER 3 + +typedef struct { + int32_t type; + int32_t valSz; + uint8_t *val; + int32_t idx; +} IpcDataInfo; + +enum { + CB_ID_ON_TRANS = 1, + CB_ID_SESS_KEY_DONE, + CB_ID_ON_FINISH, + CB_ID_ON_ERROR, + CB_ID_ON_REQUEST, + CB_ID_ON_GROUP_CREATED, + CB_ID_ON_GROUP_DELETED, + CB_ID_ON_DEV_BOUND, + CB_ID_ON_DEV_UNBOUND, + CB_ID_ON_DEV_UNTRUSTED, + CB_ID_ON_LAST_GROUP_DELETED, + CB_ID_ON_TRUST_DEV_NUM_CHANGED, +}; + +typedef int32_t (*IpcServiceCall)(const IpcDataInfo *, int32_t, uintptr_t); + +int32_t IpcEncodeCallReplay(uintptr_t replayCache, int32_t type, const uint8_t *result, int32_t resultSz); +uint32_t SetIpcCallMap(uintptr_t ipcInstance, IpcServiceCall method, int32_t methodId); + +void SetCbCtxToDataCtx(uintptr_t callCtx, int32_t cbIdx); +int32_t CreateCallCtx(uintptr_t *callCtx, uintptr_t *cbCtx); +void DestroyCallCtx(uintptr_t *callCtx, uintptr_t *cbCtx); +int32_t DoBinderCall(uintptr_t callCtx, int32_t methodId, bool withSync); +int32_t SetCallRequestParamInfo(uintptr_t callCtx, int32_t type, const uint8_t *param, int32_t paramSz); + +int32_t CreateServiceInstance(uintptr_t *ipcInstance); +void DestroyServiceInstance(uintptr_t *ipcInstance); + +int32_t AddDevAuthServiceToManager(uintptr_t *serviceCtx); +void DecodeCallReply(uintptr_t callCtx, IpcDataInfo *replyCache, int32_t cacheNum); + +int32_t InitIpcCallBackList(void); +void DeInitIpcCallBackList(void); +void InitDeviceAuthCbCtx(DeviceAuthCallback *ctx, int32_t type); +void InitDevAuthListenerCbCtx(DataChangeListener *ctx); +int32_t AddIpcCallBackByAppId(const char *appId, const uint8_t *cbPtr, int32_t cbSz, int32_t type); +void DelIpcCallBackByAppId(const char *appId, int32_t type); +int32_t AddIpcCallBackByReqId(int64_t reqId, const uint8_t *cbPtr, int32_t cbSz, int32_t type); +void DelIpcCallBackByReqId(int64_t reqId, int32_t type, bool withLock); + +int32_t DecodeIpcData(uintptr_t data, int32_t *type, uint8_t **val, int32_t *valSz); +void ProcCbHook(int32_t callbackId, uintptr_t cbHook, + const IpcDataInfo *cbDataCache, int32_t cacheNum, uintptr_t replyCtx); + +int32_t GetIpcRequestParamByType(const IpcDataInfo *ipcParams, int32_t paramNum, + int32_t type, uint8_t *paramCache, int32_t *cacheLen); +int32_t AddReqIdByAppId(const char *appId, int64_t reqId); +void AddIpcCbObjByAppId(const char *appId, int32_t objIdx, int32_t type); +void AddIpcCbObjByReqId(int64_t reqId, int32_t objIdx, int32_t type); + +bool IsCallbackMethod(int32_t methodId); +bool IsServiceRunning(void); +void ResetIpcCallBackNodeByNodeId(int32_t nodeIdx); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/frameworks/inc/ipc_callback_proxy.h b/frameworks/inc/ipc_callback_proxy.h new file mode 100644 index 0000000..63c153c --- /dev/null +++ b/frameworks/inc/ipc_callback_proxy.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef IPC_CALLBACK_PROXY_H +#define IPC_CALLBACK_PROXY_H + +#include "ipc_iface.h" +#include "iremote_proxy.h" + +namespace OHOS { +class ProxyDevAuthCb : public IRemoteProxy { +public: + explicit ProxyDevAuthCb(const sptr &impl); + ~ProxyDevAuthCb(); + virtual void DoCallBack(int32_t callbackId, uintptr_t cbHook, + MessageParcel &dataParcel, MessageParcel &reply) override; +private: + static inline BrokerDelegator delegator_; +}; +} + +#endif \ No newline at end of file diff --git a/frameworks/inc/ipc_callback_stub.h b/frameworks/inc/ipc_callback_stub.h new file mode 100644 index 0000000..0077428 --- /dev/null +++ b/frameworks/inc/ipc_callback_stub.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef IPC_CALLBACK_STUB_H +#define IPC_CALLBACK_STUB_H + +#include "ipc_iface.h" +#include "iremote_stub.h" + +namespace OHOS { +class StubDevAuthCb : public IRemoteStub { +public: + StubDevAuthCb(); + ~StubDevAuthCb(); + virtual int32_t OnRemoteRequest(uint32_t code, MessageParcel &data, + MessageParcel &reply, MessageOption &option) override; + virtual void DoCallBack(int32_t callbackId, uintptr_t cbHook, + MessageParcel &dataParcel, MessageParcel &reply) override; +}; +} + +#endif \ No newline at end of file diff --git a/frameworks/inc/ipc_dev_auth_proxy.h b/frameworks/inc/ipc_dev_auth_proxy.h new file mode 100644 index 0000000..7439ee6 --- /dev/null +++ b/frameworks/inc/ipc_dev_auth_proxy.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef IPC_DEV_AUTH_PROXY_H +#define IPC_DEV_AUTH_PROXY_H + +#include "ipc_iface.h" +#include "iremote_proxy.h" +#include "ipc_callback_stub.h" + +namespace OHOS { +class ProxyDevAuth : public IRemoteProxy { +public: + explicit ProxyDevAuth(const sptr &impl); + ~ProxyDevAuth(); + int32_t DoCallRequest(MessageParcel &dataParcel, MessageParcel &replyParcel, bool withSync); + static bool ServiceRunning(void); + +private: + static inline BrokerDelegator delegator_; +}; + +class ProxyDevAuthData { +public: + ProxyDevAuthData() = default; + virtual ~ProxyDevAuthData() = default; + int32_t EncodeCallRequest(int32_t type, const uint8_t *param, int32_t paramSz); + int32_t FinalCallRequest(int32_t methodId); + int32_t ActCall(bool withSync); + void SetCallbackStub(sptr cbRemote); + MessageParcel *GetReplyParcel(void); + +public: + MessageParcel replyParcel; +private: + MessageParcel dataParcel; + MessageParcel tmpDataParcel; + sptr cbStub = nullptr; + int32_t paramCnt = 0; + sptr GetProxy() const; + bool withCallback = false; +}; +} +#endif diff --git a/frameworks/inc/ipc_dev_auth_stub.h b/frameworks/inc/ipc_dev_auth_stub.h new file mode 100644 index 0000000..e2bde13 --- /dev/null +++ b/frameworks/inc/ipc_dev_auth_stub.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef IPC_DEV_AUTH_STUB_H +#define IPC_DEV_AUTH_STUB_H + +#include "ipc_iface.h" +#include "ipc_adapt.h" +#include "iremote_stub.h" + +namespace OHOS { +typedef struct { + IpcServiceCall method; + int32_t methodId; +} IpcServiceCallMap; +const int32_t MAX_CALLMAP_SIZE = 32; +const int32_t MAX_CBSTUB_SIZE = 32; + +class ServiceDevAuth : public IRemoteStub { +public: + ServiceDevAuth(); + ~ServiceDevAuth(); + virtual int32_t OnRemoteRequest(uint32_t code, MessageParcel &data, + MessageParcel &reply, MessageOption &option) override; + void ResetCallMap(void); + int32_t SetCallMap(IpcServiceCall method, int32_t methodId); + static int32_t SetRemoteObject(sptr &object); + static void SetCbDeathRecipient(int32_t cbStubIdx, int32_t cbDataIdx); + static void ResetRemoteObject(int32_t idx); + static void ActCallback(int32_t objIdx, int32_t callbackId, + uintptr_t cbHook, MessageParcel &dataParcel, MessageParcel &reply); + +private: + int32_t maxCallMapSz = MAX_CALLMAP_SIZE; + IpcServiceCallMap *callMapTable = nullptr; + int32_t callMapElemNum = 0; + IpcServiceCall GetCallMethodByMethodId(int32_t methodId); +}; + +class DevAuthDeathRecipient : public IRemoteObject::DeathRecipient { +public: + DevAuthDeathRecipient() {} + DevAuthDeathRecipient(int32_t cbIdx); + ~DevAuthDeathRecipient() {} + virtual void OnRemoteDied(const wptr& remoteObject) override; +private: + int32_t callbackIdx; +}; +} +#endif diff --git a/frameworks/inc/ipc_iface.h b/frameworks/inc/ipc_iface.h new file mode 100644 index 0000000..20f0c04 --- /dev/null +++ b/frameworks/inc/ipc_iface.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef IPC_IFACE_H +#define IPC_IFACE_H + +#include +#include "iremote_broker.h" +#include "message_parcel.h" + +namespace OHOS { +class IMethodsIpcCall : public IRemoteBroker { +public: + enum { + DEV_AUTH_CALL_REQUEST = 1, + }; + DECLARE_INTERFACE_DESCRIPTOR(u"MethodsIpcCall"); +}; + +class ICommIpcCallback : public IRemoteBroker { +public: + enum { + DEV_AUTH_CALLBACK_REQUEST = 1, + }; + DECLARE_INTERFACE_DESCRIPTOR(u"CommIpcCallback"); + virtual void DoCallBack(int32_t callbackId, uintptr_t cbHook, + MessageParcel &dataParcel, MessageParcel &reply) = 0; +}; +} + +#endif \ No newline at end of file diff --git a/frameworks/inc/ipc_sdk.h b/frameworks/inc/ipc_sdk.h new file mode 100644 index 0000000..b12f351 --- /dev/null +++ b/frameworks/inc/ipc_sdk.h @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef IPC_SDK_H +#define IPC_SDK_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define IPC_RESULT_NUM_1 1 +#define IPC_RESULT_NUM_2 2 + +#define IPC_CALL_BACK_STUB_AUTH_ID 0 +#define IPC_CALL_BACK_STUB_BIND_ID 1 + +/* params type for ipc call */ +#define PARAM_TYPE_APPID 1 +#define PARAM_TYPE_DEV_AUTH_CB 2 +#define PARAM_TYPE_LISTERNER 3 +#define PARAM_TYPE_REQID 4 +#define PARAM_TYPE_CREATE_PARAMS 5 +#define PARAM_TYPE_GROUPID 6 +#define PARAM_TYPE_UDID 7 +#define PARAM_TYPE_ADD_PARAMS 8 +#define PARAM_TYPE_DEL_PARAMS 9 +#define PARAM_TYPE_COMM_DATA 10 +#define PARAM_TYPE_REQ_CFM 11 +#define PARAM_TYPE_BIND 12 +#define PARAM_TYPE_UNBIND 13 +#define PARAM_TYPE_GROUP_TYPE 14 +#define PARAM_TYPE_CREDENTIAL 15 +#define PARAM_TYPE_MGR_APPID 16 +#define PARAM_TYPE_FRIEND_APPID 17 +#define PARAM_TYPE_QUERY_PARAMS 18 +#define PARAM_TYPE_REG_INFO 19 +#define PARAM_TYPE_DATA_NUM 20 +#define PARAM_TYPE_SESS_KEY 21 +#define PARAM_TYPE_OPCODE 22 +#define PARAM_TYPE_IPC_RESULT 23 +#define PARAM_TYPE_IPC_RESULT_NUM 24 +#define PARAM_TYPE_ERRCODE 25 +#define PARAM_TYPE_ERR_INFO 26 +#define PARAM_TYPE_REQ_INFO 27 +#define PARAM_TYPE_GROUP_INFO 28 +#define PARAM_TYPE_DEVICE_INFO 29 +#define PARAM_TYPE_AUTH_PARAMS 30 +#define PARAM_TYPE_CB_OBJECT 31 + +enum { + IPC_CALL_ID_REG_CB = 1, + IPC_CALL_ID_UNREG_CB, + IPC_CALL_ID_REG_LISTENER, + IPC_CALL_ID_UNREG_LISTENER, + IPC_CALL_ID_CREATE_GROUP, + IPC_CALL_ID_DEL_GROUP, + IPC_CALL_ID_ADD_GROUP_MEMBER, + IPC_CALL_ID_DEL_GROUP_MEMBER, + IPC_CALL_ID_GM_PROC_DATA, + IPC_CALL_ID_CFM_REQUEST, + IPC_CALL_ID_BIND_PEER, + IPC_CALL_ID_UNBIND_PEER, + IPC_CALL_ID_PROC_LIGHT_DATA, + IPC_CALL_ID_SAVE_CREDENTIAL, + IPC_CALL_ID_APPLY_REG_INFO, + IPC_CALL_ID_ADD_GROUP_MGR, + IPC_CALL_ID_ADD_GROUP_FRIEND, + IPC_CALL_ID_DEL_GROUP_MGR, + IPC_CALL_ID_DEL_GROUP_FRIEND, + IPC_CALL_ID_GET_GROUP_MGR, + IPC_CALL_ID_GET_GROUP_FRIEND, + IPC_CALL_ID_GET_GROUP_INFO, + IPC_CALL_ID_SEARCH_GROUPS, + IPC_CALL_ID_GET_JOINED_GROUPS, + IPC_CALL_ID_GET_RELATED_GROUPS, + IPC_CALL_ID_GET_DEV_INFO_BY_ID, + IPC_CALL_ID_GET_TRUST_DEVICES, + IPC_CALL_ID_IS_DEV_IN_GROUP, + IPC_CALL_ID_DESTROY_INFO, + IPC_CALL_ID_GA_PROC_DATA, + IPC_CALL_ID_QUERY_TRUST_DEV_NUM, + IPC_CALL_ID_IS_TRUST_DEVICE, + IPC_CALL_ID_GET_AUTH_STATE, + IPC_CALL_ID_AUTH_DEVICE, + IPC_CALL_ID_INFORM_DEV_DISCONN +}; + +#ifdef __cplusplus +} +#endif +#endif diff --git a/frameworks/inc/ipc_service.h b/frameworks/inc/ipc_service.h new file mode 100644 index 0000000..e3eb11b --- /dev/null +++ b/frameworks/inc/ipc_service.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef IPC_SERVICE_H +#define IPC_SERVICE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif +#endif diff --git a/frameworks/src/deviceauth_service.rc b/frameworks/src/deviceauth_service.rc new file mode 100644 index 0000000..09c436e --- /dev/null +++ b/frameworks/src/deviceauth_service.rc @@ -0,0 +1,21 @@ +# Copyright (C) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +on post-fs-data + start deviceauth_service + +service deviceauth_service /system/bin/deviceauth_service + class z_core + user system + group system shell + seclabel u:r:deviceauth_service:s0 diff --git a/frameworks/src/ipc_adapt.cpp b/frameworks/src/ipc_adapt.cpp new file mode 100644 index 0000000..6880663 --- /dev/null +++ b/frameworks/src/ipc_adapt.cpp @@ -0,0 +1,1477 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ipc_adapt.h" +#include "common_defs.h" +#include "hc_log.h" +#include "hc_types.h" +#include "ipc_callback_proxy.h" +#include "ipc_callback_stub.h" +#include "ipc_dev_auth_proxy.h" +#include "ipc_dev_auth_stub.h" +#include "ipc_sdk.h" +#include "ipc_service.h" +#include "iservice_registry.h" +#include "securec.h" +#include "system_ability_definition.h" + +using namespace std; +using namespace OHOS; +namespace { + static const int32_t BUFF_MAX_SZ = 128; + static const int32_t IPC_CALL_BACK_MAX_NODES = 64; + static const int32_t IPC_CALL_BACK_STUB_NODES = 2; +} + +static StubDevAuthCb g_sdkCbStub[IPC_CALL_BACK_STUB_NODES]; + +typedef void (*CallbackStub)(uintptr_t, const IpcDataInfo *, int32_t, MessageParcel &); +typedef struct { + union { + DeviceAuthCallback devAuth; + DataChangeListener listener; + } cbCtx; + int64_t requestId; + char appId[BUFF_MAX_SZ]; + int32_t cbType; + int32_t delOnFni; + int32_t methodId; + int32_t proxyId; + int32_t nodeIdx; +} IpcCallBackNode; + +static struct { + IpcCallBackNode *ctx; + int32_t nodeCnt; +} g_ipcCallBackList = {nullptr, 0}; +static std::mutex g_cbListLock; + +static void SetIpcCallBackNodeDefault(IpcCallBackNode &node) +{ + (void)memset_s(&node, sizeof(IpcCallBackNode), 0, sizeof(IpcCallBackNode)); + node.proxyId = -1; + node.nodeIdx = -1; + return; +} + +int32_t InitIpcCallBackList(void) +{ + int32_t i; + + LOGI("initializing ..."); + if (g_ipcCallBackList.ctx != nullptr) { + LOGI("has initialized"); + return HC_SUCCESS; + } + + g_ipcCallBackList.ctx = new(std::nothrow) IpcCallBackNode[IPC_CALL_BACK_MAX_NODES]; + if (g_ipcCallBackList.ctx == nullptr) { + LOGE("initialized failed"); + return HC_ERROR; + } + for (i = 0; i < IPC_CALL_BACK_MAX_NODES; i++) { + SetIpcCallBackNodeDefault(g_ipcCallBackList.ctx[i]); + } + g_ipcCallBackList.nodeCnt = 0; + LOGI("initialized successful"); + return HC_SUCCESS; +} + +static void ResetIpcCallBackNode(IpcCallBackNode &node) +{ + ServiceDevAuth::ResetRemoteObject(node.proxyId); + SetIpcCallBackNodeDefault(node); + return; +} + +void DeInitIpcCallBackList(void) +{ + int32_t i; + + std::lock_guard autoLock(g_cbListLock); + if (g_ipcCallBackList.ctx == nullptr) { + return; + } + for (i = 0; i < IPC_CALL_BACK_MAX_NODES; i++) { + ResetIpcCallBackNode(g_ipcCallBackList.ctx[i]); + } + delete g_ipcCallBackList.ctx; + g_ipcCallBackList.ctx = nullptr; + return; +} + +void ResetIpcCallBackNodeByNodeId(int32_t nodeIdx) +{ + LOGI("starting..., index %d", nodeIdx); + if ((nodeIdx < 0) || (nodeIdx >= IPC_CALL_BACK_MAX_NODES)) { + return; + } + std::lock_guard autoLock(g_cbListLock); + if (g_ipcCallBackList.ctx == nullptr) { + return; + } + ResetIpcCallBackNode(g_ipcCallBackList.ctx[nodeIdx]); + LOGI("done, index %d", nodeIdx); + return; +} + +static IpcCallBackNode *GetIpcCallBackByAppId(const char *appId, int32_t type) +{ + int32_t i; + int32_t ret; + + LOGI("appid: %s", appId); + for (i = 0; i < IPC_CALL_BACK_MAX_NODES; i++) { + if (g_ipcCallBackList.ctx[i].appId[0] == 0) { + continue; + } + ret = strcmp(g_ipcCallBackList.ctx[i].appId, appId); + if ((ret == 0) && (g_ipcCallBackList.ctx[i].cbType == type)) { + return &g_ipcCallBackList.ctx[i]; + } + } + return nullptr; +} + +static IpcCallBackNode *GetFreeIpcCallBackNode(void) +{ + int32_t i; + + for (i = 0; i < IPC_CALL_BACK_MAX_NODES; i++) { + if ((g_ipcCallBackList.ctx[i].appId[0] == 0) && (g_ipcCallBackList.ctx[i].cbType == 0)) { + g_ipcCallBackList.ctx[i].nodeIdx = i; + return &g_ipcCallBackList.ctx[i]; + } + } + return nullptr; +} + +static void SetCbDeathRecipient(int32_t type, int32_t objIdx, int32_t cbDataIdx) +{ + if ((type == CB_TYPE_DEV_AUTH) || (type == CB_TYPE_LISTENER)) { + ServiceDevAuth::SetCbDeathRecipient(objIdx, cbDataIdx); + } + return; +} + +void AddIpcCbObjByAppId(const char *appId, int32_t objIdx, int32_t type) +{ + IpcCallBackNode *node = nullptr; + + std::lock_guard autoLock(g_cbListLock); + if (g_ipcCallBackList.ctx == nullptr) { + LOGE("list not inited"); + return; + } + + if (g_ipcCallBackList.nodeCnt >= IPC_CALL_BACK_MAX_NODES) { + LOGE("list is full"); + return; + } + + node = GetIpcCallBackByAppId(appId, type); + if (node != nullptr) { + node->proxyId = objIdx; + SetCbDeathRecipient(type, objIdx, node->nodeIdx); + LOGI("ipc object add success, appid: %s, proxyId %d", appId, node->proxyId); + } + return; +} + +int32_t AddIpcCallBackByAppId(const char *appId, const uint8_t *cbPtr, int32_t cbSz, int32_t type) +{ + IpcCallBackNode *node = nullptr; + errno_t eno; + + std::lock_guard autoLock(g_cbListLock); + if (g_ipcCallBackList.ctx == nullptr) { + LOGE("list not inited"); + return HC_ERROR; + } + + if (g_ipcCallBackList.nodeCnt >= IPC_CALL_BACK_MAX_NODES) { + LOGE("list is full"); + return HC_ERROR; + } + + node = GetIpcCallBackByAppId(appId, type); + if (node != nullptr) { + eno = memcpy_s(&(node->cbCtx), sizeof(node->cbCtx), cbPtr, cbSz); + if (eno != EOK) { + LOGE("callback context memory copy failed"); + return HC_ERROR; + } + if (node->proxyId >= 0) { + ServiceDevAuth::ResetRemoteObject(node->proxyId); + node->proxyId = -1; + } + LOGI("callback add success, appid: %s", appId); + return HC_SUCCESS; + } + + LOGI("new callback to add, appid: %s", appId); + node = GetFreeIpcCallBackNode(); + if (node == nullptr) { + LOGE("get free node failed"); + return HC_ERROR; + } + node->cbType = type; + eno = memcpy_s(&(node->appId), sizeof(node->appId), appId, strlen(appId) + 1); + if (eno != EOK) { + ResetIpcCallBackNode(*node); + LOGE("appid memory copy failed"); + return HC_ERROR; + } + eno = memcpy_s(&(node->cbCtx), sizeof(node->cbCtx), cbPtr, cbSz); + if (eno != EOK) { + ResetIpcCallBackNode(*node); + LOGE("callback context memory copy failed"); + return HC_ERROR; + } + node->proxyId = -1; + g_ipcCallBackList.nodeCnt++; + LOGI("callback add success, appid: %s, type %d", node->appId, node->cbType); + return HC_SUCCESS; +} + +void DelIpcCallBackByAppId(const char *appId, int32_t type) +{ + IpcCallBackNode *node = nullptr; + + std::lock_guard autoLock(g_cbListLock); + if ((g_ipcCallBackList.nodeCnt <= 0) || (g_ipcCallBackList.ctx == nullptr)) { + return; + } + + node = GetIpcCallBackByAppId(appId, type); + if (node != nullptr) { + ResetIpcCallBackNode(*node); + g_ipcCallBackList.nodeCnt--; + } + return; +} + +static IpcCallBackNode *GetIpcCallBackByReqId(int64_t reqId, int32_t type) +{ + int32_t i; + + for (i = 0; i < IPC_CALL_BACK_MAX_NODES; i++) { + if ((reqId == g_ipcCallBackList.ctx[i].requestId) && + (g_ipcCallBackList.ctx[i].cbType == type)) { + return &g_ipcCallBackList.ctx[i]; + } + } + return nullptr; +} + +int32_t AddReqIdByAppId(const char *appId, int64_t reqId) +{ + IpcCallBackNode *node = nullptr; + + std::lock_guard autoLock(g_cbListLock); + if (g_ipcCallBackList.ctx == nullptr) { + LOGE("ipc callback list not inited"); + return HC_ERROR; + } + + node = GetIpcCallBackByAppId(appId, CB_TYPE_DEV_AUTH); + if (node == nullptr) { + LOGE("ipc callback node not found, appid: %s", appId); + return HC_ERROR; + } + node->requestId = reqId; + node->delOnFni = 0; + LOGI("success, appid: %s, requestId: %lld", appId, reqId); + return HC_SUCCESS; +} + +void AddIpcCbObjByReqId(int64_t reqId, int32_t objIdx, int32_t type) +{ + IpcCallBackNode *node = nullptr; + + std::lock_guard autoLock(g_cbListLock); + if (g_ipcCallBackList.ctx == nullptr) { + LOGE("list not inited"); + return; + } + + if (g_ipcCallBackList.nodeCnt >= IPC_CALL_BACK_MAX_NODES) { + LOGE("list is full"); + return; + } + + node = GetIpcCallBackByReqId(reqId, type); + if (node != nullptr) { + node->proxyId = objIdx; + LOGI("ipc object add success, request id %lld, type %d, proxy id %d", + reqId, type, node->proxyId); + } + return; +} + +int32_t AddIpcCallBackByReqId(int64_t reqId, const uint8_t *cbPtr, int32_t cbSz, int32_t type) +{ + IpcCallBackNode *node = nullptr; + errno_t eno; + + std::lock_guard autoLock(g_cbListLock); + if (g_ipcCallBackList.ctx == nullptr) { + LOGE("list is full"); + return HC_ERROR; + } + + if (g_ipcCallBackList.nodeCnt >= IPC_CALL_BACK_MAX_NODES) { + LOGE("list is full"); + return HC_ERROR; + } + + node = GetIpcCallBackByReqId(reqId, type); + if (node != nullptr) { + eno = memcpy_s(&(node->cbCtx), sizeof(node->cbCtx), cbPtr, cbSz); + if (eno != EOK) { + LOGE("callback context memory copy failed"); + return HC_ERROR; + } + if (node->proxyId >= 0) { + ServiceDevAuth::ResetRemoteObject(node->proxyId); + node->proxyId = -1; + } + LOGI("callback added success, request id %lld, type %d", reqId, type); + return HC_SUCCESS; + } + + LOGI("new callback to add, request id %lld, type %d", reqId, type); + node = GetFreeIpcCallBackNode(); + if (node == nullptr) { + LOGE("get free node failed"); + return HC_ERROR; + } + node->cbType = type; + node->requestId = reqId; + eno = memcpy_s(&(node->cbCtx), sizeof(node->cbCtx), cbPtr, cbSz); + if (eno != EOK) { + ResetIpcCallBackNode(*node); + LOGE("callback context memory copy failed"); + return HC_ERROR; + } + node->delOnFni = 1; + node->proxyId = -1; + g_ipcCallBackList.nodeCnt++; + LOGI("callback added success, request id %lld, type %d", reqId, type); + return HC_SUCCESS; +} + +static void DelCallBackByReqId(int64_t reqId, int32_t type) +{ + IpcCallBackNode *node = nullptr; + + if ((g_ipcCallBackList.nodeCnt <= 0) || (g_ipcCallBackList.ctx == nullptr)) { + return; + } + + node = GetIpcCallBackByReqId(reqId, type); + if ((node != nullptr) && (node->delOnFni == 1)) { + ResetIpcCallBackNode(*node); + g_ipcCallBackList.nodeCnt--; + } + return; +} + +void DelIpcCallBackByReqId(int64_t reqId, int32_t type, bool withLock) +{ + if (withLock) { + std::lock_guard autoLock(g_cbListLock); + DelCallBackByReqId(reqId, type); + return; + } + DelCallBackByReqId(reqId, type); + return; +} + +static void OnTransmitStub(uintptr_t cbHook, const IpcDataInfo *cbDataCache, int32_t cacheNum, MessageParcel &reply) +{ + int64_t requestId = 0; + int32_t inOutLen = 0; + uint8_t *data = nullptr; + uint32_t dataLen = 0u; + bool bRet = false; + bool (*onTransmitHook)(int64_t, uint8_t *, uint32_t) = nullptr; + + onTransmitHook = reinterpret_cast(cbHook); + inOutLen = sizeof(requestId); + (void)GetIpcRequestParamByType(cbDataCache, cacheNum, PARAM_TYPE_REQID, + reinterpret_cast(&requestId), &inOutLen); + (void)GetIpcRequestParamByType(cbDataCache, cacheNum, + PARAM_TYPE_COMM_DATA, (uint8_t *)&data, reinterpret_cast(&dataLen)); + bRet = onTransmitHook(requestId, data, dataLen); + (bRet == true) ? reply.WriteInt32(HC_SUCCESS) : reply.WriteInt32(HC_ERROR); + return; +} + +static void OnSessKeyStub(uintptr_t cbHook, const IpcDataInfo *cbDataCache, int32_t cacheNum, MessageParcel &reply) +{ + int64_t requestId = 0; + int32_t inOutLen = 0; + uint8_t *keyData = nullptr; + uint32_t dataLen = 0u; + void (*onSessKeyHook)(int64_t, uint8_t *, uint32_t) = nullptr; + + (void)reply; + onSessKeyHook = reinterpret_cast(cbHook); + inOutLen = sizeof(requestId); + (void)GetIpcRequestParamByType(cbDataCache, cacheNum, PARAM_TYPE_REQID, + reinterpret_cast(&requestId), &inOutLen); + (void)GetIpcRequestParamByType(cbDataCache, cacheNum, PARAM_TYPE_SESS_KEY, + reinterpret_cast(&keyData), reinterpret_cast(&dataLen)); + onSessKeyHook(requestId, keyData, dataLen); + return; +} + +static void OnFinishStub(uintptr_t cbHook, const IpcDataInfo *cbDataCache, int32_t cacheNum, MessageParcel &reply) +{ + int64_t requestId = 0; + int32_t opCode = 0; + int32_t inOutLen = 0; + char *data = nullptr; + void (*onFinishHook)(int64_t, int32_t, char *) = nullptr; + + (void)reply; + onFinishHook = reinterpret_cast(cbHook); + inOutLen = sizeof(requestId); + (void)GetIpcRequestParamByType(cbDataCache, cacheNum, PARAM_TYPE_REQID, + reinterpret_cast(&requestId), &inOutLen); + inOutLen = sizeof(opCode); + (void)GetIpcRequestParamByType(cbDataCache, cacheNum, PARAM_TYPE_OPCODE, + reinterpret_cast(&opCode), &inOutLen); + (void)GetIpcRequestParamByType(cbDataCache, cacheNum, PARAM_TYPE_COMM_DATA, + reinterpret_cast(&data), nullptr); + onFinishHook(requestId, opCode, data); + return; +} + +static void OnErrorStub(uintptr_t cbHook, const IpcDataInfo *cbDataCache, int32_t cacheNum, MessageParcel &reply) +{ + int64_t requestId = 0; + int32_t opCode = 0; + int32_t errCode = 0; + int32_t inOutLen = 0; + char *errInfo = nullptr; + void (*onErrorHook)(int64_t, int32_t, int32_t, char *) = nullptr; + + onErrorHook = reinterpret_cast(cbHook); + inOutLen = sizeof(requestId); + (void)GetIpcRequestParamByType(cbDataCache, cacheNum, PARAM_TYPE_REQID, + reinterpret_cast(&requestId), &inOutLen); + inOutLen = sizeof(opCode); + (void)GetIpcRequestParamByType(cbDataCache, cacheNum, PARAM_TYPE_OPCODE, + reinterpret_cast(&opCode), &inOutLen); + (void)GetIpcRequestParamByType(cbDataCache, cacheNum, PARAM_TYPE_ERRCODE, + reinterpret_cast(&errCode), &inOutLen); + (void)GetIpcRequestParamByType(cbDataCache, cacheNum, PARAM_TYPE_ERR_INFO, + reinterpret_cast(&errInfo), nullptr); + onErrorHook(requestId, opCode, errCode, errInfo); + return; +} + +static void OnRequestStub(uintptr_t cbHook, const IpcDataInfo *cbDataCache, int32_t cacheNum, MessageParcel &reply) +{ + int64_t requestId = 0; + int32_t opCode = 0; + int32_t inOutLen = 0; + char *reqParams = nullptr; + char *reqResult = nullptr; + char *(*onReqHook)(int64_t, int32_t, char *) = nullptr; + + (void)reply; + onReqHook = reinterpret_cast(cbHook); + inOutLen = sizeof(requestId); + (void)GetIpcRequestParamByType(cbDataCache, cacheNum, PARAM_TYPE_REQID, + reinterpret_cast(&requestId), &inOutLen); + inOutLen = sizeof(opCode); + (void)GetIpcRequestParamByType(cbDataCache, cacheNum, PARAM_TYPE_OPCODE, + reinterpret_cast(&opCode), &inOutLen); + (void)GetIpcRequestParamByType(cbDataCache, cacheNum, PARAM_TYPE_REQ_INFO, + reinterpret_cast(&reqParams), nullptr); + reqResult = onReqHook(requestId, opCode, reqParams); + if (reqResult == nullptr) { + reply.WriteInt32(HC_ERROR); + return; + } + reply.WriteInt32(HC_SUCCESS); + reply.WriteCString(const_cast(reqResult)); + HcFree(reqResult); + reqResult = nullptr; + return; +} + +static void OnGroupCreatedStub(uintptr_t cbHook, const IpcDataInfo *cbDataCache, int32_t cacheNum, MessageParcel &reply) +{ + const char *groupInfo = nullptr; + void (*onGroupCreatedHook)(const char *) = nullptr; + + (void)reply; + onGroupCreatedHook = reinterpret_cast(cbHook); + (void)GetIpcRequestParamByType(cbDataCache, cacheNum, PARAM_TYPE_GROUP_INFO, + reinterpret_cast(&groupInfo), nullptr); + onGroupCreatedHook(groupInfo); + return; +} + +static void OnGroupDeletedStub(uintptr_t cbHook, const IpcDataInfo *cbDataCache, int32_t cacheNum, MessageParcel &reply) +{ + const char *groupInfo = nullptr; + void (*onDelGroupHook)(const char *) = nullptr; + + (void)reply; + onDelGroupHook = reinterpret_cast(cbHook); + (void)GetIpcRequestParamByType(cbDataCache, cacheNum, PARAM_TYPE_GROUP_INFO, + reinterpret_cast(&groupInfo), nullptr); + onDelGroupHook(groupInfo); + return; +} + +static void OnDevBoundStub(uintptr_t cbHook, const IpcDataInfo *cbDataCache, int32_t cacheNum, MessageParcel &reply) +{ + const char *groupInfo = nullptr; + const char *udid = nullptr; + void (*onDevBoundHook)(const char *, const char *) = nullptr; + + (void)reply; + onDevBoundHook = reinterpret_cast(cbHook); + (void)GetIpcRequestParamByType(cbDataCache, cacheNum, PARAM_TYPE_UDID, reinterpret_cast(&udid), nullptr); + (void)GetIpcRequestParamByType(cbDataCache, cacheNum, PARAM_TYPE_GROUP_INFO, + reinterpret_cast(&groupInfo), nullptr); + onDevBoundHook(udid, groupInfo); + return; +} + +static void OnDevUnboundStub(uintptr_t cbHook, const IpcDataInfo *cbDataCache, int32_t cacheNum, MessageParcel &reply) +{ + const char *groupInfo = nullptr; + const char *udid = nullptr; + void (*onDevUnBoundHook)(const char *, const char *) = nullptr; + + (void)reply; + onDevUnBoundHook = reinterpret_cast(cbHook); + (void)GetIpcRequestParamByType(cbDataCache, cacheNum, PARAM_TYPE_UDID, reinterpret_cast(&udid), nullptr); + (void)GetIpcRequestParamByType(cbDataCache, cacheNum, PARAM_TYPE_GROUP_INFO, + reinterpret_cast(&groupInfo), nullptr); + onDevUnBoundHook(udid, groupInfo); + return; +} + +static void OnDevUnTrustStub(uintptr_t cbHook, const IpcDataInfo *cbDataCache, int32_t cacheNum, MessageParcel &reply) +{ + const char *udid = nullptr; + void (*onDevUnTrustHook)(const char *) = nullptr; + + (void)reply; + onDevUnTrustHook = reinterpret_cast(cbHook); + (void)GetIpcRequestParamByType(cbDataCache, cacheNum, PARAM_TYPE_UDID, reinterpret_cast(&udid), nullptr); + onDevUnTrustHook(udid); + return; +} + +static void OnDelLastGroupStub(uintptr_t cbHook, const IpcDataInfo *cbDataCache, int32_t cacheNum, MessageParcel &reply) +{ + const char *udid = nullptr; + int32_t groupType = 0; + int32_t inOutLen = 0; + void (*onDelLastGroupHook)(const char *, int32_t) = nullptr; + + (void)reply; + onDelLastGroupHook = reinterpret_cast(cbHook); + (void)GetIpcRequestParamByType(cbDataCache, cacheNum, PARAM_TYPE_UDID, reinterpret_cast(&udid), nullptr); + inOutLen = sizeof(groupType); + (void)GetIpcRequestParamByType(cbDataCache, cacheNum, PARAM_TYPE_GROUP_TYPE, + reinterpret_cast(&groupType), &inOutLen); + onDelLastGroupHook(udid, groupType); + return; +} + +static void OnTrustDevNumChangedStub(uintptr_t cbHook, + const IpcDataInfo *cbDataCache, int32_t cacheNum, MessageParcel &reply) +{ + int32_t devNum = 0; + int32_t inOutLen = 0; + void (*onTrustDevNumChangedHook)(int32_t) = nullptr; + + (void)reply; + onTrustDevNumChangedHook = reinterpret_cast(cbHook); + inOutLen = sizeof(devNum); + (void)GetIpcRequestParamByType(cbDataCache, cacheNum, PARAM_TYPE_DATA_NUM, + reinterpret_cast(&devNum), &inOutLen); + onTrustDevNumChangedHook(devNum); + return; +} + +void ProcCbHook(int32_t callbackId, uintptr_t cbHook, + const IpcDataInfo *cbDataCache, int32_t cacheNum, uintptr_t replyCtx) +{ + CallbackStub stubTable[] = { + OnTransmitStub, OnSessKeyStub, OnFinishStub, OnErrorStub, + OnRequestStub, OnGroupCreatedStub, OnGroupDeletedStub, OnDevBoundStub, + OnDevUnboundStub, OnDevUnTrustStub, OnDelLastGroupStub, OnTrustDevNumChangedStub + }; + MessageParcel *reply = nullptr; + + reply = reinterpret_cast(replyCtx); + LOGI("Process call back hook, callback id %d", callbackId); + if ((callbackId < CB_ID_ON_TRANS) || (callbackId > CB_ID_ON_TRUST_DEV_NUM_CHANGED)) { + LOGE("Invalid call back id"); + return; + } + if (cbHook == 0x0) { + LOGE("Invalid call back hook"); + return; + } + stubTable[callbackId - 1](cbHook, cbDataCache, cacheNum, *reply); + LOGI("ProcCbHook done"); + return; +} + +static int32_t EncodeCallData(MessageParcel &dataParcel, int32_t type, const uint8_t *param, int32_t paramSz) +{ + const uint8_t *paramTmp = nullptr; + int32_t zeroVal = 0; + + paramTmp = param; + if ((param == nullptr) || (paramSz == 0)) { + paramTmp = reinterpret_cast(&zeroVal); + paramSz = sizeof(zeroVal); + } + if (dataParcel.WriteInt32(type) && dataParcel.WriteInt32(paramSz) && + dataParcel.WriteBuffer(reinterpret_cast(paramTmp), static_cast(paramSz))) { + return HC_SUCCESS; + } + return HC_ERROR; +} + +/* group auth callback adapter */ +static bool GaCbOnTransmitWithType(int64_t requestId, const uint8_t *data, uint32_t dataLen, int32_t type) +{ + int32_t ret = -1; + MessageParcel dataParcel; + MessageParcel reply; + IpcCallBackNode *node = nullptr; + + LOGI("starting ... request id: %lld, type %d", requestId, type); + std::lock_guard autoLock(g_cbListLock); + node = GetIpcCallBackByReqId(requestId, type); + if (node == nullptr) { + LOGE("onTransmit hook is null, request id %lld", requestId); + return false; + } + ret = EncodeCallData(dataParcel, PARAM_TYPE_REQID, + reinterpret_cast(&requestId), sizeof(requestId)); + ret += EncodeCallData(dataParcel, PARAM_TYPE_COMM_DATA, data, dataLen); + if (ret != HC_SUCCESS) { + LOGE("build trans data failed"); + return false; + } + ServiceDevAuth::ActCallback(node->proxyId, CB_ID_ON_TRANS, + reinterpret_cast(node->cbCtx.devAuth.onTransmit), dataParcel, reply); + LOGI("process done, request id: %lld", requestId); + if (reply.ReadInt32(ret) && (ret == HC_SUCCESS)) { + return true; + } + return false; +} + +static bool IpcGaCbOnTransmit(int64_t requestId, const uint8_t *data, uint32_t dataLen) +{ + return GaCbOnTransmitWithType(requestId, data, dataLen, CB_TYPE_DEV_AUTH); +} + +static bool TmpIpcGaCbOnTransmit(int64_t requestId, const uint8_t *data, uint32_t dataLen) +{ + return GaCbOnTransmitWithType(requestId, data, dataLen, CB_TYPE_TMP_DEV_AUTH); +} + +static void GaCbOnSessionKeyRetWithType(int64_t requestId, const uint8_t *sessKey, uint32_t sessKeyLen, int32_t type) +{ + int32_t ret; + MessageParcel dataParcel; + MessageParcel reply; + IpcCallBackNode *node = nullptr; + + LOGI("starting ... request id: %lld, type %d", requestId, type); + std::lock_guard autoLock(g_cbListLock); + node = GetIpcCallBackByReqId(requestId, type); + if (node == nullptr) { + LOGE("onSessionKeyReturned hook is null, request id %lld", requestId); + return; + } + + ret = EncodeCallData(dataParcel, PARAM_TYPE_REQID, reinterpret_cast(&requestId), sizeof(requestId)); + ret += EncodeCallData(dataParcel, PARAM_TYPE_SESS_KEY, sessKey, sessKeyLen); + if (ret != HC_SUCCESS) { + LOGE("build trans data failed"); + return; + } + ServiceDevAuth::ActCallback(node->proxyId, CB_ID_SESS_KEY_DONE, + reinterpret_cast(node->cbCtx.devAuth.onSessionKeyReturned), dataParcel, reply); + LOGI("process done, request id: %lld", requestId); + return; +} + +static void IpcGaCbOnSessionKeyReturned(int64_t requestId, const uint8_t *sessKey, uint32_t sessKeyLen) +{ + GaCbOnSessionKeyRetWithType(requestId, sessKey, sessKeyLen, CB_TYPE_DEV_AUTH); + return; +} + +static void TmpIpcGaCbOnSessionKeyReturned(int64_t requestId, const uint8_t *sessKey, uint32_t sessKeyLen) +{ + GaCbOnSessionKeyRetWithType(requestId, sessKey, sessKeyLen, CB_TYPE_TMP_DEV_AUTH); + return; +} + +static void GaCbOnFinishWithType(int64_t requestId, int32_t operationCode, const char *returnData, int32_t type) +{ + int32_t ret; + MessageParcel dataParcel; + MessageParcel reply; + IpcCallBackNode *node = nullptr; + + LOGI("starting ... request id: %lld, type %d", requestId, type); + std::lock_guard autoLock(g_cbListLock); + node = GetIpcCallBackByReqId(requestId, type); + if (node == nullptr) { + LOGE("onFinish hook is null, request id %lld", requestId); + return; + } + ret = EncodeCallData(dataParcel, PARAM_TYPE_REQID, reinterpret_cast(&requestId), sizeof(requestId)); + ret += EncodeCallData(dataParcel, PARAM_TYPE_OPCODE, + reinterpret_cast(&operationCode), sizeof(operationCode)); + ret += EncodeCallData(dataParcel, PARAM_TYPE_COMM_DATA, + reinterpret_cast(returnData), strlen(returnData) + 1); + if (ret != HC_SUCCESS) { + LOGE("build trans data failed"); + return; + } + ServiceDevAuth::ActCallback(node->proxyId, CB_ID_ON_FINISH, + reinterpret_cast(node->cbCtx.devAuth.onFinish), dataParcel, reply); + /* delete request id */ + DelIpcCallBackByReqId(requestId, type, false); + LOGI("process done, request id: %lld", requestId); + return; +} + +static void IpcGaCbOnFinish(int64_t requestId, int32_t operationCode, const char *returnData) +{ + GaCbOnFinishWithType(requestId, operationCode, returnData, CB_TYPE_DEV_AUTH); + return; +} + +static void TmpIpcGaCbOnFinish(int64_t requestId, int32_t operationCode, const char *returnData) +{ + GaCbOnFinishWithType(requestId, operationCode, returnData, CB_TYPE_TMP_DEV_AUTH); + return; +} + +static void GaCbOnErrorWithType(int64_t requestId, int32_t operationCode, + int32_t errorCode, const char *errorReturn, int32_t type) +{ + int32_t ret; + MessageParcel dataParcel; + MessageParcel reply; + IpcCallBackNode *node = nullptr; + + LOGI("starting ... request id: %lld, type %d", requestId, type); + std::lock_guard autoLock(g_cbListLock); + node = GetIpcCallBackByReqId(requestId, type); + if (node == nullptr) { + LOGE("onError hook is null, request id %lld", requestId); + return; + } + ret = EncodeCallData(dataParcel, PARAM_TYPE_REQID, reinterpret_cast(&requestId), sizeof(requestId)); + ret += EncodeCallData(dataParcel, PARAM_TYPE_OPCODE, + reinterpret_cast(&operationCode), sizeof(operationCode)); + ret += EncodeCallData(dataParcel, PARAM_TYPE_ERRCODE, reinterpret_cast(&errorCode), sizeof(errorCode)); + if (errorReturn != nullptr) { + ret += EncodeCallData(dataParcel, PARAM_TYPE_ERR_INFO, + reinterpret_cast(errorReturn), strlen(errorReturn) + 1); + } + if (ret != HC_SUCCESS) { + LOGE("build trans data failed"); + return; + } + ServiceDevAuth::ActCallback(node->proxyId, CB_ID_ON_ERROR, + reinterpret_cast(node->cbCtx.devAuth.onError), dataParcel, reply); + /* delete request id */ + DelIpcCallBackByReqId(requestId, type, false); + LOGI("process done, request id: %lld", requestId); + return; +} + +static void IpcGaCbOnError(int64_t requestId, int32_t operationCode, int32_t errorCode, const char *errorReturn) +{ + GaCbOnErrorWithType(requestId, operationCode, errorCode, errorReturn, CB_TYPE_DEV_AUTH); + return; +} + +static void TmpIpcGaCbOnError(int64_t requestId, int32_t operationCode, int32_t errorCode, const char *errorReturn) +{ + GaCbOnErrorWithType(requestId, operationCode, errorCode, errorReturn, CB_TYPE_TMP_DEV_AUTH); + return; +} + +static char *GaCbOnRequestWithType(int64_t requestId, int32_t operationCode, const char *reqParams, int32_t type) +{ + int32_t ret = -1; + MessageParcel dataParcel; + MessageParcel reply; + const char *dPtr = nullptr; + IpcCallBackNode *node = nullptr; + + LOGI("starting ... request id: %lld, type %d", requestId, type); + std::lock_guard autoLock(g_cbListLock); + node = GetIpcCallBackByReqId(requestId, type); + if (node == nullptr) { + LOGE("onRequest hook is null, request id %lld", requestId); + return nullptr; + } + + ret = EncodeCallData(dataParcel, PARAM_TYPE_REQID, reinterpret_cast(&requestId), sizeof(requestId)); + ret += EncodeCallData(dataParcel, PARAM_TYPE_OPCODE, + reinterpret_cast(&operationCode), sizeof(operationCode)); + if (reqParams != nullptr) { + ret += EncodeCallData(dataParcel, PARAM_TYPE_REQ_INFO, + reinterpret_cast(reqParams), strlen(reqParams) + 1); + } + if (ret != HC_SUCCESS) { + LOGE("build trans data failed"); + return nullptr; + } + + ServiceDevAuth::ActCallback(node->proxyId, CB_ID_ON_REQUEST, + reinterpret_cast(node->cbCtx.devAuth.onRequest), dataParcel, reply); + if (reply.ReadInt32(ret) && (ret == HC_SUCCESS)) { + if (reply.GetReadableBytes() == 0) { + LOGE("onRequest has no data, but success"); + return nullptr; + } + dPtr = reply.ReadCString(); + LOGI("process done, request id: %lld, %s string", requestId, (dPtr != nullptr) ? "valid" : "invalid"); + return (dPtr != nullptr) ? strdup(dPtr) : nullptr; + } + return nullptr; +} + +static char *IpcGaCbOnRequest(int64_t requestId, int32_t operationCode, const char *reqParams) +{ + return GaCbOnRequestWithType(requestId, operationCode, reqParams, CB_TYPE_DEV_AUTH); +} + +static char *TmpIpcGaCbOnRequest(int64_t requestId, int32_t operationCode, const char *reqParams) +{ + return GaCbOnRequestWithType(requestId, operationCode, reqParams, CB_TYPE_TMP_DEV_AUTH); +} + +void IpcOnGroupCreated(const char *groupInfo) +{ + int32_t i; + int32_t ret; + MessageParcel dataParcel; + MessageParcel reply; + DataChangeListener *listener = nullptr; + + std::lock_guard autoLock(g_cbListLock); + if (g_ipcCallBackList.ctx == nullptr) { + LOGE("IpcCallBackList un-initialized"); + return; + } + + if (groupInfo == nullptr) { + LOGE("IpcOnGroupCreated, params error"); + return; + } + + ret = EncodeCallData(dataParcel, PARAM_TYPE_GROUP_INFO, + reinterpret_cast(groupInfo), strlen(groupInfo) + 1); + if (ret != HC_SUCCESS) { + LOGE("IpcGaCbOnRequest, build trans data failed"); + return; + } + + for (i = 0; i < IPC_CALL_BACK_MAX_NODES; i++) { + if (g_ipcCallBackList.ctx[i].cbType == CB_TYPE_LISTENER) { + listener = &(g_ipcCallBackList.ctx[i].cbCtx.listener); + if (listener->onGroupCreated == nullptr) { + LOGE("onGroupCreated hook is invalid"); + continue; + } + ServiceDevAuth::ActCallback(g_ipcCallBackList.ctx[i].proxyId, CB_ID_ON_GROUP_CREATED, + reinterpret_cast(listener->onGroupCreated), dataParcel, reply); + } + } + return; +} + +void IpcOnGroupDeleted(const char *groupInfo) +{ + int32_t i; + int32_t ret; + MessageParcel dataParcel; + MessageParcel reply; + DataChangeListener *listener = nullptr; + + std::lock_guard autoLock(g_cbListLock); + if (g_ipcCallBackList.ctx == nullptr) { + LOGE("IpcCallBackList un-initialized"); + return; + } + + if (groupInfo == nullptr) { + LOGE("IpcOnGroupDeleted, params error"); + return; + } + + ret = EncodeCallData(dataParcel, PARAM_TYPE_GROUP_INFO, + reinterpret_cast(groupInfo), strlen(groupInfo) + 1); + if (ret != HC_SUCCESS) { + LOGE("IpcGaCbOnRequest, build trans data failed"); + return; + } + + for (i = 0; i < IPC_CALL_BACK_MAX_NODES; i++) { + if (g_ipcCallBackList.ctx[i].cbType == CB_TYPE_LISTENER) { + listener = &(g_ipcCallBackList.ctx[i].cbCtx.listener); + if (listener->onGroupDeleted == nullptr) { + LOGE("onGroupDeleted hook is null"); + continue; + } + ServiceDevAuth::ActCallback(g_ipcCallBackList.ctx[i].proxyId, CB_ID_ON_GROUP_DELETED, + reinterpret_cast(listener->onGroupDeleted), dataParcel, reply); + } + } + return; +} + +void IpcOnDeviceBound(const char *peerUdid, const char *groupInfo) +{ + int32_t i; + int32_t ret; + MessageParcel dataParcel; + MessageParcel reply; + DataChangeListener *listener = nullptr; + + std::lock_guard autoLock(g_cbListLock); + if (g_ipcCallBackList.ctx == nullptr) { + LOGE("IpcCallBackList un-initialized"); + return; + } + + if ((peerUdid == nullptr) || (groupInfo == nullptr)) { + LOGE("params error"); + return; + } + + ret = EncodeCallData(dataParcel, PARAM_TYPE_UDID, + reinterpret_cast(peerUdid), strlen(peerUdid) + 1); + ret += EncodeCallData(dataParcel, PARAM_TYPE_GROUP_INFO, + reinterpret_cast(groupInfo), strlen(groupInfo) + 1); + if (ret != HC_SUCCESS) { + LOGE("build trans data failed"); + return; + } + + for (i = 0; i < IPC_CALL_BACK_MAX_NODES; i++) { + if (g_ipcCallBackList.ctx[i].cbType == CB_TYPE_LISTENER) { + listener = &(g_ipcCallBackList.ctx[i].cbCtx.listener); + if (listener->onDeviceBound == nullptr) { + LOGE("onDeviceBound hook is null"); + continue; + } + ServiceDevAuth::ActCallback(g_ipcCallBackList.ctx[i].proxyId, CB_ID_ON_DEV_BOUND, + reinterpret_cast(listener->onDeviceBound), dataParcel, reply); + } + } + return; +} + +void IpcOnDeviceUnBound(const char *peerUdid, const char *groupInfo) +{ + int32_t i; + int32_t ret; + MessageParcel dataParcel; + MessageParcel reply; + DataChangeListener *listener = nullptr; + + std::lock_guard autoLock(g_cbListLock); + if (g_ipcCallBackList.ctx == nullptr) { + LOGE("IpcCallBackList un-initialized"); + return; + } + + if ((peerUdid == nullptr) || (groupInfo == nullptr)) { + LOGE("params error"); + return; + } + + ret = EncodeCallData(dataParcel, PARAM_TYPE_UDID, + reinterpret_cast(peerUdid), strlen(peerUdid) + 1); + ret += EncodeCallData(dataParcel, PARAM_TYPE_GROUP_INFO, + reinterpret_cast(groupInfo), strlen(groupInfo) + 1); + if (ret != HC_SUCCESS) { + LOGE("build trans data failed"); + return; + } + + for (i = 0; i < IPC_CALL_BACK_MAX_NODES; i++) { + if (g_ipcCallBackList.ctx[i].cbType == CB_TYPE_LISTENER) { + listener = &(g_ipcCallBackList.ctx[i].cbCtx.listener); + if (listener->onDeviceUnBound == nullptr) { + LOGE("onDeviceUnBound hook is null"); + continue; + } + ServiceDevAuth::ActCallback(g_ipcCallBackList.ctx[i].proxyId, CB_ID_ON_DEV_UNBOUND, + reinterpret_cast(listener->onDeviceUnBound), dataParcel, reply); + } + } + return; +} + +void IpcOnDeviceNotTrusted(const char *peerUdid) +{ + int32_t i; + int32_t ret; + MessageParcel dataParcel; + MessageParcel reply; + DataChangeListener *listener = nullptr; + + std::lock_guard autoLock(g_cbListLock); + if (g_ipcCallBackList.ctx == nullptr) { + LOGE("IpcCallBackList un-initialized"); + return; + } + + if (peerUdid == nullptr) { + LOGE("params error"); + return; + } + + ret = EncodeCallData(dataParcel, PARAM_TYPE_UDID, + reinterpret_cast(peerUdid), strlen(peerUdid) + 1); + if (ret != HC_SUCCESS) { + LOGE("build trans data failed"); + return; + } + + for (i = 0; i < IPC_CALL_BACK_MAX_NODES; i++) { + if (g_ipcCallBackList.ctx[i].cbType == CB_TYPE_LISTENER) { + listener = &(g_ipcCallBackList.ctx[i].cbCtx.listener); + if (listener->onDeviceNotTrusted == nullptr) { + LOGE("onDeviceNotTrusted hook is null"); + continue; + } + ServiceDevAuth::ActCallback(g_ipcCallBackList.ctx[i].proxyId, CB_ID_ON_DEV_UNTRUSTED, + reinterpret_cast(listener->onDeviceNotTrusted), dataParcel, reply); + } + } + return; +} + +void IpcOnLastGroupDeleted(const char *peerUdid, int32_t groupType) +{ + int32_t i; + int32_t ret; + MessageParcel dataParcel; + MessageParcel reply; + DataChangeListener *listener = nullptr; + + std::lock_guard autoLock(g_cbListLock); + if (g_ipcCallBackList.ctx == nullptr) { + LOGE("IpcCallBackList un-initialized"); + return; + } + + if (peerUdid == nullptr) { + LOGE("params error"); + return; + } + + ret = EncodeCallData(dataParcel, PARAM_TYPE_UDID, + reinterpret_cast(peerUdid), strlen(peerUdid) + 1); + ret += EncodeCallData(dataParcel, PARAM_TYPE_GROUP_TYPE, + reinterpret_cast(&groupType), sizeof(groupType)); + if (ret != HC_SUCCESS) { + LOGE("build trans data failed"); + return; + } + + for (i = 0; i < IPC_CALL_BACK_MAX_NODES; i++) { + if (g_ipcCallBackList.ctx[i].cbType == CB_TYPE_LISTENER) { + listener = &(g_ipcCallBackList.ctx[i].cbCtx.listener); + if (listener->onLastGroupDeleted == nullptr) { + LOGE("onLastGroupDeleted hook is null"); + continue; + } + ServiceDevAuth::ActCallback(g_ipcCallBackList.ctx[i].proxyId, CB_ID_ON_LAST_GROUP_DELETED, + reinterpret_cast(listener->onLastGroupDeleted), dataParcel, reply); + } + } + return; +} + +void IpcOnTrustedDeviceNumChanged(int32_t curTrustedDeviceNum) +{ + int32_t i; + int32_t ret; + MessageParcel dataParcel; + MessageParcel reply; + DataChangeListener *listener = nullptr; + + std::lock_guard autoLock(g_cbListLock); + if (g_ipcCallBackList.ctx == nullptr) { + LOGE("IpcCallBackList un-initialized"); + return; + } + + ret = EncodeCallData(dataParcel, PARAM_TYPE_DATA_NUM, + reinterpret_cast(&curTrustedDeviceNum), sizeof(curTrustedDeviceNum)); + if (ret != HC_SUCCESS) { + LOGE("IpcOnTrustedDeviceNumChanged, build trans data failed"); + return; + } + + for (i = 0; i < IPC_CALL_BACK_MAX_NODES; i++) { + if (g_ipcCallBackList.ctx[i].cbType == CB_TYPE_LISTENER) { + listener = &(g_ipcCallBackList.ctx[i].cbCtx.listener); + if (listener->onTrustedDeviceNumChanged == nullptr) { + LOGE("onTrustedDeviceNumChanged hook is null"); + continue; + } + ServiceDevAuth::ActCallback(g_ipcCallBackList.ctx[i].proxyId, CB_ID_ON_TRUST_DEV_NUM_CHANGED, + reinterpret_cast(listener->onTrustedDeviceNumChanged), dataParcel, reply); + } + } + return; +} + +void InitDeviceAuthCbCtx(DeviceAuthCallback *ctx, int32_t type) +{ + if (ctx == nullptr) { + return; + } + if (type == CB_TYPE_DEV_AUTH) { + ctx->onTransmit = IpcGaCbOnTransmit; + ctx->onSessionKeyReturned = IpcGaCbOnSessionKeyReturned; + ctx->onFinish = IpcGaCbOnFinish; + ctx->onError = IpcGaCbOnError; + ctx->onRequest = IpcGaCbOnRequest; + } + if (type == CB_TYPE_TMP_DEV_AUTH) { + ctx->onTransmit = TmpIpcGaCbOnTransmit; + ctx->onSessionKeyReturned = TmpIpcGaCbOnSessionKeyReturned; + ctx->onFinish = TmpIpcGaCbOnFinish; + ctx->onError = TmpIpcGaCbOnError; + ctx->onRequest = TmpIpcGaCbOnRequest; + } + return; +} + +void InitDevAuthListenerCbCtx(DataChangeListener *ctx) +{ + if (ctx == nullptr) { + return; + } + ctx->onGroupCreated = IpcOnGroupCreated; + ctx->onGroupDeleted = IpcOnGroupDeleted; + ctx->onDeviceBound = IpcOnDeviceBound; + ctx->onDeviceUnBound = IpcOnDeviceUnBound; + ctx->onDeviceNotTrusted = IpcOnDeviceNotTrusted; + ctx->onLastGroupDeleted = IpcOnLastGroupDeleted; + ctx->onTrustedDeviceNumChanged = IpcOnTrustedDeviceNumChanged; + return; +} + +/* ipc client process adapter */ +int32_t CreateCallCtx(uintptr_t *callCtx, uintptr_t *cbCtx) +{ + ProxyDevAuthData *dataCache = nullptr; + + (void)cbCtx; + if (callCtx == nullptr) { + return HC_ERR_INVALID_PARAMS; + } + + dataCache = new(std::nothrow) ProxyDevAuthData(); + if (dataCache == nullptr) { + LOGE("call context alloc failed"); + return HC_ERR_ALLOC_MEMORY; + } + *callCtx = reinterpret_cast(dataCache); + return HC_SUCCESS; +} + +void DestroyCallCtx(uintptr_t *callCtx, uintptr_t *cbCtx) +{ + ProxyDevAuthData *dataCache = nullptr; + + (void)cbCtx; + if ((callCtx != nullptr) && (*callCtx != 0)) { + dataCache = reinterpret_cast(*callCtx); + delete dataCache; + *callCtx = 0; + } + return; +} + +void SetCbCtxToDataCtx(uintptr_t callCtx, int32_t cbIdx) +{ + ProxyDevAuthData *dataCache = nullptr; + sptr remote = g_sdkCbStub[cbIdx].AsObject(); + dataCache = reinterpret_cast(callCtx); + dataCache->SetCallbackStub(remote); + return; +} + +int32_t SetCallRequestParamInfo(uintptr_t callCtx, int32_t type, const uint8_t *param, int32_t paramSz) +{ + ProxyDevAuthData *dataCache = reinterpret_cast(callCtx); + + return dataCache->EncodeCallRequest(type, param, paramSz); +} + +int32_t DoBinderCall(uintptr_t callCtx, int32_t methodId, bool withSync) +{ + int32_t ret; + ProxyDevAuthData *dataCache = reinterpret_cast(callCtx); + + LOGI("proc method %d", methodId); + ret = dataCache->FinalCallRequest(methodId); + if (ret != HC_SUCCESS) { + return ret; + } + return dataCache->ActCall(withSync); +} + +/* ipc service process adapter */ +uint32_t SetIpcCallMap(uintptr_t ipcInstance, IpcServiceCall method, int32_t methodId) +{ + sptr service = nullptr; + if ((method == nullptr) || (methodId <= 0)) { + return static_cast(HC_ERR_INVALID_PARAMS); + } + + service = reinterpret_cast(ipcInstance); + return static_cast(service->SetCallMap(method, methodId)); +} + +int32_t CreateServiceInstance(uintptr_t *ipcInstance) +{ + ServiceDevAuth *service = nullptr; + service = new(std::nothrow) ServiceDevAuth(); + if (service == nullptr) { + return HC_ERR_ALLOC_MEMORY; + } + *ipcInstance = reinterpret_cast(service); + return HC_SUCCESS; +} + +void DestroyServiceInstance(uintptr_t *ipcInstance) +{ + sptr service = nullptr; + if (ipcInstance == nullptr) { + return; + } + service = reinterpret_cast(*ipcInstance); + if (service == nullptr) { + return; + } + delete service; + *ipcInstance = 0x0; + return; +} + +int32_t AddDevAuthServiceToManager(uintptr_t *serviceCtx) +{ + int32_t ret = ERR_OK; + ServiceDevAuth *sPtr = nullptr; + + sptr sysMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (sysMgr == nullptr) { + return HC_ERR_IPC_GET_SERVICE; + } + sPtr = new(std::nothrow) ServiceDevAuth(); + if (sPtr == nullptr) { + return HC_ERR_ALLOC_MEMORY; + } + ret = sysMgr->AddSystemAbility(DEVICE_AUTH_SERVICE_ID, sPtr); + if (ret != ERR_OK) { + LOGE("add service failed"); + return HC_ERROR; + } + *serviceCtx = reinterpret_cast(sPtr); + LOGI("AddSystemAbility to SA manager success"); + return HC_SUCCESS; +} + +int32_t IpcEncodeCallReplay(uintptr_t replayCache, int32_t type, const uint8_t *result, int32_t resultSz) +{ + int32_t errCnt = 0; + MessageParcel *replyParcel = nullptr; + unsigned long valZero = 0ul; + + replyParcel = reinterpret_cast(replayCache); + errCnt += replyParcel->WriteInt32(type) ? 0 : 1; + errCnt += replyParcel->WriteInt32(resultSz) ? 0 : 1; + if ((result != nullptr) && (resultSz > 0)) { + errCnt += replyParcel->WriteBuffer( + reinterpret_cast(result), static_cast(resultSz)) ? 0 : 1; + } else { + errCnt += replyParcel->WriteBuffer( + reinterpret_cast(&valZero), sizeof(unsigned long)) ? 0 : 1; + } + LOGI("reply type %d, %s", type, (errCnt == 0) ? "success" : "failed"); + return (errCnt == 0) ? HC_SUCCESS : HC_ERROR; +} + +int32_t DecodeIpcData(uintptr_t data, int32_t *type, uint8_t **val, int32_t *valSz) +{ + MessageParcel *dataPtr = nullptr; + + dataPtr = reinterpret_cast(data); + if (dataPtr->GetReadableBytes() == 0) { + return HC_SUCCESS; + } + if (sizeof(int32_t) > dataPtr->GetReadableBytes()) { + return HC_ERR_IPC_BAD_MESSAGE_LENGTH; + } + *type = dataPtr->ReadInt32(); + *valSz = dataPtr->ReadInt32(); + if (*valSz > static_cast(dataPtr->GetReadableBytes())) { + return HC_ERR_IPC_BAD_VAL_LENGTH; + } + *val = const_cast(dataPtr->ReadUnpadBuffer(*valSz)); + return HC_SUCCESS; +} + +void DecodeCallReply(uintptr_t callCtx, IpcDataInfo *replyCache, int32_t cacheNum) +{ + int32_t dataLen = 0; + int32_t i; + int32_t ret; + + ProxyDevAuthData *dataCache = reinterpret_cast(callCtx); + MessageParcel *tmpParcel = dataCache->GetReplyParcel(); + dataLen = tmpParcel->ReadInt32(); + if ((dataLen <= 0) || (dataLen != static_cast(tmpParcel->GetReadableBytes()))) { + LOGE("decode failed, data length %d", dataLen); + return; + } + + for (i = 0; i < cacheNum; i++) { + ret = DecodeIpcData(reinterpret_cast(tmpParcel), + &(replyCache[i].type), &(replyCache[i].val), &(replyCache[i].valSz)); + if (ret != HC_SUCCESS) { + return; + } + LOGI("decode success, type %d", replyCache[i].type); + } + return; +} + +static bool IsTypeForSettingPtr(int32_t type) +{ + int32_t typeList[] = { + PARAM_TYPE_APPID, PARAM_TYPE_DEV_AUTH_CB, PARAM_TYPE_LISTERNER, PARAM_TYPE_CREATE_PARAMS, + PARAM_TYPE_GROUPID, PARAM_TYPE_UDID, PARAM_TYPE_ADD_PARAMS, PARAM_TYPE_DEL_PARAMS, + PARAM_TYPE_BIND, PARAM_TYPE_UNBIND, PARAM_TYPE_CREDENTIAL, PARAM_TYPE_MGR_APPID, + PARAM_TYPE_FRIEND_APPID, PARAM_TYPE_QUERY_PARAMS, PARAM_TYPE_COMM_DATA, PARAM_TYPE_REQ_CFM, + PARAM_TYPE_SESS_KEY, PARAM_TYPE_REQ_INFO, PARAM_TYPE_GROUP_INFO, PARAM_TYPE_AUTH_PARAMS + }; + int32_t i; + int32_t n = sizeof(typeList) / sizeof(typeList[0]); + for (i = 0; i < n; i++) { + if (typeList[i] == type) { + return true; + } + } + return false; +} + +static bool IsTypeForCpyData(int32_t type) +{ + int32_t typeList[] = { + PARAM_TYPE_REQID, PARAM_TYPE_GROUP_TYPE, PARAM_TYPE_OPCODE, PARAM_TYPE_ERRCODE + }; + int32_t i; + int32_t n = sizeof(typeList) / sizeof(typeList[0]); + for (i = 0; i < n; i++) { + if (typeList[i] == type) { + return true; + } + } + return false; +} + +int32_t GetIpcRequestParamByType(const IpcDataInfo *ipcParams, int32_t paramNum, + int32_t type, uint8_t *paramCache, int32_t *cacheLen) +{ + int32_t i; + int32_t ret = HC_ERR_IPC_BAD_MSG_TYPE; + errno_t eno; + + for (i = 0; i < paramNum; i++) { + if (ipcParams[i].type != type) { + continue; + } + ret = HC_SUCCESS; + if (IsTypeForSettingPtr(type)) { + *(uint8_t **)paramCache = ipcParams[i].val; + if (cacheLen != NULL) { + *cacheLen = ipcParams[i].valSz; + } + break; + } + if (IsTypeForCpyData(type)) { + if ((ipcParams[i].val == nullptr) || (ipcParams[i].valSz <= 0)) { + ret = HC_ERR_INVALID_PARAMS; + break; + } + eno = memcpy_s(paramCache, *cacheLen, ipcParams[i].val, ipcParams[i].valSz); + if (eno != EOK) { + ret = HC_ERR_MEMORY_COPY; + } + *cacheLen = ipcParams[i].valSz; + break; + } + if ((type == PARAM_TYPE_CB_OBJECT) && (*(uint32_t *)cacheLen >= sizeof(ipcParams[i].idx))) { + *(int32_t *)paramCache = ipcParams[i].idx; + } + break; + } + LOGI("type %d, result 0x%x", type, ret); + return ret; +} + +bool IsCallbackMethod(int32_t methodId) +{ + if ((methodId == IPC_CALL_ID_REG_CB) || (methodId == IPC_CALL_ID_REG_LISTENER) || + (methodId == IPC_CALL_ID_GA_PROC_DATA) || (methodId == IPC_CALL_ID_AUTH_DEVICE)) { + return true; + } + return false; +} + +bool IsServiceRunning(void) +{ + LOGI("service activity check"); + return ProxyDevAuth::ServiceRunning(); +} + diff --git a/frameworks/src/ipc_callback_proxy.cpp b/frameworks/src/ipc_callback_proxy.cpp new file mode 100644 index 0000000..295b493 --- /dev/null +++ b/frameworks/src/ipc_callback_proxy.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ipc_callback_proxy.h" +#include "hc_log.h" +#include "ipc_adapt.h" +#include "system_ability_definition.h" + +namespace OHOS { +ProxyDevAuthCb::ProxyDevAuthCb(const sptr &impl) : IRemoteProxy(impl) +{} + +ProxyDevAuthCb::~ProxyDevAuthCb() +{} + +void ProxyDevAuthCb::DoCallBack(int32_t callbackId, uintptr_t cbHook, MessageParcel &dataParcel, MessageParcel &reply) +{ + int32_t ret; + MessageParcel data; + MessageOption option(MessageOption::TF_SYNC); + + sptr remote = Remote(); + if (remote == nullptr) { + LOGE("Proxy DoCallBack Remote() is null"); + return; + } + (void)data.WriteInt32(callbackId); + (void)data.WritePointer(cbHook); + if (dataParcel.GetDataSize() > 0) { + (void)data.WriteBuffer(reinterpret_cast(dataParcel.GetData()), dataParcel.GetDataSize()); + } + ret = remote->SendRequest(static_cast(DEV_AUTH_CALLBACK_REQUEST), data, reply, option); + if (ret != NO_ERROR) { + LOGE("SendRequest is failed, error code: %d", ret); + } + return; +} +} \ No newline at end of file diff --git a/frameworks/src/ipc_callback_stub.cpp b/frameworks/src/ipc_callback_stub.cpp new file mode 100644 index 0000000..c8bc0b0 --- /dev/null +++ b/frameworks/src/ipc_callback_stub.cpp @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ipc_callback_stub.h" +#include "common_defs.h" +#include "hc_log.h" +#include "ipc_adapt.h" +#include "securec.h" +#include "system_ability_definition.h" + +namespace OHOS { +StubDevAuthCb::StubDevAuthCb() +{} + +StubDevAuthCb::~StubDevAuthCb() +{} + +void StubDevAuthCb::DoCallBack(int32_t callbackId, uintptr_t cbHook, MessageParcel &dataParcel, MessageParcel &reply) +{ + int32_t ret; + int32_t i; + MessageParcel retParcel; + IpcDataInfo cbDataCache[MAX_REQUEST_PARAMS_NUM] = {{0}}; + + if (cbHook == 0x0) { + LOGE("Invalid call back hook"); + return; + } + + for (i = 0; i < MAX_REQUEST_PARAMS_NUM; i++) { + ret = DecodeIpcData(reinterpret_cast(&dataParcel), &(cbDataCache[i].type), + &(cbDataCache[i].val), &(cbDataCache[i].valSz)); + if (ret != HC_SUCCESS) { + LOGE("decode failed, ret %d", ret); + return; + } + } + ProcCbHook(callbackId, cbHook, cbDataCache, MAX_REQUEST_PARAMS_NUM, reinterpret_cast(&reply)); + return; +} + +int32_t StubDevAuthCb::OnRemoteRequest(uint32_t code, + MessageParcel &data, MessageParcel &reply, MessageOption &option) +{ + int32_t callbackId; + uintptr_t cbHook = 0x0; + + LOGI("enter invoking callback..."); + switch (code) { + case DEV_AUTH_CALLBACK_REQUEST: + callbackId = data.ReadInt32(); + cbHook = data.ReadPointer(); + StubDevAuthCb::DoCallBack(callbackId, cbHook, data, reply); + break; + default: + LOGE("Invoke call back cmd id error, %u", code); + break; + } + LOGI("Invoke callback done"); + return 0; +} +} \ No newline at end of file diff --git a/frameworks/src/ipc_dev_auth_proxy.cpp b/frameworks/src/ipc_dev_auth_proxy.cpp new file mode 100644 index 0000000..0b61897 --- /dev/null +++ b/frameworks/src/ipc_dev_auth_proxy.cpp @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ipc_dev_auth_proxy.h" + +#include "common_defs.h" +#include "hc_log.h" +#include "ipc_adapt.h" +#include "ipc_sdk.h" +#include "iservice_registry.h" +#include "system_ability_definition.h" + +namespace OHOS { +ProxyDevAuth::ProxyDevAuth(const sptr &impl) : IRemoteProxy(impl) +{} + +ProxyDevAuth::~ProxyDevAuth() +{} + +int32_t ProxyDevAuth::DoCallRequest(MessageParcel &dataParcel, MessageParcel &replyParcel, bool withSync) +{ + int32_t ret; + sptr remote = nullptr; + MessageOption option = { MessageOption::TF_SYNC }; + + LOGI("ProxyDevAuth, SendRequest..."); + remote = Remote(); + if (remote == nullptr) { + LOGE("Proxy DoCallRequest Remote() is null"); + return HC_ERR_IPC_INTERNAL_FAILED; + } + + if (withSync == false) { + option = { MessageOption::TF_ASYNC }; + } + ret = remote->SendRequest(DEV_AUTH_CALL_REQUEST, dataParcel, replyParcel, option); + LOGI("SendRequest done, ret %d", ret); + (ret == ERR_NONE) ? replyParcel.ReadInt32(ret) : (ret = HC_ERR_IPC_INTERNAL_FAILED); + return ret; +} + +bool ProxyDevAuth::ServiceRunning(void) +{ + auto saMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (saMgr == nullptr) { + return false; + } + auto daSa = saMgr->GetSystemAbility(DEVICE_AUTH_SERVICE_ID); + if (daSa == nullptr) { + return false; + } + return true; +} + +int32_t ProxyDevAuthData::EncodeCallRequest(int32_t type, const uint8_t *param, int32_t paramSz) +{ + LOGI("type %d, paramSz %d", type, paramSz); + if (tmpDataParcel.WriteInt32(type) && tmpDataParcel.WriteInt32(paramSz) && + tmpDataParcel.WriteBuffer(reinterpret_cast(param), static_cast(paramSz))) { + paramCnt++; + return HC_SUCCESS; + } + return HC_ERROR; +} + +int32_t ProxyDevAuthData::FinalCallRequest(int32_t methodId) +{ + int32_t dataLen; + const uint8_t *dataPtr = nullptr; + + dataLen = static_cast(tmpDataParcel.GetDataSize()); + dataPtr = const_cast(reinterpret_cast(tmpDataParcel.GetData())); + if ((dataLen <= 0) || (dataPtr == nullptr)) { + LOGE("data invalid"); + return HC_ERROR; + } + LOGI("method id %d, param num %d, data length %d", methodId, paramCnt, dataLen); + /* request data length = number of params + params information */ + if (!dataParcel.WriteInt32(methodId) || !dataParcel.WriteInt32(dataLen + sizeof(int32_t)) || + !dataParcel.WriteInt32(paramCnt)) { + return HC_ERROR; + } + if (!dataParcel.WriteBuffer(reinterpret_cast(dataPtr), static_cast(dataLen))) { + return HC_ERROR; + } + if (withCallback) { + if (!dataParcel.WriteInt32(PARAM_TYPE_CB_OBJECT) || !dataParcel.WriteRemoteObject(cbStub)) { + return HC_ERROR; + } + LOGI("type %d, cbStub %s", PARAM_TYPE_CB_OBJECT, (cbStub != nullptr) ? "true" : "false"); + } + cbStub = nullptr; + withCallback = false; + return HC_SUCCESS; +} + +sptr ProxyDevAuthData::GetProxy() const +{ + auto saMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (saMgr == nullptr) { + LOGE("GetSystemAbilityManager failed"); + return nullptr; + } + auto daSa = saMgr->GetSystemAbility(DEVICE_AUTH_SERVICE_ID); + if (daSa == nullptr) { + LOGE("GetSystemAbility failed"); + return nullptr; + } + + return iface_cast(daSa); +} + +int32_t ProxyDevAuthData::ActCall(bool withSync) +{ + auto proxy = GetProxy(); + if (proxy == nullptr) { + LOGE("proxy failed"); + return HC_ERR_IPC_GET_PROXY; + } + return proxy->DoCallRequest(dataParcel, replyParcel, withSync); +} + +MessageParcel *ProxyDevAuthData::GetReplyParcel(void) +{ + return &replyParcel; +} + +void ProxyDevAuthData::SetCallbackStub(sptr cbRemote) +{ + if (cbRemote != nullptr) { + this->cbStub = cbRemote; + withCallback = true; + } + return; +} +} diff --git a/frameworks/src/ipc_dev_auth_stub.cpp b/frameworks/src/ipc_dev_auth_stub.cpp new file mode 100644 index 0000000..18685f1 --- /dev/null +++ b/frameworks/src/ipc_dev_auth_stub.cpp @@ -0,0 +1,298 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ipc_dev_auth_stub.h" + +#include "common_defs.h" +#include "hc_log.h" +#include "ipc_adapt.h" +#include "ipc_callback_stub.h" +#include "ipc_sdk.h" +#include "securec.h" +#include "system_ability_definition.h" + +using namespace std; +namespace OHOS { +static std::mutex g_cBMutex; + +struct CbStubInfo { + sptr cbStub; + bool inUse; +}; +static struct CbStubInfo g_cbStub[MAX_CBSTUB_SIZE]; +static bool g_cbStubInited = false; + +ServiceDevAuth::ServiceDevAuth() +{} + +ServiceDevAuth::~ServiceDevAuth() +{ + maxCallMapSz = MAX_CALLMAP_SIZE; + if (callMapTable != nullptr) { + delete callMapTable; + callMapTable = nullptr; + } + callMapElemNum = 0; +} + +IpcServiceCall ServiceDevAuth::GetCallMethodByMethodId(int32_t methodId) +{ + int32_t i; + + if (callMapTable == nullptr) { + return nullptr; + } + + for (i = 0; i < maxCallMapSz; i++) { + if ((callMapTable[i].methodId == methodId) && (callMapTable[i].method != nullptr)) { + return callMapTable[i].method; + } + } + return nullptr; +} + +static int32_t DecodeCallRequest(MessageParcel &data, IpcDataInfo *paramsCache, int32_t cacheNum, int32_t &inParamNum) +{ + int32_t dataLen = 0; + int32_t i; + int32_t ret; + + if (data.GetReadableBytes() == 0) { + return HC_SUCCESS; + } + + data.ReadInt32(dataLen); + if (dataLen > static_cast(data.GetReadableBytes())) { + return HC_ERR_IPC_BAD_MESSAGE_LENGTH; + } + + data.ReadInt32(inParamNum); + if ((inParamNum < 0) || (inParamNum > cacheNum)) { + LOGE("param number invalid, inParamNum - %d", inParamNum); + return HC_ERR_IPC_BAD_PARAM_NUM; + } + LOGI("param number: %d", inParamNum); + + for (i = 0; i < inParamNum; i++) { + ret = DecodeIpcData(reinterpret_cast(&data), &(paramsCache[i].type), + &(paramsCache[i].val), &(paramsCache[i].valSz)); + if (ret != HC_SUCCESS) { + LOGE("decode failed, ret %d", ret); + return ret; + } + LOGI("decode success, param type %d, val size %d", paramsCache[i].type, paramsCache[i].valSz); + } + return HC_SUCCESS; +} + +static int32_t GetMethodId(MessageParcel &data, int32_t &methodId) +{ + if (data.GetDataSize() < sizeof(int32_t)) { + return HC_ERR_IPC_CALL_DATA_LENGTH; + } + methodId = data.ReadInt32(); + LOGI("GetMethodId, id code %d", methodId); + return HC_SUCCESS; +} + +static void WithObject(int32_t methodId, MessageParcel &data, IpcDataInfo &ipcData, int32_t &cnt) +{ + if (IsCallbackMethod(methodId)) { + ipcData.type = data.ReadInt32(); + ipcData.valSz = sizeof(StubDevAuthCb); + sptr tmp = data.ReadRemoteObject(); + if (!tmp) { + LOGE("should with remote object, but read failed"); + return; + } + ipcData.idx = ServiceDevAuth::SetRemoteObject(tmp); + if (ipcData.idx >= 0) { + ipcData.val = reinterpret_cast(&(ipcData.idx)); + LOGI("object trans success, set id %d", ipcData.idx); + cnt++; + } + } + return; +} + +static void InitCbStubTable() +{ + int32_t i; + if (g_cbStubInited) { + return; + } + std::lock_guard autoLock(g_cBMutex); + if (g_cbStubInited) { /* for first init at the same time */ + return; + } + for (i = 0; i < MAX_CBSTUB_SIZE; i++) { + g_cbStub[i].inUse = false; + } + g_cbStubInited = true; + return; +} + +int32_t ServiceDevAuth::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) +{ + int32_t ret = HC_ERR_IPC_UNKNOW_OPCODE; + int32_t dataLen; + int32_t methodId = 0; + int32_t reqParamNum = 0; + MessageParcel replyCache; + IpcDataInfo reqParams[MAX_REQUEST_PARAMS_NUM] = {{0}}; + IpcServiceCall serviceCall = nullptr; + + LOGI("request code %u", code); + switch (code) { + case DEV_AUTH_CALL_REQUEST: + ret = GetMethodId(data, methodId); + if (ret != HC_SUCCESS) { + break; + } + serviceCall = GetCallMethodByMethodId(methodId); + if (serviceCall == nullptr) { + ret = HC_ERR_IPC_METHOD_ID_INVALID; + break; + } + ret = DecodeCallRequest(data, reqParams, MAX_REQUEST_PARAMS_NUM, reqParamNum); + if (ret != HC_SUCCESS) { + break; + } + if (reqParamNum < (MAX_REQUEST_PARAMS_NUM - 1)) { + InitCbStubTable(); + WithObject(methodId, data, reqParams[reqParamNum], reqParamNum); + } + ret = serviceCall(reqParams, reqParamNum, reinterpret_cast(&replyCache)); + break; + default: + break; + } + reply.WriteInt32(ret); + dataLen = replyCache.GetDataSize(); + if (dataLen > 0) { + reply.WriteInt32(dataLen); + reply.WriteBuffer(reinterpret_cast(replyCache.GetData()), dataLen); + } + LOGI("done, request code %u, method id %d, call result %d", code, methodId, ret); + return 0; +} + +int32_t ServiceDevAuth::SetCallMap(IpcServiceCall method, int32_t methodId) +{ + int32_t len; + errno_t eno; + IpcServiceCallMap *callMapTmp = nullptr; + + if ((1 + callMapElemNum) > maxCallMapSz) { + maxCallMapSz += MAX_CALLMAP_SIZE; + if (callMapTable != nullptr) { + callMapTmp = callMapTable; + callMapTable = nullptr; + } + } + if (callMapTable == nullptr) { + callMapTable = new(std::nothrow) IpcServiceCallMap[maxCallMapSz]; + if (callMapTable == nullptr) { + return HC_ERR_ALLOC_MEMORY; + } + len = sizeof(IpcServiceCallMap) * maxCallMapSz; + (void)memset_s(callMapTable, len, 0, len); + if (callMapTmp != nullptr) { + eno = memcpy_s(callMapTable, len, callMapTmp, (sizeof(IpcServiceCallMap) * callMapElemNum)); + if (eno != EOK) { + delete callMapTable; + callMapTable = callMapTmp; + maxCallMapSz -= MAX_CALLMAP_SIZE; + return HC_ERR_MEMORY_COPY; + } + delete callMapTmp; + callMapTmp = nullptr; + } + } + callMapTable[callMapElemNum].method = method; + callMapTable[callMapElemNum].methodId = methodId; + callMapElemNum++; + return HC_SUCCESS; +} + +int32_t ServiceDevAuth::SetRemoteObject(sptr &object) +{ + int32_t idx = -1; + int32_t i; + + std::lock_guard autoLock(g_cBMutex); + for (i = 0; i < MAX_CBSTUB_SIZE; i++) { + if (!g_cbStub[i].inUse) { + idx = i; + break; + } + } + LOGI("remote object cache index %d", idx); + if (idx == -1) { + return -1; + } + g_cbStub[idx].cbStub = object; + g_cbStub[idx].inUse = true; + return idx; +} + +void ServiceDevAuth::SetCbDeathRecipient(int32_t objIdx, int32_t cbDataIdx) +{ + bool bRet = false; + if ((objIdx < 0) || (objIdx >= MAX_CBSTUB_SIZE) || (!g_cbStub[objIdx].inUse)) { + return; + } + + std::lock_guard autoLock(g_cBMutex); + bRet = g_cbStub[objIdx].cbStub->AddDeathRecipient(new(std::nothrow) DevAuthDeathRecipient(cbDataIdx)); + LOGI("AddDeathRecipient %s, callback stub idx %d", bRet ? "success" : "failed", objIdx); + return; +} + +void ServiceDevAuth::ResetRemoteObject(int32_t idx) +{ + if ((idx >= 0) && (idx < MAX_CBSTUB_SIZE)) { + LOGI("remote object used done, idx %d", idx); + std::lock_guard autoLock(g_cBMutex); + g_cbStub[idx].inUse = false; + } + return; +} + +void ServiceDevAuth::ActCallback(int32_t objIdx, int32_t callbackId, + uintptr_t cbHook, MessageParcel &dataParcel, MessageParcel &reply) +{ + if ((objIdx < 0) || (objIdx >= MAX_CBSTUB_SIZE) || (!g_cbStub[objIdx].inUse)) { + LOGW("nothing to do, callback id %d, remote object id %d", callbackId, objIdx); + return; + } + + std::lock_guard autoLock(g_cBMutex); + sptr proxy = iface_cast(g_cbStub[objIdx].cbStub); + proxy->DoCallBack(callbackId, cbHook, dataParcel, reply); + return; +} + +DevAuthDeathRecipient::DevAuthDeathRecipient(int32_t cbIdx) +{ + callbackIdx = cbIdx; +} + +void DevAuthDeathRecipient::OnRemoteDied(const wptr &remoteObject) +{ + LOGI("remote is not actively, to reset local resource"); + ResetIpcCallBackNodeByNodeId(callbackIdx); +} +} diff --git a/frameworks/src/ipc_sdk.c b/frameworks/src/ipc_sdk.c new file mode 100644 index 0000000..44123fd --- /dev/null +++ b/frameworks/src/ipc_sdk.c @@ -0,0 +1,2125 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ipc_sdk.h" + +#include "common_defs.h" +#include "device_auth_defines.h" +#include "device_auth.h" +#include "hc_log.h" +#include "hc_mutex.h" + +#include "ipc_adapt.h" +#include "securec.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define IPC_DATA_CACHES_3 3 +#define IPC_DATA_CACHES_4 4 +#define REPLAY_CACHE_NUM(caches) (sizeof(caches) / sizeof(IpcDataInfo)) +#define IPC_APPID_LEN 128 + +#define IS_STRING_VALID(str) (((str) != NULL) && ((str)[0] != 0)) + +typedef struct { + uintptr_t inst; + char appId[IPC_APPID_LEN]; +} IpcProxyCbInfo; +static IpcProxyCbInfo g_ipcProxyCbList = {0}; +static IpcProxyCbInfo g_ipcListenerCbList = {0}; +static HcMutex g_ipcMutex; + +static void DelIpcCliCallbackCtx(const char *appId, IpcProxyCbInfo *cbCache) +{ + int32_t ret; + + if (cbCache->appId[0] == 0) { + return; + } + g_ipcMutex.lock(&g_ipcMutex); + ret = memcmp(appId, cbCache->appId, strlen(cbCache->appId) + 1); + if (ret == 0) { + cbCache->appId[0] = 0; + } + g_ipcMutex.unlock(&g_ipcMutex); + return; +} + +static void AddIpcCliCallbackCtx(const char *appId, uintptr_t cbInst, IpcProxyCbInfo *cbCache) +{ + errno_t eno; + + LOGI("starting ..."); + g_ipcMutex.lock(&g_ipcMutex); + eno = memcpy_s(cbCache->appId, IPC_APPID_LEN, appId, strlen(appId) + 1); + if (eno != EOK) { + g_ipcMutex.unlock(&g_ipcMutex); + LOGE("memory copy failed"); + return; + } + cbCache->inst = cbInst; + g_ipcMutex.unlock(&g_ipcMutex); + LOGI("success, appid: %s", appId); + return; +} + +static void GetIpcReplyByType(const IpcDataInfo *ipcData, + int32_t dataNum, int32_t type, uint8_t *outCache, int32_t *cacheLen) +{ + int32_t i; + int32_t ret = HC_ERR_IPC_BAD_MSG_TYPE; + errno_t eno; + + LOGI("type %d", type); + for (i = 0; i < dataNum; i++) { + if (ipcData[i].type != type) { + continue; + } + ret = HC_SUCCESS; + switch (type) { + case PARAM_TYPE_REG_INFO: + case PARAM_TYPE_MGR_APPID: + case PARAM_TYPE_FRIEND_APPID: + case PARAM_TYPE_DEVICE_INFO: + case PARAM_TYPE_GROUP_INFO: + *(uint8_t **)outCache = ipcData[i].val; + if (cacheLen != NULL) { + *cacheLen = ipcData[i].valSz; + } + break; + case PARAM_TYPE_IPC_RESULT: + case PARAM_TYPE_IPC_RESULT_NUM: + case PARAM_TYPE_COMM_DATA: + case PARAM_TYPE_DATA_NUM: + eno = memcpy_s(outCache, *cacheLen, ipcData[i].val, ipcData[i].valSz); + if (eno != EOK) { + ret = HC_ERR_MEMORY_COPY; + break; + } + *cacheLen = ipcData[i].valSz; + break; + default: + ret = HC_ERR_IPC_BAD_MSG_TYPE; + LOGE("un-expectation type case"); + break; + } + } + LOGI("process done, type %d, result %d", type, ret); + return; +} + +static int32_t IpcGmRegCallback(const char *appId, const DeviceAuthCallback *callback) +{ + uintptr_t callCtx = 0x0; + int32_t ret; + + LOGI("starting ..."); + if (!IS_STRING_VALID(appId)) { + LOGE("invalid params"); + return HC_ERR_INVALID_PARAMS; + } + if (!IsServiceRunning()) { + LOGE("service is not activity"); + return HC_ERROR; + } + ret = CreateCallCtx(&callCtx, NULL); + if (ret != HC_SUCCESS) { + LOGE("CreateCallCtx failed, ret %d", ret); + return HC_ERR_IPC_INIT; + } + + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_APPID, (const uint8_t *)appId, strlen(appId) + 1); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, type %d", ret, PARAM_TYPE_APPID); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_DEV_AUTH_CB, (const uint8_t *)callback, sizeof(*callback)); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, type %d", ret, PARAM_TYPE_DEV_AUTH_CB); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + SetCbCtxToDataCtx(callCtx, IPC_CALL_BACK_STUB_BIND_ID); + ret = DoBinderCall(callCtx, IPC_CALL_ID_REG_CB, true); + if (ret == HC_SUCCESS) { + AddIpcCliCallbackCtx(appId, 0, &g_ipcProxyCbList); + } + DestroyCallCtx(&callCtx, NULL); + LOGI("process done, ret %d", ret); + return (ret == HC_SUCCESS) ? HC_SUCCESS : HC_ERR_IPC_PROC_FAILED; +} + +static int32_t IpcGmUnRegCallback(const char *appId) +{ + uintptr_t callCtx = 0x0; + int32_t ret; + + LOGI("starting ..."); + if (!IS_STRING_VALID(appId)) { + return HC_ERR_INVALID_PARAMS; + } + if (!IsServiceRunning()) { + LOGE("service is not activity"); + return HC_ERROR; + } + ret = CreateCallCtx(&callCtx, NULL); + if (ret != HC_SUCCESS) { + LOGE("CreateCallCtx failed, ret %d", ret); + return HC_ERR_IPC_INIT; + } + + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_APPID, (const uint8_t *)appId, strlen(appId) + 1); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d", ret); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = DoBinderCall(callCtx, IPC_CALL_ID_UNREG_CB, true); + if (ret == HC_SUCCESS) { + DelIpcCliCallbackCtx(appId, &g_ipcProxyCbList); + } + DestroyCallCtx(&callCtx, NULL); + LOGI("process done, ret %d", HC_SUCCESS); + return HC_SUCCESS; +} + +static int32_t IpcGmRegDataChangeListener(const char *appId, const DataChangeListener *listener) +{ + uintptr_t callCtx = 0x0; + int32_t ret; + + LOGI("starting ..."); + if (!IS_STRING_VALID(appId) || (listener == NULL)) { + LOGE("invalid params"); + return HC_ERR_INVALID_PARAMS; + } + if (!IsServiceRunning()) { + LOGE("service is not activity"); + return HC_ERROR; + } + ret = CreateCallCtx(&callCtx, NULL); + if (ret != HC_SUCCESS) { + LOGE("CreateCallCtx failed, ret %d", ret); + return HC_ERR_IPC_INIT; + } + + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_APPID, (const uint8_t *)appId, strlen(appId) + 1); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, type %d", ret, PARAM_TYPE_APPID); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_LISTERNER, (const uint8_t *)listener, sizeof(*listener)); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, type %d", ret, PARAM_TYPE_LISTERNER); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + SetCbCtxToDataCtx(callCtx, IPC_CALL_BACK_STUB_BIND_ID); + ret = DoBinderCall(callCtx, IPC_CALL_ID_REG_LISTENER, true); + if (ret == HC_SUCCESS) { + AddIpcCliCallbackCtx(appId, 0, &g_ipcListenerCbList); + } + DestroyCallCtx(&callCtx, NULL); + LOGI("process done, ret %d", ret); + return (ret == HC_SUCCESS) ? HC_SUCCESS : HC_ERR_IPC_PROC_FAILED; +} + +static int32_t IpcGmUnRegDataChangeListener(const char *appId) +{ + uintptr_t callCtx = 0x0; + int32_t ret; + + LOGI("starting ..."); + if (!IS_STRING_VALID(appId)) { + return HC_ERR_INVALID_PARAMS; + } + if (!IsServiceRunning()) { + LOGE("service is not activity"); + return HC_ERROR; + } + ret = CreateCallCtx(&callCtx, NULL); + if (ret != HC_SUCCESS) { + LOGE("CreateCallCtx failed, ret %d", ret); + return HC_ERR_IPC_INIT; + } + + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_APPID, (const uint8_t *)appId, strlen(appId) + 1); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d", ret); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = DoBinderCall(callCtx, IPC_CALL_ID_UNREG_LISTENER, true); + if (ret == HC_SUCCESS) { + DelIpcCliCallbackCtx(appId, &g_ipcListenerCbList); + } + DestroyCallCtx(&callCtx, NULL); + LOGI("process done"); + return HC_SUCCESS; +} + +static int32_t IpcGmCreateGroup(int64_t requestId, const char *appid, const char *createParams) +{ + uintptr_t callCtx = 0x0; + int32_t ret; + int32_t inOutLen; + IpcDataInfo replyCache = {0}; + + LOGI("starting ..."); + if (!IS_STRING_VALID(createParams) || !IS_STRING_VALID(appid)) { + return HC_ERR_INVALID_PARAMS; + } + if (!IsServiceRunning()) { + LOGE("service is not activity"); + return HC_ERROR; + } + ret = CreateCallCtx(&callCtx, NULL); + if (ret != HC_SUCCESS) { + LOGE("CreateCallCtx failed, ret %d", ret); + return HC_ERR_IPC_INIT; + } + + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_REQID, (const uint8_t *)&requestId, sizeof(requestId)); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_REQID); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_APPID, (const uint8_t *)appid, strlen(appid) + 1); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_CREATE_PARAMS); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_CREATE_PARAMS, + (const uint8_t *)createParams, strlen(createParams) + 1); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_CREATE_PARAMS); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = DoBinderCall(callCtx, IPC_CALL_ID_CREATE_GROUP, true); + if (ret == HC_ERR_IPC_INTERNAL_FAILED) { + LOGE("ipc call failed"); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_PROC_FAILED; + } + DecodeCallReply(callCtx, &replyCache, REPLAY_CACHE_NUM(replyCache)); + ret = HC_ERR_IPC_UNKNOW_REPLAY; + inOutLen = sizeof(int32_t); + GetIpcReplyByType(&replyCache, REPLAY_CACHE_NUM(replyCache), PARAM_TYPE_IPC_RESULT, (uint8_t *)&ret, &inOutLen); + DestroyCallCtx(&callCtx, NULL); + LOGI("process done, ret %d", ret); + return ret; +} + +static int32_t IpcGmDelGroup(int64_t requestId, const char *groupId, const char *appId) +{ + uintptr_t callCtx = 0x0; + int32_t ret; + int32_t inOutLen; + IpcDataInfo replyCache = {0}; + + LOGI("starting ..."); + if (!IS_STRING_VALID(groupId) || !IS_STRING_VALID(appId)) { + return HC_ERR_INVALID_PARAMS; + } + if (!IsServiceRunning()) { + LOGE("service is not activity"); + return HC_ERROR; + } + ret = CreateCallCtx(&callCtx, NULL); + if (ret != HC_SUCCESS) { + LOGE("CreateCallCtx failed, ret %d", ret); + return HC_ERR_IPC_INIT; + } + + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_REQID, (const uint8_t *)&requestId, sizeof(requestId)); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_REQID); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_GROUPID, (const uint8_t *)groupId, strlen(groupId) + 1); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_GROUPID); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_APPID, (const uint8_t *)appId, strlen(appId) + 1); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_APPID); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = DoBinderCall(callCtx, IPC_CALL_ID_DEL_GROUP, true); + if (ret == HC_ERR_IPC_INTERNAL_FAILED) { + LOGE("ipc call failed"); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_PROC_FAILED; + } + DecodeCallReply(callCtx, &replyCache, REPLAY_CACHE_NUM(replyCache)); + ret = HC_ERR_IPC_UNKNOW_REPLAY; + inOutLen = sizeof(int32_t); + GetIpcReplyByType(&replyCache, REPLAY_CACHE_NUM(replyCache), PARAM_TYPE_IPC_RESULT, (uint8_t *)&ret, &inOutLen); + DestroyCallCtx(&callCtx, NULL); + LOGI("process done, ret %d", ret); + return ret; +} + +static int32_t IpcGmAddMemberToGroup(int64_t requestId, const char *groupId, const char *addParams) +{ + uintptr_t callCtx = 0x0; + int32_t ret; + int32_t inOutLen; + IpcDataInfo replyCache = {0}; + + LOGI("starting ..."); + if (!IS_STRING_VALID(groupId) || !IS_STRING_VALID(addParams)) { + return HC_ERR_INVALID_PARAMS; + } + if (!IsServiceRunning()) { + LOGE("service is not activity"); + return HC_ERROR; + } + ret = CreateCallCtx(&callCtx, NULL); + if (ret != HC_SUCCESS) { + LOGE("CreateCallCtx failed, ret %d", ret); + return HC_ERR_IPC_INIT; + } + + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_REQID, (const uint8_t *)&requestId, sizeof(requestId)); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_REQID); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_GROUPID, (const uint8_t *)groupId, strlen(groupId) + 1); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_GROUPID); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_ADD_PARAMS, (const uint8_t *)addParams, strlen(addParams) + 1); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_ADD_PARAMS); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = DoBinderCall(callCtx, IPC_CALL_ID_ADD_GROUP_MEMBER, true); + if (ret == HC_ERR_IPC_INTERNAL_FAILED) { + LOGE("ipc call failed"); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_PROC_FAILED; + } + DecodeCallReply(callCtx, &replyCache, REPLAY_CACHE_NUM(replyCache)); + ret = HC_ERR_IPC_UNKNOW_REPLAY; + inOutLen = sizeof(int32_t); + GetIpcReplyByType(&replyCache, REPLAY_CACHE_NUM(replyCache), PARAM_TYPE_IPC_RESULT, (uint8_t *)&ret, &inOutLen); + DestroyCallCtx(&callCtx, NULL); + LOGI("process done, ret %d", ret); + return ret; +} + +static int32_t IpcGmDelMemberFromGroup(int64_t requestId, const char *appId, const char *delParams) +{ + uintptr_t callCtx = 0x0; + int32_t ret; + int32_t inOutLen; + IpcDataInfo replyCache = {0}; + + LOGI("starting ..."); + if (!IS_STRING_VALID(appId) || !IS_STRING_VALID(delParams)) { + return HC_ERR_INVALID_PARAMS; + } + if (!IsServiceRunning()) { + LOGE("service is not activity"); + return HC_ERROR; + } + ret = CreateCallCtx(&callCtx, NULL); + if (ret != HC_SUCCESS) { + LOGE("CreateCallCtx failed, ret %d", ret); + return HC_ERR_IPC_INIT; + } + + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_REQID, (const uint8_t *)&requestId, sizeof(requestId)); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_REQID); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_APPID, (const uint8_t *)appId, strlen(appId) + 1); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_APPID); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_DEL_PARAMS, (const uint8_t *)delParams, strlen(delParams) + 1); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_DEL_PARAMS); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = DoBinderCall(callCtx, IPC_CALL_ID_DEL_GROUP_MEMBER, true); + if (ret == HC_ERR_IPC_INTERNAL_FAILED) { + LOGE("ipc call failed"); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_PROC_FAILED; + } + DecodeCallReply(callCtx, &replyCache, REPLAY_CACHE_NUM(replyCache)); + ret = HC_ERR_IPC_UNKNOW_REPLAY; + inOutLen = sizeof(int32_t); + GetIpcReplyByType(&replyCache, REPLAY_CACHE_NUM(replyCache), PARAM_TYPE_IPC_RESULT, (uint8_t *)&ret, &inOutLen); + DestroyCallCtx(&callCtx, NULL); + LOGI("process done, ret %d", ret); + return ret; +} + +static int32_t IpcGmProcessData(int64_t requestId, const uint8_t *data, uint32_t dataLen) +{ + uintptr_t callCtx = 0x0; + int32_t ret; + int32_t inOutLen; + IpcDataInfo replyCache = {0}; + + LOGI("starting ..."); + if ((data == NULL) || (dataLen == 0)) { + return HC_ERR_INVALID_PARAMS; + } + if (!IsServiceRunning()) { + LOGE("service is not activity"); + return HC_ERROR; + } + ret = CreateCallCtx(&callCtx, NULL); + if (ret != HC_SUCCESS) { + LOGE("CreateCallCtx failed, ret %d", ret); + return HC_ERR_IPC_INIT; + } + + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_REQID, (const uint8_t *)&requestId, sizeof(requestId)); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_REQID); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_COMM_DATA, data, dataLen); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_COMM_DATA); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = DoBinderCall(callCtx, IPC_CALL_ID_GM_PROC_DATA, true); + if (ret == HC_ERR_IPC_INTERNAL_FAILED) { + LOGE("ipc call failed"); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_PROC_FAILED; + } + DecodeCallReply(callCtx, &replyCache, REPLAY_CACHE_NUM(replyCache)); + ret = HC_ERR_IPC_UNKNOW_REPLAY; + inOutLen = sizeof(int32_t); + GetIpcReplyByType(&replyCache, REPLAY_CACHE_NUM(replyCache), PARAM_TYPE_IPC_RESULT, (uint8_t *)&ret, &inOutLen); + DestroyCallCtx(&callCtx, NULL); + LOGI("process done, ret %d", ret); + return ret; +} + +static int32_t IpcGmConfirmRequest(int64_t requestId, const char *appId, const char *returnParams) +{ + uintptr_t callCtx = 0x0; + int32_t ret; + int32_t inOutLen; + IpcDataInfo replyCache = {0}; + + LOGI("starting ..."); + if (!IS_STRING_VALID(appId) || !IS_STRING_VALID(returnParams)) { + return HC_ERR_INVALID_PARAMS; + } + if (!IsServiceRunning()) { + LOGE("service is not activity"); + return HC_ERROR; + } + ret = CreateCallCtx(&callCtx, NULL); + if (ret != HC_SUCCESS) { + LOGE("CreateCallCtx failed, ret %d", ret); + return HC_ERR_IPC_INIT; + } + + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_REQID, (const uint8_t *)&requestId, sizeof(requestId)); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_REQID); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_APPID, (const uint8_t *)appId, strlen(appId) + 1); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_APPID); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_REQ_CFM, (const uint8_t *)returnParams, strlen(returnParams) + 1); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_REQ_CFM); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = DoBinderCall(callCtx, IPC_CALL_ID_CFM_REQUEST, true); + if (ret == HC_ERR_IPC_INTERNAL_FAILED) { + LOGE("ipc call failed"); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_PROC_FAILED; + } + DecodeCallReply(callCtx, &replyCache, REPLAY_CACHE_NUM(replyCache)); + ret = HC_ERR_IPC_UNKNOW_REPLAY; + inOutLen = sizeof(int32_t); + GetIpcReplyByType(&replyCache, REPLAY_CACHE_NUM(replyCache), PARAM_TYPE_IPC_RESULT, (uint8_t *)&ret, &inOutLen); + DestroyCallCtx(&callCtx, NULL); + LOGI("process done, ret %d", ret); + return ret; +} + +static int32_t IpcGmBindPeer(int64_t requestId, const char *appId, const char *bindParams) +{ + uintptr_t callCtx = 0x0; + int32_t ret; + int32_t inOutLen; + IpcDataInfo replyCache = {0}; + + LOGI("starting ..."); + if (!IS_STRING_VALID(appId) || !IS_STRING_VALID(bindParams)) { + return HC_ERR_INVALID_PARAMS; + } + if (!IsServiceRunning()) { + LOGE("service is not activity"); + return HC_ERROR; + } + ret = CreateCallCtx(&callCtx, NULL); + if (ret != HC_SUCCESS) { + LOGE("CreateCallCtx failed, ret %d", ret); + return HC_ERR_IPC_INIT; + } + + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_REQID, (const uint8_t *)&requestId, sizeof(requestId)); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_REQID); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_APPID, (const uint8_t *)appId, strlen(appId) + 1); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_APPID); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_BIND, (const uint8_t *)bindParams, strlen(bindParams) + 1); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_BIND); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = DoBinderCall(callCtx, IPC_CALL_ID_BIND_PEER, true); + if (ret == HC_ERR_IPC_INTERNAL_FAILED) { + LOGE("ipc call failed"); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_PROC_FAILED; + } + DecodeCallReply(callCtx, &replyCache, REPLAY_CACHE_NUM(replyCache)); + ret = HC_ERR_IPC_UNKNOW_REPLAY; + inOutLen = sizeof(int32_t); + GetIpcReplyByType(&replyCache, REPLAY_CACHE_NUM(replyCache), PARAM_TYPE_IPC_RESULT, (uint8_t *)&ret, &inOutLen); + DestroyCallCtx(&callCtx, NULL); + LOGI("process done, ret %d", ret); + return ret; +} + +static int32_t IpcGmUnBindPeer(int64_t requestId, const char *appId, const char *unBindParams) +{ + uintptr_t callCtx = 0x0; + int32_t ret; + int32_t inOutLen; + IpcDataInfo replyCache = {0}; + + LOGI("starting ..."); + if (!IS_STRING_VALID(appId) || !IS_STRING_VALID(unBindParams)) { + return HC_ERR_INVALID_PARAMS; + } + if (!IsServiceRunning()) { + LOGE("service is not activity"); + return HC_ERROR; + } + ret = CreateCallCtx(&callCtx, NULL); + if (ret != HC_SUCCESS) { + LOGE("CreateCallCtx failed, ret %d", ret); + return HC_ERR_IPC_INIT; + } + + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_REQID, (const uint8_t *)&requestId, sizeof(requestId)); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_REQID); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_APPID, (const uint8_t *)appId, strlen(appId) + 1); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_APPID); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_UNBIND, (const uint8_t *)unBindParams, strlen(unBindParams) + 1); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_UNBIND); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = DoBinderCall(callCtx, IPC_CALL_ID_UNBIND_PEER, true); + if (ret == HC_ERR_IPC_INTERNAL_FAILED) { + LOGE("ipc call failed"); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_PROC_FAILED; + } + DecodeCallReply(callCtx, &replyCache, REPLAY_CACHE_NUM(replyCache)); + ret = HC_ERR_IPC_UNKNOW_REPLAY; + inOutLen = sizeof(int32_t); + GetIpcReplyByType(&replyCache, REPLAY_CACHE_NUM(replyCache), PARAM_TYPE_IPC_RESULT, (uint8_t *)&ret, &inOutLen); + DestroyCallCtx(&callCtx, NULL); + LOGI("process done, ret %d", ret); + return ret; +} + +static int32_t IpcGmProcessLiteData(int64_t requestId, const char *appId, const uint8_t *data, uint32_t dataLen) +{ + uintptr_t callCtx = 0x0; + int32_t ret; + int32_t inOutLen; + IpcDataInfo replyCache = {0}; + + LOGI("starting ..."); + if ((data == NULL) || (dataLen == 0) || !IS_STRING_VALID(appId)) { + return HC_ERR_INVALID_PARAMS; + } + if (!IsServiceRunning()) { + LOGE("service is not activity"); + return HC_ERROR; + } + ret = CreateCallCtx(&callCtx, NULL); + if (ret != HC_SUCCESS) { + LOGE("CreateCallCtx failed, ret %d", ret); + return HC_ERR_IPC_INIT; + } + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_REQID, (const uint8_t *)(&requestId), sizeof(requestId)); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_APPID); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_APPID, (const uint8_t *)appId, strlen(appId) + 1); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_APPID); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_COMM_DATA, data, dataLen); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_COMM_DATA); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = DoBinderCall(callCtx, IPC_CALL_ID_PROC_LIGHT_DATA, true); + if (ret == HC_ERR_IPC_INTERNAL_FAILED) { + LOGE("ipc call failed"); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_PROC_FAILED; + } + DecodeCallReply(callCtx, &replyCache, REPLAY_CACHE_NUM(replyCache)); + ret = HC_ERR_IPC_UNKNOW_REPLAY; + inOutLen = sizeof(int32_t); + GetIpcReplyByType(&replyCache, REPLAY_CACHE_NUM(replyCache), PARAM_TYPE_IPC_RESULT, (uint8_t *)&ret, &inOutLen); + DestroyCallCtx(&callCtx, NULL); + LOGI("process done, ret %d", ret); + return ret; +} + +static int32_t IpcGmProcCredential(int32_t operationCode, const char *credential, char **returnJsonStr) +{ + LOGI("starting ..."); + (void)operationCode; + if (!IS_STRING_VALID(credential) || (returnJsonStr == NULL)) { + LOGE("The input groupType is invalid or credential is NULL!"); + return HC_ERR_INVALID_PARAMS; + } + + return HC_ERR_NOT_SUPPORT; +} + +static int32_t IpcGmGetRegisterInfo(char **registerInfo) +{ + uintptr_t callCtx = 0x0; + int32_t ret; + int32_t inOutLen; + IpcDataInfo replyCache[IPC_DATA_CACHES_3] = {{0}}; + char *outInfo = NULL; + + LOGI("starting ..."); + if (registerInfo == NULL) { + return HC_ERR_INVALID_PARAMS; + } + if (!IsServiceRunning()) { + LOGE("service is not activity"); + return HC_ERROR; + } + ret = CreateCallCtx(&callCtx, NULL); + if (ret != HC_SUCCESS) { + LOGE("CreateCallCtx failed, ret %d", ret); + return HC_ERR_IPC_INIT; + } + ret = DoBinderCall(callCtx, IPC_CALL_ID_APPLY_REG_INFO, true); + if (ret == HC_ERR_IPC_INTERNAL_FAILED) { + LOGE("ipc call failed"); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_PROC_FAILED; + } + DecodeCallReply(callCtx, replyCache, REPLAY_CACHE_NUM(replyCache)); + ret = HC_ERR_IPC_UNKNOW_REPLAY; + inOutLen = sizeof(int32_t); + GetIpcReplyByType(replyCache, REPLAY_CACHE_NUM(replyCache), PARAM_TYPE_IPC_RESULT, (uint8_t *)&ret, &inOutLen); + LOGI("process done, ret %d", ret); + if ((ret != HC_SUCCESS) || (inOutLen != sizeof(int32_t))) { + DestroyCallCtx(&callCtx, NULL); + return ret; + } + GetIpcReplyByType(replyCache, REPLAY_CACHE_NUM(replyCache), PARAM_TYPE_IPC_RESULT_NUM, (uint8_t *)&ret, &inOutLen); + if ((ret < IPC_RESULT_NUM_1) || (inOutLen != sizeof(int32_t))) { + LOGE("done, ret %d", HC_ERR_IPC_OUT_DATA_NUM); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_OUT_DATA_NUM; + } + GetIpcReplyByType(replyCache, REPLAY_CACHE_NUM(replyCache), PARAM_TYPE_REG_INFO, (uint8_t *)&outInfo, NULL); + if ((outInfo == NULL) || (strlen(outInfo) == 0)) { + LOGE("done, ret %d", HC_ERR_IPC_OUT_DATA); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_OUT_DATA; + } + *registerInfo = strdup(outInfo); + DestroyCallCtx(&callCtx, NULL); + return (*registerInfo != NULL) ? HC_SUCCESS : HC_ERR_NULL_PTR; +} + +static int32_t IpcGmGetLocalConnectInfo(char **outLocalConnInfo) +{ + LOGI("starting ..."); + if (outLocalConnInfo == NULL) { + return HC_ERR_INVALID_PARAMS; + } + + return HC_ERR_NOT_SUPPORT; +} + +static int32_t IpcGmAddGroupManager(const char *appId, const char *groupId, const char *managerAppId) +{ + uintptr_t callCtx = 0x0; + int32_t ret; + int32_t inOutLen; + IpcDataInfo replyCache = {0}; + + LOGI("starting ..."); + if (!IS_STRING_VALID(appId) || !IS_STRING_VALID(groupId) || !IS_STRING_VALID(managerAppId)) { + return HC_ERR_INVALID_PARAMS; + } + if (!IsServiceRunning()) { + LOGE("service is not activity"); + return HC_ERROR; + } + ret = CreateCallCtx(&callCtx, NULL); + if (ret != HC_SUCCESS) { + LOGE("CreateCallCtx failed, ret %d", ret); + return HC_ERR_IPC_INIT; + } + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_APPID, (const uint8_t *)appId, strlen(appId) + 1); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_APPID); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_GROUPID, (const uint8_t *)groupId, strlen(groupId) + 1); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_GROUPID); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_MGR_APPID, + (const uint8_t *)managerAppId, strlen(managerAppId) + 1); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_MGR_APPID); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = DoBinderCall(callCtx, IPC_CALL_ID_ADD_GROUP_MGR, true); + if (ret == HC_ERR_IPC_INTERNAL_FAILED) { + LOGE("ipc call failed"); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_PROC_FAILED; + } + DecodeCallReply(callCtx, &replyCache, REPLAY_CACHE_NUM(replyCache)); + ret = HC_ERR_IPC_UNKNOW_REPLAY; + inOutLen = sizeof(int32_t); + GetIpcReplyByType(&replyCache, REPLAY_CACHE_NUM(replyCache), PARAM_TYPE_IPC_RESULT, (uint8_t *)&ret, &inOutLen); + DestroyCallCtx(&callCtx, NULL); + LOGI("process done, ret %d", ret); + return ret; +} + +static int32_t IpcGmAddGroupFriend(const char *appId, const char *groupId, const char *friendAppId) +{ + uintptr_t callCtx = 0x0; + int32_t ret; + int32_t inOutLen; + IpcDataInfo replyCache = {0}; + + LOGI("starting ..."); + if (!IS_STRING_VALID(groupId) || !IS_STRING_VALID(friendAppId) || !IS_STRING_VALID(appId)) { + return HC_ERR_INVALID_PARAMS; + } + if (!IsServiceRunning()) { + LOGE("service is not activity"); + return HC_ERROR; + } + ret = CreateCallCtx(&callCtx, NULL); + if (ret != HC_SUCCESS) { + LOGE("CreateCallCtx failed, ret %d", ret); + return HC_ERR_IPC_INIT; + } + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_APPID, (const uint8_t *)appId, strlen(appId) + 1); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_APPID); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_GROUPID, (const uint8_t *)groupId, strlen(groupId) + 1); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_GROUPID); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_FRIEND_APPID, + (const uint8_t *)friendAppId, strlen(friendAppId) + 1); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_FRIEND_APPID); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = DoBinderCall(callCtx, IPC_CALL_ID_ADD_GROUP_FRIEND, true); + if (ret == HC_ERR_IPC_INTERNAL_FAILED) { + LOGE("ipc call failed"); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_PROC_FAILED; + } + DecodeCallReply(callCtx, &replyCache, REPLAY_CACHE_NUM(replyCache)); + ret = HC_ERR_IPC_UNKNOW_REPLAY; + inOutLen = sizeof(int32_t); + GetIpcReplyByType(&replyCache, REPLAY_CACHE_NUM(replyCache), PARAM_TYPE_IPC_RESULT, (uint8_t *)&ret, &inOutLen); + DestroyCallCtx(&callCtx, NULL); + LOGI("process done, ret %d", ret); + return ret; +} + +static int32_t IpcGmDelGroupManager(const char *appId, const char *groupId, const char *managerAppId) +{ + uintptr_t callCtx = 0x0; + int32_t ret; + int32_t inOutLen; + IpcDataInfo replyCache = {0}; + + LOGI("starting ..."); + if (!IS_STRING_VALID(groupId) || !IS_STRING_VALID(managerAppId) || !IS_STRING_VALID(appId)) { + return HC_ERR_INVALID_PARAMS; + } + if (!IsServiceRunning()) { + LOGE("service is not activity"); + return HC_ERROR; + } + ret = CreateCallCtx(&callCtx, NULL); + if (ret != HC_SUCCESS) { + LOGE("CreateCallCtx failed, ret %d", ret); + return HC_ERR_IPC_INIT; + } + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_APPID, (const uint8_t *)appId, strlen(appId) + 1); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_APPID); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_GROUPID, (const uint8_t *)groupId, strlen(groupId) + 1); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_GROUPID); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_MGR_APPID, + (const uint8_t *)managerAppId, strlen(managerAppId) + 1); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_MGR_APPID); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = DoBinderCall(callCtx, IPC_CALL_ID_DEL_GROUP_MGR, true); + if (ret == HC_ERR_IPC_INTERNAL_FAILED) { + LOGE("ipc call failed"); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_PROC_FAILED; + } + DecodeCallReply(callCtx, &replyCache, REPLAY_CACHE_NUM(replyCache)); + ret = HC_ERR_IPC_UNKNOW_REPLAY; + inOutLen = sizeof(int32_t); + GetIpcReplyByType(&replyCache, REPLAY_CACHE_NUM(replyCache), PARAM_TYPE_IPC_RESULT, (uint8_t *)&ret, &inOutLen); + DestroyCallCtx(&callCtx, NULL); + LOGI("process done, ret %d", ret); + return ret; +} + +static int32_t IpcGmDelGroupFriend(const char *appId, const char *groupId, const char *friendAppId) +{ + uintptr_t callCtx = 0x0; + int32_t ret; + int32_t inOutLen; + IpcDataInfo replyCache = {0}; + + LOGI("starting ..."); + if (!IS_STRING_VALID(groupId) || !IS_STRING_VALID(friendAppId) || !IS_STRING_VALID(appId)) { + return HC_ERR_INVALID_PARAMS; + } + if (!IsServiceRunning()) { + LOGE("service is not activity"); + return HC_ERROR; + } + ret = CreateCallCtx(&callCtx, NULL); + if (ret != HC_SUCCESS) { + LOGE("CreateCallCtx failed, ret %d", ret); + return HC_ERR_IPC_INIT; + } + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_APPID, (const uint8_t *)appId, strlen(appId) + 1); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_APPID); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_GROUPID, (const uint8_t *)groupId, strlen(groupId) + 1); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_GROUPID); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_FRIEND_APPID, + (const uint8_t *)friendAppId, strlen(friendAppId) + 1); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_FRIEND_APPID); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = DoBinderCall(callCtx, IPC_CALL_ID_DEL_GROUP_FRIEND, true); + if (ret == HC_ERR_IPC_INTERNAL_FAILED) { + LOGE("ipc call failed"); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_PROC_FAILED; + } + DecodeCallReply(callCtx, &replyCache, REPLAY_CACHE_NUM(replyCache)); + ret = HC_ERR_IPC_UNKNOW_REPLAY; + inOutLen = sizeof(int32_t); + GetIpcReplyByType(&replyCache, REPLAY_CACHE_NUM(replyCache), PARAM_TYPE_IPC_RESULT, (uint8_t *)&ret, &inOutLen); + DestroyCallCtx(&callCtx, NULL); + LOGI("process done, ret %d", ret); + return ret; +} + +static int32_t GetGroupManagersIpcResult(const IpcDataInfo *replies, int32_t cacheNum, + char **outManagers, uint32_t *outSize) +{ + int32_t inOutLen; + int32_t ret; + + inOutLen = sizeof(int32_t); + GetIpcReplyByType(replies, cacheNum, PARAM_TYPE_IPC_RESULT_NUM, (uint8_t *)&ret, &inOutLen); + if ((ret < IPC_RESULT_NUM_2) || (inOutLen != sizeof(int32_t))) { + return HC_ERR_IPC_OUT_DATA_NUM; + } + GetIpcReplyByType(replies, cacheNum, PARAM_TYPE_MGR_APPID, (uint8_t *)outManagers, NULL); + if ((*outManagers == NULL) || (strlen(*outManagers) == 0)) { + return HC_ERR_IPC_OUT_DATA; + } + *outManagers = strdup(*outManagers); + if (*outManagers == NULL) { + return HC_ERR_ALLOC_MEMORY; + } + inOutLen = sizeof(int32_t); + GetIpcReplyByType(replies, cacheNum, PARAM_TYPE_DATA_NUM, (uint8_t *)outSize, &inOutLen); + return HC_SUCCESS; +} + +static int32_t IpcGmGetGroupManagers(const char *appId, const char *groupId, char **outManagers, uint32_t *outSize) +{ + uintptr_t callCtx = 0x0; + int32_t ret; + int32_t inOutLen; + IpcDataInfo replyCache[IPC_DATA_CACHES_4] = {{0}}; + + LOGI("starting ..."); + if (!IS_STRING_VALID(groupId) || !IS_STRING_VALID(appId) || (outManagers == NULL) || (outSize == NULL)) { + return HC_ERR_INVALID_PARAMS; + } + if (!IsServiceRunning()) { + LOGE("service is not activity"); + return HC_ERROR; + } + ret = CreateCallCtx(&callCtx, NULL); + if (ret != HC_SUCCESS) { + LOGE("CreateCallCtx failed, ret %d", ret); + return HC_ERR_IPC_INIT; + } + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_APPID, (const uint8_t *)appId, strlen(appId) + 1); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_APPID); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_GROUPID, (const uint8_t *)groupId, strlen(groupId) + 1); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_GROUPID); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = DoBinderCall(callCtx, IPC_CALL_ID_GET_GROUP_MGR, true); + if (ret == HC_ERR_IPC_INTERNAL_FAILED) { + LOGE("ipc call failed"); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_PROC_FAILED; + } + DecodeCallReply(callCtx, replyCache, REPLAY_CACHE_NUM(replyCache)); + ret = HC_ERR_IPC_UNKNOW_REPLAY; + inOutLen = sizeof(int32_t); + GetIpcReplyByType(replyCache, REPLAY_CACHE_NUM(replyCache), PARAM_TYPE_IPC_RESULT, (uint8_t *)&ret, &inOutLen); + LOGI("process done, ret %d", ret); + if (ret != HC_SUCCESS) { + DestroyCallCtx(&callCtx, NULL); + return ret; + } + ret = GetGroupManagersIpcResult(replyCache, REPLAY_CACHE_NUM(replyCache), outManagers, outSize); + LOGI("proc result done, ret %d", ret); + DestroyCallCtx(&callCtx, NULL); + return ret; +} + +static int32_t GetGroupFriendsIpcResult(const IpcDataInfo *replies, + int32_t cacheNum, char **outFriends, uint32_t *outSize) +{ + int32_t inOutLen; + int32_t ret; + + inOutLen = sizeof(int32_t); + GetIpcReplyByType(replies, cacheNum, PARAM_TYPE_IPC_RESULT_NUM, (uint8_t *)&ret, &inOutLen); + if ((ret < IPC_RESULT_NUM_2) || (inOutLen != sizeof(int32_t))) { + return HC_ERR_IPC_OUT_DATA_NUM; + } + GetIpcReplyByType(replies, cacheNum, PARAM_TYPE_FRIEND_APPID, (uint8_t *)outFriends, NULL); + if ((*outFriends == NULL) || (strlen(*outFriends) == 0)) { + return HC_ERR_IPC_OUT_DATA; + } + *outFriends = strdup(*outFriends); + if (*outFriends == NULL) { + return HC_ERR_ALLOC_MEMORY; + } + inOutLen = sizeof(int32_t); + GetIpcReplyByType(replies, cacheNum, PARAM_TYPE_DATA_NUM, (uint8_t *)outSize, &inOutLen); + return HC_SUCCESS; +} + +static int32_t IpcGmGetGroupFriends(const char *appId, const char *groupId, char **outFriends, uint32_t *outSize) +{ + uintptr_t callCtx = 0x0; + int32_t ret; + int32_t inOutLen; + IpcDataInfo replyCache[IPC_DATA_CACHES_4] = {{0}}; + + LOGI("starting ..."); + if (!IS_STRING_VALID(groupId) || !IS_STRING_VALID(appId) || (outFriends == NULL) || (outSize == NULL)) { + return HC_ERR_INVALID_PARAMS; + } + if (!IsServiceRunning()) { + LOGE("service is not activity"); + return HC_ERROR; + } + ret = CreateCallCtx(&callCtx, NULL); + if (ret != HC_SUCCESS) { + LOGE("CreateCallCtx failed, ret %d", ret); + return HC_ERR_IPC_INIT; + } + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_APPID, (const uint8_t *)appId, strlen(appId) + 1); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_APPID); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_GROUPID, (const uint8_t *)groupId, strlen(groupId) + 1); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_GROUPID); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = DoBinderCall(callCtx, IPC_CALL_ID_GET_GROUP_FRIEND, true); + if (ret == HC_ERR_IPC_INTERNAL_FAILED) { + LOGE("ipc call failed"); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_PROC_FAILED; + } + DecodeCallReply(callCtx, replyCache, REPLAY_CACHE_NUM(replyCache)); + ret = HC_ERR_IPC_UNKNOW_REPLAY; + inOutLen = sizeof(int32_t); + GetIpcReplyByType(replyCache, REPLAY_CACHE_NUM(replyCache), PARAM_TYPE_IPC_RESULT, (uint8_t *)&ret, &inOutLen); + LOGI("process done, ret %d", ret); + if (ret != HC_SUCCESS) { + DestroyCallCtx(&callCtx, NULL); + return ret; + } + ret = GetGroupFriendsIpcResult(replyCache, REPLAY_CACHE_NUM(replyCache), outFriends, outSize); + LOGI("proc result done, ret %d", ret); + DestroyCallCtx(&callCtx, NULL); + return ret; +} + +static int32_t GroupInfoIpcResult(const IpcDataInfo *replies, int32_t cacheNum, char **outGroupInfo) +{ + int32_t inOutLen; + int32_t ret; + + inOutLen = sizeof(int32_t); + GetIpcReplyByType(replies, cacheNum, PARAM_TYPE_IPC_RESULT_NUM, (uint8_t *)&ret, &inOutLen); + if ((ret < IPC_RESULT_NUM_1) || (inOutLen != sizeof(int32_t))) { + return HC_ERR_IPC_OUT_DATA_NUM; + } + GetIpcReplyByType(replies, cacheNum, PARAM_TYPE_GROUP_INFO, (uint8_t *)outGroupInfo, NULL); + if (*outGroupInfo == NULL) { + return HC_ERR_IPC_OUT_DATA; + } + *outGroupInfo = strdup(*outGroupInfo); + if (*outGroupInfo == NULL) { + return HC_ERR_ALLOC_MEMORY; + } + return HC_SUCCESS; +} + +static int32_t IpcGmGetGroupInfoById(const char *appId, const char *groupId, char **outGroupInfo) +{ + uintptr_t callCtx = 0x0; + int32_t ret; + int32_t inOutLen; + IpcDataInfo replyCache[IPC_DATA_CACHES_3] = {{0}}; + + LOGI("starting ..."); + if (!IS_STRING_VALID(groupId) || !IS_STRING_VALID(appId) || (outGroupInfo == NULL)) { + return HC_ERR_INVALID_PARAMS; + } + if (!IsServiceRunning()) { + LOGE("service is not activity"); + return HC_ERROR; + } + ret = CreateCallCtx(&callCtx, NULL); + if (ret != HC_SUCCESS) { + LOGE("CreateCallCtx failed, ret %d", ret); + return HC_ERR_IPC_INIT; + } + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_APPID, (const uint8_t *)appId, strlen(appId) + 1); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_APPID); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_GROUPID, (const uint8_t *)groupId, strlen(groupId) + 1); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_GROUPID); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = DoBinderCall(callCtx, IPC_CALL_ID_GET_GROUP_INFO, true); + if (ret == HC_ERR_IPC_INTERNAL_FAILED) { + LOGE("ipc call failed"); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_PROC_FAILED; + } + DecodeCallReply(callCtx, replyCache, REPLAY_CACHE_NUM(replyCache)); + ret = HC_ERR_IPC_UNKNOW_REPLAY; + inOutLen = sizeof(int32_t); + GetIpcReplyByType(replyCache, REPLAY_CACHE_NUM(replyCache), PARAM_TYPE_IPC_RESULT, (uint8_t *)&ret, &inOutLen); + LOGI("process done, ret %d", ret); + if (ret != HC_SUCCESS) { + DestroyCallCtx(&callCtx, NULL); + return ret; + } + ret = GroupInfoIpcResult(replyCache, REPLAY_CACHE_NUM(replyCache), outGroupInfo); + DestroyCallCtx(&callCtx, NULL); + LOGI("proc result done, ret %d", ret); + return ret; +} + +static int32_t SearchGroupsIpcResult(const IpcDataInfo *replies, + int32_t cacheNum, char **outGroupVec, uint32_t *groupNum) +{ + int32_t ret; + int32_t inOutLen; + + inOutLen = sizeof(int32_t); + GetIpcReplyByType(replies, cacheNum, PARAM_TYPE_IPC_RESULT_NUM, (uint8_t *)&ret, &inOutLen); + if ((ret < IPC_RESULT_NUM_2) || (inOutLen != sizeof(int32_t))) { + return HC_ERR_IPC_OUT_DATA_NUM; + } + GetIpcReplyByType(replies, cacheNum, PARAM_TYPE_GROUP_INFO, (uint8_t *)outGroupVec, NULL); + if (*outGroupVec == NULL) { + return HC_ERR_IPC_OUT_DATA; + } + *outGroupVec = strdup(*outGroupVec); + if (*outGroupVec == NULL) { + return HC_ERR_ALLOC_MEMORY; + } + inOutLen = sizeof(int32_t); + GetIpcReplyByType(replies, cacheNum, PARAM_TYPE_DATA_NUM, (uint8_t *)groupNum, &inOutLen); + return HC_SUCCESS; +} + +static int32_t IpcGmGetGroupInfo(const char *appId, const char *queryParams, char **outGroupVec, uint32_t *groupNum) +{ + uintptr_t callCtx = 0x0; + int32_t ret; + int32_t inOutLen; + IpcDataInfo replyCache[IPC_DATA_CACHES_4] = {{0}}; + + LOGI("starting ..."); + if (!IS_STRING_VALID(queryParams) || !IS_STRING_VALID(appId) || (outGroupVec == NULL) || (groupNum == NULL)) { + return HC_ERR_INVALID_PARAMS; + } + if (!IsServiceRunning()) { + LOGE("service is not activity"); + return HC_ERROR; + } + ret = CreateCallCtx(&callCtx, NULL); + if (ret != HC_SUCCESS) { + LOGE("CreateCallCtx failed, ret %d", ret); + return HC_ERR_IPC_INIT; + } + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_APPID, (const uint8_t *)appId, strlen(appId) + 1); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_APPID); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_QUERY_PARAMS, + (const uint8_t *)queryParams, strlen(queryParams) + 1); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_QUERY_PARAMS); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = DoBinderCall(callCtx, IPC_CALL_ID_SEARCH_GROUPS, true); + if (ret == HC_ERR_IPC_INTERNAL_FAILED) { + LOGE("ipc call failed"); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_PROC_FAILED; + } + DecodeCallReply(callCtx, replyCache, REPLAY_CACHE_NUM(replyCache)); + ret = HC_ERR_IPC_UNKNOW_REPLAY; + inOutLen = sizeof(int32_t); + GetIpcReplyByType(replyCache, REPLAY_CACHE_NUM(replyCache), PARAM_TYPE_IPC_RESULT, (uint8_t *)&ret, &inOutLen); + LOGI("process done, ret %d", ret); + if (ret != HC_SUCCESS) { + DestroyCallCtx(&callCtx, NULL); + return ret; + } + ret = SearchGroupsIpcResult(replyCache, REPLAY_CACHE_NUM(replyCache), outGroupVec, groupNum); + LOGI("proc result done, ret %d", ret); + DestroyCallCtx(&callCtx, NULL); + return ret; +} + +static int32_t JoinedGroupsIpcResult(const IpcDataInfo *replies, + int32_t cacheNum, char **outGroupVec, uint32_t *groupNum) +{ + int32_t ret; + int32_t inOutLen; + + inOutLen = sizeof(int32_t); + GetIpcReplyByType(replies, cacheNum, PARAM_TYPE_IPC_RESULT_NUM, (uint8_t *)&ret, &inOutLen); + if ((ret < IPC_RESULT_NUM_2) || (inOutLen != sizeof(int32_t))) { + return HC_ERR_IPC_OUT_DATA_NUM; + } + GetIpcReplyByType(replies, cacheNum, PARAM_TYPE_GROUP_INFO, (uint8_t *)outGroupVec, NULL); + if (*outGroupVec == NULL) { + return HC_ERR_IPC_OUT_DATA; + } + *outGroupVec = strdup(*outGroupVec); + if (*outGroupVec == NULL) { + return HC_ERR_ALLOC_MEMORY; + } + inOutLen = sizeof(int32_t); + GetIpcReplyByType(replies, cacheNum, PARAM_TYPE_DATA_NUM, (uint8_t *)groupNum, &inOutLen); + return HC_SUCCESS; +} + +static int32_t IpcGmGetJoinedGroups(const char *appId, int32_t groupType, char **outGroupVec, uint32_t *groupNum) +{ + uintptr_t callCtx = 0x0; + int32_t ret; + int32_t inOutLen; + IpcDataInfo replyCache[IPC_DATA_CACHES_4] = {{0}}; + + LOGI("starting ..."); + if (!IS_STRING_VALID(appId) || (outGroupVec == NULL) || + (groupNum == NULL) || (groupType != ACROSS_ACCOUNT_AUTHORIZE_GROUP)) { + return HC_ERR_INVALID_PARAMS; + } + if (!IsServiceRunning()) { + LOGE("service is not activity"); + return HC_ERROR; + } + ret = CreateCallCtx(&callCtx, NULL); + if (ret != HC_SUCCESS) { + LOGE("CreateCallCtx failed, ret %d", ret); + return HC_ERR_IPC_INIT; + } + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_APPID, (const uint8_t *)appId, strlen(appId) + 1); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_APPID); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_GROUP_TYPE, (const uint8_t *)&groupType, sizeof(groupType)); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_GROUP_TYPE); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = DoBinderCall(callCtx, IPC_CALL_ID_GET_JOINED_GROUPS, true); + if (ret == HC_ERR_IPC_INTERNAL_FAILED) { + LOGE("ipc call failed"); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_PROC_FAILED; + } + DecodeCallReply(callCtx, replyCache, REPLAY_CACHE_NUM(replyCache)); + ret = HC_ERR_IPC_UNKNOW_REPLAY; + inOutLen = sizeof(int32_t); + GetIpcReplyByType(replyCache, REPLAY_CACHE_NUM(replyCache), PARAM_TYPE_IPC_RESULT, (uint8_t *)&ret, &inOutLen); + LOGI("process done, ret %d", ret); + if (ret != HC_SUCCESS) { + DestroyCallCtx(&callCtx, NULL); + return ret; + } + ret = JoinedGroupsIpcResult(replyCache, REPLAY_CACHE_NUM(replyCache), outGroupVec, groupNum); + LOGI("proc result done, ret %d", ret); + DestroyCallCtx(&callCtx, NULL); + return ret; +} + +static int32_t RelatedGroupsIpcResult(const IpcDataInfo *replies, + int32_t cacheNum, char **outGroupVec, uint32_t *groupNum) +{ + int32_t ret; + int32_t inOutLen; + + inOutLen = sizeof(int32_t); + GetIpcReplyByType(replies, cacheNum, PARAM_TYPE_IPC_RESULT_NUM, (uint8_t *)&ret, &inOutLen); + if ((ret < IPC_RESULT_NUM_2) || (inOutLen != sizeof(int32_t))) { + return HC_ERR_IPC_OUT_DATA_NUM; + } + GetIpcReplyByType(replies, cacheNum, PARAM_TYPE_GROUP_INFO, (uint8_t *)outGroupVec, NULL); + if (*outGroupVec == NULL) { + return HC_ERR_IPC_OUT_DATA; + } + *outGroupVec = strdup(*outGroupVec); + if (*outGroupVec == NULL) { + return HC_ERR_ALLOC_MEMORY; + } + inOutLen = sizeof(int32_t); + GetIpcReplyByType(replies, cacheNum, PARAM_TYPE_DATA_NUM, (uint8_t *)groupNum, &inOutLen); + return HC_SUCCESS; +} + +static int32_t IpcGmGetRelatedGroups(const char *appId, const char *peerUdid, char **outGroupVec, uint32_t *groupNum) +{ + uintptr_t callCtx = 0x0; + int32_t ret; + int32_t inOutLen; + IpcDataInfo replyCache[IPC_DATA_CACHES_4] = {{0}}; + + LOGI("starting ..."); + if (!IS_STRING_VALID(appId) || !IS_STRING_VALID(peerUdid) || (outGroupVec == NULL) || (groupNum == NULL)) { + return HC_ERR_INVALID_PARAMS; + } + if (!IsServiceRunning()) { + LOGE("service is not activity"); + return HC_ERROR; + } + ret = CreateCallCtx(&callCtx, NULL); + if (ret != HC_SUCCESS) { + LOGE("CreateCallCtx failed, ret %d", ret); + return HC_ERR_IPC_INIT; + } + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_APPID, (const uint8_t *)appId, strlen(appId) + 1); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_APPID); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_UDID, (const uint8_t *)peerUdid, strlen(peerUdid) + 1); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_UDID); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = DoBinderCall(callCtx, IPC_CALL_ID_GET_RELATED_GROUPS, true); + if (ret == HC_ERR_IPC_INTERNAL_FAILED) { + LOGE("ipc call failed"); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_PROC_FAILED; + } + DecodeCallReply(callCtx, replyCache, REPLAY_CACHE_NUM(replyCache)); + ret = HC_ERR_IPC_UNKNOW_REPLAY; + inOutLen = sizeof(int32_t); + GetIpcReplyByType(replyCache, REPLAY_CACHE_NUM(replyCache), PARAM_TYPE_IPC_RESULT, (uint8_t *)&ret, &inOutLen); + LOGI("process done, ret %d", ret); + if (ret != HC_SUCCESS) { + DestroyCallCtx(&callCtx, NULL); + return ret; + } + ret = RelatedGroupsIpcResult(replyCache, REPLAY_CACHE_NUM(replyCache), outGroupVec, groupNum); + LOGI("proc result done, ret %d", ret); + DestroyCallCtx(&callCtx, NULL); + return ret; +} + +static int32_t DevInfoByIdIpcResult(const IpcDataInfo *replies, int32_t cacheNum, char **outDevInfo) +{ + int32_t ret; + int32_t inOutLen; + + inOutLen = sizeof(int32_t); + GetIpcReplyByType(replies, cacheNum, PARAM_TYPE_IPC_RESULT_NUM, (uint8_t *)&ret, &inOutLen); + if ((ret < IPC_RESULT_NUM_1) || (inOutLen != sizeof(int32_t))) { + return HC_ERR_IPC_OUT_DATA_NUM; + } + GetIpcReplyByType(replies, cacheNum, PARAM_TYPE_DEVICE_INFO, (uint8_t *)outDevInfo, NULL); + if (*outDevInfo == NULL) { + return HC_ERR_IPC_OUT_DATA; + } + *outDevInfo = strdup(*outDevInfo); + if (*outDevInfo == NULL) { + return HC_ERR_ALLOC_MEMORY; + } + return HC_SUCCESS; +} + +static int32_t FormParamsForGettingDeviceInfo(const char *appId, + const char *peerUdid, const char *groupId, uintptr_t callCtx) +{ + int32_t ret; + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_APPID, (const uint8_t *)appId, strlen(appId) + 1); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_APPID); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_UDID, (const uint8_t *)peerUdid, strlen(peerUdid) + 1); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_UDID); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_GROUPID, (const uint8_t *)groupId, strlen(groupId) + 1); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_GROUPID); + return HC_ERR_IPC_BUILD_PARAM; + } + return HC_SUCCESS; +} + +static int32_t IpcGmGetDeviceInfoById(const char *appId, const char *peerUdid, const char *groupId, char **outDevInfo) +{ + uintptr_t callCtx = 0x0; + int32_t ret; + int32_t inOutLen; + IpcDataInfo replyCache[IPC_DATA_CACHES_3] = {{0}}; + + LOGI("starting ..."); + if (!IS_STRING_VALID(appId) || !IS_STRING_VALID(peerUdid) || !IS_STRING_VALID(groupId) || (outDevInfo == NULL)) { + return HC_ERR_INVALID_PARAMS; + } + if (!IsServiceRunning()) { + LOGE("service is not activity"); + return HC_ERROR; + } + ret = CreateCallCtx(&callCtx, NULL); + if (ret != HC_SUCCESS) { + LOGE("CreateCallCtx failed, ret %d", ret); + return HC_ERR_IPC_INIT; + } + ret = FormParamsForGettingDeviceInfo(appId, peerUdid, groupId, callCtx); + if (ret != HC_SUCCESS) { + DestroyCallCtx(&callCtx, NULL); + return ret; + } + ret = DoBinderCall(callCtx, IPC_CALL_ID_GET_DEV_INFO_BY_ID, true); + if (ret == HC_ERR_IPC_INTERNAL_FAILED) { + LOGE("ipc call failed"); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_PROC_FAILED; + } + DecodeCallReply(callCtx, replyCache, REPLAY_CACHE_NUM(replyCache)); + ret = HC_ERR_IPC_UNKNOW_REPLAY; + inOutLen = sizeof(int32_t); + GetIpcReplyByType(replyCache, REPLAY_CACHE_NUM(replyCache), PARAM_TYPE_IPC_RESULT, (uint8_t *)&ret, &inOutLen); + LOGI("process done, ret %d", ret); + if (ret != HC_SUCCESS) { + DestroyCallCtx(&callCtx, NULL); + return ret; + } + ret = DevInfoByIdIpcResult(replyCache, REPLAY_CACHE_NUM(replyCache), outDevInfo); + LOGI("proc result done, ret %d", ret); + DestroyCallCtx(&callCtx, NULL); + return ret; +} + +static int32_t TrustedDevIpcResult(const IpcDataInfo *replies, int32_t cacheNum, char **outDevInfoVec, uint32_t *devNum) +{ + int32_t ret; + int32_t inOutLen; + + inOutLen = sizeof(int32_t); + GetIpcReplyByType(replies, cacheNum, PARAM_TYPE_IPC_RESULT_NUM, (uint8_t *)&ret, &inOutLen); + if ((ret < IPC_RESULT_NUM_2) || (inOutLen != sizeof(int32_t))) { + return HC_ERR_IPC_OUT_DATA_NUM; + } + GetIpcReplyByType(replies, cacheNum, PARAM_TYPE_DEVICE_INFO, (uint8_t *)outDevInfoVec, NULL); + if (*outDevInfoVec == NULL) { + return HC_ERR_IPC_OUT_DATA; + } + *outDevInfoVec = strdup(*outDevInfoVec); + if (*outDevInfoVec == NULL) { + return HC_ERR_ALLOC_MEMORY; + } + inOutLen = sizeof(int32_t); + GetIpcReplyByType(replies, cacheNum, PARAM_TYPE_DATA_NUM, (uint8_t *)devNum, &inOutLen); + return HC_SUCCESS; +} + +static int32_t IpcGmGetTrustedDevices(const char *appId, + const char *groupId, char **outDevInfoVec, uint32_t *deviceNum) +{ + uintptr_t callCtx = 0x0; + int32_t ret; + int32_t inOutLen; + IpcDataInfo replyCache[IPC_DATA_CACHES_4] = {{0}}; + + LOGI("starting ..."); + if (!IS_STRING_VALID(appId) || !IS_STRING_VALID(groupId) || + (outDevInfoVec == NULL) || (deviceNum == NULL)) { + return HC_ERR_INVALID_PARAMS; + } + if (!IsServiceRunning()) { + LOGE("service is not activity"); + return HC_ERROR; + } + ret = CreateCallCtx(&callCtx, NULL); + if (ret != HC_SUCCESS) { + LOGE("CreateCallCtx failed, ret %d", ret); + return HC_ERR_IPC_INIT; + } + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_APPID, (const uint8_t *)appId, strlen(appId) + 1); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_APPID); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_GROUPID, (const uint8_t *)groupId, strlen(groupId) + 1); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_GROUPID); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = DoBinderCall(callCtx, IPC_CALL_ID_GET_TRUST_DEVICES, true); + if (ret == HC_ERR_IPC_INTERNAL_FAILED) { + LOGE("ipc call failed"); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_PROC_FAILED; + } + DecodeCallReply(callCtx, replyCache, REPLAY_CACHE_NUM(replyCache)); + ret = HC_ERR_IPC_UNKNOW_REPLAY; + inOutLen = sizeof(int32_t); + GetIpcReplyByType(replyCache, REPLAY_CACHE_NUM(replyCache), PARAM_TYPE_IPC_RESULT, (uint8_t *)&ret, &inOutLen); + LOGI("process done, ret %d", ret); + if (ret != HC_SUCCESS) { + DestroyCallCtx(&callCtx, NULL); + return ret; + } + ret = TrustedDevIpcResult(replyCache, REPLAY_CACHE_NUM(replyCache), outDevInfoVec, deviceNum); + LOGI("proc result done, ret %d", ret); + DestroyCallCtx(&callCtx, NULL); + return ret; +} + +static bool IpcGmIsDeviceInGroup(const char *appId, const char *groupId, const char *udid) +{ + uintptr_t callCtx = 0x0; + int32_t ret; + int32_t inOutLen; + IpcDataInfo replyCache = {0}; + + LOGI("starting ..."); + if (!IS_STRING_VALID(appId) || !IS_STRING_VALID(groupId) || !IS_STRING_VALID(udid)) { + return HC_ERR_INVALID_PARAMS; + } + if (!IsServiceRunning()) { + LOGE("service is not activity"); + return HC_ERROR; + } + ret = CreateCallCtx(&callCtx, NULL); + if (ret != HC_SUCCESS) { + LOGE("CreateCallCtx failed, ret %d", ret); + return HC_ERR_IPC_INIT; + } + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_APPID, (const uint8_t *)appId, strlen(appId) + 1); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_APPID); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_GROUPID, (const uint8_t *)groupId, strlen(groupId) + 1); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_GROUPID); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_UDID, (const uint8_t *)udid, strlen(udid) + 1); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_UDID); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = DoBinderCall(callCtx, IPC_CALL_ID_IS_DEV_IN_GROUP, true); + if (ret == HC_ERR_IPC_INTERNAL_FAILED) { + LOGE("ipc call failed"); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_PROC_FAILED; + } + DecodeCallReply(callCtx, &replyCache, REPLAY_CACHE_NUM(replyCache)); + ret = HC_ERR_IPC_UNKNOW_REPLAY; + inOutLen = sizeof(int32_t); + GetIpcReplyByType(&replyCache, REPLAY_CACHE_NUM(replyCache), PARAM_TYPE_IPC_RESULT, (uint8_t *)&ret, &inOutLen); + LOGI("process done, ret %d", ret); + DestroyCallCtx(&callCtx, NULL); + return (ret == HC_SUCCESS) ? true : false; +} + +void IpcGmDestroyInfo(char **returnInfo) +{ + if ((returnInfo == NULL) || (*returnInfo == NULL)) { + return; + } + FreeJsonString(*returnInfo); + *returnInfo = NULL; +} + +static void InitIpcGmMethods(DeviceGroupManager *gmMethodObj) +{ + LOGI("starting ..."); + gmMethodObj->regCallback = IpcGmRegCallback; + gmMethodObj->unRegCallback = IpcGmUnRegCallback; + gmMethodObj->regDataChangeListener = IpcGmRegDataChangeListener; + gmMethodObj->unRegDataChangeListener = IpcGmUnRegDataChangeListener; + gmMethodObj->createGroup = IpcGmCreateGroup; + gmMethodObj->deleteGroup = IpcGmDelGroup; + gmMethodObj->addMemberToGroup = IpcGmAddMemberToGroup; + gmMethodObj->deleteMemberFromGroup = IpcGmDelMemberFromGroup; + gmMethodObj->processData = IpcGmProcessData; + gmMethodObj->confirmRequest = IpcGmConfirmRequest; + gmMethodObj->bindPeer = IpcGmBindPeer; + gmMethodObj->unbindPeer = IpcGmUnBindPeer; + gmMethodObj->processLiteData = IpcGmProcessLiteData; + gmMethodObj->processCredential = IpcGmProcCredential; + gmMethodObj->getRegisterInfo = IpcGmGetRegisterInfo; + gmMethodObj->getLocalConnectInfo = IpcGmGetLocalConnectInfo; + gmMethodObj->addGroupManager = IpcGmAddGroupManager; + gmMethodObj->addGroupFriend = IpcGmAddGroupFriend; + gmMethodObj->deleteGroupManager = IpcGmDelGroupManager; + gmMethodObj->deleteGroupFriend = IpcGmDelGroupFriend; + gmMethodObj->getGroupManagers = IpcGmGetGroupManagers; + gmMethodObj->getGroupFriends = IpcGmGetGroupFriends; + gmMethodObj->getGroupInfoById = IpcGmGetGroupInfoById; + gmMethodObj->getGroupInfo = IpcGmGetGroupInfo; + gmMethodObj->getJoinedGroups = IpcGmGetJoinedGroups; + gmMethodObj->getRelatedGroups = IpcGmGetRelatedGroups; + gmMethodObj->getDeviceInfoById = IpcGmGetDeviceInfoById; + gmMethodObj->getTrustedDevices = IpcGmGetTrustedDevices; + gmMethodObj->isDeviceInGroup = IpcGmIsDeviceInGroup; + gmMethodObj->destroyInfo = IpcGmDestroyInfo; + LOGI("process done"); + return; +} + +static int32_t IpcGaProcessData(int64_t authReqId, + const uint8_t *data, uint32_t dataLen, const DeviceAuthCallback *callback) +{ + uintptr_t callCtx = 0x0; + int32_t ret; + int32_t inOutLen; + IpcDataInfo replyCache = {0}; + + LOGI("starting ..."); + if ((data == NULL) || (dataLen == 0) || (callback == NULL)) { + LOGE("invalid params"); + return HC_ERR_INVALID_PARAMS; + } + if (!IsServiceRunning()) { + LOGE("service is not activity"); + return HC_ERROR; + } + ret = CreateCallCtx(&callCtx, NULL); + if (ret != HC_SUCCESS) { + LOGE("CreateCallCtx failed, ret %d", ret); + return HC_ERR_IPC_INIT; + } + + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_REQID, (const uint8_t *)(&authReqId), sizeof(authReqId)); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, type %d", ret, PARAM_TYPE_REQID); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_COMM_DATA, (const uint8_t *)data, dataLen); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, type %d", ret, PARAM_TYPE_COMM_DATA); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_DEV_AUTH_CB, (const uint8_t *)callback, sizeof(*callback)); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, type %d", ret, PARAM_TYPE_DEV_AUTH_CB); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + SetCbCtxToDataCtx(callCtx, 0x0); + ret = DoBinderCall(callCtx, IPC_CALL_ID_GA_PROC_DATA, true); + if (ret == HC_ERR_IPC_INTERNAL_FAILED) { + LOGE("ipc call failed"); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_PROC_FAILED; + } + DecodeCallReply(callCtx, &replyCache, REPLAY_CACHE_NUM(replyCache)); + ret = HC_ERR_IPC_UNKNOW_REPLAY; + inOutLen = sizeof(int32_t); + GetIpcReplyByType(&replyCache, REPLAY_CACHE_NUM(replyCache), PARAM_TYPE_IPC_RESULT, (uint8_t *)&ret, &inOutLen); + LOGI("process done, ret %d", ret); + DestroyCallCtx(&callCtx, NULL); + return ret; +} + +static int32_t IpcGaQueryTrustedDeviceNum(void) +{ + uintptr_t callCtx = 0x0; + int32_t ret; + int32_t inOutLen; + IpcDataInfo replyCache = {0}; + + LOGI("starting ..."); + if (!IsServiceRunning()) { + LOGE("service is not activity"); + return HC_ERROR; + } + ret = CreateCallCtx(&callCtx, NULL); + if (ret != HC_SUCCESS) { + LOGE("CreateCallCtx failed, ret %d", ret); + return HC_ERR_IPC_INIT; + } + ret = DoBinderCall(callCtx, IPC_CALL_ID_QUERY_TRUST_DEV_NUM, true); + if (ret == HC_ERR_IPC_INTERNAL_FAILED) { + LOGE("ipc call failed"); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_PROC_FAILED; + } + DecodeCallReply(callCtx, &replyCache, REPLAY_CACHE_NUM(replyCache)); + ret = HC_ERR_IPC_UNKNOW_REPLAY; + inOutLen = sizeof(int32_t); + GetIpcReplyByType(&replyCache, REPLAY_CACHE_NUM(replyCache), PARAM_TYPE_IPC_RESULT, (uint8_t *)&ret, &inOutLen); + LOGI("process done, device num %d", ret); + DestroyCallCtx(&callCtx, NULL); + return ret; +} + +static bool IpcGaIsTrustedDevice(const char *udid) +{ + uintptr_t callCtx = 0x0; + int32_t ret; + int32_t inOutLen; + IpcDataInfo replyCache = {0}; + + LOGI("starting ..."); + if (udid == NULL) { + return HC_ERR_INVALID_PARAMS; + } + if (!IsServiceRunning()) { + LOGE("service is not activity"); + return HC_ERROR; + } + ret = CreateCallCtx(&callCtx, NULL); + if (ret != HC_SUCCESS) { + LOGE("CreateCallCtx failed, ret %d", ret); + return HC_ERR_IPC_INIT; + } + uint32_t udidLen = strlen(udid) + 1; + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_COMM_DATA, (const uint8_t *)udid, udidLen); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_COMM_DATA); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = DoBinderCall(callCtx, IPC_CALL_ID_IS_TRUST_DEVICE, true); + if (ret == HC_ERR_IPC_INTERNAL_FAILED) { + LOGE("ipc call failed"); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_PROC_FAILED; + } + DecodeCallReply(callCtx, &replyCache, REPLAY_CACHE_NUM(replyCache)); + ret = HC_ERR_IPC_UNKNOW_REPLAY; + inOutLen = sizeof(int32_t); + GetIpcReplyByType(&replyCache, REPLAY_CACHE_NUM(replyCache), PARAM_TYPE_IPC_RESULT, (uint8_t *)&ret, &inOutLen); + LOGI("process done, ret %d", ret); + DestroyCallCtx(&callCtx, NULL); + return (ret == HC_SUCCESS) ? true : false; +} + +static int32_t FormParamsForGettingAuthState(int64_t authReqId, const char *groupId, + const char *peerUdid, uintptr_t callCtx) +{ + int32_t ret; + int32_t inOutLen; + inOutLen = sizeof(authReqId); + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_REQID, (const uint8_t *)&authReqId, inOutLen); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_REQID); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_GROUPID, (const uint8_t *)groupId, strlen(groupId) + 1); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_GROUPID); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_UDID, (const uint8_t *)peerUdid, strlen(peerUdid) + 1); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_UDID); + return HC_ERR_IPC_BUILD_PARAM; + } + return HC_SUCCESS; +} + +static int32_t IpcGaGetAuthState(int64_t authReqId, const char *groupId, + const char *peerUdid, uint8_t *out, uint32_t *outLen) +{ + uintptr_t callCtx = 0x0; + int32_t ret; + int32_t inOutLen; + IpcDataInfo replyCache[IPC_DATA_CACHES_3] = {{0}}; + + LOGI("starting ..."); + if (!IS_STRING_VALID(peerUdid) || !IS_STRING_VALID(groupId) || (out == NULL) || (outLen == NULL)) { + LOGE("invalid params"); + return HC_ERR_INVALID_PARAMS; + } + if (!IsServiceRunning()) { + LOGE("service is not activity"); + return HC_ERROR; + } + ret = CreateCallCtx(&callCtx, NULL); + if (ret != HC_SUCCESS) { + LOGE("CreateCallCtx failed, ret %d", ret); + return HC_ERR_IPC_INIT; + } + ret = FormParamsForGettingAuthState(authReqId, groupId, peerUdid, callCtx); + if (ret != HC_SUCCESS) { + DestroyCallCtx(&callCtx, NULL); + return ret; + } + ret = DoBinderCall(callCtx, IPC_CALL_ID_GET_AUTH_STATE, true); + if (ret == HC_ERR_IPC_INTERNAL_FAILED) { + LOGE("ipc call failed"); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_PROC_FAILED; + } + DecodeCallReply(callCtx, replyCache, REPLAY_CACHE_NUM(replyCache)); + ret = HC_ERR_IPC_UNKNOW_REPLAY; + inOutLen = sizeof(int32_t); + GetIpcReplyByType(replyCache, REPLAY_CACHE_NUM(replyCache), PARAM_TYPE_IPC_RESULT, (uint8_t *)&ret, &inOutLen); + LOGI("process done, ret %d", ret); + if (ret != HC_SUCCESS) { + DestroyCallCtx(&callCtx, NULL); + return ret; + } + GetIpcReplyByType(replyCache, REPLAY_CACHE_NUM(replyCache), PARAM_TYPE_COMM_DATA, out, (int32_t *)outLen); + DestroyCallCtx(&callCtx, NULL); + return ret; +} + +static int32_t IpcGaAuthDevice(int64_t authReqId, const char *authParams, const DeviceAuthCallback *callback) +{ + uintptr_t callCtx = 0x0; + int32_t ret; + int32_t inOutLen; + IpcDataInfo replyCache = {0}; + + LOGI("starting ..."); + if (!IS_STRING_VALID(authParams) || (callback == NULL)) { + LOGE("invalid params"); + return HC_ERR_INVALID_PARAMS; + } + if (!IsServiceRunning()) { + LOGE("service is not activity"); + return HC_ERROR; + } + ret = CreateCallCtx(&callCtx, NULL); + if (ret != HC_SUCCESS) { + LOGE("CreateCallCtx failed, ret %d", ret); + return HC_ERR_IPC_INIT; + } + + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_REQID, (const uint8_t *)(&authReqId), sizeof(authReqId)); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, type %d", ret, PARAM_TYPE_REQID); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_AUTH_PARAMS, (const uint8_t *)authParams, strlen(authParams) + 1); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, type %d", ret, PARAM_TYPE_AUTH_PARAMS); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_DEV_AUTH_CB, (const uint8_t *)callback, sizeof(*callback)); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, type %d", ret, PARAM_TYPE_DEV_AUTH_CB); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } + SetCbCtxToDataCtx(callCtx, IPC_CALL_BACK_STUB_AUTH_ID); + ret = DoBinderCall(callCtx, IPC_CALL_ID_AUTH_DEVICE, true); + if (ret == HC_ERR_IPC_INTERNAL_FAILED) { + LOGE("ipc call failed"); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_PROC_FAILED; + } + DecodeCallReply(callCtx, &replyCache, REPLAY_CACHE_NUM(replyCache)); + ret = HC_ERR_IPC_UNKNOW_REPLAY; + inOutLen = sizeof(int32_t); + GetIpcReplyByType(&replyCache, REPLAY_CACHE_NUM(replyCache), PARAM_TYPE_IPC_RESULT, (uint8_t *)&ret, &inOutLen); + LOGI("process done, ret %d", ret); + DestroyCallCtx(&callCtx, NULL); + return ret; +} + +static void IpcGaInformDeviceDisconn(const char *udid) +{ + uintptr_t callCtx = 0x0; + int32_t ret; + + LOGI("entering ..."); + if (udid == NULL) { + LOGE("invalid params"); + return; + } + if (!IsServiceRunning()) { + LOGE("service is not activity"); + return; + } + ret = CreateCallCtx(&callCtx, NULL); + if (ret != HC_SUCCESS) { + LOGE("CreateCallCtx failed, ret %d", ret); + return; + } + uint32_t udidLen = strlen(udid) + 1; + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_COMM_DATA, (const uint8_t *)udid, udidLen); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_COMM_DATA); + DestroyCallCtx(&callCtx, NULL); + return; + } + ret = DoBinderCall(callCtx, IPC_CALL_ID_INFORM_DEV_DISCONN, true); + if (ret == HC_ERR_IPC_INTERNAL_FAILED) { + LOGE("ipc call error"); + DestroyCallCtx(&callCtx, NULL); + return; + } + LOGI("process done"); + DestroyCallCtx(&callCtx, NULL); + return; +} + +static void InitIpcGaMethods(GroupAuthManager *gaMethodObj) +{ + LOGI("entering..."); + gaMethodObj->processData = IpcGaProcessData; + gaMethodObj->queryTrustedDeviceNum = IpcGaQueryTrustedDeviceNum; + gaMethodObj->isTrustedDevice = IpcGaIsTrustedDevice; + gaMethodObj->getAuthState = IpcGaGetAuthState; + gaMethodObj->authDevice = IpcGaAuthDevice; + gaMethodObj->informDeviceDisconnection = IpcGaInformDeviceDisconn; + LOGI("process done"); + return; +} + +DEVICE_AUTH_API_PUBLIC int InitDeviceAuthService(void) +{ + InitHcMutex(&g_ipcMutex); + return HC_SUCCESS; +} + +DEVICE_AUTH_API_PUBLIC void DestroyDeviceAuthService(void) +{ + DestroyHcMutex(&g_ipcMutex); +} + +DEVICE_AUTH_API_PUBLIC const GroupAuthManager *GetGaInstance(void) +{ + static GroupAuthManager gaInstCtx = {NULL}; + static GroupAuthManager *gaInstPtr = NULL; + + LOGI("Enter InitIpcMethods..."); + if (gaInstPtr == NULL) { + InitIpcGaMethods(&gaInstCtx); + gaInstPtr = &gaInstCtx; + } + LOGI("InitIpcMethods done"); + return (const GroupAuthManager *)(gaInstPtr); +} + +DEVICE_AUTH_API_PUBLIC const DeviceGroupManager *GetGmInstance(void) +{ + static DeviceGroupManager gmInstCtx = {NULL}; + static DeviceGroupManager *gmInstPtr = NULL; + + LOGI("Enter InitIpcMethods..."); + if (gmInstPtr == NULL) { + InitIpcGmMethods(&gmInstCtx); + gmInstPtr = &gmInstCtx; + } + LOGI("InitIpcMethods done"); + return (const DeviceGroupManager *)(gmInstPtr); +} + +#ifdef __cplusplus +} +#endif diff --git a/frameworks/src/ipc_service.c b/frameworks/src/ipc_service.c new file mode 100644 index 0000000..c6e4725 --- /dev/null +++ b/frameworks/src/ipc_service.c @@ -0,0 +1,1327 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ipc_service.h" + +#include "common_defs.h" +#include "device_auth_defines.h" +#include "device_auth.h" +#include "hc_condition.h" +#include "hc_log.h" +#include "hc_thread.h" +#include "ipc_adapt.h" +#include "ipc_sdk.h" +#include "securec.h" + +#ifdef __cplusplus +extern "C" { +#endif + +static const int32_t g_ipcResultNum1 = IPC_RESULT_NUM_1; +static const int32_t g_ipcResultNum2 = IPC_RESULT_NUM_2; +static const char *g_serviceAppId = "deviceauth_service"; +static DeviceGroupManager g_devGroupMgrMethod = {NULL}; +static GroupAuthManager g_groupAuthMgrMethod = {NULL}; +static DeviceAuthCallback g_bindCbAdt = {NULL}; +static DeviceAuthCallback g_authCbAdt = {NULL}; +static DataChangeListener g_listenCbAdt = {NULL}; + +static int32_t BindRequestIdWithAppId(const char *data) +{ + const char *appId = NULL; + int32_t ret; + int64_t requestId = -1; + CJson *dataJson = CreateJsonFromString(data); + if (dataJson == NULL) { + LOGE("failed to create json from string!"); + return HC_ERROR; + } + + appId = GetStringFromJson(dataJson, FIELD_APP_ID); + if (appId == NULL) { + LOGE("failed to get appId from json object!"); + FreeJson(dataJson); + return HC_ERROR; + } + (void)GetInt64FromJson(dataJson, FIELD_REQUEST_ID, &requestId); + ret = AddReqIdByAppId(appId, requestId); + FreeJson(dataJson); + return ret; +} + +static int32_t IpcServiceGmRegCallback(const IpcDataInfo *ipcParams, int32_t paramNum, uintptr_t outCache) +{ + int32_t callRet; + int32_t ret; + const char *appId = NULL; + const DeviceAuthCallback *callback = NULL; + int32_t cbObjIdx = -1; + int32_t idxLen; + + LOGI("starting ..."); + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_APPID, (uint8_t *)&appId, NULL); + if (ret != HC_SUCCESS) { + LOGE("get param error, type %d", PARAM_TYPE_APPID); + return ret; + } + + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_DEV_AUTH_CB, (uint8_t *)&callback, NULL); + if (ret != HC_SUCCESS) { + LOGE("get param error, type %d", PARAM_TYPE_DEV_AUTH_CB); + return ret; + } + ret = AddIpcCallBackByAppId(appId, (const uint8_t *)callback, sizeof(DeviceAuthCallback), CB_TYPE_DEV_AUTH); + if (ret != HC_SUCCESS) { + LOGE("add ipc callback failed"); + return HC_ERROR; + } + + idxLen = sizeof(cbObjIdx); + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_CB_OBJECT, (uint8_t *)&cbObjIdx, &idxLen); + if (ret != HC_SUCCESS) { + LOGE("get param error, type %d", PARAM_TYPE_CB_OBJECT); + DelIpcCallBackByAppId(appId, CB_TYPE_DEV_AUTH); + return ret; + } + AddIpcCbObjByAppId(appId, cbObjIdx, CB_TYPE_DEV_AUTH); + InitDeviceAuthCbCtx(&g_bindCbAdt, CB_TYPE_DEV_AUTH); + callRet = g_devGroupMgrMethod.regCallback(appId, &g_bindCbAdt); + if (callRet != HC_SUCCESS) { + DelIpcCallBackByAppId(appId, CB_TYPE_DEV_AUTH); + } + ret = IpcEncodeCallReplay(outCache, PARAM_TYPE_IPC_RESULT, (const uint8_t *)&callRet, sizeof(int32_t)); + LOGI("process done, call ret %d, ipc ret %d", callRet, ret); + return ret; +} + +static int32_t IpcServiceGmUnRegCallback(const IpcDataInfo *ipcParams, int32_t paramNum, uintptr_t outCache) +{ + int32_t callRet = HC_SUCCESS; + int32_t ret; + const char *appId = NULL; + + LOGI("starting ..."); + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_APPID, (uint8_t *)&appId, NULL); + if (ret != HC_SUCCESS) { + LOGE("get param error, type %d", PARAM_TYPE_APPID); + return ret; + } + + DelIpcCallBackByAppId(appId, CB_TYPE_DEV_AUTH); + ret = IpcEncodeCallReplay(outCache, PARAM_TYPE_IPC_RESULT, (const uint8_t *)&callRet, sizeof(int32_t)); + LOGI("process done, call ret %d, ipc ret %d", callRet, ret); + return ret; +} + +static int32_t IpcServiceGmRegDataChangeListener(const IpcDataInfo *ipcParams, int32_t paramNum, uintptr_t outCache) +{ + int32_t callRet; + int32_t ret; + const char *appId = NULL; + const DataChangeListener *callback = NULL; + static int32_t registered = 0; + int32_t cbObjIdx = -1; + int32_t idxLen; + + LOGI("starting ..."); + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_APPID, (uint8_t *)&appId, NULL); + if (ret != HC_SUCCESS) { + LOGE("get param error, type %d", PARAM_TYPE_APPID); + return ret; + } + + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_LISTERNER, (uint8_t *)&callback, NULL); + if (ret != HC_SUCCESS) { + LOGE("get param error, type %d", PARAM_TYPE_LISTERNER); + return ret; + } + + ret = AddIpcCallBackByAppId(appId, (const uint8_t *)callback, sizeof(DataChangeListener), CB_TYPE_LISTENER); + if (ret != HC_SUCCESS) { + LOGE("add ipc callback failed"); + return HC_ERROR; + } + + idxLen = sizeof(cbObjIdx); + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_CB_OBJECT, (uint8_t *)&cbObjIdx, &idxLen); + if (ret != HC_SUCCESS) { + LOGE("get param error, type %d", PARAM_TYPE_CB_OBJECT); + DelIpcCallBackByAppId(appId, CB_TYPE_DEV_AUTH); + return ret; + } + AddIpcCbObjByAppId(appId, cbObjIdx, CB_TYPE_LISTENER); + + callRet = HC_SUCCESS; + if (registered == 0) { + InitDevAuthListenerCbCtx(&g_listenCbAdt); + callRet = g_devGroupMgrMethod.regDataChangeListener(g_serviceAppId, &g_listenCbAdt); + if (callRet == HC_SUCCESS) { + registered = 1; + } else { + DelIpcCallBackByAppId(appId, CB_TYPE_LISTENER); + } + } + ret = IpcEncodeCallReplay(outCache, PARAM_TYPE_IPC_RESULT, (const uint8_t *)&callRet, sizeof(int32_t)); + LOGI("process done, call ret %d, ipc ret %d", callRet, ret); + return ret; +} + +static int32_t IpcServiceGmUnRegDataChangeListener(const IpcDataInfo *ipcParams, int32_t paramNum, uintptr_t outCache) +{ + int32_t callRet = HC_SUCCESS; + int32_t ret; + const char *appId = NULL; + + LOGI("starting ..."); + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_APPID, (uint8_t *)&appId, NULL); + if (ret != HC_SUCCESS) { + LOGE("get param error, type %d", PARAM_TYPE_APPID); + return ret; + } + DelIpcCallBackByAppId(appId, CB_TYPE_LISTENER); + ret = IpcEncodeCallReplay(outCache, PARAM_TYPE_IPC_RESULT, (const uint8_t *)&callRet, sizeof(int32_t)); + LOGI("process done, call ret %d, ipc ret %d", callRet, ret); + return ret; +} + +static int32_t IpcServiceGmCreateGroup(const IpcDataInfo *ipcParams, int32_t paramNum, uintptr_t outCache) +{ + int32_t callRet; + int32_t ret; + int64_t requestId = 0; + int32_t inOutLen; + const char *createParams = NULL; + const char *appId = NULL; + + LOGI("starting ..."); + inOutLen = sizeof(int64_t); + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_REQID, (uint8_t *)&requestId, &inOutLen); + if ((ret != HC_SUCCESS) || (inOutLen != sizeof(int64_t))) { + LOGE("get param error, type %d", PARAM_TYPE_REQID); + return ret; + } + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_APPID, (uint8_t *)&appId, NULL); + if (ret != HC_SUCCESS) { + LOGE("get param error, type %d", PARAM_TYPE_APPID); + return ret; + } + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_CREATE_PARAMS, (uint8_t *)&createParams, NULL); + if (ret != HC_SUCCESS) { + LOGE("get param error, type %d", PARAM_TYPE_CREATE_PARAMS); + return ret; + } + + callRet = g_devGroupMgrMethod.createGroup(requestId, appId, createParams); + ret = IpcEncodeCallReplay(outCache, PARAM_TYPE_IPC_RESULT, (const uint8_t *)&callRet, sizeof(int32_t)); + LOGI("process done, call ret %d, ipc ret %d", callRet, ret); + return ret; +} + +static int32_t IpcServiceGmDelGroup(const IpcDataInfo *ipcParams, int32_t paramNum, uintptr_t outCache) +{ + int32_t callRet; + int32_t ret; + int64_t requestId = 0; + int32_t inOutLen; + const char *appId = NULL; + const char *groupId = NULL; + + LOGI("starting ..."); + inOutLen = sizeof(int64_t); + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_REQID, (uint8_t *)&requestId, &inOutLen); + if ((ret != HC_SUCCESS) || (inOutLen != sizeof(int64_t))) { + LOGE("get param error, type %d", PARAM_TYPE_REQID); + return ret; + } + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_APPID, (uint8_t *)&appId, NULL); + if (ret != HC_SUCCESS) { + LOGE("get param error, type %d", PARAM_TYPE_APPID); + return ret; + } + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_GROUPID, (uint8_t *)&groupId, NULL); + if (ret != HC_SUCCESS) { + LOGE("get param error, type %d", PARAM_TYPE_GROUPID); + return ret; + } + + callRet = g_devGroupMgrMethod.deleteGroup(requestId, groupId, appId); + ret = IpcEncodeCallReplay(outCache, PARAM_TYPE_IPC_RESULT, (const uint8_t *)&callRet, sizeof(int32_t)); + LOGI("process done, call ret %d, ipc ret %d", callRet, ret); + return ret; +} + +static int32_t IpcServiceGmAddMemberToGroup(const IpcDataInfo *ipcParams, int32_t paramNum, uintptr_t outCache) +{ + int32_t callRet; + int32_t ret; + int32_t inOutLen; + int64_t requestId = 0; + const char *addParams = NULL; + const char *groupId = NULL; + + LOGI("starting ..."); + inOutLen = sizeof(int64_t); + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_REQID, (uint8_t *)&requestId, &inOutLen); + if ((ret != HC_SUCCESS) || (inOutLen != sizeof(int64_t))) { + LOGE("get param error, type %d", PARAM_TYPE_REQID); + return ret; + } + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_ADD_PARAMS, (uint8_t *)&addParams, NULL); + if (ret != HC_SUCCESS) { + LOGE("get param error, type %d", PARAM_TYPE_ADD_PARAMS); + return ret; + } + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_GROUPID, (uint8_t *)&groupId, NULL); + if (ret != HC_SUCCESS) { + LOGE("get param error, type %d", PARAM_TYPE_GROUPID); + return ret; + } + + callRet = g_devGroupMgrMethod.addMemberToGroup(requestId, groupId, addParams); + ret = IpcEncodeCallReplay(outCache, PARAM_TYPE_IPC_RESULT, (const uint8_t *)&callRet, sizeof(int32_t)); + LOGI("process done, call ret %d, ipc ret %d", callRet, ret); + return ret; +} + +static int32_t IpcServiceGmDelMemberFromGroup(const IpcDataInfo *ipcParams, int32_t paramNum, uintptr_t outCache) +{ + int32_t callRet; + int32_t ret; + int32_t inOutLen; + int64_t requestId = 0; + const char *delParams = NULL; + const char *appId = NULL; + + LOGI("starting ..."); + inOutLen = sizeof(int64_t); + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_REQID, (uint8_t *)&requestId, &inOutLen); + if ((ret != HC_SUCCESS) || (inOutLen != sizeof(int64_t))) { + LOGE("get param error, type %d", PARAM_TYPE_REQID); + return ret; + } + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_APPID, (uint8_t *)&appId, NULL); + if (ret != HC_SUCCESS) { + LOGE("get param error, type %d", PARAM_TYPE_APPID); + return ret; + } + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_DEL_PARAMS, (uint8_t *)&delParams, NULL); + if (ret != HC_SUCCESS) { + LOGE("get param error, type %d", PARAM_TYPE_DEL_PARAMS); + return ret; + } + + callRet = g_devGroupMgrMethod.deleteMemberFromGroup(requestId, appId, delParams); + ret = IpcEncodeCallReplay(outCache, PARAM_TYPE_IPC_RESULT, (const uint8_t *)&callRet, sizeof(int32_t)); + LOGI("process done, call ret %d, ipc ret %d", callRet, ret); + return ret; +} + +static int32_t IpcServiceGmProcessData(const IpcDataInfo *ipcParams, int32_t paramNum, uintptr_t outCache) +{ + int32_t callRet; + int32_t ret; + int32_t dataLen; + int32_t inOutLen; + int64_t requestId = 0; + const uint8_t *data = NULL; + + LOGI("starting ..."); + inOutLen = sizeof(int64_t); + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_REQID, (uint8_t *)&requestId, &inOutLen); + if ((ret != HC_SUCCESS) || (inOutLen != sizeof(int64_t))) { + LOGE("get param error, type %d", PARAM_TYPE_REQID); + return ret; + } + + dataLen = 0; + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_COMM_DATA, (uint8_t *)&data, &dataLen); + if ((ret != HC_SUCCESS) || (dataLen <= 0)) { + LOGE("get param error, type %d, data length %d", PARAM_TYPE_COMM_DATA, dataLen); + return ret; + } + ret = BindRequestIdWithAppId((const char *)data); + if (ret != HC_SUCCESS) { + return ret; + } + callRet = g_devGroupMgrMethod.processData(requestId, data, dataLen); + ret = IpcEncodeCallReplay(outCache, PARAM_TYPE_IPC_RESULT, (const uint8_t *)&callRet, sizeof(int32_t)); + LOGI("process done, call ret %d, ipc ret %d", callRet, ret); + return ret; +} + +static int32_t IpcServiceGmConfirmRequest(const IpcDataInfo *ipcParams, int32_t paramNum, uintptr_t outCache) +{ + int32_t callRet; + int32_t ret; + int32_t inOutLen; + int64_t requestId = 0; + const char *cfmParams = NULL; + const char *appId = NULL; + + LOGI("starting ..."); + inOutLen = sizeof(int64_t); + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_REQID, (uint8_t *)&requestId, &inOutLen); + if ((ret != HC_SUCCESS) || (inOutLen != sizeof(int64_t))) { + LOGE("get param error, type %d", PARAM_TYPE_REQID); + return ret; + } + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_APPID, (uint8_t *)&cfmParams, NULL); + if (ret != HC_SUCCESS) { + LOGE("get param error, type %d", PARAM_TYPE_APPID); + return ret; + } + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_REQ_CFM, (uint8_t *)&cfmParams, NULL); + if (ret != HC_SUCCESS) { + LOGE("get param error, type %d", PARAM_TYPE_REQ_CFM); + return ret; + } + + callRet = g_devGroupMgrMethod.confirmRequest(requestId, appId, cfmParams); + ret = IpcEncodeCallReplay(outCache, PARAM_TYPE_IPC_RESULT, (const uint8_t *)&callRet, sizeof(int32_t)); + LOGI("process done, call ret %d, ipc ret %d", callRet, ret); + return ret; +} + +static int32_t IpcServiceGmBindPeer(const IpcDataInfo *ipcParams, int32_t paramNum, uintptr_t outCache) +{ + int32_t callRet; + int32_t ret; + int32_t inOutLen; + int64_t requestId = 0; + const char *bindParams = NULL; + const char *appId = NULL; + + LOGI("starting ..."); + inOutLen = sizeof(int64_t); + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_REQID, (uint8_t *)&requestId, &inOutLen); + if ((ret != HC_SUCCESS) || (inOutLen != sizeof(int64_t))) { + LOGE("get param error, type %d", PARAM_TYPE_REQID); + return ret; + } + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_APPID, (uint8_t *)&appId, NULL); + if (ret != HC_SUCCESS) { + LOGE("get param error, type %d", PARAM_TYPE_APPID); + return ret; + } + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_BIND, (uint8_t *)&bindParams, NULL); + if (ret != HC_SUCCESS) { + LOGE("get param error, type %d", PARAM_TYPE_BIND); + return ret; + } + + callRet = g_devGroupMgrMethod.bindPeer(requestId, appId, bindParams); + ret = IpcEncodeCallReplay(outCache, PARAM_TYPE_IPC_RESULT, (const uint8_t *)&callRet, sizeof(int32_t)); + LOGI("process done, call ret %d, ipc ret %d", callRet, ret); + return ret; +} + +static int32_t IpcServiceGmUnBindPeer(const IpcDataInfo *ipcParams, int32_t paramNum, uintptr_t outCache) +{ + int32_t callRet; + int32_t ret; + int32_t inOutLen; + int64_t requestId = 0; + const char *unBindParams = NULL; + const char *appId = NULL; + + LOGI("starting ..."); + inOutLen = sizeof(int64_t); + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_REQID, (uint8_t *)&requestId, &inOutLen); + if ((ret != HC_SUCCESS) || (inOutLen != sizeof(int64_t))) { + LOGE("get param error, type %d", PARAM_TYPE_REQID); + return ret; + } + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_APPID, (uint8_t *)&appId, NULL); + if (ret != HC_SUCCESS) { + LOGE("get param error, type %d", PARAM_TYPE_UNBIND); + return ret; + } + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_UNBIND, (uint8_t *)&unBindParams, NULL); + if (ret != HC_SUCCESS) { + LOGE("get param error, type %d", PARAM_TYPE_UNBIND); + return ret; + } + + callRet = g_devGroupMgrMethod.unbindPeer(requestId, appId, unBindParams); + ret = IpcEncodeCallReplay(outCache, PARAM_TYPE_IPC_RESULT, (const uint8_t *)&callRet, sizeof(int32_t)); + LOGI("process done, call ret %d, ipc ret %d", callRet, ret); + return ret; +} + +static int32_t IpcServiceGmProcessLiteData(const IpcDataInfo *ipcParams, int32_t paramNum, uintptr_t outCache) +{ + int32_t callRet; + int32_t ret; + int32_t dataLen; + int32_t inOutLen; + int64_t requestId; + const uint8_t *data = NULL; + const char *appId = NULL; + + LOGI("starting ..."); + inOutLen = sizeof(int64_t); + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_REQID, (uint8_t *)&requestId, &inOutLen); + if ((ret != HC_SUCCESS) || (inOutLen != sizeof(int64_t))) { + LOGE("get param error, type %d", PARAM_TYPE_REQID); + return ret; + } + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_APPID, (uint8_t *)&appId, NULL); + if ((ret != HC_SUCCESS) || (appId == NULL)) { + LOGE("get param error, type %d", PARAM_TYPE_APPID); + return ret; + } + + dataLen = 0; + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_COMM_DATA, (uint8_t *)&data, &dataLen); + if ((ret != HC_SUCCESS) || (dataLen <= 0)) { + LOGE("get param error, type %d", PARAM_TYPE_COMM_DATA); + return ret; + } + AddReqIdByAppId(appId, requestId); + callRet = g_devGroupMgrMethod.processLiteData(requestId, appId, data, dataLen); + ret = IpcEncodeCallReplay(outCache, PARAM_TYPE_IPC_RESULT, (const uint8_t *)&callRet, sizeof(int32_t)); + LOGI("process done, call ret %d, ipc ret %d", callRet, ret); + return ret; +} + +static int32_t IpcServiceGmSaveCredential(const IpcDataInfo *ipcParams, int32_t paramNum, uintptr_t outCache) +{ + int32_t callRet; + int32_t ret; + int32_t opCode = 0; + int32_t inOutLen; + const char *credential = NULL; + char *returnJsonStr = NULL; + + LOGI("starting ..."); + inOutLen = sizeof(int32_t); + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_OPCODE, (uint8_t *)&opCode, &inOutLen); + if ((ret != HC_SUCCESS) || (inOutLen != sizeof(int32_t))) { + LOGE("get param error, type %d", PARAM_TYPE_OPCODE); + return ret; + } + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_CREDENTIAL, (uint8_t *)&credential, NULL); + if ((ret != HC_SUCCESS) || (credential == NULL)) { + LOGE("get param error, type %d", PARAM_TYPE_CREDENTIAL); + return ret; + } + callRet = g_devGroupMgrMethod.processCredential(opCode, credential, &returnJsonStr); + ret = IpcEncodeCallReplay(outCache, PARAM_TYPE_IPC_RESULT, (const uint8_t *)&callRet, sizeof(int32_t)); + LOGI("process done, call ret %d, ipc ret %d", callRet, ret); + if ((ret == HC_SUCCESS) && (returnJsonStr != NULL)) { + ret += IpcEncodeCallReplay(outCache, PARAM_TYPE_REQ_INFO, + (const uint8_t *)returnJsonStr, strlen(returnJsonStr) + 1); + g_devGroupMgrMethod.destroyInfo(&returnJsonStr); + } else { + ret += IpcEncodeCallReplay(outCache, PARAM_TYPE_REG_INFO, NULL, 0); + } + return (ret == HC_SUCCESS) ? ret : HC_ERROR; +} + +static int32_t IpcServiceGmApplyRegisterInfo(const IpcDataInfo *ipcParams, int32_t paramNum, uintptr_t outCache) +{ + int32_t callRet; + int32_t ret; + char *registerInfo = NULL; + + (void)ipcParams; + (void)paramNum; + LOGI("starting ..."); + callRet = g_devGroupMgrMethod.getRegisterInfo(®isterInfo); + ret = IpcEncodeCallReplay(outCache, PARAM_TYPE_IPC_RESULT, (const uint8_t *)&callRet, sizeof(int32_t)); + ret += IpcEncodeCallReplay(outCache, PARAM_TYPE_IPC_RESULT_NUM, + (const uint8_t *)&g_ipcResultNum1, sizeof(int32_t)); + if (registerInfo != NULL) { + ret += IpcEncodeCallReplay(outCache, PARAM_TYPE_REG_INFO, + (const uint8_t *)registerInfo, strlen(registerInfo) + 1); + g_devGroupMgrMethod.destroyInfo(®isterInfo); + } else { + ret += IpcEncodeCallReplay(outCache, PARAM_TYPE_REG_INFO, NULL, 0); + } + LOGI("process done, call ret %d, ipc ret %d", callRet, ret); + return (ret == HC_SUCCESS) ? ret : HC_ERROR; +} + +static int32_t IpcServiceGmAddGroupManager(const IpcDataInfo *ipcParams, int32_t paramNum, uintptr_t outCache) +{ + int32_t callRet; + int32_t ret; + const char *appId = NULL; + const char *groupId = NULL; + const char *managerAppId = NULL; + + LOGI("starting ..."); + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_APPID, (uint8_t *)&appId, NULL); + if ((ret != HC_SUCCESS) || (appId == NULL)) { + LOGE("get param error, type %d", PARAM_TYPE_APPID); + return ret; + } + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_GROUPID, (uint8_t *)&groupId, NULL); + if ((ret != HC_SUCCESS) || (groupId == NULL)) { + LOGE("get param error, type %d", PARAM_TYPE_GROUPID); + return ret; + } + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_MGR_APPID, (uint8_t *)&managerAppId, NULL); + if ((ret != HC_SUCCESS) || (managerAppId == NULL)) { + LOGE("get param error, type %d", PARAM_TYPE_MGR_APPID); + return ret; + } + callRet = g_devGroupMgrMethod.addGroupManager(appId, groupId, managerAppId); + ret = IpcEncodeCallReplay(outCache, PARAM_TYPE_IPC_RESULT, (const uint8_t *)&callRet, sizeof(int32_t)); + LOGI("process done, call ret %d, ipc ret %d", callRet, ret); + return ret; +} + +static int32_t IpcServiceGmAddGroupFriend(const IpcDataInfo *ipcParams, int32_t paramNum, uintptr_t outCache) +{ + int32_t callRet; + int32_t ret; + const char *appId = NULL; + const char *groupId = NULL; + const char *friendAppId = NULL; + + LOGI("starting ..."); + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_APPID, (uint8_t *)&appId, NULL); + if ((ret != HC_SUCCESS) || (appId == NULL)) { + LOGE("get param error, type %d", PARAM_TYPE_APPID); + return ret; + } + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_GROUPID, (uint8_t *)&groupId, NULL); + if ((ret != HC_SUCCESS) || (groupId == NULL)) { + LOGE("get param error, type %d", PARAM_TYPE_GROUPID); + return ret; + } + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_FRIEND_APPID, (uint8_t *)&friendAppId, NULL); + if ((ret != HC_SUCCESS) || (friendAppId == NULL)) { + LOGE("get param error, type %d", PARAM_TYPE_FRIEND_APPID); + return ret; + } + callRet = g_devGroupMgrMethod.addGroupFriend(appId, groupId, friendAppId); + ret = IpcEncodeCallReplay(outCache, PARAM_TYPE_IPC_RESULT, (const uint8_t *)&callRet, sizeof(int32_t)); + LOGI("process done, call ret %d, ipc ret %d", callRet, ret); + return ret; +} + +static int32_t IpcServiceGmDelGroupManager(const IpcDataInfo *ipcParams, int32_t paramNum, uintptr_t outCache) +{ + int32_t callRet; + int32_t ret; + const char *appId = NULL; + const char *groupId = NULL; + const char *managerAppId = NULL; + + LOGI("starting ..."); + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_APPID, (uint8_t *)&appId, NULL); + if ((ret != HC_SUCCESS) || (appId == NULL)) { + LOGE("get param error, type %d", PARAM_TYPE_APPID); + return ret; + } + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_GROUPID, (uint8_t *)&groupId, NULL); + if ((ret != HC_SUCCESS) || (groupId == NULL)) { + LOGE("get param error, type %d", PARAM_TYPE_GROUPID); + return ret; + } + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_MGR_APPID, (uint8_t *)&managerAppId, NULL); + if ((ret != HC_SUCCESS) || (managerAppId == NULL)) { + LOGE("get param error, type %d", PARAM_TYPE_MGR_APPID); + return ret; + } + callRet = g_devGroupMgrMethod.deleteGroupManager(appId, groupId, managerAppId); + ret = IpcEncodeCallReplay(outCache, PARAM_TYPE_IPC_RESULT, (const uint8_t *)&callRet, sizeof(int32_t)); + LOGI("process done, call ret %d, ipc ret %d", callRet, ret); + return ret; +} + +static int32_t IpcServiceGmDelGroupFriend(const IpcDataInfo *ipcParams, int32_t paramNum, uintptr_t outCache) +{ + int32_t callRet; + int32_t ret; + const char *appId = NULL; + const char *groupId = NULL; + const char *friendAppId = NULL; + + LOGI("starting ..."); + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_APPID, (uint8_t *)&appId, NULL); + if ((ret != HC_SUCCESS) || (appId == NULL)) { + LOGE("get param error, type %d", PARAM_TYPE_APPID); + return ret; + } + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_GROUPID, (uint8_t *)&groupId, NULL); + if ((ret != HC_SUCCESS) || (groupId == NULL)) { + LOGE("get param error, type %d", PARAM_TYPE_GROUPID); + return ret; + } + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_FRIEND_APPID, (uint8_t *)&friendAppId, NULL); + if ((ret != HC_SUCCESS) || (friendAppId == NULL)) { + LOGE("get param error, type %d", PARAM_TYPE_FRIEND_APPID); + return ret; + } + callRet = g_devGroupMgrMethod.deleteGroupFriend(appId, groupId, friendAppId); + ret = IpcEncodeCallReplay(outCache, PARAM_TYPE_IPC_RESULT, (const uint8_t *)&callRet, sizeof(int32_t)); + LOGI("process done, call ret %d, ipc ret %d", callRet, ret); + return ret; +} + +static int32_t IpcServiceGmGetGroupManagers(const IpcDataInfo *ipcParams, int32_t paramNum, uintptr_t outCache) +{ + int32_t callRet; + int32_t ret; + const char *appId = NULL; + const char *groupId = NULL; + char *managers = NULL; + uint32_t managersNum = 0; + + LOGI("starting ..."); + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_APPID, (uint8_t *)&appId, NULL); + if ((ret != HC_SUCCESS) || (appId == NULL)) { + LOGE("get param error, type %d", PARAM_TYPE_APPID); + return ret; + } + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_GROUPID, (uint8_t *)&groupId, NULL); + if ((ret != HC_SUCCESS) || (groupId == NULL)) { + LOGE("get param error, type %d", PARAM_TYPE_GROUPID); + return ret; + } + + callRet = g_devGroupMgrMethod.getGroupManagers(appId, groupId, &managers, &managersNum); + ret = IpcEncodeCallReplay(outCache, PARAM_TYPE_IPC_RESULT, (const uint8_t *)&callRet, sizeof(int32_t)); + ret += IpcEncodeCallReplay(outCache, PARAM_TYPE_IPC_RESULT_NUM, + (const uint8_t *)&g_ipcResultNum2, sizeof(int32_t)); + if (managers != NULL) { + ret += IpcEncodeCallReplay(outCache, PARAM_TYPE_MGR_APPID, (const uint8_t *)managers, strlen(managers) + 1); + g_devGroupMgrMethod.destroyInfo(&managers); + } else { + ret += IpcEncodeCallReplay(outCache, PARAM_TYPE_MGR_APPID, NULL, 0); + } + ret += IpcEncodeCallReplay(outCache, PARAM_TYPE_DATA_NUM, (const uint8_t *)&managersNum, sizeof(int32_t)); + LOGI("process done, call ret %d, ipc ret %d", callRet, ret); + return (ret == HC_SUCCESS) ? ret : HC_ERROR; +} + +static int32_t IpcServiceGmGetGroupFriends(const IpcDataInfo *ipcParams, int32_t paramNum, uintptr_t outCache) +{ + int32_t callRet; + int32_t ret; + const char *appId = NULL; + const char *groupId = NULL; + char *friends = NULL; + uint32_t friendsNum = 0; + + LOGI("starting ..."); + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_APPID, (uint8_t *)&appId, NULL); + if ((ret != HC_SUCCESS) || (appId == NULL)) { + LOGE("get param error, type %d", PARAM_TYPE_APPID); + return ret; + } + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_GROUPID, (uint8_t *)&groupId, NULL); + if ((ret != HC_SUCCESS) || (groupId == NULL)) { + LOGE("get param error, type %d", PARAM_TYPE_GROUPID); + return ret; + } + + callRet = g_devGroupMgrMethod.getGroupFriends(appId, groupId, &friends, &friendsNum); + ret = IpcEncodeCallReplay(outCache, PARAM_TYPE_IPC_RESULT, (const uint8_t *)&callRet, sizeof(int32_t)); + ret += IpcEncodeCallReplay(outCache, PARAM_TYPE_IPC_RESULT_NUM, + (const uint8_t *)&g_ipcResultNum2, sizeof(int32_t)); + if (friends != NULL) { + ret += IpcEncodeCallReplay(outCache, PARAM_TYPE_FRIEND_APPID, (const uint8_t *)friends, strlen(friends) + 1); + g_devGroupMgrMethod.destroyInfo(&friends); + } else { + ret += IpcEncodeCallReplay(outCache, PARAM_TYPE_FRIEND_APPID, NULL, 0); + } + ret += IpcEncodeCallReplay(outCache, PARAM_TYPE_DATA_NUM, (const uint8_t *)&friendsNum, sizeof(int32_t)); + LOGI("process done, call ret %d, ipc ret %d", callRet, ret); + return (ret == HC_SUCCESS) ? ret : HC_ERROR; +} + +static int32_t IpcServiceGmGetGroupInfoById(const IpcDataInfo *ipcParams, int32_t paramNum, uintptr_t outCache) +{ + int32_t callRet; + int32_t ret; + const char *appId = NULL; + const char *groupId = NULL; + char *groupInfo = NULL; + + LOGI("starting ..."); + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_APPID, (uint8_t *)&appId, NULL); + if ((ret != HC_SUCCESS) || (appId == NULL)) { + LOGE("get param error, type %d", PARAM_TYPE_APPID); + return ret; + } + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_GROUPID, (uint8_t *)&groupId, NULL); + if ((ret != HC_SUCCESS) || (groupId == NULL)) { + LOGE("get param error, type %d", PARAM_TYPE_GROUPID); + return ret; + } + + callRet = g_devGroupMgrMethod.getGroupInfoById(appId, groupId, &groupInfo); + ret = IpcEncodeCallReplay(outCache, PARAM_TYPE_IPC_RESULT, (const uint8_t *)&callRet, sizeof(int32_t)); + ret += IpcEncodeCallReplay(outCache, PARAM_TYPE_IPC_RESULT_NUM, + (const uint8_t *)&g_ipcResultNum1, sizeof(int32_t)); + if (groupInfo != NULL) { + ret += IpcEncodeCallReplay(outCache, PARAM_TYPE_GROUP_INFO, (const uint8_t *)groupInfo, strlen(groupInfo) + 1); + g_devGroupMgrMethod.destroyInfo(&groupInfo); + } else { + ret += IpcEncodeCallReplay(outCache, PARAM_TYPE_GROUP_INFO, NULL, 0); + } + LOGI("process done, call ret %d, ipc ret %d", callRet, ret); + return (ret == HC_SUCCESS) ? ret : HC_ERROR; +} + +static int32_t IpcServiceGmGetGroupInfo(const IpcDataInfo *ipcParams, int32_t paramNum, uintptr_t outCache) +{ + int32_t callRet; + int32_t ret; + const char *appId = NULL; + const char *queryParams = NULL; + char *outGroups = NULL; + uint32_t groupNum = 0; + + LOGI("starting ..."); + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_APPID, (uint8_t *)&appId, NULL); + if ((ret != HC_SUCCESS) || (appId == NULL)) { + LOGE("get param error, type %d", PARAM_TYPE_APPID); + return ret; + } + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_QUERY_PARAMS, (uint8_t *)&queryParams, NULL); + if ((ret != HC_SUCCESS) || (queryParams == NULL)) { + LOGE("get param error, type %d", PARAM_TYPE_QUERY_PARAMS); + return ret; + } + + callRet = g_devGroupMgrMethod.getGroupInfo(appId, queryParams, &outGroups, &groupNum); + ret = IpcEncodeCallReplay(outCache, PARAM_TYPE_IPC_RESULT, (const uint8_t *)&callRet, sizeof(int32_t)); + ret += IpcEncodeCallReplay(outCache, PARAM_TYPE_IPC_RESULT_NUM, + (const uint8_t *)&g_ipcResultNum2, sizeof(int32_t)); + if (outGroups != NULL) { + ret += IpcEncodeCallReplay(outCache, PARAM_TYPE_GROUP_INFO, (const uint8_t *)outGroups, strlen(outGroups) + 1); + } else { + ret += IpcEncodeCallReplay(outCache, PARAM_TYPE_GROUP_INFO, NULL, 0); + } + ret += IpcEncodeCallReplay(outCache, PARAM_TYPE_DATA_NUM, (const uint8_t *)&groupNum, sizeof(int32_t)); + LOGI("process done, call ret %d, ipc ret %d", callRet, ret); + g_devGroupMgrMethod.destroyInfo(&outGroups); + return (ret == HC_SUCCESS) ? ret : HC_ERROR; +} + +static int32_t IpcServiceGmGetJoinedGroups(const IpcDataInfo *ipcParams, int32_t paramNum, uintptr_t outCache) +{ + int32_t callRet; + int32_t ret; + int32_t groupType = 0; + const char *appId = NULL; + char *outGroups = NULL; + uint32_t groupNum = 0; + int32_t inOutLen; + + LOGI("starting ..."); + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_APPID, (uint8_t *)&appId, NULL); + if ((ret != HC_SUCCESS) || (appId == NULL)) { + LOGE("get param error, type %d", PARAM_TYPE_APPID); + return ret; + } + inOutLen = sizeof(groupType); + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_GROUP_TYPE, (uint8_t *)&groupType, &inOutLen); + if ((ret != HC_SUCCESS || (inOutLen != sizeof(groupType)))) { + LOGE("get param error, type %d", PARAM_TYPE_GROUP_TYPE); + return ret; + } + + callRet = g_devGroupMgrMethod.getJoinedGroups(appId, groupType, &outGroups, &groupNum); + ret = IpcEncodeCallReplay(outCache, PARAM_TYPE_IPC_RESULT, (const uint8_t *)&callRet, sizeof(int32_t)); + ret += IpcEncodeCallReplay(outCache, PARAM_TYPE_IPC_RESULT_NUM, + (const uint8_t *)&g_ipcResultNum2, sizeof(int32_t)); + if (outGroups != NULL) { + ret += IpcEncodeCallReplay(outCache, PARAM_TYPE_GROUP_INFO, (const uint8_t *)outGroups, strlen(outGroups) + 1); + g_devGroupMgrMethod.destroyInfo(&outGroups); + } else { + ret += IpcEncodeCallReplay(outCache, PARAM_TYPE_GROUP_INFO, NULL, 0); + } + ret += IpcEncodeCallReplay(outCache, PARAM_TYPE_DATA_NUM, (const uint8_t *)&groupNum, sizeof(int32_t)); + LOGI("process done, call ret %d, ipc ret %d", callRet, ret); + return (ret == HC_SUCCESS) ? ret : HC_ERROR; +} + +static int32_t IpcServiceGmGetRelatedGroups(const IpcDataInfo *ipcParams, int32_t paramNum, uintptr_t outCache) +{ + int32_t callRet; + int32_t ret; + const char *appId = NULL; + const char *peerUdid = NULL; + char *outGroups = NULL; + uint32_t groupNum = 0; + + LOGI("starting ..."); + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_APPID, (uint8_t *)&appId, NULL); + if ((ret != HC_SUCCESS) || (appId == NULL)) { + LOGE("get param error, type %d", PARAM_TYPE_APPID); + return ret; + } + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_UDID, (uint8_t *)&peerUdid, NULL); + if ((ret != HC_SUCCESS) || (peerUdid == NULL)) { + LOGE("get param error, type %d", PARAM_TYPE_UDID); + return ret; + } + + callRet = g_devGroupMgrMethod.getRelatedGroups(appId, peerUdid, &outGroups, &groupNum); + ret = IpcEncodeCallReplay(outCache, PARAM_TYPE_IPC_RESULT, (const uint8_t *)&callRet, sizeof(int32_t)); + ret += IpcEncodeCallReplay(outCache, PARAM_TYPE_IPC_RESULT_NUM, + (const uint8_t *)&g_ipcResultNum2, sizeof(int32_t)); + if (outGroups != NULL) { + ret += IpcEncodeCallReplay(outCache, PARAM_TYPE_GROUP_INFO, (const uint8_t *)outGroups, strlen(outGroups) + 1); + } else { + ret += IpcEncodeCallReplay(outCache, PARAM_TYPE_GROUP_INFO, NULL, 0); + } + ret += IpcEncodeCallReplay(outCache, PARAM_TYPE_DATA_NUM, (const uint8_t *)&groupNum, sizeof(int32_t)); + LOGI("process done, call ret %d, ipc ret %d", callRet, ret); + g_devGroupMgrMethod.destroyInfo(&outGroups); + return (ret == HC_SUCCESS) ? ret : HC_ERROR; +} + +static int32_t IpcServiceGmGetDeviceInfoById(const IpcDataInfo *ipcParams, int32_t paramNum, uintptr_t outCache) +{ + int32_t callRet; + int32_t ret; + const char *appId = NULL; + const char *peerUdid = NULL; + const char *groupId = NULL; + char *outDevInfo = NULL; + + LOGI("starting ..."); + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_APPID, (uint8_t *)&appId, NULL); + if ((ret != HC_SUCCESS) || (appId == NULL)) { + LOGE("get param error, type %d", PARAM_TYPE_APPID); + return ret; + } + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_UDID, (uint8_t *)&peerUdid, NULL); + if ((ret != HC_SUCCESS) || (peerUdid == NULL)) { + LOGE("get param error, type %d", PARAM_TYPE_UDID); + return ret; + } + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_GROUPID, (uint8_t *)&groupId, NULL); + if ((ret != HC_SUCCESS) || (groupId == NULL)) { + LOGE("get param error, type %d", PARAM_TYPE_GROUPID); + return ret; + } + + callRet = g_devGroupMgrMethod.getDeviceInfoById(appId, peerUdid, groupId, &outDevInfo); + ret = IpcEncodeCallReplay(outCache, PARAM_TYPE_IPC_RESULT, (const uint8_t *)&callRet, sizeof(int32_t)); + ret += IpcEncodeCallReplay(outCache, PARAM_TYPE_IPC_RESULT_NUM, + (const uint8_t *)&g_ipcResultNum1, sizeof(int32_t)); + if (outDevInfo != NULL) { + ret += IpcEncodeCallReplay(outCache, PARAM_TYPE_DEVICE_INFO, + (const uint8_t *)outDevInfo, strlen(outDevInfo) + 1); + g_devGroupMgrMethod.destroyInfo(&outDevInfo); + } else { + ret += IpcEncodeCallReplay(outCache, PARAM_TYPE_DEVICE_INFO, NULL, 0); + } + LOGI("process done, call ret %d, ipc ret %d", callRet, ret); + return (ret == HC_SUCCESS) ? ret : HC_ERROR; +} + +static int32_t IpcServiceGmGetTrustedDevices(const IpcDataInfo *ipcParams, int32_t paramNum, uintptr_t outCache) +{ + int32_t callRet; + int32_t ret; + const char *appId = NULL; + const char *groupId = NULL; + char *outDevInfo = NULL; + uint32_t outDevNum = 0; + + LOGI("starting ..."); + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_APPID, (uint8_t *)&appId, NULL); + if ((ret != HC_SUCCESS) || (appId == NULL)) { + LOGE("get param error, type %d", PARAM_TYPE_APPID); + return ret; + } + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_GROUPID, (uint8_t *)&groupId, NULL); + if ((ret != HC_SUCCESS) || (groupId == NULL)) { + LOGE("get param error, type %d", PARAM_TYPE_GROUPID); + return ret; + } + + callRet = g_devGroupMgrMethod.getTrustedDevices(appId, groupId, &outDevInfo, &outDevNum); + ret = IpcEncodeCallReplay(outCache, PARAM_TYPE_IPC_RESULT, (const uint8_t *)&callRet, sizeof(int32_t)); + ret += IpcEncodeCallReplay(outCache, PARAM_TYPE_IPC_RESULT_NUM, + (const uint8_t *)&g_ipcResultNum2, sizeof(int32_t)); + if (outDevInfo != NULL) { + ret += IpcEncodeCallReplay(outCache, PARAM_TYPE_DEVICE_INFO, + (const uint8_t *)outDevInfo, strlen(outDevInfo) + 1); + } else { + ret += IpcEncodeCallReplay(outCache, PARAM_TYPE_DEVICE_INFO, NULL, 0); + } + ret += IpcEncodeCallReplay(outCache, PARAM_TYPE_DATA_NUM, (const uint8_t *)&outDevNum, sizeof(int32_t)); + LOGI("process done, call ret %d, ipc ret %d", callRet, ret); + g_devGroupMgrMethod.destroyInfo(&outDevInfo); + return (ret == HC_SUCCESS) ? ret : HC_ERROR; +} + +static int32_t IpcServiceGmIsDeviceInGroup(const IpcDataInfo *ipcParams, int32_t paramNum, uintptr_t outCache) +{ + int32_t callRet; + int32_t ret; + bool bRet = false; + const char *appId = NULL; + const char *udid = NULL; + const char *groupId = NULL; + + LOGI("starting ..."); + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_APPID, (uint8_t *)&appId, NULL); + if ((ret != HC_SUCCESS) || (appId == NULL)) { + LOGE("get param error, type %d", PARAM_TYPE_APPID); + return ret; + } + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_UDID, (uint8_t *)&udid, NULL); + if ((ret != HC_SUCCESS) || (udid == NULL)) { + LOGE("get param error, type %d", PARAM_TYPE_UDID); + return ret; + } + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_GROUPID, (uint8_t *)&groupId, NULL); + if ((ret != HC_SUCCESS) || (groupId == NULL)) { + LOGE("get param error, type %d", PARAM_TYPE_GROUPID); + return ret; + } + + bRet = g_devGroupMgrMethod.isDeviceInGroup(appId, groupId, udid); + callRet = ((bRet == true) ? HC_SUCCESS : HC_ERROR); + ret = IpcEncodeCallReplay(outCache, PARAM_TYPE_IPC_RESULT, (const uint8_t *)&callRet, sizeof(int32_t)); + LOGI("process done, call ret %d, ipc ret %d", callRet, ret); + return ret; +} + +static int32_t IpcServiceGaProcessData(const IpcDataInfo *ipcParams, int32_t paramNum, uintptr_t outCache) +{ + int32_t callRet; + int32_t ret; + const DeviceAuthCallback *gaCallback = NULL; + int64_t authReqId = 0; + uint8_t *data = NULL; + uint32_t dataLen = 0; + int32_t inOutLen; + int32_t cbObjIdx = -1; + + LOGI("starting ..."); + inOutLen = sizeof(authReqId); + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_REQID, (uint8_t *)&authReqId, &inOutLen); + if ((ret != HC_SUCCESS) || (inOutLen != sizeof(authReqId))) { + LOGE("get param error, type %d", PARAM_TYPE_REQID); + return ret; + } + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_COMM_DATA, (uint8_t *)&data, (int32_t *)&dataLen); + if ((ret != HC_SUCCESS) || (data == NULL) || (dataLen == 0)) { + LOGE("get param error, type %d", PARAM_TYPE_COMM_DATA); + return ret; + } + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_DEV_AUTH_CB, (uint8_t *)&gaCallback, NULL); + if (ret != HC_SUCCESS) { + LOGE("get param error, type %d", PARAM_TYPE_DEV_AUTH_CB); + return ret; + } + /* add call back */ + ret = AddIpcCallBackByReqId(authReqId, (const uint8_t *)gaCallback, + sizeof(DeviceAuthCallback), CB_TYPE_TMP_DEV_AUTH); + if (ret != HC_SUCCESS) { + LOGE("add ipc callback failed"); + return HC_ERROR; + } + inOutLen = sizeof(cbObjIdx); + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_CB_OBJECT, (uint8_t *)&cbObjIdx, &inOutLen); + if (ret != HC_SUCCESS) { + LOGE("get param error, type %d", PARAM_TYPE_CB_OBJECT); + DelIpcCallBackByReqId(authReqId, CB_TYPE_TMP_DEV_AUTH, true); + return ret; + } + AddIpcCbObjByReqId(authReqId, cbObjIdx, CB_TYPE_TMP_DEV_AUTH); + InitDeviceAuthCbCtx(&g_authCbAdt, CB_TYPE_TMP_DEV_AUTH); + callRet = g_groupAuthMgrMethod.processData(authReqId, data, dataLen, &g_authCbAdt); + if (callRet != HC_SUCCESS) { + DelIpcCallBackByReqId(authReqId, CB_TYPE_TMP_DEV_AUTH, true); + } + ret = IpcEncodeCallReplay(outCache, PARAM_TYPE_IPC_RESULT, (const uint8_t *)&callRet, sizeof(int32_t)); + LOGI("process done, call ret %d, ipc ret %d", callRet, ret); + return ret; +} + +static int32_t IpcServiceGaQueryTrustedDeviceNum(const IpcDataInfo *ipcParams, int32_t paramNum, uintptr_t outCache) +{ + int32_t callRet; + int32_t ret; + + (void)ipcParams; + (void)paramNum; + LOGI("starting ..."); + callRet = g_groupAuthMgrMethod.queryTrustedDeviceNum(); + ret = IpcEncodeCallReplay(outCache, PARAM_TYPE_IPC_RESULT, (const uint8_t *)&callRet, sizeof(int32_t)); + LOGI("process done, call ret %d, ipc ret %d", callRet, ret); + return ret; +} + +static int32_t IpcServiceGaIsTrustedDevice(const IpcDataInfo *ipcParams, int32_t paramNum, uintptr_t outCache) +{ + int32_t callRet; + int32_t ret; + int32_t udidLen = 0; + bool bRet = false; + const char *udid = NULL; + + LOGI("starting ..."); + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_COMM_DATA, (uint8_t *)&udid, &udidLen); + if ((ret != HC_SUCCESS) || (udid == NULL) || (udidLen == 0)) { + LOGE("get param error, type %d", PARAM_TYPE_COMM_DATA); + return ret; + } + + bRet = g_groupAuthMgrMethod.isTrustedDevice(udid); + callRet = ((bRet == true) ? HC_SUCCESS : HC_ERROR); + ret = IpcEncodeCallReplay(outCache, PARAM_TYPE_IPC_RESULT, (const uint8_t *)&callRet, sizeof(int32_t)); + LOGI("process done, call ret %d, ipc ret %d", callRet, ret); + return ret; +} + +static int32_t IpcServiceGaGetAuthState(const IpcDataInfo *ipcParams, int32_t paramNum, uintptr_t outCache) +{ + int32_t callRet; + int32_t ret; + const char *groupId = NULL; + const char *peerUdid = NULL; + int64_t authReqId = 0; + int32_t inOutLen; + uint8_t out[512] = {0}; /* 512 - buffer size */ + uint32_t outLen = sizeof(out); + + LOGI("starting ..."); + inOutLen = sizeof(authReqId); + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_REQID, (uint8_t *)&authReqId, &inOutLen); + if ((ret != HC_SUCCESS) || (inOutLen != sizeof(authReqId))) { + LOGE("get param error, type %d", PARAM_TYPE_REQID); + return ret; + } + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_GROUPID, (uint8_t *)&groupId, NULL); + if (ret != HC_SUCCESS) { + LOGE("get param error, type %d", PARAM_TYPE_GROUPID); + return ret; + } + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_UDID, (uint8_t *)&peerUdid, NULL); + if (ret != HC_SUCCESS) { + LOGE("get param error, type %d", PARAM_TYPE_UDID); + return ret; + } + + callRet = g_groupAuthMgrMethod.getAuthState(authReqId, groupId, peerUdid, out, &outLen); + ret = IpcEncodeCallReplay(outCache, PARAM_TYPE_IPC_RESULT, (const uint8_t *)&callRet, sizeof(int32_t)); + ret += IpcEncodeCallReplay(outCache, PARAM_TYPE_COMM_DATA, (const uint8_t *)out, (int32_t)outLen); + LOGI("process done, call ret %d, ipc ret %d", callRet, ret); + return (ret == HC_SUCCESS) ? ret : HC_ERROR; +} + +static int32_t IpcServiceGaAuthDevice(const IpcDataInfo *ipcParams, int32_t paramNum, uintptr_t outCache) +{ + int32_t callRet; + int32_t ret; + DeviceAuthCallback *gaCallback = NULL; + int64_t authReqId = 0; + const char *authParams = NULL; + int32_t inOutLen; + int32_t cbObjIdx = -1; + + LOGI("starting ..."); + inOutLen = sizeof(authReqId); + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_REQID, (uint8_t *)&authReqId, &inOutLen); + if ((ret != HC_SUCCESS) || (inOutLen != sizeof(authReqId))) { + LOGE("get param error, type %d", PARAM_TYPE_REQID); + return ret; + } + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_AUTH_PARAMS, (uint8_t *)&authParams, NULL); + if ((ret != HC_SUCCESS) || (authParams == NULL)) { + LOGE("get param error, type %d", PARAM_TYPE_AUTH_PARAMS); + return ret; + } + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_DEV_AUTH_CB, (uint8_t *)&gaCallback, NULL); + if (ret != HC_SUCCESS) { + LOGE("get param error, type %d", PARAM_TYPE_DEV_AUTH_CB); + return ret; + } + + /* add call back */ + ret = AddIpcCallBackByReqId(authReqId, (const uint8_t *)gaCallback, + sizeof(DeviceAuthCallback), CB_TYPE_TMP_DEV_AUTH); + if (ret != HC_SUCCESS) { + LOGE("add ipc callback failed"); + return HC_ERROR; + } + inOutLen = sizeof(cbObjIdx); + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_CB_OBJECT, (uint8_t *)&cbObjIdx, &inOutLen); + if (ret != HC_SUCCESS) { + LOGE("get param error, type %d", PARAM_TYPE_CB_OBJECT); + DelIpcCallBackByReqId(authReqId, CB_TYPE_TMP_DEV_AUTH, true); + return ret; + } + AddIpcCbObjByReqId(authReqId, cbObjIdx, CB_TYPE_TMP_DEV_AUTH); + InitDeviceAuthCbCtx(&g_authCbAdt, CB_TYPE_TMP_DEV_AUTH); + callRet = g_groupAuthMgrMethod.authDevice(authReqId, authParams, &g_authCbAdt); + if (callRet != HC_SUCCESS) { + DelIpcCallBackByReqId(authReqId, CB_TYPE_TMP_DEV_AUTH, true); + } + ret = IpcEncodeCallReplay(outCache, PARAM_TYPE_IPC_RESULT, (const uint8_t *)&callRet, sizeof(int32_t)); + LOGI("process done, call ret %d, ipc ret %d", callRet, ret); + return ret; +} + +static int32_t IpcServiceGaInformDevDisconnection(const IpcDataInfo *ipcParams, int32_t paramNum, uintptr_t outCache) +{ + int32_t callRet = HC_SUCCESS; + int32_t ret; + int32_t udidLen = 0; + const char *udid = NULL; + + LOGI("starting ..."); + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_COMM_DATA, (uint8_t *)&udid, &udidLen); + if ((ret != HC_SUCCESS) || (udid == NULL) || (udidLen == 0)) { + LOGE("get param error, type %d", PARAM_TYPE_COMM_DATA); + return ret; + } + + g_groupAuthMgrMethod.informDeviceDisconnection(udid); + ret = IpcEncodeCallReplay(outCache, PARAM_TYPE_IPC_RESULT, (const uint8_t *)&callRet, sizeof(int32_t)); + LOGI("process done, call ret %d, ipc ret %d", callRet, ret); + return ret; +} + +static int32_t AddMethodMap(uintptr_t ipcInstance) +{ + uint32_t ret; + + ret = SetIpcCallMap(ipcInstance, IpcServiceGmRegCallback, IPC_CALL_ID_REG_CB); + ret &= SetIpcCallMap(ipcInstance, IpcServiceGmUnRegCallback, IPC_CALL_ID_UNREG_CB); + ret &= SetIpcCallMap(ipcInstance, IpcServiceGmRegDataChangeListener, IPC_CALL_ID_REG_LISTENER); + ret &= SetIpcCallMap(ipcInstance, IpcServiceGmUnRegDataChangeListener, IPC_CALL_ID_UNREG_LISTENER); + ret &= SetIpcCallMap(ipcInstance, IpcServiceGmCreateGroup, IPC_CALL_ID_CREATE_GROUP); + ret &= SetIpcCallMap(ipcInstance, IpcServiceGmDelGroup, IPC_CALL_ID_DEL_GROUP); + ret &= SetIpcCallMap(ipcInstance, IpcServiceGmAddMemberToGroup, IPC_CALL_ID_ADD_GROUP_MEMBER); + ret &= SetIpcCallMap(ipcInstance, IpcServiceGmDelMemberFromGroup, IPC_CALL_ID_DEL_GROUP_MEMBER); + ret &= SetIpcCallMap(ipcInstance, IpcServiceGmProcessData, IPC_CALL_ID_GM_PROC_DATA); + ret &= SetIpcCallMap(ipcInstance, IpcServiceGmConfirmRequest, IPC_CALL_ID_CFM_REQUEST); + ret &= SetIpcCallMap(ipcInstance, IpcServiceGmBindPeer, IPC_CALL_ID_BIND_PEER); + ret &= SetIpcCallMap(ipcInstance, IpcServiceGmUnBindPeer, IPC_CALL_ID_UNBIND_PEER); + ret &= SetIpcCallMap(ipcInstance, IpcServiceGmProcessLiteData, IPC_CALL_ID_PROC_LIGHT_DATA); + ret &= SetIpcCallMap(ipcInstance, IpcServiceGmSaveCredential, IPC_CALL_ID_SAVE_CREDENTIAL); + ret &= SetIpcCallMap(ipcInstance, IpcServiceGmApplyRegisterInfo, IPC_CALL_ID_APPLY_REG_INFO); + ret &= SetIpcCallMap(ipcInstance, IpcServiceGmAddGroupManager, IPC_CALL_ID_ADD_GROUP_MGR); + ret &= SetIpcCallMap(ipcInstance, IpcServiceGmAddGroupFriend, IPC_CALL_ID_ADD_GROUP_FRIEND); + ret &= SetIpcCallMap(ipcInstance, IpcServiceGmDelGroupManager, IPC_CALL_ID_DEL_GROUP_MGR); + ret &= SetIpcCallMap(ipcInstance, IpcServiceGmDelGroupFriend, IPC_CALL_ID_DEL_GROUP_FRIEND); + ret &= SetIpcCallMap(ipcInstance, IpcServiceGmGetGroupManagers, IPC_CALL_ID_GET_GROUP_MGR); + ret &= SetIpcCallMap(ipcInstance, IpcServiceGmGetGroupFriends, IPC_CALL_ID_GET_GROUP_FRIEND); + ret &= SetIpcCallMap(ipcInstance, IpcServiceGmGetGroupInfoById, IPC_CALL_ID_GET_GROUP_INFO); + ret &= SetIpcCallMap(ipcInstance, IpcServiceGmGetGroupInfo, IPC_CALL_ID_SEARCH_GROUPS); + ret &= SetIpcCallMap(ipcInstance, IpcServiceGmGetJoinedGroups, IPC_CALL_ID_GET_JOINED_GROUPS); + ret &= SetIpcCallMap(ipcInstance, IpcServiceGmGetRelatedGroups, IPC_CALL_ID_GET_RELATED_GROUPS); + ret &= SetIpcCallMap(ipcInstance, IpcServiceGmGetDeviceInfoById, IPC_CALL_ID_GET_DEV_INFO_BY_ID); + ret &= SetIpcCallMap(ipcInstance, IpcServiceGmGetTrustedDevices, IPC_CALL_ID_GET_TRUST_DEVICES); + ret &= SetIpcCallMap(ipcInstance, IpcServiceGmIsDeviceInGroup, IPC_CALL_ID_IS_DEV_IN_GROUP); + ret &= SetIpcCallMap(ipcInstance, IpcServiceGaProcessData, IPC_CALL_ID_GA_PROC_DATA); + ret &= SetIpcCallMap(ipcInstance, IpcServiceGaQueryTrustedDeviceNum, IPC_CALL_ID_QUERY_TRUST_DEV_NUM); + ret &= SetIpcCallMap(ipcInstance, IpcServiceGaIsTrustedDevice, IPC_CALL_ID_IS_TRUST_DEVICE); + ret &= SetIpcCallMap(ipcInstance, IpcServiceGaGetAuthState, IPC_CALL_ID_GET_AUTH_STATE); + ret &= SetIpcCallMap(ipcInstance, IpcServiceGaAuthDevice, IPC_CALL_ID_AUTH_DEVICE); + ret &= SetIpcCallMap(ipcInstance, IpcServiceGaInformDevDisconnection, IPC_CALL_ID_INFORM_DEV_DISCONN); + LOGI("process done, ret %u", ret); + return ret; +} + +void DeMainRescInit(uintptr_t *serviceCtx) +{ + if (g_devGroupMgrMethod.unRegDataChangeListener != NULL) { + (void)g_devGroupMgrMethod.unRegDataChangeListener(g_serviceAppId); + } + DeInitIpcCallBackList(); + DestroyServiceInstance(serviceCtx); + return; +} + +int32_t MainRescInit(void) +{ + int32_t ret; + const DeviceGroupManager *gmInst = NULL; + const GroupAuthManager *gaInst = NULL; + + LOGI("starting ..."); + ret = InitIpcCallBackList(); + if (ret != HC_SUCCESS) { + return ret; + } + gmInst = GetGmInstance(); + gaInst = GetGaInstance(); + if ((gmInst == NULL) || (gaInst == NULL)) { + DeInitIpcCallBackList(); + LOGE("MainInit, GetGmInstance failed"); + return HC_ERROR; + } + g_devGroupMgrMethod = (DeviceGroupManager)(*gmInst); + g_groupAuthMgrMethod = (GroupAuthManager)(*gaInst); + InitDevAuthListenerCbCtx(&g_listenCbAdt); + ret = gmInst->regDataChangeListener(g_serviceAppId, &g_listenCbAdt); + if (ret != HC_SUCCESS) { + DeInitIpcCallBackList(); + LOGE("MainInit, register ipc listener failed, ret %d", ret); + return HC_ERROR; + } + + LOGI("process done"); + return HC_SUCCESS; +} + +int32_t main(int32_t argc, char const *argv[]) +{ + uintptr_t serviceCtx = 0x0; + int32_t ret; + HcCondition cond; + + (void)argc; + (void)argv; + LOGI("device authentication service starting ..."); + ret = InitDeviceAuthService(); + if (ret != HC_SUCCESS) { + LOGE("device auth service main, InitDeviceAuthService failed, ret %d", ret); + return 1; + } + + ret = MainRescInit(); + if (ret != HC_SUCCESS) { + DestroyDeviceAuthService(); + LOGE("device auth service main, init work failed"); + return 1; + } + + ret = AddDevAuthServiceToManager(&serviceCtx); + if (ret != HC_SUCCESS) { + DeMainRescInit(&serviceCtx); + DestroyDeviceAuthService(); + serviceCtx = 0x0; + LOGE("device auth service main, AddDevAuthServiceToManager failed, ret %d", ret); + return 1; + } + (void)AddMethodMap(serviceCtx); + LOGI("device authentication service register to IPC manager done, service running..."); + (void)memset_s(&cond, sizeof(cond), 0, sizeof(cond)); + InitHcCond(&cond, NULL); + cond.wait(&cond); + DestroyHcCond(&cond); + return 0; +} + +#ifdef __cplusplus +} +#endif diff --git a/hals/BUILD.gn b/hals/BUILD.gn new file mode 100644 index 0000000..127466d --- /dev/null +++ b/hals/BUILD.gn @@ -0,0 +1,94 @@ +# Copyright (C) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("deviceauth_hals.gni") + +hal_common_files = [ + "src/common/hc_parcel.c", + "src/common/hc_string.c", + "src/common/hc_task_thread.c", + "src/common/hc_tlv_parser.c", + "src/common/json_utils.c", + "src/common/common_util.c", + "src/common/alg_loader.c", +] + +ohos_static_library("deviceauth_hal_linux") { + subsystem_name = "security" + + include_dirs = hals_inc_path + include_dirs += [ + "//third_party/cJSON", + "//utils/native/base/include", + "//third_party/openssl/include/", + "//base/security/huks/interfaces/innerkits/huks_standard/main/include", + ] + + sources = hal_common_files + sources += [ + "src/dev_info/3516/hc_dev_info.c", + "src/linux/L2/crypto_hash_to_point.c", + "src/linux/L2/huks_adapter.c", + "src/linux/hc_condition.c", + "src/linux/hc_file.c", + "src/linux/hc_init_protection.c", + "src/linux/hc_mutex.c", + "src/linux/hc_thread.c", + "src/linux/hc_time.c", + "src/linux/hc_types.c", + ] + + cflags = [ "-DHILOG_ENABLE" ] + + deps = [ + "//base/security/huks/interfaces/innerkits/huks_standard/main:libhukssdk", + "//third_party/cJSON:cjson_static", + "//third_party/openssl:libcrypto_static", + "//utils/native/base:utils", + ] + + external_deps = [ "hiviewdfx_hilog_native:libhilog" ] +} + +ohos_static_library("deviceauth_hal_liteos") { + subsystem_name = "security" + + include_dirs = hals_inc_path + include_dirs += [ + "//third_party/cJSON", + "//utils/native/base/include", + ] + + sources = hal_common_files + sources += [ + "src/dev_info/watch/hc_dev_info.c", + "src/liteos/L0/hc_init_protection.c", + "src/liteos/L0/huks_adapter.c", + "src/liteos/hc_condition.c", + "src/liteos/hc_file.c", + "src/liteos/hc_mutex.c", + "src/liteos/hc_thread.c", + "src/liteos/hc_time.c", + "src/liteos/hc_types.c", + ] + + cflags = [ "-DHILOG_ENABLE" ] + + deps = [ + "//third_party/cJSON:cjson", + "//utils/native/base:utils", + ] + + external_deps = [ "hiviewdfx_hilog_native:libhilog" ] +} diff --git a/hals/deviceauth_hals.gni b/hals/deviceauth_hals.gni new file mode 100644 index 0000000..4ab003a --- /dev/null +++ b/hals/deviceauth_hals.gni @@ -0,0 +1,30 @@ +# Copyright (C) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//base/security/deviceauth/deviceauth_env.gni") + +if (target_os == "liteos") { + hals_inc_path = [ + "${hals_path}/inc/common", + "${hals_path}/inc/liteos", + "${hals_path}/inc/dev_info/watch", + ] + hal_module_name = "deviceauth_hal_liteos" +} else { + hals_inc_path = [ + "${hals_path}/inc/common", + "${hals_path}/inc/linux", + "${hals_path}/inc/dev_info/3516", + ] + hal_module_name = "deviceauth_hal_linux" +} diff --git a/hals/inc/common/alg_defs.h b/hals/inc/common/alg_defs.h new file mode 100644 index 0000000..edcca29 --- /dev/null +++ b/hals/inc/common/alg_defs.h @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ALG_DEFS_H +#define ALG_DEFS_H + +#include "common_util.h" +#include "hc_types.h" + +#define SHA256_LEN 32 +#define HMAC_LEN 32 +#define SIGNATURE_LEN 64 +#define AE_TAG_LEN 16 +#define BIG_PRIME_LEN_384 384 +#define BIG_PRIME_LEN_256 256 + +typedef enum { + PAIR_TYPE_BIND = 0, + PAIR_TYPE_CLONE = 1, + PAIR_TYPE_END +} PairType; // range: 0 ~ 2^8-1 + +typedef struct { + Uint8Buff authId; + int32_t userType; + int32_t pairType; +} ExtraInfo; + +typedef enum { + ED25519 = 0, + X25519 = 1, + P256 = 2, +} Algorithm; + +typedef enum { + CURVE_NONE, + CURVE_256, + CURVE_25519, +} CurveType; + +typedef struct { + uint8_t *nonce; + uint32_t nonceLen; + uint8_t *aad; + uint32_t aadLen; +} GcmParam; + +typedef struct { + uint8_t *key; + uint32_t keyLen; + bool isAlias; +} KeyBuff; + +typedef int32_t (*InitAlgFunc)(); + +typedef int32_t (*Sha256Func)(const Uint8Buff *message, Uint8Buff *hash); + +typedef int32_t (*GenerateRandomFunc)(Uint8Buff *rand); + +typedef int32_t (*ComputeHmacFunc)(const Uint8Buff *key, const Uint8Buff *message, Uint8Buff *outHmac, bool isAlias); + +typedef int32_t (*ComputeHkdfFunc)(const Uint8Buff *baseKey, const Uint8Buff *salt, const Uint8Buff *keyInfo, + Uint8Buff *outHkdf, bool isAlias); + +typedef int32_t (*ImportAsymmetricKeyFunc)(const Uint8Buff *keyAlias, const Uint8Buff *authToken, + const ExtraInfo *exInfo); + +typedef int32_t (*CheckKeyExistFunc)(const Uint8Buff *keyAlias); +typedef int32_t (*DeleteKeyFunc)(const Uint8Buff *keyAlias); + +typedef int32_t (*AesGcmEncryptFunc)(const Uint8Buff *key, const Uint8Buff *plain, + const GcmParam *encryptInfo, bool isAlias, Uint8Buff *outCipher); +typedef int32_t (*AesGcmDecryptFunc)(const Uint8Buff *key, const Uint8Buff *cipher, + const GcmParam *decryptInfo, bool isAlias, Uint8Buff *outPlain); + +typedef int32_t (*GetTrustAuthIdListFunc)(const Uint8Buff *ownerAuthId, int32_t trustUserType, + Uint8Buff *outAuthIdList, uint32_t *outCount); + +typedef int32_t (*HashToPointFunc)(const Uint8Buff *hash, Algorithm algo, Uint8Buff *outEcPoint); + +typedef int32_t (*AgreeSharedSecretWithStorageFunc)(const KeyBuff *priKey, const KeyBuff *pubKey, Algorithm algo, + uint32_t sharedKeyLen, const Uint8Buff *sharedKeyAlias); + +typedef int32_t (*AgreeSharedSecretFunc)(const KeyBuff *priKey, const KeyBuff *pubKey, Algorithm algo, + Uint8Buff *sharedKey); + +typedef int32_t (*ComputePublicKeyFunc)(const Uint8Buff *priKey, const Uint8Buff *base, Algorithm algo, + Uint8Buff *pubKey); + +typedef int32_t (*BigNumExpModFunc)(const Uint8Buff *base, const Uint8Buff *exp, const char *bigNumHex, + Uint8Buff *outNum); + +typedef int32_t (*GenerateKeyPairWithStorageFunc)(const Uint8Buff *keyAlias, uint32_t keyLen, Algorithm algo, + const ExtraInfo *exInfo); + +typedef int32_t (*GenerateKeyPairFunc)(Algorithm algo, Uint8Buff *outPriKey, Uint8Buff *outPubKey); + +typedef int32_t (*ExportPublicKeyFunc)(const Uint8Buff *keyAlias, Uint8Buff *outPubKey); + +typedef int32_t (*SignFunc)(const Uint8Buff *keyAlias, const Uint8Buff *message, Algorithm algo, + Uint8Buff *outSignature, bool isAlias); + +typedef int32_t (*VerifyFunc)(const Uint8Buff *key, const Uint8Buff *message, Algorithm algo, + const Uint8Buff *signature, bool isAlias); + +typedef int32_t (*ImportPublicKeyFunc)(const Uint8Buff *keyAlias, const Uint8Buff *pubKey, Algorithm algo, + const ExtraInfo *exInfo); + +typedef bool (*CheckEcPublicKeyFunc)(const Uint8Buff *pubKey, Algorithm algo); + +typedef bool (*CheckDlPublicKeyFunc)(const Uint8Buff *key, const char *primeHex); + +typedef struct { + InitAlgFunc initAlg; + Sha256Func sha256; + GenerateRandomFunc generateRandom; + ComputeHmacFunc computeHmac; + ComputeHkdfFunc computeHkdf; + ImportAsymmetricKeyFunc importAsymmetricKey; + CheckKeyExistFunc checkKeyExist; + DeleteKeyFunc deleteKey; + AesGcmEncryptFunc aesGcmEncrypt; + AesGcmDecryptFunc aesGcmDecrypt; + HashToPointFunc hashToPoint; + AgreeSharedSecretWithStorageFunc agreeSharedSecretWithStorage; + AgreeSharedSecretFunc agreeSharedSecret; + BigNumExpModFunc bigNumExpMod; + GenerateKeyPairWithStorageFunc generateKeyPairWithStorage; + GenerateKeyPairFunc generateKeyPair; + ExportPublicKeyFunc exportPublicKey; + SignFunc sign; + VerifyFunc verify; + ImportPublicKeyFunc importPublicKey; + ComputePublicKeyFunc computePublicKey; + CheckDlPublicKeyFunc checkDlPublicKey; + CheckEcPublicKeyFunc checkEcPublicKey; +} AlgLoader; + +#endif \ No newline at end of file diff --git a/hals/inc/common/alg_loader.h b/hals/inc/common/alg_loader.h new file mode 100644 index 0000000..ad46a86 --- /dev/null +++ b/hals/inc/common/alg_loader.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ALG_LOADER_H +#define ALG_LOADER_H + +#include "alg_defs.h" + +const AlgLoader *GetLoaderInstance(); + +#endif \ No newline at end of file diff --git a/hals/inc/common/common_util.h b/hals/inc/common/common_util.h new file mode 100755 index 0000000..0cc0415 --- /dev/null +++ b/hals/inc/common/common_util.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef COMMON_UTIL_H +#define COMMON_UTIL_H + +#include + +#define BYTE_TO_HEX_OPER_LENGTH 2 +#define DEC 10 + +typedef struct { + uint8_t *val; + uint32_t length; +} Uint8Buff; + +/* + * Convert hex string to byte. + * @param hexStr: hex string + * @param byte: the converted result, need malloc by caller + * @param byteLen: the length of byte + * @result success(0), otherwise, failure. + */ +int32_t HexStringToByte(const char *hexStr, uint8_t *byte, uint32_t byteLen); + +/* + * Convert byte to hex string. + * @param byte: byte to be converted + * @param byteLen: the length of byte + * @param hexStr: the converted result, need malloc by caller, and need malloc for '\0' + * @param hexLen: strlen(hexStr) + 1, for '\0' + * @result success(0), otherwise, failure. + */ +int32_t ByteToHexString(const uint8_t *byte, uint32_t byteLen, char *hexStr, uint32_t hexLen); + + +/* + * Convert string to int64_t. + * @param cp: string to be converted + * @return the converted result. + */ +int64_t StringToInt64(const char *cp); + +#endif \ No newline at end of file diff --git a/hals/inc/common/hc_error.h b/hals/inc/common/hc_error.h new file mode 100755 index 0000000..2473491 --- /dev/null +++ b/hals/inc/common/hc_error.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HC_ERROR_H +#define HC_ERROR_H + +enum { + HAL_SUCCESS = 0, + HAL_FAILED = -1, + HAL_ERR_INVALID_PARAM = -2, + HAL_ERR_INVALID_LEN = -3, + HAL_ERR_BAD_ALLOC = -4, + HAL_ERR_NULL_PTR = -5, + HAL_ERR_MEMORY_COPY = -6, + + HAL_ERR_FILE_NOT_EXIST = -7, + HAL_ERR_FILE = -8, + + HAL_ERR_JSON_FAILED = -9, + HAL_ERR_JSON_GET = -10, + HAL_ERR_JSON_ADD = -11, + HAL_ERR_JSON_REPLACE = -12, + HAL_ERR_JSON_DUPLICATE = -13, + + HAL_ERR_INIT_PARAM_SET_FAILED = -14, + HAL_ERR_ADD_PARAM_FAILED = -15, + HAL_ERR_GET_PARAM_FAILED = -16, + HAL_ERR_BUILD_PARAM_SET_FAILED = -17, + HAL_ERR_FRESH_PARAM_SET_FAILED = -18, + HAL_ERR_INIT_FAILED = -19, +}; + +#endif diff --git a/hals/inc/common/hc_parcel.h b/hals/inc/common/hc_parcel.h new file mode 100755 index 0000000..1083223 --- /dev/null +++ b/hals/inc/common/hc_parcel.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HC_PARCEL_H +#define HC_PARCEL_H + +#include "hc_types.h" + +#define PARCEL_DEFAULT_LENGTH 0 +#define PARCEL_DEFAULT_ALLOC_UNIT 0 + +typedef struct { + char *data; + unsigned int beginPos; + unsigned int endPos; + unsigned int length; + unsigned int allocUnit; +} HcParcel; + +HcParcel CreateParcel(uint32_t size, uint32_t allocUnit); +void DeleteParcel(HcParcel *parcel); +void ClearParcel(HcParcel *parcel); +void ResetParcel(HcParcel *parcel, uint32_t size, uint32_t allocUnit); +HcBool ParcelReadWithoutPopData(HcParcel *parcel, void *dst, uint32_t dataSize); +HcBool ParcelRead(HcParcel *parcel, void *dst, uint32_t dataSize); +HcBool ParcelWrite(HcParcel *parcel, const void *src, uint32_t dataSize); +HcBool ParcelReadRevert(HcParcel *parcel, void *dst, uint32_t dataSize); +HcBool ParcelWriteRevert(HcParcel *parcel, const void *src, uint32_t dataSize); +uint32_t GetParcelDataSize(const HcParcel *parcel); +const char *GetParcelData(const HcParcel *parcel); +const char* GetParcelLastChar(const HcParcel *parcel); + +HcBool ParcelReadInt32(HcParcel *parcel, int *dst); +HcBool ParcelReadUint32(HcParcel *parcel, uint32_t *dst); +HcBool ParcelReadInt16(HcParcel *parcel, short *dst); +HcBool ParcelReadUint16(HcParcel *parcel, uint16_t *dst); +HcBool ParcelReadInt8(HcParcel *parcel, char *dst); +HcBool ParcelReadUint8(HcParcel *parcel, uint8_t *dst); +HcBool ParcelReadUint64(HcParcel *parcel, uint64_t *dst); +HcBool ParcelReadInt64(HcParcel *parcel, int64_t *dst); +HcBool ParcelWriteInt32(HcParcel *parcel, int src); +HcBool ParcelWriteUint32(HcParcel *parcel, uint32_t src); +HcBool ParcelWriteInt16(HcParcel *parcel, short src); +HcBool ParcelWriteUint16(HcParcel *parcel, uint16_t src); +HcBool ParcelWriteInt8(HcParcel *parcel, char src); +HcBool ParcelWriteUint8(HcParcel *parcel, uint8_t src); +HcBool ParcelWriteUint64(HcParcel *parcel, uint64_t src); +HcBool ParcelWriteInt64(HcParcel *parcel, int64_t src); +HcBool ParcelWriteString(HcParcel *parcel, const char *str); +HcBool ParcelReadString(HcParcel *parcel, char **str); +HcBool ParcelReadParcel(HcParcel *src, HcParcel *dst, uint32_t size, HcBool copy); +HcBool ParcelCopy(HcParcel *src, HcParcel *dst); + +HcBool ParcelReadInt32Revert(HcParcel *parcel, int32_t *dst); +HcBool ParcelReadUint32Revert(HcParcel *parcel, uint32_t *dst); +HcBool ParcelReadInt16Revert(HcParcel *parcel, short *dst); +HcBool ParcelReadUint16Revert(HcParcel *parcel, uint16_t *dst); +HcBool ParcelReadInt8Revert(HcParcel *parcel, char *dst); +HcBool ParcelReadUint8Revert(HcParcel *parcel, uint8_t *dst); +HcBool ParcelReadUint64Revert(HcParcel *parcel, uint64_t *dst); +HcBool ParcelReadInt64Revert(HcParcel *parcel, int64_t *dst); +HcBool ParcelWriteInt32Revert(HcParcel *parcel, int src); +HcBool ParcelWriteUint32Revert(HcParcel *parcel, uint32_t src); +HcBool ParcelWriteInt16Revert(HcParcel *parcel, short src); +HcBool ParcelWriteUint16Revert(HcParcel *parcel, uint16_t src); +HcBool ParcelWriteInt8Revert(HcParcel *parcel, char src); +HcBool ParcelWriteUint8Revert(HcParcel *parcel, uint8_t src); +HcBool ParcelWriteUint64Revert(HcParcel *parcel, uint64_t src); +HcBool ParcelWriteInt64Revert(HcParcel *parcel, int64_t src); + +void DataRevert(void *data, uint32_t length); +HcBool ParcelPopBack(HcParcel *parcel, uint32_t size); +HcBool ParcelPopFront(HcParcel *parcel, uint32_t size); +HcBool ParcelEraseBlock(HcParcel *parcel, uint32_t start, uint32_t data_size, void *dst); + +#endif diff --git a/hals/inc/common/hc_string.h b/hals/inc/common/hc_string.h new file mode 100755 index 0000000..17598ac --- /dev/null +++ b/hals/inc/common/hc_string.h @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HC_STRING_H +#define HC_STRING_H + +#include "hc_parcel.h" + +typedef struct HcString { + HcParcel parcel; // parcel data, used to storage the string data +} HcString; + +/* + * Append a HcString + * Notice: It will add '\0' automatically. + * @param self: self pointer. + * @param str: append string. + * @return HC_TRUE (ok), HC_FALSE (error) + */ +HcBool StringAppend(HcString *self, HcString str); + +/* + * Append string pointer + * Notice: It will add '\0' automatically. + * @param self: self pointer. + * @param str: string pointer. + * @return HC_TRUE (ok), HC_FALSE (error) + */ +HcBool StringAppendPointer(HcString *self, const char *str); + +/* + * Append a char + * Notice: It will add '\0' automatically. + * @param self: self pointer. + * @param str: char. + * @return HC_TRUE (ok), HC_FALSE (error) + */ +HcBool StringAppendChar(HcString *self, char c); + +/* + * Assign a value to the HcString + * Notice: It will add '\0' automatically. + * @param self: self pointer. + * @param str: assign value of ta_sting. + * @return HC_TRUE (ok), HC_FALSE (error) + */ +HcBool StringSet(HcString *self, HcString str); + +/* + * Assign a value to the HcString + * Notice: It will add '\0' automatically. + * @param self: self pointer. + * @param str: assign value of string pointer. + * @return HC_TRUE (ok), HC_FALSE (error) + */ +HcBool StringSetPointer(HcString *self, const char *str); + +/* + * Get the string pointer data + * @param self: self pointer. + * @return the pointer data of the string + */ +const char* StringGet(const HcString *self); + +/* + * Get the length of the string + * @param self: self pointer. + * @return the length of the string + */ +uint32_t StringLength(const HcString *self); + +/* + * Create a string. + * Notice: You should delete string when you don't need the string anymore. + * @return the created string. + */ +HcString CreateString(); + +/* + * Delete a string. In fact it will not destroy the string, + * but only free the allocated memory of the string and reset the member's value + * of the string. You can continue to use the string if you want. + * Notice: You should delete the string when you don't need it any more to avoid memory leak. + * @param str: The string you want to delete. + */ +void DeleteString(HcString *str); + +#endif diff --git a/hals/inc/common/hc_task_thread.h b/hals/inc/common/hc_task_thread.h new file mode 100644 index 0000000..5c80e09 --- /dev/null +++ b/hals/inc/common/hc_task_thread.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HC_TASK_THREAD_H +#define HC_TASK_THREAD_H + +#include "hc_thread.h" +#include "hc_vector.h" + +typedef struct HcTaskBaseT { + void (*doAction) (struct HcTaskBaseT*); + void (*destroy) (struct HcTaskBaseT*); +} HcTaskBase; + +typedef struct { + HcTaskBase* task; +} HcTaskWrap; + +DECLARE_HC_VECTOR(TaskVec, HcTaskWrap) + +typedef struct HcTaskThreadT { + HcThread thread; + TaskVec tasks; + int32_t (*startThread)(struct HcTaskThreadT* thread); + void (*pushTask) (struct HcTaskThreadT* thread, HcTaskBase* task); + void (*clear) (struct HcTaskThreadT* thread); + void (*stopAndClear) (struct HcTaskThreadT* thread); + HcMutex queueLock; + HcBool quit; +} HcTaskThread; + +int32_t InitHcTaskThread(HcTaskThread* thread, size_t stackSize, const char* threadName); +void DestroyHcTaskThread(HcTaskThread* thread); +#endif \ No newline at end of file diff --git a/hals/inc/common/hc_tlv_parser.h b/hals/inc/common/hc_tlv_parser.h new file mode 100755 index 0000000..0cdec87 --- /dev/null +++ b/hals/inc/common/hc_tlv_parser.h @@ -0,0 +1,313 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HC_TLV_PARSER_H +#define HC_TLV_PARSER_H + +#include +#include +#include + +#define USE_DEFAULT_TAG 0xFFFF +#define TLV_FAIL (-1) +#define NO_REVERT 0 +#define NEED_REVERT 1 +#define MAX_TOTOL_LEN (100 * 1024 * 1024) + +typedef struct TlvBaseT { + unsigned short tag; + unsigned short length; + unsigned short checkTag; + unsigned short hasValue; + int32_t (*parse)(struct TlvBaseT *, HcParcel *, HcBool); + int32_t (*getlen)(struct TlvBaseT *); + int32_t (*encode)(struct TlvBaseT *, HcParcel *); + void (*deinit)(struct TlvBaseT *); +} TlvBase; + +#define DECLARE_TLV_STRUCT(x) \ + TlvBase base; \ + unsigned int offsetCount; \ + unsigned int offset[x]; + +unsigned short GetTag(unsigned short checkTag, unsigned short defaultTag); + +#define BEGIN_TLV_STRUCT_DEFINE(TlvS, CheckTag) \ +void Init##TlvS(TlvS *tlv, unsigned short checkTag) \ +{ \ + typedef TlvS TlvStructType; \ + unsigned int index = 0; \ + (void)memset_s(&tlv->base, sizeof(tlv->base), 0, sizeof(tlv->base)); \ + tlv->base.checkTag = GetTag(checkTag, CheckTag); + +#define TLV_MEMBER_OPTION(TlvMember, TlvMemberName, CheckTag) \ + Init##TlvMember(&tlv->TlvMemberName, CheckTag); \ + tlv->TlvMemberName.base.option = 1; \ + tlv->offset[index++] = offsetof(TlvStructType, TlvMemberName); + +#define TLV_MEMBER(TlvMember, TlvMemberName, CheckTag) \ + Init##TlvMember(&tlv->TlvMemberName, CheckTag); \ + tlv->offset[index++] = offsetof(TlvStructType, TlvMemberName); + +#define END_TLV_STRUCT_DEFINE() \ + tlv->offsetCount = index; \ + tlv->base.parse = ParseTlvStruct; \ + tlv->base.getlen = GetLenTlvStruct; \ + tlv->base.encode = EncodeTlvStruct; \ + tlv->base.deinit = DeinitTlvStruct; \ +} + +#define DECLARE_TLV_FIX_LENGTH_TYPE(TlvName, TypeName) \ +typedef struct \ +{ \ + TlvBase base; \ + TypeName data; \ +} TlvName; + +DECLARE_TLV_FIX_LENGTH_TYPE(TlvInt32, int) +DECLARE_TLV_FIX_LENGTH_TYPE(TlvInt16, short) +DECLARE_TLV_FIX_LENGTH_TYPE(TlvInt8, char) +DECLARE_TLV_FIX_LENGTH_TYPE(TlvUint32, uint32_t) +DECLARE_TLV_FIX_LENGTH_TYPE(TlvUint16, uint16_t) +DECLARE_TLV_FIX_LENGTH_TYPE(TlvUint8, uint8_t) +DECLARE_TLV_FIX_LENGTH_TYPE(TlvUint64, uint64_t) +DECLARE_TLV_FIX_LENGTH_TYPE(TlvInt64, uint64_t) + +#define DEFINE_TLV_FIX_LENGTH_TYPE(TlvName, Revert) \ +int32_t ParseTlv##TlvName(TlvBase *tlv, HcParcel *parcel, HcBool strict) \ +{ \ + (void)strict; \ + TlvName *realTlv = (TlvName *)(tlv); \ + HcBool readRet = HC_FALSE; \ + if (tlv->length != sizeof(realTlv->data)) \ + { \ + return TLV_FAIL; \ + } \ +\ + if (Revert) \ + { \ + readRet = ParcelReadRevert(parcel, &realTlv->data, sizeof(realTlv->data)); \ + } else { \ + readRet = ParcelRead(parcel, &realTlv->data, sizeof(realTlv->data)); \ + } \ + if (readRet) \ + { \ + return tlv->length; \ + } else { \ + return TLV_FAIL; \ + } \ +} \ +\ +int32_t GetLenTlv##TlvName(TlvBase *tlv) \ +{ \ + TlvName *realTlv = (TlvName *)(tlv); \ + return (int32_t)sizeof(realTlv->data); \ +} \ +\ +int32_t EncodeTlv##TlvName(TlvBase *tlv, HcParcel *parcel) \ +{ \ + HcBool writeRet = HC_FALSE; \ + TlvName *realTlv = (TlvName *)(tlv); \ + if (Revert) \ + { \ + writeRet = ParcelWriteRevert(parcel, &realTlv->data, sizeof(realTlv->data)); \ + } else { \ + writeRet = ParcelWrite(parcel, &realTlv->data, sizeof(realTlv->data)); \ + } \ + if (writeRet) \ + { \ + return sizeof(realTlv->data); \ + } else { \ + return TLV_FAIL; \ + } \ +} \ +\ +DECLARE_TLV_PARSE_FUNC(TlvName, ParseTlv##TlvName, GetLenTlv##TlvName, EncodeTlv##TlvName); + +void DeinitTlvFixMember(TlvBase *tlv); + +#define DECLARE_TLV_PARSE_FUNC(TlvName, TlvParseFunc, TlvGetLenFunc, TlvEncodeFunc) \ +void Init##TlvName(TlvName *tlv, unsigned short checkTag) \ +{ \ + (void)memset_s(&tlv->base, sizeof(tlv->base), 0, sizeof(tlv->base)); \ + tlv->base.parse = TlvParseFunc; \ + tlv->base.getlen = TlvGetLenFunc; \ + tlv->base.encode = TlvEncodeFunc; \ + tlv->base.deinit = DeinitTlvFixMember; \ + tlv->base.checkTag = checkTag; \ +} + +#define TLV_INIT(TlvName, TlvData) Init##TlvName(TlvData, USE_DEFAULT_TAG); + +#define TLV_DEINIT(TlvData) TlvData.base.deinit((TlvBase *)(&TlvData)); +typedef struct { + TlvBase base; + unsigned int offsetCount; + unsigned int offset[0]; +} TlvOffsetExample; + +HcBool ParseTlvHead(TlvBase *tlv, HcParcel *parcel); +int32_t ParseTlvNode(TlvBase *tlv, HcParcel *parcel, HcBool strict); +int32_t GetlenTlvNode(TlvBase *tlv); +void DeinitTlvNode(TlvBase *tlv); + +int32_t ParseTlvStruct(TlvBase *tlv, HcParcel *parcel, HcBool strict); +int32_t EncodeTlvStruct(TlvBase *tlv, HcParcel *parcel); +int32_t GetLenTlvStruct(TlvBase *tlv); +void DeinitTlvStruct(TlvBase *tlv); +int32_t EncodeTlvNode(TlvBase *tlv, HcParcel *parcel, HcBool isRoot); +HcBool DecodeTlvMessage(TlvBase *msg, HcParcel *parcel, HcBool strict); +HcBool EncodeTlvMessage(TlvBase *msg, HcParcel *parcel); + +typedef struct { + TlvBase base; + HcParcel data; +} TlvBuffer; + +void InitTlvBuffer(TlvBuffer *tlv, unsigned short checkTag); +int32_t ParseTlvBuffer(TlvBase *tlv, HcParcel *parcel, HcBool strict); +int32_t GetlenTlvBuffer(TlvBase *tlv); +int32_t EncodeTlvBuffer(TlvBase *tlv, HcParcel *parcel); +void DeinitTlvBuffer(TlvBase *tlv); + +typedef struct { + TlvBase base; + HcString data; +} TlvString; + +void InitTlvString(TlvString *tlv, unsigned short checkTag); +int32_t ParseTlvString(TlvBase *tlv, HcParcel *parcel, HcBool strict); +int32_t GetlenTlvString(TlvBase *tlv); +int32_t EncodeTlvString(TlvBase *tlv, HcParcel *parcel); +void DeinitTlvString(TlvBase *tlv); + +#define DECLEAR_INIT_FUNC(TlvStruct) \ +void Init##TlvStruct(TlvStruct *tlv, unsigned short checkTag); + +DECLEAR_INIT_FUNC(TlvUint64) +DECLEAR_INIT_FUNC(TlvUint32) +DECLEAR_INIT_FUNC(TlvUint16) +DECLEAR_INIT_FUNC(TlvUint8) +DECLEAR_INIT_FUNC(TlvInt64) +DECLEAR_INIT_FUNC(TlvInt32) +DECLEAR_INIT_FUNC(TlvInt16) +DECLEAR_INIT_FUNC(TlvInt8) + +#define DECLARE_TLV_VECTOR(TlvVecName, TlvVecElement) \ +DECLARE_HC_VECTOR(Vec##TlvVecName, TlvVecElement) \ +typedef struct { \ + TlvBase base; \ + Vec##TlvVecName data; \ +} TlvVecName; \ +void DeinitTlv##TlvVecName(TlvBase *tlv); \ +void Init##TlvVecName(TlvVecName *tlv, unsigned short checkTag); + +#define IMPLEMENT_TLV_VECTOR(TlvVecName, TlvElementName, VecAllocCount) \ +IMPLEMENT_HC_VECTOR(Vec##TlvVecName, TlvElementName, VecAllocCount) \ +int32_t ParseTlv##TlvVecName(TlvBase *tlv, HcParcel *parcel, HcBool strict) \ +{ \ + TlvVecName *realTlv = (TlvVecName *)(tlv); \ + uint32_t count = 0; \ + if (!ParcelReadUint32(parcel, &count)) { \ + return TLV_FAIL; \ + } \ + int32_t totalLen = sizeof(count); \ + uint32_t index = 0; \ + for (index = 0; index < count; ++index) { \ + TlvElementName tlvElement; \ + TlvElementName *curElement = realTlv->data.pushBack(&realTlv->data, &tlvElement); \ + if (curElement == NULL) { \ + return TLV_FAIL; \ + } \ + TLV_INIT(TlvElementName, curElement); \ +\ + int32_t elementLen = ParseTlvNode((TlvBase *)curElement, parcel, strict); \ + if (elementLen < 0) { \ + return TLV_FAIL; \ + } \ + totalLen += elementLen; \ + if (totalLen >= MAX_TOTOL_LEN) { \ + return TLV_FAIL; \ + } \ + } \ +\ + return totalLen; \ +} \ +\ +int32_t EncodeTlv##TlvVecName(TlvBase *tlv, HcParcel *parcel) \ +{ \ + TlvVecName *realTlv = (TlvVecName *)(tlv); \ + uint32_t index = 0; \ + TlvElementName *element = NULL; \ + uint32_t totalLen = 4; \ + uint32_t count = realTlv->data.size(&realTlv->data); \ + if (!ParcelWriteUint32(parcel, count)) { \ + return TLV_FAIL; \ + } \ +\ + FOR_EACH_HC_VECTOR(realTlv->data, index, element) { \ + if (element != NULL) { \ + uint32_t len = EncodeTlvNode((TlvBase *)element, parcel, HC_FALSE); \ + totalLen += len; \ + if (totalLen >= MAX_TOTOL_LEN) { \ + return TLV_FAIL; \ + } \ + } \ + } \ + return totalLen; \ +} \ +int32_t GetLenTlv##TlvVecName(TlvBase *tlv) \ +{ \ + TlvVecName *realTlv = (TlvVecName *)(tlv); \ + uint32_t index = 0; \ + TlvElementName *element = NULL; \ + uint32_t totalLen = sizeof(uint32_t); \ + FOR_EACH_HC_VECTOR(realTlv->data, index, element) { \ + if (element != NULL) { \ + totalLen += GetlenTlvNode((TlvBase *)element); \ + if (totalLen >= MAX_TOTOL_LEN) { \ + return TLV_FAIL; \ + } \ + } else { \ + return TLV_FAIL; \ + } \ + } \ + return totalLen; \ +} \ +\ +void DeinitTlv##TlvVecName(TlvBase *tlv) \ +{ \ + TlvVecName *realTlv = (TlvVecName *)(tlv); \ + uint32_t index = 0; \ + TlvElementName *element = NULL; \ + FOR_EACH_HC_VECTOR(realTlv->data, index, element) { \ + if (element != NULL) { \ + TLV_DEINIT((*element)); \ + } \ + } \ + DESTROY_HC_VECTOR(Vec##TlvVecName, &((TlvVecName *)tlv)->data); \ +} \ +\ +void Init##TlvVecName(TlvVecName *tlv, unsigned short checkTag) \ +{ \ + (void)memset_s(&tlv->base, sizeof(tlv->base), 0, sizeof(tlv->base)); \ + tlv->base.parse = ParseTlv##TlvVecName; \ + tlv->base.encode = EncodeTlv##TlvVecName; \ + tlv->base.getlen = GetLenTlv##TlvVecName; \ + tlv->base.deinit = DeinitTlv##TlvVecName; \ + tlv->base.checkTag = checkTag; \ + tlv->data = CREATE_HC_VECTOR(Vec##TlvVecName); \ +} +#endif diff --git a/hals/inc/common/hc_vector.h b/hals/inc/common/hc_vector.h new file mode 100755 index 0000000..5e9853a --- /dev/null +++ b/hals/inc/common/hc_vector.h @@ -0,0 +1,172 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HC_VECTOR_H +#define HC_VECTOR_H + +#include "hc_parcel.h" +#include "securec.h" + +/* + * Use DECLARE_HC_VECTOR to declare the vector in the head/src file. + * @para ClassName: the name of the vector-class/vector-struct + * @para Element: the type of the vector element + * @for example: + * DECLARE_HC_VECTOR(IntVec, int) + */ +#define DECLARE_HC_VECTOR(ClassName, Element) \ +typedef struct V##ClassName{ \ + Element* (*pushBack)(struct V##ClassName*, const Element*); \ + Element* (*pushBackT)(struct V##ClassName*, Element); \ + HcBool (*popFront)(struct V##ClassName*, Element*); \ + HcBool (*eraseElement)(struct V##ClassName*, Element*, uint32_t index); \ + uint32_t (*size)(const struct V##ClassName*); \ + Element (*get)(const struct V##ClassName*, uint32_t index); \ + Element* (*getp)(const struct V##ClassName*, uint32_t index); \ + void (*clear)(struct V##ClassName*); \ + HcParcel parcel; \ +} ClassName; + +/* + * Use IMPLEMENT_HC_VECTOR to implement the vector in the source file. + * @para ClassName: the name of the vector-class/vector-struct + * @para Element: the type of the vector element + * @para allocCount: the minimum alloc count + * @for example: + * IMPLEMENT_HC_VECTOR(IntVec, int) + */ +#define IMPLEMENT_HC_VECTOR(ClassName, Element, allocCount) \ +Element* VPushBack##ClassName(ClassName* obj, const Element *e) { \ + if (obj == NULL || e == NULL) { \ + return NULL; \ + } \ + \ + if (ParcelWrite(&obj->parcel, e, sizeof(Element))) { \ + int size = obj->size(obj); \ + return obj->getp(obj, size-1); \ + } else { \ + return NULL; \ + } \ +} \ +Element* VPushBackT##ClassName(ClassName* obj, Element e) { \ + if (obj == NULL) { \ + return NULL; \ + } \ + \ + if (ParcelWrite(&obj->parcel, &e, sizeof(Element))) { \ + int size = obj->size(obj); \ + return obj->getp(obj, size-1); \ + } else { \ + return NULL; \ + } \ +} \ +HcBool VPopFront##ClassName(ClassName* obj, Element* e) { \ + if (NULL == obj || NULL == e) { \ + return HC_FALSE; \ + } \ + if (obj->size(obj) > 0) { \ + return ParcelRead(&obj->parcel, e, sizeof(Element)); \ + } else { \ + return HC_FALSE; \ + } \ +} \ +HcBool VErase##ClassName(ClassName* obj, Element* e, uint32_t index) { \ + if (NULL == obj || NULL == e || index + 1 > obj->size(obj)) { \ + return HC_FALSE; \ + } \ + if (obj->size(obj) > 0) { \ + return ParcelEraseBlock(&obj->parcel, index*sizeof(Element), sizeof(Element), e); \ + } else { \ + return HC_FALSE; \ + } \ +} \ +uint32_t VSize##ClassName(const ClassName* obj) \ +{ \ + if (NULL == obj) { \ + return 0; \ + } \ + return GetParcelDataSize(&obj->parcel) / sizeof(Element); \ +} \ +Element VGet##ClassName(const ClassName* obj, uint32_t index) \ +{ \ + Element e; \ + (void)memset_s(&e, sizeof(e), 0, sizeof(e)); \ + if (NULL != obj) { \ + if (index < obj->size(obj)) { \ + if (GetParcelData(&obj->parcel)) { \ + return *((Element*)(GetParcelData(&obj->parcel)) + index); \ + } else { \ + return e; \ + } \ + } \ + } \ + (void)memset_s(&e, sizeof(e), 0, sizeof(e)); \ + return e; \ +} \ +Element* VGetPointer##ClassName(const ClassName* obj, uint32_t index) \ +{ \ + if (NULL != obj) { \ + if (index < obj->size(obj)) { \ + if (GetParcelData(&obj->parcel)) { \ + return ((Element*)(GetParcelData(&obj->parcel)) + index); \ + } else { \ + return NULL; \ + } \ + } \ + } \ + return NULL; \ +} \ +void VClear##ClassName(ClassName* obj) \ +{ \ + if (NULL != obj) { \ + ClearParcel(&obj->parcel); \ + } \ +} \ +ClassName Create##ClassName() \ +{ \ + ClassName obj; \ + obj.pushBack = VPushBack##ClassName; \ + obj.pushBackT = VPushBackT##ClassName; \ + obj.popFront = VPopFront##ClassName; \ + obj.clear = VClear##ClassName; \ + obj.eraseElement = VErase##ClassName; \ + obj.size = VSize##ClassName; \ + obj.get = VGet##ClassName; \ + obj.getp = VGetPointer##ClassName; \ + obj.parcel = CreateParcel(0, sizeof(Element) * allocCount); \ + return obj; \ +} \ +void Destroy##ClassName(ClassName* obj) \ +{ \ + if (NULL != obj) { \ + DeleteParcel(&obj->parcel); \ + } \ +} + +/* Use these two macros to create and destroy vector */ +#define CREATE_HC_VECTOR(classname) Create##classname(); +#define DESTROY_HC_VECTOR(classname, obj) Destroy##classname(obj); + +#define FOR_EACH_HC_VECTOR(vec, index, iter) for (index = 0; index < (vec).size(&(vec)) && \ + (iter = (vec).getp(&(vec), index)); ++index) + +#define HC_VECTOR_PUSHBACK(obj, element) (obj)->pushBack((obj), (element)) +#define HC_VECTOR_POPFRONT(obj, element) (obj)->popFront((obj), (element)) +#define HC_VECTOR_POPELEMENT(obj, element, index) (obj)->eraseElement((obj), (element), (index)) +#define HC_VECTOR_SIZE(obj) (obj)->size(obj) +#define HC_VECTOR_GET(obj, index) (obj)->get((obj), (index)) +#define HC_VECTOR_GETP(_obj, _index) (_obj)->getp((_obj), (_index)) + +#endif diff --git a/hals/inc/common/huks_adapter.h b/hals/inc/common/huks_adapter.h new file mode 100644 index 0000000..5d3d839 --- /dev/null +++ b/hals/inc/common/huks_adapter.h @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HUKS_ADAPTER_H +#define HUKS_ADAPTER_H + +#include "alg_defs.h" +#include "hc_error.h" +#include "hc_types.h" + +#define BITS_PER_BYTE 8 + +#define CAL_ARRAY_SIZE(arr) ((sizeof(arr)) / (sizeof((arr)[0]))) + +#define CHECK_LEN_ZERO_RETURN_ERROR_CODE(len, paramTag) \ + do { \ + if ((len) == 0) { \ + LOGE("%s is invalid length", (paramTag)); \ + return HAL_ERR_INVALID_LEN; \ + } \ + } while (0) + +#define CHECK_PTR_RETURN_ERROR_CODE(ptr, paramTag) \ + do { \ + if ((ptr) == NULL) { \ + LOGE("%s is null ptr", (paramTag)); \ + return HAL_ERR_NULL_PTR; \ + } \ + } while (0) + +#define CHECK_LEN_LOWER_RETURN(len, min, paramTag) \ + do { \ + if ((len) < (min)) { \ + LOGE("%s is invalid length.", (paramTag)); \ + return HAL_ERR_INVALID_LEN; \ + } \ + } while (0) + +#define CHECK_LEN_HIGHER_RETURN(len, max, paramTag) \ + do { \ + if ((len) > (max)) { \ + LOGE("%s is invalid length.", (paramTag)); \ + return HAL_ERR_INVALID_LEN; \ + } \ + } while (0) + +#define CHECK_LEN_EQUAL_RETURN(len, value, paramTag) \ + do { \ + if ((len) != (value)) { \ + LOGE("%s is invalid length.", (paramTag)); \ + return HAL_ERR_INVALID_LEN; \ + } \ + } while (0) + +struct KeyRoleInfo { + uint8_t userType; + uint8_t pairType; + uint8_t reserved1; + uint8_t reserved2; +}; + +union KeyRoleInfoUnion { + struct KeyRoleInfo roleInfoStruct; + uint32_t roleInfo; +}; + +const AlgLoader *GetRealLoaderInstance(); + +#endif diff --git a/hals/inc/common/json_utils.h b/hals/inc/common/json_utils.h new file mode 100644 index 0000000..8981a03 --- /dev/null +++ b/hals/inc/common/json_utils.h @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef JSON_UTILS_H +#define JSON_UTILS_H + +#include +#include +#include +#include +#include "cJSON.h" + +typedef cJSON CJson; + +/* Need to call FreeJson to free the returned pointer when it's no longer in use. */ +CJson *CreateJsonFromString(const char *jsonStr); +/* Need to call FreeJson to free the returned pointer when it's no longer in use. */ +CJson *CreateJson(); +/* Need to call FreeJson to free the returned pointer when it's no longer in use. */ +CJson *CreateJsonArray(); +/* Need to call FreeJson to free the returned pointer when it's no longer in use. */ +CJson *DuplicateJson(const CJson *jsonObj); +void FreeJson(CJson *jsonObj); + +void DeleteItemFromJson(CJson *jsonObj, const char *key); +void DeleteAllItemExceptOne(CJson *jsonObj, const char *key); +void DeleteAllItem(CJson *jsonObj); +CJson *DetachItemFromJson(CJson *jsonObj, const char *key); + +/* Need to call FreeJsonString to free the returned pointer when it's no longer in use. */ +char *PackJsonToString(const CJson *jsonObj); +void FreeJsonString(char *jsonStr); + +int GetItemNum(const CJson *jsonObj); +/* + * Can't release the returned pointer, otherwise, an exception may occur. + * It refers to the parent object(param--jsonObj)'s memory. + * It will be recycled along with jsonObj when jsonObj is released. + */ +const char *GetItemKey(const CJson *item); + +/* + * Can't release the returned pointer, otherwise, an exception may occur. + * It refers to the parent object(param--jsonObj)'s memory. + * It will be recycled along with jsonObj when jsonObj is released. + */ +CJson *GetObjFromJson(const CJson *jsonObj, const char *key); + +/* + * Can't release the returned pointer, otherwise, an exception may occur. + * It refers to the parent object(param--jsonObj)'s memory. + * It will be recycled along with jsonObj when jsonObj is released. + */ +CJson *GetItemFromArray(const CJson *jsonArr, int index); + +/* + * Can't release the returned pointer, otherwise, an exception may occur. + * It refers to the parent object(param--jsonObj)'s memory. + * It will be recycled along with jsonObj when jsonObj is released. + */ +const char *GetStringFromJson(const CJson *jsonObj, const char *key); + +/* + * The byte in jsonObj must be in the form of hex string. + * This function will convert the hex string to byte, and then put it in param--byte in the form of byte. + */ +int32_t GetByteFromJson(const CJson *jsonObj, const char *key, uint8_t *byte, uint32_t len); +int32_t GetIntFromJson(const CJson *jsonObj, const char *key, int *value); +int32_t GetInt64FromJson(const CJson *jsonObj, const char *key, int64_t *value); +int32_t GetBoolFromJson(const CJson *jsonObj, const char *key, bool *value); +char *GetStringValue(const CJson *item); + +int32_t AddObjToJson(CJson *jsonObj, const char *key, const CJson *childObj); +int32_t AddObjToArray(CJson *jsonArr, CJson *item); +int32_t AddStringToJson(CJson *jsonObj, const char *key, const char *value); +int32_t AddStringToArray(CJson *jsonArr, const char *string); +/* The function will convert the byte to hex string, and then add it to object. */ +int32_t AddByteToJson(CJson *jsonObj, const char *key, const uint8_t *byte, uint32_t len); +int32_t AddBoolToJson(CJson *jsonObj, const char *key, bool value); +int32_t AddIntToJson(CJson *jsonObj, const char *key, int value); +int32_t AddInt64StringToJson(CJson *jsonObj, const char *key, int64_t value); +int32_t AddStringArrayToJson(CJson *jsonObj, const char *key, const char * const *stringArray, uint32_t arrayLen); +void ClearSensitiveStringInJson(CJson *jsonObj, const char *key); +void ClearAndFreeJsonString(char *jsonStr); + +#endif diff --git a/hals/inc/dev_info/3516/hc_dev_info.h b/hals/inc/dev_info/3516/hc_dev_info.h new file mode 100644 index 0000000..41ad226 --- /dev/null +++ b/hals/inc/dev_info/3516/hc_dev_info.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HC_DEV_INFO_H +#define HC_DEV_INFO_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define INPUT_UDID_LEN 65 +#define MAX_INPUT_UDID_LEN 200 +#define MAX_SESSION_COUNT 30 + +/* + * Get the unique device ID of the device(UDID). + * udid: It is used to store the UDID finally obtained. + * udidLen: The size of array to store UDID. Its value is the real udid size + 1 (including '\0'). + * In liteos and linux, the udidLen must be 65. + * Return 0 if the UDID is successfully obtained, other returns an error code. + */ +int32_t HcGetUdid(uint8_t *udid, int32_t udidLen); + +const char *GetStoragePath(); + +#ifdef __cplusplus +} +#endif +#endif \ No newline at end of file diff --git a/hals/inc/dev_info/watch/hc_dev_info.h b/hals/inc/dev_info/watch/hc_dev_info.h new file mode 100644 index 0000000..ebe073e --- /dev/null +++ b/hals/inc/dev_info/watch/hc_dev_info.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HC_DEV_INFO_H +#define HC_DEV_INFO_H + +#include + +#define INPUT_UDID_LEN 65 +#define MAX_INPUT_UDID_LEN 200 +#define MAX_SESSION_COUNT 20 + +/* + * Get the unique device ID of the device(UDID). + * udid: It is used to store the UDID finally obtained. + * udidLen: The size of array to store UDID. Its value is the real udid size + 1 (including '\0'). + * In liteos and linux, the udidLen must be 65. + * Return 0 if the UDID is successfully obtained, other returns an error code. + */ +int32_t HcGetUdid(uint8_t *udid, int32_t udidLen); + +const char *GetStoragePath(); + +#endif \ No newline at end of file diff --git a/hals/inc/linux/crypto_hash_to_point.h b/hals/inc/linux/crypto_hash_to_point.h new file mode 100644 index 0000000..fe36cc0 --- /dev/null +++ b/hals/inc/linux/crypto_hash_to_point.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef CRYPTO_HASH_TO_POINT_H +#define CRYPTO_HASH_TO_POINT_H + +#include +#include "hks_type.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int32_t OpensslHashToPoint(const struct HksBlob *hash, struct HksBlob *point); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/hals/inc/linux/hc_condition.h b/hals/inc/linux/hc_condition.h new file mode 100755 index 0000000..d04aec7 --- /dev/null +++ b/hals/inc/linux/hc_condition.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HC_CONDITION_H +#define HC_CONDITION_H + +#include "hc_mutex.h" +#include "hc_types.h" +#include "pthread.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct HcConditionT { + HcBool notified; + HcBool innerMutex; + HcBool waited; + HcMutex* mutex; + int (*wait)(struct HcConditionT*); + void (*notify)(struct HcConditionT*); + int (*waitWithoutLock)(struct HcConditionT*); + void (*notifyWithoutLock)(struct HcConditionT*); + pthread_cond_t cond; +} HcCondition; + +int32_t InitHcCond(HcCondition* hcCond, HcMutex* mutex); +void DestroyHcCond(HcCondition* hcCond); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/hals/inc/linux/hc_file.h b/hals/inc/linux/hc_file.h new file mode 100644 index 0000000..78f7620 --- /dev/null +++ b/hals/inc/linux/hc_file.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HC_FILE_H +#define HC_FILE_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef union { + void *pfd; + int fd; +} FileHandle; + +typedef enum FileIdEnumT { + FILE_ID_GROUP = 0, + FILE_ID_LAST, +} FileIdEnum; + +#define MODE_FILE_READ 0 +#define MODE_FILE_WRITE 1 + +// 0 indicates success +// -1 indicates fail +int HcFileOpen(int fileId, int mode, FileHandle *file); +int HcFileSize(FileHandle file); +int HcFileRead(FileHandle file, void *dst, int dstSize); +int HcFileWrite(FileHandle file, const void *src, int srcSize); +void HcFileClose(FileHandle file); +void HcFileRemove(int fileId); +void SetFilePath(FileIdEnum fileId, const char *path); + +#ifdef __cplusplus +} +#endif +#endif \ No newline at end of file diff --git a/hals/inc/linux/hc_init_protection.h b/hals/inc/linux/hc_init_protection.h new file mode 100644 index 0000000..60d481f --- /dev/null +++ b/hals/inc/linux/hc_init_protection.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HC_INIT_PROTECTION_H +#define HC_INIT_PROTECTION_H + +#include + +typedef enum InitStatusEnum { + CONTINUE_INIT = 0, + FINISH_INIT, + CONTINUE_DESTROY, + FINISH_DESTROY, +} InitStatus; + +int CheckInit(); +int CheckDestroy(); +void SetInitStatus(); +void SetDeInitStatus(); + +#endif \ No newline at end of file diff --git a/hals/inc/linux/hc_log.h b/hals/inc/linux/hc_log.h new file mode 100644 index 0000000..b6f885d --- /dev/null +++ b/hals/inc/linux/hc_log.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HC_LOG_H +#define HC_LOG_H + +#ifdef HILOG_ENABLE + +#include "hilog/log.h" + +#define LOGD(fmt, ...) \ + ((void)HiLogPrint(LOG_CORE, LOG_DEBUG, LOG_DOMAIN, "[DEVAUTH]", "%s: " fmt, __FUNCTION__, ##__VA_ARGS__)) +#define LOGE(fmt, ...) \ + ((void)HiLogPrint(LOG_CORE, LOG_ERROR, LOG_DOMAIN, "[DEVAUTH]", "%s: " fmt, __FUNCTION__, ##__VA_ARGS__)) +#define LOGI(fmt, ...) \ + ((void)HiLogPrint(LOG_CORE, LOG_INFO, LOG_DOMAIN, "[DEVAUTH]", "%s: " fmt, __FUNCTION__, ##__VA_ARGS__)) +#define LOGW(fmt, ...) \ + ((void)HiLogPrint(LOG_CORE, LOG_WARN, LOG_DOMAIN, "[DEVAUTH]", "%s: " fmt, __FUNCTION__, ##__VA_ARGS__)) + +#else + +#include +#include + +#define LOGD(fmt, ...) printf("[D][%s]" fmt "\n", __FUNCTION__, ##__VA_ARGS__) +#define LOGE(fmt, ...) printf("[E][%s]" fmt "\n", __FUNCTION__, ##__VA_ARGS__) +#define LOGI(fmt, ...) printf("[I][%s]" fmt "\n", __FUNCTION__, ##__VA_ARGS__) +#define LOGW(fmt, ...) printf("[W][%s]" fmt "\n", __FUNCTION__, ##__VA_ARGS__) +#endif + +#endif diff --git a/hals/inc/linux/hc_mutex.h b/hals/inc/linux/hc_mutex.h new file mode 100755 index 0000000..e4b905f --- /dev/null +++ b/hals/inc/linux/hc_mutex.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HC_MUTEX_H +#define HC_MUTEX_H + +#include "pthread.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct HcMutexT { + int (*lock)(struct HcMutexT* mutex); + void (*unlock)(struct HcMutexT* mutex); + pthread_mutex_t mutex; +} HcMutex; + +int32_t InitHcMutex(HcMutex* mutex); +void DestroyHcMutex(HcMutex* mutex); + +#ifdef __cplusplus +} +#endif +#endif \ No newline at end of file diff --git a/hals/inc/linux/hc_thread.h b/hals/inc/linux/hc_thread.h new file mode 100755 index 0000000..4778f6d --- /dev/null +++ b/hals/inc/linux/hc_thread.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HC_THREAD_H +#define HC_THREAD_H + +#include "pthread.h" +#include "hc_types.h" +#include "hc_string.h" +#include "hc_condition.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef int (*ThreadFunc)(void*); + +typedef struct HcThreadT { + ThreadFunc threadFunc; + int (*start)(struct HcThreadT* thread); + void(*join)(struct HcThreadT* thread); + void (*wait)(struct HcThreadT* thread); + void (*notify)(struct HcThreadT* thread); + pthread_t thread; + size_t stackSize; + HcBool running; + HcString name; + HcCondition threadWaitObj; + HcMutex threadLock; + HcCondition bizWaitObj; +} HcThread; + +int32_t InitThread(HcThread* thread, ThreadFunc func, size_t stackSize, const char* threadName); +void DestroyThread(HcThread* thread); + +#ifdef __cplusplus +} +#endif +#endif \ No newline at end of file diff --git a/hals/inc/linux/hc_time.h b/hals/inc/linux/hc_time.h new file mode 100644 index 0000000..adb0aa6 --- /dev/null +++ b/hals/inc/linux/hc_time.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HC_TIME_H +#define HC_TIME_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Calculate in seconds */ +#define TIME_OUT_VALUE 600 + +/* Return in seconds */ +int64_t HcGetCurTime(); + +/* Return the interval seconds from startTime to current Time */ +int64_t HcGetIntervalTime(int64_t startTime); + +#ifdef __cplusplus +} +#endif +#endif \ No newline at end of file diff --git a/hals/inc/linux/hc_types.h b/hals/inc/linux/hc_types.h new file mode 100755 index 0000000..b73be19 --- /dev/null +++ b/hals/inc/linux/hc_types.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HC_TYPES_H +#define HC_TYPES_H + +#include +#include +#include +#include +#include "securec.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef uint32_t HcBool; +#define HC_TRUE 1 +#define HC_FALSE 0 + +#ifndef NULL +#define NULL 0 +#endif + +void* HcMalloc(uint32_t size, char val); +void HcFree(void* addr); +void ReportMalloc(); +uint32_t HcStrlen(const char *str); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/hals/inc/liteos/hc_condition.h b/hals/inc/liteos/hc_condition.h new file mode 100755 index 0000000..09e13c7 --- /dev/null +++ b/hals/inc/liteos/hc_condition.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HC_CONDITION_H +#define HC_CONDITION_H + +#include "hc_mutex.h" +#include "hc_types.h" +#include + +typedef struct HcConditionT { + int (*wait)(struct HcConditionT*); + void (*notify)(struct HcConditionT*); + int (*waitWithoutLock)(struct HcConditionT*); + void (*notifyWithoutLock)(struct HcConditionT*); + sem_t sem; +} HcCondition; + +int32_t InitHcCond(HcCondition* hcCond, HcMutex* mutex); +void DestroyHcCond(HcCondition* hcCond); + +#endif diff --git a/hals/inc/liteos/hc_file.h b/hals/inc/liteos/hc_file.h new file mode 100755 index 0000000..b982eaa --- /dev/null +++ b/hals/inc/liteos/hc_file.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HC_FILE_H +#define HC_FILE_H + +typedef union { + void* pfd; + int fd; +} FileHandle; + +typedef enum FileIdEnumT { + FILE_ID_GROUP = 0, + FILE_ID_LAST, +} FileIdEnum; + +#define MODE_FILE_READ 0 +#define MODE_FILE_WRITE 1 + +/* 0 indicates success, -1 indicates fail */ +int HcFileOpen(int fileId, int mode, FileHandle* file); +int HcFileSize(FileHandle file); +int HcFileRead(FileHandle file, void* dst, int dstSize); +int HcFileWrite(FileHandle file, const void* src, int srcSize); +void HcFileClose(FileHandle file); +void HcFileRemove(int fileId); +void SetFilePath(FileIdEnum fileId, const char *path); + +#endif \ No newline at end of file diff --git a/hals/inc/liteos/hc_init_protection.h b/hals/inc/liteos/hc_init_protection.h new file mode 100644 index 0000000..60d481f --- /dev/null +++ b/hals/inc/liteos/hc_init_protection.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HC_INIT_PROTECTION_H +#define HC_INIT_PROTECTION_H + +#include + +typedef enum InitStatusEnum { + CONTINUE_INIT = 0, + FINISH_INIT, + CONTINUE_DESTROY, + FINISH_DESTROY, +} InitStatus; + +int CheckInit(); +int CheckDestroy(); +void SetInitStatus(); +void SetDeInitStatus(); + +#endif \ No newline at end of file diff --git a/hals/inc/liteos/hc_log.h b/hals/inc/liteos/hc_log.h new file mode 100755 index 0000000..dd6dbfb --- /dev/null +++ b/hals/inc/liteos/hc_log.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HC_LOG_H +#define HC_LOG_H + +#include "log.h" + +#define LOGD(fmt, arg...) HILOG_DEBUG(HILOG_MODULE_SCY, fmt, ##arg) +#define LOGI(fmt, arg...) HILOG_INFO(HILOG_MODULE_SCY, fmt, ##arg) +#define LOGE(fmt, arg...) HILOG_ERROR(HILOG_MODULE_SCY, fmt, ##arg) + +#endif diff --git a/hals/inc/liteos/hc_mutex.h b/hals/inc/liteos/hc_mutex.h new file mode 100755 index 0000000..8859dd6 --- /dev/null +++ b/hals/inc/liteos/hc_mutex.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HC_MUTEX_H +#define HC_MUTEX_H + +#include "pthread.h" +#include + +typedef struct HcMutexT { + int (*lock)(struct HcMutexT* mutex); + void (*unlock)(struct HcMutexT* mutex); + pthread_mutex_t mutex; +} HcMutex; + +int32_t InitHcMutex(HcMutex* mutex); +void DestroyHcMutex(HcMutex* mutex); + +#endif \ No newline at end of file diff --git a/hals/inc/liteos/hc_thread.h b/hals/inc/liteos/hc_thread.h new file mode 100755 index 0000000..f786c7f --- /dev/null +++ b/hals/inc/liteos/hc_thread.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HC_THREAD_H +#define HC_THREAD_H + +#include "pthread.h" +#include "hc_types.h" +#include "hc_string.h" +#include "hc_condition.h" + +typedef int (*ThreadFunc)(void*); + +typedef struct HcThreadT { + ThreadFunc threadFunc; + int (*start)(struct HcThreadT* thread); + void(*join)(struct HcThreadT* thread); + void (*wait)(struct HcThreadT* thread); + void (*notify)(struct HcThreadT* thread); + pthread_t thread; + size_t stackSize; + HcBool running; + HcString name; + HcCondition threadWaitObj; + HcMutex threadLock; + HcCondition bizWaitObj; +} HcThread; + +int32_t InitThread(HcThread* thread, ThreadFunc func, size_t stackSize, const char* threadName); +void DestroyThread(HcThread* thread); + +#endif \ No newline at end of file diff --git a/hals/inc/liteos/hc_time.h b/hals/inc/liteos/hc_time.h new file mode 100755 index 0000000..5acc2e1 --- /dev/null +++ b/hals/inc/liteos/hc_time.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HC_TIME_H +#define HC_TIME_H + +#include + + /* Calculate in seconds */ +#define TIME_OUT_VALUE 600 + +/* Return in seconds */ +int64_t HcGetCurTime(); + +/* Return the interval seconds from startTime to current Time */ +int64_t HcGetIntervalTime(int64_t startTime); + +#endif \ No newline at end of file diff --git a/hals/inc/liteos/hc_types.h b/hals/inc/liteos/hc_types.h new file mode 100755 index 0000000..8c7b46d --- /dev/null +++ b/hals/inc/liteos/hc_types.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HC_TYPES_H +#define HC_TYPES_H + +#include +#include +#include +#include +#include + +typedef uint32_t HcBool; +#define HC_TRUE 1 +#define HC_FALSE 0 + +#ifndef NULL +#define NULL 0 +#endif + +void *HcMalloc(uint32_t size, char val); +void HcFree(void* addr); +uint32_t HcStrlen(const char *str); + +#endif diff --git a/hals/src/common/alg_loader.c b/hals/src/common/alg_loader.c new file mode 100644 index 0000000..b7f761f --- /dev/null +++ b/hals/src/common/alg_loader.c @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "alg_loader.h" +#include "huks_adapter.h" + +const AlgLoader *GetLoaderInstance() +{ + return GetRealLoaderInstance(); +} diff --git a/hals/src/common/common_util.c b/hals/src/common/common_util.c new file mode 100755 index 0000000..6e726fa --- /dev/null +++ b/hals/src/common/common_util.c @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "common_util.h" +#include +#include +#include "hc_error.h" +#include "hc_log.h" + +#define OUT_OF_HEX 16 +#define NUMBER_9_IN_DECIMAL 9 + +static char HexToChar(uint8_t hex) +{ + return (hex > NUMBER_9_IN_DECIMAL) ? (hex + 0x37) : (hex + 0x30); /* Convert to the corresponding character */ +} + +int32_t ByteToHexString(const uint8_t *byte, uint32_t byteLen, char *hexStr, uint32_t hexLen) +{ + if (byte == NULL || hexStr == NULL) { + LOGE("Param is null ptr."); + return HAL_ERR_NULL_PTR; + } + /* The terminator('\0') needs 1 bit */ + if (hexLen < byteLen * BYTE_TO_HEX_OPER_LENGTH + 1) { + LOGE("Invalid length"); + return HAL_ERR_INVALID_LEN; + } + + for (uint32_t i = 0; i < byteLen; i++) { + hexStr[i * BYTE_TO_HEX_OPER_LENGTH] = HexToChar((byte[i] & 0xF0) >> 4); /* 4: shift right for filling */ + hexStr[i * BYTE_TO_HEX_OPER_LENGTH + 1] = HexToChar(byte[i] & 0x0F); /* get low four bits */ + } + hexStr[byteLen * BYTE_TO_HEX_OPER_LENGTH] = '\0'; + + return HAL_SUCCESS; +} + +static uint8_t CharToHex(char c) +{ + if ((c >= 'A') && (c <= 'F')) { + return (c - 'A' + DEC); + } else if ((c >= 'a') && (c <= 'f')) { + return (c - 'a' + DEC); + } else if ((c >= '0') && (c <= '9')) { + return (c - '0'); + } else { + return OUT_OF_HEX; + } +} + +int32_t HexStringToByte(const char *hexStr, uint8_t *byte, uint32_t byteLen) +{ + if (byte == NULL || hexStr == NULL) { + LOGE("Param is null ptr."); + return HAL_ERR_NULL_PTR; + } + uint32_t realHexLen = strlen(hexStr); + /* even number or not */ + if (realHexLen % BYTE_TO_HEX_OPER_LENGTH != 0 || byteLen < realHexLen / BYTE_TO_HEX_OPER_LENGTH) { + return HAL_ERR_INVALID_LEN; + } + + for (uint32_t i = 0; i < realHexLen / BYTE_TO_HEX_OPER_LENGTH; i++) { + uint8_t high = CharToHex(hexStr[i * BYTE_TO_HEX_OPER_LENGTH]); + uint8_t low = CharToHex(hexStr[i * BYTE_TO_HEX_OPER_LENGTH + 1]); + if (high == OUT_OF_HEX || low == OUT_OF_HEX) { + return HAL_ERR_INVALID_PARAM; + } + byte[i] = high << 4; /* 4: Set the high nibble */ + byte[i] |= low; /* Set the low nibble */ + } + return HAL_SUCCESS; +} + +int64_t StringToInt64(const char *cp) +{ + if (cp == NULL) { + return 0; + } + return strtoll(cp, NULL, DEC); +} \ No newline at end of file diff --git a/hals/src/common/hc_parcel.c b/hals/src/common/hc_parcel.c new file mode 100755 index 0000000..cf5f5a5 --- /dev/null +++ b/hals/src/common/hc_parcel.c @@ -0,0 +1,557 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "hc_parcel.h" +#include "hc_log.h" +#include "securec.h" + +const int PARCEL_DEFAULT_INCREASE_STEP = 16; +const uint32_t PARCEL_UINT_MAX = 0xffffffffU; + +HcParcel CreateParcel(uint32_t size, uint32_t allocUnit) +{ + HcParcel parcel; + (void)memset_s(&parcel, sizeof(parcel), 0, sizeof(parcel)); + parcel.allocUnit = allocUnit; + if (parcel.allocUnit == 0) { + parcel.allocUnit = PARCEL_DEFAULT_INCREASE_STEP; + } + if (size > 0) { + parcel.data = (char*)HcMalloc(size, 0); + if (parcel.data != NULL) { + parcel.length = size; + } + } + return parcel; +} + +void DeleteParcel(HcParcel *parcel) +{ + if (parcel == NULL) { + return; + } + + if (parcel->data != NULL) { + HcFree(parcel->data); + parcel->data = 0; + } + parcel->length = 0; + parcel->beginPos = 0; + parcel->endPos = 0; +} + +void ClearParcel(HcParcel *parcel) +{ + if (parcel != NULL) { + parcel->beginPos = 0; + parcel->endPos = 0; + } +} + +void ResetParcel(HcParcel *parcel, uint32_t size, uint32_t allocUnit) +{ + if (parcel != NULL) { + DeleteParcel(parcel); + HcParcel newParcel = CreateParcel(size, allocUnit); + (void)memcpy_s(parcel, sizeof(HcParcel), &newParcel, sizeof(HcParcel)); + } +} + +uint32_t GetParcelDataSize(const HcParcel *parcel) +{ + if (parcel == NULL) { + return 0; + } + if (parcel->endPos >= parcel->beginPos) { + return parcel->endPos - parcel->beginPos; + } + return 0; +} + +const char *GetParcelData(const HcParcel *parcel) +{ + if (parcel == NULL) { + return NULL; + } + return parcel->data + parcel->beginPos; +} + +const char* GetParcelLastChar(const HcParcel *parcel) +{ + if (parcel == NULL || GetParcelDataSize(parcel) == 0) { + return NULL; + } + return parcel->data + parcel->endPos - 1; +} + +HcBool ParcelReadWithoutPopData(HcParcel *parcel, void *dst, uint32_t dataSize) +{ +#ifdef IS_BIG_ENDIAN + HcBool ret = ParcelReadRevert(parcel, dst, dataSize); +#else + HcBool ret = ParcelRead(parcel, dst, dataSize); +#endif + if (ret == HC_TRUE) { + parcel->beginPos -= dataSize; + } + return ret; +} + +HcBool ParcelRead(HcParcel *parcel, void *dst, uint32_t dataSize) +{ + errno_t rc; + if (parcel == NULL || dst == NULL || dataSize == 0) { + LOGE("%s: Bad Parameters!", __func__); + return HC_FALSE; + } + if (parcel->beginPos > PARCEL_UINT_MAX - dataSize) { + LOGE("%s: Bad Parameters!", __func__); + return HC_FALSE; + } + if (parcel->beginPos + dataSize > parcel->endPos) { + LOGI("%s: parcel size < dataSize you want to read: parcel size %d while dataSize %u!", + __func__, GetParcelDataSize(parcel), dataSize); + return HC_FALSE; + } + rc = memmove_s(dst, dataSize, parcel->data + parcel->beginPos, dataSize); + if (rc != EOK) { + LOGE("%s: get data failed:%d.\n", __func__, rc); + return HC_FALSE; + } + parcel->beginPos += dataSize; + return HC_TRUE; +} + +HcBool ParcelEraseBlock(HcParcel *parcel, uint32_t start, uint32_t dataSize, void *dst) +{ + errno_t rc; + if (parcel == NULL || dst == NULL || dataSize == 0) { + LOGE("%s: Bad Parameters!", __func__); + return HC_FALSE; + } + if (start > PARCEL_UINT_MAX - dataSize) { + return HC_FALSE; + } + uint32_t parcelSizeOrg = GetParcelDataSize(parcel); + if (parcelSizeOrg < start + dataSize) { + return HC_FALSE; + } + char *beginCopy = parcel->data + parcel->beginPos + start; + uint32_t copySize = parcelSizeOrg - start - dataSize; + + rc = memmove_s(dst, dataSize, beginCopy, dataSize); + if (rc != EOK) { + LOGE("%s: get data failed:%d.\n", __func__, rc); + return HC_FALSE; + } + if (copySize != 0) { + rc = memmove_s(beginCopy, copySize, beginCopy + dataSize, copySize); + if (rc != EOK) { + LOGE("%s: copy data failed:%d.\n", __func__, rc); + return HC_FALSE; + } + } + parcel->endPos -= dataSize; + return HC_TRUE; +} + + +HcBool ParcelReadRevert(HcParcel *parcel, void *dst, uint32_t dataSize) +{ + if (ParcelRead(parcel, dst, dataSize)) { + DataRevert(dst, dataSize); + return HC_TRUE; + } else { + return HC_FALSE; + } +} + +HcBool ParcelWriteRevert(HcParcel *parcel, const void *src, uint32_t dataSize) +{ + errno_t rc; + void *srcCopy = HcMalloc(dataSize, 0); + if (srcCopy == NULL) { + return HC_FALSE; + } + rc = memmove_s(srcCopy, dataSize, src, dataSize); + if (rc != EOK) { + HcFree(srcCopy); + return HC_FALSE; + } + DataRevert(srcCopy, dataSize); + HcBool ret = ParcelWrite(parcel, srcCopy, dataSize); + HcFree(srcCopy); + return ret; +} + +HcBool ParcelReadInt32(HcParcel *parcel, int *dst) +{ + return ParcelRead(parcel, dst, sizeof(int)); +} + +HcBool ParcelReadUint32(HcParcel *parcel, uint32_t *dst) +{ + return ParcelRead(parcel, dst, sizeof(uint32_t)); +} + +HcBool ParcelReadInt16(HcParcel *parcel, short *dst) +{ + return ParcelRead(parcel, dst, sizeof(short)); +} + +HcBool ParcelReadUint16(HcParcel *parcel, uint16_t *dst) +{ + return ParcelRead(parcel, dst, sizeof(uint16_t)); +} + +HcBool ParcelReadInt8(HcParcel *parcel, char *dst) +{ + return ParcelRead(parcel, dst, sizeof(char)); +} + +HcBool ParcelReadUint8(HcParcel *parcel, uint8_t *dst) +{ + return ParcelRead(parcel, dst, sizeof(uint8_t)); +} + +HcBool ParcelReadUint64(HcParcel *parcel, uint64_t *dst) +{ + return ParcelRead(parcel, dst, sizeof(uint64_t)); +} + +HcBool ParcelReadInt64(HcParcel *parcel, int64_t *dst) +{ + return ParcelRead(parcel, dst, sizeof(int64_t)); +} + +static HcBool ParcelRealloc(HcParcel *parcel, uint32_t size) +{ + if (parcel->length >= size) { + LOGE("%s: ParcelRealloc failed, length is too big", __func__); + return HC_FALSE; + } + char *newData = (char*)HcMalloc(size, 0); + if (newData == NULL) { + LOGE("%s: ParcelRealloc failed, out of memory", __func__); + return HC_FALSE; + } + if (memcpy_s(newData, size, parcel->data, parcel->length) != EOK) { + HcFree(newData); + return HC_FALSE; + } + HcFree(parcel->data); + parcel->data = newData; + parcel->length = size; + return HC_TRUE; +} + +static HcBool ParcelIncrease(HcParcel *parcel, uint32_t size) +{ + if (parcel == NULL || size == 0) { + LOGE("%s: ParcelIncrease, invalid parameter", __func__); + return HC_FALSE; + } + if (parcel->data == NULL) { + if (parcel->length != 0) { + LOGE("%s: ParcelIncrease faile, invalid length", __func__); + return HC_FALSE; + } + (*parcel) = CreateParcel(size, parcel->allocUnit); + if (parcel->data == NULL) { + LOGE("%s: ParcelIncrease failed, create parcel failed", __func__); + return HC_FALSE; + } else { + return HC_TRUE; + } + } else { + return ParcelRealloc(parcel, size); + } +} + +static void ParcelRecycle(HcParcel *parcel) +{ + if (parcel == NULL) { + return; + } + if (parcel->data == NULL || parcel->beginPos < parcel->allocUnit) { + return; + } + + uint32_t contentSize = parcel->endPos - parcel->beginPos; + if (contentSize > 0) { + if (memmove_s(parcel->data, parcel->endPos - parcel->beginPos, + parcel->data + parcel->beginPos, parcel->endPos - parcel->beginPos) != EOK) { + LOGE("Move parcel's data failed."); + } + } + parcel->beginPos = 0; + parcel->endPos = contentSize; +} + +static uint32_t GetParcelIncreaseSize(HcParcel *parcel, uint32_t newSize) +{ + if (parcel == NULL || parcel->allocUnit == 0) { + return 0; + } + if (newSize % parcel->allocUnit) { + return (newSize / parcel->allocUnit + 1) * parcel->allocUnit; + } else { + return (newSize / parcel->allocUnit) * parcel->allocUnit; + } +} + +HcBool ParcelWrite(HcParcel *parcel, const void *src, uint32_t dataSize) +{ + errno_t rc; + if (parcel == NULL || src == NULL || dataSize == 0) { + LOGE("%s: Bad Parameters!", __func__); + return HC_FALSE; + } + if (parcel->endPos > PARCEL_UINT_MAX - dataSize) { + LOGE("%s: Bad Parameters overflow!", __func__); + return HC_FALSE; + } + if (parcel->endPos + dataSize > parcel->length) { + ParcelRecycle(parcel); + if (parcel->endPos + dataSize > parcel->length) { + uint32_t newSize = GetParcelIncreaseSize(parcel, parcel->endPos + dataSize); + if (!ParcelIncrease(parcel, newSize)) { + LOGE("%s: ParcelIncrease failed", __func__); + return HC_FALSE; + } + } + } + rc = memmove_s(parcel->data + parcel->endPos, dataSize, src, dataSize); + if (rc != EOK) { + LOGE("%s: get data failed:%d.\n", __func__, rc); + return HC_FALSE; + } + parcel->endPos += dataSize; + return HC_TRUE; +} + +HcBool ParcelWriteInt32(HcParcel *parcel, int src) +{ + return ParcelWrite(parcel, &src, sizeof(src)); +} + +HcBool ParcelWriteUint32(HcParcel *parcel, uint32_t src) +{ + return ParcelWrite(parcel, &src, sizeof(src)); +} + +HcBool ParcelWriteInt16(HcParcel *parcel, short src) +{ + return ParcelWrite(parcel, &src, sizeof(src)); +} + +HcBool ParcelWriteUint16(HcParcel *parcel, uint16_t src) +{ + return ParcelWrite(parcel, &src, sizeof(src)); +} + +HcBool ParcelWriteInt8(HcParcel *parcel, char src) +{ + return ParcelWrite(parcel, &src, sizeof(src)); +} + +HcBool ParcelWriteUint8(HcParcel *parcel, uint8_t src) +{ + return ParcelWrite(parcel, &src, sizeof(src)); +} + +HcBool ParcelWriteUint64(HcParcel *parcel, uint64_t src) +{ + return ParcelWrite(parcel, &src, sizeof(src)); +} + +HcBool ParcelWriteInt64(HcParcel *parcel, int64_t src) +{ + return ParcelWrite(parcel, &src, sizeof(src)); +} + +HcBool ParcelReadParcel(HcParcel *src, HcParcel *dst, uint32_t size, HcBool copy) +{ + if (src == NULL || dst == NULL) { + return HC_FALSE; + } + if (GetParcelDataSize(src) < size) { + return HC_FALSE; + } + if (!ParcelWrite(dst, (void*)GetParcelData(src), size)) { + return HC_FALSE; + } + + if (!copy) { + src->beginPos += size; + } + return HC_TRUE; +} + +HcBool ParcelCopy(HcParcel *src, HcParcel *dst) +{ + if (src == NULL || dst == NULL) { + return HC_FALSE; + } + if (GetParcelDataSize(src) == 0) { + return HC_TRUE; + } + return ParcelReadParcel(src, dst, GetParcelDataSize(src), HC_TRUE); +} + +void DataRevert(void *data, uint32_t length) +{ + if (data != NULL) { + uint8_t *pc = (uint8_t *) data; + uint32_t i = 0; + for (; i < length / 2; ++i) { /* half of the length */ + /* swap p[i] and p[length-i-1] */ + pc[i] ^= pc[length - i - 1]; + pc[length - i - 1] ^= pc[i]; + pc[i] ^= pc[length - i - 1]; + } + } +} + +HcBool ParcelReadInt32Revert(HcParcel *parcel, int32_t *dst) +{ + HcBool ret = ParcelRead(parcel, dst, sizeof(int)); + if (ret) { + DataRevert(dst, sizeof(int)); + } + return ret; +} + +HcBool ParcelReadUint32Revert(HcParcel *parcel, uint32_t *dst) +{ + HcBool ret = ParcelRead(parcel, dst, sizeof(uint32_t)); + if (ret) { + DataRevert(dst, sizeof(uint32_t)); + } + return ret; +} + +HcBool ParcelReadInt16Revert(HcParcel *parcel, short *dst) +{ + HcBool ret = ParcelRead(parcel, dst, sizeof(short)); + if (ret) { + DataRevert(dst, sizeof(short)); + } + return ret; +} + +HcBool ParcelReadUint16Revert(HcParcel *parcel, uint16_t *dst) +{ + if (parcel == NULL || dst == NULL) { + return HC_FALSE; + } + HcBool ret = ParcelRead(parcel, dst, sizeof(uint16_t)); + if (ret) { + DataRevert(dst, sizeof(uint16_t)); + } + return ret; +} + +HcBool ParcelReadInt8Revert(HcParcel *parcel, char *dst) +{ + return ParcelRead(parcel, dst, sizeof(char)); +} + +HcBool ParcelReadUint8Revert(HcParcel *parcel, uint8_t *dst) +{ + return ParcelRead(parcel, dst, sizeof(uint8_t)); +} + +HcBool ParcelReadUint64Revert(HcParcel *parcel, uint64_t *dst) +{ + HcBool ret = ParcelRead(parcel, dst, sizeof(uint64_t)); + if (ret) { + DataRevert(dst, sizeof(uint64_t)); + } + return ret; +} + +HcBool ParcelReadInt64Revert(HcParcel *parcel, int64_t *dst) +{ + HcBool ret = ParcelRead(parcel, dst, sizeof(int64_t)); + if (ret) { + DataRevert(dst, sizeof(int64_t)); + } + return ret; +} + +HcBool ParcelWriteInt32Revert(HcParcel *parcel, int src) +{ + DataRevert(&src, sizeof(src)); + return ParcelWriteInt32(parcel, src); +} + +HcBool ParcelWriteUint32Revert(HcParcel *parcel, uint32_t src) +{ + DataRevert(&src, sizeof(src)); + return ParcelWriteUint32(parcel, src); +} + +HcBool ParcelWriteInt16Revert(HcParcel *parcel, short src) +{ + DataRevert(&src, sizeof(src)); + return ParcelWriteInt16(parcel, src); +} + +HcBool ParcelWriteUint16Revert(HcParcel *parcel, uint16_t src) +{ + DataRevert(&src, sizeof(src)); + return ParcelWriteUint16(parcel, src); +} + +HcBool ParcelWriteInt8Revert(HcParcel *parcel, char src) +{ + return ParcelWriteInt8(parcel, src); +} + +HcBool ParcelWriteUint8Revert(HcParcel *parcel, uint8_t src) +{ + return ParcelWriteUint8(parcel, src); +} + +HcBool ParcelWriteUint64Revert(HcParcel *parcel, uint64_t src) +{ + DataRevert(&src, sizeof(src)); + return ParcelWriteUint64(parcel, src); +} + +HcBool ParcelWriteInt64Revert(HcParcel *parcel, int64_t src) +{ + DataRevert(&src, sizeof(src)); + return ParcelWriteInt64(parcel, src); +} + +HcBool ParcelPopBack(HcParcel *parcel, uint32_t size) +{ + if (parcel != NULL && size > 0 && GetParcelDataSize(parcel) >= size) { + parcel->endPos -= size; + return HC_TRUE; + } + return HC_FALSE; +} + +HcBool ParcelPopFront(HcParcel *parcel, uint32_t size) +{ + if ((parcel != NULL) && (size > 0) && (GetParcelDataSize(parcel) >= size)) { + parcel->beginPos += size; + return HC_TRUE; + } + return HC_FALSE; +} diff --git a/hals/src/common/hc_string.c b/hals/src/common/hc_string.c new file mode 100644 index 0000000..4c2aa21 --- /dev/null +++ b/hals/src/common/hc_string.c @@ -0,0 +1,175 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "hc_string.h" + +const uint32_t STRING_ALLOC_SIZE = 10; +const uint32_t STRING_END_CHAR_LENGTH = 1; +const char STRING_END_CHAR = '\0'; + +/* + * Append a HcString + * Notice: It will add '\0' automatically. + * @param self: self pointer. + * @param str: append string. + * @return HC_TRUE (ok), HC_FALSE (error) + */ +HcBool StringAppend(HcString *self, HcString str) +{ + uint32_t length = GetParcelDataSize(&str.parcel); + if (self != NULL && length > 0) { + // remove '\0' + ParcelPopBack(&self->parcel, STRING_END_CHAR_LENGTH); + // append string(include '\0') + return StringAppendPointer(self, GetParcelData(&str.parcel)); + } + + return HC_FALSE; +} + +/* + * Append string pointer + * Notice: It will add '\0' automatically. + * @param self: self pointer. + * @param str: string pointer. + * @return HC_TRUE (ok), HC_FALSE (error) + */ +HcBool StringAppendPointer(HcString *self, const char *str) +{ + if (self != NULL && str != NULL) { + // remove '\0' + ParcelPopBack(&self->parcel, STRING_END_CHAR_LENGTH); + // append string (include '\0') + return ParcelWrite(&self->parcel, (void *)str, strlen(str) + 1); + } + + return HC_FALSE; +} + +/* + * Append a char + * Notice: It will add '\0' automatically. + * @param self: self pointer. + * @param str: char. + * @return HC_TRUE (ok), HC_FALSE (error) + */ +HcBool StringAppendChar(HcString *self, char c) +{ + if (self != NULL && c != STRING_END_CHAR) { + // remove '\0' + ParcelPopBack(&self->parcel, STRING_END_CHAR_LENGTH); + + if (ParcelWriteInt8(&self->parcel, c)) { + return ParcelWriteInt8(&self->parcel, (uint32_t)STRING_END_CHAR); + } + } + + return HC_FALSE; +} + +/* + * Assign a value to the HcString + * Notice: It will add '\0' automatically. + * @param self: self pointer. + * @param str: assign value of ta_sting. + * @return HC_TRUE (ok), HC_FALSE (error) + */ +HcBool StringSet(HcString *self, HcString str) +{ + if (self != NULL) { + DeleteParcel(&self->parcel); + return StringAppend(self, str); + } + + return HC_FALSE; +} + +/* + * Assign a value to the HcString + * Notice: It will add '\0' automatically. + * @param self: self pointer. + * @param str: assign value of string pointer. + * @return HC_TRUE (ok), HC_FALSE (error) + */ +HcBool StringSetPointer(HcString *self, const char *str) +{ + if (self != NULL) { + DeleteParcel(&self->parcel); + return StringAppendPointer(self, str); + } + + return HC_FALSE; +} + +/* + * Get the string pointer data + * @param self: self pointer. + * @return the pointer data of the string + */ +const char* StringGet(const HcString *self) +{ + if (self == NULL) { + return NULL; + } + + return GetParcelData(&self->parcel); +} + +/* + * Get the length of the string + * @param self: self pointer. + * @return the length of the string + */ +uint32_t StringLength(const HcString *self) +{ + if (self == NULL) { + return 0; + } else { + uint32_t length = GetParcelDataSize(&self->parcel); + if (length > 0) { + return length - STRING_END_CHAR_LENGTH; + } else { + return 0; + } + } +} + +/* + * Create a string. + * Notice: You should delete_string when you don't need the string anymore. + * @return return the created string. + */ +HcString CreateString() +{ + HcString str; + str.parcel = CreateParcel(0, STRING_ALLOC_SIZE); + ParcelWriteInt8(&str.parcel, STRING_END_CHAR); + return str; +} + +/* + * Delete a string. In fact it will not destroy the string, + * but only free the allocate memory of the string and reset the member's value + * of the string. + * You can continue to use the string if you want. + * Notice: You should delete the string when you don't need it any more to avoid memory leak. + * @param str: The string you want to delete. + */ +void DeleteString(HcString *str) +{ + if (str != NULL) { + DeleteParcel(&str->parcel); + } +} diff --git a/hals/src/common/hc_task_thread.c b/hals/src/common/hc_task_thread.c new file mode 100755 index 0000000..42e9a93 --- /dev/null +++ b/hals/src/common/hc_task_thread.c @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "hc_task_thread.h" +#include "hc_error.h" +#include "hc_log.h" + +#define TASK_ALLOC_UINT 5 + +IMPLEMENT_HC_VECTOR(TaskVec, HcTaskWrap, TASK_ALLOC_UINT) + +static HcTaskBase* PopTask(HcTaskThread* thread) +{ + if (thread == NULL) { + return NULL; + } + + thread->queueLock.lock(&thread->queueLock); + HcTaskWrap task; + HcBool ret = thread->tasks.popFront(&thread->tasks, &task); + thread->queueLock.unlock(&thread->queueLock); + if (ret) { + return task.task; + } + return NULL; +} + +static void PushTask(struct HcTaskThreadT* thread, HcTaskBase* task) +{ + if (thread == NULL || task == NULL) { + return; + } + + thread->queueLock.lock(&thread->queueLock); + HcTaskWrap taskWarp; + taskWarp.task = task; + thread->tasks.pushBack(&thread->tasks, &taskWarp); + thread->thread.notify(&thread->thread); + thread->queueLock.unlock(&thread->queueLock); +} + +static void Clear(struct HcTaskThreadT* thread) +{ + thread->queueLock.lock(&thread->queueLock); + HcTaskWrap *taskWarp = NULL; + uint32_t index; + FOR_EACH_HC_VECTOR(thread->tasks, index, taskWarp) { + if (taskWarp->task->destroy) { + taskWarp->task->destroy(taskWarp->task); + } + HcFree(taskWarp->task); + } + thread->tasks.clear(&thread->tasks); + thread->queueLock.unlock(&thread->queueLock); +} + +static void StopAndClear(struct HcTaskThreadT* thread) +{ + if (thread == NULL) { + return; + } + thread->clear(thread); + thread->quit = HC_TRUE; + thread->thread.notify(&thread->thread); + thread->thread.join(&thread->thread); +} + +static int32_t StartTaskThread(struct HcTaskThreadT* thread) +{ + if (thread == NULL) { + return HAL_ERR_BAD_ALLOC; + } + + thread->quit = HC_FALSE; + int32_t res = thread->thread.start(&thread->thread); + if (res != HAL_SUCCESS) { + LOGE("Start thread failed, res:%d", res); + } + return res; +} + +static int TaskThreadLoop(void* args) +{ + HcTaskThread* thread = (HcTaskThread*)args; + if (thread == NULL) { + return -1; + } + + while (1) { + if (thread->quit) { + break; + } + HcTaskBase* task = PopTask(thread); + if (task != NULL) { + if (task->doAction) { + task->doAction(task); + } + if (task->destroy) { + task->destroy(task); + } + HcFree(task); + } else { + thread->thread.wait(&thread->thread); + } + } + return 0; +} + +int32_t InitHcTaskThread(HcTaskThread* thread, size_t stackSize, const char* threadName) +{ + if (thread == NULL) { + return -1; + } + + thread->pushTask = PushTask; + thread->startThread = StartTaskThread; + thread->clear = Clear; + thread->stopAndClear = StopAndClear; + int32_t res = InitThread(&thread->thread, TaskThreadLoop, stackSize, threadName); + if (res != 0) { + return res; + } + res = InitHcMutex(&thread->queueLock); + if (res != 0) { + DestroyThread(&thread->thread); + return res; + } + thread->tasks = CREATE_HC_VECTOR(TaskVec); + return 0; +} + +void DestroyHcTaskThread(HcTaskThread* thread) +{ + DESTROY_HC_VECTOR(TaskVec, &thread->tasks); + DestroyHcMutex(&thread->queueLock); + DestroyThread(&thread->thread); +} \ No newline at end of file diff --git a/hals/src/common/hc_tlv_parser.c b/hals/src/common/hc_tlv_parser.c new file mode 100755 index 0000000..ac86b09 --- /dev/null +++ b/hals/src/common/hc_tlv_parser.c @@ -0,0 +1,476 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "hc_tlv_parser.h" +#include +#include "hc_log.h" + +#define MAX_TLV_LENGTH (32 * 1024) + +HcBool ParseTlvHead(TlvBase *tlv, HcParcel *parcel) +{ +#ifdef IS_BIG_ENDIAN + if (!ParcelReadUint16Revert(parcel, &tlv->tag)) { + LOGE(" ParseTlvHead failed, read tag failed!!!"); + return HC_FALSE; + } +#else + if (!ParcelReadUint16(parcel, &tlv->tag)) { + LOGE(" ParseTlvHead failed, read tag failed!!!"); + return HC_FALSE; + } +#endif + + if (tlv->tag != tlv->checkTag) { + LOGE(" ParseTlvHead failed, tag is error, expect:%x, get:%x!!!", tlv->checkTag, tlv->tag); + return HC_FALSE; + } +#ifdef IS_BIG_ENDIAN + if (!ParcelReadUint16Revert(parcel, &tlv->length)) { + LOGE(" ParseTlvHead failed, read length failed!!!"); + return HC_FALSE; + } +#else + if (!ParcelReadUint16(parcel, &tlv->length)) { + LOGE(" ParseTlvHead failed, read length failed!!!"); + return HC_FALSE; + } +#endif + if (tlv->length > MAX_TLV_LENGTH) { + return HC_FALSE; + } + return HC_TRUE; +} + +int32_t ParseTlvNode(TlvBase *tlv, HcParcel *parcel, HcBool strict) +{ + if (!ParseTlvHead(tlv, parcel)) { + return TLV_FAIL; + } else { + if (GetParcelDataSize(parcel) < tlv->length) { + LOGE("parcel buffer too short tlv->tag is:%x, parcel size is %x and tlv->length is %x", + tlv->tag, GetParcelDataSize(parcel), tlv->length); + return TLV_FAIL; + } + + int ret = tlv->parse(tlv, parcel, strict); + if (ret < 0 || ret > MAX_TLV_LENGTH) { + return TLV_FAIL; + } else { + return ret + sizeof(tlv->tag) + sizeof(tlv->length); + } + } +} + +int32_t GetlenTlvNode(TlvBase *tlv) +{ + int32_t bodyLen = tlv->getlen(tlv); + if (bodyLen < 0 || bodyLen > MAX_TLV_LENGTH) { + return TLV_FAIL; + } else { + tlv->length = bodyLen + sizeof(tlv->tag) + sizeof(tlv->length); + return tlv->length; + } +} + +void DeinitTlvNode(TlvBase *tlv) +{ + if (tlv != NULL) { + tlv->deinit(tlv); + } +} + +int32_t EncodeTlvNode(TlvBase *tlv, HcParcel *parcel, HcBool isRoot) +{ + int32_t bodyLen = tlv->getlen(tlv); + if (bodyLen < 0 || bodyLen > MAX_TLV_LENGTH) { + return TLV_FAIL; + } else if (bodyLen == 0) { + if (isRoot) { + ResetParcel(parcel, sizeof(uint16_t) + sizeof(uint16_t), 0); + } +#ifdef IS_BIG_ENDIAN + ParcelWriteUint16Revert(parcel, tlv->checkTag); + ParcelWriteUint16Revert(parcel, bodyLen); +#else + ParcelWriteUint16(parcel, tlv->checkTag); + ParcelWriteUint16(parcel, bodyLen); +#endif + return sizeof(tlv->tag) + sizeof(tlv->length); + } else { // has value + if (isRoot) { + ResetParcel(parcel, sizeof(uint16_t) + sizeof(uint16_t) + bodyLen, 0); + } + int32_t encodeLen; + tlv->length = (uint16_t)bodyLen; +#ifdef IS_BIG_ENDIAN + ParcelWriteUint16Revert(parcel, tlv->checkTag); + ParcelWriteUint16Revert(parcel, tlv->length); +#else + ParcelWriteUint16(parcel, tlv->checkTag); + ParcelWriteUint16(parcel, tlv->length); +#endif + encodeLen = tlv->encode(tlv, parcel); + if (encodeLen < 0 || encodeLen > MAX_TLV_LENGTH) { + return TLV_FAIL; + } else { + return encodeLen + sizeof(tlv->tag) + sizeof(tlv->length); + } + } +} + +TlvBase* GetEmptyStructNode(TlvBase *tlv, unsigned short tag) +{ + if (tlv == NULL) { + return NULL; + } + + unsigned int index; + unsigned int memberCount = *(unsigned int *)((char *)tlv + offsetof(TlvOffsetExample, offsetCount)); + unsigned int *offset = (unsigned int *)((char *)tlv + offsetof(TlvOffsetExample, offset)); + for (index = 0; index < memberCount; ++index) { + TlvBase *tlvChild = (TlvBase *)(((char *)tlv) + offset[index]); + if (tlvChild->checkTag == tag && tlvChild->hasValue == 0) { + return tlvChild; + } + } + + return NULL; +} + +int32_t CheckStructNodeAllHasValue(TlvBase *tlv) +{ + if (tlv == NULL) { + return 0; + } else { + unsigned int index; + unsigned int memberCount = *(unsigned int *)((char *)tlv + offsetof(TlvOffsetExample, offsetCount)); + unsigned int *offset = (unsigned int *)((char *)tlv + offsetof(TlvOffsetExample, offset)); + for (index = 0; index < memberCount; ++index) { + TlvBase *tlvChild = (TlvBase *)(((char *)tlv) + offset[index]); + if (tlvChild->hasValue == 0) { + return -1; + } + } + } + + return 0; +} + +void SetStructNodeHasValue(TlvBase *tlv) +{ + if (tlv != NULL) { + tlv->hasValue = 1; + } +} + +int32_t ParseAndSkipTlvUnknownNode(HcParcel *parcel) +{ + // read tag + uint16_t tag = 0; + if (!ParcelReadUint16(parcel, &tag)) { + return TLV_FAIL; + } + + // read length + uint16_t length = 0; + if (!ParcelReadUint16(parcel, &length)) { + return TLV_FAIL; + } + + // pop data + if (!ParcelPopFront(parcel, length)) { + return TLV_FAIL; + } + + return sizeof(tag) + sizeof(length) + length; +} + +int32_t ParseTlvStruct(TlvBase *tlv, HcParcel *parcel, HcBool strict) +{ + uint32_t childTotalLength = 0; + do { + uint16_t tag = 0; + if (!ParcelReadWithoutPopData(parcel, &tag, sizeof(tag))) { + return TLV_FAIL; + } + TlvBase *tlvChild = GetEmptyStructNode(tlv, tag); + if (tlvChild == NULL) { + if (strict) { + LOGE("ParseTlvStruct error, unknown tag in strict mode:%x", tlv->tag); + return TLV_FAIL; + } + + int32_t unknownChildLength = ParseAndSkipTlvUnknownNode(parcel); + if (unknownChildLength < 0 || unknownChildLength > MAX_TLV_LENGTH) { + return TLV_FAIL; + } + childTotalLength += unknownChildLength; + if (childTotalLength > MAX_TLV_LENGTH) { + return TLV_FAIL; + } + } else { + int32_t childLength = ParseTlvNode(tlvChild, parcel, strict); + if (childLength < 0 || childLength > MAX_TLV_LENGTH) { + LOGE("ParseTlvStruct parse member child length error:%x", tag); + return TLV_FAIL; + } + SetStructNodeHasValue(tlvChild); + childTotalLength += childLength; + if (childTotalLength > MAX_TLV_LENGTH) { + return TLV_FAIL; + } + } + } while (childTotalLength < tlv->length); + + if (childTotalLength > tlv->length) { + LOGE("ParseTlvStruct failed, because child length is too big"); + return TLV_FAIL; + } + + if (strict && CheckStructNodeAllHasValue(tlv) != 0) { + LOGE("ParseTlvStruct error, the tag's child value is empty, tag:%x", tlv->tag); + return TLV_FAIL; + } + + return childTotalLength; +} + +int32_t EncodeTlvStruct(TlvBase *tlv, HcParcel *parcel) +{ + unsigned int index; + unsigned int memberCount = *(unsigned int *)((char *)tlv + offsetof(TlvOffsetExample, offsetCount)); + unsigned int *offset = (unsigned int *)((char *)tlv + offsetof(TlvOffsetExample, offset)); + + uint32_t totalLen = 0; + for (index = 0; index < memberCount; ++index) { + TlvBase *tlvChild = (TlvBase *)(((char *)tlv) + offset[index]); + int32_t childLen = EncodeTlvNode(tlvChild, parcel, HC_FALSE); + if (childLen < 0 || childLen > MAX_TLV_LENGTH) { + return TLV_FAIL; + } else { + totalLen += childLen; + } + if (totalLen > MAX_TLV_LENGTH) { + return TLV_FAIL; + } + } + + return totalLen; +} + +int32_t GetLenTlvStruct(TlvBase *tlv) +{ + unsigned int index; + unsigned int memberCount = *(unsigned int *)((char *)tlv + offsetof(TlvOffsetExample, offsetCount)); + unsigned int *offset = (unsigned int *)((char *)tlv + offsetof(TlvOffsetExample, offset)); + uint32_t childTotalLength = 0; + + for (index = 0; index < memberCount; ++index) { + TlvBase *tlvChild = (TlvBase *)(((char *)tlv) + offset[index]); + int32_t childLength = GetlenTlvNode(tlvChild); + if (childLength <= 0 || childLength > MAX_TLV_LENGTH) { + return TLV_FAIL; + } else { + childTotalLength += childLength; + } + if (childTotalLength > MAX_TLV_LENGTH) { + return TLV_FAIL; + } + } + + return childTotalLength; +} + +void DeinitTlvStruct(TlvBase *tlv) +{ + unsigned int index; + unsigned int memberCount = *(unsigned int *)((char *)tlv + offsetof(TlvOffsetExample, offsetCount)); + unsigned int *offset = (unsigned int *)((char *)tlv + offsetof(TlvOffsetExample, offset)); + + for (index = 0; index < memberCount; ++index) { + TlvBase *tlvChild = (TlvBase *)(((char *)tlv) + offset[index]); + DeinitTlvNode(tlvChild); + } +} + +HcBool DecodeTlvMessage(TlvBase *msg, HcParcel *parcel, HcBool strict) +{ + if (msg == NULL || parcel == NULL) { + return HC_FALSE; + } else { + int32_t msgLen = ParseTlvNode(msg, parcel, strict); + if (msgLen > MAX_TLV_LENGTH) { + return HC_FALSE; + } + if ((int32_t)(msg->length + sizeof(msg->length) + sizeof(msg->tag)) != msgLen) { + return HC_FALSE; + } + + if (GetParcelDataSize(parcel) != 0) { + return HC_FALSE; + } + } + + return HC_TRUE; +} + + +HcBool EncodeTlvMessage(TlvBase *msg, HcParcel *parcel) +{ + if (msg == NULL || parcel == NULL) { + return HC_FALSE; + } else { + if (EncodeTlvNode(msg, parcel, HC_TRUE) < 0) { + return HC_FALSE; + } + } + + return HC_TRUE; +} + +int32_t ParseTlvBuffer(TlvBase *tlv, HcParcel *parcel, HcBool strict) +{ + (void)strict; + TlvBuffer *realTlv = (TlvBuffer *)(tlv); + if (tlv->length == 0 || ParcelReadParcel(parcel, &realTlv->data, tlv->length, HC_FALSE)) { + return tlv->length; + } else { + LOGE("ParseTlvBuffer error"); + return TLV_FAIL; + } +} + +int32_t GetlenTlvBuffer(TlvBase *tlv) +{ + TlvBuffer *realTlv = (TlvBuffer *)(tlv); + return (int32_t)GetParcelDataSize(&realTlv->data); +} + +int32_t EncodeTlvBuffer(TlvBase *tlv, HcParcel *parcel) +{ + TlvBuffer *realTlv = (TlvBuffer *)(tlv); + int32_t len = GetlenTlvBuffer(tlv); + if (len <= 0 || len > MAX_TLV_LENGTH) { + return TLV_FAIL; + } + + if (ParcelReadParcel(&realTlv->data, parcel, len, HC_TRUE)) { + return len; + } else { + return TLV_FAIL; + } +} + +void DeinitTlvBuffer(TlvBase *tlv) +{ + DeleteParcel(&((TlvBuffer *)tlv)->data); +} + +void InitTlvBuffer(TlvBuffer *tlv, unsigned short checkTag) +{ + (void)memset_s(&tlv->base, sizeof(tlv->base), 0, sizeof(tlv->base)); + tlv->base.parse = ParseTlvBuffer; + tlv->base.getlen = GetlenTlvBuffer; + tlv->base.encode = EncodeTlvBuffer; + tlv->base.deinit = DeinitTlvBuffer; + tlv->base.checkTag = checkTag; + tlv->data = CreateParcel(PARCEL_DEFAULT_LENGTH, PARCEL_DEFAULT_ALLOC_UNIT); +} + +int32_t ParseTlvString(TlvBase *tlv, HcParcel *parcel, HcBool strict) +{ + (void)strict; + TlvString *realTlv = (TlvString *)(tlv); + ClearParcel(&realTlv->data.parcel); + if (tlv->length == 0 || ParcelReadParcel(parcel, &realTlv->data.parcel, tlv->length, HC_FALSE)) { + return tlv->length; + } else { + LOGE("ParseTlvBuffer error"); + return TLV_FAIL; + } +} + +int32_t GetlenTlvString(TlvBase *tlv) +{ + TlvString *realTlv = (TlvString *)(tlv); + return (int32_t)GetParcelDataSize(&realTlv->data.parcel); +} + +int32_t EncodeTlvString(TlvBase *tlv, HcParcel *parcel) +{ + TlvString *realTlv = (TlvString *)(tlv); + int32_t len = GetlenTlvString(tlv); + if (len <= 0 || len > MAX_TLV_LENGTH) { + return TLV_FAIL; + } + + if (ParcelReadParcel(&realTlv->data.parcel, parcel, len, HC_TRUE)) { + return len; + } else { + return TLV_FAIL; + } +} + +void DeinitTlvString(TlvBase *tlv) +{ + DeleteString(&((TlvString*)tlv)->data); +} + +void InitTlvString(TlvString *tlv, unsigned short checkTag) +{ + (void)memset_s(&tlv->base, sizeof(tlv->base), 0, sizeof(tlv->base)); + tlv->base.parse = ParseTlvString; + tlv->base.getlen = GetlenTlvString; + tlv->base.encode = EncodeTlvString; + tlv->base.deinit = DeinitTlvString; + tlv->base.checkTag = checkTag; + tlv->data = CreateString(); +} + +unsigned short GetTag(unsigned short checkTag, unsigned short defaultTag) +{ + if (checkTag == USE_DEFAULT_TAG) { + return defaultTag; + } else { + return checkTag; + } +} + +void DeinitTlvFixMember(TlvBase* tlv) +{ + (void)tlv; + return; +} + +#ifdef IS_BIG_ENDIAN +DEFINE_TLV_FIX_LENGTH_TYPE(TlvInt64, NEED_REVERT) +DEFINE_TLV_FIX_LENGTH_TYPE(TlvInt32, NEED_REVERT) +DEFINE_TLV_FIX_LENGTH_TYPE(TlvInt16, NEED_REVERT) +DEFINE_TLV_FIX_LENGTH_TYPE(TlvInt8, NEED_REVERT) +DEFINE_TLV_FIX_LENGTH_TYPE(TlvUint64, NEED_REVERT) +DEFINE_TLV_FIX_LENGTH_TYPE(TlvUint32, NEED_REVERT) +DEFINE_TLV_FIX_LENGTH_TYPE(TlvUint16, NEED_REVERT) +DEFINE_TLV_FIX_LENGTH_TYPE(TlvUint8, NEED_REVERT) +#else +DEFINE_TLV_FIX_LENGTH_TYPE(TlvInt64, NO_REVERT) +DEFINE_TLV_FIX_LENGTH_TYPE(TlvInt32, NO_REVERT) +DEFINE_TLV_FIX_LENGTH_TYPE(TlvInt16, NO_REVERT) +DEFINE_TLV_FIX_LENGTH_TYPE(TlvInt8, NO_REVERT) +DEFINE_TLV_FIX_LENGTH_TYPE(TlvUint64, NO_REVERT) +DEFINE_TLV_FIX_LENGTH_TYPE(TlvUint32, NO_REVERT) +DEFINE_TLV_FIX_LENGTH_TYPE(TlvUint16, NO_REVERT) +DEFINE_TLV_FIX_LENGTH_TYPE(TlvUint8, NO_REVERT) +#endif diff --git a/hals/src/common/json_utils.c b/hals/src/common/json_utils.c new file mode 100755 index 0000000..b254118 --- /dev/null +++ b/hals/src/common/json_utils.c @@ -0,0 +1,551 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "json_utils.h" +#include "cJSON.h" +#include "common_util.h" +#include "hc_error.h" +#include "hc_log.h" +#include "hc_types.h" + +#define RECURSE_FLAG_TRUE 1 + +CJson *CreateJsonFromString(const char *jsonStr) +{ + if (jsonStr == NULL) { + LOGE("Param is null."); + return NULL; + } + return cJSON_Parse(jsonStr); +} + +CJson *CreateJson() +{ + return cJSON_CreateObject(); +} + +CJson *CreateJsonArray() +{ + return cJSON_CreateArray(); +} + +CJson *DuplicateJson(const CJson *jsonObj) +{ + if (jsonObj == NULL) { + LOGE("Param is null."); + return NULL; + } + return cJSON_Duplicate(jsonObj, RECURSE_FLAG_TRUE); +} + +void FreeJson(CJson *jsonObj) +{ + cJSON_Delete(jsonObj); +} + +void DeleteItemFromJson(CJson *jsonObj, const char *key) +{ + if (jsonObj == NULL || key == NULL) { + LOGE("Param is null."); + return; + } + cJSON_DeleteItemFromObjectCaseSensitive(jsonObj, key); +} + +void DeleteAllItemExceptOne(CJson *jsonObj, const char *key) +{ + if (jsonObj == NULL || key == NULL) { + LOGE("Param is null."); + return; + } + + CJson *curItem = jsonObj->child; + CJson *nextItem = NULL; + while (curItem != NULL) { + nextItem = curItem->next; + if (strcmp(key, curItem->string) != 0) { + cJSON_Delete(cJSON_DetachItemViaPointer(jsonObj, curItem)); + } + curItem = nextItem; + } +} + +void DeleteAllItem(CJson *jsonObj) +{ + if (jsonObj == NULL) { + LOGE("Param is null."); + return; + } + + CJson *curItem = jsonObj->child; + CJson *nextItem = NULL; + while (curItem != NULL) { + nextItem = curItem->next; + cJSON_Delete(cJSON_DetachItemViaPointer(jsonObj, curItem)); + curItem = nextItem; + } +} + +CJson *DetachItemFromJson(CJson *jsonObj, const char *key) +{ + if (jsonObj == NULL || key == NULL) { + LOGE("Param is null."); + return NULL; + } + + return cJSON_DetachItemFromObjectCaseSensitive(jsonObj, key); +} + +char *PackJsonToString(const CJson *jsonObj) +{ + if (jsonObj == NULL) { + LOGE("Param is null."); + return NULL; + } + return cJSON_PrintUnformatted(jsonObj); +} + +void FreeJsonString(char *jsonStr) +{ + cJSON_free(jsonStr); +} + +int GetItemNum(const CJson *jsonObj) +{ + if (jsonObj == NULL) { + LOGE("Param is null."); + return 0; + } + return cJSON_GetArraySize(jsonObj); +} + +const char *GetItemKey(const CJson *item) +{ + if (item == NULL) { + LOGE("Param is null."); + return NULL; + } + return item->string; +} + +CJson *GetObjFromJson(const CJson *jsonObj, const char *key) +{ + if (jsonObj == NULL || key == NULL) { + LOGE("Param is null."); + return NULL; + } + + cJSON *objValue = cJSON_GetObjectItemCaseSensitive(jsonObj, key); + if (objValue != NULL) { + return objValue; + } + + int len = cJSON_GetArraySize(jsonObj); + for (int i = 0; i < len; i++) { + cJSON *item = cJSON_GetArrayItem(jsonObj, i); + if (cJSON_IsObject(item)) { + cJSON *obj = GetObjFromJson(item, key); + if (obj != NULL) { + return obj; + } + } + } + + return NULL; +} + +CJson *GetItemFromArray(const CJson *jsonArr, int index) +{ + if (jsonArr == NULL) { + LOGE("Param is null."); + return NULL; + } + return cJSON_GetArrayItem(jsonArr, index); +} + +const char *GetStringFromJson(const CJson *jsonObj, const char *key) +{ + if (jsonObj == NULL || key == NULL) { + LOGE("Param is null."); + return NULL; + } + + cJSON *jsonObjTmp = cJSON_GetObjectItemCaseSensitive(jsonObj, key); + if (jsonObjTmp != NULL && cJSON_IsString(jsonObjTmp)) { + return cJSON_GetStringValue(jsonObjTmp); + } + + int len = cJSON_GetArraySize(jsonObj); + for (int i = 0; i < len; i++) { + cJSON *item = cJSON_GetArrayItem(jsonObj, i); + if (cJSON_IsObject(item)) { + const char *resValue = GetStringFromJson(item, key); + if (resValue != NULL) { + return resValue; + } + } + } + + return NULL; +} + +int32_t GetByteFromJson(const CJson *jsonObj, const char *key, uint8_t *byte, uint32_t len) +{ + if (jsonObj == NULL || key == NULL || byte == NULL) { + LOGE("Param is null."); + return HAL_ERR_NULL_PTR; + } + + const char *valueStr = GetStringFromJson(jsonObj, key); + if (valueStr == NULL) { + return HAL_ERR_JSON_GET; + } + if (len < strlen(valueStr) / BYTE_TO_HEX_OPER_LENGTH) { + LOGE("Invalid length."); + return HAL_ERR_INVALID_LEN; + } + int32_t ret = HexStringToByte(valueStr, byte, len); + if (ret != HAL_SUCCESS) { + LOGE("Convert hex string to byte failed."); + return ret; + } + + return ret; +} + +int32_t GetIntFromJson(const CJson *jsonObj, const char *key, int *value) +{ + if (jsonObj == NULL || key == NULL || value == NULL) { + LOGE("Param is null."); + return HAL_ERR_NULL_PTR; + } + + cJSON *jsonObjTmp = cJSON_GetObjectItemCaseSensitive(jsonObj, key); + if (jsonObjTmp != NULL && cJSON_IsNumber(jsonObjTmp)) { + *value = (int)cJSON_GetNumberValue(jsonObjTmp); + return HAL_SUCCESS; + } + + int len = cJSON_GetArraySize(jsonObj); + for (int i = 0; i < len; i++) { + cJSON *item = cJSON_GetArrayItem(jsonObj, i); + if (cJSON_IsObject(item)) { + int32_t ret = GetIntFromJson(item, key, value); + if (ret == HAL_SUCCESS) { + return ret; + } + } + } + + return HAL_ERR_JSON_GET; +} + +int32_t GetInt64FromJson(const CJson *jsonObj, const char *key, int64_t *value) +{ + const char *str = GetStringFromJson(jsonObj, key); + if (str == NULL) { + LOGE("Failed to get int64_t from json!"); + return HAL_ERR_JSON_GET; + } + *value = StringToInt64(str); + return HAL_SUCCESS; +} + +int32_t GetBoolFromJson(const CJson *jsonObj, const char *key, bool *value) +{ + if (jsonObj == NULL || key == NULL || value == NULL) { + LOGE("Param is null."); + return HAL_ERR_NULL_PTR; + } + + cJSON *jsonObjTmp = cJSON_GetObjectItemCaseSensitive(jsonObj, key); + if (jsonObjTmp != NULL && cJSON_IsBool(jsonObjTmp)) { + *value = cJSON_IsTrue(jsonObjTmp) ? true : false; + return HAL_SUCCESS; + } + + int len = cJSON_GetArraySize(jsonObj); + for (int i = 0; i < len; i++) { + cJSON *item = cJSON_GetArrayItem(jsonObj, i); + if (cJSON_IsObject(item)) { + int32_t ret = GetBoolFromJson(item, key, value); + if (ret == HAL_SUCCESS) { + return ret; + } + } + } + + return HAL_ERR_JSON_GET; +} + +char *GetStringValue(const CJson *item) +{ + return cJSON_GetStringValue(item); +} + +int32_t AddObjToJson(CJson *jsonObj, const char *key, const CJson *childObj) +{ + if (jsonObj == NULL || key == NULL || childObj == NULL) { + LOGE("Param is null."); + return HAL_ERR_NULL_PTR; + } + + cJSON *tmpObj = cJSON_Duplicate(childObj, RECURSE_FLAG_TRUE); + if (tmpObj == NULL) { + LOGE("Duplicate json object failed."); + return HAL_ERR_JSON_DUPLICATE; + } + + cJSON *objInJson = cJSON_GetObjectItemCaseSensitive(jsonObj, key); + if (objInJson == NULL) { + if (cJSON_AddItemToObject(jsonObj, key, tmpObj) == false) { + LOGE("Add object to json failed."); + cJSON_Delete(tmpObj); + return HAL_ERR_JSON_ADD; + } + } else { + if (cJSON_ReplaceItemInObjectCaseSensitive(jsonObj, key, tmpObj) == false) { + LOGE("Replace object in json failed."); + cJSON_Delete(tmpObj); + return HAL_ERR_JSON_REPLACE; + } + } + + return HAL_SUCCESS; +} + +int32_t AddObjToArray(CJson *jsonArr, CJson *item) +{ + if (jsonArr == NULL || item == NULL) { + LOGE("Param is null."); + return HAL_ERR_NULL_PTR; + } + + if (cJSON_IsArray(jsonArr) == false) { + LOGE("Object is not array."); + return HAL_ERR_INVALID_PARAM; + } + + bool ret = cJSON_AddItemToArray(jsonArr, item); + if (ret == false) { + LOGE("Add object to array failed."); + return HAL_ERR_JSON_ADD; + } + + return HAL_SUCCESS; +} + +int32_t AddStringToArray(CJson *jsonArr, const char *string) +{ + if (jsonArr == NULL || string == NULL) { + LOGE("Param is null."); + return HAL_ERR_NULL_PTR; + } + + if (cJSON_IsArray(jsonArr) == false) { + LOGE("Object is not array."); + return HAL_ERR_INVALID_PARAM; + } + + cJSON *strObj = cJSON_CreateString(string); + if (strObj == NULL) { + LOGE("Create string json object failed."); + return HAL_ERR_BAD_ALLOC; + } + bool ret = cJSON_AddItemToArray(jsonArr, strObj); + if (ret == false) { + LOGE("Add string to array failed."); + cJSON_Delete(strObj); + return HAL_ERR_JSON_ADD; + } + + return HAL_SUCCESS; +} + +int32_t AddStringToJson(CJson *jsonObj, const char *key, const char *value) +{ + if (jsonObj == NULL || key == NULL || value == NULL) { + LOGE("Param is null."); + return HAL_ERR_NULL_PTR; + } + + cJSON *objInJson = cJSON_GetObjectItemCaseSensitive(jsonObj, key); + if (objInJson == NULL) { + if (cJSON_AddStringToObject(jsonObj, key, value) == NULL) { + LOGE("Add string to json failed."); + return HAL_ERR_JSON_GET; + } + } else { + cJSON *tmp = cJSON_CreateString(value); + if (tmp == NULL) { + LOGE("Create string json object failed."); + return HAL_ERR_BAD_ALLOC; + } + if (cJSON_ReplaceItemInObjectCaseSensitive(jsonObj, key, tmp) == false) { + LOGE("Replace string in json failed."); + cJSON_Delete(tmp); + return HAL_ERR_JSON_REPLACE; + } + } + + return HAL_SUCCESS; +} + +int32_t AddByteToJson(CJson *jsonObj, const char *key, const uint8_t *byte, uint32_t len) +{ + if (jsonObj == NULL || key == NULL || byte == NULL) { + LOGE("Param is null."); + return HAL_ERR_NULL_PTR; + } + + uint32_t hexLen = len * BYTE_TO_HEX_OPER_LENGTH + 1; + char *hexStr = (char *)HcMalloc(hexLen, 0); + if (hexStr == NULL) { + LOGE("Malloc hex string failed."); + return HAL_ERR_BAD_ALLOC; + } + int32_t ret = ByteToHexString(byte, len, hexStr, hexLen); + if (ret != HAL_SUCCESS) { + LOGE("Convert byte to hex string failed."); + HcFree(hexStr); + return ret; + } + + ret = AddStringToJson(jsonObj, key, hexStr); + if (ret != HAL_SUCCESS) { + LOGE("Add string to json failed."); + HcFree(hexStr); + return ret; + } + + HcFree(hexStr); + return HAL_SUCCESS; +} + +int32_t AddBoolToJson(CJson *jsonObj, const char *key, bool value) +{ + if (jsonObj == NULL || key == NULL) { + LOGE("Param is null."); + return HAL_ERR_NULL_PTR; + } + + cJSON *objInJson = cJSON_GetObjectItemCaseSensitive(jsonObj, key); + if (objInJson == NULL) { + if (cJSON_AddBoolToObject(jsonObj, key, value) == NULL) { + LOGE("Add bool to json failed."); + return HAL_ERR_JSON_GET; + } + } else { + cJSON *tmp = cJSON_CreateBool(value); + if (tmp == NULL) { + LOGE("Create bool json object failed."); + return HAL_ERR_BAD_ALLOC; + } + if (cJSON_ReplaceItemInObjectCaseSensitive(jsonObj, key, tmp) == false) { + LOGE("Repalce bool in json failed."); + cJSON_Delete(tmp); + return HAL_ERR_JSON_REPLACE; + } + } + + return HAL_SUCCESS; +} + +int32_t AddIntToJson(CJson *jsonObj, const char *key, int value) +{ + if (jsonObj == NULL || key == NULL) { + LOGE("Param is null."); + return HAL_ERR_NULL_PTR; + } + + cJSON *objInJson = cJSON_GetObjectItemCaseSensitive(jsonObj, key); + if (objInJson == NULL) { + if (cJSON_AddNumberToObject(jsonObj, key, value) == NULL) { + LOGE("Add int to json failed."); + return HAL_ERR_JSON_GET; + } + } else { + cJSON *tmp = cJSON_CreateNumber(value); + if (tmp == NULL) { + LOGE("Create int json object failed."); + return HAL_ERR_BAD_ALLOC; + } + if (cJSON_ReplaceItemInObjectCaseSensitive(jsonObj, key, tmp) == false) { + LOGE("Replace int in json failed."); + cJSON_Delete(tmp); + return HAL_ERR_JSON_REPLACE; + } + } + + return HAL_SUCCESS; +} + +int32_t AddInt64StringToJson(CJson *jsonObj, const char *key, int64_t value) +{ + char buffer[65] = { 0 }; + if (sprintf_s(buffer, sizeof(buffer), "%lld", value) <= 0) { + LOGE("Failed to convert int64_t to string!"); + return HAL_FAILED; + } + if (AddStringToJson(jsonObj, key, buffer) != HAL_SUCCESS) { + LOGE("Failed to add int64_t string to json!"); + return HAL_ERR_JSON_ADD; + } + return HAL_SUCCESS; +} + +int32_t AddStringArrayToJson(CJson *jsonObj, const char *key, const char * const *stringArray, uint32_t arrayLen) +{ + if (jsonObj == NULL || key == NULL || stringArray == NULL) { + LOGE("Param is null."); + return HAL_ERR_NULL_PTR; + } + + cJSON *strArrayObj = cJSON_CreateStringArray(stringArray, arrayLen); + if (strArrayObj == NULL) { + LOGE("Create string array object failed."); + return HAL_ERR_BAD_ALLOC; + } + if (cJSON_AddItemToObject(jsonObj, key, strArrayObj) == false) { + LOGE("Add string array to json failed."); + cJSON_Delete(strArrayObj); + return HAL_ERR_JSON_ADD; + } + return HAL_SUCCESS; +} + +void ClearSensitiveStringInJson(CJson *jsonObj, const char *key) +{ + if (jsonObj == NULL || key == NULL) { + LOGE("Param is null."); + return; + } + char *str = (char *)GetStringFromJson(jsonObj, key); + if (str == NULL) { + LOGD("Not find this value in json."); + return; + } + (void)memset_s(str, strlen(str), 0, strlen(str)); +} + +void ClearAndFreeJsonString(char *jsonStr) +{ + if (jsonStr == NULL) { + LOGE("Param is invalid."); + return; + } + (void)memset_s(jsonStr, strlen(jsonStr), 0, strlen(jsonStr)); + FreeJsonString(jsonStr); +} diff --git a/hals/src/dev_info/3516/hc_dev_info.c b/hals/src/dev_info/3516/hc_dev_info.c new file mode 100755 index 0000000..c2da39c --- /dev/null +++ b/hals/src/dev_info/3516/hc_dev_info.c @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "hc_dev_info.h" +#include "hc_error.h" +#include "securec.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int32_t HcGetUdid(uint8_t *udid, int32_t udidLen) +{ + if (udid == NULL || udidLen < INPUT_UDID_LEN || udidLen > MAX_INPUT_UDID_LEN) { + return HAL_ERR_INVALID_PARAM; + } + const char *udidTemp = "ABCDEF00ABCDEF00ABCDEF00ABCDEF00ABCDEF00ABCDEF00ABCDEF00ABCDEF00"; + (void)memset_s(udid, udidLen, 0, udidLen); + if (memcpy_s(udid, udidLen, udidTemp, strlen(udidTemp)) != EOK) { + return HAL_FAILED; + } + return HAL_SUCCESS; +} + +const char *GetStoragePath() +{ + return "/data/data/deviceauth/hcgroup.dat"; +} + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/hals/src/dev_info/watch/hc_dev_info.c b/hals/src/dev_info/watch/hc_dev_info.c new file mode 100755 index 0000000..ff81835 --- /dev/null +++ b/hals/src/dev_info/watch/hc_dev_info.c @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "hc_dev_info.h" +#include "common_util.h" +#include "hc_error.h" +#include "hc_log.h" +#include "hc_types.h" + +#define UDID_BYTE_LEN_IN_L0_DEVICE 32 + +extern uint8_t GetUdid(uint8_t *buf, uint8_t length); + +int32_t HcGetUdid(uint8_t *udid, int32_t udidLen) +{ + if (udid == NULL || udidLen < INPUT_UDID_LEN || udidLen > MAX_INPUT_UDID_LEN) { + return HAL_ERR_INVALID_PARAM; + } + uint8_t *udidInner = (uint8_t *)HcMalloc(UDID_BYTE_LEN_IN_L0_DEVICE, 0); + if (udidInner == NULL) { + return HAL_ERR_BAD_ALLOC; + } + uint8_t resultLen = GetUdid(udidInner, UDID_BYTE_LEN_IN_L0_DEVICE); + if (resultLen != UDID_BYTE_LEN_IN_L0_DEVICE) { + HcFree(udidInner); + LOGE("GetUdid in L0 device failed, resultLen:%u", resultLen); + return HAL_FAILED; + } + int32_t result = ByteToHexString(udidInner, UDID_BYTE_LEN_IN_L0_DEVICE, udid, udidLen); + HcFree(udidInner); + if (result != HAL_SUCCESS) { + LOGE("ByteToHexString for udid failed, result:%d", result); + } + return result; +} + +const char *GetStoragePath() +{ + return "user/Hichain/hcgroup.dat"; +} \ No newline at end of file diff --git a/hals/src/linux/L2/crypto_hash_to_point.c b/hals/src/linux/L2/crypto_hash_to_point.c new file mode 100644 index 0000000..3052b66 --- /dev/null +++ b/hals/src/linux/L2/crypto_hash_to_point.c @@ -0,0 +1,382 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "crypto_hash_to_point.h" +#include +#include +#include +#include "hc_error.h" +#include "hc_log.h" +#include "hc_types.h" +#include "hks_type.h" + +#define KEY_BYTES_CURVE25519 32 + +struct CurveConstPara { + BIGNUM *p; + BIGNUM *one; + BIGNUM *d; + BIGNUM *k; + BIGNUM *capitalA; + BIGNUM *minusA; + BIGNUM *u; + BIGNUM *q; +}; + +/* RFC 8032, the prime of Curve25519, p = 2^255-19 */ +static const uint8_t g_curveParamP[KEY_BYTES_CURVE25519] = { + 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xed +}; + +/* RFC 8032, one = 1 */ +static const uint8_t g_curveParamOne[KEY_BYTES_CURVE25519] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 +}; + +/* RFC 8032, A non-zero element in the finite field GF(p), not equal to 1 */ +static const uint8_t g_curveParamD[KEY_BYTES_CURVE25519] = { + 0xa3, 0x78, 0x59, 0x13, 0xca, 0x4d, 0xeb, 0x75, 0xab, 0xd8, 0x41, 0x41, 0x4d, 0x0a, 0x70, 0x00, + 0x98, 0xe8, 0x79, 0x77, 0x79, 0x40, 0xc7, 0x8c, 0x73, 0xfe, 0x6f, 0x2b, 0xee, 0x6c, 0x03, 0x52 +}; + +/* RFC 8032, k = (p - 1) / 2 */ +static const uint8_t g_curveParamK[KEY_BYTES_CURVE25519] = { + 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f +}; + +/* RFC 8032, A = 486662 */ +static const uint8_t g_curveParamCapitalA[KEY_BYTES_CURVE25519] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x6d, 0x06 +}; + +/* RFC 8032, -A = -486662 */ +static const uint8_t g_curveParamMinusA[KEY_BYTES_CURVE25519] = { + 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x92, 0xe7 +}; + +/* RFC 8032, u = 2 */ +static const uint8_t g_curveParamU[KEY_BYTES_CURVE25519] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 +}; + +/* RFC 8032, q = endian_swap(k) */ +static const uint8_t g_curveParamQ[KEY_BYTES_CURVE25519] = { + 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6 +}; + +static void CurveInitConstPara(struct CurveConstPara *para) +{ + para->p = BN_new(); + para->one = BN_new(); + para->d = BN_new(); + para->k = BN_new(); + para->capitalA = BN_new(); + para->minusA = BN_new(); + para->u = BN_new(); + para->q = BN_new(); +} + +static void CurveFreeConstPara(struct CurveConstPara *para) +{ + BN_free(para->p); + BN_free(para->one); + BN_free(para->d); + BN_free(para->k); + BN_free(para->capitalA); + BN_free(para->minusA); + BN_free(para->u); + BN_free(para->q); +} + +/* b := -A / (1 + u * a ^ 2) */ +static int32_t CurveHashToPointCalcB(const struct HksBlob *hash, + const struct CurveConstPara *curvePara, BIGNUM *b, BN_CTX *ctx) +{ + BIGNUM *swap = BN_new(); + int32_t ret = HAL_FAILED; + do { + if (BN_bin2bn(hash->data, hash->size, swap) == NULL) { + break; + } + if (BN_mul(b, swap, swap, ctx) <= 0) { + break; + } + if (BN_mod(b, b, curvePara->p, ctx) <= 0) { + break; + } + if (BN_mul(swap, b, curvePara->u, ctx) <= 0) { + break; + } + if (BN_mod(swap, swap, curvePara->p, ctx) <= 0) { + break; + } + if (BN_add(b, swap, curvePara->one) <= 0) { + break; + } + if (BN_mod(b, b, curvePara->p, ctx) <= 0) { + break; + } + if (BN_mod_inverse(swap, b, curvePara->p, ctx) <= 0) { + break; + } + if (BN_mul(b, swap, curvePara->minusA, ctx) <= 0) { + break; + } + if (BN_mod(b, b, curvePara->p, ctx) <= 0) { + break; + } + ret = HAL_SUCCESS; + } while (0); + BN_free(swap); + return ret; +} + +static int32_t CurveHashToPointCalcA(const BIGNUM *b, + const struct CurveConstPara *curvePara, BIGNUM *a, BN_CTX *ctx) +{ + BIGNUM *swap = BN_new(); + BIGNUM *result = BN_new(); + int32_t ret = HAL_FAILED; + + do { + if (BN_mul(result, b, b, ctx) <= 0) { + break; + } + if (BN_mod(result, result, curvePara->p, ctx) <= 0) { + break; + } + if (BN_mul(swap, result, b, ctx) <= 0) { + break; + } + if (BN_mod(swap, swap, curvePara->p, ctx) <= 0) { + break; + } + if (BN_mul(a, result, curvePara->capitalA, ctx) <= 0) { + break; + } + if (BN_mod(a, a, curvePara->p, ctx) <= 0) { + break; + } + if (BN_add(result, swap, a) <= 0) { + break; + } + if (BN_mod(result, result, curvePara->p, ctx) <= 0) { + break; + } + if (BN_add(a, result, b) <= 0) { + break; + } + if (BN_mod(a, a, curvePara->p, ctx) <= 0) { + break; + } + ret = HAL_SUCCESS; + } while (0); + + BN_free(swap); + BN_free(result); + return ret; +} + +static int32_t CurveHashToPointCalcC(const BIGNUM *a, BIGNUM *b, + const struct CurveConstPara *curvePara, BIGNUM *c, BN_CTX *ctx) +{ + BIGNUM *result = BN_new(); + int32_t ret = HAL_FAILED; + + do { + /* If a is a quadratic residue modulo p, c := b and high_y := 1 Otherwise c := -b - A and high_y := 0 */ + if (BN_sub(c, curvePara->p, b) <= 0) { + break; + } + if (BN_mod(c, c, curvePara->p, ctx) <= 0) { + break; + } + if (BN_add(c, c, curvePara->minusA) <= 0) { + break; + } + if (BN_mod(c, c, curvePara->p, ctx) <= 0) { + break; + } + /* Sliding-window exponentiation: result = a^q mod p */ + if (BN_mod_exp(result, a, curvePara->q, curvePara->p, ctx) <= 0) { + break; + } + if (BN_cmp(curvePara->q, result) > 0) { + BN_swap(b, c); + } + ret = HAL_SUCCESS; + } while (0); + + BN_free(result); + return ret; +} + +static int32_t CurveSetConstPara(struct CurveConstPara *para) +{ + int32_t ret = HAL_FAILED; + do { + if (BN_bin2bn(g_curveParamP, KEY_BYTES_CURVE25519, para->p) == NULL) { + break; + } + if (BN_bin2bn(g_curveParamOne, KEY_BYTES_CURVE25519, para->one) == NULL) { + break; + } + if (BN_bin2bn(g_curveParamD, KEY_BYTES_CURVE25519, para->d) == NULL) { + break; + } + if (BN_bin2bn(g_curveParamK, KEY_BYTES_CURVE25519, para->k) == NULL) { + break; + } + if (BN_bin2bn(g_curveParamCapitalA, KEY_BYTES_CURVE25519, para->capitalA) == NULL) { + break; + } + if (BN_bin2bn(g_curveParamMinusA, KEY_BYTES_CURVE25519, para->minusA) == NULL) { + break; + } + if (BN_bin2bn(g_curveParamU, KEY_BYTES_CURVE25519, para->u) == NULL) { + break; + } + if (BN_bin2bn(g_curveParamQ, KEY_BYTES_CURVE25519, para->q) == NULL) { + break; + } + ret = HAL_SUCCESS; + } while (0); + + return ret; +} + +static int32_t CurveHashToPoint(const struct HksBlob *hash, struct HksBlob *point) +{ + if ((hash == NULL) || (hash->data == NULL) || + (hash->size != KEY_BYTES_CURVE25519)) { + return HAL_ERR_NULL_PTR; + } + if ((point == NULL) || (point->data == NULL) || + (point->size != KEY_BYTES_CURVE25519)) { + return HAL_ERR_NULL_PTR; + } + + BIGNUM *a = BN_new(); + BIGNUM *b = BN_new(); + BIGNUM *c = BN_new(); + struct CurveConstPara curvePara; + (void)memset_s(&curvePara, sizeof(curvePara), 0, sizeof(curvePara)); + CurveInitConstPara(&curvePara); + int32_t ret; + BN_CTX *ctx = BN_CTX_new(); + if (ctx == NULL) { + ret = HAL_ERR_BAD_ALLOC; + goto err; + } + do { + ret = CurveSetConstPara(&curvePara); + if (ret != HAL_SUCCESS) { + break; + } + ret = CurveHashToPointCalcB(hash, &curvePara, b, ctx); + if (ret != HAL_SUCCESS) { + break; + } + + ret = CurveHashToPointCalcA(b, &curvePara, a, ctx); + if (ret != HAL_SUCCESS) { + break; + } + + ret = CurveHashToPointCalcC(a, b, &curvePara, c, ctx); + if (ret != HAL_SUCCESS) { + break; + } + + if (BN_bn2bin(c, point->data) <= 0) { + ret = HAL_FAILED; + } + } while (0); +err: + CurveFreeConstPara(&curvePara); + BN_free(a); + BN_free(b); + BN_free(c); + BN_CTX_free(ctx); + return ret; +} + +static int32_t EndianSwap(struct HksBlob *data) +{ + if (data->data == NULL) + return HAL_ERR_NULL_PTR; + + if (data->size == 0) + return HAL_ERR_NULL_PTR; + + int32_t end = data->size - 1; + const int32_t start = 0; + + /* count the middle index of array */ + int32_t cnt = data->size / 2; // 2 used to calculate half of the data size + + for (int32_t i = 0; i < cnt; i++) { + uint8_t tmp; + tmp = data->data[start + i]; + data->data[start + i] = data->data[end - i]; + data->data[end - i] = tmp; + } + return HAL_SUCCESS; +} + +int32_t OpensslHashToPoint(const struct HksBlob *hash, struct HksBlob *point) +{ + int32_t ret = HAL_FAILED; + uint8_t *copyData = HcMalloc(hash->size, 0); + if (copyData == NULL) { + LOGE("malloc size %u failed", hash->size); + return HKS_ERROR_MALLOC_FAIL; + } + struct HksBlob hashCopy = { hash->size, copyData}; + + do { + if (memcpy_s(hashCopy.data, hashCopy.size, hash->data, hash->size) != EOK) { + break; + } + + hashCopy.data[hashCopy.size - 1] &= 0x3f; /* RFC 8032 */ + ret = EndianSwap(&hashCopy); + if (ret != HAL_SUCCESS) { + LOGE("swap endian before convert failed"); + break; + } + + ret = CurveHashToPoint(&hashCopy, point); + if (ret != HAL_SUCCESS) { + LOGE("curve hash to point failed"); + break; + } + + ret = EndianSwap(point); + if (ret != HAL_SUCCESS) { + LOGE("swap endian after convert failed"); + break; + } + } while (0); + HcFree(hashCopy.data); + return ret; +} \ No newline at end of file diff --git a/hals/src/linux/L2/huks_adapter.c b/hals/src/linux/L2/huks_adapter.c new file mode 100644 index 0000000..a5bf66f --- /dev/null +++ b/hals/src/linux/L2/huks_adapter.c @@ -0,0 +1,1172 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "huks_adapter.h" +#include "common_util.h" +#include "crypto_hash_to_point.h" +#include "hc_log.h" +#include "hks_api.h" +#include "hks_param.h" +#include "hks_type.h" + +static enum HksKeyAlg g_algToHksAlgorithm[] = { + HKS_ALG_ED25519, + HKS_ALG_X25519, + HKS_ALG_ECC +}; + +static int32_t BaseCheckParams(const Uint8Buff **inParams, const char **paramTags, uint32_t len) +{ + for (uint32_t i = 0; i < len; i++) { + CHECK_PTR_RETURN_ERROR_CODE(inParams[i], paramTags[i]); + CHECK_PTR_RETURN_ERROR_CODE(inParams[i]->val, paramTags[i]); + CHECK_LEN_ZERO_RETURN_ERROR_CODE(inParams[i]->length, paramTags[i]); + } + return HAL_SUCCESS; +} + +static int32_t ConstructParamSet(struct HksParamSet **out, const struct HksParam *inParam, + const uint32_t inParamNum) +{ + struct HksParamSet *paramSet = NULL; + int32_t ret = HksInitParamSet(¶mSet); + if (ret != HKS_SUCCESS) { + LOGE("init param set failed, ret = %d", ret); + return HAL_ERR_INIT_PARAM_SET_FAILED; + } + + ret = HksAddParams(paramSet, inParam, inParamNum); + if (ret != HKS_SUCCESS) { + LOGE("add param failed, ret = %d", ret); + HksFreeParamSet(¶mSet); + return HAL_ERR_ADD_PARAM_FAILED; + } + + ret = HksBuildParamSet(¶mSet); + if (ret != HKS_SUCCESS) { + LOGE("build param set failed, ret = %d", ret); + HksFreeParamSet(¶mSet); + return HAL_ERR_BUILD_PARAM_SET_FAILED; + } + + *out = paramSet; + return HAL_SUCCESS; +} + +static int32_t InitHks() +{ + return HksInitialize(); +} + +static int32_t Sha256(const Uint8Buff *message, Uint8Buff *hash) +{ + CHECK_PTR_RETURN_ERROR_CODE(message, "message"); + CHECK_PTR_RETURN_ERROR_CODE(message->val, "message->val"); + CHECK_LEN_ZERO_RETURN_ERROR_CODE(message->length, "message->length"); + + CHECK_PTR_RETURN_ERROR_CODE(hash, "hash"); + CHECK_PTR_RETURN_ERROR_CODE(hash->val, "hash->val"); + CHECK_LEN_EQUAL_RETURN(hash->length, SHA256_LEN, "hash->length"); + + struct HksBlob srcBlob = { message->length, message->val }; + struct HksBlob hashBlob = { hash->length, hash->val }; + struct HksParamSet *paramSet = NULL; + struct HksParam digestParam[] = { + { + .tag = HKS_TAG_DIGEST, + .uint32Param = HKS_DIGEST_SHA256 + } + }; + int32_t ret = ConstructParamSet(¶mSet, digestParam, CAL_ARRAY_SIZE(digestParam)); + if (ret != HAL_SUCCESS) { + LOGE("construct param set failed, ret = %d", ret); + return ret; + } + + ret = HksHash(paramSet, &srcBlob, &hashBlob); + if (ret != HKS_SUCCESS || hashBlob.size != SHA256_LEN) { + HksFreeParamSet(¶mSet); + return HAL_FAILED; + } + + HksFreeParamSet(¶mSet); + return HAL_SUCCESS; +} + +static int32_t GenerateRandom(Uint8Buff *rand) +{ + CHECK_PTR_RETURN_ERROR_CODE(rand, "rand"); + CHECK_PTR_RETURN_ERROR_CODE(rand->val, "rand->val"); + CHECK_LEN_ZERO_RETURN_ERROR_CODE(rand->length, "rand->length"); + + struct HksBlob randBlob = { rand->length, rand->val }; + int32_t ret = HksGenerateRandom(NULL, &randBlob); + if (ret != HKS_SUCCESS) { + LOGE("Generate random failed, ret: %d", ret); + return HAL_FAILED; + } + + return HAL_SUCCESS; +} + +static int32_t CheckKeyExist(const Uint8Buff *keyAlias) +{ + CHECK_PTR_RETURN_ERROR_CODE(keyAlias, "keyAlias"); + CHECK_PTR_RETURN_ERROR_CODE(keyAlias->val, "keyAlias->val"); + CHECK_LEN_ZERO_RETURN_ERROR_CODE(keyAlias->length, "keyAlias->length"); + + struct HksBlob keyAliasBlob = { keyAlias->length, keyAlias->val }; + int32_t ret = HksKeyExist(&keyAliasBlob, NULL); + if (ret != HKS_SUCCESS) { + LOGI("Hks check key exist or not, ret = %d", ret); + return HAL_FAILED; + } + + return HAL_SUCCESS; +} + +static int32_t DeleteKey(const Uint8Buff *keyAlias) +{ + CHECK_PTR_RETURN_ERROR_CODE(keyAlias, "keyAlias"); + CHECK_PTR_RETURN_ERROR_CODE(keyAlias->val, "keyAlias->val"); + CHECK_LEN_ZERO_RETURN_ERROR_CODE(keyAlias->length, "keyAlias->length"); + + struct HksBlob keyAliasBlob = { keyAlias->length, keyAlias->val }; + int32_t ret = HksDeleteKey(&keyAliasBlob, NULL); + if (ret == HKS_ERROR_NOT_EXIST) { + LOGI("Key not exists."); + return HAL_SUCCESS; + } + if (ret != HKS_SUCCESS) { + LOGE("Delete key failed, ret = %d", ret); + return HAL_FAILED; + } + + return HAL_SUCCESS; +} + +static int32_t ComputeHmac(const Uint8Buff *key, const Uint8Buff *message, Uint8Buff *outHmac, bool isAlias) +{ + const Uint8Buff *inParams[] = { key, message, outHmac }; + const char *paramTags[] = {"key", "message", "outHmac"}; + int32_t ret = BaseCheckParams(inParams, paramTags, CAL_ARRAY_SIZE(inParams)); + if (ret != HAL_SUCCESS) { + return ret; + } + CHECK_LEN_EQUAL_RETURN(outHmac->length, HMAC_LEN, "outHmac->length"); + + struct HksBlob keyBlob = { key->length, key->val }; + struct HksBlob srcBlob = { message->length, message->val }; + struct HksBlob hmacBlob = { outHmac->length, outHmac->val }; + struct HksParamSet *paramSet = NULL; + struct HksParam hmacParam[] = { + { + .tag = HKS_TAG_PURPOSE, + .uint32Param = HKS_KEY_PURPOSE_MAC + }, { + .tag = HKS_TAG_DIGEST, + .uint32Param = HKS_DIGEST_SHA256 + }, { + .tag = HKS_TAG_IS_KEY_ALIAS, + .boolParam = isAlias + } + }; + ret = ConstructParamSet(¶mSet, hmacParam, CAL_ARRAY_SIZE(hmacParam)); + if (ret != HAL_SUCCESS) { + LOGE("construct param set failed, ret = %d", ret); + return ret; + } + + ret = HksMac(&keyBlob, paramSet, &srcBlob, &hmacBlob); + if (ret != HKS_SUCCESS || hmacBlob.size != HMAC_LEN) { + LOGE("Hmac failed, ret: %d", ret); + HksFreeParamSet(¶mSet); + return HAL_FAILED; + } + + HksFreeParamSet(¶mSet); + return HAL_SUCCESS; +} + +static int32_t ComputeHkdf(const Uint8Buff *baseKey, const Uint8Buff *salt, const Uint8Buff *keyInfo, + Uint8Buff *outHkdf, bool isAlias) +{ + const Uint8Buff *inParams[] = { baseKey, salt, outHkdf }; + const char *paramTags[] = { "baseKey", "salt", "outHkdf" }; + int32_t ret = BaseCheckParams(inParams, paramTags, CAL_ARRAY_SIZE(inParams)); + if (ret != HAL_SUCCESS) { + return ret; + } + + struct HksBlob srcKeyBlob = { baseKey->length, baseKey->val }; + struct HksBlob saltBlob = { salt->length, salt->val }; + struct HksBlob keyInfoBlob = { 0, NULL }; + if (keyInfo != NULL) { + keyInfoBlob.size = keyInfo->length; + keyInfoBlob.data = keyInfo->val; + } + struct HksBlob derivedKeyBlob = { outHkdf->length, outHkdf->val }; + + struct HksParamSet *paramSet = NULL; + struct HksParam hkdfParam[] = { + { + .tag = HKS_TAG_PURPOSE, + .uint32Param = HKS_KEY_PURPOSE_DERIVE + }, { + .tag = HKS_TAG_ALGORITHM, + .uint32Param = HKS_ALG_HKDF + }, { + .tag = HKS_TAG_DIGEST, + .uint32Param = HKS_DIGEST_SHA256 + }, { + .tag = HKS_TAG_SALT, + .blob = saltBlob + }, { + .tag = HKS_TAG_INFO, + .blob = keyInfoBlob + }, { + .tag = HKS_TAG_IS_KEY_ALIAS, + .boolParam = isAlias + } + }; + + ret = ConstructParamSet(¶mSet, hkdfParam, CAL_ARRAY_SIZE(hkdfParam)); + if (ret != HAL_SUCCESS) { + return ret; + } + + ret = HksDeriveKey(paramSet, &srcKeyBlob, &derivedKeyBlob); + if (ret != HKS_SUCCESS) { + LOGE("Key derivation failed, ret: %d", ret); + HksFreeParamSet(¶mSet); + return HAL_FAILED; + } + + HksFreeParamSet(¶mSet); + return HAL_SUCCESS; +} + +static int32_t CheckAesGcmEncryptParam(const Uint8Buff *key, const Uint8Buff *plain, const GcmParam *encryptInfo, + Uint8Buff *outCipher) +{ + const Uint8Buff *inParams[] = { key, plain, outCipher }; + const char* paramTags[] = { "key", "plain", "outCipher" }; + int32_t ret = BaseCheckParams(inParams, paramTags, CAL_ARRAY_SIZE(inParams)); + if (ret != HAL_SUCCESS) { + return ret; + } + + CHECK_PTR_RETURN_ERROR_CODE(encryptInfo, "encryptInfo"); + CHECK_PTR_RETURN_ERROR_CODE(encryptInfo->aad, "aad"); + CHECK_LEN_ZERO_RETURN_ERROR_CODE(encryptInfo->aadLen, "aadLen"); + CHECK_PTR_RETURN_ERROR_CODE(encryptInfo->nonce, "nonce"); + CHECK_LEN_LOWER_RETURN(encryptInfo->nonceLen, HKS_AE_NONCE_LEN, "nonceLen"); + CHECK_LEN_LOWER_RETURN(outCipher->length, plain->length + HKS_AE_TAG_LEN, "outCipher"); + + return HAL_SUCCESS; +} + +static int32_t AesGcmEncrypt(const Uint8Buff *key, const Uint8Buff *plain, + const GcmParam *encryptInfo, bool isAlias, Uint8Buff *outCipher) +{ + int32_t ret = CheckAesGcmEncryptParam(key, plain, encryptInfo, outCipher); + if (ret != HAL_SUCCESS) { + return ret; + } + + struct HksBlob keyBlob = { key->length, key->val }; + struct HksBlob plainBlob = { plain->length, plain->val }; + struct HksBlob cipherBlob = { outCipher->length, outCipher->val }; + + struct HksParamSet *paramSet = NULL; + struct HksParam encryptParam[] = { + { + .tag = HKS_TAG_PURPOSE, + .uint32Param = HKS_KEY_PURPOSE_ENCRYPT + }, { + .tag = HKS_TAG_ALGORITHM, + .uint32Param = HKS_ALG_AES + }, { + .tag = HKS_TAG_BLOCK_MODE, + .uint32Param = HKS_MODE_GCM + }, { + .tag = HKS_TAG_PADDING, + .uint32Param = HKS_PADDING_NONE + }, { + .tag = HKS_TAG_NONCE, + .blob = { encryptInfo->nonceLen, encryptInfo->nonce } + }, { + .tag = HKS_TAG_ASSOCIATED_DATA, + .blob = { encryptInfo->aadLen, encryptInfo->aad } + }, { + .tag = HKS_TAG_IS_KEY_ALIAS, + .boolParam = isAlias + } + }; + + ret = ConstructParamSet(¶mSet, encryptParam, CAL_ARRAY_SIZE(encryptParam)); + if (ret != HAL_SUCCESS) { + LOGE("construct param set failed, ret = %d", ret); + return ret; + } + + ret = HksEncrypt(&keyBlob, paramSet, &plainBlob, &cipherBlob); + if (ret != HKS_SUCCESS) { + LOGE("Aes-gcm encrypt failed, ret: %d", ret); + HksFreeParamSet(¶mSet); + return HAL_FAILED; + } + + HksFreeParamSet(¶mSet); + return HAL_SUCCESS; +} + +static int32_t CheckAesGcmDecryptParam(const Uint8Buff *key, const Uint8Buff *cipher, const GcmParam *decryptInfo, + Uint8Buff *outPlain) +{ + const Uint8Buff *inParams[] = { key, cipher, outPlain }; + const char *paramTags[] = { "key", "cipher", "outPlain" }; + int32_t ret = BaseCheckParams(inParams, paramTags, CAL_ARRAY_SIZE(inParams)); + if (ret != HAL_SUCCESS) { + return ret; + } + + CHECK_PTR_RETURN_ERROR_CODE(decryptInfo, "decryptInfo"); + CHECK_PTR_RETURN_ERROR_CODE(decryptInfo->aad, "aad"); + CHECK_LEN_ZERO_RETURN_ERROR_CODE(decryptInfo->aadLen, "aadLen"); + CHECK_PTR_RETURN_ERROR_CODE(decryptInfo->nonce, "nonce"); + CHECK_LEN_LOWER_RETURN(decryptInfo->nonceLen, HKS_AE_NONCE_LEN, "nonceLen"); + CHECK_LEN_LOWER_RETURN(outPlain->length, cipher->length - HKS_AE_TAG_LEN, "outPlain"); + + return HAL_SUCCESS; +} + +static int32_t AesGcmDecrypt(const Uint8Buff *key, const Uint8Buff *cipher, + const GcmParam *decryptInfo, bool isAlias, Uint8Buff *outPlain) +{ + int32_t ret = CheckAesGcmDecryptParam(key, cipher, decryptInfo, outPlain); + if (ret != HAL_SUCCESS) { + return ret; + } + + struct HksBlob keyBlob = { key->length, key->val }; + struct HksBlob cipherBlob = { cipher->length, cipher->val }; + struct HksBlob plainBlob = { outPlain->length, outPlain->val }; + + struct HksParamSet *paramSet = NULL; + struct HksParam decryptParam[] = { + { + .tag = HKS_TAG_PURPOSE, + .uint32Param = HKS_KEY_PURPOSE_DECRYPT + }, { + .tag = HKS_TAG_ALGORITHM, + .uint32Param = HKS_ALG_AES + }, { + .tag = HKS_TAG_BLOCK_MODE, + .uint32Param = HKS_MODE_GCM + }, { + .tag = HKS_TAG_PADDING, + .uint32Param = HKS_PADDING_NONE + }, { + .tag = HKS_TAG_NONCE, + .blob = { decryptInfo->nonceLen, decryptInfo->nonce } + }, { + .tag = HKS_TAG_ASSOCIATED_DATA, + .blob = { decryptInfo->aadLen, decryptInfo->aad } + }, { + .tag = HKS_TAG_IS_KEY_ALIAS, + .boolParam = isAlias + } + }; + + ret = ConstructParamSet(¶mSet, decryptParam, CAL_ARRAY_SIZE(decryptParam)); + if (ret != HAL_SUCCESS) { + LOGE("construct param set failed, ret = %d", ret); + return ret; + } + + ret = HksDecrypt(&keyBlob, paramSet, &cipherBlob, &plainBlob); + if (ret != HKS_SUCCESS) { + LOGE("Aes-gcm decrypt failed, ret: %d", ret); + HksFreeParamSet(¶mSet); + return HAL_FAILED; + } + + HksFreeParamSet(¶mSet); + return HAL_SUCCESS; +} + +static int32_t HashToPoint(const Uint8Buff *hash, Algorithm algo, Uint8Buff *outEcPoint) +{ + CHECK_PTR_RETURN_ERROR_CODE(hash, "hash"); + CHECK_PTR_RETURN_ERROR_CODE(hash->val, "hash->va"); + CHECK_LEN_EQUAL_RETURN(hash->length, SHA256_LEN, "hash->length"); + CHECK_PTR_RETURN_ERROR_CODE(outEcPoint, "outEcPoint"); + CHECK_PTR_RETURN_ERROR_CODE(outEcPoint->val, "outEcPoint->va"); + CHECK_LEN_EQUAL_RETURN(outEcPoint->length, SHA256_LEN, "outEcPoint->length"); + + struct HksBlob hashBlob = { hash->length, hash->val }; + struct HksBlob pointBlob = { outEcPoint->length, outEcPoint->val }; + + int32_t ret = OpensslHashToPoint(&hashBlob, &pointBlob); + if (ret != HAL_SUCCESS || pointBlob.size != SHA256_LEN) { + LOGE("Hks hashToPoint failed, ret: %d", ret); + return HAL_FAILED; + } + + return HAL_SUCCESS; +} + +static int32_t ConstructAgreeWithStorageParams(struct HksParamSet **paramSet, uint32_t keyLen, Algorithm algo, + const KeyBuff *priKey, const KeyBuff *pubKey) +{ + struct HksBlob priKeyBlob = { priKey->keyLen, priKey->key }; + struct HksBlob pubKeyBlob = { pubKey->keyLen, pubKey->key }; + struct HksParam agreeParam[] = { + { + .tag = HKS_TAG_ALGORITHM, + .uint32Param = HKS_ALG_AES + }, { + .tag = HKS_TAG_KEY_SIZE, + .uint32Param = keyLen * BITS_PER_BYTE + }, { + .tag = HKS_TAG_PURPOSE, + .uint32Param = HKS_KEY_PURPOSE_DERIVE + }, { + .tag = HKS_TAG_DIGEST, + .uint32Param = HKS_DIGEST_SHA256 + }, { + .tag = HKS_TAG_KEY_GENERATE_TYPE, + .uint32Param = HKS_KEY_GENERATE_TYPE_AGREE + }, { + .tag = HKS_TAG_AGREE_ALG, + .uint32Param = g_algToHksAlgorithm[algo] + }, { + .tag = HKS_TAG_AGREE_PRIVATE_KEY_ALIAS, + .blob = priKeyBlob + }, { + .tag = HKS_TAG_AGREE_PUBLIC_KEY, + .blob = pubKeyBlob + }, { + .tag = HKS_TAG_AGREE_PUBLIC_KEY_IS_KEY_ALIAS, + .boolParam = pubKey->isAlias + } + }; + + int32_t ret = ConstructParamSet(paramSet, agreeParam, CAL_ARRAY_SIZE(agreeParam)); + if (ret != HAL_SUCCESS) { + LOGE("Construct param set failed, ret = %d", ret); + return ret; + } + return ret; +} + +static int32_t AgreeSharedSecretWithStorage(const KeyBuff *priKey, const KeyBuff *pubKey, Algorithm algo, + uint32_t sharedKeyLen, const Uint8Buff *sharedKeyAlias) +{ + CHECK_PTR_RETURN_ERROR_CODE(priKey, "priKey"); + CHECK_PTR_RETURN_ERROR_CODE(priKey->key, "priKey->key"); + CHECK_LEN_ZERO_RETURN_ERROR_CODE(priKey->keyLen, "priKey->keyLen"); + CHECK_PTR_RETURN_ERROR_CODE(pubKey, "pubKey"); + CHECK_PTR_RETURN_ERROR_CODE(pubKey->key, "pubKey->key"); + CHECK_LEN_ZERO_RETURN_ERROR_CODE(pubKey->keyLen, "pubKey->keyLen"); + CHECK_PTR_RETURN_ERROR_CODE(sharedKeyAlias, "sharedKeyAlias"); + CHECK_PTR_RETURN_ERROR_CODE(sharedKeyAlias->val, "sharedKeyAlias->val"); + CHECK_LEN_ZERO_RETURN_ERROR_CODE(sharedKeyAlias->length, "sharedKeyAlias->length"); + CHECK_LEN_ZERO_RETURN_ERROR_CODE(sharedKeyLen, "sharedKeyLen"); + + struct HksBlob sharedKeyAliasBlob = { sharedKeyAlias->length, sharedKeyAlias->val }; + struct HksParamSet *paramSet = NULL; + int32_t ret = ConstructAgreeWithStorageParams(¶mSet, sharedKeyLen, algo, priKey, pubKey); + if (ret != HAL_SUCCESS) { + return ret; + } + + ret = HksGenerateKey(&sharedKeyAliasBlob, paramSet, NULL); + if (ret != HKS_SUCCESS) { + LOGE("Hks agree key with storage failed, ret = %d", ret); + HksFreeParamSet(¶mSet); + return HAL_FAILED; + } + + HksFreeParamSet(¶mSet); + return HAL_SUCCESS; +} + +static int32_t AgreeSharedSecret(const KeyBuff *priKey, const KeyBuff *pubKey, Algorithm algo, Uint8Buff *sharedKey) +{ + CHECK_PTR_RETURN_ERROR_CODE(priKey, "priKey"); + CHECK_PTR_RETURN_ERROR_CODE(priKey->key, "priKey->key"); + CHECK_LEN_ZERO_RETURN_ERROR_CODE(priKey->keyLen, "priKey->keyLen"); + CHECK_PTR_RETURN_ERROR_CODE(pubKey, "pubKey"); + CHECK_PTR_RETURN_ERROR_CODE(pubKey->key, "pubKey->key"); + CHECK_LEN_ZERO_RETURN_ERROR_CODE(pubKey->keyLen, "pubKey->keyLen"); + CHECK_PTR_RETURN_ERROR_CODE(sharedKey, "sharedKey"); + CHECK_PTR_RETURN_ERROR_CODE(sharedKey->val, "sharedKey->val"); + CHECK_LEN_ZERO_RETURN_ERROR_CODE(sharedKey->length, "sharedKey->length"); + + struct HksBlob priKeyBlob = { priKey->keyLen, priKey->key }; + struct HksBlob pubKeyBlob = { pubKey->keyLen, pubKey->key }; + struct HksBlob sharedKeyBlob = { sharedKey->length, sharedKey->val }; + + struct HksParamSet *paramSet = NULL; + struct HksParam agreeParam[] = { + { + .tag = HKS_TAG_ALGORITHM, + .uint32Param = g_algToHksAlgorithm[algo] // only support HKS_ALG_X25519 now + }, { + .tag = HKS_TAG_KEY_SIZE, + .uint32Param = sharedKey->length * BITS_PER_BYTE + }, { + .tag = HKS_TAG_IS_KEY_ALIAS, + .boolParam = priKey->isAlias + } + }; + + int32_t ret = ConstructParamSet(¶mSet, agreeParam, CAL_ARRAY_SIZE(agreeParam)); + if (ret != HAL_SUCCESS) { + LOGE("Construct param set failed, ret = %d", ret); + return ret; + } + + ret = HksAgreeKey(paramSet, &priKeyBlob, &pubKeyBlob, &sharedKeyBlob); + if (ret != HKS_SUCCESS) { + LOGE("Agree key failed, ret = %d", ret); + HksFreeParamSet(¶mSet); + return HAL_FAILED; + } + + HksFreeParamSet(¶mSet); + return HAL_SUCCESS; +} + +static int32_t BigNumExpMod(const Uint8Buff *base, const Uint8Buff *exp, const char *bigNumHex, Uint8Buff *outNum) +{ + const Uint8Buff *inParams[] = { base, exp, outNum }; + const char *paramTags[] = { "base", "exp", "outNum" }; + int32_t ret = BaseCheckParams(inParams, paramTags, CAL_ARRAY_SIZE(inParams)); + if (ret != HAL_SUCCESS) { + return ret; + } + + CHECK_PTR_RETURN_ERROR_CODE(bigNumHex, "bigNumHex"); + uint32_t primeLen = strlen(bigNumHex) / BYTE_TO_HEX_OPER_LENGTH; + if ((primeLen != BIG_PRIME_LEN_384) && (primeLen != BIG_PRIME_LEN_256)) { + LOGE("Not support big number len %d", outNum->length); + return HAL_FAILED; + } + CHECK_LEN_EQUAL_RETURN(outNum->length, primeLen, "outNum->length"); + + struct HksBlob baseBlob = { base->length, base->val }; + struct HksBlob expBlob = { exp->length, exp->val }; + struct HksBlob outNumBlob = { outNum->length, outNum->val }; + struct HksBlob bigNumBlob = { 0, NULL }; + bigNumBlob.size = outNum->length; + bigNumBlob.data = (uint8_t *)HcMalloc(bigNumBlob.size, 0); + if (bigNumBlob.data == NULL) { + LOGE("malloc bigNumBlob.data failed."); + return HAL_ERR_BAD_ALLOC; + } + ret = HexStringToByte(bigNumHex, bigNumBlob.data, bigNumBlob.size); + if (ret != HAL_SUCCESS) { + LOGE("HexStringToByte for bigNumHex failed."); + HcFree(bigNumBlob.data); + return ret; + } + + ret = HksBnExpMod(&outNumBlob, &baseBlob, &expBlob, &bigNumBlob); + if (ret != HKS_SUCCESS) { + LOGE("Huks calculate big number exp mod failed, ret = %d", ret); + HcFree(bigNumBlob.data); + return HAL_FAILED; + } + outNum->length = outNumBlob.size; + + HcFree(bigNumBlob.data); + return HAL_SUCCESS; +} + +static int32_t ConstructGenerateKeyPairWithStorageParams(struct HksParamSet **paramSet, Algorithm algo, + uint32_t keyLen, const struct HksBlob *authIdBlob) +{ + struct HksParam keyParam[] = { + { + .tag = HKS_TAG_ALGORITHM, + .uint32Param = g_algToHksAlgorithm[algo] + }, { + .tag = HKS_TAG_KEY_STORAGE_FLAG, + .uint32Param = HKS_STORAGE_PERSISTENT + }, { + .tag = HKS_TAG_PURPOSE, + .uint32Param = HKS_KEY_PURPOSE_SIGN | HKS_KEY_PURPOSE_VERIFY + }, { + .tag = HKS_TAG_KEY_SIZE, + .uint32Param = keyLen * BITS_PER_BYTE + }, { + .tag = HKS_TAG_KEY_AUTH_ID, + .blob = *authIdBlob + } + }; + + int32_t ret = ConstructParamSet(paramSet, keyParam, CAL_ARRAY_SIZE(keyParam)); + if (ret != HAL_SUCCESS) { + LOGE("Construct param set failed, ret = %d", ret); + return ret; + } + return ret; +} + +static int32_t GenerateKeyPairWithStorage(const Uint8Buff *keyAlias, uint32_t keyLen, Algorithm algo, + const ExtraInfo *exInfo) +{ + CHECK_PTR_RETURN_ERROR_CODE(keyAlias, "keyAlias"); + CHECK_PTR_RETURN_ERROR_CODE(keyAlias->val, "keyAlias->val"); + CHECK_LEN_ZERO_RETURN_ERROR_CODE(keyAlias->length, "keyAlias->length"); + CHECK_PTR_RETURN_ERROR_CODE(exInfo, "exInfo"); + CHECK_PTR_RETURN_ERROR_CODE(exInfo->authId.val, "authId->val"); + CHECK_LEN_ZERO_RETURN_ERROR_CODE(exInfo->authId.length, "authId->length"); + CHECK_LEN_ZERO_RETURN_ERROR_CODE(keyLen, "keyLen"); + + struct HksBlob keyAliasBlob = { keyAlias->length, keyAlias->val }; + struct HksBlob authIdBlob = { exInfo->authId.length, exInfo->authId.val }; + struct HksParamSet *paramSet = NULL; + int32_t ret = ConstructGenerateKeyPairWithStorageParams(¶mSet, algo, keyLen, &authIdBlob); + if (ret != HAL_SUCCESS) { + return ret; + } + + ret = HksGenerateKey(&keyAliasBlob, paramSet, NULL); + if (ret != HKS_SUCCESS) { + LOGE("Hks generate failed, ret=%d", ret); + HksFreeParamSet(¶mSet); + return HAL_FAILED; + } + + HksFreeParamSet(¶mSet); + return HAL_SUCCESS; +} + +static int32_t GetKeyPair(struct HksParamSet *outParamSet, Uint8Buff *outPriKey, Uint8Buff *outPubKey) +{ + int32_t ret = HksFreshParamSet(outParamSet, false); /* false means fresh by local, not through IPC */ + if (ret != HKS_SUCCESS) { + LOGE("fresh param set failed, ret:%d", ret); + return HAL_ERR_FRESH_PARAM_SET_FAILED; + } + + struct HksParam *pubKeyParam = NULL; + ret = HksGetParam(outParamSet, HKS_TAG_ASYMMETRIC_PUBLIC_KEY_DATA, &pubKeyParam); + if (ret != HKS_SUCCESS) { + LOGE("get pub key from param set failed, ret:%d", ret); + return HAL_ERR_GET_PARAM_FAILED; + } + + struct HksParam *priKeyParam = NULL; + ret = HksGetParam(outParamSet, HKS_TAG_ASYMMETRIC_PRIVATE_KEY_DATA, &priKeyParam); + if (ret != HKS_SUCCESS) { + LOGE("get priv key from param set failed, ret:%d", ret); + return HAL_ERR_GET_PARAM_FAILED; + } + + if (memcpy_s(outPubKey->val, outPubKey->length, pubKeyParam->blob.data, pubKeyParam->blob.size) != EOK) { + LOGE("parse x25519 output param set memcpy public key failed!"); + return HAL_ERR_MEMORY_COPY; + } + outPubKey->length = pubKeyParam->blob.size; + + if (memcpy_s(outPriKey->val, outPriKey->length, priKeyParam->blob.data, priKeyParam->blob.size) != EOK) { + LOGE("parse x25519 output param set memcpy private key failed!"); + return HAL_ERR_MEMORY_COPY; + } + outPriKey->length = priKeyParam->blob.size; + + return HAL_SUCCESS; +} + +static int32_t ConstructGenerateKeyPairParams(struct HksParamSet **paramSet, Algorithm algo, uint32_t keyLen) +{ + struct HksParam keyParam[] = { + { + .tag = HKS_TAG_KEY_STORAGE_FLAG, + .uint32Param = HKS_STORAGE_TEMP + }, { + .tag = HKS_TAG_ALGORITHM, + .uint32Param = g_algToHksAlgorithm[algo] + }, { + .tag = HKS_TAG_KEY_SIZE, + .uint32Param = keyLen * BITS_PER_BYTE + }, { + .tag = HKS_TAG_IS_KEY_ALIAS, + .uint32Param = false + } + }; + + int32_t ret = ConstructParamSet(paramSet, keyParam, CAL_ARRAY_SIZE(keyParam)); + if (ret != HAL_SUCCESS) { + LOGE("Construct param set failed, ret = %d", ret); + return ret; + } + return ret; +} + +static int32_t GenerateKeyPair(Algorithm algo, Uint8Buff *outPriKey, Uint8Buff *outPubKey) +{ + CHECK_PTR_RETURN_ERROR_CODE(outPriKey, "outPriKey"); + CHECK_PTR_RETURN_ERROR_CODE(outPriKey->val, "outPriKey->key"); + CHECK_LEN_ZERO_RETURN_ERROR_CODE(outPriKey->length, "outPriKey->keyLen"); + CHECK_PTR_RETURN_ERROR_CODE(outPubKey, "outPubKey"); + CHECK_PTR_RETURN_ERROR_CODE(outPubKey->val, "outPubKey->key"); + CHECK_LEN_ZERO_RETURN_ERROR_CODE(outPubKey->length, "outPubKey->keyLen"); + + if (outPriKey->length != outPubKey->length) { + LOGE("key len not equal."); + return HAL_ERR_INVALID_LEN; + } + uint32_t keyLen = outPriKey->length; + + struct HksParamSet *paramSet = NULL; + struct HksParamSet *outParamSet = NULL; + int32_t ret = ConstructGenerateKeyPairParams(¶mSet, algo, keyLen); + if (ret != HAL_SUCCESS) { + return ret; + } + + /* need 2 HksParam struct for outPriKey and outPubKey */ + uint32_t outParamSetSize = sizeof(struct HksParamSet) + + 2 * (sizeof(struct HksParam)) + outPriKey->length + outPubKey->length; + outParamSet = (struct HksParamSet *)HcMalloc(outParamSetSize, 0); + if (outParamSet == NULL) { + LOGE("allocate buffer for output param set failed"); + ret = HAL_ERR_BAD_ALLOC; + goto err; + } + outParamSet->paramSetSize = outParamSetSize; + + ret = HksGenerateKey(NULL, paramSet, outParamSet); + if (ret != HKS_SUCCESS) { + LOGE("generate x25519 key failed, ret:%d", ret); + ret = HAL_FAILED; + goto err; + } + + ret = GetKeyPair(outParamSet, outPriKey, outPubKey); + if (ret != HAL_SUCCESS) { + LOGE("parse x25519 output param set failed, ret:%d", ret); + goto err; + } +err: + HksFreeParamSet(¶mSet); + HcFree(outParamSet); + return ret; +} + +static int32_t ExportPublicKey(const Uint8Buff *keyAlias, Uint8Buff *outPubKey) +{ + CHECK_PTR_RETURN_ERROR_CODE(keyAlias, "keyAlias"); + CHECK_PTR_RETURN_ERROR_CODE(keyAlias->val, "keyAlias->val"); + CHECK_LEN_ZERO_RETURN_ERROR_CODE(keyAlias->length, "keyAlias->length"); + CHECK_PTR_RETURN_ERROR_CODE(outPubKey, "outPubKey"); + CHECK_PTR_RETURN_ERROR_CODE(outPubKey->val, "outPubKey->val"); + CHECK_LEN_ZERO_RETURN_ERROR_CODE(outPubKey->length, "outPubKey->length"); + + struct HksBlob keyAliasBlob = { keyAlias->length, keyAlias->val }; + struct HksBlob keyBlob = { outPubKey->length, outPubKey->val }; + + int32_t ret = HksExportPublicKey(&keyAliasBlob, NULL, &keyBlob); + if (ret != HKS_SUCCESS) { + LOGE("Export public key failed, ret=%d", ret); + return HAL_FAILED; + } + outPubKey->length = keyBlob.size; + + return HAL_SUCCESS; +} + +static int32_t ConstructSignParams(struct HksParamSet **paramSet, Algorithm algo) +{ + struct HksParam signParam[] = { + { + .tag = HKS_TAG_PURPOSE, + .uint32Param = HKS_KEY_PURPOSE_SIGN + }, { + .tag = HKS_TAG_ALGORITHM, + .uint32Param = g_algToHksAlgorithm[algo] // only support HKS_ALG_ED25519 + } + }; + + int32_t ret = ConstructParamSet(paramSet, signParam, CAL_ARRAY_SIZE(signParam)); + if (ret != HAL_SUCCESS) { + LOGE("Construct param set failed, ret = %d", ret); + return ret; + } + return ret; +} + +static int32_t Sign(const Uint8Buff *keyAlias, const Uint8Buff *message, Algorithm algo, + Uint8Buff *outSignature, bool isAlias) +{ + struct HksParamSet *paramSet = NULL; + const Uint8Buff *inParams[] = { keyAlias, message, outSignature }; + const char *paramTags[] = { "keyAlias", "message", "outSignature" }; + int32_t ret = BaseCheckParams(inParams, paramTags, CAL_ARRAY_SIZE(inParams)); + if (ret != HAL_SUCCESS) { + return ret; + } + CHECK_LEN_EQUAL_RETURN(outSignature->length, SIGNATURE_LEN, "outSignature->length"); + + struct HksBlob keyAliasBlob = { keyAlias->length, keyAlias->val }; + Uint8Buff messageHash = { NULL, 0 }; + messageHash.length = SHA256_LEN; + messageHash.val = (uint8_t *)HcMalloc(messageHash.length, 0); + if (messageHash.val == NULL) { + LOGE("malloc messageHash.data failed."); + ret = HAL_ERR_BAD_ALLOC; + goto err; + } + ret = Sha256(message, &messageHash); + if (ret != HAL_SUCCESS) { + LOGE("Sha256 failed."); + goto err; + } + struct HksBlob messageBlob = { messageHash.length, messageHash.val }; + struct HksBlob signatureBlob = { outSignature->length, outSignature->val }; + + ret = ConstructSignParams(¶mSet, algo); + if (ret != HAL_SUCCESS) { + goto err; + } + + ret = HksSign(&keyAliasBlob, paramSet, &messageBlob, &signatureBlob); + if ((ret != HKS_SUCCESS) || (signatureBlob.size != SIGNATURE_LEN)) { + LOGE("Hks sign failed."); + ret = HAL_FAILED; + goto err; + } + ret = HAL_SUCCESS; +err: + HksFreeParamSet(¶mSet); + HcFree(messageHash.val); + return ret; +} + +static int32_t ConstructVerifyParams(struct HksParamSet **paramSet, Algorithm algo, bool isAlias) +{ + struct HksParam verifyParam[] = { + { + .tag = HKS_TAG_PURPOSE, + .uint32Param = HKS_KEY_PURPOSE_VERIFY + }, { + .tag = HKS_TAG_ALGORITHM, + .uint32Param = g_algToHksAlgorithm[algo] // only support HKS_ALG_ED25519 + }, { + .tag = HKS_TAG_IS_KEY_ALIAS, + .boolParam = isAlias + } + }; + + int32_t ret = ConstructParamSet(paramSet, verifyParam, CAL_ARRAY_SIZE(verifyParam)); + if (ret != HAL_SUCCESS) { + LOGE("Construct param set failed, ret = %d", ret); + return ret; + } + return ret; +} + +static int32_t Verify(const Uint8Buff *key, const Uint8Buff *message, Algorithm algo, + const Uint8Buff *signature, bool isAlias) +{ + struct HksParamSet *paramSet = NULL; + const Uint8Buff *inParams[] = { key, message, signature }; + const char *paramTags[] = { "key", "message", "signature" }; + int32_t ret = BaseCheckParams(inParams, paramTags, CAL_ARRAY_SIZE(inParams)); + if (ret != HAL_SUCCESS) { + return ret; + } + CHECK_LEN_EQUAL_RETURN(signature->length, SIGNATURE_LEN, "signature"); + + struct HksBlob keyAliasBlob = { key->length, key->val }; + Uint8Buff messageHash = { NULL, 0 }; + messageHash.length = SHA256_LEN; + messageHash.val = (uint8_t *)HcMalloc(messageHash.length, 0); + if (messageHash.val == NULL) { + LOGE("malloc messageHash.data failed."); + ret = HAL_ERR_BAD_ALLOC; + goto err; + } + ret = Sha256(message, &messageHash); + if (ret != HAL_SUCCESS) { + LOGE("Sha256 failed."); + goto err; + } + struct HksBlob messageBlob = { messageHash.length, messageHash.val }; + struct HksBlob signatureBlob = { signature->length, signature->val }; + + ret = ConstructVerifyParams(¶mSet, algo, isAlias); + if (ret != HAL_SUCCESS) { + goto err; + } + + ret = HksVerify(&keyAliasBlob, paramSet, &messageBlob, &signatureBlob); + if ((ret != HKS_SUCCESS)) { + LOGE("HksVerify failed, ret: %d", ret); + ret = HAL_FAILED; + goto err; + } + ret = HAL_SUCCESS; +err: + HksFreeParamSet(¶mSet); + HcFree(messageHash.val); + return ret; +} + +static int32_t ConstructImportPublicKeyParams(struct HksParamSet **paramSet, Algorithm algo, uint32_t keyLen, + const struct HksBlob *authIdBlob, const union KeyRoleInfoUnion *roleInfoUnion) +{ + struct HksParam importParam[] = { + { + .tag = HKS_TAG_ALGORITHM, + .uint32Param = g_algToHksAlgorithm[algo] + }, { + .tag = HKS_TAG_KEY_SIZE, + .uint32Param = keyLen * BITS_PER_BYTE + }, { + .tag = HKS_TAG_PADDING, + .uint32Param = HKS_PADDING_NONE + }, { + .tag = HKS_TAG_KEY_AUTH_ID, + .blob = *authIdBlob + }, { + .tag = HKS_TAG_IS_ALLOWED_WRAP, + .boolParam = true + }, { + .tag = HKS_TAG_PURPOSE, + .uint32Param = HKS_KEY_PURPOSE_VERIFY + }, { + .tag = HKS_TAG_KEY_ROLE, + .uint32Param = roleInfoUnion->roleInfo + }, { + .tag = HKS_TAG_DIGEST, + .uint32Param = HKS_DIGEST_SHA256 + } + }; + + int32_t ret = ConstructParamSet(paramSet, importParam, CAL_ARRAY_SIZE(importParam)); + if (ret != HAL_SUCCESS) { + LOGE("Construct param set failed, ret = %d", ret); + return ret; + } + return ret; +} + +static int32_t ImportPublicKey(const Uint8Buff *keyAlias, const Uint8Buff *pubKey, Algorithm algo, + const ExtraInfo *exInfo) +{ + CHECK_PTR_RETURN_ERROR_CODE(keyAlias, "keyAlias"); + CHECK_PTR_RETURN_ERROR_CODE(keyAlias->val, "keyAlias->val"); + CHECK_LEN_ZERO_RETURN_ERROR_CODE(keyAlias->length, "keyAlias->length"); + CHECK_PTR_RETURN_ERROR_CODE(pubKey, "pubKey"); + CHECK_PTR_RETURN_ERROR_CODE(pubKey->val, "pubKey->val"); + CHECK_LEN_ZERO_RETURN_ERROR_CODE(pubKey->length, "pubKey->length"); + CHECK_PTR_RETURN_ERROR_CODE(exInfo, "exInfo"); + CHECK_PTR_RETURN_ERROR_CODE(exInfo->authId.val, "authId->val"); + CHECK_LEN_ZERO_RETURN_ERROR_CODE(exInfo->authId.length, "authId->length"); + CHECK_LEN_HIGHER_RETURN(exInfo->pairType, PAIR_TYPE_END - 1, "pairType"); + + struct HksBlob keyAliasBlob = { keyAlias->length, keyAlias->val }; + struct HksBlob pubKeyBlob = { pubKey->length, pubKey->val }; + + struct HksBlob authIdBlob = { exInfo->authId.length, exInfo->authId.val }; + union KeyRoleInfoUnion roleInfoUnion; + roleInfoUnion.roleInfoStruct.userType = (uint8_t)exInfo->userType; + roleInfoUnion.roleInfoStruct.pairType = (uint8_t)exInfo->pairType; + roleInfoUnion.roleInfoStruct.reserved1 = (uint8_t)0; + roleInfoUnion.roleInfoStruct.reserved2 = (uint8_t)0; + + struct HksParamSet *paramSet = NULL; + + int32_t ret = ConstructImportPublicKeyParams(¶mSet, algo, pubKey->length, &authIdBlob, &roleInfoUnion); + if (ret != HAL_SUCCESS) { + return ret; + } + + ret = HksImportKey(&keyAliasBlob, paramSet, &pubKeyBlob); + if (ret != HKS_SUCCESS) { + LOGE("Hks importKey failed, ret: %d", ret); + HksFreeParamSet(¶mSet); + return HAL_FAILED; + } + + HksFreeParamSet(¶mSet); + return HAL_SUCCESS; +} + +static int32_t ComputePublicKey(const Uint8Buff *priKey, const Uint8Buff *base, Algorithm algo, Uint8Buff *pubKey) +{ + CHECK_PTR_RETURN_ERROR_CODE(priKey, "priKey"); + CHECK_PTR_RETURN_ERROR_CODE(priKey->val, "priKey->val"); + CHECK_LEN_ZERO_RETURN_ERROR_CODE(priKey->length, "priKey->length"); + CHECK_PTR_RETURN_ERROR_CODE(base, "base"); + CHECK_PTR_RETURN_ERROR_CODE(base->val, "base->val"); + CHECK_LEN_ZERO_RETURN_ERROR_CODE(base->length, "base->length"); + CHECK_PTR_RETURN_ERROR_CODE(pubKey, "sharedKey"); + CHECK_PTR_RETURN_ERROR_CODE(pubKey->val, "pubKey->val"); + CHECK_LEN_ZERO_RETURN_ERROR_CODE(pubKey->length, "pubKey->length"); + + struct HksBlob priKeyBlob = { priKey->length, priKey->val }; + struct HksBlob pubKeyBlob = { base->length, base->val }; + struct HksBlob sharedKeyBlob = { pubKey->length, pubKey->val }; + + struct HksParamSet *paramSet = NULL; + struct HksParam agreeParam[] = { + { + .tag = HKS_TAG_ALGORITHM, + .uint32Param = g_algToHksAlgorithm[algo] // only support HKS_ALG_X25519 now + }, { + .tag = HKS_TAG_KEY_SIZE, + .uint32Param = pubKey->length * BITS_PER_BYTE + }, { + .tag = HKS_TAG_IS_KEY_ALIAS, + .boolParam = false + } + }; + + int32_t ret = ConstructParamSet(¶mSet, agreeParam, CAL_ARRAY_SIZE(agreeParam)); + if (ret != HAL_SUCCESS) { + LOGE("Construct param set failed, ret = %d", ret); + return ret; + } + + ret = HksAgreeKey(paramSet, &priKeyBlob, &pubKeyBlob, &sharedKeyBlob); + if (ret != HKS_SUCCESS) { + LOGE("Agree key failed, ret = %d", ret); + HksFreeParamSet(¶mSet); + return HAL_FAILED; + } + + HksFreeParamSet(¶mSet); + return HAL_SUCCESS; +} + +static int32_t Compare(const uint8_t *a, uint32_t lenA, const uint8_t *b, uint32_t lenB) +{ + const uint8_t *tmpA = a; + const uint8_t *tmpB = b; + uint32_t len = lenA; + if (lenA < lenB) { + for (uint32_t i = 0; i < lenB - lenA; i++) { + if (b[i] > 0) { + return 1; // a < b + } + } + tmpA = a; + tmpB = b + lenB - lenA; + len = lenA; + } + if (lenA > lenB) { + for (uint32_t i = 0; i < lenA - lenB; i++) { + if (a[i] > 0) { + return -1; // a > b + } + } + tmpA = a + lenA - lenB; + tmpB = b; + len = lenB; + } + for (uint32_t i = 0; i < len; i++) { + if (*(tmpA + i) > *(tmpB + i)) { + return -1; // a > b + } + if (*(tmpA + i) < *(tmpB + i)) { + return 1; // a < b + } + } + return 0; // a == b +} + +bool CheckDlPublicKey(const Uint8Buff *key, const char *primeHex) +{ + if (key == NULL || key->val == NULL || primeHex == NULL) { + LOGE("Params is null."); + return false; + } + uint8_t min = 1; + + uint32_t innerKeyLen = HcStrlen(primeHex) / BYTE_TO_HEX_OPER_LENGTH; + if (key->length > innerKeyLen) { + LOGE("Key length > prime number length."); + return false; + } + uint8_t *primeByte = (uint8_t *)HcMalloc(innerKeyLen, 0); + if (primeByte == NULL) { + LOGE("Malloc for primeByte failed."); + return false; + } + if (HexStringToByte(primeHex, primeByte, innerKeyLen) != HAL_SUCCESS) { + LOGE("Convert prime number from hex string to byte failed."); + HcFree(primeByte); + return false; + } + /* + * P - 1, since the last byte of large prime number must be greater than 1, + * needn't to think about borrowing forward + */ + primeByte[innerKeyLen - 1] -= 1; + + if (Compare(key->val, key->length, &min, sizeof(uint8_t)) >= 0) { + LOGE("Pubkey is invalid, key <= 1."); + HcFree(primeByte); + return false; + } + + if (Compare(key->val, key->length, primeByte, innerKeyLen) <= 0) { + LOGE("Pubkey is invalid, key >= p - 1."); + HcFree(primeByte); + return false; + } + + HcFree(primeByte); + return true; +} + +static const AlgLoader g_huksLoader = { + InitHks, + Sha256, + GenerateRandom, + ComputeHmac, + ComputeHkdf, + NULL, + CheckKeyExist, + DeleteKey, + AesGcmEncrypt, + AesGcmDecrypt, + HashToPoint, + AgreeSharedSecretWithStorage, + AgreeSharedSecret, + BigNumExpMod, + GenerateKeyPairWithStorage, + GenerateKeyPair, + ExportPublicKey, + Sign, + Verify, + ImportPublicKey, + ComputePublicKey, + CheckDlPublicKey, + NULL +}; + +const AlgLoader *GetRealLoaderInstance() +{ + return &g_huksLoader; +} \ No newline at end of file diff --git a/hals/src/linux/hc_condition.c b/hals/src/linux/hc_condition.c new file mode 100644 index 0000000..42b1492 --- /dev/null +++ b/hals/src/linux/hc_condition.c @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "hc_condition.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int Wait(pthread_cond_t* cond, HcMutex* mutex) +{ + if (cond == NULL || mutex == NULL) { + return -1; + } + return -pthread_cond_wait(cond, &mutex->mutex); +} + +void Notify(pthread_cond_t* cond) +{ + if (cond == NULL) { + return; + } + pthread_cond_signal(cond); +} + +int HcCondWaitWithoutLock(struct HcConditionT* hcCond) +{ + if (hcCond == NULL || hcCond->mutex == NULL) { + return -1; + } + if (hcCond->notified) { + hcCond->notified = HC_FALSE; + return 0; + } else { + int ret; + hcCond->waited = HC_TRUE; + ret = Wait(&hcCond->cond, hcCond->mutex); + hcCond->waited = HC_FALSE; + hcCond->notified = HC_FALSE; + return ret; + } +} + +void HcCondNotifyWithoutLock(struct HcConditionT* hcCond) +{ + if (hcCond == NULL || hcCond->mutex == NULL) { + return; + } + + if (!hcCond->waited) { + hcCond->notified = HC_TRUE; + } else { + hcCond->notified = HC_FALSE; + } + Notify(&hcCond->cond); +} + +int HcCondWait(struct HcConditionT* hcCond) +{ + if (hcCond == NULL) { + return -1; + } + if (hcCond->mutex == NULL) { + return -1; + } + + hcCond->mutex->lock(hcCond->mutex); + if (hcCond->notified) { + hcCond->notified = HC_FALSE; + hcCond->mutex->unlock(hcCond->mutex); + return 0; + } else { + int ret; + hcCond->waited = HC_TRUE; + ret = Wait(&hcCond->cond, hcCond->mutex); + hcCond->waited = HC_FALSE; + hcCond->notified = HC_FALSE; + hcCond->mutex->unlock(hcCond->mutex); + return ret; + } +} + +void HcCondNotify(struct HcConditionT* hcCond) +{ + if (hcCond == NULL || hcCond->mutex == NULL) { + return; + } + + hcCond->mutex->lock(hcCond->mutex); + + if (!hcCond->waited) { + hcCond->notified = HC_TRUE; + } else { + hcCond->notified = HC_FALSE; + } + Notify(&hcCond->cond); + hcCond->mutex->unlock(hcCond->mutex); +} + +int32_t InitHcCond(HcCondition* hcCond, HcMutex* mutex) +{ + if (hcCond == NULL) { + return -1; + } + hcCond->notified = HC_FALSE; + hcCond->waited = HC_FALSE; + hcCond->wait = HcCondWait; + hcCond->notify = HcCondNotify; + hcCond->waitWithoutLock = HcCondWaitWithoutLock; + hcCond->notifyWithoutLock = HcCondNotifyWithoutLock; + + pthread_condattr_t attr; + pthread_condattr_init(&attr); + pthread_cond_init(&hcCond->cond, &attr); + pthread_condattr_destroy(&attr); + + if (mutex != NULL) { + hcCond->mutex = mutex; + hcCond->innerMutex = HC_FALSE; + } else { + hcCond->mutex = (HcMutex*)HcMalloc(sizeof(HcMutex), 0); + if (hcCond->mutex != NULL) { + int32_t res; + res = InitHcMutex(hcCond->mutex); + if (res != 0) { + HcFree(hcCond->mutex); + hcCond->mutex = NULL; + return res; + } + hcCond->innerMutex = HC_TRUE; + } else { + return -1; + } + } + return 0; +} + +void DestroyHcCond(HcCondition* hcCond) +{ + if (hcCond == NULL) { + return; + } + + if (hcCond->innerMutex && hcCond->mutex) { + DestroyHcMutex(hcCond->mutex); + HcFree(hcCond->mutex); + hcCond->mutex = NULL; + } + pthread_cond_destroy(&hcCond->cond); +} + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/hals/src/linux/hc_file.c b/hals/src/linux/hc_file.c new file mode 100644 index 0000000..8974c50 --- /dev/null +++ b/hals/src/linux/hc_file.c @@ -0,0 +1,201 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "hc_file.h" +#include "securec.h" +#include +#include +#include +#include +#include "hc_log.h" +#include "hc_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define MAX_FILE_PATH_SIZE 256 +#define MAX_FOLDER_NAME_SIZE 128 + +typedef struct { + FileIdEnum fileId; + const char *filePath; +} FileDefInfo; + +static char g_groupPath[MAX_FILE_PATH_SIZE] = { 0 }; + +static FileDefInfo g_fileDefInfo[FILE_ID_LAST] = { + { FILE_ID_GROUP, "/data/data/deviceauth/hcgroup.dat" }, +}; + +void SetFilePath(FileIdEnum fileId, const char *path) +{ + if (path == NULL) { + LOGE("Invalid path param"); + return; + } + if (sprintf_s(g_groupPath, MAX_FILE_PATH_SIZE, "%s", path) != -1) { + g_fileDefInfo[fileId].filePath = g_groupPath; + } +} + +static int32_t CreateDirectory(const char *filePath) +{ + int32_t ret; + errno_t eno; + char *chPtr = NULL; + char dirCache[MAX_FOLDER_NAME_SIZE]; + + chPtr = (char *)filePath; + while ((chPtr = strchr(chPtr, '/')) != NULL) { + unsigned long len = (unsigned long)((uintptr_t)chPtr - (uintptr_t)filePath); + if (len == 0ul) { + chPtr++; + continue; + } + eno = memcpy_s(dirCache, sizeof(dirCache), filePath, len); + if (eno != EOK) { + LOGE("memory copy failed"); + return -1; + } + dirCache[len] = 0; + if (access(dirCache, F_OK) != 0) { + ret = mkdir(dirCache, S_IRWXU); + if (ret != 0) { + LOGE("make dir failed, err code %d", ret); + return -1; + } + } + chPtr++; + } + return 0; +} + +static FILE *HcFileOpenRead(int fileId, const char *path) +{ + (void)fileId; + return fopen(path, "rb"); +} + +static FILE *HcFileOpenWrite(int32_t fileId, const char *path) +{ + (void)fileId; + if (access(path, F_OK) != 0) { + int32_t ret = CreateDirectory(path); + if (ret != 0) { + return NULL; + } + } + return fopen(path, "w+"); +} + +int HcFileOpen(int fileId, int mode, FileHandle *file) +{ + if (fileId < 0 || fileId >= FILE_ID_LAST || file == NULL) { + return -1; + } + if (mode == MODE_FILE_READ) { + file->pfd = HcFileOpenRead(fileId, g_fileDefInfo[fileId].filePath); + } else { + file->pfd = HcFileOpenWrite(fileId, g_fileDefInfo[fileId].filePath); + } + if (file->pfd == NULL) { + return -1; + } else { + return 0; + } +} + +int HcFileSize(FileHandle file) +{ + FILE *fp = (FILE *)file.pfd; + if (fp != NULL) { + if (fseek(fp, 0L, SEEK_END) != 0) { + return -1; + } + int size = ftell(fp); + if (fseek(fp, 0L, SEEK_SET) != 0) { + return -1; + } + return size; + } else { + return -1; + } +} + +int HcFileRead(FileHandle file, void *dst, int dstSize) +{ + FILE *fp = (FILE *)file.pfd; + if (fp == NULL || dstSize < 0 || dst == NULL) { + return -1; + } + + char *dstBuffer = (char *)dst; + int total = 0; + while (total < dstSize) { + int readCount = fread(dstBuffer + total, 1, dstSize - total, fp); + if ((readCount < 0) || (readCount > (dstSize - total))) { + return -1; + } + if (readCount == 0) { + return total; + } + total += readCount; + } + + return total; +} + +int HcFileWrite(FileHandle file, const void *src, int srcSize) +{ + FILE *fp = (FILE *)file.pfd; + if (fp == NULL || srcSize < 0 || src == NULL) { + return -1; + } + + const char *srcBuffer = (const char *)src; + int total = 0; + while (total < srcSize) { + int writeCount = fwrite(srcBuffer + total, 1, srcSize - total, fp); + if (writeCount < 0 || writeCount > (srcSize - total)) { + return -1; + } + total += writeCount; + } + return total; +} + +void HcFileClose(FileHandle file) +{ + FILE *fp = (FILE *)file.pfd; + if (fp == NULL) { + return; + } + + fclose(fp); +} + +void HcFileRemove(int fileId) +{ + if (fileId >= FILE_ID_LAST) { + LOGE("Invalid fileId:%d", fileId); + return; + } + unlink(g_fileDefInfo[fileId].filePath); +} + +#ifdef __cplusplus +} +#endif diff --git a/hals/src/linux/hc_init_protection.c b/hals/src/linux/hc_init_protection.c new file mode 100755 index 0000000..ae92510 --- /dev/null +++ b/hals/src/linux/hc_init_protection.c @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "hc_init_protection.h" +#include + +static bool g_isInitialized = false; + +int CheckInit() +{ + if (g_isInitialized) { + return FINISH_INIT; + } + return CONTINUE_INIT; +} + +int CheckDestroy() +{ + if (!g_isInitialized) { + return FINISH_DESTROY; + } + return CONTINUE_DESTROY; +} + +void SetInitStatus() +{ + g_isInitialized = true; +} + +void SetDeInitStatus() +{ + g_isInitialized = false; +} \ No newline at end of file diff --git a/hals/src/linux/hc_mutex.c b/hals/src/linux/hc_mutex.c new file mode 100644 index 0000000..e1b8a0a --- /dev/null +++ b/hals/src/linux/hc_mutex.c @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "hc_mutex.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int MutexLock(HcMutex* mutex) +{ + if (mutex == NULL) { + return -1; + } + return -pthread_mutex_lock(&mutex->mutex); +} + +void MutexUnlock(HcMutex* mutex) +{ + if (mutex == NULL) { + return; + } + pthread_mutex_unlock(&mutex->mutex); +} + +int32_t InitHcMutex(struct HcMutexT* mutex) +{ + if (mutex == NULL) { + return -1; + } + int res = pthread_mutex_init(&mutex->mutex, NULL); + if (res != 0) { + return res; + } + mutex->lock = MutexLock; + mutex->unlock = MutexUnlock; + return res; +} + +void DestroyHcMutex(struct HcMutexT* mutex) +{ + if (mutex == NULL) { + return; + } + pthread_mutex_destroy(&mutex->mutex); +} + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/hals/src/linux/hc_thread.c b/hals/src/linux/hc_thread.c new file mode 100644 index 0000000..6eb17f3 --- /dev/null +++ b/hals/src/linux/hc_thread.c @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "hc_thread.h" +#include "hc_error.h" +#include "hc_log.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define MAX_THREAD_STACK_SIZE (8 * 1024 * 1024) + +void* StaticThreadFunc(void* args) +{ + HcThread* thread = (HcThread*)args; + if (thread == NULL) { + return NULL; + } + + if (thread->threadFunc) { + thread->threadFunc(args); + } + thread->threadLock.lock(&thread->threadLock); + thread->running = HC_FALSE; + thread->threadWaitObj.notifyWithoutLock(&thread->threadWaitObj); + thread->threadLock.unlock(&thread->threadLock); + return 0; +} + +int Start(struct HcThreadT* thread) +{ + if (thread == NULL) { + return HAL_ERR_NULL_PTR; + } + thread->threadLock.lock(&thread->threadLock); + if (thread->running) { + thread->threadLock.unlock(&thread->threadLock); + return 0; + } + thread->running = HC_TRUE; + + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + + if (thread->stackSize > 0 && thread->stackSize <= MAX_THREAD_STACK_SIZE) { + pthread_attr_setstacksize(&attr, thread->stackSize); + } + + int result = pthread_create(&thread->thread, &attr, StaticThreadFunc, thread); + pthread_attr_destroy(&attr); + + if (result != 0) { + LOGE("pthread_create failed."); + thread->running = HC_FALSE; + } + thread->threadLock.unlock(&thread->threadLock); + return result; +} + +void Join(struct HcThreadT* thread) +{ + if (thread == NULL) { + return; + } + thread->threadLock.lock(&thread->threadLock); + if (thread->running) { + thread->threadWaitObj.waitWithoutLock(&thread->threadWaitObj); + } + thread->threadLock.unlock(&thread->threadLock); +} + +void BizWait(struct HcThreadT* thread) +{ + if (thread == NULL) { + return; + } + thread->bizWaitObj.wait(&thread->bizWaitObj); +} + +void BizNotify(struct HcThreadT* thread) +{ + if (thread == NULL) { + return; + } + thread->bizWaitObj.notify(&thread->bizWaitObj); +} + +int32_t InitThread(HcThread* thread, ThreadFunc func, size_t stackSize, const char* threadName) +{ + if (thread == NULL) { + return -1; + } + + thread->threadFunc = func; + thread->start = Start; + thread->wait = BizWait; + thread->notify = BizNotify; + thread->join = Join; + thread->stackSize = stackSize; + thread->running = HC_FALSE; + thread->name = CreateString(); + if (StringSetPointer(&thread->name, threadName) != HC_TRUE) { + return -1; + } + + int32_t res = InitHcMutex(&thread->threadLock); + if (res != 0) { + DeleteString(&thread->name); + return res; + } + res = InitHcCond(&thread->threadWaitObj, &thread->threadLock); + if (res != 0) { + DeleteString(&thread->name); + DestroyHcMutex(&thread->threadLock); + return res; + } + res = InitHcCond(&thread->bizWaitObj, NULL); + if (res != 0) { + DeleteString(&thread->name); + DestroyHcMutex(&thread->threadLock); + DestroyHcCond(&thread->threadWaitObj); + } + return res; +} + +void DestroyThread(HcThread* thread) +{ + if (thread == NULL) { + return; + } + + DestroyHcCond(&thread->bizWaitObj); + DestroyHcCond(&thread->threadWaitObj); + DestroyHcMutex(&thread->threadLock); + DeleteString(&thread->name); +} + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/hals/src/linux/hc_time.c b/hals/src/linux/hc_time.c new file mode 100755 index 0000000..4fac40f --- /dev/null +++ b/hals/src/linux/hc_time.c @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "hc_time.h" +#include +#include +#include "hc_log.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int64_t HcGetCurTime() +{ + struct timespec start; + int res = clock_gettime(CLOCK_MONOTONIC, &start); + if (res != 0) { + LOGE("clock_gettime failed, res:%d", res); + return -1; + } + return start.tv_sec; +} + +int64_t HcGetIntervalTime(int64_t startTime) +{ + if (startTime < 0) { + LOGE("Start time is invalid"); + return -1; + } + struct timespec end; + int res = clock_gettime(CLOCK_MONOTONIC, &end); + if (res != 0) { + LOGE("clock_gettime failed, res:%d", res); + return -1; + } + if (end.tv_sec < startTime) { + LOGE("End time is invalid"); + return -1; + } + return (end.tv_sec - startTime); +} + +#ifdef __cplusplus +} +#endif diff --git a/hals/src/linux/hc_types.c b/hals/src/linux/hc_types.c new file mode 100755 index 0000000..7596934 --- /dev/null +++ b/hals/src/linux/hc_types.c @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "hc_types.h" +#include "hc_log.h" +#include "securec.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void* HcMalloc(uint32_t size, char val) +{ + if (size == 0) { + LOGE("Malloc size is invalid."); + return NULL; + } + void* addr = malloc(size); + if (addr != NULL) { + (void)memset_s(addr, size, val, size); + } + return addr; +} + +void HcFree(void* addr) +{ + if (addr != NULL) { + free(addr); + } +} + +uint32_t HcStrlen(const char *str) +{ + if (str == NULL) { + return 0; + } + const char *p = str; + while (*p++ != '\0') {} + return p - str - 1; +} + +#ifdef __cplusplus +} +#endif diff --git a/hals/src/liteos/L0/hc_init_protection.c b/hals/src/liteos/L0/hc_init_protection.c new file mode 100755 index 0000000..6d54ab1 --- /dev/null +++ b/hals/src/liteos/L0/hc_init_protection.c @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "hc_init_protection.h" +#include +#include +#include "hc_log.h" +#include "hc_thread.h" +#include "ohos_init.h" + +static HcMutex g_countMutex; +static int g_singleCount = 0; + +int CheckInit() +{ + g_countMutex.lock(&g_countMutex); + if (g_singleCount < 0) { + g_singleCount = 0; + } else if (g_singleCount > 0) { + g_singleCount++; + g_countMutex.unlock(&g_countMutex); + return FINISH_INIT; + } + g_countMutex.unlock(&g_countMutex); + return CONTINUE_INIT; +} + +int CheckDestroy() +{ + g_countMutex.lock(&g_countMutex); + if (g_singleCount == 0) { + g_countMutex.unlock(&g_countMutex); + return FINISH_DESTROY; + } + if (g_singleCount < 0) { + g_singleCount = 0; + g_countMutex.unlock(&g_countMutex); + return FINISH_DESTROY; + } + if (g_singleCount > 1) { + g_singleCount--; + g_countMutex.unlock(&g_countMutex); + return FINISH_DESTROY; + } + g_countMutex.unlock(&g_countMutex); + return CONTINUE_DESTROY; +} + +void SetInitStatus() +{ + g_countMutex.lock(&g_countMutex); + g_singleCount = 1; + g_countMutex.unlock(&g_countMutex); + return; +} + +void SetDeInitStatus() +{ + g_countMutex.lock(&g_countMutex); + g_singleCount = 0; + g_countMutex.unlock(&g_countMutex); + return; +} + +void InitSecurityDevAuth() +{ + int32_t res = InitHcMutex(&g_countMutex); + if (res != 0) { + LOGE("When init security auth, init mutex failed"); + } +} +SYS_SERVICE_INIT(InitSecurityDevAuth); + +void DestroySecurityDevAuth() +{ + DestroyHcMutex(&g_countMutex); +} \ No newline at end of file diff --git a/hals/src/liteos/L0/huks_adapter.c b/hals/src/liteos/L0/huks_adapter.c new file mode 100755 index 0000000..c428379 --- /dev/null +++ b/hals/src/liteos/L0/huks_adapter.c @@ -0,0 +1,554 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "huks_adapter.h" +#include "common_util.h" +#include "hc_error.h" +#include "hc_file.h" +#include "hc_log.h" +#include "hks_api.h" +#include "hks_param.h" +#include "hks_type.h" + +static int32_t BaseCheckParams(const Uint8Buff **inParams, const char **paramTags, uint32_t len) +{ + for (uint32_t i = 0; i < len; i++) { + CHECK_PTR_RETURN_ERROR_CODE(inParams[i], paramTags[i]); + CHECK_PTR_RETURN_ERROR_CODE(inParams[i]->val, paramTags[i]); + CHECK_LEN_ZERO_RETURN_ERROR_CODE(inParams[i]->length, paramTags[i]); + } + return HAL_SUCCESS; +} + +static int32_t ConstructParamSet(struct HksParamSet **out, const struct HksParam *inParam, + const uint32_t inParamNum) +{ + struct HksParamSet *paramSet = NULL; + int32_t ret = HksInitParamSet(¶mSet); + if (ret != HKS_SUCCESS) { + LOGE("init param set failed, ret = %d", ret); + return HAL_ERR_INIT_PARAM_SET_FAILED; + } + + ret = HksAddParams(paramSet, inParam, inParamNum); + if (ret != HKS_SUCCESS) { + LOGE("add param failed, ret = %d", ret); + HksFreeParamSet(¶mSet); + return HAL_ERR_ADD_PARAM_FAILED; + } + + ret = HksBuildParamSet(¶mSet); + if (ret != HKS_SUCCESS) { + LOGE("build param set failed, ret = %d", ret); + HksFreeParamSet(¶mSet); + return HAL_ERR_BUILD_PARAM_SET_FAILED; + } + + *out = paramSet; + return HAL_SUCCESS; +} + +static int32_t InitHks() +{ + int32_t res = HksInitialize(); + if (res == HKS_SUCCESS) { + return HAL_SUCCESS; + } + + if ((res != HKS_ERROR_INVALID_KEY_FILE) && (res != HKS_ERROR_CRYPTO_ENGINE_ERROR) && + (res != HKS_ERROR_UPDATE_ROOT_KEY_MATERIAL_FAIL)) { + LOGE("Hks: Init hks failed, res: %d.", res); + return HAL_ERR_INIT_FAILED; + } + + LOGD("Hks: The local hks file needs to be refreshed!"); + LOGI("Start to delete local database file!"); + HcFileRemove(FILE_ID_GROUP); + LOGI("Delete local database file successfully!"); + res = HksRefreshKeyInfo(); + if (res != HKS_SUCCESS) { + LOGE("Hks: HksRefreshKeyInfo failed, res: %d.", res); + return HAL_ERR_INIT_FAILED; + } + res = HksInitialize(); + if (res != HKS_SUCCESS) { + LOGE("Hks: Init hks failed, res: %d.", res); + return HAL_ERR_INIT_FAILED; + } + + return HAL_SUCCESS; +} + +static int32_t Sha256(const Uint8Buff *message, Uint8Buff *hash) +{ + CHECK_PTR_RETURN_ERROR_CODE(message, "message"); + CHECK_PTR_RETURN_ERROR_CODE(message->val, "message->val"); + CHECK_LEN_ZERO_RETURN_ERROR_CODE(message->length, "message->length"); + + CHECK_PTR_RETURN_ERROR_CODE(hash, "hash"); + CHECK_PTR_RETURN_ERROR_CODE(hash->val, "hash->val"); + CHECK_LEN_EQUAL_RETURN(hash->length, SHA256_LEN, "hash->length"); + + struct HksBlob srcBlob = { message->length, message->val }; + struct HksBlob hashBlob = { hash->length, hash->val }; + struct HksParamSet *paramSet = NULL; + struct HksParam digestParam[] = { + { + .tag = HKS_TAG_DIGEST, + .uint32Param = HKS_DIGEST_SHA256 + } + }; + int32_t ret = ConstructParamSet(¶mSet, digestParam, CAL_ARRAY_SIZE(digestParam)); + if (ret != HAL_SUCCESS) { + LOGE("construct param set failed, ret = %d", ret); + return ret; + } + + ret = HksHash(paramSet, &srcBlob, &hashBlob); + if (ret != HKS_SUCCESS || hashBlob.size != SHA256_LEN) { + HksFreeParamSet(¶mSet); + return HAL_FAILED; + } + + HksFreeParamSet(¶mSet); + return HAL_SUCCESS; +} + +static int32_t GenerateRandom(Uint8Buff *rand) +{ + CHECK_PTR_RETURN_ERROR_CODE(rand, "rand"); + CHECK_PTR_RETURN_ERROR_CODE(rand->val, "rand->val"); + CHECK_LEN_ZERO_RETURN_ERROR_CODE(rand->length, "rand->length"); + + struct HksBlob randBlob = { rand->length, rand->val }; + int32_t ret = HksGenerateRandom(NULL, &randBlob); + if (ret != HKS_SUCCESS) { + LOGE("Generate random failed, ret: %d", ret); + return HAL_FAILED; + } + + return HAL_SUCCESS; +} + +static int32_t CheckKeyExist(const Uint8Buff *keyAlias) +{ + CHECK_PTR_RETURN_ERROR_CODE(keyAlias, "keyAlias"); + CHECK_PTR_RETURN_ERROR_CODE(keyAlias->val, "keyAlias->val"); + CHECK_LEN_ZERO_RETURN_ERROR_CODE(keyAlias->length, "keyAlias->length"); + + struct HksBlob keyAliasBlob = { keyAlias->length, keyAlias->val }; + int32_t ret = HksKeyExist(&keyAliasBlob, NULL); + if (ret != HKS_SUCCESS) { + LOGE("Check key exist failed, ret = %d", ret); + return HAL_FAILED; + } + + return HAL_SUCCESS; +} + +static int32_t DeleteKey(const Uint8Buff *keyAlias) +{ + CHECK_PTR_RETURN_ERROR_CODE(keyAlias, "keyAlias"); + CHECK_PTR_RETURN_ERROR_CODE(keyAlias->val, "keyAlias->val"); + CHECK_LEN_ZERO_RETURN_ERROR_CODE(keyAlias->length, "keyAlias->length"); + + struct HksBlob keyAliasBlob = { keyAlias->length, keyAlias->val }; + int32_t ret = HksDeleteKey(&keyAliasBlob, NULL); + if (ret == HKS_ERROR_NOT_EXIST) { + LOGI("Key not exists."); + return HAL_SUCCESS; + } + if (ret != HKS_SUCCESS) { + LOGE("Delete key failed, ret = %d", ret); + return HAL_FAILED; + } + + return HAL_SUCCESS; +} + +static int32_t ComputeHmac(const Uint8Buff *key, const Uint8Buff *message, Uint8Buff *outHmac, bool isAlias) +{ + const Uint8Buff *inParams[] = { key, message, outHmac }; + const char *paramTags[] = {"key", "message", "outHmac"}; + int32_t ret = BaseCheckParams(inParams, paramTags, CAL_ARRAY_SIZE(inParams)); + if (ret != HAL_SUCCESS) { + return ret; + } + CHECK_LEN_EQUAL_RETURN(outHmac->length, HMAC_LEN, "outHmac->length"); + + struct HksBlob keyBlob = { key->length, key->val }; + struct HksBlob srcBlob = { message->length, message->val }; + struct HksBlob hmacBlob = { outHmac->length, outHmac->val }; + struct HksParamSet *paramSet = NULL; + struct HksParam hmacParam[] = { + { + .tag = HKS_TAG_PURPOSE, + .uint32Param = HKS_KEY_PURPOSE_MAC + }, { + .tag = HKS_TAG_DIGEST, + .uint32Param = HKS_DIGEST_SHA256 + }, { + .tag = HKS_TAG_IS_KEY_ALIAS, + .boolParam = isAlias + } + }; + ret = ConstructParamSet(¶mSet, hmacParam, CAL_ARRAY_SIZE(hmacParam)); + if (ret != HAL_SUCCESS) { + LOGE("construct param set failed, ret = %d", ret); + return ret; + } + + ret = HksMac(&keyBlob, paramSet, &srcBlob, &hmacBlob); + if (ret != HKS_SUCCESS || hmacBlob.size != HMAC_LEN) { + LOGE("Hmac failed, ret: %d", ret); + HksFreeParamSet(¶mSet); + return HAL_FAILED; + } + + HksFreeParamSet(¶mSet); + return HAL_SUCCESS; +} + +static int32_t ComputeHkdf(const Uint8Buff *baseKey, const Uint8Buff *salt, const Uint8Buff *keyInfo, + Uint8Buff *outHkdf, bool isAlias) +{ + const Uint8Buff *inParams[] = { baseKey, salt, outHkdf }; + const char *paramTags[] = { "baseKey", "salt", "outHkdf" }; + int32_t ret = BaseCheckParams(inParams, paramTags, CAL_ARRAY_SIZE(inParams)); + if (ret != HAL_SUCCESS) { + return ret; + } + + struct HksBlob srcKeyBlob = { baseKey->length, baseKey->val }; + struct HksBlob saltBlob = { salt->length, salt->val }; + struct HksBlob keyInfoBlob = { 0, NULL }; + if (keyInfo != NULL) { + keyInfoBlob.size = keyInfo->length; + keyInfoBlob.data = keyInfo->val; + } + struct HksBlob derivedKeyBlob = { outHkdf->length, outHkdf->val }; + + struct HksParamSet *paramSet = NULL; + struct HksParam hkdfParam[] = { + { + .tag = HKS_TAG_PURPOSE, + .uint32Param = HKS_KEY_PURPOSE_DERIVE + }, { + .tag = HKS_TAG_ALGORITHM, + .uint32Param = HKS_ALG_HKDF + }, { + .tag = HKS_TAG_DIGEST, + .uint32Param = HKS_DIGEST_SHA256 + }, { + .tag = HKS_TAG_SALT, + .blob = saltBlob + }, { + .tag = HKS_TAG_INFO, + .blob = keyInfoBlob + }, { + .tag = HKS_TAG_IS_KEY_ALIAS, + .boolParam = isAlias + } + }; + + ret = ConstructParamSet(¶mSet, hkdfParam, CAL_ARRAY_SIZE(hkdfParam)); + if (ret != HAL_SUCCESS) { + return ret; + } + + ret = HksDeriveKey(paramSet, &srcKeyBlob, &derivedKeyBlob); + if (ret != HKS_SUCCESS) { + LOGE("Key derivation failed, ret: %d", ret); + HksFreeParamSet(¶mSet); + return HAL_FAILED; + } + + HksFreeParamSet(¶mSet); + return HAL_SUCCESS; +} + +static int32_t CheckAesGcmEncryptParam(const Uint8Buff *key, const Uint8Buff *plain, const GcmParam *encryptInfo, + Uint8Buff *outCipher) +{ + const Uint8Buff *inParams[] = { key, plain, outCipher }; + const char* paramTags[] = { "key", "plain", "outCipher" }; + int32_t ret = BaseCheckParams(inParams, paramTags, CAL_ARRAY_SIZE(inParams)); + if (ret != HAL_SUCCESS) { + return ret; + } + + CHECK_PTR_RETURN_ERROR_CODE(encryptInfo, "encryptInfo"); + CHECK_PTR_RETURN_ERROR_CODE(encryptInfo->aad, "aad"); + CHECK_LEN_ZERO_RETURN_ERROR_CODE(encryptInfo->aadLen, "aadLen"); + CHECK_PTR_RETURN_ERROR_CODE(encryptInfo->nonce, "nonce"); + CHECK_LEN_LOWER_RETURN(encryptInfo->nonceLen, HKS_AE_NONCE_LEN, "nonceLen"); + CHECK_LEN_LOWER_RETURN(outCipher->length, plain->length + HKS_AE_TAG_LEN, "outCipher"); + + return HAL_SUCCESS; +} + +static int32_t AesGcmEncrypt(const Uint8Buff *key, const Uint8Buff *plain, + const GcmParam *encryptInfo, bool isAlias, Uint8Buff *outCipher) +{ + int32_t ret = CheckAesGcmEncryptParam(key, plain, encryptInfo, outCipher); + if (ret != HAL_SUCCESS) { + return ret; + } + + struct HksBlob keyBlob = { key->length, key->val }; + struct HksBlob plainBlob = { plain->length, plain->val }; + struct HksBlob cipherBlob = { outCipher->length, outCipher->val }; + + struct HksParamSet *paramSet = NULL; + struct HksParam encryptParam[] = { + { + .tag = HKS_TAG_PURPOSE, + .uint32Param = HKS_KEY_PURPOSE_ENCRYPT + }, { + .tag = HKS_TAG_ALGORITHM, + .uint32Param = HKS_ALG_AES + }, { + .tag = HKS_TAG_BLOCK_MODE, + .uint32Param = HKS_MODE_GCM + }, { + .tag = HKS_TAG_PADDING, + .uint32Param = HKS_PADDING_NONE + }, { + .tag = HKS_TAG_NONCE, + .blob = { encryptInfo->nonceLen, encryptInfo->nonce } + }, { + .tag = HKS_TAG_ASSOCIATED_DATA, + .blob = { encryptInfo->aadLen, encryptInfo->aad } + }, { + .tag = HKS_TAG_IS_KEY_ALIAS, + .boolParam = isAlias + } + }; + + ret = ConstructParamSet(¶mSet, encryptParam, CAL_ARRAY_SIZE(encryptParam)); + if (ret != HAL_SUCCESS) { + LOGE("construct param set failed, ret = %d", ret); + return ret; + } + + ret = HksEncrypt(&keyBlob, paramSet, &plainBlob, &cipherBlob); + if (ret != HKS_SUCCESS) { + LOGE("Aes-gcm encrypt failed, ret: %d", ret); + HksFreeParamSet(¶mSet); + return HAL_FAILED; + } + + HksFreeParamSet(¶mSet); + return HAL_SUCCESS; +} + +static int32_t CheckAesGcmDecryptParam(const Uint8Buff *key, const Uint8Buff *cipher, const GcmParam *decryptInfo, + Uint8Buff *outPlain) +{ + const Uint8Buff *inParams[] = { key, cipher, outPlain }; + const char *paramTags[] = { "key", "cipher", "outPlain" }; + int32_t ret = BaseCheckParams(inParams, paramTags, CAL_ARRAY_SIZE(inParams)); + if (ret != HAL_SUCCESS) { + return ret; + } + + CHECK_PTR_RETURN_ERROR_CODE(decryptInfo, "decryptInfo"); + CHECK_PTR_RETURN_ERROR_CODE(decryptInfo->aad, "aad"); + CHECK_LEN_ZERO_RETURN_ERROR_CODE(decryptInfo->aadLen, "aadLen"); + CHECK_PTR_RETURN_ERROR_CODE(decryptInfo->nonce, "nonce"); + CHECK_LEN_LOWER_RETURN(decryptInfo->nonceLen, HKS_AE_NONCE_LEN, "nonceLen"); + CHECK_LEN_LOWER_RETURN(outPlain->length, cipher->length - HKS_AE_TAG_LEN, "outPlain"); + + return HAL_SUCCESS; +} + +static int32_t AesGcmDecrypt(const Uint8Buff *key, const Uint8Buff *cipher, + const GcmParam *decryptInfo, bool isAlias, Uint8Buff *outPlain) +{ + int32_t ret = CheckAesGcmDecryptParam(key, cipher, decryptInfo, outPlain); + if (ret != HAL_SUCCESS) { + return ret; + } + + struct HksBlob keyBlob = { key->length, key->val }; + struct HksBlob cipherBlob = { cipher->length, cipher->val }; + struct HksBlob plainBlob = { outPlain->length, outPlain->val }; + + struct HksParamSet *paramSet = NULL; + struct HksParam decryptParam[] = { + { + .tag = HKS_TAG_PURPOSE, + .uint32Param = HKS_KEY_PURPOSE_DECRYPT + }, { + .tag = HKS_TAG_ALGORITHM, + .uint32Param = HKS_ALG_AES + }, { + .tag = HKS_TAG_BLOCK_MODE, + .uint32Param = HKS_MODE_GCM + }, { + .tag = HKS_TAG_PADDING, + .uint32Param = HKS_PADDING_NONE + }, { + .tag = HKS_TAG_NONCE, + .blob = { decryptInfo->nonceLen, decryptInfo->nonce } + }, { + .tag = HKS_TAG_ASSOCIATED_DATA, + .blob = { decryptInfo->aadLen, decryptInfo->aad } + }, { + .tag = HKS_TAG_IS_KEY_ALIAS, + .boolParam = isAlias + } + }; + + ret = ConstructParamSet(¶mSet, decryptParam, CAL_ARRAY_SIZE(decryptParam)); + if (ret != HAL_SUCCESS) { + LOGE("construct param set failed, ret = %d", ret); + return ret; + } + + ret = HksDecrypt(&keyBlob, paramSet, &cipherBlob, &plainBlob); + if (ret != HKS_SUCCESS) { + LOGE("Aes-gcm decrypt failed, ret: %d", ret); + HksFreeParamSet(¶mSet); + return HAL_FAILED; + } + + HksFreeParamSet(¶mSet); + return HAL_SUCCESS; +} + +static int32_t CheckImportAsymmetricKeyParam(const Uint8Buff *keyAlias, const Uint8Buff *authToken, + const Uint8Buff *authId, const int32_t userType, const int32_t pairType) +{ + const Uint8Buff *inParams[] = { keyAlias, authToken, authId }; + const char *paramTags[] = { "keyAlias", "authToken", "authId" }; + int32_t ret = BaseCheckParams(inParams, paramTags, CAL_ARRAY_SIZE(inParams)); + if (ret != HAL_SUCCESS) { + return ret; + } + + CHECK_LEN_HIGHER_RETURN(pairType, PAIR_TYPE_END - 1, "pairType"); + + return HAL_SUCCESS; +} + +static int32_t ConstructImportAsymmetricKeyParam(struct HksParamSet **paramSet, uint32_t keyLen, uint32_t roleInfo, + const struct HksBlob *authIdBlob) +{ + struct HksParam importParam[] = { + { + .tag = HKS_TAG_ALGORITHM, + .uint32Param = HKS_ALG_AES + }, { + .tag = HKS_TAG_KEY_SIZE, + .uint32Param = keyLen * BITS_PER_BYTE + }, { + .tag = HKS_TAG_PADDING, + .uint32Param = HKS_PADDING_NONE + }, { + .tag = HKS_TAG_KEY_AUTH_ID, + .blob = *authIdBlob + }, { + .tag = HKS_TAG_IS_ALLOWED_WRAP, + .boolParam = false + }, { + .tag = HKS_TAG_PURPOSE, + .uint32Param = HKS_KEY_PURPOSE_MAC + }, { + .tag = HKS_TAG_KEY_ROLE, + .uint32Param = roleInfo + }, { + .tag = HKS_TAG_BLOCK_MODE, + .uint32Param = HKS_MODE_GCM + }, { + .tag = HKS_TAG_DIGEST, + .uint32Param = HKS_DIGEST_SHA256 + } + }; + + int ret = ConstructParamSet(paramSet, importParam, CAL_ARRAY_SIZE(importParam)); + if (ret != HAL_SUCCESS) { + LOGE("construct decrypt param set failed, ret = %d", ret); + return ret; + } + + return ret; +} + +static int32_t ImportAsymmetricKey(const Uint8Buff *keyAlias, const Uint8Buff *authToken, const ExtraInfo *exInfo) +{ + int32_t ret = CheckImportAsymmetricKeyParam(keyAlias, authToken, &exInfo->authId, exInfo->userType, + exInfo->pairType); + if (ret != HAL_SUCCESS) { + return ret; + } + + struct HksBlob keyAliasBlob = { keyAlias->length, keyAlias->val }; + struct HksBlob pubKeyBlob = { authToken->length, authToken->val }; + + struct HksBlob authIdBlob = { exInfo->authId.length, exInfo->authId.val }; + union KeyRoleInfoUnion roleInfoUnion; + roleInfoUnion.roleInfoStruct.userType = (uint8_t)exInfo->userType; + roleInfoUnion.roleInfoStruct.pairType = (uint8_t)exInfo->pairType; + roleInfoUnion.roleInfoStruct.reserved1 = (uint8_t)0; + roleInfoUnion.roleInfoStruct.reserved2 = (uint8_t)0; + + struct HksParamSet *paramSet = NULL; + ret = ConstructImportAsymmetricKeyParam(¶mSet, authToken->length, roleInfoUnion.roleInfo, &authIdBlob); + if (ret != HAL_SUCCESS) { + LOGE("construct param set failed, ret = %d", ret); + return ret; + } + + ret = HksImportKey(&keyAliasBlob, paramSet, &pubKeyBlob); + if (ret != HKS_SUCCESS) { + LOGE("HksImportKey failed, ret: %d", ret); + HksFreeParamSet(¶mSet); + return ret; + } + + HksFreeParamSet(¶mSet); + return HAL_SUCCESS; +} + +static const AlgLoader g_huksLoader = { + InitHks, + Sha256, + GenerateRandom, + ComputeHmac, + ComputeHkdf, + ImportAsymmetricKey, + CheckKeyExist, + DeleteKey, + AesGcmEncrypt, + AesGcmDecrypt, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL +}; + +const AlgLoader *GetRealLoaderInstance() +{ + return &g_huksLoader; +} \ No newline at end of file diff --git a/hals/src/liteos/L1/hc_init_protection.c b/hals/src/liteos/L1/hc_init_protection.c new file mode 100755 index 0000000..cd270a8 --- /dev/null +++ b/hals/src/liteos/L1/hc_init_protection.c @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "hc_init_protection.h" +#include +#include + +static bool g_isInitialized = false; + +int CheckInit() +{ + if (g_isInitialized) { + return FINISH_INIT; + } + return CONTINUE_INIT; +} + +int CheckDestroy() +{ + if (!g_isInitialized) { + return FINISH_DESTROY; + } + return CONTINUE_DESTROY; +} + +void SetInitStatus() +{ + g_isInitialized = true; +} + +void SetDeInitStatus() +{ + g_isInitialized = false; +} \ No newline at end of file diff --git a/hals/src/liteos/hc_condition.c b/hals/src/liteos/hc_condition.c new file mode 100644 index 0000000..ae191c0 --- /dev/null +++ b/hals/src/liteos/hc_condition.c @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "hc_condition.h" + +int HcCondWait(struct HcConditionT* hcCond) +{ + if (hcCond == NULL) { + return -1; + } + + return sem_wait(&hcCond->sem); +} + +void HcCondNotify(struct HcConditionT* hcCond) +{ + if (hcCond == NULL) { + return; + } + + sem_post(&hcCond->sem); +} + +int32_t InitHcCond(HcCondition* hcCond, HcMutex* mutex) +{ + (void)mutex; + if (hcCond == NULL) { + return -1; + } + hcCond->wait = HcCondWait; + hcCond->notify = HcCondNotify; + hcCond->waitWithoutLock = HcCondWait; + hcCond->notifyWithoutLock = HcCondNotify; + + // init the signal value to zero + return sem_init(&hcCond->sem, 0, 0); +} + +void DestroyHcCond(HcCondition* hcCond) +{ + if (hcCond == NULL) { + return; + } + + sem_destroy(&hcCond->sem); +} \ No newline at end of file diff --git a/hals/src/liteos/hc_file.c b/hals/src/liteos/hc_file.c new file mode 100755 index 0000000..17d31f6 --- /dev/null +++ b/hals/src/liteos/hc_file.c @@ -0,0 +1,215 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "hc_file.h" +#include +#include +#include +#include +#include +#include +#include "common_defs.h" +#include "hc_error.h" +#include "hc_log.h" + +#define MAX_FILE_PATH_SIZE 256 +#define MAX_FOLDER_NAME_SIZE 128 +#define GET_FOLDER_OK 0 +#define GET_FOLDER_FAILED (-1) +#define GET_FILE_OK 1 +#define DEFAULT_FILE_PERMISSION 0666 + +typedef struct { + FileIdEnum fileId; + const char* filePath; +} FileDefInfo; + +static FileDefInfo g_fileDefInfo[FILE_ID_LAST] = { + { FILE_ID_GROUP, "user/Hichain/hcgroup.dat" } +}; + +static char g_groupPath[MAX_FILE_PATH_SIZE] = { 0 }; + +void SetFilePath(FileIdEnum fileId, const char *path) +{ + if (path == NULL) { + LOGE("Invalid path param"); + return; + } + if (sprintf_s(g_groupPath, MAX_FILE_PATH_SIZE, "%s", path) != -1) { + g_fileDefInfo[fileId].filePath = g_groupPath; + } +} + +int GetNextFolder(const char* filePath, int* beginPos, char* dst, int size) +{ + int pos = (*beginPos); + while (1) { + char c = filePath[pos++]; + if (c == '\0') { + if (memcpy_s(dst, size, filePath, pos - 1) != EOK) { + return GET_FOLDER_FAILED; + } + dst[pos - 1] = '\0'; + (*beginPos) = pos; + return GET_FILE_OK; + } else if (c == '/') { + if (memcpy_s(dst, size, filePath, pos - 1) != EOK) { + return GET_FOLDER_FAILED; + } + dst[pos - 1] = '\0'; + (*beginPos) = pos; + return GET_FOLDER_OK; + } else { + if (pos >= size) { + (*beginPos) = pos; + return GET_FOLDER_FAILED; + } + } + } +} + +int HcFileOpenRead(const char* path) +{ + return open(path, O_RDONLY); +} + +static int IsFileValid(const char *path) +{ + struct stat fileStat; + int32_t ret = stat(path, &fileStat); + if (ret == -1) { + if (errno == ENOENT) { + return HAL_ERR_FILE_NOT_EXIST; + } else { + LOGE("file stat failed, errno = 0x%x", errno); + return HAL_ERR_FILE; + } + } + + return 0; +} + +int HcFileOpenWrite(const char* path) +{ + char filePath[MAX_FOLDER_NAME_SIZE + 1]; + int beginPos = 0; + while (1) { + int ret = GetNextFolder(path, &beginPos, filePath, sizeof(filePath)); + if (ret == GET_FOLDER_OK) { + if (IsFileValid(filePath) == 0) { + continue; + } + if (mkdir(filePath, DEFAULT_FILE_PERMISSION) != 0) { + return -1; + } + } else if (ret == GET_FOLDER_FAILED) { + return -1; + } else { + int fd = open(filePath, O_RDWR | O_CREAT); + if (fd == -1) { + LOGE("file stat failed, errno = 0x%x", errno); + } + return fd; + } + } +} + +int HcFileOpen(int fileId, int mode, FileHandle* file) +{ + if (fileId < 0 || fileId >= FILE_ID_LAST || file == NULL) { + return -1; + } + if (mode == MODE_FILE_READ) { + file->fd = HcFileOpenRead(g_fileDefInfo[fileId].filePath); + } else { + file->fd = HcFileOpenWrite(g_fileDefInfo[fileId].filePath); + } + if (file->fd == -1) { + return -1; + } + return 0; +} + +int HcFileSize(FileHandle file) +{ + int fp = file.fd; + int size = lseek(fp, 0, SEEK_END); + (void)lseek(fp, 0, SEEK_SET); + return size; +} + +int HcFileRead(FileHandle file, void* dst, int dstSize) +{ + int fp = file.fd; + if (fp == -1 || dstSize < 0 || dst == NULL) { + return -1; + } + + char *dstBuffer = (char *)dst; + int total = 0; + while (total < dstSize) { + int readCount = read(fp, dstBuffer + total, dstSize - total); + if (readCount < 0 || readCount > (dstSize - total)) { + LOGE("read errno :%x", errno); + return -1; + } + if (readCount == 0) { + LOGE("read errno :%x", errno); + return total; + } + total += readCount; + } + + return total; +} + +int HcFileWrite(FileHandle file, const void *src, int srcSize) +{ + int fp = file.fd; + if (fp == -1 || srcSize < 0 || src == NULL) { + return -1; + } + + const char* srcBuffer = (const char*)src; + int total = 0; + while (total < srcSize) { + int writeCount = write(fp, srcBuffer + total, srcSize - total); + if (writeCount < 0 || writeCount > (srcSize - total)) { + return -1; + } + total += writeCount; + } + return total; +} + +void HcFileClose(FileHandle file) +{ + int fp = file.fd; + if (fp == 0) { + return; + } + + close(fp); +} + +void HcFileRemove(int fileId) +{ + if (fileId >= FILE_ID_LAST) { + LOGE("Invalid fileId:%d", fileId); + return; + } + unlink(g_fileDefInfo[fileId].filePath); +} \ No newline at end of file diff --git a/hals/src/liteos/hc_mutex.c b/hals/src/liteos/hc_mutex.c new file mode 100644 index 0000000..9e91f41 --- /dev/null +++ b/hals/src/liteos/hc_mutex.c @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "hc_mutex.h" + +int MutexLock(HcMutex* mutex) +{ + if (mutex == NULL) { + return -1; + } + return -pthread_mutex_lock(&mutex->mutex); +} + +void MutexUnlock(HcMutex* mutex) +{ + if (mutex == NULL) { + return; + } + pthread_mutex_unlock(&mutex->mutex); +} + +int32_t InitHcMutex(struct HcMutexT* mutex) +{ + if (mutex == NULL) { + return -1; + } + int res = pthread_mutex_init(&mutex->mutex, NULL); + if (res != 0) { + return res; + } + mutex->lock = MutexLock; + mutex->unlock = MutexUnlock; + return 0; +} + +void DestroyHcMutex(struct HcMutexT* mutex) +{ + if (mutex == NULL) { + return; + } + pthread_mutex_destroy(&mutex->mutex); +} \ No newline at end of file diff --git a/hals/src/liteos/hc_thread.c b/hals/src/liteos/hc_thread.c new file mode 100644 index 0000000..beb28fb --- /dev/null +++ b/hals/src/liteos/hc_thread.c @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "hc_thread.h" + +#define MAX_THREAD_STACK_SIZE (8 * 1024 * 1024) + +void *StaticThreadFunc(void *args) +{ + HcThread *thread = (HcThread*)args; + if (thread == NULL) { + return NULL; + } + + if (thread->threadFunc) { + thread->threadFunc(args); + } + thread->threadLock.lock(&thread->threadLock); + thread->running = HC_FALSE; + thread->threadWaitObj.notifyWithoutLock(&thread->threadWaitObj); + thread->threadLock.unlock(&thread->threadLock); + return NULL; +} + +int Start(struct HcThreadT *thread) +{ + if (thread == NULL) { + return -1; + } + thread->threadLock.lock(&thread->threadLock); + if (thread->running) { + thread->threadLock.unlock(&thread->threadLock); + return 0; + } + thread->running = HC_TRUE; + + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); + + if (thread->stackSize > 0 && thread->stackSize <= MAX_THREAD_STACK_SIZE) { + pthread_attr_setstacksize(&attr, thread->stackSize); + } + + int result = pthread_create(&thread->thread, &attr, StaticThreadFunc, thread); + pthread_attr_destroy(&attr); + if (result != 0) { + thread->running = HC_FALSE; + } + thread->threadLock.unlock(&thread->threadLock); + return result; +} + +void Join(struct HcThreadT *thread) +{ + if (thread == NULL) { + return; + } + + if (thread->running) { + thread->threadWaitObj.waitWithoutLock(&thread->threadWaitObj); + } + void *status = NULL; + pthread_join(thread->thread, &status); +} + +void BizWait(struct HcThreadT *thread) +{ + if (thread == NULL) { + return; + } + thread->bizWaitObj.wait(&thread->bizWaitObj); +} + +void BizNotify(struct HcThreadT *thread) +{ + if (thread == NULL) { + return; + } + thread->bizWaitObj.notify(&thread->bizWaitObj); +} + +int32_t InitThread(HcThread *thread, ThreadFunc func, size_t stackSize, const char *threadName) +{ + if (thread == NULL) { + return -1; + } + + thread->threadFunc = func; + thread->start = Start; + thread->wait = BizWait; + thread->notify = BizNotify; + thread->join = Join; + thread->stackSize = stackSize; + thread->running = HC_FALSE; + thread->name = CreateString(); + if (StringSetPointer(&thread->name, threadName) != HC_TRUE) { + return -1; + } + + int32_t res = InitHcMutex(&thread->threadLock); + if (res != 0) { + DeleteString(&thread->name); + return res; + } + res = InitHcCond(&thread->threadWaitObj, &thread->threadLock); + if (res != 0) { + DeleteString(&thread->name); + DestroyHcMutex(&thread->threadLock); + return res; + } + res = InitHcCond(&thread->bizWaitObj, NULL); + if (res != 0) { + DeleteString(&thread->name); + DestroyHcMutex(&thread->threadLock); + DestroyHcCond(&thread->threadWaitObj); + } + return res; +} + +void DestroyThread(HcThread *thread) +{ + if (thread == NULL) { + return; + } + + DestroyHcCond(&thread->bizWaitObj); + DestroyHcCond(&thread->threadWaitObj); + DestroyHcMutex(&thread->threadLock); + DeleteString(&thread->name); +} \ No newline at end of file diff --git a/hals/src/liteos/hc_time.c b/hals/src/liteos/hc_time.c new file mode 100755 index 0000000..cc64aa4 --- /dev/null +++ b/hals/src/liteos/hc_time.c @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "hc_time.h" +#include +#include +#include "hc_log.h" + +int64_t HcGetCurTime() +{ + struct timespec start; + int res = clock_gettime(CLOCK_MONOTONIC, &start); + if (res != 0) { + LOGE("clock_gettime failed, res:%d", res); + return -1; + } + return start.tv_sec; +} + +int64_t HcGetIntervalTime(int64_t startTime) +{ + if (startTime < 0) { + LOGE("Start time is invalid"); + return -1; + } + struct timespec end; + int res = clock_gettime(CLOCK_MONOTONIC, &end); + if (res != 0) { + LOGE("clock_gettime failed, res:%d", res); + return -1; + } + if (end.tv_sec < startTime) { + LOGE("End time is invalid"); + return -1; + } + return (end.tv_sec - startTime); +} \ No newline at end of file diff --git a/hals/src/liteos/hc_types.c b/hals/src/liteos/hc_types.c new file mode 100755 index 0000000..a70c8b0 --- /dev/null +++ b/hals/src/liteos/hc_types.c @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "hc_types.h" +#include +#include +#include "hc_log.h" +#include "ohos_mem_pool.h" + +void *HcMalloc(uint32_t size, char val) +{ + if (size == 0) { + LOGE("Malloc size is invalid."); + return NULL; + } + void* addr = OhosMalloc(MEM_TYPE_HICHAIN, size); + if (addr != NULL) { + (void)memset_s(addr, size, val, size); + } + return addr; +} + +void HcFree(void* addr) +{ + if (addr != NULL) { + OhosFree(addr); + } +} + +uint32_t HcStrlen(const char *str) +{ + if (str == NULL) { + return 0; + } + const char *p = str; + while (*p++ != '\0') {} + return p - str - 1; +} + diff --git a/interfaces/innerkits/device_auth.h b/interfaces/innerkits/device_auth.h new file mode 100755 index 0000000..e61b3da --- /dev/null +++ b/interfaces/innerkits/device_auth.h @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DEVICE_AUTH_H +#define DEVICE_AUTH_H + +#include +#include + +#if defined(_LINUX) || defined(_UNIX) +#define DEVICE_AUTH_API_PUBLIC __attribute__ ((visibility("default"))) +#else +#define DEVICE_AUTH_API_PUBLIC +#endif + +#define FIELD_GROUP_ID "groupId" +#define FIELD_GROUP_TYPE "groupType" +#define FIELD_GROUP_NAME "groupName" +#define FIELD_PEER_DEVICE_ID "peerDeviceId" +#define FIELD_IS_ADMIN "isAdmin" +#define FIELD_CREDENTIAL_TYPE "credentialType" +#define FIELD_IS_FORCE_DELETE "isForceDelete" +#define FIELD_IS_IGNORE_CHANNEL "isIgnoreChannel" +#define FIELD_CONNECT_PARAMS "connectParams" +#define FIELD_ADD_ID "addId" +#define FIELD_DELETE_ID "deleteId" +#define FIELD_APP_ID "appId" +#define FIELD_SERVICE_TYPE "serviceType" +#define FIELD_PEER_AUTH_STATE "peerAuthState" +#define FIELD_IS_DEVICE_LEVEL "isDeviceLevel" +#define FIELD_ALTERNATIVE "alternative" +#define FIELD_PEER_UDID "peerUdid" +#define FIELD_PEER_CONN_DEVICE_ID "peerConnDeviceId" +#define FIELD_KEY_LENGTH "keyLength" +#define FIELD_IS_CLIENT "isClient" +#define FIELD_SESSION_KEY "sessionKey" +#define FIELD_AUTH_FORM "authForm" +#define FIELD_CONFIRMATION "confirmation" +#define FIELD_GROUP_OWNER "groupOwner" +#define FIELD_PEER_AUTH_ID "peerAuthId" +#define FIELD_PEER_USER_TYPE "peerUserType" +#define FIELD_PEER_USER_ID "peerUserId" +#define FIELD_SERVICE_PKG_NAME "servicePkgName" +#define FIELD_USER_TYPE "userType" +#define FIELD_USER_ID "userId" +#define FIELD_DEVICE_ID "deviceId" +#define FIELD_UID_HASH "uidHash" +#define FIELD_PIN_CODE "pinCode" +#define FIELD_AUTH_ID "authId" +#define FIELD_GROUP_VISIBILITY "groupVisibility" +#define FIELD_EXPIRE_TIME "expireTime" +#define FIELD_IS_DELETE_ALL "isDeleteAll" + +typedef enum { + GROUP_CREATE = 0, + GROUP_DISBAND = 1, + MEMBER_INVITE = 2, + MEMBER_JOIN = 3, + MEMBER_DELETE = 4, + ACCOUNT_BIND = 5 +} GroupOperationCode; + +typedef enum { + CREDENTIAL_SAVE = 0, + CREDENTIAL_CLEAR = 1, + CREDENTIAL_UPDATE = 2, + CREDENTIAL_QUERY = 3, +} CredentialCode; + +typedef enum { + DEVICE_TYPE_ACCESSORY = 0, + DEVICE_TYPE_CONTROLLER = 1, + DEVICE_TYPE_PROXY = 2 +} UserType; + +#define REQUEST_REJECTED 0x80000005 +#define REQUEST_ACCEPTED 0x80000006 +#define REQUEST_WAITING 0x80000007 + +typedef struct { + void (*onGroupCreated)(const char *groupInfo); + void (*onGroupDeleted)(const char *groupInfo); + void (*onDeviceBound)(const char *peerUdid, const char *groupInfo); + void (*onDeviceUnBound)(const char *peerUdid, const char *groupInfo); + void (*onDeviceNotTrusted)(const char *peerUdid); + void (*onLastGroupDeleted)(const char *peerUdid, int groupType); + void (*onTrustedDeviceNumChanged)(int curTrustedDeviceNum); +} DataChangeListener; + +typedef struct { + bool (*onTransmit)(int64_t requestId, const uint8_t *data, uint32_t dataLen); + void (*onSessionKeyReturned)(int64_t requestId, const uint8_t *sessionKey, uint32_t sessionKeyLen); + void (*onFinish)(int64_t requestId, int operationCode, const char *returnData); + void (*onError)(int64_t requestId, int operationCode, int errorCode, const char *errorReturn); + char *(*onRequest)(int64_t requestId, int operationCode, const char *reqParams); +} DeviceAuthCallback; + +typedef struct { + int32_t (*processData)(int64_t authReqId, const uint8_t *data, uint32_t dataLen, + const DeviceAuthCallback *gaCallback); + int32_t (*queryTrustedDeviceNum)(void); + bool (*isTrustedDevice)(const char *udid); + int32_t (*getAuthState)(int64_t authReqId, const char *groupId, const char *peerUdid, + uint8_t *out, uint32_t *outLen); + int32_t (*authDevice)(int64_t authReqId, const char *authParams, const DeviceAuthCallback *gaCallback); + void (*informDeviceDisconnection)(const char *udid); +} GroupAuthManager; + +typedef struct { + int32_t (*regCallback)(const char *appId, const DeviceAuthCallback *callback); + int32_t (*unRegCallback)(const char *appId); + int32_t (*regDataChangeListener)(const char *appId, const DataChangeListener *listener); + int32_t (*unRegDataChangeListener)(const char *appId); + int32_t (*createGroup)(int64_t requestId, const char *appId, const char *createParams); + int32_t (*deleteGroup)(int64_t requestId, const char *appId, const char *disbandParams); + int32_t (*addMemberToGroup)(int64_t requestId, const char *appId, const char *addParams); + int32_t (*deleteMemberFromGroup)(int64_t requestId, const char *appId, const char *deleteParams); + int32_t (*processData)(int64_t requestId, const uint8_t *data, uint32_t dataLen); + int32_t (*confirmRequest)(int64_t requestId, const char *appId, const char *confirmParams); + int32_t (*bindPeer)(int64_t requestId, const char *appId, const char *bindParams); + int32_t (*unbindPeer)(int64_t requestId, const char *appId, const char *unBindParams); + int32_t (*processLiteData)(int64_t requestId, const char *appId, const uint8_t *data, uint32_t dataLen); + int32_t (*authKeyAgree)(int64_t requestId, const char *appId, const char *buildParams); + int32_t (*processKeyAgreeData)(int64_t requestId, const char *appId, const uint8_t *data, uint32_t dataLen); + int32_t (*processCredential)(int operationCode, const char *reqJsonStr, char **returnJsonStr); + int32_t (*getRegisterInfo)(char **returnRegisterInfo); + int32_t (*getLocalConnectInfo)(char **returnInfo); + int32_t (*addGroupManager)(const char *appId, const char *groupId, const char *managerAppId); + int32_t (*addGroupFriend)(const char *appId, const char *groupId, const char *friendAppId); + int32_t (*deleteGroupManager)(const char *appId, const char *groupId, const char *managerAppId); + int32_t (*deleteGroupFriend)(const char *appId, const char *groupId, const char *friendAppId); + int32_t (*getGroupManagers)(const char *appId, const char *groupId, char **returnManagers, uint32_t *returnSize); + int32_t (*getGroupFriends)(const char *appId, const char *groupId, char **returnFriends, uint32_t *returnSize); + int32_t (*getGroupInfoById)(const char *appId, const char *groupId, char **returnGroupInfo); + int32_t (*getGroupInfo)(const char *appId, const char *queryParams, char **returnGroupVec, uint32_t *groupNum); + int32_t (*getJoinedGroups)(const char *appId, int groupType, char **returnGroupVec, uint32_t *groupNum); + int32_t (*getRelatedGroups)(const char *appId, const char *peerDeviceId, char **returnGroupVec, uint32_t *groupNum); + int32_t (*getDeviceInfoById)(const char *appId, const char *deviceId, const char *groupId, char **returnDeviceInfo); + int32_t (*getTrustedDevices)(const char *appId, const char *groupId, char **returnDevInfoVec, uint32_t *deviceNum); + bool (*isDeviceInGroup)(const char *appId, const char *groupId, const char *deviceId); + void (*destroyInfo)(char **returnInfo); +} DeviceGroupManager; + +#ifdef __cplusplus +extern "C" { +#endif +DEVICE_AUTH_API_PUBLIC int InitDeviceAuthService(); +DEVICE_AUTH_API_PUBLIC void DestroyDeviceAuthService(); +DEVICE_AUTH_API_PUBLIC const GroupAuthManager *GetGaInstance(); +DEVICE_AUTH_API_PUBLIC const DeviceGroupManager *GetGmInstance(); +#ifdef __cplusplus +} +#endif +#endif diff --git a/interfaces/innerkits/device_auth_defines.h b/interfaces/innerkits/device_auth_defines.h new file mode 100755 index 0000000..fdd738b --- /dev/null +++ b/interfaces/innerkits/device_auth_defines.h @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DEVICE_AUTH_DEFINES_H +#define DEVICE_AUTH_DEFINES_H + +#define HC_GROUP_FRIEND_MAX_NUM 100 /* Visibility is 1, friend list is available, and max is 100 */ +#define HC_GROUP_MANAGER_MAX_NUM 10 /* manager max number is 10, it includes owner and other managers */ + +enum { + /* common error code, 0x00000000 ~ 0x00000FFF */ + HC_SUCCESS = 0x00000000, + + HC_ERROR = 0x00000001, + HC_ERR_INVALID_PARAMS = 0x00000002, + HC_ERR_INVALID_LEN = 0x00000003, + HC_ERR_NULL_PTR = 0x00000004, + HC_ERR_ALLOC_MEMORY = 0x00000005, + HC_ERR_MEMORY_COPY = 0x00000006, + HC_HEX_CONVERT_FAILED = 0x00000007, + HC_ERR_NOT_SUPPORT = 0x00000008, + HC_ERR_TIME_OUT = 0x00000009, + HC_ERR_CASE = 0x0000000A, + HC_ERR_BAD_TIMING = 0x0000000B, + HC_ERR_PEER_ERROR = 0x0000000C, + + /* error code for huks adapter , 0x00001000 ~ 0x00001FFF */ + HC_ERR_KEY_NOT_EXIST = 0x00001001, + HC_ERR_GENERATE_KEY_FAILED = 0x000010002, + HC_ERR_INVALID_PUBLIC_KEY = 0x00001003, + HC_ERR_VERIFY_FAILED = 0x00001004, + HC_ERR_HASH_FAIL = 0x00001005, + + /* error code for json util , 0x00002000 ~ 0x00002FFF */ + HC_ERR_JSON_FAIL = 0x00002001, + HC_ERR_JSON_CREATE = 0x00002002, + HC_ERR_JSON_GET = 0x00002003, + HC_ERR_JSON_ADD = 0x00002004, + HC_ERR_PACKAGE_JSON_TO_STRING_FAIL = 0x00002005, + + /* error code for ipc, 0x00003000 ~ 0x00003FFF */ + HC_ERR_IPC_INTERNAL_FAILED = 0x00003001, + HC_ERR_IPC_UNKNOW_OPCODE = 0x00003002, + HC_ERR_IPC_CALL_DATA_LENGTH = 0x00003003, + HC_ERR_IPC_METHOD_ID_INVALID = 0x00003004, + HC_ERR_IPC_BAD_MESSAGE_LENGTH = 0x00003005, + HC_ERR_IPC_BAD_VAL_LENGTH = 0x00003006, + HC_ERR_IPC_BAD_PARAM_NUM = 0x00003007, + HC_ERR_IPC_BAD_MSG_TYPE = 0x00003008, + HC_ERR_IPC_GET_SERVICE = 0x00003009, + HC_ERR_IPC_GET_PROXY = 0x0000300A, + HC_ERR_IPC_INIT = 0x0000300B, + HC_ERR_IPC_BUILD_PARAM = 0x0000300C, + HC_ERR_IPC_PROC_FAILED = 0x0000300D, + HC_ERR_IPC_UNKNOW_REPLAY = 0x0000300E, + HC_ERR_IPC_OUT_DATA_NUM = 0x0000300F, + HC_ERR_IPC_OUT_DATA = 0x00003010, + + /* error code for module , 0x00004000 ~ 0x00004FFF */ + HC_ERR_MODULE_NOT_FOUNT = 0x00004001, + HC_ERR_UNSUPPORTED_METHOD = 0x00004002, + HC_ERR_UNSUPPORTED_VERSION = 0x00004003, + HC_ERR_UNSUPPORTED_CURVE = 0x00004004, + HC_ERR_BAD_MESSAGE = 0x00004005, + HC_ERR_PROOF_NOT_MATCH = 0x00004006, + HC_ERR_INIT_TASK_FAIL = 0x00004007, + HC_ERR_TASK_IS_NULL = 0x00004008, + HC_ERR_TASK_ID_IS_NOT_MATCH = 0x00004009, + HC_ERR_INVALID_ALG = 0x0000400A, + HC_ERR_IGNORE_MSG = 0x0000400B, + HC_ERR_LOCAL_IDENTITY_NOT_EXIST = 0x0000400C, + + /* error code for group , 0x00005000 ~ 0x00005FFF */ + HC_ERR_ACCESS_DENIED = 0x00005001, + HC_ERR_CALLBACK_NOT_FOUND = 0x00005002, + HC_ERR_SERVICE_NEED_RESTART = 0x00005003, + HC_ERR_NO_CANDIDATE_GROUP = 0x00005004, + HC_ERR_TRANSMIT_FAIL = 0x00005005, + HC_ERR_REQUEST_EXIST = 0x00005006, + HC_ERR_REQUEST_NOT_FOUND = 0x00005007, + HC_ERR_SESSION_NOT_EXIST = 0x00005008, + HC_ERR_SESSION_ID_CONFLICT = 0x00005009, + HC_ERR_REQ_REJECTED = 0x0000500A, + HC_ERR_SERVER_CONFIRM_FAIL = 0x0000500B, + HC_ERR_CREATE_SESSION_FAIL = 0x0000500C, + HC_ERR_SESSION_IS_FULL = 0x0000500D, + + /* error code for database , 0x00006000 ~ 0x00006FFF */ + HC_ERR_DB = 0x00006001, + HC_ERR_BEYOND_LIMIT = 0x00006002, + HC_ERR_SAVE_DB_FAILED = 0x00006003, + HC_ERR_FRIEND_NOT_EXIST = 0x00006004, + HC_ERR_MANAGER_NOT_EXIST = 0x00006005, + HC_ERR_GROUP_DUPLICATE = 0x00006006, + HC_ERR_GROUP_NOT_EXIST = 0x00006007, + HC_ERR_DEVICE_NOT_EXIST = 0x00006008, + HC_ERR_DEVICE_DUPLICATE = 0x00006009, + HC_ERR_LOST_DATA = 0x0000600A, + + /* error code for broadcast , 0x00007000 ~ 0x00007FFF */ + HC_ERR_LISTENER_NOT_EXIST = 0x000070012, + + /* error code for channel , 0x00008000 ~ 0x00008FFF */ + HC_ERR_CHANNEL_NOT_EXIST = 0x000080012, + HC_ERR_SOFT_BUS = 0x00008002, + + /* error code used on DAS service */ + INVALID_PARAMETERS = 0xF0000001, + EXCEED_AUTHORITY = 0xF0000002, + TIMEOUT = 0xF0000003, + NOT_REGISTERED = 0xF0000004, + NOT_TRUST_PEER = 0xF0000005, + NOT_TRUST_CONTROLLER = 0xF0000006, + NOT_TRUST_ACCESSORY = 0xF0000007, + OVER_MAX_TRUST_NUM = 0xF0000008, + CONNECTION_INTERRUPTED = 0xF0000009, + UNSUPPORTED_VERSION = 0xF000000A, + BAD_PAYLOAD = 0xF000000B, + ALGORITHM_UNSUPPORTED = 0xF000000C, + PROOF_MISMATCH = 0xF000000D, + UNKOWN = 0xF0000000, +}; + +#endif diff --git a/ohos.build b/ohos.build new file mode 100755 index 0000000..8482548 --- /dev/null +++ b/ohos.build @@ -0,0 +1,19 @@ +{ + "subsystem": "security", + "parts": { + "deviceauth_standard": { + "variants": [ + "phone", + "wearable" + ], + "module_list": [ + "//base/security/deviceauth:deviceauth_build", + "//base/security/deviceauth:deviceauth_service_build", + "//base/security/deviceauth:deviceauth_sdk_build" + ], + "test_list": [ + "//base/security/deviceauth:deviceauth_test_build" + ] + } + } +} diff --git a/services/BUILD.gn b/services/BUILD.gn new file mode 100644 index 0000000..2ce4796 --- /dev/null +++ b/services/BUILD.gn @@ -0,0 +1,125 @@ +# Copyright (C) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//base/security/deviceauth/hals/deviceauth_hals.gni") +import("//build/ohos.gni") +import("deviceauth.gni") + +ohos_static_library("deviceauth") { + subsystem_name = "security" + part_name = "deviceauth_standard" + + include_dirs = inc_path + include_dirs += hals_inc_path + include_dirs += [ + "//third_party/cJSON", + "//utils/native/base/include", + ] + + sources = deviceauth_files + + cflags = [ "-DHILOG_ENABLE" ] + cflags += build_flags + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + + deps = [ + "${hals_path}:${hal_module_name}", + "//third_party/cJSON:cjson_static", + "//utils/native/base:utils", + ] + + external_deps = [ "hiviewdfx_hilog_native:libhilog" ] +} + +ohos_prebuilt_etc("auth_service.rc") { + source = "${frameworks_path}/src/deviceauth_service.rc" + relative_install_dir = "init" + subsystem_name = "security" + part_name = "deviceauth_standard" +} + +group("etc") { + deps = [ ":auth_service.rc" ] +} + +ohos_executable("deviceauth_service") { + subsystem_name = "security" + part_name = "deviceauth_standard" + install_enable = true + + include_dirs = inc_path + include_dirs += hals_inc_path + include_dirs += [ + "//third_party/cJSON", + "//utils/native/base/include", + ] + + sources = deviceauth_ipc_files + sources += [ "${frameworks_path}/src/ipc_service.c" ] + + cflags = [ "-DHILOG_ENABLE" ] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + + deps = [ + ":auth_service.rc", + ":deviceauth", + "${hals_path}:${hal_module_name}", + "//third_party/cJSON:cjson_static", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + "safwk:system_ability_fwk", + "samgr_L2:samgr_proxy", + ] +} + +ohos_shared_library("deviceauth_sdk") { + subsystem_name = "security" + part_name = "deviceauth_standard" + + include_dirs = inc_path + include_dirs += hals_inc_path + include_dirs += [ + "//third_party/cJSON", + "//utils/native/base/include", + ] + + sources = deviceauth_ipc_files + sources += [ "${frameworks_path}/src/ipc_sdk.c" ] + + cflags = [ "-DHILOG_ENABLE" ] + cflags += build_flags + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + + deps = [ + "${hals_path}:${hal_module_name}", + "//third_party/cJSON:cjson_static", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + "safwk:system_ability_fwk", + "samgr_L2:samgr_proxy", + ] +} diff --git a/services/common/inc/broadcast_manager/broadcast_manager.h b/services/common/inc/broadcast_manager/broadcast_manager.h new file mode 100644 index 0000000..ab3ea1e --- /dev/null +++ b/services/common/inc/broadcast_manager/broadcast_manager.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BROADCAST_MANAGER_H +#define BROADCAST_MANAGER_H + +#include "database.h" +#include "device_auth.h" + +typedef struct { + void (*postOnGroupCreated)(const GroupInfo *groupInfo); + void (*postOnGroupDeleted)(const GroupInfo *groupInfo); + void (*postOnDeviceBound)(const char *peerUdid, const GroupInfo *groupInfo); + void (*postOnDeviceUnBound)(const char *peerUdid, const GroupInfo *groupInfo); + void (*postOnDeviceNotTrusted)(const char *peerUdid); + void (*postOnLastGroupDeleted)(const char *peerUdid, int groupType); + void (*postOnTrustedDeviceNumChanged)(int curTrustedDeviceNum); +} Broadcaster; + +bool IsBroadcastSupported(); +int32_t InitBroadcastManager(); +void DestroyBroadcastManager(); +Broadcaster *GetBroadcaster(); +int32_t AddListener(const char *appId, const DataChangeListener *listener); +int32_t RemoveListener(const char *appId); + +#endif diff --git a/services/common/inc/callback_manager/callback_manager.h b/services/common/inc/callback_manager/callback_manager.h new file mode 100644 index 0000000..3b2e4fa --- /dev/null +++ b/services/common/inc/callback_manager/callback_manager.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef CALLBACK_MANAGER_H +#define CALLBACK_MANAGER_H + +#include "device_auth.h" + +bool ProcessTransmitCallback(int64_t requestId, const uint8_t *data, uint32_t dataLen, + const DeviceAuthCallback *callback); +char *ProcessRequestCallback(int64_t requestId, int operationCode, const char *reqParams, + const DeviceAuthCallback *callback); +void ProcessFinishCallback(int64_t requestId, int operationCode, const char *returnData, + const DeviceAuthCallback *callback); +void ProcessSessionKeyCallback(int64_t requestId, const uint8_t *sessionKey, uint32_t sessionKeyLen, + const DeviceAuthCallback *callback); +void ProcessErrorCallback(int64_t requestId, int operationCode, int errorCode, const char *errorReturn, + const DeviceAuthCallback *callback); +#endif diff --git a/services/common/inc/channel_manager/channel_manager.h b/services/common/inc/channel_manager/channel_manager.h new file mode 100644 index 0000000..ba764f4 --- /dev/null +++ b/services/common/inc/channel_manager/channel_manager.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef CHANNEL_MANAGER_H +#define CHANNEL_MANAGER_H + +#include "device_auth.h" +#include "common_defs.h" +#include "json_utils.h" + +int32_t InitChannelManager(void (*onChannelOpened)(int64_t, int64_t, const char *, uint32_t, bool), + void (*onChannelClosed)(int64_t, int64_t), + void (*onMsgReceived)(int64_t, const uint8_t *, uint32_t), + void (*onServiceDied)()); +void DestroyChannelManager(); + +/* Channel operation interfaces */ +ChannelType GetChannelType(const DeviceAuthCallback *callback); +bool CanFindValidChannel(ChannelType channelType, const CJson *jsonParams, const DeviceAuthCallback *callback); +int32_t OpenChannel(ChannelType channelType, const CJson *jsonParams, int64_t requestId, int64_t *returnChannelId); +void CloseChannel(ChannelType channelType, int64_t channelId); +int32_t SendMsg(ChannelType channelType, int64_t requestId, int64_t channelId, + const DeviceAuthCallback *callback, const char *data); +void SetAuthResult(ChannelType channelType, int64_t channelId); +int32_t GetLocalConnectInfo(char **returnLocalConnectInfo); +#endif diff --git a/services/common/inc/channel_manager/soft_bus_channel/soft_bus_channel.h b/services/common/inc/channel_manager/soft_bus_channel/soft_bus_channel.h new file mode 100644 index 0000000..0cbeaa1 --- /dev/null +++ b/services/common/inc/channel_manager/soft_bus_channel/soft_bus_channel.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SOFT_BUS_CHANNEL_H +#define SOFT_BUS_CHANNEL_H + +#include +#include + +typedef struct { + int32_t (*openChannel)(const char *connectParams, int64_t requestId, int64_t *returnChannelId); + void (*closeChannel)(int64_t channelId); + int32_t (*sendMsg)(int64_t channelId, const uint8_t *data, uint32_t dataLen); + void (*setAuthResult)(int64_t channelId); + char *(*getLocalAuthInfo)(); +} SoftBus; + +int32_t InitSoftBusChannelModule(void (*onChannelOpened)(int64_t, int64_t, const char *, uint32_t, bool), + void (*onChannelClosed)(int64_t, int64_t), + void (*onMsgReceived)(int64_t, const uint8_t *, uint32_t), + void (*onServiceDied)()); +void DestroySoftBusChannelModule(); +SoftBus *GetSoftBusInstance(); +bool IsSoftBusChannelSupported(); + +#endif diff --git a/services/common/inc/common_defs.h b/services/common/inc/common_defs.h new file mode 100644 index 0000000..afea1c5 --- /dev/null +++ b/services/common/inc/common_defs.h @@ -0,0 +1,242 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef COMMON_DEFS_H +#define COMMON_DEFS_H + +#include "device_auth.h" +#include "device_auth_defines.h" +#include "json_utils.h" + +#define FIELD_ADD_TYPE "addType" +#define FIELD_ADD_ID "addId" +#define FIELD_ADD_KEY "addKey" +#define FIELD_AUTH_DATA "authData" +#define FIELD_AUTH_RETURN "authReturn" +#define FIELD_AUTH_ID "authId" +#define FIELD_AUTH_PK "authPk" +#define FIELD_ADD_AUTH_INFO "addAuthInfo" +#define FIELD_ADD_RETURN "addReturn" +#define FIELD_APP_ID "appId" +#define FIELD_BIND_SESSION_TYPE "bindSessionType" +#define FIELD_CHALLENGE "challenge" +#define FIELD_CHANNEL_ID "channelId" +#define FIELD_CONN_DEVICE_ID "connDeviceId" +#define FIELD_CONNECT_PARAMS "connectParams" +#define FIELD_CURRENT_VERSION "currentVersion" +#define FIELD_DELETE_ID "deleteId" +#define FIELD_ENC_AUTH_TOKEN "encAuthToken" +#define FIELD_ENC_RESULT "encResult" +#define FIELD_ENC_DATA "encData" +#define FIELD_EPK "epk" +#define FIELD_EPK_LEN "epkLen" +#define FIELD_EX_AUTH_INFO "exAuthInfo" +#define FIELD_EXPIRE_TIME "expireTime" +#define FIELD_ERROR_CODE "errorCode" +#define FIELD_GROUP_INFO "groupInfo" +#define FIELD_GROUP_MANAGERS "groupManagers" +#define FIELD_GROUP_NAME "groupName" +#define FIELD_GROUP_OP "groupOp" +#define FIELD_GROUP_TYPE "groupType" +#define FIELD_GROUP_VISIBILITY "groupVisibility" +#define FIELD_IS_ADMIN "isAdmin" +#define FIELD_IS_ACCOUNT_BIND "isAccountBind" +#define FIELD_IS_FORCE_DELETE "isForceDelete" +#define FIELD_IS_CREDENTIAL_EXISTS "isCredentialExists" +#define FIELD_KCF_DATA "kcfData" +#define FIELD_KEY_TYPE "keyType" +#define FIELD_MESSAGE "message" +#define FIELD_GROUP_ERROR_MSG "groupErrorMsg" +#define FIELD_MIN_VERSION "minVersion" +#define FIELD_GROUP_AND_MODULE_VERSION "groupAndModuleVersion" +#define FIELD_NONCE "nonce" +#define FIELD_OPERATION_CODE "operationCode" +#define FIELD_OPERATION_PARAMS "operationParams" +#define FIELD_OWNER_ID "ownerId" +#define FIELD_OWNER_NAME "ownerName" +#define FIELD_PERMISSION "Permission" +#define FIELD_PAYLOAD "payload" +#define FIELD_PEER_DEVICE_ID "peerDeviceId" +#define FIELD_PIN_CODE "pinCode" +#define FIELD_PUBLIC_KEY "publicKey" +#define FIELD_PK_INFO "pkInfo" +#define FIELD_PKG_NAME "pkgName" +#define FIELD_SELF_AUTH_ID "selfAuthId" +#define FIELD_SELF_DEVICE_ID "selfDeviceId" +#define FIELD_REQUEST_ID "requestId" +#define FIELD_RECEIVED_DATA "receivedData" +#define FIELD_RETURN_CODE "returnCode" +#define FIELD_RETURN_DATA "returnData" +#define FIELD_RETURN_CODE_MAC "returnCodeMac" +#define FIELD_RMV_TYPE "rmvType" +#define FIELD_RMV_ID "rmvId" +#define FIELD_RMV_AUTH_INFO "rmvAuthInfo" +#define FIELD_RMV_RETURN "rmvReturn" +#define FIELD_SALT "salt" +#define FIELD_ISO_SALT "isoSalt" +#define FIELD_SEED "seed" +#define FIELD_SELF_TYPE "selfType" +#define FIELD_SEND_TO_PEER "sendToPeer" +#define FIELD_SEND_TO_SELF "sendToSelf" +#define FIELD_SHARED_USER_ID_LIST "sharedUserIdList" +#define FIELD_SUPPORT_256_MOD "support256mod" +#define FIELD_TOKEN "token" +#define FIELD_IS_UUID "uuIdAsDeviceId" +#define FIELD_VERSION "version" +#define FIELD_MK_AGREE_MSG "mkaMsg" + +#define AUTH_FORM_INVALID_TYPE -1 +#define AUTH_FORM_ACCOUNT_UNRELATED 0 +#define AUTH_FORM_IDENTICAL_ACCOUNT 1 +#define AUTH_FORM_ACROSS_ACCOUNT 2 +#define INVALID_MODULE_TYPE -1 +#define GROUP_ERR_MSG 0x8080 + +/* GroupVisibility */ +#define ALL_GROUP_VISIBILITY -2 +#define GROUP_VISIBILITY_PRIVATE 0 +#define GROUP_VISIBILITY_ALLOW_LIST 1 +#define GROUP_VISIBILITY_SIGNATURE 2 +#define GROUP_VISIBILITY_SYSTEM 4 +#define GROUP_VISIBILITY_PRIVILEGE 8 +#define GROUP_VISIBILITY_PUBLIC -1 + +#define CLIENT 1 +#define SERVER 0 + +#define CREATE_KEY_PAIR 1 +#define DELETE_KEY_PAIR 2 + +/* DefaultValue */ +#define DEFAULT_MEMORY_SIZE 64 +#define DEFAULT_USER_ID 0 +#define DEFAULT_REQUEST_ID 0 +#define DEFAULT_CHANNEL_ID -1 +#define DEFAULT_EXPIRE_TIME 90 +#define GROUP_MANAGER_PACKAGE_NAME "com.huawei.devicegroupmanage" +#define DEFAULT_RETURN_KEY_LENGTH 32 +#define ERR_AUTH_FORM 0 +#define MAX_BUFFER_LEN 1024 +#define MAX_AUTH_ID_LEN 256 + +typedef enum { + ALL_GROUP = 0, + IDENTICAL_ACCOUNT_GROUP = 1, + PEER_TO_PEER_GROUP = 256, + COMPATIBLE_GROUP = 512, + ACROSS_ACCOUNT_AUTHORIZE_GROUP = 1282 +} GroupType; + +typedef enum { + NO_CHANNEL = 1, + SERVICE_CHANNEL = 2, + SOFT_BUS = 3, +} ChannelType; + +typedef enum { + SYMMETRIC = 0, + ASYMMETRIC = 1, +} CredentialType; + +#define MAX_IN_PARAM_LEN 4096 + +#define CHECK_PTR_RETURN_NULL(ptr, paramTag) \ + do { \ + if ((ptr) == NULL) { \ + LOGE("%s is null ptr", (paramTag)); \ + return NULL; \ + } \ + } while (0) + +#define CHECK_PTR_RETURN_ERROR_CODE(ptr, paramTag) \ + do { \ + if ((ptr) == NULL) { \ + LOGE("%s is null ptr", (paramTag)); \ + return HC_ERR_NULL_PTR; \ + } \ + } while (0) + +#define CHECK_PTR_RETURN_NONE(ptr, paramTag) \ + do { \ + if ((ptr) == NULL) { \ + LOGE("%s is null ptr", (paramTag)); \ + return; \ + } \ + } while (0) + +#define GOTO_IF_ERR(x) do { \ + int32_t res = x; \ + if ((res) != HC_SUCCESS) { \ + goto err; \ + } \ + } while (0) + +#define GOTO_ERR_AND_SET_RET(x, res) do { \ + res = x; \ + if ((res) != HC_SUCCESS) { \ + goto err; \ + } \ + } while (0) + +#define RETURN_IF_ERR(x) do { \ + int32_t res = x; \ + if ((res) != HC_SUCCESS) { \ + return res; \ + } \ + } while (0) + +typedef struct AuthModuleBaseT { + int moduleType; + int (*createTask)(int *, const CJson *in, CJson *out); + int (*processTask)(int, const CJson *in, CJson *out, int *status); + void (*destroyTask)(int); + void (*destroyModule)(struct AuthModuleBaseT *module); +} AuthModuleBase; + +typedef enum { + DAS_MODULE = 0x0001, + TCIS_MODULE = 0x0010, +} EnumModuleType; + +typedef enum { + CONTINUE = 0, + IGNORE_MSG = 1, + FINISH, +} TaskStatus; + +typedef enum { + CODE_NULL = 0, + OP_BIND = 1, + AUTHENTICATE = 2, + ADD_AUTH_INFO = 3, + REMOVE_AUTH_INFO = 4, + OP_UNBIND = 5, + AUTH_KEY_AGREEMENT = 6, + REGISTER = 7, + SECURE_CLONE = 8, +} OperationCode; + +typedef struct { + int64_t requestId; + int32_t type; + int64_t sessionId; +} RequestInfo; + +typedef struct { + char *appId; + DeviceAuthCallback *callback; +} CallbackEntry; + +#endif diff --git a/services/common/inc/data_base/database.h b/services/common/inc/data_base/database.h new file mode 100644 index 0000000..564459b --- /dev/null +++ b/services/common/inc/data_base/database.h @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DATABASE_H +#define DATABASE_H + +#include "hc_string.h" +#include "hc_tlv_parser.h" +#include "hc_vector.h" + +#define MAX_EXPIRE_TIME 90 + +DECLARE_HC_VECTOR(StringVector, HcString) +DECLARE_HC_VECTOR(Int64Vector, int64_t) + +typedef struct { + HcString name; /* group name */ + HcString id; /* group id */ + int32_t type; /* including identical account group(1), peer to peer group(256), across account group(1282) */ + int32_t visibility; /* visibility of the group */ + int32_t expireTime; /* the time of group expired, unit day, user config */ + int64_t userId; /* user account id */ + Int64Vector sharedUserIdVec; /* shared user account id vector */ + StringVector managers; /* group manager vector, group manager can add and delete members, index 0 is the owner */ + StringVector friends; /* group friend vector, group friend can query group information */ +} TrustedGroupEntry; +DECLARE_HC_VECTOR(TrustedGroupTable, TrustedGroupEntry*) + +typedef struct { + TrustedGroupEntry* groupEntry; + HcString udid; /* unique device id */ + HcString authId; /* id by service defined for authentication */ + HcString serviceType; /* compatible with previous versions, the value is the same as groupId */ + HcParcel ext; /* for caching extern data, user data */ + uint8_t credential; /* 1 - asymmetrical, 2 - symmetrical */ + uint8_t devType; /* 0 - accessory, 1 - controller, 2 - proxy */ + int64_t userId; /* user account id */ + uint64_t lastTm; /* accessed time of the device of the auth information, absolute time */ +} TrustedDeviceEntry; +DECLARE_HC_VECTOR(TrustedDeviceTable, TrustedDeviceEntry) + +typedef struct { + DECLARE_TLV_STRUCT(9) + TlvString name; + TlvString id; + TlvUint32 type; + TlvInt32 visibility; + TlvInt32 expireTime; + TlvInt64 userId; + TlvBuffer sharedUserIdVec; + TlvBuffer managers; + TlvBuffer friends; +} TlvGroupElement; +DECLEAR_INIT_FUNC(TlvGroupElement) +DECLARE_TLV_VECTOR(TlvGroupVec, TlvGroupElement) + +typedef struct { + uint8_t credential; + uint8_t devType; + int64_t userId; + uint64_t lastTm; +} DevAuthFixedLenInfo; +DECLARE_TLV_FIX_LENGTH_TYPE(TlvDevAuthFixedLenInfo, DevAuthFixedLenInfo) +DECLEAR_INIT_FUNC(TlvDevAuthFixedLenInfo) + +typedef struct { + DECLARE_TLV_STRUCT(6) + TlvString groupId; + TlvString udid; + TlvString authId; + TlvString serviceType; + TlvBuffer ext; + TlvDevAuthFixedLenInfo info; +} TlvDevAuthElement; +DECLEAR_INIT_FUNC(TlvDevAuthElement) +DECLARE_TLV_VECTOR(TlvDevAuthVec, TlvDevAuthElement) + +typedef struct { + DECLARE_TLV_STRUCT(3) + TlvInt32 version; + TlvGroupVec groups; + TlvDevAuthVec deviceAuthInfos; +} HCDataBaseV1; +DECLEAR_INIT_FUNC(HCDataBaseV1) + +typedef struct { + HcString name; /* group name */ + HcString id; /* group id */ + HcString ownerName; /* group owner name */ + int32_t type; /* group type, 0 - invalid, 1 - the same account, 2 - different account, 3 - none account(p2p) */ + int32_t visibility; /* visibility of the group */ + int32_t expireTime; /* the time of group expired, unit day, user config */ + int64_t userId; /* user account id */ + int64_t sharedUserId; /* shared user account id */ +} GroupInfo; +DECLARE_HC_VECTOR(GroupInfoVec, void *) + +typedef struct { + HcString udid; /* unique device id */ + HcString authId; /* id by service defined for authentication */ + uint8_t credential; /* 1 - asymmetrical, 2 - symmetrical */ + uint8_t devType; /* 0 - accessory, 1 - controller, 2 - proxy */ + int64_t userId; /* user account id */ + HcString groupId; /* map the device authentication data for group */ + HcString serviceType; /* compatible with previous versions, the value is the same as groupId */ +} DeviceInfo; +DECLARE_HC_VECTOR(DeviceInfoVec, void *) + +#endif diff --git a/services/common/inc/data_base/database_manager.h b/services/common/inc/data_base/database_manager.h new file mode 100644 index 0000000..610947b --- /dev/null +++ b/services/common/inc/data_base/database_manager.h @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DATABASE_MANAGER_H +#define DATABASE_MANAGER_H + +#include +#include +#include "broadcast_manager.h" +#include "common_defs.h" +#include "common_util.h" +#include "device_auth_defines.h" + +#define HC_TRUST_DEV_ENTRY_MAX_NUM 101 +#define HC_TRUST_GROUP_ENTRY_MAX_NUM 100 + +typedef struct { + int32_t type; /* group type */ + int32_t visibility; /* group visibility */ + char *udid; /* unique device id */ + char *authId; /* id by service defined for authentication */ +} GroupQueryParams; + +#ifdef __cplusplus +extern "C" { +#endif + +int32_t InitDatabase(); +void DestroyDatabase(); + +Int64Vector CreateInt64Vector(); +void DestroyInt64Vector(Int64Vector *obj); + +int32_t AddGroup(const GroupInfo *addParams); +int32_t DelGroupByGroupId(const char *groupId); +int32_t AddTrustedDevice(const DeviceInfo *deviceInfo, const Uint8Buff *ext); +int32_t DelTrustedDevice(const char *udid, const char *groupId); +int32_t DelTrustedDeviceByAuthId(const char *authId, const char *groupId); +int32_t DeleteUserIdExpiredGroups(int64_t curUserId); +int32_t DeleteAllAccountGroup(void); +int32_t ChangeSharedUserIdVec(Int64Vector *sharedUserIdList); + +int32_t GetLocalDevUdid(char **udid); +void DestroyUdid(char **udid); + +void RegisterBroadcaster(const Broadcaster *broadcaster); +void DeregisterBroadcaster(); +void RegGenerateGroupIdFunc(int32_t (*generateGroupId)(int64_t userId, int64_t sharedUserId, char **returnGroupId)); +void DeregGenerateGroupIdFunc(); + +int32_t GetTrustedDevNumber(); +int32_t GetGroupEntryByGroupId(const char *groupId, GroupInfo *returnGroupInfo); +int32_t GetGroupEntry(const char *groupId, const char *udid, GroupInfo *returnGroupInfo); +int32_t GetDeviceInfoForDevAuth(const char *udid, const char *groupId, DeviceInfo *deviceInfo); +int32_t GetDeviceInfoByAuthId(const char *authId, const char *groupId, DeviceInfo *deviceInfo); +int32_t GetJoinedGroupInfoVecByDevId(const GroupQueryParams *params, GroupInfoVec *vec); +int32_t GetGroupNumberByOwner(const char *ownerName); +int32_t GetCurDeviceNumByGroupId(const char *groupId); +int32_t CompareVisibility(const char *groupId, int groupVisibility); +bool IsGroupOwner(const char *groupId, const char *appId); +bool IsGroupAccessible(const char *groupId, const char *appId); +bool IsGroupEditAllowed(const char *groupId, const char *appId); +bool IsGroupExist(const char *ownerName, const char *groupName); +bool IsIdenticalGroupExist(); +bool IsAcrossAccountGroupExist(); +bool IsGroupExistByGroupId(const char *groupId); +bool IsTrustedDeviceExist(const char *udid); +bool IsTrustedDeviceInGroup(const char *groupId, const char *udid); +bool IsTrustedDeviceInGroupByAuthId(const char *groupId, const char *authId); +int32_t GetJoinedGroups(int groupType, GroupInfoVec *groupInfoVec); +int32_t GetGroupInfo(int groupType, const char *groupId, const char *groupName, const char *groupOwner, + GroupInfoVec *groupInfoVec); +int32_t GetRelatedGroups(const char *peerAuthId, GroupInfoVec *groupInfoVec); +int32_t GetTrustedDevices(const char *peerAuthId, DeviceInfoVec *deviceInfoVec); + +int32_t AddGroupManager(const char *groupId, const char *managerAppId); +int32_t RemoveGroupManager(const char *groupId, const char *managerAppId); +int32_t GetGroupManagers(const char *groupId, CJson *returnManagers); +int32_t AddGroupFriend(const char *groupId, const char *friendAppId); +int32_t RemoveGroupFriend(const char *groupId, const char *friendAppId); +int32_t GetGroupFriends(const char *groupId, CJson *returnFriends); + +GroupInfo *CreateGroupInfoStruct(); +DeviceInfo *CreateDeviceInfoStruct(); +void DestroyGroupInfoStruct(GroupInfo *groupInfo); +void DestroyDeviceInfoStruct(DeviceInfo *deviceInfo); +void CreateGroupInfoVecStruct(GroupInfoVec *vec); +void DestroyGroupInfoVecStruct(GroupInfoVec *vec); +void CreateDeviceInfoVecStruct(DeviceInfoVec *vec); +void DestroyDeviceInfoVecStruct(DeviceInfoVec *vec); + +#ifdef __cplusplus +} +#endif +#endif \ No newline at end of file diff --git a/services/common/src/broadcast_manager/broadcast_manager.c b/services/common/src/broadcast_manager/broadcast_manager.c new file mode 100644 index 0000000..bbb49e6 --- /dev/null +++ b/services/common/src/broadcast_manager/broadcast_manager.c @@ -0,0 +1,395 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "broadcast_manager.h" +#include "common_defs.h" +#include "device_auth_defines.h" +#include "hc_log.h" +#include "hc_mutex.h" +#include "securec.h" + +typedef struct { + char *appId; + DataChangeListener *listener; +} ListenerEntry; + +DECLARE_HC_VECTOR(ListenerEntryVec, ListenerEntry) +IMPLEMENT_HC_VECTOR(ListenerEntryVec, ListenerEntry, 1) +static ListenerEntryVec g_listenerEntryVec; +static HcMutex *g_broadcastMutex = NULL; + +static int32_t AddGroupId(const GroupInfo *groupInfo, CJson *message) +{ + if (AddStringToJson(message, FIELD_GROUP_ID, StringGet(&groupInfo->id)) != HC_SUCCESS) { + LOGE("Failed to add groupId to message!"); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} + +static int32_t AddGroupType(const GroupInfo *groupInfo, CJson *message) +{ + if (AddIntToJson(message, FIELD_GROUP_TYPE, groupInfo->type) != HC_SUCCESS) { + LOGE("Failed to add groupType to message!"); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} + +static int32_t AddGroupName(const GroupInfo *groupInfo, CJson *message) +{ + if (AddStringToJson(message, FIELD_GROUP_NAME, StringGet(&groupInfo->name)) != HC_SUCCESS) { + LOGE("Failed to add groupName to message!"); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} + +static int32_t AddGroupOwner(const GroupInfo *groupInfo, CJson *message) +{ + if (AddStringToJson(message, FIELD_GROUP_OWNER, StringGet(&groupInfo->ownerName)) != HC_SUCCESS) { + LOGE("Failed to add groupOwner to message!"); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} + +static int32_t AddGroupVisibility(const GroupInfo *groupInfo, CJson *message) +{ + if (AddIntToJson(message, FIELD_GROUP_VISIBILITY, groupInfo->visibility) != HC_SUCCESS) { + LOGE("Failed to add groupVisibility to message!"); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} + +static int32_t GenerateMessage(const GroupInfo *groupInfo, char **returnGroupInfo) +{ + CJson *message = CreateJson(); + if (message == NULL) { + LOGE("Failed to allocate message memory!"); + return HC_ERR_ALLOC_MEMORY; + } + int32_t result; + if (((result = AddGroupId(groupInfo, message)) != HC_SUCCESS) || + ((result = AddGroupType(groupInfo, message)) != HC_SUCCESS) || + ((result = AddGroupName(groupInfo, message)) != HC_SUCCESS) || + ((result = AddGroupOwner(groupInfo, message)) != HC_SUCCESS) || + ((result = AddGroupVisibility(groupInfo, message)) != HC_SUCCESS)) { + FreeJson(message); + return result; + } + char *messageStr = PackJsonToString(message); + FreeJson(message); + if (messageStr == NULL) { + LOGE("Failed to convert json to string!"); + return HC_ERR_JSON_FAIL; + } + *returnGroupInfo = messageStr; + return HC_SUCCESS; +} + +static void PostOnGroupCreated(const GroupInfo *groupInfo) +{ + if (groupInfo == NULL) { + LOGE("The groupEntry is NULL!"); + return; + } + char *messageStr = NULL; + if (GenerateMessage(groupInfo, &messageStr) != HC_SUCCESS) { + return; + } + uint32_t index; + ListenerEntry *entry = NULL; + g_broadcastMutex->lock(g_broadcastMutex); + FOR_EACH_HC_VECTOR(g_listenerEntryVec, index, entry) { + if ((entry != NULL) && (entry->listener != NULL) && (entry->listener->onGroupCreated != NULL)) { + LOGI("[Broadcaster]: Ready to broadcast the message to the listener! [AppId]: %s", entry->appId); + entry->listener->onGroupCreated(messageStr); + } + } + g_broadcastMutex->unlock(g_broadcastMutex); + FreeJsonString(messageStr); +} + +static void PostOnGroupDeleted(const GroupInfo *groupInfo) +{ + if (groupInfo == NULL) { + LOGE("The groupEntry is NULL!"); + return; + } + char *messageStr = NULL; + if (GenerateMessage(groupInfo, &messageStr) != HC_SUCCESS) { + return; + } + uint32_t index; + ListenerEntry *entry = NULL; + g_broadcastMutex->lock(g_broadcastMutex); + FOR_EACH_HC_VECTOR(g_listenerEntryVec, index, entry) { + if ((entry != NULL) && (entry->listener != NULL) && (entry->listener->onGroupDeleted != NULL)) { + LOGI("[Broadcaster]: Ready to broadcast the message to the listener! [AppId]: %s", entry->appId); + entry->listener->onGroupDeleted(messageStr); + } + } + g_broadcastMutex->unlock(g_broadcastMutex); + FreeJsonString(messageStr); +} + +static void PostOnDeviceBound(const char *peerUdid, const GroupInfo *groupInfo) +{ + if ((peerUdid == NULL) || (groupInfo == NULL)) { + LOGE("The peerUdid or groupEntry is NULL!"); + return; + } + char *messageStr = NULL; + if (GenerateMessage(groupInfo, &messageStr) != HC_SUCCESS) { + return; + } + uint32_t index; + ListenerEntry *entry = NULL; + g_broadcastMutex->lock(g_broadcastMutex); + FOR_EACH_HC_VECTOR(g_listenerEntryVec, index, entry) { + if ((entry != NULL) && (entry->listener != NULL) && (entry->listener->onDeviceBound != NULL)) { + LOGI("[Broadcaster]: Ready to broadcast the message to the listener! [AppId]: %s", entry->appId); + entry->listener->onDeviceBound(peerUdid, messageStr); + } + } + g_broadcastMutex->unlock(g_broadcastMutex); + FreeJsonString(messageStr); +} + +static void PostOnDeviceUnBound(const char *peerUdid, const GroupInfo *groupInfo) +{ + if ((peerUdid == NULL) || (groupInfo == NULL)) { + LOGE("The peerUdid or groupEntry is NULL!"); + return; + } + char *messageStr = NULL; + if (GenerateMessage(groupInfo, &messageStr) != HC_SUCCESS) { + return; + } + uint32_t index; + ListenerEntry *entry = NULL; + g_broadcastMutex->lock(g_broadcastMutex); + FOR_EACH_HC_VECTOR(g_listenerEntryVec, index, entry) { + if ((entry != NULL) && (entry->listener != NULL) && (entry->listener->onDeviceUnBound != NULL)) { + LOGI("[Broadcaster]: Ready to broadcast the message to the listener! [AppId]: %s", entry->appId); + entry->listener->onDeviceUnBound(peerUdid, messageStr); + } + } + g_broadcastMutex->unlock(g_broadcastMutex); + FreeJsonString(messageStr); +} + +static void PostOnDeviceNotTrusted(const char *peerUdid) +{ + if (peerUdid == NULL) { + LOGE("The peerUdid is NULL!"); + return; + } + uint32_t index; + ListenerEntry *entry = NULL; + g_broadcastMutex->lock(g_broadcastMutex); + FOR_EACH_HC_VECTOR(g_listenerEntryVec, index, entry) { + if ((entry != NULL) && (entry->listener != NULL) && (entry->listener->onDeviceNotTrusted != NULL)) { + LOGI("[Broadcaster]: Ready to broadcast the message to the listener! [AppId]: %s", entry->appId); + entry->listener->onDeviceNotTrusted(peerUdid); + } + } + g_broadcastMutex->unlock(g_broadcastMutex); +} + +static void PostOnLastGroupDeleted(const char *peerUdid, int groupType) +{ + if (peerUdid == NULL) { + LOGE("The peerUdid is NULL!"); + return; + } + uint32_t index; + ListenerEntry *entry = NULL; + g_broadcastMutex->lock(g_broadcastMutex); + FOR_EACH_HC_VECTOR(g_listenerEntryVec, index, entry) { + if ((entry != NULL) && (entry->listener != NULL) && (entry->listener->onLastGroupDeleted != NULL)) { + LOGI("[Broadcaster]: Ready to broadcast the message to the listener! [AppId]: %s, [GroupType]: %d", + entry->appId, groupType); + entry->listener->onLastGroupDeleted(peerUdid, groupType); + } + } + g_broadcastMutex->unlock(g_broadcastMutex); +} + +static void PostOnTrustedDeviceNumChanged(int curTrustedDeviceNum) +{ + uint32_t index; + ListenerEntry *entry = NULL; + g_broadcastMutex->lock(g_broadcastMutex); + FOR_EACH_HC_VECTOR(g_listenerEntryVec, index, entry) { + if ((entry != NULL) && (entry->listener != NULL) && (entry->listener->onTrustedDeviceNumChanged != NULL)) { + LOGI("[Broadcaster]: Ready to broadcast the message to the listener! [AppId]: %s", entry->appId); + entry->listener->onTrustedDeviceNumChanged(curTrustedDeviceNum); + } + } + g_broadcastMutex->unlock(g_broadcastMutex); +} + +static int32_t UpdateListenerIfExist(const char *appId, const DataChangeListener *listener) +{ + uint32_t index; + ListenerEntry *entry = NULL; + g_broadcastMutex->lock(g_broadcastMutex); + FOR_EACH_HC_VECTOR(g_listenerEntryVec, index, entry) { + if ((entry != NULL) && (strcmp(entry->appId, appId) == 0)) { + if (memcpy_s(entry->listener, sizeof(DataChangeListener), + listener, sizeof(DataChangeListener)) != HC_SUCCESS) { + g_broadcastMutex->unlock(g_broadcastMutex); + LOGE("Failed to copy listener!"); + return HC_ERR_MEMORY_COPY; + } + g_broadcastMutex->unlock(g_broadcastMutex); + return HC_SUCCESS; + } + } + g_broadcastMutex->unlock(g_broadcastMutex); + return HC_ERR_LISTENER_NOT_EXIST; +} + +static int32_t AddListenerIfNotExist(const char *appId, const DataChangeListener *listener) +{ + uint32_t appIdLen = HcStrlen(appId) + 1; + char *copyAppId = (char *)HcMalloc(appIdLen, 0); + if (copyAppId == NULL) { + LOGE("Failed to allocate copyAppId memory!"); + return HC_ERR_ALLOC_MEMORY; + } + if (strcpy_s(copyAppId, appIdLen, appId) != HC_SUCCESS) { + LOGE("Failed to copy appId!"); + HcFree(copyAppId); + return HC_ERR_MEMORY_COPY; + } + DataChangeListener *copyListener = (DataChangeListener *)HcMalloc(sizeof(DataChangeListener), 0); + if (copyListener == NULL) { + LOGE("Failed to allocate saveCallback memory!"); + HcFree(copyAppId); + return HC_ERR_ALLOC_MEMORY; + } + if (memcpy_s(copyListener, sizeof(DataChangeListener), + listener, sizeof(DataChangeListener)) != HC_SUCCESS) { + LOGE("Failed to copy listener!"); + HcFree(copyAppId); + HcFree(copyListener); + return HC_ERR_MEMORY_COPY; + } + ListenerEntry entry; + entry.appId = copyAppId; + entry.listener = copyListener; + g_broadcastMutex->lock(g_broadcastMutex); + g_listenerEntryVec.pushBack(&g_listenerEntryVec, &entry); + g_broadcastMutex->unlock(g_broadcastMutex); + LOGI("[End]: Service register listener successfully!"); + return HC_SUCCESS; +} + +static Broadcaster g_broadcaster = { + .postOnGroupCreated = PostOnGroupCreated, + .postOnGroupDeleted = PostOnGroupDeleted, + .postOnDeviceBound = PostOnDeviceBound, + .postOnDeviceUnBound = PostOnDeviceUnBound, + .postOnDeviceNotTrusted = PostOnDeviceNotTrusted, + .postOnLastGroupDeleted = PostOnLastGroupDeleted, + .postOnTrustedDeviceNumChanged = PostOnTrustedDeviceNumChanged +}; + +bool IsBroadcastSupported() +{ + return true; +} + +int32_t InitBroadcastManager() +{ + if (g_broadcastMutex == NULL) { + g_broadcastMutex = (HcMutex *)HcMalloc(sizeof(HcMutex), 0); + if (g_broadcastMutex == NULL) { + LOGE("Failed to allocate broadcast mutex memory!"); + return HC_ERR_ALLOC_MEMORY; + } + if (InitHcMutex(g_broadcastMutex) != HC_SUCCESS) { + LOGE("Init mutex failed"); + HcFree(g_broadcastMutex); + g_broadcastMutex = NULL; + return HC_ERROR; + } + } + g_listenerEntryVec = CREATE_HC_VECTOR(ListenerEntryVec) + LOGI("[Broadcaster]: Init broadcast manager module successfully!"); + return HC_SUCCESS; +} + +void DestroyBroadcastManager() +{ + uint32_t index; + ListenerEntry *entry = NULL; + FOR_EACH_HC_VECTOR(g_listenerEntryVec, index, entry) { + if (entry != NULL) { + HcFree(entry->appId); + HcFree(entry->listener); + } + } + DESTROY_HC_VECTOR(ListenerEntryVec, &g_listenerEntryVec) + if (g_broadcastMutex != NULL) { + DestroyHcMutex(g_broadcastMutex); + HcFree(g_broadcastMutex); + g_broadcastMutex = NULL; + } +} + +Broadcaster *GetBroadcaster() +{ + return &g_broadcaster; +} + +int32_t AddListener(const char *appId, const DataChangeListener *listener) +{ + if ((appId == NULL) || (listener == NULL)) { + LOGE("The input appId or listener is NULL!"); + return HC_ERR_INVALID_PARAMS; + } + if (UpdateListenerIfExist(appId, listener) == HC_SUCCESS) { + LOGI("The listener associated with the appId already exists, so we choose to update the listener!"); + return HC_SUCCESS; + } + return AddListenerIfNotExist(appId, listener); +} + +int32_t RemoveListener(const char *appId) +{ + if (appId == NULL) { + LOGE("The input appId is NULL!"); + return HC_ERR_INVALID_PARAMS; + } + uint32_t index; + ListenerEntry *entry = NULL; + FOR_EACH_HC_VECTOR(g_listenerEntryVec, index, entry) { + if (strcmp(entry->appId, appId) == 0) { + HcFree(entry->appId); + HcFree(entry->listener); + ListenerEntry tempEntry; + HC_VECTOR_POPELEMENT(&g_listenerEntryVec, &tempEntry, index); + LOGI("[End]: Service deregister listener successfully!"); + return HC_SUCCESS; + } + } + LOGI("[End]: Although the listener does not exist, we still believe it is correct to deregister the listener!"); + return HC_SUCCESS; +} diff --git a/services/common/src/broadcast_manager_mock/broadcast_manager_mock.c b/services/common/src/broadcast_manager_mock/broadcast_manager_mock.c new file mode 100644 index 0000000..546c860 --- /dev/null +++ b/services/common/src/broadcast_manager_mock/broadcast_manager_mock.c @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "broadcast_manager.h" +#include "device_auth_defines.h" +#include "hc_log.h" + +bool IsBroadcastSupported() +{ + return false; +} + +int32_t InitBroadcastManager() +{ + return HC_SUCCESS; +} + +void DestroyBroadcastManager() +{ + return; +} + +Broadcaster *GetBroadcaster() +{ + return NULL; +} + +int32_t AddListener(const char *appId, const DataChangeListener *listener) +{ + (void)appId; + (void)listener; + LOGE("Broadcast manager is not supported!"); + return HC_ERR_NOT_SUPPORT; +} + +int32_t RemoveListener(const char *appId) +{ + (void)appId; + LOGE("Broadcast manager is not supported!"); + return HC_ERR_NOT_SUPPORT; +} diff --git a/services/common/src/callback_manager/callback_manager.c b/services/common/src/callback_manager/callback_manager.c new file mode 100644 index 0000000..bc33f67 --- /dev/null +++ b/services/common/src/callback_manager/callback_manager.c @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "callback_manager.h" +#include "hc_log.h" + +bool ProcessTransmitCallback(int64_t requestId, const uint8_t *data, uint32_t dataLen, + const DeviceAuthCallback *callback) +{ + LOGI("[OnTransmit]: We're going to notify the service! [RequestId]: %lld, [DataLen]: %d", requestId, dataLen); + if ((callback != NULL) && (callback->onTransmit != NULL)) { + if (callback->onTransmit(requestId, data, dataLen)) { + LOGI("[OnTransmit]: We notify the service successfully! [RequestId]: %lld, [DataLen]: %d", + requestId, dataLen); + return true; + } + LOGE("[OnTransmit]: An error occurs when the service channel sends data! [RequestId]: %lld, [DataLen]: %d", + requestId, dataLen); + return false; + } + LOGE("[OnTransmit]: Currently, the service callback is NULL! [RequestId]: %lld, [DataLen]: %d", requestId, dataLen); + return false; +} + +void ProcessSessionKeyCallback(int64_t requestId, const uint8_t *sessionKey, uint32_t sessionKeyLen, + const DeviceAuthCallback *callback) +{ + const char *isSessionKeyExist = (sessionKeyLen > 0) ? "true" : "false"; + LOGI("[OnSessionKeyReturned]: We're going to notify the service! [RequestId]: %lld, [IsSessionKeyExist]: %s", + requestId, isSessionKeyExist); + if ((callback != NULL) && (callback->onSessionKeyReturned != NULL)) { + (void)callback->onSessionKeyReturned(requestId, sessionKey, sessionKeyLen); + LOGI("[OnSessionKeyReturned]: We notify the service successfully! [RequestId]: %lld, [IsSessionKeyExist]: %s", + requestId, isSessionKeyExist); + return; + } + LOGE("[OnSessionKeyReturned]: Currently, the service callback is NULL! [RequestId]: %lld, [IsSessionKeyExist]: %s", + requestId, isSessionKeyExist); +} + +void ProcessFinishCallback(int64_t requestId, int operationCode, const char *returnData, + const DeviceAuthCallback *callback) +{ + LOGI("[OnFinish]: We're going to notify the service! [RequestId]: %lld, [OperationCode]: %d", + requestId, operationCode); + if ((callback != NULL) && (callback->onFinish != NULL)) { + callback->onFinish(requestId, operationCode, returnData); + LOGI("[End]: [OnFinish]: We notify the service successfully! [RequestId]: %lld, [OperationCode]: %d", + requestId, operationCode); + return; + } + LOGE("[End]: [OnFinish]: Currently, the service callback is NULL! [RequestId]: %lld, [OperationCode]: %d", + requestId, operationCode); +} + +void ProcessErrorCallback(int64_t requestId, int operationCode, int errorCode, const char *errorReturn, + const DeviceAuthCallback *callback) +{ + LOGI("[OnError]: We're going to notify the service! [RequestId]: %lld, [OperationCode]: %d, [errorCode]: %d", + requestId, operationCode, errorCode); + if ((callback != NULL) && (callback->onError != NULL)) { + callback->onError(requestId, operationCode, errorCode, errorReturn); + LOGI("[End]: [OnError]: We notify the service successfully! " + "[RequestId]: %lld, [OperationCode]: %d, [errorCode]: %d", requestId, operationCode, errorCode); + return; + } + LOGE("[End]: [OnError]: Currently, the service callback is NULL! " + "[RequestId]: %lld, [OperationCode]: %d, [errorCode]: %d", requestId, operationCode, errorCode); +} + +char *ProcessRequestCallback(int64_t requestId, int operationCode, const char *reqParams, + const DeviceAuthCallback *callback) +{ + LOGI("[OnRequest]: We're going to notify the service! [RequestId]: %lld, [OperationCode]: %d", + requestId, operationCode); + if ((callback != NULL) && (callback->onRequest != NULL)) { + char *returnData = callback->onRequest(requestId, operationCode, reqParams); + LOGI("[OnRequest]: We notify the service successfully! [RequestId]: %lld, [OperationCode]: %d", + requestId, operationCode); + return returnData; + } + LOGE("[OnRequest]: Currently, the service callback is NULL! [RequestId]: %lld, [OperationCode]: %d", + requestId, operationCode); + return NULL; +} \ No newline at end of file diff --git a/services/common/src/channel_manager/channel_manager.c b/services/common/src/channel_manager/channel_manager.c new file mode 100644 index 0000000..258ade0 --- /dev/null +++ b/services/common/src/channel_manager/channel_manager.c @@ -0,0 +1,212 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "channel_manager.h" +#include "callback_manager.h" +#include "device_auth_defines.h" +#include "hc_log.h" +#include "hc_types.h" +#include "soft_bus_channel.h" + +int32_t InitChannelManager(void (*onChannelOpened)(int64_t, int64_t, const char *, uint32_t, bool), + void (*onChannelClosed)(int64_t, int64_t), + void (*onMsgReceived)(int64_t, const uint8_t *, uint32_t), + void (*onServiceDied)()) +{ + if (IsSoftBusChannelSupported()) { + int32_t res = InitSoftBusChannelModule(onChannelOpened, onChannelClosed, onMsgReceived, onServiceDied); + if (res != HC_SUCCESS) { + DestroyChannelManager(); + } + return res; + } + return HC_SUCCESS; +} + +void DestroyChannelManager() +{ + if (IsSoftBusChannelSupported()) { + DestroySoftBusChannelModule(); + } +} + +ChannelType GetChannelType(const DeviceAuthCallback *callback) +{ + if ((callback != NULL) && (callback->onTransmit != NULL)) { + return SERVICE_CHANNEL; + } + if (IsSoftBusChannelSupported()) { + return SOFT_BUS; + } + return NO_CHANNEL; +} + +bool CanFindValidChannel(ChannelType channelType, const CJson *jsonParams, const DeviceAuthCallback *callback) +{ + switch (channelType) { + case NO_CHANNEL: + return false; + case SERVICE_CHANNEL: + return ((callback != NULL) && (callback->onTransmit != NULL)) ? true : false; + case SOFT_BUS: + if (GetSoftBusInstance() == NULL) { + LOGE("The soft bus module is unavailable!"); + return false; + } + const char *connectParams = GetStringFromJson(jsonParams, FIELD_CONNECT_PARAMS); + if (connectParams == NULL) { + LOGE("Failed to get connectParams from jsonParams!"); + return false; + } + return true; + default: + LOGE("Enter the exception case!"); + return false; + } +} + +int32_t OpenChannel(ChannelType channelType, const CJson *jsonParams, int64_t requestId, int64_t *returnChannelId) +{ + int64_t channelId = DEFAULT_CHANNEL_ID; + const char *connectParams = NULL; + switch (channelType) { + case NO_CHANNEL: + LOGE("No channel!"); + return HC_ERR_CHANNEL_NOT_EXIST; + case SERVICE_CHANNEL: + LOGI("Use service channel, so we do not need to open it!"); + *returnChannelId = channelId; + return HC_SUCCESS; + case SOFT_BUS: + connectParams = GetStringFromJson(jsonParams, FIELD_CONNECT_PARAMS); + if (connectParams == NULL) { + LOGE("Failed to get connectParams from jsonParams!"); + return HC_ERR_JSON_GET; + } + SoftBus *softBusInstance = GetSoftBusInstance(); + if (softBusInstance == NULL) { + LOGE("The soft bus module is unavailable!"); + return HC_ERR_SOFT_BUS; + } + int32_t result = softBusInstance->openChannel(connectParams, requestId, &channelId); + if (result != HC_SUCCESS) { + LOGE("Failed to open soft bus channel!"); + return HC_ERR_CHANNEL_NOT_EXIST; + } + *returnChannelId = channelId; + return HC_SUCCESS; + default: + LOGE("Enter the exception case!"); + return HC_ERR_CASE; + } +} + +void CloseChannel(ChannelType channelType, int64_t channelId) +{ + SoftBus *softBusInstance = NULL; + switch (channelType) { + case NO_CHANNEL: + LOGE("No channel!"); + return; + case SERVICE_CHANNEL: + LOGI("Use service channel, so we do not need to close it!"); + return; + case SOFT_BUS: + softBusInstance = GetSoftBusInstance(); + if (softBusInstance == NULL) { + LOGI("The soft bus module is unavailable!"); + return; + } + softBusInstance->closeChannel(channelId); + return; + default: + LOGI("Enter the exception case!"); + return; + } +} + +int32_t SendMsg(ChannelType channelType, int64_t requestId, int64_t channelId, + const DeviceAuthCallback *callback, const char *data) +{ + SoftBus *softBusInstance = NULL; + switch (channelType) { + case NO_CHANNEL: + LOGE("No channel!"); + return HC_ERR_CHANNEL_NOT_EXIST; + case SERVICE_CHANNEL: + if (ProcessTransmitCallback(requestId, (uint8_t *)data, HcStrlen(data) + 1, callback)) { + return HC_SUCCESS; + } + return HC_ERR_TRANSMIT_FAIL; + case SOFT_BUS: + softBusInstance = GetSoftBusInstance(); + if (softBusInstance == NULL) { + LOGE("The soft bus module is unavailable!"); + return HC_ERR_SOFT_BUS; + } + return softBusInstance->sendMsg(channelId, (uint8_t *)data, HcStrlen(data) + 1); + default: + LOGE("Enter the exception case!"); + return HC_ERR_CASE; + } +} + +void SetAuthResult(ChannelType channelType, int64_t channelId) +{ + SoftBus *softBusInstance = NULL; + switch (channelType) { + case NO_CHANNEL: + LOGI("No channel!"); + return; + case SERVICE_CHANNEL: + return; + case SOFT_BUS: + softBusInstance = GetSoftBusInstance(); + if (softBusInstance == NULL) { + LOGI("The soft bus module is unavailable!"); + return; + } + softBusInstance->setAuthResult(channelId); + return; + default: + LOGI("Enter the exception case!"); + return; + } +} + +int32_t GetLocalConnectInfo(char **returnInfo) +{ + if (!IsSoftBusChannelSupported()) { + LOGE("Soft bus not supported!"); + return HC_ERR_NOT_SUPPORT; + } + SoftBus *softBusInstance = GetSoftBusInstance(); + if (softBusInstance == NULL) { + LOGE("The soft bus module is unavailable!"); + return HC_ERR_SOFT_BUS; + } + if (returnInfo != NULL) { + LOGI("We're going to get local connection information!"); + *returnInfo = softBusInstance->getLocalAuthInfo(); + if (*returnInfo == NULL) { + LOGE("Failed to get local connection information!"); + return HC_ERR_SOFT_BUS; + } + LOGI("Get local connection information successfully!"); + return HC_SUCCESS; + } + LOGE("The address of the input returnLocalConnectInfo is NULL!"); + return HC_ERR_INVALID_PARAMS; +} diff --git a/services/common/src/channel_manager/soft_bus_channel/soft_bus_channel.c b/services/common/src/channel_manager/soft_bus_channel/soft_bus_channel.c new file mode 100644 index 0000000..1810f8b --- /dev/null +++ b/services/common/src/channel_manager/soft_bus_channel/soft_bus_channel.c @@ -0,0 +1,243 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "soft_bus_channel.h" +#include "common_defs.h" +#include "device_auth_defines.h" +#include "hc_log.h" + +typedef struct { + void (*onChannelOpened)(int64_t channelId, int64_t requestId, const char *deviceId, + uint32_t deviceIdLen, bool isServer); + void (*onChannelClosed)(int64_t channelId, int64_t requestId); + void (*onMsgReceived)(int64_t channelId, const uint8_t *data, uint32_t dataLen); + void (*onServiceDied)(); +} IAuthMsgListener; + +typedef struct { + int (*addListener)(const char *packageName, const IAuthMsgListener *listener); + int (*removeListener)(const char *packageName); + int64_t (*openAuthChannel)(const char *packageName, const char *authInfo, int64_t requestId); + int (*closeChannel)(int64_t channelId); + int (*sendMsg)(int64_t channelId, const uint8_t *data, uint32_t len); + int (*setAuthResult)(int64_t channelId, const uint8_t *data, uint32_t len); + char *(*getLocalAuthInfo)(); +} AuthMsgService; + +#define NORMAL_CHANNEL_ID 1 + +static int AddListener(const char *packageName, const IAuthMsgListener *listener) +{ + (void)packageName; + (void)listener; + return HC_SUCCESS; +} + +static int RemoveListener(const char *packageName) +{ + (void)packageName; + return HC_SUCCESS; +} + +static int64_t OpenAuthChannel(const char *packageName, const char *connectParams, int64_t requestId) +{ + (void)packageName; + (void)connectParams; + (void)requestId; + return NORMAL_CHANNEL_ID; +} + +static int CloseChannel(int64_t channelId) +{ + (void)channelId; + return HC_SUCCESS; +} + +static int SendMsg(int64_t channelId, const uint8_t *data, uint32_t dataLen) +{ + (void)channelId; + (void)data; + (void)dataLen; + return HC_SUCCESS; +} + +static int SetAuthResult(int64_t channelId, const uint8_t *data, uint32_t dataLen) +{ + (void)channelId; + (void)data; + (void)dataLen; + return HC_SUCCESS; +} + +static char *GetLocalAuthInfo() +{ + return ""; +} + +static AuthMsgService g_softBusInstance = { + .addListener = AddListener, + .removeListener = RemoveListener, + .openAuthChannel = OpenAuthChannel, + .closeChannel = CloseChannel, + .sendMsg = SendMsg, + .setAuthResult = SetAuthResult, + .getLocalAuthInfo = GetLocalAuthInfo +}; + +static AuthMsgService *GetInstance(const char *packageName) +{ + (void)packageName; + return &g_softBusInstance; +} + +static int32_t OpenSoftBusChannel(const char *connectParams, int64_t requestId, int64_t *returnChannelId) +{ + if (returnChannelId == NULL) { + LOGE("The address of the input returnChannelId is NULL!"); + return HC_ERR_NULL_PTR; + } + AuthMsgService *instance = GetInstance(GROUP_MANAGER_PACKAGE_NAME); + if (instance == NULL) { + LOGE("Failed to get soft bus instance!"); + return HC_ERR_SOFT_BUS; + } + LOGI("Ready to open the soft bus channel!"); + int64_t channelId = instance->openAuthChannel(GROUP_MANAGER_PACKAGE_NAME, connectParams, requestId); + /* If the value of channelId is less than 0, the soft bus fails to open the channel */ + if (channelId < 0) { + LOGE("Failed to open soft bus channel!"); + return HC_ERR_SOFT_BUS; + } + LOGI("Open soft bus channel successfully!"); + *returnChannelId = channelId; + return HC_SUCCESS; +} + +static void CloseSoftBusChannel(int64_t channelId) +{ + AuthMsgService *instance = GetInstance(GROUP_MANAGER_PACKAGE_NAME); + if (instance == NULL) { + LOGE("Failed to get soft bus instance!"); + return; + } + LOGI("Ready to close the soft bus channel!"); + int32_t result = instance->closeChannel(channelId); + if (result != HC_SUCCESS) { + LOGE("Failed to close soft bus channel!"); + } + LOGI("Close soft bus channel success!"); +} + +static int32_t SendSoftBusMsg(int64_t channelId, const uint8_t *data, uint32_t dataLen) +{ + AuthMsgService *instance = GetInstance(GROUP_MANAGER_PACKAGE_NAME); + if (instance == NULL) { + LOGE("Failed to get soft bus instance!"); + return HC_ERR_SOFT_BUS; + } + LOGI("The soft bus channel starts to send data!"); + int32_t result = instance->sendMsg(channelId, data, dataLen); + if (result != HC_SUCCESS) { + LOGE("An error occurs when the soft bus channel sends data!"); + return HC_ERR_SOFT_BUS; + } + LOGI("The soft bus channel sends data successfully!"); + return HC_SUCCESS; +} + +static void SetSoftBusAuthResult(int64_t channelId) +{ + AuthMsgService *instance = GetInstance(GROUP_MANAGER_PACKAGE_NAME); + if (instance == NULL) { + LOGE("Failed to get soft bus instance!"); + return; + } + LOGI("Prepare to notify the soft bus authentication result!"); + int32_t result = instance->setAuthResult(channelId, NULL, 0); + if (result != HC_SUCCESS) { + LOGE("Failed to notify the soft bus of the authentication result!"); + return; + } + LOGI("The soft bus is successfully notified of the authentication result!"); +} + +static char *GetSoftBusLocalAuthInfo() +{ + AuthMsgService *instance = GetInstance(GROUP_MANAGER_PACKAGE_NAME); + if (instance == NULL) { + LOGE("Failed to get soft bus instance!"); + return ""; + } + return instance->getLocalAuthInfo(); +} + +SoftBus g_softBus = { + .openChannel = OpenSoftBusChannel, + .closeChannel = CloseSoftBusChannel, + .sendMsg = SendSoftBusMsg, + .setAuthResult = SetSoftBusAuthResult, + .getLocalAuthInfo = GetSoftBusLocalAuthInfo +}; + +int32_t InitSoftBusChannelModule(void (*onChannelOpened)(int64_t, int64_t, const char *, uint32_t, bool), + void (*onChannelClosed)(int64_t, int64_t), + void (*onMsgReceived)(int64_t, const uint8_t *, uint32_t), + void (*onServiceDied)()) +{ + IAuthMsgListener softBusListener = { + .onChannelOpened = onChannelOpened, + .onChannelClosed = onChannelClosed, + .onMsgReceived = onMsgReceived, + .onServiceDied = onServiceDied + }; + AuthMsgService *instance = GetInstance(GROUP_MANAGER_PACKAGE_NAME); + if (instance == NULL) { + LOGE("Failed to get soft bus instance!"); + return HC_ERR_SOFT_BUS; + } + LOGI("Prepare to add listener callback to soft bus service!"); + int32_t result = instance->addListener(GROUP_MANAGER_PACKAGE_NAME, &softBusListener); + if (result != HC_SUCCESS) { + LOGE("Failed to add listener callback to soft bus service!"); + return HC_ERR_SOFT_BUS; + } + LOGI("Add listener callback to soft bus service successfully!"); + return HC_SUCCESS; +} + +void DestroySoftBusChannelModule() +{ + AuthMsgService *instance = GetInstance(GROUP_MANAGER_PACKAGE_NAME); + if (instance == NULL) { + LOGI("Failed to get soft bus instance!"); + return; + } + LOGI("Prepare to remove listener callback from soft bus service!"); + int32_t result = instance->removeListener(GROUP_MANAGER_PACKAGE_NAME); + if (result != HC_SUCCESS) { + LOGI("Failed to remove listener callback from soft bus module!"); + } + LOGI("Remove listener callback from soft bus service successfully!"); +} + +SoftBus *GetSoftBusInstance() +{ + return &g_softBus; +} + +bool IsSoftBusChannelSupported() +{ + return true; +} \ No newline at end of file diff --git a/services/common/src/channel_manager/soft_bus_channel_mock/soft_bus_channel_mock.c b/services/common/src/channel_manager/soft_bus_channel_mock/soft_bus_channel_mock.c new file mode 100755 index 0000000..c8675b3 --- /dev/null +++ b/services/common/src/channel_manager/soft_bus_channel_mock/soft_bus_channel_mock.c @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "soft_bus_channel.h" +#include "device_auth_defines.h" +#include "hc_types.h" + +int32_t InitSoftBusChannelModule(void (*onChannelOpened)(int64_t, int64_t, const char *, uint32_t, bool), + void (*onChannelClosed)(int64_t, int64_t), + void (*onMsgReceived)(int64_t, const uint8_t *, uint32_t), + void (*onServiceDied)()) +{ + return HC_SUCCESS; +} + +void DestroySoftBusChannelModule() +{ + return; +} + +SoftBus *GetSoftBusInstance() +{ + return NULL; +} + +bool IsSoftBusChannelSupported() +{ + return false; +} \ No newline at end of file diff --git a/services/common/src/data_base/database_manager.c b/services/common/src/data_base/database_manager.c new file mode 100644 index 0000000..ccf08da --- /dev/null +++ b/services/common/src/data_base/database_manager.c @@ -0,0 +1,2466 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "alg_defs.h" +#include "database.h" +#include "database_manager.h" +#include "device_auth.h" +#include "hc_dev_info.h" +#include "hc_file.h" +#include "hc_log.h" +#include "hc_mutex.h" +#include "securec.h" + +#define MAX_STRING_LEN 256 + +DEFINE_TLV_FIX_LENGTH_TYPE(TlvDevAuthFixedLenInfo, NO_REVERT) + +BEGIN_TLV_STRUCT_DEFINE(TlvGroupElement, 0x0001) + TLV_MEMBER(TlvString, name, 0x4001) + TLV_MEMBER(TlvString, id, 0x4002) + TLV_MEMBER(TlvUint32, type, 0x4003) + TLV_MEMBER(TlvInt32, visibility, 0x4004) + TLV_MEMBER(TlvInt32, expireTime, 0x4005) + TLV_MEMBER(TlvInt64, userId, 0x4006) + TLV_MEMBER(TlvBuffer, sharedUserIdVec, 0x4007) + TLV_MEMBER(TlvBuffer, managers, 0x4008) + TLV_MEMBER(TlvBuffer, friends, 0x4009) +END_TLV_STRUCT_DEFINE() +IMPLEMENT_TLV_VECTOR(TlvGroupVec, TlvGroupElement, 1) + +BEGIN_TLV_STRUCT_DEFINE(TlvDevAuthElement, 0x0002) + TLV_MEMBER(TlvString, groupId, 0x4101) + TLV_MEMBER(TlvString, udid, 0x4102) + TLV_MEMBER(TlvString, authId, 0x4103) + TLV_MEMBER(TlvString, serviceType, 0x4104) + TLV_MEMBER(TlvBuffer, ext, 0x4105) + TLV_MEMBER(TlvDevAuthFixedLenInfo, info, 0x4106) +END_TLV_STRUCT_DEFINE() +IMPLEMENT_TLV_VECTOR(TlvDevAuthVec, TlvDevAuthElement, 2) + +BEGIN_TLV_STRUCT_DEFINE(HCDataBaseV1, 0x0001) + TLV_MEMBER(TlvInt32, version, 0x6001) + TLV_MEMBER(TlvGroupVec, groups, 0x6002) + TLV_MEMBER(TlvDevAuthVec, deviceAuthInfos, 0x6003) +END_TLV_STRUCT_DEFINE() + +IMPLEMENT_HC_VECTOR(TrustedGroupTable, TrustedGroupEntry *, 1) +IMPLEMENT_HC_VECTOR(TrustedDeviceTable, TrustedDeviceEntry, 2) +IMPLEMENT_HC_VECTOR(StringVector, HcString, 1) +IMPLEMENT_HC_VECTOR(Int64Vector, int64_t, 1) +IMPLEMENT_HC_VECTOR(GroupInfoVec, void *, 1) +IMPLEMENT_HC_VECTOR(DeviceInfoVec, void *, 2) + +static TrustedGroupTable g_trustedGroupTable; +static TrustedDeviceTable g_trustedDeviceTable; + +/* cache across account groupId func */ +static int32_t (*g_generateIdFunc)(int64_t userId, int64_t sharedUserId, char **returnGroupId) = NULL; + +/* cache broadcaster instance */ +static const Broadcaster *g_broadcaster = NULL; + +static HcMutex *g_databaseMutex = NULL; + +static void DestroyStrVector(StringVector *vec) +{ + uint32_t index; + HcString *strItemPtr = NULL; + FOR_EACH_HC_VECTOR(*vec, index, strItemPtr) { + DeleteString(strItemPtr); + } + DESTROY_HC_VECTOR(StringVector, vec) +} + +static TrustedGroupEntry *CreateGroupEntryStruct() +{ + TrustedGroupEntry *ptr = (TrustedGroupEntry *)HcMalloc(sizeof(TrustedGroupEntry), 0); + if (ptr == NULL) { + return NULL; + } + ptr->name = CreateString(); + ptr->id = CreateString(); + ptr->sharedUserIdVec = CREATE_HC_VECTOR(Int64Vector) + ptr->managers = CREATE_HC_VECTOR(StringVector) + ptr->friends = CREATE_HC_VECTOR(StringVector) + return ptr; +} + +static void DestroyGroupEntryStruct(TrustedGroupEntry *groupEntry) +{ + DeleteString(&groupEntry->name); + DeleteString(&groupEntry->id); + DestroyStrVector(&groupEntry->managers); + DestroyStrVector(&groupEntry->friends); + DESTROY_HC_VECTOR(Int64Vector, &groupEntry->sharedUserIdVec) +} + +static void DestroyGroupTable() +{ + uint32_t groupIndex; + TrustedGroupEntry **entry = NULL; + FOR_EACH_HC_VECTOR(g_trustedGroupTable, groupIndex, entry) { + DestroyGroupEntryStruct(*entry); + HcFree(*entry); + } + DESTROY_HC_VECTOR(TrustedGroupTable, &g_trustedGroupTable) +} + +static void DestroyDeviceEntryStruct(TrustedDeviceEntry *deviceEntry) +{ + DeleteString(&deviceEntry->udid); + DeleteString(&deviceEntry->authId); + DeleteString(&deviceEntry->serviceType); + DeleteParcel(&deviceEntry->ext); +} + +static void DestroyTrustDevTable() +{ + uint32_t devIndex; + TrustedDeviceEntry *deviceEntry = NULL; + FOR_EACH_HC_VECTOR(g_trustedDeviceTable, devIndex, deviceEntry) { + DestroyDeviceEntryStruct(deviceEntry); + } + DESTROY_HC_VECTOR(TrustedDeviceTable, &g_trustedDeviceTable) +} + +static int32_t GetSharedUserIdFromVecByGroupId(const TrustedGroupEntry *groupEntry, const char *groupId, + int64_t *userId) +{ + if ((groupEntry->type != ACROSS_ACCOUNT_AUTHORIZE_GROUP) || (g_generateIdFunc == NULL)) { + return HC_ERR_NOT_SUPPORT; + } + /* The groupId of the across account group needs to be generated temporarily due to device resource problems. */ + uint32_t index; + int64_t *sharedUserId = NULL; + FOR_EACH_HC_VECTOR(groupEntry->sharedUserIdVec, index, sharedUserId) { + char *tempGroupId = NULL; + int32_t result = g_generateIdFunc(groupEntry->userId, *sharedUserId, &tempGroupId); + if (result != HC_SUCCESS) { + LOGE("[DB]: Failed to generate temp groupId!"); + return result; + } + bool isEquals = (strcmp(tempGroupId, groupId) == 0) ? true : false; + HcFree(tempGroupId); + if (isEquals) { + *userId = *sharedUserId; + return HC_SUCCESS; + } + } + return HC_ERR_GROUP_NOT_EXIST; +} + +static bool IsGroupNameEquals(const TrustedGroupEntry *groupEntry, const char *groupName) +{ + if ((strcmp(StringGet(&groupEntry->name), groupName) == 0)) { + return true; + } + int64_t sharedUserId = DEFAULT_USER_ID; + if (GetSharedUserIdFromVecByGroupId(groupEntry, groupName, &sharedUserId) == HC_SUCCESS) { + return true; + } + return false; +} + +static bool IsGroupIdEquals(const TrustedGroupEntry *groupEntry, const char *groupId) +{ + if ((strcmp(StringGet(&groupEntry->id), groupId) == 0)) { + return true; + } + int64_t sharedUserId = DEFAULT_USER_ID; + if (GetSharedUserIdFromVecByGroupId(groupEntry, groupId, &sharedUserId) == HC_SUCCESS) { + return true; + } + return false; +} + +static bool CompareGroupIdInDeviceEntryOrNull(const TrustedDeviceEntry *deviceEntry, const char *groupId) +{ + if (groupId == NULL) { + return true; + } else { + const char *tmpGroupId = (deviceEntry->groupEntry->type != ACROSS_ACCOUNT_AUTHORIZE_GROUP) ? + (StringGet(&deviceEntry->groupEntry->id)) : (StringGet(&deviceEntry->serviceType)); + return (strcmp(tmpGroupId, groupId) == 0); + } +} + +static bool CompareUdidInDeviceEntryOrNull(const TrustedDeviceEntry *deviceEntry, const char *udid) +{ + if (udid == NULL) { + return true; + } else { + return (strcmp(StringGet(&deviceEntry->udid), udid) == 0); + } +} + +static bool CompareAuthIdInDeviceEntryOrNull(const TrustedDeviceEntry *deviceEntry, const char *authId) +{ + if (authId == NULL) { + return true; + } else { + return (strcmp(StringGet(&deviceEntry->authId), authId) == 0); + } +} + +static TrustedDeviceEntry *GetTrustedDeviceEntry(const char *udid, const char *groupId) +{ + uint32_t index; + TrustedDeviceEntry *deviceEntry = NULL; + FOR_EACH_HC_VECTOR(g_trustedDeviceTable, index, deviceEntry) { + if (CompareUdidInDeviceEntryOrNull(deviceEntry, udid)) { + if (CompareGroupIdInDeviceEntryOrNull(deviceEntry, groupId)) { + return deviceEntry; + } + } + } + return NULL; +} + +static TrustedDeviceEntry *GetTrustedDeviceEntryByAuthId(const char *authId, const char *groupId) +{ + uint32_t index; + TrustedDeviceEntry *deviceEntry = NULL; + FOR_EACH_HC_VECTOR(g_trustedDeviceTable, index, deviceEntry) { + if (CompareAuthIdInDeviceEntryOrNull(deviceEntry, authId)) { + if (CompareGroupIdInDeviceEntryOrNull(deviceEntry, groupId)) { + return deviceEntry; + } + } + } + return NULL; +} + +/* + * Currently, this interface does not return the actual number of trusted devices. + * If at least one trusted device exists, return 1. Otherwise, return 0. + */ +static int GetTrustedDeviceNum() +{ + return (g_trustedDeviceTable.size(&g_trustedDeviceTable) > 0) ? 1 : 0; +} + +static int32_t GenerateCommonGroupInfoByEntry(const TrustedGroupEntry *groupEntry, GroupInfo *returnGroupInfo) +{ + if (HC_VECTOR_SIZE(&(groupEntry->managers)) == 0) { + LOGE("[DB]: The group owner is lost!"); + return HC_ERR_LOST_DATA; + } + HcString entryOwner = HC_VECTOR_GET(&groupEntry->managers, 0); + if (!StringSet(&(returnGroupInfo->ownerName), entryOwner)) { + LOGE("[DB]: Failed to copy groupOwner!"); + return HC_ERR_MEMORY_COPY; + } + returnGroupInfo->type = groupEntry->type; + returnGroupInfo->visibility = groupEntry->visibility; + returnGroupInfo->expireTime = groupEntry->expireTime; + returnGroupInfo->userId = groupEntry->userId; + return HC_SUCCESS; +} + +static int32_t GenerateGroupInfoIdAndName(const char *groupId, const char *groupName, GroupInfo *returnGroupInfo) +{ + if (!StringSetPointer(&(returnGroupInfo->id), groupId)) { + LOGE("[DB]: Failed to copy groupId!"); + return HC_ERR_MEMORY_COPY; + } + if (!StringSetPointer(&(returnGroupInfo->name), groupName)) { + LOGE("[DB]: Failed to copy groupName!"); + return HC_ERR_MEMORY_COPY; + } + return HC_SUCCESS; +} + +static void GenerateGroupInfoSharedUserId(int64_t sharedUserId, GroupInfo *returnGroupInfo) +{ + returnGroupInfo->sharedUserId = sharedUserId; +} + +static int32_t GenerateGroupInfoByEntry(const TrustedGroupEntry *groupEntry, int64_t userId, GroupInfo *returnGroupInfo) +{ + int32_t result; + if ((groupEntry->type != ACROSS_ACCOUNT_AUTHORIZE_GROUP) || (g_generateIdFunc == NULL)) { + result = GenerateCommonGroupInfoByEntry(groupEntry, returnGroupInfo); + if (result != HC_SUCCESS) { + return result; + } + return GenerateGroupInfoIdAndName(StringGet(&groupEntry->id), StringGet(&groupEntry->name), returnGroupInfo); + } + char *tempGroupId = NULL; + result = g_generateIdFunc(groupEntry->userId, userId, &tempGroupId); + if (result != HC_SUCCESS) { + LOGE("[DB]: Failed to generate temp groupId!"); + return result; + } + result = GenerateGroupInfoIdAndName(tempGroupId, tempGroupId, returnGroupInfo); + HcFree(tempGroupId); + if (result != HC_SUCCESS) { + return result; + } + GenerateGroupInfoSharedUserId(userId, returnGroupInfo); + return GenerateCommonGroupInfoByEntry(groupEntry, returnGroupInfo); +} + +static int32_t GenerateCommonDeviceInfoByEntry(const TrustedDeviceEntry *entry, DeviceInfo *returnDeviceInfo) +{ + if (!StringSet(&returnDeviceInfo->udid, entry->udid)) { + LOGE("[DB]: Failed to copy udid!"); + return HC_ERR_MEMORY_COPY; + } + if (!StringSet(&returnDeviceInfo->authId, entry->authId)) { + LOGE("[DB]: Failed to copy authId!"); + return HC_ERR_MEMORY_COPY; + } + if (!StringSet(&returnDeviceInfo->serviceType, entry->serviceType)) { + LOGE("[DB]: Failed to copy authId!"); + return HC_ERR_MEMORY_COPY; + } + returnDeviceInfo->credential = entry->credential; + returnDeviceInfo->devType = entry->devType; + returnDeviceInfo->userId = entry->userId; + return HC_SUCCESS; +} + +static int32_t GenerateDeviceInfoId(const char *groupId, DeviceInfo *returnDeviceInfo) +{ + if (!StringSetPointer(&(returnDeviceInfo->groupId), groupId)) { + LOGE("[DB]: Failed to copy groupId!"); + return HC_ERR_MEMORY_COPY; + } + return HC_SUCCESS; +} + +static int32_t GenerateDeviceInfoByEntry(const TrustedDeviceEntry *deviceEntry, DeviceInfo *returnDeviceInfo) +{ + int32_t result = GenerateCommonDeviceInfoByEntry(deviceEntry, returnDeviceInfo); + if (result != HC_SUCCESS) { + return result; + } + if (deviceEntry->groupEntry->type != ACROSS_ACCOUNT_AUTHORIZE_GROUP) { + return GenerateDeviceInfoId(StringGet(&deviceEntry->groupEntry->id), returnDeviceInfo); + } + return GenerateDeviceInfoId(StringGet(&deviceEntry->serviceType), returnDeviceInfo); +} + +static void NotifyGroupCreated(const TrustedGroupEntry *groupEntry, int64_t userId) +{ + if ((g_broadcaster == NULL) || (g_broadcaster->postOnGroupCreated == NULL)) { + return; + } + GroupInfo *groupInfo = CreateGroupInfoStruct(); + if (groupInfo == NULL) { + LOGE("[DB]: Failed to allocate groupInfo memory!"); + return; + } + if (GenerateGroupInfoByEntry(groupEntry, userId, groupInfo) != HC_SUCCESS) { + DestroyGroupInfoStruct(groupInfo); + return; + } + g_broadcaster->postOnGroupCreated(groupInfo); + DestroyGroupInfoStruct(groupInfo); +} + +static void NotifyGroupDeleted(const TrustedGroupEntry *groupEntry, int64_t userId) +{ + if ((g_broadcaster == NULL) || (g_broadcaster->postOnGroupDeleted == NULL)) { + return; + } + GroupInfo *groupInfo = CreateGroupInfoStruct(); + if (groupInfo == NULL) { + LOGE("[DB]: Failed to allocate groupInfo memory!"); + return; + } + if (GenerateGroupInfoByEntry(groupEntry, userId, groupInfo) != HC_SUCCESS) { + DestroyGroupInfoStruct(groupInfo); + return; + } + g_broadcaster->postOnGroupDeleted(groupInfo); + DestroyGroupInfoStruct(groupInfo); +} + +static void NotifyDeviceBound(const TrustedGroupEntry *groupEntry, const char *udid, int64_t sharedUserId) +{ + if ((g_broadcaster == NULL) || (g_broadcaster->postOnDeviceBound == NULL)) { + return; + } + GroupInfo *groupInfo = CreateGroupInfoStruct(); + if (groupInfo == NULL) { + LOGE("[DB]: Failed to allocate groupInfo memory!"); + return; + } + if (GenerateGroupInfoByEntry(groupEntry, sharedUserId, groupInfo) != HC_SUCCESS) { + DestroyGroupInfoStruct(groupInfo); + return; + } + g_broadcaster->postOnDeviceBound(udid, groupInfo); + DestroyGroupInfoStruct(groupInfo); +} + +static void NotifyDeviceUnBound(const TrustedGroupEntry *groupEntry, const char *udid, int64_t sharedUserId) +{ + if ((g_broadcaster == NULL) || (g_broadcaster->postOnDeviceUnBound == NULL)) { + return; + } + GroupInfo *groupInfo = CreateGroupInfoStruct(); + if (groupInfo == NULL) { + LOGE("[DB]: Failed to allocate groupInfo memory!"); + return; + } + if (GenerateGroupInfoByEntry(groupEntry, sharedUserId, groupInfo) != HC_SUCCESS) { + DestroyGroupInfoStruct(groupInfo); + return; + } + g_broadcaster->postOnDeviceUnBound(udid, groupInfo); + DestroyGroupInfoStruct(groupInfo); +} + +static void NotifyDeviceNotTrusted(const char *peerUdid) +{ + if (g_broadcaster != NULL && g_broadcaster->postOnDeviceNotTrusted != NULL) { + g_broadcaster->postOnDeviceNotTrusted(peerUdid); + } +} + +static void NotifyLastGroupDeleted(const char *peerUdid, int groupType) +{ + if (g_broadcaster != NULL && g_broadcaster->postOnLastGroupDeleted != NULL) { + g_broadcaster->postOnLastGroupDeleted(peerUdid, groupType); + } +} + +static void NotifyTrustedDeviceNumChanged() +{ + int trustedDeviceNum = GetTrustedDeviceNum(); + if (g_broadcaster != NULL && g_broadcaster->postOnTrustedDeviceNumChanged != NULL) { + g_broadcaster->postOnTrustedDeviceNumChanged(trustedDeviceNum); + } +} + +static void DeleteExpiredSharedUserId(const Int64Vector *sharedUserIdList, TrustedGroupEntry *entry) +{ + int64_t sharedUserId; + uint32_t sharedUserIdIndex = 0; + while (sharedUserIdIndex < entry->sharedUserIdVec.size(&entry->sharedUserIdVec)) { + sharedUserId = sharedUserIdList->get(sharedUserIdList, sharedUserIdIndex); + bool isNeedRemove = true; + uint32_t tmpIndex; + int64_t *tmpSharedUserId = NULL; + FOR_EACH_HC_VECTOR(*sharedUserIdList, tmpIndex, tmpSharedUserId) { + if (sharedUserId == *tmpSharedUserId) { + isNeedRemove = false; + break; + } + } + if (!isNeedRemove) { + sharedUserIdIndex++; + continue; + } + HC_VECTOR_POPELEMENT(&entry->sharedUserIdVec, tmpSharedUserId, sharedUserIdIndex); + NotifyGroupDeleted(entry, sharedUserId); + } +} + +static void AddNewSharedUserId(Int64Vector *sharedUserIdList, TrustedGroupEntry *entry) +{ + int64_t sharedUserId; + uint32_t sharedUserIdIndex = 0; + while (sharedUserIdIndex < sharedUserIdList->size(sharedUserIdList)) { + sharedUserId = sharedUserIdList->get(sharedUserIdList, sharedUserIdIndex); + bool isNeedAdd = true; + uint32_t tmpIndex; + int64_t *tmpSharedUserId = NULL; + FOR_EACH_HC_VECTOR(entry->sharedUserIdVec, tmpIndex, tmpSharedUserId) { + if (sharedUserId == *tmpSharedUserId) { + isNeedAdd = false; + break; + } + } + /* Release the memory in advance to reduce the memory usage. */ + HC_VECTOR_POPELEMENT(sharedUserIdList, &sharedUserId, sharedUserIdIndex); + if (!isNeedAdd) { + continue; + } + HC_VECTOR_PUSHBACK(&entry->sharedUserIdVec, &sharedUserId); + NotifyGroupCreated(entry, sharedUserId); + } +} + +static int GenerateGroupEntryByInfo(const GroupInfo *groupInfo, TrustedGroupEntry *entry) +{ + if (!StringSet(&entry->name, groupInfo->name)) { + LOGE("[DB]: Failed to copy groupName!"); + return HC_ERR_MEMORY_COPY; + } + if (!StringSet(&entry->id, groupInfo->id)) { + LOGE("[DB]: Failed to copy groupId!"); + return HC_ERR_MEMORY_COPY; + } + entry->type = groupInfo->type; + entry->visibility = groupInfo->visibility; + entry->expireTime = groupInfo->expireTime; + entry->userId = groupInfo->userId; + HcString ownerName = CreateString(); + if (!StringSet(&ownerName, groupInfo->ownerName)) { + LOGE("[DB]: Failed to copy groupOwner!"); + DeleteString(&ownerName); + return HC_ERR_ALLOC_MEMORY; + } + if (entry->managers.pushBack(&entry->managers, &ownerName) == NULL) { + LOGE("[DB]: Failed to push groupOwner to managers!"); + DeleteString(&ownerName); + return HC_ERR_MEMORY_COPY; + } + return HC_SUCCESS; +} + +static TrustedGroupEntry *GetGroupEntryByGroupIdInner(const char *groupId) +{ + uint32_t groupIndex; + TrustedGroupEntry **entry = NULL; + FOR_EACH_HC_VECTOR(g_trustedGroupTable, groupIndex, entry) { + if ((entry != NULL) && (*entry != NULL) && (IsGroupIdEquals(*entry, groupId))) { + return *entry; + } + } + return NULL; +} + +static bool InitAuthInfo(const DeviceInfo *deviceInfo, const Uint8Buff *ext, TrustedDeviceEntry *deviceEntry) +{ + deviceEntry->udid = CreateString(); + deviceEntry->authId = CreateString(); + deviceEntry->serviceType = CreateString(); + /* reserved field */ + deviceEntry->ext = CreateParcel(0, 0); + deviceEntry->groupEntry = GetGroupEntryByGroupIdInner(StringGet(&deviceInfo->groupId)); + if (deviceEntry->groupEntry == NULL) { + LOGE("[DB]: The group corresponding to groupId cannot be found!"); + return false; + } + if (!StringSet(&deviceEntry->udid, deviceInfo->udid)) { + return false; + } + if (!StringSet(&deviceEntry->authId, deviceInfo->authId)) { + return false; + } + if (!StringSet(&deviceEntry->serviceType, deviceInfo->serviceType)) { + return false; + } + deviceEntry->credential = deviceInfo->credential; + deviceEntry->devType = deviceInfo->devType; + deviceEntry->userId = deviceInfo->userId; + deviceEntry->lastTm = 0; + if (ext != NULL && ext->val != NULL) { + if (!ParcelWrite(&deviceEntry->ext, ext->val, ext->length)) { + LOGE("[DB]: Failed to copy extern data!"); + return false; + } + } + return true; +} + +static bool IsDeleteLastSuchTypeGroup(const char *udid, int groupType) +{ + uint32_t devIndex; + TrustedDeviceEntry *deviceEntry = NULL; + FOR_EACH_HC_VECTOR(g_trustedDeviceTable, devIndex, deviceEntry) { + if ((deviceEntry != NULL) && (deviceEntry->groupEntry != NULL)) { + const char *devUdid = StringGet(&deviceEntry->udid); + if ((strcmp(devUdid, udid) == 0) && (deviceEntry->groupEntry->type == groupType)) { + return false; + } + } + } + return true; +} + +static void CheckAndNotifyAfterDelDevice(const TrustedDeviceEntry *deviceEntry) +{ + const char *udid = StringGet(&deviceEntry->udid); + int64_t sharedUserId = DEFAULT_USER_ID; + if (deviceEntry->groupEntry->type == ACROSS_ACCOUNT_AUTHORIZE_GROUP) { + (void)GetSharedUserIdFromVecByGroupId(deviceEntry->groupEntry, StringGet(&deviceEntry->serviceType), + &sharedUserId); + } + NotifyDeviceUnBound(deviceEntry->groupEntry, udid, sharedUserId); + if (IsDeleteLastSuchTypeGroup(udid, deviceEntry->groupEntry->type)) { + NotifyLastGroupDeleted(udid, deviceEntry->groupEntry->type); + } + if (GetTrustedDeviceEntry(udid, NULL) == NULL) { + NotifyDeviceNotTrusted(udid); + NotifyTrustedDeviceNumChanged(); + } +} + +static bool SatisfyType(int32_t type, int32_t standardType) +{ + return ((standardType == ALL_GROUP) || (type == standardType)); +} + +static bool SatisfyVisibility(int32_t visibility, int32_t standardVisibility) +{ + return ((standardVisibility == ALL_GROUP_VISIBILITY) || (visibility == standardVisibility)); +} + +static bool SatisfyUdid(const char *udid, const char *standardUdid) +{ + return (strcmp(udid, standardUdid) == 0); +} + +static bool SatisfyAuthId(const char *authId, const char *standardAuthId) +{ + return (strcmp(authId, standardAuthId) == 0); +} + +static bool IsSatisfyGroup(const TrustedGroupEntry *entry, const GroupQueryParams *params) +{ + return (SatisfyType(entry->type, params->type) && SatisfyVisibility(entry->visibility, params->visibility)); +} + +static bool IsGroupManager(const char *appId, const TrustedGroupEntry *entry) +{ + uint32_t index; + HcString *manager = NULL; + FOR_EACH_HC_VECTOR(entry->managers, index, manager) { + if (strcmp(StringGet(manager), appId) == 0) { + return true; + } + } + return false; +} + +static bool IsGroupFriend(const char *appId, const TrustedGroupEntry *entry) +{ + uint32_t index; + HcString *trustedFriend = NULL; + FOR_EACH_HC_VECTOR(entry->friends, index, trustedFriend) { + if (strcmp(StringGet(trustedFriend), appId) == 0) { + return true; + } + } + return false; +} + +static bool CompareSearchParams(int groupType, const char *groupId, const char *groupName, const char *groupOwner, + const TrustedGroupEntry *entry) +{ + if ((groupType != ALL_GROUP) && (entry->type != groupType)) { + return false; + } + if ((groupId != NULL) && (!IsGroupIdEquals(entry, groupId))) { + return false; + } + if ((groupName != NULL) && (!IsGroupNameEquals(entry, groupName))) { + return false; + } + if (HC_VECTOR_SIZE(&(entry->managers)) == 0) { + LOGE("[DB]: The group owner is lost!"); + return false; + } + HcString entryOwner = HC_VECTOR_GET(&(entry->managers), 0); + if ((groupOwner != NULL) && (strcmp(StringGet(&entryOwner), groupOwner) != 0)) { + return false; + } + return true; +} + +static int32_t PushGroupInfoToVec(const TrustedGroupEntry *entry, GroupInfoVec *groupInfoVec) +{ + int32_t result; + if (entry->type != ACROSS_ACCOUNT_AUTHORIZE_GROUP) { + GroupInfo *groupInfo = CreateGroupInfoStruct(); + if (groupInfo == NULL) { + LOGE("[DB]: Failed to allocate groupInfo memory!"); + return HC_ERR_ALLOC_MEMORY; + } + result = GenerateGroupInfoByEntry(entry, DEFAULT_USER_ID, groupInfo); + if (result != HC_SUCCESS) { + DestroyGroupInfoStruct(groupInfo); + return result; + } + if (groupInfoVec->pushBackT(groupInfoVec, groupInfo) == NULL) { + LOGE("[DB]: Failed to push groupInfo to groupInfoVec!"); + DestroyGroupInfoStruct(groupInfo); + return HC_ERR_MEMORY_COPY; + } + return HC_SUCCESS; + } + uint32_t index; + int64_t *sharedUserId = NULL; + FOR_EACH_HC_VECTOR(entry->sharedUserIdVec, index, sharedUserId) { + GroupInfo *groupInfo = CreateGroupInfoStruct(); + if (groupInfo == NULL) { + LOGE("[DB]: Failed to allocate groupInfo memory!"); + return HC_ERR_ALLOC_MEMORY; + } + result = GenerateGroupInfoByEntry(entry, *sharedUserId, groupInfo); + if (result != HC_SUCCESS) { + DestroyGroupInfoStruct(groupInfo); + return result; + } + if (groupInfoVec->pushBackT(groupInfoVec, groupInfo) == NULL) { + LOGE("[DB]: Failed to push groupInfo to groupInfoVec!"); + DestroyGroupInfoStruct(groupInfo); + return HC_ERR_MEMORY_COPY; + } + } + return HC_SUCCESS; +} + +static int32_t PushDevInfoToVec(const TrustedDeviceEntry *entry, DeviceInfoVec *deviceInfoVec) +{ + DeviceInfo *deviceInfo = CreateDeviceInfoStruct(); + if (deviceInfo == NULL) { + LOGE("[DB]: Failed to allocate deviceInfo memory!"); + return HC_ERR_ALLOC_MEMORY; + } + int32_t result = GenerateDeviceInfoByEntry(entry, deviceInfo); + if (result != HC_SUCCESS) { + DestroyDeviceInfoStruct(deviceInfo); + return result; + } + if (deviceInfoVec->pushBackT(deviceInfoVec, deviceInfo) == NULL) { + LOGE("[DB]: Failed to push deviceInfo to deviceInfoVec!"); + DestroyDeviceInfoStruct(deviceInfo); + return HC_ERR_MEMORY_COPY; + } + return HC_SUCCESS; +} + +static bool IsSatisfyUdidAndAuthId(const TrustedDeviceEntry *deviceEntry, const GroupQueryParams *params) +{ + if ((params->udid != NULL) && (!SatisfyUdid(StringGet(&deviceEntry->udid), params->udid))) { + return false; + } + if ((params->authId != NULL) && (!SatisfyAuthId(StringGet(&deviceEntry->authId), params->authId))) { + return false; + } + return true; +} + +static int32_t GetGroupEntryInner(const char *groupId, const char *udid, GroupInfo *returnGroupInfo) +{ + int32_t result; + uint32_t index; + TrustedGroupEntry **entry = NULL; + FOR_EACH_HC_VECTOR(g_trustedGroupTable, index, entry) { + if (((*entry)->type != ACROSS_ACCOUNT_AUTHORIZE_GROUP) && (strcmp(StringGet(&(*entry)->id), groupId) == 0)) { + if (udid != NULL) { + if (GetTrustedDeviceEntry(udid, groupId) == NULL) { + LOGE("[DB]: The trusted device does not exist in the group!"); + return HC_ERR_DEVICE_NOT_EXIST; + } + } + return GenerateGroupInfoByEntry(*entry, DEFAULT_USER_ID, returnGroupInfo); + } + int64_t sharedUserId = DEFAULT_USER_ID; + result = GetSharedUserIdFromVecByGroupId(*entry, groupId, &sharedUserId); + if (result == HC_SUCCESS) { + if (udid != NULL) { + if (GetTrustedDeviceEntry(udid, groupId) == NULL) { + LOGE("[DB]: The trusted device does not exist in the group!"); + return HC_ERR_DEVICE_NOT_EXIST; + } + } + return GenerateGroupInfoByEntry(*entry, sharedUserId, returnGroupInfo); + } + } + LOGE("[DB]: The group does not exist!"); + return HC_ERR_GROUP_NOT_EXIST; +} + +static bool EndWithZero(HcParcel *parcel) +{ + const char *p = GetParcelLastChar(parcel); + if (p == NULL) { + return false; + } + if (*p == '\0') { + return true; + } + return false; +} + +static bool LoadInt64VectorFromParcel(Int64Vector* vec, HcParcel* parcel) +{ + do { + int64_t value; + if (!ParcelReadInt64(parcel, &value)) { + return true; + } + + if (vec->pushBack(vec, &value) == NULL) { + return false; + } + } while (1); +} + +static bool SaveInt64VectorToParcel(const Int64Vector* vec, HcParcel* parcel) +{ + uint32_t index; + int64_t *value = NULL; + FOR_EACH_HC_VECTOR(*vec, index, value) { + if (!ParcelWriteInt64(parcel, *value)) { + return false; + } + } + return true; +} + +static bool LoadStringVectorFromParcel(StringVector *vec, HcParcel *parcel) +{ + uint32_t strLen; + do { + if (!ParcelReadUint32(parcel, &strLen)) { + return true; + } + if (strLen > MAX_STRING_LEN) { + return false; + } + HcString str = CreateString(); + ClearParcel(&str.parcel); + if (!ParcelReadParcel(parcel, &str.parcel, strLen, false) || + !EndWithZero(&str.parcel)) { + DeleteString(&str); + return false; + } else { + if (vec->pushBack(vec, &str) == NULL) { + DeleteString(&str); + return false; + } + } + } while (1); +} + +static bool SaveStringVectorToParcel(const StringVector *vec, HcParcel *parcel) +{ + uint32_t index; + HcString *str = NULL; + FOR_EACH_HC_VECTOR(*vec, index, str) { + uint32_t len = StringLength(str) + sizeof(char); + if (!ParcelWriteUint32(parcel, len)) { + return false; + } + if (!ParcelWrite(parcel, GetParcelData(&str->parcel), GetParcelDataSize(&str->parcel))) { + return false; + } + } + return true; +} + +static bool SetGroupFromTlv(TrustedGroupEntry *entry, TlvGroupElement *group) +{ + entry->name = CreateString(); + entry->id = CreateString(); + entry->managers = CREATE_HC_VECTOR(StringVector) + entry->friends = CREATE_HC_VECTOR(StringVector) + entry->sharedUserIdVec = CREATE_HC_VECTOR(Int64Vector) + if (!LoadStringVectorFromParcel(&entry->managers, &group->managers.data)) { + return false; + } + if (!LoadStringVectorFromParcel(&entry->friends, &group->friends.data)) { + return false; + } + if (!LoadInt64VectorFromParcel(&entry->sharedUserIdVec, &group->sharedUserIdVec.data)) { + return false; + } + if (!StringSet(&entry->name, group->name.data)) { + return false; + } + if (!StringSet(&entry->id, group->id.data)) { + return false; + } + entry->type = group->type.data; + entry->visibility = group->visibility.data; + entry->expireTime = group->expireTime.data; + entry->userId = group->userId.data; + return true; +} + +static bool LoadGroupDb(HCDataBaseV1 *db) +{ + uint32_t index; + TlvGroupElement *group = NULL; + FOR_EACH_HC_VECTOR(db->groups.data, index, group) { + TrustedGroupEntry *entry = HcMalloc(sizeof(TrustedGroupEntry), 0); + if (entry == NULL) { + return false; + } + if (!SetGroupFromTlv(entry, group)) { + DestroyGroupEntryStruct(entry); + HcFree(entry); + return false; + } + if (g_trustedGroupTable.pushBack(&g_trustedGroupTable, (const TrustedGroupEntry **)&entry) == NULL) { + DestroyGroupEntryStruct(entry); + HcFree(entry); + return false; + } + } + return true; +} + +static bool SetDevAuthFromTlv(TrustedDeviceEntry *authInfo, TlvDevAuthElement *devAuth) +{ + authInfo->udid = CreateString(); + authInfo->authId = CreateString(); + authInfo->serviceType = CreateString(); + authInfo->ext = CreateParcel(0, 0); + authInfo->groupEntry = GetGroupEntryByGroupIdInner(StringGet(&devAuth->groupId.data)); + if (authInfo->groupEntry != NULL) { + if (!StringSet(&authInfo->udid, devAuth->udid.data)) { + return false; + } + if (!StringSet(&authInfo->authId, devAuth->authId.data)) { + return false; + } + if (!StringSet(&authInfo->serviceType, devAuth->serviceType.data)) { + return false; + } + if (!ParcelCopy(&devAuth->ext.data, &authInfo->ext)) { + return false; + } + authInfo->credential = devAuth->info.data.credential; + authInfo->devType = devAuth->info.data.devType; + authInfo->userId = devAuth->info.data.userId; + authInfo->lastTm = devAuth->info.data.lastTm; + return true; + } else { + return false; + } +} + +static bool LoadDevAuthDb(HCDataBaseV1 *db) +{ + uint32_t index; + TlvDevAuthElement *devAuth = NULL; + FOR_EACH_HC_VECTOR(db->deviceAuthInfos.data, index, devAuth) { + TrustedDeviceEntry authInfo; + if (!SetDevAuthFromTlv(&authInfo, devAuth)) { + DestroyDeviceEntryStruct(&authInfo); + return false; + } + if (g_trustedDeviceTable.pushBack(&g_trustedDeviceTable, &authInfo) == NULL) { + DestroyDeviceEntryStruct(&authInfo); + return false; + } + } + return true; +} + +static bool LoadDBFromParcel(HcParcel *parcelIn) +{ + bool ret = false; + HCDataBaseV1 dbv1; + TLV_INIT(HCDataBaseV1, &dbv1); + if (DecodeTlvMessage((TlvBase *)&dbv1, parcelIn, false)) { + if (!LoadGroupDb(&dbv1)) { + TLV_DEINIT(dbv1); + return false; + } + if (!LoadDevAuthDb(&dbv1)) { + TLV_DEINIT(dbv1); + return false; + } + ret = true; + } else { + LOGE("[DB]: Decode Tlv Message Failed!"); + } + TLV_DEINIT(dbv1); + return ret; +} + +static bool LoadDB() +{ + FileHandle file; + int ret = HcFileOpen(FILE_ID_GROUP, MODE_FILE_READ, &file); + if (ret != 0) { + return false; + } + int fileSize = HcFileSize(file); + if (fileSize <= 0) { + HcFileClose(file); + return false; + } + char *fileData = (char *)HcMalloc(fileSize, 0); + if (fileData == NULL) { + HcFileClose(file); + return false; + } + if (HcFileRead(file, fileData, fileSize) != fileSize) { + HcFileClose(file); + HcFree(fileData); + return false; + } + HcFileClose(file); + HcParcel parcel = CreateParcel(0, 0); + if (!ParcelWrite(&parcel, fileData, fileSize)) { + HcFree(fileData); + DeleteParcel(&parcel); + return false; + } + ret = LoadDBFromParcel(&parcel); + HcFree(fileData); + DeleteParcel(&parcel); + return ret; +} + +static bool SaveGroupDb(HCDataBaseV1 *db) +{ + uint32_t index; + TrustedGroupEntry **entry; + FOR_EACH_HC_VECTOR(g_trustedGroupTable, index, entry) { + TlvGroupElement tmp; + TlvGroupElement *element = db->groups.data.pushBack(&db->groups.data, &tmp); + if (element != NULL) { + TLV_INIT(TlvGroupElement, element); + if (!StringSet(&element->name.data, (*entry)->name)) { + return false; + } + if (!StringSet(&element->id.data, (*entry)->id)) { + return false; + } + element->type.data = (*entry)->type; + element->visibility.data = (*entry)->visibility; + element->expireTime.data = (*entry)->expireTime; + element->userId.data = (*entry)->userId; + if (!SaveStringVectorToParcel(&(*entry)->managers, &element->managers.data)) { + return false; + } + if (!SaveStringVectorToParcel(&(*entry)->friends, &element->friends.data)) { + return false; + } + if (!SaveInt64VectorToParcel(&(*entry)->sharedUserIdVec, &element->sharedUserIdVec.data)) { + return false; + } + } else { + return false; + } + } + return true; +} + +static bool SaveDevAuthDb(HCDataBaseV1 *db) +{ + uint32_t index; + TrustedDeviceEntry *authInfo = NULL; + FOR_EACH_HC_VECTOR(g_trustedDeviceTable, index, authInfo) { + TlvDevAuthElement tmp; + TlvDevAuthElement *element = db->deviceAuthInfos.data.pushBack(&db->deviceAuthInfos.data, &tmp); + if (element != NULL) { + TLV_INIT(TlvDevAuthElement, element); + if (!StringSet(&element->groupId.data, authInfo->groupEntry->id)) { + return false; + } + if (!StringSet(&element->udid.data, authInfo->udid)) { + return false; + } + if (!StringSet(&element->authId.data, authInfo->authId)) { + return false; + } + if (!StringSet(&element->serviceType.data, authInfo->serviceType)) { + return false; + } + if (!ParcelCopy(&element->ext.data, &authInfo->ext)) { + return false; + } + element->info.data.credential = authInfo->credential; + element->info.data.devType = authInfo->devType; + element->info.data.userId = authInfo->userId; + element->info.data.lastTm = authInfo->lastTm; + } else { + return false; + } + } + return true; +} + +static bool SaveDBToParcel(HcParcel *parcelOut) +{ + int ret; + HCDataBaseV1 dbv1; + TLV_INIT(HCDataBaseV1, &dbv1); + dbv1.version.data = 1; + do { + if (!SaveGroupDb(&dbv1)) { + ret = false; + break; + } + if (!SaveDevAuthDb(&dbv1)) { + ret = false; + break; + } + if (!EncodeTlvMessage((TlvBase *)&dbv1, parcelOut)) { + LOGE("[DB]: Encode Tlv Message failed!"); + ret = false; + break; + } + ret = true; + } while (0); + TLV_DEINIT(dbv1); + return ret; +} + +static bool SaveDB() +{ + HcParcel parcel = CreateParcel(0, 0); + if (!SaveDBToParcel(&parcel)) { + DeleteParcel(&parcel); + return false; + } + FileHandle file; + int ret = HcFileOpen(FILE_ID_GROUP, MODE_FILE_WRITE, &file); + if (ret != 0) { + DeleteParcel(&parcel); + return false; + } + int fileSize = (int)GetParcelDataSize(&parcel); + const char *fileData = GetParcelData(&parcel); + if (HcFileWrite(file, fileData, fileSize) == fileSize) { + ret = true; + } else { + ret = false; + } + DeleteParcel(&parcel); + HcFileClose(file); + return ret; +} + +int32_t AddGroup(const GroupInfo *groupInfo) +{ + LOGI("[DB]: Start to add a group to database!"); + if (groupInfo == NULL) { + LOGE("[DB]: The input groupInfo is NULL!"); + return HC_ERR_INVALID_PARAMS; + } + if (IsGroupExistByGroupId(StringGet(&groupInfo->id))) { + LOGE("[DB]: The group corresponding to the groupId already exists and cannot be created again!"); + return HC_ERR_GROUP_DUPLICATE; + } + TrustedGroupEntry *entry = CreateGroupEntryStruct(); + if (entry == NULL) { + LOGE("[DB]: Failed to allocate groupEntry memory!"); + return HC_ERR_ALLOC_MEMORY; + } + int32_t result = GenerateGroupEntryByInfo(groupInfo, entry); + if (result != HC_SUCCESS) { + DestroyGroupEntryStruct(entry); + HcFree(entry); + return result; + } + g_databaseMutex->lock(g_databaseMutex); + if (g_trustedGroupTable.pushBack(&g_trustedGroupTable, (const TrustedGroupEntry **)&entry) == NULL) { + g_databaseMutex->unlock(g_databaseMutex); + LOGE("[DB]: Failed to push groupEntry to groupTable!"); + DestroyGroupEntryStruct(entry); + HcFree(entry); + return HC_ERR_MEMORY_COPY; + } + if (!SaveDB()) { + g_databaseMutex->unlock(g_databaseMutex); + LOGE("[DB]: Failed to save database!"); + return HC_ERR_SAVE_DB_FAILED; + } + g_databaseMutex->unlock(g_databaseMutex); + if (entry->type != ACROSS_ACCOUNT_AUTHORIZE_GROUP) { + NotifyGroupCreated(entry, DEFAULT_USER_ID); + } + LOGI("[DB]: Add a group to database successfully! [GroupType]: %d", groupInfo->type); + return HC_SUCCESS; +} + +int32_t AddGroupManager(const char *groupId, const char *managerAppId) +{ + LOGI("[DB]: Start to add a manager to the group! [Manager]: %s", managerAppId); + if ((groupId == NULL) || (managerAppId == NULL)) { + LOGE("[DB]: The input groupId or manager is NULL!"); + return HC_ERR_INVALID_PARAMS; + } + TrustedGroupEntry **entry = NULL; + uint32_t groupIndex; + g_databaseMutex->lock(g_databaseMutex); + FOR_EACH_HC_VECTOR(g_trustedGroupTable, groupIndex, entry) { + if ((entry != NULL) && (*entry != NULL) && (IsGroupIdEquals(*entry, groupId))) { + HcString managerStr = CreateString(); + if (!StringSetPointer(&managerStr, managerAppId)) { + g_databaseMutex->unlock(g_databaseMutex); + LOGE("[DB]: Failed to copy manager!"); + DeleteString(&managerStr); + return HC_ERR_MEMORY_COPY; + } + if ((*entry)->managers.pushBackT(&(*entry)->managers, managerStr) == NULL) { + g_databaseMutex->unlock(g_databaseMutex); + LOGE("[DB]: Failed to push manager to managerVec!"); + DeleteString(&managerStr); + return HC_ERR_MEMORY_COPY; + } + if (!SaveDB()) { + g_databaseMutex->unlock(g_databaseMutex); + LOGE("[DB]: Failed to save database!"); + return HC_ERR_SAVE_DB_FAILED; + } + g_databaseMutex->unlock(g_databaseMutex); + LOGI("[DB]: Add a manager to the group successfully! [Manager]: %s", managerAppId); + return HC_SUCCESS; + } + } + g_databaseMutex->unlock(g_databaseMutex); + LOGE("[DB]: The group does not exist!"); + return HC_ERR_GROUP_NOT_EXIST; +} + +int32_t AddGroupFriend(const char *groupId, const char *friendAppId) +{ + LOGI("[DB]: Start to add a friend to the group! [Friend]: %s", friendAppId); + if ((groupId == NULL) || (friendAppId == NULL)) { + LOGE("[DB]: The input groupId or friend is NULL!"); + return HC_ERR_INVALID_PARAMS; + } + TrustedGroupEntry **entry = NULL; + uint32_t groupIndex; + g_databaseMutex->lock(g_databaseMutex); + FOR_EACH_HC_VECTOR(g_trustedGroupTable, groupIndex, entry) { + if ((entry != NULL) && (*entry != NULL) && (IsGroupIdEquals(*entry, groupId))) { + HcString friendStr = CreateString(); + if (!StringSetPointer(&friendStr, friendAppId)) { + g_databaseMutex->unlock(g_databaseMutex); + LOGE("[DB]: Failed to copy friend!"); + DeleteString(&friendStr); + return HC_ERR_MEMORY_COPY; + } + if ((*entry)->friends.pushBackT(&(*entry)->friends, friendStr) == NULL) { + g_databaseMutex->unlock(g_databaseMutex); + LOGE("[DB]: Failed to push friend to friendVec!"); + return HC_ERR_MEMORY_COPY; + } + if (!SaveDB()) { + g_databaseMutex->unlock(g_databaseMutex); + LOGE("[DB]: Failed to save database!"); + return HC_ERR_SAVE_DB_FAILED; + } + g_databaseMutex->unlock(g_databaseMutex); + LOGI("[DB]: Add a friend to the group successfully! [Friend]: %s", friendAppId); + return HC_SUCCESS; + } + } + g_databaseMutex->unlock(g_databaseMutex); + LOGE("[DB]: The group does not exist!"); + return HC_SUCCESS; +} + +int32_t RemoveGroupManager(const char *groupId, const char *managerAppId) +{ + LOGI("[DB]: Start to delete a manager from the group! [Manager]: %s", managerAppId); + if ((groupId == NULL) || (managerAppId == NULL)) { + LOGE("[DB]: The input groupId or manager is NULL!"); + return HC_ERR_INVALID_PARAMS; + } + TrustedGroupEntry **entry = NULL; + uint32_t groupIndex; + g_databaseMutex->lock(g_databaseMutex); + FOR_EACH_HC_VECTOR(g_trustedGroupTable, groupIndex, entry) { + if ((entry != NULL) && (*entry != NULL) && (IsGroupIdEquals(*entry, groupId))) { + HcString *managerEntry = NULL; + uint32_t managerIndex; + FOR_EACH_HC_VECTOR((*entry)->managers, managerIndex, managerEntry) { + if ((managerIndex > 0) && (managerEntry != NULL) && + (strcmp(StringGet(managerEntry), managerAppId) == 0)) { + HcString tmpManager; + HC_VECTOR_POPELEMENT(&((*entry)->managers), &tmpManager, managerIndex); + DeleteString(&tmpManager); + if (!SaveDB()) { + LOGE("[DB]: Failed to save database!"); + g_databaseMutex->unlock(g_databaseMutex); + return HC_ERR_SAVE_DB_FAILED; + } + g_databaseMutex->unlock(g_databaseMutex); + LOGI("[DB]: Delete a manager from the group successfully! [Manager]: %s", managerAppId); + return HC_SUCCESS; + } + } + LOGE("[DB]: The manager does not exist in the group!"); + g_databaseMutex->unlock(g_databaseMutex); + return HC_ERR_MANAGER_NOT_EXIST; + } + } + g_databaseMutex->unlock(g_databaseMutex); + LOGE("[DB]: The group does not exist!"); + return HC_ERR_GROUP_NOT_EXIST; +} + +int32_t RemoveGroupFriend(const char *groupId, const char *friendAppId) +{ + LOGI("[DB]: Start to delete a friend from the group! [Friend]: %s", friendAppId); + if ((groupId == NULL) || (friendAppId == NULL)) { + LOGE("[DB]: The input groupId or friend is NULL!"); + return HC_ERR_INVALID_PARAMS; + } + TrustedGroupEntry **entry = NULL; + uint32_t groupIndex; + g_databaseMutex->lock(g_databaseMutex); + FOR_EACH_HC_VECTOR(g_trustedGroupTable, groupIndex, entry) { + if ((entry != NULL) && (*entry != NULL) && (IsGroupIdEquals(*entry, groupId))) { + HcString *friendEntry = NULL; + uint32_t friendIndex; + FOR_EACH_HC_VECTOR((*entry)->friends, friendIndex, friendEntry) { + if ((friendEntry != NULL) && (strcmp(StringGet(friendEntry), friendAppId) == 0)) { + HcString tmpFriend; + HC_VECTOR_POPELEMENT(&((*entry)->friends), &tmpFriend, friendIndex); + DeleteString(&tmpFriend); + if (!SaveDB()) { + LOGE("[DB]: Failed to save database!"); + g_databaseMutex->unlock(g_databaseMutex); + return HC_ERR_SAVE_DB_FAILED; + } + g_databaseMutex->unlock(g_databaseMutex); + LOGI("[DB]: Delete a friend from the group successfully! [Friend]: %s", friendAppId); + return HC_SUCCESS; + } + } + LOGE("[DB]: The friend does not exist in the group!"); + g_databaseMutex->unlock(g_databaseMutex); + return HC_ERR_FRIEND_NOT_EXIST; + } + } + LOGE("[DB]: The group does not exist!"); + g_databaseMutex->unlock(g_databaseMutex); + return HC_ERR_GROUP_NOT_EXIST; +} + +int32_t GetGroupManagers(const char *groupId, CJson *returnManagers) +{ + if ((groupId == NULL) || (returnManagers == NULL)) { + LOGE("[DB]: The input groupId or returnManagers is NULL!"); + return HC_ERR_INVALID_PARAMS; + } + TrustedGroupEntry **entry = NULL; + uint32_t groupIndex; + g_databaseMutex->lock(g_databaseMutex); + FOR_EACH_HC_VECTOR(g_trustedGroupTable, groupIndex, entry) { + if ((entry != NULL) && (*entry != NULL) && (IsGroupIdEquals(*entry, groupId))) { + HcString *managerEntry = NULL; + uint32_t managerIndex; + FOR_EACH_HC_VECTOR((*entry)->managers, managerIndex, managerEntry) { + if ((managerEntry != NULL) && + (AddStringToArray(returnManagers, StringGet(managerEntry)) != HC_SUCCESS)) { + g_databaseMutex->unlock(g_databaseMutex); + LOGE("[DB]: Failed to add manager to returnManagers!"); + return HC_ERR_JSON_FAIL; + } + } + g_databaseMutex->unlock(g_databaseMutex); + return HC_SUCCESS; + } + } + g_databaseMutex->unlock(g_databaseMutex); + LOGE("[DB]: The group does not exist!"); + return HC_ERR_GROUP_NOT_EXIST; +} + +int32_t GetGroupFriends(const char *groupId, CJson *returnFriends) +{ + if ((groupId == NULL) || (returnFriends == NULL)) { + LOGE("[DB]: The input groupId or returnFriends is NULL!"); + return HC_ERR_INVALID_PARAMS; + } + TrustedGroupEntry **entry = NULL; + uint32_t groupIndex; + g_databaseMutex->lock(g_databaseMutex); + FOR_EACH_HC_VECTOR(g_trustedGroupTable, groupIndex, entry) { + if ((entry != NULL) && (*entry != NULL) && (IsGroupIdEquals(*entry, groupId))) { + HcString *friendEntry = NULL; + uint32_t friendIndex; + FOR_EACH_HC_VECTOR((*entry)->friends, friendIndex, friendEntry) { + if ((friendEntry != NULL) && + (AddStringToArray(returnFriends, StringGet(friendEntry)) != HC_SUCCESS)) { + g_databaseMutex->unlock(g_databaseMutex); + LOGE("[DB]: Failed to add friend to returnFriends!"); + return HC_ERR_JSON_FAIL; + } + } + g_databaseMutex->unlock(g_databaseMutex); + return HC_SUCCESS; + } + } + g_databaseMutex->unlock(g_databaseMutex); + LOGE("[DB]: The group does not exist!"); + return HC_ERR_GROUP_NOT_EXIST; +} + +int32_t CompareVisibility(const char *groupId, int groupVisibility) +{ + if (groupId == NULL) { + LOGE("[DB]: The input groupId is NULL!"); + return HC_ERR_INVALID_PARAMS; + } + TrustedGroupEntry **entry = NULL; + uint32_t groupIndex; + g_databaseMutex->lock(g_databaseMutex); + FOR_EACH_HC_VECTOR(g_trustedGroupTable, groupIndex, entry) { + if ((entry != NULL) && (*entry != NULL) && (IsGroupIdEquals(*entry, groupId))) { + if (((uint32_t)((*entry)->visibility) & (uint32_t)groupVisibility) == 0) { + g_databaseMutex->unlock(g_databaseMutex); + return HC_ERROR; + } else { + g_databaseMutex->unlock(g_databaseMutex); + return HC_SUCCESS; + } + } + } + g_databaseMutex->unlock(g_databaseMutex); + LOGE("[DB]: The group does not exist!"); + return HC_ERR_GROUP_NOT_EXIST; +} + +bool IsTrustedDeviceExist(const char *udid) +{ + g_databaseMutex->lock(g_databaseMutex); + if (GetTrustedDeviceEntry(udid, NULL) != NULL) { + g_databaseMutex->unlock(g_databaseMutex); + return true; + } else { + g_databaseMutex->unlock(g_databaseMutex); + return false; + } +} + +int32_t GetTrustedDevNumber() +{ + g_databaseMutex->lock(g_databaseMutex); + int num = GetTrustedDeviceNum(); + g_databaseMutex->unlock(g_databaseMutex); + return num; +} + +int32_t AddTrustedDevice(const DeviceInfo *deviceInfo, const Uint8Buff *ext) +{ + LOGI("[DB]: Start to add a trusted device to database!"); + if (deviceInfo == NULL) { + LOGE("[DB]: The input deviceInfo is NULL!"); + return HC_ERR_INVALID_PARAMS; + } + const char *udid = StringGet(&(deviceInfo->udid)); + bool isTrustedDeviceNumChanged = false; + g_databaseMutex->lock(g_databaseMutex); + if (GetTrustedDeviceEntry(udid, NULL) == NULL) { + isTrustedDeviceNumChanged = true; + } + if (GetTrustedDeviceEntry(udid, StringGet(&deviceInfo->groupId)) == NULL) { + TrustedDeviceEntry deviceEntry; + if (!InitAuthInfo(deviceInfo, ext, &deviceEntry)) { + g_databaseMutex->unlock(g_databaseMutex); + DestroyDeviceEntryStruct(&deviceEntry); + return HC_ERR_MEMORY_COPY; + } + if (g_trustedDeviceTable.pushBack(&g_trustedDeviceTable, &deviceEntry) == NULL) { + g_databaseMutex->unlock(g_databaseMutex); + LOGE("[DB]: Failed to push deviceEntry to deviceTable!"); + DestroyDeviceEntryStruct(&deviceEntry); + return HC_ERR_MEMORY_COPY; + } + if (!SaveDB()) { + g_databaseMutex->unlock(g_databaseMutex); + LOGE("[DB]: Failed to save database!"); + return HC_ERR_SAVE_DB_FAILED; + } + if (isTrustedDeviceNumChanged) { + NotifyTrustedDeviceNumChanged(); + } + NotifyDeviceBound(deviceEntry.groupEntry, udid, DEFAULT_USER_ID); + g_databaseMutex->unlock(g_databaseMutex); + LOGI("[DB]: Add a trusted device to database successfully!"); + return HC_SUCCESS; + } + g_databaseMutex->unlock(g_databaseMutex); + LOGE("[DB]: The device already exists in the group!"); + return HC_ERR_DEVICE_DUPLICATE; +} + +int32_t DelTrustedDevice(const char *udid, const char *groupId) +{ + LOGI("[DB]: Start to delete a trusted device from database!"); + if ((udid == NULL) || (groupId == NULL)) { + LOGE("[DB]: The input udid or groupId is NULL!"); + return HC_ERR_INVALID_PARAMS; + } + uint32_t devIndex; + TrustedDeviceEntry *deviceEntry = NULL; + g_databaseMutex->lock(g_databaseMutex); + FOR_EACH_HC_VECTOR(g_trustedDeviceTable, devIndex, deviceEntry) { + if ((deviceEntry != NULL) && (deviceEntry->groupEntry != NULL)) { + if (((strcmp(StringGet(&deviceEntry->udid), udid) == 0)) && + (CompareGroupIdInDeviceEntryOrNull(deviceEntry, groupId))) { + TrustedDeviceEntry tmpDeviceEntry; + HC_VECTOR_POPELEMENT(&g_trustedDeviceTable, &tmpDeviceEntry, devIndex); + if (!SaveDB()) { + g_databaseMutex->unlock(g_databaseMutex); + LOGE("[DB]: Failed to save database!"); + return HC_ERR_SAVE_DB_FAILED; + } + CheckAndNotifyAfterDelDevice(&tmpDeviceEntry); + DestroyDeviceEntryStruct(&tmpDeviceEntry); + g_databaseMutex->unlock(g_databaseMutex); + LOGI("[DB]: Delete a trusted device from database successfully!"); + return HC_SUCCESS; + } + } + } + g_databaseMutex->unlock(g_databaseMutex); + LOGE("[DB]: The trusted device is not found!"); + return HC_ERR_DEVICE_NOT_EXIST; +} + +int32_t DelTrustedDeviceByAuthId(const char *authId, const char *groupId) +{ + LOGI("[DB]: Start to delete a trusted device from database!"); + if ((authId == NULL) || (groupId == NULL)) { + LOGE("[DB]: The input authId or groupId is NULL!"); + return HC_ERR_INVALID_PARAMS; + } + uint32_t devIndex; + TrustedDeviceEntry *deviceEntry = NULL; + g_databaseMutex->lock(g_databaseMutex); + FOR_EACH_HC_VECTOR(g_trustedDeviceTable, devIndex, deviceEntry) { + if ((deviceEntry != NULL) && (deviceEntry->groupEntry != NULL)) { + if (((strcmp(StringGet(&deviceEntry->authId), authId) == 0)) && + (IsGroupIdEquals(deviceEntry->groupEntry, groupId))) { + TrustedDeviceEntry tmpDeviceEntry; + HC_VECTOR_POPELEMENT(&g_trustedDeviceTable, &tmpDeviceEntry, devIndex); + if (!SaveDB()) { + g_databaseMutex->unlock(g_databaseMutex); + LOGE("[DB]: Failed to save database!"); + return HC_ERR_SAVE_DB_FAILED; + } + CheckAndNotifyAfterDelDevice(&tmpDeviceEntry); + DestroyDeviceEntryStruct(&tmpDeviceEntry); + g_databaseMutex->unlock(g_databaseMutex); + LOGI("[DB]: Delete a trusted device from database successfully!"); + return HC_SUCCESS; + } + } + } + g_databaseMutex->unlock(g_databaseMutex); + LOGE("[DB]: The trusted device is not found!"); + return HC_ERR_DEVICE_NOT_EXIST; +} + +static void DeleteUserIdExpiredDeviceEntry(int64_t curUserId) +{ + uint32_t devIndex = 0; + TrustedDeviceEntry *deviceEntry = NULL; + while (devIndex < g_trustedDeviceTable.size(&g_trustedDeviceTable)) { + deviceEntry = g_trustedDeviceTable.getp(&g_trustedDeviceTable, devIndex); + if (deviceEntry == NULL) { + devIndex++; + continue; + } + if (deviceEntry->groupEntry->type != ACROSS_ACCOUNT_AUTHORIZE_GROUP) { + devIndex++; + continue; + } + if (deviceEntry->groupEntry->userId == curUserId) { + devIndex++; + continue; + } + TrustedDeviceEntry tmpDeviceEntry; + HC_VECTOR_POPELEMENT(&g_trustedDeviceTable, &tmpDeviceEntry, devIndex); + CheckAndNotifyAfterDelDevice(&tmpDeviceEntry); + DestroyDeviceEntryStruct(&tmpDeviceEntry); + } +} + +static void DeleteUserIdExpiredGroupEntry(int64_t curUserId) +{ + TrustedGroupEntry **groupEntry = NULL; + uint32_t groupIndex = 0; + while (groupIndex < g_trustedGroupTable.size(&g_trustedGroupTable)) { + groupEntry = g_trustedGroupTable.getp(&g_trustedGroupTable, groupIndex); + if ((groupEntry == NULL) || (*groupEntry == NULL)) { + groupIndex++; + continue; + } + if ((*groupEntry)->type != ACROSS_ACCOUNT_AUTHORIZE_GROUP) { + groupIndex++; + continue; + } + if ((*groupEntry)->userId == curUserId) { + groupIndex++; + continue; + } + TrustedGroupEntry *tmpEntry = NULL; + HC_VECTOR_POPELEMENT(&g_trustedGroupTable, &tmpEntry, groupIndex); + uint32_t tmpIndex; + int64_t *sharedUserId = NULL; + FOR_EACH_HC_VECTOR(tmpEntry->sharedUserIdVec, tmpIndex, sharedUserId) { + NotifyGroupDeleted(tmpEntry, *sharedUserId); + } + DestroyGroupEntryStruct(tmpEntry); + HcFree(tmpEntry); + } +} + +static void DeleteAccountDeviceEntry() +{ + uint32_t devIndex = 0; + TrustedDeviceEntry *deviceEntry = NULL; + while (devIndex < g_trustedDeviceTable.size(&g_trustedDeviceTable)) { + deviceEntry = g_trustedDeviceTable.getp(&g_trustedDeviceTable, devIndex); + if (deviceEntry == NULL) { + devIndex++; + continue; + } + if ((deviceEntry->groupEntry->type != IDENTICAL_ACCOUNT_GROUP) && + (deviceEntry->groupEntry->type != ACROSS_ACCOUNT_AUTHORIZE_GROUP)) { + devIndex++; + continue; + } + TrustedDeviceEntry tmpDeviceEntry; + HC_VECTOR_POPELEMENT(&g_trustedDeviceTable, &tmpDeviceEntry, devIndex); + CheckAndNotifyAfterDelDevice(&tmpDeviceEntry); + DestroyDeviceEntryStruct(&tmpDeviceEntry); + } +} + +static void DeleteAccountGroupEntry() +{ + TrustedGroupEntry **groupEntry = NULL; + uint32_t groupIndex = 0; + while (groupIndex < g_trustedGroupTable.size(&g_trustedGroupTable)) { + groupEntry = g_trustedGroupTable.getp(&g_trustedGroupTable, groupIndex); + if ((groupEntry == NULL) || (*groupEntry == NULL)) { + groupIndex++; + continue; + } + if (((*groupEntry)->type != IDENTICAL_ACCOUNT_GROUP) && + ((*groupEntry)->type != ACROSS_ACCOUNT_AUTHORIZE_GROUP)) { + groupIndex++; + continue; + } + TrustedGroupEntry *tmpEntry = NULL; + HC_VECTOR_POPELEMENT(&g_trustedGroupTable, &tmpEntry, groupIndex); + if (tmpEntry->type == IDENTICAL_ACCOUNT_GROUP) { + NotifyGroupDeleted(tmpEntry, DEFAULT_USER_ID); + } else { + uint32_t tmpIndex; + int64_t *sharedUserId = NULL; + FOR_EACH_HC_VECTOR(tmpEntry->sharedUserIdVec, tmpIndex, sharedUserId) { + NotifyGroupDeleted(tmpEntry, *sharedUserId); + } + } + DestroyGroupEntryStruct(tmpEntry); + HcFree(tmpEntry); + } +} + +static void DelDeviceEntryByGroupId(const char *groupId) +{ + uint32_t devIndex = 0; + TrustedDeviceEntry *deviceEntry = NULL; + while (devIndex < g_trustedDeviceTable.size(&g_trustedDeviceTable)) { + deviceEntry = g_trustedDeviceTable.getp(&g_trustedDeviceTable, devIndex); + if (deviceEntry == NULL) { + devIndex++; + continue; + } + if (strcmp(StringGet(&deviceEntry->groupEntry->id), groupId) != 0) { + devIndex++; + continue; + } + TrustedDeviceEntry tmpDeviceEntry; + HC_VECTOR_POPELEMENT(&g_trustedDeviceTable, &tmpDeviceEntry, devIndex); + CheckAndNotifyAfterDelDevice(&tmpDeviceEntry); + DestroyDeviceEntryStruct(&tmpDeviceEntry); + } +} + +static void DelGroupEntryByGroupId(const char *groupId) +{ + TrustedGroupEntry **groupEntry = NULL; + uint32_t groupIndex = 0; + while (groupIndex < g_trustedGroupTable.size(&g_trustedGroupTable)) { + groupEntry = g_trustedGroupTable.getp(&g_trustedGroupTable, groupIndex); + if ((groupEntry == NULL) || (*groupEntry == NULL) || (!IsGroupIdEquals(*groupEntry, groupId))) { + groupIndex++; + continue; + } + TrustedGroupEntry *tmpEntry = NULL; + HC_VECTOR_POPELEMENT(&g_trustedGroupTable, &tmpEntry, groupIndex); + if (tmpEntry->type != ACROSS_ACCOUNT_AUTHORIZE_GROUP) { + NotifyGroupDeleted(tmpEntry, DEFAULT_USER_ID); + } else { + uint32_t tmpIndex; + int64_t *sharedUserId = NULL; + FOR_EACH_HC_VECTOR(tmpEntry->sharedUserIdVec, tmpIndex, sharedUserId) { + NotifyGroupDeleted(tmpEntry, *sharedUserId); + } + } + DestroyGroupEntryStruct(tmpEntry); + HcFree(tmpEntry); + LOGI("[DB]: Delete a group from database successfully!"); + break; + } + LOGI("[DB]: The group does not exist!"); +} + +int32_t DeleteUserIdExpiredGroups(int64_t curUserId) +{ + LOGI("[DB]: Start to delete all across account groups with expired userId!"); + g_databaseMutex->lock(g_databaseMutex); + DeleteUserIdExpiredDeviceEntry(curUserId); + DeleteUserIdExpiredGroupEntry(curUserId); + if (!SaveDB()) { + g_databaseMutex->unlock(g_databaseMutex); + LOGE("[DB]: Failed to save database!"); + return HC_ERR_SAVE_DB_FAILED; + } + g_databaseMutex->unlock(g_databaseMutex); + LOGI("[DB]: Delete all across account groups with expired userId successfully!"); + return HC_SUCCESS; +} + +int32_t DeleteAllAccountGroup(void) +{ + LOGI("[DB]: Start to delete all account-related groups!"); + g_databaseMutex->lock(g_databaseMutex); + DeleteAccountDeviceEntry(); + DeleteAccountGroupEntry(); + if (!SaveDB()) { + g_databaseMutex->unlock(g_databaseMutex); + LOGE("[DB]: Failed to save database!"); + return HC_ERR_SAVE_DB_FAILED; + } + g_databaseMutex->unlock(g_databaseMutex); + LOGI("[DB]: Delete all account-related groups successfully!"); + return HC_SUCCESS; +} + +int32_t ChangeSharedUserIdVec(Int64Vector *sharedUserIdList) +{ + LOGI("[DB]: Start to change shared userId list!"); + TrustedGroupEntry **entry = NULL; + uint32_t index; + g_databaseMutex->lock(g_databaseMutex); + FOR_EACH_HC_VECTOR(g_trustedGroupTable, index, entry) { + if ((entry != NULL) && (*entry != NULL) && ((*entry)->type == ACROSS_ACCOUNT_AUTHORIZE_GROUP)) { + DeleteExpiredSharedUserId(sharedUserIdList, *entry); + LOGI("[DB]: Delete expired local userIds successfully!"); + AddNewSharedUserId(sharedUserIdList, *entry); + LOGI("[DB]: Add new userIds successfully!"); + if (!SaveDB()) { + g_databaseMutex->unlock(g_databaseMutex); + LOGE("[DB]: Failed to save database!"); + return HC_ERR_SAVE_DB_FAILED; + } + g_databaseMutex->unlock(g_databaseMutex); + LOGI("[DB]: Change shared userId list successfully!"); + return HC_SUCCESS; + } + } + g_databaseMutex->unlock(g_databaseMutex); + LOGE("[DB]: The across account group does not exist!"); + return HC_ERR_GROUP_NOT_EXIST; +} + +int32_t DelGroupByGroupId(const char *groupId) +{ + LOGI("[DB]: Start to delete a group from database!"); + if (groupId == NULL) { + LOGE("[DB]: The input groupId is NULL!"); + return HC_ERR_INVALID_PARAMS; + } + g_databaseMutex->lock(g_databaseMutex); + DelDeviceEntryByGroupId(groupId); + DelGroupEntryByGroupId(groupId); + if (!SaveDB()) { + g_databaseMutex->unlock(g_databaseMutex); + LOGE("[DB]: Failed to save database!"); + return HC_ERR_SAVE_DB_FAILED; + } + g_databaseMutex->unlock(g_databaseMutex); + return HC_SUCCESS; +} + +bool IsTrustedDeviceInGroup(const char *groupId, const char *udid) +{ + if ((groupId == NULL) || (udid == NULL)) { + LOGE("[DB]: The input groupId or udid is NULL!"); + return false; + } + g_databaseMutex->lock(g_databaseMutex); + if (GetTrustedDeviceEntry(udid, groupId) != NULL) { + g_databaseMutex->unlock(g_databaseMutex); + return true; + } else { + g_databaseMutex->unlock(g_databaseMutex); + return false; + } +} + +bool IsTrustedDeviceInGroupByAuthId(const char *groupId, const char *authId) +{ + if ((groupId == NULL) || (authId == NULL)) { + LOGE("[DB]: The input groupId or authId is NULL!"); + return false; + } + g_databaseMutex->lock(g_databaseMutex); + if (GetTrustedDeviceEntryByAuthId(authId, groupId) != NULL) { + g_databaseMutex->unlock(g_databaseMutex); + return true; + } else { + g_databaseMutex->unlock(g_databaseMutex); + return false; + } +} + +bool IsGroupExist(const char *ownerName, const char *groupName) +{ + if ((ownerName == NULL) || (groupName == NULL)) { + LOGE("[DB]: The input ownerName or groupName is NULL!"); + return false; + } + uint32_t index; + TrustedGroupEntry **entry = NULL; + g_databaseMutex->lock(g_databaseMutex); + FOR_EACH_HC_VECTOR(g_trustedGroupTable, index, entry) { + if (strcmp(StringGet(&(*entry)->name), groupName) == 0) { + if (HC_VECTOR_SIZE(&(*entry)->managers) != 0) { + HcString entryOwner = HC_VECTOR_GET(&(*entry)->managers, 0); + if (strcmp(StringGet(&entryOwner), ownerName) == 0) { + g_databaseMutex->unlock(g_databaseMutex); + return true; + } + } + } + } + g_databaseMutex->unlock(g_databaseMutex); + return false; +} + +bool IsIdenticalGroupExist() +{ + uint32_t index; + TrustedGroupEntry **entry = NULL; + g_databaseMutex->lock(g_databaseMutex); + FOR_EACH_HC_VECTOR(g_trustedGroupTable, index, entry) { + if ((*entry)->type == IDENTICAL_ACCOUNT_GROUP) { + g_databaseMutex->unlock(g_databaseMutex); + return true; + } + } + g_databaseMutex->unlock(g_databaseMutex); + return false; +} + +bool IsAcrossAccountGroupExist() +{ + uint32_t index; + TrustedGroupEntry **entry = NULL; + g_databaseMutex->lock(g_databaseMutex); + FOR_EACH_HC_VECTOR(g_trustedGroupTable, index, entry) { + if ((*entry)->type == ACROSS_ACCOUNT_AUTHORIZE_GROUP) { + g_databaseMutex->unlock(g_databaseMutex); + return true; + } + } + g_databaseMutex->unlock(g_databaseMutex); + return false; +} + +bool IsGroupExistByGroupId(const char *groupId) +{ + if (groupId == NULL) { + LOGE("[DB]: The input groupId is NULL!"); + return false; + } + uint32_t index; + TrustedGroupEntry **entry = NULL; + g_databaseMutex->lock(g_databaseMutex); + FOR_EACH_HC_VECTOR(g_trustedGroupTable, index, entry) { + if (IsGroupIdEquals(*entry, groupId)) { + g_databaseMutex->unlock(g_databaseMutex); + return true; + } + } + g_databaseMutex->unlock(g_databaseMutex); + return false; +} + +int32_t GetDeviceInfoForDevAuth(const char *udid, const char *groupId, DeviceInfo *deviceInfo) +{ + if ((udid == NULL) || (groupId == NULL) || (deviceInfo == NULL)) { + LOGE("[DB]: The input parameters contains NULL value!"); + return HC_ERR_INVALID_PARAMS; + } + g_databaseMutex->lock(g_databaseMutex); + TrustedDeviceEntry *deviceEntry = GetTrustedDeviceEntry(udid, groupId); + if (deviceEntry == NULL) { + LOGE("[DB]: The trusted device is not found!"); + return HC_ERR_DEVICE_NOT_EXIST; + } + if (!StringSet(&deviceInfo->authId, deviceEntry->authId)) { + LOGE("[DB]: Failed to copy authId!"); + return HC_ERR_MEMORY_COPY; + } + if (!StringSet(&deviceInfo->udid, deviceEntry->udid)) { + LOGE("[DB]: Failed to copy authId!"); + return HC_ERR_MEMORY_COPY; + } + if (!StringSet(&(deviceInfo->groupId), deviceEntry->groupEntry->id)) { + LOGE("[DB]: Failed to copy groupId!"); + return HC_ERR_MEMORY_COPY; + } + if (!StringSet(&(deviceInfo->serviceType), deviceEntry->serviceType)) { + LOGE("[DB]: Failed to copy serviceType!"); + return HC_ERR_MEMORY_COPY; + } + deviceInfo->credential = deviceEntry->credential; + deviceInfo->devType = deviceEntry->devType; + deviceInfo->userId = deviceEntry->userId; + g_databaseMutex->unlock(g_databaseMutex); + return HC_SUCCESS; +} + +int32_t GetDeviceInfoByAuthId(const char *authId, const char *groupId, DeviceInfo *deviceInfo) +{ + if ((authId == NULL) || (groupId == NULL) || (deviceInfo == NULL)) { + LOGE("[DB]: The input parameters contains NULL value!"); + return HC_ERR_INVALID_PARAMS; + } + g_databaseMutex->lock(g_databaseMutex); + TrustedDeviceEntry *deviceEntry = GetTrustedDeviceEntryByAuthId(authId, groupId); + if (deviceEntry == NULL) { + LOGE("[DB]: The trusted device is not found!"); + return HC_ERR_DEVICE_NOT_EXIST; + } + if (!StringSet(&deviceInfo->authId, deviceEntry->authId)) { + LOGE("[DB]: Failed to copy authId!"); + return HC_ERR_MEMORY_COPY; + } + if (!StringSet(&deviceInfo->udid, deviceEntry->udid)) { + LOGE("[DB]: Failed to copy authId!"); + return HC_ERR_MEMORY_COPY; + } + if (!StringSet(&(deviceInfo->groupId), deviceEntry->groupEntry->id)) { + LOGE("[DB]: Failed to copy groupId!"); + return HC_ERR_MEMORY_COPY; + } + if (!StringSet(&(deviceInfo->serviceType), deviceEntry->serviceType)) { + LOGE("[DB]: Failed to copy serviceType!"); + return HC_ERR_MEMORY_COPY; + } + deviceInfo->credential = deviceEntry->credential; + deviceInfo->devType = deviceEntry->devType; + deviceInfo->userId = deviceEntry->userId; + g_databaseMutex->unlock(g_databaseMutex); + return HC_SUCCESS; +} + +int32_t GetGroupNumberByOwner(const char *ownerName) +{ + if (ownerName == NULL) { + LOGE("[DB]: The input ownerName is NULL!"); + return 0; + } + int count = 0; + uint32_t index; + TrustedGroupEntry **entry = NULL; + g_databaseMutex->lock(g_databaseMutex); + FOR_EACH_HC_VECTOR(g_trustedGroupTable, index, entry) { + if (HC_VECTOR_SIZE(&(*entry)->managers) > 0) { + HcString entryOwner = HC_VECTOR_GET(&(*entry)->managers, 0); + if (strcmp(StringGet(&entryOwner), ownerName) == 0) { + count++; + } + } + } + g_databaseMutex->unlock(g_databaseMutex); + return count; +} + +int32_t GetCurDeviceNumByGroupId(const char *groupId) +{ + if (groupId == NULL) { + LOGE("[DB]: The input groupId is NULL!"); + return 0; + } + int count = 0; + uint32_t index; + TrustedDeviceEntry *deviceEntry = NULL; + g_databaseMutex->lock(g_databaseMutex); + FOR_EACH_HC_VECTOR(g_trustedDeviceTable, index, deviceEntry) { + if (strcmp(StringGet(&deviceEntry->groupEntry->id), groupId) == 0) { + ++count; + } + } + g_databaseMutex->unlock(g_databaseMutex); + return count; +} + +int32_t GetGroupEntry(const char *groupId, const char *udid, GroupInfo *returnGroupInfo) +{ + if ((groupId == NULL) || (udid == NULL) || (returnGroupInfo == NULL)) { + LOGE("[DB]: The input parameters contains NULL value!"); + return HC_ERR_INVALID_PARAMS; + } + g_databaseMutex->lock(g_databaseMutex); + int32_t res = GetGroupEntryInner(groupId, udid, returnGroupInfo); + g_databaseMutex->unlock(g_databaseMutex); + return res; +} + +int32_t GetGroupEntryByGroupId(const char *groupId, GroupInfo *returnGroupInfo) +{ + if ((groupId == NULL) || (returnGroupInfo == NULL)) { + LOGE("[DB]: The input groupId or returnGroupInfo is NULL!"); + return HC_ERR_INVALID_PARAMS; + } + g_databaseMutex->lock(g_databaseMutex); + int32_t res = GetGroupEntryInner(groupId, NULL, returnGroupInfo); + g_databaseMutex->unlock(g_databaseMutex); + return res; +} + +GroupInfo *CreateGroupInfoStruct() +{ + GroupInfo *ptr = (GroupInfo *)HcMalloc(sizeof(GroupInfo), 0); + if (ptr == NULL) { + LOGE("[DB]: Failed to allocate groupInfo memory!"); + return NULL; + } + ptr->name = CreateString(); + ptr->id = CreateString(); + ptr->ownerName = CreateString(); + return ptr; +} + +void DestroyGroupInfoStruct(GroupInfo *groupInfo) +{ + if (groupInfo == NULL) { + return; + } + DeleteString(&(groupInfo->name)); + DeleteString(&(groupInfo->id)); + DeleteString(&(groupInfo->ownerName)); + HcFree(groupInfo); + groupInfo = NULL; +} + +DeviceInfo *CreateDeviceInfoStruct() +{ + DeviceInfo *deviceInfo = (DeviceInfo *)HcMalloc(sizeof(DeviceInfo), 0); + if (deviceInfo == NULL) { + LOGE("[DB]: Failed to allocate deviceInfo memory!"); + return NULL; + } + deviceInfo->authId = CreateString(); + deviceInfo->udid = CreateString(); + deviceInfo->serviceType = CreateString(); + deviceInfo->groupId = CreateString(); + return deviceInfo; +} + +void DestroyDeviceInfoStruct(DeviceInfo *deviceInfo) +{ + if (deviceInfo == NULL) { + return; + } + DeleteString(&(deviceInfo->authId)); + DeleteString(&(deviceInfo->udid)); + DeleteString(&(deviceInfo->serviceType)); + DeleteString(&(deviceInfo->groupId)); + HcFree(deviceInfo); + deviceInfo = NULL; +} + +void CreateGroupInfoVecStruct(GroupInfoVec *vec) +{ + if (vec == NULL) { + return; + } + *vec = CREATE_HC_VECTOR(GroupInfoVec) +} + +void DestroyGroupInfoVecStruct(GroupInfoVec *vec) +{ + uint32_t index; + void **entry = NULL; + FOR_EACH_HC_VECTOR(*vec, index, entry) { + if ((entry != NULL) && (*entry != NULL)) { + DestroyGroupInfoStruct(*entry); + } + } + DESTROY_HC_VECTOR(GroupInfoVec, vec) +} + +void CreateDeviceInfoVecStruct(DeviceInfoVec *vec) +{ + if (vec == NULL) { + return; + } + *vec = CREATE_HC_VECTOR(DeviceInfoVec) +} + +void DestroyDeviceInfoVecStruct(DeviceInfoVec *vec) +{ + uint32_t index; + void **entry = NULL; + FOR_EACH_HC_VECTOR(*vec, index, entry) { + if ((entry != NULL) && (*entry != NULL)) { + DestroyDeviceInfoStruct(*entry); + } + } + DESTROY_HC_VECTOR(DeviceInfoVec, vec) +} + +int32_t GetJoinedGroupInfoVecByDevId(const GroupQueryParams *params, GroupInfoVec *vec) +{ + if ((params == NULL) || (vec == NULL)) { + LOGE("[DB]: The input params or vec is NULL!"); + return HC_ERR_INVALID_PARAMS; + } + uint32_t index; + TrustedGroupEntry **entry = NULL; + g_databaseMutex->lock(g_databaseMutex); + FOR_EACH_HC_VECTOR(g_trustedGroupTable, index, entry) { + if ((entry == NULL) || (*entry == NULL)) { + continue; + } + TrustedDeviceEntry *deviceEntry = NULL; + if (params->udid != NULL) { + deviceEntry = GetTrustedDeviceEntry(params->udid, StringGet(&(*entry)->id)); + } else if (params->authId != NULL) { + deviceEntry = GetTrustedDeviceEntryByAuthId(params->authId, StringGet(&(*entry)->id)); + } else { + LOGE("[DB]: The values of udid and authId are null!"); + g_databaseMutex->unlock(g_databaseMutex); + return HC_ERR_INVALID_PARAMS; + } + if ((deviceEntry != NULL) && + (IsSatisfyGroup(*entry, params)) && + (IsSatisfyUdidAndAuthId(deviceEntry, params))) { + int32_t result = PushGroupInfoToVec(*entry, vec); + if (result != HC_SUCCESS) { + g_databaseMutex->unlock(g_databaseMutex); + return result; + } + } + } + g_databaseMutex->unlock(g_databaseMutex); + return HC_SUCCESS; +} + +bool IsGroupOwner(const char *groupId, const char *appId) +{ + if ((groupId == NULL) || (appId == NULL)) { + LOGE("[DB]: The input parameter contains NULL value!"); + return false; + } + g_databaseMutex->lock(g_databaseMutex); + TrustedGroupEntry *entry = GetGroupEntryByGroupIdInner(groupId); + if (entry == NULL) { + g_databaseMutex->unlock(g_databaseMutex); + LOGE("[DB]: The group cannot be found!"); + return false; + } + if (HC_VECTOR_SIZE(&(entry->managers)) == 0) { + g_databaseMutex->unlock(g_databaseMutex); + LOGE("[DB]: The group does not have manager and owner!"); + return false; + } + HcString entryOwner = HC_VECTOR_GET(&(entry->managers), 0); + if (strcmp(StringGet(&entryOwner), appId) == 0) { + g_databaseMutex->unlock(g_databaseMutex); + return true; + } + g_databaseMutex->unlock(g_databaseMutex); + LOGE("[DB]: The visitor is not the group owner!"); + return false; +} + +bool IsGroupAccessible(const char *groupId, const char *appId) +{ + if ((groupId == NULL) || (appId == NULL)) { + LOGE("[DB]: The input groupId or appId is NULL!"); + return false; + } + g_databaseMutex->lock(g_databaseMutex); + TrustedGroupEntry *entry = GetGroupEntryByGroupIdInner(groupId); + if (entry == NULL) { + LOGE("[DB]: The group cannot be found!"); + g_databaseMutex->unlock(g_databaseMutex); + return false; + } + if ((entry->visibility == GROUP_VISIBILITY_PUBLIC) || + (IsGroupManager(appId, entry)) || + (IsGroupFriend(appId, entry))) { + g_databaseMutex->unlock(g_databaseMutex); + return true; + } + g_databaseMutex->unlock(g_databaseMutex); + return false; +} + +bool IsGroupEditAllowed(const char *groupId, const char *appId) +{ + if ((groupId == NULL) || (appId == NULL)) { + LOGE("[DB]: The input groupId or appId is NULL!"); + return false; + } + g_databaseMutex->lock(g_databaseMutex); + TrustedGroupEntry *entry = GetGroupEntryByGroupIdInner(groupId); + if (entry == NULL) { + g_databaseMutex->unlock(g_databaseMutex); + LOGE("[DB]: The group cannot be found!"); + return false; + } + if (IsGroupManager(appId, entry)) { + g_databaseMutex->unlock(g_databaseMutex); + return true; + } + g_databaseMutex->unlock(g_databaseMutex); + return false; +} + +int32_t GetLocalDevUdid(char **udid) +{ + uint8_t udidLocal[INPUT_UDID_LEN] = { 0 }; + int res = HcGetUdid(udidLocal, INPUT_UDID_LEN); + if (res != 0) { + return res; + } + uint32_t index; + TrustedDeviceEntry *entry = NULL; + g_databaseMutex->lock(g_databaseMutex); + FOR_EACH_HC_VECTOR(g_trustedDeviceTable, index, entry) { + if ((entry != NULL) && (entry->groupEntry != NULL) && (CompareUdidInDeviceEntryOrNull(entry, + (char *)udidLocal))) { + const char *localUdid = StringGet(&entry->udid); + *udid = (char *)HcMalloc((uint32_t)(strlen(localUdid) + 1), 0); + if ((*udid) == NULL) { + g_databaseMutex->unlock(g_databaseMutex); + LOGE("[DB]: Failed to allocate udid memory!"); + return HC_ERR_ALLOC_MEMORY; + } + if (strcpy_s(*udid, strlen(localUdid) + 1, localUdid) != HC_SUCCESS) { + g_databaseMutex->unlock(g_databaseMutex); + LOGE("[DB]: Failed to copy localUdid!"); + HcFree(*udid); + *udid = NULL; + return HC_ERR_MEMORY_COPY; + } + g_databaseMutex->unlock(g_databaseMutex); + return HC_SUCCESS; + } + } + *udid = NULL; + g_databaseMutex->unlock(g_databaseMutex); + return HC_SUCCESS; +} + +void DestroyUdid(char **udid) +{ + HcFree(*udid); + *udid = NULL; +} + +static int32_t PushSearchGroupInfoToVec(const char *groupId, const char *groupName, TrustedGroupEntry *entry, + GroupInfoVec *groupInfoVec) +{ + GroupInfo *groupInfo = CreateGroupInfoStruct(); + if (groupInfo == NULL) { + LOGE("[DB]: Failed to allocate groupInfo memory!"); + return HC_ERR_ALLOC_MEMORY; + } + const char *tmpGroupId = (groupId != NULL) ? groupId : groupName; + int64_t sharedUserId = DEFAULT_USER_ID; + int32_t result = GetSharedUserIdFromVecByGroupId(entry, tmpGroupId, &sharedUserId); + if (result != HC_SUCCESS) { + LOGE("Failed to find sharedUserId by groupId!"); + DestroyGroupInfoStruct(groupInfo); + return result; + } + result = GenerateGroupInfoIdAndName(tmpGroupId, tmpGroupId, groupInfo); + if (result != HC_SUCCESS) { + DestroyGroupInfoStruct(groupInfo); + return result; + } + GenerateGroupInfoSharedUserId(sharedUserId, groupInfo); + result = GenerateCommonGroupInfoByEntry(entry, groupInfo); + if (result != HC_SUCCESS) { + DestroyGroupInfoStruct(groupInfo); + return result; + } + if (groupInfoVec->pushBackT(groupInfoVec, groupInfo) == NULL) { + LOGE("[DB]: Failed to push groupInfo to groupInfoVec!"); + DestroyGroupInfoStruct(groupInfo); + return HC_ERR_MEMORY_COPY; + } + return HC_SUCCESS; +} + +int32_t GetGroupInfo(int groupType, const char *groupId, const char *groupName, const char *groupOwner, + GroupInfoVec *groupInfoVec) +{ + if (groupInfoVec == NULL) { + LOGE("[DB]: The input groupInfoVec is NULL!"); + return HC_ERR_INVALID_PARAMS; + } + int32_t result; + uint32_t index; + TrustedGroupEntry **entry = NULL; + g_databaseMutex->lock(g_databaseMutex); + FOR_EACH_HC_VECTOR(g_trustedGroupTable, index, entry) { + if ((entry != NULL) && (*entry != NULL) && (CompareSearchParams(groupType, groupId, groupName, + groupOwner, *entry))) { + if (((*entry)->type != ACROSS_ACCOUNT_AUTHORIZE_GROUP) || ((groupId == NULL) && (groupName == NULL))) { + result = PushGroupInfoToVec(*entry, groupInfoVec); + } else { + result = PushSearchGroupInfoToVec(groupId, groupName, *entry, groupInfoVec); + } + if (result != HC_SUCCESS) { + g_databaseMutex->unlock(g_databaseMutex); + return result; + } + } + } + g_databaseMutex->unlock(g_databaseMutex); + return HC_SUCCESS; +} + +int32_t GetJoinedGroups(int groupType, GroupInfoVec *groupInfoVec) +{ + int32_t result; + uint32_t index; + TrustedGroupEntry **entry = NULL; + g_databaseMutex->lock(g_databaseMutex); + FOR_EACH_HC_VECTOR(g_trustedGroupTable, index, entry) { + if ((entry != NULL) && (*entry != NULL) && ((*entry)->type == groupType)) { + result = PushGroupInfoToVec(*entry, groupInfoVec); + if (result != HC_SUCCESS) { + g_databaseMutex->unlock(g_databaseMutex); + return result; + } + } + } + g_databaseMutex->unlock(g_databaseMutex); + return HC_SUCCESS; +} + +int32_t GetRelatedGroups(const char *peerAuthId, GroupInfoVec *groupInfoVec) +{ + int32_t result; + uint32_t index; + TrustedDeviceEntry *entry = NULL; + g_databaseMutex->lock(g_databaseMutex); + FOR_EACH_HC_VECTOR(g_trustedDeviceTable, index, entry) { + if ((entry != NULL) && (strcmp(StringGet(&entry->authId), peerAuthId) == 0)) { + result = PushGroupInfoToVec(entry->groupEntry, groupInfoVec); + if (result != HC_SUCCESS) { + g_databaseMutex->unlock(g_databaseMutex); + return result; + } + } + } + g_databaseMutex->unlock(g_databaseMutex); + return HC_SUCCESS; +} + +int32_t GetTrustedDevices(const char *groupId, DeviceInfoVec *deviceInfoVec) +{ + int32_t result; + uint32_t index; + TrustedDeviceEntry *entry = NULL; + g_databaseMutex->lock(g_databaseMutex); + FOR_EACH_HC_VECTOR(g_trustedDeviceTable, index, entry) { + if ((entry != NULL) && (entry->groupEntry != NULL) && (CompareGroupIdInDeviceEntryOrNull(entry, groupId))) { + result = PushDevInfoToVec(entry, deviceInfoVec); + if (result != HC_SUCCESS) { + g_databaseMutex->unlock(g_databaseMutex); + return result; + } + } + } + g_databaseMutex->unlock(g_databaseMutex); + return HC_SUCCESS; +} + +int32_t InitDatabase() +{ + g_trustedGroupTable = CREATE_HC_VECTOR(TrustedGroupTable) + g_trustedDeviceTable = CREATE_HC_VECTOR(TrustedDeviceTable) + if (g_databaseMutex == NULL) { + g_databaseMutex = (HcMutex *)HcMalloc(sizeof(HcMutex), 0); + if (g_databaseMutex == NULL) { + LOGE("[DB]: Alloc databaseMutex failed"); + DESTROY_HC_VECTOR(TrustedDeviceTable, &g_trustedDeviceTable) + DESTROY_HC_VECTOR(TrustedGroupTable, &g_trustedGroupTable) + return HC_ERR_ALLOC_MEMORY; + } + if (InitHcMutex(g_databaseMutex) != HC_SUCCESS) { + LOGE("[DB]: Init mutex failed"); + DESTROY_HC_VECTOR(TrustedDeviceTable, &g_trustedDeviceTable) + DESTROY_HC_VECTOR(TrustedGroupTable, &g_trustedGroupTable) + HcFree(g_databaseMutex); + g_databaseMutex = NULL; + return HC_ERROR; + } + } + SetFilePath(FILE_ID_GROUP, GetStoragePath()); + if (!LoadDB()) { + LOGI("[DB]: Failed to load database, it may be the first time the database is read!"); + } else { + LOGI("[DB]: Load database successfully!"); + } + return HC_SUCCESS; +} + +void DestroyDatabase() +{ + DestroyTrustDevTable(); + DestroyGroupTable(); + if (g_databaseMutex != NULL) { + DestroyHcMutex(g_databaseMutex); + HcFree(g_databaseMutex); + g_databaseMutex = NULL; + } +} + +void RegGenerateGroupIdFunc(int32_t (*generateGroupId)(int64_t userId, int64_t sharedUserId, char **returnGroupId)) +{ + if (generateGroupId == NULL) { + LOGE("[DB]: The input generate across account group groupId function is null ptr!"); + return; + } + g_generateIdFunc = generateGroupId; +} + +void DeregGenerateGroupIdFunc() +{ + g_generateIdFunc = NULL; +} + +void RegisterBroadcaster(const Broadcaster *broadcaster) +{ + if (broadcaster == NULL) { + LOGE("[DB]: The registered broadcaster is NULL!"); + return; + } + g_broadcaster = broadcaster; +} + +void DeregisterBroadcaster() +{ + g_broadcaster = NULL; +} \ No newline at end of file diff --git a/services/device_auth.c b/services/device_auth.c new file mode 100755 index 0000000..36dee30 --- /dev/null +++ b/services/device_auth.c @@ -0,0 +1,1780 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "device_auth.h" +#include "alg_loader.h" +#include "callback_manager.h" +#include "channel_manager.h" +#include "common_util.h" +#include "database_manager.h" +#include "dev_auth_module_manager.h" +#include "device_auth_defines.h" +#include "group_auth_manager.h" +#include "group_manager.h" +#include "hc_init_protection.h" +#include "hc_log.h" +#include "hc_task_thread.h" +#include "json_utils.h" +#include "securec.h" +#include "session_manager.h" + +#define STACK_SIZE 4096 + +typedef struct { + HcTaskBase base; + int64_t requestId; + CJson *jsonParams; + const DeviceAuthCallback *callback; +} GroupManagerTask; + +static GroupAuthManager *g_groupAuthManager = NULL; +static DeviceGroupManager *g_groupManagerInstance = NULL; +static HcTaskThread *g_taskThread = NULL; + +static int32_t BindCallbackToTask(GroupManagerTask *task, const CJson *jsonParams) +{ + const char *appId = GetStringFromJson(jsonParams, FIELD_APP_ID); + if (appId == NULL) { + LOGE("Failed to get appId from jsonParams!"); + return HC_ERR_JSON_GET; + } + if (!IsGroupManagerSupported()) { + LOGE("Group manager is not supported!"); + return HC_ERR_NOT_SUPPORT; + } + GroupManager *instance = GetGroupManagerInstance(); + if (instance == NULL) { + LOGE("Failed to get groupManager instance!"); + return HC_ERR_NULL_PTR; + } + task->callback = instance->getGmCallbackByAppId(appId); + if (task->callback == NULL) { + LOGE("Failed to find callback by appId!"); + return HC_ERR_CALLBACK_NOT_FOUND; + } + LOGI("Bind service callback to task successfully! [AppId]: %s", appId); + return HC_SUCCESS; +} + +static char *GenerateRecvData(int64_t channelId, const uint8_t *data, uint32_t dataLen, int64_t *requestId) +{ + char *dataStr = (char *)HcMalloc(dataLen + 1, 0); + if (dataStr == NULL) { + LOGE("Failed to allocate dataStr memory!"); + return NULL; + } + if (memcpy_s(dataStr, dataLen + 1, data, dataLen) != HC_SUCCESS) { + LOGE("Failed to copy data!"); + HcFree(dataStr); + return NULL; + } + CJson *receivedData = CreateJsonFromString(dataStr); + HcFree(dataStr); + if (receivedData == NULL) { + LOGE("Failed to create receivedData json object from string!"); + return NULL; + } + if (GetInt64FromJson(receivedData, FIELD_REQUEST_ID, requestId) != HC_SUCCESS) { + LOGE("Failed to get requestId from receivedData!"); + return NULL; + } + if (AddByteToJson(receivedData, FIELD_CHANNEL_ID, (uint8_t *)&channelId, sizeof(int64_t)) != HC_SUCCESS) { + LOGE("Failed to add channelId to recvData!"); + FreeJson(receivedData); + return NULL; + } + char *receivedDataStr = PackJsonToString(receivedData); + FreeJson(receivedData); + if (receivedDataStr == NULL) { + LOGE("Failed to convert json to string!"); + return NULL; + } + return receivedDataStr; +} + +static void DoCreateGroup(HcTaskBase *task) +{ + if (task == NULL) { + LOGE("The input task is NULL!"); + return; + } + GroupManagerTask *realTask = (GroupManagerTask *)task; + LOGI("The task thread starts to execute group creation! [RequestId]: %lld", realTask->requestId); + if (!IsGroupManagerSupported()) { + LOGE("Group manager is not supported!"); + return; + } + GroupManager *instance = GetGroupManagerInstance(); + if (instance == NULL) { + LOGE("Failed to get groupManager instance!"); + return; + } + instance->createPeerToPeerGroup(realTask->requestId, realTask->jsonParams, realTask->callback); +} + +static void DoDeleteGroup(HcTaskBase *task) +{ + if (task == NULL) { + LOGE("The input task is NULL!"); + return; + } + GroupManagerTask *realTask = (GroupManagerTask *)task; + LOGI("The task thread starts to execute group deletion! [RequestId]: %lld", realTask->requestId); + if (!IsGroupManagerSupported()) { + LOGE("Group manager is not supported!"); + return; + } + GroupManager *instance = GetGroupManagerInstance(); + if (instance == NULL) { + LOGE("Failed to get groupManager instance!"); + return; + } + instance->deletePeerToPeerGroup(realTask->requestId, realTask->jsonParams, realTask->callback); +} + +static void DoAddMember(HcTaskBase *task) +{ + if (task == NULL) { + LOGE("The input task is NULL!"); + return; + } + GroupManagerTask *realTask = (GroupManagerTask *)task; + LOGI("The task thread starts to execute member addition! [RequestId]: %lld", realTask->requestId); + if (!IsGroupManagerSupported()) { + LOGE("Group manager is not supported!"); + return; + } + GroupManager *instance = GetGroupManagerInstance(); + if (instance == NULL) { + LOGE("Failed to get groupManager instance!"); + return; + } + instance->addMemberToPeerToPeerGroup(realTask->requestId, realTask->jsonParams, realTask->callback); +} + +static void DoDeleteMember(HcTaskBase *task) +{ + if (task == NULL) { + LOGE("The input task is NULL!"); + return; + } + GroupManagerTask *realTask = (GroupManagerTask *)task; + LOGI("The task thread starts to execute member deletion! [RequestId]: %lld", realTask->requestId); + if (!IsGroupManagerSupported()) { + LOGE("Group manager is not supported!"); + return; + } + GroupManager *instance = GetGroupManagerInstance(); + if (instance == NULL) { + LOGE("Failed to get groupManager instance!"); + return; + } + instance->deleteMemberFromPeerToPeerGroup(realTask->requestId, realTask->jsonParams, realTask->callback); +} + +static void DoConfirmRequest(HcTaskBase *task) +{ + if (task == NULL) { + LOGE("The input task is NULL!"); + return; + } + GroupManagerTask *realTask = (GroupManagerTask *)task; + LOGI("The task thread starts to execute request confirmation! [RequestId]: %lld", realTask->requestId); + OnConfirmationReceived(realTask->requestId, realTask->jsonParams); +} + +static void OnChannelOpenedAction(HcTaskBase *task) +{ + if (task == NULL) { + LOGE("The input task is NULL!"); + return; + } + GroupManagerTask *realTask = (GroupManagerTask *)task; + LOGI("The task thread starts to execute the task that needs to be executed" + "when the soft bus channel is open! [RequestId]: %lld", realTask->requestId); + CJson *jsonParams = realTask->jsonParams; + int64_t channelId = DEFAULT_CHANNEL_ID; + if (GetByteFromJson(jsonParams, FIELD_CHANNEL_ID, (uint8_t *)&channelId, sizeof(int64_t)) != HC_SUCCESS) { + LOGE("Failed to get channelId from json!"); + return; + } + OnChannelOpened(realTask->requestId, channelId); +} + +static void DoProcessBindData(HcTaskBase *task) +{ + if (task == NULL) { + LOGE("The input task is NULL!"); + return; + } + GroupManagerTask *realTask = (GroupManagerTask *)task; + if (IsRequestExist(realTask->requestId)) { + LOGI("The task thread starts to process data! [RequestId]: %lld", realTask->requestId); + int ret = ProcessSession(realTask->requestId, BIND_TYPE, realTask->jsonParams); + if (ret != CONTINUE) { + DestroySession(realTask->requestId); + } + return; + } + LOGI("The task thread starts to create a server binding session! [RequestId]: %lld", realTask->requestId); + if ((BindCallbackToTask(realTask, realTask->jsonParams) != HC_SUCCESS) || + (CheckMsgRepeatability(realTask->jsonParams, DAS_MODULE) != HC_SUCCESS)) { + return; + } + if (!IsGroupManagerSupported()) { + LOGE("Group manager is not supported!"); + return; + } + GroupManager *instance = GetGroupManagerInstance(); + if (instance == NULL) { + LOGE("Failed to get groupManager instance!"); + return; + } + instance->processBindData(realTask->requestId, realTask->jsonParams, realTask->callback); +} + +static void DestroyGroupAuthTask(HcTaskBase *task) +{ + AuthDeviceTask *realTask = (AuthDeviceTask *)task; + FreeJson(realTask->authParams); +} + +static void DestroyGroupManagerTask(HcTaskBase *task) +{ + if (task == NULL) { + LOGE("The input task is NULL!"); + return; + } + GroupManagerTask *realTask = (GroupManagerTask *)task; + FreeJson(realTask->jsonParams); +} + +static bool InitAuthDeviceTask(AuthDeviceTask *task, int64_t authReqId, CJson *authParams, + const DeviceAuthCallback *gaCallback) +{ + task->base.doAction = DoAuthDevice; + task->base.destroy = DestroyGroupAuthTask; + task->authReqId = authReqId; + if (AddByteToJson(authParams, FIELD_REQUEST_ID, (const uint8_t*)&authReqId, sizeof(int64_t)) != HC_SUCCESS) { + LOGE("Failed to add requestId to json!"); + return false; + } + task->authParams = authParams; + task->callback = gaCallback; + if (task->callback == NULL) { + LOGE("The input auth callback is null!"); + return false; + } + return true; +} + +static bool InitProcessDataTask(AuthDeviceTask *task, int64_t authReqId, CJson *receivedData, + const DeviceAuthCallback *gaCallback) +{ + task->base.doAction = DoProcessData; + task->base.destroy = DestroyGroupAuthTask; + task->authReqId = authReqId; + if (AddByteToJson(receivedData, FIELD_REQUEST_ID, (const uint8_t*)&authReqId, sizeof(int64_t)) != HC_SUCCESS) { + LOGE("Failed to add requestId to json!"); + return false; + } + task->authParams = receivedData; + task->callback = gaCallback; + if (task->callback == NULL) { + LOGE("The input auth callback is null!"); + return false; + } + return true; +} + +static void InitProcessBindDataTask(GroupManagerTask *task, int64_t requestId, CJson *jsonParams) +{ + task->base.doAction = DoProcessBindData; + task->base.destroy = DestroyGroupManagerTask; + task->requestId = requestId; + task->jsonParams = jsonParams; +} + +static void InitChannelOpenedTask(GroupManagerTask *task, int64_t requestId, CJson *jsonParams) +{ + task->base.doAction = OnChannelOpenedAction; + task->base.destroy = DestroyGroupManagerTask; + task->requestId = requestId; + task->jsonParams = jsonParams; +} + +static int32_t InitCreateGroupTask(GroupManagerTask *task, int64_t requestId, CJson *jsonParams) +{ + task->base.doAction = DoCreateGroup; + task->base.destroy = DestroyGroupManagerTask; + task->requestId = requestId; + task->jsonParams = jsonParams; + return BindCallbackToTask(task, jsonParams); +} + +static int32_t InitDeleteGroupTask(GroupManagerTask *task, int64_t requestId, CJson *jsonParams) +{ + task->base.doAction = DoDeleteGroup; + task->base.destroy = DestroyGroupManagerTask; + task->requestId = requestId; + task->jsonParams = jsonParams; + return BindCallbackToTask(task, jsonParams); +} + +static int32_t InitAddMemberTask(GroupManagerTask *task, int64_t requestId, CJson *jsonParams) +{ + task->base.doAction = DoAddMember; + task->base.destroy = DestroyGroupManagerTask; + task->requestId = requestId; + task->jsonParams = jsonParams; + return BindCallbackToTask(task, jsonParams); +} + +static int32_t InitDeleteMemberTask(GroupManagerTask *task, int64_t requestId, CJson *jsonParams) +{ + task->base.doAction = DoDeleteMember; + task->base.destroy = DestroyGroupManagerTask; + task->requestId = requestId; + task->jsonParams = jsonParams; + return BindCallbackToTask(task, jsonParams); +} + +static int32_t InitConfirmRequestTask(GroupManagerTask *task, int64_t requestId, CJson *jsonParams) +{ + task->base.doAction = DoConfirmRequest; + task->base.destroy = DestroyGroupManagerTask; + task->requestId = requestId; + task->jsonParams = jsonParams; + return BindCallbackToTask(task, jsonParams); +} + +static int32_t AuthDevice(int64_t authReqId, const char *authParams, const DeviceAuthCallback *gaCallback) +{ + LOGI("Begin AuthDevice."); + if (authParams == NULL) { + LOGE("The input auth params is null!"); + return HC_ERR_INVALID_PARAMS; + } + if (g_taskThread == NULL) { + LOGE("The task thread is null!"); + return HC_ERR_SERVICE_NEED_RESTART; + } + CJson *jsonParams = CreateJsonFromString(authParams); + if (jsonParams == NULL) { + LOGE("Create json from params failed!"); + return HC_ERR_JSON_FAIL; + } + AuthDeviceTask *task = (AuthDeviceTask *)HcMalloc(sizeof(AuthDeviceTask), 0); + if (task == NULL) { + FreeJson(jsonParams); + LOGE("Failed to allocate memory for task!"); + return HC_ERR_ALLOC_MEMORY; + } + if (!InitAuthDeviceTask(task, authReqId, jsonParams, gaCallback)) { + LOGE("Failed to init task!"); + FreeJson(jsonParams); + HcFree(task); + return HC_ERR_INIT_TASK_FAIL; + } + g_taskThread->pushTask(g_taskThread, (HcTaskBase*)task); + LOGI("Push AuthDevice task successfully."); + return HC_SUCCESS; +} + +static int32_t ProcessData(int64_t authReqId, const uint8_t *data, uint32_t dataLen, + const DeviceAuthCallback *gaCallback) +{ + LOGI("Begin ProcessData."); + if ((data == NULL) || (dataLen > MAX_DATA_BUFFER_SIZE)) { + LOGE("Invalid input for ProcessData!"); + return HC_ERR_INVALID_PARAMS; + } + if (g_taskThread == NULL) { + LOGE("The task thread is null!"); + return HC_ERR_SERVICE_NEED_RESTART; + } + CJson *receivedData = CreateJsonFromString((const char *)data); + if (receivedData == NULL) { + LOGE("Create Json for input data failed!"); + return HC_ERR_JSON_FAIL; + } + AuthDeviceTask *task = (AuthDeviceTask *)HcMalloc(sizeof(AuthDeviceTask), 0); + if (task == NULL) { + FreeJson(receivedData); + LOGE("Failed to allocate memory for task!"); + return HC_ERR_ALLOC_MEMORY; + } + if (!InitProcessDataTask(task, authReqId, receivedData, gaCallback)) { + LOGE("Failed to init task!"); + FreeJson(receivedData); + HcFree(task); + return HC_ERR_INIT_TASK_FAIL; + } + g_taskThread->pushTask(g_taskThread, (HcTaskBase*)task); + LOGI("Push ProcessData task successfully."); + return HC_SUCCESS; +} + +static int GetOperationCodeWhenAdd(CJson *jsonParams) +{ + bool isAdmin = true; + /* The isAdmin parameter is optional. Default value is true. */ + (void)GetBoolFromJson(jsonParams, FIELD_IS_ADMIN, &isAdmin); + /* Release the memory in advance to reduce the memory usage. */ + (void)DeleteItemFromJson(jsonParams, FIELD_IS_ADMIN); + return isAdmin ? MEMBER_INVITE : MEMBER_JOIN; +} + +static int32_t AddReqInfoToJson(int64_t requestId, const char *appId, CJson *jsonParams) +{ + if (AddInt64StringToJson(jsonParams, FIELD_REQUEST_ID, requestId) != HC_SUCCESS) { + LOGE("Failed to add requestId to json!"); + return HC_ERR_JSON_FAIL; + } + if (AddStringToJson(jsonParams, FIELD_APP_ID, appId) != HC_SUCCESS) { + LOGE("Failed to add appId to json!"); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} + +static int32_t AddBindParamsToJson(int operationCode, int64_t requestId, const char *appId, CJson *jsonParams) +{ + if (AddIntToJson(jsonParams, FIELD_OPERATION_CODE, operationCode) != HC_SUCCESS) { + LOGE("Failed to add operationCode to json!"); + return HC_ERR_JSON_FAIL; + } + return AddReqInfoToJson(requestId, appId, jsonParams); +} + +static int32_t AddClientParamsToJson(bool isClient, int operationCode, int64_t requestId, const char *appId, + CJson *jsonParams) +{ + if (AddBoolToJson(jsonParams, FIELD_IS_CLIENT, isClient) != HC_SUCCESS) { + LOGE("Failed to add isClient to json!"); + return HC_ERR_JSON_FAIL; + } + return AddBindParamsToJson(operationCode, requestId, appId, jsonParams); +} + +static int32_t AddServerParamsToJson(bool isClient, int64_t requestId, const char *appId, CJson *jsonParams) +{ + if (AddBoolToJson(jsonParams, FIELD_IS_CLIENT, isClient) != HC_SUCCESS) { + LOGE("Failed to add isClient to json!"); + return HC_ERR_JSON_FAIL; + } + return AddReqInfoToJson(requestId, appId, jsonParams); +} + +static int32_t RegGroupManagerCallback(const char *appId, const DeviceAuthCallback *callback) +{ + LOGI("[Start]: Service register GM callback! [AppId]: %s", appId); + if ((appId == NULL) || (callback == NULL)) { + LOGE("The input parameters contains NULL value!"); + return HC_ERR_INVALID_PARAMS; + } + if (!IsGroupManagerSupported()) { + LOGE("Group manager is not supported!"); + return HC_ERR_NOT_SUPPORT; + } + GroupManager *instance = GetGroupManagerInstance(); + if (instance == NULL) { + LOGE("Failed to get groupManager instance!"); + return HC_ERR_NULL_PTR; + } + return instance->regGroupManagerCallback(appId, callback); +} + +static int32_t UnRegGroupManagerCallback(const char *appId) +{ + LOGI("[Start]: Service deregister GM callback! [AppId]: %s", appId); + if (appId == NULL) { + LOGE("The input appId is NULL!"); + return HC_ERR_INVALID_PARAMS; + } + if (!IsGroupManagerSupported()) { + LOGE("Group manager is not supported!"); + return HC_ERR_NOT_SUPPORT; + } + GroupManager *instance = GetGroupManagerInstance(); + if (instance == NULL) { + LOGE("Failed to get groupManager instance!"); + return HC_ERR_NULL_PTR; + } + return instance->unRegGroupManagerCallback(appId); +} + +static int32_t RequestCreateGroup(int64_t requestId, const char *appId, const char *createParams) +{ + LOGI("[Start]: RequestCreateGroup! [AppId]: %s, [RequestId]: %lld", appId, requestId); + if ((appId == NULL) || (createParams == NULL)) { + LOGE("The input parameters contains NULL value!"); + return HC_ERR_INVALID_PARAMS; + } + if (g_taskThread == NULL) { + LOGE("Uninitialized task thread!"); + return HC_ERR_SERVICE_NEED_RESTART; + } + + CJson *jsonCreateParams = CreateJsonFromString(createParams); + if (jsonCreateParams == NULL) { + LOGE("Failed to create json from string!"); + return HC_ERR_JSON_FAIL; + } + int32_t result = AddBindParamsToJson(GROUP_CREATE, requestId, appId, jsonCreateParams); + if (result != HC_SUCCESS) { + FreeJson(jsonCreateParams); + return result; + } + + GroupManagerTask *task = (GroupManagerTask *)HcMalloc(sizeof(GroupManagerTask), 0); + if (task == NULL) { + LOGE("Failed to allocate task memory!"); + FreeJson(jsonCreateParams); + return HC_ERR_ALLOC_MEMORY; + } + if (InitCreateGroupTask(task, requestId, jsonCreateParams) != HC_SUCCESS) { + FreeJson(jsonCreateParams); + HcFree(task); + return HC_ERR_INIT_TASK_FAIL; + } + g_taskThread->pushTask(g_taskThread, (HcTaskBase*)task); + LOGI("[End]: Create the creating group task successfully! [AppId]: %s, [RequestId]: %lld", appId, requestId); + return HC_SUCCESS; +} + +static int32_t RequestDeleteGroup(int64_t requestId, const char *appId, const char *disbandParams) +{ + LOGI("[Start]: RequestDeleteGroup! [AppId]: %s, [RequestId]: %lld", appId, requestId); + if ((appId == NULL) || (disbandParams == NULL)) { + LOGE("The input parameters contains NULL value!"); + return HC_ERR_INVALID_PARAMS; + } + if (g_taskThread == NULL) { + LOGE("Uninitialized task thread!"); + return HC_ERR_SERVICE_NEED_RESTART; + } + + CJson *jsonDisBandParams = CreateJsonFromString(disbandParams); + if (jsonDisBandParams == NULL) { + LOGE("Failed to create json from string!"); + return HC_ERR_JSON_FAIL; + } + int32_t result = AddBindParamsToJson(GROUP_DISBAND, requestId, appId, jsonDisBandParams); + if (result != HC_SUCCESS) { + FreeJson(jsonDisBandParams); + return result; + } + + GroupManagerTask *task = (GroupManagerTask *)HcMalloc(sizeof(GroupManagerTask), 0); + if (task == NULL) { + LOGE("Failed to allocate task memory!"); + FreeJson(jsonDisBandParams); + return HC_ERR_ALLOC_MEMORY; + } + if (InitDeleteGroupTask(task, requestId, jsonDisBandParams) != HC_SUCCESS) { + FreeJson(jsonDisBandParams); + HcFree(task); + return HC_ERR_INIT_TASK_FAIL; + } + g_taskThread->pushTask(g_taskThread, (HcTaskBase *)task); + LOGI("[End]: Create the deleting group task successfully! [AppId]: %s, [RequestId]: %lld", appId, requestId); + return HC_SUCCESS; +} + +static int32_t RequestAddMemberToGroup(int64_t requestId, const char *appId, const char *addParams) +{ + LOGI("[Start]: RequestAddMemberToGroup! [AppId]: %s, [RequestId]: %lld", appId, requestId); + if ((appId == NULL) || (addParams == NULL)) { + LOGE("The input parameters contains NULL value!"); + return HC_ERR_INVALID_PARAMS; + } + if (g_taskThread == NULL) { + LOGE("Uninitialized task thread!"); + return HC_ERR_SERVICE_NEED_RESTART; + } + + CJson *jsonAddParams = CreateJsonFromString(addParams); + if (jsonAddParams == NULL) { + LOGE("Failed to create json from string!"); + return HC_ERR_JSON_FAIL; + } + int32_t result = AddBindParamsToJson(GetOperationCodeWhenAdd(jsonAddParams), requestId, appId, jsonAddParams); + if (result != HC_SUCCESS) { + FreeJson(jsonAddParams); + return result; + } + + GroupManagerTask *task = (GroupManagerTask *)HcMalloc(sizeof(GroupManagerTask), 0); + if (task == NULL) { + LOGE("Failed to allocate task memory!"); + FreeJson(jsonAddParams); + return HC_ERR_ALLOC_MEMORY; + } + if (InitAddMemberTask(task, requestId, jsonAddParams) != HC_SUCCESS) { + FreeJson(jsonAddParams); + HcFree(task); + return HC_ERR_INIT_TASK_FAIL; + } + g_taskThread->pushTask(g_taskThread, (HcTaskBase*)task); + LOGI("[End]: Create the adding member task successfully! [AppId]: %s, [RequestId]: %lld", appId, requestId); + return HC_SUCCESS; +} + +static int32_t RequestDeleteMemberFromGroup(int64_t requestId, const char *appId, const char *deleteParams) +{ + LOGI("[Start]: RequestDeleteMemberFromGroup! [AppId]: %s, [RequestId]: %lld", appId, requestId); + if ((appId == NULL) || (deleteParams == NULL)) { + LOGE("The input parameters contains NULL value!"); + return HC_ERR_INVALID_PARAMS; + } + if (g_taskThread == NULL) { + LOGE("Uninitialized task thread!"); + return HC_ERR_SERVICE_NEED_RESTART; + } + + CJson *jsonDeleteParams = CreateJsonFromString(deleteParams); + if (jsonDeleteParams == NULL) { + LOGE("Failed to create json from string!"); + return HC_ERR_JSON_FAIL; + } + int32_t result = AddBindParamsToJson(MEMBER_DELETE, requestId, appId, jsonDeleteParams); + if (result != HC_SUCCESS) { + FreeJson(jsonDeleteParams); + return result; + } + + GroupManagerTask *task = (GroupManagerTask *)HcMalloc(sizeof(GroupManagerTask), 0); + if (task == NULL) { + LOGE("Failed to allocate task memory!"); + FreeJson(jsonDeleteParams); + return HC_ERR_ALLOC_MEMORY; + } + if (InitDeleteMemberTask(task, requestId, jsonDeleteParams) != HC_SUCCESS) { + FreeJson(jsonDeleteParams); + HcFree(task); + return HC_ERR_INIT_TASK_FAIL; + } + g_taskThread->pushTask(g_taskThread, (HcTaskBase*)task); + LOGI("[End]: Create the deleting member task successfully! [AppId]: %s, [RequestId]: %lld", appId, requestId); + return HC_SUCCESS; +} + +static int32_t RequestProcessBindData(int64_t requestId, const uint8_t *data, uint32_t dataLen) +{ + LOGI("[Start]: RequestProcessBindData! [RequestId]: %lld", requestId); + if ((data == NULL) || (dataLen > MAX_DATA_BUFFER_SIZE)) { + LOGE("The input data is invalid!"); + return HC_ERR_INVALID_PARAMS; + } + if (g_taskThread == NULL) { + LOGE("The task thread is NULL!"); + return HC_ERR_SERVICE_NEED_RESTART; + } + + CJson *dataJson = CreateJsonFromString((const char *)data); + if (dataJson == NULL) { + LOGE("Failed to create json from string!"); + return HC_ERR_JSON_FAIL; + } + int64_t tempRequestId = DEFAULT_REQUEST_ID; + if (GetInt64FromJson(dataJson, FIELD_REQUEST_ID, &tempRequestId) != HC_SUCCESS) { + LOGE("Failed to get requestId from json!"); + FreeJson(dataJson); + return HC_ERR_JSON_GET; + } + if (tempRequestId != requestId) { + LOGE("The requestId transferred by the service is inconsistent with that in the packet! " + "[ServiceRequestId]: %lld, [RequestId]: %lld", requestId, tempRequestId); + return HC_ERR_INVALID_PARAMS; + } + GroupManagerTask *task = (GroupManagerTask *)HcMalloc(sizeof(GroupManagerTask), 0); + if (task == NULL) { + LOGE("Failed to allocate task memory!"); + FreeJson(dataJson); + return HC_ERR_ALLOC_MEMORY; + } + InitProcessBindDataTask(task, requestId, dataJson); + g_taskThread->pushTask(g_taskThread, (HcTaskBase*)task); + LOGI("[End]: Create the processing data task successfully! [RequestId]: %lld", requestId); + return HC_SUCCESS; +} + +static int32_t ConfirmRequest(int64_t requestId, const char *appId, const char *confirmParams) +{ + LOGI("[Start]: ConfirmRequest! [AppId]: %s, [RequestId]: %lld", appId, requestId); + if ((appId == NULL) || (confirmParams == NULL)) { + LOGE("The input parameters contains NULL value!"); + return HC_ERR_INVALID_PARAMS; + } + if (g_taskThread == NULL) { + LOGE("Uninitialized task thread!"); + return HC_ERR_SERVICE_NEED_RESTART; + } + + CJson *jsonConfirmParams = CreateJsonFromString(confirmParams); + if (jsonConfirmParams == NULL) { + LOGE("Failed to create json from string!"); + return HC_ERR_JSON_FAIL; + } + if (AddStringToJson(jsonConfirmParams, FIELD_APP_ID, appId) != HC_SUCCESS) { + LOGE("Failed to add appId to json!"); + return HC_ERR_JSON_FAIL; + } + + GroupManagerTask *task = (GroupManagerTask *)HcMalloc(sizeof(GroupManagerTask), 0); + if (task == NULL) { + LOGE("Failed to allocate task memory!"); + FreeJson(jsonConfirmParams); + return HC_ERR_ALLOC_MEMORY; + } + if (InitConfirmRequestTask(task, requestId, jsonConfirmParams) != HC_SUCCESS) { + FreeJson(jsonConfirmParams); + HcFree(task); + return HC_ERR_INIT_TASK_FAIL; + } + g_taskThread->pushTask(g_taskThread, (HcTaskBase*)task); + LOGI("[End]: Create the confirming request task successfully! [AppId]: %s, [RequestId]: %lld", appId, requestId); + return HC_SUCCESS; +} + +static void OnChannelOpenedCallback(int64_t channelId, int64_t requestId, const char *deviceId, + uint32_t deviceIdLen, bool isServer) +{ + if (isServer) { + return; + } + if ((deviceId == NULL) || (deviceIdLen > MAX_DATA_BUFFER_SIZE)) { + LOGE("The input parameters is invalid!"); + return; + } + if (g_taskThread == NULL) { + LOGE("Uninitialized task thread!"); + return; + } + + CJson *jsonParams = CreateJson(); + if (jsonParams == NULL) { + LOGE("Failed to allocate jsonParams memory!"); + return; + } + if (AddByteToJson(jsonParams, FIELD_CHANNEL_ID, (uint8_t *)&channelId, sizeof(int64_t)) != HC_SUCCESS) { + LOGE("Failed to add channelId to jsonParams!"); + FreeJson(jsonParams); + return; + } + + GroupManagerTask *task = (GroupManagerTask *)HcMalloc(sizeof(GroupManagerTask), 0); + if (task == NULL) { + LOGE("Failed to allocate task memory!"); + FreeJson(jsonParams); + return; + } + InitChannelOpenedTask(task, requestId, jsonParams); + g_taskThread->pushTask(g_taskThread, (HcTaskBase*)task); +} + +static void OnChannelClosedCallback(int64_t channelId, int64_t requestId) +{ + (void)channelId; + (void)requestId; + return; +} + +static void OnMsgReceivedCallback(int64_t channelId, const uint8_t *data, uint32_t dataLen) +{ + LOGI("Receive data from the peer end!"); + if ((data == NULL) || (dataLen > MAX_DATA_BUFFER_SIZE)) { + LOGE("The input data is invalid!"); + return; + } + + int64_t requestId = DEFAULT_REQUEST_ID; + char *receivedDataStr = GenerateRecvData(channelId, data, dataLen, &requestId); + if (receivedDataStr == NULL) { + return; + } + if (RequestProcessBindData(DEFAULT_REQUEST_ID, (uint8_t *)receivedDataStr, + (uint32_t)(strlen(receivedDataStr) + 1)) != HC_SUCCESS) { + LOGE("Failed to process bind data from softBus!"); + } + FreeJsonString(receivedDataStr); +} + +static void OnServiceDiedCallback(void) +{ + return; +} + +static int32_t GetModuleType(const CJson *jsonParams) +{ + bool isAccountBind = false; + if (GetBoolFromJson(jsonParams, FIELD_IS_ACCOUNT_BIND, &isAccountBind) != HC_SUCCESS) { + return DAS_MODULE; + } + if (isAccountBind == false) { + return DAS_MODULE; + } + return TCIS_MODULE; +} + +static void DoProcessLiteData(HcTaskBase *task) +{ + if (task == NULL) { + LOGE("The input task is NULL!"); + return; + } + GroupManagerTask *realTask = (GroupManagerTask *)task; + LOGI("The task thread starts to execute the processing lite data task! [RequestId]: %lld", realTask->requestId); + if (IsRequestExist(realTask->requestId)) { + int ret = ProcessSession(realTask->requestId, BIND_TYPE, realTask->jsonParams); + if (ret != CONTINUE) { + DestroySession(realTask->requestId); + } + return; + } + if ((BindCallbackToTask(realTask, realTask->jsonParams) != HC_SUCCESS) || + ((CheckMsgRepeatability(realTask->jsonParams, GetModuleType(realTask->jsonParams))) != HC_SUCCESS)) { + return; + } + int32_t result = CreateSession(realTask->requestId, TYPE_SERVER_BIND_SESSION_LITE, + realTask->jsonParams, realTask->callback); + if (result != HC_SUCCESS) { + LOGE("Failed to create server lite bind session. We need to notify the service!"); + } +} + +static void DoBindPeer(HcTaskBase *task) +{ + if (task == NULL) { + LOGE("The input task is NULL!"); + return; + } + GroupManagerTask *realTask = (GroupManagerTask *)task; + LOGI("The task thread starts to execute the binding peer device task! [RequestId]: %lld", realTask->requestId); + int32_t result; + ChannelType channelType = GetChannelType(realTask->callback); + do { + if ((channelType == NO_CHANNEL) || + (!CanFindValidChannel(channelType, realTask->jsonParams, realTask->callback))) { + LOGE("No available channels found!"); + result = HC_ERR_CHANNEL_NOT_EXIST; + break; + } + result = CreateSession(realTask->requestId, TYPE_CLIENT_BIND_SESSION_LITE, + realTask->jsonParams, realTask->callback); + } while (0); + if (result != HC_SUCCESS) { + LOGE("Failed to create client lite bind session. We need to notify the service!"); + ProcessErrorCallback(realTask->requestId, OP_BIND, result, NULL, realTask->callback); + return; + } + /* If service open the channel by itself, + * a channel opened message needs to be triggered to unify the channel usage policy. */ + if (channelType == SERVICE_CHANNEL) { + /* Release the memory in advance to reduce the memory usage. */ + DeleteAllItem(realTask->jsonParams); + OnChannelOpened(realTask->requestId, DEFAULT_CHANNEL_ID); + } +} + +static void DoUnbindPeer(HcTaskBase *task) +{ + if (task == NULL) { + LOGE("The input task is NULL!"); + return; + } + GroupManagerTask *realTask = (GroupManagerTask *)task; + LOGI("The task thread starts to execute the unbinding peer device task! [RequestId]: %lld", realTask->requestId); + int32_t result; + ChannelType channelType = GetChannelType(realTask->callback); + do { + if ((channelType == NO_CHANNEL) || + (!CanFindValidChannel(channelType, realTask->jsonParams, realTask->callback))) { + LOGE("No available channels found!"); + result = HC_ERR_CHANNEL_NOT_EXIST; + break; + } + result = CreateSession(realTask->requestId, TYPE_CLIENT_BIND_SESSION_LITE, + realTask->jsonParams, realTask->callback); + } while (0); + if (result != HC_SUCCESS) { + LOGE("Failed to create client lite bind session. We need to notify the service!"); + ProcessErrorCallback(realTask->requestId, OP_UNBIND, result, NULL, realTask->callback); + return; + } + /* If service open the channel by itself, + * a channel opened message needs to be triggered to unify the channel usage policy. */ + if (channelType == SERVICE_CHANNEL) { + /* Release the memory in advance to reduce the memory usage. */ + DeleteAllItem(realTask->jsonParams); + OnChannelOpened(realTask->requestId, DEFAULT_CHANNEL_ID); + } +} + +static void DoAuthAgreeKey(HcTaskBase *task) +{ + if (task == NULL) { + LOGE("The input task is NULL!"); + return; + } + GroupManagerTask *realTask = (GroupManagerTask *)task; + LOGI("The task thread starts to execute the key agreement task! [RequestId]: %lld", realTask->requestId); + int32_t result; + ChannelType channelType = GetChannelType(realTask->callback); + do { + if ((channelType == NO_CHANNEL) || + (!CanFindValidChannel(channelType, realTask->jsonParams, realTask->callback))) { + LOGE("No available channels found!"); + result = HC_ERR_CHANNEL_NOT_EXIST; + break; + } + result = CreateSession(realTask->requestId, TYPE_CLIENT_KEY_AGREE_SESSION, + realTask->jsonParams, realTask->callback); + } while (0); + if (result != HC_SUCCESS) { + LOGE("Failed to create client key agreement session. We need to notify the service!"); + ProcessErrorCallback(realTask->requestId, AUTH_KEY_AGREEMENT, result, NULL, realTask->callback); + return; + } + /* If service open the channel by itself, + * a channel opened message needs to be triggered to unify the channel usage policy. */ + if (channelType == SERVICE_CHANNEL) { + /* Release the memory in advance to reduce the memory usage. */ + DeleteAllItem(realTask->jsonParams); + OnChannelOpened(realTask->requestId, DEFAULT_CHANNEL_ID); + } +} + +static void DoProcessKeyAgreeData(HcTaskBase *task) +{ + if (task == NULL) { + LOGE("The input task is NULL!"); + return; + } + GroupManagerTask *realTask = (GroupManagerTask *)task; + LOGI("The task thread starts to execute the processing key agreement data task! [RequestId]: %lld", + realTask->requestId); + if (IsRequestExist(realTask->requestId)) { + int ret = ProcessSession(realTask->requestId, BIND_TYPE, realTask->jsonParams); + if (ret != CONTINUE) { + DestroySession(realTask->requestId); + } + return; + } + if ((BindCallbackToTask(realTask, realTask->jsonParams) != HC_SUCCESS) || + ((CheckMsgRepeatability(realTask->jsonParams, DAS_MODULE)) != HC_SUCCESS)) { + return; + } + int32_t result = CreateSession(realTask->requestId, TYPE_SERVER_KEY_AGREE_SESSION, + realTask->jsonParams, realTask->callback); + if (result != HC_SUCCESS) { + LOGE("Failed to create server lite bind session. We need to notify the service!"); + } +} + +static int32_t InitProcessLiteDataTask(GroupManagerTask *task, int64_t requestId, CJson *jsonParams) +{ + task->base.doAction = DoProcessLiteData; + task->base.destroy = DestroyGroupManagerTask; + task->requestId = requestId; + task->jsonParams = jsonParams; + return HC_SUCCESS; +} + +static int32_t InitBindPeerTask(GroupManagerTask *task, int64_t requestId, CJson *jsonParams) +{ + task->base.doAction = DoBindPeer; + task->base.destroy = DestroyGroupManagerTask; + task->requestId = requestId; + task->jsonParams = jsonParams; + return BindCallbackToTask(task, jsonParams); +} + +static int32_t InitUnbindPeerTask(GroupManagerTask *task, int64_t requestId, CJson *jsonParams) +{ + task->base.doAction = DoUnbindPeer; + task->base.destroy = DestroyGroupManagerTask; + task->requestId = requestId; + task->jsonParams = jsonParams; + return BindCallbackToTask(task, jsonParams); +} + +static int32_t InitAuthAgreeKeyTask(GroupManagerTask *task, int64_t requestId, CJson *jsonParams) +{ + task->base.doAction = DoAuthAgreeKey; + task->base.destroy = DestroyGroupManagerTask; + task->requestId = requestId; + task->jsonParams = jsonParams; + return BindCallbackToTask(task, jsonParams); +} + +static int32_t InitProcessKeyAgreeDataTask(GroupManagerTask *task, int64_t requestId, CJson *jsonParams) +{ + task->base.doAction = DoProcessKeyAgreeData; + task->base.destroy = DestroyGroupManagerTask; + task->requestId = requestId; + task->jsonParams = jsonParams; + return HC_SUCCESS; +} + +static int32_t AddLiteDataToReceivedData(CJson *receivedData, int64_t requestId, const char *appId) +{ + int groupOp = ACCOUNT_BIND; + (void)GetIntFromJson(receivedData, FIELD_GROUP_OP, &groupOp); + if (groupOp == ACCOUNT_BIND) { + if (AddBoolToJson(receivedData, FIELD_IS_ACCOUNT_BIND, true) != HC_SUCCESS) { + LOGE("Failed to add isAccountBind to json!"); + return HC_ERR_JSON_FAIL; + } + return AddBindParamsToJson(groupOp, requestId, appId, receivedData); + } + return AddServerParamsToJson(true, requestId, appId, receivedData); +} + +static int32_t RequestProcessLiteData(int64_t requestId, const char *appId, const uint8_t *data, uint32_t dataLen) +{ + LOGI("[Start]: RequestProcessLiteData! [AppId]: %s, [RequestId]: %lld", appId, requestId); + if ((appId == NULL) || (data == NULL) || (dataLen > MAX_DATA_BUFFER_SIZE)) { + LOGE("The input data is NULL or dataLen is beyond max size!"); + return HC_ERR_INVALID_PARAMS; + } + if (g_taskThread == NULL) { + LOGE("Uninitialized task thread!"); + return HC_ERR_SERVICE_NEED_RESTART; + } + + CJson *receivedData = CreateJsonFromString((const char *)data); + if (receivedData == NULL) { + LOGE("Failed to create received json object from string!"); + return HC_ERR_JSON_FAIL; + } + if (AddLiteDataToReceivedData(receivedData, requestId, appId) != HC_SUCCESS) { + FreeJson(receivedData); + return HC_ERR_JSON_FAIL; + } + + GroupManagerTask *task = (GroupManagerTask *)HcMalloc(sizeof(GroupManagerTask), 0); + if (task == NULL) { + LOGE("Failed to allocate task memory!"); + FreeJson(receivedData); + return HC_ERR_ALLOC_MEMORY; + } + if (InitProcessLiteDataTask(task, requestId, receivedData) != HC_SUCCESS) { + FreeJson(receivedData); + HcFree(task); + return HC_ERR_INIT_TASK_FAIL; + } + g_taskThread->pushTask(g_taskThread, (HcTaskBase*)task); + LOGI("[End]: Create the processing lite data task successfully! [AppId]: %s, [RequestId]: %lld", appId, requestId); + return HC_SUCCESS; +} + +static int32_t RequestBindPeer(int64_t requestId, const char *appId, const char *bindParams) +{ + LOGI("[Start]: RequestBindPeer! [AppId]: %s, [RequestId]: %lld", appId, requestId); + if ((appId == NULL) || (bindParams == NULL)) { + LOGE("The input parameters contains NULL value!"); + return HC_ERR_INVALID_PARAMS; + } + if (g_taskThread == NULL) { + LOGE("Uninitialized task thread!"); + return HC_ERR_SERVICE_NEED_RESTART; + } + + CJson *jsonBindParams = CreateJsonFromString(bindParams); + if (jsonBindParams == NULL) { + LOGE("Failed to create json from string!"); + return HC_ERR_JSON_FAIL; + } + int32_t result = AddClientParamsToJson(true, OP_BIND, requestId, appId, jsonBindParams); + if (result != HC_SUCCESS) { + FreeJson(jsonBindParams); + return result; + } + + GroupManagerTask *task = (GroupManagerTask *)HcMalloc(sizeof(GroupManagerTask), 0); + if (task == NULL) { + LOGE("Failed to allocate task memory!"); + FreeJson(jsonBindParams); + return HC_ERR_ALLOC_MEMORY; + } + if (InitBindPeerTask(task, requestId, jsonBindParams) != HC_SUCCESS) { + FreeJson(jsonBindParams); + HcFree(task); + return HC_ERR_INIT_TASK_FAIL; + } + g_taskThread->pushTask(g_taskThread, (HcTaskBase*)task); + LOGI("[End]: Create the binding peer device task successfully! [AppId]: %s, [RequestId]: %lld", appId, requestId); + return HC_SUCCESS; +} + +static int32_t RequestUnbindPeer(int64_t requestId, const char *appId, const char *unBindParams) +{ + LOGI("[Start]: RequestUnbindPeer, [AppId]: %s, [RequestId]: %lld", appId, requestId); + if ((appId == NULL) || (unBindParams == NULL)) { + LOGE("The input parameters contains NULL value!"); + return HC_ERR_INVALID_PARAMS; + } + if (g_taskThread == NULL) { + LOGE("Uninitialized task thread!"); + return HC_ERR_SERVICE_NEED_RESTART; + } + + CJson *jsonUnbindParams = CreateJsonFromString(unBindParams); + if (jsonUnbindParams == NULL) { + LOGE("Failed to create json from string!"); + return HC_ERR_JSON_FAIL; + } + int32_t result = AddClientParamsToJson(true, OP_UNBIND, requestId, appId, jsonUnbindParams); + if (result != HC_SUCCESS) { + FreeJson(jsonUnbindParams); + return result; + } + + GroupManagerTask *task = (GroupManagerTask *)HcMalloc(sizeof(GroupManagerTask), 0); + if (task == NULL) { + LOGE("Failed to allocate task memory!"); + FreeJson(jsonUnbindParams); + return HC_ERR_ALLOC_MEMORY; + } + if (InitUnbindPeerTask(task, requestId, jsonUnbindParams) != HC_SUCCESS) { + FreeJson(jsonUnbindParams); + HcFree(task); + return HC_ERR_INIT_TASK_FAIL; + } + g_taskThread->pushTask(g_taskThread, (HcTaskBase*)task); + LOGI("[End]: Create the unbinding peer device task successfully! [AppId]: %s, [RequestId]: %lld", appId, requestId); + return HC_SUCCESS; +} + +static int32_t RequestAuthKeyAgree(int64_t requestId, const char *appId, const char *agreeParams) +{ + LOGI("[Start]: RequestAuthKeyAgree! [AppId]: %s, [RequestId]: %lld", appId, requestId); + if ((appId == NULL) || (agreeParams == NULL)) { + LOGE("The input parameters contains NULL value!"); + return HC_ERR_INVALID_PARAMS; + } + if (g_taskThread == NULL) { + LOGE("Uninitialized task thread!"); + return HC_ERR_SERVICE_NEED_RESTART; + } + + CJson *jsonAgreeParams = CreateJsonFromString(agreeParams); + if (jsonAgreeParams == NULL) { + LOGE("Failed to create json from string!"); + return HC_ERR_JSON_FAIL; + } + int32_t result = AddClientParamsToJson(true, AUTH_KEY_AGREEMENT, requestId, appId, jsonAgreeParams); + if (result != HC_SUCCESS) { + FreeJson(jsonAgreeParams); + return result; + } + + GroupManagerTask *task = (GroupManagerTask *)HcMalloc(sizeof(GroupManagerTask), 0); + if (task == NULL) { + LOGE("Failed to allocate task memory!"); + FreeJson(jsonAgreeParams); + return HC_ERR_ALLOC_MEMORY; + } + if (InitAuthAgreeKeyTask(task, requestId, jsonAgreeParams) != HC_SUCCESS) { + FreeJson(jsonAgreeParams); + HcFree(task); + return HC_ERR_INIT_TASK_FAIL; + } + g_taskThread->pushTask(g_taskThread, (HcTaskBase*)task); + LOGI("[End]: Create the key agreement task successfully! [AppId]: %s, [RequestId]: %lld", appId, requestId); + return HC_SUCCESS; +} + +static int32_t RequestProcessKeyAgreeData(int64_t requestId, const char *appId, const uint8_t *data, uint32_t dataLen) +{ + LOGI("[Start]: RequestProcessKeyAgreeData! [AppId]: %s, [RequestId]: %lld", appId, requestId); + if ((appId == NULL) || (data == NULL) || (dataLen > MAX_DATA_BUFFER_SIZE)) { + LOGE("The input data is NULL or dataLen is beyond max size!"); + return HC_ERR_INVALID_PARAMS; + } + if (g_taskThread == NULL) { + LOGE("Uninitialized task thread!"); + return HC_ERR_SERVICE_NEED_RESTART; + } + + CJson *receivedData = CreateJsonFromString((const char *)data); + if (receivedData == NULL) { + LOGE("Failed to create received json object from string!"); + return HC_ERR_JSON_FAIL; + } + if (AddServerParamsToJson(false, requestId, appId, receivedData) != HC_SUCCESS) { + FreeJson(receivedData); + return HC_ERR_JSON_FAIL; + } + + GroupManagerTask *task = (GroupManagerTask *)HcMalloc(sizeof(GroupManagerTask), 0); + if (task == NULL) { + LOGE("Failed to allocate task memory!"); + FreeJson(receivedData); + return HC_ERR_ALLOC_MEMORY; + } + if (InitProcessKeyAgreeDataTask(task, requestId, receivedData) != HC_SUCCESS) { + FreeJson(receivedData); + HcFree(task); + return HC_ERR_INIT_TASK_FAIL; + } + g_taskThread->pushTask(g_taskThread, (HcTaskBase*)task); + LOGI("[End]: Create the processing key agreement data task successfully! [AppId]: %s, [RequestId]: %lld", appId, + requestId); + return HC_SUCCESS; +} + +static int32_t ProcessCredential(int operationCode, const char *reqJsonStr, char **returnJsonStr) +{ + LOGE("Process credential is not supported!"); + (void)operationCode; + (void)reqJsonStr; + (void)returnJsonStr; + return HC_ERR_NOT_SUPPORT; +} + +static int32_t GetRegisterInfo(char **returnRegisterInfo) +{ + LOGE("Get register information is not supported!"); + (void)returnRegisterInfo; + return HC_ERR_NOT_SUPPORT; +} + +static int32_t AddGroupManagerIfAccessible(const char *appId, const char *groupId, const char *managerAppId) +{ + LOGI("[Start]: AddGroupManager! [AppId]: %s, [ManagerAppId]: %s", appId, managerAppId); + if ((appId == NULL) || (groupId == NULL) || (managerAppId == NULL)) { + LOGE("The input parameters contains NULL value!"); + return HC_ERR_INVALID_PARAMS; + } + if (!IsGroupManagerSupported()) { + LOGE("Group manager is not supported!"); + return HC_ERR_NOT_SUPPORT; + } + GroupManager *instance = GetGroupManagerInstance(); + if (instance == NULL) { + LOGE("Failed to get groupManager instance!"); + return HC_ERR_NULL_PTR; + } + return instance->addGroupRole(true, appId, groupId, managerAppId); +} + +static int32_t AddGroupFriendIfAccessible(const char *appId, const char *groupId, const char *friendAppId) +{ + LOGI("[Start]: AddGroupFriend! [AppId]: %s, [FriendAppId]: %s", appId, friendAppId); + if ((appId == NULL) || (groupId == NULL) || (friendAppId == NULL)) { + LOGE("The input parameters contains NULL value!"); + return HC_ERR_INVALID_PARAMS; + } + if (!IsGroupManagerSupported()) { + LOGE("Group manager is not supported!"); + return HC_ERR_NOT_SUPPORT; + } + GroupManager *instance = GetGroupManagerInstance(); + if (instance == NULL) { + LOGE("Failed to get groupManager instance!"); + return HC_ERR_NULL_PTR; + } + return instance->addGroupRole(false, appId, groupId, friendAppId); +} + +static int32_t DeleteGroupManagerIfAccessible(const char *appId, const char *groupId, const char *managerAppId) +{ + LOGI("[Start]: DeleteGroupManager! [AppId]: %s, [ManagerAppId]: %s", appId, managerAppId); + if ((appId == NULL) || (groupId == NULL) || (managerAppId == NULL)) { + LOGE("The input parameters contains NULL value!"); + return HC_ERR_INVALID_PARAMS; + } + if (!IsGroupManagerSupported()) { + LOGE("Group manager is not supported!"); + return HC_ERR_NOT_SUPPORT; + } + GroupManager *instance = GetGroupManagerInstance(); + if (instance == NULL) { + LOGE("Failed to get groupManager instance!"); + return HC_ERR_NULL_PTR; + } + return instance->deleteGroupRole(true, appId, groupId, managerAppId); +} + +static int32_t DeleteGroupFriendIfAccessible(const char *appId, const char *groupId, const char *friendAppId) +{ + LOGI("[Start]: DeleteGroupFriend! [AppId]: %s, [FriendAppId]: %s", appId, friendAppId); + if ((appId == NULL) || (groupId == NULL) || (friendAppId == NULL)) { + LOGE("The input parameters contains NULL value!"); + return HC_ERR_INVALID_PARAMS; + } + if (!IsGroupManagerSupported()) { + LOGE("Group manager is not supported!"); + return HC_ERR_NOT_SUPPORT; + } + GroupManager *instance = GetGroupManagerInstance(); + if (instance == NULL) { + LOGE("Failed to get groupManager instance!"); + return HC_ERR_NULL_PTR; + } + return instance->deleteGroupRole(false, appId, groupId, friendAppId); +} + +static int32_t GetGroupManagersIfAccessible(const char *appId, const char *groupId, char **returnManagers, + uint32_t *returnSize) +{ + LOGI("[Start]: GetGroupManagers! [AppId]: %s", appId); + if ((appId == NULL) || (groupId == NULL) || (returnManagers == NULL) || (returnSize == NULL)) { + LOGE("The input parameters contains NULL value!"); + return HC_ERR_INVALID_PARAMS; + } + if (!IsGroupManagerSupported()) { + LOGE("Group manager is not supported!"); + return HC_ERR_NOT_SUPPORT; + } + GroupManager *instance = GetGroupManagerInstance(); + if (instance == NULL) { + LOGE("Failed to get groupManager instance!"); + return HC_ERR_NULL_PTR; + } + return instance->getGroupRole(true, appId, groupId, returnManagers, returnSize); +} + +static int32_t GetGroupFriendsIfAccessible(const char *appId, const char *groupId, char **returnFriends, + uint32_t *returnSize) +{ + LOGI("[Start]: GetGroupFriends! [AppId]: %s", appId); + if ((appId == NULL) || (groupId == NULL) || (returnFriends == NULL) || (returnSize == NULL)) { + LOGE("The input parameters contains NULL value!"); + return HC_ERR_INVALID_PARAMS; + } + if (!IsGroupManagerSupported()) { + LOGE("Group manager is not supported!"); + return HC_ERR_NOT_SUPPORT; + } + GroupManager *instance = GetGroupManagerInstance(); + if (instance == NULL) { + LOGE("Failed to get groupManager instance!"); + return HC_ERR_NULL_PTR; + } + return instance->getGroupRole(false, appId, groupId, returnFriends, returnSize); +} + +static int32_t RegListener(const char *appId, const DataChangeListener *listener) +{ + LOGI("[Start]: Service register listener! [AppId]: %s", appId); + if ((appId == NULL) || (listener == NULL)) { + LOGE("The input parameter contains NULL value!"); + return HC_ERR_INVALID_PARAMS; + } + if (!IsGroupManagerSupported()) { + LOGE("Group manager is not supported!"); + return HC_ERR_NOT_SUPPORT; + } + GroupManager *instance = GetGroupManagerInstance(); + if (instance == NULL) { + LOGE("Failed to get groupManager instance!"); + return HC_ERR_NULL_PTR; + } + return instance->regListener(appId, listener); +} + +static int32_t UnRegListener(const char *appId) +{ + LOGI("[Start]: Service deregister listener! [AppId]: %s", appId); + if (appId == NULL) { + LOGE("The input appId is NULL!"); + return HC_ERR_INVALID_PARAMS; + } + if (!IsGroupManagerSupported()) { + LOGE("Group manager is not supported!"); + return HC_ERR_NOT_SUPPORT; + } + GroupManager *instance = GetGroupManagerInstance(); + if (instance == NULL) { + LOGE("Failed to get groupManager instance!"); + return HC_ERR_NULL_PTR; + } + return instance->unRegListener(appId); +} + +static int32_t GetAccessibleGroupInfoById(const char *appId, const char *groupId, char **returnGroupInfo) +{ + LOGI("[Start]: GetAccessibleGroupInfoById! [AppId]: %s, [GroupId]: %s", appId, groupId); + if ((appId == NULL) || (groupId == NULL) || (returnGroupInfo == NULL)) { + LOGE("The input parameter contains NULL value!"); + return HC_ERR_INVALID_PARAMS; + } + if (!IsGroupManagerSupported()) { + LOGE("Group manager is not supported!"); + return HC_ERR_NOT_SUPPORT; + } + GroupManager *instance = GetGroupManagerInstance(); + if (instance == NULL) { + LOGE("Failed to get groupManager instance!"); + return HC_ERR_NULL_PTR; + } + return instance->getAccessibleGroupInfoById(appId, groupId, returnGroupInfo); +} + +static int32_t GetAccessibleGroupInfo(const char *appId, const char *queryParams, char **returnGroupVec, + uint32_t *groupNum) +{ + LOGI("[Start]: GetAccessibleGroupInfo! [AppId]: %s, [QueryParams]: %s", appId, queryParams); + if ((appId == NULL) || (queryParams == NULL) || (returnGroupVec == NULL) || (groupNum == NULL)) { + LOGE("The input parameter contains NULL value!"); + return HC_ERR_INVALID_PARAMS; + } + if (!IsGroupManagerSupported()) { + LOGE("Group manager is not supported!"); + return HC_ERR_NOT_SUPPORT; + } + GroupManager *instance = GetGroupManagerInstance(); + if (instance == NULL) { + LOGE("Failed to get groupManager instance!"); + return HC_ERR_NULL_PTR; + } + return instance->getAccessibleGroupInfo(appId, queryParams, returnGroupVec, groupNum); +} + +static int32_t GetAccessibleJoinedGroups(const char *appId, int groupType, char **returnGroupVec, uint32_t *groupNum) +{ + LOGI("[Start]: GetAccessibleJoinedGroups! [AppId]: %s, [GroupType]: %d", appId, groupType); + if ((appId == NULL) || (returnGroupVec == NULL) || (groupNum == NULL)) { + LOGE("The input parameter contains NULL value!"); + return HC_ERR_INVALID_PARAMS; + } + if (!IsGroupManagerSupported()) { + LOGE("Group manager is not supported!"); + return HC_ERR_NOT_SUPPORT; + } + GroupManager *instance = GetGroupManagerInstance(); + if (instance == NULL) { + LOGE("Failed to get groupManager instance!"); + return HC_ERR_NULL_PTR; + } + return instance->getAccessibleJoinedGroups(appId, groupType, returnGroupVec, groupNum); +} + +static int32_t GetAccessibleRelatedGroups(const char *appId, const char *peerDeviceId, char **returnGroupVec, + uint32_t *groupNum) +{ + LOGI("[Start]: GetAccessibleRelatedGroups! [AppId]: %s", appId); + if ((appId == NULL) || (peerDeviceId == NULL) || (returnGroupVec == NULL) || (groupNum == NULL)) { + LOGE("The input parameter contains NULL value!"); + return HC_ERR_INVALID_PARAMS; + } + if (!IsGroupManagerSupported()) { + LOGE("Group manager is not supported!"); + return HC_ERR_NOT_SUPPORT; + } + GroupManager *instance = GetGroupManagerInstance(); + if (instance == NULL) { + LOGE("Failed to get groupManager instance!"); + return HC_ERR_NULL_PTR; + } + return instance->getAccessibleRelatedGroups(appId, peerDeviceId, returnGroupVec, groupNum); +} + +static int32_t GetAccessibleDeviceInfoById(const char *appId, const char *deviceId, const char *groupId, + char **returnDeviceInfo) +{ + LOGI("[Start]: GetAccessibleDeviceInfoById! [AppId]: %s, [GroupId]: %s", appId, groupId); + if ((appId == NULL) || (deviceId == NULL) || (groupId == NULL) || (returnDeviceInfo == NULL)) { + LOGE("The input parameter contains NULL value!"); + return HC_ERR_INVALID_PARAMS; + } + if (!IsGroupManagerSupported()) { + LOGE("Group manager is not supported!"); + return HC_ERR_NOT_SUPPORT; + } + GroupManager *instance = GetGroupManagerInstance(); + if (instance == NULL) { + LOGE("Failed to get groupManager instance!"); + return HC_ERR_NULL_PTR; + } + return instance->getAccessibleDeviceInfoById(appId, deviceId, groupId, returnDeviceInfo); +} + +static int32_t GetAccessibleTrustedDevices(const char *appId, const char *groupId, char **returnDevInfoVec, + uint32_t *deviceNum) +{ + LOGI("[Start]: GetAccessibleTrustedDevices! [AppId]: %s, [GroupId]: %s", appId, groupId); + if ((appId == NULL) || (groupId == NULL) || (returnDevInfoVec == NULL) || (deviceNum == NULL)) { + LOGE("The input parameter contains NULL value!"); + return HC_ERR_INVALID_PARAMS; + } + if (!IsGroupManagerSupported()) { + LOGE("Group manager is not supported!"); + return HC_ERR_NOT_SUPPORT; + } + GroupManager *instance = GetGroupManagerInstance(); + if (instance == NULL) { + LOGE("Failed to get groupManager instance!"); + return HC_ERR_NULL_PTR; + } + return instance->getAccessibleTrustedDevices(appId, groupId, returnDevInfoVec, deviceNum); +} + +static bool IsDeviceInAccessibleGroup(const char *appId, const char *groupId, const char *deviceId) +{ + LOGI("[Start]: IsDeviceInAccessibleGroup! [AppId]: %s, [GroupId]: %s", appId, groupId); + if ((appId == NULL) || (groupId == NULL) || (deviceId == NULL)) { + LOGE("The input parameter contains NULL value!"); + return false; + } + if (!IsGroupManagerSupported()) { + LOGE("Group manager is not supported!"); + return false; + } + GroupManager *instance = GetGroupManagerInstance(); + if (instance == NULL) { + LOGE("Failed to get groupManager instance!"); + return false; + } + return instance->isDeviceInAccessibleGroup(appId, groupId, deviceId); +} + +static void DestroyInfo(char **returnInfo) +{ + LOGI("[Start]: DestroyInfo!"); + if (returnInfo == NULL) { + LOGI("The input returnInfo is NULL!"); + return; + } + if (!IsGroupManagerSupported()) { + LOGE("Group manager is not supported!"); + return; + } + GroupManager *instance = GetGroupManagerInstance(); + if (instance == NULL) { + LOGE("Failed to get groupManager instance!"); + return; + } + instance->destroyInfo(returnInfo); +} + +static int32_t AllocGmAndGa() +{ + if (g_groupManagerInstance == NULL) { + g_groupManagerInstance = (DeviceGroupManager *)HcMalloc(sizeof(DeviceGroupManager), 0); + if (g_groupManagerInstance == NULL) { + LOGE("Failed to allocate groupManagerInstance memory!"); + return HC_ERR_ALLOC_MEMORY; + } + } + if (g_groupAuthManager == NULL) { + g_groupAuthManager = (GroupAuthManager *)HcMalloc(sizeof(GroupAuthManager), 0); + if (g_groupAuthManager == NULL) { + LOGE("Alloc memory failed!"); + HcFree(g_groupManagerInstance); + g_groupManagerInstance = NULL; + return HC_ERR_ALLOC_MEMORY; + } + } + return HC_SUCCESS; +} + +static int32_t InitAlgorithm() +{ + const AlgLoader *loader = GetLoaderInstance(); + if (loader == NULL) { + LOGE("Get loader failed."); + return HC_ERROR; + } + int32_t res = loader->initAlg(); + if (res != HC_SUCCESS) { + LOGE("Failed to init algorithm!"); + return res; + } + return res; +} + +static int InitAndStartThread() +{ + if (g_taskThread != NULL) { + LOGD("Task thread is not null"); + } + g_taskThread = HcMalloc(sizeof(HcTaskThread), 0); + if (g_taskThread == NULL) { + return HC_ERR_ALLOC_MEMORY; + } + int32_t res = InitHcTaskThread(g_taskThread, STACK_SIZE, "HichainThread"); + if (res != HC_SUCCESS) { + LOGE("Init task thread failed, res:%d", res); + HcFree(g_taskThread); + g_taskThread = NULL; + return HC_ERROR; + } + res = g_taskThread->startThread(g_taskThread); + if (res != HC_SUCCESS) { + DestroyHcTaskThread(g_taskThread); + HcFree(g_taskThread); + g_taskThread = NULL; + LOGE("Start thread failed, res:%d", res); + return HC_ERROR; + } + return res; +} + +static void DestroyGmAndGa() +{ + if (g_groupAuthManager != NULL) { + HcFree(g_groupAuthManager); + g_groupAuthManager = NULL; + } + if (g_groupManagerInstance != NULL) { + HcFree(g_groupManagerInstance); + g_groupManagerInstance = NULL; + } +} + +static void StopAndDestroyThread() +{ + if (g_taskThread != NULL) { + g_taskThread->stopAndClear(g_taskThread); + DestroyHcTaskThread(g_taskThread); + HcFree(g_taskThread); + g_taskThread = NULL; + } +} + +DEVICE_AUTH_API_PUBLIC int InitDeviceAuthService() +{ + LOGI("[Service]: Start to init device auth service!"); + if (CheckInit() == FINISH_INIT) { + LOGI("[End]: [Service]: Init device auth service successfully!"); + return HC_SUCCESS; + } + int32_t res = InitAlgorithm(); + if (res != HC_SUCCESS) { + LOGE("[End]: [Service]: Failed to init algorithm module!"); + goto err; + } + res = AllocGmAndGa(); + if (res != HC_SUCCESS) { + LOGE("[End]: [Service]: Failed to init group manage and group auth instances!"); + goto err; + } + res = InitModules(); + if (res != HC_SUCCESS) { + LOGE("[End]: [Service]: Failed to init all authenticator modules!"); + goto free_gm_ga; + } + res = InitGroupManager(); + if (res != HC_SUCCESS) { + goto free_module; + } + res = InitChannelManager(OnChannelOpenedCallback, + OnChannelClosedCallback, OnMsgReceivedCallback, OnServiceDiedCallback); + if (res != HC_SUCCESS) { + LOGE("[End]: [Service]: Failed to init channel manage module!"); + goto free_group_manager; + } + InitSessionManager(); + res = InitAndStartThread(); + if (res != HC_SUCCESS) { + LOGE("[End]: [Service]: Failed to init worker thread!"); + goto free_all; + } + SetInitStatus(); + LOGI("[End]: [Service]: Init device auth service successfully!"); + return res; +free_all: + DestroyChannelManager(); + DestroySessionManager(); +free_group_manager: + DestroyGroupManager(); +free_module: + DestroyModules(); +free_gm_ga: + DestroyGmAndGa(); +err: + SetDeInitStatus(); + return res; +} + +DEVICE_AUTH_API_PUBLIC void DestroyDeviceAuthService() +{ + LOGI("[Service]: Start to destroy device auth service!"); + if (CheckDestroy() == FINISH_DESTROY) { + LOGI("[End]: [Service]: The service has not been initialized, so it does not need to be destroyed!"); + return; + } + DestroyChannelManager(); + DestroySessionManager(); + DestroyGroupManager(); + DestroyModules(); + DestroyGmAndGa(); + StopAndDestroyThread(); + SetDeInitStatus(); + LOGI("[End]: [Service]: Destroy device auth service successfully!"); +} + +DEVICE_AUTH_API_PUBLIC const DeviceGroupManager *GetGmInstance() +{ + if (g_groupManagerInstance == NULL) { + LOGE("Service not init."); + return NULL; + } + + g_groupManagerInstance->regCallback = RegGroupManagerCallback; + g_groupManagerInstance->unRegCallback = UnRegGroupManagerCallback; + g_groupManagerInstance->createGroup = RequestCreateGroup; + g_groupManagerInstance->deleteGroup = RequestDeleteGroup; + g_groupManagerInstance->addMemberToGroup = RequestAddMemberToGroup; + g_groupManagerInstance->deleteMemberFromGroup = RequestDeleteMemberFromGroup; + g_groupManagerInstance->processData = RequestProcessBindData; + g_groupManagerInstance->confirmRequest = ConfirmRequest; + g_groupManagerInstance->bindPeer = RequestBindPeer; + g_groupManagerInstance->unbindPeer = RequestUnbindPeer; + g_groupManagerInstance->processLiteData = RequestProcessLiteData; + g_groupManagerInstance->authKeyAgree = RequestAuthKeyAgree; + g_groupManagerInstance->processKeyAgreeData = RequestProcessKeyAgreeData; + g_groupManagerInstance->processCredential = ProcessCredential; + g_groupManagerInstance->getRegisterInfo = GetRegisterInfo; + g_groupManagerInstance->getLocalConnectInfo = GetLocalConnectInfo; + g_groupManagerInstance->addGroupManager = AddGroupManagerIfAccessible; + g_groupManagerInstance->deleteGroupManager = DeleteGroupManagerIfAccessible; + g_groupManagerInstance->getGroupManagers = GetGroupManagersIfAccessible; + g_groupManagerInstance->addGroupFriend = AddGroupFriendIfAccessible; + g_groupManagerInstance->deleteGroupFriend = DeleteGroupFriendIfAccessible; + g_groupManagerInstance->getGroupFriends = GetGroupFriendsIfAccessible; + g_groupManagerInstance->regDataChangeListener = RegListener; + g_groupManagerInstance->unRegDataChangeListener = UnRegListener; + g_groupManagerInstance->getGroupInfoById = GetAccessibleGroupInfoById; + g_groupManagerInstance->getGroupInfo = GetAccessibleGroupInfo; + g_groupManagerInstance->getJoinedGroups = GetAccessibleJoinedGroups; + g_groupManagerInstance->getRelatedGroups = GetAccessibleRelatedGroups; + g_groupManagerInstance->getDeviceInfoById = GetAccessibleDeviceInfoById; + g_groupManagerInstance->getTrustedDevices = GetAccessibleTrustedDevices; + g_groupManagerInstance->isDeviceInGroup = IsDeviceInAccessibleGroup; + g_groupManagerInstance->destroyInfo = DestroyInfo; + return g_groupManagerInstance; +} + +DEVICE_AUTH_API_PUBLIC const GroupAuthManager *GetGaInstance() +{ + if (g_groupAuthManager == NULL) { + LOGE("Service not init."); + return NULL; + } + + g_groupAuthManager->processData = ProcessData; + g_groupAuthManager->queryTrustedDeviceNum = QueryTrustedDeviceNum; + g_groupAuthManager->isTrustedDevice = IsTrustedDevice; + g_groupAuthManager->getAuthState = GetAuthState; + g_groupAuthManager->authDevice = AuthDevice; + g_groupAuthManager->informDeviceDisconnection = InformDeviceDisconnection; + return g_groupAuthManager; +} diff --git a/services/deviceauth.gni b/services/deviceauth.gni new file mode 100644 index 0000000..91c5284 --- /dev/null +++ b/services/deviceauth.gni @@ -0,0 +1,149 @@ +# Copyright (C) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//base/security/deviceauth/deviceauth_env.gni") + +inc_path = [ + "${innerkits_path}", + "${frameworks_path}/inc", + "${services_path}/common/inc", + "${services_path}/common/inc/broadcast_manager", + "${services_path}/common/inc/callback_manager", + "${services_path}/common/inc/channel_manager", + "${services_path}/common/inc/channel_manager/soft_bus_channel", + "${services_path}/common/inc/data_base", + "${services_path}/group_auth/inc", + "${services_path}/group_auth/inc/account_unrelated_group_auth", + "${services_path}/group_auth/inc/account_related_group_auth", + "${services_path}/group_manager/inc", + "${services_path}/group_manager/inc/account_unrelated", + "${services_path}/group_manager/inc/account_related", + "${services_path}/module/inc", + "${services_path}/module/inc/tcis_module", + "${services_path}/module/inc/tcis_module/tcis_auth_token_manager", + "${services_path}/module/inc/das_module", + "${services_path}/module/inc/das_module/iso_task", + "${services_path}/module/inc/das_module/iso_task/iso_protocol_task", + "${services_path}/module/inc/das_module/iso_task/lite_exchange_task", + "${services_path}/module/inc/das_module/pake_task", + "${services_path}/module/inc/das_module/pake_task/new_pake_task", + "${services_path}/module/inc/das_module/pake_task/pake_task", + "${services_path}/module/inc/protocol", + "${services_path}/module/inc/protocol/pake_protocol", + "${services_path}/module/inc/protocol/pake_protocol/pake_protocol", + "${services_path}/module/inc/protocol/pake_protocol/new_pake_protocol", + "${services_path}/module/inc/protocol/iso_protocol", + "${services_path}/session/inc", + "${services_path}/session/inc/auth_session", + "${services_path}/session/inc/auth_session_lite", + "${services_path}/session/inc/bind_session", + "${services_path}/session/inc/bind_session_lite", + "${services_path}/session/inc/key_agree_session", +] + +deviceauth_files = [ + "${services_path}/device_auth.c", + "${services_path}/common/src/broadcast_manager/broadcast_manager.c", + "${services_path}/common/src/callback_manager/callback_manager.c", + "${services_path}/common/src/channel_manager/channel_manager.c", + "${services_path}/common/src/channel_manager/soft_bus_channel_mock/soft_bus_channel_mock.c", + "${services_path}/common/src/data_base/database_manager.c", + + "${services_path}/group_auth/src/group_auth_manager/group_auth_manager.c", + "${services_path}/group_auth/src/group_auth_manager/account_unrelated_group_auth/account_unrelated_group_auth.c", + "${services_path}/group_auth/src/group_auth_manager/account_related_group_auth_mock/account_related_group_auth_mock.c", + + "${services_path}/group_manager/src/group_manager/group_common.c", + "${services_path}/group_manager/src/group_manager/group_manager.c", + "${services_path}/group_manager/src/group_manager/account_unrelated/peer_to_peer_group/peer_to_peer_group.c", + "${services_path}/group_manager/src/group_manager/account_unrelated/account_unrelated_group_manager/account_unrelated_group_manager.c", + "${services_path}/group_manager/src/group_manager/account_related/across_account_group_mock/across_account_group_mock.c", + "${services_path}/group_manager/src/group_manager/account_related/identical_account_group_mock/identical_account_group_mock.c", + "${services_path}/group_manager/src/group_manager/account_related/account_related_group_manager_mock/account_related_group_manager_mock.c", + + "${services_path}/module/src/dev_auth_module_manager.c", + "${services_path}/module/src/module_common.c", + "${services_path}/module/src/version_util.c", + "${services_path}/module/src/das_module/das_common.c", + "${services_path}/module/src/das_module/das_module.c", + "${services_path}/module/src/das_module/task_main.c", + "${services_path}/module/src/das_module/das_version_util.c", + "${services_path}/module/src/das_module/iso_task/iso_client_task.c", + "${services_path}/module/src/das_module/iso_task/iso_server_task.c", + "${services_path}/module/src/das_module/iso_task/iso_task_common.c", + "${services_path}/module/src/das_module/iso_task/iso_task_main.c", + "${services_path}/module/src/das_module/iso_task/iso_protocol_task/iso_client_protocol_task.c", + "${services_path}/module/src/das_module/iso_task/iso_protocol_task/iso_server_protocol_task.c", + "${services_path}/module/src/das_module/iso_task/lite_exchange_task/iso_client_bind_exchange_task.c", + "${services_path}/module/src/das_module/iso_task/lite_exchange_task/iso_client_unbind_exchange_task.c", + "${services_path}/module/src/das_module/iso_task/lite_exchange_task/iso_server_bind_exchange_task.c", + "${services_path}/module/src/das_module/iso_task/lite_exchange_task/iso_server_unbind_exchange_task.c", + "${services_path}/module/src/das_module/pake_task/pake_task_common.c", + "${services_path}/module/src/das_module/pake_task/pake_message_util.c", + "${services_path}/module/src/das_module/pake_task/new_pake_task_mock/new_pake_task_main_mock.c", + "${services_path}/module/src/das_module/pake_task/pake_task/pake_task_main.c", + "${services_path}/module/src/das_module/pake_task/pake_task/pake_client_task.c", + "${services_path}/module/src/das_module/pake_task/pake_task/pake_server_task.c", + "${services_path}/module/src/das_module/pake_task/pake_task/pake_protocol_task/pake_client_protocol_task.c", + "${services_path}/module/src/das_module/pake_task/pake_task/pake_protocol_task/pake_server_protocol_task.c", + "${services_path}/module/src/das_module/pake_task/pake_task/pake_protocol_task/pake_protocol_task_common.c", + "${services_path}/module/src/das_module/pake_task/standard_exchange_task/common_standard_bind_exchange.c", + "${services_path}/module/src/das_module/pake_task/standard_exchange_task/common_standard_unbind_exchange.c", + "${services_path}/module/src/das_module/pake_task/standard_exchange_task/standard_client_bind_exchange_task.c", + "${services_path}/module/src/das_module/pake_task/standard_exchange_task/standard_client_unbind_exchange_task.c", + "${services_path}/module/src/das_module/pake_task/standard_exchange_task/standard_server_bind_exchange_task.c", + "${services_path}/module/src/das_module/pake_task/standard_exchange_task/standard_server_unbind_exchange_task.c", + "${services_path}/module/src/das_module/pake_task/standard_exchange_task/das_asy_token_manager.c", + "${services_path}/module/src/das_module/pake_task/standard_exchange_task/standard_exchange_message_util.c", + "${services_path}/module/src/tcis_module_mock/tcis_module_mock.c", + "${services_path}/module/src/protocol/protocol_common.c", + "${services_path}/module/src/protocol/pake_protocol/pake_protocol_common.c", + "${services_path}/module/src/protocol/pake_protocol/pake_protocol_ec/pake_protocol_ec.c", + "${services_path}/module/src/protocol/pake_protocol/pake_protocol_dl/pake_protocol_dl.c", + "${services_path}/module/src/protocol/new_pake_protocol/new_pake_protocol_ec_mock/new_pake_protocol_ec_mock.c", + "${services_path}/module/src/protocol/new_pake_protocol/new_pake_protocol_dl_mock/new_pake_protocol_dl_mock.c", + "${services_path}/module/src/protocol/iso_protocol/iso_protocol_common.c", + + "${services_path}/session/src/auth_session/auth_session_client.c", + "${services_path}/session/src/auth_session/auth_session_common.c", + "${services_path}/session/src/auth_session/auth_session_server.c", + "${services_path}/session/src/auth_session/auth_session_util.c", + "${services_path}/session/src/auth_session_lite/auth_session_client_lite.c", + "${services_path}/session/src/auth_session_lite/auth_session_server_lite.c", + "${services_path}/session/src/auth_session_lite/auth_session_common_lite.c", + "${services_path}/session/src/bind_session/bind_session_client.c", + "${services_path}/session/src/bind_session/bind_session_common.c", + "${services_path}/session/src/bind_session/bind_session_server.c", + "${services_path}/session/src/bind_session_lite/bind_session_client_lite.c", + "${services_path}/session/src/bind_session_lite/bind_session_common_lite.c", + "${services_path}/session/src/bind_session_lite/bind_session_server_lite.c", + "${services_path}/session/src/key_agree_session_mock/key_agree_session_client_mock.c", + "${services_path}/session/src/key_agree_session_mock/key_agree_session_server_mock.c", + "${services_path}/session/src/auth_session_common_util.c", + "${services_path}/session/src/session_common.c", + "${services_path}/session/src/session_manager.c", +] + +build_flags = [] + +if (target_os == "linux") { + build_flags += [ "-D_LINUX" ] +} + +deviceauth_ipc_files = [ + "${frameworks_path}/src/ipc_adapt.cpp", + "${frameworks_path}/src/ipc_dev_auth_proxy.cpp", + "${frameworks_path}/src/ipc_dev_auth_stub.cpp", + "${frameworks_path}/src/ipc_callback_proxy.cpp", + "${frameworks_path}/src/ipc_callback_stub.cpp", +] diff --git a/services/group_auth/inc/account_related_group_auth/account_related_group_auth.h b/services/group_auth/inc/account_related_group_auth/account_related_group_auth.h new file mode 100644 index 0000000..e863daa --- /dev/null +++ b/services/group_auth/inc/account_related_group_auth/account_related_group_auth.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ACCOUNT_RELATED_GROUP_AUTH_H +#define ACCOUNT_RELATED_GROUP_AUTH_H + +#include +#include "base_group_auth.h" +#include "database_manager.h" + +#define DEFAULT_CREDENTIAL_TYPE 2 + +typedef void (*GetTcisCandidateGroupFunc)(const CJson *param, GroupQueryParams *queryParams, GroupInfoVec *vec); + +typedef struct { + BaseGroupAuth base; + GetTcisCandidateGroupFunc getTcisCandidateGroup; +} AccountRelatedGroupAuth; + +BaseGroupAuth *GetAccountRelatedGroupAuth(); + +#endif diff --git a/services/group_auth/inc/account_unrelated_group_auth/account_unrelated_group_auth.h b/services/group_auth/inc/account_unrelated_group_auth/account_unrelated_group_auth.h new file mode 100644 index 0000000..5ccc0c2 --- /dev/null +++ b/services/group_auth/inc/account_unrelated_group_auth/account_unrelated_group_auth.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ACCOUNT_UNRELATED_GROUP_AUTH_H +#define ACCOUNT_UNRELATED_GROUP_AUTH_H + +#include +#include "base_group_auth.h" + +typedef void (*OnDasErrorFunc)(int64_t requestId, const AuthSession *session, int errorCode); + +typedef struct { + BaseGroupAuth base; + OnDasErrorFunc onDasError; +} NonAccountGroupAuth; + +BaseGroupAuth *GetNonAccountGroupAuth(); + +#endif diff --git a/services/group_auth/inc/base_group_auth.h b/services/group_auth/inc/base_group_auth.h new file mode 100644 index 0000000..14bff8d --- /dev/null +++ b/services/group_auth/inc/base_group_auth.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BASE_GROUP_AUTH_H +#define BASE_GROUP_AUTH_H + +#include +#include "auth_session_common_defines.h" +#include "json_utils.h" +#include "database_manager.h" +#include "device_auth.h" + +typedef struct { + void (*onFinish)(int64_t requestId, const CJson *authParam, const CJson *out, const DeviceAuthCallback *callback); + void (*onError)(int64_t requestId, const AuthSession *session, int errorCode); + int32_t (*fillDeviceAuthInfo)(const GroupInfo *entry, const DeviceInfo *localAuthInfo, CJson *paramsData); + int32_t (*getAuthParamForServer)(CJson *dataFromClient, ParamsVec *authParamsVec); + int32_t (*getReqParams)(const CJson *receiveData, CJson *reqParam); + int32_t (*combineServerConfirmParams)(const CJson *confirmationJson, CJson *dataFromClient); + int32_t authType; +} BaseGroupAuth; + +#endif diff --git a/services/group_auth/inc/group_auth_common_defines.h b/services/group_auth/inc/group_auth_common_defines.h new file mode 100644 index 0000000..97d276f --- /dev/null +++ b/services/group_auth/inc/group_auth_common_defines.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef GROUP_AUTH_COMMON_DEFINES_H +#define GROUP_AUTH_COMMON_DEFINES_H + +#include +#include "device_auth.h" +#include "hc_task_thread.h" +#include "json_utils.h" + +#define MAX_DATA_BUFFER_SIZE 4096 +#define MAX_UDID_LEN 64 + +typedef struct { + HcTaskBase base; + int64_t authReqId; + CJson *authParams; + const DeviceAuthCallback *callback; +} AuthDeviceTask; + +#endif diff --git a/services/group_auth/inc/group_auth_manager.h b/services/group_auth/inc/group_auth_manager.h new file mode 100644 index 0000000..914d1f6 --- /dev/null +++ b/services/group_auth/inc/group_auth_manager.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef GROUP_AUTH_MANAGER_H +#define GROUP_AUTH_MANAGER_H + +#include "group_auth_common_defines.h" + +int32_t GetAuthState(int64_t authReqId, const char *groupId, const char *peerUdid, uint8_t *out, uint32_t *outLen); +void InformDeviceDisconnection(const char *udid); +bool IsTrustedDevice(const char *udid); +int32_t QueryTrustedDeviceNum(void); +void DoAuthDevice(HcTaskBase *task); +void DoProcessData(HcTaskBase *task); + +#endif diff --git a/services/group_auth/src/group_auth_manager/account_related_group_auth_mock/account_related_group_auth_mock.c b/services/group_auth/src/group_auth_manager/account_related_group_auth_mock/account_related_group_auth_mock.c new file mode 100644 index 0000000..cdea033 --- /dev/null +++ b/services/group_auth/src/group_auth_manager/account_related_group_auth_mock/account_related_group_auth_mock.c @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "account_related_group_auth.h" + +BaseGroupAuth *GetAccountRelatedGroupAuth() +{ + return NULL; +} diff --git a/services/group_auth/src/group_auth_manager/account_unrelated_group_auth/account_unrelated_group_auth.c b/services/group_auth/src/group_auth_manager/account_unrelated_group_auth/account_unrelated_group_auth.c new file mode 100644 index 0000000..35203aa --- /dev/null +++ b/services/group_auth/src/group_auth_manager/account_unrelated_group_auth/account_unrelated_group_auth.c @@ -0,0 +1,447 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "account_unrelated_group_auth.h" +#include "auth_session_common.h" +#include "auth_session_common_util.h" +#include "common_defs.h" +#include "device_auth_defines.h" +#include "hc_log.h" +#include "hc_types.h" +#include "json_utils.h" + +static void OnDasFinish(int64_t requestId, const CJson *authParam, const CJson *out, + const DeviceAuthCallback *callback); +static int32_t FillNonAccountAuthInfo(const GroupInfo *entry, const DeviceInfo *localAuthInfo, CJson *paramsData); +static void OnDasError(int64_t requestId, const AuthSession *session, int errorCode); +static int32_t GetDasAuthParamForServer(CJson *dataFromClient, ParamsVec *authParamsVec); +static int32_t GetDasReqParams(const CJson *receiveData, CJson *reqParam); +static int32_t CombineDasServerConfirmParams(const CJson *confirmationJson, CJson *dataFromClient); + +static NonAccountGroupAuth g_nonAccountGroupAuth = { + .base.onFinish = OnDasFinish, + .base.onError = OnDasError, + .base.fillDeviceAuthInfo = FillNonAccountAuthInfo, + .base.getAuthParamForServer = GetDasAuthParamForServer, + .base.getReqParams = GetDasReqParams, + .base.combineServerConfirmParams = CombineDasServerConfirmParams, + .base.authType = ACCOUNT_UNRELATED_GROUP_AUTH_TYPE, +}; + +static int32_t AddGroupIdToSelfData(const CJson *authParam, CJson *returnToSelf) +{ + const char *groupId = GetStringFromJson(authParam, FIELD_SERVICE_TYPE); + if (groupId == NULL) { + LOGE("Failed to get groupId from authParam!"); + return HC_ERR_JSON_GET; + } + if (AddStringToJson(returnToSelf, FIELD_GROUP_ID, groupId) != HC_SUCCESS) { + LOGE("Failed to add group id!"); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} + +static int32_t AddPeerUdidToSelfData(const CJson *authParam, CJson *returnToSelf) +{ + const char *peerUdid = GetStringFromJson(authParam, FIELD_PEER_CONN_DEVICE_ID); + if (peerUdid == NULL) { + LOGE("Failed to get peerUdid from authParam!"); + return HC_ERR_JSON_GET; + } + if (AddStringToJson(returnToSelf, FIELD_PEER_CONN_DEVICE_ID, peerUdid) != HC_SUCCESS) { + LOGE("Failed to add peer udid!"); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} + +static int32_t AddSelfTypeToSelfData(const CJson *authParam, CJson *returnToSelf) +{ + int32_t userType = 0; + if (GetIntFromJson(authParam, FIELD_SELF_TYPE, &userType) != HC_SUCCESS) { + LOGE("Failed to get self userType from authParam!"); + return HC_ERR_JSON_GET; + } + if (AddIntToJson(returnToSelf, FIELD_USER_TYPE, userType) != HC_SUCCESS) { + LOGE("Failed to add peer self userType for onFinish!"); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} + +static int32_t AddPeerTypeToSelfData(const CJson *authParam, CJson *returnToSelf) +{ + int32_t peerUserType = 0; + if (GetIntFromJson(authParam, FIELD_PEER_USER_TYPE, &peerUserType) != HC_SUCCESS) { + LOGE("Failed to get peerUserType from authParam!"); + return HC_ERR_JSON_GET; + } + if (AddIntToJson(returnToSelf, FIELD_PEER_USER_TYPE, peerUserType) != HC_SUCCESS) { + LOGE("Failed to add peer peerUserType for onFinish!"); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} + +static int32_t AddSessionKeyToSelfData(const CJson *authParam, const CJson *sendToSelf, CJson *returnToSelf) +{ + int32_t keyLen = DEFAULT_RETURN_KEY_LENGTH; + (void)GetIntFromJson(authParam, FIELD_KEY_LENGTH, &keyLen); + uint8_t *sessionKey = (uint8_t *)HcMalloc(keyLen, 0); + if (sessionKey == NULL) { + LOGE("Failed to allocate memory for sessionKey!"); + return HC_ERR_ALLOC_MEMORY; + } + int32_t res = HC_SUCCESS; + do { + if (GetByteFromJson(sendToSelf, FIELD_SESSION_KEY, sessionKey, keyLen) != HC_SUCCESS) { + LOGE("Failed to get sessionKey!"); + res = HC_ERR_JSON_GET; + break; + } + if (AddByteToJson(returnToSelf, FIELD_SESSION_KEY, (const uint8_t *)sessionKey, keyLen) != HC_SUCCESS) { + LOGE("Failed to add sessionKey for onFinish!"); + res = HC_ERR_JSON_FAIL; + break; + } + } while (0); + (void)memset_s(sessionKey, keyLen, 0, keyLen); + HcFree(sessionKey); + sessionKey = NULL; + return res; +} + +static int32_t PrepareDasReturnToSelfData(const CJson *authParam, const CJson *sendToSelf, CJson *returnToSelf) +{ + int32_t res = AddGroupIdToSelfData(authParam, returnToSelf); + if (res != HC_SUCCESS) { + return res; + } + res = AddPeerUdidToSelfData(authParam, returnToSelf); + if (res != HC_SUCCESS) { + return res; + } + res = AddSelfTypeToSelfData(authParam, returnToSelf); + if (res != HC_SUCCESS) { + return res; + } + res = AddPeerTypeToSelfData(authParam, returnToSelf); + if (res != HC_SUCCESS) { + return res; + } + res = AddSessionKeyToSelfData(authParam, sendToSelf, returnToSelf); + if (res != HC_SUCCESS) { + return res; + } + return HC_SUCCESS; +} + +static int32_t DasOnFinishToPeer(int64_t requestId, const CJson *out, const DeviceAuthCallback *callback) +{ + int32_t res = HC_SUCCESS; + const CJson *sendToPeer = GetObjFromJson(out, FIELD_SEND_TO_PEER); + if (sendToPeer == NULL) { + LOGI("No need to transmit data to peer."); + return res; + } + char *sendToPeerStr = PackJsonToString(sendToPeer); + if (sendToPeerStr == NULL) { + LOGE("Failed to pack sendToPeerStr for onTransmit!"); + return HC_ERR_ALLOC_MEMORY; + } + if ((callback != NULL) && (callback->onTransmit != NULL)) { + if (!callback->onTransmit(requestId, (uint8_t *)sendToPeerStr, (uint32_t)strlen(sendToPeerStr) + 1)) { + LOGE("Failed to transmit data to peer!"); + res = HC_ERR_TRANSMIT_FAIL; + } + } + FreeJsonString(sendToPeerStr); + return res; +} + +static int32_t DasOnFinishToSelf(int64_t requestId, const CJson *authParam, const CJson *out, + const DeviceAuthCallback *callback) +{ + const CJson *sendToSelf = GetObjFromJson(out, FIELD_SEND_TO_SELF); + if (sendToSelf == NULL) { + LOGE("No data to send to self for onFinish."); + return HC_ERR_LOST_DATA; + } + CJson *returnToSelf = CreateJson(); + if (returnToSelf == NULL) { + LOGE("Create json failed!"); + return HC_ERR_ALLOC_MEMORY; + } + int32_t res = PrepareDasReturnToSelfData(authParam, sendToSelf, returnToSelf); + if (res != HC_SUCCESS) { + LOGE("Failed to add das returnToSelf data!"); + ClearSensitiveStringInJson(returnToSelf, FIELD_SESSION_KEY); + FreeJson(returnToSelf); + return res; + } + char *returnStr = PackJsonToString(returnToSelf); + ClearSensitiveStringInJson(returnToSelf, FIELD_SESSION_KEY); + FreeJson(returnToSelf); + if (returnStr == NULL) { + LOGE("Failed to pack returnToSelf for onFinish!"); + return HC_ERR_ALLOC_MEMORY; + } + if ((callback != NULL) && (callback->onFinish != NULL)) { + callback->onFinish(requestId, AUTH_FORM_ACCOUNT_UNRELATED, returnStr); + } + ClearAndFreeJsonString(returnStr); + return res; +} + +static int32_t AddNonAccountPkgName(const GroupInfo *entry, CJson *paramsData) +{ + int32_t res = HC_SUCCESS; + int32_t groupType = entry->type; + if (groupType == COMPATIBLE_GROUP) { + if (AddStringToJson(paramsData, FIELD_SERVICE_PKG_NAME, StringGet(&entry->ownerName)) + != HC_SUCCESS) { + LOGE("Failed to add ownerName to json!"); + res = HC_ERR_JSON_FAIL; + } + } else { + if (AddStringToJson(paramsData, FIELD_SERVICE_PKG_NAME, GROUP_MANAGER_PACKAGE_NAME) != HC_SUCCESS) { + LOGE("Failed to add group manager name to json!"); + res = HC_ERR_JSON_FAIL; + } + } + return res; +} + +static int32_t AddPeerUdidIfPossible(const char *peerUdid, const DeviceInfo *peerAuthInfo, CJson *paramsData) +{ + if (peerUdid != NULL) { + return HC_SUCCESS; + } + const char *peerUdidFromDb = StringGet(&peerAuthInfo->udid); + if (peerUdidFromDb == NULL) { + LOGE("Peer device's udid in db is null!"); + return HC_ERR_DB; + } + if (AddStringToJson(paramsData, FIELD_PEER_CONN_DEVICE_ID, peerUdidFromDb) != HC_SUCCESS) { + LOGE("Failed to add peer udid in db to paramsData!"); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} + +static int32_t AddNonAccountAuthInfo(const DeviceInfo *localAuthInfo, const DeviceInfo *peerAuthInfo, + CJson *paramsData) +{ + int32_t keyLen = DEFAULT_RETURN_KEY_LENGTH; + (void)GetIntFromJson(paramsData, FIELD_KEY_LENGTH, &keyLen); + if (AddIntToJson(paramsData, FIELD_KEY_LENGTH, keyLen) != HC_SUCCESS) { + LOGE("Failed to add keyLen for client auth!"); + return HC_ERR_JSON_FAIL; + } + if (AddStringToJson(paramsData, FIELD_SELF_AUTH_ID, StringGet(&localAuthInfo->authId)) + != HC_SUCCESS) { + LOGE("Failed to add self authId to paramsData!"); + return HC_ERR_JSON_FAIL; + } + if (AddIntToJson(paramsData, FIELD_SELF_TYPE, localAuthInfo->devType) != HC_SUCCESS) { + LOGE("Failed to add self devType to paramsData!"); + return HC_ERR_JSON_FAIL; + } + if (AddStringToJson(paramsData, FIELD_PEER_AUTH_ID, StringGet(&peerAuthInfo->authId)) + != HC_SUCCESS) { + LOGE("Failed to add peer authId to paramsData!"); + return HC_ERR_JSON_FAIL; + } + if (AddIntToJson(paramsData, FIELD_PEER_USER_TYPE, peerAuthInfo->devType) != HC_SUCCESS) { + LOGE("Failed to add peer devType to paramsData!"); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} + +static void OnDasError(int64_t requestId, const AuthSession *session, int errorCode) +{ + const DeviceAuthCallback *callback = session->base.callback; + ParamsVec list = session->paramsList; + CJson *authParam = list.get(&list, session->currentIndex); + if (authParam == NULL) { + LOGE("The json data in session is null!"); + return; + } + /* If there is alternative group, do not return error. */ + const char *altGroup = GetStringFromJson(authParam, FIELD_ALTERNATIVE); + if ((session->currentIndex < (list.size(&list) - 1)) || (altGroup != NULL)) { + return; + } + CJson *returnData = CreateJson(); + if (returnData == NULL) { + LOGE("Failed to create json for returnData!"); + return; + } + int32_t res = AddGroupIdToSelfData(authParam, returnData); + if (res != HC_SUCCESS) { + FreeJson(returnData); + return; + } + res = AddPeerUdidToSelfData(authParam, returnData); + if (res != HC_SUCCESS) { + FreeJson(returnData); + return; + } + char *returnStr = PackJsonToString(returnData); + FreeJson(returnData); + if (returnStr == NULL) { + LOGE("Failed to pack returnStr for onError!"); + return; + } + if ((callback != NULL) && (callback->onError != NULL)) { + callback->onError(requestId, AUTH_FORM_ACCOUNT_UNRELATED, errorCode, returnStr); + } + FreeJsonString(returnStr); +} + +static int32_t FillNonAccountAuthInfo(const GroupInfo *entry, const DeviceInfo *localAuthInfo, CJson *paramsData) +{ + int32_t res; + const char *groupId = StringGet(&entry->id); + DeviceInfo *peerAuthInfo = CreateDeviceInfoStruct(); + if (peerAuthInfo == NULL) { + LOGE("Failed to allocate devEntry memory for peerAuthInfo!"); + return HC_ERR_ALLOC_MEMORY; + } + const char *peerUdid = GetStringFromJson(paramsData, FIELD_PEER_CONN_DEVICE_ID); + const char *peeAuthId = GetStringFromJson(paramsData, FIELD_PEER_AUTH_ID); + if (peerUdid != NULL) { + res = GetDeviceInfoForDevAuth(peerUdid, groupId, peerAuthInfo); + } else if (peeAuthId != NULL) { + res = GetDeviceInfoByAuthId(peeAuthId, groupId, peerAuthInfo); + } else { + LOGE("Invalid input, both peer udid and peer authId are null!"); + res = HC_ERR_NULL_PTR; + } + do { + if (res != HC_SUCCESS) { + LOGE("Failed to get peer device info from database!"); + break; + } + res = AddNonAccountPkgName(entry, paramsData); + if (res != HC_SUCCESS) { + LOGE("Failed to add pkg name to paramsData!"); + break; + } + res = AddPeerUdidIfPossible(peerUdid, peerAuthInfo, paramsData); + if (res != HC_SUCCESS) { + LOGE("Failed to add peer udid!"); + break; + } + res = AddNonAccountAuthInfo(localAuthInfo, peerAuthInfo, paramsData); + if (res != HC_SUCCESS) { + LOGE("Failed to add device auth info for non-account group!"); + break; + } + } while (0); + DestroyDeviceInfoStruct(peerAuthInfo); + return res; +} + +static int32_t GetDasReqParams(const CJson *receiveData, CJson *reqParam) +{ + int32_t res = GetGeneralReqParams(receiveData, reqParam); + if (res != HC_SUCCESS) { + LOGE("Failed to get general request params!"); + return res; + } + bool receiveDeviceLevel = false; + (void)GetBoolFromJson(receiveData, FIELD_IS_DEVICE_LEVEL, &receiveDeviceLevel); + if (receiveDeviceLevel) { + const char *altGroup = GetStringFromJson(receiveData, FIELD_ALTERNATIVE); + if (altGroup != NULL && AddStringToJson(reqParam, FIELD_ALTERNATIVE, altGroup) != HC_SUCCESS) { + LOGE("Failed to add alternativeGroup to reqParam!"); + return HC_ERR_JSON_FAIL; + } + } + if (AddBoolToJson(reqParam, FIELD_IS_DEVICE_LEVEL, receiveDeviceLevel) != HC_SUCCESS) { + LOGE("Failed to add reqParam for onRequest!"); + return HC_ERR_JSON_FAIL; + } + return res; +} + +static int32_t CombineDasServerConfirmParams(const CJson *confirmationJson, CJson *dataFromClient) +{ + bool isClient = false; + if (AddBoolToJson(dataFromClient, FIELD_IS_CLIENT, isClient) != HC_SUCCESS) { + LOGE("Failed to combine server param for isClient!"); + return HC_ERR_JSON_FAIL; + } + const char *pkgName = GetStringFromJson(confirmationJson, FIELD_SERVICE_PKG_NAME); + if (pkgName != NULL) { + if (AddStringToJson(dataFromClient, FIELD_SERVICE_PKG_NAME, pkgName) != HC_SUCCESS) { + LOGE("Failed to combine server param for pkgName!"); + return HC_ERR_JSON_FAIL; + } + } + + const char *peerUdid = GetStringFromJson(confirmationJson, FIELD_PEER_CONN_DEVICE_ID); + if (peerUdid != NULL) { + if (AddStringToJson(dataFromClient, FIELD_PEER_CONN_DEVICE_ID, peerUdid) != HC_SUCCESS) { + LOGE("Failed to combine server param for peerUdid!"); + return HC_ERR_JSON_FAIL; + } + } + const char *peerAuthId = GetStringFromJson(confirmationJson, FIELD_PEER_AUTH_ID); + if (peerAuthId != NULL) { + if (AddStringToJson(dataFromClient, FIELD_PEER_AUTH_ID, peerAuthId) != HC_SUCCESS) { + LOGE("Failed to combine server param for peerAuthId!"); + return HC_ERR_JSON_FAIL; + } + } + return HC_SUCCESS; +} + +static int32_t GetDasAuthParamForServer(CJson *dataFromClient, ParamsVec *authParamsVec) +{ + LOGI("Begin get non-account auth params for server."); + int32_t res = GetAuthParamsList(dataFromClient, authParamsVec); + if (res != HC_SUCCESS) { + LOGE("Failed to get non-account auth params!"); + } + return res; +} + +static void OnDasFinish(int64_t requestId, const CJson *authParam, const CJson *out, + const DeviceAuthCallback *callback) +{ + LOGI("Begin call onFinish for non-account auth."); + if (DasOnFinishToPeer(requestId, out, callback) != HC_SUCCESS) { + LOGE("Failed to send data to peer when auth finished!"); + return; + } + if (ReturnSessionKey(requestId, authParam, out, callback) != HC_SUCCESS) { + LOGE("Failed to return session key when auth finished!"); + return; + } + if (DasOnFinishToSelf(requestId, authParam, out, callback) != HC_SUCCESS) { + LOGE("Failed to send data to self when auth finished!"); + return; + } + LOGI("Call onFinish for non-account auth successfully."); +} + +BaseGroupAuth *GetNonAccountGroupAuth() +{ + return (BaseGroupAuth *)&g_nonAccountGroupAuth; +} diff --git a/services/group_auth/src/group_auth_manager/account_unrelated_group_auth_mock/account_unrelated_group_auth_mock.c b/services/group_auth/src/group_auth_manager/account_unrelated_group_auth_mock/account_unrelated_group_auth_mock.c new file mode 100644 index 0000000..293e73a --- /dev/null +++ b/services/group_auth/src/group_auth_manager/account_unrelated_group_auth_mock/account_unrelated_group_auth_mock.c @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "account_unrelated_group_auth.h" + +BaseGroupAuth *GetNonAccountGroupAuth() +{ + return NULL; +} diff --git a/services/group_auth/src/group_auth_manager/group_auth_manager.c b/services/group_auth/src/group_auth_manager/group_auth_manager.c new file mode 100644 index 0000000..330eef3 --- /dev/null +++ b/services/group_auth/src/group_auth_manager/group_auth_manager.c @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "group_auth_manager.h" +#include "database_manager.h" +#include "device_auth_defines.h" +#include "hc_log.h" +#include "session_manager.h" + +int32_t GetAuthState(int64_t authReqId, const char *groupId, const char *peerUdid, uint8_t *out, uint32_t *outLen) +{ + (void)authReqId; + (void)groupId; + (void)peerUdid; + (void)out; + (void)outLen; + return HC_ERROR; +} + +void InformDeviceDisconnection(const char *udid) +{ + (void)udid; + return; +} + +bool IsTrustedDevice(const char *udid) +{ + if (udid == NULL) { + LOGE("InValid params in IsTrustedDevice"); + return false; + } + return IsTrustedDeviceExist(udid); +} + +int32_t QueryTrustedDeviceNum(void) +{ + return GetTrustedDevNumber(); +} + +void DoAuthDevice(HcTaskBase *task) +{ + if (task == NULL) { + LOGE("The input task is NULL, can't start auth device!"); + return; + } + AuthDeviceTask *realTask = (AuthDeviceTask *)task; + bool isClient = true; + if (GetBoolFromJson(realTask->authParams, FIELD_IS_CLIENT, &isClient)) { + LOGE("Failed to get role of client or server when start auth!"); + return; + } + int32_t result; + if (isClient) { + result = CreateSession(realTask->authReqId, TYPE_CLIENT_AUTH_SESSION, realTask->authParams, realTask->callback); + } else { + result = CreateSession(realTask->authReqId, TYPE_SERVER_AUTH_SESSION, realTask->authParams, realTask->callback); + } + if (result != HC_SUCCESS) { + LOGE("Failed to create session for authDevice!"); + } +} + +void DoProcessData(HcTaskBase *task) +{ + if (task == NULL) { + LOGE("The input task is NULL, can't process auth data!"); + return; + } + AuthDeviceTask *realTask = (AuthDeviceTask *)task; + if (IsRequestExist(realTask->authReqId)) { + int ret = ProcessSession(realTask->authReqId, AUTH_TYPE, realTask->authParams); + if (ret != HC_SUCCESS) { + DestroySession(realTask->authReqId); + } + return; + } + int32_t result = CreateSession(realTask->authReqId, TYPE_SERVER_AUTH_SESSION, realTask->authParams, + realTask->callback); + if (result != HC_SUCCESS) { + LOGE("Failed to create session for process auth data!"); + } +} diff --git a/services/group_auth/src/group_auth_manager_lite/group_auth_manager_lite.c b/services/group_auth/src/group_auth_manager_lite/group_auth_manager_lite.c new file mode 100644 index 0000000..af078f5 --- /dev/null +++ b/services/group_auth/src/group_auth_manager_lite/group_auth_manager_lite.c @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "group_auth_manager.h" +#include "common_defs.h" +#include "device_auth_defines.h" +#include "hc_log.h" +#include "session_manager.h" + +int32_t GetAuthState(int64_t authReqId, const char *groupId, const char *peerUdid, uint8_t *out, uint32_t *outLen) +{ + (void)authReqId; + (void)groupId; + (void)peerUdid; + (void)out; + (void)outLen; + LOGE("Lite group auth do not support func: %s!", __func__); + return HC_ERR_NOT_SUPPORT; +} + +void InformDeviceDisconnection(const char *udid) +{ + (void)udid; + LOGE("Lite group auth do not support func: %s!", __func__); + return; +} + +bool IsTrustedDevice(const char *udid) +{ + (void)udid; + LOGE("Lite group auth do not support func: %s!", __func__); + return false; +} + +int32_t QueryTrustedDeviceNum(void) +{ + LOGE("Lite group auth do not support func: %s!", __func__); + return HC_ERR_NOT_SUPPORT; +} + +void DoAuthDevice(HcTaskBase *task) +{ + if (task == NULL) { + LOGE("The input task is NULL, can't start lite-auth device!"); + return; + } + AuthDeviceTask *realTask = (AuthDeviceTask *)task; + int32_t result = CreateSession(realTask->authReqId, TYPE_CLIENT_AUTH_SESSION_LITE, + realTask->authParams, realTask->callback); + if (result != HC_SUCCESS) { + LOGE("Failed to create lite auth session for auth device!"); + if ((realTask->callback != NULL) && (realTask->callback->onError != NULL)) { + realTask->callback->onError(realTask->authReqId, AUTH_FORM_INVALID_TYPE, result, NULL); + } + } +} + +void DoProcessData(HcTaskBase *task) +{ + if (task == NULL) { + LOGE("The input task is NULL, can't process lite-auth data!"); + return; + } + AuthDeviceTask *realTask = (AuthDeviceTask *)task; + if (IsRequestExist(realTask->authReqId)) { + int ret = ProcessSession(realTask->authReqId, AUTH_TYPE, realTask->authParams); + if (ret != HC_SUCCESS) { + DestroySession(realTask->authReqId); + } + return; + } + int32_t result = CreateSession(realTask->authReqId, TYPE_SERVER_AUTH_SESSION_LITE, realTask->authParams, + realTask->callback); + if (result != HC_SUCCESS) { + LOGE("Failed to create lite auth session for process data!"); + if ((realTask->callback != NULL) && (realTask->callback->onError != NULL)) { + realTask->callback->onError(realTask->authReqId, AUTH_FORM_INVALID_TYPE, result, NULL); + } + } +} \ No newline at end of file diff --git a/services/group_manager/inc/account_related/account_related_group_common.h b/services/group_manager/inc/account_related/account_related_group_common.h new file mode 100644 index 0000000..9a9d4f6 --- /dev/null +++ b/services/group_manager/inc/account_related/account_related_group_common.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ACCOUNT_RELATED_GROUP_COMMON_H +#define ACCOUNT_RELATED_GROUP_COMMON_H + +#include "common_defs.h" +#include "database_manager.h" + +int32_t CheckUserId(const CJson *jsonParams); +int32_t AddUserIdToDevParams(const CJson *jsonParams, DeviceInfo *devParams); +int32_t AddUserIdToGroupParams(const CJson *jsonParams, GroupInfo *groupParams); + +#endif \ No newline at end of file diff --git a/services/group_manager/inc/account_related/account_related_group_manager.h b/services/group_manager/inc/account_related/account_related_group_manager.h new file mode 100644 index 0000000..f36547a --- /dev/null +++ b/services/group_manager/inc/account_related/account_related_group_manager.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ACCOUNT_RELATED_GROUP_MANAGER_H +#define ACCOUNT_RELATED_GROUP_MANAGER_H + +#include "json_utils.h" + +typedef struct { + int32_t (*syncCreateIdenticalAccountGroup)(const CJson *jsonParams, char **returnDataStr); + int32_t (*syncDeleteIdenticalAccountGroup)(const CJson *jsonParams); + int32_t (*generateAcrossAccountGroupId)(int64_t userId, int64_t sharedUserId, char **returnGroupId); + int32_t (*getRegisterInfo)(char **returnRegisterInfo); + int32_t (*processCredential)(int operationCode, const char *reqJsonStr, char **returnJsonStr); +} AccountRelatedGroupManager; + +AccountRelatedGroupManager *GetAccountRelatedGroupManager(); +bool IsAccountRelatedGroupManagerSupported(); +bool IsAccountRelatedGroupTypeSupported(int32_t groupType); + +#endif diff --git a/services/group_manager/inc/account_related/across_account_group.h b/services/group_manager/inc/account_related/across_account_group.h new file mode 100644 index 0000000..d0781a0 --- /dev/null +++ b/services/group_manager/inc/account_related/across_account_group.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ACROSS_ACCOUNT_GROUP_H +#define ACROSS_ACCOUNT_GROUP_H + +#include "base_group.h" + +typedef struct { + BaseGroup base; + int32_t (*syncGroup)(const char *appId, int64_t userId, const char *deviceId, const CJson *sharedUserIdList); + int32_t (*generateGroupId)(int64_t userId, int64_t sharedUserId, char **returnGroupId); +} AcrossAccountGroup; + +bool IsAcrossAccountGroupSupported(); +BaseGroup *GetAcrossAccountGroupInstance(); + +#endif diff --git a/services/group_manager/inc/account_related/identical_account_group.h b/services/group_manager/inc/account_related/identical_account_group.h new file mode 100644 index 0000000..370293b --- /dev/null +++ b/services/group_manager/inc/account_related/identical_account_group.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef IDENTICAL_ACCOUNT_GROUP_H +#define IDENTICAL_ACCOUNT_GROUP_H + +#include "base_group.h" + +typedef struct { + BaseGroup base; + int32_t (*syncCreateGroup)(const CJson *jsonParams, char **returnGroupId); + int32_t (*syncDeleteGroup)(const CJson *jsonParams); +} IdenticalAccountGroup; + +bool IsIdenticalAccountGroupSupported(); +BaseGroup *GetIdenticalAccountGroupInstance(); + +#endif diff --git a/services/group_manager/inc/account_unrelated/account_unrelated_group_manager.h b/services/group_manager/inc/account_unrelated/account_unrelated_group_manager.h new file mode 100644 index 0000000..686ad08 --- /dev/null +++ b/services/group_manager/inc/account_unrelated/account_unrelated_group_manager.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ACCOUNT_UNRELATED_GROUP_MANAGER_H +#define ACCOUNT_UNRELATED_GROUP_MANAGER_H + +#include "device_auth.h" +#include "json_utils.h" + +typedef struct { + void (*createPeerToPeerGroup)(int64_t requestId, CJson *jsonParams, const DeviceAuthCallback *callback); + void (*deletePeerToPeerGroup)(int64_t requestId, CJson *jsonParams, const DeviceAuthCallback *callback); + void (*addMemberToPeerToPeerGroup)(int64_t requestId, CJson *jsonParams, const DeviceAuthCallback *callback); + void (*deleteMemberFromPeerToPeerGroup)(int64_t requestId, CJson *jsonParams, const DeviceAuthCallback *callback); + void (*processBindData)(int64_t requestId, CJson *jsonParams, const DeviceAuthCallback *callback); + int32_t (*addGroupRole)(bool isManager, const char *appId, const char *groupId, const char *roleAppId); + int32_t (*deleteGroupRole)(bool isManager, const char *appId, const char *groupId, const char *roleAppId); + int32_t (*getGroupRole)(bool isManager, const char *appId, const char *groupId, char **returnJsonStr, + uint32_t *returnSize); +} AccountUnrelatedGroupManager; + +AccountUnrelatedGroupManager *GetAccountUnrelatedGroupManager(); +bool IsAccountUnrelatedGroupManagerSupported(); +bool IsAccountUnrelatedGroupTypeSupported(int32_t groupType); + +#endif diff --git a/services/group_manager/inc/account_unrelated/peer_to_peer_group.h b/services/group_manager/inc/account_unrelated/peer_to_peer_group.h new file mode 100644 index 0000000..8a81ca8 --- /dev/null +++ b/services/group_manager/inc/account_unrelated/peer_to_peer_group.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PEER_TO_PEER_GROUP_H +#define PEER_TO_PEER_GROUP_H + +#include "base_group.h" + +typedef struct { + BaseGroup base; + int32_t (*createGroup)(int64_t requestId, CJson *jsonParams, const DeviceAuthCallback *callback); + int32_t (*deleteGroup)(int64_t requestId, CJson *jsonParams, const DeviceAuthCallback *callback); + int32_t (*addMember)(int64_t requestId, CJson *jsonParams, const DeviceAuthCallback *callback); + int32_t (*deleteMember)(int64_t requestId, CJson *jsonParams, const DeviceAuthCallback *callback); + int32_t (*processData)(int64_t requestId, CJson *jsonParams, const DeviceAuthCallback *callback); + int32_t (*addGroupRole)(bool isManager, const char *appId, const char *groupId, const char *roleAppId); + int32_t (*deleteGroupRole)(bool isManager, const char *appId, const char *groupId, const char *roleAppId); + int32_t (*getGroupRole)(bool isManager, const char *appId, const char *groupId, char **returnJsonStr, + uint32_t *returnSize); +} PeerToPeerGroup; + +BaseGroup *GetPeerToPeerGroupInstance(); +bool IsPeerToPeerGroupSupported(); + +#endif diff --git a/services/group_manager/inc/base_group.h b/services/group_manager/inc/base_group.h new file mode 100644 index 0000000..dd74043 --- /dev/null +++ b/services/group_manager/inc/base_group.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BASE_GROUP_H +#define BASE_GROUP_H + +#include "json_utils.h" +#include "device_auth.h" + +typedef struct { + int type; +} BaseGroup; + +#endif diff --git a/services/group_manager/inc/group_common.h b/services/group_manager/inc/group_common.h new file mode 100755 index 0000000..18baee8 --- /dev/null +++ b/services/group_manager/inc/group_common.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef GROUP_COMMON_H +#define GROUP_COMMON_H + +#include "common_util.h" +#include "database.h" +#include "json_utils.h" + +bool IsUserTypeValid(int userType); +bool IsExpireTimeValid(int expireTime); +bool IsGroupVisibilityValid(int groupVisibility); + +int32_t ProcessKeyPair(int action, const CJson *jsonParams, const char *groupId); +int32_t DeletePeerKeyIfForceUnbind(const char *groupId, const char *peerAuthId, int32_t peerUserType); +int32_t GetHashMessage(const Uint8Buff *first, const Uint8Buff *second, uint8_t **hashMessage, uint32_t *messageSize); +int32_t GetHashResult(const uint8_t *info, uint32_t infoLen, char *hash, uint32_t hashLen); + +int32_t CheckGroupExist(const char *groupId); +int32_t CheckGroupNumLimit(int32_t groupType, const char *appId); +int32_t CheckDeviceNumLimit(const char *groupId, const char *peerUdid); +int32_t CheckUserTypeIfExist(const CJson *jsonParams); +int32_t CheckGroupVisibilityIfExist(const CJson *jsonParams); +int32_t CheckExpireTimeIfExist(const CJson *jsonParams); +int32_t CheckPermForGroup(int actionType, const char *callerPkgName, const char *groupId); + +int32_t AddGroupNameToParams(const char *groupName, GroupInfo *groupParams); +int32_t AddGroupIdToParams(const char *groupId, GroupInfo *groupParams); +int32_t AddGroupOwnerToParams(const char *owner, GroupInfo *groupParams); +int32_t AddGroupTypeToParams(int groupType, GroupInfo *groupParams); +int32_t AddGroupVisibilityOrDefault(GroupInfo *groupParams); +int32_t AddExpireTimeOrDefault(const CJson *jsonParams, GroupInfo *groupParams); +int32_t AddUdidToParams(DeviceInfo *devParams); +int32_t AddAuthIdToParamsOrDefault(const CJson *jsonParams, DeviceInfo *devParams); +int32_t AddUserTypeToParamsOrDefault(const CJson *jsonParams, DeviceInfo *devParams); +int32_t AddServiceTypeToParams(const char *groupId, DeviceInfo *devParams); +int32_t AddGroupIdToDevParams(const char *groupId, DeviceInfo *devParams); + +int32_t AddGroupToDatabaseByJson(int32_t (*generateGroupParams)(const CJson*, const char *, GroupInfo*), + const CJson *jsonParams, const char *groupId); +int32_t AddDeviceToDatabaseByJson(int32_t (*generateDevParams)(const CJson*, const char*, DeviceInfo*), + const CJson *jsonParams, const char *groupId); +int32_t DelGroupFromDatabase(const char *groupId); + +int32_t ConvertGroupIdToJsonStr(const char *groupId, char **returnJsonStr); +int32_t GenerateBindSuccessData(const char *peerAuthId, const char *groupId, char **returnDataStr); +int32_t GenerateUnbindSuccessData(const char *peerAuthId, const char *groupId, char **returnDataStr); + +int32_t GetGroupTypeFromDb(const char *groupId, int *returnGroupType); + +#endif diff --git a/services/group_manager/inc/group_manager.h b/services/group_manager/inc/group_manager.h new file mode 100644 index 0000000..798d456 --- /dev/null +++ b/services/group_manager/inc/group_manager.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef GROUP_MANAGER_H +#define GROUP_MANAGER_H + +#include "device_auth.h" +#include "json_utils.h" + +typedef struct { + /* callback operation interface for device group management */ + int32_t (*regGroupManagerCallback)(const char *appId, const DeviceAuthCallback *callback); + int32_t (*unRegGroupManagerCallback)(const char *appId); + const DeviceAuthCallback *(*getGmCallbackByAppId)(const char *appId); + /* Non-account groups operation interfaces */ + void (*createPeerToPeerGroup)(int64_t requestId, CJson *jsonParams, const DeviceAuthCallback *callback); + void (*deletePeerToPeerGroup)(int64_t requestId, CJson *jsonParams, const DeviceAuthCallback *callback); + void (*addMemberToPeerToPeerGroup)(int64_t requestId, CJson *jsonParams, const DeviceAuthCallback *callback); + void (*deleteMemberFromPeerToPeerGroup)(int64_t requestId, CJson *jsonParams, const DeviceAuthCallback *callback); + void (*processBindData)(int64_t requestId, CJson *jsonParams, const DeviceAuthCallback *callback); + int32_t (*addGroupRole)(bool isManager, const char *appId, const char *groupId, const char *roleAppId); + int32_t (*deleteGroupRole)(bool isManager, const char *appId, const char *groupId, const char *roleAppId); + int32_t (*getGroupRole)(bool isManager, const char *appId, const char *groupId, char **returnJsonStr, + uint32_t *returnSize); + /* listener related operation interfaces */ + int32_t (*regListener)(const char *appId, const DataChangeListener *listener); + int32_t (*unRegListener)(const char *appId); + /* Account groups operation interfaces */ + int32_t (*syncCreateIdenticalAccountGroup)(const CJson *jsonParams, char **returnDataStr); + int32_t (*syncDeleteIdenticalAccountGroup)(const CJson *jsonParams); + int32_t (*getRegisterInfo)(char **returnRegisterInfo); + int32_t (*processCredential)(int operationCode, const char *reqJsonStr, char **returnJsonStr); + /* external query interface */ + int32_t (*getAccessibleGroupInfoById)(const char *appId, const char *groupId, char **returnGroupInfo); + int32_t (*getAccessibleGroupInfo)(const char *appId, const char *queryParams, char **returnGroupVec, + uint32_t *groupNum); + int32_t (*getAccessibleJoinedGroups)(const char *appId, int groupType, char **returnGroupVec, uint32_t *groupNum); + int32_t (*getAccessibleRelatedGroups)(const char *appId, const char *peerDeviceId, + char **returnGroupVec, uint32_t *groupNum); + int32_t (*getAccessibleDeviceInfoById)(const char *appId, const char *deviceId, + const char *groupId, char **returnDeviceInfo); + int32_t (*getAccessibleTrustedDevices)(const char *appId, const char *groupId, + char **returnDevInfoVec, uint32_t *deviceNum); + bool (*isDeviceInAccessibleGroup)(const char *appId, const char *groupId, const char *deviceId); + void (*destroyInfo)(char **returnInfo); +} GroupManager; + +int32_t InitGroupManager(); +void DestroyGroupManager(); +GroupManager *GetGroupManagerInstance(); +bool IsGroupManagerSupported(); + +#endif diff --git a/services/group_manager/src/group_manager/account_related/account_related_group_manager_mock/account_related_group_manager_mock.c b/services/group_manager/src/group_manager/account_related/account_related_group_manager_mock/account_related_group_manager_mock.c new file mode 100644 index 0000000..3a36c23 --- /dev/null +++ b/services/group_manager/src/group_manager/account_related/account_related_group_manager_mock/account_related_group_manager_mock.c @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "account_related_group_manager.h" +#include "hc_log.h" + +AccountRelatedGroupManager *GetAccountRelatedGroupManager() +{ + return NULL; +} + +bool IsAccountRelatedGroupManagerSupported() +{ + return false; +} + +bool IsAccountRelatedGroupTypeSupported(int32_t groupType) +{ + (void)groupType; + return false; +} \ No newline at end of file diff --git a/services/group_manager/src/group_manager/account_related/across_account_group_mock/across_account_group_mock.c b/services/group_manager/src/group_manager/account_related/across_account_group_mock/across_account_group_mock.c new file mode 100644 index 0000000..1295914 --- /dev/null +++ b/services/group_manager/src/group_manager/account_related/across_account_group_mock/across_account_group_mock.c @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "across_account_group.h" +#include "device_auth_defines.h" +#include "hc_log.h" + +BaseGroup *GetAcrossAccountGroupInstance() +{ + return NULL; +} + +bool IsAcrossAccountGroupSupported() +{ + return false; +} + +int32_t GenerateAcrossAccountGroupId(int64_t userId, int64_t sharedUserId, char **returnGroupId) +{ + (void)userId; + (void)sharedUserId; + (void)returnGroupId; + LOGE("Across account group is not supported!"); + return HC_ERR_NOT_SUPPORT; +} \ No newline at end of file diff --git a/services/group_manager/src/group_manager/account_related/identical_account_group_mock/identical_account_group_mock.c b/services/group_manager/src/group_manager/account_related/identical_account_group_mock/identical_account_group_mock.c new file mode 100644 index 0000000..6a52dfb --- /dev/null +++ b/services/group_manager/src/group_manager/account_related/identical_account_group_mock/identical_account_group_mock.c @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "identical_account_group.h" + +BaseGroup *GetIdenticalAccountGroupInstance() +{ + return NULL; +} + +bool IsIdenticalAccountGroupSupported() +{ + return false; +} diff --git a/services/group_manager/src/group_manager/account_unrelated/account_unrelated_group_manager/account_unrelated_group_manager.c b/services/group_manager/src/group_manager/account_unrelated/account_unrelated_group_manager/account_unrelated_group_manager.c new file mode 100644 index 0000000..14720b8 --- /dev/null +++ b/services/group_manager/src/group_manager/account_unrelated/account_unrelated_group_manager/account_unrelated_group_manager.c @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "account_unrelated_group_manager.h" +#include "common_defs.h" +#include "device_auth_defines.h" +#include "hc_log.h" +#include "peer_to_peer_group.h" + +static void CreatePeerToPeerGroup(int64_t requestId, CJson *jsonParams, const DeviceAuthCallback *callback) +{ + if (!IsPeerToPeerGroupSupported()) { + LOGE("Peer to peer group is not supported!"); + return; + } + PeerToPeerGroup *instance = (PeerToPeerGroup *)GetPeerToPeerGroupInstance(); + if (instance == NULL) { + LOGE("Failed to get peerToPeerGroup instance!"); + return; + } + (void)instance->createGroup(requestId, jsonParams, callback); +} + +static void DeletePeerToPeerGroup(int64_t requestId, CJson *jsonParams, const DeviceAuthCallback *callback) +{ + if (!IsPeerToPeerGroupSupported()) { + LOGE("Peer to peer group is not supported!"); + return; + } + PeerToPeerGroup *instance = (PeerToPeerGroup *)GetPeerToPeerGroupInstance(); + if (instance == NULL) { + LOGE("Failed to get peerToPeerGroup instance!"); + return; + } + (void)instance->deleteGroup(requestId, jsonParams, callback); +} + +static void AddMemberToPeerToPeerGroup(int64_t requestId, CJson *jsonParams, const DeviceAuthCallback *callback) +{ + if (!IsPeerToPeerGroupSupported()) { + LOGE("Peer to peer group is not supported!"); + return; + } + PeerToPeerGroup *instance = (PeerToPeerGroup *)GetPeerToPeerGroupInstance(); + if (instance == NULL) { + LOGE("Failed to get peerToPeerGroup instance!"); + return; + } + (void)instance->addMember(requestId, jsonParams, callback); +} + +static void DeleteMemberFromPeerToPeerGroup(int64_t requestId, CJson *jsonParams, const DeviceAuthCallback *callback) +{ + if (!IsPeerToPeerGroupSupported()) { + LOGE("Peer to peer group is not supported!"); + return; + } + PeerToPeerGroup *instance = (PeerToPeerGroup *)GetPeerToPeerGroupInstance(); + if (instance == NULL) { + LOGE("Failed to get peerToPeerGroup instance!"); + return; + } + (void)instance->deleteMember(requestId, jsonParams, callback); +} + +static void ProcessBindData(int64_t requestId, CJson *jsonParams, const DeviceAuthCallback *callback) +{ + if (!IsPeerToPeerGroupSupported()) { + LOGE("Peer to peer group is not supported!"); + return; + } + PeerToPeerGroup *instance = (PeerToPeerGroup *)GetPeerToPeerGroupInstance(); + if (instance == NULL) { + LOGE("Failed to get peerToPeerGroup instance!"); + return; + } + (void)instance->processData(requestId, jsonParams, callback); +} + +static int32_t AddGroupRole(bool isManager, const char *appId, const char *groupId, const char *roleAppId) +{ + if (!IsPeerToPeerGroupSupported()) { + LOGE("Peer to peer group is not supported!"); + return HC_ERR_NOT_SUPPORT; + } + PeerToPeerGroup *instance = (PeerToPeerGroup *)GetPeerToPeerGroupInstance(); + if (instance == NULL) { + LOGE("Failed to get peerToPeerGroup instance!"); + return HC_ERR_NULL_PTR; + } + return instance->addGroupRole(isManager, appId, groupId, roleAppId); +} + +static int32_t DeleteGroupRole(bool isManager, const char *appId, const char *groupId, const char *roleAppId) +{ + if (!IsPeerToPeerGroupSupported()) { + LOGE("Peer to peer group is not supported!"); + return HC_ERR_NOT_SUPPORT; + } + PeerToPeerGroup *instance = (PeerToPeerGroup *)GetPeerToPeerGroupInstance(); + if (instance == NULL) { + LOGE("Failed to get peerToPeerGroup instance!"); + return HC_ERR_NULL_PTR; + } + return instance->deleteGroupRole(isManager, appId, groupId, roleAppId); +} + +static int32_t GetGroupRole(bool isManager, const char *appId, const char *groupId, char **returnJsonStr, + uint32_t *returnSize) +{ + if (!IsPeerToPeerGroupSupported()) { + LOGE("Peer to peer group is not supported!"); + return HC_ERR_NOT_SUPPORT; + } + PeerToPeerGroup *instance = (PeerToPeerGroup *)GetPeerToPeerGroupInstance(); + if (instance == NULL) { + LOGE("Failed to get peerToPeerGroup instance!"); + return HC_ERR_NULL_PTR; + } + return instance->getGroupRole(isManager, appId, groupId, returnJsonStr, returnSize); +} + +static AccountUnrelatedGroupManager g_nonAccountGroupManager = { + .createPeerToPeerGroup = CreatePeerToPeerGroup, + .deletePeerToPeerGroup = DeletePeerToPeerGroup, + .addMemberToPeerToPeerGroup = AddMemberToPeerToPeerGroup, + .deleteMemberFromPeerToPeerGroup = DeleteMemberFromPeerToPeerGroup, + .processBindData = ProcessBindData, + .addGroupRole = AddGroupRole, + .deleteGroupRole = DeleteGroupRole, + .getGroupRole = GetGroupRole +}; + +AccountUnrelatedGroupManager *GetAccountUnrelatedGroupManager() +{ + return &g_nonAccountGroupManager; +} + +bool IsAccountUnrelatedGroupManagerSupported() +{ + return true; +} + +bool IsAccountUnrelatedGroupTypeSupported(int32_t groupType) +{ + if ((groupType == PEER_TO_PEER_GROUP) && (IsPeerToPeerGroupSupported())) { + return true; + } + return false; +} \ No newline at end of file diff --git a/services/group_manager/src/group_manager/account_unrelated/account_unrelated_group_manager_mock/account_unrelated_group_manager_mock.c b/services/group_manager/src/group_manager/account_unrelated/account_unrelated_group_manager_mock/account_unrelated_group_manager_mock.c new file mode 100644 index 0000000..e567693 --- /dev/null +++ b/services/group_manager/src/group_manager/account_unrelated/account_unrelated_group_manager_mock/account_unrelated_group_manager_mock.c @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "account_unrelated_group_manager.h" +#include "hc_log.h" + +AccountUnrelatedGroupManager *GetAccountUnrelatedGroupManager() +{ + return NULL; +} + +bool IsAccountUnrelatedGroupManagerSupported() +{ + return false; +} + +bool IsAccountUnrelatedGroupTypeSupported(int32_t groupType) +{ + (void)groupType; + return false; +} \ No newline at end of file diff --git a/services/group_manager/src/group_manager/account_unrelated/peer_to_peer_group/peer_to_peer_group.c b/services/group_manager/src/group_manager/account_unrelated/peer_to_peer_group/peer_to_peer_group.c new file mode 100755 index 0000000..29f54ed --- /dev/null +++ b/services/group_manager/src/group_manager/account_unrelated/peer_to_peer_group/peer_to_peer_group.c @@ -0,0 +1,852 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "peer_to_peer_group.h" +#include "alg_defs.h" +#include "callback_manager.h" +#include "channel_manager.h" +#include "common_util.h" +#include "database_manager.h" +#include "group_common.h" +#include "hc_dev_info.h" +#include "hc_log.h" +#include "session_manager.h" + +static int32_t CheckGroupName(const char *appId, const CJson *jsonParams) +{ + const char *groupName = GetStringFromJson(jsonParams, FIELD_GROUP_NAME); + if (groupName == NULL) { + LOGE("Failed to get groupName from jsonParams!"); + return HC_ERR_JSON_GET; + } + + if (IsGroupExist(appId, groupName)) { + LOGE("A group with the same group name has been created! [AppId]: %s, [GroupName]: %s", appId, groupName); + return HC_ERR_INVALID_PARAMS; + } + return HC_SUCCESS; +} + +static int32_t GenerateGroupId(const CJson *jsonParams, char **returnGroupId) +{ + const char *groupName = GetStringFromJson(jsonParams, FIELD_GROUP_NAME); + if (groupName == NULL) { + LOGE("Failed to get groupName from jsonParams!"); + return HC_ERR_JSON_GET; + } + const char *appId = GetStringFromJson(jsonParams, FIELD_APP_ID); + if (appId == NULL) { + LOGE("Failed to get appId from jsonParams!"); + return HC_ERR_JSON_GET; + } + /* peer to peer group: groupId = sha256(groupName | appId) */ + uint8_t *hashMessage = NULL; + uint32_t messageSize = 0; + Uint8Buff groupNameBuff = {(uint8_t *)groupName, HcStrlen(groupName)}; + Uint8Buff appIdBuff = {(uint8_t *)appId, HcStrlen(appId)}; + int32_t result = GetHashMessage(&groupNameBuff, &appIdBuff, &hashMessage, &messageSize); + if (result != HC_SUCCESS) { + return result; + } + int hashStrLen = SHA256_LEN * BYTE_TO_HEX_OPER_LENGTH + 1; + *returnGroupId = (char *)HcMalloc(hashStrLen, 0); + result = GetHashResult(hashMessage, messageSize, *returnGroupId, hashStrLen); + HcFree(hashMessage); + if (result != HC_SUCCESS) { + LOGE("Failed to get hash for groupId! [AppId]: %s, [GroupName]: %s", appId, groupName); + HcFree(*returnGroupId); + *returnGroupId = NULL; + return HC_ERR_HASH_FAIL; + } + LOGI("Generate groupId successfully! [AppId]: %s, [GroupName]: %s", appId, groupName); + return HC_SUCCESS; +} + +static int32_t CheckCreateParams(const CJson *jsonParams) +{ + const char *appId = GetStringFromJson(jsonParams, FIELD_APP_ID); + if (appId == NULL) { + LOGE("Failed to get appId from jsonParams!"); + return HC_ERR_JSON_GET; + } + int32_t result; + if (((result = CheckGroupName(appId, jsonParams)) != HC_SUCCESS) || + ((result = CheckUserTypeIfExist(jsonParams)) != HC_SUCCESS) || + ((result = CheckGroupVisibilityIfExist(jsonParams)) != HC_SUCCESS) || + ((result = CheckExpireTimeIfExist(jsonParams)) != HC_SUCCESS) || + ((result = CheckGroupNumLimit(PEER_TO_PEER_GROUP, appId)) != HC_SUCCESS)) { + return result; + } + LOGI("The group creation parameters transferred by the user are valid! [AppId]: %s", appId); + return HC_SUCCESS; +} + +static int32_t GenerateGroupParams(const CJson *jsonParams, const char *groupId, GroupInfo *groupParams) +{ + const char *groupName = GetStringFromJson(jsonParams, FIELD_GROUP_NAME); + if (groupName == NULL) { + LOGE("Failed to get groupName from jsonParams!"); + return HC_ERR_JSON_GET; + } + const char *appId = GetStringFromJson(jsonParams, FIELD_APP_ID); + if (appId == NULL) { + LOGE("Failed to get appId from jsonParams!"); + return HC_ERR_JSON_GET; + } + int32_t result; + if (((result = AddGroupTypeToParams(PEER_TO_PEER_GROUP, groupParams)) != HC_SUCCESS) || + ((result = AddGroupNameToParams(groupName, groupParams)) != HC_SUCCESS) || + ((result = AddGroupIdToParams(groupId, groupParams)) != HC_SUCCESS) || + ((result = AddGroupOwnerToParams(appId, groupParams)) != HC_SUCCESS) || + ((result = AddGroupVisibilityOrDefault(groupParams)) != HC_SUCCESS) || + ((result = AddExpireTimeOrDefault(jsonParams, groupParams)) != HC_SUCCESS)) { + return result; + } + return HC_SUCCESS; +} + +static int32_t GenerateDevParams(const CJson *jsonParams, const char *groupId, DeviceInfo *devParams) +{ + int32_t result; + if (((result = AddUdidToParams(devParams)) != HC_SUCCESS) || + ((result = AddAuthIdToParamsOrDefault(jsonParams, devParams))) || + ((result = AddUserTypeToParamsOrDefault(jsonParams, devParams)) != HC_SUCCESS) || + ((result = AddGroupIdToDevParams(groupId, devParams)) != HC_SUCCESS) || + ((result = AddServiceTypeToParams(groupId, devParams)) != HC_SUCCESS)) { + return result; + } + return HC_SUCCESS; +} + +static int32_t CreateGroupInner(const CJson *jsonParams, char **returnGroupId) +{ + char *groupId = NULL; + int32_t result; + if (((result = CheckCreateParams(jsonParams)) != HC_SUCCESS) || + ((result = GenerateGroupId(jsonParams, &groupId)) != HC_SUCCESS) || + ((result = ProcessKeyPair(CREATE_KEY_PAIR, jsonParams, groupId)) != HC_SUCCESS) || + ((result = AddGroupToDatabaseByJson(GenerateGroupParams, jsonParams, groupId)) != HC_SUCCESS) || + ((result = AddDeviceToDatabaseByJson(GenerateDevParams, jsonParams, groupId)) != HC_SUCCESS)) { + HcFree(groupId); + return result; + } + *returnGroupId = groupId; + return HC_SUCCESS; +} + +static int32_t GetPeerUserType(const char *groupId, const char *peerAuthId) +{ + int peerUserType = DEVICE_TYPE_ACCESSORY; + DeviceInfo *devAuthParams = CreateDeviceInfoStruct(); + if (devAuthParams == NULL) { + LOGE("Failed to allocate devEntry memory!"); + return peerUserType; + } + if (GetDeviceInfoByAuthId(peerAuthId, groupId, devAuthParams) != HC_SUCCESS) { + LOGE("Failed to obtain the device information from the database!"); + DestroyDeviceInfoStruct(devAuthParams); + return peerUserType; + } + peerUserType = devAuthParams->devType; + DestroyDeviceInfoStruct(devAuthParams); + return peerUserType; +} + +static int32_t HandleLocalUnbind(int64_t requestId, const CJson *jsonParams, const DeviceAuthCallback *callback) +{ + const char *peerAuthId = GetStringFromJson(jsonParams, FIELD_DELETE_ID); + if (peerAuthId == NULL) { + LOGE("Failed to get peerAuthId from jsonParams!"); + return HC_ERR_JSON_GET; + } + const char *groupId = GetStringFromJson(jsonParams, FIELD_GROUP_ID); + if (groupId == NULL) { + LOGE("Failed to get groupId from jsonParams!"); + return HC_ERR_JSON_GET; + } + int32_t peerUserType = GetPeerUserType(groupId, peerAuthId); + int32_t result = DelTrustedDeviceByAuthId(peerAuthId, groupId); + if (result != HC_SUCCESS) { + LOGE("Failed to delete trust device from database!"); + return result; + } + /* + * If the trusted device has been deleted from the database but the peer key fails to be deleted, + * the forcible unbinding is still considered successful. Only logs need to be printed. + */ + result = DeletePeerKeyIfForceUnbind(groupId, peerAuthId, peerUserType); + if (result != HC_SUCCESS) { + LOGD("Failed to delete peer key!"); + } + char *returnDataStr = NULL; + result = GenerateUnbindSuccessData(peerAuthId, groupId, &returnDataStr); + if (result != HC_SUCCESS) { + return result; + } + ProcessFinishCallback(requestId, MEMBER_DELETE, returnDataStr, callback); + FreeJsonString(returnDataStr); + return HC_SUCCESS; +} + +static int32_t AddAuthIdAndUserTypeToParams(const char *groupId, CJson *jsonParams) +{ + DeviceInfo *devAuthParams = CreateDeviceInfoStruct(); + if (devAuthParams == NULL) { + LOGE("Failed to allocate devEntry memory!"); + return HC_ERR_ALLOC_MEMORY; + } + uint8_t udid[INPUT_UDID_LEN] = { 0 }; + if (HcGetUdid(udid, INPUT_UDID_LEN) != HC_SUCCESS) { + LOGE("Get local udid failed"); + return HC_ERROR; + } + if (GetDeviceInfoForDevAuth((const char *)udid, groupId, devAuthParams) != HC_SUCCESS) { + LOGE("Failed to obtain the device information from the database!"); + DestroyDeviceInfoStruct(devAuthParams); + return HC_ERR_DB; + } + if (AddStringToJson(jsonParams, FIELD_DEVICE_ID, StringGet(&devAuthParams->authId)) != HC_SUCCESS) { + LOGE("Failed to add authId to params!"); + DestroyDeviceInfoStruct(devAuthParams); + return HC_ERR_JSON_FAIL; + } + if (AddIntToJson(jsonParams, FIELD_USER_TYPE, devAuthParams->devType) != HC_SUCCESS) { + LOGE("Failed to add userType to params!"); + DestroyDeviceInfoStruct(devAuthParams); + return HC_ERR_JSON_FAIL; + } + DestroyDeviceInfoStruct(devAuthParams); + return HC_SUCCESS; +} + +static int32_t AssertPeerToPeerGroupType(int32_t groupType) +{ + if (groupType != PEER_TO_PEER_GROUP) { + LOGE("Invalid group type! [GroupType]: %d", groupType); + return HC_ERR_INVALID_PARAMS; + } + return HC_SUCCESS; +} + +static int32_t CheckInputGroupTypeValid(const CJson *jsonParams) +{ + int32_t groupType = PEER_TO_PEER_GROUP; + if (GetIntFromJson(jsonParams, FIELD_GROUP_TYPE, &groupType) != HC_SUCCESS) { + LOGE("Failed to get groupType from jsonParams!"); + return HC_ERR_JSON_GET; + } + return AssertPeerToPeerGroupType(groupType); +} + +static int32_t IsPeerDeviceIdNotSelf(const char *peerUdid) +{ + uint8_t udid[INPUT_UDID_LEN] = { 0 }; + if (HcGetUdid(udid, INPUT_UDID_LEN) != HC_SUCCESS) { + LOGE("Get local udid failed"); + return HC_ERROR; + } + if (strcmp(peerUdid, (char *)udid) == 0) { + LOGE("You are not allowed to delete yourself!"); + return HC_ERR_INVALID_PARAMS; + } + return HC_SUCCESS; +} + +static int32_t CheckPeerDeviceStatus(const char *groupId, const CJson *jsonParams) +{ + const char *peerAuthId = GetStringFromJson(jsonParams, FIELD_DELETE_ID); + if (peerAuthId == NULL) { + LOGE("Failed to get peerUdid from jsonParams!"); + return HC_ERR_JSON_GET; + } + DeviceInfo *deviceInfo = CreateDeviceInfoStruct(); + if (deviceInfo == NULL) { + LOGE("Failed to allocate deviceInfo memory!"); + return HC_ERR_ALLOC_MEMORY; + } + int32_t result = GetDeviceInfoByAuthId(peerAuthId, groupId, deviceInfo); + if (result != HC_SUCCESS) { + LOGE("Failed to obtain the peer device information from the database!"); + DestroyDeviceInfoStruct(deviceInfo); + return result; + } + result = IsPeerDeviceIdNotSelf(StringGet(&deviceInfo->udid)); + DestroyDeviceInfoStruct(deviceInfo); + return result; +} + +static int32_t CheckInvitePeer(const CJson *jsonParams) +{ + const char *groupId = GetStringFromJson(jsonParams, FIELD_GROUP_ID); + if (groupId == NULL) { + LOGE("Failed to get groupId from jsonParams!"); + return HC_ERR_JSON_GET; + } + const char *appId = GetStringFromJson(jsonParams, FIELD_APP_ID); + if (appId == NULL) { + LOGE("Failed to get appId from jsonParams!"); + return HC_ERR_JSON_GET; + } + + int32_t groupType = PEER_TO_PEER_GROUP; + int32_t result; + if (((result = CheckGroupExist(groupId)) != HC_SUCCESS) || + ((result = GetGroupTypeFromDb(groupId, &groupType)) != HC_SUCCESS) || + ((result = AssertPeerToPeerGroupType(groupType)) != HC_SUCCESS) || + ((result = CheckPermForGroup(MEMBER_INVITE, appId, groupId)) != HC_SUCCESS) || + ((result = CheckDeviceNumLimit(groupId, NULL)) != HC_SUCCESS)) { + return result; + } + return HC_SUCCESS; +} + +static int32_t CheckJoinPeer(const CJson *jsonParams) +{ + return CheckInputGroupTypeValid(jsonParams); +} + +static int32_t CheckDeletePeer(const CJson *jsonParams) +{ + const char *groupId = GetStringFromJson(jsonParams, FIELD_GROUP_ID); + if (groupId == NULL) { + LOGE("Failed to get groupId from jsonParams!"); + return HC_ERR_JSON_GET; + } + const char *appId = GetStringFromJson(jsonParams, FIELD_APP_ID); + if (appId == NULL) { + LOGE("Failed to get appId from jsonParams!"); + return HC_ERR_JSON_GET; + } + + int32_t groupType = PEER_TO_PEER_GROUP; + int32_t result; + if (((result = CheckGroupExist(groupId)) != HC_SUCCESS) || + ((result = GetGroupTypeFromDb(groupId, &groupType)) != HC_SUCCESS) || + ((result = AssertPeerToPeerGroupType(groupType)) != HC_SUCCESS) || + ((result = CheckPermForGroup(MEMBER_DELETE, appId, groupId)) != HC_SUCCESS) || + ((result = CheckPeerDeviceStatus(groupId, jsonParams)) != HC_SUCCESS)) { + return result; + } + return HC_SUCCESS; +} + +static int32_t CheckClientStatus(int operationCode, const CJson *jsonParams) +{ + switch (operationCode) { + case MEMBER_INVITE: + return CheckInvitePeer(jsonParams); + case MEMBER_JOIN: + return CheckJoinPeer(jsonParams); + case MEMBER_DELETE: + return CheckDeletePeer(jsonParams); + default: + LOGE("Enter the exception case!"); + return HC_ERR_CASE; + } +} + +static CJson *GenerateGroupErrorMsg(int32_t errorCode, int64_t requestId) +{ + CJson *errorData = CreateJson(); + if (errorData == NULL) { + LOGE("Failed to allocate errorData memory!"); + return NULL; + } + if (AddIntToJson(errorData, FIELD_GROUP_ERROR_MSG, errorCode) != HC_SUCCESS) { + LOGE("Failed to add errorCode to errorData!"); + FreeJson(errorData); + return NULL; + } + if (AddInt64StringToJson(errorData, FIELD_REQUEST_ID, requestId) != HC_SUCCESS) { + LOGE("Failed to add requestId to errorData!"); + FreeJson(errorData); + return NULL; + } + return errorData; +} + +static void InformPeerProcessError(int64_t requestId, const CJson *jsonParams, const DeviceAuthCallback *callback, + int32_t errorCode) +{ + ChannelType channelType = GetChannelType(callback); + int64_t channelId = DEFAULT_CHANNEL_ID; + if ((channelType == NO_CHANNEL) || + ((channelType == SOFT_BUS) && + (GetByteFromJson(jsonParams, FIELD_CHANNEL_ID, (uint8_t *)&channelId, sizeof(int64_t)) != HC_SUCCESS))) { + LOGE("No available channels found!"); + return; + } + CJson *errorData = GenerateGroupErrorMsg(errorCode, requestId); + if (errorData == NULL) { + return; + } + char *errorDataStr = PackJsonToString(errorData); + FreeJson(errorData); + if (errorDataStr == NULL) { + LOGE("An error occurred when converting json to string!"); + return; + } + (void)SendMsg(channelType, requestId, channelId, callback, errorDataStr); + FreeJsonString(errorDataStr); +} + +static int32_t CheckServerStatusIfNotInvite(int operationCode, const CJson *jsonParams) +{ + if (operationCode == MEMBER_INVITE) { + return HC_SUCCESS; + } + const char *groupId = GetStringFromJson(jsonParams, FIELD_GROUP_ID); + if (groupId == NULL) { + LOGE("Failed to get groupId from jsonParams!"); + return HC_ERR_JSON_GET; + } + const char *appId = GetStringFromJson(jsonParams, FIELD_APP_ID); + if (appId == NULL) { + LOGE("Failed to get appId from jsonParams!"); + return HC_ERR_JSON_GET; + } + const char *peerUdid = GetStringFromJson(jsonParams, FIELD_CONN_DEVICE_ID); + if (peerUdid == NULL) { + LOGE("Failed to get peerUdid from jsonParams!"); + return HC_ERR_JSON_GET; + } + int32_t result = CheckGroupExist(groupId); + if (result != HC_SUCCESS) { + return result; + } + if (operationCode == MEMBER_JOIN) { + /* The client sends a join request, which is equivalent to the server performing an invitation operation. */ + result = CheckPermForGroup(MEMBER_INVITE, appId, groupId); + if (result != HC_SUCCESS) { + return result; + } + result = CheckDeviceNumLimit(groupId, peerUdid); + } else if (operationCode == MEMBER_DELETE) { + result = CheckPermForGroup(MEMBER_DELETE, appId, groupId); + if (result != HC_SUCCESS) { + return result; + } + if (!IsTrustedDeviceInGroup(groupId, peerUdid)) { + result = HC_ERR_DEVICE_NOT_EXIST; + } + } + return result; +} + +static int32_t CreateGroup(int64_t requestId, CJson *jsonParams, const DeviceAuthCallback *callback) +{ + LOGI("[Start]: Start to create a peer to peer group! [RequestId]: %lld", requestId); + int32_t result; + char *groupId = NULL; + char *returnDataStr = NULL; + do { + result = CheckInputGroupTypeValid(jsonParams); + if (result != HC_SUCCESS) { + break; + } + result = CreateGroupInner(jsonParams, &groupId); + if (result != HC_SUCCESS) { + break; + } + result = ConvertGroupIdToJsonStr(groupId, &returnDataStr); + HcFree(groupId); + } while (0); + if (result != HC_SUCCESS) { + ProcessErrorCallback(requestId, GROUP_CREATE, result, NULL, callback); + LOGE("[End]: Failed to create a peer to peer group! [RequestId]: %lld", requestId); + return result; + } + ProcessFinishCallback(requestId, GROUP_CREATE, returnDataStr, callback); + FreeJsonString(returnDataStr); + LOGI("[End]: Create a peer to peer group successfully! [RequestId]: %lld", requestId); + return HC_SUCCESS; +} + +static int32_t DeleteGroup(int64_t requestId, CJson *jsonParams, const DeviceAuthCallback *callback) +{ + int32_t result; + const char *groupId = NULL; + const char *appId = NULL; + char *returnDataStr = NULL; + do { + LOGI("[Start]: Start to delete a peer to peer group! [RequestId]: %lld", requestId); + groupId = GetStringFromJson(jsonParams, FIELD_GROUP_ID); + if (groupId == NULL) { + LOGE("Failed to get groupId from jsonParams!"); + result = HC_ERR_JSON_GET; + break; + } + appId = GetStringFromJson(jsonParams, FIELD_APP_ID); + if (appId == NULL) { + LOGE("Failed to get appId from jsonParams!"); + result = HC_ERR_JSON_GET; + break; + } + int32_t groupType = PEER_TO_PEER_GROUP; + if (((result = CheckGroupExist(groupId)) != HC_SUCCESS) || + ((result = GetGroupTypeFromDb(groupId, &groupType)) != HC_SUCCESS) || + ((result = AssertPeerToPeerGroupType(groupType)) != HC_SUCCESS) || + ((result = CheckPermForGroup(GROUP_DISBAND, appId, groupId)) != HC_SUCCESS) || + ((result = AddAuthIdAndUserTypeToParams(groupId, jsonParams)) != HC_SUCCESS) || + ((result = DelGroupFromDatabase(groupId)) != HC_SUCCESS) || + ((result = ConvertGroupIdToJsonStr(groupId, &returnDataStr)) != HC_SUCCESS)) { + break; + } + } while (0); + if (result != HC_SUCCESS) { + ProcessErrorCallback(requestId, GROUP_DISBAND, result, NULL, callback); + LOGE("[End]: Failed to delete a peer to peer group! [RequestId]: %lld", requestId); + return result; + } + /* + * If the group has been disbanded from the database but the key pair fails to be deleted, + * we still believe we succeeded in disbanding the group. Only logs need to be printed. + */ + result = ProcessKeyPair(DELETE_KEY_PAIR, jsonParams, groupId); + if (result != HC_SUCCESS) { + LOGD("Failed to delete peer key!"); + } + ProcessFinishCallback(requestId, GROUP_DISBAND, returnDataStr, callback); + FreeJsonString(returnDataStr); + LOGI("[End]: Delete a peer to peer group successfully! [RequestId]: %lld", requestId); + return HC_SUCCESS; +} + +static int32_t AddMemberToGroup(int64_t requestId, CJson *jsonParams, const DeviceAuthCallback *callback) +{ + int32_t result; + int operationCode = MEMBER_INVITE; + do { + LOGI("[Start]: Start to add member to a peer to peer group! [RequestId]: %lld", requestId); + (void)GetIntFromJson(jsonParams, FIELD_OPERATION_CODE, &operationCode); + result = CheckClientStatus(operationCode, jsonParams); + if (result != HC_SUCCESS) { + break; + } + ChannelType channelType = GetChannelType(callback); + if ((channelType == NO_CHANNEL) || (!CanFindValidChannel(channelType, jsonParams, callback))) { + LOGE("No available channels found!"); + result = HC_ERR_CHANNEL_NOT_EXIST; + break; + } + result = CreateSession(requestId, TYPE_CLIENT_BIND_SESSION, jsonParams, callback); + if (result != HC_SUCCESS) { + LOGE("Failed to create client bind session!"); + break; + } + /** + * If service open the channel by itself, + * a channel opened message needs to be triggered to unify the channel usage policy. + */ + if (channelType == SERVICE_CHANNEL) { + /* Release the memory in advance to reduce the memory usage. */ + DeleteAllItem(jsonParams); + OnChannelOpened(requestId, DEFAULT_CHANNEL_ID); + } + } while (0); + if (result != HC_SUCCESS) { + ProcessErrorCallback(requestId, operationCode, result, NULL, callback); + LOGE("[End]: Failed to add member to a peer to peer group! [RequestId]: %lld", requestId); + } + return result; +} + +static int32_t DeleteMemberFromGroupInner(int64_t requestId, CJson *jsonParams, const DeviceAuthCallback *callback) +{ + int32_t result = CheckClientStatus(MEMBER_DELETE, jsonParams); + if (result != HC_SUCCESS) { + return result; + } + bool isForceDelete = false; + bool isIgnoreChannel = false; + (void)(GetBoolFromJson(jsonParams, FIELD_IS_FORCE_DELETE, &isForceDelete)); + (void)(GetBoolFromJson(jsonParams, FIELD_IS_IGNORE_CHANNEL, &isIgnoreChannel)); + /* Release the memory in advance to reduce the memory usage. */ + DeleteItemFromJson(jsonParams, FIELD_IS_IGNORE_CHANNEL); + if (isForceDelete && isIgnoreChannel) { + LOGI("The service requires that the device be forcibly unbound locally instead of being unbound online!"); + return HandleLocalUnbind(requestId, jsonParams, callback); + } + ChannelType channelType = GetChannelType(callback); + if ((channelType == NO_CHANNEL) || (!CanFindValidChannel(channelType, jsonParams, callback))) { + LOGI("No available channels found!"); + if (isForceDelete) { + LOGI("The peer device is forcibly unbound because no available channel is found!"); + return HandleLocalUnbind(requestId, jsonParams, callback); + } else { + LOGE("The service cannot unbind the device because it is not forcibly unbind and no channel is available!"); + return HC_ERR_CHANNEL_NOT_EXIST; + } + } + result = CreateSession(requestId, TYPE_CLIENT_BIND_SESSION, jsonParams, callback); + if (result != HC_SUCCESS) { + if (isForceDelete) { + LOGE("Failed to create client bind session. Therefore, we forcibly unbind the peer device!"); + return HandleLocalUnbind(requestId, jsonParams, callback); + } + LOGE("Failed to create client bind session!"); + return result; + } + /* + * If service open the channel by itself, + * a channel opened message needs to be triggered to unify the channel usage policy. + */ + if (channelType == SERVICE_CHANNEL) { + /* Release the memory in advance to reduce the memory usage. */ + DeleteAllItem(jsonParams); + OnChannelOpened(requestId, DEFAULT_CHANNEL_ID); + } + return HC_SUCCESS; +} + +static int32_t DeleteMemberFromGroup(int64_t requestId, CJson *jsonParams, const DeviceAuthCallback *callback) +{ + LOGI("[Start]: Start to delete member from a peer to peer group! [RequestId]: %lld", requestId); + int32_t result = DeleteMemberFromGroupInner(requestId, jsonParams, callback); + if (result != HC_SUCCESS) { + ProcessErrorCallback(requestId, MEMBER_DELETE, result, NULL, callback); + LOGE("[End]: Failed to delete member from a peer to peer group! [RequestId]: %lld", requestId); + } + return result; +} + +static int32_t ProcessData(int64_t requestId, CJson *jsonParams, const DeviceAuthCallback *callback) +{ + int32_t result; + int operationCode = MEMBER_INVITE; + (void)(GetIntFromJson(jsonParams, FIELD_GROUP_OP, &operationCode)); + result = CheckServerStatusIfNotInvite(operationCode, jsonParams); + if (result != HC_SUCCESS) { + InformPeerProcessError(requestId, jsonParams, callback, result); + ProcessErrorCallback(requestId, operationCode, result, NULL, callback); + return result; + } + result = CreateSession(requestId, TYPE_SERVER_BIND_SESSION, jsonParams, callback); + if (result != HC_SUCCESS) { + LOGE("Failed to create server bind session!"); + } + return result; +} + +static int32_t AddManager(const char *appId, const char *groupId, const char *managerAppId) +{ + int32_t groupType = PEER_TO_PEER_GROUP; + if (GetGroupTypeFromDb(groupId, &groupType) != HC_SUCCESS) { + LOGE("No group is found based on the query parameters!"); + return HC_ERR_GROUP_NOT_EXIST; + } + if (AssertPeerToPeerGroupType(groupType) != HC_SUCCESS) { + return HC_ERR_NOT_SUPPORT; + } + if (!IsGroupOwner(groupId, appId)) { + LOGE("You do not have the permission to add a manager to the group!"); + return HC_ERR_ACCESS_DENIED; + } + if (AddGroupManager(groupId, managerAppId) != HC_SUCCESS) { + LOGE("Failed to add manager!"); + return HC_ERR_DB; + } + return HC_SUCCESS; +} + +static int32_t AddFriend(const char *appId, const char *groupId, const char *friendAppId) +{ + int32_t groupType = PEER_TO_PEER_GROUP; + if (GetGroupTypeFromDb(groupId, &groupType) != HC_SUCCESS) { + LOGE("No group is found based on the query parameters!"); + return HC_ERR_GROUP_NOT_EXIST; + } + if (AssertPeerToPeerGroupType(groupType) != HC_SUCCESS) { + return HC_ERR_NOT_SUPPORT; + } + if (!IsGroupEditAllowed(groupId, appId)) { + LOGE("You do not have the permission to add a friend to the group!"); + return HC_ERR_ACCESS_DENIED; + } + if (CompareVisibility(groupId, GROUP_VISIBILITY_ALLOW_LIST) != HC_SUCCESS) { + LOGE("The group dose not support the allow list protection!"); + return HC_ERR_NOT_SUPPORT; + } + if (AddGroupFriend(groupId, friendAppId) != HC_SUCCESS) { + LOGE("Failed to add friend!"); + return HC_ERR_DB; + } + return HC_SUCCESS; +} + +static int32_t DeleteManager(const char *appId, const char *groupId, const char *managerAppId) +{ + int32_t groupType = PEER_TO_PEER_GROUP; + if (GetGroupTypeFromDb(groupId, &groupType) != HC_SUCCESS) { + LOGE("No group is found based on the query parameters!"); + return HC_ERR_GROUP_NOT_EXIST; + } + if (AssertPeerToPeerGroupType(groupType) != HC_SUCCESS) { + return HC_ERR_NOT_SUPPORT; + } + if (!IsGroupOwner(groupId, appId)) { + LOGE("You do not have the permission to delete a manager from the group!"); + return HC_ERR_ACCESS_DENIED; + } + if (RemoveGroupManager(groupId, managerAppId) != HC_SUCCESS) { + LOGE("Failed to delete manager!"); + return HC_ERR_DB; + } + return HC_SUCCESS; +} + +static int32_t DeleteFriend(const char *appId, const char *groupId, const char *friendAppId) +{ + int32_t groupType = PEER_TO_PEER_GROUP; + if (GetGroupTypeFromDb(groupId, &groupType) != HC_SUCCESS) { + LOGE("No group is found based on the query parameters!"); + return HC_ERR_GROUP_NOT_EXIST; + } + if (AssertPeerToPeerGroupType(groupType) != HC_SUCCESS) { + return HC_ERR_NOT_SUPPORT; + } + if (!IsGroupEditAllowed(groupId, appId)) { + LOGE("You do not have the permission to add a friend to the group!"); + return HC_ERR_ACCESS_DENIED; + } + if (CompareVisibility(groupId, GROUP_VISIBILITY_ALLOW_LIST) != HC_SUCCESS) { + LOGE("The group dose not support the allow list protection!"); + return HC_ERR_NOT_SUPPORT; + } + if (RemoveGroupFriend(groupId, friendAppId) != HC_SUCCESS) { + LOGE("Failed to delete friend!"); + return HC_ERR_DB; + } + return HC_SUCCESS; +} + +static int32_t GetManagers(const char *appId, const char *groupId, char **returnManagers, uint32_t *returnSize) +{ + int32_t groupType = PEER_TO_PEER_GROUP; + if (GetGroupTypeFromDb(groupId, &groupType) != HC_SUCCESS) { + LOGE("No group is found based on the query parameters!"); + return HC_ERR_GROUP_NOT_EXIST; + } + if (AssertPeerToPeerGroupType(groupType) != HC_SUCCESS) { + return HC_ERR_NOT_SUPPORT; + } + if (!IsGroupOwner(groupId, appId)) { + LOGE("You do not have the permission to query the group managers information!"); + return HC_ERR_ACCESS_DENIED; + } + CJson *managers = CreateJsonArray(); + if (managers == NULL) { + LOGE("Failed to allocate managers memory!"); + return HC_ERR_JSON_FAIL; + } + int32_t result = GetGroupManagers(groupId, managers); + if (result != HC_SUCCESS) { + LOGE("Failed to get managers!"); + FreeJson(managers); + return result; + } + *returnManagers = PackJsonToString(managers); + if (*returnManagers == NULL) { + LOGE("Failed to convert json to string!"); + FreeJson(managers); + return HC_ERR_JSON_FAIL; + } + *returnSize = GetItemNum(managers); + FreeJson(managers); + return HC_SUCCESS; +} + +static int32_t GetFriends(const char *appId, const char *groupId, char **returnFriends, uint32_t *returnSize) +{ + int32_t groupType = PEER_TO_PEER_GROUP; + if (GetGroupTypeFromDb(groupId, &groupType) != HC_SUCCESS) { + LOGE("No group is found based on the query parameters!"); + return HC_ERR_GROUP_NOT_EXIST; + } + if (AssertPeerToPeerGroupType(groupType) != HC_SUCCESS) { + return HC_ERR_NOT_SUPPORT; + } + if (!IsGroupEditAllowed(groupId, appId)) { + LOGE("You do not have the permission to query the group friends information!"); + return HC_ERR_ACCESS_DENIED; + } + CJson *friends = CreateJsonArray(); + if (friends == NULL) { + LOGE("Failed to allocate friends memory!"); + return HC_ERR_JSON_FAIL; + } + int32_t result = GetGroupFriends(groupId, friends); + if (result != HC_SUCCESS) { + LOGE("Failed to get friends!"); + FreeJson(friends); + return result; + } + *returnFriends = PackJsonToString(friends); + if (*returnFriends == NULL) { + LOGE("Failed to convert json to string!"); + FreeJson(friends); + return HC_ERR_JSON_FAIL; + } + *returnSize = GetItemNum(friends); + FreeJson(friends); + return HC_SUCCESS; +} + +static int32_t AddGroupRole(bool isManager, const char *appId, const char *groupId, const char *roleAppId) +{ + if (isManager) { + return AddManager(appId, groupId, roleAppId); + } + return AddFriend(appId, groupId, roleAppId); +} + +static int32_t DeleteGroupRole(bool isManager, const char *appId, const char *groupId, const char *roleAppId) +{ + if (isManager) { + return DeleteManager(appId, groupId, roleAppId); + } + return DeleteFriend(appId, groupId, roleAppId); +} + +static int32_t GetGroupRole(bool isManager, const char *appId, const char *groupId, char **returnJsonStr, + uint32_t *returnSize) +{ + if (isManager) { + return GetManagers(appId, groupId, returnJsonStr, returnSize); + } + return GetFriends(appId, groupId, returnJsonStr, returnSize); +} + +static PeerToPeerGroup g_peerToPeerGroup = { + .base.type = PEER_TO_PEER_GROUP, + .createGroup = CreateGroup, + .deleteGroup = DeleteGroup, + .addMember = AddMemberToGroup, + .deleteMember = DeleteMemberFromGroup, + .processData = ProcessData, + .addGroupRole = AddGroupRole, + .deleteGroupRole = DeleteGroupRole, + .getGroupRole = GetGroupRole +}; + +BaseGroup *GetPeerToPeerGroupInstance() +{ + return (BaseGroup *)&g_peerToPeerGroup; +} + +bool IsPeerToPeerGroupSupported() +{ + return true; +} diff --git a/services/group_manager/src/group_manager/account_unrelated/peer_to_peer_group_mock/peer_to_peer_group_mock.c b/services/group_manager/src/group_manager/account_unrelated/peer_to_peer_group_mock/peer_to_peer_group_mock.c new file mode 100644 index 0000000..57ebece --- /dev/null +++ b/services/group_manager/src/group_manager/account_unrelated/peer_to_peer_group_mock/peer_to_peer_group_mock.c @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "peer_to_peer_group.h" + +BaseGroup *GetPeerToPeerGroupInstance() +{ + return NULL; +} + +bool IsPeerToPeerGroupSupported() +{ + return false; +} diff --git a/services/group_manager/src/group_manager/group_common.c b/services/group_manager/src/group_manager/group_common.c new file mode 100755 index 0000000..340dc39 --- /dev/null +++ b/services/group_manager/src/group_manager/group_common.c @@ -0,0 +1,519 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "group_common.h" +#include "alg_loader.h" +#include "common_util.h" +#include "database_manager.h" +#include "dev_auth_module_manager.h" +#include "group_manager.h" +#include "hc_dev_info.h" +#include "hc_log.h" + +int32_t GetHashMessage(const Uint8Buff *first, const Uint8Buff *second, uint8_t **hashMessage, uint32_t *messageSize) +{ + if ((first == NULL) || (second == NULL)) { + LOGE("The input first message or second message is NULL!"); + return HC_ERR_NULL_PTR; + } + const char *separator = "|"; + uint32_t firstSize = first->length; + uint32_t secondSize = second->length; + uint32_t separatorSize = HcStrlen(separator); + uint32_t totalSize = firstSize + secondSize + separatorSize; + *hashMessage = (uint8_t *)HcMalloc(totalSize, 0); + if (*hashMessage == NULL) { + LOGE("Failed to allocate hashMessage memory!"); + return HC_ERR_ALLOC_MEMORY; + } + int32_t result = HC_SUCCESS; + do { + if (memcpy_s((*hashMessage), totalSize, first->val, firstSize) != HC_SUCCESS) { + LOGE("Failed to copy first!"); + result = HC_ERR_MEMORY_COPY; + break; + } + if (memcpy_s((*hashMessage) + firstSize, totalSize - firstSize, separator, separatorSize) != HC_SUCCESS) { + LOGE("Failed to copy separator!"); + result = HC_ERR_MEMORY_COPY; + break; + } + if (memcpy_s((*hashMessage) + firstSize + separatorSize, secondSize, second->val, secondSize) != HC_SUCCESS) { + LOGE("Failed to copy second!"); + result = HC_ERR_MEMORY_COPY; + } + } while (0); + if (result != HC_SUCCESS) { + HcFree(*hashMessage); + *hashMessage = NULL; + return result; + } + *messageSize = totalSize; + return HC_SUCCESS; +} + +int32_t GetHashResult(const uint8_t *info, uint32_t infoLen, char *hash, uint32_t hashLen) +{ + if (info == NULL) { + LOGE("The input info is NULL!"); + return HC_ERR_NULL_PTR; + } + Uint8Buff infoHash = { NULL, SHA256_LEN }; + Uint8Buff message = { NULL, infoLen }; + infoHash.val = (uint8_t *)HcMalloc(SHA256_LEN, 0); + if (infoHash.val == NULL) { + LOGE("Malloc infoHash.val failed."); + return HC_ERR_ALLOC_MEMORY; + } + message.val = (uint8_t *)HcMalloc(infoLen, 0); + if (message.val == NULL) { + LOGE("Malloc message.val failed."); + HcFree(infoHash.val); + return HC_ERR_ALLOC_MEMORY; + } + (void)memcpy_s(message.val, infoLen, info, infoLen); + const AlgLoader *loader = GetLoaderInstance(); + if (loader == NULL) { + LOGE("Failed to get AlgLoader instance!"); + HcFree(infoHash.val); + HcFree(message.val); + return HC_ERR_NOT_SUPPORT; + } + int32_t result = loader->sha256(&message, &infoHash); + HcFree(message.val); + if (result == HC_SUCCESS) { + if (ByteToHexString(infoHash.val, infoHash.length, hash, hashLen) != HC_SUCCESS) { + LOGE("Failed to convert bytes to string!"); + result = HC_HEX_CONVERT_FAILED; + } + } + HcFree(infoHash.val); + return result; +} + +int32_t CheckGroupNumLimit(int32_t groupType, const char *appId) +{ + if ((groupType == IDENTICAL_ACCOUNT_GROUP) && (IsIdenticalGroupExist())) { + LOGE("The identical account group already exists!"); + return HC_ERR_BEYOND_LIMIT; + } + if (GetGroupNumberByOwner(appId) >= HC_TRUST_GROUP_ENTRY_MAX_NUM) { + LOGE("The number of groups created by the service exceeds the maximum! [AppId]: %s", appId); + return HC_ERR_BEYOND_LIMIT; + } + return HC_SUCCESS; +} + +int32_t CheckDeviceNumLimit(const char *groupId, const char *peerUdid) +{ + /* + * If the peer device does not exist in the group and needs to be added, + * check whether the number of trusted devices exceeds the upper limit. + */ + if ((peerUdid != NULL) && (IsTrustedDeviceInGroup(groupId, peerUdid))) { + return HC_SUCCESS; + } + if (GetCurDeviceNumByGroupId(groupId) >= HC_TRUST_DEV_ENTRY_MAX_NUM) { + LOGE("The number of devices in the group has reached the upper limit!"); + return HC_ERR_BEYOND_LIMIT; + } + return HC_SUCCESS; +} + +bool IsUserTypeValid(int userType) +{ + if ((userType == DEVICE_TYPE_ACCESSORY) || + (userType == DEVICE_TYPE_CONTROLLER) || + (userType == DEVICE_TYPE_PROXY)) { + return true; + } + return false; +} + +bool IsExpireTimeValid(int expireTime) +{ + if ((expireTime < -1) || (expireTime == 0) || (expireTime > MAX_EXPIRE_TIME)) { + return false; + } + return true; +} + +bool IsGroupVisibilityValid(int groupVisibility) +{ + /* Currently, only the public group can be created. */ + if (groupVisibility == GROUP_VISIBILITY_PUBLIC) { + return true; + } + return false; +} + +int32_t CheckUserTypeIfExist(const CJson *jsonParams) +{ + int userType = DEVICE_TYPE_ACCESSORY; + (void)GetIntFromJson(jsonParams, FIELD_USER_TYPE, &userType); + if (!IsUserTypeValid(userType)) { + LOGE("The input userType is invalid! [UserType]: %d", userType); + return HC_ERR_INVALID_PARAMS; + } + return HC_SUCCESS; +} + +int32_t CheckGroupVisibilityIfExist(const CJson *jsonParams) +{ + int groupVisibility = GROUP_VISIBILITY_PUBLIC; + (void)GetIntFromJson(jsonParams, FIELD_GROUP_VISIBILITY, &groupVisibility); + if (!IsGroupVisibilityValid(groupVisibility)) { + LOGE("The input groupVisibility is invalid! [GroupVisibility]: %d", groupVisibility); + return HC_ERR_INVALID_PARAMS; + } + return HC_SUCCESS; +} + +int32_t CheckExpireTimeIfExist(const CJson *jsonParams) +{ + int expireTime = DEFAULT_EXPIRE_TIME; + (void)GetIntFromJson(jsonParams, FIELD_EXPIRE_TIME, &expireTime); + if (!IsExpireTimeValid(expireTime)) { + LOGE("Invalid group expire time! [ExpireTime]: %d", expireTime); + return HC_ERR_INVALID_PARAMS; + } + return HC_SUCCESS; +} + +int32_t AddGroupNameToParams(const char *groupName, GroupInfo *groupParams) +{ + if (!StringSetPointer(&groupParams->name, groupName)) { + LOGE("Failed to copy groupName!"); + return HC_ERR_MEMORY_COPY; + } + return HC_SUCCESS; +} + +int32_t AddGroupIdToParams(const char *groupId, GroupInfo *groupParams) +{ + if (!StringSetPointer(&groupParams->id, groupId)) { + LOGE("Failed to copy groupId!"); + return HC_ERR_MEMORY_COPY; + } + return HC_SUCCESS; +} + +int32_t AddGroupOwnerToParams(const char *owner, GroupInfo *groupParams) +{ + if (!StringSetPointer(&groupParams->ownerName, owner)) { + LOGE("Failed to copy groupOwner!"); + return HC_ERR_MEMORY_COPY; + } + return HC_SUCCESS; +} + +int32_t AddGroupTypeToParams(int groupType, GroupInfo *groupParams) +{ + groupParams->type = groupType; + return HC_SUCCESS; +} + +int32_t AddGroupVisibilityOrDefault(GroupInfo *groupParams) +{ + /* Currently, only the public group can be created. */ + groupParams->visibility = GROUP_VISIBILITY_PUBLIC; + return HC_SUCCESS; +} + +int32_t AddExpireTimeOrDefault(const CJson *jsonParams, GroupInfo *groupParams) +{ + int expireTime = DEFAULT_EXPIRE_TIME; + (void)GetIntFromJson(jsonParams, FIELD_EXPIRE_TIME, &expireTime); + groupParams->expireTime = expireTime; + return HC_SUCCESS; +} + +int32_t AddUdidToParams(DeviceInfo *devParams) +{ + uint8_t udid[INPUT_UDID_LEN] = { 0 }; + if (HcGetUdid(udid, INPUT_UDID_LEN) != HC_SUCCESS) { + LOGE("Get local udid failed"); + return HC_ERROR; + } + if (!StringSetPointer(&devParams->udid, (char *)udid)) { + LOGE("Failed to copy udid!"); + return HC_ERR_MEMORY_COPY; + } + return HC_SUCCESS; +} + +int32_t AddAuthIdToParamsOrDefault(const CJson *jsonParams, DeviceInfo *devParams) +{ + uint8_t udid[INPUT_UDID_LEN] = { 0 }; + const char *authId = GetStringFromJson(jsonParams, FIELD_DEVICE_ID); + if (authId == NULL) { + LOGD("No authId is found. The default value is udid!"); + if (HcGetUdid(udid, INPUT_UDID_LEN) != HC_SUCCESS) { + LOGE("Get local udid failed"); + return HC_ERROR; + } + authId = (const char *)udid; + } + if (!StringSetPointer(&devParams->authId, authId)) { + LOGE("Failed to copy authId!"); + return HC_ERR_MEMORY_COPY; + } + return HC_SUCCESS; +} + +int32_t AddUserTypeToParamsOrDefault(const CJson *jsonParams, DeviceInfo *devParams) +{ + int userType = DEVICE_TYPE_ACCESSORY; + (void)GetIntFromJson(jsonParams, FIELD_USER_TYPE, &userType); + devParams->devType = userType; + return HC_SUCCESS; +} + +int32_t AddServiceTypeToParams(const char *groupId, DeviceInfo *devParams) +{ + if (!StringSetPointer(&devParams->serviceType, groupId)) { + LOGE("Failed to copy authId!"); + return HC_ERR_MEMORY_COPY; + } + return HC_SUCCESS; +} + +int32_t AddGroupIdToDevParams(const char *groupId, DeviceInfo *devParams) +{ + if (!StringSetPointer(&devParams->groupId, groupId)) { + LOGE("Failed to copy groupId!"); + return HC_ERR_MEMORY_COPY; + } + return HC_SUCCESS; +} + +int32_t CheckGroupExist(const char *groupId) +{ + if (!IsGroupExistByGroupId(groupId)) { + LOGE("The group does not exist!"); + return HC_ERR_GROUP_NOT_EXIST; + } + return HC_SUCCESS; +} + +int32_t AddGroupToDatabaseByJson(int32_t (*generateGroupParams)(const CJson*, const char *, GroupInfo*), + const CJson *jsonParams, const char *groupId) +{ + GroupInfo *groupParams = CreateGroupInfoStruct(); + if (groupParams == NULL) { + LOGE("Failed to allocate groupParams memory!"); + return HC_ERR_ALLOC_MEMORY; + } + + int32_t result = (*generateGroupParams)(jsonParams, groupId, groupParams); + if (result != HC_SUCCESS) { + DestroyGroupInfoStruct(groupParams); + return result; + } + + result = AddGroup(groupParams); + DestroyGroupInfoStruct(groupParams); + if (result != HC_SUCCESS) { + LOGE("Failed to add the group to the database!"); + } + return result; +} + +int32_t AddDeviceToDatabaseByJson(int32_t (*generateDevParams)(const CJson*, const char*, DeviceInfo*), + const CJson *jsonParams, const char *groupId) +{ + DeviceInfo *devParams = CreateDeviceInfoStruct(); + if (devParams == NULL) { + LOGE("Failed to allocate devParams memory!"); + return HC_ERR_ALLOC_MEMORY; + } + + int32_t result = (*generateDevParams)(jsonParams, groupId, devParams); + if (result != HC_SUCCESS) { + DestroyDeviceInfoStruct(devParams); + return result; + } + + result = AddTrustedDevice(devParams, NULL); + DestroyDeviceInfoStruct(devParams); + if (result != HC_SUCCESS) { + LOGE("Failed to add the trust device to the database!"); + } + return result; +} + +int32_t DelGroupFromDatabase(const char *groupId) +{ + int32_t result = DelGroupByGroupId(groupId); + if (result != HC_SUCCESS) { + LOGE("Failed to delete group from database!"); + return result; + } + return HC_SUCCESS; +} + +int32_t ConvertGroupIdToJsonStr(const char *groupId, char **returnJsonStr) +{ + CJson *json = CreateJson(); + if (json == NULL) { + LOGE("Failed to allocate json memory!"); + return HC_ERR_ALLOC_MEMORY; + } + if (AddStringToJson(json, FIELD_GROUP_ID, groupId) != HC_SUCCESS) { + LOGE("Failed to add groupId to json!"); + FreeJson(json); + return HC_ERR_JSON_FAIL; + } + *returnJsonStr = PackJsonToString(json); + FreeJson(json); + if (*returnJsonStr == NULL) { + LOGE("Failed to convert json to string!"); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} + +int32_t GenerateBindSuccessData(const char *peerAuthId, const char *groupId, char **returnDataStr) +{ + CJson *jsonData = CreateJson(); + if (jsonData == NULL) { + LOGE("Failed to allocate jsonData memory!"); + return HC_ERR_JSON_FAIL; + } + if (AddStringToJson(jsonData, FIELD_GROUP_ID, groupId) != HC_SUCCESS) { + LOGE("Failed to add groupId to jsonData!"); + FreeJson(jsonData); + return HC_ERR_JSON_FAIL; + } + if (AddStringToJson(jsonData, FIELD_ADD_ID, peerAuthId) != HC_SUCCESS) { + LOGE("Failed to add addId to jsonData!"); + FreeJson(jsonData); + return HC_ERR_JSON_FAIL; + } + char *jsonDataStr = PackJsonToString(jsonData); + FreeJson(jsonData); + if (jsonDataStr == NULL) { + LOGE("An error occurred when converting JSON data to String data!"); + return HC_ERR_JSON_FAIL; + } + *returnDataStr = jsonDataStr; + return HC_SUCCESS; +} + +int32_t GenerateUnbindSuccessData(const char *peerAuthId, const char *groupId, char **returnDataStr) +{ + CJson *jsonData = CreateJson(); + if (jsonData == NULL) { + LOGE("Failed to allocate jsonData memory!"); + return HC_ERR_JSON_FAIL; + } + if (AddStringToJson(jsonData, FIELD_GROUP_ID, groupId) != HC_SUCCESS) { + LOGE("Failed to add groupId to jsonData!"); + FreeJson(jsonData); + return HC_ERR_JSON_FAIL; + } + if (AddStringToJson(jsonData, FIELD_DELETE_ID, peerAuthId) != HC_SUCCESS) { + LOGE("Failed to add deleteId to jsonData!"); + FreeJson(jsonData); + return HC_ERR_JSON_FAIL; + } + char *jsonDataStr = PackJsonToString(jsonData); + FreeJson(jsonData); + if (jsonDataStr == NULL) { + LOGE("An error occurred when converting JSON data to String data!"); + return HC_ERR_JSON_FAIL; + } + *returnDataStr = jsonDataStr; + return HC_SUCCESS; +} + +int32_t ProcessKeyPair(int action, const CJson *jsonParams, const char *groupId) +{ + uint8_t udid[INPUT_UDID_LEN] = { 0 }; + /* Use the DeviceGroupManager package name. */ + const char *appId = GROUP_MANAGER_PACKAGE_NAME; + const char *authId = GetStringFromJson(jsonParams, FIELD_DEVICE_ID); + if (authId == NULL) { + LOGD("No authId is found. The default value is udid!"); + if (HcGetUdid(udid, INPUT_UDID_LEN) != HC_SUCCESS) { + LOGE("Get local udid failed"); + return HC_ERROR; + } + authId = (const char *)udid; + } + int userType = DEVICE_TYPE_ACCESSORY; + (void)GetIntFromJson(jsonParams, FIELD_USER_TYPE, &userType); + Uint8Buff authIdBuff = { 0, 0 }; + authIdBuff.length = HcStrlen(authId); + authIdBuff.val = (uint8_t *)HcMalloc(authIdBuff.length, 0); + if (authIdBuff.val == NULL) { + LOGE("Failed to allocate authIdBuff memory!"); + return HC_ERR_ALLOC_MEMORY; + } + if (memcpy_s(authIdBuff.val, authIdBuff.length, authId, authIdBuff.length) != HC_SUCCESS) { + LOGE("Failed to copy authId!"); + HcFree(authIdBuff.val); + return HC_ERR_MEMORY_COPY; + } + int32_t result; + if (action == CREATE_KEY_PAIR) { + LOGI("Start to register identity! [GroupId]: %s, [UserType]: %d", groupId, userType); + result = RegisterLocalIdentity(appId, groupId, &authIdBuff, userType, DAS_MODULE); + } else { + LOGI("Start to deregister identity! [GroupId]: %s, [UserType]: %d", groupId, userType); + result = UnregisterLocalIdentity(appId, groupId, &authIdBuff, userType, DAS_MODULE); + } + HcFree(authIdBuff.val); + return result; +} + +int32_t DeletePeerKeyIfForceUnbind(const char *groupId, const char *peerAuthId, int32_t peerUserType) +{ + /* Use the DeviceGroupManager package name. */ + const char *appId = GROUP_MANAGER_PACKAGE_NAME; + Uint8Buff peerAuthIdBuff = { + .val = (uint8_t *)peerAuthId, + .length = HcStrlen(peerAuthId) + }; + return DeletePeerAuthInfo(appId, groupId, &peerAuthIdBuff, peerUserType, DAS_MODULE); +} + +int32_t GetGroupTypeFromDb(const char *groupId, int *returnGroupType) +{ + GroupInfo *groupEntry = CreateGroupInfoStruct(); + if (groupEntry == NULL) { + LOGE("Failed to allocate groupEntry memory!"); + return HC_ERR_ALLOC_MEMORY; + } + if (GetGroupEntryByGroupId(groupId, groupEntry) != HC_SUCCESS) { + LOGE("Failed to get groupEntry from database!"); + DestroyGroupInfoStruct(groupEntry); + return HC_ERR_DB; + } + *returnGroupType = groupEntry->type; + DestroyGroupInfoStruct(groupEntry); + return HC_SUCCESS; +} + +int32_t CheckPermForGroup(int actionType, const char *callerPkgName, const char *groupId) +{ + if (((actionType == GROUP_DISBAND) && (IsGroupOwner(groupId, callerPkgName))) || + ((actionType == MEMBER_INVITE) && (IsGroupEditAllowed(groupId, callerPkgName))) || + ((actionType == MEMBER_DELETE) && (IsGroupEditAllowed(groupId, callerPkgName)))) { + return HC_SUCCESS; + } + LOGE("You do not have the right to execute the command!"); + return HC_ERR_ACCESS_DENIED; +} \ No newline at end of file diff --git a/services/group_manager/src/group_manager/group_manager.c b/services/group_manager/src/group_manager/group_manager.c new file mode 100644 index 0000000..76a116a --- /dev/null +++ b/services/group_manager/src/group_manager/group_manager.c @@ -0,0 +1,929 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "group_manager.h" +#include "account_related_group_manager.h" +#include "account_unrelated_group_manager.h" +#include "broadcast_manager.h" +#include "database_manager.h" +#include "hc_log.h" + +DECLARE_HC_VECTOR(GmCallbackEntryVec, CallbackEntry) +IMPLEMENT_HC_VECTOR(GmCallbackEntryVec, CallbackEntry, 1) +static GmCallbackEntryVec g_callbackVec; + +static bool IsGroupTypeSupported(int groupType) +{ + if (((groupType == PEER_TO_PEER_GROUP) && (IsAccountUnrelatedGroupTypeSupported(groupType))) || + ((groupType == IDENTICAL_ACCOUNT_GROUP) && (IsAccountRelatedGroupTypeSupported(groupType))) || + ((groupType == ACROSS_ACCOUNT_AUTHORIZE_GROUP) && (IsAccountRelatedGroupTypeSupported(groupType)))) { + return true; + } + return false; +} + +static int32_t UpdateCallbackIfExist(const char *appId, const DeviceAuthCallback *callback) +{ + uint32_t index; + CallbackEntry *entry = NULL; + FOR_EACH_HC_VECTOR(g_callbackVec, index, entry) { + if ((entry != NULL) && (strcmp(entry->appId, appId) == 0)) { + if (memcpy_s(entry->callback, sizeof(DeviceAuthCallback), + callback, sizeof(DeviceAuthCallback)) != HC_SUCCESS) { + LOGE("Failed to copy service callback!"); + return HC_ERR_MEMORY_COPY; + } + return HC_SUCCESS; + } + } + return HC_ERR_CALLBACK_NOT_FOUND; +} + +static int32_t AddCallbackIfNotExist(const char *appId, const DeviceAuthCallback *callback) +{ + uint32_t appIdLen = HcStrlen(appId) + 1; + char *copyAppId = (char *)HcMalloc(appIdLen, 0); + if (copyAppId == NULL) { + LOGE("Failed to allocate copyAppId memory!"); + return HC_ERR_ALLOC_MEMORY; + } + if (strcpy_s(copyAppId, appIdLen, appId) != HC_SUCCESS) { + LOGE("Failed to copy appId!"); + HcFree(copyAppId); + return HC_ERR_MEMORY_COPY; + } + DeviceAuthCallback *copyCallback = (DeviceAuthCallback *)HcMalloc(sizeof(DeviceAuthCallback), 0); + if (copyCallback == NULL) { + LOGE("Failed to allocate copyCallback memory!"); + HcFree(copyAppId); + return HC_ERR_ALLOC_MEMORY; + } + if (memcpy_s(copyCallback, sizeof(DeviceAuthCallback), + callback, sizeof(DeviceAuthCallback)) != HC_SUCCESS) { + LOGE("Failed to copy service callback!"); + HcFree(copyAppId); + HcFree(copyCallback); + return HC_ERR_MEMORY_COPY; + } + CallbackEntry entry; + entry.appId = copyAppId; + entry.callback = copyCallback; + g_callbackVec.pushBack(&g_callbackVec, &entry); + LOGI("[End]: Service register GM callback successfully!"); + return HC_SUCCESS; +} + +static int32_t AddGroupNameToReturn(const GroupInfo *groupEntry, CJson *json) +{ + const char *groupName = StringGet(&groupEntry->name); + if (AddStringToJson(json, FIELD_GROUP_NAME, groupName) != HC_SUCCESS) { + LOGE("Failed to add groupName to json!"); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} + +static int32_t AddGroupIdToReturn(const GroupInfo *groupEntry, CJson *json) +{ + const char *groupId = StringGet(&groupEntry->id); + if (AddStringToJson(json, FIELD_GROUP_ID, groupId) != HC_SUCCESS) { + LOGE("Failed to add groupId to json!"); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} + +static int32_t AddGroupOwnerToReturn(const GroupInfo *groupEntry, CJson *json) +{ + const char *ownerName = StringGet(&groupEntry->ownerName); + if (AddStringToJson(json, FIELD_GROUP_OWNER, ownerName) != HC_SUCCESS) { + LOGE("Failed to add groupOwner to json!"); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} + +static int32_t AddGroupTypeToReturn(const GroupInfo *groupEntry, CJson *json) +{ + int32_t groupType = groupEntry->type; + if (AddIntToJson(json, FIELD_GROUP_TYPE, groupType) != HC_SUCCESS) { + LOGE("Failed to add groupType to json!"); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} + +static int32_t AddGroupVisibilityToReturn(const GroupInfo *groupEntry, CJson *json) +{ + int groupVisibility = groupEntry->visibility; + if (AddIntToJson(json, FIELD_GROUP_VISIBILITY, groupVisibility) != HC_SUCCESS) { + LOGE("Failed to add groupType to json!"); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} + +static int32_t AddUdidToReturn(const DeviceInfo *devEntry, CJson *json) +{ + const char *udid = StringGet(&devEntry->udid); + if (AddStringToJson(json, FIELD_PEER_UDID, udid) != HC_SUCCESS) { + LOGE("Failed to add udid to json!"); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} + +static int32_t AddAuthIdToReturn(const DeviceInfo *devEntry, CJson *json) +{ + const char *authId = StringGet(&devEntry->authId); + if (AddStringToJson(json, FIELD_AUTH_ID, authId) != HC_SUCCESS) { + LOGE("Failed to add authId to json!"); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} + +static int32_t AddUserIdToReturn(const DeviceInfo *devEntry, CJson *json) +{ + int64_t userId = devEntry->userId; + if (AddByteToJson(json, FIELD_USER_ID, (uint8_t*)&userId, sizeof(int64_t)) != HC_SUCCESS) { + LOGE("Failed to add userId to json!"); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} + +static int32_t AddCredentialTypeToReturn(const DeviceInfo *devEntry, CJson *json) +{ + int credentialType = devEntry->credential; + if (AddIntToJson(json, FIELD_CREDENTIAL_TYPE, credentialType) != HC_SUCCESS) { + LOGE("Failed to add credentialType to json!"); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} + +static int32_t AddUserTypeToReturn(const DeviceInfo *devEntry, CJson *json) +{ + int userType = devEntry->devType; + if (AddIntToJson(json, FIELD_USER_TYPE, userType) != HC_SUCCESS) { + LOGE("Failed to add userType to json!"); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} + +static int32_t GenerateReturnGroupInfo(const GroupInfo *groupEntry, CJson *returnJson) +{ + int32_t result; + if (((result = AddGroupNameToReturn(groupEntry, returnJson)) != HC_SUCCESS) || + ((result = AddGroupIdToReturn(groupEntry, returnJson)) != HC_SUCCESS) || + ((result = AddGroupOwnerToReturn(groupEntry, returnJson)) != HC_SUCCESS) || + ((result = AddGroupTypeToReturn(groupEntry, returnJson)) != HC_SUCCESS) || + ((result = AddGroupVisibilityToReturn(groupEntry, returnJson)) != HC_SUCCESS)) { + return result; + } + return HC_SUCCESS; +} + +static int32_t GenerateReturnDevInfo(const DeviceInfo *devEntry, CJson *returnJson) +{ + int32_t result; + if (((result = AddUdidToReturn(devEntry, returnJson)) != HC_SUCCESS) || + ((result = AddAuthIdToReturn(devEntry, returnJson)) != HC_SUCCESS) || + ((result = AddUserIdToReturn(devEntry, returnJson)) != HC_SUCCESS) || + ((result = AddCredentialTypeToReturn(devEntry, returnJson)) != HC_SUCCESS) || + ((result = AddUserTypeToReturn(devEntry, returnJson)) != HC_SUCCESS)) { + return result; + } + return HC_SUCCESS; +} + +static void RemoveNoPermissionGroup(GroupInfoVec *groupEntryVec, const char *appId) +{ + uint32_t index = 0; + void **groupEntryPtr = NULL; + while (index < groupEntryVec->size(groupEntryVec)) { + groupEntryPtr = groupEntryVec->getp(groupEntryVec, index); + if ((groupEntryPtr == NULL) || (*groupEntryPtr == NULL)) { + index++; + continue; + } + GroupInfo *groupEntry = (GroupInfo *)(*groupEntryPtr); + if (IsGroupAccessible(StringGet(&groupEntry->id), appId)) { + index++; + continue; + } + void *tempEntry = NULL; + HC_VECTOR_POPELEMENT(groupEntryVec, &tempEntry, index); + LOGI("Pop a no permission group from vector!"); + } +} + +static int32_t GenerateReturnEmptyArrayStr(char **returnVec) +{ + CJson *json = CreateJsonArray(); + if (json == NULL) { + LOGE("Failed to allocate json memory!"); + return HC_ERR_JSON_FAIL; + } + *returnVec = PackJsonToString(json); + FreeJson(json); + if (*returnVec == NULL) { + LOGE("Failed to convert json to string!"); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} + +static int32_t GenerateReturnGroupVec(GroupInfoVec *groupEntryVec, char **returnGroupVec, uint32_t *groupNum) +{ + if (HC_VECTOR_SIZE(groupEntryVec) == 0) { + LOGI("No group is found based on the query parameters!"); + *groupNum = 0; + return GenerateReturnEmptyArrayStr(returnGroupVec); + } + + CJson *json = CreateJsonArray(); + if (json == NULL) { + LOGE("Failed to allocate json memory!"); + return HC_ERR_JSON_FAIL; + } + uint32_t groupCount = 0; + uint32_t index; + void **groupEntryPtr = NULL; + FOR_EACH_HC_VECTOR(*groupEntryVec, index, groupEntryPtr) { + if ((groupEntryPtr != NULL) && ((*groupEntryPtr) != NULL)) { + GroupInfo *groupEntry = (GroupInfo*)(*groupEntryPtr); + CJson *groupInfoJson = CreateJson(); + if (groupInfoJson == NULL) { + LOGE("Failed to allocate groupInfoJson memory!"); + FreeJson(json); + return HC_ERR_ALLOC_MEMORY; + } + int32_t result = GenerateReturnGroupInfo(groupEntry, groupInfoJson); + if (result != HC_SUCCESS) { + FreeJson(groupInfoJson); + FreeJson(json); + return result; + } + if (AddObjToArray(json, groupInfoJson) != HC_SUCCESS) { + LOGE("Failed to add groupInfoStr to returnGroupVec!"); + FreeJson(groupInfoJson); + FreeJson(json); + return HC_ERR_JSON_FAIL; + } + ++groupCount; + } + } + *returnGroupVec = PackJsonToString(json); + FreeJson(json); + if ((*returnGroupVec) == NULL) { + LOGE("Failed to convert json to string!"); + return HC_ERR_JSON_FAIL; + } + *groupNum = groupCount; + return HC_SUCCESS; +} + +static int32_t GenerateReturnDeviceVec(DeviceInfoVec *devEntryVec, char **returnDevInfoVec, uint32_t *deviceNum) +{ + if (HC_VECTOR_SIZE(devEntryVec) == 0) { + LOGI("No device is found based on the query parameters!"); + *deviceNum = 0; + return GenerateReturnEmptyArrayStr(returnDevInfoVec); + } + + CJson *json = CreateJsonArray(); + if (json == NULL) { + LOGE("Failed to allocate json memory!"); + return HC_ERR_JSON_FAIL; + } + uint32_t devCount = 0; + uint32_t index; + void **devEntryPtr = NULL; + FOR_EACH_HC_VECTOR(*devEntryVec, index, devEntryPtr) { + if ((devEntryPtr != NULL) && ((*devEntryPtr) != NULL)) { + DeviceInfo *devEntry = (DeviceInfo*)(*devEntryPtr); + CJson *devInfoJson = CreateJson(); + if (devInfoJson == NULL) { + LOGE("Failed to allocate devInfoJson memory!"); + FreeJson(json); + return HC_ERR_ALLOC_MEMORY; + } + int32_t result = GenerateReturnDevInfo(devEntry, devInfoJson); + if (result != HC_SUCCESS) { + FreeJson(devInfoJson); + FreeJson(json); + return result; + } + if (AddObjToArray(json, devInfoJson) != HC_SUCCESS) { + LOGE("Failed to add devInfoStr to returnGroupVec!"); + FreeJson(devInfoJson); + FreeJson(json); + return HC_ERR_JSON_FAIL; + } + ++devCount; + } + } + *returnDevInfoVec = PackJsonToString(json); + FreeJson(json); + if ((*returnDevInfoVec) == NULL) { + LOGE("Failed to convert json to string!"); + return HC_ERR_JSON_FAIL; + } + *deviceNum = devCount; + return HC_SUCCESS; +} + +static bool IsQueryParamsValid(int groupType, const char *groupId, const char *groupName, const char *groupOwner) +{ + if ((groupType == ALL_GROUP) && (groupId == NULL) && (groupName == NULL) && (groupOwner == NULL)) { + return false; + } else { + return true; + } +} + +static const DeviceAuthCallback *GetGmCallbackByAppId(const char *appId) +{ + uint32_t index; + CallbackEntry *entry = NULL; + FOR_EACH_HC_VECTOR(g_callbackVec, index, entry) { + if (strcmp(entry->appId, appId) == 0) { + return entry->callback; + } + } + return NULL; +} + +static int32_t RegGroupManagerCallback(const char *appId, const DeviceAuthCallback *callback) +{ + if ((appId == NULL) || (callback == NULL)) { + LOGE("The input appId or callback is NULL!"); + return HC_ERR_INVALID_PARAMS; + } + if (UpdateCallbackIfExist(appId, callback) == HC_SUCCESS) { + LOGI("[End]: The callback associated with the appId already exists, so we update the callback!"); + return HC_SUCCESS; + } + return AddCallbackIfNotExist(appId, callback); +} + +static int32_t UnRegGroupManagerCallback(const char *appId) +{ + if (appId == NULL) { + LOGE("The input appId is NULL!"); + return HC_ERR_INVALID_PARAMS; + } + uint32_t index; + CallbackEntry *entry = NULL; + FOR_EACH_HC_VECTOR(g_callbackVec, index, entry) { + if (strcmp(entry->appId, appId) == 0) { + HcFree(entry->appId); + HcFree(entry->callback); + CallbackEntry tempEntry; + HC_VECTOR_POPELEMENT(&g_callbackVec, &tempEntry, index); + LOGI("[End]: Service deregister GM callback successfully!"); + return HC_SUCCESS; + } + } + LOGI("[End]: Although the callback does not exist, we still believe it is correct to deregister the callback!"); + return HC_SUCCESS; +} + +static void CreatePeerToPeerGroup(int64_t requestId, CJson *jsonParams, const DeviceAuthCallback *callback) +{ + if (!IsAccountUnrelatedGroupManagerSupported()) { + LOGE("All non-account groups are not supported!"); + return; + } + AccountUnrelatedGroupManager *instance = GetAccountUnrelatedGroupManager(); + if (instance == NULL) { + LOGE("Failed to get AccountUnrelatedGroupManager instance!"); + return; + } + instance->createPeerToPeerGroup(requestId, jsonParams, callback); +} + +static void DeletePeerToPeerGroup(int64_t requestId, CJson *jsonParams, const DeviceAuthCallback *callback) +{ + if (!IsAccountUnrelatedGroupManagerSupported()) { + LOGE("All non-account groups are not supported!"); + return; + } + AccountUnrelatedGroupManager *instance = GetAccountUnrelatedGroupManager(); + if (instance == NULL) { + LOGE("Failed to get AccountUnrelatedGroupManager instance!"); + return; + } + instance->deletePeerToPeerGroup(requestId, jsonParams, callback); +} + +static void AddMemberToPeerToPeerGroup(int64_t requestId, CJson *jsonParams, const DeviceAuthCallback *callback) +{ + if (!IsAccountUnrelatedGroupManagerSupported()) { + LOGE("All non-account groups are not supported!"); + return; + } + AccountUnrelatedGroupManager *instance = GetAccountUnrelatedGroupManager(); + if (instance == NULL) { + LOGE("Failed to get AccountUnrelatedGroupManager instance!"); + return; + } + instance->addMemberToPeerToPeerGroup(requestId, jsonParams, callback); +} + +static void DeleteMemberFromPeerToPeerGroup(int64_t requestId, CJson *jsonParams, const DeviceAuthCallback *callback) +{ + if (!IsAccountUnrelatedGroupManagerSupported()) { + LOGE("All non-account groups are not supported!"); + return; + } + AccountUnrelatedGroupManager *instance = GetAccountUnrelatedGroupManager(); + if (instance == NULL) { + LOGE("Failed to get AccountUnrelatedGroupManager instance!"); + return; + } + instance->deleteMemberFromPeerToPeerGroup(requestId, jsonParams, callback); +} + +static void ProcessBindData(int64_t requestId, CJson *jsonParams, const DeviceAuthCallback *callback) +{ + if (!IsAccountUnrelatedGroupManagerSupported()) { + LOGE("All non-account groups are not supported!"); + return; + } + AccountUnrelatedGroupManager *instance = GetAccountUnrelatedGroupManager(); + if (instance == NULL) { + LOGE("Failed to get AccountUnrelatedGroupManager instance!"); + return; + } + instance->processBindData(requestId, jsonParams, callback); +} + +static int32_t AddGroupRole(bool isManager, const char *appId, const char *groupId, const char *roleAppId) +{ + if (!IsAccountUnrelatedGroupManagerSupported()) { + LOGE("All non-account groups are not supported!"); + return HC_ERR_NOT_SUPPORT; + } + AccountUnrelatedGroupManager *instance = GetAccountUnrelatedGroupManager(); + if (instance == NULL) { + LOGE("Failed to get AccountUnrelatedGroupManager instance!"); + return HC_ERR_NULL_PTR; + } + return instance->addGroupRole(isManager, appId, groupId, roleAppId); +} + +static int32_t DeleteGroupRole(bool isManager, const char *appId, const char *groupId, const char *roleAppId) +{ + if (!IsAccountUnrelatedGroupManagerSupported()) { + LOGE("All non-account groups are not supported!"); + return HC_ERR_NOT_SUPPORT; + } + AccountUnrelatedGroupManager *instance = GetAccountUnrelatedGroupManager(); + if (instance == NULL) { + LOGE("Failed to get AccountUnrelatedGroupManager instance!"); + return HC_ERR_NULL_PTR; + } + return instance->deleteGroupRole(isManager, appId, groupId, roleAppId); +} + +static int32_t GetGroupRole(bool isManager, const char *appId, const char *groupId, char **returnJsonStr, + uint32_t *returnSize) +{ + if (!IsAccountUnrelatedGroupManagerSupported()) { + LOGE("All non-account groups are not supported!"); + return HC_ERR_NOT_SUPPORT; + } + AccountUnrelatedGroupManager *instance = GetAccountUnrelatedGroupManager(); + if (instance == NULL) { + LOGE("Failed to get AccountUnrelatedGroupManager instance!"); + return HC_ERR_NULL_PTR; + } + return instance->getGroupRole(isManager, appId, groupId, returnJsonStr, returnSize); +} + +static int32_t SyncCreateIdenticalAccountGroup(const CJson *jsonParams, char **returnDataStr) +{ + if (!IsAccountRelatedGroupManagerSupported()) { + LOGE("All account groups are not supported!"); + return HC_ERR_NOT_SUPPORT; + } + AccountRelatedGroupManager *instance = GetAccountRelatedGroupManager(); + if (instance == NULL) { + LOGE("Failed to get AccountRelatedGroupManager instance!"); + return HC_ERR_NULL_PTR; + } + return instance->syncCreateIdenticalAccountGroup(jsonParams, returnDataStr); +} + +static int32_t SyncDeleteIdenticalAccountGroup(const CJson *jsonParams) +{ + if (!IsAccountRelatedGroupManagerSupported()) { + LOGE("All account groups are not supported!"); + return HC_ERR_NOT_SUPPORT; + } + AccountRelatedGroupManager *instance = GetAccountRelatedGroupManager(); + if (instance == NULL) { + LOGE("Failed to get AccountRelatedGroupManager instance!"); + return HC_ERR_NULL_PTR; + } + return instance->syncDeleteIdenticalAccountGroup(jsonParams); +} + +static int32_t GetRegisterInfo(char **returnRegisterInfo) +{ + if (!IsAccountRelatedGroupManagerSupported()) { + LOGE("All account groups are not supported!"); + return HC_ERR_NOT_SUPPORT; + } + AccountRelatedGroupManager *instance = GetAccountRelatedGroupManager(); + if (instance == NULL) { + LOGE("Failed to get AccountRelatedGroupManager instance!"); + return HC_ERR_NULL_PTR; + } + return instance->getRegisterInfo(returnRegisterInfo); +} + +static int32_t ProcessCredential(int operationCode, const char *reqJsonStr, char **returnJsonStr) +{ + if (!IsAccountRelatedGroupManagerSupported()) { + LOGE("All account groups are not supported!"); + return HC_ERR_NOT_SUPPORT; + } + AccountRelatedGroupManager *instance = GetAccountRelatedGroupManager(); + if (instance == NULL) { + LOGE("Failed to get AccountRelatedGroupManager instance!"); + return HC_ERR_NULL_PTR; + } + return instance->processCredential(operationCode, reqJsonStr, returnJsonStr); +} + +static int32_t RegListener(const char *appId, const DataChangeListener *listener) +{ + if ((appId == NULL) || (listener == NULL)) { + LOGE("The input parameter contains NULL value!"); + return HC_ERR_INVALID_PARAMS; + } + if (!IsBroadcastSupported()) { + LOGE("Broadcast not supported!"); + return HC_ERR_NOT_SUPPORT; + } + return AddListener(appId, listener); +} + +static int32_t UnRegListener(const char *appId) +{ + if (appId == NULL) { + LOGE("The input appId is NULL!"); + return HC_ERR_INVALID_PARAMS; + } + if (!IsBroadcastSupported()) { + LOGE("Broadcast not supported!"); + return HC_ERR_NOT_SUPPORT; + } + return RemoveListener(appId); +} + +static int32_t GetAccessibleGroupInfoById(const char *appId, const char *groupId, char **returnGroupInfo) +{ + if ((appId == NULL) || (groupId == NULL)) { + LOGE("The input appId or groupId is NULL!"); + return HC_ERR_INVALID_PARAMS; + } + if (!IsGroupExistByGroupId(groupId)) { + LOGE("No group is found based on the query parameters!"); + return HC_ERR_GROUP_NOT_EXIST; + } + if (!IsGroupAccessible(groupId, appId)) { + LOGE("You do not have the permission to query the group information!"); + return HC_ERR_ACCESS_DENIED; + } + GroupInfo *groupEntry = CreateGroupInfoStruct(); + if (groupEntry == NULL) { + LOGE("Failed to allocate groupInfo memory!"); + return HC_ERR_ALLOC_MEMORY; + } + if (GetGroupEntryByGroupId(groupId, groupEntry) != HC_SUCCESS) { + LOGE("Failed to obtain the group information from the database!"); + DestroyGroupInfoStruct(groupEntry); + return HC_ERR_DB; + } + CJson *groupInfoJson = CreateJson(); + if (groupInfoJson == NULL) { + LOGE("Failed to allocate groupInfoJson memory!"); + DestroyGroupInfoStruct(groupEntry); + return HC_ERR_JSON_FAIL; + } + int32_t result = GenerateReturnGroupInfo(groupEntry, groupInfoJson); + DestroyGroupInfoStruct(groupEntry); + if (result != HC_SUCCESS) { + FreeJson(groupInfoJson); + return result; + } + *returnGroupInfo = PackJsonToString(groupInfoJson); + FreeJson(groupInfoJson); + if (*returnGroupInfo == NULL) { + LOGE("Failed to convert json to string!"); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} + +static int32_t GetAccessibleGroupInfo(const char *appId, const char *queryParams, char **returnGroupVec, + uint32_t *groupNum) +{ + if ((appId == NULL) || (queryParams == NULL)) { + LOGE("The input appId or queryParams is NULL!"); + return HC_ERR_INVALID_PARAMS; + } + CJson *queryParamsJson = CreateJsonFromString(queryParams); + if (queryParamsJson == NULL) { + LOGE("Failed to create queryParamsJson from string!"); + return HC_ERR_JSON_FAIL; + } + int32_t groupType = ALL_GROUP; + (void)GetIntFromJson(queryParamsJson, FIELD_GROUP_TYPE, &groupType); + if ((groupType != ALL_GROUP) && (!IsGroupTypeSupported(groupType))) { + LOGE("Invalid group type!"); + FreeJson(queryParamsJson); + return HC_ERR_INVALID_PARAMS; + } + const char *groupId = GetStringFromJson(queryParamsJson, FIELD_GROUP_ID); + const char *groupName = GetStringFromJson(queryParamsJson, FIELD_GROUP_NAME); + const char *groupOwner = GetStringFromJson(queryParamsJson, FIELD_GROUP_OWNER); + if (!IsQueryParamsValid(groupType, groupId, groupName, groupOwner)) { + LOGE("The query parameters cannot be all null!"); + FreeJson(queryParamsJson); + return HC_ERR_INVALID_PARAMS; + } + GroupInfoVec groupInfoVec; + CreateGroupInfoVecStruct(&groupInfoVec); + int32_t result = GetGroupInfo(groupType, groupId, groupName, groupOwner, &groupInfoVec); + FreeJson(queryParamsJson); + if (result != HC_SUCCESS) { + DestroyGroupInfoVecStruct(&groupInfoVec); + return result; + } + RemoveNoPermissionGroup(&groupInfoVec, appId); + result = GenerateReturnGroupVec(&groupInfoVec, returnGroupVec, groupNum); + DestroyGroupInfoVecStruct(&groupInfoVec); + return result; +} + +static int32_t GetAccessibleJoinedGroups(const char *appId, int groupType, char **returnGroupVec, uint32_t *groupNum) +{ + if (appId == NULL) { + LOGE("The input appId is NULL!"); + return HC_ERR_INVALID_PARAMS; + } + if (!IsGroupTypeSupported(groupType)) { + LOGE("Invalid group type!"); + return HC_ERR_INVALID_PARAMS; + } + GroupInfoVec groupInfoVec; + CreateGroupInfoVecStruct(&groupInfoVec); + int32_t result = GetJoinedGroups(groupType, &groupInfoVec); + if (result != HC_SUCCESS) { + DestroyGroupInfoVecStruct(&groupInfoVec); + return result; + } + RemoveNoPermissionGroup(&groupInfoVec, appId); + result = GenerateReturnGroupVec(&groupInfoVec, returnGroupVec, groupNum); + DestroyGroupInfoVecStruct(&groupInfoVec); + return result; +} + +static int32_t GetAccessibleRelatedGroups(const char *appId, const char *peerDeviceId, + char **returnGroupVec, uint32_t *groupNum) +{ + if ((appId == NULL) || (peerDeviceId == NULL)) { + LOGE("The input appId or peerUdid is NULL!"); + return HC_ERR_INVALID_PARAMS; + } + LOGI("Start to get related groups! [AppId]: %s", appId); + GroupInfoVec groupInfoVec; + CreateGroupInfoVecStruct(&groupInfoVec); + int32_t result = GetRelatedGroups(peerDeviceId, &groupInfoVec); + if (result != HC_SUCCESS) { + DestroyGroupInfoVecStruct(&groupInfoVec); + return result; + } + RemoveNoPermissionGroup(&groupInfoVec, appId); + result = GenerateReturnGroupVec(&groupInfoVec, returnGroupVec, groupNum); + DestroyGroupInfoVecStruct(&groupInfoVec); + return result; +} + +static int32_t GetAccessibleDeviceInfoById(const char *appId, const char *deviceId, + const char *groupId, char **returnDeviceInfo) +{ + if ((appId == NULL) || (deviceId == NULL) || (groupId == NULL)) { + LOGE("The input parameters contains NULL value!"); + return HC_ERR_INVALID_PARAMS; + } + if (!IsGroupExistByGroupId(groupId)) { + LOGE("No group is found based on the query parameters!"); + return HC_ERR_GROUP_NOT_EXIST; + } + if (!IsGroupAccessible(groupId, appId)) { + LOGE("You do not have the permission to query the group information!"); + return HC_ERR_ACCESS_DENIED; + } + DeviceInfo *devInfo = CreateDeviceInfoStruct(); + if (devInfo == NULL) { + LOGE("Failed to allocate devInfo memory!"); + return HC_ERR_ALLOC_MEMORY; + } + if (GetDeviceInfoByAuthId(deviceId, groupId, devInfo) != HC_SUCCESS) { + LOGE("No device is found based on the query parameters!"); + DestroyDeviceInfoStruct(devInfo); + return HC_ERR_DEVICE_NOT_EXIST; + } + CJson *devInfoJson = CreateJson(); + if (devInfoJson == NULL) { + LOGE("Failed to allocate devInfoJson memory!"); + DestroyDeviceInfoStruct(devInfo); + return HC_ERR_JSON_FAIL; + } + int32_t result = GenerateReturnDevInfo(devInfo, devInfoJson); + DestroyDeviceInfoStruct(devInfo); + if (result != HC_SUCCESS) { + FreeJson(devInfoJson); + return result; + } + *returnDeviceInfo = PackJsonToString(devInfoJson); + FreeJson(devInfoJson); + if (*returnDeviceInfo == NULL) { + LOGE("Failed to convert json to string!"); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} + +static int32_t GetAccessibleTrustedDevices(const char *appId, const char *groupId, + char **returnDevInfoVec, uint32_t *deviceNum) +{ + if ((appId == NULL) || (groupId == NULL)) { + LOGE("The input appId or groupId is NULL!"); + return HC_ERR_INVALID_PARAMS; + } + if (!IsGroupExistByGroupId(groupId)) { + LOGE("No group is found based on the query parameters!"); + return HC_ERR_GROUP_NOT_EXIST; + } + if (!IsGroupAccessible(groupId, appId)) { + LOGE("You do not have the permission to query the group information!"); + return HC_ERR_ACCESS_DENIED; + } + DeviceInfoVec deviceInfoVec; + CreateDeviceInfoVecStruct(&deviceInfoVec); + int32_t result = GetTrustedDevices(groupId, &deviceInfoVec); + if (result != HC_SUCCESS) { + DestroyDeviceInfoVecStruct(&deviceInfoVec); + return result; + } + result = GenerateReturnDeviceVec(&deviceInfoVec, returnDevInfoVec, deviceNum); + DestroyDeviceInfoVecStruct(&deviceInfoVec); + return result; +} + +static bool IsDeviceInAccessibleGroup(const char *appId, const char *groupId, const char *deviceId) +{ + if ((appId == NULL) || (groupId == NULL) || (deviceId == NULL)) { + LOGE("The input parameters contains NULL value!"); + return false; + } + if (!IsGroupExistByGroupId(groupId)) { + LOGE("No group is found based on the query parameters!"); + return false; + } + if (!IsGroupAccessible(groupId, appId)) { + LOGI("You do not have the permission to query the group information!"); + return false; + } + return IsTrustedDeviceInGroupByAuthId(groupId, deviceId); +} + +static void DestroyInfo(char **returnInfo) +{ + FreeJsonString(*returnInfo); + *returnInfo = NULL; +} + +static void InitGroupManagerInstance(GroupManager *instance) +{ + instance->regGroupManagerCallback = RegGroupManagerCallback; + instance->unRegGroupManagerCallback = UnRegGroupManagerCallback; + instance->getGmCallbackByAppId = GetGmCallbackByAppId; + instance->createPeerToPeerGroup = CreatePeerToPeerGroup; + instance->deletePeerToPeerGroup = DeletePeerToPeerGroup; + instance->addMemberToPeerToPeerGroup = AddMemberToPeerToPeerGroup; + instance->deleteMemberFromPeerToPeerGroup = DeleteMemberFromPeerToPeerGroup; + instance->processBindData = ProcessBindData; + instance->addGroupRole = AddGroupRole; + instance->deleteGroupRole = DeleteGroupRole; + instance->getGroupRole = GetGroupRole; + instance->regListener = RegListener; + instance->unRegListener = UnRegListener; + instance->syncCreateIdenticalAccountGroup = SyncCreateIdenticalAccountGroup; + instance->syncDeleteIdenticalAccountGroup = SyncDeleteIdenticalAccountGroup; + instance->getRegisterInfo = GetRegisterInfo; + instance->processCredential = ProcessCredential; + instance->getAccessibleGroupInfoById = GetAccessibleGroupInfoById; + instance->getAccessibleGroupInfo = GetAccessibleGroupInfo; + instance->getAccessibleJoinedGroups = GetAccessibleJoinedGroups; + instance->getAccessibleRelatedGroups = GetAccessibleRelatedGroups; + instance->getAccessibleDeviceInfoById = GetAccessibleDeviceInfoById; + instance->getAccessibleTrustedDevices = GetAccessibleTrustedDevices; + instance->isDeviceInAccessibleGroup = IsDeviceInAccessibleGroup; + instance->destroyInfo = DestroyInfo; +} + +static GroupManager *g_groupManager = NULL; + +int32_t InitGroupManager() +{ + if (InitDatabase() != HC_SUCCESS) { + LOGE("[End]: [Service]: Failed to init database module!"); + return HC_ERR_SERVICE_NEED_RESTART; + } + if (IsBroadcastSupported()) { + if (InitBroadcastManager() != HC_SUCCESS) { + LOGE("[End]: [Service]: Failed to init broadcast manage module!"); + DestroyDatabase(); + return HC_ERR_SERVICE_NEED_RESTART; + } + Broadcaster *broadcaster = GetBroadcaster(); + if (broadcaster == NULL) { + LOGE("[End]: [Service]: Failed to get broadcast manager instance!"); + DestroyDatabase(); + DestroyBroadcastManager(); + return HC_ERR_NULL_PTR; + } + RegisterBroadcaster(broadcaster); + } + if (IsAccountRelatedGroupManagerSupported() && IsGroupTypeSupported(ACROSS_ACCOUNT_AUTHORIZE_GROUP)) { + AccountRelatedGroupManager *instance = GetAccountRelatedGroupManager(); + if (instance == NULL) { + LOGE("Failed to get AccountRelatedGroupManager instance!"); + DestroyDatabase(); + DestroyBroadcastManager(); + return HC_ERR_NULL_PTR; + } + RegGenerateGroupIdFunc(instance->generateAcrossAccountGroupId); + } + g_groupManager = (GroupManager *)HcMalloc(sizeof(GroupManager), 0); + if (g_groupManager == NULL) { + LOGE("Failed to allocate groupManager instance memory!"); + DestroyDatabase(); + DestroyBroadcastManager(); + return HC_ERR_ALLOC_MEMORY; + } + g_callbackVec = CREATE_HC_VECTOR(GmCallbackEntryVec) + InitGroupManagerInstance(g_groupManager); + return HC_SUCCESS; +} + +void DestroyGroupManager() +{ + HcFree(g_groupManager); + g_groupManager = NULL; + DeregGenerateGroupIdFunc(); + DeregisterBroadcaster(); + DestroyBroadcastManager(); + DestroyDatabase(); + uint32_t index; + CallbackEntry *entry = NULL; + FOR_EACH_HC_VECTOR(g_callbackVec, index, entry) { + if (entry != NULL) { + HcFree(entry->appId); + HcFree(entry->callback); + } + } + DESTROY_HC_VECTOR(GmCallbackEntryVec, &g_callbackVec) +} + +GroupManager *GetGroupManagerInstance() +{ + return g_groupManager; +} + +bool IsGroupManagerSupported() +{ + return true; +} \ No newline at end of file diff --git a/services/group_manager/src/group_manager_mock/group_manager_mock.c b/services/group_manager/src/group_manager_mock/group_manager_mock.c new file mode 100644 index 0000000..bf0678f --- /dev/null +++ b/services/group_manager/src/group_manager_mock/group_manager_mock.c @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "group_manager.h" +#include "device_auth_defines.h" +#include "hc_log.h" + +int32_t InitGroupManager() +{ + return HC_SUCCESS; +} + +void DestroyGroupManager() +{ + return; +} + +GroupManager *GetGroupManagerInstance() +{ + return NULL; +} + +bool IsGroupManagerSupported() +{ + return false; +} \ No newline at end of file diff --git a/services/module/inc/das_module/base_sub_task.h b/services/module/inc/das_module/base_sub_task.h new file mode 100644 index 0000000..2306144 --- /dev/null +++ b/services/module/inc/das_module/base_sub_task.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BASE_SUB_TASK_H +#define BASE_SUB_TASK_H + +#include "json_utils.h" +#include "das_module_defines.h" +#include "das_version_util.h" + +typedef struct SubTaskBaseT { + int (*getTaskType)(const struct SubTaskBaseT *); + void (*destroyTask)(struct SubTaskBaseT *); + int (*process)(struct SubTaskBaseT *, const CJson *in, CJson *out, int *status); + VersionStruct curVersion; +} SubTaskBase; + +typedef SubTaskBase *(*CreateSubTaskFunc)(CJson *, CJson *); + +#endif diff --git a/services/module/inc/das_module/das_common.h b/services/module/inc/das_module/das_common.h new file mode 100644 index 0000000..bdb3379 --- /dev/null +++ b/services/module/inc/das_module/das_common.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DAS_COMMON_H +#define DAS_COMMON_H + +#include "common_util.h" +#include "das_module_defines.h" +#include "hc_types.h" +#include "json_utils.h" + +int32_t GenerateKeyAlias(const Uint8Buff *pkgName, const Uint8Buff *serviceType, const KeyAliasType keyType, + const Uint8Buff *authId, Uint8Buff *outKeyAlias); +int32_t GetAndCheckAuthIdPeer(const CJson *in, const Uint8Buff *authIdPeer); +int32_t GetAuthIdPeer(const CJson *in, Uint8Buff *authIdPeer); +int32_t GetAndCheckKeyLenOnServer(const CJson *in, uint32_t *returnKeyLen); + +void SendErrMsgToSelf(const CJson *in, CJson *out, int errCode); +void SendErrorToOut(CJson *out, int opCode, int errCode); + +uint32_t ProtocolMessageIn(const CJson *in); +int ClientProtocolMessageOut(CJson *out, int opCode, uint32_t step); +int ServerProtocolMessageOut(CJson *out, int opCode, uint32_t step); + +#endif diff --git a/services/module/inc/das_module/das_module.h b/services/module/inc/das_module/das_module.h new file mode 100644 index 0000000..ca3f237 --- /dev/null +++ b/services/module/inc/das_module/das_module.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DAS_MODULE_H +#define DAS_MODULE_H + +#include "common_defs.h" +#include "common_util.h" + +bool IsDasSupported(); + +typedef struct DasAuthModuleT { + AuthModuleBase moduleBase; + int (*registerLocalIdentity)(const char *, const char *, Uint8Buff *, int); + int (*unregisterLocalIdentity)(const char *, const char *, Uint8Buff *, int); + int (*deletePeerAuthInfo)(const char *, const char *, Uint8Buff *, int); +} DasAuthModule; + +AuthModuleBase *CreateDasModule(); + +#endif diff --git a/services/module/inc/das_module/das_module_defines.h b/services/module/inc/das_module/das_module_defines.h new file mode 100644 index 0000000..5f487da --- /dev/null +++ b/services/module/inc/das_module/das_module_defines.h @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DAS_MODULE_DEFINES_H +#define DAS_MODULE_DEFINES_H + +#include "common_defs.h" +#include "device_auth_defines.h" +#include "hc_types.h" + +#define STEP_ONE 1 +#define STEP_TWO 2 +#define STEP_THREE 3 +#define MIN_PIN_LEN 4 +#define MAX_PIN_LEN 1024 +#define MIN_OUTPUT_KEY_LEN 16 +#define MAX_OUTPUT_KEY_LEN 32 + +typedef enum { + PAKE_REQUEST = 0x0001, + PAKE_RESPONSE = 0x8001, + PAKE_CLIENT_CONFIRM = 0x0002, + PAKE_SERVER_CONFIRM = 0x8002, + + PAKE_BIND_EXCHANGE_REQUEST = 0x0003, + PAKE_BIND_EXCHANGE_RESPONSE = 0x8003, + + PAKE_UNBIND_EXCHANGE_REQUEST = 0x0033, + PAKE_UNBIND_EXCHANGE_RESPONSE = 0x8033, + + ISO_CLIENT_BIND_START = 0x0001, + ISO_SERVER_BIND_START = 0x8001, + ISO_CLIENT_BIND_CAL_TOKEN = 0x0002, + ISO_SERVER_BIND_CAL_TOKEN = 0x8002, + + ISO_CLIENT_AUTH_OR_UNBIND_START = 0x0011, + ISO_SERVER_AUTH_OR_UNBIND_START = 0x8011, + ISO_CLIENT_AUTH_OR_UNBIND_CAL_TAOKEN = 0x0012, + ISO_SERVER_AUTH_OR_UNBIND_CAL_TAOKEN = 0x8012, + + ISO_CLIENT_BIND_EXCHANGE_CMD = 0x0003, + ISO_SERVER_BIND_EXCHANGE_RET = 0x8003, + ISO_CLIENT_BIND_EXCHANGE_CONFIRM = 0x0004, + + ISO_CLIENT_UNBIND_EXCHANGE_CMD = 0x0013, + ISO_SERVER_UNBIND_EXCHANGE_RET = 0x8013, + ISO_CLIENT_UNBIND_EXCHANGE_CONFIRM = 0x0014, + + ISO_RESULT_CONFIRM_CMD = 0x0013, + + ERR_MESSAGE = 0x8080, + INVALID_MESSAGE = 0xFFFF, +} DasMessageCode; + +typedef enum CurTaskTypeT { + TASK_TYPE_ISO_PROTOCOL = 0, + TASK_TYPE_PAKE_PROTOCOL = 1, + TASK_TYPE_NEW_PAKE_PROTOCOL = 2, + TASK_TYPE_BIND_LITE_EXCHANGE, + TASK_TYPE_UNBIND_LITE_EXCHANGE, + TASK_TYPE_BIND_STANDARD_EXCHANGE, + TASK_TYPE_UNBIND_STANDARD_EXCHANGE, + TASK_TYPE_NONE, +} CurTaskType; + +typedef enum { + KEY_ALIAS_ACCESSOR_PK = DEVICE_TYPE_ACCESSORY, + KEY_ALIAS_CONTROLLER_PK = DEVICE_TYPE_CONTROLLER, + KEY_ALIAS_LT_KEY_PAIR = 2, + KEY_ALIAS_KEK = 3, + KEY_ALIAS_DEK = 4, + KEY_ALIAS_TMP = 5, + KEY_ALIAS_PSK = 6, + KEY_ALIAS_AUTH_TOKEN = 7, + + KEY_ALIAS_TYPE_END +} KeyAliasType; // 0 ~ 2^8-1, don't change the order + +#endif diff --git a/services/module/inc/das_module/das_version_util.h b/services/module/inc/das_module/das_version_util.h new file mode 100644 index 0000000..f5b8302 --- /dev/null +++ b/services/module/inc/das_module/das_version_util.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DAS_VERSION_UTIL_H +#define DAS_VERSION_UTIL_H + +#include "version_util.h" + +typedef enum { + INITIAL, + VERSION_CONFIRM, + VERSION_DECIDED, +} VersionAgreementStatus; + +typedef struct VersionInfoT { + int opCode; + VersionAgreementStatus versionStatus; + VersionStruct minVersion; + VersionStruct curVersion; +} VersionInfo; + +int32_t GetVersionFromJson(const CJson *jsonObj, VersionStruct *min, VersionStruct *max); +int32_t AddVersionToJson(CJson *jsonObj, const VersionStruct *min, const VersionStruct *max); + +bool IsVersionEqual(VersionStruct *src, VersionStruct *des); +int32_t NegotiateVersion(VersionStruct *minVersionPeer, VersionStruct *curVersionPeer, + VersionStruct *curVersionSelf); + +ProtocolType GetPrototolType(VersionStruct *curVersion, OperationCode opCode); + +AlgType GetSupportedPakeAlg(VersionStruct *curVersion); + +#endif \ No newline at end of file diff --git a/services/module/inc/das_module/iso_task/iso_base_cur_task.h b/services/module/inc/das_module/iso_task/iso_base_cur_task.h new file mode 100644 index 0000000..faf871e --- /dev/null +++ b/services/module/inc/das_module/iso_task/iso_base_cur_task.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ISO_BASE_CUR_TASK_H +#define ISO_BASE_CUR_TASK_H + +#include "json_utils.h" +#include "alg_loader.h" +#include "common_defs.h" +#include "das_module_defines.h" +#include "iso_protocol_common.h" + +#define CHALLENGE_SIZE 16 +#define NONCE_SIZE 12 +#define TAG_LEN 16 +#define EXCHANGE_AAD "hichain_iso_exchange" +#define RESULT_AAD "hichain_iso_result" +#define UNBIND_ADD_REQUEST "hichain_remove_info_request" +#define UNBIND_ADD_RESPONSE "hichain_remove_info_response" +#define GENERATE_RETURN_KEY_STR "hichain_return_key" +#define ISO_TOKEN_LEN 32 +#define RESULT_MAC_LEN 32 +#define AUTH_CODE_LEN 32 +#define KEY_ALIAS_SIZE 32 +#define ENC_CHALLENGE_LEN (CHALLENGE_SIZE + TAG_LEN) +#define SEED_LEN 32 +#define ISO_KEY_ALIAS_LEN 32 + +typedef struct IsoParamsT { + IsoBaseParams baseParams; + + Uint8Buff seed; + int selfUserType; + int peerUserType; + char *packageName; + char *serviceType; + char *pinCodeString; + int opCode; + uint32_t keyLen; + bool isClient; +} IsoParams; + +typedef struct SymBaseCurTaskT { + CurTaskType (*getCurTaskType)(); + void (*destroyTask)(struct SymBaseCurTaskT *); + int(*process)(struct SymBaseCurTaskT *, IsoParams *params, const CJson *in, CJson *out, int *status); + int taskStatus; +} SymBaseCurTask; + +#endif diff --git a/services/module/inc/das_module/iso_task/iso_client_task.h b/services/module/inc/das_module/iso_task/iso_client_task.h new file mode 100644 index 0000000..d81897f --- /dev/null +++ b/services/module/inc/das_module/iso_task/iso_client_task.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ISO_CLIENT_TASK_H +#define ISO_CLIENT_TASK_H + +#include "base_sub_task.h" +#include "iso_base_cur_task.h" + +typedef struct { + SubTaskBase taskBase; + IsoParams params; + SymBaseCurTask *curTask; +} IsoClientTask; + +SubTaskBase *CreateIsoClientTask(const CJson *in); + +#endif diff --git a/services/module/inc/das_module/iso_task/iso_protocol_task/iso_client_protocol_task.h b/services/module/inc/das_module/iso_task/iso_protocol_task/iso_client_protocol_task.h new file mode 100644 index 0000000..ba6c61c --- /dev/null +++ b/services/module/inc/das_module/iso_task/iso_protocol_task/iso_client_protocol_task.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ISO_CLIENT_PROTOCOL_TASK_H +#define ISO_CLIENT_PROTOCOL_TASK_H + +#include "iso_base_cur_task.h" + +typedef struct { + SymBaseCurTask taskBase; +} IsoProtocolClientTask; + +SymBaseCurTask *CreateProtocolClientTask(); + +#endif diff --git a/services/module/inc/das_module/iso_task/iso_protocol_task/iso_server_protocol_task.h b/services/module/inc/das_module/iso_task/iso_protocol_task/iso_server_protocol_task.h new file mode 100644 index 0000000..040d983 --- /dev/null +++ b/services/module/inc/das_module/iso_task/iso_protocol_task/iso_server_protocol_task.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ISO_SERVER_PROTOCOL_TASK_H +#define ISO_SERVER_PROTOCOL_TASK_H + +#include "iso_base_cur_task.h" + +typedef struct { + SymBaseCurTask taskBase; +} IsoProtocolServerTask; + +SymBaseCurTask *CreateProtocolServerTask(); + +#endif diff --git a/services/module/inc/das_module/iso_task/iso_server_task.h b/services/module/inc/das_module/iso_task/iso_server_task.h new file mode 100644 index 0000000..79b8238 --- /dev/null +++ b/services/module/inc/das_module/iso_task/iso_server_task.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ISO_SERVER_TASK_H +#define ISO_SERVER_TASK_H + +#include "base_sub_task.h" +#include "iso_base_cur_task.h" + +typedef struct { + SubTaskBase taskBase; + IsoParams params; + SymBaseCurTask *curTask; +} IsoServerTask; + +SubTaskBase *CreateIsoServerTask(const CJson *in, CJson *out); + +#endif diff --git a/services/module/inc/das_module/iso_task/iso_task_common.h b/services/module/inc/das_module/iso_task/iso_task_common.h new file mode 100644 index 0000000..7f7d655 --- /dev/null +++ b/services/module/inc/das_module/iso_task/iso_task_common.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ISO_TASK_COMMON_H +#define ISO_TASK_COMMON_H + +#include "json_utils.h" +#include "iso_base_cur_task.h" + +void DestroyIsoParams(IsoParams *params); +int InitIsoParams(IsoParams *params, const CJson *in); + +int GenerateSeed(IsoParams *params); + +int GenerateKeyAliasInIso(const IsoParams *params, uint8_t *keyAlias, uint32_t keyAliasLen, bool useOpposite); +int GeneratePsk(const CJson *in, IsoParams *params); + +int GenerateEncResult(const IsoParams *params, int message, CJson *sendToPeer, const char *aad); +int GenEncResult(const IsoParams *params, int message, CJson *out, const char *aad, bool isNeedReturnKey); +int SendResultToFinalSelf(const IsoParams *params, CJson *out, bool isNeedReturnKey); +int CheckEncResult(IsoParams *params, const CJson *in, const char *aad); +void DeleteAuthCode(const IsoParams *params); + +#endif diff --git a/services/module/inc/das_module/iso_task/iso_task_main.h b/services/module/inc/das_module/iso_task/iso_task_main.h new file mode 100644 index 0000000..419fcc8 --- /dev/null +++ b/services/module/inc/das_module/iso_task/iso_task_main.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ISO_TASK_MAIN_H +#define ISO_TASK_MAIN_H + +#include "base_sub_task.h" +#include "json_utils.h" +#include "das_asy_token_manager.h" + +bool IsIsoSupported(); +const TokenManager *GetSymTokenManagerInstance(); +SubTaskBase *CreateIsoSubTask(const CJson *in, CJson *out); + +#endif diff --git a/services/module/inc/das_module/iso_task/lite_exchange_task/iso_client_bind_exchange_task.h b/services/module/inc/das_module/iso_task/lite_exchange_task/iso_client_bind_exchange_task.h new file mode 100644 index 0000000..ce35e9c --- /dev/null +++ b/services/module/inc/das_module/iso_task/lite_exchange_task/iso_client_bind_exchange_task.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ISO_CLIENT_BIND_EXCHANGE_TASK +#define ISO_CLIENT_BIND_EXCHANGE_TASK + +#include "iso_base_cur_task.h" + +typedef struct { + SymBaseCurTask taskBase; + uint8_t challenge[CHALLENGE_SIZE]; +} IsoClientBindExchangeTask; + +SymBaseCurTask *CreateClientBindExchangeTask(IsoParams *params, const CJson *in, CJson *out, int *status); + +#endif diff --git a/services/module/inc/das_module/iso_task/lite_exchange_task/iso_client_unbind_exchange_task.h b/services/module/inc/das_module/iso_task/lite_exchange_task/iso_client_unbind_exchange_task.h new file mode 100644 index 0000000..c5e8569 --- /dev/null +++ b/services/module/inc/das_module/iso_task/lite_exchange_task/iso_client_unbind_exchange_task.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ISO_CLIENT_UNBIND_EXCHANGE_TASK_H +#define ISO_CLIENT_UNBIND_EXCHANGE_TASK_H + +#include "iso_base_cur_task.h" + +typedef struct { + SymBaseCurTask taskBase; +} IsoClientUnbindExchangeTask; + +SymBaseCurTask *CreateClientUnbindExchangeTask(IsoParams *params, const CJson *in, CJson *out, int *status); + +#endif diff --git a/services/module/inc/das_module/iso_task/lite_exchange_task/iso_server_bind_exchange_task.h b/services/module/inc/das_module/iso_task/lite_exchange_task/iso_server_bind_exchange_task.h new file mode 100644 index 0000000..37a1423 --- /dev/null +++ b/services/module/inc/das_module/iso_task/lite_exchange_task/iso_server_bind_exchange_task.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ISO_SERVER_BIND_EXCHANGE_TASK_H +#define ISO_SERVER_BIND_EXCHANGE_TASK_H + +#include "iso_base_cur_task.h" + +typedef struct { + SymBaseCurTask taskBase; +} IsoServerBindExchangeTask; + +SymBaseCurTask *CreateServerBindExchangeTask(IsoParams *params, const CJson *in, CJson *out, int *status); + +#endif diff --git a/services/module/inc/das_module/iso_task/lite_exchange_task/iso_server_unbind_exchange_task.h b/services/module/inc/das_module/iso_task/lite_exchange_task/iso_server_unbind_exchange_task.h new file mode 100644 index 0000000..b8956dd --- /dev/null +++ b/services/module/inc/das_module/iso_task/lite_exchange_task/iso_server_unbind_exchange_task.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ISO_SERVER_UNBIND_EXCHANGE_TASK_H +#define ISO_SERVER_UNBIND_EXCHANGE_TASK_H + +#include "iso_base_cur_task.h" + +typedef struct { + SymBaseCurTask taskBase; +} IsoServerUnbindExchangeTask; + +SymBaseCurTask *CreateServerUnbindExchangeTask(IsoParams *params, const CJson *in, CJson *out, int *status); + +#endif diff --git a/services/module/inc/das_module/pake_task/common_standard_bind_exchange.h b/services/module/inc/das_module/pake_task/common_standard_bind_exchange.h new file mode 100644 index 0000000..6580385 --- /dev/null +++ b/services/module/inc/das_module/pake_task/common_standard_bind_exchange.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef COMMON_STANDARD_BIND_EXCHANGE_H +#define COMMON_STANDARD_BIND_EXCHANGE_H + +#include +#include "common_defs.h" +#include "pake_base_cur_task.h" + +#define HICHAIN_EXCHANGE_REQUEST "hichain_exchange_request" +#define HICHAIN_EXCHANGE_RESPONSE "hichain_exchange_response" +#define STANDARD_BIND_EXCHANGE_NONCE_LEN 12 + +typedef struct StandardBindExchangeParamsT { + Uint8Buff pubKeySelf; + Uint8Buff pubKeyPeer; + Uint8Buff authInfo; + Uint8Buff exInfoCipher; + Uint8Buff nonce; +} StandardBindExchangeParams; + +int32_t InitStandardBindExchangeParams(StandardBindExchangeParams *params); +void DestroyStandardBindExchangeParams(StandardBindExchangeParams *params); + +int32_t ClientRequestStandardBindExchange(const PakeParams *pakeParams, StandardBindExchangeParams *exchangeParams); +int32_t ServerResponseStandardBindExchange(PakeParams *pakeParams, StandardBindExchangeParams *exchangeParams); +int32_t ClientConfirmStandardBindExchange(PakeParams *pakeParams, StandardBindExchangeParams *exchangeParams); + +#endif diff --git a/services/module/inc/das_module/pake_task/common_standard_unbind_exchange.h b/services/module/inc/das_module/pake_task/common_standard_unbind_exchange.h new file mode 100644 index 0000000..d0be863 --- /dev/null +++ b/services/module/inc/das_module/pake_task/common_standard_unbind_exchange.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef COMMON_STANDARD_UNBIND_EXCHANGE_H +#define COMMON_STANDARD_UNBIND_EXCHANGE_H + +#include +#include "common_defs.h" +#include "pake_base_cur_task.h" + +#define HICHAIN_REMOVE_INFO_REQUEST "hichain_remove_info_request" +#define HICHAIN_REMOVE_INFO_RESPONSE "hichain_remove_info_response" + +#define STANDARD_UNBIND_EXCHANGE_NONCE_LEN 12 + +typedef struct StandardUnbindExchangeParamsT { + Uint8Buff rmvInfo; + Uint8Buff exRmvCipher; + Uint8Buff resultCipher; + Uint8Buff nonce; +} StandardUnbindExchangeParams; + +int32_t InitStandardUnbindExchangeParams(StandardUnbindExchangeParams *params); +void DestroyStandardUnbindExchangeParams(StandardUnbindExchangeParams *params); + +int32_t ClientRequestStandardUnbindExchange(const PakeParams *pakeParams, StandardUnbindExchangeParams *exchangeParams); +int32_t ServerResponseStandardUnbindExchange(PakeParams *pakeParams, StandardUnbindExchangeParams *exchangeParams); +int32_t ClientConfirmStandardUnbindExchange(PakeParams *pakeParams, StandardUnbindExchangeParams *exchangeParams); + +#endif diff --git a/services/module/inc/das_module/pake_task/das_asy_token_manager.h b/services/module/inc/das_module/pake_task/das_asy_token_manager.h new file mode 100644 index 0000000..1e7b180 --- /dev/null +++ b/services/module/inc/das_module/pake_task/das_asy_token_manager.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DAS_ASY_TOKEN_MANAGER +#define DAS_ASY_TOKEN_MANAGER + +#include "common_defs.h" +#include "pake_base_cur_task.h" + +typedef struct TokenManagerT { + int (*registerLocalIdentity)(const char *, const char *, Uint8Buff *, int); + int (*unregisterLocalIdentity)(const char *, const char *, Uint8Buff *, int); + int (*deletePeerAuthInfo)(const char *, const char *, Uint8Buff *, int); + int (*computeAndSavePsk)(const PakeParams *params); +} TokenManager; + +const TokenManager *GetAsyTokenManagerInstance(); + +#endif diff --git a/services/module/inc/das_module/pake_task/new_pake_task/new_pake_client_protocol_task.h b/services/module/inc/das_module/pake_task/new_pake_task/new_pake_client_protocol_task.h new file mode 100644 index 0000000..37d837f --- /dev/null +++ b/services/module/inc/das_module/pake_task/new_pake_task/new_pake_client_protocol_task.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef NEW_PAKE_CLIENT_PROTOCOL_TASK_H +#define NEW_PAKE_CLIENT_PROTOCOL_TASK_H + +#include "pake_base_cur_task.h" + +typedef struct { + AsyBaseCurTask taskBase; +} NewPakeProtocolClientTask; + +AsyBaseCurTask *CreateNewPakeProtocolClientTask(); + +#endif diff --git a/services/module/inc/das_module/pake_task/new_pake_task/new_pake_client_task.h b/services/module/inc/das_module/pake_task/new_pake_task/new_pake_client_task.h new file mode 100644 index 0000000..ff450c3 --- /dev/null +++ b/services/module/inc/das_module/pake_task/new_pake_task/new_pake_client_task.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef NEW_PAKE_CLIENT_TASK_H +#define NEW_PAKE_CLIENT_TASK_H + +#include "json_utils.h" +#include "pake_base_cur_task.h" +#include "base_sub_task.h" + +typedef struct { + SubTaskBase taskBase; + PakeParams params; + AsyBaseCurTask *curTask; +} NewPakeClientTask; + +SubTaskBase *CreateNewPakeClientTask(const CJson *in, CJson *out); + +#endif diff --git a/services/module/inc/das_module/pake_task/new_pake_task/new_pake_protocol_task_common.h b/services/module/inc/das_module/pake_task/new_pake_task/new_pake_protocol_task_common.h new file mode 100644 index 0000000..a1f51e8 --- /dev/null +++ b/services/module/inc/das_module/pake_task/new_pake_task/new_pake_protocol_task_common.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef NEW_PAKE_PROTOCOL_TASK_COMMOM_H +#define NEW_PAKE_PROTOCOL_TASK_COMMOM_H + +#include "pake_base_cur_task.h" +#include "json_utils.h" + +int32_t InitDasNewPakeParams(PakeParams *params, const CJson *in); +void DestroyDasNewPakeParams(PakeParams *params); + +#endif diff --git a/services/module/inc/das_module/pake_task/new_pake_task/new_pake_server_protocol_task.h b/services/module/inc/das_module/pake_task/new_pake_task/new_pake_server_protocol_task.h new file mode 100644 index 0000000..ab4f34c --- /dev/null +++ b/services/module/inc/das_module/pake_task/new_pake_task/new_pake_server_protocol_task.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef NEW_PAKE_SERVER_PROTOCOL_TASK_H +#define NEW_PAKE_SERVER_PROTOCOL_TASK_H + +#include "pake_base_cur_task.h" + +typedef struct { + AsyBaseCurTask taskBase; +} NewPakeProtocolServerTask; + +AsyBaseCurTask *CreateNewPakeProtocolServerTask(); + +#endif diff --git a/services/module/inc/das_module/pake_task/new_pake_task/new_pake_server_task.h b/services/module/inc/das_module/pake_task/new_pake_task/new_pake_server_task.h new file mode 100644 index 0000000..edff176 --- /dev/null +++ b/services/module/inc/das_module/pake_task/new_pake_task/new_pake_server_task.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef NEW_PAKE_SERVER_TASK_H +#define NEW_PAKE_SERVER_TASK_H + +#include "json_utils.h" +#include "pake_base_cur_task.h" +#include "base_sub_task.h" + +typedef struct { + SubTaskBase taskBase; + PakeParams params; + AsyBaseCurTask *curTask; +} NewPakeServerTask; + +SubTaskBase *CreateNewPakeServerTask(const CJson *in, CJson *out); + +#endif diff --git a/services/module/inc/das_module/pake_task/new_pake_task/new_pake_task_main.h b/services/module/inc/das_module/pake_task/new_pake_task/new_pake_task_main.h new file mode 100644 index 0000000..2b552d3 --- /dev/null +++ b/services/module/inc/das_module/pake_task/new_pake_task/new_pake_task_main.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef NEW_PAKE_TASK_MAIN_H +#define NEW_PAKE_TASK_MAIN_H + +#include "base_sub_task.h" +#include "json_utils.h" +#include "das_module_defines.h" + +bool IsSupportNewPake(); +SubTaskBase *CreateNewPakeSubTask(const CJson *in, CJson *out); + +#endif diff --git a/services/module/inc/das_module/pake_task/pake_base_cur_task.h b/services/module/inc/das_module/pake_task/pake_base_cur_task.h new file mode 100644 index 0000000..7d40617 --- /dev/null +++ b/services/module/inc/das_module/pake_task/pake_base_cur_task.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PAKE_BASE_CUR_TASK_H +#define PAKE_BASE_CUR_TASK_H + +#include +#include "json_utils.h" +#include "das_module_defines.h" +#include "pake_defs.h" + +#define PAKE_KEY_ALIAS_LEN 64 +#define PAKE_ED25519_KEY_PAIR_LEN 32 + +typedef struct PakeParamsT { + PakeBaseParams baseParams; + + Uint8Buff returnKey; + Uint8Buff nonce; + int opCode; + int32_t userType; + int32_t userTypePeer; + char *packageName; + char *serviceType; +} PakeParams; + +typedef struct AsyBaseCurTaskT { + CurTaskType (*getCurTaskType)(); + void (*destroyTask)(struct AsyBaseCurTaskT *); + int(*process)(struct AsyBaseCurTaskT *, PakeParams *params, const CJson *in, CJson *out, int *status); + int taskStatus; +} AsyBaseCurTask; + +#endif diff --git a/services/module/inc/das_module/pake_task/pake_message_util.h b/services/module/inc/das_module/pake_task/pake_message_util.h new file mode 100644 index 0000000..d4005f5 --- /dev/null +++ b/services/module/inc/das_module/pake_task/pake_message_util.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PAKE_MESSAGE_UTIL_H +#define PAKE_MESSAGE_UTIL_H + +#include "json_utils.h" +#include "pake_base_cur_task.h" + +int32_t ParseStartJsonParams(PakeParams *params, const CJson *in); +int32_t PackagePakeRequestData(const PakeParams *params, CJson *payload); +int32_t ParsePakeRequestMessage(PakeParams *params, const CJson *in); +int32_t PackagePakeResponseData(const PakeParams *params, CJson *payload); +int32_t ParsePakeResponseMessage(PakeParams *params, const CJson *in); +int32_t PackagePakeClientConfirmData(const PakeParams *params, CJson *payload); +int32_t ParsePakeClientConfirmMessage(PakeParams *params, const CJson *in); +int32_t PackagePakeServerConfirmData(const PakeParams *params, CJson *payload); +int32_t ParsePakeServerConfirmMessage(PakeParams *params, const CJson *in); + +#endif \ No newline at end of file diff --git a/services/module/inc/das_module/pake_task/pake_task/pake_client_protocol_task.h b/services/module/inc/das_module/pake_task/pake_task/pake_client_protocol_task.h new file mode 100644 index 0000000..3206867 --- /dev/null +++ b/services/module/inc/das_module/pake_task/pake_task/pake_client_protocol_task.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PAKE_CLIENT_PROTOCOL_TASK_H +#define PAKE_CLIENT_PROTOCOL_TASK_H + +#include "pake_base_cur_task.h" + +typedef struct { + AsyBaseCurTask taskBase; +} PakeProtocolClientTask; + +AsyBaseCurTask *CreatePakeProtocolClientTask(); + +#endif diff --git a/services/module/inc/das_module/pake_task/pake_task/pake_client_task.h b/services/module/inc/das_module/pake_task/pake_task/pake_client_task.h new file mode 100644 index 0000000..b4dfca3 --- /dev/null +++ b/services/module/inc/das_module/pake_task/pake_task/pake_client_task.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PAKE_CLIENT_TASK_H +#define PAKE_CLIENT_TASK_H + +#include "json_utils.h" +#include "pake_base_cur_task.h" +#include "base_sub_task.h" + +typedef struct { + SubTaskBase taskBase; + PakeParams params; + AsyBaseCurTask *curTask; +} PakeClientTask; + +SubTaskBase *CreatePakeClientTask(const CJson *in, CJson *out); + +#endif diff --git a/services/module/inc/das_module/pake_task/pake_task/pake_protocol_task_common.h b/services/module/inc/das_module/pake_task/pake_task/pake_protocol_task_common.h new file mode 100644 index 0000000..c141441 --- /dev/null +++ b/services/module/inc/das_module/pake_task/pake_task/pake_protocol_task_common.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PAKE_PROTOCOL_TASK_COMMOM_H +#define PAKE_PROTOCOL_TASK_COMMOM_H + +#include "pake_base_cur_task.h" +#include "json_utils.h" + +int32_t InitDasPakeParams(PakeParams *params, const CJson *in); +void DestroyDasPakeParams(PakeParams *params); + +#endif \ No newline at end of file diff --git a/services/module/inc/das_module/pake_task/pake_task/pake_server_protocol_task.h b/services/module/inc/das_module/pake_task/pake_task/pake_server_protocol_task.h new file mode 100644 index 0000000..14ce742 --- /dev/null +++ b/services/module/inc/das_module/pake_task/pake_task/pake_server_protocol_task.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PAKE_SERVER_PROTOCOL_TASK_H +#define PAKE_SERVER_PROTOCOL_TASK_H + +#include "pake_base_cur_task.h" + +typedef struct { + AsyBaseCurTask taskBase; +} PakeProtocolServerTask; + +AsyBaseCurTask *CreatePakeProtocolServerTask(); + +#endif diff --git a/services/module/inc/das_module/pake_task/pake_task/pake_server_task.h b/services/module/inc/das_module/pake_task/pake_task/pake_server_task.h new file mode 100644 index 0000000..93fb80d --- /dev/null +++ b/services/module/inc/das_module/pake_task/pake_task/pake_server_task.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PAKE_SERVER_TASK_H +#define PAKE_SERVER_TASK_H + +#include "json_utils.h" +#include "pake_base_cur_task.h" +#include "base_sub_task.h" + +typedef struct { + SubTaskBase taskBase; + PakeParams params; + AsyBaseCurTask *curTask; +} PakeServerTask; + +SubTaskBase *CreatePakeServerTask(const CJson *in, CJson *out); + +#endif diff --git a/services/module/inc/das_module/pake_task/pake_task/pake_task_main.h b/services/module/inc/das_module/pake_task/pake_task/pake_task_main.h new file mode 100644 index 0000000..73b4174 --- /dev/null +++ b/services/module/inc/das_module/pake_task/pake_task/pake_task_main.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PAKE_TASK_MAIN_H +#define PAKE_TASK_MAIN_H + +#include "base_sub_task.h" +#include "json_utils.h" +#include "das_module_defines.h" + +bool IsSupportPake(); +SubTaskBase *CreatePakeSubTask(const CJson *in, CJson *out); + +#endif diff --git a/services/module/inc/das_module/pake_task/pake_task_common.h b/services/module/inc/das_module/pake_task/pake_task_common.h new file mode 100644 index 0000000..b0f01ab --- /dev/null +++ b/services/module/inc/das_module/pake_task/pake_task_common.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PAKE_TASK_COMMOM_H +#define PAKE_TASK_COMMOM_H + +#include "pake_base_cur_task.h" +#include "json_utils.h" + +int32_t FillPskWithDerivedKey(PakeParams *params); +int32_t FillDasPakeParams(PakeParams *params, const CJson *in); +int32_t ConstructOutJson(const PakeParams *params, CJson *out); +int32_t SendResultToSelf(PakeParams *params, CJson *out); + +#endif diff --git a/services/module/inc/das_module/pake_task/standard_client_bind_exchange_task.h b/services/module/inc/das_module/pake_task/standard_client_bind_exchange_task.h new file mode 100644 index 0000000..d427474 --- /dev/null +++ b/services/module/inc/das_module/pake_task/standard_client_bind_exchange_task.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef STANDARD_CLIENT_BIND_EXCHANGE_TASK_H +#define STANDARD_CLIENT_BIND_EXCHANGE_TASK_H + +#include "pake_base_cur_task.h" +#include "common_standard_bind_exchange.h" + +typedef struct { + AsyBaseCurTask taskBase; + StandardBindExchangeParams params; +} StandardBindExchangeClientTask; + +AsyBaseCurTask *CreateStandardBindExchangeClientTask(); + +#endif diff --git a/services/module/inc/das_module/pake_task/standard_client_unbind_exchange_task.h b/services/module/inc/das_module/pake_task/standard_client_unbind_exchange_task.h new file mode 100644 index 0000000..85a84a8 --- /dev/null +++ b/services/module/inc/das_module/pake_task/standard_client_unbind_exchange_task.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef STANDARD_CLIENT_UNBIND_EXCHANGE_TASK_H +#define STANDARD_CLIENT_UNBIND_EXCHANGE_TASK_H + +#include "pake_base_cur_task.h" +#include "common_standard_unbind_exchange.h" + +typedef struct { + AsyBaseCurTask taskBase; + StandardUnbindExchangeParams params; +} StandardUnbindExchangeClientTask; + +AsyBaseCurTask *CreateStandardUnbindExchangeClientTask(); + +#endif diff --git a/services/module/inc/das_module/pake_task/standard_exchange_message_util.h b/services/module/inc/das_module/pake_task/standard_exchange_message_util.h new file mode 100644 index 0000000..a9c33bf --- /dev/null +++ b/services/module/inc/das_module/pake_task/standard_exchange_message_util.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef STANDARD_EXCHANGE_MESSAGE_UTIL_H +#define STANDARD_EXCHANGE_MESSAGE_UTIL_H + +#include "common_defs.h" +#include "json_utils.h" +#include "pake_base_cur_task.h" + +int32_t PackageNonceAndCipherToJson(const Uint8Buff *nonce, const Uint8Buff *cipher, CJson *data, const char *key); +int32_t ParseNonceAndCipherFromJson(Uint8Buff *nonce, Uint8Buff *cipher, const CJson *in, const char *key); + +int32_t GenerateSelfChallenge(PakeParams *params); +int32_t GetPeerChallenge(PakeParams *params, const CJson *in); + +#endif diff --git a/services/module/inc/das_module/pake_task/standard_server_bind_exchange_task.h b/services/module/inc/das_module/pake_task/standard_server_bind_exchange_task.h new file mode 100644 index 0000000..bdd5a9e --- /dev/null +++ b/services/module/inc/das_module/pake_task/standard_server_bind_exchange_task.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef STANDARD_SERVER_BIND_EXCHANGE_TASK_H +#define STANDARD_SERVER_BIND_EXCHANGE_TASK_H + +#include "pake_base_cur_task.h" +#include "common_standard_bind_exchange.h" + +typedef struct { + AsyBaseCurTask taskBase; + StandardBindExchangeParams params; +} StandardBindExchangeServerTask; + +AsyBaseCurTask *CreateStandardBindExchangeServerTask(); + +#endif diff --git a/services/module/inc/das_module/pake_task/standard_server_unbind_exchange_task.h b/services/module/inc/das_module/pake_task/standard_server_unbind_exchange_task.h new file mode 100644 index 0000000..01d2787 --- /dev/null +++ b/services/module/inc/das_module/pake_task/standard_server_unbind_exchange_task.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef STANDARD_SERVER_UNBIND_EXCHANGE_TASK_H +#define STANDARD_SERVER_UNBIND_EXCHANGE_TASK_H + +#include "pake_base_cur_task.h" +#include "common_standard_unbind_exchange.h" + +typedef struct { + AsyBaseCurTask taskBase; + StandardUnbindExchangeParams params; +} StandardUnbindExchangeServerTask; + +AsyBaseCurTask *CreateStandardUnbindExchangeServerTask(); + +#endif diff --git a/services/module/inc/das_module/task_main.h b/services/module/inc/das_module/task_main.h new file mode 100644 index 0000000..e25a627 --- /dev/null +++ b/services/module/inc/das_module/task_main.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef TASK_MAIN_H +#define TASK_MAIN_H + +#include "common_defs.h" +#include "hc_vector.h" +#include "json_utils.h" +#include "das_version_util.h" + +DECLARE_HC_VECTOR(SubTaskVec, void *) + +typedef struct TaskT { + int taskId; + VersionInfo versionInfo; + void(*destroyTask)(struct TaskT *); + int(*processTask)(struct TaskT *, const CJson *in, CJson *out, int *status); + SubTaskVec vec; +} Task; + +Task *CreateTaskT(int *taskId, const CJson *in, CJson *out); + +int32_t InitDasProtocolType(); +void DestroyDasProtocolType(); + +int32_t RegisterLocalIdentityInTask(const char *pkgName, const char *serviceType, Uint8Buff *authId, int userType); +int32_t UnregisterLocalIdentityInTask(const char *pkgName, const char *serviceType, Uint8Buff *authId, int userType); +int32_t DeletePeerAuthInfoInTask(const char *pkgName, const char *serviceType, Uint8Buff *authIdPeer, int userTypePeer); + +#endif diff --git a/services/module/inc/dev_auth_module_manager.h b/services/module/inc/dev_auth_module_manager.h new file mode 100644 index 0000000..700d2ab --- /dev/null +++ b/services/module/inc/dev_auth_module_manager.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DEV_AUTH_MODULE_MANAGER_H +#define DEV_AUTH_MODULE_MANAGER_H + +#include "common_util.h" +#include "json_utils.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int32_t InitModules(); +void DestroyModules(); + +int32_t CreateTask(int *taskId, const CJson *in, CJson *out, int moduleType); +int32_t ProcessTask(int taskId, const CJson *in, CJson *out, int *status, int moduleType); +void DestroyTask(int taskId, int moduleType); + +// for DAS +int32_t CheckMsgRepeatability(const CJson *in, int moduleType); +int32_t RegisterLocalIdentity(const char *pkgName, const char *serviceType, Uint8Buff *authId, int userType, + int moduleType); +int32_t UnregisterLocalIdentity(const char *pkgName, const char *serviceType, Uint8Buff *authId, int userType, + int moduleType); +int32_t DeletePeerAuthInfo(const char *pkgName, const char *serviceType, Uint8Buff *authId, int userType, + int moduleType); + +// for TCIS +int32_t SetToken(CJson *in, CJson *out, int moduleType); +int32_t DeleteToken(int moduleType); +int32_t GetRegisterProof(CJson *out, int moduleType); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/services/module/inc/module_common.h b/services/module/inc/module_common.h new file mode 100644 index 0000000..d3bdfac --- /dev/null +++ b/services/module/inc/module_common.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MODULE_COMMON_H +#define MODULE_COMMON_H + +#include "common_util.h" + +int32_t InitSingleParam(Uint8Buff *param, uint32_t len); + +#endif \ No newline at end of file diff --git a/services/module/inc/protocol/iso_protocol/iso_protocol_common.h b/services/module/inc/protocol/iso_protocol/iso_protocol_common.h new file mode 100644 index 0000000..372954e --- /dev/null +++ b/services/module/inc/protocol/iso_protocol/iso_protocol_common.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ISO_PROTOCOL_COMMON_H +#define ISO_PROTOCOL_COMMON_H + +#include "common_defs.h" +#include "alg_defs.h" + +#define GENERATE_SESSION_KEY_STR "hichain_iso_session_key" + +#define RAND_BYTE_LEN 16 +#define PSK_LEN 32 +#define ISO_SESSION_KEY_LEN 32 + +typedef struct IsoBaseParamsT { + Uint8Buff randSelf; + Uint8Buff randPeer; + Uint8Buff authIdSelf; + Uint8Buff authIdPeer; + Uint8Buff sessionKey; + uint8_t psk[PSK_LEN]; + const AlgLoader *loader; +} IsoBaseParams; + +int IsoClientGenRandom(IsoBaseParams *params); +int IsoClientCheckAndGenToken(const IsoBaseParams *params, const Uint8Buff *perrToken, Uint8Buff *selfToken); +int IsoClientGenSessionKey(IsoBaseParams *params, int returnResult, const uint8_t *hmac, uint32_t hmacLen); + +int IsoServerGenRandomAndToken(IsoBaseParams *params, Uint8Buff *selfTokenBuf); +int IsoServerGenSessionKeyAndCalToken(IsoBaseParams *params, const Uint8Buff *tokenFromPeer, Uint8Buff *tokenToPeer); + +#endif \ No newline at end of file diff --git a/services/module/inc/protocol/pake_protocol/new_pake_protocol/new_pake_protocol_common.h b/services/module/inc/protocol/pake_protocol/new_pake_protocol/new_pake_protocol_common.h new file mode 100644 index 0000000..bf1a546 --- /dev/null +++ b/services/module/inc/protocol/pake_protocol/new_pake_protocol/new_pake_protocol_common.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef NEW_PAKE_PROTOCOL_COMMON_H +#define NEW_PAKE_PROTOCOL_COMMON_H + +#include "hc_types.h" +#include "pake_defs.h" + +int32_t InitNewPakeBaseParams(PakeBaseParams *params); +void DestroyNewPakeBaseParams(PakeBaseParams *params); + +int32_t ClientRequestNewPakeProtocol(const PakeBaseParams *params); +int32_t ClientConfirmNewPakeProtocol(PakeBaseParams *params); +int32_t ClientVerifyConfirmNewPakeProtocol(PakeBaseParams *params); + +int32_t ServerResponseNewPakeProtocol(PakeBaseParams *params); +int32_t ServerConfirmNewPakeProtocol(PakeBaseParams *params); + +#endif diff --git a/services/module/inc/protocol/pake_protocol/new_pake_protocol/new_pake_protocol_dl.h b/services/module/inc/protocol/pake_protocol/new_pake_protocol/new_pake_protocol_dl.h new file mode 100644 index 0000000..ff7c1a5 --- /dev/null +++ b/services/module/inc/protocol/pake_protocol/new_pake_protocol/new_pake_protocol_dl.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef NEW_PAKE_PROTOCOL_DL_H +#define NEW_PAKE_PROTOCOL_DL_H + +#include "common_defs.h" +#include "hc_types.h" +#include "pake_defs.h" + +uint32_t GetPakeNewDlAlg(); +int32_t GenerateNewDlPakeParams(PakeBaseParams *params, const Uint8Buff *secret); +int32_t AgreeNewDlSharedSecret(PakeBaseParams *params, Uint8Buff *sharedSecret); + +#endif diff --git a/services/module/inc/protocol/pake_protocol/new_pake_protocol/new_pake_protocol_ec.h b/services/module/inc/protocol/pake_protocol/new_pake_protocol/new_pake_protocol_ec.h new file mode 100644 index 0000000..fc90c1a --- /dev/null +++ b/services/module/inc/protocol/pake_protocol/new_pake_protocol/new_pake_protocol_ec.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef NEW_PAKE_PROTOCOL_EC_H +#define NEW_PAKE_PROTOCOL_EC_H + +#include "common_defs.h" +#include "hc_types.h" +#include "pake_defs.h" + +uint32_t GetPakeNewEcAlg(); +int32_t GenerateNewEcPakeParams(PakeBaseParams *params, Uint8Buff *secret); +int32_t AgreeNewEcSharedSecret(PakeBaseParams *params, Uint8Buff *sharedSecret); + +#endif diff --git a/services/module/inc/protocol/pake_protocol/pake_defs.h b/services/module/inc/protocol/pake_protocol/pake_defs.h new file mode 100644 index 0000000..fecd40c --- /dev/null +++ b/services/module/inc/protocol/pake_protocol/pake_defs.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PAKE_DEFS_H +#define PAKE_DEFS_H + +#include "common_defs.h" +#include "protocol_common.h" +#include "alg_defs.h" + +#define HICHAIN_SPEKE_BASE_INFO "hichain_speke_base_info" +#define HICHAIN_SPEKE_SESSIONKEY_INFO "hichain_speke_sessionkey_info" +#define HICHAIN_RETURN_KEY "hichain_return_key" +#define TMP_AUTH_KEY_FACTOR "hichain_tmp_auth_enc_key" +#define SHARED_SECRET_DERIVED_FACTOR "hichain_speke_shared_secret_info" + +#define PAKE_SALT_LEN 16 +#define PAKE_NONCE_LEN 32 +#define PAKE_PSK_LEN 32 +#define PAKE_CHALLENGE_LEN 16 +#define PAKE_ESK_LEN 32 +#define PAKE_EPK_LEN 32 +#define PAKE_SECRET_LEN 32 +#define PAKE_EC_POINT_LEN 32 +#define PAKE_HMAC_KEY_LEN 32 +#define PAKE_EC_KEY_LEN 32 +#define PAKE_DL_EXP_LEN 1 +#define PAKE_DL_ESK_SMALL_LEN 28 +#define PAKE_DL_ESK_LEN 32 +#define PAKE_DL_PRIME_SMALL_LEN 256 +#define PAKE_DL_PRIME_LEN 384 + +typedef struct PakeBaseParamsT { + Uint8Buff salt; + Uint8Buff psk; + Uint8Buff challengeSelf; + Uint8Buff challengePeer; + Uint8Buff base; + Uint8Buff eskSelf; + Uint8Buff epkSelf; + Uint8Buff epkPeer; + Uint8Buff idSelf; + Uint8Buff idPeer; + Uint8Buff sessionKey; + Uint8Buff sharedSecret; + Uint8Buff hmacKey; + Uint8Buff kcfData; + Uint8Buff kcfDataPeer; + uint32_t innerKeyLen; + const char *largePrimeNumHex; + bool is256ModSupported; + + AlgType supportedPakeAlg; + CurveType curveType; + bool isClient; + const AlgLoader *loader; +} PakeBaseParams; + +#endif \ No newline at end of file diff --git a/services/module/inc/protocol/pake_protocol/pake_protocol/pake_protocol_common.h b/services/module/inc/protocol/pake_protocol/pake_protocol/pake_protocol_common.h new file mode 100644 index 0000000..a17d1a6 --- /dev/null +++ b/services/module/inc/protocol/pake_protocol/pake_protocol/pake_protocol_common.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PAKE_PROTOCOL_COMMON_H +#define PAKE_PROTOCOL_COMMON_H + +#include "hc_types.h" +#include "pake_defs.h" + +int32_t InitPakeBaseParams(PakeBaseParams *params); +void DestroyPakeBaseParams(PakeBaseParams *params); + +int32_t ClientRequestPakeProtocol(const PakeBaseParams *params); +int32_t ClientConfirmPakeProtocol(PakeBaseParams *params); +int32_t ClientVerifyConfirmPakeProtocol(const PakeBaseParams *params); + +int32_t ServerResponsePakeProtocol(PakeBaseParams *params); +int32_t ServerConfirmPakeProtocol(PakeBaseParams *params); + +#endif diff --git a/services/module/inc/protocol/pake_protocol/pake_protocol/pake_protocol_dl.h b/services/module/inc/protocol/pake_protocol/pake_protocol/pake_protocol_dl.h new file mode 100644 index 0000000..ebe8d4d --- /dev/null +++ b/services/module/inc/protocol/pake_protocol/pake_protocol/pake_protocol_dl.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PAKE_PROTOCOL_DL_H +#define PAKE_PROTOCOL_DL_H + +#include "common_defs.h" +#include "hc_types.h" +#include "pake_defs.h" + +uint32_t GetPakeDlAlg(); +int32_t GenerateDlPakeParams(PakeBaseParams *params, const Uint8Buff *secret); +int32_t GenerateDlSharedSecret(PakeBaseParams *params, Uint8Buff *sharedSecret); + +#endif diff --git a/services/module/inc/protocol/pake_protocol/pake_protocol/pake_protocol_ec.h b/services/module/inc/protocol/pake_protocol/pake_protocol/pake_protocol_ec.h new file mode 100644 index 0000000..d086485 --- /dev/null +++ b/services/module/inc/protocol/pake_protocol/pake_protocol/pake_protocol_ec.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PAKE_PROTOCOL_EC_H +#define PAKE_PROTOCOL_EC_H + +#include "common_defs.h" +#include "hc_types.h" +#include "pake_defs.h" + +uint32_t GetPakeEcAlg(); +int32_t GenerateEcPakeParams(PakeBaseParams *params, Uint8Buff *secret); +int32_t GenerateEcSharedSecret(PakeBaseParams *params, Uint8Buff *sharedSecret); + +#endif diff --git a/services/module/inc/protocol/protocol_common.h b/services/module/inc/protocol/protocol_common.h new file mode 100644 index 0000000..d6b22cc --- /dev/null +++ b/services/module/inc/protocol/protocol_common.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PROTOCOL_COMMON_H +#define PROTOCOL_COMMON_H + +#include "common_util.h" + +typedef enum { + UNSUPPORTED_ALG = 0x0000, + DL_SPEKE = 0x0001, + EC_SPEKE = 0x0002, + STS_ALG = 0x0004, + PSK_SPEKE = 0x0008, + ISO_ALG = 0x0010, + NEW_DL_SPEKE = 0x0020, + NEW_EC_SPEKE = 0x0040, +} AlgType; + +typedef enum { + UNSUPPORTED, + ISO, + PAKE, + NEW_PAKE, + STS, +} ProtocolType; + +void FreeAndCleanKey(Uint8Buff *key); + +#endif diff --git a/services/module/inc/tcis_module/auth_common.h b/services/module/inc/tcis_module/auth_common.h new file mode 100644 index 0000000..0964688 --- /dev/null +++ b/services/module/inc/tcis_module/auth_common.h @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef AUTH_COMMON_H +#define AUTH_COMMON_H + +#include "stdint.h" + +#define AUTH_STEP "authStep" +#define DEV_ID "devId" +#define SALT "salt" +#define USER_ID "userId" +#define SEED "seed" +#define AUTH_FORM "authForm" +#define AUTH_KEY_ALG_ENCODE "authKeyAlgEncode" +#define TOKEN "token" +#define SESSION_KEY "sessionKey" +#define AUTH_RESULT "authResult" +#define AUTH_RESULT_MAC "authResultMac" +#define IS_CLIENT "isClient" +#define HI_CHAIN_RETURN_KEY "hichain_return_key" +#define SEND_TO_SELF "sendToSelf" +#define SEND_TO_PEER "sendToPeer" + +#define SEED_SIZE 32 +#define AUTH_ID_SIZE 8 +#define USER_ID_SIZE 20 +#define TCIS_ID_SIZE 10 +#define DEV_ID_SIZE 40 +#define DEV_ID_MAX_SIZE 40 +#define DEV_TYPE_SIZE 3 +#define DEV_MODEL_MAX_SIZE 40 +#define UDID_SIZE 10 +#define RANDOM_SIZE 16 +#define TOKEN_SIZE 32 +#define PSK_SIZE 32 +#define AUTH_RESULT_MAC_SIZE 32 +#define AUTH_CODE_SIZE 32 +#define PUBLIC_KEY_LENGTH 64 +#define PUBLIC_KEY_HEX_LENGTH 128 +#define AUTH_PK_SIG_SIZE 64 +#define AUTH_RESULT_SIGN_SIZE 64 +#define SIGNATURE_SIZE 128 +#define SERVER_PK_SIZE 64 +#define HI_CHAIN_STRING_SIZE 18 +#define PUBLIC_KEY_INFO_SIZE 300 +#ifdef ASY +#define PROOF_LEN 146 +#define TOKEN_LEN 218 +#endif +#ifdef SYM +#define TOKEN_LEN 48 +#endif + +typedef enum { + SYMMETRIC_AUTH = 0, + ASYMMETRIC_AUTH, + POINT_TO_POINT, + SAME_ACCOUNT, + ACROSS_ACCOUNT, +} AuthForm; + +typedef enum { + AUTH_ERR_AUTH_STEP, + AUTH_ERR_INVALID_PARAM, + AUTH_ERR_TOKEN_NOT_MATCH, + AUTH_ERR_ALLOC_MEMORY, + AUTH_ERR_MAC_NOT_EQUAL, + AUTH_ERR_PROCESS_TASK, + AUTH_ERR_MESSAGE_PEER, + AUTH_ERR_STATUS, + AUTH_ERR_INTERNAL, + AUTH_ERR_GET_HMAC, + AUTH_ERR_JSON, + AUTH_ERR_GET_ITEM, + AUTH_ERR_COMPARE, + ERR_MULTI_AUTH_TASK_CREATE_FAIL, + AUTH_ERR_SUCCESS = 0, +} AuthResult; + +typedef enum { + ALG_ECC = 0x0000, + ALG_RSA = 0x0001, + ALG_HKDF = 0x0002, + ALG_HMAC = 0x0003, + ALG_AES = 0x0004, + ALG_PBKDF2 = 0x0005, + ALG_ECDH = 0x0006, + ALG_X25519 = 0x0007, + ALG_ED25519 = 0x0008, +} KeyAlg; +#endif diff --git a/services/module/inc/tcis_module/task_base.h b/services/module/inc/tcis_module/task_base.h new file mode 100644 index 0000000..e5f1842 --- /dev/null +++ b/services/module/inc/tcis_module/task_base.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef TCIS_DEVICE_AUTH_TASK_BASE_H +#define TCIS_DEVICE_AUTH_TASK_BASE_H + +#include "alg_defs.h" +#include "tcis_module_defines.h" + +typedef struct _TaskBase { + TcisTaskType (*getTaskType)(); + void (*destroyTask)(struct _TaskBase *); + int (*process)(struct _TaskBase *, CJson *in, CJson *out, int *status); + int taskStatus; + int taskId; +} TaskBase; + +typedef TaskBase *(*CreateTaskFunc)(int *, const CJson *, CJson *, AlgLoader *); + +typedef struct { + int taskTypeId; + CreateTaskFunc createTask; +} TaskCreateInfo; + +#endif diff --git a/services/module/inc/tcis_module/tcis_auth_token_manager/tcis_auth_token_manager.h b/services/module/inc/tcis_module/tcis_auth_token_manager/tcis_auth_token_manager.h new file mode 100644 index 0000000..41948c3 --- /dev/null +++ b/services/module/inc/tcis_module/tcis_auth_token_manager/tcis_auth_token_manager.h @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef TCIS_DEVICE_AUTH_TCIS_AUTH_TOKEN_MANAGER_H +#define TCIS_DEVICE_AUTH_TCIS_AUTH_TOKEN_MANAGER_H + +#ifndef ASY +#define ASY + +#include +#include "common_defs.h" +#include "common_util.h" +#include "auth_common.h" + +#define FILE_VERSION 0x01 +#define SERVER_PUBLIC_KEY_ALIAS "tcisServerPk" +#define ECC_KEY_ALIAS "tcisEccKeyPair" +#define AUTH_CODE_ALIAS "tcisAuthCode" + +#define PRINT_CHAR_ARRAY(x) do { \ + for (int i = 0; i < sizeof(x); ++i) { \ + printf_s("%c", x[i]); \ + } \ + printf_s("\n"); \ + } while (0) + +typedef enum { + CMD_USER_ID = 0, + CMD_DEVICE_ID, +} FileCmd; + +typedef struct { + uint64_t userId; + uint8_t deviceType[DEV_TYPE_SIZE]; + uint8_t deviceId[DEV_ID_MAX_SIZE]; + uint8_t deviceModel[DEV_MODEL_MAX_SIZE]; + uint8_t publicKey[PUBLIC_KEY_HEX_LENGTH]; +} PkInfo; + +#ifdef ASY +typedef struct { + uint32_t version; + uint8_t userId[USER_ID_SIZE]; + uint8_t deviceId[DEV_ID_MAX_SIZE]; + uint8_t deviceModel[DEV_MODEL_MAX_SIZE]; + uint8_t deviceType[DEV_TYPE_SIZE]; + uint32_t algType; + uint8_t pairingTcisId[TCIS_ID_SIZE]; + uint8_t publicKey[PUBLIC_KEY_HEX_LENGTH]; + uint8_t signature[SIGNATURE_SIZE]; +} RegisterProof; + +typedef struct { + uint8_t pkInfoStr[PUBLIC_KEY_INFO_SIZE]; + PkInfo pkInfo; + uint8_t pkInfoSignature[SIGNATURE_SIZE]; +} TcisToken; +#endif + +typedef struct { + int (*setToken)(CJson *in, CJson *out); + uint64_t (*getUserId)(); + int (*getDeviceId)(Uint8Buff *deviceId); + int (*getToken)(TcisToken *token); + int (*getServerPublicKey)(Uint8Buff *publicKey); + int (*deleteToken)(); +#ifdef ASY + int (*setRegisterProof)(CJson *in); + int (*getRegisterProof)(CJson *out); +#endif +} TcisAuthTokenManager; + +TcisAuthTokenManager *GetTcisAuthTokenManager(); + +void InitTcisTokenManagerAlg(); + +#endif +#endif diff --git a/services/module/inc/tcis_module/tcis_module.h b/services/module/inc/tcis_module/tcis_module.h new file mode 100644 index 0000000..6616db4 --- /dev/null +++ b/services/module/inc/tcis_module/tcis_module.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef TCIS_DEVICE_AUTH_TCIS_MODULE_H +#define TCIS_DEVICE_AUTH_TCIS_MODULE_H + +#include "task_base.h" +#include "auth_common.h" +#include "tcis_auth_token_manager.h" + +#define TASK_MULTI_AUTH_NUM_MAX 8 +#define TASK_INFOS_LENGTH 5 + +typedef enum { + CMD_ASY_AUTH_MAIN_ONE = 0x0030, + RET_ASY_AUTH_FOLLOWER_ONE = 0x0031, + CMD_ASY_AUTH_MAIN_TWO = 0x0032, + RET_ASY_AUTH_FOLLOWER_TWO = 0x0033, + CMD_ASY_AUTH_MAIN_FINAL = 0x0034, + + ASY_BIND_PAKE_REQUEST = 0x0040, + ASY_BIND_PAKE_RESPONSE = 0x0041, + ASY_BIND_PAKE_CLIENT_CONFIRM = 0x0042, + ASY_BIND_PAKE_SERVER_CONFIRM = 0x0043, + ASY_BIND_EXCHANGE_REQUEST = 0x0043, + ASY_BIND_EXCHANGE_RESPONSE = 0x0044, + + CMD_SYM_AUTH_MAIN_ONE = 0x0050, + RET_SYM_AUTH_FOLLOWER_ONE = 0x0051, + CMD_SYM_AUTH_MAIN_TWO = 0x0052, + RET_SYM_AUTH_FOLLOWER_TWO = 0x0053, + ERR_MSG = 0x8080, +} TcisMessageType; + +typedef struct { + AuthModuleBase moduleBase; + TcisAuthTokenManager *tokenManager; + AlgLoader *algLoader; +} TcisAuthModule; + +AuthModuleBase *CreateTcisModule(); + +bool IsTcisSupported(); + +#endif diff --git a/services/module/inc/tcis_module/tcis_module_defines.h b/services/module/inc/tcis_module/tcis_module_defines.h new file mode 100644 index 0000000..2a35742 --- /dev/null +++ b/services/module/inc/tcis_module/tcis_module_defines.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef TCIS_DEVICE_AUTH_TCIS_MODULE_DEFINES_H +#define TCIS_DEVICE_AUTH_TCIS_MODULE_DEFINES_H + +#include "alg_defs.h" +#include "auth_common.h" +#include "common_util.h" +#include "pake_protocol_common.h" + +typedef enum { + TASK_TYPE_DEFAULT = 0, + TASK_TYPE_ASY_SERVER_BIND = 1, + TASK_TYPE_ASY_CLIENT_AUTH = 2, + TASK_TYPE_ASY_SERVER_AUTH = 3, + TASK_TYPE_SYM_SERVER_AUTH, + TASK_TYPE_SYM_CLIENT_AUTH, +} TcisTaskType; + +typedef struct { + int authVersion; + bool isClient; + int authForm; + uint8_t seed[SEED_SIZE]; + uint8_t userIdSelf[USER_ID_SIZE]; + uint8_t userIdPeer[USER_ID_SIZE]; + uint8_t devIdSelf[DEV_ID_MAX_SIZE]; + uint8_t devIdPeer[DEV_ID_MAX_SIZE]; + uint8_t saltSelf[RANDOM_SIZE]; + uint8_t saltPeer[RANDOM_SIZE]; + uint8_t token[TOKEN_SIZE]; + uint8_t *sessionKey; + int keyLength; + KeyAlg authKeyAlgEncode; + uint8_t psk[PSK_SIZE]; + AlgLoader *loader; +} SymAuthParams; + +typedef struct BindParams { + PakeBaseParams baseParams; + uint8_t nonce[16]; + uint8_t dataEncKey[32]; +} BindParams; +#endif \ No newline at end of file diff --git a/services/module/inc/version_util.h b/services/module/inc/version_util.h new file mode 100644 index 0000000..8da6c01 --- /dev/null +++ b/services/module/inc/version_util.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef VERSION_UTIL_H +#define VERSION_UTIL_H + +#include "json_utils.h" +#include "common_defs.h" +#include "protocol_common.h" + +#define VERSION_FIRST_BIT 2 +#define TMP_VERSION_STR_LEN 15 + +typedef struct { + uint32_t first; + uint32_t second; + uint32_t third; +} VersionStruct; + +int32_t VersionToString(const VersionStruct *version, char *verStr, uint32_t len); +int32_t StringToVersion(const char* verStr, uint32_t len, VersionStruct* version); + +int32_t AddSingleVersionToJson(CJson *jsonObj, const VersionStruct *version); +int32_t GetSingleVersionFromJson(const CJson* jsonObj, VersionStruct *version); +void InitGroupAndModuleVersion(VersionStruct *version); + +#endif diff --git a/services/module/src/das_module/das_common.c b/services/module/src/das_module/das_common.c new file mode 100644 index 0000000..99c3984 --- /dev/null +++ b/services/module/src/das_module/das_common.c @@ -0,0 +1,421 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "das_common.h" +#include "alg_defs.h" +#include "alg_loader.h" +#include "common_util.h" +#include "hc_log.h" +#include "hc_types.h" +#include "module_common.h" + +#define KEY_TYPE_PAIR_LEN 2 +#define PACKAGE_NAME_MAX_LEN 256 +#define SERVICE_TYPE_MAX_LEN 256 +#define AUTH_ID_MAX_LEN 64 + +#define MESSAGE_RETURN 0x8000 +#define MESSAGE_PREFIX 0x0010 + +/* in order to expand to uint16_t */ +static const uint8_t KEY_TYPE_PAIRS[KEY_ALIAS_TYPE_END][KEY_TYPE_PAIR_LEN] = { + { 0x00, 0x00 }, /* ACCESSOR_PK */ + { 0x00, 0x01 }, /* CONTROLLER_PK */ + { 0x00, 0x02 }, /* ed25519 KEYPAIR */ + { 0x00, 0x03 }, /* KEK, key encryption key, used only by DeviceAuthService */ + { 0x00, 0x04 }, /* DEK, data encryption key, used only by upper apps */ + { 0x00, 0x05 }, /* key tmp */ + { 0x00, 0x06 }, /* PSK, preshared key index */ + { 0x00, 0x07 } /* AUTHTOKEN */ +}; + +void SendErrorToOut(CJson *out, int opCode, int errCode) +{ + CJson *sendToSelf = CreateJson(); + if (sendToSelf == NULL) { + return; + } + CJson *sendToPeer = CreateJson(); + if (sendToPeer == NULL) { + FreeJson(sendToSelf); + return; + } + CJson *payload = CreateJson(); + if (payload == NULL) { + goto err; + } + int res; + GOTO_ERR_AND_SET_RET(AddIntToJson(sendToSelf, FIELD_AUTH_FORM, AUTH_FORM_ACCOUNT_UNRELATED), res); + GOTO_ERR_AND_SET_RET(AddIntToJson(sendToSelf, FIELD_OPERATION_CODE, opCode), res); + GOTO_ERR_AND_SET_RET(AddIntToJson(sendToSelf, FIELD_ERROR_CODE, errCode), res); + + GOTO_ERR_AND_SET_RET(AddIntToJson(payload, FIELD_ERROR_CODE, errCode), res); + GOTO_ERR_AND_SET_RET(AddObjToJson(sendToPeer, FIELD_PAYLOAD, payload), res); + GOTO_ERR_AND_SET_RET(AddIntToJson(sendToPeer, FIELD_MESSAGE, ERR_MESSAGE), res); + + GOTO_ERR_AND_SET_RET(AddObjToJson(out, FIELD_SEND_TO_PEER, sendToPeer), res); + GOTO_ERR_AND_SET_RET(AddObjToJson(out, FIELD_SEND_TO_SELF, sendToSelf), res); +err: + FreeJson(sendToPeer); + FreeJson(sendToSelf); + FreeJson(payload); +} + +void SendErrMsgToSelf(const CJson *in, CJson *out, int errCode) +{ + CJson *sendToSelf = CreateJson(); + if (sendToSelf == NULL) { + return; + } + int res = AddIntToJson(sendToSelf, FIELD_AUTH_FORM, AUTH_FORM_ACCOUNT_UNRELATED); + if (res != 0) { + FreeJson(sendToSelf); + LOGE("add authForm failed: %d", res); + return; + } + res = AddIntToJson(sendToSelf, FIELD_ERROR_CODE, errCode); + if (res != 0) { + FreeJson(sendToSelf); + LOGE("add errCode failed: %d", res); + return; + } + res = AddObjToJson(out, FIELD_SEND_TO_SELF, sendToSelf); + if (res != 0) { + FreeJson(sendToSelf); + LOGE("add obj failed :%d", res); + return; + } + FreeJson(sendToSelf); +} + +uint32_t ProtocolMessageIn(const CJson *in) +{ + uint32_t message = 0; + int res = GetIntFromJson(in, FIELD_MESSAGE, (int *)&message); + if (res != HC_SUCCESS) { + return INVALID_MESSAGE; + } + if (message == ERR_MESSAGE) { + return ERR_MESSAGE; + } + return message & 0x000F; /* get lower 8 bit */ +} + +int ClientProtocolMessageOut(CJson *out, int opCode, uint32_t step) +{ + CJson *sendToPeer = GetObjFromJson(out, FIELD_SEND_TO_PEER); + if (sendToPeer == NULL) { + LOGD("No need to send to peer"); + return HC_SUCCESS; + } + int res; + switch (opCode) { + case OP_BIND: + res = AddIntToJson(sendToPeer, FIELD_MESSAGE, step); + break; + default: + step = step | MESSAGE_PREFIX; + res = AddIntToJson(sendToPeer, FIELD_MESSAGE, step); + break; + } + return res; +} + +int ServerProtocolMessageOut(CJson *out, int opCode, uint32_t step) +{ + int res; + CJson *sendToPeer = GetObjFromJson(out, FIELD_SEND_TO_PEER); + if (sendToPeer == NULL) { + LOGD("No need to send to peer"); + return HC_SUCCESS; + } + switch (opCode) { + case OP_BIND: + step = step | MESSAGE_RETURN; + res = AddIntToJson(sendToPeer, FIELD_MESSAGE, step); + break; + default: + step = step | MESSAGE_RETURN; + step = step | MESSAGE_PREFIX; + res = AddIntToJson(sendToPeer, FIELD_MESSAGE, step); + break; + } + return res; +} + +static int32_t CombineServiceId(const Uint8Buff *pkgName, const Uint8Buff *serviceType, Uint8Buff *serviceId) +{ + int32_t res = HC_SUCCESS; + Uint8Buff serviceIdPlain = { NULL, 0 }; + serviceIdPlain.length = pkgName->length + serviceType->length; + serviceIdPlain.val = (uint8_t *)HcMalloc(serviceIdPlain.length, 0); + if (serviceIdPlain.val == NULL) { + LOGE("malloc serviceIdPlain.val failed."); + res = HC_ERR_ALLOC_MEMORY; + goto err; + } + + if (memcpy_s(serviceIdPlain.val, serviceIdPlain.length, pkgName->val, pkgName->length) != EOK) { + LOGE("Copy service id: pkgName failed."); + res = HC_ERR_MEMORY_COPY; + goto err; + } + if (memcpy_s(serviceIdPlain.val + pkgName->length, serviceIdPlain.length - pkgName->length, + serviceType->val, serviceType->length) != EOK) { + LOGE("Copy service id: serviceType failed."); + res = HC_ERR_MEMORY_COPY; + goto err; + } + + res = GetLoaderInstance()->sha256(&serviceIdPlain, serviceId); + if (res != HC_SUCCESS) { + LOGE("Service id Sha256 failed."); + goto err; + } +err: + HcFree(serviceIdPlain.val); + return res; +} + +static int32_t CombineKeyAlias(const Uint8Buff *serviceId, const Uint8Buff *keyType, + const Uint8Buff *authId, Uint8Buff *keyAliasHash) +{ + int32_t res = HC_SUCCESS; + Uint8Buff keyAliasBuff = { NULL, 0 }; + keyAliasBuff.length = serviceId->length + authId->length + keyType->length; + keyAliasBuff.val = (uint8_t *)HcMalloc(keyAliasBuff.length, 0); + if (keyAliasBuff.val == NULL) { + LOGE("Malloc mem failed."); + return HC_ERR_ALLOC_MEMORY; + } + + uint32_t totalLen = keyAliasBuff.length; + uint32_t usedLen = 0; + if (memcpy_s(keyAliasBuff.val, totalLen, serviceId->val, serviceId->length) != EOK) { + LOGE("Copy serviceId failed."); + res = HC_ERR_MEMORY_COPY; + goto err; + } + usedLen = usedLen + serviceId->length; + + if (memcpy_s(keyAliasBuff.val + usedLen, totalLen - usedLen, keyType->val, keyType->length) != EOK) { + LOGE("Copy keyType failed."); + res = HC_ERR_MEMORY_COPY; + goto err; + } + usedLen = usedLen + keyType->length; + + if (memcpy_s(keyAliasBuff.val + usedLen, totalLen - usedLen, authId->val, authId->length) != EOK) { + LOGE("Copy authId failed."); + res = HC_ERR_MEMORY_COPY; + goto err; + } + + res = GetLoaderInstance()->sha256(&keyAliasBuff, keyAliasHash); + if (res != HC_SUCCESS) { + LOGE("Sha256 failed."); + goto err; + } +err: + HcFree(keyAliasBuff.val); + return res; +} + +static int32_t CombineKeyAliasForIso(const Uint8Buff *serviceId, const Uint8Buff *keyType, + const Uint8Buff *authId, Uint8Buff *outKeyAlias) +{ + if (outKeyAlias->length != SHA256_LEN) { + return HC_ERR_INVALID_LEN; + } + int32_t res = CombineKeyAlias(serviceId, keyType, authId, outKeyAlias); + if (res != HC_SUCCESS) { + LOGE("CombineKeyAlias failed."); + return res; + } + return res; +} + +static int32_t CombineKeyAliasForPake(const Uint8Buff *serviceId, const Uint8Buff *keyType, + const Uint8Buff *authId, Uint8Buff *outKeyAlias) +{ + int32_t res; + Uint8Buff keyAliasHash = { NULL, SHA256_LEN }; + char *outKeyAliasHex = NULL; + if (outKeyAlias->length != SHA256_LEN * BYTE_TO_HEX_OPER_LENGTH) { + res = HC_ERR_INVALID_LEN; + goto err; + } + keyAliasHash.val = (uint8_t *)HcMalloc(keyAliasHash.length, 0); + if (keyAliasHash.val == NULL) { + LOGE("Malloc keyAliasHash failed"); + res = HC_ERR_ALLOC_MEMORY; + goto err; + } + res = CombineKeyAlias(serviceId, keyType, authId, &keyAliasHash); + if (res != HC_SUCCESS) { + LOGE("CombineKeyAlias failed."); + goto err; + } + uint32_t outKeyAliasHexLen = keyAliasHash.length * BYTE_TO_HEX_OPER_LENGTH + 1; + outKeyAliasHex = (char *)HcMalloc(outKeyAliasHexLen, 0); + res = ByteToHexString(keyAliasHash.val, keyAliasHash.length, outKeyAliasHex, outKeyAliasHexLen); + if (res != HC_SUCCESS) { + LOGE("ByteToHexString failed"); + goto err; + } + if (memcpy_s(outKeyAlias->val, outKeyAlias->length, outKeyAliasHex, strlen(outKeyAliasHex)) != EOK) { + LOGE("memcpy outkeyalias failed."); + res = HC_ERR_MEMORY_COPY; + goto err; + } +err: + HcFree(keyAliasHash.val); + HcFree(outKeyAliasHex); + return res; +} + +int32_t GenerateKeyAlias(const Uint8Buff *pkgName, const Uint8Buff *serviceType, + const KeyAliasType keyType, const Uint8Buff *authId, Uint8Buff *outKeyAlias) +{ + CHECK_PTR_RETURN_ERROR_CODE(pkgName, "pkgName"); + CHECK_PTR_RETURN_ERROR_CODE(pkgName->val, "pkgName->val"); + CHECK_PTR_RETURN_ERROR_CODE(serviceType, "serviceType"); + CHECK_PTR_RETURN_ERROR_CODE(serviceType->val, "serviceType->val"); + CHECK_PTR_RETURN_ERROR_CODE(authId, "authId"); + CHECK_PTR_RETURN_ERROR_CODE(authId->val, "authId->val"); + CHECK_PTR_RETURN_ERROR_CODE(outKeyAlias, "outKeyAlias"); + CHECK_PTR_RETURN_ERROR_CODE(outKeyAlias->val, "outKeyAlias->val"); + if (pkgName->length == 0 || serviceType->length == 0 || authId->length == 0 || outKeyAlias->length == 0) { + return HC_ERR_INVALID_LEN; + } + if (pkgName->length > PACKAGE_NAME_MAX_LEN || serviceType->length > SERVICE_TYPE_MAX_LEN || + authId->length > AUTH_ID_MAX_LEN || keyType >= KEY_ALIAS_TYPE_END) { + return HC_ERR_INVALID_LEN; + } + + int32_t res; + Uint8Buff serviceId = { NULL, SHA256_LEN }; + serviceId.val = (uint8_t *)HcMalloc(serviceId.length, 0); + if (serviceId.val == NULL) { + LOGE("malloc serviceId.val failed."); + res = HC_ERR_ALLOC_MEMORY; + goto err; + } + res = CombineServiceId(pkgName, serviceType, &serviceId); + if (res != HC_SUCCESS) { + LOGE("CombineServiceId failed."); + goto err; + } + Uint8Buff keyTypeBuff = { (uint8_t *)KEY_TYPE_PAIRS[keyType], KEY_TYPE_PAIR_LEN }; + if (keyType == KEY_ALIAS_AUTH_TOKEN) { + res = CombineKeyAliasForIso(&serviceId, &keyTypeBuff, authId, outKeyAlias); + } else { + res = CombineKeyAliasForPake(&serviceId, &keyTypeBuff, authId, outKeyAlias); + } + if (res != HC_SUCCESS) { + LOGE("CombineKeyAlias failed, keyType: %d, res: %d", keyType, res); + } +err: + HcFree(serviceId.val); + return res; +} + +int32_t GetAndCheckAuthIdPeer(const CJson *in, const Uint8Buff *authIdPeer) +{ + const CJson *payload = GetObjFromJson(in, FIELD_PAYLOAD); + if (payload == NULL) { + LOGE("Get payload failed."); + return HC_ERR_JSON_GET; + } + const char *authIdStr = GetStringFromJson(payload, FIELD_PEER_AUTH_ID); + if (authIdStr == NULL) { + LOGE("Get peer authId from payload failed."); + return HC_ERR_JSON_GET; + } + uint32_t authIdPeerLen = HcStrlen(authIdStr) / BYTE_TO_HEX_OPER_LENGTH; + if (authIdPeerLen == 0 || authIdPeerLen > MAX_AUTH_ID_LEN) { + LOGE("Invalid peer authId length."); + return HC_ERR_INVALID_LEN; + } + uint8_t *authIdPeerTmp = (uint8_t *)HcMalloc(authIdPeerLen, 0); + if (authIdPeerTmp == NULL) { + LOGE("Malloc for authIdPeerTmp failed."); + return HC_ERR_ALLOC_MEMORY; + } + int32_t res = HexStringToByte(authIdStr, authIdPeerTmp, authIdPeerLen); + if (res != HC_SUCCESS) { + LOGE("Convert peer authId from hex string to byte failed, res: %d.", res); + goto err; + } + if (memcmp(authIdPeer->val, authIdPeerTmp, authIdPeer->length) != 0) { + LOGE("Peer authId does not match."); + res = HC_ERR_INVALID_PARAMS; + goto err; + } +err: + HcFree(authIdPeerTmp); + return res; +} + +int32_t GetAuthIdPeer(const CJson *in, Uint8Buff *authIdPeer) +{ + const CJson *payload = GetObjFromJson(in, FIELD_PAYLOAD); + if (payload == NULL) { + LOGE("Not have payload."); + return HC_ERR_INVALID_PARAMS; + } + const char *authIdStr = GetStringFromJson(payload, FIELD_PEER_AUTH_ID); + if (authIdStr == NULL) { + LOGE("AuthIdPeer in payload is null."); + return HC_ERR_INVALID_PARAMS; + } + uint32_t authIdLen = HcStrlen(authIdStr) / BYTE_TO_HEX_OPER_LENGTH; + if (authIdLen == 0 || authIdLen > MAX_AUTH_ID_LEN) { + LOGE("Invalid authIdPeerLen"); + return HC_ERR_INVALID_PARAMS; + } + int32_t res = InitSingleParam(authIdPeer, authIdLen); + if (res != HC_SUCCESS) { + LOGE("InitSingleParam for peer authId failed, res: %d.", res); + return res; + } + res = HexStringToByte(authIdStr, authIdPeer->val, authIdPeer->length); + if (res != HC_SUCCESS) { + LOGE("HexStringToByte for authIdPeer failed."); + } + + return res; +} + +int32_t GetAndCheckKeyLenOnServer(const CJson *in, uint32_t *keyLen) +{ + const CJson *payload = GetObjFromJson(in, FIELD_PAYLOAD); + if (payload == NULL) { + LOGE("Get payload failed."); + return HC_ERR_JSON_GET; + } + uint32_t tmpKeyLen = 0; + int32_t res = GetIntFromJson(payload, FIELD_KEY_LENGTH, (int *)&tmpKeyLen); + if (res != HC_SUCCESS) { + LOGE("Get tmpKeyLen from payload failed, res: %d.", res); + return HC_ERR_JSON_GET; + } + + if (*keyLen != tmpKeyLen) { + LOGE("Key length is not equal."); + return HC_ERR_INVALID_PARAMS; + } + return res; +} diff --git a/services/module/src/das_module/das_module.c b/services/module/src/das_module/das_module.c new file mode 100644 index 0000000..1a762e5 --- /dev/null +++ b/services/module/src/das_module/das_module.c @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "das_module.h" +#include "common_defs.h" +#include "hc_log.h" +#include "hc_types.h" +#include "hc_vector.h" +#include "task_main.h" + +DECLARE_HC_VECTOR(TaskInModuleVec, void *) +IMPLEMENT_HC_VECTOR(TaskInModuleVec, void *, 1) + +TaskInModuleVec g_taskInModuleVec; +DasAuthModule g_dasModule = {0}; + +static int32_t RegisterLocalIdentity(const char *pkgName, const char *serviceType, Uint8Buff *authId, int userType) +{ + return RegisterLocalIdentityInTask(pkgName, serviceType, authId, userType); +} + +static int32_t UnregisterLocalIdentity(const char *pkgName, const char *serviceType, Uint8Buff *authId, int userType) +{ + return UnregisterLocalIdentityInTask(pkgName, serviceType, authId, userType); +} + +static int32_t DeletePeerAuthInfo(const char *pkgName, const char *serviceType, Uint8Buff *authId, int userType) +{ + return DeletePeerAuthInfoInTask(pkgName, serviceType, authId, userType); +} + +static int CreateDasTask(int *taskId, const CJson *in, CJson *out) +{ + if (taskId == NULL || in == NULL || out == NULL) { + return HC_ERR_INVALID_PARAMS; + } + Task *task = CreateTaskT(taskId, in, out); + if (task == NULL) { + LOGE("CreateTaskT failed"); + return HC_ERR_ALLOC_MEMORY; + } + + g_taskInModuleVec.pushBackT(&g_taskInModuleVec, (void *)task); + return HC_SUCCESS; +} + +static void DestroyDasModule(AuthModuleBase *module) +{ + uint32_t index; + void **ptr = NULL; + FOR_EACH_HC_VECTOR(g_taskInModuleVec, index, ptr) { + if ((ptr != NULL) && (*ptr != NULL)) { + ((Task *)(*ptr))->destroyTask((Task *)(*ptr)); + } + } + DESTROY_HC_VECTOR(TaskInModuleVec, &g_taskInModuleVec) + DestroyDasProtocolType(); + if (module != NULL) { + (void)memset_s(module, sizeof(AuthModuleBase), 0, sizeof(AuthModuleBase)); + } +} + +static int ProcessDasTask(int taskId, const CJson* in, CJson* out, int *status) +{ + uint32_t index; + void **ptr = NULL; + FOR_EACH_HC_VECTOR(g_taskInModuleVec, index, ptr) { + if ((ptr != NULL) && (*ptr != NULL)) { + Task *temp = (Task *)*ptr; + if (taskId == temp->taskId) { + return temp->processTask(temp, in, out, status); + } + } + } + return HC_ERR_TASK_IS_NULL; +} + +static void DestroyDasTask(int taskId) +{ + uint32_t index; + void **ptr = NULL; + FOR_EACH_HC_VECTOR(g_taskInModuleVec, index, ptr) { + if ((ptr != NULL) && (*ptr != NULL)) { + Task *temp = (Task *)(*ptr); + if (taskId == temp->taskId) { + temp->destroyTask(temp); + void *tempPtr = NULL; + HC_VECTOR_POPELEMENT(&g_taskInModuleVec, &tempPtr, index); + return; + } + } + } +} + +bool IsDasSupported() +{ + return true; +} + +AuthModuleBase *CreateDasModule() +{ + g_dasModule.moduleBase.moduleType = DAS_MODULE; + g_dasModule.moduleBase.createTask = CreateDasTask; + g_dasModule.moduleBase.processTask = ProcessDasTask; + g_dasModule.moduleBase.destroyTask = DestroyDasTask; + g_dasModule.moduleBase.destroyModule = DestroyDasModule; + g_dasModule.registerLocalIdentity = RegisterLocalIdentity; + g_dasModule.unregisterLocalIdentity = UnregisterLocalIdentity; + g_dasModule.deletePeerAuthInfo = DeletePeerAuthInfo; + g_taskInModuleVec = CREATE_HC_VECTOR(TaskInModuleVec) + if (InitDasProtocolType() != HC_SUCCESS) { + LOGE("InitDasProtocolType failed."); + DestroyDasModule((AuthModuleBase *)&g_dasModule); + return NULL; + } + return (AuthModuleBase *)&g_dasModule; +} diff --git a/services/module/src/das_module/das_version_util.c b/services/module/src/das_module/das_version_util.c new file mode 100644 index 0000000..a641903 --- /dev/null +++ b/services/module/src/das_module/das_version_util.c @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "das_version_util.h" +#include "common_defs.h" +#include "common_util.h" +#include "hc_log.h" +#include "hc_types.h" +#include "json_utils.h" + +#define BIND_PRIORITY_LEN 5 +#define AUTH_PRIORITY_LEN 5 + +typedef struct PriorityMapT { + uint32_t alg; + ProtocolType type; +} PriorityMap; + +VersionStruct g_defaultVersion = { 1, 0, 0 }; +PriorityMap g_bindPriorityList[BIND_PRIORITY_LEN] = { + { NEW_EC_SPEKE, NEW_PAKE }, + { NEW_DL_SPEKE, NEW_PAKE }, + { EC_SPEKE, PAKE }, + { DL_SPEKE, PAKE }, + { ISO_ALG, ISO } +}; +PriorityMap g_authPriorityList[AUTH_PRIORITY_LEN] = { + { PSK_SPEKE | NEW_EC_SPEKE, NEW_PAKE }, + { PSK_SPEKE | NEW_DL_SPEKE, NEW_PAKE }, + { PSK_SPEKE | EC_SPEKE, PAKE }, + { PSK_SPEKE | DL_SPEKE, PAKE }, + { ISO_ALG, ISO } +}; + +int32_t GetVersionFromJson(const CJson* jsonObj, VersionStruct *minVer, VersionStruct *maxVer) +{ + CHECK_PTR_RETURN_ERROR_CODE(jsonObj, "jsonObj"); + CHECK_PTR_RETURN_ERROR_CODE(minVer, "minVer"); + CHECK_PTR_RETURN_ERROR_CODE(maxVer, "maxVer"); + + const char *minStr = GetStringFromJson(jsonObj, FIELD_MIN_VERSION); + CHECK_PTR_RETURN_ERROR_CODE(minStr, "minStr"); + const char *maxStr = GetStringFromJson(jsonObj, FIELD_CURRENT_VERSION); + CHECK_PTR_RETURN_ERROR_CODE(maxStr, "maxStr"); + + int32_t minRet = StringToVersion(minStr, strlen(minStr), minVer); + int32_t maxRet = StringToVersion(maxStr, strlen(maxStr), maxVer); + if (minRet != HC_SUCCESS || maxRet != HC_SUCCESS) { + return HC_ERROR; + } + return HC_SUCCESS; +} + +int32_t AddVersionToJson(CJson *jsonObj, const VersionStruct *minVer, const VersionStruct *maxVer) +{ + CHECK_PTR_RETURN_ERROR_CODE(jsonObj, "jsonObj"); + CHECK_PTR_RETURN_ERROR_CODE(minVer, "minVer"); + CHECK_PTR_RETURN_ERROR_CODE(maxVer, "maxVer"); + + char minStr[TMP_VERSION_STR_LEN] = { 0 }; + int32_t minRet = VersionToString(minVer, minStr, TMP_VERSION_STR_LEN); + char maxStr[TMP_VERSION_STR_LEN] = { 0 }; + int32_t maxRet = VersionToString(maxVer, maxStr, TMP_VERSION_STR_LEN); + if (minRet != HC_SUCCESS || maxRet != HC_SUCCESS) { + return HC_ERROR; + } + CJson* version = CreateJson(); + if (version == NULL) { + LOGE("CreateJson for version failed."); + return HC_ERR_JSON_CREATE; + } + if (AddStringToJson(version, FIELD_MIN_VERSION, minStr) != HC_SUCCESS) { + LOGE("Add min version to json failed."); + FreeJson(version); + return HC_ERR_JSON_ADD; + } + if (AddStringToJson(version, FIELD_CURRENT_VERSION, maxStr) != HC_SUCCESS) { + LOGE("Add max version to json failed."); + FreeJson(version); + return HC_ERR_JSON_ADD; + } + if (AddObjToJson(jsonObj, FIELD_VERSION, version) != HC_SUCCESS) { + LOGE("Add version object to json failed."); + FreeJson(version); + return HC_ERR_JSON_ADD; + } + FreeJson(version); + return HC_SUCCESS; +} + +bool IsVersionEqual(VersionStruct *src, VersionStruct *des) +{ + if ((src->first == des->first) && (src->second == des->second) && (src->third == des->third)) { + return true; + } + return false; +} + +int32_t NegotiateVersion(VersionStruct *minVersionPeer, VersionStruct *curVersionPeer, + VersionStruct *curVersionSelf) +{ + (void)minVersionPeer; + if (IsVersionEqual(curVersionPeer, &g_defaultVersion)) { + curVersionSelf->first = g_defaultVersion.first; + curVersionSelf->second = g_defaultVersion.second; + curVersionSelf->third = g_defaultVersion.third; + return HC_SUCCESS; + } + curVersionSelf->third = curVersionSelf->third & curVersionPeer->third; + if (curVersionSelf->third == 0) { + LOGE("Unsupported version!"); + return HC_ERR_UNSUPPORTED_VERSION; + } + return HC_SUCCESS; +} + +static ProtocolType GetBindPrototolType(VersionStruct *curVersion) +{ + if (IsVersionEqual(curVersion, &g_defaultVersion)) { + return PAKE; + } else { + for (int i = 0; i < BIND_PRIORITY_LEN; i++) { + if ((curVersion->third & g_bindPriorityList[i].alg) == g_bindPriorityList[i].alg) { + return g_bindPriorityList[i].type; + } + } + } + return UNSUPPORTED; +} + +static ProtocolType GetAuthPrototolType(VersionStruct *curVersion) +{ + if (IsVersionEqual(curVersion, &g_defaultVersion)) { + return STS; + } else { + for (int i = 0; i < AUTH_PRIORITY_LEN; i++) { + if ((curVersion->third & g_authPriorityList[i].alg) == g_authPriorityList[i].alg) { + return g_authPriorityList[i].type; + } + } + } + return UNSUPPORTED; +} + +ProtocolType GetPrototolType(VersionStruct *curVersion, OperationCode opCode) +{ + if (opCode == OP_BIND) { + return GetBindPrototolType(curVersion); + } else { + return GetAuthPrototolType(curVersion); + } +} + +AlgType GetSupportedPakeAlg(VersionStruct *curVersion) +{ + return curVersion->third & (DL_SPEKE | EC_SPEKE | PSK_SPEKE | NEW_DL_SPEKE | NEW_EC_SPEKE); +} + +bool IsSupportedPsk(VersionStruct *curVersion) +{ + if (curVersion->third & PSK_SPEKE) { + return true; + } + return false; +} \ No newline at end of file diff --git a/services/module/src/das_module/iso_task/iso_client_task.c b/services/module/src/das_module/iso_task/iso_client_task.c new file mode 100644 index 0000000..8a0e8c2 --- /dev/null +++ b/services/module/src/das_module/iso_task/iso_client_task.c @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "iso_client_task.h" +#include "das_common.h" +#include "hc_log.h" +#include "hc_types.h" +#include "iso_client_bind_exchange_task.h" +#include "iso_client_protocol_task.h" +#include "iso_client_unbind_exchange_task.h" +#include "iso_task_common.h" + +static int GetIsoClientTaskType(const struct SubTaskBaseT *task) +{ + IsoClientTask *realTask = (IsoClientTask *)task; + if (realTask->curTask == NULL) { + LOGE("cur Task is null"); + return TASK_TYPE_NONE; + } + return realTask->curTask->getCurTaskType(); +} + +static void DestroyIsoClientTask(struct SubTaskBaseT *task) +{ + IsoClientTask *innerTask = (IsoClientTask *)task; + if (innerTask == NULL) { + return; + } + DestroyIsoParams(&(innerTask->params)); + if (innerTask->curTask != NULL) { + innerTask->curTask->destroyTask(innerTask->curTask); + } + HcFree(innerTask); +} + +static int CreateNextTask(IsoClientTask *realTask, const CJson *in, CJson *out, int *status) +{ + int res = HC_SUCCESS; + switch (realTask->params.opCode) { + case OP_BIND: + if (realTask->curTask->getCurTaskType() == TASK_TYPE_BIND_LITE_EXCHANGE) { + LOGD("bind exchange task end"); + *status = FINISH; + return HC_SUCCESS; + } + realTask->curTask->destroyTask(realTask->curTask); + realTask->curTask = CreateClientBindExchangeTask(&(realTask->params), in, out, status); + if (realTask->curTask == NULL) { + LOGE("CreateBindExchangeTask failed"); + SendErrorToOut(out, realTask->params.opCode, HC_ERROR); + return HC_ERROR; + } + break; + case OP_UNBIND: + if (realTask->curTask->getCurTaskType() == TASK_TYPE_UNBIND_LITE_EXCHANGE) { + LOGD("unbind exchange task end"); + *status = FINISH; + return HC_SUCCESS; + } + realTask->curTask->destroyTask(realTask->curTask); + realTask->curTask = CreateClientUnbindExchangeTask(&(realTask->params), in, out, status); + if (realTask->curTask == NULL) { + LOGE("CreateBindExchangeTask failed"); + SendErrorToOut(out, realTask->params.opCode, HC_ERROR); + return HC_ERROR; + } + break; + default: + res = GenEncResult(&(realTask->params), ISO_RESULT_CONFIRM_CMD, out, RESULT_AAD, true); + if (res != HC_SUCCESS) { + LOGE("GenEncResult failed, res:%d", res); + SendErrorToOut(out, realTask->params.opCode, res); + return res; + } + LOGD("Authenticate task end."); + *status = FINISH; + break; + } + return res; +} + +static int Process(struct SubTaskBaseT *task, const CJson *in, CJson *out, int *status) +{ + if (task == NULL || in == NULL || out == NULL || status == NULL) { + return HC_ERR_INVALID_PARAMS; + } + IsoClientTask *realTask = (IsoClientTask *)task; + if (realTask->curTask == NULL) { + LOGE("cur Task is null"); + return HC_ERROR; + } + int res = realTask->curTask->process(realTask->curTask, &(realTask->params), in, out, status); + if (*status != FINISH) { + if (res != 0) { + SendErrorToOut(out, realTask->params.opCode, res); + } + return res; + } + if (res != 0) { + LOGE("process failed, res:%d", res); + SendErrorToOut(out, realTask->params.opCode, res); + return res; + } + return CreateNextTask(realTask, in, out, status); +} + +SubTaskBase *CreateIsoClientTask(const CJson *in) +{ + IsoClientTask *task = (IsoClientTask *)HcMalloc(sizeof(IsoClientTask), 0); + if (task == NULL) { + return NULL; + } + + task->taskBase.getTaskType = GetIsoClientTaskType; + task->taskBase.destroyTask = DestroyIsoClientTask; + task->taskBase.process = Process; + + int res = InitIsoParams(&(task->params), in); + if (res != 0) { + DestroyIsoClientTask((struct SubTaskBaseT *)task); + return NULL; + } + + task->curTask = CreateProtocolClientTask(); + if (task->curTask == NULL) { + DestroyIsoClientTask((struct SubTaskBaseT *)task); + return NULL; + } + return (SubTaskBase *)task; +} diff --git a/services/module/src/das_module/iso_task/iso_protocol_task/iso_client_protocol_task.c b/services/module/src/das_module/iso_task/iso_protocol_task/iso_client_protocol_task.c new file mode 100644 index 0000000..0602992 --- /dev/null +++ b/services/module/src/das_module/iso_task/iso_protocol_task/iso_client_protocol_task.c @@ -0,0 +1,298 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "iso_client_protocol_task.h" +#include "common_defs.h" +#include "das_common.h" +#include "hc_log.h" +#include "hc_types.h" +#include "iso_protocol_common.h" +#include "iso_task_common.h" + +enum { + TASK_STATUS_BEGIN = 0, + TASK_STATUS_SERVER_RES_TOKEN, + TASK_STATUS_GEN_SESSION_KEY, + TASK_STATUS_FINAL, +}; + +static CurTaskType GetTaskType() +{ + return TASK_TYPE_ISO_PROTOCOL; +} + +static void DestroyProtocolClientTask(struct SymBaseCurTaskT *task) +{ + IsoProtocolClientTask *realTask = (IsoProtocolClientTask *)task; + if (realTask == NULL) { + return; + } + HcFree(realTask); +} + +static int IsoClientStartPackData(CJson *out, const IsoParams *params) +{ + int res = HC_SUCCESS; + CJson *payload = NULL; + CJson *sendToPeer = NULL; + payload = CreateJson(); + if (payload == NULL) { + res = HC_ERR_ALLOC_MEMORY; + goto err; + } + sendToPeer = CreateJson(); + if (sendToPeer == NULL) { + res = HC_ERR_ALLOC_MEMORY; + goto err; + } + GOTO_ERR_AND_SET_RET(AddIntToJson(sendToPeer, FIELD_AUTH_FORM, AUTH_FORM_ACCOUNT_UNRELATED), res); + + GOTO_ERR_AND_SET_RET(AddByteToJson(payload, FIELD_ISO_SALT, params->baseParams.randSelf.val, + params->baseParams.randSelf.length), res); + GOTO_ERR_AND_SET_RET(AddByteToJson(payload, FIELD_PEER_AUTH_ID, params->baseParams.authIdSelf.val, + params->baseParams.authIdSelf.length), res); + GOTO_ERR_AND_SET_RET(AddIntToJson(payload, FIELD_OPERATION_CODE, params->opCode), res); + GOTO_ERR_AND_SET_RET(AddByteToJson(payload, FIELD_SEED, params->seed.val, params->seed.length), res); + GOTO_ERR_AND_SET_RET(AddIntToJson(payload, FIELD_PEER_USER_TYPE, params->selfUserType), res); + if (params->opCode == AUTHENTICATE || params->opCode == OP_UNBIND) { + GOTO_ERR_AND_SET_RET(AddStringToJson(payload, FIELD_PKG_NAME, params->packageName), res); + GOTO_ERR_AND_SET_RET(AddStringToJson(payload, FIELD_SERVICE_TYPE, params->serviceType), res); + GOTO_ERR_AND_SET_RET(AddIntToJson(payload, FIELD_KEY_LENGTH, params->keyLen), res); + } + GOTO_ERR_AND_SET_RET(AddObjToJson(sendToPeer, FIELD_PAYLOAD, payload), res); + GOTO_ERR_AND_SET_RET(AddObjToJson(out, FIELD_SEND_TO_PEER, sendToPeer), res); +err: + FreeJson(payload); + FreeJson(sendToPeer); + return res; +} + +static int IsoClientStart(SymBaseCurTask *task, IsoParams *params, const CJson *in, CJson *out, int *status) +{ + if (task->taskStatus != TASK_STATUS_BEGIN) { + LOGI("The message is repeated, ignore it, status :%d", task->taskStatus); + *status = IGNORE_MSG; + return HC_SUCCESS; + } + int res; + res = IsoClientGenRandom(¶ms->baseParams); + if (res != 0) { + return res; + } + res = GenerateSeed(params); + if (res != 0) { + return res; + } + res = IsoClientStartPackData(out, params); + if (res != 0) { + LOGE("IsoClientStartPackData failed, res:%d", res); + return res; + } + task->taskStatus = TASK_STATUS_SERVER_RES_TOKEN; + *status = CONTINUE; + return res; +} + +static int PackDataForCalToken(const IsoParams *params, const Uint8Buff *selfTokenBuf, CJson *out) +{ + int res = HC_SUCCESS; + CJson *payload = NULL; + CJson *sendToPeer = NULL; + + sendToPeer = CreateJson(); + if (sendToPeer == NULL) { + res = HC_ERR_ALLOC_MEMORY; + goto err; + } + payload = CreateJson(); + if (payload == NULL) { + res = HC_ERR_ALLOC_MEMORY; + goto err; + } + + GOTO_ERR_AND_SET_RET(AddIntToJson(sendToPeer, FIELD_AUTH_FORM, AUTH_FORM_ACCOUNT_UNRELATED), res); + GOTO_ERR_AND_SET_RET(AddByteToJson(payload, FIELD_PEER_AUTH_ID, params->baseParams.authIdSelf.val, + params->baseParams.authIdSelf.length), res); + GOTO_ERR_AND_SET_RET(AddByteToJson(payload, FIELD_TOKEN, selfTokenBuf->val, selfTokenBuf->length), res); + GOTO_ERR_AND_SET_RET(AddObjToJson(sendToPeer, FIELD_PAYLOAD, payload), res); + GOTO_ERR_AND_SET_RET(AddObjToJson(out, FIELD_SEND_TO_PEER, sendToPeer), res); +err: + FreeJson(payload); + FreeJson(sendToPeer); + return res; +} + +static int ParseServerStartMessage(IsoParams *params, const CJson *in, uint8_t *peerToken) +{ + if (params->opCode == OP_BIND) { + RETURN_IF_ERR(GetAuthIdPeer(in, &(params->baseParams.authIdPeer))); + } else { + RETURN_IF_ERR(GetAndCheckAuthIdPeer(in, &(params->baseParams.authIdPeer))); + } + RETURN_IF_ERR(GetByteFromJson(in, FIELD_ISO_SALT, params->baseParams.randPeer.val, + params->baseParams.randPeer.length)); + RETURN_IF_ERR(GetByteFromJson(in, FIELD_TOKEN, peerToken, ISO_TOKEN_LEN)); + RETURN_IF_ERR(GetIntFromJson(in, FIELD_PEER_USER_TYPE, &(params->peerUserType))); + return HC_SUCCESS; +} + +static int CalculateTokenClient(SymBaseCurTask *task, IsoParams *params, const CJson *in, CJson *out, int *status) +{ + int res; + uint8_t *peerToken = NULL; + uint8_t *selfToken = NULL; + if (task->taskStatus < TASK_STATUS_SERVER_RES_TOKEN) { + LOGE("Invalid taskStatus:%d", task->taskStatus); + return HC_ERR_BAD_MESSAGE; + } + + if (task->taskStatus > TASK_STATUS_SERVER_RES_TOKEN) { + LOGI("The message is repeated, ignore it, status :%d", task->taskStatus); + *status = IGNORE_MSG; + return HC_SUCCESS; + } + + // parse message + peerToken = (uint8_t *)HcMalloc(ISO_TOKEN_LEN, 0); + if (peerToken == NULL) { + res = HC_ERR_ALLOC_MEMORY; + goto err; + } + Uint8Buff peerTokenBuf = { peerToken, ISO_TOKEN_LEN }; + + selfToken = (uint8_t *)HcMalloc(ISO_TOKEN_LEN, 0); + if (selfToken == NULL) { + res = HC_ERR_ALLOC_MEMORY; + goto err; + } + Uint8Buff selfTokenBuf = { selfToken, ISO_TOKEN_LEN }; + + res = ParseServerStartMessage(params, in, peerToken); + if (res != 0) { + LOGE("ParseServerStartMessage failed, res:%d", res); + goto err; + } + res = GeneratePsk(in, params); + if (res != 0) { + LOGE("GeneratePsk failed, res:%d", res); + goto err; + } + + // execute + res = IsoClientCheckAndGenToken(¶ms->baseParams, &peerTokenBuf, &selfTokenBuf); + if (res != HC_SUCCESS) { + LOGE("IsoClientCheckAndGenToken failed, res:%d", res); + goto err; + } + + // package message + res = PackDataForCalToken(params, &selfTokenBuf, out); + if (res != 0) { + LOGE("PackDataForCalToken failed, res: %d", res); + goto err; + } + task->taskStatus = TASK_STATUS_GEN_SESSION_KEY; + *status = CONTINUE; +err: + HcFree(peerToken); + HcFree(selfToken); + return res; +} + +static int GenerateSessionKey(SymBaseCurTask *task, IsoParams *params, const CJson *in, int *status) +{ + if (task->taskStatus < TASK_STATUS_GEN_SESSION_KEY) { + LOGE("Invalid taskStatus:%d", task->taskStatus); + return HC_ERR_BAD_MESSAGE; + } + + if (task->taskStatus > TASK_STATUS_GEN_SESSION_KEY) { + LOGI("The message is repeated, ignore it, status :%d", task->taskStatus); + *status = IGNORE_MSG; + return HC_SUCCESS; + } + + uint8_t *hmac = (uint8_t *)HcMalloc(HMAC_LEN, 0); + if (hmac == NULL) { + return HC_ERR_ALLOC_MEMORY; + } + int res = GetByteFromJson(in, FIELD_RETURN_CODE_MAC, hmac, HMAC_LEN); + if (res != 0) { + LOGE("get mac failed, res:%d", res); + goto err; + } + + // execute + res = IsoClientGenSessionKey(¶ms->baseParams, 0, hmac, HMAC_LEN); + if (res != 0) { + LOGE("IsoClientGenSessionKey failed, res:%d", res); + goto err; + } + + task->taskStatus = TASK_STATUS_FINAL; + *status = FINISH; +err: + HcFree(hmac); + return res; +} + +static int Process(struct SymBaseCurTaskT *task, IsoParams *params, const CJson *in, CJson *out, + int *status) +{ + int res; + uint32_t step = ProtocolMessageIn(in); + if (step == INVALID_MESSAGE) { + res = IsoClientStart(task, params, in, out, status); + step = STEP_ONE; + goto out_func; + } + + step = step + 1; /* when receive peer message code, need to do next step */ + switch (step) { + case STEP_TWO: + res = CalculateTokenClient(task, params, in, out, status); + break; + case STEP_THREE: + res = GenerateSessionKey(task, params, in, status); + break; + default: + res = HC_ERR_BAD_MESSAGE; + break; + } +out_func: + if (res != HC_SUCCESS) { + return res; + } + if (step != STEP_THREE) { + res = ClientProtocolMessageOut(out, params->opCode, step); + if (res != HC_SUCCESS) { + LOGE("ClientProtocolMessageOut failed, res:%d", res); + } + } + + return res; +} + +SymBaseCurTask *CreateProtocolClientTask() +{ + IsoProtocolClientTask *task = (IsoProtocolClientTask *)HcMalloc(sizeof(IsoProtocolClientTask), 0); + if (task == NULL) { + return NULL; + } + task->taskBase.destroyTask = DestroyProtocolClientTask; + task->taskBase.process = Process; + task->taskBase.getCurTaskType = GetTaskType; + return (SymBaseCurTask *)task; +} \ No newline at end of file diff --git a/services/module/src/das_module/iso_task/iso_protocol_task/iso_server_protocol_task.c b/services/module/src/das_module/iso_task/iso_protocol_task/iso_server_protocol_task.c new file mode 100644 index 0000000..0a17cfa --- /dev/null +++ b/services/module/src/das_module/iso_task/iso_protocol_task/iso_server_protocol_task.c @@ -0,0 +1,246 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "iso_server_protocol_task.h" +#include "common_defs.h" +#include "das_common.h" +#include "hc_log.h" +#include "hc_types.h" +#include "iso_protocol_common.h" +#include "iso_task_common.h" +#include "protocol_common.h" + +enum { + TASK_STATUS_BEGIN = 0, + TASK_STATUS_CMD_RES_TOKEN, + TASK_STATUS_GEN_SESSION_KEY, + TASK_STATUS_FINAL, +}; + +static CurTaskType GetTaskType() +{ + return TASK_TYPE_ISO_PROTOCOL; +} + +static void DestroyProtocolServerTask(struct SymBaseCurTaskT *task) +{ + IsoProtocolServerTask *realTask = (IsoProtocolServerTask *)task; + if (realTask == NULL) { + return; + } + HcFree(realTask); +} + +static int PackageServerStartMessage(const IsoParams *params, const Uint8Buff *selfTokenBuf, CJson *out) +{ + int res; + CJson *payload = NULL; + CJson *sendToPeer = NULL; + payload = CreateJson(); + if (payload == NULL) { + res = HC_ERR_ALLOC_MEMORY; + goto err; + } + sendToPeer = CreateJson(); + if (sendToPeer == NULL) { + res = HC_ERR_ALLOC_MEMORY; + goto err; + } + GOTO_ERR_AND_SET_RET(AddByteToJson(payload, FIELD_ISO_SALT, params->baseParams.randSelf.val, + params->baseParams.randSelf.length), res); + GOTO_ERR_AND_SET_RET(AddByteToJson(payload, FIELD_TOKEN, selfTokenBuf->val, selfTokenBuf->length), res); + GOTO_ERR_AND_SET_RET(AddByteToJson(payload, FIELD_PEER_AUTH_ID, params->baseParams.authIdSelf.val, + params->baseParams.authIdSelf.length), res); + GOTO_ERR_AND_SET_RET(AddIntToJson(payload, FIELD_PEER_USER_TYPE, params->selfUserType), res); + GOTO_ERR_AND_SET_RET(AddIntToJson(payload, FIELD_OPERATION_CODE, params->opCode), res); + GOTO_ERR_AND_SET_RET(AddIntToJson(sendToPeer, FIELD_AUTH_FORM, AUTH_FORM_ACCOUNT_UNRELATED), res); + GOTO_ERR_AND_SET_RET(AddObjToJson(sendToPeer, FIELD_PAYLOAD, payload), res); + GOTO_ERR_AND_SET_RET(AddObjToJson(out, FIELD_SEND_TO_PEER, sendToPeer), res); +err: + FreeJson(payload); + FreeJson(sendToPeer); + return res; +} + +static int IsoServerStart(SymBaseCurTask *task, IsoParams *params, const CJson *in, CJson *out, int *status) +{ + if (task->taskStatus != TASK_STATUS_BEGIN) { + LOGI("The message is repeated, ignore it, status :%d", task->taskStatus); + *status = IGNORE_MSG; + return HC_SUCCESS; + } + int res; + uint8_t *selfToken = (uint8_t *)HcMalloc(ISO_TOKEN_LEN, 0); + if (selfToken == NULL) { + return HC_ERR_ALLOC_MEMORY; + } + Uint8Buff selfTokenBuf = { selfToken, ISO_TOKEN_LEN }; + if (params->opCode == OP_BIND) { + GOTO_ERR_AND_SET_RET(GetAuthIdPeer(in, &(params->baseParams.authIdPeer)), res); + } else { + GOTO_ERR_AND_SET_RET(GetAndCheckAuthIdPeer(in, &(params->baseParams.authIdPeer)), res); + GOTO_ERR_AND_SET_RET(GetAndCheckKeyLenOnServer(in, &(params->keyLen)), res); + } + GOTO_ERR_AND_SET_RET(GetByteFromJson(in, FIELD_ISO_SALT, params->baseParams.randPeer.val, + params->baseParams.randPeer.length), res); + res = GeneratePsk(in, params); + if (res != 0) { + LOGE("Generate psk failed, res:%d", res); + goto err; + } + res = IsoServerGenRandomAndToken(¶ms->baseParams, &selfTokenBuf); + if (res != 0) { + LOGE("IsoServerGenRandomAndToken failed, res:%d", res); + goto err; + } + + res = PackageServerStartMessage(params, &selfTokenBuf, out); + if (res != HC_SUCCESS) { + LOGE("PackageServerStartMessage failed."); + goto err; + } + + task->taskStatus = TASK_STATUS_CMD_RES_TOKEN; + *status = CONTINUE; +err: + HcFree(selfToken); + return res; +} + +static int PackDataForCalTokenServer(const IsoParams *params, const Uint8Buff *tokenToPeer, CJson *out) +{ + int res = 0; + CJson *payload = NULL; + CJson *sendToPeer = NULL; + + sendToPeer = CreateJson(); + if (sendToPeer == NULL) { + res = HC_ERR_ALLOC_MEMORY; + goto err; + } + payload = CreateJson(); + if (payload == NULL) { + res = HC_ERR_ALLOC_MEMORY; + goto err; + } + GOTO_ERR_AND_SET_RET(AddByteToJson(payload, FIELD_PEER_AUTH_ID, params->baseParams.authIdSelf.val, + params->baseParams.authIdSelf.length), res); + GOTO_ERR_AND_SET_RET(AddByteToJson(payload, FIELD_RETURN_CODE_MAC, tokenToPeer->val, tokenToPeer->length), res); + GOTO_ERR_AND_SET_RET(AddIntToJson(payload, FIELD_OPERATION_CODE, params->opCode), res); + GOTO_ERR_AND_SET_RET(AddIntToJson(sendToPeer, FIELD_AUTH_FORM, AUTH_FORM_ACCOUNT_UNRELATED), res); + GOTO_ERR_AND_SET_RET(AddObjToJson(sendToPeer, FIELD_PAYLOAD, payload), res); + GOTO_ERR_AND_SET_RET(AddObjToJson(out, FIELD_SEND_TO_PEER, sendToPeer), res); +err: + FreeJson(payload); + FreeJson(sendToPeer); + return res; +} + +static int CalTokenAndGenSessionKey(SymBaseCurTask *task, IsoParams *params, const CJson *in, CJson *out, int *status) +{ + int res; + uint8_t *peerToken = NULL; + uint8_t *tokenSelf = NULL; + + if (task->taskStatus < TASK_STATUS_CMD_RES_TOKEN) { + LOGE("Invalid taskStatus:%d", task->taskStatus); + return HC_ERR_BAD_MESSAGE; + } + + if (task->taskStatus > TASK_STATUS_CMD_RES_TOKEN) { + LOGI("The message is repeated, ignore it, status :%d", task->taskStatus); + *status = IGNORE_MSG; + return HC_SUCCESS; + } + + // parse message + peerToken = (uint8_t *)HcMalloc(ISO_TOKEN_LEN, 0); + if (peerToken == NULL) { + res = HC_ERR_ALLOC_MEMORY; + goto err; + } + GOTO_ERR_AND_SET_RET(GetByteFromJson(in, FIELD_TOKEN, peerToken, ISO_TOKEN_LEN), res); + Uint8Buff tokenFromPeer = { peerToken, ISO_TOKEN_LEN }; + + tokenSelf = (uint8_t *)HcMalloc(ISO_TOKEN_LEN, 0); + if (tokenSelf == NULL) { + res = HC_ERR_ALLOC_MEMORY; + goto err; + } + Uint8Buff tokenToPeer = { tokenSelf, ISO_TOKEN_LEN }; + + // execute + res = IsoServerGenSessionKeyAndCalToken(¶ms->baseParams, &tokenFromPeer, &tokenToPeer); + if (res != 0) { + LOGE("IsoServerGenSessionKeyAndCalToken failed, res:%d", res); + goto err; + } + + // package message + res = PackDataForCalTokenServer(params, &tokenToPeer, out); + if (res != 0) { + LOGE("PackDataForCalTokenServer failed, res:%d", res); + goto err; + } + task->taskStatus = TASK_STATUS_GEN_SESSION_KEY; + *status = FINISH; +err: + HcFree(peerToken); + HcFree(tokenSelf); + return res; +} + +static int Process(struct SymBaseCurTaskT *task, IsoParams *params, const CJson *in, CJson *out, int *status) +{ + int res; + if ((task == NULL) || (in == NULL) || (out == NULL) || (status == NULL) || (params == NULL)) { + res = HC_ERR_INVALID_PARAMS; + goto out; + } + uint32_t step = ProtocolMessageIn(in); + if (step == INVALID_MESSAGE) { + res = HC_ERR_BAD_MESSAGE; + goto out; + } + switch (step) { + case STEP_ONE: + res = IsoServerStart(task, params, in, out, status); + break; + case STEP_TWO: + res = CalTokenAndGenSessionKey(task, params, in, out, status); + break; + default: + res = HC_ERR_BAD_MESSAGE; + break; + } +out: + if (res == 0) { + res = ServerProtocolMessageOut(out, params->opCode, step); + } + + return res; +} + +SymBaseCurTask *CreateProtocolServerTask() +{ + IsoProtocolServerTask *task = (IsoProtocolServerTask *)HcMalloc(sizeof(IsoProtocolServerTask), 0); + if (task == NULL) { + return NULL; + } + task->taskBase.destroyTask = DestroyProtocolServerTask; + task->taskBase.process = Process; + task->taskBase.getCurTaskType = GetTaskType; + return (SymBaseCurTask *)task; +} \ No newline at end of file diff --git a/services/module/src/das_module/iso_task/iso_server_task.c b/services/module/src/das_module/iso_task/iso_server_task.c new file mode 100644 index 0000000..6cb1edb --- /dev/null +++ b/services/module/src/das_module/iso_task/iso_server_task.c @@ -0,0 +1,161 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "iso_server_task.h" +#include "das_common.h" +#include "hc_log.h" +#include "hc_types.h" +#include "iso_server_bind_exchange_task.h" +#include "iso_server_protocol_task.h" +#include "iso_server_unbind_exchange_task.h" +#include "iso_task_common.h" + +static int GetIsoServerTaskType(const struct SubTaskBaseT *task) +{ + IsoServerTask *realTask = (IsoServerTask *)task; + if (realTask->curTask == NULL) { + LOGE("cur Task is null"); + return TASK_TYPE_NONE; + } + return realTask->curTask->getCurTaskType(); +} + +static void DestroyIsoServerTask(struct SubTaskBaseT *task) +{ + IsoServerTask *innerTask = (IsoServerTask *)task; + if (innerTask == NULL) { + return; + } + DestroyIsoParams(&(innerTask->params)); + if (innerTask->curTask != NULL) { + innerTask->curTask->destroyTask(innerTask->curTask); + } + HcFree(innerTask); +} + +static int CreateNextTask(IsoServerTask *realTask, const CJson *in, CJson *out, int *status) +{ + int message = 0; + int res = GetIntFromJson(in, FIELD_MESSAGE, &message); + if (res != 0) { + LOGE("GetIntFromJson failed, res:%d", res); + return res; + } + switch (realTask->params.opCode) { + case OP_BIND: + if (message != ISO_CLIENT_BIND_EXCHANGE_CMD) { + LOGI("The message is repeated, ignore it message :%d.", message); + *status = IGNORE_MSG; + break; + } + realTask->curTask = CreateServerBindExchangeTask(&(realTask->params), in, out, status); + if (realTask->curTask == NULL) { + LOGE("CreateBindExchangeTask failed"); + res = HC_ERROR; + } + break; + case OP_UNBIND: + if (message != ISO_CLIENT_UNBIND_EXCHANGE_CMD) { + LOGI("The message is repeated, ignore it message :%d.", message); + *status = IGNORE_MSG; + break; + } + realTask->curTask = CreateServerUnbindExchangeTask(&(realTask->params), in, out, status); + if (realTask->curTask == NULL) { + LOGE("CreateBindExchangeTask failed"); + res = HC_ERROR; + } + break; + default: + res = CheckEncResult(&(realTask->params), in, RESULT_AAD); + if (res != 0) { + LOGE("CheckEncResult failed, res:%d", res); + break; + } + res = SendResultToFinalSelf(&(realTask->params), out, true); + if (res != 0) { + LOGE("SendResultToFinalSelf failed, res:%d", res); + break; + } + LOGD("Authenticate task end."); + *status = FINISH; + } + if (res != 0) { + SendErrorToOut(out, realTask->params.opCode, res); + } + return res; +} + +static int Process(struct SubTaskBaseT *task, const CJson *in, CJson *out, int *status) +{ + if (task == NULL || in == NULL || out == NULL || status == NULL) { + return HC_ERR_INVALID_PARAMS; + } + IsoServerTask *realTask = (IsoServerTask *)task; + int res; + if (realTask->curTask != NULL) { + res = realTask->curTask->process(realTask->curTask, &(realTask->params), in, out, status); + if (*status != FINISH) { + if (res != 0) { + SendErrorToOut(out, realTask->params.opCode, res); + } + return res; + } else { + if (realTask->curTask->getCurTaskType() == TASK_TYPE_ISO_PROTOCOL) { + realTask->curTask->destroyTask(realTask->curTask); + realTask->curTask = NULL; + *status = CONTINUE; + } + } + if (res != 0) { + LOGE("process failed, res:%d", res); + SendErrorToOut(out, realTask->params.opCode, res); + return res; + } + } else { + res = CreateNextTask(realTask, in, out, status); + } + if (res != 0) { + SendErrorToOut(out, realTask->params.opCode, res); + } + return res; +} + +SubTaskBase *CreateIsoServerTask(const CJson *in, CJson *out) +{ + IsoServerTask *task = (IsoServerTask *)HcMalloc(sizeof(IsoServerTask), 0); + if (task == NULL) { + return NULL; + } + + task->taskBase.getTaskType = GetIsoServerTaskType; + task->taskBase.destroyTask = DestroyIsoServerTask; + task->taskBase.process = Process; + + int res = InitIsoParams(&(task->params), in); + if (res != 0) { + SendErrorToOut(out, task->params.opCode, res); + DestroyIsoServerTask((struct SubTaskBaseT *)task); + return NULL; + } + + task->curTask = CreateProtocolServerTask(); + if (task->curTask == NULL) { + SendErrorToOut(out, task->params.opCode, res); + DestroyIsoServerTask((struct SubTaskBaseT *)task); + return NULL; + } + return (SubTaskBase *)task; +} diff --git a/services/module/src/das_module/iso_task/iso_task_common.c b/services/module/src/das_module/iso_task/iso_task_common.c new file mode 100755 index 0000000..694ba51 --- /dev/null +++ b/services/module/src/das_module/iso_task/iso_task_common.c @@ -0,0 +1,633 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "iso_task_common.h" +#include +#include "das_common.h" +#include "das_module_defines.h" +#include "hc_log.h" +#include "hc_types.h" +#include "iso_protocol_common.h" + +static int GenerateReturnKey(const IsoParams *params, uint8_t *returnKey, uint32_t returnKeyLen) +{ + int hkdfSaltLen = params->baseParams.randPeer.length + params->baseParams.randPeer.length; + int res; + uint8_t *hkdfSalt = (uint8_t *)HcMalloc(hkdfSaltLen, 0); + if (hkdfSalt == NULL) { + return HC_ERR_ALLOC_MEMORY; + } + if (params->isClient) { + if (memcpy_s(hkdfSalt, hkdfSaltLen, params->baseParams.randSelf.val, + params->baseParams.randSelf.length) != EOK) { + LOGE("Copy randSelf failed."); + res = HC_ERR_MEMORY_COPY; + goto err; + } + if (memcpy_s(hkdfSalt + params->baseParams.randSelf.length, hkdfSaltLen - params->baseParams.randSelf.length, + params->baseParams.randPeer.val, params->baseParams.randPeer.length) != EOK) { + LOGE("Copy randPeer failed."); + res = HC_ERR_MEMORY_COPY; + goto err; + } + } else { + if (memcpy_s(hkdfSalt, hkdfSaltLen, params->baseParams.randPeer.val, + params->baseParams.randPeer.length) != EOK) { + LOGE("Copy randPeer failed."); + res = HC_ERR_MEMORY_COPY; + goto err; + } + if (memcpy_s(hkdfSalt + params->baseParams.randPeer.length, hkdfSaltLen - params->baseParams.randPeer.length, + params->baseParams.randSelf.val, params->baseParams.randSelf.length) != EOK) { + LOGE("Copy randSelf failed."); + res = HC_ERR_MEMORY_COPY; + goto err; + } + } + Uint8Buff hkdfSaltBuf = { hkdfSalt, hkdfSaltLen }; + Uint8Buff keyInfoBuf = { (uint8_t *)GENERATE_RETURN_KEY_STR, (uint32_t)strlen(GENERATE_RETURN_KEY_STR) }; + Uint8Buff returnKeyBuf = { returnKey, returnKeyLen }; + res = params->baseParams.loader->computeHkdf(&(params->baseParams.sessionKey), &hkdfSaltBuf, &keyInfoBuf, + &returnKeyBuf, false); + if (res != HC_SUCCESS) { + LOGE("computeHkdf for returnKey failed."); + goto err; + } +err: + HcFree(hkdfSalt); + return res; +} + +int GenerateEncResult(const IsoParams *params, int message, CJson *sendToPeer, const char *aad) +{ + CJson *payload = NULL; + uint8_t *out = NULL; + uint8_t nonce[NONCE_SIZE] = { 0 }; + Uint8Buff nonceBuf = { nonce, sizeof(nonce) }; + int ret = params->baseParams.loader->generateRandom(&nonceBuf); + if (ret != 0) { + return ret; + } + + int result = 0; + Uint8Buff plainBuf = { (uint8_t *)&result, sizeof(int) }; + GcmParam encryptInfo; + encryptInfo.nonce = nonce; + encryptInfo.nonceLen = NONCE_SIZE; + encryptInfo.aad = (uint8_t *)aad; + encryptInfo.aadLen = (uint32_t)strlen(aad); + out = (uint8_t *)HcMalloc((sizeof(int) + TAG_LEN), 0); + if (out == NULL) { + ret = HC_ERR_ALLOC_MEMORY; + goto err; + } + Uint8Buff outBuf = { out, sizeof(int) + TAG_LEN }; + ret = params->baseParams.loader->aesGcmEncrypt(¶ms->baseParams.sessionKey, &plainBuf, + &encryptInfo, false, &outBuf); + if (ret != HC_SUCCESS) { + goto err; + } + payload = CreateJson(); + if (payload == NULL) { + ret = HC_ERR_ALLOC_MEMORY; + goto err; + } + GOTO_ERR_AND_SET_RET(AddByteToJson(payload, FIELD_NONCE, nonce, sizeof(nonce)), ret); + GOTO_ERR_AND_SET_RET(AddByteToJson(payload, FIELD_ENC_RESULT, out, sizeof(int) + TAG_LEN), ret); + GOTO_ERR_AND_SET_RET(AddIntToJson(payload, FIELD_OPERATION_CODE, params->opCode), ret); + GOTO_ERR_AND_SET_RET(AddObjToJson(sendToPeer, FIELD_PAYLOAD, payload), ret); + GOTO_ERR_AND_SET_RET(AddIntToJson(sendToPeer, FIELD_MESSAGE, message), ret); + GOTO_ERR_AND_SET_RET(AddIntToJson(sendToPeer, FIELD_AUTH_FORM, AUTH_FORM_ACCOUNT_UNRELATED), ret); +err: + FreeJson(payload); + HcFree(out); + return ret; +} + +int SendResultToFinalSelf(const IsoParams *params, CJson *out, bool isNeedReturnKey) +{ + CJson *sendToSelf = CreateJson(); + if (sendToSelf == NULL) { + return HC_ERR_ALLOC_MEMORY; + } + uint8_t *returnSessionKey = NULL; + int res = 0; + GOTO_ERR_AND_SET_RET(AddIntToJson(sendToSelf, FIELD_OPERATION_CODE, OP_BIND), res); + GOTO_ERR_AND_SET_RET(AddIntToJson(sendToSelf, FIELD_AUTH_FORM, AUTH_FORM_ACCOUNT_UNRELATED), res); + if (isNeedReturnKey) { + returnSessionKey = (uint8_t *)HcMalloc(params->keyLen, 0); + if (returnSessionKey == NULL) { + res = HC_ERR_ALLOC_MEMORY; + goto err; + } + res = GenerateReturnKey(params, returnSessionKey, params->keyLen); + if (res != 0) { + LOGE("gen return key failed, res:%d", res); + goto err; + } + GOTO_ERR_AND_SET_RET(AddByteToJson(sendToSelf, FIELD_SESSION_KEY, returnSessionKey, params->keyLen), res); + } + GOTO_ERR_AND_SET_RET(AddObjToJson(out, FIELD_SEND_TO_SELF, sendToSelf), res); +err: + FreeJson(sendToSelf); + if (returnSessionKey != NULL) { + (void)memset_s(returnSessionKey, params->keyLen, 0, params->keyLen); + } + HcFree(returnSessionKey); + return res; +} + +int GenEncResult(const IsoParams *params, int message, CJson *out, const char *aad, bool isNeedReturnKey) +{ + CJson *sendToSelf = CreateJson(); + if (sendToSelf == NULL) { + return HC_ERR_ALLOC_MEMORY; + } + CJson *sendToPeer = CreateJson(); + if (sendToPeer == NULL) { + FreeJson(sendToSelf); + return HC_ERR_ALLOC_MEMORY; + } + + uint8_t *returnKey = NULL; + int res = GenerateEncResult(params, message, sendToPeer, aad); + if (res != 0) { + goto err; + } + GOTO_ERR_AND_SET_RET(AddIntToJson(sendToSelf, FIELD_AUTH_FORM, AUTH_FORM_ACCOUNT_UNRELATED), res); + if (isNeedReturnKey) { + returnKey = (uint8_t *)HcMalloc(params->keyLen, 0); + if (returnKey == NULL) { + res = HC_ERR_ALLOC_MEMORY; + goto err; + } + res = GenerateReturnKey(params, returnKey, params->keyLen); + if (res != 0) { + LOGE("gen return key failed, res:%d", res); + goto err; + } + GOTO_ERR_AND_SET_RET(AddByteToJson(sendToSelf, FIELD_SESSION_KEY, returnKey, + params->keyLen), res); + } + GOTO_ERR_AND_SET_RET(AddIntToJson(sendToSelf, FIELD_OPERATION_CODE, params->opCode), res); + GOTO_ERR_AND_SET_RET(AddObjToJson(out, FIELD_SEND_TO_PEER, sendToPeer), res); + GOTO_ERR_AND_SET_RET(AddObjToJson(out, FIELD_SEND_TO_SELF, sendToSelf), res); + GOTO_ERR_AND_SET_RET(AddIntToJson(out, FIELD_CREDENTIAL_TYPE, SYMMETRIC), res); +err: + FreeJson(sendToPeer); + FreeJson(sendToSelf); + if (returnKey != NULL) { + (void)memset_s(returnKey, params->keyLen, 0, params->keyLen); + } + HcFree(returnKey); + return res; +} + +int CheckEncResult(IsoParams *params, const CJson *in, const char *aad) +{ + int result = 0; + int res; + uint8_t *nonce = NULL; + uint8_t *encResult = NULL; + + nonce = (uint8_t *)HcMalloc(NONCE_SIZE, 0); + if (nonce == NULL) { + res = HC_ERR_ALLOC_MEMORY; + goto err; + } + GOTO_ERR_AND_SET_RET(GetByteFromJson(in, FIELD_NONCE, nonce, NONCE_SIZE), res); + encResult = (uint8_t *)HcMalloc(sizeof(int) + TAG_LEN, 0); + if (encResult == NULL) { + res = HC_ERR_ALLOC_MEMORY; + goto err; + } + GOTO_ERR_AND_SET_RET(GetByteFromJson(in, FIELD_ENC_RESULT, encResult, sizeof(int) + TAG_LEN), res); + Uint8Buff outBuf = { (uint8_t *)&result, sizeof(int) }; + Uint8Buff encResultBuf = { encResult, sizeof(int) + TAG_LEN }; + GcmParam gcmParam; + gcmParam.aad = (uint8_t *)aad; + gcmParam.aadLen = (uint32_t)strlen(aad); + gcmParam.nonce = nonce; + gcmParam.nonceLen = NONCE_SIZE; + + res = params->baseParams.loader->aesGcmDecrypt(¶ms->baseParams.sessionKey, &encResultBuf, &gcmParam, false, + &outBuf); + if (res != 0) { + LOGE("decrypt result failed, res:%d", res); + goto err; + } +err: + HcFree(nonce); + HcFree(encResult); + return res; +} + +void DeleteAuthCode(const IsoParams *params) +{ + uint8_t *keyAlias = (uint8_t *)HcMalloc(ISO_KEY_ALIAS_LEN, 0); + if (keyAlias == NULL) { + return; + } + int res = GenerateKeyAliasInIso(params, keyAlias, ISO_KEY_ALIAS_LEN, true); + if (res != 0) { + LOGE("GenerateKeyAliasInIso failed, res:%d", res); + goto err; + } + Uint8Buff outKeyAlias = { keyAlias, ISO_KEY_ALIAS_LEN }; + params->baseParams.loader->deleteKey(&outKeyAlias); +err: + HcFree(keyAlias); + return; +} + +void DestroyIsoParams(IsoParams *params) +{ + if (params == NULL) { + return; + } + if (params->baseParams.sessionKey.val != NULL) { + (void)memset_s(params->baseParams.sessionKey.val, params->baseParams.sessionKey.length, 0, + params->baseParams.sessionKey.length); + HcFree(params->baseParams.sessionKey.val); + params->baseParams.sessionKey.val = NULL; + } + if (params->packageName != NULL) { + HcFree(params->packageName); + params->packageName = NULL; + } + if (params->serviceType != NULL) { + HcFree(params->serviceType); + params->serviceType = NULL; + } + if (params->baseParams.randSelf.val != NULL) { + HcFree(params->baseParams.randSelf.val); + params->baseParams.randSelf.val = NULL; + } + if (params->baseParams.randPeer.val != NULL) { + HcFree(params->baseParams.randPeer.val); + params->baseParams.randPeer.val = NULL; + } + if (params->baseParams.authIdPeer.val != NULL) { + HcFree(params->baseParams.authIdPeer.val); + params->baseParams.authIdPeer.val = NULL; + } + if (params->baseParams.authIdSelf.val != NULL) { + HcFree(params->baseParams.authIdSelf.val); + params->baseParams.authIdSelf.val = NULL; + } + if (params->seed.val != NULL) { + HcFree(params->seed.val); + params->seed.val = NULL; + } + if (params->pinCodeString != NULL) { + (void)memset_s(params->pinCodeString, strlen(params->pinCodeString), 0, strlen(params->pinCodeString)); + HcFree(params->pinCodeString); + params->pinCodeString = NULL; + } + (void)memset_s(params, sizeof(IsoParams), 0, sizeof(IsoParams)); +} + +static int FillAuthId(IsoParams *params, const CJson *in) +{ + const char *authId = GetStringFromJson(in, FIELD_SELF_AUTH_ID); + if (authId == NULL) { + LOGE("get self authId failed"); + return HC_ERROR; + } + uint32_t authIdLen = strlen(authId); + if (authIdLen == 0 || authIdLen > MAX_AUTH_ID_LEN) { + LOGE("Invalid authIdSelfLen"); + return HC_ERR_INVALID_PARAMS; + } + params->baseParams.authIdSelf.length = authIdLen; + params->baseParams.authIdSelf.val = (uint8_t *)HcMalloc(params->baseParams.authIdSelf.length, 0); + if (params->baseParams.authIdSelf.val == NULL) { + LOGE("malloc authIdSelf failed"); + return HC_ERROR; + } + if (memcpy_s(params->baseParams.authIdSelf.val, params->baseParams.authIdSelf.length, + authId, strlen(authId)) != EOK) { + LOGE("Memcpy authIdSelf failed."); + return HC_ERR_MEMORY_COPY; + } + + if (params->opCode == OP_BIND) { + params->baseParams.authIdPeer.length = 0; + params->baseParams.authIdPeer.val = NULL; + } else { + authId = GetStringFromJson(in, FIELD_PEER_AUTH_ID); + if (authId == NULL) { + LOGE("get peer authId failed"); + return HC_ERROR; + } + authIdLen = strlen(authId); + if (authIdLen == 0 || authIdLen > MAX_AUTH_ID_LEN) { + LOGE("Invalid authIdPeerLen"); + return HC_ERR_INVALID_PARAMS; + } + params->baseParams.authIdPeer.length = authIdLen; + params->baseParams.authIdPeer.val = (uint8_t *)HcMalloc(params->baseParams.authIdPeer.length, 0); + if (params->baseParams.authIdPeer.val == NULL) { + LOGE("malloc authIdPeer failed"); + return HC_ERROR; + } + if (memcpy_s(params->baseParams.authIdPeer.val, params->baseParams.authIdPeer.length, + authId, strlen(authId)) != EOK) { + LOGE("Memcpy authIdPeer failed."); + return HC_ERR_MEMORY_COPY; + } + } + + return HC_SUCCESS; +} + +static int AllocRandom(IsoParams *params) +{ + int res = HC_SUCCESS; + params->baseParams.randSelf.length = RAND_BYTE_LEN; + params->baseParams.randPeer.length = RAND_BYTE_LEN; + params->baseParams.randSelf.val = (uint8_t *)HcMalloc(params->baseParams.randSelf.length, 0); + if (params->baseParams.randSelf.val == NULL) { + LOGE("malloc randSelf failed"); + return HC_ERR_ALLOC_MEMORY; + } + params->baseParams.randPeer.val = (uint8_t *)HcMalloc(params->baseParams.randPeer.length, 0); + if (params->baseParams.randPeer.val == NULL) { + LOGE("malloc randPeer failed"); + res = HC_ERR_ALLOC_MEMORY; + } + return res; +} + +static int FillPkgNameAndServiceType(IsoParams *params, const CJson *in) +{ + const char *serviceType = GetStringFromJson(in, FIELD_SERVICE_TYPE); + if (serviceType == NULL) { + LOGE("get serviceType failed"); + return HC_ERROR; + } + params->serviceType = (char *)HcMalloc((uint32_t)(strlen(serviceType) + 1), 0); + if (params->serviceType == NULL) { + LOGE("malloc serviceType failed"); + return HC_ERR_ALLOC_MEMORY; + } + if (memcpy_s(params->serviceType, strlen(serviceType) + 1, serviceType, strlen(serviceType)) != EOK) { + LOGE("memcpy serviceType failed."); + return HC_ERR_MEMORY_COPY; + } + const char *packageName = GetStringFromJson(in, FIELD_PKG_NAME); + if (packageName == NULL) { + LOGE("get packageName failed"); + return HC_ERROR; + } + params->packageName = (char *)HcMalloc((uint32_t)(strlen(packageName) + 1), 0); + if (params->packageName == NULL) { + LOGE("malloc packageName failed"); + return HC_ERROR; + } + if (memcpy_s(params->packageName, strlen(packageName) + 1, packageName, strlen(packageName)) != EOK) { + LOGE("memcpy packageName failed."); + return HC_ERR_MEMORY_COPY; + } + return HC_SUCCESS; +} + +static int FillPin(IsoParams *params, const CJson *in) +{ + if (params->opCode == OP_BIND) { + const char *pinString = GetStringFromJson(in, FIELD_PIN_CODE); + if (pinString == NULL) { + LOGE("Get pin failed."); + return HC_ERROR; + } + if (strlen(pinString) < MIN_PIN_LEN || strlen(pinString) > MAX_PIN_LEN) { + LOGE("Pin is too short."); + return HC_ERR_INVALID_PARAMS; + } + params->pinCodeString = (char *)HcMalloc(strlen(pinString) + 1, 0); + if (params->pinCodeString == NULL) { + LOGE("malloc pinCode failed."); + return HC_ERR_ALLOC_MEMORY; + } + if (memcpy_s(params->pinCodeString, strlen(pinString) + 1, pinString, strlen(pinString)) != EOK) { + LOGE("memcpy pinCodeString failed."); + (void)memset_s(params->pinCodeString, strlen(pinString) + 1, 0, strlen(pinString) + 1); + return HC_ERR_MEMORY_COPY; + } + } + return HC_SUCCESS; +} + +static int AllocSeed(IsoParams *params) +{ + params->seed.val = (uint8_t *)HcMalloc(SEED_LEN, 0); + if (params->seed.val == NULL) { + return HC_ERR_ALLOC_MEMORY; + } + params->seed.length = SEED_LEN; + return HC_SUCCESS; +} + +static int GetUserType(IsoParams *params, const CJson *in) +{ + int res = GetIntFromJson(in, FIELD_SELF_TYPE, &(params->selfUserType)); + if (res != 0) { + LOGE("get userType failed: %d", res); + return res; + } + + res = GetIntFromJson(in, FIELD_PEER_USER_TYPE, &(params->peerUserType)); + if (res != 0) { + LOGD("get peer Type failed use default, res: %d", res); + params->peerUserType = 0; /* fill default value */ + res = HC_SUCCESS; + } + return res; +} + +static int32_t GetKeyLength(IsoParams *params, const CJson *in) +{ + if (params->opCode == OP_UNBIND || params->opCode == OP_BIND) { + params->keyLen = 0; + return HC_SUCCESS; + } + int res = GetIntFromJson(in, FIELD_KEY_LENGTH, (int *)&(params->keyLen)); + if (res != HC_SUCCESS) { + LOGD("get key length failed, use default, res: %d", res); + params->keyLen = DEFAULT_RETURN_KEY_LENGTH; + } + if (params->keyLen < MIN_OUTPUT_KEY_LEN || params->keyLen > MAX_OUTPUT_KEY_LEN) { + LOGE("Output key length is invalid."); + return HC_ERR_INVALID_LEN; + } + return HC_SUCCESS; +} + +int InitIsoParams(IsoParams *params, const CJson *in) +{ + int res = GetIntFromJson(in, FIELD_OPERATION_CODE, &(params->opCode)); + if (res != 0) { + params->opCode = AUTHENTICATE; + } + res = GetBoolFromJson(in, FIELD_IS_CLIENT, &(params->isClient)); + if (res != HC_SUCCESS) { + LOGE("get isClient failed"); + goto err; + } + res = GetKeyLength(params, in); + if (res != 0) { + goto err; + } + params->baseParams.sessionKey.length = ISO_SESSION_KEY_LEN; + params->baseParams.loader = GetLoaderInstance(); + if (params->baseParams.loader == NULL) { + res = HC_ERROR; + goto err; + } + res = GetUserType(params, in); + if (res != 0) { + goto err; + } + res = FillAuthId(params, in); + if (res != 0) { + goto err; + } + res = AllocRandom(params); + if (res != 0) { + goto err; + } + res = FillPkgNameAndServiceType(params, in); + if (res != 0) { + goto err; + } + res = FillPin(params, in); + if (res != 0) { + goto err; + } + res = AllocSeed(params); + if (res != 0) { + goto err; + } + return HC_SUCCESS; +err: + DestroyIsoParams(params); + return res; +} + +static int AuthGeneratePsk(const Uint8Buff *seed, IsoParams *params) +{ + uint8_t keyAlias[ISO_KEY_ALIAS_LEN] = { 0 }; + int res = GenerateKeyAliasInIso(params, keyAlias, sizeof(keyAlias), true); + if (res != 0) { + return res; + } + + Uint8Buff keyAliasBuf = { keyAlias, sizeof(keyAlias) }; + Uint8Buff pskBuf = { params->baseParams.psk, sizeof(params->baseParams.psk) }; + return params->baseParams.loader->computeHmac(&keyAliasBuf, seed, &pskBuf, true); +} + +static int AuthGeneratePskUsePin(const Uint8Buff *seed, IsoParams *params, const char *pinString) +{ + Uint8Buff messageBuf = { (uint8_t *)pinString, (uint32_t)strlen(pinString) }; + Uint8Buff pskBuf = { params->baseParams.psk, sizeof(params->baseParams.psk) }; + uint8_t hash[SHA256_LEN] = { 0 }; + Uint8Buff hashBuf = { hash, sizeof(hash) }; + int res = params->baseParams.loader->sha256(&messageBuf, &hashBuf); + if (res != 0) { + LOGE("sha256 failed, res:%d", res); + return res; + } + return params->baseParams.loader->computeHmac(&hashBuf, seed, &pskBuf, false); +} + +int GenerateKeyAliasInIso(const IsoParams *params, uint8_t *keyAlias, uint32_t keyAliasLen, bool useOpposite) +{ + if (params == NULL || keyAlias == NULL || keyAliasLen == 0) { + return HC_ERR_INVALID_PARAMS; + } + Uint8Buff pkgName = { (uint8_t *)params->packageName, (uint32_t)strlen(params->packageName) }; + Uint8Buff serviceType = { (uint8_t *)params->serviceType, (uint32_t)strlen(params->serviceType) }; + Uint8Buff authId = { NULL, 0 }; + if (useOpposite) { + authId.val = params->baseParams.authIdPeer.val; + authId.length = params->baseParams.authIdPeer.length; + } else { + authId.val = params->baseParams.authIdSelf.val; + authId.length = params->baseParams.authIdSelf.length; + } + Uint8Buff outKeyAlias = { keyAlias, keyAliasLen }; + return GenerateKeyAlias(&pkgName, &serviceType, KEY_ALIAS_AUTH_TOKEN, &authId, + &outKeyAlias); +} + +int GeneratePsk(const CJson *in, IsoParams *params) +{ + int res = 0; + if (!params->isClient) { + res = GetByteFromJson(in, FIELD_SEED, params->seed.val, params->seed.length); + } + if (res != 0) { + LOGE("get seed failed."); + return res; + } + if (params->opCode == AUTHENTICATE || params->opCode == OP_UNBIND) { + return AuthGeneratePsk(¶ms->seed, params); + } + return AuthGeneratePskUsePin(¶ms->seed, params, params->pinCodeString); +} + +int GenerateSeed(IsoParams *params) +{ + uint8_t *random = (uint8_t *)HcMalloc(SEED_LEN, 0); + if (random == NULL) { + LOGE("malloc random failed"); + return HC_ERR_ALLOC_MEMORY; + } + Uint8Buff randomBuf = { random, SEED_LEN }; + int res = params->baseParams.loader->generateRandom(&randomBuf); + if (res != 0) { + LOGE("generate random failed, res:%d", res); + HcFree(random); + return res; + } + clock_t times = clock(); + uint8_t *input = (uint8_t *)HcMalloc(SEED_LEN + sizeof(clock_t), 0); + if (input == NULL) { + LOGE("malloc failed"); + HcFree(random); + return HC_ERR_ALLOC_MEMORY; + } + if (memcpy_s(input, SEED_LEN + sizeof(clock_t), random, SEED_LEN) != EOK) { + LOGE("memcpy seed failed."); + res = HC_ERR_MEMORY_COPY; + goto err; + } + if (memcpy_s(input + SEED_LEN, sizeof(clock_t), ×, sizeof(clock_t)) != EOK) { + LOGE("memcpy times failed."); + res = HC_ERR_MEMORY_COPY; + goto err; + } + Uint8Buff inputBuf = { input, SEED_LEN + sizeof(clock_t) }; + res = params->baseParams.loader->sha256(&inputBuf, ¶ms->seed); + if (res != HC_SUCCESS) { + LOGE("sha256 failed."); + goto err; + } +err: + HcFree(random); + HcFree(input); + return res; +} \ No newline at end of file diff --git a/services/module/src/das_module/iso_task/iso_task_main.c b/services/module/src/das_module/iso_task/iso_task_main.c new file mode 100644 index 0000000..4598d99 --- /dev/null +++ b/services/module/src/das_module/iso_task/iso_task_main.c @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "iso_task_main.h" +#include "das_asy_token_manager.h" +#include "das_common.h" +#include "hc_log.h" +#include "hc_types.h" +#include "iso_base_cur_task.h" +#include "iso_client_task.h" +#include "iso_server_task.h" + +static int32_t UnregisterLocalIdentity(const char *pkgName, const char *serviceType, Uint8Buff *authId, int userType) +{ + const AlgLoader *loader = GetLoaderInstance(); + Uint8Buff pkgNameBuff = { (uint8_t *)pkgName, HcStrlen(pkgName) }; + Uint8Buff serviceTypeBuff = { (uint8_t *)serviceType, HcStrlen(serviceType) }; + + uint8_t isoKeyAliasVal[ISO_KEY_ALIAS_LEN] = { 0 }; + Uint8Buff isoKeyAliasBuff = { isoKeyAliasVal, ISO_KEY_ALIAS_LEN }; + int32_t res = GenerateKeyAlias(&pkgNameBuff, &serviceTypeBuff, KEY_ALIAS_AUTH_TOKEN, authId, &isoKeyAliasBuff); + if (res != HC_SUCCESS) { + LOGE("Failed to generate authtoken alias!"); + return res; + } + res = loader->deleteKey(&isoKeyAliasBuff); + if (res != HC_SUCCESS) { + LOGE("Failed to delete authtoken!"); + return res; + } + LOGI("Authtoken deleted successfully!"); + + return HC_SUCCESS; +} + +static int32_t DeletePeerAuthInfo(const char *pkgName, const char *serviceType, Uint8Buff *authIdPeer, int userTypePeer) +{ + const AlgLoader *loader = GetLoaderInstance(); + Uint8Buff pkgNameBuff = { (uint8_t *)pkgName, HcStrlen(pkgName)}; + Uint8Buff serviceTypeBuff = { (uint8_t *)serviceType, HcStrlen(serviceType) }; + + uint8_t isoKeyAliasVal[ISO_KEY_ALIAS_LEN] = { 0 }; + Uint8Buff isoKeyAliasBuff = { isoKeyAliasVal, ISO_KEY_ALIAS_LEN }; + int32_t res = GenerateKeyAlias(&pkgNameBuff, &serviceTypeBuff, KEY_ALIAS_AUTH_TOKEN, authIdPeer, &isoKeyAliasBuff); + if (res != HC_SUCCESS) { + LOGE("Failed to generate authtoken alias!"); + return res; + } + res = loader->deleteKey(&isoKeyAliasBuff); + if (res != HC_SUCCESS) { + LOGE("Failed to delete authtoken!"); + return res; + } + LOGI("Authtoken deleted successfully!"); + + return HC_SUCCESS; +} + +TokenManager g_symTokenManagerInstance = { + NULL, + UnregisterLocalIdentity, + DeletePeerAuthInfo, + NULL +}; + +bool IsIsoSupported() +{ + return true; +} + +SubTaskBase *CreateIsoSubTask(const CJson *in, CJson *out) +{ + if (in == NULL || out == NULL) { + return NULL; + } + bool isClient = true; + if (GetBoolFromJson(in, FIELD_IS_CLIENT, &isClient) != HC_SUCCESS) { + LOGE("Get isClient failed."); + return NULL; + } + if (isClient) { + return CreateIsoClientTask(in); + } else { + return CreateIsoServerTask(in, out); + } +} + +const TokenManager *GetSymTokenManagerInstance() +{ + return &g_symTokenManagerInstance; +} \ No newline at end of file diff --git a/services/module/src/das_module/iso_task/lite_exchange_task/iso_client_bind_exchange_task.c b/services/module/src/das_module/iso_task/lite_exchange_task/iso_client_bind_exchange_task.c new file mode 100644 index 0000000..79b2656 --- /dev/null +++ b/services/module/src/das_module/iso_task/lite_exchange_task/iso_client_bind_exchange_task.c @@ -0,0 +1,252 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "iso_client_bind_exchange_task.h" +#include "alg_defs.h" +#include "das_common.h" +#include "das_module_defines.h" +#include "hc_log.h" +#include "hc_types.h" +#include "iso_protocol_common.h" +#include "iso_task_common.h" +#include "securec.h" + +enum { + TASK_TYPE_BEGIN = 1, + TASK_TYPE_FINAL, +}; + +static CurTaskType GetTaskType() +{ + return TASK_TYPE_BIND_LITE_EXCHANGE; +} + +static void DestroyCreateClientBindExchangeTask(struct SymBaseCurTaskT *task) +{ + IsoClientBindExchangeTask *realTask = (IsoClientBindExchangeTask *)task; + HcFree(realTask); +} + +static int DecAndImportInner(IsoClientBindExchangeTask *realTask, const IsoParams *params, + const Uint8Buff *nonceBuf, const Uint8Buff *encDataBuf, Uint8Buff *authCodeBuf) +{ + int res; + uint8_t *keyAlias = (uint8_t *)HcMalloc(ISO_KEY_ALIAS_LEN, 0); + if (keyAlias == NULL) { + res = HC_ERR_ALLOC_MEMORY; + goto err; + } + Uint8Buff keyAliasBuf = { keyAlias, ISO_KEY_ALIAS_LEN }; + GcmParam gcmParam; + gcmParam.aad = realTask->challenge; + gcmParam.aadLen = sizeof(realTask->challenge); + gcmParam.nonce = nonceBuf->val; + gcmParam.nonceLen = nonceBuf->length; + res = params->baseParams.loader->aesGcmDecrypt(¶ms->baseParams.sessionKey, encDataBuf, + &gcmParam, false, authCodeBuf); + if (res != 0) { + LOGE("gcm decrypt failed, res:%d", res); + goto err; + } + res = GenerateKeyAliasInIso(params, keyAlias, ISO_KEY_ALIAS_LEN, true); + if (res != 0) { + LOGE("GenerateKeyAliasInIso failed, res:%d", res); + goto err; + } + + ExtraInfo exInfo = { { params->baseParams.authIdPeer.val, params->baseParams.authIdPeer.length }, + params->peerUserType, PAIR_TYPE_BIND }; + res = params->baseParams.loader->importAsymmetricKey(&keyAliasBuf, authCodeBuf, &exInfo); + if (res != 0) { + LOGE("import token failed, res:%d", res); + goto err; + } +err: + HcFree(keyAlias); + return res; +} + +static int DecAndImportAuthCode(IsoClientBindExchangeTask *realTask, const IsoParams *params, const CJson *in) +{ + uint8_t *nonce = NULL; + uint8_t *encData = NULL; + uint8_t *authCode = NULL; + int encDataLen = AUTH_CODE_LEN + TAG_LEN; + int res; + nonce = (uint8_t *)HcMalloc(NONCE_SIZE, 0); + if (nonce == NULL) { + res = HC_ERR_ALLOC_MEMORY; + goto err; + } + encData = (uint8_t *)HcMalloc(encDataLen, 0); + if (encData == NULL) { + res = HC_ERR_ALLOC_MEMORY; + goto err; + } + GOTO_ERR_AND_SET_RET(GetByteFromJson(in, FIELD_NONCE, nonce, NONCE_SIZE), res); + GOTO_ERR_AND_SET_RET(GetByteFromJson(in, FIELD_ENC_AUTH_TOKEN, encData, encDataLen), res); + + Uint8Buff encDataBuf = { encData, encDataLen }; + authCode = (uint8_t *)HcMalloc(AUTH_CODE_LEN, 0); + if (authCode == NULL) { + res = HC_ERR_ALLOC_MEMORY; + goto err; + } + Uint8Buff authCodeBuf = { authCode, AUTH_CODE_LEN }; + Uint8Buff nonceBuf = { nonce, NONCE_SIZE }; + + res = DecAndImportInner(realTask, params, &nonceBuf, &encDataBuf, &authCodeBuf); + if (res != 0) { + LOGE("DecAndImportInner failed, res:%d", res); + } +err: + HcFree(nonce); + HcFree(encData); + if (authCode != NULL) { + (void)memset_s(authCode, AUTH_CODE_LEN, 0, AUTH_CODE_LEN); + } + HcFree(authCode); + return res; +} + +static int Process(struct SymBaseCurTaskT *task, IsoParams *params, const CJson *in, CJson *out, int *status) +{ + IsoClientBindExchangeTask *realTask = (IsoClientBindExchangeTask *)task; + if (realTask->taskBase.taskStatus < TASK_TYPE_BEGIN) { + LOGE("taskStatus err %d", realTask->taskBase.taskStatus); + return HC_ERR_BAD_MESSAGE; + } + + if (realTask->taskBase.taskStatus > TASK_TYPE_BEGIN) { + LOGI("The message is repeated, ignore it, status :%d", realTask->taskBase.taskStatus); + *status = IGNORE_MSG; + return HC_SUCCESS; + } + int res; + int message = 0; + res = GetIntFromJson(in, FIELD_MESSAGE, &message); + if (res != 0 || message != ISO_SERVER_BIND_EXCHANGE_RET) { + return HC_ERR_BAD_MESSAGE; + } + res = DecAndImportAuthCode(realTask, params, in); + if (res != 0) { + LOGE("dec and import authCode failed, res:%d", res); + return res; + } + res = GenEncResult(params, ISO_CLIENT_BIND_EXCHANGE_CONFIRM, out, RESULT_AAD, false); + if (res == HC_SUCCESS) { + realTask->taskBase.taskStatus = TASK_TYPE_FINAL; + *status = FINISH; + } + return res; +} + +static int ClientBindAesEncrypt(IsoClientBindExchangeTask *task, const IsoParams *params, + uint8_t **encData, uint8_t **nonce) +{ + Uint8Buff challengeBuf = { task->challenge, sizeof(task->challenge) }; + int res = params->baseParams.loader->generateRandom(&challengeBuf); + if (res != 0) { + LOGE("generate random failed, res:%d", res); + return res; + } + *nonce = (uint8_t *)HcMalloc(NONCE_SIZE, 0); + if (*nonce == NULL) { + LOGE("malloc nonce failed"); + return HC_ERR_ALLOC_MEMORY; + } + Uint8Buff nonceBuf = { *nonce, NONCE_SIZE }; + res = params->baseParams.loader->generateRandom(&nonceBuf); + if (res != 0) { + LOGE("generateRandom failed, res:%d", res); + return res; + } + *encData = (uint8_t *)HcMalloc(sizeof(task->challenge) + TAG_LEN, 0); + if (*encData == NULL) { + return HC_ERR_ALLOC_MEMORY; + } + GcmParam gcmParams; + gcmParams.aad = (uint8_t *)EXCHANGE_AAD; + gcmParams.aadLen = (uint32_t)strlen(EXCHANGE_AAD); + gcmParams.nonce = *nonce; + gcmParams.nonceLen = NONCE_SIZE; + Uint8Buff outBuf = { *encData, sizeof(task->challenge) + TAG_LEN }; + res = params->baseParams.loader->aesGcmEncrypt(¶ms->baseParams.sessionKey, &challengeBuf, &gcmParams, false, + &outBuf); + if (res != 0) { + LOGE("encrypt failed, res:%d", res); + return res; + } + return res; +} + +static int ClientBindExchangeStart(const IsoParams *params, IsoClientBindExchangeTask *task, CJson *out, int *status) +{ + uint8_t *nonce = NULL; + uint8_t *encData = NULL; + CJson *payload = NULL; + CJson *sendToPeer = NULL; + + // execute + int res = ClientBindAesEncrypt(task, params, &encData, &nonce); + if (res != 0) { + goto err; + } + + // package message + sendToPeer = CreateJson(); + if (sendToPeer == NULL) { + res = HC_ERR_ALLOC_MEMORY; + goto err; + } + payload = CreateJson(); + if (payload == NULL) { + res = HC_ERR_ALLOC_MEMORY; + goto err; + } + GOTO_ERR_AND_SET_RET(AddIntToJson(sendToPeer, FIELD_MESSAGE, ISO_CLIENT_BIND_EXCHANGE_CMD), res); + GOTO_ERR_AND_SET_RET(AddByteToJson(payload, FIELD_NONCE, nonce, NONCE_SIZE), res); + GOTO_ERR_AND_SET_RET(AddByteToJson(payload, FIELD_ENC_DATA, encData, sizeof(task->challenge) + TAG_LEN), res); + GOTO_ERR_AND_SET_RET(AddObjToJson(sendToPeer, FIELD_PAYLOAD, payload), res); + GOTO_ERR_AND_SET_RET(AddObjToJson(out, FIELD_SEND_TO_PEER, sendToPeer), res); + + task->taskBase.taskStatus = TASK_TYPE_BEGIN; + *status = CONTINUE; +err: + FreeJson(payload); + FreeJson(sendToPeer); + HcFree(nonce); + HcFree(encData); + return res; +} + +SymBaseCurTask *CreateClientBindExchangeTask(IsoParams *params, const CJson *in, CJson *out, int *status) +{ + (void)in; + IsoClientBindExchangeTask *task = (IsoClientBindExchangeTask *)HcMalloc(sizeof(IsoClientBindExchangeTask), 0); + if (task == NULL) { + LOGE("Failed to create client bind exchange task."); + return NULL; + } + task->taskBase.destroyTask = DestroyCreateClientBindExchangeTask; + task->taskBase.process = Process; + task->taskBase.getCurTaskType = GetTaskType; + int res = ClientBindExchangeStart(params, task, out, status); + if (res != 0) { + DestroyCreateClientBindExchangeTask((struct SymBaseCurTaskT *)task); + return NULL; + } + return (SymBaseCurTask *)task; +} diff --git a/services/module/src/das_module/iso_task/lite_exchange_task/iso_client_unbind_exchange_task.c b/services/module/src/das_module/iso_task/lite_exchange_task/iso_client_unbind_exchange_task.c new file mode 100644 index 0000000..87217bb --- /dev/null +++ b/services/module/src/das_module/iso_task/lite_exchange_task/iso_client_unbind_exchange_task.c @@ -0,0 +1,216 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "iso_client_unbind_exchange_task.h" +#include "hc_log.h" +#include "hc_types.h" +#include "iso_task_common.h" +#include "securec.h" + +enum { + TASK_TYPE_BEGIN = 1, + TASK_TYPE_FINAL, +}; + +static CurTaskType GetTaskType() +{ + return TASK_TYPE_UNBIND_LITE_EXCHANGE; +} + +static void DestroyClientUnbindExchangeTask(struct SymBaseCurTaskT *task) +{ + IsoClientUnbindExchangeTask *realTask = (IsoClientUnbindExchangeTask *)task; + HcFree(realTask); +} + +static int Process(struct SymBaseCurTaskT *task, IsoParams *params, const CJson *in, CJson *out, int *status) +{ + IsoClientUnbindExchangeTask *realTask = (IsoClientUnbindExchangeTask *)task; + if (realTask->taskBase.taskStatus < TASK_TYPE_BEGIN) { + LOGE("taskStatus err %d", realTask->taskBase.taskStatus); + return HC_ERR_BAD_MESSAGE; + } + + if (realTask->taskBase.taskStatus > TASK_TYPE_BEGIN) { + LOGI("The message is repeated, ignore it, status :%d", realTask->taskBase.taskStatus); + *status = IGNORE_MSG; + return HC_SUCCESS; + } + int res; + uint8_t *keyAlias = NULL; + int message = 0; + res = GetIntFromJson(in, FIELD_MESSAGE, &message); + if (res != 0 || message != ISO_SERVER_UNBIND_EXCHANGE_RET) { + return HC_ERR_BAD_MESSAGE; + } + res = CheckEncResult(params, in, UNBIND_ADD_RESPONSE); + if (res != 0) { + LOGE("CheckEncResult failed, res:%d", res); + return res; + } + keyAlias = (uint8_t *)HcMalloc(ISO_KEY_ALIAS_LEN, 0); + if (keyAlias == NULL) { + res = HC_ERR_ALLOC_MEMORY; + goto err; + } + res = GenerateKeyAliasInIso(params, keyAlias, ISO_KEY_ALIAS_LEN, true); + if (res != 0) { + LOGE("GenerateKeyAliasInIso failed, res:%d", res); + goto err; + } + Uint8Buff outKeyAlias = { (uint8_t *)keyAlias, ISO_KEY_ALIAS_LEN }; + res = params->baseParams.loader->deleteKey(&outKeyAlias); + if (res != 0) { + LOGE("delete auth code failed, res:%d", res); + goto err; + } + res = SendResultToFinalSelf(params, out, false); + if (res == 0) { + realTask->taskBase.taskStatus = TASK_TYPE_FINAL; + *status = FINISH; + } +err: + HcFree(keyAlias); + return res; +} + +static int PackDataForStartUnbind(const IsoParams *params, const Uint8Buff *encDataBuf, const Uint8Buff *nonceBuf, + CJson *out) +{ + int res = 0; + CJson *payload = NULL; + CJson *sendToPeer = NULL; + + payload = CreateJson(); + if (payload == NULL) { + res = HC_ERR_ALLOC_MEMORY; + goto err; + } + sendToPeer = CreateJson(); + if (sendToPeer == NULL) { + res = HC_ERR_ALLOC_MEMORY; + goto err; + } + GOTO_ERR_AND_SET_RET(AddIntToJson(sendToPeer, FIELD_MESSAGE, ISO_CLIENT_UNBIND_EXCHANGE_CMD), res); + GOTO_ERR_AND_SET_RET(AddIntToJson(payload, FIELD_OPERATION_CODE, params->opCode), res); + GOTO_ERR_AND_SET_RET(AddByteToJson(payload, FIELD_ENC_DATA, encDataBuf->val, encDataBuf->length), res); + GOTO_ERR_AND_SET_RET(AddByteToJson(payload, FIELD_NONCE, nonceBuf->val, nonceBuf->length), res); + GOTO_ERR_AND_SET_RET(AddObjToJson(sendToPeer, FIELD_PAYLOAD, payload), res); + GOTO_ERR_AND_SET_RET(AddObjToJson(out, FIELD_SEND_TO_PEER, sendToPeer), res); +err: + FreeJson(payload); + FreeJson(sendToPeer); + return res; +} + +static int GenerateEncRemoveInfo(const IsoParams *params, const Uint8Buff *nonceBuf, CJson *out) +{ + int res; + char *rmvInfoStr = NULL; + uint8_t *encData = NULL; + CJson *rmvInfoJson = CreateJson(); + if (rmvInfoJson == NULL) { + LOGE("Create json failed"); + return HC_ERR_ALLOC_MEMORY; + } + GOTO_ERR_AND_SET_RET(AddByteToJson(rmvInfoJson, FIELD_RMV_ID, params->baseParams.authIdSelf.val, + params->baseParams.authIdSelf.length), res); + GOTO_ERR_AND_SET_RET(AddIntToJson(rmvInfoJson, FIELD_RMV_TYPE, params->selfUserType), res); + rmvInfoStr = PackJsonToString(rmvInfoJson); + if (rmvInfoStr == NULL) { + LOGE("rmvInfoStr PackJsonToString failed"); + res = HC_ERR_PACKAGE_JSON_TO_STRING_FAIL; + goto err; + } + + Uint8Buff removeInfoBuf = { (uint8_t *)rmvInfoStr, strlen(rmvInfoStr) }; + + int encDataLen = strlen(rmvInfoStr) + TAG_LEN; + encData = (uint8_t *)HcMalloc(encDataLen, 0); + if (encData == NULL) { + res = HC_ERR_ALLOC_MEMORY; + goto err; + } + Uint8Buff encDataBuf = { encData, encDataLen }; + GcmParam gcmParam; + gcmParam.aad = (uint8_t *)UNBIND_ADD_REQUEST; + gcmParam.aadLen = (uint32_t)strlen(UNBIND_ADD_REQUEST); + gcmParam.nonce = nonceBuf->val; + gcmParam.nonceLen = nonceBuf->length; + res = params->baseParams.loader->aesGcmEncrypt(¶ms->baseParams.sessionKey, &removeInfoBuf, &gcmParam, false, + &encDataBuf); + if (res != 0) { + LOGE("encrypt removeInfo failed, res:%d", res); + goto err; + } + res = PackDataForStartUnbind(params, &encDataBuf, nonceBuf, out); + if (res != HC_SUCCESS) { + LOGE("PackDataForStartUnbind failed, res:%d", res); + } +err: + FreeJson(rmvInfoJson); + FreeJsonString(rmvInfoStr); + HcFree(encData); + return res; +} + + +static int ClientUnbindExchangeStart(const IsoParams *params, IsoClientUnbindExchangeTask *task, CJson *out, + int *status) +{ + int res; + uint8_t *nonce = NULL; + + nonce = (uint8_t *)HcMalloc(NONCE_SIZE, 0); + if (nonce == NULL) { + res = HC_ERR_ALLOC_MEMORY; + goto err; + } + Uint8Buff nonceBuf = { nonce, NONCE_SIZE }; + res = params->baseParams.loader->generateRandom(&nonceBuf); + if (res != 0) { + LOGE("generate nonce failed, res:%d", res); + goto err; + } + + res = GenerateEncRemoveInfo(params, &nonceBuf, out); + if (res != 0) { + LOGE("GenerateEncRemoveInfo failed, res:%d", res); + goto err; + } + task->taskBase.taskStatus = TASK_TYPE_BEGIN; + *status = CONTINUE; +err: + HcFree(nonce); + return res; +} + +SymBaseCurTask *CreateClientUnbindExchangeTask(IsoParams *params, const CJson *in, CJson *out, int *status) +{ + (void)in; + IsoClientUnbindExchangeTask *task = (IsoClientUnbindExchangeTask *)HcMalloc(sizeof(IsoClientUnbindExchangeTask), 0); + if (task == NULL) { + return NULL; + } + task->taskBase.destroyTask = DestroyClientUnbindExchangeTask; + task->taskBase.process = Process; + task->taskBase.getCurTaskType = GetTaskType; + int res = ClientUnbindExchangeStart(params, task, out, status); + if (res != 0) { + DestroyClientUnbindExchangeTask((struct SymBaseCurTaskT *)task); + return NULL; + } + return (SymBaseCurTask *)task; +} \ No newline at end of file diff --git a/services/module/src/das_module/iso_task/lite_exchange_task/iso_server_bind_exchange_task.c b/services/module/src/das_module/iso_task/lite_exchange_task/iso_server_bind_exchange_task.c new file mode 100644 index 0000000..da8410b --- /dev/null +++ b/services/module/src/das_module/iso_task/lite_exchange_task/iso_server_bind_exchange_task.c @@ -0,0 +1,262 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "iso_server_bind_exchange_task.h" +#include "das_common.h" +#include "das_module_defines.h" +#include "hc_log.h" +#include "hc_types.h" +#include "iso_protocol_common.h" +#include "iso_task_common.h" +#include "protocol_common.h" + +enum { + TASK_TYPE_BEGIN = 1, + TASK_TYPE_FINAL, +}; + +static CurTaskType GetTaskType() +{ + return TASK_TYPE_BIND_LITE_EXCHANGE; +} + +void DestroyServerBindExchangeTask(struct SymBaseCurTaskT *task) +{ + IsoServerBindExchangeTask *realTask = (IsoServerBindExchangeTask *)task; + HcFree(realTask); +} + +static int Process(struct SymBaseCurTaskT *task, IsoParams *params, const CJson *in, CJson *out, int *status) +{ + IsoServerBindExchangeTask *realTask = (IsoServerBindExchangeTask *)task; + if (realTask->taskBase.taskStatus < TASK_TYPE_BEGIN) { + LOGE("task status failed"); + return HC_ERR_BAD_MESSAGE; + } + + if (realTask->taskBase.taskStatus > TASK_TYPE_BEGIN) { + LOGI("The message is repeated, ignore it, status :%d", realTask->taskBase.taskStatus); + *status = IGNORE_MSG; + return HC_SUCCESS; + } + int res; + int message = 0; + res = GetIntFromJson(in, FIELD_MESSAGE, &message); + if (res != 0 || message != ISO_CLIENT_BIND_EXCHANGE_CONFIRM) { + return HC_ERR_BAD_MESSAGE; + } + res = CheckEncResult(params, in, RESULT_AAD); + if (res != 0) { + LOGE("CheckEncResult failed, res:%d", res); + DeleteAuthCode(params); + return res; + } + res = SendResultToFinalSelf(params, out, false); + if (res != 0) { + LOGE("SendResultToFinalSelf failed, res:%d", res); + DeleteAuthCode(params); + return res; + } + realTask->taskBase.taskStatus = TASK_TYPE_FINAL; + *status = FINISH; + return res; +} + +static int DecryptChallenge(const IsoParams *params, const CJson *in, uint8_t *challenge, uint32_t challengeLen) +{ + (void)challengeLen; + int res; + uint8_t *encData = NULL; + uint8_t *nonce = NULL; + + encData = (uint8_t *)HcMalloc(ENC_CHALLENGE_LEN, 0); + if (encData == NULL) { + res = HC_ERR_ALLOC_MEMORY; + goto err; + } + GOTO_ERR_AND_SET_RET(GetByteFromJson(in, FIELD_ENC_DATA, encData, ENC_CHALLENGE_LEN), res); + nonce = (uint8_t *)HcMalloc(NONCE_SIZE, 0); + if (nonce == NULL) { + res = HC_ERR_ALLOC_MEMORY; + goto err; + } + GOTO_ERR_AND_SET_RET(GetByteFromJson(in, FIELD_NONCE, nonce, NONCE_SIZE), res); + Uint8Buff encDataBuf = { encData, ENC_CHALLENGE_LEN }; + GcmParam gcmParam; + gcmParam.aad = (uint8_t *)EXCHANGE_AAD; + gcmParam.aadLen = (uint32_t)strlen(EXCHANGE_AAD); + gcmParam.nonce = nonce; + gcmParam.nonceLen = NONCE_SIZE; + Uint8Buff challengeBuf = { challenge, CHALLENGE_SIZE }; + res = params->baseParams.loader->aesGcmDecrypt(¶ms->baseParams.sessionKey, &encDataBuf, &gcmParam, false, + &challengeBuf); + if (res != 0) { + LOGE("decrypt challenge failed, res:%d", res); + goto err; + } +err: + HcFree(encData); + HcFree(nonce); + return res; +} + +static int GenAndEncAuthCode(const IsoParams *params, Uint8Buff *nonceBuf, const Uint8Buff *challengeBuf, + Uint8Buff *encAuthCodeBuf) +{ + int res; + uint8_t *keyAlias = NULL; + uint8_t *authCode = (uint8_t *)HcMalloc(AUTH_CODE_LEN, 0); + if (authCode == NULL) { + res = HC_ERR_ALLOC_MEMORY; + goto err; + } + Uint8Buff authCodeBuf = { authCode, AUTH_CODE_LEN }; + res = params->baseParams.loader->generateRandom(&authCodeBuf); + if (res != 0) { + LOGE("generate auth code failed, res:%d", res); + goto err; + } + + res = params->baseParams.loader->generateRandom(nonceBuf); + if (res != 0) { + LOGE("generate nonce failed, res:%d", res); + goto err; + } + GcmParam gcmParam = { nonceBuf->val, nonceBuf->length, challengeBuf->val, challengeBuf->length }; + res = params->baseParams.loader->aesGcmEncrypt(¶ms->baseParams.sessionKey, &authCodeBuf, &gcmParam, false, + encAuthCodeBuf); + if (res != 0) { + LOGE("encrypt auth code failed, res:%d", res); + goto err; + } + + keyAlias = (uint8_t *)HcMalloc(ISO_KEY_ALIAS_LEN, 0); + if (keyAlias == NULL) { + res = HC_ERR_ALLOC_MEMORY; + goto err; + } + res = GenerateKeyAliasInIso(params, keyAlias, ISO_KEY_ALIAS_LEN, true); + if (res != 0) { + LOGE("GenerateKeyAliasInIso failed, res:%d", res); + goto err; + } + + Uint8Buff keyAliasBuf = { keyAlias, ISO_KEY_ALIAS_LEN }; + ExtraInfo exInfo = { { params->baseParams.authIdPeer.val, params->baseParams.authIdPeer.length }, + params->peerUserType, PAIR_TYPE_BIND }; + res = params->baseParams.loader->importAsymmetricKey(&keyAliasBuf, &authCodeBuf, &exInfo); + if (res != 0) { + LOGE("importAsymmetricKey failed, res:%d", res); + goto err; + } +err: + HcFree(keyAlias); + FreeAndCleanKey(&authCodeBuf); + return res; +} + +static int GenerateAuthCodeAndImport(const IsoParams *params, CJson *out, uint8_t *challenge, uint32_t challengeLen) +{ + int res; + uint8_t *nonce = NULL; + uint8_t *encAuthCode = NULL; + CJson *payload = NULL; + CJson *sendToPeer = NULL; + + nonce = (uint8_t *)HcMalloc(NONCE_SIZE, 0); + if (nonce == NULL) { + res = HC_ERR_ALLOC_MEMORY; + goto err; + } + encAuthCode = (uint8_t *)HcMalloc(AUTH_CODE_LEN + TAG_LEN, 0); + if (encAuthCode == NULL) { + res = HC_ERR_ALLOC_MEMORY; + goto err; + } + Uint8Buff encAuthCodeBuf = { encAuthCode, AUTH_CODE_LEN + TAG_LEN }; + Uint8Buff nonceBuf = { nonce, NONCE_SIZE }; + Uint8Buff challengeBuf = { challenge, challengeLen }; + + res = GenAndEncAuthCode(params, &nonceBuf, &challengeBuf, &encAuthCodeBuf); + if (res != 0) { + LOGE("GenAndEncAuthCode failed, res:%d", res); + goto err; + } + payload = CreateJson(); + if (payload == NULL) { + res = HC_ERR_ALLOC_MEMORY; + goto err; + } + sendToPeer = CreateJson(); + if (sendToPeer == NULL) { + res = HC_ERR_ALLOC_MEMORY; + goto err; + } + GOTO_ERR_AND_SET_RET(AddIntToJson(sendToPeer, FIELD_MESSAGE, ISO_SERVER_BIND_EXCHANGE_RET), res); + GOTO_ERR_AND_SET_RET(AddByteToJson(payload, FIELD_ENC_AUTH_TOKEN, encAuthCodeBuf.val, encAuthCodeBuf.length), res); + GOTO_ERR_AND_SET_RET(AddByteToJson(payload, FIELD_NONCE, nonceBuf.val, nonceBuf.length), res); + GOTO_ERR_AND_SET_RET(AddObjToJson(sendToPeer, FIELD_PAYLOAD, payload), res); + GOTO_ERR_AND_SET_RET(AddObjToJson(out, FIELD_SEND_TO_PEER, sendToPeer), res); + +err: + HcFree(nonce); + HcFree(encAuthCode); + FreeJson(payload); + FreeJson(sendToPeer); + return res; +} + +static int ServerBindExchangeStart(const IsoParams *params, IsoServerBindExchangeTask *task, + const CJson *in, CJson *out, int *status) +{ + int res; + uint8_t *challenge = (uint8_t *)HcMalloc(CHALLENGE_SIZE, 0); + if (challenge == NULL) { + res = HC_ERR_ALLOC_MEMORY; + goto err; + } + res = DecryptChallenge(params, in, challenge, CHALLENGE_SIZE); + if (res != 0) { + LOGE("decrypt challenge failed, res:%d", res); + goto err; + } + res = GenerateAuthCodeAndImport(params, out, challenge, CHALLENGE_SIZE); + if (res != 0) { + LOGE("GenerateAuthCodeAndImport failed, res:%d", res); + goto err; + } + task->taskBase.taskStatus = TASK_TYPE_BEGIN; + *status = CONTINUE; +err: + HcFree(challenge); + return res; +} + +SymBaseCurTask *CreateServerBindExchangeTask(IsoParams *params, const CJson *in, CJson *out, int *status) +{ + IsoServerBindExchangeTask *task = (IsoServerBindExchangeTask *)HcMalloc(sizeof(IsoServerBindExchangeTask), 0); + if (task == NULL) { + return NULL; + } + task->taskBase.destroyTask = DestroyServerBindExchangeTask; + task->taskBase.process = Process; + task->taskBase.getCurTaskType = GetTaskType; + int res = ServerBindExchangeStart(params, task, in, out, status); + if (res != 0) { + DestroyServerBindExchangeTask((struct SymBaseCurTaskT *)task); + return NULL; + } + return (SymBaseCurTask *)task; +} \ No newline at end of file diff --git a/services/module/src/das_module/iso_task/lite_exchange_task/iso_server_unbind_exchange_task.c b/services/module/src/das_module/iso_task/lite_exchange_task/iso_server_unbind_exchange_task.c new file mode 100644 index 0000000..6053e1b --- /dev/null +++ b/services/module/src/das_module/iso_task/lite_exchange_task/iso_server_unbind_exchange_task.c @@ -0,0 +1,196 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "iso_server_unbind_exchange_task.h" +#include "common_util.h" +#include "das_module_defines.h" +#include "hc_log.h" +#include "hc_types.h" +#include "iso_task_common.h" + +enum { + TASK_TYPE_BEGIN = 1, + TASK_TYPE_FINAL, +}; + +static CurTaskType GetTaskType() +{ + return TASK_TYPE_UNBIND_LITE_EXCHANGE; +} + +static void DestroyServerUnbindExchangeTask(struct SymBaseCurTaskT *task) +{ + IsoServerUnbindExchangeTask *realTask = (IsoServerUnbindExchangeTask *)task; + HcFree(realTask); +} + +static int Process(struct SymBaseCurTaskT *task, IsoParams *params, const CJson *in, CJson *out, int *status) +{ + (void)task; + (void)params; + (void)in; + (void)out; + (void)status; + return HC_ERROR; +} + +static int CheckRemoveInfo(const Uint8Buff *removeInfoBuf, const IsoParams *params) +{ + CJson *removeInfoJson = CreateJsonFromString((const char *)(removeInfoBuf->val)); + if (removeInfoJson == NULL) { + LOGE("Get remove info json failed"); + return HC_ERR_JSON_GET; + } + int userType = 0; + uint8_t *peerAuthId = NULL; + int res = GetIntFromJson(removeInfoJson, FIELD_RMV_TYPE, &userType); + if (res != HC_SUCCESS) { + LOGE("Get user type failed"); + goto err; + } + if (userType != params->peerUserType) { + LOGE("User type not match :%d", userType); + res = HC_ERR_JSON_GET; + goto err; + } + peerAuthId = (uint8_t *)HcMalloc(params->baseParams.authIdPeer.length, 0); + if (peerAuthId == NULL) { + LOGE("Malloc failed"); + res = HC_ERR_ALLOC_MEMORY; + goto err; + } + res = GetByteFromJson(removeInfoJson, FIELD_RMV_ID, peerAuthId, params->baseParams.authIdPeer.length); + if (res != HC_SUCCESS) { + LOGE("Get remove id failed, res:%d", res); + goto err; + } + if (memcmp(peerAuthId, params->baseParams.authIdPeer.val, params->baseParams.authIdPeer.length) != 0) { + LOGE("Compare peerAuthId failed"); + res = HC_ERROR; + } +err: + FreeJson(removeInfoJson); + HcFree(peerAuthId); + return res; +} + +static char *GetAndCheckEncDataStr(const CJson *in, uint32_t *removeInfoFromJsonLen) +{ + char *removeInfoFromJson = (char *)GetStringFromJson(in, FIELD_ENC_DATA); + if (removeInfoFromJson == NULL) { + LOGE("No encData in unbind json"); + return NULL; + } + + *removeInfoFromJsonLen = strlen(removeInfoFromJson); + if (*removeInfoFromJsonLen <= TAG_LEN || *removeInfoFromJsonLen > MAX_BUFFER_LEN) { + LOGE("err removeInfoFromJsonLen"); + return NULL; + } + return removeInfoFromJson; +} + +static int DecryptRemoveInfo(const IsoParams *params, const CJson *in) +{ + int res; + uint8_t *nonce = NULL; + uint8_t *removeInfo = NULL; + Uint8Buff encDataBuf = { NULL, 0 }; + + nonce = (uint8_t *)HcMalloc(NONCE_SIZE, 0); + if (nonce == NULL) { + res = HC_ERR_ALLOC_MEMORY; + goto err; + } + GOTO_ERR_AND_SET_RET(GetByteFromJson(in, FIELD_NONCE, nonce, NONCE_SIZE), res); + uint32_t removeInfoFromJsonLen = 0; + char *removeInfoFromJson = GetAndCheckEncDataStr(in, &removeInfoFromJsonLen); + if (removeInfoFromJson == NULL) { + res = HC_ERR_JSON_GET; + goto err; + } + + uint32_t removeInfoLen = removeInfoFromJsonLen - TAG_LEN; + removeInfo = (uint8_t *)HcMalloc(removeInfoLen, 0); + if (removeInfo == NULL) { + res = HC_ERR_ALLOC_MEMORY; + goto err; + } + + encDataBuf.length = removeInfoFromJsonLen / BYTE_TO_HEX_OPER_LENGTH; + encDataBuf.val = (uint8_t *)HcMalloc(encDataBuf.length, 0); + if (encDataBuf.val == NULL) { + LOGE("Malloc encDataBuf.val failed."); + res = HC_ERR_ALLOC_MEMORY; + goto err; + } + res = HexStringToByte(removeInfoFromJson, encDataBuf.val, encDataBuf.length); + if (res != HC_SUCCESS) { + LOGE("HexStringToByte for encData failed."); + goto err; + } + Uint8Buff removeInfoBuf = { removeInfo, removeInfoLen }; + GcmParam gcmParam = { nonce, NONCE_SIZE, (uint8_t *)UNBIND_ADD_REQUEST, HcStrlen(UNBIND_ADD_REQUEST) }; + res = params->baseParams.loader->aesGcmDecrypt(¶ms->baseParams.sessionKey, &encDataBuf, &gcmParam, false, + &removeInfoBuf); + if (res != 0) { + LOGE("decrypt removeInfo failed, res:%d", res); + goto err; + } + res = CheckRemoveInfo(&removeInfoBuf, params); +err: + HcFree(nonce); + HcFree(removeInfo); + HcFree(encDataBuf.val); + return res; +} + +static int ServerUnbindExchangeStart(const IsoParams *param, IsoServerUnbindExchangeTask *task, + const CJson *in, CJson *out, int *status) +{ + int res = DecryptRemoveInfo(param, in); + if (res != 0) { + return res; + } + + res = GenEncResult(param, ISO_SERVER_UNBIND_EXCHANGE_RET, out, UNBIND_ADD_RESPONSE, false); + if (res != 0) { + LOGE("unbind exchange gen enc result failed, res:%d", res); + goto err; + } + + task->taskBase.taskStatus = TASK_TYPE_BEGIN; + *status = FINISH; +err: + return res; +} + +SymBaseCurTask *CreateServerUnbindExchangeTask(IsoParams *params, const CJson *in, CJson *out, int *status) +{ + (void)in; + IsoServerUnbindExchangeTask *task = (IsoServerUnbindExchangeTask *)HcMalloc(sizeof(IsoServerUnbindExchangeTask), 0); + if (task == NULL) { + return NULL; + } + task->taskBase.destroyTask = DestroyServerUnbindExchangeTask; + task->taskBase.process = Process; + task->taskBase.getCurTaskType = GetTaskType; + int res = ServerUnbindExchangeStart(params, task, in, out, status); + if (res != 0) { + DestroyServerUnbindExchangeTask((struct SymBaseCurTaskT *)task); + return NULL; + } + return (SymBaseCurTask *)task; +} \ No newline at end of file diff --git a/services/module/src/das_module/iso_task_mock/iso_task_main_mock.c b/services/module/src/das_module/iso_task_mock/iso_task_main_mock.c new file mode 100644 index 0000000..79badc5 --- /dev/null +++ b/services/module/src/das_module/iso_task_mock/iso_task_main_mock.c @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "iso_task_main.h" +#include "das_asy_token_manager.h" + +bool IsIsoSupported() +{ + return false; +} + +SubTaskBase *CreateIsoSubTask(const CJson *in, CJson *out) +{ + (void)in; + (void)out; + return NULL; +} + +const TokenManager *GetSymTokenManagerInstance() +{ + return NULL; +} \ No newline at end of file diff --git a/services/module/src/das_module/pake_task/new_pake_task_mock/new_pake_task_main_mock.c b/services/module/src/das_module/pake_task/new_pake_task_mock/new_pake_task_main_mock.c new file mode 100644 index 0000000..a4290fa --- /dev/null +++ b/services/module/src/das_module/pake_task/new_pake_task_mock/new_pake_task_main_mock.c @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "new_pake_task_main.h" + +bool IsSupportNewPake() +{ + return false; +} + +SubTaskBase *CreateNewPakeSubTask(const CJson *in, CJson *out) +{ + (void)in; + (void)out; + return NULL; +} \ No newline at end of file diff --git a/services/module/src/das_module/pake_task/pake_message_util.c b/services/module/src/das_module/pake_task/pake_message_util.c new file mode 100644 index 0000000..085a5f5 --- /dev/null +++ b/services/module/src/das_module/pake_task/pake_message_util.c @@ -0,0 +1,205 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "json_utils.h" +#include "common_util.h" +#include "das_common.h" +#include "hc_log.h" +#include "module_common.h" +#include "pake_base_cur_task.h" +#include "protocol_common.h" + +int32_t ParseStartJsonParams(PakeParams *params, const CJson *in) +{ + if (GetBoolFromJson(in, FIELD_SUPPORT_256_MOD, &(params->baseParams.is256ModSupported)) != HC_SUCCESS) { + LOGD("Use default DL mod length: 384."); + } + return HC_SUCCESS; +} + +int32_t PackagePakeRequestData(const PakeParams *params, CJson *payload) +{ + int32_t res = AddBoolToJson(payload, FIELD_SUPPORT_256_MOD, params->baseParams.is256ModSupported); + if (res != HC_SUCCESS) { + LOGE("Add is256ModSupported failed, res: %d.", res); + return res; + } + res = AddIntToJson(payload, FIELD_OPERATION_CODE, params->opCode); + if (res != HC_SUCCESS) { + LOGE("Add opCode failed, res: %d.", res); + return res; + } + if (params->opCode == AUTHENTICATE || params->opCode == OP_UNBIND) { + res = AddStringToJson(payload, FIELD_PKG_NAME, params->packageName); + if (res != HC_SUCCESS) { + LOGE("Add packageName failed, res: %d.", res); + return res; + } + res = AddStringToJson(payload, FIELD_SERVICE_TYPE, params->serviceType); + if (res != HC_SUCCESS) { + LOGE("Add serviceType failed, res: %d.", res); + return res; + } + res = AddIntToJson(payload, FIELD_PEER_USER_TYPE, params->userType); + if (res != HC_SUCCESS) { + LOGE("Add userType failed, res: %d.", res); + return res; + } + } + return res; +} + +int32_t ParsePakeRequestMessage(PakeParams *params, const CJson *in) +{ + int32_t res = GetBoolFromJson(in, FIELD_SUPPORT_256_MOD, &(params->baseParams.is256ModSupported)); + if (res != HC_SUCCESS) { + LOGE("Get is256ModSupported failed, res: %d.", res); + return res; + } + + if (params->opCode == AUTHENTICATE) { + res = GetAndCheckKeyLenOnServer(in, &(params->returnKey.length)); + if (res != HC_SUCCESS) { + LOGE("GetAndCheckKeyLenOnServer failed, res: %d.", res); + return res; + } + } + + return res; +} + +int32_t PackagePakeResponseData(const PakeParams *params, CJson *payload) +{ + int32_t res = AddByteToJson(payload, FIELD_SALT, params->baseParams.salt.val, params->baseParams.salt.length); + if (res != HC_SUCCESS) { + LOGE("Add salt failed, res: %d.", res); + return res; + } + res = AddByteToJson(payload, FIELD_EPK, params->baseParams.epkSelf.val, params->baseParams.epkSelf.length); + if (res != HC_SUCCESS) { + LOGE("Add epkSelf failed, res: %d.", res); + return res; + } + if (params->opCode == AUTHENTICATE || params->opCode == OP_UNBIND) { + res = AddByteToJson(payload, FIELD_NONCE, params->nonce.val, params->nonce.length); + if (res != HC_SUCCESS) { + LOGE("Add nonce failed, res: %d.", res); + return res; + } + res = AddIntToJson(payload, FIELD_PEER_USER_TYPE, params->userType); + if (res != HC_SUCCESS) { + LOGE("Add userType failed, res: %d.", res); + return res; + } + } + return res; +} + +static int32_t GetDasEpkPeerFromJson(PakeParams *params, const CJson *in) +{ + const char *epkPeerHex = GetStringFromJson(in, FIELD_EPK); + if (epkPeerHex == NULL) { + LOGE("Get epkPeerHex failed."); + return HC_ERR_JSON_GET; + } + int res = InitSingleParam(&(params->baseParams.epkPeer), strlen(epkPeerHex) / BYTE_TO_HEX_OPER_LENGTH); + if (res != HC_SUCCESS) { + LOGE("InitSingleParam for epkPeer failed, res: %d.", res); + return res; + } + res = HexStringToByte(epkPeerHex, params->baseParams.epkPeer.val, params->baseParams.epkPeer.length); + if (res != HC_SUCCESS) { + LOGE("Convert epkPeer from hex string to byte failed, res: %d.", res); + return res; + } + return res; +} + +int32_t ParsePakeResponseMessage(PakeParams *params, const CJson *in) +{ + int32_t res = GetByteFromJson(in, FIELD_SALT, params->baseParams.salt.val, params->baseParams.salt.length); + if (res != HC_SUCCESS) { + LOGE("Get salt failed, res: %d.", res); + return res; + } + res = GetDasEpkPeerFromJson(params, in); + if (res != HC_SUCCESS) { + LOGE("GetDasEpkPeerFromJson failed, res: %d.", res); + return res; + } + if (params->opCode == AUTHENTICATE || params->opCode == OP_UNBIND) { + res = GetByteFromJson(in, FIELD_NONCE, params->nonce.val, params->nonce.length); + if (res != HC_SUCCESS) { + LOGE("Get nonce failed, res: %d.", res); + return res; + } + } + + return res; +} + +int32_t PackagePakeClientConfirmData(const PakeParams *params, CJson *payload) +{ + int32_t res = AddByteToJson(payload, FIELD_EPK, params->baseParams.epkSelf.val, params->baseParams.epkSelf.length); + if (res != HC_SUCCESS) { + LOGE("Add epkSelf failed, res: %d.", res); + return res; + } + res = AddByteToJson(payload, FIELD_KCF_DATA, params->baseParams.kcfData.val, params->baseParams.kcfData.length); + if (res != HC_SUCCESS) { + LOGE("Add kcfData failed, res: %d.", res); + return res; + } + + return res; +} + +int32_t ParsePakeClientConfirmMessage(PakeParams *params, const CJson *in) +{ + int32_t res = GetByteFromJson(in, FIELD_KCF_DATA, params->baseParams.kcfDataPeer.val, + params->baseParams.kcfDataPeer.length); + if (res != HC_SUCCESS) { + LOGE("Get kcfDataPeer failed, res: %d.", res); + return res; + } + res = GetDasEpkPeerFromJson(params, in); + if (res != HC_SUCCESS) { + LOGE("GetDasEpkPeerFromJson failed, res: %d.", res); + return res; + } + return res; +} + +int32_t PackagePakeServerConfirmData(const PakeParams *params, CJson *payload) +{ + int32_t res = AddByteToJson(payload, FIELD_KCF_DATA, + params->baseParams.kcfData.val, params->baseParams.kcfData.length); + if (res != HC_SUCCESS) { + LOGE("Add kcfData failed, res: %d.", res); + return res; + } + return res; +} + +int32_t ParsePakeServerConfirmMessage(PakeParams *params, const CJson *in) +{ + int32_t res = GetByteFromJson(in, FIELD_KCF_DATA, params->baseParams.kcfDataPeer.val, + params->baseParams.kcfDataPeer.length); + if (res != HC_SUCCESS) { + LOGE("Get kcfDataPeer failed, res: %d.", res); + return res; + } + return res; +} \ No newline at end of file diff --git a/services/module/src/das_module/pake_task/pake_task/pake_client_task.c b/services/module/src/das_module/pake_task/pake_task/pake_client_task.c new file mode 100644 index 0000000..cb7ff24 --- /dev/null +++ b/services/module/src/das_module/pake_task/pake_task/pake_client_task.c @@ -0,0 +1,170 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "pake_client_task.h" +#include "das_common.h" +#include "device_auth_defines.h" +#include "hc_log.h" +#include "hc_types.h" +#include "pake_client_protocol_task.h" +#include "pake_protocol_task_common.h" +#include "pake_task_common.h" +#include "standard_client_bind_exchange_task.h" +#include "standard_client_unbind_exchange_task.h" + +static int GetPakeClientTaskType(const struct SubTaskBaseT *task) +{ + PakeClientTask *realTask = (PakeClientTask *)task; + if (realTask->curTask == NULL) { + LOGE("cur Task is null"); + return TASK_TYPE_NONE; + } + return realTask->curTask->getCurTaskType(); +} + +static void DestroyPakeClientTask(struct SubTaskBaseT *task) +{ + PakeClientTask *innerTask = (PakeClientTask *)task; + if (innerTask == NULL) { + return; + } + + DestroyDasPakeParams(&(innerTask->params)); + if (innerTask->curTask != NULL) { + innerTask->curTask->destroyTask(innerTask->curTask); + } + HcFree(innerTask); +} + +static int CreateAndProcessNextBindTask(PakeClientTask *realTask, const CJson *in, CJson *out, int *status) +{ + realTask->curTask->destroyTask(realTask->curTask); + realTask->curTask = CreateStandardBindExchangeClientTask(); + if (realTask->curTask == NULL) { + LOGE("CreateBindExchangeTask failed"); + return HC_ERROR; + } + int res = realTask->curTask->process(realTask->curTask, &(realTask->params), in, out, status); + if (res != HC_SUCCESS) { + LOGE("process StandardBindExchangeClientTask failed."); + } + return res; +} + +static int CreateAndProcessNextUnbindTask(PakeClientTask *realTask, const CJson *in, CJson *out, int *status) +{ + realTask->curTask->destroyTask(realTask->curTask); + realTask->curTask = CreateStandardUnbindExchangeClientTask(); + if (realTask->curTask == NULL) { + LOGE("CreateBindExchangeTask failed"); + return HC_ERROR; + } + int res = realTask->curTask->process(realTask->curTask, &(realTask->params), in, out, status); + if (res != HC_SUCCESS) { + LOGE("process StandardUnbindExchangeClientTask failed."); + } + return res; +} + +static int CreateNextTask(PakeClientTask *realTask, const CJson *in, CJson *out, int *status) +{ + int res = HC_SUCCESS; + switch (realTask->params.opCode) { + case OP_BIND: + if (realTask->curTask->getCurTaskType() == TASK_TYPE_BIND_STANDARD_EXCHANGE) { + break; + } + res = CreateAndProcessNextBindTask(realTask, in, out, status); + break; + case OP_UNBIND: + if (realTask->curTask->getCurTaskType() == TASK_TYPE_UNBIND_STANDARD_EXCHANGE) { + break; + } + res = CreateAndProcessNextUnbindTask(realTask, in, out, status); + break; + case AUTH_KEY_AGREEMENT: + case AUTHENTICATE: + break; + default: + LOGE("error opcode: %d", realTask->params.opCode); + res = HC_ERR_INVALID_PARAMS; + } + if (res != HC_SUCCESS) { + LOGE("Create and process next task failed, opcode: %d, res: %d.", realTask->params.opCode, res); + SendErrorToOut(out, realTask->params.opCode, res); + return res; + } + if (*status != FINISH) { + return res; + } + res = SendResultToSelf(&realTask->params, out); + if (res != HC_SUCCESS) { + LOGE("SendResultToSelf failed, res: %d", res); + SendErrorToOut(out, realTask->params.opCode, res); + return res; + } + LOGD("End client task successfully."); + return res; +} + +static int Process(struct SubTaskBaseT *task, const CJson *in, CJson *out, int *status) +{ + if (task == NULL || in == NULL || out == NULL || status == NULL) { + return HC_ERR_INVALID_PARAMS; + } + PakeClientTask *realTask = (PakeClientTask *)task; + if (realTask->curTask == NULL) { + LOGE("cur Task is null"); + return HC_ERROR; + } + + realTask->params.baseParams.supportedPakeAlg = GetSupportedPakeAlg(&(realTask->taskBase.curVersion)); + int res = realTask->curTask->process(realTask->curTask, &(realTask->params), in, out, status); + if (*status != FINISH) { + return res; + } + if (res != HC_SUCCESS) { + LOGE("process failed, res:%d", res); + return res; + } + return CreateNextTask(realTask, in, out, status); +} + +SubTaskBase *CreatePakeClientTask(const CJson *in, CJson *out) +{ + PakeClientTask *task = (PakeClientTask *)HcMalloc(sizeof(PakeClientTask), 0); + if (task == NULL) { + LOGE("Malloc for PakeClientTask failed."); + return NULL; + } + + task->taskBase.getTaskType = GetPakeClientTaskType; + task->taskBase.destroyTask = DestroyPakeClientTask; + task->taskBase.process = Process; + + int res = InitDasPakeParams(&(task->params), in); + if (res != HC_SUCCESS) { + LOGE("Init das pake params failed, res: %d.", res); + DestroyPakeClientTask((struct SubTaskBaseT *)task); + return NULL; + } + task->curTask = CreatePakeProtocolClientTask(); + if (task->curTask == NULL) { + LOGE("Create pake protocol client task failed, res: %d.", res); + DestroyPakeClientTask((struct SubTaskBaseT *)task); + return NULL; + } + return (SubTaskBase *)task; +} diff --git a/services/module/src/das_module/pake_task/pake_task/pake_protocol_task/pake_client_protocol_task.c b/services/module/src/das_module/pake_task/pake_task/pake_protocol_task/pake_client_protocol_task.c new file mode 100755 index 0000000..0797d40 --- /dev/null +++ b/services/module/src/das_module/pake_task/pake_task/pake_protocol_task/pake_client_protocol_task.c @@ -0,0 +1,273 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "pake_client_protocol_task.h" +#include "das_common.h" +#include "hc_log.h" +#include "hc_types.h" +#include "pake_message_util.h" +#include "pake_protocol_common.h" +#include "pake_task_common.h" + +enum { + TASK_STATUS_CLIENT_PAKE_BEGIN = 0, + TASK_STATUS_CLIENT_PAKE_REQUEST, + TASK_STATUS_CLIENT_PAKE_CONFIRM, + TASK_STATUS_CLIENT_PAKE_VERIFY_CONFIRM, +}; + +static CurTaskType GetTaskType() +{ + return TASK_TYPE_PAKE_PROTOCOL; +} + +static int PakeRequest(AsyBaseCurTask *task, PakeParams *params, const CJson *in, CJson *out, int *status) +{ + int res; + if (task->taskStatus != TASK_STATUS_CLIENT_PAKE_BEGIN) { + LOGI("The message is repeated, ignore it, status :%d", task->taskStatus); + *status = IGNORE_MSG; + return HC_SUCCESS; + } + + res = ParseStartJsonParams(params, in); + if (res != HC_SUCCESS) { + LOGE("ParseStartJsonParams failed, res: %d.", res); + return res; + } + + // execute + res = ClientRequestPakeProtocol(¶ms->baseParams); + if (res != HC_SUCCESS) { + LOGE("ClientRequestPakeProtocol failed, res: %d.", res); + return res; + } + + res = ConstructOutJson(params, out); + if (res != HC_SUCCESS) { + LOGE("ConstructOutJson failed, res: %d.", res); + return res; + } + CJson *payload = GetObjFromJson(out, FIELD_PAYLOAD); + if (payload == NULL) { + LOGE("Get payload from json failed."); + return HC_ERR_JSON_GET; + } + res = PackagePakeRequestData(params, payload); + if (res != HC_SUCCESS) { + LOGE("PackagePakeRequestData failed, res: %d.", res); + return res; + } + // package differentiated data + if (params->opCode == AUTHENTICATE || params->opCode == OP_UNBIND) { + res = AddByteToJson(payload, FIELD_PEER_AUTH_ID, params->baseParams.idSelf.val, + params->baseParams.idSelf.length); + if (res != HC_SUCCESS) { + LOGE("Add idSelf failed, res: %d.", res); + return res; + } + res = AddIntToJson(payload, FIELD_KEY_LENGTH, params->returnKey.length); + if (res != HC_SUCCESS) { + LOGE("Add keyLength failed, res: %d.", res); + return res; + } + } + + task->taskStatus = TASK_STATUS_CLIENT_PAKE_REQUEST; + *status = CONTINUE; + return res; +} + +static int ParseMsgForClientConfirm(PakeParams *params, const CJson *in) +{ + int res = ParsePakeResponseMessage(params, in); + if (res != HC_SUCCESS) { + LOGE("ParsePakeResponseMessage failed, res: %d.", res); + return res; + } + // parse differentiated data + res = GetByteFromJson(in, FIELD_CHALLENGE, params->baseParams.challengePeer.val, + params->baseParams.challengePeer.length); + if (res != HC_SUCCESS) { + LOGE("Get challengePeer failed, res: %d.", res); + return res; + } + if (params->opCode == AUTHENTICATE || params->opCode == OP_UNBIND) { + res = GetAndCheckAuthIdPeer(in, &(params->baseParams.idPeer)); + if (res != HC_SUCCESS) { + LOGE("GetAndCheckAuthIdPeer failed, res: %d.", res); + return res; + } + } + return res; +} + +static int PackageMsgForClientConfirm(PakeParams *params, CJson *out) +{ + int res = ConstructOutJson(params, out); + if (res != HC_SUCCESS) { + LOGE("ConstructOutJson failed, res: %d.", res); + return res; + } + CJson *payload = GetObjFromJson(out, FIELD_PAYLOAD); + if (payload == NULL) { + LOGE("Get payload from json failed."); + return HC_ERR_JSON_GET; + } + res = PackagePakeClientConfirmData(params, payload); + if (res != HC_SUCCESS) { + LOGE("PackagePakeClientConfirmData failed, res: %d.", res); + return res; + } + res = AddByteToJson(payload, FIELD_CHALLENGE, params->baseParams.challengeSelf.val, + params->baseParams.challengeSelf.length); + if (res != HC_SUCCESS) { + LOGE("Add challengeSelf failed, res: %d.", res); + return res; + } + return res; +} + +static int PakeClientConfirm(AsyBaseCurTask *task, PakeParams *params, const CJson *in, CJson *out, int *status) +{ + int res; + if (task->taskStatus < TASK_STATUS_CLIENT_PAKE_REQUEST) { + return HC_ERR_BAD_MESSAGE; + } + if (task->taskStatus > TASK_STATUS_CLIENT_PAKE_REQUEST) { + LOGI("The message is repeated, ignore it, status :%d", task->taskStatus); + *status = IGNORE_MSG; + return HC_SUCCESS; + } + + res = ParseMsgForClientConfirm(params, in); + if (res != HC_SUCCESS) { + LOGE("ParseMsgForClientConfirm failed, res: %d.", res); + return res; + } + if (((uint32_t)params->baseParams.supportedPakeAlg & PSK_SPEKE) && + (params->opCode == AUTHENTICATE || params->opCode == OP_UNBIND)) { + res = FillPskWithDerivedKey(params); + if (res != HC_SUCCESS) { + LOGE("FillPskWithDerivedKey failed."); + return res; + } + } + + // execute + res = ClientConfirmPakeProtocol(&(params->baseParams)); + if (res != HC_SUCCESS) { + LOGE("ClientConfirmPakeProtocol failed, res:%d", res); + return res; + } + + res = PackageMsgForClientConfirm(params, out); + if (res != HC_SUCCESS) { + LOGE("PackageMsgForClientConfirm failed, res: %d.", res); + return res; + } + + task->taskStatus = TASK_STATUS_CLIENT_PAKE_CONFIRM; + *status = CONTINUE; + return res; +} + +static int PakeClientVerifyConfirm(AsyBaseCurTask *task, PakeParams *params, const CJson *in, CJson *out, int *status) +{ + int res; + + if (task->taskStatus < TASK_STATUS_CLIENT_PAKE_CONFIRM) { + return HC_ERR_BAD_MESSAGE; + } + if (task->taskStatus > TASK_STATUS_CLIENT_PAKE_CONFIRM) { + LOGI("The message is repeated, ignore it, status :%d", task->taskStatus); + *status = IGNORE_MSG; + return HC_SUCCESS; + } + + // parse message + res = ParsePakeServerConfirmMessage(params, in); + if (res != HC_SUCCESS) { + LOGE("ParsePakeServerConfirmMessage failed, res: %d.", res); + return res; + } + + // execute + res = ClientVerifyConfirmPakeProtocol(¶ms->baseParams); + if (res != HC_SUCCESS) { + LOGE("ClientVerifyConfirmPakeProtocol failed, res: %d.", res); + return res; + } + + task->taskStatus = TASK_STATUS_CLIENT_PAKE_VERIFY_CONFIRM; + *status = FINISH; + return res; +} + +static int Process(struct AsyBaseCurTaskT *task, PakeParams *params, const CJson *in, CJson *out, int *status) +{ + int res = HC_SUCCESS; + uint32_t step = ProtocolMessageIn(in); + if (step == INVALID_MESSAGE) { + res = PakeRequest(task, params, in, out, status); + step = 1; + goto out; + } + + step = step + 1; /* when receive peer message code, need to do next step */ + switch (step) { + case STEP_TWO: + res = PakeClientConfirm(task, params, in, out, status); + break; + case STEP_THREE: + res = PakeClientVerifyConfirm(task, params, in, out, status); + break; + default: + res = HC_ERR_BAD_MESSAGE; + break; + } +out: + if (res != HC_SUCCESS) { + SendErrorToOut(out, params->opCode, res); + } else { + if (step != STEP_THREE) { + res = ClientProtocolMessageOut(out, params->opCode, step); + } + } + return res; +} + +static void DestroyPakeProtocolClientTask(struct AsyBaseCurTaskT *task) +{ + PakeProtocolClientTask *innerTask = (PakeProtocolClientTask *)task; + if (innerTask == NULL) { + return; + } + + HcFree(innerTask); +} + +AsyBaseCurTask *CreatePakeProtocolClientTask() +{ + PakeProtocolClientTask *task = (PakeProtocolClientTask *)HcMalloc(sizeof(PakeProtocolClientTask), 0); + if (task == NULL) { + return NULL; + } + task->taskBase.destroyTask = DestroyPakeProtocolClientTask; + task->taskBase.process = Process; + task->taskBase.taskStatus = TASK_STATUS_CLIENT_PAKE_BEGIN; + task->taskBase.getCurTaskType = GetTaskType; + return (AsyBaseCurTask *)task; +} \ No newline at end of file diff --git a/services/module/src/das_module/pake_task/pake_task/pake_protocol_task/pake_protocol_task_common.c b/services/module/src/das_module/pake_task/pake_task/pake_protocol_task/pake_protocol_task_common.c new file mode 100644 index 0000000..9215a6f --- /dev/null +++ b/services/module/src/das_module/pake_task/pake_task/pake_protocol_task/pake_protocol_task_common.c @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "pake_protocol_task_common.h" +#include "hc_log.h" +#include "hc_types.h" +#include "module_common.h" +#include "pake_protocol_common.h" +#include "pake_task_common.h" + +void DestroyDasPakeParams(PakeParams *params) +{ + if (params == NULL) { + return; + } + + DestroyPakeBaseParams(&(params->baseParams)); + + if (params->returnKey.val != NULL) { + (void)memset_s(params->returnKey.val, params->returnKey.length, 0, params->returnKey.length); + HcFree(params->returnKey.val); + params->returnKey.val = NULL; + } + + HcFree(params->packageName); + params->packageName = NULL; + + HcFree(params->serviceType); + params->serviceType = NULL; + + HcFree(params->nonce.val); + params->nonce.val = NULL; +} + +static int32_t FillReturnKey(PakeParams *params, const CJson *in) +{ + if (params->opCode == OP_UNBIND) { + params->returnKey.val = NULL; + params->returnKey.length = 0; + return HC_SUCCESS; + } + int32_t res = GetIntFromJson(in, FIELD_KEY_LENGTH, (int *)&(params->returnKey.length)); + if (res != HC_SUCCESS) { + LOGD("Get key length failed, use default, res: %d", res); + params->returnKey.length = DEFAULT_RETURN_KEY_LENGTH; + } + if (params->returnKey.length < MIN_OUTPUT_KEY_LEN || params->returnKey.length > MAX_OUTPUT_KEY_LEN) { + LOGE("Output key length is invalid."); + return HC_ERR_INVALID_LEN; + } + res = InitSingleParam(¶ms->returnKey, params->returnKey.length); + if (res != HC_SUCCESS) { + LOGE("InitSingleParam for returnKey failed, res: %d.", res); + } + return res; +} + +int32_t InitDasPakeParams(PakeParams *params, const CJson *in) +{ + if (params == NULL || in == NULL) { + LOGE("%s; %s;", (params == NULL) ? "params is null" : "params is not null", + (in == NULL) ? "in is null" : "in is not null"); + return HC_ERR_INVALID_PARAMS; + } + + int32_t res = InitPakeBaseParams(&(params->baseParams)); + if (res != HC_SUCCESS) { + LOGE("InitPakeBaseParams failed, res: %d.", res); + goto err; + } + + res = FillDasPakeParams(params, in); + if (res != HC_SUCCESS) { + LOGE("FillDasPakeParams failed, res: %d.", res); + goto err; + } + + res = FillReturnKey(params, in); + if (res != HC_SUCCESS) { + LOGE("FillReturnKey failed, res: %d.", res); + goto err; + } + + return HC_SUCCESS; +err: + DestroyDasPakeParams(params); + return res; +} \ No newline at end of file diff --git a/services/module/src/das_module/pake_task/pake_task/pake_protocol_task/pake_server_protocol_task.c b/services/module/src/das_module/pake_task/pake_task/pake_protocol_task/pake_server_protocol_task.c new file mode 100755 index 0000000..f7f65ab --- /dev/null +++ b/services/module/src/das_module/pake_task/pake_task/pake_protocol_task/pake_server_protocol_task.c @@ -0,0 +1,232 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "pake_server_protocol_task.h" +#include "das_common.h" +#include "hc_log.h" +#include "hc_types.h" +#include "pake_message_util.h" +#include "pake_protocol_common.h" +#include "pake_task_common.h" + +enum { + TASK_STATUS_SERVER_PAKE_BEGIN = 0, + TASK_STATUS_SERVER_PAKE_RESPONSE, + TASK_STATUS_SERVER_PAKE_CONFIRM +}; + +static CurTaskType GetTaskType() +{ + return TASK_TYPE_PAKE_PROTOCOL; +} + +static int PackageMsgForResponse(const PakeParams *params, CJson *out) +{ + int res = ConstructOutJson(params, out); + if (res != HC_SUCCESS) { + LOGE("ConstructOutJson failed, res: %d.", res); + return res; + } + CJson *payload = GetObjFromJson(out, FIELD_PAYLOAD); + if (payload == NULL) { + LOGE("Get payload from json failed."); + return HC_ERR_JSON_GET; + } + res = PackagePakeResponseData(params, payload); + if (res != HC_SUCCESS) { + LOGE("PackagePakeResponseData failed, res: %d.", res); + return res; + } + // package differentiated data + res = AddByteToJson(payload, FIELD_CHALLENGE, params->baseParams.challengeSelf.val, + params->baseParams.challengeSelf.length); + if (res != HC_SUCCESS) { + LOGE("Add challengeSelf failed, res: %d.", res); + return res; + } + if (params->opCode == AUTHENTICATE || params->opCode == OP_UNBIND) { + res = AddByteToJson(payload, FIELD_PEER_AUTH_ID, params->baseParams.idSelf.val, + params->baseParams.idSelf.length); + if (res != HC_SUCCESS) { + LOGE("Add idSelf failed, res: %d.", res); + return res; + } + } + return res; +} + +static int PakeResponse(AsyBaseCurTask *task, PakeParams *params, const CJson *in, CJson *out, int *status) +{ + int res; + if (task->taskStatus > TASK_STATUS_SERVER_PAKE_BEGIN) { + LOGI("The message is repeated, ignore it, status :%d", task->taskStatus); + *status = IGNORE_MSG; + return HC_SUCCESS; + } + + res = ParsePakeRequestMessage(params, in); + if (res != HC_SUCCESS) { + LOGE("ParsePakeRequestMessage failed, res: %d.", res); + return res; + } + // parse differentiated data + if (params->opCode == AUTHENTICATE || params->opCode == OP_UNBIND) { + res = GetAndCheckAuthIdPeer(in, &(params->baseParams.idPeer)); + if (res != HC_SUCCESS) { + LOGE("GetAndCheckAuthIdPeer failed, res: %d.", res); + return res; + } + } + + if (((uint32_t)params->baseParams.supportedPakeAlg & PSK_SPEKE) && + (params->opCode == AUTHENTICATE || params->opCode == OP_UNBIND)) { + res = FillPskWithDerivedKey(params); + if (res != HC_SUCCESS) { + LOGE("FillPskWithDerivedKey failed, res: %d.", res); + return res; + } + } + + // execute + res = ServerResponsePakeProtocol(¶ms->baseParams); + if (res != HC_SUCCESS) { + LOGE("ServerResponsePakeProtocol failed, res:%d", res); + return res; + } + + // package message + res = PackageMsgForResponse(params, out); + if (res != HC_SUCCESS) { + LOGE("PackageMsgForResponse failed, res: %d.", res); + return res; + } + + task->taskStatus = TASK_STATUS_SERVER_PAKE_RESPONSE; + *status = CONTINUE; + return res; +} + +static int PakeServerConfirm(AsyBaseCurTask *task, PakeParams *params, const CJson *in, CJson *out, int *status) +{ + int res; + if (task->taskStatus < TASK_STATUS_SERVER_PAKE_RESPONSE) { + return HC_ERR_BAD_MESSAGE; + } + if (task->taskStatus > TASK_STATUS_SERVER_PAKE_RESPONSE) { + LOGI("The message is repeated, ignore it, status :%d", task->taskStatus); + *status = IGNORE_MSG; + return HC_SUCCESS; + } + + // parse message + res = ParsePakeClientConfirmMessage(params, in); + if (res != HC_SUCCESS) { + LOGE("ParsePakeClientConfirmMessage failed, res: %d", res); + return res; + } + res = GetByteFromJson(in, FIELD_CHALLENGE, params->baseParams.challengePeer.val, + params->baseParams.challengePeer.length); + if (res != HC_SUCCESS) { + LOGE("Get challengePeer failed, res: %d.", res); + return res; + } + + // execute + res = ServerConfirmPakeProtocol(¶ms->baseParams); + if (res != HC_SUCCESS) { + LOGE("ServerConfirmPakeProtocol failed, res:%d", res); + return res; + } + + // package message + res = ConstructOutJson(params, out); + if (res != HC_SUCCESS) { + LOGE("ConstructOutJson failed, res: %d.", res); + return res; + } + CJson *payload = GetObjFromJson(out, FIELD_PAYLOAD); + if (payload == NULL) { + LOGE("Get payload from json failed."); + return HC_ERR_JSON_GET; + } + res = PackagePakeServerConfirmData(params, payload); + if (res != HC_SUCCESS) { + LOGE("PackagePakeServerConfirmData failed, res: %d.", res); + return res; + } + + task->taskStatus = TASK_STATUS_SERVER_PAKE_CONFIRM; + *status = FINISH; + return res; +} + +static int Process(struct AsyBaseCurTaskT *task, PakeParams *params, const CJson *in, CJson *out, int *status) +{ + int res = HC_SUCCESS; + if ((task == NULL) || (in == NULL) || (out == NULL) || (status == NULL) || (params == NULL)) { + res = HC_ERR_INVALID_PARAMS; + goto out; + } + uint32_t step = ProtocolMessageIn(in); + if (step == INVALID_MESSAGE) { + res = HC_ERR_BAD_MESSAGE; + goto out; + } + + switch (step) { + case STEP_ONE: + res = PakeResponse(task, params, in, out, status); + break; + case STEP_TWO: + res = PakeServerConfirm(task, params, in, out, status); + break; + default: + res = HC_ERR_BAD_MESSAGE; + break; + } +out: + if (res != HC_SUCCESS) { + if (out != NULL && params != NULL) { + SendErrorToOut(out, params->opCode, res); + } + } else { + res = ServerProtocolMessageOut(out, params->opCode, step); + } + return res; +} + +static void DestroyPakeProtocolServerTask(struct AsyBaseCurTaskT *task) +{ + PakeProtocolServerTask *innerTask = (PakeProtocolServerTask *)task; + if (innerTask == NULL) { + return; + } + + HcFree(innerTask); +} + +AsyBaseCurTask *CreatePakeProtocolServerTask() +{ + PakeProtocolServerTask *task = (PakeProtocolServerTask *)HcMalloc(sizeof(PakeProtocolServerTask), 0); + if (task == NULL) { + return NULL; + } + task->taskBase.destroyTask = DestroyPakeProtocolServerTask; + task->taskBase.process = Process; + task->taskBase.taskStatus = TASK_STATUS_SERVER_PAKE_BEGIN; + task->taskBase.getCurTaskType = GetTaskType; + return (AsyBaseCurTask *)task; +} + diff --git a/services/module/src/das_module/pake_task/pake_task/pake_server_task.c b/services/module/src/das_module/pake_task/pake_task/pake_server_task.c new file mode 100644 index 0000000..9e9630f --- /dev/null +++ b/services/module/src/das_module/pake_task/pake_task/pake_server_task.c @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "pake_server_task.h" +#include "das_common.h" +#include "hc_log.h" +#include "hc_types.h" +#include "pake_protocol_task_common.h" +#include "pake_server_protocol_task.h" +#include "pake_task_common.h" +#include "standard_server_bind_exchange_task.h" +#include "standard_server_unbind_exchange_task.h" + +static int GetPakeServerTaskType(const struct SubTaskBaseT *task) +{ + PakeServerTask *realTask = (PakeServerTask *)task; + if (realTask->curTask == NULL) { + LOGE("cur Task is null"); + return TASK_TYPE_NONE; + } + return realTask->curTask->getCurTaskType(); +} + +static void DestroyPakeServerTask(struct SubTaskBaseT *task) +{ + PakeServerTask *innerTask = (PakeServerTask *)task; + if (innerTask == NULL) { + return; + } + + DestroyDasPakeParams(&(innerTask->params)); + if (innerTask->curTask != NULL) { + innerTask->curTask->destroyTask(innerTask->curTask); + } + HcFree(innerTask); +} + +static int CreateAndProcessNextBindTask(PakeServerTask *realTask, const CJson *in, CJson *out, int *status) +{ + realTask->curTask->destroyTask(realTask->curTask); + realTask->curTask = CreateStandardBindExchangeServerTask(); + if (realTask->curTask == NULL) { + LOGE("CreateStandardBindExchangeServerTask failed"); + return HC_ERROR; + } + int res = realTask->curTask->process(realTask->curTask, &(realTask->params), in, out, status); + if (res != HC_SUCCESS) { + LOGE("Process StandardBindExchangeServerTask failed."); + } + return res; +} + +static int CreateAndProcessNextUnbindTask(PakeServerTask *realTask, const CJson *in, CJson *out, int *status) +{ + realTask->curTask->destroyTask(realTask->curTask); + realTask->curTask = CreateStandardUnbindExchangeServerTask(); + if (realTask->curTask == NULL) { + LOGE("CreateBindExchangeTask failed"); + return HC_ERROR; + } + int res = realTask->curTask->process(realTask->curTask, &(realTask->params), in, out, status); + if (res != HC_SUCCESS) { + LOGE("process StandardUnbindExchangeServerTask failed."); + } + return res; +} + +static int CreateNextTask(PakeServerTask *realTask, const CJson *in, CJson *out, int *status) +{ + int res = HC_SUCCESS; + switch (realTask->params.opCode) { + case OP_BIND: + if (realTask->curTask->getCurTaskType() == TASK_TYPE_BIND_STANDARD_EXCHANGE) { + break; + } + res = CreateAndProcessNextBindTask(realTask, in, out, status); + break; + case OP_UNBIND: + if (realTask->curTask->getCurTaskType() == TASK_TYPE_UNBIND_STANDARD_EXCHANGE) { + break; + } + res = CreateAndProcessNextUnbindTask(realTask, in, out, status); + break; + case AUTH_KEY_AGREEMENT: + case AUTHENTICATE: + break; + default: + LOGE("error opcode: %d", realTask->params.opCode); + res = HC_ERR_INVALID_PARAMS; + } + if (res != HC_SUCCESS) { + SendErrorToOut(out, realTask->params.opCode, res); + return res; + } + if (*status != FINISH) { + return res; + } + res = SendResultToSelf(&realTask->params, out); + if (res != HC_SUCCESS) { + LOGE("SendResultToSelf failed, res: %d", res); + SendErrorToOut(out, realTask->params.opCode, res); + return res; + } + LOGD("End server task successfully."); + return res; +} + +static int Process(struct SubTaskBaseT *task, const CJson *in, CJson *out, int *status) +{ + if (task == NULL || in == NULL || out == NULL || status == NULL) { + return HC_ERR_INVALID_PARAMS; + } + PakeServerTask *realTask = (PakeServerTask *)task; + if (realTask->curTask == NULL) { + LOGE("cur Task is null"); + return HC_ERROR; + } + + realTask->params.baseParams.supportedPakeAlg = GetSupportedPakeAlg(&(realTask->taskBase.curVersion)); + int res = realTask->curTask->process(realTask->curTask, &(realTask->params), in, out, status); + if (*status != FINISH) { + return res; + } + if (res != HC_SUCCESS) { + LOGE("process failed, res:%d", res); + return res; + } + return CreateNextTask(realTask, in, out, status); +} + +SubTaskBase *CreatePakeServerTask(const CJson *in, CJson *out) +{ + PakeServerTask *task = (PakeServerTask *)HcMalloc(sizeof(PakeServerTask), 0); + if (task == NULL) { + return NULL; + } + + task->taskBase.getTaskType = GetPakeServerTaskType; + task->taskBase.destroyTask = DestroyPakeServerTask; + task->taskBase.process = Process; + + int res = InitDasPakeParams(&(task->params), in); + if (res != HC_SUCCESS) { + LOGE("Init das pake params failed, res: %d.", res); + SendErrorToOut(out, task->params.opCode, HC_ERR_ALLOC_MEMORY); + DestroyPakeServerTask((struct SubTaskBaseT *)task); + return NULL; + } + task->curTask = CreatePakeProtocolServerTask(); + if (task->curTask == NULL) { + LOGE("Create pake protocol server task failed, res: %d.", res); + SendErrorToOut(out, task->params.opCode, HC_ERR_ALLOC_MEMORY); + DestroyPakeServerTask((struct SubTaskBaseT *)task); + return NULL; + } + return (SubTaskBase *)task; +} diff --git a/services/module/src/das_module/pake_task/pake_task/pake_task_main.c b/services/module/src/das_module/pake_task/pake_task/pake_task_main.c new file mode 100644 index 0000000..8a0585b --- /dev/null +++ b/services/module/src/das_module/pake_task/pake_task/pake_task_main.c @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "pake_task_main.h" +#include "hc_log.h" +#include "hc_types.h" +#include "pake_base_cur_task.h" +#include "pake_client_task.h" +#include "pake_server_task.h" + +bool IsSupportPake() +{ + return true; +} + +SubTaskBase *CreatePakeSubTask(const CJson *in, CJson *out) +{ + if (in == NULL || out == NULL) { + return NULL; + } + bool isClient = true; + if (GetBoolFromJson(in, FIELD_IS_CLIENT, &isClient) != HC_SUCCESS) { + LOGE("Get isClient failed."); + return NULL; + } + if (isClient) { + return CreatePakeClientTask(in, out); + } else { + return CreatePakeServerTask(in, out); + } +} diff --git a/services/module/src/das_module/pake_task/pake_task_common.c b/services/module/src/das_module/pake_task/pake_task_common.c new file mode 100644 index 0000000..a486e78 --- /dev/null +++ b/services/module/src/das_module/pake_task/pake_task_common.c @@ -0,0 +1,383 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "pake_task_common.h" +#include "common_util.h" +#include "das_asy_token_manager.h" +#include "das_common.h" +#include "das_module_defines.h" +#include "hc_log.h" +#include "hc_types.h" +#include "module_common.h" +#include "protocol_common.h" +#include "standard_client_bind_exchange_task.h" + +#define ASCII_CASE_DIFFERENCE_VALUE 32 + +int32_t ConstructOutJson(const PakeParams *params, CJson *out) +{ + int32_t res; + CJson *payload = NULL; + CJson *sendToPeer = NULL; + + payload = CreateJson(); + if (payload == NULL) { + LOGE("Create payload json failed."); + res = HC_ERR_ALLOC_MEMORY; + goto err; + } + sendToPeer = CreateJson(); + if (sendToPeer == NULL) { + LOGE("Create sendToPeer json failed."); + res = HC_ERR_ALLOC_MEMORY; + goto err; + } + + if (params->opCode == AUTHENTICATE) { + res = AddIntToJson(sendToPeer, FIELD_AUTH_FORM, AUTH_FORM_ACCOUNT_UNRELATED); + if (res != HC_SUCCESS) { + LOGE("Add authForm failed, res: %d.", res); + goto err; + } + } + res = AddObjToJson(sendToPeer, FIELD_PAYLOAD, payload); + if (res != HC_SUCCESS) { + LOGE("Add payload to sendToPeer failed, res: %d.", res); + goto err; + } + + res = AddObjToJson(out, FIELD_SEND_TO_PEER, sendToPeer); + if (res != HC_SUCCESS) { + LOGE("Add sendToPeer to out failed, res: %d.", res); + goto err; + } +err: + FreeJson(payload); + FreeJson(sendToPeer); + return res; +} + +static int32_t GenerateOutputKey(PakeParams *params) +{ + Uint8Buff keyInfo = { (uint8_t *)HICHAIN_RETURN_KEY, strlen(HICHAIN_RETURN_KEY) }; + int32_t res = params->baseParams.loader->computeHkdf(&(params->baseParams.sessionKey), &(params->baseParams.salt), + &keyInfo, &(params->returnKey), false); + if (res != HC_SUCCESS) { + LOGE("generate returnKey failed"); + FreeAndCleanKey(&(params->baseParams.sessionKey)); + FreeAndCleanKey(&(params->returnKey)); + return res; + } + return res; +} + +int32_t SendResultToSelf(PakeParams *params, CJson *out) +{ + int res = HC_SUCCESS; + CJson *sendToSelf = CreateJson(); + if (sendToSelf == NULL) { + return HC_ERR_ALLOC_MEMORY; + } + GOTO_ERR_AND_SET_RET(AddIntToJson(sendToSelf, FIELD_OPERATION_CODE, OP_BIND), res); + GOTO_ERR_AND_SET_RET(AddIntToJson(sendToSelf, FIELD_AUTH_FORM, AUTH_FORM_ACCOUNT_UNRELATED), res); + + if (params->returnKey.length != 0) { /* keyLen == 0 means unbind, needn't to generate returnKey */ + res = GenerateOutputKey(params); + if (res != HC_SUCCESS) { + LOGE("GenerateOutputKey failed, res:%d", res); + goto err; + } + GOTO_ERR_AND_SET_RET(AddByteToJson(sendToSelf, FIELD_SESSION_KEY, params->returnKey.val, + params->returnKey.length), res); + } + + GOTO_ERR_AND_SET_RET(AddObjToJson(out, FIELD_SEND_TO_SELF, sendToSelf), res); +err: + FreeAndCleanKey(&(params->baseParams.sessionKey)); + FreeAndCleanKey(&(params->returnKey)); + FreeJson(sendToSelf); + return res; +} + +static int32_t FillPskWithPin(PakeParams *params, const CJson *in) +{ + const char *pinString = GetStringFromJson(in, FIELD_PIN_CODE); + if (pinString == NULL) { + LOGE("Get pin code failed."); + return HC_ERR_JSON_GET; + } + if (strlen(pinString) < MIN_PIN_LEN || strlen(pinString) > MAX_PIN_LEN) { + LOGE("Pin code is too short."); + return HC_ERR_INVALID_LEN; + } + + int res = InitSingleParam(&(params->baseParams.psk), strlen(pinString)); + if (res != HC_SUCCESS) { + LOGE("InitSingleParam for psk failed, res: %d.", res); + return res; + } + if (memcpy_s(params->baseParams.psk.val, params->baseParams.psk.length, + pinString, strlen(pinString)) != HC_SUCCESS) { + LOGE("Memcpy for pin code failed."); + FreeAndCleanKey(¶ms->baseParams.psk); + return HC_ERR_MEMORY_COPY; + } + + return HC_SUCCESS; +} + +static void UpperToLowercase(Uint8Buff *hex) +{ + for (uint32_t i = 0; i < hex->length; i++) { + if (hex->val[i] >= 'A' && hex->val[i] <= 'F') { + hex->val[i] += ASCII_CASE_DIFFERENCE_VALUE; + } + } +} + +static int32_t ConvertPsk(const Uint8Buff *srcPsk, PakeParams *params) +{ + int res; + res = InitSingleParam(&(params->baseParams.psk), PAKE_PSK_LEN * BYTE_TO_HEX_OPER_LENGTH + 1); + if (res != HC_SUCCESS) { + LOGE("InitSingleParam for psk failed, res: %d.", res); + return res; + } + /* For compatibility, to be same with HiChain 2.0 */ + res = ByteToHexString(srcPsk->val, srcPsk->length, (char *)params->baseParams.psk.val, + params->baseParams.psk.length); + if (res != HC_SUCCESS) { + LOGE("Convert psk from byte to hex string failed, res: %d.", res); + return res; + } + params->baseParams.psk.length = params->baseParams.psk.length - 1; // do not need include '\0' when using psk + (void)UpperToLowercase(&(params->baseParams.psk)); + return res; +} + +int32_t FillPskWithDerivedKey(PakeParams *params) +{ + int32_t res; + if (!(params->baseParams.isClient)) { + res = params->baseParams.loader->generateRandom(&(params->nonce)); + if (res != HC_SUCCESS) { + LOGE("Generate nonce failed, res: %d.", res); + return res; + } + } + uint8_t pskKeyAliasVal[PAKE_KEY_ALIAS_LEN] = { 0 }; + Uint8Buff pskKeyAlias = { pskKeyAliasVal, PAKE_KEY_ALIAS_LEN }; + Uint8Buff packageName = { (uint8_t *)params->packageName, strlen(params->packageName) }; + Uint8Buff serviceType = { (uint8_t *)params->serviceType, strlen(params->serviceType) }; + res = GenerateKeyAlias(&packageName, &serviceType, KEY_ALIAS_PSK, &(params->baseParams.idPeer), &pskKeyAlias); + if (res != HC_SUCCESS) { + LOGE("GenerateKeyAlias for psk failed, res: %d.", res); + return res; + } + + if (params->baseParams.loader->checkKeyExist(&pskKeyAlias) != HC_SUCCESS) { + res = GetAsyTokenManagerInstance()->computeAndSavePsk(params); + if (res != HC_SUCCESS) { + LOGE("ComputeAndSavePsk failed, res: %d.", res); + return res; + } + } + + Uint8Buff pskByte = { NULL, PAKE_PSK_LEN }; + pskByte.val = (uint8_t *)HcMalloc(PAKE_PSK_LEN, 0); + if (pskByte.val == NULL) { + LOGE("Malloc for pskByte failed."); + return HC_ERR_ALLOC_MEMORY; + } + Uint8Buff keyInfo = { (uint8_t *)TMP_AUTH_KEY_FACTOR, strlen(TMP_AUTH_KEY_FACTOR) }; + res = params->baseParams.loader->computeHkdf(&pskKeyAlias, &(params->nonce), &keyInfo, &pskByte, true); + if (res != HC_SUCCESS) { + LOGE("ComputeHkdf for psk failed, res: %d.", res); + goto err; + } + + res = ConvertPsk(&pskByte, params); + if (res != HC_SUCCESS) { + LOGE("ConvertPsk failed, res: %d.", res); + goto err; + } + goto out; +err: + FreeAndCleanKey(&(params->baseParams.psk)); +out: + FreeAndCleanKey(&pskByte); + return res; +} + +static int32_t FillAuthId(PakeParams *params, const CJson *in) +{ + const char *authId = GetStringFromJson(in, FIELD_SELF_AUTH_ID); + if (authId == NULL) { + LOGE("Get self authId failed."); + return HC_ERR_JSON_GET; + } + uint32_t authIdLen = strlen(authId); + if (authIdLen == 0 || authIdLen > MAX_AUTH_ID_LEN) { + LOGE("Invalid self authId length."); + return HC_ERR_INVALID_LEN; + } + params->baseParams.idSelf.length = authIdLen; + params->baseParams.idSelf.val = (uint8_t *)HcMalloc(params->baseParams.idSelf.length, 0); + if (params->baseParams.idSelf.val == NULL) { + LOGE("Malloc for idSelf failed."); + return HC_ERR_ALLOC_MEMORY; + } + if (memcpy_s(params->baseParams.idSelf.val, params->baseParams.idSelf.length, authId, strlen(authId)) != EOK) { + LOGE("Memcpy for idSelf failed."); + return HC_ERR_MEMORY_COPY; + } + + if (params->opCode == AUTHENTICATE || params->opCode == OP_UNBIND) { + authId = GetStringFromJson(in, FIELD_PEER_AUTH_ID); + if (authId == NULL) { + LOGE("Get peer authId failed."); + return HC_ERR_JSON_GET; + } + authIdLen = strlen(authId); + if (authIdLen == 0 || authIdLen > MAX_AUTH_ID_LEN) { + LOGE("Invalid peer authId length."); + return HC_ERR_INVALID_LEN; + } + params->baseParams.idPeer.length = authIdLen; + params->baseParams.idPeer.val = (uint8_t *)HcMalloc(params->baseParams.idPeer.length, 0); + if (params->baseParams.idPeer.val == NULL) { + LOGE("Malloc for idPeer failed."); + return HC_ERR_ALLOC_MEMORY; + } + if (memcpy_s(params->baseParams.idPeer.val, params->baseParams.idPeer.length, authId, strlen(authId)) != EOK) { + LOGE("Memcpy for idPeer failed."); + return HC_ERR_MEMORY_COPY; + } + } + + return HC_SUCCESS; +} + +static int32_t FillUserType(PakeParams *params, const CJson *in) +{ + int32_t res = GetIntFromJson(in, FIELD_SELF_TYPE, &(params->userType)); + if (res != HC_SUCCESS) { + LOGE("Get userType failed: %d", res); + return res; + } + + res = GetIntFromJson(in, FIELD_PEER_USER_TYPE, &(params->userTypePeer)); + if (res != HC_SUCCESS) { + LOGD("Get peer userType failed, use default, res: %d", res); + params->userTypePeer = DEVICE_TYPE_ACCESSORY; + } + return HC_SUCCESS; +} + +static int32_t FillPkgNameAndServiceType(PakeParams *params, const CJson *in) +{ + const char *packageName = GetStringFromJson(in, FIELD_PKG_NAME); + if (packageName == NULL) { + LOGE("Get packageName failed."); + return HC_ERR_JSON_GET; + } + params->packageName = (char *)HcMalloc(strlen(packageName) + 1, 0); + if (params->packageName == NULL) { + LOGE("Malloc for packageName failed."); + return HC_ERR_ALLOC_MEMORY; + } + if (memcpy_s(params->packageName, strlen(packageName) + 1, packageName, strlen(packageName)) != EOK) { + LOGE("Memcpy for packageName failed."); + return HC_ERR_MEMORY_COPY; + } + + const char *serviceType = GetStringFromJson(in, FIELD_SERVICE_TYPE); + if (serviceType == NULL) { + LOGE("Get serviceType failed."); + return HC_ERR_JSON_GET; + } + params->serviceType = (char *)HcMalloc(strlen(serviceType) + 1, 0); + if (params->serviceType == NULL) { + LOGE("Malloc for serviceType failed."); + return HC_ERR_ALLOC_MEMORY; + } + if (memcpy_s(params->serviceType, strlen(serviceType) + 1, serviceType, strlen(serviceType)) != EOK) { + LOGE("Memcpy for serviceType failed."); + return HC_ERR_MEMORY_COPY; + } + + return HC_SUCCESS; +} + +static int32_t FillNonce(PakeParams *params, const CJson *in) +{ + if (params->opCode == AUTHENTICATE || params->opCode == OP_UNBIND) { + params->nonce.length = PAKE_NONCE_LEN; + params->nonce.val = (uint8_t *)HcMalloc(params->nonce.length, 0); + if (params->nonce.val == NULL) { + LOGE("Malloc for nonce failed."); + return HC_ERR_ALLOC_MEMORY; + } + } else { + params->nonce.length = 0; + params->nonce.val = NULL; + } + return HC_SUCCESS; +} + +int32_t FillDasPakeParams(PakeParams *params, const CJson *in) +{ + int32_t res = GetIntFromJson(in, FIELD_OPERATION_CODE, &(params->opCode)); + if (res != HC_SUCCESS) { + LOGD("Get opCode failed, use default, res: %d", res); + params->opCode = AUTHENTICATE; + } + + res = GetBoolFromJson(in, FIELD_IS_CLIENT, &(params->baseParams.isClient)); + if (res != HC_SUCCESS) { + LOGE("Get isClient failed, res: %d.", res); + return res; + } + + res = FillNonce(params, in); + if (res != HC_SUCCESS) { + return res; + } + + res = FillUserType(params, in); + if (res != HC_SUCCESS) { + return res; + } + + res = FillPkgNameAndServiceType(params, in); + if (res != HC_SUCCESS) { + return res; + } + + res = FillAuthId(params, in); + if (res != HC_SUCCESS) { + return res; + } + + if (params->opCode == OP_BIND) { + res = FillPskWithPin(params, in); + if (res != HC_SUCCESS) { + return res; + } + } + + params->baseParams.curveType = CURVE_25519; + return HC_SUCCESS; +} diff --git a/services/module/src/das_module/pake_task/pake_task_mock/pake_task_main_mock.c b/services/module/src/das_module/pake_task/pake_task_mock/pake_task_main_mock.c new file mode 100644 index 0000000..8c719ae --- /dev/null +++ b/services/module/src/das_module/pake_task/pake_task_mock/pake_task_main_mock.c @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "pake_task_main.h" + +bool IsSupportPake() +{ + return false; +} + +SubTaskBase *CreatePakeSubTask(const CJson *in, CJson *out) +{ + (void)in; + (void)out; + return NULL; +} diff --git a/services/module/src/das_module/pake_task/standard_exchange_task/common_standard_bind_exchange.c b/services/module/src/das_module/pake_task/standard_exchange_task/common_standard_bind_exchange.c new file mode 100644 index 0000000..cc832e1 --- /dev/null +++ b/services/module/src/das_module/pake_task/standard_exchange_task/common_standard_bind_exchange.c @@ -0,0 +1,533 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "common_standard_bind_exchange.h" +#include "alg_defs.h" +#include "common_util.h" +#include "das_asy_token_manager.h" +#include "das_common.h" +#include "hc_log.h" +#include "hc_types.h" +#include "module_common.h" +#include "securec.h" + +int32_t InitStandardBindExchangeParams(StandardBindExchangeParams *params) +{ + int32_t res; + if (params == NULL) { + return HC_ERR_INVALID_PARAMS; + } + + params->pubKeyPeer.length = PAKE_ED25519_KEY_PAIR_LEN; + params->pubKeyPeer.val = (uint8_t *)HcMalloc(params->pubKeyPeer.length, 0); + if (params->pubKeyPeer.val == NULL) { + res = HC_ERR_ALLOC_MEMORY; + goto err; + } + + params->pubKeySelf.length = PAKE_ED25519_KEY_PAIR_LEN; + params->pubKeySelf.val = (uint8_t *)HcMalloc(params->pubKeySelf.length, 0); + if (params->pubKeySelf.val == NULL) { + res = HC_ERR_ALLOC_MEMORY; + goto err; + } + + params->nonce.length = STANDARD_BIND_EXCHANGE_NONCE_LEN; + params->nonce.val = (uint8_t *)HcMalloc(params->nonce.length, 0); + if (params->nonce.val == NULL) { + res = HC_ERR_ALLOC_MEMORY; + goto err; + } + + params->authInfo.length = 0; + params->authInfo.val = NULL; + params->exInfoCipher.length = 0; + params->exInfoCipher.val = NULL; + + return HC_SUCCESS; +err: + DestroyStandardBindExchangeParams(params); + return res; +} + +void DestroyStandardBindExchangeParams(StandardBindExchangeParams *params) +{ + if (params == NULL) { + return; + } + if (params->pubKeySelf.val != NULL) { + HcFree(params->pubKeySelf.val); + params->pubKeySelf.val = NULL; + } + if (params->pubKeyPeer.val != NULL) { + HcFree(params->pubKeyPeer.val); + params->pubKeyPeer.val = NULL; + } + if (params->authInfo.val != NULL) { + HcFree(params->authInfo.val); + params->authInfo.val = NULL; + } + if (params->exInfoCipher.val != NULL) { + HcFree(params->exInfoCipher.val); + params->exInfoCipher.val = NULL; + } + if (params->nonce.val != NULL) { + HcFree(params->nonce.val); + params->nonce.val = NULL; + } +} + +static int32_t PackageAuthInfo(const PakeParams *pakeParams, StandardBindExchangeParams *exchangeParams, + const Uint8Buff *keyAlias) +{ + int32_t res = pakeParams->baseParams.loader->checkKeyExist(keyAlias); + if (res != HC_SUCCESS) { + Algorithm alg = (pakeParams->baseParams.curveType == CURVE_256) ? P256 : ED25519; + /* UserType and pairType are not required when generating key. */ + ExtraInfo exInfo = { pakeParams->baseParams.idSelf, -1, -1 }; + res = pakeParams->baseParams.loader->generateKeyPairWithStorage(keyAlias, PAKE_ED25519_KEY_PAIR_LEN, alg, + &exInfo); + if (res != HC_SUCCESS) { + LOGE("generate self auth keyPair failed."); + return res; + } + } + + res = pakeParams->baseParams.loader->exportPublicKey(keyAlias, &(exchangeParams->pubKeySelf)); + if (res != HC_SUCCESS) { + LOGE("exportPublicKey failed"); + return res; + } + + CJson *authInfoJson = CreateJson(); + char *authInfoStr = NULL; + GOTO_ERR_AND_SET_RET(AddByteToJson(authInfoJson, FIELD_AUTH_ID, pakeParams->baseParams.idSelf.val, + pakeParams->baseParams.idSelf.length), res); + GOTO_ERR_AND_SET_RET(AddByteToJson(authInfoJson, FIELD_AUTH_PK, exchangeParams->pubKeySelf.val, + exchangeParams->pubKeySelf.length), res); + authInfoStr = PackJsonToString(authInfoJson); + if (authInfoStr == NULL) { + LOGE("authInfoStr PackJsonToString failed"); + res = HC_ERR_PACKAGE_JSON_TO_STRING_FAIL; + goto err; + } + + res = InitSingleParam(&(exchangeParams->authInfo), strlen(authInfoStr)); + if (res != HC_SUCCESS) { + LOGE("InitSingleParam for authInfo failed."); + goto err; + } + + if (memcpy_s(exchangeParams->authInfo.val, exchangeParams->authInfo.length, + authInfoStr, strlen(authInfoStr)) != EOK) { + LOGE("Memcpy authInfo failed."); + res = HC_ERR_MEMORY_COPY; + goto err; + } +err: + FreeJson(authInfoJson); + FreeJsonString(authInfoStr); + return res; +} + +static int32_t GenerateSignInfo(const PakeParams *pakeParams, const StandardBindExchangeParams *exchangeParams, + const Uint8Buff *keyAlias, Uint8Buff *signInfo) +{ + // add challenge + int32_t res = HC_SUCCESS; + uint32_t msgInfoLen = pakeParams->baseParams.challengeSelf.length + pakeParams->baseParams.challengePeer.length + + exchangeParams->authInfo.length; + uint8_t *msgInfoVal = (uint8_t *)HcMalloc(msgInfoLen, 0); + if (msgInfoVal == NULL) { + LOGE("Malloc msgInfoVal failed."); + return HC_ERR_ALLOC_MEMORY; + } + Uint8Buff msgInfo = { msgInfoVal, msgInfoLen }; + if (memcpy_s(msgInfo.val, msgInfo.length, pakeParams->baseParams.challengeSelf.val, + pakeParams->baseParams.challengeSelf.length) != EOK) { + LOGE("Memcpy for challengeSelf failed."); + res = HC_ERR_MEMORY_COPY; + goto err; + } + uint32_t usedLen = pakeParams->baseParams.challengeSelf.length; + + if (memcpy_s(msgInfo.val + usedLen, msgInfo.length - usedLen, pakeParams->baseParams.challengePeer.val, + pakeParams->baseParams.challengePeer.length) != EOK) { + LOGE("Memcpy for challengePeer failed."); + res = HC_ERR_MEMORY_COPY; + goto err; + } + usedLen += pakeParams->baseParams.challengePeer.length; + + if (memcpy_s(msgInfo.val + usedLen, msgInfo.length - usedLen, exchangeParams->authInfo.val, + exchangeParams->authInfo.length) != EOK) { + LOGE("Memcpy for authInfo failed."); + res = HC_ERR_MEMORY_COPY; + goto err; + } + + Algorithm alg = (pakeParams->baseParams.curveType == CURVE_256) ? P256 : ED25519; + res = pakeParams->baseParams.loader->sign(keyAlias, &msgInfo, alg, signInfo, true); + if (res != HC_SUCCESS) { + LOGE("sign failed"); + goto err; + } +err: + HcFree(msgInfo.val); + return res; +} + +static int32_t EncryptAuthAndSignInfo(const PakeParams *pakeParams, StandardBindExchangeParams *exchangeParams, + const Uint8Buff *signInfo, const char *aad) +{ + // contact auth and sign info + int32_t res = HC_SUCCESS; + uint32_t exchangeInfoLen = exchangeParams->authInfo.length + signInfo->length; + uint8_t *exchangeInfoVal = (uint8_t *)HcMalloc(exchangeInfoLen, 0); + if (exchangeInfoVal == NULL) { + LOGE("Malloc exchangeInfoVal failed."); + return HC_ERR_ALLOC_MEMORY; + } + Uint8Buff exchangeInfo = { exchangeInfoVal, exchangeInfoLen }; + if (memcpy_s(exchangeInfo.val, exchangeInfo.length, exchangeParams->authInfo.val, + exchangeParams->authInfo.length) != EOK) { + res = HC_ERR_MEMORY_COPY; + goto err; + } + if (memcpy_s(exchangeInfo.val + exchangeParams->authInfo.length, + exchangeInfo.length - exchangeParams->authInfo.length, signInfo->val, signInfo->length) != EOK) { + res = HC_ERR_MEMORY_COPY; + goto err; + } + + res = InitSingleParam(&(exchangeParams->exInfoCipher), exchangeInfo.length + AE_TAG_LEN); + if (res != HC_SUCCESS) { + LOGE("InitSingleParam for failed."); + goto err; + } + + // encrypt + res = pakeParams->baseParams.loader->generateRandom(&(exchangeParams->nonce)); + if (res != HC_SUCCESS) { + LOGE("generateRandom failed"); + goto err; + } + + GcmParam encryptInfo = { + .aad = (uint8_t *)aad, + .aadLen = strlen(aad), + .nonce = exchangeParams->nonce.val, + .nonceLen = exchangeParams->nonce.length + }; + res = pakeParams->baseParams.loader->aesGcmEncrypt(&(pakeParams->baseParams.sessionKey), &exchangeInfo, + &encryptInfo, false, &(exchangeParams->exInfoCipher)); + if (res != HC_SUCCESS) { + LOGE("aesGcmEncrypt failed"); + goto err; + } + +err: + HcFree(exchangeInfo.val); + return res; +} + +static int32_t DecryptAuthAndSignInfo(const PakeParams *pakeParams, StandardBindExchangeParams *exchangeParams, + Uint8Buff *signInfo, const char *aad) +{ + uint32_t exchangeInfoLen = exchangeParams->exInfoCipher.length - AE_TAG_LEN; + uint8_t *exchangeInfoVal = (uint8_t *)HcMalloc(exchangeInfoLen, 0); + if (exchangeInfoVal == NULL) { + LOGE("Malloc exchangeInfoVal failed."); + return HC_ERR_ALLOC_MEMORY; + } + Uint8Buff exchangeInfo = { exchangeInfoVal, exchangeInfoLen }; + + GcmParam decryptInfo = { + .aad = (uint8_t *)aad, + .aadLen = strlen(aad), + .nonce = exchangeParams->nonce.val, + .nonceLen = exchangeParams->nonce.length + }; + + int32_t res = pakeParams->baseParams.loader->aesGcmDecrypt(&(pakeParams->baseParams.sessionKey), + &(exchangeParams->exInfoCipher), &decryptInfo, false, &exchangeInfo); + if (res != HC_SUCCESS) { + LOGE("aesGcmDecrypt failed"); + goto err; + } + + // get authInfo + res = InitSingleParam(&(exchangeParams->authInfo), exchangeInfo.length - SIGNATURE_LEN); + if (res != HC_SUCCESS) { + LOGE("InitSingleParam for authInfo failed."); + goto err; + } + + if (memcpy_s(exchangeParams->authInfo.val, exchangeParams->authInfo.length, exchangeInfo.val, + exchangeParams->authInfo.length) != EOK) { + LOGE("memcpy authInfo failed."); + res = HC_ERR_MEMORY_COPY; + goto err; + } + if (memcpy_s(signInfo->val, signInfo->length, exchangeInfo.val + exchangeParams->authInfo.length, + SIGNATURE_LEN) != EOK) { + LOGE("memcpy signInfo failed."); + res = HC_ERR_MEMORY_COPY; + goto err; + } +err: + HcFree(exchangeInfo.val); + return res; +} + +static int32_t ParseAuthInfo(PakeParams *pakeParams, const StandardBindExchangeParams *exchangeParams) +{ + int32_t res = HC_SUCCESS; + CJson *authInfoJson = CreateJsonFromString((char *)exchangeParams->authInfo.val); + if (authInfoJson == NULL) { + LOGE("create authInfoJson failed"); + res = HC_ERROR; + goto err; + } + + GOTO_ERR_AND_SET_RET(GetByteFromJson(authInfoJson, FIELD_AUTH_PK, exchangeParams->pubKeyPeer.val, + exchangeParams->pubKeyPeer.length), res); + const char *authId = GetStringFromJson(authInfoJson, FIELD_AUTH_ID); + if (authId == NULL) { + LOGE("get authId failed"); + res = HC_ERROR; + goto err; + } + res = InitSingleParam(&pakeParams->baseParams.idPeer, strlen(authId) / BYTE_TO_HEX_OPER_LENGTH); + if (res != HC_SUCCESS) { + LOGE("InitSingleParam for idPeer failed."); + goto err; + } + res = HexStringToByte(authId, pakeParams->baseParams.idPeer.val, pakeParams->baseParams.idPeer.length); + if (res != HC_SUCCESS) { + LOGE("Convert idPeer from hex string to byte failed."); + goto err; + } +err: + FreeJson(authInfoJson); + return res; +} + +static int32_t VerifySignInfo(const PakeParams *pakeParams, StandardBindExchangeParams *exchangeParams, + Uint8Buff *signInfo) +{ + int32_t res = HC_SUCCESS; + uint32_t verifyMsgLen = exchangeParams->authInfo.length + pakeParams->baseParams.challengePeer.length + + pakeParams->baseParams.challengeSelf.length; + uint8_t *verifyMsgVal = (uint8_t *)HcMalloc(verifyMsgLen, 0); + if (verifyMsgVal == NULL) { + LOGE("Malloc verifyMsgVal failed."); + return HC_ERR_ALLOC_MEMORY; + } + Uint8Buff verifyMsg = { verifyMsgVal, verifyMsgLen }; + if (memcpy_s(verifyMsg.val, verifyMsg.length, pakeParams->baseParams.challengePeer.val, + pakeParams->baseParams.challengePeer.length) != EOK) { + res = HC_ERR_MEMORY_COPY; + goto err; + } + uint32_t usedLen = pakeParams->baseParams.challengePeer.length; + if (memcpy_s(verifyMsg.val + usedLen, verifyMsg.length - usedLen, pakeParams->baseParams.challengeSelf.val, + pakeParams->baseParams.challengeSelf.length) != EOK) { + res = HC_ERR_MEMORY_COPY; + goto err; + } + usedLen += pakeParams->baseParams.challengeSelf.length; + if (memcpy_s(verifyMsg.val + usedLen, verifyMsg.length - usedLen, exchangeParams->authInfo.val, + exchangeParams->authInfo.length) != EOK) { + res = HC_ERR_MEMORY_COPY; + goto err; + } + + Algorithm alg = (pakeParams->baseParams.curveType == CURVE_256) ? P256 : ED25519; + res = pakeParams->baseParams.loader->verify(&(exchangeParams->pubKeyPeer), &verifyMsg, alg, signInfo, false); + if (res != HC_SUCCESS) { + LOGE("verify failed"); + goto err; + } +err: + HcFree(verifyMsg.val); + return res; +} + +static int32_t SaveAuthInfo(const PakeParams *pakeParams, const StandardBindExchangeParams *exchangeParams) +{ + uint8_t keyAliasPeerVal[PAKE_KEY_ALIAS_LEN] = { 0 }; + Uint8Buff keyAliasPeer = { keyAliasPeerVal, PAKE_KEY_ALIAS_LEN }; + KeyAliasType keyType = pakeParams->userTypePeer; + Uint8Buff packageName = { (uint8_t *)pakeParams->packageName, strlen(pakeParams->packageName) }; + Uint8Buff serviceType = { (uint8_t *)pakeParams->serviceType, strlen(pakeParams->serviceType) }; + int32_t res = GenerateKeyAlias(&packageName, &serviceType, keyType, &(pakeParams->baseParams.idPeer), + &keyAliasPeer); + if (res != HC_SUCCESS) { + LOGE("generateKeyAlias failed"); + return res; + } + Algorithm alg = (pakeParams->baseParams.curveType == CURVE_256) ? P256 : ED25519; + ExtraInfo exInfo = { pakeParams->baseParams.idPeer, pakeParams->userType, PAIR_TYPE_BIND }; + res = pakeParams->baseParams.loader->importPublicKey(&keyAliasPeer, &(exchangeParams->pubKeyPeer), alg, &exInfo); + if (res != HC_SUCCESS) { + LOGE("importPublicKey failed"); + return res; + } + res = GetAsyTokenManagerInstance()->computeAndSavePsk(pakeParams); + if (res != HC_SUCCESS) { + LOGE("ComputeAndSavePsk failed"); + } + LOGI("Save pubKey and psk success."); + return res; +} + +int32_t ClientRequestStandardBindExchange(const PakeParams *pakeParams, StandardBindExchangeParams *exchangeParams) +{ + uint8_t keyAliasVal[PAKE_KEY_ALIAS_LEN] = { 0 }; + Uint8Buff keyAlias = { keyAliasVal, PAKE_KEY_ALIAS_LEN }; + KeyAliasType keyType = pakeParams->userType; + Uint8Buff packageName = { (uint8_t *)pakeParams->packageName, strlen(pakeParams->packageName) }; + Uint8Buff serviceType = { (uint8_t *)pakeParams->serviceType, strlen(pakeParams->serviceType) }; + int32_t res = GenerateKeyAlias(&packageName, &serviceType, keyType, &(pakeParams->baseParams.idSelf), &keyAlias); + if (res != HC_SUCCESS) { + LOGE("generateKeyAlias failed"); + return res; + } + + res = PackageAuthInfo(pakeParams, exchangeParams, &keyAlias); + if (res != HC_SUCCESS) { + LOGE("PackageAuthInfo failed"); + return res; + } + + uint8_t signInfoVal[SIGNATURE_LEN] = { 0 }; + Uint8Buff signInfo = { signInfoVal, SIGNATURE_LEN }; + res = GenerateSignInfo(pakeParams, exchangeParams, &keyAlias, &signInfo); + if (res != HC_SUCCESS) { + LOGE("GenerateSignInfo failed"); + return res; + } + + res = EncryptAuthAndSignInfo(pakeParams, exchangeParams, &signInfo, HICHAIN_EXCHANGE_REQUEST); + if (res != HC_SUCCESS) { + LOGE("EncryptAuthAndSignInfo failed"); + return res; + } + + return res; +} + +int32_t ServerResponseStandardBindExchange(PakeParams *pakeParams, StandardBindExchangeParams *exchangeParams) +{ + uint8_t keyAliasVal[PAKE_KEY_ALIAS_LEN] = { 0 }; + Uint8Buff keyAlias = { keyAliasVal, PAKE_KEY_ALIAS_LEN }; + KeyAliasType keyType = pakeParams->userType; + Uint8Buff packageName = { (uint8_t *)pakeParams->packageName, strlen(pakeParams->packageName) }; + Uint8Buff serviceType = { (uint8_t *)pakeParams->serviceType, strlen(pakeParams->serviceType) }; + int32_t res = GenerateKeyAlias(&packageName, &serviceType, keyType, &(pakeParams->baseParams.idSelf), &keyAlias); + if (res != HC_SUCCESS) { + LOGE("generateKeyAlias failed"); + return res; + } + + uint8_t signInfoVal[SIGNATURE_LEN] = { 0 }; + Uint8Buff signInfo = { signInfoVal, SIGNATURE_LEN }; + res = DecryptAuthAndSignInfo(pakeParams, exchangeParams, &signInfo, HICHAIN_EXCHANGE_REQUEST); + if (res != HC_SUCCESS) { + LOGE("DecryptAuthAndSignInfo failed"); + return res; + } + + res = ParseAuthInfo(pakeParams, exchangeParams); + if (res != HC_SUCCESS) { + LOGE("ParseAuthInfo failed"); + return res; + } + + res = VerifySignInfo(pakeParams, exchangeParams, &signInfo); + if (res != HC_SUCCESS) { + LOGE("VerifySignInfo failed"); + return res; + } + + res = SaveAuthInfo(pakeParams, exchangeParams); + if (res != HC_SUCCESS) { + LOGE("SaveAuthInfo failed"); + return res; + } + + res = PackageAuthInfo(pakeParams, exchangeParams, &keyAlias); + if (res != HC_SUCCESS) { + LOGE("PackageAuthInfo failed"); + return res; + } + + res = GenerateSignInfo(pakeParams, exchangeParams, &keyAlias, &signInfo); + if (res != HC_SUCCESS) { + LOGE("GenerateSignInfo failed"); + return res; + } + + res = EncryptAuthAndSignInfo(pakeParams, exchangeParams, &signInfo, HICHAIN_EXCHANGE_RESPONSE); + if (res != HC_SUCCESS) { + LOGE("EncryptAuthAndSignInfo failed"); + return res; + } + + return HC_SUCCESS; +} + +int32_t ClientConfirmStandardBindExchange(PakeParams *pakeParams, StandardBindExchangeParams *exchangeParams) +{ + uint8_t keyAliasVal[PAKE_KEY_ALIAS_LEN] = { 0 }; + Uint8Buff keyAlias = { keyAliasVal, PAKE_KEY_ALIAS_LEN }; + KeyAliasType keyType = pakeParams->userType; + Uint8Buff packageName = { (uint8_t *)pakeParams->packageName, strlen(pakeParams->packageName) }; + Uint8Buff serviceType = { (uint8_t *)pakeParams->serviceType, strlen(pakeParams->serviceType) }; + int32_t res = GenerateKeyAlias(&packageName, &serviceType, keyType, &(pakeParams->baseParams.idSelf), &keyAlias); + if (res != HC_SUCCESS) { + LOGE("generateKeyAlias failed"); + return res; + } + + uint8_t signInfoVal[SIGNATURE_LEN] = { 0 }; + Uint8Buff signInfo = { signInfoVal, SIGNATURE_LEN }; + res = DecryptAuthAndSignInfo(pakeParams, exchangeParams, &signInfo, HICHAIN_EXCHANGE_RESPONSE); + if (res != HC_SUCCESS) { + LOGE("DecryptAuthAndSignInfo failed"); + return res; + } + + res = ParseAuthInfo(pakeParams, exchangeParams); + if (res != HC_SUCCESS) { + LOGE("ParseAuthInfo failed"); + return res; + } + + res = VerifySignInfo(pakeParams, exchangeParams, &signInfo); + if (res != HC_SUCCESS) { + LOGE("VerifySignInfo failed"); + return res; + } + + res = SaveAuthInfo(pakeParams, exchangeParams); + if (res != HC_SUCCESS) { + LOGE("SaveAuthInfo failed"); + return res; + } + + return HC_SUCCESS; +} \ No newline at end of file diff --git a/services/module/src/das_module/pake_task/standard_exchange_task/common_standard_unbind_exchange.c b/services/module/src/das_module/pake_task/standard_exchange_task/common_standard_unbind_exchange.c new file mode 100644 index 0000000..90c71c2 --- /dev/null +++ b/services/module/src/das_module/pake_task/standard_exchange_task/common_standard_unbind_exchange.c @@ -0,0 +1,334 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "common_standard_unbind_exchange.h" +#include "das_common.h" +#include "hc_log.h" +#include "hc_types.h" +#include "module_common.h" +#include "securec.h" + +int32_t InitStandardUnbindExchangeParams(StandardUnbindExchangeParams *params) +{ + if (params == NULL) { + return HC_ERR_INVALID_PARAMS; + } + + int32_t res; + + params->nonce.length = STANDARD_UNBIND_EXCHANGE_NONCE_LEN; + params->nonce.val = (uint8_t *)HcMalloc(params->nonce.length, 0); + if (params->nonce.val == NULL) { + res = HC_ERR_ALLOC_MEMORY; + goto err; + } + + params->rmvInfo.length = 0; + params->rmvInfo.val = NULL; + params->exRmvCipher.length = 0; + params->exRmvCipher.val = NULL; + params->resultCipher.length = 0; + params->resultCipher.val = NULL; + + return HC_SUCCESS; +err: + DestroyStandardUnbindExchangeParams(params); + return res; +} + +void DestroyStandardUnbindExchangeParams(StandardUnbindExchangeParams *params) +{ + if (params == NULL) { + return; + } + if (params->rmvInfo.val != NULL) { + HcFree(params->rmvInfo.val); + params->rmvInfo.val = NULL; + } + if (params->exRmvCipher.val != NULL) { + HcFree(params->exRmvCipher.val); + params->exRmvCipher.val = NULL; + } + if (params->resultCipher.val != NULL) { + HcFree(params->resultCipher.val); + params->resultCipher.val = NULL; + } + if (params->nonce.val != NULL) { + HcFree(params->nonce.val); + params->nonce.val = NULL; + } +} + +static int32_t PackageRmvInfo(const PakeParams *pakeParams, StandardUnbindExchangeParams *exchangeParams) +{ + int32_t res = HC_SUCCESS; + CJson *rmvInfoJson = CreateJson(); + char *rmvInfoStr = NULL; + GOTO_ERR_AND_SET_RET(AddByteToJson(rmvInfoJson, FIELD_RMV_ID, pakeParams->baseParams.idSelf.val, + pakeParams->baseParams.idSelf.length), res); + GOTO_ERR_AND_SET_RET(AddIntToJson(rmvInfoJson, FIELD_RMV_TYPE, pakeParams->userType), res); + rmvInfoStr = PackJsonToString(rmvInfoJson); + if (rmvInfoStr == NULL) { + LOGE("rmvInfoStr PackJsonToString failed"); + res = HC_ERR_PACKAGE_JSON_TO_STRING_FAIL; + goto err; + } + + res = InitSingleParam(&exchangeParams->rmvInfo, strlen(rmvInfoStr)); + if (res != HC_SUCCESS) { + LOGE("InitSingleParam rmvInfo failed."); + goto err; + } + + if (memcpy_s(exchangeParams->rmvInfo.val, exchangeParams->rmvInfo.length, rmvInfoStr, strlen(rmvInfoStr)) != EOK) { + LOGE("Memcpy rmvInfo failed."); + res = HC_ERR_MEMORY_COPY; + goto err; + } +err: + FreeJson(rmvInfoJson); + FreeJsonString(rmvInfoStr); + return res; +} + +static int32_t EncryptRmvInfo(const PakeParams *pakeParams, StandardUnbindExchangeParams *exchangeParams) +{ + int32_t res = InitSingleParam(&(exchangeParams->exRmvCipher), exchangeParams->rmvInfo.length + AE_TAG_LEN); + if (res != HC_SUCCESS) { + LOGE("InitRmvInfoCipher failed"); + return res; + } + + // encrypt + res = pakeParams->baseParams.loader->generateRandom(&(exchangeParams->nonce)); + if (res != HC_SUCCESS) { + LOGE("generateRandom failed"); + return res; + } + + GcmParam encryptInfo = { + .aad = (uint8_t *)HICHAIN_REMOVE_INFO_REQUEST, + .aadLen = strlen(HICHAIN_REMOVE_INFO_REQUEST), + .nonce = exchangeParams->nonce.val, + .nonceLen = exchangeParams->nonce.length + }; + res = pakeParams->baseParams.loader->aesGcmEncrypt(&(pakeParams->baseParams.sessionKey), &(exchangeParams->rmvInfo), + &encryptInfo, false, &(exchangeParams->exRmvCipher)); + if (res != HC_SUCCESS) { + LOGE("aesGcmEncrypt failed"); + return res; + } + + return HC_SUCCESS; +} + +static int32_t DecryptRmvInfo(PakeParams *pakeParams, StandardUnbindExchangeParams *exchangeParams) +{ + int32_t res = InitSingleParam(&exchangeParams->rmvInfo, exchangeParams->exRmvCipher.length - AE_TAG_LEN); + if (res != HC_SUCCESS) { + LOGE("InitSingleParam rmvInfo failed."); + return res; + } + + GcmParam decryptInfo = { + .aad = (uint8_t *)HICHAIN_REMOVE_INFO_REQUEST, + .aadLen = strlen(HICHAIN_REMOVE_INFO_REQUEST), + .nonce = exchangeParams->nonce.val, + .nonceLen = exchangeParams->nonce.length + }; + + res = pakeParams->baseParams.loader->aesGcmDecrypt(&(pakeParams->baseParams.sessionKey), + &(exchangeParams->exRmvCipher), &decryptInfo, false, &(exchangeParams->rmvInfo)); + if (res != HC_SUCCESS) { + LOGE("aesGcmDecrypt failed"); + return res; + } + + return res; +} + +static int32_t ParseRmvInfo(PakeParams *pakeParams, StandardUnbindExchangeParams *exchangeParams) +{ + int32_t res; + CJson *rmvInfoJson = CreateJsonFromString((char *)exchangeParams->rmvInfo.val); + + GOTO_ERR_AND_SET_RET(GetIntFromJson(rmvInfoJson, FIELD_RMV_TYPE, &(pakeParams->userTypePeer)), res); + GOTO_ERR_AND_SET_RET(GetByteFromJson(rmvInfoJson, FIELD_RMV_ID, pakeParams->baseParams.idPeer.val, + pakeParams->baseParams.idPeer.length), res); +err: + FreeJson(rmvInfoJson); + return res; +} + +static int32_t DeleteAuthInfo(PakeParams *pakeParams) +{ + uint8_t keyAliasVal[PAKE_KEY_ALIAS_LEN] = { 0 }; + Uint8Buff keyAlias = { keyAliasVal, PAKE_KEY_ALIAS_LEN }; + KeyAliasType keyType = pakeParams->userTypePeer; + Uint8Buff packageName = { (uint8_t *)pakeParams->packageName, strlen(pakeParams->packageName) }; + Uint8Buff serviceType = { (uint8_t *)pakeParams->serviceType, strlen(pakeParams->serviceType) }; + int32_t res = GenerateKeyAlias(&packageName, &serviceType, keyType, &(pakeParams->baseParams.idPeer), &keyAlias); + if (res != HC_SUCCESS) { + LOGE("generate pubKey alias failed"); + return res; + } + res = pakeParams->baseParams.loader->deleteKey(&keyAlias); + if (res != HC_SUCCESS) { + LOGE("deleteKey failed"); + return res; + } + LOGI("delete peer pubKey success."); + (void)memset_s(keyAlias.val, keyAlias.length, 0, keyAlias.length); + res = GenerateKeyAlias(&packageName, &serviceType, KEY_ALIAS_PSK, &(pakeParams->baseParams.idPeer), + &keyAlias); + if (res != HC_SUCCESS) { + LOGE("generate pskKey alias failed"); + return res; + } + res = pakeParams->baseParams.loader->deleteKey(&keyAlias); + if (res != HC_SUCCESS) { + LOGE("delete pskKey failed"); + return res; + } + LOGI("delete pskKey success."); + return HC_SUCCESS; +} + +static int32_t BuildRmvResult(PakeParams *pakeParams, StandardUnbindExchangeParams *exchangeParams) +{ + uint8_t resultVal[sizeof(int32_t)] = { 0 }; + Uint8Buff result = { resultVal, sizeof(int32_t) }; + int32_t res = InitSingleParam(&(exchangeParams->resultCipher), result.length + AE_TAG_LEN); + if (res != HC_SUCCESS) { + LOGE("InitResultInfoCipher failed"); + return res; + } + + // encrypt + res = pakeParams->baseParams.loader->generateRandom(&(exchangeParams->nonce)); + if (res != HC_SUCCESS) { + LOGE("generateRandom failed"); + return res; + } + + GcmParam encryptInfo = { + .aad = (uint8_t *)HICHAIN_REMOVE_INFO_RESPONSE, + .aadLen = strlen(HICHAIN_REMOVE_INFO_RESPONSE), + .nonce = exchangeParams->nonce.val, + .nonceLen = exchangeParams->nonce.length + }; + + res = pakeParams->baseParams.loader->aesGcmEncrypt(&(pakeParams->baseParams.sessionKey), + &result, &encryptInfo, false, &(exchangeParams->resultCipher)); + if (res != HC_SUCCESS) { + LOGE("aesGcmEncrypt failed"); + return res; + } + + return HC_SUCCESS; +} + +static int32_t ConfirmRmvResult(PakeParams *pakeParams, StandardUnbindExchangeParams *exchangeParams) +{ + uint8_t resultVal[sizeof(int32_t)] = { 0 }; + Uint8Buff result = { resultVal, sizeof(int32_t) }; + + // decrypt + GcmParam decryptInfo = { + .aad = (uint8_t *)HICHAIN_REMOVE_INFO_RESPONSE, + .aadLen = strlen(HICHAIN_REMOVE_INFO_RESPONSE), + .nonce = exchangeParams->nonce.val, + .nonceLen = exchangeParams->nonce.length + }; + + int32_t res = pakeParams->baseParams.loader->aesGcmDecrypt(&(pakeParams->baseParams.sessionKey), + &(exchangeParams->resultCipher), &decryptInfo, false, &result); + if (res != HC_SUCCESS) { + LOGE("aesGcmDecrypt failed"); + return res; + } + + uint8_t resultSuccess[sizeof(int32_t)] = { 0 }; + if (memcmp(result.val, resultSuccess, sizeof(int32_t)) != 0) { + LOGE("RemoveAuthStartRequest failed, ret: %d", res); + int32_t *resultTmp = (int32_t *)result.val; + return *resultTmp; + } + + return HC_SUCCESS; +} + +int32_t ClientRequestStandardUnbindExchange(const PakeParams *pakeParams, StandardUnbindExchangeParams *exchangeParams) +{ + int32_t res = PackageRmvInfo(pakeParams, exchangeParams); + if (res != HC_SUCCESS) { + LOGE("PackageRmvInfo failed"); + return res; + } + + res = EncryptRmvInfo(pakeParams, exchangeParams); + if (res != HC_SUCCESS) { + LOGE("EncryptRmvInfo failed"); + return res; + } + + return res; +} + +int32_t ServerResponseStandardUnbindExchange(PakeParams *pakeParams, StandardUnbindExchangeParams *exchangeParams) +{ + int32_t res = DecryptRmvInfo(pakeParams, exchangeParams); + if (res != HC_SUCCESS) { + LOGE("DecryptRmvInfo failed"); + return res; + } + + res = ParseRmvInfo(pakeParams, exchangeParams); + if (res != HC_SUCCESS) { + LOGE("ParseRmvInfo failed"); + return res; + } + + res = DeleteAuthInfo(pakeParams); + if (res != HC_SUCCESS) { + LOGE("DeleteAuthInfo failed"); + return res; + } + + res = BuildRmvResult(pakeParams, exchangeParams); + if (res != HC_SUCCESS) { + LOGE("BuildRmvResult failed"); + return res; + } + + return HC_SUCCESS; +} + +int32_t ClientConfirmStandardUnbindExchange(PakeParams *pakeParams, StandardUnbindExchangeParams *exchangeParams) +{ + int32_t res = ConfirmRmvResult(pakeParams, exchangeParams); + if (res != HC_SUCCESS) { + LOGE("ConfirmRmvResult failed"); + return res; + } + + res = DeleteAuthInfo(pakeParams); + if (res != HC_SUCCESS) { + LOGE("DeleteAuthInfo failed"); + return res; + } + + return HC_SUCCESS; +} \ No newline at end of file diff --git a/services/module/src/das_module/pake_task/standard_exchange_task/das_asy_token_manager.c b/services/module/src/das_module/pake_task/standard_exchange_task/das_asy_token_manager.c new file mode 100644 index 0000000..ecbe7d4 --- /dev/null +++ b/services/module/src/das_module/pake_task/standard_exchange_task/das_asy_token_manager.c @@ -0,0 +1,173 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "das_asy_token_manager.h" +#include "alg_loader.h" +#include "das_common.h" +#include "hc_log.h" + +static int32_t RegisterLocalIdentity(const char *pkgName, const char *serviceType, Uint8Buff *authId, int userType) +{ + const AlgLoader *loader = GetLoaderInstance(); + Uint8Buff pkgNameBuff = { (uint8_t *)pkgName, strlen(pkgName)}; + Uint8Buff serviceTypeBuff = { (uint8_t *)serviceType, strlen(serviceType) }; + KeyAliasType keyType = userType; + uint8_t keyAliasVal[PAKE_KEY_ALIAS_LEN] = { 0 }; + Uint8Buff keyAliasBuff = { keyAliasVal, PAKE_KEY_ALIAS_LEN }; + int32_t res = GenerateKeyAlias(&pkgNameBuff, &serviceTypeBuff, keyType, authId, &keyAliasBuff); + if (res != HC_SUCCESS) { + LOGE("Failed to generate identity keyPair alias!"); + return res; + } + + res = loader->checkKeyExist(&keyAliasBuff); + if (res == HC_SUCCESS) { + LOGD("Key pair is exist."); + return HC_SUCCESS; + } + + ExtraInfo exInfo = { *authId, -1, -1 }; /* UserType and pairType are not required when generating key. */ + res = loader->generateKeyPairWithStorage(&keyAliasBuff, PAKE_ED25519_KEY_PAIR_LEN, ED25519, &exInfo); + if (res != HC_SUCCESS) { + LOGE("Failed to generate key pair!"); + return res; + } + LOGI("Key pair generated successfully!"); + return HC_SUCCESS; +} + +static int32_t UnregisterLocalIdentity(const char *pkgName, const char *serviceType, Uint8Buff *authId, int userType) +{ + const AlgLoader *loader = GetLoaderInstance(); + Uint8Buff pkgNameBuff = { (uint8_t *)pkgName, strlen(pkgName)}; + Uint8Buff serviceTypeBuff = { (uint8_t *)serviceType, strlen(serviceType) }; + KeyAliasType keyType = userType; + uint8_t pakeKeyAliasVal[PAKE_KEY_ALIAS_LEN] = { 0 }; + Uint8Buff pakeKeyAliasBuff = { pakeKeyAliasVal, PAKE_KEY_ALIAS_LEN }; + int32_t res = GenerateKeyAlias(&pkgNameBuff, &serviceTypeBuff, keyType, authId, &pakeKeyAliasBuff); + if (res != HC_SUCCESS) { + LOGE("Failed to generate identity keyPair alias!"); + return res; + } + res = loader->deleteKey(&pakeKeyAliasBuff); + if (res != HC_SUCCESS) { + LOGE("Failed to delete key pair!"); + return res; + } + LOGI("Key pair deleted successfully!"); + + return HC_SUCCESS; +} + +static int32_t DeletePeerAuthInfo(const char *pkgName, const char *serviceType, Uint8Buff *authIdPeer, int userTypePeer) +{ + const AlgLoader *loader = GetLoaderInstance(); + Uint8Buff pkgNameBuff = { (uint8_t *)pkgName, strlen(pkgName)}; + Uint8Buff serviceTypeBuff = { (uint8_t *)serviceType, strlen(serviceType) }; + KeyAliasType keyType = userTypePeer; + uint8_t pakeKeyAliasVal[PAKE_KEY_ALIAS_LEN] = { 0 }; + Uint8Buff pakeKeyAliasBuff = { pakeKeyAliasVal, PAKE_KEY_ALIAS_LEN }; + int32_t res = GenerateKeyAlias(&pkgNameBuff, &serviceTypeBuff, keyType, authIdPeer, &pakeKeyAliasBuff); + if (res != HC_SUCCESS) { + LOGE("Failed to generate identity keyPair alias!"); + return res; + } + res = loader->deleteKey(&pakeKeyAliasBuff); + if (res != HC_SUCCESS) { + LOGE("Failed to delete key pair!"); + return res; + } + LOGI("Key pair deleted successfully!"); + + (void)memset_s(pakeKeyAliasBuff.val, pakeKeyAliasBuff.length, 0, pakeKeyAliasBuff.length); + res = GenerateKeyAlias(&pkgNameBuff, &serviceTypeBuff, KEY_ALIAS_PSK, authIdPeer, &pakeKeyAliasBuff); + if (res != HC_SUCCESS) { + LOGE("Failed to generate psk alias!"); + return res; + } + res = loader->deleteKey(&pakeKeyAliasBuff); + if (res != HC_SUCCESS) { + LOGE("Failed to delete psk!"); + return res; + } + LOGI("Psk deleted successfully!"); + + return HC_SUCCESS; +} + +static int32_t ComputeAndSavePsk(const PakeParams *params) +{ + uint8_t selfKeyAliasVal[PAKE_KEY_ALIAS_LEN] = { 0 }; + Uint8Buff selfKeyAlias = { selfKeyAliasVal, PAKE_KEY_ALIAS_LEN }; + uint8_t peerKeyAliasVal[PAKE_KEY_ALIAS_LEN] = { 0 }; + Uint8Buff peerKeyAlias = { peerKeyAliasVal, PAKE_KEY_ALIAS_LEN }; + KeyAliasType keyType = params->userType; + Uint8Buff packageName = { (uint8_t *)params->packageName, strlen(params->packageName) }; + Uint8Buff serviceType = { (uint8_t *)params->serviceType, strlen(params->serviceType) }; + int32_t res = GenerateKeyAlias(&packageName, &serviceType, keyType, &(params->baseParams.idSelf), &selfKeyAlias); + if (res != HC_SUCCESS) { + LOGE("generateKeyAlias self failed"); + return res; + } + KeyAliasType keyTypePeer = params->userTypePeer; + res = GenerateKeyAlias(&packageName, &serviceType, keyTypePeer, &(params->baseParams.idPeer), &peerKeyAlias); + if (res != HC_SUCCESS) { + LOGE("generateKeyAlias peer failed"); + return res; + } + + res = params->baseParams.loader->checkKeyExist(&selfKeyAlias); + if (res != HC_SUCCESS) { + LOGE("self auth keyPair not exist"); + return res; + } + res = params->baseParams.loader->checkKeyExist(&peerKeyAlias); + if (res != HC_SUCCESS) { + LOGE("peer auth pubKey not exist"); + return res; + } + + uint8_t sharedKeyAliasVal[PAKE_KEY_ALIAS_LEN] = { 0 }; + Uint8Buff sharedKeyAlias = { sharedKeyAliasVal, PAKE_KEY_ALIAS_LEN }; + res = GenerateKeyAlias(&packageName, &serviceType, KEY_ALIAS_PSK, &(params->baseParams.idPeer), &sharedKeyAlias); + if (res != HC_SUCCESS) { + LOGE("generateKeyAlias psk failed"); + return res; + } + + KeyBuff selfKeyAliasBuff = { selfKeyAlias.val, selfKeyAlias.length, true }; + KeyBuff peerKeyAliasBuff = { peerKeyAlias.val, peerKeyAlias.length, true }; + Algorithm alg = (params->baseParams.curveType == CURVE_256) ? P256 : ED25519; + res = params->baseParams.loader->agreeSharedSecretWithStorage(&selfKeyAliasBuff, &peerKeyAliasBuff, alg, + PAKE_PSK_LEN, &sharedKeyAlias); + if (res != HC_SUCCESS) { + LOGE("agree psk failed"); + return res; + } + + return res; +} + +TokenManager g_asyTokenManagerInstance = { + RegisterLocalIdentity, + UnregisterLocalIdentity, + DeletePeerAuthInfo, + ComputeAndSavePsk +}; + +const TokenManager *GetAsyTokenManagerInstance() +{ + return &g_asyTokenManagerInstance; +} \ No newline at end of file diff --git a/services/module/src/das_module/pake_task/standard_exchange_task/standard_client_bind_exchange_task.c b/services/module/src/das_module/pake_task/standard_exchange_task/standard_client_bind_exchange_task.c new file mode 100644 index 0000000..ff481eb --- /dev/null +++ b/services/module/src/das_module/pake_task/standard_exchange_task/standard_client_bind_exchange_task.c @@ -0,0 +1,181 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "standard_client_bind_exchange_task.h" +#include "das_common.h" +#include "hc_log.h" +#include "hc_types.h" +#include "protocol_common.h" +#include "standard_exchange_message_util.h" + +enum { + TASK_STATUS_CLIENT_BIND_EXCHANGE_BEGIN = 0, + TASK_STATUS_CLIENT_BIND_EXCHANGE_REQUEST, + TASK_STATUS_CLIENT_BIND_EXCHANGE_CONFIRM, +}; + +static CurTaskType GetTaskType() +{ + return TASK_TYPE_BIND_STANDARD_EXCHANGE; +} + +static int ExchangeRequest(AsyBaseCurTask *task, PakeParams *params, const CJson *in, CJson *out, int *status) +{ + int res; + if (task->taskStatus != TASK_STATUS_CLIENT_BIND_EXCHANGE_BEGIN) { + LOGI("The message is repeated, ignore it, status :%d", task->taskStatus); + *status = IGNORE_MSG; + return HC_SUCCESS; + } + StandardBindExchangeClientTask *realTask = (StandardBindExchangeClientTask *)task; + CJson *data = CreateJson(); + if (data == NULL) { + return HC_ERR_ALLOC_MEMORY; + } + CJson *sendToPeer = CreateJson(); + if (sendToPeer == NULL) { + res = HC_ERR_ALLOC_MEMORY; + goto err; + } + + // parse message + if (params->baseParams.challengePeer.val == NULL) { + GOTO_ERR_AND_SET_RET(GetPeerChallenge(params, in), res); + GOTO_ERR_AND_SET_RET(GenerateSelfChallenge(params), res); + GOTO_ERR_AND_SET_RET(AddByteToJson(data, FIELD_CHALLENGE, params->baseParams.challengeSelf.val, + params->baseParams.challengeSelf.length), res); + } + + // execute + res = ClientRequestStandardBindExchange(params, &(realTask->params)); + if (res != HC_SUCCESS) { + LOGE("ClientRequestStandardBindExchange failed"); + return res; + } + + // package message + GOTO_ERR_AND_SET_RET(AddIntToJson(sendToPeer, FIELD_MESSAGE, PAKE_BIND_EXCHANGE_REQUEST), res); + GOTO_ERR_AND_SET_RET(PackageNonceAndCipherToJson(&(realTask->params.nonce), &(realTask->params.exInfoCipher), + data, FIELD_EX_AUTH_INFO), res); + GOTO_ERR_AND_SET_RET(AddIntToJson(data, FIELD_PEER_USER_TYPE, params->userType), res); + GOTO_ERR_AND_SET_RET(AddObjToJson(sendToPeer, FIELD_PAYLOAD, data), res); + GOTO_ERR_AND_SET_RET(AddObjToJson(out, FIELD_SEND_TO_PEER, sendToPeer), res); + + task->taskStatus = TASK_STATUS_CLIENT_BIND_EXCHANGE_REQUEST; + *status = CONTINUE; +err: + FreeJson(data); + FreeJson(sendToPeer); + return res; +} + +static int ExchangeConfirm(AsyBaseCurTask *task, PakeParams *params, const CJson *in, CJson *out, int *status) +{ + int res; + if (task->taskStatus < TASK_STATUS_CLIENT_BIND_EXCHANGE_REQUEST) { + LOGE("Invalid taskStatus:%d", task->taskStatus); + return HC_ERR_BAD_MESSAGE; + } + if (task->taskStatus > TASK_STATUS_CLIENT_BIND_EXCHANGE_REQUEST) { + LOGI("The message is repeated, ignore it, status :%d", task->taskStatus); + *status = IGNORE_MSG; + return HC_SUCCESS; + } + + StandardBindExchangeClientTask *realTask = (StandardBindExchangeClientTask *)task; + + // parse message + RETURN_IF_ERR(GetIntFromJson(in, FIELD_PEER_USER_TYPE, &(params->userTypePeer))); + RETURN_IF_ERR(ParseNonceAndCipherFromJson(&(realTask->params.nonce), + &(realTask->params.exInfoCipher), in, FIELD_EX_AUTH_INFO)); + + // execute + res = ClientConfirmStandardBindExchange(params, &(realTask->params)); + if (res != HC_SUCCESS) { + LOGE("ClientConfirmStandardBindExchange failed"); + return res; + } + + task->taskStatus = TASK_STATUS_CLIENT_BIND_EXCHANGE_CONFIRM; + *status = FINISH; + return res; +} + +static int Process(struct AsyBaseCurTaskT *task, PakeParams *params, const CJson *in, CJson *out, int *status) +{ + int res = HC_SUCCESS; + if (task->taskStatus == TASK_STATUS_CLIENT_BIND_EXCHANGE_BEGIN) { + res = ExchangeRequest(task, params, in, out, status); + if (res != HC_SUCCESS) { + goto err; + } + return res; + } + + int message = 0; + res = GetIntFromJson(in, "message", &message); + if (res != HC_SUCCESS) { + goto err; + } + + switch (message) { + case PAKE_BIND_EXCHANGE_RESPONSE: + res = ExchangeConfirm(task, params, in, out, status); + break; + default: + res = HC_ERR_INVALID_PARAMS; + break; + } + if (res != HC_SUCCESS) { + goto err; + } + return res; +err: + FreeAndCleanKey(&(params->baseParams.sessionKey)); + SendErrorToOut(out, params->opCode, res); + return res; +} + +static void DestroyStandardBindExchangeClientTask(struct AsyBaseCurTaskT *task) +{ + StandardBindExchangeClientTask *innerTask = (StandardBindExchangeClientTask *)task; + if (innerTask == NULL) { + return; + } + + DestroyStandardBindExchangeParams(&(innerTask->params)); + HcFree(innerTask); +} + +AsyBaseCurTask *CreateStandardBindExchangeClientTask() +{ + StandardBindExchangeClientTask *task = + (StandardBindExchangeClientTask *)HcMalloc(sizeof(StandardBindExchangeClientTask), 0); + if (task == NULL) { + return NULL; + } + task->taskBase.destroyTask = DestroyStandardBindExchangeClientTask; + task->taskBase.process = Process; + task->taskBase.taskStatus = TASK_STATUS_CLIENT_BIND_EXCHANGE_BEGIN; + task->taskBase.getCurTaskType = GetTaskType; + + int res = InitStandardBindExchangeParams(&(task->params)); + if (res != HC_SUCCESS) { + DestroyStandardBindExchangeClientTask((struct AsyBaseCurTaskT *)task); + return NULL; + } + + return (AsyBaseCurTask *)task; +} diff --git a/services/module/src/das_module/pake_task/standard_exchange_task/standard_client_unbind_exchange_task.c b/services/module/src/das_module/pake_task/standard_exchange_task/standard_client_unbind_exchange_task.c new file mode 100644 index 0000000..65d4d60 --- /dev/null +++ b/services/module/src/das_module/pake_task/standard_exchange_task/standard_client_unbind_exchange_task.c @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "standard_client_unbind_exchange_task.h" +#include "das_common.h" +#include "hc_log.h" +#include "standard_exchange_message_util.h" + +enum { + TASK_STATUS_CLIENT_UNBIND_EXCHANGE_BEGIN = 0, + TASK_STATUS_CLIENT_UNBIND_EXCHANGE_REQUEST, + TASK_STATUS_CLIENT_UNBIND_EXCHANGE_CONFIRM, +}; + +static CurTaskType GetTaskType() +{ + return TASK_TYPE_UNBIND_STANDARD_EXCHANGE; +} + +static int ExchangeRequest(AsyBaseCurTask *task, PakeParams *params, const CJson *in, CJson *out, int *status) +{ + int res; + if (task->taskStatus != TASK_STATUS_CLIENT_UNBIND_EXCHANGE_BEGIN) { + LOGI("The message is repeated, ignore it, status :%d", task->taskStatus); + *status = IGNORE_MSG; + return HC_SUCCESS; + } + StandardUnbindExchangeClientTask *realTask = (StandardUnbindExchangeClientTask *)task; + CJson *data = CreateJson(); + if (data == NULL) { + return HC_ERR_ALLOC_MEMORY; + } + CJson *sendToPeer = CreateJson(); + if (sendToPeer == NULL) { + res = HC_ERR_ALLOC_MEMORY; + goto err; + } + + // parse message + if (params->baseParams.challengePeer.val == NULL) { + GOTO_ERR_AND_SET_RET(GetPeerChallenge(params, in), res); + GOTO_ERR_AND_SET_RET(GenerateSelfChallenge(params), res); + GOTO_ERR_AND_SET_RET(AddByteToJson(data, FIELD_CHALLENGE, params->baseParams.challengeSelf.val, + params->baseParams.challengeSelf.length), res); + } + + // execute + res = ClientRequestStandardUnbindExchange(params, &(realTask->params)); + if (res != HC_SUCCESS) { + LOGE("ClientRequestStandardUnbindExchange failed"); + return res; + } + + // package message + GOTO_ERR_AND_SET_RET(AddIntToJson(sendToPeer, FIELD_MESSAGE, PAKE_UNBIND_EXCHANGE_REQUEST), res); + GOTO_ERR_AND_SET_RET(PackageNonceAndCipherToJson(&(realTask->params.nonce), &(realTask->params.exRmvCipher), + data, FIELD_RMV_AUTH_INFO), res); + GOTO_ERR_AND_SET_RET(AddObjToJson(sendToPeer, FIELD_PAYLOAD, data), res); + GOTO_ERR_AND_SET_RET(AddObjToJson(out, FIELD_SEND_TO_PEER, sendToPeer), res); + + task->taskStatus = TASK_STATUS_CLIENT_UNBIND_EXCHANGE_REQUEST; + *status = CONTINUE; +err: + FreeJson(data); + FreeJson(sendToPeer); + return res; +} + +static int ExchangeConfirm(AsyBaseCurTask *task, PakeParams *params, const CJson *in, CJson *out, int *status) +{ + int res; + if (task->taskStatus < TASK_STATUS_CLIENT_UNBIND_EXCHANGE_REQUEST) { + LOGE("task status failed"); + return HC_ERR_BAD_MESSAGE; + } + + if (task->taskStatus > TASK_STATUS_CLIENT_UNBIND_EXCHANGE_REQUEST) { + LOGI("The message is repeated, ignore it, status :%d", task->taskStatus); + *status = IGNORE_MSG; + return HC_SUCCESS; + } + + StandardUnbindExchangeClientTask *realTask = (StandardUnbindExchangeClientTask *)task; + + // parse message + RETURN_IF_ERR(ParseNonceAndCipherFromJson(&(realTask->params.nonce), &(realTask->params.resultCipher), + in, FIELD_RMV_RETURN)); + + // execute + res = ClientConfirmStandardUnbindExchange(params, &(realTask->params)); + if (res != HC_SUCCESS) { + LOGE("ClientRequestStandardUnbindExchange failed"); + return res; + } + + task->taskStatus = TASK_STATUS_CLIENT_UNBIND_EXCHANGE_CONFIRM; + *status = FINISH; + return res; +} + +static int Process(struct AsyBaseCurTaskT *task, PakeParams *params, const CJson *in, CJson *out, int *status) +{ + int res; + if (task->taskStatus == TASK_STATUS_CLIENT_UNBIND_EXCHANGE_BEGIN) { + res = ExchangeRequest(task, params, in, out, status); + if (res != HC_SUCCESS) { + goto err; + } + return res; + } + + int message = 0; + res = GetIntFromJson(in, "message", &message); + if (res != HC_SUCCESS) { + goto err; + } + + switch (message) { + case PAKE_UNBIND_EXCHANGE_RESPONSE: + res = ExchangeConfirm(task, params, in, out, status); + break; + default: + res = HC_ERR_INVALID_PARAMS; + break; + } + if (res != HC_SUCCESS) { + goto err; + } + return res; +err: + FreeAndCleanKey(&(params->baseParams.sessionKey)); + SendErrorToOut(out, params->opCode, res); + return res; +} + +static void DestroyStandardUnbindExchangeClientTask(struct AsyBaseCurTaskT *task) +{ + StandardUnbindExchangeClientTask *innerTask = (StandardUnbindExchangeClientTask *)task; + if (innerTask == NULL) { + return; + } + + DestroyStandardUnbindExchangeParams(&(innerTask->params)); + HcFree(innerTask); +} + +AsyBaseCurTask *CreateStandardUnbindExchangeClientTask() +{ + StandardUnbindExchangeClientTask *task = + (StandardUnbindExchangeClientTask *)HcMalloc(sizeof(StandardUnbindExchangeClientTask), 0); + if (task == NULL) { + return NULL; + } + task->taskBase.destroyTask = DestroyStandardUnbindExchangeClientTask; + task->taskBase.process = Process; + task->taskBase.taskStatus = TASK_STATUS_CLIENT_UNBIND_EXCHANGE_BEGIN; + task->taskBase.getCurTaskType = GetTaskType; + + int res = InitStandardUnbindExchangeParams(&(task->params)); + if (res != HC_SUCCESS) { + DestroyStandardUnbindExchangeClientTask((struct AsyBaseCurTaskT *)task); + return NULL; + } + + return (AsyBaseCurTask *)task; +} \ No newline at end of file diff --git a/services/module/src/das_module/pake_task/standard_exchange_task/standard_exchange_message_util.c b/services/module/src/das_module/pake_task/standard_exchange_task/standard_exchange_message_util.c new file mode 100644 index 0000000..5d491d9 --- /dev/null +++ b/services/module/src/das_module/pake_task/standard_exchange_task/standard_exchange_message_util.c @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "standard_exchange_message_util.h" +#include "common_defs.h" +#include "common_util.h" +#include "hc_log.h" +#include "hc_types.h" +#include "json_utils.h" +#include "module_common.h" +#include "pake_base_cur_task.h" + +int32_t PackageNonceAndCipherToJson(const Uint8Buff *nonce, const Uint8Buff *cipher, CJson *data, const char *key) +{ + int32_t res = HC_SUCCESS; + uint32_t exAuthInfoLen = nonce->length + cipher->length; + uint8_t *exAuthInfoVal = (uint8_t *)HcMalloc(exAuthInfoLen, 0); + if (exAuthInfoVal == NULL) { + LOGE("malloc exAuthInfoVal failed."); + res = HC_ERR_ALLOC_MEMORY; + goto err; + } + if (memcpy_s(exAuthInfoVal, exAuthInfoLen, nonce->val, nonce->length) != EOK) { + LOGE("memcpy nonce failed"); + res = HC_ERR_MEMORY_COPY; + goto err; + } + if (memcpy_s(exAuthInfoVal + nonce->length, exAuthInfoLen - nonce->length, + cipher->val, cipher->length) != EOK) { + LOGE("memcpy exInfoCipher failed"); + res = HC_ERR_MEMORY_COPY; + goto err; + } + GOTO_ERR_AND_SET_RET(AddByteToJson(data, key, exAuthInfoVal, exAuthInfoLen), res); +err: + HcFree(exAuthInfoVal); + return res; +} + +int32_t ParseNonceAndCipherFromJson(Uint8Buff *nonce, Uint8Buff *cipher, const CJson *in, const char *key) +{ + int32_t res = HC_SUCCESS; + uint8_t *exAuthInfoVal = NULL; + const char *exAuthInfoStr = GetStringFromJson(in, key); + if (exAuthInfoStr == NULL) { + LOGE("get exAuthInfoStr failed."); + res = HC_ERR_JSON_GET; + goto err; + } + int32_t exAuthInfoLen = strlen(exAuthInfoStr) / BYTE_TO_HEX_OPER_LENGTH; + exAuthInfoVal = (uint8_t *)HcMalloc(exAuthInfoLen, 0); + if (exAuthInfoVal == NULL) { + LOGE("Malloc exAuthInfoVal failed."); + res = HC_ERR_ALLOC_MEMORY; + goto err; + } + res = HexStringToByte(exAuthInfoStr, exAuthInfoVal, exAuthInfoLen); + if (res != HC_SUCCESS) { + LOGE("Convert exAuthInfo from hex string to byte failed."); + goto err; + } + if (memcpy_s(nonce->val, nonce->length, exAuthInfoVal, nonce->length) != EOK) { + LOGE("copy nonce failed!"); + res = HC_ERR_MEMORY_COPY; + goto err; + } + + res = InitSingleParam(cipher, exAuthInfoLen - nonce->length); + if (res != HC_SUCCESS) { + LOGE("init exInfoCipher failed"); + goto err; + } + if (memcpy_s(cipher->val, cipher->length, exAuthInfoVal + nonce->length, + exAuthInfoLen - nonce->length) != EOK) { + LOGE("copy exInfoCipher failed!"); + res = HC_ERR_MEMORY_COPY; + goto err; + } +err: + HcFree(exAuthInfoVal); + return res; +} + +int32_t GenerateSelfChallenge(PakeParams *params) +{ + int res = InitSingleParam(&(params->baseParams.challengeSelf), PAKE_CHALLENGE_LEN); + if (res != HC_SUCCESS) { + LOGE("InitSingleParam for challengeSelf failed, res: %d.", res); + return res; + } + res = params->baseParams.loader->generateRandom(&(params->baseParams.challengeSelf)); + if (res != HC_SUCCESS) { + LOGE("GenerateRandom for challengeSelf failed, res: %d.", res); + return res; + } + return res; +} + +int32_t GetPeerChallenge(PakeParams *params, const CJson *in) +{ + int res = InitSingleParam(&(params->baseParams.challengePeer), PAKE_CHALLENGE_LEN); + if (res != HC_SUCCESS) { + LOGE("InitSingleParam for challengePeer failed, res: %d.", res); + return res; + } + res = GetByteFromJson(in, FIELD_CHALLENGE, + params->baseParams.challengePeer.val, params->baseParams.challengePeer.length); + if (res != HC_SUCCESS) { + LOGE("Get challengePeer failed, res: %d.", res); + return res; + } + return res; +} diff --git a/services/module/src/das_module/pake_task/standard_exchange_task/standard_server_bind_exchange_task.c b/services/module/src/das_module/pake_task/standard_exchange_task/standard_server_bind_exchange_task.c new file mode 100644 index 0000000..1561c64 --- /dev/null +++ b/services/module/src/das_module/pake_task/standard_exchange_task/standard_server_bind_exchange_task.c @@ -0,0 +1,188 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "standard_server_bind_exchange_task.h" +#include "das_common.h" +#include "hc_log.h" +#include "standard_exchange_message_util.h" + +enum { + TASK_STATUS_SERVER_BIND_EXCHANGE_BEGIN = 0, + TASK_STATUS_SERVER_BIND_EXCHANGE_START, + TASK_STATUS_SERVER_BIND_EXCHANGE_RESPONSE, +}; + +static CurTaskType GetTaskType() +{ + return TASK_TYPE_BIND_STANDARD_EXCHANGE; +} + +static int ExchangeStart(AsyBaseCurTask *task, PakeParams *params, const CJson *in, CJson *out, int *status) +{ + int res = HC_SUCCESS; + if (task->taskStatus != TASK_STATUS_SERVER_BIND_EXCHANGE_BEGIN) { + LOGI("The message is repeated, ignore it, status :%d", task->taskStatus); + *status = IGNORE_MSG; + return HC_SUCCESS; + } + + if (params->baseParams.challengeSelf.val == NULL) { + res = GenerateSelfChallenge(params); + if (res != HC_SUCCESS) { + LOGE("GenerateSelfChallenge failed"); + return res; + } + CJson *payload = GetObjFromJson(out, FIELD_PAYLOAD); + if (payload == NULL) { + LOGE("Get payload failed."); + return HC_ERR_JSON_GET; + } + RETURN_IF_ERR(AddByteToJson(payload, FIELD_CHALLENGE, + params->baseParams.challengeSelf.val, params->baseParams.challengeSelf.length)); + } + + task->taskStatus = TASK_STATUS_SERVER_BIND_EXCHANGE_START; + *status = CONTINUE; + return res; +} + +static int ExchangeResponse(AsyBaseCurTask *task, PakeParams *params, const CJson *in, CJson *out, int *status) +{ + int res = HC_SUCCESS; + CJson *data = NULL; + CJson *sendToPeer = NULL; + + if (task->taskStatus < TASK_STATUS_SERVER_BIND_EXCHANGE_START) { + return HC_ERR_BAD_MESSAGE; + } + if (task->taskStatus > TASK_STATUS_SERVER_BIND_EXCHANGE_START) { + LOGI("The message is repeated, ignore it, status :%d", task->taskStatus); + *status = IGNORE_MSG; + return HC_SUCCESS; + } + + StandardBindExchangeServerTask *realTask = (StandardBindExchangeServerTask *)task; + + // parse message + GOTO_ERR_AND_SET_RET(GetIntFromJson(in, FIELD_PEER_USER_TYPE, &(params->userTypePeer)), res); + if (params->baseParams.challengePeer.val == NULL) { + GOTO_ERR_AND_SET_RET(GetPeerChallenge(params, in), res); + } + GOTO_ERR_AND_SET_RET(ParseNonceAndCipherFromJson(&(realTask->params.nonce), &(realTask->params.exInfoCipher), + in, FIELD_EX_AUTH_INFO), res); + + // execute + res = ServerResponseStandardBindExchange(params, &(realTask->params)); + if (res != HC_SUCCESS) { + LOGE("ServerResponseStandardBindExchange failed"); + return res; + } + + sendToPeer = CreateJson(); + if (sendToPeer == NULL) { + res = HC_ERR_ALLOC_MEMORY; + goto err; + } + GOTO_ERR_AND_SET_RET(AddIntToJson(sendToPeer, FIELD_MESSAGE, PAKE_BIND_EXCHANGE_RESPONSE), res); + data = CreateJson(); + if (data == NULL) { + res = HC_ERR_ALLOC_MEMORY; + goto err; + } + GOTO_ERR_AND_SET_RET(PackageNonceAndCipherToJson(&(realTask->params.nonce), &(realTask->params.exInfoCipher), + data, FIELD_EX_AUTH_INFO), res); + GOTO_ERR_AND_SET_RET(AddIntToJson(data, FIELD_PEER_USER_TYPE, params->userType), res); + GOTO_ERR_AND_SET_RET(AddObjToJson(sendToPeer, "payload", data), res); + GOTO_ERR_AND_SET_RET(AddObjToJson(out, FIELD_SEND_TO_PEER, sendToPeer), res); + + task->taskStatus = TASK_STATUS_SERVER_BIND_EXCHANGE_RESPONSE; + *status = FINISH; +err: + FreeJson(data); + FreeJson(sendToPeer); + return res; +} + +static int Process(struct AsyBaseCurTaskT *task, PakeParams *params, const CJson *in, CJson *out, int *status) +{ + int res; + if ((task == NULL) || (in == NULL) || (out == NULL) || (status == NULL)) { + return HC_ERR_INVALID_PARAMS; + } + + if (task->taskStatus == TASK_STATUS_SERVER_BIND_EXCHANGE_BEGIN) { + res = ExchangeStart(task, params, in, out, status); + if (res != HC_SUCCESS) { + goto err; + } + return res; + } + + int message = 0; + res = GetIntFromJson(in, "message", &message); + if (res != HC_SUCCESS) { + goto err; + } + + switch (message) { + case PAKE_BIND_EXCHANGE_REQUEST: + res = ExchangeResponse(task, params, in, out, status); + break; + default: + res = HC_ERR_INVALID_PARAMS; + break; + } + if (res != HC_SUCCESS) { + goto err; + } + return res; +err: + FreeAndCleanKey(&(params->baseParams.sessionKey)); + SendErrorToOut(out, params->opCode, res); + return res; +} + +static void DestroyStandardBindExchangeServerTask(struct AsyBaseCurTaskT *task) +{ + StandardBindExchangeServerTask *innerTask = (StandardBindExchangeServerTask *)task; + if (innerTask == NULL) { + return; + } + + DestroyStandardBindExchangeParams(&(innerTask->params)); + HcFree(innerTask); +} + +AsyBaseCurTask *CreateStandardBindExchangeServerTask() +{ + StandardBindExchangeServerTask *task = + (StandardBindExchangeServerTask *)HcMalloc(sizeof(StandardBindExchangeServerTask), 0); + if (task == NULL) { + return NULL; + } + task->taskBase.destroyTask = DestroyStandardBindExchangeServerTask; + task->taskBase.process = Process; + task->taskBase.taskStatus = TASK_STATUS_SERVER_BIND_EXCHANGE_BEGIN; + task->taskBase.getCurTaskType = GetTaskType; + + int res = InitStandardBindExchangeParams(&(task->params)); + if (res != 0) { + DestroyStandardBindExchangeServerTask((struct AsyBaseCurTaskT *)task); + return NULL; + } + + return (AsyBaseCurTask *)task; +} + diff --git a/services/module/src/das_module/pake_task/standard_exchange_task/standard_server_unbind_exchange_task.c b/services/module/src/das_module/pake_task/standard_exchange_task/standard_server_unbind_exchange_task.c new file mode 100644 index 0000000..10f79dd --- /dev/null +++ b/services/module/src/das_module/pake_task/standard_exchange_task/standard_server_unbind_exchange_task.c @@ -0,0 +1,186 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "standard_server_unbind_exchange_task.h" +#include "das_common.h" +#include "hc_log.h" +#include "standard_exchange_message_util.h" + +enum { + TASK_STATUS_SERVER_UNBIND_EXCHANGE_BEGIN = 0, + TASK_STATUS_SERVER_UNBIND_EXCHANGE_START, + TASK_STATUS_SERVER_UNBIND_EXCHANGE_RESPONSE, +}; + +static CurTaskType GetTaskType() +{ + return TASK_TYPE_UNBIND_STANDARD_EXCHANGE; +} + +static int ExchangeStart(AsyBaseCurTask *task, PakeParams *params, const CJson *in, CJson *out, int *status) +{ + int res = HC_SUCCESS; + if (task->taskStatus != TASK_STATUS_SERVER_UNBIND_EXCHANGE_BEGIN) { + LOGI("The message is repeated, ignore it, status :%d", task->taskStatus); + *status = IGNORE_MSG; + return HC_SUCCESS; + } + + if (params->baseParams.challengeSelf.val == NULL) { + res = GenerateSelfChallenge(params); + if (res != HC_SUCCESS) { + LOGE("GenerateSelfChallenge failed"); + return res; + } + CJson *payload = GetObjFromJson(out, FIELD_PAYLOAD); + if (payload == NULL) { + LOGE("Get payload failed."); + return HC_ERR_JSON_GET; + } + RETURN_IF_ERR(AddByteToJson(payload, FIELD_CHALLENGE, + params->baseParams.challengeSelf.val, params->baseParams.challengeSelf.length)); + } + + task->taskStatus = TASK_STATUS_SERVER_UNBIND_EXCHANGE_START; + *status = CONTINUE; + return res; +} + +static int ExchangeResponse(AsyBaseCurTask *task, PakeParams *params, const CJson *in, CJson *out, int *status) +{ + int res = HC_SUCCESS; + CJson *data = NULL; + CJson *sendToPeer = NULL; + + if (task->taskStatus < TASK_STATUS_SERVER_UNBIND_EXCHANGE_START) { + return HC_ERR_BAD_MESSAGE; + } + if (task->taskStatus > TASK_STATUS_SERVER_UNBIND_EXCHANGE_START) { + LOGI("The message is repeated, ignore it, status :%d", task->taskStatus); + *status = IGNORE_MSG; + return HC_SUCCESS; + } + + StandardUnbindExchangeServerTask *realTask = (StandardUnbindExchangeServerTask *)task; + + if (params->baseParams.challengePeer.val == NULL) { + GOTO_ERR_AND_SET_RET(GetPeerChallenge(params, in), res); + } + GOTO_ERR_AND_SET_RET(ParseNonceAndCipherFromJson(&(realTask->params.nonce), &(realTask->params.exRmvCipher), + in, FIELD_RMV_AUTH_INFO), res); + + // execute + res = ServerResponseStandardUnbindExchange(params, &(realTask->params)); + if (res != HC_SUCCESS) { + LOGE("ServerResponseStandardUnbindExchange failed"); + return res; + } + + sendToPeer = CreateJson(); + if (sendToPeer == NULL) { + res = HC_ERR_ALLOC_MEMORY; + goto err; + } + GOTO_ERR_AND_SET_RET(AddIntToJson(sendToPeer, FIELD_MESSAGE, PAKE_UNBIND_EXCHANGE_RESPONSE), res); + data = CreateJson(); + if (data == NULL) { + res = HC_ERR_ALLOC_MEMORY; + goto err; + } + GOTO_ERR_AND_SET_RET(PackageNonceAndCipherToJson(&(realTask->params.nonce), &(realTask->params.resultCipher), + data, FIELD_RMV_RETURN), res); + GOTO_ERR_AND_SET_RET(AddObjToJson(sendToPeer, FIELD_PAYLOAD, data), res); + GOTO_ERR_AND_SET_RET(AddObjToJson(out, FIELD_SEND_TO_PEER, sendToPeer), res); + + task->taskStatus = TASK_STATUS_SERVER_UNBIND_EXCHANGE_RESPONSE; + *status = FINISH; +err: + FreeJson(data); + FreeJson(sendToPeer); + return res; +} + +static int Process(struct AsyBaseCurTaskT *task, PakeParams *params, const CJson *in, CJson *out, int *status) +{ + int res; + if ((task == NULL) || (in == NULL) || (out == NULL) || (status == NULL)) { + return HC_ERR_INVALID_PARAMS; + } + + if (task->taskStatus == TASK_STATUS_SERVER_UNBIND_EXCHANGE_BEGIN) { + res = ExchangeStart(task, params, in, out, status); + if (res != HC_SUCCESS) { + goto err; + } + return res; + } + + int message = 0; + res = GetIntFromJson(in, "message", &message); + if (res != HC_SUCCESS) { + goto err; + } + + switch (message) { + case PAKE_UNBIND_EXCHANGE_REQUEST: + res = ExchangeResponse(task, params, in, out, status); + break; + default: + res = HC_ERR_INVALID_PARAMS; + break; + } + + if (res != HC_SUCCESS) { + goto err; + } + return res; +err: + FreeAndCleanKey(&(params->baseParams.sessionKey)); + SendErrorToOut(out, params->opCode, res); + return res; +} + +static void DestroyStandardUnbindExchangeServerTask(struct AsyBaseCurTaskT *task) +{ + StandardUnbindExchangeServerTask *innerTask = (StandardUnbindExchangeServerTask *)task; + if (innerTask == NULL) { + return; + } + + DestroyStandardUnbindExchangeParams(&(innerTask->params)); + HcFree(innerTask); +} + +AsyBaseCurTask *CreateStandardUnbindExchangeServerTask() +{ + StandardUnbindExchangeServerTask *task = + (StandardUnbindExchangeServerTask *)HcMalloc(sizeof(StandardUnbindExchangeServerTask), 0); + if (task == NULL) { + return NULL; + } + task->taskBase.destroyTask = DestroyStandardUnbindExchangeServerTask; + task->taskBase.process = Process; + task->taskBase.taskStatus = TASK_STATUS_SERVER_UNBIND_EXCHANGE_BEGIN; + task->taskBase.getCurTaskType = GetTaskType; + + int res = InitStandardUnbindExchangeParams(&(task->params)); + if (res != HC_SUCCESS) { + DestroyStandardUnbindExchangeServerTask((struct AsyBaseCurTaskT *)task); + return NULL; + } + + return (AsyBaseCurTask *)task; +} + diff --git a/services/module/src/das_module/pake_task/standard_exchange_task_mock/standard_exchange_task_mock.c b/services/module/src/das_module/pake_task/standard_exchange_task_mock/standard_exchange_task_mock.c new file mode 100644 index 0000000..ad52dbc --- /dev/null +++ b/services/module/src/das_module/pake_task/standard_exchange_task_mock/standard_exchange_task_mock.c @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "das_asy_token_manager.h" +#include "standard_client_bind_exchange_task.h" +#include "standard_client_unbind_exchange_task.h" +#include "standard_server_bind_exchange_task.h" +#include "standard_server_unbind_exchange_task.h" + +AsyBaseCurTask *CreateStandardBindExchangeClientTask() +{ + return NULL; +} + +AsyBaseCurTask *CreateStandardBindExchangeServerTask() +{ + return NULL; +} + +AsyBaseCurTask *CreateStandardUnbindExchangeClientTask() +{ + return NULL; +} + +AsyBaseCurTask *CreateStandardUnbindExchangeServerTask() +{ + return NULL; +} + +const TokenManager *GetAsyTokenManagerInstance() +{ + return NULL; +} \ No newline at end of file diff --git a/services/module/src/das_module/task_main.c b/services/module/src/das_module/task_main.c new file mode 100644 index 0000000..329dd94 --- /dev/null +++ b/services/module/src/das_module/task_main.c @@ -0,0 +1,532 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "task_main.h" +#include "alg_loader.h" +#include "base_sub_task.h" +#include "das_asy_token_manager.h" +#include "das_common.h" +#include "hc_log.h" +#include "iso_task_main.h" +#include "new_pake_protocol_dl.h" +#include "new_pake_protocol_ec.h" +#include "new_pake_task_main.h" +#include "pake_protocol_dl.h" +#include "pake_protocol_ec.h" +#include "pake_task_main.h" +#include "protocol_common.h" + +typedef struct DasProtocolTypeT { + ProtocolType type; + uint32_t algInProtocol; + const TokenManager *tokenManagerInstance; + SubTaskBase *(*createSubTask)(const CJson *, CJson *); +} DasProtocolType; +IMPLEMENT_HC_VECTOR(SubTaskVec, void *, 1) +DECLARE_HC_VECTOR(DasProtocolTypeVec, void *) +IMPLEMENT_HC_VECTOR(DasProtocolTypeVec, void *, 1) + +DasProtocolTypeVec g_protocolTypeVec; +ProtocolType g_subTaskTypeToAlgType[] = { + ISO, // TASK_TYPE_ISO_PROTOCOL = 0, + PAKE, // TASK_TYPE_PAKE_PROTOCOL = 1, + NEW_PAKE // TASK_TYPE_NEW_PAKE_PROTOCOL = 2, +}; + +static void GetMinVersion(VersionStruct *version) +{ + version->first = 1; + version->second = 0; + version->third = 0; +} + +static void GetMaxVersion(VersionStruct *version) +{ + version->first = VERSION_FIRST_BIT; + version->second = 0; + version->third = 0; + + uint32_t index; + void **ptr = NULL; + FOR_EACH_HC_VECTOR(g_protocolTypeVec, index, ptr) { + if (ptr != NULL && *ptr != NULL) { + DasProtocolType *temp = (DasProtocolType *)(*ptr); + version->third = (version->third) | temp->algInProtocol; + } + } +} + +static void InitVersionInfo(VersionInfo *versionInfo) +{ + GetMinVersion(&(versionInfo->minVersion)); + GetMaxVersion(&(versionInfo->curVersion)); + versionInfo->versionStatus = INITIAL; +} + +static int AddVersionToOut(const VersionInfo *versionInfo, CJson *out) +{ + CJson *payload = GetObjFromJson(out, FIELD_PAYLOAD); + if (payload == NULL) { + LOGD("not find payload"); + return HC_SUCCESS; + } + return AddVersionToJson(payload, &(versionInfo->minVersion), &(versionInfo->curVersion)); +} + +static int CombineJson(CJson *desObj, const CJson *srcObj) +{ + CHECK_PTR_RETURN_ERROR_CODE(desObj, "desObj"); + CHECK_PTR_RETURN_ERROR_CODE(srcObj, "srcObj"); + int res; + int len = GetItemNum(srcObj); + for (int i = 0; i < len; i++) { + CJson *item = GetItemFromArray(srcObj, i); + const char *key = GetItemKey(item); + CJson *payload = GetObjFromJson(desObj, FIELD_PAYLOAD); + if (strcmp(key, FIELD_PAYLOAD) == 0 && payload != NULL) { + res = CombineJson(payload, item); + if (res != HC_SUCCESS) { + LOGE("combine payload failed"); + return res; + } + } else { + res = AddObjToJson(desObj, key, item); + if (res != HC_SUCCESS) { + LOGE("AddObjToJson failed"); + return res; + } + } + } + return res; +} + +static int AddErrToOut(CJson *out, const CJson *err) +{ + CJson *sendToPeer = GetObjFromJson(err, FIELD_SEND_TO_PEER); + if (sendToPeer != NULL) { + if (AddObjToJson(out, FIELD_SEND_TO_PEER, sendToPeer) != HC_SUCCESS) { + LOGE("Add sendToPeer to json failed."); + return HC_ERR_JSON_ADD; + } + } + CJson *sendToSelf = GetObjFromJson(err, FIELD_SEND_TO_PEER); + if (sendToSelf != NULL) { + if (AddObjToJson(out, FIELD_SEND_TO_SELF, sendToSelf) != HC_SUCCESS) { + LOGE("Add sendToSelf to json failed."); + return HC_ERR_JSON_ADD; + } + } + return HC_SUCCESS; +} + +static void DestroyTask(Task *task) +{ + if (task == NULL) { + return; + } + uint32_t index; + void **ptr = NULL; + FOR_EACH_HC_VECTOR(task->vec, index, ptr) { + if (ptr != NULL && *ptr != NULL) { + ((SubTaskBase *)(*ptr))->destroyTask((SubTaskBase *)(*ptr)); + } + } + DESTROY_HC_VECTOR(SubTaskVec, &(task->vec)) + HcFree(task); +} + +static int ProcessMultiTask(Task *task, const CJson *in, CJson *out, int *status) +{ + int res; + uint32_t index; + void **ptr = NULL; + CJson *tmpOut = NULL; + CJson *combinedSendToPeer = CreateJson(); + FOR_EACH_HC_VECTOR(task->vec, index, ptr) { + if ((ptr == NULL) || (*ptr == NULL)) { + LOGD("Null ptr in subTask vector."); + continue; + } + tmpOut = CreateJson(); + res = ((SubTaskBase *)(*ptr))->process((*ptr), in, tmpOut, status); + if (res != HC_SUCCESS) { + LOGE("process SubTaskBase failed, index: %u", index); + res = AddErrToOut(out, tmpOut); + if (res != HC_SUCCESS) { + LOGE("AddErrToOut failed"); + goto err; + } + goto err; + } + + CJson *tmpSendToPeer = GetObjFromJson(tmpOut, FIELD_SEND_TO_PEER); + res = CombineJson(combinedSendToPeer, tmpSendToPeer); + if (res != HC_SUCCESS) { + LOGE("CombineJson failed"); + goto err; + } + FreeJson(tmpOut); + tmpOut = NULL; + } + res = AddObjToJson(out, FIELD_SEND_TO_PEER, combinedSendToPeer); + if (res != HC_SUCCESS) { + LOGE("AddObjToJson failed"); + goto err; + } +err: + FreeJson(combinedSendToPeer); + FreeJson(tmpOut); + return res; +} + +static int NegotiateAndProcessTask(Task *task, const CJson *in, CJson *out, int *status) +{ + VersionStruct curVersionPeer = { 0, 0, 0 }; + VersionStruct minVersionPeer = { 0, 0, 0 }; + int res = GetVersionFromJson(in, &minVersionPeer, &curVersionPeer); + if (res != HC_SUCCESS) { + LOGE("Get peer version info failed"); + return res; + } + res = NegotiateVersion(&minVersionPeer, &curVersionPeer, &(task->versionInfo.curVersion)); + if (res != HC_SUCCESS) { + LOGE("NegotiateVersion failed"); + return res; + } + if (!IsVersionEqual(&(task->versionInfo.curVersion), &curVersionPeer)) { + LOGE("Negotiated version not equal"); + return HC_ERR_UNSUPPORTED_VERSION; + } + ProtocolType protocolType = GetPrototolType(&(task->versionInfo.curVersion), task->versionInfo.opCode); + LOGI("client create protocolType:%d", protocolType); + + SubTaskBase *subTask = NULL; + uint32_t index = 0; + void **ptr = task->vec.getp(&(task->vec), 0); + while (index < task->vec.size(&(task->vec)) && ptr != NULL) { + SubTaskBase *temp = (SubTaskBase *)(*ptr); + if (g_subTaskTypeToAlgType[temp->getTaskType(temp)] == protocolType) { + subTask = temp; + index++; + } else { + temp->destroyTask(temp); + task->vec.eraseElement(&(task->vec), ptr, index); + } + ptr = task->vec.getp(&(task->vec), index); + } + if (subTask == NULL) { + LOGE("Not find subTask."); + return HC_ERROR; + } + subTask->curVersion = task->versionInfo.curVersion; + res = subTask->process(subTask, in, out, status); + if (res != HC_SUCCESS) { + LOGE("Process subTask failed"); + return res; + } + return res; +} + +static bool IsPeerErrMessage(const CJson *in, CJson *out, int32_t *res) +{ + int message = 0; + if (GetIntFromJson(in, FIELD_MESSAGE, &message) != HC_SUCCESS) { + LOGD("Get message code failed."); + return false; + } + if (message != ERR_MESSAGE) { + return false; + } + + LOGE("Receive error message from peer."); + if (GetIntFromJson(in, FIELD_ERROR_CODE, res) != HC_SUCCESS) { + LOGE("Get error code failed."); + } + SendErrMsgToSelf(in, out, *res); /* when receive peer ERR_MESSAGE, only need to inform self */ + return true; +} + +static int ProcessTask(Task *task, const CJson *in, CJson *out, int *status) +{ + if (task == NULL || in == NULL || out == NULL || status == NULL) { + return HC_ERR_INVALID_PARAMS; + } + if (task->vec.size(&(task->vec)) == 0) { + LOGE("not has subTask"); + return HC_ERROR; + } + int res = HC_ERROR; + if (IsPeerErrMessage(in, out, &res)) { + LOGE("Peer message is error message."); + return res; + } + + if (task->versionInfo.versionStatus == INITIAL) { + res = ProcessMultiTask(task, in, out, status); + if (res != HC_SUCCESS) { + LOGE("ProcessMultiTask failed"); + return res; + } + task->versionInfo.versionStatus = VERSION_CONFIRM; + } else if (task->versionInfo.versionStatus == VERSION_CONFIRM) { + res = NegotiateAndProcessTask(task, in, out, status); + if (res != HC_SUCCESS) { + LOGE("NegotiateAndProcessTask failed."); + return res; + } + task->versionInfo.versionStatus = VERSION_DECIDED; + } else { + SubTaskBase *subTask = HC_VECTOR_GET(&(task->vec), 0); + res = subTask->process(subTask, in, out, status); + if (res != HC_SUCCESS) { + LOGE("Process subTask failed"); + return res; + } + } + + res = AddVersionToOut(&(task->versionInfo), out); + if (res != HC_SUCCESS) { + LOGE("AddVersionToOut failed"); + } + return res; +} + +static int CreateMultiSubTask(Task *task, const CJson *in, CJson *out) +{ + InitVersionInfo(&(task->versionInfo)); + uint32_t index; + void **ptr = NULL; + FOR_EACH_HC_VECTOR(g_protocolTypeVec, index, ptr) { + if (ptr != NULL && (*ptr) != NULL) { + DasProtocolType *temp = (DasProtocolType *)(*ptr); + SubTaskBase *subTask = temp->createSubTask(in, out); + if (subTask == NULL) { + LOGE("Create subTask failed"); + return HC_ERR_ALLOC_MEMORY; + } + subTask->curVersion = task->versionInfo.curVersion; + task->vec.pushBackT(&(task->vec), (void *)subTask); + } + } + return HC_SUCCESS; +} + +static int CreateSingleSubTask(Task *task, const CJson *in, CJson *out) +{ + VersionStruct curVersionPeer = { 0, 0, 0 }; + VersionStruct minVersionPeer = { 0, 0, 0 }; + int res = GetVersionFromJson(in, &minVersionPeer, &curVersionPeer); + if (res != HC_SUCCESS) { + LOGE("Get peer version info failed"); + return res; + } + InitVersionInfo(&(task->versionInfo)); + res = NegotiateVersion(&minVersionPeer, &curVersionPeer, &(task->versionInfo.curVersion)); + if (res != HC_SUCCESS) { + LOGE("NegotiateVersion failed"); + return res; + } + task->versionInfo.versionStatus = VERSION_DECIDED; + + ProtocolType protocolType = GetPrototolType(&(task->versionInfo.curVersion), task->versionInfo.opCode); + LOGI("server create protocolType:%d", protocolType); + + uint32_t index; + void **ptr = NULL; + FOR_EACH_HC_VECTOR(g_protocolTypeVec, index, ptr) { + DasProtocolType *temp = (DasProtocolType *)(*ptr); + if ((ptr != NULL) && ((*ptr) != NULL) && (temp->type == protocolType)) { + SubTaskBase *subTask = temp->createSubTask(in, out); + if (subTask == NULL) { + LOGE("Create subTask failed"); + return HC_ERR_ALLOC_MEMORY; + } + subTask->curVersion = task->versionInfo.curVersion; + task->vec.pushBackT(&(task->vec), (void *)subTask); + break; + } + } + + return HC_SUCCESS; +} + +Task *CreateTaskT(int *taskId, const CJson *in, CJson *out) +{ + if (taskId == NULL || in == NULL || out == NULL) { + return NULL; + } + Task *task = (Task *)HcMalloc(sizeof(Task), 0); + if (task == NULL) { + return NULL; + } + task->vec = CREATE_HC_VECTOR(SubTaskVec) + task->destroyTask = DestroyTask; + task->processTask = ProcessTask; + const AlgLoader *loader = GetLoaderInstance(); + if (loader == NULL) { + DestroyTask(task); + return NULL; + } + Uint8Buff taskIdBuf = { (uint8_t *)taskId, sizeof(int) }; + int res = loader->generateRandom(&taskIdBuf); + if (res != 0) { + DestroyTask(task); + return NULL; + } + task->taskId = *taskId; + if (GetIntFromJson(in, FIELD_OPERATION_CODE, &(task->versionInfo.opCode)) != HC_SUCCESS) { + LOGE("Get opcode failed."); + DestroyTask(task); + return NULL; + } + bool isClient = true; + if (GetBoolFromJson(in, FIELD_IS_CLIENT, &isClient) != HC_SUCCESS) { + LOGE("Get isClient failed."); + DestroyTask(task); + return NULL; + } + if (isClient) { + res = CreateMultiSubTask(task, in, out); + } else { + res = CreateSingleSubTask(task, in, out); + } + if (res != 0) { + DestroyTask(task); + return NULL; + } + return task; +} + +int32_t RegisterLocalIdentityInTask(const char *pkgName, const char *serviceType, Uint8Buff *authId, int userType) +{ + int32_t res = HC_SUCCESS; + uint32_t index; + void **ptr = NULL; + FOR_EACH_HC_VECTOR(g_protocolTypeVec, index, ptr) { + if (ptr != NULL && (*ptr) != NULL) { + DasProtocolType *temp = (DasProtocolType *)(*ptr); + if ((temp->tokenManagerInstance == NULL) || (temp->tokenManagerInstance->registerLocalIdentity == NULL)) { + LOGD("Protocol type: %d, unsupported method!", temp->type); + continue; + } + res = temp->tokenManagerInstance->registerLocalIdentity(pkgName, serviceType, authId, userType); + if (res != HC_SUCCESS) { + LOGE("Protocol type: %d, registerLocalIdentity failed, res: %d!", temp->type, res); + return HC_ERR_GENERATE_KEY_FAILED; + } + } + } + return res; +} + +int32_t UnregisterLocalIdentityInTask(const char *pkgName, const char *serviceType, Uint8Buff *authId, int userType) +{ + int32_t res = HC_SUCCESS; + uint32_t index; + void **ptr = NULL; + FOR_EACH_HC_VECTOR(g_protocolTypeVec, index, ptr) { + if (ptr != NULL && (*ptr) != NULL) { + DasProtocolType *temp = (DasProtocolType *)(*ptr); + if ((temp->tokenManagerInstance == NULL) || (temp->tokenManagerInstance->unregisterLocalIdentity == NULL)) { + LOGD("Protocol type: %d, unsupported method!", temp->type); + continue; + } + res = temp->tokenManagerInstance->unregisterLocalIdentity(pkgName, serviceType, authId, userType); + if (res != HC_SUCCESS) { + LOGE("Protocol type: %d, unregisterLocalIdentity failed, res: %d!", temp->type, res); + return res; + } + } + } + return res; +} + +int32_t DeletePeerAuthInfoInTask(const char *pkgName, const char *serviceType, Uint8Buff *authIdPeer, int userTypePeer) +{ + int32_t res = HC_SUCCESS; + uint32_t index; + void **ptr = NULL; + FOR_EACH_HC_VECTOR(g_protocolTypeVec, index, ptr) { + if (ptr != NULL && (*ptr) != NULL) { + DasProtocolType *temp = (DasProtocolType *)(*ptr); + if ((temp->tokenManagerInstance == NULL) || (temp->tokenManagerInstance->deletePeerAuthInfo == NULL)) { + LOGD("Protocol type: %d, unsupported method!", temp->type); + continue; + } + res = temp->tokenManagerInstance->deletePeerAuthInfo(pkgName, serviceType, authIdPeer, userTypePeer); + if (res != HC_SUCCESS) { + LOGE("Protocol type: %d, deletePeerAuthInfo failed, res: %d!", temp->type, res); + return res; + } + } + } + return res; +} + +int32_t InitDasProtocolType() +{ + g_protocolTypeVec = CREATE_HC_VECTOR(DasProtocolTypeVec) + DasProtocolType *protocol = NULL; + if (IsIsoSupported()) { + protocol = (DasProtocolType *)HcMalloc(sizeof(DasProtocolType), 0); + if (protocol == NULL) { + return HC_ERR_ALLOC_MEMORY; + } + protocol->type = ISO; + protocol->algInProtocol = ISO_ALG; + protocol->createSubTask = CreateIsoSubTask; + protocol->tokenManagerInstance = GetSymTokenManagerInstance(); + g_protocolTypeVec.pushBackT(&g_protocolTypeVec, (void *)protocol); + } + + if (IsSupportPake()) { + protocol = (DasProtocolType *)HcMalloc(sizeof(DasProtocolType), 0); + if (protocol == NULL) { + return HC_ERR_ALLOC_MEMORY; + } + protocol->type = PAKE; + protocol->algInProtocol = GetPakeEcAlg() | GetPakeDlAlg() | PSK_SPEKE; + protocol->createSubTask = CreatePakeSubTask; + protocol->tokenManagerInstance = GetAsyTokenManagerInstance(); + g_protocolTypeVec.pushBackT(&g_protocolTypeVec, (void *)protocol); + } + + if (IsSupportNewPake()) { + protocol = (DasProtocolType *)HcMalloc(sizeof(DasProtocolType), 0); + if (protocol == NULL) { + return HC_ERR_ALLOC_MEMORY; + } + protocol->type = NEW_PAKE; + protocol->algInProtocol = GetPakeNewEcAlg() | GetPakeNewDlAlg() | PSK_SPEKE; + protocol->createSubTask = CreateNewPakeSubTask; + protocol->tokenManagerInstance = GetAsyTokenManagerInstance(); + g_protocolTypeVec.pushBackT(&g_protocolTypeVec, (void *)protocol); + } + + return HC_SUCCESS; +} + +void DestroyDasProtocolType() +{ + uint32_t index; + void **ptr = NULL; + FOR_EACH_HC_VECTOR(g_protocolTypeVec, index, ptr) { + if (ptr != NULL && *ptr != NULL) { + HcFree((DasProtocolType *)(*ptr)); + *ptr = NULL; + } + } + DESTROY_HC_VECTOR(DasProtocolTypeVec, &g_protocolTypeVec) +} diff --git a/services/module/src/das_module_mock/das_module_mock.c b/services/module/src/das_module_mock/das_module_mock.c new file mode 100644 index 0000000..ad14e6c --- /dev/null +++ b/services/module/src/das_module_mock/das_module_mock.c @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "das_module.h" + +bool IsDasSupported() +{ + return false; +} + +AuthModuleBase *CreateDasModule() +{ + return NULL; +} diff --git a/services/module/src/dev_auth_module_manager.c b/services/module/src/dev_auth_module_manager.c new file mode 100644 index 0000000..a8e1443 --- /dev/null +++ b/services/module/src/dev_auth_module_manager.c @@ -0,0 +1,349 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "dev_auth_module_manager.h" +#include "das_module.h" +#include "hc_log.h" +#include "hc_vector.h" +#include "tcis_module.h" +#include "version_util.h" + +#define CLIENT_FIRST_MESSAGE 0x0001 + +DECLARE_HC_VECTOR(AuthModuleVec, void *) +IMPLEMENT_HC_VECTOR(AuthModuleVec, void *, 1) + +static AuthModuleVec g_authModuleVec; +static VersionStruct g_version; + +static AuthModuleBase *GetModule(int moduleType) +{ + uint32_t index; + void **module = NULL; + FOR_EACH_HC_VECTOR(g_authModuleVec, index, module) { + if ((module != NULL) && (*module != NULL)) { + if (moduleType == ((AuthModuleBase *)(*module))->moduleType) { + return *module; + } + } + } + return NULL; +} + +static bool IsDasMsgRepeated(const CJson *in) +{ + uint32_t message = 0; + int res = GetIntFromJson(in, FIELD_MESSAGE, (int *)&message); + if (res != HC_SUCCESS) { + return false; + } + if ((message & 0xF00F) == CLIENT_FIRST_MESSAGE) { + return false; + } + + LOGI("The message is repeated, ignore it message :%u.", message); + return true; +} + +int32_t CheckMsgRepeatability(const CJson *in, int moduleType) +{ + if (in == NULL) { + LOGE("Params is null."); + return HC_ERR_NULL_PTR; + } + switch (moduleType) { + case DAS_MODULE: + if (IsDasMsgRepeated(in)) { + return HC_ERR_IGNORE_MSG; + } + return HC_SUCCESS; + case TCIS_MODULE: + return HC_ERR_UNSUPPORTED_METHOD; + default: + LOGE("Invalid module type."); + return HC_ERR_MODULE_NOT_FOUNT; + } +} + +int32_t RegisterLocalIdentity(const char *pkgName, const char *serviceType, Uint8Buff *authId, int userType, + int moduleType) +{ + if (pkgName == NULL || serviceType == NULL || authId == NULL || authId->val == NULL) { + LOGE("Params is null."); + return HC_ERR_NULL_PTR; + } + if (moduleType != DAS_MODULE) { + LOGE("Unsupported method."); + return HC_ERR_UNSUPPORTED_METHOD; + } + AuthModuleBase *module = GetModule(moduleType); + if (module == NULL) { + LOGE("Failed to get module!"); + return HC_ERR_MODULE_NOT_FOUNT; + } + DasAuthModule *dasModule = (DasAuthModule *)module; + int32_t res = dasModule->registerLocalIdentity(pkgName, serviceType, authId, userType); + if (res != HC_SUCCESS) { + LOGE("An error occurs when the module processes task!"); + return res; + } + return HC_SUCCESS; +} + +int32_t UnregisterLocalIdentity(const char *pkgName, const char *serviceType, Uint8Buff *authId, int userType, + int moduleType) +{ + if (pkgName == NULL || serviceType == NULL || authId == NULL || authId->val == NULL) { + LOGE("Params is null."); + return HC_ERR_NULL_PTR; + } + if (moduleType != DAS_MODULE) { + LOGE("Unsupported method."); + return HC_ERR_UNSUPPORTED_METHOD; + } + AuthModuleBase *module = GetModule(moduleType); + if (module == NULL) { + LOGE("Failed to get module!"); + return HC_ERR_MODULE_NOT_FOUNT; + } + DasAuthModule *dasModule = (DasAuthModule *)module; + int32_t res = dasModule->unregisterLocalIdentity(pkgName, serviceType, authId, userType); + if (res != HC_SUCCESS) { + LOGE("An error occurs when the module processes task!"); + return res; + } + return HC_SUCCESS; +} + +int32_t DeletePeerAuthInfo(const char *pkgName, const char *serviceType, Uint8Buff *authId, int userType, + int moduleType) +{ + if (pkgName == NULL || serviceType == NULL || authId == NULL || authId->val == NULL) { + LOGE("Params is null."); + return HC_ERR_NULL_PTR; + } + if (moduleType != DAS_MODULE) { + LOGE("Unsupported method."); + return HC_ERR_UNSUPPORTED_METHOD; + } + AuthModuleBase *module = GetModule(moduleType); + if (module == NULL) { + LOGE("Failed to get module!"); + return HC_ERR_MODULE_NOT_FOUNT; + } + DasAuthModule *dasModule = (DasAuthModule *)module; + int32_t res = dasModule->deletePeerAuthInfo(pkgName, serviceType, authId, userType); + if (res != HC_SUCCESS) { + LOGE("An error occurs when the module processes task!"); + return res; + } + return HC_SUCCESS; +} + +int32_t SetToken(CJson *in, CJson *out, int moduleType) +{ + if (in == NULL || out == NULL) { + LOGE("Params is null."); + return HC_ERR_NULL_PTR; + } + if (moduleType != TCIS_MODULE) { + LOGE("Unsupported method."); + return HC_ERR_UNSUPPORTED_METHOD; + } + AuthModuleBase *module = GetModule(moduleType); + if (module == NULL) { + LOGE("Failed to get module!"); + return HC_ERR_MODULE_NOT_FOUNT; + } + + TcisAuthModule *realModule = (TcisAuthModule *)module; + if (realModule->tokenManager == NULL) { + LOGE("Tcis tokenManager is null"); + return HC_ERR_MODULE_NOT_FOUNT; + } + realModule->tokenManager->setToken(in, out); + + return HC_SUCCESS; +} + +int32_t DeleteToken(int moduleType) +{ + if (moduleType != TCIS_MODULE) { + LOGE("Unsupported method."); + return HC_ERR_UNSUPPORTED_METHOD; + } + AuthModuleBase *module = GetModule(moduleType); + if (module == NULL) { + LOGE("Failed to get module!"); + return HC_ERR_MODULE_NOT_FOUNT; + } + + TcisAuthModule *realModule = (TcisAuthModule *)module; + if (realModule->tokenManager == NULL) { + LOGE("Tcis tokenManager is null"); + return HC_ERR_MODULE_NOT_FOUNT; + } + realModule->tokenManager->deleteToken(); + + return HC_SUCCESS; +} + +int32_t GetRegisterProof(CJson *out, int moduleType) +{ + if (out == NULL) { + LOGE("Params is null."); + return HC_ERR_NULL_PTR; + } + if (moduleType != TCIS_MODULE) { + LOGE("Unsupported method."); + return HC_ERR_UNSUPPORTED_METHOD; + } + AuthModuleBase *module = GetModule(moduleType); + if (module == NULL) { + LOGE("Failed to get module!"); + return HC_ERR_MODULE_NOT_FOUNT; + } + + TcisAuthModule *realModule = (TcisAuthModule *)module; + if (realModule->tokenManager == NULL) { + LOGE("Tcis tokenManager is null"); + return HC_ERR_MODULE_NOT_FOUNT; + } + realModule->tokenManager->getRegisterProof(out); + + return HC_SUCCESS; +} + +int32_t ProcessTask(int taskId, const CJson *in, CJson *out, int *status, int moduleType) +{ + AuthModuleBase *module = GetModule(moduleType); + if (module == NULL) { + LOGE("Failed to get module!"); + return HC_ERR_MODULE_NOT_FOUNT; + } + if (module->processTask == NULL) { + LOGE("Unsupported method."); + return HC_ERR_UNSUPPORTED_METHOD; + } + int32_t res = module->processTask(taskId, in, out, status); + if (res != HC_SUCCESS) { + LOGE("An error occurs when the module processes task!"); + return res; + } + res = AddSingleVersionToJson(out, &g_version); + if (res != HC_SUCCESS) { + LOGE("AddSingleVersionToJson failed, res:%d", res); + } else { + LOGI("Create task success."); + } + return res; +} + +int32_t CreateTask(int *taskId, const CJson *in, CJson *out, int moduleType) +{ + AuthModuleBase *module = GetModule(moduleType); + if (module == NULL) { + LOGE("Failed to get module!"); + return HC_ERR_MODULE_NOT_FOUNT; + } + if (module->createTask == NULL) { + LOGE("Unsupported method."); + return HC_ERR_UNSUPPORTED_METHOD; + } + int32_t res = module->createTask(taskId, in, out); + if (res != HC_SUCCESS) { + LOGE("An error occurs when the module create task!"); + return res; + } + LOGI("Create task success."); + return HC_SUCCESS; +} + +void DestroyTask(int taskId, int moduleType) +{ + AuthModuleBase *module = GetModule(moduleType); + if (module == NULL) { + return; + } + if (module->destroyTask == NULL) { + LOGE("Unsupported method."); + return; + } + module->destroyTask(taskId); +} + +static AuthModuleBase *CreateDasModuleStatic() +{ + return CreateDasModule(); +} + +static uint32_t InitDasModule() +{ + AuthModuleBase *das = CreateDasModuleStatic(); + if (das == NULL) { + LOGE("CreateDasModuleStatic failed."); + return HC_ERR_ALLOC_MEMORY; + } + g_authModuleVec.pushBackT(&g_authModuleVec, (void *)das); + return HC_SUCCESS; +} + +static uint32_t InitTcisModule() +{ + AuthModuleBase *tcis = CreateTcisModule(); + if (tcis == NULL) { + LOGE("Create tcis module failed."); + return HC_ERR_ALLOC_MEMORY; + } + g_authModuleVec.pushBackT(&g_authModuleVec, (void *)tcis); + return HC_SUCCESS; +} + +int32_t InitModules() +{ + g_authModuleVec = CREATE_HC_VECTOR(AuthModuleVec) + InitGroupAndModuleVersion(&g_version); + int res = HC_SUCCESS; + if (IsDasSupported()) { + res = InitDasModule(); + if (res != HC_SUCCESS) { + LOGE("InitDasModule failed."); + DESTROY_HC_VECTOR(AuthModuleVec, &g_authModuleVec) + } + g_version.third |= DAS_MODULE; + } + if (IsTcisSupported()) { + res = InitTcisModule(); + if (res != HC_SUCCESS) { + LOGE("InitTcisModule failed."); + DESTROY_HC_VECTOR(AuthModuleVec, &g_authModuleVec) + } + g_version.third |= TCIS_MODULE; + } + return res; +} + +void DestroyModules() +{ + uint32_t index; + void **module = NULL; + FOR_EACH_HC_VECTOR(g_authModuleVec, index, module) { + if ((module != NULL) && (*module != NULL)) { + ((AuthModuleBase *)(*module))->destroyModule((AuthModuleBase *)*module); + } + } + DESTROY_HC_VECTOR(AuthModuleVec, &g_authModuleVec) + (void)memset_s(&g_version, sizeof(VersionStruct), 0, sizeof(VersionStruct)); +} diff --git a/services/module/src/module_common.c b/services/module/src/module_common.c new file mode 100644 index 0000000..c4e0de2 --- /dev/null +++ b/services/module/src/module_common.c @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "module_common.h" +#include "common_defs.h" +#include "hc_log.h" +#include "hc_types.h" + +int32_t InitSingleParam(Uint8Buff *param, uint32_t len) +{ + if (param->val != NULL) { + (void)memset_s(param->val, param->length, 0, param->length); + HcFree(param->val); + param->val = NULL; + param->length = 0; + } + + param->length = len; + param->val = (uint8_t *)HcMalloc(param->length, 0); + if (param->val == NULL) { + LOGE("Malloc for param failed."); + return HC_ERR_ALLOC_MEMORY; + } + return HC_SUCCESS; +} \ No newline at end of file diff --git a/services/module/src/protocol/iso_protocol/iso_protocol_common.c b/services/module/src/protocol/iso_protocol/iso_protocol_common.c new file mode 100644 index 0000000..c0adfd2 --- /dev/null +++ b/services/module/src/protocol/iso_protocol/iso_protocol_common.c @@ -0,0 +1,247 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "iso_protocol_common.h" +#include "hc_log.h" +#include "hc_types.h" +#include "securec.h" + +static int IsoCalSelfToken(const IsoBaseParams *params, Uint8Buff *outHmac) +{ + int res; + int length = params->randSelf.length + params->randPeer.length + params->authIdSelf.length + + params->authIdPeer.length; + uint8_t *messagePeer = (uint8_t *)HcMalloc(length, 0); + if (messagePeer == NULL) { + return HC_ERROR; + } + int usedLen = 0; + if (memcpy_s(messagePeer, length, params->randPeer.val, params->randPeer.length) != EOK) { + LOGE("memcpy randPeer failed."); + res = HC_ERR_MEMORY_COPY; + goto err; + } + usedLen += params->randPeer.length; + if (memcpy_s(messagePeer + usedLen, length - usedLen, params->randSelf.val, params->randSelf.length) != EOK) { + LOGE("memcpy randSelf failed."); + res = HC_ERR_MEMORY_COPY; + goto err; + } + usedLen += params->randSelf.length; + if (memcpy_s(messagePeer + usedLen, length - usedLen, params->authIdSelf.val, params->authIdSelf.length) != EOK) { + LOGE("memcpy authIdSelf failed."); + res = HC_ERR_MEMORY_COPY; + goto err; + } + usedLen += params->authIdSelf.length; + if (memcpy_s(messagePeer + usedLen, length - usedLen, params->authIdPeer.val, params->authIdPeer.length) != EOK) { + LOGE("memcpy authIdPeer failed."); + res = HC_ERR_MEMORY_COPY; + goto err; + } + Uint8Buff messageBuf = { messagePeer, length }; + Uint8Buff pskBuf = { (uint8_t *)params->psk, sizeof(params->psk) }; + res = params->loader->computeHmac(&pskBuf, &messageBuf, outHmac, false); + if (res != 0) { + LOGE("computeHmac failed."); + goto err; + } +err: + HcFree(messagePeer); + return res; +} + +static int IsoCalPeerToken(const IsoBaseParams *params, Uint8Buff *selfToken) +{ + int res; + int length = params->randSelf.length + params->randPeer.length + params->authIdPeer.length + + params->authIdSelf.length; + uint8_t *messageSelf = (uint8_t *)HcMalloc(length, 0); + if (messageSelf == NULL) { + return HC_ERR_ALLOC_MEMORY; + } + int usedLen = 0; + if (memcpy_s(messageSelf, length, params->randSelf.val, params->randSelf.length) != EOK) { + LOGE("memcpy randSelf failed."); + res = HC_ERR_MEMORY_COPY; + goto err; + } + usedLen += params->randSelf.length; + if (memcpy_s(messageSelf + usedLen, length - usedLen, params->randPeer.val, params->randPeer.length) != EOK) { + LOGE("memcpy randPeer failed."); + res = HC_ERR_MEMORY_COPY; + goto err; + } + usedLen += params->randPeer.length; + if (memcpy_s(messageSelf + usedLen, length - usedLen, params->authIdPeer.val, params->authIdPeer.length) != EOK) { + LOGE("memcpy authIdPeer failed."); + res = HC_ERR_MEMORY_COPY; + goto err; + } + usedLen += params->authIdPeer.length; + if (memcpy_s(messageSelf + usedLen, length - usedLen, params->authIdSelf.val, params->authIdSelf.length) != EOK) { + LOGE("memcpy authIdSelf failed."); + res = HC_ERR_MEMORY_COPY; + goto err; + } + Uint8Buff messageBufSelf = { messageSelf, length }; + Uint8Buff pskBuf = { (uint8_t *)params->psk, sizeof(params->psk) }; + res = params->loader->computeHmac(&pskBuf, &messageBufSelf, selfToken, false); + if (res != HC_SUCCESS) { + LOGE("computeHmac failed."); + goto err; + } +err: + HcFree(messageSelf); + return res; +} + +int IsoClientGenRandom(IsoBaseParams *params) +{ + if (params == NULL) { + return HC_ERR_INVALID_PARAMS; + } + return params->loader->generateRandom(¶ms->randSelf); +} + +int IsoClientCheckAndGenToken(const IsoBaseParams *params, const Uint8Buff *peerToken, Uint8Buff *selfToken) +{ + if (params == NULL || peerToken == NULL || selfToken == NULL) { + return HC_ERR_INVALID_PARAMS; + } + + uint8_t hmacPeer[SHA256_LEN] = { 0 }; + Uint8Buff outHmac = { hmacPeer, sizeof(hmacPeer) }; + int res = IsoCalSelfToken(params, &outHmac); + if (res != 0) { + return res; + } + if (memcmp(peerToken->val, outHmac.val, outHmac.length) != 0) { + return HC_ERR_PROOF_NOT_MATCH; + } + return IsoCalPeerToken(params, selfToken); +} + +int IsoClientGenSessionKey(IsoBaseParams *params, int returnResult, const uint8_t *hmac, uint32_t hmacLen) +{ + if (params == NULL) { + return HC_ERR_INVALID_PARAMS; + } + + Uint8Buff pskBuf = { params->psk, sizeof(params->psk) }; + Uint8Buff hmacMessage = { (uint8_t *)&returnResult, sizeof(int) }; + uint8_t hmacSelf[SHA256_LEN] = { 0 }; + Uint8Buff outHmacBuf = { hmacSelf, sizeof(hmacSelf) }; + int res = params->loader->computeHmac(&pskBuf, &hmacMessage, &outHmacBuf, false); + if (res != 0) { + return res; + } + if (memcmp(outHmacBuf.val, hmac, hmacLen) != 0) { + return HC_ERR_PROOF_NOT_MATCH; + } + + int hkdfSaltLen = params->randPeer.length + params->randSelf.length; + uint8_t *hkdfSalt = (uint8_t *)HcMalloc(hkdfSaltLen, 0); + if (hkdfSalt == NULL) { + return HC_ERR_ALLOC_MEMORY; + } + if (memcpy_s(hkdfSalt, hkdfSaltLen, params->randSelf.val, params->randSelf.length) != EOK) { + LOGE("memcpy randSelf failed."); + HcFree(hkdfSalt); + return HC_ERR_MEMORY_COPY; + } + if (memcpy_s(hkdfSalt + params->randSelf.length, hkdfSaltLen - params->randSelf.length, + params->randPeer.val, params->randPeer.length) != EOK) { + LOGE("memcpy randPeer failed."); + HcFree(hkdfSalt); + return HC_ERR_MEMORY_COPY; + } + Uint8Buff hkdfSaltBuf = { hkdfSalt, hkdfSaltLen }; + Uint8Buff keyInfoBuf = { (uint8_t *)GENERATE_SESSION_KEY_STR, (uint32_t)strlen(GENERATE_SESSION_KEY_STR) }; + params->sessionKey.val = (uint8_t *)HcMalloc(params->sessionKey.length, 0); + if (params->sessionKey.val == NULL) { + HcFree(hkdfSalt); + return HC_ERR_ALLOC_MEMORY; + } + res = params->loader->computeHkdf(&pskBuf, &hkdfSaltBuf, &keyInfoBuf, ¶ms->sessionKey, false); + if (res != 0) { + LOGE("compute hkdf failed, res:%d", res); + } + HcFree(hkdfSalt); + return res; +} + +int IsoServerGenRandomAndToken(IsoBaseParams *params, Uint8Buff *selfTokenBuf) +{ + int res = params->loader->generateRandom(¶ms->randSelf); + if (res != 0) { + return res; + } + return IsoCalPeerToken(params, selfTokenBuf); +} + +int IsoServerGenSessionKeyAndCalToken(IsoBaseParams *params, const Uint8Buff *tokenFromPeer, Uint8Buff *tokenToPeer) +{ + uint8_t hmacPeer[SHA256_LEN] = {0}; + Uint8Buff outHmac = { hmacPeer, sizeof(hmacPeer) }; + int res = IsoCalSelfToken(params, &outHmac); + if (res != 0) { + return res; + } + if (memcmp(tokenFromPeer->val, outHmac.val, outHmac.length) != 0) { + return HC_ERR_PROOF_NOT_MATCH; + } + + int hkdfSaltLen = params->randPeer.length + params->randSelf.length; + uint8_t *hkdfSalt = (uint8_t *)HcMalloc(hkdfSaltLen, 0); + if (hkdfSalt == NULL) { + return HC_ERR_ALLOC_MEMORY; + } + if (memcpy_s(hkdfSalt, hkdfSaltLen, params->randPeer.val, params->randPeer.length) != EOK) { + LOGE("memcpy randPeer failed."); + HcFree(hkdfSalt); + return HC_ERR_MEMORY_COPY; + } + if (memcpy_s(hkdfSalt + params->randPeer.length, hkdfSaltLen - params->randPeer.length, + params->randSelf.val, params->randSelf.length) != EOK) { + LOGE("memcpy randSelf failed."); + HcFree(hkdfSalt); + return HC_ERR_MEMORY_COPY; + } + Uint8Buff hkdfSaltBuf = { hkdfSalt, hkdfSaltLen }; + Uint8Buff keyInfoBuf = { (uint8_t *)GENERATE_SESSION_KEY_STR, (uint32_t)strlen(GENERATE_SESSION_KEY_STR) }; + params->sessionKey.val = (uint8_t *)HcMalloc(params->sessionKey.length, 0); + if (params->sessionKey.val == NULL) { + HcFree(hkdfSalt); + return HC_ERR_ALLOC_MEMORY; + } + Uint8Buff pskBuf = { params->psk, sizeof(params->psk) }; + res = params->loader->computeHkdf(&pskBuf, &hkdfSaltBuf, &keyInfoBuf, &(params->sessionKey), false); + HcFree(hkdfSalt); + if (res != 0) { + HcFree(params->sessionKey.val); + params->sessionKey.val = NULL; + return res; + } + + int returnCode = 0; + Uint8Buff messageBuf = { (uint8_t *)&returnCode, sizeof(int) }; + res = params->loader->computeHmac(&pskBuf, &messageBuf, tokenToPeer, false); + if (res != 0) { + HcFree(params->sessionKey.val); + params->sessionKey.val = NULL; + } + return res; +} \ No newline at end of file diff --git a/services/module/src/protocol/new_pake_protocol/new_pake_protocol_dl_mock/new_pake_protocol_dl_mock.c b/services/module/src/protocol/new_pake_protocol/new_pake_protocol_dl_mock/new_pake_protocol_dl_mock.c new file mode 100644 index 0000000..d69aa60 --- /dev/null +++ b/services/module/src/protocol/new_pake_protocol/new_pake_protocol_dl_mock/new_pake_protocol_dl_mock.c @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "new_pake_protocol_dl.h" +#include "common_defs.h" +#include "hc_log.h" +#include "pake_defs.h" +#include "protocol_common.h" + +uint32_t GetPakeNewDlAlg() +{ + return UNSUPPORTED_ALG; +} + +int32_t GenerateNewDlPakeParams(PakeBaseParams *params, const Uint8Buff *secret) +{ + (void)params; + (void)secret; + LOGE("NEW-PAKE-DL unsupported."); + return HC_ERROR; +} + +int32_t AgreeNewDlSharedSecret(PakeBaseParams *params, Uint8Buff *sharedSecret) +{ + (void)params; + (void)sharedSecret; + LOGE("NEW-PAKE-DL unsupported."); + return HC_ERROR; +} \ No newline at end of file diff --git a/services/module/src/protocol/new_pake_protocol/new_pake_protocol_ec_mock/new_pake_protocol_ec_mock.c b/services/module/src/protocol/new_pake_protocol/new_pake_protocol_ec_mock/new_pake_protocol_ec_mock.c new file mode 100644 index 0000000..0c73c44 --- /dev/null +++ b/services/module/src/protocol/new_pake_protocol/new_pake_protocol_ec_mock/new_pake_protocol_ec_mock.c @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "new_pake_protocol_ec.h" +#include "hc_log.h" +#include "pake_defs.h" +#include "protocol_common.h" + +uint32_t GetPakeNewEcAlg() +{ + return UNSUPPORTED_ALG; +} + +int32_t GenerateNewEcPakeParams(PakeBaseParams *params, Uint8Buff *secret) +{ + (void)params; + (void)secret; + LOGE("PAKE-EC unsupported."); + return HC_ERROR; +} + +int32_t AgreeNewEcSharedSecret(PakeBaseParams *params, Uint8Buff *sharedSecret) +{ + (void)params; + (void)sharedSecret; + LOGE("PAKE-EC unsupported."); + return HC_ERROR; +} \ No newline at end of file diff --git a/services/module/src/protocol/pake_protocol/pake_protocol_common.c b/services/module/src/protocol/pake_protocol/pake_protocol_common.c new file mode 100644 index 0000000..fdaec15 --- /dev/null +++ b/services/module/src/protocol/pake_protocol/pake_protocol_common.c @@ -0,0 +1,400 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "pake_protocol_common.h" +#include "alg_loader.h" +#include "hc_log.h" +#include "hc_types.h" +#include "module_common.h" +#include "pake_defs.h" +#include "pake_protocol_dl.h" +#include "pake_protocol_ec.h" +#include "protocol_common.h" + +#define PAKE_SESSION_KEY_LEN 16 + +void DestroyPakeBaseParams(PakeBaseParams *params) +{ + if (params == NULL) { + return; + } + + FreeAndCleanKey(¶ms->psk); + FreeAndCleanKey(¶ms->base); + FreeAndCleanKey(¶ms->eskSelf); + FreeAndCleanKey(¶ms->sharedSecret); + FreeAndCleanKey(¶ms->sessionKey); + FreeAndCleanKey(¶ms->hmacKey); + + HcFree(params->salt.val); + params->salt.val = NULL; + + HcFree(params->challengeSelf.val); + params->challengeSelf.val = NULL; + + HcFree(params->challengePeer.val); + params->challengePeer.val = NULL; + + HcFree(params->epkSelf.val); + params->epkSelf.val = NULL; + + HcFree(params->epkPeer.val); + params->epkPeer.val = NULL; + + HcFree(params->idSelf.val); + params->idSelf.val = NULL; + + HcFree(params->idPeer.val); + params->idPeer.val = NULL; + + HcFree(params->kcfData.val); + params->kcfData.val = NULL; + + HcFree(params->kcfDataPeer.val); + params->kcfDataPeer.val = NULL; +} + +static int32_t AllocDefaultParams(PakeBaseParams *params) +{ + params->salt.length = PAKE_SALT_LEN; + params->salt.val = (uint8_t *)HcMalloc(params->salt.length, 0); + if (params->salt.val == NULL) { + return HC_ERROR; + } + + params->challengeSelf.length = PAKE_CHALLENGE_LEN; + params->challengeSelf.val = (uint8_t *)HcMalloc(params->challengeSelf.length, 0); + if (params->challengeSelf.val == NULL) { + return HC_ERR_ALLOC_MEMORY; + } + + params->challengePeer.length = PAKE_CHALLENGE_LEN; + params->challengePeer.val = (uint8_t *)HcMalloc(params->challengePeer.length, 0); + if (params->challengePeer.val == NULL) { + return HC_ERR_ALLOC_MEMORY; + } + + params->sessionKey.length = PAKE_SESSION_KEY_LEN; + params->sessionKey.val = (uint8_t *)HcMalloc(params->sessionKey.length, 0); + if (params->sessionKey.val == NULL) { + return HC_ERR_ALLOC_MEMORY; + } + + params->hmacKey.length = PAKE_HMAC_KEY_LEN; + params->hmacKey.val = (uint8_t *)HcMalloc(params->hmacKey.length, 0); + if (params->hmacKey.val == NULL) { + return HC_ERR_ALLOC_MEMORY; + } + + params->kcfData.length = HMAC_LEN; + params->kcfData.val = (uint8_t *)HcMalloc(params->kcfData.length, 0); + if (params->kcfData.val == NULL) { + return HC_ERR_ALLOC_MEMORY; + } + + params->kcfDataPeer.length = HMAC_LEN; + params->kcfDataPeer.val = (uint8_t *)HcMalloc(params->kcfDataPeer.length, 0); + if (params->kcfDataPeer.val == NULL) { + return HC_ERR_ALLOC_MEMORY; + } + return HC_SUCCESS; +} + +static void FillDefaultValue(PakeBaseParams *params) +{ + params->psk.val = NULL; + params->psk.length = 0; + params->eskSelf.val = NULL; + params->eskSelf.length = 0; + params->epkSelf.val = NULL; + params->epkSelf.length = 0; + params->epkPeer.val = NULL; + params->epkPeer.length = 0; + params->base.val = NULL; + params->base.length = 0; + params->sharedSecret.val = NULL; + params->sharedSecret.length = 0; + params->idSelf.val = NULL; + params->idSelf.length = 0; + params->idPeer.val = NULL; + params->idPeer.length = 0; + params->is256ModSupported = false; /* default 384 */ + params->largePrimeNumHex = NULL; + params->innerKeyLen = 0; + params->supportedPakeAlg = UNSUPPORTED_ALG; + params->curveType = CURVE_NONE; + params->isClient = true; +} + +int32_t InitPakeBaseParams(PakeBaseParams *params) +{ + if (params == NULL) { + LOGE("Params is null."); + return HC_ERR_NULL_PTR; + } + + int32_t res = AllocDefaultParams(params); + if (res != HC_SUCCESS) { + goto err; + } + + FillDefaultValue(params); + + params->loader = GetLoaderInstance(); + if (params->loader == NULL) { + res = HC_ERROR; + goto err; + } + + return HC_SUCCESS; +err: + DestroyPakeBaseParams(params); + return res; +} + +static int32_t GeneratePakeParams(PakeBaseParams *params) +{ + int32_t res; + uint8_t secretVal[PAKE_SECRET_LEN] = { 0 }; + Uint8Buff secret = { secretVal, PAKE_SECRET_LEN }; + if (!params->isClient) { + res = params->loader->generateRandom(&(params->salt)); + if (res != HC_SUCCESS) { + LOGE("Generate salt failed, res: %d.", res); + goto err; + } + } + + res = params->loader->generateRandom(&(params->challengeSelf)); + if (res != HC_SUCCESS) { + LOGE("Generate challengeSelf failed, res: %d.", res); + goto err; + } + + Uint8Buff keyInfo = { (uint8_t *)HICHAIN_SPEKE_BASE_INFO, strlen(HICHAIN_SPEKE_BASE_INFO) }; + res = params->loader->computeHkdf(&(params->psk), &(params->salt), &keyInfo, &secret, false); + if (res != HC_SUCCESS) { + LOGE("Derive secret from psk failed, res: %d.", res); + goto err; + } + + if ((uint32_t)params->supportedPakeAlg & EC_SPEKE) { + res = GenerateEcPakeParams(params, &secret); + } else if ((uint32_t)params->supportedPakeAlg & DL_SPEKE) { + res = GenerateDlPakeParams(params, &secret); + } else { + res = HC_ERR_INVALID_ALG; + } + if (res != HC_SUCCESS) { + LOGE("GeneratePakeParams failed, PakeAlg: 0x%x, res: %d.", params->supportedPakeAlg, res); + } +err: + (void)memset_s(secret.val, secret.length, 0, secret.length); + FreeAndCleanKey(¶ms->psk); + return res; +} + +static int32_t DeriveKeyFromSharedSecret(PakeBaseParams *params, const Uint8Buff *sharedSecret) +{ + int32_t res; + Uint8Buff unionKey = { NULL, 0 }; + Uint8Buff keyInfo = { (uint8_t *)HICHAIN_SPEKE_SESSIONKEY_INFO, strlen(HICHAIN_SPEKE_SESSIONKEY_INFO) }; + unionKey.length = params->sessionKey.length + params->hmacKey.length; + unionKey.val = (uint8_t *)HcMalloc(unionKey.length, 0); + if (unionKey.val == NULL) { + LOGE("Malloc unionKey val failed."); + res = HC_ERR_ALLOC_MEMORY; + goto err; + } + + res = params->loader->computeHkdf(sharedSecret, &(params->salt), &keyInfo, &unionKey, false); + if (res != HC_SUCCESS) { + LOGE("computeHkdf for unionKey failed."); + goto err; + } + if (memcpy_s(params->sessionKey.val, params->sessionKey.length, unionKey.val, params->sessionKey.length) != 0) { + LOGE("memcpy sessionKey failed"); + res = HC_ERR_ALLOC_MEMORY; + goto err; + } + if (memcpy_s(params->hmacKey.val, params->hmacKey.length, + unionKey.val + params->sessionKey.length, params->hmacKey.length) != 0) { + LOGE("memcpy hmacKey failed"); + res = HC_ERR_ALLOC_MEMORY; + goto err; + } +err: + FreeAndCleanKey(&unionKey); + return res; +} + +static int32_t GenerateSessionKey(PakeBaseParams *params) +{ + int32_t res = InitSingleParam(¶ms->sharedSecret, params->innerKeyLen); + if (res != HC_SUCCESS) { + LOGE("InitSingleParam for sharedSecret failed, res: %d.", res); + goto err; + } + + if ((uint32_t)params->supportedPakeAlg & EC_SPEKE) { + res = GenerateEcSharedSecret(params, ¶ms->sharedSecret); + } else if ((uint32_t)params->supportedPakeAlg & DL_SPEKE) { + res = GenerateDlSharedSecret(params, ¶ms->sharedSecret); + } else { + res = HC_ERR_INVALID_ALG; + } + if (res != HC_SUCCESS) { + LOGE("GenerateSharedSecret failed, pakeAlg: %x, res: %d.", params->supportedPakeAlg, res); + goto err; + } + + res = DeriveKeyFromSharedSecret(params, ¶ms->sharedSecret); + if (res != HC_SUCCESS) { + LOGE("DeriveKeyFromSharedSecret failed."); + goto err; + } + return res; +err: + FreeAndCleanKey(¶ms->sharedSecret); + FreeAndCleanKey(¶ms->sessionKey); + FreeAndCleanKey(¶ms->hmacKey); + return res; +} + +static int32_t GenerateProof(PakeBaseParams *params) +{ + uint8_t challengeVal[PAKE_CHALLENGE_LEN + PAKE_CHALLENGE_LEN] = { 0 }; + Uint8Buff challenge = { challengeVal, PAKE_CHALLENGE_LEN + PAKE_CHALLENGE_LEN }; + if (memcpy_s(challenge.val, challenge.length, params->challengeSelf.val, params->challengeSelf.length) != EOK) { + LOGE("Memcpy challengeSelf failed."); + return HC_ERR_MEMORY_COPY; + } + if (memcpy_s(challenge.val + params->challengeSelf.length, challenge.length - params->challengeSelf.length, + params->challengePeer.val, params->challengePeer.length) != EOK) { + LOGE("Memcpy challengePeer failed."); + return HC_ERR_MEMORY_COPY; + } + + int32_t res = params->loader->computeHmac(&(params->hmacKey), &challenge, &(params->kcfData), false); + if (res != HC_SUCCESS) { + LOGE("compute kcfData failed"); + return res; + } + + return res; +} + +static int32_t VerifyProof(const PakeBaseParams *params) +{ + uint8_t challengeVal[PAKE_CHALLENGE_LEN + PAKE_CHALLENGE_LEN] = { 0 }; + Uint8Buff challenge = { challengeVal, PAKE_CHALLENGE_LEN + PAKE_CHALLENGE_LEN }; + if (memcpy_s(challenge.val, challenge.length, params->challengePeer.val, params->challengePeer.length) != EOK) { + LOGE("Memcpy challengePeer failed."); + return HC_ERR_MEMORY_COPY; + } + if (memcpy_s(challenge.val + params->challengePeer.length, challenge.length - params->challengePeer.length, + params->challengeSelf.val, params->challengeSelf.length) != EOK) { + LOGE("Memcpy challengeSelf failed."); + return HC_ERR_MEMORY_COPY; + } + + uint8_t verifyProofVal[HMAC_LEN] = { 0 }; + Uint8Buff verifyProof = { verifyProofVal, HMAC_LEN }; + int32_t res = params->loader->computeHmac(&(params->hmacKey), &challenge, &verifyProof, false); + if (res != HC_SUCCESS) { + LOGE("compute kcfData failed"); + return res; + } + + res = memcmp(verifyProof.val, params->kcfDataPeer.val, verifyProof.length); + if (res != HC_SUCCESS) { + LOGE("compare failed"); + return res; + } + + return res; +} + +int32_t ClientRequestPakeProtocol(const PakeBaseParams *params) +{ + return HC_SUCCESS; +} + +int32_t ClientConfirmPakeProtocol(PakeBaseParams *params) +{ + int32_t res = GeneratePakeParams(params); + if (res != HC_SUCCESS) { + LOGE("GeneratePakeParams failed, res:%d", res); + return res; + } + + res = GenerateSessionKey(params); + if (res != HC_SUCCESS) { + LOGE("GenerateSessionKey failed, res:%d", res); + return res; + } + + res = GenerateProof(params); + if (res != HC_SUCCESS) { + LOGE("GenerateProof failed, res:%d", res); + return res; + } + return res; +} + +int32_t ClientVerifyConfirmPakeProtocol(const PakeBaseParams *params) +{ + int32_t res = VerifyProof(params); + if (res != HC_SUCCESS) { + LOGE("VerifyProof failed, res:%d", res); + return res; + } + + return res; +} + +int32_t ServerResponsePakeProtocol(PakeBaseParams *params) +{ + int32_t res = GeneratePakeParams(params); + if (res != HC_SUCCESS) { + LOGE("GeneratePakeParams failed, res:%d", res); + return res; + } + + return res; +} + +int32_t ServerConfirmPakeProtocol(PakeBaseParams *params) +{ + int32_t res = GenerateSessionKey(params); + if (res != HC_SUCCESS) { + LOGE("GenerateSessionKey failed, res:%d", res); + return res; + } + + res = VerifyProof(params); + if (res != HC_SUCCESS) { + LOGE("VerifyProof failed, res:%d", res); + return res; + } + + res = GenerateProof(params); + if (res != HC_SUCCESS) { + LOGE("GenerateProof failed, res:%d", res); + return res; + } + + return res; +} diff --git a/services/module/src/protocol/pake_protocol/pake_protocol_dl/pake_protocol_dl.c b/services/module/src/protocol/pake_protocol/pake_protocol_dl/pake_protocol_dl.c new file mode 100644 index 0000000..8f2747e --- /dev/null +++ b/services/module/src/protocol/pake_protocol/pake_protocol_dl/pake_protocol_dl.c @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "pake_protocol_dl.h" +#include "hc_log.h" +#include "module_common.h" + +static const char *g_largePrimeNumberHex348 = + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74"\ + "020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437"\ + "4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"\ + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF05"\ + "98DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB"\ + "9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"\ + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718"\ + "3995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33"\ + "A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7"\ + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864"\ + "D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E2"\ + "08E24FA074E5AB3143DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF"; + +static const char *g_largePrimeNumberHex256 = + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74"\ + "020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437"\ + "4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"\ + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF05"\ + "98DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB"\ + "9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"\ + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718"\ + "3995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF"; + +uint32_t GetPakeDlAlg() +{ + return DL_SPEKE; +} + +static int32_t GenerateEsk(PakeBaseParams *params) +{ + int res = params->loader->generateRandom(&(params->eskSelf)); + if (res != HC_SUCCESS) { + LOGE("GenerateRandom for eskSelf failed, res: %d.", res); + FreeAndCleanKey(¶ms->eskSelf); + } + return res; +} + +static int32_t InitDlPakeParams(PakeBaseParams *params) +{ + if (params->isClient) { + params->eskSelf.length = (params->epkPeer.length < PAKE_DL_PRIME_LEN) ? + PAKE_DL_ESK_SMALL_LEN : PAKE_DL_ESK_LEN; + params->innerKeyLen = (params->epkPeer.length < PAKE_DL_PRIME_LEN) ? + PAKE_DL_PRIME_SMALL_LEN : PAKE_DL_PRIME_LEN; + } else { + params->eskSelf.length = params->is256ModSupported ? PAKE_DL_ESK_SMALL_LEN : PAKE_DL_ESK_LEN; + params->innerKeyLen = params->is256ModSupported ? PAKE_DL_PRIME_SMALL_LEN : PAKE_DL_PRIME_LEN; + } + int32_t res = InitSingleParam(&(params->eskSelf), params->eskSelf.length); + if (res != HC_SUCCESS) { + LOGE("InitSingleParam for eskSelf failed, res: %d.", res); + return res; + } + res = InitSingleParam(&(params->epkSelf), params->innerKeyLen); + if (res != HC_SUCCESS) { + LOGE("InitSingleParam for epkSelf failed, res: %d.", res); + return res; + } + res = InitSingleParam(&(params->base), params->innerKeyLen); + if (res != HC_SUCCESS) { + LOGE("InitSingleParam for base failed, res: %d.", res); + return res; + } + return res; +} + +int32_t GenerateDlPakeParams(PakeBaseParams *params, const Uint8Buff *secret) +{ + int32_t res = InitDlPakeParams(params); + if (res != HC_SUCCESS) { + LOGE("InitDlPakeParams failed, res: %d.", res); + goto err; + } + res = GenerateEsk(params); + if (res != HC_SUCCESS) { + LOGE("GenerateEsk failed, res: %d.", res); + goto err; + } + uint8_t expVal[PAKE_DL_EXP_LEN] = { 2 }; + Uint8Buff exp = { expVal, PAKE_DL_EXP_LEN }; + params->largePrimeNumHex = params->is256ModSupported ? g_largePrimeNumberHex256 : g_largePrimeNumberHex348; + res = params->loader->bigNumExpMod(secret, &exp, params->largePrimeNumHex, ¶ms->base); + if (res != HC_SUCCESS) { + LOGE("BigNumExpMod for base failed, res: %d.", res); + goto err; + } + + res = params->loader->bigNumExpMod(¶ms->base, &(params->eskSelf), params->largePrimeNumHex, &(params->epkSelf)); + if (res != HC_SUCCESS) { + LOGE("BigNumExpMod for epkSelf failed, res: %d.", res); + goto err; + } + return res; +err: + FreeAndCleanKey(¶ms->eskSelf); + FreeAndCleanKey(¶ms->base); + return res; +} + +int32_t GenerateDlSharedSecret(PakeBaseParams *params, Uint8Buff *sharedSecret) +{ + if (!params->loader->checkDlPublicKey(&(params->epkPeer), params->largePrimeNumHex)) { + LOGE("CheckDlPublicKey failed."); + return HC_ERR_INVALID_PUBLIC_KEY; + } + int32_t res = params->loader->bigNumExpMod(&(params->epkPeer), &(params->eskSelf), params->largePrimeNumHex, + sharedSecret); + if (res != HC_SUCCESS) { + LOGE("BigNumExpMod for sharedSecret failed."); + } + return res; +} \ No newline at end of file diff --git a/services/module/src/protocol/pake_protocol/pake_protocol_dl_mock/pake_protocol_dl_mock.c b/services/module/src/protocol/pake_protocol/pake_protocol_dl_mock/pake_protocol_dl_mock.c new file mode 100644 index 0000000..6f00055 --- /dev/null +++ b/services/module/src/protocol/pake_protocol/pake_protocol_dl_mock/pake_protocol_dl_mock.c @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "pake_protocol_dl.h" +#include "common_defs.h" +#include "hc_log.h" +#include "protocol_common.h" + +uint32_t GetPakeDlAlg() +{ + return UNSUPPORTED_ALG; +} + +int32_t GenerateDlPakeParams(PakeBaseParams *params, const Uint8Buff *secret) +{ + (void)params; + (void)secret; + LOGE("PAKE-DL unsupported."); + return HC_ERROR; +} + +int32_t GenerateDlSharedSecret(PakeBaseParams *params, Uint8Buff *sharedSecret) +{ + (void)params; + (void)sharedSecret; + LOGE("PAKE-DL unsupported."); + return HC_ERROR; +} \ No newline at end of file diff --git a/services/module/src/protocol/pake_protocol/pake_protocol_ec/pake_protocol_ec.c b/services/module/src/protocol/pake_protocol/pake_protocol_ec/pake_protocol_ec.c new file mode 100644 index 0000000..a42e65b --- /dev/null +++ b/services/module/src/protocol/pake_protocol/pake_protocol_ec/pake_protocol_ec.c @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "pake_protocol_ec.h" +#include "hc_log.h" +#include "module_common.h" + +#define PAKE_PRIVATE_KEY_ANDMASK_HIGH 0xF8 +#define PAKE_PRIVATE_KEY_ANDMASK_LOW 0x7F +#define PAKE_PRIVATE_KEY_ORMASK_LOW 0x40 + +uint32_t GetPakeEcAlg() +{ + return EC_SPEKE; +} + +static int32_t GenerateEsk(PakeBaseParams *params) +{ + int32_t res = params->loader->generateRandom(&(params->eskSelf)); + if (res != HC_SUCCESS) { + LOGE("CURVE_25519: GenerateRandom for eskSelf failed, res: %d.", res); + FreeAndCleanKey(¶ms->eskSelf); + return res; + } + params->eskSelf.val[PAKE_EC_KEY_LEN - 1] &= PAKE_PRIVATE_KEY_ANDMASK_HIGH; + params->eskSelf.val[0] &= PAKE_PRIVATE_KEY_ANDMASK_LOW; + params->eskSelf.val[0] |= PAKE_PRIVATE_KEY_ORMASK_LOW; + return res; +} + +static int32_t InitEcPakeParams(PakeBaseParams *params) +{ + params->eskSelf.length = PAKE_EC_KEY_LEN; + params->innerKeyLen = PAKE_EC_KEY_LEN; + int32_t res = InitSingleParam(&(params->eskSelf), params->eskSelf.length); + if (res != HC_SUCCESS) { + LOGE("InitSingleParam for eskSelf failed, res: %d.", res); + return res; + } + res = InitSingleParam(&(params->epkSelf), params->innerKeyLen); + if (res != HC_SUCCESS) { + LOGE("InitSingleParam for epkSelf failed, res: %d.", res); + return res; + } + res = InitSingleParam(&(params->base), params->innerKeyLen); + if (res != HC_SUCCESS) { + LOGE("InitSingleParam for base failed, res: %d.", res); + return res; + } + return res; +} + +int32_t GenerateEcPakeParams(PakeBaseParams *params, Uint8Buff *secret) +{ + if (params->curveType == CURVE_256) { + LOGE("Unsupport curve type."); + return HC_ERROR; + } + + int32_t res = InitEcPakeParams(params); + if (res != HC_SUCCESS) { + LOGE("InitEcPakeParams failed, res: %d.", res); + goto err; + } + + res = GenerateEsk(params); + if (res != HC_SUCCESS) { + LOGE("GenerateEsk failed, res: %d.", res); + goto err; + } + + res = params->loader->hashToPoint(secret, X25519, ¶ms->base); + if (res != HC_SUCCESS) { + LOGE("HashToPoint from secret to base failed, res: %d.", res); + goto err; + } + + res = params->loader->computePublicKey(¶ms->eskSelf, ¶ms->base, X25519, ¶ms->epkSelf); + if (res != HC_SUCCESS) { + LOGE("ComputePublicKey failed, res: %d.", res); + goto err; + } + return res; +err: + FreeAndCleanKey(¶ms->eskSelf); + FreeAndCleanKey(¶ms->base); + return res; +} + +int32_t GenerateEcSharedSecret(PakeBaseParams *params, Uint8Buff *sharedSecret) +{ + if (params->curveType == CURVE_256) { + LOGE("Unsupport curve type."); + return HC_ERROR; + } + + KeyBuff eskSelfBuff = { params->eskSelf.val, params->eskSelf.length, false }; + KeyBuff epkPeerBuff = { params->epkPeer.val, params->epkPeer.length, false }; + int32_t res = params->loader->agreeSharedSecret(&eskSelfBuff, &epkPeerBuff, X25519, sharedSecret); + if (res != HC_SUCCESS) { + LOGE("AgreeSharedSecret failed, res: %d.", res); + return res; + } + + return res; +} \ No newline at end of file diff --git a/services/module/src/protocol/pake_protocol/pake_protocol_ec_mock/pake_protocol_ec_mock.c b/services/module/src/protocol/pake_protocol/pake_protocol_ec_mock/pake_protocol_ec_mock.c new file mode 100644 index 0000000..aedbea4 --- /dev/null +++ b/services/module/src/protocol/pake_protocol/pake_protocol_ec_mock/pake_protocol_ec_mock.c @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "pake_protocol_ec.h" +#include "common_defs.h" +#include "hc_log.h" +#include "protocol_common.h" + +uint32_t GetPakeEcAlg() +{ + return UNSUPPORTED_ALG; +} + +int32_t GenerateEcPakeParams(PakeBaseParams *params, Uint8Buff *secret) +{ + (void)params; + (void)secret; + LOGE("PAKE-EC unsupported."); + return HC_ERROR; +} + +int32_t GenerateEcSharedSecret(PakeBaseParams *params, Uint8Buff *sharedSecret) +{ + (void)params; + (void)sharedSecret; + LOGE("PAKE-EC unsupported."); + return HC_ERROR; +} \ No newline at end of file diff --git a/services/module/src/protocol/protocol_common.c b/services/module/src/protocol/protocol_common.c new file mode 100644 index 0000000..dd90210 --- /dev/null +++ b/services/module/src/protocol/protocol_common.c @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "protocol_common.h" +#include "common_defs.h" +#include "hc_types.h" +#include "securec.h" + +void FreeAndCleanKey(Uint8Buff *key) +{ + if (key == NULL || key->val == NULL) { + return; + } + (void)memset_s(key->val, key->length, 0, key->length); + HcFree(key->val); + key->val = NULL; + key->length = 0; +} \ No newline at end of file diff --git a/services/module/src/tcis_module_mock/tcis_module_mock.c b/services/module/src/tcis_module_mock/tcis_module_mock.c new file mode 100644 index 0000000..29040c1 --- /dev/null +++ b/services/module/src/tcis_module_mock/tcis_module_mock.c @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "tcis_module.h" + +bool IsTcisSupported() +{ + return false; +} + +AuthModuleBase *CreateTcisModule() +{ + return NULL; +} \ No newline at end of file diff --git a/services/module/src/version_util.c b/services/module/src/version_util.c new file mode 100644 index 0000000..8e4a0ee --- /dev/null +++ b/services/module/src/version_util.c @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "version_util.h" +#include "common_util.h" +#include "hc_log.h" +#include "hc_types.h" +#include "protocol_common.h" +#include "securec.h" + +static const char *Split(char *str, char delim, int *next) +{ + int len = strlen(str); + for (int i = 0; i < len; i++) { + if (str[i] == delim) { + *next = *next + i + 1; + str[i] = '\0'; + return str; + } + } + return str; +} + +int32_t StringToVersion(const char* verStr, uint32_t len, VersionStruct* version) +{ + CHECK_PTR_RETURN_ERROR_CODE(version, "version"); + CHECK_PTR_RETURN_ERROR_CODE(verStr, "verStr"); + if (*(verStr + len) != '\0') { + return HC_ERR_INVALID_PARAMS; + } + + const char *subVer = NULL; + int next = 0; + + char *verStrTmp = (char *)HcMalloc(len + 1, 0); + if (verStrTmp == NULL) { + LOGE("Malloc verStrTmp failed."); + return HC_ERR_ALLOC_MEMORY; + } + if (memcpy_s(verStrTmp, len + 1, verStr, len) != EOK) { + LOGE("Memcpy verStrTmp failed."); + HcFree(verStrTmp); + return HC_ERR_MEMORY_COPY; + } + + subVer = Split(verStrTmp, '.', &next); + if (subVer == NULL) { + goto err; + } + version->first = (uint32_t)strtoul(subVer, NULL, DEC); + + subVer = Split(verStrTmp + next, '.', &next); + if (subVer == NULL) { + goto err; + } + version->second = (uint32_t)strtoul(subVer, NULL, DEC); + + subVer = Split(verStrTmp + next, '.', &next); + if (subVer == NULL) { + goto err; + } + version->third = (uint32_t)strtoul(subVer, NULL, DEC); + + HcFree(verStrTmp); + return HC_SUCCESS; +err: + LOGE("Split failed"); + HcFree(verStrTmp); + return HC_ERR_NULL_PTR; +} + +int32_t VersionToString(const VersionStruct *version, char *verStr, uint32_t len) +{ + CHECK_PTR_RETURN_ERROR_CODE(version, "version"); + CHECK_PTR_RETURN_ERROR_CODE(verStr, "verStr"); + + char tmpStr[TMP_VERSION_STR_LEN] = { 0 }; + if (sprintf_s(tmpStr, TMP_VERSION_STR_LEN, "%d.%d.%d", version->first, version->second, version->third) == -1) { + return HC_ERROR; + } + + if (memcpy_s(verStr, len, tmpStr, strlen(tmpStr) + 1) != 0) { + return HC_ERR_MEMORY_COPY; + } + + return HC_SUCCESS; +} + +int32_t AddSingleVersionToJson(CJson *jsonObj, const VersionStruct *version) +{ + CHECK_PTR_RETURN_ERROR_CODE(jsonObj, "jsonObj"); + CHECK_PTR_RETURN_ERROR_CODE(version, "version"); + + char versionStr[TMP_VERSION_STR_LEN] = { 0 }; + int32_t ret = VersionToString(version, versionStr, TMP_VERSION_STR_LEN); + if (ret != HC_SUCCESS) { + return HC_ERROR; + } + + CJson *sendToPeer = GetObjFromJson(jsonObj, FIELD_SEND_TO_PEER); + if (sendToPeer == NULL) { + LOGD("There is not sendToPeer in json."); + return HC_SUCCESS; + } + if (AddStringToJson(sendToPeer, FIELD_GROUP_AND_MODULE_VERSION, versionStr) != HC_SUCCESS) { + LOGE("Add group and module version to sendToPeer failed."); + return HC_ERR_JSON_ADD; + } + return HC_SUCCESS; +} + +int32_t GetSingleVersionFromJson(const CJson* jsonObj, VersionStruct *version) +{ + CHECK_PTR_RETURN_ERROR_CODE(jsonObj, "jsonObj"); + CHECK_PTR_RETURN_ERROR_CODE(version, "version"); + + const char *versionStr = GetStringFromJson(jsonObj, FIELD_GROUP_AND_MODULE_VERSION); + CHECK_PTR_RETURN_ERROR_CODE(versionStr, "versionStr"); + + int32_t ret = StringToVersion(versionStr, strlen(versionStr), version); + if (ret != HC_SUCCESS) { + return HC_ERROR; + } + return HC_SUCCESS; +} + +void InitGroupAndModuleVersion(VersionStruct *version) +{ + if (version == NULL) { + LOGE("version is invalid."); + return; + } + version->first = VERSION_FIRST_BIT; + version->second = 0; + version->third = 0; +} \ No newline at end of file diff --git a/services/session/inc/auth_session/auth_session_client.h b/services/session/inc/auth_session/auth_session_client.h new file mode 100644 index 0000000..973de0c --- /dev/null +++ b/services/session/inc/auth_session/auth_session_client.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef AUTH_SESSION_CLIENT_H +#define AUTH_SESSION_CLIENT_H + +#include "auth_session_common.h" + +Session *CreateClientAuthSession(CJson *param, const DeviceAuthCallback *callback); + +#endif diff --git a/services/session/inc/auth_session/auth_session_common.h b/services/session/inc/auth_session/auth_session_common.h new file mode 100644 index 0000000..f05505c --- /dev/null +++ b/services/session/inc/auth_session/auth_session_common.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef AUTH_SESSION_COMMON_H +#define AUTH_SESSION_COMMON_H + +#include "auth_session_common_defines.h" +#include "common_defs.h" +#include "database_manager.h" + +void InformLocalAuthError(const CJson *param, const DeviceAuthCallback *callback); +void InformPeerAuthError(const CJson *param, const DeviceAuthCallback *callback); +int32_t InformAuthError(AuthSession *session, const CJson *out, int errorCode); +int32_t GetAuthParamsList(const CJson *param, ParamsVec *authParamsVec); +int32_t ProcessTaskStatusForAuth(const AuthSession *session, const CJson *param, CJson *out, int32_t status); +int32_t CreateAndProcessTask(AuthSession *session, CJson *paramInSession, CJson *out, int32_t *status); +void ProcessDeviceLevel(const CJson *receiveData, CJson *authParam); +void DestroyAuthSession(Session *session); +void DeleteCachedData(CJson *paramInSession); +int32_t GetGroupAuthType(int32_t authForm); +void CreateAuthParamsVec(ParamsVec *vec); +void DestroyAuthParamsVec(ParamsVec *vec); +int32_t ReturnSessionKey(int64_t requestId, const CJson *authParam, + const CJson *out, const DeviceAuthCallback *callback); + +#endif diff --git a/services/session/inc/auth_session/auth_session_server.h b/services/session/inc/auth_session/auth_session_server.h new file mode 100644 index 0000000..d65fbde --- /dev/null +++ b/services/session/inc/auth_session/auth_session_server.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef AUTH_SESSION_SERVER_H +#define AUTH_SESSION_SERVER_H + +#include "auth_session_common_defines.h" +#include "device_auth.h" +#include "json_utils.h" + +#define INDEX_OF_PARAMS_FOR_TASK 1 +#define LIST_SIZE_ONE 1 + +Session *CreateServerAuthSession(CJson *param, const DeviceAuthCallback *callback); + +#endif diff --git a/services/session/inc/auth_session/auth_session_util.h b/services/session/inc/auth_session/auth_session_util.h new file mode 100644 index 0000000..312941f --- /dev/null +++ b/services/session/inc/auth_session/auth_session_util.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef AUTH_SESSION_UTIL_H +#define AUTH_SESSION_UTIL_H + +#include +#include "base_group_auth.h" +#include "device_auth.h" +#include "json_utils.h" + + +int32_t GetGroupAuth(int32_t groupAuthType, BaseGroupAuth **groupAuthHandle); +int32_t GetAuthModuleType(const CJson *in); +int32_t GetInfoHash(const uint8_t *info, uint32_t infoLen, char *str, uint32_t strLen); + +#endif diff --git a/services/session/inc/auth_session_common_defines.h b/services/session/inc/auth_session_common_defines.h new file mode 100644 index 0000000..2c585eb --- /dev/null +++ b/services/session/inc/auth_session_common_defines.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef AUTH_SESSION_COMMON_DEFINES_H +#define AUTH_SESSION_COMMON_DEFINES_H + +#include "base_session.h" +#include "device_auth.h" +#include "hc_vector.h" + +DECLARE_HC_VECTOR(ParamsVec, void*) + +typedef struct { + Session base; + int curTaskId; + ParamsVec paramsList; + uint32_t currentIndex; +} AuthSession; + +typedef enum { + INVALID_GROUP_AUTH_TYPE = -1, + ACCOUNT_UNRELATED_GROUP_AUTH_TYPE, + ACCOUNT_RELATED_GROUP_AUTH_TYPE, +} GroupAuthType; + +#define ALL_GROUP_TYPE 0 +#define ANY_GROUP_VISIBILITY -2 +#define MIN_KEY_LENGTH 16 +#define MAX_KEY_LENGTH 1024 + +#endif diff --git a/services/session/inc/auth_session_common_util.h b/services/session/inc/auth_session_common_util.h new file mode 100644 index 0000000..98628bf --- /dev/null +++ b/services/session/inc/auth_session_common_util.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef AUTH_SESSION_COMMON_UTIL_H +#define AUTH_SESSION_COMMON_UTIL_H + +#include +#include "device_auth.h" +#include "json_utils.h" + +char *GetServerConfirmation(const CJson *paramsFromClient, const CJson *reqParam, + const DeviceAuthCallback *callback); +int32_t GetGeneralReqParams(const CJson *receiveData, CJson *reqParam); + +#endif diff --git a/services/session/inc/auth_session_lite/auth_session_client_lite.h b/services/session/inc/auth_session_lite/auth_session_client_lite.h new file mode 100644 index 0000000..e5285e1 --- /dev/null +++ b/services/session/inc/auth_session_lite/auth_session_client_lite.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef AUTH_SESSION_CLIENT_LITE_H +#define AUTH_SESSION_CLIENT_LITE_H + +#include "auth_session_common_lite.h" + +Session *CreateClientAuthSessionLite(CJson *in, const DeviceAuthCallback *callback); + +#endif diff --git a/services/session/inc/auth_session_lite/auth_session_common_lite.h b/services/session/inc/auth_session_lite/auth_session_common_lite.h new file mode 100644 index 0000000..062ff6b --- /dev/null +++ b/services/session/inc/auth_session_lite/auth_session_common_lite.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef AUTH_SESSION_COMMON_LITE_H +#define AUTH_SESSION_COMMON_LITE_H + +#include "base_session.h" +#include "common_defs.h" +#include "json_utils.h" +#include "device_auth.h" + +typedef struct AuthSessionLiteT { + Session base; + int curTaskId; + CJson *authParams; +} AuthSessionLite; + +int32_t ReturnTransmitDataLite(const AuthSessionLite *session, CJson *out); +void InformLocalAuthErrorLite(const CJson *authParam, const DeviceAuthCallback *callback); +void InformPeerAuthErrorLite(const CJson *in, const DeviceAuthCallback *callback); +void InformAuthErrorLite(const CJson *in, const DeviceAuthCallback *callback, const CJson *out, int errorCode); +int32_t CreateAndProcessLiteTask(AuthSessionLite *session, CJson *out, int32_t *status); +int32_t ProcessLiteTaskStatusForAuth(const AuthSessionLite *session, CJson *out, int32_t status); +void DestroyAuthSessionLite(Session *session); +AuthSessionLite *InitAuthSessionLite(CJson *param, const DeviceAuthCallback *callback); + +#endif diff --git a/services/session/inc/auth_session_lite/auth_session_server_lite.h b/services/session/inc/auth_session_lite/auth_session_server_lite.h new file mode 100644 index 0000000..99822d9 --- /dev/null +++ b/services/session/inc/auth_session_lite/auth_session_server_lite.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef AUTH_SESSION_SERVER_LITE_H +#define AUTH_SESSION_SERVER_LITE_H + +#include "auth_session_common_lite.h" + +Session *CreateServerAuthSessionLite(CJson *in, const DeviceAuthCallback *callback); + +#endif diff --git a/services/session/inc/base_session.h b/services/session/inc/base_session.h new file mode 100644 index 0000000..381f25f --- /dev/null +++ b/services/session/inc/base_session.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BASE_SESSION_H +#define BASE_SESSION_H + +#include +#include +#include "device_auth.h" +#include "json_utils.h" + +typedef struct SessionT { + int (*process)(struct SessionT *, CJson *); + void (*destroy)(struct SessionT *); + const DeviceAuthCallback *callback; + int type; + int64_t sessionId; + int64_t createTime; +} Session; + +typedef enum SessionTypeValueT { + TYPE_CLIENT_BIND_SESSION = 1, + TYPE_SERVER_BIND_SESSION, + TYPE_CLIENT_AUTH_SESSION, + TYPE_SERVER_AUTH_SESSION, + TYPE_CLIENT_BIND_SESSION_LITE, + TYPE_SERVER_BIND_SESSION_LITE, + TYPE_CLIENT_AUTH_SESSION_LITE, + TYPE_SERVER_AUTH_SESSION_LITE, + TYPE_CLIENT_KEY_AGREE_SESSION, + TYPE_SERVER_KEY_AGREE_SESSION +} SessionTypeValue; + +#endif diff --git a/services/session/inc/bind_session/bind_session_client.h b/services/session/inc/bind_session/bind_session_client.h new file mode 100644 index 0000000..caa0ad4 --- /dev/null +++ b/services/session/inc/bind_session/bind_session_client.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BIND_SESSION_CLIENT_H +#define BIND_SESSION_CLIENT_H + +#include "bind_session_common.h" + +Session *CreateClientBindSession(CJson *jsonParams, const DeviceAuthCallback *callback); + +#endif diff --git a/services/session/inc/bind_session/bind_session_common.h b/services/session/inc/bind_session/bind_session_common.h new file mode 100644 index 0000000..237a49b --- /dev/null +++ b/services/session/inc/bind_session/bind_session_common.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BIND_SESSION_COMMON_H +#define BIND_SESSION_COMMON_H + +#include "base_session.h" +#include "common_defs.h" +#include "hc_types.h" + +typedef struct { + Session base; + void (*onChannelOpened)(Session *, int64_t channelId, int64_t requestId); + void (*onConfirmationReceived)(Session *, CJson *returnData); + int curTaskId; + int operationCode; + ChannelType channelType; + bool isWaiting; + int64_t requestId; + int64_t channelId; + CJson *params; +} BindSession; + +void DestroyBindSession(Session *session); + +/* session interfaces */ +int32_t SendBindSessionData(const BindSession *session, const CJson *out); +void InformPeerProcessErrorIfNeed(bool isModuleError, int32_t errorCode, const BindSession *session); +void InformPeerModuleErrorIfNeed(CJson *out, const BindSession *session); +void InitBindSession(int bindType, int operationCode, int64_t requestId, const DeviceAuthCallback *callback, + BindSession *session); +int32_t CreateAndProcessModule(BindSession *session, const CJson *in, CJson *out); +int32_t ProcessModule(const BindSession *session, const CJson *in, CJson *out, int *status); +int32_t AddInfoToSendData(bool isNeedCompatibleInfo, const BindSession *session, CJson *data); +int32_t GenerateBasicModuleParams(bool isClient, BindSession *session, CJson *moduleParams); +int32_t GenerateBindParams(int isClient, const CJson *jsonParams, BindSession *session); +bool NeedCreateGroup(int isClient, int operationCode); +bool NeedForceDelete(const BindSession *session); +int32_t ForceUnbindDevice(const BindSession *session); +#endif diff --git a/services/session/inc/bind_session/bind_session_server.h b/services/session/inc/bind_session/bind_session_server.h new file mode 100644 index 0000000..c875055 --- /dev/null +++ b/services/session/inc/bind_session/bind_session_server.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BIND_SESSION_SERVER_H +#define BIND_SESSION_SERVER_H + +#include "bind_session_common.h" + +Session *CreateServerBindSession(CJson *jsonParams, const DeviceAuthCallback *callback); + +#endif diff --git a/services/session/inc/bind_session_lite/bind_session_client_lite.h b/services/session/inc/bind_session_lite/bind_session_client_lite.h new file mode 100644 index 0000000..168d5b8 --- /dev/null +++ b/services/session/inc/bind_session_lite/bind_session_client_lite.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BIND_SESSION_CLIENT_LITE_H +#define BIND_SESSION_CLIENT_LITE_H + +#include "bind_session_common_lite.h" + +Session *CreateLiteClientBindSession(CJson *jsonParams, const DeviceAuthCallback *callback); + +#endif diff --git a/services/session/inc/bind_session_lite/bind_session_common_lite.h b/services/session/inc/bind_session_lite/bind_session_common_lite.h new file mode 100644 index 0000000..e471072 --- /dev/null +++ b/services/session/inc/bind_session_lite/bind_session_common_lite.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BIND_SESSION_COMMON_LITE_H +#define BIND_SESSION_COMMON_LITE_H + +#include "base_session.h" +#include "common_defs.h" +#include "hc_types.h" + +typedef struct { + Session base; + void (*onChannelOpened)(Session *, int64_t channelId, int64_t requestId); + void (*onConfirmationReceived)(Session *, CJson *returnData); + int curTaskId; + int operationCode; + ChannelType channelType; + bool isWaiting; + int64_t requestId; + int64_t channelId; + CJson *params; +} LiteBindSession; + +void InitLiteBindSession(int bindType, int operationCode, int64_t requestId, LiteBindSession *session, + const DeviceAuthCallback *callback); +void DestroyLiteBindSession(Session *session); +void LiteInformPeerErrorIfNeed(bool isNeedInform, int32_t errorCode, LiteBindSession *session); +int32_t LiteSaveReceivedData(LiteBindSession *session, const CJson *jsonParams); +int32_t LitePrepareAndSendData(LiteBindSession *session, bool *isNeedInform); +#endif diff --git a/services/session/inc/bind_session_lite/bind_session_server_lite.h b/services/session/inc/bind_session_lite/bind_session_server_lite.h new file mode 100644 index 0000000..4d09411 --- /dev/null +++ b/services/session/inc/bind_session_lite/bind_session_server_lite.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BIND_SESSION_SERVER_LITE_H +#define BIND_SESSION_SERVER_LITE_H + +#include "bind_session_common_lite.h" + +Session *CreateLiteServerBindSession(CJson *jsonParams, const DeviceAuthCallback *callback); + +#endif diff --git a/services/session/inc/key_agree_session/key_agree_session_client.h b/services/session/inc/key_agree_session/key_agree_session_client.h new file mode 100644 index 0000000..b756fa5 --- /dev/null +++ b/services/session/inc/key_agree_session/key_agree_session_client.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef KEY_AGREE_SESSION_CLIENT_H +#define KEY_AGREE_SESSION_CLIENT_H + +#include "key_agree_session_common.h" + +Session *CreateClientKeyAgreeSession(CJson *jsonParams, const DeviceAuthCallback *callback); + +#endif diff --git a/services/session/inc/key_agree_session/key_agree_session_common.h b/services/session/inc/key_agree_session/key_agree_session_common.h new file mode 100644 index 0000000..77df6af --- /dev/null +++ b/services/session/inc/key_agree_session/key_agree_session_common.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef KEY_AGREE_SESSION_COMMON_H +#define KEY_AGREE_SESSION_COMMON_H + +#include "base_session.h" +#include "common_defs.h" +#include "hc_types.h" + +typedef struct { + Session base; + void (*onChannelOpened)(Session *, int64_t channelId, int64_t requestId); + void (*onConfirmationReceived)(Session *, CJson *returnData); + int curTaskId; + int operationCode; + ChannelType channelType; + bool isWaiting; + int64_t requestId; + int64_t channelId; + CJson *params; +} KeyAgreeSession; + +void InitKeyAgreeSession(int bindType, int operationCode, int64_t requestId, KeyAgreeSession *session, + const DeviceAuthCallback *callback); +void DestroyKeyAgreeSession(Session *session); +void InformPeerKeyAgreeErrorIfNeed(bool isNeedInform, int32_t errorCode, KeyAgreeSession *session); +int32_t SaveReceivedKeyAgreeData(KeyAgreeSession *session, const CJson *jsonParams); +int32_t PrepareAndSendKeyAgreeData(KeyAgreeSession *session, bool *isNeedInform); +#endif diff --git a/services/session/inc/key_agree_session/key_agree_session_server.h b/services/session/inc/key_agree_session/key_agree_session_server.h new file mode 100644 index 0000000..16a6a02 --- /dev/null +++ b/services/session/inc/key_agree_session/key_agree_session_server.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef KEY_AGREE_SESSION_SERVER_H +#define KEY_AGREE_SESSION_SERVER_H + +#include "key_agree_session_common.h" + +Session *CreateServerKeyAgreeSession(CJson *jsonParams, const DeviceAuthCallback *callback); + +#endif diff --git a/services/session/inc/session_common.h b/services/session/inc/session_common.h new file mode 100644 index 0000000..297aac3 --- /dev/null +++ b/services/session/inc/session_common.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SESSION_COMMON_H +#define SESSION_COMMON_H + +#include +#include "json_utils.h" + +int GenerateSessionOrTaskId(int64_t *id); +#endif \ No newline at end of file diff --git a/services/session/inc/session_manager.h b/services/session/inc/session_manager.h new file mode 100644 index 0000000..b8b5369 --- /dev/null +++ b/services/session/inc/session_manager.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SESSION_MANAGER_H +#define SESSION_MANAGER_H + +#include +#include "base_session.h" +#include "device_auth.h" + +#define BIND_TYPE 0 +#define AUTH_TYPE 1 + +void InitSessionManager(); +void DestroySessionManager(); + +bool IsRequestExist(int64_t requestId); + +int32_t CreateSession(int64_t requestId, SessionTypeValue sessionType, CJson *param, + const DeviceAuthCallback *callback); +int32_t ProcessSession(int64_t requestId, int32_t type, CJson *in); +void DestroySession(int64_t requestId); +void OnChannelOpened(int64_t requestId, int64_t channelId); +void OnConfirmationReceived(int64_t requestId, CJson *returnData); + +#endif diff --git a/services/session/src/auth_session/auth_session_client.c b/services/session/src/auth_session/auth_session_client.c new file mode 100644 index 0000000..9b7b02a --- /dev/null +++ b/services/session/src/auth_session/auth_session_client.c @@ -0,0 +1,218 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "auth_session_client.h" +#include "auth_session_common.h" +#include "auth_session_util.h" +#include "dev_auth_module_manager.h" +#include "hc_log.h" +#include "json_utils.h" +#include "session_common.h" + +static int ProcessClientAuthSession(Session *session, CJson *in); + +int32_t CheckInputAuthParams(const CJson *authParam) +{ + int32_t keyLen = DEFAULT_RETURN_KEY_LENGTH; + (void)GetIntFromJson(authParam, FIELD_KEY_LENGTH, &keyLen); + if ((keyLen < MIN_KEY_LENGTH) || (keyLen > MAX_KEY_LENGTH)) { + LOGE("The key length is invalid!"); + return HC_ERR_INVALID_PARAMS; + } + const char *pkgName = GetStringFromJson(authParam, FIELD_SERVICE_PKG_NAME); + if (pkgName == NULL) { + LOGE("Pkg name is null, the input is invalid!"); + return HC_ERR_INVALID_PARAMS; + } + return HC_SUCCESS; +} + +static AuthSession *InitClientAuthSession(const DeviceAuthCallback *callback, ParamsVec *authParamsVec) +{ + AuthSession *session = (AuthSession *)HcMalloc(sizeof(AuthSession), 0); + if (session == NULL) { + LOGE("Failed to allocate memory for session!"); + DestroyAuthParamsVec(authParamsVec); + return NULL; + } + session->base.process = ProcessClientAuthSession; + session->base.destroy = DestroyAuthSession; + session->base.callback = callback; + session->currentIndex = 0; + session->paramsList = *authParamsVec; + int32_t res = GenerateSessionOrTaskId(&session->base.sessionId); + if (res != HC_SUCCESS) { + LOGE("Failed to generate session id!"); + DestroyAuthSession((Session *)session); + return NULL; + } + return session; +} + +static int32_t ProcessClientAuthTask(AuthSession *session, int32_t moduleType, CJson *in, CJson *out) +{ + int32_t status = 0; + CJson *paramInSession = (session->paramsList).get(&(session->paramsList), session->currentIndex); + int32_t res = ProcessTask(session->curTaskId, in, out, &status, moduleType); + DeleteItemFromJson(in, FIELD_PAYLOAD); + if (res != HC_SUCCESS) { + DestroyTask(session->curTaskId, moduleType); + res = InformAuthError(session, out, res); + return res; + } + res = ProcessTaskStatusForAuth(session, paramInSession, out, status); + return res; +} + +static int32_t StartClientAuthTask(AuthSession *session) +{ + CJson *paramInSession = (session->paramsList).get(&(session->paramsList), session->currentIndex); + if (paramInSession == NULL) { + LOGE("Failed to get param in session!"); + return HC_ERR_NULL_PTR; + } + CJson *out = CreateJson(); + int32_t res; + int32_t status = 0; + do { + if (out == NULL) { + LOGE("Failed to create json!"); + res = HC_ERR_ALLOC_MEMORY; + break; + } + res = CreateAndProcessTask(session, paramInSession, out, &status); + } while (0); + if (res != HC_SUCCESS) { + DestroyTask(session->curTaskId, GetAuthModuleType(paramInSession)); + res = InformAuthError(session, out, res); + FreeJson(out); + LOGD("Start process client auth task, res = %d.", res); + return res; + } + res = ProcessTaskStatusForAuth(session, paramInSession, out, status); + FreeJson(out); + return res; +} + +int32_t CheckClientGroupAuthMsg(AuthSession *session, const CJson *in) +{ + int32_t GroupErrMsg = 0; + if (GetIntFromJson(in, FIELD_GROUP_ERROR_MSG, (int *)&GroupErrMsg) != HC_SUCCESS) { + return HC_SUCCESS; + } + CJson *outData = CreateJson(); + if (outData == NULL) { + LOGE("Failed to malloc for outData!"); + return HC_ERR_ALLOC_MEMORY; + } + if (AddIntToJson(outData, FIELD_GROUP_ERROR_MSG, GroupErrMsg) != HC_SUCCESS) { + LOGE("Failed to add info to outData!"); + FreeJson(outData); + return HC_ERR_JSON_FAIL; + } + if (InformAuthError(session, outData, HC_ERR_PEER_ERROR) != HC_SUCCESS) { + LOGE("Failed to inform auth error!"); + } + FreeJson(outData); + return HC_ERR_PEER_ERROR; +} + +static int32_t ProcessClientAuthSession(Session *session, CJson *in) +{ + LOGI("Begin process client authSession."); + if ((session == NULL) || (in == NULL)) { + LOGE("Invalid input params!"); + return HC_ERR_INVALID_PARAMS; + } + AuthSession *realSession = (AuthSession *)session; + CJson *paramInSession = (realSession->paramsList).get(&(realSession->paramsList), realSession->currentIndex); + if (paramInSession == NULL) { + LOGE("Failed to get param in session!"); + return HC_ERR_NULL_PTR; + } + ProcessDeviceLevel(in, paramInSession); + int32_t res = CheckClientGroupAuthMsg(realSession, in); + if (res != HC_SUCCESS) { + LOGE("Peer device's group has error, so we stop client auth session!"); + return res; + } + CJson *out = CreateJson(); + if (out == NULL) { + LOGE("Failed to create json for out!"); + InformLocalAuthError(paramInSession, realSession->base.callback); + InformPeerAuthError(paramInSession, realSession->base.callback); + return HC_ERR_ALLOC_MEMORY; + } + res = ProcessClientAuthTask(realSession, GetAuthModuleType(paramInSession), in, out); + ClearSensitiveStringInJson(out, FIELD_SESSION_KEY); + FreeJson(out); + if (res == FINISH) { + LOGI("End process client authSession, auth completed successfully."); + } + return res; +} + +static Session *CreateClientAuthSessionInner(CJson *param, const DeviceAuthCallback *callback) +{ + ParamsVec authParamsVec; + CreateAuthParamsVec(&authParamsVec); + AuthSession *session = NULL; + int32_t res = GetAuthParamsList(param, &authParamsVec); + if (res != HC_SUCCESS) { + LOGE("Failed to get auth param list!"); + DestroyAuthParamsVec(&authParamsVec); + InformLocalAuthError(param, callback); + return NULL; + } + if (authParamsVec.size(&authParamsVec) == 0) { + LOGE("No candidate auth group!"); + DestroyAuthParamsVec(&authParamsVec); + InformLocalAuthError(param, callback); + return NULL; + } + session = InitClientAuthSession(callback, &authParamsVec); + if (session == NULL) { + LOGE("Failed to initial session!"); + InformLocalAuthError(param, callback); + return NULL; + } + res = StartClientAuthTask(session); + if (res != HC_SUCCESS) { + DestroyAuthSession((Session *)session); + return NULL; + } + return (Session *)session; +} + +Session *CreateClientAuthSession(CJson *param, const DeviceAuthCallback *callback) +{ + Session *session = NULL; + if (CheckInputAuthParams(param) != HC_SUCCESS) { + LOGE("Invalid input params!"); + InformLocalAuthError(param, callback); + return NULL; + } + if (AddIntToJson(param, FIELD_OPERATION_CODE, AUTHENTICATE) != HC_SUCCESS) { + LOGE("Failed to add operation code to json!"); + InformLocalAuthError(param, callback); + return NULL; + } + session = CreateClientAuthSessionInner(param, callback); + if (session == NULL) { + LOGE("Failed to create client auth session!"); + return NULL; + } + return session; +} \ No newline at end of file diff --git a/services/session/src/auth_session/auth_session_common.c b/services/session/src/auth_session/auth_session_common.c new file mode 100644 index 0000000..cc7f5db --- /dev/null +++ b/services/session/src/auth_session/auth_session_common.c @@ -0,0 +1,831 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "auth_session_common.h" +#include "account_related_group_auth.h" +#include "account_unrelated_group_auth.h" +#include "alg_defs.h" +#include "auth_session_util.h" +#include "common_defs.h" +#include "common_util.h" +#include "dev_auth_module_manager.h" +#include "hc_log.h" +#include "json_utils.h" + +IMPLEMENT_HC_VECTOR(ParamsVec, void *, 1) + +static bool IsOldFormatParams(const CJson *param) +{ + int32_t authForm = AUTH_FORM_INVALID_TYPE; + (void)GetIntFromJson(param, FIELD_AUTH_FORM, &authForm); + int64_t uid = 0; + (void)GetByteFromJson(param, FIELD_USER_ID, (uint8_t *)&uid, sizeof(int64_t)); + bool isOldFormat = ((GetStringFromJson(param, FIELD_SELF_AUTH_ID) != NULL) || + (uid != 0L) || (authForm == AUTH_FORM_IDENTICAL_ACCOUNT)); + return isOldFormat; +} + +static int32_t UnifyOldFormatParams(const CJson *param, ParamsVec *paramsVec) +{ + LOGI("Unify old format parameters."); + CJson *oldFormatParams = DuplicateJson(param); + if (oldFormatParams == NULL) { + LOGE("Failed to create json for old form params!"); + return HC_ERR_JSON_FAIL; + } + int64_t uid = 0; + uint32_t groupIdLen = SHA256_LEN * BYTE_TO_HEX_OPER_LENGTH + 1; + char groupId[SHA256_LEN * BYTE_TO_HEX_OPER_LENGTH + 1] = { 0 }; + int32_t res = HC_SUCCESS; + do { + if (GetByteFromJson(param, FIELD_USER_ID, (uint8_t *)&uid, sizeof(int64_t)) != HC_SUCCESS) { + LOGI("No uid in auth param!"); + } + if (uid == 0L) { + break; + } + if (GetInfoHash((const uint8_t *)&uid, sizeof(int64_t), groupId, groupIdLen) != HC_SUCCESS) { + LOGE("Failed to get hash for groupId!"); + res = HC_ERR_HASH_FAIL; + break; + } + if (AddStringToJson(oldFormatParams, FIELD_GROUP_ID, groupId) != HC_SUCCESS) { + LOGE("Failed to add groupId to json params!"); + res = HC_ERR_JSON_FAIL; + break; + } + } while (0); + if (res != HC_SUCCESS) { + FreeJson(oldFormatParams); + return res; + } + paramsVec->pushBack(paramsVec, (const void **)&oldFormatParams); + return res; +} + +static bool IsGroupAvailable(const char *groupId, const char *pkgName) +{ + if (IsGroupAccessible(groupId, pkgName)) { + return true; + } + LOGI("%s don't have enough right for group: %s!", pkgName, groupId); + return false; +} + +static int32_t GroupTypeToAuthForm(int32_t groupType) +{ + int32_t authForm; + switch (groupType) { + case PEER_TO_PEER_GROUP: + case COMPATIBLE_GROUP: + authForm = AUTH_FORM_ACCOUNT_UNRELATED; + break; + case IDENTICAL_ACCOUNT_GROUP: + authForm = AUTH_FORM_IDENTICAL_ACCOUNT; + break; + case ACROSS_ACCOUNT_AUTHORIZE_GROUP: + authForm = AUTH_FORM_ACROSS_ACCOUNT; + break; + default: + LOGE("Invalid group type!"); + authForm = AUTH_FORM_INVALID_TYPE; + break; + } + return authForm; +} + +static int32_t AddGeneralParams(const char *groupId, int32_t groupType, const DeviceInfo *localAuthInfo, + CJson *paramsData) +{ + int32_t res = HC_SUCCESS; + int32_t authForm = GroupTypeToAuthForm(groupType); + const char *serviceType = StringGet(&(localAuthInfo->serviceType)); + do { + if (AddStringToJson(paramsData, FIELD_GROUP_ID, groupId) != HC_SUCCESS) { + LOGE("Failed to add groupId for client auth!"); + res = HC_ERR_JSON_FAIL; + break; + } + if (AddIntToJson(paramsData, FIELD_AUTH_FORM, authForm) != HC_SUCCESS) { + LOGE("Failed to add authFrom for client auth!"); + res = HC_ERR_JSON_FAIL; + break; + } + if ((groupType == COMPATIBLE_GROUP) && (serviceType != NULL)) { + if (AddStringToJson(paramsData, FIELD_SERVICE_TYPE, serviceType) != HC_SUCCESS) { + LOGE("Failed to add serviceType for client compatible group auth!"); + res = HC_ERR_JSON_FAIL; + break; + } + } else { + if (AddStringToJson(paramsData, FIELD_SERVICE_TYPE, groupId) != HC_SUCCESS) { + LOGE("Failed to add serviceType with groupId for client auth!"); + res = HC_ERR_JSON_FAIL; + break; + } + } + } while (0); + return res; +} + +static int32_t GetLocalDeviceInfoFromDatabase(const char *groupId, DeviceInfo *localAuthInfo) +{ + int32_t res; + char *localUdidStr = NULL; + if (GetLocalDevUdid(&localUdidStr) != HC_SUCCESS) { + LOGE("Failed to get local udid!"); + return HC_ERROR; + } + res = GetDeviceInfoForDevAuth(localUdidStr, groupId, localAuthInfo); + if (res != HC_SUCCESS) { + LOGE("Failed to get local device info from database!"); + } + DestroyUdid(&localUdidStr); + return res; +} + +static int32_t ExtractAndAddParams(const char *groupId, const GroupInfo *groupInfo, CJson *paramsData) +{ + int32_t res; + DeviceInfo *localAuthInfo = CreateDeviceInfoStruct(); + if (localAuthInfo == NULL) { + LOGE("Failed to allocate memory for peerAuthInfo!"); + return HC_ERR_ALLOC_MEMORY; + } + int32_t groupType = groupInfo->type; + int32_t authForm = GroupTypeToAuthForm(groupType); + do { + res = GetLocalDeviceInfoFromDatabase(groupId, localAuthInfo); + if (res != HC_SUCCESS) { + break; + } + res = AddGeneralParams(groupId, groupType, localAuthInfo, paramsData); + if (res != HC_SUCCESS) { + LOGE("Failed to add general params!"); + break; + } + BaseGroupAuth *groupAuth = NULL; + res = GetGroupAuth(GetGroupAuthType(authForm), &groupAuth); + if (res != HC_SUCCESS) { + LOGE("Failed to get group auth handle!"); + break; + } + res = groupAuth->fillDeviceAuthInfo(groupInfo, localAuthInfo, paramsData); + if (res != HC_SUCCESS) { + LOGE("Failed to fill device auth info!"); + break; + } + } while (0); + DestroyDeviceInfoStruct(localAuthInfo); + return res; +} + +static int32_t FillAuthParams(const CJson *param, const GroupInfoVec *vec, ParamsVec *paramsVec) +{ + const char *pkgName = GetStringFromJson(param, FIELD_SERVICE_PKG_NAME); + if (pkgName == NULL) { + LOGE("Pkg name is null, can't extract params from db!"); + return HC_ERR_INVALID_PARAMS; + } + uint32_t index; + void **ptr = NULL; + FOR_EACH_HC_VECTOR(*vec, index, ptr) { + if ((ptr == NULL) || (*ptr == NULL)) { + continue; + } + const GroupInfo *groupInfo = (GroupInfo *)(*ptr); + const char *groupId = StringGet(&(groupInfo->id)); + if (groupId == NULL) { + continue; + } + if (!IsGroupAvailable(groupId, pkgName)) { + continue; + } + CJson *paramsData = DuplicateJson(param); + if (paramsData == NULL) { + LOGE("Failed to duplicate auth param data!"); + return HC_ERR_JSON_FAIL; + } + if (ExtractAndAddParams(groupId, groupInfo, paramsData) == HC_SUCCESS) { + paramsVec->pushBack(paramsVec, (const void **)¶msData); + } + } + return HC_SUCCESS; +} + +static void GetCandidateGroupByOrder(const CJson *param, GroupQueryParams *queryParams, GroupInfoVec *vec) +{ + BaseGroupAuth *groupAuth = NULL; + if (GetGroupAuth(ACCOUNT_RELATED_GROUP_AUTH_TYPE, &groupAuth) == HC_SUCCESS) { + AccountRelatedGroupAuth *realGroupAuth = (AccountRelatedGroupAuth *)groupAuth; + realGroupAuth->getTcisCandidateGroup(param, queryParams, vec); + } + queryParams->type = PEER_TO_PEER_GROUP; + (void)GetJoinedGroupInfoVecByDevId(queryParams, vec); + queryParams->type = COMPATIBLE_GROUP; + (void)GetJoinedGroupInfoVecByDevId(queryParams, vec); +} + +static int32_t InitGroupQueryParams(const char *peerUdid, const char *peerAuthId, GroupQueryParams *queryParams) +{ + queryParams->type = ALL_GROUP_TYPE; + queryParams->visibility = ANY_GROUP_VISIBILITY; + if (peerUdid != NULL) { + queryParams->udid = (char *)HcMalloc(HcStrlen(peerUdid) + 1, 0); + if (queryParams->udid == NULL) { + LOGE("Failed to allocate memory for queryParams of udid!"); + return HC_ERR_ALLOC_MEMORY; + } + if (strcpy_s(queryParams->udid, HcStrlen(peerUdid) + 1, peerUdid) != HC_SUCCESS) { + LOGE("Failed to copy udid for queryParams!"); + HcFree(queryParams->udid); + queryParams->udid = NULL; + return HC_ERR_MEMORY_COPY; + } + } else if (peerAuthId != NULL) { + queryParams->authId = (char *)HcMalloc(HcStrlen(peerAuthId) + 1, 0); + if (queryParams->authId == NULL) { + LOGE("Failed to allocate memory for queryParams of authId!"); + return HC_ERR_ALLOC_MEMORY; + } + if (strcpy_s(queryParams->authId, HcStrlen(peerAuthId) + 1, peerAuthId) != HC_SUCCESS) { + LOGE("Failed to copy authId for queryParams!"); + HcFree(queryParams->authId); + queryParams->authId = NULL; + return HC_ERR_MEMORY_COPY; + } + } + return HC_SUCCESS; +} + +static void DestroyGroupQueryParams(const char *peerUdid, const char *peerAuthId, GroupQueryParams *queryParams) +{ + if (peerUdid != NULL) { + HcFree(queryParams->udid); + queryParams->udid = NULL; + } else if (peerAuthId != NULL) { + HcFree(queryParams->authId); + queryParams->authId = NULL; + } +} + +static void GetCandidateGroupInfo(const CJson *param, const char *peerUdid, + const char *peerAuthId, GroupInfoVec *vec) +{ + LOGI("No input of groupId, extract group info without groupId."); + bool deviceLevelFlag = false; + bool isClient = true; + (void)GetBoolFromJson(param, FIELD_IS_DEVICE_LEVEL, &deviceLevelFlag); + if (GetBoolFromJson(param, FIELD_IS_CLIENT, &isClient) != HC_SUCCESS) { + LOGE("Failed to get the value: isClient!"); + return; + } + GroupQueryParams queryParams = { 0 }; + if (InitGroupQueryParams(peerUdid, peerAuthId, &queryParams) != HC_SUCCESS) { + LOGE("Failed to init group query params!"); + return; + } + if (deviceLevelFlag && isClient) { + GetCandidateGroupByOrder(param, &queryParams, vec); + } else { + queryParams.visibility = GROUP_VISIBILITY_PUBLIC; + GetCandidateGroupByOrder(param, &queryParams, vec); + } + DestroyGroupQueryParams(peerUdid, peerAuthId, &queryParams); +} + +static void GetGroupInfoByGroupId(const char *groupId, const char *peerUdid, const char *peerAuthId, GroupInfoVec *vec) +{ + GroupInfo *entry = CreateGroupInfoStruct(); + if (entry == NULL) { + LOGE("Failed to create entry struct!"); + return; + } + int32_t res = HC_SUCCESS; + if (peerUdid != NULL) { + res = GetGroupEntry(groupId, peerUdid, entry); + } else { + if (IsTrustedDeviceInGroupByAuthId(groupId, peerAuthId)) { + res = GetGroupEntryByGroupId(groupId, entry); + } + } + if (res == HC_SUCCESS) { + vec->pushBackT(vec, (void *)entry); + } else { + LOGE("Failed to get group entry!"); + DestroyGroupInfoStruct(entry); + } +} + +static int32_t GetCandidateAuthInfo(const char *groupId, const CJson *param, ParamsVec *authParamsVec) +{ + const char *peerUdid = GetStringFromJson(param, FIELD_PEER_CONN_DEVICE_ID); + const char *peerAuthId = GetStringFromJson(param, FIELD_PEER_AUTH_ID); + if ((peerUdid == NULL) && (peerAuthId == NULL)) { + LOGE("Invalid input, peer udid and peer auth id are both null!"); + return HC_ERR_INVALID_PARAMS; + } + GroupInfoVec vec; + CreateGroupInfoVecStruct(&vec); + if (groupId == NULL) { + GetCandidateGroupInfo(param, peerUdid, peerAuthId, &vec); + } else { + GetGroupInfoByGroupId(groupId, peerUdid, peerAuthId, &vec); + } + if (vec.size(&vec) == 0) { + LOGE("No satisfied candidate group!"); + DestroyGroupInfoVecStruct(&vec); + return HC_ERR_NO_CANDIDATE_GROUP; + } + int32_t ret = FillAuthParams(param, &vec, authParamsVec); + DestroyGroupInfoVecStruct(&vec); + return ret; +} + +static int32_t AddGroupAuthTransmitData(const AuthSession *session, CJson *sendToPeer) +{ + ParamsVec list = session->paramsList; + CJson *authParam = list.get(&list, session->currentIndex); + if (authParam == NULL) { + LOGE("The json data in session is null!"); + return HC_ERR_NULL_PTR; + } + bool isDeviceLevel = false; + /* Disable device-level auth. */ + if (AddBoolToJson(sendToPeer, FIELD_IS_DEVICE_LEVEL, isDeviceLevel) != HC_SUCCESS) { + LOGE("Failed to add device level!"); + return HC_ERR_JSON_FAIL; + } + bool isClient = true; + if (GetBoolFromJson(authParam, FIELD_IS_CLIENT, &isClient)) { + LOGE("Failed to get isClient!"); + return HC_ERR_JSON_GET; + } + if (isClient && (session->currentIndex < (list.size(&list) - 1))) { + const char *altGroup = GetStringFromJson(list.get(&list, session->currentIndex + 1), FIELD_SERVICE_TYPE); + if ((altGroup != NULL) && (AddStringToJson(sendToPeer, FIELD_ALTERNATIVE, altGroup) != HC_SUCCESS)) { + LOGE("Failed to add alternative group!"); + return HC_ERR_JSON_FAIL; + } + } + return HC_SUCCESS; +} + +static int32_t ReturnTransmitData(const AuthSession *session, CJson *out) +{ + CJson *sendToPeer = GetObjFromJson(out, FIELD_SEND_TO_PEER); + if (sendToPeer == NULL) { + LOGI("The transmit data to peer is null!"); + return HC_ERR_JSON_GET; + } + CJson *authParam = (session->paramsList).get(&(session->paramsList), session->currentIndex); + if (authParam == NULL) { + LOGE("The json data in session is null!"); + return HC_ERR_NULL_PTR; + } + int64_t requestId = 0; + if (GetByteFromJson(authParam, FIELD_REQUEST_ID, (uint8_t *)&requestId, sizeof(int64_t)) != HC_SUCCESS) { + LOGE("Failed to get request id!"); + return HC_ERR_JSON_GET; + } + + int32_t ret = AddGroupAuthTransmitData(session, sendToPeer); + if (ret != HC_SUCCESS) { + LOGE("Failed to add extra data!"); + return ret; + } + char *outStr = PackJsonToString(sendToPeer); + if (outStr == NULL) { + LOGE("Failed to pack outStr for onTransmit!"); + return HC_ERR_ALLOC_MEMORY; + } + + const DeviceAuthCallback *callback = session->base.callback; + do { + if ((callback == NULL) || (callback->onTransmit == NULL)) { + LOGE("The callback for transmit is null!"); + ret = HC_ERR_TRANSMIT_FAIL; + break; + } + if (!callback->onTransmit(requestId, (uint8_t *)outStr, (uint32_t)strlen(outStr) + 1)) { + LOGE("Failed to transmit data to peer!"); + ret = HC_ERR_TRANSMIT_FAIL; + } + } while (0); + FreeJsonString(outStr); + return ret; +} + +int32_t GetAuthParamsList(const CJson *param, ParamsVec *authParamsVec) +{ + int32_t ret; + const char *groupId = GetStringFromJson(param, FIELD_GROUP_ID); + if (groupId == NULL) { + groupId = GetStringFromJson(param, FIELD_SERVICE_TYPE); + } + if (IsOldFormatParams(param)) { + LOGI("The input params' type is in old format!"); + ret = UnifyOldFormatParams(param, authParamsVec); + } else { + ret = GetCandidateAuthInfo(groupId, param, authParamsVec); + } + return ret; +} + +static void ReturnFinishData(const AuthSession *session, const CJson *out) +{ + if (out == NULL) { + LOGE("The return data is null!"); + return; + } + ParamsVec list = session->paramsList; + const CJson *authParam = list.get(&list, session->currentIndex); + if (authParam == NULL) { + LOGE("The json data in session is null!"); + return; + } + int64_t requestId = 0; + if (GetByteFromJson(authParam, FIELD_REQUEST_ID, (uint8_t *)&requestId, sizeof(int64_t)) != HC_SUCCESS) { + LOGE("Failed to get request id!"); + return; + } + int32_t authForm = AUTH_FORM_INVALID_TYPE; + if (GetIntFromJson(authParam, FIELD_AUTH_FORM, &authForm) != HC_SUCCESS) { + LOGE("Failed to get auth type!"); + return; + } + BaseGroupAuth *groupAuth = NULL; + if (GetGroupAuth(GetGroupAuthType(authForm), &groupAuth) == HC_SUCCESS) { + groupAuth->onFinish(requestId, authParam, out, session->base.callback); + } +} + +static int32_t ReturnErrorToLocalBySession(const AuthSession *session, int errorCode) +{ + ParamsVec list = session->paramsList; + CJson *authParam = list.get(&list, session->currentIndex); + int64_t requestId = 0; + int32_t authForm = 0; + if (authParam == NULL) { + LOGE("The json data in session is null!"); + return HC_ERR_NULL_PTR; + } + if (GetByteFromJson(authParam, FIELD_REQUEST_ID, (uint8_t *)&requestId, sizeof(int64_t)) != HC_SUCCESS) { + LOGE("Failed to add request id!"); + return HC_ERR_JSON_GET; + } + if (GetIntFromJson(authParam, FIELD_AUTH_FORM, &authForm) != HC_SUCCESS) { + LOGE("Failed to add auth form!"); + return HC_ERR_JSON_GET; + } + + BaseGroupAuth *groupAuth = NULL; + int32_t res = GetGroupAuth(GetGroupAuthType(authForm), &groupAuth); + if (res == HC_SUCCESS) { + groupAuth->onError(requestId, session, errorCode); + } + return res; +} + +static int32_t ReturnErrorToPeerBySession(const CJson *authParam, const DeviceAuthCallback *callback) +{ + int64_t requestId = 0; + if (GetByteFromJson(authParam, FIELD_REQUEST_ID, (uint8_t *)&requestId, sizeof(int64_t)) != HC_SUCCESS) { + LOGE("Failed to get request ID!"); + return HC_ERR_JSON_GET; + } + CJson *errorToPeer = CreateJson(); + if (errorToPeer == NULL) { + LOGE("Failed to allocate memory for errorToPeer!"); + return HC_ERR_ALLOC_MEMORY; + } + if (AddIntToJson(errorToPeer, FIELD_GROUP_ERROR_MSG, GROUP_ERR_MSG) != HC_SUCCESS) { + LOGE("Failed to add err message to return data!"); + FreeJson(errorToPeer); + return HC_ERR_JSON_FAIL; + } + char *errorToPeerStr = PackJsonToString(errorToPeer); + FreeJson(errorToPeer); + if (errorToPeerStr == NULL) { + LOGE("Failed to pack errorToPeer to string!"); + return HC_ERR_ALLOC_MEMORY; + } + + int32_t res = HC_SUCCESS; + do { + if ((callback == NULL) || (callback->onTransmit == NULL)) { + LOGE("The callback of onTransmit is null!"); + res = HC_ERR_NULL_PTR; + break; + } + if (!callback->onTransmit(requestId, (uint8_t *)errorToPeerStr, (uint32_t)strlen(errorToPeerStr) + 1)) { + LOGE("Failed to invoke onTransmit!"); + res = HC_ERR_TRANSMIT_FAIL; + break; + } + } while (0); + FreeJsonString(errorToPeerStr); + return res; +} + +static int32_t ReturnErrorToPeerByTask(const CJson *sendToPeer, const CJson *authParam, + const DeviceAuthCallback *callback) +{ + if (sendToPeer == NULL) { + LOGD("NO need to send data to peer!"); + return HC_SUCCESS; + } + int64_t requestId = 0; + if (GetByteFromJson(authParam, FIELD_REQUEST_ID, (uint8_t *)&requestId, sizeof(int64_t)) != HC_SUCCESS) { + LOGE("Failed to get request id!"); + return HC_ERR_JSON_FAIL; + } + char *sendToPeerStr = PackJsonToString(sendToPeer); + if (sendToPeerStr == NULL) { + LOGE("Failed to pack json to string!"); + return HC_ERR_ALLOC_MEMORY; + } + + int32_t res = HC_SUCCESS; + do { + if ((callback == NULL) || (callback->onTransmit == NULL)) { + LOGE("The callback of onTransmit is null!"); + res = HC_ERR_NULL_PTR; + break; + } + if (!callback->onTransmit(requestId, (uint8_t *)sendToPeerStr, (uint32_t)strlen(sendToPeerStr) + 1)) { + LOGE("Failed to invoke onTransmit!"); + res = HC_ERR_TRANSMIT_FAIL; + break; + } + } while (0); + FreeJsonString(sendToPeerStr); + return res; +} + +bool HasAlternativeAuthGroup(const AuthSession *session) +{ + if (session->currentIndex >= session->paramsList.size(&session->paramsList) - 1) { + return false; + } + return true; +} + +static int32_t ProcessNextGroupIfPossible(AuthSession *session) +{ + if (!HasAlternativeAuthGroup(session)) { + LOGD("There is no alternative auth group."); + return HC_ERR_NO_CANDIDATE_GROUP; + } + int32_t res; + session->currentIndex++; + CJson *paramInNextSession = (session->paramsList).get(&(session->paramsList), session->currentIndex); + if (paramInNextSession == NULL) { + LOGE("The json data in session is null!"); + return HC_ERR_NULL_PTR; + } + CJson *outNext = CreateJson(); + do { + if (outNext == NULL) { + LOGE("Failed to create json for outNext!"); + res = HC_ERR_ALLOC_MEMORY; + break; + } + int32_t status = 0; + res = CreateAndProcessTask(session, paramInNextSession, outNext, &status); + if (res != HC_SUCCESS) { + break; + } + res = ProcessTaskStatusForAuth(session, paramInNextSession, outNext, status); + } while (0); + if (res != HC_SUCCESS) { + DestroyTask(session->curTaskId, GetAuthModuleType(paramInNextSession)); + res = InformAuthError(session, outNext, res); + } + FreeJson(outNext); + return res; +} + +int32_t ReturnSessionKey(int64_t requestId, const CJson *authParam, + const CJson *out, const DeviceAuthCallback *callback) +{ + LOGI("Begin return session key."); + int32_t keyLen = DEFAULT_RETURN_KEY_LENGTH; + (void)GetIntFromJson(authParam, FIELD_KEY_LENGTH, &keyLen); + uint8_t *sessionKey = (uint8_t *)HcMalloc(keyLen, 0); + if (sessionKey == NULL) { + LOGE("Failed to allocate memory for sessionKey!"); + return HC_ERR_ALLOC_MEMORY; + } + + int32_t res = HC_SUCCESS; + do { + if (GetByteFromJson(out, FIELD_SESSION_KEY, sessionKey, keyLen) != HC_SUCCESS) { + LOGE("Failed to get sessionKey!"); + res = HC_ERR_JSON_GET; + break; + } + if ((callback == NULL) || (callback->onSessionKeyReturned == NULL)) { + LOGE("The callback of onSessionKeyReturned is null!"); + res = HC_ERR_INVALID_PARAMS; + break; + } + callback->onSessionKeyReturned(requestId, sessionKey, keyLen); + } while (0); + (void)memset_s(sessionKey, keyLen, 0, keyLen); + HcFree(sessionKey); + sessionKey = NULL; + LOGI("End return session key, res = %d.", res); + return res; +} + +void DeleteCachedData(CJson *paramInSession) +{ + DeleteItemFromJson(paramInSession, FIELD_PAYLOAD); + DeleteItemFromJson(paramInSession, FIELD_SELF_AUTH_ID); + DeleteItemFromJson(paramInSession, FIELD_PEER_AUTH_ID); + DeleteItemFromJson(paramInSession, FIELD_OPERATION_CODE); +} + +int32_t GetGroupAuthType(int32_t authForm) +{ + switch (authForm) { + case AUTH_FORM_ACCOUNT_UNRELATED: + return ACCOUNT_UNRELATED_GROUP_AUTH_TYPE; + case AUTH_FORM_IDENTICAL_ACCOUNT: + case AUTH_FORM_ACROSS_ACCOUNT: + return ACCOUNT_RELATED_GROUP_AUTH_TYPE; + default: + LOGE("Invalid authForm!"); + return INVALID_GROUP_AUTH_TYPE; + } +} + +int32_t InformAuthError(AuthSession *session, const CJson *out, int errorCode) +{ + ParamsVec list = session->paramsList; + CJson *paramInSession = list.get(&list, session->currentIndex); + if (paramInSession == NULL) { + LOGE("The json data in session is null!"); + return HC_ERR_NULL_PTR; + } + int32_t res; + if (out == NULL) { + res = ReturnErrorToPeerBySession(paramInSession, session->base.callback); + LOGI("Out data is null, so assemble error msg to peer by auth session."); + return res; + } + const CJson *sendToPeer = GetObjFromJson(out, FIELD_SEND_TO_PEER); + res = ReturnErrorToPeerByTask(sendToPeer, paramInSession, session->base.callback); + if (res != HC_SUCCESS) { + LOGE("Failed to return task's error msg to peer!"); + return res; + } + + res = ProcessNextGroupIfPossible(session); + if (res == HC_SUCCESS) { + return HC_SUCCESS; + } + + const char *altGroup = GetStringFromJson(paramInSession, FIELD_ALTERNATIVE); + if (altGroup == NULL) { + res = ReturnErrorToLocalBySession(session, errorCode); + } + return res; +} + +void ProcessDeviceLevel(const CJson *receiveData, CJson *authParam) +{ + bool receiveLevel = false; + bool authLevel = false; + (void)GetBoolFromJson(receiveData, FIELD_IS_DEVICE_LEVEL, &receiveLevel); + (void)GetBoolFromJson(authParam, FIELD_IS_DEVICE_LEVEL, &authLevel); + authLevel = receiveLevel && authLevel; + if (AddBoolToJson(authParam, FIELD_IS_DEVICE_LEVEL, authLevel) != HC_SUCCESS) { + LOGE("Failed to add device level to auth param!"); + return; + } +} + +int32_t ProcessTaskStatusForAuth(const AuthSession *session, const CJson *param, CJson *out, int32_t status) +{ + int32_t res = HC_SUCCESS; + switch (status) { + case IGNORE_MSG: + LOGI("Ignore this msg."); + break; + case CONTINUE: + res = ReturnTransmitData(session, out); + if (res != HC_SUCCESS) { + LOGE("Failed to transmit data to peer!"); + InformLocalAuthError(param, session->base.callback); + } + break; + case FINISH: + ReturnFinishData(session, out); + ClearSensitiveStringInJson(out, FIELD_SESSION_KEY); + res = FINISH; + break; + default: + LOGE("Invalid status after process task!"); + res = HC_ERR_INVALID_PARAMS; + break; + } + return res; +} + +int32_t CreateAndProcessTask(AuthSession *session, CJson *paramInSession, CJson *out, int32_t *status) +{ + int32_t moduleType = GetAuthModuleType(paramInSession); + const char *pkgName = GetStringFromJson(paramInSession, FIELD_SERVICE_PKG_NAME); + if (AddStringToJson(paramInSession, FIELD_PKG_NAME, pkgName) != HC_SUCCESS) { + LOGE("Failed to add pkg name to json!"); + return HC_ERR_JSON_FAIL; + } + session->curTaskId = 0; + int32_t res = CreateTask(&(session->curTaskId), paramInSession, out, moduleType); + if (res != HC_SUCCESS) { + LOGE("Failed to create task for auth!"); + return res; + } + res = ProcessTask(session->curTaskId, paramInSession, out, status, moduleType); + DeleteCachedData(paramInSession); + if (res != HC_SUCCESS) { + LOGE("Failed to process task for auth!"); + return res; + } + return HC_SUCCESS; +} + +void InformLocalAuthError(const CJson *authParam, const DeviceAuthCallback *callback) +{ + bool isClient = false; + (void)GetBoolFromJson(authParam, FIELD_IS_CLIENT, &isClient); + const char *altGroup = GetStringFromJson(authParam, FIELD_ALTERNATIVE); + if (!isClient && (altGroup != NULL)) { /* Server wait for next group auth. */ + LOGI("Server wait for next group auth."); + return; + } + int64_t requestId = 0; + if (GetByteFromJson(authParam, FIELD_REQUEST_ID, (uint8_t *)&requestId, sizeof(int64_t)) != HC_SUCCESS) { + LOGE("Failed to get request id!"); + return; + } + if ((callback != NULL) && (callback->onError != NULL)) { + callback->onError(requestId, AUTH_FORM_INVALID_TYPE, HC_ERR_CREATE_SESSION_FAIL, NULL); + } +} + +void InformPeerAuthError(const CJson *authParam, const DeviceAuthCallback *callback) +{ + if (ReturnErrorToPeerBySession(authParam, callback) != HC_SUCCESS) { + LOGE("Failed to return error to peer by session!"); + } +} + +void DestroyAuthSession(Session *session) +{ + if (session == NULL) { + return; + } + AuthSession *realSession = (AuthSession *)session; + CJson *paramInSession = (realSession->paramsList).get(&(realSession->paramsList), realSession->currentIndex); + if (paramInSession == NULL) { + LOGE("The json data in session is null!"); + return; + } + DestroyTask(realSession->curTaskId, GetAuthModuleType(paramInSession)); + + uint32_t index; + void **paramsData = NULL; + FOR_EACH_HC_VECTOR(realSession->paramsList, index, paramsData) { + if (paramsData != NULL) { + FreeJson((CJson *)*paramsData); + } + } + DESTROY_HC_VECTOR(ParamsVec, &(realSession->paramsList)) + HcFree(realSession); + realSession = NULL; +} + +void CreateAuthParamsVec(ParamsVec *vec) +{ + *vec = CREATE_HC_VECTOR(ParamsVec) +} + +void DestroyAuthParamsVec(ParamsVec *vec) +{ + DESTROY_HC_VECTOR(ParamsVec, vec) +} diff --git a/services/session/src/auth_session/auth_session_server.c b/services/session/src/auth_session/auth_session_server.c new file mode 100644 index 0000000..c50dd87 --- /dev/null +++ b/services/session/src/auth_session/auth_session_server.c @@ -0,0 +1,311 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "auth_session_server.h" +#include "auth_session_common.h" +#include "auth_session_common_util.h" +#include "auth_session_util.h" +#include "base_group_auth.h" +#include "common_defs.h" +#include "dev_auth_module_manager.h" +#include "device_auth_defines.h" +#include "hc_log.h" +#include "session_common.h" + +static int ProcessServerAuthSession(Session *session, CJson *in); + +static int32_t CombineServerParams(const CJson *confirmationJson, CJson *dataFromClient) +{ + int32_t authForm = AUTH_FORM_INVALID_TYPE; + if (GetIntFromJson(dataFromClient, FIELD_AUTH_FORM, &authForm) != HC_SUCCESS) { + LOGE("Failed to get auth form in data sent by client for the first time!"); + return HC_ERR_JSON_GET; + } + int32_t groupAuthType = GetGroupAuthType(authForm); + BaseGroupAuth *groupAuthHandle = NULL; + int32_t res = GetGroupAuth(groupAuthType, &groupAuthHandle); + if (res != HC_SUCCESS) { + LOGE("Failed to get group auth handle!"); + return res; + } + res = groupAuthHandle->combineServerConfirmParams(confirmationJson, dataFromClient); + if (res != HC_SUCCESS) { + LOGE("Failed to combine server confirm params!"); + } + return res; +} + +static int32_t GetAuthInfoForServer(CJson *dataFromClient, ParamsVec *authParamsVec) +{ + int32_t authForm = AUTH_FORM_INVALID_TYPE; + if (GetIntFromJson(dataFromClient, FIELD_AUTH_FORM, &authForm) != HC_SUCCESS) { + LOGE("Failed to get auth form!"); + return HC_ERR_JSON_FAIL; + } + int32_t groupAuthType = GetGroupAuthType(authForm); + BaseGroupAuth *groupAuthHandle = NULL; + int32_t res = GetGroupAuth(groupAuthType, &groupAuthHandle); + if (res != HC_SUCCESS) { + LOGE("Failed to get group auth handle!"); + return res; + } + res = groupAuthHandle->getAuthParamForServer(dataFromClient, authParamsVec); + return res; +} + +static char *StartServerRequest(const CJson *dataFromClient, const DeviceAuthCallback *callback) +{ + CJson *reqParam = CreateJson(); + if (reqParam == NULL) { + LOGE("Failed to create reqParam json!"); + return NULL; + } + char *confirmation = NULL; + do { + int32_t authForm = AUTH_FORM_INVALID_TYPE; + if (GetIntFromJson(dataFromClient, FIELD_AUTH_FORM, &authForm) != HC_SUCCESS) { + LOGE("Failed to get auth form!"); + break; + } + int32_t groupAuthType = GetGroupAuthType(authForm); + BaseGroupAuth *groupAuthHandle = NULL; + int32_t res = GetGroupAuth(groupAuthType, &groupAuthHandle); + if (res != HC_SUCCESS) { + LOGE("Failed to get group auth handle!"); + break; + } + res = groupAuthHandle->getReqParams(dataFromClient, reqParam); + if (res != HC_SUCCESS) { + LOGE("Failed to get request params!"); + break; + } + confirmation = GetServerConfirmation(dataFromClient, reqParam, callback); + } while (0); + FreeJson(reqParam); + return confirmation; +} + +static int32_t AddAuthParamByRequest(CJson *dataFromClient, const DeviceAuthCallback *callback, + ParamsVec *authParamsVec) +{ + char *confirmation = StartServerRequest(dataFromClient, callback); + if (confirmation == NULL) { + LOGE("Failed to get confirmation from server!"); + return HC_ERR_SERVER_CONFIRM_FAIL; + } + CJson *confirmationJson = CreateJsonFromString(confirmation); + FreeJsonString(confirmation); + if (confirmationJson == NULL) { + LOGE("Failed to create json from string!"); + return HC_ERR_JSON_FAIL; + } + int serverConfirm = REQUEST_ACCEPTED; + (void)GetIntFromJson(confirmationJson, FIELD_CONFIRMATION, &serverConfirm); + if ((uint32_t)serverConfirm == REQUEST_REJECTED) { + LOGE("Server reject to response."); + FreeJson(confirmationJson); + return HC_ERR_REQ_REJECTED; + } + + int32_t res = CombineServerParams(confirmationJson, dataFromClient); + FreeJson(confirmationJson); + if (res != HC_SUCCESS) { + LOGE("Failed to combine server params!"); + return res; + } + + res = GetAuthInfoForServer(dataFromClient, authParamsVec); + if (res != HC_SUCCESS) { + LOGE("Failed to fill device auth info for server!"); + } + return res; +} + +static AuthSession *InitServerAuthSession(const DeviceAuthCallback *callback, ParamsVec *authParamsVec) +{ + AuthSession *session = (AuthSession *)HcMalloc(sizeof(AuthSession), 0); + if (session == NULL) { + LOGE("Failed to malloc memory for session!"); + DestroyAuthParamsVec(authParamsVec); + return NULL; + } + session->base.process = ProcessServerAuthSession; + session->base.destroy = DestroyAuthSession; + session->base.callback = callback; + session->currentIndex = 0; + session->paramsList = *authParamsVec; + int32_t res = GenerateSessionOrTaskId(&session->base.sessionId); + if (res != HC_SUCCESS) { + LOGE("Failed to generate session id!"); + DestroyAuthSession((Session *)session); + return NULL; + } + return session; +} + +static int32_t ProcessServerAuthTask(AuthSession *session, int32_t moduleType, CJson *in, CJson *out) +{ + int32_t status = 0; + CJson *paramInSession = (session->paramsList).get(&(session->paramsList), session->currentIndex); + if (paramInSession == NULL) { + LOGE("The json data in session is null!"); + return HC_ERR_NULL_PTR; + } + int32_t res = ProcessTask(session->curTaskId, in, out, &status, moduleType); + DeleteItemFromJson(in, FIELD_PAYLOAD); + if (res != HC_SUCCESS) { + LOGE("Failed to process task, res = %d!", res); + if (InformAuthError(session, out, res) != HC_SUCCESS) { + LOGE("Failed to inform auth error!"); + } + return res; + } + res = ProcessTaskStatusForAuth(session, paramInSession, out, status); + return res; +} + +static int32_t StartServerAuthTask(AuthSession *session, const CJson *receivedData) +{ + CJson *paramInSession = (session->paramsList).get(&(session->paramsList), session->currentIndex); + if (paramInSession == NULL) { + LOGE("The json data in session is null!"); + return HC_ERR_NULL_PTR; + } + ProcessDeviceLevel(receivedData, paramInSession); + CJson *out = CreateJson(); + if (out == NULL) { + LOGE("Failed to create json!"); + InformLocalAuthError(receivedData, session->base.callback); + InformPeerAuthError(receivedData, session->base.callback); + return HC_ERR_ALLOC_MEMORY; + } + int32_t status = 0; + int32_t res = CreateAndProcessTask(session, paramInSession, out, &status); + DeleteCachedData(paramInSession); + if (res != HC_SUCCESS) { + LOGE("Failed to process server auth task, res = %d!", res); + if (InformAuthError(session, out, res) != HC_SUCCESS) { + LOGE("Failed to inform auth error!"); + } + FreeJson(out); + return res; + } + res = ProcessTaskStatusForAuth(session, receivedData, out, status); + FreeJson(out); + return res; +} + +static int32_t CheckServerGroupAuthMsg(const CJson *in, const CJson *paramInSession, const DeviceAuthCallback *callback) +{ + int32_t GroupErrMsg = 0; + if (GetIntFromJson(in, FIELD_GROUP_ERROR_MSG, (int *)&GroupErrMsg) != HC_SUCCESS) { + return HC_SUCCESS; + } + InformLocalAuthError(paramInSession, callback); + return HC_ERR_PEER_ERROR; +} + +static int ProcessServerAuthSession(Session *session, CJson *in) +{ + LOGI("Begin process server authSession."); + if ((session == NULL) || (in == NULL)) { + LOGE("Invalid input params!"); + return HC_ERR_INVALID_PARAMS; + } + AuthSession *realSession = (AuthSession *)session; + CJson *paramInSession = (realSession->paramsList).get(&(realSession->paramsList), realSession->currentIndex); + if (paramInSession == NULL) { + LOGE("Failed to get param in session!"); + return HC_ERR_NULL_PTR; + } + int32_t res = CheckServerGroupAuthMsg(in, paramInSession, realSession->base.callback); + if (res != HC_SUCCESS) { + LOGE("Peer device's group has error, so we stop server auth session!"); + return res; + } + CJson *out = CreateJson(); + if (out == NULL) { + LOGE("Failed to create json for out!"); + InformLocalAuthError(paramInSession, realSession->base.callback); + InformPeerAuthError(paramInSession, realSession->base.callback); + return HC_ERR_ALLOC_MEMORY; + } + int32_t moduleType = GetAuthModuleType(paramInSession); + res = ProcessServerAuthTask(realSession, moduleType, in, out); + FreeJson(out); + if (res == FINISH) { + LOGI("End process server authSession, auth completed successfully."); + } + return res; +} + +static AuthSession *CreateServerAuthSessionInner(CJson *param, const DeviceAuthCallback *callback) +{ + bool isClient = true; + (void)GetBoolFromJson(param, FIELD_IS_CLIENT, &isClient); + if (!isClient) { + LOGI("Server invokes authDevice, return directly."); + return NULL; + } + ParamsVec authParamsVec; + CreateAuthParamsVec(&authParamsVec); + AuthSession *session = NULL; + int32_t res = AddAuthParamByRequest(param, callback, &authParamsVec); + DeleteCachedData(param); + if (res != HC_SUCCESS) { + LOGE("Failed to add auth param by request, res = %d!", res); + DestroyAuthParamsVec(&authParamsVec); + goto err; + } + if (authParamsVec.size(&authParamsVec) == 0) { + LOGE("No candidate auth group for server!"); + DestroyAuthParamsVec(&authParamsVec); + goto err; + } + session = InitServerAuthSession(callback, &authParamsVec); + if (session == NULL) { + LOGE("Failed to init auth session!"); + goto err; + } + + res = StartServerAuthTask(session, param); + if (res != HC_SUCCESS) { + LOGE("Failed to start server auth task!"); + DestroyAuthSession((Session *)session); + return NULL; + } + return (AuthSession *)session; +err: + InformLocalAuthError(param, callback); + InformPeerAuthError(param, callback); + return NULL; +} + +Session *CreateServerAuthSession(CJson *param, const DeviceAuthCallback *callback) +{ + AuthSession *session = NULL; + if (AddIntToJson(param, FIELD_OPERATION_CODE, AUTHENTICATE) != HC_SUCCESS) { + LOGE("Failed to add operation code to json!"); + InformLocalAuthError(param, callback); + InformPeerAuthError(param, callback); + return NULL; + } + session = CreateServerAuthSessionInner(param, callback); + if (session == NULL) { + LOGE("Failed to create server auth session!"); + return NULL; + } + return (Session *)session; +} \ No newline at end of file diff --git a/services/session/src/auth_session/auth_session_util.c b/services/session/src/auth_session/auth_session_util.c new file mode 100644 index 0000000..b545f78 --- /dev/null +++ b/services/session/src/auth_session/auth_session_util.c @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "auth_session_util.h" +#include "account_related_group_auth.h" +#include "account_unrelated_group_auth.h" +#include "alg_loader.h" +#include "auth_session_common_defines.h" +#include "common_defs.h" +#include "common_util.h" +#include "device_auth_defines.h" +#include "hc_log.h" + +static int32_t AuthFormToModuleType(int32_t authForm) +{ + int moduleType = INVALID_MODULE_TYPE; + if (authForm == AUTH_FORM_ACCOUNT_UNRELATED) { + moduleType = DAS_MODULE; + } else if ((authForm == AUTH_FORM_IDENTICAL_ACCOUNT) || (authForm == AUTH_FORM_ACROSS_ACCOUNT)) { + moduleType = TCIS_MODULE; + } else { + LOGE("Invalid auth form!"); + } + return moduleType; +} + +int32_t GetGroupAuth(int32_t groupAuthType, BaseGroupAuth **groupAuthHandle) +{ + switch (groupAuthType) { + case ACCOUNT_UNRELATED_GROUP_AUTH_TYPE: + LOGI("Non-account auth type."); + *groupAuthHandle = GetNonAccountGroupAuth(); + break; + case ACCOUNT_RELATED_GROUP_AUTH_TYPE: + LOGI("Account-related auth type."); + *groupAuthHandle = GetAccountRelatedGroupAuth(); + break; + default: + LOGE("Invalid auth type!"); + break; + } + if ((*groupAuthHandle) == NULL) { + LOGE("Device auth do not support groupAuthType: %d, !", groupAuthType); + return HC_ERR_NULL_PTR; + } + return HC_SUCCESS; +} + +int32_t GetAuthModuleType(const CJson *in) +{ + int32_t authForm = AUTH_FORM_INVALID_TYPE; + if (GetIntFromJson(in, FIELD_AUTH_FORM, &authForm) != HC_SUCCESS) { + LOGE("Failed to get auth form!"); + return INVALID_MODULE_TYPE; + } + return AuthFormToModuleType(authForm); +} + +int32_t GetInfoHash(const uint8_t *info, uint32_t infoLen, char *str, uint32_t strLen) +{ + Uint8Buff infoHash = {NULL, SHA256_LEN}; + Uint8Buff message = {NULL, infoLen}; + infoHash.val = (uint8_t *)HcMalloc(SHA256_LEN, 0); + if (infoHash.val == NULL) { + LOGE("Failed to malloc for info hash!"); + return HC_ERR_ALLOC_MEMORY; + } + message.val = (uint8_t *)HcMalloc(infoLen, 0); + if (message.val == NULL) { + LOGE("Failed to malloc for message hash!"); + HcFree(infoHash.val); + infoHash.val = NULL; + return HC_ERR_ALLOC_MEMORY; + } + int32_t res; + do { + if (memcpy_s(message.val, message.length, info, infoLen) != HC_SUCCESS) { + LOGE("Failed to copy data!"); + res = HC_ERR_ALLOC_MEMORY; + break; + } + res = GetLoaderInstance()->sha256(&message, &infoHash); + if (res != HC_SUCCESS) { + LOGE("Failed to sha256 message!"); + res = HC_ERROR; + break; + } + if (ByteToHexString(infoHash.val, infoHash.length, str, strLen) != HC_SUCCESS) { + LOGE("Failed to convert byte to string!"); + res = HC_ERROR; + break; + } + } while (0); + HcFree(message.val); + message.val = NULL; + HcFree(infoHash.val); + infoHash.val = NULL; + return res; +} diff --git a/services/session/src/auth_session_common_util.c b/services/session/src/auth_session_common_util.c new file mode 100644 index 0000000..d9c61cd --- /dev/null +++ b/services/session/src/auth_session_common_util.c @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "auth_session_common_util.h" +#include "auth_session_common_defines.h" +#include "common_defs.h" +#include "common_util.h" +#include "device_auth_defines.h" +#include "hc_log.h" + +static int32_t AddPeerIdToReqParam(const CJson *receiveData, CJson *reqParam) +{ + const char *peerId = GetStringFromJson(receiveData, FIELD_PEER_AUTH_ID); + if (peerId == NULL) { + LOGE("Failed to get peerId from the data transmitted by the client!"); + return HC_ERR_JSON_GET; + } + uint32_t peerIdLen = strlen(peerId); + if ((peerIdLen == 0) || (peerIdLen > MAX_AUTH_ID_LEN) || ((peerIdLen % 2) != 0)) { /* 2: even numbers. */ + LOGE("Invalid len of peerId!"); + return HC_ERR_JSON_GET; + } + uint32_t peerIdToRequestLen = peerIdLen / BYTE_TO_HEX_OPER_LENGTH; + uint8_t *peerIdToRequest = (uint8_t *)HcMalloc(peerIdToRequestLen + 1, 0); + if (peerIdToRequest == NULL) { + LOGE("Malloc failed for peerIdToRequest!"); + return HC_ERR_ALLOC_MEMORY; + } + int32_t res = HexStringToByte(peerId, peerIdToRequest, peerIdToRequestLen); + if (res != HC_SUCCESS) { + LOGE("Failed to convert peerId to byte, res: %d!", res); + HcFree(peerIdToRequest); + return res; + } + if (AddStringToJson(reqParam, FIELD_PEER_AUTH_ID, (const char *)peerIdToRequest) != HC_SUCCESS) { + LOGE("Failed to add reqParam: peerId for onRequest!"); + HcFree(peerIdToRequest); + return HC_ERR_JSON_FAIL; + } + HcFree(peerIdToRequest); + return HC_SUCCESS; +} + +char *GetServerConfirmation(const CJson *paramsFromClient, const CJson *reqParam, + const DeviceAuthCallback *callback) +{ + int64_t requestId = 0; + if (GetByteFromJson(paramsFromClient, FIELD_REQUEST_ID, (uint8_t *)&requestId, sizeof(int64_t)) != HC_SUCCESS) { + LOGE("Failed to get request id!"); + return NULL; + } + char *reqParamStr = PackJsonToString(reqParam); + if (reqParamStr == NULL) { + LOGE("Failed to pack reqParam!"); + return NULL; + } + char *serverInfo = NULL; + do { + int32_t authForm = AUTH_FORM_INVALID_TYPE; + if (GetIntFromJson(paramsFromClient, FIELD_AUTH_FORM, &authForm) != HC_SUCCESS) { + LOGE("Failed to get authForm in received data!"); + break; + } + if ((callback == NULL) || (callback->onRequest == NULL)) { + LOGE("Failed to get request callback!"); + break; + } + serverInfo = callback->onRequest(requestId, authForm, reqParamStr); + if (serverInfo == NULL) { + LOGE("Failed to get server confirmation info!"); + } + } while (0); + FreeJsonString(reqParamStr); + return serverInfo; +} + + +int32_t GetGeneralReqParams(const CJson *receiveData, CJson *reqParam) +{ + const char *pkgName = GetStringFromJson(receiveData, FIELD_PKG_NAME); + if (pkgName == NULL) { + LOGE("Failed to get pkgName from the data transmitted by the client!"); + return HC_ERR_JSON_GET; + } + if (AddStringToJson(reqParam, FIELD_SERVICE_PKG_NAME, pkgName) != HC_SUCCESS) { + LOGE("Failed to add reqParam: pkgName for onRequest!"); + return HC_ERR_JSON_FAIL; + } + const char *serviceType = GetStringFromJson(receiveData, FIELD_SERVICE_TYPE); + if (serviceType == NULL) { + LOGE("Failed to get serviceType from the data transmitted by the client!"); + return HC_ERR_JSON_GET; + } + if (AddStringToJson(reqParam, FIELD_SERVICE_TYPE, serviceType) != HC_SUCCESS) { + LOGE("Failed to add reqParam: serviceType for onRequest!"); + return HC_ERR_JSON_FAIL; + } + int32_t res = AddPeerIdToReqParam(receiveData, reqParam); + if (res != HC_SUCCESS) { + LOGE("Failed to add peerId to reqParam!"); + return res; + } + int32_t peerType = 0; + if (GetIntFromJson(receiveData, FIELD_PEER_USER_TYPE, &peerType) != HC_SUCCESS) { + LOGE("Failed to get peerType from the data transmitted by the client!"); + return HC_ERR_JSON_GET; + } + if (AddIntToJson(reqParam, FIELD_PEER_USER_TYPE, peerType) != HC_SUCCESS) { + LOGE("Failed to add reqParam: peerType for onRequest!"); + return HC_ERR_JSON_FAIL; + } + int32_t keyLen = DEFAULT_RETURN_KEY_LENGTH; + (void)GetIntFromJson(receiveData, FIELD_KEY_LENGTH, &keyLen); + if (AddIntToJson(reqParam, FIELD_KEY_LENGTH, keyLen) != HC_SUCCESS) { + LOGE("Failed to add reqParam: keyLen for onRequest!"); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} diff --git a/services/session/src/auth_session_lite/auth_session_client_lite.c b/services/session/src/auth_session_lite/auth_session_client_lite.c new file mode 100644 index 0000000..58d91f0 --- /dev/null +++ b/services/session/src/auth_session_lite/auth_session_client_lite.c @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "auth_session_client_lite.h" +#include "common_defs.h" +#include "device_auth_defines.h" +#include "hc_log.h" +#include "json_utils.h" + +static int32_t StartClientAuthLiteTask(AuthSessionLite *session) +{ + CJson *out = CreateJson(); + if (out == NULL) { + LOGE("Failed to create json!"); + InformLocalAuthErrorLite(session->authParams, session->base.callback); + return HC_ERR_ALLOC_MEMORY; + } + int32_t status = 0; + int32_t res = CreateAndProcessLiteTask(session, out, &status); + if (res != HC_SUCCESS) { + FreeJson(out); + LOGE("Failed to process for client auth session!"); + return res; + } + res = ProcessLiteTaskStatusForAuth(session, out, status); + FreeJson(out); + return res; +} + +static Session *CreateClientAuthSessionLiteInner(CJson *param, const DeviceAuthCallback *callback) +{ + AuthSessionLite *session = InitAuthSessionLite(param, callback); + if (session == NULL) { + LOGE("Failed to initial session!"); + InformLocalAuthErrorLite(param, callback); + return NULL; + } + int32_t res = StartClientAuthLiteTask(session); + if (res != HC_SUCCESS) { + DestroyAuthSessionLite((Session *)session); + return NULL; + } + return (Session *)session; +} + +Session *CreateClientAuthSessionLite(CJson *in, const DeviceAuthCallback *callback) +{ + if (AddBoolToJson(in, FIELD_IS_CLIENT, true) != HC_SUCCESS) { + LOGE("Failed to add isClient to json!"); + InformLocalAuthErrorLite(in, callback); + return NULL; + } + if (AddIntToJson(in, FIELD_OPERATION_CODE, AUTHENTICATE) != HC_SUCCESS) { + LOGE("Failed to add operation code to json!"); + InformLocalAuthErrorLite(in, callback); + return NULL; + } + Session *session = CreateClientAuthSessionLiteInner(in, callback); + if (session == NULL) { + LOGE("Failed to create lite client auth session!"); + return NULL; + } + return session; +} diff --git a/services/session/src/auth_session_lite/auth_session_common_lite.c b/services/session/src/auth_session_lite/auth_session_common_lite.c new file mode 100644 index 0000000..8ec1727 --- /dev/null +++ b/services/session/src/auth_session_lite/auth_session_common_lite.c @@ -0,0 +1,373 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "auth_session_common_lite.h" +#include "auth_session_util.h" +#include "common_defs.h" +#include "das_module_defines.h" +#include "dev_auth_module_manager.h" +#include "device_auth_defines.h" +#include "hc_log.h" +#include "hc_types.h" +#include "session_common.h" + +static void ReturnFinishDataLite(const CJson *in, const DeviceAuthCallback *callback, const CJson *out); + +static int32_t ProcessAuthTaskLite(AuthSessionLite *session, int32_t moduleType, CJson *in, CJson *out) +{ + int32_t status = 0; + int32_t res = ProcessTask(session->curTaskId, in, out, &status, moduleType); + if (res != HC_SUCCESS) { + InformAuthErrorLite(in, session->base.callback, out, res); + return res; + } + res = ProcessLiteTaskStatusForAuth(session, out, status); + return res; +} + +static int ProcessAuthSessionLite(Session *session, CJson *in) +{ + LOGI("Begin process authSession lite."); + if ((session == NULL) || (in == NULL)) { + LOGE("Invalid input params!"); + return HC_ERR_INVALID_PARAMS; + } + CJson *out = NULL; + AuthSessionLite *realSession = (AuthSessionLite *)session; + out = CreateJson(); + if (out == NULL) { + LOGE("Failed to create json!"); + return HC_ERR_ALLOC_MEMORY; + } + int32_t res = ProcessAuthTaskLite(realSession, GetAuthModuleType(realSession->authParams), in, out); + FreeJson(out); + LOGI("End process authSession lite, res = %d.", res); + return res; +} + +static void ReturnErrorDataLite(const CJson *in, const DeviceAuthCallback *callback, const CJson *out, int errorCode) +{ + int64_t requestId = 0; + int32_t authForm = 0; + if (GetByteFromJson(in, FIELD_REQUEST_ID, (uint8_t *)&requestId, sizeof(int64_t)) != HC_SUCCESS) { + LOGE("Failed to add request id!"); + return; + } + if (GetIntFromJson(in, FIELD_AUTH_FORM, &authForm) != HC_SUCCESS) { + LOGE("Failed to add auth form!"); + return; + } + char *returnStr = PackJsonToString(out); + if (returnStr == NULL) { + LOGE("Failed to convert json: out to string!"); + return; + } + if ((callback != NULL) && (callback->onError != NULL)) { + callback->onError(requestId, authForm, errorCode, returnStr); + } + FreeJsonString(returnStr); +} + +static int32_t ReturnSessionKeyLite(int64_t requestId, const CJson *authParams, + const CJson *out, const DeviceAuthCallback *callback) +{ + int32_t keyLen = DEFAULT_RETURN_KEY_LENGTH; + (void)GetIntFromJson(authParams, FIELD_KEY_LENGTH, &keyLen); + uint8_t *sessionKey = (uint8_t *)HcMalloc(keyLen, 0); + if (sessionKey == NULL) { + LOGE("Failed to allocate memory for sessionKey!"); + return HC_ERR_ALLOC_MEMORY; + } + int32_t res = HC_SUCCESS; + do { + if (GetByteFromJson(out, FIELD_SESSION_KEY, sessionKey, keyLen) != HC_SUCCESS) { + LOGE("Failed to get sessionKey!"); + res = HC_ERR_JSON_GET; + break; + } + if ((callback == NULL) || (callback->onSessionKeyReturned == NULL)) { + LOGE("The callback of onSessionKeyReturned is null!"); + res = HC_ERR_JSON_GET; + break; + } + callback->onSessionKeyReturned(requestId, sessionKey, keyLen); + } while (0); + (void)memset_s(sessionKey, keyLen, 0, keyLen); + HcFree(sessionKey); + sessionKey = NULL; + return res; +} + +static void ReturnFinishDataLiteInner(int64_t requestId, const CJson *in, const DeviceAuthCallback *callback, + const CJson *out) +{ + int32_t authForm = AUTH_FORM_INVALID_TYPE; + if (GetIntFromJson(in, FIELD_AUTH_FORM, &authForm) != HC_SUCCESS) { + LOGE("Failed to get auth type!"); + return; + } + const CJson *sendToPeer = GetObjFromJson(out, FIELD_SEND_TO_PEER); + if (sendToPeer != NULL) { + char *sendToPeerStr = PackJsonToString(sendToPeer); + if (sendToPeerStr == NULL) { + LOGE("Failed to pack sendToPeerStr for onTransmit!"); + return; + } + if ((callback != NULL) && (callback->onTransmit != NULL)) { + if (!callback->onTransmit(requestId, (uint8_t *)sendToPeerStr, (uint32_t)strlen(sendToPeerStr) + 1)) { + LOGE("Failed to transmit data to peer!"); + FreeJsonString(sendToPeerStr); + return; + } + } + FreeJsonString(sendToPeerStr); + } + CJson *sendToSelf = GetObjFromJson(out, FIELD_SEND_TO_SELF); + if (sendToSelf == NULL) { + return; + } + char *returnStr = PackJsonToString(sendToSelf); + ClearSensitiveStringInJson(sendToSelf, FIELD_SESSION_KEY); + if (returnStr == NULL) { + LOGE("Failed to pack returnStr for onFinish!"); + return; + } + if ((callback != NULL) && (callback->onFinish != NULL)) { + callback->onFinish(requestId, authForm, returnStr); + } + ClearAndFreeJsonString(returnStr); +} + +static void ReturnFinishDataLite(const CJson *in, const DeviceAuthCallback *callback, const CJson *out) +{ + if (out == NULL) { + LOGE("No data for finish return!"); + return; + } + int64_t requestId = 0; + if (GetByteFromJson(in, FIELD_REQUEST_ID, (uint8_t *)&requestId, sizeof(int64_t)) != HC_SUCCESS) { + LOGE("Failed to get request id!"); + return; + } + if (ReturnSessionKeyLite(requestId, in, out, callback) != HC_SUCCESS) { + LOGE("Failed to return session key!"); + return; + } + ReturnFinishDataLiteInner(requestId, in, callback, out); +} + +int32_t ReturnTransmitDataLite(const AuthSessionLite *session, CJson *out) +{ + CJson *sendToPeer = GetObjFromJson(out, FIELD_SEND_TO_PEER); + if (sendToPeer == NULL) { + LOGI("The transmit data to peer is null in lite auth session!"); + return HC_ERR_JSON_GET; + } + int32_t ret = HC_SUCCESS; + const DeviceAuthCallback *callback = session->base.callback; + int64_t requestId = 0; + if (GetByteFromJson(session->authParams, FIELD_REQUEST_ID, + (uint8_t *)&requestId, sizeof(int64_t)) != HC_SUCCESS) { + LOGE("Failed to get request id!"); + return HC_ERR_JSON_GET; + } + char *outStr = PackJsonToString(sendToPeer); + if (outStr == NULL) { + LOGE("Failed to pack outStr for onTransmit!"); + return HC_ERR_ALLOC_MEMORY; + } + do { + if ((callback == NULL) || (callback->onTransmit == NULL)) { + LOGE("The callback for transmit is null!"); + ret = HC_ERR_NULL_PTR; + break; + } + if (!callback->onTransmit(requestId, (uint8_t *)outStr, (uint32_t)strlen(outStr) + 1)) { + LOGE("Failed to transmit data to peer!"); + ret = HC_ERR_TRANSMIT_FAIL; + } + } while (0); + FreeJsonString(outStr); + return ret; +} + +void InformLocalAuthErrorLite(const CJson *authParam, const DeviceAuthCallback *callback) +{ + int64_t requestId = 0; + if (GetByteFromJson(authParam, FIELD_REQUEST_ID, (uint8_t *)&requestId, sizeof(int64_t)) != HC_SUCCESS) { + LOGE("Failed to get request id!"); + return; + } + if ((callback != NULL) && (callback->onError != NULL)) { + callback->onError(requestId, AUTH_FORM_INVALID_TYPE, HC_ERR_CREATE_SESSION_FAIL, NULL); + } +} + +void InformPeerAuthErrorLite(const CJson *in, const DeviceAuthCallback *callback) +{ + bool isClient = false; + (void)GetBoolFromJson(in, FIELD_IS_CLIENT, &isClient); + if (isClient) { + return; + } + int32_t message = 0; + (void)GetIntFromJson(in, FIELD_MESSAGE, &message); + if (message == ERR_MESSAGE) { + LOGI("Peer send error msg, no need to let peer device process error twice!"); + return; + } + int64_t requestId = 0; + if (GetByteFromJson(in, FIELD_REQUEST_ID, (uint8_t *)&requestId, sizeof(int64_t)) != HC_SUCCESS) { + LOGE("Failed to get request ID!"); + return; + } + CJson *errorToPeer = CreateJson(); + if (errorToPeer == NULL) { + LOGE("Failed to allocate memory!"); + return; + } + if (AddIntToJson(errorToPeer, FIELD_MESSAGE, ERR_MESSAGE) != HC_SUCCESS) { + LOGE("Failed to add errMessage to json!"); + FreeJson(errorToPeer); + return; + } + char *errorToPeerStr = PackJsonToString(errorToPeer); + FreeJson(errorToPeer); + if (errorToPeerStr == NULL) { + LOGE("Failed to pack errorToPeer to string!"); + return; + } + if ((callback != NULL) && (callback->onTransmit != NULL)) { + (void)callback->onTransmit(requestId, (uint8_t *)errorToPeerStr, (uint32_t)strlen(errorToPeerStr) + 1); + } + FreeJsonString(errorToPeerStr); +} + +void InformAuthErrorLite(const CJson *in, const DeviceAuthCallback *callback, const CJson *out, int errorCode) +{ + bool isClient = false; + (void)GetBoolFromJson(in, FIELD_IS_CLIENT, &isClient); + const CJson *sendToSelf = GetObjFromJson(out, FIELD_SEND_TO_SELF); + if (sendToSelf != NULL) { + ReturnErrorDataLite(in, callback, sendToSelf, errorCode); + } + const CJson *sendToPeer = GetObjFromJson(out, FIELD_SEND_TO_PEER); + if (sendToPeer == NULL) { + return; + } + int64_t requestId = 0; + if (GetByteFromJson(in, FIELD_REQUEST_ID, (uint8_t *)&requestId, sizeof(int64_t)) != HC_SUCCESS) { + LOGE("Failed to get request id!"); + return; + } + char *sendToPeerStr = PackJsonToString(sendToPeer); + if (sendToPeerStr == NULL) { + LOGE("Failed to pack json to string!"); + return; + } + if ((callback != NULL) && (callback->onTransmit != NULL)) { + (void)callback->onTransmit(requestId, (uint8_t *)sendToPeerStr, (uint32_t)strlen(sendToPeerStr) + 1); + } + FreeJsonString(sendToPeerStr); +} + +int32_t CreateAndProcessLiteTask(AuthSessionLite *session, CJson *out, int32_t *status) +{ + int32_t moduleType = GetAuthModuleType(session->authParams); + const char *pkgName = GetStringFromJson(session->authParams, FIELD_SERVICE_PKG_NAME); + if (AddStringToJson(session->authParams, FIELD_PKG_NAME, pkgName) != HC_SUCCESS) { + LOGE("Failed to add pkg name to json!"); + InformLocalAuthErrorLite(session->authParams, session->base.callback); + InformPeerAuthErrorLite(session->authParams, session->base.callback); + return HC_ERR_JSON_FAIL; + } + session->curTaskId = 0; + int32_t res = CreateTask(&(session->curTaskId), session->authParams, out, moduleType); + if (res != HC_SUCCESS) { + LOGE("Failed to create task for auth!"); + InformAuthErrorLite(session->authParams, session->base.callback, out, res); + return res; + } + res = ProcessTask(session->curTaskId, session->authParams, out, status, moduleType); + if (res != HC_SUCCESS) { + LOGE("Failed to process task for auth!"); + InformAuthErrorLite(session->authParams, session->base.callback, out, res); + return res; + } + return HC_SUCCESS; +} + +int32_t ProcessLiteTaskStatusForAuth(const AuthSessionLite *session, CJson *out, int32_t status) +{ + int32_t res = HC_SUCCESS; + switch (status) { + case IGNORE_MSG: + LOGI("Ignore this msg."); + break; + case CONTINUE: + res = ReturnTransmitDataLite(session, out); + FreeJson(out); + if (res != HC_SUCCESS) { + LOGE("Failed to transmit lite auth data to peer!"); + InformLocalAuthErrorLite(session->authParams, session->base.callback); + } + break; + case FINISH: + ReturnFinishDataLite(session->authParams, session->base.callback, out); + res = FINISH; + break; + default: + LOGE("Invalid status after process task!"); + res = HC_ERR_INVALID_PARAMS; + break; + } + return res; +} + +void DestroyAuthSessionLite(Session *session) +{ + if (session == NULL) { + return; + } + AuthSessionLite *realSession = (AuthSessionLite *)session; + FreeJson(realSession->authParams); + HcFree(realSession); + realSession = NULL; +} + +AuthSessionLite *InitAuthSessionLite(CJson *param, const DeviceAuthCallback *callback) +{ + AuthSessionLite *session = (AuthSessionLite *)HcMalloc(sizeof(AuthSessionLite), 0); + if (session == NULL) { + LOGE("Failed to allocate memory for session!"); + return NULL; + } + session->base.process = ProcessAuthSessionLite; + session->base.destroy = DestroyAuthSessionLite; + session->base.callback = callback; + session->authParams = DuplicateJson(param); + if (session->authParams == NULL) { + LOGE("Failed to duplicate param!"); + DestroyAuthSessionLite((Session *)session); + return NULL; + } + int32_t res = GenerateSessionOrTaskId(&session->base.sessionId); + if (res != HC_SUCCESS) { + LOGE("Failed to generate session id!"); + DestroyAuthSessionLite((Session *)session); + return NULL; + } + return session; +} \ No newline at end of file diff --git a/services/session/src/auth_session_lite/auth_session_server_lite.c b/services/session/src/auth_session_lite/auth_session_server_lite.c new file mode 100644 index 0000000..5819c08 --- /dev/null +++ b/services/session/src/auth_session_lite/auth_session_server_lite.c @@ -0,0 +1,180 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "auth_session_server_lite.h" +#include "auth_session_common_util.h" +#include "common_defs.h" +#include "device_auth_defines.h" +#include "hc_log.h" +#include "json_utils.h" + +static int32_t StartServerAuthLiteTask(AuthSessionLite *session) +{ + CJson *out = CreateJson(); + if (out == NULL) { + LOGE("Failed to create json!"); + InformLocalAuthErrorLite(session->authParams, session->base.callback); + InformPeerAuthErrorLite(session->authParams, session->base.callback); + return HC_ERR_ALLOC_MEMORY; + } + int32_t status = 0; + int32_t res = CreateAndProcessLiteTask(session, out, &status); + DeleteItemFromJson(session->authParams, FIELD_PAYLOAD); + if (res != HC_SUCCESS) { + FreeJson(out); + LOGE("Failed to process for Server auth lite session!"); + return res; + } + res = ProcessLiteTaskStatusForAuth(session, out, status); + FreeJson(out); + return res; +} + +static int32_t CombineServerParamsLite(const CJson *confirmationJson, CJson *dataFromClient) +{ + bool isClient = false; + if (AddBoolToJson(dataFromClient, FIELD_IS_CLIENT, isClient) != HC_SUCCESS) { + LOGE("Failed to combine server param with isClient!"); + return HC_ERR_JSON_FAIL; + } + const char *pkgName = GetStringFromJson(confirmationJson, FIELD_SERVICE_PKG_NAME); + if (pkgName == NULL) { + LOGE("Failed to get pkgName from confirmation data!"); + return HC_ERR_JSON_GET; + } + if (AddStringToJson(dataFromClient, FIELD_SERVICE_PKG_NAME, pkgName) != HC_SUCCESS) { + LOGE("Failed to combine server param with pkgName!"); + return HC_ERR_JSON_FAIL; + } + const char *selfId = GetStringFromJson(confirmationJson, FIELD_SELF_AUTH_ID); + if (selfId == NULL) { + LOGE("Failed to get selfId from confirmation data!"); + return HC_ERR_JSON_GET; + } + if (AddStringToJson(dataFromClient, FIELD_SELF_AUTH_ID, selfId) != HC_SUCCESS) { + LOGE("Failed to combine server param with selfId!"); + return HC_ERR_JSON_FAIL; + } + int32_t selfType; + if (GetIntFromJson(confirmationJson, FIELD_SELF_TYPE, &selfType) != HC_SUCCESS) { + LOGE("Failed to get selfId from confirmation data!"); + return HC_ERR_JSON_GET; + } + if (AddIntToJson(dataFromClient, FIELD_SELF_TYPE, selfType) != HC_SUCCESS) { + LOGE("Failed to combine server param with selfType!"); + return HC_ERR_JSON_FAIL; + } + const char *serviceType = GetStringFromJson(confirmationJson, FIELD_SERVICE_TYPE); + if (serviceType == NULL) { + LOGE("Failed to get serviceType from confirmation data!"); + return HC_ERR_JSON_GET; + } + if (AddStringToJson(dataFromClient, FIELD_SERVICE_TYPE, serviceType) != HC_SUCCESS) { + LOGE("Failed to combine server param with serviceType!"); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} + +static char *StartServerRequestLite(const CJson *in, const DeviceAuthCallback *callback) +{ + CJson *reqParam = CreateJson(); + if (reqParam == NULL) { + LOGE("Failed to create reqParam json!"); + return NULL; + } + int32_t res = GetGeneralReqParams(in, reqParam); + if (res != HC_SUCCESS) { + LOGE("Failed to get request params!"); + FreeJson(reqParam); + return NULL; + } + char *confirmation = GetServerConfirmation(in, reqParam, callback); + FreeJson(reqParam); + return confirmation; +} + +static int32_t AddAuthParamByRequestLite(CJson *in, const DeviceAuthCallback *callback) +{ + char *confirmation = StartServerRequestLite(in, callback); + if (confirmation == NULL) { + LOGE("Failed to get confirmation from server!"); + return HC_ERR_SERVER_CONFIRM_FAIL; + } + CJson *confirmationJson = CreateJsonFromString(confirmation); + FreeJsonString(confirmation); + if (confirmationJson == NULL) { + LOGE("Failed to create json from string!"); + return HC_ERR_JSON_FAIL; + } + int serverConfirm = REQUEST_ACCEPTED; + (void)GetIntFromJson(confirmationJson, FIELD_CONFIRMATION, &serverConfirm); + if ((uint32_t)serverConfirm == REQUEST_REJECTED) { + LOGE("Server reject to response!"); + FreeJson(confirmationJson); + return HC_ERR_REQ_REJECTED; + } + int32_t res = CombineServerParamsLite(confirmationJson, in); + FreeJson(confirmationJson); + if (res != HC_SUCCESS) { + LOGE("Failed to combine server params!"); + return res; + } + return res; +} + +static Session *CreateServerAuthSessionLiteInner(CJson *in, const DeviceAuthCallback *callback) +{ + int32_t res = AddAuthParamByRequestLite(in, callback); + if (res != HC_SUCCESS) { + LOGE("Failed to add auth params by request!"); + return NULL; + } + AuthSessionLite *session = InitAuthSessionLite(in, callback); + if (session == NULL) { + LOGE("Failed to initial session!"); + InformLocalAuthErrorLite(in, callback); + InformPeerAuthErrorLite(in, callback); + return NULL; + } + res = StartServerAuthLiteTask(session); + if (res != HC_SUCCESS) { + DestroyAuthSessionLite((Session *)session); + return NULL; + } + return (Session *)session; +} + +Session *CreateServerAuthSessionLite(CJson *in, const DeviceAuthCallback *callback) +{ + if (AddBoolToJson(in, FIELD_IS_CLIENT, false) != HC_SUCCESS) { + LOGE("Failed to add isClient to json!"); + InformLocalAuthErrorLite(in, callback); + InformPeerAuthErrorLite(in, callback); + return NULL; + } + if (AddIntToJson(in, FIELD_OPERATION_CODE, AUTHENTICATE) != HC_SUCCESS) { + LOGE("Failed to add operation code to json!"); + InformLocalAuthErrorLite(in, callback); + InformPeerAuthErrorLite(in, callback); + return NULL; + } + Session *session = CreateServerAuthSessionLiteInner(in, callback); + if (session == NULL) { + LOGE("Failed to create lite server auth session!"); + return NULL; + } + return session; +} \ No newline at end of file diff --git a/services/session/src/auth_session_lite_mock/auth_session_client_lite_mock.c b/services/session/src/auth_session_lite_mock/auth_session_client_lite_mock.c new file mode 100644 index 0000000..91ea2c4 --- /dev/null +++ b/services/session/src/auth_session_lite_mock/auth_session_client_lite_mock.c @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "auth_session_client_lite.h" +#include "hc_log.h" + +Session *CreateClientAuthSessionLite(CJson *in, const DeviceAuthCallback *callback) +{ + LOGE("Lite auth session is not supported!"); + (void)in; + (void)callback; + return NULL; +} diff --git a/services/session/src/auth_session_lite_mock/auth_session_server_lite_mock.c b/services/session/src/auth_session_lite_mock/auth_session_server_lite_mock.c new file mode 100644 index 0000000..bb435e5 --- /dev/null +++ b/services/session/src/auth_session_lite_mock/auth_session_server_lite_mock.c @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "auth_session_server_lite.h" +#include "hc_log.h" + +Session *CreateServerAuthSessionLite(CJson *in, const DeviceAuthCallback *callback) +{ + LOGE("Lite auth session is not supported!"); + (void)in; + (void)callback; + return NULL; +} diff --git a/services/session/src/auth_session_mock/auth_session_client_mock.c b/services/session/src/auth_session_mock/auth_session_client_mock.c new file mode 100644 index 0000000..944c823 --- /dev/null +++ b/services/session/src/auth_session_mock/auth_session_client_mock.c @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "auth_session_client.h" +#include "hc_log.h" + +Session *CreateClientAuthSession(CJson *param, const DeviceAuthCallback *callback) +{ + LOGE("Auth session is not supported!"); + (void)param; + (void)callback; + return NULL; +} diff --git a/services/session/src/auth_session_mock/auth_session_server_mock.c b/services/session/src/auth_session_mock/auth_session_server_mock.c new file mode 100644 index 0000000..f968874 --- /dev/null +++ b/services/session/src/auth_session_mock/auth_session_server_mock.c @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "auth_session_server.h" +#include "hc_log.h" + +Session *CreateServerAuthSession(CJson *param, const DeviceAuthCallback *callback) +{ + LOGE("Auth session is not supported!"); + (void)param; + (void)callback; + return NULL; +} diff --git a/services/session/src/bind_session/bind_session_client.c b/services/session/src/bind_session/bind_session_client.c new file mode 100644 index 0000000..e0e0a92 --- /dev/null +++ b/services/session/src/bind_session/bind_session_client.c @@ -0,0 +1,198 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "bind_session_client.h" +#include "callback_manager.h" +#include "channel_manager.h" +#include "group_common.h" +#include "hc_log.h" +#include "session_manager.h" + +static int32_t GenerateClientModuleParams(BindSession *session, CJson *moduleParams) +{ + if (AddIntToJson(moduleParams, FIELD_OPERATION_CODE, + ((session->operationCode == MEMBER_DELETE) ? OP_UNBIND : OP_BIND)) != HC_SUCCESS) { + LOGE("Failed to add operationCode to moduleParams!"); + return HC_ERR_JSON_FAIL; + } + return GenerateBasicModuleParams(true, session, moduleParams); +} + +static int32_t GetClientModuleReturnData(BindSession *session, CJson *out) +{ + CJson *moduleParams = CreateJson(); + if (moduleParams == NULL) { + LOGE("Failed to allocate moduleParams memory!"); + return HC_ERR_JSON_FAIL; + } + + int32_t result = GenerateClientModuleParams(session, moduleParams); + if (result != HC_SUCCESS) { + LOGE("Failed to generate all params sent to the module!"); + FreeJson(moduleParams); + return result; + } + + result = CreateAndProcessModule(session, moduleParams, out); + FreeJson(moduleParams); + if (result != HC_SUCCESS) { + return result; + } + return HC_SUCCESS; +} + +static int32_t PrepareData(BindSession *session, CJson **sendData) +{ + CJson *out = CreateJson(); + if (out == NULL) { + LOGE("Failed to allocate out memory!"); + return HC_ERR_JSON_FAIL; + } + int32_t result = GetClientModuleReturnData(session, out); + if (result != HC_SUCCESS) { + FreeJson(out); + return result; + } + + *sendData = DetachItemFromJson(out, FIELD_SEND_TO_PEER); + FreeJson(out); + if (*sendData == NULL) { + LOGE("Failed to get sendToPeer from out!"); + return HC_ERR_JSON_GET; + } + + result = AddInfoToSendData(false, session, *sendData); + if (result != HC_SUCCESS) { + LOGE("Failed to add information to sendData!"); + FreeJson(*sendData); + *sendData = NULL; + return result; + } + return HC_SUCCESS; +} + +static int32_t PrepareAndSendData(BindSession *session) +{ + CJson *sendData = NULL; + int32_t result = PrepareData(session, &sendData); + if (result != HC_SUCCESS) { + return result; + } + + result = SendBindSessionData(session, sendData); + FreeJson(sendData); + return result; +} + +static int32_t DoubleCheckChannelId(int64_t channelId, int64_t oldChannelId) +{ + if (oldChannelId != channelId) { + /* If the two channelIds are different, the soft bus channel must be used. */ + LOGE("The channelId returned by the soft bus are inconsistent, causing a channel error!"); + return HC_ERR_CHANNEL_NOT_EXIST; + } + return HC_SUCCESS; +} + +static void OnBindChannelOpened(Session *session, int64_t channelId, int64_t requestId) +{ + if (session == NULL) { + LOGE("The input session is NULL!"); + return; + } + + BindSession *realSession = (BindSession *)session; + /* Double check channelId. If the two channelIds are different, the channel fails to be established. */ + int32_t result = DoubleCheckChannelId(channelId, realSession->channelId); + if (result != HC_SUCCESS) { + ProcessErrorCallback(requestId, realSession->operationCode, result, NULL, realSession->base.callback); + DestroySession(requestId); + return; + } + + result = PrepareAndSendData(realSession); + if (result != HC_SUCCESS) { + LOGI("An error occurs before the client send data to the server. We need to notify the service!"); + if ((!NeedForceDelete(realSession)) || (ForceUnbindDevice(realSession) != HC_SUCCESS)) { + ProcessErrorCallback(requestId, realSession->operationCode, result, NULL, + realSession->base.callback); + } + CloseChannel(realSession->channelType, realSession->channelId); + DestroySession(requestId); + } +} + +static int32_t PrepareClient(const CJson *jsonParams, BindSession *session) +{ + int32_t result = GenerateBindParams(CLIENT, jsonParams, session); + if (result != HC_SUCCESS) { + return result; + } + return OpenChannel(session->channelType, jsonParams, session->requestId, &session->channelId); +} + +static void InitClientChannel(const DeviceAuthCallback *callback, BindSession *session) +{ + session->channelType = GetChannelType(callback); +} + +Session *CreateClientBindSession(CJson *jsonParams, const DeviceAuthCallback *callback) +{ + int64_t requestId = DEFAULT_REQUEST_ID; + if (GetInt64FromJson(jsonParams, FIELD_REQUEST_ID, &requestId) != HC_SUCCESS) { + LOGE("Failed to get requestId from jsonParams!"); + return NULL; + } + int operationCode = MEMBER_INVITE; + if (GetIntFromJson(jsonParams, FIELD_OPERATION_CODE, &operationCode) != HC_SUCCESS) { + LOGE("Failed to get operationCode from jsonParams!"); + return NULL; + } + LOGI("Start to create client bind session! [RequestId]: %lld, [OperationCode]: %d", requestId, operationCode); + /* + * If service want to join the peer group, + * the identity key pair of the corresponding group needs to be generated here. + */ + int32_t result; + if (NeedCreateGroup(CLIENT, operationCode)) { + const char *groupId = GetStringFromJson(jsonParams, FIELD_GROUP_ID); + if (groupId == NULL) { + LOGE("Failed to get groupId from jsonParams!"); + return NULL; + } + result = ProcessKeyPair(CREATE_KEY_PAIR, jsonParams, groupId); + if (result != HC_SUCCESS) { + return NULL; + } + } + + BindSession *session = (BindSession *)HcMalloc(sizeof(BindSession), 0); + if (session == NULL) { + LOGE("Failed to allocate session memory!"); + return NULL; + } + InitBindSession(TYPE_CLIENT_BIND_SESSION, operationCode, requestId, callback, session); + InitClientChannel(callback, session); + /* The client bind session needs to receive a message indicating that the channel is open. */ + session->onChannelOpened = OnBindChannelOpened; + + result = PrepareClient(jsonParams, session); + if (result != HC_SUCCESS) { + DestroyBindSession((Session *)session); + return NULL; + } + LOGI("Create client bind session successfully! [RequestId]: %lld, [OperationCode]: %d", requestId, operationCode); + return (Session *)session; +} \ No newline at end of file diff --git a/services/session/src/bind_session/bind_session_common.c b/services/session/src/bind_session/bind_session_common.c new file mode 100644 index 0000000..bfe32eb --- /dev/null +++ b/services/session/src/bind_session/bind_session_common.c @@ -0,0 +1,1387 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "bind_session_common.h" +#include "callback_manager.h" +#include "channel_manager.h" +#include "database_manager.h" +#include "dev_auth_module_manager.h" +#include "group_common.h" +#include "hc_dev_info.h" +#include "hc_log.h" +#include "session_common.h" + +static int32_t AddGroupInfoToSendData(const BindSession *session, CJson *data) +{ + const char *groupId = GetStringFromJson(session->params, FIELD_GROUP_ID); + if (groupId == NULL) { + LOGE("Failed to get groupId from params!"); + return HC_ERR_JSON_GET; + } + const char *groupName = GetStringFromJson(session->params, FIELD_GROUP_NAME); + if (groupName == NULL) { + LOGE("Failed to get groupName from params!"); + return HC_ERR_JSON_GET; + } + if (AddStringToJson(data, FIELD_GROUP_ID, groupId) != HC_SUCCESS) { + LOGE("Failed to add groupId to data!"); + return HC_ERR_JSON_FAIL; + } + if (AddStringToJson(data, FIELD_GROUP_NAME, groupName) != HC_SUCCESS) { + LOGE("Failed to add groupName to data!"); + return HC_ERR_JSON_FAIL; + } + if (AddIntToJson(data, FIELD_GROUP_OP, session->operationCode) != HC_SUCCESS) { + LOGE("Failed to add groupOp to data!"); + return HC_ERR_JSON_FAIL; + } + if (AddIntToJson(data, FIELD_GROUP_TYPE, PEER_TO_PEER_GROUP) != HC_SUCCESS) { + LOGE("Failed to add groupType to data!"); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} + +static int32_t AddDevInfoToSendData(const BindSession *session, CJson *data) +{ + const char *authId = GetStringFromJson(session->params, FIELD_AUTH_ID); + if (authId == NULL) { + LOGE("Failed to get authId from params!"); + return HC_ERR_JSON_GET; + } + const char *udid = GetStringFromJson(session->params, FIELD_CONN_DEVICE_ID); + if (udid == NULL) { + LOGE("Failed to get udid from params!"); + return HC_ERR_JSON_GET; + } + if (AddStringToJson(data, FIELD_PEER_DEVICE_ID, authId) != HC_SUCCESS) { + LOGE("Failed to add peerDeviceId to data!"); + return HC_ERR_JSON_FAIL; + } + if (AddStringToJson(data, FIELD_CONN_DEVICE_ID, udid) != HC_SUCCESS) { + LOGE("Failed to add connDeviceId to data!"); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} + +static int32_t AddRequestInfoToSendData(const BindSession *session, CJson *data) +{ + const char *appId = GetStringFromJson(session->params, FIELD_APP_ID); + if (appId == NULL) { + LOGE("Failed to get appId from params!"); + return HC_ERR_JSON_GET; + } + if (AddStringToJson(data, FIELD_APP_ID, appId) != HC_SUCCESS) { + LOGE("Failed to add appId to data!"); + return HC_ERR_JSON_FAIL; + } + if (AddInt64StringToJson(data, FIELD_REQUEST_ID, session->requestId) != HC_SUCCESS) { + LOGE("Failed to add requestId to data!"); + return HC_ERR_JSON_FAIL; + } + if (AddStringToJson(data, FIELD_OWNER_NAME, "") != HC_SUCCESS) { + LOGE("Failed to add ownerName to data!"); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} + +static int32_t GenerateCompatibleInfo(CJson *groupInfo) +{ + uint8_t udid[INPUT_UDID_LEN] = { 0 }; + if (HcGetUdid(udid, INPUT_UDID_LEN) != HC_SUCCESS) { + LOGE("Get local udid failed"); + return HC_ERROR; + } + if (AddStringToJson(groupInfo, FIELD_DEVICE_ID, (const char *)udid) != HC_SUCCESS) { + LOGE("Failed to add deviceId to groupInfo!"); + return HC_ERR_JSON_FAIL; + } + if (AddBoolToJson(groupInfo, FIELD_IS_UUID, true) != HC_SUCCESS) { + LOGE("Failed to add uuIdAsDeviceId to groupInfo!"); + return HC_ERR_JSON_FAIL; + } + /* To be compatible with packets of earlier versions. */ + CJson *managers = CreateJsonArray(); + if (managers == NULL) { + LOGE("Failed to allocate managers memory!"); + return HC_ERR_JSON_FAIL; + } + if (AddObjToJson(groupInfo, FIELD_GROUP_MANAGERS, managers) != HC_SUCCESS) { + LOGE("Failed to add groupManagers to groupInfo!"); + FreeJson(managers); + return HC_ERR_JSON_FAIL; + } + FreeJson(managers); + /* Currently, only the public group can be created. */ + if (AddIntToJson(groupInfo, FIELD_GROUP_VISIBILITY, GROUP_VISIBILITY_PUBLIC) != HC_SUCCESS) { + LOGE("Failed to add groupVisibility to groupInfo!"); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} + +static int32_t AddCompatibleInfoToSendData(bool isNeedCompatibleInfo, CJson *data) +{ + if (!isNeedCompatibleInfo) { + return HC_SUCCESS; + } + CJson *groupInfo = CreateJson(); + if (groupInfo == NULL) { + LOGE("Failed to allocate groupInfo memory!"); + return HC_ERR_ALLOC_MEMORY; + } + if (GenerateCompatibleInfo(groupInfo) != HC_SUCCESS) { + FreeJson(groupInfo); + return HC_ERR_JSON_FAIL; + } + if (AddObjToJson(data, FIELD_GROUP_INFO, groupInfo) != HC_SUCCESS) { + LOGE("Failed to add groupInfo to sendData!"); + FreeJson(groupInfo); + return HC_ERR_JSON_FAIL; + } + FreeJson(groupInfo); + return HC_SUCCESS; +} + +static int32_t AddGroupAndDevInfoToParams(const BindSession *session, CJson *moduleParams) +{ + const char *groupId = GetStringFromJson(session->params, FIELD_GROUP_ID); + if (groupId == NULL) { + LOGE("Failed to get groupId from params!"); + return HC_ERR_JSON_GET; + } + const char *authId = GetStringFromJson(session->params, FIELD_AUTH_ID); + if (authId == NULL) { + LOGE("Failed to get authId from params!"); + return HC_ERR_JSON_GET; + } + int userType = DEVICE_TYPE_ACCESSORY; + if (GetIntFromJson(session->params, FIELD_USER_TYPE, &userType) != HC_SUCCESS) { + LOGE("Failed to get userType from params!"); + return HC_ERR_JSON_GET; + } + if (AddStringToJson(moduleParams, FIELD_SERVICE_TYPE, groupId) != HC_SUCCESS) { + LOGE("Failed to add serviceType to moduleParams!"); + return HC_ERR_JSON_FAIL; + } + if (AddStringToJson(moduleParams, FIELD_SELF_AUTH_ID, authId) != HC_SUCCESS) { + LOGE("Failed to add serviceType to moduleParams!"); + return HC_ERR_JSON_FAIL; + } + if (AddIntToJson(moduleParams, FIELD_SELF_TYPE, userType) != HC_SUCCESS) { + LOGE("Failed to add userType to moduleParams!"); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} + +static int32_t AddRequestInfoToParams(bool isClient, const BindSession *session, CJson *moduleParams) +{ + if (AddByteToJson(moduleParams, FIELD_REQUEST_ID, + (const uint8_t *)&session->requestId, sizeof(int64_t)) != HC_SUCCESS) { + LOGE("Failed to add requestId to moduleParams!"); + return HC_ERR_JSON_FAIL; + } + if (AddIntToJson(moduleParams, FIELD_KEY_LENGTH, DEFAULT_RETURN_KEY_LENGTH) != HC_SUCCESS) { + LOGE("Failed to add sessionKeyLength to moduleParams!"); + return HC_ERR_JSON_FAIL; + } + if (AddBoolToJson(moduleParams, FIELD_IS_CLIENT, isClient) != HC_SUCCESS) { + LOGE("Failed to add isClient to moduleParams!"); + return HC_ERR_JSON_FAIL; + } + /* Use the GroupManager package name. */ + if (AddStringToJson(moduleParams, FIELD_PKG_NAME, GROUP_MANAGER_PACKAGE_NAME) != HC_SUCCESS) { + LOGE("Failed to add pkgName to moduleParams!"); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} + +static int32_t AddPinCodeToParamsIfNeed(BindSession *session, CJson *moduleParams) +{ + if (session->operationCode == MEMBER_DELETE) { + return HC_SUCCESS; + } + const char *pinCode = GetStringFromJson(session->params, FIELD_PIN_CODE); + if (pinCode == NULL) { + LOGE("Failed to get pinCode from params!"); + return HC_ERR_JSON_GET; + } + if (AddStringToJson(moduleParams, FIELD_PIN_CODE, pinCode) != HC_SUCCESS) { + LOGE("Failed to add pinCode to moduleParams!"); + return HC_ERR_JSON_FAIL; + } + /* Release the memory in advance to reduce the memory usage. */ + (void)DeleteItemFromJson(session->params, FIELD_PIN_CODE); + return HC_SUCCESS; +} + +static int32_t AddPeerAuthIdToParams(BindSession *session, CJson *moduleParams) +{ + const char *peerAuthId = GetStringFromJson(session->params, FIELD_PEER_AUTH_ID); + if (peerAuthId == NULL) { + LOGE("Failed to get peerAuthId from params!"); + return HC_ERR_JSON_GET; + } + if (AddStringToJson(moduleParams, FIELD_PEER_AUTH_ID, peerAuthId) != HC_SUCCESS) { + LOGE("Failed to add peerAuthId to moduleParams!"); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} + +static int32_t AddPeerUserTypeToParams(BindSession *session, CJson *moduleParams) +{ + int peerUserType = DEVICE_TYPE_ACCESSORY; + if (GetIntFromJson(session->params, FIELD_PEER_USER_TYPE, &peerUserType) != HC_SUCCESS) { + LOGE("Failed to get peerUserType from params!"); + return HC_ERR_JSON_GET; + } + if (AddIntToJson(moduleParams, FIELD_PEER_USER_TYPE, peerUserType) != HC_SUCCESS) { + LOGE("Failed to add peerUserType to moduleParams!"); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} + +static int32_t AddPeerAuthIdAndUserTypeToParamsIfNeed(BindSession *session, CJson *moduleParams) +{ + if (session->operationCode != MEMBER_DELETE) { + return HC_SUCCESS; + } + int32_t result = AddPeerAuthIdToParams(session, moduleParams); + if (result != HC_SUCCESS) { + return result; + } + return AddPeerUserTypeToParams(session, moduleParams); +} + +static int32_t TryAddPeerUserTypeToParams(const CJson *jsonParams, BindSession *session) +{ + int peerUserType = DEVICE_TYPE_ACCESSORY; + if (GetIntFromJson(jsonParams, FIELD_PEER_USER_TYPE, &peerUserType) == HC_SUCCESS) { + if (AddIntToJson(session->params, FIELD_PEER_USER_TYPE, peerUserType) != HC_SUCCESS) { + LOGE("Failed to add peerUserType to params!"); + return HC_ERR_JSON_FAIL; + } + } + return HC_SUCCESS; +} + +static int32_t AddGroupInfoToParams(const GroupInfo *entry, CJson *params) +{ + if (AddStringToJson(params, FIELD_GROUP_ID, StringGet(&entry->id)) != HC_SUCCESS) { + LOGE("Failed to add groupId to json!"); + return HC_ERR_JSON_FAIL; + } + if (AddIntToJson(params, FIELD_GROUP_TYPE, entry->type) != HC_SUCCESS) { + LOGE("Failed to add groupType to json!"); + return HC_ERR_JSON_FAIL; + } + if (AddStringToJson(params, FIELD_GROUP_NAME, StringGet(&entry->name)) != HC_SUCCESS) { + LOGE("Failed to add groupName to json!"); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} + +static int32_t AddDevInfoToParams(const DeviceInfo *devAuthParams, CJson *params) +{ + if (AddStringToJson(params, FIELD_AUTH_ID, StringGet(&devAuthParams->authId)) != HC_SUCCESS) { + LOGE("Failed to add authId to params!"); + return HC_ERR_JSON_FAIL; + } + if (AddStringToJson(params, FIELD_CONN_DEVICE_ID, StringGet(&devAuthParams->udid)) != HC_SUCCESS) { + LOGE("Failed to add udid to params!"); + return HC_ERR_JSON_FAIL; + } + if (AddIntToJson(params, FIELD_USER_TYPE, devAuthParams->devType) != HC_SUCCESS) { + LOGE("Failed to add userType to params!"); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} + +static int32_t AddGroupInfoByDatabase(const char *groupId, CJson *params) +{ + GroupInfo *entry = CreateGroupInfoStruct(); + if (entry == NULL) { + LOGE("Failed to allocate groupEntry memory!"); + return HC_ERR_ALLOC_MEMORY; + } + if (GetGroupEntryByGroupId(groupId, entry) != HC_SUCCESS) { + LOGE("Failed to obtain the group information from the database!"); + DestroyGroupInfoStruct(entry); + return HC_ERR_DB; + } + if (AddGroupInfoToParams(entry, params) != HC_SUCCESS) { + DestroyGroupInfoStruct(entry); + return HC_ERR_JSON_FAIL; + } + DestroyGroupInfoStruct(entry); + return HC_SUCCESS; +} + +static int32_t AddDevInfoByDatabase(const char *groupId, CJson *params) +{ + uint8_t udid[INPUT_UDID_LEN] = { 0 }; + if (HcGetUdid(udid, INPUT_UDID_LEN) != HC_SUCCESS) { + LOGE("Get local udid failed"); + return HC_ERROR; + } + DeviceInfo *devAuthParams = CreateDeviceInfoStruct(); + if (devAuthParams == NULL) { + LOGE("Failed to allocate devEntry memory!"); + return HC_ERR_ALLOC_MEMORY; + } + if (GetDeviceInfoForDevAuth((const char *)udid, groupId, devAuthParams) != HC_SUCCESS) { + LOGE("Failed to obtain the device information from the database!"); + DestroyDeviceInfoStruct(devAuthParams); + return HC_ERR_DB; + } + if (AddDevInfoToParams(devAuthParams, params) != HC_SUCCESS) { + DestroyDeviceInfoStruct(devAuthParams); + return HC_ERR_JSON_FAIL; + } + DestroyDeviceInfoStruct(devAuthParams); + return HC_SUCCESS; +} + +static int32_t AddGroupId(const char *groupId, CJson *params) +{ + if (AddStringToJson(params, FIELD_GROUP_ID, groupId) != HC_SUCCESS) { + LOGE("Failed to add groupId to params!"); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} + +static int32_t AddGroupName(const CJson *jsonParams, CJson *params) +{ + const char *groupName = GetStringFromJson(jsonParams, FIELD_GROUP_NAME); + if (groupName == NULL) { + LOGE("Failed to get groupName from jsonParams!"); + return HC_ERR_JSON_GET; + } + if (AddStringToJson(params, FIELD_GROUP_NAME, groupName) != HC_SUCCESS) { + LOGE("Failed to add groupName to params!"); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} + +static int32_t AddGroupOwnerIfExist(const CJson *jsonParams, CJson *params) +{ + const char *groupOwner = GetStringFromJson(jsonParams, FIELD_GROUP_OWNER); + if (groupOwner != NULL) { + if (AddStringToJson(params, FIELD_GROUP_OWNER, groupOwner) != HC_SUCCESS) { + LOGE("Failed to add groupOwner to params!"); + return HC_ERR_JSON_FAIL; + } + } + return HC_SUCCESS; +} + +static int32_t AddGroupTypeIfValid(const CJson *jsonParams, CJson *params) +{ + int32_t groupType = PEER_TO_PEER_GROUP; + if (GetIntFromJson(jsonParams, FIELD_GROUP_TYPE, &groupType) != HC_SUCCESS) { + LOGE("Failed to get groupType from in!"); + return HC_ERR_JSON_GET; + } + if (groupType != PEER_TO_PEER_GROUP) { + LOGE("The input groupType is invalid!"); + return HC_ERR_INVALID_PARAMS; + } + if (AddIntToJson(params, FIELD_GROUP_TYPE, groupType) != HC_SUCCESS) { + LOGE("Failed to add groupType to params!"); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} + +static int32_t AddGroupVisibilityIfValidOrDefault(const CJson *jsonParams, CJson *params) +{ + int groupVisibility = GROUP_VISIBILITY_PUBLIC; + (void)GetIntFromJson(jsonParams, FIELD_GROUP_VISIBILITY, &groupVisibility); + if (!IsGroupVisibilityValid(groupVisibility)) { + LOGE("The input groupVisibility is invalid!"); + return HC_ERR_INVALID_PARAMS; + } + if (AddIntToJson(params, FIELD_GROUP_VISIBILITY, groupVisibility) != HC_SUCCESS) { + LOGE("Failed to add groupVisibility to params!"); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} + +static int32_t AddExpireTimeIfValidOrDefault(const CJson *jsonParams, CJson *params) +{ + int expireTime = DEFAULT_EXPIRE_TIME; + (void)GetIntFromJson(jsonParams, FIELD_EXPIRE_TIME, &expireTime); + if (!IsExpireTimeValid(expireTime)) { + LOGE("The input expireTime is invalid!"); + return HC_ERR_INVALID_PARAMS; + } + if (AddIntToJson(params, FIELD_EXPIRE_TIME, expireTime) != HC_SUCCESS) { + LOGE("Failed to add expireTime to params!"); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} + +static int32_t CheckAuthIdAndUserTypeValid(int userType, const char *groupId, const char *authId) +{ + if (!IsGroupExistByGroupId(groupId)) { + return HC_SUCCESS; + } + uint8_t udid[INPUT_UDID_LEN] = { 0 }; + if (HcGetUdid(udid, INPUT_UDID_LEN) != HC_SUCCESS) { + LOGE("Get local udid failed"); + return HC_ERROR; + } + DeviceInfo *deviceInfo = CreateDeviceInfoStruct(); + if (deviceInfo == NULL) { + LOGE("Failed to allocate deviceInfo memory!"); + return HC_ERR_ALLOC_MEMORY; + } + int32_t result = GetDeviceInfoForDevAuth((char *)udid, groupId, deviceInfo); + if (result != HC_SUCCESS) { + LOGE("Failed to obtain the local device information from the database!"); + DestroyDeviceInfoStruct(deviceInfo); + return result; + } + if ((deviceInfo->devType != userType) || (strcmp(StringGet(&deviceInfo->authId), authId) != 0)) { + LOGE("Once a group is created, the service cannot change the local authId and userType used in the group!"); + DestroyDeviceInfoStruct(deviceInfo); + return HC_ERR_INVALID_PARAMS; + } + DestroyDeviceInfoStruct(deviceInfo); + return HC_SUCCESS; +} + +static int32_t AddAuthIdAndUserTypeIfValidOrDefault(const char *groupId, const CJson *jsonParams, CJson *params) +{ + int userType = DEVICE_TYPE_ACCESSORY; + (void)GetIntFromJson(jsonParams, FIELD_USER_TYPE, &userType); + if (!IsUserTypeValid(userType)) { + LOGE("The input userType is invalid!"); + return HC_ERR_INVALID_PARAMS; + } + uint8_t udid[INPUT_UDID_LEN] = { 0 }; + const char *authId = GetStringFromJson(jsonParams, FIELD_DEVICE_ID); + if (authId == NULL) { + LOGD("No authId is found. The default value is udid!"); + if (HcGetUdid(udid, INPUT_UDID_LEN) != HC_SUCCESS) { + LOGE("Get local udid failed"); + return HC_ERROR; + } + authId = (const char *)udid; + } + int32_t result = CheckAuthIdAndUserTypeValid(userType, groupId, authId); + if (result != HC_SUCCESS) { + return result; + } + if (AddIntToJson(params, FIELD_USER_TYPE, userType) != HC_SUCCESS) { + LOGE("Failed to add userType to params!"); + return HC_ERR_JSON_FAIL; + } + if (AddStringToJson(params, FIELD_AUTH_ID, authId) != HC_SUCCESS) { + LOGE("Failed to add authId to params!"); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} + +static int32_t AddUdid(CJson *params) +{ + uint8_t udid[INPUT_UDID_LEN] = { 0 }; + if (HcGetUdid(udid, INPUT_UDID_LEN) != HC_SUCCESS) { + LOGE("Get local udid failed"); + return HC_ERROR; + } + if (AddStringToJson(params, FIELD_CONN_DEVICE_ID, (const char *)udid) != HC_SUCCESS) { + LOGE("Failed to add udid to params!"); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} + +static int32_t AddUserTypeIfValidOrDefault(const CJson *jsonParams, CJson *params) +{ + int userType = DEVICE_TYPE_ACCESSORY; + (void)GetIntFromJson(jsonParams, FIELD_USER_TYPE, &userType); + if (!IsUserTypeValid(userType)) { + LOGE("The input userType is invalid!"); + return HC_ERR_INVALID_PARAMS; + } + if (AddIntToJson(params, FIELD_USER_TYPE, userType) != HC_SUCCESS) { + LOGE("Failed to add userType to params!"); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} + +static int32_t AddGroupInfoToSessionParams(const char *groupId, const CJson *jsonParams, CJson *params) +{ + int32_t result; + if (((result = AddGroupId(groupId, params)) != HC_SUCCESS) || + ((result = AddGroupName(jsonParams, params)) != HC_SUCCESS) || + ((result = AddGroupOwnerIfExist(jsonParams, params)) != HC_SUCCESS) || + ((result = AddGroupTypeIfValid(jsonParams, params)) != HC_SUCCESS) || + ((result = AddGroupVisibilityIfValidOrDefault(jsonParams, params)) != HC_SUCCESS) || + ((result = AddExpireTimeIfValidOrDefault(jsonParams, params)) != HC_SUCCESS)) { + return result; + } + return HC_SUCCESS; +} + +static int32_t AddDevInfoToSessionParams(const char *groupId, const CJson *jsonParams, CJson *params) +{ + int32_t result; + if (((result = AddAuthIdAndUserTypeIfValidOrDefault(groupId, jsonParams, params)) != HC_SUCCESS) || + ((result = AddUdid(params)) != HC_SUCCESS) || + ((result = AddUserTypeIfValidOrDefault(jsonParams, params)) != HC_SUCCESS)) { + return result; + } + return HC_SUCCESS; +} + +static int32_t GenerateParamsByInput(const char *groupId, const CJson *jsonParams, CJson *params) +{ + int32_t result = AddGroupInfoToSessionParams(groupId, jsonParams, params); + if (result != HC_SUCCESS) { + return result; + } + return AddDevInfoToSessionParams(groupId, jsonParams, params); +} + +static int32_t GenerateParamsByDatabase(const char *groupId, CJson *params) +{ + int32_t result = AddGroupInfoByDatabase(groupId, params); + if (result != HC_SUCCESS) { + return result; + } + return AddDevInfoByDatabase(groupId, params); +} + +static int32_t AddIsForceDeleteIfNeed(int isClient, const CJson *jsonParams, BindSession *session) +{ + if ((isClient == CLIENT) && (session->operationCode == MEMBER_DELETE)) { + bool isForceDelete = false; + if (GetBoolFromJson(jsonParams, FIELD_IS_FORCE_DELETE, &isForceDelete) != HC_SUCCESS) { + LOGE("Failed to get isForceDelete from jsonParams!"); + return HC_ERR_JSON_GET; + } + if (AddBoolToJson(session->params, FIELD_IS_FORCE_DELETE, isForceDelete) != HC_SUCCESS) { + LOGE("Failed to add isForceDelete to params!"); + return HC_ERR_JSON_FAIL; + } + } + return HC_SUCCESS; +} + +static int32_t AddChannelIdIfNeed(int isClient, const CJson *jsonParams, BindSession *session) +{ + if ((isClient == SERVER) && (session->channelType == SOFT_BUS)) { + int64_t channelId = DEFAULT_CHANNEL_ID; + if (GetByteFromJson(jsonParams, FIELD_CHANNEL_ID, (uint8_t *)&channelId, sizeof(int64_t)) != HC_SUCCESS) { + LOGE("Failed to get channelId from jsonParams!"); + return HC_ERR_JSON_GET; + } + session->channelId = channelId; + } + return HC_SUCCESS; +} + +static int32_t AddPinCodeIfNeed(const CJson *jsonParams, BindSession *session) +{ + if (session->operationCode != MEMBER_DELETE) { + const char *pinCode = GetStringFromJson(jsonParams, FIELD_PIN_CODE); + if (pinCode == NULL) { + LOGE("Failed to get pinCode from jsonParams!"); + return HC_ERR_JSON_GET; + } + if (AddStringToJson(session->params, FIELD_PIN_CODE, pinCode) != HC_SUCCESS) { + LOGE("Failed to add pinCode to params!"); + return HC_ERR_JSON_FAIL; + } + } + return HC_SUCCESS; +} + +static int32_t AddPeerAuthIdAndUdidIfExist(const CJson *jsonParams, BindSession *session) +{ + const char *peerAuthId = GetStringFromJson(jsonParams, FIELD_PEER_DEVICE_ID); + const char *peerUdid = GetStringFromJson(jsonParams, FIELD_PEER_UDID); + if (peerAuthId != NULL) { + if (AddStringToJson(session->params, FIELD_PEER_AUTH_ID, peerAuthId) != HC_SUCCESS) { + LOGE("Failed to add peerAuthId to params!"); + return HC_ERR_JSON_FAIL; + } + } + if (peerUdid != NULL) { + if (AddStringToJson(session->params, FIELD_PEER_UDID, peerUdid) != HC_SUCCESS) { + LOGE("Failed to add peerUdid to params!"); + return HC_ERR_JSON_FAIL; + } + } + return HC_SUCCESS; +} + +static int32_t AddPeerAuthIdIfDelete(bool isClient, const CJson *jsonParams, BindSession *session) +{ + const char *peerAuthId = NULL; + if (isClient) { + peerAuthId = GetStringFromJson(jsonParams, FIELD_DELETE_ID); + } else { + peerAuthId = GetStringFromJson(jsonParams, FIELD_PEER_DEVICE_ID); + } + if (peerAuthId == NULL) { + LOGE("Failed to get peerAuthId from jsonParams!"); + return HC_ERR_JSON_GET; + } + if (AddStringToJson(session->params, FIELD_PEER_AUTH_ID, peerAuthId) != HC_SUCCESS) { + LOGE("Failed to add peerAuthId to params!"); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} + +static int32_t AddPeerUserTypeIfDelete(BindSession *session) +{ + const char *peerAuthId = GetStringFromJson(session->params, FIELD_PEER_AUTH_ID); + if (peerAuthId == NULL) { + LOGE("Failed to get peerAuthId from params!"); + return HC_ERR_JSON_GET; + } + const char *groupId = GetStringFromJson(session->params, FIELD_GROUP_ID); + if (groupId == NULL) { + LOGE("Failed to get groupId from params!"); + return HC_ERR_JSON_GET; + } + DeviceInfo *devAuthParams = CreateDeviceInfoStruct(); + if (devAuthParams == NULL) { + LOGE("Failed to allocate devEntry memory!"); + return HC_ERR_ALLOC_MEMORY; + } + if (GetDeviceInfoByAuthId(peerAuthId, groupId, devAuthParams) != HC_SUCCESS) { + LOGE("Failed to obtain the device information from the database!"); + DestroyDeviceInfoStruct(devAuthParams); + return HC_ERR_DB; + } + if (AddIntToJson(session->params, FIELD_PEER_USER_TYPE, devAuthParams->devType) != HC_SUCCESS) { + DestroyDeviceInfoStruct(devAuthParams); + return HC_ERR_JSON_FAIL; + } + DestroyDeviceInfoStruct(devAuthParams); + return HC_SUCCESS; +} + +static int32_t AddPeerDevInfoIfNeed(bool isClient, const CJson *jsonParams, BindSession *session) +{ + if (session->operationCode == MEMBER_DELETE) { + int32_t result = AddPeerAuthIdIfDelete(isClient, jsonParams, session); + if (result != HC_SUCCESS) { + return result; + } + return AddPeerUserTypeIfDelete(session); + } + return AddPeerAuthIdAndUdidIfExist(jsonParams, session); +} + +static int32_t AddGroupAndDevInfo(int isClient, const CJson *jsonParams, BindSession *session) +{ + const char *groupId = GetStringFromJson(jsonParams, FIELD_GROUP_ID); + if (groupId == NULL) { + LOGE("Failed to get groupId from jsonParams!"); + return HC_ERR_JSON_GET; + } + if (NeedCreateGroup(isClient, session->operationCode)) { + return GenerateParamsByInput(groupId, jsonParams, session->params); + } else { + return GenerateParamsByDatabase(groupId, session->params); + } +} + +static int32_t AddAppId(const CJson *jsonParams, BindSession *session) +{ + const char *appId = GetStringFromJson(jsonParams, FIELD_APP_ID); + if (appId == NULL) { + LOGE("Failed to get appId from in!"); + return HC_ERR_JSON_GET; + } + if (AddStringToJson(session->params, FIELD_APP_ID, appId) != HC_SUCCESS) { + LOGE("Failed to add appId to params!"); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} + +static int32_t InteractWithPeer(const BindSession *session, CJson *sendData) +{ + int32_t result = AddInfoToSendData(false, session, sendData); + if (result != HC_SUCCESS) { + LOGE("Failed to generate sendData!"); + return result; + } + return SendBindSessionData(session, sendData); +} + +static int32_t InformSelfBindSuccess(const char *peerAuthId, const char *groupId, const BindSession *session, + CJson *out) +{ + uint8_t sessionKey[DEFAULT_RETURN_KEY_LENGTH] = { 0 }; + if (GetByteFromJson(out, FIELD_SESSION_KEY, sessionKey, DEFAULT_RETURN_KEY_LENGTH) == HC_SUCCESS) { + ProcessSessionKeyCallback(session->requestId, sessionKey, DEFAULT_RETURN_KEY_LENGTH, session->base.callback); + (void)memset_s(sessionKey, DEFAULT_RETURN_KEY_LENGTH, 0, DEFAULT_RETURN_KEY_LENGTH); + ClearSensitiveStringInJson(out, FIELD_SESSION_KEY); + } + + char *jsonDataStr = NULL; + int32_t result = GenerateBindSuccessData(peerAuthId, groupId, &jsonDataStr); + if (result != HC_SUCCESS) { + LOGE("Failed to generate the data to be sent to the service!"); + return result; + } + ProcessFinishCallback(session->requestId, session->operationCode, jsonDataStr, session->base.callback); + FreeJsonString(jsonDataStr); + return HC_SUCCESS; +} + +static int32_t InformSelfUnbindSuccess(const char *peerAuthId, const char *groupId, const BindSession *session) +{ + char *jsonDataStr = NULL; + int32_t result = GenerateUnbindSuccessData(peerAuthId, groupId, &jsonDataStr); + if (result != HC_SUCCESS) { + LOGE("Failed to generate the data to be sent to the service!"); + return result; + } + ProcessFinishCallback(session->requestId, session->operationCode, jsonDataStr, session->base.callback); + FreeJsonString(jsonDataStr); + return HC_SUCCESS; +} + +static int32_t SetGroupId(const CJson *params, GroupInfo *groupParams) +{ + const char *groupId = GetStringFromJson(params, FIELD_GROUP_ID); + if (groupId == NULL) { + LOGE("Failed to get groupId from params!"); + return HC_ERR_JSON_GET; + } + if (!StringSetPointer(&groupParams->id, groupId)) { + LOGE("Failed to copy groupId!"); + return HC_ERR_MEMORY_COPY; + } + return HC_SUCCESS; +} + +static int32_t SetGroupName(const CJson *params, GroupInfo *groupParams) +{ + const char *groupName = GetStringFromJson(params, FIELD_GROUP_NAME); + if (groupName == NULL) { + LOGE("Failed to get groupName from params!"); + return HC_ERR_JSON_GET; + } + if (!StringSetPointer(&groupParams->name, groupName)) { + LOGE("Failed to copy groupName!"); + return HC_ERR_MEMORY_COPY; + } + return HC_SUCCESS; +} + +static int32_t SetGroupOwner(const CJson *params, GroupInfo *groupParams) +{ + const char *groupOwner = GetStringFromJson(params, FIELD_APP_ID); + if (groupOwner == NULL) { + LOGE("Failed to get appId from params!"); + return HC_ERR_JSON_GET; + } + if (!StringSetPointer(&groupParams->ownerName, groupOwner)) { + LOGE("Failed to copy groupOwner!"); + return HC_ERR_MEMORY_COPY; + } + return HC_SUCCESS; +} + +static int32_t SetGroupType(const CJson *params, GroupInfo *groupParams) +{ + int32_t groupType = PEER_TO_PEER_GROUP; + if (GetIntFromJson(params, FIELD_GROUP_TYPE, &groupType) != HC_SUCCESS) { + LOGE("Failed to get groupType from params!"); + return HC_ERR_JSON_GET; + } + groupParams->type = groupType; + return HC_SUCCESS; +} + +static int32_t SetGroupVisibility(const CJson *params, GroupInfo *groupParams) +{ + int groupVisibility = GROUP_VISIBILITY_PUBLIC; + (void)GetIntFromJson(params, FIELD_GROUP_VISIBILITY, &groupVisibility); + groupParams->visibility = groupVisibility; + return HC_SUCCESS; +} + +static int32_t SetGroupExpireTime(const CJson *params, GroupInfo *groupParams) +{ + int expireTime = DEFAULT_EXPIRE_TIME; + (void)GetIntFromJson(params, FIELD_EXPIRE_TIME, &expireTime); + groupParams->expireTime = expireTime; + return HC_SUCCESS; +} + +static int32_t ForceDeletePeerKey(CJson *params) +{ + /* Use the DeviceGroupManager package name. */ + const char *appId = GROUP_MANAGER_PACKAGE_NAME; + const char *peerAuthId = GetStringFromJson(params, FIELD_PEER_AUTH_ID); + if (peerAuthId == NULL) { + LOGE("Failed to get peerAuthId from params!"); + return HC_ERR_JSON_GET; + } + const char *groupId = GetStringFromJson(params, FIELD_GROUP_ID); + if (groupId == NULL) { + LOGE("Failed to get groupId from params!"); + return HC_ERR_JSON_GET; + } + int peerUserType = DEVICE_TYPE_ACCESSORY; + (void)GetIntFromJson(params, FIELD_PEER_USER_TYPE, &peerUserType); + Uint8Buff peerAuthIdBuff = { + .val = (uint8_t *)peerAuthId, + .length = HcStrlen(peerAuthId) + }; + return DeletePeerAuthInfo(appId, groupId, &peerAuthIdBuff, peerUserType, DAS_MODULE); +} + +static int32_t GenerateGroupParams(const CJson *params, GroupInfo *groupParams) +{ + int32_t result; + if (((result = SetGroupId(params, groupParams)) != HC_SUCCESS) || + ((result = SetGroupName(params, groupParams)) != HC_SUCCESS) || + ((result = SetGroupOwner(params, groupParams)) != HC_SUCCESS) || + ((result = SetGroupType(params, groupParams)) != HC_SUCCESS) || + ((result = SetGroupVisibility(params, groupParams)) != HC_SUCCESS) || + ((result = SetGroupExpireTime(params, groupParams)) != HC_SUCCESS)) { + return result; + } + return HC_SUCCESS; +} + +static int32_t AddGroupToDatabase(const CJson *params) +{ + GroupInfo *groupParams = CreateGroupInfoStruct(); + if (groupParams == NULL) { + LOGE("Failed to allocate groupParams memory!"); + return HC_ERR_ALLOC_MEMORY; + } + int32_t result = GenerateGroupParams(params, groupParams); + if (result != HC_SUCCESS) { + LOGE("Failed to generate groupParams!"); + DestroyGroupInfoStruct(groupParams); + return HC_ERR_DB; + } + result = AddGroup(groupParams); + DestroyGroupInfoStruct(groupParams); + if (result != HC_SUCCESS) { + LOGE("Failed to add the group to the database!"); + return HC_ERR_DB; + } + return HC_SUCCESS; +} + +static int32_t GenerateDevAuthParams(const char *authId, const char *udid, const char *groupId, + int userType, DeviceInfo *devAuthParams) +{ + devAuthParams->devType = userType; + StringSetPointer(&(devAuthParams->authId), authId); + StringSetPointer(&(devAuthParams->udid), udid); + StringSetPointer(&(devAuthParams->groupId), groupId); + StringSetPointer(&(devAuthParams->serviceType), groupId); + return HC_SUCCESS; +} + +static int32_t AddTrustDevToDatabase(const char *authId, const char *udid, const char *groupId, int userType) +{ + DeviceInfo *devAuthParams = CreateDeviceInfoStruct(); + if (devAuthParams == NULL) { + LOGE("Failed to allocate devAuthParams memory!"); + return HC_ERR_ALLOC_MEMORY; + } + int32_t result = GenerateDevAuthParams(authId, udid, groupId, userType, devAuthParams); + if (result != HC_SUCCESS) { + LOGE("Failed to generate devAuthParams!"); + DestroyDeviceInfoStruct(devAuthParams); + return result; + } + result = AddTrustedDevice(devAuthParams, NULL); + DestroyDeviceInfoStruct(devAuthParams); + if (result != HC_SUCCESS) { + LOGE("Failed to add the trusted devices to the database!"); + return HC_ERR_DB; + } + return HC_SUCCESS; +} + +static int32_t AddGroupAndLocalDevIfNotExist(const char *groupId, const BindSession *session) +{ + int32_t result = HC_SUCCESS; + if (!IsGroupExistByGroupId(groupId)) { + result = AddGroupToDatabase(session->params); + if (result != HC_SUCCESS) { + return result; + } + uint8_t udid[INPUT_UDID_LEN] = { 0 }; + if (HcGetUdid(udid, INPUT_UDID_LEN) != HC_SUCCESS) { + LOGE("Get local udid failed"); + return HC_ERROR; + } + const char *authId = GetStringFromJson(session->params, FIELD_AUTH_ID); + if (authId == NULL) { + LOGI("No authId is found. The default value is udid!"); + authId = (const char *)udid; + } + int userType = DEVICE_TYPE_ACCESSORY; + (void)GetIntFromJson(session->params, FIELD_USER_TYPE, &userType); + return AddTrustDevToDatabase(authId, (char *)udid, groupId, userType); + } + LOGI("The group corresponding to the groupId already exists. " + "Therefore, the group will not be created again, and some data transferred by the service may be ignored!"); + return result; +} + +static int32_t AddPeerDevToGroup(const char *peerAuthId, const char *peerUdid, + const char *groupId, const BindSession *session) +{ + if (IsTrustedDeviceInGroupByAuthId(groupId, peerAuthId)) { + LOGI("The peer device already exists in the group! RequestId: %lld", session->requestId); + if (DelTrustedDeviceByAuthId(peerAuthId, groupId) != HC_SUCCESS) { + LOGE("Failed to delete the original data! RequestId: %lld", session->requestId); + return HC_ERR_DB; + } + LOGI("Delete the original data successfully! RequestId: %lld", session->requestId); + } + int peerUserType = DEVICE_TYPE_ACCESSORY; + (void)GetIntFromJson(session->params, FIELD_PEER_USER_TYPE, &peerUserType); + int32_t result = AddTrustDevToDatabase(peerAuthId, peerUdid, groupId, peerUserType); + if (result != HC_SUCCESS) { + LOGE("Failed to update the peer trusted device information! RequestId: %lld", session->requestId); + return result; + } + LOGI("The peer trusted device is added to the database successfully! RequestId: %lld", session->requestId); + return HC_SUCCESS; +} + +static int32_t AddGroupAndDev(const char *peerAuthId, const char *peerUdid, + const char *groupId, const BindSession *session) +{ + int32_t result = AddGroupAndLocalDevIfNotExist(groupId, session); + if (result != HC_SUCCESS) { + return result; + } + return AddPeerDevToGroup(peerAuthId, peerUdid, groupId, session); +} + +static int32_t HandleBindSuccess(const char *peerAuthId, const char *peerUdid, + const char *groupId, const BindSession *session, CJson *out) +{ + int32_t result = AddGroupAndDev(peerAuthId, peerUdid, groupId, session); + if (result != HC_SUCCESS) { + return result; + } + return InformSelfBindSuccess(peerAuthId, groupId, session, out); +} + +static int32_t HandleUnbindSuccess(const char *peerAuthId, const char *groupId, const BindSession *session) +{ + if (IsGroupExistByGroupId(groupId)) { + if (DelTrustedDeviceByAuthId(peerAuthId, groupId) != HC_SUCCESS) { + LOGE("Failed to unbind device from database!"); + return HC_ERR_DB; + } + LOGI("The device is successfully unbound from the database!"); + } + return InformSelfUnbindSuccess(peerAuthId, groupId, session); +} + +static int32_t OnBindOrUnbindFinish(const BindSession *session, const CJson *jsonParams, CJson *out) +{ + const char *peerAuthId = GetStringFromJson(jsonParams, FIELD_PEER_DEVICE_ID); + if (peerAuthId == NULL) { + peerAuthId = GetStringFromJson(session->params, FIELD_PEER_AUTH_ID); + } + if (peerAuthId == NULL) { + LOGE("Failed to get peerAuthId from jsonParams and params!"); + return HC_ERR_JSON_GET; + } + const char *peerUdid = GetStringFromJson(jsonParams, FIELD_CONN_DEVICE_ID); + if (peerUdid == NULL) { + peerUdid = GetStringFromJson(session->params, FIELD_PEER_UDID); + } + if (peerUdid == NULL) { + LOGE("Failed to get peerUdid from jsonParams and params!"); + return HC_ERR_JSON_GET; + } + const char *groupId = GetStringFromJson(session->params, FIELD_GROUP_ID); + if (groupId == NULL) { + LOGE("Failed to get groupId from session params!"); + return HC_ERR_JSON_GET; + } + if (session->operationCode == MEMBER_DELETE) { + return HandleUnbindSuccess(peerAuthId, groupId, session); + } else { + return HandleBindSuccess(peerAuthId, peerUdid, groupId, session, out); + } +} + +static int32_t OnSessionFinish(const BindSession *session, CJson *jsonParams, CJson *out) +{ + int32_t result; + CJson *sendData = GetObjFromJson(out, FIELD_SEND_TO_PEER); + /* The last packet may need to be sent. */ + if (sendData != NULL) { + result = InteractWithPeer(session, sendData); + if (result != HC_SUCCESS) { + return result; + } + } + result = OnBindOrUnbindFinish(session, jsonParams, out); + if (result != HC_SUCCESS) { + LOGE("An error occurred when processing different end operations!"); + return result; + } + LOGI("The device is successfully %s!", (session->operationCode == MEMBER_DELETE) ? "unbound" : "bound"); + SetAuthResult(session->channelType, session->channelId); + CloseChannel(session->channelType, session->channelId); + return HC_SUCCESS; +} + +static int32_t CheckPeerStatus(const CJson *jsonParams, bool *isNeedInform) +{ + int32_t errorCode = 0; + if (GetIntFromJson(jsonParams, FIELD_GROUP_ERROR_MSG, &errorCode) == HC_SUCCESS) { + LOGE("An error occurs in the peer service! [ErrorCode]: %d", errorCode); + *isNeedInform = false; + return errorCode; + } + return HC_SUCCESS; +} + +static CJson *GenerateGroupErrorMsg(int32_t errorCode, int64_t requestId) +{ + CJson *errorData = CreateJson(); + if (errorData == NULL) { + LOGE("Failed to allocate errorData memory!"); + return NULL; + } + if (AddIntToJson(errorData, FIELD_GROUP_ERROR_MSG, errorCode) != HC_SUCCESS) { + LOGE("Failed to add errorCode to errorData!"); + FreeJson(errorData); + return NULL; + } + if (AddInt64StringToJson(errorData, FIELD_REQUEST_ID, requestId) != HC_SUCCESS) { + LOGE("Failed to add requestId to errorData!"); + FreeJson(errorData); + return NULL; + } + return errorData; +} + +static int32_t ProcessBindSessionInner(BindSession *session, CJson *jsonParams, int32_t *status, bool *isNeedInform) +{ + int32_t result; + if (((result = CheckPeerStatus(jsonParams, isNeedInform)) != HC_SUCCESS) || + ((result = TryAddPeerUserTypeToParams(jsonParams, session))) != HC_SUCCESS) { + return result; + } + + CJson *out = CreateJson(); + if (out == NULL) { + LOGE("Failed to allocate out memory!"); + return HC_ERR_JSON_FAIL; + } + result = ProcessModule(session, jsonParams, out, status); + if (result != HC_SUCCESS) { + *isNeedInform = false; + InformPeerModuleErrorIfNeed(out, session); + FreeJson(out); + return result; + } + if (*status == IGNORE_MSG) { + FreeJson(out); + return HC_SUCCESS; + } else if (*status == CONTINUE) { + DeleteAllItem(jsonParams); + CJson *sendData = DetachItemFromJson(out, FIELD_SEND_TO_PEER); + FreeJson(out); + if (sendData == NULL) { + LOGE("Failed to get sendToPeer from out!"); + return HC_ERR_JSON_GET; + } + result = InteractWithPeer(session, sendData); + FreeJson(sendData); + return result; + } + result = OnSessionFinish(session, jsonParams, out); + FreeJson(out); + return result; +} + +static int32_t ProcessBindSession(Session *session, CJson *jsonParams) +{ + if ((session == NULL) || (jsonParams == NULL)) { + LOGE("The input session or jsonParams is NULL!"); + return HC_ERR_INVALID_PARAMS; + } + BindSession *realSession = (BindSession *)session; + LOGI("Start to process bind session! [RequestId]: %lld, [OperationCode]: %d", + realSession->requestId, realSession->operationCode); + + bool isNeedInform = true; + int32_t status = CONTINUE; + int32_t result = ProcessBindSessionInner(realSession, jsonParams, &status, &isNeedInform); + if (result != HC_SUCCESS) { + LOGE("An error occurs during processing bind session. We need to notify the service!"); + InformPeerProcessErrorIfNeed(isNeedInform, result, realSession); + if ((!NeedForceDelete(realSession)) || (ForceUnbindDevice(realSession) != HC_SUCCESS)) { + ProcessErrorCallback(realSession->requestId, realSession->operationCode, result, NULL, + realSession->base.callback); + } + CloseChannel(realSession->channelType, realSession->channelId); + return result; + } + LOGI("Process bind session successfully! [RequestId]: %lld, [OperationCode]: %d", + realSession->requestId, realSession->operationCode); + if (status == FINISH) { + return status; + } + return result; +} + +bool NeedCreateGroup(int isClient, int operationCode) +{ + if (((isClient == CLIENT) && (operationCode == MEMBER_JOIN)) || + ((isClient == SERVER) && (operationCode == MEMBER_INVITE))) { + return true; + } else { + return false; + } +} + +bool NeedForceDelete(const BindSession *session) +{ + bool needForceDelete = false; + (void)GetBoolFromJson(session->params, FIELD_IS_FORCE_DELETE, &needForceDelete); + return needForceDelete; +} + +int32_t ForceUnbindDevice(const BindSession *session) +{ + const char *peerAuthId = GetStringFromJson(session->params, FIELD_PEER_AUTH_ID); + if (peerAuthId == NULL) { + LOGE("Failed to get peerAuthId from jsonParams!"); + return HC_ERR_JSON_GET; + } + const char *groupId = GetStringFromJson(session->params, FIELD_GROUP_ID); + if (groupId == NULL) { + LOGE("Failed to get groupId from jsonParams!"); + return HC_ERR_JSON_GET; + } + int32_t result = DelTrustedDeviceByAuthId(peerAuthId, groupId); + if (result != HC_SUCCESS) { + LOGE("Failed to delete trust device from database!"); + return result; + } + /* + * If the trusted device has been deleted from the database but the peer key fails to be deleted, + * the forcible unbinding is still considered successful. Only logs need to be printed. + */ + result = ForceDeletePeerKey(session->params); + if (result != HC_SUCCESS) { + LOGE("Failed to delete peer key!"); + } + LOGI("An error occurs during the online unbinding. Therefore, we forcibly unbind the peer device!"); + char *returnDataStr = NULL; + result = GenerateUnbindSuccessData(peerAuthId, groupId, &returnDataStr); + if (result != HC_SUCCESS) { + return result; + } + ProcessFinishCallback(session->requestId, MEMBER_DELETE, returnDataStr, session->base.callback); + FreeJsonString(returnDataStr); + return HC_SUCCESS; +} + +int32_t GenerateBindParams(int isClient, const CJson *jsonParams, BindSession *session) +{ + if (session->params == NULL) { + session->params = CreateJson(); + if (session->params == NULL) { + LOGE("Failed to allocate session params memory!"); + return HC_ERR_ALLOC_MEMORY; + } + } + + int32_t result; + if (((result = AddAppId(jsonParams, session)) != HC_SUCCESS) || + ((result = AddIsForceDeleteIfNeed(isClient, jsonParams, session)) != HC_SUCCESS) || + ((result = AddChannelIdIfNeed(isClient, jsonParams, session)) != HC_SUCCESS) || + ((result = AddPinCodeIfNeed(jsonParams, session)) != HC_SUCCESS) || + ((result = AddGroupAndDevInfo(isClient, jsonParams, session)) != HC_SUCCESS) || + ((result = AddPeerDevInfoIfNeed(isClient, jsonParams, session)) != HC_SUCCESS)) { + return result; + } + return HC_SUCCESS; +} + +int32_t SendBindSessionData(const BindSession *session, const CJson *sendData) +{ + char *sendDataStr = PackJsonToString(sendData); + if (sendDataStr == NULL) { + LOGE("An error occurred when converting json to string!"); + return HC_ERR_JSON_FAIL; + } + int32_t result = SendMsg(session->channelType, session->requestId, + session->channelId, session->base.callback, sendDataStr); + FreeJsonString(sendDataStr); + return result; +} + +void InformPeerProcessErrorIfNeed(bool isNeedInform, int32_t errorCode, const BindSession *session) +{ + if (!isNeedInform) { + return; + } + CJson *errorData = GenerateGroupErrorMsg(errorCode, session->requestId); + if (errorData == NULL) { + return; + } + int32_t result = SendBindSessionData(session, errorData); + FreeJson(errorData); + if (result != HC_SUCCESS) { + LOGE("An error occurred when notifying the peer service!"); + return; + } + LOGI("Succeeded in notifying the peer device that an error occurred at the local end!"); +} + +void InformPeerModuleErrorIfNeed(CJson *out, const BindSession *session) +{ + CJson *errorData = GetObjFromJson(out, FIELD_SEND_TO_PEER); + if (errorData == NULL) { + return; + } + if (AddInt64StringToJson(errorData, FIELD_REQUEST_ID, session->requestId) != HC_SUCCESS) { + LOGE("Failed to add requestId to errorData!"); + return; + } + int32_t result = SendBindSessionData(session, errorData); + if (result != HC_SUCCESS) { + LOGE("An error occurred when notifying the peer service!"); + return; + } + LOGI("Succeeded in notifying the peer device that an error occurred at the local end!"); +} + +void DestroyBindSession(Session *session) +{ + if (session == NULL) { + return; + } + BindSession *realSession = (BindSession *)session; + DestroyTask(realSession->curTaskId, DAS_MODULE); + FreeJson(realSession->params); + realSession->params = NULL; + HcFree(realSession); + realSession = NULL; +} + +int32_t ProcessModule(const BindSession *session, const CJson *in, CJson *out, int *status) +{ + LOGI("Start to process DAS module task!"); + int32_t result = ProcessTask(session->curTaskId, in, out, status, DAS_MODULE); + if (result != HC_SUCCESS) { + LOGE("An error occurs when the module processes task! [ErrorCode]: %d", result); + return result; + } + LOGI("Process DAS module task successfully!"); + return HC_SUCCESS; +} + +int32_t CreateAndProcessModule(BindSession *session, const CJson *in, CJson *out) +{ + int status = 0; + LOGI("Start to create and process DAS module task!"); + int32_t result = CreateTask(&(session->curTaskId), in, out, DAS_MODULE); + if (result != HC_SUCCESS) { + LOGE("An error occurs when creating a module task! [ErrorCode]: %d", result); + return result; + } + result = ProcessTask(session->curTaskId, in, out, &status, DAS_MODULE); + if (result != HC_SUCCESS) { + LOGE("An error occurs when the module processes task! [ErrorCode]: %d", result); + return result; + } + LOGI("Create and process DAS module task successfully!"); + return HC_SUCCESS; +} + +int32_t AddInfoToSendData(bool isNeedCompatibleInfo, const BindSession *session, CJson *data) +{ + int32_t result; + if (((result = AddGroupInfoToSendData(session, data)) != HC_SUCCESS) || + ((result = AddDevInfoToSendData(session, data)) != HC_SUCCESS) || + ((result = AddRequestInfoToSendData(session, data)) != HC_SUCCESS) || + ((result = AddCompatibleInfoToSendData(isNeedCompatibleInfo, data)) != HC_SUCCESS)) { + return result; + } + return HC_SUCCESS; +} + +int32_t GenerateBasicModuleParams(bool isClient, BindSession *session, CJson *moduleParams) +{ + int32_t result; + if (((result = AddGroupAndDevInfoToParams(session, moduleParams)) != HC_SUCCESS) || + ((result = AddRequestInfoToParams(isClient, session, moduleParams)) != HC_SUCCESS) || + ((result = AddPinCodeToParamsIfNeed(session, moduleParams)) != HC_SUCCESS) || + ((result = AddPeerAuthIdAndUserTypeToParamsIfNeed(session, moduleParams)) != HC_SUCCESS)) { + return result; + } + return HC_SUCCESS; +} + +void InitBindSession(int bindType, int operationCode, int64_t requestId, const DeviceAuthCallback *callback, + BindSession *session) +{ + session->base.process = ProcessBindSession; + session->base.destroy = DestroyBindSession; + session->curTaskId = 0; + session->base.callback = callback; + int res = GenerateSessionOrTaskId(&session->base.sessionId); + if (res != 0) { + return; + } + session->base.type = bindType; + session->channelType = NO_CHANNEL; + session->operationCode = operationCode; + session->requestId = requestId; + session->channelId = DEFAULT_CHANNEL_ID; + session->isWaiting = HC_FALSE; + session->params = NULL; + session->onChannelOpened = NULL; + session->onConfirmationReceived = NULL; +} \ No newline at end of file diff --git a/services/session/src/bind_session/bind_session_server.c b/services/session/src/bind_session/bind_session_server.c new file mode 100644 index 0000000..dd3dd5f --- /dev/null +++ b/services/session/src/bind_session/bind_session_server.c @@ -0,0 +1,494 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "bind_session_server.h" +#include "callback_manager.h" +#include "channel_manager.h" +#include "das_module_defines.h" +#include "group_common.h" +#include "hc_log.h" +#include "session_manager.h" + +static int32_t AddRecvModuleDataToParams(CJson *jsonParams, CJson *moduleParams) +{ + int message = ERR_MESSAGE; + if (GetIntFromJson(jsonParams, FIELD_MESSAGE, &message) != HC_SUCCESS) { + LOGE("Failed to get message from in!"); + return HC_ERR_JSON_GET; + } + int authForm = ERR_AUTH_FORM; + (void)GetIntFromJson(jsonParams, FIELD_AUTH_FORM, &authForm); + CJson *payload = GetObjFromJson(jsonParams, FIELD_PAYLOAD); + if (payload == NULL) { + LOGE("Failed to get payload from in!"); + return HC_ERR_JSON_GET; + } + if (AddIntToJson(moduleParams, FIELD_MESSAGE, message) != HC_SUCCESS) { + LOGE("Failed to add message to moduleParams!"); + return HC_ERR_JSON_FAIL; + } + if (AddIntToJson(moduleParams, FIELD_AUTH_FORM, authForm) != HC_SUCCESS) { + LOGE("Failed to add authForm to moduleParams!"); + return HC_ERR_JSON_FAIL; + } + if (AddObjToJson(moduleParams, FIELD_PAYLOAD, payload) != HC_SUCCESS) { + LOGE("Failed to add payload to moduleParams!"); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} + +static int32_t AddConfirmationToParams(CJson *moduleParams) +{ + if (AddIntToJson(moduleParams, FIELD_CONFIRMATION, REQUEST_ACCEPTED) != HC_SUCCESS) { + LOGE("Failed to add confirmation to moduleParams!"); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} + +static int32_t GenerateServerModuleParams(BindSession *session, CJson *jsonParams, CJson *moduleParams) +{ + int32_t result; + if (((result = GenerateBasicModuleParams(false, session, moduleParams)) != HC_SUCCESS) || + ((result = AddConfirmationToParams(moduleParams)) != HC_SUCCESS) || + ((result = AddRecvModuleDataToParams(jsonParams, moduleParams)) != HC_SUCCESS)) { + return result; + } + return HC_SUCCESS; +} + +static int32_t GetServerModuleReturnData(BindSession *session, CJson *jsonParams, CJson *out, bool *isNeedInform) +{ + CJson *moduleParams = CreateJson(); + if (moduleParams == NULL) { + LOGE("Failed to allocate moduleParams memory!"); + return HC_ERR_JSON_FAIL; + } + + int32_t result = GenerateServerModuleParams(session, jsonParams, moduleParams); + if (result != HC_SUCCESS) { + LOGE("Failed to generate all params sent to the module!"); + FreeJson(moduleParams); + return result; + } + /* Release the memory in advance to reduce the memory usage. */ + DeleteAllItem(jsonParams); + + result = CreateAndProcessModule(session, moduleParams, out); + FreeJson(moduleParams); + if (result != HC_SUCCESS) { + *isNeedInform = false; + InformPeerModuleErrorIfNeed(out, session); + return result; + } + return HC_SUCCESS; +} + +static int32_t PrepareData(BindSession *session, CJson *jsonParams, CJson **sendData, bool *isNeedInform) +{ + CJson *out = CreateJson(); + if (out == NULL) { + LOGE("Failed to allocate out memory!"); + return HC_ERR_JSON_FAIL; + } + + int32_t result = GetServerModuleReturnData(session, jsonParams, out, isNeedInform); + if (result != HC_SUCCESS) { + FreeJson(out); + return result; + } + + *sendData = DetachItemFromJson(out, FIELD_SEND_TO_PEER); + FreeJson(out); + if (*sendData == NULL) { + LOGE("Failed to get sendToPeer from out!"); + return HC_ERR_JSON_GET; + } + + result = AddInfoToSendData((session->operationCode == MEMBER_JOIN), session, *sendData); + if (result != HC_SUCCESS) { + LOGE("Failed to add information to sendData!"); + FreeJson(*sendData); + *sendData = NULL; + return result; + } + return HC_SUCCESS; +} + +static int32_t PrepareAndSendDataServer(BindSession *session, CJson *jsonParams, bool *isNeedInform) +{ + CJson *sendData = NULL; + int32_t result = PrepareData(session, jsonParams, &sendData, isNeedInform); + if (result != HC_SUCCESS) { + return result; + } + + result = SendBindSessionData(session, sendData); + FreeJson(sendData); + return result; +} + +static int32_t GenerateRequestParams(const CJson *jsonParams, CJson *requestParams) +{ + const char *groupId = GetStringFromJson(jsonParams, FIELD_GROUP_ID); + if (groupId == NULL) { + LOGE("Failed to get groupId from jsonParams!"); + return HC_ERR_JSON_GET; + } + const char *peerAuthId = GetStringFromJson(jsonParams, FIELD_PEER_DEVICE_ID); + if (peerAuthId == NULL) { + LOGE("Failed to get peerAuthId from jsonParams!"); + return HC_ERR_JSON_GET; + } + int32_t groupType = PEER_TO_PEER_GROUP; + if (GetIntFromJson(jsonParams, FIELD_GROUP_TYPE, &groupType) != HC_SUCCESS) { + LOGE("Failed to get groupType from jsonParams!"); + return HC_ERR_JSON_GET; + } + if (AddStringToJson(requestParams, FIELD_GROUP_ID, groupId) != HC_SUCCESS) { + LOGE("Failed to add groupId to requestParams!"); + return HC_ERR_JSON_FAIL; + } + if (AddIntToJson(requestParams, FIELD_GROUP_TYPE, groupType) != HC_SUCCESS) { + LOGE("Failed to add groupType to requestParams!"); + return HC_ERR_JSON_FAIL; + } + if (AddStringToJson(requestParams, FIELD_PEER_DEVICE_ID, peerAuthId) != HC_SUCCESS) { + LOGE("Failed to add peerDeviceId to requestParams!"); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} + +static int32_t RequestConfirmation(const CJson *jsonParams, const BindSession *session, char **returnStr) +{ + CJson *requestParams = CreateJson(); + if (requestParams == NULL) { + LOGE("Failed to create json object!"); + return HC_ERR_JSON_FAIL; + } + int32_t result = GenerateRequestParams(jsonParams, requestParams); + if (result != HC_SUCCESS) { + LOGE("An error occurs when the request parameters are generated!"); + FreeJson(requestParams); + return result; + } + char *requestParamsStr = PackJsonToString(requestParams); + FreeJson(requestParams); + if (requestParamsStr == NULL) { + LOGE("An error occurred when converting JSON data to String data.!"); + return HC_ERR_JSON_FAIL; + } + char *returnDataStr = ProcessRequestCallback(session->requestId, session->operationCode, + requestParamsStr, session->base.callback); + FreeJsonString(requestParamsStr); + if (returnDataStr == NULL) { + LOGE("The OnRequest callback is fail!"); + return HC_ERR_REQ_REJECTED; + } + *returnStr = returnDataStr; + return HC_SUCCESS; +} + +static int32_t AddAuthIdIfExist(const CJson *returnData, CJson *jsonParams) +{ + const char *authId = GetStringFromJson(returnData, FIELD_DEVICE_ID); + if (authId != NULL) { + if (AddStringToJson(jsonParams, FIELD_DEVICE_ID, authId) != HC_SUCCESS) { + LOGE("Failed to add authId to jsonParams!"); + return HC_ERR_JSON_FAIL; + } + } + return HC_SUCCESS; +} + +static int32_t AddUserTypeIfExistAndValid(const CJson *returnData, CJson *jsonParams) +{ + int userType = DEVICE_TYPE_ACCESSORY; + if (GetIntFromJson(returnData, FIELD_USER_TYPE, &userType) == HC_SUCCESS) { + if (!IsUserTypeValid(userType)) { + LOGE("The input userType is invalid!"); + return HC_ERR_INVALID_PARAMS; + } + if (AddIntToJson(jsonParams, FIELD_USER_TYPE, userType) != HC_SUCCESS) { + LOGE("Failed to add userType to jsonParams!"); + return HC_ERR_JSON_FAIL; + } + } + return HC_SUCCESS; +} + +static int32_t AddGroupVisibilityIfExistAndValid(const CJson *returnData, CJson *jsonParams) +{ + int groupVisibility = GROUP_VISIBILITY_PUBLIC; + if (GetIntFromJson(returnData, FIELD_GROUP_VISIBILITY, &groupVisibility) == HC_SUCCESS) { + if (!IsGroupVisibilityValid(groupVisibility)) { + LOGE("The input groupVisibility invalid!"); + return HC_ERR_INVALID_PARAMS; + } + if (AddIntToJson(jsonParams, FIELD_GROUP_VISIBILITY, groupVisibility) != HC_SUCCESS) { + LOGE("Failed to add groupVisibility to jsonParams!"); + return HC_ERR_JSON_FAIL; + } + } + return HC_SUCCESS; +} + +static int32_t AddExpireTimeIfExistAndValid(const CJson *returnData, CJson *jsonParams) +{ + int expireTime = DEFAULT_EXPIRE_TIME; + if (GetIntFromJson(returnData, FIELD_EXPIRE_TIME, &expireTime) == HC_SUCCESS) { + if (!IsExpireTimeValid(expireTime)) { + LOGE("The input expireTime invalid!"); + return HC_ERR_INVALID_PARAMS; + } + if (AddIntToJson(jsonParams, FIELD_EXPIRE_TIME, expireTime) != HC_SUCCESS) { + LOGE("Failed to add expireTime to jsonParams!"); + return HC_ERR_JSON_FAIL; + } + } + return HC_SUCCESS; +} + +static int32_t AddPinCode(const CJson *returnData, CJson *jsonParams) +{ + const char *pinCode = GetStringFromJson(returnData, FIELD_PIN_CODE); + if (pinCode == NULL) { + LOGE("Failed to get pinCode from returnData!"); + return HC_ERR_JSON_GET; + } + if (AddStringToJson(jsonParams, FIELD_PIN_CODE, pinCode) != HC_SUCCESS) { + LOGE("Failed to add pinCode to jsonParams!"); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} + +static int32_t CombineInfoWhenInvite(const CJson *returnData, CJson *jsonParams) +{ + int32_t result; + if (((result = AddPinCode(returnData, jsonParams)) != HC_SUCCESS) || + ((result = AddAuthIdIfExist(returnData, jsonParams)) != HC_SUCCESS) || + ((result = AddUserTypeIfExistAndValid(returnData, jsonParams)) != HC_SUCCESS) || + ((result = AddGroupVisibilityIfExistAndValid(returnData, jsonParams)) != HC_SUCCESS) || + ((result = AddExpireTimeIfExistAndValid(returnData, jsonParams)) != HC_SUCCESS)) { + return result; + } + return HC_SUCCESS; +} + +static int32_t CombineInputData(int operationCode, const CJson *returnData, CJson *jsonParams) +{ + if (operationCode == MEMBER_DELETE) { + return HC_SUCCESS; + } else if (operationCode == MEMBER_JOIN) { + return AddPinCode(returnData, jsonParams); + } else { + return CombineInfoWhenInvite(returnData, jsonParams); + } +} + +static bool IsAcceptRequest(const CJson *returnData) +{ + int confirmation = REQUEST_REJECTED; + if (GetIntFromJson(returnData, FIELD_CONFIRMATION, &confirmation) != HC_SUCCESS) { + LOGE("Failed to get confirmation from returnData!"); + return false; + } + return ((uint32_t)confirmation == REQUEST_ACCEPTED); +} + +static int32_t PrepareServer(BindSession *session, CJson *returnData, bool *isNeedInform) +{ + if ((session->isWaiting) && (!IsAcceptRequest(returnData))) { + LOGE("The service rejects the request!"); + return HC_ERR_REQ_REJECTED; + } + CJson *jsonParams = DetachItemFromJson(session->params, FIELD_RECEIVED_DATA); + if (jsonParams == NULL) { + LOGE("Received data before request confirmation are lost!"); + return HC_ERR_LOST_DATA; + } + int32_t result = CombineInputData(session->operationCode, returnData, jsonParams); + /* Release the memory in advance to reduce the memory usage. */ + DeleteAllItem(returnData); + session->isWaiting = false; + if (result != HC_SUCCESS) { + FreeJson(jsonParams); + return result; + } + result = GenerateBindParams(SERVER, jsonParams, session); + if (result != HC_SUCCESS) { + FreeJson(jsonParams); + return result; + } + /* + * If the service is invited to join the peer group, + * the identity key pair of the corresponding group needs to be generated here. + */ + if (NeedCreateGroup(SERVER, session->operationCode)) { + const char *groupId = GetStringFromJson(jsonParams, FIELD_GROUP_ID); + if (groupId == NULL) { + LOGE("Failed to get groupId from jsonParams!"); + FreeJson(jsonParams); + return HC_ERR_JSON_GET; + } + result = ProcessKeyPair(CREATE_KEY_PAIR, jsonParams, groupId); + if (result != HC_SUCCESS) { + FreeJson(jsonParams); + return result; + } + } + result = PrepareAndSendDataServer(session, jsonParams, isNeedInform); + FreeJson(jsonParams); + return result; +} + +static void OnBindConfirmationReceived(Session *session, CJson *returnData) +{ + if ((session == NULL) || (returnData == NULL)) { + LOGE("The input session or returnData is NULL!"); + return; + } + BindSession *realSession = (BindSession *)session; + + bool isNeedInform = true; + int32_t result = PrepareServer(realSession, returnData, &isNeedInform); + if (result != HC_SUCCESS) { + LOGI("An error occurs after the server receives the response to the request. We need to notify the service!"); + InformPeerProcessErrorIfNeed(isNeedInform, result, realSession); + ProcessErrorCallback(realSession->requestId, realSession->operationCode, result, NULL, + realSession->base.callback); + CloseChannel(realSession->channelType, realSession->channelId); + DestroySession(realSession->requestId); + } +} + +static int32_t BindSaveReceivedData(BindSession *session, const CJson *jsonParams) +{ + if (session->params == NULL) { + session->params = CreateJson(); + if (session->params == NULL) { + LOGE("Failed to allocate session params memory!"); + return HC_ERR_ALLOC_MEMORY; + } + } + if (AddObjToJson(session->params, FIELD_RECEIVED_DATA, jsonParams) != HC_SUCCESS) { + LOGE("Failed to add received data to session params!"); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} + +static int32_t JudgeConfirmation(CJson *returnData, CJson *jsonParams, BindSession *session, bool *isNeedInform) +{ + int confirmation = REQUEST_ACCEPTED; + if (GetIntFromJson(returnData, FIELD_CONFIRMATION, &confirmation) != HC_SUCCESS) { + LOGE("Failed to get confirmation from returnData!"); + return HC_ERR_JSON_FAIL; + } + int32_t result; + switch (confirmation) { + case REQUEST_WAITING: + LOGI("The service wants us to wait for its signal!"); + result = BindSaveReceivedData(session, jsonParams); + session->isWaiting = true; + return result; + case REQUEST_ACCEPTED: + LOGI("The service accepts the request!"); + result = BindSaveReceivedData(session, jsonParams); + if (result != HC_SUCCESS) { + return result; + } + /* Release the memory in advance to reduce the memory usage. */ + DeleteAllItem(jsonParams); + return PrepareServer(session, returnData, isNeedInform); + case REQUEST_REJECTED: + LOGE("The service rejects the request!"); + return HC_ERR_REQ_REJECTED; + default: + LOGE("Enter the exception case!"); + return HC_ERR_CASE; + } +} + +static int32_t HandleRequest(CJson *jsonParams, BindSession *session, bool *isNeedInform) +{ + char *returnDataStr = NULL; + int32_t result = RequestConfirmation(jsonParams, session, &returnDataStr); + if (result != HC_SUCCESS) { + return result; + } + + CJson *returnData = CreateJsonFromString(returnDataStr); + FreeJsonString(returnDataStr); + if (returnData == NULL) { + LOGE("Failed to create returnData from string!"); + return HC_ERR_JSON_FAIL; + } + result = JudgeConfirmation(returnData, jsonParams, session, isNeedInform); + FreeJson(returnData); + return result; +} + +static void InitServerChannel(const CJson *jsonParams, BindSession *session) +{ + int64_t channelId = DEFAULT_CHANNEL_ID; + if (GetByteFromJson(jsonParams, FIELD_CHANNEL_ID, (uint8_t *)&channelId, sizeof(int64_t)) == HC_SUCCESS) { + session->channelType = SOFT_BUS; + session->channelId = channelId; + } else { + session->channelType = SERVICE_CHANNEL; + } +} + +Session *CreateServerBindSession(CJson *jsonParams, const DeviceAuthCallback *callback) +{ + int64_t requestId = DEFAULT_REQUEST_ID; + if (GetInt64FromJson(jsonParams, FIELD_REQUEST_ID, &requestId) != HC_SUCCESS) { + LOGE("Failed to get requestId from jsonParams!"); + return NULL; + } + int operationCode = MEMBER_INVITE; + if (GetIntFromJson(jsonParams, FIELD_GROUP_OP, &operationCode) != HC_SUCCESS) { + LOGE("Failed to get operationCode from jsonParams!"); + return NULL; + } + LOGI("Start to create server bind session! [RequestId]: %lld, [OperationCode]: %d", requestId, operationCode); + + BindSession *session = (BindSession *)HcMalloc(sizeof(BindSession), 0); + if (session == NULL) { + LOGE("Failed to allocate session memory!"); + return NULL; + } + InitBindSession(TYPE_SERVER_BIND_SESSION, operationCode, requestId, callback, session); + InitServerChannel(jsonParams, session); + /* The server may receive the confirm request message. */ + session->onConfirmationReceived = OnBindConfirmationReceived; + + bool isNeedInform = true; + int32_t result = HandleRequest(jsonParams, session, &isNeedInform); + if (result != HC_SUCCESS) { + InformPeerProcessErrorIfNeed(isNeedInform, result, session); + ProcessErrorCallback(session->requestId, session->operationCode, result, NULL, + session->base.callback); + CloseChannel(session->channelType, session->channelId); + DestroyBindSession((Session *)session); + return NULL; + } + LOGI("Create server bind session successfully! [RequestId]: %lld, [OperationCode]: %d", requestId, operationCode); + return (Session *)session; +} \ No newline at end of file diff --git a/services/session/src/bind_session_lite/bind_session_client_lite.c b/services/session/src/bind_session_lite/bind_session_client_lite.c new file mode 100644 index 0000000..f4eea97 --- /dev/null +++ b/services/session/src/bind_session_lite/bind_session_client_lite.c @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "bind_session_client_lite.h" +#include "callback_manager.h" +#include "channel_manager.h" +#include "device_auth_defines.h" +#include "hc_log.h" +#include "session_manager.h" + +static int32_t DoubleCheckChannelId(int64_t channelId, int64_t oldChannelId) +{ + if (oldChannelId != channelId) { + /* If the two channelIds are different, the soft bus channel must be used. */ + LOGE("The channelId returned by the soft bus are inconsistent, causing a channel error!"); + return HC_ERR_CHANNEL_NOT_EXIST; + } + return HC_SUCCESS; +} + +static void OnLiteBindChannelOpened(Session *session, int64_t channelId, int64_t requestId) +{ + if (session == NULL) { + LOGE("The input session is NULL!"); + return; + } + + LiteBindSession *realSession = (LiteBindSession *)session; + /* Double check channelId. If the two channelIds are different, the channel fails to be established. */ + int32_t result = DoubleCheckChannelId(channelId, realSession->channelId); + if (result != HC_SUCCESS) { + ProcessErrorCallback(requestId, realSession->operationCode, result, NULL, realSession->base.callback); + DestroySession(requestId); + return; + } + + bool isNeedInform = true; + result = LitePrepareAndSendData(realSession, &isNeedInform); + if (result != HC_SUCCESS) { + LOGI("An error occurs before the client send data to the server. We need to notify the service!"); + ProcessErrorCallback(requestId, realSession->operationCode, result, NULL, realSession->base.callback); + CloseChannel(realSession->channelType, realSession->channelId); + DestroySession(requestId); + } +} + +static int32_t LitePrepareClient(const CJson *jsonParams, LiteBindSession *session) +{ + int32_t result = LiteSaveReceivedData(session, jsonParams); + if (result != HC_SUCCESS) { + return result; + } + return OpenChannel(session->channelType, jsonParams, session->requestId, &session->channelId); +} + +static void InitClientChannel(const DeviceAuthCallback *callback, LiteBindSession *session) +{ + session->channelType = GetChannelType(callback); +} + +Session *CreateLiteClientBindSession(CJson *jsonParams, const DeviceAuthCallback *callback) +{ + int64_t requestId = DEFAULT_REQUEST_ID; + if (GetInt64FromJson(jsonParams, FIELD_REQUEST_ID, &requestId) != HC_SUCCESS) { + LOGE("Failed to get requestId from jsonParams!"); + return NULL; + } + int operationCode = OP_BIND; + if (GetIntFromJson(jsonParams, FIELD_OPERATION_CODE, &operationCode) != HC_SUCCESS) { + LOGE("Failed to get operationCode from jsonParams!"); + return NULL; + } + LOGI("Start to create lite client bind session! [RequestId]: %lld, [OperationCode]: %d", requestId, operationCode); + + LiteBindSession *session = (LiteBindSession *)HcMalloc(sizeof(LiteBindSession), 0); + if (session == NULL) { + LOGE("Failed to allocate session memory!"); + return NULL; + } + InitLiteBindSession(TYPE_CLIENT_BIND_SESSION_LITE, operationCode, requestId, session, callback); + InitClientChannel(callback, session); + /* The client bind session needs to receive a message indicating that the channel is open. */ + session->onChannelOpened = OnLiteBindChannelOpened; + + int32_t result = LitePrepareClient(jsonParams, session); + if (result != HC_SUCCESS) { + LOGI("An error occurs before the client send data to the server. We need to notify the service!"); + DestroyLiteBindSession((Session *)session); + return NULL; + } + LOGI("Create lite client bind session successfully! [RequestId]: %lld, [OperationCode]: %d", + requestId, operationCode); + return (Session *)session; +} \ No newline at end of file diff --git a/services/session/src/bind_session_lite/bind_session_common_lite.c b/services/session/src/bind_session_lite/bind_session_common_lite.c new file mode 100644 index 0000000..cf9e042 --- /dev/null +++ b/services/session/src/bind_session_lite/bind_session_common_lite.c @@ -0,0 +1,351 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "bind_session_common_lite.h" +#include "callback_manager.h" +#include "channel_manager.h" +#include "das_module_defines.h" +#include "dev_auth_module_manager.h" +#include "hc_log.h" +#include "securec.h" +#include "session_common.h" + +static int32_t SendLiteBindSessionData(const LiteBindSession *session, const CJson *sendData) +{ + char *sendDataStr = PackJsonToString(sendData); + if (sendDataStr == NULL) { + LOGE("An error occurred when converting json to string!"); + return HC_ERR_JSON_FAIL; + } + int32_t result = SendMsg(session->channelType, session->requestId, + session->channelId, session->base.callback, sendDataStr); + FreeJsonString(sendDataStr); + return result; +} + +static void InformPeerModuleErrorIfNeed(CJson *out, const LiteBindSession *session) +{ + CJson *errorData = GetObjFromJson(out, FIELD_SEND_TO_PEER); + if (errorData == NULL) { + return; + } + if (AddInt64StringToJson(errorData, FIELD_REQUEST_ID, session->requestId) != HC_SUCCESS) { + LOGE("Failed to add requestId to errorData!"); + return; + } + int32_t result = SendLiteBindSessionData(session, errorData); + if (result != HC_SUCCESS) { + LOGE("An error occurred when notifying the peer service!"); + return; + } + LOGI("Succeeded in notifying the peer device that an error occurred at the local end!"); +} + +static int32_t ProcessModule(bool isAccountBind, const LiteBindSession *session, CJson *in, CJson *out, int *status) +{ + int moduleType = (isAccountBind ? TCIS_MODULE : DAS_MODULE); + LOGI("Start to process %s task!", ((moduleType) == TCIS_MODULE ? "TCIS module" : "DAS module")); + if (isAccountBind) { + CJson *receivedData = GetObjFromJson(in, FIELD_RECEIVED_DATA); + AddIntToJson(receivedData, FIELD_OPERATION_CODE, OP_BIND); + } + int32_t result = ProcessTask(session->curTaskId, in, out, status, moduleType); + if (result != HC_SUCCESS) { + LOGE("An error occurs when the module processes task! [ErrorCode]: %d", result); + return result; + } + LOGI("Process %s task successfully!", ((moduleType) == TCIS_MODULE ? "TCIS module" : "DAS module")); + return HC_SUCCESS; +} + +static int32_t CreateAndProcessModule(bool isAccountBind, LiteBindSession *session, CJson *in, CJson *out) +{ + int status = 0; + int moduleType = (isAccountBind ? TCIS_MODULE : DAS_MODULE); + LOGI("Start to create and process %s task!", ((moduleType) == TCIS_MODULE ? "TCIS module" : "DAS module")); + if (isAccountBind) { + CJson *receivedData = GetObjFromJson(in, FIELD_RECEIVED_DATA); + AddIntToJson(receivedData, FIELD_OPERATION_CODE, OP_BIND); + } + int32_t result = CreateTask(&(session->curTaskId), in, out, moduleType); + if (result != HC_SUCCESS) { + LOGE("An error occurs when creating a module task! [ErrorCode]: %d", result); + return result; + } + result = ProcessTask(session->curTaskId, in, out, &status, moduleType); + if (result != HC_SUCCESS) { + LOGE("An error occurs when the module processes task! [ErrorCode]: %d", result); + return result; + } + LOGI("Create and process %s task successfully!", ((moduleType) == TCIS_MODULE ? "TCIS module" : "DAS module")); + return HC_SUCCESS; +} + +static int32_t OnSessionFinish(bool isAccountBind, const LiteBindSession *session, CJson *out) +{ + int32_t result; + CJson *sendData = GetObjFromJson(out, FIELD_SEND_TO_PEER); + /* The last packet may need to be sent */ + if (sendData != NULL) { + if (isAccountBind && (AddIntToJson(sendData, FIELD_GROUP_OP, ACCOUNT_BIND) != HC_SUCCESS)) { + LOGE("Failed to add groupOp to sendData!"); + return HC_ERR_JSON_FAIL; + } + result = SendLiteBindSessionData(session, sendData); + if (result != HC_SUCCESS) { + return result; + } + } + uint8_t sessionKey[DEFAULT_RETURN_KEY_LENGTH] = { 0 }; + if (GetByteFromJson(out, FIELD_SESSION_KEY, sessionKey, DEFAULT_RETURN_KEY_LENGTH) == HC_SUCCESS) { + ProcessSessionKeyCallback(session->requestId, sessionKey, DEFAULT_RETURN_KEY_LENGTH, session->base.callback); + (void)memset_s(sessionKey, DEFAULT_RETURN_KEY_LENGTH, 0, DEFAULT_RETURN_KEY_LENGTH); + ClearSensitiveStringInJson(out, FIELD_SESSION_KEY); + } + const CJson *returnData = GetObjFromJson(out, FIELD_SEND_TO_SELF); + char *returnDataStr = PackJsonToString(returnData); + ProcessFinishCallback(session->requestId, session->operationCode, returnDataStr, session->base.callback); + FreeJsonString(returnDataStr); + LOGI("The device is successfully %s!", ((session->operationCode == OP_BIND) ? "bound" : "unbound")); + SetAuthResult(session->channelType, session->channelId); + CloseChannel(session->channelType, session->channelId); + return HC_SUCCESS; +} + +static int32_t CheckPeerStatus(const CJson *jsonParams, bool *isNeedInform) +{ + int32_t errorCode = 0; + if (GetIntFromJson(jsonParams, FIELD_GROUP_ERROR_MSG, &errorCode) == HC_SUCCESS) { + LOGE("An error occurs in the peer service! [ErrorCode]: %d", errorCode); + *isNeedInform = false; + return errorCode; + } + return HC_SUCCESS; +} + +static CJson *GenerateGroupErrorMsg(int32_t errorCode, int64_t requestId) +{ + CJson *errorData = CreateJson(); + if (errorData == NULL) { + LOGE("Failed to allocate errorData memory!"); + return NULL; + } + if (AddIntToJson(errorData, FIELD_GROUP_ERROR_MSG, errorCode) != HC_SUCCESS) { + LOGE("Failed to add errorCode to errorData!"); + FreeJson(errorData); + return NULL; + } + if (AddInt64StringToJson(errorData, FIELD_REQUEST_ID, requestId) != HC_SUCCESS) { + LOGE("Failed to add requestId to errorData!"); + FreeJson(errorData); + return NULL; + } + return errorData; +} + +static int32_t ProcessLiteBindSessionInner(LiteBindSession *session, CJson *jsonParams, int32_t *status, + bool *isNeedInform) +{ + int32_t result = CheckPeerStatus(jsonParams, isNeedInform); + if (result != HC_SUCCESS) { + return result; + } + + CJson *out = CreateJson(); + if (out == NULL) { + LOGE("Failed to allocate out memory!"); + return HC_ERR_JSON_FAIL; + } + + bool isAccountBind = false; + (void)GetBoolFromJson(jsonParams, FIELD_IS_ACCOUNT_BIND, &isAccountBind); + result = ProcessModule(isAccountBind, session, jsonParams, out, status); + DeleteAllItem(jsonParams); + if (result != HC_SUCCESS) { + *isNeedInform = false; + InformPeerModuleErrorIfNeed(out, session); + FreeJson(out); + return result; + } + + if (*status == IGNORE_MSG) { + FreeJson(out); + return HC_SUCCESS; + } else if (*status == CONTINUE) { + CJson *sendData = DetachItemFromJson(out, FIELD_SEND_TO_PEER); + FreeJson(out); + if (sendData == NULL) { + LOGE("Failed to get sendToPeer from out!"); + return HC_ERR_JSON_GET; + } + if (isAccountBind && (AddIntToJson(sendData, FIELD_GROUP_OP, ACCOUNT_BIND) != HC_SUCCESS)) { + LOGE("Failed to add groupOp to sendData!"); + FreeJson(sendData); + return HC_ERR_JSON_FAIL; + } + result = SendLiteBindSessionData(session, sendData); + FreeJson(sendData); + return result; + } + + result = OnSessionFinish(isAccountBind, session, out); + FreeJson(out); + return result; +} + +static int32_t ProcessLiteBindSession(Session *session, CJson *jsonParams) +{ + if ((session == NULL) || (jsonParams == NULL)) { + LOGE("The input session or jsonParams is NULL!"); + return HC_ERR_INVALID_PARAMS; + } + + LiteBindSession *realSession = (LiteBindSession *)session; + + bool isNeedInform = true; + int32_t status = CONTINUE; + int32_t result = ProcessLiteBindSessionInner(realSession, jsonParams, &status, &isNeedInform); + if (result != HC_SUCCESS) { + LOGE("An error occurs during processing lite bind session. We need to notify the service!"); + LiteInformPeerErrorIfNeed(isNeedInform, result, realSession); + ProcessErrorCallback(realSession->requestId, realSession->operationCode, result, NULL, + realSession->base.callback); + CloseChannel(realSession->channelType, realSession->channelId); + return result; + } + if (status == FINISH) { + return status; + } + return result; +} + +static int32_t LitePrepareData(LiteBindSession *session, CJson **sendData, bool *isNeedInform) +{ + CJson *out = CreateJson(); + if (out == NULL) { + LOGE("Failed to allocate out memory!"); + return HC_ERR_JSON_FAIL; + } + + bool isAccountBind = false; + (void)GetBoolFromJson(session->params, FIELD_IS_ACCOUNT_BIND, &isAccountBind); + int32_t result = CreateAndProcessModule(isAccountBind, session, session->params, out); + if (result != HC_SUCCESS) { + *isNeedInform = false; + InformPeerModuleErrorIfNeed(out, session); + FreeJson(out); + return result; + } + + DeleteAllItem(session->params); + *sendData = DetachItemFromJson(out, FIELD_SEND_TO_PEER); + FreeJson(out); + if (*sendData == NULL) { + LOGE("Failed to get sendToPeer from out!"); + return HC_ERR_JSON_GET; + } + if (isAccountBind && (AddIntToJson(*sendData, FIELD_GROUP_OP, ACCOUNT_BIND) != HC_SUCCESS)) { + LOGE("Failed to add groupOp to sendData!"); + FreeJson(*sendData); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} + +int32_t LitePrepareAndSendData(LiteBindSession *session, bool *isNeedInform) +{ + CJson *sendData = NULL; + int32_t result = LitePrepareData(session, &sendData, isNeedInform); + if (result != HC_SUCCESS) { + return result; + } + + result = SendLiteBindSessionData(session, sendData); + FreeJson(sendData); + return result; +} + +void DestroyLiteBindSession(Session *session) +{ + if (session == NULL) { + return; + } + LiteBindSession *realSession = (LiteBindSession *)session; + DestroyTask(realSession->curTaskId, DAS_MODULE); + FreeJson(realSession->params); + realSession->params = NULL; + HcFree(realSession); + realSession = NULL; +} + +void LiteInformPeerErrorIfNeed(bool isNeedInform, int32_t errorCode, LiteBindSession *session) +{ + if (!isNeedInform) { + return; + } + CJson *errorData = GenerateGroupErrorMsg(errorCode, session->requestId); + if (errorData == NULL) { + return; + } + int32_t result = SendLiteBindSessionData(session, errorData); + FreeJson(errorData); + if (result != HC_SUCCESS) { + LOGE("An error occurred when notifying the peer service!"); + return; + } + LOGI("Succeeded in notifying the peer device that an error occurred at the local end!"); +} + +int32_t LiteSaveReceivedData(LiteBindSession *session, const CJson *jsonParams) +{ + if (session->params == NULL) { + session->params = CreateJson(); + if (session->params == NULL) { + LOGE("Failed to allocate session params memory!"); + return HC_ERR_ALLOC_MEMORY; + } + } + if (AddObjToJson(session->params, FIELD_RECEIVED_DATA, jsonParams) != HC_SUCCESS) { + LOGE("Failed to add received data to session params!"); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} + +void InitLiteBindSession(int bindType, int operationCode, int64_t requestId, LiteBindSession *session, + const DeviceAuthCallback *callback) +{ + if (session == NULL) { + LOGE("The input session is NULL!"); + return; + } + session->base.process = ProcessLiteBindSession; + session->base.destroy = DestroyLiteBindSession; + session->curTaskId = 0; + session->base.callback = callback; + int res = GenerateSessionOrTaskId(&session->base.sessionId); + if (res != 0) { + return; + }; + session->base.type = bindType; + session->operationCode = operationCode; + session->requestId = requestId; + session->channelType = GetChannelType(callback); + session->channelId = DEFAULT_CHANNEL_ID; + session->isWaiting = false; + session->params = NULL; + session->onChannelOpened = NULL; + session->onConfirmationReceived = NULL; +} \ No newline at end of file diff --git a/services/session/src/bind_session_lite/bind_session_server_lite.c b/services/session/src/bind_session_lite/bind_session_server_lite.c new file mode 100644 index 0000000..017c61b --- /dev/null +++ b/services/session/src/bind_session_lite/bind_session_server_lite.c @@ -0,0 +1,192 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "bind_session_server_lite.h" +#include "callback_manager.h" +#include "channel_manager.h" +#include "device_auth_defines.h" +#include "hc_log.h" +#include "session_manager.h" + +static int32_t RequestConfirmation(const LiteBindSession *session, char **returnStr) +{ + char *returnDataStr = ProcessRequestCallback(session->requestId, session->operationCode, NULL, + session->base.callback); + if (returnDataStr == NULL) { + LOGE("The OnRequest callback is fail!"); + return HC_ERR_REQ_REJECTED; + } + *returnStr = returnDataStr; + LOGI("The server receives the data returned by the service!"); + return HC_SUCCESS; +} + +static int32_t CombineInputData(const CJson *returnData, CJson *jsonParams) +{ + CJson *tempReturnData = DuplicateJson(returnData); + if (tempReturnData == NULL) { + LOGE("Failed to copy returnData!"); + return HC_ERR_JSON_FAIL; + } + if (AddObjToJson(jsonParams, FIELD_RETURN_DATA, tempReturnData) != HC_SUCCESS) { + LOGE("Failed to add returnData to jsonParams!"); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} + +static bool IsAcceptRequest(const CJson *returnData) +{ + int confirmation = REQUEST_REJECTED; + if (GetIntFromJson(returnData, FIELD_CONFIRMATION, &confirmation) != HC_SUCCESS) { + LOGE("Failed to get confirmation from returnData!"); + return false; + } + return ((uint32_t)confirmation == REQUEST_ACCEPTED); +} + +static int32_t LitePrepareServer(LiteBindSession *session, CJson *returnData, bool *isNeedInform) +{ + if ((session->isWaiting) && (!IsAcceptRequest(returnData))) { + LOGE("The service rejects the request!"); + return HC_ERR_REQ_REJECTED; + } + int32_t result = CombineInputData(returnData, session->params); + /* Release the memory in advance to reduce the memory usage. */ + DeleteAllItem(returnData); + session->isWaiting = false; + if (result != HC_SUCCESS) { + return result; + } + return LitePrepareAndSendData(session, isNeedInform); +} + +static int32_t JudgeConfirmation(CJson *returnData, CJson *jsonParams, LiteBindSession *session, bool *isNeedInform) +{ + int confirmation = REQUEST_ACCEPTED; + if (GetIntFromJson(returnData, FIELD_CONFIRMATION, &confirmation) != HC_SUCCESS) { + LOGE("Failed to get confirmation from returnData!"); + return HC_ERR_JSON_FAIL; + } + int32_t result; + switch (confirmation) { + case REQUEST_WAITING: + LOGI("The service wants us to wait for its signal!"); + result = LiteSaveReceivedData(session, jsonParams); + session->isWaiting = true; + return result; + case REQUEST_ACCEPTED: + LOGI("The service accepts the request!"); + result = LiteSaveReceivedData(session, jsonParams); + if (result != HC_SUCCESS) { + return result; + } + /* Release the memory in advance to reduce the memory usage. */ + DeleteAllItem(jsonParams); + return LitePrepareServer(session, returnData, isNeedInform); + case REQUEST_REJECTED: + LOGE("The service rejects the request!"); + return HC_ERR_REQ_REJECTED; + default: + LOGE("Enter the exception case!"); + return HC_ERR_CASE; + } +} + +static int32_t HandleRequest(CJson *jsonParams, LiteBindSession *session, bool *isNeedInform) +{ + char *returnDataStr = NULL; + int32_t result = RequestConfirmation(session, &returnDataStr); + if (result != HC_SUCCESS) { + return result; + } + + CJson *returnData = CreateJsonFromString(returnDataStr); + FreeJsonString(returnDataStr); + if (returnData == NULL) { + LOGE("Failed to create returnData from string!"); + return HC_ERR_JSON_FAIL; + } + result = JudgeConfirmation(returnData, jsonParams, session, isNeedInform); + FreeJson(returnData); + return result; +} + +static void OnLiteBindConfirmationReceived(Session *session, CJson *returnData) +{ + if ((session == NULL) || (returnData == NULL)) { + LOGE("The input session or returnData is NULL!"); + return; + } + LiteBindSession *realSession = (LiteBindSession *)session; + + bool isNeedInform = true; + int32_t result = LitePrepareServer(realSession, returnData, &isNeedInform); + if (result != HC_SUCCESS) { + LOGI("An error occurs after the server receives the response to the request. We need to notify the service!"); + LiteInformPeerErrorIfNeed(isNeedInform, result, realSession); + ProcessErrorCallback(realSession->requestId, realSession->operationCode, result, NULL, + realSession->base.callback); + CloseChannel(realSession->channelType, realSession->channelId); + DestroySession(realSession->requestId); + } +} + +static void InitServerChannel(const CJson *jsonParams, LiteBindSession *session) +{ + int64_t channelId = DEFAULT_CHANNEL_ID; + if (GetByteFromJson(jsonParams, FIELD_CHANNEL_ID, (uint8_t *)&channelId, sizeof(int64_t)) == HC_SUCCESS) { + session->channelType = SOFT_BUS; + session->channelId = channelId; + } else { + session->channelType = SERVICE_CHANNEL; + } +} + +Session *CreateLiteServerBindSession(CJson *jsonParams, const DeviceAuthCallback *callback) +{ + int64_t requestId = DEFAULT_REQUEST_ID; + if (GetInt64FromJson(jsonParams, FIELD_REQUEST_ID, &requestId) != HC_SUCCESS) { + LOGE("Failed to get requestId from jsonParams!"); + return NULL; + } + int operationCode = OP_BIND; + (void)(GetIntFromJson(jsonParams, FIELD_OPERATION_CODE, &operationCode)); + LOGI("Start to create lite server bind session! [RequestId]: %lld, [OperationCode]: %d", requestId, operationCode); + + LiteBindSession *session = (LiteBindSession *)HcMalloc(sizeof(LiteBindSession), 0); + if (session == NULL) { + LOGE("Failed to allocate session memory!"); + return NULL; + } + InitLiteBindSession(TYPE_SERVER_BIND_SESSION_LITE, operationCode, requestId, session, callback); + InitServerChannel(jsonParams, session); + /* The server may receive the confirm request message. */ + session->onConfirmationReceived = OnLiteBindConfirmationReceived; + + bool isNeedInform = true; + int32_t result = HandleRequest(jsonParams, session, &isNeedInform); + if (result != HC_SUCCESS) { + LiteInformPeerErrorIfNeed(isNeedInform, result, session); + ProcessErrorCallback(session->requestId, session->operationCode, result, NULL, + session->base.callback); + CloseChannel(session->channelType, session->channelId); + DestroyLiteBindSession((Session *)session); + return NULL; + } + LOGI("Create lite server bind session successfully! [RequestId]: %lld, [OperationCode]: %d", + requestId, operationCode); + return (Session *)session; +} \ No newline at end of file diff --git a/services/session/src/bind_session_lite_mock/bind_session_client_lite_mock.c b/services/session/src/bind_session_lite_mock/bind_session_client_lite_mock.c new file mode 100644 index 0000000..0744090 --- /dev/null +++ b/services/session/src/bind_session_lite_mock/bind_session_client_lite_mock.c @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "bind_session_client_lite.h" +#include "hc_log.h" + +Session *CreateLiteClientBindSession(CJson *jsonParams, const DeviceAuthCallback *callback) +{ + LOGE("Lite bind session is not supported!"); + (void)jsonParams; + (void)callback; + return NULL; +} \ No newline at end of file diff --git a/services/session/src/bind_session_lite_mock/bind_session_server_lite_mock.c b/services/session/src/bind_session_lite_mock/bind_session_server_lite_mock.c new file mode 100644 index 0000000..459f3f2 --- /dev/null +++ b/services/session/src/bind_session_lite_mock/bind_session_server_lite_mock.c @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "bind_session_client_lite.h" +#include "hc_log.h" + +Session *CreateLiteServerBindSession(CJson *jsonParams, const DeviceAuthCallback *callback) +{ + LOGE("Lite bind session is not supported!"); + (void)jsonParams; + (void)callback; + return NULL; +} \ No newline at end of file diff --git a/services/session/src/bind_session_mock/bind_session_client_mock.c b/services/session/src/bind_session_mock/bind_session_client_mock.c new file mode 100644 index 0000000..58914e4 --- /dev/null +++ b/services/session/src/bind_session_mock/bind_session_client_mock.c @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "bind_session_client.h" +#include "hc_log.h" + +Session *CreateClientBindSession(CJson *jsonParams, const DeviceAuthCallback *callback) +{ + LOGE("Bind session is not supported!"); + (void)jsonParams; + (void)callback; + return NULL; +} \ No newline at end of file diff --git a/services/session/src/bind_session_mock/bind_session_server_mock.c b/services/session/src/bind_session_mock/bind_session_server_mock.c new file mode 100644 index 0000000..d2366ba --- /dev/null +++ b/services/session/src/bind_session_mock/bind_session_server_mock.c @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "bind_session_server.h" +#include "hc_log.h" + +Session *CreateServerBindSession(CJson *jsonParams, const DeviceAuthCallback *callback) +{ + LOGE("Bind session is not supported!"); + (void)jsonParams; + (void)callback; + return NULL; +} \ No newline at end of file diff --git a/services/session/src/key_agree_session_mock/key_agree_session_client_mock.c b/services/session/src/key_agree_session_mock/key_agree_session_client_mock.c new file mode 100644 index 0000000..a8555f5 --- /dev/null +++ b/services/session/src/key_agree_session_mock/key_agree_session_client_mock.c @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "key_agree_session_client.h" +#include "hc_log.h" + +Session *CreateClientKeyAgreeSession(CJson *jsonParams, const DeviceAuthCallback *callback) +{ + LOGE("Key agreement session is not supported!"); + (void)jsonParams; + (void)callback; + return NULL; +} \ No newline at end of file diff --git a/services/session/src/key_agree_session_mock/key_agree_session_server_mock.c b/services/session/src/key_agree_session_mock/key_agree_session_server_mock.c new file mode 100644 index 0000000..fe248e2 --- /dev/null +++ b/services/session/src/key_agree_session_mock/key_agree_session_server_mock.c @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "key_agree_session_server.h" +#include "hc_log.h" + +Session *CreateServerKeyAgreeSession(CJson *jsonParams, const DeviceAuthCallback *callback) +{ + LOGE("Key agreement session is not supported!"); + (void)jsonParams; + (void)callback; + return NULL; +} \ No newline at end of file diff --git a/services/session/src/session_common.c b/services/session/src/session_common.c new file mode 100755 index 0000000..f49f05a --- /dev/null +++ b/services/session/src/session_common.c @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "session_common.h" +#include "alg_loader.h" +#include "das_module_defines.h" + +int GenerateSessionOrTaskId(int64_t *id) +{ + const AlgLoader *loader = GetLoaderInstance(); + if (loader == NULL) { + return HC_ERROR; + } + Uint8Buff idBuf = { (void *)id, sizeof(int64_t) }; + return loader->generateRandom(&idBuf); +} diff --git a/services/session/src/session_manager.c b/services/session/src/session_manager.c new file mode 100644 index 0000000..3b384b3 --- /dev/null +++ b/services/session/src/session_manager.c @@ -0,0 +1,349 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "session_manager.h" +#include "auth_session_client.h" +#include "auth_session_client_lite.h" +#include "auth_session_server.h" +#include "auth_session_server_lite.h" +#include "bind_session_client.h" +#include "bind_session_client_lite.h" +#include "bind_session_server.h" +#include "bind_session_server_lite.h" +#include "common_defs.h" +#include "device_auth.h" +#include "device_auth_defines.h" +#include "hc_dev_info.h" +#include "hc_log.h" +#include "hc_time.h" +#include "hc_vector.h" +#include "key_agree_session_client.h" +#include "key_agree_session_server.h" + +DECLARE_HC_VECTOR(SessionManagerVec, void *) +IMPLEMENT_HC_VECTOR(SessionManagerVec, void *, 1) + +DECLARE_HC_VECTOR(RequestInfoVec, RequestInfo) +IMPLEMENT_HC_VECTOR(RequestInfoVec, RequestInfo, 1) + +static SessionManagerVec g_sessionManagerVec; +static RequestInfoVec g_requestVec; + +typedef Session *(*CreateSessionFunc)(CJson *, const DeviceAuthCallback *); + +typedef struct SessionManagerInfoStruct { + SessionTypeValue sessionType; + int requestType; /* only BIND_TYPE or AUTH_TYPE currently */ + CreateSessionFunc createSessionFunc; +} SessionManagerInfo; + +static const SessionManagerInfo SESSION_MANAGER_INFO[] = { + { TYPE_CLIENT_BIND_SESSION, BIND_TYPE, CreateClientBindSession }, + { TYPE_SERVER_BIND_SESSION, BIND_TYPE, CreateServerBindSession }, + { TYPE_CLIENT_AUTH_SESSION, AUTH_TYPE, CreateClientAuthSession }, + { TYPE_SERVER_AUTH_SESSION, AUTH_TYPE, CreateServerAuthSession }, + { TYPE_CLIENT_BIND_SESSION_LITE, BIND_TYPE, CreateLiteClientBindSession }, + { TYPE_SERVER_BIND_SESSION_LITE, BIND_TYPE, CreateLiteServerBindSession }, + { TYPE_CLIENT_AUTH_SESSION_LITE, AUTH_TYPE, CreateClientAuthSessionLite }, + { TYPE_SERVER_AUTH_SESSION_LITE, AUTH_TYPE, CreateServerAuthSessionLite }, + { TYPE_CLIENT_KEY_AGREE_SESSION, BIND_TYPE, CreateClientKeyAgreeSession }, + { TYPE_SERVER_KEY_AGREE_SESSION, BIND_TYPE, CreateServerKeyAgreeSession } +}; + +static int32_t GetSessionId(int64_t requestId, int64_t *sessionId) +{ + uint32_t index; + RequestInfo *requestInfo = NULL; + FOR_EACH_HC_VECTOR(g_requestVec, index, requestInfo) { + if ((requestInfo != NULL) && (requestInfo->requestId == requestId)) { + *sessionId = requestInfo->sessionId; + return HC_SUCCESS; + } + } + return HC_ERR_REQUEST_NOT_FOUND; +} + +static int32_t GetSessionIdByType(int64_t requestId, int32_t type, int64_t *sessionId) +{ + uint32_t index; + RequestInfo *requestInfo = NULL; + FOR_EACH_HC_VECTOR(g_requestVec, index, requestInfo) { + if ((requestInfo != NULL) && (requestInfo->requestId == requestId)) { + if (requestInfo->type != type) { + LOGE("RequestId is match but type not match"); + return HC_ERR_REQUEST_NOT_FOUND; + } + *sessionId = requestInfo->sessionId; + return HC_SUCCESS; + } + } + return HC_ERR_REQUEST_NOT_FOUND; +} + +static void DestroyRequest(int64_t requestId) +{ + uint32_t index; + RequestInfo *request = NULL; + FOR_EACH_HC_VECTOR(g_requestVec, index, request) { + if ((request != NULL) && (request->requestId == requestId)) { + RequestInfo tempRequest; + HC_VECTOR_POPELEMENT(&g_requestVec, &tempRequest, index); + return; + } + } +} + +void InitSessionManager() +{ + g_sessionManagerVec = CREATE_HC_VECTOR(SessionManagerVec) + g_requestVec = CREATE_HC_VECTOR(RequestInfoVec) +} + +void DestroySessionManager() +{ + uint32_t index; + void **session = NULL; + FOR_EACH_HC_VECTOR(g_sessionManagerVec, index, session) { + if (session != NULL && (*session != NULL)) { + Session *temp = (Session *)(*session); + temp->destroy(temp); + } + } + DESTROY_HC_VECTOR(SessionManagerVec, &g_sessionManagerVec) + DESTROY_HC_VECTOR(RequestInfoVec, &g_requestVec) +} + +bool IsRequestExist(int64_t requestId) +{ + int64_t sessionId = 0; + return (GetSessionId(requestId, &sessionId) == HC_SUCCESS) ? true : false; +} + +static void InformTimeOutAndDestroyRequest(const DeviceAuthCallback *callback, int64_t sessionId) +{ + if (callback == NULL || callback->onError == NULL) { + LOGD("Callback is null, can't inform timeout"); + return; + } + int64_t requestId = 0; + uint32_t index; + RequestInfo *requestInfo = NULL; + FOR_EACH_HC_VECTOR(g_requestVec, index, requestInfo) { + if ((requestInfo != NULL) && (requestInfo->sessionId == sessionId)) { + requestId = requestInfo->requestId; + RequestInfo tempRequest; + HC_VECTOR_POPELEMENT(&g_requestVec, &tempRequest, index); + break; + } + } + LOGI("Begin to inform time out, requestId :%lld", requestId); + callback->onError(requestId, AUTH_FORM_INVALID_TYPE, HC_ERR_TIME_OUT, NULL); +} + +static void RemoveOverTimeSession() +{ + uint32_t index = 0; + void **session = NULL; + while (index < g_sessionManagerVec.size(&(g_sessionManagerVec))) { + session = g_sessionManagerVec.getp(&(g_sessionManagerVec), index); + if (session == NULL || (*session == NULL)) { + index++; + continue; + } + Session *ptr = (Session *)(*session); + if (HcGetIntervalTime(ptr->createTime) < TIME_OUT_VALUE) { + index++; + } else { + InformTimeOutAndDestroyRequest(ptr->callback, ptr->sessionId); + ptr->destroy(ptr); + g_sessionManagerVec.eraseElement(&(g_sessionManagerVec), session, index); + } + session = g_sessionManagerVec.getp(&(g_sessionManagerVec), index); + } +} + +int32_t ProcessSession(int64_t requestId, int32_t type, CJson *in) +{ + int64_t sessionId = 0; + RemoveOverTimeSession(); + int32_t result = GetSessionIdByType(requestId, type, &sessionId); + if (result != HC_SUCCESS) { + LOGE("The corresponding session is not found!"); + return result; + } + uint32_t index; + void **session = NULL; + FOR_EACH_HC_VECTOR(g_sessionManagerVec, index, session) { + if (session != NULL && (*session != NULL)) { + Session *ptr = (Session *)(*session); + if (ptr->sessionId == sessionId) { + return ptr->process(ptr, in); + } + } + } + return HC_ERR_SESSION_NOT_EXIST; +} + +static int32_t CheckForCreateSession(int64_t requestId, CJson *params, const DeviceAuthCallback *callback) +{ + if ((params == NULL) && (callback == NULL)) { + LOGE("The input params or callback is NULL!"); + return HC_ERR_INVALID_PARAMS; + } + if (IsRequestExist(requestId)) { + LOGE("A request with the request ID already exists!"); + return HC_ERR_REQUEST_EXIST; + } + return HC_SUCCESS; +} + +int32_t CreateSession(int64_t requestId, SessionTypeValue sessionType, CJson *params, + const DeviceAuthCallback *callback) +{ + int32_t res = CheckForCreateSession(requestId, params, callback); + if (res != HC_SUCCESS) { + return res; + } + uint32_t vecSize = g_sessionManagerVec.size(&g_sessionManagerVec); + if (vecSize >= MAX_SESSION_COUNT) { + LOGE("Session vector is full."); + return HC_ERR_SESSION_IS_FULL; + } + RequestInfo requestInfo; + requestInfo.requestId = requestId; + Session *session = NULL; + for (uint32_t i = 0; i < sizeof(SESSION_MANAGER_INFO) / sizeof(SessionManagerInfo); i++) { + if (SESSION_MANAGER_INFO[i].sessionType == sessionType) { + session = SESSION_MANAGER_INFO[i].createSessionFunc(params, callback); + requestInfo.type = SESSION_MANAGER_INFO[i].requestType; + break; + } + } + if (session == NULL) { + LOGE("Failed to create session! Session Type: %d", sessionType); + return HC_ERR_CREATE_SESSION_FAIL; + } + + requestInfo.sessionId = session->sessionId; + g_sessionManagerVec.pushBackT(&g_sessionManagerVec, (void *)session); + g_requestVec.pushBack(&g_requestVec, &requestInfo); + session->createTime = HcGetCurTime(); + if (session->createTime <= 0) { + session->createTime = 0; + LOGE("Failed to get cur time."); + } + return HC_SUCCESS; +} + +void DestroySession(int64_t requestId) +{ + int64_t sessionId = 0; + if (GetSessionId(requestId, &sessionId) != HC_SUCCESS) { + LOGI("The corresponding session is not found. Therefore, the destruction operation is not required!"); + return; + } + uint32_t index; + void **session = NULL; + FOR_EACH_HC_VECTOR(g_sessionManagerVec, index, session) { + if (session != NULL && (*session != NULL)) { + if (((Session *)(*session))->sessionId == sessionId) { + ((Session *)(*session))->destroy(((Session *)(*session))); + *session = NULL; + HC_VECTOR_POPELEMENT(&g_sessionManagerVec, session, index); + break; + } + } + } + DestroyRequest(requestId); +} + +void OnChannelOpened(int64_t requestId, int64_t channelId) +{ + int64_t sessionId = 0; + if (GetSessionIdByType(requestId, BIND_TYPE, &sessionId) != HC_SUCCESS) { + LOGE("The corresponding session is not found!"); + return; + } + uint32_t index; + void **session = NULL; + FOR_EACH_HC_VECTOR(g_sessionManagerVec, index, session) { + if (session != NULL && (*session != NULL)) { + if (((Session *)(*session))->sessionId == sessionId) { + if (((Session *)(*session))->type == TYPE_CLIENT_BIND_SESSION) { + BindSession *realSession = (BindSession *)(*session); + realSession->onChannelOpened(*session, channelId, requestId); + return; + } + if (((Session *)(*session))->type == TYPE_CLIENT_BIND_SESSION_LITE) { + LiteBindSession *realSession = (LiteBindSession *)(*session); + realSession->onChannelOpened(*session, channelId, requestId); + return; + } + if (((Session *)(*session))->type == TYPE_CLIENT_KEY_AGREE_SESSION) { + KeyAgreeSession *realSession = (KeyAgreeSession *)(*session); + realSession->onChannelOpened(*session, channelId, requestId); + return; + } + LOGE("The type of the found session is not as expected!"); + return; + } + } + } +} + +void OnConfirmationReceived(int64_t requestId, CJson *returnData) +{ + int64_t sessionId = 0; + if (GetSessionIdByType(requestId, BIND_TYPE, &sessionId) != HC_SUCCESS) { + LOGE("The corresponding session is not found!"); + return; + } + uint32_t index; + void **session = NULL; + FOR_EACH_HC_VECTOR(g_sessionManagerVec, index, session) { + if ((session == NULL) || (*session == NULL) || (((Session *)(*session))->sessionId != sessionId)) { + continue; + } + if (((Session *)(*session))->type == TYPE_SERVER_BIND_SESSION) { + BindSession *realSession = (BindSession *)(*session); + if (!realSession->isWaiting) { + LOGE("The found session is not in the waiting state!"); + return; + } + realSession->onConfirmationReceived(*session, returnData); + return; + } + if (((Session *)(*session))->type == TYPE_SERVER_BIND_SESSION_LITE) { + LiteBindSession *realSession = (LiteBindSession *)(*session); + if (!realSession->isWaiting) { + LOGE("The found session is not in the waiting state!"); + return; + } + realSession->onConfirmationReceived(*session, returnData); + return; + } + if (((Session *)(*session))->type == TYPE_SERVER_KEY_AGREE_SESSION) { + KeyAgreeSession *realSession = (KeyAgreeSession *)(*session); + if (!realSession->isWaiting) { + LOGE("The found session is not in the waiting state!"); + return; + } + realSession->onConfirmationReceived(*session, returnData); + return; + } + LOGE("The type of the found session is not as expected!"); + return; + } +} \ No newline at end of file diff --git a/test/unittest/deviceauth/BUILD.gn b/test/unittest/deviceauth/BUILD.gn new file mode 100644 index 0000000..6681fe9 --- /dev/null +++ b/test/unittest/deviceauth/BUILD.gn @@ -0,0 +1,64 @@ +# Copyright (C) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//base/security/deviceauth/hals/deviceauth_hals.gni") +import("//base/security/deviceauth/services/deviceauth.gni") +import("//build/test.gni") + +module_output_path = "deviceauth_standard/deviceauth_test" + +ohos_unittest("deviceauth_llt") { + module_out_path = module_output_path + include_dirs = [ + "./include", + "//third_party/json/include", + "//utils/native/base/include", + ] + include_dirs += inc_path + include_dirs += hals_inc_path + + sources = [ + "${hals_path}/src/common/alg_loader.c", + "${hals_path}/src/common/common_util.c", + "${hals_path}/src/common/hc_parcel.c", + "${hals_path}/src/common/hc_string.c", + "${hals_path}/src/common/hc_task_thread.c", + "${hals_path}/src/common/hc_tlv_parser.c", + "${hals_path}/src/common/json_utils.c", + "${hals_path}/src/linux/L2/crypto_hash_to_point.c", + "${hals_path}/src/linux/L2/huks_adapter.c", + "${hals_path}/src/linux/hc_condition.c", + "${hals_path}/src/linux/hc_file.c", + "${hals_path}/src/linux/hc_init_protection.c", + "${hals_path}/src/linux/hc_mutex.c", + "${hals_path}/src/linux/hc_thread.c", + "${hals_path}/src/linux/hc_time.c", + "${hals_path}/src/linux/hc_types.c", + ] + sources += deviceauth_files + sources += [ + "source/deviceauth_standard_test.cpp", + "source/deviceauth_test_mock.cpp", + ] + + deps = [ + "//base/security/huks/interfaces/innerkits/huks_standard/main:libhukssdk", + "//third_party/cJSON:cjson_static", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//third_party/openssl:libcrypto_static", + "//utils/native/base:utils", + ] + + external_deps = [ "hiviewdfx_hilog_native:libhilog" ] +} diff --git a/test/unittest/deviceauth/include/deviceauth_standard_test.h b/test/unittest/deviceauth/include/deviceauth_standard_test.h new file mode 100644 index 0000000..f995428 --- /dev/null +++ b/test/unittest/deviceauth/include/deviceauth_standard_test.h @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DEVICEAUTH_STANDARD_TEST_H +#define DEVICEAUTH_STANDARD_TEST_H + +#include +#include "gtest/gtest.h" +#include "gmock/gmock.h" + +extern "C" { +#include "device_auth.h" +} + +namespace { + const char *TEST_APP_NAME = "TestApp"; + const int32_t TEMP_REQUEST_ID = 123; + const int32_t BUFFER_SIZE = 2048; + const char *CLIENT_AUTH_ID = "3C58C27533D8"; + const char *SERVER_AUTH_ID = "CAF34E13190CBA510AA8DABB70CDFF8E9F623656DED400EF0D4CFD9E88FD6202"; + const char *PIN_CODE = "123456"; + const int32_t CLIENT_REQUEST_ID = 123; + const int32_t SERVER_REQUEST_ID = 345; + const int32_t STR_BUFF_SZ_MIN = 32; + const int32_t STR_BUFF_SZ_NORMAL = 128; + const int32_t MAX_GROUP_NUMBER = 101; +} + +typedef enum { + ON_REQUEST = 1, + ON_ERROR = 2, + ON_FINISH = 3, + ON_SESSION_KEY_RETURNED = 4, + ON_TRANSMIT = 5 +} CallbackType; + +class GET_INSTANCE : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override {} + void TearDown() override {} +}; + +class REGISTER_CALLBACK : public testing::Test { +public: + static void SetUpTestCase() {} + static void TearDownTestCase() {} + virtual void SetUp() override; + virtual void TearDown() override; + + const DeviceGroupManager *gm = nullptr; + const GroupAuthManager *ga = nullptr; +}; + +class CREATE_GROUP_P2P : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; +}; + +class AUTHENTICATE_GA : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override {} + void TearDown() override {} +}; + +class ADD_MEMBER_TO_GROUP : public testing::Test { +public: + static void SetUpTestCase() {}; + static void TearDownTestCase() {}; + void SetUp() override; + void TearDown() override; +}; + +class REGISTER_LISTENER : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; +}; + +class QUERY_INTERFACE : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; +}; +#endif + diff --git a/test/unittest/deviceauth/include/deviceauth_test_mock.h b/test/unittest/deviceauth/include/deviceauth_test_mock.h new file mode 100644 index 0000000..e8c7efe --- /dev/null +++ b/test/unittest/deviceauth/include/deviceauth_test_mock.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DEVICEAUTH_STANDARD_MOCK_H +#define DEVICEAUTH_STANDARD_MOCK_H + +#include +#include +#include "hc_dev_info.h" + +void SetClient(bool tag); +bool GetClient(); + +#endif diff --git a/test/unittest/deviceauth/source/deviceauth_standard_test.cpp b/test/unittest/deviceauth/source/deviceauth_standard_test.cpp new file mode 100644 index 0000000..719f62e --- /dev/null +++ b/test/unittest/deviceauth/source/deviceauth_standard_test.cpp @@ -0,0 +1,1524 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "deviceauth_standard_test.h" +#include "deviceauth_test_mock.h" +#include +extern "C" { +#include "common_defs.h" +#include "json_utils.h" +#include "device_auth.h" +#include "device_auth_defines.h" +#include "database_manager.h" +#include "hc_condition.h" +#include "hc_mutex.h" +#include "hc_types.h" +} + +using namespace std; + +static bool g_isNeedContinue = false; +static int64_t g_requestId = 0L; +static int g_operationCode = -1; +static int g_errorCode = 1; +static char *g_tempStr = nullptr; +static int g_messageCode = -1; +static char g_dataBuffer[BUFFER_SIZE] = { 0 }; +static HcCondition g_testCondition; +static const DeviceGroupManager *g_testGm = nullptr; +static const GroupAuthManager *g_testGa = nullptr; +static DeviceAuthCallback g_gaCallback; + +static void DelayWithMSec(int32_t mSecs) +{ + struct timeval out; + out.tv_sec = 0; + out.tv_usec = mSecs * 1000; + (void)select(1, NULL, NULL, NULL, &out); + return; +} + +void ClearTempValue() +{ + g_isNeedContinue = false; + g_requestId = 0L; + g_operationCode = -1; + g_errorCode = 1; + g_tempStr = nullptr; + g_messageCode = -1; +} + +/* delete file path success */ +static int32_t RemoveDir(const char *path) +{ + char strBuf[BUFFER_SIZE] = {0}; + if (path == nullptr) { + return -1; + } + sprintf_s(strBuf, sizeof(strBuf) - 1, "rm -rf %s", path); + cout << strBuf << endl; + system(strBuf); + return 0; +} + +static void RemoveHuks(void) +{ + int ret; + ret = RemoveDir("/data/data/maindata"); + cout << "[Clear] clear huks:maindata done: " << ret << endl; + ret = RemoveDir("/data/data/bakdata"); + cout << "[Clear] clear huks:bakdata done: " << ret << endl; +} + +static int DeleteDatabase() +{ + const char *groupPath = "/data/data/deviceauth/hcgroup.dat"; + int ret; + ret = RemoveDir(groupPath); + cout << "[Clear] clear db: done: " << ret << endl; + RemoveHuks(); + /* wait for delete data */ + DelayWithMSec(500); + return 0; +} + +#define CHECK_GROUP_ID(groupInfo) const char *groupId = GetStringFromJson(groupInfo, FIELD_GROUP_ID); \ +ret = strcmp(groupId, "BC680ED1137A5731F4A5A90B1AACC4A0A3663F6FC2387B7273EFBCC66A54DC0B"); \ +EXPECT_EQ(ret == HC_SUCCESS, true); + +#define PRINT_COST_TIME(costTime) cout << "[ TIME ] used time: " << costTime << "(ms)" << endl; + +#define CHECK_EXPIRE_TIME(groupInfo, tmpExpireTime) int expireTime = 0; \ +GetIntFromJson(groupInfo, FIELD_EXPIRE_TIME, &expireTime); \ +EXPECT_EQ(expireTime, tmpExpireTime); + +static char *OnRequestNormal(int64_t requestId, int operationCode, const char *reqParams) +{ + g_messageCode = ON_REQUEST; + g_requestId = requestId; + g_operationCode = operationCode; + CJson *json = CreateJson(); + AddIntToJson(json, FIELD_CONFIRMATION, REQUEST_ACCEPTED); + AddStringToJson(json, FIELD_PIN_CODE, "123456"); + AddStringToJson(json, FIELD_DEVICE_ID, SERVER_AUTH_ID); + AddIntToJson(json, FIELD_USER_TYPE, DEVICE_TYPE_ACCESSORY); + AddIntToJson(json, FIELD_GROUP_VISIBILITY, GROUP_VISIBILITY_PUBLIC); + AddIntToJson(json, FIELD_EXPIRE_TIME, 90); + char *returnDataStr = PackJsonToString(json); + FreeJson(json); + return returnDataStr; +} + +static char *OnRequestError1(int64_t requestId, int operationCode, const char *reqParams) +{ + g_messageCode = ON_REQUEST; + g_requestId = requestId; + g_operationCode = operationCode; + CJson *json = CreateJson(); + AddIntToJson(json, FIELD_CONFIRMATION, REQUEST_REJECTED); + AddStringToJson(json, FIELD_PIN_CODE, "123456"); + AddStringToJson(json, FIELD_DEVICE_ID, SERVER_AUTH_ID); + AddIntToJson(json, FIELD_USER_TYPE, DEVICE_TYPE_ACCESSORY); + AddIntToJson(json, FIELD_GROUP_VISIBILITY, GROUP_VISIBILITY_PUBLIC); + AddIntToJson(json, FIELD_EXPIRE_TIME, 90); + char *returnDataStr = PackJsonToString(json); + FreeJson(json); + return returnDataStr; +} + +static char *OnRequestError2(int64_t requestId, int operationCode, const char *reqParams) +{ + g_messageCode = ON_REQUEST; + g_requestId = requestId; + g_operationCode = operationCode; + CJson *json = CreateJson(); + AddIntToJson(json, FIELD_CONFIRMATION, REQUEST_ACCEPTED); + AddStringToJson(json, FIELD_DEVICE_ID, SERVER_AUTH_ID); + AddIntToJson(json, FIELD_USER_TYPE, DEVICE_TYPE_ACCESSORY); + AddIntToJson(json, FIELD_GROUP_VISIBILITY, GROUP_VISIBILITY_PUBLIC); + AddIntToJson(json, FIELD_EXPIRE_TIME, 90); + char *returnDataStr = PackJsonToString(json); + FreeJson(json); + return returnDataStr; +} + +static char *OnRequestError3(int64_t requestId, int operationCode, const char *reqParams) +{ + g_messageCode = ON_REQUEST; + g_requestId = requestId; + g_operationCode = operationCode; + CJson *json = CreateJson(); + AddIntToJson(json, FIELD_CONFIRMATION, REQUEST_ACCEPTED); + AddStringToJson(json, FIELD_PIN_CODE, "123456"); + AddStringToJson(json, FIELD_DEVICE_ID, SERVER_AUTH_ID); + AddIntToJson(json, FIELD_USER_TYPE, -1); + AddIntToJson(json, FIELD_GROUP_VISIBILITY, GROUP_VISIBILITY_PUBLIC); + AddIntToJson(json, FIELD_EXPIRE_TIME, 90); + char *returnDataStr = PackJsonToString(json); + FreeJson(json); + return returnDataStr; +} + +static char *OnRequestError4(int64_t requestId, int operationCode, const char *reqParams) +{ + g_messageCode = ON_REQUEST; + g_requestId = requestId; + g_operationCode = operationCode; + CJson *json = CreateJson(); + AddIntToJson(json, FIELD_CONFIRMATION, REQUEST_ACCEPTED); + AddStringToJson(json, FIELD_PIN_CODE, "123456"); + AddStringToJson(json, FIELD_DEVICE_ID, SERVER_AUTH_ID); + AddIntToJson(json, FIELD_USER_TYPE, DEVICE_TYPE_ACCESSORY); + AddIntToJson(json, FIELD_GROUP_VISIBILITY, GROUP_VISIBILITY_SIGNATURE); + AddIntToJson(json, FIELD_EXPIRE_TIME, 90); + char *returnDataStr = PackJsonToString(json); + FreeJson(json); + return returnDataStr; +} + +static char *OnRequestError5(int64_t requestId, int operationCode, const char *reqParams) +{ + g_messageCode = ON_REQUEST; + g_requestId = requestId; + g_operationCode = operationCode; + CJson *json = CreateJson(); + AddIntToJson(json, FIELD_CONFIRMATION, REQUEST_ACCEPTED); + AddStringToJson(json, FIELD_PIN_CODE, "123456"); + AddStringToJson(json, FIELD_DEVICE_ID, SERVER_AUTH_ID); + AddIntToJson(json, FIELD_USER_TYPE, DEVICE_TYPE_ACCESSORY); + AddIntToJson(json, FIELD_GROUP_VISIBILITY, GROUP_VISIBILITY_PUBLIC); + AddIntToJson(json, FIELD_EXPIRE_TIME, -2); + char *returnDataStr = PackJsonToString(json); + FreeJson(json); + return returnDataStr; +} + +static void OnError(int64_t requestId, int operationCode, int errorCode, const char *errorReturn) +{ + (void)errorReturn; + g_messageCode = ON_ERROR; + g_requestId = requestId; + g_operationCode = operationCode; + g_errorCode = errorCode; + g_testCondition.notify(&g_testCondition); +} + +static void OnError2(int64_t requestId, int operationCode, int errorCode, const char *errorReturn) +{ + (void)errorReturn; + g_messageCode = ON_ERROR; + g_requestId = requestId; + g_operationCode = operationCode; + g_errorCode = errorCode; +} + +static void OnFinish(int64_t requestId, int operationCode, const char *returnData) +{ + g_messageCode = ON_FINISH; + g_requestId = requestId; + g_operationCode = operationCode; + if (operationCode == GROUP_CREATE) { + CJson *json = CreateJsonFromString(returnData); + const char *groupId = GetStringFromJson(json, FIELD_GROUP_ID); + (void)memcpy_s(g_dataBuffer, BUFFER_SIZE, groupId, strlen(groupId)); + FreeJson(json); + } + g_testCondition.notify(&g_testCondition); +} + +static void OnFinish2(int64_t requestId, int operationCode, const char *returnData) +{ + g_messageCode = ON_FINISH; + g_requestId = requestId; + g_operationCode = operationCode; +} + +static void OnSessionKeyReturned(int64_t requestId, const uint8_t *sessionKey, uint32_t sessionKeyLen) +{ + g_messageCode = ON_SESSION_KEY_RETURNED; + g_requestId = requestId; +} + +static bool OnTransmit(int64_t requestId, const uint8_t *data, uint32_t dataLen) +{ + g_messageCode = ON_TRANSMIT; + g_requestId = requestId; + g_isNeedContinue = true; + memset_s(g_dataBuffer, BUFFER_SIZE, 0, BUFFER_SIZE); + memcpy_s(g_dataBuffer, BUFFER_SIZE, data, dataLen); + return true; +} + +static char *GaOnRequest(int64_t requestId, int operationCode, const char *reqParams) +{ + g_messageCode = ON_REQUEST; + g_requestId = requestId; + g_operationCode = operationCode; + CJson *json = CreateJson(); + AddIntToJson(json, FIELD_CONFIRMATION, REQUEST_ACCEPTED); + AddStringToJson(json, FIELD_SERVICE_PKG_NAME, TEST_APP_NAME); + AddStringToJson(json, FIELD_PEER_CONN_DEVICE_ID, "udid1"); + char *returnDataStr = PackJsonToString(json); + FreeJson(json); + return returnDataStr; +} + +enum { + GROUP_CREATED = 0, + GROUP_DELETED, + DEVICE_BOUND, + DEVICE_UNBOUND, + DEVICE_NOT_TRUSTED, + LAST_GROUP_DELETED, + TRUSTED_DEVICE_NUM_CHANGED +}; + +static int g_receivedMessageNum[7] = {0}; + +void OnGroupCreated(const char *groupInfo) +{ + g_receivedMessageNum[GROUP_CREATED]++; +} + +void OnGroupDeleted(const char *groupInfo) +{ + g_receivedMessageNum[GROUP_DELETED]++; +} + +void OnDeviceBound(const char *peerUdid, const char *groupInfo) +{ + g_receivedMessageNum[DEVICE_BOUND]++; +} + +void OnDeviceUnBound(const char *peerUdid, const char *groupInfo) +{ + g_receivedMessageNum[DEVICE_UNBOUND]++; +} + +void OnDeviceNotTrusted(const char *peerUdid) +{ + g_receivedMessageNum[DEVICE_NOT_TRUSTED]++; +} + +void OnLastGroupDeleted(const char *peerUdid, int groupType) +{ + g_receivedMessageNum[LAST_GROUP_DELETED]++; +} + +void OnTrustedDeviceNumChanged(int curTrustedDeviceNum) +{ + g_receivedMessageNum[TRUSTED_DEVICE_NUM_CHANGED]++; +} + +static void InitCaseResource(void) +{ + int32_t ret; + const DeviceGroupManager *gmTmp = nullptr; + ret = InitDeviceAuthService(); + EXPECT_EQ(ret == HC_SUCCESS, true); + gmTmp = GetGmInstance(); + EXPECT_NE(gmTmp, nullptr); + g_testGm = gmTmp; + g_gaCallback.onRequest = OnRequestNormal; + g_gaCallback.onTransmit = OnTransmit; + g_gaCallback.onFinish = OnFinish; + g_gaCallback.onError = OnError; + g_gaCallback.onSessionKeyReturned = OnSessionKeyReturned; + g_testGm->regCallback(TEST_APP_NAME, &g_gaCallback); + DelayWithMSec(500); +} + +static void DeInitCaseResource(void) +{ + DestroyDeviceAuthService(); + ClearTempValue(); + g_testGm = nullptr; +} + +/* test suit - GET_INSTANCE */ +void GET_INSTANCE::SetUpTestCase() +{ + int32_t ret; + ret = InitDeviceAuthService(); + EXPECT_EQ(ret == HC_SUCCESS, true); +} + +void GET_INSTANCE::TearDownTestCase() +{ + DestroyDeviceAuthService(); + ClearTempValue(); +} + +/* test suit - REGISTER_CALLBACK */ +void REGISTER_CALLBACK::SetUp() +{ + int32_t ret; + ret = InitDeviceAuthService(); + EXPECT_EQ(ret == HC_SUCCESS, true); + gm = GetGmInstance(); + EXPECT_NE(gm, nullptr); +} + +void REGISTER_CALLBACK::TearDown() +{ + DestroyDeviceAuthService(); + ClearTempValue(); + gm = nullptr; +} + +/* test suit - CREATE_GROUP_P2P */ +void CREATE_GROUP_P2P::SetUpTestCase() +{ + InitHcCond(&g_testCondition, nullptr); +} + +void CREATE_GROUP_P2P::TearDownTestCase() +{ + DestroyHcCond(&g_testCondition); +} +void CREATE_GROUP_P2P::SetUp() +{ + SetClient(false); + DeleteDatabase(); + InitCaseResource(); +} + +void CREATE_GROUP_P2P::TearDown() +{ + DeInitCaseResource(); +} + +/* test suit - AUTHENTICATE_GA */ +void AUTHENTICATE_GA::SetUpTestCase() +{ + int32_t ret; + ret = InitDeviceAuthService(); + EXPECT_EQ(ret == HC_SUCCESS, true); + g_gaCallback = { + OnTransmit, + OnSessionKeyReturned, + OnFinish, + OnError, + GaOnRequest + }; + g_testGa = GetGaInstance(); + EXPECT_NE(g_testGa, nullptr); + SetClient(false); +} + +void AUTHENTICATE_GA::TearDownTestCase() +{ + DestroyDeviceAuthService(); + DeleteDatabase(); + ClearTempValue(); + g_testGa = nullptr; +} + +/* test suit - ADD_MEMBER_TO_GROUP */ +void ADD_MEMBER_TO_GROUP::SetUp() +{ + int32_t ret; + const DeviceGroupManager *gmTmp = nullptr; + + DeleteDatabase(); + ret = InitDeviceAuthService(); + EXPECT_EQ(ret == HC_SUCCESS, true); + g_gaCallback = { + OnTransmit, + OnSessionKeyReturned, + OnFinish2, + OnError2, + OnRequestNormal + }; + gmTmp = GetGmInstance(); + EXPECT_NE(gmTmp, nullptr); + g_testGm = gmTmp; + ret = g_testGm->regCallback(TEST_APP_NAME, &g_gaCallback); + EXPECT_EQ(ret == HC_SUCCESS, true); + SetClient(false); +} + +void ADD_MEMBER_TO_GROUP::TearDown() +{ + DestroyDeviceAuthService(); + DeleteDatabase(); + ClearTempValue(); + g_testGm = nullptr; +} + +/* test suit - REGISTER_LISTENER */ +void REGISTER_LISTENER::SetUpTestCase() +{ + DeleteDatabase(); + InitHcCond(&g_testCondition, nullptr); +} + +void REGISTER_LISTENER::TearDownTestCase() +{ + DestroyHcCond(&g_testCondition); +} + +void REGISTER_LISTENER::SetUp() +{ + InitDeviceAuthService(); + g_gaCallback = { + OnTransmit, + OnSessionKeyReturned, + OnFinish, + OnError, + OnRequestNormal + }; + g_testGm = GetGmInstance(); + g_testGm->regCallback(TEST_APP_NAME, &g_gaCallback); + DelayWithMSec(500); +} +void REGISTER_LISTENER::TearDown() +{ + DestroyDeviceAuthService(); + DeleteDatabase(); + ClearTempValue(); +} + +void QUERY_INTERFACE::SetUpTestCase() +{ + DeleteDatabase(); +} + +void QUERY_INTERFACE::TearDownTestCase() {} + +void QUERY_INTERFACE::SetUp() +{ + InitDeviceAuthService(); + g_gaCallback = { + OnTransmit, + OnSessionKeyReturned, + OnFinish2, + OnError2, + OnRequestNormal + }; + g_testGm = GetGmInstance(); + g_testGm->regCallback(TEST_APP_NAME, &g_gaCallback); +} +void QUERY_INTERFACE::TearDown() +{ + DestroyDeviceAuthService(); + DeleteDatabase(); + ClearTempValue(); +} + +/* start cases */ +TEST_F(GET_INSTANCE, TC_GET_GM_INSTANCE) +{ + const DeviceGroupManager *gm = GetGmInstance(); + EXPECT_NE(gm, nullptr); +} + +TEST_F(GET_INSTANCE, TC_GET_GA_INSTANCE) +{ + const GroupAuthManager *ga = GetGaInstance(); + EXPECT_NE(ga, nullptr); +} + +TEST_F(REGISTER_CALLBACK, TC_REGISTER_CALLBACK_NORMAL) +{ + DeviceAuthCallback callback; + callback.onRequest = OnRequestNormal; + callback.onError = OnError; + callback.onFinish = OnFinish; + callback.onSessionKeyReturned = OnSessionKeyReturned; + callback.onTransmit = OnTransmit; + int ret = gm->regCallback(TEST_APP_NAME, &callback); + EXPECT_EQ(ret == HC_SUCCESS, true); +} + +TEST_F(REGISTER_CALLBACK, TC_DEREGISTER_CALLBACK_NORMAL) +{ + EXPECT_EQ(gm->unRegCallback(TEST_APP_NAME) == HC_SUCCESS, true); +} + +TEST_F(CREATE_GROUP_P2P, TC_CREATE_P2P_GROUP) +{ + g_gaCallback.onRequest = OnRequestNormal; + g_gaCallback.onTransmit = OnTransmit; + g_gaCallback.onFinish = OnFinish; + g_gaCallback.onError = OnError; + g_gaCallback.onSessionKeyReturned = OnSessionKeyReturned; + g_testGm->regCallback(TEST_APP_NAME, &g_gaCallback); + DelayWithMSec(500); + + CJson *createParams = CreateJson(); + AddIntToJson(createParams, FIELD_GROUP_TYPE, PEER_TO_PEER_GROUP); + AddStringToJson(createParams, FIELD_DEVICE_ID, "3C58C27533D8"); + AddIntToJson(createParams, FIELD_USER_TYPE, DEVICE_TYPE_ACCESSORY); + AddIntToJson(createParams, FIELD_GROUP_VISIBILITY, GROUP_VISIBILITY_PUBLIC); + AddIntToJson(createParams, FIELD_EXPIRE_TIME, 90); + AddStringToJson(createParams, FIELD_GROUP_NAME, "P2PGroup"); + char *createParamsStr = PackJsonToString(createParams); + int ret = g_testGm->createGroup(TEMP_REQUEST_ID, TEST_APP_NAME, createParamsStr); + FreeJsonString(createParamsStr); + FreeJson(createParams); + g_testCondition.wait(&g_testCondition); + EXPECT_EQ(ret == HC_SUCCESS, true); + EXPECT_EQ(g_messageCode, ON_FINISH); + EXPECT_EQ(g_operationCode, GROUP_CREATE); + EXPECT_EQ(g_requestId, TEMP_REQUEST_ID); + CJson *returnData = CreateJson(); + AddStringToJson(returnData, FIELD_GROUP_OWNER, TEST_APP_NAME); + char *queryParams = PackJsonToString(returnData); + FreeJson(returnData); + char *groupVec = nullptr; + uint32_t num = 0; + ret = g_testGm->getGroupInfo(TEST_APP_NAME, queryParams, &groupVec, &num); + FreeJsonString(queryParams); + EXPECT_EQ(ret == HC_SUCCESS, true); + EXPECT_EQ(num, 1u); + CJson *groupVecJson = CreateJsonFromString(groupVec); + CJson *groupInfo = GetItemFromArray(groupVecJson, 0); + CHECK_GROUP_ID(groupInfo); + FreeJson(groupVecJson); + g_testGm->destroyInfo(&groupVec); +} + +TEST_F(CREATE_GROUP_P2P, TC_INVALID_PARAM_01) +{ + CJson *createParams = CreateJson(); + AddIntToJson(createParams, FIELD_GROUP_TYPE, 258); + AddStringToJson(createParams, FIELD_DEVICE_ID, "3C58C27533D8"); + AddIntToJson(createParams, FIELD_USER_TYPE, DEVICE_TYPE_ACCESSORY); + AddIntToJson(createParams, FIELD_GROUP_VISIBILITY, GROUP_VISIBILITY_PUBLIC); + AddIntToJson(createParams, FIELD_EXPIRE_TIME, 90); + AddStringToJson(createParams, FIELD_GROUP_NAME, "P2PGroup"); + char *createParamsStr = PackJsonToString(createParams); + FreeJson(createParams); + int ret = g_testGm->createGroup(TEMP_REQUEST_ID, TEST_APP_NAME, createParamsStr); + FreeJsonString(createParamsStr); + g_testCondition.wait(&g_testCondition); + EXPECT_EQ(ret == HC_SUCCESS, true); + EXPECT_EQ(g_messageCode, ON_ERROR); + EXPECT_EQ(g_operationCode, GROUP_CREATE); + EXPECT_EQ(g_requestId, TEMP_REQUEST_ID); + EXPECT_EQ(g_errorCode == HC_ERR_INVALID_PARAMS, true); +} + +TEST_F(CREATE_GROUP_P2P, TC_INVALID_PARAM_02) +{ + CJson *createParams = CreateJson(); + AddIntToJson(createParams, FIELD_GROUP_TYPE, PEER_TO_PEER_GROUP); + AddIntToJson(createParams, FIELD_USER_TYPE, DEVICE_TYPE_ACCESSORY); + AddIntToJson(createParams, FIELD_GROUP_VISIBILITY, GROUP_VISIBILITY_PUBLIC); + AddIntToJson(createParams, FIELD_EXPIRE_TIME, 90); + AddStringToJson(createParams, FIELD_GROUP_NAME, "P2PGroup"); + char *createParamsStr = PackJsonToString(createParams); + FreeJson(createParams); + int ret = g_testGm->createGroup(TEMP_REQUEST_ID, TEST_APP_NAME, createParamsStr); + FreeJsonString(createParamsStr); + g_testCondition.wait(&g_testCondition); + EXPECT_EQ(ret == HC_SUCCESS, true); + EXPECT_EQ(g_messageCode, ON_FINISH); + EXPECT_EQ(g_operationCode, GROUP_CREATE); + EXPECT_EQ(g_requestId, TEMP_REQUEST_ID); + CJson *returnData = CreateJson(); + AddStringToJson(returnData, FIELD_GROUP_OWNER, TEST_APP_NAME); + char *queryParams = PackJsonToString(returnData); + FreeJson(returnData); + char *groupVec = nullptr; + uint32_t num = 0; + ret = g_testGm->getGroupInfo(TEST_APP_NAME, queryParams, &groupVec, &num); + FreeJsonString(queryParams); + EXPECT_EQ(ret == HC_SUCCESS, true); + EXPECT_EQ(num, 1u); + g_testGm->destroyInfo(&groupVec); +} + +TEST_F(CREATE_GROUP_P2P, TC_INVALID_PARAM_03) +{ + CJson *createParams = CreateJson(); + AddIntToJson(createParams, FIELD_GROUP_TYPE, PEER_TO_PEER_GROUP); + AddStringToJson(createParams, FIELD_DEVICE_ID, "3C58C27533D8"); + AddIntToJson(createParams, FIELD_USER_TYPE, 3); + AddIntToJson(createParams, FIELD_GROUP_VISIBILITY, GROUP_VISIBILITY_PUBLIC); + AddIntToJson(createParams, FIELD_EXPIRE_TIME, 90); + AddStringToJson(createParams, FIELD_GROUP_NAME, "P2PGroup"); + char *createParamsStr = PackJsonToString(createParams); + FreeJson(createParams); + int ret = g_testGm->createGroup(TEMP_REQUEST_ID, TEST_APP_NAME, createParamsStr); + FreeJsonString(createParamsStr); + g_testCondition.wait(&g_testCondition); + EXPECT_EQ(ret == HC_SUCCESS, true); + EXPECT_EQ(g_messageCode, ON_ERROR); + EXPECT_EQ(g_operationCode, GROUP_CREATE); + EXPECT_EQ(g_requestId, TEMP_REQUEST_ID); + EXPECT_EQ(g_errorCode == HC_ERR_INVALID_PARAMS, true); +} + +TEST_F(CREATE_GROUP_P2P, TC_INVALID_PARAM_04) +{ + CJson *createParams = CreateJson(); + AddIntToJson(createParams, FIELD_GROUP_TYPE, PEER_TO_PEER_GROUP); + AddStringToJson(createParams, FIELD_DEVICE_ID, "3C58C27533D8"); + AddIntToJson(createParams, FIELD_USER_TYPE, DEVICE_TYPE_ACCESSORY); + AddIntToJson(createParams, FIELD_GROUP_VISIBILITY, 1); + AddIntToJson(createParams, FIELD_EXPIRE_TIME, 90); + AddStringToJson(createParams, FIELD_GROUP_NAME, "P2PGroup"); + char *createParamsStr = PackJsonToString(createParams); + FreeJson(createParams); + int ret = g_testGm->createGroup(TEMP_REQUEST_ID, TEST_APP_NAME, createParamsStr); + FreeJsonString(createParamsStr); + g_testCondition.wait(&g_testCondition); + EXPECT_EQ(ret == HC_SUCCESS, true); + EXPECT_EQ(g_messageCode, ON_ERROR); + EXPECT_EQ(g_operationCode, GROUP_CREATE); + EXPECT_EQ(g_requestId, TEMP_REQUEST_ID); + EXPECT_EQ(g_errorCode == HC_ERR_INVALID_PARAMS, true); +} + +TEST_F(CREATE_GROUP_P2P, TC_INVALID_PARAM_05) +{ + CJson *createParams = CreateJson(); + AddIntToJson(createParams, FIELD_GROUP_TYPE, PEER_TO_PEER_GROUP); + AddStringToJson(createParams, FIELD_DEVICE_ID, "3C58C27533D8"); + AddIntToJson(createParams, FIELD_USER_TYPE, DEVICE_TYPE_ACCESSORY); + AddIntToJson(createParams, FIELD_GROUP_VISIBILITY, GROUP_VISIBILITY_PUBLIC); + AddIntToJson(createParams, FIELD_EXPIRE_TIME, 90); + char *createParamsStr = PackJsonToString(createParams); + FreeJson(createParams); + int ret = g_testGm->createGroup(TEMP_REQUEST_ID, TEST_APP_NAME, createParamsStr); + FreeJsonString(createParamsStr); + g_testCondition.wait(&g_testCondition); + EXPECT_EQ(ret == HC_SUCCESS, true); + EXPECT_EQ(g_messageCode, ON_ERROR); + EXPECT_EQ(g_operationCode, GROUP_CREATE); + EXPECT_EQ(g_requestId, TEMP_REQUEST_ID); + EXPECT_EQ(g_errorCode == HC_ERR_JSON_GET, true); +} + +TEST_F(CREATE_GROUP_P2P, TC_INVALID_PARAM_06) +{ + CJson *createParams = CreateJson(); + AddIntToJson(createParams, FIELD_GROUP_TYPE, PEER_TO_PEER_GROUP); + AddStringToJson(createParams, FIELD_DEVICE_ID, "3C58C27533D8"); + AddIntToJson(createParams, FIELD_USER_TYPE, DEVICE_TYPE_ACCESSORY); + AddIntToJson(createParams, FIELD_GROUP_VISIBILITY, GROUP_VISIBILITY_PUBLIC); + AddIntToJson(createParams, FIELD_EXPIRE_TIME, 90); + AddStringToJson(createParams, FIELD_GROUP_NAME, "P2PGroup"); + char *createParamsStr = PackJsonToString(createParams); + int ret = g_testGm->createGroup(TEMP_REQUEST_ID, TEST_APP_NAME, createParamsStr); + g_testCondition.wait(&g_testCondition); + ClearTempValue(); + ret = g_testGm->createGroup(TEMP_REQUEST_ID, TEST_APP_NAME, createParamsStr); + FreeJsonString(createParamsStr); + FreeJson(createParams); + g_testCondition.wait(&g_testCondition); + EXPECT_EQ(ret == HC_SUCCESS, true); + EXPECT_EQ(g_messageCode, ON_ERROR); + EXPECT_EQ(g_operationCode, GROUP_CREATE); + EXPECT_EQ(g_requestId, TEMP_REQUEST_ID); + EXPECT_EQ(g_errorCode == HC_ERR_INVALID_PARAMS, true); +} + +TEST_F(CREATE_GROUP_P2P, TC_INVALID_PARAM_07) +{ + CJson *createParams = CreateJson(); + AddIntToJson(createParams, FIELD_GROUP_TYPE, PEER_TO_PEER_GROUP); + AddStringToJson(createParams, FIELD_DEVICE_ID, "3C58C27533D8"); + AddIntToJson(createParams, FIELD_USER_TYPE, DEVICE_TYPE_ACCESSORY); + AddIntToJson(createParams, FIELD_GROUP_VISIBILITY, GROUP_VISIBILITY_PUBLIC); + AddIntToJson(createParams, FIELD_EXPIRE_TIME, -2); + AddStringToJson(createParams, FIELD_GROUP_NAME, "P2PGroup"); + char *createParamsStr = PackJsonToString(createParams); + FreeJson(createParams); + int ret = g_testGm->createGroup(TEMP_REQUEST_ID, TEST_APP_NAME, createParamsStr); + FreeJsonString(createParamsStr); + g_testCondition.wait(&g_testCondition); + EXPECT_EQ(ret == HC_SUCCESS, true); + EXPECT_EQ(g_messageCode, ON_ERROR); + EXPECT_EQ(g_operationCode, GROUP_CREATE); + EXPECT_EQ(g_requestId, TEMP_REQUEST_ID); + EXPECT_EQ(g_errorCode == HC_ERR_INVALID_PARAMS, true); +} + +TEST_F(CREATE_GROUP_P2P, TC_INVALID_PARAM_08) +{ + CJson *createParams = CreateJson(); + AddIntToJson(createParams, FIELD_GROUP_TYPE, PEER_TO_PEER_GROUP); + AddStringToJson(createParams, FIELD_DEVICE_ID, "3C58C27533D8"); + AddIntToJson(createParams, FIELD_USER_TYPE, DEVICE_TYPE_ACCESSORY); + AddIntToJson(createParams, FIELD_GROUP_VISIBILITY, GROUP_VISIBILITY_PUBLIC); + AddIntToJson(createParams, FIELD_EXPIRE_TIME, 0); + AddStringToJson(createParams, FIELD_GROUP_NAME, "P2PGroup"); + char *createParamsStr = PackJsonToString(createParams); + FreeJson(createParams); + int ret = g_testGm->createGroup(TEMP_REQUEST_ID, TEST_APP_NAME, createParamsStr); + FreeJsonString(createParamsStr); + g_testCondition.wait(&g_testCondition); + EXPECT_EQ(ret == HC_SUCCESS, true); + EXPECT_EQ(g_messageCode, ON_ERROR); + EXPECT_EQ(g_operationCode, GROUP_CREATE); + EXPECT_EQ(g_requestId, TEMP_REQUEST_ID); + EXPECT_EQ(g_errorCode == HC_ERR_INVALID_PARAMS, true); +} + +TEST_F(CREATE_GROUP_P2P, TC_INVALID_PARAM_09) +{ + CJson *createParams = CreateJson(); + AddIntToJson(createParams, FIELD_GROUP_TYPE, PEER_TO_PEER_GROUP); + AddStringToJson(createParams, FIELD_DEVICE_ID, "3C58C27533D8"); + AddIntToJson(createParams, FIELD_USER_TYPE, DEVICE_TYPE_ACCESSORY); + AddIntToJson(createParams, FIELD_GROUP_VISIBILITY, GROUP_VISIBILITY_PUBLIC); + AddIntToJson(createParams, FIELD_EXPIRE_TIME, 91); + AddStringToJson(createParams, FIELD_GROUP_NAME, "P2PGroup"); + char *createParamsStr = PackJsonToString(createParams); + FreeJson(createParams); + int ret = g_testGm->createGroup(TEMP_REQUEST_ID, TEST_APP_NAME, createParamsStr); + FreeJsonString(createParamsStr); + g_testCondition.wait(&g_testCondition); + EXPECT_EQ(ret == HC_SUCCESS, true); + EXPECT_EQ(g_messageCode, ON_ERROR); + EXPECT_EQ(g_operationCode, GROUP_CREATE); + EXPECT_EQ(g_requestId, TEMP_REQUEST_ID); + EXPECT_EQ(g_errorCode == HC_ERR_INVALID_PARAMS, true); +} + +TEST_F(CREATE_GROUP_P2P, TC_VALID_PARAM_01) +{ + CJson *createParams = CreateJson(); + AddIntToJson(createParams, FIELD_GROUP_TYPE, PEER_TO_PEER_GROUP); + AddStringToJson(createParams, FIELD_DEVICE_ID, "3C58C27533D9"); + AddIntToJson(createParams, FIELD_USER_TYPE, DEVICE_TYPE_ACCESSORY); + AddIntToJson(createParams, FIELD_GROUP_VISIBILITY, GROUP_VISIBILITY_PUBLIC); + AddIntToJson(createParams, FIELD_EXPIRE_TIME, 1); + AddStringToJson(createParams, FIELD_GROUP_NAME, "P2PGroup"); + char *createParamsStr = PackJsonToString(createParams); + FreeJson(createParams); + int ret = g_testGm->createGroup(TEMP_REQUEST_ID, TEST_APP_NAME, createParamsStr); + FreeJsonString(createParamsStr); + g_testCondition.wait(&g_testCondition); + EXPECT_EQ(ret == HC_SUCCESS, true); + EXPECT_EQ(g_messageCode, ON_FINISH); + EXPECT_EQ(g_operationCode, GROUP_CREATE); + EXPECT_EQ(g_requestId, TEMP_REQUEST_ID); +} + +TEST_F(CREATE_GROUP_P2P, TC_VALID_PARAM_02) +{ + CJson *createParams = CreateJson(); + AddIntToJson(createParams, FIELD_GROUP_TYPE, PEER_TO_PEER_GROUP); + AddStringToJson(createParams, FIELD_DEVICE_ID, "3C58C27533D9"); + AddIntToJson(createParams, FIELD_USER_TYPE, DEVICE_TYPE_ACCESSORY); + AddIntToJson(createParams, FIELD_GROUP_VISIBILITY, GROUP_VISIBILITY_PUBLIC); + AddIntToJson(createParams, FIELD_EXPIRE_TIME, -1); + AddStringToJson(createParams, FIELD_GROUP_NAME, "P2PGroup"); + char *createParamsStr = PackJsonToString(createParams); + FreeJson(createParams); + int ret = g_testGm->createGroup(TEMP_REQUEST_ID, TEST_APP_NAME, createParamsStr); + FreeJsonString(createParamsStr); + g_testCondition.wait(&g_testCondition); + EXPECT_EQ(ret == HC_SUCCESS, true); + EXPECT_EQ(g_messageCode, ON_FINISH); + EXPECT_EQ(g_operationCode, GROUP_CREATE); + EXPECT_EQ(g_requestId, TEMP_REQUEST_ID); +} + +TEST_F(CREATE_GROUP_P2P, TC_MAX_GROUP_NUMBER) +{ + CJson *createParams = CreateJson(); + AddIntToJson(createParams, FIELD_GROUP_TYPE, PEER_TO_PEER_GROUP); + AddStringToJson(createParams, FIELD_DEVICE_ID, "7533D8"); + AddIntToJson(createParams, FIELD_USER_TYPE, DEVICE_TYPE_ACCESSORY); + AddIntToJson(createParams, FIELD_GROUP_VISIBILITY, GROUP_VISIBILITY_PUBLIC); + AddIntToJson(createParams, FIELD_EXPIRE_TIME, 90); + for (int i = 1; i < 101; ++i) { + char str[STR_BUFF_SZ_MIN] = {0}; + (void)sprintf_s(str, sizeof(str) - 1, "P2PGroup%d", i); + AddStringToJson(createParams, FIELD_GROUP_NAME, str); + char *createParamsStr = PackJsonToString(createParams); + int ret = g_testGm->createGroup(TEMP_REQUEST_ID, TEST_APP_NAME, createParamsStr); + FreeJsonString(createParamsStr); + g_testCondition.wait(&g_testCondition); + EXPECT_EQ(ret == HC_SUCCESS, true); + EXPECT_EQ(g_messageCode, ON_FINISH); + EXPECT_EQ(g_operationCode, GROUP_CREATE); + EXPECT_EQ(g_requestId, TEMP_REQUEST_ID); + (void)DelTrustedDevice( + "ABCDEF00ABCDEF00ABCDEF00ABCDEF00ABCDEF00ABCDEF00ABCDEF00ABCDEF00", g_dataBuffer); + DelayWithMSec(500); + } + char str[STR_BUFF_SZ_MIN] = {0}; + (void)sprintf_s(str, sizeof(str) - 1, "P2PGroup%d", 101); + AddStringToJson(createParams, FIELD_GROUP_NAME, str); + char *createParamsStr = PackJsonToString(createParams); + FreeJson(createParams); + int ret = g_testGm->createGroup(TEMP_REQUEST_ID, TEST_APP_NAME, createParamsStr); + FreeJsonString(createParamsStr); + g_testCondition.wait(&g_testCondition); + EXPECT_EQ(ret == HC_SUCCESS, true); + EXPECT_EQ(g_messageCode, ON_ERROR); + EXPECT_EQ(g_operationCode, GROUP_CREATE); + EXPECT_EQ(g_requestId, TEMP_REQUEST_ID); +} + +TEST_F(ADD_MEMBER_TO_GROUP, TC_DEV_P2P_BIND_01) +{ + SetClient(true); + g_isNeedContinue = true; + const char * createParamsStr = "{\"groupType\":256,\"deviceId\":\"3C58C27533D8\",\"userType\":0,\"" + "groupVisibility\":-1,\"expireTime\":90,\"groupName\":\"P2PGroup\"}"; + (void)g_testGm->createGroup(TEMP_REQUEST_ID, TEST_APP_NAME, createParamsStr); + DelayWithMSec(500); + DeviceInfo *devAuthParams = CreateDeviceInfoStruct(); + devAuthParams->devType = DEVICE_TYPE_ACCESSORY; + StringSetPointer(&(devAuthParams->authId), "CAF34E13190CBA510AA8DABB70CDFF8E9F623656DED400EF0D4CFD9E88FD6202"); + StringSetPointer(&(devAuthParams->udid), "ABCDEF00ABCDEF00ABCDEF00ABCDEF00ABCDEF00ABCDEF00ABCDEF00ABCDEF00"); + StringSetPointer(&(devAuthParams->groupId), "BC680ED1137A5731F4A5A90B1AACC4A0A3663F6FC2387B7273EFBCC66A54DC0B"); + StringSetPointer(&(devAuthParams->serviceType), "BC680ED1137A5731F4A5A90B1AACC4A0A3663F6FC2387B7273EFBCC66A54DC0B"); + AddTrustedDevice(devAuthParams, NULL); + DestroyDeviceInfoStruct(devAuthParams); + CJson *addParams = CreateJson(); + AddStringToJson(addParams, FIELD_GROUP_ID, "BC680ED1137A5731F4A5A90B1AACC4A0A3663F6FC2387B7273EFBCC66A54DC0B"); + AddIntToJson(addParams, FIELD_GROUP_TYPE, PEER_TO_PEER_GROUP); + AddStringToJson(addParams, FIELD_PIN_CODE, "123456"); + AddBoolToJson(addParams, FIELD_IS_ADMIN, true); + char *addParamsStr = PackJsonToString(addParams); + FreeJson(addParams); + (void)g_testGm->addMemberToGroup(CLIENT_REQUEST_ID, TEST_APP_NAME, addParamsStr); + FreeJsonString(addParamsStr); + DelayWithMSec(500); + while (g_isNeedContinue) + { + SetClient(!GetClient()); + CJson *data = CreateJsonFromString(g_dataBuffer); + int64_t req = DEFAULT_REQUEST_ID; + GetInt64FromJson(data, FIELD_REQUEST_ID, &req); + if (req == CLIENT_REQUEST_ID) { + req = SERVER_REQUEST_ID; + } else { + req = CLIENT_REQUEST_ID; + } + AddInt64StringToJson(data, FIELD_REQUEST_ID, req); + char *dataStr = PackJsonToString(data); + FreeJson(data); + memset_s(g_dataBuffer, BUFFER_SIZE, 0, BUFFER_SIZE); + memcpy_s(g_dataBuffer, BUFFER_SIZE, dataStr, strlen(dataStr) + 1); + FreeJsonString(dataStr); + g_testGm->processData(req, (uint8_t *)g_dataBuffer, strlen(g_dataBuffer) + 1); + g_isNeedContinue = false; + DelayWithMSec(500); + } + EXPECT_EQ(g_messageCode, ON_FINISH); + EXPECT_EQ(g_operationCode, MEMBER_INVITE); +} + +static char *ConstructAddParams02() +{ + CJson *addParams = CreateJson(); + AddStringToJson(addParams, FIELD_GROUP_ID, "BC680ED1137A5731F4A5A90B1AACC4A0A3663F6FC2387B7273EFBCC66A54DC0B"); + AddIntToJson(addParams, FIELD_GROUP_TYPE, PEER_TO_PEER_GROUP); + AddStringToJson(addParams, FIELD_PIN_CODE, "123456"); + AddBoolToJson(addParams, FIELD_IS_ADMIN, false); + AddStringToJson(addParams, FIELD_DEVICE_ID, CLIENT_AUTH_ID); + AddStringToJson(addParams, FIELD_GROUP_NAME, "P2PGroup"); + char *addParamsStr = PackJsonToString(addParams); + FreeJson(addParams); + return addParamsStr; +} + +TEST_F(ADD_MEMBER_TO_GROUP, TC_DEV_P2P_BIND_02) +{ + SetClient(false); + g_isNeedContinue = true; + const char * createParamsStr = + "{\"groupType\":256,\"deviceId\":\"CAF34E13190CBA510AA8DABB70CDFF8E9F623656DED400EF0D4CFD9E88FD6202\"," + "\"userType\":0,\"groupVisibility\":-1,\"expireTime\":90,\"groupName\":\"P2PGroup\"}"; + g_testGm->createGroup(TEMP_REQUEST_ID, TEST_APP_NAME, createParamsStr); + DelayWithMSec(500); + SetClient(true); + DeviceInfo *devAuthParams = CreateDeviceInfoStruct(); + devAuthParams->devType = DEVICE_TYPE_ACCESSORY; + StringSetPointer(&(devAuthParams->authId), "3C58C27533D8"); + StringSetPointer(&(devAuthParams->udid), "D6350E39AD8F11963C181BEEDC11AC85158E04466B68F1F4E6D895237E0FE81C"); + StringSetPointer(&(devAuthParams->groupId), "BC680ED1137A5731F4A5A90B1AACC4A0A3663F6FC2387B7273EFBCC66A54DC0B"); + StringSetPointer(&(devAuthParams->serviceType), "BC680ED1137A5731F4A5A90B1AACC4A0A3663F6FC2387B7273EFBCC66A54DC0B"); + AddTrustedDevice(devAuthParams, NULL); + DestroyDeviceInfoStruct(devAuthParams); + char *addParamsStr = ConstructAddParams02(); + g_testGm->addMemberToGroup(CLIENT_REQUEST_ID, TEST_APP_NAME, addParamsStr); + FreeJsonString(addParamsStr); + DelayWithMSec(500); + while (g_isNeedContinue) + { + SetClient(!GetClient()); + CJson *data = CreateJsonFromString(g_dataBuffer); + int64_t req = DEFAULT_REQUEST_ID; + GetInt64FromJson(data, FIELD_REQUEST_ID, &req); + if (req == CLIENT_REQUEST_ID) { + req = SERVER_REQUEST_ID; + } else { + req = CLIENT_REQUEST_ID; + } + AddInt64StringToJson(data, FIELD_REQUEST_ID, req); + char *dataStr = PackJsonToString(data); + FreeJson(data); + memset_s(g_dataBuffer, BUFFER_SIZE, 0, BUFFER_SIZE); + memcpy_s(g_dataBuffer, BUFFER_SIZE, dataStr, strlen(dataStr) + 1); + FreeJsonString(dataStr); + g_testGm->processData(req, (uint8_t *)g_dataBuffer, strlen(g_dataBuffer) + 1); + g_isNeedContinue = false; + DelayWithMSec(500); + } + EXPECT_EQ(g_messageCode, ON_FINISH); + EXPECT_EQ(g_operationCode, MEMBER_JOIN); +} + +TEST_F(ADD_MEMBER_TO_GROUP, TC_DEV_P2P_BIND_03) +{ + SetClient(true); + g_isNeedContinue = true; + const char * createParamsStr = "{\"groupType\":256,\"deviceId\":\"3C58C27533D8\",\"userType\":0,\"" + "groupVisibility\":-1,\"expireTime\":90,\"groupName\":\"P2PGroup\"}"; + g_testGm->createGroup(TEMP_REQUEST_ID, TEST_APP_NAME, createParamsStr); + /* delay 1 seconds */ + DelayWithMSec(500); + CJson *addParams = CreateJson(); + AddStringToJson(addParams, FIELD_GROUP_ID, "BC680ED1137A5731F4A5A90B1AACC4A0A3663F6FC2387B7273EFBCC66A54DC0B"); + AddIntToJson(addParams, FIELD_GROUP_TYPE, PEER_TO_PEER_GROUP); + AddStringToJson(addParams, FIELD_PIN_CODE, "123456"); + AddBoolToJson(addParams, FIELD_IS_ADMIN, true); + char *addParamsStr = PackJsonToString(addParams); + FreeJson(addParams); + g_testGm->addMemberToGroup(CLIENT_REQUEST_ID, TEST_APP_NAME, addParamsStr); + DelayWithMSec(500); + g_testGm->addMemberToGroup(CLIENT_REQUEST_ID, TEST_APP_NAME, addParamsStr); + FreeJsonString(addParamsStr); + DelayWithMSec(500); + EXPECT_EQ(g_messageCode, ON_ERROR); + EXPECT_EQ(g_operationCode, MEMBER_INVITE); +} + +TEST_F(ADD_MEMBER_TO_GROUP, TC_DEV_P2P_BIND_04) +{ + SetClient(true); + g_isNeedContinue = true; + const char * createParamsStr = "{\"groupType\":256,\"deviceId\":\"3C58C27533D8\",\"userType\":0,\"" + "groupVisibility\":-1,\"expireTime\":90,\"groupName\":\"P2PGroup\"}"; + g_testGm->createGroup(TEMP_REQUEST_ID, TEST_APP_NAME, createParamsStr); + /* delay 1 seconds */ + DelayWithMSec(500); + CJson *addParams = CreateJson(); + AddStringToJson(addParams, FIELD_GROUP_ID, "abc"); + AddIntToJson(addParams, FIELD_GROUP_TYPE, PEER_TO_PEER_GROUP); + AddStringToJson(addParams, FIELD_PIN_CODE, "123456"); + AddBoolToJson(addParams, FIELD_IS_ADMIN, true); + char *addParamsStr = PackJsonToString(addParams); + FreeJson(addParams); + g_testGm->addMemberToGroup(CLIENT_REQUEST_ID, TEST_APP_NAME, addParamsStr); + FreeJsonString(addParamsStr); + DelayWithMSec(500); + EXPECT_EQ(g_messageCode, ON_ERROR); + EXPECT_EQ(g_operationCode, MEMBER_INVITE); +} + +TEST_F(ADD_MEMBER_TO_GROUP, TC_DEV_P2P_BIND_05) +{ + SetClient(true); + g_isNeedContinue = true; + const char * createParamsStr = "{\"groupType\":256,\"deviceId\":\"3C58C27533D8\",\"userType\":0,\"" + "groupVisibility\":-1,\"expireTime\":90,\"groupName\":\"P2PGroup\"}"; + g_testGm->createGroup(TEMP_REQUEST_ID, TEST_APP_NAME, createParamsStr); + /* delay 1 seconds */ + DelayWithMSec(500); + CJson *addParams = CreateJson(); + AddStringToJson(addParams, FIELD_GROUP_ID, "BC680ED1137A5731F4A5A90B1AACC4A0A3663F6FC2387B7273EFBCC66A54DC0B"); + AddIntToJson(addParams, FIELD_GROUP_TYPE, PEER_TO_PEER_GROUP); + AddStringToJson(addParams, FIELD_PIN_CODE, "123456"); + AddBoolToJson(addParams, FIELD_IS_ADMIN, true); + char *addParamsStr = PackJsonToString(addParams); + FreeJson(addParams); + int ret = g_testGm->addMemberToGroup(CLIENT_REQUEST_ID, "testApp2", addParamsStr); + FreeJsonString(addParamsStr); + DelayWithMSec(500); + EXPECT_EQ(ret != HC_SUCCESS, true); +} + +TEST_F(ADD_MEMBER_TO_GROUP, TC_DEV_P2P_BIND_06) +{ + SetClient(true); + g_isNeedContinue = true; + const char * createParamsStr = "{\"groupType\":256,\"deviceId\":\"3C58C27533D8\",\"userType\":0,\"" + "groupVisibility\":-1,\"expireTime\":90,\"groupName\":\"P2PGroup\"}"; + g_testGm->createGroup(TEMP_REQUEST_ID, TEST_APP_NAME, createParamsStr); + /* delay 1 seconds */ + DelayWithMSec(500); + CJson *addParams = CreateJson(); + AddStringToJson(addParams, FIELD_GROUP_ID, "BC680ED1137A5731F4A5A90B1AACC4A0A3663F6FC2387B7273EFBCC66A54DC0B"); + AddIntToJson(addParams, FIELD_GROUP_TYPE, PEER_TO_PEER_GROUP); + AddBoolToJson(addParams, FIELD_IS_ADMIN, true); + char *addParamsStr = PackJsonToString(addParams); + FreeJson(addParams); + g_testGm->addMemberToGroup(CLIENT_REQUEST_ID, TEST_APP_NAME, addParamsStr); + FreeJsonString(addParamsStr); + DelayWithMSec(500); + EXPECT_EQ(g_messageCode, ON_ERROR); + EXPECT_EQ(g_operationCode, MEMBER_INVITE); +} + +TEST_F(ADD_MEMBER_TO_GROUP, TC_DEV_P2P_BIND_07) +{ + SetClient(true); + g_isNeedContinue = true; + g_gaCallback.onRequest = OnRequestError1; + const char * createParamsStr = "{\"groupType\":256,\"deviceId\":\"3C58C27533D8\",\"userType\":0,\"" + "groupVisibility\":-1,\"expireTime\":90,\"groupName\":\"P2PGroup\"}"; + g_testGm->createGroup(TEMP_REQUEST_ID, TEST_APP_NAME, createParamsStr); + /* delay 1 seconds */ + DelayWithMSec(500); + CJson *addParams = CreateJson(); + AddStringToJson(addParams, FIELD_GROUP_ID, "BC680ED1137A5731F4A5A90B1AACC4A0A3663F6FC2387B7273EFBCC66A54DC0B"); + AddIntToJson(addParams, FIELD_GROUP_TYPE, PEER_TO_PEER_GROUP); + AddStringToJson(addParams, FIELD_PIN_CODE, "123456"); + AddBoolToJson(addParams, FIELD_IS_ADMIN, true); + char *addParamsStr = PackJsonToString(addParams); + FreeJson(addParams); + g_testGm->addMemberToGroup(CLIENT_REQUEST_ID, TEST_APP_NAME, addParamsStr); + FreeJsonString(addParamsStr); + DelayWithMSec(500); + while (g_isNeedContinue) + { + SetClient(!GetClient()); + CJson *data = CreateJsonFromString(g_dataBuffer); + int64_t req = DEFAULT_REQUEST_ID; + GetInt64FromJson(data, FIELD_REQUEST_ID, &req); + if (req == CLIENT_REQUEST_ID) { + req = SERVER_REQUEST_ID; + } else { + req = CLIENT_REQUEST_ID; + } + AddInt64StringToJson(data, FIELD_REQUEST_ID, req); + char *dataStr = PackJsonToString(data); + FreeJson(data); + memset_s(g_dataBuffer, BUFFER_SIZE, 0, BUFFER_SIZE); + memcpy_s(g_dataBuffer, BUFFER_SIZE, dataStr, strlen(dataStr) + 1); + FreeJsonString(dataStr); + g_testGm->processData(req, (uint8_t *)g_dataBuffer, strlen(g_dataBuffer) + 1); + g_isNeedContinue = false; + DelayWithMSec(500); + } + EXPECT_EQ(g_messageCode, ON_ERROR); + EXPECT_EQ(g_operationCode, MEMBER_INVITE); +} + +TEST_F(ADD_MEMBER_TO_GROUP, TC_DEV_P2P_BIND_08) +{ + SetClient(true); + g_isNeedContinue = true; + g_gaCallback.onRequest = OnRequestError2; + const char * createParamsStr = "{\"groupType\":256,\"deviceId\":\"3C58C27533D8\",\"userType\":0,\"" + "groupVisibility\":-1,\"expireTime\":90,\"groupName\":\"P2PGroup\"}"; + g_testGm->createGroup(TEMP_REQUEST_ID, TEST_APP_NAME, createParamsStr); + /* delay 1 seconds */ + DelayWithMSec(500); + CJson *addParams = CreateJson(); + AddStringToJson(addParams, FIELD_GROUP_ID, "BC680ED1137A5731F4A5A90B1AACC4A0A3663F6FC2387B7273EFBCC66A54DC0B"); + AddIntToJson(addParams, FIELD_GROUP_TYPE, PEER_TO_PEER_GROUP); + AddStringToJson(addParams, FIELD_PIN_CODE, "123456"); + AddBoolToJson(addParams, FIELD_IS_ADMIN, true); + char *addParamsStr = PackJsonToString(addParams); + FreeJson(addParams); + g_testGm->addMemberToGroup(CLIENT_REQUEST_ID, TEST_APP_NAME, addParamsStr); + FreeJsonString(addParamsStr); + DelayWithMSec(500); + while (g_isNeedContinue) + { + SetClient(!GetClient()); + CJson *data = CreateJsonFromString(g_dataBuffer); + int64_t req = DEFAULT_REQUEST_ID; + GetInt64FromJson(data, FIELD_REQUEST_ID, &req); + if (req == CLIENT_REQUEST_ID) { + req = SERVER_REQUEST_ID; + } else { + req = CLIENT_REQUEST_ID; + } + AddInt64StringToJson(data, FIELD_REQUEST_ID, req); + char *dataStr = PackJsonToString(data); + FreeJson(data); + memset_s(g_dataBuffer, BUFFER_SIZE, 0, BUFFER_SIZE); + memcpy_s(g_dataBuffer, BUFFER_SIZE, dataStr, strlen(dataStr) + 1); + FreeJsonString(dataStr); + g_testGm->processData(req, (uint8_t *)g_dataBuffer, strlen(g_dataBuffer) + 1); + g_isNeedContinue = false; + DelayWithMSec(500); + } + EXPECT_EQ(g_messageCode, ON_ERROR); + EXPECT_EQ(g_operationCode, MEMBER_INVITE); +} + +TEST_F(ADD_MEMBER_TO_GROUP, TC_DEV_P2P_BIND_10) +{ + SetClient(true); + g_isNeedContinue = true; + g_gaCallback.onRequest = OnRequestError3; + const char * createParamsStr = "{\"groupType\":256,\"deviceId\":\"3C58C27533D8\",\"userType\":0,\"" + "groupVisibility\":-1,\"expireTime\":90,\"groupName\":\"P2PGroup\"}"; + g_testGm->createGroup(TEMP_REQUEST_ID, TEST_APP_NAME, createParamsStr); + /* delay 1 seconds */ + DelayWithMSec(500); + CJson *addParams = CreateJson(); + AddStringToJson(addParams, FIELD_GROUP_ID, "BC680ED1137A5731F4A5A90B1AACC4A0A3663F6FC2387B7273EFBCC66A54DC0B"); + AddIntToJson(addParams, FIELD_GROUP_TYPE, PEER_TO_PEER_GROUP); + AddStringToJson(addParams, FIELD_PIN_CODE, "123456"); + AddBoolToJson(addParams, FIELD_IS_ADMIN, true); + char *addParamsStr = PackJsonToString(addParams); + FreeJson(addParams); + g_testGm->addMemberToGroup(CLIENT_REQUEST_ID, TEST_APP_NAME, addParamsStr); + FreeJsonString(addParamsStr); + DelayWithMSec(500); + while (g_isNeedContinue) + { + SetClient(!GetClient()); + CJson *data = CreateJsonFromString(g_dataBuffer); + int64_t req = DEFAULT_REQUEST_ID; + GetInt64FromJson(data, FIELD_REQUEST_ID, &req); + if (req == CLIENT_REQUEST_ID) { + req = SERVER_REQUEST_ID; + } else { + req = CLIENT_REQUEST_ID; + } + AddInt64StringToJson(data, FIELD_REQUEST_ID, req); + char *dataStr = PackJsonToString(data); + FreeJson(data); + memset_s(g_dataBuffer, BUFFER_SIZE, 0, BUFFER_SIZE); + memcpy_s(g_dataBuffer, BUFFER_SIZE, dataStr, strlen(dataStr) + 1); + FreeJsonString(dataStr); + g_testGm->processData(req, (uint8_t *)g_dataBuffer, strlen(g_dataBuffer) + 1); + g_isNeedContinue = false; + DelayWithMSec(500); + } + EXPECT_EQ(g_messageCode, ON_ERROR); + EXPECT_EQ(g_operationCode, MEMBER_INVITE); +} + +TEST_F(ADD_MEMBER_TO_GROUP, TC_DEV_P2P_BIND_11) +{ + SetClient(true); + g_isNeedContinue = true; + g_gaCallback.onRequest = OnRequestError4; + const char * createParamsStr = "{\"groupType\":256,\"deviceId\":\"3C58C27533D8\",\"userType\":0,\"" + "groupVisibility\":-1,\"expireTime\":90,\"groupName\":\"P2PGroup\"}"; + g_testGm->createGroup(TEMP_REQUEST_ID, TEST_APP_NAME, createParamsStr); + /* delay 1 second */ + DelayWithMSec(500); + CJson *addParams = CreateJson(); + AddStringToJson(addParams, FIELD_GROUP_ID, "BC680ED1137A5731F4A5A90B1AACC4A0A3663F6FC2387B7273EFBCC66A54DC0B"); + AddIntToJson(addParams, FIELD_GROUP_TYPE, PEER_TO_PEER_GROUP); + AddStringToJson(addParams, FIELD_PIN_CODE, "123456"); + AddBoolToJson(addParams, FIELD_IS_ADMIN, true); + char *addParamsStr = PackJsonToString(addParams); + FreeJson(addParams); + g_testGm->addMemberToGroup(CLIENT_REQUEST_ID, TEST_APP_NAME, addParamsStr); + FreeJsonString(addParamsStr); + DelayWithMSec(500); + while (g_isNeedContinue) + { + SetClient(!GetClient()); + CJson *data = CreateJsonFromString(g_dataBuffer); + int64_t req = DEFAULT_REQUEST_ID; + GetInt64FromJson(data, FIELD_REQUEST_ID, &req); + if (req == CLIENT_REQUEST_ID) { + req = SERVER_REQUEST_ID; + } else { + req = CLIENT_REQUEST_ID; + } + AddInt64StringToJson(data, FIELD_REQUEST_ID, req); + char *dataStr = PackJsonToString(data); + FreeJson(data); + memset_s(g_dataBuffer, BUFFER_SIZE, 0, BUFFER_SIZE); + memcpy_s(g_dataBuffer, BUFFER_SIZE, dataStr, strlen(dataStr) + 1); + FreeJsonString(dataStr); + g_testGm->processData(req, (uint8_t *)g_dataBuffer, strlen(g_dataBuffer) + 1); + g_isNeedContinue = false; + DelayWithMSec(500); + } + EXPECT_EQ(g_messageCode, ON_ERROR); + EXPECT_EQ(g_operationCode, MEMBER_INVITE); +} + +TEST_F(ADD_MEMBER_TO_GROUP, TC_DEV_P2P_BIND_12) +{ + SetClient(true); + g_isNeedContinue = true; + g_gaCallback.onRequest = OnRequestError5; + const char * createParamsStr = "{\"groupType\":256,\"deviceId\":\"3C58C27533D8\",\"userType\":0,\"" + "groupVisibility\":-1,\"expireTime\":90,\"groupName\":\"P2PGroup\"}"; + g_testGm->createGroup(TEMP_REQUEST_ID, TEST_APP_NAME, createParamsStr); + /* delay 1 second */ + DelayWithMSec(500); + CJson *addParams = CreateJson(); + AddStringToJson(addParams, FIELD_GROUP_ID, "BC680ED1137A5731F4A5A90B1AACC4A0A3663F6FC2387B7273EFBCC66A54DC0B"); + AddIntToJson(addParams, FIELD_GROUP_TYPE, PEER_TO_PEER_GROUP); + AddStringToJson(addParams, FIELD_PIN_CODE, "123456"); + AddBoolToJson(addParams, FIELD_IS_ADMIN, true); + char *addParamsStr = PackJsonToString(addParams); + FreeJson(addParams); + g_testGm->addMemberToGroup(CLIENT_REQUEST_ID, TEST_APP_NAME, addParamsStr); + FreeJsonString(addParamsStr); + DelayWithMSec(500); + while (g_isNeedContinue) + { + SetClient(!GetClient()); + CJson *data = CreateJsonFromString(g_dataBuffer); + int64_t req = DEFAULT_REQUEST_ID; + GetInt64FromJson(data, FIELD_REQUEST_ID, &req); + if (req == CLIENT_REQUEST_ID) { + req = SERVER_REQUEST_ID; + } else { + req = CLIENT_REQUEST_ID; + } + AddInt64StringToJson(data, FIELD_REQUEST_ID, req); + char *dataStr = PackJsonToString(data); + FreeJson(data); + memset_s(g_dataBuffer, BUFFER_SIZE, 0, BUFFER_SIZE); + memcpy_s(g_dataBuffer, BUFFER_SIZE, dataStr, strlen(dataStr) + 1); + FreeJsonString(dataStr); + g_testGm->processData(req, (uint8_t *)g_dataBuffer, strlen(g_dataBuffer) + 1); + g_isNeedContinue = false; + DelayWithMSec(500); + } + EXPECT_EQ(g_messageCode, ON_ERROR); + EXPECT_EQ(g_operationCode, MEMBER_INVITE); +} + +static char *ConstructAddParams13() +{ + CJson *addParams = CreateJson(); + AddStringToJson(addParams, FIELD_GROUP_ID, "BC680ED1137A5731F4A5A90B1AACC4A0A3663F6FC2387B7273EFBCC66A54DC0B"); + AddIntToJson(addParams, FIELD_GROUP_TYPE, PEER_TO_PEER_GROUP); + AddStringToJson(addParams, FIELD_PIN_CODE, "123456"); + AddBoolToJson(addParams, FIELD_IS_ADMIN, true); + char *addParamsStr = PackJsonToString(addParams); + FreeJson(addParams); + return addParamsStr; +} + +TEST_F(ADD_MEMBER_TO_GROUP, TC_DEV_P2P_BIND_13) +{ + SetClient(true); + g_isNeedContinue = true; + const char * createParamsStr = "{\"groupType\":256,\"deviceId\":\"3C58C27533D8\",\"userType\":0,\"" + "groupVisibility\":-1,\"expireTime\":90,\"groupName\":\"P2PGroup\"}"; + g_testGm->createGroup(TEMP_REQUEST_ID, TEST_APP_NAME, createParamsStr); + /* delay 1 second */ + DelayWithMSec(500); + DeviceInfo *devAuthParams = CreateDeviceInfoStruct(); + devAuthParams->devType = DEVICE_TYPE_ACCESSORY; + StringSetPointer(&(devAuthParams->authId), "CAF34E13190CBA510AA8DABB70CDFF8E9F623656DED400EF0D4CFD9E88FD6202"); + StringSetPointer(&(devAuthParams->udid), "ABCDEF00ABCDEF00ABCDEF00ABCDEF00ABCDEF00ABCDEF00ABCDEF00ABCDEF00"); + StringSetPointer(&(devAuthParams->groupId), "BC680ED1137A5731F4A5A90B1AACC4A0A3663F6FC2387B7273EFBCC66A54DC0B"); + StringSetPointer(&(devAuthParams->serviceType), "BC680ED1137A5731F4A5A90B1AACC4A0A3663F6FC2387B7273EFBCC66A54DC0B"); + AddTrustedDevice(devAuthParams, NULL); + DestroyDeviceInfoStruct(devAuthParams); + char *addParamsStr = ConstructAddParams13(); + g_testGm->addMemberToGroup(CLIENT_REQUEST_ID, TEST_APP_NAME, addParamsStr); + FreeJsonString(addParamsStr); + DelayWithMSec(500); + while (g_isNeedContinue) + { + SetClient(!GetClient()); + CJson *data = CreateJsonFromString(g_dataBuffer); + int64_t req = DEFAULT_REQUEST_ID; + GetInt64FromJson(data, FIELD_REQUEST_ID, &req); + if (req == CLIENT_REQUEST_ID) { + req = SERVER_REQUEST_ID; + } else { + req = CLIENT_REQUEST_ID; + } + AddInt64StringToJson(data, FIELD_REQUEST_ID, req); + char *dataStr = PackJsonToString(data); + FreeJson(data); + memset_s(g_dataBuffer, BUFFER_SIZE, 0, BUFFER_SIZE); + memcpy_s(g_dataBuffer, BUFFER_SIZE, dataStr, strlen(dataStr) + 1); + FreeJsonString(dataStr); + g_testGm->processData(req, (uint8_t *)g_dataBuffer, strlen(g_dataBuffer) + 1); + g_isNeedContinue = false; + DelayWithMSec(500); + } + g_testGm->processData(CLIENT_REQUEST_ID, (uint8_t *)g_dataBuffer, strlen(g_dataBuffer) + 1); + DelayWithMSec(500); + EXPECT_EQ(g_messageCode, ON_FINISH); + EXPECT_EQ(g_operationCode, MEMBER_INVITE); +} + +TEST_F(REGISTER_LISTENER, TC_LISTENER_01) +{ + DataChangeListener listener; + listener.onGroupCreated = OnGroupCreated; + listener.onGroupDeleted = OnGroupDeleted; + listener.onDeviceBound = OnDeviceBound; + listener.onDeviceUnBound = OnDeviceUnBound; + listener.onDeviceNotTrusted = OnDeviceNotTrusted; + listener.onLastGroupDeleted = OnLastGroupDeleted; + listener.onTrustedDeviceNumChanged = OnTrustedDeviceNumChanged; + int ret = g_testGm->regDataChangeListener(TEST_APP_NAME, &listener); + EXPECT_EQ(ret == HC_SUCCESS, true); +} + +TEST_F(REGISTER_LISTENER, TC_LISTENER_02) +{ + DataChangeListener listener; + listener.onGroupCreated = OnGroupCreated; + listener.onGroupDeleted = OnGroupDeleted; + listener.onDeviceBound = OnDeviceBound; + listener.onDeviceUnBound = OnDeviceUnBound; + listener.onDeviceNotTrusted = OnDeviceNotTrusted; + listener.onLastGroupDeleted = OnLastGroupDeleted; + listener.onTrustedDeviceNumChanged = OnTrustedDeviceNumChanged; + int ret = g_testGm->regDataChangeListener(TEST_APP_NAME, &listener); + EXPECT_EQ(ret == HC_SUCCESS, true); + ret = g_testGm->regDataChangeListener(TEST_APP_NAME, &listener); + EXPECT_EQ(ret == HC_SUCCESS, true); +} + +TEST_F(REGISTER_LISTENER, TC_LISTENER_03) +{ + DataChangeListener listener; + listener.onGroupCreated = OnGroupCreated; + listener.onGroupDeleted = OnGroupDeleted; + listener.onDeviceBound = OnDeviceBound; + listener.onDeviceUnBound = OnDeviceUnBound; + listener.onDeviceNotTrusted = OnDeviceNotTrusted; + listener.onLastGroupDeleted = OnLastGroupDeleted; + listener.onTrustedDeviceNumChanged = OnTrustedDeviceNumChanged; + int ret = g_testGm->regDataChangeListener(TEST_APP_NAME, &listener); + EXPECT_EQ(ret == HC_SUCCESS, true); + ret = g_testGm->unRegDataChangeListener(TEST_APP_NAME); + EXPECT_EQ(ret == HC_SUCCESS, true); +} + +TEST_F(REGISTER_LISTENER, TC_LISTENER_04) +{ + DataChangeListener listener; + listener.onGroupCreated = OnGroupCreated; + listener.onGroupDeleted = OnGroupDeleted; + listener.onDeviceBound = OnDeviceBound; + listener.onDeviceUnBound = OnDeviceUnBound; + listener.onDeviceNotTrusted = OnDeviceNotTrusted; + listener.onLastGroupDeleted = OnLastGroupDeleted; + listener.onTrustedDeviceNumChanged = OnTrustedDeviceNumChanged; + int ret = g_testGm->regDataChangeListener(TEST_APP_NAME, &listener); + EXPECT_EQ(ret == HC_SUCCESS, true); + ret = g_testGm->unRegDataChangeListener(TEST_APP_NAME); + EXPECT_EQ(ret == HC_SUCCESS, true); + ret = g_testGm->unRegDataChangeListener(TEST_APP_NAME); + EXPECT_EQ(ret == HC_SUCCESS, true); +} + +TEST_F(REGISTER_LISTENER, TC_LISTENER_05) +{ + DataChangeListener listener; + listener.onGroupCreated = OnGroupCreated; + listener.onGroupDeleted = OnGroupDeleted; + listener.onDeviceBound = OnDeviceBound; + listener.onDeviceUnBound = OnDeviceUnBound; + listener.onDeviceNotTrusted = OnDeviceNotTrusted; + listener.onLastGroupDeleted = OnLastGroupDeleted; + listener.onTrustedDeviceNumChanged = OnTrustedDeviceNumChanged; + int ret = g_testGm->regDataChangeListener(TEST_APP_NAME, &listener); + EXPECT_EQ(ret == HC_SUCCESS, true); + const char * createParamsStr = "{\"groupType\":256,\"deviceId\":\"3C58C27533D8\",\"userType\":0,\"" + "groupVisibility\":-1,\"expireTime\":90,\"groupName\":\"P2PGroup\"}"; + g_testGm->createGroup(TEMP_REQUEST_ID, TEST_APP_NAME, createParamsStr); + g_testCondition.wait(&g_testCondition); + EXPECT_EQ(g_receivedMessageNum[GROUP_CREATED], 1); +} + +TEST_F(REGISTER_LISTENER, TC_LISTENER_06) +{ + DataChangeListener listener; + listener.onGroupCreated = OnGroupCreated; + listener.onGroupDeleted = OnGroupDeleted; + listener.onDeviceBound = OnDeviceBound; + listener.onDeviceUnBound = OnDeviceUnBound; + listener.onDeviceNotTrusted = OnDeviceNotTrusted; + listener.onLastGroupDeleted = OnLastGroupDeleted; + listener.onTrustedDeviceNumChanged = OnTrustedDeviceNumChanged; + int ret = g_testGm->regDataChangeListener(TEST_APP_NAME, &listener); + EXPECT_EQ(ret == HC_SUCCESS, true); + const char * createParamsStr = "{\"groupType\":256,\"deviceId\":\"3C58C27533D8\",\"userType\":0,\"" + "groupVisibility\":-1,\"expireTime\":90,\"groupName\":\"P2PGroup\"}"; + g_testGm->createGroup(TEMP_REQUEST_ID, TEST_APP_NAME, createParamsStr); + g_testCondition.wait(&g_testCondition); + const char *deleteParamsStr = R"({"groupId": "BC680ED1137A5731F4A5A90B1AACC4A0A3663F6FC2387B7273EFBCC66A54DC0B"})"; + g_testGm->deleteGroup(TEMP_REQUEST_ID, TEST_APP_NAME, deleteParamsStr); + DelayWithMSec(500); + EXPECT_EQ(g_receivedMessageNum[DEVICE_UNBOUND], 1); + EXPECT_EQ(g_receivedMessageNum[LAST_GROUP_DELETED], 1); + EXPECT_EQ(g_receivedMessageNum[TRUSTED_DEVICE_NUM_CHANGED], 3); + EXPECT_EQ(g_receivedMessageNum[DEVICE_NOT_TRUSTED], 1); + EXPECT_EQ(g_receivedMessageNum[GROUP_DELETED], 1); +} + +TEST_F(QUERY_INTERFACE, TC_QUERY_01) +{ + const char * createParamsStr = + "{\"groupType\":256,\"deviceId\":\"3C58C27533D8\",\"userType\":0,\"" + "groupVisibility\":-1,\"expireTime\":90,\"groupName\":\"P2PGroup\"}"; + int ret = g_testGm->createGroup(TEMP_REQUEST_ID, TEST_APP_NAME, createParamsStr); + DelayWithMSec(500); + char *returnDataStr = NULL; + g_testGm->getGroupInfoById(TEST_APP_NAME, + "BC680ED1137A5731F4A5A90B1AACC4A0A3663F6FC2387B7273EFBCC66A54DC0B", &returnDataStr); + CJson *json = CreateJsonFromString(returnDataStr); + const char *groupName = GetStringFromJson(json, FIELD_GROUP_NAME); + ret = strcmp(groupName, "P2PGroup"); + FreeJson(json); + g_testGm->destroyInfo(&returnDataStr); + EXPECT_EQ(ret, 0); +} + +TEST_F(QUERY_INTERFACE, TC_QUERY_02) +{ + const char * createParamsStr = + "{\"groupType\":256,\"deviceId\":\"3C58C27533D8\",\"userType\":0,\"" + "groupVisibility\":-1,\"expireTime\":90,\"groupName\":\"P2PGroup\"}"; + int ret = g_testGm->createGroup(TEMP_REQUEST_ID, TEST_APP_NAME, createParamsStr); + DelayWithMSec(500); + char *returnDataStr = NULL; + ret = g_testGm->getGroupInfoById(TEST_APP_NAME, nullptr, &returnDataStr); + EXPECT_NE(ret, 0); +} + +TEST_F(QUERY_INTERFACE, TC_QUERY_03) +{ + const char * createParamsStr = + "{\"groupType\":256,\"deviceId\":\"3C58C27533D8\",\"userType\":0,\"" + "groupVisibility\":-1,\"expireTime\":90,\"groupName\":\"P2PGroup\"}"; + int ret = g_testGm->createGroup(TEMP_REQUEST_ID, TEST_APP_NAME, createParamsStr); + DelayWithMSec(500); + char *returnDataStr = NULL; + ret = g_testGm->getGroupInfoById(TEST_APP_NAME, "GROUPID", &returnDataStr); + EXPECT_NE(ret, 0); +} + +TEST_F(QUERY_INTERFACE, TC_QUERY_04) +{ + const char * createParamsStr = + "{\"groupType\":256,\"deviceId\":\"3C58C27533D8\",\"userType\":0,\"" + "groupVisibility\":-1,\"expireTime\":90,\"groupName\":\"P2PGroup\"}"; + int ret = g_testGm->createGroup(TEMP_REQUEST_ID, TEST_APP_NAME, createParamsStr); + DelayWithMSec(500); + char *returnDataStr = NULL; + ret = g_testGm->getGroupInfoById("tesstApp2", + "BC680ED1137A5731F4A5A90B1AACC4A0A3663F6FC2387B7273EFBCC66A54DC0B", &returnDataStr); + EXPECT_EQ(ret, 0); +} + diff --git a/test/unittest/deviceauth/source/deviceauth_test_mock.cpp b/test/unittest/deviceauth/source/deviceauth_test_mock.cpp new file mode 100644 index 0000000..d9135cb --- /dev/null +++ b/test/unittest/deviceauth/source/deviceauth_test_mock.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "deviceauth_test_mock.h" +#include +#include "securec.h" + +static bool g_testForClient = false; + +void SetClient(bool tag) +{ + g_testForClient = tag; +} + +bool GetClient() +{ + return g_testForClient; +} + +int32_t HcGetUdid(uint8_t *udid, int32_t udidLen) +{ + const char *clientUdid = "D6350E39AD8F11963C181BEEDC11AC85158E04466B68F1F4E6D895237E0FE81C"; + const char *serverUdid = "ABCDEF00ABCDEF00ABCDEF00ABCDEF00ABCDEF00ABCDEF00ABCDEF00ABCDEF00"; + if (g_testForClient) { + (void)memcpy_s(udid, udidLen - 1, clientUdid, strlen(clientUdid)); + return 0; + } + (void)memcpy_s(udid, udidLen - 1, serverUdid, strlen(serverUdid)); + return 0; +} + +const char *GetStoragePath() +{ + return "/data/data/deviceauth/hcgroup.dat"; +}