@@ -15,7 +15,6 @@ public enum CertificateError: Error {
1515 case noCertsInProvision
1616 case publicKeyExportFailed( OSStatus )
1717 case unsupportedPlatform
18- case opensslError( String )
1918}
2019
2120public final class CertificatesManager {
@@ -30,11 +29,11 @@ public final class CertificatesManager {
3029 guard let secKey = SecCertificateCopyKey ( cert) else {
3130 throw CertificateError . certExtractionFailed
3231 }
32+
3333 var cfErr : Unmanaged < CFError > ?
3434 guard let keyData = SecKeyCopyExternalRepresentation ( secKey, & cfErr) as Data ? else {
3535 if let cfError = cfErr? . takeRetainedValue ( ) {
36- // Fixed: Force cast CFError to NSError
37- let nsError = cfError as! NSError
36+ let nsError = cfError as NSError
3837 throw CertificateError . publicKeyExportFailed ( OSStatus ( nsError. code) )
3938 } else {
4039 throw CertificateError . publicKeyExportFailed ( - 1 )
@@ -43,67 +42,39 @@ public final class CertificatesManager {
4342 return keyData
4443 }
4544
46- // Parse PKCS#7 (DER) from the mobileprovision using OpenSSL functions ,
47- // convert X509 -> DER -> SecCertificate
45+ // Parse PKCS#7 (DER) from the mobileprovision using Security's CMSDecoder ,
46+ // convert to SecCertificate array (no OpenSSL required)
4847 private static func certificatesFromMobileProvision( _ data: Data ) throws -> [ SecCertificate ] {
49- var certs : [ SecCertificate ] = [ ]
50-
51- // Create BIO from data
52- let bio = data. withUnsafeBytes { ( ptr: UnsafeRawBufferPointer ) -> OpaquePointer ? in
53- guard let base = ptr. baseAddress else { return nil }
54- return BIO_new_mem_buf ( UnsafeMutableRawPointer ( mutating: base) , Int32 ( data. count) )
55- }
56-
57- guard let bioPtr = bio else {
58- throw CertificateError . opensslError ( " BIO_new_mem_buf failed " )
48+ // Create decoder
49+ var decoderOptional : CMSDecoder ?
50+ var status = CMSDecoderCreate ( & decoderOptional)
51+ guard status == errSecSuccess, let decoder = decoderOptional else {
52+ throw CertificateError . certExtractionFailed
5953 }
60- defer { BIO_free ( bioPtr) }
6154
62- guard let p7 = d2i_PKCS7_bio ( bioPtr, nil ) else {
63- throw CertificateError . opensslError ( " d2i_PKCS7_bio failed " )
55+ // Feed data into decoder
56+ let updateStatus : OSStatus = data. withUnsafeBytes { ( rawPtr: UnsafeRawBufferPointer ) in
57+ guard let base = rawPtr. baseAddress else { return errSecParam }
58+ return CMSDecoderUpdateMessage ( decoder, base. assumingMemoryBound ( to: UInt8 . self) , data. count)
6459 }
65- defer { PKCS7_free ( p7) }
66-
67- // Get signers (stack of X509). PKCS7_get0_signers often returns an allocated stack pointer.
68- guard let signers = PKCS7_get0_signers ( p7, nil , 0 ) else {
69- throw CertificateError . noCertsInProvision
60+ guard updateStatus == errSecSuccess else {
61+ throw CertificateError . certExtractionFailed
7062 }
7163
72- // Fixed: Proper cast for signers to OpaquePointer (assuming signers is UnsafeMutableRawPointer)
73- let stackPtr = OpaquePointer ( UnsafeMutableRawPointer ( signers) )
74-
75- // Use OPENSSL_sk_num and OPENSSL_sk_value with proper index types
76- let count = Int ( OPENSSL_sk_num ( stackPtr) )
77- for i in 0 ..< count {
78- guard let rawVal = OPENSSL_sk_value ( stackPtr, Int32 ( i) ) else { continue }
79- // rawVal is UnsafeMutableRawPointer; interpret as X509*
80- let x509Ptr = rawVal. assumingMemoryBound ( to: X509 . self)
81-
82- // convert X509 -> DER
83- var derPtr : UnsafeMutablePointer < UInt8 > ? = nil
84- let derLen = i2d_X509 ( x509Ptr, & derPtr)
85- guard derLen > 0 , let dptr = derPtr else { continue }
86- // wrap into Data
87- let derData = Data ( bytes: dptr, count: Int ( derLen) )
88- // free OpenSSL buffer produced by i2d_X509
89- OPENSSL_free ( dptr)
90-
91- // create SecCertificate from DER
92- if let secCert = SecCertificateCreateWithData ( nil , derData as CFData ) {
93- certs. append ( secCert)
94- } else {
95- // skip if cannot create
96- continue
97- }
64+ // Finalize
65+ status = CMSDecoderFinalizeMessage ( decoder)
66+ guard status == errSecSuccess else {
67+ throw CertificateError . certExtractionFailed
9868 }
9969
100- // Fixed warning: Safer way to cast the free func without unsafeBitCast
101- OPENSSL_sk_pop_free ( stackPtr) { ptr in
102- X509_free ( OpaquePointer ( ptr) )
70+ // Extract all certificates
71+ var certsCF : CFArray ?
72+ status = CMSDecoderCopyAllCerts ( decoder, & certsCF)
73+ guard status == errSecSuccess, let certsArray = certsCF as? [ SecCertificate ] , !certsArray. isEmpty else {
74+ throw CertificateError . noCertsInProvision
10375 }
10476
105- guard certs. count > 0 else { throw CertificateError . noCertsInProvision }
106- return certs
77+ return certsArray
10778 }
10879
10980 /// Top-level check: returns result
@@ -129,7 +100,9 @@ public final class CertificatesManager {
129100 guard let first = items. first else {
130101 return . failure( CertificateError . identityExtractionFailed)
131102 }
132- let identity = first [ kSecImportItemIdentity as String ] as! SecIdentity
103+ guard let identity = first [ kSecImportItemIdentity as String ] as? SecIdentity else {
104+ return . failure( CertificateError . identityExtractionFailed)
105+ }
133106
134107 // 2) extract certificate from identity
135108 var certRef : SecCertificate ?
0 commit comments