Re: [PATCH v4 08/16] efi_loader: image_loader: support image authentication
On Thu, Jan 23, 2020 at 06:41:53PM +0100, Heinrich Schuchardt wrote: > On 1/22/20 8:42 AM, AKASHI Takahiro wrote: > >Heinrich, > > > >On Wed, Jan 22, 2020 at 10:13:48AM +0900, AKASHI Takahiro wrote: > >>On Tue, Jan 21, 2020 at 08:15:06AM +0100, Heinrich Schuchardt wrote: > >>>On 1/21/20 7:12 AM, AKASHI Takahiro wrote: > On Fri, Jan 17, 2020 at 06:51:50AM +0100, Heinrich Schuchardt wrote: > >On 1/17/20 6:11 AM, AKASHI Takahiro wrote: > >>On Thu, Jan 09, 2020 at 12:55:17AM +0100, Heinrich Schuchardt wrote: > >>>On 12/18/19 1:45 AM, AKASHI Takahiro wrote: > With this commit, image validation can be enforced, as UEFI > specification > section 32.5 describes, if CONFIG_EFI_SECURE_BOOT is enabled. > > Currently we support > * authentication based on db and dbx, > so dbx-validated image will always be rejected. > * following signature types: > EFI_CERT_SHA256_GUID (SHA256 digest for unsigned images) > EFI_CERT_X509_GUID (x509 certificate for signed images) > Timestamp-based certificate revocation is not supported here. > > Internally, authentication data is stored in one of certificates > tables > of PE image (See efi_image_parse()) and will be verified by > efi_image_authenticate() before loading a given image. > > It seems that UEFI specification defines the verification process > in a bit ambiguous way. I tried to implement it as closely to as > EDK2 does. > > Signed-off-by: AKASHI Takahiro > --- > include/efi_loader.h | 7 +- > lib/efi_loader/efi_boottime.c | 2 +- > lib/efi_loader/efi_image_loader.c | 454 > +- > 3 files changed, 449 insertions(+), 14 deletions(-) > > diff --git a/include/efi_loader.h b/include/efi_loader.h > index 1f88caf86709..e12b49098fb0 100644 > --- a/include/efi_loader.h > +++ b/include/efi_loader.h > @@ -11,6 +11,7 @@ > #include > #include > #include > +#include > > static inline int guidcmp(const void *g1, const void *g2) > { > @@ -398,7 +399,8 @@ efi_status_t efi_set_watchdog(unsigned long > timeout); > /* Called from places to check whether a timer expired */ > void efi_timer_check(void); > /* PE loader implementation */ > -efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle, void > *efi, > +efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle, > + void *efi, size_t efi_size, > struct efi_loaded_image *loaded_image_info); > /* Called once to store the pristine gd pointer */ > void efi_save_gd(void); > @@ -726,6 +728,9 @@ void efi_sigstore_free(struct efi_signature_store > *sigstore); > struct efi_signature_store *efi_sigstore_parse_sigdb(u16 *name); > > bool efi_secure_boot_enabled(void); > + > +bool efi_image_parse(void *efi, size_t len, struct efi_image_regions > **regp, > + WIN_CERTIFICATE **auth, size_t *auth_len); > #endif /* CONFIG_EFI_SECURE_BOOT */ > > #else /* CONFIG_IS_ENABLED(EFI_LOADER) */ > diff --git a/lib/efi_loader/efi_boottime.c > b/lib/efi_loader/efi_boottime.c > index 493d906c641d..311681764034 100644 > --- a/lib/efi_loader/efi_boottime.c > +++ b/lib/efi_loader/efi_boottime.c > @@ -1879,7 +1879,7 @@ efi_status_t EFIAPI efi_load_image(bool > boot_policy, > efi_dp_split_file_path(file_path, , ); > ret = efi_setup_loaded_image(dp, fp, image_obj, ); > if (ret == EFI_SUCCESS) > - ret = efi_load_pe(*image_obj, dest_buffer, info); > + ret = efi_load_pe(*image_obj, dest_buffer, source_size, > info); > if (!source_buffer) > /* Release buffer to which file was loaded */ > efi_free_pages((uintptr_t)dest_buffer, > diff --git a/lib/efi_loader/efi_image_loader.c > b/lib/efi_loader/efi_image_loader.c > index 13541cfa7a28..939758e61e3c 100644 > --- a/lib/efi_loader/efi_image_loader.c > +++ b/lib/efi_loader/efi_image_loader.c > @@ -9,7 +9,9 @@ > > #include > #include > +#include > #include > +#include "../lib/crypto/pkcs7_parser.h" > > const efi_guid_t efi_global_variable_guid = > EFI_GLOBAL_VARIABLE_GUID; > const efi_guid_t efi_guid_device_path = > EFI_DEVICE_PATH_PROTOCOL_GUID; > @@ -205,6
Re: [PATCH v4 08/16] efi_loader: image_loader: support image authentication
On 1/22/20 8:42 AM, AKASHI Takahiro wrote: Heinrich, On Wed, Jan 22, 2020 at 10:13:48AM +0900, AKASHI Takahiro wrote: On Tue, Jan 21, 2020 at 08:15:06AM +0100, Heinrich Schuchardt wrote: On 1/21/20 7:12 AM, AKASHI Takahiro wrote: On Fri, Jan 17, 2020 at 06:51:50AM +0100, Heinrich Schuchardt wrote: On 1/17/20 6:11 AM, AKASHI Takahiro wrote: On Thu, Jan 09, 2020 at 12:55:17AM +0100, Heinrich Schuchardt wrote: On 12/18/19 1:45 AM, AKASHI Takahiro wrote: With this commit, image validation can be enforced, as UEFI specification section 32.5 describes, if CONFIG_EFI_SECURE_BOOT is enabled. Currently we support * authentication based on db and dbx, so dbx-validated image will always be rejected. * following signature types: EFI_CERT_SHA256_GUID (SHA256 digest for unsigned images) EFI_CERT_X509_GUID (x509 certificate for signed images) Timestamp-based certificate revocation is not supported here. Internally, authentication data is stored in one of certificates tables of PE image (See efi_image_parse()) and will be verified by efi_image_authenticate() before loading a given image. It seems that UEFI specification defines the verification process in a bit ambiguous way. I tried to implement it as closely to as EDK2 does. Signed-off-by: AKASHI Takahiro --- include/efi_loader.h | 7 +- lib/efi_loader/efi_boottime.c | 2 +- lib/efi_loader/efi_image_loader.c | 454 +- 3 files changed, 449 insertions(+), 14 deletions(-) diff --git a/include/efi_loader.h b/include/efi_loader.h index 1f88caf86709..e12b49098fb0 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -11,6 +11,7 @@ #include #include #include +#include static inline int guidcmp(const void *g1, const void *g2) { @@ -398,7 +399,8 @@ efi_status_t efi_set_watchdog(unsigned long timeout); /* Called from places to check whether a timer expired */ void efi_timer_check(void); /* PE loader implementation */ -efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle, void *efi, +efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle, +void *efi, size_t efi_size, struct efi_loaded_image *loaded_image_info); /* Called once to store the pristine gd pointer */ void efi_save_gd(void); @@ -726,6 +728,9 @@ void efi_sigstore_free(struct efi_signature_store *sigstore); struct efi_signature_store *efi_sigstore_parse_sigdb(u16 *name); bool efi_secure_boot_enabled(void); + +bool efi_image_parse(void *efi, size_t len, struct efi_image_regions **regp, +WIN_CERTIFICATE **auth, size_t *auth_len); #endif /* CONFIG_EFI_SECURE_BOOT */ #else /* CONFIG_IS_ENABLED(EFI_LOADER) */ diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 493d906c641d..311681764034 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -1879,7 +1879,7 @@ efi_status_t EFIAPI efi_load_image(bool boot_policy, efi_dp_split_file_path(file_path, , ); ret = efi_setup_loaded_image(dp, fp, image_obj, ); if (ret == EFI_SUCCESS) - ret = efi_load_pe(*image_obj, dest_buffer, info); + ret = efi_load_pe(*image_obj, dest_buffer, source_size, info); if (!source_buffer) /* Release buffer to which file was loaded */ efi_free_pages((uintptr_t)dest_buffer, diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c index 13541cfa7a28..939758e61e3c 100644 --- a/lib/efi_loader/efi_image_loader.c +++ b/lib/efi_loader/efi_image_loader.c @@ -9,7 +9,9 @@ #include #include +#include #include +#include "../lib/crypto/pkcs7_parser.h" const efi_guid_t efi_global_variable_guid = EFI_GLOBAL_VARIABLE_GUID; const efi_guid_t efi_guid_device_path = EFI_DEVICE_PATH_PROTOCOL_GUID; @@ -205,6 +207,367 @@ static void efi_set_code_and_data_type( } } +#ifdef CONFIG_EFI_SECURE_BOOT +/** + * efi_image_parse - parse a PE image + * @efi: Pointer to image + * @len: Size of @efi + * @regs: Pointer to a list of regions + * @auth: Pointer to a pointer to authentication data in PE + * @auth_len: Size of @auth + * + * Parse image binary in PE32(+) format, assuming that sanity of PE image + * has been checked by a caller. + * On success, an address of authentication data in @efi and its size will + * be returned in @auth and @auth_len, respectively. + * + * Return: true on success, false on error + */ +bool efi_image_parse(void *efi, size_t len, struct efi_image_regions **regp, +WIN_CERTIFICATE **auth, size_t *auth_len) This function is way too long (> 100 lines). Please, cut it into logical units. +{ + struct efi_image_regions *regs; + IMAGE_DOS_HEADER *dos; + IMAGE_NT_HEADERS32 *nt; + IMAGE_SECTION_HEADER *sections, **sorted; + int num_regions, num_sections, i, j; + int ctidx =
Re: [PATCH v4 08/16] efi_loader: image_loader: support image authentication
Heinrich, On Wed, Jan 22, 2020 at 10:13:48AM +0900, AKASHI Takahiro wrote: > On Tue, Jan 21, 2020 at 08:15:06AM +0100, Heinrich Schuchardt wrote: > > On 1/21/20 7:12 AM, AKASHI Takahiro wrote: > > >On Fri, Jan 17, 2020 at 06:51:50AM +0100, Heinrich Schuchardt wrote: > > >>On 1/17/20 6:11 AM, AKASHI Takahiro wrote: > > >>>On Thu, Jan 09, 2020 at 12:55:17AM +0100, Heinrich Schuchardt wrote: > > On 12/18/19 1:45 AM, AKASHI Takahiro wrote: > > >With this commit, image validation can be enforced, as UEFI > > >specification > > >section 32.5 describes, if CONFIG_EFI_SECURE_BOOT is enabled. > > > > > >Currently we support > > >* authentication based on db and dbx, > > > so dbx-validated image will always be rejected. > > >* following signature types: > > > EFI_CERT_SHA256_GUID (SHA256 digest for unsigned images) > > > EFI_CERT_X509_GUID (x509 certificate for signed images) > > >Timestamp-based certificate revocation is not supported here. > > > > > >Internally, authentication data is stored in one of certificates tables > > >of PE image (See efi_image_parse()) and will be verified by > > >efi_image_authenticate() before loading a given image. > > > > > >It seems that UEFI specification defines the verification process > > >in a bit ambiguous way. I tried to implement it as closely to as > > >EDK2 does. > > > > > >Signed-off-by: AKASHI Takahiro > > >--- > > > include/efi_loader.h | 7 +- > > > lib/efi_loader/efi_boottime.c | 2 +- > > > lib/efi_loader/efi_image_loader.c | 454 > > > +- > > > 3 files changed, 449 insertions(+), 14 deletions(-) > > > > > >diff --git a/include/efi_loader.h b/include/efi_loader.h > > >index 1f88caf86709..e12b49098fb0 100644 > > >--- a/include/efi_loader.h > > >+++ b/include/efi_loader.h > > >@@ -11,6 +11,7 @@ > > > #include > > > #include > > > #include > > >+#include > > > > > > static inline int guidcmp(const void *g1, const void *g2) > > > { > > >@@ -398,7 +399,8 @@ efi_status_t efi_set_watchdog(unsigned long > > >timeout); > > > /* Called from places to check whether a timer expired */ > > > void efi_timer_check(void); > > > /* PE loader implementation */ > > >-efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle, void > > >*efi, > > >+efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle, > > >+ void *efi, size_t efi_size, > > >struct efi_loaded_image *loaded_image_info); > > > /* Called once to store the pristine gd pointer */ > > > void efi_save_gd(void); > > >@@ -726,6 +728,9 @@ void efi_sigstore_free(struct efi_signature_store > > >*sigstore); > > > struct efi_signature_store *efi_sigstore_parse_sigdb(u16 *name); > > > > > > bool efi_secure_boot_enabled(void); > > >+ > > >+bool efi_image_parse(void *efi, size_t len, struct efi_image_regions > > >**regp, > > >+ WIN_CERTIFICATE **auth, size_t *auth_len); > > > #endif /* CONFIG_EFI_SECURE_BOOT */ > > > > > > #else /* CONFIG_IS_ENABLED(EFI_LOADER) */ > > >diff --git a/lib/efi_loader/efi_boottime.c > > >b/lib/efi_loader/efi_boottime.c > > >index 493d906c641d..311681764034 100644 > > >--- a/lib/efi_loader/efi_boottime.c > > >+++ b/lib/efi_loader/efi_boottime.c > > >@@ -1879,7 +1879,7 @@ efi_status_t EFIAPI efi_load_image(bool > > >boot_policy, > > > efi_dp_split_file_path(file_path, , ); > > > ret = efi_setup_loaded_image(dp, fp, image_obj, ); > > > if (ret == EFI_SUCCESS) > > >- ret = efi_load_pe(*image_obj, dest_buffer, info); > > >+ ret = efi_load_pe(*image_obj, dest_buffer, source_size, > > >info); > > > if (!source_buffer) > > > /* Release buffer to which file was loaded */ > > > efi_free_pages((uintptr_t)dest_buffer, > > >diff --git a/lib/efi_loader/efi_image_loader.c > > >b/lib/efi_loader/efi_image_loader.c > > >index 13541cfa7a28..939758e61e3c 100644 > > >--- a/lib/efi_loader/efi_image_loader.c > > >+++ b/lib/efi_loader/efi_image_loader.c > > >@@ -9,7 +9,9 @@ > > > > > > #include > > > #include > > >+#include > > > #include > > >+#include "../lib/crypto/pkcs7_parser.h" > > > > > > const efi_guid_t efi_global_variable_guid = EFI_GLOBAL_VARIABLE_GUID; > > > const efi_guid_t efi_guid_device_path = > > > EFI_DEVICE_PATH_PROTOCOL_GUID; > > >@@ -205,6 +207,367 @@ static void efi_set_code_and_data_type( > > > } > > > } > > > > > >+#ifdef CONFIG_EFI_SECURE_BOOT > > >+/** > > >+ * efi_image_parse - parse a PE image > > >+ * @efi: Pointer to image > >
Re: [PATCH v4 08/16] efi_loader: image_loader: support image authentication
On Tue, Jan 21, 2020 at 08:15:06AM +0100, Heinrich Schuchardt wrote: > On 1/21/20 7:12 AM, AKASHI Takahiro wrote: > >On Fri, Jan 17, 2020 at 06:51:50AM +0100, Heinrich Schuchardt wrote: > >>On 1/17/20 6:11 AM, AKASHI Takahiro wrote: > >>>On Thu, Jan 09, 2020 at 12:55:17AM +0100, Heinrich Schuchardt wrote: > On 12/18/19 1:45 AM, AKASHI Takahiro wrote: > >With this commit, image validation can be enforced, as UEFI specification > >section 32.5 describes, if CONFIG_EFI_SECURE_BOOT is enabled. > > > >Currently we support > >* authentication based on db and dbx, > > so dbx-validated image will always be rejected. > >* following signature types: > > EFI_CERT_SHA256_GUID (SHA256 digest for unsigned images) > > EFI_CERT_X509_GUID (x509 certificate for signed images) > >Timestamp-based certificate revocation is not supported here. > > > >Internally, authentication data is stored in one of certificates tables > >of PE image (See efi_image_parse()) and will be verified by > >efi_image_authenticate() before loading a given image. > > > >It seems that UEFI specification defines the verification process > >in a bit ambiguous way. I tried to implement it as closely to as > >EDK2 does. > > > >Signed-off-by: AKASHI Takahiro > >--- > > include/efi_loader.h | 7 +- > > lib/efi_loader/efi_boottime.c | 2 +- > > lib/efi_loader/efi_image_loader.c | 454 +- > > 3 files changed, 449 insertions(+), 14 deletions(-) > > > >diff --git a/include/efi_loader.h b/include/efi_loader.h > >index 1f88caf86709..e12b49098fb0 100644 > >--- a/include/efi_loader.h > >+++ b/include/efi_loader.h > >@@ -11,6 +11,7 @@ > > #include > > #include > > #include > >+#include > > > > static inline int guidcmp(const void *g1, const void *g2) > > { > >@@ -398,7 +399,8 @@ efi_status_t efi_set_watchdog(unsigned long timeout); > > /* Called from places to check whether a timer expired */ > > void efi_timer_check(void); > > /* PE loader implementation */ > >-efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle, void *efi, > >+efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle, > >+ void *efi, size_t efi_size, > > struct efi_loaded_image *loaded_image_info); > > /* Called once to store the pristine gd pointer */ > > void efi_save_gd(void); > >@@ -726,6 +728,9 @@ void efi_sigstore_free(struct efi_signature_store > >*sigstore); > > struct efi_signature_store *efi_sigstore_parse_sigdb(u16 *name); > > > > bool efi_secure_boot_enabled(void); > >+ > >+bool efi_image_parse(void *efi, size_t len, struct efi_image_regions > >**regp, > >+ WIN_CERTIFICATE **auth, size_t *auth_len); > > #endif /* CONFIG_EFI_SECURE_BOOT */ > > > > #else /* CONFIG_IS_ENABLED(EFI_LOADER) */ > >diff --git a/lib/efi_loader/efi_boottime.c > >b/lib/efi_loader/efi_boottime.c > >index 493d906c641d..311681764034 100644 > >--- a/lib/efi_loader/efi_boottime.c > >+++ b/lib/efi_loader/efi_boottime.c > >@@ -1879,7 +1879,7 @@ efi_status_t EFIAPI efi_load_image(bool > >boot_policy, > > efi_dp_split_file_path(file_path, , ); > > ret = efi_setup_loaded_image(dp, fp, image_obj, ); > > if (ret == EFI_SUCCESS) > >-ret = efi_load_pe(*image_obj, dest_buffer, info); > >+ret = efi_load_pe(*image_obj, dest_buffer, source_size, > >info); > > if (!source_buffer) > > /* Release buffer to which file was loaded */ > > efi_free_pages((uintptr_t)dest_buffer, > >diff --git a/lib/efi_loader/efi_image_loader.c > >b/lib/efi_loader/efi_image_loader.c > >index 13541cfa7a28..939758e61e3c 100644 > >--- a/lib/efi_loader/efi_image_loader.c > >+++ b/lib/efi_loader/efi_image_loader.c > >@@ -9,7 +9,9 @@ > > > > #include > > #include > >+#include > > #include > >+#include "../lib/crypto/pkcs7_parser.h" > > > > const efi_guid_t efi_global_variable_guid = EFI_GLOBAL_VARIABLE_GUID; > > const efi_guid_t efi_guid_device_path = EFI_DEVICE_PATH_PROTOCOL_GUID; > >@@ -205,6 +207,367 @@ static void efi_set_code_and_data_type( > > } > > } > > > >+#ifdef CONFIG_EFI_SECURE_BOOT > >+/** > >+ * efi_image_parse - parse a PE image > >+ * @efi:Pointer to image > >+ * @len:Size of @efi > >+ * @regs: Pointer to a list of regions > >+ * @auth: Pointer to a pointer to authentication data in PE > >+ * @auth_len: Size of @auth > >+ * > >+ * Parse image binary in PE32(+) format, assuming that sanity of PE > >image > >+ * has
Re: [PATCH v4 08/16] efi_loader: image_loader: support image authentication
On 1/21/20 7:12 AM, AKASHI Takahiro wrote: On Fri, Jan 17, 2020 at 06:51:50AM +0100, Heinrich Schuchardt wrote: On 1/17/20 6:11 AM, AKASHI Takahiro wrote: On Thu, Jan 09, 2020 at 12:55:17AM +0100, Heinrich Schuchardt wrote: On 12/18/19 1:45 AM, AKASHI Takahiro wrote: With this commit, image validation can be enforced, as UEFI specification section 32.5 describes, if CONFIG_EFI_SECURE_BOOT is enabled. Currently we support * authentication based on db and dbx, so dbx-validated image will always be rejected. * following signature types: EFI_CERT_SHA256_GUID (SHA256 digest for unsigned images) EFI_CERT_X509_GUID (x509 certificate for signed images) Timestamp-based certificate revocation is not supported here. Internally, authentication data is stored in one of certificates tables of PE image (See efi_image_parse()) and will be verified by efi_image_authenticate() before loading a given image. It seems that UEFI specification defines the verification process in a bit ambiguous way. I tried to implement it as closely to as EDK2 does. Signed-off-by: AKASHI Takahiro --- include/efi_loader.h | 7 +- lib/efi_loader/efi_boottime.c | 2 +- lib/efi_loader/efi_image_loader.c | 454 +- 3 files changed, 449 insertions(+), 14 deletions(-) diff --git a/include/efi_loader.h b/include/efi_loader.h index 1f88caf86709..e12b49098fb0 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -11,6 +11,7 @@ #include #include #include +#include static inline int guidcmp(const void *g1, const void *g2) { @@ -398,7 +399,8 @@ efi_status_t efi_set_watchdog(unsigned long timeout); /* Called from places to check whether a timer expired */ void efi_timer_check(void); /* PE loader implementation */ -efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle, void *efi, +efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle, +void *efi, size_t efi_size, struct efi_loaded_image *loaded_image_info); /* Called once to store the pristine gd pointer */ void efi_save_gd(void); @@ -726,6 +728,9 @@ void efi_sigstore_free(struct efi_signature_store *sigstore); struct efi_signature_store *efi_sigstore_parse_sigdb(u16 *name); bool efi_secure_boot_enabled(void); + +bool efi_image_parse(void *efi, size_t len, struct efi_image_regions **regp, +WIN_CERTIFICATE **auth, size_t *auth_len); #endif /* CONFIG_EFI_SECURE_BOOT */ #else /* CONFIG_IS_ENABLED(EFI_LOADER) */ diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 493d906c641d..311681764034 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -1879,7 +1879,7 @@ efi_status_t EFIAPI efi_load_image(bool boot_policy, efi_dp_split_file_path(file_path, , ); ret = efi_setup_loaded_image(dp, fp, image_obj, ); if (ret == EFI_SUCCESS) - ret = efi_load_pe(*image_obj, dest_buffer, info); + ret = efi_load_pe(*image_obj, dest_buffer, source_size, info); if (!source_buffer) /* Release buffer to which file was loaded */ efi_free_pages((uintptr_t)dest_buffer, diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c index 13541cfa7a28..939758e61e3c 100644 --- a/lib/efi_loader/efi_image_loader.c +++ b/lib/efi_loader/efi_image_loader.c @@ -9,7 +9,9 @@ #include #include +#include #include +#include "../lib/crypto/pkcs7_parser.h" const efi_guid_t efi_global_variable_guid = EFI_GLOBAL_VARIABLE_GUID; const efi_guid_t efi_guid_device_path = EFI_DEVICE_PATH_PROTOCOL_GUID; @@ -205,6 +207,367 @@ static void efi_set_code_and_data_type( } } +#ifdef CONFIG_EFI_SECURE_BOOT +/** + * efi_image_parse - parse a PE image + * @efi: Pointer to image + * @len: Size of @efi + * @regs: Pointer to a list of regions + * @auth: Pointer to a pointer to authentication data in PE + * @auth_len: Size of @auth + * + * Parse image binary in PE32(+) format, assuming that sanity of PE image + * has been checked by a caller. + * On success, an address of authentication data in @efi and its size will + * be returned in @auth and @auth_len, respectively. + * + * Return: true on success, false on error + */ +bool efi_image_parse(void *efi, size_t len, struct efi_image_regions **regp, +WIN_CERTIFICATE **auth, size_t *auth_len) This function is way too long (> 100 lines). Please, cut it into logical units. +{ + struct efi_image_regions *regs; + IMAGE_DOS_HEADER *dos; + IMAGE_NT_HEADERS32 *nt; + IMAGE_SECTION_HEADER *sections, **sorted; + int num_regions, num_sections, i, j; + int ctidx = IMAGE_DIRECTORY_ENTRY_SECURITY; + u32 align, size, authsz, authoff; + size_t bytes_hashed; + + dos = (void *)efi; + nt = (void *)(efi + dos->e_lfanew); + + /* +
Re: [PATCH v4 08/16] efi_loader: image_loader: support image authentication
On Fri, Jan 17, 2020 at 06:51:50AM +0100, Heinrich Schuchardt wrote: > On 1/17/20 6:11 AM, AKASHI Takahiro wrote: > >On Thu, Jan 09, 2020 at 12:55:17AM +0100, Heinrich Schuchardt wrote: > >>On 12/18/19 1:45 AM, AKASHI Takahiro wrote: > >>>With this commit, image validation can be enforced, as UEFI specification > >>>section 32.5 describes, if CONFIG_EFI_SECURE_BOOT is enabled. > >>> > >>>Currently we support > >>>* authentication based on db and dbx, > >>> so dbx-validated image will always be rejected. > >>>* following signature types: > >>> EFI_CERT_SHA256_GUID (SHA256 digest for unsigned images) > >>> EFI_CERT_X509_GUID (x509 certificate for signed images) > >>>Timestamp-based certificate revocation is not supported here. > >>> > >>>Internally, authentication data is stored in one of certificates tables > >>>of PE image (See efi_image_parse()) and will be verified by > >>>efi_image_authenticate() before loading a given image. > >>> > >>>It seems that UEFI specification defines the verification process > >>>in a bit ambiguous way. I tried to implement it as closely to as > >>>EDK2 does. > >>> > >>>Signed-off-by: AKASHI Takahiro > >>>--- > >>> include/efi_loader.h | 7 +- > >>> lib/efi_loader/efi_boottime.c | 2 +- > >>> lib/efi_loader/efi_image_loader.c | 454 +- > >>> 3 files changed, 449 insertions(+), 14 deletions(-) > >>> > >>>diff --git a/include/efi_loader.h b/include/efi_loader.h > >>>index 1f88caf86709..e12b49098fb0 100644 > >>>--- a/include/efi_loader.h > >>>+++ b/include/efi_loader.h > >>>@@ -11,6 +11,7 @@ > >>> #include > >>> #include > >>> #include > >>>+#include > >>> > >>> static inline int guidcmp(const void *g1, const void *g2) > >>> { > >>>@@ -398,7 +399,8 @@ efi_status_t efi_set_watchdog(unsigned long timeout); > >>> /* Called from places to check whether a timer expired */ > >>> void efi_timer_check(void); > >>> /* PE loader implementation */ > >>>-efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle, void *efi, > >>>+efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle, > >>>+ void *efi, size_t efi_size, > >>>struct efi_loaded_image *loaded_image_info); > >>> /* Called once to store the pristine gd pointer */ > >>> void efi_save_gd(void); > >>>@@ -726,6 +728,9 @@ void efi_sigstore_free(struct efi_signature_store > >>>*sigstore); > >>> struct efi_signature_store *efi_sigstore_parse_sigdb(u16 *name); > >>> > >>> bool efi_secure_boot_enabled(void); > >>>+ > >>>+bool efi_image_parse(void *efi, size_t len, struct efi_image_regions > >>>**regp, > >>>+ WIN_CERTIFICATE **auth, size_t *auth_len); > >>> #endif /* CONFIG_EFI_SECURE_BOOT */ > >>> > >>> #else /* CONFIG_IS_ENABLED(EFI_LOADER) */ > >>>diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c > >>>index 493d906c641d..311681764034 100644 > >>>--- a/lib/efi_loader/efi_boottime.c > >>>+++ b/lib/efi_loader/efi_boottime.c > >>>@@ -1879,7 +1879,7 @@ efi_status_t EFIAPI efi_load_image(bool boot_policy, > >>> efi_dp_split_file_path(file_path, , ); > >>> ret = efi_setup_loaded_image(dp, fp, image_obj, ); > >>> if (ret == EFI_SUCCESS) > >>>- ret = efi_load_pe(*image_obj, dest_buffer, info); > >>>+ ret = efi_load_pe(*image_obj, dest_buffer, source_size, info); > >>> if (!source_buffer) > >>> /* Release buffer to which file was loaded */ > >>> efi_free_pages((uintptr_t)dest_buffer, > >>>diff --git a/lib/efi_loader/efi_image_loader.c > >>>b/lib/efi_loader/efi_image_loader.c > >>>index 13541cfa7a28..939758e61e3c 100644 > >>>--- a/lib/efi_loader/efi_image_loader.c > >>>+++ b/lib/efi_loader/efi_image_loader.c > >>>@@ -9,7 +9,9 @@ > >>> > >>> #include > >>> #include > >>>+#include > >>> #include > >>>+#include "../lib/crypto/pkcs7_parser.h" > >>> > >>> const efi_guid_t efi_global_variable_guid = EFI_GLOBAL_VARIABLE_GUID; > >>> const efi_guid_t efi_guid_device_path = EFI_DEVICE_PATH_PROTOCOL_GUID; > >>>@@ -205,6 +207,367 @@ static void efi_set_code_and_data_type( > >>> } > >>> } > >>> > >>>+#ifdef CONFIG_EFI_SECURE_BOOT > >>>+/** > >>>+ * efi_image_parse - parse a PE image > >>>+ * @efi: Pointer to image > >>>+ * @len: Size of @efi > >>>+ * @regs: Pointer to a list of regions > >>>+ * @auth: Pointer to a pointer to authentication data in PE > >>>+ * @auth_len: Size of @auth > >>>+ * > >>>+ * Parse image binary in PE32(+) format, assuming that sanity of PE image > >>>+ * has been checked by a caller. > >>>+ * On success, an address of authentication data in @efi and its size will > >>>+ * be returned in @auth and @auth_len, respectively. > >>>+ * > >>>+ * Return:true on success, false on error > >>>+ */ > >>>+bool efi_image_parse(void *efi, size_t len, struct efi_image_regions > >>>**regp, > >>>+ WIN_CERTIFICATE **auth, size_t *auth_len) > >> > >> > >>This function is way too long (> 100 lines).
Re: [PATCH v4 08/16] efi_loader: image_loader: support image authentication
On 1/17/20 6:11 AM, AKASHI Takahiro wrote: On Thu, Jan 09, 2020 at 12:55:17AM +0100, Heinrich Schuchardt wrote: On 12/18/19 1:45 AM, AKASHI Takahiro wrote: With this commit, image validation can be enforced, as UEFI specification section 32.5 describes, if CONFIG_EFI_SECURE_BOOT is enabled. Currently we support * authentication based on db and dbx, so dbx-validated image will always be rejected. * following signature types: EFI_CERT_SHA256_GUID (SHA256 digest for unsigned images) EFI_CERT_X509_GUID (x509 certificate for signed images) Timestamp-based certificate revocation is not supported here. Internally, authentication data is stored in one of certificates tables of PE image (See efi_image_parse()) and will be verified by efi_image_authenticate() before loading a given image. It seems that UEFI specification defines the verification process in a bit ambiguous way. I tried to implement it as closely to as EDK2 does. Signed-off-by: AKASHI Takahiro --- include/efi_loader.h | 7 +- lib/efi_loader/efi_boottime.c | 2 +- lib/efi_loader/efi_image_loader.c | 454 +- 3 files changed, 449 insertions(+), 14 deletions(-) diff --git a/include/efi_loader.h b/include/efi_loader.h index 1f88caf86709..e12b49098fb0 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -11,6 +11,7 @@ #include #include #include +#include static inline int guidcmp(const void *g1, const void *g2) { @@ -398,7 +399,8 @@ efi_status_t efi_set_watchdog(unsigned long timeout); /* Called from places to check whether a timer expired */ void efi_timer_check(void); /* PE loader implementation */ -efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle, void *efi, +efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle, +void *efi, size_t efi_size, struct efi_loaded_image *loaded_image_info); /* Called once to store the pristine gd pointer */ void efi_save_gd(void); @@ -726,6 +728,9 @@ void efi_sigstore_free(struct efi_signature_store *sigstore); struct efi_signature_store *efi_sigstore_parse_sigdb(u16 *name); bool efi_secure_boot_enabled(void); + +bool efi_image_parse(void *efi, size_t len, struct efi_image_regions **regp, +WIN_CERTIFICATE **auth, size_t *auth_len); #endif /* CONFIG_EFI_SECURE_BOOT */ #else /* CONFIG_IS_ENABLED(EFI_LOADER) */ diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 493d906c641d..311681764034 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -1879,7 +1879,7 @@ efi_status_t EFIAPI efi_load_image(bool boot_policy, efi_dp_split_file_path(file_path, , ); ret = efi_setup_loaded_image(dp, fp, image_obj, ); if (ret == EFI_SUCCESS) - ret = efi_load_pe(*image_obj, dest_buffer, info); + ret = efi_load_pe(*image_obj, dest_buffer, source_size, info); if (!source_buffer) /* Release buffer to which file was loaded */ efi_free_pages((uintptr_t)dest_buffer, diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c index 13541cfa7a28..939758e61e3c 100644 --- a/lib/efi_loader/efi_image_loader.c +++ b/lib/efi_loader/efi_image_loader.c @@ -9,7 +9,9 @@ #include #include +#include #include +#include "../lib/crypto/pkcs7_parser.h" const efi_guid_t efi_global_variable_guid = EFI_GLOBAL_VARIABLE_GUID; const efi_guid_t efi_guid_device_path = EFI_DEVICE_PATH_PROTOCOL_GUID; @@ -205,6 +207,367 @@ static void efi_set_code_and_data_type( } } +#ifdef CONFIG_EFI_SECURE_BOOT +/** + * efi_image_parse - parse a PE image + * @efi: Pointer to image + * @len: Size of @efi + * @regs: Pointer to a list of regions + * @auth: Pointer to a pointer to authentication data in PE + * @auth_len: Size of @auth + * + * Parse image binary in PE32(+) format, assuming that sanity of PE image + * has been checked by a caller. + * On success, an address of authentication data in @efi and its size will + * be returned in @auth and @auth_len, respectively. + * + * Return: true on success, false on error + */ +bool efi_image_parse(void *efi, size_t len, struct efi_image_regions **regp, +WIN_CERTIFICATE **auth, size_t *auth_len) This function is way too long (> 100 lines). Please, cut it into logical units. +{ + struct efi_image_regions *regs; + IMAGE_DOS_HEADER *dos; + IMAGE_NT_HEADERS32 *nt; + IMAGE_SECTION_HEADER *sections, **sorted; + int num_regions, num_sections, i, j; + int ctidx = IMAGE_DIRECTORY_ENTRY_SECURITY; + u32 align, size, authsz, authoff; + size_t bytes_hashed; + + dos = (void *)efi; + nt = (void *)(efi + dos->e_lfanew); + + /* +* Count maximum number of regions to be digested. +* We don't have to have an exact number here. +
Re: [PATCH v4 08/16] efi_loader: image_loader: support image authentication
On Thu, Jan 09, 2020 at 12:55:17AM +0100, Heinrich Schuchardt wrote: > On 12/18/19 1:45 AM, AKASHI Takahiro wrote: > >With this commit, image validation can be enforced, as UEFI specification > >section 32.5 describes, if CONFIG_EFI_SECURE_BOOT is enabled. > > > >Currently we support > >* authentication based on db and dbx, > > so dbx-validated image will always be rejected. > >* following signature types: > > EFI_CERT_SHA256_GUID (SHA256 digest for unsigned images) > > EFI_CERT_X509_GUID (x509 certificate for signed images) > >Timestamp-based certificate revocation is not supported here. > > > >Internally, authentication data is stored in one of certificates tables > >of PE image (See efi_image_parse()) and will be verified by > >efi_image_authenticate() before loading a given image. > > > >It seems that UEFI specification defines the verification process > >in a bit ambiguous way. I tried to implement it as closely to as > >EDK2 does. > > > >Signed-off-by: AKASHI Takahiro > >--- > > include/efi_loader.h | 7 +- > > lib/efi_loader/efi_boottime.c | 2 +- > > lib/efi_loader/efi_image_loader.c | 454 +- > > 3 files changed, 449 insertions(+), 14 deletions(-) > > > >diff --git a/include/efi_loader.h b/include/efi_loader.h > >index 1f88caf86709..e12b49098fb0 100644 > >--- a/include/efi_loader.h > >+++ b/include/efi_loader.h > >@@ -11,6 +11,7 @@ > > #include > > #include > > #include > >+#include > > > > static inline int guidcmp(const void *g1, const void *g2) > > { > >@@ -398,7 +399,8 @@ efi_status_t efi_set_watchdog(unsigned long timeout); > > /* Called from places to check whether a timer expired */ > > void efi_timer_check(void); > > /* PE loader implementation */ > >-efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle, void *efi, > >+efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle, > >+ void *efi, size_t efi_size, > > struct efi_loaded_image *loaded_image_info); > > /* Called once to store the pristine gd pointer */ > > void efi_save_gd(void); > >@@ -726,6 +728,9 @@ void efi_sigstore_free(struct efi_signature_store > >*sigstore); > > struct efi_signature_store *efi_sigstore_parse_sigdb(u16 *name); > > > > bool efi_secure_boot_enabled(void); > >+ > >+bool efi_image_parse(void *efi, size_t len, struct efi_image_regions **regp, > >+ WIN_CERTIFICATE **auth, size_t *auth_len); > > #endif /* CONFIG_EFI_SECURE_BOOT */ > > > > #else /* CONFIG_IS_ENABLED(EFI_LOADER) */ > >diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c > >index 493d906c641d..311681764034 100644 > >--- a/lib/efi_loader/efi_boottime.c > >+++ b/lib/efi_loader/efi_boottime.c > >@@ -1879,7 +1879,7 @@ efi_status_t EFIAPI efi_load_image(bool boot_policy, > > efi_dp_split_file_path(file_path, , ); > > ret = efi_setup_loaded_image(dp, fp, image_obj, ); > > if (ret == EFI_SUCCESS) > >-ret = efi_load_pe(*image_obj, dest_buffer, info); > >+ret = efi_load_pe(*image_obj, dest_buffer, source_size, info); > > if (!source_buffer) > > /* Release buffer to which file was loaded */ > > efi_free_pages((uintptr_t)dest_buffer, > >diff --git a/lib/efi_loader/efi_image_loader.c > >b/lib/efi_loader/efi_image_loader.c > >index 13541cfa7a28..939758e61e3c 100644 > >--- a/lib/efi_loader/efi_image_loader.c > >+++ b/lib/efi_loader/efi_image_loader.c > >@@ -9,7 +9,9 @@ > > > > #include > > #include > >+#include > > #include > >+#include "../lib/crypto/pkcs7_parser.h" > > > > const efi_guid_t efi_global_variable_guid = EFI_GLOBAL_VARIABLE_GUID; > > const efi_guid_t efi_guid_device_path = EFI_DEVICE_PATH_PROTOCOL_GUID; > >@@ -205,6 +207,367 @@ static void efi_set_code_and_data_type( > > } > > } > > > >+#ifdef CONFIG_EFI_SECURE_BOOT > >+/** > >+ * efi_image_parse - parse a PE image > >+ * @efi:Pointer to image > >+ * @len:Size of @efi > >+ * @regs: Pointer to a list of regions > >+ * @auth: Pointer to a pointer to authentication data in PE > >+ * @auth_len: Size of @auth > >+ * > >+ * Parse image binary in PE32(+) format, assuming that sanity of PE image > >+ * has been checked by a caller. > >+ * On success, an address of authentication data in @efi and its size will > >+ * be returned in @auth and @auth_len, respectively. > >+ * > >+ * Return: true on success, false on error > >+ */ > >+bool efi_image_parse(void *efi, size_t len, struct efi_image_regions **regp, > >+ WIN_CERTIFICATE **auth, size_t *auth_len) > > > This function is way too long (> 100 lines). Please, cut it into logical > units. > > > > >+{ > >+struct efi_image_regions *regs; > >+IMAGE_DOS_HEADER *dos; > >+IMAGE_NT_HEADERS32 *nt; > >+IMAGE_SECTION_HEADER *sections, **sorted; > >+int num_regions, num_sections, i, j; > >+int ctidx = IMAGE_DIRECTORY_ENTRY_SECURITY; > >+u32 align, size,
Re: [PATCH v4 08/16] efi_loader: image_loader: support image authentication
On 12/18/19 1:45 AM, AKASHI Takahiro wrote: With this commit, image validation can be enforced, as UEFI specification section 32.5 describes, if CONFIG_EFI_SECURE_BOOT is enabled. Currently we support * authentication based on db and dbx, so dbx-validated image will always be rejected. * following signature types: EFI_CERT_SHA256_GUID (SHA256 digest for unsigned images) EFI_CERT_X509_GUID (x509 certificate for signed images) Timestamp-based certificate revocation is not supported here. Internally, authentication data is stored in one of certificates tables of PE image (See efi_image_parse()) and will be verified by efi_image_authenticate() before loading a given image. It seems that UEFI specification defines the verification process in a bit ambiguous way. I tried to implement it as closely to as EDK2 does. Signed-off-by: AKASHI Takahiro --- include/efi_loader.h | 7 +- lib/efi_loader/efi_boottime.c | 2 +- lib/efi_loader/efi_image_loader.c | 454 +- 3 files changed, 449 insertions(+), 14 deletions(-) diff --git a/include/efi_loader.h b/include/efi_loader.h index 1f88caf86709..e12b49098fb0 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -11,6 +11,7 @@ #include #include #include +#include static inline int guidcmp(const void *g1, const void *g2) { @@ -398,7 +399,8 @@ efi_status_t efi_set_watchdog(unsigned long timeout); /* Called from places to check whether a timer expired */ void efi_timer_check(void); /* PE loader implementation */ -efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle, void *efi, +efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle, +void *efi, size_t efi_size, struct efi_loaded_image *loaded_image_info); /* Called once to store the pristine gd pointer */ void efi_save_gd(void); @@ -726,6 +728,9 @@ void efi_sigstore_free(struct efi_signature_store *sigstore); struct efi_signature_store *efi_sigstore_parse_sigdb(u16 *name); bool efi_secure_boot_enabled(void); + +bool efi_image_parse(void *efi, size_t len, struct efi_image_regions **regp, +WIN_CERTIFICATE **auth, size_t *auth_len); #endif /* CONFIG_EFI_SECURE_BOOT */ #else /* CONFIG_IS_ENABLED(EFI_LOADER) */ diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 493d906c641d..311681764034 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -1879,7 +1879,7 @@ efi_status_t EFIAPI efi_load_image(bool boot_policy, efi_dp_split_file_path(file_path, , ); ret = efi_setup_loaded_image(dp, fp, image_obj, ); if (ret == EFI_SUCCESS) - ret = efi_load_pe(*image_obj, dest_buffer, info); + ret = efi_load_pe(*image_obj, dest_buffer, source_size, info); if (!source_buffer) /* Release buffer to which file was loaded */ efi_free_pages((uintptr_t)dest_buffer, diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c index 13541cfa7a28..939758e61e3c 100644 --- a/lib/efi_loader/efi_image_loader.c +++ b/lib/efi_loader/efi_image_loader.c @@ -9,7 +9,9 @@ #include #include +#include #include +#include "../lib/crypto/pkcs7_parser.h" const efi_guid_t efi_global_variable_guid = EFI_GLOBAL_VARIABLE_GUID; const efi_guid_t efi_guid_device_path = EFI_DEVICE_PATH_PROTOCOL_GUID; @@ -205,6 +207,367 @@ static void efi_set_code_and_data_type( } } +#ifdef CONFIG_EFI_SECURE_BOOT +/** + * efi_image_parse - parse a PE image + * @efi: Pointer to image + * @len: Size of @efi + * @regs: Pointer to a list of regions + * @auth: Pointer to a pointer to authentication data in PE + * @auth_len: Size of @auth + * + * Parse image binary in PE32(+) format, assuming that sanity of PE image + * has been checked by a caller. + * On success, an address of authentication data in @efi and its size will + * be returned in @auth and @auth_len, respectively. + * + * Return: true on success, false on error + */ +bool efi_image_parse(void *efi, size_t len, struct efi_image_regions **regp, +WIN_CERTIFICATE **auth, size_t *auth_len) This function is way too long (> 100 lines). Please, cut it into logical units. +{ + struct efi_image_regions *regs; + IMAGE_DOS_HEADER *dos; + IMAGE_NT_HEADERS32 *nt; + IMAGE_SECTION_HEADER *sections, **sorted; + int num_regions, num_sections, i, j; + int ctidx = IMAGE_DIRECTORY_ENTRY_SECURITY; + u32 align, size, authsz, authoff; + size_t bytes_hashed; + + dos = (void *)efi; + nt = (void *)(efi + dos->e_lfanew); + + /* +* Count maximum number of regions to be digested. +* We don't have to have an exact number here. +* See efi_image_region_add()'s in parsing below. +*/ + num_regions = 3; /* for header */ +
[PATCH v4 08/16] efi_loader: image_loader: support image authentication
With this commit, image validation can be enforced, as UEFI specification section 32.5 describes, if CONFIG_EFI_SECURE_BOOT is enabled. Currently we support * authentication based on db and dbx, so dbx-validated image will always be rejected. * following signature types: EFI_CERT_SHA256_GUID (SHA256 digest for unsigned images) EFI_CERT_X509_GUID (x509 certificate for signed images) Timestamp-based certificate revocation is not supported here. Internally, authentication data is stored in one of certificates tables of PE image (See efi_image_parse()) and will be verified by efi_image_authenticate() before loading a given image. It seems that UEFI specification defines the verification process in a bit ambiguous way. I tried to implement it as closely to as EDK2 does. Signed-off-by: AKASHI Takahiro --- include/efi_loader.h | 7 +- lib/efi_loader/efi_boottime.c | 2 +- lib/efi_loader/efi_image_loader.c | 454 +- 3 files changed, 449 insertions(+), 14 deletions(-) diff --git a/include/efi_loader.h b/include/efi_loader.h index 1f88caf86709..e12b49098fb0 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -11,6 +11,7 @@ #include #include #include +#include static inline int guidcmp(const void *g1, const void *g2) { @@ -398,7 +399,8 @@ efi_status_t efi_set_watchdog(unsigned long timeout); /* Called from places to check whether a timer expired */ void efi_timer_check(void); /* PE loader implementation */ -efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle, void *efi, +efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle, +void *efi, size_t efi_size, struct efi_loaded_image *loaded_image_info); /* Called once to store the pristine gd pointer */ void efi_save_gd(void); @@ -726,6 +728,9 @@ void efi_sigstore_free(struct efi_signature_store *sigstore); struct efi_signature_store *efi_sigstore_parse_sigdb(u16 *name); bool efi_secure_boot_enabled(void); + +bool efi_image_parse(void *efi, size_t len, struct efi_image_regions **regp, +WIN_CERTIFICATE **auth, size_t *auth_len); #endif /* CONFIG_EFI_SECURE_BOOT */ #else /* CONFIG_IS_ENABLED(EFI_LOADER) */ diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 493d906c641d..311681764034 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -1879,7 +1879,7 @@ efi_status_t EFIAPI efi_load_image(bool boot_policy, efi_dp_split_file_path(file_path, , ); ret = efi_setup_loaded_image(dp, fp, image_obj, ); if (ret == EFI_SUCCESS) - ret = efi_load_pe(*image_obj, dest_buffer, info); + ret = efi_load_pe(*image_obj, dest_buffer, source_size, info); if (!source_buffer) /* Release buffer to which file was loaded */ efi_free_pages((uintptr_t)dest_buffer, diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c index 13541cfa7a28..939758e61e3c 100644 --- a/lib/efi_loader/efi_image_loader.c +++ b/lib/efi_loader/efi_image_loader.c @@ -9,7 +9,9 @@ #include #include +#include #include +#include "../lib/crypto/pkcs7_parser.h" const efi_guid_t efi_global_variable_guid = EFI_GLOBAL_VARIABLE_GUID; const efi_guid_t efi_guid_device_path = EFI_DEVICE_PATH_PROTOCOL_GUID; @@ -205,6 +207,367 @@ static void efi_set_code_and_data_type( } } +#ifdef CONFIG_EFI_SECURE_BOOT +/** + * efi_image_parse - parse a PE image + * @efi: Pointer to image + * @len: Size of @efi + * @regs: Pointer to a list of regions + * @auth: Pointer to a pointer to authentication data in PE + * @auth_len: Size of @auth + * + * Parse image binary in PE32(+) format, assuming that sanity of PE image + * has been checked by a caller. + * On success, an address of authentication data in @efi and its size will + * be returned in @auth and @auth_len, respectively. + * + * Return: true on success, false on error + */ +bool efi_image_parse(void *efi, size_t len, struct efi_image_regions **regp, +WIN_CERTIFICATE **auth, size_t *auth_len) +{ + struct efi_image_regions *regs; + IMAGE_DOS_HEADER *dos; + IMAGE_NT_HEADERS32 *nt; + IMAGE_SECTION_HEADER *sections, **sorted; + int num_regions, num_sections, i, j; + int ctidx = IMAGE_DIRECTORY_ENTRY_SECURITY; + u32 align, size, authsz, authoff; + size_t bytes_hashed; + + dos = (void *)efi; + nt = (void *)(efi + dos->e_lfanew); + + /* +* Count maximum number of regions to be digested. +* We don't have to have an exact number here. +* See efi_image_region_add()'s in parsing below. +*/ + num_regions = 3; /* for header */ + num_regions += nt->FileHeader.NumberOfSections; + num_regions++; /* for extra */ + + regs = calloc(sizeof(*regs) + sizeof(struct image_region)