Post

Replies

Boosts

Views

Created

SecKeychainItem cast to SecCertificate crashes
Hi, I'm building on macOS Ventura 13.0.1, usingApple Swift version 5.7.2 (swiftlang-5.7.2.135.5 clang-1400.0.29.51) and targetting .macOS(.v10_15). I'm experiencing a crash / exception (illegal hardware instruction) when trying to cast a SecKeychainItem into a SecCertificate. This should be safe according to the docs: A SecKeychainItem object for a certificate that is stored in a keychain can be safely cast to a SecCertificate for use with Certificate, Key, and Trust Services. I'm trying to load PKCS12 (PEM-wrapped) data to obtain a SecIdentity from the contained certificate. To do this I'm loading in an array of SecKeychainItems via SecItemImport. I can see the resulting output CFArray populated with 2 items as expected. The following is the resulting dump: ▿ Optional(<__NSArrayM 0x600001270210>( <cert(0x7f804f906fa0) s: Just a test certificate>, <SecCDSAKeyRef 0x6000012792f0: algorithm id: 1, class=1, algorithm=2a, usage=80000000 attrs=38> ) ) I extract the SecKeychainItem whose type is a certifcate by finding the item where CFGetTypeID($0) == SecCertificateGetTypeID(). The following is my code: private static func protection( _ passphrase: String ) -> SecItemImportExportKeyParameters { SecItemImportExportKeyParameters( version: UInt32(bitPattern: SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION), flags: .noAccessControl, passphrase: Unmanaged<AnyObject>.passUnretained(passphrase as AnyObject), alertTitle: nil, alertPrompt: nil, accessRef: nil, keyUsage: nil, keyAttributes: nil ) } static func load(pkcs12Data: Data, passphrase: String = "") throws -> SecIdentity { // setup the import parameters let data = pkcs12Data as CFData var protection = Self.protection(passphrase) var externalFormat: SecExternalFormat = .formatPEMSequence var externalItemType: SecExternalItemType = .itemTypeAggregate var result: CFArray? // import the results SecItemImport( data, nil, &externalFormat, &externalItemType, .pemArmour, &protection, nil, &result ) // cast results to an array of SecKeychainItems guard let items = result as? [SecKeychainItem] else { print("Failed to cast result to [SecKeychainItem]") fatalError() } // extract the certificate result guard let certItem = items.first(where: { CFGetTypeID($0) == SecCertificateGetTypeID() }) else { print("Failed to extract certItem from items") fatalError() } // force cast because SecKeychainItem cast will always succeed according to documentation // the next line crashes with the exception "illegal hardware instruction" print(certItem) let certificate = certItem as! SecCertificate print("Loading identity from cert:") var identity: SecIdentity? let identityImportStatus = SecIdentityCreateWithCertificate(nil, certificate, &identity) guard identityImportStatus == errSecSuccess, let identity = identity else { print("Failed to create identity. Status: \(identityImportStatus)") fatalError() } print("Loaded identity: \(identity)") return identity } I'd really appreciate any insight or help understanding why the cast (let certificate = certItem as! SecCertificate) causes an exception / crash? Am I doing something wrong here? How should I obtain the SecCertificate? Many thanks for reading this :)
2
0
829
Jan ’23