Added implementation of C_[Create|Copy|Destroy]Object.

BUG=chromium-os:20415,chromium-os:20587
TEST=make runtests
     manual tests on x86-zgb
     > sudo /usr/sbin/chapsd libopencryptoki.so &
     > ./chapsd_test --use_dbus
     > ./chapsd_test

Change-Id: I4995fece98f03d20572337d07d174c0040fadbab
diff --git a/chaps.cc b/chaps.cc
index 17ac924..93c5f77 100644
--- a/chaps.cc
+++ b/chaps.cc
@@ -143,7 +143,7 @@
   if (!pSlotList)
     return CKR_OK;
   LOG_CK_RV_AND_RETURN_IF(slot_list.size() > max_copy, CKR_BUFFER_TOO_SMALL);
-  for (size_t i = 0; i < slot_list.size(); i++) {
+  for (size_t i = 0; i < slot_list.size(); ++i) {
     pSlotList[i] = slot_list[i];
   }
   return CKR_OK;
@@ -245,7 +245,7 @@
     return CKR_OK;
   LOG_CK_RV_AND_RETURN_IF(mechanism_list.size() > max_copy,
                           CKR_BUFFER_TOO_SMALL);
-  for (size_t i = 0; i < mechanism_list.size(); i++) {
+  for (size_t i = 0; i < mechanism_list.size(); ++i) {
     pMechanismList[i] = static_cast<CK_MECHANISM_TYPE>(mechanism_list[i]);
   }
   return CKR_OK;
@@ -399,6 +399,7 @@
   return CKR_OK;
 }
 
+// PKCS #11 v2.20 section 11.6 page 125.
 CK_RV C_Login(CK_SESSION_HANDLE hSession,
               CK_USER_TYPE userType,
               CK_UTF8CHAR_PTR pPin,
@@ -411,7 +412,7 @@
   return CKR_OK;
 }
 
-
+// PKCS #11 v2.20 section 11.6 page 127.
 CK_RV C_Logout(CK_SESSION_HANDLE hSession) {
   LOG_CK_RV_AND_RETURN_IF(!g_is_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
   CK_RV result = g_proxy->Logout(hSession);
@@ -419,4 +420,44 @@
   return CKR_OK;
 }
 
+// PKCS #11 v2.20 section 11.7 page 128.
+CK_RV C_CreateObject(CK_SESSION_HANDLE hSession,
+                     CK_ATTRIBUTE_PTR  pTemplate,
+                     CK_ULONG          ulCount,
+                     CK_OBJECT_HANDLE_PTR phObject) {
+  LOG_CK_RV_AND_RETURN_IF(!g_is_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+  if (pTemplate == NULL_PTR || phObject == NULL_PTR)
+    LOG_CK_RV_AND_RETURN(CKR_ARGUMENTS_BAD);
+  CK_RV result = g_proxy->CreateObject(
+      hSession,
+      chaps::EncodeAttributes(pTemplate, ulCount),
+      chaps::PreservedCK_ULONG(phObject));
+  LOG_CK_RV_AND_RETURN_IF_ERR(result);
+  return CKR_OK;
+}
 
+// PKCS #11 v2.20 section 11.7 page 130.
+CK_RV C_CopyObject(CK_SESSION_HANDLE    hSession,
+                   CK_OBJECT_HANDLE     hObject,
+                   CK_ATTRIBUTE_PTR     pTemplate,
+                   CK_ULONG             ulCount,
+                   CK_OBJECT_HANDLE_PTR phNewObject) {
+  LOG_CK_RV_AND_RETURN_IF(!g_is_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+  if (pTemplate == NULL_PTR || phNewObject == NULL_PTR)
+    LOG_CK_RV_AND_RETURN(CKR_ARGUMENTS_BAD);
+  CK_RV result = g_proxy->CopyObject(
+      hSession,
+      hObject,
+      chaps::EncodeAttributes(pTemplate, ulCount),
+      chaps::PreservedCK_ULONG(phNewObject));
+  LOG_CK_RV_AND_RETURN_IF_ERR(result);
+  return CKR_OK;
+}
+
+// PKCS #11 v2.20 section 11.7 page 131.
+CK_RV C_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject) {
+  LOG_CK_RV_AND_RETURN_IF(!g_is_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+  CK_RV result = g_proxy->DestroyObject(hSession, hObject);
+  LOG_CK_RV_AND_RETURN_IF_ERR(result);
+  return CKR_OK;
+}
diff --git a/chaps.h b/chaps.h
index 320e347..99502e8 100644
--- a/chaps.h
+++ b/chaps.h
@@ -2,10 +2,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <map>
+#include <vector>
+
 namespace chaps {
 
 extern const char* kChapsServicePath;
 extern const char* kChapsServiceName;
 extern const int kTokenLabelSize;
 
+// A PKCS #11 template is encoded as an attribute-value map for dbus-c++.
+typedef std::map<uint32_t, std::vector<uint8_t> > AttributeValueMap;
+
 }  // namespace
diff --git a/chaps_adaptor.cc b/chaps_adaptor.cc
index a32db63..a29395e 100644
--- a/chaps_adaptor.cc
+++ b/chaps_adaptor.cc
@@ -210,4 +210,30 @@
   return service_->Logout(session_id);
 }
 
+void ChapsAdaptor::CreateObject(
+      const uint32_t& session_id,
+      const std::map<uint32_t, std::vector<uint8_t> >& attributes,
+      uint32_t& new_object_handle,
+      uint32_t& result,
+      ::DBus::Error &error) {
+  result = service_->CreateObject(session_id, attributes, &new_object_handle);
+}
+
+void ChapsAdaptor::CopyObject(
+      const uint32_t& session_id,
+      const uint32_t& object_handle,
+      const std::map<uint32_t, std::vector<uint8_t> >& attributes,
+      uint32_t& new_object_handle,
+      uint32_t& result,
+      ::DBus::Error &error) {
+  result = service_->CopyObject(session_id, object_handle, attributes,
+                                &new_object_handle);
+}
+
+uint32_t ChapsAdaptor::DestroyObject(const uint32_t& session_id,
+                                 const uint32_t& object_handle,
+                                 ::DBus::Error &error) {
+  return service_->DestroyObject(session_id, object_handle);
+}
+
 }  // namespace
diff --git a/chaps_adaptor.h b/chaps_adaptor.h
index 239bdf6..6086ffb 100644
--- a/chaps_adaptor.h
+++ b/chaps_adaptor.h
@@ -117,6 +117,22 @@
                          const std::string& optional_pin,
                          ::DBus::Error &error);
   virtual uint32_t Logout(const uint32_t& session_id, ::DBus::Error &error);
+  virtual void CreateObject(
+      const uint32_t& session_id,
+      const std::map<uint32_t, std::vector<uint8_t> >& attributes,
+      uint32_t& new_object_handle,
+      uint32_t& result,
+      ::DBus::Error &error);
+  virtual void CopyObject(
+      const uint32_t& session_id,
+      const uint32_t& object_handle,
+      const std::map<uint32_t, std::vector<uint8_t> >& attributes,
+      uint32_t& new_object_handle,
+      uint32_t& result,
+      ::DBus::Error &error);
+  virtual uint32_t DestroyObject(const uint32_t& session_id,
+                                 const uint32_t& object_handle,
+                                 ::DBus::Error &error);
 
 private:
   ChapsInterface* service_;
diff --git a/chaps_interface.h b/chaps_interface.h
index 8e967ea..be68e26 100644
--- a/chaps_interface.h
+++ b/chaps_interface.h
@@ -11,6 +11,8 @@
 
 #include <base/basictypes.h>
 
+#include "chaps/chaps.h"
+
 namespace chaps {
 
 // ChapsInterface provides an abstract interface closely matching the
@@ -109,6 +111,18 @@
                          const std::string* pin) = 0;
   // PKCS #11 v2.20 section 11.6 page 127.
   virtual uint32_t Logout(uint32_t session_id) = 0;
+  // PKCS #11 v2.20 section 11.7 page 128.
+  virtual uint32_t CreateObject(uint32_t session_id,
+                                const AttributeValueMap& attributes,
+                                uint32_t* new_object_handle) = 0;
+  // PKCS #11 v2.20 section 11.7 page 130.
+  virtual uint32_t CopyObject(uint32_t session_id,
+                              uint32_t object_handle,
+                              const AttributeValueMap& attributes,
+                              uint32_t* new_object_handle) = 0;
+  // PKCS #11 v2.20 section 11.7 page 131.
+  virtual uint32_t DestroyObject(uint32_t session_id,
+                                 uint32_t object_handle) = 0;
 
 private:
   DISALLOW_COPY_AND_ASSIGN(ChapsInterface);
diff --git a/chaps_interface.xml b/chaps_interface.xml
index 7bdc861..3563bc9 100644
--- a/chaps_interface.xml
+++ b/chaps_interface.xml
@@ -208,6 +208,36 @@
         <annotation name="org.freedesktop.DBus.GLib.ReturnVal" value=""/>
       </arg>
     </method>
+
+    <!-- PKCS #11 v2.20 section 11.7 page 128. -->
+    <method name="CreateObject">
+      <arg type="u" name="session_id" direction="in"/>
+      <arg type="a{uay}" name="attributes" direction="in"/>
+      <arg type="u" name="new_object_handle" direction="out"/>
+      <arg type="u" name="result" direction="out">
+        <annotation name="org.freedesktop.DBus.GLib.ReturnVal" value=""/>
+      </arg>
+    </method>
+
+    <!-- PKCS #11 v2.20 section 11.7 page 130. -->
+    <method name="CopyObject">
+      <arg type="u" name="session_id" direction="in"/>
+      <arg type="u" name="object_handle" direction="in"/>
+      <arg type="a{uay}" name="attributes" direction="in"/>
+      <arg type="u" name="new_object_handle" direction="out"/>
+      <arg type="u" name="result" direction="out">
+        <annotation name="org.freedesktop.DBus.GLib.ReturnVal" value=""/>
+      </arg>
+    </method>
+
+    <!-- PKCS #11 v2.20 section 11.7 page 131. -->
+    <method name="DestroyObject">
+      <arg type="u" name="session_id" direction="in"/>
+      <arg type="u" name="object_handle" direction="in"/>
+      <arg type="u" name="result" direction="out">
+        <annotation name="org.freedesktop.DBus.GLib.ReturnVal" value=""/>
+      </arg>
+    </method>
   </interface>
 </node>
 
diff --git a/chaps_proxy.cc b/chaps_proxy.cc
index 79da92e..6e039e2 100644
--- a/chaps_proxy.cc
+++ b/chaps_proxy.cc
@@ -350,4 +350,55 @@
   return result;
 }
 
+uint32_t ChapsProxyImpl::CreateObject(uint32_t session_id,
+                                      const AttributeValueMap& attributes,
+                                      uint32_t* new_object_handle) {
+  LOG_CK_RV_AND_RETURN_IF(!proxy_.get(), CKR_CRYPTOKI_NOT_INITIALIZED);
+  LOG_CK_RV_AND_RETURN_IF(!new_object_handle, CKR_ARGUMENTS_BAD);
+  uint32_t result = CKR_OK;
+  try {
+    proxy_->CreateObject(session_id,
+                         attributes,
+                         *new_object_handle,
+                         result);
+  } catch (DBus::Error err) {
+    result = CKR_GENERAL_ERROR;
+    LOG(ERROR) << "DBus::Error - " << err.what();
+  }
+  return result;
+}
+
+uint32_t ChapsProxyImpl::CopyObject(uint32_t session_id,
+                                    uint32_t object_handle,
+                                    const AttributeValueMap& attributes,
+                                    uint32_t* new_object_handle) {
+  LOG_CK_RV_AND_RETURN_IF(!proxy_.get(), CKR_CRYPTOKI_NOT_INITIALIZED);
+  LOG_CK_RV_AND_RETURN_IF(!new_object_handle, CKR_ARGUMENTS_BAD);
+  uint32_t result = CKR_OK;
+  try {
+    proxy_->CopyObject(session_id,
+                       object_handle,
+                       attributes,
+                       *new_object_handle,
+                       result);
+  } catch (DBus::Error err) {
+    result = CKR_GENERAL_ERROR;
+    LOG(ERROR) << "DBus::Error - " << err.what();
+  }
+  return result;
+}
+
+uint32_t ChapsProxyImpl::DestroyObject(uint32_t session_id,
+                                       uint32_t object_handle) {
+  LOG_CK_RV_AND_RETURN_IF(!proxy_.get(), CKR_CRYPTOKI_NOT_INITIALIZED);
+  uint32_t result = CKR_OK;
+  try {
+    result = proxy_->DestroyObject(session_id, object_handle);
+  } catch (DBus::Error err) {
+    result = CKR_GENERAL_ERROR;
+    LOG(ERROR) << "DBus::Error - " << err.what();
+  }
+  return result;
+}
+
 }  // namespace
diff --git a/chaps_proxy.h b/chaps_proxy.h
index be237dd..2a26f93 100644
--- a/chaps_proxy.h
+++ b/chaps_proxy.h
@@ -88,6 +88,15 @@
                          uint32_t user_type,
                          const std::string* pin);
   virtual uint32_t Logout(uint32_t session_id);
+  virtual uint32_t CreateObject(uint32_t session_id,
+                                const AttributeValueMap& attributes,
+                                uint32_t* new_object_handle);
+  virtual uint32_t CopyObject(uint32_t session_id,
+                              uint32_t object_handle,
+                              const AttributeValueMap& attributes,
+                              uint32_t* new_object_handle);
+  virtual uint32_t DestroyObject(uint32_t session_id,
+                                 uint32_t object_handle);
 
 private:
   // This class provides the link to the dbus-c++ generated proxy.
diff --git a/chaps_proxy_mock.h b/chaps_proxy_mock.h
index 1b572ce..97e30b4 100644
--- a/chaps_proxy_mock.h
+++ b/chaps_proxy_mock.h
@@ -79,6 +79,11 @@
                                             uint32_t));
   MOCK_METHOD3(Login, uint32_t (uint32_t, uint32_t, const std::string*));
   MOCK_METHOD1(Logout, uint32_t (uint32_t));
+  MOCK_METHOD3(CreateObject, uint32_t (uint32_t, const AttributeValueMap&,
+                                       uint32_t*));
+  MOCK_METHOD4(CopyObject, uint32_t (uint32_t, uint32_t,
+                                     const AttributeValueMap&, uint32_t*));
+  MOCK_METHOD2(DestroyObject, uint32_t (uint32_t, uint32_t));
 
 private:
   DISALLOW_COPY_AND_ASSIGN(ChapsProxyMock);
diff --git a/chaps_service_redirect.cc b/chaps_service_redirect.cc
index b0f674d..18cd49c 100644
--- a/chaps_service_redirect.cc
+++ b/chaps_service_redirect.cc
@@ -80,7 +80,7 @@
   // Now, query the actual list.
   result = functions_->C_GetSlotList(token_present, slot_array.get(), &count);
   LOG_CK_RV_AND_RETURN_IF_ERR(result);
-  for (CK_ULONG i = 0; i < count; i++) {
+  for (CK_ULONG i = 0; i < count; ++i) {
     slot_list->push_back(static_cast<uint32_t>(slot_array[i]));
   }
   return CKR_OK;
@@ -187,7 +187,7 @@
   // Now, query the actual list.
   result = functions_->C_GetMechanismList(slot_id, mech_array.get(), &count);
   LOG_CK_RV_AND_RETURN_IF_ERR(result);
-  for (CK_ULONG i = 0; i < count; i++) {
+  for (CK_ULONG i = 0; i < count; ++i) {
     mechanism_list->push_back(static_cast<uint32_t>(mech_array[i]));
   }
   return CKR_OK;
@@ -346,7 +346,6 @@
                                         pin_buffer,
                                         pin_length);
   LOG_CK_RV_AND_RETURN_IF_ERR(result);
-  LOG(INFO) << "Login success!";
   return CKR_OK;
 }
 
@@ -357,4 +356,48 @@
   return CKR_OK;
 }
 
+uint32_t ChapsServiceRedirect::CreateObject(uint32_t session_id,
+                                            const AttributeValueMap& attributes,
+                                            uint32_t* new_object_handle) {
+  CHECK(functions_);
+  LOG_CK_RV_AND_RETURN_IF(!new_object_handle, CKR_ARGUMENTS_BAD);
+  CK_ULONG num_attributes = static_cast<CK_ULONG>(attributes.size());
+  ScopedAttributes decoded_attributes(DecodeAttributes(attributes),
+                                      num_attributes);
+  uint32_t result = functions_->C_CreateObject(
+      session_id,
+      decoded_attributes,
+      num_attributes,
+      PreservedUint32_t(new_object_handle));
+  LOG_CK_RV_AND_RETURN_IF_ERR(result);
+  return CKR_OK;
+}
+
+uint32_t ChapsServiceRedirect::CopyObject(uint32_t session_id,
+                                          uint32_t object_handle,
+                                          const AttributeValueMap& attributes,
+                                          uint32_t* new_object_handle) {
+  CHECK(functions_);
+  LOG_CK_RV_AND_RETURN_IF(!new_object_handle, CKR_ARGUMENTS_BAD);
+  CK_ULONG num_attributes = static_cast<CK_ULONG>(attributes.size());
+  ScopedAttributes decoded_attributes(DecodeAttributes(attributes),
+                                      num_attributes);
+  uint32_t result = functions_->C_CopyObject(
+      session_id,
+      object_handle,
+      decoded_attributes,
+      num_attributes,
+      PreservedUint32_t(new_object_handle));
+  LOG_CK_RV_AND_RETURN_IF_ERR(result);
+  return CKR_OK;
+}
+
+uint32_t ChapsServiceRedirect::DestroyObject(uint32_t session_id,
+                                             uint32_t object_handle) {
+  CHECK(functions_);
+  uint32_t result = functions_->C_DestroyObject(session_id, object_handle);
+  LOG_CK_RV_AND_RETURN_IF_ERR(result);
+  return CKR_OK;
+}
+
 }  // namespace
diff --git a/chaps_service_redirect.h b/chaps_service_redirect.h
index 347bbf5..85935ab 100644
--- a/chaps_service_redirect.h
+++ b/chaps_service_redirect.h
@@ -81,6 +81,16 @@
                          uint32_t user_type,
                          const std::string* pin);
   virtual uint32_t Logout(uint32_t session_id);
+  virtual uint32_t CreateObject(uint32_t session_id,
+                                const AttributeValueMap& attributes,
+                                uint32_t* new_object_handle);
+  virtual uint32_t CopyObject(uint32_t session_id,
+                              uint32_t object_handle,
+                              const AttributeValueMap& attributes,
+                              uint32_t* new_object_handle);
+  virtual uint32_t DestroyObject(uint32_t session_id,
+                                 uint32_t object_handle);
+
 private:
   std::string library_path_;
   void* library_;
diff --git a/chaps_test.cc b/chaps_test.cc
index df0b8b9..525962f 100644
--- a/chaps_test.cc
+++ b/chaps_test.cc
@@ -11,6 +11,7 @@
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
 
+#include "chaps/chaps_utility.h"
 #include "pkcs11/cryptoki.h"
 
 using std::string;
@@ -22,26 +23,26 @@
 using ::testing::SetArgumentPointee;
 
 // Initialize / Finalize tests
-TEST(TestInitialize,InitializeNULL) {
+TEST(TestInitialize, InitializeNULL) {
   chaps::ChapsProxyMock proxy(false);
   EXPECT_EQ(CKR_OK, C_Initialize(NULL_PTR));
   EXPECT_EQ(CKR_OK, C_Finalize(NULL_PTR));
 }
 
-TEST(TestInitializeDeathTest,InitializeOutOfMem) {
+TEST(TestInitializeDeathTest, InitializeOutOfMem) {
   chaps::EnableMockProxy(NULL, false);
   EXPECT_DEATH_IF_SUPPORTED(C_Initialize(NULL_PTR), "Check failed");
   chaps::DisableMockProxy();
 }
 
-TEST(TestInitialize,InitializeTwice) {
+TEST(TestInitialize, InitializeTwice) {
   chaps::ChapsProxyMock proxy(false);
   EXPECT_EQ(CKR_OK, C_Initialize(NULL_PTR));
   EXPECT_EQ(CKR_CRYPTOKI_ALREADY_INITIALIZED, C_Initialize(NULL_PTR));
   EXPECT_EQ(CKR_OK, C_Finalize(NULL_PTR));
 }
 
-TEST(TestInitialize,InitializeWithArgs) {
+TEST(TestInitialize, InitializeWithArgs) {
   chaps::ChapsProxyMock proxy(false);
   CK_C_INITIALIZE_ARGS args;
   memset(&args, 0, sizeof(args));
@@ -49,7 +50,7 @@
   EXPECT_EQ(CKR_OK, C_Finalize(NULL_PTR));
 }
 
-TEST(TestInitialize,InitializeWithBadArgs) {
+TEST(TestInitialize, InitializeWithBadArgs) {
   chaps::ChapsProxyMock proxy(false);
   CK_C_INITIALIZE_ARGS args;
   memset(&args, 0, sizeof(args));
@@ -60,7 +61,7 @@
   EXPECT_EQ(CKR_ARGUMENTS_BAD, C_Initialize(&args));
 }
 
-TEST(TestInitialize,InitializeNoLocking) {
+TEST(TestInitialize, InitializeNoLocking) {
   chaps::ChapsProxyMock proxy(false);
   CK_C_INITIALIZE_ARGS args;
   memset(&args, 0xFF, sizeof(args));
@@ -69,15 +70,15 @@
   EXPECT_EQ(CKR_CANT_LOCK, C_Initialize(&args));
 }
 
-TEST(TestInitialize,FinalizeWithArgs) {
+TEST(TestInitialize, FinalizeWithArgs) {
   EXPECT_EQ(CKR_ARGUMENTS_BAD, C_Finalize((void*)1));
 }
 
-TEST(TestInitialize,FinalizeNotInit) {
+TEST(TestInitialize, FinalizeNotInit) {
   EXPECT_EQ(CKR_CRYPTOKI_NOT_INITIALIZED, C_Finalize(NULL_PTR));
 }
 
-TEST(TestInitialize,Reinitialize) {
+TEST(TestInitialize, Reinitialize) {
   chaps::ChapsProxyMock proxy(false);
   EXPECT_EQ(CKR_OK, C_Initialize(NULL_PTR));
   EXPECT_EQ(CKR_OK, C_Finalize(NULL_PTR));
@@ -85,18 +86,18 @@
 }
 
 // Library Information Tests
-TEST(TestLibInfo,LibInfoOK) {
+TEST(TestLibInfo, LibInfoOK) {
   chaps::ChapsProxyMock proxy(true);
   CK_INFO info;
   EXPECT_EQ(CKR_OK, C_GetInfo(&info));
 }
 
-TEST(TestLibInfo,LibInfoNull) {
+TEST(TestLibInfo, LibInfoNull) {
   chaps::ChapsProxyMock proxy(true);
   EXPECT_EQ(CKR_ARGUMENTS_BAD, C_GetInfo(NULL));
 }
 
-TEST(TestLibInfo,LibInfoNotInit) {
+TEST(TestLibInfo, LibInfoNotInit) {
   chaps::ChapsProxyMock proxy(false);
   CK_INFO info;
   EXPECT_EQ(CKR_CRYPTOKI_NOT_INITIALIZED, C_GetInfo(&info));
@@ -114,9 +115,9 @@
   vector<uint32_t> slot_list_present_;
 };
 
-TEST_F(TestSlotList,SlotListOK) {
+TEST_F(TestSlotList, SlotListOK) {
   chaps::ChapsProxyMock proxy(true);
-  EXPECT_CALL(proxy, GetSlotList(false,_))
+  EXPECT_CALL(proxy, GetSlotList(false, _))
       .WillOnce(DoAll(SetArgumentPointee<1>(slot_list_all_),
                       Return(CKR_OK)));
   CK_SLOT_ID slots[3];
@@ -128,12 +129,12 @@
   EXPECT_EQ(slots[2], slot_list_all_[2]);
 }
 
-TEST_F(TestSlotList,SlotListNull) {
+TEST_F(TestSlotList, SlotListNull) {
   chaps::ChapsProxyMock proxy(true);
   EXPECT_EQ(CKR_ARGUMENTS_BAD, C_GetSlotList(CK_FALSE, NULL, NULL));
 }
 
-TEST_F(TestSlotList,SlotListNotInit) {
+TEST_F(TestSlotList, SlotListNotInit) {
   chaps::ChapsProxyMock proxy(false);
   CK_SLOT_ID slots[3];
   CK_ULONG num_slots = 3;
@@ -141,9 +142,9 @@
             C_GetSlotList(CK_FALSE, slots, &num_slots));
 }
 
-TEST_F(TestSlotList,SlotListNoBuffer) {
+TEST_F(TestSlotList, SlotListNoBuffer) {
   chaps::ChapsProxyMock proxy(true);
-  EXPECT_CALL(proxy, GetSlotList(false,_))
+  EXPECT_CALL(proxy, GetSlotList(false, _))
       .WillOnce(DoAll(SetArgumentPointee<1>(slot_list_all_),
                       Return(CKR_OK)));
   CK_ULONG num_slots = 17;
@@ -151,9 +152,9 @@
   EXPECT_EQ(num_slots, slot_list_all_.size());
 }
 
-TEST_F(TestSlotList,SlotListSmallBuffer) {
+TEST_F(TestSlotList, SlotListSmallBuffer) {
   chaps::ChapsProxyMock proxy(true);
-  EXPECT_CALL(proxy, GetSlotList(false,_))
+  EXPECT_CALL(proxy, GetSlotList(false, _))
       .WillOnce(DoAll(SetArgumentPointee<1>(slot_list_all_),
                       Return(CKR_OK)));
   CK_SLOT_ID slots[2];
@@ -162,9 +163,9 @@
   EXPECT_EQ(num_slots, slot_list_all_.size());
 }
 
-TEST_F(TestSlotList,SlotListLargeBuffer) {
+TEST_F(TestSlotList, SlotListLargeBuffer) {
   chaps::ChapsProxyMock proxy(true);
-  EXPECT_CALL(proxy, GetSlotList(false,_))
+  EXPECT_CALL(proxy, GetSlotList(false, _))
       .WillOnce(DoAll(SetArgumentPointee<1>(slot_list_all_),
                       Return(CKR_OK)));
   CK_SLOT_ID slots[4];
@@ -176,9 +177,9 @@
   EXPECT_EQ(slots[2], slot_list_all_[2]);
 }
 
-TEST_F(TestSlotList,SlotListPresentOnly) {
+TEST_F(TestSlotList, SlotListPresentOnly) {
   chaps::ChapsProxyMock proxy(true);
-  EXPECT_CALL(proxy, GetSlotList(true,_))
+  EXPECT_CALL(proxy, GetSlotList(true, _))
       .WillOnce(DoAll(SetArgumentPointee<1>(slot_list_present_),
                       Return(CKR_OK)));
   CK_SLOT_ID slots[4];
@@ -189,9 +190,9 @@
   EXPECT_EQ(slots[1], slot_list_present_[1]);
 }
 
-TEST_F(TestSlotList,SlotListFailure) {
+TEST_F(TestSlotList, SlotListFailure) {
   chaps::ChapsProxyMock proxy(true);
-  EXPECT_CALL(proxy, GetSlotList(false,_))
+  EXPECT_CALL(proxy, GetSlotList(false, _))
       .WillOnce(DoAll(SetArgumentPointee<1>(slot_list_present_),
                       Return(CKR_FUNCTION_FAILED)));
   CK_SLOT_ID slots[4];
@@ -200,9 +201,9 @@
 }
 
 // Slot Info Tests
-TEST(TestSlotInfo,SlotInfoOK) {
+TEST(TestSlotInfo, SlotInfoOK) {
   chaps::ChapsProxyMock proxy(true);
-  EXPECT_CALL(proxy, GetSlotInfo(1,_,_,_,_,_,_,_))
+  EXPECT_CALL(proxy, GetSlotInfo(1, _, _, _, _, _, _, _))
       .WillOnce(DoAll(SetArgumentPointee<3>(1), Return(CKR_OK)));
   CK_SLOT_INFO info;
   memset(&info, 0, sizeof(info));
@@ -212,27 +213,27 @@
   EXPECT_EQ(1, info.flags);
 }
 
-TEST(TestSlotInfo,SlotInfoNull) {
+TEST(TestSlotInfo, SlotInfoNull) {
   chaps::ChapsProxyMock proxy(true);
   EXPECT_EQ(CKR_ARGUMENTS_BAD, C_GetSlotInfo(1, NULL));
 }
 
-TEST(TestSlotInfo,SlotInfoNotInit) {
+TEST(TestSlotInfo, SlotInfoNotInit) {
   chaps::ChapsProxyMock proxy(false);
   CK_SLOT_INFO info;
   EXPECT_EQ(CKR_CRYPTOKI_NOT_INITIALIZED, C_GetSlotInfo(1, &info));
 }
 
-TEST(TestSlotInfo,SlotInfoFailure) {
+TEST(TestSlotInfo, SlotInfoFailure) {
   chaps::ChapsProxyMock proxy(true);
-  EXPECT_CALL(proxy, GetSlotInfo(1,_,_,_,_,_,_,_))
+  EXPECT_CALL(proxy, GetSlotInfo(1, _, _, _, _, _, _, _))
       .WillOnce(Return(CKR_FUNCTION_FAILED));
   CK_SLOT_INFO info;
   EXPECT_EQ(CKR_FUNCTION_FAILED, C_GetSlotInfo(1, &info));
 }
 
 // Token Info Tests
-TEST(TestTokenInfo,TokenInfoOK) {
+TEST(TestTokenInfo, TokenInfoOK) {
   chaps::ChapsProxyMock proxy(true);
   CK_TOKEN_INFO info;
   memset(&info, 0, sizeof(info));
@@ -242,19 +243,19 @@
   EXPECT_EQ(1, info.flags);
 }
 
-TEST(TestTokenInfo,TokenInfoNull) {
+TEST(TestTokenInfo, TokenInfoNull) {
   chaps::ChapsProxyMock proxy(true);
   EXPECT_EQ(CKR_ARGUMENTS_BAD, C_GetTokenInfo(1, NULL));
 }
 
-TEST(TestTokenInfo,TokenInfoNotInit) {
+TEST(TestTokenInfo, TokenInfoNotInit) {
   chaps::ChapsProxyMock proxy(false);
   CK_TOKEN_INFO info;
   EXPECT_EQ(CKR_CRYPTOKI_NOT_INITIALIZED, C_GetTokenInfo(1, &info));
 }
 
 // WaitSlotEvent Tests
-TEST(TestWaitSlotEvent,SlotEventNonBlock) {
+TEST(TestWaitSlotEvent, SlotEventNonBlock) {
   chaps::ChapsProxyMock proxy(true);
   CK_SLOT_ID slot = 0;
   EXPECT_EQ(CKR_NO_EVENT, C_WaitForSlotEvent(CKF_DONT_BLOCK, &slot, NULL));
@@ -271,7 +272,7 @@
   return NULL;
 }
 
-TEST(TestWaitSlotEvent,SlotEventBlock) {
+TEST(TestWaitSlotEvent, SlotEventBlock) {
   chaps::ChapsProxyMock proxy(true);
   CK_SLOT_ID slot = 0;
   pthread_t thread;
@@ -279,13 +280,13 @@
   EXPECT_EQ(CKR_CRYPTOKI_NOT_INITIALIZED, C_WaitForSlotEvent(0, &slot, NULL));
 }
 
-TEST(TestWaitSlotEvent,SlotEventNotInit) {
+TEST(TestWaitSlotEvent, SlotEventNotInit) {
   chaps::ChapsProxyMock proxy(false);
   CK_SLOT_ID slot = 0;
   EXPECT_EQ(CKR_CRYPTOKI_NOT_INITIALIZED, C_WaitForSlotEvent(0, &slot, NULL));
 }
 
-TEST(TestWaitSlotEvent,SlotEventBadArgs) {
+TEST(TestWaitSlotEvent, SlotEventBadArgs) {
   chaps::ChapsProxyMock proxy(true);
   EXPECT_EQ(CKR_ARGUMENTS_BAD, C_WaitForSlotEvent(0, NULL, NULL));
 }
@@ -302,9 +303,9 @@
   vector<uint32_t> mech_list_present_;
 };
 
-TEST_F(TestMechList,MechListOK) {
+TEST_F(TestMechList, MechListOK) {
   chaps::ChapsProxyMock proxy(true);
-  EXPECT_CALL(proxy, GetMechanismList(false,_))
+  EXPECT_CALL(proxy, GetMechanismList(false, _))
       .WillOnce(DoAll(SetArgumentPointee<1>(mech_list_all_),
                       Return(CKR_OK)));
   CK_SLOT_ID mechs[3];
@@ -316,12 +317,12 @@
   EXPECT_EQ(mechs[2], mech_list_all_[2]);
 }
 
-TEST_F(TestMechList,MechListNull) {
+TEST_F(TestMechList, MechListNull) {
   chaps::ChapsProxyMock proxy(true);
   EXPECT_EQ(CKR_ARGUMENTS_BAD, C_GetMechanismList(CK_FALSE, NULL, NULL));
 }
 
-TEST_F(TestMechList,MechListNotInit) {
+TEST_F(TestMechList, MechListNotInit) {
   chaps::ChapsProxyMock proxy(false);
   CK_SLOT_ID mechs[3];
   CK_ULONG num_mechs = 3;
@@ -329,9 +330,9 @@
             C_GetMechanismList(CK_FALSE, mechs, &num_mechs));
 }
 
-TEST_F(TestMechList,MechListNoBuffer) {
+TEST_F(TestMechList, MechListNoBuffer) {
   chaps::ChapsProxyMock proxy(true);
-  EXPECT_CALL(proxy, GetMechanismList(false,_))
+  EXPECT_CALL(proxy, GetMechanismList(false, _))
       .WillOnce(DoAll(SetArgumentPointee<1>(mech_list_all_),
                       Return(CKR_OK)));
   CK_ULONG num_mechs = 17;
@@ -339,9 +340,9 @@
   EXPECT_EQ(num_mechs, mech_list_all_.size());
 }
 
-TEST_F(TestMechList,MechListSmallBuffer) {
+TEST_F(TestMechList, MechListSmallBuffer) {
   chaps::ChapsProxyMock proxy(true);
-  EXPECT_CALL(proxy, GetMechanismList(false,_))
+  EXPECT_CALL(proxy, GetMechanismList(false, _))
       .WillOnce(DoAll(SetArgumentPointee<1>(mech_list_all_),
                       Return(CKR_OK)));
   CK_SLOT_ID mechs[2];
@@ -351,9 +352,9 @@
   EXPECT_EQ(num_mechs, mech_list_all_.size());
 }
 
-TEST_F(TestMechList,MechListLargeBuffer) {
+TEST_F(TestMechList, MechListLargeBuffer) {
   chaps::ChapsProxyMock proxy(true);
-  EXPECT_CALL(proxy, GetMechanismList(false,_))
+  EXPECT_CALL(proxy, GetMechanismList(false, _))
       .WillOnce(DoAll(SetArgumentPointee<1>(mech_list_all_),
                       Return(CKR_OK)));
   CK_SLOT_ID mechs[4];
@@ -365,9 +366,9 @@
   EXPECT_EQ(mechs[2], mech_list_all_[2]);
 }
 
-TEST_F(TestMechList,MechListPresentOnly) {
+TEST_F(TestMechList, MechListPresentOnly) {
   chaps::ChapsProxyMock proxy(true);
-  EXPECT_CALL(proxy, GetMechanismList(true,_))
+  EXPECT_CALL(proxy, GetMechanismList(true, _))
       .WillOnce(DoAll(SetArgumentPointee<1>(mech_list_present_),
                       Return(CKR_OK)));
   CK_SLOT_ID mechs[4];
@@ -378,9 +379,9 @@
   EXPECT_EQ(mechs[1], mech_list_present_[1]);
 }
 
-TEST_F(TestMechList,MechListFailure) {
+TEST_F(TestMechList, MechListFailure) {
   chaps::ChapsProxyMock proxy(true);
-  EXPECT_CALL(proxy, GetMechanismList(false,_))
+  EXPECT_CALL(proxy, GetMechanismList(false, _))
       .WillOnce(DoAll(SetArgumentPointee<1>(mech_list_present_),
                       Return(CKR_FUNCTION_FAILED)));
   CK_SLOT_ID mechs[4];
@@ -390,9 +391,9 @@
 }
 
 // Mechanism Info Tests
-TEST(TestMechInfo,MechInfoOK) {
+TEST(TestMechInfo, MechInfoOK) {
   chaps::ChapsProxyMock proxy(true);
-  EXPECT_CALL(proxy, GetMechanismInfo(1,2,_,_,_))
+  EXPECT_CALL(proxy, GetMechanismInfo(1, 2, _, _, _))
       .WillOnce(DoAll(SetArgumentPointee<4>(1), Return(CKR_OK)));
   CK_MECHANISM_INFO info;
   memset(&info, 0, sizeof(info));
@@ -400,29 +401,29 @@
   EXPECT_EQ(1, info.flags);
 }
 
-TEST(TestMechInfo,MechInfoNull) {
+TEST(TestMechInfo, MechInfoNull) {
   chaps::ChapsProxyMock proxy(true);
   EXPECT_EQ(CKR_ARGUMENTS_BAD, C_GetMechanismInfo(1, 2, NULL));
 }
 
-TEST(TestMechInfo,MechInfoNotInit) {
+TEST(TestMechInfo, MechInfoNotInit) {
   chaps::ChapsProxyMock proxy(false);
   CK_MECHANISM_INFO info;
   EXPECT_EQ(CKR_CRYPTOKI_NOT_INITIALIZED, C_GetMechanismInfo(1, 2, &info));
 }
 
-TEST(TestMechInfo,MechInfoFailure) {
+TEST(TestMechInfo, MechInfoFailure) {
   chaps::ChapsProxyMock proxy(true);
-  EXPECT_CALL(proxy, GetMechanismInfo(1,2,_,_,_))
+  EXPECT_CALL(proxy, GetMechanismInfo(1, 2, _, _, _))
       .WillOnce(Return(CKR_MECHANISM_INVALID));
   CK_MECHANISM_INFO info;
   EXPECT_EQ(CKR_MECHANISM_INVALID, C_GetMechanismInfo(1, 2, &info));
 }
 
 // Init Token Tests
-TEST(TestInitToken,InitTokenOK) {
+TEST(TestInitToken, InitTokenOK) {
   chaps::ChapsProxyMock proxy(true);
-  EXPECT_CALL(proxy, InitToken(1,_,_))
+  EXPECT_CALL(proxy, InitToken(1, _, _))
       .WillOnce(Return(CKR_OK));
   CK_UTF8CHAR_PTR pin = (CK_UTF8CHAR_PTR)"test";
   CK_UTF8CHAR label[32];
@@ -431,7 +432,7 @@
   EXPECT_EQ(CKR_OK, C_InitToken(1, pin, 4, label));
 }
 
-TEST(TestInitToken,InitTokenNotInit) {
+TEST(TestInitToken, InitTokenNotInit) {
   chaps::ChapsProxyMock proxy(false);
   CK_UTF8CHAR label[32];
   memset(label, ' ', 32);
@@ -439,14 +440,14 @@
   EXPECT_EQ(CKR_CRYPTOKI_NOT_INITIALIZED, C_InitToken(1, NULL, 0, label));
 }
 
-TEST(TestInitToken,InitTokenNULLLabel) {
+TEST(TestInitToken, InitTokenNULLLabel) {
   chaps::ChapsProxyMock proxy(true);
   EXPECT_EQ(CKR_ARGUMENTS_BAD, C_InitToken(1, NULL, 0, NULL));
 }
 
-TEST(TestInitToken,InitTokenNULLPin) {
+TEST(TestInitToken, InitTokenNULLPin) {
   chaps::ChapsProxyMock proxy(true);
-  EXPECT_CALL(proxy, InitToken(1,_,_))
+  EXPECT_CALL(proxy, InitToken(1, _, _))
       .WillOnce(Return(CKR_OK));
   CK_UTF8CHAR label[32];
   memset(label, ' ', 32);
@@ -454,9 +455,9 @@
   EXPECT_EQ(CKR_OK, C_InitToken(1, NULL, 0, label));
 }
 
-TEST(TestInitToken,InitTokenFail) {
+TEST(TestInitToken, InitTokenFail) {
   chaps::ChapsProxyMock proxy(true);
-  EXPECT_CALL(proxy, InitToken(1,_,_))
+  EXPECT_CALL(proxy, InitToken(1, _, _))
       .WillOnce(Return(CKR_PIN_INVALID));
   CK_UTF8CHAR label[32];
   memset(label, ' ', 32);
@@ -465,57 +466,57 @@
 }
 
 // Init PIN Tests
-TEST(TestInitPIN,InitPINOK) {
+TEST(TestInitPIN, InitPINOK) {
   chaps::ChapsProxyMock proxy(true);
-  EXPECT_CALL(proxy, InitPIN(1,_))
+  EXPECT_CALL(proxy, InitPIN(1, _))
       .WillOnce(Return(CKR_OK));
   CK_UTF8CHAR_PTR pin = (CK_UTF8CHAR_PTR)"test";
   EXPECT_EQ(CKR_OK, C_InitPIN(1, pin, 4));
 }
 
-TEST(TestInitPIN,InitPINNotInit) {
+TEST(TestInitPIN, InitPINNotInit) {
   chaps::ChapsProxyMock proxy(false);
   EXPECT_EQ(CKR_CRYPTOKI_NOT_INITIALIZED, C_InitPIN(1, NULL, 0));
 }
 
-TEST(TestInitPIN,InitPINNULLPin) {
+TEST(TestInitPIN, InitPINNULLPin) {
   chaps::ChapsProxyMock proxy(true);
-  EXPECT_CALL(proxy, InitPIN(1,_))
+  EXPECT_CALL(proxy, InitPIN(1, _))
       .WillOnce(Return(CKR_OK));
   EXPECT_EQ(CKR_OK, C_InitPIN(1, NULL, 0));
 }
 
-TEST(TestInitPIN,InitPINFail) {
+TEST(TestInitPIN, InitPINFail) {
   chaps::ChapsProxyMock proxy(true);
-  EXPECT_CALL(proxy, InitPIN(1,_))
+  EXPECT_CALL(proxy, InitPIN(1, _))
       .WillOnce(Return(CKR_PIN_INVALID));
   EXPECT_EQ(CKR_PIN_INVALID, C_InitPIN(1, NULL, 0));
 }
 
 // Set PIN Tests
-TEST(TestSetPIN,SetPINOK) {
+TEST(TestSetPIN, SetPINOK) {
   chaps::ChapsProxyMock proxy(true);
-  EXPECT_CALL(proxy, SetPIN(1,_,_))
+  EXPECT_CALL(proxy, SetPIN(1, _, _))
       .WillOnce(Return(CKR_OK));
   CK_UTF8CHAR_PTR pin = (CK_UTF8CHAR_PTR)"test";
   EXPECT_EQ(CKR_OK, C_SetPIN(1, pin, 4, pin, 4));
 }
 
-TEST(TestSetPIN,SetPINNotInit) {
+TEST(TestSetPIN, SetPINNotInit) {
   chaps::ChapsProxyMock proxy(false);
   EXPECT_EQ(CKR_CRYPTOKI_NOT_INITIALIZED, C_SetPIN(1, NULL, 0, NULL, 0));
 }
 
-TEST(TestSetPIN,SetPINNULLPin) {
+TEST(TestSetPIN, SetPINNULLPin) {
   chaps::ChapsProxyMock proxy(true);
-  EXPECT_CALL(proxy, SetPIN(1,_,_))
+  EXPECT_CALL(proxy, SetPIN(1, _, _))
       .WillOnce(Return(CKR_OK));
   EXPECT_EQ(CKR_OK, C_SetPIN(1, NULL, 0, NULL, 0));
 }
 
-TEST(TestSetPIN,SetPINFail) {
+TEST(TestSetPIN, SetPINFail) {
   chaps::ChapsProxyMock proxy(true);
-  EXPECT_CALL(proxy, SetPIN(1,_,_))
+  EXPECT_CALL(proxy, SetPIN(1, _, _))
       .WillOnce(Return(CKR_PIN_INVALID));
   EXPECT_EQ(CKR_PIN_INVALID, C_SetPIN(1, NULL, 0, NULL, 0));
 }
@@ -523,29 +524,29 @@
 // Open Session Tests
 TEST(TestOpenSession, OpenSessionOK) {
   chaps::ChapsProxyMock proxy(true);
-  EXPECT_CALL(proxy, OpenSession(1,CKF_SERIAL_SESSION,_))
+  EXPECT_CALL(proxy, OpenSession(1, CKF_SERIAL_SESSION, _))
       .WillOnce(DoAll(SetArgumentPointee<2>(3), Return(CKR_OK)));
   CK_SESSION_HANDLE session;
   EXPECT_EQ(CKR_OK, C_OpenSession(1, CKF_SERIAL_SESSION, NULL, NULL, &session));
   EXPECT_EQ(session, 3);
 }
 
-TEST(TestOpenSession,OpenSessionNotInit) {
+TEST(TestOpenSession, OpenSessionNotInit) {
   chaps::ChapsProxyMock proxy(false);
   CK_SESSION_HANDLE session;
   EXPECT_EQ(CKR_CRYPTOKI_NOT_INITIALIZED,
             C_OpenSession(1, CKF_SERIAL_SESSION, NULL, NULL, &session));
 }
 
-TEST(TestOpenSession,OpenSessionNull) {
+TEST(TestOpenSession, OpenSessionNull) {
   chaps::ChapsProxyMock proxy(true);
   EXPECT_EQ(CKR_ARGUMENTS_BAD,
             C_OpenSession(1, CKF_SERIAL_SESSION, NULL, NULL, NULL));
 }
 
-TEST(TestOpenSession,OpenSessionFail) {
+TEST(TestOpenSession, OpenSessionFail) {
   chaps::ChapsProxyMock proxy(true);
-  EXPECT_CALL(proxy, OpenSession(1,CKF_SERIAL_SESSION,_))
+  EXPECT_CALL(proxy, OpenSession(1, CKF_SERIAL_SESSION, _))
       .WillOnce(Return(CKR_SESSION_COUNT));
   CK_SESSION_HANDLE session;
   EXPECT_EQ(CKR_SESSION_COUNT,
@@ -560,12 +561,12 @@
   EXPECT_EQ(CKR_OK, C_CloseSession(1));
 }
 
-TEST(TestCloseSession,CloseSessionNotInit) {
+TEST(TestCloseSession, CloseSessionNotInit) {
   chaps::ChapsProxyMock proxy(false);
   EXPECT_EQ(CKR_CRYPTOKI_NOT_INITIALIZED, C_CloseSession(1));
 }
 
-TEST(TestCloseSession,CloseSessionFail) {
+TEST(TestCloseSession, CloseSessionFail) {
   chaps::ChapsProxyMock proxy(true);
   EXPECT_CALL(proxy, CloseSession(1))
       .WillOnce(Return(CKR_SESSION_HANDLE_INVALID));
@@ -579,12 +580,12 @@
   EXPECT_EQ(CKR_OK, C_CloseAllSessions(1));
 }
 
-TEST(TestCloseSession,CloseAllSessionsNotInit) {
+TEST(TestCloseSession, CloseAllSessionsNotInit) {
   chaps::ChapsProxyMock proxy(false);
   EXPECT_EQ(CKR_CRYPTOKI_NOT_INITIALIZED, C_CloseAllSessions(1));
 }
 
-TEST(TestCloseSession,CloseAllSessionsFail) {
+TEST(TestCloseSession, CloseAllSessionsFail) {
   chaps::ChapsProxyMock proxy(true);
   EXPECT_CALL(proxy, CloseAllSessions(1))
       .WillOnce(Return(CKR_SLOT_ID_INVALID));
@@ -594,27 +595,27 @@
 // Get Session Info Tests
 TEST(TestGetSessionInfo, GetSessionInfoOK) {
   chaps::ChapsProxyMock proxy(true);
-  EXPECT_CALL(proxy, GetSessionInfo(1,_,_,_,_))
+  EXPECT_CALL(proxy, GetSessionInfo(1, _, _, _, _))
       .WillOnce(DoAll(SetArgumentPointee<1>(2), Return(CKR_OK)));
   CK_SESSION_INFO info;
   EXPECT_EQ(CKR_OK, C_GetSessionInfo(1, &info));
   EXPECT_EQ(2, info.slotID);
 }
 
-TEST(TestGetSessionInfo,GetSessionInfoNotInit) {
+TEST(TestGetSessionInfo, GetSessionInfoNotInit) {
   chaps::ChapsProxyMock proxy(false);
   CK_SESSION_INFO info;
   EXPECT_EQ(CKR_CRYPTOKI_NOT_INITIALIZED, C_GetSessionInfo(1, &info));
 }
 
-TEST(TestGetSessionInfo,GetSessionInfoNull) {
+TEST(TestGetSessionInfo, GetSessionInfoNull) {
   chaps::ChapsProxyMock proxy(true);
   EXPECT_EQ(CKR_ARGUMENTS_BAD, C_GetSessionInfo(1, NULL));
 }
 
-TEST(TestGetSessionInfo,GetSessionInfoFail) {
+TEST(TestGetSessionInfo, GetSessionInfoFail) {
   chaps::ChapsProxyMock proxy(true);
-  EXPECT_CALL(proxy, GetSessionInfo(1,_,_,_,_))
+  EXPECT_CALL(proxy, GetSessionInfo(1, _, _, _, _))
       .WillOnce(Return(CKR_SESSION_HANDLE_INVALID));
   CK_SESSION_INFO info;
   EXPECT_EQ(CKR_SESSION_HANDLE_INVALID, C_GetSessionInfo(1, &info));
@@ -632,7 +633,7 @@
 
 TEST_F(TestGetOperationState, GetOperationStateOK) {
   chaps::ChapsProxyMock proxy(true);
-  EXPECT_CALL(proxy, GetOperationState(1,_))
+  EXPECT_CALL(proxy, GetOperationState(1, _))
       .WillOnce(DoAll(SetArgumentPointee<1>(buffer_), Return(CKR_OK)));
   CK_BYTE buffer[3];
   CK_ULONG size = 3;
@@ -642,12 +643,12 @@
   EXPECT_EQ(buffer[2], buffer_[2]);
 }
 
-TEST_F(TestGetOperationState,GetOperationStateNull) {
+TEST_F(TestGetOperationState, GetOperationStateNull) {
   chaps::ChapsProxyMock proxy(true);
   EXPECT_EQ(CKR_ARGUMENTS_BAD, C_GetOperationState(CK_FALSE, NULL, NULL));
 }
 
-TEST_F(TestGetOperationState,GetOperationStateNotInit) {
+TEST_F(TestGetOperationState, GetOperationStateNotInit) {
   chaps::ChapsProxyMock proxy(false);
   CK_BYTE buffer[3];
   CK_ULONG size = 3;
@@ -655,18 +656,18 @@
             C_GetOperationState(1, buffer, &size));
 }
 
-TEST_F(TestGetOperationState,GetOperationStateNoBuffer) {
+TEST_F(TestGetOperationState, GetOperationStateNoBuffer) {
   chaps::ChapsProxyMock proxy(true);
-  EXPECT_CALL(proxy, GetOperationState(1,_))
+  EXPECT_CALL(proxy, GetOperationState(1, _))
       .WillOnce(DoAll(SetArgumentPointee<1>(buffer_), Return(CKR_OK)));
   CK_ULONG size = 17;
   EXPECT_EQ(CKR_OK, C_GetOperationState(1, NULL, &size));
   EXPECT_EQ(size, buffer_.size());
 }
 
-TEST_F(TestGetOperationState,GetOperationStateSmallBuffer) {
+TEST_F(TestGetOperationState, GetOperationStateSmallBuffer) {
   chaps::ChapsProxyMock proxy(true);
-  EXPECT_CALL(proxy, GetOperationState(1,_))
+  EXPECT_CALL(proxy, GetOperationState(1, _))
       .WillOnce(DoAll(SetArgumentPointee<1>(buffer_), Return(CKR_OK)));
   CK_BYTE buffer[2];
   CK_ULONG size = 2;
@@ -674,9 +675,9 @@
   EXPECT_EQ(size, buffer_.size());
 }
 
-TEST_F(TestGetOperationState,GetOperationStateLargeBuffer) {
+TEST_F(TestGetOperationState, GetOperationStateLargeBuffer) {
   chaps::ChapsProxyMock proxy(true);
-  EXPECT_CALL(proxy, GetOperationState(1,_))
+  EXPECT_CALL(proxy, GetOperationState(1, _))
       .WillOnce(DoAll(SetArgumentPointee<1>(buffer_), Return(CKR_OK)));
   CK_BYTE buffer[4];
   CK_ULONG size = 4;
@@ -687,9 +688,9 @@
   EXPECT_EQ(buffer[2], buffer_[2]);
 }
 
-TEST_F(TestGetOperationState,GetOperationStateFailure) {
+TEST_F(TestGetOperationState, GetOperationStateFailure) {
   chaps::ChapsProxyMock proxy(true);
-  EXPECT_CALL(proxy, GetOperationState(1,_))
+  EXPECT_CALL(proxy, GetOperationState(1, _))
       .WillOnce(Return(CKR_STATE_UNSAVEABLE));
   CK_BYTE buffer[3];
   CK_ULONG size = 3;
@@ -699,14 +700,14 @@
 // Set Operation State Tests
 TEST(TestSetOperationState, SetOperationStateOK) {
   chaps::ChapsProxyMock proxy(true);
-  EXPECT_CALL(proxy, SetOperationState(1,_,2,3))
+  EXPECT_CALL(proxy, SetOperationState(1, _, 2, 3))
       .WillOnce(Return(CKR_OK));
   CK_BYTE buffer[3];
   CK_ULONG size = 3;
   EXPECT_EQ(CKR_OK, C_SetOperationState(1, buffer, size, 2, 3));
 }
 
-TEST(TestSetOperationState,SetOperationStateNotInit) {
+TEST(TestSetOperationState, SetOperationStateNotInit) {
   chaps::ChapsProxyMock proxy(false);
   CK_BYTE buffer[3];
   CK_ULONG size = 3;
@@ -714,14 +715,14 @@
             C_SetOperationState(1, buffer, size, 2, 3));
 }
 
-TEST(TestSetOperationState,SetOperationStateNull) {
+TEST(TestSetOperationState, SetOperationStateNull) {
   chaps::ChapsProxyMock proxy(true);
   EXPECT_EQ(CKR_ARGUMENTS_BAD, C_SetOperationState(1, NULL, 0, 2, 3));
 }
 
-TEST(TestSetOperationState,SetOperationStateFail) {
+TEST(TestSetOperationState, SetOperationStateFail) {
   chaps::ChapsProxyMock proxy(true);
-  EXPECT_CALL(proxy, SetOperationState(1,_,2,3))
+  EXPECT_CALL(proxy, SetOperationState(1, _, 2, 3))
       .WillOnce(Return(CKR_SESSION_HANDLE_INVALID));
   CK_BYTE buffer[3];
   CK_ULONG size = 3;
@@ -730,53 +731,190 @@
 }
 
 // Login Tests
-TEST(TestLogin,LoginOK) {
+TEST(TestLogin, LoginOK) {
   chaps::ChapsProxyMock proxy(true);
-  EXPECT_CALL(proxy, Login(1,CKU_USER,_))
+  EXPECT_CALL(proxy, Login(1, CKU_USER, _))
       .WillOnce(Return(CKR_OK));
   CK_UTF8CHAR_PTR pin = (CK_UTF8CHAR_PTR)"test";
   EXPECT_EQ(CKR_OK, C_Login(1, CKU_USER, pin, 4));
 }
 
-TEST(TestLogin,LoginNotInit) {
+TEST(TestLogin, LoginNotInit) {
   chaps::ChapsProxyMock proxy(false);
   EXPECT_EQ(CKR_CRYPTOKI_NOT_INITIALIZED, C_Login(1, CKU_USER, NULL, 0));
 }
 
-TEST(TestLogin,LoginNULLPin) {
+TEST(TestLogin, LoginNULLPin) {
   chaps::ChapsProxyMock proxy(true);
-  EXPECT_CALL(proxy, Login(1,CKU_USER,_))
+  EXPECT_CALL(proxy, Login(1, CKU_USER, _))
       .WillOnce(Return(CKR_OK));
   EXPECT_EQ(CKR_OK, C_Login(1, CKU_USER, NULL, 0));
 }
 
-TEST(TestLogin,LoginFail) {
+TEST(TestLogin, LoginFail) {
   chaps::ChapsProxyMock proxy(true);
-  EXPECT_CALL(proxy, Login(1,CKU_USER,_))
+  EXPECT_CALL(proxy, Login(1, CKU_USER, _))
       .WillOnce(Return(CKR_PIN_INVALID));
   EXPECT_EQ(CKR_PIN_INVALID, C_Login(1, CKU_USER, NULL, 0));
 }
 
 // Logout Tests
-TEST(TestLogout,LogoutOK) {
+TEST(TestLogout, LogoutOK) {
   chaps::ChapsProxyMock proxy(true);
   EXPECT_CALL(proxy, Logout(1))
       .WillOnce(Return(CKR_OK));
   EXPECT_EQ(CKR_OK, C_Logout(1));
 }
 
-TEST(TestLogout,LogoutNotInit) {
+TEST(TestLogout, LogoutNotInit) {
   chaps::ChapsProxyMock proxy(false);
   EXPECT_EQ(CKR_CRYPTOKI_NOT_INITIALIZED, C_Logout(1));
 }
 
-TEST(TestLogout,LogoutFail) {
+TEST(TestLogout, LogoutFail) {
   chaps::ChapsProxyMock proxy(true);
   EXPECT_CALL(proxy, Logout(1))
       .WillOnce(Return(CKR_SESSION_HANDLE_INVALID));
   EXPECT_EQ(CKR_SESSION_HANDLE_INVALID, C_Logout(1));
 }
 
+// CreateObject Tests
+class TestCreateObject : public ::testing::Test {
+protected:
+  vector<uint8_t> s2v(const string& s) {
+    const uint8_t* buf = reinterpret_cast<const uint8_t*>(s.data());
+    return vector<uint8_t>(&buf[0], &buf[s.length()]);
+  }
+
+  virtual void SetUp() {
+    attribute_template_[0].type = CKA_ID;
+    attribute_template_[0].ulValueLen = 4;
+    attribute_template_[0].pValue = const_cast<char*>("test");
+    attribute_template_[1].type = CKA_AC_ISSUER;
+    attribute_template_[1].ulValueLen = 5;
+    attribute_template_[1].pValue = const_cast<char*>("test2");
+    attribute_map_[CKA_ID] = s2v("test");
+    attribute_map_[CKA_AC_ISSUER] = s2v("test2");
+  }
+
+  void CompareAttributes(CK_ATTRIBUTE_PTR a1, CK_ATTRIBUTE_PTR a2, int size) {
+    for (int i = 0; i < size; ++i) {
+      int j = 0;
+      for (; j < size; ++j) {
+        if (a1[i].type == a2[j].type)
+          break;
+      }
+      EXPECT_LT(j, size);
+      EXPECT_EQ(a1[i].ulValueLen, a2[j].ulValueLen);
+      EXPECT_EQ(0, memcmp(a1[i].pValue, a2[j].pValue, a1[i].ulValueLen));
+    }
+  }
+
+  chaps::AttributeValueMap attribute_map_;
+  CK_ATTRIBUTE attribute_template_[2];
+};
+
+TEST_F(TestCreateObject, CreateObjectOK) {
+  chaps::ChapsProxyMock proxy(true);
+  EXPECT_CALL(proxy, CreateObject(1, attribute_map_, _))
+      .WillOnce(DoAll(SetArgumentPointee<2>(3), Return(CKR_OK)));
+  CK_OBJECT_HANDLE object_handle = 0;
+  EXPECT_EQ(CKR_OK, C_CreateObject(1, attribute_template_, 2, &object_handle));
+  EXPECT_EQ(3, object_handle);
+}
+
+TEST_F(TestCreateObject, CreateObjectNotInit) {
+  chaps::ChapsProxyMock proxy(false);
+  CK_OBJECT_HANDLE object_handle = 0;
+  EXPECT_EQ(CKR_CRYPTOKI_NOT_INITIALIZED, C_CreateObject(1,
+                                                         attribute_template_, 2,
+                                                         &object_handle));
+}
+
+TEST_F(TestCreateObject, CreateObjectNULLHandle) {
+  chaps::ChapsProxyMock proxy(true);
+  EXPECT_EQ(CKR_ARGUMENTS_BAD, C_CreateObject(1, attribute_template_, 2, NULL));
+}
+
+TEST_F(TestCreateObject, CreateObjectFail) {
+  chaps::ChapsProxyMock proxy(true);
+  EXPECT_CALL(proxy, CreateObject(1, attribute_map_, _))
+      .WillOnce(Return(CKR_ATTRIBUTE_TYPE_INVALID));
+  CK_OBJECT_HANDLE object_handle = 0;
+  EXPECT_EQ(CKR_ATTRIBUTE_TYPE_INVALID, C_CreateObject(1,
+                                                       attribute_template_, 2,
+                                                       &object_handle));
+}
+
+// CopyObject Tests
+TEST_F(TestCreateObject, CopyObjectOK) {
+  chaps::ChapsProxyMock proxy(true);
+  EXPECT_CALL(proxy, CopyObject(1, 2, attribute_map_, _))
+      .WillOnce(DoAll(SetArgumentPointee<3>(3), Return(CKR_OK)));
+  CK_OBJECT_HANDLE object_handle = 0;
+  EXPECT_EQ(CKR_OK, C_CopyObject(1, 2, attribute_template_, 2, &object_handle));
+  EXPECT_EQ(3, object_handle);
+}
+
+TEST_F(TestCreateObject, CopyObjectNotInit) {
+  chaps::ChapsProxyMock proxy(false);
+  CK_OBJECT_HANDLE object_handle = 0;
+  EXPECT_EQ(CKR_CRYPTOKI_NOT_INITIALIZED, C_CopyObject(1, 2,
+                                                       attribute_template_, 2,
+                                                       &object_handle));
+}
+
+TEST_F(TestCreateObject, CopyObjectNULLHandle) {
+  chaps::ChapsProxyMock proxy(true);
+  EXPECT_EQ(CKR_ARGUMENTS_BAD, C_CopyObject(1, 2,
+                                            attribute_template_, 2,
+                                            NULL));
+}
+
+TEST_F(TestCreateObject, CopyObjectFail) {
+  chaps::ChapsProxyMock proxy(true);
+  EXPECT_CALL(proxy, CopyObject(1, 2, attribute_map_, _))
+      .WillOnce(Return(CKR_ATTRIBUTE_TYPE_INVALID));
+  CK_OBJECT_HANDLE object_handle = 0;
+  EXPECT_EQ(CKR_ATTRIBUTE_TYPE_INVALID, C_CopyObject(1, 2,
+                                                     attribute_template_, 2,
+                                                     &object_handle));
+}
+
+// Attribute Tests
+TEST_F(TestCreateObject, TestAttributes) {
+  chaps::AttributeValueMap tmp_map =
+      chaps::EncodeAttributes(attribute_template_, 2);
+  EXPECT_TRUE(tmp_map == attribute_map_);
+  CK_ATTRIBUTE_PTR tmp_array = chaps::DecodeAttributes(attribute_map_);
+  CompareAttributes(tmp_array, attribute_template_, 2);
+  EXPECT_TRUE(attribute_map_ == chaps::EncodeAttributes(tmp_array, 2));
+  CK_ATTRIBUTE_PTR tmp_array_2 = chaps::DecodeAttributes(tmp_map);
+  CompareAttributes(attribute_template_, tmp_array_2, 2);
+  chaps::FreeAttributes(tmp_array, 2);
+  chaps::FreeAttributes(tmp_array_2, 2);
+}
+
+// DestroyObject Tests
+TEST(TestDestroyObject, DestroyObjectOK) {
+  chaps::ChapsProxyMock proxy(true);
+  EXPECT_CALL(proxy, DestroyObject(1, 2))
+      .WillOnce(Return(CKR_OK));
+  EXPECT_EQ(CKR_OK, C_DestroyObject(1, 2));
+}
+
+TEST(TestDestroyObject, DestroyObjectNotInit) {
+  chaps::ChapsProxyMock proxy(false);
+  EXPECT_EQ(CKR_CRYPTOKI_NOT_INITIALIZED, C_DestroyObject(1, 2));
+}
+
+TEST(TestDestroyObject, DestroyObjectFail) {
+  chaps::ChapsProxyMock proxy(true);
+  EXPECT_CALL(proxy, DestroyObject(1, 2))
+      .WillOnce(Return(CKR_OBJECT_HANDLE_INVALID));
+  EXPECT_EQ(CKR_OBJECT_HANDLE_INVALID, C_DestroyObject(1, 2));
+}
+
 int main(int argc, char** argv) {
   ::testing::InitGoogleMock(&argc, argv);
   return RUN_ALL_TESTS();
diff --git a/chaps_utility.cc b/chaps_utility.cc
index f15babb..a3d69e5 100644
--- a/chaps_utility.cc
+++ b/chaps_utility.cc
@@ -2,11 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chaps_utility.h"
+#include "chaps/chaps_utility.h"
 
 #include <stdio.h>
 
-#include "chaps.h"
+#include <base/logging.h>
+
+#include "chaps/chaps.h"
 
 namespace chaps {
 
@@ -15,6 +17,48 @@
 const char* kChapsServiceName = "org.chromium.Chaps";
 const int kTokenLabelSize = 32;
 
+AttributeValueMap EncodeAttributes(CK_ATTRIBUTE_PTR attributes,
+                                   CK_ULONG num_attributes) {
+  AttributeValueMap encoded_attributes;
+  for (CK_ULONG i = 0; i < num_attributes; ++i) {
+    // Interpret the value as a byte array; we don't care what it actually is.
+    uint8_t* byte_value = reinterpret_cast<uint8_t*>(attributes[i].pValue);
+    // Encode the value as a vector.
+    std::vector<uint8_t> encoded_value(&byte_value[0],
+                                       &byte_value[attributes[i].ulValueLen]);
+    // Push the entry into the map.
+    encoded_attributes[attributes[i].type] = encoded_value;
+  }
+  return encoded_attributes;
+}
+
+CK_ATTRIBUTE_PTR DecodeAttributes(const AttributeValueMap& attributes) {
+  CK_ATTRIBUTE_PTR decoded_attributes = new CK_ATTRIBUTE[attributes.size()];
+  CHECK(decoded_attributes) << "Out of memory!";
+  AttributeValueMap::const_iterator iterator = attributes.begin();
+  for (size_t i = 0; iterator != attributes.end(); ++iterator, ++i) {
+    decoded_attributes[i].type =
+        static_cast<CK_ATTRIBUTE_TYPE>(iterator->first);
+    decoded_attributes[i].ulValueLen =
+        static_cast<CK_ULONG>(iterator->second.size());
+    decoded_attributes[i].pValue = new CK_BYTE[iterator->second.size()];
+    CHECK(decoded_attributes[i].pValue) << "Out of memory!";
+    memcpy(decoded_attributes[i].pValue,
+           &iterator->second.front(),
+           iterator->second.size());
+  }
+  return decoded_attributes;
+}
+
+void FreeAttributes(CK_ATTRIBUTE_PTR attributes, CK_ULONG num_attributes) {
+  for (CK_ULONG i = 0; i < num_attributes; ++i) {
+    // This was allocated as a CK_BYTE array, delete the same way.
+    CK_BYTE_PTR value = reinterpret_cast<CK_BYTE_PTR>(attributes[i].pValue);
+    delete [] value;
+  }
+  delete [] attributes;
+}
+
 const char* CK_RVToString(CK_RV value) {
   switch (value) {
     case CKR_OK:
diff --git a/chaps_utility.h b/chaps_utility.h
index 258af8e..5394be3 100644
--- a/chaps_utility.h
+++ b/chaps_utility.h
@@ -9,6 +9,7 @@
 
 #include <base/basictypes.h>
 
+#include "chaps/chaps.h"
 #include "pkcs11/cryptoki.h"
 
 namespace chaps {
@@ -87,6 +88,41 @@
 };
 
 typedef PreservedValue<CK_ULONG, uint32_t> PreservedCK_ULONG;
+typedef PreservedValue<uint32_t, CK_ULONG> PreservedUint32_t;
+
+// This function encodes a PKCS #11 template as an attribute-value map.
+AttributeValueMap EncodeAttributes(CK_ATTRIBUTE_PTR attributes,
+                                   CK_ULONG num_attributes);
+
+// This function decodes an attribute-value map into a PKCS #11 template.  The
+// number of attributes in the template will always be the same as the size of
+// the attribute map provided. The CK_ATTRIBUTE_PTR returned should be freed
+// using FreeAttributes.
+CK_ATTRIBUTE_PTR DecodeAttributes(const AttributeValueMap& attributes);
+
+// This function frees an attribute list created by DecodeAttributes.
+void FreeAttributes(CK_ATTRIBUTE_PTR attributes, CK_ULONG num_attributes);
+
+// This class frees attributes on destruction; similar to scoped_ptr but for use
+// with DecodeAttributes and FreeAttributes.
+class ScopedAttributes {
+ public:
+  ScopedAttributes(CK_ATTRIBUTE_PTR attributes, CK_ULONG num_attributes)
+      : attributes_(attributes),
+        num_attributes_(num_attributes) {}
+  ~ScopedAttributes() {
+    FreeAttributes(attributes_, num_attributes_);
+  }
+  operator CK_ATTRIBUTE_PTR() {
+    return attributes_;
+  }
+
+ private:
+  CK_ATTRIBUTE_PTR attributes_;
+  CK_ULONG num_attributes_;
+
+  DISALLOW_COPY_AND_ASSIGN(ScopedAttributes);
+};
 
 }  // namespace
 #endif  // CHAPS_CHAPS_UTILITY_H
diff --git a/chapsd_test.cc b/chapsd_test.cc
index 486fed7..9798c62 100644
--- a/chapsd_test.cc
+++ b/chapsd_test.cc
@@ -11,12 +11,15 @@
 #include "chaps/chaps_interface.h"
 #include "chaps/chaps_proxy.h"
 #include "chaps/chaps_service_redirect.h"
+#include "chaps/chaps_utility.h"
 
 using std::string;
 using std::vector;
 
 DEFINE_bool(use_dbus, false, "");
 
+namespace chaps {
+
 static chaps::ChapsInterface* CreateChapsInstance() {
   if (FLAGS_use_dbus) {
     scoped_ptr<chaps::ChapsProxyImpl> proxy(new chaps::ChapsProxyImpl());
@@ -70,7 +73,7 @@
   EXPECT_EQ(CKR_OK, result);
   EXPECT_LT(0, slot_list.size());
   printf("Slots: ");
-  for (size_t i = 0; i < slot_list.size(); i++) {
+  for (size_t i = 0; i < slot_list.size(); ++i) {
     printf("%d ", slot_list[i]);
   }
   printf("\n");
@@ -298,6 +301,42 @@
   EXPECT_EQ(CKR_SESSION_HANDLE_INVALID, chaps_->Logout(17));
 }
 
+TEST_F(TestP11Session, CreateObject) {
+  CK_OBJECT_CLASS class_value = CKO_DATA;
+  CK_UTF8CHAR label[] = "A data object";
+  CK_UTF8CHAR application[] = "An application";
+  CK_BYTE data[] = "Sample data";
+  CK_BYTE data2[] = "Sample data 2";
+  CK_BBOOL false_value = CK_FALSE;
+  CK_ATTRIBUTE attributes[] = {
+    {CKA_CLASS, &class_value, sizeof(class_value)},
+    {CKA_TOKEN, &false_value, sizeof(false_value)},
+    {CKA_LABEL, label, sizeof(label)-1},
+    {CKA_APPLICATION, application, sizeof(application)-1},
+    {CKA_VALUE, data, sizeof(data)}
+  };
+  CK_ATTRIBUTE attributes2[] = {
+    {CKA_VALUE, data2, sizeof(data2)}
+  };
+  AttributeValueMap attribute_map = EncodeAttributes(attributes, 5);
+  uint32_t handle = 0;
+  EXPECT_EQ(CKR_ARGUMENTS_BAD,
+            chaps_->CreateObject(session_id_, attribute_map, NULL));
+  EXPECT_EQ(CKR_OK, chaps_->CreateObject(session_id_, attribute_map, &handle));
+  AttributeValueMap attribute_map2 = EncodeAttributes(attributes2, 1);
+  uint32_t handle2 = 0;
+  EXPECT_EQ(CKR_OK,
+            chaps_->CopyObject(session_id_, handle, attribute_map2, &handle2));
+  EXPECT_EQ(CKR_OK, chaps_->DestroyObject(session_id_, handle));
+  EXPECT_EQ(CKR_OK, chaps_->DestroyObject(session_id_, handle2));
+  EXPECT_EQ(CKR_SESSION_HANDLE_INVALID,
+            chaps_->CreateObject(17, attribute_map, &handle));
+  EXPECT_EQ(CKR_TEMPLATE_INCOMPLETE,
+            chaps_->CreateObject(session_id_, attribute_map2, &handle));
+}
+
+} // namespace chaps
+
 int main(int argc, char** argv) {
   google::ParseCommandLineFlags(&argc, &argv, true);
   ::testing::InitGoogleTest(&argc, argv);