blob: 94d3bfe6645bb518f36a5547e3e95f3df3e3a72a [file] [log] [blame]
Jeff Thompson2747dc02013-10-04 19:11:34 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
2/**
3 * Copyright (C) 2013 Regents of the University of California.
4 * @author: Yingdi Yu <yingdi@cs.ucla.edu>
5 * See COPYING for copyright and distribution information.
6 */
7
Alexander Afanasyeve2dcdfd2014-02-07 15:53:28 -08008#include "common.hpp"
9
Alexander Afanasyev19508852014-01-29 01:01:51 -080010#include "sec-tpm-osx.hpp"
11
12#include "security/public-key.hpp"
13#include "util/logging.hpp"
Yingdi Yu8dceb1d2014-02-18 12:45:10 -080014#include <cryptopp/files.h>
15#include <cryptopp/asn.h>
Jeff Thompson2747dc02013-10-04 19:11:34 -070016
Yingdi Yu2b2b4792014-02-04 16:27:07 -080017#include <pwd.h>
18#include <unistd.h>
19#include <stdlib.h>
20#include <string.h>
Jeff Thompson2747dc02013-10-04 19:11:34 -070021
Alexander Afanasyev04b22a92014-01-05 22:40:17 -080022#include <CoreFoundation/CoreFoundation.h>
23#include <Security/Security.h>
Yingdi Yu4b752752014-02-18 12:24:03 -080024#include <Security/SecRandom.h>
Alexander Afanasyev04b22a92014-01-05 22:40:17 -080025#include <CoreServices/CoreServices.h>
Jeff Thompson2747dc02013-10-04 19:11:34 -070026
27using namespace std;
Jeff Thompson2747dc02013-10-04 19:11:34 -070028
Yingdi Yu87581582014-01-14 14:28:39 -080029INIT_LOGGER("SecTpmOsx");
Jeff Thompson2747dc02013-10-04 19:11:34 -070030
Yingdi Yufc40d872014-02-18 12:56:04 -080031namespace ndn {
32
Yingdi Yu2b2b4792014-02-04 16:27:07 -080033class SecTpmOsx::Impl {
34public:
35 Impl()
36 {}
Alexander Afanasyev04b22a92014-01-05 22:40:17 -080037
Yingdi Yu2b2b4792014-02-04 16:27:07 -080038 /**
39 * @brief Convert NDN name of a key to internal name of the key.
40 *
Yingdi Yufc40d872014-02-18 12:56:04 -080041 * @param keyName
42 * @param keyClass
Yingdi Yu2b2b4792014-02-04 16:27:07 -080043 * @return the internal key name
44 */
45 std::string
46 toInternalKeyName(const Name & keyName, KeyClass keyClass);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -080047
Yingdi Yu2b2b4792014-02-04 16:27:07 -080048 /**
49 * @brief Get key.
Yingdi Yufc40d872014-02-18 12:56:04 -080050 *
51 * @param keyName
52 * @param keyClass
Yingdi Yu2b2b4792014-02-04 16:27:07 -080053 * @returns pointer to the key
54 */
55 SecKeychainItemRef
56 getKey(const Name & keyName, KeyClass keyClass);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -080057
Yingdi Yu2b2b4792014-02-04 16:27:07 -080058 /**
Yingdi Yufc40d872014-02-18 12:56:04 -080059 * @brief Convert keyType to MAC OS symmetric key key type
60 *
Yingdi Yu2b2b4792014-02-04 16:27:07 -080061 * @param keyType
62 * @returns MAC OS key type
63 */
Yingdi Yu87581582014-01-14 14:28:39 -080064 const CFTypeRef
Yingdi Yu2b2b4792014-02-04 16:27:07 -080065 getSymKeyType(KeyType keyType);
66
67 /**
Yingdi Yufc40d872014-02-18 12:56:04 -080068 * @brief Convert keyType to MAC OS asymmetirc key type
69 *
Yingdi Yu2b2b4792014-02-04 16:27:07 -080070 * @param keyType
71 * @returns MAC OS key type
72 */
Yingdi Yu87581582014-01-14 14:28:39 -080073 const CFTypeRef
Yingdi Yu2b2b4792014-02-04 16:27:07 -080074 getAsymKeyType(KeyType keyType);
75
76 /**
Yingdi Yufc40d872014-02-18 12:56:04 -080077 * @brief Convert keyClass to MAC OS key class
78 *
Yingdi Yu2b2b4792014-02-04 16:27:07 -080079 * @param keyClass
80 * @returns MAC OS key class
81 */
Yingdi Yu87581582014-01-14 14:28:39 -080082 const CFTypeRef
Yingdi Yu2b2b4792014-02-04 16:27:07 -080083 getKeyClass(KeyClass keyClass);
84
85 /**
Yingdi Yufc40d872014-02-18 12:56:04 -080086 * @brief Convert digestAlgo to MAC OS algorithm id
87 *
Yingdi Yu2b2b4792014-02-04 16:27:07 -080088 * @param digestAlgo
89 * @returns MAC OS algorithm id
90 */
Yingdi Yu87581582014-01-14 14:28:39 -080091 const CFStringRef
Yingdi Yu2b2b4792014-02-04 16:27:07 -080092 getDigestAlgorithm(DigestAlgorithm digestAlgo);
93
94 /**
Yingdi Yufc40d872014-02-18 12:56:04 -080095 * @brief Get the digest size of the corresponding algorithm
96 *
97 * @param digestAlgo
Yingdi Yu2b2b4792014-02-04 16:27:07 -080098 * @return digest size
99 */
100 long
101 getDigestSize(DigestAlgorithm digestAlgo);
102
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800103 ///////////////////////////////////////////////
104 // everything here is public, including data //
105 ///////////////////////////////////////////////
106public:
107 SecKeychainRef m_keyChainRef;
108};
109
110
111SecTpmOsx::SecTpmOsx()
112 : m_impl(new Impl)
113{
114 OSStatus res = SecKeychainCopyDefault(&m_impl->m_keyChainRef);
115
116
117 if (res == errSecNoDefaultKeychain) //If no default key chain, create one.
118 {
119 //Get the password for the new key chain.
120 string keyChainName("ndnroot.keychain");
121 cerr << "No Default KeyChain! Create " << keyChainName << ":" << endl;
122 string password;
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800123 while(!getPassWord(password, keyChainName))
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800124 {
125 cerr << "Password mismatch!" << endl;
126 }
127
128 //Create the key chain
129 res = SecKeychainCreate(keyChainName.c_str(), //Keychain path
130 password.size(), //Keychain password length
131 password.c_str(), //Keychain password
132 false, //User prompt
133 NULL, //Initial access of Keychain
134 &m_impl->m_keyChainRef); //Keychain reference
135
136 if(res == errSecSuccess)
137 cerr << keyChainName << " has been created!" << endl;
138 else
139 {
140 char* pw = const_cast<char*>(password.c_str());
141 memset(pw, 0, password.size());
142 throw Error("No default keychain!");
143 }
144
145 //Unlock the default key chain
146 SecKeychainUnlock(m_impl->m_keyChainRef,
147 password.size(),
148 password.c_str(),
149 true);
150
151 char* pw = const_cast<char*>(password.c_str());
152 memset(pw, 0, password.size());
153
154 return;
155 }
156
157 //If the default key chain exists, check if it is unlocked
158 SecKeychainStatus keychainStatus;
159 res = SecKeychainGetStatus(m_impl->m_keyChainRef, &keychainStatus);
160 if(kSecUnlockStateStatus & keychainStatus)
161 return;
162
163
164 //If the default key chain is locked, unlock the key chain
165 bool locked = true;
166 while(locked)
167 {
168 const char* fmt = "Password to unlock the default keychain: ";
169 char* password = NULL;
170 password = getpass(fmt);
171
172 if (!password)
173 {
174 memset(password, 0, strlen(password));
175 continue;
176 }
177
178 res = SecKeychainUnlock(m_impl->m_keyChainRef,
179 strlen(password),
180 password,
181 true);
182
183 memset(password, 0, strlen(password));
184
185 if(res == errSecSuccess)
186 locked = false;
187 }
188}
189
190SecTpmOsx::~SecTpmOsx(){
191 //TODO: implement
192}
193
194void
195SecTpmOsx::generateKeyPairInTpm(const Name & keyName, KeyType keyType, int keySize)
196{
197
198 if(doesKeyExistInTpm(keyName, KEY_CLASS_PUBLIC)){
199 _LOG_DEBUG("keyName has existed");
200 throw Error("keyName has existed");
201 }
202
203 string keyNameUri = m_impl->toInternalKeyName(keyName, KEY_CLASS_PUBLIC);
204
205 SecKeyRef publicKey, privateKey;
206
207 CFStringRef keyLabel = CFStringCreateWithCString(NULL,
208 keyNameUri.c_str(),
209 kCFStringEncodingUTF8);
210
211 CFMutableDictionaryRef attrDict = CFDictionaryCreateMutable(NULL,
212 3,
213 &kCFTypeDictionaryKeyCallBacks,
214 NULL);
215
216 CFDictionaryAddValue(attrDict, kSecAttrKeyType, m_impl->getAsymKeyType(keyType));
217 CFDictionaryAddValue(attrDict, kSecAttrKeySizeInBits, CFNumberCreate(NULL, kCFNumberIntType, &keySize));
218 CFDictionaryAddValue(attrDict, kSecAttrLabel, keyLabel);
219
220 OSStatus res = SecKeyGeneratePair((CFDictionaryRef)attrDict, &publicKey, &privateKey);
221
222 CFRelease(publicKey);
223 CFRelease(privateKey);
224
225 if (res != errSecSuccess){
226 _LOG_DEBUG("Fail to create a key pair: " << res);
227 throw Error("Fail to create a key pair");
228 }
229}
230
231void
232SecTpmOsx::deleteKeyPairInTpm(const Name &keyName)
233{
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800234 CFStringRef keyLabel = CFStringCreateWithCString(NULL,
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800235 keyName.toUri().c_str(),
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800236 kCFStringEncodingUTF8);
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800237
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800238 CFMutableDictionaryRef searchDict =
239 CFDictionaryCreateMutable(NULL, 5, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800240
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800241 CFDictionaryAddValue(searchDict, kSecClass, kSecClassKey);
242 CFDictionaryAddValue(searchDict, kSecAttrLabel, keyLabel);
243 CFDictionaryAddValue(searchDict, kSecMatchLimit, kSecMatchLimitAll);
244 SecItemDelete(searchDict);
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800245}
246
247void
248SecTpmOsx::generateSymmetricKeyInTpm(const Name & keyName, KeyType keyType, int keySize)
249{
250
251 if(doesKeyExistInTpm(keyName, KEY_CLASS_SYMMETRIC))
252 throw Error("keyName has existed!");
253
254 string keyNameUri = m_impl->toInternalKeyName(keyName, KEY_CLASS_SYMMETRIC);
255
256 CFMutableDictionaryRef attrDict = CFDictionaryCreateMutable(kCFAllocatorDefault,
257 0,
258 &kCFTypeDictionaryKeyCallBacks,
259 &kCFTypeDictionaryValueCallBacks);
260
261 CFStringRef keyLabel = CFStringCreateWithCString(NULL,
262 keyNameUri.c_str(),
263 kCFStringEncodingUTF8);
264
265 CFDictionaryAddValue(attrDict, kSecAttrKeyType, m_impl->getSymKeyType(keyType));
266 CFDictionaryAddValue(attrDict, kSecAttrKeySizeInBits, CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &keySize));
267 CFDictionaryAddValue(attrDict, kSecAttrIsPermanent, kCFBooleanTrue);
268 CFDictionaryAddValue(attrDict, kSecAttrLabel, keyLabel);
269
270 CFErrorRef error = NULL;
271
272 SecKeyRef symmetricKey = SecKeyGenerateSymmetric(attrDict, &error);
273
274 if (error)
275 throw Error("Fail to create a symmetric key");
276}
277
278ptr_lib::shared_ptr<PublicKey>
279SecTpmOsx::getPublicKeyFromTpm(const Name & keyName)
280{
281 _LOG_TRACE("OSXPrivateKeyStorage::getPublickey");
282
283 SecKeychainItemRef publicKey = m_impl->getKey(keyName, KEY_CLASS_PUBLIC);
284
285 CFDataRef exportedKey;
286
287 OSStatus res = SecItemExport(publicKey,
288 kSecFormatOpenSSL,
289 0,
290 NULL,
291 &exportedKey);
292
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800293 shared_ptr<PublicKey> key = make_shared<PublicKey>(CFDataGetBytePtr(exportedKey), CFDataGetLength(exportedKey));
294 CFRelease(exportedKey);
295 return key;
296}
297
298ConstBufferPtr
299SecTpmOsx::exportPrivateKeyPkcs1FromTpm(const Name& keyName)
300{
301 using namespace CryptoPP;
302
303 SecKeychainItemRef privateKey = m_impl->getKey(keyName, KEY_CLASS_PRIVATE);
304 CFDataRef exportedKey;
305 OSStatus res = SecItemExport(privateKey,
306 kSecFormatOpenSSL,
307 0,
308 NULL,
309 &exportedKey);
310
311 if(res != errSecSuccess)
312 {
313 return shared_ptr<Buffer>();
314 }
315
316 OBufferStream pkcs1Os;
317 FileSink sink(pkcs1Os);
318
319 uint32_t version = 0;
320 OID algorithm("1.2.840.113549.1.1.1");
321 SecByteBlock rawKeyBits;
322 // PrivateKeyInfo ::= SEQUENCE {
323 // version INTEGER,
324 // privateKeyAlgorithm SEQUENCE,
325 // privateKey OCTECT STRING}
326 DERSequenceEncoder privateKeyInfo(sink);
327 {
328 DEREncodeUnsigned<uint32_t>(privateKeyInfo, version, INTEGER);
329 DERSequenceEncoder privateKeyAlgorithm(privateKeyInfo);
330 {
331 algorithm.encode(privateKeyAlgorithm);
332 DEREncodeNull(privateKeyAlgorithm);
333 }
334 privateKeyAlgorithm.MessageEnd();
335 DEREncodeOctetString(privateKeyInfo, CFDataGetBytePtr(exportedKey), CFDataGetLength(exportedKey));
336 }
337 privateKeyInfo.MessageEnd();
338
339 CFRelease(exportedKey);
340 return pkcs1Os.buf();
341}
342
343bool
344SecTpmOsx::importPrivateKeyPkcs1IntoTpm(const Name& keyName, const uint8_t* buf, size_t size)
345{
346 using namespace CryptoPP;
347
348 StringSource privateKeySource(buf, size, true);
349 uint32_t tmpNum;
350 OID tmpOID;
351 SecByteBlock rawKeyBits;
352 // PrivateKeyInfo ::= SEQUENCE {
353 // INTEGER,
354 // SEQUENCE,
355 // OCTECT STRING}
356 BERSequenceDecoder privateKeyInfo(privateKeySource);
357 {
358 BERDecodeUnsigned<uint32_t>(privateKeyInfo, tmpNum, INTEGER);
359 BERSequenceDecoder sequenceDecoder(privateKeyInfo);
360 {
361 tmpOID.decode(sequenceDecoder);
362 BERDecodeNull(sequenceDecoder);
363 }
364 BERDecodeOctetString(privateKeyInfo, rawKeyBits);
365 }
366 privateKeyInfo.MessageEnd();
367
368 CFDataRef importedKey = CFDataCreateWithBytesNoCopy(NULL,
369 rawKeyBits.BytePtr(),
370 rawKeyBits.size(),
371 kCFAllocatorNull);
372
373 SecExternalFormat externalFormat = kSecFormatOpenSSL;
374 SecExternalItemType externalType = kSecItemTypePrivateKey;
375 SecKeyImportExportParameters keyParams;
376 memset(&keyParams, 0, sizeof(keyParams));
377 keyParams.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
378 keyParams.keyAttributes = CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_PERMANENT;
379 SecAccessRef access;
380 CFStringRef keyLabel = CFStringCreateWithCString(NULL,
381 keyName.toUri().c_str(),
382 kCFStringEncodingUTF8);
383 SecAccessCreate(keyLabel, NULL, &access);
384 keyParams.accessRef = access;
385 CFArrayRef outItems;
386
387 OSStatus res = SecKeychainItemImport (importedKey,
388 NULL,
389 &externalFormat,
390 &externalType,
391 0,
392 &keyParams,
393 m_impl->m_keyChainRef,
394 &outItems);
395
396 if(res != errSecSuccess)
397 {
398 return false;
399 }
400
401 SecKeychainItemRef privateKey = (SecKeychainItemRef)CFArrayGetValueAtIndex(outItems, 0);
402 SecKeychainAttribute attrs[1]; // maximum number of attributes
403 SecKeychainAttributeList attrList = { 0, attrs };
404 string keyUri = keyName.toUri();
405 {
406 attrs[attrList.count].tag = kSecKeyPrintName;
407 attrs[attrList.count].length = keyUri.size();
408 attrs[attrList.count].data = (void *)keyUri.c_str();
409 attrList.count++;
410 }
411
412 res = SecKeychainItemModifyAttributesAndData(privateKey,
413 &attrList,
414 0,
415 NULL);
416
417 if(res != errSecSuccess)
418 {
419 return false;
420 }
421
422 CFRelease(importedKey);
423 return true;
424}
425
426bool
427SecTpmOsx::importPublicKeyPkcs1IntoTpm(const Name& keyName, const uint8_t* buf, size_t size)
428{
429 CFDataRef importedKey = CFDataCreateWithBytesNoCopy(NULL,
430 buf,
431 size,
432 kCFAllocatorNull);
433
434 SecExternalFormat externalFormat = kSecFormatOpenSSL;
435 SecExternalItemType externalType = kSecItemTypePublicKey;
436 CFArrayRef outItems;
437
438 OSStatus res = SecItemImport (importedKey,
439 NULL,
440 &externalFormat,
441 &externalType,
442 0,
443 NULL,
444 m_impl->m_keyChainRef,
445 &outItems);
446
447 if(res != errSecSuccess)
448 return false;
449
450 SecKeychainItemRef publicKey = (SecKeychainItemRef)CFArrayGetValueAtIndex(outItems, 0);
451 SecKeychainAttribute attrs[1]; // maximum number of attributes
452 SecKeychainAttributeList attrList = { 0, attrs };
453 string keyUri = keyName.toUri();
454 {
455 attrs[attrList.count].tag = kSecKeyPrintName;
456 attrs[attrList.count].length = keyUri.size();
457 attrs[attrList.count].data = (void *)keyUri.c_str();
458 attrList.count++;
459 }
460
461 res = SecKeychainItemModifyAttributesAndData(publicKey,
462 &attrList,
463 0,
464 NULL);
465
466 CFRelease(importedKey);
467 return true;
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800468}
469
470Block
471SecTpmOsx::signInTpm(const uint8_t *data, size_t dataLength, const Name& keyName, DigestAlgorithm digestAlgorithm)
472{
473 _LOG_TRACE("OSXPrivateKeyStorage::Sign");
474
475 CFDataRef dataRef = CFDataCreateWithBytesNoCopy(NULL,
476 data,
477 dataLength,
478 kCFAllocatorNull
479 );
480
481 SecKeyRef privateKey = (SecKeyRef)m_impl->getKey(keyName, KEY_CLASS_PRIVATE);
482
483 CFErrorRef error;
484 SecTransformRef signer = SecSignTransformCreate((SecKeyRef)privateKey, &error);
485 if (error) throw Error("Fail to create signer");
486
487 // Set input
488 Boolean set_res = SecTransformSetAttribute(signer,
489 kSecTransformInputAttributeName,
490 dataRef,
491 &error);
492 if (error) throw Error("Fail to configure input of signer");
493
494 // Enable use of padding
495 SecTransformSetAttribute(
496 signer,
497 kSecPaddingKey,
498 kSecPaddingPKCS1Key,
499 &error);
500 if (error) throw Error("Fail to configure digest algorithm of signer");
501
502 // Set padding type
503 set_res = SecTransformSetAttribute(signer,
504 kSecDigestTypeAttribute,
505 m_impl->getDigestAlgorithm(digestAlgorithm),
506 &error);
507 if (error) throw Error("Fail to configure digest algorithm of signer");
508
509 // Set padding attribute
510 long digestSize = m_impl->getDigestSize(digestAlgorithm);
511 set_res = SecTransformSetAttribute(signer,
512 kSecDigestLengthAttribute,
513 CFNumberCreate(NULL, kCFNumberLongType, &digestSize),
514 &error);
515 if (error) throw Error("Fail to configure digest size of signer");
516
517 // Actually sign
518 CFDataRef signature = (CFDataRef) SecTransformExecute(signer, &error);
519 if (error) {
520 CFShow(error);
521 throw Error("Fail to sign data");
522 }
523
524 if (!signature) throw Error("Signature is NULL!\n");
525
526 return Block(Tlv::SignatureValue,
527 ptr_lib::make_shared<Buffer>(CFDataGetBytePtr(signature), CFDataGetLength(signature)));
528}
529
530ConstBufferPtr
Yingdi Yufc40d872014-02-18 12:56:04 -0800531SecTpmOsx::decryptInTpm(const uint8_t* data, size_t dataLength, const Name & keyName, bool sym)
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800532{
533 _LOG_TRACE("OSXPrivateKeyStorage::Decrypt");
534
535 KeyClass keyClass;
536 if(sym)
537 keyClass = KEY_CLASS_SYMMETRIC;
538 else
539 keyClass = KEY_CLASS_PRIVATE;
540
541 CFDataRef dataRef = CFDataCreate(NULL,
542 reinterpret_cast<const unsigned char*>(data),
543 dataLength
544 );
545
546 // _LOG_DEBUG("CreateData");
547
548 SecKeyRef decryptKey = (SecKeyRef)m_impl->getKey(keyName, keyClass);
549
550 // _LOG_DEBUG("GetKey");
551
552 CFErrorRef error;
553 SecTransformRef decrypt = SecDecryptTransformCreate(decryptKey, &error);
554 if (error) throw Error("Fail to create decrypt");
555
556 Boolean set_res = SecTransformSetAttribute(decrypt,
557 kSecTransformInputAttributeName,
558 dataRef,
559 &error);
560 if (error) throw Error("Fail to configure decrypt");
561
562 CFDataRef output = (CFDataRef) SecTransformExecute(decrypt, &error);
563 if (error)
564 {
565 CFShow(error);
566 throw Error("Fail to decrypt data");
567 }
568 if (!output) throw Error("Output is NULL!\n");
569
570 return ptr_lib::make_shared<Buffer>(CFDataGetBytePtr(output), CFDataGetLength(output));
571}
572
573bool
574SecTpmOsx::setACL(const Name & keyName, KeyClass keyClass, int acl, const string & appPath)
575{
576 SecKeychainItemRef privateKey = m_impl->getKey(keyName, keyClass);
577
578 SecAccessRef accRef;
579 OSStatus acc_res = SecKeychainItemCopyAccess(privateKey, &accRef);
580
581 CFArrayRef signACL = SecAccessCopyMatchingACLList(accRef,
582 kSecACLAuthorizationSign);
583
584 SecACLRef aclRef = (SecACLRef) CFArrayGetValueAtIndex(signACL, 0);
585
586 CFArrayRef appList;
587 CFStringRef description;
588 SecKeychainPromptSelector promptSelector;
589 OSStatus acl_res = SecACLCopyContents(aclRef,
590 &appList,
591 &description,
592 &promptSelector);
593
594 CFMutableArrayRef newAppList = CFArrayCreateMutableCopy(NULL,
595 0,
596 appList);
597
598 SecTrustedApplicationRef trustedApp;
599 acl_res = SecTrustedApplicationCreateFromPath(appPath.c_str(),
600 &trustedApp);
601
602 CFArrayAppendValue(newAppList, trustedApp);
603
604
605 CFArrayRef authList = SecACLCopyAuthorizations(aclRef);
606
607 acl_res = SecACLRemove(aclRef);
608
609 SecACLRef newACL;
610 acl_res = SecACLCreateWithSimpleContents(accRef,
611 newAppList,
612 description,
613 promptSelector,
614 &newACL);
615
616 acl_res = SecACLUpdateAuthorizations(newACL, authList);
617
618 acc_res = SecKeychainItemSetAccess(privateKey, accRef);
619
620 return true;
621}
622
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800623ConstBufferPtr
Yingdi Yufc40d872014-02-18 12:56:04 -0800624SecTpmOsx::encryptInTpm(const uint8_t* data, size_t dataLength, const Name & keyName, bool sym)
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800625{
626 _LOG_TRACE("OSXPrivateKeyStorage::Encrypt");
627
628 KeyClass keyClass;
629 if(sym)
630 keyClass = KEY_CLASS_SYMMETRIC;
631 else
632 keyClass = KEY_CLASS_PUBLIC;
633
634 CFDataRef dataRef = CFDataCreate(NULL,
635 reinterpret_cast<const unsigned char*>(data),
636 dataLength
637 );
638
639 SecKeyRef encryptKey = (SecKeyRef)m_impl->getKey(keyName, keyClass);
640
641 CFErrorRef error;
642 SecTransformRef encrypt = SecEncryptTransformCreate(encryptKey, &error);
643 if (error) throw Error("Fail to create encrypt");
644
645 Boolean set_res = SecTransformSetAttribute(encrypt,
646 kSecTransformInputAttributeName,
647 dataRef,
648 &error);
649 if (error) throw Error("Fail to configure encrypt");
650
651 CFDataRef output = (CFDataRef) SecTransformExecute(encrypt, &error);
652 if (error) throw Error("Fail to encrypt data");
653
654 if (!output) throw Error("Output is NULL!\n");
655
656 return ptr_lib::make_shared<Buffer> (CFDataGetBytePtr(output), CFDataGetLength(output));
657}
658
659bool
660SecTpmOsx::doesKeyExistInTpm(const Name & keyName, KeyClass keyClass)
661{
662 _LOG_TRACE("OSXPrivateKeyStorage::doesKeyExist");
663
664 string keyNameUri = m_impl->toInternalKeyName(keyName, keyClass);
665
666 CFStringRef keyLabel = CFStringCreateWithCString(NULL,
667 keyNameUri.c_str(),
668 kCFStringEncodingUTF8);
669
670 CFMutableDictionaryRef attrDict = CFDictionaryCreateMutable(NULL,
671 4,
672 &kCFTypeDictionaryKeyCallBacks,
673 NULL);
674
675 CFDictionaryAddValue(attrDict, kSecClass, kSecClassKey);
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800676 // CFDictionaryAddValue(attrDict, kSecAttrKeyClass, m_impl->getKeyClass(keyClass));
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800677 CFDictionaryAddValue(attrDict, kSecAttrLabel, keyLabel);
678 CFDictionaryAddValue(attrDict, kSecReturnRef, kCFBooleanTrue);
679
680 SecKeychainItemRef itemRef;
681 OSStatus res = SecItemCopyMatching((CFDictionaryRef)attrDict, (CFTypeRef*)&itemRef);
682
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800683 if(res == errSecSuccess)
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800684 return true;
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800685 else
686 return false;
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800687
688}
689
Yingdi Yu4b752752014-02-18 12:24:03 -0800690bool
691SecTpmOsx::generateRandomBlock(uint8_t* res, size_t size)
692{
693 return (SecRandomCopyBytes(kSecRandomDefault, size, res) == 0);
694}
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800695
696////////////////////////////////
697// OSXPrivateKeyStorage::Impl //
698////////////////////////////////
699
700SecKeychainItemRef
701SecTpmOsx::Impl::getKey(const Name & keyName, KeyClass keyClass)
702{
703 string keyNameUri = toInternalKeyName(keyName, keyClass);
704
705 CFStringRef keyLabel = CFStringCreateWithCString(NULL,
706 keyNameUri.c_str(),
707 kCFStringEncodingUTF8);
708
709 CFMutableDictionaryRef attrDict = CFDictionaryCreateMutable(NULL,
710 5,
711 &kCFTypeDictionaryKeyCallBacks,
712 NULL);
713
714 CFDictionaryAddValue(attrDict, kSecClass, kSecClassKey);
715 CFDictionaryAddValue(attrDict, kSecAttrLabel, keyLabel);
716 CFDictionaryAddValue(attrDict, kSecAttrKeyClass, getKeyClass(keyClass));
717 CFDictionaryAddValue(attrDict, kSecReturnRef, kCFBooleanTrue);
718
719 SecKeychainItemRef keyItem;
720
721 OSStatus res = SecItemCopyMatching((CFDictionaryRef) attrDict, (CFTypeRef*)&keyItem);
722
723 if(res != errSecSuccess){
724 _LOG_DEBUG("Fail to find the key!");
725 return NULL;
726 }
727 else
728 return keyItem;
729}
730
731string
732SecTpmOsx::Impl::toInternalKeyName(const Name & keyName, KeyClass keyClass)
733{
734 string keyUri = keyName.toUri();
735
736 if(KEY_CLASS_SYMMETRIC == keyClass)
737 return keyUri + "/symmetric";
738 else
739 return keyUri;
740}
741
742const CFTypeRef
743SecTpmOsx::Impl::getAsymKeyType(KeyType keyType)
744{
745 switch(keyType){
746 case KEY_TYPE_RSA:
747 return kSecAttrKeyTypeRSA;
748 default:
749 _LOG_DEBUG("Unrecognized key type!")
750 return NULL;
751 }
752}
753
754const CFTypeRef
755SecTpmOsx::Impl::getSymKeyType(KeyType keyType)
756{
757 switch(keyType){
758 case KEY_TYPE_AES:
759 return kSecAttrKeyTypeAES;
760 default:
761 _LOG_DEBUG("Unrecognized key type!")
762 return NULL;
763 }
764}
765
766const CFTypeRef
767SecTpmOsx::Impl::getKeyClass(KeyClass keyClass)
768{
769 switch(keyClass){
770 case KEY_CLASS_PRIVATE:
771 return kSecAttrKeyClassPrivate;
772 case KEY_CLASS_PUBLIC:
773 return kSecAttrKeyClassPublic;
774 case KEY_CLASS_SYMMETRIC:
775 return kSecAttrKeyClassSymmetric;
776 default:
777 _LOG_DEBUG("Unrecognized key class!");
778 return NULL;
779 }
780}
781
782const CFStringRef
783SecTpmOsx::Impl::getDigestAlgorithm(DigestAlgorithm digestAlgo)
784{
785 switch(digestAlgo){
Jeff Thompson2747dc02013-10-04 19:11:34 -0700786 // case DIGEST_MD2:
787 // return kSecDigestMD2;
788 // case DIGEST_MD5:
789 // return kSecDigestMD5;
790 // case DIGEST_SHA1:
791 // return kSecDigestSHA1;
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800792 case DIGEST_ALGORITHM_SHA256:
793 return kSecDigestSHA2;
794 default:
795 _LOG_DEBUG("Unrecognized digest algorithm!");
796 return NULL;
Jeff Thompson2747dc02013-10-04 19:11:34 -0700797 }
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800798}
Jeff Thompson2747dc02013-10-04 19:11:34 -0700799
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800800long
801SecTpmOsx::Impl::getDigestSize(DigestAlgorithm digestAlgo)
802{
803 switch(digestAlgo){
804 case DIGEST_ALGORITHM_SHA256:
805 return 256;
Jeff Thompson2747dc02013-10-04 19:11:34 -0700806 // case DIGEST_SHA1:
807 // case DIGEST_MD2:
808 // case DIGEST_MD5:
809 // return 0;
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800810 default:
811 _LOG_DEBUG("Unrecognized digest algorithm! Unknown digest size");
812 return -1;
Jeff Thompson2747dc02013-10-04 19:11:34 -0700813 }
Jeff Thompson2747dc02013-10-04 19:11:34 -0700814}
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800815
Yingdi Yufc40d872014-02-18 12:56:04 -0800816} // namespace ndn