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.
5 #include "chromeos/cryptohome/homedir_methods.h"
8 #include "chromeos/dbus/cryptohome/key.pb.h"
9 #include "chromeos/dbus/cryptohome/rpc.pb.h"
10 #include "chromeos/dbus/cryptohome_client.h"
11 #include "chromeos/dbus/dbus_thread_manager.h"
13 using chromeos::DBusThreadManager
;
15 namespace cryptohome
{
19 HomedirMethods
* g_homedir_methods
= NULL
;
21 void FillKeyProtobuf(const KeyDefinition
& key_def
, Key
* key
) {
22 key
->set_secret(key_def
.key
);
23 KeyData
* data
= key
->mutable_data();
24 data
->set_label(key_def
.label
);
26 if (key_def
.revision
> 0)
27 data
->set_revision(key_def
.revision
);
29 if (key_def
.privileges
!= 0) {
30 KeyPrivileges
* privileges
= data
->mutable_privileges();
31 privileges
->set_mount(key_def
.privileges
& PRIV_MOUNT
);
32 privileges
->set_add(key_def
.privileges
& PRIV_ADD
);
33 privileges
->set_remove(key_def
.privileges
& PRIV_REMOVE
);
34 privileges
->set_update(key_def
.privileges
& PRIV_MIGRATE
);
35 privileges
->set_authorized_update(key_def
.privileges
&
36 PRIV_AUTHORIZED_UPDATE
);
39 if (key_def
.encryption_key
.empty() && key_def
.signature_key
.empty())
42 KeyAuthorizationData
* auth_data
= data
->add_authorization_data();
43 auth_data
->set_type(KeyAuthorizationData::KEY_AUTHORIZATION_TYPE_HMACSHA256
);
44 if (!key_def
.encryption_key
.empty()) {
45 KeyAuthorizationSecret
* secret
= auth_data
->add_secrets();
46 secret
->mutable_usage()->set_encrypt(true);
47 secret
->set_symmetric_key(key_def
.encryption_key
);
49 if (!key_def
.signature_key
.empty()) {
50 KeyAuthorizationSecret
* secret
= auth_data
->add_secrets();
51 secret
->mutable_usage()->set_sign(true);
52 secret
->set_symmetric_key(key_def
.signature_key
);
56 // Fill identification protobuffer.
57 void FillIdentificationProtobuf(const Identification
& id
,
58 cryptohome::AccountIdentifier
* id_proto
) {
59 id_proto
->set_email(id
.user_id
);
62 // Fill authorization protobuffer.
63 void FillAuthorizationProtobuf(const Authorization
& auth
,
64 cryptohome::AuthorizationRequest
* auth_proto
) {
65 Key
* key
= auth_proto
->mutable_key();
66 if (!auth
.label
.empty()) {
67 key
->mutable_data()->set_label(auth
.label
);
69 key
->set_secret(auth
.key
);
72 MountError
MapError(CryptohomeErrorCode code
) {
74 case CRYPTOHOME_ERROR_NOT_SET
:
75 return MOUNT_ERROR_NONE
;
76 case CRYPTOHOME_ERROR_ACCOUNT_NOT_FOUND
:
77 return MOUNT_ERROR_USER_DOES_NOT_EXIST
;
78 case CRYPTOHOME_ERROR_NOT_IMPLEMENTED
:
79 case CRYPTOHOME_ERROR_MOUNT_FATAL
:
80 case CRYPTOHOME_ERROR_KEY_QUOTA_EXCEEDED
:
81 case CRYPTOHOME_ERROR_BACKING_STORE_FAILURE
:
82 return MOUNT_ERROR_FATAL
;
83 case CRYPTOHOME_ERROR_AUTHORIZATION_KEY_NOT_FOUND
:
84 case CRYPTOHOME_ERROR_KEY_NOT_FOUND
:
85 case CRYPTOHOME_ERROR_AUTHORIZATION_KEY_FAILED
:
86 return MOUNT_ERROR_KEY_FAILURE
;
87 case CRYPTOHOME_ERROR_TPM_COMM_ERROR
:
88 return MOUNT_ERROR_TPM_COMM_ERROR
;
89 case CRYPTOHOME_ERROR_TPM_DEFEND_LOCK
:
90 return MOUNT_ERROR_TPM_DEFEND_LOCK
;
91 case CRYPTOHOME_ERROR_MOUNT_MOUNT_POINT_BUSY
:
92 return MOUNT_ERROR_MOUNT_POINT_BUSY
;
93 case CRYPTOHOME_ERROR_TPM_NEEDS_REBOOT
:
94 return MOUNT_ERROR_TPM_NEEDS_REBOOT
;
95 case CRYPTOHOME_ERROR_AUTHORIZATION_KEY_DENIED
:
96 case CRYPTOHOME_ERROR_KEY_LABEL_EXISTS
:
97 case CRYPTOHOME_ERROR_UPDATE_SIGNATURE_INVALID
:
98 return MOUNT_ERROR_KEY_FAILURE
;
101 return MOUNT_ERROR_FATAL
;
105 // The implementation of HomedirMethods
106 class HomedirMethodsImpl
: public HomedirMethods
{
108 HomedirMethodsImpl() : weak_ptr_factory_(this) {}
110 virtual ~HomedirMethodsImpl() {}
112 virtual void CheckKeyEx(const Identification
& id
,
113 const Authorization
& auth
,
114 const Callback
& callback
) OVERRIDE
{
115 cryptohome::AccountIdentifier id_proto
;
116 cryptohome::AuthorizationRequest auth_proto
;
117 cryptohome::CheckKeyRequest request
;
119 FillIdentificationProtobuf(id
, &id_proto
);
120 FillAuthorizationProtobuf(auth
, &auth_proto
);
122 DBusThreadManager::Get()->GetCryptohomeClient()->CheckKeyEx(
126 base::Bind(&HomedirMethodsImpl::OnBaseReplyCallback
,
127 weak_ptr_factory_
.GetWeakPtr(),
131 virtual void MountEx(const Identification
& id
,
132 const Authorization
& auth
,
133 const MountParameters
& request
,
134 const MountCallback
& callback
) OVERRIDE
{
135 cryptohome::AccountIdentifier id_proto
;
136 cryptohome::AuthorizationRequest auth_proto
;
137 cryptohome::MountRequest request_proto
;
139 FillIdentificationProtobuf(id
, &id_proto
);
140 FillAuthorizationProtobuf(auth
, &auth_proto
);
142 if (request
.ephemeral
)
143 request_proto
.set_require_ephemeral(true);
145 if (!request
.create_keys
.empty()) {
146 CreateRequest
* create
= request_proto
.mutable_create();
147 for (size_t i
= 0; i
< request
.create_keys
.size(); ++i
)
148 FillKeyProtobuf(request
.create_keys
[i
], create
->add_keys());
151 DBusThreadManager::Get()->GetCryptohomeClient()->MountEx(
155 base::Bind(&HomedirMethodsImpl::OnMountExCallback
,
156 weak_ptr_factory_
.GetWeakPtr(),
160 virtual void AddKeyEx(const Identification
& id
,
161 const Authorization
& auth
,
162 const KeyDefinition
& new_key
,
163 bool clobber_if_exists
,
164 const Callback
& callback
) OVERRIDE
{
165 cryptohome::AccountIdentifier id_proto
;
166 cryptohome::AuthorizationRequest auth_proto
;
167 cryptohome::AddKeyRequest request
;
169 FillIdentificationProtobuf(id
, &id_proto
);
170 FillAuthorizationProtobuf(auth
, &auth_proto
);
171 FillKeyProtobuf(new_key
, request
.mutable_key());
172 request
.set_clobber_if_exists(clobber_if_exists
);
174 DBusThreadManager::Get()->GetCryptohomeClient()->AddKeyEx(
178 base::Bind(&HomedirMethodsImpl::OnBaseReplyCallback
,
179 weak_ptr_factory_
.GetWeakPtr(),
183 virtual void RemoveKeyEx(const Identification
& id
,
184 const Authorization
& auth
,
185 const std::string
& label
,
186 const Callback
& callback
) OVERRIDE
{
187 cryptohome::AccountIdentifier id_proto
;
188 cryptohome::AuthorizationRequest auth_proto
;
189 cryptohome::RemoveKeyRequest request
;
191 FillIdentificationProtobuf(id
, &id_proto
);
192 FillAuthorizationProtobuf(auth
, &auth_proto
);
193 request
.mutable_key()->mutable_data()->set_label(label
);
195 DBusThreadManager::Get()->GetCryptohomeClient()->RemoveKeyEx(
199 base::Bind(&HomedirMethodsImpl::OnBaseReplyCallback
,
200 weak_ptr_factory_
.GetWeakPtr(),
204 virtual void UpdateKeyEx(const Identification
& id
,
205 const Authorization
& auth
,
206 const KeyDefinition
& new_key
,
207 const std::string
& signature
,
208 const Callback
& callback
) OVERRIDE
{
209 cryptohome::AccountIdentifier id_proto
;
210 cryptohome::AuthorizationRequest auth_proto
;
211 cryptohome::UpdateKeyRequest pb_update_key
;
213 FillIdentificationProtobuf(id
, &id_proto
);
214 FillAuthorizationProtobuf(auth
, &auth_proto
);
215 FillKeyProtobuf(new_key
, pb_update_key
.mutable_changes());
216 pb_update_key
.set_authorization_signature(signature
);
218 DBusThreadManager::Get()->GetCryptohomeClient()->UpdateKeyEx(
222 base::Bind(&HomedirMethodsImpl::OnBaseReplyCallback
,
223 weak_ptr_factory_
.GetWeakPtr(),
228 void OnMountExCallback(const MountCallback
& callback
,
229 chromeos::DBusMethodCallStatus call_status
,
231 const BaseReply
& reply
) {
232 if (call_status
!= chromeos::DBUS_METHOD_CALL_SUCCESS
) {
233 callback
.Run(false, MOUNT_ERROR_FATAL
, std::string());
236 if (reply
.has_error()) {
237 if (reply
.error() != CRYPTOHOME_ERROR_NOT_SET
) {
238 callback
.Run(false, MapError(reply
.error()), std::string());
242 if (!reply
.HasExtension(MountReply::reply
)) {
243 callback
.Run(false, MOUNT_ERROR_FATAL
, std::string());
247 std::string mount_hash
;
248 mount_hash
= reply
.GetExtension(MountReply::reply
).sanitized_username();
249 callback
.Run(true, MOUNT_ERROR_NONE
, mount_hash
);
252 void OnBaseReplyCallback(const Callback
& callback
,
253 chromeos::DBusMethodCallStatus call_status
,
255 const BaseReply
& reply
) {
256 if (call_status
!= chromeos::DBUS_METHOD_CALL_SUCCESS
) {
257 callback
.Run(false, MOUNT_ERROR_FATAL
);
260 if (reply
.has_error()) {
261 if (reply
.error() != CRYPTOHOME_ERROR_NOT_SET
) {
262 callback
.Run(false, MapError(reply
.error()));
266 callback
.Run(true, MOUNT_ERROR_NONE
);
269 base::WeakPtrFactory
<HomedirMethodsImpl
> weak_ptr_factory_
;
271 DISALLOW_COPY_AND_ASSIGN(HomedirMethodsImpl
);
277 void HomedirMethods::Initialize() {
278 if (g_homedir_methods
) {
279 LOG(WARNING
) << "HomedirMethods was already initialized";
282 g_homedir_methods
= new HomedirMethodsImpl();
283 VLOG(1) << "HomedirMethods initialized";
287 void HomedirMethods::InitializeForTesting(HomedirMethods
* homedir_methods
) {
288 if (g_homedir_methods
) {
289 LOG(WARNING
) << "HomedirMethods was already initialized";
292 g_homedir_methods
= homedir_methods
;
293 VLOG(1) << "HomedirMethods initialized";
297 void HomedirMethods::Shutdown() {
298 if (!g_homedir_methods
) {
299 LOG(WARNING
) << "AsyncMethodCaller::Shutdown() called with NULL manager";
302 delete g_homedir_methods
;
303 g_homedir_methods
= NULL
;
304 VLOG(1) << "HomedirMethods Shutdown completed";
308 HomedirMethods
* HomedirMethods::GetInstance() { return g_homedir_methods
; }
310 } // namespace cryptohome