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>
82 retain(inReleaser.m_typeRef);
88 if (typeRef != m_typeRef) {
98 retain(inReleaser.m_typeRef);
138 if (typeRef !=
nullptr) {
148 if (m_typeRef !=
nullptr) {
149 CFRelease(m_typeRef);
157 return get() ==
nullptr;
163 return get() !=
nullptr;
251 if (m_impl->m_inTerminal)
252 SecKeychainSetUserInteractionAllowed(
false);
254 SecKeychainSetUserInteractionAllowed(
true);
256 OSStatus res = SecKeychainCopyDefault(&m_impl->m_keyChainRef);
258 if (res == errSecNoDefaultKeychain)
259 BOOST_THROW_EXCEPTION(
Error(
"No default keychain, please create one first"));
269 m_impl->m_passwordSet =
true;
270 std::fill(m_impl->m_password.begin(), m_impl->m_password.end(), 0);
271 m_impl->m_password.clear();
272 m_impl->m_password.append(reinterpret_cast<const char*>(password), passwordLength);
278 m_impl->m_passwordSet =
false;
279 std::fill(m_impl->m_password.begin(), m_impl->m_password.end(), 0);
280 m_impl->m_password.clear();
286 m_impl->m_inTerminal = inTerminal;
288 SecKeychainSetUserInteractionAllowed(
false);
290 SecKeychainSetUserInteractionAllowed(
true);
296 return m_impl->m_inTerminal;
302 SecKeychainStatus keychainStatus;
304 OSStatus res = SecKeychainGetStatus(m_impl->m_keyChainRef, &keychainStatus);
305 if (res != errSecSuccess)
308 return ((kSecUnlockStateStatus & keychainStatus) == 0);
323 res = SecKeychainUnlock(m_impl->m_keyChainRef,
328 else if (m_impl->m_passwordSet) {
330 SecKeychainUnlock(m_impl->m_keyChainRef,
331 m_impl->m_password.size(),
332 m_impl->m_password.c_str(),
335 #ifdef NDN_CXX_HAVE_GETPASS
336 else if (m_impl->m_inTerminal) {
339 const char* fmt =
"Password to unlock the default keychain: ";
346 char* getPassword =
nullptr;
347 getPassword = getpass(fmt);
353 res = SecKeychainUnlock(m_impl->m_keyChainRef,
358 memset(getPassword, 0, strlen(getPassword));
360 if (res == errSecSuccess)
364 #endif // NDN_CXX_HAVE_GETPASS
367 SecKeychainUnlock(m_impl->m_keyChainRef, 0,
nullptr,
false);
380 BOOST_THROW_EXCEPTION(
Error(
"keyName already exists"));
386 CFStringCreateWithCString(0,
388 kCFStringEncodingUTF8);
391 CFDictionaryCreateMutable(0,
393 &kCFTypeDictionaryKeyCallBacks,
397 uint32_t keySize = 0;
412 BOOST_THROW_EXCEPTION(
Error(
"Fail to create a key pair: Unsupported key type"));
417 CFDictionaryAddValue(attrDict.get(), kSecAttrKeyType, m_impl->getAsymKeyType(keyType));
418 CFDictionaryAddValue(attrDict.get(), kSecAttrKeySizeInBits, cfKeySize.
get());
419 CFDictionaryAddValue(attrDict.get(), kSecAttrLabel, keyLabel.
get());
423 OSStatus res = SecKeyGeneratePair((CFDictionaryRef)attrDict.get(),
424 &publicKey.get(), &privateKey.get());
426 if (res == errSecSuccess) {
430 if (res == errSecAuthFailed && !needRetry) {
434 BOOST_THROW_EXCEPTION(
Error(
"Fail to unlock the keychain"));
437 BOOST_THROW_EXCEPTION(
Error(
"Fail to create a key pair"));
445 CFStringCreateWithCString(0,
446 keyName.
toUri().c_str(),
447 kCFStringEncodingUTF8);
450 CFDictionaryCreateMutable(0, 5,
451 &kCFTypeDictionaryKeyCallBacks,
452 &kCFTypeDictionaryValueCallBacks);
454 CFDictionaryAddValue(searchDict.get(), kSecClass, kSecClassKey);
455 CFDictionaryAddValue(searchDict.get(), kSecAttrLabel, keyLabel.
get());
456 CFDictionaryAddValue(searchDict.get(), kSecMatchLimit, kSecMatchLimitAll);
457 OSStatus res = SecItemDelete(searchDict.get());
459 if (res == errSecSuccess)
462 if (res == errSecAuthFailed && !needRetry) {
471 BOOST_THROW_EXCEPTION(
Error(
"SecTpmOsx::generateSymmetricKeyInTpm is not supported"));
503 shared_ptr<PublicKey>
507 if (publicKey ==
nullptr) {
508 BOOST_THROW_EXCEPTION(
Error(
"Requested public key [" + keyName.
toUri() +
"] does not exist "
513 OSStatus res = SecItemExport(publicKey.
get(),
518 if (res != errSecSuccess) {
519 BOOST_THROW_EXCEPTION(
Error(
"Cannot export requested public key from OSX Keychain"));
522 shared_ptr<PublicKey> key = make_shared<PublicKey>(CFDataGetBytePtr(exportedKey.
get()),
523 CFDataGetLength(exportedKey.
get()));
539 if (privateKey ==
nullptr) {
541 BOOST_THROW_EXCEPTION(
Error(
"Private key [" + keyName.
toUri() +
"] does not exist "
548 OSStatus res = SecItemExport(privateKey.
get(),
554 if (res != errSecSuccess) {
555 if (res == errSecAuthFailed && !needRetry) {
565 uint32_t version = 0;
567 bool hasParameters =
false;
568 Oid algorithmParameter;
569 switch (publicKey->getKeyType()) {
572 hasParameters =
false;
578 StringSource src(publicKey->get().buf(), publicKey->get().size(),
true);
579 BERSequenceDecoder subjectPublicKeyInfo(src);
581 BERSequenceDecoder algorithmInfo(subjectPublicKeyInfo);
583 algorithm.
decode(algorithmInfo);
584 algorithmParameter.
decode(algorithmInfo);
587 hasParameters =
true;
592 BOOST_THROW_EXCEPTION(
Error(
"Unsupported key type" +
593 boost::lexical_cast<std::string>(publicKey->getKeyType())));
597 FileSink sink(pkcs8Os);
599 SecByteBlock rawKeyBits;
604 DERSequenceEncoder privateKeyInfo(sink);
606 DEREncodeUnsigned<uint32_t>(privateKeyInfo, version, INTEGER);
607 DERSequenceEncoder privateKeyAlgorithm(privateKeyInfo);
609 algorithm.
encode(privateKeyAlgorithm);
611 algorithmParameter.
encode(privateKeyAlgorithm);
613 DEREncodeNull(privateKeyAlgorithm);
615 privateKeyAlgorithm.MessageEnd();
616 DEREncodeOctetString(privateKeyInfo,
617 CFDataGetBytePtr(exportedKey.
get()),
618 CFDataGetLength(exportedKey.
get()));
620 privateKeyInfo.MessageEnd();
622 return pkcs8Os.
buf();
626 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
627 #pragma GCC diagnostic push
628 #endif // __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
629 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
634 const uint8_t* buf,
size_t size,
639 StringSource privateKeySource(buf, size,
true);
640 SecByteBlock rawKeyBits;
645 BERSequenceDecoder privateKeyInfo(privateKeySource);
648 BERDecodeUnsigned<uint32_t>(privateKeyInfo, versionNum, INTEGER);
649 BERSequenceDecoder sequenceDecoder(privateKeyInfo);
652 keyTypeOid.
decode(sequenceDecoder);
655 BERDecodeNull(sequenceDecoder);
658 parameterOid.
decode(sequenceDecoder);
663 BERDecodeOctetString(privateKeyInfo, rawKeyBits);
665 privateKeyInfo.MessageEnd();
668 rawKeyBits.BytePtr(),
672 SecExternalFormat externalFormat = kSecFormatOpenSSL;
673 SecExternalItemType externalType = kSecItemTypePrivateKey;
674 SecKeyImportExportParameters keyParams;
675 memset(&keyParams, 0,
sizeof(keyParams));
676 keyParams.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
677 keyParams.keyAttributes = CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_PERMANENT;
680 keyName.
toUri().c_str(),
681 kCFStringEncodingUTF8);
682 SecAccessCreate(keyLabel.
get(), 0, &access.
get());
683 keyParams.accessRef = access.
get();
687 #pragma clang diagnostic push
688 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
691 OSStatus res = SecKeychainItemImport(importedKey.
get(),
697 m_impl->m_keyChainRef,
701 #pragma clang diagnostic pop
704 if (res != errSecSuccess) {
705 if (res == errSecAuthFailed && !needRetry) {
716 SecKeychainItemRef privateKey = (SecKeychainItemRef)CFArrayGetValueAtIndex(outItems.
get(), 0);
717 SecKeychainAttribute attrs[1];
718 SecKeychainAttributeList attrList = {0, attrs};
719 string keyUri = keyName.
toUri();
721 attrs[attrList.count].tag = kSecKeyPrintName;
722 attrs[attrList.count].length = keyUri.size();
723 attrs[attrList.count].data =
const_cast<char*
>(keyUri.c_str());
727 res = SecKeychainItemModifyAttributesAndData(privateKey,
732 if (res != errSecSuccess) {
739 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
740 #pragma GCC diagnostic pop
741 #endif // __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
751 SecExternalFormat externalFormat = kSecFormatOpenSSL;
752 SecExternalItemType externalType = kSecItemTypePublicKey;
755 OSStatus res = SecItemImport(importedKey.
get(),
761 m_impl->m_keyChainRef,
764 if (res != errSecSuccess)
768 SecKeychainItemRef publicKey = (SecKeychainItemRef)CFArrayGetValueAtIndex(outItems.
get(), 0);
769 SecKeychainAttribute attrs[1];
770 SecKeychainAttributeList attrList = { 0, attrs };
771 string keyUri = keyName.
toUri();
773 attrs[attrList.count].tag = kSecKeyPrintName;
774 attrs[attrList.count].length = keyUri.size();
775 attrs[attrList.count].data =
const_cast<char*
>(keyUri.c_str());
779 res = SecKeychainItemModifyAttributesAndData(publicKey,
784 if (res != errSecSuccess)
800 if (privateKey ==
nullptr) {
801 BOOST_THROW_EXCEPTION(
Error(
"Private key [" + keyName.
toUri() +
"] does not exist "
809 if (error !=
nullptr)
810 BOOST_THROW_EXCEPTION(
Error(
"Fail to create signer"));
813 SecTransformSetAttribute(signer.
get(),
814 kSecTransformInputAttributeName,
817 if (error !=
nullptr)
818 BOOST_THROW_EXCEPTION(
Error(
"Fail to configure input of signer"));
821 SecTransformSetAttribute(signer.
get(),
825 if (error !=
nullptr)
826 BOOST_THROW_EXCEPTION(
Error(
"Fail to configure digest algorithm of signer"));
829 SecTransformSetAttribute(signer.
get(),
830 kSecDigestTypeAttribute,
831 m_impl->getDigestAlgorithm(digestAlgorithm),
833 if (error !=
nullptr)
834 BOOST_THROW_EXCEPTION(
Error(
"Fail to configure digest algorithm of signer"));
837 long digestSize = m_impl->getDigestSize(digestAlgorithm);
839 SecTransformSetAttribute(signer.
get(),
840 kSecDigestLengthAttribute,
843 if (error !=
nullptr)
844 BOOST_THROW_EXCEPTION(
Error(
"Fail to configure digest size of signer"));
849 if (error !=
nullptr) {
854 BOOST_THROW_EXCEPTION(
Error(
"Fail to unlock the keychain"));
858 BOOST_THROW_EXCEPTION(
Error(
"Fail to sign data"));
862 if (signature ==
nullptr)
863 BOOST_THROW_EXCEPTION(
Error(
"Signature is NULL!\n"));
866 make_shared<Buffer>(CFDataGetBytePtr(signature.
get()),
867 CFDataGetLength(signature.
get())));
873 BOOST_THROW_EXCEPTION(
Error(
"SecTpmOsx::decryptInTpm is not supported"));
919 if (privateKey ==
nullptr) {
920 BOOST_THROW_EXCEPTION(
Error(
"Private key [" + keyName.
toUri() +
"] does not exist "
925 SecKeychainItemCopyAccess(privateKey.
get(), &accRef.
get());
928 kSecACLAuthorizationSign);
931 SecACLRef aclRef = (SecACLRef)CFArrayGetValueAtIndex(signACL.get(), 0);
935 SecKeychainPromptSelector promptSelector;
936 SecACLCopyContents(aclRef,
946 SecTrustedApplicationCreateFromPath(appPath.c_str(),
949 CFArrayAppendValue(newAppList.get(), trustedApp.get());
951 SecACLSetContents(aclRef,
956 SecKeychainItemSetAccess(privateKey.
get(), accRef.
get());
963 BOOST_THROW_EXCEPTION(
Error(
"SecTpmOsx::encryptInTpm is not supported"));
1003 string keyNameUri = m_impl->toInternalKeyName(keyName, keyClass);
1007 kCFStringEncodingUTF8);
1010 CFDictionaryCreateMutable(0,
1012 &kCFTypeDictionaryKeyCallBacks,
1015 CFDictionaryAddValue(attrDict.get(), kSecClass, kSecClassKey);
1017 CFDictionaryAddValue(attrDict.get(), kSecAttrLabel, keyLabel.
get());
1018 CFDictionaryAddValue(attrDict.get(), kSecReturnRef, kCFBooleanTrue);
1022 OSStatus res = SecItemCopyMatching((CFDictionaryRef)attrDict.get(), (CFTypeRef*)&itemRef.get());
1024 if (res == errSecSuccess)
1034 return SecRandomCopyBytes(kSecRandomDefault, size, res) == 0;
1044 string keyNameUri = toInternalKeyName(keyName, keyClass);
1048 kCFStringEncodingUTF8);
1051 CFDictionaryCreateMutable(0,
1053 &kCFTypeDictionaryKeyCallBacks,
1056 CFDictionaryAddValue(attrDict.get(), kSecClass, kSecClassKey);
1057 CFDictionaryAddValue(attrDict.get(), kSecAttrLabel, keyLabel.
get());
1058 CFDictionaryAddValue(attrDict.get(), kSecAttrKeyClass, getKeyClass(keyClass));
1059 CFDictionaryAddValue(attrDict.get(), kSecReturnRef, kCFBooleanTrue);
1063 OSStatus res = SecItemCopyMatching((CFDictionaryRef)attrDict.get(), (CFTypeRef*)&keyItem.get());
1065 if (res != errSecSuccess)
1074 string keyUri = keyName.
toUri();
1077 return keyUri +
"/symmetric";
1087 return kSecAttrKeyTypeRSA;
1089 return kSecAttrKeyTypeECDSA;
1100 return kSecAttrKeyTypeAES;
1111 return kSecAttrKeyClassPrivate;
1113 return kSecAttrKeyClassPublic;
1115 return kSecAttrKeyClassSymmetric;
1124 switch (digestAlgo) {
1126 return kSecDigestSHA2;
1135 switch (digestAlgo) {
bool importPrivateKeyPkcs8IntoTpmInternal(const Name &keyName, const uint8_t *buf, size_t size, bool needRetry)
void decode(CryptoPP::BufferedTransformation &in)
virtual std::string getScheme()
CFTypeRef getAsymKeyType(KeyType keyType)
Convert keyType to MAC OS asymmetirc key type.
virtual bool doesKeyExistInTpm(const Name &keyName, KeyClass keyClass)
Check if a particular key exists.
virtual void setTpmPassword(const uint8_t *password, size_t passwordLength)
set password of TPM
const Oid ECDSA("1.2.840.10045.2.1")
Copyright (c) 2013-2016 Regents of the University of California.
bool operator!=(std::nullptr_t)
Copyright (c) 2013-2016 Regents of the University of California.
std::string toInternalKeyName(const Name &keyName, KeyClass keyClass)
Convert NDN name of a key to internal name of the key.
KeyType getKeyType() const
uint32_t getKeySize() const
void encode(CryptoPP::BufferedTransformation &out) const
virtual void generateSymmetricKeyInTpm(const Name &keyName, const KeyParams ¶ms)
Generate a symmetric key.
Class representing a wire element of NDN-TLV packet format.
ConstBufferPtr exportPrivateKeyPkcs8FromTpmInternal(const Name &keyName, bool needRetry)
CFReleaser & operator=(const T &typeRef)
virtual void addAppToAcl(const Name &keyName, KeyClass keyClass, const std::string &appPath, AclType acl)
Add the application into the ACL of a particular key.
void retain(const T &typeRef)
std::string toUri() const
Encode this name as a URI.
virtual void resetTpmPassword()
reset password of TPM
CFReleaser & operator=(const CFReleaser &inReleaser)
long getDigestSize(DigestAlgorithm digestAlgo)
Get the digest size of the corresponding algorithm.
CFReleaser< SecKeychainItemRef > getKey(const Name &keyName, KeyClass keyClass)
Get key.
const Oid RSA("1.2.840.113549.1.1.1")
SecTpmOsx(const std::string &location="")
Helper class to wrap CoreFoundation object pointers.
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.
virtual bool getInTerminal() const
Get value of inTerminal flag.
virtual ConstBufferPtr decryptInTpm(const uint8_t *data, size_t dataLength, const Name &keyName, bool isSymmetric)
Decrypt data.
Use the SHA256 hash of the public key as the key id.
Name abstraction to represent an absolute name.
CFTypeRef getSymKeyType(KeyType keyType)
Convert keyType to MAC OS symmetric key key type.
virtual bool generateRandomBlock(uint8_t *res, size_t size)
Generate a random block.
void generateKeyPairInTpmInternal(const Name &keyName, const KeyParams ¶ms, bool needRetry)
virtual bool unlockTpm(const char *password, size_t passwordLength, bool usePassword)
Unlock the TPM.
CFReleaser(const T &typeRef)
virtual void setInTerminal(bool inTerminal)
Set inTerminal flag to inTerminal.
CFTypeRef getKeyClass(KeyClass keyClass)
Convert keyClass to MAC OS key class.
shared_ptr< Buffer > buf()
Flush written data to the stream and return shared pointer to the underlying buffer.
bool operator==(std::nullptr_t)
virtual ConstBufferPtr encryptInTpm(const uint8_t *data, size_t dataLength, const Name &keyName, bool isSymmetric)
Encrypt data.
SecTpm is the base class of the TPM classes.
void deleteKeyPairInTpmInternal(const Name &keyName, bool needRetry)
SecKeychainRef m_keyChainRef
Base class of key parameters.
virtual bool isLocked()
Check if TPM is locked.
implements an output stream that constructs ndn::Buffer
shared_ptr< const Buffer > ConstBufferPtr
SimplePublicKeyParams is a template for public keys with only one parameter: size.
static const std::string SCHEME
Block signInTpmInternal(const uint8_t *data, size_t dataLength, const Name &keyName, DigestAlgorithm digestAlgorithm, bool needRetry)
virtual shared_ptr< v1::PublicKey > getPublicKeyFromTpm(const Name &keyName)
Get a public key.
CFStringRef getDigestAlgorithm(DigestAlgorithm digestAlgo)
Convert digestAlgo to MAC OS algorithm id.
CFReleaser(const CFReleaser &inReleaser)