tpm_manager: Add client side code to call the NVRAM api

This CL implements client side code to call and use the NVRAM api
exposed by TpmManager.

Bug: 24059574
TEST=run nvram methods on DUT and observe print statements

Change-Id: I0acd2fbbd3abb6b76f4774b35972665d83128669
diff --git a/client/dbus_proxy.cc b/client/dbus_proxy.cc
index eed2688..a0dfdd0 100644
--- a/client/dbus_proxy.cc
+++ b/client/dbus_proxy.cc
@@ -50,25 +50,60 @@
 
 void DBusProxy::GetTpmStatus(const GetTpmStatusRequest& request,
                              const GetTpmStatusCallback& callback) {
-  auto on_error = [callback](chromeos::Error* error) {
-    GetTpmStatusReply reply;
-    reply.set_status(STATUS_NOT_AVAILABLE);
-    callback.Run(reply);
-  };
-  chromeos::dbus_utils::CallMethodWithTimeout(
-      kDBusTimeoutMS,
-      object_proxy_,
-      tpm_manager::kTpmManagerInterface,
-      tpm_manager::kGetTpmStatus,
-      callback,
-      base::Bind(on_error),
-      request);
+  CallMethod<GetTpmStatusReply>(tpm_manager::kGetTpmStatus, request, callback);
 }
 
 void DBusProxy::TakeOwnership(const TakeOwnershipRequest& request,
                               const TakeOwnershipCallback& callback) {
+  CallMethod<TakeOwnershipReply>(
+      tpm_manager::kTakeOwnership, request, callback);
+}
+
+void DBusProxy::DefineNvram(const DefineNvramRequest& request,
+                            const DefineNvramCallback& callback) {
+  CallMethod<DefineNvramReply>(tpm_manager::kDefineNvram, request, callback);
+}
+
+void DBusProxy::DestroyNvram(const DestroyNvramRequest& request,
+                             const DestroyNvramCallback& callback) {
+  CallMethod<DestroyNvramReply>(tpm_manager::kDestroyNvram, request, callback);
+}
+
+void DBusProxy::WriteNvram(const WriteNvramRequest& request,
+                           const WriteNvramCallback& callback) {
+  CallMethod<WriteNvramReply>(tpm_manager::kWriteNvram, request, callback);
+}
+
+void DBusProxy::ReadNvram(const ReadNvramRequest& request,
+                          const ReadNvramCallback& callback) {
+  CallMethod<ReadNvramReply>(tpm_manager::kReadNvram, request, callback);
+}
+
+void DBusProxy::IsNvramDefined(const IsNvramDefinedRequest& request,
+                               const IsNvramDefinedCallback& callback) {
+  CallMethod<IsNvramDefinedReply>(
+      tpm_manager::kIsNvramDefined, request, callback);
+}
+
+void DBusProxy::IsNvramLocked(const IsNvramLockedRequest& request,
+                              const IsNvramLockedCallback& callback) {
+  CallMethod<IsNvramLockedReply>(
+      tpm_manager::kIsNvramLocked, request, callback);
+}
+
+void DBusProxy::GetNvramSize(const GetNvramSizeRequest& request,
+                             const GetNvramSizeCallback& callback) {
+  CallMethod<GetNvramSizeReply>(tpm_manager::kGetNvramSize, request, callback);
+}
+
+template<typename ReplyProtobufType,
+         typename RequestProtobufType,
+         typename CallbackType>
+void DBusProxy::CallMethod(const std::string& method_name,
+                           const RequestProtobufType& request,
+                           const CallbackType& callback) {
   auto on_error = [callback](chromeos::Error* error) {
-    TakeOwnershipReply reply;
+    ReplyProtobufType reply;
     reply.set_status(STATUS_NOT_AVAILABLE);
     callback.Run(reply);
   };
@@ -76,7 +111,7 @@
       kDBusTimeoutMS,
       object_proxy_,
       tpm_manager::kTpmManagerInterface,
-      tpm_manager::kTakeOwnership,
+      method_name,
       callback,
       base::Bind(on_error),
       request);
diff --git a/client/dbus_proxy.h b/client/dbus_proxy.h
index 62660a3..d52c68c 100644
--- a/client/dbus_proxy.h
+++ b/client/dbus_proxy.h
@@ -45,12 +45,34 @@
                     const GetTpmStatusCallback& callback) override;
   void TakeOwnership(const TakeOwnershipRequest& request,
                      const TakeOwnershipCallback& callback) override;
+  void DefineNvram(const DefineNvramRequest& request,
+                   const DefineNvramCallback& callback) override;
+  void DestroyNvram(const DestroyNvramRequest& request,
+                    const DestroyNvramCallback& callback) override;
+  void WriteNvram(const WriteNvramRequest& request,
+                  const WriteNvramCallback& callback) override;
+  void ReadNvram(const ReadNvramRequest& request,
+                 const ReadNvramCallback& callback) override;
+  void IsNvramDefined(const IsNvramDefinedRequest& request,
+                      const IsNvramDefinedCallback& callback) override;
+  void IsNvramLocked(const IsNvramLockedRequest& request,
+                     const IsNvramLockedCallback& callback) override;
+  void GetNvramSize(const GetNvramSizeRequest& request,
+                    const GetNvramSizeCallback& callback) override;
 
   void set_object_proxy(dbus::ObjectProxy* object_proxy) {
     object_proxy_ = object_proxy;
   }
 
  private:
+  // Template method to call a given |method_name| remotely via dbus.
+  template<typename ReplyProtobufType,
+           typename RequestProtobufType,
+           typename CallbackType>
+  void CallMethod(const std::string& method_name,
+                  const RequestProtobufType& request,
+                  const CallbackType& callback);
+
   scoped_refptr<dbus::Bus> bus_;
   dbus::ObjectProxy* object_proxy_;
   DISALLOW_COPY_AND_ASSIGN(DBusProxy);
diff --git a/client/dbus_proxy_test.cc b/client/dbus_proxy_test.cc
index 20a31d0..bb03fc9 100644
--- a/client/dbus_proxy_test.cc
+++ b/client/dbus_proxy_test.cc
@@ -38,6 +38,7 @@
         nullptr, "", dbus::ObjectPath(""));
     proxy_.set_object_proxy(mock_object_proxy_.get());
   }
+
  protected:
   scoped_refptr<StrictMock<dbus::MockObjectProxy>> mock_object_proxy_;
   DBusProxy proxy_;
@@ -55,7 +56,7 @@
     auto response = dbus::Response::CreateEmpty();
     dbus::MessageWriter writer(response.get());
     GetTpmStatusReply reply;
-    reply.set_status(STATUS_NOT_AVAILABLE);
+    reply.set_status(STATUS_SUCCESS);
     reply.set_enabled(true);
     reply.set_owned(true);
     reply.mutable_local_data()->set_owned_by_this_install(true);
@@ -73,7 +74,7 @@
   int callback_count = 0;
   auto callback = [&callback_count](const GetTpmStatusReply& reply) {
     callback_count++;
-    EXPECT_EQ(STATUS_NOT_AVAILABLE, reply.status());
+    EXPECT_EQ(STATUS_SUCCESS, reply.status());
     EXPECT_TRUE(reply.enabled());
     EXPECT_TRUE(reply.owned());
     EXPECT_TRUE(reply.local_data().owned_by_this_install());
@@ -99,7 +100,7 @@
     auto response = dbus::Response::CreateEmpty();
     dbus::MessageWriter writer(response.get());
     TakeOwnershipReply reply;
-    reply.set_status(STATUS_NOT_AVAILABLE);
+    reply.set_status(STATUS_SUCCESS);
     writer.AppendProtoAsArrayOfBytes(reply);
     response_callback.Run(response.release());
   };
@@ -110,11 +111,268 @@
   int callback_count = 0;
   auto callback = [&callback_count](const TakeOwnershipReply& reply) {
     callback_count++;
-    EXPECT_EQ(STATUS_NOT_AVAILABLE, reply.status());
+    EXPECT_EQ(STATUS_SUCCESS, reply.status());
   };
   TakeOwnershipRequest request;
   proxy_.TakeOwnership(request, base::Bind(callback));
   EXPECT_EQ(1, callback_count);
 }
 
+TEST_F(DBusProxyTest, DefineNvram) {
+  uint32_t nvram_index = 5;
+  size_t nvram_length = 32;
+  auto fake_dbus_call = [nvram_index, nvram_length](
+      dbus::MethodCall* method_call,
+      const dbus::MockObjectProxy::ResponseCallback& response_callback) {
+    // Verify request protobuf.
+    dbus::MessageReader reader(method_call);
+    DefineNvramRequest request;
+    EXPECT_TRUE(reader.PopArrayOfBytesAsProto(&request));
+    EXPECT_TRUE(request.has_index());
+    EXPECT_EQ(nvram_index, request.index());
+    EXPECT_TRUE(request.has_length());
+    EXPECT_EQ(nvram_length, request.length());
+    // Create reply protobuf.
+    auto response = dbus::Response::CreateEmpty();
+    dbus::MessageWriter writer(response.get());
+    DefineNvramReply reply;
+    reply.set_status(STATUS_SUCCESS);
+    writer.AppendProtoAsArrayOfBytes(reply);
+    response_callback.Run(response.release());
+  };
+  EXPECT_CALL(*mock_object_proxy_, CallMethodWithErrorCallback(_, _, _, _))
+      .WillOnce(WithArgs<0, 2>(Invoke(fake_dbus_call)));
+  // Set expectations on the outputs.
+  int callback_count = 0;
+  auto callback = [&callback_count](const DefineNvramReply& reply) {
+    callback_count++;
+    EXPECT_EQ(STATUS_SUCCESS, reply.status());
+  };
+  DefineNvramRequest request;
+  request.set_index(nvram_index);
+  request.set_length(nvram_length);
+  proxy_.DefineNvram(request, base::Bind(callback));
+  EXPECT_EQ(1, callback_count);
+}
+
+TEST_F(DBusProxyTest, DestroyNvram) {
+  uint32_t nvram_index = 5;
+  auto fake_dbus_call = [nvram_index](
+      dbus::MethodCall* method_call,
+      const dbus::MockObjectProxy::ResponseCallback& response_callback) {
+    // Verify request protobuf.
+    dbus::MessageReader reader(method_call);
+    DestroyNvramRequest request;
+    EXPECT_TRUE(reader.PopArrayOfBytesAsProto(&request));
+    EXPECT_TRUE(request.has_index());
+    EXPECT_EQ(nvram_index, request.index());
+    // Create reply protobuf.
+    auto response = dbus::Response::CreateEmpty();
+    dbus::MessageWriter writer(response.get());
+    DestroyNvramReply reply;
+    reply.set_status(STATUS_SUCCESS);
+    writer.AppendProtoAsArrayOfBytes(reply);
+    response_callback.Run(response.release());
+  };
+  EXPECT_CALL(*mock_object_proxy_, CallMethodWithErrorCallback(_, _, _, _))
+      .WillOnce(WithArgs<0, 2>(Invoke(fake_dbus_call)));
+  // Set expectations on the outputs.
+  int callback_count = 0;
+  auto callback = [&callback_count](const DestroyNvramReply& reply) {
+    callback_count++;
+    EXPECT_EQ(STATUS_SUCCESS, reply.status());
+  };
+  DestroyNvramRequest request;
+  request.set_index(nvram_index);
+  proxy_.DestroyNvram(request, base::Bind(callback));
+  EXPECT_EQ(1, callback_count);
+}
+TEST_F(DBusProxyTest, WriteNvram) {
+  uint32_t nvram_index = 5;
+  std::string nvram_data("nvram_data");
+  auto fake_dbus_call = [nvram_index, nvram_data](
+      dbus::MethodCall* method_call,
+      const dbus::MockObjectProxy::ResponseCallback& response_callback) {
+    // Verify request protobuf.
+    dbus::MessageReader reader(method_call);
+    WriteNvramRequest request;
+    EXPECT_TRUE(reader.PopArrayOfBytesAsProto(&request));
+    EXPECT_TRUE(request.has_index());
+    EXPECT_EQ(nvram_index, request.index());
+    EXPECT_TRUE(request.has_data());
+    EXPECT_EQ(nvram_data, request.data());
+    // Create reply protobuf.
+    auto response = dbus::Response::CreateEmpty();
+    dbus::MessageWriter writer(response.get());
+    WriteNvramReply reply;
+    reply.set_status(STATUS_SUCCESS);
+    writer.AppendProtoAsArrayOfBytes(reply);
+    response_callback.Run(response.release());
+  };
+  EXPECT_CALL(*mock_object_proxy_, CallMethodWithErrorCallback(_, _, _, _))
+      .WillOnce(WithArgs<0, 2>(Invoke(fake_dbus_call)));
+  // Set expectations on the outputs.
+  int callback_count = 0;
+  auto callback = [&callback_count](const WriteNvramReply& reply) {
+    callback_count++;
+    EXPECT_EQ(STATUS_SUCCESS, reply.status());
+  };
+  WriteNvramRequest request;
+  request.set_index(nvram_index);
+  request.set_data(nvram_data);
+  proxy_.WriteNvram(request, base::Bind(callback));
+  EXPECT_EQ(1, callback_count);
+}
+
+TEST_F(DBusProxyTest, ReadNvram) {
+  uint32_t nvram_index = 5;
+  std::string nvram_data("nvram_data");
+  auto fake_dbus_call = [nvram_index, nvram_data](
+      dbus::MethodCall* method_call,
+      const dbus::MockObjectProxy::ResponseCallback& response_callback) {
+    // Verify request protobuf.
+    dbus::MessageReader reader(method_call);
+    ReadNvramRequest request;
+    EXPECT_TRUE(reader.PopArrayOfBytesAsProto(&request));
+    EXPECT_TRUE(request.has_index());
+    EXPECT_EQ(nvram_index, request.index());
+    // Create reply protobuf.
+    auto response = dbus::Response::CreateEmpty();
+    dbus::MessageWriter writer(response.get());
+    ReadNvramReply reply;
+    reply.set_status(STATUS_SUCCESS);
+    reply.set_data(nvram_data);
+    writer.AppendProtoAsArrayOfBytes(reply);
+    response_callback.Run(response.release());
+  };
+  EXPECT_CALL(*mock_object_proxy_, CallMethodWithErrorCallback(_, _, _, _))
+      .WillOnce(WithArgs<0, 2>(Invoke(fake_dbus_call)));
+  // Set expectations on the outputs.
+  int callback_count = 0;
+  auto callback = [&callback_count, nvram_data](const ReadNvramReply& reply) {
+    callback_count++;
+    EXPECT_EQ(STATUS_SUCCESS, reply.status());
+    EXPECT_TRUE(reply.has_data());
+    EXPECT_EQ(nvram_data, reply.data());
+  };
+  ReadNvramRequest request;
+  request.set_index(nvram_index);
+  proxy_.ReadNvram(request, base::Bind(callback));
+  EXPECT_EQ(1, callback_count);
+}
+
+TEST_F(DBusProxyTest, IsNvramDefined) {
+  uint32_t nvram_index = 5;
+  bool nvram_defined = true;
+  auto fake_dbus_call = [nvram_index, nvram_defined](
+      dbus::MethodCall* method_call,
+      const dbus::MockObjectProxy::ResponseCallback& response_callback) {
+    // Verify request protobuf.
+    dbus::MessageReader reader(method_call);
+    IsNvramDefinedRequest request;
+    EXPECT_TRUE(reader.PopArrayOfBytesAsProto(&request));
+    EXPECT_TRUE(request.has_index());
+    EXPECT_EQ(nvram_index, request.index());
+    // Create reply protobuf.
+    auto response = dbus::Response::CreateEmpty();
+    dbus::MessageWriter writer(response.get());
+    IsNvramDefinedReply reply;
+    reply.set_status(STATUS_SUCCESS);
+    reply.set_is_defined(nvram_defined);
+    writer.AppendProtoAsArrayOfBytes(reply);
+    response_callback.Run(response.release());
+  };
+  EXPECT_CALL(*mock_object_proxy_, CallMethodWithErrorCallback(_, _, _, _))
+      .WillOnce(WithArgs<0, 2>(Invoke(fake_dbus_call)));
+  // Set expectations on the outputs.
+  int callback_count = 0;
+  auto callback = [&callback_count, nvram_defined](
+      const IsNvramDefinedReply& reply) {
+    callback_count++;
+    EXPECT_EQ(STATUS_SUCCESS, reply.status());
+    EXPECT_TRUE(reply.has_is_defined());
+    EXPECT_EQ(nvram_defined, reply.is_defined());
+  };
+  IsNvramDefinedRequest request;
+  request.set_index(nvram_index);
+  proxy_.IsNvramDefined(request, base::Bind(callback));
+  EXPECT_EQ(1, callback_count);
+}
+
+TEST_F(DBusProxyTest, IsNvramLocked) {
+  uint32_t nvram_index = 5;
+  bool nvram_locked = true;
+  auto fake_dbus_call = [nvram_index, nvram_locked](
+      dbus::MethodCall* method_call,
+      const dbus::MockObjectProxy::ResponseCallback& response_callback) {
+    // Verify request protobuf.
+    dbus::MessageReader reader(method_call);
+    IsNvramLockedRequest request;
+    EXPECT_TRUE(reader.PopArrayOfBytesAsProto(&request));
+    EXPECT_TRUE(request.has_index());
+    EXPECT_EQ(nvram_index, request.index());
+    // Create reply protobuf.
+    auto response = dbus::Response::CreateEmpty();
+    dbus::MessageWriter writer(response.get());
+    IsNvramLockedReply reply;
+    reply.set_status(STATUS_SUCCESS);
+    reply.set_is_locked(nvram_locked);
+    writer.AppendProtoAsArrayOfBytes(reply);
+    response_callback.Run(response.release());
+  };
+  EXPECT_CALL(*mock_object_proxy_, CallMethodWithErrorCallback(_, _, _, _))
+      .WillOnce(WithArgs<0, 2>(Invoke(fake_dbus_call)));
+  // Set expectations on the outputs.
+  int callback_count = 0;
+  auto callback = [&callback_count, nvram_locked](
+      const IsNvramLockedReply& reply) {
+    callback_count++;
+    EXPECT_EQ(STATUS_SUCCESS, reply.status());
+    EXPECT_TRUE(reply.has_is_locked());
+    EXPECT_EQ(nvram_locked, reply.is_locked());
+  };
+  IsNvramLockedRequest request;
+  request.set_index(nvram_index);
+  proxy_.IsNvramLocked(request, base::Bind(callback));
+  EXPECT_EQ(1, callback_count);
+}
+
+TEST_F(DBusProxyTest, GetNvramSize) {
+  uint32_t nvram_index = 5;
+  size_t nvram_size = 32;
+  auto fake_dbus_call = [nvram_index, nvram_size](
+      dbus::MethodCall* method_call,
+      const dbus::MockObjectProxy::ResponseCallback& response_callback) {
+    // Verify request protobuf.
+    dbus::MessageReader reader(method_call);
+    GetNvramSizeRequest request;
+    EXPECT_TRUE(reader.PopArrayOfBytesAsProto(&request));
+    EXPECT_TRUE(request.has_index());
+    EXPECT_EQ(nvram_index, request.index());
+    // Create reply protobuf.
+    auto response = dbus::Response::CreateEmpty();
+    dbus::MessageWriter writer(response.get());
+    GetNvramSizeReply reply;
+    reply.set_status(STATUS_SUCCESS);
+    reply.set_size(nvram_size);
+    writer.AppendProtoAsArrayOfBytes(reply);
+    response_callback.Run(response.release());
+  };
+  EXPECT_CALL(*mock_object_proxy_, CallMethodWithErrorCallback(_, _, _, _))
+      .WillOnce(WithArgs<0, 2>(Invoke(fake_dbus_call)));
+  // Set expectations on the outputs.
+  int callback_count = 0;
+  auto callback = [&callback_count, nvram_size](
+      const GetNvramSizeReply& reply) {
+    callback_count++;
+    EXPECT_EQ(STATUS_SUCCESS, reply.status());
+    EXPECT_TRUE(reply.has_size());
+    EXPECT_EQ(nvram_size, reply.size());
+  };
+  GetNvramSizeRequest request;
+  request.set_index(nvram_index);
+  proxy_.GetNvramSize(request, base::Bind(callback));
+  EXPECT_EQ(1, callback_count);
+}
+
 }  // namespace tpm_manager
diff --git a/client/main.cc b/client/main.cc
index 425135b..124d88d 100644
--- a/client/main.cc
+++ b/client/main.cc
@@ -15,6 +15,7 @@
 //
 
 #include <stdio.h>
+#include <stdlib.h>
 #include <sysexits.h>
 
 #include <memory>
@@ -35,13 +36,46 @@
 
 const char kGetTpmStatusCommand[] = "status";
 const char kTakeOwnershipCommand[] = "take_ownership";
+const char kDefineNvramCommand[] = "define_nvram";
+const char kDestroyNvramCommand[] = "destroy_nvram";
+const char kWriteNvramCommand[] = "write_nvram";
+const char kReadNvramCommand[] = "read_nvram";
+const char kIsNvramDefinedCommand[] = "is_nvram_defined";
+const char kIsNvramLockedCommand[] = "is_nvram_locked";
+const char kGetNvramSizeCommand[] = "get_nvram_size";
+
+const char kNvramIndexArg[] = "nvram_index";
+const char kNvramLengthArg[] = "nvram_length";
+const char kNvramDataArg[] = "nvram_data";
+
 const char kUsage[] = R"(
-Usage: tpm_manager_client <command> [<args>]
-Commands:
-  status
+Usage: tpm_manager_client <command> [<arguments>]
+Commands (used as switches):
+  --status
       Prints the current status of the Tpm.
-  take_ownership
+  --take_ownership
       Takes ownership of the Tpm with a random password.
+  --define_nvram
+      Defines an NV space at |nvram_index| with length |nvram_length|.
+  --destroy_nvram
+      Destroys the NV space at |nvram_index|.
+  --write_nvram
+      Writes the NV space at |nvram_index| with |nvram_data|.
+  --read_nvram
+      Prints the contents of the NV space at |nvram_index|.
+  --is_nvram_defined
+      Prints whether the NV space at |nvram_index| is defined.
+  --is_nvram_locked
+      Prints whether the NV space at |nvram_index|  is locked for writing.
+  --get_nvram_size
+      Prints the size of the NV space at |nvram_index|.
+Arguments (used as switches):
+  --nvram_index=<index>
+      Index of NV space to operate on.
+  --nvram_length=<length>
+      Size in bytes of the NV space to be created.
+  --nvram_data=<data>
+      Data to write to NV space.
 )";
 
 using ClientLoopBase = chromeos::Daemon;
@@ -87,6 +121,73 @@
     } else if (command_line->HasSwitch(kTakeOwnershipCommand)) {
       task = base::Bind(&ClientLoop::HandleTakeOwnership,
                         weak_factory_.GetWeakPtr());
+    } else if (command_line->HasSwitch(kDefineNvramCommand)) {
+      if (!command_line->HasSwitch(kNvramIndexArg) ||
+          !command_line->HasSwitch(kNvramLengthArg)) {
+        LOG(ERROR) << "Cannot define nvram without a valid index and length.";
+        return EX_USAGE;
+      }
+      task = base::Bind(
+          &ClientLoop::HandleDefineNvram,
+          weak_factory_.GetWeakPtr(),
+          atoi(command_line->GetSwitchValueASCII(kNvramIndexArg).c_str()),
+          atoi(command_line->GetSwitchValueASCII(kNvramLengthArg).c_str()));
+    } else if (command_line->HasSwitch(kDestroyNvramCommand)) {
+      if (!command_line->HasSwitch(kNvramIndexArg)) {
+        LOG(ERROR) << "Cannot destroy nvram without a valid index.";
+        return EX_USAGE;
+      }
+      task = base::Bind(
+          &ClientLoop::HandleDestroyNvram,
+          weak_factory_.GetWeakPtr(),
+          atoi(command_line->GetSwitchValueASCII(kNvramIndexArg).c_str()));
+    } else if (command_line->HasSwitch(kWriteNvramCommand)) {
+      if (!command_line->HasSwitch(kNvramIndexArg) ||
+          !command_line->HasSwitch(kNvramDataArg)) {
+        LOG(ERROR) << "Cannot write nvram without a valid index and data.";
+        return EX_USAGE;
+      }
+      task = base::Bind(
+          &ClientLoop::HandleWriteNvram,
+          weak_factory_.GetWeakPtr(),
+          atoi(command_line->GetSwitchValueASCII(kNvramIndexArg).c_str()),
+          command_line->GetSwitchValueASCII(kNvramDataArg));
+    } else if (command_line->HasSwitch(kReadNvramCommand)) {
+      if (!command_line->HasSwitch(kNvramIndexArg)) {
+        LOG(ERROR) << "Cannot read nvram without a valid index.";
+        return EX_USAGE;
+      }
+      task = base::Bind(
+          &ClientLoop::HandleReadNvram,
+          weak_factory_.GetWeakPtr(),
+          atoi(command_line->GetSwitchValueASCII(kNvramIndexArg).c_str()));
+    } else if (command_line->HasSwitch(kIsNvramDefinedCommand)) {
+      if (!command_line->HasSwitch(kNvramIndexArg)) {
+        LOG(ERROR) << "Cannot query nvram without a valid index.";
+        return EX_USAGE;
+      }
+      task = base::Bind(
+          &ClientLoop::HandleIsNvramDefined,
+          weak_factory_.GetWeakPtr(),
+          atoi(command_line->GetSwitchValueASCII(kNvramIndexArg).c_str()));
+    } else if (command_line->HasSwitch(kIsNvramLockedCommand)) {
+      if (!command_line->HasSwitch(kNvramIndexArg)) {
+        LOG(ERROR) << "Cannot query nvram without a valid index.";
+        return EX_USAGE;
+      }
+      task = base::Bind(
+          &ClientLoop::HandleIsNvramLocked,
+          weak_factory_.GetWeakPtr(),
+          atoi(command_line->GetSwitchValueASCII(kNvramIndexArg).c_str()));
+    } else if (command_line->HasSwitch(kGetNvramSizeCommand)) {
+      if (!command_line->HasSwitch(kNvramIndexArg)) {
+        LOG(ERROR) << "Cannot query nvram without a valid index.";
+        return EX_USAGE;
+      }
+      task = base::Bind(
+          &ClientLoop::HandleGetNvramSize,
+          weak_factory_.GetWeakPtr(),
+          atoi(command_line->GetSwitchValueASCII(kNvramIndexArg).c_str()));
     } else {
       // Command line arguments did not match any valid commands.
       LOG(ERROR) << "No Valid Command selected.";
@@ -96,12 +197,10 @@
     return EX_OK;
   }
 
-  void PrintGetTpmStatusReply(const GetTpmStatusReply& reply) {
-    if (reply.has_status() && reply.status() == STATUS_NOT_AVAILABLE) {
-      LOG(INFO) << "tpm_managerd is not available.";
-    } else {
-      LOG(INFO) << "TpmStatusReply: " << GetProtoDebugString(reply);
-    }
+  // Template to print reply protobuf.
+  template <typename ProtobufType>
+  void PrintReplyAndQuit(const ProtobufType& reply) {
+    LOG(INFO) << "Message Reply: " << GetProtoDebugString(reply);
     Quit();
   }
 
@@ -109,24 +208,81 @@
     GetTpmStatusRequest request;
     tpm_manager_->GetTpmStatus(
         request,
-        base::Bind(&ClientLoop::PrintGetTpmStatusReply,
+        base::Bind(&ClientLoop::PrintReplyAndQuit<GetTpmStatusReply>,
                    weak_factory_.GetWeakPtr()));
   }
 
-  void PrintTakeOwnershipReply(const TakeOwnershipReply& reply) {
-    if (reply.has_status() && reply.status() == STATUS_NOT_AVAILABLE) {
-      LOG(INFO) << "tpm_managerd is not available.";
-    } else {
-      LOG(INFO) << "TakeOwnershipReply: " << GetProtoDebugString(reply);
-    }
-    Quit();
-  }
-
   void HandleTakeOwnership() {
     TakeOwnershipRequest request;
-    tpm_manager_->TakeOwnership(request,
-                                base::Bind(&ClientLoop::PrintTakeOwnershipReply,
-                                           weak_factory_.GetWeakPtr()));
+    tpm_manager_->TakeOwnership(
+        request,
+        base::Bind(&ClientLoop::PrintReplyAndQuit<TakeOwnershipReply>,
+                   weak_factory_.GetWeakPtr()));
+  }
+
+  void HandleDefineNvram(uint32_t index, size_t length) {
+    DefineNvramRequest request;
+    request.set_index(index);
+    request.set_length(length);
+    tpm_manager_->DefineNvram(
+        request,
+        base::Bind(&ClientLoop::PrintReplyAndQuit<DefineNvramReply>,
+                   weak_factory_.GetWeakPtr()));
+  }
+
+  void HandleDestroyNvram(uint32_t index) {
+    DestroyNvramRequest request;
+    request.set_index(index);
+    tpm_manager_->DestroyNvram(
+        request,
+        base::Bind(&ClientLoop::PrintReplyAndQuit<DestroyNvramReply>,
+                   weak_factory_.GetWeakPtr()));
+  }
+
+  void HandleWriteNvram(uint32_t index, const std::string& data) {
+    WriteNvramRequest request;
+    request.set_index(index);
+    request.set_data(data);
+    tpm_manager_->WriteNvram(
+        request,
+        base::Bind(&ClientLoop::PrintReplyAndQuit<WriteNvramReply>,
+                   weak_factory_.GetWeakPtr()));
+  }
+
+  void HandleReadNvram(uint32_t index) {
+    ReadNvramRequest request;
+    request.set_index(index);
+    tpm_manager_->ReadNvram(
+        request,
+        base::Bind(&ClientLoop::PrintReplyAndQuit<ReadNvramReply>,
+                   weak_factory_.GetWeakPtr()));
+  }
+
+  void HandleIsNvramDefined(uint32_t index) {
+    IsNvramDefinedRequest request;
+    request.set_index(index);
+    tpm_manager_->IsNvramDefined(
+        request,
+        base::Bind(&ClientLoop::PrintReplyAndQuit<IsNvramDefinedReply>,
+                   weak_factory_.GetWeakPtr()));
+  }
+
+  void HandleIsNvramLocked(uint32_t index) {
+    IsNvramLockedRequest request;
+    request.set_index(index);
+    tpm_manager_->IsNvramLocked(
+        request,
+        base::Bind(&ClientLoop::PrintReplyAndQuit<IsNvramLockedReply>,
+                   weak_factory_.GetWeakPtr()));
+  }
+
+  void HandleGetNvramSize(uint32_t index) {
+    GetNvramSizeRequest request;
+    request.set_index(index);
+    tpm_manager_->GetNvramSize(
+        request,
+        base::Bind(&ClientLoop::PrintReplyAndQuit<GetNvramSizeReply>,
+                   weak_factory_.GetWeakPtr()));
   }
 
   // Pointer to a DBus proxy to tpm_managerd.