SSL root certificate optional?

The server always sends a chain. As per the TLS standard, the chain may or may not include the root certificate itself; the client does not need that root since it already has it. And, indeed, if the client does not already have the root, then receiving it from the server would not help since a root can be trusted only by virtue of being already there.

What Symantec says is that they recommend not sending the root, only the rest of the chain. This makes sense: since the root is useless for validation purposes, you may as well avoid sending it and save the 1 kB or so of data bandwith per connection.

Anyway:

  • The server's certificate, with its chain, is not for the server. The server has no use for its own certificate. Certificates are always for other people (here, the client). What is used by the server is its private key (that corresponds to the public key in its certificate). In particular, the server does not need to trust its own certificate or any CA which issued it.

  • In TLS, the server is supposed to send a chain; and the client is supposed to somehow use the server's public key for the handshake. The client is free to "know" that public key in any way that it wishes to, although of course it is expected that the client will obtain the server's public key from the certificate chain that the server just sent. Browsers will primarily try to use the chain sent by the server (by trying to link it below one of the roots already trusted by the browser); in case of failure, they will try to build other chains based on intermediate CA certificates that they already know or can download on-the-fly.

    In stand-alone applications, application writers are free to configure or bypass that step in arbitrary ways, which can be useful if the server's public key can be hardcoded in the application code (in which case the chain sent by the server is just completely ignored). Unfortunately, freedom to implement a custom certificate validation step is also freedom to wallop security, stab it to death and then throw its corpse in a ditch. It happens way too often.


what does a browser use to compare against for validation since the server won't be supplying its root cert during the handshake

The whole idea of certificate checking is that the clients has some root certificates it trusts (shipped with the browser or OS) and that it validates the certificate the browser sends against this local trust anchor.

This means, that the server does not need to (and should not) send the root certificate to the client, because this root certificate is supposed to be at the clients end already. If it still sends the root certificate the client will simply discard it, i.e. it will not trust any root certificate send by the server.

Again if this is true what about stand-alone client apps that use SSL libraries? Will this depend on the application since it may have different path building methods to a trusted root vs a browser?

The basic verification process between browsers and SSL libraries is the same. There are some differences in path building in edge cases between openssl and browsers (see http://rt.openssl.org/Ticket/Display.html?id=2732&user=guest&pass=guest) and the verification of the hostname of the target against the name(s) in the servers certificate is often buggy or even non-existing outside the common browsers.


I send the root when it is convenient to do so.

If the client trusts the root, then it makes no difference whether you send it or not.

When the client does not recognize the root, in my experience the MS Windows client produces much less confusing diagnostic messages if the untrusted root was provided in the chain.

As for how it knows what root to use if one is not provided, the next-to-root (which has to be in the provided chain) contains the identifying information for the root, which the client uses to look up the root in the client's store.