3. Summary
Purpose
This document provides a basic function calling flow of OpenSSL library for constructing a secure TCP
connection to send/receive critical data.
General Description
The OpenSSL library implements the Secure Sockets Layer (SSL v2/v3) protocols.
At first, the library must be initialized by calling the function : SSL_library_init() .
Then an SSL_CTX object is created as a framework to establish TLS/SSL enabled connections. This object
is created by calling the function : SSL_CTX_new().
Various options regarding certificates, algorithms etc. can be set in this object.
When a network connection (e.g. TCP connection) has been created, it can be assigned to an SSL object.
After the SSL object has been created using SSL_new(), SSL_set_fd() or SSL_set_bio() can be used to
associate the network connection with the object.
Then the TLS/SSL handshake is performed using SSL_accept() (for server side) or SSL_connect() (for
client side) respectively.
SSL_read() and SSL_write() are used to read and write data on the TLS/SSL connection.
SSL_shutdown() can be used to shut down the TLS/SSL connection.
4. OpenSSL Data Structures
Currently the OpenSSL library functions deals with the following data structures:
SSL_METHOD
The SSL Method. That's a dispatch structure describing the internal SSL library methods/functions which
implement the various protocol versions (SSLv1, SSLv2 and TLSv1). It's needed to create an SSL_CTX.
Data Structure SSL_METHOD
Definded in ssl.h
File Location OpenSSL-Srcssl
SSL_CIPHER
The SSL Cipher. This structure holds the algorithm information for a particular cipher which are a core part
of the SSL/TLS protocol. The available ciphers are configured on a SSL_CTX basis and the actually used
ones are then part of the SSL_SESSION.
Data Structure SSL_CIPHER
Definded in ssl.h
File Location OpenSSL-Srcssl
SSL_CTX
The SSL Context. That's the global context structure which is created by a server or client once per program
life-time and which holds mainly default values for the SSL structures which are later created for the
connections.
Data Structure SSL_CTX
Definded in ssl.h
File Location OpenSSL-Src ssl
SSL_SESSION
The SSL Session . This is a structure containing the current TLS/SSL session details for a connection:
SSL_CIPHER, client and server certificates, keys, etc.
Data Structure SSL_SESSION
Definded in ssl.h
File Location OpenSSL-Src ssl
SSL
The SSL Connection . That's the main SSL/TLS structure which is created by a server or client per
established connection. This actually is the core structure in the SSL API. Under run-time the application
usually deals with this structure which has links to mostly all other structures.
6. Basic Calling Flow
int SSL_library_init(void)
Initializing the OpenSSL library.
call
SSL_METHOD *SSLv23_method(void)
Constructor for the SSLv2 or SSLv3
SSL_METHOD structure for combined
client and server.
call
SSL_CTX* SSL_CTX_new(SSL_METHOD *method)
SSL_CTX object is created as a framework to establish
TLS/SSL enabled connections.
call
RAND_add() : Load the Randomness
This step is for initializing the randomness for generating session key
(client key).
This phase will do automatically with RAND_poll() function which will
call RAND_add() indirectly in below O.S platform:
<1>OS2 <2>Unix <3>OpenBSD <4>Linux <5>Windows.
If the platform other than the above, we must call RAND_add() explicitly.
For example, in VxWorks RTOS, it must call RAND_add() explicitly.
call
7. call
Creates a TCP connection.
{ This will generate a socket
handler,e.g. file descriptor }
call
SSL* SSL_new(SSL_CTX *ctx)
Creates a new SSL structure which
is needed to hold the data for a
TLS/SSL connection.
call
int SSL_set_fd (SSL *ssl, int 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.
call
call
Is this a Server
application
Yes, this is a
Server application
call
No, this is a Client
application
int SSL_connect(SSL *ssl)
Initiates the TLS/SSL handshake
with a server.
SSL Handshaking
int SSL_accept(SSL *ssl)
Waits for a TLS/SSL client to
initiate the TLS/SSL handshake.
Successful Handshaking
8. int SSL_read(SSL*ssl, void *buf, int num)
Tries to read num bytes from the specified
ssl into the buffer buf.
int SSL_write(SSL *ssl, const void
*buf, int num)
Writes num bytes from the buffer buf into
the specified SSL connection, ssl.
from read from write
Need to
terminating the
SSL connection?
No, continues to
use the active
SSL connection.
Yes, terminate the
SSL connection
int SSL_shutdown(SSL *ssl)
Shuts down an active TLS/SSL
connection. It sends the “close notify”
shutdown alert to the peer.
Going back to the
SSL read/write
operation
call
int SSL_free(SSL *ssl)
Decrements the reference count of ssl, and removes the
SSL structure pointed to by ssl and frees up the allocated
memory if the the reference count has reached 0.
call
read
operation?
call
No, this is a
write operation
call
Yes, this is a
read operation
Successful Handshaking
9. call
int SSL_CTX_free(SSL_CTX *ctx)
Decrements the reference count of ctx, and removes the SSL_CTX
object pointed to by ctx and frees up the allocated memory if the the
reference count has reached 0.
It also calls free() to release memory of items(if it is available):
session cache, list of ciphers, list of Client CAs, certificates and keys.
call
int close(int socket)
This the socket function to close a
socket and terminate a TCP connection.
Finish
The above function call flow is just a basic flow to create a SSL connection without client authentication
and doing read/write operations.
10. genRANDOM() Function
This is a randomness initialization function we created. It calls the OpenSSL function, RAND_add(), to
accomplish the randomness initialization operation(that is to seed unpredictable data to a cryptographic
PRNG (Pseudo-Random Number Generator). The function signature is :
void RAND_add (const void *buf, int num, double entropy)
The followings are the steps showing how to use RAND_add() function to initailize randomness.
Step 1)
We created a string type variable and fill arbitrary chars (the content should be unpredictable that any one
can’t guess it). In our codes, we do as below :
static char* strRANDOM =
"FreeBSD -STABLE #4: Tue g5 15:50:0PDT000
Tiecounti8254 frequen193182 Hz
CP: Pent II/Xeon/Celeron400.MHz 6-cls CPU)
Prbing fdevices on PCI b:
chp0: <Il 82443BX host tI bri> v 02 on pci0.0.0
Prbing fPnP devices:
sc: VGA or <16 virtualoles, flagsx0>
ed not fd at 0x280
ah0 not nd at 0x34
ai0 not nd
vg0 at 00-0x3df madd000 msize 1372 on isa";
Step 2)
Now, we start use RAND_add() function to seed PRNG. The using is shown below :
11. for(;;)
{
if (Bytes > 0)
n = (Bytes < BUFSIZ)?(int)Bytes:BUFSIZ;
else
n = BUFSIZ;
while( (i = rand()%1000-13) ==0)
;
strncpy(buf, (strRANDOM+offset), i);
RAND_add (buf, n, i);
offset += i;
if (offset>=(len+1))
break;
if (Bytes > 0)
{
Bytes -= n;
if (Bytes <= 0)
break;
} /*if(Bytes)*/
} /* for(;;) */
12. The complete genRANDOM() body is :
#define BUFSIZ 1024
static void genRANDOM()
{
long Bytes = 1024*10;
int i =0, offset=0, n=0, len=strlen(strRANDOM);
char buf[BUFSIZ];
printf("[CWMP] genRANDOM()n");
memset(buf, 0, BUFSIZ);
for(;;)
{
if (Bytes > 0)
n = (Bytes < BUFSIZ)?(int)Bytes:BUFSIZ;
else
n = BUFSIZ;
while( (i = rand()%1000-13) ==0)
;
strncpy(buf, (strRANDOM+offset), i);
RAND_add (buf, n, i);
offset += i;
if (offset>=(len+1))
break;
if (Bytes > 0)
{
Bytes -= n;
if (Bytes <= 0)
break;
}
} /* End of for(;;) */
} /* End of genRAND() */
13. SSL Client Side Example Codes
#include "openssl/bio.h"
#include "openssl/crypto.h"
#include "openssl/x509.h"
#include "openssl/ssl.h"
#include "openssl/err.h" /* For error message */
#include “openssl/rand.h” /* For RAND_add() */
#define BUFSIZZ 2048
/*================ Global variables ================*/
static char *hostIP = "10.1.25.162";
struct sockaddr_in addr; /* socket address */
int sock = 0; /* socket */
unsigned int hp = 0; /* for host IP address */
int ret= 0, request_len, len;
char buf[BUFSIZZ];
SSL_METHOD *meth = NULL;
SSL_CTX *ctx = NULL;
BIO *sbio = NULL;
/*===================== SSL Initialization =====================*/
SSL_library_init(); /* Initializing the SSL libraries */
SSL_load_error_strings(); /* Loading the error message string for each error code */
meth = SSLv23_method(); /* Init the methods for handshaking and accessing SSL data */
ctx = SSL_CTX_new(meth); /* Create a SSL context */
genRANDOM();
printf("SSL Init Done!n");
/* Resolving the IP address of the target host */
if ( (hp=hostGetByName((char*)hostIP)) == ERROR) /* hostGetByName() calls gethostbyname()*/
{
/* socket interface */
printf ("Couldn't resolve host");
exit (1);
}
/* Setting the network address structure */
memset (&addr, 0, sizeof(addr));
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_family = AF_INET;
addr.sin_port = htons (443); /* Well-known port number for HTTPS */
14. /* Get the socket */
if ( (sock = socket(AF_INET,SOCK_STREAM, IPPROTO_TCP))<0 )
{
fprintf(stderr, "Couldn't create socket");
exit(1);
}
/*================ Try to create the TCP connection ================*/
if ( connect(sock, (struct sockaddr *)&addr, sizeof(addr))<0 )
{
fprintf(stderr, "Couldn't connect socket");
exit(1);
}
printf("The TCP Connection is created!n");
/*================ Create the SSL connection context ================*/
ssl = SSL_new (ctx);
sbio = BIO_new_socket (sock, BIO_NOCLOSE);
SSL_set_bio (ssl, sbio, sbio);
printf("Starting to do SSL Handshaking…n");
if ( SSL_connect (ssl) <= 0 ) /* Note: at this point it is in blocking mode */
{
char errstr[256];
int sslres;
printf("SSL handshaking fail!n");
sslres = SSL_get_error (ssl, res);
ERR_error_string_n (sslres, errstr,s 256); /* Convert the error code to the man readable error
string. */
printf(“The SSL error is %d => %sn”, sslres, errstr);
exit(1);
}
char* httpRequest =
”GET /top.html HTTP/1.0rnUser-Agent:"
"HTTP_ClientrnHost: 10.1.25.162:443rnrn”;
request_len = strlen (httpRequest );
ret = SSL_write(ssl, httpRequest , request_len); /* Send out the HTTP request message */
switch ( SSL_get_error(ssl, ret) )
15. {
case SSL_ERROR_NONE :
if ( request_len != ret )
{
fprintf(stderr, "Incomplete write!");
exit(1);
}
break;
default:
fprintf(stderr, "SSL write problem");
exit(1);
} /* End of switch */
/* Now read the server's response, assuming that it's terminated by a close */
while (1)
{
ret = SSL_read (ssl, buf, BUFSIZZ);
switch ( SSL_get_error (ssl, ret))
{
case SSL_ERROR_NONE:
len=ret;
break;
case SSL_ERROR_WANT_READ:
continue;
case SSL_ERROR_ZERO_RETURN:
goto shutdown;
case SSL_ERROR_SYSCALL:
fprintf(stderr,"SSL Error: Premature closen");
goto done;
default:
{
fprintf(stedrr, "SSL read problem"); exit(1);
}
} /* End of switch */
printf("Content = n%sn", buf);
} /* End of while(1) */
shutdown:
ret = SSL_shutdown (ssl); /* Send “Close” notify to the HTTP server */
switch(ret)
{
case 1:
break; /* Success */
16. case 0:
case -1:
default:
{ fprintf(stderr, "Shutdown failed"); exit(1); }
} /* End of switch */
done:
SSL_free(ssl);
SSL_CTX_free (ctx);
close(sock); /* Send “Close” notify to the HTTP server */
/*~~~~~~~~~~~~~~~~~~~ End of SSL client side example codes ~~~~~~~~~~~~~~~~~~~*/
17. Reference
* OpenSSL, http://www.openssl.org/
* http://www.openssl.org/docs/apps/
* http://www.openssl.org/docs/crypto/
* http://www.openssl.org/docs/ssl/
* PRNG implementation interface of OpenSSL
http://www.openssl.org/docs/crypto/rand.html
* RAND_add function how-to
http://www.openssl.org/docs/crypto/RAND_add.html
* Randomness Recommendations for Security
http://www.potaroo.net/ietf/rfc/rfc1750.txt