In OpenSSL 1.1, all structures in public header files were made opaque. For C libraries, this change was breaking, but not too bad. For Swift libraries that interface directly with OpenSSL however, this change was huge.
Vapor 3's crypto package (vapor/crypto) currently supports OpenSSL pre-1.1 and post-1.1 APIs. In order to achieve this without completely duplicating the code base, a number of awful hacks had to be put in place. NIO had to employ similar hacks.
Potential solution: Require OpenSSL 1.1+ for Vapor 4
The maintenance and testing burden caused by supporting pre-1.1 APIs is quite high. Because of this, it would be a huge win for Vapor 4 to drop support for OpenSSL pre-1.1. This however comes with some downsides. I'd like to present the pros and cons in this post and get feedback on what Vapor users would think of this change.
Pros:
Greatly simplify vapor/crypto testing and maintenance.
Cons:
Vapor 4 will require Ubuntu 18.04 (16.04 comes with OpenSSL 1.0)
Neutral:
Vapor 4 will use OpenSSL@1.1 instead of LibreSSL on macOS.
Alternative Ideas
Compile OpenSSL 1.1 for Ubuntu 16.04
Users that need to support Ubuntu 16.04 could build and install OpenSSL 1.1 from source. This would admittedly suck.
BoringSSL
Swift NIO is moving to BoringSSL for version 2. Vapor crypto could do something similar and embed BoringSSL for its crypto needs.
Continue hacks
If Ubuntu 16.04 support is deemed absolutely necessary, we can continue maintaining the current state of hacks.
I've used Ondřej's PPA for lots of PHP/Apache backports, pretty impressive he's doing the same for OpenSSL as well.
As a user I'd expect to see a fast-moving project like Vapor require me to keep up with general infrastructure/OS/dependency versions on a new major release, so I think that's a solid move. If I'm not ready to move to Vapor 4 I can stay on a previous version until I'm ready to include this in my migration plans.
@tanner0101 Can you talk about the pros and cons of embedding BoringSSL or using the swift-nio-ssl package directly? Reading the Swift NIO proposal the deployment story sounds much better to have it embedded but there does seem to be some significant maintenance to avoid symbol conflicts.
The main pro (for crypto at least) is that you don't need to link OpenSSL. But the big downsides are increased compile time and increased maintenance burden since we'd be copying in the source files.
Using SwiftNIO SSL
The CNIOBoringSSL module that NIOSSL uses is considered a private module. This means its public API could change at any point. If the API were to remain stable, this could be a great option because we wouldn't need to link OpenSSL and we could just use the copy NIOSSL already needs to build. But, BoringSSL's public API is unstable and likely to change. If / when that happens, it would be difficult to deal with and potentially break people's projects.
IMO, linking OpenSSL is our best option. We just need to figure out whether OpenSSL 1.0 is a necessity for Vapor 4.