1 /*
2 * Copyright (c) 2022-2024 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 "mine_hichain_connector.h"
17
18 #include <cstdlib>
19 #include <chrono>
20 #include <unistd.h>
21 #include <securec.h>
22
23 #include "device_auth.h"
24 #include "device_auth_defines.h"
25 #include "dm_constants.h"
26 #include "dm_log.h"
27 #include "nlohmann/json.hpp"
28 #include "parameter.h"
29
30
31 namespace OHOS {
32 namespace DistributedHardware {
33 constexpr int32_t DEVICE_UDID_LENGTH = 65;
34 constexpr int64_t CREATE_GROUP_REQUESTID = 159357462;
35 constexpr int32_t MAX_HICHAIN_DELAY_TIME = 10;
36
37 std::mutex g_createGroupMutex;
38 std::condition_variable g_createGroupNotify;
39
40 bool g_mineCreateGroupFlag = false;
41
42 const DeviceGroupManager *g_deviceGroupManager = nullptr;
43 DeviceAuthCallback g_deviceAuthCallback = {
44 .onTransmit = nullptr,
45 .onFinish = MineHiChainConnector::onFinish,
46 .onError = MineHiChainConnector::onError,
47 .onRequest = nullptr
48 };
MineHiChainConnector()49 MineHiChainConnector::MineHiChainConnector()
50 {
51 Init();
52 LOGI("HiChainConnector::constructor success.");
53 }
54
~MineHiChainConnector()55 MineHiChainConnector::~MineHiChainConnector()
56 {
57 UnInit();
58 LOGI("HiChainConnector::destructor.");
59 }
60
onFinish(int64_t requestId,int operationCode,const char * returnData)61 void MineHiChainConnector::onFinish(int64_t requestId, int operationCode, const char *returnData)
62 {
63 (void)returnData;
64 LOGD("start to notify the asynchronous operation group of the successful result.");
65 if (requestId == CREATE_GROUP_REQUESTID) {
66 std::unique_lock<std::mutex> locker(g_createGroupMutex);
67 g_mineCreateGroupFlag = true;
68 g_createGroupNotify.notify_one();
69 LOGI("Create group success");
70 }
71 LOGI("OnFinish callback complete with requestId: %{public}" PRId64 ", operation: %{public}d.", requestId,
72 operationCode);
73 }
74
onError(int64_t requestId,int operationCode,int errorCode,const char * errorReturn)75 void MineHiChainConnector::onError(int64_t requestId, int operationCode, int errorCode, const char *errorReturn)
76 {
77 (void)errorReturn;
78 LOGD("start to notify the asynchronous operation group of the successful result.");
79 if (requestId == CREATE_GROUP_REQUESTID) {
80 std::unique_lock<std::mutex> locker(g_createGroupMutex);
81 g_mineCreateGroupFlag = false;
82 g_createGroupNotify.notify_one();
83 LOGI("failed to create group");
84 }
85 LOGI("OnError callback complete with requestId: %{public}" PRId64 ", operation: %{public}d, errorCode: %{public}d.",
86 requestId, operationCode, errorCode);
87 }
88
Init(void)89 int32_t MineHiChainConnector::Init(void)
90 {
91 int retValue = InitDeviceAuthService();
92 if (retValue != HC_SUCCESS) {
93 LOGE("failed to init device auth service with ret:%{public}d.", retValue);
94 return ERR_DM_FAILED;
95 }
96 g_deviceGroupManager = GetGmInstance();
97 if (g_deviceGroupManager == nullptr) {
98 LOGE("failed to get Gm instance from hichain");
99 return ERR_DM_FAILED;
100 }
101 #if (defined(MINE_HARMONY))
102 retValue = g_deviceGroupManager->unRegCallback(DM_PKG_NAME);
103 if (retValue != HC_SUCCESS) {
104 LOGE("failed to register callback function to hichain with ret:%{public}d.", retValue);
105 }
106 retValue = g_deviceGroupManager->regCallback(DM_PKG_NAME, &g_deviceAuthCallback);
107 if (retValue != HC_SUCCESS) {
108 LOGE("failed to register callback function to hichain with ret:%{public}d.", retValue);
109 return ERR_DM_FAILED;
110 }
111 #endif
112 LOGI("init hichain modle successfully.");
113 return DM_OK;
114 }
115
116
UnInit(void)117 int32_t MineHiChainConnector::UnInit(void)
118 {
119 if (g_deviceGroupManager == nullptr) {
120 LOGE("g_deviceGroupManager os nullptr");
121 return ERR_DM_POINT_NULL;
122 }
123 #if (defined(MINE_HARMONY))
124 if (g_deviceGroupManager->unRegCallback(DM_PKG_NAME) != HC_SUCCESS) {
125 LOGE("failed to unregister callback to hichain");
126 return ERR_DM_HICHAIN_UNREGISTER_CALLBACK;
127 }
128 DestroyDeviceAuthService();
129 #endif
130 LOGI("uninit hichain modle successfully");
131 return DM_OK;
132 }
133
DeleteCredentialAndGroup(void)134 int32_t MineHiChainConnector::DeleteCredentialAndGroup(void)
135 {
136 nlohmann::json jsonObj;
137 jsonObj[FIELD_IS_DELETE_ALL] = true;
138 std::string params = jsonObj.dump();
139 #if (defined(MINE_HARMONY))
140 char *returnInfo = nullptr;
141 int32_t retValue = g_deviceGroupManager->processCredential(DELETE_SELF_CREDENTIAL, params.c_str(), &returnInfo);
142 if (retValue != HC_SUCCESS) {
143 LOGE("failed to delete hichain credential and group with ret:%{public}d.", retValue);
144 return ERR_DM_FAILED;
145 }
146 #endif
147 return DM_OK;
148 }
149
CreateGroup(const std::string & reqJsonStr)150 int32_t MineHiChainConnector::CreateGroup(const std::string &reqJsonStr)
151 {
152 int64_t requestId = CREATE_GROUP_REQUESTID;
153 char deviceUdid[DEVICE_UDID_LENGTH + 1] = {0};
154
155 nlohmann::json jsonObject = nlohmann::json::parse(reqJsonStr, nullptr, false);
156 if (jsonObject.is_discarded()) {
157 LOGE("reqJsonStr string not a json type.");
158 return ERR_DM_FAILED;
159 }
160 if (!jsonObject.contains(FIELD_USER_ID) || !jsonObject[FIELD_USER_ID].is_string()) {
161 LOGE("userId key is not exist in reqJsonStr.");
162 return ERR_DM_FAILED;
163 }
164 int32_t retValue = GetDevUdid(deviceUdid, DEVICE_UDID_LENGTH);
165 if (retValue != 0) {
166 LOGE("failed to local device Udid with ret: %{public}d", retValue);
167 return ERR_DM_FAILED;
168 }
169
170 nlohmann::json jsonObj;
171 jsonObj[FIELD_USER_ID] = jsonObject[FIELD_USER_ID];
172 jsonObj[FIELD_GROUP_NAME] = DEVICE_MANAGER_GROUPNAME;
173 jsonObj[FIELD_DEVICE_ID] = std::string(deviceUdid);
174 jsonObj[FIELD_GROUP_TYPE] = IDENTICAL_ACCOUNT_GROUP;
175 std::string createParams = jsonObj.dump();
176 retValue = g_deviceGroupManager->createGroup(DEFAULT_OS_ACCOUNT, requestId, DM_PKG_NAME, createParams.c_str());
177 if (retValue != HC_SUCCESS) {
178 LOGE("failed to create group with ret:%{public}d.", retValue);
179 return ERR_DM_FAILED;
180 }
181
182 std::chrono::seconds timeout = std::chrono::seconds(MAX_HICHAIN_DELAY_TIME);
183 std::unique_lock<std::mutex> locker(g_createGroupMutex);
184 if (g_createGroupNotify.wait_for(locker, timeout, [] { return g_mineCreateGroupFlag; })) {
185 g_mineCreateGroupFlag = false;
186 return DM_OK;
187 }
188 g_mineCreateGroupFlag = false;
189 return ERR_DM_FAILED;
190 }
191
RequestCredential(std::string & returnJsonStr)192 int MineHiChainConnector::RequestCredential(std::string &returnJsonStr)
193 {
194 if (g_deviceGroupManager == nullptr) {
195 LOGE("HiChainConnector::g_deviceGroupManager is nullptr.");
196 return ERR_DM_INPUT_PARA_INVALID;
197 }
198
199 LOGI("start to request device credential.");
200 #if (defined(MINE_HARMONY))
201 char *returnInfo = nullptr;
202 int32_t retValue = g_deviceGroupManager->getRegisterInfo(&returnInfo);
203 if (retValue != HC_SUCCESS || returnInfo == nullptr) {
204 LOGE("failed to request hichain credential with ret:%{public}d.", retValue);
205 return ERR_DM_HICHAIN_GET_REGISTER_INFO;
206 }
207 returnJsonStr = returnInfo;
208 g_deviceGroupManager->destroyInfo(&returnInfo);
209 #endif
210 LOGI("request hichain device credential successfully with JsonStrLen:%{public}zu", returnJsonStr.size());
211 return DM_OK;
212 }
213
CheckCredential(std::string reqJsonStr,std::string & returnJsonStr)214 int MineHiChainConnector::CheckCredential(std::string reqJsonStr, std::string &returnJsonStr)
215 {
216 if (reqJsonStr.empty() || g_deviceGroupManager == nullptr) {
217 LOGE("HiChainConnector::g_deviceGroupManager is nullptr.");
218 return ERR_DM_INPUT_PARA_INVALID;
219 }
220 LOGI("start to check device credential.");
221 #if (defined(MINE_HARMONY))
222 char *returnInfo = nullptr;
223 int32_t retValue = g_deviceGroupManager->processCredential(QUERY_SELF_CREDENTIAL_INFO,
224 reqJsonStr.c_str(), &returnInfo);
225 if (retValue != HC_SUCCESS) {
226 LOGE("failed to check device credential info with ret:%{public}d.", retValue);
227 return ERR_DM_HICHAIN_GET_REGISTER_INFO;
228 }
229 returnJsonStr = returnInfo;
230 g_deviceGroupManager->destroyInfo(&returnInfo);
231 #endif
232 LOGI("check device credential info successfully with JsonStrLen:%{public}zu", returnJsonStr.size());
233 return DM_OK;
234 }
235
ImportCredential(std::string reqJsonStr,std::string & returnJsonStr)236 int MineHiChainConnector::ImportCredential(std::string reqJsonStr, std::string &returnJsonStr)
237 {
238 if (reqJsonStr.empty() || g_deviceGroupManager == nullptr) {
239 LOGE("reqJsonStr is empty or g_deviceGroupManager is nullptr.");
240 return ERR_DM_INPUT_PARA_INVALID;
241 }
242 nlohmann::json jsonObject = nlohmann::json::parse(reqJsonStr, nullptr, false);
243 if (jsonObject.is_discarded()) {
244 LOGE("import credenfial input reqJsonStr string not a json string type.");
245 return ERR_DM_INPUT_PARA_INVALID;
246 }
247 if (IsCredentialExist()) {
248 LOGE("the device has already exists credential.");
249 return ERR_DM_HICHAIN_CREDENTIAL_EXISTS;
250 }
251 int32_t retValue = g_deviceGroupManager->regCallback(DM_PKG_NAME, &g_deviceAuthCallback);
252 if (retValue != HC_SUCCESS) {
253 LOGE("failed to register callback function to hichain with ret:%{public}d.", retValue);
254 return ERR_DM_HICHAIN_REGISTER_CALLBACK;
255 }
256 LOGI("start to import device credential info to hichain.");
257 #if (defined(MINE_HARMONY))
258 char *returnInfo = nullptr;
259 retValue = g_deviceGroupManager->processCredential(IMPORT_SELF_CREDENTIAL, reqJsonStr.c_str(), &returnInfo);
260 if (retValue != HC_SUCCESS) {
261 LOGE("failed to import hichain credential with ret:%{public}d.", retValue);
262 return ERR_DM_HICHAIN_GROUP_CREATE_FAILED;
263 }
264 if (CreateGroup(reqJsonStr) != DM_OK) {
265 DeleteCredentialAndGroup();
266 LOGE("fail to import hichain credential bacause create group unsuccessfully.");
267 return ERR_DM_HICHAIN_GROUP_CREATE_FAILED;
268 }
269 #endif
270 LOGI("import device credential info successfully.");
271 return DM_OK;
272 }
273
DeleteCredential(std::string reqJsonStr,std::string & returnJsonStr)274 int MineHiChainConnector::DeleteCredential(std::string reqJsonStr, std::string &returnJsonStr)
275 {
276 if (reqJsonStr.empty() || g_deviceGroupManager == nullptr) {
277 LOGE("reqJsonStr is empty or g_deviceGroupManager is nullptr.");
278 return ERR_DM_INPUT_PARA_INVALID;
279 }
280
281 LOGI("start to delete device credential from hichain.");
282 if (DeleteCredentialAndGroup() != DM_OK) {
283 LOGE("failed to delete hichain credential.");
284 return ERR_DM_HICHAIN_CREDENTIAL_DELETE_FAILED;
285 }
286 LOGI("delete device credential info from hichain successfully.");
287 return DM_OK;
288 }
289
IsCredentialExist(void)290 bool MineHiChainConnector::IsCredentialExist(void)
291 {
292 bool resultFlag = false;
293 std::string reqJsonStr = "{\n}";
294
295 if (g_deviceGroupManager == nullptr) {
296 LOGE("g_deviceGroupManager is nullptr.");
297 return resultFlag;
298 }
299 #if (defined(MINE_HARMONY))
300 char *returnInfo = nullptr;
301 int32_t retValue = g_deviceGroupManager->processCredential(QUERY_SELF_CREDENTIAL_INFO,
302 reqJsonStr.c_str(), &returnInfo);
303 if (retValue != HC_SUCCESS || returnInfo == nullptr) {
304 LOGE("failed to check device credential info with ret:%{public}d.", retValue);
305 return resultFlag;
306 }
307
308 do {
309 nlohmann::json jsonObject = nlohmann::json::parse(returnInfo, nullptr, false);
310 if (jsonObject.is_discarded()) {
311 LOGE("reqJsonStr is not a json string type.");
312 break;
313 }
314 if (!jsonObject.contains(FIELD_CREDENTIAL_EXISTS) || !jsonObject[FIELD_CREDENTIAL_EXISTS].is_boolean()) {
315 LOGE("failed to get key:%{public}s from import json object.", FIELD_CREDENTIAL_EXISTS);
316 break;
317 }
318 if (!jsonObject[FIELD_CREDENTIAL_EXISTS]) {
319 LOGI("credential information does not exist on the current device.");
320 break;
321 }
322 LOGI("credential information exist on the current device.");
323 resultFlag = true;
324 } while (false);
325
326 g_deviceGroupManager->destroyInfo(&returnInfo);
327 #endif
328 return resultFlag;
329 }
330 } // namespace DistributedHardware
331 } // namespace OHOS