\documentclass[aspectratio=169,obeyspaces,spaces,hyphens,dvipsnames]{beamer}
\usepackage[utf8]{inputenc}
\usepackage{lmodern}% http://ctan.org/pkg/lm
\usepackage{minted}
\usepackage{hyperref}
\usepackage{xcolor}
\usepackage{pgfplots}
\usepackage{tikz}
\usepackage[normalem]{ulem}

\mode<presentation>
\usetheme{Bootlin}

\def\signed #1{{\leavevmode\unskip\nobreak\hfil\penalty50\hskip2em
  \hbox{}\nobreak\hfil(#1)
  \parfillskip=0pt \finalhyphendemerits=0 \endgraf}}

\newsavebox\mybox
\newenvironment{aquote}[1]
  {\savebox\mybox{#1}\begin{quotation}}
  {\signed{\usebox\mybox}\end{quotation}}

\title{Secure boot in embedded Linux systems}
\authors{Thomas Perrot}
\email{thomas.perrot@bootlin.com}
\slidesurl{https://bootlin.com/pub/conferences/2021/lee/perrot-secure-boot/}
\institute{Bootlin}
\conference{Live Embedded Event, June 3rd 2021}

\begin{document}

\addtocontents{toc}{\protect\setcounter{tocdepth}{-1}}
\section{Secure boot in embedded Linux systems}
\addtocontents{toc}{\protect\setcounter{tocdepth}{2}}

\begin{frame}{Who is speaking ?}
  \begin{columns}
    \column{0.6\textwidth}
    \begin{itemize}
    \item Thomas Perrot
    \item Embedded Linux and kernel engineer at Bootlin
    \item Joined in 2020
    \item Embedded Linux engineer and trainer
    \item Open-source contributor
    \item Based in Toulouse, France
    \end{itemize}
    \column{0.4\textwidth}
    \includegraphics[width=\textwidth]{thomas-perrot-small.png}
  \end{columns}
\end{frame}

\begin{frame}{Agenda}
  \begin{itemize}
  \item Introduction
    \begin{itemize}
    \item What is it for?
    \item Chain of trust
    \item Signature process
    \item Workflows impacts
%%    \item Vendor specific part
    \end{itemize}
  \item Presenting one of available solutions based on:
    \begin{itemize}
    \item NXP i.MX8 AHAB secure boot
    \item U-boot verified boot
    \item dm-init + dm-verity
    \end{itemize}
  \end{itemize}
\end{frame}

\subsection{Introduction}

\begin{frame}{What is it for?}
  \begin{itemize}
  \item system integrity checking at boot
  \item prevent
    \begin{itemize}
    \item hijack
    \item tampering
    \item unauthorized software
    \item malware execution
    \end{itemize}
  \end{itemize}
\end{frame}

\begin{frame}{Chain of trust}
  \begin{center}
    \includegraphics[width=0.6\textwidth]{graphics/chain-of-trust.pdf}
  \end{center}
  \begin{itemize}
  \item At \textbf{build} time:
    \begin{itemize}
    \item stages are signed
    \item stages embed the public key of next
    \end{itemize}
  \item At \textbf{boot} time, each stage verify the signature the next one
  \item Next stage isn't loaded when the authentication fails
  \end{itemize}
\end{frame}

\begin{frame}{Signature process}
  %% TODO colums ?
  \includegraphics[width=\textwidth]{graphics/signature-process.pdf}
  \begin{itemize}
  \item Based on digest and asymmetric keys
  \item The private key
    \begin{itemize}
    \item It is used to sign at build
    \item It \textbf{must} not be published
    \end{itemize}
  \item The public key
    \begin{itemize}
    \item It is used to verify at boot
    \item It is shared
    \end{itemize}
  \end{itemize}
\end{frame}

\begin{frame}{Workflows impacts}
  \begin{itemize}
  \item Keys management
  \item Manufactory
  \item Upgrade
  \item boot time
  \end{itemize}
\end{frame}

%% \begin{frame}{Vendor Specific part}
%% \end{frame}

\subsection{A secure boot implementation on i.MX8}

\begin{frame}{Global view}
  \includegraphics[width=\textwidth]{graphics/global-view.pdf}
  \begin{itemize}
  \item \textbf{AHAB} to check the Bootloader integrity, from \textbf{ROM code}
  \item \textbf{U-boot verified boot} to check the kernel integrity, from \textbf{U-boot}
  \item \textbf{dm-verity} to check the rootfs integrity, from the \textbf{kernel}
  \item \textbf{dm-init} and a \textbf{boot script} so as not to need initramfs.
  \end{itemize}
\end{frame}

\begin{frame}{ROM code: NXP i.MX8 secure boot}
  \begin{columns}
    \begin{column}{0.5\textwidth}
      \includegraphics[height=0.45\textheight]{graphics/ahab-boot-flow.png}
    \end{column}
    \begin{column}{0.5\textwidth}
      \begin{itemize}
      \item Called Advanced High Assurance Boot (AHAB)
      \item Different from HAB, the image uses three containers
      \item Uses asymetric keys (PKI tree)
      \item Signed by i.MX code signing tool (CST) at build
      \item Uses One-Time programmable (OTP) to store SRK
      \item Status can be checked from U-boot with \code{hab_status}
      \item Cryptographic Acceleration and Assurance Module (CAAM)
      \end{itemize}
    \end{column}
  \end{columns}
\end{frame}

\begin{frame}{ROM code: AHAB image layout}
  \begin{columns}
    \begin{column}{0.40\textwidth}
      \begin{itemize}
      \item SECO FW using NXP signatures
      \item SCFW, SPL and M4 images using OEM signatures
      \item U-boot and ATF, loaded by SPL
      \item Operations perform by the SECO FW through the SCU ROM
      \end{itemize}
    \end{column}
    \begin{column}{0.20\textwidth}
      \includegraphics[height=0.6\textheight]{graphics/ahab-image-layout.png}
    \end{column}
    \begin{column}{0.40\textwidth}
      \includegraphics[height=0.6\textheight]{graphics/ahab-container-layout.png}
    \end{column}
  \end{columns}
\end{frame}

\begin{frame}[fragile]{ROM code: Generating PKI tree}
  \begin{itemize}
  \item Set the certificate ID:
    \begin{block}{}
      \begin{minted}[fontsize=\scriptsize]{console}
echo 00000001 > serial
      \end{minted}
    \end{block}
  \item Set the passphrase to store the private key:
    \begin{block}{}
      \begin{minted}[fontsize=\scriptsize]{console}
echo -e “mypassphrase\nmypassphrase” > key_pass.txt
      \end{minted}
    \end{block}
  \item Generating a P384 ECC PKI tree:
    \begin{block}{}
      \begin{minted}[fontsize=\scriptsize]{console}
./ahab_pki_tree.sh
[...]
Do you want to use an existing CA key (y/n)?: n
Do you want to use Elliptic Curve Cryptography (y/n)?: y
Enter length for elliptic curve to be used for PKI tree:
Possible values p256, p384, p521:  p384
Enter the digest algorithm to use: sha384
Enter PKI tree duration (years): 10
Do you want the SRK certificates to have the CA flag set? (y/n)?: n
      \end{minted}
    \end{block}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]{ROM code: Generating PKI tree}
  \begin{itemize}
    \item Generating SRK Table and SRK Hash:
      \begin{block}{}
        \begin{minted}[fontsize=\scriptsize]{console}
cd ../crts/
../linux64/bin/srktool -a -s sha384 -t SRK_1_2_3_4_table.bin \
    -e SRK_1_2_3_4_fuse.bin -f 1 -c \
       SRK1_sha384_secp384r1_v3_usr_crt.pem,\
       SRK2_sha384_secp384r1_v3_usr_crt.pem,\
       SRK3_sha384_secp384r1_v3_usr_crt.pem,\
       SRK4_sha384_secp384r1_v3_usr_crt.pem
        \end{minted}
      \end{block}
    \item Checking SRK table matches with the SRK fuse:
      \begin{block}{}
        \begin{minted}[fontsize=\scriptsize]{console}
od -t x4 --endian=big SRK_1_2_3_4_fuse.bin
sha512sum SRK_1_2_3_4_table.bin
        \end{minted}
      \end{block}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]{ROM code: CST configuration}
  \begin{block}{}
    \begin{minted}[fontsize=\scriptsize]{console}
[Header]
Target = AHAB
Version = 1.0
[Install SRK]
# SRK table generated by srktool
File = "crts/SRK_1_2_3_4_table.bin"
# Public key certificate in PEM format
Source = "crts/SRK1_sha384_secp384r1_v3_usr_crt.pem"
# Index of the public key certificate within the SRK table (0 .. 3)
Source index = 0
# Type of SRK set (NXP or OEM)
Source set = OEM
# bitmask of the revoked SRKs
Revocations = 0x0
[Authenticate Data]
# Binary to be signed generated by mkimage
File = "flash.bin.nosigned"
# Offsets = Container header  Signature block (printed out by mkimage)
Offsets   = 0x400             0x590
    \end{minted}
  \end{block}
\end{frame}

\begin{frame}[fragile]{ROM code: One-Time programmable}
  \begin{columns}
    \begin{column}{0.5\textwidth}
      \begin{itemize}
        \item Program fuses:
          \begin{block}{}
            \begin{minted}[fontsize=\scriptsize]{console}
=> fuse prog 0 730 0xbef4d897
=> fuse prog 0 731 0x6abedffa
=> fuse prog 0 732 0xaf28b37c
=> fuse prog 0 733 0xbd3c149a
=> fuse prog 0 734 0xb9bf25cd
=> fuse prog 0 735 0xb23f7389
=> fuse prog 0 736 0x86a0b06f
=> fuse prog 0 737 0xd25485c2
=> fuse prog 0 738 0xcfe655a4
=> fuse prog 0 739 0xe5e7a92e
=> fuse prog 0 740 0xf18dfa06
=> fuse prog 0 741 0x43d7dbc6
=> fuse prog 0 742 0x3a59e53b
=> fuse prog 0 743 0x78c7bf59
=> fuse prog 0 744 0xe7c860bd
=> fuse prog 0 745 0xd8b27ab0
            \end{minted}
          \end{block}
      \end{itemize}
    \end{column}
    \begin{column}{0.5\textwidth}
      \begin{itemize}
        \item Read fuses:
          \begin{block}{}
            \begin{minted}[fontsize=\scriptsize]{console}
=> fuse read 0 730
=> fuse read 0 731
=> fuse read 0 732
=> fuse read 0 733
=> fuse read 0 734
=> fuse read 0 735
=> fuse read 0 736
=> fuse read 0 737
=> fuse read 0 738
=> fuse read 0 739
=> fuse read 0 740
=> fuse read 0 741
=> fuse read 0 742
=> fuse read 0 743
=> fuse read 0 744
=> fuse read 0 745
            \end{minted}
          \end{block}
      \end{itemize}
    \end{column}
  \end{columns}
\end{frame}

\begin{frame}[fragile]{ROM code: Check status}
  \begin{itemize}
  \item Check the status of secure:
    \begin{block}{}
      \begin{minted}[fontsize=\scriptsize]{console}
=> ahab_status
Lifecycle: 0x0020, NXP closed
No SECO Events Found!
      \end{minted}
    \end{block}
  \item SECO event is raised in case of issue:
    \begin{block}{}
      \begin{minted}[fontsize=\scriptsize]{console}
=> ahab_status
Lifecycle: 0x0020, NXP closed
SECO Event[0] = 0x0087EE00
        CMD = AHAB_AUTH_CONTAINER_REQ (0x87)
        IND = AHAB_NO_AUTHENTICATION_IND (0xEE)
sc_seco_get_event: idx: 1, res:3
      \end{minted}
    \end{block}
  \item Close the device:
    \begin{block}{}
      \begin{minted}[fontsize=\scriptsize]{console}
=> ahab_close
=> reset
=> ahab_status
Lifecycle: 0x0080, OEM closed
No SECO Events Found!
      \end{minted}
    \end{block}
  \end{itemize}
\end{frame}

\begin{frame}{bootloader: U-boot verified boot}
  \begin{columns}
    \begin{column}{0.65\textwidth}
      \includegraphics[width=\textwidth]{graphics/uboot-fitimage-build-flow.png}
    \end{column}
    \begin{column}{0.35\textwidth}
      \begin{itemize}
      \item Uses fitimage
      \item Uses asymetric key
      \item Signed by \code{mkimage}
      \end{itemize}
    \end{column}
  \end{columns}
\end{frame}

\begin{frame}[fragile]{bootloader: fitimage is a container}
  \begin{columns}
    \begin{column}{0.29\textwidth}
      \begin{block}{}
        \fontsize{4}{6}\selectfont
        \begin{minted}{console}
/dts-v1/;

/ {
    description = "U-Boot fitImage for bar";
    #address-cells = <1>;

    images {
        kernel@1 {
            description = "Linux kernel";
            data = /incbin/("fitImage-linux.bin");
                        type = "kernel";
                        arch = "arm64";
                        os = "linux";
                        compression = "gzip";
                        load = <0x80280000>;
                        entry = <0x80280000>;
                        hash@1 {
                                algo = "sha256";
                        };
                };
        fdt@1 {
            description = "Flattened Device Tree blob";
            data = /incbin/("foo.dtb");
            type = "flat_dt";
            arch = "arm64";
            compression = "none";
            load = <0x83000000>;
            hash@1 {
                algo = "sha256";
            };
        };
        \end{minted}
      \end{block}
    \end{column}
    \begin{column}{0.26\textwidth}
      \begin{block}{}
        \fontsize{4}{6}\selectfont
        \begin{minted}{console}
        bootscr@1 {
            description = "U-boot script";
            data = /incbin/("boot.scr");
            type = "script";
            arch = "arm64";
            compression = "none";
            hash@1 {
                algo = "sha256";
            };
        };

    configurations {
        default = "conf@1";
        conf@1 {
            description = "kernel, dtb, bootscr";
            kernel = "kernel@1";
            fdt = "fdt@1";
            bootscr = "bootscr@1";
            hash@1 {
                algo = "sha256";
            };
    };
};
        \end{minted}
      \end{block}
    \end{column}
    \begin{column}{0.45\textwidth}
      \begin{itemize}
      \item To store some \code{images}:
        \begin{itemize}
        \item Some kernel images
        \item Some device tree binaries or overlays
        \item Some boot script
        \item Some FPGA bitstreams...
        \end{itemize}
      \item But also some \code{configurations} that are combinations of images.
      \end{itemize}
    \end{column}
  \end{columns}
\end{frame}

\begin{frame}[fragile]{bootloader: How the fitimage is signed}
  \begin{itemize}
  \item Isn't globally signed
  \item There are two available ways:
    \begin{itemize}
    \item Sign images
    \item Sign configurations
    \end{itemize}
  \item Sign the configurations allows to prevent mix-and-match attack
  \end{itemize}
  \begin{block}{}
    \begin{minted}[fontsize=\scriptsize]{console}
conf@1 {
    description = "1 Linux kernel, FDT blob, boot script";
    kernel = "kernel@1";
    fdt = "fdt@1";
    bootscr = "bootscr@1";
    hash@1 {
        algo = "sha256";
    };
    signature@1 {
        algo = "sha256,rsa4096";
        key-name-hint = "kernel-dev";
        sign-images = "kernel", "fdt", "bootscr";
    };
};
    \end{minted}
  \end{block}
\end{frame}

\begin{frame}[fragile]{bootloader: Generating keys and the certificate}
  \begin{itemize}
  \item Generate a private key
    \begin{block}{}
      \begin{minted}[fontsize=\scriptsize]{console}
openssl genpkey -algorithm RSA -out kernel-dev.key -pkeyopt rsa_keygen_bits:4096
      \end{minted}
    \end{block}
  \item Generate a certificat
    \begin{block}{}
      \begin{minted}[fontsize=\scriptsize]{console}
openssl req -new -x509 -key kernel-dev.key -out kernel-dev.crt
      \end{minted}
    \end{block}
  \item Generate a public key
    \begin{block}{}
      \begin{minted}[fontsize=\scriptsize]{console}
openssl rsa -pubout -in kernel-dev.key -out kernel-dev.pem
      \end{minted}
    \end{block}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]{bootloader: Build the signed fitimage}
  \begin{block}{}
    \begin{minted}[fontsize=\scriptsize]{console}
dtc u-boot_pubkey.dts -O dtb -o u-boot_pubkey.dtb
make CROSS_COMPILE=arm-linux-gnueabihf- foo_defconfig
make CROSS_COMPILE=arm-linux-gnueabihf- tools
tools/mkimage -f fitImage.its -K u-boot_pubkey.dtb -k /path/to/keys -r fitImage
make CROSS_COMPILE=arm-linux-gnueabihf- EXT_DTB=u-boot_pubkey.dtb
    \end{minted}
  \end{block}
\end{frame}

\begin{frame}[fragile]{rootfs: dm-verity}
  \begin{block}{}
    \begin{minted}[fontsize=\scriptsize]{console}
                            [   root    ]
                           /    . . .    \
                [entry_0]                 [entry_1]
               /  . . .  \                 . . .   \
    [entry_0_0]   . . .  [entry_0_127]    . . . .  [entry_1_127]
      / ... \             /   . . .  \             /           \
blk_0 ... blk_127  blk_16256   blk_16383      blk_32640 . . . blk_32767
    \end{minted}
  \end{block}

  \begin{itemize}
  \item Virtual layer provides integrity checking
  \item Using cryptographic hash tree (Merkle tree)
  \item Blocks are hashed and the value is checked \textbf{only on access}
  \item Only for read-only block devices
  \item Data and hash device can be the same
  \item Since 5.4, the root hash can be signed
  \end{itemize}
\end{frame}

\begin{frame}[fragile]{rootfs: dm-verity}
  \begin{itemize}
    \item Create hash on the image:
      \begin{block}{}
        \fontsize{5}{6}\selectfont
        \begin{minted}{console}
veritysetup format verify --hash-offset=${OFFSET} image.squashfs image.squashfs
VERITY header information for image.squashfs
UUID:                   5f1872a8-6bd0-4824-82fc-886b944b60c2
Hash type:              1
Data blocks:            12800
Data block size:        4096
Hash block size:        4096
Hash algorithm:         sha256
Salt:                   
73be30a3f4338cd9046492b9abcb172bb6fe4b741e9104cc7cf768dbd0901547
Root hash:              
408323fad51d3a85c26384270da3980a63874b67d1e30a47330bd163bba98a41
        \end{minted}
      \end{block}
    \item Verify the image:
      \begin{block}{}
        \fontsize{5}{6}\selectfont
        \begin{minted}{console}
veritysetup verify --hash-offset=${OFFSET} image.squashfs image.squashfs ${HASH_ALG}
        \end{minted}
      \end{block}
    \item Open the image:
      \begin{block}{}
        \fontsize{5}{6}\selectfont
        \begin{minted}{console}
veritysetup open --hash-offset=${OFFSET} image.squashfs foo image.squashfs ${KEY} ${SALT}
dmsetup table --concise
foo,5f1872a8-6bd0-4824-82fc-886b944b60c2,1,ro,0 905896
verity 1 7:0 7:0 4096 4096 113237 113238 sha256
        \end{minted}
      \end{block}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]{rootfs: dm-init}
  \begin{itemize}
  \item Early create device mapper from kernel cmdline
    \begin{block}{}
      \fontsize{4}{6}\selectfont
    \begin{minted}{console}
dm-mod.create="rootfs,,0,ro,0 905880 verity 1 /dev/mmcblk0p2 /dev/mmcblk0p2 4096 4096 113235 113236 sha256 76defbdb8fd7842ab708b2b23ee718ec46dda3e41367462d12ad8c793cedfc76
3a7ea567e63eabf5c18fa938573e5e16e2fe81b440267751bd8a8fd70d22f8db"
    \end{minted}
  \end{block}
  \item Allows to mount dm-verity device
    \begin{itemize}
    \item \textbf{Without} initramfs and \code{veritysetup}
    \item \textbf{Only with} a boot script that extend the kernel cmdline:
      \begin{block}{}
        \fontsize{4}{6}\selectfont
        \begin{minted}{console}
source ${fitimage_loadaddr}:bootscr@1
sha256+
        \end{minted}
      \end{block}
    \end{itemize}
  \item Boot script example:
    \begin{block}{}
      \fontsize{4}{6}\selectfont
      \begin{minted}{console}
setenv sectors 244184
setenv data_blocks 30523
setenv hash_start 30524
setenv data_block_sz 4096
setenv hash_block_sz 4096
setenv hash_alg sha256
setenv salt e2f254232415ea2c694c8064bc62169e895ab56f0d6f6b0db9a8734f5a4759d4
setenv root_hash bf67ab59b4b09263da1306e996f35f515c54c9c4078cbf6ecb629fcea3afee99
setenv bootargs ${bootargs} rootfstype=squashfs root=/dev/dm-0 dm-mod.create="rootfs,,0,ro,0 ${sectors} verity 1 /dev/mmcblk0p2 /dev/mmcblk0p2 ${data_block_sz} ${hash_block_sz} \
    ${data_blocks} ${hash_start} ${hash_alg} ${root_hash} ${salt}"
      \end{minted}
    \end{block}
  \end{itemize}
\end{frame}

\questionslide

\end{document}
