[2/2] brcmfmac: pcie: Provide a buffer of random bytes to the device

Message ID 20230214080034.3828-3-marcan@marcan.st
State New
Headers
Series Apple T2 platform support |

Commit Message

Hector Martin Feb. 14, 2023, 8 a.m. UTC
  Newer Apple firmwares on chipsets without a hardware RNG require the
host to provide a buffer of 256 random bytes to the device on
initialization. This buffer is present immediately before NVRAM,
suffixed by a footer containing a magic number and the buffer length.

This won't affect chips/firmwares that do not use this feature, so do it
unconditionally for all Apple platforms (those with an Apple OTP).

Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Hector Martin <marcan@marcan.st>
---
 .../broadcom/brcm80211/brcmfmac/pcie.c        | 32 +++++++++++++++++++
 1 file changed, 32 insertions(+)
  

Comments

Julian Calaby Feb. 14, 2023, 9 a.m. UTC | #1
Hi Arend,

On Tue, Feb 14, 2023 at 7:04 PM Hector Martin <marcan@marcan.st> wrote:
>
> Newer Apple firmwares on chipsets without a hardware RNG require the
> host to provide a buffer of 256 random bytes to the device on
> initialization. This buffer is present immediately before NVRAM,
> suffixed by a footer containing a magic number and the buffer length.
>
> This won't affect chips/firmwares that do not use this feature, so do it
> unconditionally for all Apple platforms (those with an Apple OTP).

Following on from the conversation a year ago, is there a way to
detect chipsets that need these random bytes? While I'm sure Apple is
doing their own special thing for special Apple reasons, it seems
relatively sensible to omit a RNG on lower-cost chipsets, so would
other chipsets need it?

> Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
> Signed-off-by: Hector Martin <marcan@marcan.st>

Beyond that, it all seems pretty sensible.

Reviewed-by: Julian Calaby <julian.calaby@gmail.com>

> ---
>  .../broadcom/brcm80211/brcmfmac/pcie.c        | 32 +++++++++++++++++++
>  1 file changed, 32 insertions(+)

Thanks,
  
Hector Martin Feb. 14, 2023, 9:08 a.m. UTC | #2
On 14/02/2023 18.00, Julian Calaby wrote:
> Hi Arend,
> 
> On Tue, Feb 14, 2023 at 7:04 PM Hector Martin <marcan@marcan.st> wrote:
>>
>> Newer Apple firmwares on chipsets without a hardware RNG require the
>> host to provide a buffer of 256 random bytes to the device on
>> initialization. This buffer is present immediately before NVRAM,
>> suffixed by a footer containing a magic number and the buffer length.
>>
>> This won't affect chips/firmwares that do not use this feature, so do it
>> unconditionally for all Apple platforms (those with an Apple OTP).
> 
> Following on from the conversation a year ago, is there a way to
> detect chipsets that need these random bytes? While I'm sure Apple is
> doing their own special thing for special Apple reasons, it seems
> relatively sensible to omit a RNG on lower-cost chipsets, so would
> other chipsets need it?

I think we could include a list of chips known not to have the RNG (I
think it's only the ones shipped on T2 machines). The main issue is I
don't have access to those machines so it's hard for me to test exactly
which ones need it. IIRC Apple's driver unconditionally provides the
randomness. I could at least test the newer chips on AS platforms and
figure out if they need it to exclude them... but then again, all I can
do is test whether they work without the blob, but they might still want
it (and simply become less secure without it).

So I guess the answer is "maybe, I don't know, and it's kind of hard to
know for sure"... the joys of reverse engineering hardware without
vendor documentation.

If you mean whether other chips with non-apple firmware can use this, I
have no idea. That's probably something for Arend to answer. My gut
feeling is Apple added this as part of a hardening mechanism and
non-Apple firmware does not use it (and Broadcom then probably started
shipping chips with a hardware RNG and firmware that uses it directly
across all vendors), in which case the answer is no.

- Hector
  
Julian Calaby Feb. 14, 2023, 9:11 a.m. UTC | #3
Hi Hector,

On Tue, Feb 14, 2023 at 8:08 PM Hector Martin <marcan@marcan.st> wrote:
>
> On 14/02/2023 18.00, Julian Calaby wrote:
> > Hi Arend,
> >
> > On Tue, Feb 14, 2023 at 7:04 PM Hector Martin <marcan@marcan.st> wrote:
> >>
> >> Newer Apple firmwares on chipsets without a hardware RNG require the
> >> host to provide a buffer of 256 random bytes to the device on
> >> initialization. This buffer is present immediately before NVRAM,
> >> suffixed by a footer containing a magic number and the buffer length.
> >>
> >> This won't affect chips/firmwares that do not use this feature, so do it
> >> unconditionally for all Apple platforms (those with an Apple OTP).
> >
> > Following on from the conversation a year ago, is there a way to
> > detect chipsets that need these random bytes? While I'm sure Apple is
> > doing their own special thing for special Apple reasons, it seems
> > relatively sensible to omit a RNG on lower-cost chipsets, so would
> > other chipsets need it?
>
> I think we could include a list of chips known not to have the RNG (I
> think it's only the ones shipped on T2 machines). The main issue is I
> don't have access to those machines so it's hard for me to test exactly
> which ones need it. IIRC Apple's driver unconditionally provides the
> randomness. I could at least test the newer chips on AS platforms and
> figure out if they need it to exclude them... but then again, all I can
> do is test whether they work without the blob, but they might still want
> it (and simply become less secure without it).
>
> So I guess the answer is "maybe, I don't know, and it's kind of hard to
> know for sure"... the joys of reverse engineering hardware without
> vendor documentation.
>
> If you mean whether other chips with non-apple firmware can use this, I
> have no idea. That's probably something for Arend to answer. My gut
> feeling is Apple added this as part of a hardening mechanism and
> non-Apple firmware does not use it (and Broadcom then probably started
> shipping chips with a hardware RNG and firmware that uses it directly
> across all vendors), in which case the answer is no.

Sorry, I should have been more clear, I wasn't expecting you to know,
I was asking Arend if he knew.

Thanks,
  

Patch

diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
index f320b6ce8bff..a7b88ab609c2 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
@@ -15,6 +15,7 @@ 
 #include <linux/sched/signal.h>
 #include <linux/kthread.h>
 #include <linux/io.h>
+#include <linux/random.h>
 #include <asm/unaligned.h>
 
 #include <soc.h>
@@ -1653,6 +1654,13 @@  brcmf_pcie_init_share_ram_info(struct brcmf_pciedev_info *devinfo,
 	return 0;
 }
 
+struct brcmf_random_seed_footer {
+	__le32 length;
+	__le32 magic;
+};
+
+#define BRCMF_RANDOM_SEED_MAGIC		0xfeedc0de
+#define BRCMF_RANDOM_SEED_LENGTH	0x100
 
 static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo,
 					const struct firmware *fw, void *nvram,
@@ -1689,6 +1697,30 @@  static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo,
 			  nvram_len;
 		memcpy_toio(devinfo->tcm + address, nvram, nvram_len);
 		brcmf_fw_nvram_free(nvram);
+
+		if (devinfo->otp.valid) {
+			size_t rand_len = BRCMF_RANDOM_SEED_LENGTH;
+			struct brcmf_random_seed_footer footer = {
+				.length = cpu_to_le32(rand_len),
+				.magic = cpu_to_le32(BRCMF_RANDOM_SEED_MAGIC),
+			};
+			void *randbuf;
+
+			/* Some Apple chips/firmwares expect a buffer of random
+			 * data to be present before NVRAM
+			 */
+			brcmf_dbg(PCIE, "Download random seed\n");
+
+			address -= sizeof(footer);
+			memcpy_toio(devinfo->tcm + address, &footer,
+				    sizeof(footer));
+
+			address -= rand_len;
+			randbuf = kzalloc(rand_len, GFP_KERNEL);
+			get_random_bytes(randbuf, rand_len);
+			memcpy_toio(devinfo->tcm + address, randbuf, rand_len);
+			kfree(randbuf);
+		}
 	} else {
 		brcmf_dbg(PCIE, "No matching NVRAM file found %s\n",
 			  devinfo->nvram_name);