已开启
feat(home_base): SPEKE安全认证 DB数据存储 #26
祝你好运创建于 19 天前
feat(home_base): SPEKE安全认证 DB数据存储 #26
已开启
祝你好运创建于 19 天前
97 个文件变更+9265-50
Acore/home_base/db/iot_device_info_cache.cpp+137-0
@@ -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+#include "iot_device_info_cache.h"
17+#include "iot_device_info_manager.h"
18+#include "iot_coap_session_entity.h"
19+#include "iotc_log.h"
20+#include "iotc_constants.h"
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
Acore/home_base/db/iot_device_info_cache.h+59-0
@@ -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+#ifndef IOT_DEVICE_INFO_CACHE_H
17+#define IOT_DEVICE_INFO_CACHE_H
18+ 
19+#include <string>
20+#include <memory>
21+#include <vector>
22+#include <map>
23+#include "iot_deviceInfo_table.h"
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+#endif // IOT_DEVICE_INFO_CACHE_H
Acore/home_base/db/iot_device_info_manager.cpp+98-0
@@ -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+#include "iot_device_info_manager.h"
17+#include "iot_connect_db.h"
18+#include "iotc_log.h"
19+#include "iotc_constants.h"
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
Acore/home_base/db/iot_device_info_manager.h+43-0
@@ -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+#ifndef IOT_DEVICE_INFO_MANAGER_H
17+#define IOT_DEVICE_INFO_MANAGER_H
18+ 
19+#include <string>
20+#include <memory>
21+#include <vector>
22+#include "iot_deviceInfo_table.h"
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+#endif // IOT_DEVICE_INFO_MANAGER_H
Acore/home_base/db/strage/iot_connect_db.cpp+76-0
@@ -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+#include "iot_connect_db.h"
16+#include "kv_storage.h"
17+#include "iot_deviceInfo_table.h"
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
Acore/home_base/db/strage/iot_connect_db.h+61-0
@@ -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+#ifndef IOT_CONNECT_DB_H
16+#define IOT_CONNECT_DB_H
17+ 
18+#include <vector>
19+#include <string>
20+#include <memory>
21+#include <cstdint>
22+#include <unordered_map>
23+#include <mutex>
24+#include "storage_base.h"
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+#endif
Acore/home_base/db/strage/rdb_storage.cpp+88-0
@@ -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+#include "rdb_storage.h"
16+#include "iot_deviceInfo_table.h"
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
Acore/home_base/db/strage/rdb_storage.h+45-0
@@ -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+#ifndef RDB_STORAGE_H
16+#define RDB_STORAGE_H
17+ 
18+#include "storage_base.h"
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+#endif
Acore/home_base/db/strage/storage_base.h+58-0
@@ -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+#ifndef STORAGE_BASE_H
16+#define STORAGE_BASE_H
17+ 
18+#include <vector>
19+#include <string>
20+#include <memory>
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+#endif
Acore/home_base/db/table/iot_deviceInfo_table.cpp+118-0
@@ -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+#include "iot_deviceInfo_table.h"
17+#include "iotc_json_object.h"
18+#include "iotc_log.h"
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
Acore/home_base/db/table/iot_deviceInfo_table.h+62-0
@@ -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+#ifndef IOT_DEVICE_INFO_TABLE_H
17+#define IOT_DEVICE_INFO_TABLE_H
18+ 
19+#include <string>
20+#include <memory>
21+#include "storage_base.h"
22+#include "iot_coap_session_entity.h"
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+#endif // IOT_DEVICE_INFO_TABLE_H
Acore/home_base/speke/adapter/speke_message_cryptor.h+45-0
@@ -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+#ifndef SPEKE_MESSAGE_CRYPTOR_H
17+#define SPEKE_MESSAGE_CRYPTOR_H
18+ 
19+#include <vector>
20+#include <cstdint>
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+#endif // SPEKE_MESSAGE_CRYPTOR_H
Acore/home_base/speke/adapter/speke_message_hmacor.h+37-0
@@ -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+#ifndef SPEKE_MESSAGE_HMACOR_H
17+#define SPEKE_MESSAGE_HMACOR_H
18+ 
19+#include <vector>
20+#include <cstdint>
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+#endif // SPEKE_MESSAGE_HMACOR_H
Acore/home_base/speke/adapter/speke_negotiate_adapter.cpp+300-0
@@ -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+#include <string>
17+#include "speke_negotiate_adapter.h"
18+#include "iotc_log.h"
19+#include "iotc_constants.h"
20+#include "iotc_json_object.h"
21+#include "e2e_security_api.h"
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
Acore/home_base/speke/adapter/speke_negotiate_adapter.h+109-0
@@ -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+#ifndef SPEKE_NEGOTIATE_ADAPTER_H
17+#define SPEKE_NEGOTIATE_ADAPTER_H
18+ 
19+#include <string>
20+#include <memory>
21+#include <vector>
22+#include <cstdint>
23+#include <atomic>
24+#include <mutex>
25+#include "iotc_constants.h"
26+#include "speke_callback.h"
27+#include "speke_transfer_layer.h"
28+#include "speke_request.h"
29+#include "speke_entity.h"
30+#include "speke_negotiate_callback.h"
31+#include "security_cipher.h"
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+#endif // SPEKE_NEGOTIATE_ADAPTER_H
Acore/home_base/speke/adapter/speke_negotiate_manager.cpp+138-0
@@ -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+#include "speke_negotiate_manager.h"
17+#include "speke_transfer_factory.h"
18+#include "iotc_log.h"
19+#include "iotc_constants.h"
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
Acore/home_base/speke/adapter/speke_negotiate_manager.h+88-0
@@ -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+#ifndef SPEKE_NEGOTIATE_MANAGER_H
17+#define SPEKE_NEGOTIATE_MANAGER_H
18+ 
19+#include <string>
20+#include <memory>
21+#include <mutex>
22+#include <vector>
23+#include <cstdint>
24+#include "speke_negotiate_adapter.h"
25+#include "speke_callback.h"
26+#include "speke_request.h"
27+#include "speke_entity.h"
28+#include "speke_message_cryptor.h"
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+#endif // SPEKE_NEGOTIATE_MANAGER_H
Acore/home_base/speke/callback/speke_callback.h+66-0
@@ -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+#ifndef SPEKE_CALLBACK_H
17+#define SPEKE_CALLBACK_H
18+ 
19+#include <cstdint>
20+#include <string>
21+#include <functional>
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+#endif // SPEKE_CALLBACK_H
Acore/home_base/speke/callback/speke_negotiate_callback.h+92-0
@@ -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+#ifndef SPEKE_NEGOTIATE_CALLBACK_H
17+#define SPEKE_NEGOTIATE_CALLBACK_H
18+ 
19+#include <cstdint>
20+#include <functional>
21+#include <memory>
22+#include <string>
23+#include "security_cipher.h"
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+#endif // SPEKE_NEGOTIATE_CALLBACK_H
Acore/home_base/speke/entity/configured_version_info.cpp+52-0
@@ -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+#include "configured_version_info.h"
17+#include "iotc_constants.h"
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
Acore/home_base/speke/entity/configured_version_info.h+45-0
@@ -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+#ifndef CONFIGURED_VERSION_INFO_H
17+#define CONFIGURED_VERSION_INFO_H
18+ 
19+#include <string>
20+#include <vector>
21+#include "iotc_constants.h"
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+#endif // CONFIGURED_VERSION_INFO_H
Acore/home_base/speke/entity/confirm_params.cpp+62-0
@@ -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+#include "confirm_params.h"
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
Acore/home_base/speke/entity/confirm_params.h+51-0
@@ -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+#ifndef CONFIRM_PARAMS_H
17+#define CONFIRM_PARAMS_H
18+ 
19+#include <string>
20+#include <cstdint>
21+#include "iotc_constants.h"
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+#endif // CONFIRM_PARAMS_H
Acore/home_base/speke/entity/identity_info.cpp+101-0
@@ -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+#include "identity_info.h"
17+#include "iotc_log.h"
18+#include "iotc_md.h"
19+#include "iotc_constants.h"
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
Acore/home_base/speke/entity/identity_info.h+58-0
@@ -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+#ifndef IDENTITY_INFO_H
17+#define IDENTITY_INFO_H
18+ 
19+#include <string>
20+#include <vector>
21+#include <cstdint>
22+#include "identity_type.h"
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+#endif // IDENTITY_INFO_H
Acore/home_base/speke/entity/message_config.cpp+59-0
@@ -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+#ifndef MESSAGE_CONFIG_CPP
17+#define MESSAGE_CONFIG_CPP
18+ 
19+#include "message_config.h"
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+#endif // MESSAGE_CONFIG_CPP
Acore/home_base/speke/entity/message_config.h+47-0
@@ -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+#ifndef MESSAGE_CONFIG_H
17+#define MESSAGE_CONFIG_H
18+ 
19+#include <cstdint>
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+#endif // MESSAGE_CONFIG_H
Acore/home_base/speke/entity/operation_parameter.cpp+109-0
@@ -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+#include "operation_parameter.h"
17+#include "iotc_log.h"
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
Acore/home_base/speke/entity/operation_parameter.h+82-0
@@ -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+#ifndef OPERATION_PARAMETER_H
17+#define OPERATION_PARAMETER_H
18+ 
19+#include <string>
20+#include <vector>
21+#include <memory>
22+#include <cstdint>
23+#include "iotc_constants.h"
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+#endif // OPERATION_PARAMETER_H
Acore/home_base/speke/entity/parameter_builder.cpp+73-0
@@ -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+#include "parameter_builder.h"
17+#include "iotc_log.h"
18+#include "iotc_md.h"
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
Acore/home_base/speke/entity/parameter_builder.h+49-0
@@ -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+#ifndef PARAMETER_BUILDER_H
17+#define PARAMETER_BUILDER_H
18+ 
19+#include <string>
20+#include <memory>
21+#include "operation_parameter.h"
22+#include "identity_info.h"
23+#include "iotc_constants.h"
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+#endif // PARAMETER_BUILDER_H
Acore/home_base/speke/entity/pass_through_data.cpp+277-0
@@ -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+#include "pass_through_data.h"
17+#include "iotc_log.h"
18+#include "security_adapter.h"
19+#include "operation_code.h"
20+#include "message_code.h"
21+#include "common_util.h"
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
Acore/home_base/speke/entity/pass_through_data.h+73-0
@@ -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+#ifndef PASS_THROUGH_DATA_H
17+#define PASS_THROUGH_DATA_H
18+ 
19+#include <string>
20+#include <vector>
21+#include <memory>
22+#include "iotc_json_object.h"
23+#include "identity_info.h"
24+#include "iotc_constants.h"
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+#endif // PASS_THROUGH_DATA_H
Acore/home_base/speke/entity/payload_response.cpp+80-0
@@ -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+#include "payload_response.h"
17+#include "iotc_json_object.h"
18+#include "iotc_constants.h"
19+#include <map>
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
Acore/home_base/speke/entity/payload_response.h+51-0
@@ -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+#ifndef PAYLOAD_RESPONSE_H
17+#define PAYLOAD_RESPONSE_H
18+ 
19+#include <string>
20+#include <vector>
21+#include <cstdint>
22+#include "version_info.h"
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+#endif // PAYLOAD_RESPONSE_H
Acore/home_base/speke/entity/version_info.cpp+107-0
@@ -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+#include "version_info.h"
17+#include "iotc_log.h"
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
Acore/home_base/speke/entity/version_info.h+60-0
@@ -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+#ifndef VERSION_INFO_H
17+#define VERSION_INFO_H
18+ 
19+#include <string>
20+#include <vector>
21+#include <map>
22+#include "iotc_constants.h"
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+#endif // VERSION_INFO_H
Acore/home_base/speke/request/auth_key_agree_request.cpp+76-0
@@ -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+#include "auth_key_agree_request.h"
17+#include "iotc_log.h"
18+#include "operation_code.h"
19+#include "speke_task.h"
20+#include "request_status.h"
21+#include "global_params.h"
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
Acore/home_base/speke/request/auth_key_agree_request.h+43-0
@@ -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+#ifndef AUTH_KEY_AGREE_REQUEST_H
17+#define AUTH_KEY_AGREE_REQUEST_H
18+ 
19+#include <memory>
20+#include "request_base.h"
21+#include "speke_task.h"
22+#include "confirm_params.h"
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+#endif // AUTH_KEY_AGREE_REQUEST_H
Acore/home_base/speke/request/request_base.cpp+287-0
@@ -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+#include "request_base.h"
17+#include "iotc_log.h"
18+#include "global_params.h"
19+#include "return_code.h"
20+#include "request_manager.h"
21+#include "speke_task.h"
22+#include "iotc_json_object.h"
23+#include "iotc_constants.h"
24+#include "common_util.h"
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
Acore/home_base/speke/request/request_base.h+87-0
@@ -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+#ifndef REQUEST_BASE_H
17+#define REQUEST_BASE_H
18+ 
19+#include <string>
20+#include <vector>
21+#include <memory>
22+#include <functional>
23+#include <atomic>
24+#include "task_feedback.h"
25+#include "status_base.h"
26+#include "operation_parameter.h"
27+#include "delayed_timer.h"
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+#endif // REQUEST_BASE_H
Acore/home_base/speke/request/request_manager.cpp+82-0
@@ -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+#include "request_manager.h"
17+#include "request_base.h"
18+#include "iotc_log.h"
19+#include "return_code.h"
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
Acore/home_base/speke/request/request_manager.h+54-0
@@ -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+#ifndef REQUEST_MANAGER_H
17+#define REQUEST_MANAGER_H
18+ 
19+#include <string>
20+#include <map>
21+#include <memory>
22+#include <mutex>
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+#endif // REQUEST_MANAGER_H
Acore/home_base/speke/request/request_status.cpp+47-0
@@ -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+#include "request_status.h"
17+#include "iotc_log.h"
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
Acore/home_base/speke/request/request_status.h+35-0
@@ -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+#ifndef REQUEST_STATUS_H
17+#define REQUEST_STATUS_H
18+ 
19+#include <string>
20+#include "status_base.h"
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+#endif // REQUEST_STATUS_H
Acore/home_base/speke/request/speke_task.cpp+506-0
@@ -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+#include "speke_task.h"
17+#include "iotc_log.h"
18+#include "common_util.h"
19+#include "return_code.h"
20+#include "message_code.h"
21+#include "operation_code.h"
22+#include "iotc_constants.h"
23+#include "crypto_random.h"
24+#include "crypto_kdf.h"
25+#include "iotc_x25519.h"
26+#include "iotc_kdf.h"
27+#include "global_params.h"
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
Acore/home_base/speke/request/speke_task.h+87-0
@@ -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+#ifndef SPEKE_TASK_H
17+#define SPEKE_TASK_H
18+ 
19+#include <string>
20+#include <vector>
21+#include <memory>
22+#include "task_base.h"
23+#include "speke_task_status.h"
24+#include "operation_parameter.h"
25+#include "task_feedback.h"
26+#include "speke_utils.h"
27+#include "payload_response.h"
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+#endif // SPEKE_TASK_H
Acore/home_base/speke/request/speke_task_status.cpp+58-0
@@ -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+#include "speke_task_status.h"
17+#include "iotc_log.h"
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
Acore/home_base/speke/request/speke_task_status.h+40-0
@@ -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+#ifndef SPEKE_TASK_STATUS_H
17+#define SPEKE_TASK_STATUS_H
18+ 
19+#include "status_base.h"
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+#endif // SPEKE_TASK_STATUS_H
Acore/home_base/speke/request/status_base.cpp+59-0
@@ -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+#include "status_base.h"
17+#include "iotc_log.h"
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
Acore/home_base/speke/request/status_base.h+59-0
@@ -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+#ifndef STATUS_BASE_H
17+#define STATUS_BASE_H
18+ 
19+#include <cstdint>
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+#endif // STATUS_BASE_H
Acore/home_base/speke/request/task_base.cpp+364-0
@@ -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+#include "task_base.h"
17+#include "task_timer.h"
18+#include "return_code.h"
19+#include "cJSON.h"
20+#include "iotc_constants.h"
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
Acore/home_base/speke/request/task_base.h+125-0
@@ -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+#ifndef TASK_BASE_H
17+#define TASK_BASE_H
18+ 
19+#include <string>
20+#include <vector>
21+#include <memory>
22+#include <functional>
23+#include <map>
24+#include <thread>
25+#include <mutex>
26+#include <atomic>
27+#include "status_base.h"
28+#include "task_feedback.h"
29+#include "operation_parameter.h"
30+#include "version_info.h"
31+#include "configured_version_info.h"
32+#include "global_params.h"
33+#include "message_code.h"
34+#include "security_adapter.h"
35+#include "message_config.h"
36+#include "iotc_json_object.h"
37+#include "common_util.h"
38+#include "iotc_log.h"
39+#include "payload_response.h"
40+#include "task_timer.h"
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+#endif // TASK_BASE_H
Acore/home_base/speke/request/task_feedback.h+65-0
@@ -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+#ifndef TASK_FEEDBACK_H
17+#define TASK_FEEDBACK_H
18+ 
19+#include <string>
20+#include <vector>
21+#include <functional>
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+#endif // TASK_FEEDBACK_H
Acore/home_base/speke/request/task_timer.cpp+128-0
@@ -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+#include "task_timer.h"
17+#include "iotc_log.h"
18+#include "task_base.h"
19+#include "message_code.h"
20+#include "common_util.h"
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
Acore/home_base/speke/request/task_timer.h+57-0
@@ -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+#ifndef TASK_TIMER_H
17+#define TASK_TIMER_H
18+ 
19+#include <memory>
20+#include <thread>
21+#include <atomic>
22+#include <chrono>
23+#include <string>
24+#include <condition_variable>
25+#include <mutex>
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+#endif // TASK_TIMER_H
Acore/home_base/speke/security/auth_callback_methods.cpp+114-0
@@ -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+#include "auth_callback_methods.h"
17+#include "iotc_log.h"
18+#include "iotc_constants.h"
19+#include "global_params.h"
20+#include "operation_code.h"
21+#include "confirm_params.h"
22+#include "security_adapter.h"
23+#include "security_cipher.h"
24+#include "speke_negotiate_callback.h"
25+#include "common_util.h"
26+#include "pass_through_data.h"
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
Acore/home_base/speke/security/auth_callback_methods.h+55-0
@@ -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+#ifndef CALLBACK_METHODS_IMPL_H
17+#define CALLBACK_METHODS_IMPL_H
18+ 
19+#include <string>
20+#include <vector>
21+#include <cstdint>
22+#include <memory>
23+#include "iotc_constants.h"
24+#include "operation_parameter.h"
25+#include "speke_negotiate_callback.h"
26+#include "confirm_params.h"
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+#endif // CALLBACK_METHODS_IMPL_H
Acore/home_base/speke/security/e2e_security_api.cpp+149-0
@@ -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+#include "e2e_security_api.h"
17+#include "iotc_log.h"
18+#include "iotc_constants.h"
19+#include "iotc_json_object.h"
20+#include "security_pin.h"
21+#include "identity_info.h"
22+#include "message_config.h"
23+#include "identity_type.h"
24+#include "security_adapter.h"
25+#include "security_cipher.h"
26+#include "crypto_random.h"
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
Acore/home_base/speke/security/e2e_security_api.h+142-0
@@ -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+#ifndef E2E_SECURITY_API_H
17+#define E2E_SECURITY_API_H
18+ 
19+#include <string>
20+#include <vector>
21+#include <cstdint>
22+#include <memory>
23+#include "iotc_constants.h"
24+#include "speke_negotiate_callback.h"
25+#include "security_cipher.h"
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+#endif // E2E_SECURITY_API_H
Acore/home_base/speke/security/hw_device_auth_manager.cpp+170-0
@@ -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+#include "hw_device_auth_manager.h"
17+#include "iotc_log.h"
18+#include "request_manager.h"
19+#include "request_base.h"
20+#include "auth_key_agree_request.h"
21+#include "confirm_params.h"
22+#include "status_base.h"
23+#include "user_type.h"
24+#include "configured_version_info.h"
25+#include "speke_task_status.h"
26+#include "request_status.h"
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
Acore/home_base/speke/security/hw_device_auth_manager.h+55-0
@@ -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+#ifndef HW_DEVICE_AUTH_MANAGER_H
17+#define HW_DEVICE_AUTH_MANAGER_H
18+ 
19+#include <string>
20+#include <memory>
21+#include <mutex>
22+#include "operation_parameter.h"
23+#include "return_code.h"
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+#endif // HW_DEVICE_AUTH_MANAGER_H
Acore/home_base/speke/security/iot_security_manager.cpp+108-0
@@ -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+#include "iot_security_manager.h"
17+#include "iotc_log.h"
18+#include "aes_gcm_util.h"
19+#include "crypto_random.h"
20+#include "common_util.h"
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
Acore/home_base/speke/security/iot_security_manager.h+44-0
@@ -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+#ifndef IOT_SECURITY_MANAGER_H
17+#define IOT_SECURITY_MANAGER_H
18+ 
19+#include <vector>
20+#include <cstdint>
21+#include <string>
22+#include <memory>
23+#include "security_session_manager.h"
24+#include "speke_message_cryptor.h"
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+#endif // IOT_SECURITY_MANAGER_H
Acore/home_base/speke/security/security_adapter.cpp+239-0
@@ -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+#include "security_adapter.h"
17+#include "iotc_log.h"
18+#include "iotc_drbg.h"
19+#include "parameter_builder.h"
20+#include "pass_through_data.h"
21+#include "global_params.h"
22+#include "auth_callback_methods.h"
23+#include "hw_device_auth_manager.h"
24+#include "request_manager.h"
25+#include "crypto_random.h"
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
Acore/home_base/speke/security/security_adapter.h+86-0
@@ -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+#ifndef SECURITY_ADAPTER_H
17+#define SECURITY_ADAPTER_H
18+ 
19+#include <string>
20+#include <map>
21+#include <memory>
22+#include <functional>
23+#include "iotc_constants.h"
24+#include "identity_info.h"
25+#include "message_config.h"
26+#include "speke_negotiate_callback.h"
27+#include "return_code.h"
28+#include "operation_parameter.h"
29+#include "auth_callback_methods.h"
30+#include "iotc_json_object.h"
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+#endif // SECURITY_ADAPTER_H
Acore/home_base/speke/security/security_cipher.cpp+113-0
@@ -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+#include "security_cipher.h"
17+#include "iotc_log.h"
18+#include "crypto_random.h"
19+#include "aes_gcm_util.h"
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
Acore/home_base/speke/security/security_cipher.h+48-0
@@ -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+#ifndef SECURITY_CIPHER_H
17+#define SECURITY_CIPHER_H
18+ 
19+#include <vector>
20+#include <cstdint>
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+#endif // SECURITY_CIPHER_H
Acore/home_base/speke/security/security_pin.cpp+121-0
@@ -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+#include "security_pin.h"
17+#include "security_adapter.h"
18+#include "iotc_log.h"
19+#include "iotc_constants.h"
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
Acore/home_base/speke/security/security_pin.h+91-0
@@ -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+#ifndef SECURITY_PIN_H
17+#define SECURITY_PIN_H
18+ 
19+#include <string>
20+#include <cstdint>
21+#include <memory>
22+#include "iotc_constants.h"
23+#include "identity_info.h"
24+#include "message_config.h"
25+#include "speke_negotiate_callback.h"
26+#include "iotc_json_object.h"
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+#endif // SECURITY_PIN_H
Acore/home_base/speke/security/security_session_manager.cpp+312-0
@@ -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+#include "security_session_manager.h"
17+#include "iotc_log.h"
18+#include "crypto_kdf.h"
19+#include "crypto_random.h"
20+#include "e2e_security_api.h"
21+#include "iotc_constants.h"
22+#include "common_util.h"
23+#include "aes_gcm_util.h"
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
Acore/home_base/speke/security/security_session_manager.h+78-0
@@ -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+#ifndef SECURITY_SESSION_MANAGER_H
17+#define SECURITY_SESSION_MANAGER_H
18+ 
19+#include <vector>
20+#include <cstdint>
21+#include <string>
22+#include <memory>
23+#include "coap_session_entity.h"
24+#include "speke_message_hmacor.h"
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+#endif // SECURITY_SESSION_MANAGER_H
Acore/home_base/speke/security/speke_utils.cpp+351-0
@@ -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+#include "speke_utils.h"
17+#include "iotc_log.h"
18+#include "iotc_mpi.h"
19+#include "iotc_kdf.h"
20+#include "iotc_x25519.h"
21+#include "global_params.h"
22+#include "x25519/hash_to_curve_x25519.h"
23+#include "iotc_constants.h"
24+#include <cstring>
25+#include <cstdint>
26+#include <vector>
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(&param, 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(&param, 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
Acore/home_base/speke/security/speke_utils.h+112-0
@@ -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+#ifndef SSPEKE_UTILS_H
17+#define SSPEKE_UTILS_H
18+ 
19+#include <vector>
20+#include <cstdint>
21+#include <string>
22+#include "speke_type.h"
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+#endif // SSPEKE_UTILS_H
Acore/home_base/speke/security/x25519/hash_to_curve_x25519.cpp+427-0
@@ -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+#include "hash_to_curve_x25519.h"
17+#include "iotc_log.h"
18+#include "global_params.h"
19+#include "iotc_mpi.h"
20+#include <cstring>
21+#include <cstdint>
22+#include <cstdio>
23+#include <vector>
24+#include <algorithm>
25+#include <string>
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
Acore/home_base/speke/security/x25519/hash_to_curve_x25519.h+46-0
@@ -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+#ifndef HASH_TO_CURVE_X25519_H
17+#define HASH_TO_CURVE_X25519_H
18+ 
19+#include <cstdint>
20+#include <vector>
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+#endif // HASH_TO_CURVE_X25519_H
Acore/home_base/speke/transfer/ble/speke_request_over_adv_ble.cpp+37-0
@@ -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+#include "speke_request_over_adv_ble.h"
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
Acore/home_base/speke/transfer/ble/speke_request_over_adv_ble.h+42-0
@@ -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+#ifndef SPEKE_REQUEST_OVER_ADV_BLE_H
17+#define SPEKE_REQUEST_OVER_ADV_BLE_H
18+ 
19+#include <string>
20+#include "speke_request.h"
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+#endif // SPEKE_REQUEST_OVER_ADV_BLE_H
Acore/home_base/speke/transfer/ble/speke_transfer_over_adv_ble.cpp+80-0
@@ -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+#include "iotc_log.h"
17+#include "iotc_constants.h"
18+#include "speke_transfer_over_adv_ble.h"
19+#include "inner_callback.h"
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
Acore/home_base/speke/transfer/ble/speke_transfer_over_adv_ble.h+48-0
@@ -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+#ifndef SPEKE_TRANSFER_OVER_ADV_BLE_H
17+#define SPEKE_TRANSFER_OVER_ADV_BLE_H
18+ 
19+#include <string>
20+#include <memory>
21+#include "speke_request_over_adv_ble.h"
22+#include "speke_transfer_layer.h"
23+#include "adv_ble_request.h"
24+#include "base_entity_model.h"
25+#include "inner_callback.h"
26+#include "adv_ble_device_api.h"
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+#endif // SPEKE_TRANSFER_OVER_ADV_BLE_H
Mcore/home_base/speke/transfer/coap/speke_request_over_coap.cpp+1-1
@@ -54,4 +54,4 @@ void SpekeRequestOverCoap::SetUrl(const std::string& url)
54}54}
55 55 
56} // namespace IotcManagement56} // namespace IotcManagement
57-} // namespace OHOS57+} // namespace OHOS
Mcore/home_base/speke/transfer/coap/speke_transfer_over_coap.cpp+27-47
@@ -17,11 +17,13 @@
17#include "speke_entity.h"17#include "speke_entity.h"
18#include "iotc_log.h"18#include "iotc_log.h"
19#include "iotc_constants.h"19#include "iotc_constants.h"
20-#include "e2e_security_api.h"
21 20 
22namespace OHOS {21namespace OHOS {
23namespace IotcManagement {22namespace IotcManagement {
24 23 
24+namespace {
25+constexpr int32_t COAP_NO_RESPONSE = -1;
26+}
25 27 
26SpeckTransferOverCoap::SpeckTransferOverCoap(std::shared_ptr<SpekeRequestOverCoap> speckRequest)28SpeckTransferOverCoap::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 
31void SpeckTransferOverCoap::Send(const std::string& sendData, std::shared_ptr<TransferResponseCallback> callback)33void 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 IotcManagement71} // namespace IotcManagement
Mcore/home_base/speke/transfer/coap/speke_transfer_over_coap.h+0-2
@@ -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- 
39private:37private:
40 std::shared_ptr<SpekeRequestOverCoap> mSpeckRequestOverCoap_;38 std::shared_ptr<SpekeRequestOverCoap> mSpeckRequestOverCoap_;
41 std::shared_ptr<CoapDeviceApi> coapDeviceApi_;39 std::shared_ptr<CoapDeviceApi> coapDeviceApi_;
Acore/home_base/speke/transfer/speke_entity.cpp+66-0
@@ -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+#include "speke_entity.h"
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
Acore/home_base/speke/transfer/speke_entity.h+53-0
@@ -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+#ifndef SPEKE_ENTITY_H
17+#define SPEKE_ENTITY_H
18+ 
19+#include <string>
20+#include <vector>
21+#include <cstdint>
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+#endif // SPEKE_ENTITY_H
Acore/home_base/speke/transfer/speke_request.cpp+72-0
@@ -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+#include "speke_request.h"
17+#include "iotc_constants.h"
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
Acore/home_base/speke/transfer/speke_request.h+67-0
@@ -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+#ifndef SPEKE_REQUEST_H
17+#define SPEKE_REQUEST_H
18+ 
19+#include <string>
20+#include <vector>
21+#include <cstdint>
22+#include "iotc_constants.h"
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+#endif // SPEKE_REQUEST_H
Acore/home_base/speke/transfer/speke_transfer_factory.cpp+76-0
@@ -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+#include "speke_transfer_factory.h"
17+#ifdef IOTC_BLE_SUPPORT
18+#include "speke_transfer_over_adv_ble.h"
19+#include "speke_request_over_adv_ble.h"
20+#endif
21+#ifdef IOTC_COAP_SUPPORT
22+#include "speke_transfer_over_coap.h"
23+#endif
24+#include "speke_request.h"
25+#ifdef IOTC_COAP_SUPPORT
26+#include "speke_request_over_coap.h"
27+#endif
28+#include "iotc_log.h"
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+#ifdef IOTC_BLE_SUPPORT
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+#else
52+ (void)request;
53+ IOTC_LOGW("BLE transport is disabled");
54+ return nullptr;
55+#endif
56+ }
57+ 
58+#ifdef IOTC_COAP_SUPPORT
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+#endif
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
Acore/home_base/speke/transfer/speke_transfer_factory.h+52-0
@@ -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+#ifndef SPEKE_TRANSFER_FACTORY_H
17+#define SPEKE_TRANSFER_FACTORY_H
18+ 
19+#include <memory>
20+#include "speke_transfer_layer.h"
21+#include "speke_request.h"
22+#include "speke_entity.h"
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+#endif // SPEKE_TRANSFER_FACTORY_H
Acore/home_base/speke/transfer/speke_transfer_layer.h+41-0
@@ -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+#ifndef SPEKE_TRANSFER_LAYER_H
17+#define SPEKE_TRANSFER_LAYER_H
18+ 
19+#include <string>
20+#include "inner_callback.h"
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+#endif // SPEKE_TRANSFER_LAYER_H
Acore/home_base/speke/util/global_params.h+49-0
@@ -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+#ifndef GLOBAL_PARAMS_H
17+#define GLOBAL_PARAMS_H
18+ 
19+#include <cstdint>
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+#endif // GLOBAL_PARAMS_H
Acore/home_base/speke/util/identity_type.h+31-0
@@ -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+#ifndef IDENTITY_TYPE_H
17+#define IDENTITY_TYPE_H
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+#endif // IDENTITY_TYPE_H
Acore/home_base/speke/util/message_code.h+36-0
@@ -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+#ifndef MESSAGE_CODE_H
17+#define MESSAGE_CODE_H
18+ 
19+#include <cstdint>
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+#endif // MESSAGE_CODE_H
Acore/home_base/speke/util/operation_code.h+33-0
@@ -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+#ifndef OPERATION_CODE_H
17+#define OPERATION_CODE_H
18+ 
19+#include <cstdint>
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+#endif // OPERATION_CODE_H
Acore/home_base/speke/util/return_code.h+94-0
@@ -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+#ifndef RETURN_CODE_H
17+#define RETURN_CODE_H
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+#endif // RETURN_CODE_H
Acore/home_base/speke/util/speke_type.h+42-0
@@ -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+#ifndef SPEKE_TYPE_H
17+#define SPEKE_TYPE_H
18+ 
19+#include <cstdint>
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+#endif // SPEKE_TYPE_H
Acore/home_base/speke/util/user_type.h+42-0
@@ -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+#ifndef USER_TYPE_H
17+#define USER_TYPE_H
18+ 
19+#include <cstdint>
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+#endif // USER_TYPE_H