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