security: Add common boot media write protection
Introduce boot media protection settings and use the existing boot_device_wp_region() function to apply settings on all platforms that supports it yet. Also remove the Intel southbridge code, which is now obsolete. Every platform locks the SPIBAR in a different stage. For align up with the common mrc cache driver and lock after it has been written to. Tested on Supermicro X11SSH-TF. The whole address space is write-protected. Change-Id: Iceb3ecf0bde5cec562bc62d1d5c79da35305d183 Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/32704 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Philipp Deppenwiese <zaolin.daisuki@gmail.com> Reviewed-by: Julius Werner <jwerner@chromium.org>
This commit is contained in:
		
				
					committed by
					
						
						Philipp Deppenwiese
					
				
			
			
				
	
			
			
			
						parent
						
							7bcd9a1d91
						
					
				
				
					commit
					78feacc440
				
			@@ -62,4 +62,12 @@ int boot_device_wp_region(const struct region_device *rd,
 | 
				
			|||||||
 **/
 | 
					 **/
 | 
				
			||||||
void boot_device_init(void);
 | 
					void boot_device_init(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Restrict read/write access to the bootmedia using platform defined rules.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#if CONFIG(BOOTMEDIA_LOCK_NONE)
 | 
				
			||||||
 | 
					static inline void boot_device_security_lockdown(void) {}
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					void boot_device_security_lockdown(void);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
#endif /* _BOOT_DEVICE_H_ */
 | 
					#endif /* _BOOT_DEVICE_H_ */
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -15,3 +15,4 @@ source "src/security/vboot/Kconfig"
 | 
				
			|||||||
source "src/security/tpm/Kconfig"
 | 
					source "src/security/tpm/Kconfig"
 | 
				
			||||||
source "src/security/memory/Kconfig"
 | 
					source "src/security/memory/Kconfig"
 | 
				
			||||||
source "src/security/intel/Kconfig"
 | 
					source "src/security/intel/Kconfig"
 | 
				
			||||||
 | 
					source "src/security/lockdown/Kconfig"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,3 +2,4 @@ subdirs-y += vboot
 | 
				
			|||||||
subdirs-y += tpm
 | 
					subdirs-y += tpm
 | 
				
			||||||
subdirs-y += memory
 | 
					subdirs-y += memory
 | 
				
			||||||
subdirs-y += intel
 | 
					subdirs-y += intel
 | 
				
			||||||
 | 
					subdirs-y += lockdown
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										62
									
								
								src/security/lockdown/Kconfig
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								src/security/lockdown/Kconfig
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,62 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					choice
 | 
				
			||||||
 | 
						prompt "Boot media protection mechanism"
 | 
				
			||||||
 | 
						default BOOTMEDIA_LOCK_NONE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					config BOOTMEDIA_LOCK_NONE
 | 
				
			||||||
 | 
						bool "Don't lock boot media sections"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					config BOOTMEDIA_LOCK_CONTROLLER
 | 
				
			||||||
 | 
						bool "Lock boot media using the controller"
 | 
				
			||||||
 | 
						help
 | 
				
			||||||
 | 
						  Select this if you want the controller to lock specific regions.
 | 
				
			||||||
 | 
						  This only works on some platforms, please check the code or boot log.
 | 
				
			||||||
 | 
						  On Intel platforms for e.g. this will make use of the SPIBAR PRRs.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					config BOOTMEDIA_LOCK_CHIP
 | 
				
			||||||
 | 
						bool "Lock boot media using the chip"
 | 
				
			||||||
 | 
						help
 | 
				
			||||||
 | 
						  Select this if you want the chip to lock specific regions.
 | 
				
			||||||
 | 
						  This only works on some chips, please check the code or boot log.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					endchoice
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					choice
 | 
				
			||||||
 | 
						prompt "Boot media protected regions"
 | 
				
			||||||
 | 
						depends on !BOOTMEDIA_LOCK_NONE
 | 
				
			||||||
 | 
						default BOOTMEDIA_LOCK_WHOLE_RO
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					config BOOTMEDIA_LOCK_WHOLE_RO
 | 
				
			||||||
 | 
						bool "Write-protect the whole boot medium"
 | 
				
			||||||
 | 
						help
 | 
				
			||||||
 | 
						  Select this if you want to write-protect the whole firmware boot
 | 
				
			||||||
 | 
						  medium.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						  The locking will take place during the chipset lockdown.
 | 
				
			||||||
 | 
						  Chipset lockdown is platform specific und might be done unconditionally,
 | 
				
			||||||
 | 
						  when INTEL_CHIPSET_LOCKDOWN is set or has to be triggered later
 | 
				
			||||||
 | 
						  (e.g. by the payload or the OS).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						  NOTE: If you trigger the chipset lockdown unconditionally,
 | 
				
			||||||
 | 
						  you won't be able to write to the whole flash chip using the
 | 
				
			||||||
 | 
						  internal controller any more.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					config BOOTMEDIA_LOCK_WHOLE_NO_ACCESS
 | 
				
			||||||
 | 
						depends on BOOTMEDIA_LOCK_CONTROLLER
 | 
				
			||||||
 | 
						bool "Read- and write-protect the whole boot medium"
 | 
				
			||||||
 | 
						help
 | 
				
			||||||
 | 
						  Select this if you want to protect the firmware boot medium against
 | 
				
			||||||
 | 
						  all further accesses. On platforms that memory map a part of the
 | 
				
			||||||
 | 
						  boot medium the corresponding region is still readable.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						  The locking will take place during the chipset lockdown.
 | 
				
			||||||
 | 
						  Chipset lockdown is platform specific und might be done unconditionally,
 | 
				
			||||||
 | 
						  when INTEL_CHIPSET_LOCKDOWN is set or has to be triggered later
 | 
				
			||||||
 | 
						  (e.g. by the payload or the OS).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						  NOTE: If you trigger the chipset lockdown unconditionally,
 | 
				
			||||||
 | 
						  you won't be able to write to the whole flash chip using the
 | 
				
			||||||
 | 
						  internal controller any more.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					endchoice
 | 
				
			||||||
							
								
								
									
										6
									
								
								src/security/lockdown/Makefile.inc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/security/lockdown/Makefile.inc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					## SPDX-License-Identifier: GPL-2.0-or-later
 | 
				
			||||||
 | 
					## This file is part of the coreboot project.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ifneq ($(CONFIG_BOOTMEDIA_LOCK_NONE),y)
 | 
				
			||||||
 | 
					ramstage-y += lockdown.c
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
							
								
								
									
										57
									
								
								src/security/lockdown/lockdown.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								src/security/lockdown/lockdown.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,57 @@
 | 
				
			|||||||
 | 
					/* SPDX-License-Identifier: GPL-2.0-or-later */
 | 
				
			||||||
 | 
					/* This file is part of the coreboot project. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <boot_device.h>
 | 
				
			||||||
 | 
					#include <commonlib/region.h>
 | 
				
			||||||
 | 
					#include <console/console.h>
 | 
				
			||||||
 | 
					#include <bootstate.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Enables read- /write protection of the bootmedia.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void boot_device_security_lockdown(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						const struct region_device *rdev;
 | 
				
			||||||
 | 
						enum bootdev_prot_type lock_type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						printk(BIOS_DEBUG, "BM-LOCKDOWN: Enabling boot media protection scheme ");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (CONFIG(BOOTMEDIA_LOCK_CONTROLLER)) {
 | 
				
			||||||
 | 
							if (CONFIG(BOOTMEDIA_LOCK_WHOLE_RO)) {
 | 
				
			||||||
 | 
								printk(BIOS_DEBUG, "'readonly'");
 | 
				
			||||||
 | 
								lock_type = CTRLR_WP;
 | 
				
			||||||
 | 
							} else if (CONFIG(BOOTMEDIA_LOCK_WHOLE_NO_ACCESS)) {
 | 
				
			||||||
 | 
								printk(BIOS_DEBUG, "'no access'");
 | 
				
			||||||
 | 
								lock_type = CTRLR_RWP;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							printk(BIOS_DEBUG, "using CTRL...\n");
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							if (CONFIG(BOOTMEDIA_LOCK_WHOLE_RO)) {
 | 
				
			||||||
 | 
								printk(BIOS_DEBUG, "'readonly'");
 | 
				
			||||||
 | 
								lock_type = MEDIA_WP;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							printk(BIOS_DEBUG, "using flash chip...\n");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rdev = boot_device_ro();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (boot_device_wp_region(rdev, lock_type) >= 0)
 | 
				
			||||||
 | 
							printk(BIOS_INFO, "BM-LOCKDOWN: Enabled bootmedia protection\n");
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							printk(BIOS_ERR, "BM-LOCKDOWN: Failed to enable bootmedia protection\n");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void lock(void *unused)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						boot_device_security_lockdown();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Keep in sync with mrc_cache.c
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if CONFIG(MRC_WRITE_NV_LATE)
 | 
				
			||||||
 | 
					BOOT_STATE_INIT_ENTRY(BS_OS_RESUME_CHECK, BS_ON_EXIT, lock, NULL);
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					BOOT_STATE_INIT_ENTRY(BS_DEV_RESOURCES, BS_ON_ENTRY, lock, NULL);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
@@ -97,42 +97,3 @@ config INTEL_CHIPSET_LOCKDOWN
 | 
				
			|||||||
config SOUTHBRIDGE_INTEL_COMMON_WATCHDOG
 | 
					config SOUTHBRIDGE_INTEL_COMMON_WATCHDOG
 | 
				
			||||||
	bool
 | 
						bool
 | 
				
			||||||
	depends on SOUTHBRIDGE_INTEL_COMMON_PMBASE
 | 
						depends on SOUTHBRIDGE_INTEL_COMMON_PMBASE
 | 
				
			||||||
 | 
					 | 
				
			||||||
if SOUTHBRIDGE_INTEL_COMMON_FINALIZE
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
choice
 | 
					 | 
				
			||||||
	prompt "Flash locking during chipset lockdown"
 | 
					 | 
				
			||||||
	default LOCK_SPI_FLASH_NONE
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
config LOCK_SPI_FLASH_NONE
 | 
					 | 
				
			||||||
	bool "Don't lock flash sections"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
config LOCK_SPI_FLASH_RO
 | 
					 | 
				
			||||||
	bool "Write-protect all flash sections"
 | 
					 | 
				
			||||||
	help
 | 
					 | 
				
			||||||
	  Select this if you want to write-protect the whole firmware flash
 | 
					 | 
				
			||||||
	  chip. The locking will take place during the chipset lockdown, which
 | 
					 | 
				
			||||||
	  is either triggered by coreboot (when INTEL_CHIPSET_LOCKDOWN is set)
 | 
					 | 
				
			||||||
	  or has to be triggered later (e.g. by the payload or the OS).
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	        NOTE: If you trigger the chipset lockdown unconditionally,
 | 
					 | 
				
			||||||
	        you won't be able to write to the flash chip using the
 | 
					 | 
				
			||||||
	        internal programmer any more.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
config LOCK_SPI_FLASH_NO_ACCESS
 | 
					 | 
				
			||||||
	bool "Write-protect all flash sections and read-protect non-BIOS sections"
 | 
					 | 
				
			||||||
	help
 | 
					 | 
				
			||||||
	  Select this if you want to protect the firmware flash against all
 | 
					 | 
				
			||||||
	  further accesses (with the exception of the memory mapped BIOS re-
 | 
					 | 
				
			||||||
	  gion which is always readable). The locking will take place during
 | 
					 | 
				
			||||||
	  the chipset lockdown, which is either triggered by coreboot (when
 | 
					 | 
				
			||||||
	  INTEL_CHIPSET_LOCKDOWN is set) or has to be triggered later (e.g.
 | 
					 | 
				
			||||||
	  by the payload or the OS).
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	        NOTE: If you trigger the chipset lockdown unconditionally,
 | 
					 | 
				
			||||||
	        you won't be able to write to the flash chip using the
 | 
					 | 
				
			||||||
	        internal programmer any more.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
endchoice
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
endif
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -15,16 +15,6 @@ void intel_pch_finalize_smm(void)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	const pci_devfn_t lpc_dev = PCI_DEV(0, 0x1f, 0);
 | 
						const pci_devfn_t lpc_dev = PCI_DEV(0, 0x1f, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (CONFIG(LOCK_SPI_FLASH_RO) ||
 | 
					 | 
				
			||||||
	    CONFIG(LOCK_SPI_FLASH_NO_ACCESS)) {
 | 
					 | 
				
			||||||
		int i;
 | 
					 | 
				
			||||||
		u32 lockmask = 1UL << 31;
 | 
					 | 
				
			||||||
		if (CONFIG(LOCK_SPI_FLASH_NO_ACCESS))
 | 
					 | 
				
			||||||
			lockmask |= 1 << 15;
 | 
					 | 
				
			||||||
		for (i = 0; i < 20; i += 4)
 | 
					 | 
				
			||||||
			RCBA32(0x3874 + i) = RCBA32(0x3854 + i) | lockmask;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Lock SPIBAR */
 | 
						/* Lock SPIBAR */
 | 
				
			||||||
	RCBA32_OR(0x3804, (1 << 15));
 | 
						RCBA32_OR(0x3804, (1 << 15));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user