blob: 25b42dff591039367a880382a10196a4c9485d7c [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 Afanasyev19508852014-01-29 01:01:51 -08008#include "sec-tpm-osx.hpp"
9
10#include "security/public-key.hpp"
11#include "util/logging.hpp"
Jeff Thompson2747dc02013-10-04 19:11:34 -070012
13#include <fstream>
14#include <sstream>
Jeff Thompson2747dc02013-10-04 19:11:34 -070015
Alexander Afanasyev04b22a92014-01-05 22:40:17 -080016#include <CoreFoundation/CoreFoundation.h>
17#include <Security/Security.h>
18#include <CoreServices/CoreServices.h>
Jeff Thompson2747dc02013-10-04 19:11:34 -070019
20using namespace std;
Jeff Thompson2747dc02013-10-04 19:11:34 -070021
Yingdi Yu87581582014-01-14 14:28:39 -080022INIT_LOGGER("SecTpmOsx");
Jeff Thompson2747dc02013-10-04 19:11:34 -070023
24namespace ndn
25{
Yingdi Yu87581582014-01-14 14:28:39 -080026 class SecTpmOsx::Impl {
Alexander Afanasyev04b22a92014-01-05 22:40:17 -080027 public:
28 Impl(const std::string &keychainName)
Yingdi Yubdfa6242013-12-24 11:49:13 +080029 : keyChainName_ ("" == keychainName ? "login.keychain" : keychainName)
Alexander Afanasyev04b22a92014-01-05 22:40:17 -080030 {
31 }
32
33 /**
34 * convert NDN name of a key to internal name of the key
35 * @param keyName the NDN name of the key
36 * @param keyClass the class of the key
37 * @return the internal key name
38 */
39 std::string
40 toInternalKeyName(const Name & keyName, KeyClass keyClass);
41
42 /**
43 * Get key
44 * @param keyName the name of the key
45 * @param keyClass the class of the key
46 * @returns pointer to the key
47 */
48 SecKeychainItemRef
49 getKey(const Name & keyName, KeyClass keyClass);
50
51 /**
52 * convert keyType to MAC OS symmetric key key type
53 * @param keyType
54 * @returns MAC OS key type
55 */
56 const CFTypeRef
57 getSymKeyType(KeyType keyType);
58
59 /**
60 * convert keyType to MAC OS asymmetirc key type
61 * @param keyType
62 * @returns MAC OS key type
63 */
64 const CFTypeRef
65 getAsymKeyType(KeyType keyType);
66
67 /**
68 * convert keyClass to MAC OS key class
69 * @param keyClass
70 * @returns MAC OS key class
71 */
72 const CFTypeRef
73 getKeyClass(KeyClass keyClass);
74
75 /**
76 * convert digestAlgo to MAC OS algorithm id
77 * @param digestAlgo
78 * @returns MAC OS algorithm id
79 */
80 const CFStringRef
81 getDigestAlgorithm(DigestAlgorithm digestAlgo);
82
83 /**
84 * get the digest size of the corresponding algorithm
85 * @param digestAlgo the digest algorithm
86 * @return digest size
87 */
88 long
89 getDigestSize(DigestAlgorithm digestAlgo);
90
91 ///////////////////////////////////////////////
92 // everything here is public, including data //
93 ///////////////////////////////////////////////
94 public:
95 const std::string keyChainName_;
96 SecKeychainRef keyChainRef_;
97 SecKeychainRef originalDefaultKeyChain_;
98 };
99
100
101
Yingdi Yu87581582014-01-14 14:28:39 -0800102 SecTpmOsx::SecTpmOsx(const string & keychainName)
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800103 : impl_(new Impl(keychainName))
Jeff Thompson2747dc02013-10-04 19:11:34 -0700104 {
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800105 OSStatus res = SecKeychainCreate(impl_->keyChainName_.c_str(), //Keychain path
Yingdi Yu87581582014-01-14 14:28:39 -0800106 0, //Keychain password length
107 NULL, //Keychain password
108 true, //User prompt
109 NULL, //Initial access of Keychain
110 &impl_->keyChainRef_); //Keychain reference
Jeff Thompson2747dc02013-10-04 19:11:34 -0700111
112 if (res == errSecDuplicateKeychain)
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800113 res = SecKeychainOpen(impl_->keyChainName_.c_str(),
114 &impl_->keyChainRef_);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700115
116 if (res != errSecSuccess){
117 _LOG_DEBUG("Fail to initialize keychain ref: " << res);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800118 throw Error("Fail to initialize keychain ref");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700119 }
120
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800121 res = SecKeychainCopyDefault(&impl_->originalDefaultKeyChain_);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700122
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800123 res = SecKeychainSetDefault(impl_->keyChainRef_);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700124 if (res != errSecSuccess){
125 _LOG_DEBUG("Fail to set default keychain: " << res);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800126 throw Error("Fail to set default keychain");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700127 }
128 }
129
Yingdi Yu87581582014-01-14 14:28:39 -0800130 SecTpmOsx::~SecTpmOsx(){
Jeff Thompson2747dc02013-10-04 19:11:34 -0700131 //TODO: implement
132 }
133
134 void
Yingdi Yu87581582014-01-14 14:28:39 -0800135 SecTpmOsx::generateKeyPairInTpm(const Name & keyName, KeyType keyType, int keySize)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700136 {
137
Yingdi Yub4bb85a2014-01-16 10:11:04 -0800138 if(doesKeyExistInTpm(keyName, KEY_CLASS_PUBLIC)){
Jeff Thompson2747dc02013-10-04 19:11:34 -0700139 _LOG_DEBUG("keyName has existed");
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800140 throw Error("keyName has existed");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700141 }
142
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800143 string keyNameUri = impl_->toInternalKeyName(keyName, KEY_CLASS_PUBLIC);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700144
145 SecKeyRef publicKey, privateKey;
146
147 CFStringRef keyLabel = CFStringCreateWithCString(NULL,
Jeff Thompson556cc302013-10-22 17:40:07 -0700148 keyNameUri.c_str(),
149 kCFStringEncodingUTF8);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700150
151 CFMutableDictionaryRef attrDict = CFDictionaryCreateMutable(NULL,
152 3,
153 &kCFTypeDictionaryKeyCallBacks,
154 NULL);
155
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800156 CFDictionaryAddValue(attrDict, kSecAttrKeyType, impl_->getAsymKeyType(keyType));
Jeff Thompson2747dc02013-10-04 19:11:34 -0700157 CFDictionaryAddValue(attrDict, kSecAttrKeySizeInBits, CFNumberCreate(NULL, kCFNumberIntType, &keySize));
158 CFDictionaryAddValue(attrDict, kSecAttrLabel, keyLabel);
159
160 OSStatus res = SecKeyGeneratePair((CFDictionaryRef)attrDict, &publicKey, &privateKey);
161
162 CFRelease(publicKey);
163 CFRelease(privateKey);
164
165 if (res != errSecSuccess){
166 _LOG_DEBUG("Fail to create a key pair: " << res);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800167 throw Error("Fail to create a key pair");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700168 }
169 }
170
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800171 void
172 SecTpmOsx::deleteKeyPairInTpm(const Name &keyName)
173 {
174 string keyNameUri = keyName.toUri();
175
176 CFStringRef keyLabel = CFStringCreateWithCString(NULL,
177 keyNameUri.c_str(),
178 kCFStringEncodingUTF8);
179
180 CFMutableDictionaryRef attrDict = CFDictionaryCreateMutable(NULL,
181 5,
182 &kCFTypeDictionaryKeyCallBacks,
183 NULL);
184
185 CFDictionaryAddValue(attrDict, kSecClass, kSecClassKey);
186 CFDictionaryAddValue(attrDict, kSecAttrLabel, keyLabel);
187 CFDictionaryAddValue(attrDict, kSecMatchLimit, kSecMatchLimitAll);
188
189 OSStatus res = SecItemDelete((CFDictionaryRef) attrDict);
190
191 if(res != errSecSuccess)
192 _LOG_DEBUG("Fail to find the key!");
193 }
194
Jeff Thompson2747dc02013-10-04 19:11:34 -0700195 void
Yingdi Yub4bb85a2014-01-16 10:11:04 -0800196 SecTpmOsx::generateSymmetricKeyInTpm(const Name & keyName, KeyType keyType, int keySize)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700197 {
198
Yingdi Yub4bb85a2014-01-16 10:11:04 -0800199 if(doesKeyExistInTpm(keyName, KEY_CLASS_SYMMETRIC))
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800200 throw Error("keyName has existed!");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700201
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800202 string keyNameUri = impl_->toInternalKeyName(keyName, KEY_CLASS_SYMMETRIC);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700203
204 CFMutableDictionaryRef attrDict = CFDictionaryCreateMutable(kCFAllocatorDefault,
205 0,
206 &kCFTypeDictionaryKeyCallBacks,
207 &kCFTypeDictionaryValueCallBacks);
208
209 CFStringRef keyLabel = CFStringCreateWithCString(NULL,
Jeff Thompson556cc302013-10-22 17:40:07 -0700210 keyNameUri.c_str(),
211 kCFStringEncodingUTF8);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700212
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800213 CFDictionaryAddValue(attrDict, kSecAttrKeyType, impl_->getSymKeyType(keyType));
Jeff Thompson2747dc02013-10-04 19:11:34 -0700214 CFDictionaryAddValue(attrDict, kSecAttrKeySizeInBits, CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &keySize));
215 CFDictionaryAddValue(attrDict, kSecAttrIsPermanent, kCFBooleanTrue);
216 CFDictionaryAddValue(attrDict, kSecAttrLabel, keyLabel);
217
218 CFErrorRef error = NULL;
219
220 SecKeyRef symmetricKey = SecKeyGenerateSymmetric(attrDict, &error);
221
222 if (error)
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800223 throw Error("Fail to create a symmetric key");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700224 }
225
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800226 ptr_lib::shared_ptr<PublicKey>
Yingdi Yu87581582014-01-14 14:28:39 -0800227 SecTpmOsx::getPublicKeyFromTpm(const Name & keyName)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700228 {
229 _LOG_TRACE("OSXPrivateKeyStorage::getPublickey");
230
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800231 SecKeychainItemRef publicKey = impl_->getKey(keyName, KEY_CLASS_PUBLIC);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700232
233 CFDataRef exportedKey;
234
235 OSStatus res = SecItemExport(publicKey,
236 kSecFormatOpenSSL,
237 0,
238 NULL,
239 &exportedKey);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700240
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800241 return ptr_lib::make_shared<PublicKey>(CFDataGetBytePtr(exportedKey), CFDataGetLength(exportedKey));
Jeff Thompson2747dc02013-10-04 19:11:34 -0700242 }
243
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800244 Block
Yingdi Yub4bb85a2014-01-16 10:11:04 -0800245 SecTpmOsx::signInTpm(const uint8_t *data, size_t dataLength, const Name& keyName, DigestAlgorithm digestAlgorithm)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700246 {
247 _LOG_TRACE("OSXPrivateKeyStorage::Sign");
248
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800249 CFDataRef dataRef = CFDataCreateWithBytesNoCopy(NULL,
250 data,
251 dataLength,
252 kCFAllocatorNull
253 );
Jeff Thompson2747dc02013-10-04 19:11:34 -0700254
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800255 SecKeyRef privateKey = (SecKeyRef)impl_->getKey(keyName, KEY_CLASS_PRIVATE);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700256
257 CFErrorRef error;
258 SecTransformRef signer = SecSignTransformCreate((SecKeyRef)privateKey, &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800259 if (error) throw Error("Fail to create signer");
260
261 // Set input
Jeff Thompson2747dc02013-10-04 19:11:34 -0700262 Boolean set_res = SecTransformSetAttribute(signer,
263 kSecTransformInputAttributeName,
264 dataRef,
265 &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800266 if (error) throw Error("Fail to configure input of signer");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700267
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800268 // Enable use of padding
269 SecTransformSetAttribute(
270 signer,
271 kSecPaddingKey,
272 kSecPaddingPKCS1Key,
273 &error);
274 if (error) throw Error("Fail to configure digest algorithm of signer");
275
276 // Set padding type
Jeff Thompson2747dc02013-10-04 19:11:34 -0700277 set_res = SecTransformSetAttribute(signer,
278 kSecDigestTypeAttribute,
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800279 impl_->getDigestAlgorithm(digestAlgorithm),
Jeff Thompson2747dc02013-10-04 19:11:34 -0700280 &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800281 if (error) throw Error("Fail to configure digest algorithm of signer");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700282
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800283 // Set padding attribute
284 long digestSize = impl_->getDigestSize(digestAlgorithm);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700285 set_res = SecTransformSetAttribute(signer,
286 kSecDigestLengthAttribute,
287 CFNumberCreate(NULL, kCFNumberLongType, &digestSize),
288 &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800289 if (error) throw Error("Fail to configure digest size of signer");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700290
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800291 // Actually sign
Jeff Thompson2747dc02013-10-04 19:11:34 -0700292 CFDataRef signature = (CFDataRef) SecTransformExecute(signer, &error);
293 if (error) {
294 CFShow(error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800295 throw Error("Fail to sign data");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700296 }
297
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800298 if (!signature) throw Error("Signature is NULL!\n");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700299
Alexander Afanasyevbd5ba402014-01-05 22:41:09 -0800300 return Block(Tlv::SignatureValue,
301 ptr_lib::make_shared<Buffer>(CFDataGetBytePtr(signature), CFDataGetLength(signature)));
Jeff Thompson2747dc02013-10-04 19:11:34 -0700302 }
303
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800304 ConstBufferPtr
Yingdi Yub4bb85a2014-01-16 10:11:04 -0800305 SecTpmOsx::decryptInTpm(const Name & keyName, const uint8_t* data, size_t dataLength, bool sym)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700306 {
307 _LOG_TRACE("OSXPrivateKeyStorage::Decrypt");
308
309 KeyClass keyClass;
310 if(sym)
311 keyClass = KEY_CLASS_SYMMETRIC;
312 else
313 keyClass = KEY_CLASS_PRIVATE;
314
315 CFDataRef dataRef = CFDataCreate(NULL,
316 reinterpret_cast<const unsigned char*>(data),
317 dataLength
318 );
319
320 // _LOG_DEBUG("CreateData");
321
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800322 SecKeyRef decryptKey = (SecKeyRef)impl_->getKey(keyName, keyClass);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700323
324 // _LOG_DEBUG("GetKey");
325
326 CFErrorRef error;
327 SecTransformRef decrypt = SecDecryptTransformCreate(decryptKey, &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800328 if (error) throw Error("Fail to create decrypt");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700329
330 Boolean set_res = SecTransformSetAttribute(decrypt,
331 kSecTransformInputAttributeName,
332 dataRef,
333 &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800334 if (error) throw Error("Fail to configure decrypt");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700335
336 CFDataRef output = (CFDataRef) SecTransformExecute(decrypt, &error);
337 if (error)
338 {
339 CFShow(error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800340 throw Error("Fail to decrypt data");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700341 }
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800342 if (!output) throw Error("Output is NULL!\n");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700343
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800344 return ptr_lib::make_shared<Buffer>(CFDataGetBytePtr(output), CFDataGetLength(output));
Jeff Thompson2747dc02013-10-04 19:11:34 -0700345 }
346
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800347 bool
Yingdi Yu87581582014-01-14 14:28:39 -0800348 SecTpmOsx::setACL(const Name & keyName, KeyClass keyClass, int acl, const string & appPath)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700349 {
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800350 SecKeychainItemRef privateKey = impl_->getKey(keyName, keyClass);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700351
352 SecAccessRef accRef;
353 OSStatus acc_res = SecKeychainItemCopyAccess(privateKey, &accRef);
354
355 CFArrayRef signACL = SecAccessCopyMatchingACLList(accRef,
356 kSecACLAuthorizationSign);
357
358 SecACLRef aclRef = (SecACLRef) CFArrayGetValueAtIndex(signACL, 0);
359
360 CFArrayRef appList;
361 CFStringRef description;
362 SecKeychainPromptSelector promptSelector;
363 OSStatus acl_res = SecACLCopyContents(aclRef,
364 &appList,
365 &description,
366 &promptSelector);
367
368 CFMutableArrayRef newAppList = CFArrayCreateMutableCopy(NULL,
369 0,
370 appList);
371
372 SecTrustedApplicationRef trustedApp;
373 acl_res = SecTrustedApplicationCreateFromPath(appPath.c_str(),
374 &trustedApp);
375
376 CFArrayAppendValue(newAppList, trustedApp);
377
378
379 CFArrayRef authList = SecACLCopyAuthorizations(aclRef);
380
381 acl_res = SecACLRemove(aclRef);
382
383 SecACLRef newACL;
384 acl_res = SecACLCreateWithSimpleContents(accRef,
385 newAppList,
386 description,
387 promptSelector,
388 &newACL);
389
390 acl_res = SecACLUpdateAuthorizations(newACL, authList);
391
392 acc_res = SecKeychainItemSetAccess(privateKey, accRef);
393
394 return true;
395 }
396
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800397 // bool
398 // OSXPrivateKeyStorage::verifyData(const Name & keyName, const Blob & pData, const Blob & pSig, DigestAlgorithm digestAlgo)
399 // {
400 // _LOG_TRACE("OSXPrivateKeyStorage::Verify");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700401
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800402 // CFDataRef dataRef = CFDataCreate(NULL,
403 // reinterpret_cast<const unsigned char*>(pData.buf()),
404 // pData.size());
Jeff Thompson2747dc02013-10-04 19:11:34 -0700405
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800406 // CFDataRef sigRef = CFDataCreate(NULL,
407 // reinterpret_cast<const unsigned char*>(pSig.buf()),
408 // pSig.size());
Jeff Thompson2747dc02013-10-04 19:11:34 -0700409
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800410 // SecKeyRef publicKey = (SecKeyRef)impl_->getKey(keyName, KEY_CLASS_PUBLIC);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700411
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800412 // CFErrorRef error;
413 // SecTransformRef verifier = SecVerifyTransformCreate(publicKey, sigRef, &error);
414 // if (error) throw Error("Fail to create verifier");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700415
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800416 // Boolean set_res = SecTransformSetAttribute(verifier,
417 // kSecTransformInputAttributeName,
418 // dataRef,
419 // &error);
420 // if (error) throw Error("Fail to configure input of verifier");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700421
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800422 // set_res = SecTransformSetAttribute(verifier,
423 // kSecDigestTypeAttribute,
424 // impl_->getDigestAlgorithm(digestAlgo),
425 // &error);
426 // if (error) throw Error("Fail to configure digest algorithm of verifier");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700427
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800428 // long digestSize = impl_->getDigestSize(digestAlgo);
429 // set_res = SecTransformSetAttribute(verifier,
430 // kSecDigestLengthAttribute,
431 // CFNumberCreate(NULL, kCFNumberLongType, &digestSize),
432 // &error);
433 // if (error) throw Error("Fail to configure digest size of verifier");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700434
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800435 // CFBooleanRef result = (CFBooleanRef) SecTransformExecute(verifier, &error);
436 // if (error) throw Error("Fail to verify data");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700437
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800438 // if (result == kCFBooleanTrue)
439 // return true;
440 // else
441 // return false;
442 // }
Jeff Thompson2747dc02013-10-04 19:11:34 -0700443
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800444 ConstBufferPtr
Yingdi Yub4bb85a2014-01-16 10:11:04 -0800445 SecTpmOsx::encryptInTpm(const Name & keyName, const uint8_t* data, size_t dataLength, bool sym)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700446 {
447 _LOG_TRACE("OSXPrivateKeyStorage::Encrypt");
448
449 KeyClass keyClass;
450 if(sym)
451 keyClass = KEY_CLASS_SYMMETRIC;
452 else
453 keyClass = KEY_CLASS_PUBLIC;
454
455 CFDataRef dataRef = CFDataCreate(NULL,
456 reinterpret_cast<const unsigned char*>(data),
457 dataLength
458 );
459
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800460 SecKeyRef encryptKey = (SecKeyRef)impl_->getKey(keyName, keyClass);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700461
462 CFErrorRef error;
463 SecTransformRef encrypt = SecEncryptTransformCreate(encryptKey, &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800464 if (error) throw Error("Fail to create encrypt");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700465
466 Boolean set_res = SecTransformSetAttribute(encrypt,
467 kSecTransformInputAttributeName,
468 dataRef,
469 &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800470 if (error) throw Error("Fail to configure encrypt");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700471
472 CFDataRef output = (CFDataRef) SecTransformExecute(encrypt, &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800473 if (error) throw Error("Fail to encrypt data");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700474
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800475 if (!output) throw Error("Output is NULL!\n");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700476
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800477 return ptr_lib::make_shared<Buffer> (CFDataGetBytePtr(output), CFDataGetLength(output));
Jeff Thompson2747dc02013-10-04 19:11:34 -0700478 }
479
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800480 bool
Yingdi Yub4bb85a2014-01-16 10:11:04 -0800481 SecTpmOsx::doesKeyExistInTpm(const Name & keyName, KeyClass keyClass)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700482 {
483 _LOG_TRACE("OSXPrivateKeyStorage::doesKeyExist");
484
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800485 string keyNameUri = impl_->toInternalKeyName(keyName, keyClass);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700486
487 CFStringRef keyLabel = CFStringCreateWithCString(NULL,
Jeff Thompson556cc302013-10-22 17:40:07 -0700488 keyNameUri.c_str(),
489 kCFStringEncodingUTF8);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700490
491 CFMutableDictionaryRef attrDict = CFDictionaryCreateMutable(NULL,
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800492 4,
Jeff Thompson2747dc02013-10-04 19:11:34 -0700493 &kCFTypeDictionaryKeyCallBacks,
494 NULL);
495
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800496 CFDictionaryAddValue(attrDict, kSecClass, kSecClassKey);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800497 CFDictionaryAddValue(attrDict, kSecAttrKeyClass, impl_->getKeyClass(keyClass));
Jeff Thompson2747dc02013-10-04 19:11:34 -0700498 CFDictionaryAddValue(attrDict, kSecAttrLabel, keyLabel);
499 CFDictionaryAddValue(attrDict, kSecReturnRef, kCFBooleanTrue);
500
501 SecKeychainItemRef itemRef;
502 OSStatus res = SecItemCopyMatching((CFDictionaryRef)attrDict, (CFTypeRef*)&itemRef);
503
504 if(res == errSecItemNotFound)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700505 return false;
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800506 else
507 return true;
Jeff Thompson2747dc02013-10-04 19:11:34 -0700508
509 }
510
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800511
512 ////////////////////////////////
513 // OSXPrivateKeyStorage::Impl //
514 ////////////////////////////////
515
516 SecKeychainItemRef
Yingdi Yu87581582014-01-14 14:28:39 -0800517 SecTpmOsx::Impl::getKey(const Name & keyName, KeyClass keyClass)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700518 {
519 string keyNameUri = toInternalKeyName(keyName, keyClass);
520
Jeff Thompson556cc302013-10-22 17:40:07 -0700521 CFStringRef keyLabel = CFStringCreateWithCString(NULL,
522 keyNameUri.c_str(),
523 kCFStringEncodingUTF8);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700524
525 CFMutableDictionaryRef attrDict = CFDictionaryCreateMutable(NULL,
526 5,
527 &kCFTypeDictionaryKeyCallBacks,
528 NULL);
529
530 CFDictionaryAddValue(attrDict, kSecClass, kSecClassKey);
531 CFDictionaryAddValue(attrDict, kSecAttrLabel, keyLabel);
532 CFDictionaryAddValue(attrDict, kSecAttrKeyClass, getKeyClass(keyClass));
533 CFDictionaryAddValue(attrDict, kSecReturnRef, kCFBooleanTrue);
534
535 SecKeychainItemRef keyItem;
536
537 OSStatus res = SecItemCopyMatching((CFDictionaryRef) attrDict, (CFTypeRef*)&keyItem);
538
539 if(res != errSecSuccess){
540 _LOG_DEBUG("Fail to find the key!");
541 return NULL;
542 }
543 else
544 return keyItem;
545 }
546
Yingdi Yu87581582014-01-14 14:28:39 -0800547 string
548 SecTpmOsx::Impl::toInternalKeyName(const Name & keyName, KeyClass keyClass)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700549 {
550 string keyUri = keyName.toUri();
551
552 if(KEY_CLASS_SYMMETRIC == keyClass)
553 return keyUri + "/symmetric";
554 else
555 return keyUri;
556 }
557
Yingdi Yu87581582014-01-14 14:28:39 -0800558 const CFTypeRef
559 SecTpmOsx::Impl::getAsymKeyType(KeyType keyType)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700560 {
561 switch(keyType){
562 case KEY_TYPE_RSA:
563 return kSecAttrKeyTypeRSA;
564 default:
565 _LOG_DEBUG("Unrecognized key type!")
566 return NULL;
567 }
568 }
569
Yingdi Yu87581582014-01-14 14:28:39 -0800570 const CFTypeRef
571 SecTpmOsx::Impl::getSymKeyType(KeyType keyType)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700572 {
573 switch(keyType){
574 case KEY_TYPE_AES:
575 return kSecAttrKeyTypeAES;
576 default:
577 _LOG_DEBUG("Unrecognized key type!")
578 return NULL;
579 }
580 }
581
Yingdi Yu87581582014-01-14 14:28:39 -0800582 const CFTypeRef
583 SecTpmOsx::Impl::getKeyClass(KeyClass keyClass)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700584 {
585 switch(keyClass){
586 case KEY_CLASS_PRIVATE:
587 return kSecAttrKeyClassPrivate;
588 case KEY_CLASS_PUBLIC:
589 return kSecAttrKeyClassPublic;
590 case KEY_CLASS_SYMMETRIC:
591 return kSecAttrKeyClassSymmetric;
592 default:
593 _LOG_DEBUG("Unrecognized key class!");
594 return NULL;
595 }
596 }
597
Yingdi Yu87581582014-01-14 14:28:39 -0800598 const CFStringRef
599 SecTpmOsx::Impl::getDigestAlgorithm(DigestAlgorithm digestAlgo)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700600 {
601 switch(digestAlgo){
602 // case DIGEST_MD2:
603 // return kSecDigestMD2;
604 // case DIGEST_MD5:
605 // return kSecDigestMD5;
606 // case DIGEST_SHA1:
607 // return kSecDigestSHA1;
608 case DIGEST_ALGORITHM_SHA256:
609 return kSecDigestSHA2;
610 default:
611 _LOG_DEBUG("Unrecognized digest algorithm!");
612 return NULL;
613 }
614 }
615
Yingdi Yu87581582014-01-14 14:28:39 -0800616 long
617 SecTpmOsx::Impl::getDigestSize(DigestAlgorithm digestAlgo)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700618 {
619 switch(digestAlgo){
620 case DIGEST_ALGORITHM_SHA256:
621 return 256;
622 // case DIGEST_SHA1:
623 // case DIGEST_MD2:
624 // case DIGEST_MD5:
625 // return 0;
626 default:
627 _LOG_DEBUG("Unrecognized digest algorithm! Unknown digest size");
628 return -1;
629 }
630 }
631
632}