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 "huks_aes_adapter.h"
16
17 #include <string>
18 #include "hks_api.h"
19 #include "securec.h"
20 #include "intell_voice_log.h"
21 #include "scope_guard.h"
22
23 #define LOG_TAG "HuksAesAdapter"
24
25 using namespace std;
26
27 namespace OHOS {
28 namespace IntellVoiceUtils {
29 static char g_aliasName[] = "IntelligentVoiceKey";
30 static char g_aadValue[] = "IntelligentVoiceAAD";
31
32 static constexpr uint32_t MAX_UPDATE_SIZE = 64 * 1024;
33 static constexpr uint32_t MAX_OUTDATA_SIZE = 128 * 1024;
34
35 static constexpr uint32_t NONCE_SIZE = 12;
36 static constexpr uint32_t AEAD_SIZE = 16;
37
38 static struct HksParam g_existParams[] = {
39 {
40 .tag = HKS_TAG_AUTH_STORAGE_LEVEL,
41 .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE
42 }
43 };
44
45 static struct HksParam g_genParams[] = {
46 {
47 .tag = HKS_TAG_ALGORITHM,
48 .uint32Param = HKS_ALG_AES
49 }, {
50 .tag = HKS_TAG_PURPOSE,
51 .uint32Param = HKS_KEY_PURPOSE_ENCRYPT | HKS_KEY_PURPOSE_DECRYPT
52 }, {
53 .tag = HKS_TAG_KEY_SIZE,
54 .uint32Param = HKS_AES_KEY_SIZE_128
55 }, {
56 .tag = HKS_TAG_PADDING,
57 .uint32Param = HKS_PADDING_NONE
58 }, {
59 .tag = HKS_TAG_BLOCK_MODE,
60 .uint32Param = HKS_MODE_GCM
61 }, {
62 .tag = HKS_TAG_AUTH_STORAGE_LEVEL,
63 .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE
64 }
65 };
66
CreateEncryptParamSet(struct HksParamSet ** encryptParamSet,struct HksBlob * encryptNonce)67 int32_t HuksAesAdapter::CreateEncryptParamSet(struct HksParamSet **encryptParamSet, struct HksBlob *encryptNonce)
68 {
69 int32_t ret = HksGenerateRandom(nullptr, encryptNonce);
70 if (ret != HKS_SUCCESS) {
71 INTELL_VOICE_LOG_ERROR("generate random encrypt nonce failed, ret:%{public}d", ret);
72 return ret;
73 }
74
75 struct HksParam encryptParams[] = {
76 {
77 .tag = HKS_TAG_ALGORITHM,
78 .uint32Param = HKS_ALG_AES
79 }, {
80 .tag = HKS_TAG_PURPOSE,
81 .uint32Param = HKS_KEY_PURPOSE_ENCRYPT
82 }, {
83 .tag = HKS_TAG_KEY_SIZE,
84 .uint32Param = HKS_AES_KEY_SIZE_128
85 }, {
86 .tag = HKS_TAG_PADDING,
87 .uint32Param = HKS_PADDING_NONE
88 }, {
89 .tag = HKS_TAG_BLOCK_MODE,
90 .uint32Param = HKS_MODE_GCM
91 }, {
92 .tag = HKS_TAG_DIGEST,
93 .uint32Param = HKS_DIGEST_NONE
94 }, {
95 .tag = HKS_TAG_ASSOCIATED_DATA,
96 .blob = {
97 .size = static_cast<uint32_t>(strlen(g_aadValue)),
98 .data = reinterpret_cast<uint8_t*>(g_aadValue)
99 }
100 }, {
101 .tag = HKS_TAG_NONCE,
102 .blob = {
103 .size = encryptNonce->size,
104 .data = encryptNonce->data
105 }
106 }, {
107 .tag = HKS_TAG_AUTH_STORAGE_LEVEL,
108 .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE
109 }
110 };
111 ret = ConstructParamSet(encryptParamSet, encryptParams, sizeof(encryptParams) / sizeof(struct HksParam));
112 if (ret != HKS_SUCCESS) {
113 INTELL_VOICE_LOG_ERROR("constuct encrypt param set failed, ret:%{public}d", ret);
114 }
115 return ret;
116 }
117
CreateDecryptParamSet(struct HksParamSet ** decryptParamSet,struct HksBlob * decryptNonce,struct HksBlob * decryptAead)118 int32_t HuksAesAdapter::CreateDecryptParamSet(struct HksParamSet **decryptParamSet, struct HksBlob *decryptNonce,
119 struct HksBlob *decryptAead)
120 {
121 struct HksParam decryptParams[] = {
122 {
123 .tag = HKS_TAG_ALGORITHM,
124 .uint32Param = HKS_ALG_AES
125 }, {
126 .tag = HKS_TAG_PURPOSE,
127 .uint32Param = HKS_KEY_PURPOSE_DECRYPT
128 }, {
129 .tag = HKS_TAG_KEY_SIZE,
130 .uint32Param = HKS_AES_KEY_SIZE_128
131 }, {
132 .tag = HKS_TAG_PADDING,
133 .uint32Param = HKS_PADDING_NONE
134 }, {
135 .tag = HKS_TAG_BLOCK_MODE,
136 .uint32Param = HKS_MODE_GCM
137 }, {
138 .tag = HKS_TAG_DIGEST,
139 .uint32Param = HKS_DIGEST_NONE
140 }, {
141 .tag = HKS_TAG_ASSOCIATED_DATA,
142 .blob = {
143 .size = static_cast<uint32_t>(strlen(g_aadValue)),
144 .data = reinterpret_cast<uint8_t*>(g_aadValue)
145 }
146 }, {
147 .tag = HKS_TAG_NONCE,
148 .blob = {
149 .size = decryptNonce->size,
150 .data = decryptNonce->data
151 }
152 }, {
153 .tag = HKS_TAG_AE_TAG,
154 .blob = {
155 .size = decryptAead->size,
156 .data = decryptAead->data
157 }
158 }, {
159 .tag = HKS_TAG_AUTH_STORAGE_LEVEL,
160 .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE
161 }
162 };
163
164 int32_t ret = ConstructParamSet(decryptParamSet, decryptParams, sizeof(decryptParams) / sizeof(struct HksParam));
165 if (ret != HKS_SUCCESS) {
166 INTELL_VOICE_LOG_ERROR("constuct decrypt param set failed, ret:%{public}d", ret);
167 }
168 return ret;
169 }
170
Encrypt(std::unique_ptr<Uint8ArrayBuffer> & inBuffer,std::unique_ptr<Uint8ArrayBuffer> & outBuffer)171 int32_t HuksAesAdapter::Encrypt(std::unique_ptr<Uint8ArrayBuffer> &inBuffer,
172 std::unique_ptr<Uint8ArrayBuffer> &outBuffer)
173 {
174 CHECK_CONDITION_RETURN_RET(((inBuffer == nullptr) || (inBuffer->GetSize() == 0)), HKS_ERROR_INVALID_ARGUMENT,
175 "invalid arguments");
176 struct HksBlob keyAlias = { static_cast<uint32_t>(strlen(g_aliasName)), reinterpret_cast<uint8_t *>(g_aliasName) };
177 bool isExist = false;
178 int32_t ret = IsKeyExist(&keyAlias, isExist);
179 CHECK_CONDITION_RETURN_RET((ret != HKS_SUCCESS), ret, "key exist failed");
180 if (!isExist) {
181 ret = GenerateKey(&keyAlias);
182 CHECK_CONDITION_RETURN_RET((ret != HKS_SUCCESS), ret, "generate key failed");
183 }
184
185 struct HksParamSet *encryptParamSet = nullptr;
186 uint8_t nonceValue[NONCE_SIZE] = { 0 };
187 struct HksBlob encryptNonce = { NONCE_SIZE, nonceValue};
188 ret = CreateEncryptParamSet(&encryptParamSet, &encryptNonce);
189 CHECK_CONDITION_RETURN_RET((ret != HKS_SUCCESS), ret, "create encrypt param set failed");
190
191 ON_SCOPE_EXIT {
192 HksFreeParamSet(&encryptParamSet);
193 };
194
195 uint8_t handle[sizeof(uint64_t)] = {0};
196 struct HksBlob handleEncrypt = { sizeof(uint64_t), handle };
197 ret = HksInit(&keyAlias, encryptParamSet, &handleEncrypt, nullptr);
198 if (ret != HKS_SUCCESS) {
199 INTELL_VOICE_LOG_ERROR("huks init failed, ret:%{public}d", ret);
200 return ret;
201 }
202
203 struct HksBlob inData = { inBuffer->GetSize() * sizeof(uint8_t), inBuffer->GetData() };
204 auto encryptData = std::make_unique<uint8_t[]>(inBuffer->GetSize() * sizeof(uint8_t) + NONCE_SIZE + AEAD_SIZE);
205 CHECK_CONDITION_RETURN_RET((encryptData == nullptr), HKS_ERROR_MALLOC_FAIL, "encryptData is nullptr");
206
207 struct HksBlob outData = { inBuffer->GetSize() * sizeof(uint8_t) + AEAD_SIZE, encryptData.get() + NONCE_SIZE };
208
209 ret = UpdateAndFinish(&handleEncrypt, encryptParamSet, &inData, &outData);
210 CHECK_CONDITION_RETURN_RET((ret != HKS_SUCCESS), ret, "update and finish failed");
211
212 (void)memcpy_s(encryptData.get(), NONCE_SIZE, encryptNonce.data, encryptNonce.size);
213 outBuffer = CreateArrayBuffer<uint8_t>(outData.size + NONCE_SIZE, encryptData.get());
214 if (outBuffer == nullptr) {
215 INTELL_VOICE_LOG_ERROR("allocate out buffer failed, size:%{public}u", outData.size);
216 return HKS_ERROR_MALLOC_FAIL;
217 }
218 return HKS_SUCCESS;
219 }
220
Decrypt(std::unique_ptr<Uint8ArrayBuffer> & inBuffer,std::unique_ptr<Uint8ArrayBuffer> & outBuffer)221 int32_t HuksAesAdapter::Decrypt(std::unique_ptr<Uint8ArrayBuffer> &inBuffer,
222 std::unique_ptr<Uint8ArrayBuffer> &outBuffer)
223 {
224 if ((inBuffer == nullptr) || (inBuffer->GetSize() <= (NONCE_SIZE + AEAD_SIZE))) {
225 return HKS_ERROR_INVALID_ARGUMENT;
226 }
227
228 struct HksBlob keyAlias = { static_cast<uint32_t>(strlen(g_aliasName)), reinterpret_cast<uint8_t *>(g_aliasName) };
229 bool isExist = false;
230 int32_t ret = IsKeyExist(&keyAlias, isExist);
231 CHECK_CONDITION_RETURN_RET((ret != HKS_SUCCESS), ret, "key exist failed");
232 CHECK_CONDITION_RETURN_RET((!isExist), HKS_FAILURE, "key is not exist");
233
234 struct HksParamSet *decryptParamSet = nullptr;
235 struct HksBlob decryptNonce = { NONCE_SIZE, inBuffer->GetData() };
236 struct HksBlob decryptAead = { AEAD_SIZE, inBuffer->GetData() + inBuffer->GetSize() * sizeof(uint8_t) - AEAD_SIZE};
237 ret = CreateDecryptParamSet(&decryptParamSet, &decryptNonce, &decryptAead);
238 CHECK_CONDITION_RETURN_RET((ret != HKS_SUCCESS), ret, "create decrypt param set failed");
239
240 ON_SCOPE_EXIT {
241 HksFreeParamSet(&decryptParamSet);
242 };
243
244 uint8_t handle[sizeof(uint64_t)] = { 0 };
245 struct HksBlob handleDecrypt = { sizeof(uint64_t), handle };
246 ret = HksInit(&keyAlias, decryptParamSet, &handleDecrypt, nullptr);
247 if (ret != HKS_SUCCESS) {
248 INTELL_VOICE_LOG_ERROR("huks init failed, ret:%{public}d", ret);
249 return ret;
250 }
251
252 auto decryptData = std::make_unique<uint8_t[]>(inBuffer->GetSize() * sizeof(uint8_t) - NONCE_SIZE - AEAD_SIZE);
253 CHECK_CONDITION_RETURN_RET((decryptData == nullptr), HKS_ERROR_MALLOC_FAIL, "decryptData is nullptr");
254
255 struct HksBlob inData = { inBuffer->GetSize() * sizeof(uint8_t) - NONCE_SIZE - AEAD_SIZE,
256 inBuffer->GetData() + NONCE_SIZE };
257 struct HksBlob outData = { inBuffer->GetSize() * sizeof(uint8_t) - NONCE_SIZE - AEAD_SIZE, decryptData.get() };
258
259 ret = UpdateAndFinish(&handleDecrypt, decryptParamSet, &inData, &outData);
260 if (ret != HKS_SUCCESS) {
261 INTELL_VOICE_LOG_ERROR("update and finish failed, size:%{public}u", outData.size);
262 return ret;
263 }
264
265 outBuffer = CreateArrayBuffer<uint8_t>(outData.size, outData.data);
266 if (outBuffer == nullptr) {
267 INTELL_VOICE_LOG_ERROR("allocate out buffer failed, size:%{public}u", outData.size);
268 return HKS_ERROR_MALLOC_FAIL;
269 }
270 return HKS_SUCCESS;
271 }
272
IsKeyExist(struct HksBlob * keyAlias,bool & isExist)273 int32_t HuksAesAdapter::IsKeyExist(struct HksBlob *keyAlias, bool &isExist)
274 {
275 struct HksParamSet *existParamSet = nullptr;
276 int32_t ret = ConstructParamSet(&existParamSet, g_existParams, sizeof(g_existParams) / sizeof(struct HksParam));
277 if (ret != HKS_SUCCESS) {
278 INTELL_VOICE_LOG_ERROR("constuct exist param set failed");
279 return ret;
280 }
281
282 if (HksKeyExist(keyAlias, existParamSet) == HKS_SUCCESS) {
283 INTELL_VOICE_LOG_INFO("key is already exist");
284 isExist = true;
285 } else {
286 INTELL_VOICE_LOG_INFO("key is not exist");
287 isExist = false;
288 }
289
290 HksFreeParamSet(&existParamSet);
291 return HKS_SUCCESS;
292 }
293
GenerateKey(struct HksBlob * keyAlias)294 int32_t HuksAesAdapter::GenerateKey(struct HksBlob *keyAlias)
295 {
296 struct HksParamSet *genParamSet = nullptr;
297 int32_t ret = ConstructParamSet(&genParamSet, g_genParams, sizeof(g_genParams) / sizeof(struct HksParam));
298 if (ret != HKS_SUCCESS) {
299 INTELL_VOICE_LOG_ERROR("constuct gen param set failed");
300 return ret;
301 }
302
303 ret = HksGenerateKey(keyAlias, genParamSet, nullptr);
304 if (ret != HKS_SUCCESS) {
305 INTELL_VOICE_LOG_ERROR("generate key failed, ret:%{public}d", ret);
306 }
307
308 HksFreeParamSet(&genParamSet);
309 return ret;
310 }
311
ConstructParamSet(struct HksParamSet ** paramSet,const struct HksParam * params,uint32_t paramCount)312 int32_t HuksAesAdapter::ConstructParamSet(struct HksParamSet **paramSet, const struct HksParam *params,
313 uint32_t paramCount)
314 {
315 int32_t ret = HksInitParamSet(paramSet);
316 if (ret != HKS_SUCCESS) {
317 INTELL_VOICE_LOG_ERROR("HksInitParamSet failed, ret:%{public}d", ret);
318 return ret;
319 }
320
321 ON_SCOPE_EXIT {
322 HksFreeParamSet(paramSet);
323 };
324
325 ret = HksAddParams(*paramSet, params, paramCount);
326 if (ret != HKS_SUCCESS) {
327 INTELL_VOICE_LOG_ERROR("HksAddParams failed, ret:%{public}d", ret);
328 return ret;
329 }
330
331 ret = HksBuildParamSet(paramSet);
332 if (ret != HKS_SUCCESS) {
333 INTELL_VOICE_LOG_ERROR("HksBuildParamSet failed, ret:%{public}d", ret);
334 return ret;
335 }
336
337 CANCEL_SCOPE_EXIT;
338 return ret;
339 }
340
UpdateAndFinish(const struct HksBlob * handle,const struct HksParamSet * paramSet,const struct HksBlob * inData,struct HksBlob * outData)341 int32_t HuksAesAdapter::UpdateAndFinish(const struct HksBlob *handle, const struct HksParamSet *paramSet,
342 const struct HksBlob *inData, struct HksBlob *outData)
343 {
344 struct HksBlob inDataSeg = { MAX_UPDATE_SIZE, inData->data };
345 struct HksBlob outDataSeg = { MAX_OUTDATA_SIZE, nullptr };
346 uint32_t inUpdateSize = 0;
347 uint8_t *outDataAddr = outData->data;
348 uint32_t outUpdateSize = 0;
349 int32_t ret = HKS_SUCCESS;
350
351 while (inUpdateSize < inData->size) {
352 if (inUpdateSize + MAX_UPDATE_SIZE >= inData->size) {
353 inDataSeg.size = inData->size - inUpdateSize;
354 break;
355 }
356
357 std::unique_ptr<Uint8ArrayBuffer> tmpUpdateBuff= CreateArrayBuffer<uint8_t>(outDataSeg.size);
358 CHECK_CONDITION_RETURN_RET((tmpUpdateBuff == nullptr), HKS_FAILURE, "tmpUpdateBuff is nullptr");
359 outDataSeg.data = tmpUpdateBuff->GetData();
360
361 ret = HksUpdate(handle, paramSet, &inDataSeg, &outDataSeg);
362 if (ret != HKS_SUCCESS) {
363 INTELL_VOICE_LOG_ERROR("Hks update failed, ret:%{public}d", ret);
364 return HKS_FAILURE;
365 }
366
367 if (outUpdateSize + outDataSeg.size > outData->size) {
368 INTELL_VOICE_LOG_ERROR("Hks update size failed, outUpdateSize:%{public}u", outUpdateSize);
369 return HKS_FAILURE;
370 }
371
372 (void)memcpy_s(outDataAddr, outData->size - outUpdateSize, outDataSeg.data, outDataSeg.size);
373 outDataAddr += outDataSeg.size;
374 outUpdateSize += outDataSeg.size;
375 tmpUpdateBuff = nullptr;
376 inUpdateSize += MAX_UPDATE_SIZE;
377 inDataSeg.data = inData->data + inUpdateSize;
378 }
379
380 std::unique_ptr<Uint8ArrayBuffer> tmpFinishBuff= CreateArrayBuffer<uint8_t>(inDataSeg.size + AEAD_SIZE);
381 CHECK_CONDITION_RETURN_RET((tmpFinishBuff == nullptr), HKS_FAILURE, "tmpFinishBuff is nullptr");
382
383 struct HksBlob outDataFinish = { tmpFinishBuff->GetSize() * sizeof(uint8_t), tmpFinishBuff->GetData() };
384 ret = HksFinish(handle, paramSet, &inDataSeg, &outDataFinish);
385 if (ret != HKS_SUCCESS) {
386 INTELL_VOICE_LOG_ERROR("Hks finish failed, ret:%{public}d", ret);
387 return HKS_FAILURE;
388 }
389
390 if (outUpdateSize + outDataFinish.size > outData->size) {
391 INTELL_VOICE_LOG_ERROR("%{public}u, %{public}u, %{public}u", outUpdateSize, outDataFinish.size, outData->size);
392 return HKS_FAILURE;
393 }
394 (void)memcpy_s(outDataAddr, outData->size - outUpdateSize, outDataFinish.data, outDataFinish.size);
395 outData->size = outUpdateSize + outDataFinish.size;
396
397 return HKS_SUCCESS;
398 }
399 }
400 }
401