@@ -42,9 +42,43 @@ public enum NIOSSLPrivateKeySource {
4242
4343/// Places NIOSSL can obtain a trust store from.
4444public enum NIOSSLTrustRoots {
45+ /// Path to either a file of CA certificates in PEM format, or a directory containing CA certificates in PEM format.
46+ ///
47+ /// If a path to a file is provided, the file can contain several CA certificates identified by
48+ ///
49+ /// -----BEGIN CERTIFICATE-----
50+ /// ... (CA certificate in base64 encoding) ...
51+ /// -----END CERTIFICATE-----
52+ ///
53+ /// sequences. Before, between, and after the certificates, text is allowed which can be used e.g.
54+ /// for descriptions of the certificates.
55+ ///
56+ /// If a path to a directory is provided, the files each contain one CA certificate in PEM format.
4557 case file( String )
58+
59+ /// A list of certificates.
4660 case certificates( [ NIOSSLCertificate ] )
61+
62+ /// The system default root of trust.
4763 case `default`
64+
65+ internal init ( from trustRoots: NIOSSLAdditionalTrustRoots ) {
66+ switch trustRoots {
67+ case . file( let path) :
68+ self = . file( path)
69+ case . certificates( let certs) :
70+ self = . certificates( certs)
71+ }
72+ }
73+ }
74+
75+ /// Places NIOSSL can obtain additional trust roots from.
76+ public enum NIOSSLAdditionalTrustRoots {
77+ /// See `NIOSSLTrustRoots.file`
78+ case file( String )
79+
80+ /// See `NIOSSLTrustRoots.certificates`
81+ case certificates( [ NIOSSLCertificate ] )
4882}
4983
5084/// Formats NIOSSL supports for serializing keys and certificates.
@@ -179,8 +213,14 @@ public struct TLSConfiguration {
179213
180214 /// The trust roots to use to validate certificates. This only needs to be provided if you intend to validate
181215 /// certificates.
216+ ///
217+ /// - NOTE: If certificate validation is enabled and `trustRoots` is `nil` then the system default root of
218+ /// trust is used (as if `trustRoots` had been explicitly set to `.default`).
182219 public var trustRoots : NIOSSLTrustRoots ?
183220
221+ /// Additional trust roots to use to validate certificates, used in addition to `trustRoots`.
222+ public var additionalTrustRoots : [ NIOSSLAdditionalTrustRoots ]
223+
184224 /// The certificates to offer during negotiation. If not present, no certificates will be offered.
185225 public var certificateChain : [ NIOSSLCertificateSource ]
186226
@@ -224,14 +264,16 @@ public struct TLSConfiguration {
224264 applicationProtocols: [ String ] ,
225265 shutdownTimeout: TimeAmount ,
226266 keyLogCallback: NIOSSLKeyLogCallback ? ,
227- renegotiationSupport: NIORenegotiationSupport ) {
267+ renegotiationSupport: NIORenegotiationSupport ,
268+ additionalTrustRoots: [ NIOSSLAdditionalTrustRoots ] ) {
228269 self . cipherSuites = cipherSuites
229270 self . verifySignatureAlgorithms = verifySignatureAlgorithms
230271 self . signingSignatureAlgorithms = signingSignatureAlgorithms
231272 self . minimumTLSVersion = minimumTLSVersion
232273 self . maximumTLSVersion = maximumTLSVersion
233274 self . certificateVerification = certificateVerification
234275 self . trustRoots = trustRoots
276+ self . additionalTrustRoots = additionalTrustRoots
235277 self . certificateChain = certificateChain
236278 self . privateKey = privateKey
237279 self . encodedApplicationProtocols = [ ]
@@ -267,7 +309,8 @@ public struct TLSConfiguration {
267309 applicationProtocols: applicationProtocols,
268310 shutdownTimeout: shutdownTimeout,
269311 keyLogCallback: keyLogCallback,
270- renegotiationSupport: . none) // Servers never support renegotiation: there's no point.
312+ renegotiationSupport: . none, // Servers never support renegotiation: there's no point.
313+ additionalTrustRoots: [ ] )
271314 }
272315
273316 /// Create a TLS configuration for use with server-side contexts.
@@ -298,7 +341,41 @@ public struct TLSConfiguration {
298341 applicationProtocols: applicationProtocols,
299342 shutdownTimeout: shutdownTimeout,
300343 keyLogCallback: keyLogCallback,
301- renegotiationSupport: . none) // Servers never support renegotiation: there's no point.
344+ renegotiationSupport: . none, // Servers never support renegotiation: there's no point.
345+ additionalTrustRoots: [ ] )
346+ }
347+
348+ /// Create a TLS configuration for use with server-side contexts.
349+ ///
350+ /// This provides sensible defaults while requiring that you provide any data that is necessary
351+ /// for server-side function. For client use, try `forClient` instead.
352+ public static func forServer( certificateChain: [ NIOSSLCertificateSource ] ,
353+ privateKey: NIOSSLPrivateKeySource ,
354+ cipherSuites: String = defaultCipherSuites,
355+ verifySignatureAlgorithms: [ SignatureAlgorithm ] ? = nil ,
356+ signingSignatureAlgorithms: [ SignatureAlgorithm ] ? = nil ,
357+ minimumTLSVersion: TLSVersion = . tlsv1,
358+ maximumTLSVersion: TLSVersion ? = nil ,
359+ certificateVerification: CertificateVerification = . none,
360+ trustRoots: NIOSSLTrustRoots = . default,
361+ applicationProtocols: [ String ] = [ ] ,
362+ shutdownTimeout: TimeAmount = . seconds( 5 ) ,
363+ keyLogCallback: NIOSSLKeyLogCallback ? = nil ,
364+ additionalTrustRoots: [ NIOSSLAdditionalTrustRoots ] ) -> TLSConfiguration {
365+ return TLSConfiguration ( cipherSuites: cipherSuites,
366+ verifySignatureAlgorithms: verifySignatureAlgorithms,
367+ signingSignatureAlgorithms: signingSignatureAlgorithms,
368+ minimumTLSVersion: minimumTLSVersion,
369+ maximumTLSVersion: maximumTLSVersion,
370+ certificateVerification: certificateVerification,
371+ trustRoots: trustRoots,
372+ certificateChain: certificateChain,
373+ privateKey: privateKey,
374+ applicationProtocols: applicationProtocols,
375+ shutdownTimeout: shutdownTimeout,
376+ keyLogCallback: keyLogCallback,
377+ renegotiationSupport: . none, // Servers never support renegotiation: there's no point.
378+ additionalTrustRoots: additionalTrustRoots)
302379 }
303380
304381 /// Creates a TLS configuration for use with client-side contexts.
@@ -327,7 +404,8 @@ public struct TLSConfiguration {
327404 applicationProtocols: applicationProtocols,
328405 shutdownTimeout: shutdownTimeout,
329406 keyLogCallback: keyLogCallback,
330- renegotiationSupport: . none) // Default value is here for backward-compatibility.
407+ renegotiationSupport: . none, // Default value is here for backward-compatibility.
408+ additionalTrustRoots: [ ] )
331409 }
332410
333411
@@ -358,7 +436,8 @@ public struct TLSConfiguration {
358436 applicationProtocols: applicationProtocols,
359437 shutdownTimeout: shutdownTimeout,
360438 keyLogCallback: keyLogCallback,
361- renegotiationSupport: renegotiationSupport)
439+ renegotiationSupport: renegotiationSupport,
440+ additionalTrustRoots: [ ] )
362441 }
363442
364443 /// Creates a TLS configuration for use with client-side contexts.
@@ -390,6 +469,41 @@ public struct TLSConfiguration {
390469 applicationProtocols: applicationProtocols,
391470 shutdownTimeout: shutdownTimeout,
392471 keyLogCallback: keyLogCallback,
393- renegotiationSupport: renegotiationSupport)
472+ renegotiationSupport: renegotiationSupport,
473+ additionalTrustRoots: [ ] )
474+ }
475+
476+ /// Creates a TLS configuration for use with client-side contexts.
477+ ///
478+ /// This provides sensible defaults, and can be used without customisation. For server-side
479+ /// contexts, you should use `forServer` instead.
480+ public static func forClient( cipherSuites: String = defaultCipherSuites,
481+ verifySignatureAlgorithms: [ SignatureAlgorithm ] ? = nil ,
482+ signingSignatureAlgorithms: [ SignatureAlgorithm ] ? = nil ,
483+ minimumTLSVersion: TLSVersion = . tlsv1,
484+ maximumTLSVersion: TLSVersion ? = nil ,
485+ certificateVerification: CertificateVerification = . fullVerification,
486+ trustRoots: NIOSSLTrustRoots = . default,
487+ certificateChain: [ NIOSSLCertificateSource ] = [ ] ,
488+ privateKey: NIOSSLPrivateKeySource ? = nil ,
489+ applicationProtocols: [ String ] = [ ] ,
490+ shutdownTimeout: TimeAmount = . seconds( 5 ) ,
491+ keyLogCallback: NIOSSLKeyLogCallback ? = nil ,
492+ renegotiationSupport: NIORenegotiationSupport = . none,
493+ additionalTrustRoots: [ NIOSSLAdditionalTrustRoots ] ) -> TLSConfiguration {
494+ return TLSConfiguration ( cipherSuites: cipherSuites,
495+ verifySignatureAlgorithms: verifySignatureAlgorithms,
496+ signingSignatureAlgorithms: signingSignatureAlgorithms,
497+ minimumTLSVersion: minimumTLSVersion,
498+ maximumTLSVersion: maximumTLSVersion,
499+ certificateVerification: certificateVerification,
500+ trustRoots: trustRoots,
501+ certificateChain: certificateChain,
502+ privateKey: privateKey,
503+ applicationProtocols: applicationProtocols,
504+ shutdownTimeout: shutdownTimeout,
505+ keyLogCallback: keyLogCallback,
506+ renegotiationSupport: renegotiationSupport,
507+ additionalTrustRoots: additionalTrustRoots)
394508 }
395509}
0 commit comments