Home | History | Annotate | Download | only in util
      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 
     16 namespace syncer {
     17 
     18 namespace {
     19 
     20 using ::testing::_;
     21 
     22 }  // namespace
     23 
     24 class CryptographerTest : public ::testing::Test {
     25  protected:
     26   CryptographerTest() : cryptographer_(&encryptor_) {}
     27 
     28   FakeEncryptor encryptor_;
     29   Cryptographer cryptographer_;
     30 };
     31 
     32 TEST_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 
     42 TEST_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 
     50 TEST_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 
     62 TEST_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 
     81 TEST_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 
    112 TEST_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
    147 TEST_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 
    186 TEST_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.
    211 TEST_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