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.
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"
15 using testing::AtLeast
;
16 using testing::DoDefault
;
17 using testing::Invoke
;
18 using testing::NiceMock
;
19 using testing::Return
;
20 using testing::Sequence
;
21 using testing::StrictMock
;
22 using testing::WithArgs
;
25 namespace attestation
{
29 void DBusCallbackFalse(const BoolDBusMethodCallback
& callback
) {
30 base::MessageLoop::current()->PostTask(
31 FROM_HERE
, base::Bind(callback
, DBUS_METHOD_CALL_SUCCESS
, false));
34 void DBusCallbackTrue(const BoolDBusMethodCallback
& callback
) {
35 base::MessageLoop::current()->PostTask(
36 FROM_HERE
, base::Bind(callback
, DBUS_METHOD_CALL_SUCCESS
, true));
39 void DBusCallbackFail(const BoolDBusMethodCallback
& callback
) {
40 base::MessageLoop::current()->PostTask(
41 FROM_HERE
, base::Bind(callback
, DBUS_METHOD_CALL_FAILURE
, false));
44 void AsyncCallbackFalse(cryptohome::AsyncMethodCaller::Callback callback
) {
45 callback
.Run(false, cryptohome::MOUNT_ERROR_NONE
);
50 explicit FakeDBusData(const std::string
& data
) : data_(data
) {}
52 void operator() (const CryptohomeClient::DataMethodCallback
& callback
) {
53 base::MessageLoop::current()->PostTask(
55 base::Bind(callback
, DBUS_METHOD_CALL_SUCCESS
, true, data_
));
64 class AttestationFlowTest
: public testing::Test
{
67 base::RunLoop run_loop
;
68 run_loop
.RunUntilIdle();
70 base::MessageLoop message_loop_
;
73 TEST_F(AttestationFlowTest
, GetCertificate
) {
74 // Verify the order of calls in a sequence.
77 // Use DBusCallbackFalse so the full enrollment flow is triggered.
78 chromeos::MockCryptohomeClient client
;
79 EXPECT_CALL(client
, TpmAttestationIsEnrolled(_
))
80 .InSequence(flow_order
)
81 .WillRepeatedly(Invoke(DBusCallbackFalse
));
83 // Use StrictMock when we want to verify invocation frequency.
84 StrictMock
<cryptohome::MockAsyncMethodCaller
> async_caller
;
85 async_caller
.SetUp(true, cryptohome::MOUNT_ERROR_NONE
);
86 EXPECT_CALL(async_caller
, AsyncTpmAttestationCreateEnrollRequest(_
, _
))
88 .InSequence(flow_order
);
90 scoped_ptr
<MockServerProxy
> proxy(new StrictMock
<MockServerProxy
>());
91 proxy
->DeferToFake(true);
92 EXPECT_CALL(*proxy
, GetType()).WillRepeatedly(DoDefault());
93 EXPECT_CALL(*proxy
, SendEnrollRequest(
94 cryptohome::MockAsyncMethodCaller::kFakeAttestationEnrollRequest
,
96 .InSequence(flow_order
);
98 std::string fake_enroll_response
=
99 cryptohome::MockAsyncMethodCaller::kFakeAttestationEnrollRequest
;
100 fake_enroll_response
+= "_response";
101 EXPECT_CALL(async_caller
,
102 AsyncTpmAttestationEnroll(_
, fake_enroll_response
, _
))
104 .InSequence(flow_order
);
108 AsyncTpmAttestationCreateCertRequest(_
,
109 PROFILE_ENTERPRISE_USER_CERTIFICATE
,
110 "fake@test.com", "fake_origin", _
))
112 .InSequence(flow_order
);
114 EXPECT_CALL(*proxy
, SendCertificateRequest(
115 cryptohome::MockAsyncMethodCaller::kFakeAttestationCertRequest
,
117 .InSequence(flow_order
);
119 std::string fake_cert_response
=
120 cryptohome::MockAsyncMethodCaller::kFakeAttestationCertRequest
;
121 fake_cert_response
+= "_response";
122 EXPECT_CALL(async_caller
,
123 AsyncTpmAttestationFinishCertRequest(fake_cert_response
,
129 .InSequence(flow_order
);
131 StrictMock
<MockObserver
> observer
;
132 EXPECT_CALL(observer
, MockCertificateCallback(
134 cryptohome::MockAsyncMethodCaller::kFakeAttestationCert
))
136 .InSequence(flow_order
);
137 AttestationFlow::CertificateCallback mock_callback
= base::Bind(
138 &MockObserver::MockCertificateCallback
,
139 base::Unretained(&observer
));
141 scoped_ptr
<ServerProxy
> proxy_interface(proxy
.release());
142 AttestationFlow
flow(&async_caller
, &client
, proxy_interface
.Pass());
143 flow
.GetCertificate(PROFILE_ENTERPRISE_USER_CERTIFICATE
, "fake@test.com",
144 "fake_origin", true, mock_callback
);
148 TEST_F(AttestationFlowTest
, GetCertificate_NoEK
) {
149 StrictMock
<cryptohome::MockAsyncMethodCaller
> async_caller
;
150 async_caller
.SetUp(false, cryptohome::MOUNT_ERROR_NONE
);
151 EXPECT_CALL(async_caller
, AsyncTpmAttestationCreateEnrollRequest(_
, _
))
154 chromeos::MockCryptohomeClient client
;
155 EXPECT_CALL(client
, TpmAttestationIsEnrolled(_
))
156 .WillRepeatedly(Invoke(DBusCallbackFalse
));
158 // We're not expecting any server calls in this case; StrictMock will verify.
159 scoped_ptr
<MockServerProxy
> proxy(new StrictMock
<MockServerProxy
>());
160 EXPECT_CALL(*proxy
, GetType()).WillRepeatedly(DoDefault());
162 StrictMock
<MockObserver
> observer
;
163 EXPECT_CALL(observer
, MockCertificateCallback(false, ""))
165 AttestationFlow::CertificateCallback mock_callback
= base::Bind(
166 &MockObserver::MockCertificateCallback
,
167 base::Unretained(&observer
));
169 scoped_ptr
<ServerProxy
> proxy_interface(proxy
.release());
170 AttestationFlow
flow(&async_caller
, &client
, proxy_interface
.Pass());
171 flow
.GetCertificate(PROFILE_ENTERPRISE_USER_CERTIFICATE
, "", "", true,
176 TEST_F(AttestationFlowTest
, GetCertificate_EKRejected
) {
177 StrictMock
<cryptohome::MockAsyncMethodCaller
> async_caller
;
178 async_caller
.SetUp(true, cryptohome::MOUNT_ERROR_NONE
);
179 EXPECT_CALL(async_caller
, AsyncTpmAttestationCreateEnrollRequest(_
, _
))
182 chromeos::MockCryptohomeClient client
;
183 EXPECT_CALL(client
, TpmAttestationIsEnrolled(_
))
184 .WillRepeatedly(Invoke(DBusCallbackFalse
));
186 scoped_ptr
<MockServerProxy
> proxy(new StrictMock
<MockServerProxy
>());
187 proxy
->DeferToFake(false);
188 EXPECT_CALL(*proxy
, GetType()).WillRepeatedly(DoDefault());
189 EXPECT_CALL(*proxy
, SendEnrollRequest(
190 cryptohome::MockAsyncMethodCaller::kFakeAttestationEnrollRequest
,
193 StrictMock
<MockObserver
> observer
;
194 EXPECT_CALL(observer
, MockCertificateCallback(false, ""))
196 AttestationFlow::CertificateCallback mock_callback
= base::Bind(
197 &MockObserver::MockCertificateCallback
,
198 base::Unretained(&observer
));
200 scoped_ptr
<ServerProxy
> proxy_interface(proxy
.release());
201 AttestationFlow
flow(&async_caller
, &client
, proxy_interface
.Pass());
202 flow
.GetCertificate(PROFILE_ENTERPRISE_USER_CERTIFICATE
, "", "", true,
207 TEST_F(AttestationFlowTest
, GetCertificate_FailEnroll
) {
208 StrictMock
<cryptohome::MockAsyncMethodCaller
> async_caller
;
209 async_caller
.SetUp(true, cryptohome::MOUNT_ERROR_NONE
);
210 EXPECT_CALL(async_caller
, AsyncTpmAttestationCreateEnrollRequest(_
, _
))
212 std::string fake_enroll_response
=
213 cryptohome::MockAsyncMethodCaller::kFakeAttestationEnrollRequest
;
214 fake_enroll_response
+= "_response";
215 EXPECT_CALL(async_caller
,
216 AsyncTpmAttestationEnroll(_
, fake_enroll_response
, _
))
217 .WillOnce(WithArgs
<2>(Invoke(AsyncCallbackFalse
)));
219 chromeos::MockCryptohomeClient client
;
220 EXPECT_CALL(client
, TpmAttestationIsEnrolled(_
))
221 .WillRepeatedly(Invoke(DBusCallbackFalse
));
223 scoped_ptr
<MockServerProxy
> proxy(new StrictMock
<MockServerProxy
>());
224 proxy
->DeferToFake(true);
225 EXPECT_CALL(*proxy
, GetType()).WillRepeatedly(DoDefault());
226 EXPECT_CALL(*proxy
, SendEnrollRequest(
227 cryptohome::MockAsyncMethodCaller::kFakeAttestationEnrollRequest
,
230 StrictMock
<MockObserver
> observer
;
231 EXPECT_CALL(observer
, MockCertificateCallback(false, "")).Times(1);
232 AttestationFlow::CertificateCallback mock_callback
= base::Bind(
233 &MockObserver::MockCertificateCallback
,
234 base::Unretained(&observer
));
236 scoped_ptr
<ServerProxy
> proxy_interface(proxy
.release());
237 AttestationFlow
flow(&async_caller
, &client
, proxy_interface
.Pass());
238 flow
.GetCertificate(PROFILE_ENTERPRISE_USER_CERTIFICATE
, "", "", true,
243 TEST_F(AttestationFlowTest
, GetMachineCertificateAlreadyEnrolled
) {
244 StrictMock
<cryptohome::MockAsyncMethodCaller
> async_caller
;
245 async_caller
.SetUp(true, cryptohome::MOUNT_ERROR_NONE
);
246 EXPECT_CALL(async_caller
,
247 AsyncTpmAttestationCreateCertRequest(
248 _
, PROFILE_ENTERPRISE_MACHINE_CERTIFICATE
, "", "", _
))
250 std::string fake_cert_response
=
251 cryptohome::MockAsyncMethodCaller::kFakeAttestationCertRequest
;
252 fake_cert_response
+= "_response";
253 EXPECT_CALL(async_caller
,
254 AsyncTpmAttestationFinishCertRequest(fake_cert_response
,
257 kEnterpriseMachineKey
,
261 chromeos::MockCryptohomeClient client
;
262 EXPECT_CALL(client
, TpmAttestationIsEnrolled(_
))
263 .WillRepeatedly(Invoke(DBusCallbackTrue
));
265 scoped_ptr
<MockServerProxy
> proxy(new StrictMock
<MockServerProxy
>());
266 proxy
->DeferToFake(true);
267 EXPECT_CALL(*proxy
, GetType()).WillRepeatedly(DoDefault());
268 EXPECT_CALL(*proxy
, SendCertificateRequest(
269 cryptohome::MockAsyncMethodCaller::kFakeAttestationCertRequest
,
272 StrictMock
<MockObserver
> observer
;
273 EXPECT_CALL(observer
, MockCertificateCallback(
275 cryptohome::MockAsyncMethodCaller::kFakeAttestationCert
)).Times(1);
276 AttestationFlow::CertificateCallback mock_callback
= base::Bind(
277 &MockObserver::MockCertificateCallback
,
278 base::Unretained(&observer
));
280 scoped_ptr
<ServerProxy
> proxy_interface(proxy
.release());
281 AttestationFlow
flow(&async_caller
, &client
, proxy_interface
.Pass());
282 flow
.GetCertificate(PROFILE_ENTERPRISE_MACHINE_CERTIFICATE
, "", "", true,
287 TEST_F(AttestationFlowTest
, GetCertificate_FailCreateCertRequest
) {
288 StrictMock
<cryptohome::MockAsyncMethodCaller
> async_caller
;
289 async_caller
.SetUp(false, cryptohome::MOUNT_ERROR_NONE
);
290 EXPECT_CALL(async_caller
,
291 AsyncTpmAttestationCreateCertRequest(
292 _
, PROFILE_ENTERPRISE_USER_CERTIFICATE
, "", "", _
))
295 chromeos::MockCryptohomeClient client
;
296 EXPECT_CALL(client
, TpmAttestationIsEnrolled(_
))
297 .WillRepeatedly(Invoke(DBusCallbackTrue
));
299 // We're not expecting any server calls in this case; StrictMock will verify.
300 scoped_ptr
<MockServerProxy
> proxy(new StrictMock
<MockServerProxy
>());
301 EXPECT_CALL(*proxy
, GetType()).WillRepeatedly(DoDefault());
303 StrictMock
<MockObserver
> observer
;
304 EXPECT_CALL(observer
, MockCertificateCallback(false, "")).Times(1);
305 AttestationFlow::CertificateCallback mock_callback
= base::Bind(
306 &MockObserver::MockCertificateCallback
,
307 base::Unretained(&observer
));
309 scoped_ptr
<ServerProxy
> proxy_interface(proxy
.release());
310 AttestationFlow
flow(&async_caller
, &client
, proxy_interface
.Pass());
311 flow
.GetCertificate(PROFILE_ENTERPRISE_USER_CERTIFICATE
, "", "", true,
316 TEST_F(AttestationFlowTest
, GetCertificate_CertRequestRejected
) {
317 StrictMock
<cryptohome::MockAsyncMethodCaller
> async_caller
;
318 async_caller
.SetUp(true, cryptohome::MOUNT_ERROR_NONE
);
319 EXPECT_CALL(async_caller
,
320 AsyncTpmAttestationCreateCertRequest(
321 _
, PROFILE_ENTERPRISE_USER_CERTIFICATE
, "", "", _
))
324 chromeos::MockCryptohomeClient client
;
325 EXPECT_CALL(client
, TpmAttestationIsEnrolled(_
))
326 .WillRepeatedly(Invoke(DBusCallbackTrue
));
328 scoped_ptr
<MockServerProxy
> proxy(new StrictMock
<MockServerProxy
>());
329 proxy
->DeferToFake(false);
330 EXPECT_CALL(*proxy
, GetType()).WillRepeatedly(DoDefault());
331 EXPECT_CALL(*proxy
, SendCertificateRequest(
332 cryptohome::MockAsyncMethodCaller::kFakeAttestationCertRequest
,
335 StrictMock
<MockObserver
> observer
;
336 EXPECT_CALL(observer
, MockCertificateCallback(false, "")).Times(1);
337 AttestationFlow::CertificateCallback mock_callback
= base::Bind(
338 &MockObserver::MockCertificateCallback
,
339 base::Unretained(&observer
));
341 scoped_ptr
<ServerProxy
> proxy_interface(proxy
.release());
342 AttestationFlow
flow(&async_caller
, &client
, proxy_interface
.Pass());
343 flow
.GetCertificate(PROFILE_ENTERPRISE_USER_CERTIFICATE
, "", "", true,
348 TEST_F(AttestationFlowTest
, GetCertificate_FailIsEnrolled
) {
349 // We're not expecting any async calls in this case; StrictMock will verify.
350 StrictMock
<cryptohome::MockAsyncMethodCaller
> async_caller
;
352 chromeos::MockCryptohomeClient client
;
353 EXPECT_CALL(client
, TpmAttestationIsEnrolled(_
))
354 .WillRepeatedly(Invoke(DBusCallbackFail
));
356 // We're not expecting any server calls in this case; StrictMock will verify.
357 scoped_ptr
<MockServerProxy
> proxy(new StrictMock
<MockServerProxy
>());
358 EXPECT_CALL(*proxy
, GetType()).WillRepeatedly(DoDefault());
360 StrictMock
<MockObserver
> observer
;
361 EXPECT_CALL(observer
, MockCertificateCallback(false, "")).Times(1);
362 AttestationFlow::CertificateCallback mock_callback
= base::Bind(
363 &MockObserver::MockCertificateCallback
,
364 base::Unretained(&observer
));
366 scoped_ptr
<ServerProxy
> proxy_interface(proxy
.release());
367 AttestationFlow
flow(&async_caller
, &client
, proxy_interface
.Pass());
368 flow
.GetCertificate(PROFILE_ENTERPRISE_USER_CERTIFICATE
, "", "", true,
373 TEST_F(AttestationFlowTest
, GetCertificate_CheckExisting
) {
374 StrictMock
<cryptohome::MockAsyncMethodCaller
> async_caller
;
375 async_caller
.SetUp(true, cryptohome::MOUNT_ERROR_NONE
);
376 EXPECT_CALL(async_caller
,
377 AsyncTpmAttestationCreateCertRequest(
378 _
, PROFILE_ENTERPRISE_USER_CERTIFICATE
, "", "", _
))
380 std::string fake_cert_response
=
381 cryptohome::MockAsyncMethodCaller::kFakeAttestationCertRequest
;
382 fake_cert_response
+= "_response";
383 EXPECT_CALL(async_caller
,
384 AsyncTpmAttestationFinishCertRequest(fake_cert_response
,
391 chromeos::MockCryptohomeClient client
;
392 EXPECT_CALL(client
, TpmAttestationIsEnrolled(_
))
393 .WillRepeatedly(Invoke(DBusCallbackTrue
));
395 TpmAttestationDoesKeyExist(KEY_USER
, "", kEnterpriseUserKey
, _
))
396 .WillRepeatedly(WithArgs
<3>(Invoke(DBusCallbackFalse
)));
398 scoped_ptr
<MockServerProxy
> proxy(new StrictMock
<MockServerProxy
>());
399 proxy
->DeferToFake(true);
400 EXPECT_CALL(*proxy
, GetType()).WillRepeatedly(DoDefault());
401 EXPECT_CALL(*proxy
, SendCertificateRequest(
402 cryptohome::MockAsyncMethodCaller::kFakeAttestationCertRequest
,
405 StrictMock
<MockObserver
> observer
;
406 EXPECT_CALL(observer
, MockCertificateCallback(
408 cryptohome::MockAsyncMethodCaller::kFakeAttestationCert
)).Times(1);
409 AttestationFlow::CertificateCallback mock_callback
= base::Bind(
410 &MockObserver::MockCertificateCallback
,
411 base::Unretained(&observer
));
413 scoped_ptr
<ServerProxy
> proxy_interface(proxy
.release());
414 AttestationFlow
flow(&async_caller
, &client
, proxy_interface
.Pass());
415 flow
.GetCertificate(PROFILE_ENTERPRISE_USER_CERTIFICATE
, "", "", false,
420 TEST_F(AttestationFlowTest
, GetCertificate_AlreadyExists
) {
421 // We're not expecting any async calls in this case; StrictMock will verify.
422 StrictMock
<cryptohome::MockAsyncMethodCaller
> async_caller
;
424 chromeos::MockCryptohomeClient client
;
425 EXPECT_CALL(client
, TpmAttestationIsEnrolled(_
))
426 .WillRepeatedly(Invoke(DBusCallbackTrue
));
428 TpmAttestationDoesKeyExist(KEY_USER
, "", kEnterpriseUserKey
, _
))
429 .WillRepeatedly(WithArgs
<3>(Invoke(DBusCallbackTrue
)));
431 TpmAttestationGetCertificate(KEY_USER
, "", kEnterpriseUserKey
, _
))
432 .WillRepeatedly(WithArgs
<3>(Invoke(FakeDBusData("fake_cert"))));
434 // We're not expecting any server calls in this case; StrictMock will verify.
435 scoped_ptr
<MockServerProxy
> proxy(new StrictMock
<MockServerProxy
>());
436 EXPECT_CALL(*proxy
, GetType()).WillRepeatedly(DoDefault());
438 StrictMock
<MockObserver
> observer
;
439 EXPECT_CALL(observer
, MockCertificateCallback(true, "fake_cert")).Times(1);
440 AttestationFlow::CertificateCallback mock_callback
= base::Bind(
441 &MockObserver::MockCertificateCallback
,
442 base::Unretained(&observer
));
444 scoped_ptr
<ServerProxy
> proxy_interface(proxy
.release());
445 AttestationFlow
flow(&async_caller
, &client
, proxy_interface
.Pass());
446 flow
.GetCertificate(PROFILE_ENTERPRISE_USER_CERTIFICATE
, "", "", false,
451 TEST_F(AttestationFlowTest
, AlternatePCA
) {
452 // Strategy: Create a ServerProxy mock which reports ALTERNATE_PCA and check
453 // that all calls to the AsyncMethodCaller reflect this PCA type.
454 scoped_ptr
<MockServerProxy
> proxy(new NiceMock
<MockServerProxy
>());
455 proxy
->DeferToFake(true);
456 EXPECT_CALL(*proxy
, GetType()).WillRepeatedly(Return(ALTERNATE_PCA
));
458 chromeos::MockCryptohomeClient client
;
459 EXPECT_CALL(client
, TpmAttestationIsEnrolled(_
))
460 .WillRepeatedly(Invoke(DBusCallbackFalse
));
462 NiceMock
<cryptohome::MockAsyncMethodCaller
> async_caller
;
463 async_caller
.SetUp(true, cryptohome::MOUNT_ERROR_NONE
);
464 EXPECT_CALL(async_caller
,
465 AsyncTpmAttestationCreateEnrollRequest(ALTERNATE_PCA
, _
))
467 EXPECT_CALL(async_caller
,
468 AsyncTpmAttestationEnroll(ALTERNATE_PCA
, _
, _
))
470 EXPECT_CALL(async_caller
,
471 AsyncTpmAttestationCreateCertRequest(ALTERNATE_PCA
, _
, _
, _
, _
))
474 NiceMock
<MockObserver
> observer
;
475 AttestationFlow::CertificateCallback mock_callback
= base::Bind(
476 &MockObserver::MockCertificateCallback
,
477 base::Unretained(&observer
));
479 scoped_ptr
<ServerProxy
> proxy_interface(proxy
.release());
480 AttestationFlow
flow(&async_caller
, &client
, proxy_interface
.Pass());
481 flow
.GetCertificate(PROFILE_ENTERPRISE_USER_CERTIFICATE
, "", "", true,
486 } // namespace attestation
487 } // namespace chromeos