├── 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 |  
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 |
--------------------------------------------------------------------------------