• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2025-2025 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 "antifraud_cloud_service.h"
17 
18 #include <chrono>
19 #include <cJSON.h>
20 #include <limits>
21 #include <openssl/sha.h>
22 #include <openssl/hmac.h>
23 #include <parameter.h>
24 #include <parameters.h>
25 #include <random>
26 #include <sstream>
27 #include "telephony_log_wrapper.h"
28 
29 namespace OHOS {
30 namespace Telephony {
31 constexpr size_t BOUNDARY_LENGTH = 32;
32 constexpr size_t REQUEST_NO_LENGTH = 10;
33 constexpr size_t SERIAL_NUM_LEN = 16;
34 constexpr int BASE64_NUMBER2 = 2;
35 constexpr int BASE64_NUMBER3 = 3;
36 constexpr int BASE64_NUMBER4 = 4;
37 constexpr int BASE64_NUMBER6 = 6;
38 constexpr int COMMON_TIME_OUT = 5000;
39 const std::string BASE_64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
40 const std::string RANDOM_CHAR_SET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
41 const std::string UPLOAD_MODEL_PATH = "/rms/v1/antiFraud/upload-model-result";
42 const std::string CLOUD_CONNECT_SERVICE_NAME = "com.cloud.afs.ROOT";
43 const std::string UCS_SERVICE_NAME = "com.hmos.hsdr.antifraud";
44 
AntiFraudCloudService(const std::string & phoneNum)45 AntiFraudCloudService::AntiFraudCloudService(const std::string &phoneNum) : phoneNum_(phoneNum) {}
46 
UploadPostRequest(const OHOS::AntiFraudService::AntiFraudResult & antiFraudResult)47 bool AntiFraudCloudService::UploadPostRequest(const OHOS::AntiFraudService::AntiFraudResult &antiFraudResult)
48 {
49     auto &helper = DelayedRefSingleton<HsdrHelper>().GetInstance();
50     std::string metaData = GeneratePayload(antiFraudResult);
51     std::weak_ptr<AntiFraudCloudService> weakPtr = shared_from_this();
52     std::unique_lock<std::mutex> lock(mutex_);
53     isSettled_ = false;
54     std::string auth;
55     helper.ConnectHsdr([weakPtr, metaData, &auth](sptr<IRemoteObject> remoteObject) {
56         auto ptr = weakPtr.lock();
57         if (ptr == nullptr) {
58             auto &helper = DelayedRefSingleton<HsdrHelper>().GetInstance();
59             helper.DisconnectHsdr();
60             return;
61         }
62         std::lock_guard<std::mutex> lock(ptr->mutex_);
63         auto pair = ptr->EncryptSync(metaData, remoteObject);
64         auto ak = pair.first;
65         if (ak.empty()) {
66             TELEPHONY_LOGE("Failed to get ak.");
67             ptr->isSettled_ = true;
68             ptr->cv_.notify_all();
69             return;
70         }
71         auth = ptr->GetAuthSync(metaData, ak, remoteObject);
72         ptr->isSettled_ = true;
73         ptr->cv_.notify_all();
74     });
75 
76     while (!isSettled_) {
77         if (cv_.wait_for(lock, std::chrono::milliseconds(COMMON_TIME_OUT)) == std::cv_status::timeout) {
78             TELEPHONY_LOGE("get auth timeout.");
79             helper.DisconnectHsdr();
80             return false;
81         }
82     }
83 
84     if (auth.empty()) {
85         TELEPHONY_LOGE("Failed to get auth.");
86         helper.DisconnectHsdr();
87         return false;
88     }
89 
90     helper.ConnectHsdr([metaData, auth, antiFraudResult, weakPtr](sptr<IRemoteObject> remoteObject) {
91         auto ptr = weakPtr.lock();
92         if (ptr == nullptr) {
93             auto &helper = DelayedRefSingleton<HsdrHelper>().GetInstance();
94             helper.DisconnectHsdr();
95             return;
96         }
97         ptr->ConnectCloudAsync(metaData, auth, antiFraudResult, remoteObject);
98     });
99     return true;
100 }
101 
GeneratePayload(const OHOS::AntiFraudService::AntiFraudResult & antiFraudResult)102 std::string AntiFraudCloudService::GeneratePayload(const OHOS::AntiFraudService::AntiFraudResult &antiFraudResult)
103 {
104     cJSON *root = cJSON_CreateObject();
105     if (root == nullptr) {
106         TELEPHONY_LOGE("Failed to create json object");
107         return "";
108     }
109     cJSON_AddStringToObject(root, "modelCaller", "com.hsdr");
110     cJSON_AddStringToObject(root, "reqNo", GenerateRandomString(REQUEST_NO_LENGTH).c_str());
111     cJSON_AddStringToObject(root, "calleeId", "15564984");
112     cJSON_AddStringToObject(root, "osType", "1");
113     cJSON_AddStringToObject(root, "serviceType", "00000002");
114     cJSON_AddStringToObject(root, "callerNum", phoneNum_.c_str());
115     cJSON_AddStringToObject(root, "markerId", "11");
116     cJSON_AddStringToObject(root, "romVer", GetRomVersion().c_str());
117     cJSON_AddStringToObject(root, "modelVer", std::to_string(antiFraudResult.modelVersion).c_str());
118     cJSON_AddNumberToObject(root, "modelScore", antiFraudResult.pvalue);
119     cJSON_AddStringToObject(root, "modelDecision", std::to_string(antiFraudResult.fraudType).c_str());
120     char *jsonString = cJSON_Print(root);
121     if (jsonString == nullptr) {
122         TELEPHONY_LOGE("Failed to generate json string.");
123         cJSON_Delete(root);
124         return "";
125     }
126     std::string payload(jsonString);
127     cJSON_Delete(root);
128     free(jsonString);
129     return payload;
130 }
131 
EncryptSync(const std::string & metaData,sptr<IRemoteObject> remoteObject)132 std::pair<std::string, std::string> AntiFraudCloudService::EncryptSync(const std::string &metaData,
133     sptr<IRemoteObject> remoteObject)
134 {
135     if (remoteObject == nullptr) {
136         TELEPHONY_LOGE("remoteObject is nullptr.");
137         return {"", ""};
138     }
139     HsdrProxy service(remoteObject);
140     std::string encryptResult;
141     HsdrRequest encryptReq = { std::to_string(GenerateRandomLong()), UCS_SERVICE_NAME,
142         HsdrCommands::COMMAND_UCS_REQUEST, GenerateUcsRequestBody(UcsMethod::Encrypt, metaData) };
143     auto ret = service.RequestHsdrServiceSync(encryptReq, encryptResult);
144     TELEPHONY_LOGI("RequestHsdrServiceSync ret = %{public}d", ret);
145 
146     auto pair = ProcessEncryptResult(encryptResult);
147     return pair;
148 }
149 
ProcessEncryptResult(const std::string & encryptResult)150 std::pair<std::string, std::string> AntiFraudCloudService::ProcessEncryptResult(const std::string &encryptResult)
151 {
152     cJSON *root = cJSON_Parse(encryptResult.c_str());
153     if (root == nullptr) {
154         TELEPHONY_LOGE("cJSON_Parse failed");
155         return {"", ""};
156     }
157     cJSON *ak = cJSON_GetObjectItem(root, "ak");
158     if (ak == nullptr || ak->type != cJSON_String) {
159         TELEPHONY_LOGE("ak is not string.");
160         cJSON_Delete(root);
161         return {"", ""};
162     }
163     std::string akString(ak->valuestring);
164     cJSON *encrypt = cJSON_GetObjectItem(root, "data");
165     if (encrypt == nullptr || encrypt->type != cJSON_String) {
166         TELEPHONY_LOGE("encrypt is not string.");
167         cJSON_Delete(root);
168         return {akString, ""};
169     }
170     std::string encryptString(encrypt->valuestring);
171     cJSON_Delete(root);
172     return {akString, encryptString};
173 }
174 
GetAuthSync(const std::string & metaData,const std::string & ak,sptr<IRemoteObject> remoteObject)175 std::string AntiFraudCloudService::GetAuthSync(const std::string &metaData, const std::string &ak,
176     sptr<IRemoteObject> remoteObject)
177 {
178     if (remoteObject == nullptr) {
179         TELEPHONY_LOGE("remoteObject is nullptr.");
180         return "";
181     }
182     HsdrProxy service(remoteObject);
183     auto timestamp = std::to_string(std::chrono::duration_cast<std::chrono::milliseconds>(
184         std::chrono::system_clock::now().time_since_epoch()).count());
185     std::string toSign = "POST&" + UPLOAD_MODEL_PATH + "&&";
186     toSign += metaData + "&";
187     toSign += "ak=" + ak + "&";
188     toSign += "timestamp=" + timestamp;
189     std::string signResult;
190     HsdrRequest signReq = { std::to_string(GenerateRandomLong()), UCS_SERVICE_NAME, HsdrCommands::COMMAND_UCS_REQUEST,
191         GenerateUcsRequestBody(UcsMethod::Sign, toSign) };
192     auto ret = service.RequestHsdrServiceSync(signReq, signResult);
193     TELEPHONY_LOGI("RequestHsdrServiceSync ret = %{public}d", ret);
194     std::string signature = ProcessSignResult(signResult);
195     std::string auth = "EXT-CLOUDSOA-HMAC-SHA256 ak=\"" + ak + "\",timestamp=" + timestamp +
196         ",signature=\"" + signature + "\"";
197     return auth;
198 }
199 
ProcessSignResult(const std::string & signResult)200 std::string AntiFraudCloudService::ProcessSignResult(const std::string &signResult)
201 {
202     cJSON *root = cJSON_Parse(signResult.c_str());
203     if (root == nullptr) {
204         TELEPHONY_LOGE("cJSON_Parse failed");
205         return "";
206     }
207     cJSON *data = cJSON_GetObjectItem(root, "data");
208     if (data == nullptr || data->type != cJSON_String) {
209         TELEPHONY_LOGE("signature data is not string.");
210         cJSON_Delete(root);
211         return "";
212     }
213     std::string signature(data->valuestring);
214     cJSON_Delete(root);
215     return signature;
216 }
217 
GenerateUcsRequestBody(UcsMethod code,const std::string & requestData)218 std::string AntiFraudCloudService::GenerateUcsRequestBody(UcsMethod code, const std::string &requestData)
219 {
220     cJSON *root = cJSON_CreateObject();
221     if (root == nullptr) {
222         TELEPHONY_LOGE("Failed to create json object.");
223         return "";
224     }
225     cJSON_AddNumberToObject(root, "method", static_cast<int>(code));
226     cJSON_AddStringToObject(root, "data", EncodeBase64(requestData.c_str(), requestData.size()).c_str());
227     char *jsonString = cJSON_Print(root);
228     if (jsonString == nullptr) {
229         TELEPHONY_LOGE("Failed to generate json string.");
230         cJSON_Delete(root);
231         return "";
232     }
233     std::string requestBody(jsonString);
234     free(jsonString);
235     cJSON_Delete(root);
236     return requestBody;
237 }
238 
EncodeBase64(const char * bytes,unsigned int size)239 std::string AntiFraudCloudService::EncodeBase64(const char *bytes, unsigned int size)
240 {
241     std::string result;
242     int i = 0;
243     int j = 0;
244     uint8_t charArray3[BASE64_NUMBER3] = { 0 }; // store 3 byte of bytes_to_encode
245     uint8_t charArray4[BASE64_NUMBER4] = { 0 }; // store encoded character to 4 bytes
246 
247     while (size--) {
248         charArray3[i++] = *(bytes++); // get three bytes (24 bits)
249         if (i == BASE64_NUMBER3) {
250             // eg. we have 3 bytes as ( 0100 1101, 0110 0001, 0110 1110) --> (010011, 010110, 000101, 101110)
251             charArray4[0] = (charArray3[0] & 0xfc) >> BASE64_NUMBER2; // get first 6 bits of first byte
252             // get last 2 bits of first byte and first 4 bit of second byte
253             charArray4[1] = ((charArray3[0] & 0x03) << BASE64_NUMBER4) + ((charArray3[1] & 0xf0) >> BASE64_NUMBER4);
254             // get last 4 bits of second byte and first 2 bits of third byte
255             charArray4[BASE64_NUMBER2] = ((charArray3[1] & 0x0f) << BASE64_NUMBER2) +
256                 ((charArray3[BASE64_NUMBER2] & 0xc0) >> BASE64_NUMBER6);
257             charArray4[BASE64_NUMBER3] = charArray3[BASE64_NUMBER2] & 0x3f; // get last 6 bits of third byte
258 
259             for (i = 0; (i < BASE64_NUMBER4); i++) {
260                 result += BASE_64_CHARS[charArray4[i]];
261             }
262             i = 0;
263         }
264     }
265 
266     if (i) {
267         for (j = i; j < BASE64_NUMBER3; j++) {
268             charArray3[j] = '\0';
269         }
270 
271         charArray4[0] = (charArray3[0] & 0xfc) >> BASE64_NUMBER2;
272         charArray4[1] = ((charArray3[0] & 0x03) << BASE64_NUMBER4) + ((charArray3[1] & 0xf0) >> BASE64_NUMBER4);
273         charArray4[BASE64_NUMBER2] = ((charArray3[1] & 0x0f) << BASE64_NUMBER2) +
274             ((charArray3[BASE64_NUMBER2] & 0xc0) >> BASE64_NUMBER6);
275 
276         for (j = 0; (j < i + 1); j++) {
277             result += BASE_64_CHARS[charArray4[j]];
278         }
279 
280         while ((i++ < BASE64_NUMBER3)) {
281             result += '=';
282         }
283     }
284 
285     return result;
286 }
287 
ConnectCloudAsync(const std::string & metaData,const std::string & auth,const OHOS::AntiFraudService::AntiFraudResult & antiFraudResult,sptr<IRemoteObject> remoteObject)288 bool AntiFraudCloudService::ConnectCloudAsync(const std::string &metaData, const std::string &auth,
289     const OHOS::AntiFraudService::AntiFraudResult &antiFraudResult, sptr<IRemoteObject> remoteObject)
290 {
291     if (remoteObject == nullptr) {
292         TELEPHONY_LOGE("remoteObject is nullptr.");
293         auto &helper = DelayedRefSingleton<HsdrHelper>().GetInstance();
294         helper.DisconnectHsdr();
295         return false;
296     }
297     HsdrProxy service(remoteObject);
298     std::string boundary = GenerateRandomString(BOUNDARY_LENGTH);
299     std::map<std::string, std::string> headers = GenerateHeadersMap(auth, antiFraudResult.text, boundary);
300     std::ostringstream bodyStream;
301     bodyStream << "--" << boundary << "\r\n" <<
302         "Content-Disposition: form-data; name=\"meta-data\"\r\n" <<
303         "Content-Type: application/json\r\n" <<
304         "\r\n" <<
305         metaData << "\r\n" <<
306         "--" << boundary << "\r\n" <<
307         "Content-Disposition: form-data; name=\"file-data\"; filename=\"file.txt\"\r\n" <<
308         "Content-Type: text/plain\r\n" <<
309         "\r\n" <<
310         antiFraudResult.text << "\r\n" <<
311         "--" << boundary << "--";
312     std::string body = bodyStream.str();
313     std::string requestJson = GenerateRequestJson(headers, body);
314     OnResponse onResponse = [](const HsdrResponse &response) {
315         TELEPHONY_LOGI("Onresponse, body: %{public}s", response.body_.c_str());
316         auto &helper = DelayedRefSingleton<HsdrHelper>().GetInstance();
317         helper.DisconnectHsdr();
318     };
319     OnError onError = [](int errCode) {
320         TELEPHONY_LOGE("error code = %{public}d", errCode);
321         auto &helper = DelayedRefSingleton<HsdrHelper>().GetInstance();
322         helper.DisconnectHsdr();
323     };
324     std::string requestId = std::to_string(GenerateRandomLong());
325     sptr<HsdrCallbackStub> callbackStub =
326         new (std::nothrow) HsdrCallbackStub(requestId, onResponse, onError);
327     if (callbackStub == nullptr) {
328         TELEPHONY_LOGE("callbackStub is nullptr.");
329         auto &helper = DelayedRefSingleton<HsdrHelper>().GetInstance();
330         helper.DisconnectHsdr();
331         return false;
332     }
333     HsdrRequest request = { requestId, CLOUD_CONNECT_SERVICE_NAME, HsdrCommands::COMMAND_CLOUD_CONNECT,
334         requestJson };
335     int ret = service.RequestHsdrServiceAsync(callbackStub, request);
336     TELEPHONY_LOGI("RequestHsdrServiceAsync ret = %{public}d", ret);
337     return ret == 0;
338 }
339 
GenerateHeadersMap(const std::string & auth,const std::string & fileContent,const std::string & boundary)340 std::map<std::string, std::string> AntiFraudCloudService::GenerateHeadersMap(const std::string &auth,
341     const std::string &fileContent, const std::string &boundary)
342 {
343     std::map<std::string, std::string> headers;
344     headers["Authorization"] = auth;
345     headers["X-Request-ID"] = GetDeviceSerial();
346     headers["Content-Digest"] = CalculateDigest(fileContent);
347     headers["down-algo"] = "AES-GCM";
348     headers["X-OS-Version"] = GetOsVersion();
349     std::string contentType = "multipart/form-data; boundary=" + boundary;
350     headers["Content-Type"] = contentType;
351     return headers;
352 }
353 
CalculateDigest(const std::string & payload)354 std::string AntiFraudCloudService::CalculateDigest(const std::string &payload)
355 {
356     unsigned char hash[SHA256_DIGEST_LENGTH];
357     SHA256_CTX sha256;
358     SHA256_Init(&sha256);
359     SHA256_Update(&sha256, payload.c_str(), payload.size());
360     SHA256_Final(hash, &sha256);
361 
362     std::stringstream ss;
363     for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) {
364         ss << std::hex << std::setw(BASE64_NUMBER2) << std::setfill('0') << (int)hash[i];
365     }
366     return ss.str();
367 }
368 
GenerateRequestJson(const std::map<std::string,std::string> & headersMap,const std::string & body)369 std::string AntiFraudCloudService::GenerateRequestJson(const std::map<std::string, std::string> &headersMap,
370     const std::string &body)
371 {
372     cJSON *root = cJSON_CreateObject();
373     if (root == nullptr) {
374         TELEPHONY_LOGE("Failed to create json object.");
375         return "";
376     }
377     cJSON_AddStringToObject(root, "method", "POST");
378     cJSON_AddStringToObject(root, "path", UPLOAD_MODEL_PATH.c_str());
379 
380     cJSON *headers = cJSON_CreateObject();
381     if (headers == nullptr) {
382         TELEPHONY_LOGE("Failed to create json object.");
383         cJSON_Delete(root);
384         return "";
385     }
386     cJSON *params = cJSON_CreateArray();
387     if (params == nullptr) {
388         TELEPHONY_LOGE("Failed to create json object.");
389         cJSON_Delete(root);
390         cJSON_Delete(headers);
391         return "";
392     }
393     for (auto header : headersMap) {
394         cJSON *param = cJSON_CreateObject();
395         if (param == nullptr) {
396             TELEPHONY_LOGE("Failed to create json object.");
397             cJSON_Delete(root);
398             cJSON_Delete(headers);
399             cJSON_Delete(params);
400             return "";
401         }
402         cJSON_AddStringToObject(param, "name", header.first.c_str());
403         cJSON_AddStringToObject(param, "value", header.second.c_str());
404         cJSON_AddItemToArray(params, param);
405     }
406     cJSON_AddItemToObject(headers, "params", params);
407     cJSON_AddItemToObject(root, "headers", headers);
408 
409     cJSON_AddStringToObject(root, "body", body.c_str());
410     cJSON_AddNumberToObject(root, "connectTimeout", COMMON_TIME_OUT);
411     cJSON_AddNumberToObject(root, "readTimeout", COMMON_TIME_OUT);
412     char *str = cJSON_Print(root);
413     if (str == nullptr) {
414         TELEPHONY_LOGE("Failed to generate json string.");
415         cJSON_Delete(root);
416         return "";
417     }
418     std::string requestJson(str);
419     cJSON_Delete(root);
420     free(str);
421     return requestJson;
422 }
423 
GenerateRandomString(size_t length)424 std::string AntiFraudCloudService::GenerateRandomString(size_t length)
425 {
426     std::string randomString;
427     randomString.reserve(length);
428     for (size_t i = 0; i < length; i++) {
429         std::random_device rd;
430         std::uniform_int_distribution<size_t> dist(0, RANDOM_CHAR_SET.size() - 1);
431         size_t randomNum = dist(rd);
432         randomString += RANDOM_CHAR_SET[randomNum];
433     }
434 
435     return randomString;
436 }
437 
GenerateRandomLong()438 uint64_t AntiFraudCloudService::GenerateRandomLong()
439 {
440     std::random_device seed;
441     std::mt19937_64 gen(seed());
442     std::uniform_int_distribution<uint64_t> dis(std::numeric_limits<uint64_t>::min(),
443         std::numeric_limits<uint64_t>::max());
444     return dis(gen);
445 }
446 
GetOsVersion()447 std::string AntiFraudCloudService::GetOsVersion()
448 {
449     return system::GetParameter("const.ohos.fullname", "");
450 }
451 
GetDeviceSerial()452 std::string AntiFraudCloudService::GetDeviceSerial()
453 {
454     const char *serial = GetSerial();
455     if (serial == nullptr) {
456         TELEPHONY_LOGE("GetSerial failed.");
457         return GenerateRandomString(SERIAL_NUM_LEN);
458     }
459     std::string deviceSerial(serial);
460     return deviceSerial;
461 }
462 
GetRomVersion()463 std::string AntiFraudCloudService::GetRomVersion()
464 {
465     std::string fullVersion = system::GetParameter("const.product.software.version", "");
466     return GetSubstringBeforeSymbol(fullVersion, "(");
467 }
468 
GetSubstringBeforeSymbol(const std::string & str,const std::string & symbol)469 std::string AntiFraudCloudService::GetSubstringBeforeSymbol(const std::string &str, const std::string &symbol)
470 {
471     size_t pos = str.rfind(symbol);
472     if (pos != std::string::npos) {
473         return str.substr(0, pos);
474     } else {
475         return str;
476     }
477 }
478 } // namespace Telephony
479 } // namsespace OHOS