xref: /aosp_15_r20/external/federated-compute/fcp/secagg/shared/aes_gcm_encryption.cc (revision 14675a029014e728ec732f129a32e299b2da0601)
1 /*
2  * Copyright 2018 Google LLC
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     https://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "fcp/secagg/shared/aes_gcm_encryption.h"
18 
19 #include <cstdint>
20 #include <string>
21 
22 #include "fcp/base/monitoring.h"
23 #include "fcp/secagg/shared/aes_key.h"
24 #include "fcp/secagg/shared/prng.h"
25 #include "openssl/cipher.h"
26 #include "openssl/evp.h"
27 #include "openssl/rand.h"
28 
29 namespace fcp {
30 namespace secagg {
31 
32 constexpr int kIvSize = 12;
33 constexpr int kTagSize = 16;
34 
AesGcmEncryption()35 AesGcmEncryption::AesGcmEncryption() {}
36 
Encrypt(const AesKey & key,const std::string & plaintext)37 std::string AesGcmEncryption::Encrypt(const AesKey& key,
38                                       const std::string& plaintext) {
39   FCP_CHECK(key.size() != 0) << "Encrypt called with blank key.";
40   FCP_CHECK(key.size() == AesKey::kSize)
41       << "Encrypt called with key of " << key.size()
42       << " bytes, but 32 bytes are required.";
43   std::vector<uint8_t> ciphertext_buffer;
44   ciphertext_buffer.resize(kIvSize + plaintext.length() + kTagSize);
45   FCP_CHECK(RAND_bytes(ciphertext_buffer.data(), kIvSize));
46 
47   // ScopedEVP_AEAD_CTX will automatically call EVP_AEAD_CTX_cleanup when going
48   // out of scope.
49   bssl::ScopedEVP_AEAD_CTX ctx;
50   FCP_CHECK(EVP_AEAD_CTX_init(ctx.get(), EVP_aead_aes_256_gcm(),
51                               const_cast<uint8_t*>(key.data()), key.size(),
52                               EVP_AEAD_DEFAULT_TAG_LENGTH, nullptr) == 1);
53   size_t len;
54   FCP_CHECK(EVP_AEAD_CTX_seal(
55                 ctx.get(), ciphertext_buffer.data() + kIvSize, &len,
56                 plaintext.size() + kTagSize, ciphertext_buffer.data(), kIvSize,
57                 reinterpret_cast<const uint8_t*>(plaintext.c_str()),
58                 plaintext.size(), nullptr, 0) == 1);
59   return std::string(ciphertext_buffer.begin(), ciphertext_buffer.end());
60 }
61 
Decrypt(const AesKey & key,const std::string & ciphertext)62 StatusOr<std::string> AesGcmEncryption::Decrypt(const AesKey& key,
63                                                 const std::string& ciphertext) {
64   FCP_CHECK(key.size() != 0) << "Decrypt called with blank key.";
65   FCP_CHECK(key.size() == AesKey::kSize)
66       << "Decrypt called with key of " << key.size()
67       << " bytes, but 32 bytes are required.";
68   if (ciphertext.size() < kIvSize + kTagSize) {
69     return FCP_STATUS(DATA_LOSS) << "Ciphertext is too short.";
70   }
71   size_t len;
72   std::vector<uint8_t> plaintext_buffer;
73   plaintext_buffer.resize(ciphertext.size() - kIvSize - kTagSize);
74 
75   // ScopedEVP_AEAD_CTX will automatically call EVP_AEAD_CTX_cleanup when going
76   // out of scope.
77   bssl::ScopedEVP_AEAD_CTX ctx;
78   FCP_CHECK(EVP_AEAD_CTX_init(ctx.get(), EVP_aead_aes_256_gcm(),
79                               const_cast<uint8_t*>(key.data()), key.size(),
80                               EVP_AEAD_DEFAULT_TAG_LENGTH, nullptr) == 1);
81   if (EVP_AEAD_CTX_open(
82           ctx.get(), plaintext_buffer.data(), &len, plaintext_buffer.size(),
83           reinterpret_cast<const uint8_t*>(ciphertext.data()), kIvSize,
84           reinterpret_cast<const uint8_t*>(ciphertext.data() + kIvSize),
85           ciphertext.size() - kIvSize, nullptr, 0) != 1) {
86     return FCP_STATUS(DATA_LOSS) << "Verification of ciphertext failed.";
87   }
88   return std::string(plaintext_buffer.begin(), plaintext_buffer.end());
89 }
90 
91 }  // namespace secagg
92 }  // namespace fcp
93