Home | History | Annotate | Download | only in attestation
      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 
     25 void DBusCallbackFalse(const BoolDBusMethodCallback& callback) {
     26   base::MessageLoop::current()->PostTask(
     27       FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, false));
     28 }
     29 
     30 void DBusCallbackTrue(const BoolDBusMethodCallback& callback) {
     31   base::MessageLoop::current()->PostTask(
     32       FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true));
     33 }
     34 
     35 void DBusCallbackFail(const BoolDBusMethodCallback& callback) {
     36   base::MessageLoop::current()->PostTask(
     37       FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_FAILURE, false));
     38 }
     39 
     40 void AsyncCallbackFalse(cryptohome::AsyncMethodCaller::Callback callback) {
     41   callback.Run(false, cryptohome::MOUNT_ERROR_NONE);
     42 }
     43 
     44 class FakeDBusData {
     45  public:
     46   explicit FakeDBusData(const std::string& data) : data_(data) {}
     47 
     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:
     62   void Run() {
     63     base::RunLoop run_loop;
     64     run_loop.RunUntilIdle();
     65   }
     66   base::MessageLoop message_loop_;
     67 };
     68 
     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 (at) 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 (at) 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 (at) test.com",
    137                       "fake_origin", true, mock_callback);
    138   Run();
    139 }
    140 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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