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> 81 retain(inReleaser.m_typeRef);
87 if (typeRef != m_typeRef) {
97 retain(inReleaser.m_typeRef);
137 if (typeRef !=
nullptr) {
147 if (m_typeRef !=
nullptr) {
148 CFRelease(m_typeRef);
156 return get() ==
nullptr;
162 return get() !=
nullptr;
174 : m_passwordSet(false)
175 , m_inTerminal(false)
185 toInternalKeyName(
const Name& keyName,
KeyClass keyClass);
192 CFReleaser<SecKeychainItemRef>
201 getSymKeyType(
KeyType keyType);
209 getAsymKeyType(
KeyType keyType);
250 if (m_impl->m_inTerminal)
251 SecKeychainSetUserInteractionAllowed(
false);
253 SecKeychainSetUserInteractionAllowed(
true);
255 OSStatus res = SecKeychainCopyDefault(&m_impl->m_keyChainRef);
257 if (res == errSecNoDefaultKeychain)
258 BOOST_THROW_EXCEPTION(
Error(
"No default keychain, please create one first"));
268 m_impl->m_passwordSet =
true;
269 std::fill(m_impl->m_password.begin(), m_impl->m_password.end(), 0);
270 m_impl->m_password.clear();
271 m_impl->m_password.append(reinterpret_cast<const char*>(password), passwordLength);
277 m_impl->m_passwordSet =
false;
278 std::fill(m_impl->m_password.begin(), m_impl->m_password.end(), 0);
279 m_impl->m_password.clear();
285 m_impl->m_inTerminal = inTerminal;
287 SecKeychainSetUserInteractionAllowed(
false);
289 SecKeychainSetUserInteractionAllowed(
true);
295 return m_impl->m_inTerminal;
301 SecKeychainStatus keychainStatus;
303 OSStatus res = SecKeychainGetStatus(m_impl->m_keyChainRef, &keychainStatus);
304 if (res != errSecSuccess)
307 return ((kSecUnlockStateStatus & keychainStatus) == 0);
322 res = SecKeychainUnlock(m_impl->m_keyChainRef,
327 else if (m_impl->m_passwordSet) {
329 SecKeychainUnlock(m_impl->m_keyChainRef,
330 m_impl->m_password.size(),
331 m_impl->m_password.c_str(),
334 #ifdef NDN_CXX_HAVE_GETPASS 335 else if (m_impl->m_inTerminal) {
338 const char* fmt =
"Password to unlock the default keychain: ";
345 char* getPassword =
nullptr;
346 getPassword = getpass(fmt);
352 res = SecKeychainUnlock(m_impl->m_keyChainRef,
357 memset(getPassword, 0, strlen(getPassword));
359 if (res == errSecSuccess)
363 #endif // NDN_CXX_HAVE_GETPASS 366 SecKeychainUnlock(m_impl->m_keyChainRef, 0,
nullptr,
false);
379 BOOST_THROW_EXCEPTION(
Error(
"keyName already exists"));
385 CFStringCreateWithCString(0,
387 kCFStringEncodingUTF8);
390 CFDictionaryCreateMutable(0,
392 &kCFTypeDictionaryKeyCallBacks,
396 uint32_t keySize = 0;
411 BOOST_THROW_EXCEPTION(
Error(
"Fail to create a key pair: Unsupported key type"));
416 CFDictionaryAddValue(attrDict.get(), kSecAttrKeyType, m_impl->getAsymKeyType(keyType));
417 CFDictionaryAddValue(attrDict.get(), kSecAttrKeySizeInBits, cfKeySize.
get());
418 CFDictionaryAddValue(attrDict.get(), kSecAttrLabel, keyLabel.
get());
422 OSStatus res = SecKeyGeneratePair((CFDictionaryRef)attrDict.get(),
423 &publicKey.get(), &privateKey.get());
425 if (res == errSecSuccess) {
429 if (res == errSecAuthFailed && !needRetry) {
433 BOOST_THROW_EXCEPTION(
Error(
"Fail to unlock the keychain"));
436 BOOST_THROW_EXCEPTION(
Error(
"Fail to create a key pair"));
444 CFStringCreateWithCString(0,
445 keyName.
toUri().c_str(),
446 kCFStringEncodingUTF8);
449 CFDictionaryCreateMutable(0, 5,
450 &kCFTypeDictionaryKeyCallBacks,
451 &kCFTypeDictionaryValueCallBacks);
453 CFDictionaryAddValue(searchDict.get(), kSecClass, kSecClassKey);
454 CFDictionaryAddValue(searchDict.get(), kSecAttrLabel, keyLabel.
get());
455 CFDictionaryAddValue(searchDict.get(), kSecMatchLimit, kSecMatchLimitAll);
456 OSStatus res = SecItemDelete(searchDict.get());
458 if (res == errSecSuccess)
461 if (res == errSecAuthFailed && !needRetry) {
470 BOOST_THROW_EXCEPTION(
Error(
"SecTpmOsx::generateSymmetricKeyInTpm is not supported"));
502 shared_ptr<v1::PublicKey>
506 if (publicKey ==
nullptr) {
507 BOOST_THROW_EXCEPTION(
Error(
"Requested public key [" + keyName.
toUri() +
"] does not exist " 512 OSStatus res = SecItemExport(publicKey.
get(),
517 if (res != errSecSuccess) {
518 BOOST_THROW_EXCEPTION(
Error(
"Cannot export requested public key from OSX Keychain"));
521 shared_ptr<v1::PublicKey> key = make_shared<v1::PublicKey>(CFDataGetBytePtr(exportedKey.
get()),
522 CFDataGetLength(exportedKey.
get()));
538 if (privateKey ==
nullptr) {
540 BOOST_THROW_EXCEPTION(
Error(
"Private key [" + keyName.
toUri() +
"] does not exist " 547 OSStatus res = SecItemExport(privateKey.
get(),
553 if (res != errSecSuccess) {
554 if (res == errSecAuthFailed && !needRetry) {
564 uint32_t version = 0;
566 bool hasParameters =
false;
567 Oid algorithmParameter;
568 switch (publicKey->getKeyType()) {
571 hasParameters =
false;
577 StringSource src(publicKey->get().buf(), publicKey->get().size(),
true);
578 BERSequenceDecoder subjectPublicKeyInfo(src);
580 BERSequenceDecoder algorithmInfo(subjectPublicKeyInfo);
582 algorithm.
decode(algorithmInfo);
583 algorithmParameter.
decode(algorithmInfo);
586 hasParameters =
true;
591 BOOST_THROW_EXCEPTION(
Error(
"Unsupported key type" +
592 boost::lexical_cast<std::string>(publicKey->getKeyType())));
596 FileSink sink(pkcs8Os);
598 SecByteBlock rawKeyBits;
603 DERSequenceEncoder privateKeyInfo(sink);
605 DEREncodeUnsigned<uint32_t>(privateKeyInfo, version, INTEGER);
606 DERSequenceEncoder privateKeyAlgorithm(privateKeyInfo);
608 algorithm.
encode(privateKeyAlgorithm);
610 algorithmParameter.
encode(privateKeyAlgorithm);
612 DEREncodeNull(privateKeyAlgorithm);
614 privateKeyAlgorithm.MessageEnd();
615 DEREncodeOctetString(privateKeyInfo,
616 CFDataGetBytePtr(exportedKey.
get()),
617 CFDataGetLength(exportedKey.
get()));
619 privateKeyInfo.MessageEnd();
621 return pkcs8Os.buf();
625 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) 626 #pragma GCC diagnostic push 627 #endif // __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) 628 #pragma GCC diagnostic ignored "-Wdeprecated-declarations" 633 const uint8_t* buf,
size_t size,
638 StringSource privateKeySource(buf, size,
true);
639 SecByteBlock rawKeyBits;
644 BERSequenceDecoder privateKeyInfo(privateKeySource);
647 BERDecodeUnsigned<uint32_t>(privateKeyInfo, versionNum, INTEGER);
648 BERSequenceDecoder sequenceDecoder(privateKeyInfo);
651 keyTypeOid.
decode(sequenceDecoder);
654 BERDecodeNull(sequenceDecoder);
657 parameterOid.
decode(sequenceDecoder);
662 BERDecodeOctetString(privateKeyInfo, rawKeyBits);
664 privateKeyInfo.MessageEnd();
667 rawKeyBits.BytePtr(),
671 SecExternalFormat externalFormat = kSecFormatOpenSSL;
672 SecExternalItemType externalType = kSecItemTypePrivateKey;
673 SecKeyImportExportParameters keyParams;
674 memset(&keyParams, 0,
sizeof(keyParams));
675 keyParams.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
676 keyParams.keyAttributes = CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_PERMANENT;
679 keyName.
toUri().c_str(),
680 kCFStringEncodingUTF8);
681 SecAccessCreate(keyLabel.
get(), 0, &access.
get());
682 keyParams.accessRef = access.
get();
686 #pragma clang diagnostic push 687 #pragma clang diagnostic ignored "-Wdeprecated-declarations" 690 OSStatus res = SecKeychainItemImport(importedKey.
get(),
696 m_impl->m_keyChainRef,
700 #pragma clang diagnostic pop 703 if (res != errSecSuccess) {
704 if (res == errSecAuthFailed && !needRetry) {
715 SecKeychainItemRef privateKey = (SecKeychainItemRef)CFArrayGetValueAtIndex(outItems.
get(), 0);
716 SecKeychainAttribute attrs[1];
717 SecKeychainAttributeList attrList = {0, attrs};
718 string keyUri = keyName.
toUri();
720 attrs[attrList.count].tag = kSecKeyPrintName;
721 attrs[attrList.count].length = keyUri.size();
722 attrs[attrList.count].data =
const_cast<char*
>(keyUri.c_str());
726 res = SecKeychainItemModifyAttributesAndData(privateKey,
731 if (res != errSecSuccess) {
738 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) 739 #pragma GCC diagnostic pop 740 #endif // __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) 750 SecExternalFormat externalFormat = kSecFormatOpenSSL;
751 SecExternalItemType externalType = kSecItemTypePublicKey;
754 OSStatus res = SecItemImport(importedKey.
get(),
760 m_impl->m_keyChainRef,
763 if (res != errSecSuccess)
767 SecKeychainItemRef publicKey = (SecKeychainItemRef)CFArrayGetValueAtIndex(outItems.
get(), 0);
768 SecKeychainAttribute attrs[1];
769 SecKeychainAttributeList attrList = { 0, attrs };
770 string keyUri = keyName.
toUri();
772 attrs[attrList.count].tag = kSecKeyPrintName;
773 attrs[attrList.count].length = keyUri.size();
774 attrs[attrList.count].data =
const_cast<char*
>(keyUri.c_str());
778 res = SecKeychainItemModifyAttributesAndData(publicKey,
783 if (res != errSecSuccess)
799 if (privateKey ==
nullptr) {
800 BOOST_THROW_EXCEPTION(
Error(
"Private key [" + keyName.
toUri() +
"] does not exist " 808 if (error !=
nullptr)
809 BOOST_THROW_EXCEPTION(
Error(
"Fail to create signer"));
812 SecTransformSetAttribute(signer.
get(),
813 kSecTransformInputAttributeName,
816 if (error !=
nullptr)
817 BOOST_THROW_EXCEPTION(
Error(
"Fail to configure input of signer"));
820 SecTransformSetAttribute(signer.
get(),
824 if (error !=
nullptr)
825 BOOST_THROW_EXCEPTION(
Error(
"Fail to configure digest algorithm of signer"));
828 SecTransformSetAttribute(signer.
get(),
829 kSecDigestTypeAttribute,
830 m_impl->getDigestAlgorithm(digestAlgorithm),
832 if (error !=
nullptr)
833 BOOST_THROW_EXCEPTION(
Error(
"Fail to configure digest algorithm of signer"));
836 long digestSize = m_impl->getDigestSize(digestAlgorithm);
838 SecTransformSetAttribute(signer.
get(),
839 kSecDigestLengthAttribute,
842 if (error !=
nullptr)
843 BOOST_THROW_EXCEPTION(
Error(
"Fail to configure digest size of signer"));
848 if (error !=
nullptr) {
853 BOOST_THROW_EXCEPTION(
Error(
"Fail to unlock the keychain"));
857 BOOST_THROW_EXCEPTION(
Error(
"Fail to sign data"));
861 if (signature ==
nullptr)
862 BOOST_THROW_EXCEPTION(
Error(
"Signature is NULL!\n"));
865 make_shared<Buffer>(CFDataGetBytePtr(signature.
get()),
866 CFDataGetLength(signature.
get())));
872 BOOST_THROW_EXCEPTION(
Error(
"SecTpmOsx::decryptInTpm is not supported"));
918 if (privateKey ==
nullptr) {
919 BOOST_THROW_EXCEPTION(
Error(
"Private key [" + keyName.
toUri() +
"] does not exist " 924 SecKeychainItemCopyAccess(privateKey.
get(), &accRef.
get());
927 kSecACLAuthorizationSign);
930 SecACLRef aclRef = (SecACLRef)CFArrayGetValueAtIndex(signACL.get(), 0);
934 SecKeychainPromptSelector promptSelector;
935 SecACLCopyContents(aclRef,
945 SecTrustedApplicationCreateFromPath(appPath.c_str(),
948 CFArrayAppendValue(newAppList.get(), trustedApp.get());
950 SecACLSetContents(aclRef,
955 SecKeychainItemSetAccess(privateKey.
get(), accRef.
get());
962 BOOST_THROW_EXCEPTION(
Error(
"SecTpmOsx::encryptInTpm is not supported"));
1002 string keyNameUri = m_impl->toInternalKeyName(keyName, keyClass);
1006 kCFStringEncodingUTF8);
1009 CFDictionaryCreateMutable(0,
1011 &kCFTypeDictionaryKeyCallBacks,
1014 CFDictionaryAddValue(attrDict.get(), kSecClass, kSecClassKey);
1016 CFDictionaryAddValue(attrDict.get(), kSecAttrLabel, keyLabel.
get());
1017 CFDictionaryAddValue(attrDict.get(), kSecReturnRef, kCFBooleanTrue);
1021 OSStatus res = SecItemCopyMatching((CFDictionaryRef)attrDict.get(), (CFTypeRef*)&itemRef.get());
1023 if (res == errSecSuccess)
1033 return SecRandomCopyBytes(kSecRandomDefault, size, res) == 0;
1043 string keyNameUri = toInternalKeyName(keyName, keyClass);
1045 CFReleaser<CFStringRef> keyLabel = CFStringCreateWithCString(0,
1047 kCFStringEncodingUTF8);
1049 CFReleaser<CFMutableDictionaryRef> attrDict =
1050 CFDictionaryCreateMutable(0,
1052 &kCFTypeDictionaryKeyCallBacks,
1055 CFDictionaryAddValue(attrDict.get(), kSecClass, kSecClassKey);
1056 CFDictionaryAddValue(attrDict.get(), kSecAttrLabel, keyLabel.get());
1057 CFDictionaryAddValue(attrDict.get(), kSecAttrKeyClass, getKeyClass(keyClass));
1058 CFDictionaryAddValue(attrDict.get(), kSecReturnRef, kCFBooleanTrue);
1060 CFReleaser<SecKeychainItemRef> keyItem;
1062 OSStatus res = SecItemCopyMatching((CFDictionaryRef)attrDict.get(), (CFTypeRef*)&keyItem.get());
1064 if (res != errSecSuccess)
1073 string keyUri = keyName.toUri();
1076 return keyUri +
"/symmetric";
1086 return kSecAttrKeyTypeRSA;
1088 return kSecAttrKeyTypeECDSA;
1099 return kSecAttrKeyTypeAES;
1110 return kSecAttrKeyClassPrivate;
1112 return kSecAttrKeyClassPublic;
1114 return kSecAttrKeyClassSymmetric;
1123 switch (digestAlgo) {
1125 return kSecDigestSHA2;
1134 switch (digestAlgo) {
void encode(CryptoPP::BufferedTransformation &out) const
void decode(CryptoPP::BufferedTransformation &in)
const Oid ECDSA("1.2.840.10045.2.1")
Copyright (c) 2011-2015 Regents of the University of California.
std::string toUri() const
Encode this name as a URI.
CFTypeRef getAsymKeyType(KeyType keyType)
Convert keyType to MAC OS asymmetirc key type.
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.
Copyright (c) 2013-2016 Regents of the University of California.
virtual void setTpmPassword(const uint8_t *password, size_t passwordLength)
set password of TPM
virtual shared_ptr< v1::PublicKey > getPublicKeyFromTpm(const Name &keyName)
Get a public key.
bool operator!=(std::nullptr_t)
SecTpm is the base class of the TPM classes.
ConstBufferPtr exportPrivateKeyPkcs8FromTpmInternal(const Name &keyName, bool needRetry)
virtual ConstBufferPtr decryptInTpm(const uint8_t *data, size_t dataLength, const Name &keyName, bool isSymmetric)
Decrypt data.
Class representing a wire element of NDN-TLV packet format.
bool operator==(std::nullptr_t)
virtual bool getInTerminal() const
Get value of inTerminal flag.
Helper class to wrap CoreFoundation object pointers.
CFStringRef getDigestAlgorithm(DigestAlgorithm digestAlgo)
Convert digestAlgo to MAC OS algorithm id.
void retain(const T &typeRef)
SecTpmOsx(const std::string &location="")
const Oid RSA("1.2.840.113549.1.1.1")
CFTypeRef getKeyClass(KeyClass keyClass)
Convert keyClass to MAC OS key class.
virtual bool unlockTpm(const char *password, size_t passwordLength, bool usePassword)
Unlock the TPM.
virtual std::string getScheme()
long getDigestSize(DigestAlgorithm digestAlgo)
Get the digest size of the corresponding algorithm.
CFReleaser(const CFReleaser &inReleaser)
Name abstraction to represent an absolute name.
KeyType getKeyType() const
CFReleaser & operator=(const CFReleaser &inReleaser)
CFReleaser & operator=(const T &typeRef)
std::string toInternalKeyName(const Name &keyName, KeyClass keyClass)
Convert NDN name of a key to internal name of the key.
virtual bool generateRandomBlock(uint8_t *res, size_t size)
Generate a random block.
CFReleaser< SecKeychainItemRef > getKey(const Name &keyName, KeyClass keyClass)
Get key.
CFTypeRef getSymKeyType(KeyType keyType)
Convert keyType to MAC OS symmetric key key type.
virtual bool doesKeyExistInTpm(const Name &keyName, KeyClass keyClass)
Check if a particular key exists.
virtual void generateSymmetricKeyInTpm(const Name &keyName, const KeyParams ¶ms)
Generate a symmetric key.
virtual ConstBufferPtr encryptInTpm(const uint8_t *data, size_t dataLength, const Name &keyName, bool isSymmetric)
Encrypt data.
Base class of key parameters.
uint32_t getKeySize() const
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 generateKeyPairInTpmInternal(const Name &keyName, const KeyParams ¶ms, bool needRetry)
implements an output stream that constructs ndn::Buffer
void deleteKeyPairInTpmInternal(const Name &keyName, bool needRetry)
virtual bool isLocked()
Check if TPM is locked.
bool importPrivateKeyPkcs8IntoTpmInternal(const Name &keyName, const uint8_t *buf, size_t size, bool needRetry)
shared_ptr< const Buffer > ConstBufferPtr
SimplePublicKeyParams is a template for public keys with only one parameter: size.
static const std::string SCHEME
CFReleaser(const T &typeRef)
SecKeychainRef m_keyChainRef
Block signInTpmInternal(const uint8_t *data, size_t dataLength, const Name &keyName, DigestAlgorithm digestAlgorithm, bool needRetry)
virtual void setInTerminal(bool inTerminal)
Set inTerminal flag to inTerminal.
virtual void resetTpmPassword()
reset password of TPM