• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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