blob: d85636da13c4ba1752bab2ad734875c0876031b6 [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
31namespace 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 *
41 * @param keyName the NDN name of the key
42 * @param keyClass the class of the key
43 * @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.
50 * @param keyName the name of the key
51 * @param keyClass the class of the key
52 * @returns pointer to the key
53 */
54 SecKeychainItemRef
55 getKey(const Name & keyName, KeyClass keyClass);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -080056
Yingdi Yu2b2b4792014-02-04 16:27:07 -080057 /**
58 * convert keyType to MAC OS symmetric key key type
59 * @param keyType
60 * @returns MAC OS key type
61 */
Yingdi Yu87581582014-01-14 14:28:39 -080062 const CFTypeRef
Yingdi Yu2b2b4792014-02-04 16:27:07 -080063 getSymKeyType(KeyType keyType);
64
65 /**
66 * convert keyType to MAC OS asymmetirc key type
67 * @param keyType
68 * @returns MAC OS key type
69 */
Yingdi Yu87581582014-01-14 14:28:39 -080070 const CFTypeRef
Yingdi Yu2b2b4792014-02-04 16:27:07 -080071 getAsymKeyType(KeyType keyType);
72
73 /**
74 * convert keyClass to MAC OS key class
75 * @param keyClass
76 * @returns MAC OS key class
77 */
Yingdi Yu87581582014-01-14 14:28:39 -080078 const CFTypeRef
Yingdi Yu2b2b4792014-02-04 16:27:07 -080079 getKeyClass(KeyClass keyClass);
80
81 /**
82 * convert digestAlgo to MAC OS algorithm id
83 * @param digestAlgo
84 * @returns MAC OS algorithm id
85 */
Yingdi Yu87581582014-01-14 14:28:39 -080086 const CFStringRef
Yingdi Yu2b2b4792014-02-04 16:27:07 -080087 getDigestAlgorithm(DigestAlgorithm digestAlgo);
88
89 /**
90 * get the digest size of the corresponding algorithm
91 * @param digestAlgo the digest algorithm
92 * @return digest size
93 */
94 long
95 getDigestSize(DigestAlgorithm digestAlgo);
96
Yingdi Yu2b2b4792014-02-04 16:27:07 -080097 ///////////////////////////////////////////////
98 // everything here is public, including data //
99 ///////////////////////////////////////////////
100public:
101 SecKeychainRef m_keyChainRef;
102};
103
104
105SecTpmOsx::SecTpmOsx()
106 : m_impl(new Impl)
107{
108 OSStatus res = SecKeychainCopyDefault(&m_impl->m_keyChainRef);
109
110
111 if (res == errSecNoDefaultKeychain) //If no default key chain, create one.
112 {
113 //Get the password for the new key chain.
114 string keyChainName("ndnroot.keychain");
115 cerr << "No Default KeyChain! Create " << keyChainName << ":" << endl;
116 string password;
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800117 while(!getPassWord(password, keyChainName))
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800118 {
119 cerr << "Password mismatch!" << endl;
120 }
121
122 //Create the key chain
123 res = SecKeychainCreate(keyChainName.c_str(), //Keychain path
124 password.size(), //Keychain password length
125 password.c_str(), //Keychain password
126 false, //User prompt
127 NULL, //Initial access of Keychain
128 &m_impl->m_keyChainRef); //Keychain reference
129
130 if(res == errSecSuccess)
131 cerr << keyChainName << " has been created!" << endl;
132 else
133 {
134 char* pw = const_cast<char*>(password.c_str());
135 memset(pw, 0, password.size());
136 throw Error("No default keychain!");
137 }
138
139 //Unlock the default key chain
140 SecKeychainUnlock(m_impl->m_keyChainRef,
141 password.size(),
142 password.c_str(),
143 true);
144
145 char* pw = const_cast<char*>(password.c_str());
146 memset(pw, 0, password.size());
147
148 return;
149 }
150
151 //If the default key chain exists, check if it is unlocked
152 SecKeychainStatus keychainStatus;
153 res = SecKeychainGetStatus(m_impl->m_keyChainRef, &keychainStatus);
154 if(kSecUnlockStateStatus & keychainStatus)
155 return;
156
157
158 //If the default key chain is locked, unlock the key chain
159 bool locked = true;
160 while(locked)
161 {
162 const char* fmt = "Password to unlock the default keychain: ";
163 char* password = NULL;
164 password = getpass(fmt);
165
166 if (!password)
167 {
168 memset(password, 0, strlen(password));
169 continue;
170 }
171
172 res = SecKeychainUnlock(m_impl->m_keyChainRef,
173 strlen(password),
174 password,
175 true);
176
177 memset(password, 0, strlen(password));
178
179 if(res == errSecSuccess)
180 locked = false;
181 }
182}
183
184SecTpmOsx::~SecTpmOsx(){
185 //TODO: implement
186}
187
188void
189SecTpmOsx::generateKeyPairInTpm(const Name & keyName, KeyType keyType, int keySize)
190{
191
192 if(doesKeyExistInTpm(keyName, KEY_CLASS_PUBLIC)){
193 _LOG_DEBUG("keyName has existed");
194 throw Error("keyName has existed");
195 }
196
197 string keyNameUri = m_impl->toInternalKeyName(keyName, KEY_CLASS_PUBLIC);
198
199 SecKeyRef publicKey, privateKey;
200
201 CFStringRef keyLabel = CFStringCreateWithCString(NULL,
202 keyNameUri.c_str(),
203 kCFStringEncodingUTF8);
204
205 CFMutableDictionaryRef attrDict = CFDictionaryCreateMutable(NULL,
206 3,
207 &kCFTypeDictionaryKeyCallBacks,
208 NULL);
209
210 CFDictionaryAddValue(attrDict, kSecAttrKeyType, m_impl->getAsymKeyType(keyType));
211 CFDictionaryAddValue(attrDict, kSecAttrKeySizeInBits, CFNumberCreate(NULL, kCFNumberIntType, &keySize));
212 CFDictionaryAddValue(attrDict, kSecAttrLabel, keyLabel);
213
214 OSStatus res = SecKeyGeneratePair((CFDictionaryRef)attrDict, &publicKey, &privateKey);
215
216 CFRelease(publicKey);
217 CFRelease(privateKey);
218
219 if (res != errSecSuccess){
220 _LOG_DEBUG("Fail to create a key pair: " << res);
221 throw Error("Fail to create a key pair");
222 }
223}
224
225void
226SecTpmOsx::deleteKeyPairInTpm(const Name &keyName)
227{
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800228 CFStringRef keyLabel = CFStringCreateWithCString(NULL,
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800229 keyName.toUri().c_str(),
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800230 kCFStringEncodingUTF8);
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800231
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800232 CFMutableDictionaryRef searchDict =
233 CFDictionaryCreateMutable(NULL, 5, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800234
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800235 CFDictionaryAddValue(searchDict, kSecClass, kSecClassKey);
236 CFDictionaryAddValue(searchDict, kSecAttrLabel, keyLabel);
237 CFDictionaryAddValue(searchDict, kSecMatchLimit, kSecMatchLimitAll);
238 SecItemDelete(searchDict);
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800239}
240
241void
242SecTpmOsx::generateSymmetricKeyInTpm(const Name & keyName, KeyType keyType, int keySize)
243{
244
245 if(doesKeyExistInTpm(keyName, KEY_CLASS_SYMMETRIC))
246 throw Error("keyName has existed!");
247
248 string keyNameUri = m_impl->toInternalKeyName(keyName, KEY_CLASS_SYMMETRIC);
249
250 CFMutableDictionaryRef attrDict = CFDictionaryCreateMutable(kCFAllocatorDefault,
251 0,
252 &kCFTypeDictionaryKeyCallBacks,
253 &kCFTypeDictionaryValueCallBacks);
254
255 CFStringRef keyLabel = CFStringCreateWithCString(NULL,
256 keyNameUri.c_str(),
257 kCFStringEncodingUTF8);
258
259 CFDictionaryAddValue(attrDict, kSecAttrKeyType, m_impl->getSymKeyType(keyType));
260 CFDictionaryAddValue(attrDict, kSecAttrKeySizeInBits, CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &keySize));
261 CFDictionaryAddValue(attrDict, kSecAttrIsPermanent, kCFBooleanTrue);
262 CFDictionaryAddValue(attrDict, kSecAttrLabel, keyLabel);
263
264 CFErrorRef error = NULL;
265
266 SecKeyRef symmetricKey = SecKeyGenerateSymmetric(attrDict, &error);
267
268 if (error)
269 throw Error("Fail to create a symmetric key");
270}
271
272ptr_lib::shared_ptr<PublicKey>
273SecTpmOsx::getPublicKeyFromTpm(const Name & keyName)
274{
275 _LOG_TRACE("OSXPrivateKeyStorage::getPublickey");
276
277 SecKeychainItemRef publicKey = m_impl->getKey(keyName, KEY_CLASS_PUBLIC);
278
279 CFDataRef exportedKey;
280
281 OSStatus res = SecItemExport(publicKey,
282 kSecFormatOpenSSL,
283 0,
284 NULL,
285 &exportedKey);
286
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800287 shared_ptr<PublicKey> key = make_shared<PublicKey>(CFDataGetBytePtr(exportedKey), CFDataGetLength(exportedKey));
288 CFRelease(exportedKey);
289 return key;
290}
291
292ConstBufferPtr
293SecTpmOsx::exportPrivateKeyPkcs1FromTpm(const Name& keyName)
294{
295 using namespace CryptoPP;
296
297 SecKeychainItemRef privateKey = m_impl->getKey(keyName, KEY_CLASS_PRIVATE);
298 CFDataRef exportedKey;
299 OSStatus res = SecItemExport(privateKey,
300 kSecFormatOpenSSL,
301 0,
302 NULL,
303 &exportedKey);
304
305 if(res != errSecSuccess)
306 {
307 return shared_ptr<Buffer>();
308 }
309
310 OBufferStream pkcs1Os;
311 FileSink sink(pkcs1Os);
312
313 uint32_t version = 0;
314 OID algorithm("1.2.840.113549.1.1.1");
315 SecByteBlock rawKeyBits;
316 // PrivateKeyInfo ::= SEQUENCE {
317 // version INTEGER,
318 // privateKeyAlgorithm SEQUENCE,
319 // privateKey OCTECT STRING}
320 DERSequenceEncoder privateKeyInfo(sink);
321 {
322 DEREncodeUnsigned<uint32_t>(privateKeyInfo, version, INTEGER);
323 DERSequenceEncoder privateKeyAlgorithm(privateKeyInfo);
324 {
325 algorithm.encode(privateKeyAlgorithm);
326 DEREncodeNull(privateKeyAlgorithm);
327 }
328 privateKeyAlgorithm.MessageEnd();
329 DEREncodeOctetString(privateKeyInfo, CFDataGetBytePtr(exportedKey), CFDataGetLength(exportedKey));
330 }
331 privateKeyInfo.MessageEnd();
332
333 CFRelease(exportedKey);
334 return pkcs1Os.buf();
335}
336
337bool
338SecTpmOsx::importPrivateKeyPkcs1IntoTpm(const Name& keyName, const uint8_t* buf, size_t size)
339{
340 using namespace CryptoPP;
341
342 StringSource privateKeySource(buf, size, true);
343 uint32_t tmpNum;
344 OID tmpOID;
345 SecByteBlock rawKeyBits;
346 // PrivateKeyInfo ::= SEQUENCE {
347 // INTEGER,
348 // SEQUENCE,
349 // OCTECT STRING}
350 BERSequenceDecoder privateKeyInfo(privateKeySource);
351 {
352 BERDecodeUnsigned<uint32_t>(privateKeyInfo, tmpNum, INTEGER);
353 BERSequenceDecoder sequenceDecoder(privateKeyInfo);
354 {
355 tmpOID.decode(sequenceDecoder);
356 BERDecodeNull(sequenceDecoder);
357 }
358 BERDecodeOctetString(privateKeyInfo, rawKeyBits);
359 }
360 privateKeyInfo.MessageEnd();
361
362 CFDataRef importedKey = CFDataCreateWithBytesNoCopy(NULL,
363 rawKeyBits.BytePtr(),
364 rawKeyBits.size(),
365 kCFAllocatorNull);
366
367 SecExternalFormat externalFormat = kSecFormatOpenSSL;
368 SecExternalItemType externalType = kSecItemTypePrivateKey;
369 SecKeyImportExportParameters keyParams;
370 memset(&keyParams, 0, sizeof(keyParams));
371 keyParams.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
372 keyParams.keyAttributes = CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_PERMANENT;
373 SecAccessRef access;
374 CFStringRef keyLabel = CFStringCreateWithCString(NULL,
375 keyName.toUri().c_str(),
376 kCFStringEncodingUTF8);
377 SecAccessCreate(keyLabel, NULL, &access);
378 keyParams.accessRef = access;
379 CFArrayRef outItems;
380
381 OSStatus res = SecKeychainItemImport (importedKey,
382 NULL,
383 &externalFormat,
384 &externalType,
385 0,
386 &keyParams,
387 m_impl->m_keyChainRef,
388 &outItems);
389
390 if(res != errSecSuccess)
391 {
392 return false;
393 }
394
395 SecKeychainItemRef privateKey = (SecKeychainItemRef)CFArrayGetValueAtIndex(outItems, 0);
396 SecKeychainAttribute attrs[1]; // maximum number of attributes
397 SecKeychainAttributeList attrList = { 0, attrs };
398 string keyUri = keyName.toUri();
399 {
400 attrs[attrList.count].tag = kSecKeyPrintName;
401 attrs[attrList.count].length = keyUri.size();
402 attrs[attrList.count].data = (void *)keyUri.c_str();
403 attrList.count++;
404 }
405
406 res = SecKeychainItemModifyAttributesAndData(privateKey,
407 &attrList,
408 0,
409 NULL);
410
411 if(res != errSecSuccess)
412 {
413 return false;
414 }
415
416 CFRelease(importedKey);
417 return true;
418}
419
420bool
421SecTpmOsx::importPublicKeyPkcs1IntoTpm(const Name& keyName, const uint8_t* buf, size_t size)
422{
423 CFDataRef importedKey = CFDataCreateWithBytesNoCopy(NULL,
424 buf,
425 size,
426 kCFAllocatorNull);
427
428 SecExternalFormat externalFormat = kSecFormatOpenSSL;
429 SecExternalItemType externalType = kSecItemTypePublicKey;
430 CFArrayRef outItems;
431
432 OSStatus res = SecItemImport (importedKey,
433 NULL,
434 &externalFormat,
435 &externalType,
436 0,
437 NULL,
438 m_impl->m_keyChainRef,
439 &outItems);
440
441 if(res != errSecSuccess)
442 return false;
443
444 SecKeychainItemRef publicKey = (SecKeychainItemRef)CFArrayGetValueAtIndex(outItems, 0);
445 SecKeychainAttribute attrs[1]; // maximum number of attributes
446 SecKeychainAttributeList attrList = { 0, attrs };
447 string keyUri = keyName.toUri();
448 {
449 attrs[attrList.count].tag = kSecKeyPrintName;
450 attrs[attrList.count].length = keyUri.size();
451 attrs[attrList.count].data = (void *)keyUri.c_str();
452 attrList.count++;
453 }
454
455 res = SecKeychainItemModifyAttributesAndData(publicKey,
456 &attrList,
457 0,
458 NULL);
459
460 CFRelease(importedKey);
461 return true;
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800462}
463
464Block
465SecTpmOsx::signInTpm(const uint8_t *data, size_t dataLength, const Name& keyName, DigestAlgorithm digestAlgorithm)
466{
467 _LOG_TRACE("OSXPrivateKeyStorage::Sign");
468
469 CFDataRef dataRef = CFDataCreateWithBytesNoCopy(NULL,
470 data,
471 dataLength,
472 kCFAllocatorNull
473 );
474
475 SecKeyRef privateKey = (SecKeyRef)m_impl->getKey(keyName, KEY_CLASS_PRIVATE);
476
477 CFErrorRef error;
478 SecTransformRef signer = SecSignTransformCreate((SecKeyRef)privateKey, &error);
479 if (error) throw Error("Fail to create signer");
480
481 // Set input
482 Boolean set_res = SecTransformSetAttribute(signer,
483 kSecTransformInputAttributeName,
484 dataRef,
485 &error);
486 if (error) throw Error("Fail to configure input of signer");
487
488 // Enable use of padding
489 SecTransformSetAttribute(
490 signer,
491 kSecPaddingKey,
492 kSecPaddingPKCS1Key,
493 &error);
494 if (error) throw Error("Fail to configure digest algorithm of signer");
495
496 // Set padding type
497 set_res = SecTransformSetAttribute(signer,
498 kSecDigestTypeAttribute,
499 m_impl->getDigestAlgorithm(digestAlgorithm),
500 &error);
501 if (error) throw Error("Fail to configure digest algorithm of signer");
502
503 // Set padding attribute
504 long digestSize = m_impl->getDigestSize(digestAlgorithm);
505 set_res = SecTransformSetAttribute(signer,
506 kSecDigestLengthAttribute,
507 CFNumberCreate(NULL, kCFNumberLongType, &digestSize),
508 &error);
509 if (error) throw Error("Fail to configure digest size of signer");
510
511 // Actually sign
512 CFDataRef signature = (CFDataRef) SecTransformExecute(signer, &error);
513 if (error) {
514 CFShow(error);
515 throw Error("Fail to sign data");
516 }
517
518 if (!signature) throw Error("Signature is NULL!\n");
519
520 return Block(Tlv::SignatureValue,
521 ptr_lib::make_shared<Buffer>(CFDataGetBytePtr(signature), CFDataGetLength(signature)));
522}
523
524ConstBufferPtr
525SecTpmOsx::decryptInTpm(const Name & keyName, const uint8_t* data, size_t dataLength, bool sym)
526{
527 _LOG_TRACE("OSXPrivateKeyStorage::Decrypt");
528
529 KeyClass keyClass;
530 if(sym)
531 keyClass = KEY_CLASS_SYMMETRIC;
532 else
533 keyClass = KEY_CLASS_PRIVATE;
534
535 CFDataRef dataRef = CFDataCreate(NULL,
536 reinterpret_cast<const unsigned char*>(data),
537 dataLength
538 );
539
540 // _LOG_DEBUG("CreateData");
541
542 SecKeyRef decryptKey = (SecKeyRef)m_impl->getKey(keyName, keyClass);
543
544 // _LOG_DEBUG("GetKey");
545
546 CFErrorRef error;
547 SecTransformRef decrypt = SecDecryptTransformCreate(decryptKey, &error);
548 if (error) throw Error("Fail to create decrypt");
549
550 Boolean set_res = SecTransformSetAttribute(decrypt,
551 kSecTransformInputAttributeName,
552 dataRef,
553 &error);
554 if (error) throw Error("Fail to configure decrypt");
555
556 CFDataRef output = (CFDataRef) SecTransformExecute(decrypt, &error);
557 if (error)
558 {
559 CFShow(error);
560 throw Error("Fail to decrypt data");
561 }
562 if (!output) throw Error("Output is NULL!\n");
563
564 return ptr_lib::make_shared<Buffer>(CFDataGetBytePtr(output), CFDataGetLength(output));
565}
566
567bool
568SecTpmOsx::setACL(const Name & keyName, KeyClass keyClass, int acl, const string & appPath)
569{
570 SecKeychainItemRef privateKey = m_impl->getKey(keyName, keyClass);
571
572 SecAccessRef accRef;
573 OSStatus acc_res = SecKeychainItemCopyAccess(privateKey, &accRef);
574
575 CFArrayRef signACL = SecAccessCopyMatchingACLList(accRef,
576 kSecACLAuthorizationSign);
577
578 SecACLRef aclRef = (SecACLRef) CFArrayGetValueAtIndex(signACL, 0);
579
580 CFArrayRef appList;
581 CFStringRef description;
582 SecKeychainPromptSelector promptSelector;
583 OSStatus acl_res = SecACLCopyContents(aclRef,
584 &appList,
585 &description,
586 &promptSelector);
587
588 CFMutableArrayRef newAppList = CFArrayCreateMutableCopy(NULL,
589 0,
590 appList);
591
592 SecTrustedApplicationRef trustedApp;
593 acl_res = SecTrustedApplicationCreateFromPath(appPath.c_str(),
594 &trustedApp);
595
596 CFArrayAppendValue(newAppList, trustedApp);
597
598
599 CFArrayRef authList = SecACLCopyAuthorizations(aclRef);
600
601 acl_res = SecACLRemove(aclRef);
602
603 SecACLRef newACL;
604 acl_res = SecACLCreateWithSimpleContents(accRef,
605 newAppList,
606 description,
607 promptSelector,
608 &newACL);
609
610 acl_res = SecACLUpdateAuthorizations(newACL, authList);
611
612 acc_res = SecKeychainItemSetAccess(privateKey, accRef);
613
614 return true;
615}
616
617// bool
618// OSXPrivateKeyStorage::verifyData(const Name & keyName, const Blob & pData, const Blob & pSig, DigestAlgorithm digestAlgo)
619// {
620// _LOG_TRACE("OSXPrivateKeyStorage::Verify");
621
622// CFDataRef dataRef = CFDataCreate(NULL,
623// reinterpret_cast<const unsigned char*>(pData.buf()),
624// pData.size());
625
626// CFDataRef sigRef = CFDataCreate(NULL,
627// reinterpret_cast<const unsigned char*>(pSig.buf()),
628// pSig.size());
629
630// SecKeyRef publicKey = (SecKeyRef)m_impl->getKey(keyName, KEY_CLASS_PUBLIC);
631
632// CFErrorRef error;
633// SecTransformRef verifier = SecVerifyTransformCreate(publicKey, sigRef, &error);
634// if (error) throw Error("Fail to create verifier");
635
636// Boolean set_res = SecTransformSetAttribute(verifier,
637// kSecTransformInputAttributeName,
638// dataRef,
639// &error);
640// if (error) throw Error("Fail to configure input of verifier");
641
642// set_res = SecTransformSetAttribute(verifier,
643// kSecDigestTypeAttribute,
644// m_impl->getDigestAlgorithm(digestAlgo),
645// &error);
646// if (error) throw Error("Fail to configure digest algorithm of verifier");
647
648// long digestSize = m_impl->getDigestSize(digestAlgo);
649// set_res = SecTransformSetAttribute(verifier,
650// kSecDigestLengthAttribute,
651// CFNumberCreate(NULL, kCFNumberLongType, &digestSize),
652// &error);
653// if (error) throw Error("Fail to configure digest size of verifier");
654
655// CFBooleanRef result = (CFBooleanRef) SecTransformExecute(verifier, &error);
656// if (error) throw Error("Fail to verify data");
657
658// if (result == kCFBooleanTrue)
659// return true;
660// else
661// return false;
662// }
663
664ConstBufferPtr
665SecTpmOsx::encryptInTpm(const Name & keyName, const uint8_t* data, size_t dataLength, bool sym)
666{
667 _LOG_TRACE("OSXPrivateKeyStorage::Encrypt");
668
669 KeyClass keyClass;
670 if(sym)
671 keyClass = KEY_CLASS_SYMMETRIC;
672 else
673 keyClass = KEY_CLASS_PUBLIC;
674
675 CFDataRef dataRef = CFDataCreate(NULL,
676 reinterpret_cast<const unsigned char*>(data),
677 dataLength
678 );
679
680 SecKeyRef encryptKey = (SecKeyRef)m_impl->getKey(keyName, keyClass);
681
682 CFErrorRef error;
683 SecTransformRef encrypt = SecEncryptTransformCreate(encryptKey, &error);
684 if (error) throw Error("Fail to create encrypt");
685
686 Boolean set_res = SecTransformSetAttribute(encrypt,
687 kSecTransformInputAttributeName,
688 dataRef,
689 &error);
690 if (error) throw Error("Fail to configure encrypt");
691
692 CFDataRef output = (CFDataRef) SecTransformExecute(encrypt, &error);
693 if (error) throw Error("Fail to encrypt data");
694
695 if (!output) throw Error("Output is NULL!\n");
696
697 return ptr_lib::make_shared<Buffer> (CFDataGetBytePtr(output), CFDataGetLength(output));
698}
699
700bool
701SecTpmOsx::doesKeyExistInTpm(const Name & keyName, KeyClass keyClass)
702{
703 _LOG_TRACE("OSXPrivateKeyStorage::doesKeyExist");
704
705 string keyNameUri = m_impl->toInternalKeyName(keyName, keyClass);
706
707 CFStringRef keyLabel = CFStringCreateWithCString(NULL,
708 keyNameUri.c_str(),
709 kCFStringEncodingUTF8);
710
711 CFMutableDictionaryRef attrDict = CFDictionaryCreateMutable(NULL,
712 4,
713 &kCFTypeDictionaryKeyCallBacks,
714 NULL);
715
716 CFDictionaryAddValue(attrDict, kSecClass, kSecClassKey);
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800717 // CFDictionaryAddValue(attrDict, kSecAttrKeyClass, m_impl->getKeyClass(keyClass));
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800718 CFDictionaryAddValue(attrDict, kSecAttrLabel, keyLabel);
719 CFDictionaryAddValue(attrDict, kSecReturnRef, kCFBooleanTrue);
720
721 SecKeychainItemRef itemRef;
722 OSStatus res = SecItemCopyMatching((CFDictionaryRef)attrDict, (CFTypeRef*)&itemRef);
723
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800724 if(res == errSecSuccess)
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800725 return true;
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800726 else
727 return false;
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800728
729}
730
Yingdi Yu4b752752014-02-18 12:24:03 -0800731bool
732SecTpmOsx::generateRandomBlock(uint8_t* res, size_t size)
733{
734 return (SecRandomCopyBytes(kSecRandomDefault, size, res) == 0);
735}
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800736
737////////////////////////////////
738// OSXPrivateKeyStorage::Impl //
739////////////////////////////////
740
741SecKeychainItemRef
742SecTpmOsx::Impl::getKey(const Name & keyName, KeyClass keyClass)
743{
744 string keyNameUri = toInternalKeyName(keyName, keyClass);
745
746 CFStringRef keyLabel = CFStringCreateWithCString(NULL,
747 keyNameUri.c_str(),
748 kCFStringEncodingUTF8);
749
750 CFMutableDictionaryRef attrDict = CFDictionaryCreateMutable(NULL,
751 5,
752 &kCFTypeDictionaryKeyCallBacks,
753 NULL);
754
755 CFDictionaryAddValue(attrDict, kSecClass, kSecClassKey);
756 CFDictionaryAddValue(attrDict, kSecAttrLabel, keyLabel);
757 CFDictionaryAddValue(attrDict, kSecAttrKeyClass, getKeyClass(keyClass));
758 CFDictionaryAddValue(attrDict, kSecReturnRef, kCFBooleanTrue);
759
760 SecKeychainItemRef keyItem;
761
762 OSStatus res = SecItemCopyMatching((CFDictionaryRef) attrDict, (CFTypeRef*)&keyItem);
763
764 if(res != errSecSuccess){
765 _LOG_DEBUG("Fail to find the key!");
766 return NULL;
767 }
768 else
769 return keyItem;
770}
771
772string
773SecTpmOsx::Impl::toInternalKeyName(const Name & keyName, KeyClass keyClass)
774{
775 string keyUri = keyName.toUri();
776
777 if(KEY_CLASS_SYMMETRIC == keyClass)
778 return keyUri + "/symmetric";
779 else
780 return keyUri;
781}
782
783const CFTypeRef
784SecTpmOsx::Impl::getAsymKeyType(KeyType keyType)
785{
786 switch(keyType){
787 case KEY_TYPE_RSA:
788 return kSecAttrKeyTypeRSA;
789 default:
790 _LOG_DEBUG("Unrecognized key type!")
791 return NULL;
792 }
793}
794
795const CFTypeRef
796SecTpmOsx::Impl::getSymKeyType(KeyType keyType)
797{
798 switch(keyType){
799 case KEY_TYPE_AES:
800 return kSecAttrKeyTypeAES;
801 default:
802 _LOG_DEBUG("Unrecognized key type!")
803 return NULL;
804 }
805}
806
807const CFTypeRef
808SecTpmOsx::Impl::getKeyClass(KeyClass keyClass)
809{
810 switch(keyClass){
811 case KEY_CLASS_PRIVATE:
812 return kSecAttrKeyClassPrivate;
813 case KEY_CLASS_PUBLIC:
814 return kSecAttrKeyClassPublic;
815 case KEY_CLASS_SYMMETRIC:
816 return kSecAttrKeyClassSymmetric;
817 default:
818 _LOG_DEBUG("Unrecognized key class!");
819 return NULL;
820 }
821}
822
823const CFStringRef
824SecTpmOsx::Impl::getDigestAlgorithm(DigestAlgorithm digestAlgo)
825{
826 switch(digestAlgo){
Jeff Thompson2747dc02013-10-04 19:11:34 -0700827 // case DIGEST_MD2:
828 // return kSecDigestMD2;
829 // case DIGEST_MD5:
830 // return kSecDigestMD5;
831 // case DIGEST_SHA1:
832 // return kSecDigestSHA1;
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800833 case DIGEST_ALGORITHM_SHA256:
834 return kSecDigestSHA2;
835 default:
836 _LOG_DEBUG("Unrecognized digest algorithm!");
837 return NULL;
Jeff Thompson2747dc02013-10-04 19:11:34 -0700838 }
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800839}
Jeff Thompson2747dc02013-10-04 19:11:34 -0700840
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800841long
842SecTpmOsx::Impl::getDigestSize(DigestAlgorithm digestAlgo)
843{
844 switch(digestAlgo){
845 case DIGEST_ALGORITHM_SHA256:
846 return 256;
Jeff Thompson2747dc02013-10-04 19:11:34 -0700847 // case DIGEST_SHA1:
848 // case DIGEST_MD2:
849 // case DIGEST_MD5:
850 // return 0;
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800851 default:
852 _LOG_DEBUG("Unrecognized digest algorithm! Unknown digest size");
853 return -1;
Jeff Thompson2747dc02013-10-04 19:11:34 -0700854 }
Jeff Thompson2747dc02013-10-04 19:11:34 -0700855}
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800856
857}// ndn