0

I'm trying to work with OpenSSL C API, I'm relatively new to all this still, and I find a lot of mixed information out there, so I think it's wise to ask for ideas/opinions/clarification.

Anyway, the client program requires a certificate or directory to be loaded which contains a "TrustStore". Is this just another meaning for the server's CA certificate itself in the case I'm creating my own SSL certificates for said server?

And if so, will the intermediate CA work for this purpose in replacement of root CA?

I think I'm on the right track. However, I just wanted some clarification so as to prevent myself making some real daft mistake, as I've heard some conflicting information in regards to this. Some say the client needs the root CA itself; other sources say they only install intermediate CA for security reasons, which seems logical.

I'm generally a little confused as to how the chain of trust works in regards to a client connection though. I've actually only ever needed to generate a CSR and install a certificate on the web server, so the client side stuff is kinda new to me.

This question was originally asked here on Stack Overflow, it was suggested that I ask the info-sec community.

  • 1
    I think you are using the wrong phrase: a [self-signed certificate](https://en.wikipedia.org/wiki/Self-signed_certificate) is a certificate where the issuer certificate is the certificate itself. You probably mean a certificate which is signed by your own CA instead. In this case: the root CA is usually put into the trust store and the intermediate certificate signed by the root CA and the leaf certificate signed by the intermediate certificate are sent during the TLS handshake. – Steffen Ullrich Mar 17 '17 at 08:43
  • 3
    Possible duplicate of [How does SSL/TLS PKI work?](https://security.stackexchange.com/questions/87564/how-does-ssl-tls-pki-work) – Stephane Mar 17 '17 at 08:51

2 Answers2

1

tl;dr If the cert contains some variation of CA:TRUE, it makes sense to distribute it, if it does not, then there is no benefit to distributing it.

The chain of trust itself can be explained in terms of the certificate structure.

If we start from your server's cert (i.e. the cert you would typically use for apache):

  • you server cert is generated by a certificate authority, based on a CSR you provide. That CSR contains your public key, and some other information the CA may or may not be interested in using.
  • the CA receives your CSR, and (generally), will create a signed certificate using an intermediate CA. Your certificate will have two public keys: one for the subject (which is the public key extracted from your CSR), and one for the issuing party, which is the CA's intermediate certificate.
  • the CA's intermediate certificate is itself a signed certificate (with some special options), where the subject key will be the intermediate CA's public key (which is the same public key as is found in the Issuer Public Key of your server certificate). The signing (or issuing) key will be the CA's root certificate (alternatively, it will be another intermediate).
  • the CA's root certificate is (generally) a self-signed certificate. In practice, this means that the Issuer and Subject keys are the same public key.

You can see this by checking certificates in the wild, e.g.:

$ openssl s_client -connect google.com:443 < /dev/null
CONNECTED(00000003)
depth=2 C = US, O = GeoTrust Inc., CN = GeoTrust Global CA
verify return:1
depth=1 C = US, O = Google Inc, CN = Google Internet Authority G2
verify return:1
depth=0 C = US, ST = California, L = Mountain View, O = Google Inc, CN = *.google.com
verify return:1
---
Certificate chain
 0 s:/C=US/ST=California/L=Mountain View/O=Google Inc/CN=*.google.com
   i:/C=US/O=Google Inc/CN=Google Internet Authority G2
 1 s:/C=US/O=Google Inc/CN=Google Internet Authority G2
   i:/C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
 2 s:/C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
   i:/C=US/O=Equifax/OU=Equifax Secure Certificate Authority

The chain of trust this builds can be summarised as (I am starting from the 'bottom' - the Equifax cert):

  • the root CA (Equifax) delegates day-to-day activities to an intermediate CA (GeoTrust) and signs a certificate representing this fact (i.e setting CA:TRUE, KeyUsage: keyCertSign). In other words, the root CA 'trusts' the intermediate to issue certificates on its behalf (hopefully after completing a series of mandatory validation steps).
  • in this chain, the intermediate (Geotrust) has further delegated to a Google CA (CN=Google Internet Authority G2).
  • the delegate (a.k.a the Google intermediate CA) then signs a CSR, which effectively is a document stating that for a given set of names (the CN, and possibly Subject Alternative Names), a private/public key pair is valid/trusted (the trust here coming from the fact they have validated the claim to speak for a given name - in this case, the Google CA has issued a certificate for *.google.com).

Note that (root) CAs are generally self-signed - a CA is trusted generally because it abides by a set of processes and procedures that are felt to ensure it does not issue certificates to people who should not have them. Which is why I can't go out and get myself a certificate saying I am google. This is therefore a convention of sorts (albeit one backed by formal mechanisms), and if you start your own CA, distributing its root (and intermediate) certificates achieves exactly the same thing as distributing the certs of other CAs does: it makes certificates issued by that CA be accepted as valid (i.e. trustworthy) by the system.

In more practical terms, the trust store (for openSSL) is pretty much a bunch of files with a specific naming convention. See https://www.openssl.org/docs/faq.html#USER5:

When a certificate is verified its root CA must be "trusted" by OpenSSL this typically means that the CA certificate must be placed in a directory or file and the relevant program configured to read it

That directory is /etc/ssl/certs (there are others, such as /etc/pki on RH-likes).

https://superuser.com/questions/437330/how-do-you-add-a-certificate-authority-ca-to-ubuntu#719047 provides some further overview of how one adds a certificate to the store, as does https://askubuntu.com/questions/73287/how-do-i-install-a-root-certificate,

The short version is that update-ca-certificates automates the process, and is the commonly used tool.

The slightly longer version is that certificates need to be stored by hash (e.g. in files named based on the output of openssl x509 -hash -in cert.pem), so that openSSL can efficiently validate chains.

See https://www.openssl.org/docs/man1.0.2/apps/c_rehash.html for some additional background.

updated to respond to the questions in comments:

The server certificate, in this discussion, is defined as trusted or not based on its chain of trust. If you think about how (e.g.) curl https://google.com works, it is a bit easier to understand:

  • curl opens a TLS connection to google, which returns a certificate.
  • curl looks at that 'end-user' certificate - i.e. the server's certificate, and looks specifically for the issuer.
  • if the issuer is 'known' in the trust store, the remainder of the trust chain is validated (i.e. the server certificate issuer's certificate is checked, and if it has an issuer other than itself, that issuer is checked, etc). Only if the full trust chain can be validated is the certificate considered valid.

However, it would absolutely impractical to distribute trust chains if end-user certificates needed to be included. I don't have any numbers on how many websites are out there, but based on the fact Alexa provide a top 1M, you would assume it is more than 1 million.

Which is sort of the point of a chain of trust: you generally need to have the issuer certificates around, but you do not need the end certificates to be distributed, because they tell you who the issuer is.

And you can verify they aren't lying, because you can check the issuers public key (and the chain of trust that establishes it is the proper key), and validate whether the end-user (i.e. server) certificate was really signed by the private counterpart of the issuer's public key.

So no, you should not distribute the end-user certs, but only the chain of trust - or, in simpler terms: distribute all the certs you generate where the BasicConstraints (legitimately) say something at least CA:TRUE. Do not distribute anything that does not meet that condition, because it is a waste of your time and disk space - everything that does not say CA:TRUE can be validated against something that does.

iwaseatenbyagrue
  • 3,631
  • 1
  • 13
  • 24
  • So does that mean in any case, the client needs access to the root CA cert , or just the CA cert of which the server certificate was signed by? Or am i still completely missing some point? – Michael Strobel Mar 17 '17 at 09:44
  • In order to verify the server certificate, the client(s) would need access to the full trust chain for that cert. Otherwise, the client will either consider the cert invalid, or ask the user to accept it. In your case, it seems somewhat likely you would not be setting up a distribution point for your CA/CRLs, so the simplest way is to ensure your certs are in /etc/ssl/certs on client machines. tl;dr: a certificate is a limited use in establishing trust if you can't establish its chain of trust. And you need to validate the full chain to establish that. So make the whole trust chain available – iwaseatenbyagrue Mar 17 '17 at 09:47
  • Does that mean if there is a root CA, an intermediate CA and the signed certificate on the server, All three of these certificates need to be available to the client within the `/etc/ssl/certs` directory? As these all contain the public keys? – Michael Strobel Mar 17 '17 at 09:50
0

A self-signed certificate is exactly that: it is signed my itself (it is its own trust anchor).

Therefore, in order to be trusted, it needs to be manually and explicitly placed in the application's trusted anchors list. How that is done depends on the OS and application.

For instance, if you are using Windows's internal certificate storage, then you need to place that self-signed certificate in the "trusted root certificate authority" store or the cert will not be accepted. OpenSSL uses a different, application-specific storage system: you will need to install the certificate as a trusted CA as well but how to do so depends widely on exactly what application and OS you're using (see this article for some generic instructions).

Stephane
  • 18,607
  • 3
  • 62
  • 70
  • So does this mean the "Trust Store" certificate is just the same as the one installed into apache, for example? That's the part that is most confusing, i'm a `GNU/Linux` user, the directory of which i needed to link to in the client application, was `/etc/ssl/certs`. However i was unable to find a clear explanation of what exactly the process is on that side of things. At least you understand my question here, the main point behind it is to write the client and have it trust the server it is connecting to. – Michael Strobel Mar 17 '17 at 08:45
  • What i'm trying to do exactly is create a CA, and i guess the certificate is signed by the CA (intermediate) , so in that case, does this mean the CA is the trust anchor, therefore the intermediate Ca should be installed in the trusted certificates directory? Thanks for responding. – Michael Strobel Mar 17 '17 at 08:48
  • Your question therefore is more general. I've proposed to close it with a link to the answer you seek. – Stephane Mar 17 '17 at 08:52