xref: /aosp_15_r20/external/federated-compute/fcp/secagg/shared/aes_gcm_encryption_test.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 <string>
20 
21 #include "gmock/gmock.h"
22 #include "gtest/gtest.h"
23 #include "fcp/secagg/shared/aes_key.h"
24 
25 namespace fcp {
26 namespace secagg {
27 namespace {
28 
29 using ::testing::Eq;
30 using ::testing::Ne;
31 
32 // For testing purposes, make an AesKey out of a string.
MakeAesKey(const std::string & key)33 AesKey MakeAesKey(const std::string& key) {
34   EXPECT_THAT(key.size(), Eq(AesKey::kSize));
35   return AesKey(reinterpret_cast<const uint8_t*>(key.c_str()));
36 }
37 
TEST(AesGcmEncryptionTest,EncryptionThenDecryptionWorks)38 TEST(AesGcmEncryptionTest, EncryptionThenDecryptionWorks) {
39   AesGcmEncryption aes;
40   AesKey key = MakeAesKey("Just some random 32 byte AES key");
41   std::string test_str = "This is a test. Should work on arbitrary strings.";
42 
43   std::string ciphertext = aes.Encrypt(key, test_str);
44   StatusOr<std::string> plaintext = aes.Decrypt(key, ciphertext);
45   ASSERT_TRUE(plaintext.ok());
46   EXPECT_THAT(plaintext.value(), Eq(test_str));
47 }
48 
TEST(AesGcmEncryptionTest,MultipleOperationsWithSameObjectWork)49 TEST(AesGcmEncryptionTest, MultipleOperationsWithSameObjectWork) {
50   AesGcmEncryption aes;
51   AesKey key1 = MakeAesKey("Just some random 32 byte AES key");
52   AesKey key2 = MakeAesKey("A different 32-byte-long AES key");
53   std::string test_str1 = "This is a test. Should work on arbitrary strings.";
54   std::string test_str2 = "Another test string.";
55 
56   std::string ciphertext1 = aes.Encrypt(key1, test_str1);
57   std::string ciphertext2 = aes.Encrypt(key2, test_str2);
58   StatusOr<std::string> plaintext1 = aes.Decrypt(key1, ciphertext1);
59   StatusOr<std::string> plaintext2 = aes.Decrypt(key2, ciphertext2);
60   ASSERT_TRUE(plaintext1.ok());
61   EXPECT_THAT(plaintext1.value(), Eq(test_str1));
62   ASSERT_TRUE(plaintext2.ok());
63   EXPECT_THAT(plaintext2.value(), Eq(test_str2));
64 }
65 
TEST(AesGcmEncryptionTest,EncryptionsWithDifferentKeysAreDifferent)66 TEST(AesGcmEncryptionTest, EncryptionsWithDifferentKeysAreDifferent) {
67   AesGcmEncryption aes;
68   AesKey key1 = MakeAesKey("Just some random 32 byte AES key");
69   AesKey key2 = MakeAesKey("A different 32-byte-long AES key");
70   std::string test_str = "This is a test. Should work on arbitrary strings.";
71 
72   std::string ciphertext1 = aes.Encrypt(key1, test_str);
73   std::string ciphertext2 = aes.Encrypt(key2, test_str);
74   EXPECT_THAT(ciphertext1, Ne(ciphertext2));
75   StatusOr<std::string> plaintext1 = aes.Decrypt(key1, ciphertext1);
76   StatusOr<std::string> plaintext2 = aes.Decrypt(key2, ciphertext2);
77   ASSERT_TRUE(plaintext1.ok());
78   EXPECT_THAT(plaintext1.value(), Eq(test_str));
79   ASSERT_TRUE(plaintext2.ok());
80   EXPECT_THAT(plaintext2.value(), Eq(test_str));
81 }
82 
TEST(AesGcmEncryptionTest,VerificationFailsOnBadTag)83 TEST(AesGcmEncryptionTest, VerificationFailsOnBadTag) {
84   AesGcmEncryption aes;
85   AesKey key = MakeAesKey("Just some random 32 byte AES key");
86   std::string test_str = "This is a test. Should work on arbitrary strings.";
87 
88   std::string ciphertext = aes.Encrypt(key, test_str);
89   ciphertext[ciphertext.size() - 1] = 'X';
90   StatusOr<std::string> plaintext = aes.Decrypt(key, ciphertext);
91   EXPECT_THAT(plaintext.ok(), Eq(false));
92 }
93 
TEST(AesGcmEncryptionTest,VerificationFailsOnBadCiphertext)94 TEST(AesGcmEncryptionTest, VerificationFailsOnBadCiphertext) {
95   AesGcmEncryption aes;
96   AesKey key = MakeAesKey("Just some random 32 byte AES key");
97   std::string test_str = "This is a test. Should work on arbitrary strings.";
98 
99   std::string ciphertext = aes.Encrypt(key, test_str);
100   for (int i = 0; i < ciphertext.size(); i++) {
101     // modify every bit of the ciphertext
102     for (int j = 0; j < 8; j++) {
103       ciphertext[i] ^= (1 << j);
104 
105       StatusOr<std::string> plaintext = aes.Decrypt(key, ciphertext);
106       EXPECT_THAT(plaintext.ok(), Eq(false));
107 
108       // reset the ciphertext
109       ciphertext[i] ^= (1 << j);
110     }
111   }
112 }
113 
TEST(AesGcmEncryptionTest,VerificationFailsOnWrongKey)114 TEST(AesGcmEncryptionTest, VerificationFailsOnWrongKey) {
115   AesGcmEncryption aes;
116   AesKey key = MakeAesKey("Just some random 32 byte AES key");
117   AesKey key2 = MakeAesKey("A different 32-byte-long AES key");
118   std::string test_str = "This is a test. Should work on arbitrary strings.";
119 
120   std::string ciphertext = aes.Encrypt(key, test_str);
121   StatusOr<std::string> plaintext = aes.Decrypt(key2, ciphertext);
122   EXPECT_THAT(plaintext.ok(), Eq(false));
123 }
124 
TEST(AesGcmEncryptionTest,EncryptionDiesOnEmptyKey)125 TEST(AesGcmEncryptionTest, EncryptionDiesOnEmptyKey) {
126   AesGcmEncryption aes;
127   std::string test_str = "This is a test. Should work on arbitrary strings.";
128 
129   EXPECT_DEATH(aes.Encrypt(AesKey(), test_str),
130                "Encrypt called with blank key.");
131 }
132 
TEST(AesGcmEncryptionTest,DecryptionDiesOnEmptyKey)133 TEST(AesGcmEncryptionTest, DecryptionDiesOnEmptyKey) {
134   AesGcmEncryption aes;
135   AesKey key = MakeAesKey("Just some random 32 byte AES key");
136   std::string test_str = "This is a test. Should work on arbitrary strings.";
137 
138   std::string ciphertext = aes.Encrypt(key, test_str);
139   EXPECT_DEATH(aes.Decrypt(AesKey(), ciphertext).IgnoreError(),
140                "Decrypt called with blank key.");
141 }
TEST(AesGcmEncryptionTest,EncryptionDiesOnShortKey)142 TEST(AesGcmEncryptionTest, EncryptionDiesOnShortKey) {
143   AesGcmEncryption aes;
144   std::string test_str = "This is a test. Should work on arbitrary strings.";
145 
146   std::string bad_key_input = "only 16 byte key";
147   EXPECT_DEATH(
148       aes.Encrypt(
149           AesKey(reinterpret_cast<const uint8_t*>(bad_key_input.c_str()), 16),
150           test_str),
151       "Encrypt called with key of 16 bytes, but 32 bytes are required.");
152 }
153 
TEST(AesGcmEncryptionTest,DecryptionDiesOnShortKey)154 TEST(AesGcmEncryptionTest, DecryptionDiesOnShortKey) {
155   AesGcmEncryption aes;
156   AesKey key = MakeAesKey("Just some random 32 byte AES key");
157   std::string test_str = "This is a test. Should work on arbitrary strings.";
158 
159   std::string ciphertext = aes.Encrypt(key, test_str);
160   std::string bad_key_input = "short 17 byte key";
161   EXPECT_DEATH(
162       aes.Decrypt(
163              AesKey(reinterpret_cast<const uint8_t*>(bad_key_input.c_str()),
164                     17),
165              ciphertext)
166           .IgnoreError(),
167       "Decrypt called with key of 17 bytes, but 32 bytes are required.");
168 }
169 }  // namespace
170 }  // namespace secagg
171 }  // namespace fcp
172