diff --git a/bundle.json b/bundle.json index 1abf4373daa2f5d671aac014acd3984ca3d44b4f..f0bcdfccce3c263a992f764dbbadb43d485bc75b 100644 --- a/bundle.json +++ b/bundle.json @@ -59,7 +59,8 @@ "resource_management", "wifi", "screenlock_mgr", - "mbedtls" + "mbedtls", + "zlib" ], "third_party": [] }, diff --git a/common/include/dm_constants.h b/common/include/dm_constants.h index fc275dc0db44c6000261dd25e9cd0608d67e9832..d51e9fca4295eac2b3d7430dda6e2004753c2e26 100755 --- a/common/include/dm_constants.h +++ b/common/include/dm_constants.h @@ -26,6 +26,7 @@ extern const char* TAG_GROUP_ID; extern const char* TAG_GROUP_NAME; extern const char* TAG_REQUEST_ID; extern const char* TAG_DEVICE_ID; +extern const char* TAG_USER_ID; extern const char* TAG_AUTH_TYPE; extern const char* TAG_CRYPTO_SUPPORT; extern const char* TAG_VER; diff --git a/common/include/dm_error_type.h b/common/include/dm_error_type.h index 27fdd4c6e16f9312e71a6d3d949124ab2e3179f0..bd6b6c3598e7b1aedb988f4413c5d7dbfa55779d 100644 --- a/common/include/dm_error_type.h +++ b/common/include/dm_error_type.h @@ -21,6 +21,7 @@ namespace DistributedHardware { enum { DM_OK = 0, SOFTBUS_OK = 0, + DM_AUTHENTICATE_FINISH = 0, STOP_BIND = 1, /* Transfer to the other end device, not define specification error code */ @@ -118,7 +119,10 @@ enum { ERR_DM_WISE_NEED_LOGIN = 96929830, ERR_DM_NAME_EMPTY = 96929831, ERR_DM_HICHAIN_PROOFMISMATCH = 96929832, - ERR_DM_PROCESS_SESSION_KEY_FAILED = 96929833 + ERR_DM_PROCESS_SESSION_KEY_FAILED = 96929833, + ERR_DM_GET_SESSION_KEY_FAILED = 96929834, + ERR_DM_QUADRUPLE_NOT_SAME = 96929835, + ERR_DM_NEXT_STATE_INVALID = 96929836 }; } // namespace DistributedHardware } // namespace OHOS diff --git a/common/src/dm_constants.cpp b/common/src/dm_constants.cpp index 2f91c8ca548b0a9fb73c387c839a143d657829b5..ba1fa49b0e79739496528c11c9eebac96eaa640f 100644 --- a/common/src/dm_constants.cpp +++ b/common/src/dm_constants.cpp @@ -21,6 +21,7 @@ const char* TAG_GROUP_ID = "groupId"; const char* TAG_GROUP_NAME = "GROUPNAME"; const char* TAG_REQUEST_ID = "REQUESTID"; const char* TAG_DEVICE_ID = "DEVICEID"; +const char* TAG_USER_ID = "USERID"; const char* TAG_AUTH_TYPE = "AUTHTYPE"; const char* TAG_CRYPTO_SUPPORT = "CRYPTOSUPPORT"; const char* TAG_VER = "ITF_VER"; diff --git a/commondependency/include/deviceprofile_connector.h b/commondependency/include/deviceprofile_connector.h index 3cff80ef815fbbcf19add3a6c73383952d2a579c..52501ed838bb19463653303d25b1672098d242de 100644 --- a/commondependency/include/deviceprofile_connector.h +++ b/commondependency/include/deviceprofile_connector.h @@ -198,6 +198,7 @@ public: int32_t GetLocalServiceInfoByBundleNameAndPinExchangeType(const std::string &bundleName, int32_t pinExchangeType, DistributedDeviceProfile::LocalServiceInfo &localServiceInfo); int32_t PutSessionKey(const std::vector &sessionKeyArray, int32_t &sessionKeyId); + int32_t DeleteSessionKey(int32_t sessionKeyId); int32_t HandleUserStop(int32_t stopUserId, const std::string &stopEventUdid); int32_t HandleUserStop(int32_t stopUserId, const std::string &localUdid, const std::vector &acceptEventUdids); diff --git a/commondependency/src/deviceprofile_connector.cpp b/commondependency/src/deviceprofile_connector.cpp index 66a809a343eb9bad4588774fa4c9b8662961f28a..4a04307d4b3aa62c558a2d68f5e067546f2489cb 100644 --- a/commondependency/src/deviceprofile_connector.cpp +++ b/commondependency/src/deviceprofile_connector.cpp @@ -1820,6 +1820,17 @@ int32_t DeviceProfileConnector::PutSessionKey(const std::vector & return DM_OK; } +int32_t DeviceProfileConnector::DeleteSessionKey(int32_t sessionKeyId) +{ + uint32_t userId = static_cast(MultipleUserConnector::GetCurrentAccountUserID()); + int32_t ret = DistributedDeviceProfileClient::GetInstance().DeleteSessionKey(userId, sessionKeyId); + if (ret != DM_OK) { + LOGE("failed: %{public}d", ret); + return ret; + } + return DM_OK; +} + bool DeviceProfileConnector::CheckAclStatusNotMatch(const DistributedDeviceProfile::AccessControlProfile &profile, const std::string &localUdid, const std::vector &foregroundUserIds, const std::vector &backgroundUserIds) diff --git a/services/implementation/BUILD.gn b/services/implementation/BUILD.gn index 997f5746af9f56a3f4a1062e0256fb6c9663d208..e4e9c9b02c3d17541b4d1d966d4c912ccb76935a 100644 --- a/services/implementation/BUILD.gn +++ b/services/implementation/BUILD.gn @@ -44,6 +44,7 @@ if (defined(ohos_lite)) { "${utils_path}/include/fwkload/lite", "${utils_path}/include/timer/lite", "//third_party/json/include", + "//third_party/zlib/zlib.h", "${services_path}/include", "${services_path}/include/ipc/lite", "${interfaces_path}/c/ipc/include", @@ -89,6 +90,7 @@ if (defined(ohos_lite)) { "//foundation/systemabilitymgr/safwk_lite:safwk_lite", "//foundation/systemabilitymgr/samgr_lite/samgr:samgr", "//third_party/bounds_checking_function:libsec_shared", + "//third_party/zlib", ] cflags = [ @@ -114,6 +116,7 @@ if (defined(ohos_lite)) { "include/config", "include/adapter", "include/authentication", + "include/authentication_v2", "include/authentication/showconfirm/standard", "include/ability", "include/credential", @@ -180,6 +183,17 @@ if (defined(ohos_lite)) { "src/authentication/auth_ui_state_manager.cpp", "src/authentication/dm_auth_manager.cpp", "src/authentication/showconfirm/standard/show_confirm.cpp", + "src/authentication_v2/auth_stages/auth_acl.cpp", + "src/authentication_v2/auth_stages/auth_confirm.cpp", + "src/authentication_v2/auth_stages/auth_credential.cpp", + "src/authentication_v2/auth_stages/auth_negotiate.cpp", + "src/authentication_v2/auth_stages/auth_pin_auth.cpp", + "src/authentication_v2/auth_manager.cpp", + "src/authentication_v2/dm_auth_message_processor.cpp", + "src/authentication_v2/dm_auth_state_machine.cpp", + "src/authentication_v2/dm_auth_state.cpp", + "src/authentication_v2/dm_auth_context.cpp", + "src/authentication_v2/dm_auth_manager_base.cpp", "src/config/dm_config_manager.cpp", "src/credential/dm_credential_manager.cpp", "src/cryptomgr/crypto_mgr.cpp", @@ -235,8 +249,10 @@ if (defined(ohos_lite)) { "mbedtls:mbedtls_shared", "openssl:libcrypto_shared", "os_account:libaccountkits", + "os_account:os_account_innerkits", "resource_management:resmgr_napi_core", "samgr:samgr_proxy", + "zlib:shared_libz", ] if (support_screenlock && device_manager_feature_product == "default") { diff --git a/services/implementation/include/authentication/dm_auth_manager.h b/services/implementation/include/authentication/dm_auth_manager.h index dc03c567c38f55f3b7fcb5a0e25eed1778305371..2db8af888d8ccfd41c2649d11d118c33e72ce272 100644 --- a/services/implementation/include/authentication/dm_auth_manager.h +++ b/services/implementation/include/authentication/dm_auth_manager.h @@ -28,6 +28,7 @@ #include "deviceprofile_connector.h" #include "dm_ability_manager.h" #include "dm_adapter_manager.h" +#include "dm_auth_manager_base.h" #include "dm_constants.h" #include "dm_device_info.h" #include "dm_timer.h" @@ -203,9 +204,7 @@ typedef struct DmAuthResponseContext { class AuthMessageProcessor; -class DmAuthManager final : public ISoftbusSessionCallback, - public IHiChainConnectorCallback, - public IDmDeviceAuthCallback, +class DmAuthManager final : public AuthManagerBase, public std::enable_shared_from_this { public: DmAuthManager(std::shared_ptr softbusConnector, @@ -538,6 +537,7 @@ public: void AuthDeviceError(int64_t requestId, int32_t errorCode); void GetRemoteDeviceId(std::string &deviceId); void AuthDeviceSessionKey(int64_t requestId, const uint8_t *sessionKey, uint32_t sessionKeyLen); + char *AuthDeviceRequest(int64_t requestId, int operationCode, const char *reqParams); int32_t GetSessionKeyIdSync(int64_t requestId); void OnAuthDeviceDataReceived(const int32_t sessionId, const std::string message); void OnScreenLocked(); @@ -569,8 +569,6 @@ private: void SrcAuthenticateFinish(); std::string GetBundleLable(const std::string &bundleName); bool IsScreenLocked(); - std::string ConvertSrcVersion(const std::string &version, const std::string &edition); - std::string ConvertSinkVersion(const std::string &version); void NegotiateRespMsg(const std::string &version); void SetAuthType(int32_t authType); int32_t GetTaskTimeout(const char* taskName, int32_t taskTimeOut); diff --git a/services/implementation/include/authentication_v2/auth_manager.h b/services/implementation/include/authentication_v2/auth_manager.h new file mode 100644 index 0000000000000000000000000000000000000000..a43453db6e77eb96b38d41b10dc360ad49999e3d --- /dev/null +++ b/services/implementation/include/authentication_v2/auth_manager.h @@ -0,0 +1,235 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 OHOS_DM_AUTH_MANAGER_V2_H +#define OHOS_DM_AUTH_MANAGER_V2_H + +#include +#include "hichain_auth_connector.h" +#include "hichain_connector.h" +#include "softbus_connector.h" +#include "softbus_session.h" +#include "auth_ui_state_manager.h" +#include "dm_auth_manager_base.h" + +namespace OHOS { +namespace DistributedHardware { +struct DmAuthContext; + +const int32_t DM_AUTH_TYPE_MAX = 5; +const int32_t DM_AUTH_TYPE_MIN = 0; +const int32_t MIN_PIN_TOKEN = 10000000; +const int32_t MAX_PIN_TOKEN = 90000000; +const int32_t NEGOTIATE_TIMEOUT = 10; +const int32_t WAIT_REQUEST_TIMEOUT = 10; +const int32_t WAIT_NEGOTIATE_TIMEOUT = 10; +const int32_t HML_SESSION_TIMEOUT = 10; +const int32_t AUTHENTICATE_TIMEOUT = 120; +constexpr const char* DM_VERSION_5_0_1 = "5.0.1"; +constexpr const char* DM_VERSION_5_0_9 = "5.0.9"; // 预估的旧版本最高版本号 +constexpr const char* BUNDLE_NAME_KEY = "bundleName"; + +// 取自security_device_auth中的identity_operation.h,该头文件为内部头文件,不能直接引用 +// 若冲突删除此处 +enum { + ACCOUNT_RELATED = 1, + ACCOUNT_UNRELATED, + ACCOUNT_ACROSS +}; + +// 取自security_device_auth中的identity_operation.h,该头文件为内部头文件,不能直接引用 +// 若冲突删除此处 +enum { + SCOPE_DEVICE = 1, + SCOPE_USER, + SCOPE_APP, +}; + +class AuthManager : public AuthManagerBase, + public std::enable_shared_from_this { +public: + AuthManager(std::shared_ptr softbusConnector, + std::shared_ptr listener, + std::shared_ptr hiChainAuthConnector); + virtual ~AuthManager() = default; + + // 对外API 实现 begin + virtual int32_t OnUserOperation(int32_t action, const std::string ¶ms) = 0; + void OnScreenLocked(); + /** + * @tc.name: AuthManager::GeneratePincode + * @tc.desc: Generate Pincode of the DeviceManager Authenticate Manager + * @tc.type: FUNC + */ + int32_t BindTarget(const std::string &sessionName, const PeerTargetId &targetId, + const std::map &bindParam); + // 停止绑定 TODO 如果多会话实例隔离后,pkgName 是不是不需要了? 后续其他API同理? + int32_t StopAuthenticateDevice(const std::string &sessionName); + + /** + * @tc.name: AuthManager::OnUserOperation + * @tc.desc: User Operation of the DeviceManager Authenticate Manager + * @tc.type: FUNC + */ + int32_t GeneratePincode(); + /** + * @tc.name: AuthManager::ImportAuthCode + * @tc.desc: Import auth code + * @tc.type: FUNC + */ + // todo 新协议是通过DP去查询的? + int32_t ImportAuthCode(const std::string &sessionName, const std::string &authCode); + /** + * @tc.name: AuthManager::RegisterUiStateCallback + * @tc.desc: Register ui state callback + * @tc.type: FUNC + */ + int32_t RegisterUiStateCallback(const std::string sessionName); + + /** + * @tc.name: AuthManager::UnRegisterUiStateCallback + * @tc.desc: Unregister ui state callback + * @tc.type: FUNC + */ + int32_t UnRegisterUiStateCallback(const std::string sessionName); + + /** + * @tc.name: AuthManager::UnAuthenticateDevice + * @tc.desc: UnAuthenticate Device of the DeviceManager Authenticate Manager + * @tc.type: FUNC + */ + int32_t UnAuthenticateDevice(const std::string &sessionName, const std::string &udid, int32_t bindLevel); + + /** + * @brief UnBind device. + * @param sessionName package name. + * @param deviceId device id. + * @return Return 0 if success. + */ + int32_t UnBindDevice(const std::string &sessionName, const std::string &udid, + int32_t bindLevel, const std::string &extra); + + void HandleDeviceNotTrust(const std::string &udid); + int32_t DeleteGroup(const std::string &sessionName, const std::string &deviceId); + + int32_t RegisterAuthenticationType(int32_t authenticationType); + // 对外API 实现 end + + // AuthManager 内部使用的接口 begin + void SetAuthContext(std::shared_ptr context); + std::shared_ptr GetAuthContext(); + static bool IsHmlSessionType(std::string sessionType); + int32_t GetTokenIdByBundleName(int32_t userId, std::string &bundleName, int64_t &tokenId); + void GetBindTargetParams(std::string &pkgName, PeerTargetId &targetId, + std::map &bindParam); + int32_t GetReason(); + + // 提取本端ACL 用于消息解析和总线使用 无ACL会返回空字符串 json格式字符串:{dmversion:x,accesser:[{accesserDeviceId:y,...},...],accessee:{...}} + int32_t GetAclListStr(std::string &aclList); + +protected: + // 上下文(需在该层级进行创建) + std::shared_ptr context_; + std::shared_ptr authUiStateMgr_; + std::map bindParam_; + + // IDmDeviceAuthCallback 转内部接口 + // pkgName是#define DM_APP_ID "ohos.distributedhardware.devicemanager" + // int32_t GetPinCode(std::string &sessionName, int32_t &code); + int32_t GetPinCode(int32_t &code); + void GetRemoteDeviceId(std::string &deviceId); + // IDmDeviceAuthCallback 转内部接口 +private: + int32_t ParseAuthType(const std::map &bindParam, int32_t &authType); + int32_t ParseConnectAddr(const PeerTargetId &targetId, std::string &deviceId, std::string &addrType); + void ParseHmlInfoInJsonObject(nlohmann::json jsonObject); + void ParseJsonObject(nlohmann::json jsonObject); + void GetAuthParam(const std::string &sessionName, int32_t authType, + const std::string &deviceId, const std::string &extra); + std::string GetBundleName(nlohmann::json &jsonObject); + int32_t GetBindLevel(int32_t bindLevel); + void SetAuthType(int32_t authType); + bool IsAuthTypeSupported(const int32_t &authType); + bool IsAuthCodeReady(const std::string &sessionName); + int32_t CheckAuthParamVaild(const std::string &sessionName, int32_t authType, + const std::string &deviceId, const std::string &extra); + void InitAuthState(const std::string &sessionName, int32_t authType, + const std::string &deviceId, const std::string &extra); + int32_t AuthenticateDevice(const std::string &sessionName, int32_t authType, + const std::string &deviceId, const std::string &extra); +}; + +class AuthSrcManager : public AuthManager { +public: + AuthSrcManager(std::shared_ptr softbusConnector, + std::shared_ptr listener, + std::shared_ptr hiChainAuthConnector); + virtual ~AuthSrcManager() override = default; + + // 对外API 实现 begin + int32_t OnUserOperation(int32_t action, const std::string ¶ms) override; + // 对外API 实现 end + + // IDmDeviceAuthCallback implement begin + bool AuthDeviceTransmit(int64_t requestId, const uint8_t *data, uint32_t dataLen) override; + void AuthDeviceError(int64_t requestId, int32_t errorCode) override; + void AuthDeviceFinish(int64_t requestId) override; + void AuthDeviceSessionKey(int64_t requestId, const uint8_t *sessionKey, uint32_t sessionKeyLen) override; + char *AuthDeviceRequest(int64_t requestId, int operationCode, const char *reqParams) override; + // IDmDeviceAuthCallback implement end + + // ISoftbusSessionCallback implement begin + void OnSessionOpened(int32_t sessionId, int32_t sessionSide, int32_t result) override; + void OnSessionClosed(int32_t sessionId) override; + void OnDataReceived(int32_t sessionId, std::string message) override; + + // 下面2个接口还需要实现吗? + bool GetIsCryptoSupport() override; + // 与 OnDataReceived 合并实现 + void OnAuthDeviceDataReceived(int32_t sessionId, std::string message) override; + // ISoftbusSessionCallback implement end +}; + +class AuthSinkManager : public AuthManager { +public: + AuthSinkManager(std::shared_ptr softbusConnector, + std::shared_ptr listener, + std::shared_ptr hiChainAuthConnector); + virtual ~AuthSinkManager() override = default; + + // 对外API 实现 begin + int32_t OnUserOperation(int32_t action, const std::string ¶ms) override; + // 对外API 实现 end + + // IDmDeviceAuthCallback implement begin + bool AuthDeviceTransmit(int64_t requestId, const uint8_t *data, uint32_t dataLen) override; + void AuthDeviceError(int64_t requestId, int32_t errorCode) override; + void AuthDeviceFinish(int64_t requestId) override; + void AuthDeviceSessionKey(int64_t requestId, const uint8_t *sessionKey, uint32_t sessionKeyLen) override; + char *AuthDeviceRequest(int64_t requestId, int operationCode, const char *reqParams) override; + // IDmDeviceAuthCallback implement end + + // ISoftbusSessionCallback implement begin + void OnSessionOpened(int32_t sessionId, int32_t sessionSide, int32_t result) override; + void OnSessionClosed(int32_t sessionId) override; + void OnDataReceived(int32_t sessionId, std::string message) override; + bool GetIsCryptoSupport() override; + void OnAuthDeviceDataReceived(int32_t sessionId, std::string message) override; + // ISoftbusSessionCallback implement end +}; + +} // namespace DistributedHardware +} // namespace OHOS +#endif // OHOS_DM_AUTH_MANAGER_V2_H \ No newline at end of file diff --git a/services/implementation/include/authentication_v2/dm_auth_context.h b/services/implementation/include/authentication_v2/dm_auth_context.h new file mode 100644 index 0000000000000000000000000000000000000000..7263362a23e049586859fbecdca9350f2de379a2 --- /dev/null +++ b/services/implementation/include/authentication_v2/dm_auth_context.h @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 OHOS_DM_AUTH_CONTEXT_V2_H +#define OHOS_DM_AUTH_CONTEXT_V2_H + +#include +#include + +#include "nlohmann/json.hpp" +#include "auth_ui_state_manager.h" +#include "hichain_auth_connector.h" +#include "hichain_connector.h" +#include "softbus_connector.h" +#include "softbus_session.h" +#include "authentication.h" + +#include "dm_timer.h" +#include "dm_auth_message_processor.h" +#include "dm_device_info.h" +#include "dm_ability_manager.h" +#include "dm_log.h" +#include "dm_anonymous.h" +#include "dm_constants.h" + +namespace OHOS { +namespace DistributedHardware { + +class DmAuthStateMachine; +class DmAuthMessageProcessor; + +// PIN码认证类型 +enum DmAuthType : int32_t { + AUTH_TYPE_CRE = 0, // 新协议未使用 + AUTH_TYPE_PIN, // 输入PIN码 + AUTH_TYPE_QR_CODE, // 新协议未使用 + AUTH_TYPE_NFC, // 新协议未使用 + AUTH_TYPE_NO_INTER_ACTION, // 新协议未使用 + AUTH_TYPE_IMPORT_AUTH_CODE, // 导入PIN码 + AUTH_TYPE_UNKNOW, // 新协议未使用 + AUTH_TYPE_PIN_ULTRASONIC, // 超声PIN码 +}; + +enum DmAuthDirection { + DM_AUTH_SOURCE = 0, + DM_AUTH_SINK, +}; + +enum DmBindType { + DM_AUTH_USERID = 1, + DM_AUTH_SYSTEM_SERVICE, + DM_AUTH_APP_SERVICE, + DM_AUTH_DEVICEID, +}; + +// 本端/远端 +enum DmAuthSide { + DM_AUTH_LOCAL_SIDE = 0, // 本端 + DM_AUTH_REMOTE_SIDE, // 远端 +}; + +// 凭据或公钥级别 authorizedScope +enum DmAuthScope { + DM_AUTH_SCOPE_DEVICE = 1, // 设备级凭据 + DM_AUTH_SCOPE_USER, // 用户级凭据 + DM_AUTH_SCOPE_APP, // 应用级凭据 +}; + +struct DmPeerTargetAddress { + std::string peerBrMacAddress; //一碰投使用,直接可以蓝牙建链 + std::string peerBleMacAddress; //一碰投使用,直接可以蓝牙建链 + std::string peerWifiMacAddress; //一碰投使用,直接可以蓝牙建链 + std::string peerActionMacAddress; //一碰投使用,直接可以蓝牙建链 + std::string peerWifiChannel; //一碰投使用 + std::string peerWifiIp; //一碰投使用 + uint16_t peerWifiPort; //一碰投使用 +}; + +struct DmPeerTarget { + DmBindType peerType; // 绑定目标的类型 + std::string peerDeivceId; // 兼容性,UDID,哈希值,PUBLIC权限 + int64_t peerServiceId; // Serviceid,主推,PUBLIC权限 + uint64_t peerSaTokenId; // SA-TokenID,过度,SA使用,校验系统权限 + std::string peerBundleName; //过度,同厂商使用,PUBLIC权限 + DmPeerTargetAddress peerTargetAddress; //通信对象的物理地址,校验系统权限 +}; + +struct DmAccess { + std::string deviceName; + int32_t deviceType; // PC、mobile、手表、大屏等类型,为业务透传的数据,无需自定义 + std::string deviceId; // A->B, 无论是A端还是B端,Accesser对象都存A端的deviceId,Accessee对象都存B端的deviceId + std::string deviceIdHash; + std::string addr; + int32_t userId; + std::string userIdHash; + int32_t displayId = 0; // 逻辑屏幕id + std::string accountId; + std::string accountIdHash; + uint64_t tokenId; + std::string tokenIdHash; + std::string token; + std::string networkId; + std::string bundleName; // 存PacketName + int64_t serviceId; // 保留字段,后续会使用 + std::string accesserHapSignature; + int32_t bindLevel; // 为业务透传数据,无需自定义 + std::string userCredentialId; // 用户级凭据Id + std::string appCredentialId; // 应用级凭据Id + std::string userPublicKey; // 用户级公钥 + std::string appPublicKey; // 应用级公钥 + std::vector bindType; // 绑定类型,如DM_IDENTICAL_ACCOUNT、DM_ACROSS_ACCOUNT、DM_POINT_TO_POINT + std::string publicKey; // T公钥长度 + int32_t credentialId; // 应用凭据ID + int32_t status; // 表示服务为前台还是后台,业务透传,只保存 + int32_t sessionKeyId; // 作为秘钥派送的材料,在总线中取出sk + int32_t appSessionKeyId; // 本端永久应用SKID,由DP返回用于ACL的更新、老化 + int32_t userSessionKeyId; // 本端永久用户SKID,由DP返回用于ACL的更新、老化 + int64_t appSkTimeStamp; // 老化,时间为2天 应用级凭据时间戳 + int64_t userSkTimeStamp; // 老化,时间为2天 用户级凭据时间戳 + int64_t skTimeStamp; // 老化,时间为2天 + bool isAuthed; + bool isOnline; + std::string dmVersion; // 版本 5.1.0 + std::string edition; // 用于5.1.0版本前的兼容,协助版本协商 + std::string aclList; //可信关系列表,用于数据老化 KV格式 + std::vector aclChecksumList; // 可信关系列表,用于数据老化 + std::string credentialInfos; //凭据信息(点对点,同账号,..) 只保存凭据类型 kv结构 + std::string extraInfo; //可扩展字段,kv结构 +}; + +// TODO 统一用初始化列表进行初始化 +struct DmAuthContext { + bool isOnline; // 是否上线 + DmMessageType msgType; // 报文类型,枚举MsgType + int32_t sessionId; // 总线传输会话ID + int64_t requestId; // hichain认证ID + int32_t authBoxType{1}; // 认证框类型 + UiAction pinInputResult; // 输入PIN码结果 + UiAction authResult{UiAction::USER_OPERATION_TYPE_ALLOW_AUTH}; // 授权结果(使用0、1、6,即单次,取消和始终信任,enum UiAction) + DmAuthType authType{DmAuthType::AUTH_TYPE_PIN}; // 认证方式,弹pin码、超声pin码、导入pin码 + std::vector authTypeList; // 共有认证方式列表 + uint32_t currentAuthTypeIdx{0}; // 认证方式索引 + int32_t inputPinAuthFailTimes{0}; // 输入PIN认证失败次数,超过3次则失败 + int32_t pinCode{INVALID_PINCODE}; // 生成的PIN码 + int32_t connDelayCloseTime; // 链路延迟释放时间, 授权结束后不自动断链(有业务需要使用)保留字段 + int32_t reason{DM_OK}; // 本端失败的原因 + int32_t reply; // 对端回复的结果 引用common/include/dm_constants.h,有新的错误码可新增 + int32_t state; // 结束的状态 + int32_t appSessionKeyId; // 本端永久应用SKID,由DP返回用于ACL的更新、老化 + int32_t userSessionKeyId; // 本端永久用户SKID,由DP返回用于ACL的更新、老化 + int64_t appSkTimeStamp; // 老化,时间为2天 应用级凭据时间戳 + int64_t userSkTimeStamp; // 老化,时间为2天 用户级凭据时间戳 + int32_t hmlActionId = 0; + bool normalFinishAuth; // 标识认证过程是否正常结束 + bool authenticating; // 标识正在认证中 + bool isAppCredentialVerified = false; // 应用凭据是否认证 + bool hmlEnable160M = false; + std::string sessionName; // 业务传入的标识,业务自定义,有被仿冒的风险 + std::string pkgLabel; + std::string importCodeBundleName; // 导入pin码的包名,从系统中读取,与acceserBundleName一致 + std::string appThumbnail; // 应用图标 + std::string appOperation; // 授权弹框中显示本次绑定用于什么操作 + std::string customData; // 业务自定义字段,详细提示用户本次绑定的操作 + std::string connSessionType; + std::string extraInfo; // 可扩展字段,kv结构 + DmAuthDirection direction; // 标识认证方向 + ProcessInfo processInfo; // 进程信息 + DmPeerTarget peerTarget; // 对端目标的信息 + DmAccess accesser; + DmAccess accessee; + DmAccess encryAccesser; // 密文阶段accesser + DmAccess encryAccessee; // 密文阶段accessee + std::multimap proxy; // 前面是accesser,后面是accessee + + std::shared_ptr authStateMachine; // 状态机 + std::shared_ptr authUiStateMgr; + std::shared_ptr hiChainAuthConnector; // HiChain交互接口 + std::shared_ptr authMessageProcessor; // 报文处理接口 + std::shared_ptr softbusConnector; // 软总线接口 + std::shared_ptr listener; + std::shared_ptr authPtr; + std::shared_ptr timer; + std::string transmitData; // 保存 onTrasmit返回数据 + std::string importSessionName = ""; + std::string importAuthCode = ""; + std::map> authenticationMap; + PeerTargetId peerTargetId; + bool pinNegotiateStarted{false}; // pin协商是否已开始 + bool isAuthenticateDevice = false; + + // 获取设备ID + std::string GetDeviceId(DmAuthSide side); + // 获取用户ID + int32_t GetUserId(DmAuthSide side); + // 获取凭据ID + std::string GetCredentialId(DmAuthSide side, DmAuthScope authorizedScope); + // 获取公钥 + std::string GetPublicKey(DmAuthSide side, DmAuthScope authorizedScope); + // 设置凭据ID + int32_t SetCredentialId(DmAuthSide side, DmAuthScope authorizedScope, const std::string &credentialId); + // 设置公钥 + int32_t SetPublicKey(DmAuthSide side, DmAuthScope authorizedScope, const std::string &publicKey); + // 获取账号ID + std::string GetAccountId(DmAuthSide side); +}; + +} // namespace DistributedHardware +} // namespace OHOS +#endif // OHOS_DM_AUTH_CONTEXT_V2_H diff --git a/services/implementation/include/authentication_v2/dm_auth_manager_base.h b/services/implementation/include/authentication_v2/dm_auth_manager_base.h new file mode 100644 index 0000000000000000000000000000000000000000..32184d20575a8264af46ac9f12f80189b349038a --- /dev/null +++ b/services/implementation/include/authentication_v2/dm_auth_manager_base.h @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 OHOS_DM_AUTH_ADAPTER_V2_H +#define OHOS_DM_AUTH_ADAPTER_V2_H + +#include +#include +#include +#include + +#include "softbus_session_callback.h" +#include "hichain_connector_callback.h" +#include "hichain_connector_callback.h" +#include "auth_request_state.h" +#include "auth_response_state.h" +#include "dm_device_info.h" + +namespace OHOS { +namespace DistributedHardware { + +// device_manager_service_impl.cpp需要此定义,所以放在此处 +constexpr const char *DM_TAG_DMVERSION = "dmVersion"; +constexpr const char *DM_TAG_EDITION = "edition"; +constexpr const char* DM_VERSION_4_1_5_1 = "4.1.5.1"; +constexpr const char* DM_VERSION_5_1_0 = "5.1.0"; + +class AuthManagerBase : public ISoftbusSessionCallback, + public IHiChainConnectorCallback, + public IDmDeviceAuthCallback { +public: + virtual int32_t AuthenticateDevice(const std::string &pkgName, int32_t authType, const std::string &deviceId, + const std::string &extra); + + virtual int32_t UnAuthenticateDevice(const std::string &pkgName, const std::string &udid, int32_t bindLevel); + + virtual int32_t UnBindDevice(const std::string &pkgName, const std::string &udid, + int32_t bindLevel, const std::string &extra); + + virtual void OnSessionOpened(int32_t sessionId, int32_t sessionSide, int32_t result); + + virtual void OnSessionClosed(const int32_t sessionId); + + virtual void OnDataReceived(const int32_t sessionId, const std::string message); + + virtual void OnGroupCreated(int64_t requestId, const std::string &groupId); + + virtual void OnMemberJoin(int64_t requestId, int32_t status); + + virtual int32_t EstablishAuthChannel(const std::string &deviceId); + + virtual void StartNegotiate(const int32_t &sessionId); + + virtual void RespNegotiate(const int32_t &sessionId); + + virtual void SendAuthRequest(const int32_t &sessionId); + + virtual int32_t StartAuthProcess(const int32_t &action); + + virtual void StartRespAuthProcess(); + + virtual int32_t CreateGroup(); + + virtual int32_t ProcessPincode(int32_t pinCode); + + virtual std::string GetConnectAddr(std::string deviceId); + + virtual int32_t JoinNetwork(); + + virtual void AuthenticateFinish(); + + virtual bool GetIsCryptoSupport(); + + virtual int32_t SetAuthRequestState(std::shared_ptr authRequestState); + + virtual int32_t SetAuthResponseState(std::shared_ptr authResponseState); + + virtual int32_t GetPinCode(int32_t &code); + + virtual std::string GenerateGroupName(); + + virtual void HandleAuthenticateTimeout(std::string name); + + virtual int32_t GeneratePincode(); + + virtual void ShowConfigDialog(); + + virtual void ShowAuthInfoDialog(bool authDeviceError = false); + + virtual void ShowStartAuthDialog(); + + virtual int32_t OnUserOperation(int32_t action, const std::string ¶ms); + + virtual int32_t SetPageId(int32_t pageId); + + virtual int32_t SetReasonAndFinish(int32_t reason, int32_t state); + + virtual bool IsIdenticalAccount(); + + virtual int32_t RegisterUiStateCallback(const std::string pkgName); + + virtual int32_t UnRegisterUiStateCallback(const std::string pkgName); + + virtual int32_t ImportAuthCode(const std::string &pkgName, const std::string &authCode); + + virtual int32_t BindTarget(const std::string &pkgName, const PeerTargetId &targetId, + const std::map &bindParam); + + virtual int32_t RegisterAuthenticationType(int32_t authenticationType); + + virtual int32_t StopAuthenticateDevice(const std::string &pkgName); + + virtual void OnScreenLocked() = 0; + + virtual void HandleDeviceNotTrust(const std::string &udid) = 0; + + virtual int32_t DeleteGroup(const std::string &pkgName, const std::string &deviceId) = 0; + + // 5.1.0版本新增接口 + virtual int32_t GetReason(); + // 新协议切换到老协议时,需要获取之前的Params,以供老协议使用 + virtual void GetBindTargetParams(std::string &pkgName, PeerTargetId &targetId, + std::map &bindParam); + + // 公共函数 + static std::string ConvertSrcVersion(const std::string &version, const std::string &edition); + static std::string ConvertSinkVersion(const std::string &version); + + // 公共变量 + bool isAuthNewVersion_ = true; +}; + +} // namespace DistributedHardware +} // namespace OHOS +#endif // OHOS_DM_AUTH_ADAPTER_V2_H diff --git a/services/implementation/include/authentication_v2/dm_auth_message_processor.h b/services/implementation/include/authentication_v2/dm_auth_message_processor.h new file mode 100644 index 0000000000000000000000000000000000000000..640494ff16da93c2e44e4eb84275c7ce01911c8c --- /dev/null +++ b/services/implementation/include/authentication_v2/dm_auth_message_processor.h @@ -0,0 +1,303 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 OHOS_DM_AUTH_MESSAGE_PROCESSOR_V2_H +#define OHOS_DM_AUTH_MESSAGE_PROCESSOR_V2_H + +#include +#include "nlohmann/json.hpp" +#include "crypto_mgr.h" +#include "access_control_profile.h" +#include "deviceprofile_connector.h" + +namespace OHOS { +namespace DistributedHardware { +struct DmAuthContext; +struct DmAccess; + +constexpr const char *DM_TAG_MSG_TYPE = "messageType"; // 报文类型 +constexpr const char *DM_TAG_DATA = "data"; // 报文数据 +constexpr const char* DM_TAG_DATA_LEN = "dataLen"; +constexpr const char *DM_TAG_USER_PUBLICK_KEY = "userPublicKey"; // 用户级公钥 userPublicKey +constexpr const char *DM_TAG_APP_PUBLICK_KEY = "appPublicKey"; // 应用级公钥 appPublicKey +constexpr const char *DM_TAG_USER_CREDENTIAL_ID = "userCredentialId"; // 用户级凭据Id +constexpr const char *DM_TAG_APP_CREDENTIAL_ID = "appCredentialId"; // 应用级凭据Id +constexpr const char *DM_TAG_AUTH_RESULT = "authResult"; // 授权结果 +constexpr const char *DM_TAG_AUTH_TYPE_LIST = "authTypeList"; // 授权类型列表 +constexpr const char *DM_TAG_CURRENT_AUTH_TYPE_IDX = "currentAuthTypeIdx"; // 当前授权类型索引 + +// is接口入参 json格式字符串中的key +constexpr const char *DM_TAG_METHOD = "method"; +constexpr const char *DM_TAG_DEVICE_ID = "deviceId"; +constexpr const char *DM_TAG_PEER_USER_SPACE_ID = "peerUserSpaceId"; +constexpr const char *DM_TAG_SUBJECT = "subject"; +constexpr const char *DM_TAG_CRED_TYPE = "credType"; +constexpr const char *DM_TAG_KEY_FORMAT = "keyFormat"; +constexpr const char *DM_TAG_ALGORITHM_TYPE = "algorithmType"; +constexpr const char *DM_TAG_PROOF_TYPE = "proofType"; +constexpr const char *DM_TAG_KEY_VALUE = "keyValue"; +constexpr const char *DM_TAG_AUTHORIZED_SCOPE = "authorizedScope"; +constexpr const char *DM_TAG_AUTHRIZED_APP_LIST = "authorizedAppList"; +constexpr const char *DM_TAG_CREDENTIAL_OWNER = "credOwner"; +constexpr const char *DM_AUTH_CREDENTIAL_OWNER = "DM"; // 凭据拥有者 +constexpr const char *DM_TAG_SYNC = "syncMessage"; +constexpr const char *DM_TAG_ACCESS = "dmAccess"; +constexpr const char *DM_TAG_PROXY = "proxy"; +constexpr const char *DM_TAG_ACL = "accessControlTable"; +constexpr const char *DM_TAG_ACCESSER = "dmAccesser"; +constexpr const char *DM_TAG_ACCESSEE = "dmAccessee"; +constexpr const char *DM_TAG_SERVICEINFO = "serviceInfo"; +constexpr const char *DM_TAG_APP_SK_ID = "accessAppSKId"; // 本端sk信息 同步给对端 用于构造acl-accesser/accessee +constexpr const char *DM_TAG_USER_SK_ID = "accessUserSKId"; +constexpr const char *DM_TAG_APP_SK_TIMESTAMP = "accessAppSKTimeStamp"; +constexpr const char *DM_TAG_USER_SK_TIMESTAMP = "accessUserSKTimeStamp"; +constexpr const char *DM_TAG_USER_ID = "userId"; +constexpr const char* DM_TAG_TOKEN_ID = "tokenId"; +constexpr const char *DM_TAG_ISSUER = "issuer"; + +constexpr const char* APP_OPERATION_KEY = "appOperation"; +constexpr const char* APP_THUMBNAIL = "appThumbnail"; +constexpr const char* CUSTOM_DESCRIPTION_KEY = "customDescription"; +constexpr const char* TAG_DEVICE_VERSION = "deviceVersion"; +constexpr const char* TAG_DEVICE_NAME = "deviceName"; +constexpr const char* TAG_DEVICE_ID_HASH = "deviceIdHash"; +constexpr const char* TAG_USER_ID_HASH = "userIdHash"; +constexpr const char* TAG_ACCOUNT_ID_HASH = "accountIdHash"; +constexpr const char* TAG_TOKEN_ID_HASH = "tokenIdHash"; +constexpr const char* TAG_BUNDLE_NAME = "bundleName"; +constexpr const char* TAG_PEER_BUNDLE_NAME = "peerBundleName"; +constexpr const char* TAG_BIND_LEVEL = "bindLevel"; +constexpr const char* TAG_SESSION_NAME = "sessionName"; +constexpr const char *DM_TAG_ACL_CHECKSUM = "aclCheckSum"; +constexpr const char *DM_TAG_COMPRESS_ORI_LEN = "compressOriLen"; +constexpr const char *DM_TAG_COMPRESS = "compressMsg"; +constexpr const char *DM_TAG_REPLY = "reply"; +constexpr const char *DM_TAG_STATE = "state"; +constexpr const char *DM_TAG_REASON = "reason"; +constexpr const char* DM_TAG_PEER_USER_ID = "peerUserId"; +constexpr const char* DM_TAG_PEER_DISPLAY_ID = "peerDisplayId"; +constexpr const char* DM_TAG_EXTRA_INFO = "extraInfo"; + +constexpr const int32_t DM_HASH_LEN = 32; +constexpr const char* TAG_IS_ONLINE = "isOnline"; +constexpr const char* TAG_IS_AUTHED = "isAuthed"; +constexpr const char* TAG_CREDENTIAL_INFO = "credentialInfo"; + +// accesser table内容 用于同步ACL +constexpr const char* DM_TAG_ACCESSER_DEVICE_ID = "accesserDeviceId"; +constexpr const char* DM_TAG_ACCESSER_USER_ID = "accesserUserId"; +constexpr const char* DM_TAG_ACCESSER_ACOUNT_ID = "accesserAcountId"; +constexpr const char* DM_TAG_ACCESSER_TOKEN_ID = "accesserTokenId"; +constexpr const char* DM_TAG_ACCESSER_SERVICE_NAME = "accesserServiceName"; +constexpr const char* DM_TAG_ACCESSER_BUNDLE_NAME = "accesserBundleName"; +constexpr const char* DM_TAG_ACCESSER_HAP_SIGNATURE = "accesserHapSignature"; +constexpr const char* DM_TAG_ACCESSER_BIND_LEVEL = "accesserBindLevel"; +constexpr const char* DM_TAG_ACCESSER_CREDENTIAL_ID = "accesserCredetialId"; +constexpr const char* DM_TAG_ACCESSER_STATUS = "accesserStatus"; +constexpr const char* DM_TAG_ACCESSER_SK_ID = "accesserSessionKeyId"; +constexpr const char* DM_TAG_ACCESSER_SK_TIMESTAMP = "accesserSKTimeStamp"; + +// accessee table内容 用于同步ACL +constexpr const char* DM_TAG_ACCESSEE_DEVICE_ID = "accesseeDeviceId"; +constexpr const char* DM_TAG_ACCESSEE_USER_ID = "accesseeUserId"; +constexpr const char* DM_TAG_ACCESSEE_ACOUNT_ID = "accesseeAcountId"; +constexpr const char* DM_TAG_ACCESSEE_TOKEN_ID = "accesseeTokenId"; +constexpr const char* DM_TAG_ACCESSEE_SERVICE_NAME = "accesseeServiceName"; +constexpr const char* DM_TAG_ACCESSEE_BUNDLE_NAME = "accesseeBundleName"; +constexpr const char* DM_TAG_ACCESSEE_HAP_SIGNATURE = "accesseeHapSignature"; +constexpr const char* DM_TAG_ACCESSEE_BIND_LEVEL = "accesseeBindLevel"; +constexpr const char* DM_TAG_ACCESSEE_CREDENTIAL_ID = "accesseeCredetialId"; +constexpr const char* DM_TAG_ACCESSEE_STATUS = "accesseeStatus"; +constexpr const char* DM_TAG_ACCESSEE_SK_ID = "accesseeSessionKeyId"; +constexpr const char* DM_TAG_ACCESSEE_SK_TIMESTAMP = "accesseeSKTimeStamp"; + +// 报文类型 +enum DmMessageType { + // 终止/异常报文 + MSG_TYPE_UNKNOWN = 0, + MSG_TYPE_AUTH_TERMINATE = 1, + // 正常报文 + MSG_TYPE_REQ_ACL_NEGOTIATE = 80, + MSG_TYPE_RESP_ACL_NEGOTIATE = 90, + MSG_TYPE_REQ_USER_CONFIRM = 100, + MSG_TYPE_RESP_USER_CONFIRM = 110, + MSG_TYPE_REQ_PIN_AUTH_START = 120, + MSG_TYPE_RESP_PIN_AUTH_START = 130, + MSG_TYPE_REQ_PIN_AUTH_MSG_NEGOTIATE = 121, + MSG_TYPE_RESP_PIN_AUTH_MSG_NEGOTIATE = 131, + MSG_TYPE_REQ_CREDENTIAL_EXCHANGE = 140, + MSG_TYPE_RESP_CREDENTIAL_EXCHANGE = 150, + MSG_TYPE_REQ_CREDENTIAL_AUTH_START = 160, + MSG_TYPE_RESP_CREDENTIAL_AUTH_START = 170, + MSG_TYPE_REQ_CREDENTIAL_AUTH_NEGOTIATE = 161, + MSG_TYPE_RESP_CREDENTIAL_AUTH_NEGOTIATE = 171, + MSG_TYPE_REQ_DATA_SYNC = 180, + MSG_TYPE_RESP_DATA_SYNC = 190, + MSG_TYPE_AUTH_FINISH = 200, +}; + +struct DmAccessControlTable { + int32_t accessControlId; + int64_t accesserId; + int64_t accesseeId; + std::string deviceId; + std::string sessionKey; + int32_t bindType; + uint32_t authType; + uint32_t deviceType; + std::string deviceIdHash; + int32_t status; + int32_t validPeriod; + int32_t lastAuthTime; + uint32_t bindLevel; + NLOHMANN_DEFINE_TYPE_INTRUSIVE(DmAccessControlTable, accessControlId, accesserId, accesseeId, deviceId, sessionKey, + bindType, authType, deviceType, deviceIdHash, status, validPeriod, lastAuthTime, + bindLevel, deviceIdHash) +}; + +// 用于同步ACL的access结构 +struct DmAccessToSync { + std::string deviceName; + std::string deviceId; // A->B, 无论是A端还是B端,Accesser对象都存A端的deviceId,Accessee对象都存B端的deviceId + int32_t userId; + std::string accountId; + uint64_t tokenId; + std::string bundleName; // 存PacketName + int32_t bindLevel; // 为业务透传数据,无需自定义 + int32_t sessionKeyId; // 用户凭据ID + int64_t skTimeStamp; // 老化,时间为2天 用户级凭据时间戳 + // 使用宏进行序列化和反序列化 + NLOHMANN_DEFINE_TYPE_INTRUSIVE(DmAccessToSync, deviceName, deviceId, userId, accountId, tokenId, bundleName, + bindLevel, sessionKeyId, skTimeStamp) +}; + +class DmAuthMessageProcessor { +public: + DmAuthMessageProcessor(); + ~DmAuthMessageProcessor(); + // 解析报文,返回值为错误码,实际解析出来的信息保存到context中 + int32_t ParseMessage(std::shared_ptr context, const std::string &message); + // 创建报文,构造对应msgType的报文,返回值为json格式报文的字符串 + std::string CreateMessage(DmMessageType msgType, std::shared_ptr context); + + // 创建报文并发送 + void CreateAndSendMsg(DmMessageType msgType, std::shared_ptr context); + + // 保存秘钥 + int32_t SaveSessionKey(const uint8_t *sessionKey, const uint32_t keyLen); + + // 保存永久SK + int32_t SaveSessionKeyToDP(int32_t &skId); + + // 保留本次acl + int32_t PutAccessControlList(std::shared_ptr context, + DmAccess &access, std::string trustDeviceId); + + // 对acl进行checksum + std::string ChecksumAcl(DistributedDeviceProfile::AccessControlProfile &acl); + + // 提取本端ACL 用于消息解析和总线使用 无ACL会返回空字符串 json格式字符串:{dmversion:x,accesser:[{accesserDeviceId:y,...},...],accessee:{...}} + int32_t GetAclListStr(std::shared_ptr &context, std::string &aclList); +private: + // 内部各类报文的实现 + + // 用于组装syncMsg中的加密部分 + int32_t EncryptSyncMessage(std::shared_ptr &context, DmAccess &accessSide, std::string &encSyncMsg); + int32_t ParseAuthStartMessgae(nlohmann::json &jsonObject, std::shared_ptr &context); + + // 解析 80报文 + int32_t ParseNegotiateMessage(nlohmann::json &jsonObject, std::shared_ptr context); + // 解析 90 报文 + int32_t ParseMessageRespAclNegotiate(const nlohmann::json &json, std::shared_ptr context); + // 解析 100 报文 + int32_t ParseMessageReqUserConfirm(const nlohmann::json &json, std::shared_ptr context); + // 解析 110 报文 + int32_t ParseMessageRespUserConfirm(const nlohmann::json &json, std::shared_ptr context); + // 解析 120 报文 + int32_t ParseMessageReqPinAuthStart(const nlohmann::json &json, std::shared_ptr context); + // 解析 130 报文 + int32_t ParseMessageRespPinAuthStart(const nlohmann::json &json, std::shared_ptr context); + // 解析 121 报文 + int32_t ParseMessageReqPinAuthNegotiate(const nlohmann::json &json, std::shared_ptr context); + // 解析 131报文 + int32_t ParseMessageRespPinAuthNegotiate(const nlohmann::json &jsonObject, std::shared_ptr context); + // 解析 140报文信息MSG_TYPE_REQ_CREDENTIAL_EXCHANGE,SINK端存放对方公钥 + int32_t ParseMessageReqCredExchange(const nlohmann::json &jsonObject, std::shared_ptr context); + // 解析 150报文信息MSG_TYPE_RESP_CREDENTIAL_EXCHANGE,存放对方公钥,和协商凭据Id + int32_t ParseMessageRspCredExchange(const nlohmann::json &jsonObject, std::shared_ptr context); + // 解析161 170 171 + int32_t ParseMessageNegotiateTransmit(const nlohmann::json &jsonObject, std::shared_ptr &context, + DmMessageType msgType); + // 解析 180报文信息 MSG_TYPE_REQ_DATA_SYNC 存放对方密文四元组,acl,sp skid + int32_t ParseMessageSyncReq(const nlohmann::json &jsonObject, std::shared_ptr context); + // 解析 190报文信息 MSG_TYPE_RESP_DATA_SYNC 存放对方密文四元组,acl sp skid + int32_t ParseMessageSyncResp(const nlohmann::json &jsonObject, std::shared_ptr context); + // 解析 200报文信息 + int32_t ParseMessageFinish(std::shared_ptr context, nlohmann::json &jsonObject); + + // 创建 80报文 + void CreateNegotiateMessage(std::shared_ptr context, nlohmann::json &jsonObject); + // 创建 90报文 + void CreateRespNegotiateMessage(std::shared_ptr context, nlohmann::json &jsonObject); + // 创建 100 报文 + void CreateMessageReqUserConfirm(std::shared_ptr context, nlohmann::json &json); + // 创建 110 报文 + void CreateMessageRespUserConfirm(std::shared_ptr context, nlohmann::json &json); + // 创建 120 报文 + void CreateMessageReqPinAuthStart(std::shared_ptr context, nlohmann::json &json); + // 创建 130 报文 + void CreateMessageRespPinAuthStart(std::shared_ptr context, nlohmann::json &json); + // 创建 121 报文 + void CreateMessageReqPinAuthNegotiate(std::shared_ptr context, nlohmann::json &json); + // 创建 131 报文 + void CreateMessageRespPinAuthNegotiate(std::shared_ptr context, nlohmann::json &json); + // 创建140报文 + void CreateMessageReqCredExchange(std::shared_ptr context, nlohmann::json &jsonObject); + // 创建150报文 + void CreateMessageRspCredExchange(std::shared_ptr context, nlohmann::json &jsonObject); + // 创建160报文 + void CreateMessageReqCredAuthStart(std::shared_ptr context, nlohmann::json &jsonObject); + // 161 170 171 透传凭据认证消息构造 + int32_t CreateCredentialNegotiateMessage(std::shared_ptr &context, nlohmann::json &jsonObject); + // 180 190 消息构造 + int32_t CreateSyncMessage(std::shared_ptr &context, nlohmann::json &jsonObject); + // 压缩sync 消息 + std::string CompressSyncMsg(std::string &inputStr); + // 解压缩sync 消息 + std::string DecompressSyncMsg(std::string& compressed, uint32_t oriLen); + // 序列化acl + int32_t ACLToStr(DistributedDeviceProfile::AccessControlProfile acl, std::string aclStr); + // 创建190报文 + void CreateMessageSyncResp(std::shared_ptr context, nlohmann::json &jsonObject); + // 创建200报文 + void CreateMessageFinish(std::shared_ptr context, nlohmann::json &jsonObject); + // 解密180 190报文 + int32_t DecryptSyncMessage(std::shared_ptr &context, + DmAccess &access, std::string &enSyncMsg); + int32_t ParseSyncMessage(std::shared_ptr &context, + DmAccess &access, nlohmann::json jsonObject); + + // DP中accesser_table记录转string + std::string AccesserToStr(DistributedDeviceProfile::AccessControlProfile acl); + // DP中accessee_table记录转string + std::string AccesseeToStr(DistributedDeviceProfile::AccessControlProfile acl); + std::string Base64Encode(std::string &inputStr); + std::string Base64Decode(std::string &inputStr); + std::shared_ptr cryptoMgr_ = nullptr; +}; + +} // namespace DistributedHardware +} // namespace OHOS +#endif // OHOS_DM_AUTH_MESSAGE_PROCESSOR_V2_H \ No newline at end of file diff --git a/services/implementation/include/authentication_v2/dm_auth_state.h b/services/implementation/include/authentication_v2/dm_auth_state.h new file mode 100644 index 0000000000000000000000000000000000000000..8f889bc716ce8e889e8461e833ca84f9aa77af91 --- /dev/null +++ b/services/implementation/include/authentication_v2/dm_auth_state.h @@ -0,0 +1,381 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 OHOS_DM_AUTH_STATE_V2_H +#define OHOS_DM_AUTH_STATE_V2_H + +#include + +#include "access_control_profile.h" +#include "dm_auth_context.h" + +namespace OHOS { +namespace DistributedHardware { + +constexpr const char* AUTHENTICATE_TIMEOUT_TASK = "deviceManagerTimer:authenticate"; +constexpr const char* NEGOTIATE_TIMEOUT_TASK = "deviceManagerTimer:negotiate"; +constexpr const char* CONFIRM_TIMEOUT_TASK = "deviceManagerTimer:confirm"; +constexpr const char* SESSION_HEARTBEAT_TIMEOUT_TASK = "deviceManagerTimer:sessionHeartbeat"; +constexpr const char* WAIT_REQUEST_TIMEOUT_TASK = "deviceManagerTimer:waitRequest"; +constexpr const char* AUTH_DEVICE_TIMEOUT_TASK = "deviceManagerTimer:authDevice_"; +constexpr const char* WAIT_NEGOTIATE_TIMEOUT_TASK = "deviceManagerTimer:waitNegotiate"; +constexpr const char* ADD_TIMEOUT_TASK = "deviceManagerTimer:add"; + +// 状态类型 +enum class DmAuthStateType { + AUTH_IDLE_STATE = 0, // 设备初始化时 + // source端的状态 + AUTH_SRC_START_STATE = 1, // 用户触发BindTarget + AUTH_SRC_NEGOTIATE_STATE = 2, // 收到软总线回调函数OnSessionOpened,发送80报文 + AUTH_SRC_CONFIRM_STATE = 3, // 收到90授权结果报文,发送100报文 + AUTH_SRC_PIN_NEGOTIATE_START_STATE = 4, // 开始协商PIN码,收到110授权结果报文 或回退 或 90跳转 + AUTH_SRC_PIN_INPUT_STATE = 5, // 输入PIN + AUTH_SRC_PIN_NEGOTIATE_ULTRASONIC_PIN_STATE = 6, // 超声PIN协商 + AUTH_SRC_PIN_AUTH_START_STATE = 7, // 开始做认证,发送120报文 + AUTH_SRC_PIN_AUTH_MSG_NEGOTIATE_STATE = 8, // 收到130认证PIN结果报文,发送121报文 + AUTH_SRC_PIN_AUTH_DONE_STATE = 9, // 收到131认证PIN结果报文,调用processData + AUTH_SRC_CREDENTIAL_EXCHANGE_STATE = 10, // 触发Onfinish回调事件,发送140报文 + AUTH_SRC_CREDENTIAL_AUTH_START_STATE = 11, // 收到150加密报文,发送160报文 + AUTH_SRC_CREDENTIAL_AUTH_NEGOTIATE_STATE = 12, // 收到170凭据认证报文,发送161报文 + AUTH_SRC_CREDENTIAL_AUTH_DONE_STATE = 13, // 收到171凭据认证报文,回复160报文或者180报文 + AUTH_SRC_DATA_SYNC_STATE = 14, // 触发Onfinish回调事件,发送180报文 todo 可以删除 + AUTH_SRC_FINISH_STATE = 15, // 收到190报文,发送200报文 + + // sink端的状态 + AUTH_SINK_START_STATE = 50, // 总线触发OnSessionOpened + AUTH_SINK_NEGOTIATE_STATE = 51, // 收到80可信关系协商报文,发送90报文 + AUTH_SINK_CONFIRM_STATE = 52, // 收到100用户授权报文,发送110报文 + AUTH_SINK_PIN_NEGOTIATE_START_STATE = 53, // 开始协商PIN码,CONFIRM_STATE 主动迁移或者 错误回退 + AUTH_SINK_PIN_DISPLAY_STATE = 54, // 生成并显示PIN + AUTH_SINK_PIN_NEGOTIATE_ULTRASONIC_PIN_STATE = 55, // 协商超声PIN状态 (收src端报文)被动触发 或 其他状态主动迁移 进入超声码协商状态 + AUTH_SINK_PIN_AUTH_START_STATE = 56, // 收到120认证PIN报文,发送130报文 + AUTH_SINK_PIN_AUTH_MSG_NEGOTIATE_STATE = 57, // 收到121认证PIN报文,发送131报文 + AUTH_SINK_PIN_AUTH_DONE_STATE = 58, // 触发Onfinish回调事件 + AUTH_SINK_CREDENTIAL_EXCHANGE_STATE = 59, // 收到140加密报文,发送150报文 + AUTH_SINK_CREDENTIAL_AUTH_START_STATE = 60, // 收到160凭证认证报文,发送170报文 + AUTH_SINK_CREDENTIAL_AUTH_NEGOTIATE_STATE = 61, // 收到161凭据协商报文,回复171报文 + AUTH_SINK_DATA_SYNC_STATE = 62, // 收到180同步报文,发送190报文 + AUTH_SINK_FINISH_STATE = 63, // 收到200结束报文 +}; + +// 凭据添加方式 +enum DmAuthCredentialAddMethod : uint8_t { + DM_AUTH_CREDENTIAL_ADD_METHOD_GENERATE = 1, // 生成 + DM_AUTH_CREDENTIAL_ADD_METHOD_IMPORT, // 导入 +}; + +// 凭据主体 +enum DmAuthCredentialSubject : uint8_t { + DM_AUTH_CREDENTIAL_SUBJECT_PRIMARY = 1, // 主控 + DM_AUTH_CREDENTIAL_SUBJECT_SUPPLEMENT, // 配件 +}; + +// 凭据与账号关联 +enum DmAuthCredentialAccountRelation : uint8_t { + DM_AUTH_CREDENTIAL_ACCOUNT_RELATED = 1, // 账号相关 + DM_AUTH_CREDENTIAL_ACCOUNT_UNRELATED, // 账号无关 +}; + +// 秘钥类型 +enum DmAuthKeyFormat : uint8_t { + DM_AUTH_KEY_FORMAT_SYMM_IMPORT = 1, // 对称密钥(仅在导入下支持) + DM_AUTH_KEY_FORMAT_ASYMM_IMPORT, // 非对称密钥公钥(仅在导入下支持) + DM_AUTH_KEY_FORMAT_ASYMM_GENERATE, // 非对称密钥(仅在生成下支持) + DM_AUTH_KEY_FORMAT_X509, // X509证书 +}; + +// 算法类型 +enum DmAuthAlgorithmType : uint8_t { + DM_AUTH_ALG_TYPE_AES256 = 1, // AES256 + DM_AUTH_ALG_TYPE_AES128, // AES128 + DM_AUTH_ALG_TYPE_P256, // P256 + DM_AUTH_ALG_TYPE_ED25519 // ED25519 +}; + +// 凭据证明类型 +enum DmAuthCredentialProofType : uint8_t { + DM_AUTH_CREDENTIAL_PROOF_PSK = 1, // PSK + DM_AUTH_CREDENTIAL_PROOF_PKI, // PKI +}; + +class DmAuthState { +public: + virtual ~DmAuthState() {}; + virtual DmAuthStateType GetStateType() = 0; + virtual int32_t Action(std::shared_ptr context) = 0; // 执行状态对应的action动作 + void SyncAclList(std::shared_ptr context, int32_t accountId, + std::string credId, int32_t sessionKeyId, int32_t aclId); + static bool IsScreenLocked(); + static int32_t GetTaskTimeout(std::shared_ptr context, const char* taskName, int32_t taskTimeOut); + static void HandleAuthenticateTimeout(std::shared_ptr context, std::string name); +protected: +}; + +class AuthSrcConfirmState : public DmAuthState { +public: + virtual ~AuthSrcConfirmState() {}; + DmAuthStateType GetStateType() override; + int32_t Action(std::shared_ptr context) override; +private: + int32_t DoPinAuth(std::shared_ptr context); +}; + +class AuthSinkStatePinAuthComm { +public: + static void GeneratePincode(std::shared_ptr context); + static int32_t ShowAuthInfoDialog(std::shared_ptr context); +private: + static void HandleSessionHeartbeat(std::shared_ptr context, std::string name); +}; + +class AuthSinkConfirmState : public DmAuthState { +public: + virtual ~AuthSinkConfirmState() {}; + DmAuthStateType GetStateType() override; + int32_t Action(std::shared_ptr context) override; +private: + int32_t MatchAuthType(std::shared_ptr context); // 从DP配置读取授权类型 + int32_t ShowConfigDialog(std::shared_ptr context); // 提示用户授权对话框 + int64_t GenRequestId(std::shared_ptr context); // 生成HiChain请求ID +}; + +class AuthSrcPinNegotiateStartState : public DmAuthState { +public: + virtual ~AuthSrcPinNegotiateStartState() {}; + DmAuthStateType GetStateType() override; + int32_t Action(std::shared_ptr context) override; +}; + +class AuthSrcPinInputState : public DmAuthState { +public: + virtual ~AuthSrcPinInputState() {}; + DmAuthStateType GetStateType() override; + int32_t Action(std::shared_ptr context) override; +private: + int32_t ShowStartAuthDialog(std::shared_ptr context); +}; + +class AuthSinkPinNegotiateStartState : public DmAuthState { +public: + virtual ~AuthSinkPinNegotiateStartState() {}; + DmAuthStateType GetStateType() override; + int32_t Action(std::shared_ptr context) override; +}; + +class AuthSinkPinDisplayState : public DmAuthState { +public: + virtual ~AuthSinkPinDisplayState() {}; + DmAuthStateType GetStateType() override; + int32_t Action(std::shared_ptr context) override; +}; + +class AuthSrcPinNegotiateUltrasonicPinState : public DmAuthState { +public: + virtual ~AuthSrcPinNegotiateUltrasonicPinState() {}; + DmAuthStateType GetStateType() override; + int32_t Action(std::shared_ptr context) override; +}; + +class AuthSinkPinNegotiateUltrasonicPinState : public DmAuthState { +public: + virtual ~AuthSinkPinNegotiateUltrasonicPinState() {}; + DmAuthStateType GetStateType() override; + int32_t Action(std::shared_ptr context) override; +}; + +class AuthSrcPinAuthStartState : public DmAuthState { +public: + virtual ~AuthSrcPinAuthStartState() {}; + DmAuthStateType GetStateType() override; + int32_t Action(std::shared_ptr context) override; +private: + int32_t GetPinCode(std::shared_ptr context); // 获取PIN码 + int32_t ShowStartAuthDialog(std::shared_ptr context); // 向用户显示PIN输入框 + int32_t GetPinCodeFromServerInfo(std::shared_ptr context); // 从服务端配置信息中获取PIN码 + int32_t AuthDevice(std::shared_ptr context); // 向HiChain发起PIN认证请求 +}; + +class AuthSinkPinAuthStartState : public DmAuthState { +public: + virtual ~AuthSinkPinAuthStartState() {}; + DmAuthStateType GetStateType() override; + int32_t Action(std::shared_ptr context) override; +}; + +class AuthSrcPinAuthMsgNegotiateState : public DmAuthState { +public: + virtual ~AuthSrcPinAuthMsgNegotiateState() {}; + DmAuthStateType GetStateType() override; + int32_t Action(std::shared_ptr context) override; +}; + +class AuthSinkPinAuthMsgNegotiateState : public DmAuthState { +public: + virtual ~AuthSinkPinAuthMsgNegotiateState() {}; + DmAuthStateType GetStateType() override; + int32_t Action(std::shared_ptr context) override; +}; + +class AuthSinkPinAuthDoneState : public DmAuthState { +public: + virtual ~AuthSinkPinAuthDoneState() {}; + DmAuthStateType GetStateType() override; + int32_t Action(std::shared_ptr context) override; +}; + +// 收到131认证PIN结果报文,调用processData +class AuthSrcPinAuthDoneState : public DmAuthState { +public: + virtual ~AuthSrcPinAuthDoneState() {}; + DmAuthStateType GetStateType() override; + int32_t Action(std::shared_ptr context) override; +}; + +class AuthSrcStartState : public DmAuthState { +public: + virtual ~AuthSrcStartState() {}; + DmAuthStateType GetStateType() override; + int32_t Action(std::shared_ptr context) override; +}; + +class AuthSrcNegotiateStateMachine : public DmAuthState { +public: + virtual ~AuthSrcNegotiateStateMachine() {}; + DmAuthStateType GetStateType() override; + int32_t Action(std::shared_ptr context) override; +}; + +// 凭据协商阶段,AuthSrcCredentialExchangeState AuthSinkCredentialExchangeState AuthSrcCredentialAuthStartState +// 中间类 封装业务相关的公共接口 +class AuthCredentialAgreeState : public DmAuthState { +public: + virtual ~AuthCredentialAgreeState() {}; +protected: + // 生成凭据协商状态下的authParams的json格式字符串 + std::string CreateAuthParamsString(DmAuthScope authorizedScope, DmAuthCredentialAddMethod method, + const std::shared_ptr &authContext); + // 生成凭据Id和公钥 + int32_t GenerateCredIdAndPublicKey(DmAuthScope authorizedScope, std::shared_ptr &authContext); + // 协商凭据得到协商凭据Id + int32_t AgreeCredential(DmAuthScope authorizedScope, std::shared_ptr &authContext); +}; + +// 收到131报文,发送140报文 +class AuthSrcCredentialExchangeState : public AuthCredentialAgreeState { +public: + virtual ~AuthSrcCredentialExchangeState() {}; + DmAuthStateType GetStateType() override; + int32_t Action(std::shared_ptr context) override; +}; + +// AuthSinkCredentialExchangeState 收到140报文发送150报文 +class AuthSinkCredentialExchangeState : public AuthCredentialAgreeState { +public: + virtual ~AuthSinkCredentialExchangeState() {}; + DmAuthStateType GetStateType() override; + int32_t Action(std::shared_ptr context) override; +}; + +// AuthSrcCredentialAuthStartState, // 收到150加密报文,发送160报文 +class AuthSrcCredentialAuthStartState : public AuthCredentialAgreeState { +public: + virtual ~AuthSrcCredentialAuthStartState() {}; + DmAuthStateType GetStateType() override; + int32_t Action(std::shared_ptr context) override; +}; +// 收到170凭据认证报文,解析ontransmit,回复161报文 +class AuthSrcCredentialAuthNegotiateState : public DmAuthState { +public: + virtual ~AuthSrcCredentialAuthNegotiateState() {}; + DmAuthStateType GetStateType() override; + int32_t Action(std::shared_ptr context) override; // 执行状态对应的action动作 +}; + +// 收到171凭据认证报文 发送160/180 报文 +class AuthSrcCredentialAuthDoneState : public DmAuthState { +public: + virtual ~AuthSrcCredentialAuthDoneState() {}; + DmAuthStateType GetStateType() override; + int32_t Action(std::shared_ptr context) override; // 执行状态对应的action动作 +}; + +// 收到160凭证认证报文 发送170报文 +class AuthSinkCredentialAuthStartState : public DmAuthState { +public: + virtual ~AuthSinkCredentialAuthStartState() {}; + DmAuthStateType GetStateType() override; + int32_t Action(std::shared_ptr context) override; // 执行状态对应的action动作 +}; + +// 收到161凭据协商报文 并回复171报文 +class AuthSinkCredentialAuthNegotiateState : public DmAuthState { +public: + virtual ~AuthSinkCredentialAuthNegotiateState() {}; + DmAuthStateType GetStateType() override; + int32_t Action(std::shared_ptr context) override; // 执行状态对应的action动作 +}; + +// 收到80报文,准备发送90报文 +class AuthSinkNegotiateStateMachine : public DmAuthState { +public: + virtual ~AuthSinkNegotiateStateMachine() {}; + DmAuthStateType GetStateType() override; + int32_t Action(std::shared_ptr context) override; + +private: + int32_t RespQueryAcceseeIds(std::shared_ptr context); + bool HaveSameTokenId(std::shared_ptr context, const std::vector &tokenList); + uint32_t GetCredentialType(std::shared_ptr context, nlohmann::json credInfo); + bool AclCompareTwoIds(std::shared_ptr context, + const DistributedDeviceProfile::Accesser &accesser, const DistributedDeviceProfile::Accessee &accessee); + bool AclCompareFourIds(std::shared_ptr context, + const DistributedDeviceProfile::Accesser &accesser, const DistributedDeviceProfile::Accessee &accessee); + int32_t ProcRespNegotiate5_1_0(std::shared_ptr context); + int32_t GetAuthCredentialInfo(std::shared_ptr context); + void MatchFallBackCandidateList(std::shared_ptr context, DmAuthType authType); + int64_t GenRequestId(); + bool IsAuthCodeReady(std::shared_ptr context); + void NegotiatePinAuthType(std::shared_ptr context); +}; + + +// AuthSinkDataSyncState // 收到180同步报文,发送190报文 +class AuthSinkDataSyncState : public DmAuthState { + public: + virtual ~AuthSinkDataSyncState() {}; + DmAuthStateType GetStateType() override; + int32_t Action(std::shared_ptr context) override; +}; + +// AuthSrcFinishState // 收到190报文,发送200报文 +class AuthSrcFinishState : public DmAuthState { + public: + virtual ~AuthSrcFinishState() {}; + DmAuthStateType GetStateType() override; + int32_t Action(std::shared_ptr context) override; + void SourceFinish(std::shared_ptr context); +}; + +// AuthSinkFinishState // 收到200结束报文 +class AuthSinkFinishState : public DmAuthState { + public: + virtual ~AuthSinkFinishState() {}; + DmAuthStateType GetStateType() override; + int32_t Action(std::shared_ptr context) override; + void SinkFinish(std::shared_ptr context); +}; +} // namespace DistributedHardware +} // namespace OHOS +#endif // OHOS_DM_AUTH_STATE_V2_H \ No newline at end of file diff --git a/services/implementation/include/authentication_v2/dm_auth_state_machine.h b/services/implementation/include/authentication_v2/dm_auth_state_machine.h new file mode 100644 index 0000000000000000000000000000000000000000..b9e51ab1089a441f936b5a839f7e506c7d554074 --- /dev/null +++ b/services/implementation/include/authentication_v2/dm_auth_state_machine.h @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 OHOS_DM_AUTH_STATE_MACHINE_V2_H +#define OHOS_DM_AUTH_STATE_MACHINE_V2_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dm_auth_state.h" + +namespace OHOS { +namespace DistributedHardware { + +// 事件等待超时时间 +constexpr const int EVENT_TIMEOUT = 5000; // 5000 毫秒 = 5 秒 + +// 定义状态迁移表类型 +using StateTransitionTable = std::map>; + +enum DmEventType { + ON_TRANSMIT = 0, + ON_SESSION_KEY_RETURNED, + ON_REQUEST, + ON_FINISH, + ON_ERROR, + + ON_TIMEOUT, // 超时 + ON_USER_OPERATION, // 用户操作 + ON_FAIL, // 失败流程 + ON_SCREEN_LOCKED, // 锁屏 +}; + +class DmAuthStateMachine { +public: + DmAuthStateMachine(std::shared_ptr context); + ~DmAuthStateMachine(); + + // 通知状态迁移,执行状态对应具体action与异常处理(只允许在OnDataReceived中调用) + int32_t TransitionTo(std::shared_ptr state); + // action内部的期望事件,用于阻塞,当等到期望事件完成或其他异常时,返回实际发生的事件,而其他正常事件则会继续阻塞(只允许在action中调用) + DmEventType WaitExpectEvent(DmEventType eventType); + // 事件完成调用,传事件枚举(只允许在事件触发中调用),如果是异常事件,需在context的reason或者reply记录 + void NotifyEventFinish(DmEventType eventType); + // 获取当前状态 + DmAuthStateType GetCurState(); +private: + // 循环等待状态转移,执行action + void Run(std::shared_ptr context); + // 停止线程 + void Stop(); + // 获取状态,进行执行 + std::optional> FetchState(); + // 设置当前状态 + void SetCurState(DmAuthStateType state); + // 检验下一状态迁移合法性 + bool CheckStateTransitValid(DmAuthStateType nextState); + + // 存储当前状态 + DmAuthStateType curState_; + // 正常状态迁移表,但所有状态切换到Finish状态是合法的 + StateTransitionTable stateTransitionTable_; + + // 事件队列 + std::queue eventQueue_; + // 异常事件集合 + std::set exceptionEvent_; + + std::thread thread_; + std::atomic running_; + std::queue> statesQueue_; + // 同步原语 + std::mutex stateMutex_; + std::condition_variable stateCv_; + std::mutex eventMutex_; + std::condition_variable eventCv_; + DmAuthDirection direction_; +}; + +} // namespace DistributedHardware +} // namespace OHOS +#endif // OHOS_DM_AUTH_STATE_MACHINE_V2_H diff --git a/services/implementation/include/cryptomgr/crypto_mgr.h b/services/implementation/include/cryptomgr/crypto_mgr.h index 86a759081dcc686b32730176d758fda0a71369a9..8afd26aa64dd5d386f978360d101098b6a196eb6 100644 --- a/services/implementation/include/cryptomgr/crypto_mgr.h +++ b/services/implementation/include/cryptomgr/crypto_mgr.h @@ -45,6 +45,7 @@ public: int32_t SaveSessionKey(const uint8_t *sessionKey, const uint32_t keyLen); int32_t ProcessSessionKey(const uint8_t *sessionKey, const uint32_t keyLen); void ClearSessionKey(); + uint32_t GetSessionKey(uint8_t *sesionKey); private: int32_t DoEncryptData(AesGcmCipherKey *cipherKey, const unsigned char *input, uint32_t inLen, diff --git a/services/implementation/include/dependency/hichain/hichain_auth_connector.h b/services/implementation/include/dependency/hichain/hichain_auth_connector.h index ef02d721df743057a10b61d38b3d700388971428..306d000c65960455048ccdd5f197db6b09ab8fc8 100644 --- a/services/implementation/include/dependency/hichain/hichain_auth_connector.h +++ b/services/implementation/include/dependency/hichain/hichain_auth_connector.h @@ -53,10 +53,29 @@ public: int32_t ProcessAuthData(int64_t requestId, std::string authData, int32_t osAccountId); int32_t GenerateCredential(std::string &localUdid, int32_t osAccountId, std::string &publicKey); bool QueryCredential(std::string &localUdid, int32_t osAccountId); + int32_t QueryCredentialInfo(int32_t userId, nlohmann::json queryParams, nlohmann::json &resultJson); int32_t ImportCredential(int32_t osAccountId, std::string deviceId, std::string publicKey); int32_t DeleteCredential(const std::string &deviceId, int32_t userId); int32_t RegisterHiChainAuthCallback(std::shared_ptr callback); int32_t GetCredential(std::string &localUdid, int32_t osAccountId, std::string &publicKey); + + // 处理凭据认证报文 + int32_t ProcessCredData(int64_t authReqId, const std::string &data); + // 生成凭据,返回凭据Id + int32_t AddCredential(int32_t osAccountId, const std::string &authParams, std::string &creId); + // 根据凭据Id导出公钥 + int32_t ExportCredential(int32_t osAccountId, const std::string &credId, std::string &publicKey); + // 凭据协商 + int32_t AgreeCredential(int32_t osAccountId, const std::string selfCredId, const std::string &authParams, + std::string &credId); + // 删除凭据 + int32_t DeleteCredential(int32_t osAccountId, const std::string &creId); + // 凭据认证 pinCode pin码(点对点临时凭据必填) + int32_t AuthCredential(int32_t osAccountId, int64_t authReqId, const std::string &credId, + const std::string &pinCode); + // pin码 认证 + int32_t AuthCredentialPinCode(int32_t osAccountId, int64_t authReqId, int32_t pinCode); + private: void FreeJsonString(char *jsonStr); diff --git a/services/implementation/include/dependency/hichain/hichain_connector_callback.h b/services/implementation/include/dependency/hichain/hichain_connector_callback.h index 1e8e73f430f2a86209dad621e8fa96be5731e84d..26ab015763742e4867b6e5821335bd306fef91c7 100644 --- a/services/implementation/include/dependency/hichain/hichain_connector_callback.h +++ b/services/implementation/include/dependency/hichain/hichain_connector_callback.h @@ -37,8 +37,14 @@ public: virtual void AuthDeviceFinish(int64_t requestId) = 0; virtual void AuthDeviceError(int64_t requestId, int32_t errorCode) = 0; virtual void AuthDeviceSessionKey(int64_t requestId, const uint8_t *sessionKey, uint32_t sessionKeyLen) = 0; - virtual int32_t GetPinCode(int32_t &code) = 0; - virtual void GetRemoteDeviceId(std::string &deviceId) = 0; + // virtual int32_t GetPinCode(std::string &pkgName, int32_t &code) + // { + // pkgName = ""; + // return GetPinCode(code); + // }; + // virtual int32_t GetPinCode(int32_t &code) = 0; + // virtual void GetRemoteDeviceId(std::string &deviceId) = 0; + virtual char *AuthDeviceRequest(int64_t requestId, int operationCode, const char *reqParams) = 0; }; } // namespace DistributedHardware } // namespace OHOS diff --git a/services/implementation/include/dependency/softbus/softbus_connector.h b/services/implementation/include/dependency/softbus/softbus_connector.h index afdf110ebb4bb74bd0e38040c4da5cbf82ce8895..996ff36df43c24da87d272b8817e2204d105d119 100644 --- a/services/implementation/include/dependency/softbus/softbus_connector.h +++ b/services/implementation/include/dependency/softbus/softbus_connector.h @@ -105,6 +105,7 @@ public: void HandleDeviceOffline(std::string deviceId); void SetProcessInfo(ProcessInfo processInfo); bool CheckIsOnline(const std::string &targetDeviceId); + bool CheckIsOnline(const std::string &targetDeviceIdHash, bool isHash); void SetProcessInfoVec(std::vector processInfoVec); std::vector GetProcessInfo(); void ClearProcessInfo(); diff --git a/services/implementation/include/device_manager_service_impl.h b/services/implementation/include/device_manager_service_impl.h index 4fcb6cd47aa3adf5d50bc92736db8ed731398433..8fac2b80a3179f0328a5066bf99227da10926c5b 100644 --- a/services/implementation/include/device_manager_service_impl.h +++ b/services/implementation/include/device_manager_service_impl.h @@ -21,6 +21,7 @@ #include "access_control_profile.h" #include "dm_ability_manager.h" +#include "dm_auth_manager_base.h" #include "dm_auth_manager.h" #include "dm_common_event_manager.h" #include "dm_credential_manager.h" @@ -31,6 +32,7 @@ #include "dm_single_instance.h" #include "softbus_connector.h" #include "mine_hichain_connector.h" +#include "auth_manager.h" namespace OHOS { namespace DistributedHardware { @@ -154,9 +156,11 @@ private: void HandleUserRemoved(int32_t preUserId); void HandleRemoteUserRemoved(int32_t preUserId, const std::string &remoteUdid); DmAuthForm ConvertBindTypeToAuthForm(int32_t bindType); + int32_t InitAndRegisterAuthMgr(bool isSrcSide); + int32_t CreateAuthMgrByMessage(int sessionId, const void *data, unsigned int dataLen); private: - std::shared_ptr authMgr_; + std::shared_ptr authMgr_; std::shared_ptr deviceStateMgr_; std::shared_ptr softbusConnector_; std::shared_ptr abilityMgr_; diff --git a/services/implementation/src/authentication/dm_auth_manager.cpp b/services/implementation/src/authentication/dm_auth_manager.cpp index 8edd9245f829935cbfaa5a8900f794e59dde9c90..eda9c8262a4e2aa3b8fef31bc3842a1dc5d7415b 100644 --- a/services/implementation/src/authentication/dm_auth_manager.cpp +++ b/services/implementation/src/authentication/dm_auth_manager.cpp @@ -58,13 +58,13 @@ const int32_t NEGOTIATE_TIMEOUT = 10; const int32_t INPUT_TIMEOUT = 60; const int32_t ADD_TIMEOUT = 10; const int32_t WAIT_NEGOTIATE_TIMEOUT = 10; -const int32_t WAIT_REQUEST_TIMEOUT = 10; +const int32_t WAIT_REQUEST_TIMEOUT = 60; const int32_t CLONE_AUTHENTICATE_TIMEOUT = 20; -const int32_t CLONE_CONFIRM_TIMEOUT = 10; +const int32_t CLONE_CONFIRM_TIMEOUT = 60; const int32_t CLONE_NEGOTIATE_TIMEOUT = 10; const int32_t CLONE_ADD_TIMEOUT = 10; const int32_t CLONE_WAIT_NEGOTIATE_TIMEOUT = 10; -const int32_t CLONE_WAIT_REQUEST_TIMEOUT = 10; +const int32_t CLONE_WAIT_REQUEST_TIMEOUT = 60; const int32_t CLONE_SESSION_HEARTBEAT_TIMEOUT = 20; const int32_t HML_SESSION_TIMEOUT = 10; const int32_t CANCEL_PIN_CODE_DISPLAY = 1; @@ -115,7 +115,6 @@ constexpr const char* TARGET_PKG_NAME_KEY = "targetPkgName"; constexpr const char* CUSTOM_DESCRIPTION_KEY = "customDescription"; constexpr const char* CANCEL_DISPLAY_KEY = "cancelPinCodeDisplay"; constexpr const char* BUNDLE_NAME_KEY = "bundleName"; -constexpr const char* DM_VERSION_4_1_5_1 = "4.1.5.1"; constexpr const char* DM_VERSION_5_0_1 = "5.0.1"; constexpr const char* DM_VERSION_5_0_2 = "5.0.2"; constexpr const char* DM_VERSION_5_0_3 = "5.0.3"; @@ -1023,7 +1022,7 @@ void DmAuthManager::RespNegotiate(const int32_t &sessionId) remoteDeviceId_ = authResponseContext_->localDeviceId; authResponseContext_->networkId = softbusConnector_->GetLocalDeviceNetworkId(); authResponseContext_->targetDeviceName = softbusConnector_->GetLocalDeviceName(); - remoteVersion_ = ConvertSrcVersion(authResponseContext_->dmVersion, authResponseContext_->edition); + remoteVersion_ = AuthManagerBase::ConvertSrcVersion(authResponseContext_->dmVersion, authResponseContext_->edition); NegotiateRespMsg(remoteVersion_); if (CompareVersion(remoteVersion_, std::string(DM_VERSION_4_1_5_1)) && (static_cast(authResponseContext_->bindLevel) >= DEVICE && @@ -1072,7 +1071,7 @@ void DmAuthManager::SendAuthRequest(const int32_t &sessionId) } remoteDeviceId_ = authResponseContext_->localDeviceId; authRequestContext_->remoteDeviceName = authResponseContext_->targetDeviceName; - remoteVersion_ = ConvertSinkVersion(authResponseContext_->dmVersion); + remoteVersion_ = AuthManagerBase::ConvertSinkVersion(authResponseContext_->dmVersion); if (timer_ != nullptr) { timer_->DeleteTimer(std::string(NEGOTIATE_TIMEOUT_TASK)); } @@ -2552,6 +2551,27 @@ int32_t DmAuthManager::GetSessionKeyIdSync(int64_t requestId) return keyid; } +char *DmAuthManager::AuthDeviceRequest(int64_t requestId, int operationCode, const char *reqParams) +{ + LOGI("DmAuthManager::AuthDeviceRequest start."); + (void)requestId; + (void)reqParams; + nlohmann::json jsonObj; + int32_t pinCode = INVALID_PINCODE; + if (GetPinCode(pinCode) == ERR_DM_FAILED || pinCode == INVALID_PINCODE) { + jsonObj[FIELD_CONFIRMATION] = RequestResponse::REQUEST_REJECTED; + } else { + jsonObj[FIELD_CONFIRMATION] = RequestResponse::REQUEST_ACCEPTED; + jsonObj[FIELD_PIN_CODE] = std::to_string(pinCode); + } + std::string deviceId = ""; + GetRemoteDeviceId(deviceId); + jsonObj[FIELD_PEER_CONN_DEVICE_ID] = deviceId; + std::string jsonStr = SafetyDump(jsonObj); + char *buffer = strdup(jsonStr.c_str()); + return buffer; +} + void DmAuthManager::GetRemoteDeviceId(std::string &deviceId) { LOGI("GetRemoteDeviceId start."); @@ -2994,33 +3014,6 @@ void DmAuthManager::HandleDeviceNotTrust(const std::string &udid) hiChainConnector_->DeleteAllGroupByUdid(udid); } -std::string DmAuthManager::ConvertSrcVersion(const std::string &version, const std::string &edition) -{ - std::string srcVersion = ""; - if (version == "" && edition != "") { - srcVersion = edition; - } else if (version == "" && edition == "") { - srcVersion = DM_VERSION_5_0_1; - } else if (version != "" && edition == "") { - srcVersion = version; - } - LOGI("ConvertSrcVersion version %{public}s, edition %{public}s, srcVersion is %{public}s.", - version.c_str(), edition.c_str(), srcVersion.c_str()); - return srcVersion; -} - -std::string DmAuthManager::ConvertSinkVersion(const std::string &version) -{ - std::string sinkVersion = ""; - if (version == "") { - sinkVersion = DM_VERSION_4_1_5_1; - } else { - sinkVersion = version; - } - LOGI("ConvertSinkVersion version %{public}s, sinkVersion is %{public}s.", version.c_str(), sinkVersion.c_str()); - return sinkVersion; -} - void DmAuthManager::SetAuthType(int32_t authType) { authType_ = authType; diff --git a/services/implementation/src/authentication_v2/README.md b/services/implementation/src/authentication_v2/README.md new file mode 100644 index 0000000000000000000000000000000000000000..050a6e6578267c3f1d0ef3b509ddf4f859351de0 --- /dev/null +++ b/services/implementation/src/authentication_v2/README.md @@ -0,0 +1,120 @@ +1. source和sink的状态机(枚举) +2. 使用sessionId做src端的状态机资源隔离 +3. 实现状态管理类 + 1) 使用transitionTo进行状态迁移 + 2) 对于状态内部,会有action + +##### source +```C++ +// 业务初始化 ->S0 +S0:AuthSrcIdleState // 用户触发BindTarget (S0->S1) +S1:AuthSrcStartState // 收到软总线回调函数OnSessionOpened (S1->S2) +S2:AuthSrcNegotiateState // 收到90协商回复报文 (S2->S3) +S3:AuthSrcConfirmState // 收到110授权结果报文 (S3->S4) +S4:AuthSrcPinAuthStartState // 收到130认证PIN结果报文 (S4->S5) +S5:AuthSrcPinAuthMsgNegotiateState // 收到131认证PIN结果报文(S5->S6) +S6:AuthSrcPinAuthDoneState // 触发Onfinish回调事件 (S6->S7) +S7:AuthSrcCredentialExchangeState // 收到150加密报文 (S7->S8) +S8:AuthSrcCredetialAuthStartState // 收到170凭据认证报文 (S8->S9) +S9:AuthSrcCredetialAuthNegotiateState // 收到171凭据认证报文 (S9->S10) +S10:AuthSrcCredetialAuthDoneState // 触发Onfinish回调事件 (S10->S11) +S11:AuthSrcDataSyncState // 收到190同步报文 (S11->S12) +S12:AuthSrcFinishState + +异常: +1、IPC接口StopAuthenticateDevice触发 // 事件触发 +2、收到MSG_TYPE_REQ_AUTH_TERMINATE +3、各状态下流程超时(丢包) +4、锁屏 +5、参数不合法 +6、pin码输入超时 +7、pin码输入错误(3次前,重回状态,3次后,S8) +以上异常都会让任意状态迁移到S8 + +重点:使用sessionId做src端的状态机资源隔离 + +--- +class AuthSrcStateMachinePool +存储多个状态机实例(AuthSrcStateMachine) +成员函数: +get和set接口(sessionId入参) +成员变量: +使用sessionId隔离多份AuthSrcStateMachine + +--- +class AuthSrcStateMachine +1、提供context上下文存储(设置,获取) +2、操作当前状态(设置、获取(打印)) +3、状态迁移检验功能(下一状态是否在列表中) +4、提供transitionTo函数(事件触发 - 用于事件发生时调用) + +成员变量: +context 上下文 +AuthSrcState 状态 + +--- +class AuthSrcState +Source端的状态基类,提供handleEvent函数: + 1)enter:状态检验 + 2)action:状态迁移时需要做的动作 + 3)exit:状态切换 + +每个state都会继承自改基类,做以上4个函数的具体实现 +``` + +##### sink +```C++ +// 业务初始化 ->S0 +S0:AuthSinkIdleState // 总线触发OnSessionOpened (S0->S1) +S1:AuthSinkStartState // 收到80可信关系协商报文 (S1->S2) +S2:AuthSinkNegotiateState // 收到100用户授权报文 (S2->S3) +S3:AuthSinkConfirmState // 收到120认证PIN报文 (S3->S4) +S4:AuthSinkPinAuthStartState // 收到121认证PIN报文 (S4->S5) +S5: AuthSinkPinAuthMsgNegotiateState // 触发Onfinish回调事件 (S5->S6) +S6: AuthSinkPinAuthDoneState // 收到140加密报文 (S6->S7) +S7:AuthSinkCredentialExchangeState // 收到160凭证认证报文 (S7->S8) +S8:AuthSinkCredetialAuthStartState // 收到161凭据协商报文 (S8->S9) +S9:AuthSinkCredetialAuthNegotiateState // 触发Onfinish回调事件 (S9->S10) +S10: AuthSinkCredetialAuthDoneState // 收到180同步报文 (S10->S11) +S11:AuthSinkDataSyncState // 收到200结束报文 (S11->S12) +S12:AuthSinkFinishState + +异常:(扩展性) +1、IPC接口StopAuthenticateDevice触发 +2、收到MSG_TYPE_REQ_AUTH_TERMINATE +3、各状态下流程超时(丢包) +4、锁屏 +5、参数不合法 +6、pin码输入超时 +7、pin码输入错误(3次前,重回状态,3次后,S8) +8、周边依赖crush => 超时,错误=>异常 + +--- +class AuthSinkStateMachinePool +存储多个状态机实例(AuthSinkStateMachine) +成员函数: +get和set接口(sessionId入参) +成员变量: +使用sessionId隔离多份AuthSinkStateMachine + +--- +class AuthSinkStateMachine +1、提供context上下文存储(设置,获取) +2、操作当前状态(设置、获取(打印)) +3、状态迁移检验功能(下一状态是否在列表中) +4、提供transitionTo函数(事件触发 - 用于事件发生时调用) + +成员变量: +context 上下文 +AuthSinkState 状态 + +--- +class AuthSinkState +Sink端的状态基类,提供transitionTo函数: + 1)enter:状态检验 + 2)action:状态迁移时需要做的动作 + 3)exit:状态切换 + +每个state都会继承自改基类,做以上4个函数的具体实现 + +``` diff --git a/services/implementation/src/authentication_v2/auth_manager.cpp b/services/implementation/src/authentication_v2/auth_manager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..da9a7e4bef44a7be7a097f9311deb53869577580 --- /dev/null +++ b/services/implementation/src/authentication_v2/auth_manager.cpp @@ -0,0 +1,1191 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 + +#include "app_manager.h" +#include "softbus_common.h" +#include "system_ability_definition.h" +#include "iservice_registry.h" +#include "parameter.h" +#include "deviceprofile_connector.h" +#include "multiple_user_connector.h" + +#include "dm_constants.h" +#include "dm_crypto.h" +#include "dm_random.h" +#include "dm_log.h" +#include "dm_timer.h" +#include "dm_radar_helper.h" +#include "dm_device_info.h" +#include "dm_anonymous.h" +#include "dm_auth_state_machine.h" +#include "dm_auth_context.h" +#include "dm_auth_message_processor.h" +#include "auth_manager.h" +#include "dm_auth_state.h" +#undef LOG_TAG +#define LOG_TAG "DHDM_V2" + +namespace OHOS { +namespace DistributedHardware { +namespace { + +constexpr int32_t MIN_PIN_CODE = 100000; +constexpr int32_t MAX_PIN_CODE = 999999; +#ifndef NEW_PIN_STATE // todo del +const int32_t MAX_AUTH_FAIL_TIMES = 3; +#endif + +int32_t GetCloseSessionDelaySeconds(std::string &delaySecondsStr) +{ + if (!IsNumberString(delaySecondsStr)) { + LOGE("Invalid parameter, param is not number."); + return 0; + } + const int32_t CLOSE_SESSION_DELAY_SECONDS_MAX = 10; + int32_t delaySeconds = std::atoi(delaySecondsStr.c_str()); + if (delaySeconds < 0 || delaySeconds > CLOSE_SESSION_DELAY_SECONDS_MAX) { + LOGE("Invalid parameter, param out of range."); + return 0; + } + return delaySeconds; +} + +std::string GetBundleLable(const std::string &bundleName) +{ + auto samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (samgr == nullptr) { + LOGE("Get ability manager failed"); + return bundleName; + } + + sptr object = samgr->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID); + if (object == nullptr) { + LOGE("object is NULL."); + return bundleName; + } + + sptr bms = iface_cast(object); + if (bms == nullptr) { + LOGE("bundle manager service is NULL."); + return bundleName; + } + + auto bundleResourceProxy = bms->GetBundleResourceProxy(); + if (bundleResourceProxy == nullptr) { + LOGE("GetBundleResourceProxy fail"); + return bundleName; + } + AppExecFwk::BundleResourceInfo resourceInfo; + auto result = bundleResourceProxy->GetBundleResourceInfo(bundleName, + static_cast(OHOS::AppExecFwk::ResourceFlag::GET_RESOURCE_INFO_ALL), resourceInfo); + if (result != ERR_OK) { + LOGE("GetBundleResourceInfo failed"); + return bundleName; + } + LOGI("bundle resource label is %{public}s ", (resourceInfo.label).c_str()); + return resourceInfo.label; +} + +bool IsAllowDeviceBind(void) +{ + if (AppManager::GetInstance().IsSystemSA()) { + return true; + } + return false; +} + +int32_t CheckAuthParamVaildExtra(const std::string &extra) +{ + nlohmann::json jsonObject = nlohmann::json::parse(extra, nullptr, false); + if (jsonObject.is_discarded() || jsonObject.find(TAG_BIND_LEVEL) == jsonObject.end() || + !IsInt32(jsonObject, TAG_BIND_LEVEL)) { + return DM_OK; + } + int32_t bindLevel = jsonObject[TAG_BIND_LEVEL].get(); + if (static_cast(bindLevel) > APP || bindLevel < INVALID_TYPE) { + LOGE("bindlevel error %{public}d.", bindLevel); + return ERR_DM_INPUT_PARA_INVALID; + } + + if (static_cast(bindLevel) == DEVICE && !IsAllowDeviceBind()) { + LOGE("not allowd device level bind bindlevel: %{public}d.", bindLevel); + return ERR_DM_INPUT_PARA_INVALID; + } + return DM_OK; +} + +std::string ParseExtraFromMap(const std::map &bindParam) +{ + auto iter = bindParam.find(PARAM_KEY_BIND_EXTRA_DATA); + if (iter != bindParam.end()) { + return iter->second; + } + return ConvertMapToJsonString(bindParam); +} + +} // namespace + +bool AuthManager::IsHmlSessionType(std::string sessionType) +{ + return sessionType == CONN_SESSION_TYPE_HML; +} + +AuthManager::AuthManager(std::shared_ptr softbusConnector, + std::shared_ptr listener, + std::shared_ptr hiChainAuthConnector) +{ + LOGI("DmAuthManager constructor"); + context_ = std::make_shared(); + context_->softbusConnector = softbusConnector; + context_->listener = listener; + context_->hiChainAuthConnector = hiChainAuthConnector; + + context_->authUiStateMgr = std::make_shared(context_->listener); + context_->authenticationMap[AUTH_TYPE_PIN] = nullptr; + context_->authenticationMap[AUTH_TYPE_IMPORT_AUTH_CODE] = nullptr; + context_->authenticationMap[AUTH_TYPE_PIN_ULTRASONIC] = nullptr; + context_->accesser.dmVersion = DM_VERSION_5_1_0; + context_->accessee.dmVersion = DM_VERSION_5_1_0; + + // TODO:上下文的成员,authStateMachine、authMessageProcessor等成员是否统一在构造函数中初始化比较好,目前比较分散 +} + +void AuthManager::SetAuthContext(std::shared_ptr context) +{ + this->context_ = context; +} + +std::shared_ptr AuthManager::GetAuthContext() +{ + return this->context_; +} + +int32_t AuthManager::ParseAuthType(const std::map &bindParam, int32_t &authType) +{ + auto iter = bindParam.find(PARAM_KEY_AUTH_TYPE); + if (iter == bindParam.end()) { + LOGE("AuthManager::ParseAuthType bind param key: %{public}s not exist.", PARAM_KEY_AUTH_TYPE); + return ERR_DM_INPUT_PARA_INVALID; + } + std::string authTypeStr = iter->second; + if (authTypeStr.empty()) { + LOGE("AuthManager::ParseAuthType bind param %{public}s is empty.", PARAM_KEY_AUTH_TYPE); + return ERR_DM_INPUT_PARA_INVALID; + } + if (authTypeStr.length() > 1) { + LOGE("AuthManager::ParseAuthType bind param %{public}s length is unsupported.", PARAM_KEY_AUTH_TYPE); + return ERR_DM_INPUT_PARA_INVALID; + } + if (!isdigit(authTypeStr[0])) { + LOGE("AuthManager::ParseAuthType bind param %{public}s fromat is unsupported.", PARAM_KEY_AUTH_TYPE); + return ERR_DM_INPUT_PARA_INVALID; + } + // TODO:std::atoi统一排查换成strtol函数 + authType = std::atoi(authTypeStr.c_str()); + return DM_OK; +} + +int32_t AuthManager::GeneratePincode() +{ + LOGI("AuthManager::GeneratePincode start"); + context_->pinCode = GenRandInt(MIN_PIN_CODE, MAX_PIN_CODE); + return context_->pinCode; +} + +int32_t AuthManager::RegisterUiStateCallback(const std::string sessionName) +{ + LOGI("AuthManager::RegisterUiStateCallback start"); + if (context_->authUiStateMgr == nullptr) { + LOGE("AuthManager::RegisterUiStateCallback context_->authUiStateMgr is null."); + return ERR_DM_FAILED; + } + context_->authUiStateMgr->RegisterUiStateCallback(sessionName); + return DM_OK; +} + +int32_t AuthManager::UnRegisterUiStateCallback(const std::string sessionName) +{ + LOGI("AuthManager::UnRegisterUiStateCallback start"); + if (context_->authUiStateMgr == nullptr) { + LOGE("AuthManager::UnRegisterUiStateCallback context_->authUiStateMgr is null."); + return ERR_DM_FAILED; + } + context_->authUiStateMgr->UnRegisterUiStateCallback(sessionName); + return DM_OK; +} + +int32_t AuthManager::UnAuthenticateDevice(const std::string &sessionName, const std::string &udid, int32_t bindLevel) +{ + // todo + LOGI("AuthManager::UnAuthenticateDevice start"); + return ERR_DM_FAILED; +} + +int32_t AuthManager::ImportAuthCode(const std::string &sessionName, const std::string &authCode) +{ + if (authCode.empty() || sessionName.empty()) { + LOGE("ImportAuthCode failed, authCode or sessionName is empty"); + return ERR_DM_INPUT_PARA_INVALID; + } + context_->importAuthCode = authCode; + context_->importSessionName = sessionName; + context_->pinCode = std::atoi(authCode.c_str()); + return DM_OK; +} + +int32_t AuthManager::UnBindDevice(const std::string &sessionName, const std::string &udid, + int32_t bindLevel, const std::string &extra) +{ + // todo + LOGI("AuthManager::UnBindDevice start"); + return ERR_DM_FAILED; +} +int32_t AuthManager::StopAuthenticateDevice(const std::string &sessionName) +{ + (void)sessionName; + LOGI("AuthManager::StopAuthenticateDevice start"); + + context_->reason = STOP_BIND; + if (context_->direction == DM_AUTH_SOURCE) { + context_->authStateMachine->TransitionTo(std::make_shared()); + } else { + context_->authStateMachine->TransitionTo(std::make_shared()); + } + return DM_OK; +} + +void AuthManager::OnScreenLocked() +{ + LOGI("AuthManager::OnScreenLocked start"); + if (context_->authType == DmAuthType::AUTH_TYPE_IMPORT_AUTH_CODE) { + LOGI("OnScreenLocked authtype is: %{public}d, no need stop bind.", context_->authType); + return; + } + context_->reason = ERR_DM_BIND_USER_CANCEL; + context_->authStateMachine->NotifyEventFinish(DmEventType::ON_FAIL); +} +void AuthManager::HandleDeviceNotTrust(const std::string &udid) +{ + // todo + LOGI("AuthManager::HandleDeviceNotTrust start"); +} +int32_t AuthManager::DeleteGroup(const std::string &sessionName, const std::string &deviceId) +{ + // todo + LOGI("AuthManager::DeleteGroup start"); + return ERR_DM_FAILED; +} +int32_t AuthManager::RegisterAuthenticationType(int32_t authenticationType) +{ + if (authenticationType != USER_OPERATION_TYPE_ALLOW_AUTH && + authenticationType != USER_OPERATION_TYPE_ALLOW_AUTH_ALWAYS) { + LOGE("Invalid parameter."); + return ERR_DM_INPUT_PARA_INVALID; + } + context_->authResult = static_cast(authenticationType); + return DM_OK; +} + +int32_t AuthManager::GetAclListStr(std::string &aclList) +{ + return context_->authMessageProcessor->GetAclListStr(context_, aclList); +} + +int32_t AuthManager::GetReason() +{ + return context_->reason; +} + +// 保存秘钥 +void AuthSrcManager::AuthDeviceSessionKey(int64_t requestId, const uint8_t *sessionKey, uint32_t sessionKeyLen) +{ + LOGI("AuthSrcManager::AuthDeviceSessionKey start. keyLen: %{public}u", sessionKeyLen); + if (context_ == nullptr || context_->authMessageProcessor == nullptr || context_->authStateMachine == nullptr) { + LOGE("AuthSrcManager::AuthDeviceSessionKey failed, auth context not initial."); + return; + } + if (requestId != context_->requestId) { + LOGE("AuthSrcManager::onTransmit requestId %{public}" PRId64 "is error.", requestId); + return; + } + int32_t ret = context_->authMessageProcessor->SaveSessionKey(sessionKey, sessionKeyLen); + if (ret != DM_OK) { + LOGE("AuthSrcManager::AuthDeviceSessionKey, save session key error, ret: %{public}d", ret); + } + + // 通知ON_SESSION_KEY_RETURNED事件完成 + context_->authStateMachine->NotifyEventFinish(ON_SESSION_KEY_RETURNED); + LOGI("AuthSrcManager::AuthDeviceSessionKey leave."); +} + +char *AuthSrcManager::AuthDeviceRequest(int64_t requestId, int operationCode, const char *reqParams) +{ + LOGI("AuthSrcManager::AuthDeviceRequest start"); + return nullptr; +} + +int32_t AuthManager::ParseConnectAddr(const PeerTargetId &targetId, std::string &deviceId, std::string &addrType) +{ + int32_t index = 0; + std::shared_ptr deviceInfo = std::make_shared(); + ConnectionAddr addr; + if (!targetId.wifiIp.empty() && targetId.wifiIp.length() <= IP_STR_MAX_LEN) { + LOGI("AuthManager::ParseConnectAddr parse wifiIp: %{public}s.", GetAnonyString(targetId.wifiIp).c_str()); + if (!addrType.empty()) { + addr.type = static_cast(std::atoi(addrType.c_str())); + } else { + addr.type = ConnectionAddrType::CONNECTION_ADDR_WLAN; + } + memcpy_s(addr.info.ip.ip, IP_STR_MAX_LEN, targetId.wifiIp.c_str(), targetId.wifiIp.length()); + addr.info.ip.port = targetId.wifiPort; + deviceInfo->addr[index] = addr; + deviceId = targetId.wifiIp; + index++; + } else if (!targetId.brMac.empty() && targetId.brMac.length() <= BT_MAC_LEN) { + LOGI("AuthManager::ParseConnectAddr parse brMac: %{public}s.", GetAnonyString(targetId.brMac).c_str()); + addr.type = ConnectionAddrType::CONNECTION_ADDR_BR; + memcpy_s(addr.info.br.brMac, BT_MAC_LEN, targetId.brMac.c_str(), targetId.brMac.length()); + deviceInfo->addr[index] = addr; + deviceId = targetId.brMac; + index++; + } else if (!targetId.bleMac.empty() && targetId.bleMac.length() <= BT_MAC_LEN) { + LOGI("AuthManager::ParseConnectAddr parse bleMac: %{public}s.", GetAnonyString(targetId.bleMac).c_str()); + addr.type = ConnectionAddrType::CONNECTION_ADDR_BLE; + memcpy_s(addr.info.ble.bleMac, BT_MAC_LEN, targetId.bleMac.c_str(), targetId.bleMac.length()); + if (!targetId.deviceId.empty()) { + Crypto::ConvertHexStringToBytes(addr.info.ble.udidHash, UDID_HASH_LEN, + targetId.deviceId.c_str(), targetId.deviceId.length()); + } + deviceInfo->addr[index] = addr; + deviceId = targetId.bleMac; + index++; + } else { + LOGE("AuthManager::ParseConnectAddr failed, not addr."); + return ERR_DM_INPUT_PARA_INVALID; + } + + deviceInfo->addrNum = static_cast(index); + if (context_->softbusConnector->AddMemberToDiscoverMap(deviceId, deviceInfo) != DM_OK) { + LOGE("AuthManager::ParseConnectAddr failed, AddMemberToDiscoverMap failed."); + return ERR_DM_INPUT_PARA_INVALID; + } + deviceInfo = nullptr; + return DM_OK; +} + +void AuthManager::SetAuthType(int32_t authType) +{ + context_->authType = (DmAuthType)authType; +} + +bool AuthManager::IsAuthTypeSupported(const int32_t &authType) +{ + if (context_->authenticationMap.find(authType) == context_->authenticationMap.end()) { + LOGE("IsAuthTypeSupported failed, authType is not supported."); + return false; + } + return true; +} + +bool AuthManager::IsAuthCodeReady(const std::string &sessionName) +{ + if (context_->importAuthCode.empty() || context_->importSessionName.empty()) { + LOGE("AuthManager::IsAuthCodeReady, auth code not ready."); + return false; + } + if (sessionName != context_->importSessionName) { + LOGE("IsAuthCodeReady failed, sessionName not supported."); + return false; + } + return true; +} + +int32_t AuthManager::CheckAuthParamVaild(const std::string &sessionName, int32_t authType, + const std::string &deviceId, const std::string &extra) +{ + LOGI("AuthManager::CheckAuthParamVaild start."); + if (authType < DM_AUTH_TYPE_MIN || authType > DM_AUTH_TYPE_MAX) { + LOGE("CheckAuthParamVaild failed, authType is illegal."); + return ERR_DM_AUTH_FAILED; + } + if (sessionName.empty() || deviceId.empty()) { + LOGE("AuthManager::CheckAuthParamVaild failed, sessionName is %{public}s, deviceId is %{public}s, extra is" + "%{public}s.", sessionName.c_str(), GetAnonyString(deviceId).c_str(), extra.c_str()); + return ERR_DM_INPUT_PARA_INVALID; + } + if (context_->listener == nullptr || context_->authUiStateMgr == nullptr) { + LOGE("AuthManager::CheckAuthParamVaild listener or authUiStateMgr is nullptr."); + return ERR_DM_INPUT_PARA_INVALID; + } + + if (!IsAuthTypeSupported(authType)) { + LOGE("AuthManager::CheckAuthParamVaild authType %{public}d not support.", authType); + context_->listener->OnAuthResult(context_->processInfo, context_->peerTargetId.deviceId, "", STATUS_DM_AUTH_DEFAULT, + ERR_DM_UNSUPPORTED_AUTH_TYPE); + context_->listener->OnBindResult(context_->processInfo, context_->peerTargetId, + ERR_DM_UNSUPPORTED_AUTH_TYPE, STATUS_DM_AUTH_DEFAULT, ""); + return ERR_DM_UNSUPPORTED_AUTH_TYPE; + } + + if (!context_->softbusConnector->HaveDeviceInMap(deviceId)) { + LOGE("CheckAuthParamVaild failed, the discoveryDeviceInfoMap_ not have this device."); + context_->listener->OnAuthResult(context_->processInfo, context_->peerTargetId.deviceId, "", + STATUS_DM_AUTH_DEFAULT, ERR_DM_INPUT_PARA_INVALID); + context_->listener->OnBindResult(context_->processInfo, context_->peerTargetId, + ERR_DM_INPUT_PARA_INVALID, STATUS_DM_AUTH_DEFAULT, ""); + return ERR_DM_INPUT_PARA_INVALID; + } + + if ((authType == AUTH_TYPE_IMPORT_AUTH_CODE) && (!IsAuthCodeReady(sessionName))) { + LOGE("Auth code not exist."); + context_->listener->OnAuthResult(context_->processInfo, context_->peerTargetId.deviceId, "", + STATUS_DM_AUTH_DEFAULT, ERR_DM_INPUT_PARA_INVALID); + context_->listener->OnBindResult(context_->processInfo, context_->peerTargetId, + ERR_DM_INPUT_PARA_INVALID, STATUS_DM_AUTH_DEFAULT, ""); + return ERR_DM_INPUT_PARA_INVALID; + } + return DM_OK; +} + +void AuthManager::ParseHmlInfoInJsonObject(nlohmann::json jsonObject) +{ + if (IsString(jsonObject, PARAM_KEY_CONN_SESSIONTYPE)) { + context_->connSessionType = jsonObject[PARAM_KEY_CONN_SESSIONTYPE].get(); + LOGI("connSessionType %{public}s", context_->connSessionType.c_str()); + } + if (!IsHmlSessionType(context_->connSessionType)) { + return; + } + context_->connDelayCloseTime = HML_SESSION_TIMEOUT; + if (IsBool(jsonObject, PARAM_KEY_HML_ENABLE_160M)) { + context_->hmlEnable160M = jsonObject[PARAM_KEY_HML_ENABLE_160M].get(); + LOGI("hmlEnable160M %{public}d", context_->hmlEnable160M); + } + if (IsInt32(jsonObject, PARAM_KEY_HML_ACTIONID)) { + context_->hmlActionId = jsonObject[PARAM_KEY_HML_ACTIONID].get(); + if (context_->hmlActionId <= 0) { + context_->hmlActionId = 0; + } + LOGI("hmlActionId %{public}d", context_->hmlActionId); + } + + return; +} + +std::string AuthManager::GetBundleName(nlohmann::json &jsonObject) +{ + if (!jsonObject.is_discarded() && IsString(jsonObject, BUNDLE_NAME_KEY)) { + return jsonObject[BUNDLE_NAME_KEY].get(); + } + bool isSystemSA = false; + std::string bundleName; + AppManager::GetInstance().GetCallerName(isSystemSA, bundleName); + return bundleName; +} + +void AuthManager::ParseJsonObject(nlohmann::json jsonObject) +{ + if (jsonObject.is_discarded()) { + return; + } + + // 填充context_ + if (IsString(jsonObject, APP_OPERATION_KEY)) { + context_->appOperation = jsonObject[APP_OPERATION_KEY].get(); + } + if (IsString(jsonObject, CUSTOM_DESCRIPTION_KEY)) { + context_->customData = jsonObject[CUSTOM_DESCRIPTION_KEY].get(); + } + if (IsString(jsonObject, APP_THUMBNAIL)) { + context_->appThumbnail = jsonObject[APP_THUMBNAIL].get(); + } + context_->connDelayCloseTime = 0; + if (IsString(jsonObject, PARAM_CLOSE_SESSION_DELAY_SECONDS)) { + std::string delaySecondsStr = jsonObject[PARAM_CLOSE_SESSION_DELAY_SECONDS].get(); + context_->connDelayCloseTime = GetCloseSessionDelaySeconds(delaySecondsStr); + } + + // 填充context_->accesser + if (IsInt32(jsonObject, TAG_BIND_LEVEL)) { + context_->accesser.bindLevel = jsonObject[TAG_BIND_LEVEL].get(); + } + context_->accesser.bundleName = GetBundleName(jsonObject); + + // 填充context_accessee + if (IsString(jsonObject, TAG_PEER_BUNDLE_NAME)) { + context_->accessee.bundleName = jsonObject[TAG_PEER_BUNDLE_NAME].get(); + if (context_->accessee.bundleName == "") { + context_->accessee.bundleName = context_->sessionName; + } + LOGI("ParseJsonObject accessee bundleName = %{public}s", context_->accessee.bundleName.c_str()); + } else { + context_->accessee.bundleName = context_->sessionName; + } + if (IsInt32(jsonObject, DM_TAG_PEER_USER_ID)) { + context_->accessee.userId = jsonObject[DM_TAG_PEER_USER_ID].get(); + } + if (IsInt32(jsonObject, DM_TAG_PEER_DISPLAY_ID)) { + context_->accessee.displayId = jsonObject[DM_TAG_PEER_DISPLAY_ID].get(); + } + + ParseHmlInfoInJsonObject(jsonObject); + return; +} + +int32_t AuthManager::GetBindLevel(int32_t bindLevel) +{ +#ifdef DEVICE_MANAGER_COMMON_FLAG + LOGI("device_manager_common is true!"); + std::string processName = ""; + int32_t ret = AppManager::GetInstance().GetCallerProcessName(processName); + LOGI("GetBindLevel processName = %{public}s", GetAnonyString(processName).c_str()); + if (ret == DM_OK && CheckProcessNameInWhiteList(processName)) { + return DEVICE; + } +#endif + if (IsAllowDeviceBind()) { + if (static_cast(bindLevel) == INVALIED_TYPE || static_cast(bindLevel) > APP || + static_cast(bindLevel) < DEVICE) { + return DEVICE; + } + return bindLevel; + } + if (static_cast(bindLevel) == INVALIED_TYPE || (static_cast(bindLevel) != APP && + static_cast(bindLevel) != SERVICE)) { + return APP; + } + return bindLevel; +} + +int32_t AuthManager::GetTokenIdByBundleName(int32_t userId, std::string &bundleName, int64_t &tokenId) +{ + int32_t ret = AppManager::GetInstance().GetNativeTokenIdByName(bundleName, tokenId); + if (ret == DM_OK) { + return DM_OK; + } + ret = AppManager::GetInstance().GetHapTokenIdByName(userId, bundleName, 0, tokenId); + if (ret != DM_OK) { + LOGE("get tokenId by bundleName failed %{public}s", GetAnonyString(bundleName).c_str()); + } + return ret; +} + +void AuthManager::GetAuthParam(const std::string &sessionName, int32_t authType, + const std::string &deviceId, const std::string &extra) +{ + LOGI("Get auth param."); + char localDeviceId[DEVICE_UUID_LENGTH] = {0}; + GetDevUdid(localDeviceId, DEVICE_UUID_LENGTH); + std::string localUdid = std::string(localDeviceId); + std::string realPkgName = GetSubStr(sessionName, PICKER_PROXY_SPLIT, 1); + realPkgName = realPkgName.empty() ? sessionName : realPkgName; + context_->sessionName = sessionName; + context_->pkgLabel = GetBundleLable(sessionName); + context_->authType = (DmAuthType)authType; + context_->accesser.deviceName = context_->softbusConnector->GetLocalDeviceName(); + context_->accesser.deviceType = context_->softbusConnector->GetLocalDeviceTypeId(); + context_->accesser.deviceId = localUdid; + uint32_t tokenId = 0 ; + MultipleUserConnector::GetTokenIdAndForegroundUserId(tokenId, context_->accesser.userId); + context_->accesser.tokenId = static_cast(tokenId); + if (realPkgName != sessionName) { + int64_t tmpTokenId = 0; + GetTokenIdByBundleName(context_->accesser.userId, realPkgName, tmpTokenId); + context_->accesser.tokenId = static_cast(tmpTokenId); + } + context_->accesser.accountId = MultipleUserConnector::GetOhosAccountIdByUserId(context_->accesser.userId); + context_->accesser.isOnline = false; + context_->accesser.isAuthed = !context_->accesser.bindType.empty(); + context_->accesser.bindLevel = INVALIED_TYPE; + + context_->accessee.deviceId = deviceId; + context_->accessee.addr = deviceId; + nlohmann::json jsonObject = nlohmann::json::parse(extra, nullptr, false); + if (jsonObject.is_discarded()) { + LOGE("extra string not a json type."); + return; + } + ParseJsonObject(jsonObject); + + context_->accesser.token = std::to_string(GenRandInt(MIN_PIN_TOKEN, MAX_PIN_TOKEN)); + context_->accesser.bindLevel = this->GetBindLevel(context_->accesser.bindLevel); +} + +void AuthManager::InitAuthState(const std::string &sessionName, int32_t authType, + const std::string &deviceId, const std::string &extra) +{ + auto iter = context_->authenticationMap.find(authType); + if (iter != context_->authenticationMap.end()) { + context_->authPtr = iter->second; + } + + // if (authType > AUTH_TYPE_IMPORT_AUTH_CODE || authType < AUTH_TYPE_PIN) { + // LOGE("AuthManager::InitAuthState invalid authType"); + // return; + // } + + if (context_->timer == nullptr) { + context_->timer = std::make_shared(); + } + context_->timer->StartTimer(std::string(AUTHENTICATE_TIMEOUT_TASK), + DmAuthState::GetTaskTimeout(context_, AUTHENTICATE_TIMEOUT_TASK, AUTHENTICATE_TIMEOUT), [this] (std::string name) { + DmAuthState::HandleAuthenticateTimeout(context_, name); + }); + context_->authMessageProcessor = std::make_shared(); + GetAuthParam(sessionName, authType, deviceId, extra); + context_->authStateMachine = std::make_shared(context_); + context_->authStateMachine->TransitionTo(std::make_shared()); + LOGI("AuthManager::AuthenticateDevice complete"); + + return; +} + +int32_t AuthManager::AuthenticateDevice(const std::string &sessionName, int32_t authType, + const std::string &deviceId, const std::string &extra) +{ + LOGI("AuthManager::AuthenticateDevice start auth type %{public}d.", authType); + SetAuthType(authType); + int32_t userId = -1; + MultipleUserConnector::GetCallerUserId(userId); + context_->processInfo.pkgName = sessionName; + context_->processInfo.userId = userId; + int32_t ret = CheckAuthParamVaild(sessionName, authType, deviceId, extra); + if (ret != DM_OK) { + LOGE("AuthManager::AuthenticateDevice failed, param is invaild."); + return ret; + } + ret = CheckAuthParamVaildExtra(extra); + if (ret != DM_OK) { + LOGE("CheckAuthParamVaildExtra failed, param is invaild."); + return ret; + } + context_->isAuthenticateDevice = true; + // TODO: 当前已经没有AUTH_TYPE_CRE类型,待确认 + // if (authType == AUTH_TYPE_CRE) { + // LOGI("AuthManager::AuthenticateDevice for credential type, joinLNN directly."); + // context_->softbusConnector->JoinLnn(deviceId); + // context_->listener->OnAuthResult(context_->processInfo, context_->peerTargetId.deviceId, "", + // STATUS_DM_AUTH_DEFAULT, DM_OK); + // context_->listener->OnBindResult(context_->processInfo, context_->peerTargetId, + // DM_OK, STATUS_DM_AUTH_DEFAULT, ""); + // return DM_OK; + // } + InitAuthState(sessionName, authType, deviceId, extra); + return DM_OK; +} + +int32_t AuthManager::BindTarget(const std::string &sessionName, const PeerTargetId &targetId, + const std::map &bindParam) +{ + LOGI("AuthManager::BindTarget start. sessionName: %{public}s", sessionName.c_str()); + for (auto iter = bindParam.begin(); iter != bindParam.end(); iter++) { + LOGI("AuthManager::BindTarget para: %{public}s : %{public}s ", iter->first.c_str(), iter->second.c_str()); + } + + struct RadarInfo info = { + .funcName = "AuthenticateDevice", + .stageRes = static_cast(StageRes::STAGE_SUCC), + .bizState = static_cast(BizState::BIZ_STATE_END), + }; + if (!DmRadarHelper::GetInstance().ReportDiscoverUserRes(info)) { + LOGE("ReportDiscoverUserRes failed"); + } + if (sessionName.empty()) { + LOGE("AuthManager::BindTarget failed, sessionName is empty."); + return ERR_DM_INPUT_PARA_INVALID; + } + int32_t authType = -1; + if (ParseAuthType(bindParam, authType) != DM_OK) { + LOGE("AuthManager::BindTarget failed, key: %{public}s error.", PARAM_KEY_AUTH_TYPE); + return ERR_DM_INPUT_PARA_INVALID; + } + context_->peerTargetId = targetId; + bindParam_ = bindParam; + std::string deviceId = ""; + std::string addrType; + if (bindParam.count(PARAM_KEY_CONN_ADDR_TYPE) != 0) { + addrType = bindParam.at(PARAM_KEY_CONN_ADDR_TYPE); + } + if (ParseConnectAddr(targetId, deviceId, addrType) == DM_OK) { + return AuthenticateDevice(sessionName, authType, deviceId, ParseExtraFromMap(bindParam)); + } else if (!targetId.deviceId.empty()) { + return AuthenticateDevice(sessionName, authType, targetId.deviceId, ParseExtraFromMap(bindParam)); + } else { + LOGE("AuthManager::BindTarget failed, targetId is error."); + return ERR_DM_INPUT_PARA_INVALID; + } +} + +AuthSinkManager::AuthSinkManager(std::shared_ptr softbusConnector, + std::shared_ptr listener, + std::shared_ptr hiChainAuthConnector) + : AuthManager(softbusConnector, listener, hiChainAuthConnector) +{ + context_->direction = DM_AUTH_SINK; +} + +void AuthSinkManager::OnSessionOpened(int32_t sessionId, int32_t sessionSide, int32_t result) +{ + LOGI("sessionId = %{public}d and sessionSide = %{public}d result = %{public}d", sessionId, sessionSide, result); + if (context_->authMessageProcessor == nullptr) { + // authMessage为空,开始初始化 + context_->authMessageProcessor = std::make_shared(); + context_->authStateMachine = std::make_shared(context_); + context_->sessionId = sessionId; + context_->timer = std::make_shared(); + context_->timer->StartTimer(std::string(AUTHENTICATE_TIMEOUT_TASK), + DmAuthState::GetTaskTimeout(context_, AUTHENTICATE_TIMEOUT_TASK, AUTHENTICATE_TIMEOUT), + [this] (std::string name) { DmAuthState::HandleAuthenticateTimeout(context_, name); + }); + context_->timer->StartTimer(std::string(WAIT_NEGOTIATE_TIMEOUT_TASK), + DmAuthState::GetTaskTimeout(context_, WAIT_NEGOTIATE_TIMEOUT_TASK, WAIT_NEGOTIATE_TIMEOUT), + [this] (std::string name) { DmAuthState::HandleAuthenticateTimeout(context_, name); + }); + } + + return; +} + +void AuthSinkManager::OnSessionClosed(int32_t sessionId) +{ + LOGI("AuthSrcManager::OnSessionClosed sessionId = %{public}d", sessionId); +} + +void AuthSinkManager::OnDataReceived(int32_t sessionId, std::string message) +{ + if (context_->authMessageProcessor == nullptr) { + LOGE("OnDataReceived failed, authMessageProcessor is nullptr."); + return; + } + + context_->sessionId = sessionId; + int32_t ret = context_->authMessageProcessor->ParseMessage(context_, message); + if (ret != DM_OK) { + LOGE("OnDataReceived failed, parse input message error."); + } + + return; +} + +bool AuthSinkManager::GetIsCryptoSupport() +{ + return false; +} + +void AuthSinkManager::OnAuthDeviceDataReceived(int32_t sessionId, std::string message) +{ + if (context_->hiChainAuthConnector == nullptr) { + LOGE("OnAuthDeviceDataReceived param is invalid"); + return; + } + + if (context_->sessionId != sessionId) { + LOGE("OnAuthDeviceDataReceived unmatched sessionId"); + return; + } + + nlohmann::json jsonObject = nlohmann::json::parse(message, nullptr, false); + if (jsonObject.is_discarded()) { + LOGE("DecodeRequestAuth jsonStr error"); + return; + } + if (!IsString(jsonObject, DM_TAG_DATA) || !IsInt32(jsonObject, DM_TAG_DATA_LEN) || + !IsInt32(jsonObject, TAG_MSG_TYPE)) { + LOGE("Auth device data is error."); + return; + } + LOGI("OnAuthDeviceDataReceived start msgType %{public}d.", jsonObject[TAG_MSG_TYPE].get()); + std::string authData = jsonObject[DM_TAG_DATA].get(); + int32_t osAccountId = MultipleUserConnector::GetCurrentAccountUserID(); + context_->hiChainAuthConnector->ProcessAuthData(context_->requestId, authData, osAccountId); + + return; +} + +void AuthManager::GetRemoteDeviceId(std::string &deviceId) +{ + deviceId = (context_->direction == DM_AUTH_SOURCE) ? context_->accessee.deviceId : context_->accesser.deviceId; + return; +} +int32_t AuthSinkManager::OnUserOperation(int32_t action, const std::string ¶ms) +{ + LOGI("AuthSinkManager::OnUserOperation start."); + if (context_ == nullptr || context_->authStateMachine == nullptr) { + LOGE("OnUserOperation: Authenticate is not start"); + return ERR_DM_AUTH_NOT_START; + } + + switch (action) { + case USER_OPERATION_TYPE_CANCEL_AUTH: + case USER_OPERATION_TYPE_ALLOW_AUTH: + case USER_OPERATION_TYPE_ALLOW_AUTH_ALWAYS: + context_->authResult = static_cast(action); + context_->reply = USER_OPERATION_TYPE_ALLOW_AUTH; + if (action == USER_OPERATION_TYPE_CANCEL_AUTH) { + LOGI("AuthSinkManager::OnUserOperation USER_OPERATION_TYPE_CANCEL_AUTH."); + context_->reply = USER_OPERATION_TYPE_CANCEL_AUTH; + } + context_->authStateMachine->NotifyEventFinish(DmEventType::ON_USER_OPERATION); + break; + case USER_OPERATION_TYPE_AUTH_CONFIRM_TIMEOUT: + LOGI("AuthSinkManager::OnUserOperation USER_OPERATION_TYPE_AUTH_CONFIRM_TIMEOUT."); + context_->authResult = USER_OPERATION_TYPE_AUTH_CONFIRM_TIMEOUT; + context_->reason = ERR_DM_TIME_OUT; + context_->authStateMachine->NotifyEventFinish(DmEventType::ON_FAIL); + break; + case USER_OPERATION_TYPE_CANCEL_PINCODE_DISPLAY: + LOGI("AuthSinkManager::OnUserOperation USER_OPERATION_TYPE_CANCEL_PINCODE_DISPLAY."); + context_->authResult = USER_OPERATION_TYPE_CANCEL_PINCODE_DISPLAY; + context_->reason = ERR_DM_BIND_USER_CANCEL_PIN_CODE_DISPLAY; + context_->authStateMachine->NotifyEventFinish(DmEventType::ON_FAIL); + break; + default: + LOGE("this action id not support"); + break; + } + LOGI("AuthSinkManager::OnUserOperation leave."); + return DM_OK; +} + +AuthSrcManager::AuthSrcManager(std::shared_ptr softbusConnector, + std::shared_ptr listener, + std::shared_ptr hiChainAuthConnector) + : AuthManager(softbusConnector, listener, hiChainAuthConnector) +{ + context_->direction = DM_AUTH_SOURCE; +} + +void AuthSrcManager::OnSessionOpened(int32_t sessionId, int32_t sessionSide, int32_t result) +{ + LOGI("sessionId = %{public}d and sessionSide = %{public}d result = %{public}d", sessionId, sessionSide, result); + + if (context_->authMessageProcessor == nullptr) { + context_->softbusConnector->GetSoftbusSession()->CloseAuthSession(sessionId); + LOGE("AuthSrcManager::OnSessionOpened but request state is wrong"); + return; + } + + context_->sessionId = sessionId; + context_->authStateMachine->TransitionTo(std::make_shared()); + struct RadarInfo info = { .funcName = "OnSessionOpened" }; + info.channelId = sessionId; + DmRadarHelper::GetInstance().ReportAuthSendRequest(info); + + return; +} + +void AuthSrcManager::OnSessionClosed(int32_t sessionId) +{ + LOGI("AuthSrcManager::OnSessionClosed sessionId = %{public}d", sessionId); +} +void AuthSrcManager::OnDataReceived(int32_t sessionId, std::string message) +{ + if (context_->authMessageProcessor == nullptr) { + LOGE("OnDataReceived failed, authMessageProcessor is nullptr."); + return; + } + + context_->sessionId = sessionId; + int32_t ret = context_->authMessageProcessor->ParseMessage(context_, message); + if (ret != DM_OK) { + LOGE("OnDataReceived failed, parse input message error."); + } + + return; +} +bool AuthSrcManager::GetIsCryptoSupport() +{ + return false; +} +void AuthSrcManager::OnAuthDeviceDataReceived(int32_t sessionId, std::string message) +{ + if (context_->hiChainAuthConnector == nullptr) { + LOGE("OnAuthDeviceDataReceived param is invalid"); + return; + } + + if (context_->sessionId != sessionId) { + LOGE("OnAuthDeviceDataReceived unmatched sessionId"); + return; + } + + nlohmann::json jsonObject = nlohmann::json::parse(message, nullptr, false); + if (jsonObject.is_discarded()) { + LOGE("DecodeRequestAuth jsonStr error"); + return; + } + if (!IsString(jsonObject, DM_TAG_DATA) || !IsInt32(jsonObject, DM_TAG_DATA_LEN) || + !IsInt32(jsonObject, TAG_MSG_TYPE)) { + LOGE("Auth device data is error."); + return; + } + LOGI("OnAuthDeviceDataReceived start msgType %{public}d.", jsonObject[TAG_MSG_TYPE].get()); + std::string authData = jsonObject[DM_TAG_DATA].get(); + int32_t osAccountId = MultipleUserConnector::GetCurrentAccountUserID(); + context_->hiChainAuthConnector->ProcessAuthData(context_->requestId, authData, osAccountId); + + return; +} + +int32_t AuthSrcManager::OnUserOperation(int32_t action, const std::string ¶ms) +{ + LOGI("AuthSrcManager::OnUserOperation start."); + if (context_ == nullptr || context_->authStateMachine == nullptr) { + LOGE("OnUserOperation: Authenticate is not start"); + return ERR_DM_AUTH_NOT_START; + } + + switch (action) { + case USER_OPERATION_TYPE_CANCEL_PINCODE_INPUT: + LOGE("AuthSrcManager OnUserOperation user cancel"); + context_->pinInputResult = USER_OPERATION_TYPE_CANCEL_PINCODE_INPUT; + context_->reason = ERR_DM_BIND_USER_CANCEL_ERROR; + context_->authStateMachine->NotifyEventFinish(DmEventType::ON_FAIL); + break; + case USER_OPERATION_TYPE_DONE_PINCODE_INPUT: + LOGE("AuthSrcManager OnUserOperation user input done"); + context_->pinInputResult = USER_OPERATION_TYPE_DONE_PINCODE_INPUT; + context_->pinCode = std::atoi(params.c_str()); + context_->authStateMachine->NotifyEventFinish(DmEventType::ON_USER_OPERATION); + break; + default: + LOGE("this action id not support"); + break; + } + LOGI("AuthSrcManager::OnUserOperation leave."); + return DM_OK; +} + +void AuthSrcManager::AuthDeviceError(int64_t requestId, int32_t errorCode) +{ + LOGI("AuthSrcManager::AuthDeviceError start."); + auto curState = context_->authStateMachine->GetCurState(); + if (curState == DmAuthStateType::AUTH_SRC_PIN_AUTH_START_STATE || + curState == DmAuthStateType::AUTH_SRC_PIN_AUTH_MSG_NEGOTIATE_STATE || + curState == DmAuthStateType::AUTH_SRC_PIN_AUTH_DONE_STATE) { + LOGI("AuthSrcManager::AuthDeviceError Auth pin err."); + #ifndef NEW_PIN_STATE // todo del + if (context_->authType == DmAuthType::AUTH_TYPE_PIN) { + context_->inputPinAuthFailTimes++; + } else if (!context_->pinNegotiateStarted) { + LOGI("AuthSrcManager::AuthDeviceError fallback to input pin."); + context_->pinNegotiateStarted = true; + } else { + context_->inputPinAuthFailTimes++; + } + + // 失败 MAX_AUTH_FAIL_TIMES 次后,走认证失败 ON_FAIL + if (context_->inputPinAuthFailTimes >= MAX_AUTH_FAIL_TIMES) { + LOGI("AuthSrcManager::AuthDeviceError Auth pin err fail."); + context_->authStateMachine->NotifyEventFinish(DmEventType::ON_FAIL); + } else { + // Notify ON_ERROR 事件,对应 Action 内会当正常重试处理,而非失败 + context_->authStateMachine->NotifyEventFinish(DmEventType::ON_ERROR); + // 回退状态到 AuthSrcPinAuthStartState + context_->authStateMachine->TransitionTo(std::make_shared()); + LOGI("AuthSrcManager::AuthDeviceError Auth pin err, will retry."); + } + #else + if (context_->authType == DmAuthType::AUTH_TYPE_PIN) { + context_->inputPinAuthFailTimes++; + } + context_->authStateMachine->NotifyEventFinish(DmEventType::ON_ERROR); + context_->authStateMachine->TransitionTo(std::make_shared()); + #endif + } + LOGI("AuthSrcManager::AuthDeviceError leave."); +} + +void AuthSinkManager::AuthDeviceError(int64_t requestId, int32_t errorCode) +{ + LOGI("AuthSinkManager::AuthDeviceError start."); + auto curState = context_->authStateMachine->GetCurState(); + if (curState == DmAuthStateType::AUTH_SINK_PIN_AUTH_START_STATE || + curState == DmAuthStateType::AUTH_SINK_PIN_AUTH_MSG_NEGOTIATE_STATE) { + + #ifndef NEW_PIN_STATE // todo del + if (context_->authType == DmAuthType::AUTH_TYPE_PIN) { + context_->inputPinAuthFailTimes++; + } else if (!context_->pinNegotiateStarted) { + LOGI("AuthSinkManager::AuthDeviceError fallback to input pin."); + context_->pinNegotiateStarted = true; + // 生成PIN码 + AuthSinkStatePinAuthComm::GeneratePincode(context_); + // 显示PIN码 + if (AuthSinkStatePinAuthComm::ShowAuthInfoDialog(context_) != DM_OK) { + LOGI("ShowAuthInfoDialog err."); + context_->reason = ERR_DM_BIND_USER_CANCEL; + context_->authStateMachine->NotifyEventFinish(DmEventType::ON_FAIL); + } + } else { + context_->inputPinAuthFailTimes++; + } + // 失败 MAX_AUTH_FAIL_TIMES 次后,走认证失败 ON_FAIL + if (context_->inputPinAuthFailTimes >= MAX_AUTH_FAIL_TIMES) { + LOGI("AuthSinkManager::AuthDeviceError Auth pin err fail."); + context_->reason = ERR_DM_INPUT_PARA_INVALID; + context_->authStateMachine->NotifyEventFinish(DmEventType::ON_FAIL); + } else { + // Notify ON_ERROR 事件,对应 Action 内会当正常重试处理,而非失败 + + context_->authStateMachine->NotifyEventFinish(DmEventType::ON_ERROR); + // 将由新收到的120报文触发回退状态到 AuthSinkPinAuthStartState + LOGI("AuthSinkManager::AuthDeviceError Auth pin err, will retry."); + } + #else + if (context_->authType == DmAuthType::AUTH_TYPE_PIN) { + context_->inputPinAuthFailTimes++; + } + context_->authStateMachine->NotifyEventFinish(DmEventType::ON_ERROR); + context_->authStateMachine->TransitionTo(std::make_shared()); + #endif + } + LOGI("AuthSinkManager::AuthDeviceError leave."); +} + +bool AuthSrcManager::AuthDeviceTransmit(int64_t requestId, const uint8_t *data, uint32_t dataLen) +{ + LOGI("AuthSrcManager::AuthDeviceTransmit start."); + // check request id first + if (requestId != context_->requestId) { + LOGE("AuthSrcManager::onTransmit requestId %{public}" PRId64"is error.", requestId); + return false; + } + + context_->transmitData = std::string(reinterpret_cast(data), dataLen); + context_->authStateMachine->NotifyEventFinish(ON_TRANSMIT); + LOGI("AuthSrcManager::AuthDeviceTransmit leave."); + return true; +} + +bool AuthSinkManager::AuthDeviceTransmit(int64_t requestId, const uint8_t *data, uint32_t dataLen) +{ + LOGI("AuthSinkManager::AuthDeviceTransmit start."); + // check request id first + if (requestId != context_->requestId) { + LOGE("AuthSinkManager::onTransmit requestId %{public}" PRId64"is error.", requestId); + return false; + } + + context_->transmitData = std::string(reinterpret_cast(data), dataLen); + context_->authStateMachine->NotifyEventFinish(ON_TRANSMIT); + LOGI("AuthSinkManager::AuthDeviceTransmit leave."); + return true; +} +void AuthSrcManager::AuthDeviceFinish(int64_t requestId) +{ + LOGI("AuthSrcManager::AuthDeviceFinish start."); + context_->authStateMachine->NotifyEventFinish(ON_FINISH); + // 根据当前状态进行业务处理 + DmAuthStateType curState = context_->authStateMachine->GetCurState(); + switch (curState) { + case DmAuthStateType::AUTH_SRC_PIN_AUTH_DONE_STATE: + // ON_FINISH事件到来,启动凭据交换 + context_->authStateMachine->TransitionTo(std::make_shared()); + break; + default: + break; + } + LOGI("AuthSrcManager::AuthDeviceFinish leave."); +} + +void AuthSinkManager::AuthDeviceFinish(int64_t requestId) +{ + LOGI("AuthSinkManager::AuthDeviceFinish start."); + context_->authStateMachine->NotifyEventFinish(ON_FINISH); + LOGI("AuthSinkManager::AuthDeviceFinish leave."); +} + +void AuthSinkManager::AuthDeviceSessionKey(int64_t requestId, const uint8_t *sessionKey, uint32_t sessionKeyLen) +{ + LOGI("AuthSrcManager::AuthDeviceSessionKey start. keyLen: %{public}u", sessionKeyLen); + if (context_ == nullptr || context_->authMessageProcessor == nullptr || context_->authStateMachine == nullptr) { + LOGE("AuthSrcManager::AuthDeviceSessionKey failed, auth context not initial."); + return; + } + if (requestId != context_->requestId) { + LOGE("AuthSrcManager::onTransmit requestId %{public}" PRId64 "is error.", requestId); + return; + } + int32_t ret = context_->authMessageProcessor->SaveSessionKey(sessionKey, sessionKeyLen); + if (ret != DM_OK) { + LOGE("AuthSrcManager::AuthDeviceSessionKey, save session key error, ret: %{public}d", ret); + } + + // 通知ON_SESSION_KEY_RETURNED事件完成 + context_->authStateMachine->NotifyEventFinish(ON_SESSION_KEY_RETURNED); +} + +char *AuthSinkManager::AuthDeviceRequest(int64_t requestId, int operationCode, const char *reqParams) +{ + LOGI("AuthSrcManager::AuthDeviceRequest start"); + (void)requestId; + (void)reqParams; + nlohmann::json jsonObj; + + DmAuthStateType curState = context_->authStateMachine->GetCurState(); + if (curState == DmAuthStateType::AUTH_SINK_PIN_AUTH_START_STATE) { + int32_t pinCode = INVALID_PINCODE; + if (GetPinCode(pinCode) == ERR_DM_FAILED || pinCode == INVALID_PINCODE) { + jsonObj[FIELD_CONFIRMATION] = RequestResponse::REQUEST_REJECTED; + } else { + jsonObj[FIELD_CONFIRMATION] = RequestResponse::REQUEST_ACCEPTED; + jsonObj[FIELD_PIN_CODE] = std::to_string(pinCode); + } + } else if (curState == DmAuthStateType::AUTH_SINK_CREDENTIAL_AUTH_START_STATE) { + if (context_->isOnline) { // 非首次认证 + jsonObj[FIELD_CONFIRMATION] = RequestResponse::REQUEST_ACCEPTED; + jsonObj[FIELD_CRED_ID] = context_->accessee.appCredentialId; + } else if (!context_->isAppCredentialVerified) { // 首次认证 && 应用凭据认证 + jsonObj[FIELD_CONFIRMATION] = RequestResponse::REQUEST_ACCEPTED; + jsonObj[FIELD_CRED_ID] = context_->accessee.appCredentialId; + } else { // 首次认证 && 用户凭据认证 + jsonObj[FIELD_CONFIRMATION] = RequestResponse::REQUEST_ACCEPTED; + jsonObj[FIELD_CRED_ID] = context_->accessee.userCredentialId; + } + } + jsonObj[FIELD_SERVICE_PKG_NAME] = std::string(DM_PKG_NAME); + std::string jsonStr = SafetyDump(jsonObj); + char *buffer = strdup(jsonStr.c_str()); + return buffer; +} + +int32_t AuthManager::GetPinCode(int32_t &code) +{ + if (context_ == nullptr) { + LOGE("AuthManager failed to GetPinCode because context_ is nullptr"); + return ERR_DM_FAILED; + } + LOGI("GetPinCode called."); + code = context_->pinCode; + return DM_OK; +} + +// 重新获取BindParams,以重建链路,一般用于新老协议对象切换 +void AuthManager::GetBindTargetParams(std::string &pkgName, PeerTargetId &targetId, + std::map &bindParam) +{ + pkgName = context_->sessionName; + targetId = context_->peerTargetId; + bindParam = bindParam_; + + LOGI("AuthManager::GetBindTargetParams get pkgName %{public}s to reuse", pkgName.c_str()); + return; +} + +} // namespace DistributedHardware +} // namespace OHOS \ No newline at end of file diff --git a/services/implementation/src/authentication_v2/auth_stages/auth_acl.cpp b/services/implementation/src/authentication_v2/auth_stages/auth_acl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a4026043495378413e7a5638b454e29f1f296419 --- /dev/null +++ b/services/implementation/src/authentication_v2/auth_stages/auth_acl.cpp @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "dm_auth_state.h" + +#include +#include + +#include "deviceprofile_connector.h" +#include "dm_auth_context.h" +#include "dm_constants.h" +namespace OHOS { +namespace DistributedHardware { + +/* +数据同步,ACL老化与保存(180、190和200报文处理) +source端状态: +AuthSrcDataSyncState, // 触发Onfinish回调事件,发送180报文 +AuthSrcFinishState, // 收到190报文,发送200报文 + +sink端状态: +AuthSinkDataSyncState, // 收到180同步报文,发送190报文 +AuthSinkFinishState, // 收到200结束报文 + +*/ +const int32_t USLEEP_TIME_US_500000 = 500000; // 500ms +// 收到180同步报文,发送190报文 +int32_t AuthSinkDataSyncState::Action(std::shared_ptr context) +{ + LOGI("AuthSinkDataSyncState::Action start"); + // 判断密文阶段和明文阶段的四元组是否相同,不同则直接结束 + bool isSame = context->encryAccesser.deviceId == context->accesser.deviceId && + context->encryAccesser.userId == context->accesser.userId && + context->encryAccesser.accountId == context->accesser.accountId && + context->encryAccesser.tokenId == context->accesser.tokenId; + if (!isSame) { + LOGE("data between two stages different, stop auth"); + context->reply = DM_AUTHENTICATE_FINISH; + context->reason = ERR_DM_QUADRUPLE_NOT_SAME; + context->state = static_cast(GetStateType()); + return ERR_DM_FAILED; + } + // 查询sink端acl + std::vector profiles = + DeviceProfileConnector::GetInstance().GetAccessControlProfile(); + std::vector sinkAclList; + for (auto &item : profiles) { + if (item.GetAccesser().GetAccesserDeviceId() == context->accesser.deviceId && + item.GetAccesser().GetAccesserUserId() == context->accesser.userId && + item.GetAccessee().GetAccesseeDeviceId() == context->accessee.deviceId && + item.GetAccessee().GetAccesseeUserId() == context->accessee.userId) { + sinkAclList.push_back(item); // 打印并写入 + } + } + if (sinkAclList.empty()) { + LOGI("AuthSinkDataSyncState::Action acl is empty"); // 首次认证 无acl同步 + } + // 比较双端的acl + for (auto &sinkAcl : sinkAclList) { + std::string aclChecksum = context->authMessageProcessor->ChecksumAcl(sinkAcl); + auto item = find(context->encryAccesser.aclChecksumList.begin(), + context->encryAccesser.aclChecksumList.end(), aclChecksum); + if (item != context->encryAccesser.aclChecksumList.end()) { + continue; + } + SyncAclList(context, std::atoi(sinkAcl.GetAccessee().GetAccesseeAccountId().c_str()), + std::to_string(sinkAcl.GetAccessee().GetAccesseeCredentialId()), + sinkAcl.GetAccessee().GetAccesseeSessionKeyId(), sinkAcl.GetAccessControlId()); + } + // 保存本次acl + context->authMessageProcessor->PutAccessControlList(context, context->accessee, context->accesser.deviceId); + + // 同步本端的sp信息,不确定格式,暂不做 + + context->authMessageProcessor->CreateAndSendMsg(MSG_TYPE_RESP_DATA_SYNC, context); + LOGI("AuthSinkDataSyncState::Action ok"); + return DM_OK; +} + +DmAuthStateType AuthSinkDataSyncState::GetStateType() +{ + return DmAuthStateType::AUTH_SINK_DATA_SYNC_STATE; +} + +// 收到190报文,发送200报文 +int32_t AuthSrcFinishState::Action(std::shared_ptr context) +{ + LOGI("AuthSrcFinishState::Action start"); + // 判断密文阶段和明文阶段的四元组是否相同,不同则直接结束 + bool isSame = context->encryAccessee.deviceId == context->accessee.deviceId && + context->encryAccessee.userId == context->accessee.userId && + context->encryAccessee.accountId == context->accessee.accountId && + context->encryAccessee.tokenId == context->accessee.tokenId; + if (!isSame) { + LOGE("data between two stages different, stop auth"); + // 不同直接结束,发送200给sink端 + context->reason = ERR_DM_QUADRUPLE_NOT_SAME; + context->reply = DM_AUTHENTICATE_FINISH; + context->state = static_cast(GetStateType()); + context->authMessageProcessor->CreateAndSendMsg(MSG_TYPE_AUTH_FINISH, context); + return ERR_DM_FAILED; + } + // 查询sink端acl + std::vector profiles = + DeviceProfileConnector::GetInstance().GetAccessControlProfile(); + std::vector srcAclList; + for (auto &item : profiles) { + if (item.GetAccesser().GetAccesserDeviceId() == context->accesser.deviceId && + item.GetAccesser().GetAccesserUserId() == context->accesser.userId && + item.GetAccessee().GetAccesseeDeviceId() == context->accessee.deviceId && + item.GetAccessee().GetAccesseeUserId() == context->accessee.userId) { + srcAclList.push_back(item); // 打印并写入 + } + } + if (srcAclList.empty()) { + LOGI("AuthSrcFinishState::Action acl is empty"); // 首次认证 无acl同步 + } + // 比较双端的acl + for (auto &srcAcl : srcAclList) { + std::string aclChecksum = context->authMessageProcessor->ChecksumAcl(srcAcl); + auto item = find(context->encryAccessee.aclChecksumList.begin(), + context->encryAccessee.aclChecksumList.end(), aclChecksum); + if (item != context->encryAccessee.aclChecksumList.end()) { + continue; + } + SyncAclList(context, std::atoi(srcAcl.GetAccesser().GetAccesserAccountId().c_str()), + std::to_string(srcAcl.GetAccesser().GetAccesserCredentialId()), + srcAcl.GetAccesser().GetAccesserSessionKeyId(), srcAcl.GetAccessControlId()); + } + // 保存本次acl + context->authMessageProcessor->PutAccessControlList(context, context->accesser, context->accessee.deviceId); + // 同步本端的sp信息,不确定格式,暂不做 + + // 触发组网 + if (!context->accesser.isOnline) { + context->softbusConnector->JoinLnn(context->accessee.deviceId); + } + context->reason = DM_OK; + context->reply = DM_AUTHENTICATE_FINISH; + context->state = static_cast(GetStateType()); + context->authMessageProcessor->CreateAndSendMsg(MSG_TYPE_AUTH_FINISH, context); + LOGI("AuthSrcFinishState::Action ok"); + SourceFinish(context); + return DM_OK; +} + +DmAuthStateType AuthSrcFinishState::GetStateType() +{ + return DmAuthStateType::AUTH_SRC_FINISH_STATE; +} + +void AuthSrcFinishState::SourceFinish(std::shared_ptr context) +{ + context->authStateMachine = nullptr; + context->authUiStateMgr = nullptr; + context->hiChainAuthConnector = nullptr; + context->authMessageProcessor = nullptr; + usleep(USLEEP_TIME_US_500000); // 500ms + context->softbusConnector->GetSoftbusSession()->CloseAuthSession(context->sessionId); + context->softbusConnector = nullptr; + context->listener = nullptr; + context->authPtr = nullptr; + context->timer->DeleteAll(); + context->timer = nullptr; + context = nullptr; +} + +// 收到200结束报文 +int32_t AuthSinkFinishState::Action(std::shared_ptr context) +{ + LOGI("AuthSinkFinishState::Action start"); + SinkFinish(context); + LOGI("AuthSinkFinishState::Action ok"); + return DM_OK; +} + +DmAuthStateType AuthSinkFinishState::GetStateType() +{ + return DmAuthStateType::AUTH_SINK_FINISH_STATE; +} + +void AuthSinkFinishState::SinkFinish(std::shared_ptr context) +{ + context->authStateMachine = nullptr; + context->authUiStateMgr = nullptr; + context->hiChainAuthConnector = nullptr; + context->authMessageProcessor = nullptr; + context->softbusConnector = nullptr; + context->listener = nullptr; + context->authPtr = nullptr; + context->timer->DeleteAll(); + context->timer = nullptr; + context = nullptr; +} +} // namespace DistributedHardware +} // namespace OHOS \ No newline at end of file diff --git a/services/implementation/src/authentication_v2/auth_stages/auth_confirm.cpp b/services/implementation/src/authentication_v2/auth_stages/auth_confirm.cpp new file mode 100644 index 0000000000000000000000000000000000000000..07295dbe43ac30271ef579a26124da31afc6ba25 --- /dev/null +++ b/services/implementation/src/authentication_v2/auth_stages/auth_confirm.cpp @@ -0,0 +1,386 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "dm_auth_state.h" +// #include "service_info_profile.h" +#include "dm_auth_context.h" +#include "dm_log.h" +#include "dm_dialog_manager.h" +#include "dm_anonymous.h" +#include "dm_auth_state_machine.h" +#include "deviceprofile_connector.h" +#include "auth_manager.h" +#undef LOG_TAG +#define LOG_TAG "DHDM_V2" + +namespace OHOS { +namespace DistributedHardware { + +constexpr const char* TAG_APP_OPERATION = "APPOPERATION"; +constexpr const char* TAG_CUSTOM_DESCRIPTION = "CUSTOMDESC"; +constexpr const char* TAG_LOCAL_DEVICE_TYPE = "LOCALDEVICETYPE"; +constexpr const char* TAG_REQUESTER = "REQUESTER"; +constexpr const char* TAG_HOST_PKGLABEL = "hostPkgLabel"; + +constexpr int32_t CONFIRM_TIMEOUT = 60; +std::set g_shareByPinAuthDeviceTypeSet{DmDeviceType::DEVICE_TYPE_SMART_DISPLAY}; + +/* +用户授权(100和110报文处理) +source端状态: +AuthSrcConfirmState, // 收到90授权结果报文,发送100报文 + +sink端状态: +AuthSinkConfirmState, // 收到100用户授权报文,发送110报文 +*/ + +DmAuthStateType AuthSrcConfirmState::GetStateType() +{ + return DmAuthStateType::AUTH_SRC_CONFIRM_STATE; +} + +int32_t AuthSrcConfirmState::DoPinAuth(std::shared_ptr context) +{ + LOGI("AuthSrcConfirmState::DoPinAuth start"); + int32_t authResult = context->authResult; + if (authResult != USER_OPERATION_TYPE_ALLOW_AUTH && + authResult != USER_OPERATION_TYPE_ALLOW_AUTH_ALWAYS) { + LOGE("AuthSrcConfirmState::DoPinAuth authResult not allow"); + context->reason = ERR_DM_BIND_USER_CANCEL; + return ERR_DM_BIND_USER_CANCEL; + } + + if (context->authTypeList.empty()) { + LOGE("AuthSrcConfirmState::DoPinAuth authTypeList empty"); + context->reason = ERR_DM_UNSUPPORTED_AUTH_TYPE; + return ERR_DM_UNSUPPORTED_AUTH_TYPE; + } + + context->currentAuthTypeIdx = 0; + context->authType = context->authTypeList[0]; + // 首次认证是输入PIN或超声PIN时,先授权 + if (context->authType == DmAuthType::AUTH_TYPE_PIN || context->authType == DmAuthType::AUTH_TYPE_PIN_ULTRASONIC) { + // send 100 + context->authMessageProcessor->CreateAndSendMsg(MSG_TYPE_REQ_USER_CONFIRM, context); + + context->timer->StartTimer(std::string(CONFIRM_TIMEOUT_TASK), + CONFIRM_TIMEOUT, [context] (std::string name) { + HandleAuthenticateTimeout(context, name); + }); + } else { + // 少一轮 100,110 + context->authStateMachine->TransitionTo(std::make_shared()); + } + LOGI("AuthSrcConfirmState::DoPinAuth end"); + return DM_OK; +} + +int32_t AuthSrcConfirmState::Action(std::shared_ptr context) +{ + LOGI("AuthSrcConfirmState::Action start"); + context->timer->DeleteTimer(std::string(NEGOTIATE_TIMEOUT_TASK)); + if (CompareVersion(context->accessee.dmVersion, std::string(DM_VERSION_5_1_0))) { + LOGE("AuthSrcConfirmState::Action incompatible version %{public}s compare to 5.1.0", + context->accessee.dmVersion.c_str()); + context->reason = ERR_DM_VERSION_INCOMPATIBLE; // todo 发104报文???应该finished状态处理 + return ERR_DM_VERSION_INCOMPATIBLE; + } +#if 0 // todo 有凭据情况 + nlohmann::json jsonObject = nlohmann::json::parse(context->accessee.credentialInfos, nullptr, false); + if (jsonObject.is_discarded()) { + LOGE("AuthSrcConfirmState::Action parse credentialInfos error"); + return ERR_DM_FAILED; + } + // 转结束绑定 + context->authStateMachine->TransitionTo(std::make_shared()); + + // 转凭据认证 + context->authStateMachine->TransitionTo(std::make_shared()); + + // 有无可信关系的分享凭据 + if (g_shareByPinAuthDeviceTypeSet.contains(static_cast(context->deviceType))) { + // 走PIN码认证 + return DoPinAuth(context); + } else { + // 转凭据认证 + context->authStateMachine->TransitionTo(std::make_shared()); + } + + // 有点对点可信 + // if (context->authType == DmAuthType::AUTH_TYPE_IMPORT_AUTH_CODE) { + if (!context->authTypeList.empty() && context->authTypeList[0] == DmAuthType::AUTH_TYPE_IMPORT_AUTH_CODE) { + // 走PIN码导入 + return DoPinAuth(context); + } else { + // 结束绑定 + context->authStateMachine->TransitionTo(std::make_shared()); + } + // 无凭据 + return DoPinAuth(context); +#else +#ifndef NEW_PIN_STATE // todo del + // todo del 无凭据 send 100 + context->authMessageProcessor->CreateAndSendMsg(MSG_TYPE_REQ_USER_CONFIRM, context); + + context->timer->StartTimer(std::string(CONFIRM_TIMEOUT_TASK), + CONFIRM_TIMEOUT, [context] (std::string name) { + HandleAuthenticateTimeout(context, name); + }); + LOGI("AuthSrcConfirmState::Action ok"); + return DM_OK; +#else + return DoPinAuth(context); +#endif +#endif +} + +DmAuthStateType AuthSinkConfirmState::GetStateType() +{ + return DmAuthStateType::AUTH_SINK_CONFIRM_STATE; +} + +int32_t AuthSinkConfirmState::ShowConfigDialog(std::shared_ptr context) +{ + LOGI("AuthSinkConfirmState::ShowConfigDialog start"); + + if (IsScreenLocked()) { + LOGE("AuthSinkConfirmState::ShowStartAuthDialog screen is locked."); + context->reason = ERR_DM_BIND_USER_CANCEL; + context->authStateMachine->NotifyEventFinish(DmEventType::ON_FAIL); + return STOP_BIND; + } + + nlohmann::json jsonObj; + jsonObj[TAG_CUSTOM_DESCRIPTION] = context->customData; + jsonObj[TAG_LOCAL_DEVICE_TYPE] = context->accesser.deviceType; + jsonObj[TAG_REQUESTER] = context->accesser.deviceName; + jsonObj[TAG_USER_ID] = context->accessee.userId; + jsonObj[TAG_HOST_PKGLABEL] = context->sessionName; + + const std::string params = SafetyDump(jsonObj); + DmDialogManager::GetInstance().ShowConfirmDialog(params); + + LOGI("AuthSinkConfirmState::ShowConfigDialog end"); + return DM_OK; +} +#if 0 // todo del 新的获取方法 根据客户端AuthType和BundleName从服务端SP表里查询业务注册的认证类型 +int32_t AuthSinkConfirmState::MatchAuthType(std::shared_ptr context) +{ + // DP 接口 查询ServiceInfoProfile + std::vector serviceInfos; + DistributedDeviceProfile::ServiceInfoUniqueKey key; + auto tokenId = std::to_string(context->accessee.tokenId); + key.SetUserId(context->accessee.userId); + key.SetDeviceId(context->accessee.deviceId); + key.SetTokenId(tokenId); + auto ret = DeviceProfileConnector::GetInstance().GetServiceInfoProfileListByTokenId(key, serviceInfos); + if (ret != DM_OK) { + LOGE("AuthSinkConfirmState::MatchAuthType GetServiceInfoByTokenId err %{public}d", ret); + // 获取不到走PIN认证方案 + if (context->authType != DmAuthType::AUTH_TYPE_PIN) { + LOGE("AuthSinkConfirmState::MatchAuthType AUTH_TYPE_PIN not match"); + return STOP_BIND; + } + return DM_OK; + } + + LOGI("AuthSinkConfirmState::Action GetServiceInfoByTokenId ret ok"); + + // 过滤掉 以下2个字段不为空(或0)的 serviceInfo + // serviceId 发布的服务ID,服务的唯一标识 + // serviceType 发布的服务类型 + std::vector filterServiceInfos; + for (auto& serviceInfo : serviceInfos) { + if (serviceInfo.GetServiceId() == 0 && serviceInfo.GetServiceType().empty()) { + filterServiceInfos.push_back(serviceInfo); + } + } + + // 期望有且仅有一条符合的 serviceInfo + if (filterServiceInfos.size() != 1) { + LOGE("AuthSinkConfirmState::MatchAuthType filterServiceInfo not unique"); + return STOP_BIND; + } + + auto& srvInfo = filterServiceInfos[0]; // 弹框用到 serviceInfo 中的内容? + + auto authBoxType = srvInfo.GetAuthBoxType(); + int32_t pinExchangeType = srvInfo.GetPinExchangeType(); + if (authBoxType == DistributedDeviceProfile::NUM_1) { // 三态框 + if (context->authType != DmAuthType::AUTH_TYPE_PIN) { + LOGE("AuthSinkConfirmState::MatchAuthType AUTH_TYPE_PIN not match"); + return STOP_BIND; + } + return DM_OK; + } else if (authBoxType == DistributedDeviceProfile::NUM_2) { + int32_t authResult = srvInfo.GetAuthType(); + if (authResult == 0) { + context->authResult = USER_OPERATION_TYPE_ALLOW_AUTH; + } else if (authResult == DistributedDeviceProfile::NUM_1) { + context->authResult = USER_OPERATION_TYPE_CANCEL_AUTH; + } else if (authResult == DistributedDeviceProfile::NUM_6) { + context->authResult = USER_OPERATION_TYPE_ALLOW_AUTH_ALWAYS; + } + + if (pinExchangeType == DistributedDeviceProfile::NUM_2) { // 超声交换PIN + if (context->authType != DmAuthType::AUTH_TYPE_PIN_ULTRASONIC) { + LOGE("AuthSinkConfirmState::MatchAuthType AUTH_TYPE_PIN_ULTRASONIC not match"); + return STOP_BIND; + } + return DM_OK; + } else if (pinExchangeType == DistributedDeviceProfile::NUM_3) { // 导入PIN + if (context->authType != DmAuthType::AUTH_TYPE_IMPORT_AUTH_CODE) { + LOGE("AuthSinkConfirmState::MatchAuthType AUTH_TYPE_IMPORT_AUTH_CODE not match"); + return STOP_BIND; + } + // 读取PIN码 + std::string pinCode = srvInfo.GetPinCode(); + context->pinCode = std::stoi(pinCode); + return DM_OK; + } + } + + LOGE("AuthSinkConfirmState::MatchAuthType authType not support"); + return STOP_BIND; +} +#else +int32_t AuthSinkConfirmState::MatchAuthType(std::shared_ptr context) +{ + context->authResult = USER_OPERATION_TYPE_ALLOW_AUTH; + return DM_OK; +} +#endif + +int64_t AuthSinkConfirmState::GenRequestId(std::shared_ptr context) +{ + uint64_t requestId = static_cast(context->sessionId); + requestId <<= 32; // 高32位为sessionId + requestId += static_cast(DmAuthStateType::AUTH_SINK_CONFIRM_STATE); // 低32位为状态编号 + return static_cast(requestId); +} + +int32_t AuthSinkConfirmState::Action(std::shared_ptr context) +{ +#ifdef NEW_PIN_STATE // todo 新状态流程,待测试 + LOGI("AuthSinkConfirmState::Action start"); + // 停止授权报文计时 + context->timer->DeleteTimer(std::string(WAIT_REQUEST_TIMEOUT_TASK)); + + if (context->authTypeList.empty()) { + LOGE("AuthSinkConfirmState::Action authTypeList empty"); + context->reason = ERR_DM_UNSUPPORTED_AUTH_TYPE; + return ERR_DM_UNSUPPORTED_AUTH_TYPE; + } + context->authType = context->authTypeList[context->currentAuthTypeIdx]; + + if (context->authBoxType == DistributedDeviceProfile::NUM_1) { // 三态框 + LOGI("AuthSinkConfirmState::Action 3box"); + // 拉起授权确认页面 + auto ret = ShowConfigDialog(context); + if (ret != DM_OK) { + return ret; + } + // 等待用户授权操作完成 + if(DmEventType::ON_USER_OPERATION != context->authStateMachine->WaitExpectEvent(DmEventType::ON_USER_OPERATION)) { + LOGE("AuthSinkConfirmState::Action wait ON_USER_OPERATION err"); + return STOP_BIND; // 外部事件错误,中止流程 + } + // 判断授权结果 + if (context->reply != USER_OPERATION_TYPE_ALLOW_AUTH) { + LOGI("AuthSinkConfirmState::Action USER_OPERATION_TYPE_CANCEL_AUTH"); + context->reason = ERR_DM_BIND_USER_CANCEL; + return STOP_BIND; // 用户取消授权 + } + } else if (context->authBoxType == DistributedDeviceProfile::NUM_2) { // 免弹框 + if (context->authResult == USER_OPERATION_TYPE_CANCEL_AUTH) { + LOGI("AuthSinkConfirmState::Action USER_OPERATION_TYPE_CANCEL_AUTH"); + context->reason = ERR_DM_BIND_USER_CANCEL; + return STOP_BIND; // 用户取消授权 + } + } else { + LOGE("AuthSinkConfirmState::Action authBoxType not support"); + context->reason = ERR_DM_UNSUPPORTED_AUTH_TYPE; + return ERR_DM_UNSUPPORTED_AUTH_TYPE; + } + + // 发送110报文 + context->authMessageProcessor->CreateAndSendMsg(MSG_TYPE_RESP_USER_CONFIRM, context); + + context->authStateMachine->TransitionTo(std::make_shared()); + + LOGI("AuthSinkConfirmState::Action ok"); + return DM_OK; + +#else // todo del + LOGI("AuthSinkConfirmState::Action start"); + // 停止授权报文计时 + context->timer->DeleteTimer(std::string(WAIT_REQUEST_TIMEOUT_TASK)); + context->requestId = GenRequestId(context); + auto ret = MatchAuthType(context); + if (ret != DM_OK) { + return ret; + } + + if (context->authType == DmAuthType::AUTH_TYPE_PIN) { // 三态框 + LOGI("AuthSinkConfirmState::Action AUTH_TYPE_PIN "); + // 拉起授权确认页面 + if ((ret = ShowConfigDialog(context)) != DM_OK) { + return ret; + } + // 等待用户授权操作完成 + if(DmEventType::ON_USER_OPERATION != context->authStateMachine->WaitExpectEvent(DmEventType::ON_USER_OPERATION)) { + LOGE("AuthSinkConfirmState::Action wait ON_USER_OPERATION err"); + return STOP_BIND; // 外部事件错误,中止流程 + } + // 判断授权结果 + if (context->reply == USER_OPERATION_TYPE_ALLOW_AUTH) { + LOGI("AuthSinkConfirmState::Action USER_OPERATION_TYPE_ALLOW_AUTH"); + // 发送110报文 + context->authMessageProcessor->CreateAndSendMsg(MSG_TYPE_RESP_USER_CONFIRM, context); + // 生成PIN码 + AuthSinkStatePinAuthComm::GeneratePincode(context); + // 显示PIN码 + if ((ret = AuthSinkStatePinAuthComm::ShowAuthInfoDialog(context)) != DM_OK) { + return ret; + } + } else { + LOGI("AuthSinkConfirmState::Action USER_OPERATION_TYPE_CANCEL_AUTH"); + context->reason = ERR_DM_BIND_USER_CANCEL; + return STOP_BIND; // 用户取消授权 + } + } else { + if (context->authResult == USER_OPERATION_TYPE_CANCEL_AUTH) { + LOGI("AuthSinkConfirmState::Action USER_OPERATION_TYPE_CANCEL_AUTH"); + context->reason = ERR_DM_BIND_USER_CANCEL; + return STOP_BIND; // 用户取消授权 + } + if (context->authType == DmAuthType::AUTH_TYPE_PIN_ULTRASONIC) { // 超声交换PIN + LOGI("AuthSinkConfirmState::Action AUTH_TYPE_PIN_ULTRASONIC"); + // 发送110报文 + context->authMessageProcessor->CreateAndSendMsg(MSG_TYPE_RESP_USER_CONFIRM, context); + // 请求发送超声PIN码 + } else if (context->authType == DmAuthType::AUTH_TYPE_IMPORT_AUTH_CODE) { // 导入PIN + LOGI("AuthSinkConfirmState::Action AUTH_TYPE_IMPORT_AUTH_CODE"); + // 发送110报文 + context->authMessageProcessor->CreateAndSendMsg(MSG_TYPE_RESP_USER_CONFIRM, context); + } + } + LOGI("AuthSinkConfirmState::Action ok"); + return DM_OK; +#endif +} + +} // namespace DistributedHardware +} // namespace OHOS \ No newline at end of file diff --git a/services/implementation/src/authentication_v2/auth_stages/auth_credential.cpp b/services/implementation/src/authentication_v2/auth_stages/auth_credential.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f89b4155266eae306a3d595bfdf017ad8c181747 --- /dev/null +++ b/services/implementation/src/authentication_v2/auth_stages/auth_credential.cpp @@ -0,0 +1,537 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 +#include +#include +#include +#include "dm_auth_state.h" +#include "dm_auth_context.h" +#include "dm_auth_state_machine.h" +#include "dm_auth_message_processor.h" +#include "dm_log.h" +#include "dm_constants.h" +#include "multiple_user_connector.h" +#include "deviceprofile_connector.h" +#include "hichain_auth_connector.h" +#undef LOG_TAG +#define LOG_TAG "DHDM_V2" + +namespace OHOS { +namespace DistributedHardware { + +// 从context中提取transmit data,使用SK解密,并透传给HICHAIN +// 如果ontransmit事件,在对应回调解析并保存在context +// 如果onsessionkeyreturned事件,在对应回调解析并保存在cryptomgr +static int32_t AuthCredentialTransmitDecryptProcess(std::shared_ptr context, DmEventType event) +{ + if (context->transmitData.empty()) { + LOGE("DmAuthMessageProcessor::CreateMessageReqCredAuthStart failed, get onTransmitData failed."); + return ERR_DM_FAILED; + } + + // 透传给hichain + int32_t ret = context->hiChainAuthConnector->ProcessCredData(context->requestId, context->transmitData); + if (ret != DM_OK) { + LOGE("AuthCredentialTransmitDecryptProcess: ProcessCredData transmit data failed"); + return ERR_DM_FAILED; + } + // 等待hichain返回结果 + if (context->authStateMachine->WaitExpectEvent(event) != event) { + LOGE("AuthCredentialTransmitDecryptProcess: Hichain auth transmit data failed"); + return ERR_DM_FAILED; + } + return DM_OK; +} + +// 解析HICHAIN transmit data,并透传给对端 +static int32_t AuthCredentialTransmitSend(std::shared_ptr context, DmMessageType msgType) +{ + // 获取transmit data + if (context->transmitData.empty()) { + LOGE("AuthCredentialTransmitSend: Get onTransmitData failed."); + return ERR_DM_FAILED; + } + + std::string message = + context->authMessageProcessor->CreateMessage(msgType, context); // 不需要额外传data,context中均有 + if (message.empty()) { + LOGE("AuthCredentialTransmitSend: CreateMessage AuthCredential transmit data failed"); + return ERR_DM_FAILED; + } + // 发送报文 + return context->softbusConnector->GetSoftbusSession()->SendData(context->sessionId, message); +} + +// SOURCE端凭据校验操作 + +DmAuthStateType AuthSrcCredentialAuthNegotiateState::GetStateType() +{ + return DmAuthStateType::AUTH_SRC_CREDENTIAL_AUTH_NEGOTIATE_STATE; +} +// 收到170凭据认证报文,解析ontransmit,回复161报文 +int32_t AuthSrcCredentialAuthNegotiateState::Action(std::shared_ptr context) +{ + // 解密并透传transmitData + int32_t ret = AuthCredentialTransmitDecryptProcess(context, ON_TRANSMIT); + if (ret != DM_OK) { + return ret; + } + // 发送161报文 + return AuthCredentialTransmitSend(context, DmMessageType::MSG_TYPE_REQ_CREDENTIAL_AUTH_NEGOTIATE); +} + +DmAuthStateType AuthSrcCredentialAuthDoneState::GetStateType() +{ + return DmAuthStateType::AUTH_SRC_CREDENTIAL_AUTH_DONE_STATE; +} +// 收到171凭据认证报文 +int32_t AuthSrcCredentialAuthDoneState::Action(std::shared_ptr context) +{ + // 解密并透传transmitData + // 171报文在首次认证情况下会发生两次,先进行应用凭据认证,后进行用户凭据认证;非首次认证仅进行应用凭据认证 + // 最后一次认证结束后会收到ON_FINISH + int32_t ret = AuthCredentialTransmitDecryptProcess(context, ON_SESSION_KEY_RETURNED); + if (ret != DM_OK) { + return ret; + } + + // 认证结束触发Onfinish回调事件 + if (context->authStateMachine->WaitExpectEvent(ON_FINISH) != ON_FINISH) { + LOGE("AuthSrcCredentialAuthDoneState::Action Hichain auth SINK transmit data failed"); + return ERR_DM_FAILED; + } + DmMessageType msgType; + int32_t skId; + ret = context->authMessageProcessor->SaveSessionKeyToDP(skId); + if (ret != DM_OK) { + LOGE("AuthSrcCredentialAuthDoneState::Action DP save user session key failed"); + return ret; + } + // 首次认证 且 应用凭据流程 + if (context->isOnline == false && context->isAppCredentialVerified == false) { + context->isAppCredentialVerified = true; + // 保存到DP 获取应用凭据ID 并保存 + context->appSkTimeStamp = + std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()) + .count(); + context->appSessionKeyId = skId; + msgType = MSG_TYPE_REQ_CREDENTIAL_AUTH_START; // 发送160 + // 认证用户凭据 + int32_t osAccountId = MultipleUserConnector::GetCurrentAccountUserID(); + ret = context->hiChainAuthConnector->AuthCredential(osAccountId, context->requestId, + context->accesser.userCredentialId, std::string("")); + if (ret != DM_OK) { + LOGE("AuthSrcCredentialAuthDoneState::Action Hichain auth credentail failed"); + return ret; + } + + // 等待onTransmit事件 + if (context->authStateMachine->WaitExpectEvent(ON_TRANSMIT) != ON_TRANSMIT) { + LOGE("AuthSrcCredentialAuthDoneState::Action failed, ON_TRANSMIT event not arrived."); + return ERR_DM_FAILED; + } + } else if (context->isOnline == false) { + // 首次认证 且 用户凭据流程 + // 保存到DP 获取用户凭据ID 并保存 + context->userSkTimeStamp = + std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()) + .count(); + context->userSessionKeyId = skId; + msgType = MSG_TYPE_REQ_DATA_SYNC; // 发送180 + } else { + // 非首次认证 应用凭据流程 + // 保存到DP 获取应用凭据ID 并保存 + context->appSkTimeStamp = + std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()) + .count(); + context->appSessionKeyId = skId; + msgType = MSG_TYPE_REQ_DATA_SYNC; // 发送180 + } + std::string message = + context->authMessageProcessor->CreateMessage(msgType, context); // 不需要额外传data,context中均有 + if (message.empty()) { + LOGE("AuthSrcCredentialAuthDoneState::Action CreateMessage failed"); + return ERR_DM_FAILED; + } + + return context->softbusConnector->GetSoftbusSession()->SendData(context->sessionId, message); +} + +// SINK端凭据校验操作 +DmAuthStateType AuthSinkCredentialAuthStartState::GetStateType() +{ + return DmAuthStateType::AUTH_SINK_CREDENTIAL_AUTH_START_STATE; +} +// 收到160凭证认证报文,发送170报文 +int32_t AuthSinkCredentialAuthStartState::Action(std::shared_ptr context) +{ + context->timer->DeleteTimer(std::string(WAIT_REQUEST_TIMEOUT_TASK)); + // 解密并透传transmitData + int32_t ret = AuthCredentialTransmitDecryptProcess(context, ON_TRANSMIT); + if (ret != DM_OK) { + return ret; + } + // 构造并发送170报文 + return AuthCredentialTransmitSend(context, DmMessageType::MSG_TYPE_RESP_CREDENTIAL_AUTH_START); +} + +DmAuthStateType AuthSinkCredentialAuthNegotiateState::GetStateType() +{ + return DmAuthStateType::AUTH_SINK_CREDENTIAL_AUTH_NEGOTIATE_STATE; +} + +// 收到161凭据协商报文,并回复171报文 +// 通过isAppCredentialVerified关键词区分首次认证、非首次认证 +int32_t AuthSinkCredentialAuthNegotiateState::Action(std::shared_ptr context) +{ + // 解密并透传transmitData + int32_t ret = AuthCredentialTransmitDecryptProcess(context, ON_TRANSMIT); + if (ret != DM_OK) { + return ret; // 内部有日志 不重复打印 + } + // 构造并发送171报文 + ret = AuthCredentialTransmitSend(context, DmMessageType::MSG_TYPE_RESP_CREDENTIAL_AUTH_NEGOTIATE); + if (ret != DM_OK) { + return ret; // 内部有日志 不重复打印 + } + + if (context->authStateMachine->WaitExpectEvent(ON_SESSION_KEY_RETURNED) != ON_SESSION_KEY_RETURNED) { + LOGE("AuthSinkCredentialAuthNegotiateState::Action Hichain auth SINK transmit data failed"); + return ERR_DM_FAILED; + } + + if (context->authStateMachine->WaitExpectEvent(ON_FINISH) != ON_FINISH) { + LOGE("AuthSinkCredentialAuthNegotiateState::Action Hichain auth SINK transmit data failed"); + return ERR_DM_FAILED; + } + int32_t skId; + ret = context->authMessageProcessor->SaveSessionKeyToDP(skId); + if (ret != DM_OK) { + LOGE("AuthSinkCredentialAuthNegotiateState::Action DP save user session key failed"); + return ret; + } + + if (context->isOnline == false && + context->isAppCredentialVerified == true) { // SINK首次认证场景,第二次收到161的流程 保存用户级永久SK到DP + context->userSkTimeStamp = + std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()) + .count(); + context->userSessionKeyId = skId; + } else { // 应用级凭据认证流程 首次认证的第一次161处理 和 非首次认证的161处理 + context->isAppCredentialVerified = true; // 用于指示 首次认证的应用级凭据已认证 + context->appSkTimeStamp = + std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()) + .count(); + context->appSessionKeyId = skId; + } + return DM_OK; +} + +// 生成凭据协商状态下的authParams的json格式字符串 +// authScope 设备级还是应用级 +// method 凭据生成方式 +// authContext 上下文指针 +std::string AuthCredentialAgreeState::CreateAuthParamsString(DmAuthScope authorizedScope, + DmAuthCredentialAddMethod method, const std::shared_ptr &authContext) +{ + LOGI("AuthCredentialAgreeState::CreateAuthParamsString start."); + // 参数校验 + if ((authorizedScope != DM_AUTH_SCOPE_USER && authorizedScope != DM_AUTH_SCOPE_APP) || + (method != DM_AUTH_CREDENTIAL_ADD_METHOD_GENERATE && method != DM_AUTH_CREDENTIAL_ADD_METHOD_IMPORT)) { + return std::string(""); + } + + nlohmann::json jsonObj; + if (method == DM_AUTH_CREDENTIAL_ADD_METHOD_GENERATE) { + jsonObj[DM_TAG_METHOD] = method; // 凭据生成方式 + } + + jsonObj[DM_TAG_DEVICE_ID] = (method == DM_AUTH_CREDENTIAL_ADD_METHOD_GENERATE) ? // 设备ID 生成是本端,导入是对端 + authContext->GetDeviceId(DM_AUTH_LOCAL_SIDE) : authContext->GetDeviceId(DM_AUTH_REMOTE_SIDE); + if (method == DM_AUTH_CREDENTIAL_ADD_METHOD_IMPORT) { + jsonObj[DM_TAG_PEER_USER_SPACE_ID] = std::to_string(authContext->GetUserId(DM_AUTH_REMOTE_SIDE)); + } + jsonObj[DM_TAG_SUBJECT] = DM_AUTH_CREDENTIAL_SUBJECT_PRIMARY; // 主控设备 + jsonObj[DM_TAG_CRED_TYPE] = DM_AUTH_CREDENTIAL_ACCOUNT_UNRELATED; // 账号无关 + jsonObj[DM_TAG_KEY_FORMAT] = (method == DM_AUTH_CREDENTIAL_ADD_METHOD_GENERATE) ? + DM_AUTH_KEY_FORMAT_ASYMM_GENERATE : DM_AUTH_KEY_FORMAT_ASYMM_IMPORT; // 生成或导入非对称秘钥 + jsonObj[DM_TAG_ALGORITHM_TYPE] = DM_AUTH_ALG_TYPE_P256; // ED25519还没开发完,目前用P256 + jsonObj[DM_TAG_PROOF_TYPE] = DM_AUTH_CREDENTIAL_PROOF_PSK; // PSK + if (method == DM_AUTH_CREDENTIAL_ADD_METHOD_IMPORT) { // 导入公钥 16进制字符串 + jsonObj[DM_TAG_KEY_VALUE] = authContext->GetPublicKey(DM_AUTH_REMOTE_SIDE, authorizedScope); + } + jsonObj[DM_TAG_AUTHORIZED_SCOPE] = authorizedScope; // 用户级或者应用级 + if (authorizedScope == DM_AUTH_SCOPE_APP) { + jsonObj[DM_TAG_AUTHRIZED_APP_LIST] = {std::to_string(authContext->accesser.tokenId), + std::to_string(authContext->accessee.tokenId)}; + } + jsonObj[DM_TAG_CREDENTIAL_OWNER] = DM_AUTH_CREDENTIAL_OWNER; // 调用方包名DM模块 + + LOGI("AuthCredentialAgreeState::CreateAuthParamsString leave."); + return SafetyDump(jsonObj); +} + +// 生成凭据Id和公钥 +// authorizedScope 用户级还是应用级 +// authContext 上下文 +int32_t AuthCredentialAgreeState::GenerateCredIdAndPublicKey(DmAuthScope authorizedScope, + std::shared_ptr &authContext) +{ + LOGI("AuthCredentialAgreeState::GenerateCredIdAndPublicKey start."); + if ((authorizedScope != DM_AUTH_SCOPE_USER && authorizedScope != DM_AUTH_SCOPE_APP) || + authContext == nullptr || authContext->hiChainAuthConnector == nullptr) { + return ERR_DM_FAILED; + } + + // 创建authParams的json格式字符串 + std::string authParamsString = CreateAuthParamsString(authorizedScope, + DM_AUTH_CREDENTIAL_ADD_METHOD_GENERATE, authContext); + if (authParamsString == "") { + LOGE("AuthCredentialAgreeState::GenerateCredIdAndPublicKey() error, create authParamsString failed."); + return ERR_DM_FAILED; + } + + // 生成凭据 + int32_t osAccountId = MultipleUserConnector::GetCurrentAccountUserID(); + std::string credId; + int32_t ret = authContext->hiChainAuthConnector->AddCredential(osAccountId, authParamsString, credId); + if (ret != DM_OK) { + LOGE("AuthCredentialAgreeState::GenerateCredIdAndPublicKey() error, add credential failed."); + return ret; + } + + // 导出公钥 + std::string publicKey; + ret = authContext->hiChainAuthConnector->ExportCredential(osAccountId, credId, publicKey); + if (ret != DM_OK) { + LOGE("AuthCredentialAgreeState::GenerateCredIdAndPublicKey(), export publicKey failed."); + authContext->hiChainAuthConnector->DeleteCredential(osAccountId, credId); + return ret; + } + + // 保存凭据Id和公钥 + (void)authContext->SetCredentialId(DM_AUTH_LOCAL_SIDE, authorizedScope, credId); + (void)authContext->SetPublicKey(DM_AUTH_LOCAL_SIDE, authorizedScope, publicKey); + LOGI("AuthCredentialAgreeState::GenerateCredIdAndPublicKey credId=%{public}s, publicKey=%{public}s.\n", + authContext->GetCredentialId(DM_AUTH_LOCAL_SIDE, authorizedScope).c_str(), + authContext->GetPublicKey(DM_AUTH_LOCAL_SIDE, authorizedScope).c_str()); + LOGI("AuthCredentialAgreeState::GenerateCredIdAndPublicKey leave."); + return DM_OK; +} + +// 协商凭据得到协商凭据Id +// authorizedScope 设备级还是应用级 +// authContext 上下文 +int32_t AuthCredentialAgreeState::AgreeCredential(DmAuthScope authorizedScope, + std::shared_ptr &authContext) +{ + LOGI("AuthCredentialAgreeState::AgreeCredential start."); + if ((authorizedScope != DM_AUTH_SCOPE_USER && authorizedScope != DM_AUTH_SCOPE_APP) || authContext == nullptr) { + return ERR_DM_FAILED; + } + + // 创建authParams的json格式字符串 + std::string authParamsString = CreateAuthParamsString(authorizedScope, + DM_AUTH_CREDENTIAL_ADD_METHOD_IMPORT, authContext); + if (authParamsString == "") { + LOGE("AuthCredentialAgreeState::AgreeCredential() error, create authParamsString failed."); + return ERR_DM_FAILED; + } + + // 凭据协商得到协商凭据Id + int32_t osAccountId = MultipleUserConnector::GetCurrentAccountUserID();; + std::string selfCredId = authContext->GetCredentialId(DM_AUTH_LOCAL_SIDE, authorizedScope); + std::string credId; + int32_t ret = authContext->hiChainAuthConnector->AgreeCredential(osAccountId, selfCredId, + authParamsString, credId); + if (ret != DM_OK) { + LOGE("AuthCredentialAgreeState::AgreeCredential() error, agree credential failed."); + } + + // 保存协商凭据Id到上下文 + (void)authContext->SetCredentialId(DM_AUTH_LOCAL_SIDE, authorizedScope, credId); + LOGI("AuthCredentialAgreeState::AgreeCredential leave."); + return DM_OK; +} + +DmAuthStateType AuthSrcCredentialExchangeState::GetStateType() +{ + return DmAuthStateType::AUTH_SRC_CREDENTIAL_EXCHANGE_STATE; +} + +int32_t AuthSrcCredentialExchangeState::Action(std::shared_ptr context) +{ + LOGI("AuthSrcCredentialExchangeState::Action() start."); + int32_t ret = ERR_DM_FAILED; + context->isAppCredentialVerified = false; + + // 首次认证,生成用户级凭据和公钥 + if (!context->isOnline) { + ret = GenerateCredIdAndPublicKey(DM_AUTH_SCOPE_USER, context); + if (ret != DM_OK) { + LOGE("AuthSrcCredentialExchangeState::Action() error, generate user credId and publicKey failed."); + return ret; + } + } + + // 生成应用级凭据和公钥 + ret = GenerateCredIdAndPublicKey(DM_AUTH_SCOPE_APP, context); + if (ret != DM_OK) { + LOGE("AuthSrcCredentialExchangeState::Action() error, generate app credId and publicKey failed."); + return ret; + } + + // 发送140报文 + std::string message = context->authMessageProcessor->CreateMessage(MSG_TYPE_REQ_CREDENTIAL_EXCHANGE, context); + LOGI("AuthSrcCredentialExchangeState::Action() leave."); + return context->softbusConnector->GetSoftbusSession()->SendData(context->sessionId, message); +} + +DmAuthStateType AuthSinkCredentialExchangeState::GetStateType() +{ + return DmAuthStateType::AUTH_SINK_CREDENTIAL_EXCHANGE_STATE; +} + +int32_t AuthSinkCredentialExchangeState::Action(std::shared_ptr context) +{ + LOGI("AuthSinkCredentialExchangeState::Action start."); + int32_t ret = ERR_DM_FAILED; + std::string tmpCredId; + int32_t osAccountId = MultipleUserConnector::GetCurrentAccountUserID();; + context->isAppCredentialVerified = false; + + if (context == nullptr || context->hiChainAuthConnector == nullptr || + context->authMessageProcessor == nullptr || context->softbusConnector == nullptr) { + return ret; + } + + // 首次认证 + if (!context->isOnline) { + // 生成用户级凭据和公钥 + ret = GenerateCredIdAndPublicKey(DM_AUTH_SCOPE_USER, context); + if (ret != DM_OK) { + LOGE("AuthSinkCredentialExchangeState::Action failed, generate user cred and publicKey failed."); + return ret; + } + + // 协商用户级凭据 + tmpCredId = context->accessee.userCredentialId; + ret = AgreeCredential(DM_AUTH_SCOPE_USER, context); + if (ret != DM_OK) { + context->hiChainAuthConnector->DeleteCredential(osAccountId, tmpCredId); + context->SetCredentialId(DM_AUTH_LOCAL_SIDE, DM_AUTH_SCOPE_USER, ""); + LOGE("AuthSinkCredentialExchangeState::Action failed, agree user cred failed."); + return ret; + } + + // 删除临时用户级凭据 + context->hiChainAuthConnector->DeleteCredential(osAccountId, tmpCredId); + } + + // 生成应用级凭据和公钥 + ret = GenerateCredIdAndPublicKey(DM_AUTH_SCOPE_APP, context); + if (ret != DM_OK) { + LOGE("AuthSinkCredentialExchangeState::Action failed, generate app cred and publicKey failed."); + return ret; + } + + // 协商应用级公钥 + tmpCredId = context->accessee.appCredentialId; + ret = AgreeCredential(DM_AUTH_SCOPE_APP, context); + if (ret != DM_OK) { + context->hiChainAuthConnector->DeleteCredential(osAccountId, tmpCredId); + context->SetCredentialId(DM_AUTH_LOCAL_SIDE, DM_AUTH_SCOPE_APP, ""); + LOGE("AuthSinkCredentialExchangeState::Action failed, agree app cred failed."); + return ret; + } + + // 删除临时应用级凭据 + context->hiChainAuthConnector->DeleteCredential(osAccountId, tmpCredId); + + // 发送150报文 + std::string message = context->authMessageProcessor->CreateMessage(MSG_TYPE_RESP_CREDENTIAL_EXCHANGE, context); + LOGI("AuthSinkCredentialExchangeState::Action leave."); + return context->softbusConnector->GetSoftbusSession()->SendData(context->sessionId, message); +} + +DmAuthStateType AuthSrcCredentialAuthStartState::GetStateType() +{ + return DmAuthStateType::AUTH_SRC_CREDENTIAL_AUTH_START_STATE; +} + + +int32_t AuthSrcCredentialAuthStartState::Action(std::shared_ptr context) +{ + LOGI(" AuthSrcCredentialAuthStartState::Action start."); + int32_t ret = ERR_DM_FAILED; + std::string tmpCredId; + int32_t osAccountId = MultipleUserConnector::GetCurrentAccountUserID();; + + if (context == nullptr || context->hiChainAuthConnector == nullptr || + context->authMessageProcessor == nullptr || context->softbusConnector == nullptr) { + return ret; + } + + // 首次认证 + if (!context->isOnline) { + // 协商用户级凭据 + tmpCredId = context->accesser.userCredentialId; + ret = AgreeCredential(DM_AUTH_SCOPE_USER, context); + if (ret != DM_OK) { + context->hiChainAuthConnector->DeleteCredential(osAccountId, tmpCredId); + context->SetCredentialId(DM_AUTH_LOCAL_SIDE, DM_AUTH_SCOPE_USER, ""); + LOGE("AuthSrcCredentialAuthStartState::Action failed, agree user cred failed."); + return ret; + } + + // 删除临时用户级凭据 + context->hiChainAuthConnector->DeleteCredential(osAccountId, tmpCredId); + } + + // 协商应用级凭据 + tmpCredId = context->accesser.appCredentialId; + ret = AgreeCredential(DM_AUTH_SCOPE_APP, context); + if (ret != DM_OK) { + context->hiChainAuthConnector->DeleteCredential(osAccountId, tmpCredId); + context->SetCredentialId(DM_AUTH_LOCAL_SIDE, DM_AUTH_SCOPE_APP, ""); + LOGE("AuthSrcCredentialAuthStartState::Action failed, agree app cred failed."); + return ret; + } + + // 删除临时应用级凭据 + context->hiChainAuthConnector->DeleteCredential(osAccountId, tmpCredId); + + // 凭据认证 先进行应用级 + ret = context->hiChainAuthConnector->AuthCredential(osAccountId, context->requestId, + context->accesser.appCredentialId, std::string("")); + if (ret != DM_OK) { + LOGE("AuthSrcCredentialAuthStartState::Action failed, auth app cred failed."); + return ret; + } + + // 阻塞等待事件ON_TRANSMIT事件到来 + if (context->authStateMachine->WaitExpectEvent(ON_TRANSMIT) != ON_TRANSMIT) { + LOGE("AuthSrcCredentialAuthStartState::Action failed, ON_TRANSMIT event not arrived."); + return ERR_DM_FAILED; + } + + // 发送160报文 + std::string message = context->authMessageProcessor->CreateMessage(MSG_TYPE_REQ_CREDENTIAL_AUTH_START, context); + LOGI(" AuthSrcCredentialAuthStartState::Action leave."); + return context->softbusConnector->GetSoftbusSession()->SendData(context->sessionId, message); +} + +} // namespace DistributedHardware +} // namespace OHOS diff --git a/services/implementation/src/authentication_v2/auth_stages/auth_negotiate.cpp b/services/implementation/src/authentication_v2/auth_stages/auth_negotiate.cpp new file mode 100644 index 0000000000000000000000000000000000000000..47604e80a7961b9e3234f9b2143358817e0f8421 --- /dev/null +++ b/services/implementation/src/authentication_v2/auth_stages/auth_negotiate.cpp @@ -0,0 +1,575 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 +#include +#include "nlohmann/json.hpp" + +#include "parameter.h" +#include "multiple_user_connector.h" +#include "app_manager.h" +#include "hap_token_info.h" +#include "deviceprofile_connector.h" +#include "distributed_device_profile_errors.h" +#include "device_auth.h" +#include "os_account_manager.h" +#include "accesstoken_kit.h" +#include "access_control_profile.h" +#include "accesser.h" +#include "accessee.h" + +#include "dm_crypto.h" +#include "dm_log.h" +#include "dm_timer.h" +#include "dm_radar_helper.h" +#include "dm_constants.h" +#include "dm_anonymous.h" +#include "dm_random.h" +#include "dm_auth_context.h" +#include "auth_manager.h" +#include "dm_auth_state.h" + +#ifdef OS_ACCOUNT_PART_EXISTS +#include "os_account_manager.h" +using namespace OHOS::AccountSA; +#endif // OS_ACCOUNT_PART_EXISTS + +using namespace OHOS::Security::AccessToken; + +#undef LOG_TAG +#define LOG_TAG "DHDM_V2" + +namespace OHOS { +namespace DistributedHardware { + +namespace { + +using FallBackKey = std::pair; // accessee.bundleName, authType +static std::map g_pinAuthTypeFallBackMap = { + {{"cast_engine_service", DmAuthType::AUTH_TYPE_IMPORT_AUTH_CODE}, DmAuthType::AUTH_TYPE_PIN}, +}; +constexpr size_t MAX_FALLBACK_LOOPKUP_TIMES = 2; // 最大递归查找次数 + +// security_device_auth凭据查询相关定义,保持与device_auth.h一致 +const char * const FILED_DEVICE_ID = "deviceId"; +const char * const FILED_DEVICE_ID_HASH = "deviceIdHash"; +const char * const FILED_PEER_USER_SPACE_ID = "peerUserSpaceId"; +const char * const FILED_CRED_TYPE = "credType"; +const char * const FILED_AUTHORIZED_APP_LIST = "authorizedAppList"; +const char * const FILED_AUTHORIZED_SCOPE = "authorizedScope"; + +enum DmRole { + DM_ROLE_UNKNOWN = 0, + DM_ROLE_FA_TO_FA, + DM_ROLE_FA_TO_FA_SERVICE, + DM_ROLE_SA_TO_SA, + DM_ROLE_SA_TO_SA_SERVICE, + DM_ROLE_FA_TO_DEVICE +}; + +} + +DmAuthStateType AuthSrcStartState::GetStateType() +{ + return DmAuthStateType::AUTH_SRC_START_STATE; +} + +int32_t AuthSrcStartState::Action(std::shared_ptr context) +{ + int32_t sessionId = 0; + if (AuthManager::IsHmlSessionType(context->connSessionType)) { + LOGI("hmlActionId %{public}d, hmlReleaseTime %{public}d, hmlEnable160M %{public}d", + context->hmlActionId, context->connDelayCloseTime, context->hmlEnable160M); + sessionId = context->softbusConnector->GetSoftbusSession() + ->OpenAuthSessionWithPara(context->accessee.deviceId, context->hmlActionId, context->hmlEnable160M); + } else { + sessionId = context->softbusConnector->GetSoftbusSession()->OpenAuthSession(context->accessee.deviceId); + } + + struct RadarInfo info = { + .funcName = "EstablishAuthChannel", + .stageRes = (sessionId > 0) ? + static_cast(StageRes::STAGE_IDLE) : static_cast(StageRes::STAGE_FAIL), + .bizState = (sessionId > 0) ? + static_cast(BizState::BIZ_STATE_START) : static_cast(BizState::BIZ_STATE_END), + .localSessName = DM_SESSION_NAME, + .peerSessName = DM_SESSION_NAME, + .isTrust = static_cast(TrustStatus::NOT_TRUST), + .commServ = static_cast(CommServ::USE_SOFTBUS), + .peerUdid = context->accessee.deviceId, + .channelId = sessionId, + .errCode = sessionId, + }; + if (!DmRadarHelper::GetInstance().ReportAuthOpenSession(info)) { + LOGE("ReportAuthOpenSession failed"); + } + if (sessionId < 0) { + LOGE("OpenAuthSession failed, stop the authentication"); + return ERR_DM_FAILED; + } + return DM_OK; +} + +DmAuthStateType AuthSrcNegotiateStateMachine::GetStateType() +{ + return DmAuthStateType::AUTH_SRC_NEGOTIATE_STATE; +} + +int32_t AuthSrcNegotiateStateMachine::Action(std::shared_ptr context) +{ + LOGI("AuthSrcNegotiateStateMachine::Action sessionId %{public}d.", context->sessionId); + + context->reply = ERR_DM_AUTH_REJECT; + // Q: 初始化时已赋值,此处需确认调试结果 + context->accessee.bundleName = context->accesser.bundleName; + //TODO: 传输tokenId + // 为什么之前DmVersion传空? + context->accessee.dmVersion = ""; + + // 计算哈希值 + context->accesser.deviceIdHash = Crypto::Sha256(context->accesser.deviceId); + context->accesser.userIdHash = Crypto::Sha256(std::to_string(context->accesser.userId)); + context->accesser.accountIdHash = Crypto::Sha256(context->accesser.accountId); + context->accesser.tokenIdHash = Crypto::Sha256(std::to_string(context->accesser.tokenId)); + + std::string message = context->authMessageProcessor->CreateMessage(MSG_TYPE_REQ_ACL_NEGOTIATE, context); + context->softbusConnector->GetSoftbusSession()->SendData(context->sessionId, message); + if (context->timer != nullptr) { + context->timer->StartTimer(std::string(NEGOTIATE_TIMEOUT_TASK), + DmAuthState::GetTaskTimeout(context, NEGOTIATE_TIMEOUT_TASK, NEGOTIATE_TIMEOUT), [this, context] (std::string name) { + DmAuthState::HandleAuthenticateTimeout(context, name); + }); + } + + return DM_OK; +} + +DmAuthStateType AuthSinkNegotiateStateMachine::GetStateType() +{ + return DmAuthStateType::AUTH_SINK_NEGOTIATE_STATE; +} + +int32_t AuthSinkNegotiateStateMachine::RespQueryAcceseeIds(std::shared_ptr context) +{ + int32_t ret; + int32_t dmRole = DM_ROLE_UNKNOWN; + + // 1. 获取deviceId + char localDeviceId[DEVICE_UUID_LENGTH] = {0}; + GetDevUdid(localDeviceId, DEVICE_UUID_LENGTH); + context->accessee.deviceId = std::string(localDeviceId); + + // 2. 获取userId + std::vector userVec; + ret = MultipleUserConnector::GetForegroundUserIds(userVec); + if (ret != DM_OK) { + LOGE("RespQueryTokenId: GetForegroundUserIds failed, ret: %{public}d", ret); + return ret; + } + if (userVec.size() == 0) { + LOGE("RespQueryTokenId: GetForegroundUserIds no foreground users"); + return ERR_DM_FAILED; + } + + if (context->accessee.displayId != 0) { + ret = AccountSA::OsAccountManager::GetForegroundOsAccountLocalId(context->accessee.displayId, + context->accessee.userId); + if (ret != DM_OK) { + LOGE("RespQueryTokenId: fail to get userId by displayId %{public}d", context->accessee.displayId); + return ERR_DM_FAILED; + } + } + + // 场景1:对端指定了userId -> 校验是否为前台用户 + // 场景2:对端未指定userId + // 场景2.1: 单用户 -> 使用当前唯一前台用户 + // 场景2.2: 多用户 -> 使用当前主屏用户 + if (context->accessee.userId != 0) { + if (std::find(userVec.begin(), userVec.end(), context->accessee.userId) == userVec.end()) { + LOGE("RespQueryTokenId: userId not in foreground users"); + return ERR_DM_FAILED; + } + } else if (userVec.size() == 1) { + context->accessee.userId = userVec[0]; + } else { +#ifdef OS_ACCOUNT_PART_EXISTS + ret = AccountSA::OsAccountManager::GetForegroundOsAccountLocalId(context->accessee.userId); + if (ret != DM_OK) { + LOGE("RespQueryAcceseeIds: get foreground user failed in multi users with error %{public}d", ret); + return ERR_DM_FAILED; + } +#else + LOGE("RespQueryAcceseeIds: get foreground user failed because no OsAcccountManager"); + return ERR_DM_FAILED; +#endif + } + + // 3. 获取accountId + context->accessee.accountId = MultipleUserConnector::GetOhosAccountIdByUserId(context->accessee.userId); + + // 4. 获取tokenId + std::string tmpBundleName = context->accessee.bundleName.empty() ? + context->accesser.bundleName : context->accessee.bundleName; + int64_t tokenId; + ret = AppManager::GetInstance().GetHapTokenIdByName(context->accessee.userId, tmpBundleName, 0, tokenId); + if (ret != DM_OK) { + // 不传bundleName且无法获取到tokenId时,即为FA-device + if (context->accessee.bundleName.empty()) { + dmRole = DM_ROLE_FA_TO_DEVICE; + LOGI("RespQueryTokenId: FA to device"); + return DM_OK; + } + LOGE("RespQueryTokenId: get tokenId by bundleName failed %{public}s", + GetAnonyString(context->accessee.bundleName).c_str()); + return ret; + } + context->accessee.bundleName = tmpBundleName; + context->accessee.tokenId = static_cast(tokenId); + + return DM_OK; +} + +bool AuthSinkNegotiateStateMachine::HaveSameTokenId(std::shared_ptr context, const std::vector &tokenList) +{ + if (tokenList.size() != 2) { + LOGE("HaveSameTokenId invalid tokenList size."); + return false; + } + + const std::string &src_tokenId = tokenList[0]; + const std::string &sink_tokenId = tokenList[1]; + + // 计算src_tokenId的哈希值 + std::string src_tokenIdHash = Crypto::Sha256(src_tokenId); + + // 比较src_tokenId的哈希值和sink_tokenId + if (src_tokenIdHash != context->accesser.tokenIdHash) { + return false; + } + + if (sink_tokenId != std::to_string(context->accessee.tokenId)) { + return false; + } + + return true; +} + +uint32_t AuthSinkNegotiateStateMachine::GetCredentialType(std::shared_ptr context, nlohmann::json credInfo) +{ + // 判断是否同账号 + // TODO: 需要确定截断长度 + if (Crypto::Sha256(context->accessee.accountId) == context->accesser.accountIdHash && + context->accessee.accountId != "ohosAnonymousUid") { + if (credInfo[FILED_CRED_TYPE] == ACCOUNT_RELATED && credInfo[FILED_AUTHORIZED_SCOPE] == SCOPE_USER) { + return DM_IDENTICAL_ACCOUNT; + } + } else { + if (credInfo[FILED_CRED_TYPE] == ACCOUNT_ACROSS && credInfo[FILED_AUTHORIZED_SCOPE] == SCOPE_USER) { + return DM_ACROSS_ACCOUNT; + } + if (credInfo[FILED_CRED_TYPE] == ACCOUNT_UNRELATED && credInfo[FILED_AUTHORIZED_SCOPE] == SCOPE_APP && + HaveSameTokenId(context, credInfo[FILED_AUTHORIZED_APP_LIST]) == true) { + return DM_POINT_TO_POINT; + } + } + + // 未确定凭据类型 + return DM_INVALIED_BINDTYPE; +} + +// 比较ACL四元组:双端的deviceId和userId +bool AuthSinkNegotiateStateMachine::AclCompareTwoIds(std::shared_ptr context, + const DistributedDeviceProfile::Accesser &accesser, const DistributedDeviceProfile::Accessee &accessee) +{ + // TODO: 需确定deviceId、userId哈希值的截断位数是多少 + return Crypto::Sha256(accesser.GetAccesserDeviceId()) == context->accesser.deviceIdHash && + Crypto::Sha256(std::to_string(accesser.GetAccesserUserId())) == context->accesser.userIdHash && + accessee.GetAccesseeDeviceId() == context->accessee.deviceId && + accessee.GetAccesseeUserId() == context->accessee.userId; +} + +// 比较ACL八元组:四元组加双端的accountId和tokenId +bool AuthSinkNegotiateStateMachine::AclCompareFourIds(std::shared_ptr context, + const DistributedDeviceProfile::Accesser &accesser, const DistributedDeviceProfile::Accessee &accessee) +{ + return AclCompareTwoIds(context, accesser, accessee) && + // TODO: 需确定deviceId、userId哈希值的截断位数是多少 + Crypto::Sha256(accesser.GetAccesserAccountId()) == context->accesser.accountIdHash && + Crypto::Sha256(std::to_string(accesser.GetAccesserTokenId())) == context->accesser.tokenIdHash && + accessee.GetAccesseeAccountId() == context->accessee.accountId && + accessee.GetAccesseeTokenId() == static_cast(context->accessee.tokenId); +} + +/** + 有无凭据确认逻辑:以ACL的credId为索引,在凭据列表中寻找凭据,若没找到则认为无对应凭据 + - 由于获取凭据时没有对端信息,无法基于对端信息查询凭据,只能通过ACL确认 + 凭据类型获取逻辑:GetCredentialType + + 问题: + 1. 无法确定有凭据无ACL的场景(因为需要基于ACL的ids与凭据匹配,匹配不上的则无信息) + + 输出: + isAuthed = true/false + credentialInfos = "{ + "[credId1]": "[credType1]", + "[credId2]": "[credType2]" + }" + */ +int32_t AuthSinkNegotiateStateMachine::GetAuthCredentialInfo(std::shared_ptr context) +{ + int32_t ret; + uint32_t credType; + nlohmann::json queryParams; + nlohmann::json queryResult; + + // 1. 获取所有凭据 + // 本端deviceId、userId + 对端deviceId、userId + // 本端userId为QueryCredentialInfo第一个参数 + queryParams[FILED_DEVICE_ID] = context->accessee.deviceId; + queryParams[FILED_DEVICE_ID_HASH] = context->accesser.deviceIdHash; + queryParams[FILED_PEER_USER_SPACE_ID] = context->accesser.userIdHash; + // 同账号凭据 + if (context->accessee.accountId != "ohosAnonymousUid" && + Crypto::Sha256(context->accessee.accountId) == context->accesser.accountIdHash) { + queryParams[FILED_CRED_TYPE] = 1; // 1 - 账号相关 + } + ret = context->hiChainAuthConnector->QueryCredentialInfo(context->accessee.userId, queryParams, queryResult); + if (ret != DM_OK) { + LOGE("DmAuthManager::ProcRespNegotiate5_1_0 fail to query credential id list."); + context->reply = ERR_DM_UNSUPPORTED_AUTH_TYPE; + return ret; + } + + for (auto& item : queryResult) { + // 确认凭据类型 + credType = GetCredentialType(context, item); + if (credType == DM_INVALIED_BINDTYPE) { + continue; + } + + item[FILED_CRED_TYPE] = credType; + } + + // 2. 获取所有ACL + std::vector profiles = + DeviceProfileConnector::GetInstance().GetAccessControlProfile(); + bool isAclActive = false; + for (const auto &item : profiles) { + auto accesser = item.GetAccesser(); + auto accessee = item.GetAccessee(); + + // 确保凭据能跟ACL对应上。 + std::string credId = std::to_string(accessee.GetAccesseeCredentialId()); + if (queryResult.find(credId) == queryResult.end() || item.GetStatus() != ACTIVE) { + continue; + } + + // 确认是否有可信关系 + credType = queryResult[credId][FILED_CRED_TYPE]; + if (credType == DM_IDENTICAL_ACCOUNT || credType == DM_ACROSS_ACCOUNT) { + queryResult[credId]["isAclActive"] = AclCompareTwoIds(context, accesser, accessee); + } else if (credType == DM_POINT_TO_POINT) { + queryResult[credId]["isAclActive"] = AclCompareFourIds(context, accesser, accessee); + } + } + + // 3. 筛选凭据 + std::vector invalidCredIds; + nlohmann::json packResult; // 需要打包发送到对端的数据 + for (const auto& [credId, cred] : queryResult.items()) { + if (cred.find("isAclActive") == cred.end() || cred["isAclActive"] == false) { + continue; + } + + packResult[credId] = cred[FILED_CRED_TYPE]; + } + + context->accessee.isAuthed = !queryResult.empty(); + context->accessee.credentialInfos = SafetyDump(packResult); + + return DM_OK; +} + +int32_t AuthSinkNegotiateStateMachine::ProcRespNegotiate5_1_0(std::shared_ptr context) +{ + // 获取accesee四元组:uid、userId、accountId、tokenId + int32_t ret = RespQueryAcceseeIds(context); + if (ret != DM_OK) { + LOGE("DmAuthManager::ProcRespNegotiate5_1_0 fail to get all id."); + return ERR_DM_FAILED; + } + + context->accesser.isOnline = context->softbusConnector->CheckIsOnline(context->accesser.deviceIdHash, true); + // 获取凭据信息 + ret = GetAuthCredentialInfo(context); + if (ret != DM_OK) { + LOGE("DmAuthManager::ProcRespNegotiate5_1_0 fail to get credential."); + return ERR_DM_FAILED; + } + + context->accessee.deviceIdHash = Crypto::Sha256(context->accessee.deviceId); + context->accessee.userIdHash = Crypto::Sha256(std::to_string(context->accessee.userId)); + context->accessee.accountIdHash = Crypto::Sha256(context->accessee.accountId); + context->accessee.tokenIdHash = Crypto::Sha256(std::to_string(context->accessee.tokenId)); + + // 状态跳转在100报文中处理 + return DM_OK; +} + +void AuthSinkNegotiateStateMachine::MatchFallBackCandidateList( + std::shared_ptr context, DmAuthType authType) +{ + for (size_t i = 0; i < MAX_FALLBACK_LOOPKUP_TIMES; i++) { + auto it = g_pinAuthTypeFallBackMap.find({context->accessee.bundleName, authType}); + if (it != g_pinAuthTypeFallBackMap.end()) { + authType = it->second; + context->authTypeList.push_back(authType); + } else { + break; + } + } +} + +int64_t AuthSinkNegotiateStateMachine::GenRequestId() +{ + // 随机生成 PIN认证 的 requestId + int32_t part1 = GenRandInt(std::numeric_limits::min(), std::numeric_limits::max()); + int32_t part2 = GenRandInt(std::numeric_limits::min(), std::numeric_limits::max()); + uint64_t requestId = (static_cast(part1) << 32) | static_cast(part2); + return static_cast(requestId); +} + +bool AuthSinkNegotiateStateMachine::IsAuthCodeReady(std::shared_ptr context) +{ + if (context->importAuthCode.empty() || context->importSessionName.empty()) { + LOGE("AuthSinkNegotiateStateMachine::IsAuthCodeReady, auth code not ready."); + return false; + } + if (context->sessionName != context->importSessionName) { + LOGE("IsAuthCodeReady failed, sessionName not supported."); + return false; + } + return true; +} + +void AuthSinkNegotiateStateMachine::NegotiatePinAuthType(std::shared_ptr context) +{ + context->requestId = GenRequestId(); + context->authTypeList.clear(); + // 根据 accessee.bundleName 和 src端 authType 查询 SP + OHOS::DistributedDeviceProfile::LocalServiceInfo srvInfo; + auto ret = DeviceProfileConnector::GetInstance().GetLocalServiceInfoByBundleNameAndPinExchangeType( + context->accessee.bundleName, context->authType, srvInfo); + if (ret == OHOS::DistributedDeviceProfile::DP_SUCCESS) { + context->authTypeList.push_back(context->authType); // 匹配到,则添加到候选列表 + context->authBoxType = srvInfo.GetAuthBoxType(); + + if (context->authType == DmAuthType::AUTH_TYPE_IMPORT_AUTH_CODE) { + // 读取PIN码 + std::string pinCode = srvInfo.GetPinCode(); + context->pinCode = std::stoi(pinCode); + } + + if (context->authBoxType == OHOS::DistributedDeviceProfile::NUM_2) { // 免弹框 + int32_t authResult = srvInfo.GetAuthType(); + if (authResult == 0) { + context->authResult = UiAction::USER_OPERATION_TYPE_ALLOW_AUTH; + } else if (authResult == OHOS::DistributedDeviceProfile::NUM_1) { + context->authResult = UiAction::USER_OPERATION_TYPE_CANCEL_AUTH; + } else if (authResult == OHOS::DistributedDeviceProfile::NUM_6) { + context->authResult = UiAction::USER_OPERATION_TYPE_ALLOW_AUTH_ALWAYS; + } + } else { + context->customData = srvInfo.GetDescription(); + } + } else { + if (context->authType == DmAuthType::AUTH_TYPE_PIN || + context->authType == DmAuthType::AUTH_TYPE_PIN_ULTRASONIC) { + context->authBoxType = OHOS::DistributedDeviceProfile::NUM_1; // 三态框 + } else { + context->authBoxType = OHOS::DistributedDeviceProfile::NUM_2; // 免弹框 + } + if (context->authType == DmAuthType::AUTH_TYPE_IMPORT_AUTH_CODE) { + if (IsAuthCodeReady(context)) { + context->authTypeList.push_back(context->authType); + } + } else { + context->authTypeList.push_back(context->authType); // 没匹配到,但是不是导入授权码,也添加到候选列表 + } + } + // 查询回退表 + MatchFallBackCandidateList(context, context->authType); +} + +int32_t AuthSinkNegotiateStateMachine::Action(std::shared_ptr context) +{ + LOGI("AuthSinkNegotiateStateMachine::Action sessionid %{public}d", context->sessionId); + + // 1. 停止定时器 + if (context->timer != nullptr) { + context->timer->DeleteTimer(std::string(WAIT_NEGOTIATE_TIMEOUT_TASK)); + } + + // 2. 获取deviceName和udid + context->accessee.deviceName = context->softbusConnector->GetLocalDeviceName(); + char localDeviceId[DEVICE_UUID_LENGTH]; + GetDevUdid(localDeviceId, DEVICE_UUID_LENGTH); + context->accessee.deviceId = std::string(localDeviceId); + + context->accessee.networkId = context->softbusConnector->GetLocalDeviceNetworkId(); + context->accessee.deviceName = context->softbusConnector->GetLocalDeviceName(); + // 为兼容历史版本,通过ConvertSrcVersion获取src端实际version + context->accesser.dmVersion = AuthManagerBase::ConvertSrcVersion(context->accesser.dmVersion, + context->accesser.edition); + // 旧协议最高只到5.0.9版本 + std::string preVersion = std::string(DM_VERSION_5_0_9); + LOGI("AuthSinkNegotiateStateMachine::Action start version compare %{public}s to %{public}s", + context->accesser.dmVersion.c_str(), preVersion.c_str()); + if (CompareVersion(context->accesser.dmVersion, preVersion) == false) { + LOGE("AuthSinkNegotiateStateMachine::Action incompatible version"); + context->reason = ERR_DM_VERSION_INCOMPATIBLE; + return ERR_DM_VERSION_INCOMPATIBLE; + } + + int32_t ret = ProcRespNegotiate5_1_0(context); + if (ret != DM_OK) { + LOGE("AuthSinkNegotiateStateMachine::Action proc response negotiate failed"); + return ret; + } + NegotiatePinAuthType(context); + context->authMessageProcessor->CreateAndSendMsg(MSG_TYPE_RESP_ACL_NEGOTIATE, context); + context->timer->StartTimer(std::string(WAIT_REQUEST_TIMEOUT_TASK), + DmAuthState::GetTaskTimeout(context, WAIT_REQUEST_TIMEOUT_TASK, WAIT_REQUEST_TIMEOUT), + [this, context] (std::string name) { + DmAuthState::HandleAuthenticateTimeout(context, name); + }); + return DM_OK; +} + +/* +能力协商(80和90报文处理) +source端状态: +AuthIdleState, // 设备初始化时, 无需实现 +AuthSrcStartState, // 用户触发BindTarget +AuthSrcNegotiateState, // 收到软总线回调函数OnSessionOpened,发送80报文 + +sink端状态: +AuthIdleState, // 设备初始化时, 无需实现 +AuthSinkStartState, // 总线触发OnSessionOpened +AuthSinkNegotiateState, // 收到80可信关系协商报文,发送90报文 +*/ + +} // namespace DistributedHardware +} // namespace OHOS \ No newline at end of file diff --git a/services/implementation/src/authentication_v2/auth_stages/auth_pin_auth.cpp b/services/implementation/src/authentication_v2/auth_stages/auth_pin_auth.cpp new file mode 100644 index 0000000000000000000000000000000000000000..215590f1ab74af07264efeee66616cc823655979 --- /dev/null +++ b/services/implementation/src/authentication_v2/auth_stages/auth_pin_auth.cpp @@ -0,0 +1,556 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "hichain_auth_connector.h" +#include "dm_auth_state_machine.h" +#include "dm_auth_message_processor.h" +#include "dm_auth_state.h" +#include "dm_auth_context.h" +#include "dm_log.h" +#include "dm_dialog_manager.h" +#include "dm_anonymous.h" +#include "service_info_profile.h" +#include "dm_auth_state_machine.h" +#include "deviceprofile_connector.h" +#include "dm_random.h" +#include "multiple_user_connector.h" +#undef LOG_TAG +#define LOG_TAG "DHDM_V2" + +namespace OHOS { +namespace DistributedHardware { + +constexpr int32_t MAX_AUTH_INPUT_PIN_FAIL_TIMES = 3; +constexpr int32_t SESSION_HEARTBEAT_TIMEOUT = 20; +constexpr int32_t MIN_PIN_CODE = 100000; +constexpr int32_t MAX_PIN_CODE = 999999; + +/* +pin码认证(120和130报文处理、121和131报文处理) +source端状态: +AuthSrcPinAuthStartState, // 收到110授权结果报文,发送120报文 +AuthSrcPinAuthMsgNegotiateState, // 收到130认证PIN结果报文,发送121报文 +AuthSrcPinAuthDoneState, // 收到131认证PIN结果报文,调用processData + +sink端状态: +AuthSinkPinAuthStartState, // 收到120认证PIN报文,发送130报文 +AuthSinkPinAuthMsgNegotiateState, // 收到121认证PIN报文,发送131报文 +AuthSinkPinAuthDoneState, // 触发Onfinish回调事件 +*/ + +int32_t AuthSinkStatePinAuthComm::ShowAuthInfoDialog(std::shared_ptr context) +{ + LOGI("AuthSinkConfirmState::ShowAuthInfoDialog start"); + if (DmAuthState::IsScreenLocked()) { + LOGE("AuthSinkConfirmState::ShowAuthInfoDialog screen is locked."); + context->reason = ERR_DM_BIND_USER_CANCEL; + context->authStateMachine->NotifyEventFinish(DmEventType::ON_FAIL); + return STOP_BIND; + } + + DmDialogManager::GetInstance().ShowPinDialog(std::to_string(context->pinCode)); + + context->timer->StartTimer(std::string(SESSION_HEARTBEAT_TIMEOUT_TASK), + SESSION_HEARTBEAT_TIMEOUT, [context] (std::string name) { + AuthSinkStatePinAuthComm::HandleSessionHeartbeat(context, name); + }); + return DM_OK; +} + +void AuthSinkStatePinAuthComm::HandleSessionHeartbeat(std::shared_ptr context, std::string name) +{ + if (context->timer == nullptr) { + return; + } + context->timer->DeleteTimer(std::string(SESSION_HEARTBEAT_TIMEOUT_TASK)); + + LOGI("DmAuthManager::HandleSessionHeartbeat name %{public}s", name.c_str()); + nlohmann::json jsonObj; + jsonObj[TAG_SESSION_HEARTBEAT] = TAG_SESSION_HEARTBEAT; + std::string message = SafetyDump(jsonObj); + context->softbusConnector->GetSoftbusSession()->SendHeartbeatData(context->sessionId, message); + + context->timer->StartTimer(std::string(SESSION_HEARTBEAT_TIMEOUT_TASK), + SESSION_HEARTBEAT_TIMEOUT, [context] (std::string name) { + AuthSinkStatePinAuthComm::HandleSessionHeartbeat(context, name); + }); + + LOGI("DmAuthManager::HandleSessionHeartbeat complete"); +} + +void AuthSinkStatePinAuthComm::GeneratePincode(std::shared_ptr context) +{ + context->pinCode = GenRandInt(MIN_PIN_CODE, MAX_PIN_CODE); +} + +DmAuthStateType AuthSrcPinAuthStartState::GetStateType() +{ + return DmAuthStateType::AUTH_SRC_PIN_AUTH_START_STATE; +} + +int32_t AuthSrcPinAuthStartState::ShowStartAuthDialog(std::shared_ptr context) +{ + LOGI("AuthSrcPinAuthStartState::ShowStartAuthDialog start."); + if (DmAuthState::IsScreenLocked()) { + LOGE("ShowStartAuthDialog screen is locked."); + context->reason = ERR_DM_BIND_USER_CANCEL; + return STOP_BIND; + } + DmDialogManager::GetInstance().ShowInputDialog(context->accessee.deviceName); + LOGI("AuthSrcPinAuthStartState::ShowStartAuthDialog end."); + return DM_OK; +} + +int32_t AuthSrcPinAuthStartState::GetPinCodeFromServerInfo(std::shared_ptr context) +{ + LOGI("AuthSrcPinAuthStartState::GetPinCodeFromServerInfo start"); + int32_t pinCode = INVALID_PINCODE; // 没获取到返回默认INVALID_PINCODE, 失败后会进入用户输入PIN流程 +#if 0 // todo + std::vector serviceInfos; + DistributedDeviceProfile::ServiceInfoUniqueKey key; + auto tokenId = std::to_string(context->accesser.tokenId); + key.SetUserId(context->accesser.userId); + key.SetDeviceId(context->accesser.deviceId); + key.SetTokenId(tokenId); + auto ret = DeviceProfileConnector::GetInstance().GetServiceInfoProfileListByTokenId(key, serviceInfos); + if (ret == DM_OK) { + std::vector filterServiceInfos; + for (auto& serviceInfo : serviceInfos) { + if (serviceInfo.GetServiceId() == 0 && serviceInfo.GetServiceType().empty()) { + filterServiceInfos.push_back(serviceInfo); + } + } + if (filterServiceInfos.size() == 1) { + auto& srvInfo = filterServiceInfos[0]; + LOGI("AuthSrcPinAuthStartState::GetPinCodeFromServerInfo got pincode from ServiceInfoProfile"); + pinCode = std::atoi(srvInfo.GetPinCode().c_str()); + } + } else { + LOGE("AuthSinkConfirmState::GetPinCodeFromServerInfo GetServiceInfoByTokenId err %{public}d", ret); + } +#endif + return pinCode; +} + +int32_t AuthSrcPinAuthStartState::GetPinCode(std::shared_ptr context) +{ + LOGI("AuthSrcPinAuthStartState::GetPinCode start"); + if (context->inputPinAuthFailTimes == 0) { + if (context->authType == DmAuthType::AUTH_TYPE_PIN || context->pinNegotiateStarted) { + // 拉起PIN码输入界面 + auto ret = ShowStartAuthDialog(context); + if (ret != DM_OK) { + return ret; + } + } else if (context->authType == DmAuthType::AUTH_TYPE_PIN_ULTRASONIC) { + // todo: 预留超声PinCode获取 + return DM_OK; + } else { + // 从serverInfo中读取PIN码 + context->pinCode = GetPinCodeFromServerInfo(context); + return DM_OK; + } + } else { + // 清空PIN输入框,提示用户重试 + context->authUiStateMgr->UpdateUiState(DmUiStateMsg::MSG_PIN_CODE_ERROR); + } + + LOGI("AuthSrcPinAuthStartState::GetPinCode waitting user operation"); + // 等待用户输密码操作完成 + if(DmEventType::ON_USER_OPERATION != context->authStateMachine->WaitExpectEvent(DmEventType::ON_USER_OPERATION)) { + LOGI("AuthSrcPinAuthStartState::GetPinCode wait ON_USER_OPERATION err"); + return STOP_BIND; // 外部事件错误,中止流程 + } + + if (context->pinInputResult != USER_OPERATION_TYPE_DONE_PINCODE_INPUT) { + LOGE("AuthSrcPinAuthStartState::GetPinCode not USER_OPERATION_TYPE_DONE_PINCODE_INPUT err"); + return STOP_BIND; + } + + LOGI("AuthSrcPinAuthStartState::GetPinCode input ok"); + return DM_OK; +} + + +int32_t AuthSrcPinAuthStartState::AuthDevice(std::shared_ptr context) +{ + int32_t osAccountId = MultipleUserConnector::GetCurrentAccountUserID(); + auto ret = context->hiChainAuthConnector->AuthCredentialPinCode(osAccountId, context->requestId, + context->pinCode); + if (ret != DM_OK) { + LOGE("AuthSrcPinAuthStartState::AuthDevice failed."); + return ret; + } + // 等待hiChain响应 transmit + auto retEvent = context->authStateMachine->WaitExpectEvent(DmEventType::ON_TRANSMIT); + if (retEvent == DmEventType::ON_TRANSMIT) { + // 发送120报文 + context->authMessageProcessor->CreateAndSendMsg(MSG_TYPE_REQ_PIN_AUTH_START, context); + return DM_OK; + } else if (retEvent == DmEventType::ON_ERROR) { + LOGI("AuthSrcPinAuthStartState::AuthDevice ON_ERROR failed."); + return DM_OK; + } + + return STOP_BIND; +} + +int32_t AuthSrcPinAuthStartState::Action(std::shared_ptr context) +{ + LOGI("AuthSrcPinAuthStartState::Action start"); + #ifndef NEW_PIN_STATE // todo del + context->timer->DeleteTimer(std::string(WAIT_REQUEST_TIMEOUT_TASK)); + // 首次进入停止计时器 + if (context->inputPinAuthFailTimes == 0 && !context->pinNegotiateStarted) { + context->timer->DeleteTimer(std::string(CONFIRM_TIMEOUT_TASK)); + } + + // 获取PIN码 + auto ret = GetPinCode(context); + if (ret != DM_OK) { + LOGE("AuthSrcPinAuthStartState::Action GetPinCode err"); + return ret; + } + #endif + // 做认证 发120报文 + return AuthDevice(context); +} + +DmAuthStateType AuthSinkPinAuthStartState::GetStateType() +{ + return DmAuthStateType::AUTH_SINK_PIN_AUTH_START_STATE; +} + +int32_t AuthSinkPinAuthStartState::Action(std::shared_ptr context) +{ + LOGI("AuthSinkPinAuthStartState::Action start"); + context->timer->DeleteTimer(std::string(WAIT_REQUEST_TIMEOUT_TASK)); + context->pinNegotiateStarted = true; + auto ret = context->hiChainAuthConnector->ProcessCredData(context->requestId, context->transmitData); + if (ret != DM_OK) { + LOGE("AuthSinkPinAuthStartState::Action call ProcessCredData err"); + return ret; + } + // 等待hiChain响应 transmit + auto retEvent = context->authStateMachine->WaitExpectEvent(DmEventType::ON_TRANSMIT); + if (retEvent == DmEventType::ON_TRANSMIT) { + // 发送130报文 + context->authMessageProcessor->CreateAndSendMsg(MSG_TYPE_RESP_PIN_AUTH_START, context); + return DM_OK; + } + if (retEvent == DmEventType::ON_ERROR) { + LOGI("AuthSrcPinAuthStartState::AuthDevice ON_ERROR failed."); + return DM_OK; + } + return STOP_BIND; // 外部事件错误,中止流程 +} + +DmAuthStateType AuthSrcPinAuthMsgNegotiateState::GetStateType() +{ + return DmAuthStateType::AUTH_SRC_PIN_AUTH_MSG_NEGOTIATE_STATE; +} + +int32_t AuthSrcPinAuthMsgNegotiateState::Action(std::shared_ptr context) +{ + LOGI("AuthSrcPinAuthMsgNegotiateState::Action start"); + auto ret = context->hiChainAuthConnector->ProcessCredData(context->requestId, context->transmitData); + if (ret != DM_OK) { + LOGE("AuthSrcPinAuthMsgNegotiateState::Action call ProcessCredData err"); + return ret; + } + // 等待hiChain响应 transmit + auto retEvent = context->authStateMachine->WaitExpectEvent(DmEventType::ON_TRANSMIT); + if (retEvent == DmEventType::ON_TRANSMIT) { + // 发送121报文 + context->authMessageProcessor->CreateAndSendMsg(MSG_TYPE_REQ_PIN_AUTH_MSG_NEGOTIATE, context); + return DM_OK; + } + if (retEvent == DmEventType::ON_ERROR) { + LOGI("AuthSrcPinAuthMsgNegotiateState::AuthDevice ON_ERROR failed."); + return DM_OK; + } + return STOP_BIND; // 外部事件错误,中止流程 +} + +DmAuthStateType AuthSinkPinAuthMsgNegotiateState::GetStateType() +{ + return DmAuthStateType::AUTH_SINK_PIN_AUTH_MSG_NEGOTIATE_STATE; +} + +int32_t AuthSinkPinAuthMsgNegotiateState::Action(std::shared_ptr context) +{ + LOGI("AuthSinkPinAuthMsgNegotiateState::Action start"); + auto ret = context->hiChainAuthConnector->ProcessCredData(context->requestId, context->transmitData); + if (ret != DM_OK) { + LOGE("AuthSinkPinAuthMsgNegotiateState::Action call ProcessCredData err"); + return ret; + } + // 等待hiChain响应 transmit + auto retEvent = context->authStateMachine->WaitExpectEvent(DmEventType::ON_TRANSMIT); + if (retEvent == DmEventType::ON_TRANSMIT) { + // 发送131报文 + context->authMessageProcessor->CreateAndSendMsg(MSG_TYPE_RESP_PIN_AUTH_MSG_NEGOTIATE, context); + } else if (retEvent == DmEventType::ON_ERROR) { + LOGI("AuthSinkPinAuthMsgNegotiateState::AuthDevice WAIT ON_TRANSMIT ON_ERROR failed."); + return DM_OK; + } else { + return STOP_BIND; + } + + retEvent = context->authStateMachine->WaitExpectEvent(DmEventType::ON_SESSION_KEY_RETURNED); + if (retEvent == DmEventType::ON_SESSION_KEY_RETURNED) { + retEvent = context->authStateMachine->WaitExpectEvent(DmEventType::ON_FINISH); + if (retEvent == DmEventType::ON_FINISH || retEvent == DmEventType::ON_ERROR) { + context->authStateMachine->TransitionTo(std::make_shared()); + return DM_OK; + } + } else if (retEvent == DmEventType::ON_ERROR) { + LOGI("AuthSinkPinAuthMsgNegotiateState::AuthDevice WAIT ON_SESSION_KEY_RETURNED ON_ERROR failed."); + return DM_OK; + } + + LOGE("AuthSinkPinAuthMsgNegotiateState::AuthDevice failed."); + return STOP_BIND; // 外部事件错误,中止流程 +} + +DmAuthStateType AuthSinkPinAuthDoneState::GetStateType() +{ + return DmAuthStateType::AUTH_SINK_PIN_AUTH_DONE_STATE; +} + +int32_t AuthSinkPinAuthDoneState::Action(std::shared_ptr context) +{ + LOGI("AuthSinkPinAuthDoneState Action"); + return DM_OK; +} + +DmAuthStateType AuthSrcPinAuthDoneState::GetStateType() +{ + return DmAuthStateType::AUTH_SRC_PIN_AUTH_DONE_STATE; +} + +int32_t AuthSrcPinAuthDoneState::Action(std::shared_ptr context) +{ + if (context == nullptr || context->hiChainAuthConnector == nullptr) { + LOGE("AuthSrcPinAuthDoneState::Action failed, auth context not initial."); + return ERR_DM_FAILED; + } + + LOGI("AuthSrcPinAuthDoneState::Action start"); + // 处理凭据数据 + std::string onTransmitData = context->transmitData; + if (context->hiChainAuthConnector->ProcessCredData(context->requestId, onTransmitData) != DM_OK) { + LOGE("AuthSrcPinAuthDoneState::Action failed, processCredData failed."); + return ERR_DM_FAILED; + } + + // 阻塞等待ON_SESSION_KEY_RETURNED事件到来 + DmEventType ret = context->authStateMachine->WaitExpectEvent(ON_SESSION_KEY_RETURNED); + if (ret != ON_SESSION_KEY_RETURNED) { + if (ret == ON_ERROR) { // ON_ERROR事件到来,返回DM_OK, OnError回调中判断是否重试 + LOGE("AuthSrcPinAuthDoneState::Action, ON_SESSION_KEY_RETURNED event not arriverd, try again."); + return DM_OK; + } else { // 其它事件到来 + LOGE("AuthSrcPinAuthDoneState::Action failed, ON_SESSION_KEY_RETURNED event failed, other event arriverd."); + return ERR_DM_FAILED; + } + } + + LOGI("AuthSrcPinAuthDoneState::Action wait ON_SESSION_KEY_RETURNED done"); + // 阻塞等待ON_FINISH事件到来 + ret = context->authStateMachine->WaitExpectEvent(ON_FINISH); + if (ret == ON_FINISH) { + LOGI("AuthSrcPinAuthDoneState::Action wait ON_FINISH done"); + return DM_OK; + } else if (ret == ON_ERROR) { // ON_ERROR事件到来,返回DM_OK, OnError回调中判断是否重试 + return DM_OK; + LOGE("AuthSrcPinAuthDoneState::Action, ON_FINISH event not arriverd, try again."); + } + + return ERR_DM_FAILED; +} + +DmAuthStateType AuthSrcPinNegotiateStartState::GetStateType() +{ + return DmAuthStateType::AUTH_SRC_PIN_NEGOTIATE_START_STATE; +} + +int32_t AuthSrcPinNegotiateStartState::Action(std::shared_ptr context) +{ + if (!context->pinNegotiateStarted) { + // 首次认证 + context->pinNegotiateStarted = true; + context->timer->DeleteTimer(std::string(CONFIRM_TIMEOUT_TASK)); + int32_t authResult = context->authResult; + if (authResult != USER_OPERATION_TYPE_ALLOW_AUTH && + authResult != USER_OPERATION_TYPE_ALLOW_AUTH_ALWAYS) { + LOGE("AuthSrcPinNegotiateStartState::Action authResult not allow"); + context->reason = ERR_DM_BIND_USER_CANCEL; + return ERR_DM_BIND_USER_CANCEL; + } + } else { + // 回退处理 + if (context->authType == DmAuthType::AUTH_TYPE_PIN && + context->inputPinAuthFailTimes < MAX_AUTH_INPUT_PIN_FAIL_TIMES) { + LOGI("AuthSrcPinNegotiateStartState::Action input pin auth err, retry"); + } else { + if (context->currentAuthTypeIdx + 1 >= context->authTypeList.size()) { + LOGE("AuthSrcPinNegotiateStartState::Action all auth type failed"); + context->reason = ERR_DM_AUTH_REJECT; + return ERR_DM_AUTH_REJECT; + } + context->currentAuthTypeIdx++; + context->authType = context->authTypeList[context->currentAuthTypeIdx]; + } + } + + if (context->authType == DmAuthType::AUTH_TYPE_IMPORT_AUTH_CODE) { + context->authStateMachine->TransitionTo(std::make_shared()); + } else if (context->authType == DmAuthType::AUTH_TYPE_PIN) { + context->authStateMachine->TransitionTo(std::make_shared()); + } else if (context->authType == DmAuthType::AUTH_TYPE_PIN_ULTRASONIC) { + context->authStateMachine->TransitionTo(std::make_shared()); + } else { + LOGE("AuthSrcPinNegotiateStartState::Action authType not support"); + return ERR_DM_FAILED; + } + return DM_OK; +} + +DmAuthStateType AuthSrcPinInputState::GetStateType() +{ + return DmAuthStateType::AUTH_SRC_PIN_INPUT_STATE; +} + +int32_t AuthSrcPinInputState::ShowStartAuthDialog(std::shared_ptr context) +{ + LOGI("AuthSrcPinInputState::ShowStartAuthDialog start."); + if (DmAuthState::IsScreenLocked()) { + LOGE("AuthSrcPinInputState screen is locked."); + context->reason = ERR_DM_BIND_USER_CANCEL; + return STOP_BIND; + } + DmDialogManager::GetInstance().ShowInputDialog(context->accessee.deviceName); + LOGI("AuthSrcPinInputState::ShowStartAuthDialog end."); + return DM_OK; +} + +int32_t AuthSrcPinInputState::Action(std::shared_ptr context) +{ + LOGI("AuthSrcPinInputState::Action start"); + if (context->inputPinAuthFailTimes == 0) { + // 拉起PIN码输入界面 + auto ret = ShowStartAuthDialog(context); + if (ret != DM_OK) { + return ret; + } + } else { + // 清空PIN输入框,提示用户重试 + context->authUiStateMgr->UpdateUiState(DmUiStateMsg::MSG_PIN_CODE_ERROR); + } + + LOGI("AuthSrcPinInputState::Action waitting user operation"); + // 等待用户输密码操作完成 + if(DmEventType::ON_USER_OPERATION != context->authStateMachine->WaitExpectEvent(DmEventType::ON_USER_OPERATION)) { + LOGI("AuthSrcPinInputState::Action wait ON_USER_OPERATION err"); + return STOP_BIND; // 外部事件错误,中止流程 + } + + if (context->pinInputResult != USER_OPERATION_TYPE_DONE_PINCODE_INPUT) { + LOGE("AuthSrcPinInputState::Action not USER_OPERATION_TYPE_DONE_PINCODE_INPUT err"); + return STOP_BIND; + } + context->authStateMachine->TransitionTo(std::make_shared()); + LOGI("AuthSrcPinInputState::Action input ok"); + return DM_OK; +} + +DmAuthStateType AuthSinkPinNegotiateStartState::GetStateType() +{ + return DmAuthStateType::AUTH_SINK_PIN_NEGOTIATE_START_STATE; +} + +int32_t AuthSinkPinNegotiateStartState::Action(std::shared_ptr context) +{ + if (!context->pinNegotiateStarted) { + context->pinNegotiateStarted = true; + } else { + // 回退处理 + if (context->authType == DmAuthType::AUTH_TYPE_PIN && + context->inputPinAuthFailTimes < MAX_AUTH_INPUT_PIN_FAIL_TIMES) { + LOGI("AuthSinkPinNegotiateStartState::Action input pin auth err, retry"); + } else { + if (context->currentAuthTypeIdx + 1 >= context->authTypeList.size()) { + LOGE("AuthSinkPinNegotiateStartState::Action all auth type failed"); + context->reason = ERR_DM_AUTH_REJECT; + return ERR_DM_AUTH_REJECT; + } + context->currentAuthTypeIdx++; + context->authType = context->authTypeList[context->currentAuthTypeIdx]; + } + } + if (context->authType == DmAuthType::AUTH_TYPE_IMPORT_AUTH_CODE) { + LOGI("AuthSinkPinNegotiateStartState::Action import auth code"); + } else if (context->authType == DmAuthType::AUTH_TYPE_PIN) { + LOGI("AuthSinkPinNegotiateStartState::Action input pin"); + context->authStateMachine->TransitionTo(std::make_shared()); + } else if (context->authType == DmAuthType::AUTH_TYPE_PIN_ULTRASONIC) { + LOGI("AuthSinkPinNegotiateStartState::Action ultrasonic pin"); + } else { + LOGE("AuthSrcPinNegotiateStartState::Action authType not support"); + return ERR_DM_FAILED; + } + return DM_OK; +} + +DmAuthStateType AuthSinkPinDisplayState::GetStateType() +{ + return DmAuthStateType::AUTH_SINK_PIN_DISPLAY_STATE; +} + +int32_t AuthSinkPinDisplayState::Action(std::shared_ptr context) +{ + if (context->inputPinAuthFailTimes == 0) { + // 生成PIN码 + AuthSinkStatePinAuthComm::GeneratePincode(context); + // 显示PIN码 + return AuthSinkStatePinAuthComm::ShowAuthInfoDialog(context); + } + return DM_OK; +} + +DmAuthStateType AuthSrcPinNegotiateUltrasonicPinState::GetStateType() +{ + return DmAuthStateType::AUTH_SRC_PIN_NEGOTIATE_ULTRASONIC_PIN_STATE; +} + +int32_t AuthSrcPinNegotiateUltrasonicPinState::Action(std::shared_ptr context) +{ + return ERR_DM_FAILED; +} + +DmAuthStateType AuthSinkPinNegotiateUltrasonicPinState::GetStateType() +{ + return DmAuthStateType::AUTH_SINK_PIN_NEGOTIATE_ULTRASONIC_PIN_STATE; +} + +int32_t AuthSinkPinNegotiateUltrasonicPinState::Action(std::shared_ptr context) +{ + return ERR_DM_FAILED; +} + +} // namespace DistributedHardware +} // namespace OHOS \ No newline at end of file diff --git a/services/implementation/src/authentication_v2/dm_auth_context.cpp b/services/implementation/src/authentication_v2/dm_auth_context.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8db58bb7ff6cb8d61dd10e0d6c74081dbc43b9f9 --- /dev/null +++ b/services/implementation/src/authentication_v2/dm_auth_context.cpp @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "dm_auth_context.h" +#undef LOG_TAG +#define LOG_TAG "DHDM_V2" + +namespace OHOS { +namespace DistributedHardware { + +// 获取设备ID +std::string DmAuthContext::GetDeviceId(DmAuthSide side) +{ + if (side == DM_AUTH_LOCAL_SIDE) { + return (direction == DM_AUTH_SOURCE) ? accesser.deviceId : accessee.deviceId; + } else if (side == DM_AUTH_REMOTE_SIDE) { + return (direction == DM_AUTH_SOURCE) ? accessee.deviceId : accesser.deviceId; + } else { + return std::string(""); + } +} + +// 获取用户ID +int32_t DmAuthContext::GetUserId(DmAuthSide side) +{ + if (side == DM_AUTH_LOCAL_SIDE) { + return (direction == DM_AUTH_SOURCE) ? accesser.userId : accessee.userId; + } else { + return (direction == DM_AUTH_SOURCE) ? accessee.userId : accesser.userId; + } +} + +// 获取凭据ID +std::string DmAuthContext::GetCredentialId(DmAuthSide side, DmAuthScope authorizedScope) +{ + if ((side != DM_AUTH_LOCAL_SIDE && side != DM_AUTH_REMOTE_SIDE) || + (authorizedScope != DM_AUTH_SCOPE_USER && authorizedScope != DM_AUTH_SCOPE_APP)) { + return std::string(""); + } + + if (side == DM_AUTH_LOCAL_SIDE) { + if (direction == DM_AUTH_SOURCE) { + return (authorizedScope == DM_AUTH_SCOPE_USER) ? accesser.userCredentialId : accesser.appCredentialId; + } else { + return (authorizedScope == DM_AUTH_SCOPE_USER) ? accessee.userCredentialId : accessee.appCredentialId; + } + } else { + if (direction == DM_AUTH_SOURCE) { + return (authorizedScope == DM_AUTH_SCOPE_USER) ? accessee.userCredentialId : accessee.appCredentialId; + } else { + return (authorizedScope == DM_AUTH_SCOPE_USER) ? accesser.userCredentialId : accesser.appCredentialId; + } + } +} + +// 获取公钥 +std::string DmAuthContext::GetPublicKey(DmAuthSide side, DmAuthScope authorizedScope) +{ + if ((side != DM_AUTH_LOCAL_SIDE && side != DM_AUTH_REMOTE_SIDE) || + (authorizedScope != DM_AUTH_SCOPE_USER && authorizedScope != DM_AUTH_SCOPE_APP)) { + return std::string(""); + } + + if (side == DM_AUTH_LOCAL_SIDE) { + if (direction == DM_AUTH_SOURCE) { + return (authorizedScope == DM_AUTH_SCOPE_USER) ? accesser.userPublicKey : accesser.appPublicKey; + } else { + return (authorizedScope == DM_AUTH_SCOPE_USER) ? accessee.userPublicKey : accessee.appPublicKey; + } + } else { + if (direction == DM_AUTH_SOURCE) { + return (authorizedScope == DM_AUTH_SCOPE_USER) ? accessee.userPublicKey : accessee.appPublicKey; + } else { + return (authorizedScope == DM_AUTH_SCOPE_USER) ? accesser.userPublicKey : accesser.appPublicKey; + } + } +} + +// 设置凭据ID +int32_t DmAuthContext::SetCredentialId(DmAuthSide side, DmAuthScope authorizedScope, const std::string &credentialId) +{ + if ((side != DM_AUTH_LOCAL_SIDE && side != DM_AUTH_REMOTE_SIDE) || + (authorizedScope != DM_AUTH_SCOPE_USER && authorizedScope != DM_AUTH_SCOPE_APP)) { + LOGE("DmAuthContext::SetCredentialId() error, invalid input parameters"); + return ERR_DM_FAILED; + } + if (side == DM_AUTH_LOCAL_SIDE) { + if (direction == DM_AUTH_SOURCE) { + if (authorizedScope == DM_AUTH_SCOPE_USER) { + accesser.userCredentialId = credentialId; + } else { + accesser.appCredentialId = credentialId; + } + } else { + if (authorizedScope == DM_AUTH_SCOPE_USER) { + accessee.userCredentialId = credentialId; + } else { + accessee.appCredentialId = credentialId; + } + } + } else { + if (direction == DM_AUTH_SOURCE) { + if (authorizedScope == DM_AUTH_SCOPE_USER) { + accessee.userCredentialId = credentialId; + } else { + accessee.appCredentialId = credentialId; + } + } else { + if (authorizedScope == DM_AUTH_SCOPE_USER) { + accesser.userCredentialId = credentialId; + } else { + accesser.appCredentialId = credentialId; + } + } + } + return DM_OK; +} + +// 设置公钥 +int32_t DmAuthContext::SetPublicKey(DmAuthSide side, DmAuthScope authorizedScope, const std::string &publicKey) +{ + if ((side != DM_AUTH_LOCAL_SIDE && side != DM_AUTH_REMOTE_SIDE) || + (authorizedScope != DM_AUTH_SCOPE_USER && authorizedScope != DM_AUTH_SCOPE_APP)) { + LOGE("DmAuthContext::SetPublicKey() error, invalid input parameters"); + return ERR_DM_FAILED; + } + + if (side == DM_AUTH_LOCAL_SIDE) { + if (direction == DM_AUTH_SOURCE) { + if (authorizedScope == DM_AUTH_SCOPE_USER) { + accesser.userPublicKey = publicKey; + } else { + accesser.appPublicKey = publicKey; + } + } else { + if (authorizedScope == DM_AUTH_SCOPE_USER) { + accessee.userPublicKey = publicKey; + } else { + accessee.appPublicKey = publicKey; + } + } + } else { + if (direction == DM_AUTH_SOURCE) { + if (authorizedScope == DM_AUTH_SCOPE_USER) { + accessee.userPublicKey = publicKey; + } else { + accessee.appPublicKey = publicKey; + } + } else { + if (authorizedScope == DM_AUTH_SCOPE_USER) { + accesser.userPublicKey = publicKey; + } else { + accesser.appPublicKey = publicKey; + } + } + } + + return DM_OK; +} + +std::string DmAuthContext::GetAccountId(DmAuthSide side) +{ + if (side == DM_AUTH_LOCAL_SIDE) { + return (direction == DM_AUTH_SOURCE) ? accesser.accountId : accessee.accountId; + } else { + return (direction == DM_AUTH_SOURCE) ? accessee.accountId : accesser.accountId; + } +} +} // namespace DistributedHardware +} // namespace OHOS \ No newline at end of file diff --git a/services/implementation/src/authentication_v2/dm_auth_manager_base.cpp b/services/implementation/src/authentication_v2/dm_auth_manager_base.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2a5fce0e95a417f9960d9426fad836836e3ddf6c --- /dev/null +++ b/services/implementation/src/authentication_v2/dm_auth_manager_base.cpp @@ -0,0 +1,289 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "dm_error_type.h" +#include "dm_auth_manager_base.h" + +#undef LOG_TAG +#define LOG_TAG "DHDM_V2" + +namespace OHOS { +namespace DistributedHardware { + +int32_t AuthManagerBase::AuthenticateDevice(const std::string &pkgName, int32_t authType, + const std::string &deviceId, const std::string &extra) +{ + LOGE("AuthenticateDevice is not implemented in the current version"); + return ERR_DM_FAILED; +} + +int32_t AuthManagerBase::UnAuthenticateDevice(const std::string &pkgName, const std::string &udid, int32_t bindLevel) +{ + LOGE("UnAuthenticateDevice is not implemented in the current version"); + return ERR_DM_FAILED; +} + +int32_t AuthManagerBase::UnBindDevice(const std::string &pkgName, const std::string &udid, + int32_t bindLevel, const std::string &extra) +{ + LOGE("UnBindDevice is not implemented in the current version"); + return ERR_DM_FAILED; +} + +void AuthManagerBase::OnSessionOpened(int32_t sessionId, int32_t sessionSide, int32_t result) +{ + LOGE("OnSessionOpened is not implemented in the current version"); +} + +void AuthManagerBase::OnSessionClosed(const int32_t sessionId) +{ + LOGE("OnSessionClosed is not implemented in the current version"); +} + +void AuthManagerBase::OnDataReceived(const int32_t sessionId, const std::string message) +{ + LOGE("OnDataReceived is not implemented in the current version"); +} + +void AuthManagerBase::OnGroupCreated(int64_t requestId, const std::string &groupId) +{ + LOGE("OnGroupCreated is not implemented in the current version"); +} + +void AuthManagerBase::OnMemberJoin(int64_t requestId, int32_t status) +{ + LOGE("OnMemberJoin is not implemented in the current version"); +} + +int32_t AuthManagerBase::EstablishAuthChannel(const std::string &deviceId) +{ + LOGE("EstablishAuthChannel is not implemented in the current version"); + return ERR_DM_FAILED; +} + +void AuthManagerBase::StartNegotiate(const int32_t &sessionId) +{ + LOGE("StartNegotiate is not implemented in the current version"); +} + +void AuthManagerBase::RespNegotiate(const int32_t &sessionId) +{ + LOGE("RespNegotiate is not implemented in the current version"); +} + +void AuthManagerBase::SendAuthRequest(const int32_t &sessionId) +{ + LOGE("SendAuthRequest is not implemented in the current version"); +} + +int32_t AuthManagerBase::StartAuthProcess(const int32_t &action) +{ + LOGE("StartAuthProcess is not implemented in the current version"); + return ERR_DM_FAILED; +} + +void AuthManagerBase::StartRespAuthProcess() +{ + LOGE("StartRespAuthProcess is not implemented in the current version"); +} + +int32_t AuthManagerBase::CreateGroup() +{ + LOGE("CreateGroup is not implemented in the current version"); + return ERR_DM_FAILED; +} + +int32_t AuthManagerBase::ProcessPincode(int32_t pinCode) +{ + LOGE("ProcessPincode is not implemented in the current version"); + return ERR_DM_FAILED; +} + +std::string AuthManagerBase::GetConnectAddr(std::string deviceId) +{ + LOGE("GetConnectAddr is not implemented in the current version"); + return ""; +} + +int32_t AuthManagerBase::JoinNetwork() +{ + LOGE("JoinNetwork is not implemented in the current version"); + return ERR_DM_FAILED; +} + +void AuthManagerBase::AuthenticateFinish() +{ + LOGE("AuthenticateFinish is not implemented in the current version"); +} + +bool AuthManagerBase::GetIsCryptoSupport() +{ + LOGE("GetIsCryptoSupport is not implemented in the current version"); + return false; +} + +int32_t AuthManagerBase::SetAuthRequestState(std::shared_ptr authRequestState) +{ + LOGE("SetAuthRequestState is not implemented in the current version"); + return ERR_DM_FAILED; +} + +int32_t AuthManagerBase::SetAuthResponseState(std::shared_ptr authResponseState) +{ + LOGE("SetAuthResponseState is not implemented in the current version"); + return ERR_DM_FAILED; +} + +int32_t AuthManagerBase::GetPinCode(int32_t &code) +{ + LOGE("GetPinCode is not implemented in the current version"); + return ERR_DM_FAILED; +} + +std::string AuthManagerBase::GenerateGroupName() +{ + LOGE("GenerateGroupName is not implemented in the current version"); + return ""; +} + +void AuthManagerBase::HandleAuthenticateTimeout(std::string name) +{ + LOGE("HandleAuthenticateTimeout is not implemented in the current version"); +} + +int32_t AuthManagerBase::GeneratePincode() +{ + LOGE("GeneratePincode is not implemented in the current version"); + return ERR_DM_FAILED; +} + +void AuthManagerBase::ShowConfigDialog() +{ + LOGE("ShowConfigDialog is not implemented in the current version"); +} + +void AuthManagerBase::ShowAuthInfoDialog(bool authDeviceError) +{ + LOGE("ShowAuthInfoDialog is not implemented in the current version"); +} + +void AuthManagerBase::ShowStartAuthDialog() +{ + LOGE("ShowStartAuthDialog is not implemented in the current version"); +} + +int32_t AuthManagerBase::OnUserOperation(int32_t action, const std::string ¶ms) +{ + LOGE("OnUserOperation is not implemented in the current version"); + return ERR_DM_FAILED; +} + +int32_t AuthManagerBase::SetPageId(int32_t pageId) +{ + LOGE("SetPageId is not implemented in the current version"); + return ERR_DM_FAILED; +} + +int32_t AuthManagerBase::SetReasonAndFinish(int32_t reason, int32_t state) +{ + LOGE("SetReasonAndFinish is not implemented in the current version"); + return ERR_DM_FAILED; +} + +bool AuthManagerBase::IsIdenticalAccount() +{ + LOGE("IsIdenticalAccount is not implemented in the current version"); + return false; +} + +int32_t AuthManagerBase::RegisterUiStateCallback(const std::string pkgName) +{ + LOGE("RegisterUiStateCallback is not implemented in the current version"); + return ERR_DM_FAILED; +} + +int32_t AuthManagerBase::UnRegisterUiStateCallback(const std::string pkgName) +{ + LOGE("UnRegisterUiStateCallback is not implemented in the current version"); + return ERR_DM_FAILED; +} + +int32_t AuthManagerBase::ImportAuthCode(const std::string &pkgName, const std::string &authCode) +{ + LOGE("ImportAuthCode is not implemented in the current version"); + return ERR_DM_FAILED; +} + +int32_t AuthManagerBase::BindTarget(const std::string &pkgName, const PeerTargetId &targetId, + const std::map &bindParam) +{ + LOGE("BindTarget is not implemented in the current version"); + return ERR_DM_FAILED; +} + +int32_t AuthManagerBase::RegisterAuthenticationType(int32_t authenticationType) +{ + LOGE("RegisterAuthenticationType is not implemented in the current version"); + return ERR_DM_FAILED; +} + +int32_t AuthManagerBase::StopAuthenticateDevice(const std::string &pkgName) +{ + LOGE("StopAuthenticateDevice is not implemented in the current version"); + return ERR_DM_FAILED; +} + +int32_t AuthManagerBase::GetReason() +{ + LOGE("GetReason is not implemented in the current version"); + return ERR_DM_FAILED; +} + +void AuthManagerBase::GetBindTargetParams(std::string &pkgName, PeerTargetId &targetId, + std::map &bindParam) +{ + LOGE("GetBindTargetParams is not implemented in the current version"); + return; +} + +std::string AuthManagerBase::ConvertSrcVersion(const std::string &version, const std::string &edition) +{ + std::string srcVersion = ""; + if (version == "" && edition != "") { + srcVersion = edition; + } else if (version == "" && edition == "") { + srcVersion = DM_VERSION_5_1_0; + } else if (version != "" && edition == "") { + srcVersion = version; + } + LOGI("ConvertSrcVersion version %{public}s, edition %{public}s, srcVersion is %{public}s.", + version.c_str(), edition.c_str(), srcVersion.c_str()); + return srcVersion; +} + +std::string AuthManagerBase::ConvertSinkVersion(const std::string &version) +{ + std::string sinkVersion = ""; + if (version == "") { + sinkVersion = DM_VERSION_4_1_5_1; + } else { + sinkVersion = version; + } + LOGI("ConvertSinkVersion version %{public}s, sinkVersion is %{public}s.", version.c_str(), sinkVersion.c_str()); + return sinkVersion; +} + +} // namespace DistributedHardware +} // namespace OHOS \ No newline at end of file diff --git a/services/implementation/src/authentication_v2/dm_auth_message_processor.cpp b/services/implementation/src/authentication_v2/dm_auth_message_processor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d923d1b2d27a93bb73785f6b7fcc963ce1ff1130 --- /dev/null +++ b/services/implementation/src/authentication_v2/dm_auth_message_processor.cpp @@ -0,0 +1,1277 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 +#include +#include +#include +#include "dm_anonymous.h" +#include "dm_auth_context.h" +#include "dm_auth_message_processor.h" +#include "distributed_device_profile_client.h" +#include "deviceprofile_connector.h" +#include "service_info_profile.h" +#include "service_info_unique_key.h" +#include "dm_log.h" +#include "dm_constants.h" +#include "dm_anonymous.h" +#include "access_control_profile.h" +#include "dm_auth_manager_base.h" +#include "dm_auth_context.h" +#include "dm_auth_state_machine.h" +#include "dm_crypto.h" +#undef LOG_TAG +#define LOG_TAG "DHDM_V2" + +namespace OHOS { +namespace DistributedHardware { + +namespace { + +constexpr const char* TAG_DEVICE_TYPE = "deviceType"; + +void CreateNegotiateExtraInfoMessage(std::shared_ptr context, nlohmann::json &jsonExtraObject) +{ + if (context->accessee.displayId != 0) { + jsonExtraObject[DM_TAG_PEER_DISPLAY_ID] = context->accessee.displayId; + } + + return; +} + +void ParseNegotiateExtraInfoMessage(nlohmann::json &jsonExtraObject, std::shared_ptr context) +{ + // accesser在extra中传输对端peerUserId和peerDisplayId时,从中获取userId + if (IsInt32(jsonExtraObject, DM_TAG_ACCESSEE_USER_ID)) { + context->accessee.userId = jsonExtraObject[DM_TAG_ACCESSEE_USER_ID].get(); + } else if (IsInt32(jsonExtraObject, DM_TAG_PEER_DISPLAY_ID)) { + context->accessee.displayId = jsonExtraObject[DM_TAG_PEER_DISPLAY_ID].get(); + } + + return; +} + +} + +// 保存秘钥 +int32_t DmAuthMessageProcessor::SaveSessionKey(const uint8_t *sessionKey, const uint32_t keyLen) +{ + if (cryptoMgr_ == nullptr) { + LOGE("DmAuthMessageProcessor::SaveSessionKey failed, cryptoMgr_ is nullptr."); + return ERR_DM_FAILED; + } + return cryptoMgr_->SaveSessionKey(sessionKey, keyLen); +} + +// 保存永久SK +int32_t DmAuthMessageProcessor::SaveSessionKeyToDP(int32_t &skId) +{ + if (cryptoMgr_ == nullptr) { + LOGE("DmAuthMessageProcessor::SaveSessionKey failed, cryptoMgr_ is nullptr."); + return ERR_DM_FAILED; + } + uint32_t skLen = cryptoMgr_->GetSessionKey(nullptr); + uint8_t sessionKey[skLen]; + skLen = cryptoMgr_->GetSessionKey(sessionKey); + std::vector sk(sessionKey, sessionKey + skLen); + return DeviceProfileConnector::GetInstance().PutSessionKey(sk, skId); +} + +int32_t DmAuthMessageProcessor::PutAccessControlList(std::shared_ptr context, + DmAccess &access, std::string trustDeviceId) +{ + LOGI("Start."); + uint32_t bindType = DM_ACROSS_ACCOUNT; + if (context->accesser.accountId == "ohosAnonymousUid" || context->accessee.accountId == "ohosAnonymousUid") { + bindType = DM_POINT_TO_POINT; + } + uint32_t authenticationType = ALLOW_AUTH_ONCE; + if (context->authResult == USER_OPERATION_TYPE_ALLOW_AUTH_ALWAYS) { + authenticationType = ALLOW_AUTH_ALWAYS; + } + DistributedDeviceProfile::Accesser accesser; + accesser.SetAccesserDeviceId(context->accesser.deviceId); + accesser.SetAccesserUserId(context->accesser.userId); + accesser.SetAccesserAccountId(context->accesser.accountId); + accesser.SetAccesserTokenId(context->accesser.tokenId); + accesser.SetAccesserBundleName(context->accesser.bundleName); + accesser.SetAccesserDeviceName(context->accesser.deviceName); + accesser.SetAccesserServiceId(context->accesser.serviceId); + accesser.SetAccesserCredentialId(context->accesser.credentialId); + accesser.SetAccesserSessionKeyId(context->accesser.sessionKeyId); + accesser.SetAccesserSKTimeStamp(context->accesser.skTimeStamp); + DistributedDeviceProfile::Accessee accessee; + accessee.SetAccesseeDeviceId(context->accessee.deviceId); + accessee.SetAccesseeUserId(context->accessee.userId); + accessee.SetAccesseeAccountId(context->accessee.accountId); + accessee.SetAccesseeTokenId(context->accessee.tokenId); + accessee.SetAccesseeBundleName(context->accessee.bundleName); + accessee.SetAccesseeDeviceName(context->accessee.deviceName); + accessee.SetAccesseeServiceId(context->accessee.serviceId); + accessee.SetAccesseeCredentialId(context->accessee.credentialId); + accessee.SetAccesseeSessionKeyId(context->accessee.sessionKeyId); + accessee.SetAccesseeSKTimeStamp(context->accessee.skTimeStamp); + DistributedDeviceProfile::AccessControlProfile profile; + profile.SetBindType(bindType); + profile.SetBindLevel(access.bindLevel); + profile.SetStatus(ACTIVE); + profile.SetTrustDeviceId(trustDeviceId); + profile.SetDeviceIdType((int32_t)DistributedDeviceProfile::DeviceIdType::UDID); + profile.SetDeviceIdHash(access.deviceIdHash); + profile.SetAuthenticationType(authenticationType); + profile.SetAccessee(accessee); + profile.SetAccesser(accesser); + int32_t ret = + DistributedDeviceProfile::DistributedDeviceProfileClient::GetInstance().PutAccessControlProfile(profile); + if (ret != DM_OK) { + LOGE("PutAccessControlProfile failed."); + } + return ret; +} + +DmAuthMessageProcessor::DmAuthMessageProcessor() +{ + LOGI("DmAuthMessageProcessor constructor"); + cryptoMgr_ = std::make_shared(); +} + +DmAuthMessageProcessor::~DmAuthMessageProcessor() +{ + if (cryptoMgr_ != nullptr) { + cryptoMgr_->ClearSessionKey(); + cryptoMgr_ = nullptr; + } +} + +// 解析报文,返回值为错误码,实际解析出来的信息保存到context中 +int32_t DmAuthMessageProcessor::ParseMessage(std::shared_ptr context, const std::string &message) +{ + if (context == nullptr) { + return ERR_DM_FAILED; + } + + nlohmann::json jsonObject = nlohmann::json::parse(message, nullptr, false); + if (jsonObject.is_discarded()) { + LOGE("DmAuthMessageProcessor::ParseMessage failed, decodeRequestAuth jsonStr error"); + return ERR_DM_FAILED; + } + if (!IsInt32(jsonObject, TAG_MSG_TYPE)) { + LOGE("DmAuthMessageProcessor::ParseMessage failed, message type error."); + return ERR_DM_FAILED; + } + DmMessageType msgType = static_cast(jsonObject[TAG_MSG_TYPE].get()); + context->msgType = msgType; + LOGI("DmAuthMessageProcessor::ParseMessage message type %{public}d", context->msgType); + // TODO:调试信息,上库前删除 + LOGI("DmAuthMessageProcessor::ParseMessage %{public}s", SafetyDump(jsonObject).c_str()); + switch (msgType) { + case MSG_TYPE_REQ_ACL_NEGOTIATE: + return ParseNegotiateMessage(jsonObject, context); + case MSG_TYPE_RESP_ACL_NEGOTIATE: + return ParseMessageRespAclNegotiate(jsonObject, context); + case MSG_TYPE_REQ_USER_CONFIRM: + return ParseMessageReqUserConfirm(jsonObject, context); + case MSG_TYPE_RESP_USER_CONFIRM: + return ParseMessageRespUserConfirm(jsonObject, context); + case MSG_TYPE_REQ_PIN_AUTH_START: + return ParseMessageReqPinAuthStart(jsonObject, context); + case MSG_TYPE_REQ_PIN_AUTH_MSG_NEGOTIATE: + return ParseMessageReqPinAuthNegotiate(jsonObject, context); + case MSG_TYPE_RESP_PIN_AUTH_START: + return ParseMessageRespPinAuthStart(jsonObject, context); + case MSG_TYPE_REQ_CREDENTIAL_AUTH_START: // 160 + return ParseAuthStartMessgae(jsonObject, context); + case MSG_TYPE_REQ_CREDENTIAL_AUTH_NEGOTIATE: // 161 + case MSG_TYPE_RESP_CREDENTIAL_AUTH_START: // 170 + case MSG_TYPE_RESP_CREDENTIAL_AUTH_NEGOTIATE: // 171 + return ParseMessageNegotiateTransmit(jsonObject, context, msgType); + case MSG_TYPE_RESP_PIN_AUTH_MSG_NEGOTIATE: + return ParseMessageRespPinAuthNegotiate(jsonObject, context); + case MSG_TYPE_REQ_CREDENTIAL_EXCHANGE: + return ParseMessageReqCredExchange(jsonObject, context); + case MSG_TYPE_RESP_CREDENTIAL_EXCHANGE: + return ParseMessageRspCredExchange(jsonObject, context); + case MSG_TYPE_REQ_DATA_SYNC: + return ParseMessageSyncReq(jsonObject, context); + case MSG_TYPE_RESP_DATA_SYNC: + return ParseMessageSyncResp(jsonObject, context); + default: + break; + } + return ERR_DM_FAILED; +} + +static std::vector stringToVector(const std::string& str) { + std::vector vec; + std::istringstream iss(str); + int32_t num; + while (iss >> num) { + vec.push_back(static_cast(num)); + } + return vec; +} + +static std::string vectorToString(const std::vector& vec) { + std::ostringstream oss; + for (size_t i = 0; i < vec.size(); ++i) { + oss << static_cast(vec[i]); + if (i != vec.size() - 1) { + oss << " "; // 添加分隔符(例如空格) + } + } + return oss.str(); +} + +int32_t DmAuthMessageProcessor::ParseMessageNegotiateTransmit(const nlohmann::json &jsonObject, + std::shared_ptr &context, DmMessageType msgType) +{ + if (jsonObject.is_discarded() || !jsonObject.contains(DM_TAG_DATA) || !jsonObject[DM_TAG_DATA].is_string()) { + LOGE("DmAuthMessageProcessor::ParseMessageNegotiateTransmit Unlegal json string failed"); + return ERR_DM_FAILED; + } + + context->transmitData = jsonObject[DM_TAG_DATA].get(); + + switch (msgType) { + case MSG_TYPE_REQ_CREDENTIAL_AUTH_NEGOTIATE: // 161 + context->authStateMachine->TransitionTo(std::make_shared()); + break; + case MSG_TYPE_RESP_CREDENTIAL_AUTH_START: // 170 + context->authStateMachine->TransitionTo(std::make_shared()); + break; + case MSG_TYPE_RESP_CREDENTIAL_AUTH_NEGOTIATE: // 171 + context->authStateMachine->TransitionTo(std::make_shared()); + break; + default: + return ERR_DM_FAILED; + } + + return DM_OK; +} + +// 解析131报文信息MSG_TYPE_RESP_PIN_AUTH_MSG_NEGOTIATE +int32_t DmAuthMessageProcessor::ParseMessageRespPinAuthNegotiate(const nlohmann::json &jsonObject, + std::shared_ptr context) +{ + if (jsonObject.is_discarded() || !IsString(jsonObject, DM_TAG_DATA)) { + LOGE("DmAuthMessageProcessor::ParseMessageRespPinAuthNegotiate failed, decodeRequestAuth jsonStr error"); + return ERR_DM_FAILED; + } + + context->transmitData = jsonObject[DM_TAG_DATA].get(); + context->authStateMachine->TransitionTo(std::make_shared()); + return DM_OK; +} + +// 解析140报文信息MSG_TYPE_REQ_CREDENTIAL_EXCHANGE,SINK端存放对方公钥 +int32_t DmAuthMessageProcessor::ParseMessageReqCredExchange(const nlohmann::json &jsonObject, + std::shared_ptr context) +{ + if (jsonObject.is_discarded() || !IsString(jsonObject, DM_TAG_DATA)) { + LOGE("DecodeRequestAuth jsonStr error"); + return ERR_DM_FAILED; + } + + // 解密 + std::string plainText; + if (cryptoMgr_->DecryptMessage(jsonObject[DM_TAG_DATA].get(), plainText) != DM_OK) { + LOGE("DmAuthMessageProcessor::ParseMessageReqCredExchange() error, decrypt data failed."); + return ERR_DM_FAILED; + } + nlohmann::json jsonData = nlohmann::json::parse(plainText, nullptr, false); + + // 首次认证,解析用户级公钥 + if (!context->isOnline) { + if (!IsString(jsonData, DM_TAG_USER_PUBLICK_KEY)) { + LOGE("DmAuthMessageProcessor::ParseMessageReqCredExchange() error, first auth, no userPublicKey."); + return ERR_DM_FAILED; + } + context->accesser.userPublicKey = jsonData[DM_TAG_USER_PUBLICK_KEY].get(); + } + + if (!IsString(jsonData, DM_TAG_APP_PUBLICK_KEY) || + !IsString(jsonData, DM_TAG_DEVICE_ID) || + !IsInt32(jsonData, DM_TAG_PEER_USER_SPACE_ID) || + !IsInt64(jsonData, DM_TAG_TOKEN_ID)) { + LOGE("DmAuthMessageProcessor::ParseMessageReqCredExchange, MSG_TYPE_REQ_CREDENTIAL_EXCHANGE message error."); + return ERR_DM_FAILED; + } + context->accesser.appPublicKey = jsonData[DM_TAG_APP_PUBLICK_KEY].get(); // 解析应用级公钥 + context->accesser.deviceId = jsonData[DM_TAG_DEVICE_ID].get(); // 解析deviceId + context->accesser.userId = jsonData[DM_TAG_PEER_USER_SPACE_ID].get(); // 解析userId + context->accesser.tokenId = jsonData[DM_TAG_TOKEN_ID].get(); // 解析tokenId + context->authStateMachine->TransitionTo(std::make_shared()); + return DM_OK; +} + +// 解析150报文信息MSG_TYPE_RESP_CREDENTIAL_EXCHANGE,SRC端存放对方公钥,和协商凭据Id +int32_t DmAuthMessageProcessor::ParseMessageRspCredExchange(const nlohmann::json &jsonObject, + std::shared_ptr context) +{ + LOGI("DmAuthMessageProcessor::ParseMessageRspCredExchange start."); + if (jsonObject.is_discarded() || !IsString(jsonObject, DM_TAG_DATA)) { + LOGE("DmAuthMessageProcessor::ParseMessageRspCredExchange, DecodeRequestAuth jsonStr error"); + return ERR_DM_FAILED; + } + + // 解密 + std::string plainText; + if (cryptoMgr_->DecryptMessage(jsonObject[DM_TAG_DATA].get(), plainText) != DM_OK) { + LOGE("DmAuthMessageProcessor::ParseMessageRspCredExchange error, decrypt data failed."); + return ERR_DM_FAILED; + } + + LOGI("DmAuthMessageProcessor::ParseMessageRspCredExchange plainText=%{public}s", plainText.c_str()); + + nlohmann::json jsonData = nlohmann::json::parse(plainText, nullptr, false); + + // 首次认证,解析对方用户级公钥和协商用户级凭据Id + std::string tmpString; + if (!context->isOnline) { + if (!IsString(jsonData, DM_TAG_USER_PUBLICK_KEY) || !IsString(jsonData, DM_TAG_USER_CREDENTIAL_ID)) { + LOGE("DmAuthMessageProcessor::ParseMessageRspCredExchange failed, first auth but no userPublicKey or " + "userCredentialId."); + return ERR_DM_FAILED; + } + context->accessee.userPublicKey = jsonData[DM_TAG_USER_PUBLICK_KEY].get(); + context->accessee.userCredentialId = jsonData[DM_TAG_USER_CREDENTIAL_ID].get(); + } + + // 解析对方应用级公钥和协商应用级凭据Id + if (!IsString(jsonData, DM_TAG_APP_PUBLICK_KEY) || + !IsString(jsonData, DM_TAG_APP_CREDENTIAL_ID) || + !IsString(jsonData, DM_TAG_DEVICE_ID) || + !IsInt32(jsonData, DM_TAG_PEER_USER_SPACE_ID) || + !IsInt64(jsonData, DM_TAG_TOKEN_ID)) { + LOGE("DmAuthMessageProcessor::ParseMessageRspCredExchange failed, decode MSG_TYPE_RESP_CREDENTIAL_EXCHANGE " + "message error."); + return ERR_DM_FAILED; + } + context->accessee.appPublicKey = jsonData[DM_TAG_APP_PUBLICK_KEY].get(); + context->accessee.appCredentialId = jsonData[DM_TAG_APP_CREDENTIAL_ID].get(); + context->accessee.deviceId = jsonData[DM_TAG_DEVICE_ID].get(); // 解析deviceId + context->accessee.userId = jsonData[DM_TAG_PEER_USER_SPACE_ID].get(); // 解析userId + context->accessee.tokenId = jsonData[DM_TAG_TOKEN_ID].get(); // 解析tokenId + + context->authStateMachine->TransitionTo(std::make_shared()); + return DM_OK; +} + +// 创建报文,构造对应msgType的报文,返回值为json格式报文的字符串 +std::string DmAuthMessageProcessor::CreateMessage(DmMessageType msgType, std::shared_ptr context) +{ + LOGI("DmAuthMessageProcessor::CreateMessage start. msgType is %{public}d", msgType); + nlohmann::json jsonObj; + jsonObj[TAG_MSG_TYPE] = msgType; + switch (msgType) { + case MSG_TYPE_REQ_ACL_NEGOTIATE: + CreateNegotiateMessage(context, jsonObj); + break; + case MSG_TYPE_RESP_ACL_NEGOTIATE: + CreateRespNegotiateMessage(context, jsonObj); + break; + case MSG_TYPE_REQ_USER_CONFIRM: + CreateMessageReqUserConfirm(context, jsonObj); + break; + case MSG_TYPE_RESP_USER_CONFIRM: + CreateMessageRespUserConfirm(context, jsonObj); + break; + case MSG_TYPE_REQ_PIN_AUTH_START: + CreateMessageReqPinAuthStart(context, jsonObj); + break; + case MSG_TYPE_REQ_PIN_AUTH_MSG_NEGOTIATE: + CreateMessageReqPinAuthNegotiate(context, jsonObj); + break; + case MSG_TYPE_RESP_PIN_AUTH_START: + CreateMessageRespPinAuthStart(context, jsonObj); + break; + case MSG_TYPE_RESP_PIN_AUTH_MSG_NEGOTIATE: + CreateMessageRespPinAuthNegotiate(context, jsonObj); + break; + case MSG_TYPE_REQ_CREDENTIAL_EXCHANGE: + CreateMessageReqCredExchange(context, jsonObj); + break; + case MSG_TYPE_RESP_CREDENTIAL_EXCHANGE: + CreateMessageRspCredExchange(context, jsonObj); + break; + case MSG_TYPE_REQ_CREDENTIAL_AUTH_START: + CreateMessageReqCredAuthStart(context, jsonObj); + break; + case MSG_TYPE_REQ_CREDENTIAL_AUTH_NEGOTIATE: // 161 + case MSG_TYPE_RESP_CREDENTIAL_AUTH_START: // 170 + case MSG_TYPE_RESP_CREDENTIAL_AUTH_NEGOTIATE: // 171 + if (CreateCredentialNegotiateMessage(context, jsonObj) != DM_OK) { + return ""; + } + break; + case MSG_TYPE_REQ_DATA_SYNC: + if (CreateSyncMessage(context, jsonObj)!= DM_OK) { + return ""; + } + break; + case MSG_TYPE_RESP_DATA_SYNC: + CreateMessageSyncResp(context, jsonObj); + break; + case MSG_TYPE_AUTH_FINISH: + CreateMessageFinish(context, jsonObj); + break; + default: + LOGE("DmAuthMessageProcessor::CreateMessage msgType %{public}d error.", msgType); + break; + } + // TODO:调试信息,上库前删除 + LOGI("DmAuthMessageProcessor::CreateMessage %{public}s", SafetyDump(jsonObj).c_str()); + return SafetyDump(jsonObj); +} + +// 内部各类报文的实现 +// 161 170 171消息构造 +int32_t DmAuthMessageProcessor::CreateCredentialNegotiateMessage(std::shared_ptr &context, nlohmann::json &jsonObject) +{ + std::string encryptMsg; + jsonObject[DM_TAG_DATA] = context->transmitData; + return DM_OK; +} + +// 创建80报文 +void DmAuthMessageProcessor::CreateNegotiateMessage(std::shared_ptr context, nlohmann::json &jsonObject) +{ + jsonObject[TAG_AUTH_TYPE] = context->authType; + jsonObject[DM_TAG_DMVERSION] = context->accesser.dmVersion; + jsonObject[TAG_DEVICE_NAME] = context->accesser.deviceName; + + jsonObject[DM_TAG_TOKEN_ID] = static_cast(context->accesser.tokenId); + + jsonObject[TAG_DEVICE_ID_HASH] = context->accesser.deviceIdHash; + jsonObject[TAG_USER_ID_HASH] = context->accesser.userIdHash; + jsonObject[TAG_ACCOUNT_ID_HASH] = context->accesser.accountIdHash; + jsonObject[TAG_TOKEN_ID_HASH] = context->accesser.tokenIdHash; + + jsonObject[TAG_BUNDLE_NAME] = context->accesser.bundleName; + jsonObject[TAG_PEER_BUNDLE_NAME] = context->accessee.bundleName; + jsonObject[TAG_BIND_LEVEL] = context->accesser.bindLevel; + + jsonObject[DM_TAG_EXTRA_INFO] = nlohmann::json::object(); + CreateNegotiateExtraInfoMessage(context, jsonObject[DM_TAG_EXTRA_INFO]); + + return; +} + +// 创建90报文 +void DmAuthMessageProcessor::CreateRespNegotiateMessage(std::shared_ptr context, + nlohmann::json &jsonObject) +{ + jsonObject[TAG_DEVICE_VERSION] = context->accessee.dmVersion; + jsonObject[TAG_DEVICE_NAME] = context->accessee.deviceName; + + jsonObject[TAG_DEVICE_ID_HASH] = context->accessee.deviceIdHash; + jsonObject[TAG_USER_ID_HASH] = context->accessee.userIdHash; + jsonObject[TAG_ACCOUNT_ID_HASH] = context->accessee.accountIdHash; + jsonObject[TAG_TOKEN_ID_HASH] = context->accessee.tokenIdHash; + + jsonObject[TAG_BUNDLE_NAME] = context->accessee.bundleName; + jsonObject[TAG_IS_ONLINE] = context->isOnline; + jsonObject[TAG_IS_AUTHED] = context->accessee.isAuthed; + jsonObject[TAG_CREDENTIAL_INFO] = context->accessee.credentialInfos; + + jsonObject[DM_TAG_AUTH_TYPE_LIST] = vectorToString(context->authTypeList); + jsonObject[DM_TAG_AUTH_RESULT] = context->authResult; + jsonObject[TAG_REQUEST_ID] = context->requestId; + return; +} + +// 创建140报文 +void DmAuthMessageProcessor::CreateMessageReqCredExchange(std::shared_ptr context, + nlohmann::json &jsonObject) +{ + nlohmann::json jsonData; + if (!context->isOnline) { + jsonData[DM_TAG_USER_PUBLICK_KEY] = context->accesser.userPublicKey; + } + jsonData[DM_TAG_APP_PUBLICK_KEY] = context->accesser.appPublicKey; + jsonData[DM_TAG_DEVICE_ID] = context->accesser.deviceId; + jsonData[DM_TAG_PEER_USER_SPACE_ID] = context->accesser.userId; + jsonData[DM_TAG_TOKEN_ID] = context->accesser.tokenId; + + std::string plainText = SafetyDump(jsonData); + std::string cipherText; + cryptoMgr_->EncryptMessage(plainText, cipherText); + jsonObject[DM_TAG_DATA] = cipherText; +} + +// 创建150报文 +void DmAuthMessageProcessor::CreateMessageRspCredExchange(std::shared_ptr context, + nlohmann::json &jsonObject) +{ + LOGI("DmAuthMessageProcessor::CreateMessageRspCredExchange start."); + nlohmann::json jsonData; + if (!context->isOnline) { + jsonData[DM_TAG_USER_PUBLICK_KEY] = context->accessee.userPublicKey; + jsonData[DM_TAG_USER_CREDENTIAL_ID] = context->accessee.userCredentialId; + } + jsonData[DM_TAG_APP_PUBLICK_KEY] = context->accessee.appPublicKey; // 本端应用级公钥 + jsonData[DM_TAG_APP_CREDENTIAL_ID] = context->accessee.appCredentialId; // 本端应用级凭据Id + jsonData[DM_TAG_DEVICE_ID] = context->accessee.deviceId; // 本端deviceId + jsonData[DM_TAG_PEER_USER_SPACE_ID] = context->accessee.userId; // 本端userId + jsonData[DM_TAG_TOKEN_ID] = context->accessee.tokenId; // 本端tokenId + + std::string plainText = SafetyDump(jsonData); + std::string cipherText; + LOGI("DmAuthMessageProcessor::CreateMessageRspCredExchange plainText=%{public}s", plainText.c_str()); + cryptoMgr_->EncryptMessage(plainText, cipherText); + jsonObject[DM_TAG_DATA] = cipherText; +} + +// 创建160报文 +void DmAuthMessageProcessor::CreateMessageReqCredAuthStart(std::shared_ptr context, + nlohmann::json &jsonObject) +{ + std::string onTransmitData; + + nlohmann::json jsonData; + jsonObject[DM_TAG_DATA] = context->transmitData; + if (!context->isAppCredentialVerified) { // 应用级凭据认证 + jsonObject[DM_TAG_APP_CREDENTIAL_ID] = context->accesser.appCredentialId; + } else if (!context->isOnline) { // 首次用户级凭据认证 + jsonObject[DM_TAG_USER_CREDENTIAL_ID] = context->accesser.userCredentialId; + } +} + +std::string DmAuthMessageProcessor::ChecksumAcl(DistributedDeviceProfile::AccessControlProfile &acl) +{ + std::string aclChecksum = ""; + std::string aclStr = ""; + int32_t ret = ACLToStr(acl, aclStr); + if (ret != DM_OK) { + LOGE("ChecksumAcl ACLToStr failed"); + return aclChecksum; + } + uint8_t checksum[DM_HASH_LEN] = {0}; + Crypto::DmGenerateStrHash(aclStr.data(), aclStr.size(), checksum, 32, 0); + return std::string(reinterpret_cast(checksum)); +} + +// 创建190报文 +void DmAuthMessageProcessor::CreateMessageSyncResp(std::shared_ptr context, + nlohmann::json &jsonObject) +{ + DmAccess access; // 代表本端的access + if (context->direction == DM_AUTH_SINK) { + access = context->accessee; + } else { + access = context->accesser; + } + + std::string encSyncMsg; + int32_t ret = EncryptSyncMessage(context, access, encSyncMsg); + if (ret != DM_OK) { + LOGE("DmAuthMessageProcessor::CreateMessageSyncResp encrypt failed"); + return; + } + jsonObject[DM_TAG_SYNC] = encSyncMsg; + return; +} + +// 创建200报文 +void DmAuthMessageProcessor::CreateMessageFinish(std::shared_ptr context, + nlohmann::json &jsonObject) +{ + jsonObject[DM_TAG_REPLY] = context->reply; + jsonObject[DM_TAG_STATE] = context->state; + jsonObject[DM_TAG_REASON] = context->reason; + return; +} + +int32_t DmAuthMessageProcessor::ParseSyncMessage(std::shared_ptr &context, + DmAccess &access, nlohmann::json jsonObject) +{ + if (!IsString(jsonObject, DM_TAG_USER_SK_ID)) { + LOGE("ParseSyncMessage DM_TAG_USER_SK_ID error"); + return ERR_DM_FAILED; + } + context->userSessionKeyId = std::atoi(jsonObject[DM_TAG_USER_SK_ID].get().c_str()); + if (!IsString(jsonObject, DM_TAG_USER_SK_TIMESTAMP)) { + LOGE("ParseSyncMessage DM_TAG_USER_SK_TIMESTAMP error"); + return ERR_DM_FAILED; + } + context->userSkTimeStamp = std::atoi(jsonObject[DM_TAG_USER_SK_TIMESTAMP].get().c_str()); + if (!IsString(jsonObject, DM_TAG_DMVERSION)) { + LOGE("ParseSyncMessage DM_TAG_DMVERSION error"); + return ERR_DM_FAILED; + } + access.dmVersion = jsonObject[DM_TAG_DMVERSION].get(); + if (!IsString(jsonObject, DM_TAG_ACCESS)) { // 再解析一次 + LOGE("ParseSyncMessage DM_TAG_ACCESS error"); + return ERR_DM_FAILED; + } + std::string srcAccessStr = jsonObject[DM_TAG_ACCESS].get(); + // 解析到 access里面 + nlohmann::json accessjson = nlohmann::json::parse(srcAccessStr, nullptr, false); + if (jsonObject.is_discarded()) { + LOGE("ParseSyncMessage srcAccessStr error"); + return ERR_DM_FAILED; + } + DmAccessToSync srcAccessToSync = accessjson; + access.deviceName = srcAccessToSync.deviceName; + access.deviceId = srcAccessToSync.deviceId; + access.userId = srcAccessToSync.userId; + access.accountId = srcAccessToSync.accountId; + access.tokenId = srcAccessToSync.tokenId; + access.bundleName = srcAccessToSync.bundleName; + access.bindLevel = srcAccessToSync.bindLevel; + access.sessionKeyId = srcAccessToSync.sessionKeyId; + access.skTimeStamp = srcAccessToSync.skTimeStamp; + if (context->isOnline) { + access.appSessionKeyId = srcAccessToSync.sessionKeyId; + access.appSkTimeStamp = srcAccessToSync.skTimeStamp; + } else { + access.userSessionKeyId = srcAccessToSync.sessionKeyId; + access.userSkTimeStamp = srcAccessToSync.skTimeStamp; + } + if (IsString(jsonObject, DM_TAG_PROXY)) { // 预留字段 + std::string proxyInfo = jsonObject[DM_TAG_PROXY].get(); + } + if (IsArray(jsonObject, DM_TAG_ACL_CHECKSUM)) { // 再解析一次 acl + LOGE("ParseSyncMessage DM_TAG_ACL_CHECKSUM error"); + return ERR_DM_FAILED; + } + access.aclChecksumList = jsonObject[DM_TAG_ACL_CHECKSUM].get>(); + if (IsString(jsonObject, DM_TAG_SERVICEINFO)) { // sp 暂时没有传 + std::string serviceInfo = jsonObject[DM_TAG_SERVICEINFO].get(); + } + return DM_OK; +} + +int32_t DmAuthMessageProcessor::DecryptSyncMessage(std::shared_ptr &context, + DmAccess &access, std::string &enSyncMsg) +{ + // 解密整个字段 + std::string syncMsgCompress = ""; + int32_t ret = cryptoMgr_->DecryptMessage(enSyncMsg, syncMsgCompress); + if (ret != DM_OK) { + LOGE("DecryptSyncMessage syncMsg error"); + return ret; + } + nlohmann::json plainJson = nlohmann::json::parse(syncMsgCompress, nullptr, false); + if (plainJson.is_discarded()) { + LOGE("DecryptSyncMessage plainJson error"); + return ERR_DM_FAILED; + } + if (!IsInt32(plainJson, DM_TAG_COMPRESS_ORI_LEN)) { + LOGE("DecryptSyncMessage DM_TAG_COMPRESS_ORI_LEN json error"); + return ERR_DM_FAILED; + } + int32_t dataLen = plainJson[DM_TAG_COMPRESS_ORI_LEN].get(); + if (!IsString(plainJson, DM_TAG_COMPRESS)) { + LOGE("DecryptSyncMessage DM_TAG_COMPRESS_ORI_LEN json error"); + return ERR_DM_FAILED; + } + std::string compressMsg = plainJson[DM_TAG_COMPRESS].get(); + // 解压缩 + std::string compressBase64 = Base64Decode(compressMsg); + std::string syncMsg = DecompressSyncMsg(compressBase64, dataLen); + // 解析字段 + nlohmann::json jsonObject = nlohmann::json::parse(syncMsg, nullptr, false); + if (jsonObject.is_discarded()) { + LOGE("DmAuthMessageProcessor::DecryptSyncMessage jsonStr error"); + return ERR_DM_FAILED; + } + if (IsString(jsonObject, DM_TAG_APP_SK_ID)) { + context->appSessionKeyId = std::atoi(jsonObject[DM_TAG_APP_SK_ID].get().c_str()); + } + if (IsString(jsonObject, DM_TAG_APP_SK_TIMESTAMP)) { + context->appSkTimeStamp = std::atoi(jsonObject[DM_TAG_APP_SK_TIMESTAMP].get().c_str()); + } + ret = ParseSyncMessage(context, access, jsonObject); + if (ret != DM_OK) { + LOGE("DecryptSyncMessage ParseSyncMessage jsonStr error"); + return ret; + } + return DM_OK; +} + +// 解析 180报文信息 MSG_TYPE_REQ_DATA_SYNC 存放对方密文四元组,acl,sp skid +int32_t DmAuthMessageProcessor::ParseMessageSyncReq(const nlohmann::json &jsonObject, + std::shared_ptr context) +{ + // 解析json中的加密数据 + if (!IsString(jsonObject, DM_TAG_SYNC)) { // 再解析一次 acl + LOGE("ParseMessageSyncReq json error"); + return ERR_DM_FAILED; + } + std::string enSyncMsg = jsonObject[DM_TAG_SYNC].get(); + // 解密数据 + 解析数据到context中 + int32_t ret = DecryptSyncMessage(context, context->encryAccesser, enSyncMsg); + if (ret != DM_OK) { + LOGE("DecryptSyncMessage enSyncMsg error"); + return ret; + } + context->authStateMachine->TransitionTo(std::make_shared()); + return DM_OK; +} + +// 解析 190报文信息 MSG_TYPE_RESP_DATA_SYNC 存放对方密文四元组,acl sp skid +int32_t DmAuthMessageProcessor::ParseMessageSyncResp(const nlohmann::json &jsonObject, + std::shared_ptr context) +{ + // 解析json中的加密数据 + if (!IsString(jsonObject, DM_TAG_SYNC)) { // 再解析一次 acl + LOGE("ParseMessageSyncResp json error"); + return ERR_DM_FAILED; + } + std::string enSyncMsg = jsonObject[DM_TAG_SYNC].get(); + // 解密数据 + 解析数据到context中 + int32_t ret = DecryptSyncMessage(context, context->encryAccessee, enSyncMsg); + if (ret != DM_OK) { + LOGE("DecryptSyncMessage enSyncMsg error"); + return ret; + } + context->authStateMachine->TransitionTo(std::make_shared()); + return DM_OK; +} + +// 解析200报文 +int32_t DmAuthMessageProcessor::ParseMessageFinish(std::shared_ptr context, + nlohmann::json &jsonObject) +{ + if (IsInt32(jsonObject, DM_TAG_REPLY)) { + context->reply = jsonObject[DM_TAG_REPLY].get(); + } + if (IsInt32(jsonObject, DM_TAG_STATE)) { + context->state = jsonObject[DM_TAG_STATE].get(); + } + if (IsInt32(jsonObject, DM_TAG_REASON)) { + context->reason = jsonObject[DM_TAG_REASON].get(); + } + context->authStateMachine->TransitionTo(std::make_shared()); + return DM_OK; +} + +int32_t DmAuthMessageProcessor::ParseNegotiateMessage(nlohmann::json &jsonObject, + std::shared_ptr context) +{ + if (IsString(jsonObject, DM_TAG_DMVERSION)) { + context->accesser.dmVersion = jsonObject[DM_TAG_DMVERSION].get(); + } + if (IsString(jsonObject, DM_TAG_EDITION)) { + context->accesser.edition = jsonObject[DM_TAG_EDITION].get(); + } + if (IsString(jsonObject, TAG_DEVICE_NAME)) { + context->accesser.deviceName = jsonObject[TAG_DEVICE_NAME].get(); + } + if (IsInt64(jsonObject, DM_TAG_TOKEN_ID)) { + context->accesser.tokenId = static_cast(jsonObject[DM_TAG_TOKEN_ID].get()); + } + + if (IsString(jsonObject, TAG_DEVICE_ID_HASH)) { + context->accesser.deviceIdHash = jsonObject[TAG_DEVICE_ID_HASH].get(); + } + if (IsString(jsonObject, TAG_USER_ID_HASH)) { + context->accesser.userIdHash = jsonObject[TAG_USER_ID_HASH].get(); + } + if (IsString(jsonObject, TAG_ACCOUNT_ID_HASH)) { + context->accesser.accountIdHash = jsonObject[TAG_ACCOUNT_ID_HASH].get(); + } + if (IsString(jsonObject, TAG_TOKEN_ID_HASH)) { + context->accesser.tokenIdHash = jsonObject[TAG_TOKEN_ID_HASH].get(); + } + + if (IsString(jsonObject, TAG_BUNDLE_NAME)) { + context->accesser.bundleName = jsonObject[TAG_BUNDLE_NAME].get(); + } + if (IsString(jsonObject, TAG_PEER_BUNDLE_NAME)) { + context->accessee.bundleName = jsonObject[TAG_PEER_BUNDLE_NAME].get(); + } + if (IsInt32(jsonObject, TAG_BIND_LEVEL)) { + context->accesser.bindLevel = jsonObject[TAG_BIND_LEVEL].get(); + } + if (IsInt32(jsonObject, TAG_AUTH_TYPE)) { + context->authType = static_cast(jsonObject[TAG_AUTH_TYPE].get()); + } + + if (jsonObject.contains(DM_TAG_EXTRA_INFO) && jsonObject[DM_TAG_EXTRA_INFO].is_object()) { + ParseNegotiateExtraInfoMessage(jsonObject[DM_TAG_EXTRA_INFO], context); + } + + context->authStateMachine->TransitionTo(std::make_shared()); + return DM_OK; +} + +int32_t DmAuthMessageProcessor::ParseMessageRespAclNegotiate(const nlohmann::json &jsonObject, + std::shared_ptr context) +{ + if (IsString(jsonObject, TAG_DEVICE_VERSION)) { + context->accessee.dmVersion = jsonObject[TAG_DEVICE_VERSION].get(); + } + + if (IsString(jsonObject, TAG_DEVICE_NAME)) { + context->accessee.deviceName = jsonObject[TAG_DEVICE_NAME].get(); + } + + if (IsString(jsonObject, TAG_DEVICE_ID_HASH)) { + context->accessee.deviceIdHash = jsonObject[TAG_DEVICE_ID_HASH].get(); + } + + if (IsString(jsonObject, TAG_USER_ID_HASH)) { + context->accessee.userIdHash = jsonObject[TAG_USER_ID_HASH].get(); + } + + if (IsString(jsonObject, TAG_ACCOUNT_ID_HASH)) { + context->accessee.accountIdHash = jsonObject[TAG_ACCOUNT_ID_HASH].get(); + } + + if (IsString(jsonObject, TAG_TOKEN_ID_HASH)) { + context->accessee.tokenIdHash = jsonObject[TAG_TOKEN_ID_HASH].get(); + } + + if (IsString(jsonObject, TAG_BUNDLE_NAME)) { + context->accessee.bundleName = jsonObject[TAG_BUNDLE_NAME].get(); + } + + if (IsBool(jsonObject, TAG_IS_ONLINE)) { + context->isOnline = jsonObject[TAG_IS_ONLINE].get(); + } + + if (IsBool(jsonObject, TAG_IS_AUTHED)) { + context->accessee.isAuthed = jsonObject[TAG_IS_AUTHED].get(); + } + + if (IsString(jsonObject, TAG_CREDENTIAL_INFO)) { + context->accessee.credentialInfos = jsonObject[TAG_CREDENTIAL_INFO].get(); + } + + if (IsString(jsonObject, DM_TAG_AUTH_TYPE_LIST)) { + auto strList = jsonObject[DM_TAG_AUTH_TYPE_LIST].get(); + context->authTypeList = stringToVector(strList); + } + if (IsInt64(jsonObject, TAG_REQUEST_ID)) { + context->requestId = jsonObject[TAG_REQUEST_ID].get(); + } + if (IsInt32(jsonObject, DM_TAG_AUTH_RESULT)) { + context->authResult = static_cast(jsonObject[DM_TAG_AUTH_RESULT].get()); + } + + context->authStateMachine->TransitionTo(std::make_shared()); + return DM_OK; +} +int32_t DmAuthMessageProcessor::ParseMessageReqUserConfirm(const nlohmann::json &json, + std::shared_ptr context) +{ + if (IsInt32(json, TAG_AUTH_TYPE)) { + context->authType = static_cast(json[TAG_AUTH_TYPE].get()); + } + + if (IsInt32(json, TAG_DEVICE_TYPE)) { + context->accesser.deviceType = json[TAG_AUTH_TYPE].get(); + } + if (IsString(json, TAG_DEVICE_NAME)) { + context->accesser.deviceName = json[TAG_DEVICE_NAME].get(); + } + if (IsString(json, TAG_SESSION_NAME)) { + context->sessionName = json[TAG_SESSION_NAME].get(); + } + if (IsUint32(json, DM_TAG_CURRENT_AUTH_TYPE_IDX)) { + auto idx = json[DM_TAG_CURRENT_AUTH_TYPE_IDX].get(); + if (idx < context->authTypeList.size()) { + context->currentAuthTypeIdx = idx; + context->authType = context->authTypeList[idx]; + } else { + LOGI("DmAuthMessageProcessor::ParseMessageReqUserConfirm currentAuthTypeIdx err."); + context->reason = ERR_DM_INPUT_PARA_INVALID; + context->authStateMachine->NotifyEventFinish(DmEventType::ON_FAIL); + return STOP_BIND; + } + } + + context->authStateMachine->TransitionTo(std::make_shared()); + return DM_OK; +} + +int32_t DmAuthMessageProcessor::ParseMessageRespUserConfirm(const nlohmann::json &json, + std::shared_ptr context) +{ + if (IsInt32(json, DM_TAG_AUTH_RESULT)) { + context->authResult = static_cast(json[DM_TAG_AUTH_RESULT].get()); + } +#ifndef NEW_PIN_STATE // todo del + context->authStateMachine->TransitionTo(std::make_shared()); +#else + context->authStateMachine->TransitionTo(std::make_shared()); +#endif + return DM_OK; +} +int32_t DmAuthMessageProcessor::ParseMessageReqPinAuthStart(const nlohmann::json &json, + std::shared_ptr context) +{ + if (IsString(json, DM_TAG_DATA)) { + context->transmitData = json[DM_TAG_DATA].get(); + } + if (IsUint32(json, DM_TAG_CURRENT_AUTH_TYPE_IDX)) { + auto idx = json[DM_TAG_CURRENT_AUTH_TYPE_IDX].get(); + if (idx < context->authTypeList.size()) { + context->currentAuthTypeIdx = idx; + context->authType = context->authTypeList[idx]; + } else { + LOGI("DmAuthMessageProcessor::ParseMessageReqUserConfirm currentAuthTypeIdx err."); + context->reason = ERR_DM_INPUT_PARA_INVALID; + context->authStateMachine->NotifyEventFinish(DmEventType::ON_FAIL); + return STOP_BIND; + } + } + context->authStateMachine->TransitionTo(std::make_shared()); + return DM_OK; +} +int32_t DmAuthMessageProcessor::ParseMessageRespPinAuthStart(const nlohmann::json &json, + std::shared_ptr context) +{ + if (IsString(json, DM_TAG_DATA)) { + context->transmitData = json[DM_TAG_DATA].get(); + } + context->authStateMachine->TransitionTo(std::make_shared()); + return DM_OK; +} +int32_t DmAuthMessageProcessor::ParseMessageReqPinAuthNegotiate(const nlohmann::json &json, + std::shared_ptr context) +{ + if (IsString(json, DM_TAG_DATA)) { + context->transmitData = json[DM_TAG_DATA].get(); + } + context->authStateMachine->TransitionTo(std::make_shared()); + return DM_OK; +} + +void DmAuthMessageProcessor::CreateMessageReqUserConfirm(std::shared_ptr context, nlohmann::json &json) +{ + json[TAG_AUTH_TYPE] = context->authType; + json[TAG_DEVICE_TYPE] = context->accesser.deviceType; + json[TAG_DEVICE_NAME] = context->accesser.deviceName; + json[TAG_SESSION_NAME] = context->sessionName; + json[DM_TAG_CURRENT_AUTH_TYPE_IDX] = context->currentAuthTypeIdx; +} + +void DmAuthMessageProcessor::CreateMessageRespUserConfirm(std::shared_ptr context, nlohmann::json &json) +{ + json[DM_TAG_AUTH_RESULT] = context->authResult; +} + +void DmAuthMessageProcessor::CreateMessageReqPinAuthStart(std::shared_ptr context, nlohmann::json &json) +{ + json[DM_TAG_DATA] = context->transmitData; + json[DM_TAG_CURRENT_AUTH_TYPE_IDX] = context->currentAuthTypeIdx; +} + +void DmAuthMessageProcessor::CreateMessageRespPinAuthStart(std::shared_ptr context, nlohmann::json &json) +{ + json[DM_TAG_DATA] = context->transmitData; +} + +void DmAuthMessageProcessor::CreateMessageReqPinAuthNegotiate(std::shared_ptr context, + nlohmann::json &json) +{ + json[DM_TAG_DATA] = context->transmitData; +} + +void DmAuthMessageProcessor::CreateMessageRespPinAuthNegotiate(std::shared_ptr context, + nlohmann::json &json) +{ + json[DM_TAG_DATA] = context->transmitData; +} + +void DmAuthMessageProcessor::CreateAndSendMsg(DmMessageType msgType, std::shared_ptr context) +{ + auto message = CreateMessage(msgType, context); + context->softbusConnector->GetSoftbusSession()->SendData(context->sessionId, message); +} + +std::string DmAuthMessageProcessor::CompressSyncMsg(std::string &inputStr) +{ + uint32_t srcLen = inputStr.size(); + uint32_t boundSize = compressBound(srcLen); // 最大压缩长度 + std::string compressed(boundSize, '\0'); + + // 压缩到预留空间 + unsigned long destSize = boundSize; // 实际可用长度 + int32_t ret = compress(reinterpret_cast(&compressed[0]), &destSize, + reinterpret_cast(inputStr.data()), srcLen); + if (ret != Z_OK) { + LOGE("DmAuthMessageProcessor::CompressSyncMsg zlib compress failed"); + return ""; + } + compressed.resize(destSize); // 实际使用长度 + return compressed; +} + +std::string DmAuthMessageProcessor::DecompressSyncMsg(std::string& compressed, uint32_t oriLen) +{ + std::string decompressed; + decompressed.resize(oriLen); + unsigned long destLen = oriLen; // 实际使用长度 + int32_t ret = uncompress(reinterpret_cast(&decompressed[0]), &destLen, + reinterpret_cast(compressed.data()), // 解压时跳过头部 + compressed.size()); + if (ret != Z_OK || destLen != oriLen) { + LOGE("DmAuthMessageProcessor::DecompressSyncMsg decompress failed"); + return ""; + } + return decompressed; +} + +std::string DmAuthMessageProcessor::Base64Encode(std::string &inputStr) +{ + // 输入字符串转二进制 + const unsigned char* src = reinterpret_cast(inputStr.data()); + size_t srcLen = inputStr.size(); + + // 计算base64 后最大长度 + size_t maxEncodeLen = ((srcLen + 2) / 3) * 4 + 1; + std::vector buffer(maxEncodeLen); + + // 实际编码长度 + size_t encodedLen = 0; + int32_t ret = mbedtls_base64_encode(buffer.data(), buffer.size(), &encodedLen, src, srcLen); + if (ret != 0) { + LOGE("DmAuthMessageProcessor::Base64Encode mbedtls_base64_encode failed"); + return ""; + } + return std::string(reinterpret_cast(buffer.data()), encodedLen); // 无需终止符 +} + + +std::string DmAuthMessageProcessor::Base64Decode(std::string &inputStr) +{ + // 输入字符串转二进制 + const unsigned char* src = reinterpret_cast(inputStr.data()); + size_t srcLen = inputStr.size(); + + // 计算base64 后最大长度 + size_t maxEncodeLen = (srcLen / 4) * 3 + 1; + std::vector buffer(maxEncodeLen); + + // 实际编码长度 + size_t decodedLen = 0; + int32_t ret = mbedtls_base64_decode(buffer.data(), buffer.size(), &decodedLen, src, srcLen); + if (ret != 0) { + LOGE("DmAuthMessageProcessor::Base64Decode mbedtls_base64_decode failed"); + return ""; + } + return std::string(reinterpret_cast(buffer.data()), decodedLen); // 无需终止符 +} + + +// 用于组装syncMsg中的加密部分 +int32_t DmAuthMessageProcessor::EncryptSyncMessage(std::shared_ptr &context, DmAccess &accessSide, + std::string &encSyncMsg) +{ + nlohmann::json syncMsgJson; // 完整的180/190 消息 未经压缩&加密 + DmAccessToSync accessToSync; + accessToSync.deviceName = accessSide.deviceName; + accessToSync.deviceId = accessSide.deviceId; + accessToSync.userId = accessSide.userId; + accessToSync.accountId = accessSide.accountId; + accessToSync.tokenId = accessSide.tokenId; + accessToSync.bundleName = accessSide.bundleName; + accessToSync.bindLevel = accessSide.bindLevel; + + if (context->isOnline) { // 非首次认证 + accessToSync.sessionKeyId = context->appSessionKeyId; + accessToSync.skTimeStamp = context->appSkTimeStamp; + syncMsgJson[DM_TAG_APP_SK_ID]=std::to_string(context->appSessionKeyId); + syncMsgJson[DM_TAG_APP_SK_TIMESTAMP]=std::to_string(context->appSkTimeStamp); + } else { // 首次认证 + accessToSync.sessionKeyId = context->userSessionKeyId; + accessToSync.skTimeStamp = context->userSkTimeStamp; + syncMsgJson[DM_TAG_APP_SK_ID]=std::to_string(context->appSessionKeyId); + syncMsgJson[DM_TAG_USER_SK_ID]=std::to_string(context->userSessionKeyId); + syncMsgJson[DM_TAG_APP_SK_TIMESTAMP]=std::to_string(context->appSkTimeStamp); + syncMsgJson[DM_TAG_USER_SK_TIMESTAMP]=std::to_string(context->userSkTimeStamp); + } + + nlohmann::json accessJsonObj = accessToSync; // 直接使用宏构造 access json + syncMsgJson[DM_TAG_DMVERSION] = accessSide.dmVersion; + syncMsgJson[DM_TAG_ACCESS] = SafetyDump(accessJsonObj); // 接收端需要再拆一次json + syncMsgJson[DM_TAG_PROXY] = ""; // 预留字段 留空即可 + std::string aclHashList; + int32_t ret = GetAclListStr(context, aclHashList); + if (ret != DM_OK) { + LOGE("DmAuthMessageProcessor::EncryptSyncMessage GetAclListStr failed"); + return ERR_DM_FAILED; + } + + syncMsgJson[DM_TAG_ACL_CHECKSUM] = aclHashList; + std::string syncMsg = SafetyDump(syncMsgJson); // 消息构造完成 + + std::string compressMsg = CompressSyncMsg(syncMsg); // 压缩 + if (compressMsg.empty()) { + LOGE("DmAuthMessageProcessor::EncryptSyncMessage compress failed"); + return ERR_DM_FAILED; + } + nlohmann::json plainJson; + plainJson[DM_TAG_COMPRESS_ORI_LEN] = syncMsg.size(); // 记录压缩前原始长度 用于接收端解析 + plainJson[DM_TAG_COMPRESS] = Base64Encode(compressMsg); + // 加密整个字段 + return cryptoMgr_->EncryptMessage(SafetyDump(plainJson), encSyncMsg); +} + +int32_t DmAuthMessageProcessor::ACLToStr(DistributedDeviceProfile::AccessControlProfile acl, std::string aclStr) +{ + DmAccessControlTable dmAcl; + dmAcl.accessControlId = acl.GetAccessControlId(); + dmAcl.accesserId = acl.GetAccesserId(); + dmAcl.accesseeId = acl.GetAccesseeId(); + dmAcl.deviceId = acl.GetTrustDeviceId(); + dmAcl.sessionKey = acl.GetSessionKey(); + dmAcl.bindType = acl.GetBindType(); + dmAcl.authType = acl.GetAuthenticationType(); + dmAcl.deviceType = acl.GetDeviceIdType(); + dmAcl.deviceIdHash = acl.GetDeviceIdHash(); + dmAcl.status = acl.GetStatus(); + dmAcl.validPeriod = acl.GetValidPeriod(); + dmAcl.lastAuthTime = acl.GetLastAuthTime(); + dmAcl.bindLevel = acl.GetBindType(); + nlohmann::json aclJsonObj = dmAcl; + aclStr = SafetyDump(aclJsonObj); + if (aclStr.empty()) { + LOGE("DmAuthMessageProcessor::ACLToStr normalized acl failed"); + return ERR_DM_FAILED; + } + return DM_OK; +} + +std::string DmAuthMessageProcessor::AccesserToStr(DistributedDeviceProfile::AccessControlProfile acl) +{ + nlohmann::json jsonAccesserObj; + DistributedDeviceProfile::Accesser accesser = acl.GetAccesser(); + jsonAccesserObj[DM_TAG_ACCESSER_DEVICE_ID] = accesser.GetAccesserDeviceId(); + jsonAccesserObj[DM_TAG_ACCESSER_USER_ID] = accesser.GetAccesserUserId(); + jsonAccesserObj[DM_TAG_ACCESSER_ACOUNT_ID] = accesser.GetAccesserAccountId(); + jsonAccesserObj[DM_TAG_ACCESSER_TOKEN_ID] = accesser.GetAccesserTokenId(); + jsonAccesserObj[DM_TAG_ACCESSER_SERVICE_NAME] = {}; // 预留字段 DP库未适配 + jsonAccesserObj[DM_TAG_ACCESSER_BUNDLE_NAME] = accesser.GetAccesserBundleName(); + jsonAccesserObj[DM_TAG_ACCESSER_HAP_SIGNATURE] = accesser.GetAccesserHapSignature(); + jsonAccesserObj[DM_TAG_ACCESSER_BIND_LEVEL] = accesser.GetAccesserBindLevel(); + jsonAccesserObj[DM_TAG_ACCESSER_CREDENTIAL_ID] = accesser.GetAccesserBindLevel(); + jsonAccesserObj[DM_TAG_ACCESSER_STATUS] = accesser.GetAccesserStatus(); + jsonAccesserObj[DM_TAG_ACCESSER_SK_ID] = accesser.GetAccesserSessionKeyId(); + jsonAccesserObj[DM_TAG_ACCESSER_SK_TIMESTAMP] = accesser.GetAccesserSKTimeStamp(); + return SafetyDump(jsonAccesserObj); +} + +std::string DmAuthMessageProcessor::AccesseeToStr(DistributedDeviceProfile::AccessControlProfile acl) +{ + nlohmann::json jsonAccesseeObj; + DistributedDeviceProfile::Accessee accessee = acl.GetAccessee(); + jsonAccesseeObj[DM_TAG_ACCESSEE_DEVICE_ID] = accessee.GetAccesseeDeviceId(); + jsonAccesseeObj[DM_TAG_ACCESSEE_USER_ID] = accessee.GetAccesseeUserId(); + jsonAccesseeObj[DM_TAG_ACCESSEE_ACOUNT_ID] = accessee.GetAccesseeAccountId(); + jsonAccesseeObj[DM_TAG_ACCESSEE_TOKEN_ID] = accessee.GetAccesseeTokenId(); + jsonAccesseeObj[DM_TAG_ACCESSEE_SERVICE_NAME] = {}; // 预留字段 DP库未适配 + jsonAccesseeObj[DM_TAG_ACCESSEE_BUNDLE_NAME] = accessee.GetAccesseeBundleName(); + jsonAccesseeObj[DM_TAG_ACCESSEE_HAP_SIGNATURE] = accessee.GetAccesseeHapSignature(); + jsonAccesseeObj[DM_TAG_ACCESSEE_BIND_LEVEL] = accessee.GetAccesseeBindLevel(); + jsonAccesseeObj[DM_TAG_ACCESSEE_CREDENTIAL_ID] = accessee.GetAccesseeBindLevel(); + jsonAccesseeObj[DM_TAG_ACCESSEE_STATUS] = accessee.GetAccesseeStatus(); + jsonAccesseeObj[DM_TAG_ACCESSEE_SK_ID] = accessee.GetAccesseeSessionKeyId(); + jsonAccesseeObj[DM_TAG_ACCESSEE_SK_TIMESTAMP] = accessee.GetAccesseeSKTimeStamp(); + return SafetyDump(jsonAccesseeObj); +} + +int32_t DmAuthMessageProcessor::CreateSyncMessage(std::shared_ptr &context, nlohmann::json &jsonObject) +{ + DmAccess accessSide; // 代表本端的access + if (context->direction == DM_AUTH_SOURCE) { + accessSide = context->accesser; + } else { + accessSide = context->accessee; + } + std::string encSyncMsg; + int32_t ret = EncryptSyncMessage(context, accessSide, encSyncMsg); + if (ret != DM_OK) { + LOGE("DmAuthMessageProcessor::CreateSyncMessage encrypt failed"); + return ret; + } + jsonObject[DM_TAG_SYNC] = encSyncMsg; + return DM_OK; +} + +// 解析transmit和PSKID 解析160 +int32_t DmAuthMessageProcessor::ParseAuthStartMessgae(nlohmann::json &jsonObject, std::shared_ptr &context) +{ + if (jsonObject.is_discarded() || !jsonObject.contains(DM_TAG_DATA) || + !jsonObject[DM_TAG_DATA].is_string()) { + LOGE("DmAuthMessageProcessor::ParseAuthStartMessgae Unlegal json string failed"); + return ERR_DM_FAILED; + } + context->transmitData = jsonObject[DM_TAG_DATA].get(); + + std::string jsonTag; + if (context->isOnline == false && context->isAppCredentialVerified == false) { // 首次认证的应用凭据 + jsonTag = DM_TAG_APP_CREDENTIAL_ID; + context->accesser.appCredentialId = jsonObject[DM_TAG_APP_CREDENTIAL_ID].get(); + } else if (context->isOnline == false) { // 首次认证的用户凭据 + jsonTag = DM_TAG_USER_CREDENTIAL_ID; + context->accesser.userCredentialId = jsonObject[DM_TAG_USER_CREDENTIAL_ID].get(); + } else { // 非首次认证的应用凭据 + jsonTag = DM_TAG_APP_CREDENTIAL_ID; + context->accesser.appCredentialId = jsonObject[DM_TAG_APP_CREDENTIAL_ID].get(); + } + + if (!jsonObject.contains(jsonTag) || !jsonObject[jsonTag].is_string()) { + LOGE("DmAuthMessageProcessor::ParseAuthStartMessgae Unlegal json CRED ID"); + return ERR_DM_FAILED; + } + + context->authStateMachine->TransitionTo(std::make_shared()); + return DM_OK; +} + +int32_t DmAuthMessageProcessor::GetAclListStr(std::shared_ptr &context, std::string &aclList) +{ + nlohmann::json jsonAclListObj; + jsonAclListObj[DM_TAG_DMVERSION] = context->accesser.dmVersion; // 在80/90 流程会协商出双方均兼容的版本号,此处取accesser的ver即可 + + // 查询ACL + std::vector profiles = + DeviceProfileConnector::GetInstance().GetAccessControlProfile(); + std::vector accceserStrList; + std::vector accceseeStrList; + // 遍历acl table 找到双端历史acl记录 + for (auto &item : profiles) { + if (item.GetAccesser().GetAccesserDeviceId() == context->accesser.deviceId && + item.GetAccesser().GetAccesserUserId() == context->accesser.userId && + item.GetAccessee().GetAccesseeDeviceId() == context->accessee.deviceId && + item.GetAccessee().GetAccesseeUserId() == context->accessee.userId) { + // 以SHA256的摘要保存 + uint8_t accesserHash[DM_HASH_LEN] = {0}; + std::string accesserStr = AccesserToStr(item); + Crypto::DmGenerateStrHash(accesserStr.data(), accesserStr.size(), accesserHash, DM_HASH_LEN, 0); + accceserStrList.push_back(reinterpret_cast(accesserHash)); + + uint8_t accesseeHash[DM_HASH_LEN] = {0}; + std::string accesseeStr = AccesseeToStr(item); + Crypto::DmGenerateStrHash(accesseeStr.data(), accesseeStr.size(), accesseeHash, DM_HASH_LEN, 0); + accceseeStrList.push_back(reinterpret_cast(accesseeHash)); + } + } + if (accceserStrList.empty() || accceseeStrList.empty()) { + LOGI("DmAuthMessageProcessor::CreateSyncMessage acl lis is empty"); // 双方无旧ACL需要同步 此时返回空字符串 + } + + jsonAclListObj[DM_TAG_ACCESSER] = accceserStrList; + jsonAclListObj[DM_TAG_ACCESSEE] = accceseeStrList; + aclList = SafetyDump(jsonAclListObj); + return DM_OK; +} + +} // namespace DistributedHardware +} // namespace OHOS \ No newline at end of file diff --git a/services/implementation/src/authentication_v2/dm_auth_state.cpp b/services/implementation/src/authentication_v2/dm_auth_state.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2c1fda0ecf52c8b4ae2710257c77fd06bfa4713a --- /dev/null +++ b/services/implementation/src/authentication_v2/dm_auth_state.cpp @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "dm_auth_state.h" +#include "dm_auth_context.h" +#include "dm_auth_state_machine.h" +#if defined(SUPPORT_SCREENLOCK) +#include "screenlock_manager.h" +#endif +#include "dm_log.h" + +#undef LOG_TAG +#define LOG_TAG "DHDM_V2" + +namespace OHOS { +namespace DistributedHardware { + +namespace { + +const int32_t CLONE_AUTHENTICATE_TIMEOUT = 20; +const int32_t CLONE_NEGOTIATE_TIMEOUT = 10; +const int32_t CLONE_CONFIRM_TIMEOUT = 10; +const int32_t CLONE_ADD_TIMEOUT = 10; +const int32_t CLONE_WAIT_NEGOTIATE_TIMEOUT = 10; +const int32_t CLONE_WAIT_REQUEST_TIMEOUT = 10; +const int32_t CLONE_SESSION_HEARTBEAT_TIMEOUT = 20; + +} + +// clone task timeout map +const std::map TASK_TIME_OUT_MAP = { + { std::string(AUTHENTICATE_TIMEOUT_TASK), CLONE_AUTHENTICATE_TIMEOUT }, + { std::string(NEGOTIATE_TIMEOUT_TASK), CLONE_NEGOTIATE_TIMEOUT }, + { std::string(CONFIRM_TIMEOUT_TASK), CLONE_CONFIRM_TIMEOUT }, + { std::string(ADD_TIMEOUT_TASK), CLONE_ADD_TIMEOUT }, + { std::string(WAIT_NEGOTIATE_TIMEOUT_TASK), CLONE_WAIT_NEGOTIATE_TIMEOUT }, + { std::string(WAIT_REQUEST_TIMEOUT_TASK), CLONE_WAIT_REQUEST_TIMEOUT }, + { std::string(SESSION_HEARTBEAT_TIMEOUT_TASK), CLONE_SESSION_HEARTBEAT_TIMEOUT } +}; + +int32_t DmAuthState::GetTaskTimeout(std::shared_ptr context, const char* taskName, int32_t taskTimeOut) +{ + LOGI("GetTaskTimeout, taskName: %{public}s, authType_: %{public}d", taskName, context->authType); + if (context->authType == AUTH_TYPE_IMPORT_AUTH_CODE) { + auto timeout = TASK_TIME_OUT_MAP.find(std::string(taskName)); + if (timeout != TASK_TIME_OUT_MAP.end()) { + return timeout->second; + } + } + return taskTimeOut; +} + +void DmAuthState::HandleAuthenticateTimeout(std::shared_ptr context, std::string name) +{ + LOGI("DmAuthContext::HandleAuthenticateTimeout start timer name %{public}s", name.c_str()); + context->timer->DeleteTimer(name); + context->reason = ERR_DM_TIME_OUT; + context->authStateMachine->NotifyEventFinish(DmEventType::ON_FAIL); + LOGI("DmAuthContext::HandleAuthenticateTimeout complete"); +} + +bool DmAuthState::IsScreenLocked() +{ + bool isLocked = false; +#if defined(SUPPORT_SCREENLOCK) + isLocked = OHOS::ScreenLock::ScreenLockManager::GetInstance()->IsScreenLocked(); +#endif + LOGI("IsScreenLocked isLocked: %{public}d.", isLocked); + return isLocked; +} + +void DmAuthState::SyncAclList(std::shared_ptr context, int32_t accountId, + std::string credId, int32_t sessionKeyId, int32_t aclId) +{ + // 根据凭据id 删除sink端多余的凭据 + int32_t ret = context->hiChainAuthConnector->DeleteCredential(accountId, credId); + if (ret != DM_OK) { + LOGE("SyncAclList DeleteCredential failed."); + } + // 根据skid删除sk,删除skid + ret = DeviceProfileConnector::GetInstance().DeleteSessionKey(sessionKeyId); + if (ret != DM_OK) { + LOGE("SyncAclList DeleteSessionKey failed."); + } + // 删除本条acl + DeviceProfileConnector::GetInstance().DeleteAccessControlById(aclId); +} +} // namespace DistributedHardware +} // namespace OHOS diff --git a/services/implementation/src/authentication_v2/dm_auth_state_machine.cpp b/services/implementation/src/authentication_v2/dm_auth_state_machine.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0476e81d201dd656f5aff824c0b2fccc0a95e443 --- /dev/null +++ b/services/implementation/src/authentication_v2/dm_auth_state_machine.cpp @@ -0,0 +1,317 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "dm_log.h" +#include "dm_constants.h" +#include "dm_auth_state.h" +#include "dm_auth_context.h" + +#include "dm_auth_state_machine.h" +#undef LOG_TAG +#define LOG_TAG "DHDM_V2" + +namespace OHOS { +namespace DistributedHardware { + + +DmAuthStateMachine::DmAuthStateMachine(std::shared_ptr context) +{ + stateTransitionTable_ = { + // 此处省略下一状态为AuthXXXFinishState的迁移情况 + {DmAuthStateType::AUTH_IDLE_STATE, + {DmAuthStateType::AUTH_SRC_START_STATE, DmAuthStateType::AUTH_SINK_NEGOTIATE_STATE}}, + // Source端 状态迁移表 + {DmAuthStateType::AUTH_SRC_START_STATE, {DmAuthStateType::AUTH_SRC_NEGOTIATE_STATE}}, + {DmAuthStateType::AUTH_SRC_NEGOTIATE_STATE, {DmAuthStateType::AUTH_SRC_CONFIRM_STATE}}, + {DmAuthStateType::AUTH_SRC_CONFIRM_STATE, { + DmAuthStateType::AUTH_SRC_PIN_AUTH_START_STATE, // todo del + DmAuthStateType::AUTH_SRC_PIN_NEGOTIATE_START_STATE, + DmAuthStateType::AUTH_SRC_CREDENTIAL_AUTH_START_STATE, + }}, + {DmAuthStateType::AUTH_SRC_PIN_NEGOTIATE_START_STATE, { + DmAuthStateType::AUTH_SRC_PIN_INPUT_STATE, + DmAuthStateType::AUTH_SRC_PIN_NEGOTIATE_ULTRASONIC_PIN_STATE, + DmAuthStateType::AUTH_SRC_PIN_AUTH_START_STATE, + }}, + {DmAuthStateType::AUTH_SRC_PIN_INPUT_STATE, { + DmAuthStateType::AUTH_SRC_PIN_AUTH_START_STATE, + }}, + {DmAuthStateType::AUTH_SRC_PIN_NEGOTIATE_ULTRASONIC_PIN_STATE, { + DmAuthStateType::AUTH_SRC_PIN_AUTH_START_STATE, + DmAuthStateType::AUTH_SRC_PIN_NEGOTIATE_START_STATE, + }}, + {DmAuthStateType::AUTH_SRC_PIN_AUTH_START_STATE, { + DmAuthStateType::AUTH_SRC_PIN_AUTH_MSG_NEGOTIATE_STATE, + DmAuthStateType::AUTH_SRC_PIN_AUTH_START_STATE, // todo del + DmAuthStateType::AUTH_SRC_PIN_NEGOTIATE_START_STATE, + }}, + {DmAuthStateType::AUTH_SRC_PIN_AUTH_MSG_NEGOTIATE_STATE, { + DmAuthStateType::AUTH_SRC_PIN_AUTH_DONE_STATE, + DmAuthStateType::AUTH_SRC_PIN_AUTH_START_STATE, // todo del + DmAuthStateType::AUTH_SRC_PIN_NEGOTIATE_START_STATE, + }}, + {DmAuthStateType::AUTH_SRC_PIN_AUTH_DONE_STATE, { + DmAuthStateType::AUTH_SRC_CREDENTIAL_EXCHANGE_STATE, + DmAuthStateType::AUTH_SRC_PIN_AUTH_START_STATE, // todo del + DmAuthStateType::AUTH_SRC_PIN_NEGOTIATE_START_STATE, + }}, + {DmAuthStateType::AUTH_SRC_CREDENTIAL_EXCHANGE_STATE, {DmAuthStateType::AUTH_SRC_CREDENTIAL_AUTH_START_STATE}}, + {DmAuthStateType::AUTH_SRC_CREDENTIAL_AUTH_START_STATE, // 收到150的处理状态,发送160 + {DmAuthStateType::AUTH_SRC_CREDENTIAL_AUTH_NEGOTIATE_STATE}}, + + {DmAuthStateType::AUTH_SRC_CREDENTIAL_AUTH_NEGOTIATE_STATE, // 收到170的处理状态,后发送161 + {DmAuthStateType::AUTH_SRC_CREDENTIAL_AUTH_DONE_STATE}}, + + {DmAuthStateType::AUTH_SRC_CREDENTIAL_AUTH_DONE_STATE, // 收到171的处理状态 发送160/180 + {DmAuthStateType::AUTH_SRC_DATA_SYNC_STATE, DmAuthStateType::AUTH_SRC_CREDENTIAL_AUTH_NEGOTIATE_STATE}}, + + {DmAuthStateType::AUTH_SRC_DATA_SYNC_STATE, {}}, + // Sink端 状态迁移表 + //{DmAuthStateType::AUTH_IDLE_STATE, {DmAuthStateType::AUTH_SINK_NEGOTIATE_STATE}}, + //{DmAuthStateType::AUTH_SINK_START_STATE, {DmAuthStateType::AUTH_SINK_NEGOTIATE_STATE}}, + {DmAuthStateType::AUTH_SINK_NEGOTIATE_STATE, { + DmAuthStateType::AUTH_SINK_CONFIRM_STATE, + DmAuthStateType::AUTH_SINK_PIN_AUTH_START_STATE, + DmAuthStateType::AUTH_SINK_CREDENTIAL_AUTH_START_STATE + }}, // to check + {DmAuthStateType::AUTH_SINK_CONFIRM_STATE, { + DmAuthStateType::AUTH_SINK_PIN_AUTH_START_STATE, // todo del + DmAuthStateType::AUTH_SINK_PIN_NEGOTIATE_START_STATE, + }}, + {DmAuthStateType::AUTH_SINK_PIN_NEGOTIATE_START_STATE, { + DmAuthStateType::AUTH_SINK_PIN_DISPLAY_STATE, + DmAuthStateType::AUTH_SINK_PIN_NEGOTIATE_ULTRASONIC_PIN_STATE, + DmAuthStateType::AUTH_SINK_PIN_AUTH_START_STATE, + }}, + {DmAuthStateType::AUTH_SINK_PIN_DISPLAY_STATE, { + DmAuthStateType::AUTH_SINK_PIN_AUTH_START_STATE, + }}, + {DmAuthStateType::AUTH_SINK_PIN_NEGOTIATE_ULTRASONIC_PIN_STATE, { + DmAuthStateType::AUTH_SINK_PIN_AUTH_START_STATE, + DmAuthStateType::AUTH_SINK_PIN_NEGOTIATE_START_STATE, + }}, + {DmAuthStateType::AUTH_SINK_PIN_AUTH_START_STATE, { + DmAuthStateType::AUTH_SINK_PIN_AUTH_MSG_NEGOTIATE_STATE, + DmAuthStateType::AUTH_SINK_PIN_AUTH_START_STATE, // todo del + DmAuthStateType::AUTH_SINK_PIN_NEGOTIATE_START_STATE, + }}, + {DmAuthStateType::AUTH_SINK_PIN_AUTH_MSG_NEGOTIATE_STATE, { + DmAuthStateType::AUTH_SINK_PIN_AUTH_DONE_STATE, + DmAuthStateType::AUTH_SINK_PIN_AUTH_START_STATE, // todo del + DmAuthStateType::AUTH_SINK_PIN_NEGOTIATE_START_STATE, + }}, + {DmAuthStateType::AUTH_SINK_PIN_AUTH_DONE_STATE, {DmAuthStateType::AUTH_SINK_CREDENTIAL_EXCHANGE_STATE}}, + {DmAuthStateType::AUTH_SINK_CREDENTIAL_EXCHANGE_STATE, + {DmAuthStateType::AUTH_SINK_CREDENTIAL_AUTH_START_STATE}}, + + {DmAuthStateType::AUTH_SINK_CREDENTIAL_AUTH_START_STATE, // 收到160的处理状态,回复170 + {DmAuthStateType::AUTH_SINK_CREDENTIAL_AUTH_NEGOTIATE_STATE}}, + + {DmAuthStateType:: + AUTH_SINK_CREDENTIAL_AUTH_NEGOTIATE_STATE, // 收到161的处理状态,回复171;发送171后收到160 回退到AUTH_SINK_CREDENTIAL_AUTH_START_STATE进行第二次凭据认证 + {DmAuthStateType::AUTH_SINK_DATA_SYNC_STATE, DmAuthStateType::AUTH_SINK_CREDENTIAL_AUTH_START_STATE}}, + + {DmAuthStateType::AUTH_SINK_DATA_SYNC_STATE, {DmAuthStateType::AUTH_SINK_FINISH_STATE}}, // 收到180,回复190 + {DmAuthStateType::AUTH_SINK_FINISH_STATE, {}}, + }; + exceptionEvent_= { + DmEventType::ON_ERROR, // ERROR 错误 + DmEventType::ON_TIMEOUT, // 超时 + DmEventType::ON_FAIL, // 失败流程 + DmEventType::ON_SCREEN_LOCKED, // 锁屏 + }; + + running_ = true; + direction_ = context->direction; + + this->SetCurState(DmAuthStateType::AUTH_IDLE_STATE); + thread_ = std::thread(&DmAuthStateMachine::Run, this, context); +} +DmAuthStateMachine::~DmAuthStateMachine() +{ + Stop(); + thread_.join(); +}; + +// 通知状态迁移,执行状态对应具体action与异常处理(只允许在OnDataReceived中调用) +int32_t DmAuthStateMachine::TransitionTo(std::shared_ptr state) +{ + int32_t ret = DM_OK; + DmAuthStateType nextState = state->GetStateType(); + if (this->CheckStateTransitValid(nextState)) { + LOGI("DmAuthStateMachine: The state transition from %{public}d to %{public}d.", + GetCurState(), nextState); + { + std::lock_guard lock(stateMutex_); + // 存入到队列中 + statesQueue_.push(state); + } + stateCv_.notify_one(); + } else { + // 切换状态不合法,打印错误日志并返回错误码 + LOGE("DmAuthStateMachine: The state transition does not meet the rule from %{public}d to %{public}d.", + GetCurState(), nextState); + ret = ERR_DM_NEXT_STATE_INVALID; // 下一状态不合法错误码 + } + return ret; +} + +// action内部的期望事件,用于阻塞,当等到期望事件完成或其他异常时,返回实际发生的事件,而其他正常事件则会继续阻塞(只允许在action中调用) +DmEventType DmAuthStateMachine::WaitExpectEvent(DmEventType eventType) +{ + /* + 1、实际事件 = 期望事件,返回实际事件 + 2、实际事件 = 异常事件(事件超时等),同样返回实际事件 + 3、实际事件 = 其余事件,继续阻塞,但有个超时时间限制 + */ + std::unique_lock lock(eventMutex_); + // 记录进入函数的时间 + auto startTime = std::chrono::high_resolution_clock::now(); + while (true) { + eventCv_.wait(lock, [&] { + return !eventQueue_.empty(); + }); + // 获取事件, TODO:假设正常事件按序到达(状态机单线程按序等待), 是否成立? + DmEventType actualEventType = eventQueue_.front(); + eventQueue_.pop(); + // 判断是否是期望事件 + if (actualEventType == eventType || (exceptionEvent_.find(actualEventType) != exceptionEvent_.end())) { + return actualEventType; + } else { + // TODO: 非期望事件,忽略 or 结束流程 ? + } + // 做一个超时退出机制 + // 已经经过的时间 + auto elapsedTime = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - startTime); + if (elapsedTime.count() >= EVENT_TIMEOUT) { + break; + } + } + return DmEventType::ON_TIMEOUT; +} + +// 事件完成调用,传事件枚举(只允许在事件触发中调用),如果是异常事件,需在context的reason或者reply记录 +void DmAuthStateMachine::NotifyEventFinish(DmEventType eventType) +{ + LOGI("DmAuthStateMachine: NotifyEventFinish Event:%{public}d.", eventType); + { + // 添加事件到事件队列 + std::unique_lock lock(eventMutex_); + eventQueue_.push(eventType); + } + eventCv_.notify_one(); + if (eventType == DmEventType::ON_FAIL) { + if (direction_ == DM_AUTH_SOURCE) { + this->TransitionTo(std::make_shared()); + } else { + this->TransitionTo(std::make_shared()); + } + } +} + +// 循环等待状态转移,执行action +void DmAuthStateMachine::Run(std::shared_ptr context) +{ + while (running_.load()) { + auto state = FetchState(); + if (!state.has_value()) { + LOGI("DmAuthStateMachine::Run : No state to fetch."); + // 睡眠 100 毫秒 + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + continue; + } + // 获取到状态,执行状态的action + DmAuthStateType stateType = state.value()->GetStateType(); + this->SetCurState(stateType); + int32_t ret = state.value()->Action(context); + if (ret != DM_OK) { + LOGE("DmAuthStateMachine::Run err:%{public}d", ret); + if (context->reason == DM_OK) { + // 如果context的reason没有被设置,则设置为ret + context->reason = ret; + } + if (context->direction == DM_AUTH_SOURCE) { + this->TransitionTo(std::make_shared()); + } else { + this->TransitionTo(std::make_shared()); + } + // finish需要,清理context以及重启状态机 + } else { + LOGI("DmAuthStateMachine::Run ok state:%{public}d", stateType); + } + } + LOGE("DmAuthStateMachine::Run end"); +} + +std::optional> DmAuthStateMachine::FetchState() +{ + std::unique_lock lock(stateMutex_); + stateCv_.wait(lock, [&] { + return !running_.load() || !statesQueue_.empty(); + }); + + if (!running_.load()) return std::nullopt; + + std::shared_ptr state = statesQueue_.front(); + statesQueue_.pop(); + return state; +} + +// 停止线程 +void DmAuthStateMachine::Stop() +{ + running_.store(false); + stateCv_.notify_all(); + eventCv_.notify_all(); +} + + +// 设置当前状态 +void DmAuthStateMachine::SetCurState(DmAuthStateType state) +{ + LOGE("DmAuthStateMachine:: TODO LOGI SetCurState:%{public}d", state); + curState_ = state; +} + +// 获取当前状态 +DmAuthStateType DmAuthStateMachine::GetCurState() +{ + return curState_; +} + +// 检验下一状态迁移合法性 +bool DmAuthStateMachine::CheckStateTransitValid(DmAuthStateType nextState) +{ + if (curState_ == nextState || curState_ == DmAuthStateType::AUTH_SRC_FINISH_STATE || + curState_ == DmAuthStateType::AUTH_SINK_FINISH_STATE) { + return false; + } + + // 判断下一状态是否为AuthXXXFinishState,可直接切状态,返回 + if (nextState == DmAuthStateType::AUTH_SRC_FINISH_STATE || nextState == DmAuthStateType::AUTH_SINK_FINISH_STATE) { + return true; + } + // 判断是否符合状态迁移表 + auto it = stateTransitionTable_.find(curState_); + if (it != stateTransitionTable_.end()) { + const std::set& allowedStates = it->second; + return allowedStates.find(nextState) != allowedStates.end(); + } + return false; +} + + +} // namespace DistributedHardware +} // namespace OHOS diff --git a/services/implementation/src/cryptomgr/crypto_mgr.cpp b/services/implementation/src/cryptomgr/crypto_mgr.cpp index 91d35dee06ff9b250dc4346ff3b965c7ae3be67c..1e9e1cf22e1519c8a06d5f56755ede8e3721a144 100644 --- a/services/implementation/src/cryptomgr/crypto_mgr.cpp +++ b/services/implementation/src/cryptomgr/crypto_mgr.cpp @@ -17,6 +17,7 @@ #include #include +#include #include "mbedtls/base64.h" #include "mbedtls/cipher.h" @@ -304,10 +305,21 @@ int32_t CryptoMgr::SaveSessionKey(const uint8_t *sessionKey, const uint32_t keyL std::lock_guard lock(sessionKeyMtx_); sessionKey_.key = (uint8_t*)calloc(keyLen, sizeof(uint8_t)); sessionKey_.keyLen = keyLen; + memcpy_s(sessionKey_.key, keyLen, sessionKey, keyLen); } return DM_OK; } +uint32_t CryptoMgr::GetSessionKey(uint8_t *sessionKey) +{ + std::lock_guard lock(sessionKeyMtx_); + if (sessionKey == nullptr) { // 用于获取密钥长度 外部进行内存申请 + return sessionKey_.keyLen; + } + memcpy_s(sessionKey, sessionKey_.keyLen, sessionKey_.key, sessionKey_.keyLen); + return sessionKey_.keyLen; +} + void CryptoMgr::ClearSessionKey() { std::lock_guard lock(sessionKeyMtx_); diff --git a/services/implementation/src/dependency/hichain/hichain_auth_connector.cpp b/services/implementation/src/dependency/hichain/hichain_auth_connector.cpp index 5dcad89c012fb3c4a89599f855f2446c843d1ef0..bdb7fa049bbba6ab0b0fb74cd9e800718bb7a580 100644 --- a/services/implementation/src/dependency/hichain/hichain_auth_connector.cpp +++ b/services/implementation/src/dependency/hichain/hichain_auth_connector.cpp @@ -12,6 +12,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +#include #include "hichain_auth_connector.h" #include "dm_log.h" @@ -89,6 +91,181 @@ int32_t HiChainAuthConnector::ProcessAuthData(int64_t requestId, std::string aut return DM_OK; } +// 处理凭据认证报文 +// authReqId 认证Id +// data 对端报文内容 +int32_t HiChainAuthConnector::ProcessCredData(int64_t authReqId, const std::string &data) +{ + LOGI("HiChainAuthConnector::ProcessCredData start."); + const CredAuthManager *credAuthManager = GetCredAuthInstance(); + int32_t ret = credAuthManager->processCredData(authReqId, reinterpret_cast(data.c_str()), + data.length(), &deviceAuthCallback_); + if (ret != HC_SUCCESS) { + LOGE("Hichain processData failed ret %{public}d.", ret); + return ERR_DM_FAILED; + } + LOGI("HiChainAuthConnector::ProcessCredData leave."); + return DM_OK; +} + +// 生成凭据,返回凭据Id +// osAccountId 本段UserId +// authParams json格式字符串,key-value根据上下文确定 +// credId 返回的凭据Id +int32_t HiChainAuthConnector::AddCredential(int32_t osAccountId, const std::string &authParams, std::string &credId) +{ + LOGI("HiChainAuthConnector::AddCredential start."); + LOGI("HiChainAuthConnector::AddCredential osAccount=%{public}d, authParams=%{public}s\n", + osAccountId, authParams.c_str()); + char *returnData = NULL; + const CredManager *credManager = GetCredMgrInstance(); + int32_t ret = credManager->addCredential(osAccountId, authParams.c_str(), &returnData); + if (ret != HC_SUCCESS || returnData == NULL) { + LOGE("Hichain addCredential failed ret %{public}d.", ret); + free(returnData); + return ERR_DM_FAILED; + } + LOGI("HiChainAuthConnector::AddCredential addCredential success ret=%{public}d, returnData=%{public}s.", + ret, returnData); + credId = std::string(returnData); + LOGI("HiChainAuthConnector::AddCredential credId=%{public}s.", credId.c_str()); + free(returnData); + LOGI("HiChainAuthConnector::AddCredential leave."); + return DM_OK; +} + +// 根据凭据Id导出公钥 +// osAccountId 本段UserId +// credId 凭据Id +// publicKey 公钥 +int32_t HiChainAuthConnector::ExportCredential(int32_t osAccountId, const std::string &credId, std::string &publicKey) +{ + LOGI("HiChainAuthConnector::ExportCredential start."); + char *returnData = NULL; + const CredManager *credManager = GetCredMgrInstance(); + int32_t ret = credManager->exportCredential(osAccountId, credId.c_str(), &returnData); + if (ret != HC_SUCCESS || returnData == NULL) { + LOGE("Hichain exportCredential failed ret %{public}d.", ret); + free(returnData); + return ERR_DM_FAILED; + } + + // 导出的公钥是json格式,需要解析 + nlohmann::json jsonAuthParam = nlohmann::json::parse(returnData, nullptr, false); + free(returnData); + if (jsonAuthParam.is_discarded() || !IsString(jsonAuthParam, "keyValue")) { + LOGE("Hichain exportCredential failed, returnData is invalid."); + return ERR_DM_FAILED; + } + + publicKey = jsonAuthParam["keyValue"].get(); + LOGI("HiChainAuthConnector::ExportCredential leave."); + return DM_OK; +} + +// 凭据协商 +// osAccountId 本段UserId +// selfCredId 本段凭据Id +// authParams 协商参数 +// credId 返回的凭据Id +int32_t HiChainAuthConnector::AgreeCredential(int32_t osAccountId, const std::string selfCredId, + const std::string &authParams, std::string &credId) +{ + LOGI("HiChainAuthConnector::AgreeCredential start."); + LOGI("HiChainAuthConnector::AgreeCredential osAccountId=%{public}d, selfCredId=%{public}s, authParams=%{public}s\n", + osAccountId, selfCredId.c_str(), authParams.c_str()); + char *returnData = NULL; + const CredManager *credManager = GetCredMgrInstance(); + int32_t ret = credManager->agreeCredential(osAccountId, selfCredId.c_str(), authParams.c_str(), &returnData); + if (ret != HC_SUCCESS || returnData == NULL) { + LOGE("Hichain agreeCredential failed ret %{public}d.", ret); + return ERR_DM_FAILED; + } + credId = returnData; + free(returnData); + LOGI("HiChainAuthConnector::AgreeCredential leave."); + return DM_OK; +} + +// 删除凭据 +// osAccountId 本段用户Id +// credId 待删除的凭据Id +int32_t HiChainAuthConnector::DeleteCredential(int32_t osAccountId, const std::string &credId) +{ + LOGI("HiChainAuthConnector::DeleteCredential start."); + const CredManager *credManager = GetCredMgrInstance(); + int32_t ret = credManager->deleteCredential(osAccountId, credId.c_str()); + if (ret != HC_SUCCESS) { + LOGE("Hichain deleteCredential failed ret %{public}d.", ret); + return ERR_DM_FAILED; + } + LOGI("HiChainAuthConnector::DeleteCredential leave."); + return DM_OK; +} + +// 凭据认证 +// osAccountId 系统用户参数 +// authReqId 认证请求id +// credId 对端凭据Id +// pinCode pin码认证(点对点临时凭据不能为空) +int32_t HiChainAuthConnector::AuthCredential(int32_t osAccountId, int64_t authReqId, const std::string &credId, + const std::string &pinCode) +{ + LOGI("HiChainAuthConnector::AuthCredential start."); + if (credId.empty() && pinCode.empty()) { + LOGE("HiChainAuthConnector::AuthCredential failed, credId and pinCode is empty."); + return ERR_DM_FAILED; + } + + // 创建authParams的json格式字符串 + nlohmann::json jsonAuthParam; + if (!credId.empty()) { + jsonAuthParam["credId"] = credId; + } + if (!pinCode.empty()) { + jsonAuthParam["pinCode"] = pinCode; + } + std::string authParams = SafetyDump(jsonAuthParam); + + // 凭据认证 + const CredAuthManager *credAuthManager = GetCredAuthInstance(); + int32_t ret = credAuthManager->authCredential(osAccountId, authReqId, authParams.c_str(), &deviceAuthCallback_); + if (ret != HC_SUCCESS) { + LOGE("HiChainAuthConnector::AuthCredential failed ret %{public}d.", ret); + return ERR_DM_FAILED; + } + LOGI("HiChainAuthConnector::AuthCredential leave."); + return DM_OK; +} + +// pin码认证 +int32_t HiChainAuthConnector::AuthCredentialPinCode(int32_t osAccountId, int64_t authReqId, int32_t pinCode) +{ + LOGI("HiChainAuthConnector::AuthCredential start."); + if (pinCode == INVALID_PINCODE) { + LOGE("HiChainAuthConnector::AuthCredentialPinCode failed, pinCode is empty."); + return ERR_DM_FAILED; + } + + // 创建authParams的json格式字符串 + nlohmann::json jsonAuthParam; + + jsonAuthParam[FIELD_PIN_CODE] = std::to_string(pinCode); + jsonAuthParam[FIELD_SERVICE_PKG_NAME] = std::string(DM_PKG_NAME); + + std::string authParams = SafetyDump(jsonAuthParam); + + // 凭据认证 + const CredAuthManager *credAuthManager = GetCredAuthInstance(); + int32_t ret = credAuthManager->authCredential(osAccountId, authReqId, authParams.c_str(), &deviceAuthCallback_); + if (ret != HC_SUCCESS) { + LOGE("HiChainAuthConnector::AuthCredential failed ret %{public}d.", ret); + return ERR_DM_FAILED; + } + + return DM_OK; +} + bool HiChainAuthConnector::onTransmit(int64_t requestId, const uint8_t *data, uint32_t dataLen) { LOGI("AuthDevice onTransmit, requestId %{public}" PRId64, requestId); @@ -102,26 +279,11 @@ bool HiChainAuthConnector::onTransmit(int64_t requestId, const uint8_t *data, ui char *HiChainAuthConnector::onRequest(int64_t requestId, int operationCode, const char *reqParams) { LOGI("HiChainAuthConnector::onRequest start."); - (void)requestId; - (void)reqParams; if (dmDeviceAuthCallback_ == nullptr) { LOGE("HiChainAuthConnector::onRequest dmDeviceAuthCallback_ is nullptr."); return nullptr; } - nlohmann::json jsonObj; - int32_t pinCode = INVALID_PINCODE; - if (dmDeviceAuthCallback_->GetPinCode(pinCode) == ERR_DM_FAILED || pinCode == INVALID_PINCODE) { - jsonObj[FIELD_CONFIRMATION] = RequestResponse::REQUEST_REJECTED; - } else { - jsonObj[FIELD_CONFIRMATION] = RequestResponse::REQUEST_ACCEPTED; - jsonObj[FIELD_PIN_CODE] = std::to_string(pinCode); - } - std::string deviceId = ""; - dmDeviceAuthCallback_->GetRemoteDeviceId(deviceId); - jsonObj[FIELD_PEER_CONN_DEVICE_ID] = deviceId; - std::string jsonStr = SafetyDump(jsonObj); - char *buffer = strdup(jsonStr.c_str()); - return buffer; + return dmDeviceAuthCallback_->AuthDeviceRequest(requestId, operationCode, reqParams); } void HiChainAuthConnector::onFinish(int64_t requestId, int operationCode, const char *returnData) @@ -198,6 +360,53 @@ int32_t HiChainAuthConnector::GenerateCredential(std::string &localUdid, int32_t return DM_OK; } +int32_t HiChainAuthConnector::QueryCredentialInfo(int32_t userId, nlohmann::json queryParams, + nlohmann::json &resultJson) +{ + int32_t ret; + + const CredManager *cm = GetCredMgrInstance(); + char *credIdList = nullptr; + // Q: 之前都是用的ProcessCredential查询,现在是否可用queryCredentialByParams查询? + ret = cm->queryCredentialByParams(userId, SafetyDump(queryParams).c_str(), + &credIdList); + // TODO: 可能是空的,要返回DM_OK + if (ret != DM_OK) { + LOGE("HiChainAuthConnector::QueryCredentialInfo fail to query credential id list."); + return ERR_DM_FAILED; + } + nlohmann::json credIdListJson = nlohmann::json::parse(credIdList, nullptr, false); + FreeJsonString(credIdList); + if (credIdListJson.is_discarded()) { + LOGE("HiChainAuthConnector::QueryCredentialInfo credential id list to jsonStr error"); + return ERR_DM_FAILED; + } + + for (const auto& element : credIdListJson) { + if (!element.is_string()) { + continue; + } + std::string credId = element.get(); + + char *returnCredInfo = nullptr; + ret = cm->queryCredInfoByCredId(userId, credId.c_str(), &returnCredInfo); + if (ret != DM_OK) { + LOGE("HiChainAuthConnector::QueryCredentialInfo fail to query credential info."); + return ERR_DM_FAILED; + } + nlohmann::json credInfoJson = nlohmann::json::parse(returnCredInfo, nullptr, false); + FreeJsonString(returnCredInfo); + if (credInfoJson.is_discarded()) { + LOGE("HiChainAuthConnector::QueryCredentialInfo credential info jsonStr error"); + return ERR_DM_FAILED; + } + + resultJson[credId] = credInfoJson; + } + + return DM_OK; +} + bool HiChainAuthConnector::QueryCredential(std::string &localUdid, int32_t osAccountId) { LOGI("HiChainAuthConnector::QueryCredential start."); diff --git a/services/implementation/src/dependency/softbus/softbus_connector.cpp b/services/implementation/src/dependency/softbus/softbus_connector.cpp index 7c471874ee55ad38d9e41e9051711af3da981618..a4dc3ac87509748bc6829f3ddc8c7fdf71956b70 100644 --- a/services/implementation/src/dependency/softbus/softbus_connector.cpp +++ b/services/implementation/src/dependency/softbus/softbus_connector.cpp @@ -430,7 +430,8 @@ void SoftbusConnector::DeleteOffLineTimer(std::string &udidHash) } } -bool SoftbusConnector::CheckIsOnline(const std::string &targetDeviceId) +// isHash:传入的deviceId是否为哈希值 +bool SoftbusConnector::CheckIsOnline(const std::string &targetDeviceIdHash, bool isHash) { LOGI("Check the device is online."); int32_t deviceCount = 0; @@ -447,7 +448,8 @@ bool SoftbusConnector::CheckIsOnline(const std::string &targetDeviceId) LOGE("[SOFTBUS]GetNodeKeyInfo failed."); } std::string udid = reinterpret_cast(mUdid); - if (udid == targetDeviceId) { + if ((isHash == false && udid == targetDeviceIdHash) || + (isHash == true && Crypto::Sha256(udid).find(targetDeviceIdHash) == 0)) { LOGI("The device is online."); FreeNodeInfo(nodeInfo); return true; @@ -458,6 +460,11 @@ bool SoftbusConnector::CheckIsOnline(const std::string &targetDeviceId) return false; } +bool SoftbusConnector::CheckIsOnline(const std::string &targetDeviceId) +{ + return CheckIsOnline(targetDeviceId, false); +} + DmDeviceInfo SoftbusConnector::GetDeviceInfoByDeviceId(const std::string &deviceId) { LOGI("SoftbusConnector::GetDeviceInfoBydeviceId"); diff --git a/services/implementation/src/dependency/softbus/softbus_session.cpp b/services/implementation/src/dependency/softbus/softbus_session.cpp index 633aca531540f7dd65c4b15322ea0d0e973b5cf1..b10bb113786f13ea1a9a8cf1e8f49074f3d72913 100644 --- a/services/implementation/src/dependency/softbus/softbus_session.cpp +++ b/services/implementation/src/dependency/softbus/softbus_session.cpp @@ -172,7 +172,7 @@ int32_t SoftbusSession::SendData(int32_t sessionId, std::string &message) } int32_t msgType = jsonObject[TAG_MSG_TYPE].get(); LOGI("start, msgType: %{public}d.", msgType); - if (sessionCallback_->GetIsCryptoSupport()) { + if (sessionCallback_ != nullptr && sessionCallback_->GetIsCryptoSupport()) { LOGI("SendData Start encryption."); } int32_t ret = SendBytes(sessionId, message.c_str(), strlen(message.c_str())); diff --git a/services/implementation/src/device_manager_service_impl.cpp b/services/implementation/src/device_manager_service_impl.cpp index 177421b38bbb51a57976d5d98cce72832471bc1b..bb1ab1e3916e881a836b8adcd17738b3b8dd84cf 100644 --- a/services/implementation/src/device_manager_service_impl.cpp +++ b/services/implementation/src/device_manager_service_impl.cpp @@ -18,6 +18,7 @@ #include #include "app_manager.h" +#include "dm_error_type.h" #include "dm_anonymous.h" #include "dm_constants.h" #include "dm_crypto.h" @@ -29,14 +30,72 @@ #if !(defined(__LITEOS_M__) || defined(LITE_DEVICE)) #include "dm_common_event_manager.h" #include "parameter.h" +#include "dm_random.h" #include "common_event_support.h" using namespace OHOS::EventFwk; #endif namespace OHOS { namespace DistributedHardware { + +namespace { + // One year 365 * 24 * 60 * 60 constexpr int32_t MAX_ALWAYS_ALLOW_SECONDS = 31536000; +constexpr int32_t MIN_PIN_CODE = 100000; +constexpr int32_t MAX_PIN_CODE = 999999; +// 新协议字段定义,为避免对新协议头文件依赖,不直接依赖新协议头文件 +// TODO: 需要统一到公共头文件中 +constexpr int32_t MSG_TYPE_REQ_ACL_NEGOTIATE = 80; +constexpr int32_t MSG_TYPE_RESP_ACL_NEGOTIATE = 90; +constexpr int32_t MSG_TYPE_REQ_AUTH_TERMINATE = 104; +constexpr int32_t AUTH_SRC_FINISH_STATE = 12; +constexpr const char *DM_TAG_REPLY = "REPLY"; +constexpr const char *TAG_AUTH_FINISH = "isFinish"; + +bool IsMessageOldVersion(int sessionId, const void *data, unsigned int dataLen) +{ + std::string message = std::string(reinterpret_cast(data), dataLen); + nlohmann::json jsonObject = nlohmann::json::parse(message, nullptr, false); + if (jsonObject.is_discarded() || !IsInt32(jsonObject, TAG_MSG_TYPE)) { + LOGE("IsMessageOldVersion decode jsonStr error"); + return false; + } + + if (jsonObject[TAG_MSG_TYPE].get() != MSG_TYPE_REQ_ACL_NEGOTIATE && + jsonObject[TAG_MSG_TYPE].get() != MSG_TYPE_RESP_ACL_NEGOTIATE) { + return false; + } + + std::string dmVersion = ""; + std::string edition = ""; + if (IsString(jsonObject, DM_TAG_DMVERSION)) { + dmVersion = jsonObject[DM_TAG_DMVERSION].get(); + } + if (IsString(jsonObject, DM_TAG_EDITION)) { + edition = jsonObject[DM_TAG_EDITION].get(); + } + dmVersion = AuthManagerBase::ConvertSrcVersion(dmVersion, edition); + + // 若版本号高于5.0.4旧协议最高版本,则不需要切换老协议 + if (CompareVersion(dmVersion, DM_VERSION_5_0_9) == true) { + return false; + } + + return true; +} + +std::string CreateTerminateMessage(void) +{ + nlohmann::json jsonObject; + jsonObject[TAG_MSG_TYPE] = MSG_TYPE_REQ_AUTH_TERMINATE; + jsonObject[DM_TAG_REPLY] = ERR_DM_VERSION_INCOMPATIBLE; + jsonObject[TAG_AUTH_FINISH] = false; + + return jsonObject.dump(); +} + +} DeviceManagerServiceImpl::DeviceManagerServiceImpl() { @@ -47,6 +106,24 @@ DeviceManagerServiceImpl::~DeviceManagerServiceImpl() { LOGI("DeviceManagerServiceImpl destructor"); } +int32_t DeviceManagerServiceImpl::InitAndRegisterAuthMgr(bool isSrcSide) +{ + if (authMgr_ == nullptr) { + if (isSrcSide) { + authMgr_ = std::make_shared(softbusConnector_, listener_, hiChainAuthConnector_); + } else { + authMgr_ = std::make_shared(softbusConnector_, listener_, hiChainAuthConnector_); + } + softbusConnector_->GetSoftbusSession()->RegisterSessionCallback(authMgr_); + // hiChainConnector_->RegisterHiChainCallback(authMgr_); + hiChainAuthConnector_->RegisterHiChainAuthCallback(authMgr_); + } else { + // 线程已创建authMgr_,说明已有绑定事件,其他请求拒绝,返回错误码 + LOGI("DeviceManagerServiceImpl::InitAndRegisterAuthMgr authMgr_ is not null, no need to create"); + //return ERR_DM_AUTH_BUSINESS_BUSY; + } + return DM_OK; +} int32_t DeviceManagerServiceImpl::Initialize(const std::shared_ptr &listener) { @@ -68,13 +145,13 @@ int32_t DeviceManagerServiceImpl::Initialize(const std::shared_ptrRegisterSoftbusStateCallback(); } - if (authMgr_ == nullptr) { - authMgr_ = std::make_shared(softbusConnector_, hiChainConnector_, listener, - hiChainAuthConnector_); - softbusConnector_->GetSoftbusSession()->RegisterSessionCallback(authMgr_); - hiChainConnector_->RegisterHiChainCallback(authMgr_); - hiChainAuthConnector_->RegisterHiChainAuthCallback(authMgr_); - } + // if (authMgr_ == nullptr) { + // authMgr_ = std::make_shared(softbusConnector_, hiChainConnector_, listener, + // hiChainAuthConnector_); + // softbusConnector_->GetSoftbusSession()->RegisterSessionCallback(authMgr_); + // hiChainConnector_->RegisterHiChainCallback(authMgr_); + // hiChainAuthConnector_->RegisterHiChainAuthCallback(authMgr_); + // } if (credentialMgr_ == nullptr) { credentialMgr_ = std::make_shared(hiChainConnector_, listener); } @@ -302,6 +379,11 @@ std::string DeviceManagerServiceImpl::GetUdidHashByNetworkId(const std::string & int DeviceManagerServiceImpl::OnSessionOpened(int sessionId, int result) { + // sink端绑定对象初始化与方法注册 + int32_t ret = InitAndRegisterAuthMgr(false); + if (ret != DM_OK) { + return ret; + } std::string peerUdid = ""; softbusConnector_->GetSoftbusSession()->GetPeerDeviceId(sessionId, peerUdid); struct RadarInfo info = { @@ -322,9 +404,113 @@ void DeviceManagerServiceImpl::OnSessionClosed(int sessionId) SoftbusSession::OnSessionClosed(sessionId); } +int32_t DeviceManagerServiceImpl::CreateAuthMgrByMessage(int sessionId, const void *data, unsigned int dataLen) +{ + if (data == nullptr || dataLen < 0) { + LOGE("DeviceManagerServiceImpl::CreateAuthMgrByMessage fail to reveive data from DeviceManagerServiceImpl " + "with dataLen: %{public}d", dataLen); + return ERR_DM_INPUT_PARA_INVALID; + } + + std::string message = std::string(reinterpret_cast(data), dataLen); + nlohmann::json jsonObject = nlohmann::json::parse(message, nullptr, false); + if (jsonObject.is_discarded()) { + LOGE("DeviceManagerServiceImpl::CreateAuthMgrByMessage decode jsonStr error"); + return ERR_DM_JSON_PARSE_STRING; + } + + // 获取版本号 + std::string dmVersion; + std::string edition = ""; + if (IsString(jsonObject, DM_TAG_DMVERSION) == false) { + LOGE("DeviceManagerServiceImpl::CreateAuthMgrByMessage decode dmversion error"); + return ERR_DM_JSON_PARSE_STRING; + } + dmVersion = jsonObject[DM_TAG_DMVERSION].get(); + if (IsString(jsonObject, DM_TAG_EDITION)) { + edition = jsonObject[DM_TAG_EDITION].get(); + } + dmVersion = AuthManagerBase::ConvertSrcVersion(dmVersion, edition); + + if (CompareVersion(dmVersion, DM_VERSION_5_1_0) == false) { + // 创建老协议对象 + authMgr_ = std::make_shared(softbusConnector_, hiChainConnector_, + listener_, hiChainAuthConnector_); + + // 参数2 sessionSide为0,authMgr_为空一定是sink端,src端会在BindTarget时创建协议对象 + authMgr_->OnSessionOpened(sessionId, 0, 0); + LOGI("DeviceManagerServiceImpl::CreateAuthMgrByMessage sink transfer to old version success"); + return DM_OK; + } + + // 创建新协议对象 + return InitAndRegisterAuthMgr(false); +} + +// 版本降级时,基于报文判断是src还是sink +// src: 收到90报文 +// sink:收到80报文 +bool IsAuthManagerSourceByMessage(const void *data, unsigned int dataLen) +{ + std::string message = std::string(reinterpret_cast(data), dataLen); + // 走到这里已经确认可以转json,所以不需要再判断 + nlohmann::json jsonObject = nlohmann::json::parse(message, nullptr, false); + + return jsonObject[TAG_MSG_TYPE].get() == MSG_TYPE_RESP_ACL_NEGOTIATE; +} + void DeviceManagerServiceImpl::OnBytesReceived(int sessionId, const void *data, unsigned int dataLen) { + int32_t ret; + + if (data == nullptr || dataLen < 0) { + LOGE("DeviceManagerServiceImpl::OnBytesReceived fail to reveive data from DeviceManagerServiceImpl " + "with dataLen: %{public}d", dataLen); + return; + } + + /** + 监听80/90报文 + 新-老:src端收到90报文时发现版本不匹配问题,重新BindTartget + 老-新:sink端收到80报文时发现版本不匹配问题,重新OnSessionOpened和OnBytesReceived + + TODO: 考虑authMgr_的切换是否有多线程问题 + */ + if (authMgr_->isAuthNewVersion_ && IsMessageOldVersion(sessionId, data, dataLen)) { + std::string pkgName; + PeerTargetId peerTargetId; + std::map bindParam; + authMgr_->GetBindTargetParams(pkgName, peerTargetId, bindParam); + authMgr_ = std::make_shared(softbusConnector_, hiChainConnector_, + listener_, hiChainAuthConnector_); + authMgr_->isAuthNewVersion_ = false; + softbusConnector_->GetSoftbusSession()->RegisterSessionCallback(authMgr_); + hiChainAuthConnector_->RegisterHiChainAuthCallback(authMgr_); + + if (IsAuthManagerSourceByMessage(data, dataLen)) { + // 发送停止报文 + // 不能走新协议的停止,新协议是信号机制,无法串行停止,会存在时延,导致未停止就创建了新对象, + // 然后新协议的超时机制会再次停止softbus + std::string endMessage = CreateTerminateMessage(); + (void)softbusConnector_->GetSoftbusSession()->SendData(sessionId, endMessage); + softbusConnector_->GetSoftbusSession()->OnSessionClosed(sessionId); + + ret = authMgr_->BindTarget(pkgName, peerTargetId, bindParam); + if (ret != DM_OK) { + LOGE("DeviceManagerServiceImpl::OnBytesReceived authManager BindTarget failed"); + return; + } + LOGI("DeviceManagerServiceImpl::OnBytesReceived src transfer to old version success"); + return; + } + + // 参数2 sessionSide为0,authMgr_为空一定是sink端,src端会在BindTarget时创建协议对象 + authMgr_->OnSessionOpened(sessionId, 0, 0); + LOGI("DeviceManagerServiceImpl::OnBytesReceived src transfer to old version success"); + } + SoftbusSession::OnBytesReceived(sessionId, data, dataLen); + LOGI("DeviceManagerServiceImpl::OnBytesReceived in bytes received"); } int32_t DeviceManagerServiceImpl::RequestCredential(const std::string &reqJsonStr, std::string &returnJsonStr) @@ -578,7 +764,7 @@ int32_t DeviceManagerServiceImpl::ImportAuthCode(const std::string &pkgName, con int32_t DeviceManagerServiceImpl::ExportAuthCode(std::string &authCode) { - int32_t ret = authMgr_->GeneratePincode(); + int32_t ret = GenRandInt(MIN_PIN_CODE, MAX_PIN_CODE); authCode = std::to_string(ret); LOGI("ExportAuthCode success, authCode: %{public}s.", GetAnonyString(authCode).c_str()); return DM_OK; @@ -587,6 +773,11 @@ int32_t DeviceManagerServiceImpl::ExportAuthCode(std::string &authCode) int32_t DeviceManagerServiceImpl::BindTarget(const std::string &pkgName, const PeerTargetId &targetId, const std::map &bindParam) { + // source端绑定对象初始化与方法注册 + int32_t ret = InitAndRegisterAuthMgr(true); + if (ret != DM_OK) { + return ret; + } if (pkgName.empty()) { LOGE("BindTarget failed, pkgName is empty"); return ERR_DM_INPUT_PARA_INVALID; @@ -1084,3 +1275,4 @@ extern "C" IDeviceManagerServiceImpl *CreateDMServiceObject(void) } } // namespace DistributedHardware } // namespace OHOS +; \ No newline at end of file