You may want to encrypt data or code in an embedded Linux device.

Data encryption is a common approach when you need to protect the privacy and confidentiality of the users. Data is any information generated during the executing of the device, including databases, configuration files, and so on.

Code encryption depends on the situation, and encrypting the full root filesystem is not that common. Usually, most of the components are free and open source software, so there is nothing to hide. There is also the issue of GPLv3 and Tivoization (using any GPLv3 software will force you to provide a mechanism for the user to update the software, and that would make it more difficult if you are encrypting it). A more common use case is to encrypt only the applications you developed for the device. It’s usually where your intellectual property is.

There are basically two main approaches to encryption in Linux: full disk encryption and file-based encryption.

Full disk encryption provides encryption at the block level and the whole disk or a disk partition is encrypted. For that, we can use dm-crypt, the Linux kernel’s device mapper crypto target.

File-based encryption provides encryption at the file system level, where each directory may be separately and optionally encrypted with a different key. The two most common implementations of file-based encryption are fscrypt and eCryptFS. fscrypt is an API available on some filesystems like EXT4, UBIFS and F2FS, and eCryptFS is a more generic solution implemented as a layer that stacks on top of an existing filesystem.

But what about the keys used for encryption?

Since an asymmetric key algorithm is too slow to be used in encryption, usually a symmetric-key algorithm is used in encryption.

Key storage techniques

On a desktop or smartphone, the key used to encrypt the filesystem could be derived from a user password (passphrase) entered interactively. That’s how it works on Android smartphones for example.

On an embedded system, usually we don’t have user interaction to derive the key from a password every time we boot the device. So the key should be stored encrypted in the filesystem or in secure storage. And we need hardware support for that.

For example, NXP i.MX processors have a unique master key (pre-programmed by NXP) that can only be accessed by a special hardware module called CAAM (Cryptographic Accelerator and Assurance Module). This hardware device could be used to encrypt the key and store it in the filesystem (this would have to be done during manufacturing). And during boot, the CAMM module would be used to decrypt the key and restore the plain key that would be used to decrypt the filesystem. Since the key inside the CAAM module is not accessible, the encrypted key is protected.

If you don’t have security features available in the processor, you could achieve the same results with an external hardware like a Secure Element or a TPM device. These external devices usually provide secure storage, so they could be used to store a master key that could be used to encrypt/decrypt the filesystem encryption key. These devices also offer a lot of security features like random number generation, hash calculation, crypto and signing functions, etc.

A Secure Element is a secure computing system. It is basically secure storage with its own secure applications (usually implemented using Java Card, but not necessary). What a secure element does is very open and depends on the implementation, but most of them implement the Public-Key Cryptography Standard 11 (PKCS#11). Examples of Secure Elements are smart-cards and SIM-cards.

TPM (Trusted Platform Module) is a specification and an international standard (ISO/IEC 11889). TPM is not a Secure Element, although it could be implemented inside one. It can be implemented in hardware or software, but most implementations are in hardware. It provides a set of limited security features defined by the standard, including secure storage and cryptographic functions.

A third alternative for secure storage would be using a Trusted Execution Environment. A TEE is an environment where the code executed and the data accessed is isolated and protected in terms of confidentiality (no one has access to the data) and integrity (no one can change the code and its behavior). A lot of devices around us make use of a Trusted Execution Environment, including smartphones, set-top-boxes, videogame consoles and Smart TVs. If you want more details about how a TEE works you can read my article “Introduction to Trusted Execution Environment and ARM’s TrustZone”.

In the end, if you care about encryption in your embedded Linux device, you will have to think about key storage and management from the beginning of the project.

https://sergioprado.blog/introduction-embedded-linux-security-part-1/


🌱 Back to Garden