124
28 { 29 DH ret;
30 31 if dh512 || dh1024
32 init_dhparams; 33
34 switch keylength 35 {
36 case 512: 37 ret = dh512;
38 break; 39 case 1024:
40 default: generating DH params is too costly to do on the fly 41 ret = dh1024;
42 break; 43 }
44 return ret; 45 }
46 47 define CIPHER_LIST ALL:ADH:LOW:EXP:MD5:STRENGTH
48 define CAFILE rootcert.pem 49 define CADIR NULL
50 define CERTFILE server.pem 51 SSL_CTX setup_server_ctxvoid
52 { 53 SSL_CTX ctx;
54 55 ctx = SSL_CTX_newSSLv23_method;
56 if SSL_CTX_load_verify_locationsctx, CAFILE, CADIR = 1 57 int_errorError loading CA file andor directory;
58 if SSL_CTX_set_default_verify_pathsctx = 1 59 int_errorError loading default CA file andor directory;
60 if SSL_CTX_use_certificate_chain_filectx, CERTFILE = 1 61 int_errorError loading certificate from file;
62 if SSL_CTX_use_PrivateKey_filectx, CERTFILE, SSL_FILETYPE_PEM = 1
63 int_errorError loading private key from file; 64 SSL_CTX_set_verifyctx,
SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, 65 verify_callback;
66 SSL_CTX_set_verify_depthctx, 4; 67 SSL_CTX_set_optionsctx, SSL_OP_ALL | SSL_OP_NO_SSLv2 |
68 SSL_OP_SINGLE_DH_USE; 69 SSL_CTX_set_tmp_dh_callbackctx, tmp_dh_callback;
70 if SSL_CTX_set_cipher_listctx, CIPHER_LIST = 1 71 int_errorError setting cipher list no valid ciphers;
72 return ctx; 73 }
The most obvious change to this file is the addition of the functions
init_dhparams
and
tmp_dh_callback
. The initializing function reads the DH parameters from the files dh512.pem and dh1024.pem and loads them into the global parameters. The callback function simply switches
on the required key size and returns either a 512-bit DH parameter set or a 1,024-bit set. This function intentionally does not try to perform any on-the-fly generation of parameters because it is
simply too computationally expensive to be worthwhile.
The only other changes to the server not done to the client, aside from the call on line 60 to set the callback, is the inclusion of the SSL option
SSL_OP_SINGLE_DH_USE
. As discussed earlier, this causes the private part of the DH key exchange to be recomputed for each client connecting.
5.1.4.5 Beyond the example
125
For purposes of clarity in the example code, we have avoided several serious considerations for real applications. The most obvious is error handling. Our examples simply exit if errors of any
kind occur. For most applications, extension of the example to more robustly handle errors is application-specific. While specific functions may return different error codes, OpenSSL functions
and macros will generally return 1 on success; thus, implementing better error handling should be straightforward.
In addition, the examples weve built do two-way authentication. When making a new client and server application, this should always be done. However, when making applications that are meant
to connect with other SSL peers, such as a web server, we should take into account that the stringent security requirements of our example are not always desirable. For instance, to entirely
remove client authentication from a server, we simply need to remove the calls that load the verify locations, the call to set the verify mode, and the call to the post-connection verification routine.
This isnt the best approach, though. When making such compatibility-first applications, we need to try to incorporate as much security as possible. For instance, instead of removing all of the
verification calls, we could still load the verification locations and request a peer certificate with the SSL option
SSL_VERIFY_PEER
. We can, however, omit the
SSL_VERIFY_FAIL_IF_NO_PEER_CERT
option and modify the post-connection verification so that if the client does present a certificate, we go on with high security. If the client does not
present the server with a certificate, the condition and associated information can be logged so that we can keep track of unauthenticated connections.
Another point we avoided was the password callback for the encrypted private key for the certificate. For most server applications, common practice is to leave the private key in a file that
isnt encrypted so that the application can start up and stop without user input. This convention, born of simplicity of implementation, can easily be subverted. When doing something like this, it
is essential that we make sure users on the machine do not have read permission on the private key file; ideally, the file will also be owned by the root or administrator user so that the likelihood of
compromise is further reduced. For most client applications, tying the encryption passphrase to the user should not be a problem.
DSA parameters can be converted to DH parameters. This method is often utilized since the computational power necessary to generate the DSA parameters is smaller. Often, parameters
generated in this fashion are used for ephemeral DH parameters. Without having to get into the mathematics behind the algorithms, the SSL option
SSL_OP_SINGLE_DH_USE
should always be used in these cases. Without it, applications are susceptible to a subtle attack.
A large flaw of our example programs is their handling of IO on SSL connections. The examples rely on blocking IO operations. For most real applications, this is unacceptable. In the following
section, we broach the important topic of non-blocking IO on SSL connections. We have also neglected to consider renegotiations requesting that a handshake be performed during an already
established connection on SSL connections and their impact on IO. While this should occur automatically when the peer requests it, the IO routines must be robust enough to handle its subtle
impacts. In the next section, we begin by addressing server efficiency with respect to session caching and then move into a more in-depth look at IO paradigms.
5.2 Advanced Programming with SSL
OpenSSL provides many more routines than those weve discussed up to this point. In fact, most of the
SSL_CTX
routines have
SSL
counterparts that perform the same function except on an SSL object instead of the context that creates it. Aside from this small point, we will discuss techniques
for caching SSL sessions, using renegotiations, and properly reading and writing on SSL connections—including during renegotiation.