blob: fed73e1a9f967396f79dac4576e4a72d9f49a2c2 [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
171 void
Yingdi Yub4bb85a2014-01-16 10:11:04 -0800172 SecTpmOsx::generateSymmetricKeyInTpm(const Name & keyName, KeyType keyType, int keySize)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700173 {
174
Yingdi Yub4bb85a2014-01-16 10:11:04 -0800175 if(doesKeyExistInTpm(keyName, KEY_CLASS_SYMMETRIC))
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800176 throw Error("keyName has existed!");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700177
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800178 string keyNameUri = impl_->toInternalKeyName(keyName, KEY_CLASS_SYMMETRIC);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700179
180 CFMutableDictionaryRef attrDict = CFDictionaryCreateMutable(kCFAllocatorDefault,
181 0,
182 &kCFTypeDictionaryKeyCallBacks,
183 &kCFTypeDictionaryValueCallBacks);
184
185 CFStringRef keyLabel = CFStringCreateWithCString(NULL,
Jeff Thompson556cc302013-10-22 17:40:07 -0700186 keyNameUri.c_str(),
187 kCFStringEncodingUTF8);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700188
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800189 CFDictionaryAddValue(attrDict, kSecAttrKeyType, impl_->getSymKeyType(keyType));
Jeff Thompson2747dc02013-10-04 19:11:34 -0700190 CFDictionaryAddValue(attrDict, kSecAttrKeySizeInBits, CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &keySize));
191 CFDictionaryAddValue(attrDict, kSecAttrIsPermanent, kCFBooleanTrue);
192 CFDictionaryAddValue(attrDict, kSecAttrLabel, keyLabel);
193
194 CFErrorRef error = NULL;
195
196 SecKeyRef symmetricKey = SecKeyGenerateSymmetric(attrDict, &error);
197
198 if (error)
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800199 throw Error("Fail to create a symmetric key");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700200 }
201
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800202 ptr_lib::shared_ptr<PublicKey>
Yingdi Yu87581582014-01-14 14:28:39 -0800203 SecTpmOsx::getPublicKeyFromTpm(const Name & keyName)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700204 {
205 _LOG_TRACE("OSXPrivateKeyStorage::getPublickey");
206
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800207 SecKeychainItemRef publicKey = impl_->getKey(keyName, KEY_CLASS_PUBLIC);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700208
209 CFDataRef exportedKey;
210
211 OSStatus res = SecItemExport(publicKey,
212 kSecFormatOpenSSL,
213 0,
214 NULL,
215 &exportedKey);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700216
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800217 return ptr_lib::make_shared<PublicKey>(CFDataGetBytePtr(exportedKey), CFDataGetLength(exportedKey));
Jeff Thompson2747dc02013-10-04 19:11:34 -0700218 }
219
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800220 Block
Yingdi Yub4bb85a2014-01-16 10:11:04 -0800221 SecTpmOsx::signInTpm(const uint8_t *data, size_t dataLength, const Name& keyName, DigestAlgorithm digestAlgorithm)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700222 {
223 _LOG_TRACE("OSXPrivateKeyStorage::Sign");
224
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800225 CFDataRef dataRef = CFDataCreateWithBytesNoCopy(NULL,
226 data,
227 dataLength,
228 kCFAllocatorNull
229 );
Jeff Thompson2747dc02013-10-04 19:11:34 -0700230
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800231 SecKeyRef privateKey = (SecKeyRef)impl_->getKey(keyName, KEY_CLASS_PRIVATE);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700232
233 CFErrorRef error;
234 SecTransformRef signer = SecSignTransformCreate((SecKeyRef)privateKey, &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800235 if (error) throw Error("Fail to create signer");
236
237 // Set input
Jeff Thompson2747dc02013-10-04 19:11:34 -0700238 Boolean set_res = SecTransformSetAttribute(signer,
239 kSecTransformInputAttributeName,
240 dataRef,
241 &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800242 if (error) throw Error("Fail to configure input of signer");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700243
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800244 // Enable use of padding
245 SecTransformSetAttribute(
246 signer,
247 kSecPaddingKey,
248 kSecPaddingPKCS1Key,
249 &error);
250 if (error) throw Error("Fail to configure digest algorithm of signer");
251
252 // Set padding type
Jeff Thompson2747dc02013-10-04 19:11:34 -0700253 set_res = SecTransformSetAttribute(signer,
254 kSecDigestTypeAttribute,
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800255 impl_->getDigestAlgorithm(digestAlgorithm),
Jeff Thompson2747dc02013-10-04 19:11:34 -0700256 &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800257 if (error) throw Error("Fail to configure digest algorithm of signer");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700258
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800259 // Set padding attribute
260 long digestSize = impl_->getDigestSize(digestAlgorithm);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700261 set_res = SecTransformSetAttribute(signer,
262 kSecDigestLengthAttribute,
263 CFNumberCreate(NULL, kCFNumberLongType, &digestSize),
264 &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800265 if (error) throw Error("Fail to configure digest size of signer");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700266
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800267 // Actually sign
Jeff Thompson2747dc02013-10-04 19:11:34 -0700268 CFDataRef signature = (CFDataRef) SecTransformExecute(signer, &error);
269 if (error) {
270 CFShow(error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800271 throw Error("Fail to sign data");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700272 }
273
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800274 if (!signature) throw Error("Signature is NULL!\n");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700275
Alexander Afanasyevbd5ba402014-01-05 22:41:09 -0800276 return Block(Tlv::SignatureValue,
277 ptr_lib::make_shared<Buffer>(CFDataGetBytePtr(signature), CFDataGetLength(signature)));
Jeff Thompson2747dc02013-10-04 19:11:34 -0700278 }
279
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800280 ConstBufferPtr
Yingdi Yub4bb85a2014-01-16 10:11:04 -0800281 SecTpmOsx::decryptInTpm(const Name & keyName, const uint8_t* data, size_t dataLength, bool sym)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700282 {
283 _LOG_TRACE("OSXPrivateKeyStorage::Decrypt");
284
285 KeyClass keyClass;
286 if(sym)
287 keyClass = KEY_CLASS_SYMMETRIC;
288 else
289 keyClass = KEY_CLASS_PRIVATE;
290
291 CFDataRef dataRef = CFDataCreate(NULL,
292 reinterpret_cast<const unsigned char*>(data),
293 dataLength
294 );
295
296 // _LOG_DEBUG("CreateData");
297
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800298 SecKeyRef decryptKey = (SecKeyRef)impl_->getKey(keyName, keyClass);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700299
300 // _LOG_DEBUG("GetKey");
301
302 CFErrorRef error;
303 SecTransformRef decrypt = SecDecryptTransformCreate(decryptKey, &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800304 if (error) throw Error("Fail to create decrypt");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700305
306 Boolean set_res = SecTransformSetAttribute(decrypt,
307 kSecTransformInputAttributeName,
308 dataRef,
309 &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800310 if (error) throw Error("Fail to configure decrypt");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700311
312 CFDataRef output = (CFDataRef) SecTransformExecute(decrypt, &error);
313 if (error)
314 {
315 CFShow(error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800316 throw Error("Fail to decrypt data");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700317 }
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800318 if (!output) throw Error("Output is NULL!\n");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700319
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800320 return ptr_lib::make_shared<Buffer>(CFDataGetBytePtr(output), CFDataGetLength(output));
Jeff Thompson2747dc02013-10-04 19:11:34 -0700321 }
322
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800323 bool
Yingdi Yu87581582014-01-14 14:28:39 -0800324 SecTpmOsx::setACL(const Name & keyName, KeyClass keyClass, int acl, const string & appPath)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700325 {
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800326 SecKeychainItemRef privateKey = impl_->getKey(keyName, keyClass);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700327
328 SecAccessRef accRef;
329 OSStatus acc_res = SecKeychainItemCopyAccess(privateKey, &accRef);
330
331 CFArrayRef signACL = SecAccessCopyMatchingACLList(accRef,
332 kSecACLAuthorizationSign);
333
334 SecACLRef aclRef = (SecACLRef) CFArrayGetValueAtIndex(signACL, 0);
335
336 CFArrayRef appList;
337 CFStringRef description;
338 SecKeychainPromptSelector promptSelector;
339 OSStatus acl_res = SecACLCopyContents(aclRef,
340 &appList,
341 &description,
342 &promptSelector);
343
344 CFMutableArrayRef newAppList = CFArrayCreateMutableCopy(NULL,
345 0,
346 appList);
347
348 SecTrustedApplicationRef trustedApp;
349 acl_res = SecTrustedApplicationCreateFromPath(appPath.c_str(),
350 &trustedApp);
351
352 CFArrayAppendValue(newAppList, trustedApp);
353
354
355 CFArrayRef authList = SecACLCopyAuthorizations(aclRef);
356
357 acl_res = SecACLRemove(aclRef);
358
359 SecACLRef newACL;
360 acl_res = SecACLCreateWithSimpleContents(accRef,
361 newAppList,
362 description,
363 promptSelector,
364 &newACL);
365
366 acl_res = SecACLUpdateAuthorizations(newACL, authList);
367
368 acc_res = SecKeychainItemSetAccess(privateKey, accRef);
369
370 return true;
371 }
372
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800373 // bool
374 // OSXPrivateKeyStorage::verifyData(const Name & keyName, const Blob & pData, const Blob & pSig, DigestAlgorithm digestAlgo)
375 // {
376 // _LOG_TRACE("OSXPrivateKeyStorage::Verify");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700377
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800378 // CFDataRef dataRef = CFDataCreate(NULL,
379 // reinterpret_cast<const unsigned char*>(pData.buf()),
380 // pData.size());
Jeff Thompson2747dc02013-10-04 19:11:34 -0700381
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800382 // CFDataRef sigRef = CFDataCreate(NULL,
383 // reinterpret_cast<const unsigned char*>(pSig.buf()),
384 // pSig.size());
Jeff Thompson2747dc02013-10-04 19:11:34 -0700385
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800386 // SecKeyRef publicKey = (SecKeyRef)impl_->getKey(keyName, KEY_CLASS_PUBLIC);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700387
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800388 // CFErrorRef error;
389 // SecTransformRef verifier = SecVerifyTransformCreate(publicKey, sigRef, &error);
390 // if (error) throw Error("Fail to create verifier");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700391
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800392 // Boolean set_res = SecTransformSetAttribute(verifier,
393 // kSecTransformInputAttributeName,
394 // dataRef,
395 // &error);
396 // if (error) throw Error("Fail to configure input of verifier");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700397
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800398 // set_res = SecTransformSetAttribute(verifier,
399 // kSecDigestTypeAttribute,
400 // impl_->getDigestAlgorithm(digestAlgo),
401 // &error);
402 // if (error) throw Error("Fail to configure digest algorithm of verifier");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700403
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800404 // long digestSize = impl_->getDigestSize(digestAlgo);
405 // set_res = SecTransformSetAttribute(verifier,
406 // kSecDigestLengthAttribute,
407 // CFNumberCreate(NULL, kCFNumberLongType, &digestSize),
408 // &error);
409 // if (error) throw Error("Fail to configure digest size of verifier");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700410
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800411 // CFBooleanRef result = (CFBooleanRef) SecTransformExecute(verifier, &error);
412 // if (error) throw Error("Fail to verify data");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700413
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800414 // if (result == kCFBooleanTrue)
415 // return true;
416 // else
417 // return false;
418 // }
Jeff Thompson2747dc02013-10-04 19:11:34 -0700419
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800420 ConstBufferPtr
Yingdi Yub4bb85a2014-01-16 10:11:04 -0800421 SecTpmOsx::encryptInTpm(const Name & keyName, const uint8_t* data, size_t dataLength, bool sym)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700422 {
423 _LOG_TRACE("OSXPrivateKeyStorage::Encrypt");
424
425 KeyClass keyClass;
426 if(sym)
427 keyClass = KEY_CLASS_SYMMETRIC;
428 else
429 keyClass = KEY_CLASS_PUBLIC;
430
431 CFDataRef dataRef = CFDataCreate(NULL,
432 reinterpret_cast<const unsigned char*>(data),
433 dataLength
434 );
435
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800436 SecKeyRef encryptKey = (SecKeyRef)impl_->getKey(keyName, keyClass);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700437
438 CFErrorRef error;
439 SecTransformRef encrypt = SecEncryptTransformCreate(encryptKey, &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800440 if (error) throw Error("Fail to create encrypt");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700441
442 Boolean set_res = SecTransformSetAttribute(encrypt,
443 kSecTransformInputAttributeName,
444 dataRef,
445 &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800446 if (error) throw Error("Fail to configure encrypt");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700447
448 CFDataRef output = (CFDataRef) SecTransformExecute(encrypt, &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800449 if (error) throw Error("Fail to encrypt data");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700450
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800451 if (!output) throw Error("Output is NULL!\n");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700452
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800453 return ptr_lib::make_shared<Buffer> (CFDataGetBytePtr(output), CFDataGetLength(output));
Jeff Thompson2747dc02013-10-04 19:11:34 -0700454 }
455
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800456 bool
Yingdi Yub4bb85a2014-01-16 10:11:04 -0800457 SecTpmOsx::doesKeyExistInTpm(const Name & keyName, KeyClass keyClass)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700458 {
459 _LOG_TRACE("OSXPrivateKeyStorage::doesKeyExist");
460
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800461 string keyNameUri = impl_->toInternalKeyName(keyName, keyClass);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700462
463 CFStringRef keyLabel = CFStringCreateWithCString(NULL,
Jeff Thompson556cc302013-10-22 17:40:07 -0700464 keyNameUri.c_str(),
465 kCFStringEncodingUTF8);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700466
467 CFMutableDictionaryRef attrDict = CFDictionaryCreateMutable(NULL,
468 3,
469 &kCFTypeDictionaryKeyCallBacks,
470 NULL);
471
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800472 CFDictionaryAddValue(attrDict, kSecAttrKeyClass, impl_->getKeyClass(keyClass));
Jeff Thompson2747dc02013-10-04 19:11:34 -0700473 CFDictionaryAddValue(attrDict, kSecAttrLabel, keyLabel);
474 CFDictionaryAddValue(attrDict, kSecReturnRef, kCFBooleanTrue);
475
476 SecKeychainItemRef itemRef;
477 OSStatus res = SecItemCopyMatching((CFDictionaryRef)attrDict, (CFTypeRef*)&itemRef);
478
479 if(res == errSecItemNotFound)
480 return true;
481 else
482 return false;
483
484 }
485
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800486
487 ////////////////////////////////
488 // OSXPrivateKeyStorage::Impl //
489 ////////////////////////////////
490
491 SecKeychainItemRef
Yingdi Yu87581582014-01-14 14:28:39 -0800492 SecTpmOsx::Impl::getKey(const Name & keyName, KeyClass keyClass)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700493 {
494 string keyNameUri = toInternalKeyName(keyName, keyClass);
495
Jeff Thompson556cc302013-10-22 17:40:07 -0700496 CFStringRef keyLabel = CFStringCreateWithCString(NULL,
497 keyNameUri.c_str(),
498 kCFStringEncodingUTF8);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700499
500 CFMutableDictionaryRef attrDict = CFDictionaryCreateMutable(NULL,
501 5,
502 &kCFTypeDictionaryKeyCallBacks,
503 NULL);
504
505 CFDictionaryAddValue(attrDict, kSecClass, kSecClassKey);
506 CFDictionaryAddValue(attrDict, kSecAttrLabel, keyLabel);
507 CFDictionaryAddValue(attrDict, kSecAttrKeyClass, getKeyClass(keyClass));
508 CFDictionaryAddValue(attrDict, kSecReturnRef, kCFBooleanTrue);
509
510 SecKeychainItemRef keyItem;
511
512 OSStatus res = SecItemCopyMatching((CFDictionaryRef) attrDict, (CFTypeRef*)&keyItem);
513
514 if(res != errSecSuccess){
515 _LOG_DEBUG("Fail to find the key!");
516 return NULL;
517 }
518 else
519 return keyItem;
520 }
521
Yingdi Yu87581582014-01-14 14:28:39 -0800522 string
523 SecTpmOsx::Impl::toInternalKeyName(const Name & keyName, KeyClass keyClass)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700524 {
525 string keyUri = keyName.toUri();
526
527 if(KEY_CLASS_SYMMETRIC == keyClass)
528 return keyUri + "/symmetric";
529 else
530 return keyUri;
531 }
532
Yingdi Yu87581582014-01-14 14:28:39 -0800533 const CFTypeRef
534 SecTpmOsx::Impl::getAsymKeyType(KeyType keyType)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700535 {
536 switch(keyType){
537 case KEY_TYPE_RSA:
538 return kSecAttrKeyTypeRSA;
539 default:
540 _LOG_DEBUG("Unrecognized key type!")
541 return NULL;
542 }
543 }
544
Yingdi Yu87581582014-01-14 14:28:39 -0800545 const CFTypeRef
546 SecTpmOsx::Impl::getSymKeyType(KeyType keyType)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700547 {
548 switch(keyType){
549 case KEY_TYPE_AES:
550 return kSecAttrKeyTypeAES;
551 default:
552 _LOG_DEBUG("Unrecognized key type!")
553 return NULL;
554 }
555 }
556
Yingdi Yu87581582014-01-14 14:28:39 -0800557 const CFTypeRef
558 SecTpmOsx::Impl::getKeyClass(KeyClass keyClass)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700559 {
560 switch(keyClass){
561 case KEY_CLASS_PRIVATE:
562 return kSecAttrKeyClassPrivate;
563 case KEY_CLASS_PUBLIC:
564 return kSecAttrKeyClassPublic;
565 case KEY_CLASS_SYMMETRIC:
566 return kSecAttrKeyClassSymmetric;
567 default:
568 _LOG_DEBUG("Unrecognized key class!");
569 return NULL;
570 }
571 }
572
Yingdi Yu87581582014-01-14 14:28:39 -0800573 const CFStringRef
574 SecTpmOsx::Impl::getDigestAlgorithm(DigestAlgorithm digestAlgo)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700575 {
576 switch(digestAlgo){
577 // case DIGEST_MD2:
578 // return kSecDigestMD2;
579 // case DIGEST_MD5:
580 // return kSecDigestMD5;
581 // case DIGEST_SHA1:
582 // return kSecDigestSHA1;
583 case DIGEST_ALGORITHM_SHA256:
584 return kSecDigestSHA2;
585 default:
586 _LOG_DEBUG("Unrecognized digest algorithm!");
587 return NULL;
588 }
589 }
590
Yingdi Yu87581582014-01-14 14:28:39 -0800591 long
592 SecTpmOsx::Impl::getDigestSize(DigestAlgorithm digestAlgo)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700593 {
594 switch(digestAlgo){
595 case DIGEST_ALGORITHM_SHA256:
596 return 256;
597 // case DIGEST_SHA1:
598 // case DIGEST_MD2:
599 // case DIGEST_MD5:
600 // return 0;
601 default:
602 _LOG_DEBUG("Unrecognized digest algorithm! Unknown digest size");
603 return -1;
604 }
605 }
606
607}