All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Pali Rohár" <pali@kernel.org>
To: u-boot@lists.denx.de
Cc: Stefan Roese <sr@denx.de>, Tony Dinh <mibodhi@gmail.com>,
	Josua Mayer <josua@solid-run.com>
Subject: [PATCH RFC u-boot-mvebu 44/59] tools: kwbimage: Fix invalid secure boot header signature
Date: Tue, 21 Feb 2023 21:19:10 +0100	[thread overview]
Message-ID: <20230221201925.9644-45-pali@kernel.org> (raw)
In-Reply-To: <20230221201925.9644-1-pali@kernel.org>

Secure boot header signature is calculated from the image header with
zeroed header checksum. Calculation is done in add_secure_header_v1()
function. So after calling this function no header member except
main_hdr->checksum can be modified. Commit 2b0980c24027 ("tools: kwbimage:
Fill the real header size into the main header") broke this requirement as
final header size started to be filled into main_hdr->headersz_* members
after the add_secure_header_v1() call.

Fix this issue by following steps:
- Split header size and image data offset into two variables (headersz and
  *dataoff).
- Change image_headersz_v0() and add_binary_header_v1() functions to return
  real (unaligned) header size instead of image data offset.
- On every place use correct variable (headersz or *dataoff)

After these steps variable headersz is correctly filled into the
main_hdr->headersz_* members and so overwriting them in the end of the
image_create_v1() function is not needed anymore. Remove those overwriting
which effectively reverts changes in problematic commit without affecting
value in main_hdr->headersz_* members and makes secure boot header
signature valid again.

Fixes: 2b0980c24027 ("tools: kwbimage: Fill the real header size into the main header")
Signed-off-by: Pali Rohár <pali@kernel.org>
---
 tools/kwbimage.c | 41 ++++++++++++++---------------------------
 1 file changed, 14 insertions(+), 27 deletions(-)

diff --git a/tools/kwbimage.c b/tools/kwbimage.c
index a8a59c154b9c..da539541742d 100644
--- a/tools/kwbimage.c
+++ b/tools/kwbimage.c
@@ -959,7 +959,7 @@ static size_t image_headersz_v0(int *hasext)
 			*hasext = 1;
 	}
 
-	return image_headersz_align(headersz, image_get_bootfrom());
+	return headersz;
 }
 
 static void *image_create_v0(size_t *dataoff, struct image_tool_params *params,
@@ -972,10 +972,11 @@ static void *image_create_v0(size_t *dataoff, struct image_tool_params *params,
 	int has_ext = 0;
 
 	/*
-	 * Calculate the size of the header and the size of the
+	 * Calculate the size of the header and the offset of the
 	 * payload
 	 */
 	headersz = image_headersz_v0(&has_ext);
+	*dataoff = image_headersz_align(headersz, image_get_bootfrom());
 
 	image = malloc(headersz);
 	if (!image) {
@@ -990,7 +991,7 @@ static void *image_create_v0(size_t *dataoff, struct image_tool_params *params,
 	/* Fill in the main header */
 	main_hdr->blocksize =
 		cpu_to_le32(payloadsz);
-	main_hdr->srcaddr   = cpu_to_le32(headersz);
+	main_hdr->srcaddr   = cpu_to_le32(*dataoff);
 	main_hdr->ext       = has_ext;
 	main_hdr->version   = 0;
 	main_hdr->destaddr  = cpu_to_le32(params->addr);
@@ -1013,10 +1014,9 @@ static void *image_create_v0(size_t *dataoff, struct image_tool_params *params,
 	/*
 	 * For SATA srcaddr is specified in number of sectors.
 	 * This expects the sector size to be 512 bytes.
-	 * Header size is already aligned.
 	 */
 	if (main_hdr->blockid == IBR_HDR_SATA_ID)
-		main_hdr->srcaddr = cpu_to_le32(headersz / 512);
+		main_hdr->srcaddr = cpu_to_le32(le32_to_cpu(main_hdr->srcaddr) / 512);
 
 	/* For PCIe srcaddr is not used and must be set to 0xFFFFFFFF. */
 	if (main_hdr->blockid == IBR_HDR_PEX_ID)
@@ -1050,7 +1050,6 @@ static void *image_create_v0(size_t *dataoff, struct image_tool_params *params,
 	main_hdr->checksum = image_checksum8(image,
 					     sizeof(struct main_hdr_v0));
 
-	*dataoff = headersz;
 	return image;
 }
 
@@ -1064,10 +1063,6 @@ static size_t image_headersz_v1(int *hasext)
 	int cfgi;
 	int ret;
 
-	/*
-	 * Calculate the size of the header and the size of the
-	 * payload
-	 */
 	headersz = sizeof(struct main_hdr_v1);
 
 	if (image_get_csk_index() >= 0) {
@@ -1163,7 +1158,7 @@ static size_t image_headersz_v1(int *hasext)
 	if (count > 0)
 		headersz += sizeof(struct register_set_hdr_v1) + 8 * count + 4;
 
-	return image_headersz_align(headersz, image_get_bootfrom());
+	return headersz;
 }
 
 static int add_binary_header_v1(uint8_t **cur, uint8_t **next_ext,
@@ -1390,7 +1385,6 @@ static void *image_create_v1(size_t *dataoff, struct image_tool_params *params,
 {
 	struct image_cfg_element *e;
 	struct main_hdr_v1 *main_hdr;
-	struct opt_hdr_v1 *ohdr;
 	struct register_set_hdr_v1 *register_set_hdr;
 	struct secure_hdr_v1 *secure_hdr = NULL;
 	size_t headersz;
@@ -1401,12 +1395,13 @@ static void *image_create_v1(size_t *dataoff, struct image_tool_params *params,
 	uint8_t delay;
 
 	/*
-	 * Calculate the size of the header and the size of the
+	 * Calculate the size of the header and the offset of the
 	 * payload
 	 */
 	headersz = image_headersz_v1(&hasext);
 	if (headersz == 0)
 		return NULL;
+	*dataoff = image_headersz_align(headersz, image_get_bootfrom());
 
 	image = malloc(headersz);
 	if (!image) {
@@ -1428,7 +1423,7 @@ static void *image_create_v1(size_t *dataoff, struct image_tool_params *params,
 	main_hdr->headersz_msb = (headersz & 0xFFFF0000) >> 16;
 	main_hdr->destaddr     = cpu_to_le32(params->addr);
 	main_hdr->execaddr     = cpu_to_le32(params->ep);
-	main_hdr->srcaddr      = cpu_to_le32(headersz);
+	main_hdr->srcaddr      = cpu_to_le32(*dataoff);
 	main_hdr->ext          = hasext;
 	main_hdr->version      = 1;
 	main_hdr->blockid      = image_get_bootfrom();
@@ -1458,10 +1453,9 @@ static void *image_create_v1(size_t *dataoff, struct image_tool_params *params,
 	/*
 	 * For SATA srcaddr is specified in number of sectors.
 	 * This expects the sector size to be 512 bytes.
-	 * Header size is already aligned.
 	 */
 	if (main_hdr->blockid == IBR_HDR_SATA_ID)
-		main_hdr->srcaddr = cpu_to_le32(headersz / 512);
+		main_hdr->srcaddr = cpu_to_le32(le32_to_cpu(main_hdr->srcaddr) / 512);
 
 	/* For PCIe srcaddr is not used and must be set to 0xFFFFFFFF. */
 	if (main_hdr->blockid == IBR_HDR_PEX_ID)
@@ -1528,19 +1522,10 @@ static void *image_create_v1(size_t *dataoff, struct image_tool_params *params,
 					      &datai, delay);
 	}
 
-	if (secure_hdr && add_secure_header_v1(params, ptr + headersz, payloadsz,
+	if (secure_hdr && add_secure_header_v1(params, ptr + *dataoff, payloadsz,
 					       image, headersz, secure_hdr))
 		return NULL;
 
-	*dataoff = headersz;
-
-	/* Fill the real header size without padding into the main header */
-	headersz = sizeof(*main_hdr);
-	for_each_opt_hdr_v1 (ohdr, main_hdr)
-		headersz += opt_hdr_v1_size(ohdr);
-	main_hdr->headersz_lsb = cpu_to_le16(headersz & 0xFFFF);
-	main_hdr->headersz_msb = (headersz & 0xFFFF0000) >> 16;
-
 	/* Calculate and set the header checksum */
 	main_hdr->checksum = image_checksum8(main_hdr, headersz);
 
@@ -1889,7 +1874,7 @@ static void kwbimage_set_header(void *ptr, struct stat *sbuf, int ifd,
 	memcpy((uint8_t *)ptr + dataoff + datasz, &checksum, sizeof(uint32_t));
 
 	/* Finally copy the header into the image area */
-	memcpy(ptr, image, dataoff);
+	memcpy(ptr, image, kwbheader_size(image));
 
 	free(image);
 }
@@ -2109,6 +2094,8 @@ static int kwbimage_generate(struct image_tool_params *params,
 		exit(EXIT_FAILURE);
 	}
 
+	alloc_len = image_headersz_align(alloc_len, image_get_bootfrom());
+
 	free(image_cfg);
 
 	hdr = malloc(alloc_len);
-- 
2.20.1


  parent reply	other threads:[~2023-02-21 20:36 UTC|newest]

Thread overview: 143+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-02-21 20:18 [PATCH RFC u-boot-mvebu 00/59] arm: mvebu: Various fixes Pali Rohár
2023-02-21 20:18 ` [PATCH RFC u-boot-mvebu 01/59] tools: kwbimage: Fix generating, verifying and extracting SDIO kwbimage Pali Rohár
2023-02-21 20:18 ` [PATCH RFC u-boot-mvebu 02/59] tools: kwboot: Fix parsing " Pali Rohár
2023-02-21 20:18 ` [PATCH RFC u-boot-mvebu 03/59] arm: mvebu: spl: " Pali Rohár
2023-02-21 20:18 ` [PATCH RFC u-boot-mvebu 04/59] cmd: mvebu/bubt: " Pali Rohár
2023-02-21 20:18 ` [PATCH RFC u-boot-mvebu 05/59] tools: kwbimage: Fix generating, verifying and extracting SATA kwbimage Pali Rohár
2023-02-21 20:18 ` [PATCH RFC u-boot-mvebu 06/59] tools: kwboot: Fix parsing " Pali Rohár
2023-02-21 20:18 ` [PATCH RFC u-boot-mvebu 07/59] arm: mvebu: spl: " Pali Rohár
2023-02-21 20:18 ` [PATCH RFC u-boot-mvebu 08/59] cmd: mvebu/bubt: " Pali Rohár
2023-02-21 20:18 ` [PATCH RFC u-boot-mvebu 09/59] arm: mvebu: spl: Remove checks for BOOT_DEVICE_MMC2 and BOOT_DEVICE_MMC2_2 Pali Rohár
2023-02-21 20:18 ` [PATCH RFC u-boot-mvebu 10/59] arm: mvebu: spl: Load proper U-Boot from selected eMMC boot partition Pali Rohár
2023-02-21 20:18 ` [PATCH RFC u-boot-mvebu 11/59] spl: mmc: Allow to disable SYS_MMCSD_FS_BOOT_PARTITION Pali Rohár
2023-02-21 20:18 ` [PATCH RFC u-boot-mvebu 12/59] arm: mvebu: spl: Fix support for loading U-Boot proper from SD card Pali Rohár
2023-02-21 20:18 ` [PATCH RFC u-boot-mvebu 13/59] tools: kwboot: Add more documentation references Pali Rohár
2023-02-21 20:18 ` [PATCH RFC u-boot-mvebu 14/59] tools: kwboot: Add image type documentation Pali Rohár
2023-02-21 20:18 ` [PATCH RFC u-boot-mvebu 15/59] tools: kwboot: Fix parsing UART image without data checksum Pali Rohár
2023-02-23  5:23   ` Tony Dinh
2023-02-21 20:18 ` [PATCH RFC u-boot-mvebu 16/59] tools: kwboot: Validate optional kwbimage v1 headers Pali Rohár
2023-02-21 20:18 ` [PATCH RFC u-boot-mvebu 17/59] tools: kwboot: Add check that kwbimage contains DDR init code Pali Rohár
2023-02-21 20:18 ` [PATCH RFC u-boot-mvebu 18/59] tools: kwboot: Fix patching of SPI/NOR XIP images Pali Rohár
2023-02-21 20:18 ` [PATCH RFC u-boot-mvebu 19/59] tools: kwboot: Show image type and error parsing reasons Pali Rohár
2023-02-22  5:51   ` Tony Dinh
2023-02-21 20:18 ` [PATCH RFC u-boot-mvebu 20/59] cmd: mvebu/bubt: Add support for selecting eMMC HW partition Pali Rohár
2023-02-22  9:55   ` Stefan Roese
2023-02-22 18:06     ` Pali Rohár
2023-02-23  6:17       ` Stefan Roese
2023-02-23  7:55         ` Pali Rohár
2023-02-23  8:15           ` Stefan Roese
2023-02-21 20:18 ` [PATCH RFC u-boot-mvebu 21/59] cmd: mvebu/bubt: Add support for writing image to SATA disk Pali Rohár
2023-02-21 20:18 ` [PATCH RFC u-boot-mvebu 22/59] cmd: mvebu/bubt: Add support for reading image from the SATA disk partition Pali Rohár
2023-02-21 20:18 ` [PATCH RFC u-boot-mvebu 23/59] cmd: mvebu/bubt: Rename variable image_size to hdr_size Pali Rohár
2023-02-21 20:18 ` [PATCH RFC u-boot-mvebu 24/59] cmd: mvebu/bubt: Mark all local symbols as static Pali Rohár
2023-02-21 20:18 ` [PATCH RFC u-boot-mvebu 25/59] cmd: mvebu/bubt: Do not modify image in A8K check_image_header() Pali Rohár
2023-02-21 20:18 ` [PATCH RFC u-boot-mvebu 26/59] cmd: mvebu/bubt: Check also A8K boot image checksum Pali Rohár
2023-02-21 20:18 ` [PATCH RFC u-boot-mvebu 27/59] cmd: mvebu/bubt: Set correct default image name for 32-bit Armada SoCs Pali Rohár
2023-02-21 20:18 ` [PATCH RFC u-boot-mvebu 28/59] cmd: mvebu/bubt: Better guess default MVEBU_*_BOOT option Pali Rohár
2023-02-21 20:18 ` [PATCH RFC u-boot-mvebu 29/59] cmd: mvebu/bubt: Fix warnings: unused variable 'secure_mode' and 'fuse_read_u64' defined but not used Pali Rohár
2023-02-21 20:18 ` [PATCH RFC u-boot-mvebu 30/59] cmd: mvebu/bubt: Enable command by default Pali Rohár
2023-02-21 20:18 ` [PATCH RFC u-boot-mvebu 31/59] tools: kwbimage: Fix dumping register set / DATA commands Pali Rohár
2023-02-21 20:18 ` [PATCH RFC u-boot-mvebu 32/59] tools: kwbimage: Fix endianity when dumping NAND_PAGE_SIZE Pali Rohár
2023-02-21 20:18 ` [PATCH RFC u-boot-mvebu 33/59] tools: kwbimage: Fix dumping NAND_BADBLK_LOCATION Pali Rohár
2023-02-21 20:19 ` [PATCH RFC u-boot-mvebu 34/59] tools: kwbimage: Fix dumping NAND_BLKSZ Pali Rohár
2023-02-21 20:19 ` [PATCH RFC u-boot-mvebu 35/59] tools: kwbimage: Fix generating of kwbimage v0 header checksum Pali Rohár
2023-02-21 20:19 ` [PATCH RFC u-boot-mvebu 36/59] tools: kwbimage: Fix endianity when printing kwbimage header Pali Rohár
2023-02-21 20:19 ` [PATCH RFC u-boot-mvebu 37/59] tools: kwbimage: Reject mkimage -F option Pali Rohár
2023-02-21 20:19 ` [PATCH RFC u-boot-mvebu 38/59] tools: kwbimage: Add support for dumping NAND_BLKSZ for v0 images Pali Rohár
2023-02-21 20:19 ` [PATCH RFC u-boot-mvebu 39/59] tools: kwbimage: Print binary image offset as size Pali Rohár
2023-02-21 20:19 ` [PATCH RFC u-boot-mvebu 40/59] tools: kwbimage: Print image data offset when printing kwbimage header Pali Rohár
2023-02-21 20:19 ` [PATCH RFC u-boot-mvebu 41/59] tools: kwbimage: Simplify add_secure_header_v1() Pali Rohár
2023-02-21 20:19 ` [PATCH RFC u-boot-mvebu 42/59] tools: kwbimage: Rename imagesz to dataoff Pali Rohár
2023-02-21 20:19 ` [PATCH RFC u-boot-mvebu 43/59] tools: kwbimage: Fix generating secure boot data image signature Pali Rohár
2023-02-21 20:19 ` Pali Rohár [this message]
2023-02-21 20:19 ` [PATCH RFC u-boot-mvebu 45/59] tools: mkimage: Do not fill legacy_img_hdr for non-legacy XIP images Pali Rohár
2023-02-21 20:19 ` [PATCH RFC u-boot-mvebu 46/59] tools: kwbimage: Add support for XIP SPI/NOR images Pali Rohár
2023-02-21 20:19 ` [PATCH RFC u-boot-mvebu 47/59] tools: mkimage: Print human readable error when -d is not specified Pali Rohár
2023-02-21 20:19 ` [PATCH RFC u-boot-mvebu 48/59] tools: mkimage: Do not try to open datafile when it is skipped Pali Rohár
2023-02-21 20:19 ` [PATCH RFC u-boot-mvebu 49/59] tools: kwbimage: Add support for creating an image with no data Pali Rohár
2023-02-21 20:19 ` [PATCH RFC u-boot-mvebu 50/59] arm: mvebu: Add support for generating NAND kwbimage Pali Rohár
2023-02-21 20:19 ` [PATCH RFC u-boot-mvebu 51/59] arm: mvebu: Add support for generating PEX kwbimage Pali Rohár
2023-02-21 20:19 ` [PATCH RFC u-boot-mvebu 52/59] arm: mvebu: Fix description of MVEBU_SPL_BOOT_DEVICE_(SPI|MMC) options Pali Rohár
2023-02-21 20:19 ` [PATCH RFC u-boot-mvebu 53/59] arm: mvebu: db-88f6820-amc: Add defconfig for NAND booting Pali Rohár
2023-02-21 20:19 ` [PATCH RFC u-boot-mvebu 54/59] arm: mvebu: clearfog: Add defconfig for SATA booting Pali Rohár
2023-02-21 20:19 ` [PATCH RFC u-boot-mvebu 55/59] arm: mvebu: Remove A39x relicts Pali Rohár
2023-02-21 20:19 ` [PATCH RFC u-boot-mvebu 56/59] arm: mvebu: Fix comment about CPU_ATTR_BOOTROM mapping Pali Rohár
2023-02-21 20:19 ` [PATCH RFC u-boot-mvebu 57/59] arm: mvebu: Define env_sf_get_env_addr() also for Proper U-Boot Pali Rohár
2023-02-25  3:58   ` Tony Dinh
2023-02-25 21:13     ` Pali Rohár
2023-02-25 22:37       ` Tony Dinh
2023-02-21 20:19 ` [PATCH RFC u-boot-mvebu 58/59] arm: mvebu: Define SPL memory maps Pali Rohár
2023-02-21 20:19 ` [PATCH RFC u-boot-mvebu 59/59] doc/kwboot.1: Update example description Pali Rohár
2023-02-21 23:06 ` [PATCH RFC u-boot-mvebu 00/59] arm: mvebu: Various fixes Tony Dinh
2023-02-21 23:14   ` Pali Rohár
2023-02-22  5:45     ` Tony Dinh
2023-02-22  7:58       ` Pali Rohár
2023-02-22 11:59         ` Martin Rowe
2023-02-22 18:03           ` Pali Rohár
2023-02-22 21:20             ` Martin Rowe
2023-02-22 21:23               ` Pali Rohár
2023-02-23 12:11                 ` Martin Rowe
2023-02-23 18:02                   ` Pali Rohár
2023-02-24  6:27                     ` Martin Rowe
2023-02-24 15:07                       ` Martin Rowe
2023-02-24 22:34                         ` Pali Rohár
2023-02-25  1:18                           ` Martin Rowe
2023-02-25 21:16                             ` Pali Rohár
2023-02-26  1:56                               ` Martin Rowe
2023-02-26  8:14                                 ` Pali Rohár
2023-03-08 20:36                             ` kwbimage config file documentation (Was: Re: [PATCH RFC u-boot-mvebu 00/59] arm: mvebu: Various fixes) Pali Rohár
2023-02-24 22:33                       ` [PATCH RFC u-boot-mvebu 00/59] arm: mvebu: Various fixes Pali Rohár
2023-02-24 15:07                 ` Martin Rowe
2023-02-24 15:22                   ` Stefan Roese
2023-02-24 15:41                     ` Martin Rowe
2023-02-23  7:56           ` Pali Rohár
2023-02-22 22:16         ` Tony Dinh
2023-02-22 23:06           ` Pali Rohár
2023-02-22 23:16             ` Tony Dinh
2023-02-22 23:39               ` Pali Rohár
2023-02-23  0:17                 ` Tony Dinh
2023-02-23  7:46                   ` Pali Rohár
2023-02-25  1:42 ` [PATCH 0/2] arm: mvebu: clearfog: defconfig updates Martin Rowe
2023-02-25  1:42   ` [PATCH 1/2] arm: mvebu: clearfog: Fix MMC detection Martin Rowe
2023-02-25 21:49     ` Pali Rohár
2023-02-25 22:14       ` Pali Rohár
2023-02-26  1:45         ` Martin Rowe
2023-02-26 11:18           ` Pali Rohár
2023-02-26 11:28             ` Martin Rowe
2023-02-25  1:42   ` [PATCH 2/2] arm: mvebu: clearfog: Add defconfig for SPI booting Martin Rowe
2023-02-25  7:41     ` Pali Rohár
2023-02-25  9:48       ` Martin Rowe
2023-02-25 10:51         ` Josua Mayer
2023-02-25 11:47           ` Martin Rowe
2023-02-25 13:41             ` Pali Rohár
2023-02-25 22:46               ` Tony Dinh
2023-02-26  2:17                 ` Martin Rowe
2023-02-26  4:56                   ` Tony Dinh
2023-02-26 10:52                     ` Pali Rohár
2023-02-27  0:11                       ` Tony Dinh
2023-02-27  7:40                         ` Stefan Roese
2023-02-27 21:57                           ` Tony Dinh
2023-02-27 23:41                             ` Tony Dinh
2023-02-28  0:42                               ` Tony Dinh
2023-02-28  1:17                                 ` Tony Dinh
2023-02-28  9:48                                   ` Pali Rohár
2023-02-28 18:51                                     ` Pali Rohár
2023-02-28 21:51                                       ` Tony Dinh
2023-02-28 22:19                                         ` Pali Rohár
2023-03-01  1:32                                           ` Tony Dinh
2023-03-03  1:28                             ` Tony Dinh
2023-02-25 21:55           ` Pali Rohár
2023-02-25 22:00 ` [PATCH RFC u-boot-mvebu 00/59] arm: mvebu: Various fixes Pali Rohár
2023-02-27  7:44   ` Stefan Roese
2023-02-27  8:04     ` Pali Rohár
2023-02-27 11:29       ` Martin Rowe
2023-02-28  7:03         ` Stefan Roese
2023-02-28  9:16           ` Stefan Roese
2023-02-28  9:54           ` Pali Rohár
2023-02-28 10:01             ` Stefan Roese
2023-02-28 10:10               ` Pali Rohár
2023-02-28 10:16                 ` Stefan Roese
2023-02-28 22:41                   ` Pali Rohár
2023-03-01  6:01                     ` Stefan Roese
2023-02-28 10:22                 ` Pali Rohár
2023-03-01 15:48 ` Stefan Roese

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230221201925.9644-45-pali@kernel.org \
    --to=pali@kernel.org \
    --cc=josua@solid-run.com \
    --cc=mibodhi@gmail.com \
    --cc=sr@denx.de \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.