1dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// Use of this source code is governed by a BSD-style license that can be
3bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// found in the LICENSE file.
4bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
5bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "chrome/browser/chromeos/login/owner_manager.h"
6bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
7bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include <string>
8bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include <vector>
9bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
10bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "base/file_path.h"
11bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "base/file_util.h"
12513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "chrome/browser/browser_process.h"
134a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "chrome/browser/chromeos/boot_times_loader.h"
14513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "chrome/browser/chromeos/login/signed_settings_temp_storage.h"
15dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/browser_thread.h"
16dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/common/notification_service.h"
17dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/common/notification_type.h"
18bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
19bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsennamespace chromeos {
20bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
21bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian MonsenOwnerManager::OwnerManager()
22bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    : private_key_(NULL),
23ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      public_key_(0),
24bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      utils_(OwnerKeyUtils::Create()) {
25bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
26bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
27bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian MonsenOwnerManager::~OwnerManager() {}
28bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
29ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid OwnerManager::UpdateOwnerKey(const BrowserThread::ID thread_id,
30ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  const std::vector<uint8>& key,
31ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  KeyUpdateDelegate* d) {
32ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
33ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
34ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  public_key_ = key;
35ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
36ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  BrowserThread::PostTask(
37ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      thread_id, FROM_HERE,
38ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NewRunnableMethod(this, &OwnerManager::CallKeyUpdateDelegate, d));
39ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
40ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
41bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid OwnerManager::LoadOwnerKey() {
424a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  BootTimesLoader::Get()->AddLoginTimeMarker("LoadOwnerKeyStart", false);
43731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
44731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  VLOG(1) << "Loading owner key";
45bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  NotificationType result = NotificationType::OWNER_KEY_FETCH_ATTEMPT_SUCCEEDED;
46bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
47bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // If |public_key_| isn't empty, we already have the key, so don't
48bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // try to import again.
49bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (public_key_.empty() &&
50bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      !utils_->ImportPublicKey(utils_->GetOwnerKeyFilePath(), &public_key_)) {
51bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    result = NotificationType::OWNER_KEY_FETCH_ATTEMPT_FAILED;
52bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
53bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
54bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // Whether we loaded the public key or not, send a notification indicating
55bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // that we're done with this attempt.
56731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  BrowserThread::PostTask(
57731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      BrowserThread::UI, FROM_HERE,
58bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      NewRunnableMethod(this,
59bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen                        &OwnerManager::SendNotification,
60bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen                        result,
61bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen                        NotificationService::NoDetails()));
62bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
63bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
64bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenbool OwnerManager::EnsurePublicKey() {
65bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (public_key_.empty())
66bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    LoadOwnerKey();
67bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
68bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  return !public_key_.empty();
69bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
70bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
71bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenbool OwnerManager::EnsurePrivateKey() {
72bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (!EnsurePublicKey())
73bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    return false;
74bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
75bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (!private_key_.get())
76bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    private_key_.reset(utils_->FindPrivateKey(public_key_));
77bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
78bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  return private_key_.get() != NULL;
79bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
80bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
81731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid OwnerManager::Sign(const BrowserThread::ID thread_id,
82bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen                        const std::string& data,
83bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen                        Delegate* d) {
844a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  BootTimesLoader::Get()->AddLoginTimeMarker("SignStart", false);
85731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
86bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
87bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // If it's not the case that we can get both keys...
88bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (!(EnsurePublicKey() && EnsurePrivateKey())) {
89731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    BrowserThread::PostTask(
90bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        thread_id, FROM_HERE,
91bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        NewRunnableMethod(this,
92bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen                          &OwnerManager::CallDelegate,
93bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen                          d, KEY_UNAVAILABLE, std::vector<uint8>()));
944a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    BootTimesLoader::Get()->AddLoginTimeMarker("SignEnd", false);
95bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    return;
96bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
97bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
98731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  VLOG(1) << "Starting signing attempt";
99bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  KeyOpCode return_code = SUCCESS;
100bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  std::vector<uint8> signature;
101bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (!utils_->Sign(data, &signature, private_key_.get())) {
102bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    return_code = OPERATION_FAILED;
103bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
104bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
105731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  BrowserThread::PostTask(
106bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      thread_id, FROM_HERE,
107bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      NewRunnableMethod(this,
108bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen                        &OwnerManager::CallDelegate,
109bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen                        d, return_code, signature));
1104a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  BootTimesLoader::Get()->AddLoginTimeMarker("SignEnd", false);
111bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
112bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
113731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid OwnerManager::Verify(const BrowserThread::ID thread_id,
114bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen                          const std::string& data,
115bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen                          const std::vector<uint8>& signature,
116bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen                          Delegate* d) {
1174a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  BootTimesLoader::Get()->AddLoginTimeMarker("VerifyStart", false);
118731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
119bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
120bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (!EnsurePublicKey()) {
121731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    BrowserThread::PostTask(
122bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        thread_id, FROM_HERE,
123bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        NewRunnableMethod(this,
124bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen                          &OwnerManager::CallDelegate,
125bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen                          d, KEY_UNAVAILABLE, std::vector<uint8>()));
1264a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    BootTimesLoader::Get()->AddLoginTimeMarker("VerifyEnd", false);
127bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    return;
128bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
129bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
130731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  VLOG(1) << "Starting verify attempt";
131bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  KeyOpCode return_code = SUCCESS;
132bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (!utils_->Verify(data, signature, public_key_)) {
133bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    return_code = OPERATION_FAILED;
134bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
135731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  BrowserThread::PostTask(
136bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      thread_id, FROM_HERE,
137bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      NewRunnableMethod(this,
138bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen                        &OwnerManager::CallDelegate,
139bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen                        d, return_code, std::vector<uint8>()));
1404a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  BootTimesLoader::Get()->AddLoginTimeMarker("VerifyEnd", false);
141bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
142bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
143bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid OwnerManager::SendNotification(NotificationType type,
144bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen                                    const NotificationDetails& details) {
145ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  NotificationService::current()->Notify(
146ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      type,
147ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NotificationService::AllSources(),
148ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      details);
149bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
150bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
151bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}  // namespace chromeos
152