Newer
Older
arm-trusted-firmware / docs / process / security-hardening.rst
@Petre-Ionut Tudor Petre-Ionut Tudor on 12 Feb 2020 6 KB Update docs with PMU security information
Secure Development Guidelines
=============================

This page contains guidance on what to check for additional security measures,
including build options that can be modified to improve security or catch issues
early in development.

Security considerations
-----------------------

Part of the security of a platform is handling errors correctly, as described in
the previous section. There are several other security considerations covered in
this section.

Do not leak secrets to the normal world
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

The secure world **must not** leak secrets to the normal world, for example in
response to an SMC.

Handling Denial of Service attacks
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

The secure world **should never** crash or become unusable due to receiving too
many normal world requests (a *Denial of Service* or *DoS* attack). It should
have a mechanism for throttling or ignoring normal world requests.

Preventing Secure-world timing information leakage via PMU counters
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

The Secure world needs to implement some defenses to prevent the Non-secure
world from making it leak timing information. In general, higher privilege
levels must defend from those below when the PMU is treated as an attack
vector.

Refer to the :ref:`Performance Monitoring Unit` guide for detailed information
on the PMU registers.

Timing leakage attacks from the Non-secure world
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Since the Non-secure world has access to the ``PMCR`` register, it can
configure the PMU to increment counters at any exception level and in both
Secure and Non-secure state. Thus, it attempts to leak timing information from
the Secure world.

Shown below is an example of such a configuration:

-  ``PMEVTYPER0_EL0`` and ``PMCCFILTR_EL0``:

   -  Set ``P`` to ``0``.
   -  Set ``NSK`` to ``1``.
   -  Set ``M`` to ``0``.
   -  Set ``NSH`` to ``0``.
   -  Set ``SH`` to ``1``.

-  ``PMCNTENSET_EL0``:

   -  Set ``P[0]`` to ``1``.
   -  Set ``C`` to ``1``.

-  ``PMCR_EL0``:

   -  Set ``DP`` to ``0``.
   -  Set ``E`` to ``1``.

This configuration instructs ``PMEVCNTR0_EL0`` and ``PMCCNTR_EL0`` to increment
at Secure EL1, Secure EL2 (if implemented) and EL3.

Since the Non-secure world has fine-grained control over where (at which
exception levels) it instructs counters to increment, obtaining event counts
would allow it to carry out side-channel timing attacks against the Secure
world. Examples include Spectre, Meltdown, as well as extracting secrets from
cryptographic algorithms with data-dependent variations in their execution
time.

Secure world mitigation strategies
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The ``MDCR_EL3`` register allows EL3 to configure the PMU (among other things).
The `Arm ARM`_ details all of the bit fields in this register, but for the PMU
there are two bits which determine the permissions of the counters:

-  ``SPME`` for the programmable counters.
-  ``SCCD`` for the cycle counter.

Depending on the implemented features, the Secure world can prohibit counting
in AArch64 state via the following:

-  ARMv8.2-Debug not implemented:

   -  Prohibit general event counters and the cycle counter:
      ``MDCR_EL3.SPME == 0 && PMCR_EL0.DP == 1 && !ExternalSecureNoninvasiveDebugEnabled()``.

      -  ``MDCR_EL3.SPME`` resets to ``0``, so by default general events should
         not be counted in the Secure world.
      -  The ``PMCR_EL0.DP`` bit therefore needs to be set to ``1`` when EL3 is
         entered and ``PMCR_EL0`` needs to be saved and restored in EL3.
      -  ``ExternalSecureNoninvasiveDebugEnabled()`` is an authentication
         interface which is implementation-defined unless ARMv8.4-Debug is
         implemented. The `Arm ARM`_ has detailed information on this topic.

   -  The only other way is to disable the ``PMCR_EL0.E`` bit upon entering
      EL3, which disables counting altogether.

-  ARMv8.2-Debug implemented:

   -  Prohibit general event counters: ``MDCR_EL3.SPME == 0``.
   -  Prohibit cycle counter: ``MDCR_EL3.SPME == 0 && PMCR_EL0.DP == 1``.
      ``PMCR_EL0`` therefore needs to be saved and restored in EL3.

-  ARMv8.5-PMU implemented:

   -  Prohibit general event counters: as in ARMv8.2-Debug.
   -  Prohibit cycle counter: ``MDCR_EL3.SCCD == 1``

In Aarch32 execution state the ``MDCR_EL3`` alias is the ``SDCR`` register,
which has some of the bit fields of ``MDCR_EL3``, most importantly the ``SPME``
and ``SCCD`` bits.

Build options
-------------

Several build options can be used to check for security issues. Refer to the
:ref:`Build Options` for detailed information on these.

- The ``BRANCH_PROTECTION`` build flag can be used to enable Pointer
  Authentication and Branch Target Identification.

- The ``ENABLE_STACK_PROTECTOR`` build flag can be used to identify buffer
  overflows.

- The ``W`` build flag can be used to enable a number of compiler warning
  options to detect potentially incorrect code.

  - W=0 (default value)

    The ``Wunused`` with ``Wno-unused-parameter``, ``Wdisabled-optimization``
    and ``Wvla`` flags are enabled.

    The ``Wunused-but-set-variable``, ``Wmaybe-uninitialized`` and
    ``Wpacked-bitfield-compat`` are GCC specific flags that are also enabled.

  - W=1

    Adds ``Wextra``, ``Wmissing-format-attribute``, ``Wmissing-prototypes``,
    ``Wold-style-definition`` and ``Wunused-const-variable``.

  - W=2

    Adds ``Waggregate-return``, ``Wcast-align``, ``Wnested-externs``,
    ``Wshadow``, ``Wlogical-op``.

  - W=3

    Adds ``Wbad-function-cast``, ``Wcast-qual``, ``Wconversion``, ``Wpacked``,
    ``Wpointer-arith``, ``Wredundant-decls`` and
    ``Wswitch-default``.

  Refer to the GCC or Clang documentation for more information on the individual
  options: https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html and
  https://clang.llvm.org/docs/DiagnosticsReference.html.

  NB: The ``Werror`` flag is enabled by default in TF-A and can be disabled by
  setting the ``E`` build flag to 0.

.. rubric:: References

-  `Arm ARM`_

--------------

*Copyright (c) 2019-2020, Arm Limited. All rights reserved.*

.. _Arm ARM: https://developer.arm.com/docs/ddi0487/latest