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