I have a simple stream_t type in C with your basic read/write operations, and support for multiple underlying implementations using function pointers. So a stream could be backed by a file, a char buffer, etc.
One stream type is a standard POSIX socket, and I would like to code a wrapper stream that will add SSL support to an existing stream, similar to .NET's SslStream. So I could write something like this:
stream_t *socket = something();
// wrap existing stream and perform handshake as client
stream_t *ssl_stream = ssl_stream_create(socket);
ssl_stream_authenticate_as_user(ssl_stream);
// now all read/writes are encrypted and passed through to the wrapped stream
I have written some SSL socket code before using OpenSSL's BIO_new_connect(...) etc. but this is a higher level API than what I need. Does OpenSSL expose the functions I would need to manually perform the handshake and encryption? Or is there some other library I can use?
I don't know any libraries you can use but you can find plenty of samples. Most applications in C would have to do the same for their TCP code so SSL and raw socket versions don't differ too much.
For example, check out ssl_unix.c from Pine IMAP,
https://svn.cac.washington.edu/public/alpine/snapshots/imap/src/osdep/unix/
It does exactly what you are describing with OpenSSL.
I have used a BIO_s_mem as a cover for SSL socket operations. I would read from and write to the socket myself (rather than giving the handle to OpenSSL and having it do the reading/writing). The handshake is done when you call SSL_accept (on the server side) or SSL_connect (on the client side). Other than that, just call SSL_read and SSL_write to do the reading and writing.
Related
I am implementing a socket which accepts connection using TLS.
I found some information on SO on how it can be implemented using OpenSSL. Turn a simple socket into an SSL socket
My question is,
Do I have to use openssl (or some other library) to implement TLS compatible socket. Is there any standard C methods to implement it?
There is no standard C library for TLS. There is OpenSSL which is used a lot and works on many platforms but there are also platform specific libraries like SChannel (Microsoft) or Secure Transport (Apple). And there are many more cross-platform like NSS, GnuTLS, Botan, ... . See Wikipedia: Comparison of TLS implementations for more information.
Of course, you could in theory implement everything yourself but TLS is a complex protocol. And implementation of cryptographic stuff are much harder to get fully right than most other programming tasks, so better use an established library.
I want to design an EAP-TLS client. As the protocol works on the ethernet layer, I am using raw sockets in C and designing the handshake step by step. I wanted to get the TLS data into the packet i designed using OpenSSL. The examples I found online used SSL_Connect() with a socket descriptor and sent the data. I however want to copy the data into the buffer i will send using the raw sockets. Is there any way to do this ? Thank you!
If you want to have everything in your own buffer and not send directly to the socket you have to use not a file descriptor, but a memory BIO as the lower layer for SSL and then you can use the usual SSL_ functions on top of it. You might have a look at Directly Read/Write Handshake data with Memory BIO. A working implementation you'll find in AnyEvent::Handle. Although this is Perl the usage of the BIO_ functions is the same.
I have a multithreaded application that makes heavy use of OpenSSL in C. It is designed with the idea that all of its SSL connections are expected to block. Specifically, blocking BIOs. They are all allocated off a single incoming port like this:
ssl = SSL_new(ctx);
SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
sock = BIO_new_socket(socket, BIO_CLOSE);
SSL_set_bio(ssl, sock, sock);
As it turns out though, there are a few small parts of the codebase where using non-blocking BIOs would be the best choice. The small parts that would benefit from the non-blocking BIOs have no way of knowing which SSL connections will belong to them. Thus, they always receive blocking BIOs.
The question is, can the blocking BIOs be changed to be non-blocking?
I know that BIO_set_nbio can be used to make a BIO non-blocking but the documentation says:
The call to BIO_set_nbio() should be made before the connection is established because non blocking I/O is set during the connect process.
Another possible option I have thought about would be to copy the BIO and recreate it, while somehow maintaining all of the state.
I did non-blocking SSL connections in my own "lion" code, but I did not use the BIO functionality in OpenSSL at all.
Rather, I went for the calls
SSL_set_fd(ctx, fd ) and SSL_get_fd(ssl) to handle my own fdsets and calling select.
The biggest 'gotcha' that took a while to track down was to set SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER and SSL_MODE_ENABLE_PARTIAL_WRITE for it work the way I wanted.
If you want to read the SSL part of the code, it is here:
https://github.com/lundman/lion/blob/master/src/tls.c
In general, the OpenSSL library (C API) seems to offer two ways to do everything: you can either use plain system sockets configured to your liking, or you can use OpenSSL BIO objects which are sort of like streams.
However, I'm often confused by some of the duplicated functionality. For example, how do you make an SSL connection non-blocking? One way seems to be to simply access the underlying file descriptor and set it to non-blocking using fcntl. But there is also an OpenSSL API function called BIO_set_nbio which takes in a BIO* object and sets it to non-blocking mode.
So what is the best way to set up a non-blocking SSL socket? What happens if you pass OpenSSL a native file descriptor which is already set to non-blocking mode via fnctl? Do you still need to specifically call BIO_set_nbio to make the BIO object non-blocking?
I think most people prefer the BIO interface, but the BIO routines just use whatever native non-blocking socket APIs that are available on the platform. I don't know what happens if you mix and match.
Note that non-blocking I/O for SSL is much trickier than for TCP in general. If you don't understand this going in you're going to be torturing yourself. There are books by John Viega and another by Eric Rescorla that go into this, and you can certainly read the OpenSSL mailing list to get a sense of the heartburn this has caused. Some good code examples showing non-blocking SSL programming with OpenSSL are contained in the software for the TOR project, and the curl utility.
I need Mosquitto http://mosquitto.org to work with SSL.
I've read several examples with OpenSSL, but as I've never worked with sockets in C, can someone tell me what do I have to change for my existing sockets? (Accept, write, read?)
Thank you very much
My understanding is that after you've called accept(), you then have to configure the socket for use with OpenSSL - assuming you've also already configured the library for use as well.
After that, you can use SSL_read() and SSL_write() instead of read() and write().
When you want to close the socket, you need to disable SSL support before calling close().
It's a reasonable undertaking for certain - the socket code isn't really the problem, it's understanding what you need to do to start and stop the TLS support and ensuring that you don't miss something out which could lead to vulnerabilities.