| 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 |