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 |