blob: fec767102a3f8681ca214623d323ad0cb08f5bd0 [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 Afanasyevbd5ba402014-01-05 22:41:09 -0800280 return Block(Tlv::SignatureValue,
281 ptr_lib::make_shared<Buffer>(CFDataGetBytePtr(signature), CFDataGetLength(signature)));
Jeff Thompson2747dc02013-10-04 19:11:34 -0700282 }
283
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800284 void
285 OSXPrivateKeyStorage::sign(Data &data,
286 const Name& keyName, DigestAlgorithm digestAlgorithm/* = DIGEST_ALGORITHM_SHA256 */)
287 {
Alexander Afanasyevbd5ba402014-01-05 22:41:09 -0800288 const uint8_t *begin = data.wireEncode().value();
289 const uint8_t *end = &*data.getSignature().getInfo().end();
290
291 data.setSignature
292 (sign(begin, end-begin, keyName, digestAlgorithm));
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800293 }
294
295 ConstBufferPtr
296 OSXPrivateKeyStorage::decrypt(const Name & keyName, const uint8_t* data, size_t dataLength, bool sym)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700297 {
298 _LOG_TRACE("OSXPrivateKeyStorage::Decrypt");
299
300 KeyClass keyClass;
301 if(sym)
302 keyClass = KEY_CLASS_SYMMETRIC;
303 else
304 keyClass = KEY_CLASS_PRIVATE;
305
306 CFDataRef dataRef = CFDataCreate(NULL,
307 reinterpret_cast<const unsigned char*>(data),
308 dataLength
309 );
310
311 // _LOG_DEBUG("CreateData");
312
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800313 SecKeyRef decryptKey = (SecKeyRef)impl_->getKey(keyName, keyClass);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700314
315 // _LOG_DEBUG("GetKey");
316
317 CFErrorRef error;
318 SecTransformRef decrypt = SecDecryptTransformCreate(decryptKey, &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800319 if (error) throw Error("Fail to create decrypt");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700320
321 Boolean set_res = SecTransformSetAttribute(decrypt,
322 kSecTransformInputAttributeName,
323 dataRef,
324 &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800325 if (error) throw Error("Fail to configure decrypt");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700326
327 CFDataRef output = (CFDataRef) SecTransformExecute(decrypt, &error);
328 if (error)
329 {
330 CFShow(error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800331 throw Error("Fail to decrypt data");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700332 }
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800333 if (!output) throw Error("Output is NULL!\n");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700334
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800335 return ptr_lib::make_shared<Buffer>(CFDataGetBytePtr(output), CFDataGetLength(output));
Jeff Thompson2747dc02013-10-04 19:11:34 -0700336 }
337
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800338 bool
339 OSXPrivateKeyStorage::setACL(const Name & keyName, KeyClass keyClass, int acl, const string & appPath)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700340 {
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800341 SecKeychainItemRef privateKey = impl_->getKey(keyName, keyClass);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700342
343 SecAccessRef accRef;
344 OSStatus acc_res = SecKeychainItemCopyAccess(privateKey, &accRef);
345
346 CFArrayRef signACL = SecAccessCopyMatchingACLList(accRef,
347 kSecACLAuthorizationSign);
348
349 SecACLRef aclRef = (SecACLRef) CFArrayGetValueAtIndex(signACL, 0);
350
351 CFArrayRef appList;
352 CFStringRef description;
353 SecKeychainPromptSelector promptSelector;
354 OSStatus acl_res = SecACLCopyContents(aclRef,
355 &appList,
356 &description,
357 &promptSelector);
358
359 CFMutableArrayRef newAppList = CFArrayCreateMutableCopy(NULL,
360 0,
361 appList);
362
363 SecTrustedApplicationRef trustedApp;
364 acl_res = SecTrustedApplicationCreateFromPath(appPath.c_str(),
365 &trustedApp);
366
367 CFArrayAppendValue(newAppList, trustedApp);
368
369
370 CFArrayRef authList = SecACLCopyAuthorizations(aclRef);
371
372 acl_res = SecACLRemove(aclRef);
373
374 SecACLRef newACL;
375 acl_res = SecACLCreateWithSimpleContents(accRef,
376 newAppList,
377 description,
378 promptSelector,
379 &newACL);
380
381 acl_res = SecACLUpdateAuthorizations(newACL, authList);
382
383 acc_res = SecKeychainItemSetAccess(privateKey, accRef);
384
385 return true;
386 }
387
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800388 // bool
389 // OSXPrivateKeyStorage::verifyData(const Name & keyName, const Blob & pData, const Blob & pSig, DigestAlgorithm digestAlgo)
390 // {
391 // _LOG_TRACE("OSXPrivateKeyStorage::Verify");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700392
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800393 // CFDataRef dataRef = CFDataCreate(NULL,
394 // reinterpret_cast<const unsigned char*>(pData.buf()),
395 // pData.size());
Jeff Thompson2747dc02013-10-04 19:11:34 -0700396
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800397 // CFDataRef sigRef = CFDataCreate(NULL,
398 // reinterpret_cast<const unsigned char*>(pSig.buf()),
399 // pSig.size());
Jeff Thompson2747dc02013-10-04 19:11:34 -0700400
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800401 // SecKeyRef publicKey = (SecKeyRef)impl_->getKey(keyName, KEY_CLASS_PUBLIC);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700402
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800403 // CFErrorRef error;
404 // SecTransformRef verifier = SecVerifyTransformCreate(publicKey, sigRef, &error);
405 // if (error) throw Error("Fail to create verifier");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700406
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800407 // Boolean set_res = SecTransformSetAttribute(verifier,
408 // kSecTransformInputAttributeName,
409 // dataRef,
410 // &error);
411 // if (error) throw Error("Fail to configure input of verifier");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700412
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800413 // set_res = SecTransformSetAttribute(verifier,
414 // kSecDigestTypeAttribute,
415 // impl_->getDigestAlgorithm(digestAlgo),
416 // &error);
417 // if (error) throw Error("Fail to configure digest algorithm of verifier");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700418
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800419 // long digestSize = impl_->getDigestSize(digestAlgo);
420 // set_res = SecTransformSetAttribute(verifier,
421 // kSecDigestLengthAttribute,
422 // CFNumberCreate(NULL, kCFNumberLongType, &digestSize),
423 // &error);
424 // if (error) throw Error("Fail to configure digest size of verifier");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700425
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800426 // CFBooleanRef result = (CFBooleanRef) SecTransformExecute(verifier, &error);
427 // if (error) throw Error("Fail to verify data");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700428
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800429 // if (result == kCFBooleanTrue)
430 // return true;
431 // else
432 // return false;
433 // }
Jeff Thompson2747dc02013-10-04 19:11:34 -0700434
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800435 ConstBufferPtr
436 OSXPrivateKeyStorage::encrypt(const Name & keyName, const uint8_t* data, size_t dataLength, bool sym)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700437 {
438 _LOG_TRACE("OSXPrivateKeyStorage::Encrypt");
439
440 KeyClass keyClass;
441 if(sym)
442 keyClass = KEY_CLASS_SYMMETRIC;
443 else
444 keyClass = KEY_CLASS_PUBLIC;
445
446 CFDataRef dataRef = CFDataCreate(NULL,
447 reinterpret_cast<const unsigned char*>(data),
448 dataLength
449 );
450
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800451 SecKeyRef encryptKey = (SecKeyRef)impl_->getKey(keyName, keyClass);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700452
453 CFErrorRef error;
454 SecTransformRef encrypt = SecEncryptTransformCreate(encryptKey, &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800455 if (error) throw Error("Fail to create encrypt");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700456
457 Boolean set_res = SecTransformSetAttribute(encrypt,
458 kSecTransformInputAttributeName,
459 dataRef,
460 &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800461 if (error) throw Error("Fail to configure encrypt");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700462
463 CFDataRef output = (CFDataRef) SecTransformExecute(encrypt, &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800464 if (error) throw Error("Fail to encrypt data");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700465
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800466 if (!output) throw Error("Output is NULL!\n");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700467
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800468 return ptr_lib::make_shared<Buffer> (CFDataGetBytePtr(output), CFDataGetLength(output));
Jeff Thompson2747dc02013-10-04 19:11:34 -0700469 }
470
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800471 bool
472 OSXPrivateKeyStorage::doesKeyExist(const Name & keyName, KeyClass keyClass)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700473 {
474 _LOG_TRACE("OSXPrivateKeyStorage::doesKeyExist");
475
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800476 string keyNameUri = impl_->toInternalKeyName(keyName, keyClass);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700477
478 CFStringRef keyLabel = CFStringCreateWithCString(NULL,
Jeff Thompson556cc302013-10-22 17:40:07 -0700479 keyNameUri.c_str(),
480 kCFStringEncodingUTF8);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700481
482 CFMutableDictionaryRef attrDict = CFDictionaryCreateMutable(NULL,
483 3,
484 &kCFTypeDictionaryKeyCallBacks,
485 NULL);
486
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800487 CFDictionaryAddValue(attrDict, kSecAttrKeyClass, impl_->getKeyClass(keyClass));
Jeff Thompson2747dc02013-10-04 19:11:34 -0700488 CFDictionaryAddValue(attrDict, kSecAttrLabel, keyLabel);
489 CFDictionaryAddValue(attrDict, kSecReturnRef, kCFBooleanTrue);
490
491 SecKeychainItemRef itemRef;
492 OSStatus res = SecItemCopyMatching((CFDictionaryRef)attrDict, (CFTypeRef*)&itemRef);
493
494 if(res == errSecItemNotFound)
495 return true;
496 else
497 return false;
498
499 }
500
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800501
502 ////////////////////////////////
503 // OSXPrivateKeyStorage::Impl //
504 ////////////////////////////////
505
506 SecKeychainItemRef
507 OSXPrivateKeyStorage::Impl::getKey(const Name & keyName, KeyClass keyClass)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700508 {
509 string keyNameUri = toInternalKeyName(keyName, keyClass);
510
Jeff Thompson556cc302013-10-22 17:40:07 -0700511 CFStringRef keyLabel = CFStringCreateWithCString(NULL,
512 keyNameUri.c_str(),
513 kCFStringEncodingUTF8);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700514
515 CFMutableDictionaryRef attrDict = CFDictionaryCreateMutable(NULL,
516 5,
517 &kCFTypeDictionaryKeyCallBacks,
518 NULL);
519
520 CFDictionaryAddValue(attrDict, kSecClass, kSecClassKey);
521 CFDictionaryAddValue(attrDict, kSecAttrLabel, keyLabel);
522 CFDictionaryAddValue(attrDict, kSecAttrKeyClass, getKeyClass(keyClass));
523 CFDictionaryAddValue(attrDict, kSecReturnRef, kCFBooleanTrue);
524
525 SecKeychainItemRef keyItem;
526
527 OSStatus res = SecItemCopyMatching((CFDictionaryRef) attrDict, (CFTypeRef*)&keyItem);
528
529 if(res != errSecSuccess){
530 _LOG_DEBUG("Fail to find the key!");
531 return NULL;
532 }
533 else
534 return keyItem;
535 }
536
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800537 string OSXPrivateKeyStorage::Impl::toInternalKeyName(const Name & keyName, KeyClass keyClass)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700538 {
539 string keyUri = keyName.toUri();
540
541 if(KEY_CLASS_SYMMETRIC == keyClass)
542 return keyUri + "/symmetric";
543 else
544 return keyUri;
545 }
546
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800547 const CFTypeRef OSXPrivateKeyStorage::Impl::getAsymKeyType(KeyType keyType)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700548 {
549 switch(keyType){
550 case KEY_TYPE_RSA:
551 return kSecAttrKeyTypeRSA;
552 default:
553 _LOG_DEBUG("Unrecognized key type!")
554 return NULL;
555 }
556 }
557
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800558 const CFTypeRef OSXPrivateKeyStorage::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
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800569 const CFTypeRef OSXPrivateKeyStorage::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
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800584 const CFStringRef OSXPrivateKeyStorage::Impl::getDigestAlgorithm(DigestAlgorithm digestAlgo)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700585 {
586 switch(digestAlgo){
587 // case DIGEST_MD2:
588 // return kSecDigestMD2;
589 // case DIGEST_MD5:
590 // return kSecDigestMD5;
591 // case DIGEST_SHA1:
592 // return kSecDigestSHA1;
593 case DIGEST_ALGORITHM_SHA256:
594 return kSecDigestSHA2;
595 default:
596 _LOG_DEBUG("Unrecognized digest algorithm!");
597 return NULL;
598 }
599 }
600
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800601 long OSXPrivateKeyStorage::Impl::getDigestSize(DigestAlgorithm digestAlgo)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700602 {
603 switch(digestAlgo){
604 case DIGEST_ALGORITHM_SHA256:
605 return 256;
606 // case DIGEST_SHA1:
607 // case DIGEST_MD2:
608 // case DIGEST_MD5:
609 // return 0;
610 default:
611 _LOG_DEBUG("Unrecognized digest algorithm! Unknown digest size");
612 return -1;
613 }
614 }
615
616}
617
Jeff Thompsonc5647812013-10-11 18:06:38 -0700618#endif // NDN_CPP_HAVE_OSX_SECURITY