- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / api / enterprise_platform_keys_private / enterprise_platform_keys_private_api_unittest.cc
1 // Copyright (c) 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/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.h"
6
7 #include <string>
8
9 #include "base/prefs/pref_service.h"
10 #include "base/strings/stringprintf.h"
11 #include "base/values.h"
12 #include "chrome/browser/chromeos/policy/stub_enterprise_install_attributes.h"
13 #include "chrome/browser/chromeos/settings/stub_cros_settings_provider.h"
14 #include "chrome/browser/extensions/extension_function_test_utils.h"
15 #include "chrome/browser/policy/cloud/cloud_policy_constants.h"
16 #include "chrome/common/pref_names.h"
17 #include "chrome/test/base/browser_with_test_window_test.h"
18 #include "chromeos/attestation/attestation_constants.h"
19 #include "chromeos/attestation/mock_attestation_flow.h"
20 #include "chromeos/cryptohome/async_method_caller.h"
21 #include "chromeos/cryptohome/mock_async_method_caller.h"
22 #include "chromeos/dbus/dbus_method_call_status.h"
23 #include "chromeos/dbus/mock_cryptohome_client.h"
24 #include "chromeos/settings/cros_settings_provider.h"
25 #include "testing/gmock/include/gmock/gmock.h"
26 #include "testing/gtest/include/gtest/gtest.h"
27 #include "third_party/cros_system_api/dbus/service_constants.h"
28
29 using testing::_;
30 using testing::Invoke;
31 using testing::NiceMock;
32 using testing::Return;
33 using testing::WithArgs;
34
35 namespace utils = extension_function_test_utils;
36
37 namespace extensions {
38 namespace {
39
40 // Certificate errors as reported to the calling extension.
41 const int kDBusError = 1;
42 const int kUserRejected = 2;
43 const int kGetCertificateFailed = 3;
44 const int kResetRequired = 4;
45
46 // A simple functor to invoke a callback with predefined arguments.
47 class FakeBoolDBusMethod {
48  public:
49   FakeBoolDBusMethod(chromeos::DBusMethodCallStatus status, bool value)
50       : status_(status),
51         value_(value) {}
52
53   void operator() (const chromeos::BoolDBusMethodCallback& callback) {
54     callback.Run(status_, value_);
55   }
56
57  private:
58   chromeos::DBusMethodCallStatus status_;
59   bool value_;
60 };
61
62 void RegisterKeyCallbackTrue(
63     chromeos::attestation::AttestationKeyType key_type,
64     const std::string& user_id,
65     const std::string& key_name,
66     const cryptohome::AsyncMethodCaller::Callback& callback) {
67   callback.Run(true, cryptohome::MOUNT_ERROR_NONE);
68 }
69
70 void RegisterKeyCallbackFalse(
71     chromeos::attestation::AttestationKeyType key_type,
72     const std::string& user_id,
73     const std::string& key_name,
74     const cryptohome::AsyncMethodCaller::Callback& callback) {
75   callback.Run(false, cryptohome::MOUNT_ERROR_NONE);
76 }
77
78 void SignChallengeCallbackTrue(
79     chromeos::attestation::AttestationKeyType key_type,
80     const std::string& user_id,
81     const std::string& key_name,
82     const std::string& domain,
83     const std::string& device_id,
84     chromeos::attestation::AttestationChallengeOptions options,
85     const std::string& challenge,
86     const cryptohome::AsyncMethodCaller::DataCallback& callback) {
87   callback.Run(true, "response");
88 }
89
90 void SignChallengeCallbackFalse(
91     chromeos::attestation::AttestationKeyType key_type,
92     const std::string& user_id,
93     const std::string& key_name,
94     const std::string& domain,
95     const std::string& device_id,
96     chromeos::attestation::AttestationChallengeOptions options,
97     const std::string& challenge,
98     const cryptohome::AsyncMethodCaller::DataCallback& callback) {
99   callback.Run(false, "");
100 }
101
102 void GetCertificateCallbackTrue(
103     chromeos::attestation::AttestationCertificateProfile certificate_profile,
104     const std::string& user_id,
105     const std::string& request_origin,
106     bool force_new_key,
107     const chromeos::attestation::AttestationFlow::CertificateCallback&
108         callback) {
109   callback.Run(true, "certificate");
110 }
111
112 void GetCertificateCallbackFalse(
113     chromeos::attestation::AttestationCertificateProfile certificate_profile,
114     const std::string& user_id,
115     const std::string& request_origin,
116     bool force_new_key,
117     const chromeos::attestation::AttestationFlow::CertificateCallback&
118         callback) {
119   callback.Run(false, "");
120 }
121
122 class EPKPChallengeKeyTestBase : public BrowserWithTestWindowTest {
123  protected:
124   EPKPChallengeKeyTestBase()
125       : extension_(utils::CreateEmptyExtension("")) {
126     // Set up the default behavior of mocks.
127     ON_CALL(mock_cryptohome_client_, TpmAttestationDoesKeyExist(_, _, _, _))
128         .WillByDefault(WithArgs<3>(Invoke(FakeBoolDBusMethod(
129             chromeos::DBUS_METHOD_CALL_SUCCESS, false))));
130     ON_CALL(mock_cryptohome_client_, TpmAttestationIsPrepared(_))
131         .WillByDefault(Invoke(FakeBoolDBusMethod(
132             chromeos::DBUS_METHOD_CALL_SUCCESS, true)));
133     ON_CALL(mock_async_method_caller_, TpmAttestationRegisterKey(_, _, _, _))
134         .WillByDefault(Invoke(RegisterKeyCallbackTrue));
135     ON_CALL(mock_async_method_caller_,
136             TpmAttestationSignEnterpriseChallenge(_, _, _, _, _, _, _, _))
137         .WillByDefault(Invoke(SignChallengeCallbackTrue));
138     ON_CALL(mock_attestation_flow_, GetCertificate(_, _, _, _, _))
139         .WillByDefault(Invoke(GetCertificateCallbackTrue));
140
141     // Set the Enterprise install attributes.
142     stub_install_attributes_.SetDomain("google.com");
143     stub_install_attributes_.SetRegistrationUser("test@google.com");
144     stub_install_attributes_.SetDeviceId("device_id");
145     stub_install_attributes_.SetMode(policy::DEVICE_MODE_ENTERPRISE);
146
147     // Replace the default device setting provider with the stub.
148     device_settings_provider_ = chromeos::CrosSettings::Get()->GetProvider(
149         chromeos::kReportDeviceVersionInfo);
150     EXPECT_TRUE(device_settings_provider_ != NULL);
151     EXPECT_TRUE(chromeos::CrosSettings::Get()->
152                 RemoveSettingsProvider(device_settings_provider_));
153     chromeos::CrosSettings::Get()->
154         AddSettingsProvider(&stub_settings_provider_);
155
156     // Set the device settings.
157     stub_settings_provider_.Set(chromeos::kDeviceAttestationEnabled,
158                                 base::FundamentalValue(true));
159   }
160
161   virtual ~EPKPChallengeKeyTestBase() {
162     EXPECT_TRUE(chromeos::CrosSettings::Get()->
163                 RemoveSettingsProvider(&stub_settings_provider_));
164     chromeos::CrosSettings::Get()->
165         AddSettingsProvider(device_settings_provider_);
166   }
167
168   virtual void SetUp() OVERRIDE {
169     BrowserWithTestWindowTest::SetUp();
170
171     // Set the user preferences.
172     prefs_ = browser()->profile()->GetPrefs();
173     prefs_->SetString(prefs::kGoogleServicesUsername, "test@google.com");
174     base::ListValue whitelist;
175     whitelist.AppendString(extension_->id());
176     prefs_->Set(prefs::kAttestationExtensionWhitelist, whitelist);
177   }
178
179   NiceMock<chromeos::MockCryptohomeClient> mock_cryptohome_client_;
180   NiceMock<cryptohome::MockAsyncMethodCaller> mock_async_method_caller_;
181   NiceMock<chromeos::attestation::MockAttestationFlow> mock_attestation_flow_;
182   scoped_refptr<extensions::Extension> extension_;
183   policy::StubEnterpriseInstallAttributes stub_install_attributes_;
184   chromeos::CrosSettingsProvider* device_settings_provider_;
185   chromeos::StubCrosSettingsProvider stub_settings_provider_;
186   PrefService* prefs_;
187 };
188
189 class EPKPChallengeMachineKeyTest : public EPKPChallengeKeyTestBase {
190  protected:
191   static const char kArgs[];
192
193   EPKPChallengeMachineKeyTest()
194       : func_(new EPKPChallengeMachineKey(&mock_cryptohome_client_,
195                                           &mock_async_method_caller_,
196                                           &mock_attestation_flow_,
197                                           &stub_install_attributes_)) {
198     func_->set_extension(extension_.get());
199   }
200
201   // Returns an error string for the given code.
202   std::string GetCertificateError(int error_code) {
203     return base::StringPrintf(
204         EPKPChallengeMachineKey::kGetCertificateFailedError,
205         error_code);
206   }
207
208   scoped_refptr<EPKPChallengeMachineKey> func_;
209 };
210
211 // Base 64 encoding of 'challenge'.
212 const char EPKPChallengeMachineKeyTest::kArgs[] = "[\"Y2hhbGxlbmdl\"]";
213
214 TEST_F(EPKPChallengeMachineKeyTest, ChallengeBadBase64) {
215   EXPECT_EQ(EPKPChallengeKeyBase::kChallengeBadBase64Error,
216             utils::RunFunctionAndReturnError(
217                 func_.get(), "[\"****\"]", browser()));
218 }
219
220 TEST_F(EPKPChallengeMachineKeyTest, NonEnterpriseDevice) {
221   stub_install_attributes_.SetRegistrationUser("");
222
223   EXPECT_EQ(EPKPChallengeMachineKey::kNonEnterpriseDeviceError,
224             utils::RunFunctionAndReturnError(func_.get(), kArgs, browser()));
225 }
226
227 TEST_F(EPKPChallengeMachineKeyTest, ExtensionNotWhitelisted) {
228   base::ListValue empty_whitelist;
229   prefs_->Set(prefs::kAttestationExtensionWhitelist, empty_whitelist);
230
231   EXPECT_EQ(EPKPChallengeKeyBase::kExtensionNotWhitelistedError,
232             utils::RunFunctionAndReturnError(func_.get(), kArgs, browser()));
233 }
234
235 TEST_F(EPKPChallengeMachineKeyTest, UserNotManaged) {
236   prefs_->SetString(prefs::kGoogleServicesUsername, "test@chromium.org");
237
238   EXPECT_EQ(EPKPChallengeKeyBase::kUserNotManaged,
239             utils::RunFunctionAndReturnError(func_.get(), kArgs, browser()));
240 }
241
242 TEST_F(EPKPChallengeMachineKeyTest, DevicePolicyDisabled) {
243   stub_settings_provider_.Set(chromeos::kDeviceAttestationEnabled,
244                               base::FundamentalValue(false));
245
246   EXPECT_EQ(EPKPChallengeKeyBase::kDevicePolicyDisabledError,
247             utils::RunFunctionAndReturnError(func_.get(), kArgs, browser()));
248 }
249
250 TEST_F(EPKPChallengeMachineKeyTest, DoesKeyExistDbusFailed) {
251   EXPECT_CALL(mock_cryptohome_client_, TpmAttestationDoesKeyExist(_, _, _, _))
252       .WillRepeatedly(WithArgs<3>(Invoke(FakeBoolDBusMethod(
253           chromeos::DBUS_METHOD_CALL_FAILURE, false))));
254
255   EXPECT_EQ(GetCertificateError(kDBusError),
256             utils::RunFunctionAndReturnError(func_.get(), kArgs, browser()));
257 }
258
259 TEST_F(EPKPChallengeMachineKeyTest, GetCertificateFailed) {
260   EXPECT_CALL(mock_attestation_flow_, GetCertificate(_, _, _, _, _))
261       .WillRepeatedly(Invoke(GetCertificateCallbackFalse));
262
263   EXPECT_EQ(GetCertificateError(kGetCertificateFailed),
264             utils::RunFunctionAndReturnError(func_.get(), kArgs, browser()));
265 }
266
267 TEST_F(EPKPChallengeMachineKeyTest, SignChallengeFailed) {
268   EXPECT_CALL(mock_async_method_caller_,
269               TpmAttestationSignEnterpriseChallenge(_, _, _, _, _, _, _, _))
270       .WillRepeatedly(Invoke(SignChallengeCallbackFalse));
271
272   EXPECT_EQ(EPKPChallengeKeyBase::kSignChallengeFailedError,
273             utils::RunFunctionAndReturnError(func_.get(), kArgs, browser()));
274 }
275
276 TEST_F(EPKPChallengeMachineKeyTest, KeyExists) {
277   EXPECT_CALL(mock_cryptohome_client_, TpmAttestationDoesKeyExist(_, _, _, _))
278       .WillRepeatedly(WithArgs<3>(Invoke(FakeBoolDBusMethod(
279           chromeos::DBUS_METHOD_CALL_SUCCESS, true))));
280   // GetCertificate must not be called if the key exists.
281   EXPECT_CALL(mock_attestation_flow_, GetCertificate(_, _, _, _, _))
282       .Times(0);
283
284   EXPECT_TRUE(utils::RunFunction(func_.get(), kArgs, browser(), utils::NONE));
285 }
286
287 TEST_F(EPKPChallengeMachineKeyTest, Success) {
288   // GetCertificate must be called exactly once.
289   EXPECT_CALL(mock_attestation_flow_,
290               GetCertificate(
291                   chromeos::attestation::PROFILE_ENTERPRISE_MACHINE_CERTIFICATE,
292                   _, _, _, _))
293       .Times(1);
294   // SignEnterpriseChallenge must be called exactly once.
295   EXPECT_CALL(mock_async_method_caller_,
296               TpmAttestationSignEnterpriseChallenge(
297                   chromeos::attestation::KEY_DEVICE, "", "attest-ent-machine",
298                   "google.com", "device_id", _, "challenge", _))
299       .Times(1);
300
301   scoped_ptr<base::Value> value(utils::RunFunctionAndReturnSingleResult(
302       func_.get(), kArgs, browser(), utils::NONE));
303
304   std::string response;
305   value->GetAsString(&response);
306   EXPECT_EQ("cmVzcG9uc2U=" /* Base64 encoding of 'response' */, response);
307 }
308
309 TEST_F(EPKPChallengeMachineKeyTest, AttestationNotPrepared) {
310   EXPECT_CALL(mock_cryptohome_client_, TpmAttestationIsPrepared(_))
311       .WillRepeatedly(Invoke(FakeBoolDBusMethod(
312           chromeos::DBUS_METHOD_CALL_SUCCESS, false)));
313
314   EXPECT_EQ(GetCertificateError(kResetRequired),
315             utils::RunFunctionAndReturnError(func_.get(), kArgs, browser()));
316 }
317
318 TEST_F(EPKPChallengeMachineKeyTest, AttestationPreparedDbusFailed) {
319   EXPECT_CALL(mock_cryptohome_client_, TpmAttestationIsPrepared(_))
320       .WillRepeatedly(Invoke(FakeBoolDBusMethod(
321           chromeos::DBUS_METHOD_CALL_FAILURE, true)));
322
323   EXPECT_EQ(GetCertificateError(kDBusError),
324             utils::RunFunctionAndReturnError(func_.get(), kArgs, browser()));
325 }
326
327 class EPKPChallengeUserKeyTest : public EPKPChallengeKeyTestBase {
328  protected:
329   static const char kArgs[];
330
331   EPKPChallengeUserKeyTest() :
332       func_(new EPKPChallengeUserKey(&mock_cryptohome_client_,
333                                      &mock_async_method_caller_,
334                                      &mock_attestation_flow_,
335                                      &stub_install_attributes_)) {
336     func_->set_extension(extension_.get());
337   }
338
339   virtual void SetUp() OVERRIDE {
340     EPKPChallengeKeyTestBase::SetUp();
341
342     // Set the user preferences.
343     prefs_->SetBoolean(prefs::kAttestationEnabled, true);
344   }
345
346   // Returns an error string for the given code.
347   std::string GetCertificateError(int error_code) {
348     return base::StringPrintf(EPKPChallengeUserKey::kGetCertificateFailedError,
349                               error_code);
350   }
351
352   scoped_refptr<EPKPChallengeUserKey> func_;
353 };
354
355 // Base 64 encoding of 'challenge'
356 const char EPKPChallengeUserKeyTest::kArgs[] = "[\"Y2hhbGxlbmdl\", true]";
357
358 TEST_F(EPKPChallengeUserKeyTest, ChallengeBadBase64) {
359   EXPECT_EQ(EPKPChallengeKeyBase::kChallengeBadBase64Error,
360             utils::RunFunctionAndReturnError(
361                 func_.get(), "[\"****\", true]", browser()));
362 }
363
364 TEST_F(EPKPChallengeUserKeyTest, UserPolicyDisabled) {
365   prefs_->SetBoolean(prefs::kAttestationEnabled, false);
366
367   EXPECT_EQ(EPKPChallengeUserKey::kUserPolicyDisabledError,
368             utils::RunFunctionAndReturnError(func_.get(), kArgs, browser()));
369 }
370
371 TEST_F(EPKPChallengeUserKeyTest, ExtensionNotWhitelisted) {
372   base::ListValue empty_whitelist;
373   prefs_->Set(prefs::kAttestationExtensionWhitelist, empty_whitelist);
374
375   EXPECT_EQ(EPKPChallengeKeyBase::kExtensionNotWhitelistedError,
376             utils::RunFunctionAndReturnError(func_.get(), kArgs, browser()));
377 }
378
379 TEST_F(EPKPChallengeUserKeyTest, UserNotManaged) {
380   prefs_->SetString(prefs::kGoogleServicesUsername, "test@chromium.org");
381
382   EXPECT_EQ(EPKPChallengeKeyBase::kUserNotManaged,
383             utils::RunFunctionAndReturnError(func_.get(), kArgs, browser()));
384 }
385
386 TEST_F(EPKPChallengeUserKeyTest, DevicePolicyDisabled) {
387   stub_settings_provider_.Set(chromeos::kDeviceAttestationEnabled,
388                               base::FundamentalValue(false));
389
390   EXPECT_EQ(EPKPChallengeKeyBase::kDevicePolicyDisabledError,
391             utils::RunFunctionAndReturnError(func_.get(), kArgs, browser()));
392 }
393
394 TEST_F(EPKPChallengeUserKeyTest, DoesKeyExistDbusFailed) {
395   EXPECT_CALL(mock_cryptohome_client_, TpmAttestationDoesKeyExist(_, _, _, _))
396       .WillRepeatedly(WithArgs<3>(Invoke(FakeBoolDBusMethod(
397           chromeos::DBUS_METHOD_CALL_FAILURE, false))));
398
399   EXPECT_EQ(GetCertificateError(kDBusError),
400             utils::RunFunctionAndReturnError(func_.get(), kArgs, browser()));
401 }
402
403 TEST_F(EPKPChallengeUserKeyTest, GetCertificateFailed) {
404   EXPECT_CALL(mock_attestation_flow_, GetCertificate(_, _, _, _, _))
405       .WillRepeatedly(Invoke(GetCertificateCallbackFalse));
406
407   EXPECT_EQ(GetCertificateError(kGetCertificateFailed),
408             utils::RunFunctionAndReturnError(func_.get(), kArgs, browser()));
409 }
410
411 TEST_F(EPKPChallengeUserKeyTest, SignChallengeFailed) {
412   EXPECT_CALL(mock_async_method_caller_,
413               TpmAttestationSignEnterpriseChallenge(_, _, _, _, _, _, _, _))
414       .WillRepeatedly(Invoke(SignChallengeCallbackFalse));
415
416   EXPECT_EQ(EPKPChallengeKeyBase::kSignChallengeFailedError,
417             utils::RunFunctionAndReturnError(func_.get(), kArgs, browser()));
418 }
419
420 TEST_F(EPKPChallengeUserKeyTest, KeyRegistrationFailed) {
421   EXPECT_CALL(mock_async_method_caller_, TpmAttestationRegisterKey(_, _, _, _))
422       .WillRepeatedly(Invoke(RegisterKeyCallbackFalse));
423
424   EXPECT_EQ(EPKPChallengeUserKey::kKeyRegistrationFailedError,
425             utils::RunFunctionAndReturnError(func_.get(), kArgs, browser()));
426 }
427
428 TEST_F(EPKPChallengeUserKeyTest, KeyExists) {
429   EXPECT_CALL(mock_cryptohome_client_, TpmAttestationDoesKeyExist(_, _, _, _))
430       .WillRepeatedly(WithArgs<3>(Invoke(FakeBoolDBusMethod(
431           chromeos::DBUS_METHOD_CALL_SUCCESS, true))));
432   // GetCertificate must not be called if the key exists.
433   EXPECT_CALL(mock_attestation_flow_, GetCertificate(_, _, _, _, _))
434       .Times(0);
435
436   EXPECT_TRUE(utils::RunFunction(func_.get(), kArgs, browser(), utils::NONE));
437 }
438
439 TEST_F(EPKPChallengeUserKeyTest, KeyNotRegistered) {
440   EXPECT_CALL(mock_async_method_caller_, TpmAttestationRegisterKey(_, _, _, _))
441       .Times(0);
442
443   EXPECT_TRUE(utils::RunFunction(
444       func_.get(), "[\"Y2hhbGxlbmdl\", false]", browser(), utils::NONE));
445 }
446
447 TEST_F(EPKPChallengeUserKeyTest, PersonalDevice) {
448   stub_install_attributes_.SetRegistrationUser("");
449
450   // Currently personal devices are not supported.
451   EXPECT_EQ(GetCertificateError(kUserRejected),
452             utils::RunFunctionAndReturnError(func_.get(), kArgs, browser()));
453 }
454
455 TEST_F(EPKPChallengeUserKeyTest, Success) {
456   // GetCertificate must be called exactly once.
457   EXPECT_CALL(mock_attestation_flow_,
458               GetCertificate(
459                   chromeos::attestation::PROFILE_ENTERPRISE_USER_CERTIFICATE,
460                   _, _, _, _))
461       .Times(1);
462   // SignEnterpriseChallenge must be called exactly once.
463   EXPECT_CALL(mock_async_method_caller_,
464               TpmAttestationSignEnterpriseChallenge(
465                   chromeos::attestation::KEY_USER, "test@google.com",
466                   "attest-ent-user", "test@google.com", "device_id", _,
467                   "challenge", _))
468       .Times(1);
469   // RegisterKey must be called exactly once.
470   EXPECT_CALL(mock_async_method_caller_,
471               TpmAttestationRegisterKey(chromeos::attestation::KEY_USER,
472                                         "test@google.com",
473                                         "attest-ent-user", _))
474       .Times(1);
475
476   scoped_ptr<base::Value> value(utils::RunFunctionAndReturnSingleResult(
477       func_.get(), kArgs, browser(), utils::NONE));
478
479   std::string response;
480   value->GetAsString(&response);
481   EXPECT_EQ("cmVzcG9uc2U=" /* Base64 encoding of 'response' */, response);
482 }
483
484 TEST_F(EPKPChallengeUserKeyTest, AttestationNotPrepared) {
485   EXPECT_CALL(mock_cryptohome_client_, TpmAttestationIsPrepared(_))
486       .WillRepeatedly(Invoke(FakeBoolDBusMethod(
487           chromeos::DBUS_METHOD_CALL_SUCCESS, false)));
488
489   EXPECT_EQ(GetCertificateError(kResetRequired),
490             utils::RunFunctionAndReturnError(func_.get(), kArgs, browser()));
491 }
492
493 TEST_F(EPKPChallengeUserKeyTest, AttestationPreparedDbusFailed) {
494   EXPECT_CALL(mock_cryptohome_client_, TpmAttestationIsPrepared(_))
495       .WillRepeatedly(Invoke(FakeBoolDBusMethod(
496           chromeos::DBUS_METHOD_CALL_FAILURE, true)));
497
498   EXPECT_EQ(GetCertificateError(kDBusError),
499             utils::RunFunctionAndReturnError(func_.get(), kArgs, browser()));
500 }
501
502 }  // namespace
503 }  // namespace extensions