Stunnel support for Zymkey

As explained in OpenSSL: Apache Setup, Generating CSR, Zymkey can participate in the handshake of a mutual authentication (i.e. client side certificate) TLS session. Security is enhanced since the private keys that are used for signing the TLS handshake are contained in the Zymkey and are never exposed to the host.

stunnel is a package which allows a socket based application to transparently send and receive data across an encrypted tunnel. This way, an application writer can write an app which securely sends and receives data between another endpoint (e.g. a server or another Raspberry Pi) without having to know too much about cryptography.

In this example, I’ll show you how to configure stunnel for use with a Raspberry Pi host to make an encrypted chat session using netcat.

Step 1: Install Zymkey

If you have not done so already, install your Zymkey onto your Raspberry Pi per the Getting Started guide.

Step 2: Install stunnel on Your Host

After installing your Zymkey, install the stunnel package:
sudo apt-get install stunnel

Note: if you’re running Ubuntu 16.04, you may need to build stunnel yourself because (as of this writing) the version in the apt repo is too old to accept the requireCert parameter in the server configuration file. More on this later in step 8.

Step 3: Set Up Your Server

We are going to assume that your server environment runs Linux. There are several ways to do this:

  • A PC running native Linux
  • A PC running Windows with Linux running as guest on Virtualbox
  • Another Raspberry Pi

We won’t go into how to install Linux on a PC natively or in a virtual machine. Just make sure that stunnel is installed on the server machine as well.

Step 4: Set Up Your Certificate Authority (CA)

Here, we will set up our own CA rather than send the Certificate Signing Request (CSR) that we’ll be generating from the Host Raspberry Pi to a known CA like Symantec or GoDaddy. For simplicity, we will assume that the server that you configured in Step 3 is also your CA.

On the server, create a directory for the CA and change directory:
mkdir -p ~/stunnel_demo/myCA
cd ~/stunnel_demo/myCA

Next, generate the CA ECDSA key pair:
openssl ecparam -name prime256v1 -genkey -noout -out ca.key

Now generate the CA certificate:
openssl req -x509 -new -SHA256 -nodes -key ca.key -days 3650 -out ca.crt -subj "/C=US/ST=California/L=Santa Barbara/O=Zymkey/"

Step 5: Create Your Server Certificate

On the server, create a directory for the server certificate:
mkdir -p ~/stunnel_demo/myServer
cd ~/stunnel_demo/myServer

Next, generate the server ECDSA key pair:
openssl ecparam -name prime256v1 -genkey -noout -out myServer.key

Generate a server CSR:
openssl req -new -sha256 -key myServer.key -out myServer.csr -subj "/C=US/ST=California/L=Santa Barbara/O=Zymkey/"

Generate the server certificate:
openssl x509 -req -in myServer.csr -CA ~/stunnel_demo/myCA/ca.crt -CAkey ~/stunnel_demo/myCA/ca.key -CAcreateserial -days 3650 -out myServer.crt

Step 6: Create the Client Certificate on the Host Raspberry Pi

On the Host Raspberry Pi, create the CSR using a public key on the Zymkey. We’ll be using one of Zymkey’s public keys via the Zymkey OpenSSL engine. Because OpenSSL expects a private key, we’ll be “faking out” the private key file with an empty file called bogus.key:
mkdir -p ~/stunnel_demo/myClient
cd ~/stunnel_demo/myClient
touch bogus.key
openssl req -key bogus.key -new -out myClientCert.csr -engine zymkey_ssl -keyform e -subj "/C=US/ST=California/L=Santa Barbara/O=Zymkey/"

As you can see in the last command, we’re telling OpenSSL to use a hardware engine called zymkey_ssl and that the key format is an engine with -keyform e.

Next, we’ll copy myClientCert.csr to the server with scp:
scp myClientCert.csr <server username>@<server hostname>:/home/<server username>/stunnel_demo/myCA

Be sure to substitute <server username> and <server hostname> with your username on the server as well as the server’s hostname or ip address.

Step 7: Generate the Client Certificate

On the server/CA machine, cd to the myCA directory and tell OpenSSL to generate a certificate from the client CSR:
openssl x509 -req -in myClientCert.csr -CA ca.crt -CAkey ca.key -CAcreateserial -days 3650 -out myClientCert.crt

Now copy the client certificate back to the client:
scp myClientCert.crt pi@raspberrypi:/home/pi/stunnel_demo/myClient

Step 8: Create the stunnel Configuration Files

On the server/CA machine, create a file in the ~/stunnel_demo/myServer directory called nc_stunnel_server.conf:

debug = 7
output = /tmp/stunnel.log

client = no
cert = myServer.crt
key = myServer.key

accept = 4444
connect = 7777
requireCert = yes
CAfile = ../myCA/myClientCert.crt

When stunnel is started on the server machine, it will look for connections from stunnel on the client side at port 4444 and will connect to port 7777 from the application, in this case netcat. We’ve also configured the server side stunnel to require the client to provide a certificate.

As mentioned previously, if you get an error when trying to start stunnel on the server related to requireCert=yes, you can do one of two things:

  1. Remove the requireCert parameter
  2. Build stunnel on the server yourself from version 5.24 or later.

Next, create a file called nc_stunnel_client.conf on the Raspberry Pi client:

debug = 7
output = /tmp/stunnel.log

client = yes

engine = zymkey_ssl
engineDefault = EC

cert = myClientCert.crt
engineId = zymkey_ssl
connect = <server ip addr>:4444
accept = 5555

Here, we’ve configured stunnel on the client side to use a hardware engine plugin called zymkey_ssl that will be used for EC or Elliptical Curve cryptography. Be sure to change to the ip address of your server.

Step 9: Start stunnel and netcat on the Server

cd ~/stunnel_demo/myServer
sudo stunnel nc_stunnel_server.conf
nc -lv 7777

Step 10: Start stunnel and netcat on the Client

cd ~/stunnel_demo/myClient
sudo stunnel nc_stunnel_client.conf
nc localhost 5555

You should now be able to type characters on the server and see it show up client window after the Enter key is pressed and vice-versa.