blob: 23a33f037a016df1b56260feba6674553292da9e [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
Yingdi Yu61ec2722014-01-20 14:22:32 -08008#include <ndn-cpp-dev/ndn-cpp-config.h>
Jeff Thompson2747dc02013-10-04 19:11:34 -07009
10#include <fstream>
11#include <sstream>
Jeff Thompson2747dc02013-10-04 19:11:34 -070012
Yingdi Yu4f324632014-01-15 18:10:03 -080013#include "../util/logging.hpp"
Alexander Afanasyev6be1a6a2014-01-06 00:08:14 -080014
Yingdi Yu61ec2722014-01-20 14:22:32 -080015#include <ndn-cpp-dev/security/sec-tpm-osx.hpp>
16#include <ndn-cpp-dev/security/public-key.hpp>
Alexander Afanasyev04b22a92014-01-05 22:40:17 -080017
18#include <CoreFoundation/CoreFoundation.h>
19#include <Security/Security.h>
20#include <CoreServices/CoreServices.h>
Jeff Thompson2747dc02013-10-04 19:11:34 -070021
22using namespace std;
Jeff Thompson2747dc02013-10-04 19:11:34 -070023
Yingdi Yu87581582014-01-14 14:28:39 -080024INIT_LOGGER("SecTpmOsx");
Jeff Thompson2747dc02013-10-04 19:11:34 -070025
26namespace ndn
27{
Yingdi Yu87581582014-01-14 14:28:39 -080028 class SecTpmOsx::Impl {
Alexander Afanasyev04b22a92014-01-05 22:40:17 -080029 public:
30 Impl(const std::string &keychainName)
Yingdi Yubdfa6242013-12-24 11:49:13 +080031 : keyChainName_ ("" == keychainName ? "login.keychain" : keychainName)
Alexander Afanasyev04b22a92014-01-05 22:40:17 -080032 {
33 }
34
35 /**
36 * convert NDN name of a key to internal name of the key
37 * @param keyName the NDN name of the key
38 * @param keyClass the class of the key
39 * @return the internal key name
40 */
41 std::string
42 toInternalKeyName(const Name & keyName, KeyClass keyClass);
43
44 /**
45 * Get key
46 * @param keyName the name of the key
47 * @param keyClass the class of the key
48 * @returns pointer to the key
49 */
50 SecKeychainItemRef
51 getKey(const Name & keyName, KeyClass keyClass);
52
53 /**
54 * convert keyType to MAC OS symmetric key key type
55 * @param keyType
56 * @returns MAC OS key type
57 */
58 const CFTypeRef
59 getSymKeyType(KeyType keyType);
60
61 /**
62 * convert keyType to MAC OS asymmetirc key type
63 * @param keyType
64 * @returns MAC OS key type
65 */
66 const CFTypeRef
67 getAsymKeyType(KeyType keyType);
68
69 /**
70 * convert keyClass to MAC OS key class
71 * @param keyClass
72 * @returns MAC OS key class
73 */
74 const CFTypeRef
75 getKeyClass(KeyClass keyClass);
76
77 /**
78 * convert digestAlgo to MAC OS algorithm id
79 * @param digestAlgo
80 * @returns MAC OS algorithm id
81 */
82 const CFStringRef
83 getDigestAlgorithm(DigestAlgorithm digestAlgo);
84
85 /**
86 * get the digest size of the corresponding algorithm
87 * @param digestAlgo the digest algorithm
88 * @return digest size
89 */
90 long
91 getDigestSize(DigestAlgorithm digestAlgo);
92
93 ///////////////////////////////////////////////
94 // everything here is public, including data //
95 ///////////////////////////////////////////////
96 public:
97 const std::string keyChainName_;
98 SecKeychainRef keyChainRef_;
99 SecKeychainRef originalDefaultKeyChain_;
100 };
101
102
103
Yingdi Yu87581582014-01-14 14:28:39 -0800104 SecTpmOsx::SecTpmOsx(const string & keychainName)
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800105 : impl_(new Impl(keychainName))
Jeff Thompson2747dc02013-10-04 19:11:34 -0700106 {
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800107 OSStatus res = SecKeychainCreate(impl_->keyChainName_.c_str(), //Keychain path
Yingdi Yu87581582014-01-14 14:28:39 -0800108 0, //Keychain password length
109 NULL, //Keychain password
110 true, //User prompt
111 NULL, //Initial access of Keychain
112 &impl_->keyChainRef_); //Keychain reference
Jeff Thompson2747dc02013-10-04 19:11:34 -0700113
114 if (res == errSecDuplicateKeychain)
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800115 res = SecKeychainOpen(impl_->keyChainName_.c_str(),
116 &impl_->keyChainRef_);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700117
118 if (res != errSecSuccess){
119 _LOG_DEBUG("Fail to initialize keychain ref: " << res);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800120 throw Error("Fail to initialize keychain ref");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700121 }
122
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800123 res = SecKeychainCopyDefault(&impl_->originalDefaultKeyChain_);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700124
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800125 res = SecKeychainSetDefault(impl_->keyChainRef_);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700126 if (res != errSecSuccess){
127 _LOG_DEBUG("Fail to set default keychain: " << res);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800128 throw Error("Fail to set default keychain");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700129 }
130 }
131
Yingdi Yu87581582014-01-14 14:28:39 -0800132 SecTpmOsx::~SecTpmOsx(){
Jeff Thompson2747dc02013-10-04 19:11:34 -0700133 //TODO: implement
134 }
135
136 void
Yingdi Yu87581582014-01-14 14:28:39 -0800137 SecTpmOsx::generateKeyPairInTpm(const Name & keyName, KeyType keyType, int keySize)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700138 {
139
Yingdi Yub4bb85a2014-01-16 10:11:04 -0800140 if(doesKeyExistInTpm(keyName, KEY_CLASS_PUBLIC)){
Jeff Thompson2747dc02013-10-04 19:11:34 -0700141 _LOG_DEBUG("keyName has existed");
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800142 throw Error("keyName has existed");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700143 }
144
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800145 string keyNameUri = impl_->toInternalKeyName(keyName, KEY_CLASS_PUBLIC);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700146
147 SecKeyRef publicKey, privateKey;
148
149 CFStringRef keyLabel = CFStringCreateWithCString(NULL,
Jeff Thompson556cc302013-10-22 17:40:07 -0700150 keyNameUri.c_str(),
151 kCFStringEncodingUTF8);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700152
153 CFMutableDictionaryRef attrDict = CFDictionaryCreateMutable(NULL,
154 3,
155 &kCFTypeDictionaryKeyCallBacks,
156 NULL);
157
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800158 CFDictionaryAddValue(attrDict, kSecAttrKeyType, impl_->getAsymKeyType(keyType));
Jeff Thompson2747dc02013-10-04 19:11:34 -0700159 CFDictionaryAddValue(attrDict, kSecAttrKeySizeInBits, CFNumberCreate(NULL, kCFNumberIntType, &keySize));
160 CFDictionaryAddValue(attrDict, kSecAttrLabel, keyLabel);
161
162 OSStatus res = SecKeyGeneratePair((CFDictionaryRef)attrDict, &publicKey, &privateKey);
163
164 CFRelease(publicKey);
165 CFRelease(privateKey);
166
167 if (res != errSecSuccess){
168 _LOG_DEBUG("Fail to create a key pair: " << res);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800169 throw Error("Fail to create a key pair");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700170 }
171 }
172
173 void
Yingdi Yub4bb85a2014-01-16 10:11:04 -0800174 SecTpmOsx::generateSymmetricKeyInTpm(const Name & keyName, KeyType keyType, int keySize)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700175 {
176
Yingdi Yub4bb85a2014-01-16 10:11:04 -0800177 if(doesKeyExistInTpm(keyName, KEY_CLASS_SYMMETRIC))
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800178 throw Error("keyName has existed!");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700179
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800180 string keyNameUri = impl_->toInternalKeyName(keyName, KEY_CLASS_SYMMETRIC);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700181
182 CFMutableDictionaryRef attrDict = CFDictionaryCreateMutable(kCFAllocatorDefault,
183 0,
184 &kCFTypeDictionaryKeyCallBacks,
185 &kCFTypeDictionaryValueCallBacks);
186
187 CFStringRef keyLabel = CFStringCreateWithCString(NULL,
Jeff Thompson556cc302013-10-22 17:40:07 -0700188 keyNameUri.c_str(),
189 kCFStringEncodingUTF8);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700190
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800191 CFDictionaryAddValue(attrDict, kSecAttrKeyType, impl_->getSymKeyType(keyType));
Jeff Thompson2747dc02013-10-04 19:11:34 -0700192 CFDictionaryAddValue(attrDict, kSecAttrKeySizeInBits, CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &keySize));
193 CFDictionaryAddValue(attrDict, kSecAttrIsPermanent, kCFBooleanTrue);
194 CFDictionaryAddValue(attrDict, kSecAttrLabel, keyLabel);
195
196 CFErrorRef error = NULL;
197
198 SecKeyRef symmetricKey = SecKeyGenerateSymmetric(attrDict, &error);
199
200 if (error)
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800201 throw Error("Fail to create a symmetric key");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700202 }
203
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800204 ptr_lib::shared_ptr<PublicKey>
Yingdi Yu87581582014-01-14 14:28:39 -0800205 SecTpmOsx::getPublicKeyFromTpm(const Name & keyName)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700206 {
207 _LOG_TRACE("OSXPrivateKeyStorage::getPublickey");
208
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800209 SecKeychainItemRef publicKey = impl_->getKey(keyName, KEY_CLASS_PUBLIC);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700210
211 CFDataRef exportedKey;
212
213 OSStatus res = SecItemExport(publicKey,
214 kSecFormatOpenSSL,
215 0,
216 NULL,
217 &exportedKey);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700218
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800219 return ptr_lib::make_shared<PublicKey>(CFDataGetBytePtr(exportedKey), CFDataGetLength(exportedKey));
Jeff Thompson2747dc02013-10-04 19:11:34 -0700220 }
221
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800222 Block
Yingdi Yub4bb85a2014-01-16 10:11:04 -0800223 SecTpmOsx::signInTpm(const uint8_t *data, size_t dataLength, const Name& keyName, DigestAlgorithm digestAlgorithm)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700224 {
225 _LOG_TRACE("OSXPrivateKeyStorage::Sign");
226
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800227 CFDataRef dataRef = CFDataCreateWithBytesNoCopy(NULL,
228 data,
229 dataLength,
230 kCFAllocatorNull
231 );
Jeff Thompson2747dc02013-10-04 19:11:34 -0700232
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800233 SecKeyRef privateKey = (SecKeyRef)impl_->getKey(keyName, KEY_CLASS_PRIVATE);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700234
235 CFErrorRef error;
236 SecTransformRef signer = SecSignTransformCreate((SecKeyRef)privateKey, &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800237 if (error) throw Error("Fail to create signer");
238
239 // Set input
Jeff Thompson2747dc02013-10-04 19:11:34 -0700240 Boolean set_res = SecTransformSetAttribute(signer,
241 kSecTransformInputAttributeName,
242 dataRef,
243 &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800244 if (error) throw Error("Fail to configure input of signer");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700245
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800246 // Enable use of padding
247 SecTransformSetAttribute(
248 signer,
249 kSecPaddingKey,
250 kSecPaddingPKCS1Key,
251 &error);
252 if (error) throw Error("Fail to configure digest algorithm of signer");
253
254 // Set padding type
Jeff Thompson2747dc02013-10-04 19:11:34 -0700255 set_res = SecTransformSetAttribute(signer,
256 kSecDigestTypeAttribute,
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800257 impl_->getDigestAlgorithm(digestAlgorithm),
Jeff Thompson2747dc02013-10-04 19:11:34 -0700258 &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800259 if (error) throw Error("Fail to configure digest algorithm of signer");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700260
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800261 // Set padding attribute
262 long digestSize = impl_->getDigestSize(digestAlgorithm);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700263 set_res = SecTransformSetAttribute(signer,
264 kSecDigestLengthAttribute,
265 CFNumberCreate(NULL, kCFNumberLongType, &digestSize),
266 &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800267 if (error) throw Error("Fail to configure digest size of signer");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700268
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800269 // Actually sign
Jeff Thompson2747dc02013-10-04 19:11:34 -0700270 CFDataRef signature = (CFDataRef) SecTransformExecute(signer, &error);
271 if (error) {
272 CFShow(error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800273 throw Error("Fail to sign data");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700274 }
275
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800276 if (!signature) throw Error("Signature is NULL!\n");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700277
Alexander Afanasyevbd5ba402014-01-05 22:41:09 -0800278 return Block(Tlv::SignatureValue,
279 ptr_lib::make_shared<Buffer>(CFDataGetBytePtr(signature), CFDataGetLength(signature)));
Jeff Thompson2747dc02013-10-04 19:11:34 -0700280 }
281
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800282 ConstBufferPtr
Yingdi Yub4bb85a2014-01-16 10:11:04 -0800283 SecTpmOsx::decryptInTpm(const Name & keyName, const uint8_t* data, size_t dataLength, bool sym)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700284 {
285 _LOG_TRACE("OSXPrivateKeyStorage::Decrypt");
286
287 KeyClass keyClass;
288 if(sym)
289 keyClass = KEY_CLASS_SYMMETRIC;
290 else
291 keyClass = KEY_CLASS_PRIVATE;
292
293 CFDataRef dataRef = CFDataCreate(NULL,
294 reinterpret_cast<const unsigned char*>(data),
295 dataLength
296 );
297
298 // _LOG_DEBUG("CreateData");
299
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800300 SecKeyRef decryptKey = (SecKeyRef)impl_->getKey(keyName, keyClass);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700301
302 // _LOG_DEBUG("GetKey");
303
304 CFErrorRef error;
305 SecTransformRef decrypt = SecDecryptTransformCreate(decryptKey, &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800306 if (error) throw Error("Fail to create decrypt");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700307
308 Boolean set_res = SecTransformSetAttribute(decrypt,
309 kSecTransformInputAttributeName,
310 dataRef,
311 &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800312 if (error) throw Error("Fail to configure decrypt");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700313
314 CFDataRef output = (CFDataRef) SecTransformExecute(decrypt, &error);
315 if (error)
316 {
317 CFShow(error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800318 throw Error("Fail to decrypt data");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700319 }
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800320 if (!output) throw Error("Output is NULL!\n");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700321
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800322 return ptr_lib::make_shared<Buffer>(CFDataGetBytePtr(output), CFDataGetLength(output));
Jeff Thompson2747dc02013-10-04 19:11:34 -0700323 }
324
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800325 bool
Yingdi Yu87581582014-01-14 14:28:39 -0800326 SecTpmOsx::setACL(const Name & keyName, KeyClass keyClass, int acl, const string & appPath)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700327 {
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800328 SecKeychainItemRef privateKey = impl_->getKey(keyName, keyClass);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700329
330 SecAccessRef accRef;
331 OSStatus acc_res = SecKeychainItemCopyAccess(privateKey, &accRef);
332
333 CFArrayRef signACL = SecAccessCopyMatchingACLList(accRef,
334 kSecACLAuthorizationSign);
335
336 SecACLRef aclRef = (SecACLRef) CFArrayGetValueAtIndex(signACL, 0);
337
338 CFArrayRef appList;
339 CFStringRef description;
340 SecKeychainPromptSelector promptSelector;
341 OSStatus acl_res = SecACLCopyContents(aclRef,
342 &appList,
343 &description,
344 &promptSelector);
345
346 CFMutableArrayRef newAppList = CFArrayCreateMutableCopy(NULL,
347 0,
348 appList);
349
350 SecTrustedApplicationRef trustedApp;
351 acl_res = SecTrustedApplicationCreateFromPath(appPath.c_str(),
352 &trustedApp);
353
354 CFArrayAppendValue(newAppList, trustedApp);
355
356
357 CFArrayRef authList = SecACLCopyAuthorizations(aclRef);
358
359 acl_res = SecACLRemove(aclRef);
360
361 SecACLRef newACL;
362 acl_res = SecACLCreateWithSimpleContents(accRef,
363 newAppList,
364 description,
365 promptSelector,
366 &newACL);
367
368 acl_res = SecACLUpdateAuthorizations(newACL, authList);
369
370 acc_res = SecKeychainItemSetAccess(privateKey, accRef);
371
372 return true;
373 }
374
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800375 // bool
376 // OSXPrivateKeyStorage::verifyData(const Name & keyName, const Blob & pData, const Blob & pSig, DigestAlgorithm digestAlgo)
377 // {
378 // _LOG_TRACE("OSXPrivateKeyStorage::Verify");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700379
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800380 // CFDataRef dataRef = CFDataCreate(NULL,
381 // reinterpret_cast<const unsigned char*>(pData.buf()),
382 // pData.size());
Jeff Thompson2747dc02013-10-04 19:11:34 -0700383
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800384 // CFDataRef sigRef = CFDataCreate(NULL,
385 // reinterpret_cast<const unsigned char*>(pSig.buf()),
386 // pSig.size());
Jeff Thompson2747dc02013-10-04 19:11:34 -0700387
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800388 // SecKeyRef publicKey = (SecKeyRef)impl_->getKey(keyName, KEY_CLASS_PUBLIC);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700389
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800390 // CFErrorRef error;
391 // SecTransformRef verifier = SecVerifyTransformCreate(publicKey, sigRef, &error);
392 // if (error) throw Error("Fail to create verifier");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700393
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800394 // Boolean set_res = SecTransformSetAttribute(verifier,
395 // kSecTransformInputAttributeName,
396 // dataRef,
397 // &error);
398 // if (error) throw Error("Fail to configure input of verifier");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700399
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800400 // set_res = SecTransformSetAttribute(verifier,
401 // kSecDigestTypeAttribute,
402 // impl_->getDigestAlgorithm(digestAlgo),
403 // &error);
404 // if (error) throw Error("Fail to configure digest algorithm of verifier");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700405
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800406 // long digestSize = impl_->getDigestSize(digestAlgo);
407 // set_res = SecTransformSetAttribute(verifier,
408 // kSecDigestLengthAttribute,
409 // CFNumberCreate(NULL, kCFNumberLongType, &digestSize),
410 // &error);
411 // if (error) throw Error("Fail to configure digest size of verifier");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700412
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800413 // CFBooleanRef result = (CFBooleanRef) SecTransformExecute(verifier, &error);
414 // if (error) throw Error("Fail to verify data");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700415
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800416 // if (result == kCFBooleanTrue)
417 // return true;
418 // else
419 // return false;
420 // }
Jeff Thompson2747dc02013-10-04 19:11:34 -0700421
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800422 ConstBufferPtr
Yingdi Yub4bb85a2014-01-16 10:11:04 -0800423 SecTpmOsx::encryptInTpm(const Name & keyName, const uint8_t* data, size_t dataLength, bool sym)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700424 {
425 _LOG_TRACE("OSXPrivateKeyStorage::Encrypt");
426
427 KeyClass keyClass;
428 if(sym)
429 keyClass = KEY_CLASS_SYMMETRIC;
430 else
431 keyClass = KEY_CLASS_PUBLIC;
432
433 CFDataRef dataRef = CFDataCreate(NULL,
434 reinterpret_cast<const unsigned char*>(data),
435 dataLength
436 );
437
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800438 SecKeyRef encryptKey = (SecKeyRef)impl_->getKey(keyName, keyClass);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700439
440 CFErrorRef error;
441 SecTransformRef encrypt = SecEncryptTransformCreate(encryptKey, &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800442 if (error) throw Error("Fail to create encrypt");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700443
444 Boolean set_res = SecTransformSetAttribute(encrypt,
445 kSecTransformInputAttributeName,
446 dataRef,
447 &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800448 if (error) throw Error("Fail to configure encrypt");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700449
450 CFDataRef output = (CFDataRef) SecTransformExecute(encrypt, &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800451 if (error) throw Error("Fail to encrypt data");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700452
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800453 if (!output) throw Error("Output is NULL!\n");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700454
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800455 return ptr_lib::make_shared<Buffer> (CFDataGetBytePtr(output), CFDataGetLength(output));
Jeff Thompson2747dc02013-10-04 19:11:34 -0700456 }
457
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800458 bool
Yingdi Yub4bb85a2014-01-16 10:11:04 -0800459 SecTpmOsx::doesKeyExistInTpm(const Name & keyName, KeyClass keyClass)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700460 {
461 _LOG_TRACE("OSXPrivateKeyStorage::doesKeyExist");
462
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800463 string keyNameUri = impl_->toInternalKeyName(keyName, keyClass);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700464
465 CFStringRef keyLabel = CFStringCreateWithCString(NULL,
Jeff Thompson556cc302013-10-22 17:40:07 -0700466 keyNameUri.c_str(),
467 kCFStringEncodingUTF8);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700468
469 CFMutableDictionaryRef attrDict = CFDictionaryCreateMutable(NULL,
470 3,
471 &kCFTypeDictionaryKeyCallBacks,
472 NULL);
473
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800474 CFDictionaryAddValue(attrDict, kSecAttrKeyClass, impl_->getKeyClass(keyClass));
Jeff Thompson2747dc02013-10-04 19:11:34 -0700475 CFDictionaryAddValue(attrDict, kSecAttrLabel, keyLabel);
476 CFDictionaryAddValue(attrDict, kSecReturnRef, kCFBooleanTrue);
477
478 SecKeychainItemRef itemRef;
479 OSStatus res = SecItemCopyMatching((CFDictionaryRef)attrDict, (CFTypeRef*)&itemRef);
480
481 if(res == errSecItemNotFound)
482 return true;
483 else
484 return false;
485
486 }
487
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800488
489 ////////////////////////////////
490 // OSXPrivateKeyStorage::Impl //
491 ////////////////////////////////
492
493 SecKeychainItemRef
Yingdi Yu87581582014-01-14 14:28:39 -0800494 SecTpmOsx::Impl::getKey(const Name & keyName, KeyClass keyClass)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700495 {
496 string keyNameUri = toInternalKeyName(keyName, keyClass);
497
Jeff Thompson556cc302013-10-22 17:40:07 -0700498 CFStringRef keyLabel = CFStringCreateWithCString(NULL,
499 keyNameUri.c_str(),
500 kCFStringEncodingUTF8);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700501
502 CFMutableDictionaryRef attrDict = CFDictionaryCreateMutable(NULL,
503 5,
504 &kCFTypeDictionaryKeyCallBacks,
505 NULL);
506
507 CFDictionaryAddValue(attrDict, kSecClass, kSecClassKey);
508 CFDictionaryAddValue(attrDict, kSecAttrLabel, keyLabel);
509 CFDictionaryAddValue(attrDict, kSecAttrKeyClass, getKeyClass(keyClass));
510 CFDictionaryAddValue(attrDict, kSecReturnRef, kCFBooleanTrue);
511
512 SecKeychainItemRef keyItem;
513
514 OSStatus res = SecItemCopyMatching((CFDictionaryRef) attrDict, (CFTypeRef*)&keyItem);
515
516 if(res != errSecSuccess){
517 _LOG_DEBUG("Fail to find the key!");
518 return NULL;
519 }
520 else
521 return keyItem;
522 }
523
Yingdi Yu87581582014-01-14 14:28:39 -0800524 string
525 SecTpmOsx::Impl::toInternalKeyName(const Name & keyName, KeyClass keyClass)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700526 {
527 string keyUri = keyName.toUri();
528
529 if(KEY_CLASS_SYMMETRIC == keyClass)
530 return keyUri + "/symmetric";
531 else
532 return keyUri;
533 }
534
Yingdi Yu87581582014-01-14 14:28:39 -0800535 const CFTypeRef
536 SecTpmOsx::Impl::getAsymKeyType(KeyType keyType)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700537 {
538 switch(keyType){
539 case KEY_TYPE_RSA:
540 return kSecAttrKeyTypeRSA;
541 default:
542 _LOG_DEBUG("Unrecognized key type!")
543 return NULL;
544 }
545 }
546
Yingdi Yu87581582014-01-14 14:28:39 -0800547 const CFTypeRef
548 SecTpmOsx::Impl::getSymKeyType(KeyType keyType)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700549 {
550 switch(keyType){
551 case KEY_TYPE_AES:
552 return kSecAttrKeyTypeAES;
553 default:
554 _LOG_DEBUG("Unrecognized key type!")
555 return NULL;
556 }
557 }
558
Yingdi Yu87581582014-01-14 14:28:39 -0800559 const CFTypeRef
560 SecTpmOsx::Impl::getKeyClass(KeyClass keyClass)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700561 {
562 switch(keyClass){
563 case KEY_CLASS_PRIVATE:
564 return kSecAttrKeyClassPrivate;
565 case KEY_CLASS_PUBLIC:
566 return kSecAttrKeyClassPublic;
567 case KEY_CLASS_SYMMETRIC:
568 return kSecAttrKeyClassSymmetric;
569 default:
570 _LOG_DEBUG("Unrecognized key class!");
571 return NULL;
572 }
573 }
574
Yingdi Yu87581582014-01-14 14:28:39 -0800575 const CFStringRef
576 SecTpmOsx::Impl::getDigestAlgorithm(DigestAlgorithm digestAlgo)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700577 {
578 switch(digestAlgo){
579 // case DIGEST_MD2:
580 // return kSecDigestMD2;
581 // case DIGEST_MD5:
582 // return kSecDigestMD5;
583 // case DIGEST_SHA1:
584 // return kSecDigestSHA1;
585 case DIGEST_ALGORITHM_SHA256:
586 return kSecDigestSHA2;
587 default:
588 _LOG_DEBUG("Unrecognized digest algorithm!");
589 return NULL;
590 }
591 }
592
Yingdi Yu87581582014-01-14 14:28:39 -0800593 long
594 SecTpmOsx::Impl::getDigestSize(DigestAlgorithm digestAlgo)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700595 {
596 switch(digestAlgo){
597 case DIGEST_ALGORITHM_SHA256:
598 return 256;
599 // case DIGEST_SHA1:
600 // case DIGEST_MD2:
601 // case DIGEST_MD5:
602 // return 0;
603 default:
604 _LOG_DEBUG("Unrecognized digest algorithm! Unknown digest size");
605 return -1;
606 }
607 }
608
609}