269 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
			
		
		
	
	
			269 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
| *******************
 | ||
| Secure Boot Concept
 | ||
| *******************
 | ||
| 
 | ||
| Currently CoreOS provide a Proof Of Concept of some of the secure boot element that we want to 
 | ||
| implement a full secure-boot solution based on UEFI secure boot.
 | ||
| 
 | ||
| The current proof of concept is structured as follows:
 | ||
| 
 | ||
| Hardware Requirements
 | ||
| =====================
 | ||
|    
 | ||
|    - The device must have an `eMMC`.
 | ||
|    - The architecture of the device must be either `ARM32` or `AARCH64`.
 | ||
| 
 | ||
| 
 | ||
| eMMC Embedded MultiMediaCard
 | ||
| ============================
 | ||
| 
 | ||
| eMMC, or Embedded MultiMediaCard, represents a prevalent storage format in devices such as 
 | ||
| smartphones, tablets, and other embedded systems. It encapsulates NAND flash memory and a dedicated
 | ||
| controller within one package. This structure not only eases integration for device manufacturers
 | ||
| but also ensures a compact, efficient storage medium.
 | ||
| 
 | ||
| Within eMMC's architecture, distinct hardware partitions cater to diverse operational demands:
 | ||
| 
 | ||
| .. graphviz::
 | ||
| 
 | ||
|     digraph emmcStructure {
 | ||
|         rankdir=TB;
 | ||
|         node [shape=box, style=filled, fillcolor="#e6f2ff"];
 | ||
|         edge [color="#0099cc", fontsize=12];
 | ||
| 
 | ||
|         compound=true;
 | ||
| 
 | ||
|         subgraph cluster_eMMC {
 | ||
|             label="eMMC";
 | ||
|             color="#0099cc";
 | ||
| 
 | ||
|             Boot0 [label="Boot0"];
 | ||
|             Boot1 [label="Boot1"];
 | ||
|             RPMB [label="RPMB"];
 | ||
| 
 | ||
|             subgraph cluster_User {
 | ||
|                 label="User";
 | ||
|                 color="#00cc99";
 | ||
|                 GPT [label="GPT Table"];
 | ||
| 
 | ||
|                 subgraph cluster_GPT {
 | ||
|                     label="Software Partitions (GPT)";
 | ||
|                     color="#99e6e6";
 | ||
| 
 | ||
|                     SoftwarePartition1 [label="Partition 1"];
 | ||
|                     SoftwarePartition2 [label="Partition 2"];
 | ||
|                     SoftwarePartitionN [label="Partition N"];
 | ||
|                 }
 | ||
|             }
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
| 
 | ||
| #. **Boot0 and Boot1**: The boot partitions cater to device start-up requirements, typically hosting
 | ||
|    the firmware. Boot0 predominantly initiates the boot-up, while Boot1 stands as a secondary guard 
 | ||
|    or backup, ensuring booting is resilient and failsafe.
 | ||
| 
 | ||
| #. **RPMB (Replay Protected Memory Block)**: As a secure partition, RPMB shelters data against
 | ||
|    potential tampering. It's tailored for sensitive information storage, such as cryptographic keys.
 | ||
|    Its design counters data replays or rollbacks, fortifying against particular attack types.
 | ||
| 
 | ||
| #. **User**: The primary storage domain, the User partition accommodates the OS, applications,
 | ||
|    and user-centric data. It's reminiscent of the primary storage drive in larger computing devices.
 | ||
|    Importantly, the User partition has a layered structure. Using the GPT (GUID Partition Table), it
 | ||
|    is further divided into multiple software partitions, which can house diverse datasets or file
 | ||
|    systems.
 | ||
| 
 | ||
| The boot concept of CoreOS rely on the presence of an eMMC to implement the following feature:
 | ||
| 
 | ||
| - Storage of two copy of the firmware with a way to switch from a copy to another using the eMMC
 | ||
|   boot0 and boot1 hardware partition
 | ||
| - Storage of keys used by the UEFI Secure Key specification inside the secure RPMB hardware
 | ||
|   partition.
 | ||
| - Storage of the bootloader, kernel and rootfs inside the user hardware partition using multiple
 | ||
|   software partition in the GPT format.
 | ||
| 
 | ||
| Firmware
 | ||
| ========
 | ||
| 
 | ||
| The firmware of the device should implement a subset of the UEFI specification as defined in the
 | ||
| ARM Base Boot Requirements (EBBR) and should implement the optional UEFI Secure Boot part of the
 | ||
| EBBR specifications.
 | ||
| 
 | ||
| This is done in CoreOS by levering the built-in EBBR and UEFI Secure Boot present into the u-boot
 | ||
| project.
 | ||
| 
 | ||
| The hardware should verify the validity of the firmware using a hardware specific way. Then the
 | ||
| generic secure boot concept explained here can be used to valide all the following component of
 | ||
| CoreOS.
 | ||
| 
 | ||
| UEFI Key used by UEFI Secure Boot
 | ||
| =================================
 | ||
| 
 | ||
| 
 | ||
| - **PK (Platform Key)**: This top-tier key shoulders the responsibility of KEK verification and its
 | ||
|   potential revocation. PK holders have the exclusive privilege to configure the KEK and the `db`
 | ||
|   database. It's the gatekeeper ensuring only authorized software can touch the firmware or
 | ||
|   bootloader.
 | ||
| 
 | ||
| - **KEK (Key Exchange Key)**: As a medium for data exchange, the KEK is pivotal for signing the `db`
 | ||
|   and `dbx` databases.
 | ||
|   
 | ||
| - **db (Allowed Database)**: This is the white list. It houses the keys or hashes of permitted
 | ||
|   firmware and OS loaders. Execution is only granted to software with a signature that resonates
 | ||
|   with the keys/hashes in this database.
 | ||
|   
 | ||
| - **dbx (Forbidden Database)**: The black sheep are here. Housing keys or hashes of known
 | ||
|   unauthorized software, it ensures any associated software is prohibited from executing.
 | ||
| 
 | ||
| Currently all theses public keys are built-in into u-boot at build time and are read only. In the
 | ||
| future we will use the OP-TEE support into u-boot to use OP-TEE to manage the keys.
 | ||
| 
 | ||
| OP-TEE and RPMB as key manager
 | ||
| ==============================
 | ||
| 
 | ||
| OP-TEE, or Open Portable Trusted Execution Environment, is an open-source implementation of the
 | ||
| Trusted Execution Environment (TEE) designed for ARM-powered platforms. In essence, a TEE is a
 | ||
| secure enclave that provides a separated, isolated environment where specific applications and their
 | ||
| data can run independently from the regular operating system, ensuring they are protected against
 | ||
| potential tampering or unauthorized access.
 | ||
| 
 | ||
| OP-TEE guarantees confidentiality, integrity, and authenticity for critical applications by
 | ||
| executing them in this secure space. It offers a wide range of security features, including secure
 | ||
| storage of cryptographic keys, secure boot, and hardware-backed crypto operations.
 | ||
| 
 | ||
| In the context of UEFI secure boot, OP-TEE becomes instrumental. UEFI's secure boot mechanism
 | ||
| ensures that only trusted, signed firmware, OS loaders, and OS kernels are executed during the boot
 | ||
| process. To enforce this level of trust, UEFI relies on a set of cryptographic keys, including PK
 | ||
| (Platform Key), KEK (Key Exchange Key), and db/dbx (allowed and forbidden signature databases).
 | ||
| Safeguarding these keys is paramount to maintain the security and integrity of the boot process.
 | ||
| 
 | ||
| By leveraging OP-TEE, these UEFI secure boot keys can be securely stored in the RPMB (Replay
 | ||
| Protected Memory Block) partition of the eMMC. The RPMB is a write-protected, secure area of the
 | ||
| eMMC designed to hold sensitive data and protect it against tampering and replay attacks.
 | ||
| Since OP-TEE manages secure access to the RPMB partition, it ensures that the UEFI secure boot keys
 | ||
| are not only safely stored but are also accessible only by authorized firmware components.
 | ||
| 
 | ||
| eMMC User Partition
 | ||
| ===================
 | ||
| 
 | ||
| The user partition of the eMMC must be structured using the GPT (GUID Partition Table) format.
 | ||
| 
 | ||
| Within the GPT-formatted user partition, specific partitions should be established for efficient
 | ||
| booting and system operation:
 | ||
| 
 | ||
| 1. **EFI**: This is the Essential Firmware Interface partition. It holds the `efibootguard`
 | ||
|    os-loader binary, responsible for the boot sequence's initial steps and the kernel's selection
 | ||
|    based on its configuration. This binary is signed with a key present in the `dbx` database
 | ||
| 
 | ||
| 2. **EBG0 - Efibootguard Config 0**: This partition houses the `efibootguard` configuration for the
 | ||
|    first kernel option. Alongside the configuration file, it also contains a Unified Kernel Image
 | ||
|    (UKI), a bundled package comprising the Linux kernel, device trees, and associated boot
 | ||
|    components. The UKI is signed with a key present in the `dbx` database
 | ||
| 
 | ||
| 3. **EBG1 - Efibootguard Config 1**: Similar to EBG0, this partition carries the `efibootguard`
 | ||
|    configuration for the second kernel option. It too holds a Unified Kernel Image tailored for this
 | ||
|    alternate boot choice.
 | ||
| 
 | ||
| 4. **rootfs0**: This partition stores the CoreOS root filesystem designed to complement and operate
 | ||
|    with the kernel embedded in the EBG0 partition. It provides the essential system files and 
 | ||
|    structures required for the operating system's functioning when the kernel from EBG0 is booted. 
 | ||
|    Integrety of this rootfs is assured by storing an hash of the rootfs inside the UKI image.
 | ||
| 
 | ||
| 5. **rootfs1**: Analogous to `rootfs0`, this partition houses the CoreOS root filesystem tailored
 | ||
|    for the kernel within the EBG1 partition. It ensures that, should the system boot from the kernel
 | ||
|    in EBG1, the appropriate file structures and system components are readily available.
 | ||
| 
 | ||
| EFIBootGuard Configuration
 | ||
| ==========================
 | ||
| 
 | ||
| Efibootguard, as a part of its design, employs a configuration system to determine the appropriate
 | ||
| kernel and associated resources to boot from. This configuration is stored in distinct partitions, 
 | ||
| EBG0 and EBG1, each holding its configuration file.
 | ||
| 
 | ||
| The configuration file itself comprises several fields, but most crucially, it contains a revision
 | ||
| field. This field is a numerical identifier indicating the version or update level of the contained
 | ||
| kernel and resources. When the system initiates its boot sequence, Efibootguard assesses the
 | ||
| revision values in both the EBG0 and EBG1 configuration files.
 | ||
| 
 | ||
| The selection process is straightforward yet robust: Efibootguard chooses the partition with the
 | ||
| higher revision value. By doing so, it inherently opts for the most recent or updated kernel version
 | ||
| available. However, this system also supports failover mechanisms. In case the kernel in the
 | ||
| partition with the higher revision encounters issues during boot, Efibootguard can revert to the
 | ||
| other partition, ensuring resilience and continuity in system operations.
 | ||
| 
 | ||
| Moreover, the choice isn't rigidly fixed. When the system undergoes updates, the configuration files
 | ||
| can be rewritten, and the revision values adjusted, allowing for dynamic and flexible booting in
 | ||
| line with system evolutions and updates. In essence, Efibootguard, with its configuration-based
 | ||
| approach, ensures a blend of up-to-date system booting and built-in fail-safes for dependable
 | ||
| operation.
 | ||
| 
 | ||
| Unified Kernel Image
 | ||
| ====================
 | ||
| 
 | ||
| After having choosen the right configuration file, Efibootguard takes on the responsibility of
 | ||
| launching the Unified Kernel Image (UKI) linked with the active configuration. This image bundle
 | ||
| together essential boot components like the Linux kernel, device trees, and the kernel command
 | ||
| line. The secure initiation of this image is paramount, and Efibootguard ensures this by leveraging
 | ||
| UEFI's start_image system call.
 | ||
| 
 | ||
| The UEFI start_image system call  verifies the image's signature against the Secure Boot keys
 | ||
| (PK, KEK, db, and potentially dbx). If the signature matches, indicating that the image is trusted
 | ||
| and hasn't been tampered with, the image is permitted to execute. If not, the booting halts,
 | ||
| preventing any unauthorized or potentially malicious code from running.
 | ||
| 
 | ||
| Once the UKI has been securely initiated, it undertakes multiple tasks. It first extracts the
 | ||
| necessary components from the bundled package, identifying and utilizing the appropriate device
 | ||
| trees based on `compatible` node, by matching with the `compatible` node of the `device-tree` that
 | ||
| is built into the firmware. These device trees inform the system about the hardware configuration,
 | ||
| ensuring the kernel interacts correctly with the system's components. 
 | ||
| 
 | ||
| The UKI os-launcher also has CoreOS specialized patches, enabling dynamic rootfs switching without
 | ||
| requiring an initramfs by changing the `root=` part of the kernel command line at run time to
 | ||
| point to the right rootfs partition.
 | ||
| 
 | ||
| RootFS and dm-verity
 | ||
| ====================
 | ||
| 
 | ||
| dm-verity is a Linux kernel feature designed to provide transparent integrity checking of block
 | ||
| devices, particularly for read-only file systems. Rooted in cryptographic principles, dm-verity
 | ||
| employs a hash-based approach to ensure and validate the integrity of the root filesystem (rootfs).
 | ||
| 
 | ||
| The way dm-verity operates is by building a Merkle tree, a structure where each leaf node contains a
 | ||
| hash of a block of the underlying data, while each non-leaf node is a hash of its children. The
 | ||
| topmost node, the root of the Merkle tree, provides a cumulative hash representing the entirety of
 | ||
| the data. This top hash, known as the root hash, serves as a concise, cryptographic representation
 | ||
| of the entire filesystem's state.
 | ||
| 
 | ||
| When integrating dm-verity with the Unified Kernel Image (UKI), an additional layer of security is
 | ||
| established. By embedding the root hash into the signed UKI, any tampering or modification in the
 | ||
| rootfs can be swiftly detected. When the system boots, the UKI, being signed, ensures that the
 | ||
| embedded root hash is legitimate and untampered. As the OS accesses the rootfs, dm-verity
 | ||
| recalculates the hash values in real-time and compares them to the values in the original Merkle
 | ||
| tree, referenced by the embedded root hash.
 | ||
| 
 | ||
| If any discrepancies are found – that is, if the recalculated hash doesn't match the stored value –
 | ||
| it indicates potential tampering, and the OS can halt access or take appropriate measures. 
 | ||
| 
 | ||
| .. graphviz::
 | ||
| 
 | ||
|     digraph SecureBootFlow {
 | ||
|         rankdir=TB;
 | ||
| 
 | ||
|         node [shape=box, style=filled, fillcolor="#e6f2ff"];
 | ||
|         edge [color="#0099cc", fontsize=12];
 | ||
| 
 | ||
|         Hardware [label="Hardware\n(ARM32/AARCH64 with eMMC)"];
 | ||
|         Firmware [label="u-boot Firmware\n(UEFI EBRR subset)"];
 | ||
|         eMMCConfig [label="eMMC Configuration\n(GPT with EFI partition)"];
 | ||
|         EFIBootGuard [label="EFIBootGuard\n(A/B Kernel Switching)"];
 | ||
|         UnifiedKernel [label="Unified Kernel Image\n(Kernel, cmd line, DTB)"];
 | ||
|         KernelAndRootFS [label="Kernel & RootFS\n(dm-verity validation)"];
 | ||
| 
 | ||
|         Hardware -> Firmware [label="Flashed with u-boot\n+ Built-in keys"];
 | ||
|         Firmware -> eMMCConfig [label="eMMC boot"];
 | ||
|         eMMCConfig -> EFIBootGuard [label="Boots from EFI partition"];
 | ||
|         EFIBootGuard -> UnifiedKernel [label="Selects kernel A/B"];
 | ||
|         UnifiedKernel -> KernelAndRootFS [label="Kernel boot\n+ RootFS verification"];
 | ||
| 
 | ||
|     }
 |