• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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  * Description: encrypt and decrypt data module
15  * Author: lijianzhao
16  * Create: 2022-01-19
17  */
18 
19 #include "encrypt_decrypt.h"
20 
21 #include <cstdint>
22 #include "securec.h"
23 #include "cast_engine_log.h"
24 
25 namespace OHOS {
26 namespace CastEngine {
27 namespace CastEngineService {
28 DEFINE_CAST_ENGINE_LABEL("Cast-EncryptDecrypt");
29 
30 const std::string EncryptDecrypt::PC_ENCRYPT_ALG = "aes128ctr";
31 
EncryptDecrypt()32 EncryptDecrypt::EncryptDecrypt() {}
33 
~EncryptDecrypt()34 EncryptDecrypt::~EncryptDecrypt() {}
35 
GetInstance()36 EncryptDecrypt &EncryptDecrypt::GetInstance()
37 {
38     return Singleton<EncryptDecrypt>::GetInstance();
39 }
40 
GetAESIv(uint8_t iv[],int ivLen)41 void EncryptDecrypt::GetAESIv(uint8_t iv[], int ivLen)
42 {
43     uint8_t buffer[PC_ENCRYPT_LEN] = {0};
44     if (iv == nullptr || ivLen < AES_KEY_SIZE) {
45         CLOGE("iv is null or ivLen error");
46         return;
47     }
48     errno_t ret = memset_s(iv, ivLen, 0, ivLen);
49     if (ret != 0) {
50         CLOGE("memset_s failed");
51         return;
52     }
53     if (ivLen > PC_ENCRYPT_LEN) {
54         CLOGE("invalid ivLen: %d", ivLen);
55         return;
56     }
57     RAND_bytes(buffer, ivLen);
58     ret = memcpy_s(iv, ivLen, buffer, ivLen);
59     if (ret != 0) {
60         CLOGE("memcpy_s failed");
61         return;
62     }
63     return;
64 }
65 
AES128Encry(ConstPacketData inputData,PacketData & outputData,ConstPacketData sessionKey,ConstPacketData sessionIV)66 int EncryptDecrypt::AES128Encry(ConstPacketData inputData, PacketData &outputData, ConstPacketData sessionKey,
67     ConstPacketData sessionIV)
68 {
69     const uint8_t *key = sessionKey.data;
70     const uint8_t *iv = sessionIV.data;
71     if ((inputData.data == nullptr) || (outputData.data == nullptr) || (key == nullptr) || (iv == nullptr)
72         || (sessionKey.length != AES_KEY_LEN) || (sessionIV.length != AES_IV_LEN)) {
73         return ERR_R_PASSED_NULL_PARAMETER;
74     }
75 
76     EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
77     if (ctx == nullptr) {
78         return ERR_R_MALLOC_FAILURE;
79     }
80 
81     int ret = EVP_EncryptInit_ex(ctx, EVP_aes_128_ctr(), nullptr, key, iv);
82     if (ret != 1) {
83         EVP_CIPHER_CTX_free(ctx);
84         ctx = nullptr;
85         return ERR_R_INTERNAL_ERROR;
86     }
87 
88     do {
89         int resultLen1 = 0;
90         int resultLen2 = 0;
91         EVP_CIPHER_CTX_set_key_length(ctx, AES_KEY_LEN_128);
92 
93         ret = EVP_EncryptUpdate(ctx, outputData.data, &resultLen1, inputData.data, inputData.length);
94         if (ret != 1) {
95             ret = SEC_ERR_ENCRYPTUPDATE_FAIL;
96             break;
97         }
98 
99         ret = EVP_EncryptFinal_ex(ctx, outputData.data + resultLen1, &resultLen2);
100         if (ret != 1) {
101             ret = SEC_ERR_ENCRYPTFINAL_FAIL;
102             break;
103         }
104         outputData.length = resultLen1 + resultLen2;
105         ret = 0;
106     } while (0);
107 
108     EVP_CIPHER_CTX_free(ctx);
109     ctx = nullptr;
110     return ret;
111 }
112 
AES128Decrypt(ConstPacketData inputData,PacketData & outputData,ConstPacketData sessionKey,ConstPacketData sessionIV)113 int EncryptDecrypt::AES128Decrypt(ConstPacketData inputData, PacketData &outputData, ConstPacketData sessionKey,
114     ConstPacketData sessionIV)
115 {
116     const uint8_t *key = sessionKey.data;
117     const uint8_t *iv = sessionIV.data;
118     if ((outputData.data == nullptr) || (inputData.data == nullptr) || (key == nullptr) || (iv == nullptr)
119         || (sessionKey.length != AES_KEY_LEN) || (sessionIV.length != AES_IV_LEN)) {
120         return ERR_R_PASSED_NULL_PARAMETER;
121     }
122 
123     EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
124     if (ctx == nullptr) {
125         return ERR_R_MALLOC_FAILURE;
126     }
127 
128     int ret = EVP_DecryptInit_ex(ctx, EVP_aes_128_ctr(), nullptr, key, iv);
129     if (ret != 1) {
130         EVP_CIPHER_CTX_free(ctx);
131         ctx = nullptr;
132         return ERR_R_INTERNAL_ERROR;
133     }
134 
135     do {
136         int resultLen1 = 0;
137         int resultLen2 = 0;
138         EVP_CIPHER_CTX_set_key_length(ctx, AES_KEY_LEN_128);
139 
140         ret = EVP_DecryptUpdate(ctx, outputData.data, &resultLen1, inputData.data, inputData.length);
141         if (ret != 1) {
142             ret = SEC_ERR_ENCRYPTUPDATE_FAIL;
143             break;
144         }
145 
146         ret = EVP_DecryptFinal_ex(ctx, outputData.data + resultLen1, &resultLen2);
147         if (ret != 1) {
148             ret = SEC_ERR_ENCRYPTFINAL_FAIL;
149             break;
150         }
151         outputData.length = resultLen1 + resultLen2;
152         ret = 0;
153     } while (0);
154 
155     EVP_CIPHER_CTX_free(ctx);
156     ctx = nullptr;
157     return ret;
158 }
159 
AES128GCMCheckEncryPara(ConstPacketData inputData,PacketData & outputData,EncryptInfo & encryInfo)160 int EncryptDecrypt::AES128GCMCheckEncryPara(ConstPacketData inputData, PacketData &outputData, EncryptInfo &encryInfo)
161 {
162     if ((inputData.length < 0) || (encryInfo.aad.length < 0) || (encryInfo.key.length != AES_KEY_LEN_128) ||
163         (encryInfo.iv.length < AES_GCM_MAX_IVLEN) || (encryInfo.tag.length < AES_GCM_SIV_TAG_LEN)) {
164         return SEC_ERR_INVALID_KEY_LEN;
165     }
166     if ((inputData.data == nullptr) && (inputData.length > 0)) {
167         return SEC_ERR_INVALID_PLAIN;
168     }
169     if ((encryInfo.aad.data == nullptr) && (encryInfo.aad.length > 0)) {
170         return SEC_ERR_INVALID_AAD;
171     }
172     if ((encryInfo.key.data == nullptr) || (encryInfo.iv.data == nullptr) || (encryInfo.tag.data == nullptr)) {
173         return SEC_ERR_INVALID_IV;
174     }
175     if (outputData.length < inputData.length) {
176         return SEC_ERR_INVALID_DATA_LEN;
177     }
178     if ((outputData.data == nullptr) && (outputData.length > 0)) {
179         return SEC_ERR_INVALID_CIPHERTEXT;
180     }
181     return 0;
182 }
183 
EnctyptProcess(ConstPacketData inputData,PacketData & outputData,EncryptInfo & encryInfo,EVP_CIPHER_CTX * ctx)184 int EncryptDecrypt::EnctyptProcess(ConstPacketData inputData, PacketData &outputData, EncryptInfo &encryInfo,
185     EVP_CIPHER_CTX *ctx)
186 {
187     int ret = 0;
188     int len = 0;
189     int cipherTextLen = 0;
190 
191     // Enctypt
192     do {
193         /* Create and initialise the context */
194         ctx = EVP_CIPHER_CTX_new();
195         if (ctx == nullptr) {
196             ret = SEC_ERR_CREATECIPHER_FAIL;
197             break;
198         }
199 
200         /* Initialise the encryption operation. */
201         if (EVP_EncryptInit_ex(ctx, EVP_aes_128_gcm(), nullptr, nullptr, nullptr) != 1) {
202             ret = SEC_ERR_INVALID_CID;
203             break;
204         }
205 
206         /* Set IV length if default 12 bytes (96 bits) is not appropriate */
207         if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, encryInfo.iv.length, nullptr) != 1) {
208             ret = SEC_ERR_INVALID_IV_LEN;
209             break;
210         }
211 
212         /* Initialise key and IV */
213         if (EVP_EncryptInit_ex(ctx, nullptr, nullptr, encryInfo.key.data, encryInfo.iv.data) != 1) {
214             ret = SEC_ERR_INVALID_KEY;
215             break;
216         }
217 
218         /*
219          * Provide any AAD data. This can be called zero or more times as required
220          */
221         if (EVP_EncryptUpdate(ctx, nullptr, &len, encryInfo.aad.data, encryInfo.aad.length) != 1) {
222             ret = SEC_ERR_SETAAD_FAIL;
223             break;
224         }
225 
226         /*
227          * Provide the message to be encrypted, and obtain the encrypted output.
228          * EVP_EncryptUpdate can be called multiple times if necessary, like in file encryption,
229          * you may read multiple times from a file , each time you read part of the file and call EVP_EncryptUpdate
230          * on them one by one to get the whole cipherText of the file at last.
231          */
232         if (EVP_EncryptUpdate(ctx, outputData.data, &len, inputData.data, inputData.length) != 1) {
233             ret = SEC_ERR_ENCRYPTUPDATE_FAIL;
234             break;
235         }
236 
237         cipherTextLen = len;
238 
239         /*
240          * Finalise the encryption. Normally cipherText bytes may be written at
241          * this stage, but this does not occur in GCM mode
242          */
243         if (EVP_EncryptFinal_ex(ctx, outputData.data + len, &len) != 1) {
244             ret = SEC_ERR_ENCRYPTFINAL_FAIL;
245             break;
246         }
247         cipherTextLen += len;
248 
249         /* Get the tag */
250         if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, encryInfo.tag.length, encryInfo.tag.data) != 1) {
251             ret = SEC_ERR_GCMGETTAG_FAIL;
252             break;
253         }
254         outputData.length = cipherTextLen;
255         ret = 0;
256     } while (0);
257 
258     return ret;
259 }
260 
AES128GCMEncry(ConstPacketData inputData,PacketData & outputData,EncryptInfo & encryInfo)261 int EncryptDecrypt::AES128GCMEncry(ConstPacketData inputData, PacketData &outputData, EncryptInfo &encryInfo)
262 {
263     EVP_CIPHER_CTX *ctx = nullptr;
264 
265     int ret = AES128GCMCheckEncryPara(inputData, outputData, encryInfo);
266     if (ret != 0) {
267         return ret;
268     }
269 
270     ret = EnctyptProcess(inputData, outputData, encryInfo, ctx);
271 
272     if (ctx != nullptr) {
273         EVP_CIPHER_CTX_free(ctx);
274         ctx = nullptr;
275     }
276     return ret;
277 }
278 
AES128GCMCheckDecryptPara(ConstPacketData inputData,PacketData & outputData,EncryptInfo & encryInfo)279 int EncryptDecrypt::AES128GCMCheckDecryptPara(ConstPacketData inputData, PacketData &outputData, EncryptInfo &encryInfo)
280 {
281     if ((inputData.length < 0) || (encryInfo.aad.length < 0) || (encryInfo.key.length != AES_KEY_LEN_128) ||
282         (encryInfo.iv.length < AES_GCM_MAX_IVLEN) || (encryInfo.tag.length < AES_GCM_SIV_TAG_LEN)) {
283         return SEC_ERR_INVALID_KEY_LEN;
284     }
285     if ((inputData.data == nullptr) && (inputData.length > 0)) {
286         return SEC_ERR_INVALID_CIPHERTEXT;
287     }
288     if ((encryInfo.aad.data == nullptr) && (encryInfo.aad.length > 0)) {
289         return SEC_ERR_INVALID_AAD;
290     }
291     if ((encryInfo.key.data == nullptr) || (encryInfo.iv.data == nullptr) || (encryInfo.tag.data == nullptr)) {
292         return SEC_ERR_INVALID_IV;
293     }
294     if (outputData.length < inputData.length) {
295         return SEC_ERR_INVALID_DATA_LEN;
296     }
297     if ((outputData.data == nullptr) && (outputData.length > 0)) {
298         return SEC_ERR_INVALID_PLAIN;
299     }
300     return 0;
301 }
302 
DecryptProcess(ConstPacketData inputData,PacketData & outputData,EncryptInfo & encryInfo,EVP_CIPHER_CTX * ctx)303 int EncryptDecrypt::DecryptProcess(ConstPacketData inputData, PacketData &outputData, EncryptInfo &encryInfo,
304     EVP_CIPHER_CTX *ctx)
305 {
306     int ret = 0;
307     int len = 0;
308     int plainTextLen = 0;
309 
310     do {
311         /* Create and initialise the context */
312         ctx = EVP_CIPHER_CTX_new();
313         if (ctx == nullptr) {
314             ret = SEC_ERR_CREATECIPHER_FAIL;
315             break;
316         }
317 
318         /* Initialise the decryption operation. */
319         if (!EVP_DecryptInit_ex(ctx, EVP_aes_128_gcm(), nullptr, nullptr, nullptr)) {
320             ret = SEC_ERR_INVALID_CID;
321             break;
322         }
323 
324         /* Set IV length. Not necessary if this is 12 bytes (96 bits) */
325         if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, encryInfo.iv.length, nullptr)) {
326             ret = SEC_ERR_INVALID_IV_LEN;
327             break;
328         }
329 
330         /* Initialise key and IV */
331         if (!EVP_DecryptInit_ex(ctx, nullptr, nullptr, encryInfo.key.data, encryInfo.iv.data)) {
332             ret = SEC_ERR_INVALID_KEY;
333             break;
334         }
335 
336         /*
337          * Provide any AAD data. This can be called zero or more times as
338          * required
339          */
340         if (!EVP_DecryptUpdate(ctx, nullptr, &len, encryInfo.aad.data, encryInfo.aad.length)) {
341             ret = SEC_ERR_SETAAD_FAIL;
342             break;
343         }
344 
345         /*
346          * Provide the message to be decrypted, and obtain the plainText output.
347          * EVP_DecryptUpdate can be called multiple times if necessary
348          */
349         if (!EVP_DecryptUpdate(ctx, outputData.data, &len, inputData.data, inputData.length)) {
350             ret = SEC_ERR_ENCRYPTUPDATE_FAIL;
351             break;
352         }
353         plainTextLen = len;
354 
355         /* Set expected tag value. Works in OpenSSL 1.0.1d and later */
356         if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, encryInfo.tag.length, encryInfo.tag.data)) {
357             ret = SEC_ERR_GCMGETTAG_FAIL;
358             break;
359         }
360 
361         /*
362          * Finalise the decryption. A positive return value indicates success,
363          * anything else is a failure - the plainText is not trustworthy.
364          */
365         if (EVP_DecryptFinal_ex(ctx, outputData.data + len, &len) != 1) {
366             ret = SEC_ERR_ENCRYPTFINAL_FAIL;
367             break;
368         }
369         plainTextLen += len;
370         outputData.length = plainTextLen;
371         ret = 0;
372     } while (0);
373 
374     return ret;
375 }
376 
AES128GCMDecrypt(ConstPacketData inputData,PacketData & outputData,EncryptInfo & encryInfo)377 int EncryptDecrypt::AES128GCMDecrypt(ConstPacketData inputData, PacketData &outputData, EncryptInfo &encryInfo)
378 {
379     EVP_CIPHER_CTX *ctx = nullptr;
380 
381     int ret = AES128GCMCheckDecryptPara(inputData, outputData, encryInfo);
382     if (ret != 0) {
383         return ret;
384     }
385 
386     ret = DecryptProcess(inputData, outputData, encryInfo, ctx);
387 
388     if (ctx != nullptr) {
389         EVP_CIPHER_CTX_free(ctx);
390         ctx = nullptr;
391     }
392 
393     return ret;
394 }
395 
EncryptData(int algCode,const uint8_t * key,int keyLen,ConstPacketData inputData,PacketData & outputData)396 bool EncryptDecrypt::EncryptData(int algCode, const uint8_t *key, int keyLen, ConstPacketData inputData,
397     PacketData &outputData)
398 {
399     uint8_t sessionIV[AES_KEY_SIZE] = {0};
400 
401     if (outputData.data == nullptr) {
402         CLOGE("outputData is null");
403         return false;
404     }
405     if (algCode != CTR_CODE) {
406         CLOGE("encrypt not CTR for extension");
407         return false;
408     }
409     GetAESIv(sessionIV, AES_KEY_SIZE);
410 
411     int encryptDataLen = inputData.length + AES_KEY_SIZE;
412     std::unique_ptr<uint8_t[]> encryptData = std::make_unique<uint8_t[]>(encryptDataLen);
413     if (encryptData == nullptr) {
414         return false;
415     }
416     errno_t ret = memset_s(encryptData.get(), encryptDataLen, 0, encryptDataLen);
417     if (ret != 0) {
418         return false;
419     }
420     PacketData output = { encryptData.get(), encryptDataLen };
421     ConstPacketData sessionKey = { key, keyLen };
422     ConstPacketData iv = { sessionIV, AES_IV_LEN };
423     ret = AES128Encry(inputData, output, sessionKey, iv);
424     if (ret != 0 || output.length > inputData.length) {
425         CLOGE("encrypt error enLen [%u][%u]", ret, output.length);
426         return false;
427     }
428     ret = memcpy_s(outputData.data, AES_KEY_SIZE, sessionIV, AES_KEY_SIZE);
429     if (ret != 0) {
430         return false;
431     }
432     ret = memcpy_s(outputData.data + AES_KEY_SIZE, output.length, output.data, output.length);
433     if (ret != 0) {
434         return false;
435     }
436 
437     outputData.length = output.length + AES_KEY_SIZE;
438     return true;
439 }
440 
DecryptData(int algCode,const uint8_t * key,int keyLen,ConstPacketData inputData,PacketData & outputData)441 bool EncryptDecrypt::DecryptData(int algCode, const uint8_t *key, int keyLen, ConstPacketData inputData,
442     PacketData &outputData)
443 {
444     uint8_t sessionIV[AES_KEY_SIZE] = {0};
445 
446     if (algCode != CTR_CODE) {
447         CLOGE("decrypt not CTR for extension");
448         return false;
449     }
450 
451     if (inputData.length <= AES_KEY_SIZE || inputData.data == nullptr || outputData.data == nullptr) {
452         CLOGE("decrypt para error");
453         return false;
454     }
455     int32_t ret = memcpy_s(sessionIV, AES_KEY_SIZE, inputData.data, AES_KEY_SIZE);
456     if (ret != 0) {
457         CLOGE("memcpy_s failed");
458         delete[] inputData.data;
459         return false;
460     }
461     int deLen = inputData.length - AES_KEY_SIZE;
462     std::unique_ptr<uint8_t[]> decryptData = std::make_unique<uint8_t[]>(deLen);
463     if (decryptData == nullptr) {
464         CLOGE("create decrypt data memory failed");
465         return false;
466     }
467     ret = memset_s(decryptData.get(), deLen, 0, deLen);
468     if (ret != 0) {
469         CLOGE("memset_s failed");
470         return false;
471     }
472     PacketData output = { decryptData.get(), deLen };
473     ConstPacketData sessionKey = { key, keyLen };
474     ConstPacketData iv = { sessionIV, AES_IV_LEN };
475     ConstPacketData input = { inputData.data + AES_KEY_SIZE, deLen };
476     ret = AES128Decrypt(input, output, sessionKey, iv);
477     if (ret != 0 || output.length != deLen) {
478         CLOGE("decrypt error and ret[%{public}d] Len[%u] delen[%{public}d]", ret, output.length, deLen);
479         return false;
480     }
481     ret = memcpy_s(outputData.data, output.length, output.data, output.length);
482     if (ret != 0) {
483         return false;
484     }
485     outputData.length = output.length;
486 
487     return true;
488 }
489 
GetEncryptInfo()490 std::string EncryptDecrypt::GetEncryptInfo()
491 {
492     return PC_ENCRYPT_ALG;
493 }
494 
GetEncryptMatch(const std::string & encyptInfo)495 int EncryptDecrypt::GetEncryptMatch(const std::string &encyptInfo)
496 {
497     if (encyptInfo.size() >= PC_ENCRYPT_LEN) {
498         return INVALID_CODE;
499     }
500 
501     if (encyptInfo == PC_ENCRYPT_ALG) {
502         return CTR_CODE;
503     }
504 
505     return INVALID_CODE;
506 }
507 
GetVersion()508 int EncryptDecrypt::GetVersion()
509 {
510     return VERSION;
511 }
512 } // namespace CastEngineService
513 } // namespace CastEngine
514 } // namespace OHOS
515