OLD | NEW |
(Empty) | |
| 1 // Copyright 2014 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 "chrome/browser/chromeos/platform_keys/platform_keys_service.h" |
| 6 |
| 7 #include "base/base64.h" |
| 8 #include "base/callback.h" |
| 9 #include "base/values.h" |
| 10 #include "chrome/browser/chromeos/platform_keys/platform_keys.h" |
| 11 #include "chrome/browser/extensions/state_store.h" |
| 12 #include "content/public/browser/browser_thread.h" |
| 13 |
| 14 using content::BrowserThread; |
| 15 |
| 16 namespace chromeos { |
| 17 |
| 18 namespace { |
| 19 |
| 20 const char kErrorInternal[] = "Internal Error."; |
| 21 const char kErrorKeyNotAllowedForSigning[] = |
| 22 "This key is not allowed for signing. Either it was used for signing " |
| 23 "before or it was not correctly generated."; |
| 24 const char kStateStorePlatformKeys[] = "PlatformKeys"; |
| 25 |
| 26 scoped_ptr<base::StringValue> GetPublicKeyValue( |
| 27 const std::string& public_key_spki_der) { |
| 28 std::string public_key_spki_der_b64; |
| 29 base::Base64Encode(public_key_spki_der, &public_key_spki_der_b64); |
| 30 return make_scoped_ptr(new base::StringValue(public_key_spki_der_b64)); |
| 31 } |
| 32 |
| 33 // Wraps |callback| into a void(bool) callback which forwards |
| 34 // |public_key_spki_der| if |true| is passed to it. |
| 35 void WrapGenerateKeyCallback( |
| 36 const PlatformKeysService::GenerateKeyCallback& callback, |
| 37 const std::string& public_key_spki_der, |
| 38 bool success) { |
| 39 if (success) |
| 40 callback.Run(public_key_spki_der, std::string() /* no error */); |
| 41 else |
| 42 callback.Run(std::string() /* no public key */, kErrorInternal); |
| 43 } |
| 44 |
| 45 // Callback used by |PlatformKeysService::Sign|. |
| 46 // Is called with the old validity of |public_key_spki_der| (or false if an |
| 47 // error occurred during reading the StateStore). If allowed, starts the actual |
| 48 // signing operation which will call back |callback|. If not allowed, calls |
| 49 // |callback| with an error. |
| 50 void CheckValidityAndSign(const std::string& token_id, |
| 51 const std::string& public_key_spki_der, |
| 52 const std::string& data, |
| 53 const PlatformKeysService::SignCallback& callback, |
| 54 Profile* profile, |
| 55 bool key_is_valid) { |
| 56 if (!key_is_valid) { |
| 57 callback.Run(std::string() /* no signature */, |
| 58 kErrorKeyNotAllowedForSigning); |
| 59 return; |
| 60 } |
| 61 platform_keys::subtle::Sign( |
| 62 token_id, public_key_spki_der, data, callback, profile); |
| 63 } |
| 64 |
| 65 } // namespace |
| 66 |
| 67 PlatformKeysService::PlatformKeysService(extensions::StateStore* state_store) |
| 68 : state_store_(state_store), weak_factory_(this) { |
| 69 DCHECK(state_store); |
| 70 } |
| 71 |
| 72 PlatformKeysService::~PlatformKeysService() { |
| 73 } |
| 74 |
| 75 void PlatformKeysService::GenerateRSAKey(const std::string& token_id, |
| 76 unsigned int modulus_length, |
| 77 const std::string& extension_id, |
| 78 const GenerateKeyCallback& callback, |
| 79 Profile* profile) { |
| 80 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 81 |
| 82 platform_keys::subtle::GenerateRSAKey(token_id, |
| 83 modulus_length, |
| 84 base::Bind(&GenerateRSAKeyCallback, |
| 85 extension_id, |
| 86 callback, |
| 87 weak_factory_.GetWeakPtr()), |
| 88 profile); |
| 89 } |
| 90 |
| 91 void PlatformKeysService::Sign(const std::string& token_id, |
| 92 const std::string& public_key_spki_der, |
| 93 const std::string& data, |
| 94 const std::string& extension_id, |
| 95 const SignCallback& callback, |
| 96 Profile* profile) { |
| 97 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 98 ReadValidityAndInvalidateKey(extension_id, |
| 99 public_key_spki_der, |
| 100 base::Bind(&CheckValidityAndSign, |
| 101 token_id, |
| 102 public_key_spki_der, |
| 103 data, |
| 104 callback, |
| 105 profile)); |
| 106 } |
| 107 |
| 108 void PlatformKeysService::RegisterPublicKey( |
| 109 const std::string& extension_id, |
| 110 const std::string& public_key_spki_der, |
| 111 const base::Callback<void(bool)>& callback) { |
| 112 GetPlatformKeysOfExtension(extension_id, |
| 113 base::Bind(&RegisterPublicKeyGotPlatformKeys, |
| 114 extension_id, |
| 115 public_key_spki_der, |
| 116 callback)); |
| 117 } |
| 118 |
| 119 void PlatformKeysService::ReadValidityAndInvalidateKey( |
| 120 const std::string& extension_id, |
| 121 const std::string& public_key_spki_der, |
| 122 const base::Callback<void(bool)>& callback) { |
| 123 GetPlatformKeysOfExtension( |
| 124 extension_id, |
| 125 base::Bind(&InvalidateKey, extension_id, public_key_spki_der, callback)); |
| 126 } |
| 127 |
| 128 void PlatformKeysService::GetPlatformKeysOfExtension( |
| 129 const std::string& extension_id, |
| 130 const GetPlatformKeysCallback& callback) { |
| 131 state_store_->GetExtensionValue(extension_id, |
| 132 kStateStorePlatformKeys, |
| 133 base::Bind(&GotPlatformKeysOfExtension, |
| 134 extension_id, |
| 135 weak_factory_.GetWeakPtr(), |
| 136 callback)); |
| 137 } |
| 138 |
| 139 // static |
| 140 void PlatformKeysService::GenerateRSAKeyCallback( |
| 141 const std::string& extension_id, |
| 142 const GenerateKeyCallback& callback, |
| 143 base::WeakPtr<PlatformKeysService> service, |
| 144 const std::string& public_key_spki_der, |
| 145 const std::string& error_message) { |
| 146 if (!error_message.empty()) { |
| 147 callback.Run(std::string() /* no public key */, error_message); |
| 148 return; |
| 149 } |
| 150 base::Callback<void(bool)> wrapped_callback( |
| 151 base::Bind(&WrapGenerateKeyCallback, callback, public_key_spki_der)); |
| 152 if (!service) { |
| 153 LOG(ERROR) << "PlatformKeysService is already destructed."; |
| 154 wrapped_callback.Run(false); |
| 155 return; |
| 156 } |
| 157 service->RegisterPublicKey( |
| 158 extension_id, public_key_spki_der, wrapped_callback); |
| 159 } |
| 160 |
| 161 // static |
| 162 void PlatformKeysService::RegisterPublicKeyGotPlatformKeys( |
| 163 const std::string& extension_id, |
| 164 const std::string& public_key_spki_der, |
| 165 const base::Callback<void(bool)>& callback, |
| 166 base::WeakPtr<PlatformKeysService> service, |
| 167 scoped_ptr<base::ListValue> platform_keys) { |
| 168 if (!service) { |
| 169 LOG(ERROR) << "PlatformKeysService is already destructed."; |
| 170 callback.Run(false); |
| 171 return; |
| 172 } |
| 173 |
| 174 if (!platform_keys) { |
| 175 LOG(ERROR) << "Error while reading the platform keys."; |
| 176 callback.Run(false); |
| 177 return; |
| 178 } |
| 179 |
| 180 scoped_ptr<base::StringValue> key_value( |
| 181 GetPublicKeyValue(public_key_spki_der)); |
| 182 |
| 183 DCHECK(platform_keys->end() == platform_keys->Find(*key_value)) |
| 184 << "Keys are assumed to be generated and not to be registered multiple " |
| 185 "times."; |
| 186 platform_keys->Append(key_value.release()); |
| 187 |
| 188 service->state_store_->SetExtensionValue(extension_id, |
| 189 kStateStorePlatformKeys, |
| 190 platform_keys.PassAs<base::Value>()); |
| 191 callback.Run(true); |
| 192 } |
| 193 |
| 194 // static |
| 195 void PlatformKeysService::InvalidateKey( |
| 196 const std::string& extension_id, |
| 197 const std::string& public_key_spki_der, |
| 198 const base::Callback<void(bool)>& callback, |
| 199 base::WeakPtr<PlatformKeysService> service, |
| 200 scoped_ptr<base::ListValue> platform_keys) { |
| 201 if (!service) { |
| 202 LOG(ERROR) << "PlatformKeysService is already destructed."; |
| 203 callback.Run(false); |
| 204 return; |
| 205 } |
| 206 |
| 207 scoped_ptr<base::StringValue> key_value( |
| 208 GetPublicKeyValue(public_key_spki_der)); |
| 209 |
| 210 size_t index = 0; |
| 211 if (!platform_keys->Remove(*key_value, &index)) { |
| 212 // The key is not found, so it's not valid to use it for signing. |
| 213 callback.Run(false); |
| 214 return; |
| 215 } |
| 216 |
| 217 service->state_store_->SetExtensionValue(extension_id, |
| 218 kStateStorePlatformKeys, |
| 219 platform_keys.PassAs<base::Value>()); |
| 220 callback.Run(true); |
| 221 } |
| 222 |
| 223 // static |
| 224 void PlatformKeysService::GotPlatformKeysOfExtension( |
| 225 const std::string& extension_id, |
| 226 base::WeakPtr<PlatformKeysService> service, |
| 227 const GetPlatformKeysCallback& callback, |
| 228 scoped_ptr<base::Value> value) { |
| 229 if (!value) |
| 230 value.reset(new base::ListValue); |
| 231 |
| 232 base::ListValue* keys = NULL; |
| 233 if (!value->GetAsList(&keys)) { |
| 234 LOG(ERROR) << "Found a value of wrong type."; |
| 235 value.reset(); |
| 236 } |
| 237 ignore_result(value.release()); |
| 238 callback.Run(service, make_scoped_ptr(keys)); |
| 239 } |
| 240 |
| 241 } // namespace chromeos |
OLD | NEW |