views:

1362

answers:

7

Here's my question.

Right now I have a Linux server application (written using C++ - gcc) that communicates with a Windows C++ client application (Visual Studio 9, Qt 4.5.)

What is the very easiest way to add SSL support to both sides in order to secure the communication, without completely gutting the existing protocol?

It's a VOIP application that uses a combination of UDP and TCP to initially set up the connection and do port tunneling stuff, and then uses UDP for the streaming data.

I've had lots of problems in the past with creating the security certificates from scratch that were necessary to get this stuff working.

Existing working example code would be ideal.

Thank you!

+1  A: 

I recommend to use GnuTLS on both the client and the server side, only for the TCP connection. Forget about the UDP data for now. The GnuTLS documentation has example code for writing both clients and servers. Please understand that at least the server side (typically the TCP responder) needs to have a certificate; the client side can work with anonymous identification (although there is even an example without server certificate, using only DH key exchange - which would allow man-in-the-middle attacks).

In general, it is likely that you will have to understand the principles of SSL, no matter what library you use. Library alternatives are OpenSSL (both Unix and Windows), and SChannel (only Windows).

Martin v. Löwis
+1  A: 

Have you tried the SSL support in Boost.Asio or ACE? Both use OpenSSL under-the-hood, and provide similar abstractions for TCP, UDP and SSL. Sample code is available in both the Boost.Asio and ACE distributions.

One thing you may need to keep in mind is that SSL is record-oriented instead of the stream-oriented (both TCP and UDP). This may affect how you multiplex events since you must, for example, read the full SSL record before you can call a read operation complete.

Void
+5  A: 

SSL is very complex, so you're going to want to use a library.

There are several options, such as Keyczar, Botan, cryplib, etc. Each and every one of those libraries (or the libraries suggested by others, such as Boost.Asio or OpenSSL) will have sample code for this.


Answering your second question (how to integrate a library into existing code without causing to much pain): it's going to depend on your current code. If you already have simple functions that call the Winsock or socket methods to send/receive ints, strings, etc. then you just need to rewrite the guts of those functions. And, of course, change the code that sets up the socket to begin with.

On the other hand, if you're calling the Winsock/socket functions dierectly then you'll probably want to write functions that have similar semantics but send the data encrypted, and replace your Winsock calls with those functions.

However, you may want to consider switching to something like Google Protocol Buffers or Apache Thrift (a.k.a. Facebook Thrift). Google's Protocol Buffers documentation says, "Prior to protocol buffers, there was a format for requests and responses that used hand marshalling/unmarshalling of requests and responses, and that supported a number of versions of the protocol. This resulted in some very ugly code. ..."

You're currently in the hand marshalling/unmarshalling phase. It can work, and in fact a project I work on does use this method. But it is a lot nicer to leave that to a library; especially a library that has already given some thought to updating the software in the future.

If you go this route you'll set up your network connections with an SSL library, and then you'll push your Thrift/Protocol Buffer data over those connections. That's it. It does involve extensive refactoring, but you'll end up with less code to maintain. When we introduced Protocol Buffers into the codebase of that project I mentioned, we were able to get rid of about 300 lines of marshalling/demarshalling code.

Max Lybbert
Hi, Max, Thanks for the added detail. (Perhaps my original question was not worded clearly.) Your answer adds the insight that clicks for me. I have one quite ugly, hand coded socket based process in the code that does a sort of "handshake" with the server, and specifically sets up the UDP port tunnelling. The rest of the network code is abstracted out into "SendXMLViaTCPAndWaitForResponse()" type helper functions. Just biting the bullet should not be that hard, it should involve little recoding beyond the helper fcts. Thanks again for nailing this down.
Wannabe Tycoon
A: 

Max, Void and Martin, thanks for your answers - the references to specific libraries are valuable to me.

It appears that there is no well-encapsulated, transparent way to approach this. (Sigh.)

Let me ask the following second question: can you guys (or others) recommend an approach considering that both sides of the interface are coded using straight sockets & Winsock? For example, I'm currently using a little Boost in my project in the form of smart pointers, but I have been reluctant to embrace more of it.

Thanks again.

Wannabe Tycoon
I don't understand why you say that using OpenSSL or GnuTLS is not a well-encapsulated, transparent approach for this.
Martin v. Löwis
Because when I say "transparent" I mean this: I would like to replace the "clear data" Winsock functions with counterparts that "SSL"-ify the protocol, without restructuring the control flow, inventing new variables, dealing with a second set of handle variables, etc. None of the approaches mentioned in this thread seem to be capable of that level of transparency.
Wannabe Tycoon
@Wannabe, if you were already using an encapsulation such as the ones already mentioned moving from TCP, for example, to SSL would be fairly transparent since the encapsulations hide a lot of the details. Some things, such as authentication, are inherently not transparent when moving from an unprotected protocol to a protection-capable protocol like SSL.I'm not aware of any way to transparently "SSL-ify" straight Winsock/sockets functions without something like Sun STREAMS or kernel support. An encapsulation that supports both unprotected and protected communication has worked well for me.
Void
+1  A: 

To help handle this with no changes to the application yo may want to look at the stunnel project (http://www.stunnel.org/). I don't think that it will handle the UDP for you though.

A: 

After reviewing requirements with my client, I believe I will need to bite the bullet and refactor a lot of the network related code anyway due to expanding functionality. So the disruption I sought to avoid is unavoidable anyway.

Since I will be rewriting some of this code, it will give me an opportunity to consider a different platform. I am looking at the PoCo libraries because they provide an extremely nice encapsulation of socket networking and SSL.

Again, thanks to everyone for their insight.

Wannabe Tycoon
A: 

Hi,

The yaSSL and CyaSSL embedded SSL/TLS libraries have worked well for me in the past. Being targeted at embedded systems, they are optimized for both speed and size. yaSSL is written in C++ and CyaSSL is written in C. In comparison, CyaSSL can be up to 20 times smaller than OpenSSL.

Both support the most current industry standards (up to TLS 1.2), offer some cool features such as stream ciphers, and are dual licensed under the GPLv2 and a commercial license (if you need commercial support).

They have some documentation on adding CyaSSL into your pre-existing code as well: http://yassl.com/yaSSL/Docs_Getting_Started_With_CyaSSL.html

Product Page: http://yassl.com/yaSSL/Products.html

Regards,
Chris

Chrisc
Hi Chris, thanks for the answer. Unfortunately, over a year has passed since my posting, and the client canceled the project and tossed me off of the project a couple of weeks ago.
Wannabe Tycoon
Sad to hear. I did realize that it'd been a long time since your posting, but thought I'd at least post for future reference sake.
Chrisc