Skip to content
/ uvisor Public
forked from ARMmbed/uvisor

uVisor device security layer for ARMv7M microcontrollers

License

Unknown and 2 other licenses found

Licenses found

Unknown
LICENSE
BSD-3-Clause
LICENSE-BSD.txt
Zlib
LICENSE-zlib.txt
Notifications You must be signed in to change notification settings

jserv/uvisor

 
 

The uVisor

Overview

The uVisor is a self-contained software hypervisor that creates independent secure domains on ARM Cortex-M3 and M4 microcontrollers (M0+ will follow). Its function is to increase resilience against malware and to protect secrets from leaking even among different modules of the same application.

Further reading:

Word of caution

This version of the uVisor is an early beta with an incomplete implementation of the security features of the final product. Future versions of uVisor will add these functions - starting with this year's ARM TechCon that will come with a security challenge firmware.

Some of the open uVisor issues in progress are listed here:

Supported platforms:

The uVisor Design Philosophy

The need for security features applies across a wide range of today’s IoT products. We at ARM are convinced that many IoT security problems can be solved with standardised building blocks.

The uVisor project is one of these basic building blocks – complementary to other important blocks like robust communication stacks, safe firmware updates and secure crypto libraries.

The design philosophy of uVisor is to provide hardware-enforced compartments (sandboxes) for individual code blocks by limiting access to memories and peripherals using the existing hardware security features of the Cortex-M microcontrollers.

Breaking the established flat security model of microcontrollers into compartmentalised building blocks results in high security levels, as the reach of flaws or external attacks can be limited to less sensitive function blocks.

A basic example of uVisor is preventing unauthorised access to flash memory from faulty or compromised code. This not only prevents malware from getting resident on the device, but also enables protection of device secrets like cryptographic keys.

Services built on top of our security layer can safely depend on an unclonable trusted identity, secure access to internet services and benefit from encryption key protection.

Technical Details

The uVisor:

  • Is initialised right after device start-up.
  • Runs in privileged mode.
  • Sets up a protected environment using a Memory Protection Unit (the ARM Cortex-M MPU or a vendor-specific alternative). In particular:
    • Its own memories and the security-critical peripherals are protected from the unprivileged code.
    • Unprivileged access to selected hardware peripherals and memories is limited through Access Control Lists (ACLs).
  • Allows interaction from the unprivileged code by exposing SVCall-based APIs.
  • Forwards and de-privileges interrupts to the unprivileged code that has been registered for them.
  • Prevents registers leakage when switching execution between privileged and unprivileged code and between mutually untrusted unprivileged modules.
  • Forces access to some security-critical peripherals (like DMA) through SVCall-based APIs.

The Unprivileged Code

All the code that is not explicitly part of the uVisor is generally referred to as unprivileged code. The unprivileged code:

  • Runs in unprivileged mode.
  • Has direct memory access to unprivileged peripherals.
  • Can register for unprivileged interrupts.
  • The uVisor prevents its access to privileged memories and peripherals.

The unprivileged code can be made of mutually untrusted isolated modules (or boxes). This way, even if all are running with unprivileged permissions, different modules can protect their own secrets and execute critical code securely.

Memory Layout

The following figure shows the memory layout of a system where security is enforced by the uVisor.

uVisor memory layout

The uVisor secures two main memory blocks, in Flash and SRAM respectively. In both cases, the uVisor protects its own data and the data of the secure boxes it manages for the unprivileged code. In general, all the unprivileged code that is not protected in a secure domain is referred to as "main application".

The main memory sections that the uVisor protects are detailed in the following table:

Memory Section Description
uVisor code The uVisor code is readable and executable by unprivileged code, so that code sharing is facilitated and privileged-unprivileged transitions are easier
uVisor data/BSS/stack The uVisor places all its constants, initialised and initialised data and the stack in secured areas of memory, separated from the unprivileged code
Secure boxes data/BSS/stack Through a configuration process, unprivileged code can set up a secure box for which data and stack can be secured by the uVisor and placed in isolated and protected memory areas
Protected VTORs Interrupt vectors are relocated to the SRAM but protected by the uVisor. Access to them is made through specific APIs

The Boot Process

The uVisor is initialised right after device startup and takes ownership of its most critical assets, like privileged peripherals, the vector table and memory management. In particular:

  1. Several sanity checks are performed, to verify integrity of the memory structure as expected by the uVisor.
  2. The bss section is zeroed, the data section initialised (uVisor).
  3. The vector table is relocated.
  4. The virtual Memory Protection Unit (vMPU) is initialised:
    • Secure boxes are loaded:
      • The bss section is zeroed, the data section initialised (secure boxes).
      • Access Control Lists (ACLs) are registered for each secure box.
      • Stacks are initialised for each secure box.
    • The MPU (ARM or third-party) is configured.
  5. Privileged and unprivileged stack pointers are initialised.
  6. Execution is de-privileged and handed over to the unprivileged code.

The uVisor as a yotta Module

The uVisor is compiled and packaged to be included as a dependency by applications built with yotta on top of mbed. The yotta module for the uVisor is called uvisor-lib.

When used as a yotta module on top of mbed, the uVisor comes as a pre-compiled binary blob that is then included in the rest of the system. In this way the integrity of the uVisor, and hence its security model, are guaranteed. Each official release of uvisor-lib will then deliver an approved build of the code tree here presented, also exposing the APIs for the unprivileged application.

We suggest you always use the official uvisor-lib module through the regular yotta build process. For development, experimenting, or fun, the uVisor can also be manually turned into a yotta module and locally linked to your project. First of all, build the yotta module:

# select the correct platform in the code tree
cd k64f/uvisor

# build the uVisor and generate the yotta module
make clean release

Then link your local version of the module to yotta:

# the release folder is at the top level of the code tree
cd ../../release

# link the module to yotta locally
yotta link

# link your project to this version of uvisor-lib
cd ../your_custom_project
yotta link uvisor-lib

Again, consider using the official uvisor-lib release if building with yotta, and refer to its documentation for the APIs it exposes to unprivileged code.

Debugging

By default, debug output is silenced. Special debug messages only occur when the device is halted due to faults or failures caught by the uVisor. These messages are tentatively printed on the UART0 port, if it has previously been enabled by the unprivileged code. Otherwise, SWO is used as a fallback.

To enable more verbose debug messages, just build as follows:

# create local version of uvisor-lib with debug enabled
make OPT= clean release

And locally link the resulting debug release to yotta as described previously.

Note that this debug build implements non-blocking messages. If an SWO viewer is not used, messages are just lost and executions continues normally. If the uVisor caught an error or an access fault, though, the system is halted.

Debugging messages that are outputted through the SWO port can be observed with an SWO viewer. If using a JLink debugger, just do as follows:

cd k64f/uvisor
make swo

Or refer to Makefile.rules to import the swo rule in your build environment.

Software and Hardware Requirements

To build:

To debug:

About

uVisor device security layer for ARMv7M microcontrollers

Resources

License

Unknown and 2 other licenses found

Licenses found

Unknown
LICENSE
BSD-3-Clause
LICENSE-BSD.txt
Zlib
LICENSE-zlib.txt

Stars

Watchers

Forks

Packages

No packages published

Languages

  • C 99.7%
  • Other 0.3%