|
|
|
|
Although SSL client and server programs might differ in their setup and configuration, their common internal procedures can be summarized in Overview of SSL Application with OpenSSL APIs. These procedures are discussed in the following sections.
Figure 8 Overview of SSL Application with OpenSSL
APIs |
Initializing the SSL Library
Before you can call any other OpenSSL APIs in the SSL application
programs, you must perform initialization using the following SSL
APIs.
SSL_library_init(); /* load encryption & hash algorithms for SSL */ SSL_load_error_strings(); /* load the error strings for good error reporting */
The SSL_library_init()
API registers all ciphers and hash algorithms used in
SSL APIs. The encryption algorithms loaded with this API are DES-CBC,
DES-EDE3-CBC, RC2 and RC4 (IDEA and RC5 are not available in HP
SSL for OpenVMS); and the hash algorithms are MD2, MD5, and SHA.
The SSL_library_init()
API has a return value that is always 1 (integer).
SSL applications should call the SSL_load_error_strings()
API. This API loads error strings for SSL APIs as well
as for Crypto APIs. Both SSL and Crypto error strings need to be
loaded because many SSL applications call some Crypto APIs as well
as SSL APIs.
Creating and Setting Up the SSL Context Structure
(SSL_CTX)
The first step after the intialization is to choose an SSL/TLS
protocol version. Do this by creating an SSL_METHOD
structure
with one of the following APIs. The SSL_METHOD
structure
is then used to create an SSL_CTX
structure with
the SSL_CTX_new()
API.
For every SSL/TLS version, there are three types of APIs to
create an SSL_METHOD
structure: one for both client
and server, one for server only, and one for client only. SSLv2,
SSLv3, and TLSv1 APIs correspond with the same name protocols.
Types of APIs for SSL_METHOD Creation shows the types of APIs.
There is no SSL protocol version named SSLv23. The SSLv23_method() API and its variants choose SSLv2, SSLv3, or TLSv1 for
compatibility with the peer. |
SSLv23_method()
API and its variants may be used when the compatibility
with the peer is important. An SSL server with the SSLv23 method
can understand any of the SSLv2, SSLv3, and TLSv1 hello messages.
However, the SSL client using the SSLv23 method cannot establish
connection with the SSL server with the SSLv3/TLSv1 method because SSLv2
hello message is sent by the client. The SSL_CTX_new()
API takes the SSL_METHOD
structure
as an argument and creates an SSL_CTX
structure.
In the following example, an SSL_METHOD
structure
that can be used for either an SSLv3 client or SSLv3 server is created
and passed to SSL_CTX_new()
. The SSL_CTX
structure is initialized
for SSLv3 client and server.
meth = SSLv3_method(); ctx = SSL_CTX_new(meth);
Setting Up the Certificate and Key
Certificates for SSL Applications discussed how
the SSL client and server programs require you to set up appropriate
certificates. This setup is done by loading the certificates and
keys into the SSL_CTX
or SSL structures. The
mandatory and optional certificates are as follows:
Server's own certificate (mandatory)
CA certificate (optional)
CA certificate (mandatory)
Client's own certificate (optional)
Loading a Certificate (Client/Server Certificate)
Use the SSL_CTX_use_certificate_file()
API to load a certificate into an SSL_CTX
structure.
Use the SSL_use_certificate_file()
API to load a certificate into an SSL
structure.
When the SSL
structure is created, the SSL
structure
automatically loads the same certificate that is contained in the SSL_CTX
structure. Therefore,
you onlyneed to call the SSL_use_certificate_file()
API for the SSL
structure only if
it needs to load a different certificate than the default certificate
contained in the SSL_CTX
structure.
Loading a Private Key
The next step is to set a private key that corresponds to
the server or client certificate. In the SSL handshake, a certificate
(which contains the public key) is transmitted to allow the peer
to use it for encryption. The encrypted message sent from the peer
can be decrypted only using the private key. You must preload the private
key that was created with the public key into the SSL
structure.
The following APIs load a private key into an SSL
or SSL_CTX
structure:
SSL_CTX_use_PrivateKey()
SSL_CTX_use_PrivateKey_ASN1()
SSL_CTX_use_PrivateKey_file()
SSL_CTX_use_RSAPrivateKey()
SSL_CTX_use_RSAPrivateKey_ASN1()
SSL_CTX_use_RSAPrivateKey_file()
SSL_use_PrivateKey()
SSL_use_PrivateKey_ASN1()
SSL_use_PrivateKey_file()
SSL_use_RSAPrivateKey()
SSL_use_RSAPrivateKey_ASN1()
SSL_use_RSAPrivateKey_file()
Loading a CA Certificate
To verify a certificate, you must first load a CA certificate
(because the peer certificate is verified against a CA certificate).
The SSL_CTX_load_verify_locations()
API loads a CA certificate into the SSL_CTX
structure.
The prototype of this API is as follows:
int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile, const char *CApath);
The first argument, ctx
, points to an SSL_CTX
structure
into which the CA certificate is loaded. The second and third arguments, CAfile
and CApath
,
are used to specify the location of the CA certificate. When looking up
CA certificates, the OpenSSL library first searches the certificates
in CAfile
, then those in CApath
.
The following rules apply to the CAfile
and CApath
arguments:
CAfile
(the
certificate must exist in the same directory as the SSL application),
specify NULL for CApath
. CApath
,
specify NULL for CAfile
. You must also hash the
CA certificates in the directory specified by CApath
.
Use the Certificate Tool (described in Chapter 3) to perform the
hashing operation.Setting Up Peer Certificate Verification
The CA certificate loaded in the SSL_CTX
structure
is used for peer certificate verification. For example, peer certificate
verification on the SSL client is performed by checking the relationships
between the CA certificate (loaded in the SSL client) and the server
certificate.
For successful verification, the peer certificate must be
signed with the CA certificate directly or indirectly (a proper
certificate chain exists). The certificate chain length from the
CA certificate to the peer certificate can be set in the verify_depth
field
of the SSL_CTX
and SSL
structures.
(The value in SSL
is inherited from SSL_CTX
when
you create an SSL
structure using the SSL_new()
API). Setting verify_depth
to 1 means
that the peer certificate must be directly signed by the CA certificate.
The SSL_CTX_set_verify()
API allows you to set the verification flags in the SSL_CTX
structure
and a callback function for customized verification as its third
argument. (Setting NULL to the callback function means the built-in
default verification function is used.) In the second argument of SSL_CTX_set_verify()
, you can set the following macros:
SSL_VERIFY_NONE
SSL_VERIFY_PEER
SSL_VERIFY_FAIL_IF_NO_PEER_CERT
SSL_VERIFY_CLIENT_ONCE
The SSL_VERIFY_PEER
macro can be used on
both SSL client and server to enable the verification. However, the
subsequent behaviors depend on whether the macro is set on a client
or a server. For example:
/* Set a callback function (verify_callback) for peer certificate */ /* verification */ SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_callback); /* Set the verification depth to 1 */ SSL_CTX_set_verify_depth(ctx,1);You can verify a peer certificate in another, less common way - by using the
SSL_get_verify_result()
API. This method allows you to obtain the peer certificate
verification result without using the SSL_CTX_set_verify()
API.Call the following two APIs before you
call the SSL_get_verify_result()
API:
SSL_connect()
(in the client) or SSL_accept()
(in the server) to perform the SSL handshake. Certificate
verification is performed during the handshake. SSL_get_verify_result()
cannot obtain the result before the verification process. SSL_get_peer_certificate()
to explicitly obtain the peer certificate. The X509_V_OK
macro
value is returned when a peer certificate is not presented as well
as when the verification succeeds. The following code shows how to use SSL_get_verify_result()
in the SSL client:
SSL_CTX_set_verify_depth(ctx, 1); err = SSL_connect(ssl); if(SSL_get_peer_certificate(ssl) != NULL) { if(SSL_get_verify_result(ssl) == X509_V_OK)
BIO_printf(bio_c_out, "client verification with SSL_get_verify_result() succeeded.\n"); else{ BIO_printf(bio_err, "client verification with SSL_get_verify_result() failed.\n"); exit(1); } } else BIO_printf(bio_c_out, -the peer certificate was not presented.\n-);
Example 1: Setting Up Certificates for the
SSL Server
The SSL protocol requires that the server set its own certificate
and key. If you want the server to conduct client authentication
with the client certificate, the server must load a CA certificate
so that it can verify the client-s certificate.
The following example shows how to set up certificates for the SSL server:
/* Load server certificate into the SSL context */ if (SSL_CTX_use_certificate_file(ctx, SERVER_CERT, SSL_FILETYPE_PEM) <= 0) }
ERR_print_errors(bio_err); /* == ERR_print_errors_fp(stderr); */ exit(1); } /* Load the server private-key into the SSL context */ if (SSL_CTX_use_PrivateKey_file(ctx, SERVER_KEY, SSL_FILETYPE_PEM) <= 0) {
ERR_print_errors(bio_err); /* == ERR_print_errors_fp(stderr); */ exit(1); } /* Load trusted CA. */ if (!SSL_CTX_load_verify_locations(ctx,CA_CERT,NULL)) { ERR_print_errors(bio_err); /* == ERR_print_errors_fp(stderr); */ exit(1); } /* Set to require peer (client) certificate verification */ SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_callback); /* Set the verification depth to 1 */ SSL_CTX_set_verify_depth(ctx,1);
Example 2: Setting Up Certificates for the
SSL Client
Generally, the SSL client verifies the server certificate
in the process of the SSL handshake. This verification requires
the SSL client to set up its trusting CA certificate. The server
certificate must be signed with the CA certificate loaded in the
SSL client in order for the server certificate verification to succeed.
The following example shows how to set up certificates for the SSL client:
/*----- Load a client certificate into the SSL_CTX structure -----*/ if(SSL_CTX_use_certificate_file(ctx,CLIENT_CERT, SSL_FILETYPE_PEM) <= 0){ ERR_print_errors_fp(stderr); exit(1); } /*----- Load a private-key into the SSL_CTX structure -----*/ if(SSL_CTX_use_PrivateKey_file(ctx,CLIENT_KEY, SSL_FILETYPE_PEM) <= 0){ ERR_print_errors_fp(stderr); exit(1); } /* Load trusted CA. */ if (!SSL_CTX_load_verify_locations(ctx,CA_CERT,NULL)) { ERR_print_errors_fp(stderr); exit(1); }
Creating and Setting
Up the SSL Structure
Call SSL_new()
to create an SSL
structure. Information
for an SSL connection is stored in the SSL
structure. The
protocol for the SSL_new()
API is as follows:
ssl = SSL_new(ctx);
A newly created SSL
structure inherits
information from the SSL_CTX
structure. This
information includes types of connection methods, options, verification
settings, and timeout settings. No additional settings are required
for the SSL
structure if the appropriate initialization
and configuration have been done for the SSL_CTX
structure.
You can modify the default values in the SSL
structure
using SSL APIs. To do this, use variants of the APIs that set attributes
of the SSL_CTX
structure. For example, you can
use SSL_CTX_use_certificate()
to load a certificate into an SSL_CTX
structure,
and you can use SSL_use_certificate()
to load a certificate into an SSL
structure.
Setting Up the TCP/IP
Connection
Although SSL works with some other reliable protocols, TCP/IP
is the most common transport protocol used with SSL.
The following sections describe how to set up TCP/IP for the SSL APIs. This configuration is the same as in many other TCP/IP client/server application programs; it is not specific to SSL API applications. In these sections, TCP/IP is set up with the ordinary socket APIs, although it is also possible to use OpenVMS system services.
Creating and Setting Up the Listening Socket
(on the SSL Server)
The SSL server needs two sockets as an ordinary TCP/IP server--one
for the SSL connection, the other for detecting an incoming connection
request from the SSL client.
In the following code, the socket()
function creates a listening socket. After the address
and port are assigned to the listening socket with bind()
, the listen()
function allows the listening socket to handle an incoming
TCP/IP connection request from the client.
listen_sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); CHK_ERR(listen_sock, "socket"); memset(&
sa_serv, 0, sizeof(sa_serv)); sa_serv.sin_family = AF_INET; sa_serv.sin_addr.s_addr = INADDR_ANY; sa_serv.sin_port = htons(s_port); /* Server Port number */ err = bind(listen_sock, (struct sockaddr*)&
sa_serv,sizeof(sa_serv)); CHK_ERR(err, "bind"); /* Receive a TCP connection. */ err = listen(listen_sock, 5); CHK_ERR(err, "listen");
Creating and Setting Up the Socket (on the
SSL Client)
On the client, you must create a TCP/IP socket and attempt
to connect to the server with this socket. To establish a connection
to the specified server, the TCP/IP connect()
function is used. If the function succeeds, the socket
passed to the connect()
function as a first argument can be used for data communication
over the connection.
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); CHK_ERR(sock, "socket");
memset (&
server_addr, '\0', sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(s_port); /* Server Port number */ server_addr.sin_addr.s_addr = inet_addr(s_ipaddr); /* Server IP */ err = connect(sock, (struct sockaddr*)&
server_addr, sizeof(server_addr)); CHK_ERR(err, "connect");
Establishing a TCP/IP Connection (on the
SSL Server)
To accept an incoming connection request and to establish
a TCP/IP connection, the SSL server needs to call the accept()
function. The socket created with this function is used
for the data communication between the SSL client and server. For
example:
sock = accept(listen_sock, (struct sockaddr*)&
sa_cli,&
client_len); BIO_printf(bio_c_out, "Connection from %lx, port %x\n", sa_cli.sin_addr.s_addr, sa_cli.sin_port);
Setting Up the Socket/Socket
BIO in the SSL Structure
After you create the SSL
structure and
the TCP/IP socket (sock
), you must configure
them so that SSL data communication with the SSL
structure
can be performed automatically through the socket.
The following code fragments show the various ways to assign sock
to ssl
.
The simplest way is to set the socket directly into the SSL structure,
as follows:
SSL_set_fd(ssl, sock);
A better way is to use a BIO
structure,
which is the I/O abstraction provided by OpenSSL. This way is preferable
because BIO
hides details of an underlying I/O.
As long as a BIO
structure is set up properly,
you can establish SSL connections over any I/O.
The following two examples demonstrate how to create a socket BIO
and
set it into the SSL
structure.
sbio=BIO_new(BIO_s_socket()); BIO_set_fd(sbio, sock, BIO_NOCLOSE); SSL_set_bio(ssl, sbio, sbio);In the following example, the
BIO_new_socket()
API creates a socket BIO
in which
the TCP/IP socket is assigned, and the SSL_set_bio()
API assigns the socket BIO
into the SSL
structure.
The following two lines of code are equivalent to the preceding
three lines: sbio = BIO_new_socket(socket, BIO_NOCLOSE); SSL_set_bio(ssl, sbio, sbio);
If there is already a BIO connected
to ssl , BIO_free() is called
(for both the reading and writing side, if different). |
SSL Handshake
The SSL handshake is a complicated process that involves significant
cryptographic key exchanges. However, the handshake can be completed
by calling SSL_accept()
on the SSL server and SSL_connect()
on the SSL client.
SSL Handshake on the SSL Server
The SSL_accept()
API waits for an SSL handshake initiation from the SSL
client. Successful completion of this API means that the SSL handshake
has been completed.
err = SSL_accept(ssl);
SSL Handshake on the SSL Client
The SSL client calls the SSL_connect()
API to initiate an SSL handshake. If this API returns
a value of 1, the handshake has completed successfully. The data
can now be transmitted securely over this connection.
err = SSL_connect(ssl);
Performing an SSL Handshake with SSL_read
and SSL_write (Optional)
Optionally, you can call SSL_write()
and SSL_read()
to complete the SSL handshake as well as perform SSL
data exchange. With this approach, you must call SSL_set_accept_state()
before you call SSL_read()
on the SSL server. You must also call SSL_set_connect_state()
before you call SSL_write()
on the client. For example:
/* When SSL_accept() is not called, SSL_set_accept_state() */ /* must be called prior to SSL_read() */ SSL_set_accept_state(ssl); /* When SSL_connect() is not called, SSL_set_connect_state() */ /* must be called prior to
SSL_write() */ SSL_set_connect_state(ssl);
Obtaining a Peer Certificate (Optional)
Optionally, after the SSL handshake, you can obtain a peer
certificate by calling SSL_get_peer_certificate()
. This API is often used for straight certificate verification,
such as checking certificate information (for example, the common
name and expiration date).
peer_cert = SSL_get_peer_certificate(ssl);
Transmitting SSL
Data
After the SSL handshake is completed, data can be transmitted
securely over the established SSL connection. SSL_write()
and SSL_read()
are used for SSL data transmission, just as write()
and read()
or send()
and recv()
are used for an ordinary TCP/IP connection.
Sending Data
To send data over the SSL connection, call SSL_write()
. The data to be sent is stored in the buffer specified as
a second argument. For example:
err = SSL_write(ssl, wbuf, strlen(wbuf));
Receiving Data
To read data sent from the peer over the SSL connection, call SSL_read()
. The received data is stored in the buffer specified
as a second argument. For example:
err = SSL_read(ssl, rbuf, sizeof(rbuf)-1);
Using BIOs for SSL Data Transmission (Optional)
Instead of using SSL_write()
and SSL_read()
, you can transmit data by calling BIO_puts()
and BIO_gets()
, and BIO_write()
and BIO_read()
, provided that a buffer BIO is created and set up as
follows:
BIO *buf_io, *ssl_bio; char rbuf[READBUF_SIZE]; char wbuf[WRITEBUF_SIZE] buf_io = BIO_new(BIO_f_buffer()); /* create a buffer BIO */ ssl_bio = BIO_new(BIO_f_ssl()); /* create an ssl BIO */ BIO_set_ssl(ssl_bio, ssl, BIO_CLOSE); /* assign the ssl BIO to SSL */ BIO_push(buf_io, ssl_bio); /* add ssl_bio to buf_io */ ret = BIO_puts(buf_io, wbuf); /* Write contents of wbuf[] into buf_io */ ret = BIO_write(buf_io, wbuf, wlen); /* Write wlen-byte contents of wbuf[] into buf_io */ ret = BIO_gets(buf_io, rbuf, READBUF_SIZE); /* Read data from buf_io and store in rbuf[] */ ret = BIO_read(buf_io, rbuf, rlen); /* Read rlen-byte data from buf_io and store rbuf[] */
Closing an SSL Connection
When you close an SSL connection, the SSL client and server
send close_notify
messages to notify each other
of the SSL closure. You use the SSL_shutdown()
API to send the close_notify
alert
to the peer.
The shutdown procedure consists of two steps:
close_notify
shutdown
alertclose_notify
shutdown
alert from the peerThe following rules apply to closing an SSL connection:
close_notify
alert. close_notify
alert
before closing the write side of the connection. close_notify
alert of its own and to close
down the connection immediately, discarding any pending writes. close_notify
alert before
closing the read side of the connection. The SSL client or server that initiates the SSL closure calls SSL_shutdown()
either once or twice. If it calls the API twice, one
call sends the close_notify
alert and one call
receives the response from the peer. If the initator calls the API
only once, the initiator does not receive the close_notify
alert
from the peer. (The initiator is not required to wait for the responding
alert.)
The peer that receives the alert calls SSL_shutdown()
once to send the alert to the initiating party.
Resuming an SSL Connection
You can reuse the information from an already established
SSL session to create a new SSL connection. Because the new SSL
connection is reusing the same master secret, the SSL handshake
can be performed more quickly. As a result, SSL session resumption
can reduce the load of a server that is accepting many SSL connections.
Perform the following steps to resume an SSL session on the SSL client:
ret = SSL_connect(ssl) (Use SSL_read() / SSL_write() for data communication over the SSL connection)
sess = SSL_get1_session(ssl); /* sess is an SSL_SESSION, and ssl is an SSL */
SSL_shutdown(ssl);
ssl = SSL_new(ctx);
SSL_connect()
.SSL_set_session(ssl, sess); err = SSL_connect(ssl);
ret = SSL_connect(ssl) (Use SSL_read() / SSL_write() for data communication over the SSL connection)
If the SSL client calls SSL_get1_session()
and SSL_set_session()
, the SSL server can accept a new SSL connection using
the same session without calling special APIs to resume the session.
The server does this by following the steps discussed in
Creating and Setting Up the SSL Structure,
Setting Up the TCP/IP Connection,
Setting Up the Socket/Socket BIO in the SSL Structure,
SSL Handshake, and
Transmitting SSL Data.
Calling SSL_free() results in the failure of the SSL session to resume,
even if you saved the SSL session with SSL_get1_session() . |
Renegotiating the SSL Handshake
SSL renegotiation is a new SSL handshake over an already established
SSL connection. Because the renegotiation messages (including types
of ciphers and encryption keys) are encrypted and then sent over
the existing SSL connection, SSL renegotiation can establish another
SSL session securely. SSL renegotiation is useful in the following
situations, once you have established an ordinary SSL session:
The following sections discuss the required APIs for both situations.
SSLv2 cannot perform SSL renegotiation. Use SSLv3 or TLSv3 for this operation. |
SSL Renegotiation Initiated by the SSL Server
To initiate an SSL renegotiation from the SSL server, call SSL_renegotiate()
once and SSL_do_handshake()
twice.
The SSL_renegotiate()
API sets flags for SSL renegotiation. This API does
not actually initiate the renegotiation. The flags turned on by SSL_renegotiate()
inform SSL_do_handshake()
that it needs to perform SSL renegotiation with the
SSL client. The SSL_do_handshake()
API performs an actual SSL handshake. The first call
sends a -Server Hello- message to the SSL client.
If the first call succeeds, the client has agreed to perform
an SSL renegotiation. The server then sets the SSL_ST_ACCEPT
state
in the SSL structure and calls SSL_do_handshake()
again to complete the rest of the renegotiation.
The following code fragment shows how these APIs are used:
printf(The following code shows the APIs called by the SSL client when the renegotiation is initiated by the server:"
Starting SSL renegotiation on SSL server (initiating by SSL server)"
); if(SSL_renegotiate(ssl) <= 0){ printf("
SSL_renegotiate() failed\n"
); exit(1); } if(SSL_do_handshake(ssl) <= 0){ printf("
SSL_do_handshake() failed\n"
); exit(1); } ssl->state = SSL_ST_ACCEPT; if(SSL_do_handshake(ssl) <= 0){ printf("
SSL_do_handshake() failed\n"
); exit(1); }
printf("
Starting SSL renegotiation on SSL client (initiating by SSL server)"
); /* SSL renegotiation */ err = SSL_read(ssl, buf, sizeof(buf)-1);
As the example shows, SSL_READ()
performs data exchange, and can also handle connection-related
functions such as renegotiation.
SSL Renegotiation Initiated by the SSL Client
The SSL client can also initiate SSL renegotiation. In this
case, the setup on the client initiating the renegotiation is similar
to that on a server initiating the renegotiation. To complete this
operation, the SSL client calls SSL_renegotiate()
and SSL_do_handshake()
only once. SSL_renegotiate()
simply sets the flags for SSL renegotiation, and a single
call of SSL_do_handshake()
covers the entire renegotiation.
printf(The following code shows the APIs called by the SSL server when the renegotiation is initiated by the client. (These are the same APIs that are called by the SSL client when the renegotiation is initiated by the server.)"
Starting SSL renegotiation on SSL client (initiating by SSL client)"
); if(SSL_renegotiate(ssl) <= 0){ printf("
SSL_renegotiate() failed\n"
); exit(1); } if(SSL_do_handshake(ssl) <= 0){ printf("
SSL_do_handshake() failed\n"
); exit(1); }
printf(Again in this example,"
Starting SSL renegotiation on SSL server (initiating by SSL client)"
); /* SSL renegotiation */ err = SSL_read(ssl, buf, sizeof(buf)-1);
SSL_READ()
is handling the data exchange and connection renegotiation.
Finishing the SSL Application
When you finish an SSL application program, the major task
is to free (deallocate) the data structures that were created and
used in the application program. The APIs for deallocation usually
contain the _free
suffix, whereas the APIs that
create a new data structure contain the_new
suffix.
You must free data structures that you explicitly created
in the SSL application program. Data structures that were created
inside another structure with an xxx_new()
API are automatically deallocated when the structure
is deallocated with the corresponding xxx_free()
API. For example, a BIO structure created with SSL_new()
is freed when you call SSL_free()
; you do not need to call BIO_free()
to free the BIO inside the SSL structure. However, if
the application program called BIO_new()
to allocate a BIO structure, you must free that structure
with BIO_free()
.
You must call SSL_shutdown() before you call SSL_free() . |
|
|