I read online that there is no way to extract the call log from an iPhone. I want to develop an app to help people remember to call their mom, and if they did, the "nagging" would disappear automatically. I'm looking for any workaround to know when a user called someone, without having them log it manually.
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 have a launch daemon that's using the Endpoint Security framework which also is causing high memory usage (in Activity Monitor memory column shows for example 2GB and Real Memory 11MB) when building a big project in Xcode. Is it some kind of memory caching by the system? leaks -forkCorpse seems to not show any leaks.
How can I attach with heap or Instruments without the process being killed with "ENDPOINTSECURITY, Code 2 EndpointSecurity client terminated because it failed to respond to a message before its deadline"?
When we enable 3rd party authentication plugin using SFAuthorization window, then when user performs Lock Screen and then unlock the MAC. Now after unlock, if user tries to open Keychain Access, it is not getting opened.
When trying to open Keychain Access, we are prompted for credentials but after providing the credentials Keychians are not getting opened.
This is working on Sonoma 14.6.1 , but seeing this issue from macOS Sequoia onwards.
Are there any suggested settings/actions to resolve this issue?
I am developing an Authorisation Plugin which talks to Launch daemons over XPC.
Above is working neat, now I have to decide on how to get it installed on a machine.
Installation requires.
Plugin Installation
Launch Daemon Installation
Both require
Moving binary and text (.plist) file into privileged system managed directory.
Firing install/load commands as root (sudo).
I have referred this post BSD Privilege Escalation on macOS, but I am still not clear how to approach this.
Q: My requirement is:
I can use .pkg builder and install via script, however I have some initialisation task that needs to be performed. User will enter some details talk to a remote server and get some keys, all goes well restarts the system and my authorisation plugin will welcome him and get him started.
If I cannot perform initialisation I will have to do it post restart on login screen which I want to avoid if possible.
I tried unconventional way of using AppleScript from a SwiftUI application to run privileged commands, I am fine if it prompts for admin credentials, but it did not work.
I don't want that I do something and when approving it from Apple it gets rejected.
Basically, how can I provide some GUI to do initialisation during installation or may be an app which helps in this.
Q: Please also guide if I am doing elevated actions, how will it affect app distribution mechanism. In Read Me for EvenBetterAuthorizationSample I read it does.
Thanks.
Hi there,
I'm trying to use SFAuthorizationPluginView in order to show some fields in the login screen, have the user click the arrow, then continue to show more fields as a second step of authentication. How can I accomplish this?
Register multiple SecurityAgentPlugins each with their own mechanism and nib?
Some how get MacOS to call my SFAuthorizationPluginView::view() and return a new view?
Manually remove text boxes and put in new ones when button is pressed
I don't believe 1 works, for the second mechanism ended up calling the first mechanism's view's view()
Cheers,
-Ken
I’d like to confirm something regarding the hosting of the apple-app-site-association (AASA) file.
We have a server that publicly hosts the AASA file and is accessible globally. However, this server sits behind an additional security layer (a security server/reverse proxy).
My question is:
Will this security layer affect Apple’s ability to access and validate the AASA file for Universal Links or App Clips?
Are there specific requirements (e.g. headers, redirects, TLS versions, etc.) that we need to ensure the security server does not block or modify?
Any guidance or best practices would be appreciated.
Thanks!
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
Hello,
I have encountered several challenges related to System Integrity Protection (SIP) state detection and code signing requirements. I would like to seek clarification and guidance on the proper approach to programmatically determine the SIP state.
Here are the issues I’ve encountered:
XPC Code Signing Check APIs:
APIs like setCodeSigningRequirement and setConnectionCodeSigningRequirement do not work when SIP disabled and that's ok given what SIP is.
LaunchCodeRequirement API:
When using Process.launchRequirement, the LaunchCodeRequirement API does not function anymore when SIP disabled.
The IsSIPProtected requirement behaves in a way that is not clearly documented -- it appears to only apply to pre-installed Apple apps.
Legacy APIs:
Older APIs like SecCodeCheckValidity are likely to be non-functional, though I haven’t had the chance to validate this yet.
Private API Concerns:
So to mitigate those limitations I prefer my app to not even try to connect to untrusted XPC or launch untrusted Processes when SIP is disabled. The only way to determine SIP state I could find is a low-level C function csr_get_active_config. However, this function is not declared in any publicly available header file, indicating that it is a private API.
Since private APIs cannot be used in App Store-distributed apps and are best avoided for Developer ID-signed apps, this does not seem like a viable solution.
Given these limitations, what is the recommended and proper approach to programmatically determine the SIP state in a macOS application?
Any insights or guidance would be greatly appreciated.
Thank you!
Topic:
Privacy & Security
SubTopic:
General
I am new to swift development, and it's possible that I'm missing something fundamental/obvious. If so, I apologize in advance. My team is developing an application for iPadOS using SwiftUI, and I'm trying to accomplish something similar to what the original inquirer is asking for in this thread: https://developer.apple.com/forums/thread/725152. The only difference is that I'm trying to use a PIV smart card to achieve authentication to a server rather than digitally sign a document.
Unfortunately, I'm getting stuck when attempting to run the list() function provided in the accepted answer to the post mentioned above. When attempting to call SecItemCopyMatching(), I'm getting a -34018 missing entitlement error. I've attempted to add the com.apple.token to my app's keychain-access-groups entitlements, but this does not resolve the issue. I have checked the entitlements in my built app, per the recommendation in the troubleshooting guide here: https://developer.apple.com/forums/thread/114456. The entitlement for com.apple.token is indeed present in the plist. Based on other documentation I've read, however, it seems that the explicit declaration of com.apple.token should not even be required in the entitlements.
Is there something obvious that I'm missing here that would prevent my app from accessing the token access group?
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.
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.
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()
}
I have Authorisation Plugin which talks using XPC to my Launch Daemon to perform privileged actions.
I want to protect my XPC service narrowing it to be called from known trusted clients.
Now since I want authorisation plugin code which is from apple to call my service, I cannot use my own team id or app group here.
I am currently banking on following properties of client connection.
Apple Team ID : EQHXZ8M8AV
Bundle ID starting with com.apple.
Client signature verified By Apple.
This is what I have come up with.
func isClientTrusted(connection: NSXPCConnection) -> Bool {
let clientPID = connection.processIdentifier
logInfo("🔍 Checking XPC Client - PID: \(clientPID)")
var secCode: SecCode?
var secStaticCode: SecStaticCode?
let attributes = [kSecGuestAttributePid: clientPID] as NSDictionary
let status = SecCodeCopyGuestWithAttributes(nil, attributes, [], &secCode)
guard status == errSecSuccess, let code = secCode else {
logInfo("Failed to get SecCode for PID \(clientPID)")
return false
}
let staticStatus = SecCodeCopyStaticCode(code, [], &secStaticCode)
guard staticStatus == errSecSuccess, let staticCode = secStaticCode else {
logInfo("Failed to get SecStaticCode")
return false
}
var signingInfo: CFDictionary?
let signingStatus = SecCodeCopySigningInformation(staticCode, SecCSFlags(rawValue: kSecCSSigningInformation), &signingInfo)
guard signingStatus == errSecSuccess, let info = signingInfo as? [String: Any] else {
logInfo("Failed to retrieve signing info")
return false
}
// Extract and Verify Team ID
if let teamID = info["teamid"] as? String {
logInfo("XPC Client Team ID: \(teamID)")
if teamID != "EQHXZ8M8AV" { // Apple's official Team ID
logInfo("Client is NOT signed by Apple")
return false
}
} else {
logInfo("Failed to retrieve Team ID")
return false
}
// Verify Bundle ID Starts with "com.apple."
if let bundleID = info["identifier"] as? String {
logInfo("XPC Client Bundle ID: \(bundleID)")
if !bundleID.hasPrefix("com.apple.") {
logInfo("Client is NOT an Apple system process")
return false
}
} else {
logInfo("Failed to retrieve Bundle Identifier")
return false
}
// Verify Apple Code Signature Trust
var trustRequirement: SecRequirement?
let trustStatus = SecRequirementCreateWithString("anchor apple" as CFString, [], &trustRequirement)
guard trustStatus == errSecSuccess, let trust = trustRequirement else {
logInfo("Failed to create trust requirement")
return false
}
let verifyStatus = SecStaticCodeCheckValidity(staticCode, [], trust)
if verifyStatus != errSecSuccess {
logInfo("Client's signature is NOT trusted by Apple")
return false
}
logInfo("Client is fully verified as Apple-trusted")
return true
}
Q: Just wanted community feedback, is this correct approach?
We are interested in using a hardware-bound key in a launch daemon. In a previous post, Quinn explicitly told me this is not possible to use an SE keypair outside of the system context and my reading of the Apple documentation also supports that.
That said, we have gotten the following key-creation and persistence flow to work, so we have some questions as to how this fits in with the above.
(1) In a launch daemon (running thus as root), we do:
let key = SecureEnclave.P256.Signing.PrivateKey()
(2) We then use
key.dataRepresentation
to store a reference to the key in the system keychain as a kSecClassGenericPassword.
(3) When we want to use the key, we fetch the data representation from system keychain and we "rehydrate" the key using:
SecureEnclave.P256.Signing.PrivateKey(dataRepresentation: data)
(4) We then use the output of the above to sign whatever we want.
My questions:
in the above flow, are we actually getting a hardware-bound key from the Secure Enclave or is this working because it's actually defaulting to a non-hardware-backed key?
if it is an SE key, is it that the Apple documentation stating that you can only use the SE with the Data Protection Keychain in the user context is outdated (or wrong)?
does the above work, but is not an approach sanctioned by Apple?
Any feedback on this would be greatly appreciated.
I am developing a sample authorization plugin to sync the user’s local password to the network password. During the process, I prompt the user to enter both their old and new passwords in custom plugin. After the user enters the information, I use the following code to sync the passwords:
try record.changePassword(oldPssword, toPassword: newPassword)
However, I have noticed that this is clearing all saved keychain information, such as web passwords and certificates. Is it expected behavior for record.changePassword to clear previously stored keychain data?
If so, how can I overcome this issue and ensure the keychain information is preserved while syncing the password?
Thank you for your help!
I've been spending days trying to solve the memory leak in a small menu bar application I've wrote (SC Menu). I've used Instruments which shows the leaks and memory graph which shows unreleased allocations. This occurs when someone views a certificate on the smartcard.
Basically it opens a new window and displays the certificate, the same way Keychain Access displays a certificate. Whenever I create an SFCertificateView instance and set setDetailsDisclosed(true) - a memory leak happens. Instruments highlights that line.
import Cocoa
import SecurityInterface
class ViewCertsViewController: NSViewController {
var selectedCert: SecIdentity? = nil
override func viewDidLoad() {
super.viewDidLoad()
self.view = NSView(frame: NSRect(x: 0, y: 0, width: 500, height: 500))
self.view.wantsLayer = true
var secRef: SecCertificate? = nil
guard let selectedCert else { return }
let certRefErr = SecIdentityCopyCertificate(selectedCert, &secRef)
if certRefErr != errSecSuccess {
os_log("Error getting certificate from identity: %{public}@", log: OSLog.default, type: .error, String(describing: certRefErr))
return
}
let scrollView = NSScrollView()
scrollView.translatesAutoresizingMaskIntoConstraints = false
scrollView.borderType = .lineBorder
scrollView.hasHorizontalScroller = true
scrollView.hasVerticalScroller = true
let certView = SFCertificateView()
guard let secRef = secRef else { return }
certView.setCertificate(secRef)
certView.setDetailsDisclosed(true)
certView.setDisplayTrust(true)
certView.setEditableTrust(true)
certView.setDisplayDetails(true)
certView.setPolicies(SecPolicyCreateBasicX509())
certView.translatesAutoresizingMaskIntoConstraints = false
scrollView.documentView = certView
view.addSubview(scrollView)
// Layout constraints
NSLayoutConstraint.activate([
scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
scrollView.topAnchor.constraint(equalTo: view.topAnchor),
scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
// Provide certificate view a width and height constraint
certView.widthAnchor.constraint(equalTo: scrollView.widthAnchor),
certView.heightAnchor.constraint(greaterThanOrEqualToConstant: 500)
])
}
}
https://github.com/boberito/sc_menu/blob/dev_2.0/smartcard_menu/ViewCertsViewController.swift
Fairly simple.
Attempting to DECRYPT a cipher message using the Apple API SecKeyCreateDecryptedData(privateKey, .rsaEncryptionOAEPSHA256, encryptedMessage). Decryption ALWAYS fails for every algorithm.
SecKeyCreateDecryptedDataWithParameters Error: `Domain=NSOSStatusErrorDomain Code=-50 "algid:encrypt:RSA:OAEP:SHA256: algorithm not supported by the key <SecKeyRef:('com.yubico.Authenticator.TokenExtension:5621CDF8560D4C412030886584EC4C9E394CC376DD9738B0CCBB51924FC26EB6') 0x3007fd150>" UserInfo={numberOfErrorsDeep=0, NSDescription=algid:encrypt:RSA:OAEP:SHA256: algorithm not supported by the key <SecKeyRef:('com.yubico.Authenticator.TokenExtension:5621CDF8560D4C412030886584EC4C9E394CC376DD9738B0CCBB51924FC26EB6') 0x3007fd150>}`
Decryption failed: SecKeyCreateDecryptedData returned nil.
Error: One or more parameters passed to a function were not valid.
When checking with SecKeyIsAlgorithmSupported(privateKey, .decrypt, <ANYalgorithm>) all algorithms fail. Btw - The privateKey does support decryption when retrieving the attributes.
Important to know:
The private key is a reference to an external private key placed in the iOS Keychain via a 3rd party CryptoTokenKit Extension app. When I perform, the SecKeyCreateSignature(...) and pass in the SAME privateKey reference, the OS automatically calls the 3rd party app to perform a successful signing with the private key that reside on a YubiKey.
Here's my code for obtaining the private key reference from an Identity:
func getKeyPairFromIdentity() -> (privateKey: SecKey, publicKey: SecKey)? {
let query = NSDictionary(
dictionary: [
kSecClass as String: kSecClassIdentity,
kSecAttrTokenID as String: self.tokenID!,
kSecReturnRef as String: kCFBooleanTrue as Any
]
)
var identityRef: CFTypeRef?
let status = SecItemCopyMatching(query, &identityRef)
if status == errSecSuccess, let identity = identityRef {
var privateKeyRef: SecKey?
let keyStatus = SecIdentityCopyPrivateKey(identity as! SecIdentity, &privateKeyRef)
if keyStatus == errSecSuccess, let privateKey = privateKeyRef {
let publicKey = SecKeyCopyPublicKey(privateKey)
if let publicKey = publicKey {
print("Private and public keys extracted successfully.")
return (privateKey, publicKey)
} else {
print("Failed to extract public key from private key.")
return nil
}
} else {
print("SecIdentityCopyPrivateKey: Private key not found error: \(keyStatus)")
return nil
}
} else {
print("SecIdentity not found or error: \(status)")
return nil
}
}
Quinn, you've often suggested that to validate the other side of an XPC connection, we should use the audit token. But that's not available from the XPC object, whereas the PID is. So everyone uses the PID.
While looking for something completely unrelated, I found this in the SecCode.h file
OSStatus SecCodeCreateWithXPCMessage(xpc_object_t message, SecCSFlags flags,
SecCodeRef * __nonnull CF_RETURNS_RETAINED target);
Would this be the preferred way to do this now? At least from 11.0 and up.
Like I said, I was looking for something completely unrelated and found this and don't have the cycles right now to try it. But it looks promising from the description and I wanted to check in with you about it in case you can say yes or no before I get a chance to test it.
Thanks
Problem Description:
In our App, When we launch the web login part using ASWebAuthentication + Universal Links with callback scheme as "https", we are not receiving callback.
Note:
We are using "SwiftUIWebAuthentication" Swift Package Manager to display page in ASWebAuth.
But when we use custom url scheme instead of Universal link, app able to receive call back every time.
We use ".onOpenURL" to receive universal link callback scheme.
For security reasons, my application needs to prohibit external devices. If it is determined that the current phone is connected to any external devices, including non MFI authenticated devices, the app will exit. Please tell me how to do it? Thanks for your help.