blob: 9fad3673cfa963f905cbc3e3243098ad0989d6a5 [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
Jeff Thompson6e229042013-10-10 11:09:49 -07008#include <ndn-cpp/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
13#include "../../util/logging.hpp"
Alexander Afanasyev6be1a6a2014-01-06 00:08:14 -080014
Yingdi Yu87581582014-01-14 14:28:39 -080015#include <ndn-cpp/security/identity/sec-tpm-osx.hpp>
Alexander Afanasyev6be1a6a2014-01-06 00:08:14 -080016#include <ndn-cpp/security/certificate/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
140 if(doesKeyExist(keyName, KEY_CLASS_PUBLIC)){
141 _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 Yu87581582014-01-14 14:28:39 -0800174 SecTpmOsx::generateSymmetricKey(const Name & keyName, KeyType keyType, int keySize)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700175 {
176
177 if(doesKeyExist(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 Yu87581582014-01-14 14:28:39 -0800223 SecTpmOsx::sign(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 void
Yingdi Yu87581582014-01-14 14:28:39 -0800283 SecTpmOsx::sign(Data &data, const Name& keyName, DigestAlgorithm digestAlgorithm)
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800284 {
Alexander Afanasyevbd5ba402014-01-05 22:41:09 -0800285 const uint8_t *begin = data.wireEncode().value();
286 const uint8_t *end = &*data.getSignature().getInfo().end();
287
288 data.setSignature
289 (sign(begin, end-begin, keyName, digestAlgorithm));
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800290 }
291
292 ConstBufferPtr
Yingdi Yu87581582014-01-14 14:28:39 -0800293 SecTpmOsx::decrypt(const Name & keyName, const uint8_t* data, size_t dataLength, bool sym)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700294 {
295 _LOG_TRACE("OSXPrivateKeyStorage::Decrypt");
296
297 KeyClass keyClass;
298 if(sym)
299 keyClass = KEY_CLASS_SYMMETRIC;
300 else
301 keyClass = KEY_CLASS_PRIVATE;
302
303 CFDataRef dataRef = CFDataCreate(NULL,
304 reinterpret_cast<const unsigned char*>(data),
305 dataLength
306 );
307
308 // _LOG_DEBUG("CreateData");
309
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800310 SecKeyRef decryptKey = (SecKeyRef)impl_->getKey(keyName, keyClass);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700311
312 // _LOG_DEBUG("GetKey");
313
314 CFErrorRef error;
315 SecTransformRef decrypt = SecDecryptTransformCreate(decryptKey, &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800316 if (error) throw Error("Fail to create decrypt");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700317
318 Boolean set_res = SecTransformSetAttribute(decrypt,
319 kSecTransformInputAttributeName,
320 dataRef,
321 &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800322 if (error) throw Error("Fail to configure decrypt");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700323
324 CFDataRef output = (CFDataRef) SecTransformExecute(decrypt, &error);
325 if (error)
326 {
327 CFShow(error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800328 throw Error("Fail to decrypt data");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700329 }
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800330 if (!output) throw Error("Output is NULL!\n");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700331
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800332 return ptr_lib::make_shared<Buffer>(CFDataGetBytePtr(output), CFDataGetLength(output));
Jeff Thompson2747dc02013-10-04 19:11:34 -0700333 }
334
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800335 bool
Yingdi Yu87581582014-01-14 14:28:39 -0800336 SecTpmOsx::setACL(const Name & keyName, KeyClass keyClass, int acl, const string & appPath)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700337 {
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800338 SecKeychainItemRef privateKey = impl_->getKey(keyName, keyClass);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700339
340 SecAccessRef accRef;
341 OSStatus acc_res = SecKeychainItemCopyAccess(privateKey, &accRef);
342
343 CFArrayRef signACL = SecAccessCopyMatchingACLList(accRef,
344 kSecACLAuthorizationSign);
345
346 SecACLRef aclRef = (SecACLRef) CFArrayGetValueAtIndex(signACL, 0);
347
348 CFArrayRef appList;
349 CFStringRef description;
350 SecKeychainPromptSelector promptSelector;
351 OSStatus acl_res = SecACLCopyContents(aclRef,
352 &appList,
353 &description,
354 &promptSelector);
355
356 CFMutableArrayRef newAppList = CFArrayCreateMutableCopy(NULL,
357 0,
358 appList);
359
360 SecTrustedApplicationRef trustedApp;
361 acl_res = SecTrustedApplicationCreateFromPath(appPath.c_str(),
362 &trustedApp);
363
364 CFArrayAppendValue(newAppList, trustedApp);
365
366
367 CFArrayRef authList = SecACLCopyAuthorizations(aclRef);
368
369 acl_res = SecACLRemove(aclRef);
370
371 SecACLRef newACL;
372 acl_res = SecACLCreateWithSimpleContents(accRef,
373 newAppList,
374 description,
375 promptSelector,
376 &newACL);
377
378 acl_res = SecACLUpdateAuthorizations(newACL, authList);
379
380 acc_res = SecKeychainItemSetAccess(privateKey, accRef);
381
382 return true;
383 }
384
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800385 // bool
386 // OSXPrivateKeyStorage::verifyData(const Name & keyName, const Blob & pData, const Blob & pSig, DigestAlgorithm digestAlgo)
387 // {
388 // _LOG_TRACE("OSXPrivateKeyStorage::Verify");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700389
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800390 // CFDataRef dataRef = CFDataCreate(NULL,
391 // reinterpret_cast<const unsigned char*>(pData.buf()),
392 // pData.size());
Jeff Thompson2747dc02013-10-04 19:11:34 -0700393
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800394 // CFDataRef sigRef = CFDataCreate(NULL,
395 // reinterpret_cast<const unsigned char*>(pSig.buf()),
396 // pSig.size());
Jeff Thompson2747dc02013-10-04 19:11:34 -0700397
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800398 // SecKeyRef publicKey = (SecKeyRef)impl_->getKey(keyName, KEY_CLASS_PUBLIC);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700399
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800400 // CFErrorRef error;
401 // SecTransformRef verifier = SecVerifyTransformCreate(publicKey, sigRef, &error);
402 // if (error) throw Error("Fail to create verifier");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700403
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800404 // Boolean set_res = SecTransformSetAttribute(verifier,
405 // kSecTransformInputAttributeName,
406 // dataRef,
407 // &error);
408 // if (error) throw Error("Fail to configure input of verifier");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700409
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800410 // set_res = SecTransformSetAttribute(verifier,
411 // kSecDigestTypeAttribute,
412 // impl_->getDigestAlgorithm(digestAlgo),
413 // &error);
414 // if (error) throw Error("Fail to configure digest algorithm of verifier");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700415
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800416 // long digestSize = impl_->getDigestSize(digestAlgo);
417 // set_res = SecTransformSetAttribute(verifier,
418 // kSecDigestLengthAttribute,
419 // CFNumberCreate(NULL, kCFNumberLongType, &digestSize),
420 // &error);
421 // if (error) throw Error("Fail to configure digest size of verifier");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700422
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800423 // CFBooleanRef result = (CFBooleanRef) SecTransformExecute(verifier, &error);
424 // if (error) throw Error("Fail to verify data");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700425
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800426 // if (result == kCFBooleanTrue)
427 // return true;
428 // else
429 // return false;
430 // }
Jeff Thompson2747dc02013-10-04 19:11:34 -0700431
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800432 ConstBufferPtr
Yingdi Yu87581582014-01-14 14:28:39 -0800433 SecTpmOsx::encrypt(const Name & keyName, const uint8_t* data, size_t dataLength, bool sym)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700434 {
435 _LOG_TRACE("OSXPrivateKeyStorage::Encrypt");
436
437 KeyClass keyClass;
438 if(sym)
439 keyClass = KEY_CLASS_SYMMETRIC;
440 else
441 keyClass = KEY_CLASS_PUBLIC;
442
443 CFDataRef dataRef = CFDataCreate(NULL,
444 reinterpret_cast<const unsigned char*>(data),
445 dataLength
446 );
447
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800448 SecKeyRef encryptKey = (SecKeyRef)impl_->getKey(keyName, keyClass);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700449
450 CFErrorRef error;
451 SecTransformRef encrypt = SecEncryptTransformCreate(encryptKey, &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800452 if (error) throw Error("Fail to create encrypt");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700453
454 Boolean set_res = SecTransformSetAttribute(encrypt,
455 kSecTransformInputAttributeName,
456 dataRef,
457 &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800458 if (error) throw Error("Fail to configure encrypt");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700459
460 CFDataRef output = (CFDataRef) SecTransformExecute(encrypt, &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800461 if (error) throw Error("Fail to encrypt data");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700462
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800463 if (!output) throw Error("Output is NULL!\n");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700464
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800465 return ptr_lib::make_shared<Buffer> (CFDataGetBytePtr(output), CFDataGetLength(output));
Jeff Thompson2747dc02013-10-04 19:11:34 -0700466 }
467
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800468 bool
Yingdi Yu87581582014-01-14 14:28:39 -0800469 SecTpmOsx::doesKeyExist(const Name & keyName, KeyClass keyClass)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700470 {
471 _LOG_TRACE("OSXPrivateKeyStorage::doesKeyExist");
472
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800473 string keyNameUri = impl_->toInternalKeyName(keyName, keyClass);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700474
475 CFStringRef keyLabel = CFStringCreateWithCString(NULL,
Jeff Thompson556cc302013-10-22 17:40:07 -0700476 keyNameUri.c_str(),
477 kCFStringEncodingUTF8);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700478
479 CFMutableDictionaryRef attrDict = CFDictionaryCreateMutable(NULL,
480 3,
481 &kCFTypeDictionaryKeyCallBacks,
482 NULL);
483
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800484 CFDictionaryAddValue(attrDict, kSecAttrKeyClass, impl_->getKeyClass(keyClass));
Jeff Thompson2747dc02013-10-04 19:11:34 -0700485 CFDictionaryAddValue(attrDict, kSecAttrLabel, keyLabel);
486 CFDictionaryAddValue(attrDict, kSecReturnRef, kCFBooleanTrue);
487
488 SecKeychainItemRef itemRef;
489 OSStatus res = SecItemCopyMatching((CFDictionaryRef)attrDict, (CFTypeRef*)&itemRef);
490
491 if(res == errSecItemNotFound)
492 return true;
493 else
494 return false;
495
496 }
497
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800498
499 ////////////////////////////////
500 // OSXPrivateKeyStorage::Impl //
501 ////////////////////////////////
502
503 SecKeychainItemRef
Yingdi Yu87581582014-01-14 14:28:39 -0800504 SecTpmOsx::Impl::getKey(const Name & keyName, KeyClass keyClass)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700505 {
506 string keyNameUri = toInternalKeyName(keyName, keyClass);
507
Jeff Thompson556cc302013-10-22 17:40:07 -0700508 CFStringRef keyLabel = CFStringCreateWithCString(NULL,
509 keyNameUri.c_str(),
510 kCFStringEncodingUTF8);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700511
512 CFMutableDictionaryRef attrDict = CFDictionaryCreateMutable(NULL,
513 5,
514 &kCFTypeDictionaryKeyCallBacks,
515 NULL);
516
517 CFDictionaryAddValue(attrDict, kSecClass, kSecClassKey);
518 CFDictionaryAddValue(attrDict, kSecAttrLabel, keyLabel);
519 CFDictionaryAddValue(attrDict, kSecAttrKeyClass, getKeyClass(keyClass));
520 CFDictionaryAddValue(attrDict, kSecReturnRef, kCFBooleanTrue);
521
522 SecKeychainItemRef keyItem;
523
524 OSStatus res = SecItemCopyMatching((CFDictionaryRef) attrDict, (CFTypeRef*)&keyItem);
525
526 if(res != errSecSuccess){
527 _LOG_DEBUG("Fail to find the key!");
528 return NULL;
529 }
530 else
531 return keyItem;
532 }
533
Yingdi Yu87581582014-01-14 14:28:39 -0800534 string
535 SecTpmOsx::Impl::toInternalKeyName(const Name & keyName, KeyClass keyClass)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700536 {
537 string keyUri = keyName.toUri();
538
539 if(KEY_CLASS_SYMMETRIC == keyClass)
540 return keyUri + "/symmetric";
541 else
542 return keyUri;
543 }
544
Yingdi Yu87581582014-01-14 14:28:39 -0800545 const CFTypeRef
546 SecTpmOsx::Impl::getAsymKeyType(KeyType keyType)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700547 {
548 switch(keyType){
549 case KEY_TYPE_RSA:
550 return kSecAttrKeyTypeRSA;
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::getSymKeyType(KeyType keyType)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700559 {
560 switch(keyType){
561 case KEY_TYPE_AES:
562 return kSecAttrKeyTypeAES;
563 default:
564 _LOG_DEBUG("Unrecognized key type!")
565 return NULL;
566 }
567 }
568
Yingdi Yu87581582014-01-14 14:28:39 -0800569 const CFTypeRef
570 SecTpmOsx::Impl::getKeyClass(KeyClass keyClass)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700571 {
572 switch(keyClass){
573 case KEY_CLASS_PRIVATE:
574 return kSecAttrKeyClassPrivate;
575 case KEY_CLASS_PUBLIC:
576 return kSecAttrKeyClassPublic;
577 case KEY_CLASS_SYMMETRIC:
578 return kSecAttrKeyClassSymmetric;
579 default:
580 _LOG_DEBUG("Unrecognized key class!");
581 return NULL;
582 }
583 }
584
Yingdi Yu87581582014-01-14 14:28:39 -0800585 const CFStringRef
586 SecTpmOsx::Impl::getDigestAlgorithm(DigestAlgorithm digestAlgo)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700587 {
588 switch(digestAlgo){
589 // case DIGEST_MD2:
590 // return kSecDigestMD2;
591 // case DIGEST_MD5:
592 // return kSecDigestMD5;
593 // case DIGEST_SHA1:
594 // return kSecDigestSHA1;
595 case DIGEST_ALGORITHM_SHA256:
596 return kSecDigestSHA2;
597 default:
598 _LOG_DEBUG("Unrecognized digest algorithm!");
599 return NULL;
600 }
601 }
602
Yingdi Yu87581582014-01-14 14:28:39 -0800603 long
604 SecTpmOsx::Impl::getDigestSize(DigestAlgorithm digestAlgo)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700605 {
606 switch(digestAlgo){
607 case DIGEST_ALGORITHM_SHA256:
608 return 256;
609 // case DIGEST_SHA1:
610 // case DIGEST_MD2:
611 // case DIGEST_MD5:
612 // return 0;
613 default:
614 _LOG_DEBUG("Unrecognized digest algorithm! Unknown digest size");
615 return -1;
616 }
617 }
618
619}