1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
53345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/base64.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/util/cryptographer.h"
73345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/browser/password_manager/encryptor.h"
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace browser_sync {
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char kNigoriTag[] = "google_chrome_nigori";
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// We name a particular Nigori instance (ie. a triplet consisting of a hostname,
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// a username, and a password) by calling Permute on this string. Since the
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// output of Permute is always the same for a given triplet, clients will always
16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// assign the same name to a particular triplet.
17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char kNigoriKeyName[] = "nigori-key";
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochCryptographer::Cryptographer() : default_nigori_(NULL) {
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
22731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickCryptographer::~Cryptographer() {}
23731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid Cryptographer::Bootstrap(const std::string& restored_bootstrap_token) {
253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (is_ready()) {
263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    NOTREACHED();
273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return;
283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<Nigori> nigori(UnpackBootstrapToken(restored_bootstrap_token));
313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (nigori.get())
323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    AddKeyImpl(nigori.release());
333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool Cryptographer::CanDecrypt(const sync_pb::EncryptedData& data) const {
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return nigoris_.end() != nigoris_.find(data.key_name());
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
39ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool Cryptographer::CanDecryptUsingDefaultKey(
40ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const sync_pb::EncryptedData& data) const {
41ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return default_nigori_ && (data.key_name() == default_nigori_->first);
42ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
43ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool Cryptographer::Encrypt(const ::google::protobuf::MessageLite& message,
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            sync_pb::EncryptedData* encrypted) const {
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(encrypted);
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(default_nigori_);
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string serialized;
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!message.SerializeToString(&serialized)) {
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NOTREACHED();  // |message| is invalid/missing a required field.
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  encrypted->set_key_name(default_nigori_->first);
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!default_nigori_->second->Encrypt(serialized,
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                        encrypted->mutable_blob())) {
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NOTREACHED();  // Encrypt should not fail.
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool Cryptographer::Decrypt(const sync_pb::EncryptedData& encrypted,
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            ::google::protobuf::MessageLite* message) const {
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(message);
67dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  std::string plaintext = DecryptToString(encrypted);
68dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return message->ParseFromString(plaintext);
69dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
71dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenstd::string Cryptographer::DecryptToString(
72dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    const sync_pb::EncryptedData& encrypted) const {
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NigoriMap::const_iterator it = nigoris_.find(encrypted.key_name());
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (nigoris_.end() == it) {
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NOTREACHED() << "Cannot decrypt message";
76dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return std::string("");  // Caller should have called CanDecrypt(encrypt).
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string plaintext;
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!it->second->Decrypt(encrypted.blob(), &plaintext)) {
81dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return std::string("");
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
84dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return plaintext;
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool Cryptographer::GetKeys(sync_pb::EncryptedData* encrypted) const {
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(encrypted);
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(!nigoris_.empty());
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Create a bag of all the Nigori parameters we know about.
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  sync_pb::NigoriKeyBag bag;
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (NigoriMap::const_iterator it = nigoris_.begin(); it != nigoris_.end();
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       ++it) {
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const Nigori& nigori = *it->second;
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    sync_pb::NigoriKey* key = bag.add_key();
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    key->set_name(it->first);
983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    nigori.ExportKeys(key->mutable_user_key(),
993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                      key->mutable_encryption_key(),
1003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                      key->mutable_mac_key());
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Encrypt the bag with the default Nigori.
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return Encrypt(bag, encrypted);
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool Cryptographer::AddKey(const KeyParams& params) {
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(NULL == pending_keys_.get());
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Create the new Nigori and make it the default encryptor.
1113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<Nigori> nigori(new Nigori);
1123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!nigori->InitByDerivation(params.hostname,
1133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                params.username,
1143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                params.password)) {
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NOTREACHED();  // Invalid username or password.
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
1183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return AddKeyImpl(nigori.release());
1193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
1203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool Cryptographer::AddKeyImpl(Nigori* initialized_nigori) {
1223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<Nigori> nigori(initialized_nigori);
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string name;
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!nigori->Permute(Nigori::Password, kNigoriKeyName, &name)) {
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NOTREACHED();
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  nigoris_[name] = make_linked_ptr(nigori.release());
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  default_nigori_ = &*nigoris_.find(name);
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool Cryptographer::SetKeys(const sync_pb::EncryptedData& encrypted) {
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(CanDecrypt(encrypted));
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  sync_pb::NigoriKeyBag bag;
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!Decrypt(encrypted, &bag)) {
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  InstallKeys(encrypted.key_name(), bag);
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid Cryptographer::SetPendingKeys(const sync_pb::EncryptedData& encrypted) {
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(!CanDecrypt(encrypted));
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  pending_keys_.reset(new sync_pb::EncryptedData(encrypted));
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool Cryptographer::DecryptPendingKeys(const KeyParams& params) {
1503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  Nigori nigori;
1513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!nigori.InitByDerivation(params.hostname,
1523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                               params.username,
1533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                               params.password)) {
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NOTREACHED();
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string plaintext;
159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!nigori.Decrypt(pending_keys_->blob(), &plaintext))
160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  sync_pb::NigoriKeyBag bag;
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!bag.ParseFromString(plaintext)) {
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NOTREACHED();
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  InstallKeys(pending_keys_->key_name(), bag);
168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  pending_keys_.reset();
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool Cryptographer::GetBootstrapToken(std::string* token) const {
1733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK(token);
1743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!is_ready())
1753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return false;
1763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return PackBootstrapToken(default_nigori_->second.get(), token);
1783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
1793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool Cryptographer::PackBootstrapToken(const Nigori* nigori,
1813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                       std::string* pack_into) const {
1823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK(pack_into);
1833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK(nigori);
1843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  sync_pb::NigoriKey key;
1863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!nigori->ExportKeys(key.mutable_user_key(),
1873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                          key.mutable_encryption_key(),
1883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                          key.mutable_mac_key())) {
1893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    NOTREACHED();
1903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return false;
1913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
1923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  std::string unencrypted_token;
1943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!key.SerializeToString(&unencrypted_token)) {
1953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    NOTREACHED();
1963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return false;
1973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
1983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  std::string encrypted_token;
2003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!Encryptor::EncryptString(unencrypted_token, &encrypted_token)) {
2013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    NOTREACHED();
2023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return false;
2033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
2043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!base::Base64Encode(encrypted_token, pack_into)) {
2063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    NOTREACHED();
2073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return false;
2083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
2093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return true;
2103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
2113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2123345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickNigori* Cryptographer::UnpackBootstrapToken(const std::string& token) const {
2133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (token.empty())
2143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return NULL;
2153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  std::string encrypted_data;
217dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (!base::Base64Decode(token, &encrypted_data)) {
2183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    DLOG(WARNING) << "Could not decode token.";
2193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return NULL;
2203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
2213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  std::string unencrypted_token;
2233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!Encryptor::DecryptString(encrypted_data, &unencrypted_token)) {
2243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    DLOG(WARNING) << "Decryption of bootstrap token failed.";
2253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return NULL;
2263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
2273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  sync_pb::NigoriKey key;
2293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!key.ParseFromString(unencrypted_token)) {
2303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    DLOG(WARNING) << "Parsing of bootstrap token failed.";
2313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return NULL;
2323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
2333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<Nigori> nigori(new Nigori);
2353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!nigori->InitByImport(key.user_key(), key.encryption_key(),
2363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                            key.mac_key())) {
2373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    NOTREACHED();
2383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return NULL;
2393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
2403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return nigori.release();
2423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
2433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid Cryptographer::InstallKeys(const std::string& default_key_name,
245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                const sync_pb::NigoriKeyBag& bag) {
246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int key_size = bag.key_size();
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (int i = 0; i < key_size; ++i) {
248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const sync_pb::NigoriKey key = bag.key(i);
249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Only use this key if we don't already know about it.
250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (nigoris_.end() == nigoris_.find(key.name())) {
2513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      scoped_ptr<Nigori> new_nigori(new Nigori);
2523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      if (!new_nigori->InitByImport(key.user_key(),
2533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                    key.encryption_key(),
2543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                    key.mac_key())) {
255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NOTREACHED();
256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        continue;
257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      nigoris_[key.name()] = make_linked_ptr(new_nigori.release());
259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(nigoris_.end() != nigoris_.find(default_key_name));
262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  default_nigori_ = &*nigoris_.find(default_key_name);
263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace browser_sync
266