1 /* 2 * Copyright (C) 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 #include "hdc_huks.h" 16 #include "hks_param.h" 17 #include "hks_api.h" 18 #include "log.h" 19 #ifndef HDC_HOST 20 #include "os_account_manager.h" 21 #endif 22 namespace Hdc { 23 static const int AES_GCM_NONCE_BYTE_LEN = 12; 24 static const int AES_GCM_TAG_BYTE_LEN = 16; 25 26 struct HksParam aesBasePara [] = { 27 { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES }, 28 { .tag = HKS_TAG_KEY_SIZE, .uint32Param = HKS_AES_KEY_SIZE_256 }, 29 { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }, 30 { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM }, 31 { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE }, 32 }; 33 HdcHuks(const std::string & keyAlias)34 HdcHuks::HdcHuks(const std::string& keyAlias) 35 { 36 this->keyAlias = keyAlias; 37 this->keyBlobAlias = { static_cast<uint32_t>(this->keyAlias.length()), 38 reinterpret_cast<uint8_t*>(const_cast<char*>(this->keyAlias.c_str())) }; 39 } 40 41 #ifndef HDC_HOST GetUserId(void)42 static int32_t GetUserId(void) 43 { 44 std::vector<int32_t> ids; 45 46 OHOS::ErrCode err = OHOS::AccountSA::OsAccountManager::QueryActiveOsAccountIds(ids); 47 if (err != 0) { 48 WRITE_LOG(LOG_FATAL, "QueryActiveOsAccountIds failed, err %d", err); 49 return 0; 50 } 51 if (ids.empty()) { 52 WRITE_LOG(LOG_FATAL, "QueryActiveOsAccountIds is empty."); 53 return 0; 54 } 55 return ids[0]; 56 } 57 #endif DeleteAesKey(HksParamSet * paramSet)58 bool HdcHuks::DeleteAesKey(HksParamSet *paramSet) 59 { 60 if (!KeyExist(paramSet)) { 61 return true; 62 } 63 64 int32_t ret = HksDeleteKey(&(this->keyBlobAlias), paramSet); 65 if (ret != HKS_SUCCESS) { 66 WRITE_LOG(LOG_FATAL, "delete huks key, ret %d", ret); 67 return false; 68 } 69 return true; 70 } 71 ResetHuksKey(void)72 bool HdcHuks::ResetHuksKey(void) 73 { 74 bool genSuccess = false; 75 76 struct HksParamSet *paramSet = nullptr; 77 #ifndef HDC_HOST 78 int32_t currentUserId = GetUserId(); 79 if (currentUserId == 0) { 80 WRITE_LOG(LOG_FATAL, "current user id is 0, reset key failed."); 81 return false; 82 } 83 WRITE_LOG(LOG_INFO, "current user id %d", currentUserId); 84 #endif 85 struct HksParam genAesKeyPara[] = { 86 { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT | HKS_KEY_PURPOSE_DECRYPT }, 87 #ifndef HDC_HOST 88 { .tag = HKS_TAG_SPECIFIC_USER_ID, .int32Param = currentUserId }, 89 #endif 90 }; 91 92 if (!MakeHuksParamSet(¶mSet, aesBasePara, sizeof(aesBasePara) / sizeof(HksParam), 93 genAesKeyPara, sizeof(genAesKeyPara) / sizeof(HksParam))) { 94 return false; 95 } 96 do { 97 if (!DeleteAesKey(paramSet)) { 98 break; 99 } 100 if (!CreateAesKey(paramSet)) { 101 break; 102 } 103 genSuccess = true; 104 WRITE_LOG(LOG_FATAL, "reset key success"); 105 } while (0); 106 107 HksFreeParamSet(¶mSet); 108 return genSuccess; 109 } 110 KeyExist(struct HksParamSet * paramSet)111 bool HdcHuks::KeyExist(struct HksParamSet *paramSet) 112 { 113 int32_t keyExist = HksKeyExist(&(this->keyBlobAlias), paramSet); 114 WRITE_LOG(LOG_INFO, "query key alias, ret %d", keyExist); 115 if (keyExist == HKS_SUCCESS) { 116 return true; 117 } 118 return false; 119 } 120 CreateAesKey(struct HksParamSet * paramSet)121 bool HdcHuks::CreateAesKey(struct HksParamSet *paramSet) 122 { 123 int32_t ret = HksGenerateKey(&(this->keyBlobAlias), paramSet, nullptr); 124 if (ret != HKS_SUCCESS) { 125 WRITE_LOG(LOG_FATAL, "generate aes key failed, ret %d", ret); 126 return false; 127 } 128 return true; 129 } 130 GenerateNonce(uint8_t * nonce,int nonceBufLen)131 void HdcHuks::GenerateNonce(uint8_t *nonce, int nonceBufLen) 132 { 133 struct HksBlob nonceBlob = { nonceBufLen, nonce }; 134 HksGenerateRandom(nullptr, &nonceBlob); 135 } 136 MakeAesGcmEncryptParamSets(uint8_t * nonce,int length)137 struct HksParamSet* HdcHuks::MakeAesGcmEncryptParamSets(uint8_t *nonce, int length) 138 { 139 GenerateNonce(nonce, length); 140 struct HksParamSet *paramSet = nullptr; 141 #ifndef HDC_HOST 142 int32_t currentUserId = GetUserId(); 143 if (currentUserId == 0) { 144 WRITE_LOG(LOG_FATAL, "current user id is 0,failed."); 145 return nullptr; 146 } 147 WRITE_LOG(LOG_INFO, "current user id %d", currentUserId); 148 #endif 149 struct HksParam aesEncryptPara[] = { 150 { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT }, 151 { .tag = HKS_TAG_NONCE, .blob = { length, nonce} }, 152 #ifndef HDC_HOST 153 { .tag = HKS_TAG_SPECIFIC_USER_ID, .int32Param = currentUserId }, 154 #endif 155 }; 156 if (!MakeHuksParamSet(¶mSet, aesBasePara, sizeof(aesBasePara) / sizeof(HksParam), 157 aesEncryptPara, sizeof(aesEncryptPara) / sizeof(HksParam))) { 158 return nullptr; 159 } 160 return paramSet; 161 } 162 AesGcmEncrypt(const uint8_t * plainData,int plainDataLen,std::vector<uint8_t> & encryptData)163 bool HdcHuks::AesGcmEncrypt(const uint8_t* plainData, int plainDataLen, std::vector<uint8_t>& encryptData) 164 { 165 bool encryptSuccess = true; 166 struct HksParamSet *paramSet = nullptr; 167 /* 168 * encrypt data is : 12 bytes nonce + encrypt text(same length of plain text) + 16 bytes tag 169 */ 170 int encryptBufLen = AES_GCM_NONCE_BYTE_LEN + plainDataLen + AES_GCM_TAG_BYTE_LEN; 171 encryptData.resize(encryptBufLen); 172 173 paramSet = MakeAesGcmEncryptParamSets(encryptData.data(), AES_GCM_NONCE_BYTE_LEN); 174 if (paramSet == nullptr) { 175 return false; 176 } 177 struct HksBlob plainBlob = { plainDataLen, const_cast<uint8_t*>(plainData)}; 178 struct HksBlob encryptBlob = { encryptBufLen - AES_GCM_NONCE_BYTE_LEN, 179 encryptData.data() + AES_GCM_NONCE_BYTE_LEN 180 }; 181 int32_t ret = HksEncrypt(&(this->keyBlobAlias), paramSet, &plainBlob, &encryptBlob); 182 if (ret != HKS_SUCCESS) { 183 WRITE_LOG(LOG_FATAL, "HksEncrypt failed, ret %d", ret); 184 encryptSuccess = false; 185 } 186 187 WRITE_LOG(LOG_FATAL, "HksEncrypt encryptData len is %d", encryptData.size()); 188 HksFreeParamSet(¶mSet); 189 return encryptSuccess; 190 } 191 MakeAesGcmDecryptParamSets(std::vector<uint8_t> & nonce)192 struct HksParamSet* HdcHuks::MakeAesGcmDecryptParamSets(std::vector<uint8_t>& nonce) 193 { 194 struct HksParamSet *paramSet = nullptr; 195 196 #ifndef HDC_HOST 197 int32_t currentUserId = GetUserId(); 198 if (currentUserId == 0) { 199 WRITE_LOG(LOG_FATAL, "current user id is 0,failed."); 200 return nullptr; 201 } 202 WRITE_LOG(LOG_INFO, "current user id %d", currentUserId); 203 #endif 204 struct HksParam aesDecryptPara[] = { 205 { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_DECRYPT }, 206 { .tag = HKS_TAG_NONCE, .blob = { nonce.size(), nonce.data()} }, 207 #ifndef HDC_HOST 208 { .tag = HKS_TAG_SPECIFIC_USER_ID, .int32Param = currentUserId }, 209 #endif 210 211 }; 212 if (!MakeHuksParamSet(¶mSet, aesBasePara, sizeof(aesBasePara) / sizeof(HksParam), 213 aesDecryptPara, sizeof(aesDecryptPara) / sizeof(HksParam))) { 214 return nullptr; 215 } 216 return paramSet; 217 } 218 CheckEncryptDataLen(const std::string & encryptData)219 bool HdcHuks::CheckEncryptDataLen(const std::string& encryptData) 220 { 221 if (encryptData.length() < AES_GCM_NONCE_BYTE_LEN + AES_GCM_TAG_BYTE_LEN) { 222 WRITE_LOG(LOG_FATAL, "invalid data len %zd", encryptData.length()); 223 return false; 224 } 225 return true; 226 } 227 228 /* 229 * input data is 12 bytes(nonce value) + N bytes(encrypt data + 16 bytes(tag value)) 230 */ AesGcmDecrypt(const std::string & inputData)231 std::pair<uint8_t*, int> HdcHuks::AesGcmDecrypt(const std::string& inputData) 232 { 233 struct HksParamSet *paramSet = nullptr; 234 std::vector<uint8_t> encryptText; 235 std::vector<uint8_t> nonceValue; 236 237 if (!CheckEncryptDataLen(inputData)) { 238 return std::make_pair(nullptr, 0); 239 } 240 241 nonceValue.assign(inputData.begin(), inputData.begin() + AES_GCM_NONCE_BYTE_LEN); 242 encryptText.assign(inputData.begin() + AES_GCM_NONCE_BYTE_LEN, inputData.end()); 243 paramSet = MakeAesGcmDecryptParamSets(nonceValue); 244 if (paramSet == nullptr) { 245 return std::make_pair(nullptr, 0); 246 } 247 248 int maxPlainDataLen = inputData.size() - AES_GCM_NONCE_BYTE_LEN; 249 uint8_t *plainData = new(std::nothrow)uint8_t[maxPlainDataLen]; 250 if (plainData == nullptr) { 251 WRITE_LOG(LOG_FATAL, " out of memory %d", maxPlainDataLen); 252 HksFreeParamSet(¶mSet); 253 return std::make_pair(nullptr, 0); 254 } 255 256 struct HksBlob encryptBlob = { encryptText.size(), encryptText.data() }; 257 struct HksBlob plainBlob = { maxPlainDataLen, plainData}; 258 int32_t ret = HksDecrypt(&(this->keyBlobAlias), paramSet, &encryptBlob, &plainBlob); 259 if (ret != HKS_SUCCESS) { 260 WRITE_LOG(LOG_FATAL, "HksDecrypt failed, ret %d", ret); 261 delete[] plainData; 262 HksFreeParamSet(¶mSet); 263 return std::make_pair(nullptr, 0); 264 } 265 266 HksFreeParamSet(¶mSet); 267 return std::make_pair(plainData, plainBlob.size); 268 } 269 MakeHuksParamSet(struct HksParamSet ** paramSet,const struct HksParam * baseParams,int baseParamCount,const struct HksParam * params,int paramCount)270 bool HdcHuks::MakeHuksParamSet(struct HksParamSet **paramSet, 271 const struct HksParam *baseParams, int baseParamCount, const struct HksParam *params, int paramCount) 272 { 273 bool buildSuccess = true; 274 275 int32_t ret = HksInitParamSet(paramSet); 276 if (ret != HKS_SUCCESS) { 277 WRITE_LOG(LOG_FATAL, "HksInitParamSet failed, ret %d", ret); 278 return false; 279 } 280 do { 281 ret = HksAddParams(*paramSet, baseParams, baseParamCount); 282 if (ret != HKS_SUCCESS) { 283 WRITE_LOG(LOG_FATAL, "add base param failed, ret %d", ret); 284 buildSuccess = false; 285 break; 286 } 287 ret = HksAddParams(*paramSet, params, paramCount); 288 if (ret != HKS_SUCCESS) { 289 WRITE_LOG(LOG_FATAL, "add param failed, ret %d", ret); 290 buildSuccess = false; 291 break; 292 } 293 ret = HksBuildParamSet(paramSet); 294 if (ret != HKS_SUCCESS) { 295 WRITE_LOG(LOG_FATAL, "HksBuildParamSet failed, ret %d", ret); 296 buildSuccess = false; 297 break; 298 } 299 } while (0); 300 301 if (!buildSuccess) { 302 HksFreeParamSet(paramSet); 303 } 304 return buildSuccess; 305 } 306 CaculateGcmEncryptLen(int palinDataLen)307 int HdcHuks::CaculateGcmEncryptLen(int palinDataLen) 308 { 309 return palinDataLen + AES_GCM_NONCE_BYTE_LEN + AES_GCM_TAG_BYTE_LEN; 310 } 311 } // namespace Hdc