1- // GenerateCert.swift
21import Foundation
32import OpenSSL
43
@@ -52,13 +51,9 @@ public final class GenerateCert {
5251 daysValid: Int32 = 36500 ) async throws -> [ URL ] {
5352 Logger . shared. log ( " Initializing OpenSSL... " )
5453
55- // Remove deprecated calls
56- // _ = OpenSSL_add_all_algorithms() // Deprecated in OpenSSL 3.x
57- // ERR_load_crypto_strings() // Deprecated in OpenSSL 3.x
58-
59- // For OpenSSL 3.x, use explicit initialization
60- OPENSSL_init_ssl ( OPENSSL_INIT_LOAD_SSL_STRINGS | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, nil )
61- OPENSSL_init_crypto ( OPENSSL_INIT_LOAD_CONFIG | OPENSSL_INIT_ADD_ALL_CIPHERS | OPENSSL_INIT_ADD_ALL_DIGESTS, nil )
54+ // Proper initialization for OpenSSL 3.x
55+ OPENSSL_init_ssl ( UInt64 ( OPENSSL_INIT_LOAD_SSL_STRINGS | OPENSSL_INIT_LOAD_CRYPTO_STRINGS) , nil )
56+ OPENSSL_init_crypto ( UInt64 ( OPENSSL_INIT_LOAD_CONFIG | OPENSSL_INIT_ADD_ALL_CIPHERS | OPENSSL_INIT_ADD_ALL_DIGESTS) , nil )
6257
6358 Logger . shared. log ( " Generating CA key... " )
6459 guard let caPkey = try generateRSAKey ( bits: rsaBits) else { throw CertGenError . keyGenerationFailed ( " CA key generation failed " ) }
@@ -116,64 +111,80 @@ public final class GenerateCert {
116111 return url
117112 }
118113
119- private static func generateRSAKey( bits: Int32 ) throws -> OpaquePointer ? {
120- guard let rsa = RSA_new ( ) else {
121- throw CertGenError . keyGenerationFailed ( " RSA_new failed " )
122- }
123- defer { RSA_free ( rsa) } // Automatically free RSA on any early exit
124-
125- guard let bn = BN_new ( ) else {
126- throw CertGenError . keyGenerationFailed ( " BN_new failed " )
127- }
128- defer { BN_free ( bn) }
129-
130- if BN_set_word ( bn, 65537 ) != 1 {
131- throw CertGenError . keyGenerationFailed ( " BN_set_word failed " )
132- }
133-
134- if RSA_generate_key_ex ( rsa, bits, bn, nil ) != 1 {
135- throw CertGenError . keyGenerationFailed ( " RSA_generate_key_ex failed " )
136- }
137-
138- guard let pkey = EVP_PKEY_new ( ) else {
139- throw CertGenError . keyGenerationFailed ( " EVP_PKEY_new failed " )
140- }
141-
142- // ✅ FIX: Correct pointer conversion for OpenSSL API
143- if EVP_PKEY_assign ( pkey, EVP_PKEY_RSA, UnsafeMutableRawPointer ( rsa) ) != 1 {
144- EVP_PKEY_free ( pkey)
145- throw CertGenError . keyGenerationFailed ( " EVP_PKEY_assign failed " )
114+ private static func generateRSAKey( bits: Int32 ) throws -> OpaquePointer ? {
115+ // Use modern EVP API for key generation in OpenSSL 3.x
116+ guard let ctx = EVP_PKEY_CTX_new_id ( EVP_PKEY_RSA, nil ) else {
117+ throw CertGenError . keyGenerationFailed ( " EVP_PKEY_CTX_new_id failed " )
118+ }
119+ defer { EVP_PKEY_CTX_free ( ctx) }
120+
121+ if EVP_PKEY_keygen_init ( ctx) <= 0 {
122+ throw CertGenError . keyGenerationFailed ( " EVP_PKEY_keygen_init failed " )
123+ }
124+
125+ if EVP_PKEY_CTX_set_rsa_keygen_bits ( ctx, Int ( bits) ) <= 0 {
126+ throw CertGenError . keyGenerationFailed ( " EVP_PKEY_CTX_set_rsa_keygen_bits failed " )
127+ }
128+
129+ var pkey : OpaquePointer ? = nil
130+ if EVP_PKEY_keygen ( ctx, & pkey) <= 0 {
131+ throw CertGenError . keyGenerationFailed ( " EVP_PKEY_keygen failed " )
132+ }
133+
134+ return pkey
146135 }
147-
148- // ✅ IMPORTANT: Prevent RSA from being freed by the defer block,
149- // as EVP_PKEY_assign now takes ownership.
150- _ = Unmanaged . passRetained ( rsa) // Transfer ownership
151- return pkey
152- }
153136
154137 private static func createSelfSignedCertificate( pkey: OpaquePointer ? ,
155138 commonName: String ,
156139 days: Int32 ,
157140 isCA: Bool ) throws -> OpaquePointer ? {
158141 guard let x509 = X509_new ( ) else { throw CertGenError . x509CreationFailed ( " X509_new failed " ) }
159142
160- defer {
161- if let x509 = x509 {
162- // Only free if error occurs
163- }
143+ X509_set_version ( x509, 2 )
144+
145+ guard let serial = ASN1_INTEGER_new ( ) else {
146+ X509_free ( x509)
147+ throw CertGenError . x509CreationFailed ( " ASN1_INTEGER_new failed " )
164148 }
149+ defer { ASN1_INTEGER_free ( serial) }
165150
166- X509_set_version ( x509, 2 )
151+ if ASN1_INTEGER_set_int64 ( serial, 1 ) != 1 {
152+ X509_free ( x509)
153+ throw CertGenError . x509CreationFailed ( " ASN1_INTEGER_set_int64 failed " )
154+ }
155+
156+ if X509_set_serialNumber ( x509, serial) != 1 {
157+ X509_free ( x509)
158+ throw CertGenError . x509CreationFailed ( " X509_set_serialNumber failed " )
159+ }
160+
161+ // Set notBefore and notAfter using ASN1_TIME_set
162+ let currentTime = Int ( time ( nil ) )
163+
164+ guard let notBefore = ASN1_TIME_set ( nil , time_t ( currentTime) ) else {
165+ X509_free ( x509)
166+ throw CertGenError . x509CreationFailed ( " ASN1_TIME_set for notBefore failed " )
167+ }
168+ defer { ASN1_TIME_free ( notBefore) }
169+ if X509_set1_notBefore ( x509, notBefore) != 1 {
170+ X509_free ( x509)
171+ throw CertGenError . x509CreationFailed ( " X509_set1_notBefore failed " )
172+ }
167173
168- if let serial = ASN1_INTEGER_new ( ) {
169- ASN1_INTEGER_set ( serial, 1 )
170- X509_set_serialNumber ( x509, serial)
171- ASN1_INTEGER_free ( serial)
174+ guard let notAfter = ASN1_TIME_set ( nil , time_t ( currentTime + Int( days) * 86400 ) ) else {
175+ X509_free ( x509)
176+ throw CertGenError . x509CreationFailed ( " ASN1_TIME_set for notAfter failed " )
177+ }
178+ defer { ASN1_TIME_free ( notAfter) }
179+ if X509_set1_notAfter ( x509, notAfter) != 1 {
180+ X509_free ( x509)
181+ throw CertGenError . x509CreationFailed ( " X509_set1_notAfter failed " )
172182 }
173183
174- X509_gmtime_adj ( X509_get_notBefore ( x509) , 0 )
175- X509_gmtime_adj ( X509_get_notAfter ( x509) , Int64 ( days) * 24 * 3600 )
176- X509_set_pubkey ( x509, pkey)
184+ if X509_set_pubkey ( x509, pkey) != 1 {
185+ X509_free ( x509)
186+ throw CertGenError . x509CreationFailed ( " X509_set_pubkey failed " )
187+ }
177188
178189 guard let name = X509_get_subject_name ( x509) else {
179190 X509_free ( x509)
@@ -187,16 +198,25 @@ private static func generateRSAKey(bits: Int32) throws -> OpaquePointer? {
187198 _ = addNameEntry ( name: name, field: " OU " , value: " Dev " )
188199 _ = addNameEntry ( name: name, field: " CN " , value: commonName)
189200
190- X509_set_issuer_name ( x509, name)
201+ if X509_set_issuer_name ( x509, name) != 1 {
202+ X509_free ( x509)
203+ throw CertGenError . x509CreationFailed ( " X509_set_issuer_name failed " )
204+ }
191205
192206 if isCA {
193207 if let ext = X509V3_EXT_conf_nid ( nil , nil , NID_basic_constraints, " CA:TRUE " ) {
194- X509_add_ext ( x509, ext, - 1 )
195- X509_EXTENSION_free ( ext)
208+ defer { X509_EXTENSION_free ( ext) }
209+ if X509_add_ext ( x509, ext, - 1 ) != 1 {
210+ X509_free ( x509)
211+ throw CertGenError . x509CreationFailed ( " X509_add_ext for basic_constraints failed " )
212+ }
196213 }
197214 if let ext2 = X509V3_EXT_conf_nid ( nil , nil , NID_key_usage, " keyCertSign,cRLSign " ) {
198- X509_add_ext ( x509, ext2, - 1 )
199- X509_EXTENSION_free ( ext2)
215+ defer { X509_EXTENSION_free ( ext2) }
216+ if X509_add_ext ( x509, ext2, - 1 ) != 1 {
217+ X509_free ( x509)
218+ throw CertGenError . x509CreationFailed ( " X509_add_ext for key_usage failed " )
219+ }
200220 }
201221 }
202222
@@ -215,23 +235,51 @@ private static func generateRSAKey(bits: Int32) throws -> OpaquePointer? {
215235 days: Int32 ) throws -> OpaquePointer ? {
216236 guard let cert = X509_new ( ) else { throw CertGenError . x509CreationFailed ( " X509_new failed " ) }
217237
218- defer {
219- if let cert = cert {
220- // Only free if error occurs
221- }
238+ X509_set_version ( cert, 2 )
239+
240+ guard let serial = ASN1_INTEGER_new ( ) else {
241+ X509_free ( cert)
242+ throw CertGenError . x509CreationFailed ( " ASN1_INTEGER_new failed " )
222243 }
244+ defer { ASN1_INTEGER_free ( serial) }
223245
224- X509_set_version ( cert, 2 )
246+ if ASN1_INTEGER_set_int64 ( serial, Int64 ( time ( nil ) & 0xffffffff ) ) != 1 {
247+ X509_free ( cert)
248+ throw CertGenError . x509CreationFailed ( " ASN1_INTEGER_set_int64 failed " )
249+ }
225250
226- if let serial = ASN1_INTEGER_new ( ) {
227- ASN1_INTEGER_set ( serial, Int ( time ( nil ) & 0xffffffff ) )
228- X509_set_serialNumber ( cert, serial)
229- ASN1_INTEGER_free ( serial)
251+ if X509_set_serialNumber ( cert, serial) != 1 {
252+ X509_free ( cert)
253+ throw CertGenError . x509CreationFailed ( " X509_set_serialNumber failed " )
230254 }
231255
232- X509_gmtime_adj ( X509_get_notBefore ( cert) , 0 )
233- X509_gmtime_adj ( X509_get_notAfter ( cert) , Int64 ( days) * 24 * 3600 )
234- X509_set_pubkey ( cert, serverPKey)
256+ // Set notBefore and notAfter using ASN1_TIME_set
257+ let currentTime = Int ( time ( nil ) )
258+
259+ guard let notBefore = ASN1_TIME_set ( nil , time_t ( currentTime) ) else {
260+ X509_free ( cert)
261+ throw CertGenError . x509CreationFailed ( " ASN1_TIME_set for notBefore failed " )
262+ }
263+ defer { ASN1_TIME_free ( notBefore) }
264+ if X509_set1_notBefore ( cert, notBefore) != 1 {
265+ X509_free ( cert)
266+ throw CertGenError . x509CreationFailed ( " X509_set1_notBefore failed " )
267+ }
268+
269+ guard let notAfter = ASN1_TIME_set ( nil , time_t ( currentTime + Int( days) * 86400 ) ) else {
270+ X509_free ( cert)
271+ throw CertGenError . x509CreationFailed ( " ASN1_TIME_set for notAfter failed " )
272+ }
273+ defer { ASN1_TIME_free ( notAfter) }
274+ if X509_set1_notAfter ( cert, notAfter) != 1 {
275+ X509_free ( cert)
276+ throw CertGenError . x509CreationFailed ( " X509_set1_notAfter failed " )
277+ }
278+
279+ if X509_set_pubkey ( cert, serverPKey) != 1 {
280+ X509_free ( cert)
281+ throw CertGenError . x509CreationFailed ( " X509_set_pubkey failed " )
282+ }
235283
236284 guard let subj = X509_get_subject_name ( cert) else {
237285 X509_free ( cert)
@@ -247,7 +295,10 @@ private static func generateRSAKey(bits: Int32) throws -> OpaquePointer? {
247295
248296 if let ca = caX509 {
249297 if let caSubject = X509_get_subject_name ( ca) {
250- X509_set_issuer_name ( cert, caSubject)
298+ if X509_set_issuer_name ( cert, caSubject) != 1 {
299+ X509_free ( cert)
300+ throw CertGenError . x509CreationFailed ( " X509_set_issuer_name failed " )
301+ }
251302 }
252303 }
253304
@@ -257,13 +308,19 @@ private static func generateRSAKey(bits: Int32) throws -> OpaquePointer? {
257308 }
258309
259310 if let ext_bc = X509V3_EXT_conf_nid ( nil , nil , NID_basic_constraints, " CA:FALSE " ) {
260- X509_add_ext ( cert, ext_bc, - 1 )
261- X509_EXTENSION_free ( ext_bc)
311+ defer { X509_EXTENSION_free ( ext_bc) }
312+ if X509_add_ext ( cert, ext_bc, - 1 ) != 1 {
313+ X509_free ( cert)
314+ throw CertGenError . x509CreationFailed ( " X509_add_ext for basic_constraints failed " )
315+ }
262316 }
263317
264318 if let ext_ku = X509V3_EXT_conf_nid ( nil , nil , NID_key_usage, " digitalSignature,keyEncipherment " ) {
265- X509_add_ext ( cert, ext_ku, - 1 )
266- X509_EXTENSION_free ( ext_ku)
319+ defer { X509_EXTENSION_free ( ext_ku) }
320+ if X509_add_ext ( cert, ext_ku, - 1 ) != 1 {
321+ X509_free ( cert)
322+ throw CertGenError . x509CreationFailed ( " X509_add_ext for key_usage failed " )
323+ }
267324 }
268325
269326 guard let caKey = caPkey else {
0 commit comments