attestation: Implemented CreateGoogleAttestedKey.

Only mock dependencies currently exist so this code is limited to unit
tests.

BUG=brillo:737
TEST=unit

Change-Id: Ia23d0b6afdde9d7ce70a1363d143d562236f2fff
Reviewed-on: https://chromium-review.googlesource.com/265866
Reviewed-by: Darren Krahn <dkrahn@chromium.org>
Commit-Queue: Darren Krahn <dkrahn@chromium.org>
Tested-by: Darren Krahn <dkrahn@chromium.org>
diff --git a/attestation.gyp b/attestation.gyp
index 11e9f0e..c0e71c3 100644
--- a/attestation.gyp
+++ b/attestation.gyp
@@ -101,13 +101,19 @@
           'variables': {
             'deps': [
               'libchrome-test-<(libbase_ver)',
+              'libchromeos-test-<(libbase_ver)',
             ],
           },
           'sources': [
             'attestation_testrunner.cc',
             'client/dbus_proxy_test.cc',
+            'server/attestation_service_test.cc',
             'server/database_impl_test.cc',
             'server/dbus_service_test.cc',
+            'server/mock_crypto_utility.cc',
+            'server/mock_database.cc',
+            'server/mock_key_store.cc',
+            'server/mock_tpm_utility.cc',
           ],
           'dependencies': [
             'client_library',
diff --git a/client/dbus_proxy.cc b/client/dbus_proxy.cc
index 9f507a2..bde48e9 100644
--- a/client/dbus_proxy.cc
+++ b/client/dbus_proxy.cc
@@ -41,7 +41,9 @@
     KeyType key_type,
     KeyUsage key_usage,
     CertificateProfile certificate_profile,
-    const base::Callback<CreateGoogleAttestedKeyCallback>& callback) {
+    const std::string& username,
+    const std::string& origin,
+    const CreateGoogleAttestedKeyCallback& callback) {
   attestation::CreateGoogleAttestedKeyRequest request;
   request.set_key_label(key_label);
   request.set_key_type(key_type);
@@ -49,12 +51,12 @@
   request.set_certificate_profile(certificate_profile);
   auto on_success = [callback](
       const attestation::CreateGoogleAttestedKeyReply& reply) {
-    callback.Run(reply.status(),
-                 reply.certificate_chain(),
-                 reply.server_error());
+    callback.Run(reply.certificate_chain(),
+                 reply.server_error(),
+                 reply.status());
   };
   auto on_error = [callback](chromeos::Error* error) {
-    callback.Run(NOT_AVAILABLE, std::string(), std::string());
+    callback.Run(std::string(), std::string(), STATUS_NOT_AVAILABLE);
   };
   chromeos::dbus_utils::CallMethodWithTimeout(
       kDBusTimeoutMS,
diff --git a/client/dbus_proxy.h b/client/dbus_proxy.h
index 7d3d135..c8197ba 100644
--- a/client/dbus_proxy.h
+++ b/client/dbus_proxy.h
@@ -33,7 +33,9 @@
       KeyType key_type,
       KeyUsage key_usage,
       CertificateProfile certificate_profile,
-      const base::Callback<CreateGoogleAttestedKeyCallback>& callback) override;
+      const std::string& username,
+      const std::string& origin,
+      const CreateGoogleAttestedKeyCallback& callback) override;
 
   // Useful for testing.
   void set_object_proxy(dbus::ObjectProxy* object_proxy) {
diff --git a/client/dbus_proxy_test.cc b/client/dbus_proxy_test.cc
index bc1920a..a48c1c5 100644
--- a/client/dbus_proxy_test.cc
+++ b/client/dbus_proxy_test.cc
@@ -49,7 +49,7 @@
         dbus::Response::CreateEmpty();
     dbus::MessageWriter writer(response.get());
     CreateGoogleAttestedKeyReply reply_proto;
-    reply_proto.set_status(SUCCESS);
+    reply_proto.set_status(STATUS_SUCCESS);
     reply_proto.set_certificate_chain("certificate");
     reply_proto.set_server_error("server_error");
     writer.AppendProtoAsArrayOfBytes(reply_proto);
@@ -60,16 +60,19 @@
       .WillOnce(WithArgs<0, 2>(Invoke(fake_dbus_call)));
 
   // Set expectations on the outputs.
-  auto callback = [](AttestationStatus status,
-                     const std::string& certificate,
-                     const std::string& server_error) {
-    EXPECT_EQ(SUCCESS, status);
+  int callback_count = 0;
+  auto callback = [&callback_count](const std::string& certificate,
+                                    const std::string& server_error,
+                                    AttestationStatus status) {
+    callback_count++;
+    EXPECT_EQ(STATUS_SUCCESS, status);
     EXPECT_EQ("certificate", certificate);
     EXPECT_EQ("server_error", server_error);
   };
   proxy_.CreateGoogleAttestedKey("label", KEY_TYPE_ECC, KEY_USAGE_SIGN,
-                                 ENTERPRISE_MACHINE_CERTIFICATE,
+                                 ENTERPRISE_MACHINE_CERTIFICATE, "", "",
                                  base::Bind(callback));
+  EXPECT_EQ(1, callback_count);
 }
 
 }  // namespace attestation
diff --git a/client/main.cc b/client/main.cc
index b97e9a6..a432455 100644
--- a/client/main.cc
+++ b/client/main.cc
@@ -73,10 +73,10 @@
   }
 
   void HandleCreateGoogleAttestedKeyReply(
-      attestation::AttestationStatus status,
       const std::string& certificate,
-      const std::string& server_error_details) {
-    if (status == attestation::SUCCESS) {
+      const std::string& server_error_details,
+      attestation::AttestationStatus status) {
+    if (status == attestation::STATUS_SUCCESS) {
       printf("Success!\n");
     } else {
       printf("Error occurred: %d.\n", status);
@@ -93,6 +93,8 @@
         attestation::KEY_TYPE_RSA,
         attestation::KEY_USAGE_SIGN,
         attestation::ENTERPRISE_MACHINE_CERTIFICATE,
+        "",  // username
+        "",  // origin
         base::Bind(&ClientLoop::HandleCreateGoogleAttestedKeyReply,
                    weak_factory_.GetWeakPtr()));
   }
diff --git a/common/attestation_interface.h b/common/attestation_interface.h
index 58a52db..bf68121 100644
--- a/common/attestation_interface.h
+++ b/common/attestation_interface.h
@@ -35,17 +35,22 @@
   // The Google Attestation CA root certificate is well-known and not included.
   // If the CA refuses to issue a certificate, |status| will be
   // REQUEST_DENIED_BY_CA and |server_error_details| will contain an error
-  // message from the CA.
+  // message from the CA. On success both the key and certificate are associated
+  // with |username|, which must be a canonical email address or the empty
+  // string (in which case it will be associated to the device). The |origin|
+  // parameter is passed to the CA; it is required by some certificate profiles.
   using CreateGoogleAttestedKeyCallback =
-      void(AttestationStatus status,
-           const std::string& certificate_chain,
-           const std::string& server_error_details);
+      base::Callback<void(const std::string& certificate_chain,
+                          const std::string& server_error_details,
+                          AttestationStatus status)>;
   virtual void CreateGoogleAttestedKey(
       const std::string& key_label,
       KeyType key_type,
       KeyUsage key_usage,
       CertificateProfile certificate_profile,
-      const base::Callback<CreateGoogleAttestedKeyCallback>& callback) = 0;
+      const std::string& username,
+      const std::string& origin,
+      const CreateGoogleAttestedKeyCallback& callback) = 0;
 };
 
 }  // namespace attestation
diff --git a/common/interface.proto b/common/interface.proto
index b7337f9..8d6b667 100644
--- a/common/interface.proto
+++ b/common/interface.proto
@@ -9,13 +9,14 @@
 import "common.proto";
 
 enum AttestationStatus {
-  SUCCESS = 0;
-  UNEXPECTED_DEVICE_ERROR = 1;
-  NOT_AVAILABLE = 2;
-  NOT_READY = 3;
-  NOT_ALLOWED = 4;
-  INVALID_PARAMETER = 5;
-  REQUEST_DENIED_BY_CA = 6;
+  STATUS_SUCCESS = 0;
+  STATUS_UNEXPECTED_DEVICE_ERROR = 1;
+  STATUS_NOT_AVAILABLE = 2;
+  STATUS_NOT_READY = 3;
+  STATUS_NOT_ALLOWED = 4;
+  STATUS_INVALID_PARAMETER = 5;
+  STATUS_REQUEST_DENIED_BY_CA = 6;
+  STATUS_CA_NOT_AVAILABLE = 7;
 }
 
 // Describes key type.
@@ -37,6 +38,13 @@
   optional KeyUsage key_usage = 3;
   // Describes the certificate to be requested of the CA.
   optional CertificateProfile certificate_profile = 4;
+  // Provided if the new key should be accessible only by a particular user. If
+  // this field is not set or is the empty string, the key will be accessible
+  // system-wide.
+  optional string username = 5;
+  // If the |certificate_profile| is intended to be bound to a particular origin
+  // this field specifies the origin. For most profiles this is not required.
+  optional string origin = 6;
 }
 
 message CreateGoogleAttestedKeyReply {
diff --git a/common/mock_attestation_interface.h b/common/mock_attestation_interface.h
index 2dcca1f..5b8c485 100644
--- a/common/mock_attestation_interface.h
+++ b/common/mock_attestation_interface.h
@@ -19,12 +19,14 @@
   virtual ~MockAttestationInterface() = default;
 
   MOCK_METHOD0(Initialize, bool());
-  MOCK_METHOD5(CreateGoogleAttestedKey, void(
+  MOCK_METHOD7(CreateGoogleAttestedKey, void(
       const std::string&,
       KeyType,
       KeyUsage,
       CertificateProfile,
-      const base::Callback<CreateGoogleAttestedKeyCallback>&));
+      const std::string&,
+      const std::string&,
+      const CreateGoogleAttestedKeyCallback&));
 };
 
 }  // namespace attestation
diff --git a/server/attestation_service.cc b/server/attestation_service.cc
index 1ecea6b..3c65c2a 100644
--- a/server/attestation_service.cc
+++ b/server/attestation_service.cc
@@ -4,18 +4,48 @@
 
 #include "attestation/server/attestation_service.h"
 
-#include <base/callback.h>
+#include <string>
 
+#include <base/callback.h>
+#include <chromeos/bind_lambda.h>
+#include <chromeos/data_encoding.h>
+#include <chromeos/http/http_utils.h>
+#include <chromeos/mime_utils.h>
+#include <crypto/sha2.h>
+
+#include "attestation/common/attestation_ca.pb.h"
+#include "attestation/common/database.pb.h"
 #include "attestation/server/database_impl.h"
 
+namespace {
+
+#ifndef USE_TEST_ACA
+const char kACAWebOrigin[] = "https://chromeos-ca.gstatic.com";
+#else
+const char kACAWebOrigin[] = "https://asbestos-qa.corp.google.com";
+#endif
+const size_t kNonceSize = 20;  // As per TPM_NONCE definition.
+const int kNumTemporalValues = 5;
+
+}  // namespace
+
 namespace attestation {
 
+AttestationService::AttestationService()
+    : attestation_ca_origin_(kACAWebOrigin),
+      weak_factory_(this) {}
+
 bool AttestationService::Initialize() {
+  LOG(INFO) << "Attestation service started.";
+  worker_thread_.reset(new base::Thread("Attestation Service Worker"));
+  worker_thread_->Start();
   if (!database_) {
-    default_database_.reset(new DatabaseImpl(crypto_));
+    default_database_.reset(new DatabaseImpl(crypto_utility_));
+    if (!default_database_->Initialize()) {
+      LOG(WARNING) << "Creating new attestation database.";
+    }
     database_ = default_database_.get();
   }
-  LOG(INFO) << "Attestation service started.";
   return true;
 }
 
@@ -24,8 +54,522 @@
     KeyType key_type,
     KeyUsage key_usage,
     CertificateProfile certificate_profile,
-    const base::Callback<CreateGoogleAttestedKeyCallback>& callback) {
-  callback.Run(NOT_AVAILABLE, std::string(), std::string());
+    const std::string& username,
+    const std::string& origin,
+    const CreateGoogleAttestedKeyCallback& callback) {
+  auto result = std::make_shared<CreateGoogleAttestedKeyTaskResult>();
+  base::Closure task = base::Bind(
+      &AttestationService::CreateGoogleAttestedKeyTask,
+      base::Unretained(this),
+      key_label,
+      key_type,
+      key_usage,
+      certificate_profile,
+      username,
+      origin,
+      result);
+  base::Closure reply = base::Bind(
+      &AttestationService::CreateGoogleAttestedKeyTaskCallback,
+      GetWeakPtr(),
+      callback,
+      result);
+  worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, task, reply);
+}
+
+void AttestationService::CreateGoogleAttestedKeyTask(
+    const std::string& key_label,
+    KeyType key_type,
+    KeyUsage key_usage,
+    CertificateProfile certificate_profile,
+    const std::string& username,
+    const std::string& origin,
+    const std::shared_ptr<CreateGoogleAttestedKeyTaskResult>& result) {
+  LOG(INFO) << "Creating attested key: " << key_label;
+  if (!IsPreparedForEnrollment()) {
+    LOG(ERROR) << "Attestation: TPM is not ready.";
+    result->status = STATUS_NOT_READY;
+    return;
+  }
+  if (!IsEnrolled()) {
+    std::string enroll_request;
+    if (!CreateEnrollRequest(&enroll_request)) {
+      result->status = STATUS_UNEXPECTED_DEVICE_ERROR;
+      return;
+    }
+    std::string enroll_reply;
+    if (!SendACARequestAndBlock(kEnroll,
+                                enroll_request,
+                                &enroll_reply)) {
+      result->status = STATUS_CA_NOT_AVAILABLE;
+      return;
+    }
+    std::string server_error;
+    if (!FinishEnroll(enroll_reply, &result->server_error_details)) {
+      result->status = STATUS_REQUEST_DENIED_BY_CA;
+      return;
+    }
+  }
+  if (!FindKeyByLabel(username, key_label, nullptr)) {
+    if (!CreateKey(username, key_label, key_type, key_usage)) {
+      result->status = STATUS_UNEXPECTED_DEVICE_ERROR;
+      return;
+    }
+  }
+  std::string certificate_request;
+  std::string message_id;
+  if (!CreateCertificateRequest(username,
+                                key_label,
+                                certificate_profile,
+                                origin,
+                                &certificate_request,
+                                &message_id)) {
+    result->status = STATUS_UNEXPECTED_DEVICE_ERROR;
+    return;
+  }
+  std::string certificate_reply;
+  if (!SendACARequestAndBlock(kGetCertificate,
+                              certificate_request,
+                              &certificate_reply)) {
+    result->status = STATUS_CA_NOT_AVAILABLE;
+    return;
+  }
+  std::string certificate_chain;
+  std::string server_error;
+  if (!FinishCertificateRequest(certificate_reply,
+                                username,
+                                key_label,
+                                message_id,
+                                &result->certificate_chain,
+                                &result->server_error_details)) {
+    result->status = STATUS_REQUEST_DENIED_BY_CA;
+    return;
+  }
+}
+
+void AttestationService::CreateGoogleAttestedKeyTaskCallback(
+    const CreateGoogleAttestedKeyCallback& callback,
+    const std::shared_ptr<CreateGoogleAttestedKeyTaskResult>& result) {
+  callback.Run(result->certificate_chain,
+               result->server_error_details,
+               result->status);
+}
+
+bool AttestationService::IsPreparedForEnrollment() {
+  if (!tpm_utility_->IsTpmReady()) {
+    return false;
+  }
+  auto database_pb = database_->GetProtobuf();
+  if (!database_pb.has_credentials()) {
+    return false;
+  }
+  return (database_pb.credentials().has_endorsement_credential() ||
+          database_pb.credentials()
+              .has_default_encrypted_endorsement_credential());
+}
+
+bool AttestationService::IsEnrolled() {
+  auto database_pb = database_->GetProtobuf();
+  return database_pb.has_identity_key() &&
+         database_pb.identity_key().has_identity_credential();
+}
+
+bool AttestationService::CreateEnrollRequest(std::string* enroll_request) {
+  if (!IsPreparedForEnrollment()) {
+    LOG(ERROR) << __func__ << ": Enrollment is not possible, attestation data "
+               << "does not exist.";
+    return false;
+  }
+  auto database_pb = database_->GetProtobuf();
+  AttestationEnrollmentRequest request_pb;
+  *request_pb.mutable_encrypted_endorsement_credential() =
+      database_pb.credentials().default_encrypted_endorsement_credential();
+  request_pb.set_identity_public_key(
+      database_pb.identity_binding().identity_public_key());
+  *request_pb.mutable_pcr0_quote() = database_pb.pcr0_quote();
+  *request_pb.mutable_pcr1_quote() = database_pb.pcr1_quote();
+  if (!request_pb.SerializeToString(enroll_request)) {
+    LOG(ERROR) << __func__ << ": Failed to serialize protobuf.";
+    return false;
+  }
+  return true;
+}
+
+bool AttestationService::FinishEnroll(const std::string& enroll_response,
+                                      std::string* server_error) {
+  if (!tpm_utility_->IsTpmReady()) {
+    return false;
+  }
+  AttestationEnrollmentResponse response_pb;
+  if (!response_pb.ParseFromString(enroll_response)) {
+    LOG(ERROR) << __func__ << ": Failed to parse response from CA.";
+    return false;
+  }
+  if (response_pb.status() != OK) {
+    *server_error = response_pb.detail();
+    LOG(ERROR) << __func__ << ": Error received from CA: "
+               << response_pb.detail();
+    return false;
+  }
+  std::string credential;
+  auto database_pb = database_->GetProtobuf();
+  if (!tpm_utility_->ActivateIdentity(
+      database_pb.delegate().blob(),
+      database_pb.delegate().secret(),
+      database_pb.identity_key().identity_key_blob(),
+      response_pb.encrypted_identity_credential().asym_ca_contents(),
+      response_pb.encrypted_identity_credential().sym_ca_attestation(),
+      &credential)) {
+    LOG(ERROR) << __func__ << ": Failed to activate identity.";
+    return false;
+  }
+  database_->GetMutableProtobuf()->mutable_identity_key()->
+      set_identity_credential(credential);
+  if (!database_->SaveChanges()) {
+    LOG(ERROR) << __func__ << ": Failed to persist database changes.";
+    return false;
+  }
+  LOG(INFO) << "Attestation: Enrollment complete.";
+  return true;
+}
+
+bool AttestationService::CreateCertificateRequest(
+    const std::string& username,
+    const std::string& key_label,
+    CertificateProfile profile,
+    const std::string& origin,
+    std::string* certificate_request,
+    std::string* message_id) {
+  if (!tpm_utility_->IsTpmReady()) {
+    return false;
+  }
+  if (!IsEnrolled()) {
+    LOG(ERROR) << __func__ << ": Device is not enrolled for attestation.";
+    return false;
+  }
+  AttestationCertificateRequest request_pb;
+  if (!crypto_utility_->GetRandom(kNonceSize, message_id)) {
+    LOG(ERROR) << __func__ << ": GetRandom(message_id) failed.";
+    return false;
+  }
+  request_pb.set_message_id(*message_id);
+  auto database_pb = database_->GetProtobuf();
+  request_pb.set_identity_credential(
+      database_pb.identity_key().identity_credential());
+  request_pb.set_profile(profile);
+  if (!origin.empty() &&
+      (profile == CONTENT_PROTECTION_CERTIFICATE_WITH_STABLE_ID)) {
+    request_pb.set_origin(origin);
+    request_pb.set_temporal_index(ChooseTemporalIndex(username, origin));
+  }
+  std::string public_key;
+  std::string key_info;
+  std::string proof;
+  if (!CertifyKey(username, key_label, &public_key, &key_info, &proof)) {
+    return false;
+  }
+  request_pb.set_certified_public_key(public_key);
+  request_pb.set_certified_key_info(key_info);
+  request_pb.set_certified_key_proof(proof);
+  if (!request_pb.SerializeToString(certificate_request)) {
+    LOG(ERROR) << __func__ << ": Failed to serialize protobuf.";
+    return false;
+  }
+  return true;
+}
+
+bool AttestationService::FinishCertificateRequest(
+    const std::string& certificate_response,
+    const std::string& username,
+    const std::string& key_label,
+    const std::string& message_id,
+    std::string* certificate_chain,
+    std::string* server_error) {
+  if (!tpm_utility_->IsTpmReady()) {
+    return false;
+  }
+  AttestationCertificateResponse response_pb;
+  if (!response_pb.ParseFromString(certificate_response)) {
+    LOG(ERROR) << __func__ << ": Failed to parse response from Privacy CA.";
+    return false;
+  }
+  if (response_pb.status() != OK) {
+    *server_error = response_pb.detail();
+    LOG(ERROR) << __func__ << ": Error received from Privacy CA: "
+               << response_pb.detail();
+    return false;
+  }
+  if (message_id != response_pb.message_id()) {
+    LOG(ERROR) << __func__ << ": Message ID mismatch.";
+    return false;
+  }
+  CertifiedKey certified_key_pb;
+  if (!FindKeyByLabel(username, key_label, &certified_key_pb)) {
+    LOG(ERROR) << __func__ << ": Key not found.";
+    return false;
+  }
+
+  // Finish populating the CertifiedKey protobuf and store it.
+  certified_key_pb.set_certified_key_credential(
+      response_pb.certified_key_credential());
+  certified_key_pb.set_intermediate_ca_cert(response_pb.intermediate_ca_cert());
+  certified_key_pb.mutable_additional_intermediate_ca_cert()->MergeFrom(
+      response_pb.additional_intermediate_ca_cert());
+  if (!SaveKey(username, key_label, certified_key_pb)) {
+    return false;
+  }
+  LOG(INFO) << "Attestation: Certified key credential received and stored.";
+  *certificate_chain = CreatePEMCertificateChain(certified_key_pb);
+  return true;
+}
+
+bool AttestationService::SendACARequestAndBlock(ACARequestType request_type,
+                                                const std::string& request,
+                                                std::string* reply) {
+  std::shared_ptr<chromeos::http::Transport> transport = http_transport_;
+  if (!transport) {
+    transport = chromeos::http::Transport::CreateDefault();
+  }
+  std::unique_ptr<chromeos::http::Response> response = PostBinaryAndBlock(
+      GetACAURL(request_type),
+      request.data(),
+      request.size(),
+      chromeos::mime::application::kOctet_stream,
+      {},  // headers
+      transport,
+      nullptr);  // error
+  if (!response || !response->IsSuccessful()) {
+    LOG(ERROR) << "HTTP request to Attestation CA failed.";
+    return false;
+  }
+  *reply = response->ExtractDataAsString();
+  return true;
+}
+
+bool AttestationService::FindKeyByLabel(const std::string& username,
+                                        const std::string& key_label,
+                                        CertifiedKey* key) {
+  if (!username.empty()) {
+    std::string key_data;
+    if (!key_store_->Read(username, key_label, &key_data)) {
+      LOG(INFO) << "Key not found: " << key_label;
+      return false;
+    }
+    if (key && !key->ParseFromString(key_data)) {
+      LOG(ERROR) << "Failed to parse key: " << key_label;
+      return false;
+    }
+    return true;
+  }
+  auto database_pb = database_->GetProtobuf();
+  for (int i = 0; i < database_pb.device_keys_size(); ++i) {
+    if (database_pb.device_keys(i).key_name() == key_label) {
+      *key = database_pb.device_keys(i);
+      return true;
+    }
+  }
+  LOG(INFO) << "Key not found: " << key_label;
+  return false;
+}
+
+bool AttestationService::CreateKey(const std::string& username,
+                                   const std::string& key_label,
+                                   KeyType key_type,
+                                   KeyUsage key_usage) {
+  std::string key_blob;
+  std::string public_key;
+  if (!tpm_utility_->GenerateKey(key_type, key_usage, &key_blob, &public_key)) {
+    return false;
+  }
+  CertifiedKey key;
+  key.set_key_blob(key_blob);
+  key.set_public_key(public_key);
+  key.set_key_name(key_label);
+  return SaveKey(username, key_label, key);
+}
+
+bool AttestationService::SaveKey(const std::string& username,
+                                 const std::string& key_label,
+                                 const CertifiedKey& key) {
+  if (!username.empty()) {
+    std::string key_data;
+    if (!key.SerializeToString(&key_data)) {
+      LOG(ERROR) << __func__ << ": Failed to serialize protobuf.";
+      return false;
+    }
+    if (!key_store_->Write(username, key_label, key_data)) {
+      LOG(ERROR) << __func__ << ": Failed to store certified key for user.";
+      return false;
+    }
+  } else {
+    if (!AddDeviceKey(key_label, key)) {
+      LOG(ERROR) << __func__ << ": Failed to store certified key for device.";
+      return false;
+    }
+  }
+  return true;
+}
+
+void AttestationService::DeleteKey(const std::string& username,
+                                   const std::string& key_label) {
+  if (!username.empty()) {
+    key_store_->Delete(username, key_label);
+  } else {
+    RemoveDeviceKey(key_label);
+  }
+}
+
+bool AttestationService::AddDeviceKey(const std::string& key_label,
+                                      const CertifiedKey& key) {
+  // If a key by this name already exists, reuse the field.
+  auto* database_pb = database_->GetMutableProtobuf();
+  bool found = false;
+  for (int i = 0; i < database_pb->device_keys_size(); ++i) {
+    if (database_pb->device_keys(i).key_name() == key_label) {
+      found = true;
+      *database_pb->mutable_device_keys(i) = key;
+      break;
+    }
+  }
+  if (!found)
+    *database_pb->add_device_keys() = key;
+  return database_->SaveChanges();
+}
+
+void AttestationService::RemoveDeviceKey(const std::string& key_label) {
+  auto* database_pb = database_->GetMutableProtobuf();
+  bool found = false;
+  for (int i = 0; i < database_pb->device_keys_size(); ++i) {
+    if (database_pb->device_keys(i).key_name() == key_label) {
+      found = true;
+      int last = database_pb->device_keys_size() - 1;
+      if (i < last) {
+        database_pb->mutable_device_keys()->SwapElements(i, last);
+      }
+      database_pb->mutable_device_keys()->RemoveLast();
+      break;
+    }
+  }
+  if (found) {
+    if (!database_->SaveChanges()) {
+      LOG(WARNING) << __func__ << ": Failed to persist key deletion.";
+    }
+  }
+}
+
+bool AttestationService::CertifyKey(const std::string& username,
+                                    const std::string& key_label,
+                                    std::string* public_key_tpm_format,
+                                    std::string* key_info,
+                                    std::string* proof) {
+  CertifiedKey key;
+  if (!FindKeyByLabel(username, key_label, &key)) {
+    LOG(ERROR) << __func__ << ": Failed to certify key - key not found.";
+    return false;
+  }
+
+  std::string nonce;
+  if (!crypto_utility_->GetRandom(kNonceSize, &nonce)) {
+    LOG(ERROR) << __func__ << ": GetRandom(nonce) failed.";
+    return false;
+  }
+  auto database_pb = database_->GetProtobuf();
+  return tpm_utility_->CertifyKey(
+      key.key_blob(),
+      database_pb.identity_key().identity_key_blob(),
+      nonce,
+      public_key_tpm_format,
+      key_info,
+      proof);
+}
+
+std::string AttestationService::CreatePEMCertificateChain(
+    const CertifiedKey& key) {
+  if (key.certified_key_credential().empty()) {
+    LOG(WARNING) << "Certificate is empty.";
+    return std::string();
+  }
+  std::string pem = CreatePEMCertificate(key.certified_key_credential());
+  if (!key.intermediate_ca_cert().empty()) {
+    pem += "\n";
+    pem += CreatePEMCertificate(key.intermediate_ca_cert());
+  }
+  for (int i = 0; i < key.additional_intermediate_ca_cert_size(); ++i) {
+    pem += "\n";
+    pem += CreatePEMCertificate(key.additional_intermediate_ca_cert(i));
+  }
+  return pem;
+}
+
+std::string AttestationService::CreatePEMCertificate(
+    const std::string& certificate) {
+  const char kBeginCertificate[] = "-----BEGIN CERTIFICATE-----\n";
+  const char kEndCertificate[] = "-----END CERTIFICATE-----";
+
+  std::string pem = kBeginCertificate;
+  pem += chromeos::data_encoding::Base64EncodeWrapLines(certificate);
+  pem += kEndCertificate;
+  return pem;
+}
+
+
+int AttestationService::ChooseTemporalIndex(const std::string& user,
+                                            const std::string& origin) {
+  std::string user_hash = crypto::SHA256HashString(user);
+  std::string origin_hash = crypto::SHA256HashString(origin);
+  int histogram[kNumTemporalValues] = {};
+  auto database_pb = database_->GetProtobuf();
+  for (int i = 0; i < database_pb.temporal_index_record_size(); ++i) {
+    const AttestationDatabase::TemporalIndexRecord& record =
+        database_pb.temporal_index_record(i);
+    // Ignore out-of-range index values.
+    if (record.temporal_index() < 0 ||
+        record.temporal_index() >= kNumTemporalValues)
+      continue;
+    if (record.origin_hash() == origin_hash) {
+      if (record.user_hash() == user_hash) {
+        // We've previously chosen this index for this user, reuse it.
+        return record.temporal_index();
+      } else {
+        // We've previously chosen this index for another user.
+        ++histogram[record.temporal_index()];
+      }
+    }
+  }
+  int least_used_index = 0;
+  for (int i = 1; i < kNumTemporalValues; ++i) {
+    if (histogram[i] < histogram[least_used_index])
+      least_used_index = i;
+  }
+  if (histogram[least_used_index] > 0) {
+    LOG(WARNING) << "Unique origin-specific identifiers have been exhausted.";
+  }
+  // Record our choice for later reference.
+  AttestationDatabase::TemporalIndexRecord* new_record =
+      database_pb.add_temporal_index_record();
+  new_record->set_origin_hash(origin_hash);
+  new_record->set_user_hash(user_hash);
+  new_record->set_temporal_index(least_used_index);
+  database_->SaveChanges();
+  return least_used_index;
+}
+
+std::string AttestationService::GetACAURL(ACARequestType request_type) const {
+  std::string url = attestation_ca_origin_;
+  switch (request_type) {
+    case kEnroll:
+      url += "/enroll";
+      break;
+    case kGetCertificate:
+      url += "/sign";
+      break;
+    default:
+      NOTREACHED();
+  }
+  return url;
+}
+
+base::WeakPtr<AttestationService> AttestationService::GetWeakPtr() {
+  return weak_factory_.GetWeakPtr();
 }
 
 }  // namespace attestation
diff --git a/server/attestation_service.h b/server/attestation_service.h
index 0bf2d61..04dffe1 100644
--- a/server/attestation_service.h
+++ b/server/attestation_service.h
@@ -10,22 +10,45 @@
 #include <memory>
 #include <string>
 
+#include <base/callback.h>
 #include <base/macros.h>
+#include <base/memory/weak_ptr.h>
+#include <base/threading/thread.h>
+#include <chromeos/bind_lambda.h>
+#include <chromeos/http/http_transport.h>
 
 #include "attestation/server/crypto_utility.h"
 #include "attestation/server/database.h"
+#include "attestation/server/database_impl.h"
+#include "attestation/server/key_store.h"
+#include "attestation/server/tpm_utility.h"
 
 namespace attestation {
 
 // An implementation of AttestationInterface for the core attestation service.
+// Access to TPM, network and local file-system resources occurs asynchronously
+// with the exception of Initialize(). All methods must be called on the same
+// thread that originally called Initialize().
 // Usage:
 //   std::unique_ptr<AttestationInterface> attestation =
 //       new AttestationService();
 //   CHECK(attestation->Initialize());
 //   attestation->CreateGoogleAttestedKey(...);
+//
+// THREADING NOTES:
+// This class runs a worker thread and delegates all calls to it. This keeps the
+// public methods non-blocking while allowing complex implementation details
+// with dependencies on the TPM, network, and filesystem to be coded in a more
+// readable way. It also serves to serialize method execution which reduces
+// complexity with TPM state.
+//
+// Tasks that run on the worker thread are bound with base::Unretained which is
+// safe because the thread is owned by this class (so it is guaranteed not to
+// process a task after destruction). Weak pointers are used to post replies
+// back to the main thread.
 class AttestationService : public AttestationInterface {
  public:
-  AttestationService() = default;
+  AttestationService();
   ~AttestationService() override = default;
 
   // AttestationInterface methods.
@@ -35,17 +58,187 @@
       KeyType key_type,
       KeyUsage key_usage,
       CertificateProfile certificate_profile,
-      const base::Callback<CreateGoogleAttestedKeyCallback>& callback) override;
+      const std::string& username,
+      const std::string& origin,
+      const CreateGoogleAttestedKeyCallback& callback) override;
 
-  // Useful for testing.
+  // Mutators useful for testing.
+  void set_crypto_utility(CryptoUtility* crypto_utility) {
+    crypto_utility_ = crypto_utility;
+  }
+
   void set_database(Database* database) {
     database_ = database;
   }
 
+  void set_http_transport(
+      const std::shared_ptr<chromeos::http::Transport>& transport) {
+    http_transport_ = transport;
+  }
+
+  void set_key_store(KeyStore* key_store) {
+    key_store_ = key_store;
+  }
+
+  void set_tpm_utility(TpmUtility* tpm_utility) {
+    tpm_utility_ = tpm_utility;
+  }
+
+  // So tests don't need to duplicate URL decisions.
+  const std::string& attestation_ca_origin() {
+    return attestation_ca_origin_;
+  }
+
  private:
-  CryptoUtility* crypto_;
+  enum ACARequestType {
+    kEnroll,          // Enrolls a device, certifying an identity key.
+    kGetCertificate,  // Issues a certificate for a TPM-backed key.
+  };
+
+  struct CreateGoogleAttestedKeyTaskResult {
+      AttestationStatus status{STATUS_SUCCESS};
+      std::string certificate_chain;
+      std::string server_error_details;
+  };
+
+  // A synchronous implementation of CreateGoogleAttestedKey appropriate to run
+  // on the worker thread.
+  void CreateGoogleAttestedKeyTask(
+      const std::string& key_label,
+      KeyType key_type,
+      KeyUsage key_usage,
+      CertificateProfile certificate_profile,
+      const std::string& username,
+      const std::string& origin,
+      const std::shared_ptr<CreateGoogleAttestedKeyTaskResult>& result);
+
+  // A callback for CreateGoogleAttestedKeyTask that invokes the original
+  // |callback| with the given |result|. Having this relay allows us to use weak
+  // pointer semantics to cancel callbacks.
+  void CreateGoogleAttestedKeyTaskCallback(
+      const CreateGoogleAttestedKeyCallback& callback,
+      const std::shared_ptr<CreateGoogleAttestedKeyTaskResult>& result);
+
+  // Returns true iff all information required for enrollment with the Google
+  // Attestation CA is available.
+  bool IsPreparedForEnrollment();
+
+  // Returns true iff enrollment with the Google Attestation CA has been
+  // completed.
+  bool IsEnrolled();
+
+  // Creates an enrollment request compatible with the Google Attestation CA.
+  // Returns true on success.
+  bool CreateEnrollRequest(std::string* enroll_request);
+
+  // Finishes enrollment given an |enroll_response| from the Google Attestation
+  // CA. Returns true on success. On failure, returns false and sets
+  // |server_error| to the error string from the CA.
+  bool FinishEnroll(const std::string& enroll_response,
+                    std::string* server_error);
+
+  // Creates a |certificate_request| compatible with the Google Attestation CA
+  // for the key identified by |username| and |key_label|, according to the
+  // given |profile| and |origin.
+  bool CreateCertificateRequest(const std::string& username,
+                                const std::string& key_label,
+                                CertificateProfile profile,
+                                const std::string& origin,
+                                std::string* certificate_request,
+                                std::string* message_id);
+
+  // Finishes a certificate request by decoding the |certificate_response| to
+  // recover the |certificate_chain| and storing it in association with the key
+  // identified by |username| and |key_label|. Returns true on success. On
+  // failure, returns false and sets |server_error| to the error string from the
+  // CA.
+  bool FinishCertificateRequest(const std::string& certificate_response,
+                                const std::string& username,
+                                const std::string& key_label,
+                                const std::string& message_id,
+                                std::string* certficate_chain,
+                                std::string* server_error);
+
+  // Sends a |request_type| |request| to the Google Attestation CA and waits for
+  // the |reply|. Returns true on success.
+  bool SendACARequestAndBlock(ACARequestType request_type,
+                              const std::string& request,
+                              std::string* reply);
+
+  // Creates a new certifiable key for |username| with the given |key_label|,
+  // |key_type|, and |key_usage|.
+  bool CreateKey(const std::string& username,
+                 const std::string& key_label,
+                 KeyType key_type,
+                 KeyUsage key_usage);
+
+  // Finds the |key| associated with |username| and |key_label|. Returns false
+  // if such a key does not exist.
+  bool FindKeyByLabel(const std::string& username,
+                      const std::string& key_label,
+                      CertifiedKey* key);
+
+  // Saves the |key| associated with |username| and |key_label|. Returns true on
+  // success.
+  bool SaveKey(const std::string& username,
+               const std::string& key_label,
+               const CertifiedKey& key);
+
+  // Deletes the key associated with |username| and |key_label|.
+  void DeleteKey(const std::string& username,
+                 const std::string& key_label);
+
+  // Adds named device-wide key to the attestation database.
+  bool AddDeviceKey(const std::string& key_label, const CertifiedKey& key);
+
+  // Removes a device-wide key from the attestation database.
+  void RemoveDeviceKey(const std::string& key_label);
+
+  // Certifies the key associated with |username| and |key_label| with the
+  // Attestation Identity Key (AIK). On success returns true and populates
+  // outputs as required by the CA (see AttestationCertificateRequest).
+  bool CertifyKey(const std::string& username,
+                  const std::string& key_label,
+                  std::string* public_key_tpm_format,
+                  std::string* key_info,
+                  std::string* proof);
+
+  // Creates a PEM certificate chain from the credential fields of a |key|.
+  std::string CreatePEMCertificateChain(const CertifiedKey& key);
+
+  // Creates a certificate in PEM format from a DER encoded X.509 certificate.
+  std::string CreatePEMCertificate(const std::string& certificate);
+
+  // Chooses a temporal index which will be used by the ACA to create a
+  // certificate.  This decision factors in the currently signed-in |user| and
+  // the |origin| of the certificate request.  The strategy is to find an index
+  // which has not already been used by another user for the same origin.
+  int ChooseTemporalIndex(const std::string& user, const std::string& origin);
+
+  // Creates a Google Attestation CA URL for the given |request_type|.
+  std::string GetACAURL(ACARequestType request_type) const;
+
+  base::WeakPtr<AttestationService> GetWeakPtr();
+
+
+  const std::string attestation_ca_origin_;
+
+  // Other than initialization and destruction, these are used only by the
+  // worker thread.
+  CryptoUtility* crypto_utility_;
   Database* database_;
-  std::unique_ptr<Database> default_database_;
+  std::unique_ptr<DatabaseImpl> default_database_;
+  std::shared_ptr<chromeos::http::Transport> http_transport_;
+  KeyStore* key_store_;
+  TpmUtility* tpm_utility_;
+
+  // All work is done in the background. This serves to serialize requests and
+  // allow synchronous implementation of complex methods. This is intentionally
+  // declared after the thread-owned members.
+  std::unique_ptr<base::Thread> worker_thread_;
+
+  // Declared last so any weak pointers are destroyed first.
+  base::WeakPtrFactory<AttestationService> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(AttestationService);
 };
diff --git a/server/attestation_service_test.cc b/server/attestation_service_test.cc
new file mode 100644
index 0000000..9447e86
--- /dev/null
+++ b/server/attestation_service_test.cc
@@ -0,0 +1,548 @@
+// Copyright 2015 The Chromium OS 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 <string>
+
+#include <base/bind.h>
+#include <base/callback.h>
+#include <base/message_loop/message_loop.h>
+#include <base/run_loop.h>
+#include <chromeos/bind_lambda.h>
+#include <chromeos/data_encoding.h>
+#include <chromeos/http/http_transport_fake.h>
+#include <chromeos/mime_utils.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "attestation/common/attestation_ca.pb.h"
+#include "attestation/server/attestation_service.h"
+#include "attestation/server/mock_crypto_utility.h"
+#include "attestation/server/mock_database.h"
+#include "attestation/server/mock_key_store.h"
+#include "attestation/server/mock_tpm_utility.h"
+
+using chromeos::http::fake::ServerRequest;
+using chromeos::http::fake::ServerResponse;
+using testing::_;
+using testing::NiceMock;
+using testing::Return;
+
+namespace attestation {
+
+class AttestationServiceTest : public testing::Test {
+ public:
+  enum FakeCAState {
+    kSuccess,         // Valid successful response.
+    kCommandFailure,  // Valid error response.
+    kHttpFailure,     // Responds with an HTTP error.
+    kBadMessageID,    // Valid successful response but a message ID mismatch.
+  };
+
+  ~AttestationServiceTest() override = default;
+  void SetUp() override {
+    service_.reset(new AttestationService);
+    service_->set_database(&mock_database_);
+    service_->set_crypto_utility(&mock_crypto_utility_);
+    fake_http_transport_ = std::make_shared<chromeos::http::fake::Transport>();
+    service_->set_http_transport(fake_http_transport_);
+    service_->set_key_store(&mock_key_store_);
+    service_->set_tpm_utility(&mock_tpm_utility_);
+    // Setup a fake EK certificate by default.
+    mock_database_.GetMutableProtobuf()->mutable_credentials()->
+        set_endorsement_credential("ek_cert");
+    // Setup a fake Attestation CA for success by default.
+    SetupFakeCAEnroll(kSuccess);
+    SetupFakeCASign(kSuccess);
+    CHECK(service_->Initialize());
+  }
+
+  void SetupFakeCAEnroll(FakeCAState state) {
+    fake_http_transport_->AddHandler(
+        service_->attestation_ca_origin() + "/enroll",
+        chromeos::http::request_type::kPost,
+        base::Bind(&AttestationServiceTest::FakeCAEnroll,
+                   base::Unretained(this),
+                   state));
+  }
+
+  void SetupFakeCASign(FakeCAState state) {
+    fake_http_transport_->AddHandler(
+        service_->attestation_ca_origin() + "/sign",
+        chromeos::http::request_type::kPost,
+        base::Bind(&AttestationServiceTest::FakeCASign,
+                   base::Unretained(this),
+                   state));
+  }
+
+  std::string GetFakeCertificateChain() {
+    const std::string kBeginCertificate = "-----BEGIN CERTIFICATE-----\n";
+    const std::string kEndCertificate = "-----END CERTIFICATE-----";
+    std::string pem = kBeginCertificate;
+    pem += chromeos::data_encoding::Base64EncodeWrapLines("fake_cert");
+    pem += kEndCertificate + "\n" + kBeginCertificate;
+    pem += chromeos::data_encoding::Base64EncodeWrapLines("fake_ca_cert");
+    pem += kEndCertificate;
+    return pem;
+  }
+
+  void Run() {
+    run_loop_.Run();
+  }
+
+  void RunUntilIdle() {
+    run_loop_.RunUntilIdle();
+  }
+
+  void Quit() {
+    run_loop_.Quit();
+  }
+
+ protected:
+  std::shared_ptr<chromeos::http::fake::Transport> fake_http_transport_;
+  NiceMock<MockCryptoUtility> mock_crypto_utility_;
+  NiceMock<MockDatabase> mock_database_;
+  NiceMock<MockKeyStore> mock_key_store_;
+  NiceMock<MockTpmUtility> mock_tpm_utility_;
+  std::unique_ptr<AttestationService> service_;
+
+ private:
+  void FakeCAEnroll(FakeCAState state,
+                    const ServerRequest& request,
+                    ServerResponse* response) {
+    AttestationEnrollmentRequest request_pb;
+    EXPECT_TRUE(request_pb.ParseFromString(request.GetDataAsString()));
+    if (state == kHttpFailure) {
+      response->ReplyText(chromeos::http::status_code::NotFound, std::string(),
+                          chromeos::mime::application::kOctet_stream);
+      return;
+    }
+    AttestationEnrollmentResponse response_pb;
+    if (state == kCommandFailure) {
+      response_pb.set_status(SERVER_ERROR);
+      response_pb.set_detail("fake_enroll_error");
+    } else if (state == kSuccess) {
+      response_pb.set_status(OK);
+      response_pb.set_detail("");
+      response_pb.mutable_encrypted_identity_credential()->
+          set_asym_ca_contents("1234");
+      response_pb.mutable_encrypted_identity_credential()->
+          set_sym_ca_attestation("5678");
+    } else {
+      NOTREACHED();
+    }
+    std::string tmp;
+    response_pb.SerializeToString(&tmp);
+    response->ReplyText(chromeos::http::status_code::Ok, tmp,
+                        chromeos::mime::application::kOctet_stream);
+  }
+
+  void FakeCASign(FakeCAState state,
+                  const ServerRequest& request,
+                  ServerResponse* response) {
+    AttestationCertificateRequest request_pb;
+    EXPECT_TRUE(request_pb.ParseFromString(request.GetDataAsString()));
+    if (state == kHttpFailure) {
+      response->ReplyText(chromeos::http::status_code::NotFound, std::string(),
+                          chromeos::mime::application::kOctet_stream);
+      return;
+    }
+    AttestationCertificateResponse response_pb;
+    if (state == kCommandFailure) {
+      response_pb.set_status(SERVER_ERROR);
+      response_pb.set_detail("fake_sign_error");
+    } else if (state == kSuccess || state == kBadMessageID) {
+      response_pb.set_status(OK);
+      response_pb.set_detail("");
+      if (state == kSuccess) {
+        response_pb.set_message_id(request_pb.message_id());
+      }
+      response_pb.set_certified_key_credential("fake_cert");
+      response_pb.set_intermediate_ca_cert("fake_ca_cert");
+    }
+    std::string tmp;
+    response_pb.SerializeToString(&tmp);
+    response->ReplyText(chromeos::http::status_code::Ok, tmp,
+                        chromeos::mime::application::kOctet_stream);
+  }
+
+  base::MessageLoop message_loop_;
+  base::RunLoop run_loop_;
+};
+
+TEST_F(AttestationServiceTest, CreateGoogleAttestedKeySuccess) {
+  // Set expectations on the outputs.
+  auto callback = [this](const std::string& certificate_chain,
+                         const std::string& server_error,
+                         AttestationStatus status) {
+    EXPECT_EQ(STATUS_SUCCESS, status);
+    EXPECT_EQ(GetFakeCertificateChain(), certificate_chain);
+    EXPECT_EQ("", server_error);
+    Quit();
+  };
+  service_->CreateGoogleAttestedKey("label", KEY_TYPE_ECC, KEY_USAGE_SIGN,
+                                    ENTERPRISE_MACHINE_CERTIFICATE, "user",
+                                    "origin", base::Bind(callback));
+  Run();
+}
+
+TEST_F(AttestationServiceTest, CreateGoogleAttestedKeySuccessNoUser) {
+  // Set expectations on the outputs.
+  auto callback = [this](const std::string& certificate_chain,
+                         const std::string& server_error,
+                         AttestationStatus status) {
+    EXPECT_EQ(STATUS_SUCCESS, status);
+    EXPECT_EQ(GetFakeCertificateChain(), certificate_chain);
+    EXPECT_EQ("", server_error);
+    Quit();
+  };
+  service_->CreateGoogleAttestedKey("label", KEY_TYPE_ECC, KEY_USAGE_SIGN,
+                                    ENTERPRISE_MACHINE_CERTIFICATE, "",
+                                    "origin", base::Bind(callback));
+  Run();
+}
+
+TEST_F(AttestationServiceTest, CreateGoogleAttestedKeyWithEnrollHttpError) {
+  SetupFakeCAEnroll(kHttpFailure);
+  // Set expectations on the outputs.
+  auto callback = [this](const std::string& certificate_chain,
+                         const std::string& server_error,
+                         AttestationStatus status) {
+    EXPECT_EQ(STATUS_CA_NOT_AVAILABLE, status);
+    EXPECT_EQ("", certificate_chain);
+    EXPECT_EQ("", server_error);
+    Quit();
+  };
+  service_->CreateGoogleAttestedKey("label", KEY_TYPE_ECC, KEY_USAGE_SIGN,
+                                    ENTERPRISE_MACHINE_CERTIFICATE, "user",
+                                    "origin", base::Bind(callback));
+  Run();
+}
+
+TEST_F(AttestationServiceTest, CreateGoogleAttestedKeyWithSignHttpError) {
+  SetupFakeCASign(kHttpFailure);
+  // Set expectations on the outputs.
+  auto callback = [this](const std::string& certificate_chain,
+                         const std::string& server_error,
+                         AttestationStatus status) {
+    EXPECT_EQ(STATUS_CA_NOT_AVAILABLE, status);
+    EXPECT_EQ("", certificate_chain);
+    EXPECT_EQ("", server_error);
+    Quit();
+  };
+  service_->CreateGoogleAttestedKey("label", KEY_TYPE_ECC, KEY_USAGE_SIGN,
+                                    ENTERPRISE_MACHINE_CERTIFICATE, "user",
+                                    "origin", base::Bind(callback));
+  Run();
+}
+
+TEST_F(AttestationServiceTest, CreateGoogleAttestedKeyWithCAEnrollFailure) {
+  SetupFakeCAEnroll(kCommandFailure);
+  // Set expectations on the outputs.
+  auto callback = [this](const std::string& certificate_chain,
+                         const std::string& server_error,
+                         AttestationStatus status) {
+    EXPECT_EQ(STATUS_REQUEST_DENIED_BY_CA, status);
+    EXPECT_EQ("", certificate_chain);
+    EXPECT_EQ("fake_enroll_error", server_error);
+    Quit();
+  };
+  service_->CreateGoogleAttestedKey("label", KEY_TYPE_ECC, KEY_USAGE_SIGN,
+                                    ENTERPRISE_MACHINE_CERTIFICATE, "user",
+                                    "origin", base::Bind(callback));
+  Run();
+}
+
+TEST_F(AttestationServiceTest, CreateGoogleAttestedKeyWithCASignFailure) {
+  SetupFakeCASign(kCommandFailure);
+  // Set expectations on the outputs.
+  auto callback = [this](const std::string& certificate_chain,
+                         const std::string& server_error,
+                         AttestationStatus status) {
+    EXPECT_EQ(STATUS_REQUEST_DENIED_BY_CA, status);
+    EXPECT_EQ("", certificate_chain);
+    EXPECT_EQ("fake_sign_error", server_error);
+    Quit();
+  };
+  service_->CreateGoogleAttestedKey("label", KEY_TYPE_ECC, KEY_USAGE_SIGN,
+                                    ENTERPRISE_MACHINE_CERTIFICATE, "user",
+                                    "origin", base::Bind(callback));
+  Run();
+}
+
+TEST_F(AttestationServiceTest, CreateGoogleAttestedKeyWithBadCAMessageID) {
+  SetupFakeCASign(kBadMessageID);
+  // Set expectations on the outputs.
+  auto callback = [this](const std::string& certificate_chain,
+                         const std::string& server_error,
+                         AttestationStatus status) {
+    EXPECT_EQ(STATUS_REQUEST_DENIED_BY_CA, status);
+    EXPECT_EQ("", certificate_chain);
+    EXPECT_EQ("", server_error);
+    Quit();
+  };
+  service_->CreateGoogleAttestedKey("label", KEY_TYPE_ECC, KEY_USAGE_SIGN,
+                                    ENTERPRISE_MACHINE_CERTIFICATE, "user",
+                                    "origin", base::Bind(callback));
+  Run();
+}
+
+TEST_F(AttestationServiceTest, CreateGoogleAttestedKeyWithNoEKCertificate) {
+  // Remove the fake EK certificate.
+  mock_database_.GetMutableProtobuf()->mutable_credentials()->
+      clear_endorsement_credential();
+  // Set expectations on the outputs.
+  auto callback = [this](const std::string& certificate_chain,
+                         const std::string& server_error,
+                         AttestationStatus status) {
+    EXPECT_NE(STATUS_SUCCESS, status);
+    EXPECT_EQ("", certificate_chain);
+    EXPECT_EQ("", server_error);
+    Quit();
+  };
+  service_->CreateGoogleAttestedKey("label", KEY_TYPE_ECC, KEY_USAGE_SIGN,
+                                    ENTERPRISE_MACHINE_CERTIFICATE, "user",
+                                    "origin", base::Bind(callback));
+  Run();
+}
+
+TEST_F(AttestationServiceTest, CreateGoogleAttestedKeyWithRNGFailure) {
+  EXPECT_CALL(mock_crypto_utility_, GetRandom(_, _))
+      .WillRepeatedly(Return(false));
+  // Set expectations on the outputs.
+  auto callback = [this](const std::string& certificate_chain,
+                         const std::string& server_error,
+                         AttestationStatus status) {
+    EXPECT_NE(STATUS_SUCCESS, status);
+    EXPECT_EQ("", certificate_chain);
+    EXPECT_EQ("", server_error);
+    Quit();
+  };
+  service_->CreateGoogleAttestedKey("label", KEY_TYPE_ECC, KEY_USAGE_SIGN,
+                                    ENTERPRISE_MACHINE_CERTIFICATE, "user",
+                                    "origin", base::Bind(callback));
+  Run();
+}
+
+TEST_F(AttestationServiceTest, CreateGoogleAttestedKeyWithRNGFailure2) {
+  EXPECT_CALL(mock_crypto_utility_, GetRandom(_, _))
+      .WillOnce(Return(true))
+      .WillRepeatedly(Return(false));
+  // Set expectations on the outputs.
+  auto callback = [this](const std::string& certificate_chain,
+                         const std::string& server_error,
+                         AttestationStatus status) {
+    EXPECT_NE(STATUS_SUCCESS, status);
+    EXPECT_EQ("", certificate_chain);
+    EXPECT_EQ("", server_error);
+    Quit();
+  };
+  service_->CreateGoogleAttestedKey("label", KEY_TYPE_ECC, KEY_USAGE_SIGN,
+                                    ENTERPRISE_MACHINE_CERTIFICATE, "user",
+                                    "origin", base::Bind(callback));
+  Run();
+}
+
+TEST_F(AttestationServiceTest, CreateGoogleAttestedKeyWithDBFailure) {
+  EXPECT_CALL(mock_database_, SaveChanges())
+      .WillRepeatedly(Return(false));
+  // Set expectations on the outputs.
+  auto callback = [this](const std::string& certificate_chain,
+                         const std::string& server_error,
+                         AttestationStatus status) {
+    EXPECT_NE(STATUS_SUCCESS, status);
+    EXPECT_EQ("", certificate_chain);
+    EXPECT_EQ("", server_error);
+    Quit();
+  };
+  service_->CreateGoogleAttestedKey("label", KEY_TYPE_ECC, KEY_USAGE_SIGN,
+                                    ENTERPRISE_MACHINE_CERTIFICATE, "user",
+                                    "origin", base::Bind(callback));
+  Run();
+}
+
+TEST_F(AttestationServiceTest, CreateGoogleAttestedKeyWithDBFailureNoUser) {
+  EXPECT_CALL(mock_database_, SaveChanges())
+      .WillRepeatedly(Return(false));
+  // Set expectations on the outputs.
+  auto callback = [this](const std::string& certificate_chain,
+                         const std::string& server_error,
+                         AttestationStatus status) {
+    EXPECT_NE(STATUS_SUCCESS, status);
+    EXPECT_EQ("", certificate_chain);
+    EXPECT_EQ("", server_error);
+    Quit();
+  };
+  service_->CreateGoogleAttestedKey("label", KEY_TYPE_ECC, KEY_USAGE_SIGN,
+                                    ENTERPRISE_MACHINE_CERTIFICATE, "",
+                                    "origin", base::Bind(callback));
+  Run();
+}
+
+TEST_F(AttestationServiceTest, CreateGoogleAttestedKeyWithKeyReadFailure) {
+  EXPECT_CALL(mock_key_store_, Read(_, _, _))
+      .WillRepeatedly(Return(false));
+  // Set expectations on the outputs.
+  auto callback = [this](const std::string& certificate_chain,
+                         const std::string& server_error,
+                         AttestationStatus status) {
+    EXPECT_NE(STATUS_SUCCESS, status);
+    EXPECT_EQ("", certificate_chain);
+    EXPECT_EQ("", server_error);
+    Quit();
+  };
+  service_->CreateGoogleAttestedKey("label", KEY_TYPE_ECC, KEY_USAGE_SIGN,
+                                    ENTERPRISE_MACHINE_CERTIFICATE, "user",
+                                    "origin", base::Bind(callback));
+  Run();
+}
+
+TEST_F(AttestationServiceTest, CreateGoogleAttestedKeyWithKeyWriteFailure) {
+  EXPECT_CALL(mock_key_store_, Write(_, _, _))
+      .WillRepeatedly(Return(false));
+  // Set expectations on the outputs.
+  auto callback = [this](const std::string& certificate_chain,
+                         const std::string& server_error,
+                         AttestationStatus status) {
+    EXPECT_NE(STATUS_SUCCESS, status);
+    EXPECT_EQ("", certificate_chain);
+    EXPECT_EQ("", server_error);
+    Quit();
+  };
+  service_->CreateGoogleAttestedKey("label", KEY_TYPE_ECC, KEY_USAGE_SIGN,
+                                    ENTERPRISE_MACHINE_CERTIFICATE, "user",
+                                    "origin", base::Bind(callback));
+  Run();
+}
+
+TEST_F(AttestationServiceTest, CreateGoogleAttestedKeyWithTpmNotReady) {
+  EXPECT_CALL(mock_tpm_utility_, IsTpmReady())
+      .WillRepeatedly(Return(false));
+  // Set expectations on the outputs.
+  auto callback = [this](const std::string& certificate_chain,
+                         const std::string& server_error,
+                         AttestationStatus status) {
+    EXPECT_NE(STATUS_SUCCESS, status);
+    EXPECT_EQ("", certificate_chain);
+    EXPECT_EQ("", server_error);
+    Quit();
+  };
+  service_->CreateGoogleAttestedKey("label", KEY_TYPE_ECC, KEY_USAGE_SIGN,
+                                    ENTERPRISE_MACHINE_CERTIFICATE, "user",
+                                    "origin", base::Bind(callback));
+  Run();
+}
+
+TEST_F(AttestationServiceTest, CreateGoogleAttestedKeyWithTpmActivateFailure) {
+  EXPECT_CALL(mock_tpm_utility_, ActivateIdentity(_, _, _, _, _, _))
+      .WillRepeatedly(Return(false));
+  // Set expectations on the outputs.
+  auto callback = [this](const std::string& certificate_chain,
+                         const std::string& server_error,
+                         AttestationStatus status) {
+    EXPECT_NE(STATUS_SUCCESS, status);
+    EXPECT_EQ("", certificate_chain);
+    EXPECT_EQ("", server_error);
+    Quit();
+  };
+  service_->CreateGoogleAttestedKey("label", KEY_TYPE_ECC, KEY_USAGE_SIGN,
+                                    ENTERPRISE_MACHINE_CERTIFICATE, "user",
+                                    "origin", base::Bind(callback));
+  Run();
+}
+
+TEST_F(AttestationServiceTest, CreateGoogleAttestedKeyWithTpmGenerateFailure) {
+  // Return false once to simulate that a key does not initially exist.
+  EXPECT_CALL(mock_key_store_, Read(_, _, _))
+      .WillOnce(Return(false))
+      .WillRepeatedly(Return(true));
+  EXPECT_CALL(mock_tpm_utility_, GenerateKey(_, _, _, _))
+      .WillRepeatedly(Return(false));
+  // Set expectations on the outputs.
+  auto callback = [this](const std::string& certificate_chain,
+                         const std::string& server_error,
+                         AttestationStatus status) {
+    EXPECT_NE(STATUS_SUCCESS, status);
+    EXPECT_EQ("", certificate_chain);
+    EXPECT_EQ("", server_error);
+    Quit();
+  };
+  service_->CreateGoogleAttestedKey("label", KEY_TYPE_ECC, KEY_USAGE_SIGN,
+                                    ENTERPRISE_MACHINE_CERTIFICATE, "user",
+                                    "origin", base::Bind(callback));
+  Run();
+}
+
+TEST_F(AttestationServiceTest, CreateGoogleAttestedKeyWithTpmGenerateFailure2) {
+  EXPECT_CALL(mock_tpm_utility_, GenerateKey(_, _, _, _))
+      .WillRepeatedly(Return(false));
+  // Set expectations on the outputs.
+  auto callback = [this](const std::string& certificate_chain,
+                         const std::string& server_error,
+                         AttestationStatus status) {
+    EXPECT_NE(STATUS_SUCCESS, status);
+    EXPECT_EQ("", certificate_chain);
+    EXPECT_EQ("", server_error);
+    Quit();
+  };
+  service_->CreateGoogleAttestedKey("label", KEY_TYPE_ECC, KEY_USAGE_SIGN,
+                                    ENTERPRISE_MACHINE_CERTIFICATE, "",
+                                    "origin", base::Bind(callback));
+  Run();
+}
+
+TEST_F(AttestationServiceTest, CreateGoogleAttestedKeyWithTpmCertifyFailure) {
+  EXPECT_CALL(mock_tpm_utility_, CertifyKey(_, _, _, _, _, _))
+      .WillRepeatedly(Return(false));
+  // Set expectations on the outputs.
+  auto callback = [this](const std::string& certificate_chain,
+                         const std::string& server_error,
+                         AttestationStatus status) {
+    EXPECT_NE(STATUS_SUCCESS, status);
+    EXPECT_EQ("", certificate_chain);
+    EXPECT_EQ("", server_error);
+    Quit();
+  };
+  service_->CreateGoogleAttestedKey("label", KEY_TYPE_ECC, KEY_USAGE_SIGN,
+                                    ENTERPRISE_MACHINE_CERTIFICATE, "user",
+                                    "origin", base::Bind(callback));
+  Run();
+}
+
+TEST_F(AttestationServiceTest, CreateGoogleAttestedKeyAndCancel) {
+  // Set expectations on the outputs.
+  int callback_count = 0;
+  auto callback = [&callback_count](const std::string& certificate_chain,
+                                    const std::string& server_error,
+                                    AttestationStatus status) {
+    callback_count++;
+  };
+  service_->CreateGoogleAttestedKey("label", KEY_TYPE_ECC, KEY_USAGE_SIGN,
+                                    ENTERPRISE_MACHINE_CERTIFICATE, "user",
+                                    "origin", base::Bind(callback));
+  // Bring down the service, which should cancel any callbacks.
+  service_.reset();
+  EXPECT_EQ(0, callback_count);
+}
+
+TEST_F(AttestationServiceTest, CreateGoogleAttestedKeyAndCancel2) {
+  // Set expectations on the outputs.
+  int callback_count = 0;
+  auto callback = [&callback_count](const std::string& certificate_chain,
+                                    const std::string& server_error,
+                                    AttestationStatus status) {
+    callback_count++;
+  };
+  service_->CreateGoogleAttestedKey("label", KEY_TYPE_ECC, KEY_USAGE_SIGN,
+                                    ENTERPRISE_MACHINE_CERTIFICATE, "user",
+                                    "origin", base::Bind(callback));
+  // Give threads a chance to run.
+  base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(10));
+  // Bring down the service, which should cancel any callbacks.
+  service_.reset();
+  // Pump the loop to make sure no callbacks were posted.
+  RunUntilIdle();
+  EXPECT_EQ(0, callback_count);
+}
+
+}  // namespace attestation
diff --git a/server/crypto_utility.h b/server/crypto_utility.h
index 751632b..0048452 100644
--- a/server/crypto_utility.h
+++ b/server/crypto_utility.h
@@ -14,6 +14,9 @@
  public:
   virtual ~CryptoUtility() = default;
 
+  // Generates |num_bytes| of |random_data|. Returns true on success.
+  virtual bool GetRandom(size_t num_bytes, std::string* random_data) const = 0;
+
   // Creates a random |aes_key| and seals it to the TPM's PCR0, producing a
   // |sealed_key|. Returns true on success.
   virtual bool CreateSealedKey(std::string* aes_key,
diff --git a/server/database_impl_test.cc b/server/database_impl_test.cc
index aeb012a..d234c6d 100644
--- a/server/database_impl_test.cc
+++ b/server/database_impl_test.cc
@@ -21,12 +21,6 @@
 
 const char kFakeCredential[] = "1234";
 
-// For faking encrypt / decrypt operations.
-bool CopyString(const std::string& s1, std::string* s2) {
-  *s2 = s1;
-  return true;
-}
-
 }  // namespace
 
 namespace attestation {
@@ -39,14 +33,6 @@
     database_.reset(new DatabaseImpl(&mock_crypto_utility_));
     database_->set_io(this);
     InitializeFakeData();
-    ON_CALL(mock_crypto_utility_, CreateSealedKey(_, _))
-        .WillByDefault(Return(true));
-    ON_CALL(mock_crypto_utility_, EncryptData(_, _, _, _))
-        .WillByDefault(WithArgs<0, 3>(Invoke(CopyString)));
-    ON_CALL(mock_crypto_utility_, UnsealKey(_, _, _))
-        .WillByDefault(Return(true));
-    ON_CALL(mock_crypto_utility_, DecryptData(_, _, _))
-        .WillByDefault(WithArgs<0, 2>(Invoke(CopyString)));
   }
 
   // Fake DatabaseIO::Read.
diff --git a/server/dbus_service.cc b/server/dbus_service.cc
index 45db9b7..7e70731 100644
--- a/server/dbus_service.cc
+++ b/server/dbus_service.cc
@@ -46,14 +46,14 @@
       DBusMethodResponse<const CreateGoogleAttestedKeyReply&>>;
   // A callback that fills the reply protobuf and sends it.
   auto callback = [](const SharedResponsePointer& response,
-                     AttestationStatus status,
                      const std::string& certificate_chain,
-                     const std::string& server_error_details) {
+                     const std::string& server_error_details,
+                     AttestationStatus status) {
     CreateGoogleAttestedKeyReply reply;
     reply.set_status(status);
-    if (status == SUCCESS) {
+    if (status == STATUS_SUCCESS) {
       reply.set_certificate_chain(certificate_chain);
-    } else if (status == REQUEST_DENIED_BY_CA) {
+    } else if (status == STATUS_REQUEST_DENIED_BY_CA) {
       reply.set_server_error(server_error_details);
     }
     response->Return(reply);
@@ -63,6 +63,8 @@
       request.key_type(),
       request.key_usage(),
       request.certificate_profile(),
+      request.username(),
+      request.origin(),
       base::Bind(callback, SharedResponsePointer(response.release())));
 }
 
diff --git a/server/dbus_service_test.cc b/server/dbus_service_test.cc
index ab3e4e0..9e253b7 100644
--- a/server/dbus_service_test.cc
+++ b/server/dbus_service_test.cc
@@ -62,10 +62,11 @@
 
 TEST_F(DBusServiceTest, CreateGoogleAttestedKeySuccess) {
   EXPECT_CALL(mock_service_, CreateGoogleAttestedKey(
-      "label", KEY_TYPE_ECC, KEY_USAGE_SIGN, ENTERPRISE_MACHINE_CERTIFICATE, _))
-      .WillOnce(WithArgs<4>(Invoke([](const base::Callback<
-          AttestationInterface::CreateGoogleAttestedKeyCallback>& callback) {
-        callback.Run(SUCCESS, "certificate", "server_error");
+      "label", KEY_TYPE_ECC, KEY_USAGE_SIGN, ENTERPRISE_MACHINE_CERTIFICATE,
+      "username", "origin", _))
+      .WillOnce(WithArgs<6>(Invoke([](const AttestationInterface::
+            CreateGoogleAttestedKeyCallback& callback) {
+        callback.Run("certificate", "server_error", STATUS_SUCCESS);
       })));
   std::unique_ptr<dbus::MethodCall> call = CreateMethodCall(
       kCreateGoogleAttestedKey);
@@ -74,22 +75,25 @@
   request_proto.set_key_type(KEY_TYPE_ECC);
   request_proto.set_key_usage(KEY_USAGE_SIGN);
   request_proto.set_certificate_profile(ENTERPRISE_MACHINE_CERTIFICATE);
+  request_proto.set_username("username");
+  request_proto.set_origin("origin");
   dbus::MessageWriter writer(call.get());
   writer.AppendProtoAsArrayOfBytes(request_proto);
   auto response = CallMethod(call.get());
   dbus::MessageReader reader(response.get());
   CreateGoogleAttestedKeyReply reply_proto;
   EXPECT_TRUE(reader.PopArrayOfBytesAsProto(&reply_proto));
-  EXPECT_EQ(SUCCESS, reply_proto.status());
+  EXPECT_EQ(STATUS_SUCCESS, reply_proto.status());
   EXPECT_EQ("certificate", reply_proto.certificate_chain());
   EXPECT_EQ("", reply_proto.server_error());
 }
 
 TEST_F(DBusServiceTest, CreateGoogleAttestedKeyServerError) {
-  EXPECT_CALL(mock_service_, CreateGoogleAttestedKey(_, _, _, _, _))
-      .WillOnce(WithArgs<4>(Invoke([](const base::Callback<
-          AttestationInterface::CreateGoogleAttestedKeyCallback>& callback) {
-        callback.Run(REQUEST_DENIED_BY_CA, "certificate", "server_error");
+  EXPECT_CALL(mock_service_, CreateGoogleAttestedKey(_, _, _, _, _, _, _))
+      .WillOnce(WithArgs<6>(Invoke([](const AttestationInterface::
+          CreateGoogleAttestedKeyCallback& callback) {
+        callback.Run("certificate", "server_error",
+                     STATUS_REQUEST_DENIED_BY_CA);
       })));
   std::unique_ptr<dbus::MethodCall> call = CreateMethodCall(
       kCreateGoogleAttestedKey);
@@ -100,18 +104,18 @@
   dbus::MessageReader reader(response.get());
   CreateGoogleAttestedKeyReply reply_proto;
   EXPECT_TRUE(reader.PopArrayOfBytesAsProto(&reply_proto));
-  EXPECT_EQ(REQUEST_DENIED_BY_CA, reply_proto.status());
+  EXPECT_EQ(STATUS_REQUEST_DENIED_BY_CA, reply_proto.status());
   EXPECT_EQ("", reply_proto.certificate_chain());
   EXPECT_EQ("server_error", reply_proto.server_error());
 }
 
 TEST_F(DBusServiceTest, CopyableCallback) {
-  EXPECT_CALL(mock_service_, CreateGoogleAttestedKey(_, _, _, _, _))
-      .WillOnce(WithArgs<4>(Invoke([](const base::Callback<
-          AttestationInterface::CreateGoogleAttestedKeyCallback>& callback) {
+  EXPECT_CALL(mock_service_, CreateGoogleAttestedKey(_, _, _, _, _, _, _))
+      .WillOnce(WithArgs<6>(Invoke([](const AttestationInterface::
+          CreateGoogleAttestedKeyCallback& callback) {
         // Copy the callback, then call the original.
-        base::Closure copy = base::Bind(callback, SUCCESS, "", "");
-        callback.Run(SUCCESS, "", "");
+        base::Closure copy = base::Bind(callback, "", "", STATUS_SUCCESS);
+        callback.Run("", "", STATUS_SUCCESS);
       })));
   std::unique_ptr<dbus::MethodCall> call = CreateMethodCall(
       kCreateGoogleAttestedKey);
diff --git a/server/key_store.h b/server/key_store.h
new file mode 100644
index 0000000..6fc4421
--- /dev/null
+++ b/server/key_store.h
@@ -0,0 +1,66 @@
+// Copyright 2015 The Chromium OS 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 ATTESTATION_SERVER_KEY_STORE_H_
+#define ATTESTATION_SERVER_KEY_STORE_H_
+
+#include <string>
+
+#include <base/macros.h>
+
+namespace attestation {
+
+// A mock-able key storage interface.
+class KeyStore {
+ public:
+  KeyStore() {}
+  virtual ~KeyStore() {}
+
+  // Reads key data from the store for the key identified by |key_label| and by
+  // |username|. On success true is returned and |key_data| is populated.
+  virtual bool Read(const std::string& username,
+                    const std::string& key_label,
+                    std::string* key_data) = 0;
+
+  // Writes key data to the store for the key identified by |key_label| and by
+  // |username|. If such a key already exists the existing data will be
+  // overwritten.
+  virtual bool Write(const std::string& username,
+                     const std::string& key_label,
+                     const std::string& key_data) = 0;
+
+  // Deletes key data for the key identified by |key_label| and by |username|.
+  // Returns false if key data exists but could not be deleted.
+  virtual bool Delete(const std::string& username,
+                      const std::string& key_label) = 0;
+
+  // Deletes key data for all keys identified by |key_prefix| and by |username|
+  // Returns false if key data exists but could not be deleted.
+  virtual bool DeleteByPrefix(const std::string& username,
+                              const std::string& key_prefix) = 0;
+
+  // Registers a key to be associated with |username|.
+  // The provided |label| will be associated with all registered objects.
+  // |private_key_blob| holds the private key in some opaque format and
+  // |public_key_der| holds the public key in PKCS #1 RSAPublicKey format.
+  // If a non-empty |certificate| is provided it will be registered along with
+  // the key. Returns true on success.
+  virtual bool Register(const std::string& username,
+                        const std::string& label,
+                        const std::string& private_key_blob,
+                        const std::string& public_key_der,
+                        const std::string& certificate) = 0;
+
+  // Registers a |certificate| that is not associated to a registered key. The
+  // certificate will be associated with |username|.
+  virtual bool RegisterCertificate(const std::string& username,
+                                   const std::string& certificate) = 0;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(KeyStore);
+};
+
+}  // namespace attestation
+
+#endif  // ATTESTATION_SERVER_KEY_STORE_H_
diff --git a/server/mock_crypto_utility.cc b/server/mock_crypto_utility.cc
new file mode 100644
index 0000000..e3655c7
--- /dev/null
+++ b/server/mock_crypto_utility.cc
@@ -0,0 +1,40 @@
+// Copyright 2015 The Chromium OS 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 "attestation/server/mock_crypto_utility.h"
+
+using ::testing::_;
+using ::testing::Invoke;
+using ::testing::Return;
+using ::testing::WithArgs;
+
+namespace {
+
+bool FakeRandom(size_t num_bytes, std::string* output) {
+  *output = std::string(num_bytes, 'A');
+  return true;
+}
+
+bool CopyString(const std::string& s1, std::string* s2) {
+  *s2 = s1;
+  return true;
+}
+
+}  // namespace
+
+namespace attestation {
+
+MockCryptoUtility::MockCryptoUtility() {
+  ON_CALL(*this, GetRandom(_, _)).WillByDefault(Invoke(FakeRandom));
+  ON_CALL(*this, CreateSealedKey(_, _)).WillByDefault(Return(true));
+  ON_CALL(*this, UnsealKey(_, _, _)).WillByDefault(Return(true));
+  ON_CALL(*this, EncryptData(_, _, _, _))
+      .WillByDefault(WithArgs<0, 3>(Invoke(CopyString)));
+  ON_CALL(*this, DecryptData(_, _, _))
+      .WillByDefault(WithArgs<0, 2>(Invoke(CopyString)));
+}
+
+MockCryptoUtility::~MockCryptoUtility() {}
+
+}  // namespace attestation
diff --git a/server/mock_crypto_utility.h b/server/mock_crypto_utility.h
index bee86dc..98ea6d3 100644
--- a/server/mock_crypto_utility.h
+++ b/server/mock_crypto_utility.h
@@ -15,8 +15,10 @@
 
 class MockCryptoUtility : public CryptoUtility {
  public:
-  MockCryptoUtility() = default;
-  ~MockCryptoUtility() override = default;
+  MockCryptoUtility();
+  ~MockCryptoUtility() override;
+
+  MOCK_CONST_METHOD2(GetRandom, bool(size_t, std::string*));
 
   MOCK_CONST_METHOD2(CreateSealedKey, bool(std::string* aes_key,
                                            std::string* sealed_key));
diff --git a/server/mock_database.cc b/server/mock_database.cc
new file mode 100644
index 0000000..5215c2c
--- /dev/null
+++ b/server/mock_database.cc
@@ -0,0 +1,20 @@
+// Copyright 2015 The Chromium OS 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 "attestation/server/mock_database.h"
+
+using testing::Return;
+using testing::ReturnRef;
+
+namespace attestation {
+
+MockDatabase::MockDatabase() {
+  ON_CALL(*this, GetProtobuf()).WillByDefault(ReturnRef(fake_));
+  ON_CALL(*this, GetMutableProtobuf()).WillByDefault(Return(&fake_));
+  ON_CALL(*this, SaveChanges()).WillByDefault(Return(true));
+}
+
+MockDatabase::~MockDatabase() {}
+
+}  // namespace attestation
diff --git a/server/mock_database.h b/server/mock_database.h
new file mode 100644
index 0000000..d9ab985
--- /dev/null
+++ b/server/mock_database.h
@@ -0,0 +1,29 @@
+// Copyright 2015 The Chromium OS 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 ATTESTATION_SERVER_MOCK_DATABASE_H_
+#define ATTESTATION_SERVER_MOCK_DATABASE_H_
+
+#include "attestation/server/database.h"
+
+#include <gmock/gmock.h>
+
+namespace attestation {
+
+class MockDatabase : public Database {
+ public:
+  MockDatabase();
+  ~MockDatabase() override;
+
+  MOCK_CONST_METHOD0(GetProtobuf, const AttestationDatabase&());
+  MOCK_METHOD0(GetMutableProtobuf, AttestationDatabase*());
+  MOCK_METHOD0(SaveChanges, bool());
+
+ private:
+  AttestationDatabase fake_;
+};
+
+}  // namespace attestation
+
+#endif  // ATTESTATION_SERVER_MOCK_DATABASE_H_
diff --git a/server/mock_key_store.cc b/server/mock_key_store.cc
new file mode 100644
index 0000000..2558f35
--- /dev/null
+++ b/server/mock_key_store.cc
@@ -0,0 +1,23 @@
+// Copyright 2015 The Chromium OS 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 "attestation/server/mock_key_store.h"
+
+using ::testing::_;
+using ::testing::Return;
+
+namespace attestation {
+
+MockKeyStore::MockKeyStore() {
+  ON_CALL(*this, Read(_, _, _)).WillByDefault(Return(true));
+  ON_CALL(*this, Write(_, _, _)).WillByDefault(Return(true));
+  ON_CALL(*this, Delete(_, _)).WillByDefault(Return(true));
+  ON_CALL(*this, DeleteByPrefix(_, _)).WillByDefault(Return(true));
+  ON_CALL(*this, Register(_, _, _, _, _)).WillByDefault(Return(true));
+  ON_CALL(*this, RegisterCertificate(_, _)).WillByDefault(Return(true));
+}
+
+MockKeyStore::~MockKeyStore() {}
+
+}  // namespace attestation
diff --git a/server/mock_key_store.h b/server/mock_key_store.h
new file mode 100644
index 0000000..40d04f1
--- /dev/null
+++ b/server/mock_key_store.h
@@ -0,0 +1,46 @@
+// Copyright 2015 The Chromium OS 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 ATTESTATION_SERVER_MOCK_KEY_STORE_H_
+#define ATTESTATION_SERVER_MOCK_KEY_STORE_H_
+
+#include "attestation/server/key_store.h"
+
+#include <string>
+
+#include <base/macros.h>
+#include <gmock/gmock.h>
+
+namespace attestation {
+
+class MockKeyStore : public KeyStore {
+ public:
+  MockKeyStore();
+  virtual ~MockKeyStore();
+
+  MOCK_METHOD3(Read, bool(const std::string& username,
+                          const std::string& name,
+                          std::string* key_data));
+  MOCK_METHOD3(Write, bool(const std::string& username,
+                           const std::string& name,
+                           const std::string& key_data));
+  MOCK_METHOD2(Delete, bool(const std::string& username,
+                            const std::string& name));
+  MOCK_METHOD2(DeleteByPrefix, bool(const std::string& username,
+                                    const std::string& key_prefix));
+  MOCK_METHOD5(Register, bool(const std::string& username,
+                              const std::string& label,
+                              const std::string& private_key_blob,
+                              const std::string& public_key_der,
+                              const std::string& certificate));
+  MOCK_METHOD2(RegisterCertificate, bool(const std::string& username,
+                                         const std::string& certificate));
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MockKeyStore);
+};
+
+}  // namespace attestation
+
+#endif  // ATTESTATION_SERVER_MOCK_KEY_STORE_H_
diff --git a/server/mock_tpm_utility.cc b/server/mock_tpm_utility.cc
new file mode 100644
index 0000000..80692bd
--- /dev/null
+++ b/server/mock_tpm_utility.cc
@@ -0,0 +1,22 @@
+// Copyright 2015 The Chromium OS 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 "attestation/server/mock_tpm_utility.h"
+
+using ::testing::_;
+using ::testing::Return;
+
+namespace attestation {
+
+MockTpmUtility::MockTpmUtility() {
+  ON_CALL(*this, IsTpmReady()).WillByDefault(Return(true));
+  ON_CALL(*this, ActivateIdentity(_, _, _, _, _, _))
+      .WillByDefault(Return(true));
+  ON_CALL(*this, GenerateKey(_, _, _, _)).WillByDefault(Return(true));
+  ON_CALL(*this, CertifyKey(_, _, _, _, _, _)).WillByDefault(Return(true));
+}
+
+MockTpmUtility::~MockTpmUtility() {}
+
+}  // namespace attestation
diff --git a/server/mock_tpm_utility.h b/server/mock_tpm_utility.h
new file mode 100644
index 0000000..3f2b616
--- /dev/null
+++ b/server/mock_tpm_utility.h
@@ -0,0 +1,40 @@
+// Copyright 2015 The Chromium OS 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 ATTESTATION_SERVER_MOCK_TPM_UTILITY_H_
+#define ATTESTATION_SERVER_MOCK_TPM_UTILITY_H_
+
+#include "attestation/server/tpm_utility.h"
+
+#include <string>
+
+#include <gmock/gmock.h>
+
+namespace attestation {
+
+class MockTpmUtility : public TpmUtility {
+ public:
+  MockTpmUtility();
+  ~MockTpmUtility() override;
+
+  MOCK_METHOD0(IsTpmReady, bool());
+  MOCK_METHOD6(ActivateIdentity, bool(const std::string&,
+                                      const std::string&,
+                                      const std::string&,
+                                      const std::string&,
+                                      const std::string&,
+                                      std::string*));
+  MOCK_METHOD4(GenerateKey, bool(KeyType, KeyUsage, std::string*,
+                                 std::string*));
+  MOCK_METHOD6(CertifyKey, bool(const std::string&,
+                                const std::string&,
+                                const std::string&,
+                                std::string*,
+                                std::string*,
+                                std::string*));
+};
+
+}  // namespace attestation
+
+#endif  // ATTESTATION_SERVER_MOCK_TPM_UTILITY_H_
diff --git a/server/tpm_utility.h b/server/tpm_utility.h
new file mode 100644
index 0000000..bd447a2
--- /dev/null
+++ b/server/tpm_utility.h
@@ -0,0 +1,61 @@
+// Copyright 2015 The Chromium OS 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 ATTESTATION_SERVER_TPM_UTILITY_H_
+#define ATTESTATION_SERVER_TPM_UTILITY_H_
+
+#include <string>
+
+#include "attestation/common/interface.pb.h"
+
+namespace attestation {
+
+// A class which provides helpers for TPM-related tasks.
+class TpmUtility {
+ public:
+  virtual ~TpmUtility() = default;
+
+  // Returns true iff the TPM is enabled, owned, and ready for attestation.
+  virtual bool IsTpmReady() = 0;
+
+  // Activates an attestation identity key. Effectively this decrypts a
+  // certificate or some other type of credential with the endorsement key. The
+  // |delegate_blob| and |delegate_secret| must be authorized to activate with
+  // owner privilege. The |identity_key_blob| is the key to which the credential
+  // is bound. The |asym_ca_contents| and |sym_ca_attestation| parameters are
+  // encrypted TPM structures, typically created by a CA (TPM_ASYM_CA_CONTENTS
+  // and TPM_SYM_CA_ATTESTATION respectively). On success returns true and
+  // populates the decrypted |credential|.
+  virtual bool ActivateIdentity(const std::string& delegate_blob,
+                                const std::string& delegate_secret,
+                                const std::string& identity_key_blob,
+                                const std::string& asym_ca_contents,
+                                const std::string& sym_ca_attestation,
+                                std::string* credential) = 0;
+
+  // Generates a non-migratable key in the TPM corresponding to |key_type| and
+  // |key_usage|. The parent key will be the storage root key. The new key will
+  // always be certifiable.
+  virtual bool GenerateKey(KeyType key_type,
+                           KeyUsage key_usage,
+                           std::string* key_blob,
+                           std::string* public_key) = 0;
+
+  // Certifies the key represented by |key_blob| with the attestation identity
+  // key represented by |identity_key_blob|. The |external_data| will be
+  // included in the |key_info|. On success, returns true and populates
+  // |public_key_tpm_format| with the public key of |key_blob| in TPM_PUBKEY
+  // format, |key_info| with the TPM_CERTIFY_INFO that was signed, and |proof|
+  // with the signature of |key_info| by the identity key.
+  virtual bool CertifyKey(const std::string& key_blob,
+                          const std::string& identity_key_blob,
+                          const std::string& external_data,
+                          std::string* public_key_tpm_format,
+                          std::string* key_info,
+                          std::string* proof) = 0;
+};
+
+}  // namespace attestation
+
+#endif  // ATTESTATION_SERVER_TPM_UTILITY_H_