Keychain starts returning error -25330 after Mac goes to sleep for a while

Hello

I'm seeing a 100% reproducible issue with macOS keychain when dealing with items protected with kSecAccessControlApplicationPassword.

Creating, accessing the item works fine unless the user is running on macOS 12 (Monterey) and the system has been sleeping for at least 15 minutes (based on testing). I've seen the exact same behavior on an iMac and a Macbook (both running on the latest Monterey version).

After sleeping for at least 15 minutes, trying to get an existing keychain item will fail with .errSecAuthFailed. From the Console I can see various messages like this:

default	12:03:11.395081+0100	KeychainAppPasswordDemo	LAContext[3506:10] created new cid:88
default	12:03:11.395231+0100	coreauthd	setCredential:5621 type:0 on ContextProxy[398:287:387] rid:829
default	12:03:11.395261+0100	coreauthd	Replacing ACM passphrase credential with purpose 0 on ACMContext 387
default	12:03:11.395395+0100	KeychainAppPasswordDemo	setCredential:5621 type:0 on LAContext[3506:10] cid:89 returned success
default	12:03:11.395522+0100	coreauthd	isCredentialSet:0 on ContextProxy[398:287:387] rid:830
default	12:03:11.395549+0100	coreauthd	Checking ACM credential 2 on ACMContext 387
default	12:03:11.395668+0100	KeychainAppPasswordDemo	isCredentialSet:0 on LAContext[3506:10] cid:90 returned YES
default	12:03:11.395843+0100	coreauthd	externalizedContextWithReply on ContextProxy[398:287:387] rid:831
default	12:03:11.396022+0100	coreauthd	AgentProxy for coreauthd[456] (agent for user 501) has registered hash 7d18cdb (uuid 8ec80e7) => RemoteContext registration for Context[287:387] in coreauthd[456] (agent for user 501)
default	12:03:11.396223+0100	KeychainAppPasswordDemo	externalizedContext on LAContext[3506:10] cid:91 returned 7d18cdb
default	12:03:11.397073+0100	secd	Authentication is needed for genp,rowid=32577 (-25330): Error Domain=NSOSStatusErrorDomain Code=-25330 "(null)" UserInfo={-25330=(
        (
        {length = 57, bytes = 0x3137300a 0c05626f 756e6401 0101300b ... 04646163 6c010101 },
        od
    )
)}
default	12:03:11.397169+0100	secd	Authentication is needed KeychainAppPassw[3506]/1#6 LF=0 copy_matching Error Domain=NSOSStatusErrorDomain Code=-25330 "(null)" UserInfo={-25330=(
        (
        {length = 57, bytes = 0x3137300a 0c05626f 756e6401 0101300b ... 04646163 6c010101 },
        od
    )
)}
default	12:03:11.397239+0100	KeychainAppPasswordDemo	Creating LAContext with externalized context 7d18cdb cid:92
default	12:03:11.397635+0100	coreauthd	ContextProxy[399:287:387] created for Context[287:387] pid:3506 uid:501
default	12:03:11.397749+0100	KeychainAppPasswordDemo	LAContext[3506:11] created with externalized context 7d18cdb cid:92
default	12:03:11.397789+0100	KeychainAppPasswordDemo	evaluateAccessControl:<SecAccessControlRef: aku;prp(true);dacl(true)> operation:od options:(null) on LAContext[3506:11] (sync) cid:93
default	12:03:11.397902+0100	coreauthd	evaluateACL:c683961 operation:od options:(null), uiDelegate:0 on ContextProxy[399:287:387] rid:832
default	12:03:11.398142+0100	coreauthd	Determined path for PID 3506: /Users/pfandrade/Library/Developer/Xcode/DerivedData/KeychainAppPasswordDemo-hbjazmbzffpzybgdfkjdykftompn/Build/Products/Debug/KeychainAppPasswordDemo.app/Contents/MacOS/KeychainAppPasswordDemo
default	12:03:11.398686+0100	coreauthd	Determined localized name for bundle com.outercorner.KeychainAppPasswordDemo: `KeychainAppPasswordDemo`
default	12:03:11.398709+0100	coreauthd	Determined name KeychainAppPasswordDemo and bundle ID com.outercorner.KeychainAppPasswordDemo for pid 3506
default	12:03:11.398768+0100	coreauthd	<ContextPluginACM: 0x7f8690104a60> evaluates operation: od
default	12:03:11.398865+0100	coreauthd	Checking ACM credential 2 on ACMContext 387
default	12:03:11.399015+0100	KeychainAppPasswordDemo	evaluateAccessControl on LAContext[3506:11] cid:93 returned {
}
default	12:03:11.399871+0100	KeychainAppPasswordDemo	evaluateAccessControl:<SecAccessControlRef: aku;prp(true);dacl(true)> operation:od options:(null) on LAContext[3506:11] (sync) cid:94
default	12:03:11.399705+0100	secd	Authentication is needed for genp,rowid=32577 (-25330): Error Domain=NSOSStatusErrorDomain Code=-25330 "(null)" UserInfo={-25330=(
        (
        {length = 57, bytes = 0x3137300a 0c05626f 756e6401 0101300b ... 04646163 6c010101 },
        od
    )
)}

This pattern loops until it gives up with:

default	12:03:11.433438+0100	KeychainAppPasswordDemo	Simulating crash, reason: Reached maximum count of authentication attempts
 operation: od acl:3137300A0C05626F756E64010101300B0C0470726F740C03616B75301C0C0361636C311530080C0370727001010130090C046461636C010101
, code=53c00006

And the call to SecItemCopyMatching returns with .errSecAuthFailed

Simply logging the user out and back in of macOS doesn't do anything. But restarting the Mac always fixes it.

I'm baffled by this and have no clue what I could try to do on my app to avoid this. Help!

Your use of kSecAccessControlApplicationPassword indicates that you’re using the data protection keychain. See TN3137 On Mac keychain APIs and implementations for context on that.

The data protection keychain works on macOS much like it does on iOS. If the device is locked then, at some point, the system forgets the secrets necessary to access it. Apple Platform Security discusses this in more detail, albeit from a very iOS-specific viewpoint.

Based on the log messages you posted, it seems that your ongoing attempt to access it has triggered some sort of lockout.

When you create your SecAccessControl object, what do you pass in to the protection parameter?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

I'm passing in kSecAttrAccessibleWhenUnlockedThisDeviceOnly. But I've thought that could be the cause* and also tried kSecAttrAccessibleWhenUnlocked, kSecAttrAccessibleAfterFirstUnlock and even kSecAttrAccessibleAlways. The issue exists no matter what the protection is.

*since all the Macs that exhibit the issue are on 10.12 but also don't have a Secure Enclave (Intel Macs without T1 or T2 chip).

I've also just filed FB12189765. There's a sample project attached to the feedback. I can't seem to attach a zip here but I'm attaching the relevant code as a .txt for reference here.

For those reading along, I’ll be helping paulo_andrade with this in a different context.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Keychain starts returning error -25330 after Mac goes to sleep for a while
 
 
Q