security: renaming PolicyManager classess to SecPolicy___ and re-organize security file layout

Change-Id: Ibca0333129a3d4465ff294c4d97d59808ae253f4
diff --git a/src/security/sec-tpm-osx.cpp b/src/security/sec-tpm-osx.cpp
new file mode 100644
index 0000000..cfe7579
--- /dev/null
+++ b/src/security/sec-tpm-osx.cpp
@@ -0,0 +1,618 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/**
+ * Copyright (C) 2013 Regents of the University of California.
+ * @author: Yingdi Yu <yingdi@cs.ucla.edu>
+ * See COPYING for copyright and distribution information.
+ */
+
+#include <ndn-cpp/ndn-cpp-config.h>
+
+#include <fstream>
+#include <sstream>
+
+#include "../util/logging.hpp"
+
+#include <ndn-cpp/security/sec-tpm-osx.hpp>
+#include <ndn-cpp/security/public-key.hpp>
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <Security/Security.h>
+#include <CoreServices/CoreServices.h>
+
+using namespace std;
+
+INIT_LOGGER("SecTpmOsx");
+
+namespace ndn
+{
+  class SecTpmOsx::Impl {
+  public:
+    Impl(const std::string &keychainName)
+      : keyChainName_ ("" == keychainName ?  "login.keychain" : keychainName)
+    {
+    }
+    
+    /**
+     * convert NDN name of a key to internal name of the key
+     * @param keyName the NDN name of the key
+     * @param keyClass the class of the key
+     * @return the internal key name
+     */
+    std::string 
+    toInternalKeyName(const Name & keyName, KeyClass keyClass);
+  
+    /**
+     * Get key
+     * @param keyName the name of the key
+     * @param keyClass the class of the key
+     * @returns pointer to the key
+     */
+    SecKeychainItemRef 
+    getKey(const Name & keyName, KeyClass keyClass);
+        
+    /**
+     * convert keyType to MAC OS symmetric key key type
+     * @param keyType
+     * @returns MAC OS key type
+     */
+    const CFTypeRef 
+    getSymKeyType(KeyType keyType);
+  
+    /**
+     * convert keyType to MAC OS asymmetirc key type
+     * @param keyType
+     * @returns MAC OS key type
+     */
+    const CFTypeRef 
+    getAsymKeyType(KeyType keyType);
+  
+    /**
+     * convert keyClass to MAC OS key class
+     * @param keyClass
+     * @returns MAC OS key class
+     */
+    const CFTypeRef 
+    getKeyClass(KeyClass keyClass);
+  
+    /**
+     * convert digestAlgo to MAC OS algorithm id
+     * @param digestAlgo
+     * @returns MAC OS algorithm id
+     */
+    const CFStringRef 
+    getDigestAlgorithm(DigestAlgorithm digestAlgo);
+  
+    /**
+     * get the digest size of the corresponding algorithm
+     * @param digestAlgo the digest algorithm
+     * @return digest size
+     */
+    long 
+    getDigestSize(DigestAlgorithm digestAlgo);
+
+    ///////////////////////////////////////////////
+    // everything here is public, including data //
+    ///////////////////////////////////////////////
+  public:
+    const std::string keyChainName_;
+    SecKeychainRef keyChainRef_;
+    SecKeychainRef originalDefaultKeyChain_;
+  };
+
+
+
+  SecTpmOsx::SecTpmOsx(const string & keychainName)
+    : impl_(new Impl(keychainName))
+  {
+    OSStatus res = SecKeychainCreate(impl_->keyChainName_.c_str(), //Keychain path
+				     0,                       //Keychain password length
+				     NULL,                    //Keychain password
+				     true,                    //User prompt
+				     NULL,                    //Initial access of Keychain
+				     &impl_->keyChainRef_);   //Keychain reference
+
+    if (res == errSecDuplicateKeychain)
+      res = SecKeychainOpen(impl_->keyChainName_.c_str(),
+                            &impl_->keyChainRef_);
+
+    if (res != errSecSuccess){
+      _LOG_DEBUG("Fail to initialize keychain ref: " << res);
+      throw Error("Fail to initialize keychain ref");
+    }
+
+    res = SecKeychainCopyDefault(&impl_->originalDefaultKeyChain_);
+
+    res = SecKeychainSetDefault(impl_->keyChainRef_);
+    if (res != errSecSuccess){
+      _LOG_DEBUG("Fail to set default keychain: " << res);
+      throw Error("Fail to set default keychain");
+    }
+  }
+
+  SecTpmOsx::~SecTpmOsx(){
+    //TODO: implement
+  }
+
+  void 
+  SecTpmOsx::generateKeyPairInTpm(const Name & keyName, KeyType keyType, int keySize)
+  { 
+    
+    if(doesKeyExist(keyName, KEY_CLASS_PUBLIC)){
+      _LOG_DEBUG("keyName has existed");
+      throw Error("keyName has existed");
+    }
+
+    string keyNameUri = impl_->toInternalKeyName(keyName, KEY_CLASS_PUBLIC);
+
+    SecKeyRef publicKey, privateKey;
+
+    CFStringRef keyLabel = CFStringCreateWithCString(NULL, 
+                                                     keyNameUri.c_str(), 
+                                                     kCFStringEncodingUTF8);
+    
+    CFMutableDictionaryRef attrDict = CFDictionaryCreateMutable(NULL,
+                                                             3,
+                                                             &kCFTypeDictionaryKeyCallBacks,
+                                                             NULL);
+
+    CFDictionaryAddValue(attrDict, kSecAttrKeyType, impl_->getAsymKeyType(keyType));
+    CFDictionaryAddValue(attrDict, kSecAttrKeySizeInBits, CFNumberCreate(NULL, kCFNumberIntType, &keySize));
+    CFDictionaryAddValue(attrDict, kSecAttrLabel, keyLabel);
+
+    OSStatus res = SecKeyGeneratePair((CFDictionaryRef)attrDict, &publicKey, &privateKey);
+
+    CFRelease(publicKey);
+    CFRelease(privateKey);
+
+    if (res != errSecSuccess){
+      _LOG_DEBUG("Fail to create a key pair: " << res);
+      throw Error("Fail to create a key pair");
+    }
+  }
+
+  void 
+  SecTpmOsx::generateSymmetricKey(const Name & keyName, KeyType keyType, int keySize)
+  {
+
+    if(doesKeyExist(keyName, KEY_CLASS_SYMMETRIC))
+        throw Error("keyName has existed!");
+
+    string keyNameUri =  impl_->toInternalKeyName(keyName, KEY_CLASS_SYMMETRIC);
+
+    CFMutableDictionaryRef attrDict = CFDictionaryCreateMutable(kCFAllocatorDefault,
+                                                                0,
+                                                                &kCFTypeDictionaryKeyCallBacks,
+                                                                &kCFTypeDictionaryValueCallBacks);
+
+    CFStringRef keyLabel = CFStringCreateWithCString(NULL, 
+                                                     keyNameUri.c_str(), 
+                                                     kCFStringEncodingUTF8);
+
+    CFDictionaryAddValue(attrDict, kSecAttrKeyType, impl_->getSymKeyType(keyType));
+    CFDictionaryAddValue(attrDict, kSecAttrKeySizeInBits, CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &keySize));
+    CFDictionaryAddValue(attrDict, kSecAttrIsPermanent, kCFBooleanTrue);
+    CFDictionaryAddValue(attrDict, kSecAttrLabel, keyLabel);
+
+    CFErrorRef error = NULL;
+
+    SecKeyRef symmetricKey = SecKeyGenerateSymmetric(attrDict, &error);
+
+    if (error) 
+        throw Error("Fail to create a symmetric key");
+  }
+
+  ptr_lib::shared_ptr<PublicKey>
+  SecTpmOsx::getPublicKeyFromTpm(const Name & keyName)
+  {
+    _LOG_TRACE("OSXPrivateKeyStorage::getPublickey");
+
+    SecKeychainItemRef publicKey = impl_->getKey(keyName, KEY_CLASS_PUBLIC);
+
+    CFDataRef exportedKey;
+
+    OSStatus res = SecItemExport(publicKey,
+                                  kSecFormatOpenSSL,
+                                  0,
+                                  NULL,
+                                  &exportedKey);
+
+    return ptr_lib::make_shared<PublicKey>(CFDataGetBytePtr(exportedKey), CFDataGetLength(exportedKey));
+  }
+
+  Block
+  SecTpmOsx::sign(const uint8_t *data, size_t dataLength, const Name& keyName, DigestAlgorithm digestAlgorithm)
+  {
+    _LOG_TRACE("OSXPrivateKeyStorage::Sign");
+    
+    CFDataRef dataRef = CFDataCreateWithBytesNoCopy(NULL,
+                                                    data,
+                                                    dataLength,
+                                                    kCFAllocatorNull
+                                                    );
+
+    SecKeyRef privateKey = (SecKeyRef)impl_->getKey(keyName, KEY_CLASS_PRIVATE);
+    
+    CFErrorRef error;
+    SecTransformRef signer = SecSignTransformCreate((SecKeyRef)privateKey, &error);
+    if (error) throw Error("Fail to create signer");
+
+    // Set input
+    Boolean set_res = SecTransformSetAttribute(signer,
+                                               kSecTransformInputAttributeName,
+                                               dataRef,
+                                               &error);
+    if (error) throw Error("Fail to configure input of signer");
+
+    // Enable use of padding
+    SecTransformSetAttribute(
+                             signer,
+                             kSecPaddingKey,
+                             kSecPaddingPKCS1Key,
+                             &error);
+    if (error) throw Error("Fail to configure digest algorithm of signer");
+
+    // Set padding type
+    set_res = SecTransformSetAttribute(signer,
+                                       kSecDigestTypeAttribute,
+                                       impl_->getDigestAlgorithm(digestAlgorithm),
+                                       &error);
+    if (error) throw Error("Fail to configure digest algorithm of signer");
+
+    // Set padding attribute
+    long digestSize = impl_->getDigestSize(digestAlgorithm);
+    set_res = SecTransformSetAttribute(signer,
+                                       kSecDigestLengthAttribute,
+                                       CFNumberCreate(NULL, kCFNumberLongType, &digestSize),
+                                       &error);
+    if (error) throw Error("Fail to configure digest size of signer");
+
+    // Actually sign
+    CFDataRef signature = (CFDataRef) SecTransformExecute(signer, &error);
+    if (error) {
+      CFShow(error);
+      throw Error("Fail to sign data");
+    }
+
+    if (!signature) throw Error("Signature is NULL!\n");
+
+    return Block(Tlv::SignatureValue,
+                 ptr_lib::make_shared<Buffer>(CFDataGetBytePtr(signature), CFDataGetLength(signature)));
+  }
+
+  void
+  SecTpmOsx::sign(Data &data, const Name& keyName, DigestAlgorithm digestAlgorithm)
+  {
+    data.setSignatureValue
+      (sign(data.wireEncode().value(),
+            data.wireEncode().value_size() - data.getSignature().getValue().size(),
+            keyName, digestAlgorithm));
+  }
+
+  ConstBufferPtr
+  SecTpmOsx::decrypt(const Name & keyName, const uint8_t* data, size_t dataLength, bool sym)
+  {
+    _LOG_TRACE("OSXPrivateKeyStorage::Decrypt");
+
+    KeyClass keyClass;
+    if(sym)
+        keyClass = KEY_CLASS_SYMMETRIC;
+    else
+        keyClass = KEY_CLASS_PRIVATE;
+
+    CFDataRef dataRef = CFDataCreate(NULL,
+                                      reinterpret_cast<const unsigned char*>(data),
+                                      dataLength
+                                      );
+
+    // _LOG_DEBUG("CreateData");
+    
+    SecKeyRef decryptKey = (SecKeyRef)impl_->getKey(keyName, keyClass);
+
+    // _LOG_DEBUG("GetKey");
+
+    CFErrorRef error;
+    SecTransformRef decrypt = SecDecryptTransformCreate(decryptKey, &error);
+    if (error) throw Error("Fail to create decrypt");
+
+    Boolean set_res = SecTransformSetAttribute(decrypt,
+                                               kSecTransformInputAttributeName,
+                                               dataRef,
+                                               &error);
+    if (error) throw Error("Fail to configure decrypt");
+
+    CFDataRef output = (CFDataRef) SecTransformExecute(decrypt, &error);
+    if (error)
+      {
+        CFShow(error);
+        throw Error("Fail to decrypt data");
+      }
+    if (!output) throw Error("Output is NULL!\n");
+
+    return ptr_lib::make_shared<Buffer>(CFDataGetBytePtr(output), CFDataGetLength(output));
+  }
+  
+  bool
+  SecTpmOsx::setACL(const Name & keyName, KeyClass keyClass, int acl, const string & appPath)
+  {
+    SecKeychainItemRef privateKey = impl_->getKey(keyName, keyClass);
+    
+    SecAccessRef accRef;
+    OSStatus acc_res = SecKeychainItemCopyAccess(privateKey, &accRef);
+
+    CFArrayRef signACL = SecAccessCopyMatchingACLList(accRef,
+                                                       kSecACLAuthorizationSign);
+
+    SecACLRef aclRef = (SecACLRef) CFArrayGetValueAtIndex(signACL, 0);
+
+    CFArrayRef appList;
+    CFStringRef description;
+    SecKeychainPromptSelector promptSelector;
+    OSStatus acl_res = SecACLCopyContents(aclRef,
+                                           &appList,
+                                           &description,
+                                           &promptSelector);
+
+    CFMutableArrayRef newAppList = CFArrayCreateMutableCopy(NULL,
+                                                            0,
+                                                            appList);
+
+    SecTrustedApplicationRef trustedApp;
+    acl_res = SecTrustedApplicationCreateFromPath(appPath.c_str(),
+                                                   &trustedApp);
+    
+    CFArrayAppendValue(newAppList, trustedApp);
+
+
+    CFArrayRef authList = SecACLCopyAuthorizations(aclRef);
+    
+    acl_res = SecACLRemove(aclRef);
+
+    SecACLRef newACL;
+    acl_res = SecACLCreateWithSimpleContents(accRef,
+                                              newAppList,
+                                              description,
+                                              promptSelector,
+                                              &newACL);
+
+    acl_res = SecACLUpdateAuthorizations(newACL, authList);
+
+    acc_res = SecKeychainItemSetAccess(privateKey, accRef);
+
+    return true;
+  }
+
+  // bool
+  // OSXPrivateKeyStorage::verifyData(const Name & keyName, const Blob & pData, const Blob & pSig, DigestAlgorithm digestAlgo)
+  // {
+  //   _LOG_TRACE("OSXPrivateKeyStorage::Verify");
+    
+  //   CFDataRef dataRef = CFDataCreate(NULL,
+  //                                     reinterpret_cast<const unsigned char*>(pData.buf()),
+  //                                     pData.size());
+
+  //   CFDataRef sigRef = CFDataCreate(NULL,
+  //                                    reinterpret_cast<const unsigned char*>(pSig.buf()),
+  //                                    pSig.size());
+
+  //   SecKeyRef publicKey = (SecKeyRef)impl_->getKey(keyName, KEY_CLASS_PUBLIC);
+    
+  //   CFErrorRef error;
+  //   SecTransformRef verifier = SecVerifyTransformCreate(publicKey, sigRef, &error);
+  //   if (error) throw Error("Fail to create verifier");
+    
+  //   Boolean set_res = SecTransformSetAttribute(verifier,
+  //                                              kSecTransformInputAttributeName,
+  //                                              dataRef,
+  //                                              &error);
+  //   if (error) throw Error("Fail to configure input of verifier");
+
+  //   set_res = SecTransformSetAttribute(verifier,
+  //                                      kSecDigestTypeAttribute,
+  //                                      impl_->getDigestAlgorithm(digestAlgo),
+  //                                      &error);
+  //   if (error) throw Error("Fail to configure digest algorithm of verifier");
+
+  //   long digestSize = impl_->getDigestSize(digestAlgo);
+  //   set_res = SecTransformSetAttribute(verifier,
+  //                                      kSecDigestLengthAttribute,
+  //                                      CFNumberCreate(NULL, kCFNumberLongType, &digestSize),
+  //                                      &error);
+  //   if (error) throw Error("Fail to configure digest size of verifier");
+
+  //   CFBooleanRef result = (CFBooleanRef) SecTransformExecute(verifier, &error);
+  //   if (error) throw Error("Fail to verify data");
+
+  //   if (result == kCFBooleanTrue)
+  //     return true;
+  //   else
+  //     return false;
+  // }
+
+  ConstBufferPtr
+  SecTpmOsx::encrypt(const Name & keyName, const uint8_t* data, size_t dataLength, bool sym)
+  {
+    _LOG_TRACE("OSXPrivateKeyStorage::Encrypt");
+
+    KeyClass keyClass;
+    if(sym)
+        keyClass = KEY_CLASS_SYMMETRIC;
+    else
+        keyClass = KEY_CLASS_PUBLIC;
+    
+    CFDataRef dataRef = CFDataCreate(NULL,
+                                      reinterpret_cast<const unsigned char*>(data),
+                                      dataLength
+                                      );
+    
+    SecKeyRef encryptKey = (SecKeyRef)impl_->getKey(keyName, keyClass);
+
+    CFErrorRef error;
+    SecTransformRef encrypt = SecEncryptTransformCreate(encryptKey, &error);
+    if (error) throw Error("Fail to create encrypt");
+
+    Boolean set_res = SecTransformSetAttribute(encrypt,
+                                               kSecTransformInputAttributeName,
+                                               dataRef,
+                                               &error);
+    if (error) throw Error("Fail to configure encrypt");
+
+    CFDataRef output = (CFDataRef) SecTransformExecute(encrypt, &error);
+    if (error) throw Error("Fail to encrypt data");
+
+    if (!output) throw Error("Output is NULL!\n");
+
+    return ptr_lib::make_shared<Buffer> (CFDataGetBytePtr(output), CFDataGetLength(output));
+  }
+
+  bool
+  SecTpmOsx::doesKeyExist(const Name & keyName, KeyClass keyClass)
+  {
+    _LOG_TRACE("OSXPrivateKeyStorage::doesKeyExist");
+
+    string keyNameUri = impl_->toInternalKeyName(keyName, keyClass);
+
+    CFStringRef keyLabel = CFStringCreateWithCString(NULL, 
+                                                     keyNameUri.c_str(), 
+                                                     kCFStringEncodingUTF8);
+    
+    CFMutableDictionaryRef attrDict = CFDictionaryCreateMutable(NULL,
+                                                                3,
+                                                                &kCFTypeDictionaryKeyCallBacks,
+                                                                NULL);
+
+    CFDictionaryAddValue(attrDict, kSecAttrKeyClass, impl_->getKeyClass(keyClass));
+    CFDictionaryAddValue(attrDict, kSecAttrLabel, keyLabel);
+    CFDictionaryAddValue(attrDict, kSecReturnRef, kCFBooleanTrue);
+    
+    SecKeychainItemRef itemRef;
+    OSStatus res = SecItemCopyMatching((CFDictionaryRef)attrDict, (CFTypeRef*)&itemRef);
+    
+    if(res == errSecItemNotFound)
+      return true;
+    else
+      return false;
+
+  }
+
+
+  ////////////////////////////////
+  // OSXPrivateKeyStorage::Impl //
+  ////////////////////////////////
+
+  SecKeychainItemRef
+  SecTpmOsx::Impl::getKey(const Name & keyName, KeyClass keyClass)
+  {
+    string keyNameUri = toInternalKeyName(keyName, keyClass);
+
+    CFStringRef keyLabel = CFStringCreateWithCString(NULL, 
+                                                     keyNameUri.c_str(), 
+                                                     kCFStringEncodingUTF8);
+    
+    CFMutableDictionaryRef attrDict = CFDictionaryCreateMutable(NULL,
+                                                             5,
+                                                             &kCFTypeDictionaryKeyCallBacks,
+                                                             NULL);
+
+    CFDictionaryAddValue(attrDict, kSecClass, kSecClassKey);
+    CFDictionaryAddValue(attrDict, kSecAttrLabel, keyLabel);
+    CFDictionaryAddValue(attrDict, kSecAttrKeyClass, getKeyClass(keyClass));
+    CFDictionaryAddValue(attrDict, kSecReturnRef, kCFBooleanTrue);
+    
+    SecKeychainItemRef keyItem;
+
+    OSStatus res = SecItemCopyMatching((CFDictionaryRef) attrDict, (CFTypeRef*)&keyItem);
+    
+    if(res != errSecSuccess){
+      _LOG_DEBUG("Fail to find the key!");
+      return NULL;
+    }
+    else
+      return keyItem;
+  }
+  
+  string 
+  SecTpmOsx::Impl::toInternalKeyName(const Name & keyName, KeyClass keyClass)
+  {
+    string keyUri = keyName.toUri();
+
+    if(KEY_CLASS_SYMMETRIC == keyClass)
+      return keyUri + "/symmetric";
+    else
+      return keyUri;
+  }
+
+  const CFTypeRef 
+  SecTpmOsx::Impl::getAsymKeyType(KeyType keyType)
+  {
+    switch(keyType){
+    case KEY_TYPE_RSA:
+      return kSecAttrKeyTypeRSA;
+    default:
+      _LOG_DEBUG("Unrecognized key type!")
+      return NULL;
+    }
+  }
+
+  const CFTypeRef 
+  SecTpmOsx::Impl::getSymKeyType(KeyType keyType)
+  {
+    switch(keyType){
+    case KEY_TYPE_AES:
+      return kSecAttrKeyTypeAES;
+    default:
+      _LOG_DEBUG("Unrecognized key type!")
+      return NULL;
+    }
+  }
+
+  const CFTypeRef 
+  SecTpmOsx::Impl::getKeyClass(KeyClass keyClass)
+  {
+    switch(keyClass){
+    case KEY_CLASS_PRIVATE:
+      return kSecAttrKeyClassPrivate;
+    case KEY_CLASS_PUBLIC:
+      return kSecAttrKeyClassPublic;
+    case KEY_CLASS_SYMMETRIC:
+      return kSecAttrKeyClassSymmetric;
+    default:
+      _LOG_DEBUG("Unrecognized key class!");
+      return NULL;
+    }
+  }
+
+  const CFStringRef 
+  SecTpmOsx::Impl::getDigestAlgorithm(DigestAlgorithm digestAlgo)
+  {
+    switch(digestAlgo){
+    // case DIGEST_MD2:
+    //   return kSecDigestMD2;
+    // case DIGEST_MD5:
+    //   return kSecDigestMD5;
+    // case DIGEST_SHA1:
+    //   return kSecDigestSHA1;
+    case DIGEST_ALGORITHM_SHA256:
+      return kSecDigestSHA2;
+    default:
+      _LOG_DEBUG("Unrecognized digest algorithm!");
+      return NULL;
+    }
+  }
+
+  long 
+  SecTpmOsx::Impl::getDigestSize(DigestAlgorithm digestAlgo)
+  {
+    switch(digestAlgo){
+    case DIGEST_ALGORITHM_SHA256:
+      return 256;
+    // case DIGEST_SHA1:
+    // case DIGEST_MD2:
+    // case DIGEST_MD5:
+    //   return 0;
+    default:
+      _LOG_DEBUG("Unrecognized digest algorithm! Unknown digest size");
+      return -1;
+    }
+  }
+  
+}