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