Recently there was a hack published for Hyundai’s Linux based infotainment head unit. The device itself had implemented security features such as signed/authenticated and encrypted images. However the encryption key was stored in the Linux build system (Yocto) setup script. The script was inadvertently published as part of open source compliance. To make things worse, the code signing key used wasn’t unique and the hacker was able to “google it” based on the public key. The hacker used encryption keys to decrypt images and then guess the code signing key. They could then sign custom firmware and install it on the infotainment unit.
In this article, we’ll discuss ways of securing keys to avoid such scenarios.
Code signing is a technique employed to verify the authenticity of software. This is achieved by digitally signing each piece of software and verifying the signature before executing that piece of software. On an IoT/embedded device, the authenticity of software is checked by implementing secure boot and chain of trust. Typically a private key is used to sign the software at build time and the corresponding public key goes on the device for signature verification. The private key needs to be protected so that hackers can not sign custom/malicious code.
Securing code signing keys
Generating and storing the keys:
The public/private key that is generated for code signing needs to be unique, ideally using a random number generator with very good entropy (randomness). The private key then needs to be protected by transferring it onto a hardware security module (HSM). Most modern HSM’s support generating the key within the hardware, this eliminates the need to securely transfer the keys onto the HSM. Multiple keys can be stored in different key slots.
The benefits of using a HSM are:
- High level tamper resist security for keys
- Keys are never exposed outside of HSM
- Avoids keys on unsecure developer laptops or ex-employees taking keys
- Avoid accidental leaks of code signing keys
- Protects keys even if build machine is compromised
- Meets various compliance such as FIPS 140-2, Level 3
- Simplify and standardize your signing process
- Unified way of key storage / management and signing across all products
Using the keys for signing:
The tools generating software images need to request the HSM to generate signatures using the private key. On IoT devices running Linux, there are various pieces of software such as: boot loader, fitImage (kernel / device tree), root filesystem, firmware update / OTA image etc. Each piece of software is generated using different tools. The tools are responsible for embedding the signature into the image. So the build tools need to be able to interface with the HSM to request signature generation. Fortunately, most HSM’s support the PKCS#11 interface.
Using the standard PKCS#11 API/interface, the tools can request the signature in a hardware (HSM) independent manner and without needing to know the private key. Reference examples on how to interface with the HSM is typically provided by each tool vendor. For example: NXP CST (AN12812), u-boot mkimage, swupdate (SWUPDATE_SIGNING) all support PKCS#11 directly or indirectly via OpenSSL. Using the references, build recipes can be created in the build systems such as Yocto / Buildroot / OpenWRT to leverage a local HSM for code signing. Thus ensuring code signing key protection. The local HSM in this case can be USB based (e.g.: Nitrokey) attached to the build machine or for testing purposes a software emulation of the HSM (e.g.: SoftHSMv2).
When developing a scalable solution for code signing key protection, below are some other considerations:
Proxying a local HSM
The popular HSM’s (e.g.: Nitrokey) are USB based and must be attached directly to the build server / machine. Many companies might have a build server pool and relying on a USB HSM attached to a single build server is not scalable. In this case, having an option to proxy the HSM to any machine on the network needs to be considered. The p11-kit allows for the same, learn more here. Alternatively network based HSMs can be used.
Cloud HSM / API based signing
Commercial offerings for CloudHSM and/or dedicated code signing servers have become increasingly popular over the years. Many offer API’s or even PKCS#11 compatible clients that allow for signing with a remote HSM. Some additional integration code might be needed for integrating with the build tools.
It is prudent to ensure the developer productivity is not hampered because of depending on a HSM or build server to do signed builds. So having an option to disable signed builds and/or adding support for signed developer builds using a software based HSM (e.g.: SoftHSMv2) is important. The SoftHSM supports the same PKCS#11 interface, so the only change needed is to ensure generating “developer” keys that are not used in production.
Protecting encryption keys
Similar to protecting code signing keys, other keys such as encryption keys can be secured on an HSM. Companies can protect their intellectual property by encrypting their device images with keys stored on the HSM.
Protecting the code signing keys and encryption keys is an important part of securing your software supply chain. Leaked keys can cause liability, reputation and business harm. It is easier to secure the keys than try to revoke keys on devices in the field after a leak! By leveraging HSM’s, the build infrastructure can be protected with a high level of security. The necessary security architecture and build tool integration needs to be considered early in the development process to ensure high levels of security and developer productivity.
As part of our VigiShield offering, we provide out of the box tooling support for code signing using HSMs. We also support integration with custom/3rd party PKI infrastructures to secure your keys. Schedule a free consultation to learn more about how we can help secure your products and go to market faster.