• 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 "relational_store_crypt.h"
16 #define LOG_TAG "RDBCryptoFault"
17 
18 #include <cstdint>
19 #include <cstring>
20 #include <vector>
21 
22 #include "hks_api.h"
23 #include "hks_param.h"
24 #include "logger.h"
25 #include "rdb_errno.h"
26 #include "rdb_visibility.h"
27 
28 using RDBCryptoFault = OHOS::NativeRdb::RDBCryptoFault;
29 using RdbSecretContent = OHOS::NativeRdb::RdbSecretContent;
30 namespace OHOS {
31 namespace NativeRdb {
32 class RDBCrypto {
33 public:
34     static int32_t CheckRootKeyExists(std::vector<uint8_t> &rootKeyAlias);
35     static int32_t GenerateRootKey(const std::vector<uint8_t> &rootKeyAlias, RDBCryptoFault &rdbFault);
36     static std::vector<uint8_t> Encrypt(const RDBCryptoParam &param, RDBCryptoFault &rdbFault);
37     static std::vector<uint8_t> Decrypt(const RDBCryptoParam &param, RDBCryptoFault &rdbFault);
38     static std::vector<uint8_t> GenerateRandomNum(int32_t &len);
39 };
40 } // namespace NativeRdb
41 } // namespace OHOS
42 API_EXPORT int32_t CheckRootKeyExists(std::vector<uint8_t> &rootKeyAlias) asm("checkRootKeyExists");
43 API_EXPORT int32_t GenerateRootKey(const std::vector<uint8_t> &rootKeyAlias, RDBCryptoFault &rdbFault) asm(
44     "generateRootKey");
45 API_EXPORT std::vector<uint8_t> Encrypt(const OHOS::NativeRdb::RDBCryptoParam &param, RDBCryptoFault &rdbFault) asm(
46     "encrypt");
47 API_EXPORT std::vector<uint8_t> Decrypt(const OHOS::NativeRdb::RDBCryptoParam &param, RDBCryptoFault &rdbFault) asm(
48     "decrypt");
49 API_EXPORT std::vector<uint8_t> GenerateRandomNum(int32_t &len) asm("generateRandomNum");
CheckRootKeyExists(std::vector<uint8_t> & rootKeyAlias)50 int32_t CheckRootKeyExists(std::vector<uint8_t> &rootKeyAlias)
51 {
52     return OHOS::NativeRdb::RDBCrypto::CheckRootKeyExists(rootKeyAlias);
53 }
GenerateRootKey(const std::vector<uint8_t> & rootKeyAlias,RDBCryptoFault & rdbFault)54 int32_t GenerateRootKey(const std::vector<uint8_t> &rootKeyAlias, RDBCryptoFault &rdbFault)
55 {
56     return OHOS::NativeRdb::RDBCrypto::GenerateRootKey(rootKeyAlias, rdbFault);
57 }
Encrypt(const OHOS::NativeRdb::RDBCryptoParam & param,RDBCryptoFault & rdbFault)58 std::vector<uint8_t> Encrypt(const OHOS::NativeRdb::RDBCryptoParam &param, RDBCryptoFault &rdbFault)
59 {
60     return OHOS::NativeRdb::RDBCrypto::Encrypt(param, rdbFault);
61 }
Decrypt(const OHOS::NativeRdb::RDBCryptoParam & param,RDBCryptoFault & rdbFault)62 std::vector<uint8_t> Decrypt(const OHOS::NativeRdb::RDBCryptoParam &param, RDBCryptoFault &rdbFault)
63 {
64     return OHOS::NativeRdb::RDBCrypto::Decrypt(param, rdbFault);
65 }
GenerateRandomNum(int32_t & len)66 std::vector<uint8_t> GenerateRandomNum(int32_t &len)
67 {
68     return OHOS::NativeRdb::RDBCrypto::GenerateRandomNum(len);
69 }
70 namespace OHOS {
71 namespace NativeRdb {
72 using namespace OHOS::Rdb;
73 constexpr const char *RDB_HKS_BLOB_TYPE_NONCE = "Z5s0Bo571Koq";
74 constexpr const char *RDB_HKS_BLOB_TYPE_AAD = "RdbClientAAD";
75 constexpr uint32_t TIMES = 4;
76 constexpr uint32_t MAX_UPDATE_SIZE = 64;
77 constexpr uint32_t MAX_OUTDATA_SIZE = MAX_UPDATE_SIZE * TIMES;
78 constexpr uint8_t AEAD_LEN = 16;
79 static std::vector<uint8_t> g_nonce(RDB_HKS_BLOB_TYPE_NONCE, RDB_HKS_BLOB_TYPE_NONCE + strlen(RDB_HKS_BLOB_TYPE_NONCE));
80 static std::vector<uint8_t> g_add(RDB_HKS_BLOB_TYPE_AAD, RDB_HKS_BLOB_TYPE_AAD + strlen(RDB_HKS_BLOB_TYPE_AAD));
81 
GetDfxFault(int32_t code,const std::string & message)82 RDBCryptoFault GetDfxFault(int32_t code, const std::string &message)
83 {
84     RDBCryptoFault rdbDfxFault;
85     rdbDfxFault.code = code;
86     rdbDfxFault.message = message;
87     return rdbDfxFault;
88 }
89 
HksLoopUpdate(const struct HksBlob * handle,const struct HksParamSet * paramSet,const struct HksBlob * inData,struct HksBlob * outData,RDBCryptoFault & rdbFault)90 int32_t HksLoopUpdate(const struct HksBlob *handle, const struct HksParamSet *paramSet, const struct HksBlob *inData,
91     struct HksBlob *outData, RDBCryptoFault &rdbFault)
92 {
93     if (outData->size < inData->size * TIMES) {
94         HksAbort(handle, paramSet);
95         rdbFault = GetDfxFault(E_WORK_KEY_FAIL, "HksLoopUpdate out size not enough");
96         return HKS_ERROR_INVALID_ARGUMENT;
97     }
98 
99     struct HksBlob input = { MAX_UPDATE_SIZE, inData->data };
100     uint8_t *end = inData->data + inData->size - 1;
101     outData->size = 0;
102     struct HksBlob output = { MAX_OUTDATA_SIZE, outData->data };
103     while (input.data <= end) {
104         if (input.data + MAX_UPDATE_SIZE > end) {
105             input.size = end - input.data + 1;
106             break;
107         }
108         auto result = HksUpdate(handle, paramSet, &input, &output);
109         if (result != HKS_SUCCESS) {
110             rdbFault = GetDfxFault(E_WORK_KEY_FAIL, "HksUpdate ret=" + std::to_string(result));
111             LOG_ERROR("HksUpdate Failed.");
112             return HKS_FAILURE;
113         }
114 
115         output.data += output.size;
116         outData->size += output.size;
117         input.data += MAX_UPDATE_SIZE;
118     }
119     output.size = input.size * TIMES;
120     auto result = HksFinish(handle, paramSet, &input, &output);
121     if (result != HKS_SUCCESS) {
122         rdbFault = GetDfxFault(E_WORK_KEY_FAIL, "HksFinish ret=" + std::to_string(result));
123         LOG_ERROR("HksFinish Failed.");
124         return HKS_FAILURE;
125     }
126     outData->size += output.size;
127     return HKS_SUCCESS;
128 }
129 
HksDecryptThreeStage(const struct HksBlob * keyAlias,const struct HksParamSet * paramSet,const struct HksBlob * cipherText,struct HksBlob * plainText,RDBCryptoFault & rdbFault)130 int32_t HksDecryptThreeStage(const struct HksBlob *keyAlias, const struct HksParamSet *paramSet,
131     const struct HksBlob *cipherText, struct HksBlob *plainText, RDBCryptoFault &rdbFault)
132 {
133     uint8_t handle[sizeof(uint64_t)] = { 0 };
134     struct HksBlob handleBlob = { sizeof(uint64_t), handle };
135     int32_t result = HksInit(keyAlias, paramSet, &handleBlob, nullptr);
136     if (result != HKS_SUCCESS) {
137         LOG_ERROR("HksEncrypt failed with error %{public}d", result);
138         rdbFault = GetDfxFault(E_WORK_KEY_DECRYPT_FAIL, "Decrypt HksInit ret=" + std::to_string(result));
139         return result;
140     }
141     result = HksLoopUpdate(&handleBlob, paramSet, cipherText, plainText, rdbFault);
142     if (result != HKS_SUCCESS) {
143         rdbFault = GetDfxFault(E_WORK_KEY_DECRYPT_FAIL, "Decrypt HksLoopUpdate ret=" + std::to_string(result));
144     }
145     return result;
146 }
147 
HksEncryptThreeStage(const struct HksBlob * keyAlias,const struct HksParamSet * paramSet,const struct HksBlob * plainText,struct HksBlob * cipherText,RDBCryptoFault & rdbFault)148 int32_t HksEncryptThreeStage(const struct HksBlob *keyAlias, const struct HksParamSet *paramSet,
149     const struct HksBlob *plainText, struct HksBlob *cipherText, RDBCryptoFault &rdbFault)
150 {
151     uint8_t handle[sizeof(uint64_t)] = { 0 };
152     struct HksBlob handleBlob = { sizeof(uint64_t), handle };
153     int32_t result = HksInit(keyAlias, paramSet, &handleBlob, nullptr);
154     if (result != HKS_SUCCESS) {
155         rdbFault = GetDfxFault(E_WORK_KEY_ENCRYPT_FAIL, "Decrypt HksInit ret=" + std::to_string(result));
156         LOG_ERROR("HksEncrypt failed with error %{public}d", result);
157         return result;
158     }
159     return HksLoopUpdate(&handleBlob, paramSet, plainText, cipherText, rdbFault);
160 }
161 
CreateHksParams(const HksBlob & blobNonce,const HksBlob & blobAad,const HksBlob & blobAead)162 std::vector<HksParam> CreateHksParams(const HksBlob &blobNonce, const HksBlob &blobAad, const HksBlob &blobAead)
163 {
164     return { { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES },
165         { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_DECRYPT },
166         { .tag = HKS_TAG_DIGEST, .uint32Param = 0 }, { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM },
167         { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }, { .tag = HKS_TAG_NONCE, .blob = blobNonce },
168         { .tag = HKS_TAG_ASSOCIATED_DATA, .blob = blobAad }, { .tag = HKS_TAG_AE_TAG, .blob = blobAead },
169         { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE } };
170 }
171 
CheckRootKeyExists(std::vector<uint8_t> & rootKeyAlias)172 int32_t RDBCrypto::CheckRootKeyExists(std::vector<uint8_t> &rootKeyAlias)
173 {
174     LOG_DEBUG("RDB checkRootKeyExist begin.");
175     struct HksBlob rootKeyName = { uint32_t(rootKeyAlias.size()), rootKeyAlias.data() };
176     struct HksParamSet *params = nullptr;
177     int32_t ret = HksInitParamSet(&params);
178     if (ret != HKS_SUCCESS) {
179         LOG_ERROR("HksInitParamSet()-client failed with error %{public}d", ret);
180         return ret;
181     }
182 
183     struct HksParam hksParam[] = {
184         { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES },
185         { .tag = HKS_TAG_KEY_SIZE, .uint32Param = HKS_AES_KEY_SIZE_256 },
186         { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT | HKS_KEY_PURPOSE_DECRYPT },
187         { .tag = HKS_TAG_DIGEST, .uint32Param = 0 },
188         { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE },
189         { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM },
190         { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE },
191     };
192 
193     ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0]));
194     if (ret != HKS_SUCCESS) {
195         LOG_ERROR("HksAddParams failed with error %{public}d", ret);
196         HksFreeParamSet(&params);
197         return ret;
198     }
199 
200     ret = HksBuildParamSet(&params);
201     if (ret != HKS_SUCCESS) {
202         LOG_ERROR("HksBuildParamSet failed with error %{public}d", ret);
203         HksFreeParamSet(&params);
204         return ret;
205     }
206 
207     ret = HksKeyExist(&rootKeyName, params);
208     HksFreeParamSet(&params);
209     return ret;
210 }
211 
GenerateRootKey(const std::vector<uint8_t> & rootKeyAlias,RDBCryptoFault & rdbFault)212 int32_t RDBCrypto::GenerateRootKey(const std::vector<uint8_t> &rootKeyAlias, RDBCryptoFault &rdbFault)
213 {
214     LOG_INFO("RDB GenerateRootKey begin.");
215     std::vector<uint8_t> tempRootKeyAlias = rootKeyAlias;
216     struct HksBlob rootKeyName = { uint32_t(rootKeyAlias.size()), tempRootKeyAlias.data() };
217     struct HksParamSet *params = nullptr;
218     int32_t ret = HksInitParamSet(&params);
219     if (ret != HKS_SUCCESS) {
220         rdbFault = GetDfxFault(E_ROOT_KEY_FAULT, "generator root key, HksInitParamSet ret=" + std::to_string(ret));
221         LOG_ERROR("HksInitParamSet()-client failed with error %{public}d", ret);
222         return ret;
223     }
224 
225     struct HksParam hksParam[] = {
226         { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES },
227         { .tag = HKS_TAG_KEY_SIZE, .uint32Param = HKS_AES_KEY_SIZE_256 },
228         { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT | HKS_KEY_PURPOSE_DECRYPT },
229         { .tag = HKS_TAG_DIGEST, .uint32Param = 0 },
230         { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE },
231         { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM },
232         { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE },
233     };
234 
235     ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0]));
236     if (ret != HKS_SUCCESS) {
237         rdbFault = GetDfxFault(E_ROOT_KEY_FAULT, "HksAddParams ret=" + std::to_string(ret));
238         LOG_ERROR("HksAddParams-client failed with error %{public}d", ret);
239         HksFreeParamSet(&params);
240         return ret;
241     }
242 
243     ret = HksBuildParamSet(&params);
244     if (ret != HKS_SUCCESS) {
245         rdbFault = GetDfxFault(E_ROOT_KEY_FAULT, "HksBuildParamSet ret=" + std::to_string(ret));
246         LOG_ERROR("HksBuildParamSet-client failed with error %{public}d", ret);
247         HksFreeParamSet(&params);
248         return ret;
249     }
250 
251     ret = HksGenerateKey(&rootKeyName, params, nullptr);
252     HksFreeParamSet(&params);
253     if (ret != HKS_SUCCESS) {
254         rdbFault = GetDfxFault(E_ROOT_KEY_FAULT, "HksGenerateKey ret=" + std::to_string(ret));
255         LOG_ERROR("HksGenerateKey-client failed with error %{public}d", ret);
256     }
257     return ret;
258 }
259 
CreateEncryptHksParams(const HksBlob & blobNonce,const HksBlob & blobAad)260 std::vector<HksParam> CreateEncryptHksParams(const HksBlob &blobNonce, const HksBlob &blobAad)
261 {
262     return {
263         { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES },
264         { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT },
265         { .tag = HKS_TAG_DIGEST, .uint32Param = 0 },
266         { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM },
267         { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE },
268         { .tag = HKS_TAG_NONCE, .blob = blobNonce },
269         { .tag = HKS_TAG_ASSOCIATED_DATA, .blob = blobAad },
270         { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE } };
271 }
272 
Encrypt(const RDBCryptoParam & param,RDBCryptoFault & rdbFault)273 std::vector<uint8_t> RDBCrypto::Encrypt(const RDBCryptoParam &param, RDBCryptoFault &rdbFault)
274 {
275     std::vector<uint8_t> tempRootKeyAlias(param.rootAlias);
276     std::vector<uint8_t> tempKey(param.KeyValue);
277     struct HksParamSet *params = nullptr;
278     int32_t ret = HksInitParamSet(&params);
279     if (ret != HKS_SUCCESS) {
280         rdbFault = GetDfxFault(E_WORK_KEY_ENCRYPT_FAIL, "Encrypt HksInitParamSet ret=" + std::to_string(ret));
281         LOG_ERROR("HksInitParamSet() failed with error %{public}d", ret);
282         tempKey.assign(tempKey.size(), 0);
283         return {};
284     }
285     struct HksBlob blobAad = { uint32_t(g_add.size()), g_add.data() };
286     struct HksBlob rootKeyName = { uint32_t(tempRootKeyAlias.size()), tempRootKeyAlias.data() };
287     struct HksBlob plainKey = { uint32_t(tempKey.size()), tempKey.data() };
288     struct HksBlob blobNonce = { uint32_t(param.nonce_.size()), const_cast<uint8_t*>(&(param.nonce_[0])) };
289 
290     auto hksParams = CreateEncryptHksParams(blobNonce, blobAad);
291     ret = HksAddParams(params, hksParams.data(), hksParams.size());
292     if (ret != HKS_SUCCESS) {
293         rdbFault = GetDfxFault(E_WORK_KEY_ENCRYPT_FAIL, "Encrypt HksAddParams ret=" + std::to_string(ret));
294         LOG_ERROR("HksAddParams failed with error %{public}d", ret);
295         HksFreeParamSet(&params);
296         tempKey.assign(tempKey.size(), 0);
297         return {};
298     }
299 
300     ret = HksBuildParamSet(&params);
301     if (ret != HKS_SUCCESS) {
302         rdbFault = GetDfxFault(E_WORK_KEY_ENCRYPT_FAIL, "Encrypt HksBuildParamSet ret=" + std::to_string(ret));
303         LOG_ERROR("HksBuildParamSet failed with error %{public}d", ret);
304         HksFreeParamSet(&params);
305         tempKey.assign(tempKey.size(), 0);
306         return {};
307     }
308     std::vector<uint8_t> encryptedKey(plainKey.size * TIMES + 1);
309     struct HksBlob cipherText = { uint32_t(encryptedKey.size()), encryptedKey.data() };
310     ret = HksEncryptThreeStage(&rootKeyName, params, &plainKey, &cipherText, rdbFault);
311     (void)HksFreeParamSet(&params);
312     if (ret != HKS_SUCCESS) {
313         encryptedKey.assign(encryptedKey.size(), 0);
314         tempKey.assign(tempKey.size(), 0);
315         return {};
316     }
317     encryptedKey.resize(cipherText.size);
318     tempKey.assign(tempKey.size(), 0);
319     return encryptedKey;
320 }
321 
Decrypt(const RDBCryptoParam & param,RDBCryptoFault & rdbFault)322 std::vector<uint8_t> RDBCrypto::Decrypt(const RDBCryptoParam &param, RDBCryptoFault &rdbFault)
323 {
324     std::vector<uint8_t> tempRootKeyAlias(param.rootAlias);
325     std::vector<uint8_t> source(param.KeyValue);
326     struct HksBlob blobAad = { uint32_t(g_add.size()), &(g_add[0]) };
327     struct HksBlob blobNonce = { uint32_t(param.nonce_.size()), const_cast<uint8_t*>(&(param.nonce_[0])) };
328     struct HksBlob rootKeyName = { uint32_t(tempRootKeyAlias.size()), &(tempRootKeyAlias[0]) };
329     struct HksBlob encryptedKeyBlob = { uint32_t(source.size() - AEAD_LEN), source.data() };
330     struct HksBlob blobAead = { AEAD_LEN, source.data() + source.size() - AEAD_LEN };
331     struct HksParamSet *params = nullptr;
332     int32_t ret = HksInitParamSet(&params);
333     if (ret != HKS_SUCCESS) {
334         rdbFault = GetDfxFault(E_WORK_KEY_DECRYPT_FAIL, "HksInitParamSet ret=" + std::to_string(ret));
335         LOG_ERROR("HksInitParamSet() failed with error %{public}d", ret);
336         return {};
337     }
338     auto hksParams = CreateHksParams(blobNonce, blobAad, blobAead);
339     ret = HksAddParams(params, hksParams.data(), hksParams.size());
340     if (ret != HKS_SUCCESS) {
341         rdbFault = GetDfxFault(E_WORK_KEY_DECRYPT_FAIL, "HksAddParams ret=" + std::to_string(ret));
342         LOG_ERROR("HksAddParams failed with error %{public}d", ret);
343         HksFreeParamSet(&params);
344         return {};
345     }
346     ret = HksBuildParamSet(&params);
347     if (ret != HKS_SUCCESS) {
348         rdbFault = GetDfxFault(E_WORK_KEY_DECRYPT_FAIL, "HksBuildParamSet ret=" + std::to_string(ret));
349         LOG_ERROR("HksBuildParamSet failed with error %{public}d", ret);
350         HksFreeParamSet(&params);
351         return {};
352     }
353     std::vector<uint8_t> decryptKey(encryptedKeyBlob.size * TIMES + 1);
354     struct HksBlob plainKeyBlob = { uint32_t(decryptKey.size()), decryptKey.data() };
355     ret = HksDecryptThreeStage(&rootKeyName, params, &encryptedKeyBlob, &plainKeyBlob, rdbFault);
356     (void)HksFreeParamSet(&params);
357     if (ret != HKS_SUCCESS) {
358         decryptKey.assign(decryptKey.size(), 0);
359         LOG_ERROR("HksDecrypt failed with error %{public}d", ret);
360         return {};
361     }
362     decryptKey.resize(plainKeyBlob.size);
363     return decryptKey;
364 }
365 
GenerateRandomNum(int32_t & len)366 std::vector<uint8_t> RDBCrypto::GenerateRandomNum(int32_t &len)
367 {
368     std::vector<uint8_t> value(len, 0);
369     struct HksBlob blobValue = { .size = len, .data = &(value[0]) };
370     auto ret = HksGenerateRandom(nullptr, &blobValue);
371     if (ret != HKS_SUCCESS) {
372         LOG_ERROR("HksGenerateRandom failed, status: %{public}d", ret);
373         return {};
374     }
375     return value;
376 }
377 } // namespace NativeRdb
378 } // namespace OHOS