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)
173 toInternalKeyName(
const Name& keyName,
KeyClass keyClass);
192 getSymKeyType(
KeyType keyType);
201 getAsymKeyType(
KeyType keyType);
245 if (m_impl->m_inTerminal)
246 SecKeychainSetUserInteractionAllowed(
false);
248 SecKeychainSetUserInteractionAllowed(
true);
250 OSStatus res = SecKeychainCopyDefault(&m_impl->m_keyChainRef);
252 if (res == errSecNoDefaultKeychain)
253 BOOST_THROW_EXCEPTION(
Error(
"No default keychain, please create one first"));
263 m_impl->m_passwordSet =
true;
264 std::fill(m_impl->m_password.begin(), m_impl->m_password.end(), 0);
265 m_impl->m_password.clear();
266 m_impl->m_password.append(reinterpret_cast<const char*>(password), passwordLength);
272 m_impl->m_passwordSet =
false;
273 std::fill(m_impl->m_password.begin(), m_impl->m_password.end(), 0);
274 m_impl->m_password.clear();
280 m_impl->m_inTerminal = inTerminal;
282 SecKeychainSetUserInteractionAllowed(
false);
284 SecKeychainSetUserInteractionAllowed(
true);
290 return m_impl->m_inTerminal;
296 SecKeychainStatus keychainStatus;
298 OSStatus res = SecKeychainGetStatus(m_impl->m_keyChainRef, &keychainStatus);
299 if (res != errSecSuccess)
302 return ((kSecUnlockStateStatus & keychainStatus) == 0);
318 res = SecKeychainUnlock(m_impl->m_keyChainRef,
323 else if (m_impl->m_passwordSet)
326 SecKeychainUnlock(m_impl->m_keyChainRef,
327 m_impl->m_password.size(),
328 m_impl->m_password.c_str(),
331 #ifdef NDN_CXX_HAVE_GETPASS 332 else if (m_impl->m_inTerminal)
336 const char* fmt =
"Password to unlock the default keychain: ";
344 char* getPassword = 0;
345 getPassword = getpass(fmt);
351 res = SecKeychainUnlock(m_impl->m_keyChainRef,
356 memset(getPassword, 0, strlen(getPassword));
358 if (res == errSecSuccess)
362 #endif // NDN_CXX_HAVE_GETPASS 366 SecKeychainUnlock(m_impl->m_keyChainRef, 0, 0,
false);
380 BOOST_THROW_EXCEPTION(
Error(
"keyName already exists"));
386 CFStringCreateWithCString(0,
388 kCFStringEncodingUTF8);
391 CFDictionaryCreateMutable(0,
393 &kCFTypeDictionaryKeyCallBacks,
413 BOOST_THROW_EXCEPTION(
Error(
"Fail to create a key pair: Unsupported key type"));
418 CFDictionaryAddValue(attrDict.get(), kSecAttrKeyType, m_impl->getAsymKeyType(keyType));
419 CFDictionaryAddValue(attrDict.get(), kSecAttrKeySizeInBits, cfKeySize.
get());
420 CFDictionaryAddValue(attrDict.get(), kSecAttrLabel, keyLabel.
get());
424 OSStatus res = SecKeyGeneratePair((CFDictionaryRef)attrDict.get(),
425 &publicKey.get(), &privateKey.get());
427 if (res == errSecSuccess)
432 if (res == errSecAuthFailed && !needRetry)
437 BOOST_THROW_EXCEPTION(
Error(
"Fail to unlock the keychain"));
441 BOOST_THROW_EXCEPTION(
Error(
"Fail to create a key pair"));
449 CFStringCreateWithCString(0,
450 keyName.
toUri().c_str(),
451 kCFStringEncodingUTF8);
454 CFDictionaryCreateMutable(0, 5,
455 &kCFTypeDictionaryKeyCallBacks,
456 &kCFTypeDictionaryValueCallBacks);
458 CFDictionaryAddValue(searchDict.get(), kSecClass, kSecClassKey);
459 CFDictionaryAddValue(searchDict.get(), kSecAttrLabel, keyLabel.
get());
460 CFDictionaryAddValue(searchDict.get(), kSecMatchLimit, kSecMatchLimitAll);
461 OSStatus res = SecItemDelete(searchDict.get());
463 if (res == errSecSuccess)
466 if (res == errSecAuthFailed && !needRetry)
476 BOOST_THROW_EXCEPTION(
Error(
"SecTpmOsx::generateSymmetricKeyInTpm is not supported"));
508 shared_ptr<PublicKey>
512 if (publicKey.
get() == 0)
514 BOOST_THROW_EXCEPTION(
Error(
"Requested public key [" + keyName.
toUri() +
"] does not exist " 519 OSStatus res = SecItemExport(publicKey.
get(),
524 if (res != errSecSuccess)
526 BOOST_THROW_EXCEPTION(
Error(
"Cannot export requested public key from OSX Keychain"));
529 shared_ptr<PublicKey> key = make_shared<PublicKey>(CFDataGetBytePtr(exportedKey.
get()),
530 CFDataGetLength(exportedKey.
get()));
546 if (privateKey.
get() == 0)
549 BOOST_THROW_EXCEPTION(
Error(
"Private key [" + keyName.
toUri() +
"] does not exist " 556 OSStatus res = SecItemExport(privateKey.
get(),
562 if (res != errSecSuccess)
564 if (res == errSecAuthFailed && !needRetry)
569 return shared_ptr<Buffer>();
572 return shared_ptr<Buffer>();
575 uint32_t version = 0;
577 bool hasParameters =
false;
578 OID algorithmParameter;
579 switch (publicKey->getKeyType()) {
583 hasParameters =
false;
589 StringSource src(publicKey->get().buf(), publicKey->get().size(),
true);
590 BERSequenceDecoder subjectPublicKeyInfo(src);
592 BERSequenceDecoder algorithmInfo(subjectPublicKeyInfo);
594 algorithm.
decode(algorithmInfo);
595 algorithmParameter.
decode(algorithmInfo);
598 hasParameters =
true;
602 BOOST_THROW_EXCEPTION(
Error(
"Unsupported key type" +
603 boost::lexical_cast<std::string>(publicKey->getKeyType())));
607 FileSink sink(pkcs8Os);
609 SecByteBlock rawKeyBits;
614 DERSequenceEncoder privateKeyInfo(sink);
616 DEREncodeUnsigned<uint32_t>(privateKeyInfo, version, INTEGER);
617 DERSequenceEncoder privateKeyAlgorithm(privateKeyInfo);
619 algorithm.
encode(privateKeyAlgorithm);
621 algorithmParameter.
encode(privateKeyAlgorithm);
623 DEREncodeNull(privateKeyAlgorithm);
625 privateKeyAlgorithm.MessageEnd();
626 DEREncodeOctetString(privateKeyInfo,
627 CFDataGetBytePtr(exportedKey.
get()),
628 CFDataGetLength(exportedKey.
get()));
630 privateKeyInfo.MessageEnd();
632 return pkcs8Os.buf();
636 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) 637 #pragma GCC diagnostic push 638 #endif // __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) 639 #pragma GCC diagnostic ignored "-Wdeprecated-declarations" 644 const uint8_t* buf,
size_t size,
649 StringSource privateKeySource(buf, size,
true);
650 SecByteBlock rawKeyBits;
655 BERSequenceDecoder privateKeyInfo(privateKeySource);
658 BERDecodeUnsigned<uint32_t>(privateKeyInfo, versionNum, INTEGER);
659 BERSequenceDecoder sequenceDecoder(privateKeyInfo);
662 keyTypeOID.
decode(sequenceDecoder);
665 BERDecodeNull(sequenceDecoder);
669 parameterOID.
decode(sequenceDecoder);
676 BERDecodeOctetString(privateKeyInfo, rawKeyBits);
678 privateKeyInfo.MessageEnd();
681 rawKeyBits.BytePtr(),
685 SecExternalFormat externalFormat = kSecFormatOpenSSL;
686 SecExternalItemType externalType = kSecItemTypePrivateKey;
687 SecKeyImportExportParameters keyParams;
688 memset(&keyParams, 0,
sizeof(keyParams));
689 keyParams.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
690 keyParams.keyAttributes = CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_PERMANENT;
693 keyName.
toUri().c_str(),
694 kCFStringEncodingUTF8);
695 SecAccessCreate(keyLabel.
get(), 0, &access.
get());
696 keyParams.accessRef = access.
get();
700 #pragma clang diagnostic push 701 #pragma clang diagnostic ignored "-Wdeprecated-declarations" 704 OSStatus res = SecKeychainItemImport(importedKey.
get(),
710 m_impl->m_keyChainRef,
714 #pragma clang diagnostic pop 717 if (res != errSecSuccess)
719 if (res == errSecAuthFailed && !needRetry)
731 SecKeychainItemRef privateKey = (SecKeychainItemRef)CFArrayGetValueAtIndex(outItems.
get(), 0);
732 SecKeychainAttribute attrs[1];
733 SecKeychainAttributeList attrList = { 0, attrs };
734 string keyUri = keyName.
toUri();
736 attrs[attrList.count].tag = kSecKeyPrintName;
737 attrs[attrList.count].length = keyUri.size();
738 attrs[attrList.count].data =
const_cast<char*
>(keyUri.c_str());
742 res = SecKeychainItemModifyAttributesAndData(privateKey,
747 if (res != errSecSuccess)
755 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) 756 #pragma GCC diagnostic pop 757 #endif // __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) 767 SecExternalFormat externalFormat = kSecFormatOpenSSL;
768 SecExternalItemType externalType = kSecItemTypePublicKey;
771 OSStatus res = SecItemImport(importedKey.
get(),
777 m_impl->m_keyChainRef,
780 if (res != errSecSuccess)
784 SecKeychainItemRef publicKey = (SecKeychainItemRef)CFArrayGetValueAtIndex(outItems.
get(), 0);
785 SecKeychainAttribute attrs[1];
786 SecKeychainAttributeList attrList = { 0, attrs };
787 string keyUri = keyName.
toUri();
789 attrs[attrList.count].tag = kSecKeyPrintName;
790 attrs[attrList.count].length = keyUri.size();
791 attrs[attrList.count].data =
const_cast<char*
>(keyUri.c_str());
795 res = SecKeychainItemModifyAttributesAndData(publicKey,
800 if (res != errSecSuccess)
816 if (privateKey.
get() == 0)
818 BOOST_THROW_EXCEPTION(
Error(
"Private key [" + keyName.
toUri() +
"] does not exist " 826 if (error.
get() != 0)
827 BOOST_THROW_EXCEPTION(
Error(
"Fail to create signer"));
830 SecTransformSetAttribute(signer.
get(),
831 kSecTransformInputAttributeName,
834 if (error.
get() != 0)
835 BOOST_THROW_EXCEPTION(
Error(
"Fail to configure input of signer"));
838 SecTransformSetAttribute(signer.
get(),
842 if (error.
get() != 0)
843 BOOST_THROW_EXCEPTION(
Error(
"Fail to configure digest algorithm of signer"));
846 SecTransformSetAttribute(signer.
get(),
847 kSecDigestTypeAttribute,
848 m_impl->getDigestAlgorithm(digestAlgorithm),
850 if (error.
get() != 0)
851 BOOST_THROW_EXCEPTION(
Error(
"Fail to configure digest algorithm of signer"));
854 long digestSize = m_impl->getDigestSize(digestAlgorithm);
856 SecTransformSetAttribute(signer.
get(),
857 kSecDigestLengthAttribute,
860 if (error.
get() != 0)
861 BOOST_THROW_EXCEPTION(
Error(
"Fail to configure digest size of signer"));
866 if (error.
get() != 0)
873 BOOST_THROW_EXCEPTION(
Error(
"Fail to unlock the keychain"));
878 BOOST_THROW_EXCEPTION(
Error(
"Fail to sign data"));
882 if (signature.
get() == 0)
883 BOOST_THROW_EXCEPTION(
Error(
"Signature is NULL!\n"));
886 make_shared<Buffer>(CFDataGetBytePtr(signature.
get()),
887 CFDataGetLength(signature.
get())));
893 BOOST_THROW_EXCEPTION(
Error(
"SecTpmOsx::decryptInTpm is not supported"));
940 if (privateKey.
get() == 0)
942 BOOST_THROW_EXCEPTION(
Error(
"Private key [" + keyName.
toUri() +
"] does not exist " 947 SecKeychainItemCopyAccess(privateKey.
get(), &accRef.
get());
950 kSecACLAuthorizationSign);
953 SecACLRef aclRef = (SecACLRef)CFArrayGetValueAtIndex(signACL.get(), 0);
957 SecKeychainPromptSelector promptSelector;
958 SecACLCopyContents(aclRef,
968 SecTrustedApplicationCreateFromPath(appPath.c_str(),
971 CFArrayAppendValue(newAppList.get(), trustedApp.get());
973 SecACLSetContents(aclRef,
978 SecKeychainItemSetAccess(privateKey.
get(), accRef.
get());
985 BOOST_THROW_EXCEPTION(
Error(
"SecTpmOsx::encryptInTpm is not supported"));
1025 string keyNameUri = m_impl->toInternalKeyName(keyName, keyClass);
1029 kCFStringEncodingUTF8);
1032 CFDictionaryCreateMutable(0,
1034 &kCFTypeDictionaryKeyCallBacks,
1037 CFDictionaryAddValue(attrDict.get(), kSecClass, kSecClassKey);
1039 CFDictionaryAddValue(attrDict.get(), kSecAttrLabel, keyLabel.
get());
1040 CFDictionaryAddValue(attrDict.get(), kSecReturnRef, kCFBooleanTrue);
1044 OSStatus res = SecItemCopyMatching((CFDictionaryRef)attrDict.get(), (CFTypeRef*)&itemRef.get());
1046 if (res == errSecSuccess)
1056 return SecRandomCopyBytes(kSecRandomDefault, size, res) == 0;
1066 string keyNameUri = toInternalKeyName(keyName, keyClass);
1070 kCFStringEncodingUTF8);
1073 CFDictionaryCreateMutable(0,
1075 &kCFTypeDictionaryKeyCallBacks,
1078 CFDictionaryAddValue(attrDict.get(), kSecClass, kSecClassKey);
1079 CFDictionaryAddValue(attrDict.get(), kSecAttrLabel, keyLabel.
get());
1080 CFDictionaryAddValue(attrDict.get(), kSecAttrKeyClass, getKeyClass(keyClass));
1081 CFDictionaryAddValue(attrDict.get(), kSecReturnRef, kCFBooleanTrue);
1085 OSStatus res = SecItemCopyMatching((CFDictionaryRef)attrDict.get(), (CFTypeRef*)&keyItem.get());
1087 if (res != errSecSuccess)
1096 string keyUri = keyName.
toUri();
1099 return keyUri +
"/symmetric";
1109 return kSecAttrKeyTypeRSA;
1111 return kSecAttrKeyTypeECDSA;
1122 return kSecAttrKeyTypeAES;
1133 return kSecAttrKeyClassPrivate;
1135 return kSecAttrKeyClassPublic;
1137 return kSecAttrKeyClassSymmetric;
1146 switch (digestAlgo) {
1148 return kSecDigestSHA2;
1157 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.
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.
KeyType getKeyType() const
CFReleaser & operator=(const CFReleaser &inReleaser)
uint32_t getKeySize() const
virtual bool getInTerminal() const
Get value of inTerminal flag.
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.
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
std::string toUri() const
Encode this name as a URI.
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.
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.
virtual void setInTerminal(bool inTerminal)
Set inTerminal flag to.
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
void encode(CryptoPP::BufferedTransformation &out) const
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.