Security

RSS for tag

Secure 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

How can I get the public key from SecCertificate? And a few other things
Hi, I'm trying to achieve the following OpenSSL workflow in Swift. I have this intermediate certificate from Let's encrypt and I want to extract the public key from it and then hash it with SHA-256 and finally encide it in base64. The OpenSSL commands that achieve this look like this: openssl x509 -in isrgrootx1.pem -pubkey -noout > publickey.pem openssl rsa -pubin -in publickey.pem -outform der | openssl dgst -sha256 -binary | openssl enc -base64 I've tried Security, CommonCrypto, CryptoKit frameworks with no success. I was able to get the public key out of the certificate but its PEM representation seems to slightly differ from what I get with OpenSSL. At the beginning of the public jet, the OpenSSL version has a string that is not present on what I get with Swift but the rest is the same. This is the Swift code to use: import Foundation import Security import CommonCrypto // Step 1: Extract public key from the certificate func extractPublicKey(from certificate: SecCertificate) -> SecKey? { // Extract public key from the certificate var publicKey: SecKey? if let publicKeyRef = SecCertificateCopyKey(certificate) { publicKey = publicKeyRef } return publicKey } // Step 2: Calculate SHA-256 hash of the public key func calculateSHA256(of data: Data) -> Data { var hash = [UInt8](repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH)) data.withUnsafeBytes { _ = CC_SHA256($0.baseAddress, CC_LONG(data.count), &hash) } return Data(hash) } // Step 3: Encode data as base64 func base64EncodedString(from data: Data) -> String { return data.base64EncodedString() } // Step 4: Main function to perform all steps func processCertificate(certificate: SecCertificate) { // Step 1: Extract public key guard let publicKey = extractPublicKey(from: certificate) else { return } // Step 2: Export public key as data guard let publicKeyData = SecKeyCopyExternalRepresentation(publicKey, nil) as Data? else { print("Failed to export public key data") return } // Step 3: Calculate SHA-256 hash of the public key let sha256Hash = calculateSHA256(of: publicKeyData) // Step 4: Encode SHA-256 hash as base64 let base64EncodedHash = base64EncodedString(from: sha256Hash) print("SHA-256 hash of public key (base64 encoded): \(base64EncodedHash)") } This is the Public Key I get with OpenSSL: -----BEGIN PUBLIC KEY----- MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAregkc/QUN/ObnitXKByHvty33ziQjG485legePd1wqL+9Wpu9gBPKNveaIZsRJO2sWP9FBJrvx/S6jGbIX7RMzy6SPXded+zuP8S8SGaS8GKhnFpSmZmbI9+PHC/rSkiBvPkwOaAruJLj7eZfpQDn9NHl3yZSCNT6DiuTwpvgy7RSVeMgHS22i/QOI17A3AhG3XyMDz6j67d2mOr6xZPwo4RS37PC+j/tXcu9LJ7SuBMEiUMcI0DKaDhUyTsE9nuGb8Qs0qMP4mjYVHerIcHlPRjcewu4m9bmIHhiVw0eWx27zuQYnnm26SaLybF0BDhDt7ZEI4W+7f3qPfH5QIHmI82CJXn4jeWDTZ1nvsOcrEdm7wD+UkF2IHdBbQq1kHprAF2lQoP2N/VvRIfNS8oF2zSmMGoCWR3bkc3us6sWV5onX9y1onFBkEpPlk+3Sb1JMkRp1qjTEAfRqGZtac6UW6GO559cqcSBXhZ7T5ReBULA4+N0C8Fsj57ShxLcwUS/Mbq4FATfEOTdLPKdOeOHwEI0DDUW3E2tAe6wTAwXEi3gjuYpn1giqKjKYLMur2DBBuigwNBodYF8RvCtvCofIY7RqhIKojcdpp2vx9qpT0Zj+s482TeyCsNCij/99viFULUItAnXeF5/hjncIitTubZizrG3SdRbv+8ZPUzQ08CAwEAAQ== -----END PUBLIC KEY----- and this is what I get with Swift: -----BEGIN PUBLIC KEY----- MIICCgKCAgEAregkc/QUN/ObnitXKByHvty33ziQjG485legePd1wqL+9Wpu9gBPKNveaIZsRJO2sWP9FBJrvx/S6jGbIX7RMzy6SPXded+zuP8S8SGaS8GKhnFpSmZmbI9+PHC/rSkiBvPkwOaAruJLj7eZfpQDn9NHl3yZSCNT6DiuTwpvgy7RSVeMgHS22i/QOI17A3AhG3XyMDz6j67d2mOr6xZPwo4RS37PC+j/tXcu9LJ7SuBMEiUMcI0DKaDhUyTsE9nuGb8Qs0qMP4mjYVHerIcHlPRjcewu4m9bmIHhiVw0eWx27zuQYnnm26SaLybF0BDhDt7ZEI4W+7f3qPfH5QIHmI82CJXn4jeWDTZ1nvsOcrEdm7wD+UkF2IHdBbQq1kHprAF2lQoP2N/VvRIfNS8oF2zSmMGoCWR3bkc3us6sWV5onX9y1onFBkEpPlk+3Sb1JMkRp1qjTEAfRqGZtac6UW6GO559cqcSBXhZ7T5ReBULA4+N0C8Fsj57ShxLcwUS/Mbq4FATfEOTdLPKdOeOHwEI0DDUW3E2tAe6wTAwXEi3gjuYpn1giqKjKYLMur2DBBuigwNBodYF8RvCtvCofIY7RqhIKojcdpp2vx9qpT0Zj+s482TeyCsNCij/99viFULUItAnXeF5/hjncIitTubZizrG3SdRbv+8ZPUzQ08CAwEAAQ== -----END PUBLIC KEY----- Interestingly, if I use the Swift version of the Public Key I get and then run the second command I still get the correct final result. Unfortunately in Swift I don't get the correct final result. I suspect it must be something about headers since I was able to get the correct output on OpenSSL with the public key I got using the Swift. Any ideas?
3
0
876
Apr ’24
Why are EC signatures being padded?
Running through the tutorial on how to sign data using security.framework, I was trying to understand the format Apple is using & wanting for signatures (as this isn't documented anywhere): https://developer.apple.com/documentation/security/certificate_key_and_trust_services/keys/signing_and_verifying?language=objc I've learned the format of the signatures are just ASN.1 objects, with EC signatures being a sequence of the R and S coordinates as ASN.1 integers. However, I am noticing when using SecKeyCreateSignature that either the R or S value will always be prepended with an extra byte. For example: 30 45 02 20 66 B7 4C FB FC A0 26 E9 42 50 E8 B4 E3 A2 99 F1 8B A6 93 31 33 E8 7B 6F 95 D7 28 77 52 41 CC 28 02 21 00 E2 01 CB A1 4C AD 42 20 A2 ^^ why is this here? 66 A5 94 F7 B2 2F 96 13 A8 C5 8B 35 C8 D5 72 A0 3D 41 81 90 3D 5A 91 This is a ASN.1 sequence, first is a 32-byte integer and second is a 33-byte integer. Why is that 00 byte being prepended to the integer? Why is it sometimes the R and sometimes the S? Removing it causes SecKeyVerifySignature to fail, so obviously it's required, but I need to know the logic here as I'm having to hand-craft these ASN.1 objects as all I have are the raw R and S values.
2
0
448
Apr ’24
iOS Device Support Keylogger
Hello, I recently ran a virus/malware scan on my dev machine using ClamAV, this was run via macOS Terminal using the 'clamscan' function. Everything came back okay except a keylogger in the ProVideo Framework for physical iOS Test Devices. Please see below for 'clamscan' output: /Users/username/Library/Developer/Xcode/iOS DeviceSupport/iPad8,11 17.4 (21E219)/Symbols/System/Library/PrivateFrameworks/ProVideo.framework/ProVideo: Unix.Keylogger.Macos-10023932-0 FOUND My understanding is that '/Library/Developer/Xcode/iOS DeviceSupport/' is where Xcode keeps the files related to physical test devices that are required for debug. There were 3 Instances of this keylogger, all of which corresponded to physical devices I own and iOS Versions that I have installed / were installed. Can anyone verify if 'Unix.Keylogger.Macos-10023932-0' is a valid file that ClamAV is incorrectly detecting as malicious? If it is a valid debug file provided by Apple, it seems strange that it's located in the ProVideo Framework. I couldn't find any documentation online about this so any information would be appreciated. At this stage I have deleted the contents of '/Library/Developer/Xcode/iOS DeviceSupport/', my understanding is that these symbols are only transferred to the system when I test software via Xcode on a physical device and will not reproduce until I do that again. To me it's unclear if perhaps this keylogger is present on my iOS Device and is being transferred to the Mac via Xcode? Or somehow it is just appearing in this folder? Thanks!
2
0
886
Apr ’24
Platform/App Security model: clarity on code signing
Hi, I'm wondering if we'd want to improve the clarity of the Apple Platform Security guide (dated 2022) on the iOS app security model (page 99), as edits might have lost the intended structure of the sentence (although I might be reading it wrong). Current text: At runtime, code signature checks that all executable memory pages are made as they are loaded to help ensure that an app hasn’t been modified since it was installed or last updated. Possible rephrasing: At runtime, iOS checks code signature on all executable memory pages as they are loaded to help ensure that an app hasn’t been modified since it was installed or last updated.
1
0
378
Apr ’24
SecPKCS12Import not returning certificates when there’s no identity
I have a .p12 file which contains two certificates, but no identities. When attempting to use SecPKCS12Import against it it returns a success code, but the CFArray is empty: func testParsingCert() throws { let bundle = Bundle(for: Self.self) let certificateURL = bundle.url(forResource: TestConstants.SERVER_CERTIFICATE_NAME, withExtension: TestConstants.CERTIFICATE_FILE_EXTENSION)! let certificateData = try! Data(contentsOf: certificateURL) var importResult: CFArray? = nil let err = SecPKCS12Import( certificateData as NSData, [kSecImportExportPassphrase as String: TestConstants.DEFAULT_CERT_PASSWORD] as NSDictionary, &importResult ) guard err == errSecSuccess else { throw NSError(domain: NSOSStatusErrorDomain, code: Int(err), userInfo: nil) } let identityDictionaries = importResult as! [[String:Any]] var chain: CFArray chain = identityDictionaries[0][kSecImportItemCertChain as String] as! CFArray print(chain) } Above code fails with Test Case '-[TAKTrackerTests.CertificateSigningRequestTests testParsingCert]' started. Swift/ContiguousArrayBuffer.swift:600: Fatal error: Index out of range as the identityDictionaries result contains no results (nor does importResult) The specific use case for this is that users can do Certificate Enrollment against a server with a self-signed certificate, so they need to be able to upload the trust store prior to connecting for identities.
2
0
446
Apr ’24
Keychain file is suddenly created on root-level instead of user-level
Hi, I have met with a rather interesting phenomenon today and I couldn't figure out the reason. As part of a script, I import certificates and for that I create a designated keychain: security create-keychain -p "" $KEYCHAIN_NAME.keychain-db This has so far been creating the keychain at the expected location, Users/my-user/Library/Keychains/$KEYCHAIN_NAME.keychain-db. However, I have noticed that since yesterday, my script has been failing with a security: SecKeychainCreate XXXXXXXXX.keychain-db: UNIX[Permission denied] error. I kept investigating and noticed that the same script as given above, now tries to create the keychain on the /Library/Keychains/$KEYCHAIN_NAME.keychain-db path (the same path where System.keychain is located). I confirmed this in two ways: running the command with sudo no longer resulted in above UNIX error, instead created it next to the System keychain. locally, I tried to create a keychain with an absolute path, like this: security create-keychain -p 1234 "/Library/Keychains/new.keychain" and got back the same UNIX[Permission denied] error. I tried to poke around in the man page for security and search online, but found nothing that would mention the default path changing for the security command (because it must be some setting for security, given that a simple XXXX.keychain would be created at ~/Library/Keychain/***.keychain, whichever folder I execute the command from. Thanks in advance for any advice!
4
0
626
Apr ’24
TLS For Accessory Developers: does it work for non-local network?
I'm following the approach in https://developer.apple.com/forums/thread/703234 section "Doing Even Better: Proper Security". My question is: does it work if the accessory is not in the local network (i.e. out there on the Internet with an IP address) ? I tried and: SecTrustEvaluateWithError(trust, nil) returns true, but TLS still fails: ATS failed system trust Connection 1: system TLS Trust evaluation failed(-9802) <snip> Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made." UserInfo={NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, Here is my code : var err = SecTrustSetPolicies(trust, SecPolicyCreateBasicX509()) os_log("SecTrustSetPolicies returns \(err)") err = SecTrustSetAnchorCertificates(trust, [self.myCA] as NSArray) os_log("SecTrustSetAnchorCertificates returns \(err)") err = SecTrustSetAnchorCertificatesOnly(trust, true) os_log("SecTrustSetAnchorCertificatesOnly returns \(err)") // check the trust object let evalResult = SecTrustEvaluateWithError(trust, nil) os_log("SecTrust eval result: \(evalResult)") // create a credential with accepted server trust. let credential = URLCredential(trust: trust) completionHandler(.useCredential, credential) the logs are: SecTrustSetPolicies returns 0 SecTrustSetAnchorCertificates returns 0 SecTrustSetAnchorCertificatesOnly returns 0 SecTrust eval result: true Did I do anything wrong? or is it not supported outside the local network? Thanks.
2
0
666
Apr ’24
SecItemCopyMatching returns a secure enclave a ref after migrating to a new iPhone 15?
I have an app that creates a private key in the secure enclave with a unique alias. It is created with the kSecAttrTokenIDSecureEnclave flag. According to the docs, such private keys should never leave the enclave under any circumstances and definitely not restored on new devices. After migrating to a new iPhone 15 the app does not offer to create a new private key in the enclave, but rather it is able to find the unique alias of the private key in the new phone. i.e. as if it found the private key on the new phone's secure enclave I believe (/hope) that in practice the object I get in the new iPhone from SecItemCopyMatching is not usable. I assume this is a bug that should be fixed by apple? How can I detect that this SecItemCopyMatching result is stale so I can ignore it and prompt the user to create a new keypair on the secure enclave? Thanks
2
0
713
Apr ’24
Privacy Manifest Required Reasons: mach_absolute_time used for random number seed
We are using mach_absolute_time to determine the number of CPU cycles in our app, and from that, we are using it to seed a random number generator. From this random number generator, we are getting a series of random numbers and combining it with other random numbers from another generator not seeded via mach_abolute_time. This combined random number is being sent off device as a unique ID for authentication purposes. I've read through the required reasons for using this API, and I am not sure if it falls under the acceptable use cases. My gut-feeling is that it does not. The following reasons are what Apple lists as acceptable reasons for this API: 35F9.1 Declare this reason to access the system boot time in order to measure the amount of time that has elapsed between events that occurred within the app or to perform calculations to enable timers. Information accessed for this reason, or any derived information, may not be sent off-device. There is an exception for information about the amount of time that has elapsed between events that occurred within the app, which may be sent off-device. 8FFB.1 Declare this reason to access the system boot time to calculate absolute timestamps for events that occurred within your app, such as events related to the UIKit or AVFAudio frameworks. Absolute timestamps for events that occurred within your app may be sent off-device. System boot time accessed for this reason, or any other information derived from system boot time, may not be sent off-device. 3D61.1 Declare this reason to include system boot time information in an optional bug report that the person using the device chooses to submit. The system boot time information must be prominently displayed to the person as part of the report. Information accessed for this reason, or any derived information, may be sent off-device only after the user affirmatively chooses to submit the specific bug report including system boot time information, and only for the purpose of investigating or responding to the bug report. Would anybody be able to confirm that this usage is allowed or if we will need to change it to be in accordance with Apple's new policies regarding the usage of this API? Thanks
0
0
756
Apr ’24
Guidance on Authorization Plugins
From what I've gathered from the (rather old) documentation and sample projects on Authorization Plugins, I understand that those can be used to extend the macOS authorization services with custom (and possibly quite complex) requirements for privilege management. During my testing, I found it to be technically possible to allow a normal (non-admin) user to perform some actions that they normally couldn't by leveraging plugin mechanisms. For instance, if I alter the class of system.preferences.network from user to evaluate-mechanisms I can make it so my custom plugin decides which user is actually able to make modifications to the system through the Network settings pane. However, I've noticed that if I leave the actual authentication to the built-in authentication mechanism and perform my validations after that, the user will face a rather odd message: Clearly, even though this seems to work like I'd expected it to, there's something strange going on here. So my question is, what can I actually achieve with authorization plugins in terms of managing system privileges, and what should I use it for? Are there any alternatives I could consider? And if so, could they offer me the flexibility that implementing my own custom logic as a plugin does? I'm not sure what the best practices and recommendations are in terms of both security and usability regarding these plugins, and would very much appreciate some pointers in the right direction.
3
0
473
Apr ’24
Secure Enclave security
Hello! the other day I had troubles with running the application to interact with the Secure Enclave. (https://developer.apple.com/forums/thread/748611?page=1#783968022) While my program is running perfectly fine now, I still have questions regarding its security. QUESTIONS: Is there any functionality just with the public key to get an evidence of a corresponding private key to be protected by the Secure Enclave without showing the source code? Even with the most recent update of iOS 17.4, there is still no way to directly access the functionality of a Secure Element itself, is that right? So far I found a function SecureElementPass, and it seems like it’s the only interaction possible. What is the difference between using Security API and Apple CryptoKit? I heard some were saying it the matter of habit and device support, but I still would like to hear an opinion of a professional. Any information regarding that will be helpful. Thank you in advance for your time and effort!
3
0
904
Aug ’24
Keychain operations failed with XCodebuild, but succeed with Xcode.app
I'm having issue with keychain access for my SWIFT project. The keychain operations succeed while I run the test with Xcode.app (GUI), but failed when I run the test through command line tool xcodebuild. I assume I did something wrong with the environment. Is there any suggestion or instruction about how should I setup for the xcodebuild command line tool? Here is my unit test. static func run_shell(_ command: String) -> String { let task = Process() let pipe = Pipe() task.standardOutput = pipe task.standardError = pipe task.arguments = ["-c", command] task.launchPath = "/bin/zsh" task.standardInput = nil task.launch() let data = pipe.fileHandleForReading.readDataToEndOfFile() let output = String(data: data, encoding: .utf8)! return output } func testSecurityDefaultKeychain() throws { print(TLSContextTests.run_shell("security default-keychain")); } Other things I have tried: I got the same result if I use SecKeychainCopyDefault instead of the security command. If I directly run security command in my terminal, it worked fine. > security default-keychain "/Users/runner/Library/Keychains/login.keychain-db" I also tried with sudo xcodebuild & chmod a+x xcodebuild to make sure the tool has permission to access keychain, but it was not helpful. I had a post about the same issue a month ago. At that time I thought it was an issue for CI environment only. However, it turns out it was the xcodebuild. https://forums.developer.apple.com/forums/thread/747794
2
0
480
Apr ’24
Mutual TLS authentication using PIV card fails to send the entire client cert chain
My organization is using mutual TLS authentication for HTTPS, with PIV cards storing the certs. We observe that some OS X devices send only the leaf certs when establishing the mTLS connection, whereas others send the entire chain. We cannot validate the leaf cert without the intermediate cert, so those clients are rejected. What drives the decision whether to send the whole chain, vs the leaf cert only? For more details, and some things we observed. The PIV cards are US DoD CAC cards: https://www.cac.mil/common-access-card/ The client cert chain on the card looks like this: Leaf client cert, CN=LastName.Name Intermediate cert, CN=DOD ID CA-70 "Root" cert, CN=DoD Root CA 6 through 8.: Additional interoperability certs. Our system is set up to trust the "root" cert CN=DoD Root CA 6. Neither the leaf cert, nor other certs in the chain are trusted by Apple Keychain Trust Store by default. We find that most laptops will send the entire chain, 1 through 8, when establishing the mTLS connection with our servers. This allows us to validate them correctly. On a subset of OS X devices, Google Chrome will only send the leaf chain. This happens even when we use exact same PIV card, and exact same PIV reader as on working laptops. Safari will not send any cert at all. We found that if we explicitly add the CN=DoD Root CA 6 to the Apple Trust Store, Google Chrome and Safari will start sending a short chain, containing only certs 1 through 3. This allows the server to validate them. When we remove it from Trust Store, Chrome is back to sending only leaf, but Safari will not even send the leaf. Again, this only happens on some laptops; on most of the laptops, both Safari and Google Chrome will send the entire chain, regardless of whatever is set up in Trust Store. My suspicion is that for some reason, on those laptops, Safari will not send the client certs that OS X doesn't trust. This makes sense, but this is not the behavior we want. We want the same behavior on the working laptops, which is to send the whole chain. All of our laptops are on OS X 14.4
0
0
601
Mar ’24