summaryrefslogtreecommitdiffstats
path: root/chromeos/attestation
diff options
context:
space:
mode:
authordkrahn@google.com <dkrahn@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2013-04-27 02:32:45 +0000
committerdkrahn@google.com <dkrahn@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2013-04-27 02:32:45 +0000
commitcd88f791eacd3f59a83af0fe1713db55ed03a352 (patch)
treeff230ec36e7090fbe3a17e0b544b24e51c295883 /chromeos/attestation
parent901864c2613bf8dd4afb5c8ba0b231b47938741a (diff)
downloadchromium_src-cd88f791eacd3f59a83af0fe1713db55ed03a352.zip
chromium_src-cd88f791eacd3f59a83af0fe1713db55ed03a352.tar.gz
chromium_src-cd88f791eacd3f59a83af0fe1713db55ed03a352.tar.bz2
Enhanced and refactored the AttestationFlow interface.
This change makes the AttestationFlow interface easier to work with. Supported certificate profiles are explicitly defined and the clobbering of existing keys is now optional. All attestation constants have been consolidated in attestation_constants.h. BUG=chromium:219959 TEST=unit Review URL: https://chromiumcodereview.appspot.com/14305009 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@196926 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chromeos/attestation')
-rw-r--r--chromeos/attestation/attestation_constants.cc14
-rw-r--r--chromeos/attestation/attestation_constants.h64
-rw-r--r--chromeos/attestation/attestation_flow.cc140
-rw-r--r--chromeos/attestation/attestation_flow.h71
-rw-r--r--chromeos/attestation/attestation_flow_unittest.cc135
-rw-r--r--chromeos/attestation/mock_attestation_flow.h3
6 files changed, 352 insertions, 75 deletions
diff --git a/chromeos/attestation/attestation_constants.cc b/chromeos/attestation/attestation_constants.cc
new file mode 100644
index 0000000..9f3833b
--- /dev/null
+++ b/chromeos/attestation/attestation_constants.cc
@@ -0,0 +1,14 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromeos/attestation/attestation_constants.h"
+
+namespace chromeos {
+namespace attestation {
+
+const char kEnterpriseMachineKey[] = "attest-ent-machine";
+const char kEnterpriseUserKey[] = "attest-ent-user";
+
+} // namespace attestation
+} // namespace chromeos
diff --git a/chromeos/attestation/attestation_constants.h b/chromeos/attestation/attestation_constants.h
new file mode 100644
index 0000000..a704cfc
--- /dev/null
+++ b/chromeos/attestation/attestation_constants.h
@@ -0,0 +1,64 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMEOS_ATTESTATION_ATTESTATION_CONSTANTS_H_
+#define CHROMEOS_ATTESTATION_ATTESTATION_CONSTANTS_H_
+
+#include "chromeos/chromeos_export.h"
+
+namespace chromeos {
+namespace attestation {
+
+// Options available for customizing an attestation certificate.
+enum AttestationCertificateOptions {
+ CERTIFICATE_OPTION_NONE = 0,
+ // A stable identifier is simply an identifier that is not affected by device
+ // state changes, including device recovery.
+ CERTIFICATE_INCLUDE_STABLE_ID = 1,
+ // Device state information contains a quoted assertion of whether the device
+ // is in verified mode.
+ CERTIFICATE_INCLUDE_DEVICE_STATE = 1 << 1,
+};
+
+// Key types supported by the Chrome OS attestation subsystem.
+enum AttestationKeyType {
+ // The key will be associated with the device itself and will be available
+ // regardless of which user is signed-in.
+ KEY_DEVICE,
+ // The key will be associated with the current user and will only be available
+ // when that user is signed-in.
+ KEY_USER,
+};
+
+// Options available for customizing an attestation challenge response.
+enum AttestationChallengeOptions {
+ CHALLENGE_OPTION_NONE = 0,
+ // Indicates that a SignedPublicKeyAndChallenge should be embedded in the
+ // challenge response.
+ CHALLENGE_INCLUDE_SIGNED_PUBLIC_KEY = 1,
+};
+
+// Available attestation certificate profiles.
+enum AttestationCertificateProfile {
+ // Uses the following certificate options:
+ // CERTIFICATE_INCLUDE_STABLE_ID
+ // CERTIFICATE_INCLUDE_DEVICE_STATE
+ PROFILE_ENTERPRISE_MACHINE_CERTIFICATE,
+ // Uses the following certificate options:
+ // CERTIFICATE_INCLUDE_DEVICE_STATE
+ PROFILE_ENTERPRISE_USER_CERTIFICATE,
+};
+
+// A key name for the Enterprise Machine Key. This key should always be stored
+// as a DEVICE_KEY.
+CHROMEOS_EXPORT extern const char kEnterpriseMachineKey[];
+
+// A key name for the Enterprise User Key. This key should always be stored as
+// a USER_KEY.
+CHROMEOS_EXPORT extern const char kEnterpriseUserKey[];
+
+} // namespace attestation
+} // namespace chromeos
+
+#endif // CHROMEOS_ATTESTATION_ATTESTATION_CONSTANTS_H_
diff --git a/chromeos/attestation/attestation_flow.cc b/chromeos/attestation/attestation_flow.cc
index 97842a3..2fba761 100644
--- a/chromeos/attestation/attestation_flow.cc
+++ b/chromeos/attestation/attestation_flow.cc
@@ -38,30 +38,82 @@ void DBusBoolRedirectCallback(const base::Closure& on_true,
task.Run();
}
-} // namespace
+void DBusDataMethodCallback(
+ const AttestationFlow::CertificateCallback& callback,
+ DBusMethodCallStatus status,
+ bool result,
+ const std::string& data) {
+ if (status != DBUS_METHOD_CALL_SUCCESS) {
+ LOG(ERROR) << "Attestation: DBus data operation failed.";
+ if (!callback.is_null())
+ callback.Run(false, "");
+ return;
+ }
+ if (!callback.is_null())
+ callback.Run(result, data);
+}
+
+AttestationKeyType GetKeyTypeForProfile(
+ AttestationCertificateProfile profile) {
+ switch (profile) {
+ case PROFILE_ENTERPRISE_MACHINE_CERTIFICATE:
+ return KEY_DEVICE;
+ case PROFILE_ENTERPRISE_USER_CERTIFICATE:
+ return KEY_USER;
+ }
+ NOTREACHED();
+ return KEY_USER;
+}
-const char AttestationFlow::kEnterpriseMachineKey[] = "attest-ent-machine";
+std::string GetKeyNameForProfile(
+ AttestationCertificateProfile profile) {
+ switch (profile) {
+ case PROFILE_ENTERPRISE_MACHINE_CERTIFICATE:
+ return kEnterpriseMachineKey;
+ case PROFILE_ENTERPRISE_USER_CERTIFICATE:
+ return kEnterpriseUserKey;
+ }
+ NOTREACHED();
+ return "";
+}
+
+int GetCertificateOptionsForProfile(
+ AttestationCertificateProfile profile) {
+ switch (profile) {
+ case PROFILE_ENTERPRISE_MACHINE_CERTIFICATE:
+ return CERTIFICATE_INCLUDE_STABLE_ID | CERTIFICATE_INCLUDE_DEVICE_STATE;
+ case PROFILE_ENTERPRISE_USER_CERTIFICATE:
+ return CERTIFICATE_INCLUDE_DEVICE_STATE;
+ }
+ NOTREACHED();
+ return CERTIFICATE_OPTION_NONE;
+}
+
+} // namespace
AttestationFlow::AttestationFlow(cryptohome::AsyncMethodCaller* async_caller,
CryptohomeClient* cryptohome_client,
scoped_ptr<ServerProxy> server_proxy)
- : weak_factory_(this),
- async_caller_(async_caller),
+ : async_caller_(async_caller),
cryptohome_client_(cryptohome_client),
- server_proxy_(server_proxy.Pass()) {
+ server_proxy_(server_proxy.Pass()),
+ weak_factory_(this) {
}
AttestationFlow::~AttestationFlow() {
}
-void AttestationFlow::GetCertificate(const std::string& name,
- const CertificateCallback& callback) {
+void AttestationFlow::GetCertificate(
+ AttestationCertificateProfile certificate_profile,
+ bool force_new_key,
+ const CertificateCallback& callback) {
// If this device has not enrolled with the Privacy CA, we need to do that
// first. Once enrolled we can proceed with the certificate request.
base::Closure do_cert_request = base::Bind(
&AttestationFlow::StartCertificateRequest,
weak_factory_.GetWeakPtr(),
- name,
+ certificate_profile,
+ force_new_key,
callback);
base::Closure on_enroll_failure = base::Bind(callback, false, "");
base::Closure do_enroll = base::Bind(&AttestationFlow::StartEnroll,
@@ -143,22 +195,49 @@ void AttestationFlow::OnEnrollComplete(const base::Closure& on_failure,
}
void AttestationFlow::StartCertificateRequest(
- const std::string& name,
+ AttestationCertificateProfile certificate_profile,
+ bool generate_new_key,
const CertificateCallback& callback) {
- // Get the attestation service to create a Privacy CA certificate request.
- int options = CryptohomeClient::INCLUDE_DEVICE_STATE;
- if (name == kEnterpriseMachineKey)
- options |= CryptohomeClient::INCLUDE_STABLE_ID;
- async_caller_->AsyncTpmAttestationCreateCertRequest(
- options,
- base::Bind(&AttestationFlow::SendCertificateRequestToPCA,
- weak_factory_.GetWeakPtr(),
- name,
- callback));
+ AttestationKeyType key_type = GetKeyTypeForProfile(certificate_profile);
+ std::string key_name = GetKeyNameForProfile(certificate_profile);
+ if (generate_new_key) {
+ // Get the attestation service to create a Privacy CA certificate request.
+ async_caller_->AsyncTpmAttestationCreateCertRequest(
+ GetCertificateOptionsForProfile(certificate_profile),
+ base::Bind(&AttestationFlow::SendCertificateRequestToPCA,
+ weak_factory_.GetWeakPtr(),
+ key_type,
+ key_name,
+ callback));
+ } else {
+ // If the key already exists, query the existing certificate.
+ base::Closure on_key_exists = base::Bind(
+ &AttestationFlow::GetExistingCertificate,
+ weak_factory_.GetWeakPtr(),
+ key_type,
+ key_name,
+ callback);
+ // If the key does not exist, call this method back with |generate_new_key|
+ // set to true.
+ base::Closure on_key_not_exists = base::Bind(
+ &AttestationFlow::StartCertificateRequest,
+ weak_factory_.GetWeakPtr(),
+ certificate_profile,
+ true,
+ callback);
+ cryptohome_client_->TpmAttestationDoesKeyExist(
+ key_type,
+ key_name,
+ base::Bind(&DBusBoolRedirectCallback,
+ on_key_exists,
+ on_key_not_exists,
+ base::Bind(callback, false, "")));
+ }
}
void AttestationFlow::SendCertificateRequestToPCA(
- const std::string& name,
+ AttestationKeyType key_type,
+ const std::string& key_name,
const CertificateCallback& callback,
bool success,
const std::string& data) {
@@ -174,12 +253,14 @@ void AttestationFlow::SendCertificateRequestToPCA(
data,
base::Bind(&AttestationFlow::SendCertificateResponseToDaemon,
weak_factory_.GetWeakPtr(),
- name,
+ key_type,
+ key_name,
callback));
}
void AttestationFlow::SendCertificateResponseToDaemon(
- const std::string& name,
+ AttestationKeyType key_type,
+ const std::string& key_name,
const CertificateCallback& callback,
bool success,
const std::string& data) {
@@ -191,14 +272,21 @@ void AttestationFlow::SendCertificateResponseToDaemon(
}
// Forward the response to the attestation service to complete the operation.
- CryptohomeClient::AttestationKeyType key_type = CryptohomeClient::USER_KEY;
- if (name == kEnterpriseMachineKey)
- key_type = CryptohomeClient::DEVICE_KEY;
async_caller_->AsyncTpmAttestationFinishCertRequest(data,
key_type,
- name,
+ key_name,
base::Bind(callback));
}
+void AttestationFlow::GetExistingCertificate(
+ AttestationKeyType key_type,
+ const std::string& key_name,
+ const CertificateCallback& callback) {
+ cryptohome_client_->TpmAttestationGetCertificate(
+ key_type,
+ key_name,
+ base::Bind(&DBusDataMethodCallback, callback));
+}
+
} // namespace attestation
} // namespace chromeos
diff --git a/chromeos/attestation/attestation_flow.h b/chromeos/attestation/attestation_flow.h
index 76049d7..2c59f3b 100644
--- a/chromeos/attestation/attestation_flow.h
+++ b/chromeos/attestation/attestation_flow.h
@@ -11,6 +11,7 @@
#include "base/callback_forward.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
+#include "chromeos/attestation/attestation_constants.h"
#include "chromeos/chromeos_export.h"
#include "chromeos/dbus/dbus_method_call_status.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
@@ -41,12 +42,12 @@ class CHROMEOS_EXPORT ServerProxy {
// Implements the message flow for Chrome OS attestation tasks. Generally this
// consists of coordinating messages between the Chrome OS attestation service
-// and the Privacy CA server. Sample usage:
+// and the Chrome OS Privacy CA server. Sample usage:
// AttestationFlow flow(AsyncMethodCaller::GetInstance(),
// DBusThreadManager::Get().GetCryptohomeClient(),
-// my_server_proxy);
-// CertificateCallback callback = base::Bind(&MyCallback);
-// flow.GetCertificate("attest-ent-machine", callback);
+// my_server_proxy.Pass());
+// AttestationFlow::CertificateCallback callback = base::Bind(&MyCallback);
+// flow.GetCertificate(ENTERPRISE_USER_CERTIFICATE, false, callback);
class CHROMEOS_EXPORT AttestationFlow {
public:
typedef base::Callback<void(bool success,
@@ -58,25 +59,26 @@ class CHROMEOS_EXPORT AttestationFlow {
scoped_ptr<ServerProxy> server_proxy);
virtual ~AttestationFlow();
- // Asynchronously gets an attestation certificate bound to the given name.
- // If no certificate has been associated with the name, a new certificate is
- // issued.
+ // Gets an attestation certificate for a hardware-protected key. If a key for
+ // the given profile does not exist, it will be generated and a certificate
+ // request will be made to the Chrome OS Privacy CA to issue a certificate for
+ // the key. If the key already exists and |force_new_key| is false, the
+ // existing certificate is returned.
//
// Parameters
- // name - The name of the key for which to retrieve a certificate. The
- // following key names are available:
- // "attest-ent-machine" - The enterprise machine key.
- // "attest-ent-user" - An enterprise user key for the current user.
- // "content-[origin]" - A content protection key bound to a
- // specific origin for the current user.
+ // certificate_profile - Specifies what kind of certificate should be
+ // requested from the CA.
+ // force_new_key - If set to true, a new key will be generated even if a key
+ // already exists for the profile. The new key will replace
+ // the existing key on success.
// callback - A callback which will be called when the operation completes.
- virtual void GetCertificate(const std::string& name,
+ // On success |result| will be true and |data| will contain the
+ // PCA-issued certificate chain in PEM format.
+ virtual void GetCertificate(AttestationCertificateProfile certificate_profile,
+ bool force_new_key,
const CertificateCallback& callback);
private:
- // The key name defined for the special-purpose Enterprise Machine Key.
- static const char kEnterpriseMachineKey[];
-
// Asynchronously initiates the attestation enrollment flow.
//
// Parameters
@@ -130,21 +132,27 @@ class CHROMEOS_EXPORT AttestationFlow {
// enrollment must complete successfully before this operation can succeed.
//
// Parameters
- // name - The name of the key for which a certificate is requested.
+ // certificate_profile - Specifies what kind of certificate should be
+ // requested from the CA.
+ // generate_new_key - If set to true a new key is generated.
// callback - Called when the operation completes.
- void StartCertificateRequest(const std::string& name,
- const CertificateCallback& callback);
+ void StartCertificateRequest(
+ const AttestationCertificateProfile certificate_profile,
+ bool generate_new_key,
+ const CertificateCallback& callback);
// Called when the attestation daemon has finished creating a certificate
// request for the Privacy CA. The request is asynchronously forwarded as-is
// to the PCA.
//
// Parameters
- // name - The name of the key for which a certificate is requested.
+ // key_type - The type of the key for which a certificate is requested.
+ // key_name - The name of the key for which a certificate is requested.
// callback - Called when the operation completes.
// success - The status of request creation.
// data - The request data for the Privacy CA.
- void SendCertificateRequestToPCA(const std::string& name,
+ void SendCertificateRequestToPCA(AttestationKeyType key_type,
+ const std::string& key_name,
const CertificateCallback& callback,
bool success,
const std::string& data);
@@ -154,20 +162,33 @@ class CHROMEOS_EXPORT AttestationFlow {
// complete the operation.
//
// Parameters
- // name - The name of the key for which a certificate is requested.
+ // key_type - The type of the key for which a certificate is requested.
+ // key_name - The name of the key for which a certificate is requested.
// callback - Called when the operation completes.
// success - The status of the Privacy CA operation.
// data - The response data from the Privacy CA.
- void SendCertificateResponseToDaemon(const std::string& name,
+ void SendCertificateResponseToDaemon(AttestationKeyType key_type,
+ const std::string& key_name,
const CertificateCallback& callback,
bool success,
const std::string& data);
- base::WeakPtrFactory<AttestationFlow> weak_factory_;
+ // Gets an existing certificate from the attestation daemon.
+ //
+ // Parameters
+ // key_type - The type of the key for which a certificate is requested.
+ // key_name - The name of the key for which a certificate is requested.
+ // callback - Called when the operation completes.
+ void GetExistingCertificate(AttestationKeyType key_type,
+ const std::string& key_name,
+ const CertificateCallback& callback);
+
cryptohome::AsyncMethodCaller* async_caller_;
CryptohomeClient* cryptohome_client_;
scoped_ptr<ServerProxy> server_proxy_;
+ base::WeakPtrFactory<AttestationFlow> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(AttestationFlow);
};
diff --git a/chromeos/attestation/attestation_flow_unittest.cc b/chromeos/attestation/attestation_flow_unittest.cc
index 30ea3cc..9f70434 100644
--- a/chromeos/attestation/attestation_flow_unittest.cc
+++ b/chromeos/attestation/attestation_flow_unittest.cc
@@ -41,6 +41,20 @@ void AsyncCallbackFalse(cryptohome::AsyncMethodCaller::Callback callback) {
callback.Run(false, cryptohome::MOUNT_ERROR_NONE);
}
+class FakeDBusData {
+ public:
+ explicit FakeDBusData(const std::string& data) : data_(data) {}
+
+ void operator() (const CryptohomeClient::DataMethodCallback& callback) {
+ MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true, data_));
+ }
+
+ private:
+ std::string data_;
+};
+
} // namespace
class AttestationFlowTest : public testing::Test {
@@ -83,11 +97,11 @@ TEST_F(AttestationFlowTest, GetCertificate) {
.Times(1)
.InSequence(flow_order);
- int options = CryptohomeClient::INCLUDE_DEVICE_STATE;
- EXPECT_CALL(async_caller,
- AsyncTpmAttestationCreateCertRequest(options, _))
- .Times(1)
- .InSequence(flow_order);
+ EXPECT_CALL(
+ async_caller,
+ AsyncTpmAttestationCreateCertRequest(CERTIFICATE_INCLUDE_DEVICE_STATE, _))
+ .Times(1)
+ .InSequence(flow_order);
EXPECT_CALL(*proxy, SendCertificateRequest(
cryptohome::MockAsyncMethodCaller::kFakeAttestationCertRequest,
@@ -99,8 +113,8 @@ TEST_F(AttestationFlowTest, GetCertificate) {
fake_cert_response += "_response";
EXPECT_CALL(async_caller,
AsyncTpmAttestationFinishCertRequest(fake_cert_response,
- CryptohomeClient::USER_KEY,
- "test",
+ KEY_USER,
+ kEnterpriseUserKey,
_))
.Times(1)
.InSequence(flow_order);
@@ -117,7 +131,7 @@ TEST_F(AttestationFlowTest, GetCertificate) {
scoped_ptr<ServerProxy> proxy_interface(proxy.release());
AttestationFlow flow(&async_caller, &client, proxy_interface.Pass());
- flow.GetCertificate("test", mock_callback);
+ flow.GetCertificate(PROFILE_ENTERPRISE_USER_CERTIFICATE, true, mock_callback);
Run();
}
@@ -143,7 +157,7 @@ TEST_F(AttestationFlowTest, GetCertificate_NoEK) {
scoped_ptr<ServerProxy> proxy_interface(proxy.release());
AttestationFlow flow(&async_caller, &client, proxy_interface.Pass());
- flow.GetCertificate("test", mock_callback);
+ flow.GetCertificate(PROFILE_ENTERPRISE_USER_CERTIFICATE, true, mock_callback);
Run();
}
@@ -172,7 +186,7 @@ TEST_F(AttestationFlowTest, GetCertificate_EKRejected) {
scoped_ptr<ServerProxy> proxy_interface(proxy.release());
AttestationFlow flow(&async_caller, &client, proxy_interface.Pass());
- flow.GetCertificate("test", mock_callback);
+ flow.GetCertificate(PROFILE_ENTERPRISE_USER_CERTIFICATE, true, mock_callback);
Run();
}
@@ -205,15 +219,15 @@ TEST_F(AttestationFlowTest, GetCertificate_FailEnroll) {
scoped_ptr<ServerProxy> proxy_interface(proxy.release());
AttestationFlow flow(&async_caller, &client, proxy_interface.Pass());
- flow.GetCertificate("test", mock_callback);
+ flow.GetCertificate(PROFILE_ENTERPRISE_USER_CERTIFICATE, true, mock_callback);
Run();
}
-TEST_F(AttestationFlowTest, GetOwnerCertificateAlreadyEnrolled) {
+TEST_F(AttestationFlowTest, GetMachineCertificateAlreadyEnrolled) {
StrictMock<cryptohome::MockAsyncMethodCaller> async_caller;
async_caller.SetUp(true, cryptohome::MOUNT_ERROR_NONE);
- int options = CryptohomeClient::INCLUDE_DEVICE_STATE |
- CryptohomeClient::INCLUDE_STABLE_ID;
+ int options = CERTIFICATE_INCLUDE_DEVICE_STATE |
+ CERTIFICATE_INCLUDE_STABLE_ID;
EXPECT_CALL(async_caller, AsyncTpmAttestationCreateCertRequest(options, _))
.Times(1);
std::string fake_cert_response =
@@ -221,8 +235,8 @@ TEST_F(AttestationFlowTest, GetOwnerCertificateAlreadyEnrolled) {
fake_cert_response += "_response";
EXPECT_CALL(async_caller,
AsyncTpmAttestationFinishCertRequest(fake_cert_response,
- CryptohomeClient::DEVICE_KEY,
- "attest-ent-machine",
+ KEY_DEVICE,
+ kEnterpriseMachineKey,
_))
.Times(1);
@@ -246,14 +260,15 @@ TEST_F(AttestationFlowTest, GetOwnerCertificateAlreadyEnrolled) {
scoped_ptr<ServerProxy> proxy_interface(proxy.release());
AttestationFlow flow(&async_caller, &client, proxy_interface.Pass());
- flow.GetCertificate("attest-ent-machine", mock_callback);
+ flow.GetCertificate(PROFILE_ENTERPRISE_MACHINE_CERTIFICATE,
+ true, mock_callback);
Run();
}
TEST_F(AttestationFlowTest, GetCertificate_FailCreateCertRequest) {
StrictMock<cryptohome::MockAsyncMethodCaller> async_caller;
async_caller.SetUp(false, cryptohome::MOUNT_ERROR_NONE);
- int options = CryptohomeClient::INCLUDE_DEVICE_STATE;
+ int options = CERTIFICATE_INCLUDE_DEVICE_STATE;
EXPECT_CALL(async_caller,
AsyncTpmAttestationCreateCertRequest(options, _))
.Times(1);
@@ -273,14 +288,14 @@ TEST_F(AttestationFlowTest, GetCertificate_FailCreateCertRequest) {
scoped_ptr<ServerProxy> proxy_interface(proxy.release());
AttestationFlow flow(&async_caller, &client, proxy_interface.Pass());
- flow.GetCertificate("test", mock_callback);
+ flow.GetCertificate(PROFILE_ENTERPRISE_USER_CERTIFICATE, true, mock_callback);
Run();
}
TEST_F(AttestationFlowTest, GetCertificate_CertRequestRejected) {
StrictMock<cryptohome::MockAsyncMethodCaller> async_caller;
async_caller.SetUp(true, cryptohome::MOUNT_ERROR_NONE);
- int options = CryptohomeClient::INCLUDE_DEVICE_STATE;
+ int options = CERTIFICATE_INCLUDE_DEVICE_STATE;
EXPECT_CALL(async_caller,
AsyncTpmAttestationCreateCertRequest(options, _))
.Times(1);
@@ -303,12 +318,12 @@ TEST_F(AttestationFlowTest, GetCertificate_CertRequestRejected) {
scoped_ptr<ServerProxy> proxy_interface(proxy.release());
AttestationFlow flow(&async_caller, &client, proxy_interface.Pass());
- flow.GetCertificate("test", mock_callback);
+ flow.GetCertificate(PROFILE_ENTERPRISE_USER_CERTIFICATE, true, mock_callback);
Run();
}
TEST_F(AttestationFlowTest, GetCertificate_FailIsEnrolled) {
- // We're not expecting any server calls in this case; StrictMock will verify.
+ // We're not expecting any async calls in this case; StrictMock will verify.
StrictMock<cryptohome::MockAsyncMethodCaller> async_caller;
chromeos::MockCryptohomeClient client;
@@ -326,7 +341,81 @@ TEST_F(AttestationFlowTest, GetCertificate_FailIsEnrolled) {
scoped_ptr<ServerProxy> proxy_interface(proxy.release());
AttestationFlow flow(&async_caller, &client, proxy_interface.Pass());
- flow.GetCertificate("test", mock_callback);
+ flow.GetCertificate(PROFILE_ENTERPRISE_USER_CERTIFICATE, true, mock_callback);
+ Run();
+}
+
+TEST_F(AttestationFlowTest, GetCertificate_CheckExisting) {
+ StrictMock<cryptohome::MockAsyncMethodCaller> async_caller;
+ async_caller.SetUp(true, cryptohome::MOUNT_ERROR_NONE);
+ int options = CERTIFICATE_INCLUDE_DEVICE_STATE;
+ EXPECT_CALL(async_caller, AsyncTpmAttestationCreateCertRequest(options, _))
+ .Times(1);
+ std::string fake_cert_response =
+ cryptohome::MockAsyncMethodCaller::kFakeAttestationCertRequest;
+ fake_cert_response += "_response";
+ EXPECT_CALL(async_caller,
+ AsyncTpmAttestationFinishCertRequest(fake_cert_response,
+ KEY_USER,
+ kEnterpriseUserKey,
+ _))
+ .Times(1);
+
+ chromeos::MockCryptohomeClient client;
+ EXPECT_CALL(client, TpmAttestationIsEnrolled(_))
+ .WillRepeatedly(Invoke(DBusCallbackTrue));
+ EXPECT_CALL(client,
+ TpmAttestationDoesKeyExist(KEY_USER, kEnterpriseUserKey, _))
+ .WillRepeatedly(WithArgs<2>(Invoke(DBusCallbackFalse)));
+
+ scoped_ptr<MockServerProxy> proxy(new StrictMock<MockServerProxy>());
+ proxy->DeferToFake(true);
+ EXPECT_CALL(*proxy, SendCertificateRequest(
+ cryptohome::MockAsyncMethodCaller::kFakeAttestationCertRequest,
+ _)).Times(1);
+
+ StrictMock<MockObserver> observer;
+ EXPECT_CALL(observer, MockCertificateCallback(
+ true,
+ cryptohome::MockAsyncMethodCaller::kFakeAttestationCert)).Times(1);
+ AttestationFlow::CertificateCallback mock_callback = base::Bind(
+ &MockObserver::MockCertificateCallback,
+ base::Unretained(&observer));
+
+ scoped_ptr<ServerProxy> proxy_interface(proxy.release());
+ AttestationFlow flow(&async_caller, &client, proxy_interface.Pass());
+ flow.GetCertificate(PROFILE_ENTERPRISE_USER_CERTIFICATE,
+ false, mock_callback);
+ Run();
+}
+
+TEST_F(AttestationFlowTest, GetCertificate_AlreadyExists) {
+ // We're not expecting any async calls in this case; StrictMock will verify.
+ StrictMock<cryptohome::MockAsyncMethodCaller> async_caller;
+
+ chromeos::MockCryptohomeClient client;
+ EXPECT_CALL(client, TpmAttestationIsEnrolled(_))
+ .WillRepeatedly(Invoke(DBusCallbackTrue));
+ EXPECT_CALL(client,
+ TpmAttestationDoesKeyExist(KEY_USER, kEnterpriseUserKey, _))
+ .WillRepeatedly(WithArgs<2>(Invoke(DBusCallbackTrue)));
+ EXPECT_CALL(client,
+ TpmAttestationGetCertificate(KEY_USER, kEnterpriseUserKey, _))
+ .WillRepeatedly(WithArgs<2>(Invoke(FakeDBusData("fake_cert"))));
+
+ // We're not expecting any server calls in this case; StrictMock will verify.
+ scoped_ptr<MockServerProxy> proxy(new StrictMock<MockServerProxy>());
+
+ StrictMock<MockObserver> observer;
+ EXPECT_CALL(observer, MockCertificateCallback(true, "fake_cert")).Times(1);
+ AttestationFlow::CertificateCallback mock_callback = base::Bind(
+ &MockObserver::MockCertificateCallback,
+ base::Unretained(&observer));
+
+ scoped_ptr<ServerProxy> proxy_interface(proxy.release());
+ AttestationFlow flow(&async_caller, &client, proxy_interface.Pass());
+ flow.GetCertificate(PROFILE_ENTERPRISE_USER_CERTIFICATE,
+ false, mock_callback);
Run();
}
diff --git a/chromeos/attestation/mock_attestation_flow.h b/chromeos/attestation/mock_attestation_flow.h
index 59462c54..bda8a72 100644
--- a/chromeos/attestation/mock_attestation_flow.h
+++ b/chromeos/attestation/mock_attestation_flow.h
@@ -65,7 +65,8 @@ class MockAttestationFlow : public AttestationFlow {
MockAttestationFlow();
virtual ~MockAttestationFlow();
- MOCK_METHOD2(GetCertificate, void(const std::string&,
+ MOCK_METHOD3(GetCertificate, void(AttestationCertificateProfile,
+ bool,
const CertificateCallback&));
};