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