diff --git a/bundle.json b/bundle.json index dd2be1b8dad6fb5ddb3d4c0337a7ddb2e3352cb4..40c0134accd2abe61691a35f6df32a41bb7a3d6d 100644 --- a/bundle.json +++ b/bundle.json @@ -58,7 +58,8 @@ "samgr", "resource_management", "wifi", - "screenlock_mgr" + "screenlock_mgr", + "mbedtls" ], "third_party": [] }, diff --git a/common/include/dm_constants.h b/common/include/dm_constants.h index 50b550689931715da8ee13bc8831e45d13ddf119..0a3a526b572eae3f4984fc44b7f878e2fe49e81e 100755 --- a/common/include/dm_constants.h +++ b/common/include/dm_constants.h @@ -119,6 +119,9 @@ enum { ERR_DM_CHANNLE_OPEN_TIMEOUT = 96929818, ERR_DM_ADD_GOUTP_TIMEOUT = 96929819, ERR_DM_INPUT_TIMEOUT = 96929820, + ERR_DM_SAVE_SESSION_KEY_FAILED = 96929821, + ERR_DM_CRYPTO_OPT_FAILED = 96929822, + ERR_DM_CRYPTO_PARA_INVALID = 96929823 }; constexpr const char* TAG_GROUP_ID = "groupId"; diff --git a/services/implementation/BUILD.gn b/services/implementation/BUILD.gn index 3fdbe23f9720574989ffda690da20fa8c73344ad..2fcda9634f23d75fb0b37dd8f388bddcc3a57f41 100644 --- a/services/implementation/BUILD.gn +++ b/services/implementation/BUILD.gn @@ -117,6 +117,7 @@ if (defined(ohos_lite)) { "include/authentication/showconfirm/standard", "include/ability", "include/credential", + "include/cryptomgr", "include/devicestate", "include/dependency/commonevent", "include/dependency/deviceprofile", @@ -169,6 +170,7 @@ if (defined(ohos_lite)) { "src/authentication/showconfirm/standard/show_confirm.cpp", "src/config/dm_config_manager.cpp", "src/credential/dm_credential_manager.cpp", + "src/cryptomgr/crypto_mgr.cpp", "src/dependency/commonevent/dm_common_event_manager.cpp", "src/dependency/deviceprofile/dp_inited_callback.cpp", "src/dependency/hichain/hichain_auth_connector.cpp", @@ -216,6 +218,7 @@ if (defined(ohos_lite)) { "hilog:libhilog", "init:libbegetutil", "ipc:ipc_core", + "mbedtls:mbedtls_shared", "os_account:libaccountkits", "resource_management:resmgr_napi_core", "samgr:samgr_proxy", diff --git a/services/implementation/include/authentication/auth_message_processor.h b/services/implementation/include/authentication/auth_message_processor.h index e5eb58829b8e7c28cbcdfc9a3ea5493db6d99ab2..a987e0dc94ac7b720857444ff773e63b516ce14d 100644 --- a/services/implementation/include/authentication/auth_message_processor.h +++ b/services/implementation/include/authentication/auth_message_processor.h @@ -17,9 +17,11 @@ #define OHOS_DM_AUTH_MESSAGE_PROCESSOR_H #include +#include #include #include "crypto_adapter.h" +#include "crypto_mgr.h" #include "dm_auth_manager.h" #include "nlohmann/json.hpp" @@ -73,6 +75,7 @@ constexpr const char* TAG_IMPORT_AUTH_CODE = "IMPORT_AUTH_CODE"; constexpr const char* TAG_HOST_PKGLABEL = "hostPkgLabel"; constexpr const char* TAG_EDITION = "edition"; constexpr const char* TAG_BUNDLE_NAME = "bundleName"; +constexpr const char* TAG_CRYPTIC_MSG = "encryptMsg"; class DmAuthManager; struct DmAuthRequestContext; @@ -92,6 +95,8 @@ public: std::string CreateDeviceAuthMessage(int32_t msgType, const uint8_t *data, uint32_t dataLen); void CreateResponseAuthMessageExt(nlohmann::json &json); void ParseAuthResponseMessageExt(nlohmann::json &json); + void SetEncryptFlag(bool flag); + int32_t SaveSessionKey(const uint8_t *sessionKey, const uint32_t keyLen); private: std::string CreateRequestAuthMessage(nlohmann::json &json); @@ -110,6 +115,8 @@ private: void CreatePublicKeyMessageExt(nlohmann::json &json); void ParsePublicKeyMessageExt(nlohmann::json &json); void GetJsonObj(nlohmann::json &jsonObj); + void CreateReqVersionMessage(nlohmann::json &jsonObj); + void ParseReqVersionMessage(nlohmann::json &json); private: std::weak_ptr authMgr_; @@ -117,6 +124,9 @@ private: std::shared_ptr authRequestContext_; std::shared_ptr authResponseContext_; std::vector authSplitJsonList_; + std::mutex encryptFlagMutex_; + bool encryptFlag_ = false; + std::shared_ptr cryptoMgr_ = nullptr; }; } // namespace DistributedHardware } // namespace OHOS diff --git a/services/implementation/include/authentication/auth_request_state.h b/services/implementation/include/authentication/auth_request_state.h index 997012de7064ea234537c072b559d5138dacdcf0..62b659b0fd7b3597b6f936ca1d2f71efbd156c2f 100644 --- a/services/implementation/include/authentication/auth_request_state.h +++ b/services/implementation/include/authentication/auth_request_state.h @@ -199,6 +199,18 @@ public: int32_t GetStateType() override; int32_t Enter() override; }; + +class AuthRequestVersion : public AuthRequestState { +public: + int32_t GetStateType() override; + int32_t Enter() override; +}; + +class AuthRequestVersionDone : public AuthRequestState { +public: + int32_t GetStateType() override; + int32_t Enter() override; +}; } // namespace DistributedHardware } // namespace OHOS #endif // OHOS_DM_AUTH_REQUEST_STATE_H diff --git a/services/implementation/include/authentication/auth_response_state.h b/services/implementation/include/authentication/auth_response_state.h index cbf9eb9121914232259970d79288780c9409e5e3..1335755a5fed2bcab9f6f25e4322028b5c3a9895 100644 --- a/services/implementation/include/authentication/auth_response_state.h +++ b/services/implementation/include/authentication/auth_response_state.h @@ -118,6 +118,12 @@ public: int32_t GetStateType() override; int32_t Enter() override; }; + +class AuthResponseVersion : public AuthResponseState { +public: + int32_t GetStateType() override; + int32_t Enter() override; +}; } // namespace DistributedHardware } // namespace OHOS #endif // OHOS_DM_AUTH_RESPONSE_STATE_H diff --git a/services/implementation/include/authentication/dm_auth_manager.h b/services/implementation/include/authentication/dm_auth_manager.h index 70c6dd645dc2f9ab652cb9b9d8e92eb3df6c8341..d2dd94d36febcce609c6a197386be5dda3070670 100644 --- a/services/implementation/include/authentication/dm_auth_manager.h +++ b/services/implementation/include/authentication/dm_auth_manager.h @@ -48,6 +48,8 @@ typedef enum AuthState { AUTH_REQUEST_CREDENTIAL, AUTH_REQUEST_CREDENTIAL_DONE, AUTH_REQUEST_AUTH_FINISH, + AUTH_REQUEST_VERSION, + AUTH_REQUEST_VERSION_DONE, AUTH_RESPONSE_INIT = 20, AUTH_RESPONSE_NEGOTIATE, @@ -57,6 +59,7 @@ typedef enum AuthState { AUTH_RESPONSE_FINISH, AUTH_RESPONSE_CREDENTIAL, AUTH_RESPONSE_AUTH_FINISH, + AUTH_RESPONSE_VERSION, } AuthState; enum DmMsgType : int32_t { @@ -76,6 +79,8 @@ enum DmMsgType : int32_t { MSG_TYPE_RESP_AUTH_EXT, MSG_TYPE_REQ_PUBLICKEY, MSG_TYPE_RESP_PUBLICKEY, + MSG_TYPE_REQ_VERSION, + MSG_TYPE_RESP_VERSION, MSG_TYPE_REQ_AUTH_DEVICE_NEGOTIATE = 600, MSG_TYPE_RESP_AUTH_DEVICE_NEGOTIATE = 700, }; @@ -504,6 +509,9 @@ public: int32_t DeleteGroup(const std::string &pkgName, const std::string &deviceId); int32_t DeleteGroup(const std::string &pkgName, int32_t userId, const std::string &deviceId); int32_t StopAuthenticateDevice(const std::string &pkgName); + void RequestVersion(); + void ResponseVersion(); + void RequestVersionDone(); private: int32_t ImportCredential(std::string &deviceId, std::string &publicKey); void GetAuthParam(const std::string &pkgName, int32_t authType, const std::string &deviceId, @@ -534,6 +542,7 @@ private: std::string GetBundleName(nlohmann::json &jsonObject); int32_t GetBinderInfo(); void SetProcessInfo(); + void ConverToFinish(); private: std::shared_ptr softbusConnector_; @@ -560,8 +569,6 @@ private: std::string importPkgName_ = ""; std::string importAuthCode_ = ""; PeerTargetId peerTargetId_; - const uint8_t *sessionKey_ = nullptr; - uint32_t sessionKeyLen_ = 0; std::string remoteDeviceId_ = ""; std::string dmVersion_ = ""; bool isAuthDevice_ = false; diff --git a/services/implementation/include/cryptomgr/crypto_mgr.h b/services/implementation/include/cryptomgr/crypto_mgr.h new file mode 100644 index 0000000000000000000000000000000000000000..dc02f7b90167245501d8de12afd108913337ca62 --- /dev/null +++ b/services/implementation/include/cryptomgr/crypto_mgr.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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_CRYPTO_MGR_H +#define OHOS_DM_CRYPTO_MGR_H + +#include +#include +#include + +namespace OHOS { +namespace DistributedHardware { +namespace { + constexpr uint32_t MAX_SESSION_KEY_LENGTH = 512; + constexpr uint32_t SESSION_KEY_LENGTH = 32; + constexpr uint32_t GCM_IV_LEN = 12; + constexpr uint32_t TAG_LEN = 16; + constexpr uint32_t OVERHEAD_LEN = GCM_IV_LEN + TAG_LEN; + constexpr uint32_t MAX_ENCRY_MSG_LEN = 10 * 1024 * 1024; // 10MB + constexpr uint32_t KEY_BITS_UNIT = 8; + constexpr uint32_t HEX_TO_UINT8 = 2; +} +typedef struct DMSessionKey { + uint8_t *key = nullptr; + uint32_t keyLen = 0; +} DMSessionKey; + +typedef struct AesGcmCipherKey { + uint32_t keyLen = 0; + unsigned char key[SESSION_KEY_LENGTH] = {0}; + unsigned char iv[GCM_IV_LEN] = {0}; +} AesGcmCipherKey; + +class CryptoMgr { +public: + CryptoMgr(); + ~CryptoMgr(); + int32_t EncryptMessage(const std::string &inputMsg, std::string &outputMsg); + int32_t DecryptMessage(const std::string &inputMsg, std::string &outputMsg); + int32_t SaveSessionKey(const uint8_t *sessionKey, const uint32_t keyLen); + void ClearSessionKey(); + +private: + int32_t DoEncryptData(AesGcmCipherKey *cipherKey, const unsigned char *input, uint32_t inLen, + unsigned char *encryptData, uint32_t *encryptLen); + int32_t GenerateRandomArray(unsigned char *randStr, uint32_t len); + int32_t MbedAesGcmEncrypt(const AesGcmCipherKey *cipherKey, const unsigned char *plainText, + uint32_t plainTextSize, unsigned char *cipherText, uint32_t cipherTextLen); + + int32_t DoDecryptData(AesGcmCipherKey *cipherKey, const unsigned char *input, uint32_t inLen, + unsigned char *decryptData, uint32_t *decryptLen); + int32_t MbedAesGcmDecrypt(const AesGcmCipherKey *cipherKey, const unsigned char *cipherText, + uint32_t cipherTextSize, unsigned char *plain, uint32_t plainLen); +private: + std::mutex sessionKeyMtx_; + DMSessionKey sessionKey_; + std::mutex randomLock_; +}; +} // namespace DistributedHardware +} // namespace OHOS +#endif // OHOS_DM_CRYPTO_MGR_H \ No newline at end of file diff --git a/services/implementation/src/authentication/auth_message_processor.cpp b/services/implementation/src/authentication/auth_message_processor.cpp index e7a2cb9028b22769afca9e1c84f89faba2ce8974..32811b73ea1d4f198c09cf46dda2d326dc7f7120 100644 --- a/services/implementation/src/authentication/auth_message_processor.cpp +++ b/services/implementation/src/authentication/auth_message_processor.cpp @@ -33,11 +33,15 @@ constexpr const char* TAG_THUMBNAIL_SIZE = "THUMSIZE"; AuthMessageProcessor::AuthMessageProcessor(std::shared_ptr authMgr) : authMgr_(authMgr) { LOGI("AuthMessageProcessor constructor"); + cryptoMgr_ = std::make_shared(); } AuthMessageProcessor::~AuthMessageProcessor() { authMgr_.reset(); + if (cryptoMgr_ != nullptr) { + cryptoMgr_->ClearSessionKey(); + } } void AuthMessageProcessor::GetJsonObj(nlohmann::json &jsonObj) @@ -135,6 +139,10 @@ std::string AuthMessageProcessor::CreateSimpleMessage(int32_t msgType) case MSG_TYPE_RESP_PUBLICKEY: CreatePublicKeyMessageExt(jsonObj); break; + case MSG_TYPE_REQ_VERSION: + case MSG_TYPE_RESP_VERSION: + CreateReqVersionMessage(jsonObj); + break; default: break; } @@ -143,7 +151,28 @@ std::string AuthMessageProcessor::CreateSimpleMessage(int32_t msgType) void AuthMessageProcessor::CreatePublicKeyMessageExt(nlohmann::json &json) { - json[TAG_PUBLICKEY] = authResponseContext_->publicKey; + bool encryptFlag = false; + { + std::lock_guard mutexLock(encryptFlagMutex_); + encryptFlag = encryptFlag_; + } + if (!encryptFlag) { + LOGI("not encrypt publickey."); + json[TAG_PUBLICKEY] = authResponseContext_->publicKey; + return; + } else { + nlohmann::json jsonTemp; + jsonTemp[TAG_PUBLICKEY] = authResponseContext_->publicKey; + std::string strTemp = SafetyDump(jsonTemp); + std::string encryptStr = ""; + CHECK_NULL_VOID(cryptoMgr_); + if (cryptoMgr_->EncryptMessage(strTemp, encryptStr) != DM_OK) { + LOGE("EncryptMessage failed."); + return; + } + json[TAG_CRYPTIC_MSG] = encryptStr; + return; + } } void AuthMessageProcessor::CreateResponseAuthMessageExt(nlohmann::json &json) @@ -295,6 +324,10 @@ int32_t AuthMessageProcessor::ParseMessage(const std::string &message) case MSG_TYPE_RESP_PUBLICKEY: ParsePublicKeyMessageExt(jsonObject); break; + case MSG_TYPE_REQ_VERSION: + case MSG_TYPE_RESP_VERSION: + ParseReqVersionMessage(jsonObject); + break; default: break; } @@ -303,8 +336,33 @@ int32_t AuthMessageProcessor::ParseMessage(const std::string &message) void AuthMessageProcessor::ParsePublicKeyMessageExt(nlohmann::json &json) { - if (IsString(json, TAG_PUBLICKEY)) { + bool encryptFlag = false; + { + std::lock_guard mutexLock(encryptFlagMutex_); + encryptFlag = encryptFlag_; + } + if (!encryptFlag && IsString(json, TAG_PUBLICKEY)) { authResponseContext_->publicKey = json[TAG_PUBLICKEY].get(); + return; + } + if (encryptFlag && IsString(json, TAG_CRYPTIC_MSG)) { + std::string encryptStr = json[TAG_CRYPTIC_MSG].get(); + std::string decryptStr = ""; + authResponseContext_->publicKey = ""; + CHECK_NULL_VOID(cryptoMgr_); + if (cryptoMgr_->DecryptMessage(encryptStr, decryptStr) != DM_OK) { + LOGE("DecryptMessage failed."); + return; + } + nlohmann::json jsonObject = nlohmann::json::parse(decryptStr, nullptr, false); + if (jsonObject.is_discarded()) { + LOGE("DecodeRequestAuth jsonStr error"); + return; + } + if (IsString(jsonObject, TAG_PUBLICKEY)) { + authResponseContext_->publicKey = jsonObject[TAG_PUBLICKEY].get(); + } + return; } } @@ -595,5 +653,54 @@ std::string AuthMessageProcessor::CreateDeviceAuthMessage(int32_t msgType, const jsonObj[TAG_DATA_LEN] = dataLen; return SafetyDump(jsonObj); } + +void AuthMessageProcessor::CreateReqVersionMessage(nlohmann::json &jsonObj) +{ + nlohmann::json jsonTemp; + jsonTemp[TAG_EDITION] = authResponseContext_->edition; + std::string strTemp = SafetyDump(jsonTemp); + std::string encryptStr = ""; + CHECK_NULL_VOID(cryptoMgr_); + if (cryptoMgr_->EncryptMessage(strTemp, encryptStr) != DM_OK) { + LOGE("EncryptMessage failed."); + return; + } + jsonObj[TAG_CRYPTIC_MSG] = encryptStr; +} + +void AuthMessageProcessor::ParseReqVersionMessage(nlohmann::json &json) +{ + std::string encryptStr = ""; + if (IsString(json, TAG_CRYPTIC_MSG)) { + encryptStr = json[TAG_CRYPTIC_MSG].get(); + } + std::string decryptStr = ""; + authResponseContext_->edition = ""; + CHECK_NULL_VOID(cryptoMgr_); + if (cryptoMgr_->DecryptMessage(encryptStr, decryptStr) != DM_OK) { + LOGE("DecryptMessage failed."); + return; + } + nlohmann::json jsonObject = nlohmann::json::parse(decryptStr, nullptr, false); + if (jsonObject.is_discarded()) { + LOGE("DecodeRequestAuth jsonStr error"); + return; + } + if (IsString(jsonObject, TAG_EDITION)) { + authResponseContext_->edition = jsonObject[TAG_EDITION].get(); + } +} + +int32_t AuthMessageProcessor::SaveSessionKey(const uint8_t *sessionKey, const uint32_t keyLen) +{ + CHECK_NULL_RETURN(cryptoMgr_, ERR_DM_POINT_NULL); + return cryptoMgr_->SaveSessionKey(sessionKey, keyLen); +} + +void AuthMessageProcessor::SetEncryptFlag(bool flag) +{ + std::lock_guard mutexLock(encryptFlagMutex_); + encryptFlag_ = flag; +} } // namespace DistributedHardware } // namespace OHOS diff --git a/services/implementation/src/authentication/auth_request_state.cpp b/services/implementation/src/authentication/auth_request_state.cpp index 8dbcb3b84667547ca632eb8fa2c008b14b66cf12..2a74286dc964ff47764ca2c3a6f567318a24438b 100644 --- a/services/implementation/src/authentication/auth_request_state.cpp +++ b/services/implementation/src/authentication/auth_request_state.cpp @@ -214,5 +214,37 @@ int32_t AuthRequestAuthFinish::Enter() { return DM_OK; } + +int32_t AuthRequestVersion::GetStateType() +{ + return AuthState::AUTH_REQUEST_VERSION; +} + +int32_t AuthRequestVersion::Enter() +{ + std::shared_ptr stateAuthManager = authManager_.lock(); + if (stateAuthManager == nullptr) { + LOGE("AuthRequestState::authManager_ null"); + return ERR_DM_FAILED; + } + stateAuthManager->RequestVersion(); + return DM_OK; +} + +int32_t AuthRequestVersionDone::GetStateType() +{ + return AuthState::AUTH_REQUEST_VERSION_DONE; +} + +int32_t AuthRequestVersionDone::Enter() +{ + std::shared_ptr stateAuthManager = authManager_.lock(); + if (stateAuthManager == nullptr) { + LOGE("AuthRequestState::authManager_ null"); + return ERR_DM_FAILED; + } + stateAuthManager->RequestVersionDone(); + return DM_OK; +} } // namespace DistributedHardware } // namespace OHOS diff --git a/services/implementation/src/authentication/auth_response_state.cpp b/services/implementation/src/authentication/auth_response_state.cpp index afe61b0dc554b21294c922c397a16edfb57c66f3..f8b5214dabd8e3d814c9f059dcec43e851241ebe 100644 --- a/services/implementation/src/authentication/auth_response_state.cpp +++ b/services/implementation/src/authentication/auth_response_state.cpp @@ -178,5 +178,21 @@ int32_t AuthResponseAuthFinish::Enter() { return DM_OK; } + +int32_t AuthResponseVersion::GetStateType() +{ + return AuthState::AUTH_RESPONSE_VERSION; +} + +int32_t AuthResponseVersion::Enter() +{ + std::shared_ptr stateAuthManager = authManager_.lock(); + if (stateAuthManager == nullptr) { + LOGE("AuthResponseCredential authManager_ is null"); + return ERR_DM_FAILED; + } + stateAuthManager->ResponseVersion(); + return DM_OK; +} } // namespace DistributedHardware } // namespace OHOS diff --git a/services/implementation/src/authentication/dm_auth_manager.cpp b/services/implementation/src/authentication/dm_auth_manager.cpp index 18610d61cd3b926b9fa37b272636d3d2b38cb84b..0af21ef956767445d531d7b9444e4b690958b580 100644 --- a/services/implementation/src/authentication/dm_auth_manager.cpp +++ b/services/implementation/src/authentication/dm_auth_manager.cpp @@ -98,6 +98,7 @@ constexpr const char* BUNDLE_NAME_KEY = "bundleName"; constexpr const char* DM_VERSION_4_1_5_1 = "4.1.5.1"; constexpr const char* DM_VERSION_5_0_1 = "5.0.1"; constexpr const char* DM_VERSION_5_0_2 = "5.0.2"; +constexpr const char* DM_VERSION_5_0_3 = "5.0.3"; std::mutex g_authFinishLock; DmAuthManager::DmAuthManager(std::shared_ptr softbusConnector, @@ -113,7 +114,7 @@ DmAuthManager::DmAuthManager(std::shared_ptr softbusConnector, authUiStateMgr_ = std::make_shared(listener_); authenticationMap_[AUTH_TYPE_IMPORT_AUTH_CODE] = nullptr; authenticationMap_[AUTH_TYPE_CRE] = nullptr; - dmVersion_ = DM_VERSION_5_0_2; + dmVersion_ = DM_VERSION_5_0_3; } DmAuthManager::~DmAuthManager() @@ -205,7 +206,7 @@ void DmAuthManager::GetAuthParam(const std::string &pkgName, int32_t authType, authRequestContext_->localDeviceId = localUdid; authRequestContext_->deviceId = deviceId; authRequestContext_->addr = deviceId; - authRequestContext_->dmVersion = DM_VERSION_5_0_2; + authRequestContext_->dmVersion = DM_VERSION_5_0_3; uint32_t tokenId; MultipleUserConnector::GetTokenIdAndForegroundUserId(tokenId, authRequestContext_->localUserId); authRequestContext_->tokenId = static_cast(tokenId); @@ -510,6 +511,11 @@ void DmAuthManager::ProcessSourceMsg() authRequestState_->TransitionTo(std::make_shared()); } break; + case MSG_TYPE_RESP_VERSION: + if (authRequestState_->GetStateType() == AuthState::AUTH_REQUEST_VERSION) { + authRequestState_->TransitionTo(std::make_shared()); + } + break; default: break; } @@ -545,10 +551,16 @@ void DmAuthManager::ProcessSinkMsg() } break; case MSG_TYPE_REQ_PUBLICKEY: - if (authResponseState_->GetStateType() == AuthState::AUTH_RESPONSE_AUTH_FINISH) { + if (authResponseState_->GetStateType() == AuthState::AUTH_RESPONSE_AUTH_FINISH || + authResponseState_->GetStateType() == AuthState::AUTH_RESPONSE_VERSION) { authResponseState_->TransitionTo(std::make_shared()); } break; + case MSG_TYPE_REQ_VERSION: + if (authResponseState_->GetStateType() == AuthState::AUTH_RESPONSE_AUTH_FINISH) { + authResponseState_->TransitionTo(std::make_shared()); + } + break; default: break; } @@ -772,7 +784,7 @@ void DmAuthManager::StartNegotiate(const int32_t &sessionId) authResponseContext_->localAccountId = authRequestContext_->localAccountId; authResponseContext_->localUserId = authRequestContext_->localUserId; authResponseContext_->isIdenticalAccount = false; - authResponseContext_->edition = DM_VERSION_5_0_2; + authResponseContext_->edition = DM_VERSION_5_0_3; authMessageProcessor_->SetResponseContext(authResponseContext_); std::string message = authMessageProcessor_->CreateSimpleMessage(MSG_TYPE_NEGOTIATE); softbusConnector_->GetSoftbusSession()->SendData(sessionId, message); @@ -1923,11 +1935,9 @@ void DmAuthManager::GenerateCredential(std::string &publicKey) void DmAuthManager::RequestCredentialDone() { LOGI("DmAuthManager ExchangeCredentailDone start"); - if (authResponseContext_ == nullptr) { - LOGE("failed to JoinNeWork because authResponseContext_ is nullptr"); - return; - } - if (ImportCredential(remoteDeviceId_, authResponseContext_->publicKey) != DM_OK) { + CHECK_NULL_VOID(authResponseContext_); + if (authResponseContext_->publicKey != "" && + ImportCredential(remoteDeviceId_, authResponseContext_->publicKey) != DM_OK) { LOGE("ResponseCredential import credential failed."); } if (timer_ != nullptr) { @@ -1950,6 +1960,15 @@ int32_t DmAuthManager::ImportCredential(std::string &deviceId, std::string &publ void DmAuthManager::ResponseCredential() { LOGI("DmAuthManager::ResponseCredential start."); + CHECK_NULL_VOID(authResponseContext_); + if (authResponseContext_->publicKey == "") { + LOGE("authResponseContext_->publicKey is empty."); + authResponseContext_->isFinish = false; + isFinishOfLocal_ = false; + authMessageProcessor_->SetEncryptFlag(false); + authResponseState_->TransitionTo(std::make_shared()); + softbusConnector_->GetSoftbusSession()->CloseAuthSession(authResponseContext_->sessionId); + } std::string publicKey = ""; GenerateCredential(publicKey); if (ImportCredential(remoteDeviceId_, authResponseContext_->publicKey) != DM_OK) { @@ -1997,10 +2016,7 @@ void DmAuthManager::SrcAuthDeviceFinish() if (timer_ != nullptr) { timer_->DeleteTimer(std::string(AUTHENTICATE_TIMEOUT_TASK)); } - authRequestContext_->reason = DM_OK; - authResponseContext_->reply = DM_OK; - authResponseContext_->state = AuthState::AUTH_REQUEST_FINISH; - authRequestState_->TransitionTo(std::make_shared()); + ConverToFinish(); return; } if (authResponseContext_->confirmOperation == USER_OPERATION_TYPE_ALLOW_AUTH_ALWAYS && @@ -2010,22 +2026,27 @@ void DmAuthManager::SrcAuthDeviceFinish() SetProcessInfo(); } softbusConnector_->HandleDeviceOnline(remoteDeviceId_, authForm_); - authRequestState_->TransitionTo(std::make_shared()); + if (CompareVersion(remoteVersion_, std::string(DM_VERSION_5_0_2))) { + authRequestState_->TransitionTo(std::make_shared()); + } else { + authRequestState_->TransitionTo(std::make_shared()); + } return; } } if (!authResponseContext_->isOnline && authResponseContext_->haveCredential) { softbusConnector_->JoinLnn(authRequestContext_->addr); timer_->DeleteTimer(std::string(AUTHENTICATE_TIMEOUT_TASK)); - authRequestContext_->reason = DM_OK; - authResponseContext_->reply = DM_OK; - authResponseContext_->state = AuthState::AUTH_REQUEST_FINISH; - authRequestState_->TransitionTo(std::make_shared()); + ConverToFinish(); return; } if (!authResponseContext_->isOnline && !authResponseContext_->haveCredential) { authUiStateMgr_->UpdateUiState(DmUiStateMsg::MSG_CANCEL_PIN_CODE_INPUT); - authRequestState_->TransitionTo(std::make_shared()); + if (CompareVersion(remoteVersion_, std::string(DM_VERSION_5_0_2))) { + authRequestState_->TransitionTo(std::make_shared()); + } else { + authRequestState_->TransitionTo(std::make_shared()); + } return; } } @@ -2055,7 +2076,10 @@ void DmAuthManager::AuthDeviceFinish(int64_t requestId) if (timer_ != nullptr) { timer_->DeleteTimer(std::string(AUTH_DEVICE_TIMEOUT_TASK)); } - + if (CompareVersion(remoteVersion_, std::string(DM_VERSION_5_0_2))) { + LOGI("Set EncryptFlag true."); + authMessageProcessor_->SetEncryptFlag(true); + } if (authRequestState_ != nullptr && authResponseState_ == nullptr) { PutAccessControlList(); SrcAuthDeviceFinish(); @@ -2109,13 +2133,16 @@ void DmAuthManager::AuthDeviceError(int64_t requestId, int32_t errorCode) void DmAuthManager::AuthDeviceSessionKey(int64_t requestId, const uint8_t *sessionKey, uint32_t sessionKeyLen) { - LOGI("DmAuthManager::AuthDeviceSessionKey start."); + LOGI("DmAuthManager::AuthDeviceSessionKey start. keyLen: %{public}u", sessionKeyLen); if (requestId != authResponseContext_->requestId) { LOGE("DmAuthManager::onTransmit requestId %{public}" PRId64 "is error.", requestId); return; } - sessionKey_ = sessionKey; - sessionKeyLen_ = sessionKeyLen; + CHECK_NULL_VOID(authMessageProcessor_); + int32_t ret = authMessageProcessor_->SaveSessionKey(sessionKey, sessionKeyLen); + if (ret != DM_OK) { + LOGE("Save session key err, ret: %{public}d", ret); + } } void DmAuthManager::GetRemoteDeviceId(std::string &deviceId) @@ -2335,13 +2362,10 @@ void DmAuthManager::PutAccessControlList() std::string localUdidHash = static_cast(mUdidHash); DmAclInfo aclInfo; aclInfo.bindType = DM_ACROSS_ACCOUNT; - if (authResponseContext_->isIdenticalAccount) { - aclInfo.bindType = DM_IDENTICAL_ACCOUNT; - authForm_ = DmAuthForm::IDENTICAL_ACCOUNT; - } else if (authResponseContext_->localAccountId == "ohosAnonymousUid" || + if (authResponseContext_->localAccountId == "ohosAnonymousUid" || authResponseContext_->remoteAccountId == "ohosAnonymousUid") { aclInfo.bindType = DM_POINT_TO_POINT; - authForm_ = DmAuthForm::PEER_TO_PEER; + authForm_ = DmAuthForm::PEER_TO_PEER; } aclInfo.bindLevel = authResponseContext_->bindLevel; aclInfo.trustDeviceId = remoteDeviceId_; @@ -2653,5 +2677,57 @@ void DmAuthManager::SetProcessInfo() } softbusConnector_->SetProcessInfo(processInfo); } + +void DmAuthManager::ConverToFinish() +{ + authRequestContext_->reason = DM_OK; + authResponseContext_->reply = DM_OK; + authResponseContext_->state = AuthState::AUTH_REQUEST_FINISH; + authRequestState_->TransitionTo(std::make_shared()); +} + +void DmAuthManager::RequestVersion() +{ + LOGI("dmVersion %{public}s.", DM_VERSION_5_0_3); + authResponseContext_->edition = DM_VERSION_5_0_3; + authMessageProcessor_->SetResponseContext(authResponseContext_); + std::string message = authMessageProcessor_->CreateSimpleMessage(MSG_TYPE_REQ_VERSION); + softbusConnector_->GetSoftbusSession()->SendData(authResponseContext_->sessionId, message); +} + +void DmAuthManager::ResponseVersion() +{ + LOGI("remoteVersion %{public}s, authResponseContext_->edition %{public}s.", + remoteVersion_.c_str(), authResponseContext_->edition.c_str()); + if (authResponseContext_->edition != remoteVersion_) { + LOGE("peer deviceId not trust."); + authResponseContext_->isFinish = false; + isFinishOfLocal_ = false; + authMessageProcessor_->SetEncryptFlag(false); + int32_t sessionId = authResponseContext_->sessionId; + authResponseState_->TransitionTo(std::make_shared()); + softbusConnector_->GetSoftbusSession()->CloseAuthSession(sessionId); + return; + } + authResponseContext_->edition = DM_VERSION_5_0_3; + authMessageProcessor_->SetEncryptFlag(true); + std::string message = authMessageProcessor_->CreateSimpleMessage(MSG_TYPE_RESP_VERSION); + softbusConnector_->GetSoftbusSession()->SendData(authResponseContext_->sessionId, message); +} + +void DmAuthManager::RequestVersionDone() +{ + LOGI("remoteVersion %{public}s, authResponseContext_->edition %{public}s.", + remoteVersion_.c_str(), authResponseContext_->edition.c_str()); + if (authResponseContext_->edition != remoteVersion_) { + LOGE("peer deviceId not trust."); + authResponseContext_->isFinish = false; + isFinishOfLocal_ = false; + authMessageProcessor_->SetEncryptFlag(false); + authRequestState_->TransitionTo(std::make_shared()); + return; + } + authRequestState_->TransitionTo(std::make_shared()); +} } // namespace DistributedHardware } // namespace OHOS diff --git a/services/implementation/src/cryptomgr/crypto_mgr.cpp b/services/implementation/src/cryptomgr/crypto_mgr.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2a153e5558184527457a69e1211181199eef62a9 --- /dev/null +++ b/services/implementation/src/cryptomgr/crypto_mgr.cpp @@ -0,0 +1,292 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "crypto_mgr.h" + +#include +#include + +#include "mbedtls/base64.h" +#include "mbedtls/cipher.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/entropy.h" +#include "mbedtls/gcm.h" +#include "mbedtls/md.h" +#include "mbedtls/platform.h" + +#include "securec.h" + +#include "dm_constants.h" +#include "dm_crypto.h" +#include "dm_log.h" + +namespace OHOS { +namespace DistributedHardware { +CryptoMgr::CryptoMgr() +{ + LOGI("CryptoMgr ctor"); +} + +CryptoMgr::~CryptoMgr() +{ + LOGI("CryptoMgr dtor"); + ClearSessionKey(); +} + +int32_t CryptoMgr::EncryptMessage(const std::string &inputMsg, std::string &outputMsg) +{ + if (inputMsg.length() > MAX_ENCRY_MSG_LEN) { + LOGE("Encrypt msg too long, size: %{public}zu", inputMsg.size()); + return ERR_DM_CRYPTO_PARA_INVALID; + } + + std::lock_guard lock(sessionKeyMtx_); + AesGcmCipherKey cipherKey = {.keyLen = sessionKey_.keyLen}; + if (memcpy_s(cipherKey.key, SESSION_KEY_LENGTH, sessionKey_.key, sessionKey_.keyLen) != EOK) { + LOGE("set key fail"); + return ERR_DM_CRYPTO_OPT_FAILED; + } + + uint32_t encDataLen = inputMsg.length() + OVERHEAD_LEN; + unsigned char *encData = (unsigned char *)calloc(encDataLen, sizeof(unsigned char)); + int32_t ret = DoEncryptData(&cipherKey, reinterpret_cast(inputMsg.c_str()), + static_cast(inputMsg.length()), encData, &encDataLen); + (void)memset_s(&cipherKey, sizeof(AesGcmCipherKey), 0, sizeof(AesGcmCipherKey)); + if (ret != DM_OK) { + LOGE("EncryptData fail=%{public}d", ret); + return ERR_DM_CRYPTO_OPT_FAILED; + } + const uint32_t hexStrLen = encDataLen * HEX_TO_UINT8 + 1; + char hexStrTemp[hexStrLen]; + if (memset_s(hexStrTemp, hexStrLen, 0, hexStrLen) != DM_OK) { + LOGE("memset_s failed."); + return ERR_DM_CRYPTO_OPT_FAILED; + } + Crypto::ConvertBytesToHexString(hexStrTemp, hexStrLen, encData, encDataLen); + outputMsg.clear(); + outputMsg.assign(hexStrTemp, encDataLen * HEX_TO_UINT8); + free(encData); + encData = nullptr; + return DM_OK; +} + +int32_t CryptoMgr::DoEncryptData(AesGcmCipherKey *cipherKey, const unsigned char *input, uint32_t inLen, + unsigned char *encryptData, uint32_t *encryptLen) +{ + if (cipherKey == nullptr || input == nullptr || inLen == 0 || encryptData == nullptr || encryptLen == nullptr) { + return ERR_DM_CRYPTO_PARA_INVALID; + } + + if (GenerateRandomArray(cipherKey->iv, sizeof(cipherKey->iv)) != DM_OK) { + LOGE("generate random iv error."); + return ERR_DM_CRYPTO_OPT_FAILED; + } + uint32_t outLen = inLen + OVERHEAD_LEN; + int32_t result = MbedAesGcmEncrypt(cipherKey, input, inLen, encryptData, outLen); + if (result <= 0) { + return ERR_DM_CRYPTO_OPT_FAILED; + } + *encryptLen = result; + return DM_OK; +} + +int32_t CryptoMgr::MbedAesGcmEncrypt(const AesGcmCipherKey *cipherKey, const unsigned char *plainText, + uint32_t plainTextSize, unsigned char *cipherText, uint32_t cipherTextLen) +{ + if ((cipherKey == nullptr) || (plainText == nullptr) || (plainTextSize == 0) || cipherText == nullptr || + (cipherTextLen < plainTextSize + OVERHEAD_LEN)) { + LOGE("Encrypt invalid para"); + return ERR_DM_CRYPTO_PARA_INVALID; + } + + int32_t ret = -1; + unsigned char tagBuf[TAG_LEN] = { 0 }; + mbedtls_gcm_context aesContext; + mbedtls_gcm_init(&aesContext); + + ret = mbedtls_gcm_setkey(&aesContext, MBEDTLS_CIPHER_ID_AES, cipherKey->key, cipherKey->keyLen * KEY_BITS_UNIT); + if (ret != 0) { + mbedtls_gcm_free(&aesContext); + return ERR_DM_CRYPTO_OPT_FAILED; + } + + ret = mbedtls_gcm_crypt_and_tag(&aesContext, MBEDTLS_GCM_ENCRYPT, plainTextSize, cipherKey->iv, GCM_IV_LEN, NULL, 0, + plainText, cipherText + GCM_IV_LEN, TAG_LEN, tagBuf); + if (ret != 0) { + mbedtls_gcm_free(&aesContext); + return ERR_DM_CRYPTO_OPT_FAILED; + } + + if (memcpy_s(cipherText, cipherTextLen, cipherKey->iv, GCM_IV_LEN) != EOK) { + mbedtls_gcm_free(&aesContext); + return ERR_DM_CRYPTO_OPT_FAILED; + } + + if (memcpy_s(cipherText + GCM_IV_LEN + plainTextSize, cipherTextLen - GCM_IV_LEN - plainTextSize, tagBuf, + TAG_LEN) != 0) { + mbedtls_gcm_free(&aesContext); + return ERR_DM_CRYPTO_OPT_FAILED; + } + + mbedtls_gcm_free(&aesContext); + return (plainTextSize + OVERHEAD_LEN); +} + +int32_t CryptoMgr::GenerateRandomArray(unsigned char *randStr, uint32_t len) +{ + if (randStr == NULL || len == 0) { + return ERR_DM_CRYPTO_PARA_INVALID; + } + + static mbedtls_entropy_context entropy; + static mbedtls_ctr_drbg_context ctrDrbg; + static std::atomic initFlag = false; + int32_t ret; + + if (!initFlag) { + std::lock_guard lock(randomLock_); + mbedtls_ctr_drbg_init(&ctrDrbg); + mbedtls_entropy_init(&entropy); + ret = mbedtls_ctr_drbg_seed(&ctrDrbg, mbedtls_entropy_func, &entropy, NULL, 0); + if (ret != 0) { + LOGE("gen random seed error, ret=%{public}d", ret); + return ERR_DM_CRYPTO_OPT_FAILED; + } + initFlag = true; + } + + std::lock_guard lock(randomLock_); + ret = mbedtls_ctr_drbg_random(&ctrDrbg, randStr, len); + if (ret != 0) { + LOGE("gen random error, ret=%{public}d", ret); + return ERR_DM_CRYPTO_OPT_FAILED; + } + return DM_OK; +} + +int32_t CryptoMgr::DecryptMessage(const std::string &inputMsg, std::string &outputMsg) +{ + const uint32_t inputMsgBytesLen = inputMsg.length() / HEX_TO_UINT8; + unsigned char inputMsgBytsTemp[inputMsgBytesLen]; + if (memset_s(inputMsgBytsTemp, inputMsgBytesLen, 0, inputMsgBytesLen) != DM_OK) { + LOGE("memset_s failed."); + return ERR_DM_CRYPTO_OPT_FAILED; + } + Crypto::ConvertHexStringToBytes(inputMsgBytsTemp, inputMsgBytesLen, + reinterpret_cast(inputMsg.c_str()), inputMsg.length()); + std::lock_guard lock(sessionKeyMtx_); + AesGcmCipherKey cipherKey = {.keyLen = sessionKey_.keyLen}; + if (memcpy_s(cipherKey.key, SESSION_KEY_LENGTH, sessionKey_.key, sessionKey_.keyLen) != EOK) { + LOGE("set key fail"); + return ERR_DM_CRYPTO_OPT_FAILED; + } + + uint32_t outLen = inputMsgBytesLen - OVERHEAD_LEN + 1; /* for '\0' */ + unsigned char *outData = (unsigned char *)calloc(outLen, sizeof(unsigned char)); + + int32_t ret = DoDecryptData(&cipherKey, inputMsgBytsTemp, + static_cast(inputMsg.length() / HEX_TO_UINT8), outData, &outLen); + (void)memset_s(&cipherKey, sizeof(AesGcmCipherKey), 0, sizeof(AesGcmCipherKey)); + if (ret != DM_OK) { + LOGE("SoftBusDecryptDataWithSeq fail=%{public}d", ret); + return ERR_DM_CRYPTO_OPT_FAILED; + } + outputMsg.clear(); + outputMsg.assign(reinterpret_cast(outData), outLen); + free(outData); + outData = nullptr; + return DM_OK; +} + +int32_t CryptoMgr::MbedAesGcmDecrypt(const AesGcmCipherKey *cipherKey, const unsigned char *cipherText, + uint32_t cipherTextSize, unsigned char *plain, uint32_t plainLen) +{ + if ((cipherKey == NULL) || (cipherText == NULL) || (cipherTextSize <= OVERHEAD_LEN) || plain == NULL || + (plainLen < cipherTextSize - OVERHEAD_LEN)) { + LOGE("Decrypt invalid para"); + return ERR_DM_CRYPTO_PARA_INVALID; + } + + mbedtls_gcm_context aesContext; + mbedtls_gcm_init(&aesContext); + int32_t ret = + mbedtls_gcm_setkey(&aesContext, MBEDTLS_CIPHER_ID_AES, cipherKey->key, cipherKey->keyLen * KEY_BITS_UNIT); + if (ret != 0) { + LOGE("Decrypt mbedtls_gcm_setkey fail."); + mbedtls_gcm_free(&aesContext); + return ERR_DM_CRYPTO_OPT_FAILED; + } + + int32_t actualPlainLen = (int32_t)(cipherTextSize - OVERHEAD_LEN); + ret = mbedtls_gcm_auth_decrypt(&aesContext, cipherTextSize - OVERHEAD_LEN, cipherKey->iv, GCM_IV_LEN, NULL, 0, + cipherText + actualPlainLen + GCM_IV_LEN, TAG_LEN, cipherText + GCM_IV_LEN, plain); + if (ret != 0) { + LOGE("[TRANS] Decrypt mbedtls_gcm_auth_decrypt fail. ret=%{public}d", ret); + mbedtls_gcm_free(&aesContext); + return ERR_DM_CRYPTO_OPT_FAILED; + } + + mbedtls_gcm_free(&aesContext); + return actualPlainLen; +} + +int32_t CryptoMgr::DoDecryptData(AesGcmCipherKey *cipherKey, const unsigned char *input, uint32_t inLen, + unsigned char *decryptData, uint32_t *decryptLen) +{ + if (cipherKey == NULL || input == NULL || inLen < GCM_IV_LEN || decryptData == NULL || decryptLen == NULL) { + return ERR_DM_CRYPTO_PARA_INVALID; + } + + if (memcpy_s(cipherKey->iv, sizeof(cipherKey->iv), input, GCM_IV_LEN) != EOK) { + LOGE("copy iv failed."); + return ERR_DM_CRYPTO_OPT_FAILED; + } + uint32_t outLen = inLen - OVERHEAD_LEN; + int32_t result = MbedAesGcmDecrypt(cipherKey, input, inLen, decryptData, outLen); + if (result <= 0) { + return ERR_DM_CRYPTO_OPT_FAILED; + } + *decryptLen = (uint32_t)result; + return DM_OK; +} + +int32_t CryptoMgr::SaveSessionKey(const uint8_t *sessionKey, const uint32_t keyLen) +{ + if (keyLen > MAX_SESSION_KEY_LENGTH) { + LOGE("SessionKey too long, len: %{public}d", keyLen); + return ERR_DM_SAVE_SESSION_KEY_FAILED; + } + + ClearSessionKey(); + { + std::lock_guard lock(sessionKeyMtx_); + sessionKey_.key = (uint8_t*)calloc(keyLen, sizeof(uint8_t)); + sessionKey_.keyLen = keyLen; + } + return DM_OK; +} + +void CryptoMgr::ClearSessionKey() +{ + std::lock_guard lock(sessionKeyMtx_); + if (sessionKey_.key != nullptr) { + (void)memset_s(sessionKey_.key, sessionKey_.keyLen, 0, sessionKey_.keyLen); + free(sessionKey_.key); + sessionKey_.key = nullptr; + sessionKey_.keyLen = 0; + } +} +} // namespace DistributedHardware +} // namespace OHOS \ No newline at end of file diff --git a/utils/include/crypto/dm_crypto.h b/utils/include/crypto/dm_crypto.h index 52d6f2badffce223177b9f984a803468d1ef99f0..c30eb32c77d051ee83853c20a83eed5a541f3cb9 100644 --- a/utils/include/crypto/dm_crypto.h +++ b/utils/include/crypto/dm_crypto.h @@ -34,6 +34,8 @@ public: static std::string GetSecSalt(); static std::string GetHashWithSalt(const std::string &text, const std::string &salt); static int32_t GetAccountIdHash(const std::string &accountId, unsigned char *accountIdHash); + static int32_t ConvertBytesToHexString(char *outBuf, uint32_t outBufLen, + const unsigned char *inBuf, uint32_t inLen); #if !(defined(__LITEOS_M__) || defined(LITE_DEVICE)) static int32_t ConvertUdidHashToAnoyAndSave(const std::string &appId, const std::string &udidHash, DmKVValue &kvValue); diff --git a/utils/src/crypto/dm_crypto.cpp b/utils/src/crypto/dm_crypto.cpp index 59bf08e3c1f093a96591b45b3c9eb8821d67616a..473fd4ec2ce67522d73bfc37a4dd249859b81680 100644 --- a/utils/src/crypto/dm_crypto.cpp +++ b/utils/src/crypto/dm_crypto.cpp @@ -63,7 +63,7 @@ void DmGenerateStrHash(const void *data, size_t dataSize, unsigned char *outBuf, SHA256_Final(&outBuf[startIndex], &ctx); } -int32_t ConvertBytesToHexString(char *outBuf, uint32_t outBufLen, const unsigned char *inBuf, +int32_t Crypto::ConvertBytesToHexString(char *outBuf, uint32_t outBufLen, const unsigned char *inBuf, uint32_t inLen) { if ((outBuf == nullptr) || (inBuf == nullptr) || (outBufLen < HexifyLen(inLen))) {