2  * Copyright (c) 2000-2004,2011-2014 Apple Inc. All Rights Reserved. 
   4  * @APPLE_LICENSE_HEADER_START@ 
   6  * This file contains Original Code and/or Modifications of Original Code 
   7  * as defined in and that are subject to the Apple Public Source License 
   8  * Version 2.0 (the 'License'). You may not use this file except in 
   9  * compliance with the License. Please obtain a copy of the License at 
  10  * http://www.opensource.apple.com/apsl/ and read it before using this 
  13  * The Original Code and all software distributed under the License are 
  14  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  15  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  16  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 
  17  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  18  * Please see the License for the specific language governing rights and 
  19  * limitations under the License. 
  21  * @APPLE_LICENSE_HEADER_END@ 
  24 #include <Security/SecKeychain.h> 
  25 #include <Security/SecKeychainPriv.h> 
  26 #include <security_keychain/KCCursor.h> 
  27 #include <security_cdsa_utilities/cssmdata.h> 
  28 #include <security_cdsa_client/wrapkey.h> 
  29 #include <security_keychain/KCExceptions.h> 
  30 #include <securityd_client/ssblob.h> 
  31 #include <Security/SecAccess.h> 
  32 #include <Security/SecTrustedApplicationPriv.h> 
  33 #include "SecBridge.h" 
  34 #include "CCallbackMgr.h" 
  35 #include <security_cdsa_utilities/Schema.h> 
  36 #include <security_cdsa_client/mdsclient.h> 
  38 #include <Security/AuthorizationTagsPriv.h> 
  39 #include <Security/Authorization.h> 
  40 #include "TokenLogin.h" 
  43 SecKeychainMDSInstall() 
  47         Security::MDSClient::Directory d
; 
  54 SecKeychainGetTypeID(void) 
  58         return gTypes().KeychainImpl
.typeID
; 
  60         END_SECAPI1(_kCFRuntimeNotATypeID
) 
  65 SecKeychainGetVersion(UInt32 
*returnVers
) 
  70         *returnVers 
= 0x02028000; 
  76 SecKeychainOpen(const char *pathName
, SecKeychainRef 
*keychainRef
) 
  80         RequiredParam(keychainRef
)=globals().storageManager
.make(pathName
, false)->handle(); 
  87 SecKeychainOpenWithGuid(const CSSM_GUID 
*guid
, uint32 subserviceId
, uint32 subserviceType
, const char* dbName
, 
  88                                                 const CSSM_NET_ADDRESS 
*dbLocation
, SecKeychainRef 
*keychain
) 
  92         // range check parameters 
  94         RequiredParam (dbName
); 
  96         // create a DLDbIdentifier that describes what should be opened 
  97     const CSSM_VERSION 
*version 
= NULL
; 
  98     const CssmSubserviceUid 
ssuid(*guid
, version
, subserviceId
, subserviceType
); 
  99         DLDbIdentifier 
dLDbIdentifier(ssuid
, dbName
, dbLocation
); 
 101         // make a keychain from the supplied info 
 102         RequiredParam(keychain
) = globals().storageManager
.makeKeychain(dLDbIdentifier
, false, false)->handle (); 
 109 SecKeychainCreate(const char *pathName
, UInt32 passwordLength
, const void *password
, 
 110         Boolean promptUser
, SecAccessRef initialAccess
, SecKeychainRef 
*keychainRef
) 
 114     KCThrowParamErrIf_(!pathName
); 
 115         Keychain keychain 
= globals().storageManager
.make(pathName
, true, true); 
 117         // @@@ the call to StorageManager::make above leaves keychain the the cache. 
 118         // If the create below fails we should probably remove it. 
 123                 KCThrowParamErrIf_(!password
); 
 124                 keychain
->create(passwordLength
, password
); 
 127         RequiredParam(keychainRef
)=keychain
->handle(); 
 134 SecKeychainDelete(SecKeychainRef keychainOrArray
) 
 138         KCThrowIf_(!keychainOrArray
, errSecInvalidKeychain
); 
 139         StorageManager::KeychainList keychains
; 
 140         globals().storageManager
.optionalSearchList(keychainOrArray
, keychains
); 
 142         globals().storageManager
.remove(keychains
, true); 
 149 SecKeychainSetSettings(SecKeychainRef keychainRef
, const SecKeychainSettings 
*newSettings
) 
 153         Keychain keychain 
= Keychain::optional(keychainRef
); 
 154         if (newSettings
->version
==SEC_KEYCHAIN_SETTINGS_VERS1
) 
 156                 UInt32 lockInterval
=newSettings
->lockInterval
; 
 157                 bool lockOnSleep
=newSettings
->lockOnSleep
; 
 158                 keychain
->setSettings(lockInterval
, lockOnSleep
); 
 166 SecKeychainCopySettings(SecKeychainRef keychainRef
, SecKeychainSettings 
*outSettings
) 
 170         Keychain keychain 
= Keychain::optional(keychainRef
); 
 171         if (outSettings
->version
==SEC_KEYCHAIN_SETTINGS_VERS1
) 
 176                 keychain
->getSettings(lockInterval
, lockOnSleep
); 
 177                 outSettings
->lockInterval
=lockInterval
; 
 178                 outSettings
->lockOnSleep
=lockOnSleep
; 
 186 SecKeychainUnlock(SecKeychainRef keychainRef
, UInt32 passwordLength
, const void *password
, Boolean usePassword
) 
 190         Keychain keychain 
= Keychain::optional(keychainRef
); 
 193                 keychain
->unlock(CssmData(const_cast<void *>(password
), passwordLength
)); 
 202 SecKeychainLock(SecKeychainRef  keychainRef
) 
 206         Keychain keychain 
= Keychain::optional(keychainRef
); 
 214 SecKeychainLockAll(void) 
 218         globals().storageManager
.lockAll(); 
 224 OSStatus 
SecKeychainResetLogin(UInt32 passwordLength
, const void* password
, Boolean resetSearchList
) 
 228         // Get the current user (using fallback method if necessary) 
 230         char* uName 
= getenv("USER"); 
 231         string userName 
= uName 
? uName 
: ""; 
 232         if ( userName
.length() == 0 ) 
 234             uid_t uid 
= geteuid(); 
 235             if (!uid
) uid 
= getuid(); 
 236             struct passwd 
*pw 
= getpwuid(uid
);  // fallback case... 
 238                 userName 
= pw
->pw_name
; 
 241         if ( userName
.length() == 0 )   // did we ultimately get one? 
 242             MacOSError::throwMe(errAuthorizationInternal
); 
 244         SecurityServer::ClientSession().resetKeyStorePassphrase(password 
? CssmData(const_cast<void *>(password
), passwordLength
) : CssmData()); 
 248                         // Clear the plist and move aside (rename) the existing login.keychain 
 249                         globals().storageManager
.resetKeychain(resetSearchList
); 
 251                         // Create the login keychain without UI 
 252                         globals().storageManager
.login((UInt32
)userName
.length(), userName
.c_str(), passwordLength
, password
, true); 
 254                         // Set it as the default 
 255                         Keychain keychain 
= globals().storageManager
.loginKeychain(); 
 256                         globals().storageManager
.defaultKeychain(keychain
); 
 260                         // Create the login keychain, prompting for password 
 261                         // (implicitly calls resetKeychain, login, and defaultKeychain) 
 262                         globals().storageManager
.makeLoginAuthUI(NULL
, true); 
 265                 // Post a "list changed" event after a reset, so apps can refresh their list. 
 266                 // Make sure we are not holding mLock when we post this event. 
 267                 KCEventNotifier::PostKeychainEvent(kSecKeychainListChangedEvent
); 
 273 SecKeychainCopyDefault(SecKeychainRef 
*keychainRef
) 
 277         RequiredParam(keychainRef
)=globals().storageManager
.defaultKeychain()->handle(); 
 284 SecKeychainSetDefault(SecKeychainRef keychainRef
) 
 288         globals().storageManager
.defaultKeychain(Keychain::optional(keychainRef
)); 
 293 OSStatus 
SecKeychainCopySearchList(CFArrayRef 
*searchList
) 
 297         RequiredParam(searchList
); 
 298         StorageManager 
&smr 
= globals().storageManager
; 
 299         StorageManager::KeychainList keychainList
; 
 300         smr
.getSearchList(keychainList
); 
 301         *searchList 
= smr
.convertFromKeychainList(keychainList
); 
 306 OSStatus 
SecKeychainSetSearchList(CFArrayRef searchList
) 
 310         RequiredParam(searchList
); 
 311         StorageManager 
&smr 
= globals().storageManager
; 
 312         StorageManager::KeychainList keychainList
; 
 313         smr
.convertToKeychainList(searchList
, keychainList
); 
 314         smr
.setSearchList(keychainList
); 
 319 OSStatus 
SecKeychainCopyDomainDefault(SecPreferencesDomain domain
, SecKeychainRef 
*keychainRef
) 
 323         RequiredParam(keychainRef
)=globals().storageManager
.defaultKeychain(domain
)->handle(); 
 328 OSStatus 
SecKeychainSetDomainDefault(SecPreferencesDomain domain
, SecKeychainRef keychainRef
) 
 332         globals().storageManager
.defaultKeychain(domain
, Keychain::optional(keychainRef
)); 
 337 OSStatus 
SecKeychainCopyDomainSearchList(SecPreferencesDomain domain
, CFArrayRef 
*searchList
) 
 341         RequiredParam(searchList
); 
 342         StorageManager 
&smr 
= globals().storageManager
; 
 343         StorageManager::KeychainList keychainList
; 
 344         smr
.getSearchList(domain
, keychainList
); 
 345         *searchList 
= smr
.convertFromKeychainList(keychainList
); 
 350 OSStatus 
SecKeychainSetDomainSearchList(SecPreferencesDomain domain
, CFArrayRef searchList
) 
 354         RequiredParam(searchList
); 
 355         StorageManager 
&smr 
= globals().storageManager
; 
 356         StorageManager::KeychainList keychainList
; 
 357         smr
.convertToKeychainList(searchList
, keychainList
); 
 358         smr
.setSearchList(domain
, keychainList
); 
 363 OSStatus 
SecKeychainSetPreferenceDomain(SecPreferencesDomain domain
) 
 367         globals().storageManager
.domain(domain
); 
 372 OSStatus 
SecKeychainGetPreferenceDomain(SecPreferencesDomain 
*domain
) 
 376         *domain 
= globals().storageManager
.domain(); 
 383 SecKeychainGetStatus(SecKeychainRef keychainRef
, SecKeychainStatus 
*keychainStatus
) 
 387         RequiredParam(keychainStatus
) = (SecKeychainStatus
)Keychain::optional(keychainRef
)->status(); 
 394 SecKeychainGetPath(SecKeychainRef keychainRef
, UInt32 
*ioPathLength
, char *pathName
) 
 398         RequiredParam(pathName
); 
 399         RequiredParam(ioPathLength
); 
 401     const char *name 
= Keychain::optional(keychainRef
)->name(); 
 402         UInt32 nameLen 
= (UInt32
)strlen(name
); 
 403         UInt32 callersLen 
= *ioPathLength
; 
 404         *ioPathLength 
= nameLen
; 
 405         if (nameLen
+1 > callersLen
)  // if the client's buffer is too small (including null-termination), throw 
 406                 return errSecBufferTooSmall
; 
 407         strncpy(pathName
, name
, nameLen
); 
 408     pathName
[nameLen
] = 0; 
 409         *ioPathLength 
= nameLen
;   // set the length. 
 415 SecKeychainGetKeychainVersion(SecKeychainRef keychainRef
, UInt32
* version
) 
 419     RequiredParam(version
); 
 421     *version 
= Keychain::optional(keychainRef
)->database()->dbBlobVersion(); 
 427 SecKeychainAttemptMigrationWithMasterKey(SecKeychainRef keychain
, UInt32 version
, const char* masterKeyFilename
) 
 431     RequiredParam(masterKeyFilename
); 
 432     Keychain kc 
= Keychain::optional(keychain
); 
 434     SecurityServer::SystemKeychainKey 
keychainKey(masterKeyFilename
); 
 435     if(keychainKey
.valid()) { 
 436         // We've managed to read the key; now, create credentials using it 
 437         string path 
= kc
->name(); 
 439         CssmClient::Key 
keychainMasterKey(kc
->csp(), keychainKey
.key(), true); 
 440         CssmClient::AclFactory::MasterKeyUnlockCredentials 
creds(keychainMasterKey
, Allocator::standard(Allocator::sensitive
)); 
 442         // Attempt the migrate, using our master key as the ACL override 
 443         bool result 
= kc
->keychainMigration(path
, kc
->database()->dbBlobVersion(), path
, version
, creds
.getAccessCredentials()); 
 447         return (kc
->database()->dbBlobVersion() == version 
? errSecSuccess 
: errSecBadReq
); 
 458 SecKeychainListGetCount(void) 
 462         return globals().storageManager
.size(); 
 470 SecKeychainListCopyKeychainAtIndex(UInt16 index
, SecKeychainRef 
*keychainRef
) 
 474         KeychainCore::StorageManager 
&smgr
=KeychainCore::globals().storageManager
; 
 475         RequiredParam(keychainRef
)=smgr
[index
]->handle(); 
 483 SecKeychainListRemoveKeychain(SecKeychainRef 
*keychainRef
) 
 487         Required(keychainRef
); 
 488         Keychain keychain 
= Keychain::optional(*keychainRef
); 
 489         StorageManager::KeychainList keychainList
; 
 490         keychainList
.push_back(keychain
); 
 491         globals().storageManager
.remove(keychainList
); 
 499 SecKeychainAttributeInfoForItemID(SecKeychainRef keychainRef
, UInt32 itemID
, SecKeychainAttributeInfo 
**info
) 
 503         Keychain keychain 
= Keychain::optional(keychainRef
); 
 504         keychain
->getAttributeInfoForItemID(itemID
, info
); 
 511 SecKeychainFreeAttributeInfo(SecKeychainAttributeInfo 
*info
) 
 515         KeychainImpl::freeAttributeInfo(info
); 
 522 SecKeychainAddCallback(SecKeychainCallback callbackFunction
, SecKeychainEventMask eventMask
, void* userContext
) 
 526         RequiredParam(callbackFunction
); 
 527         CCallbackMgr::AddCallback(callbackFunction
,eventMask
,userContext
); 
 534 SecKeychainRemoveCallback(SecKeychainCallback callbackFunction
) 
 538         RequiredParam(callbackFunction
); 
 539         CCallbackMgr::RemoveCallback(callbackFunction
); 
 545 SecKeychainAddInternetPassword(SecKeychainRef keychainRef
, UInt32 serverNameLength
, const char *serverName
, UInt32 securityDomainLength
, const char *securityDomain
, UInt32 accountNameLength
, const char *accountName
, UInt32 pathLength
, const char *path
, UInt16 port
, SecProtocolType protocol
, SecAuthenticationType authenticationType
, UInt32 passwordLength
, const void *passwordData
, SecKeychainItemRef 
*itemRef
) 
 549         KCThrowParamErrIf_(passwordLength
!=0 && passwordData
==NULL
); 
 550         // @@@ Get real itemClass 
 551         Item 
item(kSecInternetPasswordItemClass
, 'aapl', passwordLength
, passwordData
, false); 
 553         if (serverName 
&& serverNameLength
) 
 555                 CssmData 
server(const_cast<void *>(reinterpret_cast<const void *>(serverName
)), serverNameLength
); 
 556                 item
->setAttribute(Schema::attributeInfo(kSecServerItemAttr
), server
); 
 557                 // use server name as default label 
 558                 item
->setAttribute(Schema::attributeInfo(kSecLabelItemAttr
), server
); 
 561         if (accountName 
&& accountNameLength
) 
 563                 CssmData 
account(const_cast<void *>(reinterpret_cast<const void *>(accountName
)), accountNameLength
); 
 564                 item
->setAttribute(Schema::attributeInfo(kSecAccountItemAttr
), account
); 
 567         if (securityDomain 
&& securityDomainLength
) 
 568                 item
->setAttribute(Schema::attributeInfo(kSecSecurityDomainItemAttr
), 
 569                         CssmData(const_cast<void *>(reinterpret_cast<const void *>(securityDomain
)), securityDomainLength
)); 
 571         item
->setAttribute(Schema::attributeInfo(kSecPortItemAttr
), UInt32(port
)); 
 572         item
->setAttribute(Schema::attributeInfo(kSecProtocolItemAttr
), protocol
); 
 573         item
->setAttribute(Schema::attributeInfo(kSecAuthenticationTypeItemAttr
), authenticationType
); 
 575         if (path 
&& pathLength
) 
 576                 item
->setAttribute(Schema::attributeInfo(kSecPathItemAttr
), 
 577                         CssmData(const_cast<void *>(reinterpret_cast<const void *>(path
)), pathLength
)); 
 579         Keychain keychain 
= nil
; 
 582         keychain 
= Keychain::optional(keychainRef
); 
 583         if ( !keychain
->exists() ) 
 585             MacOSError::throwMe(errSecNoSuchKeychain
);  // Might be deleted or not available at this time. 
 590         keychain 
= globals().storageManager
.defaultKeychainUI(item
); 
 596                 *itemRef 
= item
->handle(); 
 603 SecKeychainFindInternetPassword(CFTypeRef keychainOrArray
, UInt32 serverNameLength
, const char *serverName
, UInt32 securityDomainLength
, const char *securityDomain
, UInt32 accountNameLength
, const char *accountName
, UInt32 pathLength
, const char *path
, UInt16 port
, SecProtocolType protocol
, SecAuthenticationType authenticationType
, UInt32 
*passwordLength
, void **passwordData
, SecKeychainItemRef 
*itemRef
) 
 608         StorageManager::KeychainList keychains
; 
 609         globals().storageManager
.optionalSearchList(keychainOrArray
, keychains
); 
 610         KCCursor 
cursor(keychains
, kSecInternetPasswordItemClass
, NULL
); 
 612         if (serverName 
&& serverNameLength
) 
 614                 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecServerItemAttr
), 
 615                         CssmData(const_cast<char *>(serverName
), serverNameLength
)); 
 618         if (securityDomain 
&& securityDomainLength
) 
 620                 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecSecurityDomainItemAttr
), 
 621                         CssmData (const_cast<char*>(securityDomain
), securityDomainLength
)); 
 624         if (accountName 
&& accountNameLength
) 
 626                 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecAccountItemAttr
), 
 627                         CssmData (const_cast<char*>(accountName
), accountNameLength
)); 
 632                 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecPortItemAttr
), 
 638                 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecProtocolItemAttr
), 
 642         if (authenticationType
) 
 644                 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecAuthenticationTypeItemAttr
), 
 648         if (path  
&& pathLength
) 
 650                 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecPathItemAttr
), path
); 
 654         if (!cursor
->next(item
)) 
 655                 return errSecItemNotFound
; 
 657         // Get its data (only if necessary) 
 658         if (passwordData 
|| passwordLength
) 
 660                 CssmDataContainer outData
; 
 661                 item
->getData(outData
); 
 662                 if (passwordLength
) { 
 663                         *passwordLength
=(UInt32
)outData
.length(); 
 667                         *passwordData
=outData
.data(); 
 673                 *itemRef
=item
->handle(); 
 680 SecKeychainAddGenericPassword(SecKeychainRef keychainRef
, UInt32 serviceNameLength
, const char *serviceName
, UInt32 accountNameLength
, const char *accountName
, UInt32 passwordLength
, const void *passwordData
, SecKeychainItemRef 
*itemRef
) 
 684         KCThrowParamErrIf_(passwordLength
!=0 && passwordData
==NULL
); 
 685         // @@@ Get real itemClass 
 687         Item 
item(kSecGenericPasswordItemClass
, 'aapl', passwordLength
, passwordData
, false); 
 689         if (serviceName 
&& serviceNameLength
) 
 691                 CssmData 
service(const_cast<void *>(reinterpret_cast<const void *>(serviceName
)), serviceNameLength
); 
 692                 item
->setAttribute(Schema::attributeInfo(kSecServiceItemAttr
), service
); 
 693                 // use service name as default label (UNLESS the service is iTools and we have an account name [3787371]) 
 694                 const char *iTools 
= "iTools"; 
 695                 if (accountNameLength 
&& serviceNameLength
==strlen(iTools
) && !memcmp(serviceName
, iTools
, serviceNameLength
)) 
 697                         CssmData 
account(const_cast<void *>(reinterpret_cast<const void *>(accountName
)), accountNameLength
); 
 698                         item
->setAttribute(Schema::attributeInfo(kSecLabelItemAttr
), account
); 
 702                         item
->setAttribute(Schema::attributeInfo(kSecLabelItemAttr
), service
); 
 706         if (accountName 
&& accountNameLength
) 
 708                 CssmData 
account(const_cast<void *>(reinterpret_cast<const void *>(accountName
)), accountNameLength
); 
 709                 item
->setAttribute(Schema::attributeInfo(kSecAccountItemAttr
), account
); 
 712         Keychain keychain 
= nil
; 
 715         keychain 
= Keychain::optional(keychainRef
); 
 716         if ( !keychain
->exists() ) 
 718             MacOSError::throwMe(errSecNoSuchKeychain
);  // Might be deleted or not available at this time. 
 723         keychain 
= globals().storageManager
.defaultKeychainUI(item
); 
 728                 *itemRef 
= item
->handle(); 
 735 SecKeychainFindGenericPassword(CFTypeRef keychainOrArray
, UInt32 serviceNameLength
, const char *serviceName
, UInt32 accountNameLength
, const char *accountName
, UInt32 
*passwordLength
, void **passwordData
, SecKeychainItemRef 
*itemRef
) 
 740         StorageManager::KeychainList keychains
; 
 741         globals().storageManager
.optionalSearchList(keychainOrArray
, keychains
); 
 742         KCCursor 
cursor(keychains
, kSecGenericPasswordItemClass
, NULL
); 
 744         if (serviceName 
&& serviceNameLength
) 
 746                 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecServiceItemAttr
), 
 747                         CssmData(const_cast<char *>(serviceName
), serviceNameLength
)); 
 750         if (accountName 
&& accountNameLength
) 
 752                 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecAccountItemAttr
), 
 753                         CssmData(const_cast<char *>(accountName
), accountNameLength
)); 
 757         if (!cursor
->next(item
)) 
 758                 return errSecItemNotFound
; 
 760         // Get its data (only if necessary) 
 761         if (passwordData 
|| passwordLength
) 
 763                 CssmDataContainer outData
; 
 764                 item
->getData(outData
); 
 765                 if (passwordLength
) { 
 766                         *passwordLength
=(UInt32
)outData
.length(); 
 770                         *passwordData
=outData
.data(); 
 776                 *itemRef
=item
->handle(); 
 783 SecKeychainSetUserInteractionAllowed(Boolean state
)  
 787         globals().setUserInteractionAllowed(state
); 
 794 SecKeychainGetUserInteractionAllowed(Boolean 
*state
)  
 798         Required(state
)=globals().getUserInteractionAllowed(); 
 805 SecKeychainGetDLDBHandle(SecKeychainRef keychainRef
, CSSM_DL_DB_HANDLE 
*dldbHandle
) 
 809         RequiredParam(dldbHandle
); 
 811         Keychain keychain 
= Keychain::optional(keychainRef
); 
 812         *dldbHandle 
= keychain
->database()->handle(); 
 819 SecKeychainGetCSPHandle(SecKeychainRef keychainRef
, CSSM_CSP_HANDLE 
*cspHandle
) 
 823         RequiredParam(cspHandle
); 
 825         Keychain keychain 
= Keychain::optional(keychainRef
); 
 826         *cspHandle 
= keychain
->csp()->handle(); 
 833 SecKeychainCopyAccess(SecKeychainRef keychainRef
, SecAccessRef 
*accessRef
) 
 837         MacOSError::throwMe(errSecUnimplemented
);//%%%for now 
 844 SecKeychainSetAccess(SecKeychainRef keychainRef
, SecAccessRef accessRef
) 
 848         MacOSError::throwMe(errSecUnimplemented
);//%%%for now 
 854 #pragma mark ---- Private API ---- 
 858 SecKeychainChangePassword(SecKeychainRef keychainRef
, UInt32 oldPasswordLength
, const void *oldPassword
,  UInt32 newPasswordLength
, const void *newPassword
) 
 862         Keychain keychain 
= Keychain::optional(keychainRef
); 
 863         keychain
->changePassphrase (oldPasswordLength
, oldPassword
,  newPasswordLength
, newPassword
); 
 870 SecKeychainCopyLogin(SecKeychainRef 
*keychainRef
) 
 874         RequiredParam(keychainRef
)=globals().storageManager
.loginKeychain()->handle(); 
 881 SecKeychainLogin(UInt32 nameLength
, const void* name
, UInt32 passwordLength
, const void* password
) 
 888             globals().storageManager
.login(nameLength
, name
,  passwordLength
, password
, false); 
 890             globals().storageManager
.stashLogin(); 
 893         catch (CommonError 
&e
) 
 895         secnotice("KCLogin", "SecKeychainLogin failed: %d, password was%s supplied", (int)e
.osStatus(), password
?"":" not"); 
 896                 if (e
.osStatus() == CSSMERR_DL_OPERATION_AUTH_DENIED
) 
 898                         return errSecAuthFailed
; 
 907         __secapiresult
=errSecInternalComponent
; 
 909     secnotice("KCLogin", "SecKeychainLogin result: %d, password was%s supplied", (int)__secapiresult
, password
?"":" not"); 
 914 OSStatus 
SecKeychainStash() 
 920                 globals().storageManager
.stashKeychain(); 
 922         catch (CommonError 
&e
) 
 924                 if (e
.osStatus() == CSSMERR_DL_OPERATION_AUTH_DENIED
) 
 926                         return errSecAuthFailed
; 
 942         globals().storageManager
.logout(); 
 947 /* (non-exported C utility routine) 'Makes' a keychain based on a full path 
 949 static Keychain 
make(const char *name
) 
 951         return globals().storageManager
.make(name
); 
 954 /*  'Makes' a keychain based on a full path for legacy "KC" CoreServices APIs. 
 955     Note this version doesn't take an accessRef or password. 
 956     The "KC" create API takes a keychainRef... 
 958 OSStatus 
SecKeychainMakeFromFullPath(const char *fullPathName
, SecKeychainRef 
*keychainRef
) 
 961         RequiredParam(fullPathName
); 
 962         RequiredParam(keychainRef
)=make(fullPathName
)->handle(); 
 967 /* Determines if the keychainRef is a valid keychain. 
 969 OSStatus 
SecKeychainIsValid(SecKeychainRef keychainRef
, Boolean
* isValid
) 
 973         if (KeychainImpl::optional(keychainRef
)->dlDbIdentifier().ssuid().guid() == gGuidAppleCSPDL
) 
 978 /* Removes a keychain from the keychain search list for legacy "KC" CoreServices APIs. 
 980 OSStatus 
SecKeychainRemoveFromSearchList(SecKeychainRef keychainRef
) 
 983         StorageManager::KeychainList singleton
; 
 984         singleton
.push_back(KeychainImpl::required(keychainRef
)); 
 985         globals().storageManager
.remove(singleton
); 
 989 /* Create a keychain based on a keychain Ref for legacy "KC" CoreServices APIs. 
 991 OSStatus 
SecKeychainCreateNew(SecKeychainRef keychainRef
, UInt32 passwordLength
, const char* inPassword
) 
 994         RequiredParam(inPassword
); 
 995         KeychainImpl::required(keychainRef
)->create(passwordLength
, inPassword
); 
 999 /* Modify a keychain so that it can be synchronized. 
1001 OSStatus 
SecKeychainRecodeKeychain(SecKeychainRef keychainRef
, CFArrayRef dbBlobArray
, CFDataRef extraData
) 
1005         // do error checking for required parameters 
1006         RequiredParam(dbBlobArray
); 
1007         RequiredParam(extraData
); 
1009         const CssmData 
extraCssmData(const_cast<UInt8 
*>(CFDataGetBytePtr(extraData
)), 
1010                 CFDataGetLength(extraData
)); 
1012         CFIndex dbBlobArrayCount 
= CFArrayGetCount(dbBlobArray
); 
1013         size_t space 
= sizeof(uint8
) + (dbBlobArrayCount 
* sizeof(SecurityServer::DbHandle
)); 
1014         void *dataPtr 
= (void*)malloc(space
); 
1016                 return errSecAllocate
; 
1018         // Get a DbHandle(IPCDbHandle) from securityd for each blob in the array that we'll authenticate with. 
1020         uint8
* sizePtr 
= (uint8
*)dataPtr
; 
1021         *sizePtr 
= dbBlobArrayCount
; 
1022         SecurityServer::DbHandle 
*currDbHandle 
= (SecurityServer::DbHandle 
*)(sizePtr
+1); 
1024         SecurityServer::ClientSession 
ss(Allocator::standard(), Allocator::standard()); 
1025         for (index
=0; index 
< dbBlobArrayCount
; index
++) 
1027                 CFDataRef cfBlobData 
= (CFDataRef
)CFArrayGetValueAtIndex(dbBlobArray
, index
); 
1028                 const CssmData 
thisKCData(const_cast<UInt8 
*>(CFDataGetBytePtr(cfBlobData
)), CFDataGetLength(cfBlobData
)); 
1030                 // Since it's to a DbHandle that's not on our disk (it came from user's iDisk), 
1031                 // it's OK to use the mIdentifier and access credentials of the keychain we're recoding. 
1033                 Keychain kc 
= KeychainImpl::required(keychainRef
); 
1034                 *currDbHandle 
= ss
.decodeDb(kc
->dlDbIdentifier(), kc
->defaultCredentials(), thisKCData
); /* returns a DbHandle (IPCDbHandle) */ 
1039         Keychain keychain 
= Keychain::optional(keychainRef
); 
1040         const CssmData 
data(const_cast<UInt8 
*>((uint8
*)dataPtr
), space
); 
1041         Boolean recodeFailed 
= false; 
1043         int errCode
=errSecSuccess
; 
1047                 keychain
->recode(data
, extraCssmData
); 
1049         catch (MacOSError e
) 
1051                 errCode 
= e
.osStatus(); 
1052                 recodeFailed 
= true; 
1054         catch (UnixError ue
) 
1056                 errCode 
= ue
.unixError(); 
1059         currDbHandle 
= (SecurityServer::DbHandle 
*)(sizePtr
+1); 
1060         for (index
=0; index 
< dbBlobArrayCount
; index
++) 
1062                 ss
.releaseDb(*currDbHandle
); 
1076 OSStatus 
SecKeychainCopySignature(SecKeychainRef keychainRef
, CFDataRef 
*keychainSignature
)  
1080         // do error checking for required parameters 
1081         RequiredParam(keychainSignature
); 
1083         // make a keychain object "wrapper" for this keychain ref 
1084         Keychain keychain 
= Keychain::optional(keychainRef
); 
1085         CssmAutoData 
data(keychain
->database()->allocator()); 
1086         keychain
->copyBlob(data
.get()); 
1088         // get the cssmDBBlob 
1089         const SecurityServer::DbBlob 
*cssmDBBlob 
= 
1090                 data
.get().interpretedAs
<const SecurityServer::DbBlob
>(); 
1092         // convert from CDSA standards to CF standards 
1093         *keychainSignature 
= CFDataCreate(kCFAllocatorDefault
, 
1094                 cssmDBBlob
->randomSignature
.bytes
, 
1095                 sizeof(SecurityServer::DbBlob::Signature
)); 
1100 OSStatus 
SecKeychainCopyBlob(SecKeychainRef keychainRef
, CFDataRef 
*dbBlob
) 
1104         // do error checking for required parameters 
1105         RequiredParam(dbBlob
); 
1107         // make a keychain object "wrapper" for this keychain ref 
1108         Keychain keychain 
= Keychain::optional(keychainRef
); 
1109         CssmAutoData 
data(keychain
->database()->allocator()); 
1110         keychain
->copyBlob(data
.get()); 
1112         // convert from CDSA standards to CF standards 
1113         *dbBlob 
= CFDataCreate(kCFAllocatorDefault
, data
, data
.length()); 
1118 // make a new keychain with pre-existing secrets 
1119 OSStatus 
SecKeychainCreateWithBlob(const char* fullPathName
, CFDataRef dbBlob
, SecKeychainRef 
*kcRef
) 
1123         KCThrowParamErrIf_(!fullPathName
); 
1124         KCThrowParamErrIf_(!dbBlob
); 
1126         Keychain keychain 
= globals().storageManager
.make(fullPathName
); 
1128         CssmData 
blob(const_cast<unsigned char *>(CFDataGetBytePtr(dbBlob
)), CFDataGetLength(dbBlob
)); 
1130         // @@@ the call to StorageManager::make above leaves keychain the the cache. 
1131         // If the create below fails we should probably remove it. 
1132         keychain
->createWithBlob(blob
); 
1134         RequiredParam(kcRef
)=keychain
->handle(); 
1141 // add a non-file based DB to the keychain list 
1142 OSStatus 
SecKeychainAddDBToKeychainList (SecPreferencesDomain domain
, const char* dbName
, 
1143                                                                                  const CSSM_GUID 
*guid
, uint32 subServiceType
) 
1147         RequiredParam(dbName
); 
1148         StorageManager 
&smr 
= globals().storageManager
; 
1149         smr
.addToDomainList(domain
, dbName
, *guid
, subServiceType
); 
1154 // determine if a non-file based DB is in the keychain list 
1155 OSStatus 
SecKeychainDBIsInKeychainList (SecPreferencesDomain domain
, const char* dbName
, 
1156                                                                                 const CSSM_GUID 
*guid
, uint32 subServiceType
) 
1159         RequiredParam(dbName
); 
1160         StorageManager 
&smr 
= globals().storageManager
; 
1161         smr
.isInDomainList(domain
, dbName
, *guid
, subServiceType
); 
1165 // remove a non-file based DB from the keychain list 
1166 OSStatus 
SecKeychainRemoveDBFromKeychainList (SecPreferencesDomain domain
, const char* dbName
, 
1167                                                                                           const CSSM_GUID 
*guid
, uint32 subServiceType
) 
1170         RequiredParam(dbName
); 
1171         StorageManager 
&smr 
= globals().storageManager
; 
1172         smr
.removeFromDomainList(domain
, dbName
, *guid
, subServiceType
); 
1177 // set server mode -- must be called before any other Sec* etc. call 
1178 void SecKeychainSetServerMode() 
1185 OSStatus 
SecKeychainSetBatchMode (SecKeychainRef kcRef
, Boolean mode
, Boolean rollback
) 
1188         RequiredParam(kcRef
); 
1189         Keychain keychain 
= Keychain::optional(kcRef
); 
1190         keychain
->setBatchMode(mode
, rollback
); 
1196 OSStatus 
SecKeychainCleanupHandles() 
1199         END_SECAPI 
// which causes the handle cache cleanup routine to run 
1202 OSStatus 
SecKeychainVerifyKeyStorePassphrase(uint32_t retries
) 
1205     SecurityServer::ClientSession().verifyKeyStorePassphrase(retries
); 
1209 OSStatus 
SecKeychainChangeKeyStorePassphrase() 
1212     SecurityServer::ClientSession().changeKeyStorePassphrase(); 
1216 static OSStatus 
SecKeychainGetMasterKey(SecKeychainRef userKeychainRef
, CFDataRef 
*masterKey
, CFStringRef password
) 
1220     // make a keychain object "wrapper" for this keychain ref 
1221         Keychain keychain 
= Keychain::optional(userKeychainRef
); 
1223     CssmClient::Db db 
= keychain
->database(); 
1225         // create the keychain, using appropriate credentials 
1226         Allocator 
&alloc 
= db
->allocator(); 
1227         AutoCredentials 
cred(alloc
);    // will leak, but we're quitting soon :-) 
1229     char passphrase
[1024]; 
1230     CFStringGetCString(password
, passphrase
, sizeof(passphrase
), kCFStringEncodingUTF8
); 
1232     // use this passphrase 
1233     cred 
+= TypedList(alloc
, CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK
, 
1234                       new(alloc
) ListElement(CSSM_SAMPLE_TYPE_PASSWORD
), 
1235                       new(alloc
) ListElement(StringData(passphrase
))); 
1236         db
->authenticate(CSSM_DB_ACCESS_READ
, &cred
); 
1238         CSSM_DL_DB_HANDLE dlDb 
= db
->handle(); 
1239         CssmData dlDbData 
= CssmData::wrap(dlDb
); 
1241         KeySpec 
spec(CSSM_KEYUSE_ANY
, 
1242                  CSSM_KEYATTR_RETURN_REF 
| CSSM_KEYATTR_EXTRACTABLE
); 
1244     DeriveKey 
derive(keychain
->csp(), CSSM_ALGID_KEYCHAIN_KEY
, CSSM_ALGID_3DES_3KEY
, 3 * 64); 
1245         derive(&dlDbData
, spec
, refKey
); 
1247         // now extract the raw keybits 
1249         WrapKey 
wrap(keychain
->csp(), CSSM_ALGID_NONE
); 
1250         wrap(refKey
, rawKey
); 
1252     *masterKey 
= CFDataCreate(kCFAllocatorDefault
, rawKey
.keyData(), rawKey
.length()); 
1257 static const char     *kAutologinPWFilePath 
= "/etc/kcpassword"; 
1258 static const uint32_t kObfuscatedPasswordSizeMultiple 
= 12; 
1259 static const uint32_t buffer_size 
= 512; 
1260 static const uint8_t  kObfuscationKey
[] = {0x7d, 0x89, 0x52, 0x23, 0xd2, 0xbc, 0xdd, 0xea, 0xa3, 0xb9, 0x1f}; 
1262 static void obfuscate(void *buffer
, size_t bufferLength
) 
1264         uint8_t       *pBuf 
= (uint8_t *) buffer
; 
1265         const uint8_t *pKey 
= kObfuscationKey
, *eKey 
= pKey 
+ sizeof( kObfuscationKey 
); 
1267         while (bufferLength
--) { 
1268                 *pBuf 
= *pBuf 
^ *pKey
; 
1272                         pKey 
= kObfuscationKey
; 
1276 static bool _SASetAutologinPW(CFStringRef inAutologinPW
) 
1278         bool    result 
= false; 
1281         // Delete the kcpassword file if it exists already 
1282         if (stat(kAutologinPWFilePath
, &sb
) == 0) 
1283                 unlink( kAutologinPWFilePath 
); 
1285     // NIL incoming password ==> clear auto login password (above) without setting a new one. In other words: turn auto login off. 
1286     if (inAutologinPW 
!= NULL
) { 
1287                 char buffer
[buffer_size
]; 
1288                 const char *pwAsUTF8String 
= CFStringGetCStringPtr(inAutologinPW
, kCFStringEncodingUTF8
); 
1289                 if (pwAsUTF8String 
== NULL
) { 
1290                         if (CFStringGetCString(inAutologinPW
, buffer
, buffer_size
, kCFStringEncodingUTF8
)) pwAsUTF8String 
= buffer
; 
1293                 if (pwAsUTF8String 
!= NULL
) { 
1294                         size_t pwLength 
= strlen(pwAsUTF8String
) + 1; 
1295                         size_t obfuscatedPWLength
; 
1296                         char *obfuscatedPWBuffer
; 
1298                         // The size of the obfuscated password should be the smallest multiple of 
1299                         // kObfuscatedPasswordSizeMultiple greater than or equal to pwLength. 
1300                         obfuscatedPWLength 
= (((pwLength 
- 1) / kObfuscatedPasswordSizeMultiple
) + 1) * kObfuscatedPasswordSizeMultiple
; 
1301                         obfuscatedPWBuffer 
= (char *) malloc(obfuscatedPWLength
); 
1303                         // Copy the password (including null terminator) to beginning of obfuscatedPWBuffer 
1304                         bcopy(pwAsUTF8String
, obfuscatedPWBuffer
, pwLength
); 
1306                         // Pad remainder of obfuscatedPWBuffer with random bytes 
1309                                 char *endOfBuffer 
= obfuscatedPWBuffer 
+ obfuscatedPWLength
; 
1311                                 for (p 
= obfuscatedPWBuffer 
+ pwLength
; p 
< endOfBuffer
; ++p
) 
1312                                         *p 
= random() & 0x000000FF; 
1315                         obfuscate(obfuscatedPWBuffer
, obfuscatedPWLength
); 
1317                         int pwFile 
= open(kAutologinPWFilePath
, O_CREAT 
| O_WRONLY 
| O_NOFOLLOW
, S_IRUSR 
| S_IWUSR
); 
1319                                 size_t wrote 
= write(pwFile
, obfuscatedPWBuffer
, obfuscatedPWLength
); 
1320                                 if (wrote 
== obfuscatedPWLength
) 
1325                         chmod(kAutologinPWFilePath
, S_IRUSR 
| S_IWUSR
); 
1326                         free(obfuscatedPWBuffer
); 
1333 OSStatus 
SecKeychainStoreUnlockKey(SecKeychainRef userKeychainRef
, SecKeychainRef systemKeychainRef
, CFStringRef username
, CFStringRef password
) { 
1334     SecTrustedApplicationRef itemPath
; 
1335     SecAccessRef ourAccessRef 
= NULL
; 
1337     OSStatus result 
= errSecParam
; 
1339         if (userKeychainRef 
== NULL
) { 
1340                 // We don't have a specific user keychain, fall back 
1341                 if (_SASetAutologinPW(password
)) 
1342                         result 
= errSecSuccess
; 
1347     CFDataRef masterKey 
= NULL
; 
1348     result 
= SecKeychainGetMasterKey(userKeychainRef
, &masterKey
, password
); 
1349     if (errSecSuccess 
!= result
) { 
1353     result 
= SecKeychainStash(); 
1354     if (errSecSuccess 
!= result
) { 
1355         if (masterKey 
!= NULL
) CFRelease(masterKey
); 
1359     CFMutableArrayRef trustedApplications 
= CFArrayCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeArrayCallBacks
); 
1360     if (noErr 
== SecTrustedApplicationCreateApplicationGroup("com.apple.security.auto-login", NULL
, &itemPath
) && itemPath
) 
1361         CFArrayAppendValue(trustedApplications
, itemPath
); 
1363     if (trustedApplications 
&& (CFArrayGetCount(trustedApplications
) > 0)) { 
1364         if (errSecSuccess 
== (result 
= SecAccessCreate(CFSTR("Auto-Login applications"), trustedApplications
, &ourAccessRef
))) { 
1365                         SecKeychainRef internalSystemKeychainRef 
= NULL
; 
1366             if (NULL 
== systemKeychainRef
) { 
1367                                 SecKeychainCopyDomainDefault(kSecPreferencesDomainSystem
, &internalSystemKeychainRef
); 
1369                 internalSystemKeychainRef 
= systemKeychainRef
; 
1372             const void *queryKeys
[] =   { kSecClass
, 
1377             const void *queryValues
[] = { kSecClassGenericPassword
, 
1378                 CFSTR("com.apple.loginwindow.auto-login"), 
1380                                 internalSystemKeychainRef
, 
1383             const void *updateKeys
[] =   { kSecAttrAccess
, 
1386             const void *updateValues
[] = { ourAccessRef
, 
1390             CFDictionaryRef query 
= CFDictionaryCreate(kCFAllocatorDefault
, queryKeys
, queryValues
, sizeof(queryValues
)/sizeof(*queryValues
), &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
); 
1391             CFDictionaryRef update 
= CFDictionaryCreate(kCFAllocatorDefault
, updateKeys
, updateValues
, sizeof(updateValues
)/sizeof(*updateValues
), &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
); 
1393             result 
= SecItemUpdate(query
, update
); 
1395             if (errSecSuccess 
!= result
) { 
1396                 const void *addKeys
[] =   { kSecClass
, 
1403                 const void *addValues
[] = { kSecClassGenericPassword
, 
1404                     CFSTR("com.apple.loginwindow.auto-login"), 
1406                                         internalSystemKeychainRef
, 
1411                 CFDictionaryRef add 
= CFDictionaryCreate(kCFAllocatorDefault
, addKeys
, addValues
, sizeof(addValues
)/sizeof(*addValues
), &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
); 
1412                 result 
= SecItemAdd(add
, NULL
); 
1413                 if (NULL 
!= add
) CFRelease(add
); 
1416             if (NULL 
!= query
) CFRelease(query
); 
1417             if (NULL 
!= update
) CFRelease(update
); 
1419                         // If the caller wanted us to locate the system keychain reference, it's okay to go ahead and free our magically created one 
1420                         if (systemKeychainRef 
== NULL
) CFRelease(internalSystemKeychainRef
); 
1424     if (NULL 
!= masterKey
) CFRelease(masterKey
); 
1425     if (NULL 
!= trustedApplications
) CFRelease(trustedApplications
); 
1426     if (NULL 
!= ourAccessRef
) CFRelease(ourAccessRef
); 
1431 OSStatus 
SecKeychainGetUserPromptAttempts(uint32_t * attempts
) 
1436         SecurityServer::ClientSession().getUserPromptAttempts(*attempts
); 
1442 OSStatus 
SecKeychainStoreUnlockKeyWithPubKeyHash(CFDataRef pubKeyHash
, CFStringRef tokenID
, CFDataRef wrapPubKeyHash
, 
1443                                                  SecKeychainRef userKeychain
, CFStringRef password
) 
1445         CFRef
<CFStringRef
> pwd
; 
1448         if (password 
== NULL 
|| CFStringGetLength(password
) == 0) { 
1449                 AuthorizationRef authorizationRef
; 
1450                 result 
= AuthorizationCreate(NULL
, NULL
, kAuthorizationFlagDefaults
, &authorizationRef
); 
1451                 if (result 
!= errAuthorizationSuccess
) { 
1452                         secnotice("SecKeychain", "failed to create authorization"); 
1456                 AuthorizationItem myItems 
= {"com.apple.ctk.pair", 0, NULL
, 0}; 
1457                 AuthorizationRights myRights 
= {1, &myItems
}; 
1458                 AuthorizationRights 
*authorizedRights 
= NULL
; 
1460                 char pathName
[PATH_MAX
]; 
1461                 UInt32 pathLength 
= PATH_MAX
; 
1462                 result 
= SecKeychainGetPath(userKeychain
, &pathLength
, pathName
); 
1463                 if (result 
!= errSecSuccess
) { 
1464                         secnotice("SecKeychain", "failed to create authorization"); 
1468                 Boolean checkPwd 
= TRUE
; 
1469                 Boolean ignoreSession 
= TRUE
; 
1470                 AuthorizationItem envItems
[] = { 
1471                         {AGENT_HINT_KEYCHAIN_PATH
, pathLength
, pathName
, 0}, 
1472                         {AGENT_HINT_KEYCHAIN_CHECK
, sizeof(checkPwd
), &checkPwd
}, 
1473                         {AGENT_HINT_IGNORE_SESSION
, sizeof(ignoreSession
), &ignoreSession
} 
1476                 AuthorizationEnvironment environment  
= {3, envItems
}; 
1477                 AuthorizationFlags flags 
= kAuthorizationFlagDefaults 
| kAuthorizationFlagInteractionAllowed 
| kAuthorizationFlagExtendRights
; 
1478                 result 
= AuthorizationCopyRights(authorizationRef
, &myRights
, &environment
, flags
, &authorizedRights
); 
1479                 if (authorizedRights
) 
1480                         AuthorizationFreeItemSet(authorizedRights
); 
1482                 if (result 
== errAuthorizationSuccess
) { 
1483                         AuthorizationItemSet 
*items
; 
1484                         result 
= AuthorizationCopyInfo(authorizationRef
, kAuthorizationEnvironmentPassword
, &items
); 
1485                         if (result 
== errAuthorizationSuccess
) { 
1486                                 if (items
->count 
> 0) { 
1487                                         pwd 
= CFStringCreateWithCString(kCFAllocatorDefault
, (const char *)items
->items
[0].value
, kCFStringEncodingUTF8
); 
1489                                 AuthorizationFreeItemSet(items
); 
1492                 AuthorizationFree(authorizationRef
, kAuthorizationFlagDefaults
); 
1493                 if (result 
!= errAuthorizationSuccess
) { 
1494                         secnotice("SecKeychain", "did not get authorization to pair the card"); 
1502                 secnotice("SecKeychain", "did not get kcpass"); 
1503                 return errSecInternalComponent
; 
1506         CFRef
<CFDataRef
> masterKey
; 
1507         result 
= SecKeychainGetMasterKey(userKeychain
, masterKey
.take(), pwd
); 
1508         if (result 
!= errSecSuccess
) { 
1509                 secnotice("SecKeychain", "Failed to get master key: %d", (int) result
); 
1513         CFRef
<CFDataRef
> scBlob
; 
1514         result 
= TokenLoginGetScBlob(wrapPubKeyHash
, tokenID
, pwd
, scBlob
.take()); 
1515         if (result 
!= errSecSuccess
) { 
1516                 secnotice("SecKeychain", "Failed to get stash: %d", (int) result
); 
1520         result 
= TokenLoginCreateLoginData(tokenID
, pubKeyHash
, wrapPubKeyHash
, masterKey
, scBlob
); 
1521         if (result 
!= errSecSuccess
) { 
1522                 secnotice("SecKeychain", "Failed to create login data: %d", (int) result
); 
1526         secnotice("SecKeychain", "SecKeychainStoreUnlockKeyWithPubKeyHash result %d", (int) result
); 
1530 OSStatus 
SecKeychainEraseUnlockKeyWithPubKeyHash(CFDataRef pubKeyHash
) 
1532     OSStatus result 
= TokenLoginDeleteUnlockData(pubKeyHash
); 
1533     if (result 
!= errSecSuccess
) { 
1534         secnotice("SecKeychain", "Failed to erase stored wrapped unlock key: %d", (int) result
);