• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(&paramSet, 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(&paramSet);
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(&paramSet, 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(&paramSet);
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(&paramSet, 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(&paramSet);
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(&paramSet);
263             return std::make_pair(nullptr, 0);
264         }
265 
266         HksFreeParamSet(&paramSet);
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