One way to make a TLS client connection with OpenSSL is to use its SSL layer on top of a TCP connection made using the Berkeley sockets API. The TCP connection to the server is made in the usual way. For the TLS connection, an SSL context must be created first. This manages the certificates, and sets the TLS algorithm to use. For a TLS client connection, a certificate from a certificate authority is required. If the right certificate is known, it can be loaded directly into the context. In many cases, the SSL context is linked to a certificate store on the system and OpenSSL will find the right certificate automatically. Once the SSL context is setup, a TCP socket can be created along with an SSL session. The SSL session is linked to the SSL context and the socket. Most interaction with the TLS connection will go through the SSL session.
After the TCP socket is connected, the next step is the TLS handshake. OpenSSL handles all of the details of the handshake. The client application only needs to poll the handshake status until either an error or success is returned. If the handshake succeeds, the SSL session can be used to do encrypted reads and writes to the server. To do this, the client calls read and write functions on the SSL session that take plain data as input and return plain data as output. The SSL read and write functions handle the details of encryption and decryption. When the client is finished with the connection, the TCP socket can be closed and the SSL session freed.
The following code implements a minimal TLS client:
client.c
#include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <openssl/ssl.h>
int main (int argc, char *argv[]) { int s, len, result; struct sockaddr_in srv_addr; char buf[64]; SSL_CTX *ctx; SSL *ssl;
/* Create a TLS client context with a CA certificate */ ctx = SSL_CTX_new(TLS_client_method()); SSL_CTX_use_certificate_file(ctx, “ca.crt”, SSL_FILETYPE_PEM);
/* Set the address and port of the server to connect to */ srv_addr.sin_family = AF_INET; srv_addr.sin_port = 9001; inet_pton(AF_INET, “127.0.0.1”, &srv_addr.sin_addr);
/* Create a socket and SSL session */ s = socket(AF_INET, SOCK_STREAM, 0); ssl = SSL_new(ctx); SSL_set_fd(ssl, s);
/* Try to connect */ result = connect(s, (struct sockaddr *)&srv_addr, sizeof(srv_addr)); if (result == 0) {
/* Run the OpenSSL handshake */ result = SSL_connect(ssl);
/* Exchange some data if the connection succeeded */ if (result == 1) { sprintf(buf, “Hello from the client”); SSL_write(ssl, buf, strlen(buf) + 1); len = SSL_read(ssl, buf, sizeof(buf)); printf(“Received message from server: ‘%s’\n”, buf); } }
/* Done */ close(s); SSL_free(ssl); SSL_CTX_free(ctx); return 0; } |