Certificate error: peer not verified;

Certificate error: peer not verified;
Certificate error: peer not verified;

So, you've built your first TAK Server, and you think you have everything configured correctly and then you begin to onboard your first client, and nothing happens. You begin to investigate by looking at the TAK Server log takserver-messaging stored in the /log/tak/logs/ directory and you see the following error:

ERROR c.b.m.n.n.h.NioNettyHandlerBase - NioNettyServerHandler error. Cause: javax.net.ssl.SSLHandshakeException: General OpenSslEngine problem. Additional info: Remote address: 192.168.100.10; Remote port: 56640; Local port: 8089; Certificate error: peer not verified;

If you're unfamiliar with certificates and public key infrastructure (PKI), this one may have you beating your head against the wall. Based on the error we can see that the server was unable to establish a secure connection with our client via the SSL handshake. More information can be found here and here on the SSL handshake process. To understand why our connection failed we must determine who our signing certificate authority is.

Certificate Authorities

In most common deployments, the TAK Server is the certificate authority (CA) for its clients meaning that it signs and issues the client certificates. Since our clients do not inherently trust our TAK Server, we must provide our TAK Server public certificate to initiate the SSL handshake - truststore-<caName>.p12; more on this later. This public certificate is the signing CA for our TAK Server. It also is the signing CA who signed and issued our TAK Server client certificate - takserver.pem.

Signing CA

When building the TAK Server a few commands are issued to build the PKI environment. The makeRootCa.sh is the first command in the process after editing cert-metadata.sh which establishes the self-signed root CA. The public certificate of the TAK Server to be passed to the clients is then truststore-root.p12 which is configured by default in the CoreConfig.xml but in the Java Keystore format (jks). However, when using the makeCert.sh command with the ca option - makeCert.sh ca - this establishes the intermediate CA changing some configurations within our TAK Server. Using this command changes the CA public certificate trust chaining relationship between our client and server. Depending on the sequence used to sign the TAK Server this could get complicated. More on this later.

When using the makeCert.sh ca command the truststoreFile within the CoreConfig.xml is changed from truststore-root.jks to truststore-XXX.jks replacing XXX with the CA common name established in our command. We then pass the truststore-XXX.p12 to our clients to build that trust from our client to the server.

Sequence

Recall that the sequence of signing the TAK Server matters. An example sequence of events should be as follows:

  1. Edit the cert-metadata.sh to create our PKI environment
  2. Execute makeRootCa.sh to establish the self-signed root CA
  3. Execute makeCert.sh ca to establish the intermediate signing CA
  4. Execute makeCert.sh server to request and issue the TAK Server client certificate
  5. Modify the CoreConfig.xml to replace truststore-root.jks to truststore-XXX.jks

If following the sequence above the TAK Server public certificate to be passed to the TAK clients is the truststore-XXX.p12. If passing the truststore-root.p12 to the clients then when the client tries to establish a secure connection to the server the server will:

  1. Present its issued certificate which identifies XXX as the signing CA to the client
  2. The client which was passed the truststore-root.p12 contains the self-signed public root certificate
    1. The client inspects its truststore and is unable to verify who signed the TAK Server and terminates the connection
  3. The server receives a FIN from the client closing the client-to-server connection.

Since the client is unable to verify who signed the server within its own trust a secure connection cannot be established and the connection is closed.

Fix Action

In summary, the fix is to pass the correct public CA to the client. Some simple commands to help in your discovery include:

# View the Java Keystore
keytool -v -list -keystore /opt/tak/certs/files/takserver.jks

# View the PKCS12
openssl pkcs12 -info -in /opt/tak/certs/files/truststore-root.p12

Java Keystore and OpenSSL commands

Example Outputs:

keytool command run against takserver.jks
openssl command run against truststore-TAK-ID-CA-01.p12
openssl command run against truststore-root.p12

In the examples notice who the Owner (takserver) and the Issuer (TAK-ID-CA-01) are, which will identify which public certificate is required to pass to the client.

Conclusion

In summary, this error is very common and the fix is very simple. When getting this error investigate your CoreConfig.xml and the public certificates you pass to your clients to resolve this error. Additionally, inspect the /opt/tak/certs/files directory and if you have truststore-root.p12 and a truststore-XXX.p12 file - pass the truststore-XXX.p12 to your client and it should resolve your issue.