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 platform_keys::HashAlgorithm hash_algorithm, 53 const std::string& data, 54 const PlatformKeysService::SignCallback& callback, 55 content::BrowserContext* browser_context, 56 bool key_is_valid) { 57 if (!key_is_valid) { 58 callback.Run(std::string() /* no signature */, 59 kErrorKeyNotAllowedForSigning); 60 return; 61 } 62 platform_keys::subtle::Sign(token_id, 63 public_key_spki_der, 64 hash_algorithm, 65 data, 66 callback, 67 browser_context); 68 } 69 70 } // namespace 71 72 PlatformKeysService::PlatformKeysService( 73 content::BrowserContext* browser_context, 74 extensions::StateStore* state_store) 75 : browser_context_(browser_context), 76 state_store_(state_store), 77 weak_factory_(this) { 78 DCHECK(state_store); 79 } 80 81 PlatformKeysService::~PlatformKeysService() { 82 } 83 84 void PlatformKeysService::GenerateRSAKey(const std::string& token_id, 85 unsigned int modulus_length, 86 const std::string& extension_id, 87 const GenerateKeyCallback& callback) { 88 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 89 90 platform_keys::subtle::GenerateRSAKey( 91 token_id, 92 modulus_length, 93 base::Bind(&PlatformKeysService::GenerateRSAKeyCallback, 94 weak_factory_.GetWeakPtr(), 95 extension_id, 96 callback), 97 browser_context_); 98 } 99 100 void PlatformKeysService::Sign(const std::string& token_id, 101 const std::string& public_key_spki_der, 102 platform_keys::HashAlgorithm hash_algorithm, 103 const std::string& data, 104 const std::string& extension_id, 105 const SignCallback& callback) { 106 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 107 ReadValidityAndInvalidateKey(extension_id, 108 public_key_spki_der, 109 base::Bind(&CheckValidityAndSign, 110 token_id, 111 public_key_spki_der, 112 hash_algorithm, 113 data, 114 callback, 115 browser_context_)); 116 } 117 118 void PlatformKeysService::RegisterPublicKey( 119 const std::string& extension_id, 120 const std::string& public_key_spki_der, 121 const base::Callback<void(bool)>& callback) { 122 GetPlatformKeysOfExtension( 123 extension_id, 124 base::Bind(&PlatformKeysService::RegisterPublicKeyGotPlatformKeys, 125 weak_factory_.GetWeakPtr(), 126 extension_id, 127 public_key_spki_der, 128 callback)); 129 } 130 131 void PlatformKeysService::ReadValidityAndInvalidateKey( 132 const std::string& extension_id, 133 const std::string& public_key_spki_der, 134 const base::Callback<void(bool)>& callback) { 135 GetPlatformKeysOfExtension(extension_id, 136 base::Bind(&PlatformKeysService::InvalidateKey, 137 weak_factory_.GetWeakPtr(), 138 extension_id, 139 public_key_spki_der, 140 callback)); 141 } 142 143 void PlatformKeysService::GetPlatformKeysOfExtension( 144 const std::string& extension_id, 145 const GetPlatformKeysCallback& callback) { 146 state_store_->GetExtensionValue( 147 extension_id, 148 kStateStorePlatformKeys, 149 base::Bind(&PlatformKeysService::GotPlatformKeysOfExtension, 150 weak_factory_.GetWeakPtr(), 151 extension_id, 152 callback)); 153 } 154 155 void PlatformKeysService::GenerateRSAKeyCallback( 156 const std::string& extension_id, 157 const GenerateKeyCallback& callback, 158 const std::string& public_key_spki_der, 159 const std::string& error_message) { 160 if (!error_message.empty()) { 161 callback.Run(std::string() /* no public key */, error_message); 162 return; 163 } 164 base::Callback<void(bool)> wrapped_callback( 165 base::Bind(&WrapGenerateKeyCallback, callback, public_key_spki_der)); 166 RegisterPublicKey(extension_id, public_key_spki_der, wrapped_callback); 167 } 168 169 void PlatformKeysService::RegisterPublicKeyGotPlatformKeys( 170 const std::string& extension_id, 171 const std::string& public_key_spki_der, 172 const base::Callback<void(bool)>& callback, 173 scoped_ptr<base::ListValue> platform_keys) { 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 state_store_->SetExtensionValue(extension_id, 189 kStateStorePlatformKeys, 190 platform_keys.PassAs<base::Value>()); 191 callback.Run(true); 192 } 193 194 void PlatformKeysService::InvalidateKey( 195 const std::string& extension_id, 196 const std::string& public_key_spki_der, 197 const base::Callback<void(bool)>& callback, 198 scoped_ptr<base::ListValue> platform_keys) { 199 scoped_ptr<base::StringValue> key_value( 200 GetPublicKeyValue(public_key_spki_der)); 201 202 size_t index = 0; 203 if (!platform_keys->Remove(*key_value, &index)) { 204 // The key is not found, so it's not valid to use it for signing. 205 callback.Run(false); 206 return; 207 } 208 209 state_store_->SetExtensionValue(extension_id, 210 kStateStorePlatformKeys, 211 platform_keys.PassAs<base::Value>()); 212 callback.Run(true); 213 } 214 215 void PlatformKeysService::GotPlatformKeysOfExtension( 216 const std::string& extension_id, 217 const GetPlatformKeysCallback& callback, 218 scoped_ptr<base::Value> value) { 219 if (!value) 220 value.reset(new base::ListValue); 221 222 base::ListValue* keys = NULL; 223 if (!value->GetAsList(&keys)) { 224 LOG(ERROR) << "Found a value of wrong type."; 225 value.reset(); 226 } 227 ignore_result(value.release()); 228 callback.Run(make_scoped_ptr(keys)); 229 } 230 231 } // namespace chromeos 232