security: Signature interface change and initial fixes for OSX private key store
Change-Id: Ic6d074e99346c4bf9d7b2c20c961dd01d770636d
diff --git a/src/security/identity/osx-private-key-storage.cpp b/src/security/identity/osx-private-key-storage.cpp
index e504616..f41f89f 100644
--- a/src/security/identity/osx-private-key-storage.cpp
+++ b/src/security/identity/osx-private-key-storage.cpp
@@ -11,11 +11,14 @@
#include <fstream>
#include <sstream>
-#include <CoreFoundation/CoreFoundation.h>
#include "../../util/logging.hpp"
-#include <ndn-cpp/security/identity/osx-private-key-storage.hpp>
-#include <ndn-cpp/security/security-exception.hpp>
+#include "osx-private-key-storage.hpp"
+#include "../certificate/public-key.hpp"
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <Security/Security.h>
+#include <CoreServices/CoreServices.h>
using namespace std;
@@ -23,31 +26,107 @@
namespace ndn
{
+ class OSXPrivateKeyStorage::Impl {
+ public:
+ Impl(const std::string &keychainName)
+ : keyChainName_ ("" == keychainName ? "NDN.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_;
+ };
+
+
+
OSXPrivateKeyStorage::OSXPrivateKeyStorage(const string & keychainName)
- : keyChainName_("" == keychainName ? "NDN.keychain" : keychainName)
+ : impl_(new Impl(keychainName))
{
- OSStatus res = SecKeychainCreate(keyChainName_.c_str(), //Keychain path
+ OSStatus res = SecKeychainCreate(impl_->keyChainName_.c_str(), //Keychain path
0, //Keychain password length
NULL, //Keychain password
true, //User prompt
NULL, //Initial access of Keychain
- &keyChainRef_); //Keychain reference
+ &impl_->keyChainRef_); //Keychain reference
if (res == errSecDuplicateKeychain)
- res = SecKeychainOpen(keyChainName_.c_str(),
- &keyChainRef_);
+ res = SecKeychainOpen(impl_->keyChainName_.c_str(),
+ &impl_->keyChainRef_);
if (res != errSecSuccess){
_LOG_DEBUG("Fail to initialize keychain ref: " << res);
- throw SecurityException("Fail to initialize keychain ref");
+ throw Error("Fail to initialize keychain ref");
}
- res = SecKeychainCopyDefault(&originalDefaultKeyChain_);
+ res = SecKeychainCopyDefault(&impl_->originalDefaultKeyChain_);
- res = SecKeychainSetDefault(keyChainRef_);
+ res = SecKeychainSetDefault(impl_->keyChainRef_);
if (res != errSecSuccess){
_LOG_DEBUG("Fail to set default keychain: " << res);
- throw SecurityException("Fail to set default keychain");
+ throw Error("Fail to set default keychain");
}
}
@@ -61,10 +140,10 @@
if(doesKeyExist(keyName, KEY_CLASS_PUBLIC)){
_LOG_DEBUG("keyName has existed");
- throw SecurityException("keyName has existed");
+ throw Error("keyName has existed");
}
- string keyNameUri = toInternalKeyName(keyName, KEY_CLASS_PUBLIC);
+ string keyNameUri = impl_->toInternalKeyName(keyName, KEY_CLASS_PUBLIC);
SecKeyRef publicKey, privateKey;
@@ -77,7 +156,7 @@
&kCFTypeDictionaryKeyCallBacks,
NULL);
- CFDictionaryAddValue(attrDict, kSecAttrKeyType, getAsymKeyType(keyType));
+ CFDictionaryAddValue(attrDict, kSecAttrKeyType, impl_->getAsymKeyType(keyType));
CFDictionaryAddValue(attrDict, kSecAttrKeySizeInBits, CFNumberCreate(NULL, kCFNumberIntType, &keySize));
CFDictionaryAddValue(attrDict, kSecAttrLabel, keyLabel);
@@ -88,7 +167,7 @@
if (res != errSecSuccess){
_LOG_DEBUG("Fail to create a key pair: " << res);
- throw SecurityException("Fail to create a key pair");
+ throw Error("Fail to create a key pair");
}
}
@@ -97,9 +176,9 @@
{
if(doesKeyExist(keyName, KEY_CLASS_SYMMETRIC))
- throw SecurityException("keyName has existed!");
+ throw Error("keyName has existed!");
- string keyNameUri = toInternalKeyName(keyName, KEY_CLASS_SYMMETRIC);
+ string keyNameUri = impl_->toInternalKeyName(keyName, KEY_CLASS_SYMMETRIC);
CFMutableDictionaryRef attrDict = CFDictionaryCreateMutable(kCFAllocatorDefault,
0,
@@ -110,7 +189,7 @@
keyNameUri.c_str(),
kCFStringEncodingUTF8);
- CFDictionaryAddValue(attrDict, kSecAttrKeyType, getSymKeyType(keyType));
+ CFDictionaryAddValue(attrDict, kSecAttrKeyType, impl_->getSymKeyType(keyType));
CFDictionaryAddValue(attrDict, kSecAttrKeySizeInBits, CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &keySize));
CFDictionaryAddValue(attrDict, kSecAttrIsPermanent, kCFBooleanTrue);
CFDictionaryAddValue(attrDict, kSecAttrLabel, keyLabel);
@@ -120,14 +199,15 @@
SecKeyRef symmetricKey = SecKeyGenerateSymmetric(attrDict, &error);
if (error)
- throw SecurityException("Fail to create a symmetric key");
+ throw Error("Fail to create a symmetric key");
}
- ptr_lib::shared_ptr<PublicKey> OSXPrivateKeyStorage::getPublicKey(const Name & keyName)
+ ptr_lib::shared_ptr<PublicKey>
+ OSXPrivateKeyStorage::getPublicKey(const Name & keyName)
{
_LOG_TRACE("OSXPrivateKeyStorage::getPublickey");
- SecKeychainItemRef publicKey = getKey(keyName, KEY_CLASS_PUBLIC);
+ SecKeychainItemRef publicKey = impl_->getKey(keyName, KEY_CLASS_PUBLIC);
CFDataRef exportedKey;
@@ -136,59 +216,78 @@
0,
NULL,
&exportedKey);
-
- Blob blob(CFDataGetBytePtr(exportedKey), CFDataGetLength(exportedKey));
- return PublicKey::fromDer(blob);
+ return ptr_lib::make_shared<PublicKey>(CFDataGetBytePtr(exportedKey), CFDataGetLength(exportedKey));
}
- Blob OSXPrivateKeyStorage::sign(const uint8_t *data, size_t dataLength, const Name & keyName, DigestAlgorithm digestAlgo)
+ Block
+ OSXPrivateKeyStorage::sign(const uint8_t *data, size_t dataLength,
+ const Name& keyName, DigestAlgorithm digestAlgorithm/* = DIGEST_ALGORITHM_SHA256*/)
{
_LOG_TRACE("OSXPrivateKeyStorage::Sign");
- CFDataRef dataRef = CFDataCreate(NULL,
- reinterpret_cast<const unsigned char*>(data),
- dataLength
- );
+ CFDataRef dataRef = CFDataCreateWithBytesNoCopy(NULL,
+ data,
+ dataLength,
+ kCFAllocatorNull
+ );
- SecKeyRef privateKey = (SecKeyRef)getKey(keyName, KEY_CLASS_PRIVATE);
+ SecKeyRef privateKey = (SecKeyRef)impl_->getKey(keyName, KEY_CLASS_PRIVATE);
CFErrorRef error;
SecTransformRef signer = SecSignTransformCreate((SecKeyRef)privateKey, &error);
- if (error) throw SecurityException("Fail to create signer");
-
+ if (error) throw Error("Fail to create signer");
+
+ // Set input
Boolean set_res = SecTransformSetAttribute(signer,
kSecTransformInputAttributeName,
dataRef,
&error);
- if (error) throw SecurityException("Fail to configure input of signer");
+ 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,
- getDigestAlgorithm(digestAlgo),
+ impl_->getDigestAlgorithm(digestAlgorithm),
&error);
- if (error) throw SecurityException("Fail to configure digest algorithm of signer");
+ if (error) throw Error("Fail to configure digest algorithm of signer");
- long digestSize = getDigestSize(digestAlgo);
-
+ // Set padding attribute
+ long digestSize = impl_->getDigestSize(digestAlgorithm);
set_res = SecTransformSetAttribute(signer,
kSecDigestLengthAttribute,
CFNumberCreate(NULL, kCFNumberLongType, &digestSize),
&error);
- if (error) throw SecurityException("Fail to configure digest size of signer");
+ if (error) throw Error("Fail to configure digest size of signer");
+ // Actually sign
CFDataRef signature = (CFDataRef) SecTransformExecute(signer, &error);
if (error) {
CFShow(error);
- throw SecurityException("Fail to sign data");
+ throw Error("Fail to sign data");
}
- if (!signature) throw SecurityException("Signature is NULL!\n");
+ if (!signature) throw Error("Signature is NULL!\n");
- return Blob(CFDataGetBytePtr(signature), CFDataGetLength(signature));
+ return Block(Tlv::SignatureValue, ptr_lib::make_shared<Buffer>(CFDataGetBytePtr(signature), CFDataGetLength(signature)));
}
- Blob OSXPrivateKeyStorage::decrypt(const Name & keyName, const uint8_t* data, size_t dataLength, bool sym)
+ void
+ OSXPrivateKeyStorage::sign(Data &data,
+ const Name& keyName, DigestAlgorithm digestAlgorithm/* = DIGEST_ALGORITHM_SHA256 */)
+ {
+ }
+
+ ConstBufferPtr
+ OSXPrivateKeyStorage::decrypt(const Name & keyName, const uint8_t* data, size_t dataLength, bool sym)
{
_LOG_TRACE("OSXPrivateKeyStorage::Decrypt");
@@ -205,34 +304,35 @@
// _LOG_DEBUG("CreateData");
- SecKeyRef decryptKey = (SecKeyRef)getKey(keyName, keyClass);
+ SecKeyRef decryptKey = (SecKeyRef)impl_->getKey(keyName, keyClass);
// _LOG_DEBUG("GetKey");
CFErrorRef error;
SecTransformRef decrypt = SecDecryptTransformCreate(decryptKey, &error);
- if (error) throw SecurityException("Fail to create decrypt");
+ if (error) throw Error("Fail to create decrypt");
Boolean set_res = SecTransformSetAttribute(decrypt,
kSecTransformInputAttributeName,
dataRef,
&error);
- if (error) throw SecurityException("Fail to configure decrypt");
+ if (error) throw Error("Fail to configure decrypt");
CFDataRef output = (CFDataRef) SecTransformExecute(decrypt, &error);
if (error)
{
CFShow(error);
- throw SecurityException("Fail to decrypt data");
+ throw Error("Fail to decrypt data");
}
- if (!output) throw SecurityException("Output is NULL!\n");
+ if (!output) throw Error("Output is NULL!\n");
- return Blob(CFDataGetBytePtr(output), CFDataGetLength(output));
+ return ptr_lib::make_shared<Buffer>(CFDataGetBytePtr(output), CFDataGetLength(output));
}
- bool OSXPrivateKeyStorage::setACL(const Name & keyName, KeyClass keyClass, int acl, const string & appPath)
+ bool
+ OSXPrivateKeyStorage::setACL(const Name & keyName, KeyClass keyClass, int acl, const string & appPath)
{
- SecKeychainItemRef privateKey = getKey(keyName, keyClass);
+ SecKeychainItemRef privateKey = impl_->getKey(keyName, keyClass);
SecAccessRef accRef;
OSStatus acc_res = SecKeychainItemCopyAccess(privateKey, &accRef);
@@ -279,53 +379,55 @@
return true;
}
- bool OSXPrivateKeyStorage::verifyData(const Name & keyName, const Blob & pData, const Blob & pSig, DigestAlgorithm digestAlgo)
- {
- _LOG_TRACE("OSXPrivateKeyStorage::Verify");
+ // 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 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());
+ // CFDataRef sigRef = CFDataCreate(NULL,
+ // reinterpret_cast<const unsigned char*>(pSig.buf()),
+ // pSig.size());
- SecKeyRef publicKey = (SecKeyRef)getKey(keyName, KEY_CLASS_PUBLIC);
+ // SecKeyRef publicKey = (SecKeyRef)impl_->getKey(keyName, KEY_CLASS_PUBLIC);
- CFErrorRef error;
- SecTransformRef verifier = SecVerifyTransformCreate(publicKey, sigRef, &error);
- if (error) throw SecurityException("Fail to create verifier");
+ // 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 SecurityException("Fail to configure input of verifier");
+ // Boolean set_res = SecTransformSetAttribute(verifier,
+ // kSecTransformInputAttributeName,
+ // dataRef,
+ // &error);
+ // if (error) throw Error("Fail to configure input of verifier");
- set_res = SecTransformSetAttribute(verifier,
- kSecDigestTypeAttribute,
- getDigestAlgorithm(digestAlgo),
- &error);
- if (error) throw SecurityException("Fail to configure digest algorithm of verifier");
+ // set_res = SecTransformSetAttribute(verifier,
+ // kSecDigestTypeAttribute,
+ // impl_->getDigestAlgorithm(digestAlgo),
+ // &error);
+ // if (error) throw Error("Fail to configure digest algorithm of verifier");
- long digestSize = getDigestSize(digestAlgo);
- set_res = SecTransformSetAttribute(verifier,
- kSecDigestLengthAttribute,
- CFNumberCreate(NULL, kCFNumberLongType, &digestSize),
- &error);
- if (error) throw SecurityException("Fail to configure digest size 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 SecurityException("Fail to verify data");
+ // CFBooleanRef result = (CFBooleanRef) SecTransformExecute(verifier, &error);
+ // if (error) throw Error("Fail to verify data");
- if (result == kCFBooleanTrue)
- return true;
- else
- return false;
- }
+ // if (result == kCFBooleanTrue)
+ // return true;
+ // else
+ // return false;
+ // }
- Blob OSXPrivateKeyStorage::encrypt(const Name & keyName, const uint8_t* data, size_t dataLength, bool sym)
+ ConstBufferPtr
+ OSXPrivateKeyStorage::encrypt(const Name & keyName, const uint8_t* data, size_t dataLength, bool sym)
{
_LOG_TRACE("OSXPrivateKeyStorage::Encrypt");
@@ -340,31 +442,32 @@
dataLength
);
- SecKeyRef encryptKey = (SecKeyRef)getKey(keyName, keyClass);
+ SecKeyRef encryptKey = (SecKeyRef)impl_->getKey(keyName, keyClass);
CFErrorRef error;
SecTransformRef encrypt = SecEncryptTransformCreate(encryptKey, &error);
- if (error) throw SecurityException("Fail to create encrypt");
+ if (error) throw Error("Fail to create encrypt");
Boolean set_res = SecTransformSetAttribute(encrypt,
kSecTransformInputAttributeName,
dataRef,
&error);
- if (error) throw SecurityException("Fail to configure encrypt");
+ if (error) throw Error("Fail to configure encrypt");
CFDataRef output = (CFDataRef) SecTransformExecute(encrypt, &error);
- if (error) throw SecurityException("Fail to encrypt data");
+ if (error) throw Error("Fail to encrypt data");
- if (!output) throw SecurityException("Output is NULL!\n");
+ if (!output) throw Error("Output is NULL!\n");
- return Blob(CFDataGetBytePtr(output), CFDataGetLength(output));
+ return ptr_lib::make_shared<Buffer> (CFDataGetBytePtr(output), CFDataGetLength(output));
}
- bool OSXPrivateKeyStorage::doesKeyExist(const Name & keyName, KeyClass keyClass)
+ bool
+ OSXPrivateKeyStorage::doesKeyExist(const Name & keyName, KeyClass keyClass)
{
_LOG_TRACE("OSXPrivateKeyStorage::doesKeyExist");
- string keyNameUri = toInternalKeyName(keyName, keyClass);
+ string keyNameUri = impl_->toInternalKeyName(keyName, keyClass);
CFStringRef keyLabel = CFStringCreateWithCString(NULL,
keyNameUri.c_str(),
@@ -375,7 +478,7 @@
&kCFTypeDictionaryKeyCallBacks,
NULL);
- CFDictionaryAddValue(attrDict, kSecAttrKeyClass, getKeyClass(keyClass));
+ CFDictionaryAddValue(attrDict, kSecAttrKeyClass, impl_->getKeyClass(keyClass));
CFDictionaryAddValue(attrDict, kSecAttrLabel, keyLabel);
CFDictionaryAddValue(attrDict, kSecReturnRef, kCFBooleanTrue);
@@ -389,7 +492,13 @@
}
- SecKeychainItemRef OSXPrivateKeyStorage::getKey(const Name & keyName, KeyClass keyClass)
+
+ ////////////////////////////////
+ // OSXPrivateKeyStorage::Impl //
+ ////////////////////////////////
+
+ SecKeychainItemRef
+ OSXPrivateKeyStorage::Impl::getKey(const Name & keyName, KeyClass keyClass)
{
string keyNameUri = toInternalKeyName(keyName, keyClass);
@@ -419,7 +528,7 @@
return keyItem;
}
- string OSXPrivateKeyStorage::toInternalKeyName(const Name & keyName, KeyClass keyClass)
+ string OSXPrivateKeyStorage::Impl::toInternalKeyName(const Name & keyName, KeyClass keyClass)
{
string keyUri = keyName.toUri();
@@ -429,7 +538,7 @@
return keyUri;
}
- const CFTypeRef OSXPrivateKeyStorage::getAsymKeyType(KeyType keyType)
+ const CFTypeRef OSXPrivateKeyStorage::Impl::getAsymKeyType(KeyType keyType)
{
switch(keyType){
case KEY_TYPE_RSA:
@@ -440,7 +549,7 @@
}
}
- const CFTypeRef OSXPrivateKeyStorage::getSymKeyType(KeyType keyType)
+ const CFTypeRef OSXPrivateKeyStorage::Impl::getSymKeyType(KeyType keyType)
{
switch(keyType){
case KEY_TYPE_AES:
@@ -451,7 +560,7 @@
}
}
- const CFTypeRef OSXPrivateKeyStorage::getKeyClass(KeyClass keyClass)
+ const CFTypeRef OSXPrivateKeyStorage::Impl::getKeyClass(KeyClass keyClass)
{
switch(keyClass){
case KEY_CLASS_PRIVATE:
@@ -466,7 +575,7 @@
}
}
- const CFStringRef OSXPrivateKeyStorage::getDigestAlgorithm(DigestAlgorithm digestAlgo)
+ const CFStringRef OSXPrivateKeyStorage::Impl::getDigestAlgorithm(DigestAlgorithm digestAlgo)
{
switch(digestAlgo){
// case DIGEST_MD2:
@@ -483,7 +592,7 @@
}
}
- long OSXPrivateKeyStorage::getDigestSize(DigestAlgorithm digestAlgo)
+ long OSXPrivateKeyStorage::Impl::getDigestSize(DigestAlgorithm digestAlgo)
{
switch(digestAlgo){
case DIGEST_ALGORITHM_SHA256: