<html><body><p><font size="2">Hello all,</font><br><br><font size="2">I would like to share the following API proposal draft for Server security. Once enough feedback has been received, I will initiate a PR for an official review period.</font><br><br><font size="2">A more readable version of the proposal can be found at: </font><a href="https://github.com/gtaban/blogs/blob/master/TLSService_API_Proposal.md"><font size="2">https://github.com/gtaban/blogs/blob/master/TLSService_API_Proposal.md</font></a><font size="2"> </font><br><br><font size="2">Regards,</font><br><font size="2">Gelareh</font><br><br><br><font size="2">------------------------------------------</font><br><br><b><font size="2">Proposal</font></b><font size="2">: SS-001 (TLS Service APIs)</font><br><b><font size="2">Authors</font></b><font size="2">: Gelareh Taban, Bill Abt</font><br><b><font size="2">Review Manager</font></b><font size="2">: TBD</font><br><b><font size="2">Status</font></b><font size="2">: Awaiting review</font><br><br><b><font size="4">1 - Introduction</font></b><br><br><font size="2">This proposal presents the design of TLS service, which is a collection of Swift APIs that provide SSL/TLS functionality with a consistent API surface for both Apple and Linux platforms.</font><br><br><font size="2">For the purposes of brevity, we use the term TLS to refer to all SSL and TLS related functionality in the remainder of the document.</font><br><br><b><font size="4">2 - Motivation</font></b><br><br><font size="2">Currently there is no standard set of Swift TLS APIs on Apple and Linux platforms which has resulted in projects implementing their own Swift security functionality or using their security library of choice (be it OpenSSL, LibreSSL, etc.). This has resulted in fragmentation of the space as well as incompatibility of project dependencies if more than one security package is needed by different modules.</font><br><br><font size="2">This motivates the necessity for defining a standard set of protocols that define the behavior of the TLS service and how the application and the server and networking layers beneath it interact with the TLS service.</font><br><br><b><font size="4">3 - Proposed solution</font></b><br><br><font size="2">We propose a new model that is easily extensible and supports a plug-n-play architecture which allows an application to choose the underlying security framework of choice.</font><br><br><a href="https://github.com/gtaban/blogs/blob/master/TLSServiceArchitecture.png"><font size="2">https://github.com/gtaban/blogs/blob/master/TLSServiceArchitecture.png</font></a><br><br><b>3.1 - Assumptions</b><br><br><font size="2">At the time of writing this proposal, the Swift Server API work group has not yet defined any standards for the transport management or application layers. For our design, we have assumed a network stack that consists of:</font><br><br><font size="2">- System transport layer</font><br><font size="2">- Transport management</font><br><font size="2">- HTTP request management</font><br><font size="2">- (Optional) Web server</font><br><font size="2">- Application</font><br><br><br><font size="2">Our security stack is composed of:</font><br><font size="2">- Underlying security framework (SecureTransport library in Security.Framework on Apple and OpenSSL or alternatives on Linux)</font><br><font size="2">- TLS service</font><br><br><br><font size="2">In our model diagram (</font><a href="https://github.com/gtaban/blogs/blob/master/TLSServiceArchitecture.png"><font size="2">https://github.com/gtaban/blogs/blob/master/TLSServiceArchitecture.png</font></a><font size="2">)</font><font size="2"> we omit both the system level transport layer as well as the underlying security library and show the relationship between the TLS service protocol and the various application layers.</font><br><br><br><b>3.2 - Design description</b><br><br><font size="2">TLS service protocol defines a set of methods that is implemented by TLS service and it interfaces with the transport management layer (for example, socket management). These methods are implemented by the TLS service which in turn uses its choice an of underlying security library. As an example, the TLS service uses SecurityTransport library on Apple platform and OpenSSL or alternatively LibreSSL on Linux.</font><br><br><font size="2">If an application requires TLS for its use case, it creates a TLS service object and configures it based on its requirements. Note that the configuration of the TLS service is outside the scope of the current document.</font><br><br><font size="2">The application then passes the TLS service object to its lower level frameworks that deal with networking and communication. Each lower level framework maintains an optional instance variable of type TLS service protocol. If the optional variable exists, it is further passed down until it gets to the lowest level that deals with the Swift transport layer APIs (in the diagram above, this is the HTTP Management layer). When this layer creates the connection using the transport layer APIs, it assigns the TLS service object to the transport layer delegate. The Swift socket layer is then responsible for calling the TLS service protocol methods that handle the TLS functionality at the appropriate times.</font><br><br><font size="2">Note that in the diagram above, we abstract away the transport mechanism using transport management protocol. The definition for this protocol is out of the scope of this proposal and will be discussed in a separate, future proposal.</font><br><br><br><b>3.3. - Benefits</b><br><br><font size="2">There are several benefits provided by this model:</font><br><br><font size="2">1- It allows the application to choose the underlying security library of choice for their TLS by passing in the appropriate TLS service object.</font><br><br><font size="2">        As long as the TLS service object conforms to the specification of the TLS service protocol, it can implement its methods using any underlying security library. The application can then create the TLS service object of its choice and simply pass the object to the appropriate methods that invoke transport-level functionality.</font><br><br><font size="2">        This model is specially important for projects that involve multiple dependencies that use conflicting security libraries (e.g., LibreSSL and OpenSSL which share the same API surface and building a project with both of these libraries results in link errors). Now the application can choose its own TLS service object and pass it to all frameworks that require TLS.</font><br><br><font size="2">2- Application do not have dependency on underlying security framework if TLS is not enabled.</font><br><br><font size="2">        By mandating Transport/HTTP Management layers to be dependent only on the TLS service protocol, they are agnostic of the underlying security framework and hence do not need to have them in the project if they are not used.</font><br><br><font size="2">3- It allows users to use the same TLS library for both client and server applications.</font><br><br><font size="2">        This is especially important for many server side applications which need to behave as both clients and servers depending on external services they connect to. Also by decoupling the TLS service client and server objects, debugging an application with multiple types of connections will be simplified.</font><br><br><font size="2">4- The underlying Transport/HTTP Management layers are agnostic of the underlying security functionality and simply hand off the TLS service object to the Transport layer delegate.</font><br><br><font size="2">5- The underlying Transport layer is responsible for supporting blocking and non-blocking connections as long as the underlying security library supports both types of connection.</font><br><br><br><b>3.4 - A note on creating a Swifty TLS service</b><br><br><font size="2">There are a number of cases in low-level systems programming where similar functionality is differentiated by a flag or type, such as SOCK_STREAM vs. SOCK_DGRAM or SSLv23_server_method vs. SSLv23_client_method.</font><br><br><font size="2">The latter is an example of how OpenSSL differentiates between the server side or the client side of a TLS connection. In TLS, the client is the initiator of a TLS session; the server is the entity that accepts the requests for TLS sessions made by clients. Depending on the connection type (server or client), different actions and policies are supported such as cipher suite selection during a TLS handshake, request for handshake renegotiations and trust validation policies for server name and certificates.</font><br><br><font size="2">Whilst using a flag or a type is convenient in languages such as C, it's not very Swift-like and does not adhere to the single responsibility principle [1] of object oriented paradigm. We recommend that different interfaces should be created that decouple the client and server concepts as far as the higher application layers are concerned. This is generalized approach that can be adopted by the other layers of the application stack. For example, the Transport layer can also decouple the interface of client and server connections.</font><br><br><b><font size="4">4 - Detailed design</font></b><br><br><b>4.1 - TLS service protocol</b><br><br><font size="2">The TLS service protocol describes the methods that the transport layer calls to handle transport-level events for the TLS service object.</font><br><br><b><font size="2">- onClientCreate</font></b><br><br><font size="2">This will be called when a client I/O connection is created and appropriate TLS connection needs to be configured, including context creation, the handshake and connection verification.</font><br><br><font size="2">This is a client only method.</font><br><br><font size="2">        ///</font><br><font size="2">        /// Setup the contexts and process the TLSService configurations (certificates, etc)</font><br><font size="2">        ///</font><br><br><font size="2">        func onClientCreate() throws</font><br><font size="2">        </font><br><b><font size="2">- onServerCreate</font></b><br><br><font size="2">This will be called when a server I/O connection is created and appropriate TLS connection needs to be setup, including context creation, the handshake and connection verification.</font><br><br><font size="2">This is a server only method.</font><br><br><font size="2">        ///</font><br><font size="2">        /// Setup the contexts and process the TLSService configurations (certificates, etc)</font><br><font size="2">        ///</font><br><br><font size="2">        func onServerCreate() throws</font><br><font size="2">        </font><br><b><font size="2">- onDestroy</font></b><br><br><font size="2">This will be called when an I/O instance connection is closed and any remaining TLS context needs to be destroyed.</font><br><br><font size="2">This is both a client and server method.</font><br><br><font size="2">        ///</font><br><font size="2">        /// Destroy any remaining contexts </font><br><font size="2">        ///</font><br><font size="2">        func onDestroy()</font><br><br><b><font size="2">- onAccept</font></b><br><br><font size="2">This will be called once an I/O instance connection has been accepted, to setup the TLS connection, do the handshake and connection verification.</font><br><br><font size="2">This is both a client and server method.</font><br><br><font size="2">        ///</font><br><font size="2">        /// Processing on acceptance from a listening connection</font><br><font size="2">        /// </font><br><font size="2">        ///</font><br><font size="2">        /// - Parameter IORef:        The connected I/O instance</font><br><font size="2">        ///</font><br><font size="2">        func onAccept(IORef: TransportManagementDelegate) throws</font><br><font size="2">        </font><br><b><font size="2">- onConnect</font></b><br><br><font size="2">This will be called once a socket connection has been made, to setup the TLS connection, do the handshake and connection verification.</font><br><br><font size="2">This is both a client and server method.</font><br><br><font size="2">        ///</font><br><font size="2">        /// Processing on connection to a listening connection</font><br><font size="2">         ///</font><br><font size="2">        /// - Parameter connectionRef:        The connected I/O instance</font><br><font size="2">        ///</font><br><font size="2">        func onConnect(IORef: TransportManagementDelegate) throws</font><br><font size="2">        </font><br><b><font size="2">- onSend</font></b><br><br><font size="2">This will be called when data is to be written to an I/O instance. The input data buffer is written to the TLS connection associated with that I/O instance.</font><br><br><font size="2">This is both a client and server method.</font><br><br><font size="2">        ///</font><br><font size="2">        /// Low level writer</font><br><font size="2">        ///</font><br><font size="2">        /// - Parameters:</font><br><font size="2">        ///                - buffer:                Buffer pointer</font><br><font size="2">        ///                - bufSize:                Size of the buffer</font><br><font size="2">        ///</font><br><font size="2">        ///        - Returns the number of bytes written. Zero indicates TLS shutdown, less than zero indicates error.</font><br><font size="2">        ///</font><br><font size="2">        func onSend(buffer: UnsafeRawPointer, bufSize: Int) throws -&gt; Int</font><br><font size="2">        </font><br><b><font size="2">- onReceive</font></b><br><br><font size="2">This will be called when data is to be read from an I/O instance. Encrypted data is read from TLS connection associated with that I/O instance and decrypted and written to the buffer passed in.</font><br><br><font size="2">This is both a client and server method.</font><br><br><font size="2">        ///</font><br><font size="2">        /// Low level reader</font><br><font size="2">        ///</font><br><font size="2">        /// - Parameters:</font><br><font size="2">        ///                - buffer:                Buffer pointer</font><br><font size="2">        ///                - bufSize:                Size of the buffer</font><br><font size="2">        ///</font><br><font size="2">        ///        - Returns the number of bytes read. Zero indicates TLS shutdown, less than zero indicates error.</font><br><font size="2">        ///</font><br><font size="2">        func onReceive(buffer: UnsafeMutableRawPointer, bufSize: Int) throws -&gt; Int</font><br><font size="2">        </font><br><br><b><font size="4">5 - Non-goals</font></b><br><br><font size="2">This proposal:</font><br><br><font size="2">1- DOES NOT describe the TLS service configuration, which includes information on certificate types, formats and chains, cipher suites, etc. We expect this to be specified in a future proposal.</font><br><br><font size="2">2- DOES NOT describe the TLS service trust policies, which define trust and validation policies of the incoming connection. We expect this to be specified in a future proposal.</font><br><br><font size="2">3- DOES NOT describe the interface between the TLS service and the transport layer and any dependencies. We expect this to be specified in a future proposal.</font><br><br><br><b><font size="4">6 - Source compatibility</font></b><br><br><font size="2">The proposed change is designed to be as non-breaking as possible, however it does place several assumptions on the rest of the transport/application stack.</font><br><br><font size="2">- The application layer must import and instantiate a TLS service object which implements the TLS service protocol if it wants to enable TLS service.</font><br><br><font size="2">- Every framework layer above the transport management layer but below the application layer (which includes HTTP and server frameworks) has an optional object that implements the TLS service protocol. If the TLS object exists, it is passed down to each layer below.</font><br><br><font size="2">- The HTTP layer which sets up the transport management layer assigns the TLS object to the transport management delegate if the object exists.</font><br><br><font size="2">- The transport management layer which sets up the I/O communication implements the transport management protocol.</font><br><br><font size="2">- The transport management layer which sets up the I/O communication and deals with the low level C system I/O, calls the appropriate TLS service protocol methods whenever I/O data needs to be secured.</font><br><br><font size="2">- The long term goal for the location of the TLS service protocol is within the Foundation framework. In the short term, the protocol can live within the transport management framework.</font><br><br><br><b><font size="4">7 - References</font></b><br><br><font size="2">1 - <a href="https://web.archive.org/web/20150202200348/http://www.objectmentor.com/resources/articles/srp.pdf">https://web.archive.org/web/20150202200348/http://www.objectmentor.com/resources/articles/srp.pdf</a></font><br><br><br><br><br><br><BR>
</body></html>