]> git.saurik.com Git - apple/security.git/blobdiff - OSX/libsecurity_keychain/lib/SecKeychain.cpp
Security-59754.80.3.tar.gz
[apple/security.git] / OSX / libsecurity_keychain / lib / SecKeychain.cpp
index fe9caaef3056e1c7a9bc904a61889d2c93a4c675..ca80c80b0a322530139cbda1a3f5b8a3217718f2 100644 (file)
 #include <security_cdsa_utilities/Schema.h>
 #include <security_cdsa_client/mdsclient.h>
 #include <pwd.h>
+#include <os/activity.h>
+#include <Security/AuthorizationTagsPriv.h>
+#include <Security/Authorization.h>
+#include "TokenLogin.h"
+#include "LegacyAPICounts.h"
+
+extern "C" {
+#include "ctkloginhelper.h"
+}
 
 OSStatus
 SecKeychainMDSInstall()
 {
-       BEGIN_SECAPI
+    BEGIN_SECAPI
+
+          os_activity_t activity = os_activity_create("SecKeychainMDSInstall", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+    os_activity_scope(activity);
+    os_release(activity);
 
        Security::MDSClient::Directory d;
        d.install();
@@ -61,6 +74,7 @@ SecKeychainGetTypeID(void)
 OSStatus
 SecKeychainGetVersion(UInt32 *returnVers)
 {
+    COUNTLEGACYAPI
     if (!returnVers)
                return errSecSuccess;
 
@@ -74,42 +88,27 @@ SecKeychainOpen(const char *pathName, SecKeychainRef *keychainRef)
 {
     BEGIN_SECAPI
 
-       RequiredParam(keychainRef)=globals().storageManager.make(pathName, false)->handle();
-
-       END_SECAPI
-}
-
+          os_activity_t activity = os_activity_create("SecKeychainOpen", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+    os_activity_scope(activity);
+    os_release(activity);
 
-OSStatus
-SecKeychainOpenWithGuid(const CSSM_GUID *guid, uint32 subserviceId, uint32 subserviceType, const char* dbName,
-                                               const CSSM_NET_ADDRESS *dbLocation, SecKeychainRef *keychain)
-{
-    BEGIN_SECAPI
-
-       // range check parameters
-       RequiredParam (guid);
-       RequiredParam (dbName);
-       
-       // create a DLDbIdentifier that describes what should be opened
-    const CSSM_VERSION *version = NULL;
-    const CssmSubserviceUid ssuid(*guid, version, subserviceId, subserviceType);
-       DLDbIdentifier dLDbIdentifier(ssuid, dbName, dbLocation);
-       
-       // make a keychain from the supplied info
-       RequiredParam(keychain) = globals().storageManager.makeKeychain(dLDbIdentifier, false)->handle ();
+       RequiredParam(keychainRef)=globals().storageManager.make(pathName, false)->handle();
 
        END_SECAPI
 }
 
-
 OSStatus
 SecKeychainCreate(const char *pathName, UInt32 passwordLength, const void *password,
        Boolean promptUser, SecAccessRef initialAccess, SecKeychainRef *keychainRef)
 {
     BEGIN_SECAPI
+
+          os_activity_t activity = os_activity_create("SecKeychainCreate", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+    os_activity_scope(activity);
+    os_release(activity);
     
     KCThrowParamErrIf_(!pathName);
-       Keychain keychain = globals().storageManager.make(pathName);
+       Keychain keychain = globals().storageManager.make(pathName, true, true);
 
        // @@@ the call to StorageManager::make above leaves keychain the the cache.
        // If the create below fails we should probably remove it.
@@ -132,6 +131,10 @@ SecKeychainDelete(SecKeychainRef keychainOrArray)
 {
     BEGIN_SECAPI
 
+          os_activity_t activity = os_activity_create("SecKeychainDelete", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+    os_activity_scope(activity);
+    os_release(activity);
+
        KCThrowIf_(!keychainOrArray, errSecInvalidKeychain);
        StorageManager::KeychainList keychains;
        globals().storageManager.optionalSearchList(keychainOrArray, keychains);
@@ -147,6 +150,10 @@ SecKeychainSetSettings(SecKeychainRef keychainRef, const SecKeychainSettings *ne
 {
     BEGIN_SECAPI
 
+          os_activity_t activity = os_activity_create("SecKeychainSetSettings", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+    os_activity_scope(activity);
+    os_release(activity);
+
        Keychain keychain = Keychain::optional(keychainRef);
        if (newSettings->version==SEC_KEYCHAIN_SETTINGS_VERS1)
        {
@@ -164,6 +171,10 @@ SecKeychainCopySettings(SecKeychainRef keychainRef, SecKeychainSettings *outSett
 {
     BEGIN_SECAPI
 
+          os_activity_t activity = os_activity_create("SecKeychainCopySettings", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+    os_activity_scope(activity);
+    os_release(activity);
+
        Keychain keychain = Keychain::optional(keychainRef);
        if (outSettings->version==SEC_KEYCHAIN_SETTINGS_VERS1)
        {
@@ -184,6 +195,10 @@ SecKeychainUnlock(SecKeychainRef keychainRef, UInt32 passwordLength, const void
 {
        BEGIN_SECAPI
 
+          os_activity_t activity = os_activity_create("SecKeychainUnlock", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+    os_activity_scope(activity);
+    os_release(activity);
+
        Keychain keychain = Keychain::optional(keychainRef);
 
        if (usePassword)
@@ -200,6 +215,10 @@ SecKeychainLock(SecKeychainRef     keychainRef)
 {
        BEGIN_SECAPI
 
+          os_activity_t activity = os_activity_create("SecKeychainLock", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+    os_activity_scope(activity);
+    os_release(activity);
+
        Keychain keychain = Keychain::optional(keychainRef);
        keychain->lock();
 
@@ -212,6 +231,10 @@ SecKeychainLockAll(void)
 {
        BEGIN_SECAPI
 
+          os_activity_t activity = os_activity_create("SecKeychainLockAll", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+    os_activity_scope(activity);
+    os_release(activity);
+
        globals().storageManager.lockAll();
 
        END_SECAPI
@@ -221,6 +244,10 @@ SecKeychainLockAll(void)
 OSStatus SecKeychainResetLogin(UInt32 passwordLength, const void* password, Boolean resetSearchList)
 {
        BEGIN_SECAPI
+
+          os_activity_t activity = os_activity_create("SecKeychainResetLogin", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+    os_activity_scope(activity);
+    os_release(activity);
         //
         // Get the current user (using fallback method if necessary)
         //
@@ -236,15 +263,19 @@ OSStatus SecKeychainResetLogin(UInt32 passwordLength, const void* password, Bool
             endpwent();
         }
         if ( userName.length() == 0 )  // did we ultimately get one?
+        {
             MacOSError::throwMe(errAuthorizationInternal);
-               
+        }
+
+        SecurityServer::ClientSession().resetKeyStorePassphrase(password ? CssmData(const_cast<void *>(password), passwordLength) : CssmData());
+        secwarning("SecKeychainResetLogin: reset AKS passphrase");
                if (password)
                {
                        // Clear the plist and move aside (rename) the existing login.keychain
                        globals().storageManager.resetKeychain(resetSearchList);
 
                        // Create the login keychain without UI
-                       globals().storageManager.login((UInt32)userName.length(), userName.c_str(), passwordLength, password);
+                       globals().storageManager.login((UInt32)userName.length(), userName.c_str(), passwordLength, password, true);
                        
                        // Set it as the default
                        Keychain keychain = globals().storageManager.loginKeychain();
@@ -254,15 +285,15 @@ OSStatus SecKeychainResetLogin(UInt32 passwordLength, const void* password, Bool
                {
                        // Create the login keychain, prompting for password
                        // (implicitly calls resetKeychain, login, and defaultKeychain)
-                       globals().storageManager.makeLoginAuthUI(NULL);
+                       globals().storageManager.makeLoginAuthUI(NULL, true);
                }
-
-        SecurityServer::ClientSession().resetKeyStorePassphrase(password ? CssmData(const_cast<void *>(password), passwordLength) : CssmData());
+        secwarning("SecKeychainResetLogin: reset osx keychain");
 
                // Post a "list changed" event after a reset, so apps can refresh their list.
                // Make sure we are not holding mLock when we post this event.
                KCEventNotifier::PostKeychainEvent(kSecKeychainListChangedEvent);
 
+
        END_SECAPI
 }
 
@@ -282,6 +313,10 @@ SecKeychainSetDefault(SecKeychainRef keychainRef)
 {
        BEGIN_SECAPI
 
+          os_activity_t activity = os_activity_create("SecKeychainSetDefault", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+    os_activity_scope(activity);
+    os_release(activity);
+
        globals().storageManager.defaultKeychain(Keychain::optional(keychainRef));
 
        END_SECAPI
@@ -291,6 +326,10 @@ OSStatus SecKeychainCopySearchList(CFArrayRef *searchList)
 {
        BEGIN_SECAPI
 
+          os_activity_t activity = os_activity_create("SecKeychainCopySearchList", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+    os_activity_scope(activity);
+    os_release(activity);
+
        RequiredParam(searchList);
        StorageManager &smr = globals().storageManager;
        StorageManager::KeychainList keychainList;
@@ -304,6 +343,10 @@ OSStatus SecKeychainSetSearchList(CFArrayRef searchList)
 {
        BEGIN_SECAPI
 
+          os_activity_t activity = os_activity_create("SecKeychainSetSearchList", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+    os_activity_scope(activity);
+    os_release(activity);
+
        RequiredParam(searchList);
        StorageManager &smr = globals().storageManager;
        StorageManager::KeychainList keychainList;
@@ -317,6 +360,10 @@ OSStatus SecKeychainCopyDomainDefault(SecPreferencesDomain domain, SecKeychainRe
 {
        BEGIN_SECAPI
 
+          os_activity_t activity = os_activity_create("SecKeychainCopyDomainDefault", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+    os_activity_scope(activity);
+    os_release(activity);
+
        RequiredParam(keychainRef)=globals().storageManager.defaultKeychain(domain)->handle();
 
        END_SECAPI
@@ -326,6 +373,10 @@ OSStatus SecKeychainSetDomainDefault(SecPreferencesDomain domain, SecKeychainRef
 {
        BEGIN_SECAPI
 
+          os_activity_t activity = os_activity_create("SecKeychainSetDomainDefault", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+    os_activity_scope(activity);
+    os_release(activity);
+
        globals().storageManager.defaultKeychain(domain, Keychain::optional(keychainRef));
 
        END_SECAPI
@@ -348,6 +399,10 @@ OSStatus SecKeychainSetDomainSearchList(SecPreferencesDomain domain, CFArrayRef
 {
        BEGIN_SECAPI
 
+          os_activity_t activity = os_activity_create("SecKeychainSetDomainSearchList", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+    os_activity_scope(activity);
+    os_release(activity);
+
        RequiredParam(searchList);
        StorageManager &smr = globals().storageManager;
        StorageManager::KeychainList keychainList;
@@ -361,6 +416,10 @@ OSStatus SecKeychainSetPreferenceDomain(SecPreferencesDomain domain)
 {
        BEGIN_SECAPI
 
+          os_activity_t activity = os_activity_create("SecKeychainSetPreferenceDomain", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+    os_activity_scope(activity);
+    os_release(activity);
+
        globals().storageManager.domain(domain);
 
        END_SECAPI
@@ -369,6 +428,10 @@ OSStatus SecKeychainSetPreferenceDomain(SecPreferencesDomain domain)
 OSStatus SecKeychainGetPreferenceDomain(SecPreferencesDomain *domain)
 {
        BEGIN_SECAPI
+
+          os_activity_t activity = os_activity_create("SecKeychainGetPreferenceDomain", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+    os_activity_scope(activity);
+    os_release(activity);
        
        *domain = globals().storageManager.domain();
        
@@ -408,6 +471,51 @@ SecKeychainGetPath(SecKeychainRef keychainRef, UInt32 *ioPathLength, char *pathN
        END_SECAPI
 }
 
+OSStatus
+SecKeychainGetKeychainVersion(SecKeychainRef keychainRef, UInt32* version)
+{
+    BEGIN_SECAPI
+
+          RequiredParam(version);
+
+    *version = Keychain::optional(keychainRef)->database()->dbBlobVersion();
+
+    END_SECAPI
+}
+
+OSStatus
+SecKeychainAttemptMigrationWithMasterKey(SecKeychainRef keychain, UInt32 version, const char* masterKeyFilename)
+{
+    BEGIN_SECAPI
+
+          os_activity_t activity = os_activity_create("SecKeychainAttemptMigrationWithMasterKey", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+    os_activity_scope(activity);
+    os_release(activity);
+
+    RequiredParam(masterKeyFilename);
+    Keychain kc = Keychain::optional(keychain);
+
+    SecurityServer::SystemKeychainKey keychainKey(masterKeyFilename);
+    if(keychainKey.valid()) {
+        // We've managed to read the key; now, create credentials using it
+        string path = kc->name();
+
+        CssmClient::Key keychainMasterKey(kc->csp(), keychainKey.key(), true);
+        CssmClient::AclFactory::MasterKeyUnlockCredentials creds(keychainMasterKey, Allocator::standard(Allocator::sensitive));
+
+        // Attempt the migrate, using our master key as the ACL override
+        bool result = kc->keychainMigration(path, kc->database()->dbBlobVersion(), path, version, creds.getAccessCredentials());
+        if(!result) {
+            return errSecBadReq;
+        }
+        return (kc->database()->dbBlobVersion() == version ? errSecSuccess : errSecBadReq);
+    } else {
+        return errSecBadReq;
+    }
+
+    END_SECAPI
+}
+
 
 // @@@ Deprecated
 UInt16
@@ -479,6 +587,10 @@ SecKeychainAddCallback(SecKeychainCallback callbackFunction, SecKeychainEventMas
 {
     BEGIN_SECAPI
 
+          os_activity_t activity = os_activity_create("SecKeychainAddCallback", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+    os_activity_scope(activity);
+    os_release(activity);
+
        RequiredParam(callbackFunction);
        CCallbackMgr::AddCallback(callbackFunction,eventMask,userContext);
 
@@ -491,6 +603,10 @@ SecKeychainRemoveCallback(SecKeychainCallback callbackFunction)
 {
     BEGIN_SECAPI
 
+          os_activity_t activity = os_activity_create("SecKeychainRemoveCallback", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+    os_activity_scope(activity);
+    os_release(activity);
+
        RequiredParam(callbackFunction);
        CCallbackMgr::RemoveCallback(callbackFunction);
 
@@ -502,6 +618,10 @@ SecKeychainAddInternetPassword(SecKeychainRef keychainRef, UInt32 serverNameLeng
 {
     BEGIN_SECAPI
 
+          os_activity_t activity = os_activity_create("SecKeychainAddInternetPassword", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+    os_activity_scope(activity);
+    os_release(activity);
+
        KCThrowParamErrIf_(passwordLength!=0 && passwordData==NULL);
        // @@@ Get real itemClass
        Item item(kSecInternetPasswordItemClass, 'aapl', passwordLength, passwordData, false);
@@ -561,6 +681,10 @@ SecKeychainFindInternetPassword(CFTypeRef keychainOrArray, UInt32 serverNameLeng
 {
     BEGIN_SECAPI
 
+          os_activity_t activity = os_activity_create("SecKeychainFindInternetPassword", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+    os_activity_scope(activity);
+    os_release(activity);
+
        StorageManager::KeychainList keychains;
        globals().storageManager.optionalSearchList(keychainOrArray, keychains);
        KCCursor cursor(keychains, kSecInternetPasswordItemClass, NULL);
@@ -615,9 +739,13 @@ SecKeychainFindInternetPassword(CFTypeRef keychainOrArray, UInt32 serverNameLeng
        {
                CssmDataContainer outData;
                item->getData(outData);
-               *passwordLength=(UInt32)outData.length();
+               if (passwordLength) {
+                       *passwordLength=(UInt32)outData.length();
+               }
                outData.Length=0;
-               *passwordData=outData.data();
+               if (passwordData) {
+                       *passwordData=outData.data();
+               }
                outData.Data=NULL;
        }
 
@@ -633,6 +761,10 @@ SecKeychainAddGenericPassword(SecKeychainRef keychainRef, UInt32 serviceNameLeng
 {
        BEGIN_SECAPI
 
+          os_activity_t activity = os_activity_create("SecKeychainAddGenericPassword", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+    os_activity_scope(activity);
+    os_release(activity);
+
        KCThrowParamErrIf_(passwordLength!=0 && passwordData==NULL);
        // @@@ Get real itemClass
 
@@ -642,17 +774,7 @@ SecKeychainAddGenericPassword(SecKeychainRef keychainRef, UInt32 serviceNameLeng
        {
                CssmData service(const_cast<void *>(reinterpret_cast<const void *>(serviceName)), serviceNameLength);
                item->setAttribute(Schema::attributeInfo(kSecServiceItemAttr), service);
-               // use service name as default label (UNLESS the service is iTools and we have an account name [3787371])
-               const char *iTools = "iTools";
-               if (accountNameLength && serviceNameLength==strlen(iTools) && !memcmp(serviceName, iTools, serviceNameLength))
-               {
-                       CssmData account(const_cast<void *>(reinterpret_cast<const void *>(accountName)), accountNameLength);
-                       item->setAttribute(Schema::attributeInfo(kSecLabelItemAttr), account);
-               }
-               else
-               {
-                       item->setAttribute(Schema::attributeInfo(kSecLabelItemAttr), service);
-               }
+        item->setAttribute(Schema::attributeInfo(kSecLabelItemAttr), service);
        }
 
        if (accountName && accountNameLength)
@@ -689,6 +811,10 @@ SecKeychainFindGenericPassword(CFTypeRef keychainOrArray, UInt32 serviceNameLeng
 {
     BEGIN_SECAPI
 
+          os_activity_t activity = os_activity_create("SecKeychainFindGenericPassword", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+    os_activity_scope(activity);
+    os_release(activity);
+
        StorageManager::KeychainList keychains;
        globals().storageManager.optionalSearchList(keychainOrArray, keychains);
        KCCursor cursor(keychains, kSecGenericPasswordItemClass, NULL);
@@ -714,9 +840,13 @@ SecKeychainFindGenericPassword(CFTypeRef keychainOrArray, UInt32 serviceNameLeng
        {
                CssmDataContainer outData;
                item->getData(outData);
-               *passwordLength=(UInt32)outData.length();
+               if (passwordLength) {
+                       *passwordLength=(UInt32)outData.length();
+               }
                outData.Length=0;
-               *passwordData=outData.data();
+               if (passwordData) {
+                       *passwordData=outData.data();
+               }
                outData.Data=NULL;
        }
 
@@ -754,6 +884,10 @@ SecKeychainGetDLDBHandle(SecKeychainRef keychainRef, CSSM_DL_DB_HANDLE *dldbHand
 {
     BEGIN_SECAPI
 
+          os_activity_t activity = os_activity_create("SecKeychainGetDLDBHandle", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+    os_activity_scope(activity);
+    os_release(activity);
+
        RequiredParam(dldbHandle);
        
        Keychain keychain = Keychain::optional(keychainRef);
@@ -762,6 +896,8 @@ SecKeychainGetDLDBHandle(SecKeychainRef keychainRef, CSSM_DL_DB_HANDLE *dldbHand
     END_SECAPI
 }
 
+static ModuleNexus<Mutex> gSecReturnedKeychainCSPsMutex;
+static ModuleNexus<std::set<CssmClient::CSP>> gSecReturnedKeychainCSPs;
 
 OSStatus
 SecKeychainGetCSPHandle(SecKeychainRef keychainRef, CSSM_CSP_HANDLE *cspHandle)
@@ -771,7 +907,15 @@ SecKeychainGetCSPHandle(SecKeychainRef keychainRef, CSSM_CSP_HANDLE *cspHandle)
        RequiredParam(cspHandle);
 
        Keychain keychain = Keychain::optional(keychainRef);
-       *cspHandle = keychain->csp()->handle();
+
+    // Once we vend this handle, we can no longer delete this CSP object via RAII (and thus call CSSM_ModuleDetach on the CSP).
+    // Keep a global pointer to it to force the CSP to stay live forever.
+    CssmClient::CSP returnedKeychainCSP = keychain->csp();
+    {
+        StLock<Mutex> _(gSecReturnedKeychainCSPsMutex());
+        gSecReturnedKeychainCSPs().insert(returnedKeychainCSP);
+    }
+       *cspHandle = returnedKeychainCSP->handle();
 
        END_SECAPI
 }
@@ -807,6 +951,10 @@ SecKeychainChangePassword(SecKeychainRef keychainRef, UInt32 oldPasswordLength,
 {
     BEGIN_SECAPI
 
+          os_activity_t activity = os_activity_create("SecKeychainChangePassword", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+    os_activity_scope(activity);
+    os_release(activity);
+
        Keychain keychain = Keychain::optional(keychainRef);
         keychain->changePassphrase (oldPasswordLength, oldPassword,  newPasswordLength, newPassword);
 
@@ -819,6 +967,10 @@ SecKeychainCopyLogin(SecKeychainRef *keychainRef)
 {
     BEGIN_SECAPI
 
+          os_activity_t activity = os_activity_create("SecKeychainCopyLogin", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+    os_activity_scope(activity);
+    os_release(activity);
+
        RequiredParam(keychainRef)=globals().storageManager.loginKeychain()->handle();
 
     END_SECAPI
@@ -830,16 +982,21 @@ SecKeychainLogin(UInt32 nameLength, const void* name, UInt32 passwordLength, con
 {
     BEGIN_SECAPI
 
+          os_activity_t activity = os_activity_create("SecKeychainLogin", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+    os_activity_scope(activity);
+    os_release(activity);
+
        try
        {
                if (password) {
-            globals().storageManager.login(nameLength, name,  passwordLength, password);
+            globals().storageManager.login(nameLength, name,  passwordLength, password, false);
         } else {
             globals().storageManager.stashLogin();
         }
        }
        catch (CommonError &e)
        {
+        secnotice("KCLogin", "SecKeychainLogin failed: %d, password was%s supplied", (int)e.osStatus(), password?"":" not");
                if (e.osStatus() == CSSMERR_DL_OPERATION_AUTH_DENIED)
                {
                        return errSecAuthFailed;
@@ -849,13 +1006,22 @@ SecKeychainLogin(UInt32 nameLength, const void* name, UInt32 passwordLength, con
                        return e.osStatus();
                }
        }
-       
+
+    catch (...) {
+        __secapiresult=errSecInternalComponent;
+    }
+    secnotice("KCLogin", "SecKeychainLogin result: %d, password was%s supplied", (int)__secapiresult, password?"":" not");
+
     END_SECAPI
 }
 
 OSStatus SecKeychainStash()
 {
     BEGIN_SECAPI
+
+          os_activity_t activity = os_activity_create("SecKeychainStash", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+    os_activity_scope(activity);
+    os_release(activity);
     
        try
        {
@@ -881,6 +1047,10 @@ SecKeychainLogout()
 {
     BEGIN_SECAPI
 
+          os_activity_t activity = os_activity_create("SecKeychainLogout", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+    os_activity_scope(activity);
+    os_release(activity);
+
        globals().storageManager.logout();
 
     END_SECAPI
@@ -900,7 +1070,8 @@ static Keychain make(const char *name)
 OSStatus SecKeychainMakeFromFullPath(const char *fullPathName, SecKeychainRef *keychainRef)
 {
     BEGIN_SECAPI
-        RequiredParam(fullPathName);
+
+       RequiredParam(fullPathName);
         RequiredParam(keychainRef)=make(fullPathName)->handle();
        END_SECAPI
 }
@@ -911,7 +1082,8 @@ OSStatus SecKeychainMakeFromFullPath(const char *fullPathName, SecKeychainRef *k
 OSStatus SecKeychainIsValid(SecKeychainRef keychainRef, Boolean* isValid)
 {
     BEGIN_SECAPI
-        *isValid = false;
+
+       *isValid = false;
         if (KeychainImpl::optional(keychainRef)->dlDbIdentifier().ssuid().guid() == gGuidAppleCSPDL)
             *isValid = true;
        END_SECAPI
@@ -922,6 +1094,10 @@ OSStatus SecKeychainIsValid(SecKeychainRef keychainRef, Boolean* isValid)
 OSStatus SecKeychainRemoveFromSearchList(SecKeychainRef keychainRef)
 {
     BEGIN_SECAPI
+
+          os_activity_t activity = os_activity_create("SecKeychainRemoveFromSearchList", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+    os_activity_scope(activity);
+    os_release(activity);
         StorageManager::KeychainList singleton;
         singleton.push_back(KeychainImpl::required(keychainRef));
         globals().storageManager.remove(singleton);
@@ -933,6 +1109,10 @@ OSStatus SecKeychainRemoveFromSearchList(SecKeychainRef keychainRef)
 OSStatus SecKeychainCreateNew(SecKeychainRef keychainRef, UInt32 passwordLength, const char* inPassword)
 {
     BEGIN_SECAPI
+
+          os_activity_t activity = os_activity_create("SecKeychainCreateNew", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+    os_activity_scope(activity);
+    os_release(activity);
         RequiredParam(inPassword);
         KeychainImpl::required(keychainRef)->create(passwordLength, inPassword);
        END_SECAPI
@@ -944,6 +1124,10 @@ OSStatus SecKeychainRecodeKeychain(SecKeychainRef keychainRef, CFArrayRef dbBlob
 {
        BEGIN_SECAPI
 
+          os_activity_t activity = os_activity_create("SecKeychainRecodeKeychain", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+    os_activity_scope(activity);
+    os_release(activity);
+
        // do error checking for required parameters
        RequiredParam(dbBlobArray);
        RequiredParam(extraData);
@@ -1019,6 +1203,10 @@ OSStatus SecKeychainCopySignature(SecKeychainRef keychainRef, CFDataRef *keychai
 {
        BEGIN_SECAPI
 
+          os_activity_t activity = os_activity_create("SecKeychainCopySignature", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+    os_activity_scope(activity);
+    os_release(activity);
+
        // do error checking for required parameters
        RequiredParam(keychainSignature);
 
@@ -1043,6 +1231,10 @@ OSStatus SecKeychainCopyBlob(SecKeychainRef keychainRef, CFDataRef *dbBlob)
 {
        BEGIN_SECAPI
 
+          os_activity_t activity = os_activity_create("SecKeychainCopyBlob", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+    os_activity_scope(activity);
+    os_release(activity);
+
        // do error checking for required parameters
        RequiredParam(dbBlob);
 
@@ -1061,6 +1253,10 @@ OSStatus SecKeychainCopyBlob(SecKeychainRef keychainRef, CFDataRef *dbBlob)
 OSStatus SecKeychainCreateWithBlob(const char* fullPathName, CFDataRef dbBlob, SecKeychainRef *kcRef)
 {
        BEGIN_SECAPI
+
+          os_activity_t activity = os_activity_create("SecKeychainCreateWithBlob", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+    os_activity_scope(activity);
+    os_release(activity);
        
        KCThrowParamErrIf_(!fullPathName);
        KCThrowParamErrIf_(!dbBlob);
@@ -1086,6 +1282,10 @@ OSStatus SecKeychainAddDBToKeychainList (SecPreferencesDomain domain, const char
 {
        BEGIN_SECAPI
 
+          os_activity_t activity = os_activity_create("SecKeychainAddDBToKeychainList", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+    os_activity_scope(activity);
+    os_release(activity);
+
        RequiredParam(dbName);
        StorageManager &smr = globals().storageManager;
        smr.addToDomainList(domain, dbName, *guid, subServiceType);
@@ -1098,7 +1298,8 @@ OSStatus SecKeychainDBIsInKeychainList (SecPreferencesDomain domain, const char*
                                                                                const CSSM_GUID *guid, uint32 subServiceType)
 {
        BEGIN_SECAPI
-       RequiredParam(dbName);
+
+          RequiredParam(dbName);
        StorageManager &smr = globals().storageManager;
        smr.isInDomainList(domain, dbName, *guid, subServiceType);
        END_SECAPI
@@ -1109,6 +1310,10 @@ OSStatus SecKeychainRemoveDBFromKeychainList (SecPreferencesDomain domain, const
                                                                                          const CSSM_GUID *guid, uint32 subServiceType)
 {
        BEGIN_SECAPI
+
+          os_activity_t activity = os_activity_create("SecKeychainRemoveDBFromKeychainList", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+    os_activity_scope(activity);
+    os_release(activity);
        RequiredParam(dbName);
        StorageManager &smr = globals().storageManager;
        smr.removeFromDomainList(domain, dbName, *guid, subServiceType);
@@ -1127,6 +1332,10 @@ void SecKeychainSetServerMode()
 OSStatus SecKeychainSetBatchMode (SecKeychainRef kcRef, Boolean mode, Boolean rollback)
 {
        BEGIN_SECAPI
+
+          os_activity_t activity = os_activity_create("SecKeychainSetBatchMode", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+    os_activity_scope(activity);
+    os_release(activity);
        RequiredParam(kcRef);
        Keychain keychain = Keychain::optional(kcRef);
        keychain->setBatchMode(mode, rollback);
@@ -1138,12 +1347,17 @@ OSStatus SecKeychainSetBatchMode (SecKeychainRef kcRef, Boolean mode, Boolean ro
 OSStatus SecKeychainCleanupHandles()
 {
        BEGIN_SECAPI
-       END_SECAPI // which causes the handle cache cleanup routine to run
+
+          END_SECAPI // which causes the handle cache cleanup routine to run
 }
 
 OSStatus SecKeychainVerifyKeyStorePassphrase(uint32_t retries)
 {
     BEGIN_SECAPI
+
+          os_activity_t activity = os_activity_create("SecKeychainVerifyKeyStorePassphrase", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+    os_activity_scope(activity);
+    os_release(activity);
     SecurityServer::ClientSession().verifyKeyStorePassphrase(retries);
     END_SECAPI
 }
@@ -1151,6 +1365,10 @@ OSStatus SecKeychainVerifyKeyStorePassphrase(uint32_t retries)
 OSStatus SecKeychainChangeKeyStorePassphrase()
 {
     BEGIN_SECAPI
+
+          os_activity_t activity = os_activity_create("SecKeychainChangeKeyStorePassphrase", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+    os_activity_scope(activity);
+    os_release(activity);
     SecurityServer::ClientSession().changeKeyStorePassphrase();
     END_SECAPI
 }
@@ -1159,6 +1377,10 @@ static OSStatus SecKeychainGetMasterKey(SecKeychainRef userKeychainRef, CFDataRe
 {
     BEGIN_SECAPI
 
+          os_activity_t activity = os_activity_create("SecKeychainGetMasterKey", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+    os_activity_scope(activity);
+    os_release(activity);
+
     // make a keychain object "wrapper" for this keychain ref
        Keychain keychain = Keychain::optional(userKeychainRef);
 
@@ -1175,9 +1397,9 @@ static OSStatus SecKeychainGetMasterKey(SecKeychainRef userKeychainRef, CFDataRe
     cred += TypedList(alloc, CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK,
                       new(alloc) ListElement(CSSM_SAMPLE_TYPE_PASSWORD),
                       new(alloc) ListElement(StringData(passphrase)));
-       db->accessCredentials(&cred);
-    
-    CSSM_DL_DB_HANDLE dlDb = db->handle();
+       db->authenticate(CSSM_DB_ACCESS_READ, &cred);
+
+       CSSM_DL_DB_HANDLE dlDb = db->handle();
        CssmData dlDbData = CssmData::wrap(dlDb);
        CssmKey refKey;
        KeySpec spec(CSSM_KEYUSE_ANY,
@@ -1196,13 +1418,97 @@ static OSStatus SecKeychainGetMasterKey(SecKeychainRef userKeychainRef, CFDataRe
     END_SECAPI
 }
 
+static const char     *kAutologinPWFilePath = "/etc/kcpassword";
+static const uint32_t kObfuscatedPasswordSizeMultiple = 12;
+static const uint32_t buffer_size = 512;
+static const uint8_t  kObfuscationKey[] = {0x7d, 0x89, 0x52, 0x23, 0xd2, 0xbc, 0xdd, 0xea, 0xa3, 0xb9, 0x1f};
+
+static void obfuscate(void *buffer, size_t bufferLength)
+{
+       uint8_t       *pBuf = (uint8_t *) buffer;
+       const uint8_t *pKey = kObfuscationKey, *eKey = pKey + sizeof( kObfuscationKey );
+
+       while (bufferLength--) {
+               *pBuf = *pBuf ^ *pKey;
+               ++pKey;
+               ++pBuf;
+               if (pKey == eKey)
+                       pKey = kObfuscationKey;
+       }
+}
+
+static bool _SASetAutologinPW(CFStringRef inAutologinPW)
+{
+       bool    result = false;
+       struct stat sb;
+
+       // Delete the kcpassword file if it exists already
+       if (stat(kAutologinPWFilePath, &sb) == 0)
+               unlink( kAutologinPWFilePath );
+
+    // NIL incoming password ==> clear auto login password (above) without setting a new one. In other words: turn auto login off.
+    if (inAutologinPW != NULL) {
+               char buffer[buffer_size];
+               const char *pwAsUTF8String = CFStringGetCStringPtr(inAutologinPW, kCFStringEncodingUTF8);
+               if (pwAsUTF8String == NULL) {
+                       if (CFStringGetCString(inAutologinPW, buffer, buffer_size, kCFStringEncodingUTF8)) pwAsUTF8String = buffer;
+               }
+
+               if (pwAsUTF8String != NULL) {
+                       size_t pwLength = strlen(pwAsUTF8String) + 1;
+                       size_t obfuscatedPWLength;
+                       char *obfuscatedPWBuffer;
+
+                       // The size of the obfuscated password should be the smallest multiple of
+                       // kObfuscatedPasswordSizeMultiple greater than or equal to pwLength.
+                       obfuscatedPWLength = (((pwLength - 1) / kObfuscatedPasswordSizeMultiple) + 1) * kObfuscatedPasswordSizeMultiple;
+                       obfuscatedPWBuffer = (char *) malloc(obfuscatedPWLength);
+
+                       // Copy the password (including null terminator) to beginning of obfuscatedPWBuffer
+                       bcopy(pwAsUTF8String, obfuscatedPWBuffer, pwLength);
+
+                       // Pad remainder of obfuscatedPWBuffer with random bytes
+                       {
+                               char *p;
+                               char *endOfBuffer = obfuscatedPWBuffer + obfuscatedPWLength;
+
+                               for (p = obfuscatedPWBuffer + pwLength; p < endOfBuffer; ++p)
+                                       *p = random() & 0x000000FF;
+                       }
+
+                       obfuscate(obfuscatedPWBuffer, obfuscatedPWLength);
+
+                       int pwFile = open(kAutologinPWFilePath, O_CREAT | O_WRONLY | O_NOFOLLOW, S_IRUSR | S_IWUSR);
+                       if (pwFile >= 0) {
+                               size_t wrote = write(pwFile, obfuscatedPWBuffer, obfuscatedPWLength);
+                               if (wrote == obfuscatedPWLength)
+                                       result = true;
+                               close(pwFile);
+                       }
+
+                       chmod(kAutologinPWFilePath, S_IRUSR | S_IWUSR);
+                       free(obfuscatedPWBuffer);
+               }
+       }
+
+    return result;
+}
 
 OSStatus SecKeychainStoreUnlockKey(SecKeychainRef userKeychainRef, SecKeychainRef systemKeychainRef, CFStringRef username, CFStringRef password) {
+       COUNTLEGACYAPI
     SecTrustedApplicationRef itemPath;
     SecAccessRef ourAccessRef = NULL;
     
     OSStatus result = errSecParam;
     
+       if (userKeychainRef == NULL) {
+               // We don't have a specific user keychain, fall back
+               if (_SASetAutologinPW(password))
+                       result = errSecSuccess;
+
+               return result;
+       }
+
     CFDataRef masterKey = NULL;
     result = SecKeychainGetMasterKey(userKeychainRef, &masterKey, password);
     if (errSecSuccess != result) {
@@ -1211,18 +1517,21 @@ OSStatus SecKeychainStoreUnlockKey(SecKeychainRef userKeychainRef, SecKeychainRe
     
     result = SecKeychainStash();
     if (errSecSuccess != result) {
-        if (NULL != masterKey) CFRelease(masterKey);
+        if (masterKey != NULL) CFRelease(masterKey);
         return result;
     }
     
     CFMutableArrayRef trustedApplications = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
-    if ( noErr == SecTrustedApplicationCreateApplicationGroup("com.apple.security.auto-login", NULL, &itemPath) && itemPath  )
+    if (noErr == SecTrustedApplicationCreateApplicationGroup("com.apple.security.auto-login", NULL, &itemPath) && itemPath)
         CFArrayAppendValue(trustedApplications, itemPath);
     
-    if ( trustedApplications && (CFArrayGetCount(trustedApplications) > 0)) {
+    if (trustedApplications && (CFArrayGetCount(trustedApplications) > 0)) {
         if (errSecSuccess == (result = SecAccessCreate(CFSTR("Auto-Login applications"), trustedApplications, &ourAccessRef))) {
+                       SecKeychainRef internalSystemKeychainRef = NULL;
             if (NULL == systemKeychainRef) {
-                SecKeychainCopyDomainDefault(kSecPreferencesDomainSystem, &systemKeychainRef);
+                               SecKeychainCopyDomainDefault(kSecPreferencesDomainSystem, &internalSystemKeychainRef);
+            } else {
+                internalSystemKeychainRef = systemKeychainRef;
             }
             
             const void *queryKeys[] =   { kSecClass,
@@ -1233,7 +1542,7 @@ OSStatus SecKeychainStoreUnlockKey(SecKeychainRef userKeychainRef, SecKeychainRe
             const void *queryValues[] = { kSecClassGenericPassword,
                 CFSTR("com.apple.loginwindow.auto-login"),
                 username,
-                systemKeychainRef,
+                               internalSystemKeychainRef,
             };
             
             const void *updateKeys[] =   { kSecAttrAccess,
@@ -1259,7 +1568,7 @@ OSStatus SecKeychainStoreUnlockKey(SecKeychainRef userKeychainRef, SecKeychainRe
                 const void *addValues[] = { kSecClassGenericPassword,
                     CFSTR("com.apple.loginwindow.auto-login"),
                     username,
-                    systemKeychainRef,
+                                       internalSystemKeychainRef,
                     ourAccessRef,
                     masterKey,
                 };
@@ -1271,13 +1580,149 @@ OSStatus SecKeychainStoreUnlockKey(SecKeychainRef userKeychainRef, SecKeychainRe
 
             if (NULL != query) CFRelease(query);
             if (NULL != update) CFRelease(update);
+
+                       // If the caller wanted us to locate the system keychain reference, it's okay to go ahead and free our magically created one
+                       if (systemKeychainRef == NULL) CFRelease(internalSystemKeychainRef);
         }
     }
 
     if (NULL != masterKey) CFRelease(masterKey);
     if (NULL != trustedApplications) CFRelease(trustedApplications);
     if (NULL != ourAccessRef) CFRelease(ourAccessRef);
-    if (NULL != systemKeychainRef) CFRelease(systemKeychainRef);
 
     return result;
 }
+
+OSStatus SecKeychainGetUserPromptAttempts(uint32_t * attempts)
+{
+    BEGIN_SECAPI
+
+    os_activity_t activity = os_activity_create("SecKeychainGetUserPromptAttempts", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+    os_activity_scope(activity);
+    os_release(activity);
+
+    if(attempts) {
+        SecurityServer::ClientSession().getUserPromptAttempts(*attempts);
+    }
+
+    END_SECAPI
+}
+
+OSStatus SecKeychainStoreUnlockKeyWithPubKeyHash(CFDataRef pubKeyHash, CFStringRef tokenID, CFDataRef wrapPubKeyHash,
+                                                 SecKeychainRef userKeychain, CFStringRef password)
+{
+       COUNTLEGACYAPI
+       CFRef<CFStringRef> pwd;
+       OSStatus result;
+
+       if (password == NULL || CFStringGetLength(password) == 0) {
+               AuthorizationRef authorizationRef;
+               result = AuthorizationCreate(NULL, NULL, kAuthorizationFlagDefaults, &authorizationRef);
+               if (result != errAuthorizationSuccess) {
+                       secnotice("SecKeychain", "failed to create authorization");
+                       return result;
+               }
+
+               AuthorizationItem myItems = {"com.apple.ctk.pair", 0, NULL, 0};
+               AuthorizationRights myRights = {1, &myItems};
+
+               char pathName[PATH_MAX];
+               UInt32 pathLength = PATH_MAX;
+               result = SecKeychainGetPath(userKeychain, &pathLength, pathName);
+               if (result != errSecSuccess) {
+                       secnotice("SecKeychain", "failed to create authorization");
+                       return result;
+               }
+
+               Boolean checkPwd = TRUE;
+               Boolean ignoreSession = TRUE;
+               AuthorizationItem envItems[] = {
+                       {AGENT_HINT_KEYCHAIN_PATH, pathLength, pathName, 0},
+                       {AGENT_HINT_KEYCHAIN_CHECK, sizeof(checkPwd), &checkPwd},
+                       {AGENT_HINT_IGNORE_SESSION, sizeof(ignoreSession), &ignoreSession}
+               };
+
+               AuthorizationEnvironment environment  = {3, envItems};
+               AuthorizationFlags flags = kAuthorizationFlagDefaults | kAuthorizationFlagInteractionAllowed | kAuthorizationFlagExtendRights;
+               result = AuthorizationCopyRights(authorizationRef, &myRights, &environment, flags, NULL);
+        secnotice("SecKeychain", "Authorization result: %d", (int)result);
+
+               if (result == errAuthorizationSuccess) {
+                       AuthorizationItemSet *items;
+                       result = AuthorizationCopyInfo(authorizationRef, kAuthorizationEnvironmentPassword, &items);
+            secnotice("SecKeychain", "Items copy result: %d", (int)result);
+                       if (result == errAuthorizationSuccess) {
+                secnotice("SecKeychain", "Items count: %d", items->count);
+                               if (items->count > 0) {
+                                       pwd = CFStringCreateWithCString(kCFAllocatorDefault, (const char *)items->items[0].value, kCFStringEncodingUTF8);
+                    if (pwd) {
+                        secnotice("SecKeychain", "Got kcpass");
+                    }
+                               }
+                               AuthorizationFreeItemSet(items);
+                       }
+               }
+               AuthorizationFree(authorizationRef, kAuthorizationFlagDefaults);
+               if (result != errAuthorizationSuccess) {
+                       secnotice("SecKeychain", "did not get authorization to pair the card");
+                       return result;
+               }
+       } else {
+               pwd.take(password);
+       }
+
+       if (!pwd) {
+               secnotice("SecKeychain", "did not get kcpass");
+               return errSecInternalComponent;
+       }
+
+       CFRef<CFDataRef> masterKey;
+       result = SecKeychainGetMasterKey(userKeychain, masterKey.take(), pwd);
+       if (result != errSecSuccess) {
+               secnotice("SecKeychain", "Failed to get master key: %d", (int) result);
+               return result;
+       }
+
+       CFRef<CFDataRef> scBlob;
+       result = TokenLoginGetScBlob(wrapPubKeyHash, tokenID, pwd, scBlob.take());
+       if (result != errSecSuccess) {
+               secnotice("SecKeychain", "Failed to get stash: %d", (int) result);
+               return result;
+       }
+
+       result = TokenLoginCreateLoginData(tokenID, pubKeyHash, wrapPubKeyHash, masterKey, scBlob);
+       if (result != errSecSuccess) {
+               secnotice("SecKeychain", "Failed to create login data: %d", (int) result);
+               return result;
+       }
+
+       secnotice("SecKeychain", "SecKeychainStoreUnlockKeyWithPubKeyHash result %d", (int) result);
+    
+    // create SC KEK
+    // this might fail if KC password is different from user's password
+    uid_t uid = geteuid();
+    if (!uid) {
+        uid = getuid();
+    }
+    struct passwd *passwd = getpwuid(uid);
+    if (passwd) {
+        CFRef<CFStringRef> username = CFStringCreateWithCString(kCFAllocatorDefault, passwd->pw_name, kCFStringEncodingUTF8);
+        OSStatus kekRes = TKAddSecureToken(username, pwd, tokenID, wrapPubKeyHash);
+        if (kekRes != noErr) {
+            secnotice("SecKeychain", "Failed to register SC token: %d", (int) kekRes); // do not fail because KC functionality be still OK
+        }
+    } else {
+        secnotice("SecKeychain", "Unable to get name for uid %d", uid);
+    }
+       return result;
+}
+
+OSStatus SecKeychainEraseUnlockKeyWithPubKeyHash(CFDataRef pubKeyHash)
+{
+       COUNTLEGACYAPI
+    OSStatus result = TokenLoginDeleteUnlockData(pubKeyHash);
+    if (result != errSecSuccess) {
+        secnotice("SecKeychain", "Failed to erase stored wrapped unlock key: %d", (int) result);
+    }
+    return result;
+}