cygprofile: increase timeouts to allow showing web contents
[chromium-blink-merge.git] / components / gcm_driver / crypto / gcm_message_cryptographer_unittest.cc
bloba1a0280e013012f42ced3b5b2bc2df00e1d6d366
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "components/gcm_driver/crypto/gcm_message_cryptographer.h"
7 #include "base/base64.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/strings/string_util.h"
10 #include "crypto/random.h"
11 #include "crypto/symmetric_key.h"
12 #include "testing/gtest/include/gtest/gtest.h"
14 namespace gcm {
16 namespace {
18 // The number of bits of the key in AEAD_AES_128_GCM.
19 const size_t kKeySizeBits = 128;
21 // Example plaintext data to use in the tests.
22 const char kExamplePlaintext[] = "Example plaintext";
24 // A test vector contains the information necessary to either encrypt or decrypt
25 // a message. These vectors were created using a JavaScript implementation of
26 // the same RFCs that the GCMMessageCryptographer implements.
27 struct TestVector {
28 const char* const input;
29 const char* const key;
30 const char* const salt;
31 size_t record_size;
32 const char* const output;
35 const TestVector kEncryptionTestVectors[] = {
36 // Simple message.
37 { "Hello, world!",
38 "AhA6n2oFYPWIh+cXwyv1m2C0JvmjHB4ZkXj8QylESXU=",
39 "tsJYqAGvFDk6lDEv7daecw==",
40 4096,
41 "KNXRqBR9VKhtajeMaeKR/rHYIiORcyeFpUwWFGyS"
43 // Empty message.
44 { "",
45 "lMyvTong4VR053jfCpWmMDGW5dEDAqiTZUIU+inhTjU=",
46 "wH3uvZqcN6oey9whiGpn1A==",
47 4096,
48 "Mnfr+AU5o7D30gjFdVOTFtw="
50 // Message with an invalid salt size.
51 { "Hello, world!",
52 "CcdxzkR6z1EY9vSrM7/IxYVxDxu46hV638EZQTPd7XI=",
53 "aRr1fI1YSGVi5XU=",
54 4096,
55 nullptr // expected to fail
59 const TestVector kDecryptionTestVectors[] = {
60 // Simple message.
61 { "avAFNhdbQohzizu+ORbU4XHhHSaXzw9lTN7UzB/j",
62 "47ZytAw9qHlm+Q8g+7rH81rUPzaCgGcoFvlS1qxQtQk=",
63 "EuR7EVetcaWpndXd/dKeyA==",
64 4096,
65 "Hello, world!"
67 // Simple message with 16 bytes of padding.
68 { "0198n7ZJ/ZPMnl4ZU2l9Lma5ktKbuzXCiJEXyYtROmWTP8RSiZd8sUd48xpk6Q==",
69 "MYSsNybwrTzRIzQYUq/yFPc6ugcTrJdEZJDM4NswvUg=",
70 "8sEAMQYnufo2UkKl80cUGQ==",
71 4096,
72 "Hello, world!"
74 // Empty message.
75 { "g+ACk32a4gK2dS2xllKXn4c=",
76 "S3+Ki/+XtzR66gUp/zR75CC5JXO62pyr5fWfneTYwFE=",
77 "4RM6s19jJHdmqiVEJDp9jg==",
78 4096,
81 // Message with an invalid salt size.
82 { "rt4OiodS087DAQo6e24wA55k0hRPAHgz7OX7m+nj",
83 "wW3Iy5ma803lLd+ysPdHUe2NB3HqXbY0XhCCdG5Y1Gw=",
84 "N7oMH/xohAhMhOY=",
85 4096,
86 nullptr // expected to fail
88 // Message with an invalid record size.
89 { "AsuoRkFtqLE1c0mGCae4OvgZSCSHWCoeRL9mXKjY",
90 "omxWz7tse3lgDpxUP+e7u14Dp1irvV3BdzXTcZOtsHs=",
91 "vKJD3bexto1hY64KVzS7ug==",
93 nullptr // expected to fail
95 // Truncated message.
96 { "AGr4BfZSXW9txWkAG8pjg7IuRWWm1Mo8bDli/PSv",
97 "kR5BMfqMKOD1yrLKE2giObXHI7merrMtnoO2oqneqXA=",
98 "SQeJSPrqHvTdSfAMF8bBzQ==",
99 13,
100 nullptr // expected to fail
102 // Message with multiple (2) records.
103 { "H2ujfPbpRbVSy+adIG2NRe4VxkX4V0r/zl6e9xnMSF6LSutblGdWLrwQc82Xh7DXAQlihW0q3"
104 "IQzHP+LIxuAiA==",
105 "W3W4gx7sqcfmBnvNNdO9d4MBCC1bvJkvsNjZOGD+CCg=",
106 "xG0TPGi9aIcxjpXKmaYBBQ==",
108 nullptr // expected to fail
112 } // namespace
114 class GCMMessageCryptographerTest : public ::testing::Test {
115 public:
116 void SetUp() override {
117 scoped_ptr<crypto::SymmetricKey> random_key(
118 crypto::SymmetricKey::GenerateRandomKey(crypto::SymmetricKey::AES,
119 kKeySizeBits));
121 ASSERT_TRUE(random_key->GetRawKey(&key_));
124 protected:
125 // Generates a cryptographically secure random salt of 16-octets in size, the
126 // required length as expected by the HKDF.
127 std::string GenerateRandomSalt() {
128 const size_t kSaltSize = 16;
130 std::string salt;
132 crypto::RandBytes(base::WriteInto(&salt, kSaltSize + 1), kSaltSize);
133 return salt;
136 GCMMessageCryptographer* cryptographer() { return &cryptographer_; }
138 base::StringPiece key() const { return key_; }
140 private:
141 GCMMessageCryptographer cryptographer_;
143 std::string key_;
146 TEST_F(GCMMessageCryptographerTest, RoundTrip) {
147 const std::string salt = GenerateRandomSalt();
149 size_t record_size = 0;
151 std::string ciphertext, plaintext;
152 ASSERT_TRUE(cryptographer()->Encrypt(kExamplePlaintext, key(), salt,
153 &record_size, &ciphertext));
155 EXPECT_GT(record_size, ciphertext.size() - 16);
156 EXPECT_GT(ciphertext.size(), 0u);
158 ASSERT_TRUE(cryptographer()->Decrypt(ciphertext, key(), salt, record_size,
159 &plaintext));
161 EXPECT_EQ(kExamplePlaintext, plaintext);
164 TEST_F(GCMMessageCryptographerTest, RoundTripEmptyMessage) {
165 const std::string salt = GenerateRandomSalt();
166 const std::string message = "";
168 size_t record_size = 0;
170 std::string ciphertext, plaintext;
171 ASSERT_TRUE(cryptographer()->Encrypt(message, key(), salt, &record_size,
172 &ciphertext));
174 EXPECT_GT(record_size, ciphertext.size() - 16);
175 EXPECT_GT(ciphertext.size(), 0u);
177 ASSERT_TRUE(cryptographer()->Decrypt(ciphertext, key(), salt, record_size,
178 &plaintext));
180 EXPECT_EQ(message, plaintext);
183 TEST_F(GCMMessageCryptographerTest, InvalidRecordSize) {
184 const std::string salt = GenerateRandomSalt();
186 size_t record_size = 0;
188 std::string ciphertext, plaintext;
189 EXPECT_TRUE(cryptographer()->Encrypt(kExamplePlaintext, key(), salt,
190 &record_size, &ciphertext));
192 EXPECT_GT(record_size, ciphertext.size() - 16);
193 EXPECT_FALSE(cryptographer()->Decrypt(ciphertext, key(), salt,
194 0 /* record_size */, &plaintext));
196 EXPECT_FALSE(cryptographer()->Decrypt(ciphertext, key(), salt,
197 ciphertext.size() - 17, &plaintext));
199 EXPECT_TRUE(cryptographer()->Decrypt(ciphertext, key(), salt,
200 ciphertext.size() - 16, &plaintext));
203 TEST_F(GCMMessageCryptographerTest, InvalidRecordPadding) {
204 std::string message = std::string(1, '\0') + kExamplePlaintext;
206 const std::string salt = GenerateRandomSalt();
208 const std::string nonce = cryptographer()->DeriveNonce(key(), salt);
209 const std::string content_encryption_key =
210 cryptographer()->DeriveContentEncryptionKey(key(), salt);
212 ASSERT_GT(message.size(), 1u);
213 const size_t record_size = message.size() + 1;
215 std::string ciphertext, plaintext;
216 ASSERT_TRUE(cryptographer()->EncryptDecryptRecordInternal(
217 GCMMessageCryptographer::ENCRYPT, message, content_encryption_key, nonce,
218 &ciphertext));
220 ASSERT_TRUE(cryptographer()->Decrypt(ciphertext, key(), salt, record_size,
221 &plaintext));
223 // Note that GCMMessageCryptographer::Decrypt removes the padding.
224 EXPECT_EQ(kExamplePlaintext, plaintext);
226 // Now run the same steps again, but say that there are four padding octets.
227 // This should be rejected because the padding will not be all zeros.
228 message[0] = 4;
230 ASSERT_TRUE(cryptographer()->EncryptDecryptRecordInternal(
231 GCMMessageCryptographer::ENCRYPT, message, content_encryption_key, nonce,
232 &ciphertext));
234 ASSERT_FALSE(cryptographer()->Decrypt(ciphertext, key(), salt, record_size,
235 &plaintext));
237 // Run the same steps again, but say that there are more padding octets than
238 // the length of the message.
239 message[0] = 64;
241 EXPECT_GT(static_cast<size_t>(message[0]), message.size());
242 ASSERT_TRUE(cryptographer()->EncryptDecryptRecordInternal(
243 GCMMessageCryptographer::ENCRYPT, message, content_encryption_key, nonce,
244 &ciphertext));
246 ASSERT_FALSE(cryptographer()->Decrypt(ciphertext, key(), salt, record_size,
247 &plaintext));
250 TEST_F(GCMMessageCryptographerTest, EncryptionTestVectors) {
251 std::string key, salt, output, ciphertext;
252 size_t record_size = 0;
254 for (size_t i = 0; i < arraysize(kEncryptionTestVectors); ++i) {
255 SCOPED_TRACE(i);
257 ASSERT_TRUE(base::Base64Decode(kEncryptionTestVectors[i].key, &key));
258 ASSERT_TRUE(base::Base64Decode(kEncryptionTestVectors[i].salt, &salt));
260 const bool has_output = kEncryptionTestVectors[i].output;
261 const bool result = cryptographer()->Encrypt(
262 kEncryptionTestVectors[i].input, key, salt, &record_size, &ciphertext);
264 if (!has_output) {
265 EXPECT_FALSE(result);
266 continue;
269 EXPECT_TRUE(result);
270 ASSERT_TRUE(base::Base64Decode(kEncryptionTestVectors[i].output,
271 &output));
273 EXPECT_EQ(kEncryptionTestVectors[i].record_size, record_size);
274 EXPECT_EQ(output, ciphertext);
278 TEST_F(GCMMessageCryptographerTest, DecryptionTestVectors) {
279 std::string input, key, salt, plaintext;
280 for (size_t i = 0; i < arraysize(kDecryptionTestVectors); ++i) {
281 SCOPED_TRACE(i);
283 ASSERT_TRUE(base::Base64Decode(kDecryptionTestVectors[i].input, &input));
284 ASSERT_TRUE(base::Base64Decode(kDecryptionTestVectors[i].key, &key));
285 ASSERT_TRUE(base::Base64Decode(kDecryptionTestVectors[i].salt, &salt));
287 const bool has_output = kDecryptionTestVectors[i].output;
288 const bool result = cryptographer()->Decrypt(
289 input, key, salt, kDecryptionTestVectors[i].record_size, &plaintext);
291 if (!has_output) {
292 EXPECT_FALSE(result);
293 continue;
296 EXPECT_TRUE(result);
297 EXPECT_EQ(kDecryptionTestVectors[i].output, plaintext);
301 } // namespace gcm