blob: b805d4e4c24fc6db2706f171762006182b7cac6b [file] [log] [blame]
Alexander Afanasyevc169a812014-05-20 20:37:29 -04001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Jeff Thompson2747dc02013-10-04 19:11:34 -07002/**
Alexander Afanasyevc169a812014-05-20 20:37:29 -04003 * Copyright (c) 2013-2014 Regents of the University of California.
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07004 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07006 *
Alexander Afanasyevc169a812014-05-20 20:37:29 -04007 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License as published by the Free Software
9 * Foundation, either version 3 of the License, or (at your option) any later version.
10 *
11 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License and GNU Lesser
16 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -070020 *
21 * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
Jeff Thompson2747dc02013-10-04 19:11:34 -070022 */
23
Alexander Afanasyeve2dcdfd2014-02-07 15:53:28 -080024#include "common.hpp"
25
Alexander Afanasyev19508852014-01-29 01:01:51 -080026#include "sec-tpm-osx.hpp"
Yingdi Yuf56c68f2014-04-24 21:50:13 -070027#include "public-key.hpp"
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070028#include "../encoding/oid.hpp"
29#include "../encoding/buffer-stream.hpp"
Junxiao Shi482ccc52014-03-31 13:05:24 -070030#include "cryptopp.hpp"
Jeff Thompson2747dc02013-10-04 19:11:34 -070031
Yingdi Yu2b2b4792014-02-04 16:27:07 -080032#include <pwd.h>
33#include <unistd.h>
34#include <stdlib.h>
35#include <string.h>
Jeff Thompson2747dc02013-10-04 19:11:34 -070036
Alexander Afanasyev04b22a92014-01-05 22:40:17 -080037#include <CoreFoundation/CoreFoundation.h>
38#include <Security/Security.h>
Yingdi Yu4b752752014-02-18 12:24:03 -080039#include <Security/SecRandom.h>
Alexander Afanasyev04b22a92014-01-05 22:40:17 -080040#include <CoreServices/CoreServices.h>
Jeff Thompson2747dc02013-10-04 19:11:34 -070041
Alexander Afanasyev59d67a52014-04-03 16:09:31 -070042#include <Security/SecDigestTransform.h>
43
Yingdi Yufc40d872014-02-18 12:56:04 -080044namespace ndn {
45
Yingdi Yu7036ce22014-06-19 18:53:37 -070046using std::string;
47
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -070048/**
49 * @brief Helper class to wrap CoreFoundation object pointers
50 *
51 * The class is similar in spirit to shared_ptr, but uses CoreFoundation
52 * mechanisms to retain/release object.
53 *
54 * Original implementation by Christopher Hunt and it was borrowed from
55 * http://www.cocoabuilder.com/archive/cocoa/130776-auto-cfrelease-and.html
56 */
57template<class T>
58class CFReleaser
59{
60public:
61 //////////////////////////////
62 // Construction/destruction //
63
64 CFReleaser()
65 : m_typeRef(0)
66 {
67 }
68
69 CFReleaser(const T& typeRef)
70 : m_typeRef(typeRef)
71 {
72 }
73
74 CFReleaser(const CFReleaser& inReleaser)
75 : m_typeRef(0)
76 {
77 retain(inReleaser.m_typeRef);
78 }
79
80 CFReleaser&
81 operator=(const T& typeRef)
82 {
83 if (typeRef != m_typeRef) {
84 release();
85 m_typeRef = typeRef;
86 }
87 return *this;
88 }
89
90 CFReleaser&
91 operator=(const CFReleaser& inReleaser)
92 {
93 retain(inReleaser.m_typeRef);
94 return *this;
95 }
96
97 ~CFReleaser()
98 {
99 release();
100 }
101
102 ////////////
103 // Access //
104
105 // operator const T&() const
106 // {
107 // return m_typeRef;
108 // }
109
110 // operator T&()
111 // {
112 // return m_typeRef;
113 // }
114
115 const T&
116 get() const
117 {
118 return m_typeRef;
119 }
120
121 T&
122 get()
123 {
124 return m_typeRef;
125 }
126
127 ///////////////////
128 // Miscellaneous //
129
130 void
131 retain(const T& typeRef)
132 {
133 if (typeRef != 0) {
134 CFRetain(typeRef);
135 }
136 release();
137 m_typeRef = typeRef;
138 }
139
140 void release()
141 {
142 if (m_typeRef != 0) {
143 CFRelease(m_typeRef);
144 m_typeRef = 0;
145 }
146 };
147
148private:
149 T m_typeRef;
150};
151
152
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -0700153class SecTpmOsx::Impl
154{
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800155public:
156 Impl()
Yingdi Yube4150e2014-02-18 13:02:46 -0800157 : m_passwordSet(false)
158 , m_inTerminal(false)
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -0700159 {
160 }
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700161
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800162 /**
163 * @brief Convert NDN name of a key to internal name of the key.
164 *
Yingdi Yufc40d872014-02-18 12:56:04 -0800165 * @param keyName
166 * @param keyClass
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800167 * @return the internal key name
168 */
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700169 std::string
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700170 toInternalKeyName(const Name& keyName, KeyClass keyClass);
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700171
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800172 /**
173 * @brief Get key.
Yingdi Yufc40d872014-02-18 12:56:04 -0800174 *
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700175 * @param keyName
Yingdi Yufc40d872014-02-18 12:56:04 -0800176 * @param keyClass
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800177 * @returns pointer to the key
178 */
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -0700179 CFReleaser<SecKeychainItemRef>
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700180 getKey(const Name& keyName, KeyClass keyClass);
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700181
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800182 /**
Yingdi Yufc40d872014-02-18 12:56:04 -0800183 * @brief Convert keyType to MAC OS symmetric key key type
184 *
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800185 * @param keyType
186 * @returns MAC OS key type
187 */
Alexander Afanasyev24b75c82014-05-31 15:59:31 +0300188 CFTypeRef
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800189 getSymKeyType(KeyType keyType);
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700190
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800191 /**
Yingdi Yufc40d872014-02-18 12:56:04 -0800192 * @brief Convert keyType to MAC OS asymmetirc key type
193 *
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800194 * @param keyType
195 * @returns MAC OS key type
196 */
Alexander Afanasyev24b75c82014-05-31 15:59:31 +0300197 CFTypeRef
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800198 getAsymKeyType(KeyType keyType);
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700199
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800200 /**
Yingdi Yufc40d872014-02-18 12:56:04 -0800201 * @brief Convert keyClass to MAC OS key class
202 *
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800203 * @param keyClass
204 * @returns MAC OS key class
205 */
Alexander Afanasyev24b75c82014-05-31 15:59:31 +0300206 CFTypeRef
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800207 getKeyClass(KeyClass keyClass);
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700208
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800209 /**
Yingdi Yufc40d872014-02-18 12:56:04 -0800210 * @brief Convert digestAlgo to MAC OS algorithm id
211 *
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800212 * @param digestAlgo
213 * @returns MAC OS algorithm id
214 */
Alexander Afanasyev24b75c82014-05-31 15:59:31 +0300215 CFStringRef
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800216 getDigestAlgorithm(DigestAlgorithm digestAlgo);
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700217
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800218 /**
Yingdi Yufc40d872014-02-18 12:56:04 -0800219 * @brief Get the digest size of the corresponding algorithm
220 *
221 * @param digestAlgo
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800222 * @return digest size
223 */
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700224 long
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800225 getDigestSize(DigestAlgorithm digestAlgo);
226
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800227 ///////////////////////////////////////////////
228 // everything here is public, including data //
229 ///////////////////////////////////////////////
230public:
231 SecKeychainRef m_keyChainRef;
Yingdi Yube4150e2014-02-18 13:02:46 -0800232 bool m_passwordSet;
233 string m_password;
234 bool m_inTerminal;
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800235};
236
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800237SecTpmOsx::SecTpmOsx()
238 : m_impl(new Impl)
239{
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700240 if (m_impl->m_inTerminal)
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700241 SecKeychainSetUserInteractionAllowed(false);
Yingdi Yube4150e2014-02-18 13:02:46 -0800242 else
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700243 SecKeychainSetUserInteractionAllowed(true);
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800244
Yingdi Yube4150e2014-02-18 13:02:46 -0800245 OSStatus res = SecKeychainCopyDefault(&m_impl->m_keyChainRef);
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700246
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800247 if (res == errSecNoDefaultKeychain) //If no default key chain, create one.
Yingdi Yube4150e2014-02-18 13:02:46 -0800248 throw Error("No default keychain, create one first!");
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800249}
250
251SecTpmOsx::~SecTpmOsx(){
252 //TODO: implement
253}
254
Yingdi Yube4150e2014-02-18 13:02:46 -0800255void
256SecTpmOsx::setTpmPassword(const uint8_t* password, size_t passwordLength)
257{
258 m_impl->m_passwordSet = true;
Yingdi Yu7036ce22014-06-19 18:53:37 -0700259 std::fill(m_impl->m_password.begin(), m_impl->m_password.end(), 0);
Yingdi Yube4150e2014-02-18 13:02:46 -0800260 m_impl->m_password.clear();
261 m_impl->m_password.append(reinterpret_cast<const char*>(password), passwordLength);
262}
263
264void
265SecTpmOsx::resetTpmPassword()
266{
267 m_impl->m_passwordSet = false;
Yingdi Yu7036ce22014-06-19 18:53:37 -0700268 std::fill(m_impl->m_password.begin(), m_impl->m_password.end(), 0);
Yingdi Yube4150e2014-02-18 13:02:46 -0800269 m_impl->m_password.clear();
270}
271
272void
273SecTpmOsx::setInTerminal(bool inTerminal)
274{
275 m_impl->m_inTerminal = inTerminal;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700276 if (inTerminal)
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700277 SecKeychainSetUserInteractionAllowed(false);
Yingdi Yube4150e2014-02-18 13:02:46 -0800278 else
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700279 SecKeychainSetUserInteractionAllowed(true);
Yingdi Yube4150e2014-02-18 13:02:46 -0800280}
281
282bool
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700283SecTpmOsx::getInTerminal() const
Yingdi Yube4150e2014-02-18 13:02:46 -0800284{
285 return m_impl->m_inTerminal;
286}
287
288bool
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700289SecTpmOsx::isLocked()
Yingdi Yube4150e2014-02-18 13:02:46 -0800290{
291 SecKeychainStatus keychainStatus;
292
293 OSStatus res = SecKeychainGetStatus(m_impl->m_keyChainRef, &keychainStatus);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700294 if (res != errSecSuccess)
Yingdi Yube4150e2014-02-18 13:02:46 -0800295 return true;
296 else
297 return ((kSecUnlockStateStatus & keychainStatus) == 0);
298}
299
Yingdi Yu2e57a582014-02-20 23:34:43 -0800300bool
Yingdi Yube4150e2014-02-18 13:02:46 -0800301SecTpmOsx::unlockTpm(const char* password, size_t passwordLength, bool usePassword)
302{
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700303 OSStatus res;
Yingdi Yube4150e2014-02-18 13:02:46 -0800304
305 // If the default key chain is already unlocked, return immediately.
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700306 if (!isLocked())
Yingdi Yu2e57a582014-02-20 23:34:43 -0800307 return true;
Yingdi Yube4150e2014-02-18 13:02:46 -0800308
309 // If the default key chain is locked, unlock the key chain.
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700310 if (usePassword)
Yingdi Yube4150e2014-02-18 13:02:46 -0800311 {
312 // Use the supplied password.
313 res = SecKeychainUnlock(m_impl->m_keyChainRef,
314 passwordLength,
315 password,
316 true);
317 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700318 else if (m_impl->m_passwordSet)
Yingdi Yube4150e2014-02-18 13:02:46 -0800319 {
320 // If no password supplied, then use the configured password if exists.
321 SecKeychainUnlock(m_impl->m_keyChainRef,
322 m_impl->m_password.size(),
323 m_impl->m_password.c_str(),
324 true);
325 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700326 else if (m_impl->m_inTerminal)
Yingdi Yube4150e2014-02-18 13:02:46 -0800327 {
328 // If no configured password, get password from terminal if inTerminal set.
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700329 bool isLocked = true;
Yingdi Yube4150e2014-02-18 13:02:46 -0800330 const char* fmt = "Password to unlock the default keychain: ";
331 int count = 0;
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700332
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700333 while (isLocked)
Yingdi Yube4150e2014-02-18 13:02:46 -0800334 {
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700335 if (count > 2)
Yingdi Yube4150e2014-02-18 13:02:46 -0800336 break;
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700337
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700338 char* getPassword = 0;
Yingdi Yube4150e2014-02-18 13:02:46 -0800339 getPassword = getpass(fmt);
340 count++;
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700341
Yingdi Yube4150e2014-02-18 13:02:46 -0800342 if (!getPassword)
343 continue;
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700344
Yingdi Yube4150e2014-02-18 13:02:46 -0800345 res = SecKeychainUnlock(m_impl->m_keyChainRef,
346 strlen(getPassword),
347 getPassword,
348 true);
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700349
Yingdi Yube4150e2014-02-18 13:02:46 -0800350 memset(getPassword, 0, strlen(getPassword));
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700351
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700352 if (res == errSecSuccess)
Yingdi Yu2e57a582014-02-20 23:34:43 -0800353 break;
Yingdi Yube4150e2014-02-18 13:02:46 -0800354 }
355 }
356 else
357 {
358 // If inTerminal is not set, get the password from GUI.
359 SecKeychainUnlock(m_impl->m_keyChainRef, 0, 0, false);
360 }
Yingdi Yu2e57a582014-02-20 23:34:43 -0800361
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700362 return !isLocked();
Yingdi Yube4150e2014-02-18 13:02:46 -0800363}
364
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700365void
Yingdi Yu7036ce22014-06-19 18:53:37 -0700366SecTpmOsx::generateKeyPairInTpmInternal(const Name& keyName,
367 const KeyParams& params,
368 bool needRetry)
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700369{
370
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700371 if (doesKeyExistInTpm(keyName, KEY_CLASS_PUBLIC))
372 {
373 throw Error("keyName has existed");
374 }
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800375
376 string keyNameUri = m_impl->toInternalKeyName(keyName, KEY_CLASS_PUBLIC);
377
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -0700378 CFReleaser<CFStringRef> keyLabel =
379 CFStringCreateWithCString(0,
380 keyNameUri.c_str(),
381 kCFStringEncodingUTF8);
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800382
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -0700383 CFReleaser<CFMutableDictionaryRef> attrDict =
384 CFDictionaryCreateMutable(0,
385 3,
386 &kCFTypeDictionaryKeyCallBacks,
387 0);
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700388
Yingdi Yu7036ce22014-06-19 18:53:37 -0700389 KeyType keyType = params.getKeyType();
390 uint32_t keySize;
391 switch (keyType)
392 {
393 case KEY_TYPE_RSA:
394 {
395 const RsaKeyParams& rsaParams = static_cast<const RsaKeyParams&>(params);
396 keySize = rsaParams.getKeySize();
397 break;
398 }
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700399 case KEY_TYPE_ECDSA:
400 {
401 const EcdsaKeyParams& ecdsaParams = static_cast<const EcdsaKeyParams&>(params);
402 keySize = ecdsaParams.getKeySize();
403 break;
404 }
Yingdi Yu7036ce22014-06-19 18:53:37 -0700405 default:
406 throw Error("Fail to create a key pair: Unsupported key type");
407 }
408
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -0700409 CFReleaser<CFNumberRef> cfKeySize = CFNumberCreate(0, kCFNumberIntType, &keySize);
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800410
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -0700411 CFDictionaryAddValue(attrDict.get(), kSecAttrKeyType, m_impl->getAsymKeyType(keyType));
412 CFDictionaryAddValue(attrDict.get(), kSecAttrKeySizeInBits, cfKeySize.get());
413 CFDictionaryAddValue(attrDict.get(), kSecAttrLabel, keyLabel.get());
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800414
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -0700415 CFReleaser<SecKeyRef> publicKey, privateKey;
Yingdi Yu7036ce22014-06-19 18:53:37 -0700416 // C-style cast is used as per Apple convention
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -0700417 OSStatus res = SecKeyGeneratePair((CFDictionaryRef)attrDict.get(),
418 &publicKey.get(), &privateKey.get());
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800419
Yingdi Yube4150e2014-02-18 13:02:46 -0800420 if (res == errSecSuccess)
Alexander Afanasyev60c86812014-02-20 15:19:33 -0800421 {
Alexander Afanasyev60c86812014-02-20 15:19:33 -0800422 return;
423 }
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700424
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700425 if (res == errSecAuthFailed && !needRetry)
Yingdi Yube4150e2014-02-18 13:02:46 -0800426 {
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700427 if (unlockTpm(0, 0, false))
Yingdi Yu7036ce22014-06-19 18:53:37 -0700428 generateKeyPairInTpmInternal(keyName, params, true);
Yingdi Yu2e57a582014-02-20 23:34:43 -0800429 else
430 throw Error("Fail to unlock the keychain");
Yingdi Yube4150e2014-02-18 13:02:46 -0800431 }
432 else
433 {
Yingdi Yube4150e2014-02-18 13:02:46 -0800434 throw Error("Fail to create a key pair");
435 }
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800436}
437
438void
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700439SecTpmOsx::deleteKeyPairInTpmInternal(const Name& keyName, bool needRetry)
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800440{
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -0700441 CFReleaser<CFStringRef> keyLabel =
442 CFStringCreateWithCString(0,
443 keyName.toUri().c_str(),
444 kCFStringEncodingUTF8);
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800445
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -0700446 CFReleaser<CFMutableDictionaryRef> searchDict =
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700447 CFDictionaryCreateMutable(0, 5,
448 &kCFTypeDictionaryKeyCallBacks,
449 &kCFTypeDictionaryValueCallBacks);
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800450
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -0700451 CFDictionaryAddValue(searchDict.get(), kSecClass, kSecClassKey);
452 CFDictionaryAddValue(searchDict.get(), kSecAttrLabel, keyLabel.get());
453 CFDictionaryAddValue(searchDict.get(), kSecMatchLimit, kSecMatchLimitAll);
454 OSStatus res = SecItemDelete(searchDict.get());
Yingdi Yube4150e2014-02-18 13:02:46 -0800455
456 if (res == errSecSuccess)
457 return;
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700458
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700459 if (res == errSecAuthFailed && !needRetry)
Yingdi Yube4150e2014-02-18 13:02:46 -0800460 {
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700461 if (unlockTpm(0, 0, false))
Yingdi Yu2e57a582014-02-20 23:34:43 -0800462 deleteKeyPairInTpmInternal(keyName, true);
Yingdi Yube4150e2014-02-18 13:02:46 -0800463 }
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800464}
465
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700466void
Yingdi Yu7036ce22014-06-19 18:53:37 -0700467SecTpmOsx::generateSymmetricKeyInTpm(const Name& keyName, const KeyParams& params)
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800468{
Yingdi Yu2e57a582014-02-20 23:34:43 -0800469 throw Error("SecTpmOsx::generateSymmetricKeyInTpm is not supported");
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700470 // if (doesKeyExistInTpm(keyName, KEY_CLASS_SYMMETRIC))
Yingdi Yu2e57a582014-02-20 23:34:43 -0800471 // throw Error("keyName has existed!");
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800472
Yingdi Yu2e57a582014-02-20 23:34:43 -0800473 // string keyNameUri = m_impl->toInternalKeyName(keyName, KEY_CLASS_SYMMETRIC);
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800474
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -0700475 // CFReleaser<CFMutableDictionaryRef> attrDict =
476 // CFDictionaryCreateMutable(kCFAllocatorDefault,
477 // 0,
478 // &kCFTypeDictionaryKeyCallBacks,
479 // &kCFTypeDictionaryValueCallBacks);
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800480
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -0700481 // CFReleaser<CFStringRef> keyLabel =
482 // CFStringCreateWithCString(0,
483 // keyNameUri.c_str(),
484 // kCFStringEncodingUTF8);
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800485
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -0700486 // CFReleaser<CFNumberRef> cfKeySize = CFNumberCreate(0, kCFNumberIntType, &keySize);
487
488 // CFDictionaryAddValue(attrDict.get(), kSecAttrKeyType, m_impl->getSymKeyType(keyType));
489 // CFDictionaryAddValue(attrDict.get(), kSecAttrKeySizeInBits, cfKeySize.get());
490 // CFDictionaryAddValue(attrDict.get(), kSecAttrIsPermanent, kCFBooleanTrue);
491 // CFDictionaryAddValue(attrDict.get(), kSecAttrLabel, keyLabel.get());
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800492
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700493 // CFErrorRef error = 0;
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800494
Yingdi Yu2e57a582014-02-20 23:34:43 -0800495 // SecKeyRef symmetricKey = SecKeyGenerateSymmetric(attrDict, &error);
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800496
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700497 // if (error)
Yingdi Yu2e57a582014-02-20 23:34:43 -0800498 // throw Error("Fail to create a symmetric key");
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800499}
500
Yingdi Yu2e57a582014-02-20 23:34:43 -0800501shared_ptr<PublicKey>
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700502SecTpmOsx::getPublicKeyFromTpm(const Name& keyName)
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800503{
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -0700504 CFReleaser<SecKeychainItemRef> publicKey = m_impl->getKey(keyName, KEY_CLASS_PUBLIC);
505 if (publicKey.get() == 0)
506 {
507 throw Error("Requested public key [" + keyName.toUri() + "] does not exist in OSX Keychain");
508 }
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800509
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -0700510 CFReleaser<CFDataRef> exportedKey;
511 OSStatus res = SecItemExport(publicKey.get(),
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800512 kSecFormatOpenSSL,
513 0,
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700514 0,
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -0700515 &exportedKey.get());
Alexander Afanasyev60c86812014-02-20 15:19:33 -0800516 if (res != errSecSuccess)
517 {
518 throw Error("Cannot export requested public key from OSX Keychain");
519 }
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800520
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -0700521 shared_ptr<PublicKey> key = make_shared<PublicKey>(CFDataGetBytePtr(exportedKey.get()),
522 CFDataGetLength(exportedKey.get()));
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800523 return key;
524}
525
526ConstBufferPtr
Yingdi Yu5e96e002014-04-23 18:32:15 -0700527SecTpmOsx::exportPrivateKeyPkcs8FromTpmInternal(const Name& keyName, bool needRetry)
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800528{
529 using namespace CryptoPP;
530
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -0700531 CFReleaser<SecKeychainItemRef> privateKey = m_impl->getKey(keyName, KEY_CLASS_PRIVATE);
532 if (privateKey.get() == 0)
533 {
534 /// @todo Can this happen because of keychain is locked?
535 throw Error("Private key [" + keyName.toUri() + "] does not exist in OSX Keychain");
536 }
537
Yingdi Yu9d9d5992014-06-25 12:25:16 -0700538 shared_ptr<PublicKey> publicKey = getPublicKeyFromTpm(keyName);
539
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -0700540 CFReleaser<CFDataRef> exportedKey;
541 OSStatus res = SecItemExport(privateKey.get(),
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800542 kSecFormatOpenSSL,
543 0,
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700544 0,
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -0700545 &exportedKey.get());
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800546
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700547 if (res != errSecSuccess)
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800548 {
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700549 if (res == errSecAuthFailed && !needRetry)
Yingdi Yube4150e2014-02-18 13:02:46 -0800550 {
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700551 if (unlockTpm(0, 0, false))
Yingdi Yu5e96e002014-04-23 18:32:15 -0700552 return exportPrivateKeyPkcs8FromTpmInternal(keyName, true);
Yingdi Yu2e57a582014-02-20 23:34:43 -0800553 else
554 return shared_ptr<Buffer>();
Yingdi Yube4150e2014-02-18 13:02:46 -0800555 }
556 else
557 return shared_ptr<Buffer>();
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800558 }
559
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800560 uint32_t version = 0;
Yingdi Yu9d9d5992014-06-25 12:25:16 -0700561 OID algorithm;
562 bool hasParameters = false;
563 OID algorithmParameter;
564 switch (publicKey->getKeyType()) {
565 case KEY_TYPE_RSA:
566 {
567 algorithm = oid::RSA; // "RSA encryption"
568 hasParameters = false;
569 break;
570 }
571 case KEY_TYPE_ECDSA:
572 {
573 // "ECDSA encryption"
574 StringSource src(publicKey->get().buf(), publicKey->get().size(), true);
575 BERSequenceDecoder subjectPublicKeyInfo(src);
576 {
577 BERSequenceDecoder algorithmInfo(subjectPublicKeyInfo);
578 {
579 algorithm.decode(algorithmInfo);
580 algorithmParameter.decode(algorithmInfo);
581 }
582 }
583 hasParameters = true;
584 break;
585 }
586 default:
587 throw Error("Unsupported key type" +
588 boost::lexical_cast<std::string>(publicKey->getKeyType()));
589 }
590
591 OBufferStream pkcs8Os;
592 FileSink sink(pkcs8Os);
593
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800594 SecByteBlock rawKeyBits;
595 // PrivateKeyInfo ::= SEQUENCE {
596 // version INTEGER,
597 // privateKeyAlgorithm SEQUENCE,
598 // privateKey OCTECT STRING}
599 DERSequenceEncoder privateKeyInfo(sink);
600 {
601 DEREncodeUnsigned<uint32_t>(privateKeyInfo, version, INTEGER);
602 DERSequenceEncoder privateKeyAlgorithm(privateKeyInfo);
603 {
604 algorithm.encode(privateKeyAlgorithm);
Yingdi Yu9d9d5992014-06-25 12:25:16 -0700605 if (hasParameters)
606 algorithmParameter.encode(privateKeyAlgorithm);
607 else
608 DEREncodeNull(privateKeyAlgorithm);
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800609 }
610 privateKeyAlgorithm.MessageEnd();
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700611 DEREncodeOctetString(privateKeyInfo,
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -0700612 CFDataGetBytePtr(exportedKey.get()),
613 CFDataGetLength(exportedKey.get()));
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800614 }
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700615 privateKeyInfo.MessageEnd();
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800616
Yingdi Yu9d9d5992014-06-25 12:25:16 -0700617 return pkcs8Os.buf();
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800618}
619
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700620#ifdef __GNUC__
621#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
622#pragma GCC diagnostic push
623#endif // __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
624#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
625#endif // __GNUC__
626
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800627bool
Yingdi Yu5e96e002014-04-23 18:32:15 -0700628SecTpmOsx::importPrivateKeyPkcs8IntoTpmInternal(const Name& keyName,
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700629 const uint8_t* buf, size_t size,
630 bool needRetry)
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800631{
632 using namespace CryptoPP;
633
634 StringSource privateKeySource(buf, size, true);
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800635 SecByteBlock rawKeyBits;
636 // PrivateKeyInfo ::= SEQUENCE {
637 // INTEGER,
638 // SEQUENCE,
639 // OCTECT STRING}
640 BERSequenceDecoder privateKeyInfo(privateKeySource);
641 {
Yingdi Yu9d9d5992014-06-25 12:25:16 -0700642 uint32_t versionNum;
643 BERDecodeUnsigned<uint32_t>(privateKeyInfo, versionNum, INTEGER);
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800644 BERSequenceDecoder sequenceDecoder(privateKeyInfo);
645 {
Yingdi Yu9d9d5992014-06-25 12:25:16 -0700646 OID keyTypeOID;
647 keyTypeOID.decode(sequenceDecoder);
648
649 if (keyTypeOID == oid::RSA)
650 BERDecodeNull(sequenceDecoder);
651 else if (keyTypeOID == oid::ECDSA)
652 {
653 OID parameterOID;
654 parameterOID.decode(sequenceDecoder);
655 }
656 else
657 return false; // Unsupported key type;
658
659
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800660 }
661 BERDecodeOctetString(privateKeyInfo, rawKeyBits);
662 }
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700663 privateKeyInfo.MessageEnd();
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800664
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -0700665 CFReleaser<CFDataRef> importedKey = CFDataCreateWithBytesNoCopy(0,
666 rawKeyBits.BytePtr(),
667 rawKeyBits.size(),
668 kCFAllocatorNull);
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800669
670 SecExternalFormat externalFormat = kSecFormatOpenSSL;
671 SecExternalItemType externalType = kSecItemTypePrivateKey;
672 SecKeyImportExportParameters keyParams;
673 memset(&keyParams, 0, sizeof(keyParams));
674 keyParams.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
675 keyParams.keyAttributes = CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_PERMANENT;
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -0700676 CFReleaser<SecAccessRef> access;
677 CFReleaser<CFStringRef> keyLabel = CFStringCreateWithCString(0,
678 keyName.toUri().c_str(),
679 kCFStringEncodingUTF8);
680 SecAccessCreate(keyLabel.get(), 0, &access.get());
681 keyParams.accessRef = access.get();
682 CFReleaser<CFArrayRef> outItems;
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800683
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700684#ifdef __clang__
Junxiao Shi482ccc52014-03-31 13:05:24 -0700685#pragma clang diagnostic push
686#pragma clang diagnostic ignored "-Wdeprecated-declarations"
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700687#endif // __clang__
688
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -0700689 OSStatus res = SecKeychainItemImport(importedKey.get(),
690 0,
691 &externalFormat,
692 &externalType,
693 0,
694 &keyParams,
695 m_impl->m_keyChainRef,
696 &outItems.get());
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700697
698#ifdef __clang__
Junxiao Shi482ccc52014-03-31 13:05:24 -0700699#pragma clang diagnostic pop
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700700#endif // __clang__
701
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700702 if (res != errSecSuccess)
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800703 {
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700704 if (res == errSecAuthFailed && !needRetry)
Yingdi Yube4150e2014-02-18 13:02:46 -0800705 {
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700706 if (unlockTpm(0, 0, false))
Yingdi Yu5e96e002014-04-23 18:32:15 -0700707 return importPrivateKeyPkcs8IntoTpmInternal(keyName, buf, size, true);
Yingdi Yu2e57a582014-02-20 23:34:43 -0800708 else
709 return false;
Yingdi Yube4150e2014-02-18 13:02:46 -0800710 }
711 else
712 return false;
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800713 }
714
Yingdi Yu7036ce22014-06-19 18:53:37 -0700715 // C-style cast is used as per Apple convention
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -0700716 SecKeychainItemRef privateKey = (SecKeychainItemRef)CFArrayGetValueAtIndex(outItems.get(), 0);
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800717 SecKeychainAttribute attrs[1]; // maximum number of attributes
718 SecKeychainAttributeList attrList = { 0, attrs };
719 string keyUri = keyName.toUri();
720 {
721 attrs[attrList.count].tag = kSecKeyPrintName;
722 attrs[attrList.count].length = keyUri.size();
Yingdi Yu7036ce22014-06-19 18:53:37 -0700723 attrs[attrList.count].data = const_cast<char*>(keyUri.c_str());
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800724 attrList.count++;
725 }
726
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700727 res = SecKeychainItemModifyAttributesAndData(privateKey,
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800728 &attrList,
729 0,
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700730 0);
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700731
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700732 if (res != errSecSuccess)
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800733 {
734 return false;
735 }
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700736
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800737 return true;
738}
739
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700740#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
741#pragma GCC diagnostic pop
742#endif // __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
743
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800744bool
745SecTpmOsx::importPublicKeyPkcs1IntoTpm(const Name& keyName, const uint8_t* buf, size_t size)
746{
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -0700747 CFReleaser<CFDataRef> importedKey = CFDataCreateWithBytesNoCopy(0,
748 buf,
749 size,
750 kCFAllocatorNull);
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800751
752 SecExternalFormat externalFormat = kSecFormatOpenSSL;
753 SecExternalItemType externalType = kSecItemTypePublicKey;
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -0700754 CFReleaser<CFArrayRef> outItems;
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800755
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -0700756 OSStatus res = SecItemImport(importedKey.get(),
757 0,
758 &externalFormat,
759 &externalType,
760 0,
761 0,
762 m_impl->m_keyChainRef,
763 &outItems.get());
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800764
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700765 if (res != errSecSuccess)
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800766 return false;
767
Yingdi Yu7036ce22014-06-19 18:53:37 -0700768 // C-style cast is used as per Apple convention
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -0700769 SecKeychainItemRef publicKey = (SecKeychainItemRef)CFArrayGetValueAtIndex(outItems.get(), 0);
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800770 SecKeychainAttribute attrs[1]; // maximum number of attributes
771 SecKeychainAttributeList attrList = { 0, attrs };
772 string keyUri = keyName.toUri();
773 {
774 attrs[attrList.count].tag = kSecKeyPrintName;
775 attrs[attrList.count].length = keyUri.size();
Yingdi Yu7036ce22014-06-19 18:53:37 -0700776 attrs[attrList.count].data = const_cast<char*>(keyUri.c_str());
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800777 attrList.count++;
778 }
779
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700780 res = SecKeychainItemModifyAttributesAndData(publicKey,
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800781 &attrList,
782 0,
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700783 0);
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700784
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700785 if (res != errSecSuccess)
Alexander Afanasyev60c86812014-02-20 15:19:33 -0800786 return false;
787
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800788 return true;
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800789}
790
791Block
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700792SecTpmOsx::signInTpmInternal(const uint8_t* data, size_t dataLength,
793 const Name& keyName, DigestAlgorithm digestAlgorithm, bool needRetry)
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800794{
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -0700795 CFReleaser<CFDataRef> dataRef = CFDataCreateWithBytesNoCopy(0,
796 data,
797 dataLength,
798 kCFAllocatorNull);
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800799
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -0700800 CFReleaser<SecKeychainItemRef> privateKey = m_impl->getKey(keyName, KEY_CLASS_PRIVATE);
801 if (privateKey.get() == 0)
802 {
803 throw Error("Private key [" + keyName.toUri() + "] does not exist in OSX Keychain");
804 }
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700805
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -0700806 CFReleaser<CFErrorRef> error;
Yingdi Yu7036ce22014-06-19 18:53:37 -0700807 // C-style cast is used as per Apple convention
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -0700808 CFReleaser<SecTransformRef> signer = SecSignTransformCreate((SecKeyRef)privateKey.get(),
809 &error.get());
810 if (error.get() != 0)
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700811 throw Error("Fail to create signer");
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800812
813 // Set input
Yingdi Yu7036ce22014-06-19 18:53:37 -0700814 SecTransformSetAttribute(signer.get(),
815 kSecTransformInputAttributeName,
816 dataRef.get(),
817 &error.get());
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -0700818 if (error.get() != 0)
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700819 throw Error("Fail to configure input of signer");
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800820
821 // Enable use of padding
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -0700822 SecTransformSetAttribute(signer.get(),
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800823 kSecPaddingKey,
824 kSecPaddingPKCS1Key,
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -0700825 &error.get());
826 if (error.get() != 0)
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700827 throw Error("Fail to configure digest algorithm of signer");
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800828
829 // Set padding type
Yingdi Yu7036ce22014-06-19 18:53:37 -0700830 SecTransformSetAttribute(signer.get(),
831 kSecDigestTypeAttribute,
832 m_impl->getDigestAlgorithm(digestAlgorithm),
833 &error.get());
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -0700834 if (error.get() != 0)
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700835 throw Error("Fail to configure digest algorithm of signer");
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800836
837 // Set padding attribute
838 long digestSize = m_impl->getDigestSize(digestAlgorithm);
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -0700839 CFReleaser<CFNumberRef> cfDigestSize = CFNumberCreate(0, kCFNumberLongType, &digestSize);
Yingdi Yu7036ce22014-06-19 18:53:37 -0700840 SecTransformSetAttribute(signer.get(),
841 kSecDigestLengthAttribute,
842 cfDigestSize.get(),
843 &error.get());
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -0700844 if (error.get() != 0)
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700845 throw Error("Fail to configure digest size of signer");
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800846
847 // Actually sign
Yingdi Yu7036ce22014-06-19 18:53:37 -0700848 // C-style cast is used as per Apple convention
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -0700849 CFReleaser<CFDataRef> signature = (CFDataRef)SecTransformExecute(signer.get(), &error.get());
850 if (error.get() != 0)
Yingdi Yube4150e2014-02-18 13:02:46 -0800851 {
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700852 if (!needRetry)
Yingdi Yube4150e2014-02-18 13:02:46 -0800853 {
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700854 if (unlockTpm(0, 0, false))
Yingdi Yu2e57a582014-02-20 23:34:43 -0800855 return signInTpmInternal(data, dataLength, keyName, digestAlgorithm, true);
856 else
857 throw Error("Fail to unlock the keychain");
Yingdi Yube4150e2014-02-18 13:02:46 -0800858 }
859 else
860 {
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -0700861 CFShow(error.get());
Yingdi Yube4150e2014-02-18 13:02:46 -0800862 throw Error("Fail to sign data");
863 }
864 }
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800865
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -0700866 if (signature.get() == 0)
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700867 throw Error("Signature is NULL!\n");
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800868
869 return Block(Tlv::SignatureValue,
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -0700870 make_shared<Buffer>(CFDataGetBytePtr(signature.get()),
871 CFDataGetLength(signature.get())));
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800872}
873
874ConstBufferPtr
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700875SecTpmOsx::decryptInTpm(const uint8_t* data, size_t dataLength, const Name& keyName, bool sym)
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800876{
Yingdi Yu2e57a582014-02-20 23:34:43 -0800877 throw Error("SecTpmOsx::decryptInTpm is not supported");
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800878
Yingdi Yu2e57a582014-02-20 23:34:43 -0800879 // KeyClass keyClass;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700880 // if (sym)
Yingdi Yu2e57a582014-02-20 23:34:43 -0800881 // keyClass = KEY_CLASS_SYMMETRIC;
882 // else
883 // keyClass = KEY_CLASS_PRIVATE;
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800884
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700885 // CFDataRef dataRef = CFDataCreate(0,
Yingdi Yu2e57a582014-02-20 23:34:43 -0800886 // reinterpret_cast<const unsigned char*>(data),
887 // dataLength
888 // );
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800889
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -0700890 // CFReleaser<SecKeyRef> decryptKey = (SecKeyRef)m_impl->getKey(keyName, keyClass);
891 // if (decryptKey.get() == 0)
892 // {
893 // /// @todo Can this happen because of keychain is locked?
894 // throw Error("Decruption key [" + ??? + "] does not exist in OSX Keychain");
895 // }
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800896
Yingdi Yu2e57a582014-02-20 23:34:43 -0800897 // CFErrorRef error;
898 // SecTransformRef decrypt = SecDecryptTransformCreate(decryptKey, &error);
899 // if (error) throw Error("Fail to create decrypt");
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800900
Yingdi Yu2e57a582014-02-20 23:34:43 -0800901 // Boolean set_res = SecTransformSetAttribute(decrypt,
902 // kSecTransformInputAttributeName,
903 // dataRef,
904 // &error);
905 // if (error) throw Error("Fail to configure decrypt");
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800906
Yingdi Yu2e57a582014-02-20 23:34:43 -0800907 // CFDataRef output = (CFDataRef) SecTransformExecute(decrypt, &error);
908 // if (error)
909 // {
910 // CFShow(error);
911 // throw Error("Fail to decrypt data");
912 // }
913 // if (!output) throw Error("Output is NULL!\n");
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800914
Yingdi Yu2e57a582014-02-20 23:34:43 -0800915 // return make_shared<Buffer>(CFDataGetBytePtr(output), CFDataGetLength(output));
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800916}
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700917
Yingdi Yu2e57a582014-02-20 23:34:43 -0800918void
Yingdi Yuf56c68f2014-04-24 21:50:13 -0700919SecTpmOsx::addAppToAcl(const Name& keyName, KeyClass keyClass, const string& appPath, AclType acl)
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800920{
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700921 if (keyClass == KEY_CLASS_PRIVATE && acl == ACL_TYPE_PRIVATE)
Yingdi Yu2e57a582014-02-20 23:34:43 -0800922 {
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -0700923 CFReleaser<SecKeychainItemRef> privateKey = m_impl->getKey(keyName, keyClass);
924 if (privateKey.get() == 0)
925 {
926 throw Error("Private key [" + keyName.toUri() + "] does not exist in OSX Keychain");
927 }
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700928
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -0700929 CFReleaser<SecAccessRef> accRef;
Yingdi Yu7036ce22014-06-19 18:53:37 -0700930 SecKeychainItemCopyAccess(privateKey.get(), &accRef.get());
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700931
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -0700932 CFReleaser<CFArrayRef> signACL = SecAccessCopyMatchingACLList(accRef.get(),
933 kSecACLAuthorizationSign);
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700934
Yingdi Yu7036ce22014-06-19 18:53:37 -0700935 // C-style cast is used as per Apple convention
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -0700936 SecACLRef aclRef = (SecACLRef)CFArrayGetValueAtIndex(signACL.get(), 0);
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700937
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -0700938 CFReleaser<CFArrayRef> appList;
939 CFReleaser<CFStringRef> description;
Yingdi Yu2e57a582014-02-20 23:34:43 -0800940 SecKeychainPromptSelector promptSelector;
Yingdi Yu7036ce22014-06-19 18:53:37 -0700941 SecACLCopyContents(aclRef,
942 &appList.get(),
943 &description.get(),
944 &promptSelector);
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700945
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -0700946 CFReleaser<CFMutableArrayRef> newAppList = CFArrayCreateMutableCopy(0,
947 0,
948 appList.get());
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700949
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -0700950 CFReleaser<SecTrustedApplicationRef> trustedApp;
Yingdi Yu7036ce22014-06-19 18:53:37 -0700951 SecTrustedApplicationCreateFromPath(appPath.c_str(),
952 &trustedApp.get());
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700953
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -0700954 CFArrayAppendValue(newAppList.get(), trustedApp.get());
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700955
Yingdi Yu7036ce22014-06-19 18:53:37 -0700956 SecACLSetContents(aclRef,
957 newAppList.get(),
958 description.get(),
959 promptSelector);
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700960
Yingdi Yu7036ce22014-06-19 18:53:37 -0700961 SecKeychainItemSetAccess(privateKey.get(), accRef.get());
Yingdi Yu2e57a582014-02-20 23:34:43 -0800962 }
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800963}
964
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800965ConstBufferPtr
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700966SecTpmOsx::encryptInTpm(const uint8_t* data, size_t dataLength, const Name& keyName, bool sym)
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800967{
Yingdi Yu2e57a582014-02-20 23:34:43 -0800968 throw Error("SecTpmOsx::encryptInTpm is not supported");
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800969
Yingdi Yu2e57a582014-02-20 23:34:43 -0800970 // KeyClass keyClass;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700971 // if (sym)
Yingdi Yu2e57a582014-02-20 23:34:43 -0800972 // keyClass = KEY_CLASS_SYMMETRIC;
973 // else
974 // keyClass = KEY_CLASS_PUBLIC;
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700975
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700976 // CFDataRef dataRef = CFDataCreate(0,
Yingdi Yu2e57a582014-02-20 23:34:43 -0800977 // reinterpret_cast<const unsigned char*>(data),
978 // dataLength
979 // );
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700980
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -0700981 // CFReleaser<SecKeyRef> encryptKey = (SecKeyRef)m_impl->getKey(keyName, keyClass);
982 // if (encryptKey.get() == 0)
983 // {
984 // throw Error("Encryption key [" + ???? + "] does not exist in OSX Keychain");
985 // }
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800986
Yingdi Yu2e57a582014-02-20 23:34:43 -0800987 // CFErrorRef error;
988 // SecTransformRef encrypt = SecEncryptTransformCreate(encryptKey, &error);
989 // if (error) throw Error("Fail to create encrypt");
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800990
Yingdi Yu2e57a582014-02-20 23:34:43 -0800991 // Boolean set_res = SecTransformSetAttribute(encrypt,
992 // kSecTransformInputAttributeName,
993 // dataRef,
994 // &error);
995 // if (error) throw Error("Fail to configure encrypt");
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800996
Yingdi Yu2e57a582014-02-20 23:34:43 -0800997 // CFDataRef output = (CFDataRef) SecTransformExecute(encrypt, &error);
998 // if (error) throw Error("Fail to encrypt data");
Yingdi Yu2b2b4792014-02-04 16:27:07 -0800999
Yingdi Yu2e57a582014-02-20 23:34:43 -08001000 // if (!output) throw Error("Output is NULL!\n");
Yingdi Yu2b2b4792014-02-04 16:27:07 -08001001
Yingdi Yu2e57a582014-02-20 23:34:43 -08001002 // return make_shared<Buffer> (CFDataGetBytePtr(output), CFDataGetLength(output));
Yingdi Yu2b2b4792014-02-04 16:27:07 -08001003}
1004
1005bool
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -07001006SecTpmOsx::doesKeyExistInTpm(const Name& keyName, KeyClass keyClass)
Yingdi Yu2b2b4792014-02-04 16:27:07 -08001007{
Yingdi Yu2b2b4792014-02-04 16:27:07 -08001008 string keyNameUri = m_impl->toInternalKeyName(keyName, keyClass);
1009
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -07001010 CFReleaser<CFStringRef> keyLabel = CFStringCreateWithCString(0,
1011 keyNameUri.c_str(),
1012 kCFStringEncodingUTF8);
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -07001013
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -07001014 CFReleaser<CFMutableDictionaryRef> attrDict =
1015 CFDictionaryCreateMutable(0,
1016 4,
1017 &kCFTypeDictionaryKeyCallBacks,
1018 0);
Yingdi Yu2b2b4792014-02-04 16:27:07 -08001019
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -07001020 CFDictionaryAddValue(attrDict.get(), kSecClass, kSecClassKey);
1021 // CFDictionaryAddValue(attrDict.get(), kSecAttrKeyClass, m_impl->getKeyClass(keyClass));
1022 CFDictionaryAddValue(attrDict.get(), kSecAttrLabel, keyLabel.get());
1023 CFDictionaryAddValue(attrDict.get(), kSecReturnRef, kCFBooleanTrue);
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -07001024
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -07001025 CFReleaser<SecKeychainItemRef> itemRef;
Yingdi Yu7036ce22014-06-19 18:53:37 -07001026 // C-style cast is used as per Apple convention
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -07001027 OSStatus res = SecItemCopyMatching((CFDictionaryRef)attrDict.get(), (CFTypeRef*)&itemRef.get());
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -07001028
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -07001029 if (res == errSecSuccess)
Yingdi Yu2b2b4792014-02-04 16:27:07 -08001030 return true;
Yingdi Yu8dceb1d2014-02-18 12:45:10 -08001031 else
1032 return false;
Yingdi Yu2b2b4792014-02-04 16:27:07 -08001033
1034}
1035
Yingdi Yu4b752752014-02-18 12:24:03 -08001036bool
1037SecTpmOsx::generateRandomBlock(uint8_t* res, size_t size)
1038{
Yingdi Yu7036ce22014-06-19 18:53:37 -07001039 return SecRandomCopyBytes(kSecRandomDefault, size, res) == 0;
Yingdi Yu4b752752014-02-18 12:24:03 -08001040}
Yingdi Yu2b2b4792014-02-04 16:27:07 -08001041
1042////////////////////////////////
1043// OSXPrivateKeyStorage::Impl //
1044////////////////////////////////
1045
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -07001046CFReleaser<SecKeychainItemRef>
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -07001047SecTpmOsx::Impl::getKey(const Name& keyName, KeyClass keyClass)
Yingdi Yu2b2b4792014-02-04 16:27:07 -08001048{
1049 string keyNameUri = toInternalKeyName(keyName, keyClass);
1050
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -07001051 CFReleaser<CFStringRef> keyLabel = CFStringCreateWithCString(0,
1052 keyNameUri.c_str(),
1053 kCFStringEncodingUTF8);
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -07001054
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -07001055 CFReleaser<CFMutableDictionaryRef> attrDict =
1056 CFDictionaryCreateMutable(0,
1057 5,
1058 &kCFTypeDictionaryKeyCallBacks,
1059 0);
Yingdi Yu2b2b4792014-02-04 16:27:07 -08001060
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -07001061 CFDictionaryAddValue(attrDict.get(), kSecClass, kSecClassKey);
1062 CFDictionaryAddValue(attrDict.get(), kSecAttrLabel, keyLabel.get());
1063 CFDictionaryAddValue(attrDict.get(), kSecAttrKeyClass, getKeyClass(keyClass));
1064 CFDictionaryAddValue(attrDict.get(), kSecReturnRef, kCFBooleanTrue);
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -07001065
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -07001066 CFReleaser<SecKeychainItemRef> keyItem;
Yingdi Yu7036ce22014-06-19 18:53:37 -07001067 // C-style cast is used as per Apple convention
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -07001068 OSStatus res = SecItemCopyMatching((CFDictionaryRef)attrDict.get(), (CFTypeRef*)&keyItem.get());
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -07001069
Yingdi Yu4b8c6a22014-04-15 23:00:54 -07001070 if (res != errSecSuccess)
1071 return 0;
Yingdi Yu2b2b4792014-02-04 16:27:07 -08001072 else
1073 return keyItem;
1074}
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -07001075
1076string
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -07001077SecTpmOsx::Impl::toInternalKeyName(const Name& keyName, KeyClass keyClass)
Yingdi Yu2b2b4792014-02-04 16:27:07 -08001078{
1079 string keyUri = keyName.toUri();
1080
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -07001081 if (KEY_CLASS_SYMMETRIC == keyClass)
Yingdi Yu2b2b4792014-02-04 16:27:07 -08001082 return keyUri + "/symmetric";
1083 else
1084 return keyUri;
1085}
1086
Alexander Afanasyev24b75c82014-05-31 15:59:31 +03001087CFTypeRef
Yingdi Yu2b2b4792014-02-04 16:27:07 -08001088SecTpmOsx::Impl::getAsymKeyType(KeyType keyType)
1089{
Yingdi Yu7036ce22014-06-19 18:53:37 -07001090 switch (keyType) {
Yingdi Yu2b2b4792014-02-04 16:27:07 -08001091 case KEY_TYPE_RSA:
1092 return kSecAttrKeyTypeRSA;
Yingdi Yuc8f883c2014-06-20 23:25:22 -07001093 case KEY_TYPE_ECDSA:
1094 return kSecAttrKeyTypeECDSA;
Yingdi Yu2b2b4792014-02-04 16:27:07 -08001095 default:
Yingdi Yu4b8c6a22014-04-15 23:00:54 -07001096 return 0;
Yingdi Yu2b2b4792014-02-04 16:27:07 -08001097 }
1098}
1099
Alexander Afanasyev24b75c82014-05-31 15:59:31 +03001100CFTypeRef
Yingdi Yu2b2b4792014-02-04 16:27:07 -08001101SecTpmOsx::Impl::getSymKeyType(KeyType keyType)
1102{
Yingdi Yu7036ce22014-06-19 18:53:37 -07001103 switch (keyType) {
Yingdi Yu2b2b4792014-02-04 16:27:07 -08001104 case KEY_TYPE_AES:
1105 return kSecAttrKeyTypeAES;
1106 default:
Yingdi Yu4b8c6a22014-04-15 23:00:54 -07001107 return 0;
Yingdi Yu2b2b4792014-02-04 16:27:07 -08001108 }
1109}
1110
Alexander Afanasyev24b75c82014-05-31 15:59:31 +03001111CFTypeRef
Yingdi Yu2b2b4792014-02-04 16:27:07 -08001112SecTpmOsx::Impl::getKeyClass(KeyClass keyClass)
1113{
Yingdi Yu7036ce22014-06-19 18:53:37 -07001114 switch (keyClass) {
Yingdi Yu2b2b4792014-02-04 16:27:07 -08001115 case KEY_CLASS_PRIVATE:
1116 return kSecAttrKeyClassPrivate;
1117 case KEY_CLASS_PUBLIC:
1118 return kSecAttrKeyClassPublic;
1119 case KEY_CLASS_SYMMETRIC:
1120 return kSecAttrKeyClassSymmetric;
1121 default:
Yingdi Yu4b8c6a22014-04-15 23:00:54 -07001122 return 0;
Yingdi Yu2b2b4792014-02-04 16:27:07 -08001123 }
1124}
1125
Alexander Afanasyev24b75c82014-05-31 15:59:31 +03001126CFStringRef
Yingdi Yu2b2b4792014-02-04 16:27:07 -08001127SecTpmOsx::Impl::getDigestAlgorithm(DigestAlgorithm digestAlgo)
1128{
Yingdi Yu7036ce22014-06-19 18:53:37 -07001129 switch (digestAlgo) {
Yingdi Yu2b2b4792014-02-04 16:27:07 -08001130 case DIGEST_ALGORITHM_SHA256:
1131 return kSecDigestSHA2;
1132 default:
Yingdi Yu4b8c6a22014-04-15 23:00:54 -07001133 return 0;
Jeff Thompson2747dc02013-10-04 19:11:34 -07001134 }
Yingdi Yu2b2b4792014-02-04 16:27:07 -08001135}
Jeff Thompson2747dc02013-10-04 19:11:34 -07001136
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -07001137long
Yingdi Yu2b2b4792014-02-04 16:27:07 -08001138SecTpmOsx::Impl::getDigestSize(DigestAlgorithm digestAlgo)
1139{
Yingdi Yu7036ce22014-06-19 18:53:37 -07001140 switch (digestAlgo) {
Yingdi Yu2b2b4792014-02-04 16:27:07 -08001141 case DIGEST_ALGORITHM_SHA256:
1142 return 256;
Yingdi Yu2b2b4792014-02-04 16:27:07 -08001143 default:
Yingdi Yu2b2b4792014-02-04 16:27:07 -08001144 return -1;
Jeff Thompson2747dc02013-10-04 19:11:34 -07001145 }
Jeff Thompson2747dc02013-10-04 19:11:34 -07001146}
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -07001147
Yingdi Yufc40d872014-02-18 12:56:04 -08001148} // namespace ndn