已开启
feat(home_base): SPEKE安全认证 DB数据存储 #26
祝你好运创建于 19 天前
feat(home_base): SPEKE安全认证 DB数据存储 #26
已开启
共 97 个文件变更+9265-50
| @@ -0,0 +1,137 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | +namespace OHOS { | ||
| 23 | +namespace IotcManagement { | ||
| 24 | + | ||
| 25 | +IotDeviceInfoCache& IotDeviceInfoCache::GetInstance() | ||
| 26 | +{ | ||
| 27 | + static IotDeviceInfoCache instance; | ||
| 28 | + return instance; | ||
| 29 | +} | ||
| 30 | + | ||
| 31 | +std::shared_ptr<IotDeviceInfoTable> IotDeviceInfoCache::GetIotDeviceInfo(const std::string& deviceId) | ||
| 32 | +{ | ||
| 33 | + if (deviceId.empty()) { | ||
| 34 | + IOTC_LOGW("IotDeviceInfoCache::GetIotDeviceInfo deviceId is empty"); | ||
| 35 | + return nullptr; | ||
| 36 | + } | ||
| 37 | + | ||
| 38 | + auto it = deviceInfoMap_.find(deviceId); | ||
| 39 | + if (it != deviceInfoMap_.end()) { | ||
| 40 | + return it->second; | ||
| 41 | + } | ||
| 42 | + | ||
| 43 | + auto dbResult = IotDeviceInfoManager::GetIotDeviceInfoFromDB(deviceId); | ||
| 44 | + if (!dbResult) { | ||
| 45 | + IOTC_LOGW("IotDeviceInfoCache::GetIotDeviceInfo db result is null"); | ||
| 46 | + return nullptr; | ||
| 47 | + } | ||
| 48 | + | ||
| 49 | + deviceInfoMap_[deviceId] = dbResult; | ||
| 50 | + return dbResult; | ||
| 51 | +} | ||
| 52 | + | ||
| 53 | +bool IotDeviceInfoCache::UpdateDeviceInfo(const IotDeviceInfoTable& infoTable) | ||
| 54 | +{ | ||
| 55 | + if (infoTable.GetKeyValue().empty()) { | ||
| 56 | + IOTC_LOGW("IotDeviceInfoCache::UpdateDeviceInfo param is invalid"); | ||
| 57 | + return false; | ||
| 58 | + } | ||
| 59 | + | ||
| 60 | + int32_t ret = IotDeviceInfoManager::UpdateDeviceInfo(infoTable); | ||
| 61 | + IOTC_LOGI("IotDeviceInfoCache::UpdateDeviceInfo ret: %{public}d", ret); | ||
| 62 | + if (ret != CommonConstants::COMMON_SUCCESS) { | ||
| 63 | + IOTC_LOGE("IotDeviceInfoCache::UpdateDeviceInfo persist failed; keep existing cache entry"); | ||
| 64 | + return false; | ||
| 65 | + } | ||
| 66 | + | ||
| 67 | + auto newInfo = std::make_shared<IotDeviceInfoTable>(); | ||
| 68 | + newInfo->SetDeviceId(infoTable.GetDeviceId()); | ||
| 69 | + newInfo->SetIotCoapSessionEntity(infoTable.GetIotCoapSessionEntity()); | ||
| 70 | + deviceInfoMap_[infoTable.GetDeviceId()] = newInfo; | ||
| 71 | + return true; | ||
| 72 | +} | ||
| 73 | + | ||
| 74 | +bool IotDeviceInfoCache::DeleteDeviceInfo(const std::string& deviceId) | ||
| 75 | +{ | ||
| 76 | + if (deviceId.empty()) { | ||
| 77 | + IOTC_LOGW("IotDeviceInfoCache::DeleteDeviceInfo deviceId is empty"); | ||
| 78 | + return false; | ||
| 79 | + } | ||
| 80 | + | ||
| 81 | + deviceInfoMap_.erase(deviceId); | ||
| 82 | + IotDeviceInfoManager::DeleteAuthCode(deviceId); | ||
| 83 | + return true; | ||
| 84 | +} | ||
| 85 | + | ||
| 86 | +bool IotDeviceInfoCache::RemoveDeviceCache(const std::string& deviceId) | ||
| 87 | +{ | ||
| 88 | + if (deviceId.empty()) { | ||
| 89 | + IOTC_LOGW("IotDeviceInfoCache::RemoveDeviceCache deviceId is empty"); | ||
| 90 | + return false; | ||
| 91 | + } | ||
| 92 | + | ||
| 93 | + deviceInfoMap_.erase(deviceId); | ||
| 94 | + return true; | ||
| 95 | +} | ||
| 96 | + | ||
| 97 | +bool IotDeviceInfoCache::InvalidateCoapSession(const std::string& deviceId) | ||
| 98 | +{ | ||
| 99 | + auto table = GetIotDeviceInfo(deviceId); | ||
| 100 | + if (!table || !table->GetIotCoapSessionEntity()) { | ||
| 101 | + IOTC_LOGW("IotDeviceInfoCache::InvalidateCoapSession session is unavailable"); | ||
| 102 | + return false; | ||
| 103 | + } | ||
| 104 | + | ||
| 105 | + auto invalidSession = std::make_shared<IotCoapSessionEntity>(); | ||
| 106 | + invalidSession->InitSerializedData(table->GetIotCoapSessionEntity()); | ||
| 107 | + invalidSession->SetSessionId(""); | ||
| 108 | + invalidSession->SetSessionCreateTime(0); | ||
| 109 | + | ||
| 110 | + IotDeviceInfoTable invalidTable; | ||
| 111 | + invalidTable.SetDeviceId(deviceId); | ||
| 112 | + invalidTable.SetIotCoapSessionEntity(invalidSession); | ||
| 113 | + return UpdateDeviceInfo(invalidTable); | ||
| 114 | +} | ||
| 115 | + | ||
| 116 | +void IotDeviceInfoCache::ClearExpirationSession() | ||
| 117 | +{ | ||
| 118 | + auto devices = IotDeviceInfoManager::QueryAllDevice(); | ||
| 119 | + for (const auto& device : devices) { | ||
| 120 | + if (!device) { | ||
| 121 | + continue; | ||
| 122 | + } | ||
| 123 | + auto session = device->GetIotCoapSessionEntity(); | ||
| 124 | + if (session && session->IsSessionKeyExpired()) { | ||
| 125 | + DeleteDeviceInfo(device->GetDeviceId()); | ||
| 126 | + } | ||
| 127 | + } | ||
| 128 | +} | ||
| 129 | + | ||
| 130 | +void IotDeviceInfoCache::DeleteAll() | ||
| 131 | +{ | ||
| 132 | + deviceInfoMap_.clear(); | ||
| 133 | + IotDeviceInfoManager::DeleteAll(); | ||
| 134 | +} | ||
| 135 | + | ||
| 136 | +} // namespace IotcManagement | ||
| 137 | +} // namespace OHOS | ||
| @@ -0,0 +1,59 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | +namespace OHOS { | ||
| 26 | +namespace IotcManagement { | ||
| 27 | + | ||
| 28 | +class IotDeviceInfoCache { | ||
| 29 | +public: | ||
| 30 | + static IotDeviceInfoCache& GetInstance(); | ||
| 31 | + | ||
| 32 | + std::shared_ptr<IotDeviceInfoTable> GetIotDeviceInfo(const std::string& deviceId); | ||
| 33 | + | ||
| 34 | + bool UpdateDeviceInfo(const IotDeviceInfoTable& infoTable); | ||
| 35 | + | ||
| 36 | + bool DeleteDeviceInfo(const std::string& deviceId); | ||
| 37 | + | ||
| 38 | + bool RemoveDeviceCache(const std::string& deviceId); | ||
| 39 | + | ||
| 40 | + bool InvalidateCoapSession(const std::string& deviceId); | ||
| 41 | + | ||
| 42 | + void ClearExpirationSession(); | ||
| 43 | + | ||
| 44 | + void DeleteAll(); | ||
| 45 | + | ||
| 46 | +private: | ||
| 47 | + IotDeviceInfoCache() = default; | ||
| 48 | + ~IotDeviceInfoCache() = default; | ||
| 49 | + | ||
| 50 | + IotDeviceInfoCache(const IotDeviceInfoCache&) = delete; | ||
| 51 | + IotDeviceInfoCache& operator=(const IotDeviceInfoCache&) = delete; | ||
| 52 | + | ||
| 53 | + std::map<std::string, std::shared_ptr<IotDeviceInfoTable>> deviceInfoMap_; | ||
| 54 | +}; | ||
| 55 | + | ||
| 56 | +} // namespace IotcManagement | ||
| 57 | +} // namespace OHOS | ||
| 58 | + | ||
| 59 | + | ||
| @@ -0,0 +1,98 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | +namespace OHOS { | ||
| 22 | +namespace IotcManagement { | ||
| 23 | + | ||
| 24 | +std::shared_ptr<IotDeviceInfoTable> IotDeviceInfoManager::GetIotDeviceInfoFromDB(const std::string& deviceId) | ||
| 25 | +{ | ||
| 26 | + if (deviceId.empty()) { | ||
| 27 | + IOTC_LOGW("IotDeviceInfoManager::GetIotDeviceInfoFromDB deviceId is empty"); | ||
| 28 | + return nullptr; | ||
| 29 | + } | ||
| 30 | + | ||
| 31 | + IotDeviceInfoTable queryTable; | ||
| 32 | + queryTable.SetDeviceId(deviceId); | ||
| 33 | + auto result = IotConnectDB::GetInstance().QueryByKey(queryTable); | ||
| 34 | + if (!result) { | ||
| 35 | + IOTC_LOGW("IotDeviceInfoManager::GetIotDeviceInfoFromDB query result is null"); | ||
| 36 | + return nullptr; | ||
| 37 | + } | ||
| 38 | + | ||
| 39 | + return std::dynamic_pointer_cast<IotDeviceInfoTable>(result); | ||
| 40 | +} | ||
| 41 | + | ||
| 42 | +int32_t IotDeviceInfoManager::UpdateDeviceInfo(const IotDeviceInfoTable& iotDevTable) | ||
| 43 | +{ | ||
| 44 | + if (iotDevTable.GetKeyValue().empty()) { | ||
| 45 | + IOTC_LOGW("IotDeviceInfoManager::UpdateDeviceInfo param is invalid"); | ||
| 46 | + return CommonConstants::COMMON_FAILED; | ||
| 47 | + } | ||
| 48 | + | ||
| 49 | + return IotConnectDB::GetInstance().UpdateByKey(iotDevTable); | ||
| 50 | +} | ||
| 51 | + | ||
| 52 | +std::vector<std::shared_ptr<IotDeviceInfoTable>> IotDeviceInfoManager::QueryAllDevice() | ||
| 53 | +{ | ||
| 54 | + std::vector<std::shared_ptr<IotDeviceInfoTable>> results; | ||
| 55 | + | ||
| 56 | + IotDeviceInfoTable queryTable; | ||
| 57 | + auto iotDevs = IotConnectDB::GetInstance().QueryAll(queryTable); | ||
| 58 | + for (const auto& intent : iotDevs) { | ||
| 59 | + if (!intent) { | ||
| 60 | + continue; | ||
| 61 | + } | ||
| 62 | + auto iotDev = std::dynamic_pointer_cast<IotDeviceInfoTable>(intent); | ||
| 63 | + if (!iotDev) { | ||
| 64 | + continue; | ||
| 65 | + } | ||
| 66 | + if (!iotDev->GetIotCoapSessionEntity()) { | ||
| 67 | + IotDeviceInfoManager::DeleteAuthCode(iotDev->GetDeviceId()); | ||
| 68 | + continue; | ||
| 69 | + } | ||
| 70 | + results.push_back(iotDev); | ||
| 71 | + } | ||
| 72 | + | ||
| 73 | + return results; | ||
| 74 | +} | ||
| 75 | + | ||
| 76 | +void IotDeviceInfoManager::DeleteAll() | ||
| 77 | +{ | ||
| 78 | + IotDeviceInfoTable table; | ||
| 79 | + int32_t ret = IotConnectDB::GetInstance().Clear(table); | ||
| 80 | + if (ret != CommonConstants::COMMON_SUCCESS) { | ||
| 81 | + IOTC_LOGE("IotDeviceInfoManager::DeleteAll clear failed, ret: %{public}d", ret); | ||
| 82 | + } | ||
| 83 | +} | ||
| 84 | + | ||
| 85 | +void IotDeviceInfoManager::DeleteAuthCode(const std::string& deviceId) | ||
| 86 | +{ | ||
| 87 | + if (deviceId.empty()) { | ||
| 88 | + IOTC_LOGW("IotDeviceInfoManager::DeleteAuthCode deviceId is empty"); | ||
| 89 | + return; | ||
| 90 | + } | ||
| 91 | + | ||
| 92 | + IotDeviceInfoTable queryTable; | ||
| 93 | + queryTable.SetDeviceId(deviceId); | ||
| 94 | + IotConnectDB::GetInstance().DeleteByKey(queryTable); | ||
| 95 | +} | ||
| 96 | + | ||
| 97 | +} // namespace IotcManagement | ||
| 98 | +} // namespace OHOS | ||
| @@ -0,0 +1,43 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | +namespace OHOS { | ||
| 25 | +namespace IotcManagement { | ||
| 26 | + | ||
| 27 | +class IotDeviceInfoManager { | ||
| 28 | +public: | ||
| 29 | + static std::shared_ptr<IotDeviceInfoTable> GetIotDeviceInfoFromDB(const std::string& deviceId); | ||
| 30 | + | ||
| 31 | + static int32_t UpdateDeviceInfo(const IotDeviceInfoTable& iotDevTable); | ||
| 32 | + | ||
| 33 | + static std::vector<std::shared_ptr<IotDeviceInfoTable>> QueryAllDevice(); | ||
| 34 | + | ||
| 35 | + static void DeleteAll(); | ||
| 36 | + | ||
| 37 | + static void DeleteAuthCode(const std::string& deviceId); | ||
| 38 | +}; | ||
| 39 | + | ||
| 40 | +} // namespace IotcManagement | ||
| 41 | +} // namespace OHOS | ||
| 42 | + | ||
| 43 | + | ||
| @@ -0,0 +1,76 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | +namespace OHOS { | ||
| 20 | +namespace IotcManagement { | ||
| 21 | + | ||
| 22 | +IotConnectDB::IotConnectDB() | ||
| 23 | +{ | ||
| 24 | + std::shared_ptr<IStorageBase> rdbImpl = std::make_shared<KvStorage<IotDeviceInfoTable>>(); | ||
| 25 | + RegisterStorage(DeviceInfoTable::TABLE_NAME, rdbImpl); | ||
| 26 | +} | ||
| 27 | + | ||
| 28 | +void IotConnectDB::RegisterStorage(const std::string& tableName, std::shared_ptr<IStorageBase> storage) | ||
| 29 | +{ | ||
| 30 | + std::lock_guard<std::mutex> lock(mapMtx_); | ||
| 31 | + storageMap_[tableName] = storage; | ||
| 32 | +} | ||
| 33 | + | ||
| 34 | +std::shared_ptr<IDbEntity> IotConnectDB::QueryByKey(const IDbEntity& dbEntity) | ||
| 35 | +{ | ||
| 36 | + std::lock_guard<std::mutex> lock(mapMtx_); | ||
| 37 | + auto it = storageMap_.find(dbEntity.GetTableName()); | ||
| 38 | + if (it == storageMap_.end()) return nullptr; | ||
| 39 | + return it->second->QueryByKey(dbEntity.GetKeyValue()); | ||
| 40 | +} | ||
| 41 | + | ||
| 42 | +std::vector<std::shared_ptr<IDbEntity>> IotConnectDB::QueryAll(const IDbEntity& dbEntity) | ||
| 43 | +{ | ||
| 44 | + std::lock_guard<std::mutex> lock(mapMtx_); | ||
| 45 | + std::vector<std::shared_ptr<IDbEntity>> empty; | ||
| 46 | + auto it = storageMap_.find(dbEntity.GetTableName()); | ||
| 47 | + if (it == storageMap_.end()) return empty; | ||
| 48 | + return it->second->QueryAll(); | ||
| 49 | +} | ||
| 50 | + | ||
| 51 | +int32_t IotConnectDB::UpdateByKey(const IDbEntity& dbEntity) | ||
| 52 | +{ | ||
| 53 | + std::lock_guard<std::mutex> lock(mapMtx_); | ||
| 54 | + auto it = storageMap_.find(dbEntity.GetTableName()); | ||
| 55 | + if (it == storageMap_.end()) return -1; | ||
| 56 | + return it->second->UpdateByKey(dbEntity); | ||
| 57 | +} | ||
| 58 | + | ||
| 59 | +int32_t IotConnectDB::Clear(const IDbEntity& dbEntity) | ||
| 60 | +{ | ||
| 61 | + std::lock_guard<std::mutex> lock(mapMtx_); | ||
| 62 | + auto it = storageMap_.find(dbEntity.GetTableName()); | ||
| 63 | + if (it == storageMap_.end()) return -1; | ||
| 64 | + return it->second->Clear(dbEntity.GetTableName()); | ||
| 65 | +} | ||
| 66 | + | ||
| 67 | +int32_t IotConnectDB::DeleteByKey(const IDbEntity& dbEntity) | ||
| 68 | +{ | ||
| 69 | + std::lock_guard<std::mutex> lock(mapMtx_); | ||
| 70 | + auto it = storageMap_.find(dbEntity.GetTableName()); | ||
| 71 | + if (it == storageMap_.end()) return -1; | ||
| 72 | + return it->second->DeleteByKey(dbEntity.GetKeyValue()); | ||
| 73 | +} | ||
| 74 | + | ||
| 75 | +} // IotcManagement | ||
| 76 | +} // OHOS | ||
| @@ -0,0 +1,61 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | + | ||
| 26 | +namespace OHOS { | ||
| 27 | +namespace IotcManagement { | ||
| 28 | +class IotConnectDB | ||
| 29 | +{ | ||
| 30 | +public: | ||
| 31 | + static IotConnectDB& GetInstance() | ||
| 32 | + { | ||
| 33 | + static IotConnectDB inst; | ||
| 34 | + return inst; | ||
| 35 | + } | ||
| 36 | + | ||
| 37 | + IotConnectDB(const IotConnectDB&) = delete; | ||
| 38 | + IotConnectDB& operator=(const IotConnectDB&) = delete; | ||
| 39 | + IotConnectDB(IotConnectDB&&) = delete; | ||
| 40 | + IotConnectDB& operator=(IotConnectDB&&) = delete; | ||
| 41 | + | ||
| 42 | + | ||
| 43 | + std::shared_ptr<IDbEntity> QueryByKey(const IDbEntity& dbEntity); | ||
| 44 | + std::vector<std::shared_ptr<IDbEntity>> QueryAll(const IDbEntity& dbEntity); | ||
| 45 | + int32_t UpdateByKey(const IDbEntity& data); | ||
| 46 | + int32_t Clear(const IDbEntity& data); | ||
| 47 | + int32_t DeleteByKey(const IDbEntity& data); | ||
| 48 | + | ||
| 49 | +private: | ||
| 50 | + IotConnectDB(); | ||
| 51 | + ~IotConnectDB() = default; | ||
| 52 | + void RegisterStorage(const std::string& tableName, std::shared_ptr<IStorageBase> storage); | ||
| 53 | + | ||
| 54 | + std::mutex mapMtx_; | ||
| 55 | + std::unordered_map<std::string, std::shared_ptr<IStorageBase>> storageMap_; | ||
| 56 | +}; | ||
| 57 | + | ||
| 58 | +} // IotcManagement | ||
| 59 | +} // OHOS | ||
| 60 | + | ||
| 61 | + | ||
| @@ -0,0 +1,88 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | +namespace OHOS { | ||
| 19 | +namespace IotcManagement { | ||
| 20 | + | ||
| 21 | +template<typename T> | ||
| 22 | +std::shared_ptr<T> RdbStorage<T>::QueryTargetByKey(const std::string& key) | ||
| 23 | +{ | ||
| 24 | + (void)key; | ||
| 25 | + return nullptr; | ||
| 26 | +} | ||
| 27 | + | ||
| 28 | +template<typename T> | ||
| 29 | +std::vector<std::shared_ptr<T>> RdbStorage<T>::QueryTargetAll() | ||
| 30 | +{ | ||
| 31 | + std::vector<std::shared_ptr<T>> emptyList; | ||
| 32 | + return emptyList; | ||
| 33 | +} | ||
| 34 | + | ||
| 35 | +template<typename T> | ||
| 36 | +int32_t RdbStorage<T>::UpdateTargetByKey(const T& data) | ||
| 37 | +{ | ||
| 38 | + (void)data; | ||
| 39 | + return -1; | ||
| 40 | +} | ||
| 41 | + | ||
| 42 | +template<typename T> | ||
| 43 | +std::shared_ptr<IDbEntity> RdbStorage<T>::QueryByKey(const std::string& key) | ||
| 44 | +{ | ||
| 45 | + return QueryTargetByKey(key); | ||
| 46 | +} | ||
| 47 | + | ||
| 48 | +template<typename T> | ||
| 49 | +std::vector<std::shared_ptr<IDbEntity>> RdbStorage<T>::QueryAll() | ||
| 50 | +{ | ||
| 51 | + std::vector<std::shared_ptr<IDbEntity>> res; | ||
| 52 | + auto targetList = QueryTargetAll(); | ||
| 53 | + for (auto& item : targetList) | ||
| 54 | + { | ||
| 55 | + res.push_back(item); | ||
| 56 | + } | ||
| 57 | + return res; | ||
| 58 | +} | ||
| 59 | + | ||
| 60 | +template<typename T> | ||
| 61 | +int32_t RdbStorage<T>::UpdateByKey(const IDbEntity& data) | ||
| 62 | +{ | ||
| 63 | + const T* target = dynamic_cast<const T*>(&data); | ||
| 64 | + if (target == nullptr) | ||
| 65 | + { | ||
| 66 | + return -1; | ||
| 67 | + } | ||
| 68 | + return UpdateTargetByKey(*target); | ||
| 69 | +} | ||
| 70 | + | ||
| 71 | +template<typename T> | ||
| 72 | +int32_t RdbStorage<T>::Clear(const std::string& tableName) | ||
| 73 | +{ | ||
| 74 | + (void)tableName; | ||
| 75 | + return -1; | ||
| 76 | +} | ||
| 77 | + | ||
| 78 | +template<typename T> | ||
| 79 | +int32_t RdbStorage<T>::DeleteByKey(const std::string& key) | ||
| 80 | +{ | ||
| 81 | + (void)key; | ||
| 82 | + return -1; | ||
| 83 | +} | ||
| 84 | + | ||
| 85 | +template class RdbStorage<IotDeviceInfoTable>; | ||
| 86 | + | ||
| 87 | +} // IotcManagement | ||
| 88 | +} // OHOS | ||
| @@ -0,0 +1,45 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | +namespace OHOS { | ||
| 21 | +namespace IotcManagement { | ||
| 22 | + | ||
| 23 | +template<typename T> | ||
| 24 | +class RdbStorage : public IStorageBase | ||
| 25 | +{ | ||
| 26 | +public: | ||
| 27 | + RdbStorage() = default; | ||
| 28 | + | ||
| 29 | + // 实现顶层无模板虚接口,统一对外多态 | ||
| 30 | + std::shared_ptr<IDbEntity> QueryByKey(const std::string& key) override; | ||
| 31 | + std::vector<std::shared_ptr<IDbEntity>> QueryAll() override; | ||
| 32 | + int32_t UpdateByKey(const IDbEntity& data) override; | ||
| 33 | + int32_t Clear(const std::string& tableName) override; | ||
| 34 | + int32_t DeleteByKey(const std::string& key) override; | ||
| 35 | + | ||
| 36 | +private: | ||
| 37 | + // 私有模板专属接口,直接返回泛型T | ||
| 38 | + std::shared_ptr<T> QueryTargetByKey(const std::string& key); | ||
| 39 | + std::vector<std::shared_ptr<T>> QueryTargetAll(); | ||
| 40 | + int32_t UpdateTargetByKey(const T& data); | ||
| 41 | +}; | ||
| 42 | + | ||
| 43 | +} // IotcManagement | ||
| 44 | +} // OHOS | ||
| 45 | + | ||
| @@ -0,0 +1,58 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | +namespace OHOS { | ||
| 23 | +namespace IotcManagement { | ||
| 24 | + | ||
| 25 | +// 实体统一基类 | ||
| 26 | +class IDbEntity | ||
| 27 | +{ | ||
| 28 | +public: | ||
| 29 | + virtual ~IDbEntity() = default; | ||
| 30 | + | ||
| 31 | + virtual std::string GetPrimaryKey() const = 0; | ||
| 32 | + virtual std::string GetKeyValue() const = 0; | ||
| 33 | + | ||
| 34 | + // RDB | ||
| 35 | + virtual std::string GetTableName() const { return ""; } | ||
| 36 | + virtual void ToVBucket(void* bucket) const {} | ||
| 37 | + virtual void FromResultSet(void* rs) {} | ||
| 38 | + | ||
| 39 | + // KV序列化 | ||
| 40 | + virtual std::string Serialize() const { return ""; } | ||
| 41 | + virtual bool Deserialize(const std::string& buf) { return false; } | ||
| 42 | +}; | ||
| 43 | + | ||
| 44 | +class IStorageBase | ||
| 45 | +{ | ||
| 46 | +public: | ||
| 47 | + virtual ~IStorageBase() = default; | ||
| 48 | + | ||
| 49 | + virtual std::shared_ptr<IDbEntity> QueryByKey(const std::string& key) = 0; | ||
| 50 | + virtual std::vector<std::shared_ptr<IDbEntity>> QueryAll() = 0; | ||
| 51 | + virtual int32_t UpdateByKey(const IDbEntity& data) = 0; | ||
| 52 | + virtual int32_t Clear(const std::string& tableOrGroup) = 0; | ||
| 53 | + virtual int32_t DeleteByKey(const std::string& key) = 0; | ||
| 54 | +}; | ||
| 55 | +} // IotcManagement | ||
| 56 | +} // OHOS | ||
| 57 | + | ||
| 58 | + | ||
| @@ -0,0 +1,118 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | +namespace OHOS { | ||
| 21 | +namespace IotcManagement { | ||
| 22 | + | ||
| 23 | +IotDeviceInfoTable::IotDeviceInfoTable() | ||
| 24 | +{ | ||
| 25 | +} | ||
| 26 | + | ||
| 27 | +std::string IotDeviceInfoTable::GetTableName() const | ||
| 28 | +{ | ||
| 29 | + return DeviceInfoTable::TABLE_NAME; | ||
| 30 | +} | ||
| 31 | + | ||
| 32 | +std::string IotDeviceInfoTable::GetPrimaryKey() const | ||
| 33 | +{ | ||
| 34 | + return DeviceInfoTable::PRIMARY_KEY; | ||
| 35 | +} | ||
| 36 | + | ||
| 37 | +std::string IotDeviceInfoTable::GetKeyValue() const | ||
| 38 | +{ | ||
| 39 | + return deviceId_; | ||
| 40 | +} | ||
| 41 | + | ||
| 42 | +void IotDeviceInfoTable::SetDeviceId(const std::string& deviceId) | ||
| 43 | +{ | ||
| 44 | + deviceId_ = deviceId; | ||
| 45 | +} | ||
| 46 | + | ||
| 47 | +std::string IotDeviceInfoTable::GetDeviceId() const | ||
| 48 | +{ | ||
| 49 | + return deviceId_; | ||
| 50 | +} | ||
| 51 | + | ||
| 52 | +void IotDeviceInfoTable::SetIotCoapSessionEntity(std::shared_ptr<IotCoapSessionEntity> session) | ||
| 53 | +{ | ||
| 54 | + session_ = session; | ||
| 55 | +} | ||
| 56 | + | ||
| 57 | +std::shared_ptr<IotCoapSessionEntity> IotDeviceInfoTable::GetIotCoapSessionEntity() const | ||
| 58 | +{ | ||
| 59 | + return session_; | ||
| 60 | +} | ||
| 61 | + | ||
| 62 | +std::string IotDeviceInfoTable::Serialize() const | ||
| 63 | +{ | ||
| 64 | + IotcJsonObject* rootJson = IotcJsonObject::CreateObject(); | ||
| 65 | + if (rootJson == nullptr || rootJson->GetJsonObject() == nullptr) { | ||
| 66 | + IOTC_LOGE("create json object fail"); | ||
| 67 | + return ""; | ||
| 68 | + } | ||
| 69 | + | ||
| 70 | + rootJson->AddString2Obj("deviceId", deviceId_); | ||
| 71 | + IotcJsonObject* sessionJson = nullptr; | ||
| 72 | + if (session_ != nullptr) { | ||
| 73 | + std::string buf = session_->Serialize(); | ||
| 74 | + sessionJson = IotcJsonObject::Parse(buf); | ||
| 75 | + if (sessionJson == nullptr || sessionJson->GetJsonObject() == nullptr) { | ||
| 76 | + IOTC_LOGE("create session json object fail"); | ||
| 77 | + rootJson->DeleteJson(); | ||
| 78 | + delete rootJson; | ||
| 79 | + return ""; | ||
| 80 | + } | ||
| 81 | + rootJson->AddItem2Obj("session", *sessionJson); | ||
| 82 | + } | ||
| 83 | + std::string jsonStr = rootJson->Print2String(); | ||
| 84 | + rootJson->DeleteJson(); | ||
| 85 | + delete rootJson; | ||
| 86 | + delete sessionJson; | ||
| 87 | + return jsonStr; | ||
| 88 | +} | ||
| 89 | + | ||
| 90 | +bool IotDeviceInfoTable::Deserialize(const std::string& buf) | ||
| 91 | +{ | ||
| 92 | + if (buf.empty()) { | ||
| 93 | + IOTC_LOGE("buf is empty"); | ||
| 94 | + return false; | ||
| 95 | + } | ||
| 96 | + | ||
| 97 | + IotcJsonObject* rootJson = IotcJsonObject::Parse(buf); | ||
| 98 | + if (rootJson == nullptr || rootJson->GetJsonObject() == nullptr) { | ||
| 99 | + IOTC_LOGE("parse json fail"); | ||
| 100 | + return false; | ||
| 101 | + } | ||
| 102 | + | ||
| 103 | + deviceId_ = rootJson->GetString("deviceId"); | ||
| 104 | + | ||
| 105 | + IotcJsonObject* sessionJson = rootJson->GetObj("session"); | ||
| 106 | + if (sessionJson != nullptr && sessionJson->GetJsonObject() != nullptr) { | ||
| 107 | + session_ = std::make_shared<IotCoapSessionEntity>(); | ||
| 108 | + std::string buf = sessionJson->Print2String(); | ||
| 109 | + session_->Deserialize(buf); | ||
| 110 | + } | ||
| 111 | + | ||
| 112 | + rootJson->DeleteJson(); | ||
| 113 | + delete rootJson; | ||
| 114 | + delete sessionJson; | ||
| 115 | + return true; | ||
| 116 | +} | ||
| 117 | +} // namespace IotcManagement | ||
| 118 | +} // namespace OHOS | ||
| @@ -0,0 +1,62 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | +namespace OHOS { | ||
| 25 | +namespace IotcManagement { | ||
| 26 | + | ||
| 27 | +namespace DeviceInfoTable { | ||
| 28 | +constexpr const char* TABLE_NAME = "iot_device_info"; | ||
| 29 | +constexpr const char* PRIMARY_KEY = "deviceId"; | ||
| 30 | +} | ||
| 31 | + | ||
| 32 | +class IotDeviceInfoTable : public IDbEntity { | ||
| 33 | +public: | ||
| 34 | + IotDeviceInfoTable(); | ||
| 35 | + ~IotDeviceInfoTable() = default; | ||
| 36 | + | ||
| 37 | + std::string GetTableName() const override; | ||
| 38 | + | ||
| 39 | + std::string GetPrimaryKey() const override; | ||
| 40 | + | ||
| 41 | + std::string GetKeyValue() const override; | ||
| 42 | + | ||
| 43 | + std::string Serialize() const override; | ||
| 44 | + | ||
| 45 | + bool Deserialize(const std::string& buf) override; | ||
| 46 | + | ||
| 47 | + std::string GetDeviceId() const; | ||
| 48 | + | ||
| 49 | + void SetDeviceId(const std::string& deviceId); | ||
| 50 | + | ||
| 51 | + std::shared_ptr<IotCoapSessionEntity> GetIotCoapSessionEntity() const; | ||
| 52 | + | ||
| 53 | + void SetIotCoapSessionEntity(std::shared_ptr<IotCoapSessionEntity> session); | ||
| 54 | +private: | ||
| 55 | + std::string deviceId_; | ||
| 56 | + std::shared_ptr<IotCoapSessionEntity> session_; | ||
| 57 | +}; | ||
| 58 | + | ||
| 59 | +} // namespace IotcManagement | ||
| 60 | +} // namespace OHOS | ||
| 61 | + | ||
| 62 | + | ||
| @@ -0,0 +1,45 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | +namespace OHOS { | ||
| 23 | +namespace IotcManagement { | ||
| 24 | + | ||
| 25 | +class SpekeMessageCryptor { | ||
| 26 | +public: | ||
| 27 | + virtual ~SpekeMessageCryptor() = default; | ||
| 28 | + | ||
| 29 | + /** | ||
| 30 | + * 解密接口:输入密文,返回明文。 | ||
| 31 | + */ | ||
| 32 | + virtual std::vector<uint8_t> DecryptData(const std::vector<uint8_t>& data) = 0; | ||
| 33 | + | ||
| 34 | + /** | ||
| 35 | + * 加密接口:输入明文,返回密文。 | ||
| 36 | + */ | ||
| 37 | + virtual std::vector<uint8_t> EncryptData(const std::vector<uint8_t>& data) = 0; | ||
| 38 | + | ||
| 39 | + virtual void Clear() = 0; | ||
| 40 | +}; | ||
| 41 | + | ||
| 42 | +} // namespace IotcManagement | ||
| 43 | +} // namespace OHOS | ||
| 44 | + | ||
| 45 | + | ||
| @@ -0,0 +1,37 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | +namespace OHOS { | ||
| 23 | +namespace IotcManagement { | ||
| 24 | + | ||
| 25 | +class SpekeMessageHmacor { | ||
| 26 | +public: | ||
| 27 | + virtual ~SpekeMessageHmacor() = default; | ||
| 28 | + | ||
| 29 | + virtual std::vector<uint8_t> Hmac(const std::vector<uint8_t>& data) = 0; | ||
| 30 | + | ||
| 31 | + virtual void Clear() = 0; | ||
| 32 | +}; | ||
| 33 | + | ||
| 34 | +} // namespace IotcManagement | ||
| 35 | +} // namespace OHOS | ||
| 36 | + | ||
| 37 | + | ||
| @@ -0,0 +1,300 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | +namespace OHOS { | ||
| 24 | +namespace IotcManagement { | ||
| 25 | + | ||
| 26 | +SpekeNegotiateAdapter::SpekeNegotiateAdapter(std::shared_ptr<SpekeTransferLayer> transferLayer, int32_t protocolType) | ||
| 27 | + : mSessionId_(""), mDevicePin_(""), mDeviceId_(""), | ||
| 28 | + mTransferLayer_(transferLayer), mResultCallback_(nullptr), | ||
| 29 | + securityCipher_(nullptr), mProtocolType_(protocolType), | ||
| 30 | + mProtocolVersion_(CommonConstants::PROTOCOL_VERSION_V1) | ||
| 31 | +{ | ||
| 32 | +} | ||
| 33 | + | ||
| 34 | +SpekeNegotiateAdapter::~SpekeNegotiateAdapter() | ||
| 35 | +{ | ||
| 36 | + std::shared_ptr<SecurityCipher> securityCipher; | ||
| 37 | + { | ||
| 38 | + std::lock_guard<std::mutex> lock(stateMutex_); | ||
| 39 | + securityCipher = std::move(securityCipher_); | ||
| 40 | + } | ||
| 41 | + if (securityCipher) { | ||
| 42 | + E2eSecurityApi::DestorySpeke(securityCipher); | ||
| 43 | + } | ||
| 44 | +} | ||
| 45 | + | ||
| 46 | +void SpekeNegotiateAdapter::StartSpekeNegotiate(std::shared_ptr<SpekeRequest> spekeRequest, | ||
| 47 | + std::shared_ptr<ResultCallback> callback) | ||
| 48 | +{ | ||
| 49 | + if (stopped_.load()) { | ||
| 50 | + IOTC_LOGW("SpekeNegotiateAdapter::StartSpekeNegotiate already stopped"); | ||
| 51 | + return; | ||
| 52 | + } | ||
| 53 | + if (!callback) { | ||
| 54 | + IOTC_LOGW("SpekeNegotiateAdapter::StartSpekeNegotiate callback is null"); | ||
| 55 | + return; | ||
| 56 | + } | ||
| 57 | + | ||
| 58 | + if (!spekeRequest) { | ||
| 59 | + IOTC_LOGW("SpekeNegotiateAdapter::StartSpekeNegotiate spekeRequest is null"); | ||
| 60 | + callback->OnFailure(CommonConstants::COMMON_FAILED); | ||
| 61 | + return; | ||
| 62 | + } | ||
| 63 | + | ||
| 64 | + IOTC_LOGI("SpekeNegotiateAdapter::StartSpekeNegotiate"); | ||
| 65 | + | ||
| 66 | + mDevicePin_ = spekeRequest->GetPinCode(); | ||
| 67 | + mDeviceId_ = spekeRequest->GetDeviceId(); | ||
| 68 | + mProtocolVersion_ = spekeRequest->GetProtocolVersion(); | ||
| 69 | + mResultCallback_ = callback; | ||
| 70 | + | ||
| 71 | + StartBindDevice(); | ||
| 72 | +} | ||
| 73 | + | ||
| 74 | +void SpekeNegotiateAdapter::StopSpekeNegotiate() | ||
| 75 | +{ | ||
| 76 | + IOTC_LOGI("SpekeNegotiateAdapter::StopSpekeNegotiate protocolType=%{public}d", mProtocolType_); | ||
| 77 | + stopped_.store(true); | ||
| 78 | + terminalNotified_.store(true); | ||
| 79 | + | ||
| 80 | + std::string sessionId; | ||
| 81 | + std::shared_ptr<SecurityCipher> securityCipher; | ||
| 82 | + { | ||
| 83 | + std::lock_guard<std::mutex> lock(stateMutex_); | ||
| 84 | + sessionId = std::move(mSessionId_); | ||
| 85 | + securityCipher = std::move(securityCipher_); | ||
| 86 | + } | ||
| 87 | + cancelPending_.store(sessionId.empty()); | ||
| 88 | + if (!sessionId.empty()) { | ||
| 89 | + E2eSecurityApi::CancelNegotiateSpeke(sessionId, mProtocolType_); | ||
| 90 | + } | ||
| 91 | + if (securityCipher) { | ||
| 92 | + E2eSecurityApi::DestorySpeke(securityCipher); | ||
| 93 | + } | ||
| 94 | +} | ||
| 95 | + | ||
| 96 | +std::vector<uint8_t> SpekeNegotiateAdapter::EncryptData(const std::vector<uint8_t>& data) | ||
| 97 | +{ | ||
| 98 | + std::shared_ptr<SecurityCipher> securityCipher; | ||
| 99 | + { | ||
| 100 | + std::lock_guard<std::mutex> lock(stateMutex_); | ||
| 101 | + securityCipher = securityCipher_; | ||
| 102 | + } | ||
| 103 | + if (data.empty() || !securityCipher) { | ||
| 104 | + IOTC_LOGE("SpekeNegotiateAdapter::EncryptData data or securityCipher_ is null"); | ||
| 105 | + return {}; | ||
| 106 | + } | ||
| 107 | + IOTC_LOGI("SpekeNegotiateAdapter::EncryptData"); | ||
| 108 | + return E2eSecurityApi::EncryptData(securityCipher, data); | ||
| 109 | +} | ||
| 110 | + | ||
| 111 | +std::vector<uint8_t> SpekeNegotiateAdapter::DecryptData(const std::vector<uint8_t>& data) | ||
| 112 | +{ | ||
| 113 | + std::shared_ptr<SecurityCipher> securityCipher; | ||
| 114 | + { | ||
| 115 | + std::lock_guard<std::mutex> lock(stateMutex_); | ||
| 116 | + securityCipher = securityCipher_; | ||
| 117 | + } | ||
| 118 | + if (data.empty() || !securityCipher) { | ||
| 119 | + IOTC_LOGE("SpekeNegotiateAdapter::DecryptData data or securityCipher_ is null"); | ||
| 120 | + return {}; | ||
| 121 | + } | ||
| 122 | + IOTC_LOGI("SpekeNegotiateAdapter::DecryptData"); | ||
| 123 | + return E2eSecurityApi::DecryptData(securityCipher, data); | ||
| 124 | +} | ||
| 125 | + | ||
| 126 | +std::string SpekeNegotiateAdapter::GetSessionId() const | ||
| 127 | +{ | ||
| 128 | + std::lock_guard<std::mutex> lock(stateMutex_); | ||
| 129 | + return mSessionId_; | ||
| 130 | +} | ||
| 131 | + | ||
| 132 | +void SpekeNegotiateAdapter::StartBindDevice() | ||
| 133 | +{ | ||
| 134 | + IOTC_LOGI("SpekeNegotiateAdapter::StartBindDevice protocolType=%{public}d", mProtocolType_); | ||
| 135 | + if (stopped_.load()) { | ||
| 136 | + return; | ||
| 137 | + } | ||
| 138 | + std::weak_ptr<SpekeNegotiateAdapter> weakThis(shared_from_this()); | ||
| 139 | + auto callback = std::make_shared<SpekeNegotiateCallbackImpl>(); | ||
| 140 | + | ||
| 141 | + callback->onSuccess = [weakThis](std::shared_ptr<SecurityCipher> securityCipher) { | ||
| 142 | + auto self = weakThis.lock(); | ||
| 143 | + if (!self) { | ||
| 144 | + IOTC_LOGW("onSuccess: adapter already destroyed"); | ||
| 145 | + return; | ||
| 146 | + } | ||
| 147 | + if (!securityCipher) { | ||
| 148 | + IOTC_LOGW("SpekeNegotiateCallbackImpl::OnSuccess securityCipher is null"); | ||
| 149 | + if (!self->terminalNotified_.exchange(true) && self->mResultCallback_) { | ||
| 150 | + self->mResultCallback_->OnFailure(CommonConstants::COMMON_FAILED); | ||
| 151 | + } | ||
| 152 | + return; | ||
| 153 | + } | ||
| 154 | + if (self->terminalNotified_.exchange(true)) { | ||
| 155 | + IOTC_LOGW("SpekeNegotiateCallbackImpl::OnSuccess terminal result already notified"); | ||
| 156 | + return; | ||
| 157 | + } | ||
| 158 | + { | ||
| 159 | + std::lock_guard<std::mutex> lock(self->stateMutex_); | ||
| 160 | + self->securityCipher_ = securityCipher; | ||
| 161 | + } | ||
| 162 | + if (self->mResultCallback_) { | ||
| 163 | + IOTC_LOGI("SpekeNegotiateCallbackImpl::OnSuccess callback"); | ||
| 164 | + self->mResultCallback_->OnSuccess(CommonConstants::COMMON_SUCCESS, CommonConstants::EMPTY_STRING); | ||
| 165 | + } | ||
| 166 | + }; | ||
| 167 | + | ||
| 168 | + callback->onFailure = [weakThis](int32_t errorCode, const std::string& errorMessage) { | ||
| 169 | + (void)errorMessage; | ||
| 170 | + IOTC_LOGE("speke onFailure code: %{public}d", errorCode); | ||
| 171 | + auto self = weakThis.lock(); | ||
| 172 | + if (!self) { | ||
| 173 | + IOTC_LOGW("onFailure: adapter already destroyed"); | ||
| 174 | + return; | ||
| 175 | + } | ||
| 176 | + if (self->terminalNotified_.exchange(true)) { | ||
| 177 | + IOTC_LOGW("SpekeNegotiateCallbackImpl::OnFailure terminal result already notified"); | ||
| 178 | + return; | ||
| 179 | + } | ||
| 180 | + if (self->mResultCallback_) { | ||
| 181 | + self->mResultCallback_->OnFailure(errorCode); | ||
| 182 | + } | ||
| 183 | + }; | ||
| 184 | + | ||
| 185 | + callback->toPeerData = [weakThis](const std::string& peerData) { | ||
| 186 | + IOTC_LOGI("SpekeNegotiateCallbackImpl::ToPeerData requestBody len=%{public}zu", peerData.size()); | ||
| 187 | + auto self = weakThis.lock(); | ||
| 188 | + if (!self) { | ||
| 189 | + IOTC_LOGW("onFailure: adapter already destroyed"); | ||
| 190 | + return; | ||
| 191 | + } | ||
| 192 | + if (peerData.empty()) { | ||
| 193 | + IOTC_LOGW("SpekeNegotiateCallbackImpl::ToPeerData peerData is empty"); | ||
| 194 | + return; | ||
| 195 | + } | ||
| 196 | + self->TransferLayerSend(peerData); | ||
| 197 | + }; | ||
| 198 | + std::string sessionId = StartNegotiateSpeke(mProtocolType_, mDevicePin_, mDeviceId_, callback, mProtocolVersion_); | ||
| 199 | + { | ||
| 200 | + std::lock_guard<std::mutex> lock(stateMutex_); | ||
| 201 | + mSessionId_ = sessionId; | ||
| 202 | + } | ||
| 203 | + if (cancelPending_.exchange(false) && !sessionId.empty()) { | ||
| 204 | + E2eSecurityApi::CancelNegotiateSpeke(sessionId, mProtocolType_); | ||
| 205 | + std::lock_guard<std::mutex> lock(stateMutex_); | ||
| 206 | + mSessionId_.clear(); | ||
| 207 | + } | ||
| 208 | + if (sessionId.empty()) { | ||
| 209 | + IOTC_LOGE("SpekeNegotiateAdapter::StartBindDevice start negotiate failed"); | ||
| 210 | + if (!terminalNotified_.exchange(true) && mResultCallback_) { | ||
| 211 | + mResultCallback_->OnFailure(CommonConstants::COMMON_FAILED); | ||
| 212 | + } | ||
| 213 | + } | ||
| 214 | +} | ||
| 215 | + | ||
| 216 | +std::string SpekeNegotiateAdapter::StartNegotiateSpeke(int32_t spekeType, const std::string& pinCode, | ||
| 217 | + const std::string& deviceId, std::shared_ptr<SpekeNegotiateCallback> negotiateCallback, | ||
| 218 | + uint32_t protocolVersion) | ||
| 219 | +{ | ||
| 220 | + IOTC_LOGI("SpekeNegotiateAdapter::StartNegotiateSpeke ver=%{public}u", protocolVersion); | ||
| 221 | + return E2eSecurityApi::StartNegotiateSpeke(pinCode, deviceId, negotiateCallback, spekeType, | ||
| 222 | + protocolVersion); | ||
| 223 | +} | ||
| 224 | + | ||
| 225 | +void SpekeNegotiateAdapter::TransferLayerSend(const std::string& requestBody) | ||
| 226 | +{ | ||
| 227 | + if (stopped_.load()) { | ||
| 228 | + return; | ||
| 229 | + } | ||
| 230 | + std::weak_ptr<SpekeNegotiateAdapter> weakThis(shared_from_this()); | ||
| 231 | + auto wrapper = std::make_shared<TransferResponseCallbackImpl>(); | ||
| 232 | + wrapper->onResponse = [weakThis](const std::string& response) { | ||
| 233 | + IOTC_LOGI("SpekeNegotiateAdapter::TransferLayerSend response length=%{public}zu", response.length()); | ||
| 234 | + auto self = weakThis.lock(); | ||
| 235 | + if (!self) { | ||
| 236 | + IOTC_LOGW("onFailure: adapter already destroyed"); | ||
| 237 | + return; | ||
| 238 | + } | ||
| 239 | + if (self->stopped_.load()) { | ||
| 240 | + return; | ||
| 241 | + } | ||
| 242 | + if (response.empty() || self->mDeviceId_.empty()) { | ||
| 243 | + IOTC_LOGW("SpekeNegotiateAdapter::TransferLayerSend params invalid"); | ||
| 244 | + return; | ||
| 245 | + } | ||
| 246 | + self->ProcessReceivedSpekeMsg(response); | ||
| 247 | + }; | ||
| 248 | + wrapper->onFailure = [weakThis](int32_t errorCode) { | ||
| 249 | + auto self = weakThis.lock(); | ||
| 250 | + if (!self) { | ||
| 251 | + IOTC_LOGW("onFailure: adapter already destroyed"); | ||
| 252 | + return; | ||
| 253 | + } | ||
| 254 | + self->ProcessTransferFailure(errorCode); | ||
| 255 | + }; | ||
| 256 | + mTransferLayer_->Send(requestBody, wrapper); | ||
| 257 | +} | ||
| 258 | + | ||
| 259 | +void SpekeNegotiateAdapter::ProcessReceivedSpekeMsg(const std::string& response) | ||
| 260 | +{ | ||
| 261 | + IOTC_LOGI("SpekeNegotiateAdapter::ProcessReceivedSpekeMsg response len=%{public}zu protocolType=%{public}d ver=%{public}u", | ||
| 262 | + response.length(), mProtocolType_, mProtocolVersion_); | ||
| 263 | + | ||
| 264 | + if (!response.empty()) { | ||
| 265 | + E2eSecurityApi::ProcessReceivedSpekeMsg(mDeviceId_, response, mProtocolType_, mProtocolVersion_); | ||
| 266 | + } else { | ||
| 267 | + IOTC_LOGE("SpekeNegotiateAdapter::ProcessReceivedSpekeMsg responseJson is null"); | ||
| 268 | + } | ||
| 269 | +} | ||
| 270 | + | ||
| 271 | +void SpekeNegotiateAdapter::ProcessTransferFailure(int32_t errorCode) | ||
| 272 | +{ | ||
| 273 | + if (errorCode == CommonConstants::COMMON_SUCCESS) { | ||
| 274 | + errorCode = CommonConstants::COMMON_FAILED; | ||
| 275 | + } | ||
| 276 | + if (terminalNotified_.exchange(true)) { | ||
| 277 | + IOTC_LOGW("SpekeNegotiateAdapter::ProcessTransferFailure terminal result already notified"); | ||
| 278 | + return; | ||
| 279 | + } | ||
| 280 | + | ||
| 281 | + std::string sessionId; | ||
| 282 | + { | ||
| 283 | + std::lock_guard<std::mutex> lock(stateMutex_); | ||
| 284 | + sessionId = mSessionId_; | ||
| 285 | + if (!sessionId.empty()) { | ||
| 286 | + mSessionId_.clear(); | ||
| 287 | + } | ||
| 288 | + } | ||
| 289 | + if (sessionId.empty()) { | ||
| 290 | + cancelPending_.store(true); | ||
| 291 | + } else { | ||
| 292 | + E2eSecurityApi::CancelNegotiateSpeke(sessionId, mProtocolType_); | ||
| 293 | + } | ||
| 294 | + if (mResultCallback_) { | ||
| 295 | + mResultCallback_->OnFailure(errorCode); | ||
| 296 | + } | ||
| 297 | +} | ||
| 298 | + | ||
| 299 | +} // namespace IotcManagement | ||
| 300 | +} // namespace OHOS | ||
| @@ -0,0 +1,109 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | + | ||
| 26 | + | ||
| 27 | + | ||
| 28 | + | ||
| 29 | + | ||
| 30 | + | ||
| 31 | + | ||
| 32 | + | ||
| 33 | +namespace OHOS { | ||
| 34 | +namespace IotcManagement { | ||
| 35 | + | ||
| 36 | +class SpekeNegotiateAdapter : public std::enable_shared_from_this<SpekeNegotiateAdapter> { | ||
| 37 | +public: | ||
| 38 | + /** | ||
| 39 | + * speke协商构造函数 | ||
| 40 | + * | ||
| 41 | + * @param transferLayer 传输层(coap或者蓝牙) | ||
| 42 | + * @param protocolType speke协商协议类型 | ||
| 43 | + */ | ||
| 44 | + SpekeNegotiateAdapter(std::shared_ptr<SpekeTransferLayer> transferLayer, int32_t protocolType); | ||
| 45 | + | ||
| 46 | + ~SpekeNegotiateAdapter(); | ||
| 47 | + | ||
| 48 | + /** | ||
| 49 | + * 开始speke协商 | ||
| 50 | + * | ||
| 51 | + * @param spekeRequest 协商请求参数 | ||
| 52 | + * @param callback speke协商回调 | ||
| 53 | + */ | ||
| 54 | + void StartSpekeNegotiate(std::shared_ptr<SpekeRequest> spekeRequest, | ||
| 55 | + std::shared_ptr<ResultCallback> callback); | ||
| 56 | + | ||
| 57 | + /** | ||
| 58 | + * 停止speke协商 | ||
| 59 | + */ | ||
| 60 | + void StopSpekeNegotiate(); | ||
| 61 | + | ||
| 62 | + /** | ||
| 63 | + * 加密接口:明文 → 密文。 | ||
| 64 | + */ | ||
| 65 | + std::vector<uint8_t> EncryptData(const std::vector<uint8_t>& data); | ||
| 66 | + | ||
| 67 | + /** | ||
| 68 | + * 解密接口:密文 → 明文。 | ||
| 69 | + */ | ||
| 70 | + std::vector<uint8_t> DecryptData(const std::vector<uint8_t>& data); | ||
| 71 | + | ||
| 72 | + /** | ||
| 73 | + * 获取当前speke SessionId | ||
| 74 | + * | ||
| 75 | + * @return 当前 speke SessionId | ||
| 76 | + */ | ||
| 77 | + std::string GetSessionId() const; | ||
| 78 | + | ||
| 79 | +private: | ||
| 80 | + void StartBindDevice(); | ||
| 81 | + | ||
| 82 | + void TransferLayerSend(const std::string& requestBody); | ||
| 83 | + | ||
| 84 | + void ProcessReceivedSpekeMsg(const std::string& response); | ||
| 85 | + | ||
| 86 | + void ProcessTransferFailure(int32_t errorCode); | ||
| 87 | + | ||
| 88 | + std::string StartNegotiateSpeke(int32_t spekeType, const std::string& pinCode, | ||
| 89 | + const std::string& deviceId, std::shared_ptr<SpekeNegotiateCallback> negotiateCallback, | ||
| 90 | + uint32_t protocolVersion); | ||
| 91 | + | ||
| 92 | + std::string mSessionId_; | ||
| 93 | + std::string mDevicePin_; | ||
| 94 | + std::string mDeviceId_; | ||
| 95 | + std::shared_ptr<SpekeTransferLayer> mTransferLayer_; | ||
| 96 | + std::shared_ptr<ResultCallback> mResultCallback_; | ||
| 97 | + std::shared_ptr<SecurityCipher> securityCipher_; | ||
| 98 | + int32_t mProtocolType_; | ||
| 99 | + uint32_t mProtocolVersion_; | ||
| 100 | + std::atomic<bool> terminalNotified_ {false}; | ||
| 101 | + std::atomic<bool> cancelPending_ {false}; | ||
| 102 | + std::atomic<bool> stopped_ {false}; | ||
| 103 | + mutable std::mutex stateMutex_; | ||
| 104 | +}; | ||
| 105 | + | ||
| 106 | +} // namespace IotcManagement | ||
| 107 | +} // namespace OHOS | ||
| 108 | + | ||
| 109 | + | ||
| @@ -0,0 +1,138 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | +namespace OHOS { | ||
| 22 | +namespace IotcManagement { | ||
| 23 | + | ||
| 24 | +SpekeNegotiateManager::SpekeNegotiateManager() | ||
| 25 | + : mSpekeNegotiate_(nullptr) | ||
| 26 | +{ | ||
| 27 | +} | ||
| 28 | + | ||
| 29 | +void SpekeNegotiateManager::Start(std::shared_ptr<SpekeRequest> spekeRequest, | ||
| 30 | + std::shared_ptr<ResultCallback> callback, std::shared_ptr<AdvBleRequest> request) | ||
| 31 | +{ | ||
| 32 | + uint64_t generation = 0; | ||
| 33 | + { | ||
| 34 | + std::lock_guard<std::mutex> lock(mutex_); | ||
| 35 | + generation = generation_; | ||
| 36 | + } | ||
| 37 | + if (!callback) { | ||
| 38 | + IOTC_LOGW("SpekeNegotiateManager::Start callback is null"); | ||
| 39 | + return; | ||
| 40 | + } | ||
| 41 | + | ||
| 42 | + if (!spekeRequest) { | ||
| 43 | + IOTC_LOGW("SpekeNegotiateManager::Start spekeRequest is null"); | ||
| 44 | + callback->OnFailure(CommonConstants::COMMON_FAILED); | ||
| 45 | + return; | ||
| 46 | + } | ||
| 47 | + | ||
| 48 | + std::shared_ptr<SpekeTransferLayer> spekeTransferLayer = SpekeTransferFactory::GetSpekeTransferLayer(spekeRequest, request); | ||
| 49 | + if (!spekeTransferLayer) { | ||
| 50 | + IOTC_LOGW("SpekeNegotiateManager::Start spekeTransferLayer is null"); | ||
| 51 | + callback->OnFailure(CommonConstants::COMMON_FAILED); | ||
| 52 | + return; | ||
| 53 | + } | ||
| 54 | + | ||
| 55 | + auto adapter = std::make_shared<SpekeNegotiateAdapter>(spekeTransferLayer, spekeRequest->GetProtocolType()); | ||
| 56 | + { | ||
| 57 | + std::lock_guard<std::mutex> lock(mutex_); | ||
| 58 | + if (generation != generation_) { | ||
| 59 | + return; | ||
| 60 | + } | ||
| 61 | + mSpekeNegotiate_ = adapter; | ||
| 62 | + } | ||
| 63 | + adapter->StartSpekeNegotiate(spekeRequest, callback); | ||
| 64 | +} | ||
| 65 | + | ||
| 66 | +std::string SpekeNegotiateManager::GetSessionId() const | ||
| 67 | +{ | ||
| 68 | + std::shared_ptr<SpekeNegotiateAdapter> adapter; | ||
| 69 | + { | ||
| 70 | + std::lock_guard<std::mutex> lock(mutex_); | ||
| 71 | + adapter = mSpekeNegotiate_; | ||
| 72 | + } | ||
| 73 | + if (!adapter) { | ||
| 74 | + return ""; | ||
| 75 | + } | ||
| 76 | + return adapter->GetSessionId(); | ||
| 77 | +} | ||
| 78 | + | ||
| 79 | +void SpekeNegotiateManager::Clear() | ||
| 80 | +{ | ||
| 81 | + IOTC_LOGI("SpekeNegotiateManager::Clear"); | ||
| 82 | + | ||
| 83 | + std::shared_ptr<SpekeNegotiateAdapter> adapter; | ||
| 84 | + { | ||
| 85 | + std::lock_guard<std::mutex> lock(mutex_); | ||
| 86 | + ++generation_; | ||
| 87 | + adapter = std::move(mSpekeNegotiate_); | ||
| 88 | + } | ||
| 89 | + if (!adapter) { | ||
| 90 | + IOTC_LOGW("SpekeNegotiateManager::Clear mSpekeNegotiate_ is null"); | ||
| 91 | + return; | ||
| 92 | + } | ||
| 93 | + | ||
| 94 | + adapter->StopSpekeNegotiate(); | ||
| 95 | +} | ||
| 96 | + | ||
| 97 | +std::vector<uint8_t> SpekeNegotiateManager::DecryptData(const std::vector<uint8_t>& data) | ||
| 98 | +{ | ||
| 99 | + if (data.empty()) { | ||
| 100 | + IOTC_LOGW("SpekeNegotiateManager::DecryptData data is null"); | ||
| 101 | + return std::vector<uint8_t>(); | ||
| 102 | + } | ||
| 103 | + | ||
| 104 | + std::shared_ptr<SpekeNegotiateAdapter> adapter; | ||
| 105 | + { | ||
| 106 | + std::lock_guard<std::mutex> lock(mutex_); | ||
| 107 | + adapter = mSpekeNegotiate_; | ||
| 108 | + } | ||
| 109 | + if (!adapter) { | ||
| 110 | + IOTC_LOGW("SpekeNegotiateManager::DecryptData mSpekeNegotiate_ is null"); | ||
| 111 | + return std::vector<uint8_t>(); | ||
| 112 | + } | ||
| 113 | + | ||
| 114 | + return adapter->DecryptData(data); | ||
| 115 | +} | ||
| 116 | + | ||
| 117 | +std::vector<uint8_t> SpekeNegotiateManager::EncryptData(const std::vector<uint8_t>& data) | ||
| 118 | +{ | ||
| 119 | + if (data.empty()) { | ||
| 120 | + IOTC_LOGW("SpekeNegotiateManager::EncryptData data is null"); | ||
| 121 | + return std::vector<uint8_t>(); | ||
| 122 | + } | ||
| 123 | + | ||
| 124 | + std::shared_ptr<SpekeNegotiateAdapter> adapter; | ||
| 125 | + { | ||
| 126 | + std::lock_guard<std::mutex> lock(mutex_); | ||
| 127 | + adapter = mSpekeNegotiate_; | ||
| 128 | + } | ||
| 129 | + if (!adapter) { | ||
| 130 | + IOTC_LOGW("SpekeNegotiateManager::EncryptData mSpekeNegotiate_ is null"); | ||
| 131 | + return std::vector<uint8_t>(); | ||
| 132 | + } | ||
| 133 | + | ||
| 134 | + return adapter->EncryptData(data); | ||
| 135 | +} | ||
| 136 | + | ||
| 137 | +} // namespace IotcManagement | ||
| 138 | +} // namespace OHOS | ||
| @@ -0,0 +1,88 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | + | ||
| 26 | + | ||
| 27 | + | ||
| 28 | + | ||
| 29 | + | ||
| 30 | +namespace OHOS { | ||
| 31 | +namespace IotcManagement { | ||
| 32 | + | ||
| 33 | +class AdvBleRequest; | ||
| 34 | + | ||
| 35 | +class SpekeNegotiateManager : public SpekeMessageCryptor { | ||
| 36 | +public: | ||
| 37 | + SpekeNegotiateManager(); | ||
| 38 | + | ||
| 39 | + ~SpekeNegotiateManager() = default; | ||
| 40 | + | ||
| 41 | + /** | ||
| 42 | + * 开始协商 | ||
| 43 | + * | ||
| 44 | + * @param spekeRequest 协商请求参数 | ||
| 45 | + * @param callback 协商回调, speke 成功或失败时调用 | ||
| 46 | + * @param request 增强蓝牙请求数据(可选) | ||
| 47 | + */ | ||
| 48 | + void Start(std::shared_ptr<SpekeRequest> spekeRequest, std::shared_ptr<ResultCallback> callback, | ||
| 49 | + std::shared_ptr<AdvBleRequest> request = nullptr); | ||
| 50 | + | ||
| 51 | + /** | ||
| 52 | + * 获取当前 speke SessionId | ||
| 53 | + * | ||
| 54 | + * @return 当前 speke SessionId | ||
| 55 | + */ | ||
| 56 | + std::string GetSessionId() const; | ||
| 57 | + | ||
| 58 | + /** | ||
| 59 | + * 停止协商 | ||
| 60 | + */ | ||
| 61 | + void Clear() override; | ||
| 62 | + | ||
| 63 | + /** | ||
| 64 | + * 加密接口 | ||
| 65 | + * | ||
| 66 | + * @param data 待加密数据 | ||
| 67 | + * @return 加密后的数据 | ||
| 68 | + */ | ||
| 69 | + std::vector<uint8_t> DecryptData(const std::vector<uint8_t>& data) override; | ||
| 70 | + | ||
| 71 | + /** | ||
| 72 | + * 解密接口 | ||
| 73 | + * | ||
| 74 | + * @param data 待解密的数据 | ||
| 75 | + * @return 解密后的数据 | ||
| 76 | + */ | ||
| 77 | + std::vector<uint8_t> EncryptData(const std::vector<uint8_t>& data) override; | ||
| 78 | + | ||
| 79 | +private: | ||
| 80 | + std::shared_ptr<SpekeNegotiateAdapter> mSpekeNegotiate_; | ||
| 81 | + mutable std::mutex mutex_; | ||
| 82 | + uint64_t generation_ = 0; | ||
| 83 | +}; | ||
| 84 | + | ||
| 85 | +} // namespace IotcManagement | ||
| 86 | +} // namespace OHOS | ||
| 87 | + | ||
| 88 | + | ||
| @@ -0,0 +1,66 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | +namespace OHOS { | ||
| 24 | +namespace IotcManagement { | ||
| 25 | + | ||
| 26 | +class ResultCallback { | ||
| 27 | +public: | ||
| 28 | + virtual ~ResultCallback() = default; | ||
| 29 | + | ||
| 30 | + /** | ||
| 31 | + * 成功函数 | ||
| 32 | + * | ||
| 33 | + * @param result 响应码 | ||
| 34 | + * @param object 响应数据 | ||
| 35 | + */ | ||
| 36 | + virtual void OnSuccess(int32_t result, const std::string& object) = 0; | ||
| 37 | + | ||
| 38 | + /** | ||
| 39 | + * 失败函数 | ||
| 40 | + * | ||
| 41 | + * @param errorCode 错误码 | ||
| 42 | + */ | ||
| 43 | + virtual void OnFailure(int32_t errorCode) = 0; | ||
| 44 | +}; | ||
| 45 | + | ||
| 46 | +struct SpekeResultCallbackImpl : public ResultCallback { | ||
| 47 | + std::function<void(int32_t, const std::string&)> onSuccess; | ||
| 48 | + std::function<void(int32_t)> onFailure; | ||
| 49 | + | ||
| 50 | + void OnSuccess(int32_t result, const std::string& object) override { | ||
| 51 | + if (onSuccess) { | ||
| 52 | + onSuccess(result, object); | ||
| 53 | + } | ||
| 54 | + } | ||
| 55 | + | ||
| 56 | + void OnFailure(int32_t errorCode) override { | ||
| 57 | + if (onFailure) { | ||
| 58 | + onFailure(errorCode); | ||
| 59 | + } | ||
| 60 | + } | ||
| 61 | +}; | ||
| 62 | + | ||
| 63 | +} // namespace IotcManagement | ||
| 64 | +} // namespace OHOS | ||
| 65 | + | ||
| 66 | + | ||
| @@ -0,0 +1,92 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | +namespace OHOS { | ||
| 26 | +namespace IotcManagement { | ||
| 27 | + | ||
| 28 | +/** | ||
| 29 | + * Speke协商回调接口 | ||
| 30 | + */ | ||
| 31 | +class SpekeNegotiateCallback { | ||
| 32 | +public: | ||
| 33 | + virtual ~SpekeNegotiateCallback() = default; | ||
| 34 | + | ||
| 35 | + /** | ||
| 36 | + * speke协商成功函数 | ||
| 37 | + * | ||
| 38 | + * @param securityCipher speke协商生成的对象 | ||
| 39 | + */ | ||
| 40 | + virtual void OnSuccess(std::shared_ptr<SecurityCipher> securityCipher) = 0; | ||
| 41 | + | ||
| 42 | + /** | ||
| 43 | + * speke协商失败函数 | ||
| 44 | + * | ||
| 45 | + * @param errorCode 协商错误码 | ||
| 46 | + * @param errorMessage 协商错误信息 | ||
| 47 | + */ | ||
| 48 | + virtual void OnFailure(int32_t errorCode, const std::string& errorMessage) = 0; | ||
| 49 | + | ||
| 50 | + /** | ||
| 51 | + * speke发送给对端数据函数 | ||
| 52 | + * | ||
| 53 | + * @param peerData 送给对端的数据 | ||
| 54 | + */ | ||
| 55 | + virtual void ToPeerData(const std::string& peerData) = 0; | ||
| 56 | +}; | ||
| 57 | + | ||
| 58 | +struct SpekeNegotiateCallbackImpl : public SpekeNegotiateCallback { | ||
| 59 | + std::function<void(std::shared_ptr<SecurityCipher>)> onSuccess; | ||
| 60 | + std::function<void(int32_t, const std::string&)> onFailure; | ||
| 61 | + std::function<void(const std::string&)> toPeerData; | ||
| 62 | + | ||
| 63 | + void OnSuccess(std::shared_ptr<SecurityCipher> securityCipher) override { | ||
| 64 | + if (onSuccess) { | ||
| 65 | + onSuccess(securityCipher); | ||
| 66 | + } | ||
| 67 | + } | ||
| 68 | + | ||
| 69 | + void OnFailure(int32_t errorCode, const std::string& errorMessage) override { | ||
| 70 | + if (onFailure) { | ||
| 71 | + onFailure(errorCode, errorMessage); | ||
| 72 | + } | ||
| 73 | + } | ||
| 74 | + | ||
| 75 | + void ToPeerData(const std::string& peerData) override { | ||
| 76 | + if (toPeerData) { | ||
| 77 | + toPeerData(peerData); | ||
| 78 | + } | ||
| 79 | + } | ||
| 80 | +}; | ||
| 81 | + | ||
| 82 | +class SpekeNegotiateCallbackEmpty : public SpekeNegotiateCallback { | ||
| 83 | +public: | ||
| 84 | + void OnSuccess(std::shared_ptr<SecurityCipher>) override {} | ||
| 85 | + void OnFailure(int32_t, const std::string&) override {} | ||
| 86 | + void ToPeerData(const std::string&) override {} | ||
| 87 | +}; | ||
| 88 | + | ||
| 89 | +} // namespace IotcManagement | ||
| 90 | +} // namespace OHOS | ||
| 91 | + | ||
| 92 | + | ||
| @@ -0,0 +1,52 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | +namespace OHOS { | ||
| 20 | +namespace IotcManagement { | ||
| 21 | + | ||
| 22 | +std::string ConfiguredVersionInfo::defaultVersion_; | ||
| 23 | +std::string ConfiguredVersionInfo::minVersion_; | ||
| 24 | +std::vector<std::string> ConfiguredVersionInfo::supportVersions_; | ||
| 25 | + | ||
| 26 | +void ConfiguredVersionInfo::Init() | ||
| 27 | +{ | ||
| 28 | + supportVersions_.clear(); | ||
| 29 | + supportVersions_.push_back(CommonConstants::VERSION); | ||
| 30 | + supportVersions_.push_back(CommonConstants::VERSION_V2); | ||
| 31 | + // 默认版本与最低版本保持 V1 以兼容未升级的设备;支持列表包含 V2。 | ||
| 32 | + defaultVersion_ = CommonConstants::VERSION; | ||
| 33 | + minVersion_ = CommonConstants::VERSION; | ||
| 34 | +} | ||
| 35 | + | ||
| 36 | +std::string ConfiguredVersionInfo::GetDefaultVersion() | ||
| 37 | +{ | ||
| 38 | + return defaultVersion_; | ||
| 39 | +} | ||
| 40 | + | ||
| 41 | +std::vector<std::string> ConfiguredVersionInfo::GetSupportVersions() | ||
| 42 | +{ | ||
| 43 | + return supportVersions_; | ||
| 44 | +} | ||
| 45 | + | ||
| 46 | +std::string ConfiguredVersionInfo::GetMinVersion() | ||
| 47 | +{ | ||
| 48 | + return minVersion_; | ||
| 49 | +} | ||
| 50 | + | ||
| 51 | +} // namespace IotcManagement | ||
| 52 | +} // namespace OHOS | ||
| @@ -0,0 +1,45 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | +namespace OHOS { | ||
| 24 | +namespace IotcManagement { | ||
| 25 | + | ||
| 26 | +class ConfiguredVersionInfo { | ||
| 27 | +public: | ||
| 28 | + static void Init(); | ||
| 29 | + | ||
| 30 | + static std::string GetDefaultVersion(); | ||
| 31 | + | ||
| 32 | + static std::vector<std::string> GetSupportVersions(); | ||
| 33 | + | ||
| 34 | + static std::string GetMinVersion(); | ||
| 35 | + | ||
| 36 | +private: | ||
| 37 | + static std::string defaultVersion_; | ||
| 38 | + static std::string minVersion_; | ||
| 39 | + static std::vector<std::string> supportVersions_; | ||
| 40 | +}; | ||
| 41 | + | ||
| 42 | +} // namespace IotcManagement | ||
| 43 | +} // namespace OHOS | ||
| 44 | + | ||
| 45 | + | ||
| @@ -0,0 +1,62 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | +namespace OHOS { | ||
| 19 | +namespace IotcManagement { | ||
| 20 | + | ||
| 21 | +ConfirmParams::ConfirmParams() | ||
| 22 | + : confirmation_(INVALID_NUMBER), pin_(CommonConstants::INVALID_STRING), keyLength_(INVALID_NUMBER) | ||
| 23 | +{ | ||
| 24 | +} | ||
| 25 | + | ||
| 26 | +ConfirmParams::ConfirmParams(int32_t confirmation, const std::string& pin, int32_t keyLength) | ||
| 27 | + : confirmation_(confirmation), pin_(pin), keyLength_(keyLength) | ||
| 28 | +{ | ||
| 29 | +} | ||
| 30 | + | ||
| 31 | +int32_t ConfirmParams::GetKeyLength() const | ||
| 32 | +{ | ||
| 33 | + return keyLength_; | ||
| 34 | +} | ||
| 35 | + | ||
| 36 | +void ConfirmParams::SetKeyLength(int32_t keyLength) | ||
| 37 | +{ | ||
| 38 | + keyLength_ = keyLength; | ||
| 39 | +} | ||
| 40 | + | ||
| 41 | +std::string ConfirmParams::GetPin() const | ||
| 42 | +{ | ||
| 43 | + return pin_; | ||
| 44 | +} | ||
| 45 | + | ||
| 46 | +void ConfirmParams::SetPin(const std::string& pin) | ||
| 47 | +{ | ||
| 48 | + pin_ = pin; | ||
| 49 | +} | ||
| 50 | + | ||
| 51 | +int32_t ConfirmParams::GetConfirmation() const | ||
| 52 | +{ | ||
| 53 | + return confirmation_; | ||
| 54 | +} | ||
| 55 | + | ||
| 56 | +void ConfirmParams::SetConfirmation(int32_t confirmation) | ||
| 57 | +{ | ||
| 58 | + confirmation_ = confirmation; | ||
| 59 | +} | ||
| 60 | + | ||
| 61 | +} // namespace IotcManagement | ||
| 62 | +} // namespace OHOS | ||
| @@ -0,0 +1,51 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | +namespace OHOS { | ||
| 24 | +namespace IotcManagement { | ||
| 25 | + | ||
| 26 | +class ConfirmParams { | ||
| 27 | +public: | ||
| 28 | + static constexpr int32_t INVALID_NUMBER = -1; | ||
| 29 | + | ||
| 30 | + ConfirmParams(); | ||
| 31 | + ConfirmParams(int32_t confirmation, const std::string& pin, int32_t keyLength); | ||
| 32 | + | ||
| 33 | + int32_t GetKeyLength() const; | ||
| 34 | + void SetKeyLength(int32_t keyLength); | ||
| 35 | + | ||
| 36 | + std::string GetPin() const; | ||
| 37 | + void SetPin(const std::string& pin); | ||
| 38 | + | ||
| 39 | + int32_t GetConfirmation() const; | ||
| 40 | + void SetConfirmation(int32_t confirmation); | ||
| 41 | + | ||
| 42 | +private: | ||
| 43 | + int32_t confirmation_; | ||
| 44 | + std::string pin_; | ||
| 45 | + int32_t keyLength_; | ||
| 46 | +}; | ||
| 47 | + | ||
| 48 | +} // namespace IotcManagement | ||
| 49 | +} // namespace OHOS | ||
| 50 | + | ||
| 51 | + | ||
| @@ -0,0 +1,101 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | +namespace OHOS { | ||
| 22 | +namespace IotcManagement { | ||
| 23 | + | ||
| 24 | +IdentityInfo::IdentityInfo(const std::string& authId, IdentityType identityType) | ||
| 25 | + : authId_(authId), phoneUuid_(""), identityType_(identityType) | ||
| 26 | +{ | ||
| 27 | +} | ||
| 28 | + | ||
| 29 | +std::string IdentityInfo::GetAuthId() const | ||
| 30 | +{ | ||
| 31 | + return authId_; | ||
| 32 | +} | ||
| 33 | + | ||
| 34 | +IdentityType IdentityInfo::GetIdentityType() const | ||
| 35 | +{ | ||
| 36 | + return identityType_; | ||
| 37 | +} | ||
| 38 | + | ||
| 39 | +int32_t IdentityInfo::GetIdentityTypeValue() const | ||
| 40 | +{ | ||
| 41 | + if (identityType_ == IdentityType::UNKNOWN) { | ||
| 42 | + return IdentityType::UNKNOWN; | ||
| 43 | + } | ||
| 44 | + return identityType_; | ||
| 45 | +} | ||
| 46 | + | ||
| 47 | +void IdentityInfo::SetAuthId(const std::string& authId) | ||
| 48 | +{ | ||
| 49 | + authId_ = authId; | ||
| 50 | +} | ||
| 51 | + | ||
| 52 | +void IdentityInfo::SetIdentityType(IdentityType identityType) | ||
| 53 | +{ | ||
| 54 | + identityType_ = identityType; | ||
| 55 | +} | ||
| 56 | + | ||
| 57 | +void IdentityInfo::SetPhoneUuid(const std::string& phoneUuid) | ||
| 58 | +{ | ||
| 59 | + phoneUuid_ = phoneUuid; | ||
| 60 | +} | ||
| 61 | + | ||
| 62 | +std::string IdentityInfo::GetPhoneUuid() const | ||
| 63 | +{ | ||
| 64 | + return phoneUuid_; | ||
| 65 | +} | ||
| 66 | + | ||
| 67 | +bool IdentityInfo::IsValid(IdentityInfo* identityInfo) | ||
| 68 | +{ | ||
| 69 | + if (identityInfo == nullptr) { | ||
| 70 | + return false; | ||
| 71 | + } | ||
| 72 | + | ||
| 73 | + if (identityInfo->authId_.empty()) { | ||
| 74 | + return false; | ||
| 75 | + } | ||
| 76 | + return identityInfo->identityType_ != IdentityType::UNKNOWN; | ||
| 77 | +} | ||
| 78 | + | ||
| 79 | +std::vector<uint8_t> IdentityInfo::GetAuthIdBytes() const | ||
| 80 | +{ | ||
| 81 | + std::vector<uint8_t> result; | ||
| 82 | + if (authId_.empty()) { | ||
| 83 | + return result; | ||
| 84 | + } | ||
| 85 | + | ||
| 86 | + if (identityType_ == IdentityType::USER) { | ||
| 87 | + std::vector<uint8_t> hash(32); | ||
| 88 | + IotcMd md(IotcMdType::IOTC_MD_SHA256); | ||
| 89 | + int32_t ret = md.Calc(IotcMdType::IOTC_MD_SHA256, | ||
| 90 | + reinterpret_cast<const uint8_t*>(authId_.c_str()), authId_.size(), hash.data(), hash.size()); | ||
| 91 | + if (ret == CommonConstants::COMMON_SUCCESS) { | ||
| 92 | + result = hash; | ||
| 93 | + } | ||
| 94 | + } else { | ||
| 95 | + result.assign(authId_.begin(), authId_.end()); | ||
| 96 | + } | ||
| 97 | + return result; | ||
| 98 | +} | ||
| 99 | + | ||
| 100 | +} // namespace IotcManagement | ||
| 101 | +} // namespace OHOS | ||
| @@ -0,0 +1,58 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | +namespace OHOS { | ||
| 25 | +namespace IotcManagement { | ||
| 26 | + | ||
| 27 | +class IdentityInfo { | ||
| 28 | +public: | ||
| 29 | + IdentityInfo(const std::string& authId, IdentityType identityType); | ||
| 30 | + | ||
| 31 | + std::string GetAuthId() const; | ||
| 32 | + | ||
| 33 | + int32_t GetIdentityTypeValue() const; | ||
| 34 | + | ||
| 35 | + IdentityType GetIdentityType() const; | ||
| 36 | + | ||
| 37 | + void SetAuthId(const std::string& authId); | ||
| 38 | + | ||
| 39 | + void SetIdentityType(IdentityType identityType); | ||
| 40 | + | ||
| 41 | + void SetPhoneUuid(const std::string& phoneUuid); | ||
| 42 | + | ||
| 43 | + std::string GetPhoneUuid() const; | ||
| 44 | + | ||
| 45 | + static bool IsValid(IdentityInfo* identityInfo); | ||
| 46 | + | ||
| 47 | + std::vector<uint8_t> GetAuthIdBytes() const; | ||
| 48 | + | ||
| 49 | +private: | ||
| 50 | + std::string authId_; | ||
| 51 | + std::string phoneUuid_; | ||
| 52 | + IdentityType identityType_; | ||
| 53 | +}; | ||
| 54 | + | ||
| 55 | +} // namespace IotcManagement | ||
| 56 | +} // namespace OHOS | ||
| 57 | + | ||
| 58 | + | ||
| @@ -0,0 +1,59 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | +namespace OHOS { | ||
| 22 | +namespace IotcManagement { | ||
| 23 | + | ||
| 24 | +MessageConfig::MessageConfig() | ||
| 25 | + : pakeResendMaxCount_(DEFAULT_SPEKE_RESEND_MAX_COUNT), pakePeriod_(DEFAULT_SPEKE_RESEND_PERIOD) | ||
| 26 | +{ | ||
| 27 | +} | ||
| 28 | + | ||
| 29 | +uint32_t MessageConfig::GetSpekeResendMaxCount() const | ||
| 30 | +{ | ||
| 31 | + return pakeResendMaxCount_; | ||
| 32 | +} | ||
| 33 | + | ||
| 34 | +void MessageConfig::SetSpekeResendMaxCount(uint32_t pakeResendMaxCount) | ||
| 35 | +{ | ||
| 36 | + if (pakeResendMaxCount < 0) { | ||
| 37 | + pakeResendMaxCount_ = DEFAULT_SPEKE_RESEND_MAX_COUNT; | ||
| 38 | + } else { | ||
| 39 | + pakeResendMaxCount_ = pakeResendMaxCount; | ||
| 40 | + } | ||
| 41 | +} | ||
| 42 | + | ||
| 43 | +uint32_t MessageConfig::GetSpekePeriod() const | ||
| 44 | +{ | ||
| 45 | + return pakePeriod_; | ||
| 46 | +} | ||
| 47 | + | ||
| 48 | +void MessageConfig::SetSpekePeriod(uint32_t pakePeriod) | ||
| 49 | +{ | ||
| 50 | + if (pakePeriod <= 0) { | ||
| 51 | + pakePeriod_ = DEFAULT_SPEKE_RESEND_PERIOD; | ||
| 52 | + } else { | ||
| 53 | + pakePeriod_ = pakePeriod; | ||
| 54 | + } | ||
| 55 | +} | ||
| 56 | + | ||
| 57 | +} // namespace IotcManagement | ||
| 58 | +} // namespace OHOS | ||
| 59 | + | ||
| @@ -0,0 +1,47 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | +namespace OHOS { | ||
| 22 | +namespace IotcManagement { | ||
| 23 | + | ||
| 24 | +class MessageConfig { | ||
| 25 | +public: | ||
| 26 | + static constexpr uint32_t DEFAULT_SPEKE_RESEND_MAX_COUNT = 5; | ||
| 27 | + static constexpr uint32_t DEFAULT_SPEKE_RESEND_PERIOD = 500; | ||
| 28 | + | ||
| 29 | + MessageConfig(); | ||
| 30 | + | ||
| 31 | + uint32_t GetSpekeResendMaxCount() const; | ||
| 32 | + | ||
| 33 | + void SetSpekeResendMaxCount(uint32_t pakeResendMaxCount); | ||
| 34 | + | ||
| 35 | + uint32_t GetSpekePeriod() const; | ||
| 36 | + | ||
| 37 | + void SetSpekePeriod(uint32_t pakePeriod); | ||
| 38 | + | ||
| 39 | +private: | ||
| 40 | + uint32_t pakeResendMaxCount_; | ||
| 41 | + uint32_t pakePeriod_; | ||
| 42 | +}; | ||
| 43 | + | ||
| 44 | +} // namespace IotcManagement | ||
| 45 | +} // namespace OHOS | ||
| 46 | + | ||
| 47 | + | ||
| @@ -0,0 +1,109 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | +namespace OHOS { | ||
| 20 | +namespace IotcManagement { | ||
| 21 | + | ||
| 22 | +OperationParameter::OperationParameter(const std::string& sessionId) | ||
| 23 | + : sessionId_(sessionId), selfType_(-1), peerType_(-1), callbackHandler_(nullptr), | ||
| 24 | + protocolVersion_(CommonConstants::PROTOCOL_VERSION_V1) | ||
| 25 | +{ | ||
| 26 | +} | ||
| 27 | + | ||
| 28 | +std::string OperationParameter::GetSessionId() const | ||
| 29 | +{ | ||
| 30 | + return sessionId_; | ||
| 31 | +} | ||
| 32 | + | ||
| 33 | +void OperationParameter::SetSessionId(const std::string& sessionId) | ||
| 34 | +{ | ||
| 35 | + sessionId_ = sessionId; | ||
| 36 | +} | ||
| 37 | + | ||
| 38 | +std::string OperationParameter::GetServiceType() const | ||
| 39 | +{ | ||
| 40 | + return serviceType_; | ||
| 41 | +} | ||
| 42 | + | ||
| 43 | +void OperationParameter::SetServiceType(const std::string& serviceType) | ||
| 44 | +{ | ||
| 45 | + serviceType_ = serviceType; | ||
| 46 | +} | ||
| 47 | + | ||
| 48 | +int32_t OperationParameter::GetSelfType() const | ||
| 49 | +{ | ||
| 50 | + return selfType_; | ||
| 51 | +} | ||
| 52 | + | ||
| 53 | +void OperationParameter::SetSelfType(int32_t selfType) | ||
| 54 | +{ | ||
| 55 | + selfType_ = selfType; | ||
| 56 | +} | ||
| 57 | + | ||
| 58 | +std::vector<uint8_t> OperationParameter::GetSelfId() const | ||
| 59 | +{ | ||
| 60 | + return selfId_; | ||
| 61 | +} | ||
| 62 | + | ||
| 63 | +void OperationParameter::SetSelfId(const std::vector<uint8_t>& selfId) | ||
| 64 | +{ | ||
| 65 | + selfId_ = selfId; | ||
| 66 | +} | ||
| 67 | + | ||
| 68 | +int32_t OperationParameter::GetPeerType() const | ||
| 69 | +{ | ||
| 70 | + return peerType_; | ||
| 71 | +} | ||
| 72 | + | ||
| 73 | +void OperationParameter::SetPeerType(int32_t peerType) | ||
| 74 | +{ | ||
| 75 | + peerType_ = peerType; | ||
| 76 | +} | ||
| 77 | + | ||
| 78 | +std::vector<uint8_t> OperationParameter::GetPeerId() const | ||
| 79 | +{ | ||
| 80 | + return peerId_; | ||
| 81 | +} | ||
| 82 | + | ||
| 83 | +void OperationParameter::SetPeerId(const std::vector<uint8_t>& peerId) | ||
| 84 | +{ | ||
| 85 | + peerId_ = peerId; | ||
| 86 | +} | ||
| 87 | + | ||
| 88 | +std::shared_ptr<HwDevAuthCallback> OperationParameter::GetCallbackHandler() const | ||
| 89 | +{ | ||
| 90 | + return callbackHandler_; | ||
| 91 | +} | ||
| 92 | + | ||
| 93 | +void OperationParameter::SetCallbackHandler(std::shared_ptr<HwDevAuthCallback> callbackHandler) | ||
| 94 | +{ | ||
| 95 | + callbackHandler_ = callbackHandler; | ||
| 96 | +} | ||
| 97 | + | ||
| 98 | +uint32_t OperationParameter::GetProtocolVersion() const | ||
| 99 | +{ | ||
| 100 | + return protocolVersion_; | ||
| 101 | +} | ||
| 102 | + | ||
| 103 | +void OperationParameter::SetProtocolVersion(uint32_t protocolVersion) | ||
| 104 | +{ | ||
| 105 | + protocolVersion_ = protocolVersion; | ||
| 106 | +} | ||
| 107 | + | ||
| 108 | +} // namespace IotcManagement | ||
| 109 | +} // namespace OHOS | ||
| @@ -0,0 +1,82 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | +namespace OHOS { | ||
| 26 | +namespace IotcManagement { | ||
| 27 | + | ||
| 28 | +class HwDevAuthCallback { | ||
| 29 | +public: | ||
| 30 | + virtual ~HwDevAuthCallback() = default; | ||
| 31 | + | ||
| 32 | + virtual void OnOperationFinished(const std::string& sessionId, int32_t operationCode, | ||
| 33 | + int32_t result, const std::vector<uint8_t>& returnData) = 0; | ||
| 34 | + | ||
| 35 | + virtual bool OnDataTransmit(const std::string& sessionId, const std::vector<uint8_t>& toPeerData) = 0; | ||
| 36 | + | ||
| 37 | + virtual void OnSessionKeyReturned(const std::string& sessionId, const std::vector<uint8_t>& sessionKey) = 0; | ||
| 38 | +}; | ||
| 39 | + | ||
| 40 | +class OperationParameter { | ||
| 41 | +public: | ||
| 42 | + explicit OperationParameter(const std::string& sessionId); | ||
| 43 | + | ||
| 44 | + std::string GetSessionId() const; | ||
| 45 | + void SetSessionId(const std::string& sessionId); | ||
| 46 | + | ||
| 47 | + std::string GetServiceType() const; | ||
| 48 | + void SetServiceType(const std::string& serviceType); | ||
| 49 | + | ||
| 50 | + int32_t GetSelfType() const; | ||
| 51 | + void SetSelfType(int32_t selfType); | ||
| 52 | + | ||
| 53 | + std::vector<uint8_t> GetSelfId() const; | ||
| 54 | + void SetSelfId(const std::vector<uint8_t>& selfId); | ||
| 55 | + | ||
| 56 | + int32_t GetPeerType() const; | ||
| 57 | + void SetPeerType(int32_t peerType); | ||
| 58 | + | ||
| 59 | + std::vector<uint8_t> GetPeerId() const; | ||
| 60 | + void SetPeerId(const std::vector<uint8_t>& peerId); | ||
| 61 | + | ||
| 62 | + std::shared_ptr<HwDevAuthCallback> GetCallbackHandler() const; | ||
| 63 | + void SetCallbackHandler(std::shared_ptr<HwDevAuthCallback> callbackHandler); | ||
| 64 | + | ||
| 65 | + uint32_t GetProtocolVersion() const; | ||
| 66 | + void SetProtocolVersion(uint32_t protocolVersion); | ||
| 67 | + | ||
| 68 | +private: | ||
| 69 | + std::string sessionId_; | ||
| 70 | + std::string serviceType_; | ||
| 71 | + int32_t selfType_; | ||
| 72 | + std::vector<uint8_t> selfId_; | ||
| 73 | + int32_t peerType_; | ||
| 74 | + std::vector<uint8_t> peerId_; | ||
| 75 | + std::shared_ptr<HwDevAuthCallback> callbackHandler_; | ||
| 76 | + uint32_t protocolVersion_; | ||
| 77 | +}; | ||
| 78 | + | ||
| 79 | +} // namespace IotcManagement | ||
| 80 | +} // namespace OHOS | ||
| 81 | + | ||
| 82 | + | ||
| @@ -0,0 +1,73 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | +namespace OHOS { | ||
| 21 | +namespace IotcManagement { | ||
| 22 | + | ||
| 23 | +ParameterBuilder::ParameterBuilder(const std::string& sessionId) | ||
| 24 | +{ | ||
| 25 | + parameter_ = new OperationParameter(sessionId); | ||
| 26 | + parameter_->SetServiceType(CommonConstants::SERVICE_TYPE); | ||
| 27 | +} | ||
| 28 | + | ||
| 29 | +ParameterBuilder* ParameterBuilder::SetPeerIdentityInfo(IdentityInfo* peerIdentityInfo) | ||
| 30 | +{ | ||
| 31 | + if (peerIdentityInfo == nullptr) { | ||
| 32 | + IOTC_LOGW("ParameterBuilder::SetPeerIdentityInfo peerIdentityInfo is null"); | ||
| 33 | + return this; | ||
| 34 | + } | ||
| 35 | + | ||
| 36 | + std::vector<uint8_t> peerId = peerIdentityInfo->GetAuthIdBytes(); | ||
| 37 | + parameter_->SetPeerId(peerId); | ||
| 38 | + parameter_->SetPeerType(peerIdentityInfo->GetIdentityTypeValue()); | ||
| 39 | + return this; | ||
| 40 | +} | ||
| 41 | + | ||
| 42 | +ParameterBuilder* ParameterBuilder::SetCallbackMethods(std::shared_ptr<HwDevAuthCallback> callbackMethods) | ||
| 43 | +{ | ||
| 44 | + parameter_->SetCallbackHandler(callbackMethods); | ||
| 45 | + return this; | ||
| 46 | +} | ||
| 47 | + | ||
| 48 | +ParameterBuilder* ParameterBuilder::SetProtocolVersion(uint32_t protocolVersion) | ||
| 49 | +{ | ||
| 50 | + parameter_->SetProtocolVersion(protocolVersion); | ||
| 51 | + return this; | ||
| 52 | +} | ||
| 53 | + | ||
| 54 | +ParameterBuilder* ParameterBuilder::SetLocalIdentityInfo(std::shared_ptr<IdentityInfo> localIdentityInfo) | ||
| 55 | +{ | ||
| 56 | + if (localIdentityInfo == nullptr) { | ||
| 57 | + IOTC_LOGW("ParameterBuilder::SetLocalIdentityInfo localIdentityInfo is null"); | ||
| 58 | + return this; | ||
| 59 | + } | ||
| 60 | + | ||
| 61 | + std::vector<uint8_t> selfId = localIdentityInfo->GetAuthIdBytes(); | ||
| 62 | + parameter_->SetSelfId(selfId); | ||
| 63 | + parameter_->SetSelfType(localIdentityInfo->GetIdentityTypeValue()); | ||
| 64 | + return this; | ||
| 65 | +} | ||
| 66 | + | ||
| 67 | +OperationParameter* ParameterBuilder::Build() | ||
| 68 | +{ | ||
| 69 | + return parameter_; | ||
| 70 | +} | ||
| 71 | + | ||
| 72 | +} // namespace IotcManagement | ||
| 73 | +} // namespace OHOS | ||
| @@ -0,0 +1,49 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | +namespace OHOS { | ||
| 26 | +namespace IotcManagement { | ||
| 27 | + | ||
| 28 | +class ParameterBuilder { | ||
| 29 | +public: | ||
| 30 | + explicit ParameterBuilder(const std::string& sessionId); | ||
| 31 | + | ||
| 32 | + ParameterBuilder* SetPeerIdentityInfo(IdentityInfo* peerIdentityInfo); | ||
| 33 | + | ||
| 34 | + ParameterBuilder* SetCallbackMethods(std::shared_ptr<HwDevAuthCallback> callbackMethods); | ||
| 35 | + | ||
| 36 | + ParameterBuilder* SetLocalIdentityInfo(std::shared_ptr<IdentityInfo> localIdentityInfo); | ||
| 37 | + | ||
| 38 | + ParameterBuilder* SetProtocolVersion(uint32_t protocolVersion); | ||
| 39 | + | ||
| 40 | + OperationParameter* Build(); | ||
| 41 | + | ||
| 42 | +private: | ||
| 43 | + OperationParameter* parameter_; | ||
| 44 | +}; | ||
| 45 | + | ||
| 46 | +} // namespace IotcManagement | ||
| 47 | +} // namespace OHOS | ||
| 48 | + | ||
| 49 | + | ||
| @@ -0,0 +1,277 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | +namespace OHOS { | ||
| 24 | +namespace IotcManagement { | ||
| 25 | + | ||
| 26 | +PassThroughData::PassThroughData(const std::string& securityJson, const std::string& sessionId, | ||
| 27 | + uint32_t protocolVersion) | ||
| 28 | + : sessionId_(sessionId), protocolVersion_(protocolVersion) | ||
| 29 | +{ | ||
| 30 | + securityData_.ParseIntoOwned(securityJson); | ||
| 31 | + std::shared_ptr<IdentityInfo> localIdentityInfo = SecurityAdapter::GetInstance().GetLocalIdentityInfo(); | ||
| 32 | + if (localIdentityInfo != nullptr) { | ||
| 33 | + phoneUuid_ = localIdentityInfo->GetPhoneUuid(); | ||
| 34 | + authIdBytes_ = localIdentityInfo->GetAuthIdBytes(); | ||
| 35 | + } else { | ||
| 36 | + phoneUuid_.clear(); | ||
| 37 | + authIdBytes_.clear(); | ||
| 38 | + } | ||
| 39 | +} | ||
| 40 | + | ||
| 41 | +PassThroughData::~PassThroughData() | ||
| 42 | +{ | ||
| 43 | + securityData_.DeleteJson(); | ||
| 44 | +} | ||
| 45 | + | ||
| 46 | +std::string PassThroughData::GetSessionId() const | ||
| 47 | +{ | ||
| 48 | + if (!securityData_.HasObject(CommonConstants::KEY_SESSION_ID)) { | ||
| 49 | + return ""; | ||
| 50 | + } | ||
| 51 | + return securityData_.GetString(CommonConstants::KEY_SESSION_ID); | ||
| 52 | +} | ||
| 53 | + | ||
| 54 | +std::string PassThroughData::ToJson(uint32_t protocolVersion) const | ||
| 55 | +{ | ||
| 56 | + uint32_t ver = (protocolVersion != 0) ? protocolVersion : protocolVersion_; | ||
| 57 | + if (ver == CommonConstants::PROTOCOL_VERSION_V2) { | ||
| 58 | + return ToJsonV2(); | ||
| 59 | + } | ||
| 60 | + return ToJsonV1(); | ||
| 61 | +} | ||
| 62 | + | ||
| 63 | +std::string PassThroughData::ToJsonV1() const | ||
| 64 | +{ | ||
| 65 | + IotcJsonObject* jsonObj = IotcJsonObject::CreateObject(); | ||
| 66 | + if (jsonObj == nullptr || jsonObj->GetJsonObject() == nullptr) { | ||
| 67 | + IOTC_LOGE("ToJsonV1 create root json object failed"); | ||
| 68 | + if (jsonObj != nullptr) delete jsonObj; | ||
| 69 | + return ""; | ||
| 70 | + } | ||
| 71 | + int32_t ret = jsonObj->AddString2Obj(CommonConstants::KEY_SESSION_ID, sessionId_); | ||
| 72 | + ret = jsonObj->AddString2Obj(CommonConstants::KEY_PUUID, phoneUuid_); | ||
| 73 | + | ||
| 74 | + if (GetOperationType() == OperationCode::AUTH_KEY_AGREEMENT) { | ||
| 75 | + std::string authIdHex = CommonUtil::ToHexString(authIdBytes_); | ||
| 76 | + ret = jsonObj->AddString2Obj(CommonConstants::KEY_AUTH_ID, authIdHex); | ||
| 77 | + } | ||
| 78 | + ret = jsonObj->AddString2Obj(CommonConstants::KEY_CMD, CommonConstants::CMD_NEGO); | ||
| 79 | + ret = jsonObj->AddNumber2Obj(CommonConstants::AUTH_TYPE, 1); | ||
| 80 | + | ||
| 81 | + IotcJsonObject* securityDataObj = IotcJsonObject::Duplicate(securityData_, true); | ||
| 82 | + if (securityDataObj == nullptr || securityDataObj->GetJsonObject() == nullptr) { | ||
| 83 | + IOTC_LOGE("ToJsonV1 duplicate security data object failed"); | ||
| 84 | + if (securityDataObj != nullptr) delete securityDataObj; | ||
| 85 | + jsonObj->DeleteJson(); | ||
| 86 | + delete jsonObj; | ||
| 87 | + return ""; | ||
| 88 | + } | ||
| 89 | + ret = jsonObj->AddItem2Obj(CommonConstants::KEY_SECURITY_DATA, *securityDataObj); | ||
| 90 | + if (ret != static_cast<int32_t>(JsonErrCode::OK)) { | ||
| 91 | + IOTC_LOGE("ToJsonV1 add securityData failed, ret=%d", ret); | ||
| 92 | + securityDataObj->DeleteJson(); | ||
| 93 | + delete securityDataObj; | ||
| 94 | + jsonObj->DeleteJson(); | ||
| 95 | + delete jsonObj; | ||
| 96 | + return ""; | ||
| 97 | + } | ||
| 98 | + std::string josnStr = jsonObj->Print2String(); | ||
| 99 | + jsonObj->DeleteJson(); | ||
| 100 | + delete jsonObj; | ||
| 101 | + delete securityDataObj; | ||
| 102 | + return josnStr; | ||
| 103 | +} | ||
| 104 | + | ||
| 105 | +std::string PassThroughData::ToJsonV2() const | ||
| 106 | +{ | ||
| 107 | + IotcJsonObject* jsonObj = IotcJsonObject::CreateObject(); | ||
| 108 | + if (jsonObj == nullptr || jsonObj->GetJsonObject() == nullptr) { | ||
| 109 | + IOTC_LOGE("PassThroughData::ToJsonV2 create root json object failed"); | ||
| 110 | + if (jsonObj != nullptr) delete jsonObj; | ||
| 111 | + return ""; | ||
| 112 | + } | ||
| 113 | + jsonObj->AddString2Obj(CommonConstants::KEY_SESSION_ID, sessionId_); | ||
| 114 | + | ||
| 115 | + IotcJsonObject* payload = securityData_.GetObj(CommonConstants::KEY_PAYLOAD); | ||
| 116 | + if (payload == nullptr || payload->GetJsonObject() == nullptr) { | ||
| 117 | + IOTC_LOGE("PassThroughData::ToJsonV2 payload missing"); | ||
| 118 | + jsonObj->DeleteJson(); | ||
| 119 | + delete jsonObj; | ||
| 120 | + return ""; | ||
| 121 | + } | ||
| 122 | + int32_t messageId = securityData_.GetNumber(CommonConstants::KEY_MESSAGE, OperationCode::UNKNOWN); | ||
| 123 | + | ||
| 124 | + switch (messageId) { | ||
| 125 | + case MessageCode::SPEKE_REQUEST: { | ||
| 126 | + jsonObj->AddString2Obj(CommonConstants::KEY_MSG_ID, CommonConstants::MSG_ID_SPEKE_MSG1); | ||
| 127 | + IotcJsonObject* version = payload->GetObj(CommonConstants::KEY_VERSION); | ||
| 128 | + if (version != nullptr && version->GetJsonObject() != nullptr) { | ||
| 129 | + std::string cur = version->GetString(CommonConstants::KEY_CURRENT_VERSION); | ||
| 130 | + jsonObj->AddString2Obj(CommonConstants::KEY_VERSION, cur); | ||
| 131 | + } | ||
| 132 | + break; | ||
| 133 | + } | ||
| 134 | + case MessageCode::SPEKE_RESPONSE: { | ||
| 135 | + jsonObj->AddString2Obj(CommonConstants::KEY_MSG_ID, CommonConstants::MSG_ID_SPEKE_MSG2); | ||
| 136 | + std::string challenge = payload->GetString(CommonConstants::FIELD_CHALLENGE); | ||
| 137 | + std::string salt = payload->GetString(CommonConstants::FIELD_SALT); | ||
| 138 | + std::string epk = payload->GetString(CommonConstants::FIELD_ED_PUBLIC); | ||
| 139 | + jsonObj->AddString2Obj(CommonConstants::KEY_CHALLENGE1, challenge); | ||
| 140 | + jsonObj->AddString2Obj(CommonConstants::FIELD_SALT, salt); | ||
| 141 | + jsonObj->AddString2Obj(CommonConstants::KEY_PK1, epk); | ||
| 142 | + break; | ||
| 143 | + } | ||
| 144 | + case MessageCode::SPEKE_CLIENT_CONFIRM: { | ||
| 145 | + jsonObj->AddString2Obj(CommonConstants::KEY_MSG_ID, CommonConstants::MSG_ID_SPEKE_MSG3); | ||
| 146 | + std::string challenge = payload->GetString(CommonConstants::FIELD_CHALLENGE); | ||
| 147 | + std::string epk = payload->GetString(CommonConstants::FIELD_ED_PUBLIC); | ||
| 148 | + std::string kcf = payload->GetString(CommonConstants::FIELD_CONFIG_DATA); | ||
| 149 | + jsonObj->AddString2Obj(CommonConstants::KEY_CHALLENGE2, challenge); | ||
| 150 | + jsonObj->AddString2Obj(CommonConstants::KEY_PK2, epk); | ||
| 151 | + jsonObj->AddString2Obj(CommonConstants::KEY_KCFDATA2, kcf); | ||
| 152 | + break; | ||
| 153 | + } | ||
| 154 | + case MessageCode::SPEKE_SERVER_CONFIRM: { | ||
| 155 | + jsonObj->AddString2Obj(CommonConstants::KEY_MSG_ID, CommonConstants::MSG_ID_SPEKE_MSG4); | ||
| 156 | + std::string kcf = payload->GetString(CommonConstants::FIELD_CONFIG_DATA); | ||
| 157 | + jsonObj->AddString2Obj(CommonConstants::KEY_KCFDATA1, kcf); | ||
| 158 | + break; | ||
| 159 | + } | ||
| 160 | + default: | ||
| 161 | + IOTC_LOGE("PassThroughData::ToJsonV2 unknown messageId=%{public}d", messageId); | ||
| 162 | + jsonObj->DeleteJson(); | ||
| 163 | + delete jsonObj; | ||
| 164 | + return ""; | ||
| 165 | + } | ||
| 166 | + | ||
| 167 | + std::string jsonStr = jsonObj->Print2String(); | ||
| 168 | + jsonObj->DeleteJson(); | ||
| 169 | + delete jsonObj; | ||
| 170 | + return jsonStr; | ||
| 171 | +} | ||
| 172 | + | ||
| 173 | +std::string PassThroughData::GetSecurityDataObject() const | ||
| 174 | +{ | ||
| 175 | + if (securityData_.HasObject(CommonConstants::KEY_SECURITY_DATA)) { | ||
| 176 | + IotcJsonObject* jsonObj = securityData_.GetObj(CommonConstants::KEY_SECURITY_DATA); | ||
| 177 | + if (jsonObj == nullptr || jsonObj->GetJsonObject() == nullptr) { | ||
| 178 | + return ""; | ||
| 179 | + } | ||
| 180 | + std::string result = jsonObj->Print2String(); | ||
| 181 | + return result; | ||
| 182 | + } | ||
| 183 | + | ||
| 184 | + // V2 扁平报文: 由 msgId 反向还原为内部嵌套结构。 | ||
| 185 | + if (!securityData_.HasObject(CommonConstants::KEY_MSG_ID)) { | ||
| 186 | + return ""; | ||
| 187 | + } | ||
| 188 | + std::string msgId = securityData_.GetString(CommonConstants::KEY_MSG_ID); | ||
| 189 | + IotcJsonObject* outObj = IotcJsonObject::CreateObject(); | ||
| 190 | + if (outObj == nullptr || outObj->GetJsonObject() == nullptr) { | ||
| 191 | + if (outObj != nullptr) delete outObj; | ||
| 192 | + return ""; | ||
| 193 | + } | ||
| 194 | + IotcJsonObject* payload = IotcJsonObject::CreateObject(); | ||
| 195 | + if (payload == nullptr || payload->GetJsonObject() == nullptr) { | ||
| 196 | + if (payload != nullptr) delete payload; | ||
| 197 | + outObj->DeleteJson(); | ||
| 198 | + delete outObj; | ||
| 199 | + return ""; | ||
| 200 | + } | ||
| 201 | + | ||
| 202 | + if (msgId == CommonConstants::MSG_ID_SPEKE_MSG1) { | ||
| 203 | + outObj->AddNumber2Obj(CommonConstants::KEY_MESSAGE, MessageCode::SPEKE_REQUEST); | ||
| 204 | + IotcJsonObject* version = IotcJsonObject::CreateObject(); | ||
| 205 | + if (version != nullptr && version->GetJsonObject() != nullptr) { | ||
| 206 | + std::string cur = securityData_.GetString(CommonConstants::KEY_VERSION); | ||
| 207 | + version->AddString2Obj(CommonConstants::KEY_CURRENT_VERSION, cur); | ||
| 208 | + version->AddString2Obj(CommonConstants::KEY_MIN_VERSION, cur); | ||
| 209 | + payload->AddItem2Obj(CommonConstants::KEY_VERSION, *version); | ||
| 210 | + version->DeleteJson(); | ||
| 211 | + delete version; | ||
| 212 | + } | ||
| 213 | + payload->AddNumber2Obj(CommonConstants::KEY_OPERATION_CODE, OperationCode::AUTH_KEY_AGREEMENT); | ||
| 214 | + } else if (msgId == CommonConstants::MSG_ID_SPEKE_MSG2) { | ||
| 215 | + outObj->AddNumber2Obj(CommonConstants::KEY_MESSAGE, MessageCode::SPEKE_RESPONSE); | ||
| 216 | + IotcJsonObject* version = IotcJsonObject::CreateObject(); | ||
| 217 | + if (version != nullptr && version->GetJsonObject() != nullptr) { | ||
| 218 | + version->AddString2Obj(CommonConstants::KEY_CURRENT_VERSION, CommonConstants::VERSION_V2); | ||
| 219 | + version->AddString2Obj(CommonConstants::KEY_MIN_VERSION, CommonConstants::VERSION_V2); | ||
| 220 | + payload->AddItem2Obj(CommonConstants::KEY_VERSION, *version); | ||
| 221 | + version->DeleteJson(); | ||
| 222 | + delete version; | ||
| 223 | + } | ||
| 224 | + payload->AddString2Obj(CommonConstants::FIELD_CHALLENGE, | ||
| 225 | + securityData_.GetString(CommonConstants::KEY_CHALLENGE1)); | ||
| 226 | + payload->AddString2Obj(CommonConstants::FIELD_SALT, | ||
| 227 | + securityData_.GetString(CommonConstants::FIELD_SALT)); | ||
| 228 | + payload->AddString2Obj(CommonConstants::FIELD_ED_PUBLIC, | ||
| 229 | + securityData_.GetString(CommonConstants::KEY_PK1)); | ||
| 230 | + if (securityData_.HasObject(CommonConstants::KEY_ITERATIONS)) { | ||
| 231 | + payload->AddNumber2Obj(CommonConstants::KEY_ITERATIONS, | ||
| 232 | + securityData_.GetNumber(CommonConstants::KEY_ITERATIONS, 0)); | ||
| 233 | + } | ||
| 234 | + } else if (msgId == CommonConstants::MSG_ID_SPEKE_MSG3) { | ||
| 235 | + outObj->AddNumber2Obj(CommonConstants::KEY_MESSAGE, MessageCode::SPEKE_CLIENT_CONFIRM); | ||
| 236 | + payload->AddString2Obj(CommonConstants::FIELD_CHALLENGE, | ||
| 237 | + securityData_.GetString(CommonConstants::KEY_CHALLENGE2)); | ||
| 238 | + payload->AddString2Obj(CommonConstants::FIELD_ED_PUBLIC, | ||
| 239 | + securityData_.GetString(CommonConstants::KEY_PK2)); | ||
| 240 | + payload->AddString2Obj(CommonConstants::FIELD_CONFIG_DATA, | ||
| 241 | + securityData_.GetString(CommonConstants::KEY_KCFDATA2)); | ||
| 242 | + } else if (msgId == CommonConstants::MSG_ID_SPEKE_MSG4) { | ||
| 243 | + outObj->AddNumber2Obj(CommonConstants::KEY_MESSAGE, MessageCode::SPEKE_SERVER_CONFIRM); | ||
| 244 | + payload->AddString2Obj(CommonConstants::FIELD_CONFIG_DATA, | ||
| 245 | + securityData_.GetString(CommonConstants::KEY_KCFDATA1)); | ||
| 246 | + } else { | ||
| 247 | + outObj->DeleteJson(); | ||
| 248 | + delete outObj; | ||
| 249 | + payload->DeleteJson(); | ||
| 250 | + delete payload; | ||
| 251 | + return ""; | ||
| 252 | + } | ||
| 253 | + | ||
| 254 | + outObj->AddItem2Obj(CommonConstants::KEY_PAYLOAD, *payload); | ||
| 255 | + payload->DeleteJson(); | ||
| 256 | + delete payload; | ||
| 257 | + std::string result = outObj->Print2String(); | ||
| 258 | + outObj->DeleteJson(); | ||
| 259 | + delete outObj; | ||
| 260 | + return result; | ||
| 261 | +} | ||
| 262 | + | ||
| 263 | +int32_t PassThroughData::GetOperationType() const | ||
| 264 | +{ | ||
| 265 | + if (!securityData_.HasObject(CommonConstants::KEY_PAYLOAD)) { | ||
| 266 | + return OperationCode::UNKNOWN; | ||
| 267 | + } | ||
| 268 | + IotcJsonObject* payload = securityData_.GetObj(CommonConstants::KEY_PAYLOAD); | ||
| 269 | + if (payload == nullptr) { | ||
| 270 | + return OperationCode::UNKNOWN; | ||
| 271 | + } | ||
| 272 | + int32_t operationCode = payload->GetNumber(CommonConstants::KEY_OPERATION_CODE, OperationCode::UNKNOWN); | ||
| 273 | + return operationCode; | ||
| 274 | +} | ||
| 275 | + | ||
| 276 | +} // namespace IotcManagement | ||
| 277 | +} // namespace OHOS | ||
| @@ -0,0 +1,73 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | + | ||
| 26 | +namespace OHOS { | ||
| 27 | +namespace IotcManagement { | ||
| 28 | + | ||
| 29 | +class PassThroughData { | ||
| 30 | +public: | ||
| 31 | + // 外部唯一可用构造函数 | ||
| 32 | + PassThroughData(const std::string& securityJson, const std::string& sessionId, | ||
| 33 | + uint32_t protocolVersion = CommonConstants::PROTOCOL_VERSION_V1); | ||
| 34 | + | ||
| 35 | + std::string GetSessionId() const; | ||
| 36 | + /** | ||
| 37 | + * @brief 将透传数据转换为 JSON 字符串。 | ||
| 38 | + * @param protocolVersion 广播协议版本号:PROTOCOL_VERSION_V1 (V1嵌套) 或 PROTOCOL_VERSION_V2 (扁平 spekeMsg1~4)。 | ||
| 39 | + * 0 时使用构造时的协议版本。 | ||
| 40 | + */ | ||
| 41 | + std::string ToJson(uint32_t protocolVersion = 0) const; | ||
| 42 | + std::string GetSecurityDataObject() const; | ||
| 43 | + int32_t GetOperationType() const; | ||
| 44 | + | ||
| 45 | + PassThroughData(const PassThroughData&) = delete; | ||
| 46 | + PassThroughData& operator=(const PassThroughData&) = delete; | ||
| 47 | + PassThroughData(PassThroughData&&) = delete; | ||
| 48 | + PassThroughData& operator=(PassThroughData&&) = delete; | ||
| 49 | + | ||
| 50 | + ~PassThroughData(); | ||
| 51 | + | ||
| 52 | +private: | ||
| 53 | + PassThroughData() = default; | ||
| 54 | + /** | ||
| 55 | + * @brief V1 协议:嵌套 securityData 格式输出。 | ||
| 56 | + */ | ||
| 57 | + std::string ToJsonV1() const; | ||
| 58 | + /** | ||
| 59 | + * @brief V2 协议:根据 payload.message 选择 spekeMsg1~4 输出。 | ||
| 60 | + */ | ||
| 61 | + std::string ToJsonV2() const; | ||
| 62 | + | ||
| 63 | + IotcJsonObject securityData_; | ||
| 64 | + std::string phoneUuid_; | ||
| 65 | + std::vector<uint8_t> authIdBytes_; | ||
| 66 | + std::string sessionId_; | ||
| 67 | + uint32_t protocolVersion_; | ||
| 68 | +}; | ||
| 69 | + | ||
| 70 | +} // namespace IotcManagement | ||
| 71 | +} // namespace OHOS | ||
| 72 | + | ||
| 73 | + | ||
| @@ -0,0 +1,80 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | +namespace OHOS { | ||
| 22 | +namespace IotcManagement { | ||
| 23 | + | ||
| 24 | +PayloadResponse PayloadResponse::FormJson(const std::string& payloadJson) { | ||
| 25 | + PayloadResponse paylod; | ||
| 26 | + paylod.ParseByJson(payloadJson); | ||
| 27 | + return paylod; | ||
| 28 | +} | ||
| 29 | + | ||
| 30 | +void PayloadResponse::ParseByJson(const std::string& payloadJson) { | ||
| 31 | + if (payloadJson.empty()) { | ||
| 32 | + return; | ||
| 33 | + } | ||
| 34 | + IotcJsonObject* jsonObject = IotcJsonObject::Parse(payloadJson); | ||
| 35 | + if (jsonObject == nullptr || jsonObject->GetJsonObject() == nullptr) { | ||
| 36 | + if (jsonObject != nullptr) delete jsonObject; | ||
| 37 | + return; | ||
| 38 | + } | ||
| 39 | + IotcJsonObject* versionObj = jsonObject->GetObj(CommonConstants::KEY_VERSION); | ||
| 40 | + if (versionObj != nullptr && versionObj->GetJsonObject() != nullptr) { | ||
| 41 | + std::map<std::string, std::string> versionMap; | ||
| 42 | + versionMap[CommonConstants::KEY_CURRENT_VERSION] = versionObj->GetString(CommonConstants::KEY_CURRENT_VERSION); | ||
| 43 | + versionMap[CommonConstants::KEY_MIN_VERSION] = versionObj->GetString(CommonConstants::KEY_MIN_VERSION); | ||
| 44 | + versionMap[CommonConstants::KEY_SUPPORT_VERSION] = versionObj->GetString(CommonConstants::KEY_SUPPORT_VERSION); | ||
| 45 | + version_ = VersionInfo::ConstructorByJson(versionMap); | ||
| 46 | + } | ||
| 47 | + challenge_ = jsonObject->GetString(CommonConstants::FIELD_CHALLENGE); | ||
| 48 | + salt_ = jsonObject->GetString(CommonConstants::FIELD_SALT); | ||
| 49 | + epk_ = jsonObject->GetString(CommonConstants::FIELD_ED_PUBLIC); | ||
| 50 | + kcfData_ = jsonObject->GetString(CommonConstants::FIELD_CONFIG_DATA); | ||
| 51 | + errorCode_ = jsonObject->GetNumber(CommonConstants::KEY_ERROR_CODE, CommonConstants::COMMON_SUCCESS); | ||
| 52 | + jsonObject->DeleteJson(); | ||
| 53 | + delete jsonObject; | ||
| 54 | +} | ||
| 55 | + | ||
| 56 | +VersionInfo PayloadResponse::GetVersion() const { | ||
| 57 | + return version_; | ||
| 58 | +} | ||
| 59 | + | ||
| 60 | +std::string PayloadResponse::GetEpk() const { | ||
| 61 | + return epk_; | ||
| 62 | +} | ||
| 63 | + | ||
| 64 | +std::string PayloadResponse::GetChallenge() const { | ||
| 65 | + return challenge_; | ||
| 66 | +} | ||
| 67 | + | ||
| 68 | +std::string PayloadResponse::GetKcfData() const { | ||
| 69 | + return kcfData_; | ||
| 70 | +} | ||
| 71 | + | ||
| 72 | +std::string PayloadResponse::GetSalt() const { | ||
| 73 | + return salt_; | ||
| 74 | +} | ||
| 75 | + | ||
| 76 | +int32_t PayloadResponse::GetErrorCode() const { | ||
| 77 | + return errorCode_; | ||
| 78 | +} | ||
| 79 | +} // namespace IotcManagement | ||
| 80 | +} // namespace OHOS | ||
| @@ -0,0 +1,51 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | +namespace OHOS { | ||
| 25 | +namespace IotcManagement { | ||
| 26 | + | ||
| 27 | +class PayloadResponse { | ||
| 28 | +public: | ||
| 29 | + PayloadResponse() = default; | ||
| 30 | + ~PayloadResponse() = default; | ||
| 31 | + static PayloadResponse FormJson(const std::string& payloadJson); | ||
| 32 | + VersionInfo GetVersion() const; | ||
| 33 | + std::string GetEpk() const; | ||
| 34 | + std::string GetChallenge() const; | ||
| 35 | + std::string GetKcfData() const; | ||
| 36 | + std::string GetSalt() const; | ||
| 37 | + int32_t GetErrorCode() const; | ||
| 38 | +private: | ||
| 39 | + int32_t errorCode_; | ||
| 40 | + VersionInfo version_; | ||
| 41 | + std::string challenge_; | ||
| 42 | + std::string epk_; | ||
| 43 | + std::string kcfData_; | ||
| 44 | + std::string salt_; | ||
| 45 | + void ParseByJson(const std::string& payloadJson); | ||
| 46 | +}; | ||
| 47 | + | ||
| 48 | +} // namespace IotcManagement | ||
| 49 | +} // namespace OHOS | ||
| 50 | + | ||
| 51 | + | ||
| @@ -0,0 +1,107 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | +namespace OHOS { | ||
| 20 | +namespace IotcManagement { | ||
| 21 | + | ||
| 22 | +VersionInfo::VersionInfo() | ||
| 23 | +{ | ||
| 24 | +} | ||
| 25 | + | ||
| 26 | +VersionInfo VersionInfo::ConstructorByJson(const std::map<std::string, std::string>& jsonVersion) | ||
| 27 | +{ | ||
| 28 | + VersionInfo info; | ||
| 29 | + if (jsonVersion.empty()) { | ||
| 30 | + IOTC_LOGE("VersionInfo::ConstructorByJson jsonVersion is null"); | ||
| 31 | + return info; | ||
| 32 | + } | ||
| 33 | + | ||
| 34 | + auto getValue = [&](const std::string& key) -> std::string { | ||
| 35 | + auto it = jsonVersion.find(key); | ||
| 36 | + if (it == jsonVersion.end()) { | ||
| 37 | + IOTC_LOGW("VersionInfo::ConstructorByJson key not found: %s", key.c_str()); | ||
| 38 | + return ""; | ||
| 39 | + } | ||
| 40 | + return it->second; | ||
| 41 | + }; | ||
| 42 | + | ||
| 43 | + info.currentComponentVersion_ = getValue(CommonConstants::KEY_CURRENT_VERSION); | ||
| 44 | + info.supportComponentMinVersion_ = getValue(CommonConstants::KEY_MIN_VERSION); | ||
| 45 | + std::string supportVer = getValue(CommonConstants::KEY_SUPPORT_VERSION); | ||
| 46 | + if (!supportVer.empty()) { | ||
| 47 | + info.supportComponentVersionList_.push_back(supportVer); | ||
| 48 | + } | ||
| 49 | + return info; | ||
| 50 | +} | ||
| 51 | + | ||
| 52 | +VersionInfo VersionInfo::ConstructorByOther(const std::string& currentVersion, const std::string& supportMinVersion, | ||
| 53 | + const std::vector<std::string>& supportVersionList) | ||
| 54 | +{ | ||
| 55 | + VersionInfo versionInfo; | ||
| 56 | + versionInfo.currentComponentVersion_ = currentVersion; | ||
| 57 | + versionInfo.supportComponentMinVersion_ = supportMinVersion; | ||
| 58 | + versionInfo.supportComponentVersionList_ = supportVersionList; | ||
| 59 | + return versionInfo; | ||
| 60 | +} | ||
| 61 | + | ||
| 62 | +std::map<std::string, std::string> VersionInfo::GetJsonVersionInfo() const | ||
| 63 | +{ | ||
| 64 | + std::map<std::string, std::string> jsonVersion; | ||
| 65 | + jsonVersion[CommonConstants::KEY_CURRENT_VERSION] = currentComponentVersion_; | ||
| 66 | + jsonVersion[CommonConstants::KEY_MIN_VERSION] = supportComponentMinVersion_; | ||
| 67 | + return jsonVersion; | ||
| 68 | +} | ||
| 69 | + | ||
| 70 | +std::string VersionInfo::GetCurrentVersion() const | ||
| 71 | +{ | ||
| 72 | + return currentComponentVersion_; | ||
| 73 | +} | ||
| 74 | + | ||
| 75 | +void VersionInfo::SetCurrentVersion(const std::string& version) | ||
| 76 | +{ | ||
| 77 | + if (version.empty()) { | ||
| 78 | + return; | ||
| 79 | + } | ||
| 80 | + currentComponentVersion_ = version; | ||
| 81 | +} | ||
| 82 | + | ||
| 83 | +std::string VersionInfo::GetSupportMinVersion() const | ||
| 84 | +{ | ||
| 85 | + return supportComponentMinVersion_; | ||
| 86 | +} | ||
| 87 | + | ||
| 88 | +void VersionInfo::SetSupportMinVersion(const std::string& version) | ||
| 89 | +{ | ||
| 90 | + if (version.empty()) { | ||
| 91 | + return; | ||
| 92 | + } | ||
| 93 | + supportComponentMinVersion_ = version; | ||
| 94 | +} | ||
| 95 | + | ||
| 96 | +std::vector<std::string> VersionInfo::GetSupportVersionList() const | ||
| 97 | +{ | ||
| 98 | + return supportComponentVersionList_; | ||
| 99 | +} | ||
| 100 | + | ||
| 101 | +void VersionInfo::SetSupportVersionList(const std::vector<std::string>& versionList) | ||
| 102 | +{ | ||
| 103 | + supportComponentVersionList_ = versionList; | ||
| 104 | +} | ||
| 105 | + | ||
| 106 | +} // namespace IotcManagement | ||
| 107 | +} // namespace OHOS | ||
| @@ -0,0 +1,60 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | +namespace OHOS { | ||
| 25 | +namespace IotcManagement { | ||
| 26 | + | ||
| 27 | +class PayloadResponse; | ||
| 28 | + | ||
| 29 | +class VersionInfo { | ||
| 30 | +public: | ||
| 31 | + friend class PayloadResponse; | ||
| 32 | + | ||
| 33 | + static VersionInfo ConstructorByJson(const std::map<std::string, std::string>& jsonVersion); | ||
| 34 | + | ||
| 35 | + static VersionInfo ConstructorByOther(const std::string& currentVersion, const std::string& supportMinVersion, | ||
| 36 | + const std::vector<std::string>& supportVersionList); | ||
| 37 | + | ||
| 38 | + std::map<std::string, std::string> GetJsonVersionInfo() const; | ||
| 39 | + | ||
| 40 | + std::string GetCurrentVersion() const; | ||
| 41 | + void SetCurrentVersion(const std::string& version); | ||
| 42 | + | ||
| 43 | + std::string GetSupportMinVersion() const; | ||
| 44 | + void SetSupportMinVersion(const std::string& version); | ||
| 45 | + | ||
| 46 | + std::vector<std::string> GetSupportVersionList() const; | ||
| 47 | + void SetSupportVersionList(const std::vector<std::string>& versionList); | ||
| 48 | + | ||
| 49 | +private: | ||
| 50 | + VersionInfo(); | ||
| 51 | + | ||
| 52 | + std::string currentComponentVersion_; | ||
| 53 | + std::string supportComponentMinVersion_; | ||
| 54 | + std::vector<std::string> supportComponentVersionList_; | ||
| 55 | +}; | ||
| 56 | + | ||
| 57 | +} // namespace IotcManagement | ||
| 58 | +} // namespace OHOS | ||
| 59 | + | ||
| 60 | + | ||
| @@ -0,0 +1,76 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | +namespace OHOS { | ||
| 24 | +namespace IotcManagement { | ||
| 25 | + | ||
| 26 | +AuthKeyAgreeRequest::AuthKeyAgreeRequest(std::shared_ptr<OperationParameter> operationParams, bool isClient, | ||
| 27 | + const ConfirmParams& confirmParams) | ||
| 28 | + : RequestBase(operationParams, GlobalParams::AKA_TIMEOUT) | ||
| 29 | +{ | ||
| 30 | + mRequestOperation_ = OperationCode::AUTH_KEY_AGREEMENT; | ||
| 31 | + mRequestStatus_ = std::make_shared<RequestStatus>(isClient); | ||
| 32 | + operationParams_ = operationParams; | ||
| 33 | + pin_ = confirmParams.GetPin(); | ||
| 34 | + keyLength_ = confirmParams.GetKeyLength(); | ||
| 35 | +} | ||
| 36 | + | ||
| 37 | +void AuthKeyAgreeRequest::Init() | ||
| 38 | +{ | ||
| 39 | + std::weak_ptr<RequestBase> weakThis = weak_from_this(); | ||
| 40 | + auto wrapper = std::make_shared<TaskFeedbackImpl>(); | ||
| 41 | + wrapper->onTaskHalted = [weakThis](int32_t operationResult) { | ||
| 42 | + auto self = weakThis.lock(); | ||
| 43 | + if (!self) { | ||
| 44 | + IOTC_LOGW("onFailure: wrapper already destroyed"); | ||
| 45 | + return; | ||
| 46 | + } | ||
| 47 | + self->OnTaskHalted(operationResult); | ||
| 48 | + }; | ||
| 49 | + | ||
| 50 | + wrapper->onTaskFinished = [weakThis](int32_t operationResult, const std::vector<uint8_t>& returnData) { | ||
| 51 | + auto self = weakThis.lock(); | ||
| 52 | + if (!self) { | ||
| 53 | + IOTC_LOGW("onFailure: wrapper already destroyed"); | ||
| 54 | + return; | ||
| 55 | + } | ||
| 56 | + self->OnTaskFinished(operationResult, returnData); | ||
| 57 | + }; | ||
| 58 | + | ||
| 59 | + wrapper->onDataTransmit = [weakThis](const std::string& sessionId, const std::vector<uint8_t>& data) { | ||
| 60 | + auto self = weakThis.lock(); | ||
| 61 | + if (!self) { | ||
| 62 | + IOTC_LOGW("onFailure: wrapper already destroyed"); | ||
| 63 | + return false; | ||
| 64 | + } | ||
| 65 | + return self->OnDataTransmit(sessionId, data); | ||
| 66 | + }; | ||
| 67 | + | ||
| 68 | + pakeTask_ = std::make_shared<SpekeTask>(operationParams_, wrapper, mRequestStatus_->IsClient()); | ||
| 69 | + pakeTask_->SetPin(pin_); | ||
| 70 | + pakeTask_->SetKeyLen(keyLength_); | ||
| 71 | + mTaskList_.push_back(pakeTask_.get()); | ||
| 72 | + mCurrentTask_ = pakeTask_.get(); | ||
| 73 | +} | ||
| 74 | + | ||
| 75 | +} // namespace IotcManagement | ||
| 76 | +} // namespace OHOS | ||
| @@ -0,0 +1,43 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | +namespace OHOS { | ||
| 25 | +namespace IotcManagement { | ||
| 26 | + | ||
| 27 | +class AuthKeyAgreeRequest : public RequestBase { | ||
| 28 | +public: | ||
| 29 | + AuthKeyAgreeRequest(std::shared_ptr<OperationParameter> operationParams, bool isClient, | ||
| 30 | + const ConfirmParams& confirmParams); | ||
| 31 | + void Init(); | ||
| 32 | + | ||
| 33 | +private: | ||
| 34 | + std::shared_ptr<OperationParameter> operationParams_; | ||
| 35 | + std::shared_ptr<SpekeTask> pakeTask_; | ||
| 36 | + std::string pin_; | ||
| 37 | + int32_t keyLength_; | ||
| 38 | +}; | ||
| 39 | + | ||
| 40 | +} // namespace IotcManagement | ||
| 41 | +} // namespace OHOS | ||
| 42 | + | ||
| 43 | + | ||
| @@ -0,0 +1,287 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | + | ||
| 26 | +namespace OHOS { | ||
| 27 | +namespace IotcManagement { | ||
| 28 | + | ||
| 29 | +RequestBase::RequestBase(std::shared_ptr<OperationParameter> operationParams, uint32_t timeoutDelay) | ||
| 30 | + : mRequestStatus_(nullptr), mRequestOperation_(-1), mCurrentTask_(nullptr) | ||
| 31 | +{ | ||
| 32 | + mCallbackHandler_ = operationParams->GetCallbackHandler(); | ||
| 33 | + mSessionId_ = operationParams->GetSessionId(); | ||
| 34 | + | ||
| 35 | + uint32_t taskTimeoutDelay = GlobalParams::BIND_TIMEOUT; | ||
| 36 | + if (timeoutDelay > 0) { | ||
| 37 | + taskTimeoutDelay = timeoutDelay; | ||
| 38 | + } | ||
| 39 | + StartTimer(taskTimeoutDelay); | ||
| 40 | +} | ||
| 41 | + | ||
| 42 | +RequestBase::~RequestBase() | ||
| 43 | +{ | ||
| 44 | + delayedTimer_->Stop(); | ||
| 45 | +} | ||
| 46 | + | ||
| 47 | +void RequestBase::StartTimer(uint32_t timeoutDelay) | ||
| 48 | +{ | ||
| 49 | + if (delayedTimer_) { | ||
| 50 | + delayedTimer_->Stop(); | ||
| 51 | + } | ||
| 52 | + delayedTimer_ = std::unique_ptr<DelayedTimer>(new DelayedTimer(timeoutDelay, [this]() { | ||
| 53 | + this->RemindTask(); | ||
| 54 | + })); | ||
| 55 | + delayedTimer_->Start(); | ||
| 56 | +} | ||
| 57 | + | ||
| 58 | +void RequestBase::StopTimer() | ||
| 59 | +{ | ||
| 60 | + if (delayedTimer_) { | ||
| 61 | + delayedTimer_->Stop(); | ||
| 62 | + } | ||
| 63 | +} | ||
| 64 | + | ||
| 65 | +bool RequestBase::FinishRequest(int32_t operationResult, const std::vector<uint8_t>& returnData, bool cancelTask) | ||
| 66 | +{ | ||
| 67 | + bool expected = false; | ||
| 68 | + if (!finished_.compare_exchange_strong(expected, true)) { | ||
| 69 | + IOTC_LOGW("RequestBase::FinishRequest ignored duplicate terminal result: %{public}d", operationResult); | ||
| 70 | + return false; | ||
| 71 | + } | ||
| 72 | + | ||
| 73 | + // Removing the manager entry may release the last external reference. | ||
| 74 | + // Keep the request alive until cleanup and callback delivery are complete. | ||
| 75 | + auto keepAlive = weak_from_this().lock(); | ||
| 76 | + if (!keepAlive) { | ||
| 77 | + IOTC_LOGW("RequestBase::FinishRequest request is not shared-managed"); | ||
| 78 | + } | ||
| 79 | + const std::string sessionId = mSessionId_; | ||
| 80 | + const int32_t operation = mRequestOperation_; | ||
| 81 | + auto callbackHandler = mCallbackHandler_; | ||
| 82 | + | ||
| 83 | + if (cancelTask) { | ||
| 84 | + if (mRequestStatus_ != nullptr) { | ||
| 85 | + mRequestStatus_->Halt(); | ||
| 86 | + } | ||
| 87 | + if (mCurrentTask_ != nullptr) { | ||
| 88 | + mCurrentTask_->DoCancel(); | ||
| 89 | + } | ||
| 90 | + } | ||
| 91 | + | ||
| 92 | + StopTimer(); | ||
| 93 | + RequestManager::GetInstance().DeleteRequest(sessionId); | ||
| 94 | + if (callbackHandler) { | ||
| 95 | + callbackHandler->OnOperationFinished(sessionId, operation, operationResult, returnData); | ||
| 96 | + } | ||
| 97 | + return true; | ||
| 98 | +} | ||
| 99 | + | ||
| 100 | +void RequestBase::OnTaskHalted(int32_t operationResult) | ||
| 101 | +{ | ||
| 102 | + IOTC_LOGI("RequestBase::OnTaskHalted"); | ||
| 103 | + if (finished_.load() || mRequestStatus_ == nullptr || mRequestStatus_->IsCanceled() || | ||
| 104 | + mRequestStatus_->IsFinished()) { | ||
| 105 | + return; | ||
| 106 | + } | ||
| 107 | + Halt(operationResult); | ||
| 108 | +} | ||
| 109 | + | ||
| 110 | +void RequestBase::OnTaskFinished(int32_t operationResult, const std::vector<uint8_t>& returnData) | ||
| 111 | +{ | ||
| 112 | + IOTC_LOGI("RequestBase::OnTaskFinished"); | ||
| 113 | + if (finished_.load() || mRequestStatus_ == nullptr || mRequestStatus_->IsCanceled() || | ||
| 114 | + mRequestStatus_->IsFinished()) { | ||
| 115 | + return; | ||
| 116 | + } | ||
| 117 | + | ||
| 118 | + if (!mTaskList_.empty()) { | ||
| 119 | + mTaskList_.erase(mTaskList_.begin()); | ||
| 120 | + } | ||
| 121 | + | ||
| 122 | + if (operationResult != ReturnCode::SUCCESS && !mTaskList_.empty()) { | ||
| 123 | + InformPeerAndCancel(operationResult); | ||
| 124 | + return; | ||
| 125 | + } | ||
| 126 | + | ||
| 127 | + if (mCurrentTask_ != nullptr && mCurrentTask_->IsSpekeTask()) { | ||
| 128 | + mCallbackHandler_->OnSessionKeyReturned(mSessionId_, returnData); | ||
| 129 | + } | ||
| 130 | + | ||
| 131 | + if (!mTaskList_.empty()) { | ||
| 132 | + mCurrentTask_ = mTaskList_.front(); | ||
| 133 | + if (mCurrentTask_ != nullptr) { | ||
| 134 | + mCurrentTask_->Init(returnData); | ||
| 135 | + if (mRequestStatus_->IsClient()) { | ||
| 136 | + int32_t ret = mCurrentTask_->DoStart(); | ||
| 137 | + if (ret != ReturnCode::SUCCESS) { | ||
| 138 | + Halt(ret); | ||
| 139 | + } | ||
| 140 | + } | ||
| 141 | + } | ||
| 142 | + } else { | ||
| 143 | + mRequestStatus_->NextStatus(); | ||
| 144 | + IOTC_LOGD("RequestBase::OnTaskFinished next status"); | ||
| 145 | + DoStop(operationResult, returnData); | ||
| 146 | + } | ||
| 147 | +} | ||
| 148 | + | ||
| 149 | +bool RequestBase::OnDataTransmit(const std::string& sessionId, const std::vector<uint8_t>& data) | ||
| 150 | +{ | ||
| 151 | + IOTC_LOGI("RequestBase::OnDataTransmit"); | ||
| 152 | + if (mCallbackHandler_) { | ||
| 153 | + return mCallbackHandler_->OnDataTransmit(sessionId, data); | ||
| 154 | + } | ||
| 155 | + return false; | ||
| 156 | +} | ||
| 157 | + | ||
| 158 | +std::string RequestBase::GetSessionId() const | ||
| 159 | +{ | ||
| 160 | + return mSessionId_; | ||
| 161 | +} | ||
| 162 | + | ||
| 163 | +std::shared_ptr<StatusBase> RequestBase::GetRequestStatus() const | ||
| 164 | +{ | ||
| 165 | + return mRequestStatus_; | ||
| 166 | +} | ||
| 167 | + | ||
| 168 | +void RequestBase::DoStart() | ||
| 169 | +{ | ||
| 170 | + IOTC_LOGI("RequestBase::DoStart"); | ||
| 171 | + if (mTaskList_.empty()) { | ||
| 172 | + IOTC_LOGE("RequestBase::DoStart mTaskList_ is empty"); | ||
| 173 | + return; | ||
| 174 | + } | ||
| 175 | + mCurrentTask_ = mTaskList_.front(); | ||
| 176 | + if (mCurrentTask_ == nullptr) { | ||
| 177 | + IOTC_LOGE("RequestBase::DoStart mCurrentTask_ is null"); | ||
| 178 | + return; | ||
| 179 | + } | ||
| 180 | + int32_t ret = mCurrentTask_->DoStart(); | ||
| 181 | + if (ret == ReturnCode::SUCCESS) { | ||
| 182 | + if (mRequestStatus_ != nullptr) { | ||
| 183 | + mRequestStatus_->NextStatus(); | ||
| 184 | + } | ||
| 185 | + } else { | ||
| 186 | + Halt(ret); | ||
| 187 | + } | ||
| 188 | +} | ||
| 189 | + | ||
| 190 | +void RequestBase::DoStop(int32_t operationResult, const std::vector<uint8_t>& returnData) | ||
| 191 | +{ | ||
| 192 | + IOTC_LOGI("RequestBase::DoStop"); | ||
| 193 | + if (FinishRequest(operationResult, returnData, false)) { | ||
| 194 | + IOTC_LOGD("RequestBase::DoStop return operation result to caller"); | ||
| 195 | + } | ||
| 196 | +} | ||
| 197 | + | ||
| 198 | +void RequestBase::Halt(int32_t operationResult) | ||
| 199 | +{ | ||
| 200 | + IOTC_LOGE("RequestBase::Halt, operationResult: %{public}d", operationResult); | ||
| 201 | + if (FinishRequest(operationResult, std::vector<uint8_t>{}, true)) { | ||
| 202 | + IOTC_LOGE("RequestBase::Halt request is canceled because of exceptions"); | ||
| 203 | + } | ||
| 204 | +} | ||
| 205 | + | ||
| 206 | +void RequestBase::InformPeerAndCancel(int32_t operationResult) | ||
| 207 | +{ | ||
| 208 | + if (mCallbackHandler_) { | ||
| 209 | + IotcJsonObject* sendData = IotcJsonObject::CreateObject(); | ||
| 210 | + if (sendData != nullptr && sendData->GetJsonObject() != nullptr) { | ||
| 211 | + sendData->AddNumber2Obj(CommonConstants::KEY_MESSAGE, MessageCode::INFORM_MESSAGE); | ||
| 212 | + IotcJsonObject* payload = IotcJsonObject::CreateObject(); | ||
| 213 | + if (payload != nullptr && payload->GetJsonObject() != nullptr) { | ||
| 214 | + payload->AddNumber2Obj(CommonConstants::KEY_ERROR_CODE, operationResult); | ||
| 215 | + sendData->AddItem2Obj(CommonConstants::KEY_PAYLOAD, *payload); | ||
| 216 | + std::string jsonStr = sendData->Print2String(); | ||
| 217 | + std::vector<uint8_t> sendBytes = CommonUtil::StringToBytes(jsonStr); | ||
| 218 | + mCallbackHandler_->OnDataTransmit(mSessionId_, sendBytes); | ||
| 219 | + IOTC_LOGD("RequestBase::InformPeerAndCancel send passThrough data of request"); | ||
| 220 | + delete payload; | ||
| 221 | + } | ||
| 222 | + sendData->DeleteJson(); | ||
| 223 | + delete sendData; | ||
| 224 | + } | ||
| 225 | + } | ||
| 226 | + Halt(operationResult); | ||
| 227 | +} | ||
| 228 | + | ||
| 229 | +void RequestBase::DoCancel() | ||
| 230 | +{ | ||
| 231 | + IOTC_LOGI("RequestBase::DoCancel, status: %{public}d", | ||
| 232 | + mRequestStatus_ != nullptr ? mRequestStatus_->GetStatus() : -1); | ||
| 233 | + if (FinishRequest(ReturnCode::CANCELED, std::vector<uint8_t>{}, true)) { | ||
| 234 | + IOTC_LOGI("RequestBase::DoCancel request is canceled as demanded"); | ||
| 235 | + } | ||
| 236 | +} | ||
| 237 | + | ||
| 238 | +int32_t RequestBase::ProcessReceivedData(const std::string& receivedData) | ||
| 239 | +{ | ||
| 240 | + if (finished_.load() || mRequestStatus_ == nullptr || mRequestStatus_->IsFinished() || | ||
| 241 | + mRequestStatus_->IsCanceled()) { | ||
| 242 | + IOTC_LOGW("RequestBase::ProcessReceivedData receive data to death request"); | ||
| 243 | + OnTaskHalted(ReturnCode::INVALID_PARAMETERS); | ||
| 244 | + return ReturnCode::REQUEST_NOT_FOUND; | ||
| 245 | + } | ||
| 246 | + | ||
| 247 | + if (mTaskList_.empty()) { | ||
| 248 | + IOTC_LOGE("RequestBase::ProcessReceivedData mTaskList_ is empty"); | ||
| 249 | + OnTaskHalted(ReturnCode::INVALID_PARAMETERS); | ||
| 250 | + return ReturnCode::INVALID_PARAMETERS; | ||
| 251 | + } | ||
| 252 | + | ||
| 253 | + mCurrentTask_ = mTaskList_.front(); | ||
| 254 | + | ||
| 255 | + if (mCurrentTask_ == nullptr) { | ||
| 256 | + IOTC_LOGE("RequestBase::ProcessReceivedData mCurrentTask_ is null"); | ||
| 257 | + InformPeerAndCancel(ReturnCode::FAILED); | ||
| 258 | + return ReturnCode::FAILED; | ||
| 259 | + } | ||
| 260 | + | ||
| 261 | + int32_t ret = mCurrentTask_->ProcessReceivedData(receivedData); | ||
| 262 | + if (ret != ReturnCode::SUCCESS) { | ||
| 263 | + IOTC_LOGE("RequestBase::ProcessReceivedData task failed ret=%{public}d", ret); | ||
| 264 | + OnTaskHalted(ret); | ||
| 265 | + } | ||
| 266 | + return ret; | ||
| 267 | +} | ||
| 268 | + | ||
| 269 | +void RequestBase::RemindTask() | ||
| 270 | +{ | ||
| 271 | + IOTC_LOGI("RequestBase::RemindTask request timeout"); | ||
| 272 | + auto keepAlive = weak_from_this().lock(); | ||
| 273 | + if (!keepAlive) { | ||
| 274 | + IOTC_LOGW("RequestBase::RemindTask request already released"); | ||
| 275 | + return; | ||
| 276 | + } | ||
| 277 | + if (mRequestStatus_ == nullptr || mRequestStatus_->IsCanceled() || mRequestStatus_->IsFinished() || | ||
| 278 | + finished_.load()) { | ||
| 279 | + return; | ||
| 280 | + } | ||
| 281 | + if (FinishRequest(ReturnCode::TIMEOUT, std::vector<uint8_t>{}, true)) { | ||
| 282 | + IOTC_LOGI("RequestBase::RemindTask release task success"); | ||
| 283 | + } | ||
| 284 | +} | ||
| 285 | + | ||
| 286 | +} // namespace IotcManagement | ||
| 287 | +} // namespace OHOS | ||
| @@ -0,0 +1,87 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | + | ||
| 26 | + | ||
| 27 | + | ||
| 28 | + | ||
| 29 | +namespace OHOS { | ||
| 30 | +namespace IotcManagement { | ||
| 31 | + | ||
| 32 | +class TaskBase; | ||
| 33 | +class StatusBase; | ||
| 34 | + | ||
| 35 | +class RequestBase : public TaskFeedback ,public std::enable_shared_from_this<RequestBase> { | ||
| 36 | +public: | ||
| 37 | + RequestBase(std::shared_ptr<OperationParameter> operationParams, uint32_t timeoutDelay); | ||
| 38 | + virtual ~RequestBase(); | ||
| 39 | + | ||
| 40 | + void OnTaskHalted(int32_t operationResult) override; | ||
| 41 | + | ||
| 42 | + void OnTaskFinished(int32_t operationResult, const std::vector<uint8_t>& returnData) override; | ||
| 43 | + | ||
| 44 | + bool OnDataTransmit(const std::string& sessionId, const std::vector<uint8_t>& data) override; | ||
| 45 | + | ||
| 46 | + void DoStart(); | ||
| 47 | + | ||
| 48 | + void DoCancel(); | ||
| 49 | + | ||
| 50 | + int32_t ProcessReceivedData(const std::string& receivedData); | ||
| 51 | + | ||
| 52 | + std::shared_ptr<StatusBase> GetRequestStatus() const; | ||
| 53 | + | ||
| 54 | + std::string GetSessionId() const; | ||
| 55 | + | ||
| 56 | +protected: | ||
| 57 | + | ||
| 58 | + std::vector<TaskBase*> mTaskList_; | ||
| 59 | + std::shared_ptr<StatusBase> mRequestStatus_; | ||
| 60 | + int32_t mRequestOperation_; | ||
| 61 | + TaskBase* mCurrentTask_; | ||
| 62 | + | ||
| 63 | +private: | ||
| 64 | + void DoStop(int32_t operationResult, const std::vector<uint8_t>& returnData); | ||
| 65 | + | ||
| 66 | + void Halt(int32_t operationResult); | ||
| 67 | + | ||
| 68 | + void InformPeerAndCancel(int32_t operationResult); | ||
| 69 | + | ||
| 70 | + void RemindTask(); | ||
| 71 | + | ||
| 72 | + void StartTimer(uint32_t timeoutDelay); | ||
| 73 | + | ||
| 74 | + void StopTimer(); | ||
| 75 | + | ||
| 76 | + bool FinishRequest(int32_t operationResult, const std::vector<uint8_t>& returnData, bool cancelTask); | ||
| 77 | + | ||
| 78 | + std::shared_ptr<HwDevAuthCallback> mCallbackHandler_; | ||
| 79 | + std::string mSessionId_; | ||
| 80 | + std::unique_ptr<DelayedTimer> delayedTimer_; | ||
| 81 | + std::atomic<bool> finished_ {false}; | ||
| 82 | +}; | ||
| 83 | + | ||
| 84 | +} // namespace IotcManagement | ||
| 85 | +} // namespace OHOS | ||
| 86 | + | ||
| 87 | + | ||
| @@ -0,0 +1,82 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | +namespace OHOS { | ||
| 22 | +namespace IotcManagement { | ||
| 23 | + | ||
| 24 | +RequestManager& RequestManager::GetInstance() | ||
| 25 | +{ | ||
| 26 | + static RequestManager instance; | ||
| 27 | + return instance; | ||
| 28 | +} | ||
| 29 | + | ||
| 30 | +int32_t RequestManager::AddRequest(const std::string& sessionId, std::shared_ptr<RequestBase> request) | ||
| 31 | +{ | ||
| 32 | + std::lock_guard<std::mutex> lock(mutex_); | ||
| 33 | + if (requestMap_.find(sessionId) != requestMap_.end()) { | ||
| 34 | + IOTC_LOGW("RequestManager::AddRequest session already exists: %{public}s", sessionId.c_str()); | ||
| 35 | + return ReturnCode::CONFLICT_REQUEST; | ||
| 36 | + } | ||
| 37 | + requestMap_[sessionId] = request; | ||
| 38 | + IOTC_LOGI("RequestManager::AddRequest add request: %{public}s", sessionId.c_str()); | ||
| 39 | + return ReturnCode::REQUEST_ACCEPTED; | ||
| 40 | +} | ||
| 41 | + | ||
| 42 | +std::shared_ptr<RequestBase> RequestManager::GetRequest(const std::string& sessionId) const | ||
| 43 | +{ | ||
| 44 | + std::lock_guard<std::mutex> lock(mutex_); | ||
| 45 | + auto it = requestMap_.find(sessionId); | ||
| 46 | + if (it == requestMap_.end()) { | ||
| 47 | + IOTC_LOGW("RequestManager::GetRequest request not found: %{public}s", sessionId.c_str()); | ||
| 48 | + return nullptr; | ||
| 49 | + } | ||
| 50 | + return it->second; | ||
| 51 | +} | ||
| 52 | + | ||
| 53 | +int32_t RequestManager::DeleteRequest(const std::string& sessionId) | ||
| 54 | +{ | ||
| 55 | + std::lock_guard<std::mutex> lock(mutex_); | ||
| 56 | + auto it = requestMap_.find(sessionId); | ||
| 57 | + if (it == requestMap_.end()) { | ||
| 58 | + IOTC_LOGW("RequestManager::DeleteRequest request not found: %{public}s", sessionId.c_str()); | ||
| 59 | + return ReturnCode::REQUEST_NOT_FOUND; | ||
| 60 | + } | ||
| 61 | + requestMap_.erase(it); | ||
| 62 | + IOTC_LOGI("RequestManager::DeleteRequest delete request: %{public}s", sessionId.c_str()); | ||
| 63 | + return ReturnCode::SUCCESS; | ||
| 64 | +} | ||
| 65 | + | ||
| 66 | +std::string RequestManager::GetOnlyRequestSessionId() const | ||
| 67 | +{ | ||
| 68 | + std::lock_guard<std::mutex> lock(mutex_); | ||
| 69 | + if (requestMap_.size() != 1) { | ||
| 70 | + return ""; | ||
| 71 | + } | ||
| 72 | + return requestMap_.begin()->first; | ||
| 73 | +} | ||
| 74 | + | ||
| 75 | +void RequestManager::Clear() | ||
| 76 | +{ | ||
| 77 | + std::lock_guard<std::mutex> lock(mutex_); | ||
| 78 | + requestMap_.clear(); | ||
| 79 | +} | ||
| 80 | + | ||
| 81 | +} // namespace IotcManagement | ||
| 82 | +} // namespace OHOS | ||
| @@ -0,0 +1,54 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | +namespace OHOS { | ||
| 25 | +namespace IotcManagement { | ||
| 26 | + | ||
| 27 | +class RequestBase; | ||
| 28 | + | ||
| 29 | +class RequestManager { | ||
| 30 | +public: | ||
| 31 | + static RequestManager& GetInstance(); | ||
| 32 | + | ||
| 33 | + int32_t AddRequest(const std::string& sessionId, std::shared_ptr<RequestBase> request); | ||
| 34 | + | ||
| 35 | + std::shared_ptr<RequestBase> GetRequest(const std::string& sessionId) const; | ||
| 36 | + | ||
| 37 | + int32_t DeleteRequest(const std::string& sessionId); | ||
| 38 | + | ||
| 39 | + std::string GetOnlyRequestSessionId() const; | ||
| 40 | + | ||
| 41 | + void Clear(); | ||
| 42 | + | ||
| 43 | +private: | ||
| 44 | + RequestManager() = default; | ||
| 45 | + ~RequestManager() = default; | ||
| 46 | + | ||
| 47 | + std::map<std::string, std::shared_ptr<RequestBase>> requestMap_; | ||
| 48 | + mutable std::mutex mutex_; | ||
| 49 | +}; | ||
| 50 | + | ||
| 51 | +} // namespace IotcManagement | ||
| 52 | +} // namespace OHOS | ||
| 53 | + | ||
| 54 | + | ||
| @@ -0,0 +1,47 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | +namespace OHOS { | ||
| 20 | +namespace IotcManagement { | ||
| 21 | + | ||
| 22 | +RequestStatus::RequestStatus(bool isClient) | ||
| 23 | + : StatusBase(isClient) | ||
| 24 | +{ | ||
| 25 | + if (!isClient) { | ||
| 26 | + mStatus_ = BUSY; | ||
| 27 | + } | ||
| 28 | +} | ||
| 29 | + | ||
| 30 | +void RequestStatus::NextStatus() | ||
| 31 | +{ | ||
| 32 | + IOTC_LOGI("RequestStatus::NextStatus old status = %{public}d", mStatus_); | ||
| 33 | + switch (mStatus_) { | ||
| 34 | + case BUSY: | ||
| 35 | + mStatus_ = FINISH; | ||
| 36 | + break; | ||
| 37 | + case INITIAL: | ||
| 38 | + mStatus_ = BUSY; | ||
| 39 | + break; | ||
| 40 | + default: | ||
| 41 | + break; | ||
| 42 | + } | ||
| 43 | + IOTC_LOGI("RequestStatus::NextStatus current status = %{public}d", mStatus_); | ||
| 44 | +} | ||
| 45 | + | ||
| 46 | +} // namespace IotcManagement | ||
| 47 | +} // namespace OHOS | ||
| @@ -0,0 +1,35 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | +namespace OHOS { | ||
| 23 | +namespace IotcManagement { | ||
| 24 | + | ||
| 25 | +class RequestStatus : public StatusBase { | ||
| 26 | +public: | ||
| 27 | + RequestStatus(bool isClient); | ||
| 28 | + | ||
| 29 | + void NextStatus() override; | ||
| 30 | +}; | ||
| 31 | + | ||
| 32 | +} // namespace IotcManagement | ||
| 33 | +} // namespace OHOS | ||
| 34 | + | ||
| 35 | + | ||
| @@ -0,0 +1,506 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | + | ||
| 26 | + | ||
| 27 | + | ||
| 28 | + | ||
| 29 | +namespace OHOS { | ||
| 30 | +namespace IotcManagement { | ||
| 31 | + | ||
| 32 | +SpekeTask::SpekeTask(std::shared_ptr<OperationParameter> operationParameter, std::shared_ptr<TaskFeedback> taskFeedback, bool isClient) | ||
| 33 | + : TaskBase(operationParameter, taskFeedback), returnKeyLen_(0), isClient_(isClient) | ||
| 34 | +{ | ||
| 35 | + hmacKey_.resize(GlobalParams::SESSION_KEY_LENGTH); | ||
| 36 | + taskStatus_ = std::make_shared<SpekeTaskStatus>(isClient); | ||
| 37 | +} | ||
| 38 | + | ||
| 39 | +void SpekeTask::SetPin(const std::string& pin) | ||
| 40 | +{ | ||
| 41 | + pin_ = pin; | ||
| 42 | +} | ||
| 43 | + | ||
| 44 | +void SpekeTask::SetKeyLen(int32_t keyLength) | ||
| 45 | +{ | ||
| 46 | + if (keyLength < 0) { | ||
| 47 | + returnKeyLen_ = 0; | ||
| 48 | + } else if (static_cast<uint32_t>(keyLength) > GlobalParams::MAX_KEY_LEN) { | ||
| 49 | + returnKeyLen_ = GlobalParams::MAX_KEY_LEN; | ||
| 50 | + } else { | ||
| 51 | + returnKeyLen_ = keyLength; | ||
| 52 | + } | ||
| 53 | +} | ||
| 54 | + | ||
| 55 | +bool SpekeTask::IsSpekeTask() const | ||
| 56 | +{ | ||
| 57 | + return true; | ||
| 58 | +} | ||
| 59 | + | ||
| 60 | +int32_t SpekeTask::DoStart() | ||
| 61 | +{ | ||
| 62 | + return SendSpekeStartRequest(); | ||
| 63 | +} | ||
| 64 | + | ||
| 65 | +int32_t SpekeTask::SendSpekeStartRequest() | ||
| 66 | +{ | ||
| 67 | + IOTC_LOGI("SpekeTask::SendSpekeStartRequest"); | ||
| 68 | + IotcJsonObject* dataJosn = IotcJsonObject::CreateObject(); | ||
| 69 | + if (dataJosn == nullptr || dataJosn->GetJsonObject() == nullptr) { | ||
| 70 | + IOTC_LOGE("SendSpekeStartRequest failed create json error"); | ||
| 71 | + if (dataJosn != nullptr) delete dataJosn; | ||
| 72 | + return ReturnCode::FAILED; | ||
| 73 | + } | ||
| 74 | + VersionInfo versionInfo = GetVersionInfo(); | ||
| 75 | + std::map<std::string, std::string> versionInfoMap = versionInfo.GetJsonVersionInfo(); | ||
| 76 | + IotcJsonObject* versionInfoJson = IotcJsonObject::CreateObject(); | ||
| 77 | + if (versionInfoJson == nullptr || versionInfoJson->GetJsonObject() == nullptr) { | ||
| 78 | + IOTC_LOGE("SendSpekeStartRequest failed create version json error"); | ||
| 79 | + if (versionInfoJson != nullptr) delete versionInfoJson; | ||
| 80 | + dataJosn->DeleteJson(); | ||
| 81 | + delete dataJosn; | ||
| 82 | + return ReturnCode::FAILED; | ||
| 83 | + } | ||
| 84 | + for (auto& [key, value] : versionInfoMap) { | ||
| 85 | + versionInfoJson->AddString2Obj(key, value); | ||
| 86 | + } | ||
| 87 | + dataJosn->AddItem2Obj(CommonConstants::KEY_VERSION, *versionInfoJson); | ||
| 88 | + dataJosn->AddNumber2Obj(CommonConstants::KEY_OPERATION_CODE, OperationCode::AUTH_KEY_AGREEMENT); | ||
| 89 | + dataJosn->AddBool2Obj(CommonConstants::KEY_SUPPORT256MOD, true); | ||
| 90 | + std::string jsonStr = dataJosn->Print2String(); | ||
| 91 | + dataJosn->DeleteJson(); | ||
| 92 | + delete dataJosn; | ||
| 93 | + delete versionInfoJson; | ||
| 94 | + return SendPassThroughData(MessageCode::SPEKE_REQUEST, jsonStr); | ||
| 95 | +} | ||
| 96 | + | ||
| 97 | +std::vector<uint8_t> SpekeTask::GenerateProof(const std::vector<uint8_t>& beginChallenge, | ||
| 98 | + const std::vector<uint8_t>& endChallenge) | ||
| 99 | +{ | ||
| 100 | + IOTC_LOGI("SpekeTask::GenerateProof"); | ||
| 101 | + std::vector<uint8_t> challenge = CommonUtil::ConcatenateAll({beginChallenge, endChallenge}); | ||
| 102 | + std::vector<uint8_t> result = CryptoKdf::HmacSha256(hmacKey_, challenge); | ||
| 103 | + return result; | ||
| 104 | +} | ||
| 105 | + | ||
| 106 | +int32_t SpekeTask::ProcessReceived(uint16_t messageCode, const PayloadResponse* payload) | ||
| 107 | +{ | ||
| 108 | + IOTC_LOGI("SpekeTask::ProcessReceived messageCode: %{public}d", messageCode); | ||
| 109 | + int32_t ret = ReturnCode::FAILED; | ||
| 110 | + if (payload == nullptr) { | ||
| 111 | + ret = ReturnCode::BAD_PAYLOAD; | ||
| 112 | + if (requestCallback_ != nullptr) { | ||
| 113 | + requestCallback_->OnTaskHalted(ret); | ||
| 114 | + } | ||
| 115 | + return ret; | ||
| 116 | + } | ||
| 117 | + bool isConfirmPhase = false; | ||
| 118 | + switch (messageCode) { | ||
| 119 | + case MessageCode::SPEKE_REQUEST: | ||
| 120 | + ret = SendSpekeResponse(payload); | ||
| 121 | + break; | ||
| 122 | + case MessageCode::SPEKE_RESPONSE: | ||
| 123 | + ret = SendClientConfirm(payload); | ||
| 124 | + break; | ||
| 125 | + case MessageCode::SPEKE_CLIENT_CONFIRM: | ||
| 126 | + isConfirmPhase = true; | ||
| 127 | + ret = SendServerConfirm(payload); | ||
| 128 | + break; | ||
| 129 | + case MessageCode::SPEKE_SERVER_CONFIRM: | ||
| 130 | + isConfirmPhase = true; | ||
| 131 | + ret = VerifyServerConfirm(payload); | ||
| 132 | + break; | ||
| 133 | + case MessageCode::INFORM_MESSAGE: | ||
| 134 | + ret = HandleInformMessage(payload); | ||
| 135 | + break; | ||
| 136 | + default: | ||
| 137 | + break; | ||
| 138 | + } | ||
| 139 | + if (ret != ReturnCode::SUCCESS) { | ||
| 140 | + IOTC_LOGE("SpekeTask::ProcessReceived failed, messageCode=%{public}d ret=%{public}d", | ||
| 141 | + messageCode, ret); | ||
| 142 | + if (requestCallback_ != nullptr) { | ||
| 143 | + requestCallback_->OnTaskHalted(ret); | ||
| 144 | + } | ||
| 145 | + } else if (isConfirmPhase && taskStatus_ != nullptr && taskStatus_->IsFinished()) { | ||
| 146 | + DoStop(ReturnCode::SUCCESS); | ||
| 147 | + } | ||
| 148 | + return ret; | ||
| 149 | +} | ||
| 150 | + | ||
| 151 | +int32_t SpekeTask::SendSpekeResponse(const PayloadResponse* payload) | ||
| 152 | +{ | ||
| 153 | + IOTC_LOGI("SpekeTask::SendSpekeResponse"); | ||
| 154 | + VersionInfo version = payload->GetVersion(); | ||
| 155 | + int32_t ret = ParseAndCheckVersion(&version); | ||
| 156 | + if (ret != ReturnCode::SUCCESS) { | ||
| 157 | + return ret; | ||
| 158 | + } | ||
| 159 | + IotcJsonObject* iotJsonObj = IotcJsonObject::CreateObject(); | ||
| 160 | + if (iotJsonObj == nullptr || iotJsonObj->GetJsonObject() == nullptr) { | ||
| 161 | + IOTC_LOGE("SendSpekeResponse create root json object failed"); | ||
| 162 | + if (iotJsonObj != nullptr) delete iotJsonObj; | ||
| 163 | + return ReturnCode::FAILED; | ||
| 164 | + } | ||
| 165 | + if (salt_.empty()) { | ||
| 166 | + salt_ = CryptoRandom::GenerateRandom(GlobalParams::HKDF_SALT_LENGTH); | ||
| 167 | + } | ||
| 168 | + if (selfChallenge_.empty()) { | ||
| 169 | + selfChallenge_ = CryptoRandom::GenerateRandom(GlobalParams::SPEKE_CHALLENGE_LENGTH); | ||
| 170 | + } | ||
| 171 | + ret = GenerateSpekeParams(); | ||
| 172 | + if (ret != ReturnCode::SUCCESS) { | ||
| 173 | + iotJsonObj->DeleteJson(); | ||
| 174 | + delete iotJsonObj; | ||
| 175 | + return ret; | ||
| 176 | + } | ||
| 177 | + iotJsonObj->AddString2Obj(CommonConstants::FIELD_CHALLENGE, CommonUtil::Uint8ArrayToHexString(selfChallenge_)); | ||
| 178 | + iotJsonObj->AddString2Obj(CommonConstants::FIELD_SALT, CommonUtil::Uint8ArrayToHexString(salt_)); | ||
| 179 | + iotJsonObj->AddString2Obj(CommonConstants::FIELD_ED_PUBLIC, CommonUtil::Uint8ArrayToHexString(selfPublicParam_)); | ||
| 180 | + VersionInfo versionInfo = GetVersionInfo(); | ||
| 181 | + std::map<std::string, std::string> versionInfoMap = versionInfo.GetJsonVersionInfo(); | ||
| 182 | + IotcJsonObject* versionInfoJson = IotcJsonObject::CreateObject(); | ||
| 183 | + if (versionInfoJson != nullptr && versionInfoJson->GetJsonObject() != nullptr) { | ||
| 184 | + for (auto& [key, value] : versionInfoMap) { | ||
| 185 | + versionInfoJson->AddString2Obj(key, value); | ||
| 186 | + } | ||
| 187 | + iotJsonObj->AddItem2Obj(CommonConstants::KEY_VERSION, *versionInfoJson); | ||
| 188 | + } | ||
| 189 | + std::string responseJsonStr = iotJsonObj->Print2String(); | ||
| 190 | + iotJsonObj->DeleteJson(); | ||
| 191 | + delete iotJsonObj; | ||
| 192 | + delete versionInfoJson; | ||
| 193 | + ret = SendPassThroughData(MessageCode::SPEKE_RESPONSE, responseJsonStr); | ||
| 194 | + return ret; | ||
| 195 | +} | ||
| 196 | + | ||
| 197 | +int32_t SpekeTask::SendClientConfirm(const PayloadResponse* payload) | ||
| 198 | +{ | ||
| 199 | + IOTC_LOGI("SpekeTask::SendClientConfirm"); | ||
| 200 | + auto challengeIter = payload->GetChallenge(); | ||
| 201 | + auto saltIter = payload->GetSalt(); | ||
| 202 | + auto epkIter = payload->GetEpk(); | ||
| 203 | + if (challengeIter.empty() || saltIter.empty() || epkIter.empty()) { | ||
| 204 | + IOTC_LOGE("SpekeTask::SendClientConfirm challenge or salt or epk empty"); | ||
| 205 | + return ReturnCode::BAD_PAYLOAD; | ||
| 206 | + } | ||
| 207 | + peerChallenge_ = CommonUtil::ToBytesFromHex(challengeIter); | ||
| 208 | + salt_ = CommonUtil::ToBytesFromHex(saltIter); | ||
| 209 | + peerPublicParam_ = CommonUtil::ToBytesFromHex(epkIter); | ||
| 210 | + | ||
| 211 | + VersionInfo version = payload->GetVersion(); | ||
| 212 | + int32_t ret = DetermineVersion(&version); | ||
| 213 | + if (ret != ReturnCode::SUCCESS) { | ||
| 214 | + return ret; | ||
| 215 | + } | ||
| 216 | + | ||
| 217 | + if (GetNegotiatedProtocol() == CommonConstants::PROTOCOL_VERSION_V2) { | ||
| 218 | + spekeUtil_.SetSpekeType(SpekeType::SPEKE_EC); | ||
| 219 | + } else if (peerPublicParam_.size() <= GlobalParams::SPEKE_PUBLIC_LENGTH_256_MOD) { | ||
| 220 | + spekeUtil_.SetSpekeType(SpekeType::SPEKE_256); | ||
| 221 | + } else if (peerPublicParam_.size() <= GlobalParams::SPEKE_PUBLIC_LENGTH_384_MOD) { | ||
| 222 | + spekeUtil_.SetSpekeType(SpekeType::SPEKE_384); | ||
| 223 | + } else { | ||
| 224 | + IOTC_LOGE("SpekeTask::SendClientConfirm peer public param invalid"); | ||
| 225 | + return ReturnCode::BAD_PAYLOAD; | ||
| 226 | + } | ||
| 227 | + IotcJsonObject* clientConfirmData = IotcJsonObject::CreateObject(); | ||
| 228 | + if (clientConfirmData == nullptr || clientConfirmData->GetJsonObject() == nullptr) { | ||
| 229 | + IOTC_LOGE("SpekeTask::SendClientConfirm create clientConfirmData failed"); | ||
| 230 | + if (clientConfirmData != nullptr) delete clientConfirmData; | ||
| 231 | + return ReturnCode::FAILED; | ||
| 232 | + } | ||
| 233 | + selfChallenge_ = CryptoRandom::GenerateRandom(GlobalParams::SPEKE_CHALLENGE_LENGTH); | ||
| 234 | + ret = GenerateSpekeParams(); | ||
| 235 | + if (ret != ReturnCode::SUCCESS) { | ||
| 236 | + clientConfirmData->DeleteJson(); | ||
| 237 | + delete clientConfirmData; | ||
| 238 | + return ret; | ||
| 239 | + } | ||
| 240 | + ret = GenerateSessionKey(); | ||
| 241 | + if (ret != ReturnCode::SUCCESS) { | ||
| 242 | + clientConfirmData->DeleteJson(); | ||
| 243 | + delete clientConfirmData; | ||
| 244 | + return ret; | ||
| 245 | + } | ||
| 246 | + std::vector<uint8_t> clientProof = GenerateProof(selfChallenge_, peerChallenge_); | ||
| 247 | + if (clientProof.empty()) { | ||
| 248 | + IOTC_LOGE("SpekeTask::SendClientConfirm create clientProof empty"); | ||
| 249 | + clientConfirmData->DeleteJson(); | ||
| 250 | + delete clientConfirmData; | ||
| 251 | + return ReturnCode::FAILED; | ||
| 252 | + } | ||
| 253 | + clientConfirmData->AddString2Obj(CommonConstants::FIELD_CHALLENGE, CommonUtil::Uint8ArrayToHexString(selfChallenge_)); | ||
| 254 | + clientConfirmData->AddString2Obj(CommonConstants::FIELD_ED_PUBLIC, CommonUtil::Uint8ArrayToHexString(selfPublicParam_)); | ||
| 255 | + clientConfirmData->AddString2Obj(CommonConstants::FIELD_CONFIG_DATA, CommonUtil::Uint8ArrayToHexString(clientProof)); | ||
| 256 | + std::string confirmDataStr = clientConfirmData->Print2String(); | ||
| 257 | + clientConfirmData->DeleteJson(); | ||
| 258 | + delete clientConfirmData; | ||
| 259 | + ret = SendPassThroughData(MessageCode::SPEKE_CLIENT_CONFIRM, confirmDataStr); | ||
| 260 | + return ret; | ||
| 261 | +} | ||
| 262 | + | ||
| 263 | +int32_t SpekeTask::SendServerConfirm(const PayloadResponse* payload) | ||
| 264 | +{ | ||
| 265 | + IOTC_LOGI("SpekeTask::SendServerConfirm"); | ||
| 266 | + auto challengeIter = payload->GetChallenge(); | ||
| 267 | + auto configDataIter = payload->GetKcfData(); | ||
| 268 | + auto saltIter = payload->GetSalt(); | ||
| 269 | + auto epkIter = payload->GetEpk(); | ||
| 270 | + if (challengeIter.empty() || saltIter.empty() || epkIter.empty()) { | ||
| 271 | + IOTC_LOGE("SpekeTask::SendServerConfirm challenge or salt or epk empty"); | ||
| 272 | + return ReturnCode::BAD_PAYLOAD; | ||
| 273 | + } | ||
| 274 | + std::vector<uint8_t> clientProof = CommonUtil::ToBytesFromHex(configDataIter); | ||
| 275 | + peerChallenge_ = CommonUtil::ToBytesFromHex(challengeIter); | ||
| 276 | + peerPublicParam_ = CommonUtil::ToBytesFromHex(epkIter); | ||
| 277 | + | ||
| 278 | + IotcJsonObject* serverConfirmData = IotcJsonObject::CreateObject(); | ||
| 279 | + if (serverConfirmData == nullptr || serverConfirmData->GetJsonObject() == nullptr) { | ||
| 280 | + IOTC_LOGE("SpekeTask::SendServerConfirm create serverConfirmData failed"); | ||
| 281 | + if (serverConfirmData != nullptr) delete serverConfirmData; | ||
| 282 | + return ReturnCode::FAILED; | ||
| 283 | + } | ||
| 284 | + int32_t ret = GenerateSessionKey(); | ||
| 285 | + if (ret != ReturnCode::SUCCESS) { | ||
| 286 | + serverConfirmData->DeleteJson(); | ||
| 287 | + delete serverConfirmData; | ||
| 288 | + return ret; | ||
| 289 | + } | ||
| 290 | + ret = VerifyProof(clientProof); | ||
| 291 | + if (ret != ReturnCode::SUCCESS) { | ||
| 292 | + serverConfirmData->DeleteJson(); | ||
| 293 | + delete serverConfirmData; | ||
| 294 | + return ret; | ||
| 295 | + } | ||
| 296 | + ret = GenerateOutputKey(); | ||
| 297 | + if (ret != ReturnCode::SUCCESS) { | ||
| 298 | + serverConfirmData->DeleteJson(); | ||
| 299 | + delete serverConfirmData; | ||
| 300 | + return ret; | ||
| 301 | + } | ||
| 302 | + std::vector<uint8_t> serverProof = GenerateProof(selfChallenge_, peerChallenge_); | ||
| 303 | + if (serverProof.empty()) { | ||
| 304 | + serverConfirmData->DeleteJson(); | ||
| 305 | + delete serverConfirmData; | ||
| 306 | + return ReturnCode::ALGORITHM_UNSUPPORTED; | ||
| 307 | + } | ||
| 308 | + serverConfirmData->AddString2Obj(CommonConstants::FIELD_CONFIG_DATA, CommonUtil::Uint8ArrayToHexString(serverProof)); | ||
| 309 | + std::string confirmDataStr = serverConfirmData->Print2String(); | ||
| 310 | + serverConfirmData->DeleteJson(); | ||
| 311 | + delete serverConfirmData; | ||
| 312 | + ret = SendPassThroughData(MessageCode::SPEKE_SERVER_CONFIRM, confirmDataStr); | ||
| 313 | + selfChallenge_ = CommonUtil::ConcatenateAll({selfChallenge_, peerChallenge_}); | ||
| 314 | + return ret; | ||
| 315 | +} | ||
| 316 | + | ||
| 317 | +int32_t SpekeTask::VerifyServerConfirm(const PayloadResponse* payload) | ||
| 318 | +{ | ||
| 319 | + IOTC_LOGI("SpekeTask::VerifyServerConfirm"); | ||
| 320 | + auto configDataIter = payload->GetKcfData(); | ||
| 321 | + if (configDataIter.empty()) { | ||
| 322 | + IOTC_LOGE("SpekeTask::VerifyServerConfirm kcfData empty"); | ||
| 323 | + return ReturnCode::BAD_PAYLOAD; | ||
| 324 | + } | ||
| 325 | + std::vector<uint8_t> serverProof = CommonUtil::ToBytesFromHex(configDataIter); | ||
| 326 | + int32_t ret = VerifyProof(serverProof); | ||
| 327 | + if(ret != ReturnCode::SUCCESS) { | ||
| 328 | + return ret; | ||
| 329 | + } | ||
| 330 | + ret = GenerateOutputKey(); | ||
| 331 | + if(ret != ReturnCode::SUCCESS) { | ||
| 332 | + return ret; | ||
| 333 | + } | ||
| 334 | + selfChallenge_ = CommonUtil::ConcatenateAll({selfChallenge_, peerChallenge_}); | ||
| 335 | + if (taskStatus_ != nullptr) { | ||
| 336 | + taskStatus_->NextStatus(); | ||
| 337 | + } | ||
| 338 | + return ReturnCode::SUCCESS; | ||
| 339 | +} | ||
| 340 | + | ||
| 341 | +int32_t SpekeTask::VerifyProof(const std::vector<uint8_t>& proof) | ||
| 342 | +{ | ||
| 343 | + IOTC_LOGI("SpekeTask::VerifyProof"); | ||
| 344 | + if (proof.empty() || peerChallenge_.empty() || selfChallenge_.empty()) { | ||
| 345 | + IOTC_LOGE("SpekeTask::VerifyProof invalid param"); | ||
| 346 | + return ReturnCode::FAILED; | ||
| 347 | + } | ||
| 348 | + std::vector<uint8_t> recoveredProof = GenerateProof(peerChallenge_, selfChallenge_); | ||
| 349 | + if (recoveredProof.empty()) { | ||
| 350 | + IOTC_LOGE("SpekeTask::VerifyProof generate proof failed"); | ||
| 351 | + return ReturnCode::FAILED; | ||
| 352 | + } | ||
| 353 | + bool isMatch = (recoveredProof == proof); | ||
| 354 | + if (!isMatch) { | ||
| 355 | + IOTC_LOGE("SpekeTask::VerifyProof mismatch"); | ||
| 356 | + return ReturnCode::FAILED; | ||
| 357 | + } | ||
| 358 | + IOTC_LOGI("SpekeTask::VerifyProof match"); | ||
| 359 | + return ReturnCode::SUCCESS; | ||
| 360 | +} | ||
| 361 | + | ||
| 362 | +int32_t SpekeTask::GenerateSpekeParamsEc() | ||
| 363 | +{ | ||
| 364 | + std::vector<uint8_t> secret = spekeUtil_.DeriveBaseSecretV2(CommonUtil::StringToBytes(pin_), | ||
| 365 | + salt_, GlobalParams::PAKE_PBKDF2_DEFAULT_ITER); | ||
| 366 | + if (secret.empty()) { | ||
| 367 | + IOTC_LOGE("GenerateSpekeParamsEc derive secret failed"); | ||
| 368 | + return ReturnCode::ALGORITHM_UNSUPPORTED; | ||
| 369 | + } | ||
| 370 | + std::vector<uint8_t> base = spekeUtil_.ComputeSharedBase(secret); | ||
| 371 | + if (base.empty()) { | ||
| 372 | + IOTC_LOGE("GenerateSpekeParamsEc computeSharedBase failed"); | ||
| 373 | + return ReturnCode::ALGORITHM_UNSUPPORTED; | ||
| 374 | + } | ||
| 375 | + selfPrivateParam_ = IotcX25519::GeneratePrivateKey(); | ||
| 376 | + if (selfPrivateParam_.empty()) { | ||
| 377 | + IOTC_LOGE("GenerateSpekeParamsEc gen private key failed"); | ||
| 378 | + return ReturnCode::ALGORITHM_UNSUPPORTED; | ||
| 379 | + } | ||
| 380 | + selfPublicParam_ = spekeUtil_.ComputePublicParameter(base, selfPrivateParam_); | ||
| 381 | + if (selfPublicParam_.empty()) { | ||
| 382 | + IOTC_LOGE("GenerateSpekeParamsEc ComputePublicParameter failed"); | ||
| 383 | + return ReturnCode::ALGORITHM_UNSUPPORTED; | ||
| 384 | + } | ||
| 385 | + return ReturnCode::SUCCESS; | ||
| 386 | +} | ||
| 387 | + | ||
| 388 | +int32_t SpekeTask::GenerateSpekeParamsDl() | ||
| 389 | +{ | ||
| 390 | + uint32_t secretLen = GlobalParams::SPEKE_SECRET_LENGTH; | ||
| 391 | + std::vector<uint8_t> secret = CryptoKdf::HkdfSha256(CommonUtil::StringToBytes(pin_), | ||
| 392 | + salt_, CommonUtil::StringToBytes(CommonConstants::BASE_INFO), secretLen); | ||
| 393 | + if (secret.empty()) { | ||
| 394 | + IOTC_LOGE("GenerateSpekeParamsDl derive secret failed"); | ||
| 395 | + return ReturnCode::ALGORITHM_UNSUPPORTED; | ||
| 396 | + } | ||
| 397 | + std::vector<uint8_t> base = spekeUtil_.ComputeSharedBase(secret); | ||
| 398 | + if (base.empty()) { | ||
| 399 | + IOTC_LOGE("GenerateSpekeParamsDl computeSharedBase failed"); | ||
| 400 | + return ReturnCode::ALGORITHM_UNSUPPORTED; | ||
| 401 | + } | ||
| 402 | + int32_t privateParamLen = spekeUtil_.GetPrivateParamLen(); | ||
| 403 | + selfPrivateParam_ = CryptoRandom::GenerateRandom(privateParamLen); | ||
| 404 | + if (selfPrivateParam_.empty()) { | ||
| 405 | + IOTC_LOGE("GenerateSpekeParamsDl gen private key failed"); | ||
| 406 | + return ReturnCode::ALGORITHM_UNSUPPORTED; | ||
| 407 | + } | ||
| 408 | + selfPublicParam_ = spekeUtil_.ComputePublicParameter(base, selfPrivateParam_); | ||
| 409 | + if (selfPublicParam_.empty()) { | ||
| 410 | + IOTC_LOGE("GenerateSpekeParamsDl ComputePublicParameter failed"); | ||
| 411 | + return ReturnCode::ALGORITHM_UNSUPPORTED; | ||
| 412 | + } | ||
| 413 | + return ReturnCode::SUCCESS; | ||
| 414 | +} | ||
| 415 | + | ||
| 416 | +int32_t SpekeTask::GenerateSpekeParams() | ||
| 417 | +{ | ||
| 418 | + IOTC_LOGI("SpekeTask::GenerateSpekeParams"); | ||
| 419 | + if (pin_.empty()) { | ||
| 420 | + IOTC_LOGE("SpekeTask::GenerateSpekeParams PIN is empty"); | ||
| 421 | + return ReturnCode::FAILED; | ||
| 422 | + } | ||
| 423 | + if (spekeUtil_.GetSpekeType() == SpekeType::SPEKE_EC) { | ||
| 424 | + return GenerateSpekeParamsEc(); | ||
| 425 | + } | ||
| 426 | + return GenerateSpekeParamsDl(); | ||
| 427 | +} | ||
| 428 | + | ||
| 429 | +int32_t SpekeTask::GenerateSessionKeyEc() | ||
| 430 | +{ | ||
| 431 | + std::vector<uint8_t> sharedSecret = spekeUtil_.ComputeSharedKey(selfPrivateParam_, peerPublicParam_); | ||
| 432 | + if (sharedSecret.empty()) { | ||
| 433 | + IOTC_LOGE("GenerateSessionKeyEc compute shared failed"); | ||
| 434 | + return ReturnCode::ALGORITHM_UNSUPPORTED; | ||
| 435 | + } | ||
| 436 | + std::vector<uint8_t> info = CommonUtil::StringToBytes(CommonConstants::SESSION_INFO_V2); | ||
| 437 | + uint32_t keyLen = GlobalParams::SESSION_KEY_LENGTH + GlobalParams::SESSION_KEY_LENGTH; | ||
| 438 | + std::vector<uint8_t> tempKey = spekeUtil_.DeriveSessionKey(sharedSecret, salt_, info, keyLen); | ||
| 439 | + if (tempKey.empty() || tempKey.size() < GlobalParams::SESSION_KEY_LENGTH) { | ||
| 440 | + return ReturnCode::ALGORITHM_UNSUPPORTED; | ||
| 441 | + } | ||
| 442 | + sessionKey_.assign(tempKey.begin(), tempKey.begin() + GlobalParams::SESSION_KEY_LENGTH); | ||
| 443 | + hmacKey_.assign(tempKey.begin() + GlobalParams::SESSION_KEY_LENGTH, tempKey.end()); | ||
| 444 | + return ReturnCode::SUCCESS; | ||
| 445 | +} | ||
| 446 | + | ||
| 447 | +int32_t SpekeTask::GenerateSessionKeyDl() | ||
| 448 | +{ | ||
| 449 | + std::vector<uint8_t> sharedSecret = spekeUtil_.ComputeSharedKey(selfPrivateParam_, peerPublicParam_); | ||
| 450 | + if (sharedSecret.empty()) { | ||
| 451 | + IOTC_LOGE("GenerateSessionKeyDl compute shared failed"); | ||
| 452 | + return ReturnCode::ALGORITHM_UNSUPPORTED; | ||
| 453 | + } | ||
| 454 | + std::vector<uint8_t> info = CommonUtil::StringToBytes(CommonConstants::SESSION_INFO); | ||
| 455 | + uint32_t keyLen = GlobalParams::SESSION_KEY_LENGTH + GlobalParams::SESSION_KEY_LENGTH; | ||
| 456 | + std::vector<uint8_t> tempKey = CryptoKdf::HkdfSha256(sharedSecret, salt_, info, keyLen); | ||
| 457 | + if (tempKey.empty() || tempKey.size() < GlobalParams::SESSION_KEY_LENGTH) { | ||
| 458 | + return ReturnCode::ALGORITHM_UNSUPPORTED; | ||
| 459 | + } | ||
| 460 | + sessionKey_.assign(tempKey.begin(), tempKey.begin() + GlobalParams::SESSION_KEY_LENGTH); | ||
| 461 | + hmacKey_.assign(tempKey.begin() + GlobalParams::SESSION_KEY_LENGTH, tempKey.end()); | ||
| 462 | + return ReturnCode::SUCCESS; | ||
| 463 | +} | ||
| 464 | + | ||
| 465 | +int32_t SpekeTask::GenerateSessionKey() | ||
| 466 | +{ | ||
| 467 | + IOTC_LOGI("SpekeTask::GenerateSessionKey"); | ||
| 468 | + if (spekeUtil_.GetSpekeType() == SpekeType::SPEKE_EC) { | ||
| 469 | + return GenerateSessionKeyEc(); | ||
| 470 | + } | ||
| 471 | + return GenerateSessionKeyDl(); | ||
| 472 | +} | ||
| 473 | + | ||
| 474 | +int32_t SpekeTask::GenerateOutputKeyEc() | ||
| 475 | +{ | ||
| 476 | + if (returnKeyLen_ == 0) { | ||
| 477 | + IOTC_LOGE("GenerateOutputKeyEc return key length invalid: %{public}d", returnKeyLen_); | ||
| 478 | + return ReturnCode::ALGORITHM_UNSUPPORTED; | ||
| 479 | + } | ||
| 480 | + std::vector<uint8_t> returnKeyInfo = CommonUtil::StringToUint8Array(CommonConstants::RETURN_KEY_INFO_V2); | ||
| 481 | + sessionKey_ = CryptoKdf::HkdfSha256(sessionKey_, salt_, returnKeyInfo, returnKeyLen_); | ||
| 482 | + return ReturnCode::SUCCESS; | ||
| 483 | +} | ||
| 484 | + | ||
| 485 | +int32_t SpekeTask::GenerateOutputKeyDl() | ||
| 486 | +{ | ||
| 487 | + if (returnKeyLen_ == 0) { | ||
| 488 | + IOTC_LOGE("GenerateOutputKeyDl return key length invalid: %{public}d", returnKeyLen_); | ||
| 489 | + return ReturnCode::ALGORITHM_UNSUPPORTED; | ||
| 490 | + } | ||
| 491 | + std::vector<uint8_t> returnKeyInfo = CommonUtil::StringToUint8Array(CommonConstants::RETURN_KEY_INFO); | ||
| 492 | + sessionKey_ = CryptoKdf::HkdfSha256(sessionKey_, salt_, returnKeyInfo, returnKeyLen_); | ||
| 493 | + return ReturnCode::SUCCESS; | ||
| 494 | +} | ||
| 495 | + | ||
| 496 | +int32_t SpekeTask::GenerateOutputKey() | ||
| 497 | +{ | ||
| 498 | + IOTC_LOGI("SpekeTask::GenerateOutputKey"); | ||
| 499 | + if (spekeUtil_.GetSpekeType() == SpekeType::SPEKE_EC) { | ||
| 500 | + return GenerateOutputKeyEc(); | ||
| 501 | + } | ||
| 502 | + return GenerateOutputKeyDl(); | ||
| 503 | +} | ||
| 504 | + | ||
| 505 | +} // namespace IotcManagement | ||
| 506 | +} // namespace OHOS | ||
| @@ -0,0 +1,87 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | + | ||
| 26 | + | ||
| 27 | + | ||
| 28 | + | ||
| 29 | +namespace OHOS { | ||
| 30 | +namespace IotcManagement { | ||
| 31 | + | ||
| 32 | +class SpekeTask : public TaskBase { | ||
| 33 | +public: | ||
| 34 | + SpekeTask(std::shared_ptr<OperationParameter> operationParameter, std::shared_ptr<TaskFeedback> taskFeedback, bool isClient); | ||
| 35 | + | ||
| 36 | + int32_t DoStart() override; | ||
| 37 | + | ||
| 38 | + void SetPin(const std::string& pin); | ||
| 39 | + | ||
| 40 | + void SetKeyLen(int32_t keyLength); | ||
| 41 | + | ||
| 42 | + bool IsSpekeTask() const override; | ||
| 43 | + | ||
| 44 | +protected: | ||
| 45 | + int32_t ProcessReceived(uint16_t messageCode, const PayloadResponse* payload) override; | ||
| 46 | + | ||
| 47 | +private: | ||
| 48 | + int32_t SendSpekeStartRequest(); | ||
| 49 | + int32_t SendSpekeResponse(const PayloadResponse* payload); | ||
| 50 | + int32_t SendClientConfirm(const PayloadResponse* payload); | ||
| 51 | + int32_t SendServerConfirm(const PayloadResponse* payload); | ||
| 52 | + int32_t VerifyServerConfirm(const PayloadResponse* payload); | ||
| 53 | + int32_t VerifyProof(const std::vector<uint8_t>& proof); | ||
| 54 | + std::vector<uint8_t> GenerateProof(const std::vector<uint8_t>& beginChallenge, | ||
| 55 | + const std::vector<uint8_t>& endChallenge); | ||
| 56 | + | ||
| 57 | + int32_t GenerateSpekeParams(); | ||
| 58 | + int32_t GenerateSessionKey(); | ||
| 59 | + int32_t GenerateOutputKey(); | ||
| 60 | + | ||
| 61 | + /* DL SPEKE 私有方法 */ | ||
| 62 | + int32_t GenerateSpekeParamsDl(); | ||
| 63 | + int32_t GenerateSessionKeyDl(); | ||
| 64 | + int32_t GenerateOutputKeyDl(); | ||
| 65 | + | ||
| 66 | + /* EC SPEKE 私有方法 */ | ||
| 67 | + int32_t GenerateSpekeParamsEc(); | ||
| 68 | + int32_t GenerateSessionKeyEc(); | ||
| 69 | + int32_t GenerateOutputKeyEc(); | ||
| 70 | + | ||
| 71 | + std::string pin_; | ||
| 72 | + std::vector<uint8_t> salt_; | ||
| 73 | + std::vector<uint8_t> selfPublicParam_; | ||
| 74 | + std::vector<uint8_t> selfPrivateParam_; | ||
| 75 | + std::vector<uint8_t> selfChallenge_; | ||
| 76 | + std::vector<uint8_t> peerPublicParam_; | ||
| 77 | + std::vector<uint8_t> peerChallenge_; | ||
| 78 | + std::vector<uint8_t> hmacKey_; | ||
| 79 | + int32_t returnKeyLen_; | ||
| 80 | + bool isClient_; | ||
| 81 | + SpekeUtils spekeUtil_; | ||
| 82 | +}; | ||
| 83 | + | ||
| 84 | +} // namespace IotcManagement | ||
| 85 | +} // namespace OHOS | ||
| 86 | + | ||
| 87 | + | ||
| @@ -0,0 +1,58 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | +namespace OHOS { | ||
| 20 | +namespace IotcManagement { | ||
| 21 | + | ||
| 22 | +SpekeTaskStatus::SpekeTaskStatus(bool isClient) | ||
| 23 | + : StatusBase(isClient) | ||
| 24 | +{ | ||
| 25 | + if (!isClient) { | ||
| 26 | + mStatus_ = SPEKE_WAIT_REQUEST; | ||
| 27 | + } | ||
| 28 | +} | ||
| 29 | + | ||
| 30 | +void SpekeTaskStatus::NextStatus() | ||
| 31 | +{ | ||
| 32 | + IOTC_LOGI("SpekeTaskStatus::NextStatus old status = %{public}d", mStatus_); | ||
| 33 | + switch (mStatus_) { | ||
| 34 | + case INITIAL: | ||
| 35 | + if (IsClient()) { | ||
| 36 | + mStatus_ = SPEKE_WAIT_RESPONSE; | ||
| 37 | + } else { | ||
| 38 | + mStatus_ = SPEKE_WAIT_REQUEST; | ||
| 39 | + } | ||
| 40 | + break; | ||
| 41 | + case SPEKE_WAIT_REQUEST: | ||
| 42 | + mStatus_ = SPEKE_WAIT_CLIENT_CONFIRM; | ||
| 43 | + break; | ||
| 44 | + case SPEKE_WAIT_RESPONSE: | ||
| 45 | + mStatus_ = SPEKE_WAIT_SERVER_CONFIRM; | ||
| 46 | + break; | ||
| 47 | + case SPEKE_WAIT_SERVER_CONFIRM: | ||
| 48 | + case SPEKE_WAIT_CLIENT_CONFIRM: | ||
| 49 | + mStatus_ = FINISH; | ||
| 50 | + break; | ||
| 51 | + default: | ||
| 52 | + break; | ||
| 53 | + } | ||
| 54 | + IOTC_LOGI("SpekeTaskStatus::NextStatus current status = %{public}d", mStatus_); | ||
| 55 | +} | ||
| 56 | + | ||
| 57 | +} // namespace IotcManagement | ||
| 58 | +} // namespace OHOS | ||
| @@ -0,0 +1,40 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | +namespace OHOS { | ||
| 22 | +namespace IotcManagement { | ||
| 23 | + | ||
| 24 | +class SpekeTaskStatus : public StatusBase { | ||
| 25 | +public: | ||
| 26 | + explicit SpekeTaskStatus(bool isClient); | ||
| 27 | + | ||
| 28 | + void NextStatus() override; | ||
| 29 | + | ||
| 30 | +private: | ||
| 31 | + static constexpr uint16_t SPEKE_WAIT_REQUEST = 0x0001; | ||
| 32 | + static constexpr uint16_t SPEKE_WAIT_CLIENT_CONFIRM = 0x0002; | ||
| 33 | + static constexpr uint16_t SPEKE_WAIT_RESPONSE = 0x8001; | ||
| 34 | + static constexpr uint16_t SPEKE_WAIT_SERVER_CONFIRM = 0x8002; | ||
| 35 | +}; | ||
| 36 | + | ||
| 37 | +} // namespace IotcManagement | ||
| 38 | +} // namespace OHOS | ||
| 39 | + | ||
| 40 | + | ||
| @@ -0,0 +1,59 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | +namespace OHOS { | ||
| 20 | +namespace IotcManagement { | ||
| 21 | + | ||
| 22 | +StatusBase::StatusBase(bool isClient) | ||
| 23 | + : mStatus_(INITIAL), mIsClient_(isClient), stateMask_(0xFFFF) | ||
| 24 | +{ | ||
| 25 | +} | ||
| 26 | + | ||
| 27 | +void StatusBase::Halt() | ||
| 28 | +{ | ||
| 29 | + mStatus_ = HALT; | ||
| 30 | +} | ||
| 31 | + | ||
| 32 | +bool StatusBase::IsTaskStatusMatch(uint16_t messageCode) | ||
| 33 | +{ | ||
| 34 | + IOTC_LOGI("StatusBase::IsTaskStatusMatch code: %{public}d, status: %{public}d", messageCode, mStatus_); | ||
| 35 | + return messageCode == (mStatus_ & stateMask_); | ||
| 36 | +} | ||
| 37 | + | ||
| 38 | +bool StatusBase::IsFinished() const | ||
| 39 | +{ | ||
| 40 | + return mStatus_ == FINISH; | ||
| 41 | +} | ||
| 42 | + | ||
| 43 | +bool StatusBase::IsCanceled() const | ||
| 44 | +{ | ||
| 45 | + return mStatus_ == HALT; | ||
| 46 | +} | ||
| 47 | + | ||
| 48 | +uint16_t StatusBase::GetStatus() const | ||
| 49 | +{ | ||
| 50 | + return mStatus_; | ||
| 51 | +} | ||
| 52 | + | ||
| 53 | +bool StatusBase::IsClient() const | ||
| 54 | +{ | ||
| 55 | + return mIsClient_; | ||
| 56 | +} | ||
| 57 | + | ||
| 58 | +} // namespace IotcManagement | ||
| 59 | +} // namespace OHOS | ||
| @@ -0,0 +1,59 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | +namespace OHOS { | ||
| 22 | +namespace IotcManagement { | ||
| 23 | + | ||
| 24 | +class StatusBase { | ||
| 25 | +public: | ||
| 26 | + virtual ~StatusBase() = default; | ||
| 27 | + | ||
| 28 | + virtual void NextStatus() = 0; | ||
| 29 | + | ||
| 30 | + void Halt(); | ||
| 31 | + | ||
| 32 | + bool IsTaskStatusMatch(uint16_t messageCode); | ||
| 33 | + | ||
| 34 | + bool IsFinished() const; | ||
| 35 | + | ||
| 36 | + bool IsCanceled() const; | ||
| 37 | + | ||
| 38 | + uint16_t GetStatus() const; | ||
| 39 | + | ||
| 40 | + bool IsClient() const; | ||
| 41 | + | ||
| 42 | +protected: | ||
| 43 | + static constexpr uint16_t INITIAL = 0x0000; | ||
| 44 | + static constexpr uint16_t BUSY = 0xFF00; | ||
| 45 | + static constexpr uint16_t ERROR = 0xF00F; | ||
| 46 | + static constexpr uint16_t HALT = 0x00FF; | ||
| 47 | + static constexpr uint16_t FINISH = 0xFFFF; | ||
| 48 | + | ||
| 49 | + StatusBase(bool isClient); | ||
| 50 | + | ||
| 51 | + uint16_t mStatus_; | ||
| 52 | + bool mIsClient_; | ||
| 53 | + uint16_t stateMask_; | ||
| 54 | +}; | ||
| 55 | + | ||
| 56 | +} // namespace IotcManagement | ||
| 57 | +} // namespace OHOS | ||
| 58 | + | ||
| 59 | + | ||
| @@ -0,0 +1,364 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | +namespace OHOS { | ||
| 23 | +namespace IotcManagement { | ||
| 24 | + | ||
| 25 | +TaskBase::TaskBase(std::shared_ptr<OperationParameter> operationParameter, std::shared_ptr<TaskFeedback> requestCallback) | ||
| 26 | + : sessionInfo_(operationParameter), requestCallback_(requestCallback), taskStatus_(nullptr) | ||
| 27 | +{ | ||
| 28 | + uint32_t protocolVersion = CommonConstants::PROTOCOL_VERSION_V1; | ||
| 29 | + if (sessionInfo_ != nullptr) { | ||
| 30 | + protocolVersion = sessionInfo_->GetProtocolVersion(); | ||
| 31 | + } | ||
| 32 | + negotiatedProtocol_ = protocolVersion; | ||
| 33 | + currentVersion_ = (protocolVersion == CommonConstants::PROTOCOL_VERSION_V2) | ||
| 34 | + ? CommonConstants::VERSION_V2 | ||
| 35 | + : ConfiguredVersionInfo::GetDefaultVersion(); | ||
| 36 | + sessionKey_.resize(GlobalParams::SESSION_KEY_LENGTH); | ||
| 37 | +} | ||
| 38 | + | ||
| 39 | +TaskBase::~TaskBase() | ||
| 40 | +{ | ||
| 41 | + StopMessageTimer(); | ||
| 42 | +} | ||
| 43 | + | ||
| 44 | +StatusBase* TaskBase::GetStatusBase() const | ||
| 45 | +{ | ||
| 46 | + return !taskStatus_ ? nullptr : taskStatus_.get(); | ||
| 47 | +} | ||
| 48 | + | ||
| 49 | +OperationParameter* TaskBase::GetOperationParameter() const | ||
| 50 | +{ | ||
| 51 | + return !sessionInfo_ ? nullptr : sessionInfo_.get(); | ||
| 52 | +} | ||
| 53 | + | ||
| 54 | +TaskFeedback* TaskBase::GetTaskFeedback() const { | ||
| 55 | + return !requestCallback_ ? nullptr : requestCallback_.get(); | ||
| 56 | +} | ||
| 57 | + | ||
| 58 | +void TaskBase::Init(const std::vector<uint8_t>& sessionKey) | ||
| 59 | +{ | ||
| 60 | + if (!sessionKey.empty()) { | ||
| 61 | + sessionKey_ = sessionKey; | ||
| 62 | + } | ||
| 63 | +} | ||
| 64 | + | ||
| 65 | +void TaskBase::DoCancel() | ||
| 66 | +{ | ||
| 67 | + IOTC_LOGI("TaskBase::DoCancel"); | ||
| 68 | + if (taskStatus_ != nullptr) { | ||
| 69 | + taskStatus_->Halt(); | ||
| 70 | + } | ||
| 71 | + Clear(); | ||
| 72 | +} | ||
| 73 | + | ||
| 74 | +bool TaskBase::IsSpekeTask() const | ||
| 75 | +{ | ||
| 76 | + return false; | ||
| 77 | +} | ||
| 78 | + | ||
| 79 | +void TaskBase::DoStop(int32_t operationResult) | ||
| 80 | +{ | ||
| 81 | + StopMessageTimer(); | ||
| 82 | + requestCallback_->OnTaskFinished(operationResult, sessionKey_); | ||
| 83 | + Clear(); | ||
| 84 | +} | ||
| 85 | + | ||
| 86 | +VersionInfo TaskBase::GetVersionInfo() const | ||
| 87 | +{ | ||
| 88 | + return VersionInfo::ConstructorByOther( | ||
| 89 | + currentVersion_, | ||
| 90 | + ConfiguredVersionInfo::GetMinVersion(), | ||
| 91 | + ConfiguredVersionInfo::GetSupportVersions() | ||
| 92 | + ); | ||
| 93 | +} | ||
| 94 | + | ||
| 95 | +std::map<std::string, std::string> TaskBase::GetVersionInfoMap() const | ||
| 96 | +{ | ||
| 97 | + VersionInfo versionInfo = GetVersionInfo(); | ||
| 98 | + return versionInfo.GetJsonVersionInfo(); | ||
| 99 | +} | ||
| 100 | + | ||
| 101 | +std::string TaskBase::GetCurrentVersion() const | ||
| 102 | +{ | ||
| 103 | + return currentVersion_; | ||
| 104 | +} | ||
| 105 | + | ||
| 106 | +uint32_t TaskBase::GetNegotiatedProtocol() const | ||
| 107 | +{ | ||
| 108 | + return negotiatedProtocol_; | ||
| 109 | +} | ||
| 110 | + | ||
| 111 | +bool TaskBase::CheckStatus(uint16_t messageCode) | ||
| 112 | +{ | ||
| 113 | + if (taskStatus_ == nullptr) { | ||
| 114 | + IOTC_LOGW("TaskBase::CheckStatus taskStatus_ is null"); | ||
| 115 | + return false; | ||
| 116 | + } | ||
| 117 | + if (taskStatus_->IsCanceled() || taskStatus_->IsFinished()) { | ||
| 118 | + return false; | ||
| 119 | + } | ||
| 120 | + if (messageCode == MessageCode::INFORM_MESSAGE || taskStatus_->IsTaskStatusMatch(messageCode)) { | ||
| 121 | + return true; | ||
| 122 | + } | ||
| 123 | + return false; | ||
| 124 | +} | ||
| 125 | + | ||
| 126 | +void TaskBase::Clear() | ||
| 127 | +{ | ||
| 128 | + StopMessageTimer(); | ||
| 129 | + if (!sessionKey_.empty()) { | ||
| 130 | + std::fill(sessionKey_.begin(), sessionKey_.end(), 0); | ||
| 131 | + } | ||
| 132 | +} | ||
| 133 | + | ||
| 134 | +bool TaskBase::IsWaitingForResponse(uint16_t messageCode) const | ||
| 135 | +{ | ||
| 136 | + if (taskStatus_ == nullptr || taskStatus_->IsCanceled() || taskStatus_->IsFinished()) { | ||
| 137 | + return false; | ||
| 138 | + } | ||
| 139 | + if (messageCode == static_cast<uint16_t>(MessageCode::SPEKE_REQUEST)) { | ||
| 140 | + return taskStatus_->GetStatus() == static_cast<uint16_t>(MessageCode::SPEKE_RESPONSE); | ||
| 141 | + } | ||
| 142 | + if (messageCode == static_cast<uint16_t>(MessageCode::SPEKE_CLIENT_CONFIRM)) { | ||
| 143 | + return taskStatus_->GetStatus() == static_cast<uint16_t>(MessageCode::SPEKE_SERVER_CONFIRM); | ||
| 144 | + } | ||
| 145 | + return false; | ||
| 146 | +} | ||
| 147 | + | ||
| 148 | +uint64_t TaskBase::ResetMessageTimer() | ||
| 149 | +{ | ||
| 150 | + std::unique_ptr<TimerTask> timer; | ||
| 151 | + uint64_t generation = 0; | ||
| 152 | + { | ||
| 153 | + std::lock_guard<std::mutex> lock(messageTimerMutex_); | ||
| 154 | + timer = std::move(messageTimerTask_); | ||
| 155 | + generation = ++messageTimerGeneration_; | ||
| 156 | + } | ||
| 157 | + if (timer) { | ||
| 158 | + timer->Stop(); | ||
| 159 | + } | ||
| 160 | + return generation; | ||
| 161 | +} | ||
| 162 | + | ||
| 163 | +void TaskBase::StartMessageTimer(uint16_t messageCode, const std::string& message, | ||
| 164 | + uint32_t maxCount, uint32_t periodMs, uint64_t generation) | ||
| 165 | +{ | ||
| 166 | + auto timer = std::make_unique<TimerTask>(weak_from_this(), messageCode, message, maxCount, periodMs); | ||
| 167 | + std::lock_guard<std::mutex> lock(messageTimerMutex_); | ||
| 168 | + if (generation != messageTimerGeneration_ || !IsWaitingForResponse(messageCode)) { | ||
| 169 | + return; | ||
| 170 | + } | ||
| 171 | + messageTimerTask_ = std::move(timer); | ||
| 172 | + messageTimerTask_->Start(); | ||
| 173 | +} | ||
| 174 | + | ||
| 175 | +void TaskBase::StopMessageTimer() | ||
| 176 | +{ | ||
| 177 | + ResetMessageTimer(); | ||
| 178 | +} | ||
| 179 | + | ||
| 180 | +bool TaskBase::HandleVersionChange(const VersionInfo* peerVersionInfo) | ||
| 181 | +{ | ||
| 182 | + std::string targetVersion = peerVersionInfo->GetCurrentVersion(); | ||
| 183 | + std::vector<std::string> supportVersions = ConfiguredVersionInfo::GetSupportVersions(); | ||
| 184 | + | ||
| 185 | + for (const auto& version : supportVersions) { | ||
| 186 | + if (version == targetVersion) { | ||
| 187 | + currentVersion_ = peerVersionInfo->GetCurrentVersion(); | ||
| 188 | + return true; | ||
| 189 | + } | ||
| 190 | + } | ||
| 191 | + return false; | ||
| 192 | +} | ||
| 193 | + | ||
| 194 | +bool TaskBase::VersionAgreement(const VersionInfo* peerVersion) | ||
| 195 | +{ | ||
| 196 | + std::string peerVersionInfo = peerVersion->GetCurrentVersion(); | ||
| 197 | + if (peerVersionInfo.empty()) { | ||
| 198 | + IOTC_LOGE("TaskBase::VersionAgreement peerversion null"); | ||
| 199 | + return false; | ||
| 200 | + } | ||
| 201 | + | ||
| 202 | + if (currentVersion_ == peerVersionInfo) { | ||
| 203 | + IOTC_LOGI("TaskBase::VersionAgreement equal"); | ||
| 204 | + return true; | ||
| 205 | + } | ||
| 206 | + | ||
| 207 | + std::vector<std::string> supportVersions = ConfiguredVersionInfo::GetSupportVersions(); | ||
| 208 | + for (const auto& version : supportVersions) { | ||
| 209 | + if (version == peerVersionInfo) { | ||
| 210 | + currentVersion_ = peerVersionInfo; | ||
| 211 | + return true; | ||
| 212 | + } | ||
| 213 | + } | ||
| 214 | + | ||
| 215 | + if (currentVersion_ < peerVersion->GetSupportMinVersion()) { | ||
| 216 | + IOTC_LOGE("TaskBase::VersionAgreement mCurrentVersion: %{public}s, peerVersionMin: %{public}s", | ||
| 217 | + currentVersion_.c_str(), peerVersion->GetSupportMinVersion().c_str()); | ||
| 218 | + return false; | ||
| 219 | + } | ||
| 220 | + | ||
| 221 | + std::vector<std::string> peerSupportVersions = peerVersion->GetSupportVersionList(); | ||
| 222 | + if (peerSupportVersions.empty()) { | ||
| 223 | + IOTC_LOGE("TaskBase::VersionAgreement peerSupportVersions null or 0"); | ||
| 224 | + return false; | ||
| 225 | + } | ||
| 226 | + | ||
| 227 | + currentVersion_ = ""; | ||
| 228 | + for (const auto& peerSupportVersion : peerSupportVersions) { | ||
| 229 | + for (const auto& version : supportVersions) { | ||
| 230 | + if (peerSupportVersion == version && | ||
| 231 | + (currentVersion_.empty() || (peerSupportVersion > currentVersion_))) { | ||
| 232 | + currentVersion_ = peerSupportVersion; | ||
| 233 | + } | ||
| 234 | + } | ||
| 235 | + } | ||
| 236 | + return !currentVersion_.empty(); | ||
| 237 | +} | ||
| 238 | + | ||
| 239 | +int32_t TaskBase::ParseAndCheckVersion(const VersionInfo* version) | ||
| 240 | +{ | ||
| 241 | + if (version == nullptr) { | ||
| 242 | + IOTC_LOGE("TaskBase::ParseAndCheckVersion version is null"); | ||
| 243 | + return ReturnCode::BAD_PAYLOAD; | ||
| 244 | + } | ||
| 245 | + if (!VersionAgreement(version)) { | ||
| 246 | + IOTC_LOGE("TaskBase::ParseAndCheckVersion version agreement failed"); | ||
| 247 | + return ReturnCode::UNSUPPORTED_VERSION; | ||
| 248 | + } | ||
| 249 | + return ReturnCode::SUCCESS; | ||
| 250 | +} | ||
| 251 | + | ||
| 252 | +int32_t TaskBase::DetermineVersion(const VersionInfo* version) | ||
| 253 | +{ | ||
| 254 | + if (version == nullptr) { | ||
| 255 | + IOTC_LOGE("TaskBase::DetermineVersion version is null"); | ||
| 256 | + return ReturnCode::BAD_PAYLOAD; | ||
| 257 | + } | ||
| 258 | + std::string peerCurrentVersion = version->GetCurrentVersion(); | ||
| 259 | + if ((peerCurrentVersion != currentVersion_) && !HandleVersionChange(version)) { | ||
| 260 | + IOTC_LOGE("TaskBase::DetermineVersion determine version agreement failed"); | ||
| 261 | + return ReturnCode::UNSUPPORTED_VERSION; | ||
| 262 | + } | ||
| 263 | + negotiatedProtocol_ = (currentVersion_ == CommonConstants::VERSION_V2) | ||
| 264 | + ? CommonConstants::PROTOCOL_VERSION_V2 | ||
| 265 | + : CommonConstants::PROTOCOL_VERSION_V1; | ||
| 266 | + return ReturnCode::SUCCESS; | ||
| 267 | +} | ||
| 268 | + | ||
| 269 | +int32_t TaskBase::HandleInformMessage(const PayloadResponse* payload) | ||
| 270 | +{ | ||
| 271 | + if (payload == nullptr) { | ||
| 272 | + IOTC_LOGE("TaskBase::HandleInformMessage payload is null"); | ||
| 273 | + requestCallback_->OnTaskHalted(ReturnCode::BAD_PAYLOAD); | ||
| 274 | + return ReturnCode::BAD_PAYLOAD; | ||
| 275 | + } | ||
| 276 | + int32_t errorCode = payload->GetErrorCode(); | ||
| 277 | + IOTC_LOGI("TaskBase::HandleInformMessage ReturnCode from peer: 0x%{public}x", errorCode); | ||
| 278 | + requestCallback_->OnTaskHalted(errorCode | RETURN_CODE_MASK); | ||
| 279 | + return ReturnCode::SUCCESS; | ||
| 280 | +} | ||
| 281 | + | ||
| 282 | +int32_t TaskBase::SendPassThroughData(uint16_t messageCode, const std::string& sendPayload) | ||
| 283 | +{ | ||
| 284 | + if (taskStatus_ != nullptr && taskStatus_->IsCanceled()) { | ||
| 285 | + IOTC_LOGE("TaskBase::SendPassThroughData task is cancel"); | ||
| 286 | + return ReturnCode::CANCELED; | ||
| 287 | + } | ||
| 288 | + | ||
| 289 | + IotcJsonObject* sendData = IotcJsonObject::CreateObject(); | ||
| 290 | + if (sendData == nullptr || sendData->GetJsonObject() == nullptr) { | ||
| 291 | + IOTC_LOGE("TaskBase::SendPassThroughData create sendData null"); | ||
| 292 | + delete sendData; | ||
| 293 | + return ReturnCode::BAD_PAYLOAD; | ||
| 294 | + } | ||
| 295 | + IotcJsonObject* paylodData = IotcJsonObject::Parse(sendPayload); | ||
| 296 | + if (paylodData == nullptr || paylodData->GetJsonObject() == nullptr) { | ||
| 297 | + IOTC_LOGE("TaskBase::SendPassThroughData create paylodData null"); | ||
| 298 | + delete paylodData; | ||
| 299 | + delete sendData; | ||
| 300 | + return ReturnCode::BAD_PAYLOAD; | ||
| 301 | + } | ||
| 302 | + sendData->AddNumber2Obj(CommonConstants::KEY_MESSAGE, messageCode); | ||
| 303 | + | ||
| 304 | + sendData->AddItem2Obj(CommonConstants::KEY_PAYLOAD, *paylodData); | ||
| 305 | + std::string jsonStr = sendData->Print2String(); | ||
| 306 | + sendData->DeleteJson(); | ||
| 307 | + delete sendData; | ||
| 308 | + std::vector<uint8_t> sendBytes = CommonUtil::StringToBytes(jsonStr); | ||
| 309 | + if (taskStatus_ != nullptr) { | ||
| 310 | + taskStatus_->NextStatus(); | ||
| 311 | + } | ||
| 312 | + uint64_t timerGeneration = ResetMessageTimer(); | ||
| 313 | + bool isSend = requestCallback_->OnDataTransmit(sessionInfo_->GetSessionId(), sendBytes); | ||
| 314 | + IOTC_LOGI("TaskBase::SendPassThroughData send request message: %{public}d", isSend); | ||
| 315 | + | ||
| 316 | + uint32_t maxCount = MessageConfig::DEFAULT_SPEKE_RESEND_MAX_COUNT; | ||
| 317 | + uint32_t period = MessageConfig::DEFAULT_SPEKE_RESEND_PERIOD; | ||
| 318 | + | ||
| 319 | + std::shared_ptr<MessageConfig> msgConfig = SecurityAdapter::GetInstance().GetMessageConfig(); | ||
| 320 | + if (msgConfig != nullptr) { | ||
| 321 | + maxCount = msgConfig->GetSpekeResendMaxCount(); | ||
| 322 | + period = msgConfig->GetSpekePeriod(); | ||
| 323 | + } | ||
| 324 | + | ||
| 325 | + StartMessageTimer(messageCode, jsonStr, maxCount, period, timerGeneration); | ||
| 326 | + return ReturnCode::SUCCESS; | ||
| 327 | +} | ||
| 328 | + | ||
| 329 | +int32_t TaskBase::ProcessReceivedData(const std::string& receivedData) | ||
| 330 | +{ | ||
| 331 | + IotcJsonObject* jsonData = IotcJsonObject::Parse(receivedData); | ||
| 332 | + if (jsonData == nullptr || jsonData->GetJsonObject() == nullptr) { | ||
| 333 | + IOTC_LOGE("TaskBase::ProcessReceivedData failed to parse JSON"); | ||
| 334 | + if (jsonData != nullptr) delete jsonData; | ||
| 335 | + return ReturnCode::BAD_PAYLOAD; | ||
| 336 | + } | ||
| 337 | + | ||
| 338 | + uint16_t messageCode = jsonData->GetNumber(CommonConstants::KEY_MESSAGE, 0); | ||
| 339 | + IOTC_LOGI("TaskBase::ProcessReceivedData messageCode: %{public}d", messageCode); | ||
| 340 | + if (!CheckStatus(messageCode)) { | ||
| 341 | + IOTC_LOGW("TaskBase::ProcessReceivedData receive insignificant passThrough data with mismatched message"); | ||
| 342 | + delete jsonData; | ||
| 343 | + return ReturnCode::BAD_PAYLOAD; | ||
| 344 | + } | ||
| 345 | + | ||
| 346 | + IotcJsonObject* payloadObj = jsonData->GetObj(CommonConstants::KEY_PAYLOAD); | ||
| 347 | + if (payloadObj == nullptr || payloadObj->GetJsonObject() == nullptr) { | ||
| 348 | + IOTC_LOGE("TaskBase::ProcessReceivedData bad payload in passThrough data"); | ||
| 349 | + jsonData->DeleteJson(); | ||
| 350 | + delete jsonData; | ||
| 351 | + return ReturnCode::BAD_PAYLOAD; | ||
| 352 | + } | ||
| 353 | + | ||
| 354 | + std::string payloadStr = payloadObj->Print2String(); | ||
| 355 | + jsonData->DeleteJson(); | ||
| 356 | + delete jsonData; | ||
| 357 | + StopMessageTimer(); | ||
| 358 | + auto payloadResponse = PayloadResponse::FormJson(payloadStr); | ||
| 359 | + int32_t ret = ProcessReceived(messageCode, &payloadResponse); | ||
| 360 | + return ret; | ||
| 361 | +} | ||
| 362 | + | ||
| 363 | +} // namespace IotcManagement | ||
| 364 | +} // namespace OHOS | ||
| @@ -0,0 +1,125 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | + | ||
| 26 | + | ||
| 27 | + | ||
| 28 | + | ||
| 29 | + | ||
| 30 | + | ||
| 31 | + | ||
| 32 | + | ||
| 33 | + | ||
| 34 | + | ||
| 35 | + | ||
| 36 | + | ||
| 37 | + | ||
| 38 | + | ||
| 39 | + | ||
| 40 | + | ||
| 41 | + | ||
| 42 | +namespace OHOS { | ||
| 43 | +namespace IotcManagement { | ||
| 44 | + | ||
| 45 | +class TaskBase : public std::enable_shared_from_this<TaskBase> { | ||
| 46 | + friend class TimerTask; | ||
| 47 | +public: | ||
| 48 | + TaskBase(std::shared_ptr<OperationParameter> operationParameter, std::shared_ptr<TaskFeedback> requestCallback); | ||
| 49 | + virtual ~TaskBase(); | ||
| 50 | + | ||
| 51 | + virtual int32_t DoStart() = 0; | ||
| 52 | + | ||
| 53 | + virtual int32_t ProcessReceivedData(const std::string& receivedData); | ||
| 54 | + | ||
| 55 | + virtual void Init(const std::vector<uint8_t>& sessionKey); | ||
| 56 | + | ||
| 57 | + virtual void DoCancel(); | ||
| 58 | + | ||
| 59 | + virtual bool IsSpekeTask() const; | ||
| 60 | + | ||
| 61 | + StatusBase* GetStatusBase() const; | ||
| 62 | + | ||
| 63 | + OperationParameter* GetOperationParameter() const; | ||
| 64 | + | ||
| 65 | + TaskFeedback* GetTaskFeedback() const; | ||
| 66 | + | ||
| 67 | +protected: | ||
| 68 | + virtual int32_t ProcessReceived(uint16_t messageCode, const PayloadResponse* payload) = 0; | ||
| 69 | + | ||
| 70 | + virtual void DoStop(int32_t operationResult); | ||
| 71 | + | ||
| 72 | + int32_t SendPassThroughData(uint16_t messageCode, const std::string& sendPayload); | ||
| 73 | + | ||
| 74 | + bool CheckStatus(uint16_t messageCode); | ||
| 75 | + | ||
| 76 | + int32_t ParseAndCheckVersion(const VersionInfo* version); | ||
| 77 | + | ||
| 78 | + int32_t DetermineVersion(const VersionInfo* version); | ||
| 79 | + | ||
| 80 | + int32_t HandleInformMessage(const PayloadResponse* payload); | ||
| 81 | + | ||
| 82 | + VersionInfo GetVersionInfo() const; | ||
| 83 | + | ||
| 84 | + std::string GetCurrentVersion() const; | ||
| 85 | + | ||
| 86 | + uint32_t GetNegotiatedProtocol() const; | ||
| 87 | + | ||
| 88 | + void Clear(); | ||
| 89 | + | ||
| 90 | + bool VersionAgreement(const VersionInfo* peerVersion); | ||
| 91 | + | ||
| 92 | + bool HandleVersionChange(const VersionInfo* peerVersionInfo); | ||
| 93 | + | ||
| 94 | + std::map<std::string, std::string> GetVersionInfoMap() const; | ||
| 95 | + | ||
| 96 | + static constexpr uint32_t RETURN_CODE_MASK = 0x0F000000; | ||
| 97 | + | ||
| 98 | +private: | ||
| 99 | + bool IsWaitingForResponse(uint16_t messageCode) const; | ||
| 100 | + | ||
| 101 | + uint64_t ResetMessageTimer(); | ||
| 102 | + | ||
| 103 | + void StartMessageTimer(uint16_t messageCode, const std::string& message, | ||
| 104 | + uint32_t maxCount, uint32_t periodMs, uint64_t generation); | ||
| 105 | + | ||
| 106 | + void StopMessageTimer(); | ||
| 107 | + | ||
| 108 | +protected: | ||
| 109 | + std::shared_ptr<OperationParameter> sessionInfo_; | ||
| 110 | + std::shared_ptr<TaskFeedback> requestCallback_; | ||
| 111 | + std::shared_ptr<StatusBase> taskStatus_; | ||
| 112 | + std::vector<uint8_t> sessionKey_; | ||
| 113 | + std::string currentVersion_; | ||
| 114 | + uint32_t negotiatedProtocol_; | ||
| 115 | + | ||
| 116 | +private: | ||
| 117 | + std::mutex messageTimerMutex_; | ||
| 118 | + std::unique_ptr<TimerTask> messageTimerTask_; | ||
| 119 | + uint64_t messageTimerGeneration_ {0}; | ||
| 120 | +}; | ||
| 121 | + | ||
| 122 | +} // namespace IotcManagement | ||
| 123 | +} // namespace OHOS | ||
| 124 | + | ||
| 125 | + | ||
| @@ -0,0 +1,65 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | +namespace OHOS { | ||
| 24 | +namespace IotcManagement { | ||
| 25 | + | ||
| 26 | +class TaskFeedback { | ||
| 27 | +public: | ||
| 28 | + virtual ~TaskFeedback() = default; | ||
| 29 | + | ||
| 30 | + virtual void OnTaskHalted(int32_t operationResult) = 0; | ||
| 31 | + | ||
| 32 | + virtual void OnTaskFinished(int32_t operationResult, const std::vector<uint8_t>& returnData) = 0; | ||
| 33 | + | ||
| 34 | + virtual bool OnDataTransmit(const std::string& sessionId, const std::vector<uint8_t>& data) = 0; | ||
| 35 | +}; | ||
| 36 | + | ||
| 37 | +struct TaskFeedbackImpl : public TaskFeedback { | ||
| 38 | + std::function<void(int32_t)> onTaskHalted; | ||
| 39 | + std::function<void(int32_t, const std::vector<uint8_t>&)> onTaskFinished; | ||
| 40 | + std::function<bool(const std::string&, const std::vector<uint8_t>&)> onDataTransmit; | ||
| 41 | + | ||
| 42 | + void OnTaskHalted(int32_t operationResult) { | ||
| 43 | + if (onTaskHalted) { | ||
| 44 | + onTaskHalted(operationResult); | ||
| 45 | + } | ||
| 46 | + } | ||
| 47 | + | ||
| 48 | + void OnTaskFinished(int32_t operationResult, const std::vector<uint8_t>& returnData) { | ||
| 49 | + if (onTaskFinished) { | ||
| 50 | + onTaskFinished(operationResult, returnData); | ||
| 51 | + } | ||
| 52 | + } | ||
| 53 | + | ||
| 54 | + bool OnDataTransmit(const std::string& sessionId, const std::vector<uint8_t>& data) { | ||
| 55 | + if (onDataTransmit) { | ||
| 56 | + return onDataTransmit(sessionId, data); | ||
| 57 | + } | ||
| 58 | + return false; | ||
| 59 | + } | ||
| 60 | +}; | ||
| 61 | + | ||
| 62 | +} // namespace IotcManagement | ||
| 63 | +} // namespace OHOS | ||
| 64 | + | ||
| 65 | + | ||
| @@ -0,0 +1,128 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | +namespace OHOS { | ||
| 23 | +namespace IotcManagement { | ||
| 24 | + | ||
| 25 | +struct TimerTask::TimerState { | ||
| 26 | + TimerState(std::weak_ptr<TaskBase> task, uint16_t code, const std::string& data, | ||
| 27 | + uint32_t resendMaxCount, uint32_t resendPeriodMs) | ||
| 28 | + : delegate(std::move(task)), messageCode(code), message(data), | ||
| 29 | + maxCount(resendMaxCount), periodMs(resendPeriodMs == 0 ? 1 : resendPeriodMs) | ||
| 30 | + {} | ||
| 31 | + | ||
| 32 | + std::weak_ptr<TaskBase> delegate; | ||
| 33 | + uint16_t messageCode; | ||
| 34 | + std::string message; | ||
| 35 | + uint32_t maxCount; | ||
| 36 | + uint32_t periodMs; | ||
| 37 | + std::atomic<bool> running {false}; | ||
| 38 | + std::mutex waitMutex; | ||
| 39 | + std::condition_variable waitCondition; | ||
| 40 | +}; | ||
| 41 | + | ||
| 42 | +TimerTask::TimerTask(std::weak_ptr<TaskBase> delegate, uint16_t messageCode, const std::string& message, | ||
| 43 | + uint32_t maxCount, uint32_t periodMs) | ||
| 44 | + : state_(std::make_shared<TimerState>(std::move(delegate), messageCode, message, maxCount, periodMs)) | ||
| 45 | +{} | ||
| 46 | + | ||
| 47 | +TimerTask::~TimerTask() | ||
| 48 | +{ | ||
| 49 | + Stop(); | ||
| 50 | +} | ||
| 51 | + | ||
| 52 | +void TimerTask::Start() | ||
| 53 | +{ | ||
| 54 | + std::lock_guard<std::mutex> lock(threadMutex_); | ||
| 55 | + if (!state_ || state_->running.exchange(true)) { | ||
| 56 | + IOTC_LOGW("TimerTask already running"); | ||
| 57 | + return; | ||
| 58 | + } | ||
| 59 | + workThread_ = std::thread(&TimerTask::RunLoop, state_); | ||
| 60 | +} | ||
| 61 | + | ||
| 62 | +void TimerTask::Stop() | ||
| 63 | +{ | ||
| 64 | + std::thread worker; | ||
| 65 | + { | ||
| 66 | + std::lock_guard<std::mutex> lock(threadMutex_); | ||
| 67 | + if (state_) { | ||
| 68 | + state_->running.store(false); | ||
| 69 | + state_->waitCondition.notify_all(); | ||
| 70 | + } | ||
| 71 | + if (workThread_.joinable()) { | ||
| 72 | + worker = std::move(workThread_); | ||
| 73 | + } | ||
| 74 | + } | ||
| 75 | + if (!worker.joinable()) { | ||
| 76 | + return; | ||
| 77 | + } | ||
| 78 | + if (worker.get_id() == std::this_thread::get_id()) { | ||
| 79 | + worker.detach(); | ||
| 80 | + } else { | ||
| 81 | + worker.join(); | ||
| 82 | + } | ||
| 83 | +} | ||
| 84 | + | ||
| 85 | +void TimerTask::RunLoop(const std::shared_ptr<TimerState>& state) | ||
| 86 | +{ | ||
| 87 | + if (!state) { | ||
| 88 | + return; | ||
| 89 | + } | ||
| 90 | + uint32_t count = 0; | ||
| 91 | + while (state->running.load() && count < state->maxCount) { | ||
| 92 | + std::unique_lock<std::mutex> lock(state->waitMutex); | ||
| 93 | + bool stopped = state->waitCondition.wait_for(lock, std::chrono::milliseconds(state->periodMs), | ||
| 94 | + [state]() { | ||
| 95 | + return !state->running.load(); | ||
| 96 | + }); | ||
| 97 | + lock.unlock(); | ||
| 98 | + if (stopped || !state->running.load()) { | ||
| 99 | + break; | ||
| 100 | + } | ||
| 101 | + | ||
| 102 | + auto delegate = state->delegate.lock(); | ||
| 103 | + if (!delegate) { | ||
| 104 | + IOTC_LOGE("TimerTask delegate already destroyed"); | ||
| 105 | + break; | ||
| 106 | + } | ||
| 107 | + | ||
| 108 | + if (!state->running.load() || !delegate->IsWaitingForResponse(state->messageCode)) { | ||
| 109 | + break; | ||
| 110 | + } | ||
| 111 | + TaskFeedback* feedback = delegate->GetTaskFeedback(); | ||
| 112 | + OperationParameter* parameter = delegate->GetOperationParameter(); | ||
| 113 | + if (feedback != nullptr && parameter != nullptr) { | ||
| 114 | + bool isSend = feedback->OnDataTransmit( | ||
| 115 | + parameter->GetSessionId(), CommonUtil::StringToBytes(state->message)); | ||
| 116 | + IOTC_LOGI("TimerTask::Run resend message: %{public}d", isSend); | ||
| 117 | + } | ||
| 118 | + | ||
| 119 | + count++; | ||
| 120 | + } | ||
| 121 | + if (count >= state->maxCount && state->running.load()) { | ||
| 122 | + IOTC_LOGI("TimerTask::Run resend exceeded maximum for messageCode: %{public}d", state->messageCode); | ||
| 123 | + } | ||
| 124 | + state->running.store(false); | ||
| 125 | +} | ||
| 126 | + | ||
| 127 | +} // namespace IotcManagement | ||
| 128 | +} // namespace OHOS | ||
| @@ -0,0 +1,57 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | + | ||
| 26 | + | ||
| 27 | +namespace OHOS { | ||
| 28 | +namespace IotcManagement { | ||
| 29 | + | ||
| 30 | +class TaskBase; | ||
| 31 | +class CommonUtil; | ||
| 32 | + | ||
| 33 | +class TimerTask { | ||
| 34 | +public: | ||
| 35 | + TimerTask(std::weak_ptr<TaskBase> delegate, uint16_t messageCode, const std::string& message, | ||
| 36 | + uint32_t maxCount, uint32_t periodMs); | ||
| 37 | + | ||
| 38 | + ~TimerTask(); | ||
| 39 | + | ||
| 40 | + void Start(); | ||
| 41 | + void Stop(); | ||
| 42 | + | ||
| 43 | +private: | ||
| 44 | + struct TimerState; | ||
| 45 | + | ||
| 46 | + static void RunLoop(const std::shared_ptr<TimerState>& state); | ||
| 47 | + | ||
| 48 | +private: | ||
| 49 | + std::shared_ptr<TimerState> state_; | ||
| 50 | + std::thread workThread_; | ||
| 51 | + std::mutex threadMutex_; | ||
| 52 | +}; | ||
| 53 | + | ||
| 54 | +} // namespace IotcManagement | ||
| 55 | +} // namespace OHOS | ||
| 56 | + | ||
| 57 | + | ||
| @@ -0,0 +1,114 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | + | ||
| 26 | + | ||
| 27 | + | ||
| 28 | +namespace OHOS { | ||
| 29 | +namespace IotcManagement { | ||
| 30 | + | ||
| 31 | +AuthCallbackMethods::AuthCallbackMethods(std::shared_ptr<SpekeNegotiateCallback> callback, | ||
| 32 | + uint32_t protocolVersion) | ||
| 33 | + : callback_(callback), protocolVersion_(protocolVersion) | ||
| 34 | +{ | ||
| 35 | +} | ||
| 36 | + | ||
| 37 | +void AuthCallbackMethods::OnOperationFinished(const std::string& sessionId, int32_t operationCode, | ||
| 38 | + int32_t result, const std::vector<uint8_t>& returnData) | ||
| 39 | +{ | ||
| 40 | + if (!callback_) { | ||
| 41 | + IOTC_LOGW("AuthCallbackMethods::OnOperationFinished callback is null"); | ||
| 42 | + return; | ||
| 43 | + } | ||
| 44 | + if (sessionId.empty()) { | ||
| 45 | + IOTC_LOGE("AuthCallbackMethods::OnOperationFinished failed, sessionId is null"); | ||
| 46 | + callback_->OnFailure(ReturnCode::INVALID_PARAMETERS, "sessionId is empty"); | ||
| 47 | + return; | ||
| 48 | + } | ||
| 49 | + | ||
| 50 | + if (result != ReturnCode::SUCCESS) { | ||
| 51 | + IOTC_LOGE("AuthCallbackMethods::OnOperationFinished failed, result: %{public}d", result); | ||
| 52 | + callback_->OnFailure(result, "negotiate failed"); | ||
| 53 | + return; | ||
| 54 | + } | ||
| 55 | + | ||
| 56 | + if (returnData.empty()) { | ||
| 57 | + IOTC_LOGE("AuthCallbackMethods::OnOperationFinished failed, returnData is invalid"); | ||
| 58 | + callback_->OnFailure(ReturnCode::INVALID_PARAMETERS, "session key is invalid"); | ||
| 59 | + return; | ||
| 60 | + } | ||
| 61 | + | ||
| 62 | + IOTC_LOGI("AuthCallbackMethods::OnOperationFinished success"); | ||
| 63 | + auto cipher = std::make_shared<SecurityCipher>(returnData); | ||
| 64 | + callback_->OnSuccess(cipher); | ||
| 65 | +} | ||
| 66 | + | ||
| 67 | +bool AuthCallbackMethods::OnDataTransmit(const std::string& sessionId, const std::vector<uint8_t>& toPeerData) | ||
| 68 | +{ | ||
| 69 | + IOTC_LOGI("AuthCallbackMethods::OnDataTransmit"); | ||
| 70 | + if (!callback_) { | ||
| 71 | + IOTC_LOGW("AuthCallbackMethods::OnDataTransmit callback is null"); | ||
| 72 | + return false; | ||
| 73 | + } | ||
| 74 | + if (sessionId.empty()) { | ||
| 75 | + IOTC_LOGE("AuthCallbackMethods::OnDataTransmit failed, sessionId is null"); | ||
| 76 | + callback_->OnFailure(ReturnCode::INVALID_PARAMETERS, "sessionId is empty"); | ||
| 77 | + return false; | ||
| 78 | + } | ||
| 79 | + std::string peerDataStr = CommonUtil::Uint8ArrayToString(toPeerData); | ||
| 80 | + PassThroughData passThroughData(peerDataStr, sessionId, protocolVersion_); | ||
| 81 | + callback_->ToPeerData(passThroughData.ToJson(protocolVersion_)); | ||
| 82 | + return true; | ||
| 83 | +} | ||
| 84 | + | ||
| 85 | +void AuthCallbackMethods::OnSessionKeyReturned(const std::string& sessionId, const std::vector<uint8_t>& sessionKey) | ||
| 86 | +{ | ||
| 87 | + IOTC_LOGI("AuthCallbackMethods::OnSessionKeyReturned"); | ||
| 88 | +} | ||
| 89 | + | ||
| 90 | +ConfirmParams AuthCallbackMethods::OnReceiveRequest(const std::string& sessionId, int32_t operationCode) | ||
| 91 | +{ | ||
| 92 | + IOTC_LOGI("AuthCallbackMethods::OnReceiveRequest"); | ||
| 93 | + ConfirmParams result; | ||
| 94 | + if (sessionId.empty()) { | ||
| 95 | + IOTC_LOGE("AuthCallbackMethods::OnReceiveRequest failed, sessionId is null"); | ||
| 96 | + result.SetConfirmation(ReturnCode::REQUEST_REJECTED); | ||
| 97 | + return result; | ||
| 98 | + } | ||
| 99 | + result.SetConfirmation(IsAccept(operationCode) ? ReturnCode::REQUEST_ACCEPTED : ReturnCode::REQUEST_REJECTED); | ||
| 100 | + result.SetPin(SecurityAdapter::GetInstance().GetPinCode(sessionId)); | ||
| 101 | + result.SetKeyLength(GlobalParams::SESSION_KEY_LENGTH); | ||
| 102 | + return result; | ||
| 103 | +} | ||
| 104 | + | ||
| 105 | +bool AuthCallbackMethods::IsAccept(int32_t operationCode) const | ||
| 106 | +{ | ||
| 107 | + if (operationCode != OperationCode::AUTH_KEY_AGREEMENT) { | ||
| 108 | + IOTC_LOGE("AuthCallbackMethods::IsAccept unsupported operation %{public}d", operationCode); | ||
| 109 | + } | ||
| 110 | + return operationCode == OperationCode::AUTH_KEY_AGREEMENT; | ||
| 111 | +} | ||
| 112 | + | ||
| 113 | +} // namespace IotcManagement | ||
| 114 | +} // namespace OHOS | ||
| @@ -0,0 +1,55 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | + | ||
| 26 | + | ||
| 27 | + | ||
| 28 | +namespace OHOS { | ||
| 29 | +namespace IotcManagement { | ||
| 30 | + | ||
| 31 | +class AuthCallbackMethods : public HwDevAuthCallback { | ||
| 32 | +public: | ||
| 33 | + AuthCallbackMethods(std::shared_ptr<SpekeNegotiateCallback> callback, | ||
| 34 | + uint32_t protocolVersion = CommonConstants::PROTOCOL_VERSION_V1); | ||
| 35 | + | ||
| 36 | + void OnOperationFinished(const std::string& sessionId, int32_t operationCode, | ||
| 37 | + int32_t result, const std::vector<uint8_t>& returnData) override; | ||
| 38 | + | ||
| 39 | + bool OnDataTransmit(const std::string& sessionId, const std::vector<uint8_t>& toPeerData) override; | ||
| 40 | + | ||
| 41 | + void OnSessionKeyReturned(const std::string& sessionId, const std::vector<uint8_t>& sessionKey) override; | ||
| 42 | + | ||
| 43 | + ConfirmParams OnReceiveRequest(const std::string& sessionId, int32_t operationCode); | ||
| 44 | + | ||
| 45 | +private: | ||
| 46 | + bool IsAccept(int32_t operationCode) const; | ||
| 47 | + | ||
| 48 | + std::shared_ptr<SpekeNegotiateCallback> callback_; | ||
| 49 | + uint32_t protocolVersion_; | ||
| 50 | +}; | ||
| 51 | + | ||
| 52 | +} // namespace IotcManagement | ||
| 53 | +} // namespace OHOS | ||
| 54 | + | ||
| 55 | + | ||
| @@ -0,0 +1,149 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | + | ||
| 26 | + | ||
| 27 | + | ||
| 28 | +namespace OHOS { | ||
| 29 | +namespace IotcManagement { | ||
| 30 | + | ||
| 31 | +void E2eSecurityApi::InitSecuritySdk() | ||
| 32 | +{ | ||
| 33 | + IOTC_LOGI("E2eSecurityApi::InitSecuritySdk"); | ||
| 34 | + std::string phoneAccountId = CryptoRandom::GenerateRandomHexString(8); | ||
| 35 | + Init(DEFAULT_SPEKE_USER_ID, phoneAccountId, SPEKE_REQUEST_RETRANSPORT_COUNT, SPEKE_REQUEST_RETRANSPORT_INTERVAL); | ||
| 36 | +} | ||
| 37 | + | ||
| 38 | +void E2eSecurityApi::Init(const std::string& userId, const std::string& phoneAccountId, | ||
| 39 | + uint32_t transportCount, uint32_t transportInterval) | ||
| 40 | +{ | ||
| 41 | + IOTC_LOGI("E2eSecurityApi::Init"); | ||
| 42 | + if (userId.empty() || phoneAccountId.empty()) { | ||
| 43 | + IOTC_LOGE("E2eSecurityApi::Init userId or phoneAccountId is invalid"); | ||
| 44 | + return; | ||
| 45 | + } | ||
| 46 | + | ||
| 47 | + auto identityInfo = std::make_shared<IdentityInfo>(userId, IdentityType::USER); | ||
| 48 | + identityInfo->SetPhoneUuid(phoneAccountId); | ||
| 49 | + | ||
| 50 | + auto messageConfig = std::make_shared<MessageConfig>(); | ||
| 51 | + messageConfig->SetSpekeResendMaxCount(transportCount); | ||
| 52 | + messageConfig->SetSpekePeriod(transportInterval); | ||
| 53 | + | ||
| 54 | + SecurityPin::Init(identityInfo, messageConfig); | ||
| 55 | +} | ||
| 56 | + | ||
| 57 | +void E2eSecurityApi::Clear() | ||
| 58 | +{ | ||
| 59 | + IOTC_LOGI("E2eSecurityApi::Clear"); | ||
| 60 | + SecurityPin::CleanMemory(); | ||
| 61 | +} | ||
| 62 | + | ||
| 63 | +void E2eSecurityApi::Destroy() | ||
| 64 | +{ | ||
| 65 | + IOTC_LOGI("E2eSecurityApi::Destroy"); | ||
| 66 | + SecurityPin::Destroy(); | ||
| 67 | +} | ||
| 68 | + | ||
| 69 | +std::string E2eSecurityApi::StartNegotiateSpeke(const std::string& pinCode, const std::string& deviceId, | ||
| 70 | + std::shared_ptr<SpekeNegotiateCallback> negotiateCallback, int32_t spekeType, | ||
| 71 | + uint32_t protocolVersion) | ||
| 72 | +{ | ||
| 73 | + IOTC_LOGI("E2eSecurityApi::StartNegotiateSpeke spekeType=%{public}d ver=%{public}u", | ||
| 74 | + spekeType, protocolVersion); | ||
| 75 | + InitSecuritySdk(); | ||
| 76 | + | ||
| 77 | + if (pinCode.empty() || deviceId.empty() || !negotiateCallback) { | ||
| 78 | + IOTC_LOGI("E2eSecurityApi::StartNegotiateSpeke params is invalid"); | ||
| 79 | + return ""; | ||
| 80 | + } | ||
| 81 | + | ||
| 82 | + std::string sessionId = SecurityPin::NegotiateSpeke(pinCode, deviceId, spekeType, | ||
| 83 | + negotiateCallback, protocolVersion); | ||
| 84 | + | ||
| 85 | + IOTC_LOGI("E2eSecurityApi::StartNegotiateSpeke sessionId=%{public}s", sessionId.c_str()); | ||
| 86 | + return sessionId; | ||
| 87 | +} | ||
| 88 | + | ||
| 89 | +bool E2eSecurityApi::CancelNegotiateSpeke(const std::string& sessionId, int32_t spekeType) | ||
| 90 | +{ | ||
| 91 | + IOTC_LOGI("E2eSecurityApi::CancelNegotiateSpeke spekeType=%{public}d", spekeType); | ||
| 92 | + if (sessionId.empty()) { | ||
| 93 | + IOTC_LOGE("E2eSecurityApi::CancelNegotiateSpeke sessionId is invalid"); | ||
| 94 | + return false; | ||
| 95 | + } | ||
| 96 | + | ||
| 97 | + return SecurityPin::CancelRequest(sessionId, spekeType); | ||
| 98 | +} | ||
| 99 | + | ||
| 100 | +void E2eSecurityApi::ProcessReceivedSpekeMsg(const std::string& deviceId, const std::string& response, | ||
| 101 | + int32_t spekeType, uint32_t protocolVersion) | ||
| 102 | +{ | ||
| 103 | + IOTC_LOGI("E2eSecurityApi::ProcessReceivedSpekeMsg spekeType=%{public}d ver=%{public}u", | ||
| 104 | + spekeType, protocolVersion); | ||
| 105 | + if (deviceId.empty() || response.empty()) { | ||
| 106 | + IOTC_LOGE("E2eSecurityApi::ProcessReceivedSpekeMsg params is invalid"); | ||
| 107 | + } | ||
| 108 | + | ||
| 109 | + IdentityInfo identityInfo(deviceId, IdentityType::DEVICE); | ||
| 110 | + SecurityPin::ReceivedMsg(response, &identityInfo, spekeType, protocolVersion); | ||
| 111 | +} | ||
| 112 | + | ||
| 113 | +bool E2eSecurityApi::IsSupportHiChain(int32_t version) | ||
| 114 | +{ | ||
| 115 | + IOTC_LOGI("E2eSecurityApi::IsSupportHiChain version=%{public}d", version); | ||
| 116 | + return false; | ||
| 117 | +} | ||
| 118 | + | ||
| 119 | +void E2eSecurityApi::DestorySpeke(std::shared_ptr<SecurityCipher> securityCipher) | ||
| 120 | +{ | ||
| 121 | + IOTC_LOGI("E2eSecurityApi::DestorySpeke"); | ||
| 122 | + if (!securityCipher) { | ||
| 123 | + return; | ||
| 124 | + } | ||
| 125 | + securityCipher->Destroy(); | ||
| 126 | +} | ||
| 127 | + | ||
| 128 | +std::vector<uint8_t> E2eSecurityApi::EncryptData(std::shared_ptr<SecurityCipher> securityCipher, const std::vector<uint8_t>& data) | ||
| 129 | +{ | ||
| 130 | + if (data.empty() || !securityCipher) { | ||
| 131 | + IOTC_LOGE("E2eSecurityApi::EncryptData data or securityCipher is invalid"); | ||
| 132 | + return {}; | ||
| 133 | + } | ||
| 134 | + auto output = securityCipher->Encrypt(data); | ||
| 135 | + return output; | ||
| 136 | +} | ||
| 137 | + | ||
| 138 | +std::vector<uint8_t> E2eSecurityApi::DecryptData(std::shared_ptr<SecurityCipher> securityCipher, const std::vector<uint8_t>& data) | ||
| 139 | +{ | ||
| 140 | + if (data.empty() || !securityCipher) { | ||
| 141 | + IOTC_LOGE("E2eSecurityApi::DecryptData data or securityCipher is invalid"); | ||
| 142 | + return {}; | ||
| 143 | + } | ||
| 144 | + auto output = securityCipher->Decrypt(data); | ||
| 145 | + return output; | ||
| 146 | +} | ||
| 147 | + | ||
| 148 | +} // namespace IotcManagement | ||
| 149 | +} // namespace OHOS | ||
| @@ -0,0 +1,142 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | + | ||
| 26 | + | ||
| 27 | +namespace OHOS { | ||
| 28 | +namespace IotcManagement { | ||
| 29 | + | ||
| 30 | +class E2eSecurityApi { | ||
| 31 | +public: | ||
| 32 | + /** | ||
| 33 | + * SPEKE类型:HiChain | ||
| 34 | + */ | ||
| 35 | + static constexpr int32_t SPEKE_TYPE_HICHAIN = 1; | ||
| 36 | + /** | ||
| 37 | + * SPEKE类型:安全组件 | ||
| 38 | + */ | ||
| 39 | + static constexpr int32_t SPEKE_TYPE_SECURITY = 0; | ||
| 40 | + | ||
| 41 | + /** | ||
| 42 | + * 业务需要在外部自行调用E2eSecurityApi::InitSecuritySdk()初始化安全组件 | ||
| 43 | + */ | ||
| 44 | + static void InitSecuritySdk(); | ||
| 45 | + | ||
| 46 | + /** | ||
| 47 | + * 初始化端到端安全组件 | ||
| 48 | + * | ||
| 49 | + * @param userId 用户Id | ||
| 50 | + * @param phoneAccountId 手机和账号Id | ||
| 51 | + * @param transportCount speke协商请求传输次数 | ||
| 52 | + * @param transportInterval speke协商请求间隔 | ||
| 53 | + */ | ||
| 54 | + static void Init(const std::string& userId, const std::string& phoneAccountId, | ||
| 55 | + uint32_t transportCount = SPEKE_REQUEST_RETRANSPORT_COUNT, | ||
| 56 | + uint32_t transportInterval = SPEKE_REQUEST_RETRANSPORT_INTERVAL); | ||
| 57 | + | ||
| 58 | + /** | ||
| 59 | + * APP退出时调用,清除内存数据 | ||
| 60 | + */ | ||
| 61 | + static void Clear(); | ||
| 62 | + | ||
| 63 | + /** | ||
| 64 | + * 退出账号时调用,销毁安全组件 | ||
| 65 | + */ | ||
| 66 | + static void Destroy(); | ||
| 67 | + | ||
| 68 | + /** | ||
| 69 | + * 启动speke协商函数 | ||
| 70 | + * | ||
| 71 | + * @param pinCode 设备PIN码 | ||
| 72 | + * @param deviceId 云分配的设备id | ||
| 73 | + * @param negotiateCallback speke协商回调函数 | ||
| 74 | + * @param spekeType speke类型,默认安全组件 | ||
| 75 | + * @return speke协商的sessionId | ||
| 76 | + */ | ||
| 77 | + static std::string StartNegotiateSpeke(const std::string& pinCode, const std::string& deviceId, | ||
| 78 | + std::shared_ptr<SpekeNegotiateCallback> negotiateCallback, int32_t spekeType = SPEKE_TYPE_SECURITY, | ||
| 79 | + uint32_t protocolVersion = CommonConstants::PROTOCOL_VERSION_V1); | ||
| 80 | + | ||
| 81 | + /** | ||
| 82 | + * 取消speke协商 | ||
| 83 | + * | ||
| 84 | + * @param sessionId speke协商会话id | ||
| 85 | + * @param spekeType speke类型,默认安全组件 | ||
| 86 | + * @return 取消speke协商结果 | ||
| 87 | + */ | ||
| 88 | + static bool CancelNegotiateSpeke(const std::string& sessionId, int32_t spekeType = SPEKE_TYPE_SECURITY); | ||
| 89 | + | ||
| 90 | + /** | ||
| 91 | + * 处理speke响应消息 | ||
| 92 | + * | ||
| 93 | + * @param deviceId 云分配的设备id | ||
| 94 | + * @param jsonObject 响应消息 | ||
| 95 | + * @param spekeType speke类型,默认安全组件 | ||
| 96 | + */ | ||
| 97 | + static void ProcessReceivedSpekeMsg(const std::string& deviceId, const std::string& response, | ||
| 98 | + int32_t spekeType = SPEKE_TYPE_SECURITY, | ||
| 99 | + uint32_t protocolVersion = CommonConstants::PROTOCOL_VERSION_V1); | ||
| 100 | + | ||
| 101 | + /** | ||
| 102 | + * 判断是否支持hiChain 3.0 | ||
| 103 | + * @param version 设备版本号 | ||
| 104 | + * @returns true:支持 false:不支持 | ||
| 105 | + */ | ||
| 106 | + static bool IsSupportHiChain(int32_t version); | ||
| 107 | + | ||
| 108 | + /** | ||
| 109 | + * 清除掉speke信息 | ||
| 110 | + * | ||
| 111 | + * @param securityCipher speke加解密对象 | ||
| 112 | + */ | ||
| 113 | + static void DestorySpeke(std::shared_ptr<SecurityCipher> securityCipher); | ||
| 114 | + | ||
| 115 | + /** | ||
| 116 | + * 加密函数 | ||
| 117 | + * | ||
| 118 | + * @param securityCipher speke加密对象 | ||
| 119 | + * @param data 待加密数据 | ||
| 120 | + * @return 加密后数据 | ||
| 121 | + */ | ||
| 122 | + static std::vector<uint8_t> EncryptData(std::shared_ptr<SecurityCipher> securityCipher, const std::vector<uint8_t>& data); | ||
| 123 | + | ||
| 124 | + /** | ||
| 125 | + * 解密函数 | ||
| 126 | + * | ||
| 127 | + * @param securityCipher speke解密对象 | ||
| 128 | + * @param data 待解密数据 | ||
| 129 | + * @return 解密后数据 | ||
| 130 | + */ | ||
| 131 | + static std::vector<uint8_t> DecryptData(std::shared_ptr<SecurityCipher> securityCipher, const std::vector<uint8_t>& data); | ||
| 132 | + | ||
| 133 | +private: | ||
| 134 | + static constexpr uint32_t SPEKE_REQUEST_RETRANSPORT_COUNT = 5; | ||
| 135 | + static constexpr uint32_t SPEKE_REQUEST_RETRANSPORT_INTERVAL = 1500; | ||
| 136 | + static constexpr const char* DEFAULT_SPEKE_USER_ID = "iotc_local_user"; | ||
| 137 | +}; | ||
| 138 | + | ||
| 139 | +} // namespace IotcManagement | ||
| 140 | +} // namespace OHOS | ||
| 141 | + | ||
| 142 | + | ||
| @@ -0,0 +1,170 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | + | ||
| 26 | + | ||
| 27 | + | ||
| 28 | +namespace OHOS { | ||
| 29 | +namespace IotcManagement { | ||
| 30 | + | ||
| 31 | +std::mutex HwDeviceAuthManager::mutex_; | ||
| 32 | +HwDeviceAuthManager* HwDeviceAuthManager::instance_ = nullptr; | ||
| 33 | + | ||
| 34 | +HwDeviceAuthManager::HwDeviceAuthManager() | ||
| 35 | +{ | ||
| 36 | + ConfiguredVersionInfo::Init(); | ||
| 37 | +} | ||
| 38 | + | ||
| 39 | +HwDeviceAuthManager::~HwDeviceAuthManager() | ||
| 40 | +{ | ||
| 41 | +} | ||
| 42 | + | ||
| 43 | +HwDeviceAuthManager& HwDeviceAuthManager::GetInstance() | ||
| 44 | +{ | ||
| 45 | + if (instance_ == nullptr) { | ||
| 46 | + std::lock_guard<std::mutex> lock(mutex_); | ||
| 47 | + if (instance_ == nullptr) { | ||
| 48 | + instance_ = new HwDeviceAuthManager(); | ||
| 49 | + } | ||
| 50 | + } | ||
| 51 | + return *instance_; | ||
| 52 | +} | ||
| 53 | + | ||
| 54 | +bool HwDeviceAuthManager::CheckParamsValidity(std::shared_ptr<OperationParameter> operationParams) const | ||
| 55 | +{ | ||
| 56 | + if (!operationParams || !operationParams->GetCallbackHandler() || operationParams->GetSessionId().empty()) { | ||
| 57 | + IOTC_LOGE("HwDeviceAuthManager: CallbackHandler or SessionId is null"); | ||
| 58 | + return false; | ||
| 59 | + } | ||
| 60 | + | ||
| 61 | + if (operationParams->GetPeerId().size() > MAX_AUTH_ID_LEN || | ||
| 62 | + operationParams->GetSelfId().size() > MAX_AUTH_ID_LEN) { | ||
| 63 | + IOTC_LOGE("HwDeviceAuthManager: authId is too long"); | ||
| 64 | + return false; | ||
| 65 | + } | ||
| 66 | + | ||
| 67 | + if (operationParams->GetSessionId().empty() || operationParams->GetPeerId().empty() || | ||
| 68 | + operationParams->GetSelfId().empty()) { | ||
| 69 | + IOTC_LOGE("HwDeviceAuthManager: sessionInfo is invalid"); | ||
| 70 | + return false; | ||
| 71 | + } | ||
| 72 | + | ||
| 73 | + if (!UserType::ValidUserType(operationParams->GetPeerType()) || | ||
| 74 | + !UserType::ValidUserType(operationParams->GetSelfType())) { | ||
| 75 | + IOTC_LOGE("HwDeviceAuthManager: invalid user type"); | ||
| 76 | + return false; | ||
| 77 | + } | ||
| 78 | + | ||
| 79 | + return true; | ||
| 80 | +} | ||
| 81 | + | ||
| 82 | +int32_t HwDeviceAuthManager::GetSessionKeyWithPin(std::shared_ptr<OperationParameter> operationParams, | ||
| 83 | + const std::string& pinCode, int32_t keyLength) | ||
| 84 | +{ | ||
| 85 | + if (!operationParams) { | ||
| 86 | + IOTC_LOGE("HwDeviceAuthManager: operationParams is null"); | ||
| 87 | + return ReturnCode::REQUEST_REJECTED; | ||
| 88 | + } | ||
| 89 | + | ||
| 90 | + if (pinCode.empty()) { | ||
| 91 | + IOTC_LOGE("HwDeviceAuthManager: pinCode is empty"); | ||
| 92 | + return ReturnCode::INVALID_PARAMETERS; | ||
| 93 | + } | ||
| 94 | + | ||
| 95 | + std::string sessionId = operationParams->GetSessionId(); | ||
| 96 | + if (sessionId.empty()) { | ||
| 97 | + IOTC_LOGE("HwDeviceAuthManager: sessionId is empty"); | ||
| 98 | + return ReturnCode::INVALID_PARAMETERS; | ||
| 99 | + } | ||
| 100 | + | ||
| 101 | + if (RequestManager::GetInstance().GetRequest(sessionId) != nullptr) { | ||
| 102 | + IOTC_LOGE("HwDeviceAuthManager: conflict auth key agree request"); | ||
| 103 | + return ReturnCode::CONFLICT_REQUEST; | ||
| 104 | + } | ||
| 105 | + ConfirmParams confirmParams; | ||
| 106 | + confirmParams.SetPin(pinCode); | ||
| 107 | + confirmParams.SetKeyLength(keyLength); | ||
| 108 | + | ||
| 109 | + auto authKeyAgreeRequest = std::make_shared<AuthKeyAgreeRequest>(operationParams, true, confirmParams); | ||
| 110 | + authKeyAgreeRequest->Init(); | ||
| 111 | + int32_t ret = RequestManager::GetInstance().AddRequest(sessionId, authKeyAgreeRequest); | ||
| 112 | + if (ret == ReturnCode::REQUEST_ACCEPTED) { | ||
| 113 | + std::shared_ptr<RequestBase> request = RequestManager::GetInstance().GetRequest(sessionId); | ||
| 114 | + if (!request) { | ||
| 115 | + IOTC_LOGE("HwDeviceAuthManager: get auth key agree request failed"); | ||
| 116 | + return ret; | ||
| 117 | + } | ||
| 118 | + request->DoStart(); | ||
| 119 | + } | ||
| 120 | + return ret; | ||
| 121 | +} | ||
| 122 | + | ||
| 123 | +int32_t HwDeviceAuthManager::ProcessReceivedData(std::shared_ptr<OperationParameter> operationParams, | ||
| 124 | + const std::string& receivedData) | ||
| 125 | +{ | ||
| 126 | + if (!CheckParamsValidity(operationParams)) { | ||
| 127 | + return ReturnCode::INVALID_PARAMETERS; | ||
| 128 | + } | ||
| 129 | + std::string sessionId = operationParams->GetSessionId(); | ||
| 130 | + std::shared_ptr<RequestBase> request = RequestManager::GetInstance().GetRequest(sessionId); | ||
| 131 | + bool isCanceled = request != nullptr && request->GetRequestStatus() != nullptr | ||
| 132 | + && (request->GetRequestStatus()->IsCanceled() || request->GetRequestStatus()->IsFinished()); | ||
| 133 | + if (isCanceled) { | ||
| 134 | + IOTC_LOGE("HwDeviceAuthManager: request is canceled or finished"); | ||
| 135 | + return ReturnCode::REQUEST_NOT_FOUND; | ||
| 136 | + } | ||
| 137 | + if (!request) { | ||
| 138 | + IOTC_LOGE("HwDeviceAuthManager: request not found for process received data"); | ||
| 139 | + return ReturnCode::REQUEST_NOT_FOUND; | ||
| 140 | + } | ||
| 141 | + int32_t ret = request->ProcessReceivedData(receivedData); | ||
| 142 | + if (ret != ReturnCode::SUCCESS) { | ||
| 143 | + IOTC_LOGE("HwDeviceAuthManager::ProcessReceivedData task failed ret=%{public}d", ret); | ||
| 144 | + } | ||
| 145 | + return ret; | ||
| 146 | +} | ||
| 147 | + | ||
| 148 | +int32_t HwDeviceAuthManager::CancelRequest(const std::string& sessionId) | ||
| 149 | +{ | ||
| 150 | + if (sessionId.empty()) { | ||
| 151 | + IOTC_LOGE("HwDeviceAuthManager: invalid parameters when call cancel"); | ||
| 152 | + return ReturnCode::INVALID_PARAMETERS; | ||
| 153 | + } | ||
| 154 | + | ||
| 155 | + std::shared_ptr<RequestBase> request = RequestManager::GetInstance().GetRequest(sessionId); | ||
| 156 | + if (!request) { | ||
| 157 | + return ReturnCode::REQUEST_NOT_FOUND; | ||
| 158 | + } | ||
| 159 | + bool isCanceled = request->GetRequestStatus() != nullptr | ||
| 160 | + && (request->GetRequestStatus()->IsCanceled() || request->GetRequestStatus()->IsFinished()); | ||
| 161 | + if (isCanceled) { | ||
| 162 | + return ReturnCode::SUCCESS; | ||
| 163 | + } | ||
| 164 | + | ||
| 165 | + request->DoCancel(); | ||
| 166 | + return ReturnCode::SUCCESS; | ||
| 167 | +} | ||
| 168 | + | ||
| 169 | +} // namespace IotcManagement | ||
| 170 | +} // namespace OHOS | ||
| @@ -0,0 +1,55 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | +namespace OHOS { | ||
| 26 | +namespace IotcManagement { | ||
| 27 | + | ||
| 28 | +class HwDeviceAuthManager { | ||
| 29 | +public: | ||
| 30 | + static HwDeviceAuthManager& GetInstance(); | ||
| 31 | + | ||
| 32 | + int32_t GetSessionKeyWithPin(std::shared_ptr<OperationParameter> operationParams, | ||
| 33 | + const std::string& pinCode, int32_t keyLength); | ||
| 34 | + | ||
| 35 | + int32_t ProcessReceivedData(std::shared_ptr<OperationParameter> operationParams, | ||
| 36 | + const std::string& receivedData); | ||
| 37 | + | ||
| 38 | + int32_t CancelRequest(const std::string& sessionId); | ||
| 39 | + | ||
| 40 | +private: | ||
| 41 | + HwDeviceAuthManager(); | ||
| 42 | + ~HwDeviceAuthManager(); | ||
| 43 | + | ||
| 44 | + bool CheckParamsValidity(std::shared_ptr<OperationParameter> operationParams) const; | ||
| 45 | + | ||
| 46 | + static constexpr uint32_t MAX_AUTH_ID_LEN = 64; | ||
| 47 | + | ||
| 48 | + static std::mutex mutex_; | ||
| 49 | + static HwDeviceAuthManager* instance_; | ||
| 50 | +}; | ||
| 51 | + | ||
| 52 | +} // namespace IotcManagement | ||
| 53 | +} // namespace OHOS | ||
| 54 | + | ||
| 55 | + | ||
| @@ -0,0 +1,108 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | +namespace OHOS { | ||
| 23 | +namespace IotcManagement { | ||
| 24 | + | ||
| 25 | +IotSecurityManager::IotSecurityManager(std::shared_ptr<CoapSessionEntity> entity, SecurityType type) | ||
| 26 | + : SecuritySessionManager(entity, type) | ||
| 27 | +{ | ||
| 28 | +} | ||
| 29 | + | ||
| 30 | +std::vector<uint8_t> IotSecurityManager::EncryptData(const std::vector<uint8_t>& byteContent) | ||
| 31 | +{ | ||
| 32 | + std::vector<uint8_t> result; | ||
| 33 | + if (mType_ != SecurityType::TYPE_GCM) { | ||
| 34 | + IOTC_LOGW("IotSecurityManager::EncryptData type is not GCM!"); | ||
| 35 | + return result; | ||
| 36 | + } | ||
| 37 | + | ||
| 38 | + if (mPskKey_.empty()) { | ||
| 39 | + IOTC_LOGW("IotSecurityManager::EncryptData mPskKey is null!"); | ||
| 40 | + return result; | ||
| 41 | + } | ||
| 42 | + | ||
| 43 | + if (byteContent.empty()) { | ||
| 44 | + IOTC_LOGW("IotSecurityManager::EncryptData byteContent is null"); | ||
| 45 | + return result; | ||
| 46 | + } | ||
| 47 | + | ||
| 48 | + auto iv = CryptoRandom::GenerateRandom(mIvLenGcm_); | ||
| 49 | + if (iv.empty()) { | ||
| 50 | + IOTC_LOGW("IotSecurityManager::EncryptData generate random failed"); | ||
| 51 | + return result; | ||
| 52 | + } | ||
| 53 | + | ||
| 54 | + auto encryptResult = AesGcmUtil::Encrypt(byteContent, mPskKey_, iv, {}); | ||
| 55 | + if (encryptResult.empty()) { | ||
| 56 | + IOTC_LOGW("IotSecurityManager::EncryptData encrypt failed"); | ||
| 57 | + return result; | ||
| 58 | + } | ||
| 59 | + | ||
| 60 | + result.resize(mIvLenGcm_ + encryptResult.size()); | ||
| 61 | + for (size_t i = 0; i < mIvLenGcm_; ++i) { | ||
| 62 | + result[i] = iv[i]; | ||
| 63 | + } | ||
| 64 | + for (size_t i = 0; i < encryptResult.size(); ++i) { | ||
| 65 | + result[mIvLenGcm_ + i] = encryptResult[i]; | ||
| 66 | + } | ||
| 67 | + | ||
| 68 | + return result; | ||
| 69 | +} | ||
| 70 | + | ||
| 71 | +std::vector<uint8_t> IotSecurityManager::DecryptData(const std::vector<uint8_t>& data) | ||
| 72 | +{ | ||
| 73 | + std::vector<uint8_t> result; | ||
| 74 | + if (mType_ != SecurityType::TYPE_GCM) { | ||
| 75 | + IOTC_LOGW("IotSecurityManager::DecryptData type is not GCM!"); | ||
| 76 | + return result; | ||
| 77 | + } | ||
| 78 | + | ||
| 79 | + if (data.size() < mIvLenGcm_) { | ||
| 80 | + IOTC_LOGW("IotSecurityManager::DecryptData data length error!"); | ||
| 81 | + return result; | ||
| 82 | + } | ||
| 83 | + | ||
| 84 | + if (mPskKey_.empty()) { | ||
| 85 | + IOTC_LOGW("IotSecurityManager::DecryptData mPskKey is null!"); | ||
| 86 | + return result; | ||
| 87 | + } | ||
| 88 | + | ||
| 89 | + std::vector<uint8_t> iv(data.begin(), data.begin() + mIvLenGcm_); | ||
| 90 | + std::vector<uint8_t> cipherAndTag(data.begin() + mIvLenGcm_, data.end()); | ||
| 91 | + | ||
| 92 | + result = AesGcmUtil::Decrypt(cipherAndTag, mPskKey_, iv, {}); | ||
| 93 | + if (result.empty()) { | ||
| 94 | + IOTC_LOGW("IotSecurityManager::DecryptData decrypt failed"); | ||
| 95 | + return result; | ||
| 96 | + } | ||
| 97 | + | ||
| 98 | + return result; | ||
| 99 | +} | ||
| 100 | + | ||
| 101 | +void IotSecurityManager::Clear() | ||
| 102 | +{ | ||
| 103 | + IOTC_LOGI("IotSecurityManager::Clear in"); | ||
| 104 | + mPskKey_.clear(); | ||
| 105 | +} | ||
| 106 | + | ||
| 107 | +} // namespace IotcManagement | ||
| 108 | +} // namespace OHOS | ||
| @@ -0,0 +1,44 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | + | ||
| 26 | +namespace OHOS { | ||
| 27 | +namespace IotcManagement { | ||
| 28 | + | ||
| 29 | +class IotSecurityManager : public SecuritySessionManager, public SpekeMessageCryptor { | ||
| 30 | +public: | ||
| 31 | + IotSecurityManager(std::shared_ptr<CoapSessionEntity> entity, SecurityType type); | ||
| 32 | + ~IotSecurityManager() = default; | ||
| 33 | + | ||
| 34 | + std::vector<uint8_t> EncryptData(const std::vector<uint8_t>& data) override; | ||
| 35 | + | ||
| 36 | + std::vector<uint8_t> DecryptData(const std::vector<uint8_t>& data) override; | ||
| 37 | + | ||
| 38 | + void Clear() override; | ||
| 39 | +}; | ||
| 40 | + | ||
| 41 | +} // namespace IotcManagement | ||
| 42 | +} // namespace OHOS | ||
| 43 | + | ||
| 44 | + | ||
| @@ -0,0 +1,239 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | + | ||
| 26 | + | ||
| 27 | +namespace OHOS { | ||
| 28 | +namespace IotcManagement { | ||
| 29 | + | ||
| 30 | +SecurityAdapter::SecurityAdapter() | ||
| 31 | + : isInit_(false), localIdentityInfo_(nullptr), messageConfig_(nullptr) | ||
| 32 | +{ | ||
| 33 | +} | ||
| 34 | + | ||
| 35 | +SecurityAdapter& SecurityAdapter::GetInstance() | ||
| 36 | +{ | ||
| 37 | + static SecurityAdapter instance; | ||
| 38 | + return instance; | ||
| 39 | +} | ||
| 40 | + | ||
| 41 | +std::string SecurityAdapter::GenerateSessionId() | ||
| 42 | +{ | ||
| 43 | + return CryptoRandom::GenerateRandomHexString(SESSION_ID_SIZE); | ||
| 44 | +} | ||
| 45 | + | ||
| 46 | +std::string SecurityAdapter::GetPinCode(const std::string& sessionId) | ||
| 47 | +{ | ||
| 48 | + auto it = pinCodeMap_.find(sessionId); | ||
| 49 | + if (it == pinCodeMap_.end()) { | ||
| 50 | + IOTC_LOGW("SecurityAdapter::GetPinCode is undefined"); | ||
| 51 | + return ""; | ||
| 52 | + } | ||
| 53 | + std::string pinCode = it->second; | ||
| 54 | + pinCodeMap_.erase(sessionId); | ||
| 55 | + return pinCode; | ||
| 56 | +} | ||
| 57 | + | ||
| 58 | +bool SecurityAdapter::Init(std::shared_ptr<IdentityInfo> identityInfo, std::shared_ptr<MessageConfig> messageConfig) | ||
| 59 | +{ | ||
| 60 | + if (isInit_) { | ||
| 61 | + IOTC_LOGW("SecurityAdapter::Init already init"); | ||
| 62 | + return true; | ||
| 63 | + } | ||
| 64 | + if (!identityInfo || !messageConfig) { | ||
| 65 | + IOTC_LOGE("SecurityAdapter::Init identityInfo or messageConfig is null"); | ||
| 66 | + return false; | ||
| 67 | + } | ||
| 68 | + localIdentityInfo_ = identityInfo; | ||
| 69 | + messageConfig_ = messageConfig; | ||
| 70 | + isInit_ = true; | ||
| 71 | + IOTC_LOGI("SecurityAdapter::Init success"); | ||
| 72 | + return true; | ||
| 73 | +} | ||
| 74 | + | ||
| 75 | +bool SecurityAdapter::IsInit(SpekeNegotiateCallback* callback) const | ||
| 76 | +{ | ||
| 77 | + if (!isInit_) { | ||
| 78 | + IOTC_LOGE("SecurityAdapter::IsInit not init"); | ||
| 79 | + if (callback != nullptr) { | ||
| 80 | + callback->OnFailure(ReturnCode::NOT_INIT, "not init"); | ||
| 81 | + } | ||
| 82 | + return false; | ||
| 83 | + } | ||
| 84 | + if (localIdentityInfo_ == nullptr) { | ||
| 85 | + IOTC_LOGE("SecurityAdapter::IsInit localIdentityInfo is null"); | ||
| 86 | + if (callback != nullptr) { | ||
| 87 | + callback->OnFailure(ReturnCode::INVALID_PARAMETERS, "local identityInfo is null"); | ||
| 88 | + } | ||
| 89 | + return false; | ||
| 90 | + } | ||
| 91 | + return true; | ||
| 92 | +} | ||
| 93 | + | ||
| 94 | +std::string SecurityAdapter::ClientNegotiateSpeke(const std::string& pinCode, IdentityInfo* peerIdentityInfo, | ||
| 95 | + std::shared_ptr<SpekeNegotiateCallback> callback, uint32_t protocolVersion) | ||
| 96 | +{ | ||
| 97 | + if (!callback) { | ||
| 98 | + IOTC_LOGE("SecurityAdapter::ClientNegotiateSpeke callback is null"); | ||
| 99 | + return ""; | ||
| 100 | + } | ||
| 101 | + | ||
| 102 | + if (pinCode.empty() || peerIdentityInfo == nullptr) { | ||
| 103 | + IOTC_LOGE("SecurityAdapter::ClientNegotiateSpeke invalid param"); | ||
| 104 | + callback->OnFailure(ReturnCode::INVALID_PARAMETERS, "invalid param"); | ||
| 105 | + return ""; | ||
| 106 | + } | ||
| 107 | + | ||
| 108 | + std::string sessionId = GenerateSessionId(); | ||
| 109 | + IOTC_LOGI("SecurityAdapter::ClientNegotiateSpeke sessionId=%{public}s ver=%{public}u", | ||
| 110 | + sessionId.c_str(), protocolVersion); | ||
| 111 | + | ||
| 112 | + if (!IsInit(callback.get())) { | ||
| 113 | + return ""; | ||
| 114 | + } | ||
| 115 | + | ||
| 116 | + auto callbackImpl = std::make_shared<AuthCallbackMethods>(callback, protocolVersion); | ||
| 117 | + | ||
| 118 | + ParameterBuilder builder(sessionId); | ||
| 119 | + builder.SetCallbackMethods(callbackImpl); | ||
| 120 | + builder.SetLocalIdentityInfo(localIdentityInfo_); | ||
| 121 | + builder.SetPeerIdentityInfo(peerIdentityInfo); | ||
| 122 | + builder.SetProtocolVersion(protocolVersion); | ||
| 123 | + std::shared_ptr<OperationParameter> parameter(builder.Build()); | ||
| 124 | + | ||
| 125 | + int32_t returnCode = HwDeviceAuthManager::GetInstance().GetSessionKeyWithPin( | ||
| 126 | + parameter, pinCode, GlobalParams::SESSION_KEY_LENGTH); | ||
| 127 | + | ||
| 128 | + if (returnCode != ReturnCode::REQUEST_ACCEPTED) { | ||
| 129 | + IOTC_LOGE("SecurityAdapter::ClientNegotiateSpeke start request error, ret=%{public}d", returnCode); | ||
| 130 | + callback->OnFailure(returnCode, "start request error"); | ||
| 131 | + } | ||
| 132 | + | ||
| 133 | + return sessionId; | ||
| 134 | +} | ||
| 135 | + | ||
| 136 | +void SecurityAdapter::ProcessReceivedMsg(const std::string& request, IdentityInfo* peerIdentityInfo, | ||
| 137 | + uint32_t protocolVersion) | ||
| 138 | +{ | ||
| 139 | + IOTC_LOGI("SecurityAdapter::ProcessReceivedMsg ver=%{public}u", protocolVersion); | ||
| 140 | + if (request.empty()) { | ||
| 141 | + IOTC_LOGE("SecurityAdapter::ProcessReceivedMsg request is empty"); | ||
| 142 | + return; | ||
| 143 | + } | ||
| 144 | + | ||
| 145 | + std::string sessionId = ""; | ||
| 146 | + PassThroughData passThroughData(request, sessionId, protocolVersion); | ||
| 147 | + if (!IsInit(nullptr)) { | ||
| 148 | + IOTC_LOGE("SecurityAdapter::ProcessReceivedMsg passThroughData is null or not init"); | ||
| 149 | + return; | ||
| 150 | + } | ||
| 151 | + sessionId = passThroughData.GetSessionId(); | ||
| 152 | + if (sessionId.empty()) { | ||
| 153 | + // INFORM_MESSAGE 等错误响应不带 sessionId,回退到当前唯一 pending 请求 | ||
| 154 | + sessionId = RequestManager::GetInstance().GetOnlyRequestSessionId(); | ||
| 155 | + IOTC_LOGW("SecurityAdapter::ProcessReceivedMsg sessionId missing in response, fallback to pending=%{public}s", | ||
| 156 | + sessionId.c_str()); | ||
| 157 | + } | ||
| 158 | + auto callbackImpl = std::make_shared<AuthCallbackMethods>(emptyCallback_, protocolVersion); | ||
| 159 | + ParameterBuilder builder(sessionId); | ||
| 160 | + builder.SetCallbackMethods(callbackImpl); | ||
| 161 | + builder.SetLocalIdentityInfo(localIdentityInfo_); | ||
| 162 | + builder.SetPeerIdentityInfo(peerIdentityInfo); | ||
| 163 | + std::shared_ptr<OperationParameter> parameter(builder.Build()); | ||
| 164 | + | ||
| 165 | + std::string jsonData = passThroughData.GetSecurityDataObject(); | ||
| 166 | + HwDeviceAuthManager::GetInstance().ProcessReceivedData(parameter, jsonData); | ||
| 167 | +} | ||
| 168 | + | ||
| 169 | +int32_t SecurityAdapter::CancelRequest(const std::string& sessionId) | ||
| 170 | +{ | ||
| 171 | + if (!IsInit(nullptr)) { | ||
| 172 | + return ReturnCode::INVALID_PARAMETERS; | ||
| 173 | + } | ||
| 174 | + int32_t result = HwDeviceAuthManager::GetInstance().CancelRequest(sessionId); | ||
| 175 | + IOTC_LOGI("SecurityAdapter::CancelRequest result=%{public}d", result); | ||
| 176 | + return result; | ||
| 177 | +} | ||
| 178 | + | ||
| 179 | +int32_t SecurityAdapter::GetSessionKeyWithPin(std::shared_ptr<OperationParameter> operationParams, | ||
| 180 | + const std::string& pinCode, int32_t keyLength) | ||
| 181 | +{ | ||
| 182 | + IOTC_LOGI("SecurityAdapter::GetSessionKeyWithPin"); | ||
| 183 | + if (!IsInit(nullptr)) { | ||
| 184 | + return ReturnCode::NOT_INIT; | ||
| 185 | + } | ||
| 186 | + if (!operationParams || pinCode.empty()) { | ||
| 187 | + IOTC_LOGE("SecurityAdapter::GetSessionKeyWithPin invalid param"); | ||
| 188 | + return ReturnCode::INVALID_PARAMETERS; | ||
| 189 | + } | ||
| 190 | + | ||
| 191 | + std::string sessionId = operationParams->GetSessionId(); | ||
| 192 | + if (sessionId.empty()) { | ||
| 193 | + IOTC_LOGE("SecurityAdapter::GetSessionKeyWithPin sessionId is empty"); | ||
| 194 | + return ReturnCode::INVALID_PARAMETERS; | ||
| 195 | + } | ||
| 196 | + | ||
| 197 | + pinCodeMap_[sessionId] = pinCode; | ||
| 198 | + return ReturnCode::SUCCESS; | ||
| 199 | +} | ||
| 200 | + | ||
| 201 | +int32_t SecurityAdapter::ProcessReceivedData(std::shared_ptr<OperationParameter> operationParams, | ||
| 202 | + const std::string& receivedData) | ||
| 203 | +{ | ||
| 204 | + IOTC_LOGI("SecurityAdapter::ProcessReceivedData"); | ||
| 205 | + if (!IsInit(nullptr)) { | ||
| 206 | + return ReturnCode::NOT_INIT; | ||
| 207 | + } | ||
| 208 | + if (!operationParams || receivedData.empty()) { | ||
| 209 | + IOTC_LOGE("SecurityAdapter::ProcessReceivedData invalid param"); | ||
| 210 | + return ReturnCode::INVALID_PARAMETERS; | ||
| 211 | + } | ||
| 212 | + return ReturnCode::SUCCESS; | ||
| 213 | +} | ||
| 214 | + | ||
| 215 | +void SecurityAdapter::Destroy() | ||
| 216 | +{ | ||
| 217 | + Clear(); | ||
| 218 | +} | ||
| 219 | + | ||
| 220 | +void SecurityAdapter::Clear() | ||
| 221 | +{ | ||
| 222 | + localIdentityInfo_.reset(); | ||
| 223 | + messageConfig_.reset(); | ||
| 224 | + isInit_ = false; | ||
| 225 | + pinCodeMap_.clear(); | ||
| 226 | +} | ||
| 227 | + | ||
| 228 | +std::shared_ptr<MessageConfig> SecurityAdapter::GetMessageConfig() | ||
| 229 | +{ | ||
| 230 | + return messageConfig_; | ||
| 231 | +} | ||
| 232 | + | ||
| 233 | +std::shared_ptr<IdentityInfo> SecurityAdapter::GetLocalIdentityInfo() | ||
| 234 | +{ | ||
| 235 | + return localIdentityInfo_; | ||
| 236 | +} | ||
| 237 | + | ||
| 238 | +} // namespace IotcManagement | ||
| 239 | +} // namespace OHOS | ||
| @@ -0,0 +1,86 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | + | ||
| 26 | + | ||
| 27 | + | ||
| 28 | + | ||
| 29 | + | ||
| 30 | + | ||
| 31 | + | ||
| 32 | +namespace OHOS { | ||
| 33 | +namespace IotcManagement { | ||
| 34 | + | ||
| 35 | +class SecurityAdapter { | ||
| 36 | +public: | ||
| 37 | + static SecurityAdapter& GetInstance(); | ||
| 38 | + | ||
| 39 | + static std::string GenerateSessionId(); | ||
| 40 | + | ||
| 41 | + std::string GetPinCode(const std::string& sessionId); | ||
| 42 | + | ||
| 43 | + bool Init(std::shared_ptr<IdentityInfo> identityInfo, std::shared_ptr<MessageConfig> messageConfig); | ||
| 44 | + | ||
| 45 | + std::string ClientNegotiateSpeke(const std::string& pinCode, IdentityInfo* peerIdentityInfo, | ||
| 46 | + std::shared_ptr<SpekeNegotiateCallback> callback, | ||
| 47 | + uint32_t protocolVersion = CommonConstants::PROTOCOL_VERSION_V1); | ||
| 48 | + | ||
| 49 | + void ProcessReceivedMsg(const std::string& request, IdentityInfo* peerIdentityInfo, | ||
| 50 | + uint32_t protocolVersion = CommonConstants::PROTOCOL_VERSION_V1); | ||
| 51 | + | ||
| 52 | + int32_t CancelRequest(const std::string& sessionId); | ||
| 53 | + | ||
| 54 | + int32_t GetSessionKeyWithPin(std::shared_ptr<OperationParameter> operationParams, | ||
| 55 | + const std::string& pinCode, int32_t keyLength); | ||
| 56 | + | ||
| 57 | + int32_t ProcessReceivedData(std::shared_ptr<OperationParameter> operationParams, | ||
| 58 | + const std::string& receivedData); | ||
| 59 | + | ||
| 60 | + void Destroy(); | ||
| 61 | + | ||
| 62 | + void Clear(); | ||
| 63 | + | ||
| 64 | + std::shared_ptr<MessageConfig> GetMessageConfig(); | ||
| 65 | + | ||
| 66 | + std::shared_ptr<IdentityInfo> GetLocalIdentityInfo(); | ||
| 67 | + | ||
| 68 | +private: | ||
| 69 | + SecurityAdapter(); | ||
| 70 | + ~SecurityAdapter() = default; | ||
| 71 | + | ||
| 72 | + bool IsInit(SpekeNegotiateCallback* callback) const; | ||
| 73 | + | ||
| 74 | + static constexpr uint32_t SESSION_ID_SIZE = 16; | ||
| 75 | + | ||
| 76 | + bool isInit_; | ||
| 77 | + std::shared_ptr<IdentityInfo> localIdentityInfo_; | ||
| 78 | + std::shared_ptr<MessageConfig> messageConfig_; | ||
| 79 | + std::map<std::string, std::string> pinCodeMap_; | ||
| 80 | + std::shared_ptr<SpekeNegotiateCallback> emptyCallback_ = std::make_shared<SpekeNegotiateCallbackEmpty>(); | ||
| 81 | +}; | ||
| 82 | + | ||
| 83 | +} // namespace IotcManagement | ||
| 84 | +} // namespace OHOS | ||
| 85 | + | ||
| 86 | + | ||
| @@ -0,0 +1,113 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | +namespace OHOS { | ||
| 22 | +namespace IotcManagement { | ||
| 23 | + | ||
| 24 | +SecurityCipher::SecurityCipher(const std::vector<uint8_t>& sessionKey) | ||
| 25 | + : sessionKey_(sessionKey) | ||
| 26 | +{ | ||
| 27 | +} | ||
| 28 | + | ||
| 29 | +SecurityCipher::~SecurityCipher() | ||
| 30 | +{ | ||
| 31 | + Destroy(); | ||
| 32 | +} | ||
| 33 | + | ||
| 34 | +void SecurityCipher::Destroy() | ||
| 35 | +{ | ||
| 36 | + for (size_t i = 0; i < sessionKey_.size(); ++i) { | ||
| 37 | + sessionKey_[i] = 0; | ||
| 38 | + } | ||
| 39 | + sessionKey_.clear(); | ||
| 40 | + sessionKey_.shrink_to_fit(); | ||
| 41 | +} | ||
| 42 | + | ||
| 43 | +std::vector<uint8_t> SecurityCipher::Encrypt(const std::vector<uint8_t>& data) | ||
| 44 | +{ | ||
| 45 | + std::vector<uint8_t> output; | ||
| 46 | + if (sessionKey_.empty()) { | ||
| 47 | + IOTC_LOGW("SecurityCipher::Encrypt session key is null"); | ||
| 48 | + return output; | ||
| 49 | + } | ||
| 50 | + | ||
| 51 | + if (data.empty()) { | ||
| 52 | + IOTC_LOGE("SecurityCipher::Encrypt data is null"); | ||
| 53 | + return output; | ||
| 54 | + } | ||
| 55 | + | ||
| 56 | + std::vector<uint8_t> iv = CryptoRandom::GenerateRandom(IV_LENGTH); | ||
| 57 | + if (iv.empty()) { | ||
| 58 | + IOTC_LOGE("SecurityCipher::Encrypt random failed"); | ||
| 59 | + return output; | ||
| 60 | + } | ||
| 61 | + | ||
| 62 | + auto encryptResult = AesGcmUtil::Encrypt(data, sessionKey_, iv, {}); | ||
| 63 | + if (encryptResult.empty()) { | ||
| 64 | + IOTC_LOGE("SecurityCipher::Encrypt AesGcmUtil::Encrypt failed"); | ||
| 65 | + return output; | ||
| 66 | + } | ||
| 67 | + | ||
| 68 | + output.resize(VERSION_LENGTH + IV_LENGTH + encryptResult.size()); | ||
| 69 | + output[0] = VERSION_ZERO; | ||
| 70 | + for (size_t i = 0; i < IV_LENGTH; ++i) { | ||
| 71 | + output[VERSION_LENGTH + i] = iv[i]; | ||
| 72 | + } | ||
| 73 | + for (size_t i = 0; i < encryptResult.size(); ++i) { | ||
| 74 | + output[VERSION_LENGTH + IV_LENGTH + i] = encryptResult[i]; | ||
| 75 | + } | ||
| 76 | + | ||
| 77 | + return output; | ||
| 78 | +} | ||
| 79 | + | ||
| 80 | +std::vector<uint8_t> SecurityCipher::Decrypt(const std::vector<uint8_t>& data) | ||
| 81 | +{ | ||
| 82 | + std::vector<uint8_t> output; | ||
| 83 | + if (sessionKey_.empty()) { | ||
| 84 | + IOTC_LOGW("SecurityCipher::Decrypt session key is null"); | ||
| 85 | + return output; | ||
| 86 | + } | ||
| 87 | + | ||
| 88 | + uint32_t minLength = VERSION_LENGTH + IV_LENGTH; | ||
| 89 | + if (data.empty() || data.size() <= minLength) { | ||
| 90 | + IOTC_LOGE("SecurityCipher::Decrypt data too short"); | ||
| 91 | + return output; | ||
| 92 | + } | ||
| 93 | + | ||
| 94 | + uint8_t version = data[0]; | ||
| 95 | + if (version != VERSION_ZERO) { | ||
| 96 | + IOTC_LOGE("SecurityCipher::Decrypt version not supported: %{public}d", version); | ||
| 97 | + return output; | ||
| 98 | + } | ||
| 99 | + | ||
| 100 | + std::vector<uint8_t> iv(data.begin() + VERSION_LENGTH, data.begin() + VERSION_LENGTH + IV_LENGTH); | ||
| 101 | + std::vector<uint8_t> cipherAndTag(data.begin() + VERSION_LENGTH + IV_LENGTH, data.end()); | ||
| 102 | + | ||
| 103 | + output = AesGcmUtil::Decrypt(cipherAndTag, sessionKey_, iv, {}); | ||
| 104 | + if (output.empty()) { | ||
| 105 | + IOTC_LOGE("SecurityCipher::Decrypt AesGcmUtil::Decrypt failed"); | ||
| 106 | + return output; | ||
| 107 | + } | ||
| 108 | + | ||
| 109 | + return output; | ||
| 110 | +} | ||
| 111 | + | ||
| 112 | +} // namespace IotcManagement | ||
| 113 | +} // namespace OHOS | ||
| @@ -0,0 +1,48 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | +namespace OHOS { | ||
| 23 | +namespace IotcManagement { | ||
| 24 | + | ||
| 25 | +class SecurityCipher { | ||
| 26 | +public: | ||
| 27 | + SecurityCipher(const std::vector<uint8_t>& sessionKey); | ||
| 28 | + ~SecurityCipher(); | ||
| 29 | + | ||
| 30 | + void Destroy(); | ||
| 31 | + | ||
| 32 | + std::vector<uint8_t> Encrypt(const std::vector<uint8_t>& data); | ||
| 33 | + | ||
| 34 | + std::vector<uint8_t> Decrypt(const std::vector<uint8_t>& data); | ||
| 35 | + | ||
| 36 | +private: | ||
| 37 | + static constexpr uint8_t VERSION_ZERO = 0; | ||
| 38 | + static constexpr uint32_t VERSION_LENGTH = 1; | ||
| 39 | + static constexpr uint32_t IV_LENGTH = 12; | ||
| 40 | + static constexpr uint32_t TAG_LENGTH = 16; | ||
| 41 | + | ||
| 42 | + std::vector<uint8_t> sessionKey_; | ||
| 43 | +}; | ||
| 44 | + | ||
| 45 | +} // namespace IotcManagement | ||
| 46 | +} // namespace OHOS | ||
| 47 | + | ||
| 48 | + | ||
| @@ -0,0 +1,121 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | +namespace OHOS { | ||
| 22 | +namespace IotcManagement { | ||
| 23 | + | ||
| 24 | +bool SecurityPin::Init(std::shared_ptr<IdentityInfo> localIdentityInfo, | ||
| 25 | + std::shared_ptr<MessageConfig> messageConfig) | ||
| 26 | +{ | ||
| 27 | + IOTC_LOGI("SecurityPin::Init"); | ||
| 28 | + if (!localIdentityInfo || !IdentityInfo::IsValid(localIdentityInfo.get())) { | ||
| 29 | + IOTC_LOGE("SecurityPin::Init localIdentityInfo is invalid"); | ||
| 30 | + return false; | ||
| 31 | + } | ||
| 32 | + if (messageConfig == nullptr) { | ||
| 33 | + IOTC_LOGE("SecurityPin::Init messageConfig is null"); | ||
| 34 | + return false; | ||
| 35 | + } | ||
| 36 | + return SecurityAdapter::GetInstance().Init(localIdentityInfo, messageConfig); | ||
| 37 | +} | ||
| 38 | + | ||
| 39 | +std::string SecurityPin::NegotiateSpeke(const std::string& pinCode, const std::string& deviceId, | ||
| 40 | + int32_t spekeType, std::shared_ptr<SpekeNegotiateCallback> callback, | ||
| 41 | + uint32_t protocolVersion) | ||
| 42 | +{ | ||
| 43 | + IOTC_LOGI("SecurityPin::NegotiateSpeke spekeType=%{public}d ver=%{public}u", spekeType, protocolVersion); | ||
| 44 | + if (!callback) { | ||
| 45 | + IOTC_LOGE("SecurityPin::NegotiateSpeke callback is null"); | ||
| 46 | + return ""; | ||
| 47 | + } | ||
| 48 | + | ||
| 49 | + if (pinCode.empty()) { | ||
| 50 | + IOTC_LOGE("SecurityPin::NegotiateSpeke pinCode is empty"); | ||
| 51 | + callback->OnFailure(ReturnCode::INVALID_PARAMETERS, "pinCode is empty"); | ||
| 52 | + return ""; | ||
| 53 | + } | ||
| 54 | + | ||
| 55 | + if (deviceId.empty()) { | ||
| 56 | + IOTC_LOGE("SecurityPin::NegotiateSpeke deviceId is empty"); | ||
| 57 | + callback->OnFailure(ReturnCode::INVALID_PARAMETERS, "deviceId is empty"); | ||
| 58 | + return ""; | ||
| 59 | + } | ||
| 60 | + | ||
| 61 | + std::string sessionId; | ||
| 62 | + if (spekeType == SPEKE_TYPE_SECURITY) { | ||
| 63 | + IdentityInfo peerIdentityInfo(deviceId, IdentityType::DEVICE); | ||
| 64 | + sessionId = SecurityAdapter::GetInstance().ClientNegotiateSpeke(pinCode, &peerIdentityInfo, | ||
| 65 | + callback, protocolVersion); | ||
| 66 | + } else { | ||
| 67 | + IOTC_LOGE("SecurityPin::NegotiateSpeke spekeType is err: %{public}d", spekeType); | ||
| 68 | + return ""; | ||
| 69 | + } | ||
| 70 | + | ||
| 71 | + IOTC_LOGI("SecurityPin::NegotiateSpeke sessionId=%{public}s", sessionId.c_str()); | ||
| 72 | + return sessionId; | ||
| 73 | +} | ||
| 74 | + | ||
| 75 | +void SecurityPin::ReceivedMsg(const std::string& message, IdentityInfo* peerInfo, int32_t spekeType, | ||
| 76 | + uint32_t protocolVersion) | ||
| 77 | +{ | ||
| 78 | + IOTC_LOGI("SecurityPin::ReceivedMsg spekeType=%{public}d ver=%{public}u", spekeType, protocolVersion); | ||
| 79 | + if (message.empty()) { | ||
| 80 | + IOTC_LOGE("SecurityPin::ReceivedMsg message is empty"); | ||
| 81 | + return; | ||
| 82 | + } | ||
| 83 | + if (!IdentityInfo::IsValid(peerInfo)) { | ||
| 84 | + IOTC_LOGE("SecurityPin::ReceivedMsg peerInfo is invalid"); | ||
| 85 | + return; | ||
| 86 | + } | ||
| 87 | + if (spekeType == SPEKE_TYPE_SECURITY) { | ||
| 88 | + SecurityAdapter::GetInstance().ProcessReceivedMsg(message, peerInfo, protocolVersion); | ||
| 89 | + } else { | ||
| 90 | + IOTC_LOGE("SecurityPin::ReceivedMsg spekeType is err: %{public}d", spekeType); | ||
| 91 | + } | ||
| 92 | +} | ||
| 93 | + | ||
| 94 | +bool SecurityPin::CancelRequest(const std::string& sessionId, int32_t spekeType) | ||
| 95 | +{ | ||
| 96 | + IOTC_LOGI("SecurityPin::CancelRequest spekeType=%{public}d", spekeType); | ||
| 97 | + if (sessionId.empty()) { | ||
| 98 | + IOTC_LOGE("SecurityPin::CancelRequest sessionId is empty"); | ||
| 99 | + return false; | ||
| 100 | + } | ||
| 101 | + if (spekeType == SPEKE_TYPE_SECURITY) { | ||
| 102 | + return SecurityAdapter::GetInstance().CancelRequest(sessionId); | ||
| 103 | + } | ||
| 104 | + IOTC_LOGE("SecurityPin::CancelRequest spekeType is err: %{public}d", spekeType); | ||
| 105 | + return false; | ||
| 106 | +} | ||
| 107 | + | ||
| 108 | +void SecurityPin::CleanMemory() | ||
| 109 | +{ | ||
| 110 | + IOTC_LOGI("SecurityPin::CleanMemory"); | ||
| 111 | + SecurityAdapter::GetInstance().Clear(); | ||
| 112 | +} | ||
| 113 | + | ||
| 114 | +void SecurityPin::Destroy() | ||
| 115 | +{ | ||
| 116 | + IOTC_LOGI("SecurityPin::Destroy"); | ||
| 117 | + SecurityAdapter::GetInstance().Destroy(); | ||
| 118 | +} | ||
| 119 | + | ||
| 120 | +} // namespace IotcManagement | ||
| 121 | +} // namespace OHOS | ||
| @@ -0,0 +1,91 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | + | ||
| 26 | + | ||
| 27 | + | ||
| 28 | +namespace OHOS { | ||
| 29 | +namespace IotcManagement { | ||
| 30 | + | ||
| 31 | +class SecurityPin { | ||
| 32 | +public: | ||
| 33 | + static constexpr int32_t SPEKE_TYPE_SECURITY = 0; | ||
| 34 | + static constexpr int32_t SPEKE_TYPE_HICHAIN = 1; | ||
| 35 | + | ||
| 36 | + /** | ||
| 37 | + * 初始化方法 | ||
| 38 | + * | ||
| 39 | + * @param localIdentityInfo 用户信息 | ||
| 40 | + * @param messageConfig 消息发送参数配置 | ||
| 41 | + */ | ||
| 42 | + static bool Init(std::shared_ptr<IdentityInfo> localIdentityInfo, | ||
| 43 | + std::shared_ptr<MessageConfig> messageConfig); | ||
| 44 | + | ||
| 45 | + /** | ||
| 46 | + * speke协商 | ||
| 47 | + * | ||
| 48 | + * @param pinCode PIN码 | ||
| 49 | + * @param deviceId 对端设备ID | ||
| 50 | + * @param spekeType speke类型 | ||
| 51 | + * @param callback 回调方法 | ||
| 52 | + * @return sessionId 会话ID,用于协商过程中断 | ||
| 53 | + */ | ||
| 54 | +static std::string NegotiateSpeke(const std::string& pinCode, const std::string& deviceId, | ||
| 55 | + int32_t spekeType, std::shared_ptr<SpekeNegotiateCallback> callback, | ||
| 56 | + uint32_t protocolVersion = CommonConstants::PROTOCOL_VERSION_V1); | ||
| 57 | + | ||
| 58 | + /** | ||
| 59 | + * 透传消息接口 | ||
| 60 | + * | ||
| 61 | + * @param message 对端消息内容 | ||
| 62 | + * @param peerInfo 对端身份信息 | ||
| 63 | + * @parsm spekeType speke类型 | ||
| 64 | + */ | ||
| 65 | + static void ReceivedMsg(const std::string& message, IdentityInfo* peerInfo, int32_t spekeType, | ||
| 66 | + uint32_t protocolVersion = CommonConstants::PROTOCOL_VERSION_V1); | ||
| 67 | + | ||
| 68 | + /** | ||
| 69 | + * 取消操作 | ||
| 70 | + * | ||
| 71 | + * @param sessionId 会话Id | ||
| 72 | + * @param spekeType speke类型 | ||
| 73 | + * @return 取消结果 | ||
| 74 | + */ | ||
| 75 | + static bool CancelRequest(const std::string& sessionId, int32_t spekeType); | ||
| 76 | + | ||
| 77 | + /** | ||
| 78 | + * 退出App时清理内存 | ||
| 79 | + */ | ||
| 80 | + static void CleanMemory(); | ||
| 81 | + | ||
| 82 | + /** | ||
| 83 | + * 用于退出注销账号 | ||
| 84 | + */ | ||
| 85 | + static void Destroy(); | ||
| 86 | +}; | ||
| 87 | + | ||
| 88 | +} // namespace IotcManagement | ||
| 89 | +} // namespace OHOS | ||
| 90 | + | ||
| 91 | + | ||
| @@ -0,0 +1,312 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | +namespace OHOS { | ||
| 26 | +namespace IotcManagement { | ||
| 27 | + | ||
| 28 | +SecuritySessionManager::SecuritySessionManager(std::shared_ptr<CoapSessionEntity> entity, SecurityType type, | ||
| 29 | + uint32_t sessionLen) | ||
| 30 | + : mType_(type) | ||
| 31 | + , mIvLenGcm_(12) | ||
| 32 | + , mSessionLen_(sessionLen == 0 ? DEFAULT_SESSION_LEN : sessionLen) | ||
| 33 | +{ | ||
| 34 | + mSessionId_.resize(mSessionLen_, 0); | ||
| 35 | + mEntity_ = entity; | ||
| 36 | + mPskKey_.resize(DIGEST_LEN / 2, 0); | ||
| 37 | + mHmacDigest_.resize(DIGEST_LEN, 0); | ||
| 38 | +} | ||
| 39 | + | ||
| 40 | +bool SecuritySessionManager::Init() | ||
| 41 | +{ | ||
| 42 | + if (!mEntity_) { | ||
| 43 | + IOTC_LOGE("SecuritySessionManager::Init entity is null"); | ||
| 44 | + return false; | ||
| 45 | + } | ||
| 46 | + | ||
| 47 | + if (E2eSecurityApi::IsSupportHiChain(mEntity_->GetDeviceVersion())) { | ||
| 48 | + return GetKeyByHiChain(mEntity_); | ||
| 49 | + } | ||
| 50 | + return GenerateKeyByAuthCode(mEntity_); | ||
| 51 | +} | ||
| 52 | + | ||
| 53 | +std::vector<uint8_t> SecuritySessionManager::Hmac(const std::vector<uint8_t>& data) | ||
| 54 | +{ | ||
| 55 | + if (mHmacDigest_.empty()) { | ||
| 56 | + IOTC_LOGW("SecuritySessionManager::Hmac digest is null!"); | ||
| 57 | + return {}; | ||
| 58 | + } | ||
| 59 | + | ||
| 60 | + auto mac = CryptoKdf::HmacSha256(mHmacDigest_, data); | ||
| 61 | + if (mac.empty()) { | ||
| 62 | + IOTC_LOGW("SecuritySessionManager::Hmac mac is null!"); | ||
| 63 | + return {}; | ||
| 64 | + } | ||
| 65 | + return mac; | ||
| 66 | +} | ||
| 67 | + | ||
| 68 | +bool SecuritySessionManager::GenerateKeyByAuthCode(std::shared_ptr<CoapSessionEntity> entity) | ||
| 69 | +{ | ||
| 70 | + if (entity == nullptr) { | ||
| 71 | + IOTC_LOGW("SecuritySessionManager::GenerateKeyByAuthCode entity is null"); | ||
| 72 | + return false; | ||
| 73 | + } | ||
| 74 | + | ||
| 75 | + std::string authCode = entity->GetAuthCode(); | ||
| 76 | + if (authCode.empty()) { | ||
| 77 | + IOTC_LOGW("SecuritySessionManager::GenerateKeyByAuthCode authCode is empty!"); | ||
| 78 | + return false; | ||
| 79 | + } | ||
| 80 | + | ||
| 81 | + if (mType_ == SecurityType::TYPE_GCM && !entity->GetSessionId().empty() && | ||
| 82 | + entity->GetSessionId().length() == mSessionLen_ * 2) { | ||
| 83 | + IOTC_LOGI("SecuritySessionManager::GenerateKeyByAuthCode init security SessionId."); | ||
| 84 | + auto tempSessionId = CommonUtil::ToBytesFromHex(entity->GetSessionId()); | ||
| 85 | + if (tempSessionId.size() >= mSessionLen_) { | ||
| 86 | + for (size_t i = 0; i < mSessionLen_; ++i) { | ||
| 87 | + mSessionId_[i] = tempSessionId[i]; | ||
| 88 | + } | ||
| 89 | + } | ||
| 90 | + } | ||
| 91 | + | ||
| 92 | + auto salt = GenerateSalt(entity); | ||
| 93 | + if (salt.empty()) { | ||
| 94 | + IOTC_LOGW("SecuritySessionManager::GenerateKeyByAuthCode salt is null!"); | ||
| 95 | + return false; | ||
| 96 | + } | ||
| 97 | + | ||
| 98 | + auto pwd = CommonUtil::ToBytesFromHex(authCode); | ||
| 99 | + if (pwd.empty()) { | ||
| 100 | + IOTC_LOGW("SecuritySessionManager::GenerateKeyByAuthCode pwd is null!"); | ||
| 101 | + return false; | ||
| 102 | + } | ||
| 103 | + | ||
| 104 | + auto digests = CryptoKdf::Pbkdf2HmacSha256(pwd, salt, COAP_SECURITY_DERIVE_ITERATOR_COUNT, | ||
| 105 | + CBC_SECURITY_DERIVE_KEY); | ||
| 106 | + for (auto& b : pwd) { | ||
| 107 | + b = 0; | ||
| 108 | + } | ||
| 109 | + pwd.clear(); | ||
| 110 | + | ||
| 111 | + if (digests.size() != DIGEST_LEN) { | ||
| 112 | + IOTC_LOGW("SecuritySessionManager::GenerateKeyByAuthCode get digest error!"); | ||
| 113 | + return false; | ||
| 114 | + } | ||
| 115 | + | ||
| 116 | + for (size_t i = 0; i < mPskKey_.size(); ++i) { | ||
| 117 | + mPskKey_[i] = digests[i]; | ||
| 118 | + } | ||
| 119 | + | ||
| 120 | + mHmacDigest_ = CryptoKdf::Pbkdf2HmacSha256(mPskKey_, salt, COAP_SECURITY_DERIVE_ITERATOR_COUNT, | ||
| 121 | + CBC_SECURITY_DERIVE_KEY); | ||
| 122 | + if (mHmacDigest_.empty()) { | ||
| 123 | + IOTC_LOGW("SecuritySessionManager::GenerateKeyByAuthCode hmac digest is null!"); | ||
| 124 | + return false; | ||
| 125 | + } | ||
| 126 | + | ||
| 127 | + IOTC_LOGI("SecuritySessionManager::GenerateKeyByAuthCode success"); | ||
| 128 | + return true; | ||
| 129 | +} | ||
| 130 | + | ||
| 131 | +std::vector<uint8_t> SecuritySessionManager::GenerateSalt(std::shared_ptr<CoapSessionEntity> entity) | ||
| 132 | +{ | ||
| 133 | + std::vector<uint8_t> salt; | ||
| 134 | + if (entity == nullptr) { | ||
| 135 | + IOTC_LOGW("SecuritySessionManager::GenerateSalt entity is null"); | ||
| 136 | + return salt; | ||
| 137 | + } | ||
| 138 | + | ||
| 139 | + std::string sn1 = entity->GetRandomNumberOne(); | ||
| 140 | + std::string sn2 = entity->GetRandomNumberTwo(); | ||
| 141 | + | ||
| 142 | + if (sn1.empty() || sn1.length() != SN_LEN || sn2.empty() || sn2.length() != SN_LEN) { | ||
| 143 | + IOTC_LOGW("SecuritySessionManager::GenerateSalt sn1 or sn2 is not right!"); | ||
| 144 | + return salt; | ||
| 145 | + } | ||
| 146 | + | ||
| 147 | + auto bytesSn1 = CommonUtil::ToBytesFromHex(sn1); | ||
| 148 | + auto bytesSn2 = CommonUtil::ToBytesFromHex(sn2); | ||
| 149 | + | ||
| 150 | + if (bytesSn1.empty() || bytesSn2.empty()) { | ||
| 151 | + IOTC_LOGW("SecuritySessionManager::GenerateSalt bytesSn1 or bytesSn2 is null!"); | ||
| 152 | + return salt; | ||
| 153 | + } | ||
| 154 | + | ||
| 155 | + salt.reserve(bytesSn1.size() + bytesSn2.size()); | ||
| 156 | + salt.insert(salt.end(), bytesSn1.begin(), bytesSn1.end()); | ||
| 157 | + salt.insert(salt.end(), bytesSn2.begin(), bytesSn2.end()); | ||
| 158 | + | ||
| 159 | + return salt; | ||
| 160 | +} | ||
| 161 | + | ||
| 162 | +bool SecuritySessionManager::GetKeyByHiChain(std::shared_ptr<CoapSessionEntity> entity) | ||
| 163 | +{ | ||
| 164 | + if (entity == nullptr) { | ||
| 165 | + IOTC_LOGW("SecuritySessionManager::GetKeyByHiChain entity is null"); | ||
| 166 | + return false; | ||
| 167 | + } | ||
| 168 | + | ||
| 169 | + if (mType_ == SecurityType::TYPE_GCM && !entity->GetSessionId().empty() && | ||
| 170 | + entity->GetSessionId().length() == mSessionLen_ * 2) { | ||
| 171 | + IOTC_LOGI("SecuritySessionManager::GetKeyByHiChain init security SessionId."); | ||
| 172 | + auto tempSessionId = CommonUtil::ToBytesFromHex(entity->GetSessionId()); | ||
| 173 | + if (tempSessionId.size() >= mSessionLen_) { | ||
| 174 | + for (size_t i = 0; i < mSessionLen_; ++i) { | ||
| 175 | + mSessionId_[i] = tempSessionId[i]; | ||
| 176 | + } | ||
| 177 | + } | ||
| 178 | + } | ||
| 179 | + | ||
| 180 | + std::string saltString = entity->GetRandomNumberOne(); | ||
| 181 | + auto salt = CommonUtil::ToBytesFromHex(saltString); | ||
| 182 | + if (salt.size() != SN_LEN) { | ||
| 183 | + IOTC_LOGW("SecuritySessionManager::GetKeyByHiChain salt is error!"); | ||
| 184 | + return false; | ||
| 185 | + } | ||
| 186 | + | ||
| 187 | + auto secret = entity->GetHichainSecret(); | ||
| 188 | + if (secret.empty() || secret.size() != DIGEST_LEN) { | ||
| 189 | + IOTC_LOGW("SecuritySessionManager::GetKeyByHiChain secret is error!"); | ||
| 190 | + return false; | ||
| 191 | + } | ||
| 192 | + | ||
| 193 | + for (size_t i = 0; i < mPskKey_.size(); ++i) { | ||
| 194 | + mPskKey_[i] = secret[i]; | ||
| 195 | + } | ||
| 196 | + | ||
| 197 | + auto ak16Start = secret.begin() + (secret.size() / 2); | ||
| 198 | + std::vector<uint8_t> ak16(ak16Start, secret.end()); | ||
| 199 | + mHmacDigest_ = CryptoKdf::Pbkdf2HmacSha256(ak16, salt, COAP_SECURITY_DERIVE_ITERATOR_COUNT, | ||
| 200 | + CBC_SECURITY_DERIVE_KEY); | ||
| 201 | + if (mHmacDigest_.empty() || mHmacDigest_.size() != DIGEST_LEN) { | ||
| 202 | + IOTC_LOGW("SecuritySessionManager::GetKeyByHiChain hmac digest invalid"); | ||
| 203 | + return false; | ||
| 204 | + } | ||
| 205 | + | ||
| 206 | + IOTC_LOGI("SecuritySessionManager::GetKeyByHiChain success"); | ||
| 207 | + return true; | ||
| 208 | +} | ||
| 209 | + | ||
| 210 | +std::vector<uint8_t> SecuritySessionManager::EncryptDataByGcm(const std::string& data, const std::string& aad) | ||
| 211 | +{ | ||
| 212 | + std::vector<uint8_t> result; | ||
| 213 | + if (mType_ != SecurityType::TYPE_GCM) { | ||
| 214 | + IOTC_LOGW("SecuritySessionManager::EncryptDataByGcm type is not GCM!"); | ||
| 215 | + return result; | ||
| 216 | + } | ||
| 217 | + | ||
| 218 | + if (mPskKey_.empty()) { | ||
| 219 | + IOTC_LOGW("SecuritySessionManager::EncryptDataByGcm mPskKey is null!"); | ||
| 220 | + return result; | ||
| 221 | + } | ||
| 222 | + | ||
| 223 | + auto byteContent = CommonUtil::StringToUint8Array(data); | ||
| 224 | + if (byteContent.empty()) { | ||
| 225 | + IOTC_LOGW("SecuritySessionManager::EncryptDataByGcm byteContent is null"); | ||
| 226 | + return result; | ||
| 227 | + } | ||
| 228 | + | ||
| 229 | + auto byteAad = CommonUtil::StringToUint8Array(aad); | ||
| 230 | + if (byteAad.empty()) { | ||
| 231 | + IOTC_LOGW("SecuritySessionManager::EncryptDataByGcm byteAad is null"); | ||
| 232 | + return result; | ||
| 233 | + } | ||
| 234 | + | ||
| 235 | + auto iv = CryptoRandom::GenerateRandom(mIvLenGcm_); | ||
| 236 | + if (iv.empty()) { | ||
| 237 | + IOTC_LOGW("SecuritySessionManager::EncryptDataByGcm generate random failed"); | ||
| 238 | + return result; | ||
| 239 | + } | ||
| 240 | + | ||
| 241 | + auto encryptResult = AesGcmUtil::Encrypt(byteContent, mPskKey_, iv, byteAad); | ||
| 242 | + if (encryptResult.empty()) { | ||
| 243 | + IOTC_LOGW("SecuritySessionManager::EncryptDataByGcm encrypt failed"); | ||
| 244 | + return result; | ||
| 245 | + } | ||
| 246 | + | ||
| 247 | + result.resize(mIvLenGcm_ + encryptResult.size() + mSessionLen_); | ||
| 248 | + for (size_t i = 0; i < mIvLenGcm_; ++i) { | ||
| 249 | + result[i] = iv[i]; | ||
| 250 | + } | ||
| 251 | + for (size_t i = 0; i < encryptResult.size(); ++i) { | ||
| 252 | + result[mIvLenGcm_ + i] = encryptResult[i]; | ||
| 253 | + } | ||
| 254 | + for (size_t i = 0; i < mSessionLen_; ++i) { | ||
| 255 | + result[mIvLenGcm_ + encryptResult.size() + i] = mSessionId_[i]; | ||
| 256 | + } | ||
| 257 | + | ||
| 258 | + return result; | ||
| 259 | +} | ||
| 260 | + | ||
| 261 | +std::string SecuritySessionManager::DecryptDataByGcm(const std::vector<uint8_t>& data, const std::string& aad) | ||
| 262 | +{ | ||
| 263 | + std::string emptyResult; | ||
| 264 | + if (mType_ != SecurityType::TYPE_GCM) { | ||
| 265 | + IOTC_LOGW("SecuritySessionManager::DecryptDataByGcm type is not GCM!"); | ||
| 266 | + return emptyResult; | ||
| 267 | + } | ||
| 268 | + | ||
| 269 | + size_t minLength = mIvLenGcm_ + mSessionLen_; | ||
| 270 | + if (data.size() < minLength) { | ||
| 271 | + IOTC_LOGW("SecuritySessionManager::DecryptDataByGcm data length error!"); | ||
| 272 | + return emptyResult; | ||
| 273 | + } | ||
| 274 | + | ||
| 275 | + if (mPskKey_.empty()) { | ||
| 276 | + IOTC_LOGW("SecuritySessionManager::DecryptDataByGcm mPskKey is null!"); | ||
| 277 | + return emptyResult; | ||
| 278 | + } | ||
| 279 | + | ||
| 280 | + std::vector<uint8_t> iv(data.begin(), data.begin() + mIvLenGcm_); | ||
| 281 | + std::vector<uint8_t> cipherAndTag(data.begin() + mIvLenGcm_, data.end() - mSessionLen_); | ||
| 282 | + std::vector<uint8_t> sessionBytes(data.end() - mSessionLen_, data.end()); | ||
| 283 | + | ||
| 284 | + if (mSessionId_ != sessionBytes) { | ||
| 285 | + IOTC_LOGW("SecuritySessionManager::DecryptDataByGcm session not equal."); | ||
| 286 | + return emptyResult; | ||
| 287 | + } | ||
| 288 | + | ||
| 289 | + auto byteAad = CommonUtil::StringToUint8Array(aad); | ||
| 290 | + if (byteAad.empty()) { | ||
| 291 | + IOTC_LOGW("SecuritySessionManager::DecryptDataByGcm byteAad is null"); | ||
| 292 | + return emptyResult; | ||
| 293 | + } | ||
| 294 | + | ||
| 295 | + auto decryptResult = AesGcmUtil::Decrypt(cipherAndTag, mPskKey_, iv, byteAad); | ||
| 296 | + if (decryptResult.empty()) { | ||
| 297 | + IOTC_LOGW("SecuritySessionManager::DecryptDataByGcm decrypt failed"); | ||
| 298 | + return emptyResult; | ||
| 299 | + } | ||
| 300 | + | ||
| 301 | + return std::string(decryptResult.begin(), decryptResult.end()); | ||
| 302 | +} | ||
| 303 | + | ||
| 304 | +void SecuritySessionManager::Clear() | ||
| 305 | +{ | ||
| 306 | + IOTC_LOGI("SecuritySessionManager::Clear in"); | ||
| 307 | + mPskKey_.clear(); | ||
| 308 | + mHmacDigest_.clear(); | ||
| 309 | +} | ||
| 310 | + | ||
| 311 | +} // namespace IotcManagement | ||
| 312 | +} // namespace OHOS | ||
| @@ -0,0 +1,78 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | + | ||
| 26 | +namespace OHOS { | ||
| 27 | +namespace IotcManagement { | ||
| 28 | + | ||
| 29 | +enum class SecurityType { | ||
| 30 | + TYPE_CBC, | ||
| 31 | + TYPE_GCM | ||
| 32 | +}; | ||
| 33 | + | ||
| 34 | +class SecuritySessionManager : public SpekeMessageHmacor { | ||
| 35 | +public: | ||
| 36 | + static constexpr uint32_t DEFAULT_SESSION_LEN = 8; | ||
| 37 | + | ||
| 38 | + SecuritySessionManager(std::shared_ptr<CoapSessionEntity> entity, SecurityType type, | ||
| 39 | + uint32_t sessionLen = DEFAULT_SESSION_LEN); | ||
| 40 | + ~SecuritySessionManager() = default; | ||
| 41 | + | ||
| 42 | + bool Init(); | ||
| 43 | + | ||
| 44 | + std::vector<uint8_t> Hmac(const std::vector<uint8_t>& data) override; | ||
| 45 | + | ||
| 46 | + void Clear() override; | ||
| 47 | + | ||
| 48 | + std::vector<uint8_t> EncryptDataByGcm(const std::string& data, const std::string& aad); | ||
| 49 | + | ||
| 50 | + std::string DecryptDataByGcm(const std::vector<uint8_t>& data, const std::string& aad); | ||
| 51 | + | ||
| 52 | +protected: | ||
| 53 | + bool GenerateKeyByAuthCode(std::shared_ptr<CoapSessionEntity> entity); | ||
| 54 | + | ||
| 55 | + std::vector<uint8_t> GenerateSalt(std::shared_ptr<CoapSessionEntity> entity); | ||
| 56 | + | ||
| 57 | + bool GetKeyByHiChain(std::shared_ptr<CoapSessionEntity> entity); | ||
| 58 | + | ||
| 59 | + SecurityType mType_; | ||
| 60 | + std::vector<uint8_t> mSessionId_; | ||
| 61 | + std::shared_ptr<CoapSessionEntity> mEntity_; | ||
| 62 | + std::vector<uint8_t> mPskKey_; | ||
| 63 | + std::vector<uint8_t> mHmacDigest_; | ||
| 64 | + uint32_t mIvLenGcm_; | ||
| 65 | + uint32_t mSessionLen_; | ||
| 66 | + | ||
| 67 | + static constexpr uint32_t SN_LEN = 16; | ||
| 68 | + static constexpr uint32_t CBC_SECURITY_DERIVE_KEY = 32; | ||
| 69 | + static constexpr uint32_t COAP_SECURITY_DERIVE_ITERATOR_COUNT = 1; | ||
| 70 | + static constexpr uint32_t DIGEST_LEN = 32; | ||
| 71 | + static constexpr int32_t DEFAULT_POSITION = 0; | ||
| 72 | + static constexpr int32_t DEFAULT_SRC_POSITION = 0; | ||
| 73 | +}; | ||
| 74 | + | ||
| 75 | +} // namespace IotcManagement | ||
| 76 | +} // namespace OHOS | ||
| 77 | + | ||
| 78 | + | ||
| @@ -0,0 +1,351 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | + | ||
| 26 | + | ||
| 27 | + | ||
| 28 | +namespace OHOS { | ||
| 29 | +namespace IotcManagement { | ||
| 30 | + | ||
| 31 | +const std::string SpekeUtils::MOD_POW_384 = | ||
| 32 | + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74" | ||
| 33 | + "020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437" | ||
| 34 | + "4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" | ||
| 35 | + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF05" | ||
| 36 | + "98DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB" | ||
| 37 | + "9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" | ||
| 38 | + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718" | ||
| 39 | + "3995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33" | ||
| 40 | + "A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" | ||
| 41 | + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864" | ||
| 42 | + "D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E2" | ||
| 43 | + "08E24FA074E5AB3143DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF"; | ||
| 44 | + | ||
| 45 | +const std::string SpekeUtils::MOD_POW_256 = | ||
| 46 | + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74" | ||
| 47 | + "020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437" | ||
| 48 | + "4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" | ||
| 49 | + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF05" | ||
| 50 | + "98DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB" | ||
| 51 | + "9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" | ||
| 52 | + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718" | ||
| 53 | + "3995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF"; | ||
| 54 | + | ||
| 55 | +SpekeUtils::SpekeUtils() | ||
| 56 | + : pakeType_(SpekeType::SPEKE_384) | ||
| 57 | +{ | ||
| 58 | +} | ||
| 59 | + | ||
| 60 | +SpekeUtils::~SpekeUtils() | ||
| 61 | +{ | ||
| 62 | +} | ||
| 63 | + | ||
| 64 | +void SpekeUtils::SetSpekeType(SpekeType type) | ||
| 65 | +{ | ||
| 66 | + pakeType_ = type; | ||
| 67 | +} | ||
| 68 | + | ||
| 69 | +SpekeType SpekeUtils::GetSpekeType() const | ||
| 70 | +{ | ||
| 71 | + return pakeType_; | ||
| 72 | +} | ||
| 73 | + | ||
| 74 | +int32_t SpekeUtils::GetPrivateParamLen() | ||
| 75 | +{ | ||
| 76 | + if (pakeType_ == SpekeType::SPEKE_EC) { | ||
| 77 | + return static_cast<int32_t>(GlobalParams::PAKE_PUBLIC_BYTE_LEN_EC); | ||
| 78 | + } | ||
| 79 | + if (pakeType_ == SpekeType::SPEKE_256) { | ||
| 80 | + return GlobalParams::SPEKE_SECRET_LENGTH_256_MOD; | ||
| 81 | + } | ||
| 82 | + return GlobalParams::SPEKE_SECRET_LENGTH; | ||
| 83 | +} | ||
| 84 | + | ||
| 85 | +uint32_t SpekeUtils::GetDlPublicLength() const | ||
| 86 | +{ | ||
| 87 | + return (pakeType_ == SpekeType::SPEKE_256) | ||
| 88 | + ? GlobalParams::SPEKE_PUBLIC_LENGTH_256_MOD | ||
| 89 | + : GlobalParams::SPEKE_PUBLIC_LENGTH_384_MOD; | ||
| 90 | +} | ||
| 91 | + | ||
| 92 | +int32_t SpekeUtils::LoadModulus(IotcMpi& mpiN) const | ||
| 93 | +{ | ||
| 94 | + const std::string& nHex = (pakeType_ == SpekeType::SPEKE_384) ? MOD_POW_384 : MOD_POW_256; | ||
| 95 | + return mpiN.ReadString(GlobalParams::MPI_RADIX, nHex.c_str()); | ||
| 96 | +} | ||
| 97 | + | ||
| 98 | +std::vector<uint8_t> SpekeUtils::FormatMpiToFixedLength(IotcMpi& mpiResult, uint32_t targetLen) const | ||
| 99 | +{ | ||
| 100 | + if (targetLen == 0) { | ||
| 101 | + IOTC_LOGE("FormatMpiToFixedLength target length is zero"); | ||
| 102 | + return {}; | ||
| 103 | + } | ||
| 104 | + | ||
| 105 | + std::vector<uint8_t> output(targetLen, 0); | ||
| 106 | + if (mpiResult.ExportBinary(output.data(), targetLen) != 0) { | ||
| 107 | + IOTC_LOGE("FormatMpiToFixedLength export mpi failed"); | ||
| 108 | + return {}; | ||
| 109 | + } | ||
| 110 | + return output; | ||
| 111 | +} | ||
| 112 | + | ||
| 113 | +std::vector<uint8_t> SpekeUtils::ComputeSharedBaseEc(const std::vector<uint8_t>& secret) | ||
| 114 | +{ | ||
| 115 | + if (secret.size() != GlobalParams::PAKE_SECRET_LENGTH_EC) { | ||
| 116 | + IOTC_LOGW("SpekeUtils::ComputeSharedBaseEc secret size=%{public}zu invalid", | ||
| 117 | + secret.size()); | ||
| 118 | + return {}; | ||
| 119 | + } | ||
| 120 | + /* | ||
| 121 | + * EC SPEKE:base.x 必须以 BE 字节返回,详见 HashToCurveX25519::HashToPoint | ||
| 122 | + * 与 MpiToBytes32Be 的注释;进入 IotcX25519::ComputeSharedSecret 后会经 | ||
| 123 | + * "SwapEndian + read_binary(BE)" 链路,与 ComputeSharedKeyEc 接收 LE 线缆 | ||
| 124 | + * 字节时在同一约定下,保证 X25519 DH 对称性。 | ||
| 125 | + */ | ||
| 126 | + return HashToCurveX25519::HashToPoint(secret); | ||
| 127 | +} | ||
| 128 | + | ||
| 129 | +std::vector<uint8_t> SpekeUtils::ComputeSharedBaseDl(const std::vector<uint8_t>& secret) | ||
| 130 | +{ | ||
| 131 | + IotcMpi mpiSecret; | ||
| 132 | + IotcMpi mpiExp; | ||
| 133 | + IotcMpi mpiN; | ||
| 134 | + IotcMpi mpiResult; | ||
| 135 | + | ||
| 136 | + if (mpiSecret.ImportBinary(secret.data(), secret.size()) != 0) { | ||
| 137 | + IOTC_LOGE("ComputeSharedBaseDl import secret failed"); | ||
| 138 | + return {}; | ||
| 139 | + } | ||
| 140 | + if (mpiExp.ReadString(GlobalParams::MPI_RADIX, "2") != 0) { | ||
| 141 | + IOTC_LOGE("ComputeSharedBaseDl read exp failed"); | ||
| 142 | + return {}; | ||
| 143 | + } | ||
| 144 | + if (LoadModulus(mpiN) != 0) { | ||
| 145 | + IOTC_LOGE("ComputeSharedBaseDl read modulus failed"); | ||
| 146 | + return {}; | ||
| 147 | + } | ||
| 148 | + if (mpiResult.Exp(&mpiSecret, &mpiExp, &mpiN) != 0) { | ||
| 149 | + IOTC_LOGE("ComputeSharedBaseDl exp failed"); | ||
| 150 | + return {}; | ||
| 151 | + } | ||
| 152 | + | ||
| 153 | + return FormatMpiToFixedLength(mpiResult, GetDlPublicLength()); | ||
| 154 | +} | ||
| 155 | + | ||
| 156 | +std::vector<uint8_t> SpekeUtils::ComputeSharedBase(const std::vector<uint8_t>& secret) | ||
| 157 | +{ | ||
| 158 | + if (secret.empty()) { | ||
| 159 | + IOTC_LOGW("SpekeUtils::ComputeSharedBase secret is empty"); | ||
| 160 | + return {}; | ||
| 161 | + } | ||
| 162 | + if (pakeType_ == SpekeType::SPEKE_EC) { | ||
| 163 | + return ComputeSharedBaseEc(secret); | ||
| 164 | + } | ||
| 165 | + return ComputeSharedBaseDl(secret); | ||
| 166 | +} | ||
| 167 | + | ||
| 168 | +std::vector<uint8_t> SpekeUtils::ComputePublicParameterEc(const std::vector<uint8_t>& base, | ||
| 169 | + const std::vector<uint8_t>& privateParam) | ||
| 170 | +{ | ||
| 171 | + /* | ||
| 172 | + * EC SPEKE:base 是 HashToCurveX25519::HashToPoint 输出的 BE 字节, | ||
| 173 | + * privateParam 是 IotcX25519::GeneratePrivateKey 输出的 LE 字节。 | ||
| 174 | + * 进入 IotcX25519::ComputeSharedSecret 后统一走 SwapEndian + read_binary(BE) | ||
| 175 | + * 链路:BE 输入得到 byte_reversed(数值) 的 MPI,LE 输入得到数值本身的 MPI。 | ||
| 176 | + * 本路径与 ComputeSharedKeyEc 共用同一约定,X25519 DH 对称性才能成立。 | ||
| 177 | + */ | ||
| 178 | + return IotcX25519::ComputeSharedSecret(privateParam, base); | ||
| 179 | +} | ||
| 180 | + | ||
| 181 | +std::vector<uint8_t> SpekeUtils::ComputePublicParameterDl(const std::vector<uint8_t>& base, | ||
| 182 | + const std::vector<uint8_t>& privateParam) | ||
| 183 | +{ | ||
| 184 | + IotcMpi mpiBase; | ||
| 185 | + IotcMpi mpiExp; | ||
| 186 | + IotcMpi mpiN; | ||
| 187 | + IotcMpi mpiResult; | ||
| 188 | + | ||
| 189 | + if (mpiBase.ImportBinary(base.data(), base.size()) != 0) { | ||
| 190 | + IOTC_LOGE("ComputePublicParameterDl import base failed"); | ||
| 191 | + return {}; | ||
| 192 | + } | ||
| 193 | + if (mpiExp.ImportBinary(privateParam.data(), privateParam.size()) != 0) { | ||
| 194 | + IOTC_LOGE("ComputePublicParameterDl import exp failed"); | ||
| 195 | + return {}; | ||
| 196 | + } | ||
| 197 | + if (LoadModulus(mpiN) != 0) { | ||
| 198 | + IOTC_LOGE("ComputePublicParameterDl read modulus failed"); | ||
| 199 | + return {}; | ||
| 200 | + } | ||
| 201 | + if (mpiResult.Exp(&mpiBase, &mpiExp, &mpiN) != 0) { | ||
| 202 | + IOTC_LOGE("ComputePublicParameterDl mod exp failed"); | ||
| 203 | + return {}; | ||
| 204 | + } | ||
| 205 | + | ||
| 206 | + return FormatMpiToFixedLength(mpiResult, GetDlPublicLength()); | ||
| 207 | +} | ||
| 208 | + | ||
| 209 | +std::vector<uint8_t> SpekeUtils::ComputePublicParameter(const std::vector<uint8_t>& base, | ||
| 210 | + const std::vector<uint8_t>& privateParam) | ||
| 211 | +{ | ||
| 212 | + if (base.empty() || privateParam.empty()) { | ||
| 213 | + IOTC_LOGW("SpekeUtils::ComputePublicParameter invalid param"); | ||
| 214 | + return {}; | ||
| 215 | + } | ||
| 216 | + if (pakeType_ == SpekeType::SPEKE_EC) { | ||
| 217 | + return ComputePublicParameterEc(base, privateParam); | ||
| 218 | + } | ||
| 219 | + return ComputePublicParameterDl(base, privateParam); | ||
| 220 | +} | ||
| 221 | + | ||
| 222 | +std::vector<uint8_t> SpekeUtils::ComputeSharedKeyEc(const std::vector<uint8_t>& selfPrivateParam, | ||
| 223 | + const std::vector<uint8_t>& peerPublicParam) | ||
| 224 | +{ | ||
| 225 | + /* | ||
| 226 | + * EC SPEKE:selfPrivateParam / peerPublicParam 都是 LE 字节(线缆格式)。 | ||
| 227 | + * 进入 IotcX25519::ComputeSharedSecret 后经 SwapEndian 转 BE 字节再 | ||
| 228 | + * read_binary(BE),得到 MPI = 数值本身。与 ComputePublicParameterEc 走同 | ||
| 229 | + * 一链路但语义对称,两侧一致即可保证 X25519 DH 对称性。 | ||
| 230 | + */ | ||
| 231 | + return IotcX25519::ComputeSharedSecret(selfPrivateParam, peerPublicParam); | ||
| 232 | +} | ||
| 233 | + | ||
| 234 | +std::vector<uint8_t> SpekeUtils::ComputeSharedKeyDl(const std::vector<uint8_t>& selfPrivateParam, | ||
| 235 | + const std::vector<uint8_t>& peerPublicParam) | ||
| 236 | +{ | ||
| 237 | + IotcMpi mpiBase; | ||
| 238 | + IotcMpi mpiExp; | ||
| 239 | + IotcMpi mpiN; | ||
| 240 | + IotcMpi mpiResult; | ||
| 241 | + | ||
| 242 | + if (mpiBase.ImportBinary(peerPublicParam.data(), peerPublicParam.size()) != 0) { | ||
| 243 | + IOTC_LOGE("ComputeSharedKeyDl import peer public param failed"); | ||
| 244 | + return {}; | ||
| 245 | + } | ||
| 246 | + if (mpiExp.ImportBinary(selfPrivateParam.data(), selfPrivateParam.size()) != 0) { | ||
| 247 | + IOTC_LOGE("ComputeSharedKeyDl import self private param failed"); | ||
| 248 | + return {}; | ||
| 249 | + } | ||
| 250 | + if (LoadModulus(mpiN) != 0) { | ||
| 251 | + IOTC_LOGE("ComputeSharedKeyDl read modulus failed"); | ||
| 252 | + return {}; | ||
| 253 | + } | ||
| 254 | + if (mpiResult.Exp(&mpiBase, &mpiExp, &mpiN) != 0) { | ||
| 255 | + IOTC_LOGE("ComputeSharedKeyDl mod exp failed"); | ||
| 256 | + return {}; | ||
| 257 | + } | ||
| 258 | + | ||
| 259 | + return FormatMpiToFixedLength(mpiResult, GetDlPublicLength()); | ||
| 260 | +} | ||
| 261 | + | ||
| 262 | +std::vector<uint8_t> SpekeUtils::ComputeSharedKey(const std::vector<uint8_t>& selfPrivateParam, | ||
| 263 | + const std::vector<uint8_t>& peerPublicParam) | ||
| 264 | +{ | ||
| 265 | + if (selfPrivateParam.empty() || peerPublicParam.empty()) { | ||
| 266 | + IOTC_LOGW("ComputeSharedKey invalid param"); | ||
| 267 | + return {}; | ||
| 268 | + } | ||
| 269 | + if (pakeType_ == SpekeType::SPEKE_EC) { | ||
| 270 | + return ComputeSharedKeyEc(selfPrivateParam, peerPublicParam); | ||
| 271 | + } | ||
| 272 | + return ComputeSharedKeyDl(selfPrivateParam, peerPublicParam); | ||
| 273 | +} | ||
| 274 | + | ||
| 275 | +std::vector<uint8_t> SpekeUtils::DeriveBaseSecretV2(const std::vector<uint8_t>& pin, | ||
| 276 | + const std::vector<uint8_t>& salt, uint32_t iterations) | ||
| 277 | +{ | ||
| 278 | + if (pin.empty() || salt.empty() || iterations == 0) { | ||
| 279 | + IOTC_LOGW("SpekeUtils::DeriveBaseSecretV2 invalid param"); | ||
| 280 | + return {}; | ||
| 281 | + } | ||
| 282 | + if (pakeType_ != SpekeType::SPEKE_EC) { | ||
| 283 | + IOTC_LOGW("SpekeUtils::DeriveBaseSecretV2 only EC path supported"); | ||
| 284 | + return {}; | ||
| 285 | + } | ||
| 286 | + | ||
| 287 | + std::vector<uint8_t> finalSalt; | ||
| 288 | + uint32_t baseInfoLen = (uint32_t)strlen(CommonConstants::BASE_INFO_V2); | ||
| 289 | + finalSalt.reserve(salt.size() + baseInfoLen); | ||
| 290 | + finalSalt.insert(finalSalt.end(), salt.begin(), salt.end()); | ||
| 291 | + finalSalt.insert(finalSalt.end(), CommonConstants::BASE_INFO_V2, | ||
| 292 | + CommonConstants::BASE_INFO_V2 + baseInfoLen); | ||
| 293 | + | ||
| 294 | + uint32_t keyLen = GlobalParams::PAKE_SECRET_LENGTH_EC; | ||
| 295 | + IotcPbkdf2HmacParam param {}; | ||
| 296 | + param.md = IotcMdType::IOTC_MD_SHA512; | ||
| 297 | + param.password = pin.data(); | ||
| 298 | + param.passwordLen = pin.size(); | ||
| 299 | + param.salt = finalSalt.data(); | ||
| 300 | + param.saltLen = finalSalt.size(); | ||
| 301 | + param.iterCount = iterations; | ||
| 302 | + | ||
| 303 | + std::vector<uint8_t> derivedKey(keyLen, 0); | ||
| 304 | + int32_t ret = IotcKdf().Pkcs5Pbkdf2Hmac(¶m, derivedKey.data(), keyLen); | ||
| 305 | + if (ret != 0) { | ||
| 306 | + IOTC_LOGE("SpekeUtils::DeriveBaseSecretV2 PBKDF2 failed, ret=%{public}d", ret); | ||
| 307 | + std::memset(derivedKey.data(), 0, derivedKey.size()); | ||
| 308 | + std::memset(finalSalt.data(), 0, finalSalt.size()); | ||
| 309 | + return {}; | ||
| 310 | + } | ||
| 311 | + | ||
| 312 | + std::memset(finalSalt.data(), 0, finalSalt.size()); | ||
| 313 | + return derivedKey; | ||
| 314 | +} | ||
| 315 | + | ||
| 316 | +std::vector<uint8_t> SpekeUtils::DeriveSessionKey(const std::vector<uint8_t>& sharedSecret, | ||
| 317 | + const std::vector<uint8_t>& salt, const std::vector<uint8_t>& info, uint32_t keyLen) | ||
| 318 | +{ | ||
| 319 | + if (sharedSecret.empty() || salt.empty() || info.empty() || keyLen == 0) { | ||
| 320 | + IOTC_LOGW("SpekeUtils::DeriveSessionKey invalid param"); | ||
| 321 | + return {}; | ||
| 322 | + } | ||
| 323 | + | ||
| 324 | + /* 仅 EC 路径使用 HKDF-SHA256 派生会话密钥;DL 路径由调用方继续走原 HKDF-SHA256 流程。 */ | ||
| 325 | + if (pakeType_ != SpekeType::SPEKE_EC) { | ||
| 326 | + IOTC_LOGW("SpekeUtils::DeriveSessionKey only EC path supported here"); | ||
| 327 | + return {}; | ||
| 328 | + } | ||
| 329 | + | ||
| 330 | + IotcHkdfParam param {}; | ||
| 331 | + param.md = IotcMdType::IOTC_MD_SHA256; | ||
| 332 | + param.material = sharedSecret.data(); | ||
| 333 | + param.materialLen = sharedSecret.size(); | ||
| 334 | + param.salt = salt.data(); | ||
| 335 | + param.saltLen = salt.size(); | ||
| 336 | + param.info = info.data(); | ||
| 337 | + param.infoLen = info.size(); | ||
| 338 | + | ||
| 339 | + std::vector<uint8_t> derivedKey(keyLen, 0); | ||
| 340 | + int32_t ret = IotcKdf().Hkdf(¶m, derivedKey.data(), keyLen); | ||
| 341 | + if (ret != 0) { | ||
| 342 | + IOTC_LOGE("SpekeUtils::DeriveSessionKey HKDF failed, ret=%{public}d", ret); | ||
| 343 | + std::memset(derivedKey.data(), 0, derivedKey.size()); | ||
| 344 | + return {}; | ||
| 345 | + } | ||
| 346 | + | ||
| 347 | + return derivedKey; | ||
| 348 | +} | ||
| 349 | + | ||
| 350 | +} // namespace IotcManagement | ||
| 351 | +} // namespace OHOS | ||
| @@ -0,0 +1,112 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | +namespace OHOS { | ||
| 25 | +namespace IotcManagement { | ||
| 26 | + | ||
| 27 | +class IotcMpi; | ||
| 28 | + | ||
| 29 | +class SpekeUtils { | ||
| 30 | +public: | ||
| 31 | + SpekeUtils(); | ||
| 32 | + | ||
| 33 | + ~SpekeUtils(); | ||
| 34 | + | ||
| 35 | + void SetSpekeType(SpekeType type); | ||
| 36 | + | ||
| 37 | + int32_t GetPrivateParamLen(); | ||
| 38 | + | ||
| 39 | + /** | ||
| 40 | + * @brief 计算共享基值 | ||
| 41 | + * @param secret 密钥派生后的秘密值 | ||
| 42 | + * @return 共享基值向量 | ||
| 43 | + */ | ||
| 44 | + std::vector<uint8_t> ComputeSharedBase(const std::vector<uint8_t>& secret); | ||
| 45 | + | ||
| 46 | + /** | ||
| 47 | + * @brief 计算公钥参数 | ||
| 48 | + * @param base 共享基值 | ||
| 49 | + * @param privateParam 私钥参数 | ||
| 50 | + * @return 公钥参数向量(基值与私钥参数拼接) | ||
| 51 | + */ | ||
| 52 | + std::vector<uint8_t> ComputePublicParameter(const std::vector<uint8_t>& base, | ||
| 53 | + const std::vector<uint8_t>& privateParam); | ||
| 54 | + | ||
| 55 | + /** | ||
| 56 | + * @brief 计算共享密钥 | ||
| 57 | + * @param privateParam 自身的私钥参数 | ||
| 58 | + * @param peerPublicParam 对端的公钥参数 | ||
| 59 | + * @return 共享密钥(私钥参数与对端公钥参数拼接) | ||
| 60 | + */ | ||
| 61 | + std::vector<uint8_t> ComputeSharedKey(const std::vector<uint8_t>& privateParam, | ||
| 62 | + const std::vector<uint8_t>& peerPublicParam); | ||
| 63 | + | ||
| 64 | + /** | ||
| 65 | + * @brief 获取当前 SPEKE 类型。 | ||
| 66 | + */ | ||
| 67 | + SpekeType GetSpekeType() const; | ||
| 68 | + | ||
| 69 | + /** | ||
| 70 | + * @brief EC SPEKE 路径使用 PBKDF2-HMAC-SHA512 从 PIN 派生初始 secret。 | ||
| 71 | + */ | ||
| 72 | + std::vector<uint8_t> DeriveBaseSecretV2(const std::vector<uint8_t>& pin, | ||
| 73 | + const std::vector<uint8_t>& salt, uint32_t iterations); | ||
| 74 | + | ||
| 75 | + /** | ||
| 76 | + * @brief EC SPEKE 路径下使用 HKDF-SHA256 派生会话密钥。 | ||
| 77 | + * DL SPEKE 路径下不调用,保持原 HKDF 流程。 | ||
| 78 | + */ | ||
| 79 | + std::vector<uint8_t> DeriveSessionKey(const std::vector<uint8_t>& sharedSecret, | ||
| 80 | + const std::vector<uint8_t>& salt, const std::vector<uint8_t>& info, | ||
| 81 | + uint32_t keyLen); | ||
| 82 | + | ||
| 83 | +private: | ||
| 84 | + SpekeType pakeType_; | ||
| 85 | + | ||
| 86 | + static const std::string MOD_POW_384; | ||
| 87 | + static const std::string MOD_POW_256; | ||
| 88 | + | ||
| 89 | + /* DL SPEKE 私有方法 (模幂 base^pw mod N) */ | ||
| 90 | + std::vector<uint8_t> ComputeSharedBaseDl(const std::vector<uint8_t>& secret); | ||
| 91 | + std::vector<uint8_t> ComputePublicParameterDl(const std::vector<uint8_t>& base, | ||
| 92 | + const std::vector<uint8_t>& privateParam); | ||
| 93 | + std::vector<uint8_t> ComputeSharedKeyDl(const std::vector<uint8_t>& selfPrivateParam, | ||
| 94 | + const std::vector<uint8_t>& peerPublicParam); | ||
| 95 | + | ||
| 96 | + /* EC SPEKE 私有方法 (X25519 + Elligator2) */ | ||
| 97 | + std::vector<uint8_t> ComputeSharedBaseEc(const std::vector<uint8_t>& secret); | ||
| 98 | + std::vector<uint8_t> ComputePublicParameterEc(const std::vector<uint8_t>& base, | ||
| 99 | + const std::vector<uint8_t>& privateParam); | ||
| 100 | + std::vector<uint8_t> ComputeSharedKeyEc(const std::vector<uint8_t>& selfPrivateParam, | ||
| 101 | + const std::vector<uint8_t>& peerPublicParam); | ||
| 102 | + | ||
| 103 | + /* DL SPEKE 公共辅助 */ | ||
| 104 | + uint32_t GetDlPublicLength() const; | ||
| 105 | + int32_t LoadModulus(IotcMpi& mpiN) const; | ||
| 106 | + std::vector<uint8_t> FormatMpiToFixedLength(IotcMpi& mpiResult, uint32_t targetLen) const; | ||
| 107 | +}; | ||
| 108 | + | ||
| 109 | +} // namespace IotcManagement | ||
| 110 | +} // namespace OHOS | ||
| 111 | + | ||
| 112 | + | ||
| @@ -0,0 +1,427 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | + | ||
| 26 | + | ||
| 27 | +namespace OHOS { | ||
| 28 | +namespace IotcManagement { | ||
| 29 | + | ||
| 30 | +namespace { | ||
| 31 | + | ||
| 32 | +// Curve25519 域参数: P = 2^255 - 19 | ||
| 33 | +constexpr const char* P_HEX = | ||
| 34 | + "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed"; | ||
| 35 | + | ||
| 36 | +// Curve25519 上 sqrt(-1) mod P (RFC 9380 §J.1.1) | ||
| 37 | +constexpr const char* SQRT_M1_DEC = | ||
| 38 | + "19681161376707505956807079304988542015446066515923890162744021073123829784752"; | ||
| 39 | + | ||
| 40 | +constexpr int32_t RADIX_HEX = 16; | ||
| 41 | +constexpr int32_t RADIX_DEC = 10; | ||
| 42 | +constexpr uint32_t L_BYTES = 48; // ceil((255 + 128) / 8) | ||
| 43 | +constexpr uint32_t OUT_BYTES = 32; // Curve25519 点 x 坐标字节数 | ||
| 44 | + | ||
| 45 | +// === MPI 包装 ============================================================= | ||
| 46 | +struct ScopedMpi { | ||
| 47 | + IotcMpi v; | ||
| 48 | + | ||
| 49 | + ScopedMpi() = default; | ||
| 50 | + ~ScopedMpi() = default; | ||
| 51 | + ScopedMpi(const ScopedMpi&) = delete; | ||
| 52 | + ScopedMpi& operator=(const ScopedMpi&) = delete; | ||
| 53 | +}; | ||
| 54 | + | ||
| 55 | +int32_t ReadString(ScopedMpi& out, int32_t radix, const char* s) | ||
| 56 | +{ | ||
| 57 | + return out.v.ReadString(radix, s); | ||
| 58 | +} | ||
| 59 | + | ||
| 60 | +int32_t Lset(ScopedMpi& out, int32_t value) | ||
| 61 | +{ | ||
| 62 | + return out.v.Lset(value); | ||
| 63 | +} | ||
| 64 | + | ||
| 65 | +int32_t Copy(ScopedMpi& dst, const ScopedMpi& src) | ||
| 66 | +{ | ||
| 67 | + return dst.v.Copy(src.v); | ||
| 68 | +} | ||
| 69 | + | ||
| 70 | +// 域操作 (mod p, 自动取正) | ||
| 71 | +void ModPositive(const ScopedMpi& p, const ScopedMpi& src, ScopedMpi& out) | ||
| 72 | +{ | ||
| 73 | + out.v.Mod(&src.v, &p.v); | ||
| 74 | + if (out.v.CmpInt(0) < 0) { | ||
| 75 | + ScopedMpi tmp; | ||
| 76 | + tmp.v.Add(&out.v, &p.v); | ||
| 77 | + out.v.Copy(tmp.v); | ||
| 78 | + } | ||
| 79 | +} | ||
| 80 | + | ||
| 81 | +// (a + b) mod p | ||
| 82 | +void AddMod(const ScopedMpi& a, const ScopedMpi& b, const ScopedMpi& p, ScopedMpi& out) | ||
| 83 | +{ | ||
| 84 | + out.v.Add(&a.v, &b.v); | ||
| 85 | + out.v.Mod(&out.v, &p.v); | ||
| 86 | +} | ||
| 87 | + | ||
| 88 | +// (a - b) mod p, 结果归一化到 [0, p) | ||
| 89 | +void SubMod(const ScopedMpi& a, const ScopedMpi& b, const ScopedMpi& p, ScopedMpi& out) | ||
| 90 | +{ | ||
| 91 | + out.v.Sub(&a.v, &b.v); | ||
| 92 | + out.v.Mod(&out.v, &p.v); | ||
| 93 | + if (out.v.CmpInt(0) < 0) { | ||
| 94 | + ScopedMpi tmp; | ||
| 95 | + tmp.v.Add(&out.v, &p.v); | ||
| 96 | + out.v.Copy(tmp.v); | ||
| 97 | + } | ||
| 98 | +} | ||
| 99 | + | ||
| 100 | +// (a * b) mod p | ||
| 101 | +void MulMod(const ScopedMpi& a, const ScopedMpi& b, const ScopedMpi& p, ScopedMpi& out) | ||
| 102 | +{ | ||
| 103 | + out.v.Mul(&a.v, &b.v); | ||
| 104 | + out.v.Mod(&out.v, &p.v); | ||
| 105 | +} | ||
| 106 | + | ||
| 107 | +// 模逆: inv0(0) = 0, 否则返回 x^(p-2) mod p | ||
| 108 | +void InvMod(const ScopedMpi& x, const ScopedMpi& p, ScopedMpi& out) | ||
| 109 | +{ | ||
| 110 | + if (x.v.CmpInt(0) == 0) { | ||
| 111 | + Lset(out, 0); | ||
| 112 | + return; | ||
| 113 | + } | ||
| 114 | + ScopedMpi exp; | ||
| 115 | + ScopedMpi two; | ||
| 116 | + Lset(two, 2); | ||
| 117 | + exp.v.Sub(&p.v, &two.v); | ||
| 118 | + out.v.Exp(&x.v, &exp.v, &p.v); | ||
| 119 | +} | ||
| 120 | + | ||
| 121 | +// 通用幂 | ||
| 122 | +void PowMod(const ScopedMpi& base, const ScopedMpi& exp, const ScopedMpi& mod, ScopedMpi& out) | ||
| 123 | +{ | ||
| 124 | + out.v.Exp(&base.v, &exp.v, &mod.v); | ||
| 125 | +} | ||
| 126 | + | ||
| 127 | +// x 是否为平方剩余 (Euler 判别) | ||
| 128 | +bool IsSquare(const ScopedMpi& x, const ScopedMpi& p) | ||
| 129 | +{ | ||
| 130 | + if (x.v.CmpInt(0) == 0) { | ||
| 131 | + return true; | ||
| 132 | + } | ||
| 133 | + ScopedMpi half; | ||
| 134 | + ScopedMpi one; | ||
| 135 | + ScopedMpi two; | ||
| 136 | + Lset(one, 1); | ||
| 137 | + Lset(two, 2); | ||
| 138 | + half.v.Sub(&p.v, &one.v); | ||
| 139 | + ScopedMpi exp; | ||
| 140 | + exp.v.Div(&half.v, &two.v, &exp.v, nullptr); // quotient -> exp | ||
| 141 | + ScopedMpi result; | ||
| 142 | + PowMod(x, exp, p, result); | ||
| 143 | + return result.v.CmpInt(1) == 0; | ||
| 144 | +} | ||
| 145 | + | ||
| 146 | +// P ≡ 5 mod 8 优化的模平方根 | ||
| 147 | +void SqrtMod(const ScopedMpi& x, const ScopedMpi& p, const ScopedMpi& c1, ScopedMpi& out) | ||
| 148 | +{ | ||
| 149 | + if (x.v.CmpInt(0) == 0) { | ||
| 150 | + Lset(out, 0); | ||
| 151 | + return; | ||
| 152 | + } | ||
| 153 | + if (!IsSquare(x, p)) { | ||
| 154 | + Lset(out, 0); | ||
| 155 | + return; | ||
| 156 | + } | ||
| 157 | + ScopedMpi pPlus3; | ||
| 158 | + ScopedMpi three; | ||
| 159 | + Lset(three, 3); | ||
| 160 | + pPlus3.v.Add(&p.v, &three.v); | ||
| 161 | + ScopedMpi eight; | ||
| 162 | + ScopedMpi c2; | ||
| 163 | + Lset(eight, 8); | ||
| 164 | + c2.v.Div(&pPlus3.v, &eight.v, &c2.v, nullptr); // quotient -> c2 | ||
| 165 | + | ||
| 166 | + ScopedMpi tv1; | ||
| 167 | + PowMod(x, c2, p, tv1); | ||
| 168 | + ScopedMpi tv2; | ||
| 169 | + MulMod(tv1, c1, p, tv2); | ||
| 170 | + | ||
| 171 | + ScopedMpi tv1Sq; | ||
| 172 | + MulMod(tv1, tv1, p, tv1Sq); | ||
| 173 | + bool e = (tv1Sq.v.Cmp(&tv1Sq.v, &x.v) == 0); | ||
| 174 | + if (e) { | ||
| 175 | + Copy(out, tv1); | ||
| 176 | + } else { | ||
| 177 | + Copy(out, tv2); | ||
| 178 | + } | ||
| 179 | +} | ||
| 180 | + | ||
| 181 | +// 取 y 的最低位 (用于 sgn0 符号选择) | ||
| 182 | +uint32_t Sgn0(ScopedMpi& y) | ||
| 183 | +{ | ||
| 184 | + std::vector<uint8_t> buf(OUT_BYTES, 0); | ||
| 185 | + y.v.ExportBinary(buf.data(), OUT_BYTES); | ||
| 186 | + return buf[OUT_BYTES - 1] & 0x01U; | ||
| 187 | +} | ||
| 188 | + | ||
| 189 | +/* | ||
| 190 | + * EC SPEKE 字节序约定:base.x 必须以 BE 字节返回(来自 mbedtls_mpi_write_binary, | ||
| 191 | + * 未做翻转),与本侧 ComputeSharedKey 接收 LE 线缆字节时走的 "SwapEndian + | ||
| 192 | + * read_binary(BE)" 链路在语义上对称,X25519 DH 对称性才能成立;若误改为 LE | ||
| 193 | + * 输出将导致 HMAC 校验失败。 | ||
| 194 | + */ | ||
| 195 | +std::vector<uint8_t> MpiToBytes32Be(ScopedMpi& v) | ||
| 196 | +{ | ||
| 197 | + std::vector<uint8_t> buf(OUT_BYTES, 0); | ||
| 198 | + v.v.ExportBinary(buf.data(), OUT_BYTES); | ||
| 199 | + return buf; | ||
| 200 | +} | ||
| 201 | + | ||
| 202 | +// 取大端字节切片读取为 MPI | ||
| 203 | +void BytesToMpi(const std::vector<uint8_t>& bytes, uint32_t offset, uint32_t len, ScopedMpi& out) | ||
| 204 | +{ | ||
| 205 | + if (offset + len > bytes.size()) { | ||
| 206 | + return; | ||
| 207 | + } | ||
| 208 | + out.v.ImportBinary(bytes.data() + offset, len); | ||
| 209 | +} | ||
| 210 | + | ||
| 211 | +// 椭圆曲线点 | ||
| 212 | +struct Point { | ||
| 213 | + ScopedMpi x; | ||
| 214 | + ScopedMpi y; | ||
| 215 | +}; | ||
| 216 | + | ||
| 217 | +// map_to_curve (Elligator2 for Curve25519) | ||
| 218 | +void MapToCurve(const ScopedMpi& u, const ScopedMpi& p, const ScopedMpi& j, | ||
| 219 | + const ScopedMpi& z, const ScopedMpi& c1, Point& out) | ||
| 220 | +{ | ||
| 221 | + ScopedMpi uSq; | ||
| 222 | + MulMod(u, u, p, uSq); | ||
| 223 | + ScopedMpi zUSq; | ||
| 224 | + MulMod(z, uSq, p, zUSq); | ||
| 225 | + ScopedMpi denom; | ||
| 226 | + ScopedMpi one; | ||
| 227 | + Lset(one, 1); | ||
| 228 | + AddMod(one, zUSq, p, denom); | ||
| 229 | + ScopedMpi invDenom; | ||
| 230 | + InvMod(denom, p, invDenom); | ||
| 231 | + ScopedMpi negJ; | ||
| 232 | + SubMod(p, j, p, negJ); | ||
| 233 | + ScopedMpi x1; | ||
| 234 | + MulMod(negJ, invDenom, p, x1); | ||
| 235 | + | ||
| 236 | + ScopedMpi x1Sq; | ||
| 237 | + MulMod(x1, x1, p, x1Sq); | ||
| 238 | + ScopedMpi x1Cube; | ||
| 239 | + MulMod(x1Sq, x1, p, x1Cube); | ||
| 240 | + ScopedMpi jx1Sq; | ||
| 241 | + MulMod(j, x1Sq, p, jx1Sq); | ||
| 242 | + ScopedMpi gx1; | ||
| 243 | + ScopedMpi tmp; | ||
| 244 | + AddMod(x1Cube, jx1Sq, p, tmp); | ||
| 245 | + AddMod(tmp, x1, p, gx1); | ||
| 246 | + | ||
| 247 | + ScopedMpi negX1; | ||
| 248 | + SubMod(p, x1, p, negX1); | ||
| 249 | + ScopedMpi x2; | ||
| 250 | + SubMod(negX1, j, p, x2); | ||
| 251 | + | ||
| 252 | + ScopedMpi x2Sq; | ||
| 253 | + MulMod(x2, x2, p, x2Sq); | ||
| 254 | + ScopedMpi x2Cube; | ||
| 255 | + MulMod(x2Sq, x2, p, x2Cube); | ||
| 256 | + ScopedMpi jx2Sq; | ||
| 257 | + MulMod(j, x2Sq, p, jx2Sq); | ||
| 258 | + ScopedMpi gx2; | ||
| 259 | + ScopedMpi tmp2; | ||
| 260 | + AddMod(x2Cube, jx2Sq, p, tmp2); | ||
| 261 | + AddMod(tmp2, x2, p, gx2); | ||
| 262 | + | ||
| 263 | + bool wantSgn1 = false; | ||
| 264 | + ScopedMpi chosenX; | ||
| 265 | + ScopedMpi chosenG; | ||
| 266 | + if (IsSquare(gx1, p)) { | ||
| 267 | + Copy(chosenX, x1); | ||
| 268 | + Copy(chosenG, gx1); | ||
| 269 | + wantSgn1 = true; | ||
| 270 | + } else { | ||
| 271 | + Copy(chosenX, x2); | ||
| 272 | + Copy(chosenG, gx2); | ||
| 273 | + wantSgn1 = false; | ||
| 274 | + } | ||
| 275 | + | ||
| 276 | + ScopedMpi y; | ||
| 277 | + SqrtMod(chosenG, p, c1, y); | ||
| 278 | + | ||
| 279 | + uint32_t sgn = Sgn0(y); | ||
| 280 | + bool needNeg = wantSgn1 ? (sgn != 1U) : (sgn != 0U); | ||
| 281 | + if (needNeg) { | ||
| 282 | + ScopedMpi negY; | ||
| 283 | + SubMod(p, y, p, negY); | ||
| 284 | + Copy(y, negY); | ||
| 285 | + } | ||
| 286 | + | ||
| 287 | + Copy(out.x, chosenX); | ||
| 288 | + Copy(out.y, y); | ||
| 289 | +} | ||
| 290 | + | ||
| 291 | +// 椭圆曲线点加 | ||
| 292 | +void ScalarAdd(const Point& a, const Point& b, const ScopedMpi& p, const ScopedMpi& j, Point& out) | ||
| 293 | +{ | ||
| 294 | + bool aIsZero = (a.x.v.CmpInt(0) == 0) && (a.y.v.CmpInt(0) == 0); | ||
| 295 | + bool bIsZero = (b.x.v.CmpInt(0) == 0) && (b.y.v.CmpInt(0) == 0); | ||
| 296 | + | ||
| 297 | + if (aIsZero) { | ||
| 298 | + Copy(out.x, b.x); | ||
| 299 | + Copy(out.y, b.y); | ||
| 300 | + return; | ||
| 301 | + } | ||
| 302 | + if (bIsZero) { | ||
| 303 | + Copy(out.x, a.x); | ||
| 304 | + Copy(out.y, a.y); | ||
| 305 | + return; | ||
| 306 | + } | ||
| 307 | + | ||
| 308 | + ScopedMpi m; | ||
| 309 | + if (a.x.v.Cmp(&a.x.v, &b.x.v) == 0) { | ||
| 310 | + ScopedMpi negB; | ||
| 311 | + SubMod(p, b.y, p, negB); | ||
| 312 | + if (a.y.v.Cmp(&a.y.v, &negB.v) == 0) { | ||
| 313 | + Lset(out.x, 0); | ||
| 314 | + Lset(out.y, 0); | ||
| 315 | + return; | ||
| 316 | + } | ||
| 317 | + // 切线斜率 (3x^2 + 2Jx + 1) / (2y) | ||
| 318 | + ScopedMpi three; | ||
| 319 | + ScopedMpi two; | ||
| 320 | + ScopedMpi one; | ||
| 321 | + Lset(three, 3); | ||
| 322 | + Lset(two, 2); | ||
| 323 | + Lset(one, 1); | ||
| 324 | + ScopedMpi xSq; | ||
| 325 | + MulMod(a.x, a.x, p, xSq); | ||
| 326 | + ScopedMpi term1; | ||
| 327 | + MulMod(three, xSq, p, term1); | ||
| 328 | + ScopedMpi jx; | ||
| 329 | + MulMod(j, a.x, p, jx); | ||
| 330 | + ScopedMpi term2; | ||
| 331 | + MulMod(two, jx, p, term2); | ||
| 332 | + ScopedMpi num; | ||
| 333 | + ScopedMpi tmp; | ||
| 334 | + AddMod(term1, term2, p, tmp); | ||
| 335 | + AddMod(tmp, one, p, num); | ||
| 336 | + ScopedMpi twoY; | ||
| 337 | + MulMod(two, a.y, p, twoY); | ||
| 338 | + ScopedMpi invDenom; | ||
| 339 | + InvMod(twoY, p, invDenom); | ||
| 340 | + MulMod(num, invDenom, p, m); | ||
| 341 | + } else { | ||
| 342 | + ScopedMpi num; | ||
| 343 | + ScopedMpi denom; | ||
| 344 | + SubMod(a.y, b.y, p, num); | ||
| 345 | + SubMod(a.x, b.x, p, denom); | ||
| 346 | + ScopedMpi invDenom; | ||
| 347 | + InvMod(denom, p, invDenom); | ||
| 348 | + MulMod(num, invDenom, p, m); | ||
| 349 | + } | ||
| 350 | + | ||
| 351 | + // x3 = m^2 - J - x1 - x2 | ||
| 352 | + ScopedMpi mSq; | ||
| 353 | + MulMod(m, m, p, mSq); | ||
| 354 | + ScopedMpi tmp; | ||
| 355 | + SubMod(mSq, j, p, tmp); | ||
| 356 | + ScopedMpi tmp2; | ||
| 357 | + SubMod(tmp, a.x, p, tmp2); | ||
| 358 | + ScopedMpi x3; | ||
| 359 | + SubMod(tmp2, b.x, p, x3); | ||
| 360 | + | ||
| 361 | + ScopedMpi diff; | ||
| 362 | + SubMod(a.x, x3, p, diff); | ||
| 363 | + ScopedMpi y3Tmp; | ||
| 364 | + MulMod(m, diff, p, y3Tmp); | ||
| 365 | + ScopedMpi y3; | ||
| 366 | + SubMod(y3Tmp, a.y, p, y3); | ||
| 367 | + | ||
| 368 | + Copy(out.x, x3); | ||
| 369 | + Copy(out.y, y3); | ||
| 370 | +} | ||
| 371 | + | ||
| 372 | +} // namespace | ||
| 373 | + | ||
| 374 | +std::vector<uint8_t> HashToCurveX25519::HashToPoint(const std::vector<uint8_t>& secret) | ||
| 375 | +{ | ||
| 376 | + if (secret.size() != GlobalParams::PAKE_SECRET_LENGTH_EC) { | ||
| 377 | + IOTC_LOGE("HashToCurveX25519::HashToPoint secret must be %{public}u bytes, got=%{public}zu", | ||
| 378 | + GlobalParams::PAKE_SECRET_LENGTH_EC, secret.size()); | ||
| 379 | + return {}; | ||
| 380 | + } | ||
| 381 | + | ||
| 382 | + ScopedMpi p; | ||
| 383 | + if (ReadString(p, RADIX_HEX, P_HEX) != 0) { | ||
| 384 | + IOTC_LOGE("HashToCurveX25519: read P failed"); | ||
| 385 | + return {}; | ||
| 386 | + } | ||
| 387 | + ScopedMpi j; | ||
| 388 | + ScopedMpi z; | ||
| 389 | + ScopedMpi c1; | ||
| 390 | + if (ReadString(j, RADIX_HEX, "76d06") != 0 || // 486662 (Montgomery A) as hex | ||
| 391 | + ReadString(z, RADIX_HEX, "2") != 0 || | ||
| 392 | + ReadString(c1, RADIX_DEC, SQRT_M1_DEC) != 0) { | ||
| 393 | + IOTC_LOGE("HashToCurveX25519: read constants failed"); | ||
| 394 | + return {}; | ||
| 395 | + } | ||
| 396 | + | ||
| 397 | + ScopedMpi u0Bytes; | ||
| 398 | + ScopedMpi u1Bytes; | ||
| 399 | + BytesToMpi(secret, 0, L_BYTES, u0Bytes); | ||
| 400 | + BytesToMpi(secret, L_BYTES, L_BYTES, u1Bytes); | ||
| 401 | + | ||
| 402 | + ScopedMpi u0; | ||
| 403 | + ScopedMpi u1; | ||
| 404 | + ModPositive(p, u0Bytes, u0); | ||
| 405 | + ModPositive(p, u1Bytes, u1); | ||
| 406 | + | ||
| 407 | + Point q0 {}; | ||
| 408 | + Point q1 {}; | ||
| 409 | + MapToCurve(u0, p, j, z, c1, q0); | ||
| 410 | + MapToCurve(u1, p, j, z, c1, q1); | ||
| 411 | + | ||
| 412 | + Point sum {}; | ||
| 413 | + ScalarAdd(q0, q1, p, j, sum); | ||
| 414 | + | ||
| 415 | + // clear_cofactor: ×8 via 3 doublings | ||
| 416 | + Point p2 {}; | ||
| 417 | + Point p4 {}; | ||
| 418 | + Point p8 {}; | ||
| 419 | + ScalarAdd(sum, sum, p, j, p2); | ||
| 420 | + ScalarAdd(p2, p2, p, j, p4); | ||
| 421 | + ScalarAdd(p4, p4, p, j, p8); | ||
| 422 | + | ||
| 423 | + return MpiToBytes32Be(p8.x); | ||
| 424 | +} | ||
| 425 | + | ||
| 426 | +} // namespace IotcManagement | ||
| 427 | +} // namespace OHOS | ||
| @@ -0,0 +1,46 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | +namespace OHOS { | ||
| 23 | +namespace IotcManagement { | ||
| 24 | + | ||
| 25 | +/** | ||
| 26 | + * @brief 将 96B 的 HKDF 派生 secret 哈希到 Curve25519 上的合法 x 坐标。 | ||
| 27 | + * | ||
| 28 | + * 实现参考 RFC 9380 §6.7.1 (Elligator 2 Method for Montgomery Curves)。 | ||
| 29 | + * | ||
| 30 | + * 字节序约定: 本接口必须输出 BE 字节 (来自 mbedtls_mpi_write_binary,未做翻转), | ||
| 31 | + * 否则会破坏 EC SPEKE 协商中 X25519 的 DH 对称性,导致 HMAC 校验失败。 | ||
| 32 | + */ | ||
| 33 | +class HashToCurveX25519 { | ||
| 34 | +public: | ||
| 35 | + /** | ||
| 36 | + * @brief 将 secret 哈希为 Curve25519 上的点 x 坐标。 | ||
| 37 | + * @param secret PAKE_SECRET_LENGTH_EC (96) 字节输入。 | ||
| 38 | + * @return 32B BE 字节;失败返回空 vector。 | ||
| 39 | + */ | ||
| 40 | + static std::vector<uint8_t> HashToPoint(const std::vector<uint8_t>& secret); | ||
| 41 | +}; | ||
| 42 | + | ||
| 43 | +} // namespace IotcManagement | ||
| 44 | +} // namespace OHOS | ||
| 45 | + | ||
| 46 | + | ||
| @@ -0,0 +1,37 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | +namespace OHOS { | ||
| 19 | +namespace IotcManagement { | ||
| 20 | + | ||
| 21 | +SpekeRequestOverAdvBle::SpekeRequestOverAdvBle() | ||
| 22 | + : SpekeRequest(), mMac_("") | ||
| 23 | +{ | ||
| 24 | +} | ||
| 25 | + | ||
| 26 | +std::string SpekeRequestOverAdvBle::GetMac() const | ||
| 27 | +{ | ||
| 28 | + return mMac_; | ||
| 29 | +} | ||
| 30 | + | ||
| 31 | +void SpekeRequestOverAdvBle::SetMac(const std::string& mac) | ||
| 32 | +{ | ||
| 33 | + mMac_ = mac; | ||
| 34 | +} | ||
| 35 | + | ||
| 36 | +} // namespace IotcManagement | ||
| 37 | +} // namespace OHOS | ||
| @@ -0,0 +1,42 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | +namespace OHOS { | ||
| 23 | +namespace IotcManagement { | ||
| 24 | + | ||
| 25 | +class SpekeRequestOverAdvBle : public SpekeRequest { | ||
| 26 | +public: | ||
| 27 | + SpekeRequestOverAdvBle(); | ||
| 28 | + ~SpekeRequestOverAdvBle() = default; | ||
| 29 | + | ||
| 30 | + SpekeRequestType GetType() const override { return SpekeRequestType::ADAPTER_BLE; } | ||
| 31 | + | ||
| 32 | + std::string GetMac() const; | ||
| 33 | + void SetMac(const std::string& mac); | ||
| 34 | + | ||
| 35 | +private: | ||
| 36 | + std::string mMac_; | ||
| 37 | +}; | ||
| 38 | + | ||
| 39 | +} // namespace IotcManagement | ||
| 40 | +} // namespace OHOS | ||
| 41 | + | ||
| 42 | + | ||
| @@ -0,0 +1,80 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | +namespace OHOS { | ||
| 22 | +namespace IotcManagement { | ||
| 23 | + | ||
| 24 | +SpekeTransferOverAdvBle::SpekeTransferOverAdvBle(std::shared_ptr<SpekeRequestOverAdvBle> spekeRequest, | ||
| 25 | + std::shared_ptr<AdvBleRequest> request) | ||
| 26 | + : mSpekeRequestOverAdvBle_(spekeRequest) | ||
| 27 | + , mRequest_(request ? request : std::make_shared<AdvBleRequest>()) | ||
| 28 | + , advBleDeviceApi_(std::make_shared<AdvBleDeviceApi>()) | ||
| 29 | +{ | ||
| 30 | +} | ||
| 31 | + | ||
| 32 | +void SpekeTransferOverAdvBle::Send(const std::string& sendData, std::shared_ptr<TransferResponseCallback> callback) | ||
| 33 | +{ | ||
| 34 | + IOTC_LOGI("SpekeTransferOverAdvBle::Send data length=%{public}zu", sendData.length()); | ||
| 35 | + | ||
| 36 | + if (!callback) { | ||
| 37 | + IOTC_LOGW("SpekeTransferOverAdvBle::Send callback is null"); | ||
| 38 | + return; | ||
| 39 | + } | ||
| 40 | + | ||
| 41 | + if (!mSpekeRequestOverAdvBle_) { | ||
| 42 | + IOTC_LOGW("SpekeTransferOverAdvBle::Send mSpekeRequestOverAdvBle_ is null"); | ||
| 43 | + callback->OnFailure(CommonConstants::COMMON_PARAMETER_INVALID); | ||
| 44 | + return; | ||
| 45 | + } | ||
| 46 | + | ||
| 47 | + std::string mac = mSpekeRequestOverAdvBle_->GetMac(); | ||
| 48 | + if (mac.empty() || sendData.empty()) { | ||
| 49 | + IOTC_LOGW("SpekeTransferOverAdvBle::Send params are invalid"); | ||
| 50 | + callback->OnFailure(CommonConstants::COMMON_PARAMETER_INVALID); | ||
| 51 | + return; | ||
| 52 | + } | ||
| 53 | + | ||
| 54 | + mRequest_->SetAppData(sendData); | ||
| 55 | + auto entityCallback = std::make_shared<EntityResponseCallbackImpl>(); | ||
| 56 | + entityCallback->onResponse = [callback](BaseEntityModel* response) { | ||
| 57 | + if (response == nullptr) { | ||
| 58 | + IOTC_LOGW("EntityResponseCallbackImpl::OnResponse response is null"); | ||
| 59 | + callback->OnFailure(CommonConstants::COMMON_FAILED); | ||
| 60 | + return; | ||
| 61 | + } | ||
| 62 | + if (response->errorCode != CommonConstants::COMMON_SUCCESS) { | ||
| 63 | + IOTC_LOGW("EntityResponseCallbackImpl::OnResponse failed, errorCode=%{public}d", | ||
| 64 | + response->errorCode); | ||
| 65 | + callback->OnFailure(response->errorCode); | ||
| 66 | + return; | ||
| 67 | + } | ||
| 68 | + if (response->responseData.empty()) { | ||
| 69 | + IOTC_LOGW("EntityResponseCallbackImpl::OnResponse response data is empty"); | ||
| 70 | + callback->OnFailure(CommonConstants::COMMON_FAILED); | ||
| 71 | + return; | ||
| 72 | + } | ||
| 73 | + callback->OnResponse(response->responseData); | ||
| 74 | + }; | ||
| 75 | + | ||
| 76 | + advBleDeviceApi_->SpekeHandshake(mac, mRequest_, entityCallback); | ||
| 77 | +} | ||
| 78 | + | ||
| 79 | +} // namespace IotcManagement | ||
| 80 | +} // namespace OHOS | ||
| @@ -0,0 +1,48 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | + | ||
| 26 | + | ||
| 27 | + | ||
| 28 | +namespace OHOS { | ||
| 29 | +namespace IotcManagement { | ||
| 30 | + | ||
| 31 | +class SpekeTransferOverAdvBle : public SpekeTransferLayer { | ||
| 32 | +public: | ||
| 33 | + SpekeTransferOverAdvBle(std::shared_ptr<SpekeRequestOverAdvBle> spekeRequest, | ||
| 34 | + std::shared_ptr<AdvBleRequest> request); | ||
| 35 | + ~SpekeTransferOverAdvBle() = default; | ||
| 36 | + | ||
| 37 | + void Send(const std::string& sendData, std::shared_ptr<TransferResponseCallback> callback) override; | ||
| 38 | + | ||
| 39 | +private: | ||
| 40 | + std::shared_ptr<SpekeRequestOverAdvBle> mSpekeRequestOverAdvBle_; | ||
| 41 | + std::shared_ptr<AdvBleRequest> mRequest_; | ||
| 42 | + std::shared_ptr<AdvBleDeviceApi> advBleDeviceApi_; | ||
| 43 | +}; | ||
| 44 | + | ||
| 45 | +} // namespace IotcManagement | ||
| 46 | +} // namespace OHOS | ||
| 47 | + | ||
| 48 | + | ||
| @@ -54,4 +54,4 @@ void SpekeRequestOverCoap::SetUrl(const std::string& url) | |||
| 54 | } | 54 | } |
| 55 | 55 | ||
| 56 | } // namespace IotcManagement | 56 | } // namespace IotcManagement |
| 57 | -} // namespace OHOS | 57 | +} // namespace OHOS |
| @@ -17,11 +17,13 @@ | |||
| 17 | 17 | ||
| 18 | 18 | ||
| 19 | 19 | ||
| 20 | - | ||
| 21 | 20 | ||
| 22 | namespace OHOS { | 21 | namespace OHOS { |
| 23 | namespace IotcManagement { | 22 | namespace IotcManagement { |
| 24 | 23 | ||
| 24 | +namespace { | ||
| 25 | +constexpr int32_t COAP_NO_RESPONSE = -1; | ||
| 26 | +} | ||
| 25 | 27 | ||
| 26 | SpeckTransferOverCoap::SpeckTransferOverCoap(std::shared_ptr<SpekeRequestOverCoap> speckRequest) | 28 | SpeckTransferOverCoap::SpeckTransferOverCoap(std::shared_ptr<SpekeRequestOverCoap> speckRequest) |
| 27 | : mSpeckRequestOverCoap_(speckRequest), coapDeviceApi_(std::make_shared<CoapDeviceApi>()) | 29 | : mSpeckRequestOverCoap_(speckRequest), coapDeviceApi_(std::make_shared<CoapDeviceApi>()) |
| @@ -30,62 +32,40 @@ SpeckTransferOverCoap::SpeckTransferOverCoap(std::shared_ptr<SpekeRequestOverCoa | |||
| 30 | 32 | ||
| 31 | void SpeckTransferOverCoap::Send(const std::string& sendData, std::shared_ptr<TransferResponseCallback> callback) | 33 | void SpeckTransferOverCoap::Send(const std::string& sendData, std::shared_ptr<TransferResponseCallback> callback) |
| 32 | { | 34 | { |
| 33 | - (void)callback; | 35 | + if (!callback) { |
| 34 | - if (!mSpeckRequestOverCoap_ || mSpeckRequestOverCoap_->GetIpAddress().empty()) { | 36 | + IOTC_LOGW("SpeckTransferOverCoap::Send callback is null"); |
| 35 | - IOTC_LOGW("SpeckTransferOverCoap::Send mSpeckRequestOverCoap is null"); | 37 | + return; |
| 38 | + } | ||
| 39 | + if (!mSpeckRequestOverCoap_ || mSpeckRequestOverCoap_->GetIpAddress().empty() || sendData.empty()) { | ||
| 40 | + IOTC_LOGW("SpeckTransferOverCoap::Send params are invalid"); | ||
| 41 | + callback->OnFailure(CommonConstants::COMMON_PARAMETER_INVALID); | ||
| 36 | return; | 42 | return; |
| 37 | } | 43 | } |
| 38 | auto entityCallback = std::make_shared<EntityResponseCallbackImpl>(); | 44 | auto entityCallback = std::make_shared<EntityResponseCallbackImpl>(); |
| 39 | - std::weak_ptr<SpeckTransferOverCoap> weakThis(shared_from_this()); | 45 | + entityCallback->onResponse = [callback](BaseEntityModel* response) { |
| 40 | - entityCallback->onResponse = [weakThis](BaseEntityModel* response) { | 46 | + if (response == nullptr) { |
| 41 | - auto self = weakThis.lock(); | 47 | + IOTC_LOGW("EntityResponseCallbackImpl::OnResponse response is null"); |
| 42 | - if (!self) { | 48 | + callback->OnFailure(CommonConstants::COMMON_FAILED); |
| 43 | return; | 49 | return; |
| 44 | } | 50 | } |
| 45 | - if (response == nullptr || response->responseData.empty()) { | 51 | + if (response->errorCode != CommonConstants::COMMON_SUCCESS) { |
| 46 | - IOTC_LOGW("EntityResponseCallbackImpl::OnResponse response nullptr"); | 52 | + IOTC_LOGW("EntityResponseCallbackImpl::OnResponse failed, errorCode=%{public}d", |
| 53 | + response->errorCode); | ||
| 54 | + if (response->errorCode != COAP_NO_RESPONSE) { | ||
| 55 | + callback->OnFailure(response->errorCode); | ||
| 56 | + } | ||
| 47 | return; | 57 | return; |
| 48 | } | 58 | } |
| 49 | - self->ProcessReceivedSpekeMsg(response->responseData); | 59 | + if (response->responseData.empty()) { |
| 60 | + IOTC_LOGW("EntityResponseCallbackImpl::OnResponse response data is empty"); | ||
| 61 | + callback->OnFailure(CommonConstants::COMMON_FAILED); | ||
| 62 | + return; | ||
| 63 | + } | ||
| 64 | + callback->OnResponse(response->responseData); | ||
| 50 | }; | 65 | }; |
| 51 | 66 | ||
| 52 | coapDeviceApi_->SpekeHandshake(mSpeckRequestOverCoap_->GetIpAddress(), | 67 | coapDeviceApi_->SpekeHandshake(mSpeckRequestOverCoap_->GetIpAddress(), |
| 53 | - sendData, 1, entityCallback); | 68 | + sendData, 1, mSpeckRequestOverCoap_->GetUrl(), entityCallback); |
| 54 | -} | ||
| 55 | - | ||
| 56 | -/** | ||
| 57 | - * 处理接收到的Speke消息 | ||
| 58 | - * | ||
| 59 | - * @param response 响应数据 | ||
| 60 | - */ | ||
| 61 | -void SpeckTransferOverCoap::ProcessReceivedSpekeMsg(const std::string& response) | ||
| 62 | -{ | ||
| 63 | - std::string resData = response; | ||
| 64 | - int32_t num = 0; | ||
| 65 | - int32_t index = 0; | ||
| 66 | - | ||
| 67 | - while (index < static_cast<int32_t>(resData.length())) { | ||
| 68 | - if (resData[index] == '{') { | ||
| 69 | - num++; | ||
| 70 | - } else if (resData[index] == '}') { | ||
| 71 | - num--; | ||
| 72 | - } | ||
| 73 | - ++index; | ||
| 74 | - if (num == 0) { | ||
| 75 | - break; | ||
| 76 | - } | ||
| 77 | - } | ||
| 78 | - | ||
| 79 | - resData = resData.substr(0, index); | ||
| 80 | - | ||
| 81 | - if (!mSpeckRequestOverCoap_) { | ||
| 82 | - IOTC_LOGI("SpeckTransferOverCoap::ProcessReceivedSpekeMsg SpekeRequestOverCoap is null"); | ||
| 83 | - return; | ||
| 84 | - } | ||
| 85 | - | ||
| 86 | - E2eSecurityApi::ProcessReceivedSpekeMsg(mSpeckRequestOverCoap_->GetDeviceId(), | ||
| 87 | - resData, mSpeckRequestOverCoap_->GetProtocolType(), | ||
| 88 | - mSpeckRequestOverCoap_->GetProtocolVersion()); | ||
| 89 | } | 69 | } |
| 90 | 70 | ||
| 91 | } // namespace IotcManagement | 71 | } // namespace IotcManagement |
| @@ -34,8 +34,6 @@ public: | |||
| 34 | 34 | ||
| 35 | void Send(const std::string& sendData, std::shared_ptr<TransferResponseCallback> callback) override; | 35 | void Send(const std::string& sendData, std::shared_ptr<TransferResponseCallback> callback) override; |
| 36 | 36 | ||
| 37 | - void ProcessReceivedSpekeMsg(const std::string& response); | ||
| 38 | - | ||
| 39 | private: | 37 | private: |
| 40 | std::shared_ptr<SpekeRequestOverCoap> mSpeckRequestOverCoap_; | 38 | std::shared_ptr<SpekeRequestOverCoap> mSpeckRequestOverCoap_; |
| 41 | std::shared_ptr<CoapDeviceApi> coapDeviceApi_; | 39 | std::shared_ptr<CoapDeviceApi> coapDeviceApi_; |
| @@ -0,0 +1,66 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | +namespace OHOS { | ||
| 19 | +namespace IotcManagement { | ||
| 20 | + | ||
| 21 | +SpekeEntity::SpekeEntity() : deviceType_(0) | ||
| 22 | +{ | ||
| 23 | +} | ||
| 24 | + | ||
| 25 | +std::string SpekeEntity::GetDeviceId() const | ||
| 26 | +{ | ||
| 27 | + return deviceId_; | ||
| 28 | +} | ||
| 29 | + | ||
| 30 | +void SpekeEntity::SetDeviceId(const std::string& deviceId) | ||
| 31 | +{ | ||
| 32 | + deviceId_ = deviceId; | ||
| 33 | +} | ||
| 34 | + | ||
| 35 | +std::string SpekeEntity::GetDeviceName() const | ||
| 36 | +{ | ||
| 37 | + return deviceName_; | ||
| 38 | +} | ||
| 39 | + | ||
| 40 | +void SpekeEntity::SetDeviceName(const std::string& deviceName) | ||
| 41 | +{ | ||
| 42 | + deviceName_ = deviceName; | ||
| 43 | +} | ||
| 44 | + | ||
| 45 | +int32_t SpekeEntity::GetDeviceType() const | ||
| 46 | +{ | ||
| 47 | + return deviceType_; | ||
| 48 | +} | ||
| 49 | + | ||
| 50 | +void SpekeEntity::SetDeviceType(int32_t deviceType) | ||
| 51 | +{ | ||
| 52 | + deviceType_ = deviceType; | ||
| 53 | +} | ||
| 54 | + | ||
| 55 | +std::vector<uint8_t> SpekeEntity::GetDeviceUuid() const | ||
| 56 | +{ | ||
| 57 | + return deviceUuid_; | ||
| 58 | +} | ||
| 59 | + | ||
| 60 | +void SpekeEntity::SetDeviceUuid(const std::vector<uint8_t>& uuid) | ||
| 61 | +{ | ||
| 62 | + deviceUuid_ = uuid; | ||
| 63 | +} | ||
| 64 | + | ||
| 65 | +} // namespace IotcManagement | ||
| 66 | +} // namespace OHOS | ||
| @@ -0,0 +1,53 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | +namespace OHOS { | ||
| 24 | +namespace IotcManagement { | ||
| 25 | + | ||
| 26 | +class SpekeEntity { | ||
| 27 | +public: | ||
| 28 | + SpekeEntity(); | ||
| 29 | + ~SpekeEntity() = default; | ||
| 30 | + | ||
| 31 | + std::string GetDeviceId() const; | ||
| 32 | + void SetDeviceId(const std::string& deviceId); | ||
| 33 | + | ||
| 34 | + std::string GetDeviceName() const; | ||
| 35 | + void SetDeviceName(const std::string& deviceName); | ||
| 36 | + | ||
| 37 | + int32_t GetDeviceType() const; | ||
| 38 | + void SetDeviceType(int32_t deviceType); | ||
| 39 | + | ||
| 40 | + std::vector<uint8_t> GetDeviceUuid() const; | ||
| 41 | + void SetDeviceUuid(const std::vector<uint8_t>& uuid); | ||
| 42 | + | ||
| 43 | +private: | ||
| 44 | + std::string deviceId_; | ||
| 45 | + std::string deviceName_; | ||
| 46 | + int32_t deviceType_; | ||
| 47 | + std::vector<uint8_t> deviceUuid_; | ||
| 48 | +}; | ||
| 49 | + | ||
| 50 | +} // namespace IotcManagement | ||
| 51 | +} // namespace OHOS | ||
| 52 | + | ||
| 53 | + | ||
| @@ -0,0 +1,72 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | +namespace OHOS { | ||
| 20 | +namespace IotcManagement { | ||
| 21 | + | ||
| 22 | +SpekeRequest::SpekeRequest() : protocolType_(0), protocolVersion_(CommonConstants::PROTOCOL_VERSION_V1) | ||
| 23 | +{ | ||
| 24 | +} | ||
| 25 | + | ||
| 26 | +int32_t SpekeRequest::GetStrategy() const | ||
| 27 | +{ | ||
| 28 | + return 0; | ||
| 29 | +} | ||
| 30 | + | ||
| 31 | +std::string SpekeRequest::GetDeviceId() const | ||
| 32 | +{ | ||
| 33 | + return deviceId_; | ||
| 34 | +} | ||
| 35 | + | ||
| 36 | +void SpekeRequest::SetDeviceId(const std::string& deviceId) | ||
| 37 | +{ | ||
| 38 | + deviceId_ = deviceId; | ||
| 39 | +} | ||
| 40 | + | ||
| 41 | +std::string SpekeRequest::GetPinCode() const | ||
| 42 | +{ | ||
| 43 | + return pinCode_; | ||
| 44 | +} | ||
| 45 | + | ||
| 46 | +void SpekeRequest::SetPinCode(const std::string& pinCode) | ||
| 47 | +{ | ||
| 48 | + pinCode_ = pinCode; | ||
| 49 | +} | ||
| 50 | + | ||
| 51 | +int32_t SpekeRequest::GetProtocolType() const | ||
| 52 | +{ | ||
| 53 | + return protocolType_; | ||
| 54 | +} | ||
| 55 | + | ||
| 56 | +void SpekeRequest::SetProtocolType(int32_t protocolType) | ||
| 57 | +{ | ||
| 58 | + protocolType_ = protocolType; | ||
| 59 | +} | ||
| 60 | + | ||
| 61 | +uint32_t SpekeRequest::GetProtocolVersion() const | ||
| 62 | +{ | ||
| 63 | + return protocolVersion_; | ||
| 64 | +} | ||
| 65 | + | ||
| 66 | +void SpekeRequest::SetProtocolVersion(uint32_t protocolVersion) | ||
| 67 | +{ | ||
| 68 | + protocolVersion_ = protocolVersion; | ||
| 69 | +} | ||
| 70 | + | ||
| 71 | +} // namespace IotcManagement | ||
| 72 | +} // namespace OHOS | ||
| @@ -0,0 +1,67 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | +namespace OHOS { | ||
| 25 | +namespace IotcManagement { | ||
| 26 | + | ||
| 27 | +enum class SpekeRequestType : int32_t { | ||
| 28 | + ADAPTER_BLE = 0, | ||
| 29 | + ADAPTER_COAP = 1 | ||
| 30 | +}; | ||
| 31 | + | ||
| 32 | +class SpekeRequest { | ||
| 33 | +public: | ||
| 34 | + SpekeRequest(); | ||
| 35 | + virtual ~SpekeRequest() = default; | ||
| 36 | + | ||
| 37 | + virtual SpekeRequestType GetType() const = 0; | ||
| 38 | + | ||
| 39 | + int32_t GetStrategy() const; | ||
| 40 | + | ||
| 41 | + std::string GetDeviceId() const; | ||
| 42 | + void SetDeviceId(const std::string& deviceId); | ||
| 43 | + | ||
| 44 | + std::string GetPinCode() const; | ||
| 45 | + void SetPinCode(const std::string& pinCode); | ||
| 46 | + | ||
| 47 | + int32_t GetProtocolType() const; | ||
| 48 | + void SetProtocolType(int32_t protocolType); | ||
| 49 | + | ||
| 50 | + /** | ||
| 51 | + * @brief 广播协议版本号 (PROTOCOL_VERSION_V1=DL, PROTOCOL_VERSION_V2=EC)。 | ||
| 52 | + * 默认 V1 以保持向后兼容。 | ||
| 53 | + */ | ||
| 54 | + uint32_t GetProtocolVersion() const; | ||
| 55 | + void SetProtocolVersion(uint32_t protocolVersion); | ||
| 56 | + | ||
| 57 | +private: | ||
| 58 | + std::string deviceId_; | ||
| 59 | + std::string pinCode_; | ||
| 60 | + int32_t protocolType_; | ||
| 61 | + uint32_t protocolVersion_; | ||
| 62 | +}; | ||
| 63 | + | ||
| 64 | +} // namespace IotcManagement | ||
| 65 | +} // namespace OHOS | ||
| 66 | + | ||
| 67 | + | ||
| @@ -0,0 +1,76 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | + | ||
| 26 | + | ||
| 27 | + | ||
| 28 | + | ||
| 29 | + | ||
| 30 | +namespace OHOS { | ||
| 31 | +namespace IotcManagement { | ||
| 32 | + | ||
| 33 | +std::shared_ptr<SpekeTransferLayer> SpekeTransferFactory::GetSpekeTransferLayer( | ||
| 34 | + std::shared_ptr<SpekeRequest> spekeRequest, std::shared_ptr<AdvBleRequest> request) | ||
| 35 | +{ | ||
| 36 | + if (!spekeRequest) { | ||
| 37 | + IOTC_LOGW("SpekeTransferFactory::GetSpekeTransferLayer spekeRequest is null"); | ||
| 38 | + return nullptr; | ||
| 39 | + } | ||
| 40 | + | ||
| 41 | + auto reqType = spekeRequest->GetType(); | ||
| 42 | + switch (reqType) { | ||
| 43 | + case SpekeRequestType::ADAPTER_BLE: { | ||
| 44 | + | ||
| 45 | + auto bleReq = std::static_pointer_cast<SpekeRequestOverAdvBle>(spekeRequest); | ||
| 46 | + if (!bleReq || !request) { | ||
| 47 | + IOTC_LOGW("AdvBle request cast failed or request is null"); | ||
| 48 | + return nullptr; | ||
| 49 | + } | ||
| 50 | + return std::make_shared<SpekeTransferOverAdvBle>(bleReq, request); | ||
| 51 | + | ||
| 52 | + (void)request; | ||
| 53 | + IOTC_LOGW("BLE transport is disabled"); | ||
| 54 | + return nullptr; | ||
| 55 | + | ||
| 56 | + } | ||
| 57 | + | ||
| 58 | + | ||
| 59 | + case SpekeRequestType::ADAPTER_COAP: { | ||
| 60 | + auto coapReq = std::static_pointer_cast<SpekeRequestOverCoap>(spekeRequest); | ||
| 61 | + if (!coapReq) { | ||
| 62 | + IOTC_LOGW("Coap request cast failed"); | ||
| 63 | + return nullptr; | ||
| 64 | + } | ||
| 65 | + return std::make_shared<SpeckTransferOverCoap>(coapReq); | ||
| 66 | + } | ||
| 67 | + | ||
| 68 | + default: | ||
| 69 | + IOTC_LOGW("unknown speke request type: %{public}d", static_cast<int>(reqType)); | ||
| 70 | + break; | ||
| 71 | + } | ||
| 72 | + return nullptr; | ||
| 73 | +} | ||
| 74 | + | ||
| 75 | +} // namespace IotcManagement | ||
| 76 | +} // namespace OHOS | ||
| @@ -0,0 +1,52 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | +namespace OHOS { | ||
| 25 | +namespace IotcManagement { | ||
| 26 | + | ||
| 27 | +class AdvBleRequest; | ||
| 28 | + | ||
| 29 | +class SpekeTransferFactory { | ||
| 30 | +public: | ||
| 31 | + /** | ||
| 32 | + * 获取对应类型的传出层 | ||
| 33 | + * | ||
| 34 | + * @param spekeRequest 请求参数 | ||
| 35 | + * @param request 增强蓝牙请求数据 | ||
| 36 | + * @return 传输层对象 | ||
| 37 | + */ | ||
| 38 | + static std::shared_ptr<SpekeTransferLayer> GetSpekeTransferLayer(std::shared_ptr<SpekeRequest> spekeRequest, | ||
| 39 | + std::shared_ptr<AdvBleRequest> request); | ||
| 40 | + | ||
| 41 | +private: | ||
| 42 | + SpekeTransferFactory() = default; | ||
| 43 | + ~SpekeTransferFactory() = default; | ||
| 44 | + | ||
| 45 | + SpekeTransferFactory(const SpekeTransferFactory&) = delete; | ||
| 46 | + SpekeTransferFactory& operator=(const SpekeTransferFactory&) = delete; | ||
| 47 | +}; | ||
| 48 | + | ||
| 49 | +} // namespace IotcManagement | ||
| 50 | +} // namespace OHOS | ||
| 51 | + | ||
| 52 | + | ||
| @@ -0,0 +1,41 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | +namespace OHOS { | ||
| 23 | +namespace IotcManagement { | ||
| 24 | + | ||
| 25 | +class SpekeTransferLayer { | ||
| 26 | +public: | ||
| 27 | + virtual ~SpekeTransferLayer() = default; | ||
| 28 | + | ||
| 29 | + /** | ||
| 30 | + * 发送数据 | ||
| 31 | + * | ||
| 32 | + * @param sendData 待发送数据 | ||
| 33 | + * @param callback 发送回调函数 | ||
| 34 | + */ | ||
| 35 | + virtual void Send(const std::string& sendData, std::shared_ptr<TransferResponseCallback> callback) = 0; | ||
| 36 | +}; | ||
| 37 | + | ||
| 38 | +} // namespace IotcManagement | ||
| 39 | +} // namespace OHOS | ||
| 40 | + | ||
| 41 | + | ||
| @@ -0,0 +1,49 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | +namespace OHOS { | ||
| 22 | +namespace IotcManagement { | ||
| 23 | + | ||
| 24 | +class GlobalParams { | ||
| 25 | +public: | ||
| 26 | + static constexpr uint32_t SPEKE_CHALLENGE_LENGTH = 16; | ||
| 27 | + static constexpr uint32_t SPEKE_SECRET_LENGTH = 32; | ||
| 28 | + static constexpr uint32_t SPEKE_SECRET_LENGTH_256_MOD = 28; | ||
| 29 | + static constexpr uint32_t SPEKE_PUBLIC_LENGTH_256_MOD = 256; | ||
| 30 | + static constexpr uint32_t SPEKE_PUBLIC_LENGTH_384_MOD = 384; | ||
| 31 | + /** | ||
| 32 | + * EC SPEKE 协商使用 X25519。 secret 派生后扩展为 96B 后再做 hash2point。 | ||
| 33 | + */ | ||
| 34 | + static constexpr uint32_t PAKE_SECRET_LENGTH_EC = 96; | ||
| 35 | + static constexpr uint32_t PAKE_PUBLIC_BYTE_LEN_EC = 32; | ||
| 36 | + static constexpr uint32_t PAKE_PBKDF2_DEFAULT_ITER = 10000; | ||
| 37 | + static constexpr uint32_t SESSION_KEY_LENGTH = 16; | ||
| 38 | + static constexpr uint32_t HKDF_SALT_LENGTH = 16; | ||
| 39 | + static constexpr uint32_t HMAC_BLOCK_SIZE = 32; | ||
| 40 | + static constexpr uint32_t AKA_TIMEOUT = 15000; | ||
| 41 | + static constexpr uint32_t BIND_TIMEOUT = 15000; | ||
| 42 | + static constexpr uint32_t MAX_KEY_LEN = 1024; | ||
| 43 | + static constexpr uint32_t MPI_RADIX = 16; | ||
| 44 | +}; | ||
| 45 | + | ||
| 46 | +} // namespace IotcManagement | ||
| 47 | +} // namespace OHOS | ||
| 48 | + | ||
| 49 | + | ||
| @@ -0,0 +1,31 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | +namespace OHOS { | ||
| 20 | +namespace IotcManagement { | ||
| 21 | + | ||
| 22 | +enum IdentityType { | ||
| 23 | + UNKNOWN = -1, | ||
| 24 | + USER = 0, | ||
| 25 | + DEVICE = 1, | ||
| 26 | +}; | ||
| 27 | + | ||
| 28 | +} // namespace IotcManagement | ||
| 29 | +} // namespace OHOS | ||
| 30 | + | ||
| 31 | + | ||
| @@ -0,0 +1,36 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | +namespace OHOS { | ||
| 22 | +namespace IotcManagement { | ||
| 23 | + | ||
| 24 | +class MessageCode { | ||
| 25 | +public: | ||
| 26 | + static constexpr uint16_t INFORM_MESSAGE = 0x8080; | ||
| 27 | + static constexpr uint16_t SPEKE_REQUEST = 0x0001; | ||
| 28 | + static constexpr uint16_t SPEKE_RESPONSE = 0x8001; | ||
| 29 | + static constexpr uint16_t SPEKE_CLIENT_CONFIRM = 0x0002; | ||
| 30 | + static constexpr uint16_t SPEKE_SERVER_CONFIRM = 0x8002; | ||
| 31 | +}; | ||
| 32 | + | ||
| 33 | +} // namespace IotcManagement | ||
| 34 | +} // namespace OHOS | ||
| 35 | + | ||
| 36 | + | ||
| @@ -0,0 +1,33 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | +namespace OHOS { | ||
| 22 | +namespace IotcManagement { | ||
| 23 | + | ||
| 24 | +class OperationCode { | ||
| 25 | +public: | ||
| 26 | + static constexpr int32_t UNKNOWN = -1; | ||
| 27 | + static constexpr int32_t AUTH_KEY_AGREEMENT = 6; | ||
| 28 | +}; | ||
| 29 | + | ||
| 30 | +} // namespace IotcManagement | ||
| 31 | +} // namespace OHOS | ||
| 32 | + | ||
| 33 | + | ||
| @@ -0,0 +1,94 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | +namespace OHOS { | ||
| 20 | +namespace IotcManagement { | ||
| 21 | + | ||
| 22 | +class ReturnCode { | ||
| 23 | +public: | ||
| 24 | + /** 操作成功 */ | ||
| 25 | + static constexpr int32_t SUCCESS = 0x00000000; | ||
| 26 | + | ||
| 27 | + /** 操作失败 */ | ||
| 28 | + static constexpr int32_t FAILED = 0x00000001; | ||
| 29 | + | ||
| 30 | + /** 请求冲突,存在相同会话ID的正在进行中的请求 */ | ||
| 31 | + static constexpr int32_t CONFLICT_REQUEST = 0x80000001; | ||
| 32 | + | ||
| 33 | + /** 请求已取消 */ | ||
| 34 | + static constexpr int32_t CANCELED = 0x80000002; | ||
| 35 | + | ||
| 36 | + /** 请求不存在或已结束 */ | ||
| 37 | + static constexpr int32_t REQUEST_NOT_FOUND = 0x80000003; | ||
| 38 | + | ||
| 39 | + /** 请求被拒绝 */ | ||
| 40 | + static constexpr int32_t REQUEST_REJECTED = 0x80000005; | ||
| 41 | + | ||
| 42 | + /** 请求已被接受 */ | ||
| 43 | + static constexpr int32_t REQUEST_ACCEPTED = 0x80000006; | ||
| 44 | + | ||
| 45 | + /** PIN码错误 */ | ||
| 46 | + static constexpr int32_t PIN_ERROR = 0x0F000011; | ||
| 47 | + | ||
| 48 | + /** PIN码错误已达最大次数,已锁定 */ | ||
| 49 | + static constexpr int32_t PIN_ERROR_LOCK = 0x00004006; | ||
| 50 | + | ||
| 51 | + /** 未知错误 */ | ||
| 52 | + static constexpr int32_t UNKNOWN = 0xF0000000; | ||
| 53 | + | ||
| 54 | + /** 参数无效 */ | ||
| 55 | + static constexpr int32_t INVALID_PARAMETERS = 0xF0000001; | ||
| 56 | + | ||
| 57 | + /** 操作超时 */ | ||
| 58 | + static constexpr int32_t TIMEOUT = 0xF0000003; | ||
| 59 | + | ||
| 60 | + /** 连接中断 */ | ||
| 61 | + static constexpr int32_t CONNECTION_INTERRUPTED = 0xF0000009; | ||
| 62 | + | ||
| 63 | + /** 不支持的协议版本 */ | ||
| 64 | + static constexpr int32_t UNSUPPORTED_VERSION = 0xF000000A; | ||
| 65 | + | ||
| 66 | + /** 载荷格式错误 */ | ||
| 67 | + static constexpr int32_t BAD_PAYLOAD = 0xF000000B; | ||
| 68 | + | ||
| 69 | + /** 不支持的算法 */ | ||
| 70 | + static constexpr int32_t ALGORITHM_UNSUPPORTED = 0xF000000C; | ||
| 71 | + | ||
| 72 | + /** 对端未知 */ | ||
| 73 | + static constexpr int32_t PEER_UNKNOWN = 0xFF000000; | ||
| 74 | + | ||
| 75 | + /** 对端参数无效 */ | ||
| 76 | + static constexpr int32_t PEER_INVALID_PARAMETERS = 0xFF000001; | ||
| 77 | + | ||
| 78 | + /** 对端超时 */ | ||
| 79 | + static constexpr int32_t PEER_TIMEOUT = 0xFF000003; | ||
| 80 | + | ||
| 81 | + /** 对端载荷错误 */ | ||
| 82 | + static constexpr int32_t PEER_BAD_PAYLOAD = 0xFF00000B; | ||
| 83 | + | ||
| 84 | + /** 对端不支持该算法 */ | ||
| 85 | + static constexpr int32_t PEER_ALGORITHM_UNSUPPORTED = 0xFF00000C; | ||
| 86 | + | ||
| 87 | + /** 未初始化 */ | ||
| 88 | + static constexpr int32_t NOT_INIT = 0xFFFFFFFF; | ||
| 89 | +}; | ||
| 90 | + | ||
| 91 | +} // namespace IotcManagement | ||
| 92 | +} // namespace OHOS | ||
| 93 | + | ||
| 94 | + | ||
| @@ -0,0 +1,42 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | +namespace OHOS { | ||
| 22 | +namespace IotcManagement { | ||
| 23 | + | ||
| 24 | +enum SpekeType { | ||
| 25 | + /** | ||
| 26 | + * SPAKE协商使用256位素数(受限设备使用) | ||
| 27 | + */ | ||
| 28 | + SPEKE_256, | ||
| 29 | + /** | ||
| 30 | + * SPAKE协商使用384位素数(非受限设备使用) | ||
| 31 | + */ | ||
| 32 | + SPEKE_384, | ||
| 33 | + /** | ||
| 34 | + * EC SPEKE: 使用 X25519 + Elligator2 hash2point(统一互联3.0) | ||
| 35 | + */ | ||
| 36 | + SPEKE_EC, | ||
| 37 | +}; | ||
| 38 | + | ||
| 39 | +} // namespace IotcManagement | ||
| 40 | +} // namespace OHOS | ||
| 41 | + | ||
| 42 | + | ||
| @@ -0,0 +1,42 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | +namespace OHOS { | ||
| 22 | +namespace IotcManagement { | ||
| 23 | + | ||
| 24 | +class UserType { | ||
| 25 | +public: | ||
| 26 | + enum class Type : int32_t { | ||
| 27 | + ACCESSORY = 0, // 设备 | ||
| 28 | + CONTROLLER = 1 // 控制方,比如App | ||
| 29 | + }; | ||
| 30 | + | ||
| 31 | + static bool ValidUserType(int32_t userType) | ||
| 32 | + { | ||
| 33 | + // 范围校验:枚举连续从0开始,直接判断区间 | ||
| 34 | + return userType >= static_cast<int32_t>(Type::ACCESSORY) && | ||
| 35 | + userType <= static_cast<int32_t>(Type::CONTROLLER); | ||
| 36 | + } | ||
| 37 | +}; | ||
| 38 | + | ||
| 39 | +} // namespace IotcManagement | ||
| 40 | +} // namespace OHOS | ||
| 41 | + | ||
| 42 | + | ||