security: Add KeyParams to support multiple types of keys.

Different types of keys may require different size options and default key size.
This commit also fixes the undefined behavior when processing the password of TPM.

Change-Id: I8fb95f28468be8299002f0d5146a4496ea1da25f
Refs: #1660
Refs: #1693
diff --git a/src/security/sec-tpm-osx.cpp b/src/security/sec-tpm-osx.cpp
index a5a7159..031632d 100644
--- a/src/security/sec-tpm-osx.cpp
+++ b/src/security/sec-tpm-osx.cpp
@@ -41,10 +41,10 @@
 
 #include <Security/SecDigestTransform.h>
 
-using namespace std;
-
 namespace ndn {
 
+using std::string;
+
 /**
  * @brief Helper class to wrap CoreFoundation object pointers
  *
@@ -256,7 +256,7 @@
 SecTpmOsx::setTpmPassword(const uint8_t* password, size_t passwordLength)
 {
   m_impl->m_passwordSet = true;
-  memset(const_cast<char*>(m_impl->m_password.c_str()), 0, m_impl->m_password.size());
+  std::fill(m_impl->m_password.begin(), m_impl->m_password.end(), 0);
   m_impl->m_password.clear();
   m_impl->m_password.append(reinterpret_cast<const char*>(password), passwordLength);
 }
@@ -265,7 +265,7 @@
 SecTpmOsx::resetTpmPassword()
 {
   m_impl->m_passwordSet = false;
-  memset(const_cast<char*>(m_impl->m_password.c_str()), 0, m_impl->m_password.size());
+  std::fill(m_impl->m_password.begin(), m_impl->m_password.end(), 0);
   m_impl->m_password.clear();
 }
 
@@ -363,8 +363,9 @@
 }
 
 void
-SecTpmOsx::generateKeyPairInTpmInternal(const Name& keyName, KeyType keyType,
-                                        int keySize, bool needRetry)
+SecTpmOsx::generateKeyPairInTpmInternal(const Name& keyName,
+                                        const KeyParams& params,
+                                        bool needRetry)
 {
 
   if (doesKeyExistInTpm(keyName, KEY_CLASS_PUBLIC))
@@ -385,6 +386,20 @@
                               &kCFTypeDictionaryKeyCallBacks,
                               0);
 
+  KeyType keyType = params.getKeyType();
+  uint32_t keySize;
+  switch (keyType)
+    {
+    case KEY_TYPE_RSA:
+      {
+        const RsaKeyParams& rsaParams = static_cast<const RsaKeyParams&>(params);
+        keySize = rsaParams.getKeySize();
+        break;
+      }
+    default:
+      throw Error("Fail to create a key pair: Unsupported key type");
+    }
+
   CFReleaser<CFNumberRef> cfKeySize = CFNumberCreate(0, kCFNumberIntType, &keySize);
 
   CFDictionaryAddValue(attrDict.get(), kSecAttrKeyType, m_impl->getAsymKeyType(keyType));
@@ -392,6 +407,7 @@
   CFDictionaryAddValue(attrDict.get(), kSecAttrLabel, keyLabel.get());
 
   CFReleaser<SecKeyRef> publicKey, privateKey;
+  // C-style cast is used as per Apple convention
   OSStatus res = SecKeyGeneratePair((CFDictionaryRef)attrDict.get(),
                                     &publicKey.get(), &privateKey.get());
 
@@ -403,7 +419,7 @@
   if (res == errSecAuthFailed && !needRetry)
     {
       if (unlockTpm(0, 0, false))
-        generateKeyPairInTpmInternal(keyName, keyType, keySize, true);
+        generateKeyPairInTpmInternal(keyName, params, true);
       else
         throw Error("Fail to unlock the keychain");
     }
@@ -442,7 +458,7 @@
 }
 
 void
-SecTpmOsx::generateSymmetricKeyInTpm(const Name& keyName, KeyType keyType, int keySize)
+SecTpmOsx::generateSymmetricKeyInTpm(const Name& keyName, const KeyParams& params)
 {
   throw Error("SecTpmOsx::generateSymmetricKeyInTpm is not supported");
   // if (doesKeyExistInTpm(keyName, KEY_CLASS_SYMMETRIC))
@@ -537,7 +553,7 @@
   FileSink sink(pkcs1Os);
 
   uint32_t version = 0;
-  OID algorithm("1.2.840.113549.1.1.1");
+  OID algorithm("1.2.840.113549.1.1.1"); // "RSA encryption"
   SecByteBlock rawKeyBits;
   // PrivateKeyInfo ::= SEQUENCE {
   //   version              INTEGER,
@@ -645,6 +661,7 @@
         return false;
     }
 
+  // C-style cast is used as per Apple convention
   SecKeychainItemRef privateKey = (SecKeychainItemRef)CFArrayGetValueAtIndex(outItems.get(), 0);
   SecKeychainAttribute attrs[1]; // maximum number of attributes
   SecKeychainAttributeList attrList = { 0, attrs };
@@ -652,7 +669,7 @@
   {
     attrs[attrList.count].tag = kSecKeyPrintName;
     attrs[attrList.count].length = keyUri.size();
-    attrs[attrList.count].data = (void *)keyUri.c_str();
+    attrs[attrList.count].data = const_cast<char*>(keyUri.c_str());
     attrList.count++;
   }
 
@@ -697,6 +714,7 @@
   if (res != errSecSuccess)
     return false;
 
+  // C-style cast is used as per Apple convention
   SecKeychainItemRef publicKey = (SecKeychainItemRef)CFArrayGetValueAtIndex(outItems.get(), 0);
   SecKeychainAttribute attrs[1]; // maximum number of attributes
   SecKeychainAttributeList attrList = { 0, attrs };
@@ -704,7 +722,7 @@
   {
     attrs[attrList.count].tag = kSecKeyPrintName;
     attrs[attrList.count].length = keyUri.size();
-    attrs[attrList.count].data = (void *)keyUri.c_str();
+    attrs[attrList.count].data = const_cast<char*>(keyUri.c_str());
     attrList.count++;
   }
 
@@ -735,16 +753,17 @@
     }
 
   CFReleaser<CFErrorRef> error;
+  // C-style cast is used as per Apple convention
   CFReleaser<SecTransformRef> signer = SecSignTransformCreate((SecKeyRef)privateKey.get(),
                                                               &error.get());
   if (error.get() != 0)
     throw Error("Fail to create signer");
 
   // Set input
-  Boolean set_res = SecTransformSetAttribute(signer.get(),
-                                             kSecTransformInputAttributeName,
-                                             dataRef.get(),
-                                             &error.get());
+  SecTransformSetAttribute(signer.get(),
+                           kSecTransformInputAttributeName,
+                           dataRef.get(),
+                           &error.get());
   if (error.get() != 0)
     throw Error("Fail to configure input of signer");
 
@@ -757,24 +776,25 @@
     throw Error("Fail to configure digest algorithm of signer");
 
   // Set padding type
-  set_res = SecTransformSetAttribute(signer.get(),
-                                     kSecDigestTypeAttribute,
-                                     m_impl->getDigestAlgorithm(digestAlgorithm),
-                                     &error.get());
+  SecTransformSetAttribute(signer.get(),
+                           kSecDigestTypeAttribute,
+                           m_impl->getDigestAlgorithm(digestAlgorithm),
+                           &error.get());
   if (error.get() != 0)
     throw Error("Fail to configure digest algorithm of signer");
 
   // Set padding attribute
   long digestSize = m_impl->getDigestSize(digestAlgorithm);
   CFReleaser<CFNumberRef> cfDigestSize = CFNumberCreate(0, kCFNumberLongType, &digestSize);
-  set_res = SecTransformSetAttribute(signer.get(),
-                                     kSecDigestLengthAttribute,
-                                     cfDigestSize.get(),
-                                     &error.get());
+  SecTransformSetAttribute(signer.get(),
+                           kSecDigestLengthAttribute,
+                           cfDigestSize.get(),
+                           &error.get());
   if (error.get() != 0)
     throw Error("Fail to configure digest size of signer");
 
   // Actually sign
+  // C-style cast is used as per Apple convention
   CFReleaser<CFDataRef> signature = (CFDataRef)SecTransformExecute(signer.get(), &error.get());
   if (error.get() != 0)
     {
@@ -856,37 +876,38 @@
         }
 
       CFReleaser<SecAccessRef> accRef;
-      OSStatus acc_res = SecKeychainItemCopyAccess(privateKey.get(), &accRef.get());
+      SecKeychainItemCopyAccess(privateKey.get(), &accRef.get());
 
       CFReleaser<CFArrayRef> signACL = SecAccessCopyMatchingACLList(accRef.get(),
                                                                     kSecACLAuthorizationSign);
 
+      // C-style cast is used as per Apple convention
       SecACLRef aclRef = (SecACLRef)CFArrayGetValueAtIndex(signACL.get(), 0);
 
       CFReleaser<CFArrayRef> appList;
       CFReleaser<CFStringRef> description;
       SecKeychainPromptSelector promptSelector;
-      OSStatus acl_res = SecACLCopyContents(aclRef,
-                                            &appList.get(),
-                                            &description.get(),
-                                            &promptSelector);
+      SecACLCopyContents(aclRef,
+                         &appList.get(),
+                         &description.get(),
+                         &promptSelector);
 
       CFReleaser<CFMutableArrayRef> newAppList = CFArrayCreateMutableCopy(0,
                                                                           0,
                                                                           appList.get());
 
       CFReleaser<SecTrustedApplicationRef> trustedApp;
-      acl_res = SecTrustedApplicationCreateFromPath(appPath.c_str(),
-                                                    &trustedApp.get());
+      SecTrustedApplicationCreateFromPath(appPath.c_str(),
+                                          &trustedApp.get());
 
       CFArrayAppendValue(newAppList.get(), trustedApp.get());
 
-      acl_res = SecACLSetContents(aclRef,
-                                  newAppList.get(),
-                                  description.get(),
-                                  promptSelector);
+      SecACLSetContents(aclRef,
+                        newAppList.get(),
+                        description.get(),
+                        promptSelector);
 
-      acc_res = SecKeychainItemSetAccess(privateKey.get(), accRef.get());
+      SecKeychainItemSetAccess(privateKey.get(), accRef.get());
     }
 }
 
@@ -951,6 +972,7 @@
   CFDictionaryAddValue(attrDict.get(), kSecReturnRef, kCFBooleanTrue);
 
   CFReleaser<SecKeychainItemRef> itemRef;
+  // C-style cast is used as per Apple convention
   OSStatus res = SecItemCopyMatching((CFDictionaryRef)attrDict.get(), (CFTypeRef*)&itemRef.get());
 
   if (res == errSecSuccess)
@@ -963,7 +985,7 @@
 bool
 SecTpmOsx::generateRandomBlock(uint8_t* res, size_t size)
 {
-  return (SecRandomCopyBytes(kSecRandomDefault, size, res) == 0);
+  return SecRandomCopyBytes(kSecRandomDefault, size, res) == 0;
 }
 
 ////////////////////////////////
@@ -991,6 +1013,7 @@
   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());
 
   if (res != errSecSuccess)
@@ -1013,7 +1036,7 @@
 CFTypeRef
 SecTpmOsx::Impl::getAsymKeyType(KeyType keyType)
 {
-  switch (keyType){
+  switch (keyType) {
   case KEY_TYPE_RSA:
     return kSecAttrKeyTypeRSA;
   default:
@@ -1024,7 +1047,7 @@
 CFTypeRef
 SecTpmOsx::Impl::getSymKeyType(KeyType keyType)
 {
-  switch (keyType){
+  switch (keyType) {
   case KEY_TYPE_AES:
     return kSecAttrKeyTypeAES;
   default:
@@ -1035,7 +1058,7 @@
 CFTypeRef
 SecTpmOsx::Impl::getKeyClass(KeyClass keyClass)
 {
-  switch (keyClass){
+  switch (keyClass) {
   case KEY_CLASS_PRIVATE:
     return kSecAttrKeyClassPrivate;
   case KEY_CLASS_PUBLIC:
@@ -1050,13 +1073,7 @@
 CFStringRef
 SecTpmOsx::Impl::getDigestAlgorithm(DigestAlgorithm digestAlgo)
 {
-  switch (digestAlgo){
-    // case DIGEST_MD2:
-    //   return kSecDigestMD2;
-    // case DIGEST_MD5:
-    //   return kSecDigestMD5;
-    // case DIGEST_SHA1:
-    //   return kSecDigestSHA1;
+  switch (digestAlgo) {
   case DIGEST_ALGORITHM_SHA256:
     return kSecDigestSHA2;
   default:
@@ -1067,13 +1084,9 @@
 long
 SecTpmOsx::Impl::getDigestSize(DigestAlgorithm digestAlgo)
 {
-  switch (digestAlgo){
+  switch (digestAlgo) {
   case DIGEST_ALGORITHM_SHA256:
     return 256;
-    // case DIGEST_SHA1:
-    // case DIGEST_MD2:
-    // case DIGEST_MD5:
-    //   return 0;
   default:
     return -1;
   }