Carl Gundel: Correct. My ideal was to create something similar to mesock for LB, but adding TLS support to sockets turned out to be a large undertaking, compared to how relatively simple sockets are.
fwm:
For a while, I was trying to write OpenSSL/LibreSSL code directly in LB, but I didn't get very far with it. It requires quite a bit of memory manipulation to set up the required structs, which LB isn't the best at, and there's a lot more code needed to handle the various parts of the secure channel. (The handshake, maintaining crypto state, renegotiation, which can happen at any time and messes up your basic calls to socket read() and write() if you're not checking for it properly, etc.)
A wrapper to simplify the interface would definitely work best in LB.
There would also be the matter of how much to expose to LB through the wrapper.
Basic sockets are very simple, with (relatively) few options that the programmer chooses: target IP address/domain name, port, protocol(TCP/UDP/Raw), and not much else. Mapping those to a set of open/read/write/close is almost completely natural, which makes a library like mesock easy, especially if you cut out UDP entirely as mesock does, which leaves you with only needing to specify the address and port.
On the other hand, once you start working with secure channels, the number of options you may want to configure as an application developer.
Option one: What protocols are you willing to support? SSL2? SSL3? TLS 1.0? 1.1? 1.2?
The answer to this question often depends on what you're going to be connecting to.
Option two: What encryption ciphers are you willing to support? Again, this often depends on what you're going to be connecting to.
While you can often just let whatever TLS library you're using handle the protocol and cipher negotiation for you, if the defaults for the library do not match what's supported by whatever you're connecting to, the connection fails. For a basic wrapper DLL, I'd probably just hide this detail from the upper level entirely, but that can cause issues depending on what you're using connections for, especially since older protocols/ciphers are often used by companies with legacy equipment, but are also often
disabled by default in current TLS libraries, due to security/privacy concerns. If your LB app needs to connect to one of those systems using an obsolete protocol/cipher set, using the defaults isn't going to work.
EDIT: Heck, do you allow the user of your application to choose and customize the protocols and ciphers you'll support? Many applications that include TLS encryption allow you to do this, so you can scale your security needs up and down as needed, without needing to recompile the library/application. For example, if a vulnerability is found is a specific cipher, you can disable that cipher in the app's config instead of needing to change the app code or library code to do so, or recompile/redistribute the library when its defaults are changed.
As a concrete example, I know all web servers allow you to customize the protocol and cipher suite, and this is VERY important for web servers, because your protocol and cipher choice wind up determining which browsers and browser versions are able to connect to your site at all.
If you check the SSLLabs test for one of my own sites,
www.ssllabs.com/ssltest/analyze.html?d=chrisiverson.net, you'll see a list of ciphers that my server supports, as well as a list of browsers/OSes that can connect, and what cipher/protocol they'd connect with. If I edit the supported cipher list to remove some of the entries deemed "WEAK", then a good number of the older browsers listed in that test would no longer be able to connect to my site. Heck, just disabling TLS 1.0 and 1.1(something which would be required if I was conducting business that required me to follow PCI compliance guidelines due to known issues with both protocols) would probably cut out a good quarter to half of those browsers listed.
On the other hand, if you're creating both the server
and the client systems yourself, such as creating a network game server/client, you can ignore this part entirely, and the library negotiation will automatically negotiate the strongest protocol/cipher selection automatically. Since you're creating both ends, you know what'll be on the other end.
Option three: Authentication.
TLS allows for (optionally) authenticating both the server and the client ends of the connections using X.509 Certificates. This adds a whole new set of questions to answer for a wrapper library.
1) Do you support authentication at all?
It's possible to use TLS without any authentication at all. The resulting connection will be
encrypted, but it won't be
authenticated. What this means is that, the data channel itself will be scrambled over the wire, which defeats passive snooping, but your application has absolutely no assurances that the other end of the connection is what it's supposed to be, and not a hijacker that redirected your traffic. The (hypothetical) attacker doesn't need to go through cracking the encryption on your connection if he managed to get you to connect to him directly in the first place. While this is the simplest choice, it's also the least secure.
2) For the client-side, if you're having your client verify and authenticate the server, do you support only Public Key Infrastructure(PKI) authentication? Or full custom authentication?
What this means is, when you're creating a client that connects to other servers, will it verify the server's X.509 Certificate against public PKI, like Microsoft/Mozilla/Google's list of trusted Root Certificate Authorities(CAs)? And if you do so, and the verification fails, do you just abort the connection, or connect anyway, or give the user the choice?
If you go PKI-only, you make the wrapper code simpler, since LB wouldn't have to deal with any of that at all. However, if you come across a server with a cert that's not in PKI, your LB app fails to connect, unless an additional option is added to the wrapper to override that.
If you're going to allow custom authentication in your wrapper, you need a way of specifying a cert or set of certs or CAs that YOU/your app trusts, even if it's not publicly trusted. That way, your client can know if the server it's connecting to is controlled by you, even if you didn't go to a public CA like Comodo to get a TLS Certificate.
3) For the server-side: do you support Client Authentication?
TLS allows both ends of the connection to require X.509 Authentication. Client Authentication isn't often used; in most cases, the server presents a cert and matching key that is verified by the client, and then the client generates a random key to use. (This is all handled internally by the library.)
However, it is possible to create an app/server that requires the client to go through the same authentication process as the server. If that's the case, the questions above also apply to the client. Accept PKI/custom, how to provide trusted certs/CAs, etc.
4) Custom certificates
If you're using custom certificates on either end of the connection(either writing a server in LB that you want to be auth'd, or writing a client that's going to be using Client Auth), there needs to be a way of specifying the certificate to use to provide to the other end of the connection for verification. Again, if you go without authentication, this can all be ignored completely by the wrapper and LB. If you need any of this, however, these options also need to be provided via the wrapper library. If you do not give an option for providing a certificate, then whatever app you're writing, whether it's a server or a client, will be unable to prove itself. It can still verify others(especially if you're using PKI, and not custom CAs/certs), but it itself can't be verified.
Basically, to create a proper wrapper for this, you really need to know what you'll be doing with it, as a wrapper created for one scenario may not work in others. For example, creating a basic wrapper to just set up an encrypted tunnel, and ignore all the other stuff like authentication, may work just fine for your use case, which appears to be just imitating an SMTP client for a short while. However, you wouldn't be able to use that same wrapper for connecting to HTTPS connections without modification. Well, you could, but if you lose auth, it's not really HTTPS anymore.