Hi,
I'm working on developing my own CryptoTokenKit (CTK) extension to enable codesign with HSM-backed keys. Here's what I’ve done so far:
The container app sets up the tokenConfiguration with TKTokenKeychainCertificate and TKTokenKeychainKey.
The extension registers successfully and is visible via pluginkit when launching the container app.
The virtual smartcard appears when running security list-smartcards.
The certificate, key, and identity are all visible using security export-smartcard -i [card].
However, nothing appears in the Keychain.
After adding logging and reviewing output in the Console, I’ve observed the following behavior when running codesign:
My TKTokenSession is instantiated correctly, using my custom TKToken implementation — so far, so good.
However, none of the following TKTokenSession methods are ever called:
func tokenSession(_ session: TKTokenSession, beginAuthFor operation: TKTokenOperation, constraint: Any) throws -> TKTokenAuthOperation
func tokenSession(_ session: TKTokenSession, supports operation: TKTokenOperation, keyObjectID: TKToken.ObjectID, algorithm: TKTokenKeyAlgorithm) -> Bool
func tokenSession(_ session: TKTokenSession, sign dataToSign: Data, keyObjectID: Any, algorithm: TKTokenKeyAlgorithm) throws -> Data
func tokenSession(_ session: TKTokenSession, decrypt ciphertext: Data, keyObjectID: Any, algorithm: TKTokenKeyAlgorithm) throws -> Data
func tokenSession(_ session: TKTokenSession, performKeyExchange otherPartyPublicKeyData: Data, keyObjectID objectID: Any, algorithm: TKTokenKeyAlgorithm, parameters: TKTokenKeyExchangeParameters) throws -> Data
The only relevant Console log is:
default 11:31:15.453969+0200 PersistentToken [0x154d04850] invalidated because the client process (pid 4899) either cancelled the connection or exited
There’s no crash report related to the extension, so my assumption is that ctkd is closing the connection for some unknown reason.
Is there any way to debug this further?
Thank you for your help.
General
RSS for tagPrioritize user privacy and data security in your app. Discuss best practices for data handling, user consent, and security measures to protect user information.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
I am working on implementing mTLS authentication in my iOS app (Apple Inhouse & intune MAM managed app). The SCEP client certificate is deployed on the device via Intune MDM. When I try accessing the protected endpoint via SFSafariViewController/ASWebAuthenticationSession, the certificate picker appears and the request succeeds. However, from within my app (using URLSessionDelegate), the certificate is not found (errSecItemNotFound).
The didReceive challenge method is called, but my SCEP certificate is not found in the app. The certificate is visible under Settings > Device Management > SCEP Certificate.
How can I make my iOS app access and use the SCEP certificate (installed via Intune MDM) for mTLS requests?
Do I need a special entitlement, keychain access group, or configuration in Intune or Developer account to allow my app to use the certificate?
Here is the sample code I am using:
final class KeychainCertificateDelegate: NSObject, URLSessionDelegate {
func urlSession(_ session: URLSession,
didReceive challenge: URLAuthenticationChallenge,
completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
guard challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodClientCertificate else {
completionHandler(.performDefaultHandling, nil)
return
}
// Get the DNs the server will accept
guard let expectedDNs = challenge.protectionSpace.distinguishedNames else {
completionHandler(.cancelAuthenticationChallenge, nil)
return
}
var identityRefs: CFTypeRef? = nil
let err = SecItemCopyMatching([
kSecClass: kSecClassIdentity,
kSecMatchLimit: kSecMatchLimitAll,
kSecMatchIssuers: expectedDNs,
kSecReturnRef: true,
] as NSDictionary, &identityRefs)
if err != errSecSuccess {
completionHandler(.cancelAuthenticationChallenge, nil)
return
}
guard let identities = identityRefs as? [SecIdentity],
let identity = identities.first
else {
print("Identity list is empty")
completionHandler(.cancelAuthenticationChallenge, nil)
return
}
let credential = URLCredential(identity: identity, certificates: nil, persistence: .forSession)
completionHandler(.useCredential, credential)
}
}
func perform_mTLSRequest() {
guard let url = URL(string: "https://sample.com/api/endpoint") else {
return
}
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Accept")
request.setValue("Bearer \(bearerToken)", forHTTPHeaderField: "Authorization")
let delegate = KeychainCertificateDelegate()
let session = URLSession(configuration: .ephemeral, delegate: delegate, delegateQueue: nil)
let task = session.dataTask(with: request) { data, response, error in
guard let httpResponse = response as? HTTPURLResponse, (200...299).contains(httpResponse.statusCode) else {
print("Bad response")
return
}
if let data = data {
print(String(data: data, encoding: .utf8)!)
}
}
task.resume()
}
Hi,
I am using CryptoKit in my app. I am getting an error sometimes with some users. I log the description to Firebase but I am not sure what is it exactly about.
CryptoKit.CryptoKitError error 2
CryptoKit.CryptoKitError error 3
I receive both of these errors. I also save debug prints to a log file and let users share them with me. Logs are line-by-line encrypted but after getting these errors in the app also decryption of log files doesn't work and it throws these errors too.
I couldn't reproduce the same error by myself, and I can't reach the user's logs so I am a little blind about what triggers this.
It would be helpful to understand what these errors mean.
Thanks
In the macOS 14.0 SDK, environment and library constraints were introduced, which made defense against common attack vectors relatively simple (especially with the LightWeightCodeRequirements framework added in 14.4).
Now, the application I'm working on must support macOS 13.0 too, so I was looking into alternatives that do work for those operating systems as well.
What I found myself is that the SecCode/SecStaticCode APIs in the Security Framework do offer very similar fashion checks as the LightWeightCodeRequirements framework does:
SecCodeCopySigningInformation can return values like signing identifier, team identifier, code requirement string and so on.
SecStaticCodeCreateWithPath can return a SecStaticCode object to an executable/app bundle on the file system.
Let's say, I would want to protect myself against launchd executable swap.
From macOS 14.0 onward, I would use a Spawn Constraint for this, directly in the launchd.plist file.
Before macOS 14.0, I would create a SecStaticCode object for the executable path found in the launchd.plist, and then examine its SecCodeCopySigningInformation dictionary. If the expectations are met, only then would I execute the launchd.plist-defined executable or connect to it via XPC.
Are these two equivalent? If not, what are the differences?
Can you please give me a hand with importing certificates under MacOS?
I want to connect to Wi-Fi with 802.1X authentication (EAP-TLS) using a certificate that my homebrew application imported into my data protection keychain, but the imported certificate does not show up and I cannot select the certificate.
It also does not show up in the Keychain Access app.
One method I have tried is to import it into the data protection keychain by using the SecItemAdd function and setting kSecUseDataProtectionKeychain to true, but it does not work.
Is there a better way to do this?
ID:
for id in identities {
let identityParams: [String: Any] = [
kSecValueRef as String: id,
kSecReturnPersistentRef as String: true,
kSecUseDataProtectionKeychain as String: true
]
let addIdentityStatus = SecItemAdd(identityParams as CFDictionary, nil)
if addIdentityStatus == errSecSuccess {
print("Successfully added the ID.: \(addIdentityStatus)")
} else {
print("Failed to add the ID.: \(addIdentityStatus)")
}
}
Certificate:
for cert in certificates {
let certParams: [String: Any] = [
kSecValueRef as String: cert,
kSecReturnPersistentRef as String: true,
kSecUseDataProtectionKeychain as String: true
]
let addCertStatus = SecItemAdd(certParams as CFDictionary, nil)
if addCertStatus == errSecSuccess {
print("Successfully added the certificate.: (\(addCertStatus))")
} else {
print("Failed to add the certificate.: (\(addCertStatus))")
}
}
Private key:
for privateKey in keys {
let keyTag = UUID().uuidString.data(using: .utf8)!
let keyParams: [String: Any] = [
kSecAttrApplicationTag as String: keyTag,
kSecValueRef as String: privateKey,
kSecReturnPersistentRef as String: true,
kSecUseDataProtectionKeychain as String: true
]
let addKeyStatus = SecItemAdd(keyParams as CFDictionary, nil)
if addKeyStatus == errSecSuccess {
print("Successfully added the private key.: \(addKeyStatus)")
} else {
print("Failed to add the private key.: \(addKeyStatus)")
}
}
I am developing a daemon-based product that needs a cryptographic, non-spoofable proof of machine identity so a remote management server can grant permissions based on the physical machine.
I was thinking to create a signing key in the Secure Enclave and use a certificate signed by that key as the machine identity. The problem is that the Secure Enclave key I can create is only accessible from user context, while my product runs as a system daemon and must not rely on user processes or launchAgents.
Could you please advise on the recommended Apple-supported approaches for this use case ?
Specifically, Is there a supported way for a system daemon to generate and use an unremovable Secure Enclave key during phases like the pre-logon, that doesn't have non user context (only the my application which created this key/certificate will have permission to use/delete it)
If Secure Enclave access from a daemon is not supported, what Apple-recommended alternatives exist for providing a hardware-backed machine identity for system daemons?
I'd rather avoid using system keychain, as its contents may be removed or used by root privileged users.
The ideal solution would be that each Apple product, would come out with a non removable signing certificate, that represent the machine itself (lets say that the cetificate name use to represent the machine ID), and can be validated by verify that the root signer is "Apple Root CA"
Hi Apple Team and Community,
We encountered a sudden and widespread failure related to the App Attest service on Friday, July 25, starting at around 9:22 AM UTC.
After an extended investigation, our network engineers noted that the size of the attestation objects received from the attestKey call grew in size notably starting at that time. As a result, our firewall began blocking the requests from our app made to our servers with the Base64-encoded attestation objects in the payload, as these requests began triggering our firewall's max request length rule.
Could Apple engineers please confirm whether there was any change rolled out by Apple at or around that time that would cause the attestation object size to increase?
Can anyone else confirm seeing this?
Any insights from Apple or others would be appreciated to ensure continued stability.
Thanks!
We recently deployed Attestation on our application, and for a majority of the 40,000 users it works well. We have about six customers who are failing attestation. In digging through debug logs, we're seeing this error "iOS assertion verification failed. Unauthorized access attempted." We're assuming that the UUID is blocked somehow on Apple side but we're stumped as to why. We had a customer come in and we could look at the phone, and best we can tell it's just a generic phone with no jailbroken or any malicious apps. How can we determine if the UUID is blocked?
Binary code is associated with the NSUserTrackingUsageDescription deleted at present, but in the revised App privacy will contain NSUserTrackingUsageDescription, I feel very confused, don't know should shouldn't solve.
I recently turned on the enhanced security options for my macOS app in Xcode 26.0.1 by adding the Enhanced Security capability in the Signing and Capabilities tab. Then, Xcode adds the following key-value sets (with some other key-values) to my app's entitlements file.
<key>com.apple.security.hardened-process.enhanced-security-version</key>
<integer>1</integer>
<key>com.apple.security.hardened-process.platform-restrictions</key>
<integer>2</integer>
These values appear following the documentation about the enhanced security feature (Enabling enhanced security for your app) and the app works without any issues.
However, when I submitted a new version to the Mac App Store, my submission was rejected, and I received the following message from the App Review team via the App Store Connect.
Guideline 2.4.5(i) - Performance
Your app incorrectly implements sandboxing, or it contains one or more entitlements with invalid values. Please review the included entitlements and sandboxing documentation and resolve this issue before resubmitting a new binary.
Entitlement "com.apple.security.hardened-process.enhanced-security-version" value must be boolean and true.
Entitlement "com.apple.security.hardened-process.platform-restrictions" value must be boolean and true.
When I changed those values directly in the entitlements file based on this message, the app appears to still work. However, these settings are against the description in the documentation I mentioned above and against the settings Xcode inserted after changing the GUI setting view.
So, my question is, which settings are actually correct to enable the Enhanced Security and the Additional Runtime Platform Restrictions?
Hello, I am currently researching to develop an application where I want to apply the MacOS updates without the password prompt shown to the users.
I did some research on this and understand that an MDM solution can apply these patches without user intervention.
Are there any other ways we can achieve this? Any leads are much appreciated.
Hello,
I've developed a macOS app with an AutoFill Credential Provider extension that functions as a passkey provider. In the registration flow, I want my app to appear as a passkey provider only when specific conditions are met.
Is there a way to inspect the request from the web before the passkey provider selection list is displayed to the user, determine whether my app can handle it, and then use that result to instruct the OS on whether to include my app in the passkey provider selection list?
Alternatively, is there a way to predefine conditions that must be met before my app is offered as a passkey provider in the selection list?
Thanks!
Topic:
Privacy & Security
SubTopic:
General
Tags:
Extensions
Autofill
Authentication Services
Passkeys in iCloud Keychain
Has anyone here encountered this? It's driving me crazy.
It appears on launch.
App Sandbox is enabled.
The proper entitlement is selected (com.apple.security.files.user-selected.read-write)
I believe this is causing an issue with app functionality for users on different machines.
There is zero documentation across the internet on this problem.
I am on macOS 26 beta. This error appears in both Xcode and Xcode-beta.
Please help!
Thank you,
Logan
WebAuthn Level 3 § 6.3.2 Step 2 states the authenticator must :
Check if at least one of the specified combinations of PublicKeyCredentialType and cryptographic parameters in credTypesAndPubKeyAlgs is supported. If not, return an error code equivalent to "NotSupportedError" and terminate the operation.
On my iPhone 15 Pro Max running iOS 18.5, Safari + Passwords does not exhibit this behavior; instead an error is not reported and an ES256 credential is created when an RP passes a non-empty sequence that does not contain {"type":"public-key","alg":-7} (e.g., [{"type":"public-key","alg":-8}]).
When I use Chromium 138.0.7204.92 on my laptop running Arch Linux in conjunction with the Passwords app (connected via the "hybrid" protocol), a credential is not created and instead an error is reported per the spec.
Hi,
how can you authenticate a User through Biometrics with iPhone Passcode as Fallback in the Autofill Credential Provider Extension?
In the App it works without a problem. In the Extension I get
"Caller is not running foreground"
Yeah, it isn't, as it's just a sheet above e.g. Safari.
I'd like to avoid having the user setup a Passcode dedicated to my App, especially because FaceID is way faster.
Does anybody know how to achieve iOS native Auth in the extension?
Please let me know, a code sample would be appreciated.
Regards,
Mia
Topic:
Privacy & Security
SubTopic:
General
Tags:
Face ID
Touch ID
Local Authentication
Authentication Services
I have something with a new individual on my team I've never seen before. They checked out our code repository from git and now anytime they try to open a .json file that is legitimately just a text file, GateKeeper tells them it cannot verify the integrity of this file and offers to have them throw this file away. I've seen this with binaries, and that makes sense. I removed the com.apple.quarantine extended attribute from all executable files in our source tree, but I've never seen GateKeeper prompt on text files. I could remove the extended attribute from all files in our source tree, but I fear the next time he pulls from git he'll get new ones flagged. Is there someway around this? I've never personally seen GateKeeper blocking text files.
I have been trying to find a way to be able to sign some data with private key of an identity in login keychain without raising any prompts.
I am able to do this with system keychain (obviously with correct permissions and checks) but not with login keychain. It always ends up asking user for their login password.
Here is how the code looks, roughly,
NSDictionary *query = @{
(__bridge id)kSecClass: (__bridge id)kSecClassIdentity,
(__bridge id)kSecReturnRef: @YES,
(__bridge id)kSecMatchLimit: (__bridge id)kSecMatchLimitAll
};
CFTypeRef result = NULL;
OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef *)&amp;result);
NSArray *identities = ( NSArray *)result;
SecIdentityRef identity = NULL;
for (id _ident in identities) {
// pick one as required
}
SecKeyRef privateKey = NULL;
OSStatus status = SecIdentityCopyPrivateKey(identity, &amp;privateKey);
NSData *strData = [string dataUsingEncoding:NSUTF8StringEncoding];
unsigned char hash[CC_SHA256_DIGEST_LENGTH];
CC_SHA256(strData.bytes, (CC_LONG)strData.length, hash);
NSData *digestData = [NSData dataWithBytes:hash length:CC_SHA256_DIGEST_LENGTH];
CFErrorRef cfError = NULL;
NSData *signature = (__bridge_transfer NSData *)SecKeyCreateSignature(privateKey,
kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA256,
(__bridge CFDataRef)digestData,
&amp;cfError);
Above code raises these system logs in console
default 08:44:52.781024+0000 securityd client is valid, proceeding
default 08:44:52.781172+0000 securityd code requirement check failed (-67050), client is not Apple-signed
default 08:44:52.781233+0000 securityd displaying keychain prompt for /Applications/Demo.app(81692)
If the key is in login keychain, is there any way to do SecKeyCreateSignature without raising prompts? What does client is not Apple-signed mean?
PS: Identities are pre-installed either manually or via some device management solution, the application is not installing them.
I created an app in Xcode using ApplescriptObjC that is supposed to communicate with Finder and Adobe Illustrator. It has been working for the last 8 years, until now I have updated it for Sonoma and it no longer triggers the alerts for the user to approve the communication. It sends the Apple Events, but instead of the alert dialog I get this error in Console:
"Sandboxed application with pid 15728 attempted to lookup App: "Finder"/"finder"/"com.apple.finder" 654/0x0:0x1d01d MACSstill-hintable sess=100017 but was denied due to sandboxing."
The Illustrator error is prdictably similar.
I added this to the app.entitlements file:
<key>com.apple.security.automation.apple-events</key>
<array>
<string>com.apple.finder</string>
<string>com.adobe.illustrator</string>
</array>
I added this to Info.plist:
<key>NSAppleEventsUsageDescription</key>
<string>This app requires access to Finder and Adobe Illustrator for automation.</string>
I built the app, signed with the correct Developer ID Application Certificate.
I've also packaged it into a signed DMG and installed it, with the same result as running it from Xcode.
I tried stripping it down to just the lines of code that communicate with Finder and Illustrator, and built it with a different bundle identifier with the same result.
What am I missing?
I am developing a macOS application (targeting macOS 13 and later) that is non-sandboxed and needs to install and trust a root certificate by adding it to the System keychain programmatically.
I’m fine with prompting the user for admin privileges or password, if needed.
So far, I have attempted to execute the following command programmatically from both:
A user-level process
A root-level process
sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain /path/to/cert.pem
While the certificate does get installed, it does not appear as trusted in the Keychain Access app.
One more point:
The app is not distributed via MDM.
App will be distributed out side the app store.
Questions:
What is the correct way to programmatically install and trust a root certificate in the System keychain?
Does this require additional entitlements, signing, or profile configurations?
Is it possible outside of MDM management?
Any guidance or working samples would be greatly appreciated.
Hi community,
I'm wondering how can I request the permission of "System Audio Recording Only" under the Privacy & Security -> Screen & System Audio Recording via swift?
Did a bunch of search but didn't find good documentation on it.
Tried another approach here https://github.com/insidegui/AudioCap/blob/main/AudioCap/ProcessTap/AudioRecordingPermission.swift which doesn't work very reliably.
Topic:
Privacy & Security
SubTopic:
General
Tags:
AudioToolbox
AVAudioEngine
Core Audio
AVFoundation