• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2012 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 "base/bind.h"
6 #include "base/memory/scoped_ptr.h"
7 #include "base/run_loop.h"
8 #include "chromeos/attestation/mock_attestation_flow.h"
9 #include "chromeos/cryptohome/mock_async_method_caller.h"
10 #include "chromeos/dbus/mock_cryptohome_client.h"
11 #include "testing/gmock/include/gmock/gmock.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 
14 using testing::_;
15 using testing::Invoke;
16 using testing::Sequence;
17 using testing::StrictMock;
18 using testing::WithArgs;
19 
20 namespace chromeos {
21 namespace attestation {
22 
23 namespace {
24 
DBusCallbackFalse(const BoolDBusMethodCallback & callback)25 void DBusCallbackFalse(const BoolDBusMethodCallback& callback) {
26   base::MessageLoop::current()->PostTask(
27       FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, false));
28 }
29 
DBusCallbackTrue(const BoolDBusMethodCallback & callback)30 void DBusCallbackTrue(const BoolDBusMethodCallback& callback) {
31   base::MessageLoop::current()->PostTask(
32       FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true));
33 }
34 
DBusCallbackFail(const BoolDBusMethodCallback & callback)35 void DBusCallbackFail(const BoolDBusMethodCallback& callback) {
36   base::MessageLoop::current()->PostTask(
37       FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_FAILURE, false));
38 }
39 
AsyncCallbackFalse(cryptohome::AsyncMethodCaller::Callback callback)40 void AsyncCallbackFalse(cryptohome::AsyncMethodCaller::Callback callback) {
41   callback.Run(false, cryptohome::MOUNT_ERROR_NONE);
42 }
43 
44 class FakeDBusData {
45  public:
FakeDBusData(const std::string & data)46   explicit FakeDBusData(const std::string& data) : data_(data) {}
47 
operator ()(const CryptohomeClient::DataMethodCallback & callback)48   void operator() (const CryptohomeClient::DataMethodCallback& callback) {
49     base::MessageLoop::current()->PostTask(
50         FROM_HERE,
51         base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true, data_));
52   }
53 
54  private:
55   std::string data_;
56 };
57 
58 }  // namespace
59 
60 class AttestationFlowTest : public testing::Test {
61  protected:
Run()62   void Run() {
63     base::RunLoop run_loop;
64     run_loop.RunUntilIdle();
65   }
66   base::MessageLoop message_loop_;
67 };
68 
TEST_F(AttestationFlowTest,GetCertificate)69 TEST_F(AttestationFlowTest, GetCertificate) {
70   // Verify the order of calls in a sequence.
71   Sequence flow_order;
72 
73   // Use DBusCallbackFalse so the full enrollment flow is triggered.
74   chromeos::MockCryptohomeClient client;
75   EXPECT_CALL(client, TpmAttestationIsEnrolled(_))
76       .InSequence(flow_order)
77       .WillRepeatedly(Invoke(DBusCallbackFalse));
78 
79   // Use StrictMock when we want to verify invocation frequency.
80   StrictMock<cryptohome::MockAsyncMethodCaller> async_caller;
81   async_caller.SetUp(true, cryptohome::MOUNT_ERROR_NONE);
82   EXPECT_CALL(async_caller, AsyncTpmAttestationCreateEnrollRequest(_))
83       .Times(1)
84       .InSequence(flow_order);
85 
86   scoped_ptr<MockServerProxy> proxy(new StrictMock<MockServerProxy>());
87   proxy->DeferToFake(true);
88   EXPECT_CALL(*proxy, SendEnrollRequest(
89       cryptohome::MockAsyncMethodCaller::kFakeAttestationEnrollRequest,
90       _)).Times(1)
91          .InSequence(flow_order);
92 
93   std::string fake_enroll_response =
94       cryptohome::MockAsyncMethodCaller::kFakeAttestationEnrollRequest;
95   fake_enroll_response += "_response";
96   EXPECT_CALL(async_caller, AsyncTpmAttestationEnroll(fake_enroll_response, _))
97       .Times(1)
98       .InSequence(flow_order);
99 
100   EXPECT_CALL(
101       async_caller,
102       AsyncTpmAttestationCreateCertRequest(PROFILE_ENTERPRISE_USER_CERTIFICATE,
103                                            "fake@test.com", "fake_origin", _))
104           .Times(1)
105           .InSequence(flow_order);
106 
107   EXPECT_CALL(*proxy, SendCertificateRequest(
108       cryptohome::MockAsyncMethodCaller::kFakeAttestationCertRequest,
109       _)).Times(1)
110          .InSequence(flow_order);
111 
112   std::string fake_cert_response =
113       cryptohome::MockAsyncMethodCaller::kFakeAttestationCertRequest;
114   fake_cert_response += "_response";
115   EXPECT_CALL(async_caller,
116               AsyncTpmAttestationFinishCertRequest(fake_cert_response,
117                                                    KEY_USER,
118                                                    "fake@test.com",
119                                                    kEnterpriseUserKey,
120                                                    _))
121       .Times(1)
122       .InSequence(flow_order);
123 
124   StrictMock<MockObserver> observer;
125   EXPECT_CALL(observer, MockCertificateCallback(
126       true,
127       cryptohome::MockAsyncMethodCaller::kFakeAttestationCert))
128       .Times(1)
129       .InSequence(flow_order);
130   AttestationFlow::CertificateCallback mock_callback = base::Bind(
131       &MockObserver::MockCertificateCallback,
132       base::Unretained(&observer));
133 
134   scoped_ptr<ServerProxy> proxy_interface(proxy.release());
135   AttestationFlow flow(&async_caller, &client, proxy_interface.Pass());
136   flow.GetCertificate(PROFILE_ENTERPRISE_USER_CERTIFICATE, "fake@test.com",
137                       "fake_origin", true, mock_callback);
138   Run();
139 }
140 
TEST_F(AttestationFlowTest,GetCertificate_NoEK)141 TEST_F(AttestationFlowTest, GetCertificate_NoEK) {
142   StrictMock<cryptohome::MockAsyncMethodCaller> async_caller;
143   async_caller.SetUp(false, cryptohome::MOUNT_ERROR_NONE);
144   EXPECT_CALL(async_caller, AsyncTpmAttestationCreateEnrollRequest(_))
145       .Times(1);
146 
147   chromeos::MockCryptohomeClient client;
148   EXPECT_CALL(client, TpmAttestationIsEnrolled(_))
149       .WillRepeatedly(Invoke(DBusCallbackFalse));
150 
151   // We're not expecting any server calls in this case; StrictMock will verify.
152   scoped_ptr<MockServerProxy> proxy(new StrictMock<MockServerProxy>());
153 
154   StrictMock<MockObserver> observer;
155   EXPECT_CALL(observer, MockCertificateCallback(false, ""))
156       .Times(1);
157   AttestationFlow::CertificateCallback mock_callback = base::Bind(
158       &MockObserver::MockCertificateCallback,
159       base::Unretained(&observer));
160 
161   scoped_ptr<ServerProxy> proxy_interface(proxy.release());
162   AttestationFlow flow(&async_caller, &client, proxy_interface.Pass());
163   flow.GetCertificate(PROFILE_ENTERPRISE_USER_CERTIFICATE, "", "", true,
164                       mock_callback);
165   Run();
166 }
167 
TEST_F(AttestationFlowTest,GetCertificate_EKRejected)168 TEST_F(AttestationFlowTest, GetCertificate_EKRejected) {
169   StrictMock<cryptohome::MockAsyncMethodCaller> async_caller;
170   async_caller.SetUp(true, cryptohome::MOUNT_ERROR_NONE);
171   EXPECT_CALL(async_caller, AsyncTpmAttestationCreateEnrollRequest(_))
172       .Times(1);
173 
174   chromeos::MockCryptohomeClient client;
175   EXPECT_CALL(client, TpmAttestationIsEnrolled(_))
176       .WillRepeatedly(Invoke(DBusCallbackFalse));
177 
178   scoped_ptr<MockServerProxy> proxy(new StrictMock<MockServerProxy>());
179   proxy->DeferToFake(false);
180   EXPECT_CALL(*proxy, SendEnrollRequest(
181       cryptohome::MockAsyncMethodCaller::kFakeAttestationEnrollRequest,
182       _)).Times(1);
183 
184   StrictMock<MockObserver> observer;
185   EXPECT_CALL(observer, MockCertificateCallback(false, ""))
186       .Times(1);
187   AttestationFlow::CertificateCallback mock_callback = base::Bind(
188       &MockObserver::MockCertificateCallback,
189       base::Unretained(&observer));
190 
191   scoped_ptr<ServerProxy> proxy_interface(proxy.release());
192   AttestationFlow flow(&async_caller, &client, proxy_interface.Pass());
193   flow.GetCertificate(PROFILE_ENTERPRISE_USER_CERTIFICATE, "", "", true,
194                       mock_callback);
195   Run();
196 }
197 
TEST_F(AttestationFlowTest,GetCertificate_FailEnroll)198 TEST_F(AttestationFlowTest, GetCertificate_FailEnroll) {
199   StrictMock<cryptohome::MockAsyncMethodCaller> async_caller;
200   async_caller.SetUp(true, cryptohome::MOUNT_ERROR_NONE);
201   EXPECT_CALL(async_caller, AsyncTpmAttestationCreateEnrollRequest(_))
202       .Times(1);
203   std::string fake_enroll_response =
204       cryptohome::MockAsyncMethodCaller::kFakeAttestationEnrollRequest;
205   fake_enroll_response += "_response";
206   EXPECT_CALL(async_caller, AsyncTpmAttestationEnroll(fake_enroll_response, _))
207       .WillOnce(WithArgs<1>(Invoke(AsyncCallbackFalse)));
208 
209   chromeos::MockCryptohomeClient client;
210   EXPECT_CALL(client, TpmAttestationIsEnrolled(_))
211       .WillRepeatedly(Invoke(DBusCallbackFalse));
212 
213   scoped_ptr<MockServerProxy> proxy(new StrictMock<MockServerProxy>());
214   proxy->DeferToFake(true);
215   EXPECT_CALL(*proxy, SendEnrollRequest(
216       cryptohome::MockAsyncMethodCaller::kFakeAttestationEnrollRequest,
217       _)).Times(1);
218 
219   StrictMock<MockObserver> observer;
220   EXPECT_CALL(observer, MockCertificateCallback(false, "")).Times(1);
221   AttestationFlow::CertificateCallback mock_callback = base::Bind(
222       &MockObserver::MockCertificateCallback,
223       base::Unretained(&observer));
224 
225   scoped_ptr<ServerProxy> proxy_interface(proxy.release());
226   AttestationFlow flow(&async_caller, &client, proxy_interface.Pass());
227   flow.GetCertificate(PROFILE_ENTERPRISE_USER_CERTIFICATE, "", "", true,
228                       mock_callback);
229   Run();
230 }
231 
TEST_F(AttestationFlowTest,GetMachineCertificateAlreadyEnrolled)232 TEST_F(AttestationFlowTest, GetMachineCertificateAlreadyEnrolled) {
233   StrictMock<cryptohome::MockAsyncMethodCaller> async_caller;
234   async_caller.SetUp(true, cryptohome::MOUNT_ERROR_NONE);
235   EXPECT_CALL(async_caller,
236               AsyncTpmAttestationCreateCertRequest(
237                   PROFILE_ENTERPRISE_MACHINE_CERTIFICATE, "", "", _))
238       .Times(1);
239   std::string fake_cert_response =
240       cryptohome::MockAsyncMethodCaller::kFakeAttestationCertRequest;
241   fake_cert_response += "_response";
242   EXPECT_CALL(async_caller,
243               AsyncTpmAttestationFinishCertRequest(fake_cert_response,
244                                                    KEY_DEVICE,
245                                                    "",
246                                                    kEnterpriseMachineKey,
247                                                    _))
248       .Times(1);
249 
250   chromeos::MockCryptohomeClient client;
251   EXPECT_CALL(client, TpmAttestationIsEnrolled(_))
252       .WillRepeatedly(Invoke(DBusCallbackTrue));
253 
254   scoped_ptr<MockServerProxy> proxy(new StrictMock<MockServerProxy>());
255   proxy->DeferToFake(true);
256   EXPECT_CALL(*proxy, SendCertificateRequest(
257       cryptohome::MockAsyncMethodCaller::kFakeAttestationCertRequest,
258       _)).Times(1);
259 
260   StrictMock<MockObserver> observer;
261   EXPECT_CALL(observer, MockCertificateCallback(
262       true,
263       cryptohome::MockAsyncMethodCaller::kFakeAttestationCert)).Times(1);
264   AttestationFlow::CertificateCallback mock_callback = base::Bind(
265       &MockObserver::MockCertificateCallback,
266       base::Unretained(&observer));
267 
268   scoped_ptr<ServerProxy> proxy_interface(proxy.release());
269   AttestationFlow flow(&async_caller, &client, proxy_interface.Pass());
270   flow.GetCertificate(PROFILE_ENTERPRISE_MACHINE_CERTIFICATE, "", "", true,
271                       mock_callback);
272   Run();
273 }
274 
TEST_F(AttestationFlowTest,GetCertificate_FailCreateCertRequest)275 TEST_F(AttestationFlowTest, GetCertificate_FailCreateCertRequest) {
276   StrictMock<cryptohome::MockAsyncMethodCaller> async_caller;
277   async_caller.SetUp(false, cryptohome::MOUNT_ERROR_NONE);
278   EXPECT_CALL(async_caller,
279               AsyncTpmAttestationCreateCertRequest(
280                   PROFILE_ENTERPRISE_USER_CERTIFICATE, "", "", _))
281       .Times(1);
282 
283   chromeos::MockCryptohomeClient client;
284   EXPECT_CALL(client, TpmAttestationIsEnrolled(_))
285       .WillRepeatedly(Invoke(DBusCallbackTrue));
286 
287   // We're not expecting any server calls in this case; StrictMock will verify.
288   scoped_ptr<MockServerProxy> proxy(new StrictMock<MockServerProxy>());
289 
290   StrictMock<MockObserver> observer;
291   EXPECT_CALL(observer, MockCertificateCallback(false, "")).Times(1);
292   AttestationFlow::CertificateCallback mock_callback = base::Bind(
293       &MockObserver::MockCertificateCallback,
294       base::Unretained(&observer));
295 
296   scoped_ptr<ServerProxy> proxy_interface(proxy.release());
297   AttestationFlow flow(&async_caller, &client, proxy_interface.Pass());
298   flow.GetCertificate(PROFILE_ENTERPRISE_USER_CERTIFICATE, "", "", true,
299                       mock_callback);
300   Run();
301 }
302 
TEST_F(AttestationFlowTest,GetCertificate_CertRequestRejected)303 TEST_F(AttestationFlowTest, GetCertificate_CertRequestRejected) {
304   StrictMock<cryptohome::MockAsyncMethodCaller> async_caller;
305   async_caller.SetUp(true, cryptohome::MOUNT_ERROR_NONE);
306   EXPECT_CALL(async_caller,
307               AsyncTpmAttestationCreateCertRequest(
308                   PROFILE_ENTERPRISE_USER_CERTIFICATE, "", "", _))
309       .Times(1);
310 
311   chromeos::MockCryptohomeClient client;
312   EXPECT_CALL(client, TpmAttestationIsEnrolled(_))
313       .WillRepeatedly(Invoke(DBusCallbackTrue));
314 
315   scoped_ptr<MockServerProxy> proxy(new StrictMock<MockServerProxy>());
316   proxy->DeferToFake(false);
317   EXPECT_CALL(*proxy, SendCertificateRequest(
318       cryptohome::MockAsyncMethodCaller::kFakeAttestationCertRequest,
319       _)).Times(1);
320 
321   StrictMock<MockObserver> observer;
322   EXPECT_CALL(observer, MockCertificateCallback(false, "")).Times(1);
323   AttestationFlow::CertificateCallback mock_callback = base::Bind(
324       &MockObserver::MockCertificateCallback,
325       base::Unretained(&observer));
326 
327   scoped_ptr<ServerProxy> proxy_interface(proxy.release());
328   AttestationFlow flow(&async_caller, &client, proxy_interface.Pass());
329   flow.GetCertificate(PROFILE_ENTERPRISE_USER_CERTIFICATE, "", "", true,
330                       mock_callback);
331   Run();
332 }
333 
TEST_F(AttestationFlowTest,GetCertificate_FailIsEnrolled)334 TEST_F(AttestationFlowTest, GetCertificate_FailIsEnrolled) {
335   // We're not expecting any async calls in this case; StrictMock will verify.
336   StrictMock<cryptohome::MockAsyncMethodCaller> async_caller;
337 
338   chromeos::MockCryptohomeClient client;
339   EXPECT_CALL(client, TpmAttestationIsEnrolled(_))
340       .WillRepeatedly(Invoke(DBusCallbackFail));
341 
342   // We're not expecting any server calls in this case; StrictMock will verify.
343   scoped_ptr<MockServerProxy> proxy(new StrictMock<MockServerProxy>());
344 
345   StrictMock<MockObserver> observer;
346   EXPECT_CALL(observer, MockCertificateCallback(false, "")).Times(1);
347   AttestationFlow::CertificateCallback mock_callback = base::Bind(
348       &MockObserver::MockCertificateCallback,
349       base::Unretained(&observer));
350 
351   scoped_ptr<ServerProxy> proxy_interface(proxy.release());
352   AttestationFlow flow(&async_caller, &client, proxy_interface.Pass());
353   flow.GetCertificate(PROFILE_ENTERPRISE_USER_CERTIFICATE, "", "", true,
354                       mock_callback);
355   Run();
356 }
357 
TEST_F(AttestationFlowTest,GetCertificate_CheckExisting)358 TEST_F(AttestationFlowTest, GetCertificate_CheckExisting) {
359   StrictMock<cryptohome::MockAsyncMethodCaller> async_caller;
360   async_caller.SetUp(true, cryptohome::MOUNT_ERROR_NONE);
361   EXPECT_CALL(async_caller,
362               AsyncTpmAttestationCreateCertRequest(
363                   PROFILE_ENTERPRISE_USER_CERTIFICATE, "", "", _))
364       .Times(1);
365   std::string fake_cert_response =
366       cryptohome::MockAsyncMethodCaller::kFakeAttestationCertRequest;
367   fake_cert_response += "_response";
368   EXPECT_CALL(async_caller,
369               AsyncTpmAttestationFinishCertRequest(fake_cert_response,
370                                                    KEY_USER,
371                                                    "",
372                                                    kEnterpriseUserKey,
373                                                    _))
374       .Times(1);
375 
376   chromeos::MockCryptohomeClient client;
377   EXPECT_CALL(client, TpmAttestationIsEnrolled(_))
378       .WillRepeatedly(Invoke(DBusCallbackTrue));
379   EXPECT_CALL(client,
380               TpmAttestationDoesKeyExist(KEY_USER, "", kEnterpriseUserKey, _))
381       .WillRepeatedly(WithArgs<3>(Invoke(DBusCallbackFalse)));
382 
383   scoped_ptr<MockServerProxy> proxy(new StrictMock<MockServerProxy>());
384   proxy->DeferToFake(true);
385   EXPECT_CALL(*proxy, SendCertificateRequest(
386       cryptohome::MockAsyncMethodCaller::kFakeAttestationCertRequest,
387       _)).Times(1);
388 
389   StrictMock<MockObserver> observer;
390   EXPECT_CALL(observer, MockCertificateCallback(
391       true,
392       cryptohome::MockAsyncMethodCaller::kFakeAttestationCert)).Times(1);
393   AttestationFlow::CertificateCallback mock_callback = base::Bind(
394       &MockObserver::MockCertificateCallback,
395       base::Unretained(&observer));
396 
397   scoped_ptr<ServerProxy> proxy_interface(proxy.release());
398   AttestationFlow flow(&async_caller, &client, proxy_interface.Pass());
399   flow.GetCertificate(PROFILE_ENTERPRISE_USER_CERTIFICATE, "", "", false,
400                       mock_callback);
401   Run();
402 }
403 
TEST_F(AttestationFlowTest,GetCertificate_AlreadyExists)404 TEST_F(AttestationFlowTest, GetCertificate_AlreadyExists) {
405   // We're not expecting any async calls in this case; StrictMock will verify.
406   StrictMock<cryptohome::MockAsyncMethodCaller> async_caller;
407 
408   chromeos::MockCryptohomeClient client;
409   EXPECT_CALL(client, TpmAttestationIsEnrolled(_))
410       .WillRepeatedly(Invoke(DBusCallbackTrue));
411   EXPECT_CALL(client,
412               TpmAttestationDoesKeyExist(KEY_USER, "", kEnterpriseUserKey, _))
413       .WillRepeatedly(WithArgs<3>(Invoke(DBusCallbackTrue)));
414   EXPECT_CALL(client,
415               TpmAttestationGetCertificate(KEY_USER, "", kEnterpriseUserKey, _))
416       .WillRepeatedly(WithArgs<3>(Invoke(FakeDBusData("fake_cert"))));
417 
418   // We're not expecting any server calls in this case; StrictMock will verify.
419   scoped_ptr<MockServerProxy> proxy(new StrictMock<MockServerProxy>());
420 
421   StrictMock<MockObserver> observer;
422   EXPECT_CALL(observer, MockCertificateCallback(true, "fake_cert")).Times(1);
423   AttestationFlow::CertificateCallback mock_callback = base::Bind(
424       &MockObserver::MockCertificateCallback,
425       base::Unretained(&observer));
426 
427   scoped_ptr<ServerProxy> proxy_interface(proxy.release());
428   AttestationFlow flow(&async_caller, &client, proxy_interface.Pass());
429   flow.GetCertificate(PROFILE_ENTERPRISE_USER_CERTIFICATE, "", "", false,
430                       mock_callback);
431   Run();
432 }
433 
434 }  // namespace attestation
435 }  // namespace chromeos
436