Background Incorporating trusted certificates

107 In the do_server_loop function, we use a call to SSL_get_shutdown to check into the error status of the SSL object. This essentially allows us to differentiate normal client terminations from actual errors. If the SSL_RECEIVED_SHUTDOWN flag is set, we know the session hasnt had an error and its safe to cache. In other words, we can call SSL_shutdown rather than simply clear the connection. The remainder of the modifications to the server program parallel those made to the client. In summary, weve taken our applications and built them to the point of creating the objects necessary for SSL connections. Each application does provide its certificate data to the peers to which it connects, but they do not verify the certificates they receive. We will build further in the next step and learn how to validate peer certificates.

5.1.3 Step 2: Peer Authentication

The security of an SSL-enabled program is compromised by failure to verify peer certificates properly. In this step, well look into the various API calls that deal with trusted certificates, certificate chain verification, CRL usage, and post-connection verification.

5.1.3.1 Background

Certificate verification can often be confusing, so well discuss the theory before delving into the details. As we already know, a certificate is a set of credentials that has been cryptographically signed by a CA. Each certificate, including a CA certificate, contains a public key with a private key counterpart held in secret by the certificate owner. Moving forward, the process of signing a certificate involves using the private key of a CA to sign the public key in the new certificate. Thus, it should be clear that the process of verification will involve using the public key in a CA certificate to verify the signature on a certificate. Aside from using a CA to create an entity certificate, a CA may also sign a certificate and give it permissions, via X.509v3 extensions, to act as a CA itself. Generally, this procedure allows for a CA to permit another certificate to act as a CA for a specialized purpose. Through this mechanism, we become aware of certificate hierarchies, i.e., a certificate tree. Understanding this, we can see that a single entity certificate may have a list of signing certificates leading up to the original, self- signed root certificate. This list of certificates, each signed by the next, is called a certificate chain. Jumping back to a simple example of a root CA signing a single entity certificate, any party may verify the entity certificate by checking the signature on it, presuming it trusts the root CA. The process of validating an entity certificate is that simple. Extending this to a certificate chain, we must validate each subsequent signature in the list until we reach a trusted CA certificate or until we reach the end of the list. If we hit a CA we trust and the signatures are all valid, our entity certificate is verified; if we find an invalid signature or reach the end of the chain without reaching a trusted certificate, the entity certificate is not verified.

5.1.3.2 Incorporating trusted certificates

As we previously discussed, verifying a certificates authenticity requires that the verifying agent have a list of CAs that it trusts. Therefore, we must provide our application with such a list in order for it to verify the peer. We will start our discussion of peer verification by first concentrating on accomplishing this task. Loading trusted CA certificates into our application is manifested as additional setup to the SSL_CTX object. The function SSL_CTX_load_verify_locations performs this task. This function will load certificates from files, directories, or both. int SSL_CTX_load_verify_locationsSSL_CTX ctx, const char CAfile, 108 const char CApath; ctx The SSL context object that trusted CA certificates will be loaded into. CAfile The name of a file containing CA certificates in PEM format. More than one CA certificate may be present in the file. CApath The name of a directory containing CA certificates. Each file in the directory must contain only a single CA certificate, and the files must be named by the subject names hash and an extension of .0. We can call SSL_CTX_load_verify_locations with either the second or the third arguments specified as NULL , but not both. The behavior of this function is to perform the loading for the non- NULL arguments. An important difference between file and directory storage is the time when the certificates get loaded. With a flat file, the file is parsed and certificates loaded during the call to SSL_CTX_load_verify_locations . However, with a directory, certificates are read only when needed, i.e., during the verification phase that occurs during the SSL handshake. OpenSSL also has default CA certificate locations. When building the library, these paths are hardcoded into the library based on the parameters that are used to build it. In general, there is an OpenSSL directory commonly usrlocalopenssl on Unix systems. The default certificate file is named cert.pem, and it lives in this OpenSSL directory. Likewise, the default certificate directory is named certs, and it too lives in the OpenSSL directory. These default locations provide a convenient place to store system-wide CA certificates that all of the OpenSSL-based applications running on the machine require. Using the default files, we will not need to keep separate copies of common certificates for each application. The function SSL_CTX_set_default_verify_paths loads these default locations into our SSL_CTX object. For calls to this function, the same rules for determining when the CA certificates actually get loaded apply as with a call to SSL_CTX_load_verify_locations . When we load a certificate location into an SSL_CTX object, we are making the statement that we trust those certificates. It is important to understand that if our application runs on a multiuser system, any user with permissions to write to the certificate locations that we load can subvert the security of our application. This is especially important when electing to load the default verify locations. For instance, if our application loads these defaults, a user with the correct permissions could slip in a new CA certificate, thus connecting our application with peers presenting certificates signed by this rogue CA certificate. Using these two functions, we can load trusted CA certificates into our SSL_CTX . Even though they are loaded, the certificates are still not used to verify the peer. We will explore the details of enabling this in the next section.

5.1.3.3 Certificate verification