1// Copyright (c) 2012 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. 4 5#include "sync/util/cryptographer.h" 6 7#include <string> 8 9#include "base/memory/scoped_ptr.h" 10#include "base/strings/string_util.h" 11#include "sync/protocol/password_specifics.pb.h" 12#include "sync/test/fake_encryptor.h" 13#include "testing/gmock/include/gmock/gmock.h" 14#include "testing/gtest/include/gtest/gtest.h" 15 16namespace syncer { 17 18namespace { 19 20using ::testing::_; 21 22} // namespace 23 24class CryptographerTest : public ::testing::Test { 25 protected: 26 CryptographerTest() : cryptographer_(&encryptor_) {} 27 28 FakeEncryptor encryptor_; 29 Cryptographer cryptographer_; 30}; 31 32TEST_F(CryptographerTest, EmptyCantDecrypt) { 33 EXPECT_FALSE(cryptographer_.is_ready()); 34 35 sync_pb::EncryptedData encrypted; 36 encrypted.set_key_name("foo"); 37 encrypted.set_blob("bar"); 38 39 EXPECT_FALSE(cryptographer_.CanDecrypt(encrypted)); 40} 41 42TEST_F(CryptographerTest, EmptyCantEncrypt) { 43 EXPECT_FALSE(cryptographer_.is_ready()); 44 45 sync_pb::EncryptedData encrypted; 46 sync_pb::PasswordSpecificsData original; 47 EXPECT_FALSE(cryptographer_.Encrypt(original, &encrypted)); 48} 49 50TEST_F(CryptographerTest, MissingCantDecrypt) { 51 KeyParams params = {"localhost", "dummy", "dummy"}; 52 cryptographer_.AddKey(params); 53 EXPECT_TRUE(cryptographer_.is_ready()); 54 55 sync_pb::EncryptedData encrypted; 56 encrypted.set_key_name("foo"); 57 encrypted.set_blob("bar"); 58 59 EXPECT_FALSE(cryptographer_.CanDecrypt(encrypted)); 60} 61 62TEST_F(CryptographerTest, CanEncryptAndDecrypt) { 63 KeyParams params = {"localhost", "dummy", "dummy"}; 64 EXPECT_TRUE(cryptographer_.AddKey(params)); 65 EXPECT_TRUE(cryptographer_.is_ready()); 66 67 sync_pb::PasswordSpecificsData original; 68 original.set_origin("http://example.com"); 69 original.set_username_value("azure"); 70 original.set_password_value("hunter2"); 71 72 sync_pb::EncryptedData encrypted; 73 EXPECT_TRUE(cryptographer_.Encrypt(original, &encrypted)); 74 75 sync_pb::PasswordSpecificsData decrypted; 76 EXPECT_TRUE(cryptographer_.Decrypt(encrypted, &decrypted)); 77 78 EXPECT_EQ(original.SerializeAsString(), decrypted.SerializeAsString()); 79} 80 81TEST_F(CryptographerTest, EncryptOnlyIfDifferent) { 82 KeyParams params = {"localhost", "dummy", "dummy"}; 83 EXPECT_TRUE(cryptographer_.AddKey(params)); 84 EXPECT_TRUE(cryptographer_.is_ready()); 85 86 sync_pb::PasswordSpecificsData original; 87 original.set_origin("http://example.com"); 88 original.set_username_value("azure"); 89 original.set_password_value("hunter2"); 90 91 sync_pb::EncryptedData encrypted; 92 EXPECT_TRUE(cryptographer_.Encrypt(original, &encrypted)); 93 94 sync_pb::EncryptedData encrypted2, encrypted3; 95 encrypted2.CopyFrom(encrypted); 96 encrypted3.CopyFrom(encrypted); 97 EXPECT_TRUE(cryptographer_.Encrypt(original, &encrypted2)); 98 99 // Now encrypt with a new default key. Should overwrite the old data. 100 KeyParams params_new = {"localhost", "dummy", "dummy2"}; 101 cryptographer_.AddKey(params_new); 102 EXPECT_TRUE(cryptographer_.Encrypt(original, &encrypted3)); 103 104 sync_pb::PasswordSpecificsData decrypted; 105 EXPECT_TRUE(cryptographer_.Decrypt(encrypted2, &decrypted)); 106 // encrypted2 should match encrypted, encrypted3 should not (due to salting). 107 EXPECT_EQ(encrypted.SerializeAsString(), encrypted2.SerializeAsString()); 108 EXPECT_NE(encrypted.SerializeAsString(), encrypted3.SerializeAsString()); 109 EXPECT_EQ(original.SerializeAsString(), decrypted.SerializeAsString()); 110} 111 112TEST_F(CryptographerTest, AddKeySetsDefault) { 113 KeyParams params1 = {"localhost", "dummy", "dummy1"}; 114 EXPECT_TRUE(cryptographer_.AddKey(params1)); 115 EXPECT_TRUE(cryptographer_.is_ready()); 116 117 sync_pb::PasswordSpecificsData original; 118 original.set_origin("http://example.com"); 119 original.set_username_value("azure"); 120 original.set_password_value("hunter2"); 121 122 sync_pb::EncryptedData encrypted1; 123 EXPECT_TRUE(cryptographer_.Encrypt(original, &encrypted1)); 124 sync_pb::EncryptedData encrypted2; 125 EXPECT_TRUE(cryptographer_.Encrypt(original, &encrypted2)); 126 127 KeyParams params2 = {"localhost", "dummy", "dummy2"}; 128 EXPECT_TRUE(cryptographer_.AddKey(params2)); 129 EXPECT_TRUE(cryptographer_.is_ready()); 130 131 sync_pb::EncryptedData encrypted3; 132 EXPECT_TRUE(cryptographer_.Encrypt(original, &encrypted3)); 133 sync_pb::EncryptedData encrypted4; 134 EXPECT_TRUE(cryptographer_.Encrypt(original, &encrypted4)); 135 136 EXPECT_EQ(encrypted1.key_name(), encrypted2.key_name()); 137 EXPECT_NE(encrypted1.key_name(), encrypted3.key_name()); 138 EXPECT_EQ(encrypted3.key_name(), encrypted4.key_name()); 139} 140 141// Crashes, Bug 55178. 142#if defined(OS_WIN) 143#define MAYBE_EncryptExportDecrypt DISABLED_EncryptExportDecrypt 144#else 145#define MAYBE_EncryptExportDecrypt EncryptExportDecrypt 146#endif 147TEST_F(CryptographerTest, MAYBE_EncryptExportDecrypt) { 148 sync_pb::EncryptedData nigori; 149 sync_pb::EncryptedData encrypted; 150 151 sync_pb::PasswordSpecificsData original; 152 original.set_origin("http://example.com"); 153 original.set_username_value("azure"); 154 original.set_password_value("hunter2"); 155 156 { 157 Cryptographer cryptographer(&encryptor_); 158 159 KeyParams params = {"localhost", "dummy", "dummy"}; 160 cryptographer.AddKey(params); 161 EXPECT_TRUE(cryptographer.is_ready()); 162 163 EXPECT_TRUE(cryptographer.Encrypt(original, &encrypted)); 164 EXPECT_TRUE(cryptographer.GetKeys(&nigori)); 165 } 166 167 { 168 Cryptographer cryptographer(&encryptor_); 169 EXPECT_FALSE(cryptographer.CanDecrypt(nigori)); 170 171 cryptographer.SetPendingKeys(nigori); 172 EXPECT_FALSE(cryptographer.is_ready()); 173 EXPECT_TRUE(cryptographer.has_pending_keys()); 174 175 KeyParams params = {"localhost", "dummy", "dummy"}; 176 EXPECT_TRUE(cryptographer.DecryptPendingKeys(params)); 177 EXPECT_TRUE(cryptographer.is_ready()); 178 EXPECT_FALSE(cryptographer.has_pending_keys()); 179 180 sync_pb::PasswordSpecificsData decrypted; 181 EXPECT_TRUE(cryptographer.Decrypt(encrypted, &decrypted)); 182 EXPECT_EQ(original.SerializeAsString(), decrypted.SerializeAsString()); 183 } 184} 185 186TEST_F(CryptographerTest, Bootstrap) { 187 KeyParams params = {"localhost", "dummy", "dummy"}; 188 cryptographer_.AddKey(params); 189 190 std::string token; 191 EXPECT_TRUE(cryptographer_.GetBootstrapToken(&token)); 192 EXPECT_TRUE(base::IsStringUTF8(token)); 193 194 Cryptographer other_cryptographer(&encryptor_); 195 other_cryptographer.Bootstrap(token); 196 EXPECT_TRUE(other_cryptographer.is_ready()); 197 198 const char secret[] = "secret"; 199 sync_pb::EncryptedData encrypted; 200 EXPECT_TRUE(other_cryptographer.EncryptString(secret, &encrypted)); 201 EXPECT_TRUE(cryptographer_.CanDecryptUsingDefaultKey(encrypted)); 202} 203 204// Verifies that copied cryptographers are just as good as the original. 205// 206// Encrypt an item using the original cryptographer and two different sets of 207// keys. Verify that it can decrypt them. 208// 209// Then copy the original cryptographer and ensure it can also decrypt these 210// items and encrypt them with the most recent key. 211TEST_F(CryptographerTest, CopyConstructor) { 212 sync_pb::PasswordSpecificsData original; 213 original.set_origin("http://example.com"); 214 original.set_username_value("luser"); 215 original.set_password_value("p4ssw0rd"); 216 217 // Start by testing the original cryptogprapher. 218 KeyParams params1 = {"localhost", "dummy", "dummy"}; 219 EXPECT_TRUE(cryptographer_.AddKey(params1)); 220 EXPECT_TRUE(cryptographer_.is_ready()); 221 222 sync_pb::EncryptedData encrypted_k1; 223 EXPECT_TRUE(cryptographer_.Encrypt(original, &encrypted_k1)); 224 225 KeyParams params2 = {"localhost", "fatuous", "fatuous"}; 226 EXPECT_TRUE(cryptographer_.AddKey(params2)); 227 EXPECT_TRUE(cryptographer_.is_ready()); 228 229 sync_pb::EncryptedData encrypted_k2; 230 EXPECT_TRUE(cryptographer_.Encrypt(original, &encrypted_k2)); 231 232 sync_pb::PasswordSpecificsData decrypted_k1; 233 sync_pb::PasswordSpecificsData decrypted_k2; 234 EXPECT_TRUE(cryptographer_.Decrypt(encrypted_k1, &decrypted_k1)); 235 EXPECT_TRUE(cryptographer_.Decrypt(encrypted_k2, &decrypted_k2)); 236 237 EXPECT_EQ(original.SerializeAsString(), decrypted_k1.SerializeAsString()); 238 EXPECT_EQ(original.SerializeAsString(), decrypted_k2.SerializeAsString()); 239 240 // Clone the cryptographer and test that it behaves the same. 241 Cryptographer cryptographer_clone(cryptographer_); 242 243 // The clone should be able to decrypt with old and new keys. 244 sync_pb::PasswordSpecificsData decrypted_k1_clone; 245 sync_pb::PasswordSpecificsData decrypted_k2_clone; 246 EXPECT_TRUE(cryptographer_clone.Decrypt(encrypted_k1, &decrypted_k1_clone)); 247 EXPECT_TRUE(cryptographer_clone.Decrypt(encrypted_k2, &decrypted_k2_clone)); 248 249 EXPECT_EQ(original.SerializeAsString(), 250 decrypted_k1_clone.SerializeAsString()); 251 EXPECT_EQ(original.SerializeAsString(), 252 decrypted_k2_clone.SerializeAsString()); 253 254 // The old cryptographer should be able to decrypt things encrypted by the 255 // new. 256 sync_pb::EncryptedData encrypted_c; 257 EXPECT_TRUE(cryptographer_clone.Encrypt(original, &encrypted_c)); 258 259 sync_pb::PasswordSpecificsData decrypted_c; 260 EXPECT_TRUE(cryptographer_.Decrypt(encrypted_c, &decrypted_c)); 261 EXPECT_EQ(original.SerializeAsString(), decrypted_c.SerializeAsString()); 262 263 // The cloned cryptographer should be using the latest key. 264 EXPECT_EQ(encrypted_c.key_name(), encrypted_k2.key_name()); 265} 266 267} // namespace syncer 268