99
In general, an application will create just one
SSL_CTX
object for all of the connections it makes. From this
SSL_CTX
object, an
SSL
type object can be created with the
SSL_new
function. This function causes the newly created SSL object to inherit all of the parameters set forth in the
context. Even though most of the settings are copied to the
SSL
object on invocation of
SSL_new
, the order in which calls are made to OpenSSL functions can cause unexpected behavior if were
not careful.
Applications should set up an
SSL_CTX
completely, with all connection invariant settings, before creating
SSL
objects from it. In other words, after calling
SSL_new
with a particular context object, no more calls operating on that
SSL_CTX
object should be made until all produced
SSL
objects are no longer in use. The reason is simple. Modifying a context can sometimes affect the SSL connections that have already been created
i.e.., a function we examine later,
SSL_CTX_set_default_passwd_cb
, changes the callback in the context and in all connections that were already created from this
context. To avoid any unpredictability, never modify the context after connection creation has begun. If there are any connection-specific
parameters that we do need to set, most
SSL_CTX
functions have
SSL
counterparts that act on
SSL
-type objects.
5.1.2.2 Certificate preparation
The SSL protocol usually requires the server to present a certificate. The certificate contains credentials that the client may look at to determine if the server is authentic and can be trusted. As
we know, a peer validates a certificate through verification of its chain of signers. Thus, to implement an SSL server correctly, we must provide certificate and chain information to the peer.
The SSL protocol also allows the client to optionally present certificate information so that the server may authenticate it.
There are, in fact, ways of using SSL to create anonymous connections in which neither the server nor client presents a certificate. These are done
by using the Diffie-Hellman key-agreement protocol and setting the SSL cipher suite to include the anonymous DH algorithm. This is discussed
further
Section 5.1.4.3 below.
In general, server applications should always provide certificates to peers, and clients can do so optionally. The purpose and the desired security of the application should dictate whether client
certificates are used. For instance, a server may request a client certificate, and if our client does not have one to present, we may not be able to establish a secure connection. Thus, its a good idea
to implement client certificates if it makes sense to do so. On the other hand, server certificates are usually required, and, unless our goal is to create a completely nonauthenticated connection, we
should implement them.
OpenSSL presents the client certificate to the server during handshakes, as long as we assign a certificate to the client and the server asks for it. This is actually a small violation of the TLS
protocol. The protocol calls for the server to present a list of valid CAs, and the client should send a certificate only if it matches. In practice, this infraction of the standard should not affect
anything, but the behavior may be fixed in future versions of OpenSSL.
The SSL API has several ways to incorporate certificate information into an
SSL_CTX
object. The function to use is
SSL_CTX_use_certificate_chain_file
. It loads the chain of certificates from the filename specified by the second argument. The file should contain the
TE AM
FL Y
Team-Fly
®
100
certificate chain in order, starting with the certificate for the application and ending with the root CA certificate. Each of these entries must be in PEM format.
In addition to loading the certificate chain, the
SSL_CTX
object must have the applications private key. This key must correspond to the public key embedded within the certificate. The easiest way
that we can supply this key to the context is through the
SSL_CTX_use_PrivateKey_file
function. The second argument specifies the filename, and the third specifies the type of encoding. The type is specified by using a defined name—either
SSL_FILETYPE_PEM
or
SSL_FILETYPE_ASN1
. It bears mentioning that this private key must be kept secret for the application to remain secure. Therefore, using an encrypted PEM format for on-disk storage is
recommended; using triple DES in CBC mode is a good choice. The
SSL_CTX
will fail to incorporate an encrypted private key correctly unless the correct passphrase is supplied.
OpenSSL collects passphrases through a callback function. The default callback prompts the user on the terminal. For some applications, the default will not be acceptable. The function
SSL_CTX_set_default_passwd_cb
allows us to set the callback to something more appropriate for the application. The assigned function is invoked during the call to
SSL_CTX_use_PrivateKey_file
if the indicated file contains an encrypted key. Therefore, the callback should be set before making that call. In fact, the certificates in our chain could be
encrypted even though there is nothing secret about them, and our callback function would be invoked to gather the passphrase. More accurately, we could state that the passphrase function is
called any time a piece of encrypted information is loaded as a parameter to the
SSL_CTX
. The callback functions obligation is to copy the passphrase into the buffer that is supplied to it
when it is called. The callback function is called with four arguments.
int passwd_cbchar buf, int size, int flag, void userdata;
buf The buffer that the passphrase should be copied into. The buffer must be
NULL
terminated. size
The size of the buffer in bytes; includes space for the
NULL
terminating character. flag
Passed as either zero or nonzero. When the flag is nonzero, this passphrase will be used to perform encryption; otherwise, it will be used to perform decryption.
userdata Application-specific data;
SSL_CTX_set_default_passwd_cb_userdata
is used to set this data. Whatever data is set by the application is passed to the callback function
untouched by OpenSSL. There are two approaches to implementing the passphrase callback. The first method is simply to
have the callback prompt the user, copy the collected passphrase to the buffer, and return. This method is viable for applications that need to decrypt a key only once, commonly on application
startup. The second way to implement the callback is for the application to prompt the user for a passphrase on startup and store the collected information in a buffer. The passphrase can be added
to the
SSL_CTX
as user data via the function
SSL_CTX_set_default_passwd_cb_userdata
. With this method, the callback itself only
101
needs to copy the data from the fourth parameter to the first. This method is viable for applications that need to decrypt keys during normal operation in which constant user prompting is a nuisance.
An unlimited number of PEM-encoded items can be stored in a file, but only one DER item may be stored in a file. Also, different types of PEM
items may be stored within a single file. As a result, if the private key is kept in PEM encoding, it can be appended to the certificate chain file, and
the same filename can be used for the calls to
SSL_CTX_use_certificate_chain_file
and
SSL_CTX_use_PrivateKey_file
. This trick is used in Example 5-5
. PEM and DER encodings are discussed in
Chapter 8 .
At this stage, we will limit our discussion to the process of providing certificate information to the peer, rather than discussing the processes of validation. The validation problem will be discussed
in Step 2.
5.1.2.3 Our example extended