@@ -81,6 +81,43 @@ public enum NIOSSLAdditionalTrustRoots {
8181 case certificates( [ NIOSSLCertificate ] )
8282}
8383
84+ /// Available ciphers to use for TLS instead of a string based representation.
85+ public struct NIOTLSCipher : RawRepresentable , Hashable {
86+ public init ( rawValue: UInt16 ) {
87+ self . rawValue = rawValue
88+ }
89+
90+ public init ( _ rawValue: RawValue ) {
91+ self . rawValue = rawValue
92+ }
93+
94+ public var rawValue : UInt16
95+ public typealias RawValue = UInt16
96+
97+ public static let TLS_RSA_WITH_AES_128_CBC_SHA = NIOTLSCipher ( rawValue: 0x2F )
98+ public static let TLS_RSA_WITH_AES_256_CBC_SHA = NIOTLSCipher ( rawValue: 0x35 )
99+ public static let TLS_RSA_WITH_AES_128_GCM_SHA256 = NIOTLSCipher ( rawValue: 0x9C )
100+ public static let TLS_RSA_WITH_AES_256_GCM_SHA384 = NIOTLSCipher ( rawValue: 0x9D )
101+ public static let TLS_AES_128_GCM_SHA256 = NIOTLSCipher ( rawValue: 0x1301 )
102+ public static let TLS_AES_256_GCM_SHA384 = NIOTLSCipher ( rawValue: 0x1302 )
103+ public static let TLS_CHACHA20_POLY1305_SHA256 = NIOTLSCipher ( rawValue: 0x1303 )
104+ public static let TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA = NIOTLSCipher ( rawValue: 0xC009 )
105+ public static let TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA = NIOTLSCipher ( rawValue: 0xC00A )
106+ public static let TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA = NIOTLSCipher ( rawValue: 0xC013 )
107+ public static let TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = NIOTLSCipher ( rawValue: 0xC014 )
108+ public static let TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 = NIOTLSCipher ( rawValue: 0xC02B )
109+ public static let TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 = NIOTLSCipher ( rawValue: 0xC02C )
110+ public static let TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = NIOTLSCipher ( rawValue: 0xC02F )
111+ public static let TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 = NIOTLSCipher ( rawValue: 0xC030 )
112+ public static let TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = NIOTLSCipher ( rawValue: 0xCCA8 )
113+ public static let TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 = NIOTLSCipher ( rawValue: 0xCCA9 )
114+
115+ var standardName : String {
116+ let boringSSLCipher = CNIOBoringSSL_SSL_get_cipher_by_value ( self . rawValue)
117+ return String ( cString: CNIOBoringSSL_SSL_CIPHER_standard_name ( boringSSLCipher) )
118+ }
119+ }
120+
84121/// Formats NIOSSL supports for serializing keys and certificates.
85122public enum NIOSSLSerializationFormats {
86123 case pem
@@ -200,7 +237,21 @@ public struct TLSConfiguration {
200237
201238 /// The pre-TLS1.3 cipher suites supported by this handler. This uses the OpenSSL cipher string format.
202239 /// TLS 1.3 cipher suites cannot be configured.
203- public var cipherSuites : String
240+ public var cipherSuites : String = defaultCipherSuites
241+
242+ /// Public property used to set the internal cipherSuites from NIOTLSCipher.
243+ public var cipherSuiteValues : [ NIOTLSCipher ] {
244+ get {
245+ guard let sslContext = try ? NIOSSLContext ( configuration: self ) else {
246+ return [ ]
247+ }
248+ return sslContext. cipherSuites
249+ }
250+ set {
251+ let assignedCiphers = newValue. map { $0. standardName }
252+ self . cipherSuites = assignedCiphers. joined ( separator: " : " )
253+ }
254+ }
204255
205256 /// Allowed algorithms to verify signatures. Passing nil means, that a built-in set of algorithms will be used.
206257 public var verifySignatureAlgorithms : [ SignatureAlgorithm ] ?
@@ -252,7 +303,8 @@ public struct TLSConfiguration {
252303 /// Whether renegotiation is supported.
253304 public var renegotiationSupport : NIORenegotiationSupport
254305
255- private init ( cipherSuites: String ,
306+ private init ( cipherSuiteValues: [ NIOTLSCipher ] = [ ] ,
307+ cipherSuites: String = defaultCipherSuites,
256308 verifySignatureAlgorithms: [ SignatureAlgorithm ] ? ,
257309 signingSignatureAlgorithms: [ SignatureAlgorithm ] ? ,
258310 minimumTLSVersion: TLSVersion ,
@@ -281,6 +333,42 @@ public struct TLSConfiguration {
281333 self . renegotiationSupport = renegotiationSupport
282334 self . applicationProtocols = applicationProtocols
283335 self . keyLogCallback = keyLogCallback
336+ if !cipherSuiteValues. isEmpty {
337+ self . cipherSuiteValues = cipherSuiteValues
338+ }
339+ }
340+
341+ /// Create a TLS configuration for use with server-side contexts. This allows setting the `NIOTLSCipher` property specifically.
342+ ///
343+ /// This provides sensible defaults while requiring that you provide any data that is necessary
344+ /// for server-side function. For client use, try `forClient` instead.
345+ public static func forServer( certificateChain: [ NIOSSLCertificateSource ] ,
346+ privateKey: NIOSSLPrivateKeySource ,
347+ cipherSuites: [ NIOTLSCipher ] ,
348+ verifySignatureAlgorithms: [ SignatureAlgorithm ] ? = nil ,
349+ signingSignatureAlgorithms: [ SignatureAlgorithm ] ? = nil ,
350+ minimumTLSVersion: TLSVersion = . tlsv1,
351+ maximumTLSVersion: TLSVersion ? = nil ,
352+ certificateVerification: CertificateVerification = . none,
353+ trustRoots: NIOSSLTrustRoots = . default,
354+ applicationProtocols: [ String ] = [ ] ,
355+ shutdownTimeout: TimeAmount = . seconds( 5 ) ,
356+ keyLogCallback: NIOSSLKeyLogCallback ? = nil ,
357+ additionalTrustRoots: [ NIOSSLAdditionalTrustRoots ] = [ ] ) -> TLSConfiguration {
358+ return TLSConfiguration ( cipherSuiteValues: cipherSuites,
359+ verifySignatureAlgorithms: verifySignatureAlgorithms,
360+ signingSignatureAlgorithms: signingSignatureAlgorithms,
361+ minimumTLSVersion: minimumTLSVersion,
362+ maximumTLSVersion: maximumTLSVersion,
363+ certificateVerification: certificateVerification,
364+ trustRoots: trustRoots,
365+ certificateChain: certificateChain,
366+ privateKey: privateKey,
367+ applicationProtocols: applicationProtocols,
368+ shutdownTimeout: shutdownTimeout,
369+ keyLogCallback: keyLogCallback,
370+ renegotiationSupport: . none, // Servers never support renegotiation: there's no point.
371+ additionalTrustRoots: additionalTrustRoots)
284372 }
285373
286374 /// Create a TLS configuration for use with server-side contexts.
@@ -377,6 +465,40 @@ public struct TLSConfiguration {
377465 renegotiationSupport: . none, // Servers never support renegotiation: there's no point.
378466 additionalTrustRoots: additionalTrustRoots)
379467 }
468+
469+ /// Creates a TLS configuration for use with client-side contexts. This allows setting the `NIOTLSCipher` property specifically.
470+ ///
471+ /// This provides sensible defaults, and can be used without customisation. For server-side
472+ /// contexts, you should use `forServer` instead.
473+ public static func forClient( cipherSuites: [ NIOTLSCipher ] ,
474+ verifySignatureAlgorithms: [ SignatureAlgorithm ] ? = nil ,
475+ signingSignatureAlgorithms: [ SignatureAlgorithm ] ? = nil ,
476+ minimumTLSVersion: TLSVersion = . tlsv1,
477+ maximumTLSVersion: TLSVersion ? = nil ,
478+ certificateVerification: CertificateVerification = . fullVerification,
479+ trustRoots: NIOSSLTrustRoots = . default,
480+ certificateChain: [ NIOSSLCertificateSource ] = [ ] ,
481+ privateKey: NIOSSLPrivateKeySource ? = nil ,
482+ applicationProtocols: [ String ] = [ ] ,
483+ shutdownTimeout: TimeAmount = . seconds( 5 ) ,
484+ keyLogCallback: NIOSSLKeyLogCallback ? = nil ,
485+ renegotiationSupport: NIORenegotiationSupport = . none,
486+ additionalTrustRoots: [ NIOSSLAdditionalTrustRoots ] = [ ] ) -> TLSConfiguration {
487+ return TLSConfiguration ( cipherSuiteValues: cipherSuites,
488+ verifySignatureAlgorithms: verifySignatureAlgorithms,
489+ signingSignatureAlgorithms: signingSignatureAlgorithms,
490+ minimumTLSVersion: minimumTLSVersion,
491+ maximumTLSVersion: maximumTLSVersion,
492+ certificateVerification: certificateVerification,
493+ trustRoots: trustRoots,
494+ certificateChain: certificateChain,
495+ privateKey: privateKey,
496+ applicationProtocols: applicationProtocols,
497+ shutdownTimeout: shutdownTimeout,
498+ keyLogCallback: keyLogCallback,
499+ renegotiationSupport: renegotiationSupport,
500+ additionalTrustRoots: additionalTrustRoots)
501+ }
380502
381503 /// Creates a TLS configuration for use with client-side contexts.
382504 ///
0 commit comments