blob: f41f89f1c44fceeccf6a6a33a2ef3733834ef7bf [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 Thompsonf21e2242013-10-09 19:01:49 -07008// Only compile if ndn-cpp-config.h defines NDN_CPP_HAVE_OSX_SECURITY 1.
Jeff Thompson6e229042013-10-10 11:09:49 -07009#include <ndn-cpp/ndn-cpp-config.h>
Jeff Thompsonf21e2242013-10-09 19:01:49 -070010#if NDN_CPP_HAVE_OSX_SECURITY
Jeff Thompson2747dc02013-10-04 19:11:34 -070011
12#include <fstream>
13#include <sstream>
Jeff Thompson2747dc02013-10-04 19:11:34 -070014
15#include "../../util/logging.hpp"
Alexander Afanasyev04b22a92014-01-05 22:40:17 -080016#include "osx-private-key-storage.hpp"
17#include "../certificate/public-key.hpp"
18
19#include <CoreFoundation/CoreFoundation.h>
20#include <Security/Security.h>
21#include <CoreServices/CoreServices.h>
Jeff Thompson2747dc02013-10-04 19:11:34 -070022
23using namespace std;
Jeff Thompson2747dc02013-10-04 19:11:34 -070024
25INIT_LOGGER("ndn.OSXPrivateKeyStorage");
26
27namespace ndn
28{
Alexander Afanasyev04b22a92014-01-05 22:40:17 -080029 class OSXPrivateKeyStorage::Impl {
30 public:
31 Impl(const std::string &keychainName)
32 : keyChainName_ ("" == keychainName ? "NDN.keychain" : keychainName)
33 {
34 }
35
36 /**
37 * convert NDN name of a key to internal name of the key
38 * @param keyName the NDN name of the key
39 * @param keyClass the class of the key
40 * @return the internal key name
41 */
42 std::string
43 toInternalKeyName(const Name & keyName, KeyClass keyClass);
44
45 /**
46 * Get key
47 * @param keyName the name of the key
48 * @param keyClass the class of the key
49 * @returns pointer to the key
50 */
51 SecKeychainItemRef
52 getKey(const Name & keyName, KeyClass keyClass);
53
54 /**
55 * convert keyType to MAC OS symmetric key key type
56 * @param keyType
57 * @returns MAC OS key type
58 */
59 const CFTypeRef
60 getSymKeyType(KeyType keyType);
61
62 /**
63 * convert keyType to MAC OS asymmetirc key type
64 * @param keyType
65 * @returns MAC OS key type
66 */
67 const CFTypeRef
68 getAsymKeyType(KeyType keyType);
69
70 /**
71 * convert keyClass to MAC OS key class
72 * @param keyClass
73 * @returns MAC OS key class
74 */
75 const CFTypeRef
76 getKeyClass(KeyClass keyClass);
77
78 /**
79 * convert digestAlgo to MAC OS algorithm id
80 * @param digestAlgo
81 * @returns MAC OS algorithm id
82 */
83 const CFStringRef
84 getDigestAlgorithm(DigestAlgorithm digestAlgo);
85
86 /**
87 * get the digest size of the corresponding algorithm
88 * @param digestAlgo the digest algorithm
89 * @return digest size
90 */
91 long
92 getDigestSize(DigestAlgorithm digestAlgo);
93
94 ///////////////////////////////////////////////
95 // everything here is public, including data //
96 ///////////////////////////////////////////////
97 public:
98 const std::string keyChainName_;
99 SecKeychainRef keyChainRef_;
100 SecKeychainRef originalDefaultKeyChain_;
101 };
102
103
104
Jeff Thompson2747dc02013-10-04 19:11:34 -0700105 OSXPrivateKeyStorage::OSXPrivateKeyStorage(const string & keychainName)
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800106 : impl_(new Impl(keychainName))
Jeff Thompson2747dc02013-10-04 19:11:34 -0700107 {
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800108 OSStatus res = SecKeychainCreate(impl_->keyChainName_.c_str(), //Keychain path
Jeff Thompson2747dc02013-10-04 19:11:34 -0700109 0, //Keychain password length
110 NULL, //Keychain password
111 true, //User prompt
112 NULL, //Initial access of Keychain
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800113 &impl_->keyChainRef_); //Keychain reference
Jeff Thompson2747dc02013-10-04 19:11:34 -0700114
115 if (res == errSecDuplicateKeychain)
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800116 res = SecKeychainOpen(impl_->keyChainName_.c_str(),
117 &impl_->keyChainRef_);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700118
119 if (res != errSecSuccess){
120 _LOG_DEBUG("Fail to initialize keychain ref: " << res);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800121 throw Error("Fail to initialize keychain ref");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700122 }
123
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800124 res = SecKeychainCopyDefault(&impl_->originalDefaultKeyChain_);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700125
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800126 res = SecKeychainSetDefault(impl_->keyChainRef_);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700127 if (res != errSecSuccess){
128 _LOG_DEBUG("Fail to set default keychain: " << res);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800129 throw Error("Fail to set default keychain");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700130 }
131 }
132
133 OSXPrivateKeyStorage::~OSXPrivateKeyStorage(){
134 //TODO: implement
135 }
136
137 void
138 OSXPrivateKeyStorage::generateKeyPair(const Name & keyName, KeyType keyType, int keySize)
139 {
140
141 if(doesKeyExist(keyName, KEY_CLASS_PUBLIC)){
142 _LOG_DEBUG("keyName has existed");
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800143 throw Error("keyName has existed");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700144 }
145
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800146 string keyNameUri = impl_->toInternalKeyName(keyName, KEY_CLASS_PUBLIC);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700147
148 SecKeyRef publicKey, privateKey;
149
150 CFStringRef keyLabel = CFStringCreateWithCString(NULL,
Jeff Thompson556cc302013-10-22 17:40:07 -0700151 keyNameUri.c_str(),
152 kCFStringEncodingUTF8);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700153
154 CFMutableDictionaryRef attrDict = CFDictionaryCreateMutable(NULL,
155 3,
156 &kCFTypeDictionaryKeyCallBacks,
157 NULL);
158
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800159 CFDictionaryAddValue(attrDict, kSecAttrKeyType, impl_->getAsymKeyType(keyType));
Jeff Thompson2747dc02013-10-04 19:11:34 -0700160 CFDictionaryAddValue(attrDict, kSecAttrKeySizeInBits, CFNumberCreate(NULL, kCFNumberIntType, &keySize));
161 CFDictionaryAddValue(attrDict, kSecAttrLabel, keyLabel);
162
163 OSStatus res = SecKeyGeneratePair((CFDictionaryRef)attrDict, &publicKey, &privateKey);
164
165 CFRelease(publicKey);
166 CFRelease(privateKey);
167
168 if (res != errSecSuccess){
169 _LOG_DEBUG("Fail to create a key pair: " << res);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800170 throw Error("Fail to create a key pair");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700171 }
172 }
173
174 void
175 OSXPrivateKeyStorage::generateKey(const Name & keyName, KeyType keyType, int keySize)
176 {
177
178 if(doesKeyExist(keyName, KEY_CLASS_SYMMETRIC))
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800179 throw Error("keyName has existed!");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700180
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800181 string keyNameUri = impl_->toInternalKeyName(keyName, KEY_CLASS_SYMMETRIC);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700182
183 CFMutableDictionaryRef attrDict = CFDictionaryCreateMutable(kCFAllocatorDefault,
184 0,
185 &kCFTypeDictionaryKeyCallBacks,
186 &kCFTypeDictionaryValueCallBacks);
187
188 CFStringRef keyLabel = CFStringCreateWithCString(NULL,
Jeff Thompson556cc302013-10-22 17:40:07 -0700189 keyNameUri.c_str(),
190 kCFStringEncodingUTF8);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700191
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800192 CFDictionaryAddValue(attrDict, kSecAttrKeyType, impl_->getSymKeyType(keyType));
Jeff Thompson2747dc02013-10-04 19:11:34 -0700193 CFDictionaryAddValue(attrDict, kSecAttrKeySizeInBits, CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &keySize));
194 CFDictionaryAddValue(attrDict, kSecAttrIsPermanent, kCFBooleanTrue);
195 CFDictionaryAddValue(attrDict, kSecAttrLabel, keyLabel);
196
197 CFErrorRef error = NULL;
198
199 SecKeyRef symmetricKey = SecKeyGenerateSymmetric(attrDict, &error);
200
201 if (error)
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800202 throw Error("Fail to create a symmetric key");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700203 }
204
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800205 ptr_lib::shared_ptr<PublicKey>
206 OSXPrivateKeyStorage::getPublicKey(const Name & keyName)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700207 {
208 _LOG_TRACE("OSXPrivateKeyStorage::getPublickey");
209
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800210 SecKeychainItemRef publicKey = impl_->getKey(keyName, KEY_CLASS_PUBLIC);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700211
212 CFDataRef exportedKey;
213
214 OSStatus res = SecItemExport(publicKey,
215 kSecFormatOpenSSL,
216 0,
217 NULL,
218 &exportedKey);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700219
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800220 return ptr_lib::make_shared<PublicKey>(CFDataGetBytePtr(exportedKey), CFDataGetLength(exportedKey));
Jeff Thompson2747dc02013-10-04 19:11:34 -0700221 }
222
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800223 Block
224 OSXPrivateKeyStorage::sign(const uint8_t *data, size_t dataLength,
225 const Name& keyName, DigestAlgorithm digestAlgorithm/* = DIGEST_ALGORITHM_SHA256*/)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700226 {
227 _LOG_TRACE("OSXPrivateKeyStorage::Sign");
228
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800229 CFDataRef dataRef = CFDataCreateWithBytesNoCopy(NULL,
230 data,
231 dataLength,
232 kCFAllocatorNull
233 );
Jeff Thompson2747dc02013-10-04 19:11:34 -0700234
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800235 SecKeyRef privateKey = (SecKeyRef)impl_->getKey(keyName, KEY_CLASS_PRIVATE);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700236
237 CFErrorRef error;
238 SecTransformRef signer = SecSignTransformCreate((SecKeyRef)privateKey, &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800239 if (error) throw Error("Fail to create signer");
240
241 // Set input
Jeff Thompson2747dc02013-10-04 19:11:34 -0700242 Boolean set_res = SecTransformSetAttribute(signer,
243 kSecTransformInputAttributeName,
244 dataRef,
245 &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800246 if (error) throw Error("Fail to configure input of signer");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700247
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800248 // Enable use of padding
249 SecTransformSetAttribute(
250 signer,
251 kSecPaddingKey,
252 kSecPaddingPKCS1Key,
253 &error);
254 if (error) throw Error("Fail to configure digest algorithm of signer");
255
256 // Set padding type
Jeff Thompson2747dc02013-10-04 19:11:34 -0700257 set_res = SecTransformSetAttribute(signer,
258 kSecDigestTypeAttribute,
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800259 impl_->getDigestAlgorithm(digestAlgorithm),
Jeff Thompson2747dc02013-10-04 19:11:34 -0700260 &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800261 if (error) throw Error("Fail to configure digest algorithm of signer");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700262
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800263 // Set padding attribute
264 long digestSize = impl_->getDigestSize(digestAlgorithm);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700265 set_res = SecTransformSetAttribute(signer,
266 kSecDigestLengthAttribute,
267 CFNumberCreate(NULL, kCFNumberLongType, &digestSize),
268 &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800269 if (error) throw Error("Fail to configure digest size of signer");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700270
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800271 // Actually sign
Jeff Thompson2747dc02013-10-04 19:11:34 -0700272 CFDataRef signature = (CFDataRef) SecTransformExecute(signer, &error);
273 if (error) {
274 CFShow(error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800275 throw Error("Fail to sign data");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700276 }
277
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800278 if (!signature) throw Error("Signature is NULL!\n");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700279
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800280 return Block(Tlv::SignatureValue, ptr_lib::make_shared<Buffer>(CFDataGetBytePtr(signature), CFDataGetLength(signature)));
Jeff Thompson2747dc02013-10-04 19:11:34 -0700281 }
282
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800283 void
284 OSXPrivateKeyStorage::sign(Data &data,
285 const Name& keyName, DigestAlgorithm digestAlgorithm/* = DIGEST_ALGORITHM_SHA256 */)
286 {
287 }
288
289 ConstBufferPtr
290 OSXPrivateKeyStorage::decrypt(const Name & keyName, const uint8_t* data, size_t dataLength, bool sym)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700291 {
292 _LOG_TRACE("OSXPrivateKeyStorage::Decrypt");
293
294 KeyClass keyClass;
295 if(sym)
296 keyClass = KEY_CLASS_SYMMETRIC;
297 else
298 keyClass = KEY_CLASS_PRIVATE;
299
300 CFDataRef dataRef = CFDataCreate(NULL,
301 reinterpret_cast<const unsigned char*>(data),
302 dataLength
303 );
304
305 // _LOG_DEBUG("CreateData");
306
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800307 SecKeyRef decryptKey = (SecKeyRef)impl_->getKey(keyName, keyClass);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700308
309 // _LOG_DEBUG("GetKey");
310
311 CFErrorRef error;
312 SecTransformRef decrypt = SecDecryptTransformCreate(decryptKey, &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800313 if (error) throw Error("Fail to create decrypt");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700314
315 Boolean set_res = SecTransformSetAttribute(decrypt,
316 kSecTransformInputAttributeName,
317 dataRef,
318 &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800319 if (error) throw Error("Fail to configure decrypt");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700320
321 CFDataRef output = (CFDataRef) SecTransformExecute(decrypt, &error);
322 if (error)
323 {
324 CFShow(error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800325 throw Error("Fail to decrypt data");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700326 }
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800327 if (!output) throw Error("Output is NULL!\n");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700328
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800329 return ptr_lib::make_shared<Buffer>(CFDataGetBytePtr(output), CFDataGetLength(output));
Jeff Thompson2747dc02013-10-04 19:11:34 -0700330 }
331
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800332 bool
333 OSXPrivateKeyStorage::setACL(const Name & keyName, KeyClass keyClass, int acl, const string & appPath)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700334 {
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800335 SecKeychainItemRef privateKey = impl_->getKey(keyName, keyClass);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700336
337 SecAccessRef accRef;
338 OSStatus acc_res = SecKeychainItemCopyAccess(privateKey, &accRef);
339
340 CFArrayRef signACL = SecAccessCopyMatchingACLList(accRef,
341 kSecACLAuthorizationSign);
342
343 SecACLRef aclRef = (SecACLRef) CFArrayGetValueAtIndex(signACL, 0);
344
345 CFArrayRef appList;
346 CFStringRef description;
347 SecKeychainPromptSelector promptSelector;
348 OSStatus acl_res = SecACLCopyContents(aclRef,
349 &appList,
350 &description,
351 &promptSelector);
352
353 CFMutableArrayRef newAppList = CFArrayCreateMutableCopy(NULL,
354 0,
355 appList);
356
357 SecTrustedApplicationRef trustedApp;
358 acl_res = SecTrustedApplicationCreateFromPath(appPath.c_str(),
359 &trustedApp);
360
361 CFArrayAppendValue(newAppList, trustedApp);
362
363
364 CFArrayRef authList = SecACLCopyAuthorizations(aclRef);
365
366 acl_res = SecACLRemove(aclRef);
367
368 SecACLRef newACL;
369 acl_res = SecACLCreateWithSimpleContents(accRef,
370 newAppList,
371 description,
372 promptSelector,
373 &newACL);
374
375 acl_res = SecACLUpdateAuthorizations(newACL, authList);
376
377 acc_res = SecKeychainItemSetAccess(privateKey, accRef);
378
379 return true;
380 }
381
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800382 // bool
383 // OSXPrivateKeyStorage::verifyData(const Name & keyName, const Blob & pData, const Blob & pSig, DigestAlgorithm digestAlgo)
384 // {
385 // _LOG_TRACE("OSXPrivateKeyStorage::Verify");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700386
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800387 // CFDataRef dataRef = CFDataCreate(NULL,
388 // reinterpret_cast<const unsigned char*>(pData.buf()),
389 // pData.size());
Jeff Thompson2747dc02013-10-04 19:11:34 -0700390
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800391 // CFDataRef sigRef = CFDataCreate(NULL,
392 // reinterpret_cast<const unsigned char*>(pSig.buf()),
393 // pSig.size());
Jeff Thompson2747dc02013-10-04 19:11:34 -0700394
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800395 // SecKeyRef publicKey = (SecKeyRef)impl_->getKey(keyName, KEY_CLASS_PUBLIC);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700396
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800397 // CFErrorRef error;
398 // SecTransformRef verifier = SecVerifyTransformCreate(publicKey, sigRef, &error);
399 // if (error) throw Error("Fail to create verifier");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700400
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800401 // Boolean set_res = SecTransformSetAttribute(verifier,
402 // kSecTransformInputAttributeName,
403 // dataRef,
404 // &error);
405 // if (error) throw Error("Fail to configure input of verifier");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700406
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800407 // set_res = SecTransformSetAttribute(verifier,
408 // kSecDigestTypeAttribute,
409 // impl_->getDigestAlgorithm(digestAlgo),
410 // &error);
411 // if (error) throw Error("Fail to configure digest algorithm of verifier");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700412
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800413 // long digestSize = impl_->getDigestSize(digestAlgo);
414 // set_res = SecTransformSetAttribute(verifier,
415 // kSecDigestLengthAttribute,
416 // CFNumberCreate(NULL, kCFNumberLongType, &digestSize),
417 // &error);
418 // if (error) throw Error("Fail to configure digest size of verifier");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700419
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800420 // CFBooleanRef result = (CFBooleanRef) SecTransformExecute(verifier, &error);
421 // if (error) throw Error("Fail to verify data");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700422
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800423 // if (result == kCFBooleanTrue)
424 // return true;
425 // else
426 // return false;
427 // }
Jeff Thompson2747dc02013-10-04 19:11:34 -0700428
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800429 ConstBufferPtr
430 OSXPrivateKeyStorage::encrypt(const Name & keyName, const uint8_t* data, size_t dataLength, bool sym)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700431 {
432 _LOG_TRACE("OSXPrivateKeyStorage::Encrypt");
433
434 KeyClass keyClass;
435 if(sym)
436 keyClass = KEY_CLASS_SYMMETRIC;
437 else
438 keyClass = KEY_CLASS_PUBLIC;
439
440 CFDataRef dataRef = CFDataCreate(NULL,
441 reinterpret_cast<const unsigned char*>(data),
442 dataLength
443 );
444
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800445 SecKeyRef encryptKey = (SecKeyRef)impl_->getKey(keyName, keyClass);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700446
447 CFErrorRef error;
448 SecTransformRef encrypt = SecEncryptTransformCreate(encryptKey, &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800449 if (error) throw Error("Fail to create encrypt");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700450
451 Boolean set_res = SecTransformSetAttribute(encrypt,
452 kSecTransformInputAttributeName,
453 dataRef,
454 &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800455 if (error) throw Error("Fail to configure encrypt");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700456
457 CFDataRef output = (CFDataRef) SecTransformExecute(encrypt, &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800458 if (error) throw Error("Fail to encrypt data");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700459
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800460 if (!output) throw Error("Output is NULL!\n");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700461
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800462 return ptr_lib::make_shared<Buffer> (CFDataGetBytePtr(output), CFDataGetLength(output));
Jeff Thompson2747dc02013-10-04 19:11:34 -0700463 }
464
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800465 bool
466 OSXPrivateKeyStorage::doesKeyExist(const Name & keyName, KeyClass keyClass)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700467 {
468 _LOG_TRACE("OSXPrivateKeyStorage::doesKeyExist");
469
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800470 string keyNameUri = impl_->toInternalKeyName(keyName, keyClass);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700471
472 CFStringRef keyLabel = CFStringCreateWithCString(NULL,
Jeff Thompson556cc302013-10-22 17:40:07 -0700473 keyNameUri.c_str(),
474 kCFStringEncodingUTF8);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700475
476 CFMutableDictionaryRef attrDict = CFDictionaryCreateMutable(NULL,
477 3,
478 &kCFTypeDictionaryKeyCallBacks,
479 NULL);
480
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800481 CFDictionaryAddValue(attrDict, kSecAttrKeyClass, impl_->getKeyClass(keyClass));
Jeff Thompson2747dc02013-10-04 19:11:34 -0700482 CFDictionaryAddValue(attrDict, kSecAttrLabel, keyLabel);
483 CFDictionaryAddValue(attrDict, kSecReturnRef, kCFBooleanTrue);
484
485 SecKeychainItemRef itemRef;
486 OSStatus res = SecItemCopyMatching((CFDictionaryRef)attrDict, (CFTypeRef*)&itemRef);
487
488 if(res == errSecItemNotFound)
489 return true;
490 else
491 return false;
492
493 }
494
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800495
496 ////////////////////////////////
497 // OSXPrivateKeyStorage::Impl //
498 ////////////////////////////////
499
500 SecKeychainItemRef
501 OSXPrivateKeyStorage::Impl::getKey(const Name & keyName, KeyClass keyClass)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700502 {
503 string keyNameUri = toInternalKeyName(keyName, keyClass);
504
Jeff Thompson556cc302013-10-22 17:40:07 -0700505 CFStringRef keyLabel = CFStringCreateWithCString(NULL,
506 keyNameUri.c_str(),
507 kCFStringEncodingUTF8);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700508
509 CFMutableDictionaryRef attrDict = CFDictionaryCreateMutable(NULL,
510 5,
511 &kCFTypeDictionaryKeyCallBacks,
512 NULL);
513
514 CFDictionaryAddValue(attrDict, kSecClass, kSecClassKey);
515 CFDictionaryAddValue(attrDict, kSecAttrLabel, keyLabel);
516 CFDictionaryAddValue(attrDict, kSecAttrKeyClass, getKeyClass(keyClass));
517 CFDictionaryAddValue(attrDict, kSecReturnRef, kCFBooleanTrue);
518
519 SecKeychainItemRef keyItem;
520
521 OSStatus res = SecItemCopyMatching((CFDictionaryRef) attrDict, (CFTypeRef*)&keyItem);
522
523 if(res != errSecSuccess){
524 _LOG_DEBUG("Fail to find the key!");
525 return NULL;
526 }
527 else
528 return keyItem;
529 }
530
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800531 string OSXPrivateKeyStorage::Impl::toInternalKeyName(const Name & keyName, KeyClass keyClass)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700532 {
533 string keyUri = keyName.toUri();
534
535 if(KEY_CLASS_SYMMETRIC == keyClass)
536 return keyUri + "/symmetric";
537 else
538 return keyUri;
539 }
540
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800541 const CFTypeRef OSXPrivateKeyStorage::Impl::getAsymKeyType(KeyType keyType)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700542 {
543 switch(keyType){
544 case KEY_TYPE_RSA:
545 return kSecAttrKeyTypeRSA;
546 default:
547 _LOG_DEBUG("Unrecognized key type!")
548 return NULL;
549 }
550 }
551
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800552 const CFTypeRef OSXPrivateKeyStorage::Impl::getSymKeyType(KeyType keyType)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700553 {
554 switch(keyType){
555 case KEY_TYPE_AES:
556 return kSecAttrKeyTypeAES;
557 default:
558 _LOG_DEBUG("Unrecognized key type!")
559 return NULL;
560 }
561 }
562
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800563 const CFTypeRef OSXPrivateKeyStorage::Impl::getKeyClass(KeyClass keyClass)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700564 {
565 switch(keyClass){
566 case KEY_CLASS_PRIVATE:
567 return kSecAttrKeyClassPrivate;
568 case KEY_CLASS_PUBLIC:
569 return kSecAttrKeyClassPublic;
570 case KEY_CLASS_SYMMETRIC:
571 return kSecAttrKeyClassSymmetric;
572 default:
573 _LOG_DEBUG("Unrecognized key class!");
574 return NULL;
575 }
576 }
577
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800578 const CFStringRef OSXPrivateKeyStorage::Impl::getDigestAlgorithm(DigestAlgorithm digestAlgo)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700579 {
580 switch(digestAlgo){
581 // case DIGEST_MD2:
582 // return kSecDigestMD2;
583 // case DIGEST_MD5:
584 // return kSecDigestMD5;
585 // case DIGEST_SHA1:
586 // return kSecDigestSHA1;
587 case DIGEST_ALGORITHM_SHA256:
588 return kSecDigestSHA2;
589 default:
590 _LOG_DEBUG("Unrecognized digest algorithm!");
591 return NULL;
592 }
593 }
594
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800595 long OSXPrivateKeyStorage::Impl::getDigestSize(DigestAlgorithm digestAlgo)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700596 {
597 switch(digestAlgo){
598 case DIGEST_ALGORITHM_SHA256:
599 return 256;
600 // case DIGEST_SHA1:
601 // case DIGEST_MD2:
602 // case DIGEST_MD5:
603 // return 0;
604 default:
605 _LOG_DEBUG("Unrecognized digest algorithm! Unknown digest size");
606 return -1;
607 }
608 }
609
610}
611
Jeff Thompsonc5647812013-10-11 18:06:38 -0700612#endif // NDN_CPP_HAVE_OSX_SECURITY