+
+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)
+{
+ 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};
+ AuthorizationRights *authorizedRights = NULL;
+
+ 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, &authorizedRights);
+ if (authorizedRights)
+ AuthorizationFreeItemSet(authorizedRights);
+
+ if (result == errAuthorizationSuccess) {
+ AuthorizationItemSet *items;
+ result = AuthorizationCopyInfo(authorizationRef, kAuthorizationEnvironmentPassword, &items);
+ if (result == errAuthorizationSuccess) {
+ if (items->count > 0) {
+ pwd = CFStringCreateWithCString(kCFAllocatorDefault, (const char *)items->items[0].value, kCFStringEncodingUTF8);
+ }
+ 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);
+ return result;
+}
+
+OSStatus SecKeychainEraseUnlockKeyWithPubKeyHash(CFDataRef pubKeyHash)
+{
+ OSStatus result = TokenLoginDeleteUnlockData(pubKeyHash);
+ if (result != errSecSuccess) {
+ secnotice("SecKeychain", "Failed to erase stored wrapped unlock key: %d", (int) result);
+ }
+ return result;
+}
+