Certificate verification Step 2: Peer Authentication

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

Certificate verification entails checking the cryptographic signatures on a certificate to be sure an entity we trust has signed that certificate. It also involves checking the certificates notBefore 109 and notAfter dates, trust settings, purpose, and revocation status. Verification of a certificate takes place during the SSL handshake during the call to SSL_connect or SSL_accept , depending on whether the SSL object is a client or a server. Once weve properly loaded trusted certificates into the SSL_CTX object, OpenSSL has a built-in function to verify the peers certificate chain automatically. The routine used to verify the certificate chain could be changed from the default via a call to SSL_CTX_set_cert_verify_callback , but under almost all circumstances, this is undesirable since the default routine for signature verification is amply complete and robust. Instead, the developer can specify a different callback that filters the return status of the default verification and returns the new verification status. The function to perform this task is SSL_CTX_set_verify . Aside from assigning a filter verify callback, this functions primary purpose is to assign the type of verification our SSL_CTX objects connections will perform. More accurately, we can use it to control how certificates and requests are handled during a handshake. The second argument to this function is a set of flags that determine this. Four flags are defined with names that can be combined with a logical OR operation. Depending on whether the context is being used in client mode or server mode, these flags can have different meanings. SSL_VERIFY_NONE When the context is being used in server mode, no request for a certificate will be sent to the client, and the client should not send a certificate. When the context is being used in client mode, any certificate received from the server will be verified, but failure will not terminate the handshake. Do not combine this flag with any others; the others will take precedence over this one. This flag should only be used by itself. SSL_VERIFY_PEER When the context is being used in server mode, a request for a certificate will be sent to the client. The client may opt to ignore the request, but if a certificate is sent back, it will be verified. If the verification fails, the handshake will be terminated immediately. When the context is being used in client mode, if the server sends a certificate, it will be verified. If the verification fails, the handshake will be terminated immediately. The only time that a server would not send a certificate is when an anonymous cipher is in use. Anonymous ciphers are disabled by default. Any other flags combined with this one in client mode are ignored. SSL_VERIFY_FAIL_IF_NO_PEER_CERT If the context is not being used in server mode or if SSL_VERIFY_PEER is not set, this flag is ignored. Use of this flag will cause the handshake to terminate immediately if no certificate is provided by the client. SSL_VERIFY_CLIENT_ONCE If the context is not being used in server mode or if SSL_VERIFY_PEER is not set, this flag is ignored. Use of this flag will prevent the server from requesting a certificate from the client in the case of a renegotiation. A certificate will still be requested during the initial handshake. The third argument to SSL_CTX_set_verify is a pointer to the verification filter callback. Since the internal verification routine is called for each level of the peer certificate chain, our filter TE AM FL Y Team-Fly ® 110 routine will be called just after each step. This functions first argument is nonzero if the verification succeeded, and zero otherwise. The second argument is an X509_STORE_CTX object. This type of object contains the information necessary to verify a certificate. The object holds the current certificate being verified and the verification result. The return value from the function should be either zero or nonzero to indicate whether the certificate should be considered valid or not. As in most of the callbacks used with OpenSSL, there is a default supplied that simply returns the value of the first argument. When implementing our own version of this function, we need to maintain this behavior. If we return nonzero when the first parameter is actually zero, an unverified client certificate will be accepted as a verified one. Likewise, the reverse would cause a valid certificate to fail verification. At this point, it may seem as if there is no real purpose to implementing our own version, but this isnt accurate. The reason we should supply our own is so that more detailed information about the results of verification can be obtained, especially when verification fails. For instance, if a peer presents an expired certificate and we do not implement a verify callback to check status, then we find out only that the call to SSL_connect or SSL_accept failed because of handshake failure. Example 5-7 shows an implementation for this callback that we will use in our example applications. To use it in our examples, it should be implemented in common.c and prototyped in common.h. Example 5-7. A verify callback implemented in common.c and prototyped in common.h int verify_callbackint ok, X509_STORE_CTX store { char data[256]; if ok { X509 cert = X509_STORE_CTX_get_current_certstore; int depth = X509_STORE_CTX_get_error_depthstore; int err = X509_STORE_CTX_get_errorstore; fprintfstderr, -Error with certificate at depth: i\n, depth; X509_NAME_onelineX509_get_issuer_namecert, data, 256; fprintfstderr, issuer = s\n, data; X509_NAME_onelineX509_get_subject_namecert, data, 256; fprintfstderr, subject = s\n, data; fprintfstderr, err i:s\n, err, X509_verify_cert_error_stringerr; } return ok; } This callback employs several functions from the X509 family of functions to report the detailed error information. The call to SSL_CTX_set_verify is done before any SSL objects are created from the context. We should also make a call to SSL_CTX_set_verify_depth . This function sets the maximum allowable depth for peer certificates. In other words, it limits the number of certificates that we are willing to verify in order to ensure the chain is trusted. For example, if the depth was set to four and six certificates are present in the chain to reach the trusted certificate, the verification would fail because the required depth would be too great. For nearly all applications, the default depth of nine is more than high enough to ensure that the peer certificate will not fail due to too large of a certificate chain. On the other hand, if we know that our application will be used only with peers 111 presenting certificates of some smaller chain length, it is a good idea to set the value to exclude certificates composed of longer chains from being verified successfully. Setting the depth to zero allows chains of unlimited length to be used. There is a known security vulnerability in SSL_CTX_set_verify_depth in versions of OpenSSL prior to 0.9.6. The problem stemmed from the fact that the internal verification routine did not properly check extensions on peer certificate chains; it approved certificate chains that contained non-CA certificates as long as they led to a trusted root CA. Thus, using any verification depth greater than one left the application susceptible to attack from anyone signed by the trusted root CA. Since this problem has been fixed in newer versions of OpenSSL by checking the X509v3 fields regarding CA authorization, this vulnerability should be of only academic interest.

5.1.3.4 Incorporating certificate revocation lists