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 ¶m, RDBCryptoFault &rdbFault);
37 static std::vector<uint8_t> Decrypt(const RDBCryptoParam ¶m, 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 ¶m, RDBCryptoFault &rdbFault) asm(
46 "encrypt");
47 API_EXPORT std::vector<uint8_t> Decrypt(const OHOS::NativeRdb::RDBCryptoParam ¶m, 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 ¶m, 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 ¶m, 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(¶ms);
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(¶ms);
197 return ret;
198 }
199
200 ret = HksBuildParamSet(¶ms);
201 if (ret != HKS_SUCCESS) {
202 LOG_ERROR("HksBuildParamSet failed with error %{public}d", ret);
203 HksFreeParamSet(¶ms);
204 return ret;
205 }
206
207 ret = HksKeyExist(&rootKeyName, params);
208 HksFreeParamSet(¶ms);
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(¶ms);
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(¶ms);
240 return ret;
241 }
242
243 ret = HksBuildParamSet(¶ms);
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(¶ms);
248 return ret;
249 }
250
251 ret = HksGenerateKey(&rootKeyName, params, nullptr);
252 HksFreeParamSet(¶ms);
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 ¶m, 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(¶ms);
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(¶ms);
296 tempKey.assign(tempKey.size(), 0);
297 return {};
298 }
299
300 ret = HksBuildParamSet(¶ms);
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(¶ms);
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(¶ms);
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 ¶m, 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(¶ms);
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(¶ms);
344 return {};
345 }
346 ret = HksBuildParamSet(¶ms);
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(¶ms);
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(¶ms);
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