Upstream version 5.34.92.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / login / managed / supervised_user_authentication.cc
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
3 // found in the LICENSE file.
4
5 #include "chrome/browser/chromeos/login/managed/supervised_user_authentication.h"
6
7 #include "base/base64.h"
8 #include "base/command_line.h"
9 #include "base/strings/string_number_conversions.h"
10 #include "base/strings/string_util.h"
11 #include "chrome/browser/chromeos/login/supervised_user_manager.h"
12 #include "chromeos/chromeos_switches.h"
13 #include "crypto/random.h"
14 #include "crypto/symmetric_key.h"
15
16 namespace chromeos {
17
18 namespace {
19
20 // Byte size of hash salt.
21 const unsigned kSaltSize = 32;
22
23 // Parameters of cryptographic hashing.
24 const unsigned kNumIterations = 1234;
25 const unsigned kKeySizeInBits = 256;
26
27 std::string CreateSalt() {
28     char result[kSaltSize];
29     crypto::RandBytes(&result, sizeof(result));
30     return StringToLowerASCII(base::HexEncode(
31         reinterpret_cast<const void*>(result),
32         sizeof(result)));
33 }
34
35 std::string BuildPasswordForHashWithSaltSchema(
36   const std::string& salt,
37   const std::string& plain_password) {
38   scoped_ptr<crypto::SymmetricKey> key(
39       crypto::SymmetricKey::DeriveKeyFromPassword(
40           crypto::SymmetricKey::AES,
41           plain_password, salt,
42           kNumIterations, kKeySizeInBits));
43   std::string raw_result, result;
44   key->GetRawKey(&raw_result);
45   base::Base64Encode(raw_result, &result);
46   return result;
47 }
48
49 }  // namespace
50
51 SupervisedUserAuthentication::SupervisedUserAuthentication(
52     SupervisedUserManager* owner)
53       : owner_(owner),
54         migration_enabled_(false),
55         stable_schema_(SCHEMA_PLAIN) {
56   CommandLine* command_line = CommandLine::ForCurrentProcess();
57   if (command_line->HasSwitch(switches::kEnableSupervisedPasswordSync)) {
58     migration_enabled_ = true;
59     stable_schema_ = SCHEMA_SALT_HASHED;
60   }
61 }
62
63 SupervisedUserAuthentication::~SupervisedUserAuthentication() {}
64
65 std::string SupervisedUserAuthentication::TransformPassword(
66     const std::string& user_id,
67     const std::string& password) {
68   int user_schema = GetPasswordSchema(user_id);
69   if (user_schema == SCHEMA_PLAIN)
70     return password;
71
72   if (user_schema == SCHEMA_SALT_HASHED) {
73     base::DictionaryValue holder;
74     std::string salt;
75     owner_->GetPasswordInformation(user_id, &holder);
76     holder.GetStringWithoutPathExpansion(kSalt, &salt);
77     DCHECK(!salt.empty());
78     return BuildPasswordForHashWithSaltSchema(salt, password);
79   }
80   NOTREACHED();
81   return password;
82 }
83
84 bool SupervisedUserAuthentication::FillDataForNewUser(
85     const std::string& user_id,
86     const std::string& password,
87     base::DictionaryValue* password_data) {
88   Schema schema = stable_schema_;
89   if (schema == SCHEMA_PLAIN)
90     return false;
91   if (schema == SCHEMA_SALT_HASHED) {
92     password_data->SetIntegerWithoutPathExpansion(kSchemaVersion, schema);
93     std::string salt = CreateSalt();
94     password_data->SetStringWithoutPathExpansion(kSalt, salt);
95     password_data->SetIntegerWithoutPathExpansion(kPasswordRevision,
96         kMinPasswordRevision);
97     password_data->SetStringWithoutPathExpansion(kEncryptedPassword,
98         BuildPasswordForHashWithSaltSchema(salt, password));
99     return true;
100   }
101   NOTREACHED();
102   return false;
103 }
104
105 void SupervisedUserAuthentication::StorePasswordData(
106     const std::string& user_id,
107     const base::DictionaryValue& password_data) {
108   base::DictionaryValue holder;
109   owner_->GetPasswordInformation(user_id, &holder);
110   const base::Value* value;
111   if (password_data.GetWithoutPathExpansion(kSchemaVersion, &value))
112       holder.SetWithoutPathExpansion(kSchemaVersion, value->DeepCopy());
113   if (password_data.GetWithoutPathExpansion(kSalt, &value))
114       holder.SetWithoutPathExpansion(kSalt, value->DeepCopy());
115   if (password_data.GetWithoutPathExpansion(kPasswordRevision, &value))
116       holder.SetWithoutPathExpansion(kPasswordRevision, value->DeepCopy());
117   owner_->SetPasswordInformation(user_id, &holder);
118 }
119
120 bool SupervisedUserAuthentication::PasswordNeedsMigration(
121     const std::string& user_id) {
122   return GetPasswordSchema(user_id) < stable_schema_;
123 }
124
125 SupervisedUserAuthentication::Schema
126 SupervisedUserAuthentication::GetPasswordSchema(
127   const std::string& user_id) {
128   base::DictionaryValue holder;
129
130   owner_->GetPasswordInformation(user_id, &holder);
131   // Default version.
132   int schema_version_index;
133   Schema schema_version = SCHEMA_PLAIN;
134   if (holder.GetIntegerWithoutPathExpansion(kSchemaVersion,
135                                             &schema_version_index)) {
136     schema_version = static_cast<Schema>(schema_version_index);
137   }
138   return schema_version;
139 }
140
141 void SupervisedUserAuthentication::SchedulePasswordMigration(
142     const std::string& supervised_user_id,
143     const std::string& user_password,
144     SupervisedUserLoginFlow* user_flow) {
145   // TODO(antrim): Add actual migration code once cryptohome has required API.
146 }
147
148 }  // namespace chromeos