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