We have a developer-id application which includes a LaunchAgent, couple of LaunchDaemon and a system extension. We want to store our secure data in keychain that can read by any of our processes or at least by LaunchDaemons. We would also prefer for our data to not be visible to users, not be accessible to other processes and we did not want to use system keychain because of our prior experience where one of our app data on update corrupted the system keychain for one customer.
Therefore, we have decided to create our own keychain file and store our data there. However, we noticed that SecKeychainCreate and related file based keychain APIs are deprecated. This led me to below threads:
https://developer.apple.com/forums/thread/685546
https://developer.apple.com/forums/thread/712875
https://developer.apple.com/forums/thread/696431
And now I am confused. It is suggested that we should use data protection based keychain because file based keychains are on path to deprecation. However, it is also noted that data protection keychains do not work with LaunchDaemons. So which keychain is the right choice for our requirements?
Also,
One tricky aspect of this is that the SecItem API supports both keychain implementations
I do not see any option to use file based keychain using SecItem API. How can I create a new keychain file at a given path and add data in it using SecItem APIs? Can someone please elaborate on this with example?
Security
RSS for tagSecure the data your app manages and control access to your app using the Security framework.
Posts under Security tag
200 Posts
Sort by:
Post
Replies
Boosts
Views
Activity
Hello Apple
We have been facing lot of SSL issues when we are connecting to iOS devices with OS 17.5.1, 7.6.1 and 18. Need more clarification on the latest parameters to be used on the server side like -> TLS Version and Cipher Suites Please do update us on the above.
Error message-> "An SSL error has occurred and a secure connection to the server cannot be made."
Hi,
I have a question regarding data protection in ios 7.
Qustion 1 : if the passcode is turned off, and data protection is disabled, in this case, will the files in nand flash still be encrypted? Or will it just disable all hardware encryption and all the files in nand flash will be decrypted and stored in plain text? The security paper says even the NSFileProtectionNone class has some level of hardware encryption, but my question is if someone disable the passcode and disable the data protection, will the newly created file still be encrypted using UID key so the chiping-off the nand flash and reading off the nand directly does not work due to encryption even though the passcode is disabled and data protection is not active?
Question 2 : if they are still encrypted, do the files in the storage have the data protection NSFileProtectionNone class if the passcode is disabled and data protection is inactive?
I need to integrate BLE (Bluetooth Low Energy) functionality into an authorization plugin. Specifically, I want to use a beacon to send a notification to the user if the app is not running or has been killed. However, I’ve encountered a significant limitation: Core Bluetooth is not permitted to be used within authorization plugins, whereas the Multipeer Connectivity framework operates without issue which use WiFi.
This has led me to a few questions:
What are the fundamental differences in entitlements or restrictions between Core Bluetooth and the Multipeer Connectivity(WiFi) framework that could explain why Core Bluetooth is disallowed in authorization plugins?
Are there specific technical or security concerns associated with Core Bluetooth that prevent its use in these contexts, while the Multipeer Connectivity framework is allowed?
Given that Google’s Nearby Connections API can work within authorization plugins, could there be any similar approaches or best practices for implementing BLE functionality in scenarios involving authorization plugins? For reference, you can check Google’s Nearby Connections API here: Google Nearby Connections - https://developers.google.com/nearby/connections/swift/get-started
Any insights or suggestions on how to overcome this limitation or alternative approaches to achieve the desired functionality would be greatly appreciated.
Thank you in advance for your help!
Apple is Delaying the Review of a Critical iOS 17 Vulnerability to Avoid Official Acceptance and Bounty Payment
Hamed Hamedi, a security researcher, has revealed that Apple is prolonging the review process of a serious security vulnerability in the iCloud lock screen, which he discovered in iOS 17. According to Hamedi, he has submitted all the necessary evidence, including multiple videos and detailed explanations, to Apple's security team. However, despite the passage of time and providing precise information, Apple has been stalling the process by asking repetitive questions and requesting additional documentation, effectively delaying the report's resolution.
This security bug allows users to bypass the iCloud lock screen using VoiceOver and a few simple gestures, gaining access to various parts of the device. Despite the fact that all the steps are clearly demonstrated in the submitted videos, Apple has refrained from officially acknowledging the bug and processing the associated bounty.
Hamedi believes the upcoming release of the iPhone 16 and iOS 18 might be the main reason for these delays, as acknowledging the bug could negatively impact the reputation and security of Apple's new products, potentially eroding customer trust. He suspects that Apple is deliberately postponing the case to prevent the public disclosure of the vulnerability right before the launch of its new products.
Apple's delay in addressing such serious security issues raises important questions about the company's priorities in safeguarding user security and maintaining transparency in handling critical problems. It remains unclear what decision Apple will ultimately make regarding this case, but the delays have already sparked significant concern among security experts.
https://www.instagram.com/p/C_iZGUJK6ok/?igsh=MTlnMnQ0bGswM2cyYQ==
Suppose there is a key in the keychain that is protected by an ACL which specifies .userPresence as its access control - is it possible to prevent the user from being prompted to authenticate with biometrics and to force authentication via the device passcode instead?
Halo, I want to ask, i have an application. I get keychain value from i click apps launch but this case after i launch my apps keychain failed retrieve and my apps can't access this value after that the value change to nil. How to solve this problem ?
I have been bitten by this repeatedly so I am finally going to ask: Is there a way to infer an error from its localizedDescription only?
It sometimes happens that a user reaches out for support with just a localized error message, but no error code or error domain and it is really hard to correctly guess what the non-localized description may have been in order to search for it.
For example I know from experience that "Der eingegebene Benutzername oder das Passwort ist ungültig." is the German localization of "The user name or passphrase you entered is not correct." which in turn is errSecAuthFailed (aka. -25293). It would be really helpful to be able to just look this up somewhere...
Hello Apple Developer,
I have some questions regarding slow keychain access. We recently launched a product, and users with certain specific device models have reported slow performance. I'm not sure what's causing this issue and would appreciate your help in analyzing it.When using keychain groups, I didn’t specify a group, and on some devices, the queries are particularly slow. I'm unsure of the reason for this.I’m using kSecAttrTokenIDSecureEnclave, and each time I execute SecItemCopyMatching or SecItemDelete, the operation is particularly slow, taking around 2 seconds.It’s strange that when setting the default keychain group (team ID + bundle ID), the access is not slow. However, since the project has enabled the keychain group, if I set a keychain group, I cannot access the data that was stored before setting the keychain group.
Here is a snippet of my code:
NSMutableDictionary *parameters = [[NSMutableDictionary alloc] initWithObjectsAndKeys:(__bridge id)kSecAttrTokenIDSecureEnclave,(__bridge id)kSecAttrTokenID,
(__bridge id)kSecAttrKeyTypeEC,(__bridge id)kSecAttrKeyType,
@256,(__bridge id)kSecAttrKeySizeInBits,
PrivateKeyAttrs,(__bridge id)kSecPrivateKeyAttrs,nil];
privateKey = SecKeyCreateRandomKey((__bridge CFDictionaryRef)parameters, &error);
Here is a search of my code:
SecKeyRef privateKey = NULL;
//CFTypeRef *private = &privateKey;
NSDictionary *query = nil;
query = @{
(__bridge id)kSecClass: (__bridge id)kSecClassKey,
(__bridge id)kSecAttrApplicationTag: serviceID,
(__bridge id)kSecReturnRef: @YES
};
OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef *)&privateKey);
if (privateKey) {
CFRelease(privateKey);
}
How to install root trusted certificate via SSH ?
I already read that SecTrustSettingsSetTrustSettings requires user interaction.
That mean that it requires user login and password be entered.
But is it possible to move that authetification to command line, outside UI session?
I made a sample tool that try to do this.
https://github.com/DanilKorotenko/certificateTool
Accordingly to the documentation:
https://developer.apple.com/library/archive/documentation/Security/Conceptual/authorization_concepts/02authconcepts/authconcepts.html#//apple_ref/doc/uid/TP30000995-CH205-CJBJBGAA
If the timeout attribute is missing, the credential can be used to grant the right as long as the login session lasts, unless the credential is explicitly destroyed.
When I call function AuthorizationCopyRights,
I create a shared credential (login+password).
Authorization rule com.apple.trust-settings.admin does not have timeout attribute.
security authorizationdb read com.apple.trust-settings.admin
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>class</key>
<string>rule</string>
<key>comment</key>
<string>For modifying Trust Settings in the Admin domain. Requires entitlement or admin authentication.</string>
<key>created</key>
<real>745942864.47938299</real>
<key>k-of-n</key>
<integer>1</integer>
<key>modified</key>
<real>745942864.47938299</real>
<key>rule</key>
<array>
<string>entitled</string>
<string>authenticate-admin</string>
</array>
<key>version</key>
<integer>1</integer>
</dict>
</plist>
But. If read authd log, when running this tool, in logs we can read this:
default 18:28:43.117724+0300 authd Validating shared credential trustadmin (707) for authenticate-admin (engine 396)
default 18:28:43.117733+0300 authd credential 707 expired '0.136439 > 0' (does NOT satisfy rule) (engine 396)
It says that our credential is expired.
But it should not be expired because the rule does not have timeout.
In summary, accordingly to documentation, SecTrustSettingsSetTrustSettings should not require authentification, when calling process is running as root. Because, com.apple.trust-settings.admin right rule does not have timeout, and since that root authetification on process call will create shared credential which SecTrustSettingsSetTrustSettings will use.
But in reality the behavior is different.
I found, that on some other macs, that tool works as expected. It adds trust certificate silently.
May be there is some special condition for exactly this roght? May be there is some special preferences, flags or environment variables?
Steps To Reproduce
Change this constants in code before build.
const char *userLogin = "your-adminuser";
const char *userPass = "your-password";
const char *certificateName = "your-certificateFileName";
You may use testCertificate, or create our own.
Build project.
Connect to localhost by ssh
ssh <youruser>@localhost
Go to build folder.
sudo ./certificateTool
Actual result:
The tool returns:
SecTrustSettingsSetTrustSettings failure. Error: -60007
That means that user interaction is required.
Expected result:
User interaction does not required.
Hello, I'm developing an SDK that will allow iOS devices (iOS 13+) to connect to AWS IoT Core using Native C. The endpoint requires a mutual TLS handshake to connect. I have been able to successfully import a Certificate and Private Key into the keychain and generate a SecIdentityRef that combines the cert/key pair which I believe is necessary to establish a TCP TLS nw_connection.
I've searched around and while I can find the individual pieces related to creating a TLS connection, I can't seem to find any that show how things go together.
The goal would be to use
nw_connection_create(endpoint, parameters);
to establish a TLS connection.
This is currently how I am creating the parameters for this connection.
transport_ctx->secitem_identity is where the SecIdentityRef is kept.
nw_parameters_create_secure_tcp(
// nw_parameters_configure_protocol_block_t for configure_tls
^(nw_protocol_options_t tls_options) {
sec_protocol_options_t sec_options = nw_tls_copy_sec_protocol_options(tls_options);
// Set the minimum TLS version to TLS 1.2
sec_protocol_options_set_min_tls_protocol_version(sec_options, tls_protocol_version_TLSv12);
// Set the maximum TLS version to TLS 1.3
sec_protocol_options_set_max_tls_protocol_version(sec_options, tls_protocol_version_TLSv13);
sec_protocol_options_set_local_identity(sec_options, transport_ctx->secitem_identity);
},
// nw_parameters_configure_protocol_block_t for configure_tcp
// This is also manually set with a code block but not relevant to this q.
NW_PARAMETERS_DEFAULT_CONFIGURATION);
My question is whether or not I'm even on the right track with attempting to use these functions to setup the TLS options associated with the parameters? The sec_protocol_options_set_local_identity appears to be listed under "Security legacy reference" in the apple dev docs: https://developer.apple.com/documentation/security/sec_protocol_options_set_local_identity(_:_:)?language=objc
And the surrounding documentation related to using TLS with a network connection feels sparse at best.
Follow up question is whether there is any documentation or reading material available for setting up TLS with a TCP socket connection. I'd love to not have to take up time asking these questions if there's somewhere I can just learn it.
Thanks!
I've created a p256 ec key in the SE, stored it in the keychain, and have a X.509 certificate for that key, now I want to create and store a SecIdentity item in the keychain on iOS. SecIdentityCreateWithCertificate is available on macOS only., so that is not an option. How am I supposed to create a SecIdentity without having that call available?
I'm developing an SDK that will allow iOS devices (iOS 13+) to connect to AWS IoT Core using Native C. The endpoint requires a mutual TLS handshake to connect. I have been able to successfully import a Certificate and Private Key into the keychain but am unable to generate a SecIdentityRef from them for use in setting up a nw_protocol_options_t. I've looked through other forum posts and have been unable to figure out what's going on (Some are from 5+ years ago and maybe things have changed since then).
After prepping the raw data for the cert and key into expected formats I import the certificate:
const void *add_keys[] = {
kSecClass,
kSecAttrLabel,
kSecAttrSerialNumber,
kSecValueData,
kSecReturnRef };
const void *add_values[] = {
kSecClassCertificate,
label,
serial_data,
cert_data,
kCFBooleanTrue };
attributes = CFDictionaryCreate(
cf_alloc,
add_keys,
add_values,
5,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
status = SecItemAdd(attributes, (CFTypeRef *)out_certificate);
Next I import the private key:
const void *add_keys[] = {
kSecClass,
kSecAttrKeyClass,
kSecAttrKeyType,
kSecAttrApplicationLabel,
kSecAttrLabel,
kSecValueData,
kSecReturnRef };
const void *add_values[] = {
kSecClassKey,
kSecAttrKeyClassPrivate,
key_type,
application_label,
label,
key_data,
kCFBooleanTrue };
attributes = CFDictionaryCreate(
cf_alloc,
add_keys,
add_values,
7,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
status = SecItemAdd(attributes, (CFTypeRef *)out_private_key);
The full code handles duplicate items in which case attributes are updated. Following the successful import of the cert and key to the keychain, I attempt to retrieve the identity with the following:
SecIdentityRef identity = NULL;
CFDictionaryRef query = NULL;
const void *query_keys[] = {
kSecClass,
kSecReturnRef,
// kSecAttrSerialNumber,
// kSecAttrLabel
kSecMatchLimit
};
const void *query_values[] = {
kSecClassIdentity,
kCFBooleanTrue,
// cert_serial_data,
// cert_label_ref
kSecMatchLimitAll
};
query = CFDictionaryCreate(
cf_alloc,
query_keys,
query_values,
3,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
OSStatus identity_status = SecItemCopyMatching(query, (CFTypeRef *)&identity);
I have attempted using various search parameters related to the label and the serial of the certificate. Based on other forum post suggestions I have also tried expanding the search to kSecMatchLimitAll to get back ANY stored kSecClassIdentity and all variations returned OSStatus of -25300 (errSecItemNotFound). Once I am able to retrieve the SecIdentityRef, my understanding is that I can add it to the following during creation of the socket:
nw_protocol_options_t tls_options = nw_tls_create_options();
sec_protocol_options_t sec_options = nw_tls_copy_sec_protocol_options(tls_options);
sec_protocol_options_set_min_tls_protocol_version(sec_options, tls_protocol_version_TLSv12);
sec_protocol_options_set_max_tls_protocol_version(sec_options, tls_protocol_version_TLSv13);
sec_protocol_options_set_local_identity(sec_options, SecIdentityRef);
Am I missing some step that is required to create an identity from the certificate and private key? I have tested the cert/key pair and they connect properly when using the old deprecated SecItemImport and SecIdentityCreateWithCertificate (on our old macOS only implementation).
I will continue to dig through Apple documentation as well as more forum posts but I feel like I'm hitting a wall and missing something very obvious as this seems like a very common networking task. Thanks!
The provided links below are to the full code related to the work in progress iOS import functions:
Link to import function https://github.com/awslabs/aws-c-io/blob/cad8639ef0ea08ba3cc74b72cfc1c9866adbb7e5/source/darwin/darwin_pki_utils.c#L735
Link to private key import: https://github.com/awslabs/aws-c-io/blob/cad8639ef0ea08ba3cc74b72cfc1c9866adbb7e5/source/darwin/darwin_pki_utils.c#L561
Link to certificate import: https://github.com/awslabs/aws-c-io/blob/cad8639ef0ea08ba3cc74b72cfc1c9866adbb7e5/source/darwin/darwin_pki_utils.c#L398
We are having trouble with App Attest when built with different processors. We need to build an IPA to send to our testers. When the app is built using Intel processor, everything works. But when we built using a mac with processor M, them the App Attest process fails.
The error occurs in our backend while validating the attesation object. We are doing the validation as stated by this documentation: https://developer.apple.com/documentation/devicecheck/attestation-object-validation-guide
The process of validating the Attesation Object fails in the step 4, this one:
Obtain the value of the credCert extension with OID 1.2.840.113635.100.8.2, which is a DER-encoded ASN.1 sequence. Decode the sequence and extract the single octet string that it contains. Verify that the string equals nonce.
The problem is that the validation fails only when the app is built in a M processor machine.
In our server we do (using GO Lang) something like this:
if !bytes.Equal(nonce[:], unMarshalledCredCert.Bytes) {
// error
}
unMarshalledCredCert is the nonce extracted from the Attesation Object sent by the mobile application and nonce[:] is the nonce stored in our backend side cache.
What can this be?
On macOS OS updates/reboot, CryptoTokenKit extension doesn't get loaded automatically when the system boots back. It needs another reboot to get the extension loaded and working.
After update:
% security list-smartcards
<No smart cards>
.. and there is a crash for authorizationhosthelper.arm64 in keychain layer
Thread 2 Crashed:: Dispatch queue: com.apple.security.keychain-cache-queue
0 libdispatch.dylib 0x18e2e499c dispatch_channel_cancel + 12
1 Security 0x1914ccfd0 invocation function for block in Security::KeychainCore::StorageManager::tickleKeychain(Security::KeychainCore::KeychainImpl*) + 44
2 libdispatch.dylib 0x18e2ce3e8 _dispatch_client_callout + 20
3 libdispatch.dylib 0x18e2d18ec _dispatch_continuation_pop + 600
4 libdispatch.dylib 0x18e2e57f0 _dispatch_source_latch_and_call + 420
5 libdispatch.dylib 0x18e2e43b4 _dispatch_source_invoke + 832
6 libdispatch.dylib 0x18e2d5898 _dispatch_lane_serial_drain + 368
7 libdispatch.dylib 0x18e2d6544 _dispatch_lane_invoke + 380
8 libdispatch.dylib 0x18e2e12d0 _dispatch_root_queue_drain_deferred_wlh + 288
9 libdispatch.dylib 0x18e2e0b44 _dispatch_workloop_worker_thread + 404
10 libsystem_pthread.dylib 0x18e47b00c _pthread_wqthread + 288
11 libsystem_pthread.dylib 0x18e479d28 start_wqthread + 8
Opening the parent app bundle as a Login item does not help.
A reboot sometimes fixes it but this happens frequently and causes lot of enterprise endpoints not able to authenticate.
After reboot:
% security list-smartcards
com.foo.tech.mac-device-check.SecureEnclaveTokenExtension:700D6B7E8943B529569D9CC81AC6F930
Please provide and prioritize a permanent fix/workaround for this issue. We have already reported this issue with crash and sysdiagnose logs in FB13622281 earlier this year.
Hi
I want to create secIdentity from certificate & key.
I receive certificate from my server and I have private key of that.
My certificate is like this -----BEGIN CERTIFICATE-----\nMIIEyTC...jix0=\n-----END CERTIFICATE-----
And private key is like this -----BEGIN RSA PRIVATE KEY-----\nMIIEp...5KM=\n-----END RSA PRIVATE KEY-----\n
I am trying to create secIdentity by saving certificate and key in keychain, but I am getting -25300 as error.
To create the identity my code is like this.
func deleteCertificateAndKey(certLabel:String, keyTag:Data) -> Bool {
// Query for the certificate
let query: [String: Any] = [kSecClass as String: kSecClassCertificate,
kSecAttrLabel as String: certLabel]
// Attempt to delete the certificate
let certificateDeleteStatus = SecItemDelete(query as CFDictionary)
print("certificateDeleteStatus: \(certificateDeleteStatus)")
// if certificateDeleteStatus == errSecSuccess {
// print("Certificate Certificate deleted successfully.")
// } else {
// print("Failed to delete certificate Certificate. Error: \(certificateDeleteStatus)")
// return false
// }
//
// Query for the private key associated with the certificate
let keyQuery: [String: Any] = [
kSecClass as String: kSecClassKey,
kSecAttrApplicationTag as String: keyTag
]
// Attempt to delete the private key
let keyDeleteStatus = SecItemDelete(keyQuery as CFDictionary)
print("keyDeleteStatus: \(keyDeleteStatus)")
// if keyDeleteStatus == errSecSuccess {
// print("Private key associated with Key deleted successfully.")
// return true
// } else {
// print("Failed to delete private key for Key. Error: \(keyDeleteStatus)")
// return false
// }
return true;
}
func stripPemHeaders(_ pemString: String) -> String {
var result = pemString
//
result = result.replacingOccurrences(of: "-----BEGIN RSA PRIVATE KEY-----\n", with: "")
result = result.replacingOccurrences(of: "\n-----END RSA PRIVATE KEY-----\n", with: "")
//
result = result.replacingOccurrences(of: "-----BEGIN CERTIFICATE-----\n", with: "")
result = result.replacingOccurrences(of: "\n-----END CERTIFICATE-----", with: "")
return result
}
func loadIdentity(certificate: String, privateKey: String)-> SecIdentity? {
let strippedCertificate = stripPemHeaders(certificate)
print("strippedCertificate : \(strippedCertificate)")
guard let certData = Data(base64Encoded: strippedCertificate, options:NSData.Base64DecodingOptions.ignoreUnknownCharacters) else {
print("Unable to decode certificate PEM")
return nil
}
print("certData: \(certData)")
// Create certificate object
guard let cert = SecCertificateCreateWithData(kCFAllocatorDefault, certData as CFData) else {
print("Unable to create certificate")
return nil
}
let addCertQuery: [String: Any] = [kSecClass as String: kSecClassCertificate,
kSecValueRef as String: cert,
kSecAttrLabel as String: "shahanshahAlam"]
let tag = "fedvfdvjjkdf-tag".data(using: .utf8)!
_ = deleteCertificateAndKey(certLabel: "shahanshahAlam",keyTag: tag )
// print("deleteStatus finished with status: \(deleteStatus)")
let certAddStatus = SecItemAdd(addCertQuery as CFDictionary, nil)
print("certAddStatus finished with status: \(certAddStatus)")
let strippedPrivateKey = stripPemHeaders(privateKey)
print("strippedPrivateKey : \(strippedPrivateKey)")
guard let pemKeyData = Data(base64Encoded: strippedPrivateKey, options:NSData.Base64DecodingOptions.ignoreUnknownCharacters) else {
print("Error: couldn't parse the privateKeyString, pls check if headers were removed: \(privateKey)")
return nil
}
print("pemKeyData finished with status: \(pemKeyData)")
let sizeInBits = pemKeyData.count * 8
let keyDict: [CFString: Any] = [
kSecAttrKeyType: kSecAttrKeyTypeRSA,
kSecAttrKeyClass: kSecAttrKeyClassPrivate,
kSecAttrKeySizeInBits: NSNumber(value: sizeInBits),
kSecReturnPersistentRef: true
]
var error: Unmanaged<CFError>?
guard let key = SecKeyCreateWithData(pemKeyData as CFData, keyDict as CFDictionary, &error) else {
print("Failed creating a Certificate from data \(error.debugDescription)")
return nil
}
let addKeyQuery: [String: Any] = [
kSecClass as String: kSecClassKey,
kSecAttrIsPermanent as String: true,
kSecValueRef as String: key,
kSecAttrApplicationTag as String: tag
]
let privKeyAddStatus = SecItemAdd(addKeyQuery as CFDictionary, nil)
print("privKeyAddStatus status finished with status: \(privKeyAddStatus)")
// query for all avaiable identities
let getIdentityQuery = [
kSecClass : kSecClassIdentity,
// kSecReturnData : true,
// kSecReturnAttributes : true,
kSecReturnRef : true,
kSecAttrApplicationTag as String: tag,
kSecMatchLimit : kSecMatchLimitAll
] as CFDictionary
var identityItem: CFTypeRef?
let status = SecItemCopyMatching(getIdentityQuery , &identityItem)
print("identityItem finished with status: \(String(describing: identityItem))")
print("status finished with status: \(status)")
guard status == errSecSuccess else {
print("Unable to create identity")
return nil
}
return (identityItem as! SecIdentity);
}
How can I fix that.
SecKeychain API has been declared deprecated a long time ago.
Do people from Apple or developers have a rough idea when this API will be definitely removed?
One year from now? More? Less?
Hi,
I'm writing a sandboxed Daemon that I register from my sandboxed application via SMAppService.
The registration is successful, and the daemon is called based on logs.
However when I'm trying to save a keychain item into the keychain, I see entries like this in the logs:
(Security) SecItemAdd
[com.apple.securityd:atomicfile] create /Library/Keychains/System.keychain.sb-1c133873-RPL9wo: Operation not permitted
[com.apple.securityd:security_exception] UNIX error exception: 1
[com.apple.securityd:security_exception] CSSM Exception: 100001 UNIX[Operation not permitted]
[com.apple.securityd:security_exception] CSSM Exception: 100001 UNIX[Operation not permitted]
I'm attempting to create the item with the regular SecItemAdd function call:
var query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrLabel as String: "[redacted string]",
kSecAttrAccount as String: "[redacted string]",
kSecAttrService as String: "[redacted string]",
kSecValueData as String: secretData
]
SecItemAdd(query as CFDictionary, nil)
I'm guessing this is because the System keychain is outside of the sandbox for the daemon.
Is there a way to create items for the System Keychain from a sandboxed daemon?
I am trying to make https request in swift, with identity created from certificate and key. My code look like this
To create the identity.
func loadIdentity(certificate: String, privateKey: String)-> SecIdentity? {
guard let certData = Data(base64Encoded: certificate, options:NSData.Base64DecodingOptions.ignoreUnknownCharacters) else {
print("Unable to decode certificate PEM")
return nil
}
guard let cert = SecCertificateCreateWithData(kCFAllocatorDefault, certData as CFData) else {
return nil
}
let addCertQuery: [String: Any] = [kSecClass as String: kSecClassCertificate,
kSecValueRef as String: cert,
kSecAttrLabel as String: "certificateLabel"]
let tag = "fedvfdvdf-tag".data(using: .utf8)!
_ = deleteCertificateAndKey(certLabel: "certificateLabel",keyTag: tag )
let certAddStatus = SecItemAdd(addCertQuery as CFDictionary, nil)
guard let pemKeyData = Data(base64Encoded: privateKey, options:NSData.Base64DecodingOptions.ignoreUnknownCharacters) else {
return nil
}
let sizeInBits = pemKeyData.count * 8
let keyDict: [CFString: Any] = [
kSecAttrKeyType: kSecAttrKeyTypeRSA,
kSecAttrKeyClass: kSecAttrKeyClassPrivate,
kSecAttrKeySizeInBits: NSNumber(value: sizeInBits),
kSecReturnPersistentRef: true
]
var error: Unmanaged<CFError>?
guard let key = SecKeyCreateWithData(pemKeyData as CFData, keyDict as CFDictionary, &error) else {
return nil
}
let addKeyQuery: [String: Any] = [
kSecClass as String: kSecClassKey,
kSecAttrIsPermanent as String: true,
kSecValueRef as String: key,
kSecAttrApplicationTag as String: tag
]
let privKeyAddStatus = SecItemAdd(addKeyQuery as CFDictionary, nil)
let getIdentityQuery = [
kSecClass : kSecClassIdentity,
kSecReturnData : true,
kSecReturnAttributes : true,
kSecReturnRef : true,
kSecMatchLimit : kSecMatchLimitAll
] as CFDictionary
var identityItem: CFTypeRef?
let status = SecItemCopyMatching(getIdentityQuery , &identityItem)
print("identityItem finished with status: \(String(describing: identityItem))")
print("status finished with status: \(status)")
guard status == errSecSuccess else {
print("Unable to create identity")
return nil
}
return (identityItem as! SecIdentity);
}
o make api request. Code is breaking in this function, around this lines let task = session.dataTask(with: request) { (data, response, error) in and let session = URLSession(configuration: .default, delegate: URLSessionPinningDelegate(identity: identity), delegateQueue: nil) For testing I removed identity and just used default URLSession, and request start giving response (although it was 401 but it was not crashing), so my guess is error is because of URLSession.
func makeAzureRequest(scopeId:String, registrationId:String, key:String, certificate:String, provisionHost:String, fileNameWithFolder:String, modelId:String, completion: @escaping (Result<String, Error>) -> Void ) throws {
guard let identity = loadIdentity(certificate: certificate, privateKey: key) else {
throw NSError(domain: "", code: -1, userInfo: [NSLocalizedDescriptionKey: "Unable to create identity"])
}
let session = URLSession(configuration: .default, delegate: URLSessionPinningDelegate(identity: identity), delegateQueue: nil)
print("session: \(session)")
guard let url = URL(string: "https://global.azure-devices-provisioning.net/\(scopeId)/registrations/\(registrationId)/register?api-version=2021-06-01") else {
throw NSError(domain: "", code: -1, userInfo: [NSLocalizedDescriptionKey: "Invalid URL"])
}
var request = URLRequest(url: url)
request.httpMethod = "PUT"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue("utf-8", forHTTPHeaderField: "Content-Encoding")
let body = ["registrationId": registrationId]
request.httpBody = try? JSONSerialization.data(withJSONObject: body, options: [])
let task = session.dataTask(with: request) { (data, response, error) in
if let error = error {
completion(.failure(error))
} else if let data = data, let responseString = String(data: data, encoding: .utf8) {
completion(.success(responseString))
}else {
completion(.failure(NSError(domain: "", code: -1, userInfo: [NSLocalizedDescriptionKey: "Unknown error occurred"])))
}
}
task.resume()
}
to call function where api function is triggered.
@objc(AzureProvisionWithCertificate)
class AzureProvisionWithCertificate: NSObject {
@objc(provisionAndUploadFile:withRegistrationId:withKey:withCertificate:withProvisionHost:withFileNameWithFolder:withModelId:withResolver:withRejecter:)
func provisionAndUploadFile(scopeId:String, registrationId:String, key:String, certificate:String, provisionHost:String, fileNameWithFolder:String, modelId:String, resolve:@escaping RCTPromiseResolveBlock, reject:@escaping RCTPromiseRejectBlock) -> Void {
print("starting swift code here")
do {
try makeAzureRequest(scopeId: scopeId, registrationId:registrationId, key: key, certificate: certificate, provisionHost: provisionHost, fileNameWithFolder: fileNameWithFolder, modelId: modelId) { result in
switch result {
case .success(let responseString):
// Handle success, perhaps update the UI or process the response
case .failure(let error):
// Handle failure, perhaps show an error message to the user
}
}
} catch {
print("Failed to initiate request: (error.localizedDescription)")
}
}
}
And URLSessionPinningDelegate class look like this to SSL pinning.
import Foundation
import Security
class URLSessionPinningDelegate: NSObject, URLSessionDelegate {
var identity: SecIdentity
init(identity: SecIdentity) {
self.identity = identity
}
func urlSession(_ session: URLSession,
didReceive challenge: URLAuthenticationChallenge,
completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodClientCertificate {
let credential = URLCredential(identity: self.identity,
certificates: nil,
persistence: .forSession)
completionHandler(.useCredential, credential)
} else {
completionHandler(.performDefaultHandling, nil)
}
}
}
Hi,
I'm exploring ways to control wide range of peripherals such as Keyboard, Mouse, Monitor, Router etc form connecting to mac device. I was able to easily achieve the external storage mount and unmount but having trouble understanding on how can I control which peripheral is allowed to connect to mac.
Can you help me understand what events and processes in ES can be used to control them? Is ES app the correct approach for this or something else like IOKit framework?