Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F136123317
D19093.id53645.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
51 KB
Referenced Files
None
Subscribers
None
D19093.id53645.diff
View Options
Index: lib/libsecureboot/Makefile.inc
===================================================================
--- lib/libsecureboot/Makefile.inc
+++ lib/libsecureboot/Makefile.inc
@@ -104,11 +104,11 @@
vets.o vets.po vets.pico: ta.h
ta.h: ${.ALLTARGETS:M[tv]*pem:O:u}
@( echo '/* Autogenerated - DO NOT EDIT!!! */'; echo; \
- cat ${.ALLSRC:N*crl*:Mt*.pem} /dev/null | \
+ cat ${.ALLSRC:N*crl*:M*/t*.pem} /dev/null | \
file2c -sx 'static const char ta_PEM[] = {' '};'; \
echo "${.newline}${VE_HASH_LIST:@H@static char vh_$H[] = \"`cat ${.ALLSRC:N*crl*:Mv*.pem} | ${$H:U${H:tl}}`\";${.newline}@}"; ) > ${.TARGET}
.if ${VE_SELF_TESTS} != "no"
- ( cat ${.ALLSRC:N*crl*:Mv*.pem} /dev/null | \
+ ( cat ${.ALLSRC:N*crl*:M*/v*.pem} /dev/null | \
file2c -sx 'static const char vc_PEM[] = {' '};'; echo ) >> ${.TARGET}
.endif
.if !empty(BUILD_UTC_FILE)
Index: lib/libsecureboot/Makefile.libsa.inc
===================================================================
--- lib/libsecureboot/Makefile.libsa.inc
+++ lib/libsecureboot/Makefile.libsa.inc
@@ -16,6 +16,17 @@
vepcr.c \
verify_file.c \
+# Build library with support for the UEFI based authentication
+.if ${MK_LOADER_EFI_SECUREBOOT} == "yes"
+SRCS+= efi/efi_variables.c \
+ efi/efi_init.c \
+
+# Add includes required by efi part
+CFLAGS+= -I${SRCTOP}/stand/efi/include \
+ -I${SRCTOP}/lib/libsecureboot/efi/include \
+ -I${SRCTOP}/stand/efi/include/${MACHINE}
+.endif
+
# this is the list of paths (relative to a file
# that we need to verify) used to find a signed manifest.
# the signature extensions in VE_SIGNATURE_EXT_LIST
Index: lib/libsecureboot/efi/efi_init.c
===================================================================
--- /dev/null
+++ lib/libsecureboot/efi/efi_init.c
@@ -0,0 +1,79 @@
+/*-
+ * Copyright (c) 2019 Stormshield.
+ * Copyright (c) 2019 Semihalf.
+ *
+ * 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.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "../libsecureboot-priv.h"
+
+void
+ve_efi_init(void)
+{
+ br_x509_certificate *xcs;
+ hash_data *digests;
+ size_t num;
+ int result;
+ static int once = 0;
+
+ if (once)
+ return;
+
+ once = 1;
+
+ result = efi_secure_boot_enabled();
+ if (result <= 0)
+ return;
+
+ xcs = efi_get_trusted_certs(&num);
+ if (num > 0 && xcs != NULL) {
+ num = ve_trust_anchors_add(xcs, num);
+ while(num--)
+ xfree(xcs[num].data);
+
+ xfree(xcs);
+ }
+ xcs = efi_get_forbidden_certs(&num);
+ if (num > 0 && xcs != NULL) {
+ num = ve_forbidden_anchors_add(xcs, num);
+ while(num--)
+ xfree(xcs[num].data);
+
+ xfree(xcs);
+ }
+ digests = efi_get_forbidden_digests(&num);
+ if (num > 0 && digests != NULL) {
+ ve_forbidden_digest_add(digests, num);
+ /*
+ * Don't free the buffors for digests,
+ * since they are shallow copied.
+ */
+ xfree(digests);
+ }
+
+ return;
+}
Index: lib/libsecureboot/efi/efi_variables.c
===================================================================
--- /dev/null
+++ lib/libsecureboot/efi/efi_variables.c
@@ -0,0 +1,262 @@
+/*-
+ * Copyright (c) 2019 Stormshield.
+ * Copyright (c) 2019 Semihalf.
+ *
+ * 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.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stand.h>
+#include <string.h>
+
+#include <efi.h>
+#include <efilib.h>
+#include <Guid/ImageAuthentication.h>
+
+#include "../libsecureboot-priv.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(SetupMode);
+ 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)
+{
+ br_x509_certificate *certs;
+ UINT8 *database;
+ EFI_SIGNATURE_LIST *list;
+ EFI_SIGNATURE_DATA *entry;
+ size_t length;
+ ssize_t cert_count;
+ EFI_STATUS status;
+
+ database = NULL;
+ certs = NULL;
+ length = 0;
+ cert_count = 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)
+ goto fail;
+
+
+ for (list = (EFI_SIGNATURE_LIST*) database;
+ 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) {
+ cert_count = 0;
+ goto fail;
+ }
+
+ 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;
+
+ xfree(database);
+ return (certs);
+
+fail:
+ while (cert_count-- > 0)
+ xfree(certs[cert_count].data);
+
+ xfree(database);
+ xfree(certs);
+ return (NULL);
+
+}
+
+hash_data*
+efi_get_forbidden_digests(size_t *count)
+{
+ UINT8 *database;
+ hash_data *digests;
+ EFI_SIGNATURE_LIST *list;
+ EFI_SIGNATURE_DATA *entry;
+ size_t length;
+ size_t header_size;
+ size_t digest_size;
+ size_t digest_count;
+ size_t entry_count;
+ EFI_STATUS status;
+
+ length = 0;
+ digest_count = 0;
+ database = NULL;
+ digests = NULL;
+
+ status = efi_getenv(&ImageSecurityDatabaseGUID, "dbx", database, &length);
+ if (status != EFI_BUFFER_TOO_SMALL)
+ return (NULL);
+
+ database = malloc(length);
+ if (database == NULL)
+ return (NULL);
+
+ status = efi_getenv(&ImageSecurityDatabaseGUID, "dbx", database, &length);
+ if (status != EFI_SUCCESS)
+ goto fail;
+
+
+ for(list = (EFI_SIGNATURE_LIST*) database;
+ 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) {
+ digest_size = br_sha256_SIZE;
+ } else if(memcmp(&efiCertX509Sha384GUID, &list->SignatureType,
+ sizeof(EFI_GUID)) == 0) {
+ digest_size = br_sha384_SIZE;
+ } else if(memcmp(&efiCertX509Sha5122UID, &list->SignatureType,
+ sizeof(EFI_GUID)) == 0) {
+ digest_size = br_sha512_SIZE;
+ } else {
+ continue;
+ }
+
+ header_size = sizeof(EFI_SIGNATURE_LIST) + list->SignatureHeaderSize;
+
+ entry_count = list->SignatureListSize - header_size;
+ entry_count /= list->SignatureSize;
+
+ entry = (EFI_SIGNATURE_DATA*)((UINT8*)list + header_size);
+ while (entry_count-- > 0) {
+ digests = realloc(digests,
+ (digest_count + 1) * sizeof(hash_data));
+ if (digests == NULL) {
+ digest_count = 0;
+ goto fail;
+ }
+
+ digests[digest_count].data = malloc(digest_size);
+ if (digests[digest_count].data == NULL)
+ goto fail;
+
+ memcpy(digests[digest_count].data,
+ entry->SignatureData,
+ digest_size);
+ digests[digest_count].digest_size = digest_size;
+
+ entry = (EFI_SIGNATURE_DATA*)(entry + list->SignatureSize);
+ digest_count++;
+ }
+ }
+ xfree(database);
+ if (count != NULL)
+ *count = digest_count;
+
+ return (digests);
+
+fail:
+ while(digest_count--)
+ xfree(digests[digest_count].data);
+
+ xfree(database);
+ xfree(digests);
+ return (NULL);
+}
+
+/* Copy x509 certificates from db */
+br_x509_certificate*
+efi_get_trusted_certs(size_t *count)
+{
+ return (efi_get_certs("db", count));
+}
+
+/* Copy forbidden certificates from dbx */
+br_x509_certificate*
+efi_get_forbidden_certs(size_t *count)
+{
+ return (efi_get_certs("dbx", count));
+}
Index: lib/libsecureboot/efi/include/Guid/GlobalVariable.h
===================================================================
--- /dev/null
+++ lib/libsecureboot/efi/include/Guid/GlobalVariable.h
@@ -0,0 +1,191 @@
+/** @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__
+
+#ifndef EFI_GLOBAL_VARIABLE
+#define EFI_GLOBAL_VARIABLE \
+ { \
+ 0x8BE4DF61, 0x93CA, 0x11d2, {0xAA, 0x0D, 0x00, 0xE0, 0x98, 0x03, 0x2B, 0x8C } \
+ }
+#endif /* EFI_GLOBAL_VARIABLE */
+
+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: lib/libsecureboot/efi/include/Guid/ImageAuthentication.h
===================================================================
--- /dev/null
+++ lib/libsecureboot/efi/include/Guid/ImageAuthentication.h
@@ -0,0 +1,349 @@
+/** @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: lib/libsecureboot/efi/include/Protocol/Hash.h
===================================================================
--- /dev/null
+++ lib/libsecureboot/efi/include/Protocol/Hash.h
@@ -0,0 +1,168 @@
+/** @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: lib/libsecureboot/h/verify_file.h
===================================================================
--- lib/libsecureboot/h/verify_file.h
+++ lib/libsecureboot/h/verify_file.h
@@ -25,6 +25,8 @@
#ifndef _VERIFY_FILE_H_
#define _VERIFY_FILE_H_
+#include <sys/stat.h>
+
#define VE_GUESS -1 /* let verify_file work it out */
#define VE_TRY 0 /* we don't mind if unverified */
#define VE_WANT 1 /* we want this verified */
@@ -36,6 +38,7 @@
void ve_debug_set(int);
int ve_status_get(int);
+void ve_efi_init(void);
int load_manifest(const char *, const char *, const char *, struct stat *);
int verify_file(int, const char *, off_t, int);
void verify_pcr_export(void);
Index: lib/libsecureboot/libsecureboot-priv.h
===================================================================
--- lib/libsecureboot/libsecureboot-priv.h
+++ lib/libsecureboot/libsecureboot-priv.h
@@ -30,8 +30,16 @@
/* public api */
#include "libsecureboot.h"
+#include <brssl.h>
+
+typedef struct {
+ unsigned char *data;
+ int digest_size;
+} hash_data;
size_t ve_trust_anchors_add(br_x509_certificate *, size_t);
+size_t ve_forbidden_anchors_add(br_x509_certificate *, size_t);
+void ve_forbidden_digest_add(hash_data *digest, size_t);
char *fingerprint_info_lookup(int, const char *);
br_x509_certificate * parse_certificates(unsigned char *, size_t, size_t *);
@@ -45,4 +53,9 @@
int openpgp_self_tests(void);
+int efi_secure_boot_enabled(void);
+br_x509_certificate* efi_get_trusted_certs(size_t *count);
+br_x509_certificate* efi_get_forbidden_certs(size_t *count);
+hash_data* efi_get_forbidden_digests(size_t *count);
+
#endif /* _LIBSECUREBOOT_PRIV_H_ */
Index: lib/libsecureboot/local.trust.mk
===================================================================
--- lib/libsecureboot/local.trust.mk
+++ lib/libsecureboot/local.trust.mk
@@ -7,14 +7,16 @@
# for each key will provide the appropriate certificate chain on request
# force these for Junos
-MANIFEST_SKIP_ALWAYS= boot
+#MANIFEST_SKIP_ALWAYS= boot
VE_HASH_LIST= \
SHA1 \
SHA256 \
- SHA384
+ SHA384 \
+ SHA512
VE_SIGNATURE_LIST= \
- ECDSA
+ ECDSA \
+ RSA
VE_SIGNATURE_EXT_LIST= \
esig
@@ -22,9 +24,6 @@
VE_SELF_TESTS= yes
.if ${MACHINE} == "host" && ${.CURDIR:T} == "tests"
-# for testing
-VE_HASH_LIST+= \
- SHA512
VE_SIGNATURE_LIST+= \
RSA \
@@ -88,14 +87,14 @@
.endif
# we take the mtime of this as our baseline time
-BUILD_UTC_FILE= ecerts.pem
+#BUILD_UTC_FILE= ecerts.pem
.else
# you need to provide t*.pem or t*.asc files for each trust anchor
.if empty(TRUST_ANCHORS)
-TRUST_ANCHORS!= cd ${.CURDIR} && 'ls' -1 *.pem t*.asc 2> /dev/null
+TRUST_ANCHORS!= 'ls' -1 ${.CURDIR}/*.pem ${.CURDIR}/t*.asc 2> /dev/null
.endif
-.if empty(TRUST_ANCHORS)
+.if empty(TRUST_ANCHORS) && ${MK_LOADER_EFI_SECUREBOOT} != "yes"
.error Need TRUST_ANCHORS see ${.CURDIR}/README.rst
.endif
.if ${TRUST_ANCHORS:T:Mt*.pem} != ""
Index: lib/libsecureboot/verify_file.c
===================================================================
--- lib/libsecureboot/verify_file.c
+++ lib/libsecureboot/verify_file.c
@@ -126,7 +126,6 @@
verified_files = vsp;
}
-
/**
* @brief
* load specified manifest if verified
@@ -193,16 +192,19 @@
#ifdef MANIFEST_SKIP_ALWAYS
skip = MANIFEST_SKIP_ALWAYS;
#else
- if (*tp[0] == '.') {
+ if (!strncmp("../", *tp, 3)) {
#ifdef MANIFEST_SKIP
skip = MANIFEST_SKIP;
#else
- if ((skip = strrchr(prefix, '/')))
- skip++;
+ if ((skip = strrchr(prefix, '/'))) {
+ *skip = '\0';
+ skip = NULL;
+ }
#endif
} else
skip = NULL;
#endif
+
rc = load_manifest(buf, prefix, skip, &st);
break;
}
@@ -318,8 +320,9 @@
return (0);
DEBUG_PRINTF(3, ("fd=%d,name='%s',off=%lld,dev=%lld,ino=%lld\n",
- fd, filename, (long long)off, st.st_dev,st.st_ino));
-
+ fd, filename, (long long)off,
+ (long long)st.st_dev, (long long)st.st_ino));
+
rc = is_verified(&st);
if (rc != VE_NOT_CHECKED) {
@@ -334,13 +337,12 @@
if (verbose || severity > VE_WANT) {
#if defined(VE_DEBUG_LEVEL) && VE_DEBUG_LEVEL > 0
printf("Verified %s %llu,%llu\n", filename,
- st.st_dev, st.st_ino);
+ (long long)st.st_dev, (long long)st.st_ino);
#else
printf("Verified %s\n", filename);
#endif
}
if (severity < VE_MUST) { /* not a kernel or module */
-
if ((cp = strrchr(filename, '/'))) {
cp++;
if (strncmp(cp, "loader.ve.", 10) == 0) {
Index: lib/libsecureboot/vets.c
===================================================================
--- lib/libsecureboot/vets.c
+++ lib/libsecureboot/vets.c
@@ -49,8 +49,11 @@
int DebugVe = 0;
typedef VECTOR(br_x509_certificate) cert_list;
+typedef VECTOR(hash_data) digest_list;
static anchor_list trust_anchors = VEC_INIT;
+static anchor_list forbidden_anchors = VEC_INIT;
+static digest_list forbidden_digests = VEC_INIT;
void
ve_debug_set(int n)
@@ -113,12 +116,77 @@
xfree(xc->data);
}
-/**
- * @brief
- * add certs to our trust store
+/* ASN parsing related defines */
+#define ASN1_CONSTRUCTED BIT(5)
+#define ASN1_PRIMITIVE_TAG 0x1F
+#define ASN1_INF_LENGTH 0x80
+#define ASN1_LENGTH_MASK 0x7F
+
+/*
+ * Get TBS part of certificate.
+ * Since BearSSL doesn't provide any API to do this,
+ * it has to be implemented here.
*/
-size_t
-ve_trust_anchors_add(br_x509_certificate *xcs, size_t num)
+static void*
+X509_to_tbs(unsigned char* cert, size_t* output_size)
+{
+ unsigned char *result;
+ size_t tbs_size;
+ int size;
+ int i;
+
+ if (cert == NULL)
+ return (NULL);
+
+ /* Strip two sequences to get to the TBS section */
+ for (i = 0; i < 2; i++) {
+ /*
+ * XXX: We don't need to support extended tags since
+ * they should not be present in certificates.
+ */
+ if ((*cert & ASN1_PRIMITIVE_TAG) == ASN1_PRIMITIVE_TAG)
+ return (NULL);
+
+ cert++;
+
+ if (*cert == ASN1_INF_LENGTH)
+ return (NULL);
+
+ size = *cert & ASN1_LENGTH_MASK;
+ tbs_size = 0;
+
+ /* Size can either be stored on a single or multiple bytes */
+ if (*cert & (ASN1_LENGTH_MASK + 1)) {
+ cert++;
+ while (*cert == 0 && size > 0) {
+ cert++;
+ size--;
+ }
+ while(size-- > 0) {
+ tbs_size <<= 8;
+ tbs_size |= *(cert++);
+ }
+ }
+ if (i == 0)
+ result = cert;
+ }
+ tbs_size += (cert - result);
+
+ if (output_size != NULL)
+ *output_size = tbs_size;
+
+ return (result);
+}
+
+void
+ve_forbidden_digest_add(hash_data *digest, size_t num)
+{
+ while (num--)
+ VEC_ADD(forbidden_digests, digest[num]);
+}
+
+static size_t
+ve_anchors_add(br_x509_certificate *xcs, size_t num, anchor_list *anchors)
{
br_x509_trust_anchor ta;
size_t u;
@@ -127,11 +195,27 @@
if (certificate_to_trust_anchor_inner(&ta, &xcs[u]) < 0) {
break;
}
- VEC_ADD(trust_anchors, ta);
+ VEC_ADD(*anchors, ta);
}
return (u);
}
+/**
+ * @brief
+ * add certs to our trust store
+ */
+size_t
+ve_trust_anchors_add(br_x509_certificate *xcs, size_t num)
+{
+ return (ve_anchors_add(xcs, num, &trust_anchors));
+}
+
+size_t
+ve_forbidden_anchors_add(br_x509_certificate *xcs, size_t num)
+{
+ return (ve_anchors_add(xcs, num, &forbidden_anchors));
+}
+
/**
* @brief
* initialize our trust_anchors from ta_PEM
@@ -139,13 +223,14 @@
int
ve_trust_init(void)
{
+#ifdef TRUST_ANCHOR_STR
br_x509_certificate *xcs;
+#endif
static int once = -1;
size_t num;
if (once >= 0)
return (once);
- once = 0;
ve_utc_set(time(NULL));
#ifdef BUILD_UTC
@@ -159,14 +244,15 @@
#ifdef TRUST_ANCHOR_STR
xcs = parse_certificates(__DECONST(unsigned char *, TRUST_ANCHOR_STR),
sizeof(TRUST_ANCHOR_STR), &num);
- if (xcs == NULL)
- return (0);
+ if (xcs == NULL) {
+ once = (int) VEC_LEN(trust_anchors);
+ return (once);
+ }
num = ve_trust_anchors_add(xcs, num);
- once = (int) num;
-#else
- num = 0;
#endif
- return (num);
+ once = (int) VEC_LEN(trust_anchors);
+
+ return (once);
}
/**
@@ -177,7 +263,8 @@
static br_x509_pkey *
verify_signer_xcs(br_x509_certificate *xcs,
size_t num,
- br_name_element *elts, size_t num_elts)
+ br_name_element *elts, size_t num_elts,
+ anchor_list *anchors)
{
br_x509_minimal_context mc;
br_x509_certificate *xc;
@@ -196,11 +283,11 @@
}
DEBUG_PRINTF(5, ("verify_signer: %zu trust anchors\n",
- VEC_LEN(trust_anchors)));
+ VEC_LEN(*anchors)));
br_x509_minimal_init(&mc, &br_sha256_vtable,
- &VEC_ELT(trust_anchors, 0),
- VEC_LEN(trust_anchors));
+ &VEC_ELT(*anchors, 0),
+ VEC_LEN(*anchors));
#ifdef VE_ECDSA_SUPPORT
br_x509_minimal_set_ecdsa(&mc,
&br_ec_prime_i31, &br_ecdsa_i31_vrfy_asn1);
@@ -255,10 +342,72 @@
pk = xpkeydup(tpk);
}
}
- VEC_CLEAREXT(chain, &free_cert_contents);
+ VEC_CLEAR(chain);
return (pk);
}
+static int
+check_forbidden_digests(br_x509_certificate *xcs, size_t num)
+{
+ unsigned char sha256_digest[br_sha256_SIZE];
+ unsigned char sha384_digest[br_sha384_SIZE];
+ unsigned char sha512_digest[br_sha512_SIZE];
+ void *tbs_cert;
+ hash_data *digest;
+ br_hash_compat_context ctx;
+ const br_hash_class *md;
+ size_t tbs_size;
+ size_t i;
+
+ if (VEC_LEN(forbidden_digests) == 0)
+ return (0);
+
+ while (num--) {
+ tbs_cert = X509_to_tbs(xcs[num].data, &tbs_size);
+
+ md = &br_sha256_vtable;
+ md->init(&ctx.vtable);
+ md->update(&ctx.vtable, tbs_cert, tbs_size);
+ md->out(&ctx.vtable, sha256_digest);
+
+ md = &br_sha384_vtable;
+ md->init(&ctx.vtable);
+ md->update(&ctx.vtable, tbs_cert, tbs_size);
+ md->out(&ctx.vtable, sha384_digest);
+
+ md = &br_sha512_vtable;
+ md->init(&ctx.vtable);
+ md->update(&ctx.vtable, tbs_cert, tbs_size);
+ md->out(&ctx.vtable, sha512_digest);
+
+ for (i = 0; i < VEC_LEN(forbidden_digests); i++) {
+ digest = &VEC_ELT(forbidden_digests, i);
+ switch (digest->digest_size) {
+ case br_sha256_SIZE:
+ if (!memcmp(sha256_digest,
+ digest->data,
+ br_sha256_SIZE))
+ return (1);
+ break;
+ case br_sha384_SIZE:
+ if (!memcmp(sha384_digest,
+ digest->data,
+ br_sha384_SIZE))
+ return (1);
+ break;
+ case br_sha512_SIZE:
+ if (!memcmp(sha512_digest,
+ digest->data,
+ br_sha512_SIZE))
+ return (1);
+ break;
+ }
+ }
+ }
+
+ return (0);
+}
+
static br_x509_pkey *
verify_signer(const char *certs,
br_name_element *elts, size_t num_elts)
@@ -266,14 +415,44 @@
br_x509_certificate *xcs;
br_x509_pkey *pk;
size_t num;
-
+
+ pk = NULL;
+
ve_trust_init();
xcs = read_certificates(certs, &num);
if (xcs == NULL) {
ve_error_set("cannot read certificates\n");
return (NULL);
}
- pk = verify_signer_xcs(xcs, num, elts, num_elts);
+ /*
+ * Check if hash of tbs part of any certificate in chain
+ * is on the forbidden list.
+ */
+ if (check_forbidden_digests(xcs, num)) {
+ ve_error_set("Certificate hash is on forbidden list\n");
+ goto out;
+ }
+ /*
+ * Check if either
+ * 1. There is a direct match between cert from forbidden_anchors
+ * and a cert from chain.
+ * 2. CA that signed the chain is found in forbidden_anchors.
+ */
+ if (VEC_LEN(forbidden_anchors) > 0)
+ pk = verify_signer_xcs(xcs, num, elts, num_elts, &forbidden_anchors);
+ if (pk != NULL) {
+ ve_error_set("Certificate is on forbidden list\n");
+ xfreepkey(pk);
+ pk = NULL;
+ goto out;
+ }
+
+ pk = verify_signer_xcs(xcs, num, elts, num_elts, &trust_anchors);
+
+out:
+ while(num--)
+ free_cert_contents(&xcs[num]);
+
xfree(xcs);
return (pk);
}
@@ -679,7 +858,8 @@
for (u = 0; u < num; u ++) {
cn.len = sizeof(cn_buf);
- if ((pk = verify_signer_xcs(&xcs[u], 1, &cn, 1)) != NULL) {
+ if ((pk = verify_signer_xcs(&xcs[u], 1, &cn, 1, &trust_anchors)) != NULL) {
+ free_cert_contents(&xcs[u]);
once++;
printf("Testing verify certificate: %s\tPassed\n",
cn.status ? cn_buf : "");
Index: share/mk/src.opts.mk
===================================================================
--- share/mk/src.opts.mk
+++ share/mk/src.opts.mk
@@ -203,6 +203,7 @@
GNU_GREP_COMPAT \
HESIOD \
LIBSOFT \
+ LOADER_EFI_SECUREBOOT \
LOADER_FIREWIRE \
LOADER_FORCE_LE \
LOADER_VERBOSE \
@@ -434,6 +435,10 @@
MK_GDB:= no
.endif
+.if ${MK_LOADER_VERIEXEC} == "no"
+MK_LOADER_EFI_SECUREBOOT:= no
+.endif
+
.if ${MK_CAPSICUM} == "no"
MK_CASPER:= no
.endif
Index: stand/efi/loader/Makefile
===================================================================
--- stand/efi/loader/Makefile
+++ stand/efi/loader/Makefile
@@ -81,6 +81,10 @@
CFLAGS+= -DEFI_STAGING_SIZE=${EFI_STAGING_SIZE}
.endif
+.if ${MK_LOADER_EFI_SECUREBOOT} == "yes"
+CFLAGS+= -DEFI_SECUREBOOT
+.endif
+
NEWVERSWHAT= "EFI loader" ${MACHINE}
VERSION_FILE= ${.CURDIR}/../loader/version
Index: stand/efi/loader/main.c
===================================================================
--- stand/efi/loader/main.c
+++ stand/efi/loader/main.c
@@ -963,6 +963,17 @@
*/
BS->SetWatchdogTimer(0, 0, 0, NULL);
+ /*
+ * Initialize the trusted/forbidden certificates from UEFI.
+ * They will be later used to verify the manifest(s),
+ * which should contain hashes of verified files.
+ * This needs to be initialized before any configuration files
+ * are loaded.
+ */
+#ifdef EFI_SECUREBOOT
+ ve_efi_init();
+#endif
+
/*
* Try and find a good currdev based on the image that was booted.
* It might be desirable here to have a short pause to allow falling
Index: tools/build/options/WITH_LOADER_EFI_SECUREBOOT
===================================================================
--- /dev/null
+++ tools/build/options/WITH_LOADER_EFI_SECUREBOOT
@@ -0,0 +1,5 @@
+.\" $FreeBSD$
+Enable building
+.Xr loader 8
+with support for verification based on certificates obtained from UEFI.
+.Pp
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Nov 16, 11:25 PM (17 h, 56 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
25395686
Default Alt Text
D19093.id53645.diff (51 KB)
Attached To
Mode
D19093: Extend libsecureboot(old libve) to obtain trusted certificates from UEFI and implement revocation
Attached
Detach File
Event Timeline
Log In to Comment