| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/chromeos/login/managed/supervised_user_authentication.h
" | 5 #include "chrome/browser/chromeos/login/managed/supervised_user_authentication.h
" |
| 6 | 6 |
| 7 #include "base/base64.h" | 7 #include "base/base64.h" |
| 8 #include "base/json/json_file_value_serializer.h" | 8 #include "base/json/json_file_value_serializer.h" |
| 9 #include "base/macros.h" | 9 #include "base/macros.h" |
| 10 #include "base/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
| 11 #include "base/strings/string_number_conversions.h" | 11 #include "base/strings/string_number_conversions.h" |
| 12 #include "base/strings/string_util.h" | 12 #include "base/strings/string_util.h" |
| 13 #include "base/threading/sequenced_worker_pool.h" | 13 #include "base/threading/sequenced_worker_pool.h" |
| 14 #include "chrome/browser/chromeos/login/auth/key.h" |
| 14 #include "chrome/browser/chromeos/login/managed/locally_managed_user_constants.h
" | 15 #include "chrome/browser/chromeos/login/managed/locally_managed_user_constants.h
" |
| 15 #include "chrome/browser/chromeos/login/users/supervised_user_manager.h" | 16 #include "chrome/browser/chromeos/login/users/supervised_user_manager.h" |
| 16 #include "chrome/browser/chromeos/login/users/user.h" | 17 #include "chrome/browser/chromeos/login/users/user.h" |
| 17 #include "chrome/browser/chromeos/login/users/user_manager.h" | 18 #include "chrome/browser/chromeos/login/users/user_manager.h" |
| 18 #include "chrome/browser/chromeos/profiles/profile_helper.h" | 19 #include "chrome/browser/chromeos/profiles/profile_helper.h" |
| 19 #include "chromeos/cryptohome/signed_secret.pb.h" | 20 #include "chromeos/cryptohome/signed_secret.pb.h" |
| 20 #include "content/public/browser/browser_thread.h" | 21 #include "content/public/browser/browser_thread.h" |
| 21 #include "crypto/hmac.h" | 22 #include "crypto/hmac.h" |
| 22 #include "crypto/random.h" | 23 #include "crypto/random.h" |
| 23 #include "crypto/symmetric_key.h" | 24 #include "crypto/symmetric_key.h" |
| 24 | 25 |
| 25 namespace chromeos { | 26 namespace chromeos { |
| 26 | 27 |
| 27 namespace { | 28 namespace { |
| 28 | 29 |
| 29 // Byte size of hash salt. | 30 // Byte size of hash salt. |
| 30 const unsigned kSaltSize = 32; | 31 const unsigned kSaltSize = 32; |
| 31 | 32 |
| 32 // Parameters of cryptographic hashing for new user schema. | |
| 33 const unsigned kNumIterations = 1234; | |
| 34 const unsigned kKeySizeInBits = 256; | |
| 35 | |
| 36 // Size of key signature. | 33 // Size of key signature. |
| 37 const unsigned kHMACKeySizeInBits = 256; | 34 const unsigned kHMACKeySizeInBits = 256; |
| 38 const int kSignatureLength = 32; | 35 const int kSignatureLength = 32; |
| 39 | 36 |
| 40 // Size of master key (in bytes). | 37 // Size of master key (in bytes). |
| 41 const int kMasterKeySize = 32; | 38 const int kMasterKeySize = 32; |
| 42 | 39 |
| 43 std::string CreateSalt() { | 40 std::string CreateSalt() { |
| 44 char result[kSaltSize]; | 41 char result[kSaltSize]; |
| 45 crypto::RandBytes(&result, sizeof(result)); | 42 crypto::RandBytes(&result, sizeof(result)); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 97 stable_schema_(SCHEMA_SALT_HASHED) { | 94 stable_schema_(SCHEMA_SALT_HASHED) { |
| 98 } | 95 } |
| 99 | 96 |
| 100 SupervisedUserAuthentication::~SupervisedUserAuthentication() {} | 97 SupervisedUserAuthentication::~SupervisedUserAuthentication() {} |
| 101 | 98 |
| 102 SupervisedUserAuthentication::Schema | 99 SupervisedUserAuthentication::Schema |
| 103 SupervisedUserAuthentication::GetStableSchema() { | 100 SupervisedUserAuthentication::GetStableSchema() { |
| 104 return stable_schema_; | 101 return stable_schema_; |
| 105 } | 102 } |
| 106 | 103 |
| 107 std::string SupervisedUserAuthentication::TransformPassword( | 104 UserContext SupervisedUserAuthentication::TransformKey( |
| 108 const std::string& user_id, | |
| 109 const std::string& password) { | |
| 110 int user_schema = GetPasswordSchema(user_id); | |
| 111 if (user_schema == SCHEMA_PLAIN) | |
| 112 return password; | |
| 113 | |
| 114 if (user_schema == SCHEMA_SALT_HASHED) { | |
| 115 base::DictionaryValue holder; | |
| 116 std::string salt; | |
| 117 owner_->GetPasswordInformation(user_id, &holder); | |
| 118 holder.GetStringWithoutPathExpansion(kSalt, &salt); | |
| 119 DCHECK(!salt.empty()); | |
| 120 return BuildPasswordForHashWithSaltSchema(salt, password); | |
| 121 } | |
| 122 NOTREACHED(); | |
| 123 return password; | |
| 124 } | |
| 125 | |
| 126 UserContext SupervisedUserAuthentication::TransformPasswordInContext( | |
| 127 const UserContext& context) { | 105 const UserContext& context) { |
| 128 UserContext result = context; | 106 UserContext result = context; |
| 129 int user_schema = GetPasswordSchema(context.GetUserID()); | 107 int user_schema = GetPasswordSchema(context.GetUserID()); |
| 130 if (user_schema == SCHEMA_PLAIN) | 108 if (user_schema == SCHEMA_PLAIN) |
| 131 return result; | 109 return result; |
| 132 | 110 |
| 133 if (user_schema == SCHEMA_SALT_HASHED) { | 111 if (user_schema == SCHEMA_SALT_HASHED) { |
| 134 base::DictionaryValue holder; | 112 base::DictionaryValue holder; |
| 135 std::string salt; | 113 std::string salt; |
| 136 owner_->GetPasswordInformation(context.GetUserID(), &holder); | 114 owner_->GetPasswordInformation(context.GetUserID(), &holder); |
| 137 holder.GetStringWithoutPathExpansion(kSalt, &salt); | 115 holder.GetStringWithoutPathExpansion(kSalt, &salt); |
| 138 DCHECK(!salt.empty()); | 116 DCHECK(!salt.empty()); |
| 139 result.SetPassword( | 117 Key* const key = result.GetKey(); |
| 140 BuildPasswordForHashWithSaltSchema(salt, context.GetPassword())); | 118 key->Transform(Key::KEY_TYPE_SALTED_PBKDF2_AES256_1234, salt); |
| 141 result.SetDoesNeedPasswordHashing(false); | 119 key->SetLabel(kCryptohomeManagedUserKeyLabel); |
| 142 result.SetIsUsingOAuth(false); | 120 result.SetIsUsingOAuth(false); |
| 143 result.SetKeyLabel(kCryptohomeManagedUserKeyLabel); | |
| 144 return result; | 121 return result; |
| 145 } | 122 } |
| 146 NOTREACHED() << "Unknown password schema for " << context.GetUserID(); | 123 NOTREACHED() << "Unknown password schema for " << context.GetUserID(); |
| 147 return context; | 124 return context; |
| 148 } | 125 } |
| 149 | 126 |
| 150 bool SupervisedUserAuthentication::FillDataForNewUser( | 127 bool SupervisedUserAuthentication::FillDataForNewUser( |
| 151 const std::string& user_id, | 128 const std::string& user_id, |
| 152 const std::string& password, | 129 const std::string& password, |
| 153 base::DictionaryValue* password_data, | 130 base::DictionaryValue* password_data, |
| 154 base::DictionaryValue* extra_data) { | 131 base::DictionaryValue* extra_data) { |
| 155 Schema schema = stable_schema_; | 132 Schema schema = stable_schema_; |
| 156 if (schema == SCHEMA_PLAIN) | 133 if (schema == SCHEMA_PLAIN) |
| 157 return false; | 134 return false; |
| 158 | 135 |
| 159 if (schema == SCHEMA_SALT_HASHED) { | 136 if (schema == SCHEMA_SALT_HASHED) { |
| 160 password_data->SetIntegerWithoutPathExpansion(kSchemaVersion, schema); | 137 password_data->SetIntegerWithoutPathExpansion(kSchemaVersion, schema); |
| 161 std::string salt = CreateSalt(); | 138 std::string salt = CreateSalt(); |
| 162 password_data->SetStringWithoutPathExpansion(kSalt, salt); | 139 password_data->SetStringWithoutPathExpansion(kSalt, salt); |
| 163 int revision = kMinPasswordRevision; | 140 int revision = kMinPasswordRevision; |
| 164 password_data->SetIntegerWithoutPathExpansion(kPasswordRevision, revision); | 141 password_data->SetIntegerWithoutPathExpansion(kPasswordRevision, revision); |
| 165 std::string salted_password = | 142 Key key(password); |
| 166 BuildPasswordForHashWithSaltSchema(salt, password); | 143 key.Transform(Key::KEY_TYPE_SALTED_PBKDF2_AES256_1234, salt); |
| 167 std::string base64_signature_key = BuildRawHMACKey(); | 144 const std::string salted_password = key.GetSecret(); |
| 168 std::string base64_signature = | 145 const std::string base64_signature_key = BuildRawHMACKey(); |
| 146 const std::string base64_signature = |
| 169 BuildPasswordSignature(salted_password, revision, base64_signature_key); | 147 BuildPasswordSignature(salted_password, revision, base64_signature_key); |
| 170 password_data->SetStringWithoutPathExpansion(kEncryptedPassword, | 148 password_data->SetStringWithoutPathExpansion(kEncryptedPassword, |
| 171 salted_password); | 149 salted_password); |
| 172 password_data->SetStringWithoutPathExpansion(kPasswordSignature, | 150 password_data->SetStringWithoutPathExpansion(kPasswordSignature, |
| 173 base64_signature); | 151 base64_signature); |
| 174 | 152 |
| 175 extra_data->SetStringWithoutPathExpansion(kPasswordEncryptionKey, | 153 extra_data->SetStringWithoutPathExpansion(kPasswordEncryptionKey, |
| 176 BuildRawHMACKey()); | 154 BuildRawHMACKey()); |
| 177 extra_data->SetStringWithoutPathExpansion(kPasswordSignatureKey, | 155 extra_data->SetStringWithoutPathExpansion(kPasswordSignatureKey, |
| 178 base64_signature_key); | 156 base64_signature_key); |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 305 const User* user = UserManager::Get()->FindUser(user_id); | 283 const User* user = UserManager::Get()->FindUser(user_id); |
| 306 base::FilePath profile_path = | 284 base::FilePath profile_path = |
| 307 ProfileHelper::GetProfilePathByUserIdHash(user->username_hash()); | 285 ProfileHelper::GetProfilePathByUserIdHash(user->username_hash()); |
| 308 PostTaskAndReplyWithResult( | 286 PostTaskAndReplyWithResult( |
| 309 content::BrowserThread::GetBlockingPool(), | 287 content::BrowserThread::GetBlockingPool(), |
| 310 FROM_HERE, | 288 FROM_HERE, |
| 311 base::Bind(&LoadPasswordData, profile_path), | 289 base::Bind(&LoadPasswordData, profile_path), |
| 312 base::Bind(&OnPasswordDataLoaded, success_callback, failure_callback)); | 290 base::Bind(&OnPasswordDataLoaded, success_callback, failure_callback)); |
| 313 } | 291 } |
| 314 | 292 |
| 315 // static | |
| 316 std::string SupervisedUserAuthentication::BuildPasswordForHashWithSaltSchema( | |
| 317 const std::string& salt, | |
| 318 const std::string& plain_password) { | |
| 319 scoped_ptr<crypto::SymmetricKey> key( | |
| 320 crypto::SymmetricKey::DeriveKeyFromPassword(crypto::SymmetricKey::AES, | |
| 321 plain_password, | |
| 322 salt, | |
| 323 kNumIterations, | |
| 324 kKeySizeInBits)); | |
| 325 std::string raw_result, result; | |
| 326 key->GetRawKey(&raw_result); | |
| 327 base::Base64Encode(raw_result, &result); | |
| 328 return result; | |
| 329 } | |
| 330 | |
| 331 std::string SupervisedUserAuthentication::BuildPasswordSignature( | 293 std::string SupervisedUserAuthentication::BuildPasswordSignature( |
| 332 const std::string& password, | 294 const std::string& password, |
| 333 int revision, | 295 int revision, |
| 334 const std::string& base64_signature_key) { | 296 const std::string& base64_signature_key) { |
| 335 ac::chrome::managedaccounts::account::Secret secret; | 297 ac::chrome::managedaccounts::account::Secret secret; |
| 336 secret.set_revision(revision); | 298 secret.set_revision(revision); |
| 337 secret.set_secret(password); | 299 secret.set_secret(password); |
| 338 std::string buffer; | 300 std::string buffer; |
| 339 if (!secret.SerializeToString(&buffer)) | 301 if (!secret.SerializeToString(&buffer)) |
| 340 LOG(FATAL) << "Protobuf::SerializeToString failed"; | 302 LOG(FATAL) << "Protobuf::SerializeToString failed"; |
| 341 std::string signature_key; | 303 std::string signature_key; |
| 342 base::Base64Decode(base64_signature_key, &signature_key); | 304 base::Base64Decode(base64_signature_key, &signature_key); |
| 343 | 305 |
| 344 crypto::HMAC hmac(crypto::HMAC::SHA256); | 306 crypto::HMAC hmac(crypto::HMAC::SHA256); |
| 345 if (!hmac.Init(signature_key)) | 307 if (!hmac.Init(signature_key)) |
| 346 LOG(FATAL) << "HMAC::Init failed"; | 308 LOG(FATAL) << "HMAC::Init failed"; |
| 347 | 309 |
| 348 unsigned char out_bytes[kSignatureLength]; | 310 unsigned char out_bytes[kSignatureLength]; |
| 349 if (!hmac.Sign(buffer, out_bytes, sizeof(out_bytes))) | 311 if (!hmac.Sign(buffer, out_bytes, sizeof(out_bytes))) |
| 350 LOG(FATAL) << "HMAC::Sign failed"; | 312 LOG(FATAL) << "HMAC::Sign failed"; |
| 351 | 313 |
| 352 std::string raw_result(out_bytes, out_bytes + sizeof(out_bytes)); | 314 std::string raw_result(out_bytes, out_bytes + sizeof(out_bytes)); |
| 353 | 315 |
| 354 std::string result; | 316 std::string result; |
| 355 base::Base64Encode(raw_result, &result); | 317 base::Base64Encode(raw_result, &result); |
| 356 return result; | 318 return result; |
| 357 } | 319 } |
| 358 | 320 |
| 359 } // namespace chromeos | 321 } // namespace chromeos |
| OLD | NEW |