D   A   T   A   W   O   K





Creation: January 01 1970
Modified: September 11 2018

OpenSSL Basics

This document is the result of the official OpenSSL documentation analysis and personal experience experimenting with the library. Its not even nearly supposed to be an exaustive guide to the library.

SSL Contexts

User first duty is to set up a context object (SSL_CTX). This context object is the used to create a new connection object (SSL) for each new SSL connection.

SSL_METHOD *meth = TLS_client_method();
SSL_CTX *ctx = SSL_CTX_new(meth);
SSL *ssl = SSL_new(ctx);

These connection objects are used to do SSL handshakes, reads and writes. The main ssl (SSL_CTX) object allows connection objects to share data and once initialization of such shared data.

BIO data type

OpenSSL uses an abstraction library called BIO to handle communications of various kinds, including files and sockets, both secure and not. It can also be set up as a filter, such for UU or Base64 coding.

There are two types of BIO, a source/sink BIO and a filter BIO.

A source/sink BIO is a source and/or sink of data, examples include a socket and a file BIO. In short is an end-point in the OpenSSL stack.

A filter BIO takes data from one BIO and passes it through to another, or the application. The data may be left unmodified (for example a message digest BIO) or translated (for example an encryption BIO). The effect of a filter BIO may change according to the I/O operation it is performing: for example an encryption BIO will encrypt data if it is being written to and decrypt data if it is being read from.

BIOs can be joined together to form a chain (a single BIO is a chain with one component). A chain normally consist of one source/sink BIO and one or more filter BIOs. Data read from or written to the first BIO then traverses the chain to the end (normally a source/sink BIO).

Follows a list of the currently available source/sink and filets BIOs.

**** Source/sink

**** Filter

Whatever BIO is choosen, it will support four main read/write functions

int BIO_read(BIO *b, void *buf, int len);
int BIO_gets(BIO *b, char *buf, int size);
int BIO_write(BIO *b, const void *buf, int len);
int BIO_puts(BIO *b, const char *buf);

The meaning is pretty obvious. For more information refer to the official documentation.

Example

The example shows how to bind a BIO to a socket.

There are several wrapper functions to simplify the creation of a socket BIO, anyway I prefer to present the lower level functions. Assuming that you already have the socket file descriptor (as the result of a connection).

First create a new source/sink BIO of socket type.

BIO *bio = BIO_new(BIO_s_socket());

Next bind the socket to the BIO. The last argument is set then the socket is shutdown and closed when the BIO is freed. That is the BIO takes the ownership of the socket.

BIO_set_fd(bio, sock, 1);

From now on you can read and write into the socket through the BIO, thus via the four read/write BIO functions.

BIO_puts(bio, "Hello");

At the end, the BIO is released with its free function.

BIO_free(bio);

NOTE: there is no need to close the socket, since the ownership has been relinquished with the BIO_set_fd dedicated flag.

Socket abstraction

We can let OpenSSL open the socket for us, thus avoiding the BIO_set_fd call, by using the BIO_new_connect function to create the connection and set the hostname, and BIO_set_conn_port (or BIO_set_conn_int_port) to set the port number.

BIO callback

Every BIO has a callback that is called during most high level BIO operations. It can be used for debugging purposes to trace operations or to modify its operation.

The callback can be setted and getted via the BIO_set_callback and BIO_get_callback, respectively.

Setting up a secure connection

*** Handshake

A bit ot theory mainly borrowed from Wikipedia...

The handshake protocol is a four phase association that manages the following aspects:

**** Step #1

**** Phase #2

**** Phase #3

**** Phase #4

OpenSSL Receiver

SERVER [0] ossl_statem_server_process_message case TLS_ST_SR_CLNT_HELLO: return tls_process_client_hello(s, pkt);

CLIENT [1] ossl_statem_client_process_message TLS_ST_CR_SRVR_HELLO: return tls_process_server_hello(s, pkt); TLS_ST_CR_CERT: return tls_process_server_certificate(s, pkt); TLS_ST_CR_KEY_EXCH: return tls_process_key_exchange(s, pkt); TLS_ST_CR_SRVR_DONE: return tls_process_server_done(s, pkt);

SERVER [2] ossl_statem_server_process_message TLS_ST_SR_KEY_EXCH: return tls_process_client_key_exchange(s, pkt); TLS_ST_SR_CHANGE: return tls_process_change_cipher_spec(s, pkt);
TLS_ST_SR_FINISHED: return tls_process_finished(s, pkt);

[[ CONNECT-INDICATION ]](cli-cert(o), ...) // devo farlo qui, prima non ho il client certificate [[ CONNECT-RESPONSE]]] (result)

CLIENT [3] ossl_statem_client_process_message TLS_ST_CR_SESSION_TICKET: return tls_process_new_session_ticket(s, pkt); TLS_ST_CR_CHANGE: return tls_process_change_cipher_spec(s, pkt); TLS_ST_CR_FINISHED: return tls_process_finished(s, pkt);

[[[CONNECT-CONFIRMATION]]](srv-cert, result )

CLIENT

CONNECT REQ -> | (hello) | | ----------------> | | (hello, cert, key) | | <---------------- |

[[[CONNECT-CONFIRMATION]]] (SERVER CERTIFICATE)

Gentle shutdown

At the end of the TLS/SSL connection a "close notify" alert message can be sent. This message is meant to be used as a gentle connection close procedure.

SSL_shutdown() trues to send the :close notify. Whether the operation succeeds or not, the SSL_SENT_SHUTDOWN flag is set ain the currently open session is considered closed.

The shutdown procedure consists of 2 steps: the sending of the "close notify" shutdown alert and the reception of the peer's "close notify" shutdown alert. According to the TLS standard, it is acceptable for an application to only send its shutdown alert and then close the underlying connection without waiting for the peer's response.

When the application is the first party to send the "close notify" alert, SSL_shutdown() will only send the alert and then set the SSL_SENT_SHUTDOWN flag. SSL_shutdown() will then return with 0. In order to complete the bidirectional shutdown handshake, SSL_shutdown() must be called again. On success, the second call to SSL_shutdown() will return with 1.

If the peer already sent the "close notify" alert and it was already processed implicitly inside another function (SSL_read), the SSL_RECEIVED_SHUTDOWN flag is set.

If the peer already sent the "close notify" alert and it was already processed implicitly inside another function (SSL_read), the SSL_RECEIVED_SHUTDOWN flag is set. SSL_shutdown() will send the "close notify" alert, set the SSL_SENT_SHUTDOWN flag and will immediately return with 1. Whether SSL_RECEIVED_SHUTDOWN is already set can be checked using the SSL_get_shutdown().

*** OpenSSL Implementation

The OpenSSL Context SSL_CTX is a structure to hold the SSL information. It is also used to set up the SSL connection through the BIO library. This structure is created by calling SSL_CTX_new with an SSL method function, typically SSLv23_client_method.

Another needed context is of type SSL used to hold the SSL connection structure This SSL pointer can also be used later to examine the connection information or to set up additional SSL parameters.

SSL_CTX * ctx = SSL_CTX_new(SSLv23_client_method());
SSL * ssl;

Using as part of custom stack

The architecture of OpenSSL is pretty flexible and allows the library to be used as a standalone stack layer not bounded to any particular lower level layer (e.g. sockets). The motivation is usually to encapsulate the secured PDUs within a lower level protocol that is not actually implemented within the OS or contemplated by the library via one of the predefined BIOs.

To implement a standalone stack layer we'll use the built in memory BIOs.

A memory BIO is a source/sink BIO which uses memory for its I/O. Data written to a memory BIO is stored in a buffer structure which is automatically extended to accomodate stored data.

Any data written to a memory BIO can be fetched by reading it. Unless the memory BIO is read only, any data read from it is deleted from the BIO.

            +-----------+-----------+
SSL_write ->|    SSL    |  Mem BIO  |-> BIO_read
            +-----------+-----------+

1) SSL_write process the input data and sends it to the bouded BIO to be written in a buffer 2) BIO_read extracts the data from the BIO buffer for further processing, e.g. to be sent to the lower stack layer.

From the receiver once we receive some data from the lower layer, we pass it to the OPENSSL processing functions.

            +-----------+-----------+
BIO_write ->|  Mem BIO  |    SSL    |-> SSL_read
            +-----------+-----------+

1) BIO_write inserts the data into the BIO buffer to be processed the SSL layer. 2) SSL_read extracts the processed data for further processing, e.g. to be sent to the upper stack layer.

The more subtile part is the handshake. Before the secure link can be used to read/write arbitrary data we must terminate the handshake procedure.

The handshake procedure is built into the library and is handled automatically but we must invoke a particular function to let the state machine produce the output data.

Code : cipher suite hex code Name : textual representation of cipher name Proto : protocol version when the cipher was first defined Kx : key exchange method such as RSA, ECDHE, etc. Au : authentication method such as RSA, None, etc. None is the representation of anonymous ciphers. Enc : symmetric encryption method, with number of secret bits, such as AESGCM(128). Mac : message digest, such as SHA256.

Error type: (1) Client Hello contstruct (tls_construct_client_hello). Cipher disabled on the SSL context (ssl_cipher_disabled) (2) Server bad answer (verify) (3) Init error

Code Name Proto Kx Au Enc Mac Working
0xC0,0x30 ECDHE-RSA-AES256-GCM-SHA384 TLSv1.2 ECDH RSA AESGCM(256) AEAD X
0xC0,0x2C ECDHE-ECDSA-AES256-GCM-SHA384 TLSv1.2 ECDH ECDSA AESGCM(256) AEAD E2
0xC0,0x28 ECDHE-RSA-AES256-SHA384 TLSv1.2 ECDH RSA AES(256) SHA384 X
0xC0,0x24 ECDHE-ECDSA-AES256-SHA384 TLSv1.2 ECDH ECDSA AES(256) SHA384 E2
0xC0,0x14 ECDHE-RSA-AES256-SHA SSLv3 ECDH RSA AES(256) SHA1 X
0xC0,0x0A ECDHE-ECDSA-AES256-SHA SSLv3 ECDH ECDSA AES(256) SHA1 E2
0xC0,0x22 SRP-DSS-AES-256-CBC-SHA SSLv3 SRP DSS AES(256) SHA1 E1
0xC0,0x21 SRP-RSA-AES-256-CBC-SHA SSLv3 SRP RSA AES(256) SHA1 E1
0xC0,0x20 SRP-AES-256-CBC-SHA SSLv3 SRP SRP AES(256) SHA1 E3
0x00,0xA5 DH-DSS-AES256-GCM-SHA384 TLSv1.2 DH/DSS DH AESGCM(256) AEAD E3
0x00,0xA3 DHE-DSS-AES256-GCM-SHA384 TLSv1.2 DH DSS AESGCM(256) AEAD E2
0x00,0xA1 DH-RSA-AES256-GCM-SHA384 TLSv1.2 DH/RSA DH AESGCM(256) AEAD E3
0x00,0x9F DHE-RSA-AES256-GCM-SHA384 TLSv1.2 DH RSA AESGCM(256) AEAD E2
0x00,0x6B DHE-RSA-AES256-SHA256 TLSv1.2 DH RSA AES(256) Mac=SHA256
0x00,0x6A DHE-DSS-AES256-SHA256 TLSv1.2 DH DSS AES(256) Mac=SHA256
0x00,0x69 DH-RSA-AES256-SHA256 TLSv1.2 DH/RSA DH AES(256) Mac=SHA256
0x00,0x68 DH-DSS-AES256-SHA256 TLSv1.2 DH/DSS DH AES(256) Mac=SHA256
0x00,0x39 DHE-RSA-AES256-SHA SSLv3 DH RSA Enc=AES(256) Mac=SHA1
0x00,0x38 DHE-DSS-AES256-SHA SSLv3 DH DSS Enc=AES(256) Mac=SHA1
0x00,0x37 DH-RSA-AES256-SHA SSLv3 DH/RSA DH Enc=AES(256) Mac=SHA1
0x00,0x36 DH-DSS-AES256-SHA SSLv3 DH/DSS DH Enc=AES(256) Mac=SHA1
0x00,0x88 DHE-RSA-CAMELLIA256-SHA SSLv3 DH RSA Enc=Camellia(256) Mac=SHA1
0x00,0x87 DHE-DSS-CAMELLIA256-SHA SSLv3 DH DSS Enc=Camellia(256) Mac=SHA1
0x00,0x86 DH-RSA-CAMELLIA256-SHA SSLv3 DH/RSA DH Enc=Camellia(256) Mac=SHA1
0x00,0x85 DH-DSS-CAMELLIA256-SHA SSLv3 DH/DSS DH Enc=Camellia(256) Mac=SHA1
0xC0,0x32 ECDH-RSA-AES256-GCM-SHA384 TLSv1.2 ECDH/RSA ECDH Enc=AESGCM(256) Mac=AEAD
0xC0,0x2E ECDH-ECDSA-AES256-GCM-SHA384 TLSv1.2 ECDH/ECDSA ECDH AESGCM(256) AEAD E3
0xC0,0x2A ECDH-RSA-AES256-SHA384 TLSv1.2 ECDH/RSA ECDH AES(256) SHA384 E3
0xC0,0x26 ECDH-ECDSA-AES256-SHA384 TLSv1.2 ECDH/ECDSA Au=ECDH Enc=AES(256) Mac=SHA384
0xC0,0x0F ECDH-RSA-AES256-SHA SSLv3 ECDH/RSA Au=ECDH Enc=AES(256) Mac=SHA1
0xC0,0x05 ECDH-ECDSA-AES256-SHA SSLv3 ECDH/ECDSA Au=ECDH Enc=AES(256) Mac=SHA1
0x00,0x9D AES256-GCM-SHA384 TLSv1.2 RSA Au=RSA Enc=AESGCM(256) Mac=AEAD
0x00,0x3D AES256-SHA256 TLSv1.2 RSA Au=RSA Enc=AES(256) Mac=SHA256
0x00,0x35 AES256-SHA SSLv3 RSA Au=RSA Enc=AES(256) Mac=SHA1
0x00,0x84 CAMELLIA256-SHA SSLv3 RSA Au=RSA Enc=Camellia(256) Mac=SHA1
0x00,0x8D PSK-AES256-CBC-SHA SSLv3 PSK PSK AES(256) SHA1 E1
0xC0,0x2F ECDHE-RSA-AES128-GCM-SHA256 TLSv1.2 ECDH RSA AESGCM(128) AEAD OK
0xC0,0x2B ECDHE-ECDSA-AES128-GCM-SHA256 TLSv1.2 ECDH ECDSA AESGCM(128) AEAD E2
0xC0,0x27 ECDHE-RSA-AES128-SHA256 TLSv1.2 ECDH RSA Enc=AES(128) Mac=SHA256
0xC0,0x23 ECDHE-ECDSA-AES128-SHA256 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AES(128) Mac=SHA256
0xC0,0x13 ECDHE-RSA-AES128-SHA SSLv3 Kx=ECDH Au=RSA Enc=AES(128) Mac=SHA1
0xC0,0x09 ECDHE-ECDSA-AES128-SHA SSLv3 Kx=ECDH Au=ECDSA Enc=AES(128) Mac=SHA1
0xC0,0x1F SRP-DSS-AES-128-CBC-SHA SSLv3 Kx=SRP Au=DSS Enc=AES(128) Mac=SHA1
0xC0,0x1E SRP-RSA-AES-128-CBC-SHA SSLv3 Kx=SRP Au=RSA Enc=AES(128) Mac=SHA1
0xC0,0x1D SRP-AES-128-CBC-SHA SSLv3 Kx=SRP Au=SRP Enc=AES(128) Mac=SHA1
0x00,0xA4 DH-DSS-AES128-GCM-SHA256 TLSv1.2 Kx=DH/DSS Au=DH Enc=AESGCM(128) Mac=AEAD
0x00,0xA2 DHE-DSS-AES128-GCM-SHA256 TLSv1.2 Kx=DH Au=DSS Enc=AESGCM(128) Mac=AEAD
0x00,0xA0 DH-RSA-AES128-GCM-SHA256 TLSv1.2 Kx=DH/RSA Au=DH Enc=AESGCM(128) Mac=AEAD
0x00,0x9E DHE-RSA-AES128-GCM-SHA256 TLSv1.2 Kx=DH Au=RSA Enc=AESGCM(128) Mac=AEAD
0x00,0x67 DHE-RSA-AES128-SHA256 TLSv1.2 Kx=DH Au=RSA Enc=AES(128) Mac=SHA256
0x00,0x40 DHE-DSS-AES128-SHA256 TLSv1.2 Kx=DH Au=DSS Enc=AES(128) Mac=SHA256
0x00,0x3F DH-RSA-AES128-SHA256 TLSv1.2 Kx=DH/RSA Au=DH Enc=AES(128) Mac=SHA256
0x00,0x3E DH-DSS-AES128-SHA256 TLSv1.2 Kx=DH/DSS Au=DH Enc=AES(128) Mac=SHA256
0x00,0x33 DHE-RSA-AES128-SHA SSLv3 Kx=DH Au=RSA Enc=AES(128) Mac=SHA1
0x00,0x32 DHE-DSS-AES128-SHA SSLv3 Kx=DH Au=DSS Enc=AES(128) Mac=SHA1
0x00,0x31 DH-RSA-AES128-SHA SSLv3 Kx=DH/RSA Au=DH Enc=AES(128) Mac=SHA1
0x00,0x30 DH-DSS-AES128-SHA SSLv3 Kx=DH/DSS Au=DH Enc=AES(128) Mac=SHA1
0x00,0x9A DHE-RSA-SEED-SHA SSLv3 Kx=DH Au=RSA Enc=SEED(128) Mac=SHA1
0x00,0x99 DHE-DSS-SEED-SHA SSLv3 Kx=DH Au=DSS Enc=SEED(128) Mac=SHA1
0x00,0x98 DH-RSA-SEED-SHA SSLv3 Kx=DH/RSA Au=DH Enc=SEED(128) Mac=SHA1
0x00,0x97 DH-DSS-SEED-SHA SSLv3 Kx=DH/DSS Au=DH Enc=SEED(128) Mac=SHA1
0x00,0x45 DHE-RSA-CAMELLIA128-SHA SSLv3 Kx=DH Au=RSA Enc=Camellia(128) Mac=SHA1
0x00,0x44 DHE-DSS-CAMELLIA128-SHA SSLv3 Kx=DH Au=DSS Enc=Camellia(128) Mac=SHA1
0x00,0x43 DH-RSA-CAMELLIA128-SHA SSLv3 Kx=DH/RSA Au=DH Enc=Camellia(128) Mac=SHA1
0x00,0x42 DH-DSS-CAMELLIA128-SHA SSLv3 Kx=DH/DSS Au=DH Enc=Camellia(128) Mac=SHA1
0xC0,0x31 ECDH-RSA-AES128-GCM-SHA256 TLSv1.2 Kx=ECDH/RSA Au=ECDH Enc=AESGCM(128) Mac=AEAD
0xC0,0x2D ECDH-ECDSA-AES128-GCM-SHA256 TLSv1.2 Kx=ECDH/ECDSA Au=ECDH Enc=AESGCM(128) Mac=AEAD
0xC0,0x29 ECDH-RSA-AES128-SHA256 TLSv1.2 Kx=ECDH/RSA Au=ECDH Enc=AES(128) Mac=SHA256
0xC0,0x25 ECDH-ECDSA-AES128-SHA256 TLSv1.2 Kx=ECDH/ECDSA Au=ECDH Enc=AES(128) Mac=SHA256
0xC0,0x0E ECDH-RSA-AES128-SHA SSLv3 Kx=ECDH/RSA Au=ECDH Enc=AES(128) Mac=SHA1
0xC0,0x04 ECDH-ECDSA-AES128-SHA SSLv3 Kx=ECDH/ECDSA Au=ECDH Enc=AES(128) Mac=SHA1
0x00,0x9C AES128-GCM-SHA256 TLSv1.2 Kx=RSA Au=RSA Enc=AESGCM(128) Mac=AEAD
0x00,0x3C AES128-SHA256 TLSv1.2 Kx=RSA Au=RSA Enc=AES(128) Mac=SHA256
0x00,0x2F AES128-SHA SSLv3 Kx=RSA Au=RSA Enc=AES(128) Mac=SHA1
0x00,0x96 SEED-SHA SSLv3 Kx=RSA Au=RSA Enc=SEED(128) Mac=SHA1
0x00,0x41 CAMELLIA128-SHA SSLv3 Kx=RSA Au=RSA Enc=Camellia(128) Mac=SHA1
0x00,0x07 IDEA-CBC-SHA SSLv3 Kx=RSA Au=RSA Enc=IDEA(128) Mac=SHA1
0x00,0x8C PSK-AES128-CBC-SHA SSLv3 Kx=PSK Au=PSK Enc=AES(128) Mac=SHA1
0xC0,0x11 ECDHE-RSA-RC4-SHA SSLv3 Kx=ECDH Au=RSA Enc=RC4(128) Mac=SHA1
0xC0,0x07 ECDHE-ECDSA-RC4-SHA SSLv3 Kx=ECDH Au=ECDSA Enc=RC4(128) Mac=SHA1
0xC0,0x0C ECDH-RSA-RC4-SHA SSLv3 Kx=ECDH/RSA Au=ECDH Enc=RC4(128) Mac=SHA1
0xC0,0x02 ECDH-ECDSA-RC4-SHA SSLv3 Kx=ECDH/ECDSA Au=ECDH Enc=RC4(128) Mac=SHA1
0x00,0x05 RC4-SHA SSLv3 Kx=RSA Au=RSA Enc=RC4(128) Mac=SHA1
0x00,0x04 RC4-MD5 SSLv3 Kx=RSA Au=RSA Enc=RC4(128) Mac=MD5
0x00,0x8A PSK-RC4-SHA SSLv3 Kx=PSK Au=PSK Enc=RC4(128) Mac=SHA1
0xC0,0x12 ECDHE-RSA-DES-CBC3-SHA SSLv3 Kx=ECDH Au=RSA Enc=3DES(168) Mac=SHA1
0xC0,0x08 ECDHE-ECDSA-DES-CBC3-SHA SSLv3 Kx=ECDH Au=ECDSA Enc=3DES(168) Mac=SHA1
0xC0,0x1C SRP-DSS-3DES-EDE-CBC-SHA SSLv3 Kx=SRP Au=DSS Enc=3DES(168) Mac=SHA1
0xC0,0x1B SRP-RSA-3DES-EDE-CBC-SHA SSLv3 Kx=SRP Au=RSA Enc=3DES(168) Mac=SHA1
0xC0,0x1A SRP-3DES-EDE-CBC-SHA SSLv3 Kx=SRP Au=SRP Enc=3DES(168) Mac=SHA1
0x00,0x16 EDH-RSA-DES-CBC3-SHA SSLv3 Kx=DH Au=RSA Enc=3DES(168) Mac=SHA1
0x00,0x13 EDH-DSS-DES-CBC3-SHA SSLv3 Kx=DH Au=DSS Enc=3DES(168) Mac=SHA1
0x00,0x10 DH-RSA-DES-CBC3-SHA SSLv3 Kx=DH/RSA Au=DH Enc=3DES(168) Mac=SHA1
0x00,0x0D DH-DSS-DES-CBC3-SHA SSLv3 Kx=DH/DSS Au=DH Enc=3DES(168) Mac=SHA1
0xC0,0x0D ECDH-RSA-DES-CBC3-SHA SSLv3 Kx=ECDH/RSA Au=ECDH Enc=3DES(168) Mac=SHA1
0xC0,0x03 ECDH-ECDSA-DES-CBC3-SHA SSLv3 Kx=ECDH/ECDSA Au=ECDH Enc=3DES(168) Mac=SHA1
0x00,0x0A DES-CBC3-SHA SSLv3 Kx=RSA Au=RSA Enc=3DES(168) Mac=SHA1
0x00,0x8B PSK-3DES-EDE-CBC-SHA SSLv3 Kx=PSK Au=PSK Enc=3DES(168) Mac=SHA1

davxy