All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
sec-tpm-osx.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
8 #include "common.hpp"
9 
10 #include "sec-tpm-osx.hpp"
11 
12 #include "security/public-key.hpp"
13 #include "cryptopp.hpp"
14 
15 #include <pwd.h>
16 #include <unistd.h>
17 #include <stdlib.h>
18 #include <string.h>
19 
20 #include <CoreFoundation/CoreFoundation.h>
21 #include <Security/Security.h>
22 #include <Security/SecRandom.h>
23 #include <CoreServices/CoreServices.h>
24 
25 #include <Security/SecDigestTransform.h>
26 
27 using namespace std;
28 
29 namespace ndn {
30 
32 {
33 public:
34  Impl()
35  : m_passwordSet(false)
36  , m_inTerminal(false)
37  {
38  }
39 
47  std::string
48  toInternalKeyName(const Name& keyName, KeyClass keyClass);
49 
57  SecKeychainItemRef
58  getKey(const Name& keyName, KeyClass keyClass);
59 
66  const CFTypeRef
67  getSymKeyType(KeyType keyType);
68 
75  const CFTypeRef
76  getAsymKeyType(KeyType keyType);
77 
84  const CFTypeRef
85  getKeyClass(KeyClass keyClass);
86 
93  const CFStringRef
94  getDigestAlgorithm(DigestAlgorithm digestAlgo);
95 
102  long
103  getDigestSize(DigestAlgorithm digestAlgo);
104 
106  // everything here is public, including data //
108 public:
109  SecKeychainRef m_keyChainRef;
111  string m_password;
113 };
114 
115 
116 SecTpmOsx::SecTpmOsx()
117  : m_impl(new Impl)
118 {
119  if (m_impl->m_inTerminal)
120  SecKeychainSetUserInteractionAllowed(false);
121  else
122  SecKeychainSetUserInteractionAllowed(true);
123 
124  OSStatus res = SecKeychainCopyDefault(&m_impl->m_keyChainRef);
125 
126  if (res == errSecNoDefaultKeychain) //If no default key chain, create one.
127  throw Error("No default keychain, create one first!");
128 }
129 
131  //TODO: implement
132 }
133 
134 void
135 SecTpmOsx::setTpmPassword(const uint8_t* password, size_t passwordLength)
136 {
137  m_impl->m_passwordSet = true;
138  memset(const_cast<char*>(m_impl->m_password.c_str()), 0, m_impl->m_password.size());
139  m_impl->m_password.clear();
140  m_impl->m_password.append(reinterpret_cast<const char*>(password), passwordLength);
141 }
142 
143 void
145 {
146  m_impl->m_passwordSet = false;
147  memset(const_cast<char*>(m_impl->m_password.c_str()), 0, m_impl->m_password.size());
148  m_impl->m_password.clear();
149 }
150 
151 void
152 SecTpmOsx::setInTerminal(bool inTerminal)
153 {
154  m_impl->m_inTerminal = inTerminal;
155  if (inTerminal)
156  SecKeychainSetUserInteractionAllowed(false);
157  else
158  SecKeychainSetUserInteractionAllowed(true);
159 }
160 
161 bool
163 {
164  return m_impl->m_inTerminal;
165 }
166 
167 bool
169 {
170  SecKeychainStatus keychainStatus;
171 
172  OSStatus res = SecKeychainGetStatus(m_impl->m_keyChainRef, &keychainStatus);
173  if (res != errSecSuccess)
174  return true;
175  else
176  return ((kSecUnlockStateStatus & keychainStatus) == 0);
177 }
178 
179 bool
180 SecTpmOsx::unlockTpm(const char* password, size_t passwordLength, bool usePassword)
181 {
182  OSStatus res;
183 
184  // If the default key chain is already unlocked, return immediately.
185  if (!locked())
186  return true;
187 
188  // If the default key chain is locked, unlock the key chain.
189  if (usePassword)
190  {
191  // Use the supplied password.
192  res = SecKeychainUnlock(m_impl->m_keyChainRef,
193  passwordLength,
194  password,
195  true);
196  }
197  else if (m_impl->m_passwordSet)
198  {
199  // If no password supplied, then use the configured password if exists.
200  SecKeychainUnlock(m_impl->m_keyChainRef,
201  m_impl->m_password.size(),
202  m_impl->m_password.c_str(),
203  true);
204  }
205  else if (m_impl->m_inTerminal)
206  {
207  // If no configured password, get password from terminal if inTerminal set.
208  bool locked = true;
209  const char* fmt = "Password to unlock the default keychain: ";
210  int count = 0;
211 
212  while(locked)
213  {
214  if (count > 2)
215  break;
216 
217  char* getPassword = 0;
218  getPassword = getpass(fmt);
219  count++;
220 
221  if (!getPassword)
222  continue;
223 
224  res = SecKeychainUnlock(m_impl->m_keyChainRef,
225  strlen(getPassword),
226  getPassword,
227  true);
228 
229  memset(getPassword, 0, strlen(getPassword));
230 
231  if (res == errSecSuccess)
232  break;
233  }
234  }
235  else
236  {
237  // If inTerminal is not set, get the password from GUI.
238  SecKeychainUnlock(m_impl->m_keyChainRef, 0, 0, false);
239  }
240 
241  return !locked();
242 }
243 
244 void
246  int keySize, bool needRetry)
247 {
248 
249  if (doesKeyExistInTpm(keyName, KEY_CLASS_PUBLIC))
250  {
251  throw Error("keyName has existed");
252  }
253 
254  string keyNameUri = m_impl->toInternalKeyName(keyName, KEY_CLASS_PUBLIC);
255 
256  SecKeyRef publicKey, privateKey;
257 
258  CFStringRef keyLabel = CFStringCreateWithCString(0,
259  keyNameUri.c_str(),
260  kCFStringEncodingUTF8);
261 
262  CFMutableDictionaryRef attrDict = CFDictionaryCreateMutable(0,
263  3,
264  &kCFTypeDictionaryKeyCallBacks,
265  0);
266 
267  CFDictionaryAddValue(attrDict, kSecAttrKeyType, m_impl->getAsymKeyType(keyType));
268  CFDictionaryAddValue(attrDict, kSecAttrKeySizeInBits, CFNumberCreate(0,
269  kCFNumberIntType,
270  &keySize));
271  CFDictionaryAddValue(attrDict, kSecAttrLabel, keyLabel);
272 
273  OSStatus res = SecKeyGeneratePair((CFDictionaryRef)attrDict, &publicKey, &privateKey);
274 
275  if (res == errSecSuccess)
276  {
277  CFRelease(publicKey);
278  CFRelease(privateKey);
279  return;
280  }
281 
282  if (res == errSecAuthFailed && !needRetry)
283  {
284  if (unlockTpm(0, 0, false))
285  generateKeyPairInTpmInternal(keyName, keyType, keySize, true);
286  else
287  throw Error("Fail to unlock the keychain");
288  }
289  else
290  {
291  throw Error("Fail to create a key pair");
292  }
293 }
294 
295 void
296 SecTpmOsx::deleteKeyPairInTpmInternal(const Name& keyName, bool needRetry)
297 {
298  CFStringRef keyLabel = CFStringCreateWithCString(0,
299  keyName.toUri().c_str(),
300  kCFStringEncodingUTF8);
301 
302  CFMutableDictionaryRef searchDict =
303  CFDictionaryCreateMutable(0, 5,
304  &kCFTypeDictionaryKeyCallBacks,
305  &kCFTypeDictionaryValueCallBacks);
306 
307  CFDictionaryAddValue(searchDict, kSecClass, kSecClassKey);
308  CFDictionaryAddValue(searchDict, kSecAttrLabel, keyLabel);
309  CFDictionaryAddValue(searchDict, kSecMatchLimit, kSecMatchLimitAll);
310  OSStatus res = SecItemDelete(searchDict);
311 
312  if (res == errSecSuccess)
313  return;
314 
315  if (res == errSecAuthFailed && !needRetry)
316  {
317  if (unlockTpm(0, 0, false))
318  deleteKeyPairInTpmInternal(keyName, true);
319  }
320 }
321 
322 void
323 SecTpmOsx::generateSymmetricKeyInTpm(const Name& keyName, KeyType keyType, int keySize)
324 {
325  throw Error("SecTpmOsx::generateSymmetricKeyInTpm is not supported");
326  // if (doesKeyExistInTpm(keyName, KEY_CLASS_SYMMETRIC))
327  // throw Error("keyName has existed!");
328 
329  // string keyNameUri = m_impl->toInternalKeyName(keyName, KEY_CLASS_SYMMETRIC);
330 
331  // CFMutableDictionaryRef attrDict = CFDictionaryCreateMutable(kCFAllocatorDefault,
332  // 0,
333  // &kCFTypeDictionaryKeyCallBacks,
334  // &kCFTypeDictionaryValueCallBacks);
335 
336  // CFStringRef keyLabel = CFStringCreateWithCString(0,
337  // keyNameUri.c_str(),
338  // kCFStringEncodingUTF8);
339 
340  // CFDictionaryAddValue(attrDict, kSecAttrKeyType, m_impl->getSymKeyType(keyType));
341  // CFDictionaryAddValue(attrDict, kSecAttrKeySizeInBits, CFNumberCreate(kCFAllocatorDefault,
342  // kCFNumberSInt32Type,
343  // &keySize));
344  // CFDictionaryAddValue(attrDict, kSecAttrIsPermanent, kCFBooleanTrue);
345  // CFDictionaryAddValue(attrDict, kSecAttrLabel, keyLabel);
346 
347  // CFErrorRef error = 0;
348 
349  // SecKeyRef symmetricKey = SecKeyGenerateSymmetric(attrDict, &error);
350 
351  // if (error)
352  // throw Error("Fail to create a symmetric key");
353 }
354 
355 shared_ptr<PublicKey>
357 {
358  SecKeychainItemRef publicKey = m_impl->getKey(keyName, KEY_CLASS_PUBLIC);
359 
360  CFDataRef exportedKey;
361 
362  OSStatus res = SecItemExport(publicKey,
363  kSecFormatOpenSSL,
364  0,
365  0,
366  &exportedKey);
367  if (res != errSecSuccess)
368  {
369  throw Error("Cannot export requested public key from OSX Keychain");
370  }
371 
372  shared_ptr<PublicKey> key = make_shared<PublicKey>(CFDataGetBytePtr(exportedKey),
373  CFDataGetLength(exportedKey));
374  CFRelease(exportedKey);
375  return key;
376 }
377 
380 {
381  using namespace CryptoPP;
382 
383  SecKeychainItemRef privateKey = m_impl->getKey(keyName, KEY_CLASS_PRIVATE);
384  CFDataRef exportedKey;
385  OSStatus res = SecItemExport(privateKey,
386  kSecFormatOpenSSL,
387  0,
388  0,
389  &exportedKey);
390 
391  if (res != errSecSuccess)
392  {
393  if (res == errSecAuthFailed && !needRetry)
394  {
395  if (unlockTpm(0, 0, false))
396  return exportPrivateKeyPkcs8FromTpmInternal(keyName, true);
397  else
398  return shared_ptr<Buffer>();
399  }
400  else
401  return shared_ptr<Buffer>();
402  }
403 
404  OBufferStream pkcs1Os;
405  FileSink sink(pkcs1Os);
406 
407  uint32_t version = 0;
408  OID algorithm("1.2.840.113549.1.1.1");
409  SecByteBlock rawKeyBits;
410  // PrivateKeyInfo ::= SEQUENCE {
411  // version INTEGER,
412  // privateKeyAlgorithm SEQUENCE,
413  // privateKey OCTECT STRING}
414  DERSequenceEncoder privateKeyInfo(sink);
415  {
416  DEREncodeUnsigned<uint32_t>(privateKeyInfo, version, INTEGER);
417  DERSequenceEncoder privateKeyAlgorithm(privateKeyInfo);
418  {
419  algorithm.encode(privateKeyAlgorithm);
420  DEREncodeNull(privateKeyAlgorithm);
421  }
422  privateKeyAlgorithm.MessageEnd();
423  DEREncodeOctetString(privateKeyInfo,
424  CFDataGetBytePtr(exportedKey),
425  CFDataGetLength(exportedKey));
426  }
427  privateKeyInfo.MessageEnd();
428 
429  CFRelease(exportedKey);
430  return pkcs1Os.buf();
431 }
432 
433 #ifdef __GNUC__
434 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
435 #pragma GCC diagnostic push
436 #endif // __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
437 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
438 #endif // __GNUC__
439 
440 bool
442  const uint8_t* buf, size_t size,
443  bool needRetry)
444 {
445  using namespace CryptoPP;
446 
447  StringSource privateKeySource(buf, size, true);
448  uint32_t tmpNum;
449  OID tmpOID;
450  SecByteBlock rawKeyBits;
451  // PrivateKeyInfo ::= SEQUENCE {
452  // INTEGER,
453  // SEQUENCE,
454  // OCTECT STRING}
455  BERSequenceDecoder privateKeyInfo(privateKeySource);
456  {
457  BERDecodeUnsigned<uint32_t>(privateKeyInfo, tmpNum, INTEGER);
458  BERSequenceDecoder sequenceDecoder(privateKeyInfo);
459  {
460  tmpOID.decode(sequenceDecoder);
461  BERDecodeNull(sequenceDecoder);
462  }
463  BERDecodeOctetString(privateKeyInfo, rawKeyBits);
464  }
465  privateKeyInfo.MessageEnd();
466 
467  CFDataRef importedKey = CFDataCreateWithBytesNoCopy(0,
468  rawKeyBits.BytePtr(),
469  rawKeyBits.size(),
470  kCFAllocatorNull);
471 
472  SecExternalFormat externalFormat = kSecFormatOpenSSL;
473  SecExternalItemType externalType = kSecItemTypePrivateKey;
474  SecKeyImportExportParameters keyParams;
475  memset(&keyParams, 0, sizeof(keyParams));
476  keyParams.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
477  keyParams.keyAttributes = CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_PERMANENT;
478  SecAccessRef access;
479  CFStringRef keyLabel = CFStringCreateWithCString(0,
480  keyName.toUri().c_str(),
481  kCFStringEncodingUTF8);
482  SecAccessCreate(keyLabel, 0, &access);
483  keyParams.accessRef = access;
484  CFArrayRef outItems;
485 
486 #ifdef __clang__
487 #pragma clang diagnostic push
488 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
489 #endif // __clang__
490 
491  OSStatus res = SecKeychainItemImport (importedKey,
492  0,
493  &externalFormat,
494  &externalType,
495  0,
496  &keyParams,
497  m_impl->m_keyChainRef,
498  &outItems);
499 
500 #ifdef __clang__
501 #pragma clang diagnostic pop
502 #endif // __clang__
503 
504  if (res != errSecSuccess)
505  {
506  if (res == errSecAuthFailed && !needRetry)
507  {
508  if (unlockTpm(0, 0, false))
509  return importPrivateKeyPkcs8IntoTpmInternal(keyName, buf, size, true);
510  else
511  return false;
512  }
513  else
514  return false;
515  }
516 
517  SecKeychainItemRef privateKey = (SecKeychainItemRef)CFArrayGetValueAtIndex(outItems, 0);
518  SecKeychainAttribute attrs[1]; // maximum number of attributes
519  SecKeychainAttributeList attrList = { 0, attrs };
520  string keyUri = keyName.toUri();
521  {
522  attrs[attrList.count].tag = kSecKeyPrintName;
523  attrs[attrList.count].length = keyUri.size();
524  attrs[attrList.count].data = (void *)keyUri.c_str();
525  attrList.count++;
526  }
527 
528  res = SecKeychainItemModifyAttributesAndData(privateKey,
529  &attrList,
530  0,
531  0);
532 
533  if (res != errSecSuccess)
534  {
535  return false;
536  }
537 
538  CFRelease(importedKey);
539  return true;
540 }
541 
542 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
543 #pragma GCC diagnostic pop
544 #endif // __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
545 
546 bool
547 SecTpmOsx::importPublicKeyPkcs1IntoTpm(const Name& keyName, const uint8_t* buf, size_t size)
548 {
549  CFDataRef importedKey = CFDataCreateWithBytesNoCopy(0,
550  buf,
551  size,
552  kCFAllocatorNull);
553 
554  SecExternalFormat externalFormat = kSecFormatOpenSSL;
555  SecExternalItemType externalType = kSecItemTypePublicKey;
556  CFArrayRef outItems;
557 
558  OSStatus res = SecItemImport (importedKey,
559  0,
560  &externalFormat,
561  &externalType,
562  0,
563  0,
564  m_impl->m_keyChainRef,
565  &outItems);
566 
567  if (res != errSecSuccess)
568  return false;
569 
570  SecKeychainItemRef publicKey = (SecKeychainItemRef)CFArrayGetValueAtIndex(outItems, 0);
571  SecKeychainAttribute attrs[1]; // maximum number of attributes
572  SecKeychainAttributeList attrList = { 0, attrs };
573  string keyUri = keyName.toUri();
574  {
575  attrs[attrList.count].tag = kSecKeyPrintName;
576  attrs[attrList.count].length = keyUri.size();
577  attrs[attrList.count].data = (void *)keyUri.c_str();
578  attrList.count++;
579  }
580 
581  res = SecKeychainItemModifyAttributesAndData(publicKey,
582  &attrList,
583  0,
584  0);
585 
586  if (res != errSecSuccess)
587  return false;
588 
589  CFRelease(importedKey);
590  return true;
591 }
592 
593 Block
594 SecTpmOsx::signInTpmInternal(const uint8_t* data, size_t dataLength,
595  const Name& keyName, DigestAlgorithm digestAlgorithm, bool needRetry)
596 {
597  CFDataRef dataRef = CFDataCreateWithBytesNoCopy(0,
598  data,
599  dataLength,
600  kCFAllocatorNull);
601 
602  SecKeyRef privateKey = (SecKeyRef)m_impl->getKey(keyName, KEY_CLASS_PRIVATE);
603 
604  CFErrorRef error;
605  SecTransformRef signer = SecSignTransformCreate((SecKeyRef)privateKey, &error);
606  if (error)
607  throw Error("Fail to create signer");
608 
609  // Set input
610  Boolean set_res = SecTransformSetAttribute(signer,
611  kSecTransformInputAttributeName,
612  dataRef,
613  &error);
614  if (error)
615  throw Error("Fail to configure input of signer");
616 
617  // Enable use of padding
618  SecTransformSetAttribute(signer,
619  kSecPaddingKey,
620  kSecPaddingPKCS1Key,
621  &error);
622  if (error)
623  throw Error("Fail to configure digest algorithm of signer");
624 
625  // Set padding type
626  set_res = SecTransformSetAttribute(signer,
627  kSecDigestTypeAttribute,
628  m_impl->getDigestAlgorithm(digestAlgorithm),
629  &error);
630  if (error)
631  throw Error("Fail to configure digest algorithm of signer");
632 
633  // Set padding attribute
634  long digestSize = m_impl->getDigestSize(digestAlgorithm);
635  set_res = SecTransformSetAttribute(signer,
636  kSecDigestLengthAttribute,
637  CFNumberCreate(0, kCFNumberLongType, &digestSize),
638  &error);
639  if (error)
640  throw Error("Fail to configure digest size of signer");
641 
642  // Actually sign
643  CFDataRef signature = (CFDataRef) SecTransformExecute(signer, &error);
644  if (error)
645  {
646  if (!needRetry)
647  {
648  if (unlockTpm(0, 0, false))
649  return signInTpmInternal(data, dataLength, keyName, digestAlgorithm, true);
650  else
651  throw Error("Fail to unlock the keychain");
652  }
653  else
654  {
655  CFShow(error);
656  throw Error("Fail to sign data");
657  }
658  }
659 
660  if (!signature)
661  throw Error("Signature is NULL!\n");
662 
663  return Block(Tlv::SignatureValue,
664  make_shared<Buffer>(CFDataGetBytePtr(signature), CFDataGetLength(signature)));
665 }
666 
668 SecTpmOsx::decryptInTpm(const uint8_t* data, size_t dataLength, const Name& keyName, bool sym)
669 {
670  throw Error("SecTpmOsx::decryptInTpm is not supported");
671 
672  // KeyClass keyClass;
673  // if (sym)
674  // keyClass = KEY_CLASS_SYMMETRIC;
675  // else
676  // keyClass = KEY_CLASS_PRIVATE;
677 
678  // CFDataRef dataRef = CFDataCreate(0,
679  // reinterpret_cast<const unsigned char*>(data),
680  // dataLength
681  // );
682 
683  // SecKeyRef decryptKey = (SecKeyRef)m_impl->getKey(keyName, keyClass);
684 
685  // CFErrorRef error;
686  // SecTransformRef decrypt = SecDecryptTransformCreate(decryptKey, &error);
687  // if (error) throw Error("Fail to create decrypt");
688 
689  // Boolean set_res = SecTransformSetAttribute(decrypt,
690  // kSecTransformInputAttributeName,
691  // dataRef,
692  // &error);
693  // if (error) throw Error("Fail to configure decrypt");
694 
695  // CFDataRef output = (CFDataRef) SecTransformExecute(decrypt, &error);
696  // if (error)
697  // {
698  // CFShow(error);
699  // throw Error("Fail to decrypt data");
700  // }
701  // if (!output) throw Error("Output is NULL!\n");
702 
703  // return make_shared<Buffer>(CFDataGetBytePtr(output), CFDataGetLength(output));
704 }
705 
706 void
707 SecTpmOsx::addAppToACL(const Name& keyName, KeyClass keyClass, const string& appPath, AclType acl)
708 {
709  if (keyClass == KEY_CLASS_PRIVATE && acl == ACL_TYPE_PRIVATE)
710  {
711  SecKeychainItemRef privateKey = m_impl->getKey(keyName, keyClass);
712 
713  SecAccessRef accRef;
714  OSStatus acc_res = SecKeychainItemCopyAccess(privateKey, &accRef);
715 
716  CFArrayRef signACL = SecAccessCopyMatchingACLList(accRef,
717  kSecACLAuthorizationSign);
718 
719  SecACLRef aclRef = (SecACLRef) CFArrayGetValueAtIndex(signACL, 0);
720 
721  CFArrayRef appList;
722  CFStringRef description;
723  SecKeychainPromptSelector promptSelector;
724  OSStatus acl_res = SecACLCopyContents(aclRef,
725  &appList,
726  &description,
727  &promptSelector);
728 
729  CFMutableArrayRef newAppList = CFArrayCreateMutableCopy(0,
730  0,
731  appList);
732 
733  SecTrustedApplicationRef trustedApp;
734  acl_res = SecTrustedApplicationCreateFromPath(appPath.c_str(),
735  &trustedApp);
736 
737  CFArrayAppendValue(newAppList, trustedApp);
738 
739  acl_res = SecACLSetContents(aclRef,
740  newAppList,
741  description,
742  promptSelector);
743 
744  acc_res = SecKeychainItemSetAccess(privateKey, accRef);
745  }
746 }
747 
749 SecTpmOsx::encryptInTpm(const uint8_t* data, size_t dataLength, const Name& keyName, bool sym)
750 {
751  throw Error("SecTpmOsx::encryptInTpm is not supported");
752 
753  // KeyClass keyClass;
754  // if (sym)
755  // keyClass = KEY_CLASS_SYMMETRIC;
756  // else
757  // keyClass = KEY_CLASS_PUBLIC;
758 
759  // CFDataRef dataRef = CFDataCreate(0,
760  // reinterpret_cast<const unsigned char*>(data),
761  // dataLength
762  // );
763 
764  // SecKeyRef encryptKey = (SecKeyRef)m_impl->getKey(keyName, keyClass);
765 
766  // CFErrorRef error;
767  // SecTransformRef encrypt = SecEncryptTransformCreate(encryptKey, &error);
768  // if (error) throw Error("Fail to create encrypt");
769 
770  // Boolean set_res = SecTransformSetAttribute(encrypt,
771  // kSecTransformInputAttributeName,
772  // dataRef,
773  // &error);
774  // if (error) throw Error("Fail to configure encrypt");
775 
776  // CFDataRef output = (CFDataRef) SecTransformExecute(encrypt, &error);
777  // if (error) throw Error("Fail to encrypt data");
778 
779  // if (!output) throw Error("Output is NULL!\n");
780 
781  // return make_shared<Buffer> (CFDataGetBytePtr(output), CFDataGetLength(output));
782 }
783 
784 bool
785 SecTpmOsx::doesKeyExistInTpm(const Name& keyName, KeyClass keyClass)
786 {
787  string keyNameUri = m_impl->toInternalKeyName(keyName, keyClass);
788 
789  CFStringRef keyLabel = CFStringCreateWithCString(0,
790  keyNameUri.c_str(),
791  kCFStringEncodingUTF8);
792 
793  CFMutableDictionaryRef attrDict = CFDictionaryCreateMutable(0,
794  4,
795  &kCFTypeDictionaryKeyCallBacks,
796  0);
797 
798  CFDictionaryAddValue(attrDict, kSecClass, kSecClassKey);
799  // CFDictionaryAddValue(attrDict, kSecAttrKeyClass, m_impl->getKeyClass(keyClass));
800  CFDictionaryAddValue(attrDict, kSecAttrLabel, keyLabel);
801  CFDictionaryAddValue(attrDict, kSecReturnRef, kCFBooleanTrue);
802 
803  SecKeychainItemRef itemRef;
804  OSStatus res = SecItemCopyMatching((CFDictionaryRef)attrDict, (CFTypeRef*)&itemRef);
805 
806  if (res == errSecSuccess)
807  return true;
808  else
809  return false;
810 
811 }
812 
813 bool
814 SecTpmOsx::generateRandomBlock(uint8_t* res, size_t size)
815 {
816  return (SecRandomCopyBytes(kSecRandomDefault, size, res) == 0);
817 }
818 
820 // OSXPrivateKeyStorage::Impl //
822 
823 SecKeychainItemRef
824 SecTpmOsx::Impl::getKey(const Name& keyName, KeyClass keyClass)
825 {
826  string keyNameUri = toInternalKeyName(keyName, keyClass);
827 
828  CFStringRef keyLabel = CFStringCreateWithCString(0,
829  keyNameUri.c_str(),
830  kCFStringEncodingUTF8);
831 
832  CFMutableDictionaryRef attrDict = CFDictionaryCreateMutable(0,
833  5,
834  &kCFTypeDictionaryKeyCallBacks,
835  0);
836 
837  CFDictionaryAddValue(attrDict, kSecClass, kSecClassKey);
838  CFDictionaryAddValue(attrDict, kSecAttrLabel, keyLabel);
839  CFDictionaryAddValue(attrDict, kSecAttrKeyClass, getKeyClass(keyClass));
840  CFDictionaryAddValue(attrDict, kSecReturnRef, kCFBooleanTrue);
841 
842  SecKeychainItemRef keyItem;
843 
844  OSStatus res = SecItemCopyMatching((CFDictionaryRef) attrDict, (CFTypeRef*)&keyItem);
845 
846  if (res != errSecSuccess)
847  return 0;
848  else
849  return keyItem;
850 }
851 
852 string
854 {
855  string keyUri = keyName.toUri();
856 
857  if (KEY_CLASS_SYMMETRIC == keyClass)
858  return keyUri + "/symmetric";
859  else
860  return keyUri;
861 }
862 
863 const CFTypeRef
865 {
866  switch (keyType){
867  case KEY_TYPE_RSA:
868  return kSecAttrKeyTypeRSA;
869  default:
870  return 0;
871  }
872 }
873 
874 const CFTypeRef
876 {
877  switch (keyType){
878  case KEY_TYPE_AES:
879  return kSecAttrKeyTypeAES;
880  default:
881  return 0;
882  }
883 }
884 
885 const CFTypeRef
887 {
888  switch (keyClass){
889  case KEY_CLASS_PRIVATE:
890  return kSecAttrKeyClassPrivate;
891  case KEY_CLASS_PUBLIC:
892  return kSecAttrKeyClassPublic;
893  case KEY_CLASS_SYMMETRIC:
894  return kSecAttrKeyClassSymmetric;
895  default:
896  return 0;
897  }
898 }
899 
900 const CFStringRef
902 {
903  switch (digestAlgo){
904  // case DIGEST_MD2:
905  // return kSecDigestMD2;
906  // case DIGEST_MD5:
907  // return kSecDigestMD5;
908  // case DIGEST_SHA1:
909  // return kSecDigestSHA1;
911  return kSecDigestSHA2;
912  default:
913  return 0;
914  }
915 }
916 
917 long
919 {
920  switch (digestAlgo){
922  return 256;
923  // case DIGEST_SHA1:
924  // case DIGEST_MD2:
925  // case DIGEST_MD5:
926  // return 0;
927  default:
928  return -1;
929  }
930 }
931 
932 } // namespace ndn
Class implementing interface similar to ostringstream, but to construct ndn::Buffer.
Definition: buffer.hpp:176
void deleteKeyPairInTpmInternal(const Name &keyName, bool needRetry)
virtual bool getInTerminal()
get inTerminal flag
const CFStringRef getDigestAlgorithm(DigestAlgorithm digestAlgo)
Convert digestAlgo to MAC OS algorithm id.
virtual ConstBufferPtr encryptInTpm(const uint8_t *data, size_t dataLength, const Name &keyName, bool isSymmetric)
Encrypt data.
virtual bool importPublicKeyPkcs1IntoTpm(const Name &keyName, const uint8_t *buf, size_t size)
Import a public key in PKCS#1 format.
Class representing wire element of the NDN packet.
Definition: block.hpp:26
ConstBufferPtr exportPrivateKeyPkcs8FromTpmInternal(const Name &keyName, 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.
void generateKeyPairInTpmInternal(const Name &keyName, KeyType keyType, int keySize, bool needRetry)
virtual void setTpmPassword(const uint8_t *password, size_t passwordLength)
set password of TPM
virtual ~SecTpmOsx()
virtual void resetTpmPassword()
reset password of TPM
std::string toUri() const
Encode this name as a URI.
Definition: name.hpp:536
const CFTypeRef getAsymKeyType(KeyType keyType)
Convert keyType to MAC OS asymmetirc key type.
ptr_lib::shared_ptr< const Buffer > ConstBufferPtr
Definition: buffer.hpp:17
virtual bool locked()
check if TPM is locked.
virtual void generateSymmetricKeyInTpm(const Name &keyName, KeyType keyType, int keySize)
Generate a symmetric key.
virtual shared_ptr< PublicKey > getPublicKeyFromTpm(const Name &keyName)
Get a public key.
bool importPrivateKeyPkcs8IntoTpmInternal(const Name &keyName, const uint8_t *buf, size_t size, bool needRetry)
const CFTypeRef getKeyClass(KeyClass keyClass)
Convert keyClass to MAC OS key class.
A Name holds an array of Name::Component and represents an NDN name.
Definition: name.hpp:26
Definition: oid.hpp:20
virtual ConstBufferPtr decryptInTpm(const uint8_t *data, size_t dataLength, const Name &keyName, bool isSymmetric)
Decrypt data.
std::string toInternalKeyName(const Name &keyName, KeyClass keyClass)
Convert NDN name of a key to internal name of the key.
virtual bool doesKeyExistInTpm(const Name &keyName, KeyClass keyClass)
Check if a particular key exists.
virtual void setInTerminal(bool inTerminal)
set inTerminal flag
long getDigestSize(DigestAlgorithm digestAlgo)
Get the digest size of the corresponding algorithm.
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
Definition: oid.cpp:109
virtual bool generateRandomBlock(uint8_t *res, size_t size)
Generate a random block.
SecKeychainItemRef getKey(const Name &keyName, KeyClass keyClass)
Get key.
virtual bool unlockTpm(const char *password, size_t passwordLength, bool usePassword)
Unlock the TPM.
const CFTypeRef getSymKeyType(KeyType keyType)
Convert keyType to MAC OS symmetric key key type.