The Importance of Secure Boot

Secure Boot is a rather cryptic and opaque security setting on your computer. In most circumstances, it’s something you or your computer’s vendor will configure in your machine’s BIOS, and then forget about. Occasionally, you might be tempted to disable this setting to facilitate custom boot scenarios, install certain hardware, or peform botique configurations to your machine. However, Secure Boot is an essential protection mechanism to help keep your computer safe from the most dangerous and sophisticated cyber security threats.

Overview of secure boot

Secure Boot is a security standard developed by the Unified Extensible Firmware Interface (UEFI) Forum. It is used to ensure that a device boots using only software that is trusted by the manufacturer. During the boot process, the firmware checks each piece of software against a database of known good code. If any software is found to be untrusted or tampered with, the boot process is halted. This mechanism helps prevent unauthorized code from running at startup, effectively mitigating risks associated with rootkits, bootkits, and other forms of malware that attempt to compromise a system before the operating system has a chance to load.

Adding Legitimate User Applications, Operating System Files, and Kernel Modules with Secure Boot

While Secure Boot provides an essential layer of protection against malicious code, it can also pose challenges when adding your legitimate user applications, operating system files, and kernel modules. To ensure that these components are trusted by the system, developers and administrators must follow specific procedures.

Adding Legitimate User Applications

To add a legitimate user application with Secure Boot enabled, the application must be signed with a trusted certificate. This certificate is typically obtained from a trusted Certificate Authority (CA). With modern operating systems, this is handled automatically by the package management system. For example, on Linux Ubuntu, apt will handle isntalling applications with a trusted certificate. It is important when adding apt-keys that you always ensure they are trusted – if you allow sketchy repos, you can get burnt. The packagage manager will add the signed application is then added to the system’s whitelist, allowing it to run without being blocked by Secure Boot. Windows works the same way, with Microsoft only allowing application to be install for which it has a trusted CA relationship built-in to Windows.

Adding Operating System Files

When adding new operating system files, such as device drivers or system libraries, these files must also be signed with a trusted certificate. Again, a properly configured Operating System will handle this as part of its update syetem. In addition, the operating system’s package manager will typically be configured to verify the integrity of these files during installation. This ensures that only trusted operating system files are installed on the system.

Adding Kernel Modules

Kernel modules, which provide additional functionality to the operating system kernel, must also be signed with a trusted certificate. In Linux, kernel modules can be signed using the sign-file tool, which generates a digital signature for the module. The signed module is then loaded into the kernel, allowing it to function without being blocked by Secure Boot.

Here is an example:

1
sign-file -v -k /path/to/private/key -c /path/to/certificate.crt -t /path/to/kernel/module.ko

Detecting Secure Boot

As a developer, it’s often helpful to audit the machine your code is running on to determine if secureboot is enabled.

Linux

In Linux you can write a go program that does just that:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
package main

import (
	"fmt"
	"os"
	"path/filepath"
	"strings"
)

// checkSecureBoot checks if Secure Boot is enabled by reading the appropriate EFI variable.
func checkSecureBoot() (bool, error) {
	secureBootPath := "/sys/firmware/efi/efivars/SecureBoot-*"

	files, err := filepath.Glob(secureBootPath)
	if err != nil {
		return false, fmt.Errorf("failed to read Secure Boot variable: %v", err)
	}

	for _, file := range files {
		data, err := os.ReadFile(file)
		if err != nil {
			return false, fmt.Errorf("failed to read file %s: %v", file, err)
		}

		// Check the contents to determine if Secure Boot is enabled
		if strings.Contains(string(data), "1") {
			return true, nil
		}
	}

	return false, nil
}

func main() {
	enabled, err := checkSecureBoot()
	if err != nil {
		fmt.Println("Error:", err)
		return
	}

	if enabled {
		fmt.Println("Secure Boot is enabled.")
	} else {
		fmt.Println("Secure Boot is not enabled.")
	}
}

Windows Powershell

On Windows, you can detect SecureBoot with a simple Powershell command

1
Confirm-SecureBootUEFI

Windows Go

You can also write some go code to detect the same:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package main

import (
	"fmt"
	"golang.org/x/sys/windows"
)

const (	
	secureBootVariableName = "SecureBoot"
)

func main() {
	// Get the firmware environment variable value
	value, err := getFirmwareEnvironmentVariable(secureBootVariableName)
	if err != nil {
		fmt.Println(err)
		return
	}

	// Check the Secure Boot status
	if value == 1 {
		fmt.Println("Secure Boot is enabled")
	} else {
		fmt.Println("Secure Boot is disabled")
	}
}

func getFirmwareEnvironmentVariable(name string) (uint32, error) {
	// Get the firmware environment variable value using the Windows API
	var value uint32
	var size uint32
	err := windows.GetFirmwareEnvironmentVariableEx(windows.StringToUTF16Ptr(name), &value, &size)
	if err != nil {
		return 0, err
	}
	return value, nil
}
Written on December 24, 2024