security: code cleanup and doxygen improvements in tpm::BackEndOsx

Change-Id: I6d6d77ab315a10c280e7643d4cec5269ed10fe5e
diff --git a/.jenkins.d/40-standalone-header-compilation.sh b/.jenkins.d/40-standalone-header-compilation.sh
index 770e036..cb600ee 100755
--- a/.jenkins.d/40-standalone-header-compilation.sh
+++ b/.jenkins.d/40-standalone-header-compilation.sh
@@ -7,7 +7,7 @@
 
 CXX=${CXX:-g++}
 STD=-std=c++14
-CXXFLAGS="-O2 -Wall -Wno-unused-local-typedef $(pkg-config --cflags libndn-cxx)"
+CXXFLAGS="-O2 -Wall -Wno-unused-const-variable -Wno-unused-local-typedef $(pkg-config --cflags libndn-cxx)"
 INCLUDEDIR="$(pkg-config --variable=includedir libndn-cxx)"/ndn-cxx
 
 echo "Using: $CXX $STD $CXXFLAGS"
diff --git a/src/net/detail/network-monitor-impl-osx.cpp b/src/net/detail/network-monitor-impl-osx.cpp
index c4e45e6..507c3fd 100644
--- a/src/net/detail/network-monitor-impl-osx.cpp
+++ b/src/net/detail/network-monitor-impl-osx.cpp
@@ -54,6 +54,7 @@
 
 #include "../network-address.hpp"
 #include "../../name.hpp"
+#include "../../util/cf-string-osx.hpp"
 #include "../../util/logger.hpp"
 
 #include <ifaddrs.h>      // for getifaddrs()
@@ -203,26 +204,6 @@
   this->emitSignal(onEnumerationCompleted);
 }
 
-static std::string
-convertToStdString(CFStringRef cfStr)
-{
-  const char* cStr = CFStringGetCStringPtr(cfStr, kCFStringEncodingASCII);
-  if (cStr != nullptr) {
-    // fast path
-    return cStr;
-  }
-
-  // reserve space for the string + null terminator
-  std::string str(CFStringGetLength(cfStr) + 1, '\0');
-  if (!CFStringGetCString(cfStr, &str.front(), str.size(), kCFStringEncodingASCII)) {
-    BOOST_THROW_EXCEPTION(NetworkMonitorImplOsx::Error("CFString conversion failed"));
-  }
-
-  // drop the null terminator, std::string doesn't need it
-  str.pop_back();
-  return str;
-}
-
 std::set<std::string>
 NetworkMonitorImplOsx::getInterfaceNames() const
 {
@@ -241,7 +222,7 @@
   size_t count = CFArrayGetCount(interfaces);
   for (size_t i = 0; i != count; ++i) {
     auto ifName = (CFStringRef)CFArrayGetValueAtIndex(interfaces, i);
-    ifNames.insert(convertToStdString(ifName));
+    ifNames.insert(util::cfstring::toStdString(ifName));
   }
   return ifNames;
 }
@@ -268,9 +249,7 @@
 NetworkMonitorImplOsx::getInterfaceState(const NetworkInterface& netif) const
 {
   CFReleaser<CFStringRef> linkName =
-    CFStringCreateWithCString(kCFAllocatorDefault,
-                              ("State:/Network/Interface/" + netif.getName() + "/Link").data(),
-                              kCFStringEncodingASCII);
+    util::cfstring::fromStdString("State:/Network/Interface/" + netif.getName() + "/Link");
 
   CFReleaser<CFDictionaryRef> dict =
     (CFDictionaryRef)SCDynamicStoreCopyValue(m_scStore.get(), linkName.get());
@@ -426,7 +405,7 @@
 
   size_t count = CFArrayGetCount(changedKeys);
   for (size_t i = 0; i != count; ++i) {
-    Name key(convertToStdString((CFStringRef)CFArrayGetValueAtIndex(changedKeys, i)));
+    Name key(util::cfstring::toStdString((CFStringRef)CFArrayGetValueAtIndex(changedKeys, i)));
     std::string ifName = key.at(-2).toUri();
 
     auto ifIt = m_interfaces.find(ifName);
diff --git a/src/security/tpm/back-end-file.hpp b/src/security/tpm/back-end-file.hpp
index cc0db78..bf29644 100644
--- a/src/security/tpm/back-end-file.hpp
+++ b/src/security/tpm/back-end-file.hpp
@@ -34,90 +34,55 @@
 namespace tpm {
 
 /**
- * @brief The back-end implementation of file-based TPM.
+ * @brief The back-end implementation of a file-based TPM.
  *
  * In this TPM, each private key is stored in a separate file with permission 0400, i.e.,
  * owner read-only.  The key is stored in PKCS #1 format in base64 encoding.
  */
-class BackEndFile : public BackEnd
+class BackEndFile final : public BackEnd
 {
 public:
   /**
-   * @brief Create file-based TPM backend
-   * @param location Directory to store private keys
+   * @brief Create file-based TPM backend.
+   *
+   * @param location Directory to store private keys.
    */
   explicit
   BackEndFile(const std::string& location = "");
 
-  ~BackEndFile() override;
+  ~BackEndFile() final;
 
   static const std::string&
   getScheme();
 
 private: // inherited from tpm::BackEnd
-  /**
-   * @return True if a key with name @p keyName exists in TPM.
-   */
   bool
   doHasKey(const Name& keyName) const final;
 
-  /**
-   * @return The handle of a key with name @p keyName, or nullptr if the key does not exist
-   */
   unique_ptr<KeyHandle>
   doGetKeyHandle(const Name& keyName) const final;
 
-  /**
-   * @brief Create key for @p identityName according to @p params.
-   *
-   * The created key is named as: /<identityName>/[keyId]/KEY
-   * The key name is set in the returned KeyHandle.
-   *
-   * If the key with the same name exists, the old key will be overwritten.
-   * The behavior of using KeyHandler of removed key is undefined.
-   *
-   * @return The handle of the created key.
-   */
   unique_ptr<KeyHandle>
   doCreateKey(const Name& identityName, const KeyParams& params) final;
 
-  /**
-   * @brief Delete a key with name @p keyName.
-   *
-   * @throw Error the deletion failed
-   */
   void
   doDeleteKey(const Name& keyName) final;
 
-  /**
-   * @return A private key with name @p keyName in encrypted PKCS #8 format using password @p pw
-   * @throw Error the key cannot be exported, e.g., not enough privilege
-   */
   ConstBufferPtr
   doExportKey(const Name& keyName, const char* pw, size_t pwLen) final;
 
-  /**
-   * @brief Import a private key in encrypted PKCS #8 format
-   *
-   * @param keyName The name of imported private key
-   * @param buf Pointer to the key in encrypted PKCS #8 format
-   * @param size The size of the key in encrypted PKCS #8 format
-   * @param pw The password to decrypt the key
-   * @param pwLen The length of the password
-   * @throw Error import failed
-   */
   void
   doImportKey(const Name& keyName, const uint8_t* buf, size_t size, const char* pw, size_t pwLen) final;
 
 private:
   /**
-   * @brief Load a private key with name @p keyName from the key file directory
+   * @brief Load a private key with name @p keyName from the key directory.
    */
   unique_ptr<transform::PrivateKey>
   loadKey(const Name& keyName) const;
 
   /**
-   * @brief Save a private key with name @p keyName into the key file directory
+   * @brief Save a private key with name @p keyName into the key directory.
    */
   void
   saveKey(const Name& keyName, const transform::PrivateKey& key);
diff --git a/src/security/tpm/back-end-mem.hpp b/src/security/tpm/back-end-mem.hpp
index 5a40de4..07ceb6e 100644
--- a/src/security/tpm/back-end-mem.hpp
+++ b/src/security/tpm/back-end-mem.hpp
@@ -29,75 +29,40 @@
 namespace tpm {
 
 /**
- * @brief The back-end implementation of in-memory TPM.
+ * @brief The back-end implementation of an in-memory TPM.
  */
-class BackEndMem : public BackEnd
+class BackEndMem final : public BackEnd
 {
 public:
   /**
-   * @brief Create memory-based TPM backend
-   * @param location Not used (required by the TPM-registration interface)
+   * @brief Create memory-based TPM backend.
+   *
+   * @param location Not used (required by the TPM registration interface).
    */
   explicit
   BackEndMem(const std::string& location = "");
 
-  ~BackEndMem() override;
+  ~BackEndMem() final;
 
   static const std::string&
   getScheme();
 
 private: // inherited from tpm::BackEnd
-
-  /**
-   * @return True if a key with name @p keyName exists in TPM.
-   */
   bool
   doHasKey(const Name& keyName) const final;
 
-  /**
-   * @return The handle of a key with name @p keyName, or nullptr if the key does not exist
-   */
   unique_ptr<KeyHandle>
   doGetKeyHandle(const Name& keyName) const final;
 
-  /**
-   * @brief Create key for @p identityName according to @p params.
-   *
-   * The created key is named as: /<identityName>/[keyId]/KEY
-   * The key name is set in the returned KeyHandle.
-   * If the key with the same name is created, the old one will be removed.
-   * The behavior of using KeyHandler of removed key is undefined.
-   *
-   * @return The handle of the created key.
-   */
   unique_ptr<KeyHandle>
   doCreateKey(const Name& identityName, const KeyParams& params) final;
 
-  /**
-   * @brief Delete a key with name @p keyName.
-   *
-   * @throw Error the deletion failed
-   */
   void
   doDeleteKey(const Name& keyName) final;
 
-  /**
-   * @return A private key with name @p keyName in encrypted PKCS #8 format using password @p pw
-   * @throw Error the key cannot be exported, e.g., not enough privilege
-   */
   ConstBufferPtr
   doExportKey(const Name& keyName, const char* pw, size_t pwLen) final;
 
-  /**
-   * @brief Import a private key in encrypted PKCS #8 format
-   *
-   * @param keyName The name of imported private key
-   * @param buf Pointer to the key in encrypted PKCS #8 format
-   * @param size The size of the key in encrypted PKCS #8 format
-   * @param pw The password to decrypt the key
-   * @param pwLen The length of password
-   * @throw Error import failed
-   */
   void
   doImportKey(const Name& keyName, const uint8_t* buf, size_t size, const char* pw, size_t pwLen) final;
 
diff --git a/src/security/tpm/back-end-osx.cpp b/src/security/tpm/back-end-osx.cpp
index 3a2035e..139b7d2 100644
--- a/src/security/tpm/back-end-osx.cpp
+++ b/src/security/tpm/back-end-osx.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2017 Regents of the University of California.
+ * Copyright (c) 2013-2018 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -23,66 +23,37 @@
 #include "key-handle-osx.hpp"
 #include "tpm.hpp"
 #include "../transform/private-key.hpp"
+#include "../../util/cf-string-osx.hpp"
 
-#include <CoreServices/CoreServices.h>
-#include <Security/SecDigestTransform.h>
-#include <Security/SecRandom.h>
 #include <Security/Security.h>
 
 namespace ndn {
 namespace security {
 namespace tpm {
 
+namespace cfstring = util::cfstring;
 using util::CFReleaser;
 
 class BackEndOsx::Impl
 {
 public:
-  Impl()
-    : isTerminalMode(false)
-  {
-  }
-
-  /**
-   * @brief Get private key reference with name @p keyName.
-   *
-   * @param keyName
-   * @returns reference to the key
-   */
-  CFReleaser<SecKeychainItemRef>
-  getKey(const Name& keyName)
-  {
-    CFReleaser<CFStringRef> keyLabel = CFStringCreateWithCString(nullptr, keyName.toUri().c_str(),
-                                                                 kCFStringEncodingUTF8);
-
-    CFReleaser<CFMutableDictionaryRef> attrDict =
-      CFDictionaryCreateMutable(nullptr, 5, &kCFTypeDictionaryKeyCallBacks, nullptr);
-
-    CFDictionaryAddValue(attrDict.get(), kSecClass, kSecClassKey);
-    CFDictionaryAddValue(attrDict.get(), kSecAttrLabel, keyLabel.get());
-    CFDictionaryAddValue(attrDict.get(), kSecAttrKeyClass, kSecAttrKeyClassPrivate);
-    CFDictionaryAddValue(attrDict.get(), kSecReturnRef, kCFBooleanTrue);
-
-    CFReleaser<SecKeychainItemRef> keyItem;
-    // C-style cast is used as per Apple convention
-    OSStatus res = SecItemCopyMatching((CFDictionaryRef)attrDict.get(), (CFTypeRef*)&keyItem.get());
-    keyItem.retain();
-
-    if (res != errSecSuccess) {
-      if (res == errSecAuthFailed) {
-        BOOST_THROW_EXCEPTION(Error("Fail to unlock the keychain"));
-      }
-      BOOST_THROW_EXCEPTION(std::domain_error("Key does not exist"));
-    }
-
-    return keyItem;
-  }
-
-public:
   SecKeychainRef keyChainRef;
-  bool isTerminalMode;
+  bool isTerminalMode = false;
 };
 
+static CFReleaser<CFDataRef>
+makeCFDataNoCopy(const uint8_t* buf, size_t buflen)
+{
+  return CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, buf, buflen, kCFAllocatorNull);
+}
+
+static CFReleaser<CFMutableDictionaryRef>
+makeCFMutableDictionary()
+{
+  return CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
+                                   &kCFTypeDictionaryKeyCallBacks,
+                                   &kCFTypeDictionaryValueCallBacks);
+}
 
 static CFTypeRef
 getAsymKeyType(KeyType keyType)
@@ -107,7 +78,7 @@
   case DigestAlgorithm::SHA512:
     return kSecDigestSHA2;
   default:
-    return 0;
+    return nullptr;
   }
 }
 
@@ -128,14 +99,43 @@
   }
 }
 
+/**
+ * @brief Get reference to private key with name @p keyName.
+ * @param keyName
+ */
+static CFReleaser<SecKeychainItemRef>
+getKey(const Name& keyName)
+{
+  auto keyLabel = cfstring::fromStdString(keyName.toUri());
+
+  auto attrDict = makeCFMutableDictionary();
+  CFDictionaryAddValue(attrDict.get(), kSecClass, kSecClassKey);
+  CFDictionaryAddValue(attrDict.get(), kSecAttrLabel, keyLabel.get());
+  CFDictionaryAddValue(attrDict.get(), kSecAttrKeyClass, kSecAttrKeyClassPrivate);
+  CFDictionaryAddValue(attrDict.get(), kSecReturnRef, kCFBooleanTrue);
+
+  CFReleaser<SecKeychainItemRef> keyItem;
+  // C-style cast is used as per Apple convention
+  OSStatus res = SecItemCopyMatching((CFDictionaryRef)attrDict.get(), (CFTypeRef*)&keyItem.get());
+  keyItem.retain();
+
+  if (res != errSecSuccess) {
+    if (res == errSecAuthFailed) {
+      BOOST_THROW_EXCEPTION(BackEnd::Error("Fail to unlock the keychain"));
+    }
+    return nullptr;
+  }
+
+  return keyItem;
+}
+
 BackEndOsx::BackEndOsx(const std::string&)
   : m_impl(make_unique<Impl>())
 {
   SecKeychainSetUserInteractionAllowed(!m_impl->isTerminalMode);
 
   OSStatus res = SecKeychainCopyDefault(&m_impl->keyChainRef);
-
-  if (res == errSecNoDefaultKeychain) { //If no default key chain, create one.
+  if (res == errSecNoDefaultKeychain) {
     BOOST_THROW_EXCEPTION(Error("No default keychain, create one first"));
   }
 }
@@ -166,12 +166,11 @@
 BackEndOsx::isTpmLocked() const
 {
   SecKeychainStatus keychainStatus;
-
   OSStatus res = SecKeychainGetStatus(m_impl->keyChainRef, &keychainStatus);
   if (res != errSecSuccess)
     return true;
   else
-    return ((kSecUnlockStateStatus & keychainStatus) == 0);
+    return (kSecUnlockStateStatus & keychainStatus) == 0;
 }
 
 bool
@@ -203,8 +202,8 @@
   }
 
   // Set input
-  CFReleaser<CFDataRef> dataRef = CFDataCreateWithBytesNoCopy(nullptr, buf, size, kCFAllocatorNull);
-  SecTransformSetAttribute(signer.get(), kSecTransformInputAttributeName, dataRef.get(), &error.get());
+  auto data = makeCFDataNoCopy(buf, size);
+  SecTransformSetAttribute(signer.get(), kSecTransformInputAttributeName, data.get(), &error.get());
   if (error != nullptr) {
     BOOST_THROW_EXCEPTION(Error("Fail to configure input of signer"));
   }
@@ -223,7 +222,7 @@
 
   // Set digest length
   long digestSize = getDigestSize(digestAlgo);
-  CFReleaser<CFNumberRef> cfDigestSize = CFNumberCreate(nullptr, kCFNumberLongType, &digestSize);
+  CFReleaser<CFNumberRef> cfDigestSize = CFNumberCreate(kCFAllocatorDefault, kCFNumberLongType, &digestSize);
   SecTransformSetAttribute(signer.get(), kSecDigestLengthAttribute, cfDigestSize.get(), &error.get());
   if (error != nullptr) {
     BOOST_THROW_EXCEPTION(Error("Fail to configure digest length of signer"));
@@ -253,8 +252,8 @@
     BOOST_THROW_EXCEPTION(Error("Fail to create decryptor"));
   }
 
-  CFReleaser<CFDataRef> dataRef = CFDataCreateWithBytesNoCopy(nullptr, cipherText, cipherSize, kCFAllocatorNull);
-  SecTransformSetAttribute(decryptor.get(), kSecTransformInputAttributeName, dataRef.get(), &error.get());
+  auto data = makeCFDataNoCopy(cipherText, cipherSize);
+  SecTransformSetAttribute(decryptor.get(), kSecTransformInputAttributeName, data.get(), &error.get());
   if (error != nullptr) {
     BOOST_THROW_EXCEPTION(Error("Fail to configure decryptor input"));
   }
@@ -304,12 +303,9 @@
 bool
 BackEndOsx::doHasKey(const Name& keyName) const
 {
-  CFReleaser<CFStringRef> keyLabel = CFStringCreateWithCString(nullptr, keyName.toUri().c_str(),
-                                                               kCFStringEncodingUTF8);
+  auto keyLabel = cfstring::fromStdString(keyName.toUri());
 
-  CFReleaser<CFMutableDictionaryRef> attrDict =
-    CFDictionaryCreateMutable(nullptr, 4, &kCFTypeDictionaryKeyCallBacks, nullptr);
-
+  auto attrDict = makeCFMutableDictionary();
   CFDictionaryAddValue(attrDict.get(), kSecClass, kSecClassKey);
   CFDictionaryAddValue(attrDict.get(), kSecAttrLabel, keyLabel.get());
   CFDictionaryAddValue(attrDict.get(), kSecReturnRef, kCFBooleanTrue);
@@ -325,15 +321,12 @@
 unique_ptr<KeyHandle>
 BackEndOsx::doGetKeyHandle(const Name& keyName) const
 {
-  CFReleaser<SecKeychainItemRef> keyItem;
-  try {
-    keyItem = m_impl->getKey(keyName);
-  }
-  catch (const std::domain_error&) {
+  CFReleaser<SecKeychainItemRef> keychainItem = getKey(keyName);
+  if (keychainItem == nullptr) {
     return nullptr;
   }
 
-  return make_unique<KeyHandleOsx>((SecKeyRef)keyItem.get());
+  return make_unique<KeyHandleOsx>((SecKeyRef)keychainItem.get());
 }
 
 unique_ptr<KeyHandle>
@@ -356,10 +349,9 @@
       BOOST_THROW_EXCEPTION(Tpm::Error("Fail to create a key pair: Unsupported key type"));
     }
   }
-  CFReleaser<CFNumberRef> cfKeySize = CFNumberCreate(nullptr, kCFNumberIntType, &keySize);
+  CFReleaser<CFNumberRef> cfKeySize = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &keySize);
 
-  CFReleaser<CFMutableDictionaryRef> attrDict =
-    CFDictionaryCreateMutable(nullptr, 2, &kCFTypeDictionaryKeyCallBacks, nullptr);
+  auto attrDict = makeCFMutableDictionary();
   CFDictionaryAddValue(attrDict.get(), kSecAttrKeyType, getAsymKeyType(keyType));
   CFDictionaryAddValue(attrDict.get(), kSecAttrKeySizeInBits, cfKeySize.get());
 
@@ -372,8 +364,6 @@
   publicKey.retain();
   privateKey.retain();
 
-  BOOST_ASSERT(privateKey != nullptr);
-
   if (res != errSecSuccess) {
     if (res == errSecAuthFailed) {
       BOOST_THROW_EXCEPTION(Error("Fail to unlock the keychain"));
@@ -405,15 +395,13 @@
 void
 BackEndOsx::doDeleteKey(const Name& keyName)
 {
-  CFReleaser<CFStringRef> keyLabel = CFStringCreateWithCString(nullptr, keyName.toUri().c_str(),
-                                                               kCFStringEncodingUTF8);
+  auto keyLabel = cfstring::fromStdString(keyName.toUri());
 
-  CFReleaser<CFMutableDictionaryRef> searchDict =
-    CFDictionaryCreateMutable(nullptr, 5, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
-
+  auto searchDict = makeCFMutableDictionary();
   CFDictionaryAddValue(searchDict.get(), kSecClass, kSecClassKey);
   CFDictionaryAddValue(searchDict.get(), kSecAttrLabel, keyLabel.get());
   CFDictionaryAddValue(searchDict.get(), kSecMatchLimit, kSecMatchLimitAll);
+
   OSStatus res = SecItemDelete(searchDict.get());
 
   if (res != errSecSuccess) {
@@ -429,22 +417,18 @@
 ConstBufferPtr
 BackEndOsx::doExportKey(const Name& keyName, const char* pw, size_t pwLen)
 {
-  CFReleaser<SecKeychainItemRef> privateKey;
-
-  try {
-    privateKey = m_impl->getKey(keyName);
-  }
-  catch (const std::domain_error&) {
-    BOOST_THROW_EXCEPTION(Tpm::Error("Private key does not exist in OSX Keychain"));
+  CFReleaser<SecKeychainItemRef> keychainItem = getKey(keyName);
+  if (keychainItem == nullptr) {
+    BOOST_THROW_EXCEPTION(Error("Private key does not exist in macOS Keychain"));
   }
 
   CFReleaser<CFDataRef> exportedKey;
   SecItemImportExportKeyParameters keyParams;
   memset(&keyParams, 0, sizeof(keyParams));
-  CFReleaser<CFStringRef> passphrase =
-    CFStringCreateWithBytes(0, reinterpret_cast<const uint8_t*>(pw), pwLen, kCFStringEncodingUTF8, false);
+  auto passphrase = cfstring::fromBuffer(reinterpret_cast<const uint8_t*>(pw), pwLen);
   keyParams.passphrase = passphrase.get();
-  OSStatus res = SecItemExport(privateKey.get(),       // secItemOrArray
+
+  OSStatus res = SecItemExport(keychainItem.get(),     // secItemOrArray
                                kSecFormatWrappedPKCS8, // outputFormat
                                0,                      // flags
                                &keyParams,             // keyParams
@@ -466,20 +450,17 @@
 BackEndOsx::doImportKey(const Name& keyName, const uint8_t* buf, size_t size,
                         const char* pw, size_t pwLen)
 {
-  CFReleaser<CFDataRef> importedKey = CFDataCreateWithBytesNoCopy(nullptr, buf, size, kCFAllocatorNull);
+  auto importedKey = makeCFDataNoCopy(buf, size);
 
   SecExternalFormat externalFormat = kSecFormatWrappedPKCS8;
   SecExternalItemType externalType = kSecItemTypePrivateKey;
 
-  CFReleaser<CFStringRef> keyLabel = CFStringCreateWithCString(nullptr, keyName.toUri().c_str(),
-                                                               kCFStringEncodingUTF8);
-  CFReleaser<CFStringRef> passphrase =
-    CFStringCreateWithBytes(nullptr, reinterpret_cast<const uint8_t*>(pw), pwLen, kCFStringEncodingUTF8, false);
+  auto passphrase = cfstring::fromBuffer(reinterpret_cast<const uint8_t*>(pw), pwLen);
+  auto keyLabel = cfstring::fromStdString(keyName.toUri());
   CFReleaser<SecAccessRef> access;
   SecAccessCreate(keyLabel.get(), nullptr, &access.get());
 
   CFArrayRef attributes = nullptr;
-
   const SecItemImportExportKeyParameters keyParams{
     SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION, // version
     0, // flags
@@ -522,7 +503,7 @@
     attrList.count++;
   }
 
-  res = SecKeychainItemModifyAttributesAndData(privateKey, &attrList, 0, nullptr);
+  SecKeychainItemModifyAttributesAndData(privateKey, &attrList, 0, nullptr);
 }
 
 } // namespace tpm
diff --git a/src/security/tpm/back-end-osx.hpp b/src/security/tpm/back-end-osx.hpp
index bb018be..0a7ba27 100644
--- a/src/security/tpm/back-end-osx.hpp
+++ b/src/security/tpm/back-end-osx.hpp
@@ -23,12 +23,13 @@
 #define NDN_SECURITY_TPM_BACK_END_OSX_HPP
 
 #include "back-end.hpp"
-#include "key-ref-osx.hpp"
 
 #ifndef NDN_CXX_HAVE_OSX_FRAMEWORKS
 #error "This file should not be compiled ..."
 #endif
 
+#include "key-ref-osx.hpp"
+
 namespace ndn {
 namespace security {
 namespace tpm {
@@ -36,17 +37,18 @@
 /**
  * @brief The back-end implementation of TPM based on macOS Keychain Services.
  */
-class BackEndOsx : public BackEnd
+class BackEndOsx final : public BackEnd
 {
 public:
   /**
-   * @brief Create TPM backed based on macOS KeyChain service
-   * @param location Not used (required by the TPM-registration interface)
+   * @brief Create TPM backed based on macOS Keychain Services.
+   *
+   * @param location Not used (required by the TPM registration interface).
    */
   explicit
   BackEndOsx(const std::string& location = "");
 
-  ~BackEndOsx() override;
+  ~BackEndOsx() final;
 
   static const std::string&
   getScheme();
@@ -78,54 +80,21 @@
   derivePublicKey(const KeyRefOsx& key);
 
 private: // inherited from tpm::BackEnd
-  /**
-   * @return True if a key with name @p keyName exists in TPM.
-   */
   bool
   doHasKey(const Name& keyName) const final;
 
-  /**
-   * @return The handle of a key with name @p keyName, or nullptr if the key does not exist
-   */
   unique_ptr<KeyHandle>
   doGetKeyHandle(const Name& keyName) const final;
 
-  /**
-   * @brief Create key for @p identityName according to @p params.
-   *
-   * The created key is named as: /<identityName>/[keyId]/KEY
-   * The key name is set in the returned KeyHandle.
-   *
-   * @return The handle of the created key.
-   */
   unique_ptr<KeyHandle>
   doCreateKey(const Name& identityName, const KeyParams& params) final;
 
-  /**
-   * @brief Delete a key with name @p keyName.
-   *
-   * @throw Error the deletion failed
-   */
   void
   doDeleteKey(const Name& keyName) final;
 
-  /**
-   * @return A private key with name @p keyName in encrypted PKCS #8 format using password @p pw
-   * @throw Error the key cannot be exported, e.g., not enough privilege
-   */
   ConstBufferPtr
   doExportKey(const Name& keyName, const char* pw, size_t pwLen) final;
 
-  /**
-   * @brief Import a private key in encrypted PKCS #8 format
-   *
-   * @param keyName The name of imported private key
-   * @param buf Pointer to the key in encrypted PKCS #8 format
-   * @param size The size of the key in encrypted PKCS #8 format
-   * @param pw The password to decrypt the private key
-   * @param pwLen The length of the password
-   * @throw Error import fails
-   */
   void
   doImportKey(const Name& keyName, const uint8_t* buf, size_t size, const char* pw, size_t pwLen) final;
 
diff --git a/src/security/tpm/back-end.hpp b/src/security/tpm/back-end.hpp
index 2f9e389..8bbfac5 100644
--- a/src/security/tpm/back-end.hpp
+++ b/src/security/tpm/back-end.hpp
@@ -22,10 +22,9 @@
 #ifndef NDN_SECURITY_TPM_BACK_END_HPP
 #define NDN_SECURITY_TPM_BACK_END_HPP
 
-#include "../../common.hpp"
-#include "../../name.hpp"
-#include "../../encoding/buffer.hpp"
 #include "../key-params.hpp"
+#include "../../encoding/buffer.hpp"
+#include "../../name.hpp"
 
 namespace ndn {
 namespace security {
@@ -34,7 +33,7 @@
 class KeyHandle;
 
 /**
- * @brief Abstraction of Tpm back-end.
+ * @brief Abstract interface for a TPM backend implementation.
  *
  * This class provides KeyHandle to the front-end and other TPM management operations.
  */
@@ -53,157 +52,137 @@
 
 public: // key management
   /**
-   * @return True if a key with name @p keyName exists in TPM.
+   * @brief Check if the key with name @p keyName exists in the TPM.
+   *
+   * @return True if the key exists, false otherwise.
    */
   bool
   hasKey(const Name& keyName) const;
 
   /**
-   * @return The handle of a key with name @p keyName, or nullptr if the key does not exist.
+   * @brief Get the handle of the key with name @p keyName.
    *
-   * Calling getKeyHandle multiple times with the same keyName will return different KeyHandle
+   * Calling this function multiple times with the same @p keyName will return different KeyHandle
    * objects that all refer to the same key.
+   *
+   * @return The handle of the key, or nullptr if the key does not exist.
    */
   unique_ptr<KeyHandle>
   getKeyHandle(const Name& keyName) const;
 
   /**
-   * @brief Create key for @p identity according to @p params.
-   *
-   * The key name is set in the returned KeyHandle.
+   * @brief Create a key for @p identityName according to @p params.
    *
    * @return The handle of the created key.
-   * @throw Tpm::Error @p params are invalid
-   * @throw Error the key cannot be created
+   * @throw Tpm::Error @p params are invalid.
+   * @throw Error The key could not be created.
    */
   unique_ptr<KeyHandle>
-  createKey(const Name& identity, const KeyParams& params);
+  createKey(const Name& identityName, const KeyParams& params);
 
   /**
-   * @brief Delete a key with name @p keyName.
+   * @brief Delete the key with name @p keyName.
    *
-   * Continuing to use existing KeyHandles on a deleted key results in undefined behavior.
+   * @warning Continuing to use existing KeyHandle objects for a deleted key
+   *          results in undefined behavior.
    *
-   * @throw Error if the deletion fails.
+   * @throw Error The key could not be deleted.
    */
   void
   deleteKey(const Name& keyName);
 
   /**
-   * @return A private key with name @p keyName in encrypted PKCS #8 format using password @p pw
-   * @throw Error the key does not exist
-   * @throw Error the key cannot be exported, e.g., insufficient privilege
+   * @brief Get the private key with name @p keyName in encrypted PKCS #8 format.
+   *
+   * @param keyName The name of the key.
+   * @param pw The password to encrypt the private key.
+   * @param pwLen The length of the password.
+   *
+   * @return The encoded private key.
+   * @throw Error The key does not exist or cannot be exported.
    */
   ConstBufferPtr
   exportKey(const Name& keyName, const char* pw, size_t pwLen);
 
   /**
-   * @brief Import a private key in encrypted PKCS #8 format
+   * @brief Import a private key in encrypted PKCS #8 format.
    *
-   * @param keyName The name of imported private key
-   * @param pkcs8 Pointer to the key in encrypted PKCS #8 format
-   * @param pkcs8Len The size of the key in encrypted PKCS #8 format
-   * @param pw The password to decrypt the private key
-   * @param pwLen The length of the password
-   * @throw Error import failed
+   * @param keyName The name of the key to use in the TPM.
+   * @param pkcs8 Pointer to the key in encrypted PKCS #8 format.
+   * @param pkcs8Len The size of the key in encrypted PKCS #8 format.
+   * @param pw The password to decrypt the private key.
+   * @param pwLen The length of the password.
+   *
+   * @throw Error The key could not be imported.
    */
   void
   importKey(const Name& keyName, const uint8_t* pkcs8, size_t pkcs8Len, const char* pw, size_t pwLen);
 
   /**
-   * @brief Check if TPM is in terminal mode
+   * @brief Check if the TPM is in terminal mode.
    *
-   * Default implementation always returns true.
+   * The default implementation always returns true.
+   *
+   * @return True if in terminal mode, false otherwise.
    */
   virtual bool
   isTerminalMode() const;
 
   /**
-   * @brief Set the terminal mode of TPM.
+   * @brief Set the terminal mode of the TPM.
    *
-   * In terminal mode, TPM will not ask user permission from GUI.
-   *
-   * Default implementation does nothing.
+   * In terminal mode, the TPM will not ask for a password from the GUI.
+   * The default implementation does nothing.
    */
   virtual void
   setTerminalMode(bool isTerminal) const;
 
   /**
-   * @return True if TPM is locked, otherwise false
+   * @brief Check if the TPM is locked.
    *
-   * Default implementation always returns false.
+   * The default implementation always returns false.
+   *
+   * @return True if locked, false otherwise.
    */
   virtual bool
   isTpmLocked() const;
 
   /**
-   * @brief Unlock TPM
+   * @brief Unlock the TPM.
    *
-   * @param pw    The password to unlock TPM
-   * @param pwLen The password size.
+   * The default implementation does nothing and returns `!isTpmLocked()`.
    *
-   * Default implementation always returns !isTpmLocked()
+   * @param pw The password to unlock the TPM.
+   * @param pwLen The length of the password.
+   *
+   * @return True if the TPM was unlocked.
    */
   virtual bool
   unlockTpm(const char* pw, size_t pwLen) const;
 
-protected: // static helper method
+protected: // static helper methods
   /**
-   * @brief Set the key name in @p keyHandle according to @p identity and @p params
+   * @brief Set the key name in @p keyHandle according to @p identity and @p params.
    */
   static void
   setKeyName(KeyHandle& keyHandle, const Name& identity, const KeyParams& params);
 
 private: // pure virtual methods
-  /**
-   * @return True if a key with name @p keyName exists in TPM.
-   */
   virtual bool
   doHasKey(const Name& keyName) const = 0;
 
-  /**
-   * @return The handle of a key with name @p keyName, or nullptr if the key does not exist
-   */
   virtual unique_ptr<KeyHandle>
   doGetKeyHandle(const Name& keyName) const = 0;
 
-  /**
-   * @brief Create key for @p identityName according to @p params.
-   *
-   * The created key is named as: /<identityName>/[keyId]/KEY
-   * The key name is set in the returned KeyHandle.
-   *
-   * @return The handle of the created key.
-   * @throw Error key cannot be created
-   */
   virtual unique_ptr<KeyHandle>
   doCreateKey(const Name& identity, const KeyParams& params) = 0;
 
-  /**
-   * @brief Delete a key with name @p keyName.
-   *
-   * @throw Error the deletion failed
-   */
   virtual void
   doDeleteKey(const Name& keyName) = 0;
 
-  /**
-   * @return A private key with name @p keyName in encrypted PKCS #8 format using password @p pw
-   * @throw Error the key cannot be exported, e.g., insufficient privilege
-   */
   virtual ConstBufferPtr
   doExportKey(const Name& keyName, const char* pw, size_t pwLen) = 0;
 
-  /**
-   * @brief Import a private key in encrypted PKCS #8 format using @p password
-   *
-   * @param keyName The name of imported private key
-   * @param pkcs8 Pointer to the key in PKCS #8 format
-   * @param pkcs8Len The size of the key in PKCS #8 format
-   * @param pw The password to decrypt the private key
-   * @param pwLen The length of the password
-   * @throw Error import failed
-   */
   virtual void
   doImportKey(const Name& keyName, const uint8_t* pkcs8, size_t pkcs8Len, const char* pw, size_t pwLen) = 0;
 };
diff --git a/src/security/tpm/key-handle-osx.hpp b/src/security/tpm/key-handle-osx.hpp
index a6e1484..8b0e308 100644
--- a/src/security/tpm/key-handle-osx.hpp
+++ b/src/security/tpm/key-handle-osx.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2017 Regents of the University of California.
+ * Copyright (c) 2013-2018 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -23,12 +23,13 @@
 #define NDN_SECURITY_TPM_KEY_HANDLE_OSX_HPP
 
 #include "key-handle.hpp"
-#include "key-ref-osx.hpp"
 
 #ifndef NDN_CXX_HAVE_OSX_FRAMEWORKS
 #error "This file should not be compiled ..."
 #endif
 
+#include "key-ref-osx.hpp"
+
 namespace ndn {
 namespace security {
 namespace tpm {
diff --git a/src/security/tpm/key-ref-osx.hpp b/src/security/tpm/key-ref-osx.hpp
index 02ed524..b901ea3 100644
--- a/src/security/tpm/key-ref-osx.hpp
+++ b/src/security/tpm/key-ref-osx.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2013-2017 Regents of the University of California.
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -22,6 +22,12 @@
 #ifndef NDN_SECURITY_TPM_KEY_REF_OSX_HPP
 #define NDN_SECURITY_TPM_KEY_REF_OSX_HPP
 
+#include "../../common.hpp"
+
+#ifndef NDN_CXX_HAVE_OSX_FRAMEWORKS
+#error "This file should not be compiled ..."
+#endif
+
 #include "../../util/cf-releaser-osx.hpp"
 #include <Security/Security.h>
 
diff --git a/src/security/v2/key-chain.cpp b/src/security/v2/key-chain.cpp
index 2ac2e99..cf61574 100644
--- a/src/security/v2/key-chain.cpp
+++ b/src/security/v2/key-chain.cpp
@@ -89,14 +89,14 @@
 const std::string&
 KeyChain::getDefaultPibScheme()
 {
-  return pib::PibSqlite3::getScheme();;
+  return pib::PibSqlite3::getScheme();
 }
 
 const std::string&
 KeyChain::getDefaultTpmScheme()
 {
 #if defined(NDN_CXX_HAVE_OSX_FRAMEWORKS) && defined(NDN_CXX_WITH_OSX_KEYCHAIN)
-  return tpm::BackEndOsx::getScheme();;
+  return tpm::BackEndOsx::getScheme();
 #else
   return tpm::BackEndFile::getScheme();
 #endif // defined(NDN_CXX_HAVE_OSX_FRAMEWORKS) && defined(NDN_CXX_WITH_OSX_KEYCHAIN)
diff --git a/src/util/cf-string-osx.cpp b/src/util/cf-string-osx.cpp
new file mode 100644
index 0000000..a0d3814
--- /dev/null
+++ b/src/util/cf-string-osx.cpp
@@ -0,0 +1,71 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "cf-string-osx.hpp"
+
+namespace ndn {
+namespace util {
+namespace cfstring {
+
+CFReleaser<CFStringRef>
+fromBuffer(const uint8_t* buf, size_t buflen)
+{
+  CFStringRef cfStr = CFStringCreateWithBytes(kCFAllocatorDefault, buf, buflen, kCFStringEncodingUTF8, false);
+  if (cfStr == nullptr) {
+    BOOST_THROW_EXCEPTION(std::runtime_error("Failed to create CFString from buffer"));
+  }
+  return cfStr;
+}
+
+CFReleaser<CFStringRef>
+fromStdString(const std::string& str)
+{
+  CFStringRef cfStr = CFStringCreateWithCString(kCFAllocatorDefault, str.data(), kCFStringEncodingUTF8);
+  if (cfStr == nullptr) {
+    BOOST_THROW_EXCEPTION(std::runtime_error("Failed to create CFString from std::string"));
+  }
+  return cfStr;
+}
+
+std::string
+toStdString(CFStringRef cfStr)
+{
+  const char* cStr = CFStringGetCStringPtr(cfStr, kCFStringEncodingUTF8);
+  if (cStr != nullptr) {
+    // fast path
+    return cStr;
+  }
+
+  // reserve space for the string + null terminator
+  std::string str(CFStringGetLength(cfStr) + 1, '\0');
+  // copy the CFString into the std::string buffer
+  if (!CFStringGetCString(cfStr, &str.front(), str.size(), kCFStringEncodingUTF8)) {
+    BOOST_THROW_EXCEPTION(std::runtime_error("CFString to std::string conversion failed"));
+  }
+  // drop the null terminator, std::string doesn't need it
+  str.pop_back();
+
+  return str;
+}
+
+} // namespace cfstring
+} // namespace util
+} // namespace ndn
diff --git a/src/util/cf-string-osx.hpp b/src/util/cf-string-osx.hpp
new file mode 100644
index 0000000..c44fed4
--- /dev/null
+++ b/src/util/cf-string-osx.hpp
@@ -0,0 +1,68 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#ifndef NDN_UTIL_CF_STRING_OSX_HPP
+#define NDN_UTIL_CF_STRING_OSX_HPP
+
+#include "../common.hpp"
+
+#ifndef NDN_CXX_HAVE_OSX_FRAMEWORKS
+#error "This file should not be included ..."
+#endif
+
+#include "cf-releaser-osx.hpp"
+
+/**
+ * @file
+ *
+ * This file contains utilities to deal with Apple Core Foundation's CFString and related types.
+ */
+
+namespace ndn {
+namespace util {
+namespace cfstring {
+
+/**
+ * @brief Create a CFString by copying bytes from a raw buffer
+ * @throw std::runtime_error creation failed
+ */
+CFReleaser<CFStringRef>
+fromBuffer(const uint8_t* buf, size_t buflen);
+
+/**
+ * @brief Create a CFString by copying characters from a std::string
+ * @throw std::runtime_error creation failed
+ */
+CFReleaser<CFStringRef>
+fromStdString(const std::string& str);
+
+/**
+ * @brief Convert a CFString to a std::string
+ * @throw std::runtime_error conversion failed
+ */
+std::string
+toStdString(CFStringRef cfStr);
+
+} // namespace cfstring
+} // namespace util
+} // namespace ndn
+
+#endif // NDN_UTIL_CF_STRING_OSX_HPP
diff --git a/tests/unit-tests/security/tpm/back-end-wrapper-file.hpp b/tests/unit-tests/security/tpm/back-end-wrapper-file.hpp
index 64f5a0a..dabd6d3 100644
--- a/tests/unit-tests/security/tpm/back-end-wrapper-file.hpp
+++ b/tests/unit-tests/security/tpm/back-end-wrapper-file.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2013-2017 Regents of the University of California.
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -54,7 +54,7 @@
   }
 
   std::string
-  getScheme()
+  getScheme() const
   {
     return "tpm-file";
   }
diff --git a/tests/unit-tests/security/tpm/back-end-wrapper-mem.hpp b/tests/unit-tests/security/tpm/back-end-wrapper-mem.hpp
index 692ba65..ddf629b 100644
--- a/tests/unit-tests/security/tpm/back-end-wrapper-mem.hpp
+++ b/tests/unit-tests/security/tpm/back-end-wrapper-mem.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2013-2017 Regents of the University of California.
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -47,7 +47,7 @@
   }
 
   std::string
-  getScheme()
+  getScheme() const
   {
     return "tpm-memory";
   }
diff --git a/tests/unit-tests/security/tpm/back-end-wrapper-osx.hpp b/tests/unit-tests/security/tpm/back-end-wrapper-osx.hpp
index d02b717..6d7d35b 100644
--- a/tests/unit-tests/security/tpm/back-end-wrapper-osx.hpp
+++ b/tests/unit-tests/security/tpm/back-end-wrapper-osx.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2013-2016 Regents of the University of California.
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -24,7 +24,8 @@
 
 #include "security/tpm/back-end-osx.hpp"
 #include "security/tpm/key-handle-osx.hpp"
-#include <Availability.h>
+
+#include <cstdlib>
 
 namespace ndn {
 namespace security {
@@ -47,17 +48,17 @@
       m_HOME = std::getenv("HOME");
 
     if (!oldHOME.empty())
-      setenv("HOME", oldHOME.c_str(), 1);
+      setenv("HOME", oldHOME.data(), 1);
     else
       unsetenv("HOME");
 
-    m_impl = unique_ptr<BackEnd>(new BackEndOsx);
+    m_impl = make_unique<BackEndOsx>();
   }
 
   ~BackEndWrapperOsx()
   {
     if (!m_HOME.empty())
-      setenv("HOME", m_HOME.c_str(), 1);
+      setenv("HOME", m_HOME.data(), 1);
     else
       unsetenv("HOME");
   }
@@ -69,7 +70,7 @@
   }
 
   std::string
-  getScheme()
+  getScheme() const
   {
     return "tpm-osxkeychain";
   }