blob: 24d47ea497088d3e6a8d6794b68a2ffa80a5397b [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
Alexander Afanasyeve2dcdfd2014-02-07 15:53:28 -08008#include "common.hpp"
9
Alexander Afanasyev19508852014-01-29 01:01:51 -080010#include "sec-tpm-osx.hpp"
11
12#include "security/public-key.hpp"
13#include "util/logging.hpp"
Junxiao Shi482ccc52014-03-31 13:05:24 -070014#include "cryptopp.hpp"
Jeff Thompson2747dc02013-10-04 19:11:34 -070015
Yingdi Yu2b2b4792014-02-04 16:27:07 -080016#include <pwd.h>
17#include <unistd.h>
18#include <stdlib.h>
19#include <string.h>
Jeff Thompson2747dc02013-10-04 19:11:34 -070020
Alexander Afanasyev04b22a92014-01-05 22:40:17 -080021#include <CoreFoundation/CoreFoundation.h>
22#include <Security/Security.h>
Yingdi Yu4b752752014-02-18 12:24:03 -080023#include <Security/SecRandom.h>
Alexander Afanasyev04b22a92014-01-05 22:40:17 -080024#include <CoreServices/CoreServices.h>
Jeff Thompson2747dc02013-10-04 19:11:34 -070025
26using namespace std;
Jeff Thompson2747dc02013-10-04 19:11:34 -070027
Yingdi Yu21157162014-02-28 13:02:34 -080028INIT_LOGGER("ndn.SecTpmOsx");
Jeff Thompson2747dc02013-10-04 19:11:34 -070029
Yingdi Yufc40d872014-02-18 12:56:04 -080030namespace ndn {
31
Yingdi Yu2b2b4792014-02-04 16:27:07 -080032class SecTpmOsx::Impl {
33public:
34 Impl()
Yingdi Yube4150e2014-02-18 13:02:46 -080035 : m_passwordSet(false)
36 , m_inTerminal(false)
Yingdi Yu2b2b4792014-02-04 16:27:07 -080037 {}
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -070038
Yingdi Yu2b2b4792014-02-04 16:27:07 -080039 /**
40 * @brief Convert NDN name of a key to internal name of the key.
41 *
Yingdi Yufc40d872014-02-18 12:56:04 -080042 * @param keyName
43 * @param keyClass
Yingdi Yu2b2b4792014-02-04 16:27:07 -080044 * @return the internal key name
45 */
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -070046 std::string
Yingdi Yu2b2b4792014-02-04 16:27:07 -080047 toInternalKeyName(const Name & keyName, KeyClass keyClass);
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -070048
Yingdi Yu2b2b4792014-02-04 16:27:07 -080049 /**
50 * @brief Get key.
Yingdi Yufc40d872014-02-18 12:56:04 -080051 *
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -070052 * @param keyName
Yingdi Yufc40d872014-02-18 12:56:04 -080053 * @param keyClass
Yingdi Yu2b2b4792014-02-04 16:27:07 -080054 * @returns pointer to the key
55 */
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -070056 SecKeychainItemRef
Yingdi Yu2b2b4792014-02-04 16:27:07 -080057 getKey(const Name & keyName, KeyClass keyClass);
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -070058
Yingdi Yu2b2b4792014-02-04 16:27:07 -080059 /**
Yingdi Yufc40d872014-02-18 12:56:04 -080060 * @brief Convert keyType to MAC OS symmetric key key type
61 *
Yingdi Yu2b2b4792014-02-04 16:27:07 -080062 * @param keyType
63 * @returns MAC OS key type
64 */
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -070065 const CFTypeRef
Yingdi Yu2b2b4792014-02-04 16:27:07 -080066 getSymKeyType(KeyType keyType);
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -070067
Yingdi Yu2b2b4792014-02-04 16:27:07 -080068 /**
Yingdi Yufc40d872014-02-18 12:56:04 -080069 * @brief Convert keyType to MAC OS asymmetirc key type
70 *
Yingdi Yu2b2b4792014-02-04 16:27:07 -080071 * @param keyType
72 * @returns MAC OS key type
73 */
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -070074 const CFTypeRef
Yingdi Yu2b2b4792014-02-04 16:27:07 -080075 getAsymKeyType(KeyType keyType);
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -070076
Yingdi Yu2b2b4792014-02-04 16:27:07 -080077 /**
Yingdi Yufc40d872014-02-18 12:56:04 -080078 * @brief Convert keyClass to MAC OS key class
79 *
Yingdi Yu2b2b4792014-02-04 16:27:07 -080080 * @param keyClass
81 * @returns MAC OS key class
82 */
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -070083 const CFTypeRef
Yingdi Yu2b2b4792014-02-04 16:27:07 -080084 getKeyClass(KeyClass keyClass);
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -070085
Yingdi Yu2b2b4792014-02-04 16:27:07 -080086 /**
Yingdi Yufc40d872014-02-18 12:56:04 -080087 * @brief Convert digestAlgo to MAC OS algorithm id
88 *
Yingdi Yu2b2b4792014-02-04 16:27:07 -080089 * @param digestAlgo
90 * @returns MAC OS algorithm id
91 */
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -070092 const CFStringRef
Yingdi Yu2b2b4792014-02-04 16:27:07 -080093 getDigestAlgorithm(DigestAlgorithm digestAlgo);
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -070094
Yingdi Yu2b2b4792014-02-04 16:27:07 -080095 /**
Yingdi Yufc40d872014-02-18 12:56:04 -080096 * @brief Get the digest size of the corresponding algorithm
97 *
98 * @param digestAlgo
Yingdi Yu2b2b4792014-02-04 16:27:07 -080099 * @return digest size
100 */
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700101 long
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800102 getDigestSize(DigestAlgorithm digestAlgo);
103
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800104 ///////////////////////////////////////////////
105 // everything here is public, including data //
106 ///////////////////////////////////////////////
107public:
108 SecKeychainRef m_keyChainRef;
Yingdi Yube4150e2014-02-18 13:02:46 -0800109 bool m_passwordSet;
110 string m_password;
111 bool m_inTerminal;
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800112};
113
114
115SecTpmOsx::SecTpmOsx()
116 : m_impl(new Impl)
117{
Yingdi Yube4150e2014-02-18 13:02:46 -0800118 if(m_impl->m_inTerminal)
119 SecKeychainSetUserInteractionAllowed (false);
120 else
121 SecKeychainSetUserInteractionAllowed (true);
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800122
Yingdi Yube4150e2014-02-18 13:02:46 -0800123 OSStatus res = SecKeychainCopyDefault(&m_impl->m_keyChainRef);
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700124
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800125 if (res == errSecNoDefaultKeychain) //If no default key chain, create one.
Yingdi Yube4150e2014-02-18 13:02:46 -0800126 throw Error("No default keychain, create one first!");
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800127}
128
129SecTpmOsx::~SecTpmOsx(){
130 //TODO: implement
131}
132
Yingdi Yube4150e2014-02-18 13:02:46 -0800133void
134SecTpmOsx::setTpmPassword(const uint8_t* password, size_t passwordLength)
135{
136 m_impl->m_passwordSet = true;
137 memset(const_cast<char*>(m_impl->m_password.c_str()), 0, m_impl->m_password.size());
138 m_impl->m_password.clear();
139 m_impl->m_password.append(reinterpret_cast<const char*>(password), passwordLength);
140}
141
142void
143SecTpmOsx::resetTpmPassword()
144{
145 m_impl->m_passwordSet = false;
146 memset(const_cast<char*>(m_impl->m_password.c_str()), 0, m_impl->m_password.size());
147 m_impl->m_password.clear();
148}
149
150void
151SecTpmOsx::setInTerminal(bool inTerminal)
152{
153 m_impl->m_inTerminal = inTerminal;
154 if(inTerminal)
155 SecKeychainSetUserInteractionAllowed (false);
156 else
157 SecKeychainSetUserInteractionAllowed (true);
158}
159
160bool
161SecTpmOsx::getInTerminal()
162{
163 return m_impl->m_inTerminal;
164}
165
166bool
167SecTpmOsx::locked()
168{
169 SecKeychainStatus keychainStatus;
170
171 OSStatus res = SecKeychainGetStatus(m_impl->m_keyChainRef, &keychainStatus);
172 if(res != errSecSuccess)
173 return true;
174 else
175 return ((kSecUnlockStateStatus & keychainStatus) == 0);
176}
177
Yingdi Yu2e57a582014-02-20 23:34:43 -0800178bool
Yingdi Yube4150e2014-02-18 13:02:46 -0800179SecTpmOsx::unlockTpm(const char* password, size_t passwordLength, bool usePassword)
180{
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700181 OSStatus res;
Yingdi Yube4150e2014-02-18 13:02:46 -0800182
183 // If the default key chain is already unlocked, return immediately.
184 if(!locked())
Yingdi Yu2e57a582014-02-20 23:34:43 -0800185 return true;
Yingdi Yube4150e2014-02-18 13:02:46 -0800186
187 // If the default key chain is locked, unlock the key chain.
188 if(usePassword)
189 {
190 // Use the supplied password.
191 res = SecKeychainUnlock(m_impl->m_keyChainRef,
192 passwordLength,
193 password,
194 true);
195 }
196 else if(m_impl->m_passwordSet)
197 {
198 // If no password supplied, then use the configured password if exists.
199 SecKeychainUnlock(m_impl->m_keyChainRef,
200 m_impl->m_password.size(),
201 m_impl->m_password.c_str(),
202 true);
203 }
204 else if(m_impl->m_inTerminal)
205 {
206 // If no configured password, get password from terminal if inTerminal set.
207 bool locked = true;
208 const char* fmt = "Password to unlock the default keychain: ";
209 int count = 0;
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700210
Yingdi Yube4150e2014-02-18 13:02:46 -0800211 while(locked)
212 {
213 if(count > 2)
214 break;
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700215
Yingdi Yube4150e2014-02-18 13:02:46 -0800216 char* getPassword = NULL;
217 getPassword = getpass(fmt);
218 count++;
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700219
Yingdi Yube4150e2014-02-18 13:02:46 -0800220 if (!getPassword)
221 continue;
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700222
Yingdi Yube4150e2014-02-18 13:02:46 -0800223 res = SecKeychainUnlock(m_impl->m_keyChainRef,
224 strlen(getPassword),
225 getPassword,
226 true);
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700227
Yingdi Yube4150e2014-02-18 13:02:46 -0800228 memset(getPassword, 0, strlen(getPassword));
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700229
Yingdi Yube4150e2014-02-18 13:02:46 -0800230 if(res == errSecSuccess)
Yingdi Yu2e57a582014-02-20 23:34:43 -0800231 break;
Yingdi Yube4150e2014-02-18 13:02:46 -0800232 }
233 }
234 else
235 {
236 // If inTerminal is not set, get the password from GUI.
237 SecKeychainUnlock(m_impl->m_keyChainRef, 0, 0, false);
238 }
Yingdi Yu2e57a582014-02-20 23:34:43 -0800239
240 return !locked();
Yingdi Yube4150e2014-02-18 13:02:46 -0800241}
242
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700243void
Yingdi Yube4150e2014-02-18 13:02:46 -0800244SecTpmOsx::generateKeyPairInTpmInternal(const Name & keyName, KeyType keyType, int keySize, bool retry)
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700245{
246
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800247 if(doesKeyExistInTpm(keyName, KEY_CLASS_PUBLIC)){
248 _LOG_DEBUG("keyName has existed");
249 throw Error("keyName has existed");
250 }
251
252 string keyNameUri = m_impl->toInternalKeyName(keyName, KEY_CLASS_PUBLIC);
253
254 SecKeyRef publicKey, privateKey;
255
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700256 CFStringRef keyLabel = CFStringCreateWithCString(NULL,
257 keyNameUri.c_str(),
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800258 kCFStringEncodingUTF8);
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700259
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800260 CFMutableDictionaryRef attrDict = CFDictionaryCreateMutable(NULL,
261 3,
262 &kCFTypeDictionaryKeyCallBacks,
263 NULL);
264
265 CFDictionaryAddValue(attrDict, kSecAttrKeyType, m_impl->getAsymKeyType(keyType));
266 CFDictionaryAddValue(attrDict, kSecAttrKeySizeInBits, CFNumberCreate(NULL, kCFNumberIntType, &keySize));
267 CFDictionaryAddValue(attrDict, kSecAttrLabel, keyLabel);
268
269 OSStatus res = SecKeyGeneratePair((CFDictionaryRef)attrDict, &publicKey, &privateKey);
270
Yingdi Yube4150e2014-02-18 13:02:46 -0800271 if (res == errSecSuccess)
Alexander Afanasyev60c86812014-02-20 15:19:33 -0800272 {
273 CFRelease(publicKey);
274 CFRelease(privateKey);
275 return;
276 }
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700277
Yingdi Yube4150e2014-02-18 13:02:46 -0800278 if (res == errSecAuthFailed && !retry)
279 {
Yingdi Yu2e57a582014-02-20 23:34:43 -0800280 if(unlockTpm(0, 0, false))
281 generateKeyPairInTpmInternal(keyName, keyType, keySize, true);
282 else
283 throw Error("Fail to unlock the keychain");
Yingdi Yube4150e2014-02-18 13:02:46 -0800284 }
285 else
286 {
287 _LOG_DEBUG("Fail to create a key pair: " << res);
288 throw Error("Fail to create a key pair");
289 }
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800290}
291
292void
Yingdi Yube4150e2014-02-18 13:02:46 -0800293SecTpmOsx::deleteKeyPairInTpmInternal(const Name &keyName, bool retry)
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800294{
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700295 CFStringRef keyLabel = CFStringCreateWithCString(NULL,
296 keyName.toUri().c_str(),
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800297 kCFStringEncodingUTF8);
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800298
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700299 CFMutableDictionaryRef searchDict =
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800300 CFDictionaryCreateMutable(NULL, 5, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800301
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800302 CFDictionaryAddValue(searchDict, kSecClass, kSecClassKey);
303 CFDictionaryAddValue(searchDict, kSecAttrLabel, keyLabel);
304 CFDictionaryAddValue(searchDict, kSecMatchLimit, kSecMatchLimitAll);
Yingdi Yube4150e2014-02-18 13:02:46 -0800305 OSStatus res = SecItemDelete(searchDict);
306
307 if (res == errSecSuccess)
308 return;
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700309
Yingdi Yube4150e2014-02-18 13:02:46 -0800310 if (res == errSecAuthFailed && !retry)
311 {
Yingdi Yu2e57a582014-02-20 23:34:43 -0800312 if(unlockTpm(0, 0, false))
313 deleteKeyPairInTpmInternal(keyName, true);
Yingdi Yube4150e2014-02-18 13:02:46 -0800314 }
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800315}
316
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700317void
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800318SecTpmOsx::generateSymmetricKeyInTpm(const Name & keyName, KeyType keyType, int keySize)
319{
Yingdi Yu2e57a582014-02-20 23:34:43 -0800320 throw Error("SecTpmOsx::generateSymmetricKeyInTpm is not supported");
321 // if(doesKeyExistInTpm(keyName, KEY_CLASS_SYMMETRIC))
322 // throw Error("keyName has existed!");
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800323
Yingdi Yu2e57a582014-02-20 23:34:43 -0800324 // string keyNameUri = m_impl->toInternalKeyName(keyName, KEY_CLASS_SYMMETRIC);
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800325
Yingdi Yu2e57a582014-02-20 23:34:43 -0800326 // CFMutableDictionaryRef attrDict = CFDictionaryCreateMutable(kCFAllocatorDefault,
327 // 0,
328 // &kCFTypeDictionaryKeyCallBacks,
329 // &kCFTypeDictionaryValueCallBacks);
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800330
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700331 // CFStringRef keyLabel = CFStringCreateWithCString(NULL,
332 // keyNameUri.c_str(),
Yingdi Yu2e57a582014-02-20 23:34:43 -0800333 // kCFStringEncodingUTF8);
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800334
Yingdi Yu2e57a582014-02-20 23:34:43 -0800335 // CFDictionaryAddValue(attrDict, kSecAttrKeyType, m_impl->getSymKeyType(keyType));
336 // CFDictionaryAddValue(attrDict, kSecAttrKeySizeInBits, CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &keySize));
337 // CFDictionaryAddValue(attrDict, kSecAttrIsPermanent, kCFBooleanTrue);
338 // CFDictionaryAddValue(attrDict, kSecAttrLabel, keyLabel);
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800339
Yingdi Yu2e57a582014-02-20 23:34:43 -0800340 // CFErrorRef error = NULL;
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800341
Yingdi Yu2e57a582014-02-20 23:34:43 -0800342 // SecKeyRef symmetricKey = SecKeyGenerateSymmetric(attrDict, &error);
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800343
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700344 // if (error)
Yingdi Yu2e57a582014-02-20 23:34:43 -0800345 // throw Error("Fail to create a symmetric key");
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800346}
347
Yingdi Yu2e57a582014-02-20 23:34:43 -0800348shared_ptr<PublicKey>
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800349SecTpmOsx::getPublicKeyFromTpm(const Name & keyName)
350{
351 _LOG_TRACE("OSXPrivateKeyStorage::getPublickey");
352
353 SecKeychainItemRef publicKey = m_impl->getKey(keyName, KEY_CLASS_PUBLIC);
354
355 CFDataRef exportedKey;
356
357 OSStatus res = SecItemExport(publicKey,
358 kSecFormatOpenSSL,
359 0,
360 NULL,
361 &exportedKey);
Alexander Afanasyev60c86812014-02-20 15:19:33 -0800362 if (res != errSecSuccess)
363 {
364 throw Error("Cannot export requested public key from OSX Keychain");
365 }
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800366
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800367 shared_ptr<PublicKey> key = make_shared<PublicKey>(CFDataGetBytePtr(exportedKey), CFDataGetLength(exportedKey));
368 CFRelease(exportedKey);
369 return key;
370}
371
372ConstBufferPtr
Yingdi Yube4150e2014-02-18 13:02:46 -0800373SecTpmOsx::exportPrivateKeyPkcs1FromTpmInternal(const Name& keyName, bool retry)
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800374{
375 using namespace CryptoPP;
376
377 SecKeychainItemRef privateKey = m_impl->getKey(keyName, KEY_CLASS_PRIVATE);
378 CFDataRef exportedKey;
379 OSStatus res = SecItemExport(privateKey,
380 kSecFormatOpenSSL,
381 0,
382 NULL,
383 &exportedKey);
384
385 if(res != errSecSuccess)
386 {
Yingdi Yube4150e2014-02-18 13:02:46 -0800387 if(res == errSecAuthFailed && !retry)
388 {
Yingdi Yu2e57a582014-02-20 23:34:43 -0800389 if(unlockTpm(0, 0, false))
390 return exportPrivateKeyPkcs1FromTpmInternal(keyName, true);
391 else
392 return shared_ptr<Buffer>();
Yingdi Yube4150e2014-02-18 13:02:46 -0800393 }
394 else
395 return shared_ptr<Buffer>();
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800396 }
397
398 OBufferStream pkcs1Os;
399 FileSink sink(pkcs1Os);
400
401 uint32_t version = 0;
402 OID algorithm("1.2.840.113549.1.1.1");
403 SecByteBlock rawKeyBits;
404 // PrivateKeyInfo ::= SEQUENCE {
405 // version INTEGER,
406 // privateKeyAlgorithm SEQUENCE,
407 // privateKey OCTECT STRING}
408 DERSequenceEncoder privateKeyInfo(sink);
409 {
410 DEREncodeUnsigned<uint32_t>(privateKeyInfo, version, INTEGER);
411 DERSequenceEncoder privateKeyAlgorithm(privateKeyInfo);
412 {
413 algorithm.encode(privateKeyAlgorithm);
414 DEREncodeNull(privateKeyAlgorithm);
415 }
416 privateKeyAlgorithm.MessageEnd();
417 DEREncodeOctetString(privateKeyInfo, CFDataGetBytePtr(exportedKey), CFDataGetLength(exportedKey));
418 }
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700419 privateKeyInfo.MessageEnd();
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800420
421 CFRelease(exportedKey);
422 return pkcs1Os.buf();
423}
424
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700425#ifdef __GNUC__
426#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
427#pragma GCC diagnostic push
428#endif // __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
429#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
430#endif // __GNUC__
431
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800432bool
Yingdi Yube4150e2014-02-18 13:02:46 -0800433SecTpmOsx::importPrivateKeyPkcs1IntoTpmInternal(const Name& keyName, const uint8_t* buf, size_t size, bool retry)
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800434{
435 using namespace CryptoPP;
436
437 StringSource privateKeySource(buf, size, true);
438 uint32_t tmpNum;
439 OID tmpOID;
440 SecByteBlock rawKeyBits;
441 // PrivateKeyInfo ::= SEQUENCE {
442 // INTEGER,
443 // SEQUENCE,
444 // OCTECT STRING}
445 BERSequenceDecoder privateKeyInfo(privateKeySource);
446 {
447 BERDecodeUnsigned<uint32_t>(privateKeyInfo, tmpNum, INTEGER);
448 BERSequenceDecoder sequenceDecoder(privateKeyInfo);
449 {
450 tmpOID.decode(sequenceDecoder);
451 BERDecodeNull(sequenceDecoder);
452 }
453 BERDecodeOctetString(privateKeyInfo, rawKeyBits);
454 }
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700455 privateKeyInfo.MessageEnd();
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800456
457 CFDataRef importedKey = CFDataCreateWithBytesNoCopy(NULL,
458 rawKeyBits.BytePtr(),
459 rawKeyBits.size(),
460 kCFAllocatorNull);
461
462 SecExternalFormat externalFormat = kSecFormatOpenSSL;
463 SecExternalItemType externalType = kSecItemTypePrivateKey;
464 SecKeyImportExportParameters keyParams;
465 memset(&keyParams, 0, sizeof(keyParams));
466 keyParams.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
467 keyParams.keyAttributes = CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_PERMANENT;
468 SecAccessRef access;
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700469 CFStringRef keyLabel = CFStringCreateWithCString(NULL,
470 keyName.toUri().c_str(),
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800471 kCFStringEncodingUTF8);
472 SecAccessCreate(keyLabel, NULL, &access);
473 keyParams.accessRef = access;
474 CFArrayRef outItems;
475
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700476#ifdef __clang__
Junxiao Shi482ccc52014-03-31 13:05:24 -0700477#pragma clang diagnostic push
478#pragma clang diagnostic ignored "-Wdeprecated-declarations"
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700479#endif // __clang__
480
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800481 OSStatus res = SecKeychainItemImport (importedKey,
482 NULL,
483 &externalFormat,
484 &externalType,
485 0,
486 &keyParams,
487 m_impl->m_keyChainRef,
488 &outItems);
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700489
490#ifdef __clang__
Junxiao Shi482ccc52014-03-31 13:05:24 -0700491#pragma clang diagnostic pop
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700492#endif // __clang__
493
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800494 if(res != errSecSuccess)
495 {
Yingdi Yube4150e2014-02-18 13:02:46 -0800496 if(res == errSecAuthFailed && !retry)
497 {
Yingdi Yu2e57a582014-02-20 23:34:43 -0800498 if(unlockTpm(0, 0, false))
499 return importPrivateKeyPkcs1IntoTpmInternal(keyName, buf, size, true);
500 else
501 return false;
Yingdi Yube4150e2014-02-18 13:02:46 -0800502 }
503 else
504 return false;
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800505 }
506
507 SecKeychainItemRef privateKey = (SecKeychainItemRef)CFArrayGetValueAtIndex(outItems, 0);
508 SecKeychainAttribute attrs[1]; // maximum number of attributes
509 SecKeychainAttributeList attrList = { 0, attrs };
510 string keyUri = keyName.toUri();
511 {
512 attrs[attrList.count].tag = kSecKeyPrintName;
513 attrs[attrList.count].length = keyUri.size();
514 attrs[attrList.count].data = (void *)keyUri.c_str();
515 attrList.count++;
516 }
517
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700518 res = SecKeychainItemModifyAttributesAndData(privateKey,
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800519 &attrList,
520 0,
521 NULL);
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700522
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800523 if(res != errSecSuccess)
524 {
525 return false;
526 }
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700527
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800528 CFRelease(importedKey);
529 return true;
530}
531
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700532#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
533#pragma GCC diagnostic pop
534#endif // __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
535
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800536bool
537SecTpmOsx::importPublicKeyPkcs1IntoTpm(const Name& keyName, const uint8_t* buf, size_t size)
538{
539 CFDataRef importedKey = CFDataCreateWithBytesNoCopy(NULL,
540 buf,
541 size,
542 kCFAllocatorNull);
543
544 SecExternalFormat externalFormat = kSecFormatOpenSSL;
545 SecExternalItemType externalType = kSecItemTypePublicKey;
546 CFArrayRef outItems;
547
548 OSStatus res = SecItemImport (importedKey,
549 NULL,
550 &externalFormat,
551 &externalType,
552 0,
553 NULL,
554 m_impl->m_keyChainRef,
555 &outItems);
556
557 if(res != errSecSuccess)
558 return false;
559
560 SecKeychainItemRef publicKey = (SecKeychainItemRef)CFArrayGetValueAtIndex(outItems, 0);
561 SecKeychainAttribute attrs[1]; // maximum number of attributes
562 SecKeychainAttributeList attrList = { 0, attrs };
563 string keyUri = keyName.toUri();
564 {
565 attrs[attrList.count].tag = kSecKeyPrintName;
566 attrs[attrList.count].length = keyUri.size();
567 attrs[attrList.count].data = (void *)keyUri.c_str();
568 attrList.count++;
569 }
570
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700571 res = SecKeychainItemModifyAttributesAndData(publicKey,
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800572 &attrList,
573 0,
574 NULL);
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700575
Alexander Afanasyev60c86812014-02-20 15:19:33 -0800576 if(res != errSecSuccess)
577 return false;
578
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800579 CFRelease(importedKey);
580 return true;
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800581}
582
583Block
Yingdi Yube4150e2014-02-18 13:02:46 -0800584SecTpmOsx::signInTpmInternal(const uint8_t *data, size_t dataLength, const Name& keyName, DigestAlgorithm digestAlgorithm, bool retry)
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800585{
586 _LOG_TRACE("OSXPrivateKeyStorage::Sign");
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700587
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800588 CFDataRef dataRef = CFDataCreateWithBytesNoCopy(NULL,
589 data,
590 dataLength,
Yingdi Yu2e57a582014-02-20 23:34:43 -0800591 kCFAllocatorNull);
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800592
593 SecKeyRef privateKey = (SecKeyRef)m_impl->getKey(keyName, KEY_CLASS_PRIVATE);
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700594
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800595 CFErrorRef error;
596 SecTransformRef signer = SecSignTransformCreate((SecKeyRef)privateKey, &error);
597 if (error) throw Error("Fail to create signer");
598
599 // Set input
600 Boolean set_res = SecTransformSetAttribute(signer,
601 kSecTransformInputAttributeName,
602 dataRef,
603 &error);
604 if (error) throw Error("Fail to configure input of signer");
605
606 // Enable use of padding
Yingdi Yu2e57a582014-02-20 23:34:43 -0800607 SecTransformSetAttribute(signer,
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800608 kSecPaddingKey,
609 kSecPaddingPKCS1Key,
610 &error);
611 if (error) throw Error("Fail to configure digest algorithm of signer");
612
613 // Set padding type
614 set_res = SecTransformSetAttribute(signer,
615 kSecDigestTypeAttribute,
616 m_impl->getDigestAlgorithm(digestAlgorithm),
617 &error);
618 if (error) throw Error("Fail to configure digest algorithm of signer");
619
620 // Set padding attribute
621 long digestSize = m_impl->getDigestSize(digestAlgorithm);
622 set_res = SecTransformSetAttribute(signer,
623 kSecDigestLengthAttribute,
624 CFNumberCreate(NULL, kCFNumberLongType, &digestSize),
625 &error);
626 if (error) throw Error("Fail to configure digest size of signer");
627
628 // Actually sign
629 CFDataRef signature = (CFDataRef) SecTransformExecute(signer, &error);
Yingdi Yube4150e2014-02-18 13:02:46 -0800630 if (error)
631 {
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700632 if(!retry)
Yingdi Yube4150e2014-02-18 13:02:46 -0800633 {
Yingdi Yu2e57a582014-02-20 23:34:43 -0800634 if(unlockTpm(0, 0, false))
635 return signInTpmInternal(data, dataLength, keyName, digestAlgorithm, true);
636 else
637 throw Error("Fail to unlock the keychain");
Yingdi Yube4150e2014-02-18 13:02:46 -0800638 }
639 else
640 {
641 CFShow(error);
642 throw Error("Fail to sign data");
643 }
644 }
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800645
646 if (!signature) throw Error("Signature is NULL!\n");
647
648 return Block(Tlv::SignatureValue,
Yingdi Yu2e57a582014-02-20 23:34:43 -0800649 make_shared<Buffer>(CFDataGetBytePtr(signature), CFDataGetLength(signature)));
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800650}
651
652ConstBufferPtr
Yingdi Yufc40d872014-02-18 12:56:04 -0800653SecTpmOsx::decryptInTpm(const uint8_t* data, size_t dataLength, const Name & keyName, bool sym)
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800654{
Yingdi Yu2e57a582014-02-20 23:34:43 -0800655 throw Error("SecTpmOsx::decryptInTpm is not supported");
656 // _LOG_TRACE("OSXPrivateKeyStorage::Decrypt");
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800657
Yingdi Yu2e57a582014-02-20 23:34:43 -0800658 // KeyClass keyClass;
659 // if(sym)
660 // keyClass = KEY_CLASS_SYMMETRIC;
661 // else
662 // keyClass = KEY_CLASS_PRIVATE;
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800663
Yingdi Yu2e57a582014-02-20 23:34:43 -0800664 // CFDataRef dataRef = CFDataCreate(NULL,
665 // reinterpret_cast<const unsigned char*>(data),
666 // dataLength
667 // );
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800668
Yingdi Yu2e57a582014-02-20 23:34:43 -0800669 // // _LOG_DEBUG("CreateData");
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700670
Yingdi Yu2e57a582014-02-20 23:34:43 -0800671 // SecKeyRef decryptKey = (SecKeyRef)m_impl->getKey(keyName, keyClass);
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800672
Yingdi Yu2e57a582014-02-20 23:34:43 -0800673 // // _LOG_DEBUG("GetKey");
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800674
Yingdi Yu2e57a582014-02-20 23:34:43 -0800675 // CFErrorRef error;
676 // SecTransformRef decrypt = SecDecryptTransformCreate(decryptKey, &error);
677 // if (error) throw Error("Fail to create decrypt");
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800678
Yingdi Yu2e57a582014-02-20 23:34:43 -0800679 // Boolean set_res = SecTransformSetAttribute(decrypt,
680 // kSecTransformInputAttributeName,
681 // dataRef,
682 // &error);
683 // if (error) throw Error("Fail to configure decrypt");
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800684
Yingdi Yu2e57a582014-02-20 23:34:43 -0800685 // CFDataRef output = (CFDataRef) SecTransformExecute(decrypt, &error);
686 // if (error)
687 // {
688 // CFShow(error);
689 // throw Error("Fail to decrypt data");
690 // }
691 // if (!output) throw Error("Output is NULL!\n");
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800692
Yingdi Yu2e57a582014-02-20 23:34:43 -0800693 // return make_shared<Buffer>(CFDataGetBytePtr(output), CFDataGetLength(output));
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800694}
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700695
Yingdi Yu2e57a582014-02-20 23:34:43 -0800696void
697SecTpmOsx::addAppToACL(const Name & keyName, KeyClass keyClass, const string & appPath, AclType acl)
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800698{
Yingdi Yu2e57a582014-02-20 23:34:43 -0800699 if(keyClass == KEY_CLASS_PRIVATE && acl == ACL_TYPE_PRIVATE)
700 {
701 SecKeychainItemRef privateKey = m_impl->getKey(keyName, keyClass);
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700702
Yingdi Yu2e57a582014-02-20 23:34:43 -0800703 SecAccessRef accRef;
704 OSStatus acc_res = SecKeychainItemCopyAccess(privateKey, &accRef);
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700705
Yingdi Yu2e57a582014-02-20 23:34:43 -0800706 CFArrayRef signACL = SecAccessCopyMatchingACLList(accRef,
707 kSecACLAuthorizationSign);
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700708
Yingdi Yu2e57a582014-02-20 23:34:43 -0800709 SecACLRef aclRef = (SecACLRef) CFArrayGetValueAtIndex(signACL, 0);
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700710
Yingdi Yu2e57a582014-02-20 23:34:43 -0800711 CFArrayRef appList;
712 CFStringRef description;
713 SecKeychainPromptSelector promptSelector;
714 OSStatus acl_res = SecACLCopyContents(aclRef,
715 &appList,
716 &description,
717 &promptSelector);
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700718
Yingdi Yu2e57a582014-02-20 23:34:43 -0800719 CFMutableArrayRef newAppList = CFArrayCreateMutableCopy(NULL,
720 0,
721 appList);
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700722
Yingdi Yu2e57a582014-02-20 23:34:43 -0800723 SecTrustedApplicationRef trustedApp;
724 acl_res = SecTrustedApplicationCreateFromPath(appPath.c_str(),
725 &trustedApp);
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700726
Yingdi Yu2e57a582014-02-20 23:34:43 -0800727 CFArrayAppendValue(newAppList, trustedApp);
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700728
Yingdi Yu2e57a582014-02-20 23:34:43 -0800729 acl_res = SecACLSetContents(aclRef,
730 newAppList,
731 description,
732 promptSelector);
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700733
Yingdi Yu2e57a582014-02-20 23:34:43 -0800734 acc_res = SecKeychainItemSetAccess(privateKey, accRef);
735 }
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800736}
737
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800738ConstBufferPtr
Yingdi Yufc40d872014-02-18 12:56:04 -0800739SecTpmOsx::encryptInTpm(const uint8_t* data, size_t dataLength, const Name & keyName, bool sym)
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800740{
Yingdi Yu2e57a582014-02-20 23:34:43 -0800741 throw Error("SecTpmOsx::encryptInTpm is not supported");
742 // _LOG_TRACE("OSXPrivateKeyStorage::Encrypt");
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800743
Yingdi Yu2e57a582014-02-20 23:34:43 -0800744 // KeyClass keyClass;
745 // if(sym)
746 // keyClass = KEY_CLASS_SYMMETRIC;
747 // else
748 // keyClass = KEY_CLASS_PUBLIC;
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700749
Yingdi Yu2e57a582014-02-20 23:34:43 -0800750 // CFDataRef dataRef = CFDataCreate(NULL,
751 // reinterpret_cast<const unsigned char*>(data),
752 // dataLength
753 // );
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700754
Yingdi Yu2e57a582014-02-20 23:34:43 -0800755 // SecKeyRef encryptKey = (SecKeyRef)m_impl->getKey(keyName, keyClass);
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800756
Yingdi Yu2e57a582014-02-20 23:34:43 -0800757 // CFErrorRef error;
758 // SecTransformRef encrypt = SecEncryptTransformCreate(encryptKey, &error);
759 // if (error) throw Error("Fail to create encrypt");
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800760
Yingdi Yu2e57a582014-02-20 23:34:43 -0800761 // Boolean set_res = SecTransformSetAttribute(encrypt,
762 // kSecTransformInputAttributeName,
763 // dataRef,
764 // &error);
765 // if (error) throw Error("Fail to configure encrypt");
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800766
Yingdi Yu2e57a582014-02-20 23:34:43 -0800767 // CFDataRef output = (CFDataRef) SecTransformExecute(encrypt, &error);
768 // if (error) throw Error("Fail to encrypt data");
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800769
Yingdi Yu2e57a582014-02-20 23:34:43 -0800770 // if (!output) throw Error("Output is NULL!\n");
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800771
Yingdi Yu2e57a582014-02-20 23:34:43 -0800772 // return make_shared<Buffer> (CFDataGetBytePtr(output), CFDataGetLength(output));
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800773}
774
775bool
776SecTpmOsx::doesKeyExistInTpm(const Name & keyName, KeyClass keyClass)
777{
778 _LOG_TRACE("OSXPrivateKeyStorage::doesKeyExist");
779
780 string keyNameUri = m_impl->toInternalKeyName(keyName, keyClass);
781
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700782 CFStringRef keyLabel = CFStringCreateWithCString(NULL,
783 keyNameUri.c_str(),
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800784 kCFStringEncodingUTF8);
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700785
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800786 CFMutableDictionaryRef attrDict = CFDictionaryCreateMutable(NULL,
787 4,
788 &kCFTypeDictionaryKeyCallBacks,
789 NULL);
790
791 CFDictionaryAddValue(attrDict, kSecClass, kSecClassKey);
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800792 // CFDictionaryAddValue(attrDict, kSecAttrKeyClass, m_impl->getKeyClass(keyClass));
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800793 CFDictionaryAddValue(attrDict, kSecAttrLabel, keyLabel);
794 CFDictionaryAddValue(attrDict, kSecReturnRef, kCFBooleanTrue);
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700795
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800796 SecKeychainItemRef itemRef;
797 OSStatus res = SecItemCopyMatching((CFDictionaryRef)attrDict, (CFTypeRef*)&itemRef);
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700798
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800799 if(res == errSecSuccess)
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800800 return true;
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800801 else
802 return false;
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800803
804}
805
Yingdi Yu4b752752014-02-18 12:24:03 -0800806bool
807SecTpmOsx::generateRandomBlock(uint8_t* res, size_t size)
808{
809 return (SecRandomCopyBytes(kSecRandomDefault, size, res) == 0);
810}
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800811
812////////////////////////////////
813// OSXPrivateKeyStorage::Impl //
814////////////////////////////////
815
816SecKeychainItemRef
817SecTpmOsx::Impl::getKey(const Name & keyName, KeyClass keyClass)
818{
819 string keyNameUri = toInternalKeyName(keyName, keyClass);
820
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700821 CFStringRef keyLabel = CFStringCreateWithCString(NULL,
822 keyNameUri.c_str(),
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800823 kCFStringEncodingUTF8);
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700824
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800825 CFMutableDictionaryRef attrDict = CFDictionaryCreateMutable(NULL,
826 5,
827 &kCFTypeDictionaryKeyCallBacks,
828 NULL);
829
830 CFDictionaryAddValue(attrDict, kSecClass, kSecClassKey);
831 CFDictionaryAddValue(attrDict, kSecAttrLabel, keyLabel);
832 CFDictionaryAddValue(attrDict, kSecAttrKeyClass, getKeyClass(keyClass));
833 CFDictionaryAddValue(attrDict, kSecReturnRef, kCFBooleanTrue);
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700834
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800835 SecKeychainItemRef keyItem;
836
837 OSStatus res = SecItemCopyMatching((CFDictionaryRef) attrDict, (CFTypeRef*)&keyItem);
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700838
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800839 if(res != errSecSuccess){
840 _LOG_DEBUG("Fail to find the key!");
841 return NULL;
842 }
843 else
844 return keyItem;
845}
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700846
847string
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800848SecTpmOsx::Impl::toInternalKeyName(const Name & keyName, KeyClass keyClass)
849{
850 string keyUri = keyName.toUri();
851
852 if(KEY_CLASS_SYMMETRIC == keyClass)
853 return keyUri + "/symmetric";
854 else
855 return keyUri;
856}
857
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700858const CFTypeRef
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800859SecTpmOsx::Impl::getAsymKeyType(KeyType keyType)
860{
861 switch(keyType){
862 case KEY_TYPE_RSA:
863 return kSecAttrKeyTypeRSA;
864 default:
865 _LOG_DEBUG("Unrecognized key type!")
866 return NULL;
867 }
868}
869
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700870const CFTypeRef
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800871SecTpmOsx::Impl::getSymKeyType(KeyType keyType)
872{
873 switch(keyType){
874 case KEY_TYPE_AES:
875 return kSecAttrKeyTypeAES;
876 default:
877 _LOG_DEBUG("Unrecognized key type!")
878 return NULL;
879 }
880}
881
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700882const CFTypeRef
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800883SecTpmOsx::Impl::getKeyClass(KeyClass keyClass)
884{
885 switch(keyClass){
886 case KEY_CLASS_PRIVATE:
887 return kSecAttrKeyClassPrivate;
888 case KEY_CLASS_PUBLIC:
889 return kSecAttrKeyClassPublic;
890 case KEY_CLASS_SYMMETRIC:
891 return kSecAttrKeyClassSymmetric;
892 default:
893 _LOG_DEBUG("Unrecognized key class!");
894 return NULL;
895 }
896}
897
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700898const CFStringRef
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800899SecTpmOsx::Impl::getDigestAlgorithm(DigestAlgorithm digestAlgo)
900{
901 switch(digestAlgo){
Jeff Thompson2747dc02013-10-04 19:11:34 -0700902 // case DIGEST_MD2:
903 // return kSecDigestMD2;
904 // case DIGEST_MD5:
905 // return kSecDigestMD5;
906 // case DIGEST_SHA1:
907 // return kSecDigestSHA1;
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800908 case DIGEST_ALGORITHM_SHA256:
909 return kSecDigestSHA2;
910 default:
911 _LOG_DEBUG("Unrecognized digest algorithm!");
912 return NULL;
Jeff Thompson2747dc02013-10-04 19:11:34 -0700913 }
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800914}
Jeff Thompson2747dc02013-10-04 19:11:34 -0700915
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700916long
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800917SecTpmOsx::Impl::getDigestSize(DigestAlgorithm digestAlgo)
918{
919 switch(digestAlgo){
920 case DIGEST_ALGORITHM_SHA256:
921 return 256;
Jeff Thompson2747dc02013-10-04 19:11:34 -0700922 // case DIGEST_SHA1:
923 // case DIGEST_MD2:
924 // case DIGEST_MD5:
925 // return 0;
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800926 default:
927 _LOG_DEBUG("Unrecognized digest algorithm! Unknown digest size");
928 return -1;
Jeff Thompson2747dc02013-10-04 19:11:34 -0700929 }
Jeff Thompson2747dc02013-10-04 19:11:34 -0700930}
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700931
Yingdi Yufc40d872014-02-18 12:56:04 -0800932} // namespace ndn