• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2024 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "crypto/aes_cbc.h"
6 
7 #include "crypto/openssl_util.h"
8 #include "third_party/boringssl/src/include/openssl/aes.h"
9 #include "third_party/boringssl/src/include/openssl/evp.h"
10 
11 namespace crypto::aes_cbc {
12 
Encrypt(base::span<const uint8_t> key,base::span<const uint8_t,kBlockSize> iv,base::span<const uint8_t> plaintext)13 std::vector<uint8_t> Encrypt(base::span<const uint8_t> key,
14                              base::span<const uint8_t, kBlockSize> iv,
15                              base::span<const uint8_t> plaintext) {
16   const EVP_CIPHER* cipher =
17       key.size() == 32 ? EVP_aes_256_cbc() : EVP_aes_128_cbc();
18 
19   CHECK_EQ(EVP_CIPHER_key_length(cipher), key.size());
20 
21   OpenSSLErrStackTracer err_tracer(FROM_HERE);
22   bssl::ScopedEVP_CIPHER_CTX ctx;
23   CHECK(EVP_EncryptInit_ex(ctx.get(), cipher, nullptr, key.data(), iv.data()));
24 
25   std::vector<uint8_t> ciphertext(plaintext.size() + kBlockSize);
26 
27   int out_len;
28   CHECK(EVP_EncryptUpdate(ctx.get(), ciphertext.data(), &out_len,
29                           plaintext.data(), plaintext.size()));
30 
31   int tail_len;
32   CHECK(EVP_EncryptFinal_ex(ctx.get(),
33                             // SAFETY: boringssl guarantees out_len is still
34                             // inside ciphertext.
35                             UNSAFE_BUFFERS(ciphertext.data() + out_len),
36                             &tail_len));
37   ciphertext.resize(out_len + tail_len);
38   return ciphertext;
39 }
40 
Decrypt(base::span<const uint8_t> key,base::span<const uint8_t,kBlockSize> iv,base::span<const uint8_t> ciphertext)41 std::optional<std::vector<uint8_t>> Decrypt(
42     base::span<const uint8_t> key,
43     base::span<const uint8_t, kBlockSize> iv,
44     base::span<const uint8_t> ciphertext) {
45   const EVP_CIPHER* cipher =
46       key.size() == 32 ? EVP_aes_256_cbc() : EVP_aes_128_cbc();
47   OpenSSLErrStackTracer err_tracer(FROM_HERE);
48   bssl::ScopedEVP_CIPHER_CTX ctx;
49   CHECK(EVP_DecryptInit_ex(ctx.get(), cipher, nullptr, key.data(), iv.data()));
50 
51   std::vector<uint8_t> plaintext(ciphertext.size());
52 
53   int out_len;
54   CHECK(EVP_DecryptUpdate(ctx.get(), plaintext.data(), &out_len,
55                           ciphertext.data(), ciphertext.size()));
56 
57   int tail_len;
58   if (!EVP_DecryptFinal_ex(ctx.get(),
59                            // SAFETY: boringssl guarantees out_len is still
60                            // inside ciphertext.
61                            UNSAFE_BUFFERS(plaintext.data() + out_len),
62                            &tail_len)) {
63     return std::nullopt;
64   }
65 
66   plaintext.resize(out_len + tail_len);
67   return plaintext;
68 }
69 
70 }  // namespace crypto::aes_cbc
71