security: Explicitly request password to unlock keychain
refs: #1224
Change-Id: Ia6589772e32b8dbbe57a49a2661fcf451e9b6dd8
diff --git a/src/security/sec-tpm-osx.cpp b/src/security/sec-tpm-osx.cpp
index 25b42df..ba2464f 100644
--- a/src/security/sec-tpm-osx.cpp
+++ b/src/security/sec-tpm-osx.cpp
@@ -12,6 +12,10 @@
#include <fstream>
#include <sstream>
+#include <pwd.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
#include <CoreFoundation/CoreFoundation.h>
#include <Security/Security.h>
@@ -23,610 +27,695 @@
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);
+class SecTpmOsx::Impl {
+public:
+ Impl()
+ {}
- /**
- * 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);
+ /**
+ * @brief 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);
- /**
- * convert keyType to MAC OS asymmetirc key type
- * @param keyType
- * @returns MAC OS key type
- */
- const CFTypeRef
- getAsymKeyType(KeyType keyType);
+ /**
+ * @brief 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 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(doesKeyExistInTpm(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::deleteKeyPairInTpm(const Name &keyName)
- {
- string keyNameUri = keyName.toUri();
-
- 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, kSecMatchLimit, kSecMatchLimitAll);
-
- OSStatus res = SecItemDelete((CFDictionaryRef) attrDict);
-
- if(res != errSecSuccess)
- _LOG_DEBUG("Fail to find the key!");
- }
-
- void
- SecTpmOsx::generateSymmetricKeyInTpm(const Name & keyName, KeyType keyType, int keySize)
- {
-
- if(doesKeyExistInTpm(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::signInTpm(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)));
- }
-
- ConstBufferPtr
- SecTpmOsx::decryptInTpm(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::encryptInTpm(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::doesKeyExistInTpm(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,
- 4,
- &kCFTypeDictionaryKeyCallBacks,
- NULL);
-
- CFDictionaryAddValue(attrDict, kSecClass, kSecClassKey);
- 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 false;
- else
- return true;
-
- }
-
-
- ////////////////////////////////
- // 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;
- }
-
+ /**
+ * convert keyType to MAC OS symmetric key key type
+ * @param keyType
+ * @returns MAC OS key type
+ */
const CFTypeRef
- SecTpmOsx::Impl::getAsymKeyType(KeyType keyType)
- {
- switch(keyType){
- case KEY_TYPE_RSA:
- return kSecAttrKeyTypeRSA;
- default:
- _LOG_DEBUG("Unrecognized key type!")
- return NULL;
- }
- }
-
+ getSymKeyType(KeyType keyType);
+
+ /**
+ * convert keyType to MAC OS asymmetirc key type
+ * @param keyType
+ * @returns MAC OS key type
+ */
const CFTypeRef
- SecTpmOsx::Impl::getSymKeyType(KeyType keyType)
- {
- switch(keyType){
- case KEY_TYPE_AES:
- return kSecAttrKeyTypeAES;
- default:
- _LOG_DEBUG("Unrecognized key type!")
- return NULL;
- }
- }
-
+ getAsymKeyType(KeyType keyType);
+
+ /**
+ * convert keyClass to MAC OS key class
+ * @param keyClass
+ * @returns MAC OS key class
+ */
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;
- }
- }
-
+ getKeyClass(KeyClass keyClass);
+
+ /**
+ * convert digestAlgo to MAC OS algorithm id
+ * @param digestAlgo
+ * @returns MAC OS algorithm id
+ */
const CFStringRef
- SecTpmOsx::Impl::getDigestAlgorithm(DigestAlgorithm digestAlgo)
- {
- switch(digestAlgo){
+ getDigestAlgorithm(DigestAlgorithm digestAlgo);
+
+ /**
+ * get the digest size of the corresponding algorithm
+ * @param digestAlgo the digest algorithm
+ * @return digest size
+ */
+ long
+ getDigestSize(DigestAlgorithm digestAlgo);
+
+ bool
+ getPassWord(string& password, string target);
+
+ ///////////////////////////////////////////////
+ // everything here is public, including data //
+ ///////////////////////////////////////////////
+public:
+ SecKeychainRef m_keyChainRef;
+};
+
+
+SecTpmOsx::SecTpmOsx()
+ : m_impl(new Impl)
+{
+ OSStatus res = SecKeychainCopyDefault(&m_impl->m_keyChainRef);
+
+
+ if (res == errSecNoDefaultKeychain) //If no default key chain, create one.
+ {
+ //Get the password for the new key chain.
+ string keyChainName("ndnroot.keychain");
+ cerr << "No Default KeyChain! Create " << keyChainName << ":" << endl;
+ string password;
+ while(!m_impl->getPassWord(password, keyChainName))
+ {
+ cerr << "Password mismatch!" << endl;
+ }
+
+ //Create the key chain
+ res = SecKeychainCreate(keyChainName.c_str(), //Keychain path
+ password.size(), //Keychain password length
+ password.c_str(), //Keychain password
+ false, //User prompt
+ NULL, //Initial access of Keychain
+ &m_impl->m_keyChainRef); //Keychain reference
+
+ if(res == errSecSuccess)
+ cerr << keyChainName << " has been created!" << endl;
+ else
+ {
+ char* pw = const_cast<char*>(password.c_str());
+ memset(pw, 0, password.size());
+ throw Error("No default keychain!");
+ }
+
+ //Unlock the default key chain
+ SecKeychainUnlock(m_impl->m_keyChainRef,
+ password.size(),
+ password.c_str(),
+ true);
+
+ char* pw = const_cast<char*>(password.c_str());
+ memset(pw, 0, password.size());
+
+ return;
+ }
+
+ //If the default key chain exists, check if it is unlocked
+ SecKeychainStatus keychainStatus;
+ res = SecKeychainGetStatus(m_impl->m_keyChainRef, &keychainStatus);
+ if(kSecUnlockStateStatus & keychainStatus)
+ return;
+
+
+ //If the default key chain is locked, unlock the key chain
+ bool locked = true;
+ while(locked)
+ {
+ const char* fmt = "Password to unlock the default keychain: ";
+ char* password = NULL;
+ password = getpass(fmt);
+
+ if (!password)
+ {
+ memset(password, 0, strlen(password));
+ continue;
+ }
+
+ res = SecKeychainUnlock(m_impl->m_keyChainRef,
+ strlen(password),
+ password,
+ true);
+
+ memset(password, 0, strlen(password));
+
+ if(res == errSecSuccess)
+ locked = false;
+ }
+}
+
+SecTpmOsx::~SecTpmOsx(){
+ //TODO: implement
+}
+
+void
+SecTpmOsx::generateKeyPairInTpm(const Name & keyName, KeyType keyType, int keySize)
+{
+
+ if(doesKeyExistInTpm(keyName, KEY_CLASS_PUBLIC)){
+ _LOG_DEBUG("keyName has existed");
+ throw Error("keyName has existed");
+ }
+
+ string keyNameUri = m_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, m_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::deleteKeyPairInTpm(const Name &keyName)
+{
+ string keyNameUri = keyName.toUri();
+
+ 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, kSecMatchLimit, kSecMatchLimitAll);
+
+ OSStatus res = SecItemDelete((CFDictionaryRef) attrDict);
+
+ if(res != errSecSuccess)
+ _LOG_DEBUG("Fail to find the key!");
+}
+
+void
+SecTpmOsx::generateSymmetricKeyInTpm(const Name & keyName, KeyType keyType, int keySize)
+{
+
+ if(doesKeyExistInTpm(keyName, KEY_CLASS_SYMMETRIC))
+ throw Error("keyName has existed!");
+
+ string keyNameUri = m_impl->toInternalKeyName(keyName, KEY_CLASS_SYMMETRIC);
+
+ CFMutableDictionaryRef attrDict = CFDictionaryCreateMutable(kCFAllocatorDefault,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+
+ CFStringRef keyLabel = CFStringCreateWithCString(NULL,
+ keyNameUri.c_str(),
+ kCFStringEncodingUTF8);
+
+ CFDictionaryAddValue(attrDict, kSecAttrKeyType, m_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 = m_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::signInTpm(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)m_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,
+ m_impl->getDigestAlgorithm(digestAlgorithm),
+ &error);
+ if (error) throw Error("Fail to configure digest algorithm of signer");
+
+ // Set padding attribute
+ long digestSize = m_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)));
+}
+
+ConstBufferPtr
+SecTpmOsx::decryptInTpm(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)m_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 = m_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)m_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,
+// m_impl->getDigestAlgorithm(digestAlgo),
+// &error);
+// if (error) throw Error("Fail to configure digest algorithm of verifier");
+
+// long digestSize = m_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::encryptInTpm(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)m_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::doesKeyExistInTpm(const Name & keyName, KeyClass keyClass)
+{
+ _LOG_TRACE("OSXPrivateKeyStorage::doesKeyExist");
+
+ string keyNameUri = m_impl->toInternalKeyName(keyName, keyClass);
+
+ CFStringRef keyLabel = CFStringCreateWithCString(NULL,
+ keyNameUri.c_str(),
+ kCFStringEncodingUTF8);
+
+ CFMutableDictionaryRef attrDict = CFDictionaryCreateMutable(NULL,
+ 4,
+ &kCFTypeDictionaryKeyCallBacks,
+ NULL);
+
+ CFDictionaryAddValue(attrDict, kSecClass, kSecClassKey);
+ CFDictionaryAddValue(attrDict, kSecAttrKeyClass, m_impl->getKeyClass(keyClass));
+ CFDictionaryAddValue(attrDict, kSecAttrLabel, keyLabel);
+ CFDictionaryAddValue(attrDict, kSecReturnRef, kCFBooleanTrue);
+
+ SecKeychainItemRef itemRef;
+ OSStatus res = SecItemCopyMatching((CFDictionaryRef)attrDict, (CFTypeRef*)&itemRef);
+
+ if(res == errSecItemNotFound)
+ return false;
+ else
+ return true;
+
+}
+
+
+////////////////////////////////
+// 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;
- }
+ 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;
+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;
- }
+ default:
+ _LOG_DEBUG("Unrecognized digest algorithm! Unknown digest size");
+ return -1;
}
-
}
+
+bool
+SecTpmOsx::Impl::getPassWord(string& password, string target)
+{
+ int result = false;
+
+ string prompt1 = "Password for " + target + ":";
+ string prompt2 = "Confirm password for " + target + ":";
+ char* pw0 = NULL;
+
+ pw0 = getpass(prompt1.c_str());
+ if(!pw0)
+ return false;
+ string password1 = pw0;
+ memset(pw0, 0, strlen(pw0));
+
+ pw0 = getpass(prompt2.c_str());
+ if(!pw0)
+ {
+ char* pw1 = const_cast<char*>(password1.c_str());
+ memset(pw1, 0, password1.size());
+ return false;
+ }
+
+ if(!password1.compare(pw0))
+ {
+ result = true;
+ password.swap(password1);
+ }
+
+ char* pw1 = const_cast<char*>(password1.c_str());
+ memset(pw1, 0, password1.size());
+ memset(pw0, 0, strlen(pw0));
+ return result;
+}
+
+}// ndn
diff --git a/src/security/sec-tpm-osx.hpp b/src/security/sec-tpm-osx.hpp
index 915bb1d..1f95cdc 100644
--- a/src/security/sec-tpm-osx.hpp
+++ b/src/security/sec-tpm-osx.hpp
@@ -16,13 +16,13 @@
class SecTpmOsx : public SecTpm {
public:
- struct Error : public SecTpm::Error { Error(const std::string &what) : SecTpm::Error(what) {} };
+ struct Error : public SecTpm::Error { Error(const std::string& what) : SecTpm::Error(what) {} };
/**
* constructor of OSXKeyChainTpm
* @param keychainName the name of keychain
*/
- SecTpmOsx(const std::string & keychainName = "");
+ SecTpmOsx();
/**
* destructor of OSXKeyChainTpm
@@ -40,13 +40,13 @@
* @param keyName The name of the key pair.
*/
virtual void
- deleteKeyPairInTpm(const Name &keyName);
+ deleteKeyPairInTpm(const Name& keyName);
virtual ptr_lib::shared_ptr<PublicKey>
getPublicKeyFromTpm(const Name& keyName);
virtual Block
- signInTpm(const uint8_t *data, size_t dataLength, const Name& keyName, DigestAlgorithm digestAlgorithm);
+ signInTpm(const uint8_t* data, size_t dataLength, const Name& keyName, DigestAlgorithm digestAlgorithm);
/**
* Decrypt data.
@@ -102,7 +102,7 @@
* @returns true if setting succeeds
*/
bool
- setACL(const Name & keyName, KeyClass keyClass, int acl, const std::string & appPath);
+ setACL(const Name& keyName, KeyClass keyClass, int acl, const std::string& appPath);
// /**
// * verify data (test only)
@@ -117,7 +117,7 @@
private:
class Impl;
- std::auto_ptr<Impl> impl_;
+ std::auto_ptr<Impl> m_impl;
};
} // namespace ndn