# Howto install a private CA certificate?



## Henning Kessler (Aug 19, 2020)

Hello,

is there somewhere a working howto that shows how to add a private CA (2 intermediate certs and one root cert) to FreeBSD 11.3? I found this one (https://blog.socruel.nu/freebsd/how-to-install-private-CA-on-freebsd.html) but I can't make it to work. Testing the CA file directly works:

```
openssl s_client -connect host:443 -CAfile ca.pem
...
 Verify return code: 0 (ok)
```

Any help would be great

Regards

Henning


----------



## olli@ (Aug 19, 2020)

It depends on what you want to do with the certificate. This has very little to do with FreeBSD itself.

For example, if you want to use it for a web server, you have to install it in your web server’s configuration. Consult your web server’s documentation for that. In the case of Apache httpd, you usually store them in /usr/local/etc/apache*/ssl, and you might have to make small changes to a configuration file.

If you want to make the certificate known to your web browser, then it depends on the browser. For example, in Chrome open the settings page and go to the “Privacy and security” section, then select the “Manage certificates” entry.

To make the certificate available to OpenSSL-based applications, put it in /etc/ssl/certs.


----------



## Henning Kessler (Aug 19, 2020)

Hi olli,
my intention was to make all OpenSSL-based applications  trust the certificates which has been and will be signed by those CA certificates. I can verify the certificate chain by using `openssl s_client -connect` with the `-CAfile` option but when I put that file into /etc/ssl/certs and run the same command without the option the return code changes from 0 (ok) to 21 (21 (unable to verify the first certificate).


----------



## rotor (Aug 20, 2020)

Henning Kessler said:


> Hi olli,
> my intention was to make all OpenSSL-based applications  trust the certificates which has been and will be signed by those CA certificates.



Here is what I do.  I am not sure it is the solution you need, but it may help you look in a specific direction...

I have created my personal CA.

I want the apps on the server, e.g., Postfix, NGINX, to use the certs signed by my CA.

I install the pkg:

   ca_root_nss-3.55      ---          Root certificate bundle from the Mozilla Project

I then append my CA's public cert to that cert bundle file.

The applications that need to use certs all are configured to point to that master bundle file with my CA's cert in it.

That's a high level overview (definitely not a how-to) of what I do.  It has worked for me for a while.


----------



## ondra_knezour (Aug 20, 2020)

Don't care about any intermediate certificates, those are verified by the chain of trust starting with given CA root certificate. 

So you have to inform OpenSSL, that you want to add given root certificate to your trusted ones. Here you have two ways to do that. Either put all root certificates into one file and use `-CAfile` option, this is how ca_root_nss works. But you have to manually update this file each time with your addition, when Mozilla update their bundle, if you use it. Or you can use `-CApath` option, where you specify directory, where to look for trusted root certificates. Those are looked up by hash, so it is not sufficient to put only some files there, you have to rename them accordingly or create symlinks, that is the 4th part in tutorial you linked, which deals with the hashing.

Now you have your trusted root certificate(s) stored and it works, as you can try with the `openssl s_client` command. However OpenSSL by default doesn't trust to anything, unless explicitly said to. Here depends on any and all application you want to trust your private CA, because it has to say OpenSSL library what it want to be trusted.


Henning Kessler said:


> [...]but when I put that file into /etc/ssl/certs and run the same command without the option the return code changes from 0 (ok) to 21 (21 (unable to verify the first certificate).


I would guess you did not specify the `-CApath` option and did not name certificate file with correct hash either, so it would not work.

And finally, you can also try to set `SSL_CERT_FILE` and/or `SSL_CERT_DIR` environment variables to see if it helps in your case.


----------



## Henning Kessler (Aug 20, 2020)

Hi there,

thanks for all your help. Adding the certs to /usr/local/share/certs/ca-root-nss.crt did work, but re-adding them every time the package gets updated is not so great.

Is there way to set `-CApath` option as default in a .conf file? And how can the ca-root-nss then be. added as well?

Henning


----------



## ondra_knezour (Aug 20, 2020)

AFAIK, this depends on actual program you want to trust some root CA. My understanding is, that such program calls openssl library with request like "please verify this certificate for me, while trusting CAs in this CAfile/CApath" and form of configuring those roots of trust depends on given program. 

However it looks like at least `openssl s_client` should try use default locations, but long outstanding bug prevented it, if no -CA... option was used, see for example this question.

And for me it really looks like it is working as you expect.

FreeBSD 11.3
	
	



```
# freebsd-version
11.3-RELEASE-p5
# openssl version -a
OpenSSL 1.0.2s-freebsd  28 May 2019
built on: date not available
platform: FreeBSD-amd64
options:  bn(64,64) rc4(16x,int) des(idx,cisc,16,int) idea(int) blowfish(idx)
compiler: clang
OPENSSLDIR: "/etc/ssl"
```
None SSL environmental variables are set, command `# env | grep -i ssl` has empty output, [pkg]ca_root_nss[/pkg] version 3.48 is installed and at least `s_client` looks working witout any CA command line option


```
# openssl s_client -quiet -connect gmail.com:443
depth=2 OU = GlobalSign Root CA - R2, O = GlobalSign, CN = GlobalSign
verify return:1
depth=1 C = US, O = Google Trust Services, CN = GTS CA 1O1
verify return:1
depth=0 C = US, ST = California, L = Mountain View, O = Google LLC, CN = mail.google.com
verify return:1
read:errno=0
```

So my guess is you did not hash your certificate properly, see example in your example  Get it working with `s_client` in same manner with /etc/ssl/certs directory to avoid manual file updating each time you update ca_root_nss package and then experiment with your target program.


----------



## Henning Kessler (Aug 20, 2020)

mmh now this is strange or better embarrassing for me ;-). I deleted the CAs from the bundle file and created the hashs from the CA files with `sudo openssl x509 -noout -hash -in CA.pem` created the symbolic links `ln -s CA.pem HASH-FROM-CMD-BEFORE.0` in /etc/ssl/certs and it works now....

So sorry stealing all your time

Regards

Henning


----------



## ljboiler (Aug 20, 2020)

`openssl rehash <folder containing certificates>` should do the equivalent of the two commands above.  Unfortunately, the man page for this gets tromped by the shell builtins rehash() one.


----------



## Henning Kessler (Aug 20, 2020)

Just tried that command but in my 11.3 jail I get this response

```
openssl:Error: 'rehash' is an invalid command.
```
it looks like the rehash option comes with 12.0


----------



## olli@ (Aug 20, 2020)

ljboiler said:


> `openssl rehash <folder containing certificates>` should do the equivalent of the two commands above.  Unfortunately, the man page for this gets tromped by the shell builtins rehash() one.


When you have OpenSSL installed from ports, you can access that manual page as openssl-rehash(1) (the web link here doesn’t work; I’m not sure why).


----------



## seregasoft (Oct 3, 2022)

Found simple way: https://www.linuxpedia.pl/articles/freebsd-certs/

1. Copy certificate to /usr/local/etc/ssl/certs (create if necessary).
2. Run certctl rehash - it will put it in all the places necessary and update respective databases/links.


----------

