1 /*
2 * Copyright (c) 2023 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 "dm_crypto.h"
16 #include "dm_log.h"
17 #if !(defined(__LITEOS_M__) || defined(LITE_DEVICE))
18 #include "datetime_ex.h"
19 #include "kv_adapter_manager.h"
20 #endif
21 #include <iostream>
22 #include <sstream>
23
24 #include <openssl/rand.h>
25 #include "openssl/sha.h"
26
27 namespace OHOS {
28 namespace DistributedHardware {
29
30 constexpr int32_t HEX_TO_UINT8 = 2;
31 constexpr int WIDTH = 4;
32 constexpr unsigned char MASK = 0x0F;
33 constexpr int DEC_MAX_NUM = 10;
34 constexpr int HEX_MAX_BIT_NUM = 4;
35 constexpr uint32_t ERR_DM_FAILED = 96929744;
36 constexpr int32_t DM_OK = 0;
37 constexpr int32_t DM_ERR = -1;
38 constexpr int32_t ERR_DM_INPUT_PARA_INVALID = 96929749;
39 constexpr int HEX_DIGIT_MAX_NUM = 16;
40 constexpr int SHORT_DEVICE_ID_HASH_LENGTH = 16;
41 constexpr int32_t SALT_LENGTH = 8;
42 const std::string SALT_DEFAULT = "salt_defsalt_def";
43 constexpr int SHORT_ACCOUNTID_ID_HASH_LENGTH = 6;
44 #if !(defined(__LITEOS_M__) || defined(LITE_DEVICE))
45 #define DM_MAX_DEVICE_ID_LEN (97)
46 #endif
47
HexifyLen(uint32_t len)48 uint32_t HexifyLen(uint32_t len)
49 {
50 return len * HEX_TO_UINT8 + 1;
51 }
52
DmGenerateStrHash(const void *data, size_t dataSize, unsigned char *outBuf, uint32_t outBufLen, uint32_t startIndex)53 void DmGenerateStrHash(const void *data, size_t dataSize, unsigned char *outBuf, uint32_t outBufLen,
54 uint32_t startIndex)
55 {
56 if (data == nullptr || outBuf == nullptr || startIndex > outBufLen) {
57 LOGE("Invalied param.");
58 return;
59 }
60 SHA256_CTX ctx;
61 SHA256_Init(&ctx);
62 SHA256_Update(&ctx, data, dataSize);
63 SHA256_Final(&outBuf[startIndex], &ctx);
64 }
65
ConvertBytesToHexString(char *outBuf, uint32_t outBufLen, const unsigned char *inBuf, uint32_t inLen)66 int32_t ConvertBytesToHexString(char *outBuf, uint32_t outBufLen, const unsigned char *inBuf,
67 uint32_t inLen)
68 {
69 if ((outBuf == nullptr) || (inBuf == nullptr) || (outBufLen < HexifyLen(inLen))) {
70 return ERR_DM_INPUT_PARA_INVALID;
71 }
72 while (inLen > 0) {
73 unsigned char h = *inBuf / HEX_DIGIT_MAX_NUM;
74 unsigned char l = *inBuf % HEX_DIGIT_MAX_NUM;
75 if (h < DEC_MAX_NUM) {
76 *outBuf++ = '0' + h;
77 } else {
78 *outBuf++ = 'a' + h - DEC_MAX_NUM;
79 }
80 if (l < DEC_MAX_NUM) {
81 *outBuf++ = '0' + l;
82 } else {
83 *outBuf++ = 'a' + l - DEC_MAX_NUM;
84 }
85 ++inBuf;
86 inLen--;
87 }
88 return DM_OK;
89 }
90
Sha256(const std::string &text, bool isUpper)91 std::string Crypto::Sha256(const std::string &text, bool isUpper)
92 {
93 return Sha256(text.data(), text.size(), isUpper);
94 }
95
Sha256(const void *data, size_t size, bool isUpper)96 std::string Crypto::Sha256(const void *data, size_t size, bool isUpper)
97 {
98 unsigned char hash[SHA256_DIGEST_LENGTH * HEX_TO_UINT8 + 1] = "";
99 DmGenerateStrHash(data, size, hash, HexifyLen(SHA256_DIGEST_LENGTH), SHA256_DIGEST_LENGTH);
100 // here we translate sha256 hash to hexadecimal. each 8-bit char will be presented by two characters([0-9a-f])
101 const char* hexCode = isUpper ? "0123456789ABCDEF" : "0123456789abcdef";
102 for (int32_t i = 0; i < SHA256_DIGEST_LENGTH; ++i) {
103 unsigned char value = hash[SHA256_DIGEST_LENGTH + i];
104 // uint8_t is 2 digits in hexadecimal.
105 hash[i * HEX_TO_UINT8] = hexCode[(value >> WIDTH) & MASK];
106 hash[i * HEX_TO_UINT8 + 1] = hexCode[value & MASK];
107 }
108 hash[SHA256_DIGEST_LENGTH * HEX_TO_UINT8] = 0;
109 std::stringstream ss;
110 ss << hash;
111 return ss.str();
112 }
113
GetUdidHash(const std::string &udid, unsigned char *udidHash)114 int32_t Crypto::GetUdidHash(const std::string &udid, unsigned char *udidHash)
115 {
116 unsigned char hash[SHA256_DIGEST_LENGTH] = "";
117 DmGenerateStrHash(udid.data(), udid.size(), hash, SHA256_DIGEST_LENGTH, 0);
118 if (ConvertBytesToHexString(reinterpret_cast<char *>(udidHash), SHORT_DEVICE_ID_HASH_LENGTH + 1,
119 reinterpret_cast<const uint8_t *>(hash), SHORT_DEVICE_ID_HASH_LENGTH / HEX_TO_UINT8) != DM_OK) {
120 LOGE("ConvertBytesToHexString failed.");
121 return ERR_DM_FAILED;
122 }
123 return DM_OK;
124 }
125
ConvertHexStringToBytes(unsigned char *outBuf, uint32_t outBufLen, const char *inBuf, uint32_t inLen)126 int32_t Crypto::ConvertHexStringToBytes(unsigned char *outBuf, uint32_t outBufLen, const char *inBuf,
127 uint32_t inLen)
128 {
129 (void)outBufLen;
130 if ((outBuf == NULL) || (inBuf == NULL) || (inLen % HEX_TO_UINT8 != 0)) {
131 LOGE("invalid param");
132 return ERR_DM_FAILED;
133 }
134
135 uint32_t outLen = inLen / HEX_TO_UINT8;
136 uint32_t i = 0;
137 while (i < outLen) {
138 unsigned char c = *inBuf++;
139 if ((c >= '0') && (c <= '9')) {
140 c -= '0';
141 } else if ((c >= 'a') && (c <= 'f')) {
142 c -= 'a' - DEC_MAX_NUM;
143 } else if ((c >= 'A') && (c <= 'F')) {
144 c -= 'A' - DEC_MAX_NUM;
145 } else {
146 LOGE("HexToString Error! %{public}c", c);
147 return ERR_DM_FAILED;
148 }
149 unsigned char c2 = *inBuf++;
150 if ((c2 >= '0') && (c2 <= '9')) {
151 c2 -= '0';
152 } else if ((c2 >= 'a') && (c2 <= 'f')) {
153 c2 -= 'a' - DEC_MAX_NUM;
154 } else if ((c2 >= 'A') && (c2 <= 'F')) {
155 c2 -= 'A' - DEC_MAX_NUM;
156 } else {
157 LOGE("HexToString Error! %{public}c", c2);
158 return ERR_DM_FAILED;
159 }
160 *outBuf++ = (c << HEX_MAX_BIT_NUM) | c2;
161 i++;
162 }
163 return DM_OK;
164 }
165
GetGroupIdHash(const std::string &groupId)166 std::string Crypto::GetGroupIdHash(const std::string &groupId)
167 {
168 unsigned char hash[SHA256_DIGEST_LENGTH] = "";
169 DmGenerateStrHash(groupId.data(), groupId.size(), hash, SHA256_DIGEST_LENGTH, 0);
170 std::stringstream ss;
171 for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) {
172 ss << std::hex << (int)hash[i];
173 }
174 return ss.str().substr(0, SHORT_DEVICE_ID_HASH_LENGTH);
175 }
176
GetSecRandom(uint8_t *out, size_t outLen)177 int32_t Crypto::GetSecRandom(uint8_t *out, size_t outLen)
178 {
179 if (out == NULL) {
180 return DM_ERR;
181 }
182
183 if (outLen == 0) {
184 return DM_ERR;
185 }
186
187 RAND_poll();
188 RAND_bytes(out, outLen);
189 return DM_OK;
190 }
191
GetSecSalt()192 std::string Crypto::GetSecSalt()
193 {
194 uint8_t out[SALT_LENGTH] = {0};
195 if (Crypto::GetSecRandom(out, SALT_LENGTH) != DM_OK) {
196 return SALT_DEFAULT;
197 }
198
199 char outHex[SALT_LENGTH * HEX_TO_UINT8 + 1] = {0};
200 if (ConvertBytesToHexString(outHex, SALT_LENGTH * HEX_TO_UINT8 + 1, out, SALT_LENGTH) != DM_OK) {
201 return SALT_DEFAULT;
202 }
203
204 return std::string(outHex);
205 }
206
GetHashWithSalt(const std::string &text, const std::string &salt)207 std::string Crypto::GetHashWithSalt(const std::string &text, const std::string &salt)
208 {
209 std::string rawText = text + salt;
210 return Crypto::Sha256(rawText);
211 }
212
GetAccountIdHash(const std::string &accountId, unsigned char *accountIdHash)213 int32_t Crypto::GetAccountIdHash(const std::string &accountId, unsigned char *accountIdHash)
214 {
215 unsigned char hash[SHA256_DIGEST_LENGTH] = "";
216 DmGenerateStrHash(accountId.data(), accountId.size(), hash, SHA256_DIGEST_LENGTH, 0);
217 if (ConvertBytesToHexString(reinterpret_cast<char *>(accountIdHash), SHORT_ACCOUNTID_ID_HASH_LENGTH + 1,
218 reinterpret_cast<const uint8_t *>(hash), SHORT_ACCOUNTID_ID_HASH_LENGTH / HEX_TO_UINT8) != DM_OK) {
219 LOGE("ConvertBytesToHexString failed.");
220 return ERR_DM_FAILED;
221 }
222 return DM_OK;
223 }
224
225 #if !(defined(__LITEOS_M__) || defined(LITE_DEVICE))
ConvertUdidHashToAnoyAndSave(const std::string &appId, const std::string &udidHash, DmKVValue &kvValue)226 int32_t Crypto::ConvertUdidHashToAnoyAndSave(const std::string &appId, const std::string &udidHash,
227 DmKVValue &kvValue)
228 {
229 if (GetAnoyDeviceInfo(appId, udidHash, kvValue) == DM_OK) {
230 kvValue.lastModifyTime = GetSecondsSince1970ToNow();
231 KVAdapterManager::GetInstance().PutByAnoyDeviceId(kvValue.anoyDeviceId, kvValue);
232 return DM_OK;
233 }
234 int32_t ret = ConvertUdidHashToAnoyGenerate(appId, udidHash, kvValue);
235 if (ret != DM_OK) {
236 LOGE("failed");
237 return ERR_DM_FAILED;
238 }
239 KVAdapterManager::GetInstance().PutByAnoyDeviceId(kvValue.anoyDeviceId, kvValue);
240 return DM_OK;
241 }
242
ConvertUdidHashToAnoyDeviceId(const std::string &appId, const std::string &udidHash, DmKVValue &kvValue)243 int32_t Crypto::ConvertUdidHashToAnoyDeviceId(const std::string &appId, const std::string &udidHash,
244 DmKVValue &kvValue)
245 {
246 LOGI("start.");
247 if (GetAnoyDeviceInfo(appId, udidHash, kvValue) == DM_OK) {
248 return DM_OK;
249 }
250 return ConvertUdidHashToAnoyGenerate(appId, udidHash, kvValue);
251 }
252
GetAnoyDeviceInfo(const std::string &appId, const std::string &udidHash, DmKVValue &kvValue)253 int32_t Crypto::GetAnoyDeviceInfo(const std::string &appId, const std::string &udidHash, DmKVValue &kvValue)
254 {
255 LOGI("start");
256 std::string udidPrefix = appId + DB_KEY_DELIMITER + udidHash;
257 if (KVAdapterManager::GetInstance().Get(udidPrefix, kvValue) != DM_OK) {
258 LOGI("Get kv value from DB failed");
259 return ERR_DM_FAILED;
260 }
261 return DM_OK;
262 }
263
ConvertUdidHashToAnoyGenerate(const std::string &appId, const std::string &udidHash, DmKVValue &kvValue)264 int32_t Crypto::ConvertUdidHashToAnoyGenerate(const std::string &appId, const std::string &udidHash,
265 DmKVValue &kvValue)
266 {
267 LOGI("start.");
268 std::string salt = GetSecSalt();
269 std::string udidTemp = appId + DB_KEY_DELIMITER + udidHash + DB_KEY_DELIMITER + salt;
270 char anoyDeviceId[DM_MAX_DEVICE_ID_LEN] = {0};
271 if (GetUdidHash(udidTemp, reinterpret_cast<uint8_t *>(anoyDeviceId)) != DM_OK) {
272 LOGE("get anoyDeviceId by udidTemp failed.");
273 return ERR_DM_FAILED;
274 }
275 kvValue.udidHash = udidHash;
276 kvValue.anoyDeviceId = std::string(anoyDeviceId);
277 kvValue.appID = appId;
278 kvValue.salt = salt;
279 kvValue.lastModifyTime = GetSecondsSince1970ToNow();
280 return DM_OK;
281 }
282 #endif
283 } // namespace DistributedHardware
284 } // namespace OHOS
285