1- // certificates/certificates.swift
1+ // Sources/prostore/ certificates/certificates.swift
22// Put this file under Sources/prostore/certificates/
33
44import Foundation
@@ -16,7 +16,6 @@ public enum CertificateError: Error {
1616 case p12ImportFailed( OSStatus )
1717 case identityExtractionFailed
1818 case certExtractionFailed
19- case cmsDecodeFailed( OSStatus )
2019 case noCertsInProvision
2120 case publicKeyExportFailed( OSStatus )
2221 case unsupportedPlatform
@@ -37,27 +36,20 @@ public final class CertificatesManager {
3736 }
3837 var cfErr : Unmanaged < CFError > ?
3938 guard let keyData = SecKeyCopyExternalRepresentation ( secKey, & cfErr) as Data ? else {
40- if let err = cfErr? . takeRetainedValue ( ) {
41- // fixed: cast to OSStatus correctly
42- throw CertificateError . publicKeyExportFailed ( OSStatus ( ( err as NSError ) . code) )
39+ if let cfError = cfErr? . takeRetainedValue ( ) {
40+ // Safely cast CFError -> NSError if possible, otherwise fallback to -1
41+ let nsError = cfError as? NSError
42+ throw CertificateError . publicKeyExportFailed ( OSStatus ( nsError? . code ?? - 1 ) )
4343 } else {
4444 throw CertificateError . publicKeyExportFailed ( - 1 )
4545 }
4646 }
4747 return keyData
4848 }
4949
50- // Try to extract SecCertificate objects from a .mobileprovision Data blob.
51- // Strategy:
52- // - If CoreServices/CMSDecoder APIs are available, use them (preferred).
53- // - Otherwise, if OpenSSL is available via SPM, parse with OpenSSL and convert X509 -> SecCertificate.
50+ // Parse PKCS#7 (DER) from the mobileprovision using OpenSSL functions,
51+ // convert X509 -> DER -> SecCertificate
5452 private static func certificatesFromMobileProvision( _ data: Data ) throws -> [ SecCertificate ] {
55- // We'll parse PKCS#7 (DER) from the mobileprovision using OpenSSL functions.
56- // Steps:
57- // - create BIO from memory
58- // - d2i_PKCS7_bio to parse
59- // - PKCS7_get0_signers to get stack of X509
60- // - convert each X509 to DER (i2d_X509) and then to SecCertificate
6153 var certs : [ SecCertificate ] = [ ]
6254
6355 // Create BIO from data
@@ -76,22 +68,29 @@ public final class CertificatesManager {
7668 }
7769 defer { PKCS7_free ( p7) }
7870
79- // Get signers (stack of X509). PKCS7_get0_signers often returns a newly allocated stack.
71+ // Get signers (stack of X509). PKCS7_get0_signers often returns a newly allocated stack pointer .
8072 guard let signers = PKCS7_get0_signers ( p7, nil , 0 ) else {
8173 throw CertificateError . noCertsInProvision
8274 }
83- // iterate
84- let count = Int ( sk_X509_num ( signers) )
75+
76+ // Use OPENSSL_sk_* helpers (macros may be unavailable)
77+ let rawStackPtr = UnsafeMutableRawPointer ( signers)
78+ let count = Int ( OPENSSL_sk_num ( rawStackPtr) )
8579 for i in 0 ..< count {
86- guard let x509 = sk_X509_value ( signers, i) else { continue }
80+ // OPENSSL_sk_value returns UnsafeMutableRawPointer?
81+ guard let val = OPENSSL_sk_value ( rawStackPtr, i) else { continue }
82+ // Interpret the pointer as X509*
83+ let x509Ptr = val. assumingMemoryBound ( to: X509 . self)
84+
8785 // convert X509 -> DER
8886 var derPtr : UnsafeMutablePointer < UInt8 > ? = nil
89- let derLen = i2d_X509 ( x509 , & derPtr)
87+ let derLen = i2d_X509 ( x509Ptr , & derPtr)
9088 guard derLen > 0 , let dptr = derPtr else { continue }
9189 // wrap into Data
9290 let derData = Data ( bytes: dptr, count: Int ( derLen) )
9391 // free OpenSSL buffer produced by i2d_X509
9492 OPENSSL_free ( dptr)
93+
9594 // create SecCertificate from DER
9695 if let secCert = SecCertificateCreateWithData ( nil , derData as CFData ) {
9796 certs. append ( secCert)
@@ -100,8 +99,10 @@ public final class CertificatesManager {
10099 continue
101100 }
102101 }
102+
103103 // free the signers stack
104- sk_X509_pop_free ( signers, X509_free)
104+ OPENSSL_sk_pop_free ( rawStackPtr, X509_free)
105+
105106 guard certs. count > 0 else { throw CertificateError . noCertsInProvision }
106107 return certs
107108 }
@@ -125,12 +126,11 @@ public final class CertificatesManager {
125126 return . failure( CertificateError . p12ImportFailed ( importStatus) )
126127 }
127128
128- // The import result contains kSecImportItemIdentity. It's safe to downcast to SecIdentity,
129- // but we'll be cautious and fail if not present.
130- guard let first = items. first,
131- let identity = first [ kSecImportItemIdentity as String ] as? SecIdentity else {
129+ // Force-cast to SecIdentity (import guarantees this key exists for valid PKCS12)
130+ guard let first = items. first else {
132131 return . failure( CertificateError . identityExtractionFailed)
133132 }
133+ let identity = first [ kSecImportItemIdentity as String ] as! SecIdentity
134134
135135 // 2) extract certificate from identity
136136 var certRef : SecCertificate ?
@@ -166,4 +166,4 @@ public final class CertificatesManager {
166166 return . failure( error)
167167 }
168168 }
169- }
169+ }
0 commit comments