├── RFCs ├── rsa-crt-leaks.pdf └── gcm-revised-spec.pdf ├── .gitignore ├── Documentation └── SwiftTLS Design.graffle ├── Tests ├── SwiftTLSTests │ ├── Resources │ │ ├── mycert.der │ │ ├── mycert.p12 │ │ ├── certificate.cer │ │ ├── Self Signed RSA SHA-256.cer │ │ ├── Self Signed RSA Certificate.cer │ │ ├── Self Signed ECDSA Certificate.cer │ │ ├── dhparams.pem │ │ ├── ECDSA Identity.pem │ │ ├── cert.pem │ │ ├── key.pem │ │ ├── Self Signed RSA-PSS SHA-256.pem │ │ ├── mycert.pem │ │ └── mycert2.pem │ ├── Info.plist │ ├── OIDTests.swift │ ├── GaloisFieldTests.swift │ ├── TLSEncryptedExtensionsTests.swift │ ├── TLSCertificateMessageTests.swift │ ├── TLSReadExtensionsTests.swift │ ├── SocketTests.swift │ ├── MontgomeryTests.swift │ ├── SHA1Tests.swift │ ├── SHA256Tests.swift │ ├── SHA224Tests.swift │ ├── SHA384Tests.swift │ ├── TLSClientKeyExchangeTests.swift │ ├── XCTestHelper.swift │ ├── SHA512Tests.swift │ ├── TLSRecordTests.swift │ ├── TLSUtilitiesTests.swift │ ├── BigIntBitOperationTests.swift │ ├── AESTests.swift │ └── TLSServerHelloTests.swift └── macOS │ ├── external │ └── openssl │ │ ├── openssl │ │ ├── opensslconf.h │ │ ├── e_os2.h │ │ └── opensslv.h │ │ ├── bf │ │ ├── README │ │ ├── COPYRIGHT │ │ ├── bf_ecb.c │ │ └── bf_skey.c │ │ ├── openssl_utils.c │ │ ├── opensslUtils │ │ └── opensslUtils.h │ │ ├── bn │ │ ├── divtest.c │ │ ├── exp.c │ │ └── vms-helper.c │ │ ├── LICENSE │ │ └── dsa │ │ └── dsa_asn1.c │ └── tests.py ├── SwiftTLS.xcodeproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ ├── IDEWorkspaceChecks.plist │ │ └── swiftpm │ │ └── Package.resolved └── xcshareddata │ └── xcschemes │ ├── tls.xcscheme │ └── SwiftTLS.xcscheme ├── SwiftTLS ├── modulemaps │ ├── CommonCrypto │ │ └── module.modulemap │ └── OpenSSL │ │ └── module.modulemap ├── Sources │ ├── Crypto │ │ ├── Cryptor.swift │ │ ├── Hash.swift │ │ ├── Signing.swift │ │ ├── HMAC.swift │ │ ├── CryptoUtilities.swift │ │ ├── BarrettReduction.swift │ │ ├── Montgomery.swift │ │ ├── ECDHKeyExchange.swift │ │ ├── DHKeyExchange.swift │ │ ├── BinaryInteger+Extensions.swift │ │ ├── SwiftTLSCrypto.swift │ │ ├── GaloisField.swift │ │ └── SHA1.swift │ ├── TLS │ │ ├── Identity.swift │ │ ├── Protocol │ │ │ ├── TLSProtocol.swift │ │ │ ├── Messages │ │ │ │ ├── TLSApplicationData.swift │ │ │ │ ├── TLSFinished.swift │ │ │ │ ├── Extensions │ │ │ │ │ ├── TLSSupportedGroupsExtension.swift │ │ │ │ │ ├── TLSEllipticCurvePointFormatsExtension.swift │ │ │ │ │ ├── TLSSignatureAlgorithmsExtension.swift │ │ │ │ │ └── TLSServerNameExtension.swift │ │ │ │ ├── TLSCertificateVerify.swift │ │ │ │ ├── TLSMessage.swift │ │ │ │ ├── TLSAlert.swift │ │ │ │ └── TLSCertificateMessage.swift │ │ │ ├── TLS 1_3 │ │ │ │ ├── Messages │ │ │ │ │ ├── TLSEndOfEarlyData.swift │ │ │ │ │ ├── TLSEncryptedExtensions.swift │ │ │ │ │ ├── TLSHelloRetryRequest.swift │ │ │ │ │ ├── Extensions │ │ │ │ │ │ ├── TLSEarlyDataIndication.swift │ │ │ │ │ │ ├── TLSPSKKeyExchangeModesExtension.swift │ │ │ │ │ │ └── TLSSupportedVersionsExtension.swift │ │ │ │ │ └── TLSNewSessionTicket.swift │ │ │ │ └── TLS1_3.TicketStorage.swift │ │ │ └── TLS 1_2 │ │ │ │ └── Messages │ │ │ │ ├── TLSServerHelloDone.swift │ │ │ │ └── Extensions │ │ │ │ └── TLSSecureRenegotiationInfoExtension.swift │ │ ├── TLSContext.swift │ │ ├── TLSChangeCipherSpec.swift │ │ ├── TLSSession.swift │ │ ├── PEMFileIdentity.swift │ │ ├── math.swift │ │ ├── TLSRecord.swift │ │ ├── TLSProtocolVersion.swift │ │ └── TLSConfiguration.swift │ ├── Utilities.swift │ ├── DataBuffer.swift │ └── Log.swift ├── TODO ├── SwiftTLS.h └── Info.plist ├── .github └── workflows │ ├── macos.yml │ └── linux.yml ├── Package.resolved ├── TODO ├── LICENSE.txt ├── Package.swift ├── README.md └── SwiftTLSTool ├── scan.swift ├── probeCipherSuites.swift └── client.swift /RFCs/rsa-crt-leaks.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsc/SwiftTLS/HEAD/RFCs/rsa-crt-leaks.pdf -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | xcuserdata 3 | xcbaselines 4 | *.xccheckout 5 | .build 6 | .swiftpm 7 | -------------------------------------------------------------------------------- /RFCs/gcm-revised-spec.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsc/SwiftTLS/HEAD/RFCs/gcm-revised-spec.pdf -------------------------------------------------------------------------------- /Documentation/SwiftTLS Design.graffle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsc/SwiftTLS/HEAD/Documentation/SwiftTLS Design.graffle -------------------------------------------------------------------------------- /Tests/SwiftTLSTests/Resources/mycert.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsc/SwiftTLS/HEAD/Tests/SwiftTLSTests/Resources/mycert.der -------------------------------------------------------------------------------- /Tests/SwiftTLSTests/Resources/mycert.p12: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsc/SwiftTLS/HEAD/Tests/SwiftTLSTests/Resources/mycert.p12 -------------------------------------------------------------------------------- /Tests/SwiftTLSTests/Resources/certificate.cer: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsc/SwiftTLS/HEAD/Tests/SwiftTLSTests/Resources/certificate.cer -------------------------------------------------------------------------------- /Tests/macOS/external/openssl/openssl/opensslconf.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsc/SwiftTLS/HEAD/Tests/macOS/external/openssl/openssl/opensslconf.h -------------------------------------------------------------------------------- /Tests/SwiftTLSTests/Resources/Self Signed RSA SHA-256.cer: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsc/SwiftTLS/HEAD/Tests/SwiftTLSTests/Resources/Self Signed RSA SHA-256.cer -------------------------------------------------------------------------------- /Tests/SwiftTLSTests/Resources/Self Signed RSA Certificate.cer: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsc/SwiftTLS/HEAD/Tests/SwiftTLSTests/Resources/Self Signed RSA Certificate.cer -------------------------------------------------------------------------------- /Tests/SwiftTLSTests/Resources/Self Signed ECDSA Certificate.cer: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsc/SwiftTLS/HEAD/Tests/SwiftTLSTests/Resources/Self Signed ECDSA Certificate.cer -------------------------------------------------------------------------------- /SwiftTLS.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SwiftTLS/modulemaps/CommonCrypto/module.modulemap: -------------------------------------------------------------------------------- 1 | module CommonCrypto [system] { 2 | header "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/CommonCrypto/CommonCrypto.h" 3 | export * 4 | } 5 | -------------------------------------------------------------------------------- /.github/workflows/macos.yml: -------------------------------------------------------------------------------- 1 | name: macOS 2 | 3 | on: [push] 4 | 5 | jobs: 6 | build: 7 | 8 | runs-on: macOS-latest 9 | 10 | steps: 11 | - uses: actions/checkout@v3 12 | - name: Run tests 13 | run: swift test -c release -Xswiftc -enable-testing 14 | -------------------------------------------------------------------------------- /SwiftTLS/modulemaps/OpenSSL/module.modulemap: -------------------------------------------------------------------------------- 1 | module OpenSSL [system] { 2 | header "../../../Tests/macOS/external/openssl/openssl/bn.h" 3 | header "../../../Tests/macOS/external/openssl/openssl/rsa.h" 4 | header "../../../Tests/macOS/external/openssl/openssl/opensslconf.h" 5 | export * 6 | } 7 | -------------------------------------------------------------------------------- /.github/workflows/linux.yml: -------------------------------------------------------------------------------- 1 | name: Linux 2 | on: [push] 3 | 4 | jobs: 5 | linux: 6 | name: Linux 7 | runs-on: ubuntu-latest 8 | container: swift:5.7 9 | steps: 10 | - uses: actions/checkout@v1 11 | - name: Run tests 12 | run: swift test -c release -Xswiftc -enable-testing 13 | -------------------------------------------------------------------------------- /SwiftTLS/Sources/Crypto/Cryptor.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Cryptor.swift 3 | // SwiftTLS 4 | // 5 | // Created by Nico Schmidt on 19.04.18. 6 | // Copyright © 2018 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | protocol Cryptor { 10 | func update(inputBlock: MemoryBlock, outputBlock: inout MemoryBlock) -> Bool 11 | } 12 | -------------------------------------------------------------------------------- /SwiftTLS.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Tests/macOS/external/openssl/bf/README: -------------------------------------------------------------------------------- 1 | This is a quick packaging up of my blowfish code into a library. 2 | It has been lifted from SSLeay. 3 | The copyright notices seem a little harsh because I have not spent the 4 | time to rewrite the conditions from the normal SSLeay ones. 5 | 6 | Basically if you just want to play with the library, not a problem. 7 | 8 | eric 15-Apr-1997 9 | -------------------------------------------------------------------------------- /Package.resolved: -------------------------------------------------------------------------------- 1 | { 2 | "pins" : [ 3 | { 4 | "identity" : "swift-system", 5 | "kind" : "remoteSourceControl", 6 | "location" : "https://github.com/apple/swift-system", 7 | "state" : { 8 | "revision" : "025bcb1165deab2e20d4eaba79967ce73013f496", 9 | "version" : "1.2.1" 10 | } 11 | } 12 | ], 13 | "version" : 2 14 | } 15 | -------------------------------------------------------------------------------- /SwiftTLS/Sources/TLS/Identity.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Identity.swift 3 | // SwiftTLS 4 | // 5 | // Created by Nico Schmidt on 02.07.16. 6 | // Copyright © 2016 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public protocol Identity 12 | { 13 | var certificateChain: [X509.Certificate] { get } 14 | func signer(with hashAlgorithm: HashAlgorithm) -> Signing 15 | } 16 | -------------------------------------------------------------------------------- /SwiftTLS/Sources/Crypto/Hash.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Hash.swift 3 | // SwiftTLS 4 | // 5 | // Created by Nico Schmidt on 17.04.18. 6 | // Copyright © 2018 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | protocol Hash { 10 | static func hash(_ m: [UInt8]) -> [UInt8] 11 | 12 | static var blockLength: Int { get } 13 | func update(_ m: [UInt8]) 14 | func finalize() -> [UInt8] 15 | } 16 | -------------------------------------------------------------------------------- /SwiftTLS/TODO: -------------------------------------------------------------------------------- 1 | - Fix signing/verification bug with TLS 1.0 where the signature and hash algorithm wasn't part of the signed data 2 | - check padding 3 | - implement TLS 1.2 extension to choose hash function other than SHA256 4 | - generate correct alert messages 5 | 6 | - implement TLS 1.3 7 | 8 | 9 | - improve BigInt multiply and pow performance 10 | - implement support for explicit elliptic curves 11 | -------------------------------------------------------------------------------- /SwiftTLS.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved: -------------------------------------------------------------------------------- 1 | { 2 | "pins" : [ 3 | { 4 | "identity" : "swift-system", 5 | "kind" : "remoteSourceControl", 6 | "location" : "https://github.com/apple/swift-system.git", 7 | "state" : { 8 | "revision" : "025bcb1165deab2e20d4eaba79967ce73013f496", 9 | "version" : "1.2.1" 10 | } 11 | } 12 | ], 13 | "version" : 2 14 | } 15 | -------------------------------------------------------------------------------- /SwiftTLS/Sources/Crypto/Signing.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Signing.swift 3 | // SwiftTLS 4 | // 5 | // Created by Nico Schmidt on 29.12.15. 6 | // Copyright © 2015 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | public protocol Signing 10 | { 11 | var algorithm: X509.SignatureAlgorithm { get set} 12 | 13 | func sign(data : [UInt8]) throws -> [UInt8] 14 | func verify(signature : [UInt8], data : [UInt8]) throws -> Bool 15 | } 16 | -------------------------------------------------------------------------------- /Tests/SwiftTLSTests/Resources/dhparams.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN DH PARAMETERS----- 2 | MIIBCAKCAQEAtmcbwmIwO/qDRMH1izMqt4DXE5yb0tMN9c6Qu9+dmqbITQcp/Rf0 3 | TZr7YacgEliJC5tACQ6qbAF9vKXc39biP0oY/QrbE9sXKhhOM+h/8uUmymi3j5jE 4 | f6TZ+74U0pw2eBcsNcEyPNxzv109tnIC9PYrv/WPMTG24/1BvpSUk4Vz9QH92Gxy 5 | 0weZ9el/CV/rJNK/7epNQHr7qN5v/dvmAzjSTCWSWzboBIRoMlK1D9AhNNYVR72e 6 | 4CGSowQuzbUw/01UlzSO8VKzo5oTxr66iTIXvXfDQ7AGYjBaq1Q69jHO0NzF2zs3 7 | E2gjltDkg+aPpN6hxFWbWMMNsBqN8q1jUwIBAg== 8 | -----END DH PARAMETERS----- 9 | -------------------------------------------------------------------------------- /SwiftTLS/SwiftTLS.h: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftTLS.h 3 | // SwiftTLS 4 | // 5 | // Created by Nico Schmidt on 07.09.15. 6 | // Copyright © 2015 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for SwiftTLS. 12 | FOUNDATION_EXPORT double SwiftTLSVersionNumber; 13 | 14 | //! Project version string for SwiftTLS. 15 | FOUNDATION_EXPORT const unsigned char SwiftTLSVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | -------------------------------------------------------------------------------- /Tests/macOS/external/openssl/openssl_utils.c: -------------------------------------------------------------------------------- 1 | // 2 | // openssl_utils.c 3 | // SwiftTLS 4 | // 5 | // Created by Nico Schmidt on 06.06.15. 6 | // Copyright (c) 2015 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | #include 10 | 11 | int RAND_bytes(unsigned char *buf,int num) 12 | { 13 | arc4random_buf(buf, num); 14 | 15 | return 1; 16 | } 17 | 18 | int RAND_pseudo_bytes(unsigned char *buf,int num) 19 | { 20 | return RAND_bytes(buf, num); 21 | } 22 | 23 | void RAND_add(const void *buf,int num,double entropy) 24 | { 25 | } 26 | 27 | int CRYPTO_mem_ctrl(int mode) 28 | { 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /SwiftTLS/Sources/TLS/Protocol/TLSProtocol.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TLSProtocol.swift 3 | // SwiftTLS 4 | // 5 | // Created by Nico Schmidt on 13.01.17. 6 | // Copyright © 2017 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | protocol TLSProtocol 12 | { 13 | var connectionInfo: String { get } 14 | } 15 | 16 | protocol TLSClientProtocol : TLSProtocol 17 | { 18 | func connect() async throws 19 | func handle(_ serverHello: TLSServerHello) async throws 20 | } 21 | 22 | protocol TLSServerProtocol : TLSProtocol 23 | { 24 | func acceptConnection(withClientHello clientHello: TLSClientHello?) async throws 25 | } 26 | -------------------------------------------------------------------------------- /SwiftTLS/Sources/Utilities.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Utilities.swift 3 | // SwiftTLS 4 | // 5 | // Created by Nico Schmidt on 05/02/16. 6 | // Copyright © 2016 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | extension Data { 12 | func UInt8Array() -> [UInt8] { 13 | return withUnsafeBytes { bytes in 14 | return [UInt8](bytes.bindMemory(to: UInt8.self)) 15 | } 16 | } 17 | } 18 | 19 | extension Array where Element == UInt8 { 20 | init(_ data: Data) { 21 | self.init(repeating: 0, count: data.count) 22 | self.withUnsafeMutableBufferPointer { 23 | _ = data.copyBytes(to: $0) 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /SwiftTLS/Sources/TLS/TLSContext.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TLSContext.swift 3 | // SwiftTLS 4 | // 5 | // Created by Nico Schmidt on 06.01.17. 6 | // Copyright © 2017 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public class TLSContext { 12 | var ticketStorage = TLS1_3.TicketStorage() 13 | } 14 | 15 | public class TLSServerContext : TLSContext { 16 | // The saved sessions that the server can reuse when a client sends a sessionID 17 | // we know about from before 18 | var sessionCache: [TLSSessionID: TLSSession] = [:] 19 | } 20 | 21 | public class TLSClientContext : TLSContext { 22 | // The client session cache is indexed by hostname and port concatenated to 23 | // a string "\(hostname):\(port)" 24 | var sessionCache: [String : TLSSession] = [:] 25 | } 26 | -------------------------------------------------------------------------------- /SwiftTLS/Sources/TLS/Protocol/Messages/TLSApplicationData.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TLSApplicationData.swift 3 | // SwiftTLS 4 | // 5 | // Created by Nico Schmidt on 24.04.15. 6 | // Copyright (c) 2015 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class TLSApplicationData : TLSMessage 12 | { 13 | var applicationData : [UInt8] 14 | 15 | init(applicationData: [UInt8]) 16 | { 17 | self.applicationData = applicationData 18 | super.init(type: .applicationData) 19 | 20 | self.rawMessageData = applicationData 21 | } 22 | 23 | // FIXME: This constructor is only needed to fulfill the TLSMessage requirement 24 | required init?(inputStream: InputStreamType, context: TLSConnection) 25 | { 26 | fatalError("This method is not implemented") 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Tests/SwiftTLSTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /SwiftTLS/Sources/Crypto/HMAC.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HMAC.swift 3 | // SwiftTLS 4 | // 5 | // Created by Nico Schmidt on 17.04.18. 6 | // Copyright © 2018 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | func HMAC(hash: Hash.Type, secret: [UInt8], data: [UInt8]) -> [UInt8] 10 | { 11 | let k: [UInt8] 12 | if secret.count == hash.blockLength { 13 | k = secret 14 | } 15 | else if secret.count < hash.blockLength { 16 | k = secret + [UInt8](repeating: 0, count: hash.blockLength - secret.count) 17 | } 18 | else { 19 | k = hash.hash(secret) 20 | } 21 | 22 | let ipad = [UInt8](repeating: 0x36, count: hash.blockLength) 23 | let opad = [UInt8](repeating: 0x5c, count: hash.blockLength) 24 | 25 | let innerHash = hash.hash((k ^ ipad) + data) 26 | let outerHash = hash.hash((k ^ opad) + innerHash) 27 | 28 | return outerHash 29 | } 30 | -------------------------------------------------------------------------------- /SwiftTLS/Sources/TLS/Protocol/TLS 1_3/Messages/TLSEndOfEarlyData.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TLSEndOfEarlyData.swift 3 | // SwiftTLS 4 | // 5 | // Created by Nico Schmidt on 07.04.18. 6 | // Copyright © 2018 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | extension TLS1_3 { 12 | 13 | class TLSEndOfEarlyData : TLSHandshakeMessage { 14 | init() 15 | { 16 | super.init(type: .handshake(.endOfEarlyData)) 17 | } 18 | 19 | required init?(inputStream : InputStreamType, context: TLSConnection) 20 | { 21 | guard let (type, bodyLength) = TLSHandshakeMessage.readHeader(inputStream), type == .endOfEarlyData, 22 | bodyLength == 0 23 | else { 24 | return nil 25 | } 26 | 27 | super.init(type: .handshake(.endOfEarlyData)) 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | - check padding 2 | - implement TLS 1.2 extension to choose hash function other than SHA256 3 | 4 | - improve BigInt multiply and pow performance 5 | 6 | TLS 1.2: 7 | - fix session reuse 8 | 9 | 10 | In case we should ever support the selection of a certificate according 11 | to the server name indication, we should send an empty server name indication 12 | in return to signal that we have used that information (see RFC 6066): 13 | 14 | A server that receives a client hello containing the "server_name" 15 | extension MAY use the information contained in the extension to guide 16 | its selection of an appropriate certificate to return to the client, 17 | and/or other aspects of security policy. In this event, the server 18 | SHALL include an extension of type "server_name" in the (extended) 19 | server hello. The "extension_data" field of this extension SHALL be 20 | empty. 21 | 22 | -------------------------------------------------------------------------------- /SwiftTLS/Sources/TLS/TLSChangeCipherSpec.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TLSChangeCipherSpec.swift 3 | // 4 | // Created by Nico Schmidt on 25.03.15. 5 | // Copyright (c) 2015 Nico Schmidt. All rights reserved. 6 | // 7 | 8 | import Foundation 9 | 10 | class TLSChangeCipherSpec : TLSMessage 11 | { 12 | init() 13 | { 14 | super.init(type: .changeCipherSpec) 15 | } 16 | 17 | required init?(inputStream: InputStreamType, context: TLSConnection) { 18 | if let type: UInt8 = inputStream.read() { 19 | if type == 1 { 20 | super.init(type: .changeCipherSpec) 21 | return 22 | } 23 | } 24 | 25 | return nil 26 | } 27 | 28 | override func writeTo(_ target: inout Target, context: TLSConnection?) { 29 | target.write(TLSChangeCipherSpecType.changeCipherSpec.rawValue) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Tests/SwiftTLSTests/OIDTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // OIDTests.swift 3 | // SwiftTLS 4 | // 5 | // Created by Nico Schmidt on 10.01.16. 6 | // Copyright © 2016 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import SwiftTLS 11 | 12 | class OIDTests: XCTestCase { 13 | static var allTests = [ 14 | ("test_identifier_withSomeTestVectors_givesCorrectResult", test_identifier_withSomeTestVectors_givesCorrectResult), 15 | ] 16 | 17 | func test_identifier_withSomeTestVectors_givesCorrectResult() 18 | { 19 | let values : [OID] = [ 20 | .sha1 21 | ] 22 | 23 | for oid in values 24 | { 25 | let identifier = oid.identifier 26 | if let oid2 = OID(id: identifier) { 27 | XCTAssert(oid == oid2) 28 | } 29 | else { 30 | XCTFail() 31 | } 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /SwiftTLS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSHumanReadableCopyright 24 | Copyright © 2015 Nico Schmidt. All rights reserved. 25 | NSPrincipalClass 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /SwiftTLS/Sources/TLS/Protocol/TLS 1_2/Messages/TLSServerHelloDone.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TLSServerHelloDone.swift 3 | // 4 | // Created by Nico Schmidt on 17.03.15. 5 | // Copyright (c) 2015 Nico Schmidt. All rights reserved. 6 | // 7 | 8 | import Foundation 9 | 10 | class TLSServerHelloDone : TLSHandshakeMessage 11 | { 12 | init() 13 | { 14 | super.init(type: .handshake(.serverHelloDone)) 15 | } 16 | 17 | required init?(inputStream : InputStreamType, context: TLSConnection) 18 | { 19 | guard 20 | let (type, bodyLength) = TLSHandshakeMessage.readHeader(inputStream), type == TLSHandshakeType.serverHelloDone && bodyLength == 0 21 | else { 22 | return nil 23 | } 24 | 25 | super.init(type: .handshake(.serverHelloDone)) 26 | } 27 | 28 | override func writeTo(_ target: inout Target, context: TLSConnection?) 29 | { 30 | self.writeHeader(type: .serverHelloDone, bodyLength: 0, target: &target) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Tests/SwiftTLSTests/GaloisFieldTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GaloisFieldTests.swift 3 | // SwiftTLS 4 | // 5 | // Created by Nico Schmidt on 13/03/16. 6 | // Copyright © 2016 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import SwiftTLS 11 | 12 | class GaloisFieldTests: XCTestCase { 13 | static var allTests = [ 14 | ("test_rightshift_works", test_rightshift_works), 15 | ("test_leftshift_works", test_leftshift_works), 16 | ] 17 | 18 | func test_rightshift_works() 19 | { 20 | var a = GF2_128_Element(hi: 0xffffffffffffffff, lo: 0xffffffffffffffff) 21 | 22 | for i in 0..<128 23 | { 24 | a = a.rightshift() 25 | XCTAssertFalse(a.isBitSet(i)) 26 | } 27 | } 28 | 29 | func test_leftshift_works() 30 | { 31 | var a = GF2_128_Element(hi: 0xffffffffffffffff, lo: 0xffffffffffffffff) 32 | 33 | for i in 0..<128 34 | { 35 | a = a.leftshift() 36 | XCTAssertFalse(a.isBitSet(127-i)) 37 | } 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /Tests/SwiftTLSTests/TLSEncryptedExtensionsTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TLSEncryptedExtensionsTests.swift 3 | // SwiftTLSTests 4 | // 5 | // Created by Nico Schmidt on 02.04.18. 6 | // Copyright © 2018 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import SwiftTLS 11 | 12 | class TLSEncryptedExtensionsTests: XCTestCase { 13 | static var allTests = [ 14 | ("test_writeTo_withSomeExtensions_givesDataFromWhichTheSameMessageCanBeConstructed", test_writeTo_withSomeExtensions_givesDataFromWhichTheSameMessageCanBeConstructed), 15 | ] 16 | 17 | func test_writeTo_withSomeExtensions_givesDataFromWhichTheSameMessageCanBeConstructed() { 18 | let encryptedExtensions = TLS1_3.TLSEncryptedExtensions(extensions: []) 19 | 20 | let context = TLSServer(configuration: TLSConfiguration(supportedVersions: [.v1_3])) 21 | var data: [UInt8] = [] 22 | encryptedExtensions.writeTo(&data, context: context) 23 | 24 | if TLS1_3.TLSEncryptedExtensions(inputStream: BinaryInputStream(data), context: context) == nil { 25 | XCTFail() 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2015-2020 Nico Schmidt 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Tests/SwiftTLSTests/Resources/ECDSA Identity.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN EC PARAMETERS----- 2 | BggqhkjOPQMBBw== 3 | -----END EC PARAMETERS----- 4 | -----BEGIN EC PRIVATE KEY----- 5 | MHcCAQEEIL6ZXCR4x1w/aF5MUuSsVLr5YRUWhEmux9PlvlQ2+dVkoAoGCCqGSM49 6 | AwEHoUQDQgAEEHbZdY1gcETIjYp5nDzuPb5mwqRWPWPPLZRhp/cJzlWI0tKonH7n 7 | 5F7xGJjcI58cs/NR5yJuUCEcNxrW4Ydppw== 8 | -----END EC PRIVATE KEY----- 9 | -----BEGIN CERTIFICATE----- 10 | MIICKDCCAc+gAwIBAgIJAJTCNi4s/U7RMAoGCCqGSM49BAMCMEUxCzAJBgNVBAYT 11 | AkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRn 12 | aXRzIFB0eSBMdGQwHhcNMTgwNTEzMDkyNDEwWhcNMjAwNTEyMDkyNDEwWjBFMQsw 13 | CQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJu 14 | ZXQgV2lkZ2l0cyBQdHkgTHRkMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEEHbZ 15 | dY1gcETIjYp5nDzuPb5mwqRWPWPPLZRhp/cJzlWI0tKonH7n5F7xGJjcI58cs/NR 16 | 5yJuUCEcNxrW4Ydpp6OBpzCBpDAdBgNVHQ4EFgQUsHiFi9XN2byCu403L2PSC65t 17 | sBwwdQYDVR0jBG4wbIAUsHiFi9XN2byCu403L2PSC65tsByhSaRHMEUxCzAJBgNV 18 | BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX 19 | aWRnaXRzIFB0eSBMdGSCCQCUwjYuLP1O0TAMBgNVHRMEBTADAQH/MAoGCCqGSM49 20 | BAMCA0cAMEQCIEINFVcLI4Wq6hJE2smdp3B83+oWB1GZVlWrh7OwCKc2AiBsdxjg 21 | RmCuX8eXBN1u51zgSKU3LfTBRfDcRoKqoqEvsQ== 22 | -----END CERTIFICATE----- 23 | -------------------------------------------------------------------------------- /SwiftTLS/Sources/Crypto/CryptoUtilities.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Utilities.swift 3 | // SwiftTLS 4 | // 5 | // Created by Nico Schmidt on 06.06.20. 6 | // Copyright © 2020 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public func fillWithRandomBytes(_ buffer: UnsafeMutableRawBufferPointer) 12 | { 13 | #if os(Linux) 14 | struct SeedSetter { 15 | static let fd: Int32? = { 16 | let fd = open("/dev/urandom", O_RDONLY) 17 | guard fd >= 0 else { 18 | return nil 19 | } 20 | var seed: UInt32 = 0 21 | let seedSize = MemoryLayout.size 22 | let result = read(fd, &seed, seedSize) 23 | guard result == seedSize else { 24 | return nil 25 | } 26 | close(fd) 27 | 28 | srandom(seed) 29 | 30 | return fd 31 | }() 32 | } 33 | 34 | _ = SeedSetter.fd 35 | 36 | let uint8buffer = buffer.bindMemory(to: UInt8.self) 37 | for i in 0.. 0: 12 | quotient = i / j 13 | remainder = i % j 14 | 15 | print "quotient = %x" % quotient 16 | print "remainder = %x" % remainder 17 | 18 | y = y2 - y1 * quotient 19 | 20 | print "y = %x" % y 21 | 22 | i = j 23 | j = remainder 24 | y2 = y1 25 | y1 = y 26 | 27 | print "y2 = %x" % y2 28 | print "a = %x" % a 29 | 30 | result = y2 % a 31 | 32 | print "y2 %% a = %x" % result 33 | 34 | return result 35 | 36 | def modular_inverse(x, y, mod): 37 | 38 | inverse = extended_euclid(y, mod) 39 | 40 | print "inverse = %x" % inverse 41 | 42 | result = (inverse * x) % mod 43 | 44 | print "result = %x" % result 45 | 46 | if result < 0: 47 | result = result + mod 48 | 49 | return result 50 | 51 | x = int(sys.argv[1], 16) 52 | y = int(sys.argv[2], 16) 53 | mod = int(sys.argv[3], 16) 54 | 55 | result = modular_inverse(x, y, mod) 56 | 57 | print "%X" % result 58 | 59 | print "check: (y * result) %% mod == %X" % ((y * result) % mod) 60 | print " %X" % (x % mod) 61 | -------------------------------------------------------------------------------- /Tests/SwiftTLSTests/TLSCertificateMessageTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TLSCertificateMessageTests.swift 3 | // SwiftTLS 4 | // 5 | // Created by Nico Schmidt on 27.03.15. 6 | // Copyright (c) 2015 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import SwiftTLS 11 | 12 | class TLSCertificateMessageTests: XCTestCase { 13 | static var allTests = [ 14 | ("test_writeTo_withOneCertificate_givesDataFromWhichTheSameMessageCanBeConstructed", test_writeTo_withOneCertificate_givesDataFromWhichTheSameMessageCanBeConstructed), 15 | ] 16 | 17 | func test_writeTo_withOneCertificate_givesDataFromWhichTheSameMessageCanBeConstructed() 18 | { 19 | let certificatePath = path(forResource: "certificate.cer") 20 | let certificateData = try! Data(contentsOf: URL(fileURLWithPath: certificatePath)) 21 | let certificate = X509.Certificate(derData: certificateData)! 22 | let sut = TLSCertificateMessage(certificates: [certificate]) 23 | 24 | let context = TLSConnection() 25 | var data = [UInt8]() 26 | sut.writeTo(&data, context: context) 27 | let cert2Message = TLSCertificateMessage(inputStream: BinaryInputStream(data), context: context)! 28 | var data2 = [UInt8]() 29 | cert2Message.writeTo(&data2, context: context) 30 | 31 | XCTAssertEqual(data, data2) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /SwiftTLS/Sources/TLS/Protocol/Messages/TLSFinished.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TLSFinished.swift 3 | // SwiftTLS 4 | // 5 | // Created by Nico Schmidt on 08/04/15. 6 | // Copyright (c) 2015 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class TLSFinished : TLSHandshakeMessage 12 | { 13 | var verifyData : [UInt8] 14 | 15 | init(verifyData : [UInt8]) 16 | { 17 | self.verifyData = verifyData 18 | 19 | super.init(type: .handshake(.finished)) 20 | } 21 | 22 | required init?(inputStream : InputStreamType, context: TLSConnection) 23 | { 24 | let verifyDataLength = context.negotiatedProtocolVersion! >= .v1_3 ? context.hashAlgorithm.hashLength : 12 25 | guard 26 | let (type, _) = TLSHandshakeMessage.readHeader(inputStream), type == TLSHandshakeType.finished, 27 | let verifyData : [UInt8] = inputStream.read(count: verifyDataLength) 28 | else { 29 | return nil 30 | } 31 | 32 | self.verifyData = verifyData 33 | super.init(type: .handshake(.finished)) 34 | } 35 | 36 | override func writeTo(_ target: inout Target, context: TLSConnection?) 37 | { 38 | self.writeHeader(type: .finished, bodyLength: self.verifyData.count, target: &target) 39 | target.write(self.verifyData) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Tests/SwiftTLSTests/Resources/cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDoDCCAoigAwIBAgIJAMCOKb3Xq5WVMA0GCSqGSIb3DQEBBQUAMD4xCzAJBgNV 3 | BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMRowGAYDVQQKExFTb21lIE9yZ2Fu 4 | aXphdGlvbjAeFw0xNjA3MDExOTI2NTZaFw0xOTAzMjgxOTI2NTZaMD4xCzAJBgNV 5 | BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMRowGAYDVQQKExFTb21lIE9yZ2Fu 6 | aXphdGlvbjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANmW7b44CDxC 7 | /1Wh4+sz5FZB+/CjhvtwWNhG1GIMSjqY8qy6YcJfhMrAhVHWGVp0ruBC/PUyfnL7 8 | Ted5B6nhCr5SKCQMZhknAmGtbeMLzXhgWHFqn1rHlrju3r2Ey3HK95SIQQ+riddi 9 | pqroLe+CwzAifFSnxvCDcSdnW669GI25hUpQ5UWZU61x0PID6s489M3I76di8xmJ 10 | L8gW8XM5oeAyl9IerkIvq/eTj9nV0ryNfATQw4SPhjTWHIf7wezLlwGbCWNbRqsM 11 | 2ymKxOg/7yd3gK6KfkdBHA9aYMKaERb1PbQhOGwXzfeVyXZviCELU/qdLuJAZsdo 12 | 9YgAvO0vUSkCAwEAAaOBoDCBnTAdBgNVHQ4EFgQUQNrv3J/RQsA3ZbcZ8lCpLOII 13 | KYswbgYDVR0jBGcwZYAUQNrv3J/RQsA3ZbcZ8lCpLOIIKYuhQqRAMD4xCzAJBgNV 14 | BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMRowGAYDVQQKExFTb21lIE9yZ2Fu 15 | aXphdGlvboIJAMCOKb3Xq5WVMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD 16 | ggEBAKt0+512kBUEcPQNLqBd41kjr13NvRMH6I/iHr9Mw/R9lHsIeExJNiwV0PMH 17 | oVZNUBhJO5YSXBok1S+0whNboMkbEiZ4qco1Qjx6yng/vN7zzGFheksNxzyQR7a8 18 | Q4pnykfCubb7a1q0X9O1YTneqEfdsZHnFnoZtoA7bOlSjo1ICP0Yz4RsWCJN/8BC 19 | 5/DCsHNjyH0IbRUheqtwasiieBjn+vPduFDbI1jEbwhYjRVFLE4oiW9NJCJl1OOP 20 | w5BugYh6OiAzBKF+OoYV1fxZxJS0tYYVTyzxlZtt6jR3WcdupuzAa/Yn2vhItGPw 21 | qzEdFX+W1KIirozWSqpgtEhUqWA= 22 | -----END CERTIFICATE----- 23 | -------------------------------------------------------------------------------- /SwiftTLS/Sources/TLS/Protocol/TLS 1_2/Messages/Extensions/TLSSecureRenegotiationInfoExtension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TLSSecureRenegotiationInfoExtension.swift 3 | // SwiftTLS 4 | // 5 | // Created by Nico Schmidt on 23/08/2016. 6 | // Copyright © 2016 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct TLSSecureRenegotiationInfoExtension : TLSExtension 12 | { 13 | var extensionType : TLSExtensionType { 14 | get { 15 | return .secureRenegotiationInfo 16 | } 17 | } 18 | 19 | var renegotiatedConnection: [UInt8] 20 | 21 | init(renegotiatedConnection: [UInt8] = []) 22 | { 23 | self.renegotiatedConnection = renegotiatedConnection 24 | } 25 | 26 | init?(inputStream: InputStreamType, messageType: TLSMessageExtensionType) { 27 | guard 28 | let info: [UInt8] = inputStream.read8() 29 | else { 30 | return nil 31 | } 32 | 33 | self.renegotiatedConnection = info 34 | } 35 | 36 | func writeTo(_ target: inout Target, messageType: TLSMessageExtensionType, context: TLSConnection?) { 37 | let extensionsLength = renegotiatedConnection.count + 1 38 | 39 | target.write(self.extensionType.rawValue) 40 | target.write(UInt16(extensionsLength)) 41 | target.write8(renegotiatedConnection) 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /Tests/SwiftTLSTests/TLSReadExtensionsTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TLSReadExtensionsTests.swift 3 | // SwiftTLSTests 4 | // 5 | // Created by Nico Schmidt on 29.07.18. 6 | // Copyright © 2018 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | @testable import SwiftTLS 12 | 13 | class TLSReadExtensionsTests: XCTestCase { 14 | static var allTests = [ 15 | ("test_TLSReadExtensions_withMaliciouslyCraftedInput_doesntGetStuck", test_TLSReadExtensions_withMaliciouslyCraftedInput_doesntGetStuck), 16 | ] 17 | 18 | func test_TLSReadExtensions_withMaliciouslyCraftedInput_doesntGetStuck() { 19 | var extensions: [UInt8] = [] 20 | TLSWriteExtensions(&extensions, 21 | extensions: [TLSEllipticCurvePointFormatsExtension(ellipticCurvePointFormats: [.uncompressed])], 22 | messageType: .clientHello, 23 | context: nil) 24 | 25 | 26 | let appendedBytes: [UInt8] = [0x02, 0x00] 27 | extensions.append(contentsOf: appendedBytes) 28 | 29 | // Reset length 30 | var length = Int(extensions[0]) * 256 + Int(extensions[1]) 31 | length += appendedBytes.count 32 | extensions[0] = UInt8(length >> 8) 33 | extensions[1] = UInt8(length & 0xff) 34 | 35 | let result = TLSReadExtensions(from: BinaryInputStream(extensions), length: extensions.count, messageType: .clientHello, context: nil) 36 | 37 | XCTAssert(result.first as? TLSEllipticCurvePointFormatsExtension != nil) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /SwiftTLS/Sources/TLS/Protocol/TLS 1_3/Messages/TLSEncryptedExtensions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TLSEncryptedExtensions.swift 3 | // SwiftTLS 4 | // 5 | // Created by Nico Schmidt on 18.02.17. 6 | // Copyright © 2017 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | extension TLS1_3 { 12 | class TLSEncryptedExtensions : TLSHandshakeMessage 13 | { 14 | var extensions: [TLSExtension] = [] 15 | 16 | init(extensions: [TLSExtension]) 17 | { 18 | self.extensions = extensions 19 | 20 | super.init(type: .handshake(.encryptedExtensions)) 21 | } 22 | 23 | required init?(inputStream : InputStreamType, context: TLSConnection) 24 | { 25 | guard let (type, bodyLength) = TLSHandshakeMessage.readHeader(inputStream), type == TLSHandshakeType.encryptedExtensions else { 26 | return nil 27 | } 28 | 29 | self.extensions = TLSReadExtensions(from: inputStream, length: bodyLength, messageType: .encryptedExtensions, context: context) 30 | 31 | super.init(type: .handshake(.encryptedExtensions)) 32 | } 33 | 34 | override func writeTo(_ target: inout Target, context: TLSConnection?) 35 | { 36 | var data = [UInt8]() 37 | TLSWriteExtensions(&data, extensions: self.extensions, messageType: .encryptedExtensions, context: context) 38 | 39 | self.writeHeader(type: .encryptedExtensions, bodyLength: data.count, target: &target) 40 | target.write(data) 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /SwiftTLS/Sources/TLS/Protocol/Messages/Extensions/TLSSupportedGroupsExtension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TLSSupportedGroupsExtension.swift 3 | // SwiftTLS 4 | // 5 | // Created by Nico Schmidt on 11.10.15. 6 | // Copyright © 2015 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | struct TLSSupportedGroupsExtension : TLSExtension 10 | { 11 | var extensionType : TLSExtensionType { 12 | get { 13 | return .supportedGroups 14 | } 15 | } 16 | 17 | var ellipticCurves : [NamedGroup] 18 | 19 | init(ellipticCurves : [NamedGroup]) 20 | { 21 | self.ellipticCurves = ellipticCurves 22 | } 23 | 24 | init?(inputStream: InputStreamType, messageType: TLSMessageExtensionType) { 25 | self.ellipticCurves = [] 26 | 27 | guard 28 | let rawEllipticCurves : [UInt16] = inputStream.read16() 29 | else { 30 | return nil 31 | } 32 | 33 | for ec in rawEllipticCurves 34 | { 35 | guard let ellipticCurve = NamedGroup(rawValue: ec) else { 36 | continue 37 | } 38 | 39 | self.ellipticCurves.append(ellipticCurve) 40 | } 41 | } 42 | 43 | func writeTo(_ target: inout Target, messageType: TLSMessageExtensionType, context: TLSConnection?) { 44 | var extensionData: [UInt8] = [] 45 | for ec in self.ellipticCurves { 46 | extensionData.write(ec.rawValue) 47 | } 48 | 49 | target.write(self.extensionType.rawValue) 50 | target.write(UInt16(extensionData.count + 2)) 51 | target.write16(extensionData) 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /SwiftTLS/Sources/TLS/Protocol/TLS 1_3/Messages/TLSHelloRetryRequest.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TLSHelloRetryRequest.swift 3 | // SwiftTLS 4 | // 5 | // Created by Nico Schmidt on 17.04.17. 6 | // Copyright © 2017 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | let helloRetryRequestRandom = Random([ 12 | 0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11, 0xBE, 0x1D, 0x8C, 0x02, 0x1E, 0x65, 0xB8, 0x91, 13 | 0xC2, 0xA2, 0x11, 0x16, 0x7A, 0xBB, 0x8C, 0x5E, 0x07, 0x9E, 0x09, 0xE2, 0xC8, 0xA8, 0x33, 0x9C 14 | ] as [UInt8])! 15 | 16 | class TLSHelloRetryRequest : TLSServerHello 17 | { 18 | init(serverVersion: TLSProtocolVersion, cipherSuite: CipherSuite, extensions: [TLSExtension]) 19 | { 20 | super.init(serverVersion: serverVersion, random: helloRetryRequestRandom, cipherSuite: cipherSuite) 21 | 22 | self.extensions = extensions 23 | } 24 | 25 | override var type : TLSMessageType { 26 | return .handshake(handshakeType) 27 | } 28 | 29 | override var handshakeType: TLSHandshakeType { 30 | return .helloRetryRequest 31 | } 32 | 33 | convenience init(_ serverHello: TLSServerHello) 34 | { 35 | self.init(serverVersion: serverHello.legacyVersion, 36 | cipherSuite: serverHello.cipherSuite, 37 | extensions: serverHello.extensions) 38 | 39 | self.legacySessionID = serverHello.legacySessionID 40 | } 41 | 42 | required init?(inputStream: InputStreamType, context: TLSConnection) { 43 | fatalError("HelloRetryRequest is never directly constructed from an input stream, since the handshake type is serverHello.") 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.7 2 | // The swift-tools-version declares the minimum version of Swift required to build this package. 3 | 4 | import PackageDescription 5 | 6 | let package = Package( 7 | name: "SwiftTLS", 8 | platforms: [.macOS("12.0")], 9 | products: [ 10 | // Products define the executables and libraries produced by a package, and make them visible to other packages. 11 | .library( 12 | name: "SwiftTLS", 13 | targets: ["SwiftTLS"]), 14 | .executable( 15 | name: "tls", 16 | targets: ["tls"] 17 | ) 18 | ], 19 | dependencies: [ 20 | // Dependencies declare other packages that this package depends on. 21 | // .package(url: /* package url */, from: "1.0.0"), 22 | .package(url: "https://github.com/apple/swift-system", from: "1.0.0"), 23 | ], 24 | targets: [ 25 | // Targets are the basic building blocks of a package. A target can define a module or a test suite. 26 | // Targets can depend on other targets in this package, and on products in packages which this package depends on. 27 | .target( 28 | name: "SwiftTLS", 29 | dependencies: [ 30 | .product(name: "SystemPackage", package: "swift-system"), 31 | ], 32 | path: "SwiftTLS", 33 | exclude: ["Sources/Crypto/OldBigInt.swift"], 34 | sources: ["Sources"] 35 | ), 36 | .executableTarget( 37 | name: "tls", 38 | dependencies: ["SwiftTLS"], 39 | path: "SwiftTLSTool", 40 | sources: ["."] 41 | ), 42 | .testTarget( 43 | name: "SwiftTLSTests", 44 | dependencies: ["SwiftTLS"]), 45 | ] 46 | ) 47 | -------------------------------------------------------------------------------- /Tests/SwiftTLSTests/SocketTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SocketTests.swift 3 | // SwiftTLS 4 | // 5 | // Created by Nico Schmidt on 09.05.15. 6 | // Copyright (c) 2015 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import SwiftTLS 11 | 12 | class SocketTests: XCTestCase { 13 | // static var allTests = [ 14 | // ("test_listen_whenClientConnects_callsAcceptBlock", test_listen_whenClientConnects_callsAcceptBlock), 15 | // ] 16 | 17 | func dont_test_listen_whenClientConnects_callsAcceptBlock() async 18 | { 19 | let server = TCPSocket() 20 | var address = IPv4Address.localAddress 21 | address.port = UInt16(12345) 22 | 23 | let expectation = self.expectation(description: "accept connection successfully") 24 | 25 | let _ = Task.detached { [address] in 26 | do { 27 | print("server listen") 28 | try server.listen(on: address) 29 | let _ = try await server.acceptConnection() 30 | 31 | expectation.fulfill() 32 | server.close() 33 | } catch { 34 | 35 | } 36 | } 37 | 38 | sleep(1) 39 | 40 | do { 41 | let client = TCPSocket() 42 | do { 43 | try await client.connect(address) 44 | 45 | // await self.fulfillment(of: [expectation], timeout: 50) 46 | await waitForExpectations(timeout: 50.0, handler: { (error : Error?) -> Void in 47 | }) 48 | } 49 | catch let error as SocketError { 50 | print("\(error)") 51 | XCTFail() 52 | } 53 | catch _ {} 54 | } 55 | 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Tests/SwiftTLSTests/MontgomeryTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MontgomeryTests.swift 3 | // SwiftTLSTests 4 | // 5 | // Created by Nico Schmidt on 28.07.18. 6 | // Copyright © 2018 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | @testable import SwiftTLS 12 | 13 | class MontgomeryTests: XCTestCase { 14 | static var allTests = [ 15 | ("test_multiply_forSomeInput_givesCorrectResult", test_multiply_forSomeInput_givesCorrectResult), 16 | ("test_modular_pow_forSomeInput_givesCorrectResult", test_modular_pow_forSomeInput_givesCorrectResult), 17 | ] 18 | 19 | func test_multiply_forSomeInput_givesCorrectResult() { 20 | BigInt.withContext { _ in 21 | let modulus = BigInt(72639) 22 | let sut = Montgomery(modulus: modulus) 23 | 24 | print((sut.r * sut.rInv) % sut.modulus) 25 | print((sut.modulus * sut.mDash) % sut.r) 26 | 27 | let a = BigInt(5791) 28 | let b = BigInt(1229) 29 | let aMon = sut.montgomeryReduce(BigInt(5791)) 30 | let bMon = sut.montgomeryReduce(BigInt(1229)) 31 | let result = sut.multiply(aMon, bMon) 32 | 33 | XCTAssert((a * b) % modulus == (result * sut.rInv) % modulus) 34 | } 35 | } 36 | 37 | func test_modular_pow_forSomeInput_givesCorrectResult() { 38 | BigInt.withContext { _ in 39 | let modulus = BigInt(72639) 40 | let sut = Montgomery(modulus: modulus) 41 | 42 | let a = BigInt(5791) 43 | let exponent = BigInt(175) 44 | let result = sut.modular_pow(a, exponent) 45 | 46 | XCTAssert(result == modular_pow(a, exponent, modulus)) 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Tests/SwiftTLSTests/SHA1Tests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SHA1Tests.swift 3 | // SwiftTLSTests 4 | // 5 | // Created by Nico Schmidt on 16.04.18. 6 | // Copyright © 2018 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import SwiftTLS 11 | 12 | class SHA1Tests: XCTestCase { 13 | static var allTests = [ 14 | ("test_sha1_withOneBlockMessage_givesCorrectDigest", test_sha1_withOneBlockMessage_givesCorrectDigest), 15 | ("test_sha1_withMultiBlockMessage_givesCorrectDigest", test_sha1_withMultiBlockMessage_givesCorrectDigest), 16 | ("test_sha1_withLongMessage_givesCorrectDigest", test_sha1_withLongMessage_givesCorrectDigest), 17 | ] 18 | 19 | func test_sha1_withOneBlockMessage_givesCorrectDigest() { 20 | let sha1 = SHA1() 21 | sha1.update([UInt8]("abc".utf8)) 22 | let digest = sha1.finalize() 23 | 24 | XCTAssert(digest == [0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a, 0xba, 0x3e, 0x25, 0x71, 0x78, 0x50, 0xc2, 0x6c, 0x9c, 0xd0, 0xd8, 0x9d]) 25 | } 26 | 27 | func test_sha1_withMultiBlockMessage_givesCorrectDigest() { 28 | let digest = SHA1.hash([UInt8]("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq".utf8)) 29 | 30 | XCTAssert(digest == [0x84, 0x98, 0x3e, 0x44, 0x1c, 0x3b, 0xd2, 0x6e, 0xba, 0xae, 0x4a, 0xa1, 0xf9, 0x51, 0x29, 0xe5, 0xe5, 0x46, 0x70, 0xf1]) 31 | } 32 | 33 | func test_sha1_withLongMessage_givesCorrectDigest() { 34 | let message = [UInt8](repeating: [UInt8]("a".utf8)[0], count: 1_000_000) 35 | let digest = SHA1.hash(message) 36 | 37 | XCTAssert(digest == [0x34, 0xaa, 0x97, 0x3c, 0xd4, 0xc4, 0xda, 0xa4, 0xf6, 0x1e, 0xeb, 0x2b, 0xdb, 0xad, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6f]) 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /Tests/SwiftTLSTests/Resources/key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEpQIBAAKCAQEA2ZbtvjgIPEL/VaHj6zPkVkH78KOG+3BY2EbUYgxKOpjyrLph 3 | wl+EysCFUdYZWnSu4EL89TJ+cvtN53kHqeEKvlIoJAxmGScCYa1t4wvNeGBYcWqf 4 | WseWuO7evYTLccr3lIhBD6uJ12Kmqugt74LDMCJ8VKfG8INxJ2dbrr0YjbmFSlDl 5 | RZlTrXHQ8gPqzjz0zcjvp2LzGYkvyBbxczmh4DKX0h6uQi+r95OP2dXSvI18BNDD 6 | hI+GNNYch/vB7MuXAZsJY1tGqwzbKYrE6D/vJ3eArop+R0EcD1pgwpoRFvU9tCE4 7 | bBfN95XJdm+IIQtT+p0u4kBmx2j1iAC87S9RKQIDAQABAoIBAQCfzMOPttD9iOrC 8 | 9iFQRI0GeHFSOpbQpKLrO6GQ3JvLSza2ei9/s+zvhtKi1o1KLHWeSDRE06+gPEXr 9 | oKxrK9ZbDjVivCRjho2uNNOGMs3VAVUS/o5H+lsMOIonP5a2XKzVTfgSTRXvtAjZ 10 | bakGxM8a08jh11I4oyAAI11nCIM22VWHyHBp9pKEUmiC4o6HqVOrYmRaxlYfoYdu 11 | yfBf4RFmFed+8LF/8dilgteuj0tcaVH4ouSdQs6VJMBp+e4SJsHphJBLh6i8Wdae 12 | 3vE8Ds4AtN0UYCKI2v8k1hQhxtexGb2+fidZdS9K9P/exNZZWbcPKMdNLRyAsPle 13 | IqFQPcHxAoGBAO30E8BoCWYGH71huu7wbmYJ3seEfD5rLsUtKkI8KrZ6x9ywpnZM 14 | oHh48fFNBmt5dGhJwamQsHidLvT7dxGdwjw9Y7fbDZ0TJkbH/UqTau14Zw+1uMjh 15 | UHJhhAIH1hSMnRiz3YRuGdKoqvGNDD17I8wRNHFEGQVw78zW3vX2QJaVAoGBAOoX 16 | e3aqsBP56ruRSjykpXO8ka39IkhLXHgaRr3lXpln4L9DqG/IOaqFxveQSe7yWsy2 17 | zf4N+qiZVPhxC3egK7Kke0MWBgQ/Sp23ljto5lXAFyj8XZ2ANPeRloSOyM7jqTGJ 18 | RxpHyFUDwssrRK5hVXlYHE0wWZdxHNm+f4Y4JA9FAoGAHlqMSnb6+/C8C8RzvBcf 19 | fhS0Pm9AChZSGQTx5xEVwcFXzWcbVOvhbHzBIC7bKsqLduIxuhei6z/hxY5uWejt 20 | 5hFOrx1aVzciItVQEjtL4I8DVpWvxLA5Ot4FoNyvCmAFiiknkMUatiyd4cJEVXNn 21 | 1Zg8QFaXeoI1lMO0HVwUUSECgYEA1x09F49Cvxip3DNnRNMIN5LRTFGRb13RW4zJ 22 | 9TcR92a94QULg607ULgeXuD5D9smFXjnUs8FyGke7C71mrhVb5Q2sS9L2BtRNh2+ 23 | sFl1UNd0cPV4EYP/KIFhD+8mGPicQikkbcIJFhaeqpTYSGapZRjS6RvFOKV5HZ8x 24 | EOYGPQECgYEApvwZtdGhnDCk876g/DcDg2KfsPiMqdqVgFxRuUW47gGSfNbVM+2H 25 | fw83YP7v+fFB/MhyZgEZKxEY/DnLhrYnL4ZC+45cMXTYFZYeBv20sjGjWF7LFcQ/ 26 | 7o+2ehyOraCmQi+vs6HMTbW1QNBsiEkWdFqfJG2oAH1nYwvUrNUjeSI= 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /SwiftTLS/Sources/Crypto/BarrettReduction.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BarrettReduction.swift 3 | // SwiftTLS 4 | // 5 | // Created by Nico Schmidt on 24.07.18. 6 | // Copyright © 2018 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | // This is an implementation of Barrett's reduction method as described in 12 | // the Handboook of Applied Cryptography 14.3.3 13 | public struct BarrettReduction : ModularReduction 14 | { 15 | public let modulus: BigInt 16 | let µ: BigInt 17 | public init(modulus: BigInt) { 18 | self.modulus = modulus 19 | 20 | let k = modulus.words.count 21 | let bToThe2k = BigInt(1) << (2 * BigInt.Word.bitWidth * k) 22 | self.µ = bToThe2k / modulus 23 | } 24 | 25 | public func reduce(_ x: BigInt) -> BigInt { 26 | var x = x 27 | guard x.words.count <= modulus.words.count * 2 else { 28 | return x % modulus 29 | } 30 | 31 | let xSign = x.sign 32 | x = x.sign ? -x : x 33 | 34 | let k = modulus.words.count 35 | 36 | let q1 = x >> (BigInt.Word.bitWidth * (k - 1)) 37 | let q2 = q1 * µ 38 | let q3 = q2 >> (BigInt.Word.bitWidth * (k + 1)) 39 | 40 | var r1 = x 41 | r1 = r1.masked(upToHighestBit: BigInt.Word.bitWidth * (k + 1)) 42 | var r2 = q3 * modulus 43 | r2 = r2.masked(upToHighestBit: BigInt.Word.bitWidth * (k + 1)) 44 | 45 | var r = r1 - r2 46 | let tmp = r + BigInt(1) << (BigInt.Word.bitWidth * (k + 1)) 47 | if r.sign { 48 | r = tmp 49 | } 50 | 51 | while r >= modulus { 52 | r = r - modulus 53 | } 54 | 55 | if xSign { 56 | r = modulus - r 57 | } 58 | 59 | return r 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /SwiftTLS/Sources/TLS/Protocol/Messages/Extensions/TLSEllipticCurvePointFormatsExtension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TLSEllipticCurvePointFormatsExtension.swift 3 | // SwiftTLS 4 | // 5 | // Created by Nico Schmidt on 11.10.15. 6 | // Copyright © 2015 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | struct TLSEllipticCurvePointFormatsExtension : TLSExtension 10 | { 11 | var extensionType : TLSExtensionType { 12 | get { 13 | return .ecPointFormats 14 | } 15 | } 16 | 17 | var ellipticCurvePointFormats : [ECPointFormat] 18 | 19 | init(ellipticCurvePointFormats : [ECPointFormat]) 20 | { 21 | self.ellipticCurvePointFormats = ellipticCurvePointFormats 22 | } 23 | 24 | init?(inputStream: InputStreamType, messageType: TLSMessageExtensionType) { 25 | self.ellipticCurvePointFormats = [] 26 | 27 | guard 28 | let rawPointFormats : [UInt8] = inputStream.read8() 29 | else { 30 | return nil 31 | } 32 | 33 | for rawPointFormat in rawPointFormats 34 | { 35 | if let pointFormat = ECPointFormat(rawValue: rawPointFormat) { 36 | self.ellipticCurvePointFormats.append(pointFormat) 37 | } 38 | else { 39 | return nil 40 | } 41 | } 42 | } 43 | 44 | func writeTo(_ target: inout Target, messageType: TLSMessageExtensionType, context: TLSConnection?) { 45 | var extensionData: [UInt8] = [] 46 | for ec in self.ellipticCurvePointFormats { 47 | extensionData.write(ec.rawValue) 48 | } 49 | 50 | target.write(self.extensionType.rawValue) 51 | target.write(UInt16(extensionData.count + 1)) 52 | target.write8(extensionData) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /SwiftTLS/Sources/DataBuffer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DataBuffer.swift 3 | // 4 | // Created by Nico Schmidt on 14.03.15. 5 | // Copyright (c) 2015 Nico Schmidt. All rights reserved. 6 | // 7 | 8 | import Foundation 9 | 10 | class DataBuffer : OutputStreamType 11 | { 12 | var buffer : [UInt8] 13 | 14 | init() 15 | { 16 | buffer = [] 17 | } 18 | 19 | // init(_ streamable : Streamable) 20 | // { 21 | // buffer = [] 22 | // var s = self 23 | // streamable.writeTo(&s) 24 | // } 25 | 26 | func write(_ data : [UInt8]) { 27 | buffer.append(contentsOf: data) 28 | } 29 | 30 | } 31 | 32 | extension Array: OutputStreamType where Element == UInt8 33 | { 34 | init(_ streamable: Streamable, context: TLSConnection? = nil) 35 | { 36 | self.init() 37 | 38 | streamable.writeTo(&self, context: context) 39 | } 40 | 41 | mutating public func write(_ data: [UInt8]) { 42 | self.append(contentsOf: data) 43 | } 44 | } 45 | 46 | extension RangeReplaceableCollection where Iterator.Element == UInt8 47 | { 48 | mutating func write(_ data : [UInt8]) { 49 | self.append(contentsOf: data) 50 | } 51 | } 52 | 53 | class BinaryInputStream : InputStreamType 54 | { 55 | var bytesRead: Int 56 | 57 | private var index = 0 58 | private var data : [UInt8] 59 | private var length : Int 60 | 61 | init(_ data : [UInt8]) 62 | { 63 | self.data = data 64 | self.length = data.count 65 | self.bytesRead = 0 66 | } 67 | 68 | func read(count: Int) -> [UInt8]? { 69 | if index + count <= self.length { 70 | let s = data[index..(_ target: inout Target, messageType: TLSMessageExtensionType, context: TLSConnection?) { 47 | var data: [UInt8] = [] 48 | for algorithm in self.signatureAlgorithms { 49 | data.write(algorithm.rawValue) 50 | } 51 | 52 | let extensionData = data 53 | 54 | target.write(self.extensionType.rawValue) 55 | target.write(UInt16(extensionData.count + 2)) 56 | target.write16(extensionData) 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /SwiftTLS/Sources/Log.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Log.swift 3 | // SwiftTLS 4 | // 5 | // Created by Nico Schmidt on 22.04.18. 6 | // Copyright © 2018 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class LoggingDateFormatter : DateFormatter 12 | { 13 | override init() 14 | { 15 | super.init() 16 | dateFormat = "yyyy-MM-dd HH:mm:ss.SSS" 17 | } 18 | 19 | required init?(coder aDecoder: NSCoder) { 20 | super.init(coder: aDecoder) 21 | } 22 | } 23 | 24 | public class Log 25 | { 26 | @TaskLocal static var connectionNumber: Int? 27 | public static func withConnectionNumber(_ n: Int, _ handler: () async throws -> R) async rethrows -> R { 28 | try await $connectionNumber.withValue(n) { 29 | try await handler() 30 | } 31 | } 32 | 33 | var enabled: Bool = true 34 | fileprivate let formatter = LoggingDateFormatter() 35 | private let logFile: FileHandle = FileHandle(fileDescriptor: 1) 36 | private let logQueue = DispatchQueue(label: "org.swifttls.logging") 37 | 38 | func log(_ message: @autoclosure () -> String, file: StaticString, line: UInt, prefixString: String = "") { 39 | if enabled { 40 | logQueue.sync { 41 | let line = "\(prefixString)\(message())\n" 42 | let utf8 = Data(line.utf8) 43 | 44 | logFile.write(utf8) 45 | } 46 | } 47 | } 48 | } 49 | 50 | private let logger = Log() 51 | public func log(_ message: @autoclosure () -> String, file: StaticString = #file, line: UInt = #line) { 52 | var prefixString = "\(logger.formatter.string(from: Date())) " 53 | if let n = Log.connectionNumber { 54 | prefixString += "~\(n): " 55 | } 56 | 57 | logger.log(message(), file: file, line: line, prefixString: prefixString) 58 | } 59 | 60 | public func TLSEnableLogging(_ v: Bool) { 61 | logger.enabled = v 62 | } 63 | -------------------------------------------------------------------------------- /Tests/macOS/external/openssl/opensslUtils/opensslUtils.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. 3 | * 4 | * The contents of this file constitute Original Code as defined in and are 5 | * subject to the Apple Public Source License Version 1.2 (the 'License'). 6 | * You may not use this file except in compliance with the License. Please obtain 7 | * a copy of the License at http://www.apple.com/publicsource and read it before 8 | * using this file. 9 | * 10 | * This Original Code and all software distributed under the License are 11 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS 12 | * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT 13 | * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 14 | * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the 15 | * specific language governing rights and limitations under the License. 16 | */ 17 | 18 | 19 | /* 20 | * appleUtils.h - Support for ssleay-derived crypto modules 21 | */ 22 | 23 | #ifndef _OPENSSL_UTILS_H_ 24 | #define _OPENSSL_UTILS_H_ 25 | 26 | #include 27 | 28 | #ifdef __cplusplus 29 | extern "C" { 30 | #endif 31 | 32 | /* 33 | * Trivial exception class associated with an openssl error. 34 | */ 35 | class openSslException 36 | { 37 | public: 38 | openSslException( 39 | int irtn, 40 | const char *op = NULL); 41 | ~openSslException() { } 42 | int irtn() { return mIrtn; } 43 | private: 44 | int mIrtn; 45 | }; 46 | 47 | /* Clear openssl error stack. */ 48 | void clearOpensslErrors(); 49 | 50 | unsigned long logSslErrInfo(const char *op); 51 | 52 | void throwRsaDsa( 53 | const char *op); 54 | 55 | /* 56 | * given an openssl-style error, throw appropriate CssmError. 57 | */ 58 | void throwOpensslErr( 59 | int irtn); 60 | 61 | 62 | #ifdef __cplusplus 63 | } 64 | #endif 65 | 66 | #endif /* _OPENSSL_UTILS_H_ */ 67 | -------------------------------------------------------------------------------- /SwiftTLS/Sources/TLS/TLSSession.swift: -------------------------------------------------------------------------------- 1 | // 2 | // File.swift 3 | // SwiftTLS 4 | // 5 | // Created by Nico Schmidt on 18.07.16. 6 | // Copyright © 2016 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class TLSSession 12 | { 13 | let sessionID: TLSSessionID 14 | let peerCertificate: X509.Certificate? 15 | let cipherSpec: CipherSuite 16 | let masterSecret: [UInt8] 17 | 18 | init(sessionID: TLSSessionID, peerCertificate: X509.Certificate? = nil, cipherSpec: CipherSuite, masterSecret: [UInt8]) 19 | { 20 | self.sessionID = sessionID 21 | self.peerCertificate = peerCertificate 22 | self.cipherSpec = cipherSpec 23 | self.masterSecret = masterSecret 24 | } 25 | } 26 | 27 | struct TLSSessionID : Streamable 28 | { 29 | static let MaximumSessionIDLength = 32 30 | 31 | let sessionID : [UInt8] 32 | init(_ sessionID: [UInt8]) 33 | { 34 | self.sessionID = sessionID 35 | } 36 | 37 | static func new() -> TLSSessionID { 38 | let sessionID = TLSRandomBytes(count: MaximumSessionIDLength) 39 | 40 | return TLSSessionID(sessionID) 41 | } 42 | 43 | init?(inputStream : InputStreamType) 44 | { 45 | if let length : UInt8 = inputStream.read() { 46 | if let sessionID : [UInt8] = inputStream.read(count: Int(length)) { 47 | self.sessionID = sessionID 48 | return 49 | } 50 | } 51 | 52 | return nil 53 | } 54 | 55 | func writeTo(_ target: inout Target, context: TLSConnection?) { 56 | target.write8(sessionID) 57 | } 58 | } 59 | 60 | extension TLSSessionID: Hashable { 61 | public func hash(into hasher: inout Hasher) { 62 | hasher.combine(sessionID) 63 | } 64 | } 65 | 66 | func ==(lhs: TLSSessionID, rhs: TLSSessionID) -> Bool { 67 | return lhs.sessionID == rhs.sessionID 68 | } 69 | 70 | -------------------------------------------------------------------------------- /Tests/SwiftTLSTests/SHA256Tests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SHA256Tests.swift 3 | // SwiftTLSTests 4 | // 5 | // Created by Nico Schmidt on 14.04.18. 6 | // Copyright © 2018 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import SwiftTLS 11 | 12 | class SHA256Tests: XCTestCase { 13 | static var allTests = [ 14 | ("test_sha256_withOneBlockMessage_givesCorrectDigest", test_sha256_withOneBlockMessage_givesCorrectDigest), 15 | ("test_sha256_withMultiBlockMessage_givesCorrectDigest", test_sha256_withMultiBlockMessage_givesCorrectDigest), 16 | ("test_sha256_withLongMessage_givesCorrectDigest", test_sha256_withLongMessage_givesCorrectDigest), 17 | ] 18 | 19 | func test_sha256_withOneBlockMessage_givesCorrectDigest() { 20 | let sha = SHA256() 21 | sha.update([UInt8]("abc".utf8)) 22 | let digest = sha.finalize() 23 | 24 | XCTAssert(digest == [0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23, 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c, 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad]) 25 | } 26 | 27 | func test_sha256_withMultiBlockMessage_givesCorrectDigest() { 28 | let digest = SHA256.hash([UInt8]("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq".utf8)) 29 | 30 | XCTAssert(digest == [0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39, 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67, 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1]) 31 | } 32 | 33 | func test_sha256_withLongMessage_givesCorrectDigest() { 34 | let message = [UInt8](repeating: [UInt8]("a".utf8)[0], count: 1_000_000) 35 | let digest = SHA256.hash(message) 36 | 37 | XCTAssert(digest == [0xcd, 0xc7, 0x6e, 0x5c, 0x99, 0x14, 0xfb, 0x92, 0x81, 0xa1, 0xc7, 0xe2, 0x84, 0xd7, 0x3e, 0x67, 0xf1, 0x80, 0x9a, 0x48, 0xa4, 0x97, 0x20, 0x0e, 0x04, 0x6d, 0x39, 0xcc, 0xc7, 0x11, 0x2c, 0xd0]) 38 | } 39 | 40 | } 41 | 42 | -------------------------------------------------------------------------------- /Tests/macOS/external/openssl/openssl/e_os2.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. 3 | * 4 | * The contents of this file constitute Original Code as defined in and are 5 | * subject to the Apple Public Source License Version 1.2 (the 'License'). 6 | * You may not use this file except in compliance with the License. Please obtain 7 | * a copy of the License at http://www.apple.com/publicsource and read it before 8 | * using this file. 9 | * 10 | * This Original Code and all software distributed under the License are 11 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS 12 | * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT 13 | * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 14 | * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the 15 | * specific language governing rights and limitations under the License. 16 | */ 17 | 18 | 19 | /* e_os2.h */ 20 | 21 | #ifndef HEADER_E_OS2_H 22 | #define HEADER_E_OS2_H 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif 27 | 28 | #include /* OPENSSL_UNISTD */ 29 | 30 | #ifdef MSDOS 31 | # define OPENSSL_UNISTD_IO 32 | # define OPENSSL_DECLARE_EXIT extern void exit(int); 33 | #else 34 | # define OPENSSL_UNISTD_IO OPENSSL_UNISTD 35 | # define OPENSSL_DECLARE_EXIT /* declared in unistd.h */ 36 | #endif 37 | 38 | /* Definitions of OPENSSL_GLOBAL and OPENSSL_EXTERN, 39 | to define and declare certain global 40 | symbols that, with some compilers under VMS, have to be defined and 41 | declared explicitely with globaldef and globalref. On other OS:es, 42 | these macros are defined with something sensible. */ 43 | 44 | #if defined(VMS) && !defined(__DECC) 45 | # define OPENSSL_EXTERN globalref 46 | # define OPENSSL_GLOBAL globaldef 47 | #else 48 | # define OPENSSL_EXTERN extern 49 | # define OPENSSL_GLOBAL 50 | #endif 51 | 52 | #ifdef __cplusplus 53 | } 54 | #endif 55 | #endif 56 | 57 | -------------------------------------------------------------------------------- /Tests/SwiftTLSTests/SHA224Tests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SHA224Tests.swift 3 | // SwiftTLSTests 4 | // 5 | // Created by Nico Schmidt on 16.04.18. 6 | // Copyright © 2018 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import SwiftTLS 11 | 12 | class SHA224Tests: XCTestCase { 13 | static var allTests = [ 14 | ("test_sha224_withOneBlockMessage_givesCorrectDigest", test_sha224_withOneBlockMessage_givesCorrectDigest), 15 | ("test_sha224_withMultiBlockMessage_givesCorrectDigest", test_sha224_withMultiBlockMessage_givesCorrectDigest), 16 | ("test_sha224_withLongMessage_givesCorrectDigest", test_sha224_withLongMessage_givesCorrectDigest), 17 | ] 18 | 19 | func test_sha224_withOneBlockMessage_givesCorrectDigest() { 20 | let sha = SHA224() 21 | sha.update([UInt8]("abc".utf8)) 22 | let digest = sha.finalize() 23 | 24 | XCTAssert(digest == [0x23, 0x09, 0x7d, 0x22, 0x34, 0x05, 0xd8, 0x22, 0x86, 0x42, 0xa4, 0x77, 0xbd, 0xa2, 0x55, 0xb3, 0x2a, 0xad, 0xbc, 0xe4, 0xbd, 0xa0, 0xb3, 0xf7, 0xe3, 0x6c, 0x9d, 0xa7]) 25 | } 26 | 27 | func test_sha224_withMultiBlockMessage_givesCorrectDigest() { 28 | let digest = SHA224.hash([UInt8]("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq".utf8)) 29 | 30 | let expectedDigest: [UInt8] = [0x75, 0x38, 0x8b, 0x16, 0x51, 0x27, 0x76, 0xcc, 0x5d, 0xba, 0x5d, 0xa1, 0xfd, 0x89, 0x01, 0x50, 0xb0, 0xc6, 0x45, 0x5c, 0xb4, 0xf5, 0x8b, 0x19, 0x52, 0x52, 0x25, 0x25] 31 | 32 | XCTAssert(digest == expectedDigest) 33 | } 34 | 35 | func test_sha224_withLongMessage_givesCorrectDigest() { 36 | let message = [UInt8](repeating: [UInt8]("a".utf8)[0], count: 1_000_000) 37 | let digest = SHA224.hash(message) 38 | 39 | XCTAssert(digest == [0x20, 0x79, 0x46, 0x55, 0x98, 0x0c, 0x91, 0xd8, 0xbb, 0xb4, 0xc1, 0xea, 0x97, 0x61, 0x8a, 0x4b, 0xf0, 0x3f, 0x42, 0x58, 0x19, 0x48, 0xb2, 0xee, 0x4e, 0xe7, 0xad, 0x67]) 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /Tests/macOS/external/openssl/bn/divtest.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. 3 | * 4 | * The contents of this file constitute Original Code as defined in and are 5 | * subject to the Apple Public Source License Version 1.2 (the 'License'). 6 | * You may not use this file except in compliance with the License. Please obtain 7 | * a copy of the License at http://www.apple.com/publicsource and read it before 8 | * using this file. 9 | * 10 | * This Original Code and all software distributed under the License are 11 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS 12 | * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT 13 | * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 14 | * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the 15 | * specific language governing rights and limitations under the License. 16 | */ 17 | 18 | 19 | #include 20 | #include 21 | 22 | static int rand(n) 23 | { 24 | unsigned char x[2]; 25 | RAND_pseudo_bytes(x,2); 26 | return (x[0] + 2*x[1]); 27 | } 28 | 29 | static void bug(char *m, BIGNUM *a, BIGNUM *b) 30 | { 31 | printf("%s!\na=",m); 32 | BN_print_fp(stdout, a); 33 | printf("\nb="); 34 | BN_print_fp(stdout, b); 35 | printf("\n"); 36 | fflush(stdout); 37 | } 38 | 39 | main() 40 | { 41 | BIGNUM *a=BN_new(), *b=BN_new(), *c=BN_new(), *d=BN_new(), 42 | *C=BN_new(), *D=BN_new(); 43 | BN_RECP_CTX *recp=BN_RECP_CTX_new(); 44 | BN_CTX *ctx=BN_CTX_new(); 45 | 46 | for(;;) { 47 | BN_pseudo_rand(a,rand(),0,0); 48 | BN_pseudo_rand(b,rand(),0,0); 49 | if (BN_is_zero(b)) continue; 50 | 51 | BN_RECP_CTX_set(recp,b,ctx); 52 | if (BN_div(C,D,a,b,ctx) != 1) 53 | bug("BN_div failed",a,b); 54 | if (BN_div_recp(c,d,a,recp,ctx) != 1) 55 | bug("BN_div_recp failed",a,b); 56 | else if (BN_cmp(c,C) != 0 || BN_cmp(c,C) != 0) 57 | bug("mismatch",a,b); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Tests/SwiftTLSTests/SHA384Tests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SHA384.swift 3 | // SwiftTLSTests 4 | // 5 | // Created by Nico Schmidt on 16.04.18. 6 | // Copyright © 2018 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | @testable import SwiftTLS 12 | 13 | class SHA384Tests: XCTestCase { 14 | static var allTests = [ 15 | ("test_sha384_withOneBlockMessage_givesCorrectDigest", test_sha384_withOneBlockMessage_givesCorrectDigest), 16 | ("test_sha384_withMultiBlockMessage_givesCorrectDigest", test_sha384_withMultiBlockMessage_givesCorrectDigest), 17 | ("test_sha384_withLongMessage_givesCorrectDigest", test_sha384_withLongMessage_givesCorrectDigest), 18 | ] 19 | 20 | func test_sha384_withOneBlockMessage_givesCorrectDigest() { 21 | let sha = SHA384() 22 | sha.update([UInt8]("abc".utf8)) 23 | let digest = sha.finalize() 24 | 25 | let expectedDigest = BigInt("cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7", radix: 16)!.asBigEndianData() 26 | 27 | XCTAssert(digest == expectedDigest) 28 | } 29 | 30 | func test_sha384_withMultiBlockMessage_givesCorrectDigest() { 31 | let digest = SHA384.hash([UInt8]("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq".utf8)) 32 | 33 | let expectedDigest = BigInt("3391fdddfc8dc7393707a65b1b4709397cf8b1d162af05abfe8f450de5f36bc6b0455a8520bc4e6f5fe95b1fe3c8452b", radix: 16)!.asBigEndianData() 34 | 35 | XCTAssert(digest == expectedDigest) 36 | } 37 | 38 | func test_sha384_withLongMessage_givesCorrectDigest() { 39 | let message = [UInt8](repeating: [UInt8]("a".utf8)[0], count: 1_000_000) 40 | let digest = SHA384.hash(message) 41 | 42 | let expectedDigest = BigInt("9d0e1809716474cb086e834e310a4a1ced149e9c00f248527972cec5704c2a5b07b8b3dc38ecc4ebae97ddd87f3d8985", radix: 16)!.asBigEndianData() 43 | 44 | XCTAssert(digest == expectedDigest) 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SwiftTLS 2 | 3 | SwiftTLS is a Swift-only implementation of TLS 1.3 and 1.2 that hopes to avoid common classes of vulnerabilities that have traditionally plagued C-based implementations like buffer overflows or generally arbitrary memory accesses. It is written entirely in Swift and has no external dependencies, i.e. all public key crypto, symmetric crypto and hash functions are included. 4 | 5 | SwiftTLS is licensed under the MIT License. 6 | 7 | ## Status 8 | ![](https://github.com/nsc/SwiftTLS/workflows/macOS/badge.svg) ![](https://github.com/nsc/SwiftTLS/workflows/Linux/badge.svg) 9 | 10 | ## Features 11 | Crypto 12 | - RSA-PKCS1 & RSA-PSS, DHE, ECDHE, ECDSA 13 | - CBC and GCM cipher modes 14 | - secp256r1, secp384r1, secp521r1 15 | - AES 16 | - SHA-1, SHA-2 17 | 18 | TLS 1.2 19 | - session resumption 20 | 21 | TLS 1.3 22 | - 0-RTT 23 | - HelloRetryRequest 24 | 25 | 26 | ## Things to try 27 | 28 | swift run -c release tls client --connect swifttls.org 29 | 30 | swift run -c release tls server --port 4433 --certificate /path/to/mycert.pem --dhParameters /path/to/mydhparams.pem 31 | 32 | BigInt performance highly depends on the build configuration, i.e. debug builds are an order of magnitude slower than release builds. So if you want to run the tests it is best to also use the release configuration like this: 33 | 34 | swift test -c release -Xswiftc -enable-testing 35 | 36 | A test server is running at [swifttls.org](https://swifttls.org). 37 | 38 | A good starting point to see how you set up a TLS connection in code is [server.swift](SwiftTLSTool/server.swift) and [client.swift](SwiftTLSTool/client.swift). 39 | 40 | ## Disclaimer 41 | Up until now this project has mainly been an effort for me to learn how TLS works, but I'd love to get your feedback and contributions to improve it. 42 | 43 | Don't use this library in a production environment. It is not ready, has certainly a lot of bugs and received virtually no real world testing yet. 44 | 45 | Performance has not been a primary goal until now, so don't expect too much. 46 | -------------------------------------------------------------------------------- /Tests/SwiftTLSTests/TLSClientKeyExchangeTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TLSClientKeyExchangeTests.swift 3 | // SwiftTLS 4 | // 5 | // Created by Nico Schmidt on 27.03.15. 6 | // Copyright (c) 2015 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import SwiftTLS 11 | 12 | class TLSClientKeyExchangeTests: XCTestCase { 13 | static var allTests = [ 14 | ("test_writeTo__givesDataFromWhichTheSameMessageCanBeConstructed", test_writeTo__givesDataFromWhichTheSameMessageCanBeConstructed), 15 | ] 16 | 17 | func test_writeTo__givesDataFromWhichTheSameMessageCanBeConstructed() 18 | { 19 | class SUT : TLSClientKeyExchange 20 | { 21 | init!() 22 | { 23 | let encryptedPreMasterSecret : [UInt8] = [ 24 | 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16, 25 | 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16, 26 | 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16, 27 | 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] 28 | 29 | var data = [UInt8]() 30 | data.write(TLSHandshakeType.clientKeyExchange.rawValue) 31 | data.writeUInt24(encryptedPreMasterSecret.count) 32 | data.write(UInt16(encryptedPreMasterSecret.count)) 33 | data.write(encryptedPreMasterSecret) 34 | super.init(inputStream: BinaryInputStream(data), context: TLSConnection()) 35 | } 36 | 37 | required init?(inputStream: InputStreamType, context: TLSConnection) { 38 | fatalError("init(inputStream:) has not been implemented") 39 | } 40 | } 41 | 42 | let context = TLSConnection() 43 | var data = [UInt8]() 44 | SUT().writeTo(&data, context: context) 45 | let msg2 = TLSClientKeyExchange(inputStream: BinaryInputStream(data), context: context)! 46 | var data2 = [UInt8]() 47 | msg2.writeTo(&data2, context: context) 48 | 49 | XCTAssertEqual(data, data2) 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /SwiftTLS/Sources/Crypto/Montgomery.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Montgomery.swift 3 | // SwiftTLS 4 | // 5 | // Created by Nico Schmidt on 26.07.18. 6 | // Copyright © 2018 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public struct Montgomery : ModularReduction 12 | { 13 | public let modulus: BigInt 14 | let k: Int 15 | let r: BigInt 16 | let rInv: BigInt 17 | let mDash: BigInt 18 | 19 | public init(modulus: BigInt) { 20 | self.modulus = modulus 21 | self.k = modulus.words.count * MemoryLayout.size * 8 + 1 22 | self.r = BigInt(1) << k 23 | self.rInv = SwiftTLS.modular_inverse(BigInt(1), self.r, mod: self.modulus) 24 | self.mDash = SwiftTLS.modular_inverse(BigInt(-1), self.modulus, mod: self.r) 25 | } 26 | 27 | public func reduce(_ x: BigInt) -> BigInt { 28 | let result = x % modulus 29 | return result < 0 ? result + modulus : result 30 | } 31 | 32 | func montgomeryReduce(_ x: BigInt) -> BigInt { 33 | return reduce(x * r) 34 | } 35 | 36 | func multiply(_ x: BigInt, _ y: BigInt) -> BigInt { 37 | let t = x * y 38 | var m = t * mDash 39 | m = m.masked(upToHighestBit: k) 40 | var u = t + m * modulus 41 | u >>= k 42 | 43 | if u >= modulus { 44 | return u - modulus 45 | } 46 | 47 | return u 48 | } 49 | 50 | public func modular_pow(_ base: BigInt, _ exponent: BigInt, constantTime: Bool = true) -> BigInt { 51 | // let rSquared = reduce(r * r) 52 | let x = montgomeryReduce(base) 53 | 54 | let t = exponent.highestBit 55 | var a = reduce(r) 56 | for i in (0...t).reversed() { 57 | a = multiply(a, a) 58 | 59 | let bit = BigInt(exponent.bit(at: i)) 60 | let tmp = (constantTime || !bit.isZero) ? multiply(a, x) : a 61 | 62 | a = bit * tmp + (BigInt(1) - bit) * a 63 | } 64 | 65 | a = multiply(a, 1) 66 | 67 | return a 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /Tests/SwiftTLSTests/XCTestHelper.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XCTestHelper.swift 3 | // SwiftTLSTests 4 | // 5 | // Created by Nico Schmidt on 27.04.18. 6 | // Copyright © 2018 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | extension XCTestCase { 12 | func path(forResource name: String) -> String { 13 | if let value = ProcessInfo.processInfo.environment["XCTestBundlePath"] { 14 | return Bundle(for: type(of: self)).path(forResource: name, ofType: nil)! 15 | } 16 | else if let value = ProcessInfo.processInfo.environment["XPC_SERVICE_NAME"], 17 | // Xcode pre 11.4 18 | value.contains("com.apple.dt") || 19 | // Xcode >= 11.4 20 | (value.contains("com.apple.xpc.launchd") && value.hasSuffix("Xcode")) { 21 | 22 | return Bundle(for: type(of: self)).path(forResource: name, ofType: nil)! 23 | } 24 | 25 | let resourcesPath = "Tests/SwiftTLSTests/Resources/" 26 | return resourcesPath.appending(name) 27 | } 28 | 29 | #if os(macOS) 30 | func allTestMethodNames() -> [String] { 31 | var methodNames: [String] = [] 32 | 33 | let c = type(of: self) 34 | var numberOfMethods: UInt32 = 0 35 | let methods = UnsafeBufferPointer(start: class_copyMethodList(c, &numberOfMethods), count: Int(numberOfMethods)) 36 | for method in methods { 37 | let s = method_getName(method) 38 | let name = NSStringFromSelector(s) 39 | 40 | // If the method starts with "test" and has return type void ('v' == 0x76) 41 | if name.hasPrefix("test") && method_copyReturnType(method).pointee == Int8(0x76) { 42 | methodNames.append(name) 43 | } 44 | } 45 | 46 | return methodNames 47 | } 48 | 49 | func printAllTests() { 50 | print("static var allTests = [") 51 | for methodName in allTestMethodNames() { 52 | print("(\"\(methodName)\", \(methodName)),") 53 | } 54 | print("]") 55 | } 56 | #endif 57 | } 58 | -------------------------------------------------------------------------------- /SwiftTLS/Sources/TLS/Protocol/TLS 1_3/Messages/Extensions/TLSEarlyDataIndication.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TLSEarlyDataIndication.swift 3 | // SwiftTLS 4 | // 5 | // Created by Nico Schmidt on 07.04.18. 6 | // Copyright © 2018 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct TLSEarlyDataIndication : TLSExtension 12 | { 13 | var extensionType : TLSExtensionType { 14 | get { 15 | return .earlyData 16 | } 17 | } 18 | 19 | var maxEarlyDataSize: UInt32? 20 | init(maxEarlyDataSize: UInt32? = nil) 21 | { 22 | self.maxEarlyDataSize = maxEarlyDataSize 23 | } 24 | 25 | init?(inputStream: InputStreamType, messageType: TLSMessageExtensionType) { 26 | 27 | switch messageType { 28 | case .newSessionTicket: 29 | guard let size: UInt32 = inputStream.read() else { 30 | return nil 31 | } 32 | 33 | self.maxEarlyDataSize = size 34 | 35 | case .clientHello, .encryptedExtensions: 36 | break 37 | 38 | default: 39 | return nil 40 | } 41 | } 42 | 43 | func writeTo(_ target: inout Target, messageType: TLSMessageExtensionType, context: TLSConnection?) { 44 | 45 | let extensionData: [UInt8] 46 | switch messageType { 47 | case .clientHello, .encryptedExtensions: 48 | extensionData = [] 49 | case .newSessionTicket: 50 | guard let maxEarlyDataSize = self.maxEarlyDataSize else { 51 | fatalError("EarlyDataIndication extension in NewSessionTicket is missing maxEarlyDataSize") 52 | } 53 | 54 | extensionData = UInt32(maxEarlyDataSize).bigEndianBytes 55 | 56 | default: 57 | fatalError("EarlyDataIndication is not allowed in \(messageType)") 58 | } 59 | 60 | target.write(self.extensionType.rawValue) 61 | target.write(UInt16(extensionData.count)) 62 | target.write(extensionData) 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /Tests/SwiftTLSTests/SHA512Tests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SHA512Tests.swift 3 | // SwiftTLSTests 4 | // 5 | // Created by Nico Schmidt on 16.04.18. 6 | // Copyright © 2018 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import SwiftTLS 11 | 12 | class SHA512Tests: XCTestCase { 13 | static var allTests = [ 14 | ("test_sha512_withOneBlockMessage_givesCorrectDigest", test_sha512_withOneBlockMessage_givesCorrectDigest), 15 | ("test_sha512_withMultiBlockMessage_givesCorrectDigest", test_sha512_withMultiBlockMessage_givesCorrectDigest), 16 | ("test_sha512_withLongMessage_givesCorrectDigest", test_sha512_withLongMessage_givesCorrectDigest), 17 | ] 18 | 19 | func test_sha512_withOneBlockMessage_givesCorrectDigest() { 20 | let sha = SHA512() 21 | sha.update([UInt8]("abc".utf8)) 22 | let digest = sha.finalize() 23 | 24 | let expectedDigest = BigInt("ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f", radix: 16)!.asBigEndianData() 25 | 26 | XCTAssert(digest == expectedDigest) 27 | } 28 | 29 | func test_sha512_withMultiBlockMessage_givesCorrectDigest() { 30 | let digest = SHA512.hash([UInt8]("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq".utf8)) 31 | 32 | let expectedDigest = BigInt("204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a8279be331a703c33596fd15c13b1b07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445", radix: 16)!.asBigEndianData() 33 | 34 | XCTAssert(digest == expectedDigest) 35 | } 36 | 37 | func test_sha512_withLongMessage_givesCorrectDigest() { 38 | let message = [UInt8](repeating: [UInt8]("a".utf8)[0], count: 1_000_000) 39 | let digest = SHA512.hash(message) 40 | 41 | let expectedDigest = BigInt("e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973ebde0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b", radix: 16)!.asBigEndianData() 42 | 43 | XCTAssert(digest == expectedDigest) 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /SwiftTLSTool/scan.swift: -------------------------------------------------------------------------------- 1 | // 2 | // scan.swift 3 | // swifttls 4 | // 5 | // Created by Nico Schmidt on 05.04.18. 6 | // Copyright © 2018 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | /* 11 | func scan() 12 | { 13 | class StateMachine : TLSClientStateMachine 14 | { 15 | internal var state: TLSState = .idle 16 | 17 | var shouldStopHandshake: Bool = false 18 | 19 | weak var socket : TLSSocket! 20 | init(socket : TLSSocket) 21 | { 22 | self.socket = socket 23 | } 24 | 25 | func shouldContinueHandshake(with message: TLSHandshakeMessage) -> Bool 26 | { 27 | return !shouldStopHandshake 28 | } 29 | 30 | func didReceiveHandshakeMessage(_ message: TLSHandshakeMessage) throws { 31 | guard let certificate = message as? TLSCertificateMessage else { 32 | return 33 | } 34 | 35 | for certificate in certificate.certificates { 36 | print("-----BEGIN CERTIFICATE-----") 37 | print(Data(bytes: certificate.data).base64EncodedString()) 38 | print("-----END CERTIFICATE-----") 39 | } 40 | } 41 | 42 | func didReceiveAlert(_ alert: TLSAlertMessage) { 43 | } 44 | } 45 | 46 | // let address = IPAddress.addressWithString("www.google.com", port: 443)! 47 | 48 | let socket = TLSClientSocket(supportedVersions: [.v1_2]) 49 | let stateMachine = StateMachine(socket: socket) 50 | socket.connection.stateMachine = stateMachine 51 | 52 | socket.connection.configuration.cipherSuites = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256, CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256] 53 | 54 | do { 55 | try socket.connect(hostname: "www.google.com") 56 | } catch let error as SocketError { 57 | switch error { 58 | case .closed: 59 | socket.close() 60 | 61 | default: 62 | print("Error: \(error)") 63 | } 64 | } 65 | catch { 66 | print("Unhandled error: \(error)") 67 | } 68 | 69 | } 70 | */ 71 | -------------------------------------------------------------------------------- /Tests/SwiftTLSTests/Resources/Self Signed RSA-PSS SHA-256.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFyzCCA4OgAwIBAgIUKJr6Jqz7Ou9MIs17s/uVaIH2feMwPQYJKoZIhvcNAQEK 3 | MDCgDTALBglghkgBZQMEAgGhGjAYBgkqhkiG9w0BAQgwCwYJYIZIAWUDBAIBogMC 4 | AUAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM 5 | GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0xODA0MDQxNzE4MDNaFw0xOTA0 6 | MDQxNzE4MDNaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw 7 | HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggIiMA0GCSqGSIb3DQEB 8 | AQUAA4ICDwAwggIKAoICAQDAYcVNBAkYSF63YeREL5RW1ZSKhPJsRbJ9Nq3ib1GC 9 | LKXYMKmJazUFm4nfnMaJQ0+GJBTUkFbIs9El4gy2+mHlxmDEuaW4Xu0j48BlCUS6 10 | fmofJ3Arigfm0ebO819hK+QK2pWmDYmOcheXU6rbptp2dvhbsh+K+/826XHPLoV+ 11 | QwMgVSQgqfDzbKVnx+ez4TZpiP+PNodYQQ9Bd0yjW/emBRcL2ilp+K6bVoAMX2OC 12 | 3D2CRJayV+bkG+xZvlz8ooGTqYWhDdkVvL0khNpny5WDoguLVgrrOpUDeD4xMtOu 13 | Fe38yGhAS/VLupRzopiJ14bOGiqUoadfsKV6du+va7ZeQYLZESzfhHCImE2eE1BT 14 | qpZe3KNqt0s/4t6jHSv3Re7ev13RdD7/ksSu/QhEN/OmMAT0y5PMShAVsukGZY2e 15 | lHK0m6bJGQtfQWns7lyAIDr87Tjr+gDIcnojlbPxRlm18eLB+iMb0yjBeEvJqHId 16 | TeVPHqtPF027U6r4bNSrEBUSLPSViYidd6/fv+1oQNo7b65GIHyNXbl+7MrY3VH6 17 | CXXLywVVPNNAF5RC0B9SCi03B22z9nC2z79X2RBbUSyBhIPlQXBsKlJLDvrbQMok 18 | 3GB07h+mnyqWx8WPpitzbRp+VzczcX2el59XHm7nCK/QcriPxmVX+GaBofWc6Tza 19 | BQIDAQABo1MwUTAdBgNVHQ4EFgQUhQzlLkrSJSnRiAuxhHBVXqWG9tgwHwYDVR0j 20 | BBgwFoAUhQzlLkrSJSnRiAuxhHBVXqWG9tgwDwYDVR0TAQH/BAUwAwEB/zA9Bgkq 21 | hkiG9w0BAQowMKANMAsGCWCGSAFlAwQCAaEaMBgGCSqGSIb3DQEBCDALBglghkgB 22 | ZQMEAgGiAwIBQAOCAgEAO80WppOjhK1tO3DS7jnnM7+wNUe8xWG5xmNlufrlR+uu 23 | JTJ3gNyYMP5fyQsBqUFNJy6rsPbZAlANaxVoGu/wD6ILCS9MWjtz/soPG7fhnvuy 24 | xXbCIl7WJ/QQCMKJTqRd7OQyCt8OVn+J8n9vR5gN5wI7r03HmSFRGv7SGEYxixUI 25 | N77RE0hBiKLCbPPH1WKLjbVCxkiFwFMOcDOKaXccdjFPGgK3crtO4x0XtLEs02SN 26 | vX8ftT2JfktxtV1NHEMES+PnZwzMFrOaH+SaYvuVI31/XEY9+cJuT7UD6MWjz/Pc 27 | Fum5GG/cWQSdg1HyvMxiCuuyRn/iDMTRY13yq46IvV4GC6L0x4A/iOrdcSzhytTv 28 | MJ8rDWtafyUQx47lw4HqTnLYvPshoXEgDFAScX+UbB2R2FpwooE/n3gy3+iCMscT 29 | aVnmbSqINrc3OHlL12y+9j6I+j1sX0pb267tBimieARkKFr8qV9RC9j8P3vDdvAi 30 | mLEF0UnoHamepheQhnS8o7dZPPg51TF7fi0HAJHogW90Ao1EhvjyHexyp1lq+0BO 31 | rXwc/vaNhMRDVa+RUaVPZlvRL5VzSAEUMrIuM0XEpR2fy3Y3hGMh3jLRxe8SLolK 32 | PU+J0aeOyTEkqQ0lGZjOFTyOzoFuot7vniE0Y7oebw8phu+zZI4L0I0J9ajzc0M= 33 | -----END CERTIFICATE----- 34 | -------------------------------------------------------------------------------- /Tests/SwiftTLSTests/TLSRecordTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TLSRecordTests.swift 3 | // 4 | // Created by Nico Schmidt on 14.03.15. 5 | // Copyright (c) 2015 Nico Schmidt. All rights reserved. 6 | // 7 | 8 | import XCTest 9 | @testable import SwiftTLS 10 | 11 | class TLSRecordTests: XCTestCase { 12 | static var allTests = [ 13 | ("test_data_withBody_givesCorrectBinaryRepresention", test_data_withBody_givesCorrectBinaryRepresention), 14 | ("test_data_withContentTypeChangeCipherSpec_givesCorrectBinaryRepresention", test_data_withContentTypeChangeCipherSpec_givesCorrectBinaryRepresention), 15 | ("test_data_withContentTypeAlert_givesCorrectBinaryRepresention", test_data_withContentTypeAlert_givesCorrectBinaryRepresention), 16 | ("test_data_withContentTypeHandshake_givesCorrectBinaryRepresention", test_data_withContentTypeHandshake_givesCorrectBinaryRepresention), 17 | ] 18 | 19 | func test_data_withBody_givesCorrectBinaryRepresention() { 20 | let record = TLSRecord(contentType: .changeCipherSpec, protocolVersion: .v1_2, body: [1,2,3,4,5]) 21 | 22 | let data = [UInt8](record) 23 | 24 | XCTAssert(data == [UInt8]([20, 3, 3, 0, 5, 1, 2, 3, 4, 5])) 25 | } 26 | 27 | func test_data_withContentTypeChangeCipherSpec_givesCorrectBinaryRepresention() { 28 | let record = TLSRecord(contentType: .changeCipherSpec, protocolVersion: .v1_2,body: [UInt8(0xff)]) 29 | 30 | let data = [UInt8](record) 31 | 32 | XCTAssert(data == [UInt8]([20, 3, 3, 0, 1, 0xff])) 33 | } 34 | 35 | func test_data_withContentTypeAlert_givesCorrectBinaryRepresention() { 36 | let record = TLSRecord(contentType: .alert, protocolVersion: .v1_2, body: [UInt8(0xff)]) 37 | 38 | let data = [UInt8](record) 39 | 40 | XCTAssert(data == [UInt8]([21, 3, 3, 0, 1, 0xff])) 41 | } 42 | 43 | func test_data_withContentTypeHandshake_givesCorrectBinaryRepresention() { 44 | let record = TLSRecord(contentType: .handshake, protocolVersion: .v1_2, body: [UInt8(0xff)]) 45 | 46 | let data = [UInt8](record) 47 | 48 | XCTAssert(data == [UInt8]([22, 3, 3, 0, 1, 0xff])) 49 | } 50 | 51 | 52 | 53 | } 54 | -------------------------------------------------------------------------------- /SwiftTLS/Sources/Crypto/ECDHKeyExchange.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ECDHKeyExchange.swift 3 | // SwiftTLS 4 | // 5 | // Created by Nico Schmidt on 11.10.15. 6 | // Copyright © 2015 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | class ECDHKeyExchange 10 | { 11 | let curve : EllipticCurve 12 | 13 | var d : BigInt? 14 | var Q : EllipticCurvePoint? 15 | var publicKeyPoint: EllipticCurvePoint? { 16 | Q 17 | } 18 | var peerPublicKeyPoint : EllipticCurvePoint? 19 | 20 | init(curve : EllipticCurve) 21 | { 22 | self.curve = curve 23 | } 24 | 25 | func createPublicKeyPoint() -> EllipticCurvePoint 26 | { 27 | createKeyPair() 28 | 29 | return self.Q! 30 | } 31 | 32 | // dA * dB * G 33 | func calculateSharedSecret(with peerPublicKeyPoint : EllipticCurvePoint? = nil) -> BigInt? 34 | { 35 | guard 36 | let d = self.d, 37 | let peerPublicKeyPoint = peerPublicKeyPoint ?? self.peerPublicKeyPoint 38 | else { 39 | return nil 40 | } 41 | 42 | return self.curve.multiplyPoint(peerPublicKeyPoint, d).x 43 | } 44 | 45 | func createKeyPair() { 46 | let (d, Q) = self.curve.createKeyPair() 47 | 48 | self.d = d 49 | self.Q = Q 50 | } 51 | } 52 | 53 | extension ECDHKeyExchange : PFSKeyExchange 54 | { 55 | var publicKey: [UInt8]? { 56 | get { 57 | guard let Q = self.Q else { 58 | return nil 59 | } 60 | 61 | return [UInt8](Q) 62 | } 63 | } 64 | 65 | var peerPublicKey: [UInt8]? { 66 | get { 67 | guard let peerPublicKeyPoint = self.peerPublicKeyPoint else { return nil } 68 | 69 | return [UInt8](peerPublicKeyPoint) 70 | } 71 | 72 | set { 73 | if let value = newValue { 74 | self.peerPublicKeyPoint = EllipticCurvePoint(data: value) 75 | } 76 | } 77 | } 78 | func calculateSharedSecret() -> [UInt8]? { 79 | guard self.peerPublicKeyPoint != nil else { return nil } 80 | 81 | return (self.calculateSharedSecret() as BigInt?)?.asBigEndianData() 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /SwiftTLS/Sources/TLS/Protocol/Messages/Extensions/TLSServerNameExtension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TLSServerNameExtension.swift 3 | // SwiftTLS 4 | // 5 | // Created by Nico Schmidt on 02.09.15. 6 | // Copyright © 2015 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | enum TLSServerNameType : UInt8 12 | { 13 | case hostName = 0 14 | } 15 | 16 | struct TLSServerNameExtension : TLSExtension 17 | { 18 | var extensionType : TLSExtensionType { 19 | get { 20 | return .serverName 21 | } 22 | } 23 | 24 | var serverNames : [String] 25 | 26 | init(serverNames: [String]) 27 | { 28 | self.serverNames = serverNames 29 | } 30 | 31 | init?(inputStream: InputStreamType, messageType: TLSMessageExtensionType) { 32 | guard 33 | let serverNamesLength : UInt16 = inputStream.read() 34 | else { 35 | return nil 36 | } 37 | 38 | self.serverNames = [] 39 | 40 | var bytesLeft = Int(serverNamesLength) 41 | while bytesLeft > 0 { 42 | if let rawNameType : UInt8 = inputStream.read(), 43 | let serverNameBytes : [UInt8] = inputStream.read16() 44 | { 45 | if TLSServerNameType(rawValue: rawNameType) == nil { 46 | fatalError("Unknown host type \(rawNameType)") 47 | } 48 | 49 | self.serverNames.append(String.fromUTF8Bytes(serverNameBytes)!) 50 | 51 | bytesLeft -= 3 + serverNameBytes.count 52 | } 53 | else { 54 | break 55 | } 56 | } 57 | } 58 | 59 | func writeTo(_ target: inout Target, messageType: TLSMessageExtensionType, context: TLSConnection?) { 60 | var extensionData: [UInt8] = [] 61 | for serverName in self.serverNames { 62 | let utf8 = [UInt8](serverName.utf8) 63 | extensionData.write(TLSServerNameType.hostName.rawValue) 64 | extensionData.write16(utf8) 65 | } 66 | 67 | target.write(self.extensionType.rawValue) 68 | target.write(UInt16(extensionData.count + 2)) 69 | target.write16(extensionData) 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /Tests/macOS/external/openssl/openssl/opensslv.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. 3 | * 4 | * The contents of this file constitute Original Code as defined in and are 5 | * subject to the Apple Public Source License Version 1.2 (the 'License'). 6 | * You may not use this file except in compliance with the License. Please obtain 7 | * a copy of the License at http://www.apple.com/publicsource and read it before 8 | * using this file. 9 | * 10 | * This Original Code and all software distributed under the License are 11 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS 12 | * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT 13 | * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 14 | * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the 15 | * specific language governing rights and limitations under the License. 16 | */ 17 | 18 | 19 | #ifndef HEADER_OPENSSLV_H 20 | #define HEADER_OPENSSLV_H 21 | 22 | /* Numeric release version identifier: 23 | * MMNNFFPPS: major minor fix patch status 24 | * The status nibble has one of the values 0 for development, 1 to e for betas 25 | * 1 to 14, and f for release. The patch level is exactly that. 26 | * For example: 27 | * 0.9.3-dev 0x00903000 28 | * 0.9.3-beta1 0x00903001 29 | * 0.9.3-beta2-dev 0x00903002 30 | * 0.9.3-beta2 0x00903002 (same as ...beta2-dev) 31 | * 0.9.3 0x0090300f 32 | * 0.9.3a 0x0090301f 33 | * 0.9.4 0x0090400f 34 | * 1.2.3z 0x102031af 35 | * 36 | * For continuity reasons (because 0.9.5 is already out, and is coded 37 | * 0x00905100), between 0.9.5 and 0.9.6 the coding of the patch level 38 | * part is slightly different, by setting the highest bit. This means 39 | * that 0.9.5a looks like this: 0x0090581f. At 0.9.6, we can start 40 | * with 0x0090600S... 41 | * 42 | * (Prior to 0.9.3-dev a different scheme was used: 0.9.2b is 0x0922.) 43 | * (Prior to 0.9.5a beta1, a different scheme was used: MMNNFFRBB for 44 | * major minor fix final patch/beta) 45 | */ 46 | #define OPENSSL_VERSION_NUMBER 0x0090581fL 47 | #define OPENSSL_VERSION_TEXT "OpenSSL 0.9.5a 1 Apr 2000" 48 | #define OPENSSL_VERSION_PTEXT " part of " OPENSSL_VERSION_TEXT 49 | 50 | #endif /* HEADER_OPENSSLV_H */ 51 | -------------------------------------------------------------------------------- /Tests/macOS/external/openssl/bn/exp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. 3 | * 4 | * The contents of this file constitute Original Code as defined in and are 5 | * subject to the Apple Public Source License Version 1.2 (the 'License'). 6 | * You may not use this file except in compliance with the License. Please obtain 7 | * a copy of the License at http://www.apple.com/publicsource and read it before 8 | * using this file. 9 | * 10 | * This Original Code and all software distributed under the License are 11 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS 12 | * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT 13 | * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 14 | * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the 15 | * specific language governing rights and limitations under the License. 16 | */ 17 | 18 | 19 | /* unused */ 20 | 21 | #include 22 | #include 23 | #include "bn_lcl.h" 24 | 25 | #define SIZE 256 26 | #define NUM (8*8*8) 27 | #define MOD (8*8*8*8*8) 28 | 29 | main(argc,argv) 30 | int argc; 31 | char *argv[]; 32 | { 33 | BN_CTX ctx; 34 | BIGNUM a,b,c,r,rr,t,l; 35 | int j,i,size=SIZE,num=NUM,mod=MOD; 36 | char *start,*end; 37 | BN_MONT_CTX mont; 38 | double d,md; 39 | 40 | BN_MONT_CTX_init(&mont); 41 | BN_CTX_init(&ctx); 42 | BN_init(&a); 43 | BN_init(&b); 44 | BN_init(&c); 45 | BN_init(&r); 46 | 47 | start=ms_time_new(); 48 | end=ms_time_new(); 49 | while (size <= 1024*8) 50 | { 51 | BN_rand(&a,size,0,0); 52 | BN_rand(&b,size,1,0); 53 | BN_rand(&c,size,0,1); 54 | 55 | BN_mod(&a,&a,&c,&ctx); 56 | 57 | ms_time_get(start); 58 | for (i=0; i<10; i++) 59 | BN_MONT_CTX_set(&mont,&c,&ctx); 60 | ms_time_get(end); 61 | md=ms_time_diff(start,end); 62 | 63 | ms_time_get(start); 64 | for (i=0; i Bool 24 | // { 25 | // if let hello = message as? TLSServerHello { 26 | // print("\(hello.cipherSuite)") 27 | // 28 | // return false 29 | // } 30 | // 31 | // return true 32 | // } 33 | // 34 | // func didReceiveAlert(_ alert: TLSAlertMessage) { 35 | // // print("\(cipherSuite) not supported") 36 | // // print("NO") 37 | // } 38 | // } 39 | 40 | guard let address = IPv6Address.addressWithString(host, port: port) else { print("Error: No such host \(host)"); return } 41 | 42 | let cipherSuites = CipherSuite.allValues.filter({ 43 | // TLS 1.3 cipher suites are currently only in the range 0x1300...0x1305 44 | if protocolVersion == .v1_3 { 45 | return ($0.rawValue & 0xff00) == 0x1300 46 | } 47 | 48 | return ($0.rawValue & 0xff00) != 0x1300 49 | }) 50 | 51 | for cipherSuite in cipherSuites { 52 | let client = TLSClient(configuration: TLSConfiguration(supportedVersions: [protocolVersion])) 53 | 54 | client.configuration.cipherSuites = [cipherSuite] 55 | 56 | do { 57 | try await client.connect(address) 58 | } catch let error as SocketError { 59 | switch error { 60 | case .closed: 61 | await client.close() 62 | 63 | default: 64 | print("Error: \(error)") 65 | } 66 | } 67 | catch { 68 | // print("Unhandled error: \(error)") 69 | } 70 | } 71 | } 72 | 73 | -------------------------------------------------------------------------------- /SwiftTLS/Sources/TLS/PEMFileIdentity.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PEMFileIdentity.swift 3 | // SwiftTLS 4 | // 5 | // Created by Nico Schmidt on 02.07.16. 6 | // Copyright © 2016 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public class PEMFileIdentity 12 | { 13 | public var certificateChain: [X509.Certificate] 14 | public func signer(with hashAlgorithm: HashAlgorithm) -> Signing { 15 | switch _signing { 16 | case is RSA: 17 | var rsa = _signing as! RSA 18 | switch rsa.algorithm { 19 | case .rsa_pkcs1(hash: _): 20 | rsa.algorithm = .rsa_pkcs1(hash: hashAlgorithm) 21 | case .rsassa_pss(hash: _, saltLength: let saltLength): 22 | rsa.algorithm = .rsassa_pss(hash: hashAlgorithm, saltLength: saltLength) 23 | default: 24 | fatalError("Unimplemented RSA algorithm \(rsa.algorithm)") 25 | } 26 | 27 | return rsa 28 | 29 | case is ECDSA: 30 | fatalError("ECDSA certificates are currently unsupported") 31 | 32 | default: 33 | fatalError("Unsupported certificate \(_signing)") 34 | } 35 | } 36 | 37 | private var _signing: Signing 38 | 39 | public init?(certificateFile: String, privateKeyFile: String) 40 | { 41 | if let rsa = RSA.fromPEMFile(privateKeyFile) { 42 | _signing = rsa 43 | } 44 | else if let ecdsa = ECDSA.fromPEMFile(privateKeyFile) { 45 | _signing = ecdsa 46 | } 47 | else { 48 | return nil 49 | } 50 | 51 | certificateChain = [] 52 | for (section, object) in ASN1Parser.sectionsFromPEMFile(certificateFile) { 53 | switch section { 54 | case "CERTIFICATE": 55 | if let certificate = X509.Certificate(derData: object.underlyingData!) { 56 | certificateChain.append(certificate) 57 | } 58 | default: 59 | break 60 | } 61 | } 62 | 63 | if certificateChain.count == 0 { 64 | return nil 65 | } 66 | } 67 | 68 | public convenience init?(pemFile: String) 69 | { 70 | self.init(certificateFile: pemFile, privateKeyFile: pemFile) 71 | } 72 | } 73 | 74 | extension PEMFileIdentity : Identity {} 75 | -------------------------------------------------------------------------------- /SwiftTLS/Sources/Crypto/DHKeyExchange.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DHKeyExchange.swift 3 | // SwiftTLS 4 | // 5 | // Created by Nico Schmidt on 02.08.15. 6 | // Copyright © 2015 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | public class DHKeyExchange 10 | { 11 | let primeModulus : BigInt 12 | let generator : BigInt 13 | 14 | var privateKey : BigInt? 15 | var Ys : BigInt? 16 | var Yc : BigInt? 17 | 18 | 19 | init(dhParameters: DiffieHellmanParameters) 20 | { 21 | self.primeModulus = dhParameters.p 22 | self.generator = dhParameters.g 23 | self.Ys = dhParameters.Ys 24 | } 25 | 26 | init(primeModulus : BigInt, generator : BigInt) 27 | { 28 | self.primeModulus = primeModulus 29 | self.generator = generator 30 | } 31 | 32 | func createKeyPair() 33 | { 34 | self.privateKey = BigInt.random(self.primeModulus) 35 | self.Ys = modular_pow(self.generator, self.privateKey!, primeModulus) 36 | } 37 | 38 | func calculatePublicKey() -> BigInt 39 | { 40 | assert(self.privateKey == nil) 41 | 42 | createKeyPair() 43 | 44 | return self.Ys! 45 | } 46 | 47 | func calculateSharedSecret() -> BigInt? 48 | { 49 | guard let peerPublicKey = self.Yc else { 50 | return nil 51 | } 52 | 53 | 54 | if self.privateKey == nil { 55 | self.createKeyPair() 56 | } 57 | 58 | assert(peerPublicKey != self.privateKey!) 59 | 60 | return modular_pow(peerPublicKey, self.privateKey!, self.primeModulus) 61 | } 62 | } 63 | 64 | extension DHKeyExchange : PFSKeyExchange 65 | { 66 | var publicKey: [UInt8]? { 67 | return self.Ys?.asBigEndianData() 68 | } 69 | 70 | var peerPublicKey: [UInt8]? { 71 | get { 72 | guard let peerPublicKey = self.Yc else { return nil } 73 | 74 | return peerPublicKey.asBigEndianData() 75 | } 76 | 77 | set { 78 | guard let value = newValue else { return } 79 | 80 | self.Yc = BigInt(bigEndianParts: value) 81 | } 82 | } 83 | func calculateSharedSecret() -> [UInt8]? { 84 | guard self.Yc != nil else { return nil } 85 | 86 | return self.calculateSharedSecret()?.asBigEndianData() 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /Tests/macOS/external/openssl/bf/COPYRIGHT: -------------------------------------------------------------------------------- 1 | Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) 2 | All rights reserved. 3 | 4 | This package is an Blowfish implementation written 5 | by Eric Young (eay@cryptsoft.com). 6 | 7 | This library is free for commercial and non-commercial use as long as 8 | the following conditions are aheared to. The following conditions 9 | apply to all code found in this distribution. 10 | 11 | Copyright remains Eric Young's, and as such any Copyright notices in 12 | the code are not to be removed. 13 | 14 | Redistribution and use in source and binary forms, with or without 15 | modification, are permitted provided that the following conditions 16 | are met: 17 | 1. Redistributions of source code must retain the copyright 18 | notice, this list of conditions and the following disclaimer. 19 | 2. Redistributions in binary form must reproduce the above copyright 20 | notice, this list of conditions and the following disclaimer in the 21 | documentation and/or other materials provided with the distribution. 22 | 3. All advertising materials mentioning features or use of this software 23 | must display the following acknowledgement: 24 | This product includes software developed by Eric Young (eay@cryptsoft.com) 25 | 26 | THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 27 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 | ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 30 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 | OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 | SUCH DAMAGE. 37 | 38 | The license and distribution terms for any publically available version or 39 | derivative of this code cannot be changed. i.e. this code cannot simply be 40 | copied and put under another distrubution license 41 | [including the GNU Public License.] 42 | 43 | The reason behind this being stated in this direct manner is past 44 | experience in code simply being copied and the attribution removed 45 | from it and then being distributed as part of other packages. This 46 | implementation was a non-trivial and unpaid effort. 47 | -------------------------------------------------------------------------------- /SwiftTLS/Sources/TLS/Protocol/Messages/TLSCertificateVerify.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TLSCertificateVerify.swift 3 | // SwiftTLS 4 | // 5 | // Created by Nico Schmidt on 19.02.17. 6 | // Copyright © 2017 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | extension TLS1_3 { 12 | class TLSCertificateVerify : TLSHandshakeMessage 13 | { 14 | let algorithm: TLSSignatureScheme 15 | let signature: [UInt8] 16 | 17 | init(algorithm: TLSSignatureScheme, signature: [UInt8]) 18 | { 19 | self.algorithm = algorithm 20 | self.signature = signature 21 | 22 | super.init(type: .handshake(.certificateVerify)) 23 | } 24 | 25 | required init?(inputStream : InputStreamType, context: TLSConnection) 26 | { 27 | guard let (type, bodyLength) = TLSHandshakeMessage.readHeader(inputStream), type == TLSHandshakeType.certificateVerify else { 28 | return nil 29 | } 30 | 31 | guard let rawSignatureScheme: UInt16 = inputStream.read() else { 32 | return nil 33 | } 34 | 35 | guard let signatureScheme = TLSSignatureScheme(rawValue: rawSignatureScheme) else { 36 | log("Error: Unknown signature scheme \(String(format: "0x%hs", rawSignatureScheme))") 37 | return nil 38 | } 39 | log("Signature scheme \(String(format: "0x%04hx", rawSignatureScheme))") 40 | 41 | guard let signature: [UInt8] = inputStream.read16() else { 42 | return nil 43 | } 44 | 45 | guard bodyLength == (2 + 2 + signature.count) else { 46 | log("Error: excess data in CertificateVerify message") 47 | return nil 48 | } 49 | 50 | self.algorithm = signatureScheme 51 | self.signature = signature 52 | 53 | super.init(type: .handshake(.certificateVerify)) 54 | } 55 | 56 | override func writeTo(_ target: inout Target, context: TLSConnection?) 57 | { 58 | var data: [UInt8] = [] 59 | 60 | data.write(self.algorithm.rawValue) 61 | data.write16(signature) 62 | 63 | self.writeHeader(type: .certificateVerify, bodyLength: data.count, target: &target) 64 | target.write(data) 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /SwiftTLS/Sources/TLS/Protocol/TLS 1_3/Messages/Extensions/TLSPSKKeyExchangeModesExtension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TLSPSKKeyExchangeModesExtension.swift 3 | // SwiftTLS 4 | // 5 | // Created by Nico Schmidt on 26.03.18. 6 | // Copyright © 2018 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | enum PSKKeyExchangeMode : UInt8 12 | { 13 | case psk = 0 14 | case psk_dhe = 1 15 | } 16 | 17 | struct TLSPSKKeyExchangeModesExtension : TLSExtension 18 | { 19 | var extensionType : TLSExtensionType { 20 | get { 21 | return .pskKeyExchangeModes 22 | } 23 | } 24 | 25 | var keyExchangeModes: [PSKKeyExchangeMode] 26 | 27 | init(keyExchangeModes: [PSKKeyExchangeMode]) 28 | { 29 | self.keyExchangeModes = keyExchangeModes 30 | } 31 | 32 | init?(inputStream: InputStreamType, messageType: TLSMessageExtensionType) { 33 | 34 | switch messageType { 35 | case .clientHello: 36 | guard let numBytes8 : UInt8 = inputStream.read() else { 37 | return nil 38 | } 39 | 40 | var numBytes = Int(numBytes8) 41 | var keyExchangeModes: [PSKKeyExchangeMode] = [] 42 | 43 | while numBytes > 0 { 44 | let bytesRead = inputStream.bytesRead 45 | 46 | guard 47 | let rawKeyExchangeMode: UInt8 = inputStream.read(), 48 | let keyExchangeMode = PSKKeyExchangeMode(rawValue: rawKeyExchangeMode) 49 | else { 50 | return nil 51 | } 52 | 53 | numBytes -= (inputStream.bytesRead - bytesRead) 54 | 55 | keyExchangeModes.append(keyExchangeMode) 56 | } 57 | 58 | self.keyExchangeModes = keyExchangeModes 59 | 60 | default: 61 | return nil 62 | } 63 | } 64 | 65 | func writeTo(_ target: inout Target, messageType: TLSMessageExtensionType, context: TLSConnection?) { 66 | 67 | guard messageType == .clientHello else { 68 | fatalError("PSKKeyExchangeModes extension is only supported in ClientHello") 69 | } 70 | 71 | let rawKeyExchangeModes = self.keyExchangeModes.map({$0.rawValue}) 72 | 73 | let extensionData = rawKeyExchangeModes 74 | 75 | target.write(self.extensionType.rawValue) 76 | target.write(UInt16(extensionData.count + 1)) 77 | target.write8(extensionData) 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /SwiftTLS/Sources/Crypto/BinaryInteger+Extensions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BinaryInteger+Extensions.swift 3 | // SwiftTLS 4 | // 5 | // Created by Nico Schmidt on 22.02.18. 6 | // Copyright © 2018 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | extension BinaryInteger { 12 | func isBitSet(_ bitNumber : Int) -> Bool 13 | { 14 | let wordSize = MemoryLayout.size * 8 15 | let wordNumber = bitNumber / wordSize 16 | let bit = bitNumber % wordSize 17 | 18 | // guard let words = self.words as? Array else { 19 | // fatalError("isBitSet is not implemented for anything but mutable buffer pointers") 20 | // } 21 | 22 | guard let words = self.words as? BigIntStorage else { 23 | fatalError("isBitSet is not implemented for anything but BigIntSotrage") 24 | } 25 | 26 | guard wordNumber < words.count else { 27 | return false 28 | } 29 | 30 | return (UInt64(words[wordNumber]) & (UInt64(1) << UInt64(bit))) != 0 31 | } 32 | 33 | /// Retrieve the bit at the indicated position 34 | /// 35 | /// This method can be used to construct timing independent code that depends on 36 | /// whether the bit is set or not without taking a branch, e.g. 37 | /// 38 | /// instead of saying: 39 | /// 40 | /// let a = b.bit(at: position) ? resultA : resultC 41 | /// 42 | /// you can say: 43 | /// 44 | /// let a = b.bit(at: position) * resultA + (1 - b.bit(at: position)) * resultC 45 | /// - Parameter position: the position of the bit to be retrieved 46 | /// - Returns: returns the specified bit as 0 or 1 47 | func bit(at position: Int) -> Int { 48 | let wordSize = MemoryLayout.size * 8 49 | let wordNumber = position / wordSize 50 | let bit = position % wordSize 51 | 52 | guard let words = self.words as? BigIntStorage else { 53 | fatalError("bit(at:) is not implemented for anything but BigIntSotrage") 54 | } 55 | 56 | guard wordNumber < words.count else { 57 | return 0 58 | } 59 | 60 | return Int((UInt64(words[wordNumber]) & (UInt64(1) << UInt64(bit))) >> UInt64(bit)) 61 | } 62 | 63 | var highestBit: Int { 64 | let wordSize = MemoryLayout.size * 8 65 | 66 | guard let words = self.words as? BigIntStorage else { 67 | fatalError("highestBit is not implemented for anything but BigIntSotrage") 68 | } 69 | 70 | guard let firstWord = words.last else { 71 | return -1 72 | } 73 | 74 | return wordSize * words.count - firstWord.leadingZeroBitCount 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /SwiftTLSTool/client.swift: -------------------------------------------------------------------------------- 1 | // 2 | // client.swift 3 | // swifttls 4 | // 5 | // Created by Nico Schmidt on 05.04.18. 6 | // Copyright © 2018 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import SwiftTLS 11 | 12 | func connectTo(host : String, port : UInt16 = 443, supportedVersions: [TLSProtocolVersion] = [.v1_3, .v1_2], cipherSuite : CipherSuite? = nil) async throws 13 | { 14 | var configuration: TLSConfiguration 15 | 16 | if let cipherSuite = cipherSuite { 17 | configuration = TLSConfiguration(supportedVersions: cipherSuite.descriptor!.supportedProtocolVersions) 18 | configuration.cipherSuites = [cipherSuite] 19 | } 20 | else { 21 | configuration = TLSConfiguration(supportedVersions: supportedVersions) 22 | } 23 | 24 | configuration.earlyData = .supported(maximumEarlyDataSize: 4096) 25 | 26 | // Connect twice to test session resumption 27 | var context: TLSClientContext? = nil 28 | var connectionNumber = 0 29 | try await BigInt.withContext { _ in 30 | var client: TLSClient 31 | for _ in 0..<2 { 32 | do { 33 | print("Connecting to \(host):\(port)") 34 | client = TLSClient(configuration: configuration, context: context) 35 | 36 | connectionNumber += 1 37 | try await Log.withConnectionNumber(connectionNumber) { 38 | 39 | let requestData = [UInt8]("GET / HTTP/1.1\r\nHost: \(host)\r\nUser-Agent: SwiftTLS\r\nConnection: Close\r\n\r\n".utf8) 40 | try await client.connect(hostname: host, port: port, withEarlyData: Data(requestData)) 41 | 42 | let earlyDataState = client.earlyDataState 43 | print("Early data: \(earlyDataState)") 44 | 45 | if context == nil { 46 | context = client.context as? TLSClientContext 47 | } 48 | 49 | print("Connection established using cipher suite \(client.cipherSuite!)") 50 | 51 | if earlyDataState != .accepted { 52 | try await client.write(requestData) 53 | } 54 | 55 | while true { 56 | let data = try await client.read(count: 4096) 57 | if data.count == 0 { 58 | break 59 | } 60 | 61 | _ = data.withUnsafeBytes { buffer in 62 | write(1, buffer.baseAddress, buffer.count) 63 | } 64 | 65 | break 66 | } 67 | } 68 | } 69 | catch (let error) { 70 | await client.close() 71 | 72 | print("Error: \(error)") 73 | } 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /SwiftTLS/Sources/TLS/math.swift: -------------------------------------------------------------------------------- 1 | // 2 | // math.swift 3 | // SwiftTLS 4 | // 5 | // Created by Nico Schmidt on 18.11.15. 6 | // Copyright © 2015 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | // result: (quotient, remainder) 10 | func division(_ a : T, _ b : T) -> (T, T) 11 | { 12 | return a.quotientAndRemainder(dividingBy: b) 13 | } 14 | 15 | public func modular_pow(_ base : BigInt, _ exponent : BigInt, _ mod : BigInt) -> BigInt 16 | { 17 | return BarrettReduction(modulus: mod).modular_pow(base, exponent) 18 | } 19 | 20 | //public func modular_pow(_ base : T, _ exponent : T, _ mod : T) -> T 21 | //{ 22 | // let numBits = exponent.bitWidth 23 | // 24 | // // Check for leading zero bits to avoid a couple iterations of (r * r) % mod 25 | // var result = T(1) 26 | // var r = base % mod 27 | // for i in 0..(_ x : T, _ y : T) -> T 40 | { 41 | var g : T = y 42 | 43 | var x = x 44 | var y = y 45 | 46 | while x > 0 { 47 | g = x 48 | x = y % x 49 | y = g 50 | } 51 | 52 | return g 53 | } 54 | 55 | func extended_euclid(z : T, a : T) -> T 56 | { 57 | var i = a 58 | var j = z 59 | var y1 : T = 1 60 | var y2 : T = 0 61 | 62 | let zero : T = 0 63 | while j > zero 64 | { 65 | let (quotient, remainder) = division(i, j) 66 | 67 | let y = y2 - y1 * quotient 68 | 69 | i = j 70 | j = remainder 71 | y2 = y1 72 | y1 = y 73 | } 74 | 75 | return y2 % a 76 | } 77 | 78 | //public func modular_inverse(_ x : BigInt, _ y : BigInt, mod : BigInt) -> BigInt 79 | //{ 80 | // return BarrettReduction(modulus: mod).modular_inverse(x, y) 81 | //} 82 | // 83 | public func modular_inverse(_ x : T, _ y : T, mod : T) -> T 84 | { 85 | let x = x > 0 ? x : x + mod 86 | let y = y > 0 ? y : y + mod 87 | 88 | let inverse = extended_euclid(z: y, a: mod) 89 | 90 | var result = (inverse * x) % mod 91 | 92 | let zero : T = 0 93 | if result < zero { 94 | result = result + mod 95 | } 96 | 97 | return result 98 | } 99 | 100 | public func modular_inverse(_ x : BigInt, _ y : BigInt, mod : BigInt, context: UnsafeMutablePointer? = nil) -> BigInt 101 | { 102 | let x = x > 0 ? x : x + mod 103 | let y = y > 0 ? y : y + mod 104 | 105 | let inverse = extended_euclid(z: y, a: mod) 106 | 107 | var result = BigInt.divide(BigInt.multiply(inverse, x, context: context), mod).1 108 | 109 | let zero = BigInt(0) 110 | if result < zero { 111 | result = result + mod 112 | } 113 | 114 | return result 115 | } 116 | -------------------------------------------------------------------------------- /SwiftTLS/Sources/TLS/Protocol/TLS 1_3/Messages/Extensions/TLSSupportedVersionsExtension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TLSSupportedVersionsExtension.swift 3 | // SwiftTLS 4 | // 5 | // Created by Nico Schmidt on 04.11.16. 6 | // Copyright © 2016 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct TLSSupportedVersionsExtension : TLSExtension 12 | { 13 | var extensionType : TLSExtensionType { 14 | get { 15 | return .supportedVersions 16 | } 17 | } 18 | 19 | var supportedVersions: [TLSProtocolVersion] 20 | 21 | init(supportedVersions : [TLSProtocolVersion]) 22 | { 23 | self.supportedVersions = supportedVersions 24 | } 25 | 26 | init?(inputStream: InputStreamType, messageType: TLSMessageExtensionType) { 27 | self.supportedVersions = [] 28 | 29 | switch messageType { 30 | 31 | case .clientHello: 32 | guard 33 | let rawSupportedVersions : [UInt16] = inputStream.read8() 34 | else { 35 | return nil 36 | } 37 | 38 | for rawVersion in rawSupportedVersions 39 | { 40 | if let version = TLSProtocolVersion(rawValue: rawVersion) { 41 | self.supportedVersions.append(version) 42 | } 43 | else { 44 | return nil 45 | } 46 | } 47 | 48 | case .serverHello, .helloRetryRequest: 49 | guard 50 | let rawSupportedVersion: UInt16 = inputStream.read() 51 | else { 52 | return nil 53 | } 54 | 55 | guard let version = TLSProtocolVersion(rawValue: rawSupportedVersion) else { 56 | return nil 57 | } 58 | 59 | self.supportedVersions.append(version) 60 | 61 | default: 62 | fatalError("Supported Version is not a valid extension in \(extensionType)") 63 | return nil 64 | } 65 | } 66 | 67 | func writeTo(_ target: inout Target, messageType: TLSMessageExtensionType, context: TLSConnection?) { 68 | switch messageType { 69 | case .clientHello: 70 | var data: [UInt8] = [] 71 | for version in self.supportedVersions { 72 | data.write(version.rawValue) 73 | } 74 | 75 | let extensionData = data 76 | 77 | target.write(self.extensionType.rawValue) 78 | target.write(UInt16(extensionData.count + 1)) 79 | target.write8(extensionData) 80 | 81 | case .serverHello: 82 | target.write(self.extensionType.rawValue) 83 | target.write(UInt16(2)) 84 | target.write(self.supportedVersions.first!.rawValue) 85 | 86 | default: 87 | fatalError("Unsupported message type \(messageType)") 88 | } 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /SwiftTLS/Sources/TLS/Protocol/Messages/TLSMessage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TLSMessage.swift 3 | // 4 | // Created by Nico Schmidt on 16.03.15. 5 | // Copyright (c) 2015 Nico Schmidt. All rights reserved. 6 | // 7 | 8 | import Foundation 9 | 10 | enum TLSHandshakeType : UInt8 { 11 | // TLS 1.0 12 | case helloRequest = 0 13 | case clientHello = 1 14 | case serverHello = 2 15 | case certificate = 11 16 | case certificateRequest = 13 17 | case certificateVerify = 15 18 | case finished = 20 19 | 20 | // TLS 1.0 - 1.2 only, not in TLS 1.3 21 | case serverKeyExchange = 12 22 | case serverHelloDone = 14 23 | case clientKeyExchange = 16 24 | case certificateURL = 21 25 | case certificateStatus = 22 26 | 27 | // new in TLS 1.3 28 | case newSessionTicket = 4 // TLS 1.3 29 | case endOfEarlyData = 5 // TLS 1.3 30 | case helloRetryRequest = 6 // TLS 1.3 31 | case encryptedExtensions = 8 // TLS 1.3 32 | case keyUpdate = 24 // TLS 1.3 33 | 34 | case messageHash = 254 35 | } 36 | 37 | enum TLSMessageType 38 | { 39 | case changeCipherSpec 40 | case handshake(TLSHandshakeType) 41 | case alert(TLSAlertLevel, TLSAlert) 42 | case applicationData 43 | } 44 | 45 | enum TLSChangeCipherSpecType : UInt8 46 | { 47 | case changeCipherSpec = 1 48 | } 49 | 50 | public class TLSMessage : Streamable 51 | { 52 | private var _type: TLSMessageType 53 | var type : TLSMessageType { 54 | return _type 55 | } 56 | 57 | var contentType : ContentType { 58 | get { 59 | let contentType : ContentType 60 | switch (self.type) 61 | { 62 | case .changeCipherSpec: 63 | contentType = .changeCipherSpec 64 | 65 | case .alert: 66 | contentType = .alert 67 | 68 | case .handshake: 69 | contentType = .handshake 70 | 71 | case .applicationData: 72 | contentType = .applicationData 73 | } 74 | 75 | return contentType 76 | } 77 | } 78 | 79 | init(type : TLSMessageType) 80 | { 81 | self._type = type 82 | } 83 | 84 | required public init?(inputStream: InputStreamType, context: TLSConnection) { 85 | return nil 86 | } 87 | 88 | public func writeTo(_ target: inout Target, context: TLSConnection?) 89 | { 90 | } 91 | 92 | func messageData(with context: TLSConnection) -> [UInt8] { 93 | if let messageData = self.rawMessageData { 94 | return messageData 95 | } 96 | else { 97 | var messageData: [UInt8] = [] 98 | self.writeTo(&messageData, context: context) 99 | 100 | return messageData 101 | } 102 | } 103 | 104 | var rawMessageData : [UInt8]? 105 | } 106 | -------------------------------------------------------------------------------- /Tests/SwiftTLSTests/Resources/mycert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDoDCCAoigAwIBAgIJAMCOKb3Xq5WVMA0GCSqGSIb3DQEBBQUAMD4xCzAJBgNV 3 | BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMRowGAYDVQQKExFTb21lIE9yZ2Fu 4 | aXphdGlvbjAeFw0xNjA3MDExOTI2NTZaFw0xOTAzMjgxOTI2NTZaMD4xCzAJBgNV 5 | BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMRowGAYDVQQKExFTb21lIE9yZ2Fu 6 | aXphdGlvbjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANmW7b44CDxC 7 | /1Wh4+sz5FZB+/CjhvtwWNhG1GIMSjqY8qy6YcJfhMrAhVHWGVp0ruBC/PUyfnL7 8 | Ted5B6nhCr5SKCQMZhknAmGtbeMLzXhgWHFqn1rHlrju3r2Ey3HK95SIQQ+riddi 9 | pqroLe+CwzAifFSnxvCDcSdnW669GI25hUpQ5UWZU61x0PID6s489M3I76di8xmJ 10 | L8gW8XM5oeAyl9IerkIvq/eTj9nV0ryNfATQw4SPhjTWHIf7wezLlwGbCWNbRqsM 11 | 2ymKxOg/7yd3gK6KfkdBHA9aYMKaERb1PbQhOGwXzfeVyXZviCELU/qdLuJAZsdo 12 | 9YgAvO0vUSkCAwEAAaOBoDCBnTAdBgNVHQ4EFgQUQNrv3J/RQsA3ZbcZ8lCpLOII 13 | KYswbgYDVR0jBGcwZYAUQNrv3J/RQsA3ZbcZ8lCpLOIIKYuhQqRAMD4xCzAJBgNV 14 | BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMRowGAYDVQQKExFTb21lIE9yZ2Fu 15 | aXphdGlvboIJAMCOKb3Xq5WVMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD 16 | ggEBAKt0+512kBUEcPQNLqBd41kjr13NvRMH6I/iHr9Mw/R9lHsIeExJNiwV0PMH 17 | oVZNUBhJO5YSXBok1S+0whNboMkbEiZ4qco1Qjx6yng/vN7zzGFheksNxzyQR7a8 18 | Q4pnykfCubb7a1q0X9O1YTneqEfdsZHnFnoZtoA7bOlSjo1ICP0Yz4RsWCJN/8BC 19 | 5/DCsHNjyH0IbRUheqtwasiieBjn+vPduFDbI1jEbwhYjRVFLE4oiW9NJCJl1OOP 20 | w5BugYh6OiAzBKF+OoYV1fxZxJS0tYYVTyzxlZtt6jR3WcdupuzAa/Yn2vhItGPw 21 | qzEdFX+W1KIirozWSqpgtEhUqWA= 22 | -----END CERTIFICATE----- 23 | -----BEGIN RSA PRIVATE KEY----- 24 | MIIEpQIBAAKCAQEA2ZbtvjgIPEL/VaHj6zPkVkH78KOG+3BY2EbUYgxKOpjyrLph 25 | wl+EysCFUdYZWnSu4EL89TJ+cvtN53kHqeEKvlIoJAxmGScCYa1t4wvNeGBYcWqf 26 | WseWuO7evYTLccr3lIhBD6uJ12Kmqugt74LDMCJ8VKfG8INxJ2dbrr0YjbmFSlDl 27 | RZlTrXHQ8gPqzjz0zcjvp2LzGYkvyBbxczmh4DKX0h6uQi+r95OP2dXSvI18BNDD 28 | hI+GNNYch/vB7MuXAZsJY1tGqwzbKYrE6D/vJ3eArop+R0EcD1pgwpoRFvU9tCE4 29 | bBfN95XJdm+IIQtT+p0u4kBmx2j1iAC87S9RKQIDAQABAoIBAQCfzMOPttD9iOrC 30 | 9iFQRI0GeHFSOpbQpKLrO6GQ3JvLSza2ei9/s+zvhtKi1o1KLHWeSDRE06+gPEXr 31 | oKxrK9ZbDjVivCRjho2uNNOGMs3VAVUS/o5H+lsMOIonP5a2XKzVTfgSTRXvtAjZ 32 | bakGxM8a08jh11I4oyAAI11nCIM22VWHyHBp9pKEUmiC4o6HqVOrYmRaxlYfoYdu 33 | yfBf4RFmFed+8LF/8dilgteuj0tcaVH4ouSdQs6VJMBp+e4SJsHphJBLh6i8Wdae 34 | 3vE8Ds4AtN0UYCKI2v8k1hQhxtexGb2+fidZdS9K9P/exNZZWbcPKMdNLRyAsPle 35 | IqFQPcHxAoGBAO30E8BoCWYGH71huu7wbmYJ3seEfD5rLsUtKkI8KrZ6x9ywpnZM 36 | oHh48fFNBmt5dGhJwamQsHidLvT7dxGdwjw9Y7fbDZ0TJkbH/UqTau14Zw+1uMjh 37 | UHJhhAIH1hSMnRiz3YRuGdKoqvGNDD17I8wRNHFEGQVw78zW3vX2QJaVAoGBAOoX 38 | e3aqsBP56ruRSjykpXO8ka39IkhLXHgaRr3lXpln4L9DqG/IOaqFxveQSe7yWsy2 39 | zf4N+qiZVPhxC3egK7Kke0MWBgQ/Sp23ljto5lXAFyj8XZ2ANPeRloSOyM7jqTGJ 40 | RxpHyFUDwssrRK5hVXlYHE0wWZdxHNm+f4Y4JA9FAoGAHlqMSnb6+/C8C8RzvBcf 41 | fhS0Pm9AChZSGQTx5xEVwcFXzWcbVOvhbHzBIC7bKsqLduIxuhei6z/hxY5uWejt 42 | 5hFOrx1aVzciItVQEjtL4I8DVpWvxLA5Ot4FoNyvCmAFiiknkMUatiyd4cJEVXNn 43 | 1Zg8QFaXeoI1lMO0HVwUUSECgYEA1x09F49Cvxip3DNnRNMIN5LRTFGRb13RW4zJ 44 | 9TcR92a94QULg607ULgeXuD5D9smFXjnUs8FyGke7C71mrhVb5Q2sS9L2BtRNh2+ 45 | sFl1UNd0cPV4EYP/KIFhD+8mGPicQikkbcIJFhaeqpTYSGapZRjS6RvFOKV5HZ8x 46 | EOYGPQECgYEApvwZtdGhnDCk876g/DcDg2KfsPiMqdqVgFxRuUW47gGSfNbVM+2H 47 | fw83YP7v+fFB/MhyZgEZKxEY/DnLhrYnL4ZC+45cMXTYFZYeBv20sjGjWF7LFcQ/ 48 | 7o+2ehyOraCmQi+vs6HMTbW1QNBsiEkWdFqfJG2oAH1nYwvUrNUjeSI= 49 | -----END RSA PRIVATE KEY----- 50 | -------------------------------------------------------------------------------- /SwiftTLS/Sources/TLS/Protocol/Messages/TLSAlert.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TLSAlert.swift 3 | // SwiftTLS 4 | // 5 | // Created by Nico Schmidt on 26.03.15. 6 | // Copyright (c) 2015 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public enum TLSAlertLevel : UInt8 12 | { 13 | case warning = 1 14 | case fatal = 2 15 | } 16 | 17 | public enum TLSAlert : UInt8 18 | { 19 | case closeNotify = 0 20 | case unexpectedMessage = 10 21 | case badRecordMAC = 20 22 | case decryptionFailed_RESERVED = 21 23 | case recordOverflow = 22 24 | case decompressionFailure = 30 25 | case handshakeFailure = 40 26 | case noCertificate = 41 // SSLv3 only 27 | case badCertificate = 42 28 | case unsupportedCertificate = 43 29 | case certificateRevoked = 44 30 | case certificateExpired = 45 31 | case certificateUnknown = 46 32 | case illegalParameter = 47 33 | case unknownCA = 48 34 | case accessDenied = 49 35 | case decodeError = 50 36 | case decryptError = 51 37 | case exportRestriction = 60 38 | case protocolVersion = 70 39 | case insufficientSecurity = 71 40 | case internalError = 80 41 | case userCancelled = 90 42 | case noRenegotiation = 100 43 | case missingExtension = 109 44 | case unsupportedExtension = 110 45 | case certificateUnobtainable = 111 46 | case unrecognizedName = 112 47 | case badCertificateStatusResponse = 113 48 | case badCertificateHashValue = 114 49 | case unknownPSKIdentity = 115 50 | case certificateRequired = 116 51 | case noApplicationProtocol = 120 52 | 53 | } 54 | 55 | public class TLSAlertMessage : TLSMessage 56 | { 57 | let alertLevel : TLSAlertLevel 58 | let alert : TLSAlert 59 | 60 | init(alert: TLSAlert, alertLevel: TLSAlertLevel) 61 | { 62 | self.alertLevel = alertLevel 63 | self.alert = alert 64 | 65 | super.init(type: .alert(alertLevel, alert)) 66 | } 67 | 68 | public required init?(inputStream: InputStreamType, context: TLSConnection) 69 | { 70 | guard let level : UInt8 = inputStream.read(), 71 | let alertLevel = TLSAlertLevel(rawValue: level), 72 | let rawAlert : UInt8 = inputStream.read() 73 | else { 74 | return nil 75 | } 76 | 77 | if let alert = TLSAlert(rawValue: rawAlert) 78 | { 79 | self.alertLevel = alertLevel 80 | self.alert = alert 81 | } 82 | else { 83 | fatalError("Unkown alert: \(rawAlert)") 84 | return nil 85 | } 86 | 87 | super.init(type: .alert(self.alertLevel, self.alert)) 88 | } 89 | 90 | override public func writeTo(_ target: inout Target, context: TLSConnection?) 91 | { 92 | let data = [alertLevel.rawValue, alert.rawValue] 93 | target.write(data) 94 | } 95 | 96 | class func alertFromData(_ data : [UInt8], context: TLSConnection) -> TLSAlertMessage? 97 | { 98 | return TLSAlertMessage(inputStream: BinaryInputStream(data), context: context) 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /SwiftTLS/Sources/TLS/TLSRecord.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TLSRecord.swift 3 | // 4 | // Created by Nico Schmidt on 14.03.15. 5 | // Copyright (c) 2015 Nico Schmidt. All rights reserved. 6 | // 7 | 8 | import Foundation 9 | 10 | enum ContentType : UInt8 { 11 | case changeCipherSpec = 20 12 | case alert = 21 13 | case handshake = 22 14 | case applicationData = 23 15 | } 16 | 17 | let TLS_RecordHeaderLength = 5 18 | 19 | class TLSRecord : Streamable { 20 | var contentType : ContentType 21 | var protocolVersion : TLSProtocolVersion 22 | var body : [UInt8] 23 | 24 | required init?(inputStream: InputStreamType) { 25 | 26 | var contentType : ContentType? 27 | var protocolVersion : TLSProtocolVersion? 28 | var body : [UInt8]? 29 | 30 | if let c : UInt8 = inputStream.read() { 31 | if let ct = ContentType(rawValue: c) { 32 | contentType = ct 33 | } 34 | } 35 | 36 | if let major: UInt8 = inputStream.read(), 37 | let minor: UInt8 = inputStream.read() 38 | { 39 | protocolVersion = TLSProtocolVersion(major: major, minor: minor) 40 | } 41 | 42 | if let bodyLength: UInt16 = inputStream.read() { 43 | body = inputStream.read(count: Int(bodyLength)) 44 | } 45 | 46 | if let c = contentType, 47 | let v = protocolVersion, 48 | let b = body 49 | { 50 | self.contentType = c 51 | self.protocolVersion = v 52 | self.body = b 53 | } 54 | else { 55 | return nil 56 | } 57 | } 58 | 59 | init(contentType : ContentType, protocolVersion: TLSProtocolVersion, body : [UInt8]) 60 | { 61 | self.contentType = contentType 62 | self.protocolVersion = protocolVersion 63 | self.body = body 64 | } 65 | 66 | class var headerProbeLength : Int { 67 | get { 68 | return TLS_RecordHeaderLength 69 | } 70 | } 71 | 72 | class func probeHeader(_ headerData : [UInt8]) -> (contentType: ContentType, bodyLength : Int)? 73 | { 74 | if headerData.count < TLS_RecordHeaderLength { 75 | return nil 76 | } 77 | 78 | let rawContentType = headerData[0] 79 | if let contentType = ContentType(rawValue: rawContentType) { 80 | let bodyLength = Int(headerData[3]) << 8 + Int(headerData[4]) 81 | return (contentType, bodyLength) 82 | } 83 | 84 | return nil 85 | } 86 | 87 | class func writeRecordHeader(_ target: inout Target, contentType: ContentType, protocolVersion : TLSProtocolVersion, contentLength : Int) 88 | { 89 | target.write(contentType.rawValue) 90 | target.write(protocolVersion.rawValue) 91 | target.write(UInt16(contentLength)) 92 | } 93 | 94 | func writeTo(_ target: inout Target, context: TLSConnection?) 95 | { 96 | type(of: self).writeRecordHeader(&target, contentType: self.contentType, protocolVersion: self.protocolVersion, contentLength: self.body.count) 97 | target.write(self.body) 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /SwiftTLS/Sources/Crypto/SwiftTLSCrypto.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftTLSCrypto.swift 3 | // SwiftTLS 4 | // 5 | // Created by Nico Schmidt on 18.04.18. 6 | // Copyright © 2018 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | extension AES : Cryptor { 12 | func update(inputBlock: MemoryBlock, outputBlock: inout MemoryBlock) -> Bool { 13 | update(indata: inputBlock.block, outdata: &outputBlock.block) 14 | 15 | return true 16 | } 17 | } 18 | 19 | 20 | extension BlockCipher { 21 | class func encryptionBlockCipher(_ cipherAlgorithm : CipherAlgorithm, mode: BlockCipherMode, key : [UInt8]) -> BlockCipher? 22 | { 23 | let aes: AES 24 | switch cipherAlgorithm { 25 | case .aes128: 26 | aes = AES(key: key, bitSize: .aes128, encrypt: true) 27 | 28 | case .aes256: 29 | aes = AES(key: key, bitSize: .aes256, encrypt: true) 30 | 31 | default: 32 | fatalError("Unsupported cipher algorithm \(cipherAlgorithm)") 33 | } 34 | 35 | let cipher = BlockCipher(encrypt: true, cryptor: aes, mode: mode, cipher: cipherAlgorithm) 36 | 37 | return cipher 38 | } 39 | 40 | class func decryptionBlockCipher(_ cipherAlgorithm : CipherAlgorithm, mode: BlockCipherMode, key : [UInt8]) -> BlockCipher? 41 | { 42 | let aes: AES 43 | switch cipherAlgorithm { 44 | case .aes128: 45 | aes = AES(key: key, bitSize: .aes128, encrypt: (mode == .gcm)) 46 | 47 | case .aes256: 48 | aes = AES(key: key, bitSize: .aes256, encrypt: (mode == .gcm)) 49 | 50 | default: 51 | fatalError("Unsupported cipher algorithm \(cipherAlgorithm)") 52 | } 53 | 54 | let cipher = BlockCipher(encrypt: false, cryptor: aes, mode: mode, cipher: cipherAlgorithm) 55 | 56 | return cipher 57 | } 58 | } 59 | 60 | func HMAC_MD5(_ secret : [UInt8], data : [UInt8]) -> [UInt8] 61 | { 62 | fatalError("MD5 not implemented") 63 | } 64 | 65 | func HMAC_SHA1(_ secret : [UInt8], data : [UInt8]) -> [UInt8] 66 | { 67 | return HMAC(hash: SHA1.self, secret: secret, data: data) 68 | } 69 | 70 | func HMAC_SHA256(_ secret : [UInt8], data : [UInt8]) -> [UInt8] 71 | { 72 | return HMAC(hash: SHA256.self, secret: secret, data: data) 73 | } 74 | 75 | func HMAC_SHA384(_ secret : [UInt8], data : [UInt8]) -> [UInt8] 76 | { 77 | return HMAC(hash: SHA384.self, secret: secret, data: data) 78 | } 79 | 80 | func HMAC_SHA512(_ secret : [UInt8], data : [UInt8]) -> [UInt8] 81 | { 82 | return HMAC(hash: SHA384.self, secret: secret, data: data) 83 | } 84 | 85 | func Hash_MD5(_ data : [UInt8]) -> [UInt8] 86 | { 87 | fatalError("MD5 not implemented") 88 | } 89 | 90 | func Hash_SHA1(_ data : [UInt8]) -> [UInt8] 91 | { 92 | return SHA1.hash(data) 93 | } 94 | 95 | func Hash_SHA224(_ data : [UInt8]) -> [UInt8] 96 | { 97 | return SHA224.hash(data) 98 | } 99 | 100 | func Hash_SHA256(_ data : [UInt8]) -> [UInt8] 101 | { 102 | return SHA256.hash(data) 103 | } 104 | 105 | func Hash_SHA384(_ data : [UInt8]) -> [UInt8] 106 | { 107 | return SHA384.hash(data) 108 | } 109 | 110 | func Hash_SHA512(_ data : [UInt8]) -> [UInt8] 111 | { 112 | return SHA512.hash(data) 113 | } 114 | -------------------------------------------------------------------------------- /Tests/SwiftTLSTests/TLSUtilitiesTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TLSUtilitiesTests.swift 3 | // SwiftTLS 4 | // 5 | // Created by Nico Schmidt on 14.04.15. 6 | // Copyright (c) 2015 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import SwiftTLS 11 | 12 | class TLSUtilitiesTests: XCTestCase { 13 | static var allTests = [ 14 | ("test_SHA1_withKnownValues_givesCorrectResult", test_SHA1_withKnownValues_givesCorrectResult), 15 | ("test_P_SHA1_withKnownValues_givesCorrectResult", test_P_SHA1_withKnownValues_givesCorrectResult), 16 | ("test_P_SHA256_withKnownValues_givesCorrectResult", test_P_SHA256_withKnownValues_givesCorrectResult), 17 | ] 18 | 19 | func test_SHA1_withKnownValues_givesCorrectResult() 20 | { 21 | let hash = Hash_SHA1([UInt8]("abc".utf8)) 22 | let expectedResult : [UInt8] = [0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a, 0xba, 0x3e, 0x25, 0x71, 0x78, 0x50, 0xc2, 0x6c, 0x9c, 0xd0, 0xd8, 0x9d] 23 | 24 | XCTAssertEqual(hash, expectedResult) 25 | } 26 | 27 | 28 | 29 | func test_P_SHA1_withKnownValues_givesCorrectResult() 30 | { 31 | let secret : [UInt8] = [25, 46, 104, 149, 87, 175, 96, 194, 56, 189, 109, 67, 127, 254, 197, 82, 145, 220, 36, 154, 41, 78, 204, 233, 234, 202, 29, 148, 174, 63, 172, 255] 32 | let seed : [UInt8] = [46, 97, 125, 50, 55, 253, 149, 131, 26, 245, 137, 49, 100, 56, 218, 68, 87, 186, 136, 192, 31, 69, 226, 163, 206, 18, 199, 15, 29, 251, 234, 48] 33 | let expectedResult : [UInt8] = [100, 195, 143, 212, 209, 90, 229, 82, 147, 67, 194, 54, 107, 1, 151, 14, 60, 202, 63, 238, 188, 233, 235, 163, 137, 169, 224, 2, 7, 249, 55, 228] 34 | 35 | 36 | let hash = P_hash(HMAC_SHA1, secret: secret, seed: seed, outputLength: 32) 37 | 38 | XCTAssertEqual(hash, expectedResult) 39 | } 40 | 41 | 42 | 43 | func test_P_SHA256_withKnownValues_givesCorrectResult() 44 | { 45 | let secret : [UInt8] = [0x9b, 0xbe, 0x43, 0x6b, 0xa9, 0x40, 0xf0, 0x17, 0xb1, 0x76, 0x52, 0x84, 0x9a, 0x71, 0xdb, 0x35] 46 | let seed : [UInt8] = [0xa0, 0xba, 0x9f, 0x93, 0x6c, 0xda, 0x31, 0x18, 0x27, 0xa6, 0xf7, 0x96, 0xff, 0xd5, 0x19, 0x8c] 47 | let label : [UInt8] = [0x74, 0x65, 0x73, 0x74, 0x20, 0x6c, 0x61, 0x62, 0x65, 0x6c] 48 | let expectedResult : [UInt8] = [ 49 | 0xe3, 0xf2, 0x29, 0xba, 0x72, 0x7b, 0xe1, 0x7b, 50 | 0x8d, 0x12, 0x26, 0x20, 0x55, 0x7c, 0xd4, 0x53, 51 | 0xc2, 0xaa, 0xb2, 0x1d, 0x07, 0xc3, 0xd4, 0x95, 52 | 0x32, 0x9b, 0x52, 0xd4, 0xe6, 0x1e, 0xdb, 0x5a, 53 | 0x6b, 0x30, 0x17, 0x91, 0xe9, 0x0d, 0x35, 0xc9, 54 | 0xc9, 0xa4, 0x6b, 0x4e, 0x14, 0xba, 0xf9, 0xaf, 55 | 0x0f, 0xa0, 0x22, 0xf7, 0x07, 0x7d, 0xef, 0x17, 56 | 0xab, 0xfd, 0x37, 0x97, 0xc0, 0x56, 0x4b, 0xab, 57 | 0x4f, 0xbc, 0x91, 0x66, 0x6e, 0x9d, 0xef, 0x9b, 58 | 0x97, 0xfc, 0xe3, 0x4f, 0x79, 0x67, 0x89, 0xba, 59 | 0xa4, 0x80, 0x82, 0xd1, 0x22, 0xee, 0x42, 0xc5, 60 | 0xa7, 0x2e, 0x5a, 0x51, 0x10, 0xff, 0xf7, 0x01, 61 | 0x87, 0x34, 0x7b, 0x66 62 | ] 63 | 64 | let hash = P_hash(HMAC_SHA256, secret: secret, seed: label + seed, outputLength: 100) 65 | 66 | XCTAssertEqual(hash, expectedResult) 67 | } 68 | 69 | 70 | 71 | } 72 | -------------------------------------------------------------------------------- /Tests/macOS/external/openssl/LICENSE: -------------------------------------------------------------------------------- 1 | Original SSLeay License 2 | ----------------------- 3 | 4 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 5 | * All rights reserved. 6 | * 7 | * This package is an SSL implementation written 8 | * by Eric Young (eay@cryptsoft.com). 9 | * The implementation was written so as to conform with Netscapes SSL. 10 | * 11 | * This library is free for commercial and non-commercial use as long as 12 | * the following conditions are aheared to. The following conditions 13 | * apply to all code found in this distribution, be it the RC4, RSA, 14 | * lhash, DES, etc., code; not just the SSL code. The SSL documentation 15 | * included with this distribution is covered by the same copyright terms 16 | * except that the holder is Tim Hudson (tjh@cryptsoft.com). 17 | * 18 | * Copyright remains Eric Young's, and as such any Copyright notices in 19 | * the code are not to be removed. 20 | * If this package is used in a product, Eric Young should be given attribution 21 | * as the author of the parts of the library used. 22 | * This can be in the form of a textual message at program startup or 23 | * in documentation (online or textual) provided with the package. 24 | * 25 | * Redistribution and use in source and binary forms, with or without 26 | * modification, are permitted provided that the following conditions 27 | * are met: 28 | * 1. Redistributions of source code must retain the copyright 29 | * notice, this list of conditions and the following disclaimer. 30 | * 2. Redistributions in binary form must reproduce the above copyright 31 | * notice, this list of conditions and the following disclaimer in the 32 | * documentation and/or other materials provided with the distribution. 33 | * 3. All advertising materials mentioning features or use of this software 34 | * must display the following acknowledgement: 35 | * "This product includes cryptographic software written by 36 | * Eric Young (eay@cryptsoft.com)" 37 | * The word 'cryptographic' can be left out if the rouines from the library 38 | * being used are not cryptographic related :-). 39 | * 4. If you include any Windows specific code (or a derivative thereof) from 40 | * the apps directory (application code) you must include an acknowledgement: 41 | * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 42 | * 43 | * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 44 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 45 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 46 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 47 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 48 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 49 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 50 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 51 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 52 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 53 | * SUCH DAMAGE. 54 | * 55 | * The licence and distribution terms for any publically available version or 56 | * derivative of this code cannot be changed. i.e. this code cannot simply be 57 | * copied and put under another distribution licence 58 | * [including the GNU Public Licence.] 59 | */ 60 | 61 | -------------------------------------------------------------------------------- /SwiftTLS/Sources/TLS/Protocol/TLS 1_3/Messages/TLSNewSessionTicket.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TLSNewSessionTicket.swift 3 | // SwiftTLS 4 | // 5 | // Created by Nico Schmidt on 16.03.18. 6 | // Copyright © 2018 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | extension TLS1_3 { 12 | 13 | class TLSNewSessionTicket : TLSHandshakeMessage 14 | { 15 | let ticketLifetime: UInt32 16 | let ticketAgeAdd: UInt32 17 | let ticketNonce: [UInt8] 18 | let ticket: [UInt8] 19 | let extensions: [TLSExtension] 20 | 21 | var maxEarlyDataSize: UInt32 { 22 | extensions.compactMap({$0 as? TLSEarlyDataIndication}).first?.maxEarlyDataSize ?? 0 23 | } 24 | 25 | convenience init(ticket: Ticket, extensions: [TLSExtension] = []) 26 | { 27 | self.init(ticketLifetime: ticket.lifeTime, ticketAgeAdd: ticket.ageAdd, ticketNonce: ticket.nonce, ticket: ticket.identity, extensions: extensions) 28 | } 29 | 30 | init(ticketLifetime: UInt32, ticketAgeAdd: UInt32, ticketNonce: [UInt8], ticket: [UInt8], extensions: [TLSExtension]) 31 | { 32 | self.ticketLifetime = ticketLifetime 33 | self.ticketAgeAdd = ticketAgeAdd 34 | self.ticketNonce = ticketNonce 35 | self.ticket = ticket 36 | 37 | self.extensions = extensions 38 | 39 | super.init(type: .handshake(.newSessionTicket)) 40 | } 41 | 42 | required init?(inputStream : InputStreamType, context: TLSConnection) 43 | { 44 | guard let (type, bodyLength) = TLSHandshakeMessage.readHeader(inputStream), type == TLSHandshakeType.newSessionTicket else { 45 | return nil 46 | } 47 | 48 | let bytesStart = inputStream.bytesRead 49 | 50 | guard 51 | let ticketLifetime: UInt32 = inputStream.read(), 52 | let ticketAgeAdd: UInt32 = inputStream.read(), 53 | let ticketNonce: [UInt8] = inputStream.read8(), 54 | let ticket: [UInt8] = inputStream.read16() 55 | else { 56 | return nil 57 | } 58 | 59 | self.ticketLifetime = ticketLifetime 60 | self.ticketAgeAdd = ticketAgeAdd 61 | self.ticketNonce = ticketNonce 62 | self.ticket = ticket 63 | 64 | let bytesLeft = bodyLength - (inputStream.bytesRead - bytesStart) 65 | self.extensions = TLSReadExtensions(from: inputStream, length: bytesLeft, messageType: .newSessionTicket, context: context) 66 | 67 | super.init(type: .handshake(.newSessionTicket)) 68 | } 69 | 70 | override func writeTo(_ target: inout Target, context: TLSConnection?) 71 | { 72 | var data = [UInt8]() 73 | 74 | data.write(self.ticketLifetime) 75 | data.write(self.ticketAgeAdd) 76 | data.write8(self.ticketNonce) 77 | data.write16(self.ticket) 78 | 79 | TLSWriteExtensions(&data, extensions: self.extensions, messageType: .newSessionTicket, context: context) 80 | 81 | self.writeHeader(type: .newSessionTicket, bodyLength: data.count, target: &target) 82 | target.write(data) 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /Tests/SwiftTLSTests/Resources/mycert2.pem: -------------------------------------------------------------------------------- 1 | Bag Attributes 2 | friendlyName: Internet Widgits Pty Ltd 3 | localKeyID: 56 72 50 7C 8A BF AF FC B7 DB F4 E7 47 AB 28 50 D0 CD 08 CD 4 | subject=/CN=Internet Widgits Pty Ltd/C=DE/emailAddress=nico@savoysoftware.com 5 | issuer=/CN=Internet Widgits Pty Ltd/C=DE/emailAddress=nico@savoysoftware.com 6 | -----BEGIN CERTIFICATE----- 7 | MIIDUzCCAjugAwIBAgIBATANBgkqhkiG9w0BAQsFADBXMSEwHwYDVQQDDBhJbnRl 8 | cm5ldCBXaWRnaXRzIFB0eSBMdGQxCzAJBgNVBAYTAkRFMSUwIwYJKoZIhvcNAQkB 9 | FhZuaWNvQHNhdm95c29mdHdhcmUuY29tMB4XDTE2MDYyNTE1MTUzNloXDTE3MDYy 10 | NTE1MTUzNlowVzEhMB8GA1UEAwwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMQsw 11 | CQYDVQQGEwJERTElMCMGCSqGSIb3DQEJARYWbmljb0BzYXZveXNvZnR3YXJlLmNv 12 | bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKmaMLCZ2nMXElIN2Nmh 13 | wQ95jHFIfGp5fSRLR9E/jgKpXl82ZzFWFN1L5xnwK3NUjleOIJXwWyyheZX9QM0q 14 | BawRyLQvv7yc4rrjyVmRMDDWXMi6eElVvxF7MuZQlAnDzYsUKZhHRdalCl+hXxh/ 15 | HRMkih79hz479jTAZUtWvRWpV1k6yY7qgGl4hPBAC4TO5SbazykvFLtya/s9Olb7 16 | Bg6JtOScnq+YKQdtVYAyLLkvS2friNjdCUdC1E9T8XoOImy6pBMTfNEIfaR/eRPD 17 | 0X+yNmt/82NccU8Q+JDh1h2PmxKd3k0POEk5Ofjgax3+o2tOB6PEuGqlK7fgZRQM 18 | mAkCAwEAAaMqMCgwDgYDVR0PAQH/BAQDAgeAMBYGA1UdJQEB/wQMMAoGCCsGAQUF 19 | BwMBMA0GCSqGSIb3DQEBCwUAA4IBAQATf06vojot7nwxpYEgTBBPxdrD3KHA1U41 20 | 9lEDgYS+XfLqJkMQ91xSvlaS+6d2yh2Cm2C9w2aC8UyRvkZuKMsySqThuVF4//jg 21 | zOpRkObHVVssNt2aVc2yQ5MaQe/qN7fBvOV8oqJ+nvwZp8t2OVhl8ib0uzmzT0oM 22 | iN0xdtjL7PKr000LdVnbLnOi0y0E8uKqWi+Qf6EXbtW6qlwgo9sICiMUyqHXN0le 23 | pheseEX0mdXh5C11f0qJ4txeXvooIjnTOpXnGY/HpcwbISw6i0RnEiYwNlmvIvsh 24 | uwXFydU8Aqu5Wjp4NxkehtmpW4nBjxXPvFEm+2dusVV57h6a6nXs 25 | -----END CERTIFICATE----- 26 | Bag Attributes 27 | friendlyName: Internet Widgits Pty Ltd 28 | localKeyID: 56 72 50 7C 8A BF AF FC B7 DB F4 E7 47 AB 28 50 D0 CD 08 CD 29 | Key Attributes: 30 | -----BEGIN RSA PRIVATE KEY----- 31 | MIIEowIBAAKCAQEAqZowsJnacxcSUg3Y2aHBD3mMcUh8anl9JEtH0T+OAqleXzZn 32 | MVYU3UvnGfArc1SOV44glfBbLKF5lf1AzSoFrBHItC+/vJziuuPJWZEwMNZcyLp4 33 | SVW/EXsy5lCUCcPNixQpmEdF1qUKX6FfGH8dEySKHv2HPjv2NMBlS1a9FalXWTrJ 34 | juqAaXiE8EALhM7lJtrPKS8Uu3Jr+z06VvsGDom05Jyer5gpB21VgDIsuS9LZ+uI 35 | 2N0JR0LUT1Pxeg4ibLqkExN80Qh9pH95E8PRf7I2a3/zY1xxTxD4kOHWHY+bEp3e 36 | TQ84STk5+OBrHf6ja04Ho8S4aqUrt+BlFAyYCQIDAQABAoIBAEuiMVhwJBTzEv54 37 | ol3bXqcyA0l5k9I/v2jyEWLlPsU9FpLLRhWgV8mgUb0ld5sE+D1fanSzLVWn5PrY 38 | Z4+Wz9S+UYzZRl4scIf7kQ1aS+1biyEQ1xeNH5oCIN7IzFvWb9E3+pyoHCLuksO2 39 | yRu5hBPHVbkgQrGkN9WqfwGr+sKvecmdQgaVIrjRQEiC5Nh+rNMvCLVXELVxpSb+ 40 | C5HlLziXzKhyuc8ZOKGHuR/SW5DMGj21ZF238JQSqD1Lmc0MPt+W4qvQjBDYkh0j 41 | 2dM9VDLcSAGbwsyUqoaTxVyhNStlIc4DVsGqPiE+l/reX5bvhjPIoDfVGvDIqRKw 42 | 8ENOwKECgYEA3cAnulimH1qFRMdAsD2q7euEfL2DjS5VwK4xMmTYAYChQNlYsvPU 43 | RTze9XK7jzzidYrDuxcwjDhViIS9/QDzpC3EJd3NP4YLnaE8s04z0J1yu3sqjQY8 44 | dgx8A10L95tOVZ3DM6Ev0dr0gPSYW3buZbA6X50MfOrsVnEWLvu7OC0CgYEAw8wh 45 | 1K7+1hDcJsKbstdpJyEGgghyRzNlWUpkJRjvGaqPQUFZzKOvgB7+MOV5CcIY6yaU 46 | UEc7t+dA/1cjp1mstFhQgGRNIBO+9Kt1Kk07/SsNH8FVRg5vk5djFTAiTgb5Pdxh 47 | HZW84+LiPVt3/Pdb8l8htM+Trob+6LFfjKcIjM0CgYA2zrWDA0Ib4b2qoCzG4pcK 48 | svlN83E+RcOAGg2izPXueSJh6tZXdJh0fHUG6VKeNogqUR/LcBHZtlq9oUFr9P5D 49 | B+TBDy8ZkkHwtddQ4fVAjIm8+NYtgOsUqkVEd4zrqAEWfCWw7xfooFtqPAokISMP 50 | Ex16YFCj11SOkOjQt/swCQKBgQCQfdiJiArwFskgoYUdWfJzud9/npQXD0q/tjJp 51 | Xhk1K7VERuHqLvGY70ZO90l3dhHFl1bkV20uri49QSVCnt7gyDvARETWYzwMe2uf 52 | qBeZIWgyAw7XAFg+5v1r6XWnd2X/zN6uYo5e7lRfS10lBbaJCsNpF7a4mU8Mkbkd 53 | pzacEQKBgEtonZw2d9/ya/iVfWSqc6TaVsnJ+3K3mBpeIbbQ1BzDXZV/OYvzB8WQ 54 | 3km6Wq07iuzPCkxp/Ju91Smb1OHg/wBMyloBrC5RVbgN98EHqLc3bW2ZOUqHgyHm 55 | 5JJWp3sWFzt949XKR/Iy6Z7tj9i1OL9bvb0CLExbHA7fvv1+knHD 56 | -----END RSA PRIVATE KEY----- 57 | -------------------------------------------------------------------------------- /Tests/macOS/external/openssl/dsa/dsa_asn1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. 3 | * 4 | * The contents of this file constitute Original Code as defined in and are 5 | * subject to the Apple Public Source License Version 1.2 (the 'License'). 6 | * You may not use this file except in compliance with the License. Please obtain 7 | * a copy of the License at http://www.apple.com/publicsource and read it before 8 | * using this file. 9 | * 10 | * This Original Code and all software distributed under the License are 11 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS 12 | * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT 13 | * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 14 | * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the 15 | * specific language governing rights and limitations under the License. 16 | */ 17 | 18 | 19 | /* crypto/dsa/dsa_asn1.c */ 20 | 21 | #include 22 | #include "cryptlib.h" 23 | #include 24 | #include 25 | #ifndef _OPENSSL_APPLE_CDSA_ 26 | #include 27 | #endif 28 | 29 | DSA_SIG *DSA_SIG_new(void) 30 | { 31 | DSA_SIG *ret; 32 | 33 | ret = Malloc(sizeof(DSA_SIG)); 34 | if (ret == NULL) 35 | { 36 | DSAerr(DSA_F_DSA_SIG_NEW,ERR_R_MALLOC_FAILURE); 37 | return(NULL); 38 | } 39 | ret->r = NULL; 40 | ret->s = NULL; 41 | return(ret); 42 | } 43 | 44 | void DSA_SIG_free(DSA_SIG *r) 45 | { 46 | if (r == NULL) return; 47 | if (r->r) BN_clear_free(r->r); 48 | if (r->s) BN_clear_free(r->s); 49 | Free(r); 50 | } 51 | 52 | #ifndef _OPENSSL_APPLE_CDSA_ 53 | 54 | int i2d_DSA_SIG(DSA_SIG *v, unsigned char **pp) 55 | { 56 | int t=0,len; 57 | ASN1_INTEGER rbs,sbs; 58 | unsigned char *p; 59 | 60 | rbs.data=Malloc(BN_num_bits(v->r)/8+1); 61 | if (rbs.data == NULL) 62 | { 63 | DSAerr(DSA_F_I2D_DSA_SIG, ERR_R_MALLOC_FAILURE); 64 | return(0); 65 | } 66 | rbs.type=V_ASN1_INTEGER; 67 | rbs.length=BN_bn2bin(v->r,rbs.data); 68 | sbs.data=Malloc(BN_num_bits(v->s)/8+1); 69 | if (sbs.data == NULL) 70 | { 71 | Free(rbs.data); 72 | DSAerr(DSA_F_I2D_DSA_SIG, ERR_R_MALLOC_FAILURE); 73 | return(0); 74 | } 75 | sbs.type=V_ASN1_INTEGER; 76 | sbs.length=BN_bn2bin(v->s,sbs.data); 77 | 78 | len=i2d_ASN1_INTEGER(&rbs,NULL); 79 | len+=i2d_ASN1_INTEGER(&sbs,NULL); 80 | 81 | if (pp) 82 | { 83 | p=*pp; 84 | ASN1_put_object(&p,1,len,V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL); 85 | i2d_ASN1_INTEGER(&rbs,&p); 86 | i2d_ASN1_INTEGER(&sbs,&p); 87 | } 88 | t=ASN1_object_size(1,len,V_ASN1_SEQUENCE); 89 | Free(rbs.data); 90 | Free(sbs.data); 91 | return(t); 92 | } 93 | 94 | DSA_SIG *d2i_DSA_SIG(DSA_SIG **a, unsigned char **pp, long length) 95 | { 96 | int i=ERR_R_NESTED_ASN1_ERROR; 97 | ASN1_INTEGER *bs=NULL; 98 | M_ASN1_D2I_vars(a,DSA_SIG *,DSA_SIG_new); 99 | 100 | M_ASN1_D2I_Init(); 101 | M_ASN1_D2I_start_sequence(); 102 | M_ASN1_D2I_get(bs,d2i_ASN1_INTEGER); 103 | if ((ret->r=BN_bin2bn(bs->data,bs->length,ret->r)) == NULL) 104 | goto err_bn; 105 | M_ASN1_D2I_get(bs,d2i_ASN1_INTEGER); 106 | if ((ret->s=BN_bin2bn(bs->data,bs->length,ret->s)) == NULL) 107 | goto err_bn; 108 | M_ASN1_BIT_STRING_free(bs); 109 | M_ASN1_D2I_Finish_2(a); 110 | 111 | err_bn: 112 | i=ERR_R_BN_LIB; 113 | err: 114 | DSAerr(DSA_F_D2I_DSA_SIG,i); 115 | if ((ret != NULL) && ((a == NULL) || (*a != ret))) DSA_SIG_free(ret); 116 | if (bs != NULL) M_ASN1_BIT_STRING_free(bs); 117 | return(NULL); 118 | } 119 | 120 | #endif /* _OPENSSL_APPLE_CDSA_ */ 121 | -------------------------------------------------------------------------------- /SwiftTLS.xcodeproj/xcshareddata/xcschemes/tls.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 41 | 42 | 52 | 54 | 60 | 61 | 62 | 63 | 66 | 67 | 68 | 69 | 75 | 77 | 83 | 84 | 85 | 86 | 88 | 89 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /SwiftTLS/Sources/TLS/TLSProtocolVersion.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TLSProtocolVersion.swift 3 | // SwiftTLS 4 | // 5 | // Created by Nico Schmidt on 14.10.16. 6 | // Copyright © 2016 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public struct TLSProtocolVersion : RawRepresentable, CustomStringConvertible, Comparable { 12 | public typealias RawValue = UInt16 13 | init(major : UInt8, minor : UInt8) 14 | { 15 | self.init(rawValue: (UInt16(major) << 8) + UInt16(minor))! 16 | } 17 | 18 | public init?(rawValue: UInt16) 19 | { 20 | _rawValue = rawValue 21 | } 22 | 23 | init?(inputStream: InputStreamType) 24 | { 25 | guard let rawSupportedVersion : UInt16 = inputStream.read() else { 26 | return nil 27 | } 28 | 29 | self.init(rawValue: rawSupportedVersion) 30 | } 31 | 32 | private var _rawValue: UInt16 33 | public var rawValue: UInt16 { 34 | get { 35 | return _rawValue 36 | } 37 | } 38 | 39 | public static let v1_0 = TLSProtocolVersion(rawValue: 0x0301)! 40 | public static let v1_1 = TLSProtocolVersion(rawValue: 0x0302)! 41 | public static let v1_2 = TLSProtocolVersion(rawValue: 0x0303)! 42 | 43 | // For compatibility we are supporting the draft versions 26 and 28 for now. 44 | // Both of which are identical to the final version in RFC 8446 45 | public static let v1_3_draft26 = TLSProtocolVersion(rawValue: 0x7f1a)! // draft-26 46 | public static let v1_3_draft28 = TLSProtocolVersion(rawValue: 0x7f1c)! // draft-28 47 | public static let v1_3 = TLSProtocolVersion(rawValue: 0x0304)! 48 | 49 | public var description: String { 50 | get { 51 | switch self.rawValue { 52 | 53 | case TLSProtocolVersion.v1_0.rawValue: 54 | return "TLS v1.0" 55 | 56 | case TLSProtocolVersion.v1_1.rawValue: 57 | return "TLS v1.1" 58 | 59 | case TLSProtocolVersion.v1_2.rawValue: 60 | return "TLS v1.2" 61 | 62 | case TLSProtocolVersion.v1_3_draft26.rawValue: 63 | return "TLS v1.3 draft-26" 64 | 65 | case TLSProtocolVersion.v1_3_draft28.rawValue: 66 | return "TLS v1.3 draft-28" 67 | 68 | case TLSProtocolVersion.v1_3.rawValue: 69 | return "TLS v1.3" 70 | 71 | default: 72 | return "Unknown TLS version \(_rawValue >> 8).\(_rawValue & 0xff)" 73 | } 74 | } 75 | } 76 | 77 | public var isKnownVersion: Bool { 78 | get { 79 | switch self { 80 | case TLSProtocolVersion.v1_0, TLSProtocolVersion.v1_1, TLSProtocolVersion.v1_2, TLSProtocolVersion.v1_3: 81 | return true 82 | default: 83 | return false 84 | } 85 | } 86 | } 87 | } 88 | 89 | 90 | public func == (lhs : TLSProtocolVersion, rhs : TLSProtocolVersion) -> Bool 91 | { 92 | // FIXME: As long as we are still supporting drafts, make them equivalent 93 | let equivalentVersions = [TLSProtocolVersion.v1_3_draft26.rawValue, TLSProtocolVersion.v1_3_draft28.rawValue, TLSProtocolVersion.v1_3.rawValue] 94 | if equivalentVersions.contains(lhs.rawValue) && equivalentVersions.contains(rhs.rawValue){ 95 | return true 96 | } 97 | 98 | return lhs.rawValue == rhs.rawValue 99 | 100 | } 101 | 102 | public func < (lhs : TLSProtocolVersion, rhs : TLSProtocolVersion) -> Bool 103 | { 104 | if lhs == rhs { 105 | return false 106 | } 107 | 108 | return lhs.rawValue < rhs.rawValue 109 | } 110 | 111 | -------------------------------------------------------------------------------- /SwiftTLS.xcodeproj/xcshareddata/xcschemes/SwiftTLS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 42 | 48 | 49 | 50 | 51 | 52 | 62 | 63 | 69 | 70 | 71 | 72 | 78 | 79 | 85 | 86 | 87 | 88 | 90 | 91 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /Tests/macOS/external/openssl/bn/vms-helper.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. 3 | * 4 | * The contents of this file constitute Original Code as defined in and are 5 | * subject to the Apple Public Source License Version 1.2 (the 'License'). 6 | * You may not use this file except in compliance with the License. Please obtain 7 | * a copy of the License at http://www.apple.com/publicsource and read it before 8 | * using this file. 9 | * 10 | * This Original Code and all software distributed under the License are 11 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS 12 | * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT 13 | * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 14 | * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the 15 | * specific language governing rights and limitations under the License. 16 | */ 17 | 18 | 19 | /* vms-helper.c */ 20 | /* ==================================================================== 21 | * Copyright (c) 1999 The OpenSSL Project. All rights reserved. 22 | * 23 | * Redistribution and use in source and binary forms, with or without 24 | * modification, are permitted provided that the following conditions 25 | * are met: 26 | * 27 | * 1. Redistributions of source code must retain the above copyright 28 | * notice, this list of conditions and the following disclaimer. 29 | * 30 | * 2. Redistributions in binary form must reproduce the above copyright 31 | * notice, this list of conditions and the following disclaimer in 32 | * the documentation and/or other materials provided with the 33 | * distribution. 34 | * 35 | * 3. All advertising materials mentioning features or use of this 36 | * software must display the following acknowledgment: 37 | * "This product includes software developed by the OpenSSL Project 38 | * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 39 | * 40 | * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 41 | * endorse or promote products derived from this software without 42 | * prior written permission. For written permission, please contact 43 | * openssl-core@OpenSSL.org. 44 | * 45 | * 5. Products derived from this software may not be called "OpenSSL" 46 | * nor may "OpenSSL" appear in their names without prior written 47 | * permission of the OpenSSL Project. 48 | * 49 | * 6. Redistributions of any form whatsoever must retain the following 50 | * acknowledgment: 51 | * "This product includes software developed by the OpenSSL Project 52 | * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 53 | * 54 | * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 55 | * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 56 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 57 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 58 | * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 59 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 60 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 61 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 62 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 63 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 64 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 65 | * OF THE POSSIBILITY OF SUCH DAMAGE. 66 | * ==================================================================== 67 | * 68 | * This product includes cryptographic software written by Eric Young 69 | * (eay@cryptsoft.com). This product includes software written by Tim 70 | * Hudson (tjh@cryptsoft.com). 71 | * 72 | */ 73 | 74 | #include 75 | #include "cryptlib.h" 76 | #include "bn_lcl.h" 77 | 78 | void bn_div_words_abort(int i) 79 | { 80 | #if !defined(NO_STDIO) && !defined(WIN16) 81 | fprintf(stderr,"Division would overflow (%d)\n",i); 82 | #endif 83 | abort(); 84 | } 85 | -------------------------------------------------------------------------------- /Tests/SwiftTLSTests/BigIntBitOperationTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BigIntBitOperationTests.swift 3 | // SwiftTLSTests 4 | // 5 | // Created by Nico Schmidt on 24.07.18. 6 | // Copyright © 2018 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import SwiftTLS 11 | 12 | class BigIntBitOperationTests: XCTestCase { 13 | static var allTests = [ 14 | ("test_shiftRight_multiplesOfWordSize_givesCorrectResult", test_shiftRight_multiplesOfWordSize_givesCorrectResult), 15 | ("test_shiftRight_nonMultiplesOfWordSize_givesCorrectResult", test_shiftRight_nonMultiplesOfWordSize_givesCorrectResult), 16 | ("test_shiftLeft_multiplesOfWordSize_givesCorrectResult", test_shiftLeft_multiplesOfWordSize_givesCorrectResult), 17 | ("test_shiftLeft_nonMultiplesOfWordSize_givesCorrectResult", test_shiftLeft_nonMultiplesOfWordSize_givesCorrectResult), 18 | ] 19 | 20 | 21 | func test_shiftRight_multiplesOfWordSize_givesCorrectResult() { 22 | let value = BigInt([0x123456789abcdef0, 0xfedcba9876543210, 0xf67819356ef46abc] as [UInt64]) 23 | 24 | let testVectors = [(64, BigInt([0xfedcba9876543210, 0xf67819356ef46abc] as [UInt64])), 25 | (128, BigInt([0xf67819356ef46abc] as [UInt64])), 26 | (192, BigInt([0] as [UInt64])), 27 | ] 28 | 29 | for (shift, result) in testVectors { 30 | var b = value 31 | b >>= shift 32 | 33 | XCTAssertTrue(b == result) 34 | } 35 | } 36 | 37 | func test_shiftRight_nonMultiplesOfWordSize_givesCorrectResult() { 38 | let value = BigInt("123456789abcdef0fedcba9876543210f67819356ef46abc", radix: 16)! 39 | 40 | let testVectors = [(23, BigInt("2468acf13579bde1fdb97530eca86421ecf0326add", radix: 16)!), 41 | (85, BigInt("91a2b3c4d5e6f787f6e5d4c3b2", radix: 16)!), 42 | (132, BigInt("123456789abcdef", radix: 16)!) 43 | ] 44 | 45 | for (shift, result) in testVectors { 46 | var b = value 47 | b >>= shift 48 | 49 | XCTAssertTrue(b == result) 50 | } 51 | } 52 | 53 | func test_shiftLeft_multiplesOfWordSize_givesCorrectResult() { 54 | let value = BigInt([0x123456789abcdef0, 0xfedcba9876543210, 0xf67819356ef46abc] as [UInt64]) 55 | 56 | let testVectors = [(64, BigInt([0, 0x123456789abcdef0, 0xfedcba9876543210, 0xf67819356ef46abc] as [UInt64])), 57 | (128, BigInt([0, 0, 0x123456789abcdef0, 0xfedcba9876543210, 0xf67819356ef46abc] as [UInt64])), 58 | (192, BigInt([0, 0, 0, 0x123456789abcdef0, 0xfedcba9876543210, 0xf67819356ef46abc] as [UInt64])), 59 | ] 60 | 61 | for (shift, result) in testVectors { 62 | var b = value 63 | b <<= shift 64 | 65 | XCTAssertTrue(b == result) 66 | } 67 | } 68 | 69 | func test_shiftLeft_nonMultiplesOfWordSize_givesCorrectResult() { 70 | let value = BigInt("123456789abcdef0fedcba9876543210f67819356ef46abc", radix: 16)! 71 | 72 | let testVectors = [(23, BigInt("91a2b3c4d5e6f787f6e5d4c3b2a19087b3c0c9ab77a355e000000", radix: 16)!), 73 | (85, BigInt("2468acf13579bde1fdb97530eca86421ecf0326adde8d578000000000000000000000", radix: 16)!) 74 | ] 75 | 76 | for (shift, result) in testVectors { 77 | var b = value 78 | b <<= shift 79 | 80 | XCTAssertTrue(b == result) 81 | } 82 | } 83 | 84 | func test_isBitSet__givesCorrectResult() { 85 | let value = BigInt("123456789abcdef0fedcba9876543210f67819356ef46abc", radix: 16)! 86 | 87 | for i in 0..> i 89 | 90 | let result = ((a.words.first ?? 0) & 0x1) != 0 91 | 92 | let isBitSet = value.isBitSet(i) 93 | 94 | XCTAssert(result == isBitSet) 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /SwiftTLS/Sources/TLS/Protocol/Messages/TLSCertificateMessage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TLSCertificateMessage.swift 3 | // 4 | // Created by Nico Schmidt on 16.03.15. 5 | // Copyright (c) 2015 Nico Schmidt. All rights reserved. 6 | // 7 | 8 | import Foundation 9 | 10 | class TLSCertificateMessage : TLSHandshakeMessage 11 | { 12 | var certificateRequestContext: [UInt8]? // TLS 1.3 13 | var certificates : [X509.Certificate] 14 | 15 | init(certificates : [X509.Certificate]) 16 | { 17 | self.certificates = certificates 18 | 19 | super.init(type: .handshake(.certificate)) 20 | } 21 | 22 | required init?(inputStream : InputStreamType, context: TLSConnection) 23 | { 24 | var certificates : [X509.Certificate]? 25 | 26 | guard let (type, _) = TLSHandshakeMessage.readHeader(inputStream), type == TLSHandshakeType.certificate 27 | else { 28 | return nil 29 | } 30 | 31 | if context.negotiatedProtocolVersion! >= .v1_3 { 32 | certificateRequestContext = inputStream.read8() 33 | } 34 | 35 | if let header : [UInt8] = inputStream.read(count: 3) { 36 | let a = UInt32(header[0]) 37 | let b = UInt32(header[1]) 38 | let c = UInt32(header[2]) 39 | let bytesForCertificates = Int(a << 16 + b << 8 + c) 40 | 41 | certificates = [] 42 | 43 | while bytesForCertificates > 0 { 44 | if let certHeader : [UInt8] = inputStream.read(count: 3) { 45 | let a = UInt32(certHeader[0]) 46 | let b = UInt32(certHeader[1]) 47 | let c = UInt32(certHeader[2]) 48 | var bytesForCertificate = Int(a << 16 + b << 8 + c) 49 | 50 | let data : [UInt8]? = inputStream.read(count: bytesForCertificate) 51 | 52 | if let d = data { 53 | let x509Cert = X509.Certificate(derData: d) 54 | 55 | if let cert = x509Cert { 56 | certificates!.append(cert) 57 | } 58 | } 59 | 60 | bytesForCertificate -= bytesForCertificate 61 | } 62 | else { 63 | break 64 | } 65 | } 66 | } 67 | 68 | if let certs = certificates 69 | { 70 | self.certificates = certs 71 | 72 | super.init(type: .handshake(.certificate)) 73 | } 74 | else 75 | { 76 | return nil 77 | } 78 | } 79 | 80 | override func writeTo(_ target: inout Target, context: TLSConnection?) 81 | { 82 | guard let context = context else { 83 | fatalError() 84 | } 85 | 86 | var certificateData: [UInt8] = [] 87 | 88 | if context.negotiatedProtocolVersion! >= .v1_3 { 89 | let certificateRequestContext = self.certificateRequestContext ?? [] 90 | certificateData.write8(certificateRequestContext) 91 | } 92 | 93 | var certificatesList: [UInt8] = [] 94 | for certificate in self.certificates { 95 | let certificateData = certificate.data 96 | certificatesList.writeUInt24(certificateData.count) 97 | certificatesList.write(certificateData) 98 | 99 | if context.negotiatedProtocolVersion! >= .v1_3 { 100 | let extensions: [TLSExtension] = [] 101 | TLSWriteExtensions(&certificatesList, extensions: extensions, messageType: .certificate, context: context) 102 | } 103 | } 104 | certificateData.write24(certificatesList) 105 | 106 | let bodyLength = certificateData.count 107 | self.writeHeader(type: .certificate, bodyLength: bodyLength, target: &target) 108 | target.write(certificateData) 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /SwiftTLS/Sources/TLS/TLSConfiguration.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TLSConfiguration.swift 3 | // SwiftTLS 4 | // 5 | // Created by Nico Schmidt on 28.12.15. 6 | // Copyright © 2015 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | public struct TLSConfiguration 10 | { 11 | public init(supportedVersions: [TLSProtocolVersion] = [.v1_3, .v1_2], identity: Identity? = nil) 12 | { 13 | self.supportedVersions = supportedVersions 14 | 15 | self.hashAlgorithm = .sha256 16 | 17 | self.cipherSuites = TLSConfiguration.cipherSuites(for: supportedVersions) 18 | 19 | self.ecdhParameters = ECDiffieHellmanParameters(namedCurve: .secp256r1) 20 | 21 | guard let identity = identity else { 22 | return 23 | } 24 | 25 | guard identity.certificateChain.last != nil else { 26 | fatalError("Identity contains no certificates") 27 | } 28 | 29 | self.identity = identity 30 | self.ecdhParameters = ECDiffieHellmanParameters(namedCurve: .secp256r1) 31 | } 32 | 33 | public var cipherSuites: [CipherSuite] 34 | 35 | public var dhParameters: DiffieHellmanParameters? 36 | public var ecdhParameters: ECDiffieHellmanParameters? 37 | 38 | var hashAlgorithm: HashAlgorithm 39 | 40 | var signatureAlgorithm: SignatureAlgorithm? { 41 | guard let certificate = identity?.certificateChain.last else { 42 | return nil 43 | } 44 | 45 | switch certificate.signatureAlgorithm.algorithm { 46 | case .rsa_pkcs1(hash: _), .rsaEncryption, .rsassa_pss(hash: _, saltLength: _): 47 | return .rsa 48 | 49 | case .ecdsa(hash: _), .ecPublicKey(curveName: _, hash: _): 50 | return .ecdsa 51 | } 52 | } 53 | 54 | var identity: Identity? 55 | 56 | var supportedVersions: [TLSProtocolVersion] 57 | 58 | var supportsSessionResumption = true 59 | 60 | var maximumRecordSize: Int? = nil 61 | 62 | // TLS 1.3 63 | public var supportedGroups: [NamedGroup] = [.secp256r1] 64 | 65 | public enum EarlyDataSupport { 66 | case notSupported 67 | case supported(maximumEarlyDataSize: UInt32) 68 | } 69 | 70 | public var earlyData: EarlyDataSupport = .notSupported 71 | 72 | 73 | var minimumSupportedVersion: TLSProtocolVersion { 74 | var version = supportedVersions.first! 75 | for v in supportedVersions { 76 | if version < v { 77 | version = v 78 | } 79 | } 80 | 81 | return version 82 | } 83 | 84 | var maximumSupportedVersion: TLSProtocolVersion { 85 | var version = supportedVersions.first! 86 | for v in supportedVersions { 87 | if version > v { 88 | version = v 89 | } 90 | } 91 | 92 | return version 93 | } 94 | 95 | func supports(_ version: TLSProtocolVersion) -> Bool { 96 | return self.supportedVersions.contains(version) 97 | } 98 | 99 | func createServerContext() -> TLSServerContext { 100 | return TLSServerContext() 101 | } 102 | 103 | func createClientContext() -> TLSClientContext { 104 | return TLSClientContext() 105 | } 106 | 107 | private static func cipherSuites(for supportedVersions: [TLSProtocolVersion]) -> [CipherSuite] { 108 | var cipherSuites : [CipherSuite] = [] 109 | if supportedVersions.contains(.v1_2) { 110 | cipherSuites.append(contentsOf: [ 111 | .TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 112 | .TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 113 | // .TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 114 | ]) 115 | } 116 | 117 | if supportedVersions.contains(.v1_3) { 118 | cipherSuites.append(contentsOf: [ 119 | .TLS_AES_128_GCM_SHA256, 120 | .TLS_AES_256_GCM_SHA384 121 | ]) 122 | } 123 | 124 | return cipherSuites 125 | } 126 | } 127 | 128 | -------------------------------------------------------------------------------- /SwiftTLS/Sources/Crypto/GaloisField.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GaloisField.swift 3 | // SwiftTLS 4 | // 5 | // Created by Nico Schmidt on 28/02/16. 6 | // Copyright © 2016 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct GF2_128_Element { 12 | var hi : UInt64 13 | var lo : UInt64 14 | 15 | init() { 16 | hi = 0 17 | lo = 0 18 | } 19 | 20 | init(_ a : UInt) { 21 | hi = 0 22 | lo = UInt64(a) 23 | } 24 | 25 | init(hi : UInt64, lo : UInt64) { 26 | self.hi = hi 27 | self.lo = lo 28 | } 29 | 30 | init?(_ a : [UInt8]) { 31 | precondition(a.count == 16) 32 | var hi = UInt64(0) 33 | var lo = UInt64(0) 34 | a.withUnsafeBufferPointer { 35 | if let base = $0.baseAddress { 36 | base.withMemoryRebound(to: UInt64.self, capacity: 2) { 37 | hi = $0[0].bigEndian 38 | lo = $0[1].bigEndian 39 | } 40 | } 41 | } 42 | 43 | self.hi = hi 44 | self.lo = lo 45 | } 46 | 47 | func rightshift() -> GF2_128_Element { 48 | let rlo : UInt64 = (lo >> 1) + ((0x1 & hi) == 0 ? 0 : 0x8000000000000000) 49 | let rhi : UInt64 = hi >> 1 50 | return GF2_128_Element(hi: rhi, lo: rlo) 51 | } 52 | 53 | func leftshift() -> GF2_128_Element { 54 | let rhi : UInt64 = (hi << 1) + ((0x8000000000000000 & lo) == 0 ? 0 : 1) 55 | let rlo : UInt64 = lo << 1 56 | return GF2_128_Element(hi: rhi, lo: rlo) 57 | } 58 | 59 | func isBitSet(_ n : Int) -> Bool { 60 | var n = n 61 | precondition(n >= 0) 62 | 63 | n = 127 - n 64 | 65 | if n < 64 { 66 | return ((UInt64(1) << UInt64(n & 0x3f)) & lo) != 0 67 | } 68 | if n < 128 { 69 | let shift = UInt64(n - 64) 70 | return (UInt64(UInt64(1) << shift) & hi) != 0 71 | } 72 | 73 | return false 74 | } 75 | 76 | func asBigEndianByteArray() -> [UInt8] { 77 | return hi.bigEndianBytes + lo.bigEndianBytes 78 | } 79 | } 80 | 81 | func ^(x : GF2_128_Element, y : GF2_128_Element) -> GF2_128_Element { 82 | return GF2_128_Element(hi: x.hi ^ y.hi, lo: x.lo ^ y.lo) 83 | } 84 | 85 | func *(x : GF2_128_Element, y : GF2_128_Element) -> GF2_128_Element { 86 | let r = GF2_128_Element(hi: 0xe100000000000000, lo: 0) 87 | var z = GF2_128_Element(0) 88 | var v = x 89 | for i in 0..<128 { 90 | if y.isBitSet(i) { 91 | z = z ^ v 92 | } 93 | if v.isBitSet(127) { 94 | v = v.rightshift() ^ r 95 | } 96 | else { 97 | v = v.rightshift() 98 | } 99 | } 100 | 101 | return z 102 | } 103 | 104 | func ghashUpdate(_ ghash: GF2_128_Element, h: GF2_128_Element, x: [UInt8]) -> GF2_128_Element 105 | { 106 | let blockSize = 16 // byte, which is 128 bit 107 | var countX = x.count 108 | 109 | var y = ghash 110 | var startIndex = 0 111 | var xBlock = [UInt8](repeating: 0, count: 16) 112 | while countX > 0 { 113 | let length = (countX >= blockSize) ? blockSize : countX 114 | // copy next chunk from x to xBlock filling with zeros 115 | xBlock.withUnsafeMutableBufferPointer { dst in 116 | x.withUnsafeBufferPointer { src in 117 | memcpy(dst.baseAddress!, src.baseAddress! + startIndex, length) 118 | if length < blockSize { 119 | memset(dst.baseAddress! + length, 0, blockSize - length) 120 | } 121 | } 122 | } 123 | 124 | y = (y ^ GF2_128_Element(xBlock)!) * h 125 | 126 | startIndex += length 127 | countX -= length 128 | } 129 | 130 | return y 131 | } 132 | 133 | func ghash(_ h : GF2_128_Element, authData: [UInt8], x : [UInt8]) -> GF2_128_Element 134 | { 135 | var y = ghashUpdate(GF2_128_Element(), h: h, x: authData) 136 | y = ghashUpdate(y, h: h, x: x) 137 | 138 | return (y ^ GF2_128_Element(hi: UInt64(authData.count), lo: UInt64(x.count))) * h 139 | } 140 | -------------------------------------------------------------------------------- /Tests/macOS/external/openssl/bf/bf_ecb.c: -------------------------------------------------------------------------------- 1 | /* crypto/bf/bf_ecb.c */ 2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 3 | * All rights reserved. 4 | * 5 | * This package is an SSL implementation written 6 | * by Eric Young (eay@cryptsoft.com). 7 | * The implementation was written so as to conform with Netscapes SSL. 8 | * 9 | * This library is free for commercial and non-commercial use as long as 10 | * the following conditions are aheared to. The following conditions 11 | * apply to all code found in this distribution, be it the RC4, RSA, 12 | * lhash, DES, etc., code; not just the SSL code. The SSL documentation 13 | * included with this distribution is covered by the same copyright terms 14 | * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15 | * 16 | * Copyright remains Eric Young's, and as such any Copyright notices in 17 | * the code are not to be removed. 18 | * If this package is used in a product, Eric Young should be given attribution 19 | * as the author of the parts of the library used. 20 | * This can be in the form of a textual message at program startup or 21 | * in documentation (online or textual) provided with the package. 22 | * 23 | * Redistribution and use in source and binary forms, with or without 24 | * modification, are permitted provided that the following conditions 25 | * are met: 26 | * 1. Redistributions of source code must retain the copyright 27 | * notice, this list of conditions and the following disclaimer. 28 | * 2. Redistributions in binary form must reproduce the above copyright 29 | * notice, this list of conditions and the following disclaimer in the 30 | * documentation and/or other materials provided with the distribution. 31 | * 3. All advertising materials mentioning features or use of this software 32 | * must display the following acknowledgement: 33 | * "This product includes cryptographic software written by 34 | * Eric Young (eay@cryptsoft.com)" 35 | * The word 'cryptographic' can be left out if the rouines from the library 36 | * being used are not cryptographic related :-). 37 | * 4. If you include any Windows specific code (or a derivative thereof) from 38 | * the apps directory (application code) you must include an acknowledgement: 39 | * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40 | * 41 | * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 42 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 45 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51 | * SUCH DAMAGE. 52 | * 53 | * The licence and distribution terms for any publically available version or 54 | * derivative of this code cannot be changed. i.e. this code cannot simply be 55 | * copied and put under another distribution licence 56 | * [including the GNU Public Licence.] 57 | */ 58 | 59 | #include 60 | #include "bf_locl.h" 61 | #include 62 | 63 | /* Blowfish as implemented from 'Blowfish: Springer-Verlag paper' 64 | * (From LECTURE NOTES IN COMPUTER SCIENCE 809, FAST SOFTWARE ENCRYPTION, 65 | * CAMBRIDGE SECURITY WORKSHOP, CAMBRIDGE, U.K., DECEMBER 9-11, 1993) 66 | */ 67 | 68 | const char *BF_version="Blowfish" OPENSSL_VERSION_PTEXT; 69 | 70 | const char *BF_options(void) 71 | { 72 | #ifdef BF_PTR 73 | return("blowfish(ptr)"); 74 | #elif defined(BF_PTR2) 75 | return("blowfish(ptr2)"); 76 | #else 77 | return("blowfish(idx)"); 78 | #endif 79 | } 80 | 81 | void BF_ecb_encrypt(const unsigned char *in, unsigned char *out, 82 | const BF_KEY *key, int encrypt) 83 | { 84 | BF_LONG l,d[2]; 85 | 86 | n2l(in,l); d[0]=l; 87 | n2l(in,l); d[1]=l; 88 | if (encrypt) 89 | BF_encrypt(d,key); 90 | else 91 | BF_decrypt(d,key); 92 | l=d[0]; l2n(l,out); 93 | l=d[1]; l2n(l,out); 94 | l=d[0]=d[1]=0; 95 | } 96 | 97 | -------------------------------------------------------------------------------- /Tests/SwiftTLSTests/AESTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AESTests.swift 3 | // SwiftTLSTests 4 | // 5 | // Created by Nico Schmidt on 15.04.18. 6 | // Copyright © 2018 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import SwiftTLS 11 | 12 | class AESTests: XCTestCase { 13 | static var allTests = [ 14 | ("test_aes128encrypt_withExampleVector_givesCorrectOutput", test_aes128encrypt_withExampleVector_givesCorrectOutput), 15 | ("test_aes128decrypt_withExampleVector_givesCorrectOutput", test_aes128decrypt_withExampleVector_givesCorrectOutput), 16 | ("test_aes256encrypt_withExampleVector_givesCorrectOutput", test_aes256encrypt_withExampleVector_givesCorrectOutput), 17 | ("test_aes256decrypt_withExampleVector_givesCorrectOutput", test_aes256decrypt_withExampleVector_givesCorrectOutput) 18 | ] 19 | 20 | func test_aes128encrypt_withExampleVector_givesCorrectOutput() { 21 | let key: [UInt8] = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f] 22 | let input: [UInt8] = [0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff] 23 | 24 | var output = [UInt8](repeating: 0, count: 16) 25 | 26 | let aes = AES(key: key, bitSize: .aes128, encrypt: true) 27 | 28 | self.measure { 29 | for _ in 0..<100 { 30 | aes.update(indata: input, outdata: &output) 31 | } 32 | } 33 | /* 34 | let cipher = BlockCipher.encryptionBlockCipher(.aes128, mode: .cbc, key: key, IV: [])! 35 | let inputBlock = MemoryBlock(input) 36 | var outputBlock = MemoryBlock(output) 37 | self.measure { 38 | for _ in 0..<100 { 39 | _ = cipher.cryptorUpdate(inputBlock: inputBlock, outputBlock: &outputBlock) 40 | } 41 | } 42 | output = outputBlock.block 43 | */ 44 | XCTAssert(output == [0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30, 0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a]) 45 | } 46 | 47 | func test_aes128decrypt_withExampleVector_givesCorrectOutput() { 48 | let key: [UInt8] = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f] 49 | let input: [UInt8] = [0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30, 0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a] 50 | 51 | let aes = AES(key: key, bitSize: .aes128, encrypt: false) 52 | 53 | var output = [UInt8](repeating: 0, count: 16) 54 | aes.update(indata: input, outdata: &output) 55 | 56 | XCTAssert(output == [0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff]) 57 | } 58 | 59 | func test_aes256encrypt_withExampleVector_givesCorrectOutput() { 60 | let key: [UInt8] = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 61 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f] 62 | let input: [UInt8] = [0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff] 63 | 64 | var output = [UInt8](repeating: 0, count: 16) 65 | 66 | let aes = AES(key: key, bitSize: .aes256, encrypt: true) 67 | aes.update(indata: input, outdata: &output) 68 | 69 | XCTAssert(output == [0x04, 0xa1, 0x21, 0xe9, 0x20, 0x33, 0xc9, 0x21, 0x04, 0x89, 0x17, 0x75, 0x4f, 0x96, 0x1b, 0x0d]) 70 | } 71 | 72 | func test_aes256decrypt_withExampleVector_givesCorrectOutput() { 73 | let key: [UInt8] = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 74 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f] 75 | let input: [UInt8] = [0x04, 0xa1, 0x21, 0xe9, 0x20, 0x33, 0xc9, 0x21, 0x04, 0x89, 0x17, 0x75, 0x4f, 0x96, 0x1b, 0x0d] 76 | 77 | let aes = AES(key: key, bitSize: .aes256, encrypt: false) 78 | 79 | var output = [UInt8](repeating: 0, count: 16) 80 | aes.update(indata: input, outdata: &output) 81 | 82 | XCTAssert(output == [0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff]) 83 | } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /Tests/SwiftTLSTests/TLSServerHelloTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TLSServerHelloTests.swift 3 | // 4 | // Created by Nico Schmidt on 15.03.15. 5 | // Copyright (c) 2015 Nico Schmidt. All rights reserved. 6 | // 7 | 8 | import XCTest 9 | @testable import SwiftTLS 10 | 11 | extension TLSConnection { 12 | convenience init() { 13 | class EmptyDataProvider : SocketProtocol, TLSDataProvider 14 | { 15 | var isReadyToRead: Bool { return true } 16 | var isListening: Bool { return false } 17 | func read(count: Int) throws -> [UInt8] { return [] } 18 | func write(_ data: [UInt8]) throws {} 19 | func close() {} 20 | } 21 | 22 | self.init(configuration: TLSConfiguration(supportedVersions: [.v1_2]), socket: EmptyDataProvider()) 23 | } 24 | } 25 | 26 | class TLSServerHelloTests: XCTestCase { 27 | static var allTests = [ 28 | ("test_writeTo__givesCorrectBinaryRepresentation", test_writeTo__givesCorrectBinaryRepresentation), 29 | ("test_initWithBinaryInputStream_givesClientHello", test_initWithBinaryInputStream_givesClientHello), 30 | ("test_initWithBinaryInputStream_hasCorrectRandom", test_initWithBinaryInputStream_hasCorrectRandom), 31 | ("test_initWithBinaryInputStream_hasCorrectCipherSuites", test_initWithBinaryInputStream_hasCorrectCipherSuites), 32 | ] 33 | 34 | func test_writeTo__givesCorrectBinaryRepresentation() { 35 | let random = Random() 36 | let clientHello = TLSServerHello( 37 | serverVersion: TLSProtocolVersion.v1_2, 38 | random: random, 39 | sessionID: nil, 40 | cipherSuite: .TLS_RSA_WITH_RC4_128_SHA, 41 | compressionMethod: .null) 42 | 43 | let context = TLSConnection() 44 | var buffer = [UInt8]() 45 | clientHello.writeTo(&buffer, context: context) 46 | 47 | var expectedData = [UInt8]([TLSHandshakeType.serverHello.rawValue, 0, 0, 38, 3, 3]) 48 | var randomData = [UInt8]() 49 | random.writeTo(&randomData, context: context) 50 | expectedData.append(contentsOf: randomData) 51 | expectedData.append(contentsOf: [0, 0, 5, 0]) 52 | 53 | XCTAssert(buffer == expectedData) 54 | } 55 | 56 | var testServerHelloData : [UInt8] { 57 | get { 58 | let rc4_md5 = CipherSuite.TLS_RSA_WITH_RC4_128_MD5.rawValue 59 | let nullCompressionMethod = CompressionMethod.null.rawValue 60 | 61 | return [UInt8]([TLSHandshakeType.serverHello.rawValue, 0, 0, 41, 3, 1, 62 | // random 63 | 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 64 | 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 65 | // sessionID 66 | 32, 67 | 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 68 | 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 69 | // cipher suite 70 | UInt8((rc4_md5) >> 8), UInt8(rc4_md5 & 0xff), 71 | // compression method 72 | nullCompressionMethod]) 73 | } 74 | } 75 | 76 | func test_initWithBinaryInputStream_givesClientHello() { 77 | let serverHello = TLSServerHello(inputStream: BinaryInputStream(self.testServerHelloData), context: TLSConnection()) 78 | 79 | XCTAssert(serverHello != nil) 80 | } 81 | 82 | func test_initWithBinaryInputStream_hasCorrectRandom() { 83 | let serverHello = TLSServerHello(inputStream: BinaryInputStream(self.testServerHelloData), context: TLSConnection()) 84 | 85 | let expectedRandom = Random(inputStream: BinaryInputStream([UInt8]([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 86 | 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32])))! 87 | 88 | let random = serverHello!.random 89 | 90 | XCTAssert(random.randomBytes == expectedRandom.randomBytes && random.gmtUnixTime == expectedRandom.gmtUnixTime) 91 | } 92 | 93 | func test_initWithBinaryInputStream_hasCorrectCipherSuites() { 94 | let serverHello = TLSServerHello(inputStream: BinaryInputStream(self.testServerHelloData), context: TLSConnection()) 95 | 96 | let expectedCiperSuite = CipherSuite.TLS_RSA_WITH_RC4_128_MD5 97 | 98 | XCTAssert(serverHello!.cipherSuite == expectedCiperSuite) 99 | } 100 | 101 | } 102 | -------------------------------------------------------------------------------- /Tests/macOS/external/openssl/bf/bf_skey.c: -------------------------------------------------------------------------------- 1 | /* crypto/bf/bf_skey.c */ 2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 3 | * All rights reserved. 4 | * 5 | * This package is an SSL implementation written 6 | * by Eric Young (eay@cryptsoft.com). 7 | * The implementation was written so as to conform with Netscapes SSL. 8 | * 9 | * This library is free for commercial and non-commercial use as long as 10 | * the following conditions are aheared to. The following conditions 11 | * apply to all code found in this distribution, be it the RC4, RSA, 12 | * lhash, DES, etc., code; not just the SSL code. The SSL documentation 13 | * included with this distribution is covered by the same copyright terms 14 | * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15 | * 16 | * Copyright remains Eric Young's, and as such any Copyright notices in 17 | * the code are not to be removed. 18 | * If this package is used in a product, Eric Young should be given attribution 19 | * as the author of the parts of the library used. 20 | * This can be in the form of a textual message at program startup or 21 | * in documentation (online or textual) provided with the package. 22 | * 23 | * Redistribution and use in source and binary forms, with or without 24 | * modification, are permitted provided that the following conditions 25 | * are met: 26 | * 1. Redistributions of source code must retain the copyright 27 | * notice, this list of conditions and the following disclaimer. 28 | * 2. Redistributions in binary form must reproduce the above copyright 29 | * notice, this list of conditions and the following disclaimer in the 30 | * documentation and/or other materials provided with the distribution. 31 | * 3. All advertising materials mentioning features or use of this software 32 | * must display the following acknowledgement: 33 | * "This product includes cryptographic software written by 34 | * Eric Young (eay@cryptsoft.com)" 35 | * The word 'cryptographic' can be left out if the rouines from the library 36 | * being used are not cryptographic related :-). 37 | * 4. If you include any Windows specific code (or a derivative thereof) from 38 | * the apps directory (application code) you must include an acknowledgement: 39 | * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40 | * 41 | * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 42 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 45 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51 | * SUCH DAMAGE. 52 | * 53 | * The licence and distribution terms for any publically available version or 54 | * derivative of this code cannot be changed. i.e. this code cannot simply be 55 | * copied and put under another distribution licence 56 | * [including the GNU Public Licence.] 57 | */ 58 | 59 | #include 60 | #include 61 | #include 62 | #include "bf_locl.h" 63 | #include "bf_pi.h" 64 | 65 | void BF_set_key(BF_KEY *key, int len, const unsigned char *data) 66 | { 67 | int i; 68 | BF_LONG *p,ri,in[2]; 69 | const unsigned char *d,*end; 70 | 71 | 72 | memcpy((char *)key,(char *)&bf_init,sizeof(BF_KEY)); 73 | p=key->P; 74 | 75 | if (len > ((BF_ROUNDS+2)*4)) len=(BF_ROUNDS+2)*4; 76 | 77 | d=data; 78 | end= &(data[len]); 79 | for (i=0; i<(BF_ROUNDS+2); i++) 80 | { 81 | ri= *(d++); 82 | if (d >= end) d=data; 83 | 84 | ri<<=8; 85 | ri|= *(d++); 86 | if (d >= end) d=data; 87 | 88 | ri<<=8; 89 | ri|= *(d++); 90 | if (d >= end) d=data; 91 | 92 | ri<<=8; 93 | ri|= *(d++); 94 | if (d >= end) d=data; 95 | 96 | p[i]^=ri; 97 | } 98 | 99 | in[0]=0L; 100 | in[1]=0L; 101 | for (i=0; i<(BF_ROUNDS+2); i+=2) 102 | { 103 | BF_encrypt(in,key); 104 | p[i ]=in[0]; 105 | p[i+1]=in[1]; 106 | } 107 | 108 | p=key->S; 109 | for (i=0; i<4*256; i+=2) 110 | { 111 | BF_encrypt(in,key); 112 | p[i ]=in[0]; 113 | p[i+1]=in[1]; 114 | } 115 | } 116 | 117 | -------------------------------------------------------------------------------- /SwiftTLS/Sources/TLS/Protocol/TLS 1_3/TLS1_3.TicketStorage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TLS1_3.TicketStorage.swift 3 | // SwiftTLS 4 | // 5 | // Created by Nico Schmidt on 27.03.18. 6 | // Copyright © 2018 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | extension TLS1_3 { 12 | // The maximum amount we allow the clients view of a tickets age to be off in milliseconds 13 | static let maximumAcceptableTicketAgeOffset: UInt32 = 10_000 14 | 15 | struct Ticket 16 | { 17 | var serverNames: [String] 18 | var identity: [UInt8] 19 | var nonce: [UInt8] 20 | var lifeTime: UInt32 21 | var ageAdd: UInt32 22 | 23 | var preSharedKey: [UInt8]! 24 | var hashAlgorithm: HashAlgorithm 25 | var cipherSuite: CipherSuite 26 | var maxEarlyDataSize: UInt32 27 | 28 | var creationDate: Date 29 | 30 | init(serverNames: [String], 31 | identity: [UInt8], 32 | nonce: [UInt8], 33 | lifeTime: UInt32, 34 | ageAdd: UInt32, 35 | cipherSuite: CipherSuite, 36 | maxEarlyDataSize: UInt32 = 0, 37 | hashAlgorithm: HashAlgorithm = .sha256) 38 | { 39 | self.serverNames = serverNames 40 | self.identity = identity 41 | self.nonce = nonce 42 | self.lifeTime = lifeTime 43 | self.ageAdd = ageAdd 44 | self.cipherSuite = cipherSuite 45 | self.maxEarlyDataSize = maxEarlyDataSize 46 | self.hashAlgorithm = hashAlgorithm 47 | 48 | self.creationDate = Date() 49 | } 50 | 51 | func isValid(at time: Date) -> Bool { 52 | let age = -creationDate.timeIntervalSince(time) 53 | 54 | return age <= Double(self.lifeTime) 55 | } 56 | 57 | internal mutating func derivePreSharedKey(for connection: TLSConnection, sessionResumptionSecret: [UInt8]) { 58 | self.preSharedKey = (connection.protocolHandler as! BaseProtocol).HKDF_Expand_Label(secret: sessionResumptionSecret, label: resumptionLabel, hashValue: self.nonce, outputLength: self.hashAlgorithm.hashLength) 59 | } 60 | } 61 | 62 | struct TicketStorage 63 | { 64 | typealias ServerNameToTicketsDictionary = [String : [Ticket]] 65 | 66 | var tickets: ServerNameToTicketsDictionary = [:] 67 | 68 | mutating func add(_ ticket: Ticket) { 69 | for serverName in ticket.serverNames { 70 | var tickets = self.tickets[serverName, default: []] 71 | tickets.append(ticket) 72 | 73 | self.tickets[serverName] = tickets 74 | } 75 | 76 | // log("Add ticket: \(self.tickets.debugDescription)") 77 | } 78 | 79 | mutating func remove(_ ticket: Ticket) { 80 | let now = Date() 81 | 82 | for serverName in ticket.serverNames { 83 | // Filter for valid tickets in order we clean up our cache whenever we remove a ticket 84 | var tickets = self.tickets[serverName, default: []].filter({$0.isValid(at: now)}) 85 | if let index = tickets.firstIndex(where: {$0.identity == ticket.identity}) { 86 | tickets.remove(at: index) 87 | } 88 | 89 | self.tickets[serverName] = tickets 90 | } 91 | 92 | // log("Remove ticket: \(self.tickets.debugDescription)") 93 | } 94 | 95 | subscript(serverName serverName: String) -> [Ticket] { 96 | return self.tickets[serverName] ?? [] 97 | } 98 | 99 | mutating func removeInvalidTickets() { 100 | let now = Date() 101 | for serverName in tickets.keys { 102 | let tickets = self.tickets[serverName, default: []].filter({$0.isValid(at: now)}) 103 | self.tickets[serverName] = tickets 104 | } 105 | } 106 | } 107 | } 108 | 109 | extension TLS1_3.Ticket : CustomDebugStringConvertible { 110 | var debugDescription: String { 111 | return """ 112 | 113 | serverNames: \(serverNames) 114 | identity: \(hex(identity)) 115 | nonce: \(hex(nonce)) 116 | lifeTime: \(lifeTime) 117 | ageAdd: \(ageAdd) 118 | cipherSuite: \(cipherSuite) 119 | hashAlgorithm: \(hashAlgorithm) 120 | """ 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /SwiftTLS/Sources/Crypto/SHA1.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SHA1.swift 3 | // SwiftTLS 4 | // 5 | // Created by Nico Schmidt on 16.04.18. 6 | // Copyright © 2018 Nico Schmidt. All rights reserved. 7 | // 8 | 9 | private func Ch(_ x: UInt32, _ y: UInt32, _ z: UInt32) -> UInt32 { 10 | return (x & y) ^ (~x & z) 11 | } 12 | 13 | private func Parity(_ x: UInt32, _ y: UInt32, _ z: UInt32) -> UInt32 { 14 | return x ^ y ^ z 15 | } 16 | 17 | private func Maj(_ x: UInt32, _ y: UInt32, _ z: UInt32) -> UInt32 { 18 | return (x & y) ^ (x & z) ^ (y & z) 19 | } 20 | 21 | private let K0: UInt32 = 0x5a827999 22 | private let K1: UInt32 = 0x6ed9eba1 23 | private let K2: UInt32 = 0x8f1bbcdc 24 | private let K3: UInt32 = 0xca62c1d6 25 | 26 | class SHA1 : Hash { 27 | private var H: (UInt32, UInt32, UInt32, UInt32, UInt32) 28 | private var nextMessageBlock: [UInt8] = [] 29 | private var messageLength = 0 30 | 31 | init() { 32 | H = (0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0) 33 | } 34 | 35 | static func hash(_ m: [UInt8]) -> [UInt8] { 36 | let sha1 = SHA1() 37 | sha1.update(m) 38 | return sha1.finalize() 39 | } 40 | 41 | private func updateWithBlock(_ m: [UInt8]) { 42 | var m = m 43 | var W = [UInt32](repeating: 0, count: 80) 44 | 45 | var a = H.0 46 | var b = H.1 47 | var c = H.2 48 | var d = H.3 49 | var e = H.4 50 | 51 | let blockLength = type(of: self).blockLength 52 | 53 | m.withUnsafeMutableBufferPointer { 54 | let M = UnsafeRawPointer($0.baseAddress!).bindMemory(to: UInt32.self, capacity: blockLength/4) 55 | 56 | var T: UInt32 57 | 58 | for t in 0..<80 { 59 | W[t] = (t < 16) ? M[t].byteSwapped : (W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]).rotl(1) 60 | 61 | let ft: UInt32 62 | let Kt: UInt32 63 | switch t { 64 | case 0..<20: 65 | ft = Ch(b, c, d) 66 | Kt = K0 67 | case 20..<40: 68 | ft = Parity(b, c, d) 69 | Kt = K1 70 | case 40..<60: 71 | ft = Maj(b, c, d) 72 | Kt = K2 73 | case 60..<80: 74 | ft = Parity(b, c, d) 75 | Kt = K3 76 | default: 77 | fatalError("The compiler was right") 78 | break 79 | } 80 | 81 | T = a.rotl(5) &+ ft &+ e &+ Kt &+ W[t] 82 | e = d 83 | d = c 84 | c = b.rotl(30) 85 | b = a 86 | a = T 87 | } 88 | } 89 | 90 | H.0 = a &+ H.0 91 | H.1 = b &+ H.1 92 | H.2 = c &+ H.2 93 | H.3 = d &+ H.3 94 | H.4 = e &+ H.4 95 | } 96 | 97 | static var blockLength: Int { 98 | return 512/8 99 | } 100 | 101 | func update(_ m: [UInt8]) { 102 | let blockLength = type(of: self).blockLength 103 | 104 | nextMessageBlock.append(contentsOf: m) 105 | 106 | messageLength += m.count 107 | 108 | while nextMessageBlock.count >= blockLength { 109 | let messageBlock = [UInt8](nextMessageBlock.prefix(blockLength)) 110 | nextMessageBlock.removeFirst(blockLength) 111 | updateWithBlock(messageBlock) 112 | } 113 | } 114 | 115 | func finalize() -> [UInt8] { 116 | let blockLength = type(of: self).blockLength 117 | 118 | precondition(nextMessageBlock.count <= blockLength) 119 | 120 | if nextMessageBlock.count < blockLength { 121 | SHA256.padMessage(&nextMessageBlock, blockLength: blockLength, messageLength: messageLength) 122 | 123 | if nextMessageBlock.count > blockLength { 124 | let messageBlock = [UInt8](nextMessageBlock.prefix(blockLength)) 125 | nextMessageBlock.removeFirst(blockLength) 126 | updateWithBlock(messageBlock) 127 | } 128 | } 129 | 130 | updateWithBlock(nextMessageBlock) 131 | nextMessageBlock = [] 132 | 133 | return ( 134 | H.0.bigEndianBytes + 135 | H.1.bigEndianBytes + 136 | H.2.bigEndianBytes + 137 | H.3.bigEndianBytes + 138 | H.4.bigEndianBytes 139 | ) 140 | } 141 | } 142 | 143 | --------------------------------------------------------------------------------