27 #include "../encoding/oid.hpp" 28 #include "../encoding/buffer-stream.hpp" 36 #include <boost/lexical_cast.hpp> 38 #include <CoreFoundation/CoreFoundation.h> 39 #include <Security/Security.h> 40 #include <Security/SecRandom.h> 41 #include <CoreServices/CoreServices.h> 43 #include <Security/SecDigestTransform.h> 80 retain(inReleaser.m_typeRef);
86 if (typeRef != m_typeRef) {
96 retain(inReleaser.m_typeRef);
145 if (m_typeRef != 0) {
146 CFRelease(m_typeRef);
160 : m_passwordSet(false)
161 , m_inTerminal(false)
171 toInternalKeyName(
const Name& keyName,
KeyClass keyClass);
187 getSymKeyType(
KeyType keyType);
195 getAsymKeyType(
KeyType keyType);
236 if (m_impl->m_inTerminal)
237 SecKeychainSetUserInteractionAllowed(
false);
239 SecKeychainSetUserInteractionAllowed(
true);
241 OSStatus res = SecKeychainCopyDefault(&m_impl->m_keyChainRef);
243 if (res == errSecNoDefaultKeychain)
244 BOOST_THROW_EXCEPTION(
Error(
"No default keychain, please create one first"));
254 m_impl->m_passwordSet =
true;
255 std::fill(m_impl->m_password.begin(), m_impl->m_password.end(), 0);
256 m_impl->m_password.clear();
257 m_impl->m_password.append(reinterpret_cast<const char*>(password), passwordLength);
263 m_impl->m_passwordSet =
false;
264 std::fill(m_impl->m_password.begin(), m_impl->m_password.end(), 0);
265 m_impl->m_password.clear();
271 m_impl->m_inTerminal = inTerminal;
273 SecKeychainSetUserInteractionAllowed(
false);
275 SecKeychainSetUserInteractionAllowed(
true);
281 return m_impl->m_inTerminal;
287 SecKeychainStatus keychainStatus;
289 OSStatus res = SecKeychainGetStatus(m_impl->m_keyChainRef, &keychainStatus);
290 if (res != errSecSuccess)
293 return ((kSecUnlockStateStatus & keychainStatus) == 0);
309 res = SecKeychainUnlock(m_impl->m_keyChainRef,
314 else if (m_impl->m_passwordSet)
317 SecKeychainUnlock(m_impl->m_keyChainRef,
318 m_impl->m_password.size(),
319 m_impl->m_password.c_str(),
322 #ifdef NDN_CXX_HAVE_GETPASS 323 else if (m_impl->m_inTerminal)
327 const char* fmt =
"Password to unlock the default keychain: ";
335 char* getPassword = 0;
336 getPassword = getpass(fmt);
342 res = SecKeychainUnlock(m_impl->m_keyChainRef,
347 memset(getPassword, 0, strlen(getPassword));
349 if (res == errSecSuccess)
353 #endif // NDN_CXX_HAVE_GETPASS 357 SecKeychainUnlock(m_impl->m_keyChainRef, 0, 0,
false);
371 BOOST_THROW_EXCEPTION(
Error(
"keyName already exists"));
377 CFStringCreateWithCString(0,
379 kCFStringEncodingUTF8);
382 CFDictionaryCreateMutable(0,
384 &kCFTypeDictionaryKeyCallBacks,
404 BOOST_THROW_EXCEPTION(
Error(
"Fail to create a key pair: Unsupported key type"));
409 CFDictionaryAddValue(attrDict.get(), kSecAttrKeyType, m_impl->getAsymKeyType(keyType));
410 CFDictionaryAddValue(attrDict.get(), kSecAttrKeySizeInBits, cfKeySize.
get());
411 CFDictionaryAddValue(attrDict.get(), kSecAttrLabel, keyLabel.
get());
415 OSStatus res = SecKeyGeneratePair((CFDictionaryRef)attrDict.get(),
416 &publicKey.get(), &privateKey.get());
418 if (res == errSecSuccess)
423 if (res == errSecAuthFailed && !needRetry)
428 BOOST_THROW_EXCEPTION(
Error(
"Fail to unlock the keychain"));
432 BOOST_THROW_EXCEPTION(
Error(
"Fail to create a key pair"));
440 CFStringCreateWithCString(0,
441 keyName.
toUri().c_str(),
442 kCFStringEncodingUTF8);
445 CFDictionaryCreateMutable(0, 5,
446 &kCFTypeDictionaryKeyCallBacks,
447 &kCFTypeDictionaryValueCallBacks);
449 CFDictionaryAddValue(searchDict.get(), kSecClass, kSecClassKey);
450 CFDictionaryAddValue(searchDict.get(), kSecAttrLabel, keyLabel.
get());
451 CFDictionaryAddValue(searchDict.get(), kSecMatchLimit, kSecMatchLimitAll);
452 OSStatus res = SecItemDelete(searchDict.get());
454 if (res == errSecSuccess)
457 if (res == errSecAuthFailed && !needRetry)
467 BOOST_THROW_EXCEPTION(
Error(
"SecTpmOsx::generateSymmetricKeyInTpm is not supported"));
499 shared_ptr<PublicKey>
503 if (publicKey.
get() == 0)
505 BOOST_THROW_EXCEPTION(
Error(
"Requested public key [" + keyName.
toUri() +
"] does not exist " 510 OSStatus res = SecItemExport(publicKey.
get(),
515 if (res != errSecSuccess)
517 BOOST_THROW_EXCEPTION(
Error(
"Cannot export requested public key from OSX Keychain"));
520 shared_ptr<PublicKey> key = make_shared<PublicKey>(CFDataGetBytePtr(exportedKey.
get()),
521 CFDataGetLength(exportedKey.
get()));
537 if (privateKey.
get() == 0)
540 BOOST_THROW_EXCEPTION(
Error(
"Private key [" + keyName.
toUri() +
"] does not exist " 547 OSStatus res = SecItemExport(privateKey.
get(),
553 if (res != errSecSuccess)
555 if (res == errSecAuthFailed && !needRetry)
560 return shared_ptr<Buffer>();
563 return shared_ptr<Buffer>();
566 uint32_t version = 0;
568 bool hasParameters =
false;
569 OID algorithmParameter;
570 switch (publicKey->getKeyType()) {
574 hasParameters =
false;
580 StringSource src(publicKey->get().buf(), publicKey->get().size(),
true);
581 BERSequenceDecoder subjectPublicKeyInfo(src);
583 BERSequenceDecoder algorithmInfo(subjectPublicKeyInfo);
585 algorithm.
decode(algorithmInfo);
586 algorithmParameter.
decode(algorithmInfo);
589 hasParameters =
true;
593 BOOST_THROW_EXCEPTION(
Error(
"Unsupported key type" +
594 boost::lexical_cast<std::string>(publicKey->getKeyType())));
598 FileSink sink(pkcs8Os);
600 SecByteBlock rawKeyBits;
605 DERSequenceEncoder privateKeyInfo(sink);
607 DEREncodeUnsigned<uint32_t>(privateKeyInfo, version, INTEGER);
608 DERSequenceEncoder privateKeyAlgorithm(privateKeyInfo);
610 algorithm.
encode(privateKeyAlgorithm);
612 algorithmParameter.
encode(privateKeyAlgorithm);
614 DEREncodeNull(privateKeyAlgorithm);
616 privateKeyAlgorithm.MessageEnd();
617 DEREncodeOctetString(privateKeyInfo,
618 CFDataGetBytePtr(exportedKey.
get()),
619 CFDataGetLength(exportedKey.
get()));
621 privateKeyInfo.MessageEnd();
623 return pkcs8Os.buf();
627 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) 628 #pragma GCC diagnostic push 629 #endif // __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) 630 #pragma GCC diagnostic ignored "-Wdeprecated-declarations" 635 const uint8_t* buf,
size_t size,
640 StringSource privateKeySource(buf, size,
true);
641 SecByteBlock rawKeyBits;
646 BERSequenceDecoder privateKeyInfo(privateKeySource);
649 BERDecodeUnsigned<uint32_t>(privateKeyInfo, versionNum, INTEGER);
650 BERSequenceDecoder sequenceDecoder(privateKeyInfo);
653 keyTypeOID.
decode(sequenceDecoder);
656 BERDecodeNull(sequenceDecoder);
660 parameterOID.
decode(sequenceDecoder);
667 BERDecodeOctetString(privateKeyInfo, rawKeyBits);
669 privateKeyInfo.MessageEnd();
672 rawKeyBits.BytePtr(),
676 SecExternalFormat externalFormat = kSecFormatOpenSSL;
677 SecExternalItemType externalType = kSecItemTypePrivateKey;
678 SecKeyImportExportParameters keyParams;
679 memset(&keyParams, 0,
sizeof(keyParams));
680 keyParams.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
681 keyParams.keyAttributes = CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_PERMANENT;
684 keyName.
toUri().c_str(),
685 kCFStringEncodingUTF8);
686 SecAccessCreate(keyLabel.
get(), 0, &access.
get());
687 keyParams.accessRef = access.
get();
691 #pragma clang diagnostic push 692 #pragma clang diagnostic ignored "-Wdeprecated-declarations" 695 OSStatus res = SecKeychainItemImport(importedKey.
get(),
701 m_impl->m_keyChainRef,
705 #pragma clang diagnostic pop 708 if (res != errSecSuccess)
710 if (res == errSecAuthFailed && !needRetry)
722 SecKeychainItemRef privateKey = (SecKeychainItemRef)CFArrayGetValueAtIndex(outItems.
get(), 0);
723 SecKeychainAttribute attrs[1];
724 SecKeychainAttributeList attrList = { 0, attrs };
725 string keyUri = keyName.
toUri();
727 attrs[attrList.count].tag = kSecKeyPrintName;
728 attrs[attrList.count].length = keyUri.size();
729 attrs[attrList.count].data =
const_cast<char*
>(keyUri.c_str());
733 res = SecKeychainItemModifyAttributesAndData(privateKey,
738 if (res != errSecSuccess)
746 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) 747 #pragma GCC diagnostic pop 748 #endif // __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) 758 SecExternalFormat externalFormat = kSecFormatOpenSSL;
759 SecExternalItemType externalType = kSecItemTypePublicKey;
762 OSStatus res = SecItemImport(importedKey.
get(),
768 m_impl->m_keyChainRef,
771 if (res != errSecSuccess)
775 SecKeychainItemRef publicKey = (SecKeychainItemRef)CFArrayGetValueAtIndex(outItems.
get(), 0);
776 SecKeychainAttribute attrs[1];
777 SecKeychainAttributeList attrList = { 0, attrs };
778 string keyUri = keyName.
toUri();
780 attrs[attrList.count].tag = kSecKeyPrintName;
781 attrs[attrList.count].length = keyUri.size();
782 attrs[attrList.count].data =
const_cast<char*
>(keyUri.c_str());
786 res = SecKeychainItemModifyAttributesAndData(publicKey,
791 if (res != errSecSuccess)
807 if (privateKey.
get() == 0)
809 BOOST_THROW_EXCEPTION(
Error(
"Private key [" + keyName.
toUri() +
"] does not exist " 817 if (error.
get() != 0)
818 BOOST_THROW_EXCEPTION(
Error(
"Fail to create signer"));
821 SecTransformSetAttribute(signer.
get(),
822 kSecTransformInputAttributeName,
825 if (error.
get() != 0)
826 BOOST_THROW_EXCEPTION(
Error(
"Fail to configure input of signer"));
829 SecTransformSetAttribute(signer.
get(),
833 if (error.
get() != 0)
834 BOOST_THROW_EXCEPTION(
Error(
"Fail to configure digest algorithm of signer"));
837 SecTransformSetAttribute(signer.
get(),
838 kSecDigestTypeAttribute,
839 m_impl->getDigestAlgorithm(digestAlgorithm),
841 if (error.
get() != 0)
842 BOOST_THROW_EXCEPTION(
Error(
"Fail to configure digest algorithm of signer"));
845 long digestSize = m_impl->getDigestSize(digestAlgorithm);
847 SecTransformSetAttribute(signer.
get(),
848 kSecDigestLengthAttribute,
851 if (error.
get() != 0)
852 BOOST_THROW_EXCEPTION(
Error(
"Fail to configure digest size of signer"));
857 if (error.
get() != 0)
864 BOOST_THROW_EXCEPTION(
Error(
"Fail to unlock the keychain"));
869 BOOST_THROW_EXCEPTION(
Error(
"Fail to sign data"));
873 if (signature.
get() == 0)
874 BOOST_THROW_EXCEPTION(
Error(
"Signature is NULL!\n"));
877 make_shared<Buffer>(CFDataGetBytePtr(signature.
get()),
878 CFDataGetLength(signature.
get())));
884 BOOST_THROW_EXCEPTION(
Error(
"SecTpmOsx::decryptInTpm is not supported"));
931 if (privateKey.
get() == 0)
933 BOOST_THROW_EXCEPTION(
Error(
"Private key [" + keyName.
toUri() +
"] does not exist " 938 SecKeychainItemCopyAccess(privateKey.
get(), &accRef.
get());
941 kSecACLAuthorizationSign);
944 SecACLRef aclRef = (SecACLRef)CFArrayGetValueAtIndex(signACL.get(), 0);
948 SecKeychainPromptSelector promptSelector;
949 SecACLCopyContents(aclRef,
959 SecTrustedApplicationCreateFromPath(appPath.c_str(),
962 CFArrayAppendValue(newAppList.get(), trustedApp.get());
964 SecACLSetContents(aclRef,
969 SecKeychainItemSetAccess(privateKey.
get(), accRef.
get());
976 BOOST_THROW_EXCEPTION(
Error(
"SecTpmOsx::encryptInTpm is not supported"));
1016 string keyNameUri = m_impl->toInternalKeyName(keyName, keyClass);
1020 kCFStringEncodingUTF8);
1023 CFDictionaryCreateMutable(0,
1025 &kCFTypeDictionaryKeyCallBacks,
1028 CFDictionaryAddValue(attrDict.get(), kSecClass, kSecClassKey);
1030 CFDictionaryAddValue(attrDict.get(), kSecAttrLabel, keyLabel.
get());
1031 CFDictionaryAddValue(attrDict.get(), kSecReturnRef, kCFBooleanTrue);
1035 OSStatus res = SecItemCopyMatching((CFDictionaryRef)attrDict.get(), (CFTypeRef*)&itemRef.get());
1037 if (res == errSecSuccess)
1047 return SecRandomCopyBytes(kSecRandomDefault, size, res) == 0;
1057 string keyNameUri = toInternalKeyName(keyName, keyClass);
1061 kCFStringEncodingUTF8);
1064 CFDictionaryCreateMutable(0,
1066 &kCFTypeDictionaryKeyCallBacks,
1069 CFDictionaryAddValue(attrDict.get(), kSecClass, kSecClassKey);
1070 CFDictionaryAddValue(attrDict.get(), kSecAttrLabel, keyLabel.
get());
1071 CFDictionaryAddValue(attrDict.get(), kSecAttrKeyClass, getKeyClass(keyClass));
1072 CFDictionaryAddValue(attrDict.get(), kSecReturnRef, kCFBooleanTrue);
1076 OSStatus res = SecItemCopyMatching((CFDictionaryRef)attrDict.get(), (CFTypeRef*)&keyItem.get());
1078 if (res != errSecSuccess)
1087 string keyUri = keyName.
toUri();
1090 return keyUri +
"/symmetric";
1100 return kSecAttrKeyTypeRSA;
1102 return kSecAttrKeyTypeECDSA;
1113 return kSecAttrKeyTypeAES;
1124 return kSecAttrKeyClassPrivate;
1126 return kSecAttrKeyClassPublic;
1128 return kSecAttrKeyClassSymmetric;
1137 switch (digestAlgo) {
1139 return kSecDigestSHA2;
1148 switch (digestAlgo) {
void deleteKeyPairInTpmInternal(const Name &keyName, bool needRetry)
Copyright (c) 2011-2015 Regents of the University of California.
static const std::string SCHEME
Helper class to wrap CoreFoundation object pointers.
std::string toUri() const
Encode this name as a URI.
Copyright (c) 2013-2014 Regents of the University of California.
virtual ConstBufferPtr encryptInTpm(const uint8_t *data, size_t dataLength, const Name &keyName, bool isSymmetric)
Encrypt data.
CFReleaser & operator=(const CFReleaser &inReleaser)
SecTpmOsx(const std::string &location="")
virtual bool importPublicKeyPkcs1IntoTpm(const Name &keyName, const uint8_t *buf, size_t size)
Import a public key in PKCS#1 formatted buffer of size bufferSize.
void encode(CryptoPP::BufferedTransformation &out) const
virtual bool getInTerminal() const
Get value of inTerminal flag.
CFTypeRef getSymKeyType(KeyType keyType)
Convert keyType to MAC OS symmetric key key type.
Class representing a wire element of NDN-TLV packet format.
ConstBufferPtr exportPrivateKeyPkcs8FromTpmInternal(const Name &keyName, bool needRetry)
CFReleaser(const T &typeRef)
CFReleaser & operator=(const T &typeRef)
virtual void setTpmPassword(const uint8_t *password, size_t passwordLength)
set password of TPM
virtual void resetTpmPassword()
reset password of TPM
void decode(CryptoPP::BufferedTransformation &in)
void retain(const T &typeRef)
CFReleaser< SecKeychainItemRef > getKey(const Name &keyName, KeyClass keyClass)
Get key.
virtual void generateSymmetricKeyInTpm(const Name &keyName, const KeyParams ¶ms)
Generate a symmetric key.
CFStringRef getDigestAlgorithm(DigestAlgorithm digestAlgo)
Convert digestAlgo to MAC OS algorithm id.
virtual shared_ptr< PublicKey > getPublicKeyFromTpm(const Name &keyName)
Get a public key.
SecTpm is the base class of the TPM classes.
CFTypeRef getKeyClass(KeyClass keyClass)
Convert keyClass to MAC OS key class.
bool importPrivateKeyPkcs8IntoTpmInternal(const Name &keyName, const uint8_t *buf, size_t size, bool needRetry)
virtual void addAppToAcl(const Name &keyName, KeyClass keyClass, const std::string &appPath, AclType acl)
Add the application into the ACL of a particular key.
Name abstraction to represent an absolute name.
KeyType getKeyType() const
virtual ConstBufferPtr decryptInTpm(const uint8_t *data, size_t dataLength, const Name &keyName, bool isSymmetric)
Decrypt data.
void generateKeyPairInTpmInternal(const Name &keyName, const KeyParams ¶ms, bool needRetry)
std::string toInternalKeyName(const Name &keyName, KeyClass keyClass)
Convert NDN name of a key to internal name of the key.
CFReleaser(const CFReleaser &inReleaser)
virtual bool doesKeyExistInTpm(const Name &keyName, KeyClass keyClass)
Check if a particular key exists.
Base class of key parameters.
uint32_t getKeySize() const
virtual void setInTerminal(bool inTerminal)
Set inTerminal flag to inTerminal.
long getDigestSize(DigestAlgorithm digestAlgo)
Get the digest size of the corresponding algorithm.
Class implementing interface similar to ostringstream, but to construct ndn::Buffer.
shared_ptr< const Buffer > ConstBufferPtr
const OID ECDSA("1.2.840.10045.2.1")
SimplePublicKeyParams is a template for public keys with only one parameter: size.
Block signInTpmInternal(const uint8_t *data, size_t dataLength, const Name &keyName, DigestAlgorithm digestAlgorithm, bool needRetry)
SecKeychainRef m_keyChainRef
virtual std::string getScheme()
const OID RSA("1.2.840.113549.1.1.1")
virtual bool generateRandomBlock(uint8_t *res, size_t size)
Generate a random block.
virtual bool unlockTpm(const char *password, size_t passwordLength, bool usePassword)
Unlock the TPM.
virtual bool isLocked()
Check if TPM is locked.
CFTypeRef getAsymKeyType(KeyType keyType)
Convert keyType to MAC OS asymmetirc key type.