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/CN=zymkey-verify.zymbit.com.dev"
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/CN=zymkey-server.zymbit.com.dev"
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/CN=zymkey-client.zymbit.com.dev"
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
[netcat_server]
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:
- Remove the
requireCert
parameter - 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
[netcat_client]
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.