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