blob: 24d47ea497088d3e6a8d6794b68a2ffa80a5397b [file] [log] [blame]
/* -*- 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 "common.hpp"
#include "sec-tpm-osx.hpp"
#include "security/public-key.hpp"
#include "util/logging.hpp"
#include "cryptopp.hpp"
#include <pwd.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <CoreFoundation/CoreFoundation.h>
#include <Security/Security.h>
#include <Security/SecRandom.h>
#include <CoreServices/CoreServices.h>
using namespace std;
INIT_LOGGER("ndn.SecTpmOsx");
namespace ndn {
class SecTpmOsx::Impl {
public:
Impl()
: m_passwordSet(false)
, m_inTerminal(false)
{}
/**
* @brief Convert NDN name of a key to internal name of the key.
*
* @param keyName
* @param keyClass
* @return the internal key name
*/
std::string
toInternalKeyName(const Name & keyName, KeyClass keyClass);
/**
* @brief Get key.
*
* @param keyName
* @param keyClass
* @returns pointer to the key
*/
SecKeychainItemRef
getKey(const Name & keyName, KeyClass keyClass);
/**
* @brief Convert keyType to MAC OS symmetric key key type
*
* @param keyType
* @returns MAC OS key type
*/
const CFTypeRef
getSymKeyType(KeyType keyType);
/**
* @brief Convert keyType to MAC OS asymmetirc key type
*
* @param keyType
* @returns MAC OS key type
*/
const CFTypeRef
getAsymKeyType(KeyType keyType);
/**
* @brief Convert keyClass to MAC OS key class
*
* @param keyClass
* @returns MAC OS key class
*/
const CFTypeRef
getKeyClass(KeyClass keyClass);
/**
* @brief Convert digestAlgo to MAC OS algorithm id
*
* @param digestAlgo
* @returns MAC OS algorithm id
*/
const CFStringRef
getDigestAlgorithm(DigestAlgorithm digestAlgo);
/**
* @brief Get the digest size of the corresponding algorithm
*
* @param digestAlgo
* @return digest size
*/
long
getDigestSize(DigestAlgorithm digestAlgo);
///////////////////////////////////////////////
// everything here is public, including data //
///////////////////////////////////////////////
public:
SecKeychainRef m_keyChainRef;
bool m_passwordSet;
string m_password;
bool m_inTerminal;
};
SecTpmOsx::SecTpmOsx()
: m_impl(new Impl)
{
if(m_impl->m_inTerminal)
SecKeychainSetUserInteractionAllowed (false);
else
SecKeychainSetUserInteractionAllowed (true);
OSStatus res = SecKeychainCopyDefault(&m_impl->m_keyChainRef);
if (res == errSecNoDefaultKeychain) //If no default key chain, create one.
throw Error("No default keychain, create one first!");
}
SecTpmOsx::~SecTpmOsx(){
//TODO: implement
}
void
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());
m_impl->m_password.clear();
m_impl->m_password.append(reinterpret_cast<const char*>(password), passwordLength);
}
void
SecTpmOsx::resetTpmPassword()
{
m_impl->m_passwordSet = false;
memset(const_cast<char*>(m_impl->m_password.c_str()), 0, m_impl->m_password.size());
m_impl->m_password.clear();
}
void
SecTpmOsx::setInTerminal(bool inTerminal)
{
m_impl->m_inTerminal = inTerminal;
if(inTerminal)
SecKeychainSetUserInteractionAllowed (false);
else
SecKeychainSetUserInteractionAllowed (true);
}
bool
SecTpmOsx::getInTerminal()
{
return m_impl->m_inTerminal;
}
bool
SecTpmOsx::locked()
{
SecKeychainStatus keychainStatus;
OSStatus res = SecKeychainGetStatus(m_impl->m_keyChainRef, &keychainStatus);
if(res != errSecSuccess)
return true;
else
return ((kSecUnlockStateStatus & keychainStatus) == 0);
}
bool
SecTpmOsx::unlockTpm(const char* password, size_t passwordLength, bool usePassword)
{
OSStatus res;
// If the default key chain is already unlocked, return immediately.
if(!locked())
return true;
// If the default key chain is locked, unlock the key chain.
if(usePassword)
{
// Use the supplied password.
res = SecKeychainUnlock(m_impl->m_keyChainRef,
passwordLength,
password,
true);
}
else if(m_impl->m_passwordSet)
{
// If no password supplied, then use the configured password if exists.
SecKeychainUnlock(m_impl->m_keyChainRef,
m_impl->m_password.size(),
m_impl->m_password.c_str(),
true);
}
else if(m_impl->m_inTerminal)
{
// If no configured password, get password from terminal if inTerminal set.
bool locked = true;
const char* fmt = "Password to unlock the default keychain: ";
int count = 0;
while(locked)
{
if(count > 2)
break;
char* getPassword = NULL;
getPassword = getpass(fmt);
count++;
if (!getPassword)
continue;
res = SecKeychainUnlock(m_impl->m_keyChainRef,
strlen(getPassword),
getPassword,
true);
memset(getPassword, 0, strlen(getPassword));
if(res == errSecSuccess)
break;
}
}
else
{
// If inTerminal is not set, get the password from GUI.
SecKeychainUnlock(m_impl->m_keyChainRef, 0, 0, false);
}
return !locked();
}
void
SecTpmOsx::generateKeyPairInTpmInternal(const Name & keyName, KeyType keyType, int keySize, bool retry)
{
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);
if (res == errSecSuccess)
{
CFRelease(publicKey);
CFRelease(privateKey);
return;
}
if (res == errSecAuthFailed && !retry)
{
if(unlockTpm(0, 0, false))
generateKeyPairInTpmInternal(keyName, keyType, keySize, true);
else
throw Error("Fail to unlock the keychain");
}
else
{
_LOG_DEBUG("Fail to create a key pair: " << res);
throw Error("Fail to create a key pair");
}
}
void
SecTpmOsx::deleteKeyPairInTpmInternal(const Name &keyName, bool retry)
{
CFStringRef keyLabel = CFStringCreateWithCString(NULL,
keyName.toUri().c_str(),
kCFStringEncodingUTF8);
CFMutableDictionaryRef searchDict =
CFDictionaryCreateMutable(NULL, 5, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
CFDictionaryAddValue(searchDict, kSecClass, kSecClassKey);
CFDictionaryAddValue(searchDict, kSecAttrLabel, keyLabel);
CFDictionaryAddValue(searchDict, kSecMatchLimit, kSecMatchLimitAll);
OSStatus res = SecItemDelete(searchDict);
if (res == errSecSuccess)
return;
if (res == errSecAuthFailed && !retry)
{
if(unlockTpm(0, 0, false))
deleteKeyPairInTpmInternal(keyName, true);
}
}
void
SecTpmOsx::generateSymmetricKeyInTpm(const Name & keyName, KeyType keyType, int keySize)
{
throw Error("SecTpmOsx::generateSymmetricKeyInTpm is not supported");
// 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");
}
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);
if (res != errSecSuccess)
{
throw Error("Cannot export requested public key from OSX Keychain");
}
shared_ptr<PublicKey> key = make_shared<PublicKey>(CFDataGetBytePtr(exportedKey), CFDataGetLength(exportedKey));
CFRelease(exportedKey);
return key;
}
ConstBufferPtr
SecTpmOsx::exportPrivateKeyPkcs1FromTpmInternal(const Name& keyName, bool retry)
{
using namespace CryptoPP;
SecKeychainItemRef privateKey = m_impl->getKey(keyName, KEY_CLASS_PRIVATE);
CFDataRef exportedKey;
OSStatus res = SecItemExport(privateKey,
kSecFormatOpenSSL,
0,
NULL,
&exportedKey);
if(res != errSecSuccess)
{
if(res == errSecAuthFailed && !retry)
{
if(unlockTpm(0, 0, false))
return exportPrivateKeyPkcs1FromTpmInternal(keyName, true);
else
return shared_ptr<Buffer>();
}
else
return shared_ptr<Buffer>();
}
OBufferStream pkcs1Os;
FileSink sink(pkcs1Os);
uint32_t version = 0;
OID algorithm("1.2.840.113549.1.1.1");
SecByteBlock rawKeyBits;
// PrivateKeyInfo ::= SEQUENCE {
// version INTEGER,
// privateKeyAlgorithm SEQUENCE,
// privateKey OCTECT STRING}
DERSequenceEncoder privateKeyInfo(sink);
{
DEREncodeUnsigned<uint32_t>(privateKeyInfo, version, INTEGER);
DERSequenceEncoder privateKeyAlgorithm(privateKeyInfo);
{
algorithm.encode(privateKeyAlgorithm);
DEREncodeNull(privateKeyAlgorithm);
}
privateKeyAlgorithm.MessageEnd();
DEREncodeOctetString(privateKeyInfo, CFDataGetBytePtr(exportedKey), CFDataGetLength(exportedKey));
}
privateKeyInfo.MessageEnd();
CFRelease(exportedKey);
return pkcs1Os.buf();
}
#ifdef __GNUC__
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
#pragma GCC diagnostic push
#endif // __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif // __GNUC__
bool
SecTpmOsx::importPrivateKeyPkcs1IntoTpmInternal(const Name& keyName, const uint8_t* buf, size_t size, bool retry)
{
using namespace CryptoPP;
StringSource privateKeySource(buf, size, true);
uint32_t tmpNum;
OID tmpOID;
SecByteBlock rawKeyBits;
// PrivateKeyInfo ::= SEQUENCE {
// INTEGER,
// SEQUENCE,
// OCTECT STRING}
BERSequenceDecoder privateKeyInfo(privateKeySource);
{
BERDecodeUnsigned<uint32_t>(privateKeyInfo, tmpNum, INTEGER);
BERSequenceDecoder sequenceDecoder(privateKeyInfo);
{
tmpOID.decode(sequenceDecoder);
BERDecodeNull(sequenceDecoder);
}
BERDecodeOctetString(privateKeyInfo, rawKeyBits);
}
privateKeyInfo.MessageEnd();
CFDataRef importedKey = CFDataCreateWithBytesNoCopy(NULL,
rawKeyBits.BytePtr(),
rawKeyBits.size(),
kCFAllocatorNull);
SecExternalFormat externalFormat = kSecFormatOpenSSL;
SecExternalItemType externalType = kSecItemTypePrivateKey;
SecKeyImportExportParameters keyParams;
memset(&keyParams, 0, sizeof(keyParams));
keyParams.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
keyParams.keyAttributes = CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_PERMANENT;
SecAccessRef access;
CFStringRef keyLabel = CFStringCreateWithCString(NULL,
keyName.toUri().c_str(),
kCFStringEncodingUTF8);
SecAccessCreate(keyLabel, NULL, &access);
keyParams.accessRef = access;
CFArrayRef outItems;
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
#endif // __clang__
OSStatus res = SecKeychainItemImport (importedKey,
NULL,
&externalFormat,
&externalType,
0,
&keyParams,
m_impl->m_keyChainRef,
&outItems);
#ifdef __clang__
#pragma clang diagnostic pop
#endif // __clang__
if(res != errSecSuccess)
{
if(res == errSecAuthFailed && !retry)
{
if(unlockTpm(0, 0, false))
return importPrivateKeyPkcs1IntoTpmInternal(keyName, buf, size, true);
else
return false;
}
else
return false;
}
SecKeychainItemRef privateKey = (SecKeychainItemRef)CFArrayGetValueAtIndex(outItems, 0);
SecKeychainAttribute attrs[1]; // maximum number of attributes
SecKeychainAttributeList attrList = { 0, attrs };
string keyUri = keyName.toUri();
{
attrs[attrList.count].tag = kSecKeyPrintName;
attrs[attrList.count].length = keyUri.size();
attrs[attrList.count].data = (void *)keyUri.c_str();
attrList.count++;
}
res = SecKeychainItemModifyAttributesAndData(privateKey,
&attrList,
0,
NULL);
if(res != errSecSuccess)
{
return false;
}
CFRelease(importedKey);
return true;
}
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
#pragma GCC diagnostic pop
#endif // __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
bool
SecTpmOsx::importPublicKeyPkcs1IntoTpm(const Name& keyName, const uint8_t* buf, size_t size)
{
CFDataRef importedKey = CFDataCreateWithBytesNoCopy(NULL,
buf,
size,
kCFAllocatorNull);
SecExternalFormat externalFormat = kSecFormatOpenSSL;
SecExternalItemType externalType = kSecItemTypePublicKey;
CFArrayRef outItems;
OSStatus res = SecItemImport (importedKey,
NULL,
&externalFormat,
&externalType,
0,
NULL,
m_impl->m_keyChainRef,
&outItems);
if(res != errSecSuccess)
return false;
SecKeychainItemRef publicKey = (SecKeychainItemRef)CFArrayGetValueAtIndex(outItems, 0);
SecKeychainAttribute attrs[1]; // maximum number of attributes
SecKeychainAttributeList attrList = { 0, attrs };
string keyUri = keyName.toUri();
{
attrs[attrList.count].tag = kSecKeyPrintName;
attrs[attrList.count].length = keyUri.size();
attrs[attrList.count].data = (void *)keyUri.c_str();
attrList.count++;
}
res = SecKeychainItemModifyAttributesAndData(publicKey,
&attrList,
0,
NULL);
if(res != errSecSuccess)
return false;
CFRelease(importedKey);
return true;
}
Block
SecTpmOsx::signInTpmInternal(const uint8_t *data, size_t dataLength, const Name& keyName, DigestAlgorithm digestAlgorithm, bool retry)
{
_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)
{
if(!retry)
{
if(unlockTpm(0, 0, false))
return signInTpmInternal(data, dataLength, keyName, digestAlgorithm, true);
else
throw Error("Fail to unlock the keychain");
}
else
{
CFShow(error);
throw Error("Fail to sign data");
}
}
if (!signature) throw Error("Signature is NULL!\n");
return Block(Tlv::SignatureValue,
make_shared<Buffer>(CFDataGetBytePtr(signature), CFDataGetLength(signature)));
}
ConstBufferPtr
SecTpmOsx::decryptInTpm(const uint8_t* data, size_t dataLength, const Name & keyName, bool sym)
{
throw Error("SecTpmOsx::decryptInTpm is not supported");
// _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 make_shared<Buffer>(CFDataGetBytePtr(output), CFDataGetLength(output));
}
void
SecTpmOsx::addAppToACL(const Name & keyName, KeyClass keyClass, const string & appPath, AclType acl)
{
if(keyClass == KEY_CLASS_PRIVATE && acl == ACL_TYPE_PRIVATE)
{
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);
acl_res = SecACLSetContents(aclRef,
newAppList,
description,
promptSelector);
acc_res = SecKeychainItemSetAccess(privateKey, accRef);
}
}
ConstBufferPtr
SecTpmOsx::encryptInTpm(const uint8_t* data, size_t dataLength, const Name & keyName, bool sym)
{
throw Error("SecTpmOsx::encryptInTpm is not supported");
// _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 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 == errSecSuccess)
return true;
else
return false;
}
bool
SecTpmOsx::generateRandomBlock(uint8_t* res, size_t size)
{
return (SecRandomCopyBytes(kSecRandomDefault, size, res) == 0);
}
////////////////////////////////
// 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;
}
}
} // namespace ndn