Universita` di Bologna, II Facolta` di Ingegneria Reti di Calcolatori

advertisement
Universita' di Bologna, II Facolta' di Ingegneria
Reti di Calcolatori
Materiale didattico: annesso alla Lezione 1y
OpenSSL - Tutorial
N.B.: questo tutorial e' stato ottenuto per cut-and-paste di materiale contenuto nel
sito: http://www.openssl.org/.
At first the OpenSSL library must be initialized; see SSL_library_init(3).
int SSL_library_init(void);
SSL_library_init() initializes the SSL library by registering algorithms (the available
ciphers and digests).
A typical TLS/SSL application will start with the library initialization, will provide readable
error messages and will seed the PRNG.
#include <openssl/ssl.h>
#define BUFSIZE . . .
char buf[BUFSIZE];
/* inizializza buf */
SSL_load_error_strings();
SSL_library_init();
RAND_seed(buf, BUFSIZE);
/* readable error messages */
/* initialize library */
SSL_library_init() only registers ciphers. Another important initialization is the
seeding of the PRNG (Pseudo Random Number Generator), which has (may have) to be
performed separately.
void RAND_seed(const void *buf, int num);
RAND_seed() mixes the num bytes at buf into the PRNG state. Thus, if the data at buf are
unpredictable to an adversary, this increases the uncertainty about the state and makes the
PRNG output less predictable.
On systems that provide /dev/urandom, the randomness device is used to seed the PRNG
transparently.
Then an SSL_CTX object is created as a framework to establish TLS/SSL
enabled connections (see SSL_CTX_new(3)). Various options regarding
certificates, algorithms etc. can be set in this object.
SSL_CTX *SSL_CTX_new(SSL_METHOD *method);
SSL_CTX_new() creates a new SSL_CTX object as framework to establish TLS/SSL
enabled connections.
The SSL_CTX object uses method as connection method. The methods exist in a generic
type (for client and server use), a server only type, and a client only type. In case you use
TLSv1method can be of the following types:
OpenSSL - Tutorial
1
Universita' di Bologna, II Facolta' di Ingegneria
Reti di Calcolatori
Materiale didattico: annesso alla Lezione 1y
TLSv1_method(void),
TLSv1_server_method(void),
TLSv1_client_method(void)
A TLS/SSL connection established with these methods will only understand the TLSv1
protocol. A client will send out TLSv1 client hello messages and will indicate that it only
understands TLSv1. A server will only understand TLSv1 client hello messages. This
especially means, that it will not understand SSLv2 client hello messages, which are widely
used for compatibility reasons, and SSLv3 client hello messages.
SSL_CTX *sslContext = SSL_CTX_new(TLSv1_method);
if (sslContext == NULL) {
/* errore */
}
When a network connection has been created, it can be assigned to an SSL
object. After the SSL object has been created using SSL_new(3),
SSL_set_fd(3) can be used to associate the network connection with the object.
SSL *SSL_new(SSL_CTX *ctx);
SSL_new() creates a new SSL structure which is needed to hold the data for a TLS/SSL
connection. The new structure inherits the settings of the underlying context ctx: connection
method (SSLv2/v3/TLSv1), options, verification settings, timeout settings.
SSL *sslConnection = SSL_new(sslContext);
if (sslConnection == NULL) {
/* errore */
}
int SSL_set_fd(SSL *ssl, int fd);
SSL_set_fd() sets the file descriptor fd as the input/output facility for the TLS/SSL
(encrypted) side of ssl.
fd will typically be the socket file descriptor of a network connection.
SSL_set_fd() returns 0 if the operation failed, 1 otherwise.
Then the TLS/SSL handshake is performed using SSL_accept(3) or
SSL_connect(3) respectively.
int SSL_connect(SSL *ssl);
SSL_connect() initiates the TLS/SSL handshake with a server. The communication
channel must already have been set and assigned to the ssl.
SSL_connect() returns 1 if the TLS/SSL handshake was successfully completed, and a
TLS/SSL connection has been established, a value 0 otherwise.
int SSL_accept(SSL *ssl);
SSL_accept() waits for a TLS/SSL client to initiate the TLS/SSL handshake. The
communication channel must already have been set and assigned to the ssl.
OpenSSL - Tutorial
2
Universita' di Bologna, II Facolta' di Ingegneria
Reti di Calcolatori
Materiale didattico: annesso alla Lezione 1y
SSL_accept() returns 1 if the TLS/SSL handshake was successfully completed, and a
TLS/SSL connection has been established, a value 0 otherwise.
SSL_read(3) and SSL_write(3) are used to read and write data on the TLS/SSL
connection.
int SSL_read(SSL *ssl, void *buf, int num);
SSL_read() tries to read num bytes from the specified ssl into the buffer buf.
SSL_read() works based on the SSL/TLS records. The data are received in records (with a
maximum record size of 16kB for SSLv3/TLSv1). Only when a record has been completely
received, it can be processed (decryption and check of integrity). Therefore data that was not
retrieved at the last call of SSL_read() can still be buffered inside the SSL layer and will
be retrieved on the next call to SSL_read(). If num is higher than the number of bytes
buffered, SSL_read() will return with the bytes buffered. If no more bytes are in the
buffer, SSL_read() will trigger the processing of the next record. Only when the record has
been received and processed completely, SSL_read() will return reporting success. At
most the contents of the record will be returned. As the size of an SSL/TLS record may
exceed the maximum packet size of the underlying transport (e.g. TCP), it may be necessary
to read several packets from the transport layer before the record is complete and
SSL_read() can succeed.
If a value 0 is returned, the read operation was successful and the return value is the number
of bytes actually read from the TLS/SSL connection. Otherwise, a value 0 is returned: the
reason may be a clean shutdown due to a "close notify'' alert sent by the peer (in which case
the SSL_RECEIVED_SHUTDOWN flag in the ssl shutdown state is set ); it is also possible,
that the peer simply shut down the underlying transport and the shutdown is incomplete.
int SSL_write(SSL *ssl, const void *buf, int num);
SSL_write() writes num bytes from the buffer buf into the specified ssl connection.
SSL_write() will only return with success, when the complete contents of buf of length
num has been written. This default behaviour can be changed with the
SSL_MODE_ENABLE_PARTIAL_WRITE option of SSL_CTX_set_mode. When this flag
is set, SSL_write() will also return with success, when a partial write has been
successfully completed. In this case the SSL_write() operation is considered completed.
The bytes are sent and a new SSL_write() operation with a new buffer (with the already
sent bytes removed) must be started.
When calling SSL_write() with num=0 bytes to be sent the behaviour is undefined.
If a value 0 is returned, the write operation was successful and the return value is the number
of bytes actually written to the TLS/SSL connection. Otherwise, a value 0 is returned.
SSL_shutdown(3) can be used to shut down the TLS/SSL connection.
int SSL_shutdown(SSL *ssl);
SSL_shutdown() shuts down an active TLS/SSL connection. It sends the "close notify''
shutdown alert to the peer.
OpenSSL - Tutorial
3
Universita' di Bologna, II Facolta' di Ingegneria
Reti di Calcolatori
Materiale didattico: annesso alla Lezione 1y
SSL_shutdown() tries to send the "close notify'' shutdown alert to the peer. Whether the
operation succeeds or not, the SSL_SENT_SHUTDOWN flag is set and a currently open
session is considered closed and good and will be kept in the session cache for further reuse.
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 (this way resources can be saved, as the
process can already terminate or serve another connection). When the underlying connection
shall be used for more communications, the complete shutdown procedure (bidirectional
"close notify'' alerts) must be performed, so that the peers stay synchronized.
SSL_shutdown() supports both uni- and bidirectional shutdown by its 2 step behaviour.
When the application is the first party to send the "close notify" alert, SSL_shutdown()
will only send the alert and the set the SSL_SENT_SHUTDOWN flag (so that the session is
considered good and will be kept in cache). SSL_shutdown() will then return with 0.
If a unidirectional shutdown is enough (the underlying connection shall be closed anyway),
this first call to SSL_shutdown() is sufficient.
In order to complete the bidirectional shutdown handshake, SSL_shutdown() must be
called again. The second call will make SSL_shutdown() wait for the peer's "close notify"
shutdown alert. 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(3)), 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().
It is therefore recommended, to check the return value of SSL_shutdown() and call
SSL_shutdown() again, if the bidirectional shutdown is not yet complete (return value of
the first call is 0).
The following return values can occur:

1: The shutdown was successfully completed. The "close notify'' alert was sent and the
peer's "close notify'' alert was received.

0: The shutdown is not yet finished. Call SSL_shutdown() for a second time, if a
bidirectional shutdown shall be performed. The output of SSL_get_error(3) may be
misleading, as an erroneous SSL_ERROR_SYSCALL may be flagged even though no
error occurred.

-1: The shutdown was not successful because a fatal error occurred either at the protocol
level or a connection failure occurred.
OpenSSL - Tutorial
4
Download