Having a consistent development experience for Swift across iOS, tvOS, macOS and now Linux helps to drive higher developer productivity as well as better reuse of Swift assets/libraries across these platforms. The challenge then is to design and maintain consistent Swift APIs across these platforms while leveraging libraries and capabilities that might be specific to the given systems (like OpenSSL vs. Secure Transport or libcurl vs. CFNetwork).
In this post, we look at the security support in macOS and Linux and in particular transport layer security. We show how the difference in underlying frameworks has resulted in slightly different cross-platform behavior in BlueSSLService, which is the underlying framework for Kitura’s current SSL/TLS support. While we are ultimately driving for consistent APIs in our frameworks across platforms, some differences are still visible in how the developer interacts with these APIs.
By the end of this post you should better understand how our team at Swift@IBM has delivered consistent security APIs in Kitura across macOS and Linux. This is particularly helpful as a supplement to Part one of our blog series describing how a simple Kitura application can be served on top of TLS and thus provide private and authenticated communication.
BlueSSLServiceBlueSSLService is the underlying framework that integrates with Kitura web server to provide SSL/TLS. It was designed as an add-in framework for Sockets using a delegate/protocol model. BlueSSLService currently supports BlueSocket which implements low-level sockets and is used by Kitura; however, any Swift Socket framework that implements the SSLServiceDelegate protocol can use BlueSSLService.
Design Goals for BlueSSLService
We designed BlueSSLService with the following goals in mind:
- Support both macOS and Linux
- Integrate with native security libraries on supported platforms so that the user is not responsible for installing and maintaining any other libraries;
- Provide a consistent and unified Swift interface so that the developer can write simple, cross-platform applications;
- Do all the heavy lifting so that the user just has to configure the service, assign it to a socket and forget about it.
The greatest challenge in our design of BlueSSLService was the discrepancy between the native security libraries available on macOS and Linux that implemented SSL/TLS. After some investigation of the security support on the platforms, we decided on OpenSSL on Linux and Apple Secure Transport on macOS. Although there were differences in the libraries and the APIs they exposed to us, we were able to successfully come up with a set of consistent Swift APIs with minor differences across platforms. There are still two remaining differences that we have not resolved and I will go over them in some detail below.
Linux and OpenSSL
OpenSSL is the most common and prevalent open source security library on Linux. As of 2014, it was estimated that at least 66% of the web servers on the Internet use OpenSSL (via Apache and nginx).
OpenSSL is a general-purpose security library with two primary (sub)libraries:
libcrypto is a comprehensive and full-featured cryptographic library that provides the fundamental cryptographic routines used by
libssl, which implements the SSL and TLS protocols.
An important feature of OpenSSL is that it contains the OpenSSL FIPS Object Module, which is FIPS 140-2 validated (not just compliant). FIPS is a US Government cryptographic standard and is a requirement by most government agencies and many enterprises. Being compliant does not prove that the library has no bug or vulnerability, rather that best practices were used.
While there are a number of alternative crypto and SSL/TLS libraries, the most closely aligned to OpenSSL is LibreSSL which came about as a result of code review in response to Heartbleed. Its aim is to modernize the codebase and improve security and memory management of OpenSSL. One limitation of LibreSSL though, is that it is deliberately not FIPS compliant (for the library to be lean).
macOS Platform and Security Frameworks
In contrast to Linux’s single, general-purpose library, macOS has an extensive number of libraries that together make up Apple’s security frameworks. The APIs of these frameworks are exposed at different levels of the system with specific motivation and behavior in mind, including low-level crypto in CommonCrypto, high-level Core Foundation level APIs in the Security Framework, and app-level APIs in SecurityFoundation and SecurityInterface. The Figures below show an architectural stack of Apple’s security frameworks, as well as the components that make up the Security Framework. SSL/TLS APIs are available at multiple interfaces:
- At a high level, we can use an https URL with the URL Loading System (the NSURL class, CFURL functions, and related classes).
- At a lower level, we can use the CFNetwork API to negotiate an SSL or TLS connection.
- For maximum control, we can use the Secure Transport API in OS X or in iOS 5.0 and later.
We chose to use the APIs at the
Secure Transport layer in order to have maximum control and parity with the OpenSSL APIs.
OpenSSL on macOS
Although OpenSSL is compatible with macOS, Apple deprecated the programmatic interface to OpenSSL in OS X v10.7, because OpenSSL did not provide API compatibility across versions. Apple advises that “use of the Apple-provided OpenSSL libraries by apps is strongly discouraged“ and instead points to the use of CommonCrypto and Secure Transport APIs as well as CFNetwork level APIs for Certificate, Key, and Trust services.
Also, since OpenSSL has been deprecated on macOS, it is no longer submitted for FIPS 104 validation.
There are two options for a developer when an application requires OpenSSL:
- Application dynamically links to the latest OpenSSL: Application users are responsible for maintaining the latest copy of OpenSSL on their platform. This can lead to potential API incompatibility.
- Application (dynamically or statically) links to a specific version of OpenSSL: In this case, the application does not get OpenSSL updates for free. This is undesirable and critical when OpenSSL requires security updates.
From these two options, only the first is secure (assuming the user is vigilant about always being up to date) but has the limitation that the application does not necessarily have binary compatibility with the OpenSSL library and therefore updating OpenSSL can cause the application to crash.
Challenges in Unifying APIs
In order for BlueSSLService to provide a unified Swift API over OpenSSL in Linux and Secure Transport on macOS, we faced a number of challenges. These stemmed from the difference in behavior by each library. In the sections below I will describe two challenges that we have not yet resolved, and how they affect BlueSSLService.
OpenSSL supports a number of different encodings for X.509 certificates, including:
- PEM: a Base64-encoded ASCII format of public and private data;
- DER: a binary blob of the public and private data;
- PKCS#7: a Base64-encoded ASCII of public data;
- PKCS#12: a binary blob of both public and private data that can be password encrypted. This is generally one blob that contains both the certificate and the key data
In contrast, Apple platforms only support PKCS#12. In addition, they do not expose any APIs that convert between PKCS#12 and other certificate formats. The developer needs to use OpenSSL or other existing tools to convert between the formats.
BlueSSLService and Certificates
The certificate mismatch between Secure Transport and OpenSSL is a limitation of Secure Transport that is difficult to overcome without either:
- Importing OpenSSL on macOS
- Secure Transport exposing new APIs; or
The first option does not follow our design goals and therefore should not be considered.
The second option is really not in our hands, however a strong case can be made for it as Swift is being ported to non-Apple platforms and we are striving towards consistent and unified APIs.
In the meantime…
Because of the certificate mismatch across platforms, not all constructors for SSL configuration struct work on macOS and indeed only the following is supported on macOS. This includes
Configuration in BlueSSLService and
SSLConfig in Kitura. Below is the only
SSLConfig constructor that works on macOS:
SSLConfig(withChainFilePath chainFilePath: String? = nil, withPassword password: String? = nil, usingSelfSignedCerts selfSigned: Bool = true, cipherSuite: String? = nil
If you need to convert a PEM key/certificate pair to PKCS#12 (which converts two files into a single combined file), you can use the following OpenSSL command:
openssl pkcs12 -export -in cert.pem -inkey key.pem -out certkey.pfx
cert.pem is the PEM encoded certificate,
key.pem is the PEM encoded private key, and
certkey.pfx is the new password-encrypted cert/key PKCS#12 container.
SSL/TLS Cipher suite
Before a secure communication channel can be established between a client and a server, a “handshake” or negotiation phase occurs where the client and server decide what protocol version to use as well as which ciphers, or what cipher suite. This cipher suite defines what operations (such as key exchange, hashing, signing or encrypting) the client or server supports and what is their order of preference.
An example cipher suite configuration is:
This means that an RSA key exchange is used in conjunction with AES-128-CBC (the symmetric cipher) and SHA256 hashing is used for message authentication.
The choice of cipher suite defines the security operations of the TLS protocol, enables features such as forward secrecy, and disables weak operations such as RC4 or MD5. There is a trade off between higher levels of security and compatibility with legacy clients and performance. Older clients might not support newer algorithms and extra security is sometimes not worth the computing cost in software. Great references for choosing appropriate cipher suites include Mozilla and SSLLabs.
There are a number of differences in the way OpenSSL and Secure Transport treat cipher suite setup. The first difference is the name with which the algorithms are refered to. SSL/TLS specification and Internet Assigned Numbers Authority (IANA) define algorithm names with an associated code such as:
Secure Transport identifies the cipher suite string using their IANA code. OpenSSL however defines its own set of names for the cipher suites. For example:
|Code||IANA Name||OpenSSL Name||macOS Name|
Furthermore, OpenSSL defines logical operations in the cipher suite. The cipher strings which compose the cipher suite have a variety of properties:
- They can consist of a single cipher suite such as RC4-SHA.
- They can represent a list of cipher suites containing a certain algorithm, or cipher suites of a certain type. For example SHA1 represents all ciphers suites using the digest algorithm SHA1 and SSLv3 represents all SSL v3 algorithms.
- Lists of cipher suites can be combined in a single cipher string using the + character. This is used as a logical
ANDoperation. For example SHA1+DES represents all cipher suites containing the SHA1 and the DES algorithms.
- Each cipher string can be optionally preceded by the characters !, – or +, which in respectively mean permanent delete, delete or move to end of list.
Unfortunately there is not a lot of data on how cipher suites can be set in Secure Transport and whether operators such as !, – or +, or equivalents, can be used.
BlueSSLService and Cipher Suites
Because of the different way OpenSSL and Secure Transport handle cipher suites, the current implementation of BlueSSLService does not handle consistent cipher suite string values or any conversions across platforms.
We are currently exploring solutions that map the cipher suites between macOS and Linux which will be released as part of BlueSSLService in the near future.
In the meantime…
Currently, a developer needs to individually handle and validate the mapping of their cipher strings across platforms. The cipher suites currently have respective default values based on the constants defined in their underlying libraries.
In this post, we looked at the native security support on macOS and Linux and explored some of their differences. We explored some of the challenges that our Swift@IBM team faced when implementing a single Swift SSL/TLS library for Kitura which was cross-platform. While we are driving for consistent and unified APIs that improve developer productivity, some differences are still visible.
However this is still the beginning of how security should be handled across platforms. We plan on taking our insights from our experience in building security support in Kitura to the community and in particular the Server APIs Work Group Security Group to build a standard means of providing cross-platform security.
In the meantime, we would love to hear from you on your usage of BlueSSLService (e.g., by itself or through Kitura), any limitations you face, and the ideas you have for improving our services.
Learn more about Swift@IBM by visiting our DevCenter.
Here are some past posts in our blog series on Securing Kitura:
- Securing Kitura Part 1: Enabling SSL/TLS on your Swift Server
- Securing Kitura Part 2: Basic Authentication