In the rapidly evolving world of embedded systems, security has become a paramount concern. With the increasing connectivity of devices in the Internet of Things (IoT) and other embedded applications, protecting data and ensuring secure communications are critical. To do this, we need to be able to create keys and certificates, as well as validate embedded devices.
OpenSSL is the ideal tool for this job. It’s a robust, full-featured open-source toolkit that’s easy to use and broadly supported. This article explores how OpenSSL can be utilized to help secure embedded systems to enhance security.
Note that we’re not going to use OpenSSL on the device itself, unless you’re running Linux and can install the OpenSSL package.
What is OpenSSL?
OpenSSL is a software library that provides cryptographic functionalities to facilitate secure communication over networks. It implements various cryptographic algorithms and protocols, primarily SSL and TLS, which are standards for securing network communications.
Why Choose OpenSSL for Embedded Systems?
- Wide Adoption: OpenSSL is widely used and trusted, making it a reliable choice for developing systems. Several versions of OpenSSL are FIPS140-2 validated as well
- Flexibility and Customizability: It offers a high degree of flexibility, allowing developers to configure it for specific needs of an embedded environment, such as reducing memory footprint or optimizing for speed.
- Strong Cryptographic Features: OpenSSL supports a wide range of cryptographic algorithms, which is crucial for building robust embedded security systems.
OpenSSL Version
Using the right version of OpenSSL is critical, and there’s essentially two different versions:
- OpenSSL 3.x: This is the latest major version series of OpenSSL. It includes significant updates and improvements over the 1.x series.
- OpenSSL 1.1.1: This is an older major version series but still widely used but no longer maintained. It is known for its stability and has been the default choice for many applications in the past.
OpenSSL 1.1.1 was a Long Term Support (LTS) release that has today reached its End of Life (EOL). Therefore, any work should be done with OpenSSL 3.x and above.
Installing OpenSSL
OpenSSL is available natively in Linux and macOS systems. For Ubuntu and Debian-based systems it can be installed with the apt package manager:
$ sudo apt install openssl
For macOS, we can use brew to install or update openssl
$ brew install openssl
or
$brew upgrade openssl
For Windows, the easiest way to install OpenSSL is to use Cygwin. Install Cygwin and select the opessl package and install it. You can download Cygwin here.
Using OpenSSL
Now that we have OpenSSL in place on the platform of your choice, let’s use it to build a simple Public Key Infrastructure (PKI) of a Root System and a Device.
Generating a Root Key
The first step in generating a custom Public Key Infrastructure is to create a Root Certificate. All certificates will be derived from this certificate.
$openssl genrsa -out rootCA.key 2048
This command creates a 2048-bit RSA private key and saves it in a file named rootCA.key
. You can choose a stronger key (like 4096 bits) for enhanced security or use a different algorithm such as Elliptical Curve cryptography
The Root CA key is probably the most sensitive piece of information you will generate. This key is what allows verification, and signing of certificates. If it is exposed, then the PKI is no longer useful. Because of this, this key is usually contained withing a very secure device such as an Hardware Security Module (HSM). Sophisticated PKI will have the Root CA offline and use intermediate CAs for issuing device certificates.
Securing this key and creating a real PKI is outside the scope of this guide, but you definitively should consider this.
Creating the Root Certificate
With the key present, we can generate the Root Certificate:
$ openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 1024 -out rootCA.pem
Here’s what this command does:
req
: This command specifies that you want to use X.509 certificate signing request (CSR) management.-x509
: This tells OpenSSL to create a self-signed certificate.-new
: Generates a new certificate.-nodes
: Skips the option to secure the certificate with a passphrase. Security-wise, it is advisable to include a passphrase, but it can complicate automated use of the certificate.-key
: Specifies the private key to use.-sha256
: Uses the SHA-256 hash algorithm.-days
: Defines the validity period of the certificate (in this example, 1024 days).-out
: Specifies the filename to write the certificate to (rootCA.pem
).
When you execute this command, OpenSSL will prompt you to enter details for the certificate, such as country name, organization, and common name (CN). The CN is especially important as it is the name that identifies this CA. For a root CA, this could be something like “My Root CA”.
Verifying the Root Certificate
To verify the root certificate, use:
$ openssl x509 -in rootCA.pem -text -noout
This command will display the details of the generated certificate. Make sure that all the information is correct.
The Root certificate will need to be installed on devices that need to verify certificates and does not need to be secured (except to make sure that it is not modified and used properly).
Generating a Device Certificate
With the Root Certificate in place, we can now create certificate for individual devices. The devices can use these certificates to authenticate themselves or authenticate another device. Before this we need the items we generated in the previous sections:
- Root CA Certificate: Your root certificate (e.g.,
rootCA.pem
). - Root CA Private Key: The private key for your root CA (e.g.,
rootCA.key
).
Generate a Private Key for the Device
The device needs its own keys and certificate. We first have to start with creating keys. How to generate these keys depends. They can be created using OpenSSL during manufacturing and installed in the devices, or they can even be generated internally in the devices, which prevents exposing the sensitive private key which, just like the root key, should never be exposed.
To generate a new private key for a device, we can use OpenSSL as follows
$ openssl genrsa -out device_private.key 2048
This creates a 2048-bit RSA private key and saves it in a file named device_private.key
.
Creating the device Certificate Signing Request
We can’t just create a certificate. The device’s certificate has to be signed by the Root Certificate (or in a sophisticated PKI, by an issuing CA). To do this, we have to request that the Root authority sign our certificate. This is the Certificate Signing Request (CSR). To create a CSR:
$ openssl req -new -key device_private.key -out newcert.csr
You may be familiar with CSRs from installing SSL certificates in webservers. You will be prompted to enter details for the certificate, such as the country name, organization, common name, etc. The common name should be the name of the device for which you are generating the certificate.
Signing the CSR with the Root CA
Now that we have the CSR, we can use the Root CA certificate (and private key) to sign the device’s certificate
$ openssl x509 -req -in newcert.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out device.crt -days 365 -sha256
Here’s what this command does:
-req
: Indicates that this is a CSR.-in
: The input CSR file.-CA
: The root CA certificate file.-CAkey
: The private key of the root CA.-CAcreateserial
: Creates a serial number file if it doesn’t exist.-out
: The output file for the new certificate.-days
: The number of days until the certificate expires.-sha256
: Specifies the use of the SHA-256 hash algorithm.
After this command, you will have the device certificate as well.
Verifying the Device Certificate
To ensure that your certificate has been correctly signed by your root CA, you can verify it:
$ openssl verify -CAfile rootCA.pem device.crt
Conclusion
OpenSSL provides a powerful toolkit for implementing security. Its capabilities and the fact it’s a de facto industry standard make it essential in working to secure devices.
FAQ
Should I use OpenSSL in my embedded device?
Even though OpenSSL works in countless of embedded Linux systems, it’s too large and complicated for small embedded systems for which Bluetooth and Wireless are usually used. These devices typically run a small ARM Cortex-M4 and similar. For these systems, smaller security libraries like Mbed-TLS and others work better.
But even here, OpenSSL is used for the rest of the system such as manufacturing, development, testing, etc.
What cryptographic algorithms should I choose?
Even though by default, OpenSSL and other libraries use RSA, there are advantages to using Elliptic Curve Cryptography (ECC). For one, ECC keys are smaller for the same amount of security as large RSA keys. RSA keys of 2048 are already being considered insecure, with 4096 bit keys needed. These large keys have a big impact on embedded systems because they require more processing, result in larger certificates (that cause longer transfer time), etc. 256-bit ECC keys provide comparable security to RSA-3072 bit keys.
What Elliptic Curve should I choose?
The most common curves used are NIST P-256 and X25519. A recent report from F5 indicates that P-256 is used by approximately 74% of internet connected devices, while X25519 is used by 22%. For devices that need to comply with regulations, like medical devices, NIST P-256 is almost always the right choice. If you were wondering, P-256 is the default curve for OpenSSL.