blob: 7989f06a2f9caf65233432f342e6e45155f34d2b [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
15#include <ndn-cpp/security/identity/osx-private-key-storage.hpp>
16#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
24INIT_LOGGER("ndn.OSXPrivateKeyStorage");
25
26namespace ndn
27{
Alexander Afanasyev04b22a92014-01-05 22:40:17 -080028 class OSXPrivateKeyStorage::Impl {
29 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
Jeff Thompson2747dc02013-10-04 19:11:34 -0700104 OSXPrivateKeyStorage::OSXPrivateKeyStorage(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
Jeff Thompson2747dc02013-10-04 19:11:34 -0700108 0, //Keychain password length
109 NULL, //Keychain password
110 true, //User prompt
111 NULL, //Initial access of Keychain
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800112 &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
132 OSXPrivateKeyStorage::~OSXPrivateKeyStorage(){
133 //TODO: implement
134 }
135
136 void
137 OSXPrivateKeyStorage::generateKeyPair(const Name & keyName, KeyType keyType, int keySize)
138 {
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
174 OSXPrivateKeyStorage::generateKey(const Name & keyName, KeyType keyType, int keySize)
175 {
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>
205 OSXPrivateKeyStorage::getPublicKey(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
223 OSXPrivateKeyStorage::sign(const uint8_t *data, size_t dataLength,
224 const Name& keyName, DigestAlgorithm digestAlgorithm/* = DIGEST_ALGORITHM_SHA256*/)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700225 {
226 _LOG_TRACE("OSXPrivateKeyStorage::Sign");
227
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800228 CFDataRef dataRef = CFDataCreateWithBytesNoCopy(NULL,
229 data,
230 dataLength,
231 kCFAllocatorNull
232 );
Jeff Thompson2747dc02013-10-04 19:11:34 -0700233
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800234 SecKeyRef privateKey = (SecKeyRef)impl_->getKey(keyName, KEY_CLASS_PRIVATE);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700235
236 CFErrorRef error;
237 SecTransformRef signer = SecSignTransformCreate((SecKeyRef)privateKey, &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800238 if (error) throw Error("Fail to create signer");
239
240 // Set input
Jeff Thompson2747dc02013-10-04 19:11:34 -0700241 Boolean set_res = SecTransformSetAttribute(signer,
242 kSecTransformInputAttributeName,
243 dataRef,
244 &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800245 if (error) throw Error("Fail to configure input of signer");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700246
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800247 // Enable use of padding
248 SecTransformSetAttribute(
249 signer,
250 kSecPaddingKey,
251 kSecPaddingPKCS1Key,
252 &error);
253 if (error) throw Error("Fail to configure digest algorithm of signer");
254
255 // Set padding type
Jeff Thompson2747dc02013-10-04 19:11:34 -0700256 set_res = SecTransformSetAttribute(signer,
257 kSecDigestTypeAttribute,
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800258 impl_->getDigestAlgorithm(digestAlgorithm),
Jeff Thompson2747dc02013-10-04 19:11:34 -0700259 &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800260 if (error) throw Error("Fail to configure digest algorithm of signer");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700261
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800262 // Set padding attribute
263 long digestSize = impl_->getDigestSize(digestAlgorithm);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700264 set_res = SecTransformSetAttribute(signer,
265 kSecDigestLengthAttribute,
266 CFNumberCreate(NULL, kCFNumberLongType, &digestSize),
267 &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800268 if (error) throw Error("Fail to configure digest size of signer");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700269
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800270 // Actually sign
Jeff Thompson2747dc02013-10-04 19:11:34 -0700271 CFDataRef signature = (CFDataRef) SecTransformExecute(signer, &error);
272 if (error) {
273 CFShow(error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800274 throw Error("Fail to sign data");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700275 }
276
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800277 if (!signature) throw Error("Signature is NULL!\n");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700278
Alexander Afanasyevbd5ba402014-01-05 22:41:09 -0800279 return Block(Tlv::SignatureValue,
280 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 {
Alexander Afanasyevbd5ba402014-01-05 22:41:09 -0800287 const uint8_t *begin = data.wireEncode().value();
288 const uint8_t *end = &*data.getSignature().getInfo().end();
289
290 data.setSignature
291 (sign(begin, end-begin, keyName, digestAlgorithm));
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800292 }
293
294 ConstBufferPtr
295 OSXPrivateKeyStorage::decrypt(const Name & keyName, const uint8_t* data, size_t dataLength, bool sym)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700296 {
297 _LOG_TRACE("OSXPrivateKeyStorage::Decrypt");
298
299 KeyClass keyClass;
300 if(sym)
301 keyClass = KEY_CLASS_SYMMETRIC;
302 else
303 keyClass = KEY_CLASS_PRIVATE;
304
305 CFDataRef dataRef = CFDataCreate(NULL,
306 reinterpret_cast<const unsigned char*>(data),
307 dataLength
308 );
309
310 // _LOG_DEBUG("CreateData");
311
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800312 SecKeyRef decryptKey = (SecKeyRef)impl_->getKey(keyName, keyClass);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700313
314 // _LOG_DEBUG("GetKey");
315
316 CFErrorRef error;
317 SecTransformRef decrypt = SecDecryptTransformCreate(decryptKey, &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800318 if (error) throw Error("Fail to create decrypt");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700319
320 Boolean set_res = SecTransformSetAttribute(decrypt,
321 kSecTransformInputAttributeName,
322 dataRef,
323 &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800324 if (error) throw Error("Fail to configure decrypt");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700325
326 CFDataRef output = (CFDataRef) SecTransformExecute(decrypt, &error);
327 if (error)
328 {
329 CFShow(error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800330 throw Error("Fail to decrypt data");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700331 }
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800332 if (!output) throw Error("Output is NULL!\n");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700333
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800334 return ptr_lib::make_shared<Buffer>(CFDataGetBytePtr(output), CFDataGetLength(output));
Jeff Thompson2747dc02013-10-04 19:11:34 -0700335 }
336
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800337 bool
338 OSXPrivateKeyStorage::setACL(const Name & keyName, KeyClass keyClass, int acl, const string & appPath)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700339 {
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800340 SecKeychainItemRef privateKey = impl_->getKey(keyName, keyClass);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700341
342 SecAccessRef accRef;
343 OSStatus acc_res = SecKeychainItemCopyAccess(privateKey, &accRef);
344
345 CFArrayRef signACL = SecAccessCopyMatchingACLList(accRef,
346 kSecACLAuthorizationSign);
347
348 SecACLRef aclRef = (SecACLRef) CFArrayGetValueAtIndex(signACL, 0);
349
350 CFArrayRef appList;
351 CFStringRef description;
352 SecKeychainPromptSelector promptSelector;
353 OSStatus acl_res = SecACLCopyContents(aclRef,
354 &appList,
355 &description,
356 &promptSelector);
357
358 CFMutableArrayRef newAppList = CFArrayCreateMutableCopy(NULL,
359 0,
360 appList);
361
362 SecTrustedApplicationRef trustedApp;
363 acl_res = SecTrustedApplicationCreateFromPath(appPath.c_str(),
364 &trustedApp);
365
366 CFArrayAppendValue(newAppList, trustedApp);
367
368
369 CFArrayRef authList = SecACLCopyAuthorizations(aclRef);
370
371 acl_res = SecACLRemove(aclRef);
372
373 SecACLRef newACL;
374 acl_res = SecACLCreateWithSimpleContents(accRef,
375 newAppList,
376 description,
377 promptSelector,
378 &newACL);
379
380 acl_res = SecACLUpdateAuthorizations(newACL, authList);
381
382 acc_res = SecKeychainItemSetAccess(privateKey, accRef);
383
384 return true;
385 }
386
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800387 // bool
388 // OSXPrivateKeyStorage::verifyData(const Name & keyName, const Blob & pData, const Blob & pSig, DigestAlgorithm digestAlgo)
389 // {
390 // _LOG_TRACE("OSXPrivateKeyStorage::Verify");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700391
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800392 // CFDataRef dataRef = CFDataCreate(NULL,
393 // reinterpret_cast<const unsigned char*>(pData.buf()),
394 // pData.size());
Jeff Thompson2747dc02013-10-04 19:11:34 -0700395
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800396 // CFDataRef sigRef = CFDataCreate(NULL,
397 // reinterpret_cast<const unsigned char*>(pSig.buf()),
398 // pSig.size());
Jeff Thompson2747dc02013-10-04 19:11:34 -0700399
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800400 // SecKeyRef publicKey = (SecKeyRef)impl_->getKey(keyName, KEY_CLASS_PUBLIC);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700401
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800402 // CFErrorRef error;
403 // SecTransformRef verifier = SecVerifyTransformCreate(publicKey, sigRef, &error);
404 // if (error) throw Error("Fail to create verifier");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700405
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800406 // Boolean set_res = SecTransformSetAttribute(verifier,
407 // kSecTransformInputAttributeName,
408 // dataRef,
409 // &error);
410 // if (error) throw Error("Fail to configure input of verifier");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700411
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800412 // set_res = SecTransformSetAttribute(verifier,
413 // kSecDigestTypeAttribute,
414 // impl_->getDigestAlgorithm(digestAlgo),
415 // &error);
416 // if (error) throw Error("Fail to configure digest algorithm of verifier");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700417
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800418 // long digestSize = impl_->getDigestSize(digestAlgo);
419 // set_res = SecTransformSetAttribute(verifier,
420 // kSecDigestLengthAttribute,
421 // CFNumberCreate(NULL, kCFNumberLongType, &digestSize),
422 // &error);
423 // if (error) throw Error("Fail to configure digest size of verifier");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700424
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800425 // CFBooleanRef result = (CFBooleanRef) SecTransformExecute(verifier, &error);
426 // if (error) throw Error("Fail to verify data");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700427
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800428 // if (result == kCFBooleanTrue)
429 // return true;
430 // else
431 // return false;
432 // }
Jeff Thompson2747dc02013-10-04 19:11:34 -0700433
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800434 ConstBufferPtr
435 OSXPrivateKeyStorage::encrypt(const Name & keyName, const uint8_t* data, size_t dataLength, bool sym)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700436 {
437 _LOG_TRACE("OSXPrivateKeyStorage::Encrypt");
438
439 KeyClass keyClass;
440 if(sym)
441 keyClass = KEY_CLASS_SYMMETRIC;
442 else
443 keyClass = KEY_CLASS_PUBLIC;
444
445 CFDataRef dataRef = CFDataCreate(NULL,
446 reinterpret_cast<const unsigned char*>(data),
447 dataLength
448 );
449
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800450 SecKeyRef encryptKey = (SecKeyRef)impl_->getKey(keyName, keyClass);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700451
452 CFErrorRef error;
453 SecTransformRef encrypt = SecEncryptTransformCreate(encryptKey, &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800454 if (error) throw Error("Fail to create encrypt");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700455
456 Boolean set_res = SecTransformSetAttribute(encrypt,
457 kSecTransformInputAttributeName,
458 dataRef,
459 &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800460 if (error) throw Error("Fail to configure encrypt");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700461
462 CFDataRef output = (CFDataRef) SecTransformExecute(encrypt, &error);
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800463 if (error) throw Error("Fail to encrypt data");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700464
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800465 if (!output) throw Error("Output is NULL!\n");
Jeff Thompson2747dc02013-10-04 19:11:34 -0700466
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800467 return ptr_lib::make_shared<Buffer> (CFDataGetBytePtr(output), CFDataGetLength(output));
Jeff Thompson2747dc02013-10-04 19:11:34 -0700468 }
469
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800470 bool
471 OSXPrivateKeyStorage::doesKeyExist(const Name & keyName, KeyClass keyClass)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700472 {
473 _LOG_TRACE("OSXPrivateKeyStorage::doesKeyExist");
474
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800475 string keyNameUri = impl_->toInternalKeyName(keyName, keyClass);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700476
477 CFStringRef keyLabel = CFStringCreateWithCString(NULL,
Jeff Thompson556cc302013-10-22 17:40:07 -0700478 keyNameUri.c_str(),
479 kCFStringEncodingUTF8);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700480
481 CFMutableDictionaryRef attrDict = CFDictionaryCreateMutable(NULL,
482 3,
483 &kCFTypeDictionaryKeyCallBacks,
484 NULL);
485
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800486 CFDictionaryAddValue(attrDict, kSecAttrKeyClass, impl_->getKeyClass(keyClass));
Jeff Thompson2747dc02013-10-04 19:11:34 -0700487 CFDictionaryAddValue(attrDict, kSecAttrLabel, keyLabel);
488 CFDictionaryAddValue(attrDict, kSecReturnRef, kCFBooleanTrue);
489
490 SecKeychainItemRef itemRef;
491 OSStatus res = SecItemCopyMatching((CFDictionaryRef)attrDict, (CFTypeRef*)&itemRef);
492
493 if(res == errSecItemNotFound)
494 return true;
495 else
496 return false;
497
498 }
499
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800500
501 ////////////////////////////////
502 // OSXPrivateKeyStorage::Impl //
503 ////////////////////////////////
504
505 SecKeychainItemRef
506 OSXPrivateKeyStorage::Impl::getKey(const Name & keyName, KeyClass keyClass)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700507 {
508 string keyNameUri = toInternalKeyName(keyName, keyClass);
509
Jeff Thompson556cc302013-10-22 17:40:07 -0700510 CFStringRef keyLabel = CFStringCreateWithCString(NULL,
511 keyNameUri.c_str(),
512 kCFStringEncodingUTF8);
Jeff Thompson2747dc02013-10-04 19:11:34 -0700513
514 CFMutableDictionaryRef attrDict = CFDictionaryCreateMutable(NULL,
515 5,
516 &kCFTypeDictionaryKeyCallBacks,
517 NULL);
518
519 CFDictionaryAddValue(attrDict, kSecClass, kSecClassKey);
520 CFDictionaryAddValue(attrDict, kSecAttrLabel, keyLabel);
521 CFDictionaryAddValue(attrDict, kSecAttrKeyClass, getKeyClass(keyClass));
522 CFDictionaryAddValue(attrDict, kSecReturnRef, kCFBooleanTrue);
523
524 SecKeychainItemRef keyItem;
525
526 OSStatus res = SecItemCopyMatching((CFDictionaryRef) attrDict, (CFTypeRef*)&keyItem);
527
528 if(res != errSecSuccess){
529 _LOG_DEBUG("Fail to find the key!");
530 return NULL;
531 }
532 else
533 return keyItem;
534 }
535
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800536 string OSXPrivateKeyStorage::Impl::toInternalKeyName(const Name & keyName, KeyClass keyClass)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700537 {
538 string keyUri = keyName.toUri();
539
540 if(KEY_CLASS_SYMMETRIC == keyClass)
541 return keyUri + "/symmetric";
542 else
543 return keyUri;
544 }
545
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800546 const CFTypeRef OSXPrivateKeyStorage::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
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800557 const CFTypeRef OSXPrivateKeyStorage::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
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800568 const CFTypeRef OSXPrivateKeyStorage::Impl::getKeyClass(KeyClass keyClass)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700569 {
570 switch(keyClass){
571 case KEY_CLASS_PRIVATE:
572 return kSecAttrKeyClassPrivate;
573 case KEY_CLASS_PUBLIC:
574 return kSecAttrKeyClassPublic;
575 case KEY_CLASS_SYMMETRIC:
576 return kSecAttrKeyClassSymmetric;
577 default:
578 _LOG_DEBUG("Unrecognized key class!");
579 return NULL;
580 }
581 }
582
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800583 const CFStringRef OSXPrivateKeyStorage::Impl::getDigestAlgorithm(DigestAlgorithm digestAlgo)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700584 {
585 switch(digestAlgo){
586 // case DIGEST_MD2:
587 // return kSecDigestMD2;
588 // case DIGEST_MD5:
589 // return kSecDigestMD5;
590 // case DIGEST_SHA1:
591 // return kSecDigestSHA1;
592 case DIGEST_ALGORITHM_SHA256:
593 return kSecDigestSHA2;
594 default:
595 _LOG_DEBUG("Unrecognized digest algorithm!");
596 return NULL;
597 }
598 }
599
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800600 long OSXPrivateKeyStorage::Impl::getDigestSize(DigestAlgorithm digestAlgo)
Jeff Thompson2747dc02013-10-04 19:11:34 -0700601 {
602 switch(digestAlgo){
603 case DIGEST_ALGORITHM_SHA256:
604 return 256;
605 // case DIGEST_SHA1:
606 // case DIGEST_MD2:
607 // case DIGEST_MD5:
608 // return 0;
609 default:
610 _LOG_DEBUG("Unrecognized digest algorithm! Unknown digest size");
611 return -1;
612 }
613 }
614
615}