blob: f9954de675affa7c55e7ba8bfd2faea38df8556e [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 Afanasyevea23f572014-01-15 17:42:01 -0800285 data.setSignatureValue
286 (sign(data.wireEncode().value(),
287 data.wireEncode().value_size() - data.getSignature().getValue().size(),
288 keyName, digestAlgorithm));
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800289 }
290
291 ConstBufferPtr
Yingdi Yu87581582014-01-14 14:28:39 -0800292 SecTpmOsx::decrypt(const Name & keyName, const uint8_t* data, size_t dataLength, bool sym)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700293 {
294 _LOG_TRACE("OSXPrivateKeyStorage::Decrypt");
295
296 KeyClass keyClass;
297 if(sym)
298 keyClass = KEY_CLASS_SYMMETRIC;
299 else
300 keyClass = KEY_CLASS_PRIVATE;
301
302 CFDataRef dataRef = CFDataCreate(NULL,
303 reinterpret_cast<const unsigned char*>(data),
304 dataLength
305 );
306
307 // _LOG_DEBUG("CreateData");
308
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800309 SecKeyRef decryptKey = (SecKeyRef)impl_->getKey(keyName, keyClass);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700310
311 // _LOG_DEBUG("GetKey");
312
313 CFErrorRef error;
314 SecTransformRef decrypt = SecDecryptTransformCreate(decryptKey, &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800315 if (error) throw Error("Fail to create decrypt");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700316
317 Boolean set_res = SecTransformSetAttribute(decrypt,
318 kSecTransformInputAttributeName,
319 dataRef,
320 &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800321 if (error) throw Error("Fail to configure decrypt");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700322
323 CFDataRef output = (CFDataRef) SecTransformExecute(decrypt, &error);
324 if (error)
325 {
326 CFShow(error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800327 throw Error("Fail to decrypt data");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700328 }
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800329 if (!output) throw Error("Output is NULL!\n");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700330
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800331 return ptr_lib::make_shared<Buffer>(CFDataGetBytePtr(output), CFDataGetLength(output));
Jeff Thompson2747dc02013-10-04 19:11:34 -0700332 }
333
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800334 bool
Yingdi Yu87581582014-01-14 14:28:39 -0800335 SecTpmOsx::setACL(const Name & keyName, KeyClass keyClass, int acl, const string & appPath)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700336 {
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800337 SecKeychainItemRef privateKey = impl_->getKey(keyName, keyClass);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700338
339 SecAccessRef accRef;
340 OSStatus acc_res = SecKeychainItemCopyAccess(privateKey, &accRef);
341
342 CFArrayRef signACL = SecAccessCopyMatchingACLList(accRef,
343 kSecACLAuthorizationSign);
344
345 SecACLRef aclRef = (SecACLRef) CFArrayGetValueAtIndex(signACL, 0);
346
347 CFArrayRef appList;
348 CFStringRef description;
349 SecKeychainPromptSelector promptSelector;
350 OSStatus acl_res = SecACLCopyContents(aclRef,
351 &appList,
352 &description,
353 &promptSelector);
354
355 CFMutableArrayRef newAppList = CFArrayCreateMutableCopy(NULL,
356 0,
357 appList);
358
359 SecTrustedApplicationRef trustedApp;
360 acl_res = SecTrustedApplicationCreateFromPath(appPath.c_str(),
361 &trustedApp);
362
363 CFArrayAppendValue(newAppList, trustedApp);
364
365
366 CFArrayRef authList = SecACLCopyAuthorizations(aclRef);
367
368 acl_res = SecACLRemove(aclRef);
369
370 SecACLRef newACL;
371 acl_res = SecACLCreateWithSimpleContents(accRef,
372 newAppList,
373 description,
374 promptSelector,
375 &newACL);
376
377 acl_res = SecACLUpdateAuthorizations(newACL, authList);
378
379 acc_res = SecKeychainItemSetAccess(privateKey, accRef);
380
381 return true;
382 }
383
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800384 // bool
385 // OSXPrivateKeyStorage::verifyData(const Name & keyName, const Blob & pData, const Blob & pSig, DigestAlgorithm digestAlgo)
386 // {
387 // _LOG_TRACE("OSXPrivateKeyStorage::Verify");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700388
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800389 // CFDataRef dataRef = CFDataCreate(NULL,
390 // reinterpret_cast<const unsigned char*>(pData.buf()),
391 // pData.size());
Jeff Thompson2747dc02013-10-04 19:11:34 -0700392
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800393 // CFDataRef sigRef = CFDataCreate(NULL,
394 // reinterpret_cast<const unsigned char*>(pSig.buf()),
395 // pSig.size());
Jeff Thompson2747dc02013-10-04 19:11:34 -0700396
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800397 // SecKeyRef publicKey = (SecKeyRef)impl_->getKey(keyName, KEY_CLASS_PUBLIC);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700398
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800399 // CFErrorRef error;
400 // SecTransformRef verifier = SecVerifyTransformCreate(publicKey, sigRef, &error);
401 // if (error) throw Error("Fail to create verifier");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700402
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800403 // Boolean set_res = SecTransformSetAttribute(verifier,
404 // kSecTransformInputAttributeName,
405 // dataRef,
406 // &error);
407 // if (error) throw Error("Fail to configure input of verifier");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700408
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800409 // set_res = SecTransformSetAttribute(verifier,
410 // kSecDigestTypeAttribute,
411 // impl_->getDigestAlgorithm(digestAlgo),
412 // &error);
413 // if (error) throw Error("Fail to configure digest algorithm of verifier");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700414
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800415 // long digestSize = impl_->getDigestSize(digestAlgo);
416 // set_res = SecTransformSetAttribute(verifier,
417 // kSecDigestLengthAttribute,
418 // CFNumberCreate(NULL, kCFNumberLongType, &digestSize),
419 // &error);
420 // if (error) throw Error("Fail to configure digest size of verifier");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700421
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800422 // CFBooleanRef result = (CFBooleanRef) SecTransformExecute(verifier, &error);
423 // if (error) throw Error("Fail to verify data");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700424
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800425 // if (result == kCFBooleanTrue)
426 // return true;
427 // else
428 // return false;
429 // }
Jeff Thompson2747dc02013-10-04 19:11:34 -0700430
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800431 ConstBufferPtr
Yingdi Yu87581582014-01-14 14:28:39 -0800432 SecTpmOsx::encrypt(const Name & keyName, const uint8_t* data, size_t dataLength, bool sym)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700433 {
434 _LOG_TRACE("OSXPrivateKeyStorage::Encrypt");
435
436 KeyClass keyClass;
437 if(sym)
438 keyClass = KEY_CLASS_SYMMETRIC;
439 else
440 keyClass = KEY_CLASS_PUBLIC;
441
442 CFDataRef dataRef = CFDataCreate(NULL,
443 reinterpret_cast<const unsigned char*>(data),
444 dataLength
445 );
446
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800447 SecKeyRef encryptKey = (SecKeyRef)impl_->getKey(keyName, keyClass);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700448
449 CFErrorRef error;
450 SecTransformRef encrypt = SecEncryptTransformCreate(encryptKey, &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800451 if (error) throw Error("Fail to create encrypt");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700452
453 Boolean set_res = SecTransformSetAttribute(encrypt,
454 kSecTransformInputAttributeName,
455 dataRef,
456 &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800457 if (error) throw Error("Fail to configure encrypt");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700458
459 CFDataRef output = (CFDataRef) SecTransformExecute(encrypt, &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800460 if (error) throw Error("Fail to encrypt data");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700461
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800462 if (!output) throw Error("Output is NULL!\n");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700463
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800464 return ptr_lib::make_shared<Buffer> (CFDataGetBytePtr(output), CFDataGetLength(output));
Jeff Thompson2747dc02013-10-04 19:11:34 -0700465 }
466
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800467 bool
Yingdi Yu87581582014-01-14 14:28:39 -0800468 SecTpmOsx::doesKeyExist(const Name & keyName, KeyClass keyClass)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700469 {
470 _LOG_TRACE("OSXPrivateKeyStorage::doesKeyExist");
471
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800472 string keyNameUri = impl_->toInternalKeyName(keyName, keyClass);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700473
474 CFStringRef keyLabel = CFStringCreateWithCString(NULL,
Jeff Thompson556cc302013-10-22 17:40:07 -0700475 keyNameUri.c_str(),
476 kCFStringEncodingUTF8);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700477
478 CFMutableDictionaryRef attrDict = CFDictionaryCreateMutable(NULL,
479 3,
480 &kCFTypeDictionaryKeyCallBacks,
481 NULL);
482
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800483 CFDictionaryAddValue(attrDict, kSecAttrKeyClass, impl_->getKeyClass(keyClass));
Jeff Thompson2747dc02013-10-04 19:11:34 -0700484 CFDictionaryAddValue(attrDict, kSecAttrLabel, keyLabel);
485 CFDictionaryAddValue(attrDict, kSecReturnRef, kCFBooleanTrue);
486
487 SecKeychainItemRef itemRef;
488 OSStatus res = SecItemCopyMatching((CFDictionaryRef)attrDict, (CFTypeRef*)&itemRef);
489
490 if(res == errSecItemNotFound)
491 return true;
492 else
493 return false;
494
495 }
496
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800497
498 ////////////////////////////////
499 // OSXPrivateKeyStorage::Impl //
500 ////////////////////////////////
501
502 SecKeychainItemRef
Yingdi Yu87581582014-01-14 14:28:39 -0800503 SecTpmOsx::Impl::getKey(const Name & keyName, KeyClass keyClass)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700504 {
505 string keyNameUri = toInternalKeyName(keyName, keyClass);
506
Jeff Thompson556cc302013-10-22 17:40:07 -0700507 CFStringRef keyLabel = CFStringCreateWithCString(NULL,
508 keyNameUri.c_str(),
509 kCFStringEncodingUTF8);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700510
511 CFMutableDictionaryRef attrDict = CFDictionaryCreateMutable(NULL,
512 5,
513 &kCFTypeDictionaryKeyCallBacks,
514 NULL);
515
516 CFDictionaryAddValue(attrDict, kSecClass, kSecClassKey);
517 CFDictionaryAddValue(attrDict, kSecAttrLabel, keyLabel);
518 CFDictionaryAddValue(attrDict, kSecAttrKeyClass, getKeyClass(keyClass));
519 CFDictionaryAddValue(attrDict, kSecReturnRef, kCFBooleanTrue);
520
521 SecKeychainItemRef keyItem;
522
523 OSStatus res = SecItemCopyMatching((CFDictionaryRef) attrDict, (CFTypeRef*)&keyItem);
524
525 if(res != errSecSuccess){
526 _LOG_DEBUG("Fail to find the key!");
527 return NULL;
528 }
529 else
530 return keyItem;
531 }
532
Yingdi Yu87581582014-01-14 14:28:39 -0800533 string
534 SecTpmOsx::Impl::toInternalKeyName(const Name & keyName, KeyClass keyClass)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700535 {
536 string keyUri = keyName.toUri();
537
538 if(KEY_CLASS_SYMMETRIC == keyClass)
539 return keyUri + "/symmetric";
540 else
541 return keyUri;
542 }
543
Yingdi Yu87581582014-01-14 14:28:39 -0800544 const CFTypeRef
545 SecTpmOsx::Impl::getAsymKeyType(KeyType keyType)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700546 {
547 switch(keyType){
548 case KEY_TYPE_RSA:
549 return kSecAttrKeyTypeRSA;
550 default:
551 _LOG_DEBUG("Unrecognized key type!")
552 return NULL;
553 }
554 }
555
Yingdi Yu87581582014-01-14 14:28:39 -0800556 const CFTypeRef
557 SecTpmOsx::Impl::getSymKeyType(KeyType keyType)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700558 {
559 switch(keyType){
560 case KEY_TYPE_AES:
561 return kSecAttrKeyTypeAES;
562 default:
563 _LOG_DEBUG("Unrecognized key type!")
564 return NULL;
565 }
566 }
567
Yingdi Yu87581582014-01-14 14:28:39 -0800568 const CFTypeRef
569 SecTpmOsx::Impl::getKeyClass(KeyClass keyClass)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700570 {
571 switch(keyClass){
572 case KEY_CLASS_PRIVATE:
573 return kSecAttrKeyClassPrivate;
574 case KEY_CLASS_PUBLIC:
575 return kSecAttrKeyClassPublic;
576 case KEY_CLASS_SYMMETRIC:
577 return kSecAttrKeyClassSymmetric;
578 default:
579 _LOG_DEBUG("Unrecognized key class!");
580 return NULL;
581 }
582 }
583
Yingdi Yu87581582014-01-14 14:28:39 -0800584 const CFStringRef
585 SecTpmOsx::Impl::getDigestAlgorithm(DigestAlgorithm digestAlgo)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700586 {
587 switch(digestAlgo){
588 // case DIGEST_MD2:
589 // return kSecDigestMD2;
590 // case DIGEST_MD5:
591 // return kSecDigestMD5;
592 // case DIGEST_SHA1:
593 // return kSecDigestSHA1;
594 case DIGEST_ALGORITHM_SHA256:
595 return kSecDigestSHA2;
596 default:
597 _LOG_DEBUG("Unrecognized digest algorithm!");
598 return NULL;
599 }
600 }
601
Yingdi Yu87581582014-01-14 14:28:39 -0800602 long
603 SecTpmOsx::Impl::getDigestSize(DigestAlgorithm digestAlgo)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700604 {
605 switch(digestAlgo){
606 case DIGEST_ALGORITHM_SHA256:
607 return 256;
608 // case DIGEST_SHA1:
609 // case DIGEST_MD2:
610 // case DIGEST_MD5:
611 // return 0;
612 default:
613 _LOG_DEBUG("Unrecognized digest algorithm! Unknown digest size");
614 return -1;
615 }
616 }
617
618}