| 460 | } |
| 461 | |
| 462 | Status EncryptionKey::EncryptInternal( |
| 463 | bool encrypt, const uint8_t* data, int64_t len, uint8_t* out, int64_t* out_len) { |
| 464 | DCHECK(initialized_); |
| 465 | DCHECK_GE(len, 0); |
| 466 | if (IsEcbMode()) { |
| 467 | if ((encrypt && len > numeric_limits<int>::max() - AES_BLOCK_SIZE) |
| 468 | || (!encrypt && len > numeric_limits<int>::max())) { |
| 469 | return Status("Input buffer length exceeds the supported length for ECB mode."); |
| 470 | } |
| 471 | } |
| 472 | |
| 473 | const char* err_context = encrypt ? "encrypting" : "decrypting"; |
| 474 | // Create and initialize the context for encryption. |
| 475 | // If it is ECB mode then padding will be enabled |
| 476 | // for this ctx, otherwise it will be disabled. |
| 477 | bool padding_enabled = IsEcbMode(); |
| 478 | int padding_flag = padding_enabled ? 1 : 0; |
| 479 | ScopedEVPCipherCtx ctx(padding_flag); |
| 480 | |
| 481 | // Start encryption/decryption. We use a 128/256-bit AES key and support GCM, CTR |
| 482 | // CFB and ECB for encryption and decryption. When the cipher block mode is either |
| 483 | // GCM, CTR or CFB(stream cipher), it supports arbitrary length ciphertexts - it |
| 484 | // doesn't have to be a multiple of 16 bytes. While for ECB decryption, |
| 485 | // the length has to be multiples of 16. Additionally, CTR mode is |
| 486 | // well-optimized (instruction level parallelism) with hardware acceleration |
| 487 | // on x86 and PowerPC. |
| 488 | |
| 489 | // In the first initialization, only evpCipher is initialized, and in the second |
| 490 | // initialization, the key and IV vector are set. This approach is necessary because a |
| 491 | // variable-length IV vector is used. Therefore, in GCM mode, the IV length must be |
| 492 | // initialized before setting the IV vector. |
| 493 | const EVP_CIPHER* evpCipher = GetCipher(); |
| 494 | DCHECK(evpCipher != nullptr); |
| 495 | int success = encrypt ? |
| 496 | EVP_EncryptInit_ex(ctx.ctx, evpCipher, nullptr, nullptr, nullptr): |
| 497 | EVP_DecryptInit_ex(ctx.ctx, evpCipher, nullptr, nullptr, nullptr); |
| 498 | if (success != 1) { |
| 499 | return OpenSSLErr(encrypt ? "EVP_EncryptInit_ex" : "EVP_DecryptInit_ex", err_context); |
| 500 | } |
| 501 | |
| 502 | if (IsGcmMode()) { |
| 503 | // Set iv_vector for GCM mode. |
| 504 | if (EVP_CIPHER_CTX_ctrl(ctx.ctx, EVP_CTRL_GCM_SET_IVLEN, iv_length_, nullptr)!= 1) { |
| 505 | return OpenSSLErr("EVP_CIPHER_CTX_ctrl", err_context); |
| 506 | } |
| 507 | } |
| 508 | // setting iv after changing iv len, see https://github.com/openssl/openssl/pull/22590 |
| 509 | success = encrypt ? EVP_EncryptInit_ex(ctx.ctx, nullptr, nullptr, key_, iv_): |
| 510 | EVP_DecryptInit_ex(ctx.ctx, nullptr, nullptr, key_, iv_); |
| 511 | if (success != 1) { |
| 512 | return OpenSSLErr(encrypt ? "EVP_EncryptInit_ex" : "EVP_DecryptInit_ex", err_context); |
| 513 | } |
| 514 | |
| 515 | // The OpenSSL encryption APIs use INT for buffer lengths. To support larger buffers, |
| 516 | // larger buffers need to be chunked into smaller parts. |
| 517 | int64_t output_offset = 0; |
| 518 | int64_t input_offset = 0; |
| 519 | while (input_offset < len) { |
nothing calls this directly
no test coverage detected