diff mbox series

efi_loader: capsule: remove authentication data

Message ID 20210720054442.102780-1-takahiro.akashi@linaro.org
State Superseded
Headers show
Series efi_loader: capsule: remove authentication data | expand

Commit Message

AKASHI Takahiro July 20, 2021, 5:44 a.m. UTC
If capsule authentication is disabled and yet a capsule file is signed,
its signature must be removed from image data to flush.
Otherwise, the firmware will be corrupted after update.

Fixes: 04be98bd6bcf ("efi: capsule: Add support for uefi capsule
	authentication")
Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>

---
 lib/efi_loader/efi_capsule.c | 70 +++++++++++++++++++++++++++++-------
 1 file changed, 57 insertions(+), 13 deletions(-)

-- 
2.31.0

Comments

AKASHI Takahiro July 20, 2021, 5:51 a.m. UTC | #1
Please ignore this patch as I mistakenly sent out v1.

-Takahiro Akashi

On Tue, Jul 20, 2021 at 02:44:42PM +0900, AKASHI Takahiro wrote:
> If capsule authentication is disabled and yet a capsule file is signed,

> its signature must be removed from image data to flush.

> Otherwise, the firmware will be corrupted after update.

> 

> Fixes: 04be98bd6bcf ("efi: capsule: Add support for uefi capsule

> 	authentication")

> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>

> ---

>  lib/efi_loader/efi_capsule.c | 70 +++++++++++++++++++++++++++++-------

>  1 file changed, 57 insertions(+), 13 deletions(-)

> 

> diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c

> index b0dffd3ac9ce..5d156c730faa 100644

> --- a/lib/efi_loader/efi_capsule.c

> +++ b/lib/efi_loader/efi_capsule.c

> @@ -206,6 +206,39 @@ skip:

>  	return NULL;

>  }

>  

> +/**

> + * efi_remove_auth_hdr - remove authentication data from image

> + * @image:	Pointer to pointer to Image

> + * @image_size:	Pointer to Image size

> + *

> + * Remove the authentication data from image if possible.

> + * Update @image and @image_size.

> + *

> + * Return:		status code

> + */

> +static efi_status_t efi_remove_auth_hdr(void **image, efi_uintn_t *image_size)

> +{

> +	struct efi_firmware_image_authentication *auth_hdr;

> +	efi_status_t ret = EFI_INVALID_PARAMETER;

> +

> +	auth_hdr = (struct efi_firmware_image_authentication *)*image;

> +	if (*image_size < sizeof(*auth_hdr))

> +		goto out;

> +

> +	if (auth_hdr->auth_info.hdr.dwLength <=

> +	    offsetof(struct win_certificate_uefi_guid, cert_data))

> +		goto out;

> +

> +	*image = (uint8_t *)*image + sizeof(auth_hdr->monotonic_count) +

> +		auth_hdr->auth_info.hdr.dwLength;

> +	*image_size = *image_size - auth_hdr->auth_info.hdr.dwLength -

> +		sizeof(auth_hdr->monotonic_count);

> +

> +	ret = EFI_SUCCESS;

> +out:

> +	return ret;

> +}

> +

>  #if defined(CONFIG_EFI_CAPSULE_AUTHENTICATE)

>  

>  #if defined(CONFIG_EFI_PKEY_DTB_EMBED)

> @@ -271,21 +304,15 @@ efi_status_t efi_capsule_authenticate(const void *capsule, efi_uintn_t capsule_s

>  	if (capsule == NULL || capsule_size == 0)

>  		goto out;

>  

> -	auth_hdr = (struct efi_firmware_image_authentication *)capsule;

> -	if (capsule_size < sizeof(*auth_hdr))

> -		goto out;

> -

> -	if (auth_hdr->auth_info.hdr.dwLength <=

> -	    offsetof(struct win_certificate_uefi_guid, cert_data))

> +	*image = (uint8_t *)capsule;

> +	*image_size = capsule_size;

> +	if (efi_remove_auth_hdr(image, image_size) != EFI_SUCCESS)

>  		goto out;

>  

> +	auth_hdr = (struct efi_firmware_image_authentication *)capsule;

>  	if (guidcmp(&auth_hdr->auth_info.cert_type, &efi_guid_cert_type_pkcs7))

>  		goto out;

>  

> -	*image = (uint8_t *)capsule + sizeof(auth_hdr->monotonic_count) +

> -		auth_hdr->auth_info.hdr.dwLength;

> -	*image_size = capsule_size - auth_hdr->auth_info.hdr.dwLength -

> -		sizeof(auth_hdr->monotonic_count);

>  	memcpy(&monotonic_count, &auth_hdr->monotonic_count,

>  	       sizeof(monotonic_count));

>  

> @@ -367,7 +394,7 @@ static efi_status_t efi_capsule_update_firmware(

>  {

>  	struct efi_firmware_management_capsule_header *capsule;

>  	struct efi_firmware_management_capsule_image_header *image;

> -	size_t capsule_size;

> +	size_t capsule_size, image_binary_size;

>  	void *image_binary, *vendor_code;

>  	efi_handle_t *handles;

>  	efi_uintn_t no_handles;

> @@ -429,13 +456,30 @@ static efi_status_t efi_capsule_update_firmware(

>  		}

>  

>  		/* do update */

> +		if (IS_ENABLED(CONFIG_EFI_CAPSULE_AUTHENTICATE) &&

> +		    !(image->image_capsule_support &

> +				CAPSULE_SUPPORT_AUTHENTICATION)) {

> +			/* no signature */

> +			ret = EFI_SECURITY_VIOLATION;

> +			goto out;

> +		}

> +

>  		image_binary = (void *)image + sizeof(*image);

> -		vendor_code = image_binary + image->update_image_size;

> +		image_binary_size = image->update_image_size;

> +		vendor_code = image_binary + image_binary_size;

> +		if (!IS_ENABLED(CONFIG_EFI_CAPSULE_AUTHENTICATE) &&

> +		    (image->image_capsule_support &

> +				CAPSULE_SUPPORT_AUTHENTICATION)) {

> +			ret = efi_remove_auth_hdr(&image_binary,

> +						  &image_binary_size);

> +			if (ret != EFI_SUCCESS)

> +				goto out;

> +		}

>  

>  		abort_reason = NULL;

>  		ret = EFI_CALL(fmp->set_image(fmp, image->update_image_index,

>  					      image_binary,

> -					      image->update_image_size,

> +					      image_binary_size,

>  					      vendor_code, NULL,

>  					      &abort_reason));

>  		if (ret != EFI_SUCCESS) {

> -- 

> 2.31.0

>
diff mbox series

Patch

diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c
index b0dffd3ac9ce..5d156c730faa 100644
--- a/lib/efi_loader/efi_capsule.c
+++ b/lib/efi_loader/efi_capsule.c
@@ -206,6 +206,39 @@  skip:
 	return NULL;
 }
 
+/**
+ * efi_remove_auth_hdr - remove authentication data from image
+ * @image:	Pointer to pointer to Image
+ * @image_size:	Pointer to Image size
+ *
+ * Remove the authentication data from image if possible.
+ * Update @image and @image_size.
+ *
+ * Return:		status code
+ */
+static efi_status_t efi_remove_auth_hdr(void **image, efi_uintn_t *image_size)
+{
+	struct efi_firmware_image_authentication *auth_hdr;
+	efi_status_t ret = EFI_INVALID_PARAMETER;
+
+	auth_hdr = (struct efi_firmware_image_authentication *)*image;
+	if (*image_size < sizeof(*auth_hdr))
+		goto out;
+
+	if (auth_hdr->auth_info.hdr.dwLength <=
+	    offsetof(struct win_certificate_uefi_guid, cert_data))
+		goto out;
+
+	*image = (uint8_t *)*image + sizeof(auth_hdr->monotonic_count) +
+		auth_hdr->auth_info.hdr.dwLength;
+	*image_size = *image_size - auth_hdr->auth_info.hdr.dwLength -
+		sizeof(auth_hdr->monotonic_count);
+
+	ret = EFI_SUCCESS;
+out:
+	return ret;
+}
+
 #if defined(CONFIG_EFI_CAPSULE_AUTHENTICATE)
 
 #if defined(CONFIG_EFI_PKEY_DTB_EMBED)
@@ -271,21 +304,15 @@  efi_status_t efi_capsule_authenticate(const void *capsule, efi_uintn_t capsule_s
 	if (capsule == NULL || capsule_size == 0)
 		goto out;
 
-	auth_hdr = (struct efi_firmware_image_authentication *)capsule;
-	if (capsule_size < sizeof(*auth_hdr))
-		goto out;
-
-	if (auth_hdr->auth_info.hdr.dwLength <=
-	    offsetof(struct win_certificate_uefi_guid, cert_data))
+	*image = (uint8_t *)capsule;
+	*image_size = capsule_size;
+	if (efi_remove_auth_hdr(image, image_size) != EFI_SUCCESS)
 		goto out;
 
+	auth_hdr = (struct efi_firmware_image_authentication *)capsule;
 	if (guidcmp(&auth_hdr->auth_info.cert_type, &efi_guid_cert_type_pkcs7))
 		goto out;
 
-	*image = (uint8_t *)capsule + sizeof(auth_hdr->monotonic_count) +
-		auth_hdr->auth_info.hdr.dwLength;
-	*image_size = capsule_size - auth_hdr->auth_info.hdr.dwLength -
-		sizeof(auth_hdr->monotonic_count);
 	memcpy(&monotonic_count, &auth_hdr->monotonic_count,
 	       sizeof(monotonic_count));
 
@@ -367,7 +394,7 @@  static efi_status_t efi_capsule_update_firmware(
 {
 	struct efi_firmware_management_capsule_header *capsule;
 	struct efi_firmware_management_capsule_image_header *image;
-	size_t capsule_size;
+	size_t capsule_size, image_binary_size;
 	void *image_binary, *vendor_code;
 	efi_handle_t *handles;
 	efi_uintn_t no_handles;
@@ -429,13 +456,30 @@  static efi_status_t efi_capsule_update_firmware(
 		}
 
 		/* do update */
+		if (IS_ENABLED(CONFIG_EFI_CAPSULE_AUTHENTICATE) &&
+		    !(image->image_capsule_support &
+				CAPSULE_SUPPORT_AUTHENTICATION)) {
+			/* no signature */
+			ret = EFI_SECURITY_VIOLATION;
+			goto out;
+		}
+
 		image_binary = (void *)image + sizeof(*image);
-		vendor_code = image_binary + image->update_image_size;
+		image_binary_size = image->update_image_size;
+		vendor_code = image_binary + image_binary_size;
+		if (!IS_ENABLED(CONFIG_EFI_CAPSULE_AUTHENTICATE) &&
+		    (image->image_capsule_support &
+				CAPSULE_SUPPORT_AUTHENTICATION)) {
+			ret = efi_remove_auth_hdr(&image_binary,
+						  &image_binary_size);
+			if (ret != EFI_SUCCESS)
+				goto out;
+		}
 
 		abort_reason = NULL;
 		ret = EFI_CALL(fmp->set_image(fmp, image->update_image_index,
 					      image_binary,
-					      image->update_image_size,
+					      image_binary_size,
 					      vendor_code, NULL,
 					      &abort_reason));
 		if (ret != EFI_SUCCESS) {