Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F152512087
D18798.id.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
48 KB
Referenced Files
None
Subscribers
None
D18798.id.diff
View Options
Index: stand/common/bootstrap.h
===================================================================
--- stand/common/bootstrap.h
+++ stand/common/bootstrap.h
@@ -33,6 +33,10 @@
#include <sys/queue.h>
#include <sys/linker_set.h>
+#ifdef SECURE_BOOT
+#include <bearssl.h>
+#endif
+
/* Commands and return values; nonzero return sets command_errmsg != NULL */
typedef int (bootblk_cmd_t)(int argc, char *argv[]);
#define COMMAND_ERRBUFSZ (256)
@@ -332,6 +336,19 @@
/* For kexec-type loaders, get ksegment structure */
void (*arch_kexec_kseg_get)(int *nseg, void **kseg);
+#ifdef SECURE_BOOT
+ /*
+ * Check if we should verify anything.
+ * 0 - Secure boot disabled,
+ * 1 - enabled
+ */
+ int (*secure_boot_enabled)(void);
+ /* Return an array of x509 CAs */
+ br_x509_certificate* (*secure_boot_get_CAs)(size_t *count);
+ br_x509_certificate* (*secure_boot_get_forbidden_CAs)(size_t *count);
+ /* Check if the DER encoded TBS part of X509 certificate is forbidden */
+ int (*secure_boot_cert_forbidden)(const char*, size_t);
+#endif
};
extern struct arch_switch archsw;
Index: stand/common/module.c
===================================================================
--- stand/common/module.c
+++ stand/common/module.c
@@ -41,6 +41,10 @@
#include "bootstrap.h"
+#ifdef SECURE_BOOT
+#include "verify.h"
+#endif
+
#define MDIR_REMOVED 0x0001
#define MDIR_NOHINTS 0x0002
@@ -428,6 +432,11 @@
return(NULL);
}
+#ifdef SECURE_BOOT
+ if (verify(name) != 0)
+ return (NULL);
+#endif
+
if ((fd = open(name, O_RDONLY)) < 0) {
snprintf(command_errbuf, sizeof(command_errbuf),
"can't open '%s': %s", name, strerror(errno));
@@ -552,6 +561,12 @@
last_file = last_file->f_next)
;
+#ifdef SECURE_BOOT
+ err = verify(filename);
+ if (err != 0)
+ return (err);
+#endif
+
do {
err = file_load(filename, loadaddr, &fp);
if (err)
Index: stand/common/verify.h
===================================================================
--- /dev/null
+++ stand/common/verify.h
@@ -0,0 +1,6 @@
+#ifndef VERIFY_H
+#define VERIFY_H
+
+int verify(const char*);
+
+#endif /* VERIFY_H */
Index: stand/common/verify.c
===================================================================
--- /dev/null
+++ stand/common/verify.c
@@ -0,0 +1,227 @@
+/*-
+ * Copyright (c) 2019 Stormshield.
+ * Copyright (c) 2019 Semihalf.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stand.h>
+#include <secureboot.h>
+
+#include "bootstrap.h"
+#include "verify.h"
+
+int
+verify(const char *path)
+{
+ struct signature_info header;
+ unsigned char digest[br_sha256_SIZE];
+ unsigned char decrypted_digest[br_sha256_SIZE];
+ unsigned char *signature;
+ size_t tbs_size;
+ int result = 0;
+ ssize_t read_result;
+ int fd;
+
+ size_t trusted_count;
+ br_x509_certificate cert;
+ unsigned char *tbs_cert;
+ br_x509_certificate *trusted_certs;
+ br_x509_pkey *pkey;
+ br_rsa_pkcs1_vrfy vrfy_fp;
+
+ signature = NULL;
+ cert.data = NULL;
+
+ if (archsw.secure_boot_enabled == NULL) {
+ printf("archsw.secure_boot_enabled == NULL\n");
+ return (EINVAL);
+ }
+
+ result = archsw.secure_boot_enabled();
+
+ /*
+ * 0 - SecureBoot disabled,
+ * 1 - enabled,
+ * any other value - error
+ */
+ if (result == 0)
+ return (0);
+
+ if (result != 1)
+ return (EINVAL);
+
+ if (archsw.secure_boot_get_CAs == NULL) {
+ printf("archsw.secure_boot_getCAs == NULL\n");
+ return (EINVAL);
+ }
+ if (archsw.secure_boot_get_forbidden_CAs == NULL) {
+ printf("archsw.secure_boot_get_forbidden_CAs == NULL\n");
+ return (EINVAL);
+ }
+ if (archsw.secure_boot_cert_forbidden == NULL) {
+ printf("archsw.secure_boot_cert_forbidden == NULL\n");
+ return (EINVAL);
+ }
+
+ /*
+ * XXX: Opening and closing a file causes a memory leak of 4kB
+ */
+ fd = open(path, O_RDONLY);
+
+ /*
+ * The structure with information about the signature
+ * is simply appended to the binary file.
+ */
+ lseek(fd, sizeof(header), SEEK_END);
+ read_result = checked_read(fd, (char *)&header, sizeof(header));
+ if (read_result != sizeof(header)) {
+ printf("Failed to read header\n");
+ result = errno;
+ goto out;
+ }
+
+ if (header.magic != MAGIC) {
+ printf("Bad signature magic\n");
+ result = EINVAL;
+ goto out;
+ }
+
+ /*
+ * Check if the sizes are sane.
+ */
+ if (header.signature_size > 4096 || header.cert_size > 4096) {
+ result = EINVAL;
+ goto out;
+ }
+
+ lseek(fd, header.kernel_size, SEEK_SET);
+ signature = malloc(header.signature_size);
+ cert.data = malloc(header.cert_size);
+ if (signature == NULL || cert.data == NULL) {
+ printf("Failed to allocate memory\n");
+ result = ENOMEM;
+ goto out;
+ }
+
+ cert.data_len = header.cert_size;
+ read_result = checked_read(fd, signature, header.signature_size);
+ if (read_result != header.signature_size) {
+ printf("Failed to read signature\n");
+ result = errno;
+ goto out;
+ }
+ read_result = checked_read(fd, cert.data, header.cert_size);
+ if (read_result != header.cert_size) {
+ printf("Failed to read X509 certificate\n");
+ result = errno;
+ goto out;
+ }
+
+ /*
+ * Check if the certificate is blacklisted.
+ */
+ tbs_cert = X509_to_tbs(cert.data, &tbs_size);
+ result = archsw.secure_boot_cert_forbidden(tbs_cert, tbs_size);
+ if (result != 0) {
+ printf("Certificate is forbidden\n");
+ goto out;
+ }
+
+ /*
+ * Check if CA that was used to sign the certificate
+ * is on the forbidden list.
+ */
+ trusted_certs = archsw.secure_boot_get_forbidden_CAs(&trusted_count);
+ if (trusted_certs != NULL) {
+ pkey = verify_cert(&cert, trusted_certs, trusted_count);
+ free_certs(trusted_certs, trusted_count);
+ if (pkey != NULL) {
+ printf("Certificate is forbidden\n");
+ result = EACCES;
+ goto out;
+ }
+ }
+
+ /*
+ * Verify if we trust the embedded certificate.
+ */
+ trusted_certs = archsw.secure_boot_get_CAs(&trusted_count);
+ if (trusted_certs == NULL) {
+ printf("Invalid CA count\n");
+ result = EINVAL;
+ goto out;
+ }
+ pkey = verify_cert(&cert, trusted_certs, trusted_count);
+ free_certs(trusted_certs, trusted_count);
+ if (pkey == NULL) {
+ printf("Failed to verify certificate\n");
+ result = EACCES;
+ goto out;
+ }
+
+ /*
+ * Decode encrypted digest using public key
+ * of the embedded certificate.
+ */
+ vrfy_fp = br_rsa_pkcs1_vrfy_get_default();
+ result = vrfy_fp(signature, header.signature_size,
+ BR_HASH_OID_SHA256, br_sha256_SIZE,
+ &pkey->key.rsa, decrypted_digest);
+ free_pkey(pkey);
+ free(pkey);
+ if (result != 1) {
+ printf("Failed to decode signature\n");
+ result = EINVAL;
+ goto out;
+ }
+
+ /*
+ * Calculate digest, excluding the signature
+ * and compare it against what we have just decoded.
+ */
+ lseek(fd, 0, SEEK_SET);
+ result = gen_digest(fd, header.kernel_size, digest);
+ if (result != 0) {
+ printf("Failed to hash the binary\n");
+ goto out;
+ }
+ if (memcmp(digest, decrypted_digest, br_sha256_SIZE) != 0) {
+ printf("Decoded hash doesn't match\n");
+ result = EACCES;
+ goto out;
+ } else
+ result = 0;
+
+out:
+ if (signature != NULL)
+ free(signature);
+ if (cert.data != NULL)
+ free(cert.data);
+
+ close(fd);
+ return (result);
+}
Index: stand/defs.mk
===================================================================
--- stand/defs.mk
+++ stand/defs.mk
@@ -174,6 +174,12 @@
.endif
LOADER_INTERP?=${LOADER_DEFAULT_INTERP}
+# Secure Boot
+.if ${MK_SECUREBOOT} == "yes"
+.include "${SRCTOP}/lib/libbearssl/Makefile.inc"
+.include "${SRCTOP}/lib/libsecureboot/Makefile.inc"
+.endif
+
# Make sure we use the machine link we're about to create
CFLAGS+=-I.
Index: stand/efi/include/Guid/GlobalVariable.h
===================================================================
--- /dev/null
+++ stand/efi/include/Guid/GlobalVariable.h
@@ -0,0 +1,193 @@
+/* $FreeBSD$ */
+/** @file
+ GUID for EFI (NVRAM) Variables.
+
+ Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ @par Revision Reference:
+ GUID defined in UEFI 2.1
+**/
+
+#ifndef __GLOBAL_VARIABLE_GUID_H__
+#define __GLOBAL_VARIABLE_GUID_H__
+
+#define EFI_GLOBAL_VARIABLE \
+ { \
+ 0x8BE4DF61, 0x93CA, 0x11d2, {0xAA, 0x0D, 0x00, 0xE0, 0x98, 0x03, 0x2B, 0x8C } \
+ }
+
+extern EFI_GUID gEfiGlobalVariableGuid;
+
+//
+// Follow UEFI 2.4 spec:
+// To prevent name collisions with possible future globally defined variables,
+// other internal firmware data variables that are not defined here must be
+// saved with a unique VendorGuid other than EFI_GLOBAL_VARIABLE or
+// any other GUID defined by the UEFI Specification. Implementations must
+// only permit the creation of variables with a UEFI Specification-defined
+// VendorGuid when these variables are documented in the UEFI Specification.
+//
+// Note: except the globally defined variables defined below, the spec also defines
+// L"Boot####" - A boot load option.
+// L"Driver####" - A driver load option.
+// L"SysPrep####" - A System Prep application load option.
+// L"Key####" - Describes hot key relationship with a Boot#### load option.
+// The attribute for them is NV+BS+RT, #### is a printed hex value, and no 0x or h
+// is included in the hex value. They can not be expressed as a #define like other globally
+// defined variables, it is because we can not list the Boot0000, Boot0001, etc one by one.
+//
+
+///
+/// The language codes that the firmware supports. This value is deprecated.
+/// Its attribute is BS+RT.
+///
+#define EFI_LANG_CODES_VARIABLE_NAME L"LangCodes"
+///
+/// The language code that the system is configured for. This value is deprecated.
+/// Its attribute is NV+BS+RT.
+///
+#define EFI_LANG_VARIABLE_NAME L"Lang"
+///
+/// The firmware's boot managers timeout, in seconds, before initiating the default boot selection.
+/// Its attribute is NV+BS+RT.
+///
+#define EFI_TIME_OUT_VARIABLE_NAME L"Timeout"
+///
+/// The language codes that the firmware supports.
+/// Its attribute is BS+RT.
+///
+#define EFI_PLATFORM_LANG_CODES_VARIABLE_NAME L"PlatformLangCodes"
+///
+/// The language code that the system is configured for.
+/// Its attribute is NV+BS+RT.
+///
+#define EFI_PLATFORM_LANG_VARIABLE_NAME L"PlatformLang"
+///
+/// The device path of the default input/output/error output console.
+/// Its attribute is NV+BS+RT.
+///
+#define EFI_CON_IN_VARIABLE_NAME L"ConIn"
+#define EFI_CON_OUT_VARIABLE_NAME L"ConOut"
+#define EFI_ERR_OUT_VARIABLE_NAME L"ErrOut"
+///
+/// The device path of all possible input/output/error output devices.
+/// Its attribute is BS+RT.
+///
+#define EFI_CON_IN_DEV_VARIABLE_NAME L"ConInDev"
+#define EFI_CON_OUT_DEV_VARIABLE_NAME L"ConOutDev"
+#define EFI_ERR_OUT_DEV_VARIABLE_NAME L"ErrOutDev"
+///
+/// The ordered boot option load list.
+/// Its attribute is NV+BS+RT.
+///
+#define EFI_BOOT_ORDER_VARIABLE_NAME L"BootOrder"
+///
+/// The boot option for the next boot only.
+/// Its attribute is NV+BS+RT.
+///
+#define EFI_BOOT_NEXT_VARIABLE_NAME L"BootNext"
+///
+/// The boot option that was selected for the current boot.
+/// Its attribute is BS+RT.
+///
+#define EFI_BOOT_CURRENT_VARIABLE_NAME L"BootCurrent"
+///
+/// The types of boot options supported by the boot manager. Should be treated as read-only.
+/// Its attribute is BS+RT.
+///
+#define EFI_BOOT_OPTION_SUPPORT_VARIABLE_NAME L"BootOptionSupport"
+///
+/// The ordered driver load option list.
+/// Its attribute is NV+BS+RT.
+///
+#define EFI_DRIVER_ORDER_VARIABLE_NAME L"DriverOrder"
+///
+/// The ordered System Prep Application load option list.
+/// Its attribute is NV+BS+RT.
+///
+#define EFI_SYS_PREP_ORDER_VARIABLE_NAME L"SysPrepOrder"
+///
+/// Identifies the level of hardware error record persistence
+/// support implemented by the platform. This variable is
+/// only modified by firmware and is read-only to the OS.
+/// Its attribute is NV+BS+RT.
+///
+#define EFI_HW_ERR_REC_SUPPORT_VARIABLE_NAME L"HwErrRecSupport"
+///
+/// Whether the system is operating in setup mode (1) or not (0).
+/// All other values are reserved. Should be treated as read-only.
+/// Its attribute is BS+RT.
+///
+#define EFI_SETUP_MODE_NAME L"SetupMode"
+///
+/// The Key Exchange Key Signature Database.
+/// Its attribute is NV+BS+RT+AT.
+///
+#define EFI_KEY_EXCHANGE_KEY_NAME L"KEK"
+///
+/// The public Platform Key.
+/// Its attribute is NV+BS+RT+AT.
+///
+#define EFI_PLATFORM_KEY_NAME L"PK"
+///
+/// Array of GUIDs representing the type of signatures supported
+/// by the platform firmware. Should be treated as read-only.
+/// Its attribute is BS+RT.
+///
+#define EFI_SIGNATURE_SUPPORT_NAME L"SignatureSupport"
+///
+/// Whether the platform firmware is operating in Secure boot mode (1) or not (0).
+/// All other values are reserved. Should be treated as read-only.
+/// Its attribute is BS+RT.
+///
+#define EFI_SECURE_BOOT_MODE_NAME L"SecureBoot"
+///
+/// The OEM's default Key Exchange Key Signature Database. Should be treated as read-only.
+/// Its attribute is BS+RT.
+///
+#define EFI_KEK_DEFAULT_VARIABLE_NAME L"KEKDefault"
+///
+/// The OEM's default public Platform Key. Should be treated as read-only.
+/// Its attribute is BS+RT.
+///
+#define EFI_PK_DEFAULT_VARIABLE_NAME L"PKDefault"
+///
+/// The OEM's default secure boot signature store. Should be treated as read-only.
+/// Its attribute is BS+RT.
+///
+#define EFI_DB_DEFAULT_VARIABLE_NAME L"dbDefault"
+///
+/// The OEM's default secure boot blacklist signature store. Should be treated as read-only.
+/// Its attribute is BS+RT.
+///
+#define EFI_DBX_DEFAULT_VARIABLE_NAME L"dbxDefault"
+///
+/// The OEM's default secure boot timestamp signature store. Should be treated as read-only.
+/// Its attribute is BS+RT.
+///
+#define EFI_DBT_DEFAULT_VARIABLE_NAME L"dbtDefault"
+///
+/// Allows the firmware to indicate supported features and actions to the OS.
+/// Its attribute is BS+RT.
+///
+#define EFI_OS_INDICATIONS_SUPPORT_VARIABLE_NAME L"OsIndicationsSupported"
+///
+/// Allows the OS to request the firmware to enable certain features and to take certain actions.
+/// Its attribute is NV+BS+RT.
+///
+#define EFI_OS_INDICATIONS_VARIABLE_NAME L"OsIndications"
+///
+/// Whether the system is configured to use only vendor provided
+/// keys or not. Should be treated as read-only.
+/// Its attribute is BS+RT.
+///
+#define EFI_VENDOR_KEYS_VARIABLE_NAME L"VendorKeys"
+
+#endif
Index: stand/efi/include/Guid/ImageAuthentication.h
===================================================================
--- /dev/null
+++ stand/efi/include/Guid/ImageAuthentication.h
@@ -0,0 +1,353 @@
+/* $FreeBSD$ */
+/** @file
+ Image signature database are defined for the signed image validation.
+
+ Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ @par Revision Reference:
+ GUIDs defined in UEFI 2.5 spec.
+**/
+
+#ifndef __IMAGE_AUTHTICATION_H__
+#define __IMAGE_AUTHTICATION_H__
+
+#include <Guid/GlobalVariable.h>
+#include <Protocol/Hash.h>
+
+#define EFI_IMAGE_SECURITY_DATABASE_GUID \
+ { \
+ 0xd719b2cb, 0x3d3a, 0x4596, { 0xa3, 0xbc, 0xda, 0xd0, 0xe, 0x67, 0x65, 0x6f } \
+ }
+
+///
+/// Varialbe name with guid EFI_IMAGE_SECURITY_DATABASE_GUID
+/// for the authorized signature database.
+///
+#define EFI_IMAGE_SECURITY_DATABASE L"db"
+///
+/// Varialbe name with guid EFI_IMAGE_SECURITY_DATABASE_GUID
+/// for the forbidden signature database.
+///
+#define EFI_IMAGE_SECURITY_DATABASE1 L"dbx"
+///
+/// Variable name with guid EFI_IMAGE_SECURITY_DATABASE_GUID
+/// for the timestamp signature database.
+///
+#define EFI_IMAGE_SECURITY_DATABASE2 L"dbt"
+
+#define SECURE_BOOT_MODE_ENABLE 1
+#define SECURE_BOOT_MODE_DISABLE 0
+
+#define SETUP_MODE 1
+#define USER_MODE 0
+
+//***********************************************************************
+// Signature Database
+//***********************************************************************
+///
+/// The format of a signature database.
+///
+#pragma pack(1)
+
+typedef struct {
+ ///
+ /// An identifier which identifies the agent which added the signature to the list.
+ ///
+ EFI_GUID SignatureOwner;
+ ///
+ /// The format of the signature is defined by the SignatureType.
+ ///
+ UINT8 SignatureData[1];
+} EFI_SIGNATURE_DATA;
+
+typedef struct {
+ ///
+ /// Type of the signature. GUID signature types are defined in below.
+ ///
+ EFI_GUID SignatureType;
+ ///
+ /// Total size of the signature list, including this header.
+ ///
+ UINT32 SignatureListSize;
+ ///
+ /// Size of the signature header which precedes the array of signatures.
+ ///
+ UINT32 SignatureHeaderSize;
+ ///
+ /// Size of each signature.
+ ///
+ UINT32 SignatureSize;
+ ///
+ /// Header before the array of signatures. The format of this header is specified
+ /// by the SignatureType.
+ /// UINT8 SignatureHeader[SignatureHeaderSize];
+ ///
+ /// An array of signatures. Each signature is SignatureSize bytes in length.
+ /// EFI_SIGNATURE_DATA Signatures[][SignatureSize];
+ ///
+} EFI_SIGNATURE_LIST;
+
+typedef struct {
+ ///
+ /// The SHA256 hash of an X.509 certificate's To-Be-Signed contents.
+ ///
+ EFI_SHA256_HASH ToBeSignedHash;
+ ///
+ /// The time that the certificate shall be considered to be revoked.
+ ///
+ EFI_TIME TimeOfRevocation;
+} EFI_CERT_X509_SHA256;
+
+typedef struct {
+ ///
+ /// The SHA384 hash of an X.509 certificate's To-Be-Signed contents.
+ ///
+ EFI_SHA384_HASH ToBeSignedHash;
+ ///
+ /// The time that the certificate shall be considered to be revoked.
+ ///
+ EFI_TIME TimeOfRevocation;
+} EFI_CERT_X509_SHA384;
+
+typedef struct {
+ ///
+ /// The SHA512 hash of an X.509 certificate's To-Be-Signed contents.
+ ///
+ EFI_SHA512_HASH ToBeSignedHash;
+ ///
+ /// The time that the certificate shall be considered to be revoked.
+ ///
+ EFI_TIME TimeOfRevocation;
+} EFI_CERT_X509_SHA512;
+
+#pragma pack()
+
+///
+/// This identifies a signature containing a SHA-256 hash. The SignatureHeader size shall
+/// always be 0. The SignatureSize shall always be 16 (size of SignatureOwner component) +
+/// 32 bytes.
+///
+#define EFI_CERT_SHA256_GUID \
+ { \
+ 0xc1c41626, 0x504c, 0x4092, {0xac, 0xa9, 0x41, 0xf9, 0x36, 0x93, 0x43, 0x28} \
+ }
+
+///
+/// This identifies a signature containing an RSA-2048 key. The key (only the modulus
+/// since the public key exponent is known to be 0x10001) shall be stored in big-endian
+/// order.
+/// The SignatureHeader size shall always be 0. The SignatureSize shall always be 16 (size
+/// of SignatureOwner component) + 256 bytes.
+///
+#define EFI_CERT_RSA2048_GUID \
+ { \
+ 0x3c5766e8, 0x269c, 0x4e34, {0xaa, 0x14, 0xed, 0x77, 0x6e, 0x85, 0xb3, 0xb6} \
+ }
+
+///
+/// This identifies a signature containing a RSA-2048 signature of a SHA-256 hash. The
+/// SignatureHeader size shall always be 0. The SignatureSize shall always be 16 (size of
+/// SignatureOwner component) + 256 bytes.
+///
+#define EFI_CERT_RSA2048_SHA256_GUID \
+ { \
+ 0xe2b36190, 0x879b, 0x4a3d, {0xad, 0x8d, 0xf2, 0xe7, 0xbb, 0xa3, 0x27, 0x84} \
+ }
+
+///
+/// This identifies a signature containing a SHA-1 hash. The SignatureSize shall always
+/// be 16 (size of SignatureOwner component) + 20 bytes.
+///
+#define EFI_CERT_SHA1_GUID \
+ { \
+ 0x826ca512, 0xcf10, 0x4ac9, {0xb1, 0x87, 0xbe, 0x1, 0x49, 0x66, 0x31, 0xbd} \
+ }
+
+///
+/// TThis identifies a signature containing a RSA-2048 signature of a SHA-1 hash. The
+/// SignatureHeader size shall always be 0. The SignatureSize shall always be 16 (size of
+/// SignatureOwner component) + 256 bytes.
+///
+#define EFI_CERT_RSA2048_SHA1_GUID \
+ { \
+ 0x67f8444f, 0x8743, 0x48f1, {0xa3, 0x28, 0x1e, 0xaa, 0xb8, 0x73, 0x60, 0x80} \
+ }
+
+///
+/// This identifies a signature based on an X.509 certificate. If the signature is an X.509
+/// certificate then verification of the signature of an image should validate the public
+/// key certificate in the image using certificate path verification, up to this X.509
+/// certificate as a trusted root. The SignatureHeader size shall always be 0. The
+/// SignatureSize may vary but shall always be 16 (size of the SignatureOwner component) +
+/// the size of the certificate itself.
+/// Note: This means that each certificate will normally be in a separate EFI_SIGNATURE_LIST.
+///
+#define EFI_CERT_X509_GUID \
+ { \
+ 0xa5c059a1, 0x94e4, 0x4aa7, {0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72} \
+ }
+
+///
+/// This identifies a signature containing a SHA-224 hash. The SignatureHeader size shall
+/// always be 0. The SignatureSize shall always be 16 (size of SignatureOwner component) +
+/// 28 bytes.
+///
+#define EFI_CERT_SHA224_GUID \
+ { \
+ 0xb6e5233, 0xa65c, 0x44c9, {0x94, 0x7, 0xd9, 0xab, 0x83, 0xbf, 0xc8, 0xbd} \
+ }
+
+///
+/// This identifies a signature containing a SHA-384 hash. The SignatureHeader size shall
+/// always be 0. The SignatureSize shall always be 16 (size of SignatureOwner component) +
+/// 48 bytes.
+///
+#define EFI_CERT_SHA384_GUID \
+ { \
+ 0xff3e5307, 0x9fd0, 0x48c9, {0x85, 0xf1, 0x8a, 0xd5, 0x6c, 0x70, 0x1e, 0x1} \
+ }
+
+///
+/// This identifies a signature containing a SHA-512 hash. The SignatureHeader size shall
+/// always be 0. The SignatureSize shall always be 16 (size of SignatureOwner component) +
+/// 64 bytes.
+///
+#define EFI_CERT_SHA512_GUID \
+ { \
+ 0x93e0fae, 0xa6c4, 0x4f50, {0x9f, 0x1b, 0xd4, 0x1e, 0x2b, 0x89, 0xc1, 0x9a} \
+ }
+
+///
+/// This identifies a signature containing the SHA256 hash of an X.509 certificate's
+/// To-Be-Signed contents, and a time of revocation. The SignatureHeader size shall
+/// always be 0. The SignatureSize shall always be 16 (size of the SignatureOwner component)
+/// + 48 bytes for an EFI_CERT_X509_SHA256 structure. If the TimeOfRevocation is non-zero,
+/// the certificate should be considered to be revoked from that time and onwards, and
+/// otherwise the certificate shall be considered to always be revoked.
+///
+#define EFI_CERT_X509_SHA256_GUID \
+ { \
+ 0x3bd2a492, 0x96c0, 0x4079, {0xb4, 0x20, 0xfc, 0xf9, 0x8e, 0xf1, 0x03, 0xed } \
+ }
+
+///
+/// This identifies a signature containing the SHA384 hash of an X.509 certificate's
+/// To-Be-Signed contents, and a time of revocation. The SignatureHeader size shall
+/// always be 0. The SignatureSize shall always be 16 (size of the SignatureOwner component)
+/// + 64 bytes for an EFI_CERT_X509_SHA384 structure. If the TimeOfRevocation is non-zero,
+/// the certificate should be considered to be revoked from that time and onwards, and
+/// otherwise the certificate shall be considered to always be revoked.
+///
+#define EFI_CERT_X509_SHA384_GUID \
+ { \
+ 0x7076876e, 0x80c2, 0x4ee6, {0xaa, 0xd2, 0x28, 0xb3, 0x49, 0xa6, 0x86, 0x5b } \
+ }
+
+///
+/// This identifies a signature containing the SHA512 hash of an X.509 certificate's
+/// To-Be-Signed contents, and a time of revocation. The SignatureHeader size shall
+/// always be 0. The SignatureSize shall always be 16 (size of the SignatureOwner component)
+/// + 80 bytes for an EFI_CERT_X509_SHA512 structure. If the TimeOfRevocation is non-zero,
+/// the certificate should be considered to be revoked from that time and onwards, and
+/// otherwise the certificate shall be considered to always be revoked.
+///
+#define EFI_CERT_X509_SHA512_GUID \
+ { \
+ 0x446dbf63, 0x2502, 0x4cda, {0xbc, 0xfa, 0x24, 0x65, 0xd2, 0xb0, 0xfe, 0x9d } \
+ }
+
+///
+/// This identifies a signature containing a DER-encoded PKCS #7 version 1.5 [RFC2315]
+/// SignedData value.
+///
+#define EFI_CERT_TYPE_PKCS7_GUID \
+ { \
+ 0x4aafd29d, 0x68df, 0x49ee, {0x8a, 0xa9, 0x34, 0x7d, 0x37, 0x56, 0x65, 0xa7} \
+ }
+
+//***********************************************************************
+// Image Execution Information Table Definition
+//***********************************************************************
+typedef UINT32 EFI_IMAGE_EXECUTION_ACTION;
+
+#define EFI_IMAGE_EXECUTION_AUTHENTICATION 0x00000007
+#define EFI_IMAGE_EXECUTION_AUTH_UNTESTED 0x00000000
+#define EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED 0x00000001
+#define EFI_IMAGE_EXECUTION_AUTH_SIG_PASSED 0x00000002
+#define EFI_IMAGE_EXECUTION_AUTH_SIG_NOT_FOUND 0x00000003
+#define EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND 0x00000004
+#define EFI_IMAGE_EXECUTION_POLICY_FAILED 0x00000005
+#define EFI_IMAGE_EXECUTION_INITIALIZED 0x00000008
+
+//
+// EFI_IMAGE_EXECUTION_INFO is added to EFI System Configuration Table
+// and assigned the GUID EFI_IMAGE_SECURITY_DATABASE_GUID.
+//
+typedef struct {
+ ///
+ /// Describes the action taken by the firmware regarding this image.
+ ///
+ EFI_IMAGE_EXECUTION_ACTION Action;
+ ///
+ /// Size of all of the entire structure.
+ ///
+ UINT32 InfoSize;
+ ///
+ /// If this image was a UEFI device driver (for option ROM, for example) this is the
+ /// null-terminated, user-friendly name for the device. If the image was for an application,
+ /// then this is the name of the application. If this cannot be determined, then a simple
+ /// NULL character should be put in this position.
+ /// CHAR16 Name[];
+ ///
+
+ ///
+ /// For device drivers, this is the device path of the device for which this device driver
+ /// was intended. In some cases, the driver itself may be stored as part of the system
+ /// firmware, but this field should record the device's path, not the firmware path. For
+ /// applications, this is the device path of the application. If this cannot be determined,
+ /// a simple end-of-path device node should be put in this position.
+ /// EFI_DEVICE_PATH_PROTOCOL DevicePath;
+ ///
+
+ ///
+ /// Zero or more image signatures. If the image contained no signatures,
+ /// then this field is empty.
+ /// EFI_SIGNATURE_LIST Signature;
+ ///
+} EFI_IMAGE_EXECUTION_INFO;
+
+
+typedef struct {
+ ///
+ /// Number of EFI_IMAGE_EXECUTION_INFO structures.
+ ///
+ UINTN NumberOfImages;
+ ///
+ /// Number of image instances of EFI_IMAGE_EXECUTION_INFO structures.
+ ///
+ // EFI_IMAGE_EXECUTION_INFO InformationInfo[]
+} EFI_IMAGE_EXECUTION_INFO_TABLE;
+
+extern EFI_GUID gEfiImageSecurityDatabaseGuid;
+extern EFI_GUID gEfiCertSha256Guid;
+extern EFI_GUID gEfiCertRsa2048Guid;
+extern EFI_GUID gEfiCertRsa2048Sha256Guid;
+extern EFI_GUID gEfiCertSha1Guid;
+extern EFI_GUID gEfiCertRsa2048Sha1Guid;
+extern EFI_GUID gEfiCertX509Guid;
+extern EFI_GUID gEfiCertSha224Guid;
+extern EFI_GUID gEfiCertSha384Guid;
+extern EFI_GUID gEfiCertSha512Guid;
+extern EFI_GUID gEfiCertX509Sha256Guid;
+extern EFI_GUID gEfiCertX509Sha384Guid;
+extern EFI_GUID gEfiCertX509Sha512Guid;
+extern EFI_GUID gEfiCertPkcs7Guid;
+
+#endif
Index: stand/efi/include/Protocol/Hash.h
===================================================================
--- /dev/null
+++ stand/efi/include/Protocol/Hash.h
@@ -0,0 +1,178 @@
+/* $FreeBSD$ */
+/** @file
+ EFI_HASH_SERVICE_BINDING_PROTOCOL as defined in UEFI 2.0.
+ EFI_HASH_PROTOCOL as defined in UEFI 2.0.
+ The EFI Hash Service Binding Protocol is used to locate hashing services support
+ provided by a driver and to create and destroy instances of the EFI Hash Protocol
+ so that a multiple drivers can use the underlying hashing services.
+
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __EFI_HASH_PROTOCOL_H__
+#define __EFI_HASH_PROTOCOL_H__
+
+#define CONST const
+
+#define EFI_HASH_SERVICE_BINDING_PROTOCOL_GUID \
+ { \
+ 0x42881c98, 0xa4f3, 0x44b0, {0xa3, 0x9d, 0xdf, 0xa1, 0x86, 0x67, 0xd8, 0xcd } \
+ }
+
+#define EFI_HASH_PROTOCOL_GUID \
+ { \
+ 0xc5184932, 0xdba5, 0x46db, {0xa5, 0xba, 0xcc, 0x0b, 0xda, 0x9c, 0x14, 0x35 } \
+ }
+
+#define EFI_HASH_ALGORITHM_SHA1_GUID \
+ { \
+ 0x2ae9d80f, 0x3fb2, 0x4095, {0xb7, 0xb1, 0xe9, 0x31, 0x57, 0xb9, 0x46, 0xb6 } \
+ }
+
+#define EFI_HASH_ALGORITHM_SHA224_GUID \
+ { \
+ 0x8df01a06, 0x9bd5, 0x4bf7, {0xb0, 0x21, 0xdb, 0x4f, 0xd9, 0xcc, 0xf4, 0x5b } \
+ }
+
+#define EFI_HASH_ALGORITHM_SHA256_GUID \
+ { \
+ 0x51aa59de, 0xfdf2, 0x4ea3, {0xbc, 0x63, 0x87, 0x5f, 0xb7, 0x84, 0x2e, 0xe9 } \
+ }
+
+#define EFI_HASH_ALGORITHM_SHA384_GUID \
+ { \
+ 0xefa96432, 0xde33, 0x4dd2, {0xae, 0xe6, 0x32, 0x8c, 0x33, 0xdf, 0x77, 0x7a } \
+ }
+
+#define EFI_HASH_ALGORITHM_SHA512_GUID \
+ { \
+ 0xcaa4381e, 0x750c, 0x4770, {0xb8, 0x70, 0x7a, 0x23, 0xb4, 0xe4, 0x21, 0x30 } \
+ }
+
+#define EFI_HASH_ALGORTIHM_MD5_GUID \
+ { \
+ 0xaf7c79c, 0x65b5, 0x4319, {0xb0, 0xae, 0x44, 0xec, 0x48, 0x4e, 0x4a, 0xd7 } \
+ }
+
+#define EFI_HASH_ALGORITHM_SHA1_NOPAD_GUID \
+ { \
+ 0x24c5dc2f, 0x53e2, 0x40ca, {0x9e, 0xd6, 0xa5, 0xd9, 0xa4, 0x9f, 0x46, 0x3b } \
+ }
+
+#define EFI_HASH_ALGORITHM_SHA256_NOPAD_GUID \
+ { \
+ 0x8628752a, 0x6cb7, 0x4814, {0x96, 0xfc, 0x24, 0xa8, 0x15, 0xac, 0x22, 0x26 } \
+ }
+
+//
+// Note: Use of the following algorithms with EFI_HASH_PROTOCOL is deprecated.
+// EFI_HASH_ALGORITHM_SHA1_GUID
+// EFI_HASH_ALGORITHM_SHA224_GUID
+// EFI_HASH_ALGORITHM_SHA256_GUID
+// EFI_HASH_ALGORITHM_SHA384_GUID
+// EFI_HASH_ALGORITHM_SHA512_GUID
+// EFI_HASH_ALGORTIHM_MD5_GUID
+//
+
+typedef struct _EFI_HASH_PROTOCOL EFI_HASH_PROTOCOL;
+
+typedef UINT8 EFI_MD5_HASH[16];
+typedef UINT8 EFI_SHA1_HASH[20];
+typedef UINT8 EFI_SHA224_HASH[28];
+typedef UINT8 EFI_SHA256_HASH[32];
+typedef UINT8 EFI_SHA384_HASH[48];
+typedef UINT8 EFI_SHA512_HASH[64];
+
+typedef union {
+ EFI_MD5_HASH *Md5Hash;
+ EFI_SHA1_HASH *Sha1Hash;
+ EFI_SHA224_HASH *Sha224Hash;
+ EFI_SHA256_HASH *Sha256Hash;
+ EFI_SHA384_HASH *Sha384Hash;
+ EFI_SHA512_HASH *Sha512Hash;
+} EFI_HASH_OUTPUT;
+
+/**
+ Returns the size of the hash which results from a specific algorithm.
+
+ @param[in] This Points to this instance of EFI_HASH_PROTOCOL.
+ @param[in] HashAlgorithm Points to the EFI_GUID which identifies the algorithm to use.
+ @param[out] HashSize Holds the returned size of the algorithm's hash.
+
+ @retval EFI_SUCCESS Hash size returned successfully.
+ @retval EFI_INVALID_PARAMETER HashSize is NULL or HashAlgorithm is NULL.
+ @retval EFI_UNSUPPORTED The algorithm specified by HashAlgorithm is not supported
+ by this driver.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_HASH_GET_HASH_SIZE)(
+ IN CONST EFI_HASH_PROTOCOL *This,
+ IN CONST EFI_GUID *HashAlgorithm,
+ OUT UINTN *HashSize
+ );
+
+/**
+ Creates a hash for the specified message text.
+
+ @param[in] This Points to this instance of EFI_HASH_PROTOCOL.
+ @param[in] HashAlgorithm Points to the EFI_GUID which identifies the algorithm to use.
+ @param[in] Extend Specifies whether to create a new hash (FALSE) or extend the specified
+ existing hash (TRUE).
+ @param[in] Message Points to the start of the message.
+ @param[in] MessageSize The size of Message, in bytes.
+ @param[in,out] Hash On input, if Extend is TRUE, then this parameter holds a pointer
+ to a pointer to an array containing the hash to extend. If Extend
+ is FALSE, then this parameter holds a pointer to a pointer to a
+ caller-allocated array that will receive the result of the hash
+ computation. On output (regardless of the value of Extend), the
+ array will contain the result of the hash computation.
+
+ @retval EFI_SUCCESS Hash returned successfully.
+ @retval EFI_INVALID_PARAMETER Message or Hash, HashAlgorithm is NULL or MessageSize is 0.
+ MessageSize is not an integer multiple of block size.
+ @retval EFI_UNSUPPORTED The algorithm specified by HashAlgorithm is not supported by this
+ driver. Or, Extend is TRUE, and the algorithm doesn't support extending the hash.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_HASH_HASH)(
+ IN CONST EFI_HASH_PROTOCOL *This,
+ IN CONST EFI_GUID *HashAlgorithm,
+ IN BOOLEAN Extend,
+ IN CONST UINT8 *Message,
+ IN UINT64 MessageSize,
+ IN OUT EFI_HASH_OUTPUT *Hash
+ );
+
+///
+/// This protocol allows creating a hash of an arbitrary message digest
+/// using one or more hash algorithms.
+///
+struct _EFI_HASH_PROTOCOL {
+ EFI_HASH_GET_HASH_SIZE GetHashSize;
+ EFI_HASH_HASH Hash;
+};
+
+extern EFI_GUID gEfiHashServiceBindingProtocolGuid;
+extern EFI_GUID gEfiHashProtocolGuid;
+extern EFI_GUID gEfiHashAlgorithmSha1Guid;
+extern EFI_GUID gEfiHashAlgorithmSha224Guid;
+extern EFI_GUID gEfiHashAlgorithmSha256Guid;
+extern EFI_GUID gEfiHashAlgorithmSha384Guid;
+extern EFI_GUID gEfiHashAlgorithmSha512Guid;
+extern EFI_GUID gEfiHashAlgorithmMD5Guid;
+extern EFI_GUID gEfiHashAlgorithmSha1NoPadGuid;
+extern EFI_GUID gEfiHashAlgorithmSha256NoPadGuid;
+
+#endif
Index: stand/efi/include/efiapi.h
===================================================================
--- stand/efi/include/efiapi.h
+++ stand/efi/include/efiapi.h
@@ -28,6 +28,8 @@
--*/
+#include <Guid/GlobalVariable.h>
+
//
// EFI Specification Revision
//
@@ -210,13 +212,6 @@
);
-//
-// EFI platform varibles
-//
-
-#define EFI_GLOBAL_VARIABLE \
- { 0x8BE4DF61, 0x93CA, 0x11d2, {0xAA, 0x0D, 0x00, 0xE0, 0x98, 0x03, 0x2B, 0x8C} }
-
// Variable attributes
#define EFI_VARIABLE_NON_VOLATILE 0x00000001
#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x00000002
Index: stand/efi/include/efisecureboot.h
===================================================================
--- /dev/null
+++ stand/efi/include/efisecureboot.h
@@ -0,0 +1,38 @@
+/*-
+ * Copyright (c) 2019 Stormshield.
+ * Copyright (c) 2019 Semihalf.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef EFISECUREBOOT_H
+#define EFISECUREBOOT_H
+
+#include <bearssl.h>
+
+int efi_secure_boot_enabled(void);
+br_x509_certificate* efi_secure_boot_get_CAs(size_t *count);
+br_x509_certificate* efi_secure_boot_get_forbidden_CAs(size_t *count);
+int efi_secure_boot_cert_forbidden(const char *cert, size_t length);
+
+#endif /* EFISECUREBOOT_H */
Index: stand/efi/libefi/Makefile
===================================================================
--- stand/efi/libefi/Makefile
+++ stand/efi/libefi/Makefile
@@ -27,6 +27,11 @@
SRCS+= time_event.c
.endif
+.if ${MK_SECUREBOOT} == "yes"
+SRCS+= efisecureboot.c
+CFLAGS+= -DSECURE_BOOT
+.endif
+
# We implement a slightly non-standard %S in that it always takes a
# CHAR16 that's common in UEFI-land instead of a wchar_t. This only
# seems to matter on arm64 where wchar_t defaults to an int instead
Index: stand/efi/libefi/efienv.c
===================================================================
--- stand/efi/libefi/efienv.c
+++ stand/efi/libefi/efienv.c
@@ -49,7 +49,7 @@
return (EFI_OUT_OF_RESOURCES);
dl = *len;
rv = RS->GetVariable(uv, g, &attr, &dl, data);
- if (rv == EFI_SUCCESS)
+ if (rv == EFI_SUCCESS || rv == EFI_BUFFER_TOO_SMALL)
*len = dl;
free(uv);
return (rv);
Index: stand/efi/libefi/efisecureboot.c
===================================================================
--- /dev/null
+++ stand/efi/libefi/efisecureboot.c
@@ -0,0 +1,240 @@
+/*-
+ * Copyright (c) 2019 Stormshield.
+ * Copyright (c) 2019 Semihalf.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stand.h>
+#include <string.h>
+#include <sys/param.h>
+
+#include <efi.h>
+#include <efilib.h>
+#include <efisecureboot.h>
+#include <Guid/ImageAuthentication.h>
+
+#include <bearssl.h>
+
+static EFI_GUID ImageSecurityDatabaseGUID = EFI_IMAGE_SECURITY_DATABASE_GUID;
+
+static EFI_GUID efiCertX509GUID = EFI_CERT_X509_GUID;
+static EFI_GUID efiCertX509Sha256GUID = EFI_CERT_X509_SHA256_GUID;
+static EFI_GUID efiCertX509Sha384GUID = EFI_CERT_X509_SHA384_GUID;
+static EFI_GUID efiCertX509Sha5122UID = EFI_CERT_X509_SHA512_GUID;
+
+int
+efi_secure_boot_enabled(void)
+{
+ UINT8 SecureBoot;
+ UINT8 SetupMode;
+ size_t length;
+ EFI_STATUS status;
+
+ length = sizeof SecureBoot;
+ status = efi_global_getenv("SecureBoot", &SecureBoot, &length);
+ if (status != EFI_SUCCESS) {
+ if (status == EFI_NOT_FOUND)
+ return 0;
+
+ printf("Failed to read \"SecureBoot\" variable\n");
+ return -efi_status_to_errno(status);
+ }
+
+ length = sizeof SecureBoot;
+ status = efi_global_getenv("SetupMode", &SetupMode, &length);
+ if (status != EFI_SUCCESS)
+ SetupMode = 0;
+
+ printf("SecureBoot:%d, SetupMode:%d\n", SecureBoot, SetupMode);
+
+ return (SecureBoot == 1 && SetupMode == 0);
+}
+
+static br_x509_certificate*
+efi_get_certs(const char *name, size_t *count)
+{
+ UINT8 *database;
+ EFI_SIGNATURE_LIST *list;
+ EFI_SIGNATURE_DATA *entry;
+ br_x509_certificate *certs;
+ size_t length;
+ size_t cert_count;
+ EFI_STATUS status;
+
+ database = NULL;
+ length = 0;
+
+ /* Read variable length and allocate proper buffer. */
+ status = efi_getenv(&ImageSecurityDatabaseGUID, name, database, &length);
+ if (status != EFI_BUFFER_TOO_SMALL)
+ return NULL;
+
+ database = malloc(length);
+ if (database == NULL)
+ return NULL;
+
+ status = efi_getenv(&ImageSecurityDatabaseGUID, name, database, &length);
+ if (status != EFI_SUCCESS)
+ return NULL;
+
+ list = (EFI_SIGNATURE_LIST*) database;
+ certs = NULL;
+ cert_count = 0;
+
+ for(;length >= list->SignatureListSize && length > 0;
+ length -= list->SignatureListSize,
+ list = (EFI_SIGNATURE_LIST*)((UINT8*)list + list->SignatureListSize)) {
+ if (memcmp(&efiCertX509GUID, &list->SignatureType,
+ sizeof(EFI_GUID)) != 0) {
+ continue;
+ }
+
+ entry = (EFI_SIGNATURE_DATA*)
+ ((UINT8*)list +
+ sizeof(EFI_SIGNATURE_LIST) +
+ list->SignatureHeaderSize);
+
+ certs = realloc(certs, (cert_count + 1) * sizeof(br_x509_certificate));
+ if (certs == NULL)
+ return NULL;
+
+ certs[cert_count].data_len = list->SignatureSize - sizeof(EFI_GUID);
+ certs[cert_count].data = malloc(certs[cert_count].data_len);
+ if (certs[cert_count].data == NULL)
+ goto fail;
+
+ memcpy(certs[cert_count].data,
+ entry->SignatureData,
+ certs[cert_count].data_len);
+
+ cert_count++;
+ }
+
+ *count = cert_count;
+
+ free(database);
+ return certs;
+
+fail:
+ while (cert_count-- > 0) {
+ free(certs[cert_count].data);
+ free(&certs[cert_count]);
+ }
+
+ free(database);
+ free(certs);
+ return NULL;
+
+}
+
+int
+efi_secure_boot_cert_forbidden(const char *cert, size_t cert_length)
+{
+ UINT8 *database;
+ EFI_SIGNATURE_LIST *list;
+ EFI_SIGNATURE_DATA *entry;
+ size_t length;
+ size_t header_size;
+ size_t digest_size;
+ size_t hash_count;
+ EFI_STATUS status;
+ br_hash_compat_context hash_ctx;
+ const br_hash_class *md;
+ unsigned char digest[br_sha512_SIZE];
+
+ length = 0;
+
+ status = efi_getenv(&ImageSecurityDatabaseGUID, "dbx", database, &length);
+ if (status != EFI_BUFFER_TOO_SMALL) {
+ if (status == EFI_NOT_FOUND)
+ return (0);
+
+ return efi_status_to_errno(status);
+ }
+
+ database = malloc(length);
+ if (database == NULL)
+ return ENOMEM;
+
+ status = efi_getenv(&ImageSecurityDatabaseGUID, "dbx", database, &length);
+ if (status != EFI_SUCCESS)
+ return efi_status_to_errno(status);
+
+ list = (EFI_SIGNATURE_LIST*) database;
+ for(;length >= list->SignatureListSize && length > 0;
+ length -= list->SignatureListSize,
+ list = (EFI_SIGNATURE_LIST*)((UINT8*)list + list->SignatureListSize)) {
+ if (memcmp(&efiCertX509Sha256GUID, &list->SignatureType,
+ sizeof(EFI_GUID)) == 0) {
+ md = &br_sha256_vtable;
+ digest_size = br_sha256_SIZE;
+ } else if(memcmp(&efiCertX509Sha384GUID, &list->SignatureType,
+ sizeof(EFI_GUID)) == 0) {
+ md = &br_sha384_vtable;
+ digest_size = br_sha384_SIZE;
+ } else if(memcmp(&efiCertX509Sha5122UID, &list->SignatureType,
+ sizeof(EFI_GUID)) == 0) {
+ md = &br_sha512_vtable;
+ digest_size = br_sha512_SIZE;
+ } else {
+ continue;
+ }
+
+ md->init(&hash_ctx.vtable);
+ md->update(&hash_ctx.vtable, cert, cert_length);
+ md->out(&hash_ctx.vtable, digest);
+
+ header_size = sizeof(EFI_SIGNATURE_LIST) + list->SignatureHeaderSize;
+
+ hash_count = list->SignatureListSize - header_size;
+ hash_count /= list->SignatureSize;
+
+ entry = (EFI_SIGNATURE_DATA*)((UINT8*)list + header_size);
+ while (hash_count-- > 0) {
+ if (memcmp(digest, entry->SignatureData, digest_size) == 0)
+ return EACCES;
+
+ entry = (EFI_SIGNATURE_DATA*)(entry + list->SignatureSize);
+ }
+ }
+
+ return 0;
+}
+
+/* Copy x509 certificates from db */
+br_x509_certificate*
+efi_secure_boot_get_CAs(size_t *count)
+{
+ return efi_get_certs("db", count);
+}
+
+/* Copy forbidden certificates from dbx */
+br_x509_certificate*
+efi_secure_boot_get_forbidden_CAs(size_t *count)
+{
+ return efi_get_certs("dbx", count);
+}
Index: stand/efi/loader/Makefile
===================================================================
--- stand/efi/loader/Makefile
+++ stand/efi/loader/Makefile
@@ -36,6 +36,11 @@
CWARNFLAGS.self_reloc.c+= -Wno-error=maybe-uninitialized
.endif
+.if ${MK_SECUREBOOT} == "yes"
+SRCS+= verify.c
+CFLAGS+= -DSECURE_BOOT
+.endif
+
# We implement a slightly non-standard %S in that it always takes a
# CHAR16 that's common in UEFI-land instead of a wchar_t. This only
# seems to matter on arm64 where wchar_t defaults to an int instead
Index: stand/efi/loader/main.c
===================================================================
--- stand/efi/loader/main.c
+++ stand/efi/loader/main.c
@@ -43,6 +43,9 @@
#include <efi.h>
#include <efilib.h>
#include <efichar.h>
+#ifdef SECURE_BOOT
+#include <efisecureboot.h>
+#endif
#include <uuid.h>
@@ -766,6 +769,12 @@
/* Note this needs to be set before ZFS init. */
archsw.arch_zfs_probe = efi_zfs_probe;
#endif
+#ifdef SECURE_BOOT
+ archsw.secure_boot_enabled = efi_secure_boot_enabled;
+ archsw.secure_boot_get_CAs = efi_secure_boot_get_CAs;
+ archsw.secure_boot_get_forbidden_CAs = efi_secure_boot_get_forbidden_CAs;
+ archsw.secure_boot_cert_forbidden = efi_secure_boot_cert_forbidden;
+#endif
/* Get our loaded image protocol interface structure. */
BS->HandleProtocol(IH, &imgid, (VOID**)&img);
Index: stand/libsa/Makefile
===================================================================
--- stand/libsa/Makefile
+++ stand/libsa/Makefile
@@ -169,4 +169,9 @@
.include "${SASRC}/zfs/Makefile.inc"
.endif
+.if ${MK_SECUREBOOT} == "yes"
+.include "${SRCTOP}/lib/libbearssl/Makefile.libsa.inc"
+.include "${SRCTOP}/lib/libsecureboot/Makefile.libsa.inc"
+.endif
+
.include <bsd.lib.mk>
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Apr 16, 10:29 AM (12 h, 50 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31596142
Default Alt Text
D18798.id.diff (48 KB)
Attached To
Mode
D18798: Implement Secure Boot in loader.
Attached
Detach File
Event Timeline
Log In to Comment