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 c759db1587cb7544780d5a35e42653e0bf9a0357..d66527a927a757559fb5cdcba4f50405601ac2c9 100755 --- a/common/include/dm_constants.h +++ b/common/include/dm_constants.h @@ -130,7 +130,9 @@ enum { ERR_DM_HILINKSVC_DISCONNECT = 96929829, ERR_DM_WISE_NEED_LOGIN = 96929830, ERR_DM_NAME_EMPTY = 96929831, - ERR_DM_HICHAIN_PROOFMISMATCH = 96929832 + ERR_DM_HICHAIN_PROOFMISMATCH = 96929832, + ERR_DM_NEXT_STATE_INVALID = 96929833, + ERR_DM_GET_SESSION_KEY_FAILED = 96929834, }; constexpr const char* TAG_GROUP_ID = "groupId"; diff --git a/services/implementation/BUILD.gn b/services/implementation/BUILD.gn index 94f967c62e097acc2cc6762d5e1fbe4f306dc83a..28a1df69317bb8d59a9090034d900573a79060be 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", @@ -179,6 +182,16 @@ 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/config/dm_config_manager.cpp", "src/credential/dm_credential_manager.cpp", "src/cryptomgr/crypto_mgr.cpp", 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..da27042c267ff7fe072d33db2441811c2621e591 --- /dev/null +++ b/services/implementation/include/authentication_v2/auth_manager.h @@ -0,0 +1,121 @@ +/* + * 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" + +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 HML_SESSION_TIMEOUT = 10; +const int32_t AUTHENTICATE_TIMEOUT = 120; +constexpr const char* DM_VERSION_5_1_0 = "5.1.0"; +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 ISoftbusSessionCallback, + public IDmDeviceAuthCallback, + public std::enable_shared_from_this { +public: + AuthManager(std::shared_ptr softbusConnector, + std::shared_ptr listener, + std::shared_ptr hiChainAuthConnector); + void SetAuthContext(std::shared_ptr context); + + std::shared_ptr GetAuthContext(); + + // 各类事件触发的函数实现(虚函数) + int32_t GetPinCode(int32_t &code) override; + + int32_t BindTarget(const std::string &pkgName, const PeerTargetId &targetId, + const std::map &bindParam); +protected: + // 上下文(需在该层级进行创建) + std::shared_ptr context_; +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 &pkgName, 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 &pkgName); + int32_t CheckAuthParamVaild(const std::string &pkgName, int32_t authType, + const std::string &deviceId, const std::string &extra); + void InitAuthState(const std::string &pkgName, int32_t authType, + const std::string &deviceId, const std::string &extra); + int32_t AuthenticateDevice(const std::string &pkgName, int32_t authType, + const std::string &deviceId, const std::string &extra); +}; + +class AuthSrcManager : public AuthManager { +public: + // 各类事件触发的函数实现(继承) + int32_t OnUserOperation(int32_t action, const std::string ¶ms); + 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; +private: + +}; + +class AuthSinkManager : public AuthManager { +public: + // 各类事件触发的函数实现(继承) + int32_t OnUserOperation(int32_t action, const std::string ¶ms); + 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; +private: + +}; + +} // 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..a146b51fa6485aa0090cb9f7ad9f23890e9da1d6 --- /dev/null +++ b/services/implementation/include/authentication_v2/dm_auth_context.h @@ -0,0 +1,225 @@ +/* + * 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码认证类型 +typedef enum { + AUTH_TYPE_PIN_SHOW = 0, // 弹PIN码 + AUTH_TYPE_PIN_ULTRASONIC, // 超声PIN码 + AUTH_TYPE_PIN_IMPORT, // 导入PIN码 + AUTH_TYPE_IMPORT_AUTH_CODE, // 导入认证码 +} DmAuthType; + +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; // Q: 旧协议有用到addr,新设计没有,需要确认 + int32_t userId; + std::string userIdHash; + std::string accountId; + std::string accountIdHash; + uint64_t tokenId; + std::string tokenIdHash; + std::string token; // Q: 旧协议有用到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; // 表示服务为前台还是后台,业务透传,只保存 + bool isAuthed; + bool isOnline; + std::string dmVersion; // 版本 5.1.0 + std::string aclList; //可信关系列表,用于数据老化 KV格式 + std::string credentialInfos; //凭据信息(点对点,同账号,..) 只保存凭据类型 kv结构 + std::string extraInfo; //可扩展字段,kv结构 +}; + +struct DmAuthContext { + bool isOnline; // 是否上线 + DmMessageType msgType; // 报文类型,枚举MsgType + int32_t sessionId; // 总线传输会话ID + int64_t requestId; // hichain认证ID + UiAction authResult; // 授权结果(使用0、1、6,即单次,取消和始终信任,enum UiAction) + DmAuthType authType; // 认证方式,弹pin码、超声pin码、导入pin码 + int32_t authFailTimes{0}; // 认证失败次数,查过3次结束认证 + int32_t pinCode; // 保存业务导入的pin码 + int32_t connDelayCloseTime; // 链路延迟释放时间, 授权结束后不自动断链(有业务需要使用)保留字段 + int32_t reason; // 本端失败的原因 + int32_t reply; // 对端回复的结果 引用common/include/dm_constants.h,有新的错误码可新增 + 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 isAppCredentailVerified = false; // 标识用户凭据是否认证 + bool hmlEnable160M = false; + std::string pkgName; // 业务传入的标识,业务自定义,有被仿冒的风险 + 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; // 对端目标的信息 + bool isAppCredentialVerified; // 应用级凭据是否认证 + DmAccess accesser; + DmAccess 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 importPkgName = ""; + std::string importAuthCode = ""; + std::map> authenticationMap; + PeerTargetId peerTargetId; + bool fallBackToInputPin{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); + + // 设置扩展字段,key-value格式 + template + int32_t SetContextExtra(const std::string &key, const T &value) + { + nlohmann::json jsonExtra = nlohmann::json::parse(extraInfo); + if (jsonExtra.is_discarded()) { + return ERR_DM_FAILED; + } + + jsonExtra[key] = value; + extraInfo = SafetyDump(jsonExtra); + return DM_OK; + } + + // 获取扩展字段中key对应的value + template + int32_t GetFromContextExtra(const std::string &key, T &value) + { + nlohmann::json jsonExtra = nlohmann::json::parse(extraInfo); + if (jsonExtra.is_discarded()) { + return ERR_DM_FAILED; + } + value = jsonExtra[key].get(); + return DM_OK; + } +}; + +} // namespace DistributedHardware +} // namespace OHOS +#endif // OHOS_DM_AUTH_CONTEXT_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..8271e424a5586f9f70f445bcd402ca8d58409b34 --- /dev/null +++ b/services/implementation/include/authentication_v2/dm_auth_message_processor.h @@ -0,0 +1,227 @@ +/* + * 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_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_ON_TRANSMIT_DATA = "onTransmitData"; // onTransmitData接口返回信息 + +// 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 = "credentialOwner"; +constexpr const char *DM_AUTH_CREDENTIAL_OWNER = "DM"; // 凭据拥有者 +constexpr const char *DM_TAG_TOKEN_ID = "tokenId"; +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_PKG_NAME = "pkgName"; +constexpr const char *DM_TAG_DMVERSION = "dmVersion"; +constexpr const char *DM_TAG_ACCESS = "dmAccess"; +constexpr const char *DM_TAG_PROXY = "proxy"; +constexpr const char *DM_TAG_ACL_CHECKSUM = "aclCheckSum"; +constexpr const char *DM_TAG_SERVICEINFO = "serviceInfo"; +constexpr const char *DM_TAG_APPSKID = "accesserAppSKId"; +constexpr const char *DM_TAG_USERSKID = "accesserUserSKId"; +constexpr const char *DM_TAG_APPSK_TIMESTAMP = "accesserAppSKTimeStamp"; +constexpr const char *DM_TAG_USERSK_TIMESTAMP = "accesserUserSKTimeStamp"; +constexpr const char *DM_TAG_SYNC = "syncMessage"; +constexpr const char *DM_TAG_COMPRESS_ORI_LEN = "compressOriLen"; +constexpr const char *DM_TAG_COMPRESS = "compressMsg"; + +constexpr const int32_t DM_HASH_LEN = 32; + +// 报文类型 +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, +}; + +// 用于同步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) +}; + +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) +}; + +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); + + // 解析透传ON_TRANSMIT字段 + std::string GetTransmitFromContext(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); +private: + // 内部各类报文的实现 + + // 用于组装syncMsg中的加密部分 + int32_t EncryptSyncMessage(std::shared_ptr &context, std::vector aclList, + DmAccess &accessSide, std::string &encSyncMsg); + int32_t ParseAuthStartMessgae(nlohmann::json &jsonObject, std::shared_ptr &context); + + // 解析 80报文 + void 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报文onTransmitData返回的数据,存在contextd->extra中 + int32_t ParseMessageOnTransmit(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); + + // 创建 80报文 + void CreateNegotiateMessage(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); + 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..3719fad2f9dd35d0fa82281865dad7291760a882 --- /dev/null +++ b/services/implementation/include/authentication_v2/dm_auth_state.h @@ -0,0 +1,279 @@ +/* + * 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_state.h" +#include "dm_auth_context.h" + +namespace OHOS { +namespace DistributedHardware { + +// 状态类型 +enum class DmAuthStateType { + AUTH_IDLE_STATE = 0, // 设备初始化时 + // source端的状态 + AUTH_SRC_START_STATE, // 用户触发BindTarget + AUTH_SRC_NEGOTIATE_STATE, // 收到软总线回调函数OnSessionOpened,发送80报文 + AUTH_SRC_CONFIRM_STATE, // 收到90授权结果报文,发送100报文 + AUTH_SRC_PIN_AUTH_START_STATE, // 收到110授权结果报文,发送120报文 + AUTH_SRC_PIN_AUTH_MSG_NEGOTIATE_STATE, // 收到130认证PIN结果报文,发送121报文 + AUTH_SRC_PIN_AUTH_DONE_STATE, // 收到131认证PIN结果报文,调用processData + AUTH_SRC_CREDENTIAL_EXCHANGE_STATE, // 触发Onfinish回调事件,发送140报文 + AUTH_SRC_CREDENTIAL_AUTH_START_STATE, // 收到150加密报文,发送160报文 + AUTH_SRC_CREDENTIAL_AUTH_NEGOTIATE_STATE, // 收到170凭据认证报文,发送161报文 + AUTH_SRC_CREDENTIAL_AUTH_DONE_STATE, // 收到171凭据认证报文 + AUTH_SRC_DATA_SYNC_STATE, // 触发Onfinish回调事件,发送180报文 + AUTH_SRC_FINISH_STATE, // 收到190报文,发送200报文 + + // sink端的状态 + AUTH_SINK_START_STATE = 50, // 总线触发OnSessionOpened + AUTH_SINK_NEGOTIATE_STATE, // 收到80可信关系协商报文,发送90报文 + AUTH_SINK_CONFIRM_STATE, // 收到100用户授权报文,发送110报文 + AUTH_SINK_PIN_AUTH_START_STATE, // 收到120认证PIN报文,发送130报文 + AUTH_SINK_PIN_AUTH_MSG_NEGOTIATE_STATE, // 收到121认证PIN报文,发送131报文 + AUTH_SINK_PIN_AUTH_DONE_STATE, // 触发Onfinish回调事件 + AUTH_SINK_CREDENTIAL_EXCHANGE_STATE, // 收到140加密报文,发送150报文 + AUTH_SINK_CREDENTIAL_AUTH_START_STATE, // 收到160凭证认证报文,发送170报文 + AUTH_SINK_CREDENTIAL_AUTH_NEGOTIATE_STATE, // 收到161凭据协商报文 + AUTH_SINK_CREDENTIAL_AUTH_DONE_STATE, // 触发Onfinish回调事件 + AUTH_SINK_DATA_SYNC_STATE, // 收到180同步报文,发送190报文 + AUTH_SINK_FINISH_STATE, // 收到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动作 + 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; +}; + +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 GetAuthType(std::shared_ptr context); // 从DP配置读取授权类型 + int32_t ShowConfigDialog(std::shared_ptr context); // 提示用户授权对话框 + int64_t GenRequestId(std::shared_ptr context); // 生成HiChain请求ID +}; + +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 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 { + virtual ~AuthSrcCredentialAuthNegotiateState() {}; + DmAuthStateType GetStateType() override; + int32_t Action(std::shared_ptr context) override; // 执行状态对应的action动作 +}; + +// 收到171凭据认证报文 发送160/180 报文 +class AuthSrcCredentialAuthDoneState : public DmAuthState { + virtual ~AuthSrcCredentialAuthDoneState() {}; + DmAuthStateType GetStateType() override; + int32_t Action(std::shared_ptr context) override; // 执行状态对应的action动作 +}; + +// 收到160凭证认证报文 发送170报文 +class AuthSinkCredentialAuthStartState : public DmAuthState { + virtual ~AuthSinkCredentialAuthStartState() {}; + DmAuthStateType GetStateType() override; + int32_t Action(std::shared_ptr context) override; // 执行状态对应的action动作 +}; + +// 收到161凭据协商报文 并回复171报文 +class AuthSinkCredentialAuthNegotiateState : public DmAuthState { + 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); + int32_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); +}; + +} // 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..e793c4ac83c2bd93a170035be18c14a07abb2b34 --- /dev/null +++ b/services/implementation/include/authentication_v2/dm_auth_state_machine.h @@ -0,0 +1,96 @@ +/* + * 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_; + + // 实际事件 + DmEventType actualEventType_; + std::thread thread_; + std::atomic running_; + std::queue> statesQueue_; + // 同步原语 + std::mutex mutex_; + std::condition_variable stateCv_; + std::condition_variable eventCv_; +}; + +} // 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 dc02f7b90167245501d8de12afd108913337ca62..487018a4ce9d3cf6084f1e6480d9f8b2304742ba 100644 --- a/services/implementation/include/cryptomgr/crypto_mgr.h +++ b/services/implementation/include/cryptomgr/crypto_mgr.h @@ -51,6 +51,7 @@ public: int32_t DecryptMessage(const std::string &inputMsg, std::string &outputMsg); int32_t SaveSessionKey(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 cc92df1fc4caae23c946e6570ff00832f28e15b1..e2291f10ee553b7e754305773e55309b2e182139 100644 --- a/services/implementation/include/dependency/hichain/hichain_auth_connector.h +++ b/services/implementation/include/dependency/hichain/hichain_auth_connector.h @@ -54,10 +54,27 @@ 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); + private: void FreeJsonString(char *jsonStr); 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..d8ecfedc2e617cdb9647064d607b4aca5c6a4696 --- /dev/null +++ b/services/implementation/src/authentication_v2/auth_manager.cpp @@ -0,0 +1,788 @@ +/* + * 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" +#undef LOG_TAG +#define LOG_TAG "DHDM_V2" + +namespace OHOS { +namespace DistributedHardware { +namespace { + +const int32_t MAX_AUTH_FAIL_TIMES = 3; + +// TODO: 黄蓝区未同步,无CONN_SESSION_TYPE_HML符号 +bool IsHmlSessionType(std::string sessionType) +{ + return false; + // return sessionType == CONN_SESSION_TYPE_HML; +} + +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 + +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_IMPORT_AUTH_CODE] = nullptr; + context_->accesser.dmVersion = DM_VERSION_5_1_0; + context_->accessee.dmVersion = DM_VERSION_5_1_0; +} + +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; + } + authType = std::atoi(authTypeStr.c_str()); + return DM_OK; +} + +// 保存秘钥 +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); +} + +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 &pkgName) +{ + if (context_->importAuthCode.empty() || context_->importPkgName.empty()) { + LOGE("AuthManager::IsAuthCodeReady, auth code not ready."); + return false; + } + if (pkgName != context_->importPkgName) { + LOGE("IsAuthCodeReady failed, pkgName not supported."); + return false; + } + return true; +} + +int32_t AuthManager::CheckAuthParamVaild(const std::string &pkgName, 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 (pkgName.empty() || deviceId.empty()) { + LOGE("AuthManager::CheckAuthParamVaild failed, pkgName is %{public}s, deviceId is %{public}s, extra is" + "%{public}s.", pkgName.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(pkgName))) { + 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; + } + + // 由于旧协议中没怎么用,新协议的设计也没有该字段 + // 故废弃了targetPkgName + + // 填充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_->pkgName; + } + LOGI("ParseJsonObject accessee bundleName = %{public}s", context_->accessee.bundleName.c_str()); + } else { + context_->accessee.bundleName = context_->pkgName; + } + + 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; +} + +void AuthManager::GetAuthParam(const std::string &pkgName, 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 = static_cast(localDeviceId); + context_->pkgName = pkgName; + context_->pkgLabel = GetBundleLable(pkgName); + context_->authType = (DmAuthType)authType; + context_->accesser.deviceName = context_->softbusConnector->GetLocalDeviceName(); + context_->accesser.deviceType = context_->softbusConnector->GetLocalDeviceTypeId(); + context_->accesser.deviceId = localUdid; + context_->accesser.dmVersion = DM_VERSION_5_1_0; + uint32_t tokenId = 0 ; + MultipleUserConnector::GetTokenIdAndForegroundUserId(tokenId, context_->accesser.userId); + context_->accesser.tokenId = static_cast(tokenId); + 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 &pkgName, 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_SHOW) { + 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(pkgName, authType, deviceId, extra); + context_->authStateMachine = std::make_shared(context_); + LOGI("AuthManager::AuthenticateDevice complete"); + + return; +} + +int32_t AuthManager::AuthenticateDevice(const std::string &pkgName, 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 = pkgName; + context_->processInfo.userId = userId; + int32_t ret = CheckAuthParamVaild(pkgName, 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(pkgName, authType, deviceId, extra); + return DM_OK; +} + +int32_t AuthManager::BindTarget(const std::string &pkgName, const PeerTargetId &targetId, + const std::map &bindParam) +{ + 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 (pkgName.empty()) { + LOGE("AuthManager::BindTarget failed, pkgName 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; + 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(pkgName, authType, deviceId, ParseExtraFromMap(bindParam)); + } else if (!targetId.deviceId.empty()) { + return AuthenticateDevice(pkgName, authType, targetId.deviceId, ParseExtraFromMap(bindParam)); + } else { + LOGE("AuthManager::BindTarget failed, targetId is error."); + return ERR_DM_INPUT_PARA_INVALID; + } +} + +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) { + context_->reply = USER_OPERATION_TYPE_CANCEL_AUTH; + } + context_->authStateMachine->NotifyEventFinish(DmEventType::ON_USER_OPERATION); + break; + case 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: + 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; +} + +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: + context_->reason = ERR_DM_BIND_USER_CANCEL_ERROR; + context_->authStateMachine->NotifyEventFinish(DmEventType::ON_FAIL); + break; + case USER_OPERATION_TYPE_DONE_PINCODE_INPUT: + context_->pinCode = std::atoi(params.c_str()); + 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."); + if (context_->authType == DmAuthType::AUTH_TYPE_PIN_SHOW) { + context_->authFailTimes++; + } else if (!context_->fallBackToInputPin) { + LOGI("AuthSrcManager::AuthDeviceError fallback to input pin."); + context_->fallBackToInputPin = true; + } else { + context_->authFailTimes++; + } + + // 失败 MAX_AUTH_FAIL_TIMES 次后,走认证失败 ON_FAIL + if (context_->authFailTimes >= MAX_AUTH_FAIL_TIMES) { + 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 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) { + LOGI("AuthSinkManager::AuthDeviceError Auth pin err."); + if (context_->authType == DmAuthType::AUTH_TYPE_PIN_SHOW) { + context_->authFailTimes++; + } else if (!context_->fallBackToInputPin) { + LOGI("AuthSinkManager::AuthDeviceError fallback to input pin."); + context_->fallBackToInputPin = 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_->authFailTimes++; + } + // 失败 MAX_AUTH_FAIL_TIMES 次后,走认证失败 ON_FAIL + if (context_->authFailTimes >= MAX_AUTH_FAIL_TIMES) { + 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 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); +} + +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; +} + +} // 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..0d987f5711ad651e49192ce3cd282cf024751e87 --- /dev/null +++ b/services/implementation/src/authentication_v2/auth_stages/auth_acl.cpp @@ -0,0 +1,34 @@ +/* + * 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" + +namespace OHOS { +namespace DistributedHardware { + +/* +数据同步,ACL老化与保存(180、190和200报文处理) +source端状态: +AuthSrcDataSyncState, // 触发Onfinish回调事件,发送180报文 +AuthSrcFinishState, // 收到190报文,发送200报文 + +sink端状态: +AuthSinkDataSyncState, // 收到180同步报文,发送190报文 +AuthSinkFinishState, // 收到200结束报文 + +*/ + +} // 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..de29f1f1814392a6d2fdd825c651d1b9539ab8ea --- /dev/null +++ b/services/implementation/src/authentication_v2/auth_stages/auth_confirm.cpp @@ -0,0 +1,226 @@ +/* + * 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" +#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"; + +/* +用户授权(100和110报文处理) +source端状态: +AuthSrcConfirmState, // 收到90授权结果报文,发送100报文 + +sink端状态: +AuthSinkConfirmState, // 收到100用户授权报文,发送110报文 +*/ + +DmAuthStateType AuthSrcConfirmState::GetStateType() +{ + return DmAuthStateType::AUTH_SRC_CONFIRM_STATE; +} + +int32_t AuthSrcConfirmState::Action(std::shared_ptr context) +{ + LOGI("AuthSrcConfirmState::Action start"); + + LOGI("AuthSrcConfirmState::Action ok"); + return DM_OK; +} + +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_APP_OPERATION] = context->appOperation; + jsonObj[TAG_CUSTOM_DESCRIPTION] = context->customData; + jsonObj[TAG_LOCAL_DEVICE_TYPE] = context->accesser.deviceType; + jsonObj[TAG_REQUESTER] = context->accesser.deviceName; + jsonObj[TAG_HOST_PKGLABEL] = context->pkgName; + + const std::string params = SafetyDump(jsonObj); + DmDialogManager::GetInstance().ShowConfirmDialog(params); + + LOGI("AuthSinkConfirmState::ShowConfigDialog end"); + return DM_OK; +} +#if 0 +int32_t AuthSinkConfirmState::GetAuthType(std::shared_ptr context) +{ + // DP 接口 查询ServiceInfoProfile + std::vector serviceInfos; + DistributedDeviceProfile::ServiceInfoUniqueKey key(context->accessee.deviceId, + context->accessee.userId, context->accessee.tokenId, context->accessee.serviceId); + if (DeviceProfileConnector::GetInstance().GetServiceInfoProfileListByTokenId(key, serviceInfos) != DM_OK) { + // 获取不到走PIN认证方案 + context->authType = DmAuthType::AUTH_TYPE_PIN_SHOW; + 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::GetAuthType 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) { + context->authType = DmAuthType::AUTH_TYPE_PIN_SHOW; // 三态框 + 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 + context->authType = DmAuthType::AUTH_TYPE_PIN_ULTRASONIC; + return DM_OK; + } else if (pinExchangeType == DistributedDeviceProfile::NUM_3) { // 导入PIN + context->authType = DmAuthType::AUTH_TYPE_PIN_IMPORT; + // 读取PIN码 + std::string pinCode = srvInfo.GetPinCode(); + context->pinCode = std::stoi(pinCode); + return DM_OK; + } + } + + LOGE("AuthSinkConfirmState::GetAuthType authType not support"); + return STOP_BIND; +} +#else +int32_t AuthSinkConfirmState::GetAuthType(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) +{ + LOGI("AuthSinkConfirmState::Action start"); + // 停止授权报文计时 + context->timer->DeleteTimer(std::string(CONFIRM_TIMEOUT_TASK)); + context->requestId = GenRequestId(context); + auto ret = GetAuthType(context); + if (ret != DM_OK) { + return ret; + } + + if (context->authType == DmAuthType::AUTH_TYPE_PIN_SHOW) { // 三态框 + LOGI("AuthSinkConfirmState::Action AUTH_TYPE_PIN_SHOW "); + // 拉起授权确认页面 + 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_PIN_IMPORT) { // 导入PIN + LOGI("AuthSinkConfirmState::Action AUTH_TYPE_PIN_IMPORT"); + // 发送110报文 + context->authMessageProcessor->CreateAndSendMsg(MSG_TYPE_RESP_USER_CONFIRM, context); + } + } + LOGI("AuthSinkConfirmState::Action ok"); + return DM_OK; +} + +} // 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..bab2b3862ee293e5e95b1f658641921d9ebe39a1 --- /dev/null +++ b/services/implementation/src/authentication_v2/auth_stages/auth_credential.cpp @@ -0,0 +1,520 @@ +/* + * 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" + +namespace OHOS { +namespace DistributedHardware { + +// 从context中提取transmit data,使用SK解密,并透传给HICHAIN +// 如果ontransmit事件,在对应回调解析并保存在context +// 如果onsessionkeyreturned事件,在对应回调解析并保存在cryptomgr +static int32_t AuthCredentialTransmitDecryptProcess(std::shared_ptr context, DmEventType event) +{ + std::string transmitStr; + if (context->GetFromContextExtra(DM_TAG_ON_TRANSMIT_DATA, transmitStr) != DM_OK) { + LOGE("DmAuthMessageProcessor::CreateMessageReqCredAuthStart failed, get onTransmitData from extra failed."); + return ERR_DM_FAILED; + } + + // 透传给hichain + int32_t ret = context->hiChainAuthConnector->ProcessCredData(context->requestId, transmitStr); + 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 + std::string transmitStr; + transmitStr = context->authMessageProcessor->GetTransmitFromContext(context); + if (transmitStr.empty()) { + LOGE("AuthCredentialTransmitSend: GetTransmitFromContext from HICHAIN 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->isAppCredentailVerified == false) { + context->isAppCredentailVerified = 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->accessee.userCredentialId, std::string("")); + if (ret != DM_OK) { + LOGE("AuthSrcCredentialAuthDoneState::Action Hichain auth credentail failed"); + return ret; + } + } 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) +{ + // 解密并透传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报文 +// 通过isAppCredentailVerified关键词区分首次认证、非首次认证 +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->isAppCredentailVerified == 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->isAppCredentailVerified = 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) +{ + // 参数校验 + 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; + 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] = authContext->GetDeviceId(DM_AUTH_REMOTE_SIDE); // 对端userId + } + 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_ED25519; // ED25519; + jsonObj[DM_TAG_PROOF_TYPE] = DM_AUTH_CREDENTIAL_PROOF_PSK; // PSK + if (method == DM_AUTH_CREDENTIAL_ADD_METHOD_IMPORT) { // 导入公钥 16进制字符串 + std::stringstream ss; + ss.str(""); + std::string publicKey = authContext->GetPublicKey(DM_AUTH_REMOTE_SIDE, authorizedScope); + for (auto &c : publicKey) { + ss << std::hex << std::setw(2) << std::setfill('0') << c; // 2 输出填充2字节 + } + jsonObj[DM_TAG_KEY_VALUE] = ss.str(); + } + jsonObj[DM_TAG_AUTHORIZED_SCOPE] = authorizedScope; // 用户级或者应用级 + if (authorizedScope == DM_AUTH_SCOPE_APP) { + jsonObj[DM_TAG_AUTHRIZED_APP_LIST] = {authContext->accesser.tokenId, authContext->accessee.tokenId}; + } + jsonObj[DM_TAG_CREDENTIAL_OWNER] = DM_AUTH_CREDENTIAL_OWNER; // 调用方包名DM模块 + + return SafetyDump(jsonObj); +} + +// 生成凭据Id和公钥 +// authorizedScope 用户级还是应用级 +// authContext 上下文 +int32_t AuthCredentialAgreeState::GenerateCredIdAndPublicKey(DmAuthScope authorizedScope, + std::shared_ptr &authContext) +{ + 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); + + return DM_OK; +} + +// 协商凭据得到协商凭据Id +// authorizedScope 设备级还是应用级 +// authContext 上下文 +int32_t AuthCredentialAgreeState::AgreeCredential(DmAuthScope authorizedScope, + std::shared_ptr &authContext) +{ + 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); + + return DM_OK; +} + +DmAuthStateType AuthSrcCredentialExchangeState::GetStateType() +{ + return DmAuthStateType::AUTH_SRC_CREDENTIAL_EXCHANGE_STATE; +} + +int32_t AuthSrcCredentialExchangeState::Action(std::shared_ptr context) +{ + 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); + 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) +{ + 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); + 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) +{ + 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->accessee.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); + 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..cae47b95fda8f3ee472bedd08c6be1e8f33f14f5 --- /dev/null +++ b/services/implementation/src/authentication_v2/auth_stages/auth_negotiate.cpp @@ -0,0 +1,361 @@ +/* + * 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 "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 "device_auth.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_constants.h" +#include "dm_anonymous.h" +#include "dm_auth_context.h" +#include "auth_manager.h" +#include "dm_auth_state.h" + +namespace OHOS { +namespace DistributedHardware { + +int32_t AuthSrcNegotiateStateMachine::Action(std::shared_ptr context) +{ + LOGI("AuthSrcNegotiateStateMachine::Action sessionId %{public}d.", context->sessionId); + + // Q:为什么会让对端deviceId等于自己的deviceId? + context->accessee.deviceId = context->accesser.deviceId; + context->reply = ERR_DM_AUTH_REJECT; + // authType、deviceId已在BindTarget赋值 + // accountGroupIdHash已废弃,无组的概念 + // hostPkgName已废弃,直接取context的pkgName,已在初始化时赋值 + context->accessee.bundleName = context->accesser.bundleName; // 初始化时已赋值,这里是不是存在冲突? + // context的accesser和accessee的bundleName已经覆盖peerBundleName + // pkgLabel已赋值 + // tokenId已不在80报文中传输 + // bindLevel已在BindTarget赋值 + // bindType已在BindTarget赋值 + // isOnline已在BindTarget赋值 + // authed替换为isAuthed,已在BindTarget赋值 + // 为什么之前DmVersion传空? + context->accessee.dmVersion = ""; + // accountId不再在80报文中传输 + // userId不再在80报文中传输 + // isIdenticalAccount不再在80报文中传输 + // edition不再在80报文中传输 + // remoteDeviceName + + // 计算哈希值 + 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; +} + +int32_t AuthSinkNegotiateStateMachine::RespQueryAcceseeIds(std::shared_ptr context) +{ + int32_t ret; + + char localDeviceId[DEVICE_UUID_LENGTH] = {0}; + GetDevUdid(localDeviceId, DEVICE_UUID_LENGTH); + context->accessee.deviceId = static_cast(localDeviceId); + + if (context->accesser.tokenIdHash.empty()) { + // 单用户:特征为accesser未传输tokenIdHash + // 适用于:FA-FA、SA-SA + // 当前无FA-FA_service、SA-SA_service、FA-device(bindTarget暂无peerType) + std::vector userVec; + + ret = MultipleUserConnector::GetForegroundUserIds(userVec); + if (ret != DM_OK) { + LOGE("RespQueryTokenId: GetForegroundUserIds failed, ret: %{public}d", ret); + return ret; + } + + context->accessee.userId = MultipleUserConnector::GetFirstForegroundUserId(); + context->accessee.accountId = MultipleUserConnector:: + GetOhosAccountIdByUserId(context->accessee.userId); + + int64_t tokenId = 0; + ret = AppManager::GetInstance().GetHapTokenIdByName(context->accessee.userId, + context->accessee.bundleName, 0, tokenId); + if (ret != DM_OK) { + LOGI("RespQueryTokenId: get tokenId by bundleName failed %{public}s", + GetAnonyString(context->accessee.bundleName).c_str()); + return ret; + } + context->accessee.tokenId = tokenId; + } else { + // 多用户:特征为accesser传输了tokenId + // 适用于:FA-FA多用户 + // Security::AccessToken::HapTokenInfo tokenInfo; + // TODO: tokenId涉及安全问题,暂无法在80报文中传输 + // ret = AccessTokenKit::GetHapTokenInfo(authResponseContext_->remoteTokenId, tokenInfo); + // if (ret != DM_OK) { + // LOGE("RespQueryTokenId: GetHapTokenInfo failed."); + // return ret; + // } + // authResponseContext_->localUserId = tokenInfo.userID; + // authResponseContext_->localAccountId = MultipleUserConnector:: + // GetOhosAccountIdByUserId(authResponseContext_->localUserId); + // if (ret != DM_OK) { + // LOGI("RespQueryTokenId: get tokenId by bundleName failed %{public}s", + // GetAnonyString(authResponseContext_->bundleName).c_str()); + // return ret; + // } + + // 由于前面无法传输tokenId,暂时中断 + return ERR_DM_FAILED; + } + + return ret; +} + +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; +} + +int32_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["credType"] == ACCOUNT_RELATED && credInfo["authorizedScope"] == SCOPE_USER) { + return DM_IDENTICAL_ACCOUNT; + } + } else { + if (credInfo["credType"] == ACCOUNT_ACROSS && credInfo["authorizedScope"] == SCOPE_USER) { + return DM_ACROSS_ACCOUNT; + } + if (credInfo["credType"] == ACCOUNT_UNRELATED && credInfo["authorizedScope"] == SCOPE_APP && + HaveSameTokenId(context, credInfo["authorizedAppList"]) == 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与凭据匹配,匹配不上的则无信息) + */ +int32_t AuthSinkNegotiateStateMachine::GetAuthCredentialInfo(std::shared_ptr context) +{ + int32_t ret; + nlohmann::json queryParams; + nlohmann::json queryResult; + + // 1. 获取所有凭据 + queryParams["deviceIdHash"] = context->accesser.deviceIdHash; + queryParams["userIdHash"] = context->accesser.userIdHash; + // 2/27会上讨论,以下字段不需要传输,只传id相关即可 + // queryParams["subject"] = 2; // 2: 配件 + // queryParams["keyFormat"] = 2; // 2: 非对称密钥公钥 + // queryParams["algorithmType"] = 4; // 4- ED25519 + // queryParams["proofType"] = 1; // 1: PSK + // queryParams["credentialOwner"] = "DM"; + 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; + } + + // 2. 获取所有ACL + std::vector profiles = + DeviceProfileConnector::GetInstance().GetAccessControlProfile(); + bool isAclActive = false; + for (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; + } + + // 确认凭据类型 + int32_t credType = GetCredentialType(context, queryResult[credId]); + if (credType == DM_INVALIED_BINDTYPE) { + continue; + } + queryResult[credId]["credType"] = credType; + + // 确认是否有可信关系 + 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; + for (auto& [key, value] : queryResult.items()) { + if (value.find("isAclActive") == value.end() || value["isAclActive"] == false) { + invalidCredIds.push_back(key); + } + } + + 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 tokenId."); + context->reply = ERR_DM_UNSUPPORTED_AUTH_TYPE; + return ERR_DM_FAILED; + } + + // 检查accesser_deviceId是否上线 + // Q: 80报文未传输accesser.deviceId,无法校验是否上线 + // context->accesser.isOnline = context->softbusConnector->CheckIsOnline(context->accesser.deviceId); + + // 获取凭据信息 + ret = GetAuthCredentialInfo(context); + if (ret != DM_OK) { + LOGE("DmAuthManager::ProcRespNegotiate5_1_0 fail to get credential."); + context->reply = ERR_DM_UNSUPPORTED_AUTH_TYPE; + return ERR_DM_FAILED; + } + + // 状态跳转在100报文中处理 + return DM_OK; +} + +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(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 = static_cast(localDeviceId); + + // 解析message时,accesser.deviceId已赋值 + // remoteDeviceId_ = authResponseContext_->localDeviceId; + context->accessee.networkId = context->softbusConnector->GetLocalDeviceNetworkId(); + context->accessee.deviceName = context->softbusConnector->GetLocalDeviceName(); + if (CompareVersion(context->accesser.dmVersion, std::string(DM_VERSION_5_1_0)) == false) { + LOGE("AuthSinkNegotiateStateMachine::Action incompatible version compare to 5.1.0"); + 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; + } + 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..113a129cc56566d2e9803f8e4b5175af8fe00e97 --- /dev/null +++ b/services/implementation/src/authentication_v2/auth_stages/auth_pin_auth.cpp @@ -0,0 +1,378 @@ +/* + * 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 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 = 0; // 没获取到返回默认0, 失败后会进入用户输入PIN流程 +#if 0 + std::vector serviceInfos; + DistributedDeviceProfile::ServiceInfoUniqueKey key(context->accesser.deviceId, context->accesser.userId, + context->accesser.tokenId, context->accesser.serviceId); + if (DeviceProfileConnector::GetInstance().GetServiceInfoProfileListByTokenId(key, serviceInfos) == 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()); + } + } +#endif + return pinCode; +} + +int32_t AuthSrcPinAuthStartState::GetPinCode(std::shared_ptr context) +{ + LOGI("AuthSrcPinAuthStartState::GetPinCode start"); + if (context->authFailTimes == 0) { + if (context->authType == DmAuthType::AUTH_TYPE_PIN_SHOW || context->fallBackToInputPin) { + // 拉起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->authResult != 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->AuthDevice(context->pinCode, osAccountId, + context->accessee.deviceId, context->requestId); + 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"); + // 首次进入停止计时器 + if (context->authFailTimes == 0 && !context->fallBackToInputPin) { + context->timer->DeleteTimer(std::string(CONFIRM_TIMEOUT_TASK)); + } + + // 获取PIN码 + auto ret = GetPinCode(context); + if (ret != DM_OK) { + LOGE("AuthSrcPinAuthStartState::Action GetPinCode err"); + return ret; + } + + // 做认证 发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"); + + 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; + } + + std::string onTransmitData; + if (context->GetFromContextExtra(DM_TAG_DATA, onTransmitData) != DM_OK) { + LOGE("AuthSrcPinAuthDoneState::Action error, get onTransmitData From extra failed."); + return ERR_DM_FAILED; + } + + // 处理凭据数据 + 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; + } + } + + // 阻塞等待ON_FINISH事件到来 + ret = context->authStateMachine->WaitExpectEvent(ON_FINISH); + if (ret == ON_FINISH) { + 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; +} + +} // 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..58f7a24b3aa6f05d10d3882393bbbd213934e0f2 --- /dev/null +++ b/services/implementation/src/authentication_v2/dm_auth_context.cpp @@ -0,0 +1,171 @@ +/* + * 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" + +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 && DM_AUTH_SCOPE_USER != 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; +} +} // 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..f51d01be2dd1c1fb3185328472a8393023bc50fd --- /dev/null +++ b/services/implementation/src/authentication_v2/dm_auth_message_processor.cpp @@ -0,0 +1,701 @@ +/* + * 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 "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_context.h" +#include "dm_auth_state_machine.h" +#include "dm_crypto.h" + +namespace OHOS { +namespace DistributedHardware { + +constexpr const char* TAG_REPLY = "reply"; +constexpr const char* TAG_DATA = "data"; + +// 保存秘钥 +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; + } + uint8_t* sessionKey = nullptr; + uint32_t skLen = cryptoMgr_->GetSessionKey(sessionKey); + return DeviceProfileConnector::GetInstance().PutSessionKey(sessionKey, skLen, skId); +} + +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); + switch (msgType) { + 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 + case MSG_TYPE_RESP_PIN_AUTH_MSG_NEGOTIATE: + return ParseMessageNegotiateTransmit(jsonObject, context); + case MSG_TYPE_REQ_CREDENTIAL_EXCHANGE: + return ParseMessageReqCredExchange(jsonObject, context); + case MSG_TYPE_RESP_CREDENTIAL_EXCHANGE: + return ParseMessageRspCredExchange(jsonObject, context); + default: + break; + } + return ERR_DM_FAILED; +} + +int32_t DmAuthMessageProcessor::ParseMessageNegotiateTransmit(const 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; + } + // 解密 + std::string plainText; + int32_t ret = cryptoMgr_->DecryptMessage(jsonObject[DM_TAG_DATA], plainText); + if (ret != DM_OK) { + LOGE("DmAuthMessageProcessor::ParseAuthStartMessgae DecryptMessage failed"); + return ret; + } + + nlohmann::json jsonDecrptObj = plainText; + if (ParseMessageOnTransmit(jsonDecrptObj, context) != DM_OK) { + LOGE("DmAuthMessageProcessor::ParseAuthStartMessgae ParseMessageOnTransmit failed"); + return ERR_DM_FAILED; + } + return DM_OK; +} + +// 解析onTransmit返回的数据,保存到context->extra中 +int32_t DmAuthMessageProcessor::ParseMessageOnTransmit(const nlohmann::json &jsonObject, + std::shared_ptr context) +{ + if (jsonObject.is_discarded() || !IsString(jsonObject, DM_TAG_DATA)) { + LOGE("DmAuthMessageProcessor::ParseMessageOnTransmit failed, decodeRequestAuth jsonStr error"); + return ERR_DM_FAILED; + } + + context->SetContextExtra(DM_TAG_ON_TRANSMIT_DATA, jsonObject[DM_TAG_DATA].get()); + 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 + return DM_OK; +} + +// 解析150报文信息MSG_TYPE_RESP_CREDENTIAL_EXCHANGE,SRC端存放对方公钥,和协商凭据Id +int32_t DmAuthMessageProcessor::ParseMessageRspCredExchange(const nlohmann::json &jsonObject, + std::shared_ptr context) +{ + 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; + } + 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 + 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_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; + default: + LOGE("DmAuthMessageProcessor::CreateMessage msgType %{public}d error.", msgType); + break; + } + return SafetyDump(jsonObj); +} + +// 内部各类报文的实现 +int32_t DmAuthMessageProcessor::CreateCredentialNegotiateMessage(std::shared_ptr &context, nlohmann::json &jsonObject) +{ + std::string encryptMsg; + int32_t ret = cryptoMgr_->EncryptMessage(DmAuthMessageProcessor::GetTransmitFromContext(context), encryptMsg); // 临时SK加密 + if (ret != DM_OK) { + LOGE("DmAuthMessageProcessor::CreateSyncMessage encrypt failed"); + return ret; + } + jsonObject[DM_TAG_DATA] = encryptMsg; + return DM_OK; +} + + +// 创建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) +{ + 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; + cryptoMgr_->EncryptMessage(plainText, cipherText); + jsonObject[DM_TAG_DATA] = cipherText; +} + +// 创建160报文 +void DmAuthMessageProcessor::CreateMessageReqCredAuthStart(std::shared_ptr context, + nlohmann::json &jsonObject) +{ + std::string onTransmitData; + if (context->GetFromContextExtra(DM_TAG_ON_TRANSMIT_DATA, onTransmitData) != DM_OK) { + LOGE("DmAuthMessageProcessor::CreateMessageReqCredAuthStart failed, get onTransmitData from extra failed."); + return; + } + + nlohmann::json jsonData; + jsonData[DM_TAG_ON_TRANSMIT_DATA] = onTransmitData; + if (!context->isAppCredentialVerified) { // 应用级凭据认证 + jsonData[DM_TAG_APP_CREDENTIAL_ID] = context->accesser.appCredentialId; + } else if (!context->isOnline) { // 首次用户级凭据认证 + jsonData[DM_TAG_USER_CREDENTIAL_ID] = context->accesser.userCredentialId; + } + + std::string plainText = SafetyDump(jsonData); + std::string cipherText; + if (cryptoMgr_->EncryptMessage(plainText, cipherText) != DM_OK) { + LOGE("DmAuthMessageProcessor::CreateMessageReqCredAuthStart failed, encrypt data failed."); + return; + } + + jsonObject[DM_TAG_DATA] = cipherText; +} + +// 创建80报文 +void DmAuthMessageProcessor::CreateNegotiateMessage(std::shared_ptr context, nlohmann::json &jsonObject) +{ + // 目前未看到使用了cryptoAdapter_,删除 + jsonObject[TAG_DEVICE_VERSION] = context->accesser.dmVersion; + jsonObject[TAG_DEVICE_NAME] = context->accesser.deviceName; + + 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; + // 暂无serviceId的定义 + // tokenId、deviceId是否有安全问题?暂未传输 + + return; +} + +void DmAuthMessageProcessor::ParseNegotiateMessage(nlohmann::json &jsonObject, std::shared_ptr context) +{ + if (IsString(jsonObject, TAG_DEVICE_VERSION)) { + context->accesser.dmVersion = jsonObject[TAG_DEVICE_VERSION].get(); + } + if (IsString(jsonObject, TAG_DEVICE_NAME)) { + context->accesser.deviceName = jsonObject[TAG_DEVICE_NAME].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(); + } + + return; +} + +int32_t DmAuthMessageProcessor::ParseMessageRespAclNegotiate(const nlohmann::json &json, + std::shared_ptr context) +{ + // todo + return DM_OK; +} +int32_t DmAuthMessageProcessor::ParseMessageReqUserConfirm(const nlohmann::json &json, + std::shared_ptr context) +{ + // todo + context->authStateMachine->TransitionTo(std::make_shared()); + return DM_OK; +} +int32_t DmAuthMessageProcessor::ParseMessageRespUserConfirm(const nlohmann::json &json, + std::shared_ptr context) +{ + context->authType = static_cast(json[TAG_AUTH_TYPE].get()); + context->requestId = json[TAG_REQUEST_ID].get(); + if (context->authType == DmAuthType::AUTH_TYPE_PIN_SHOW) { + context->reply = json[TAG_REPLY].get(); + } + + context->authStateMachine->TransitionTo(std::make_shared()); + return DM_OK; +} +int32_t DmAuthMessageProcessor::ParseMessageReqPinAuthStart(const nlohmann::json &json, + std::shared_ptr context) +{ + context->transmitData = json[TAG_DATA].get(); + context->authStateMachine->TransitionTo(std::make_shared()); + return DM_OK; +} +int32_t DmAuthMessageProcessor::ParseMessageRespPinAuthStart(const nlohmann::json &json, + std::shared_ptr context) +{ + context->transmitData = json[TAG_DATA].get(); + context->authStateMachine->TransitionTo(std::make_shared()); + return DM_OK; +} +int32_t DmAuthMessageProcessor::ParseMessageReqPinAuthNegotiate(const nlohmann::json &json, + std::shared_ptr context) +{ + context->transmitData = json[TAG_DATA].get(); + context->authStateMachine->TransitionTo(std::make_shared()); + return DM_OK; +} + +void DmAuthMessageProcessor::CreateMessageReqUserConfirm(std::shared_ptr context, nlohmann::json &json) +{ + // todo +} + +void DmAuthMessageProcessor::CreateMessageRespUserConfirm(std::shared_ptr context, nlohmann::json &json) +{ + json[TAG_AUTH_TYPE] = context->authType; + json[TAG_REQUEST_ID] = context->requestId; + if (context->authType == DmAuthType::AUTH_TYPE_PIN_SHOW) { + json[TAG_REPLY] = context->reply; + } +} + +void DmAuthMessageProcessor::CreateMessageReqPinAuthStart(std::shared_ptr context, nlohmann::json &json) +{ + json[TAG_DATA] = context->transmitData; +} + +void DmAuthMessageProcessor::CreateMessageRespPinAuthStart(std::shared_ptr context, nlohmann::json &json) +{ + json[TAG_DATA] = context->transmitData; +} + +void DmAuthMessageProcessor::CreateMessageReqPinAuthNegotiate(std::shared_ptr context, + nlohmann::json &json) +{ + json[TAG_DATA] = context->transmitData; +} + +void DmAuthMessageProcessor::CreateMessageRespPinAuthNegotiate(std::shared_ptr context, + nlohmann::json &json) +{ + json[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; +} + +// 用于组装syncMsg中的加密部分 +int32_t DmAuthMessageProcessor::EncryptSyncMessage(std::shared_ptr &context, + std::vector aclList, 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_APPSKID]=std::to_string(context->appSessionKeyId); + syncMsgJson[DM_TAG_APPSK_TIMESTAMP]=std::to_string(context->appSkTimeStamp); + } else { // 首次认证 + accessToSync.sessionKeyId = context->userSessionKeyId; + accessToSync.skTimeStamp = context->userSkTimeStamp; + syncMsgJson[DM_TAG_APPSKID]=std::to_string(context->appSessionKeyId); + syncMsgJson[DM_TAG_USERSKID]=std::to_string(context->userSessionKeyId); + syncMsgJson[DM_TAG_APPSK_TIMESTAMP]=std::to_string(context->appSkTimeStamp); + syncMsgJson[DM_TAG_USERSK_TIMESTAMP]=std::to_string(context->userSkTimeStamp); + } + + nlohmann::json accessJsonObj = accessToSync; // 直接使用宏构造 access json + syncMsgJson[DM_TAG_DMVERSION] = accessSide.dmVersion; + syncMsgJson[DM_TAG_ACCESS] = accessJsonObj.dump(); // 接收端需要再拆一次json + syncMsgJson[DM_TAG_PROXY] = ""; // 预留字段 留空即可 + std::vector> aclHashList; + for (auto &item : aclList) { + uint8_t aclHash[DM_HASH_LEN] = {0}; + Crypto::DmGenerateStrHash(item.data(), item.size(), aclHash, DM_HASH_LEN, 0); + aclHashList.push_back(std::vector(aclHash, aclHash + DM_HASH_LEN)); + } + 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] = compressMsg; + // 加密整个字段 + return cryptoMgr_->EncryptMessage(plainJson.dump(), 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 = aclJsonObj.dump(); + if (aclStr.empty()) { + LOGE("DmAuthMessageProcessor::ACLToStr normalized acl failed"); + return ERR_DM_FAILED; + } + return DM_OK; +} +int32_t DmAuthMessageProcessor::CreateSyncMessage(std::shared_ptr &context, nlohmann::json &jsonObject) +{ + // 查询ACL + std::vector profiles = DeviceProfileConnector::GetInstance().GetAccessControlProfile(); + std::vector aclList; + int32_t ret; + 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) { + std::string aclStr; + ret = ACLToStr(item, aclStr); + if (aclStr.empty()) { + LOGE("DmAuthMessageProcessor::CreateSyncMessage normalized acl failed"); + return ERR_DM_FAILED; + } + aclList.push_back(aclStr); // 打印并写入 + } + } + if (aclList.empty()) { + LOGE("DmAuthMessageProcessor::CreateSyncMessage get acl failed"); + return ERR_DM_FAILED; + } + // 查询SP + DmAccess accessSide; // 代表本端的access + if (context->direction == DM_AUTH_SOURCE) { + accessSide = context->accesser; + } else { + accessSide = context->accessee; + } + DistributedDeviceProfile::ServiceInfoUniqueKey serviceInfoKey; + serviceInfoKey.SetDeviceId(accessSide.deviceId); + serviceInfoKey.SetUserId(accessSide.userId); + serviceInfoKey.SetTokenId(std::to_string(accessSide.tokenId)); + std::string encSyncMsg; + ret = EncryptSyncMessage(context, aclList, accessSide, encSyncMsg); + if (ret != DM_OK) { + LOGE("DmAuthMessageProcessor::CreateSyncMessage encrypt failed"); + return ret; + } + jsonObject[DM_TAG_SYNC] = encSyncMsg; + return DM_OK; +} + +std::string DmAuthMessageProcessor::GetTransmitFromContext(std::shared_ptr &context) +{ + // 解析出ontransmit字段 + std::string transmitStr = ""; + nlohmann::json jsonObject = nlohmann::json::parse(context->extraInfo, nullptr, false); + if (jsonObject.is_discarded() || !jsonObject.contains(DM_TAG_DATA) || !jsonObject[DM_TAG_DATA].is_string()) { + LOGE("DmAuthMessageProcessor::GetTransmitFromContext extraInfo jsonStr error"); + return transmitStr; + } + return SafetyDump(jsonObject[DM_TAG_DATA]); +} +// 解析transmit和PSKID +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; + } + + // 解密 + std::string plainText; + int32_t ret = cryptoMgr_->DecryptMessage(jsonObject[DM_TAG_DATA], plainText); + if (ret != DM_OK) { + LOGE("DmAuthMessageProcessor::ParseAuthStartMessgae DecryptMessage failed"); + return ret; + } + nlohmann::json jsonDecrptObj = plainText; + + if (ParseMessageOnTransmit(jsonDecrptObj, context) != DM_OK) { + LOGE("DmAuthMessageProcessor::ParseAuthStartMessgae ParseMessageOnTransmit failed"); + return ERR_DM_FAILED; + } + std::string jsonTag; + if (context->isOnline == false && context->isAppCredentailVerified == false) { // 首次认证的应用凭据 + jsonTag = DM_TAG_APP_CREDENTIAL_ID; + } else if (context->isOnline == false) { // 首次认证的用户凭据 + jsonTag = DM_TAG_USER_CREDENTIAL_ID; + } else { // 非首次认证的应用凭据 + jsonTag = DM_TAG_APP_CREDENTIAL_ID; + } + + if (!jsonDecrptObj.contains(jsonTag) || !jsonDecrptObj[jsonTag].is_string()) { + LOGE("DmAuthMessageProcessor::ParseAuthStartMessgae Unlegal json CRED ID"); + return ERR_DM_FAILED; + } + context->accesser.appCredentialId = jsonDecrptObj[jsonTag].get(); + 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..424dd1a37cc735d44ea650fc0f75a4bbf61a90ce --- /dev/null +++ b/services/implementation/src/authentication_v2/dm_auth_state.cpp @@ -0,0 +1,85 @@ +/* + * 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; +} + +} // 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..11791d0a498e7b4daf3cd98fbe87b4230059976f --- /dev/null +++ b/services/implementation/src/authentication_v2/dm_auth_state_machine.cpp @@ -0,0 +1,200 @@ +/* + * 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" + +namespace OHOS { +namespace DistributedHardware { + + +DmAuthStateMachine::DmAuthStateMachine(std::shared_ptr context) +{ + stateTransitionTable_ = { // 此处省略下一状态为AuthXXXFinishState的迁移情况 + // Source端 状态迁移表 + {DmAuthStateType::AUTH_IDLE_STATE, {DmAuthStateType::AUTH_SRC_START_STATE}}, + {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}}, + {DmAuthStateType::AUTH_SRC_PIN_AUTH_START_STATE, {DmAuthStateType::AUTH_SRC_PIN_AUTH_MSG_NEGOTIATE_STATE, + DmAuthStateType::AUTH_SINK_CONFIRM_STATE}}, // PIN输入错误,3次内会回到AuthSinkConfirmState + {DmAuthStateType::AUTH_SRC_PIN_AUTH_MSG_NEGOTIATE_STATE, {DmAuthStateType::AUTH_SRC_PIN_AUTH_DONE_STATE}}, + {DmAuthStateType::AUTH_SRC_PIN_AUTH_DONE_STATE, {DmAuthStateType::AUTH_SRC_CREDENTIAL_EXCHANGE_STATE}}, + {DmAuthStateType::AUTH_SRC_CREDENTIAL_EXCHANGE_STATE, {DmAuthStateType::AUTH_SRC_CREDENTIAL_AUTH_START_STATE}}, + {DmAuthStateType::AUTH_SRC_CREDENTIAL_AUTH_START_STATE, {DmAuthStateType::AUTH_SRC_CREDENTIAL_AUTH_NEGOTIATE_STATE}}, + {DmAuthStateType::AUTH_SRC_CREDENTIAL_AUTH_NEGOTIATE_STATE, {DmAuthStateType::AUTH_SRC_CREDENTIAL_AUTH_DONE_STATE}}, + {DmAuthStateType::AUTH_SRC_CREDENTIAL_AUTH_DONE_STATE, {DmAuthStateType::AUTH_SRC_DATA_SYNC_STATE}}, + {DmAuthStateType::AUTH_SRC_DATA_SYNC_STATE, {}}, + // Sink端 状态迁移表 + {DmAuthStateType::AUTH_IDLE_STATE, {DmAuthStateType::AUTH_SINK_START_STATE}}, + {DmAuthStateType::AUTH_SINK_START_STATE, {DmAuthStateType::AUTH_SINK_NEGOTIATE_STATE}}, + {DmAuthStateType::AUTH_SINK_NEGOTIATE_STATE, {DmAuthStateType::AUTH_SINK_CONFIRM_STATE}}, + {DmAuthStateType::AUTH_SINK_CONFIRM_STATE, {DmAuthStateType::AUTH_SINK_PIN_AUTH_START_STATE}}, + {DmAuthStateType::AUTH_SINK_PIN_AUTH_START_STATE, {DmAuthStateType::AUTH_SINK_PIN_AUTH_MSG_NEGOTIATE_STATE}}, + {DmAuthStateType::AUTH_SINK_PIN_AUTH_MSG_NEGOTIATE_STATE, {DmAuthStateType::AUTH_SINK_PIN_AUTH_DONE_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, {DmAuthStateType::AUTH_SINK_CREDENTIAL_AUTH_NEGOTIATE_STATE}}, + {DmAuthStateType::AUTH_SINK_CREDENTIAL_AUTH_NEGOTIATE_STATE, {DmAuthStateType::AUTH_SINK_CREDENTIAL_AUTH_DONE_STATE}}, + {DmAuthStateType::AUTH_SINK_CREDENTIAL_AUTH_DONE_STATE, {DmAuthStateType::AUTH_SINK_DATA_SYNC_STATE}}, + {DmAuthStateType::AUTH_SINK_DATA_SYNC_STATE, {DmAuthStateType::AUTH_SINK_FINISH_STATE}}, + {DmAuthStateType::AUTH_SINK_FINISH_STATE, {}}, + }; + running_ = true; + + 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)) { + std::lock_guard lock(mutex_); + // 存入到队列中 + statesQueue_.push(state); + stateCv_.notify_one(); + } else { + // 切换状态不合法,打印错误日志并返回错误码 + LOGE("DmAuthStateMachine: The state transition does not meet the rule."); + ret = ERR_DM_NEXT_STATE_INVALID; // 下一状态不合法错误码 + } + return ret; +} + +// action内部的期望事件,用于阻塞,当等到期望事件完成或其他异常时,返回实际发生的事件,而其他正常事件则会继续阻塞(只允许在action中调用) +DmEventType DmAuthStateMachine::WaitExpectEvent(DmEventType eventType) +{ + /* + 1、实际事件 = 期望事件,返回实际事件 + 2、实际事件 = 异常事件(事件超时等),同样返回实际事件 + 3、实际事件 = 其余事件,继续阻塞,但有个超时时间限制 + */ + std::unique_lock lock(mutex_); + // 记录进入函数的时间 + auto startTime = std::chrono::high_resolution_clock::now(); + while (true) { + eventCv_.wait(lock); + if (actualEventType_ == eventType || actualEventType_ == ON_ERROR) { + return actualEventType_; + } + // 做一个超时退出机制 + // 已经经过的时间 + 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) +{ + actualEventType_ = eventType; + eventCv_.notify_one(); +} + +// 循环等待状态转移,执行action +void DmAuthStateMachine::Run(std::shared_ptr context) +{ + while (running_.load()) { + auto state = FetchState(); + if (!state.has_value()) { + // 睡眠 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) { + context->reason = ret; + if (context->direction == DM_AUTH_SOURCE) { + // this->TransitionTo(std::make_shared()); + } else { + // this->TransitionTo(std::make_shared()); + } + // finish需要,清理context以及重启状态机 + } + } +} + +std::optional> DmAuthStateMachine::FetchState() +{ + std::unique_lock lock(mutex_); + 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) +{ + curState_ = state; +} + +// 获取当前状态 +DmAuthStateType DmAuthStateMachine::GetCurState() +{ + return curState_; +} + +// 检验下一状态迁移合法性 +bool DmAuthStateMachine::CheckStateTransitValid(DmAuthStateType nextState) +{ + // 判断下一状态是否为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 441e9e6064b2fcde75e4dc38c9a339132699c441..d8b04f7765128d360c356d62b48d824b44c91303 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" @@ -302,6 +303,13 @@ int32_t CryptoMgr::SaveSessionKey(const uint8_t *sessionKey, const uint32_t keyL return DM_OK; } +uint32_t CryptoMgr::GetSessionKey(uint8_t *sessionKey) +{ + std::lock_guard lock(sessionKeyMtx_); + sessionKey = sessionKey_.key; + 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 2c22d3bafd23e24f0e6f96f0708bc01ddd0a2a2f..ce4ae13c882403c08d0de51595673d0db61934c3 100644 --- a/services/implementation/src/dependency/hichain/hichain_auth_connector.cpp +++ b/services/implementation/src/dependency/hichain/hichain_auth_connector.cpp @@ -88,6 +88,135 @@ 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; + } + 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."); + char *returnData = NULL; + const CredManager *credManager = GetCredMgrInstance(); + int32_t ret = credManager->addCredential(osAccountId, authParams.c_str(), &returnData); + if (ret != HC_SUCCESS) { + LOGE("Hichain addCredential failed ret %{public}d.", ret); + credManager->destroyInfo(&returnData); + return ERR_DM_FAILED; + } + credId = static_cast(returnData); + credManager->destroyInfo(&returnData); + 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) { + LOGE("Hichain exportCredential failed ret %{public}d.", ret); + credManager->destroyInfo(&returnData); + return ERR_DM_FAILED; + } + publicKey = static_cast(returnData); + credManager->destroyInfo(&returnData); + 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."); + // TODO:IS黄区代码中没有这个接口 + // char *returnData = NULL; + // const CredManager *credManager = GetCredMgrInstance(); + // int32_t ret = credManager->agreeCredential(osAccountId, selfCredId.c_str(), authParams.c_str(), &returnData); + // if (ret != HC_SUCCESS) { + // LOGE("Hichain agreeCredential failed ret %{public}d.", ret); + // credManager->destroyInfo(&returnData); + // return ERR_DM_FAILED; + // } + // credId = static_cast(returnData); + // credManager->destroyInfo(&returnData); + 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; + } + 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; + } + + return DM_OK; +} + bool HiChainAuthConnector::onTransmit(int64_t requestId, const uint8_t *data, uint32_t dataLen) { LOGI("AuthDevice onTransmit, requestId %{public}" PRId64, requestId); @@ -197,6 +326,54 @@ 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); + 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; + } + + std::set credBindTypes; + 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("DmAuthManager::ProcRespNegotiate5_1_0 fail to query credential info."); + context->reply = ERR_DM_UNSUPPORTED_AUTH_TYPE; + return ERR_DM_FAILED; + } + nlohmann::json credInfoJson = nlohmann::json::parse(returnCredInfo, nullptr, false); + FreeJsonString(returnCredInfo); + if (credInfoJson.is_discarded()) { + LOGE("DmAuthManager::ProcRespNegotiate5_1_0 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.");