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.
5 #include "chrome/browser/chromeos/login/managed/supervised_user_authentication.h"
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"
20 // Byte size of hash salt.
21 const unsigned kSaltSize
= 32;
23 // Parameters of cryptographic hashing.
24 const unsigned kNumIterations
= 1234;
25 const unsigned kKeySizeInBits
= 256;
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
),
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
,
42 kNumIterations
, kKeySizeInBits
));
43 std::string raw_result
, result
;
44 key
->GetRawKey(&raw_result
);
45 base::Base64Encode(raw_result
, &result
);
51 SupervisedUserAuthentication::SupervisedUserAuthentication(
52 SupervisedUserManager
* 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
;
63 SupervisedUserAuthentication::~SupervisedUserAuthentication() {}
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
)
72 if (user_schema
== SCHEMA_SALT_HASHED
) {
73 base::DictionaryValue holder
;
75 owner_
->GetPasswordInformation(user_id
, &holder
);
76 holder
.GetStringWithoutPathExpansion(kSalt
, &salt
);
77 DCHECK(!salt
.empty());
78 return BuildPasswordForHashWithSaltSchema(salt
, password
);
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
)
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
));
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
);
120 bool SupervisedUserAuthentication::PasswordNeedsMigration(
121 const std::string
& user_id
) {
122 return GetPasswordSchema(user_id
) < stable_schema_
;
125 SupervisedUserAuthentication::Schema
126 SupervisedUserAuthentication::GetPasswordSchema(
127 const std::string
& user_id
) {
128 base::DictionaryValue holder
;
130 owner_
->GetPasswordInformation(user_id
, &holder
);
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
);
138 return schema_version
;
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.
148 } // namespace chromeos