diff mbox

[U-Boot] ARMv8/sec_firmware : Update chosen/kaslr-seed

Message ID 1494634025-22588-1-git-send-email-ruchika.gupta@nxp.com
State Changes Requested
Delegated to: Tom Rini
Headers show

Commit Message

Ruchika Gupta May 13, 2017, 12:07 a.m. UTC
kASLR support in kernel requires a random number to be passed via
chosen/kaslr-seed propert. sec_firmware generates this random seed
which can then be passed in the device tree node

sec_firmware reserves JR3 for it's own usage. Node for JR3 is
removed from device-tree.

Signed-off-by: Ruchika Gupta <ruchika.gupta@nxp.com>
---
 arch/arm/cpu/armv8/fsl-layerscape/fdt.c   | 73 +++++++++++++++++++++++++++++++
 arch/arm/cpu/armv8/sec_firmware.c         | 53 ++++++++++++++++++++++
 arch/arm/include/asm/armv8/sec_firmware.h |  9 ++++
 3 files changed, 135 insertions(+)

Comments

Tom Rini May 14, 2017, 3:38 p.m. UTC | #1
On Sat, May 13, 2017 at 05:37:05AM +0530, Ruchika Gupta wrote:

> kASLR support in kernel requires a random number to be passed via
> chosen/kaslr-seed propert. sec_firmware generates this random seed
> which can then be passed in the device tree node
> 
> sec_firmware reserves JR3 for it's own usage. Node for JR3 is
> removed from device-tree.
> 
> Signed-off-by: Ruchika Gupta <ruchika.gupta@nxp.com>
[snip]
> @@ -345,6 +345,75 @@ static void fdt_fixup_msi(void *blob)
>  }
>  #endif
>  
> +
> +int fdt_fixup_kaslr(void *fdt)

There's a few places like this where you're adding extra whitespace,
please fix.
Peter Robinson May 15, 2017, 12:48 p.m. UTC | #2
On Sat, May 13, 2017 at 1:07 AM, Ruchika Gupta <ruchika.gupta@nxp.com> wrote:
> kASLR support in kernel requires a random number to be passed via
> chosen/kaslr-seed propert. sec_firmware generates this random seed
> which can then be passed in the device tree node

Is that functionality generic that it can be consumed by other devices?

> sec_firmware reserves JR3 for it's own usage. Node for JR3 is
> removed from device-tree.
>
> Signed-off-by: Ruchika Gupta <ruchika.gupta@nxp.com>
> ---
>  arch/arm/cpu/armv8/fsl-layerscape/fdt.c   | 73 +++++++++++++++++++++++++++++++
>  arch/arm/cpu/armv8/sec_firmware.c         | 53 ++++++++++++++++++++++
>  arch/arm/include/asm/armv8/sec_firmware.h |  9 ++++
>  3 files changed, 135 insertions(+)
>
> diff --git a/arch/arm/cpu/armv8/fsl-layerscape/fdt.c b/arch/arm/cpu/armv8/fsl-layerscape/fdt.c
> index 05c4577..d4ca129 100644
> --- a/arch/arm/cpu/armv8/fsl-layerscape/fdt.c
> +++ b/arch/arm/cpu/armv8/fsl-layerscape/fdt.c
> @@ -345,6 +345,75 @@ static void fdt_fixup_msi(void *blob)
>  }
>  #endif
>
> +
> +int fdt_fixup_kaslr(void *fdt)
> +{
> +       int nodeoffset;
> +       int err, ret = 0;
> +       u8 rand[8];
> +
> +#if defined(CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT)
> +       /* Check if random seed generation is  supported */
> +       if (sec_firmware_support_hwrng() == false)
> +               return 0;
> +
> +       ret = sec_firmware_get_random(rand, 8);
> +       if (ret < 0) {
> +               printf("WARNING: could not get random number to set",
> +                      "kaslr-seed\n");
> +               return 0;
> +       }
> +
> +       err = fdt_check_header(fdt);
> +       if (err < 0) {
> +               printf("fdt_chosen: %s\n", fdt_strerror(err));
> +               return 0;
> +       }
> +
> +       /* find or create "/chosen" node. */
> +       nodeoffset = fdt_find_or_add_subnode(fdt, 0, "chosen");
> +       if (nodeoffset < 0)
> +               return 0;
> +
> +       err = fdt_setprop(fdt, nodeoffset, "kaslr-seed", rand,
> +                                 sizeof(rand));
> +       if (err < 0) {
> +               printf("WARNING: could not set kaslr-seed %s.\n",
> +                      fdt_strerror(err));
> +               return 0;
> +       }
> +       ret = 1;
> +#endif
> +
> +       return ret;
> +}
> +
> +/* Remove JR node used by SEC firmware */
> +void fdt_fixup_remove_jr(void *blob)
> +{
> +       int jr_node, addr_cells, len;
> +       int crypto_node = fdt_path_offset(blob, "crypto");
> +       u64 jr_offset, used_jr;
> +       fdt32_t *reg;
> +
> +       used_jr = sec_firmware_used_jobring_offset();
> +       of_bus_default_count_cells(blob, crypto_node, &addr_cells, NULL);
> +
> +       jr_node = fdt_node_offset_by_compatible(blob, crypto_node,
> +                                               "fsl,sec-v4.0-job-ring");
> +
> +       while (jr_node != -FDT_ERR_NOTFOUND) {
> +               reg = (fdt32_t *)fdt_getprop(blob, jr_node, "reg", &len);
> +               jr_offset = of_read_number(reg, addr_cells);
> +               if (jr_offset == used_jr) {
> +                       fdt_del_node(blob, jr_node);
> +                       break;
> +               }
> +               jr_node = fdt_node_offset_by_compatible(blob, jr_node,
> +                                                       "fsl,sec-v4.0-job-ring");
> +       }
> +}
> +
>  void ft_cpu_setup(void *blob, bd_t *bd)
>  {
>  #ifdef CONFIG_FSL_LSCH2
> @@ -358,6 +427,9 @@ void ft_cpu_setup(void *blob, bd_t *bd)
>         else {
>                 ccsr_sec_t __iomem *sec;
>
> +               if (fdt_fixup_kaslr(blob))
> +                       fdt_fixup_remove_jr(blob);
> +
>                 sec = (void __iomem *)CONFIG_SYS_FSL_SEC_ADDR;
>                 fdt_fixup_crypto_node(blob, sec_in32(&sec->secvid_ms));
>         }
> @@ -396,4 +468,5 @@ void ft_cpu_setup(void *blob, bd_t *bd)
>  #ifdef CONFIG_HAS_FEATURE_ENHANCED_MSI
>         fdt_fixup_msi(blob);
>  #endif
> +
>  }
> diff --git a/arch/arm/cpu/armv8/sec_firmware.c b/arch/arm/cpu/armv8/sec_firmware.c
> index 4afa3ad..f460cca 100644
> --- a/arch/arm/cpu/armv8/sec_firmware.c
> +++ b/arch/arm/cpu/armv8/sec_firmware.c
> @@ -232,6 +232,59 @@ unsigned int sec_firmware_support_psci_version(void)
>  #endif
>
>  /*
> + * Check with sec_firmware if it supports random number generation
> + * via HW RNG
> + *
> + * The return value will be true if it is supported
> + */
> +bool sec_firmware_support_hwrng(void)
> +{
> +       uint8_t rand[8];
> +       if (sec_firmware_addr & SEC_FIRMWARE_RUNNING) {
> +               if (!sec_firmware_get_random(rand, 8))
> +                       return true;
> +       }
> +
> +       return false;
> +}
> +
> +/*
> + * sec_firmware_get_random - Initialize the SEC Firmware
> + * @rand:              random number buffer to be filled
> + * @bytes:             Number of bytes of random number to be supported
> + * @eret:              -1 in case of error, 0 for success
> + */
> +int sec_firmware_get_random(uint8_t *rand, int bytes)
> +{
> +       unsigned long long num;
> +       struct pt_regs regs;
> +       int param1;
> +
> +       if (!bytes || bytes > 8) {
> +               printf("Max Random bytes genration supported is 8\n");
> +               return -1;
> +       }
> +#define SIP_RNG_64 0xC200FF11
> +       regs.regs[0] = SIP_RNG_64;
> +
> +       if (bytes <= 4)
> +               param1 = 0;
> +       else
> +               param1 = 1;
> +       regs.regs[1] = param1;
> +
> +       smc_call(&regs);
> +
> +       if (regs.regs[0])
> +               return -1;
> +
> +       num = regs.regs[1];
> +       memcpy(rand, &num, bytes);
> +
> +       return 0;
> +}
> +
> +/*
>   * sec_firmware_init - Initialize the SEC Firmware
>   * @sec_firmware_img:  the SEC Firmware image address
>   * @eret_hold_l:       the address to hold exception return address low
> diff --git a/arch/arm/include/asm/armv8/sec_firmware.h b/arch/arm/include/asm/armv8/sec_firmware.h
> index bc1d97d..1dc547a 100644
> --- a/arch/arm/include/asm/armv8/sec_firmware.h
> +++ b/arch/arm/include/asm/armv8/sec_firmware.h
> @@ -8,10 +8,13 @@
>  #define __SEC_FIRMWARE_H_
>
>  #define PSCI_INVALID_VER               0xffffffff
> +#define SEC_JR3_OFFSET                 0x40000
>
>  int sec_firmware_init(const void *, u32 *, u32 *);
>  int _sec_firmware_entry(const void *, u32 *, u32 *);
>  bool sec_firmware_is_valid(const void *);
> +bool sec_firmware_support_hwrng(void);
> +int sec_firmware_get_random(uint8_t *rand, int bytes);
>  #ifdef CONFIG_SEC_FIRMWARE_ARMV8_PSCI
>  unsigned int sec_firmware_support_psci_version(void);
>  unsigned int _sec_firmware_support_psci_version(void);
> @@ -22,4 +25,10 @@ static inline unsigned int sec_firmware_support_psci_version(void)
>  }
>  #endif
>
> +static inline unsigned int sec_firmware_used_jobring_offset(void)
> +{
> +       return SEC_JR3_OFFSET;
> +}
> +
> +
>  #endif /* __SEC_FIRMWARE_H_ */
> --
> 2.7.4
>
> _______________________________________________
> U-Boot mailing list
> U-Boot@lists.denx.de
> https://lists.denx.de/listinfo/u-boot
Ruchika Gupta May 17, 2017, 3:27 a.m. UTC | #3
> -----Original Message-----

> From: Peter Robinson [mailto:pbrobinson@gmail.com]

> Sent: Monday, May 15, 2017 6:18 PM

> To: Ruchika Gupta <ruchika.gupta@nxp.com>

> Cc: u-boot@lists.denx.de; sun.york@nxp.com; Prabhakar Kushwaha

> <prabhakar.kushwaha@nxp.com>

> Subject: Re: [U-Boot] [PATCH] ARMv8/sec_firmware : Update chosen/kaslr-

> seed

> 

> On Sat, May 13, 2017 at 1:07 AM, Ruchika Gupta <ruchika.gupta@nxp.com>

> wrote:

> > kASLR support in kernel requires a random number to be passed via

> > chosen/kaslr-seed propert. sec_firmware generates this random seed

> > which can then be passed in the device tree node

> 

> Is that functionality generic that it can be consumed by other devices?

Sec firmware is proprietary firmware which provides this random seed using HW engine on NXP devices.
Other devices would need to generate their own random seed to be passed as this property.

Ruchika
Peter Robinson May 17, 2017, 8:17 a.m. UTC | #4
>> -----Original Message-----
>> From: Peter Robinson [mailto:pbrobinson@gmail.com]
>> Sent: Monday, May 15, 2017 6:18 PM
>> To: Ruchika Gupta <ruchika.gupta@nxp.com>
>> Cc: u-boot@lists.denx.de; sun.york@nxp.com; Prabhakar Kushwaha
>> <prabhakar.kushwaha@nxp.com>
>> Subject: Re: [U-Boot] [PATCH] ARMv8/sec_firmware : Update chosen/kaslr-
>> seed
>>
>> On Sat, May 13, 2017 at 1:07 AM, Ruchika Gupta <ruchika.gupta@nxp.com>
>> wrote:
>> > kASLR support in kernel requires a random number to be passed via
>> > chosen/kaslr-seed propert. sec_firmware generates this random seed
>> > which can then be passed in the device tree node
>>
>> Is that functionality generic that it can be consumed by other devices?
> Sec firmware is proprietary firmware which provides this random seed using HW engine on NXP devices.
> Other devices would need to generate their own random seed to be passed as this property.

yes, my point was more shouldn't there be a generic framework for this
as the functionality isn't unique to the HW engine on the NXP devices,
even if the HW is, and kASLR is a pretty generic requirement.

I know Tom, Alexander, myself and others discussed such a thing at ELC
in Portland in February and if memory serves providing that seed via
the uefi boot services (I may have that terminology wrong) for ARMv8.
Tom/Alexander do you remember the details of that conversation, know
if anyone was working on it?

Peter
Alexander Graf May 17, 2017, 8:23 a.m. UTC | #5
On 17.05.17 10:17, Peter Robinson wrote:
>>> -----Original Message-----
>>> From: Peter Robinson [mailto:pbrobinson@gmail.com]
>>> Sent: Monday, May 15, 2017 6:18 PM
>>> To: Ruchika Gupta <ruchika.gupta@nxp.com>
>>> Cc: u-boot@lists.denx.de; sun.york@nxp.com; Prabhakar Kushwaha
>>> <prabhakar.kushwaha@nxp.com>
>>> Subject: Re: [U-Boot] [PATCH] ARMv8/sec_firmware : Update chosen/kaslr-
>>> seed
>>>
>>> On Sat, May 13, 2017 at 1:07 AM, Ruchika Gupta <ruchika.gupta@nxp.com>
>>> wrote:
>>>> kASLR support in kernel requires a random number to be passed via
>>>> chosen/kaslr-seed propert. sec_firmware generates this random seed
>>>> which can then be passed in the device tree node
>>>
>>> Is that functionality generic that it can be consumed by other devices?
>> Sec firmware is proprietary firmware which provides this random seed using HW engine on NXP devices.
>> Other devices would need to generate their own random seed to be passed as this property.
>
> yes, my point was more shouldn't there be a generic framework for this
> as the functionality isn't unique to the HW engine on the NXP devices,
> even if the HW is, and kASLR is a pretty generic requirement.
>
> I know Tom, Alexander, myself and others discussed such a thing at ELC
> in Portland in February and if memory serves providing that seed via
> the uefi boot services (I may have that terminology wrong) for ARMv8.
> Tom/Alexander do you remember the details of that conversation, know
> if anyone was working on it?

I think it's perfectly fine to have a proprietary implementation in 
EL3/EL1s that uses whatever hardware provides to fetch a random number. 
I'm surprised you provide that number to Linux using dt though.

So far, I was under the impression that the preferred path for kASLR is 
to use the EFI_RNG_PROTOCOL protocol from the EFI stub. You are 
obviously more than welcome to back that protocol implementation in an 
NXP proprietary fashion with home-grown smc calls.

Let me CC Ard to clarify.


Alex
Mark Kettenis May 17, 2017, 9:42 a.m. UTC | #6
> From: Peter Robinson <pbrobinson@gmail.com>
> Date: Wed, 17 May 2017 09:17:47 +0100
> 
> >> -----Original Message-----
> >> From: Peter Robinson [mailto:pbrobinson@gmail.com]
> >> Sent: Monday, May 15, 2017 6:18 PM
> >> To: Ruchika Gupta <ruchika.gupta@nxp.com>
> >> Cc: u-boot@lists.denx.de; sun.york@nxp.com; Prabhakar Kushwaha
> >> <prabhakar.kushwaha@nxp.com>
> >> Subject: Re: [U-Boot] [PATCH] ARMv8/sec_firmware : Update chosen/kaslr-
> >> seed
> >>
> >> On Sat, May 13, 2017 at 1:07 AM, Ruchika Gupta <ruchika.gupta@nxp.com>
> >> wrote:
> >> > kASLR support in kernel requires a random number to be passed via
> >> > chosen/kaslr-seed propert. sec_firmware generates this random seed
> >> > which can then be passed in the device tree node
> >>
> >> Is that functionality generic that it can be consumed by other devices?
> > Sec firmware is proprietary firmware which provides this random seed using HW engine on NXP devices.
> > Other devices would need to generate their own random seed to be passed as this property.
> 
> yes, my point was more shouldn't there be a generic framework for this
> as the functionality isn't unique to the HW engine on the NXP devices,
> even if the HW is, and kASLR is a pretty generic requirement.
> 
> I know Tom, Alexander, myself and others discussed such a thing at ELC
> in Portland in February and if memory serves providing that seed via
> the uefi boot services (I may have that terminology wrong) for ARMv8.
> Tom/Alexander do you remember the details of that conversation, know
> if anyone was working on it?

Having an implementation of EFI_RNG_PROTOCOL in U-Boot would be great.
On OpenBSD we would defenitely use that to have our ARM bootloaders
initialize the kernel .openbsd.randomdata[1] segment.

[1] https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/libexec/ld.so/SPECS.randomdata?rev=1.2&content-type=text/x-cvsweb-markup
Ard Biesheuvel May 17, 2017, 1:14 p.m. UTC | #7
On 17 May 2017 at 09:23, Alexander Graf <agraf@suse.de> wrote:
>
>
> On 17.05.17 10:17, Peter Robinson wrote:
>>>>
>>>> -----Original Message-----
>>>> From: Peter Robinson [mailto:pbrobinson@gmail.com]
>>>> Sent: Monday, May 15, 2017 6:18 PM
>>>> To: Ruchika Gupta <ruchika.gupta@nxp.com>
>>>> Cc: u-boot@lists.denx.de; sun.york@nxp.com; Prabhakar Kushwaha
>>>> <prabhakar.kushwaha@nxp.com>
>>>> Subject: Re: [U-Boot] [PATCH] ARMv8/sec_firmware : Update chosen/kaslr-
>>>> seed
>>>>
>>>> On Sat, May 13, 2017 at 1:07 AM, Ruchika Gupta <ruchika.gupta@nxp.com>
>>>> wrote:
>>>>>
>>>>> kASLR support in kernel requires a random number to be passed via
>>>>> chosen/kaslr-seed propert. sec_firmware generates this random seed
>>>>> which can then be passed in the device tree node
>>>>
>>>>
>>>> Is that functionality generic that it can be consumed by other devices?
>>>
>>> Sec firmware is proprietary firmware which provides this random seed
>>> using HW engine on NXP devices.
>>> Other devices would need to generate their own random seed to be passed
>>> as this property.
>>
>>
>> yes, my point was more shouldn't there be a generic framework for this
>> as the functionality isn't unique to the HW engine on the NXP devices,
>> even if the HW is, and kASLR is a pretty generic requirement.
>>
>> I know Tom, Alexander, myself and others discussed such a thing at ELC
>> in Portland in February and if memory serves providing that seed via
>> the uefi boot services (I may have that terminology wrong) for ARMv8.
>> Tom/Alexander do you remember the details of that conversation, know
>> if anyone was working on it?
>
>
> I think it's perfectly fine to have a proprietary implementation in EL3/EL1s
> that uses whatever hardware provides to fetch a random number. I'm surprised
> you provide that number to Linux using dt though.
>
> So far, I was under the impression that the preferred path for kASLR is to
> use the EFI_RNG_PROTOCOL protocol from the EFI stub. You are obviously more
> than welcome to back that protocol implementation in an NXP proprietary
> fashion with home-grown smc calls.
>
> Let me CC Ard to clarify.
>

/chosen/kaslr-seed is used by the EFI stub to communicate a KASLR
specific random seed to the early boot code, which is difficult to do
any other way. It is internal ABI, but given that the contents of
/chosen are unregulated, there is nothing preventing you from putting
a KASLR seed there if you are not booting via EFI.

However, /chosen/kaslr-seed is *not* the only random seed the EFI stub
retrieves from the platform via the EFI_RNG_PROTOCOL. There is also:
- the physical randomization seed, which affects where the EFI stub
relocates the kernel in physical memory,
- the LINUX_RNG EFI configuration table, which passes a seed to the
/dev/random routines so we have some entropy before devices are
probed,
- randomization of the virtual placement of the UEFI runtime services
code/data regions.

IOW, EFI_RNG_PROTOCOL is used in four different ways, and populating
/chosen/kaslr-seed directly only gives you one of those. If you are
not booting via EFI, there is no difference given that these other
three applications are not active anyway, but for EFI(-compatible)
boot, we should implement the EFI_RNG_PROTOCOL instead.
Tom Rini May 17, 2017, 9:57 p.m. UTC | #8
On Wed, May 17, 2017 at 02:14:28PM +0100, Ard Biesheuvel wrote:
> On 17 May 2017 at 09:23, Alexander Graf <agraf@suse.de> wrote:
> >
> >
> > On 17.05.17 10:17, Peter Robinson wrote:
> >>>>
> >>>> -----Original Message-----
> >>>> From: Peter Robinson [mailto:pbrobinson@gmail.com]
> >>>> Sent: Monday, May 15, 2017 6:18 PM
> >>>> To: Ruchika Gupta <ruchika.gupta@nxp.com>
> >>>> Cc: u-boot@lists.denx.de; sun.york@nxp.com; Prabhakar Kushwaha
> >>>> <prabhakar.kushwaha@nxp.com>
> >>>> Subject: Re: [U-Boot] [PATCH] ARMv8/sec_firmware : Update chosen/kaslr-
> >>>> seed
> >>>>
> >>>> On Sat, May 13, 2017 at 1:07 AM, Ruchika Gupta <ruchika.gupta@nxp.com>
> >>>> wrote:
> >>>>>
> >>>>> kASLR support in kernel requires a random number to be passed via
> >>>>> chosen/kaslr-seed propert. sec_firmware generates this random seed
> >>>>> which can then be passed in the device tree node
> >>>>
> >>>>
> >>>> Is that functionality generic that it can be consumed by other devices?
> >>>
> >>> Sec firmware is proprietary firmware which provides this random seed
> >>> using HW engine on NXP devices.
> >>> Other devices would need to generate their own random seed to be passed
> >>> as this property.
> >>
> >>
> >> yes, my point was more shouldn't there be a generic framework for this
> >> as the functionality isn't unique to the HW engine on the NXP devices,
> >> even if the HW is, and kASLR is a pretty generic requirement.
> >>
> >> I know Tom, Alexander, myself and others discussed such a thing at ELC
> >> in Portland in February and if memory serves providing that seed via
> >> the uefi boot services (I may have that terminology wrong) for ARMv8.
> >> Tom/Alexander do you remember the details of that conversation, know
> >> if anyone was working on it?
> >
> >
> > I think it's perfectly fine to have a proprietary implementation in EL3/EL1s
> > that uses whatever hardware provides to fetch a random number. I'm surprised
> > you provide that number to Linux using dt though.
> >
> > So far, I was under the impression that the preferred path for kASLR is to
> > use the EFI_RNG_PROTOCOL protocol from the EFI stub. You are obviously more
> > than welcome to back that protocol implementation in an NXP proprietary
> > fashion with home-grown smc calls.
> >
> > Let me CC Ard to clarify.
> >
> 
> /chosen/kaslr-seed is used by the EFI stub to communicate a KASLR
> specific random seed to the early boot code, which is difficult to do
> any other way. It is internal ABI, but given that the contents of
> /chosen are unregulated, there is nothing preventing you from putting
> a KASLR seed there if you are not booting via EFI.
> 
> However, /chosen/kaslr-seed is *not* the only random seed the EFI stub
> retrieves from the platform via the EFI_RNG_PROTOCOL. There is also:
> - the physical randomization seed, which affects where the EFI stub
> relocates the kernel in physical memory,
> - the LINUX_RNG EFI configuration table, which passes a seed to the
> /dev/random routines so we have some entropy before devices are
> probed,
> - randomization of the virtual placement of the UEFI runtime services
> code/data regions.
> 
> IOW, EFI_RNG_PROTOCOL is used in four different ways, and populating
> /chosen/kaslr-seed directly only gives you one of those. If you are
> not booting via EFI, there is no difference given that these other
> three applications are not active anyway, but for EFI(-compatible)
> boot, we should implement the EFI_RNG_PROTOCOL instead.

So it would be best, long term, to implement EFI_RNG_PROTOCOL so that
anyone using bootefi (Linux, GRUB, OpenBSD, etc) can get what randomness
they like, but it's not a problem for now to ad-hoc populate
/chosen/kaslr-seed as possible.  Yes?  Thanks!
Mark Kettenis May 17, 2017, 10:33 p.m. UTC | #9
> Date: Wed, 17 May 2017 17:57:04 -0400
> From: Tom Rini <trini@konsulko.com>
> 
> On Wed, May 17, 2017 at 02:14:28PM +0100, Ard Biesheuvel wrote:
> > On 17 May 2017 at 09:23, Alexander Graf <agraf@suse.de> wrote:
> > >
> > >
> > > On 17.05.17 10:17, Peter Robinson wrote:
> > >>>>
> > >>>> -----Original Message-----
> > >>>> From: Peter Robinson [mailto:pbrobinson@gmail.com]
> > >>>> Sent: Monday, May 15, 2017 6:18 PM
> > >>>> To: Ruchika Gupta <ruchika.gupta@nxp.com>
> > >>>> Cc: u-boot@lists.denx.de; sun.york@nxp.com; Prabhakar Kushwaha
> > >>>> <prabhakar.kushwaha@nxp.com>
> > >>>> Subject: Re: [U-Boot] [PATCH] ARMv8/sec_firmware : Update chosen/kas=
> lr-
> > >>>> seed
> > >>>>
> > >>>> On Sat, May 13, 2017 at 1:07 AM, Ruchika Gupta <ruchika.gupta@nxp.co=
> m>
> > >>>> wrote:
> > >>>>>
> > >>>>> kASLR support in kernel requires a random number to be passed via
> > >>>>> chosen/kaslr-seed propert. sec_firmware generates this random seed
> > >>>>> which can then be passed in the device tree node
> > >>>>
> > >>>>
> > >>>> Is that functionality generic that it can be consumed by other devic=
> es?
> > >>>
> > >>> Sec firmware is proprietary firmware which provides this random seed
> > >>> using HW engine on NXP devices.
> > >>> Other devices would need to generate their own random seed to be pass=
> ed
> > >>> as this property.
> > >>
> > >>
> > >> yes, my point was more shouldn't there be a generic framework for this
> > >> as the functionality isn't unique to the HW engine on the NXP devices,
> > >> even if the HW is, and kASLR is a pretty generic requirement.
> > >>
> > >> I know Tom, Alexander, myself and others discussed such a thing at ELC
> > >> in Portland in February and if memory serves providing that seed via
> > >> the uefi boot services (I may have that terminology wrong) for ARMv8.
> > >> Tom/Alexander do you remember the details of that conversation, know
> > >> if anyone was working on it?
> > >
> > >
> > > I think it's perfectly fine to have a proprietary implementation in EL3=
> /EL1s
> > > that uses whatever hardware provides to fetch a random number. I'm surp=
> rised
> > > you provide that number to Linux using dt though.
> > >
> > > So far, I was under the impression that the preferred path for kASLR is=
>  to
> > > use the EFI_RNG_PROTOCOL protocol from the EFI stub. You are obviously =
> more
> > > than welcome to back that protocol implementation in an NXP proprietary
> > > fashion with home-grown smc calls.
> > >
> > > Let me CC Ard to clarify.
> > >
> >=20
> > /chosen/kaslr-seed is used by the EFI stub to communicate a KASLR
> > specific random seed to the early boot code, which is difficult to do
> > any other way. It is internal ABI, but given that the contents of
> > /chosen are unregulated, there is nothing preventing you from putting
> > a KASLR seed there if you are not booting via EFI.
> >=20
> > However, /chosen/kaslr-seed is *not* the only random seed the EFI stub
> > retrieves from the platform via the EFI_RNG_PROTOCOL. There is also:
> > - the physical randomization seed, which affects where the EFI stub
> > relocates the kernel in physical memory,
> > - the LINUX_RNG EFI configuration table, which passes a seed to the
> > /dev/random routines so we have some entropy before devices are
> > probed,
> > - randomization of the virtual placement of the UEFI runtime services
> > code/data regions.
> >=20
> > IOW, EFI_RNG_PROTOCOL is used in four different ways, and populating
> > /chosen/kaslr-seed directly only gives you one of those. If you are
> > not booting via EFI, there is no difference given that these other
> > three applications are not active anyway, but for EFI(-compatible)
> > boot, we should implement the EFI_RNG_PROTOCOL instead.
> 
> So it would be best, long term, to implement EFI_RNG_PROTOCOL so that
> anyone using bootefi (Linux, GRUB, OpenBSD, etc) can get what randomness
> they like, but it's not a problem for now to ad-hoc populate
> /chosen/kaslr-seed as possible.  Yes?  Thanks!

Right; Perfect is the enemy of good enough ;)

Having driver code in the tree will help implementing EFI_RNG_PROTOCOL
support.  Since this is someting that is important to us, I actually
might actually work on in the near future.
diff mbox

Patch

diff --git a/arch/arm/cpu/armv8/fsl-layerscape/fdt.c b/arch/arm/cpu/armv8/fsl-layerscape/fdt.c
index 05c4577..d4ca129 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/fdt.c
+++ b/arch/arm/cpu/armv8/fsl-layerscape/fdt.c
@@ -345,6 +345,75 @@  static void fdt_fixup_msi(void *blob)
 }
 #endif
 
+
+int fdt_fixup_kaslr(void *fdt)
+{
+	int nodeoffset;
+	int err, ret = 0;
+	u8 rand[8];
+
+#if defined(CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT)
+	/* Check if random seed generation is  supported */
+	if (sec_firmware_support_hwrng() == false)
+		return 0;
+
+	ret = sec_firmware_get_random(rand, 8);
+	if (ret < 0) {
+		printf("WARNING: could not get random number to set",
+		       "kaslr-seed\n");
+		return 0;
+	}
+
+	err = fdt_check_header(fdt);
+	if (err < 0) {
+		printf("fdt_chosen: %s\n", fdt_strerror(err));
+		return 0;
+	}
+
+	/* find or create "/chosen" node. */
+	nodeoffset = fdt_find_or_add_subnode(fdt, 0, "chosen");
+	if (nodeoffset < 0)
+		return 0;
+
+	err = fdt_setprop(fdt, nodeoffset, "kaslr-seed", rand,
+				  sizeof(rand));
+	if (err < 0) {
+		printf("WARNING: could not set kaslr-seed %s.\n",
+		       fdt_strerror(err));
+		return 0;
+	}
+	ret = 1;
+#endif
+
+	return ret;
+}
+
+/* Remove JR node used by SEC firmware */
+void fdt_fixup_remove_jr(void *blob)
+{
+	int jr_node, addr_cells, len;
+	int crypto_node = fdt_path_offset(blob, "crypto");
+	u64 jr_offset, used_jr;
+	fdt32_t *reg;
+
+	used_jr = sec_firmware_used_jobring_offset();
+	of_bus_default_count_cells(blob, crypto_node, &addr_cells, NULL);
+
+	jr_node = fdt_node_offset_by_compatible(blob, crypto_node,
+						"fsl,sec-v4.0-job-ring");
+
+	while (jr_node != -FDT_ERR_NOTFOUND) {
+		reg = (fdt32_t *)fdt_getprop(blob, jr_node, "reg", &len);
+		jr_offset = of_read_number(reg, addr_cells);
+		if (jr_offset == used_jr) {
+			fdt_del_node(blob, jr_node);
+			break;
+		}
+		jr_node = fdt_node_offset_by_compatible(blob, jr_node,
+							"fsl,sec-v4.0-job-ring");
+	}
+}
+
 void ft_cpu_setup(void *blob, bd_t *bd)
 {
 #ifdef CONFIG_FSL_LSCH2
@@ -358,6 +427,9 @@  void ft_cpu_setup(void *blob, bd_t *bd)
 	else {
 		ccsr_sec_t __iomem *sec;
 
+		if (fdt_fixup_kaslr(blob))
+			fdt_fixup_remove_jr(blob);
+
 		sec = (void __iomem *)CONFIG_SYS_FSL_SEC_ADDR;
 		fdt_fixup_crypto_node(blob, sec_in32(&sec->secvid_ms));
 	}
@@ -396,4 +468,5 @@  void ft_cpu_setup(void *blob, bd_t *bd)
 #ifdef CONFIG_HAS_FEATURE_ENHANCED_MSI
 	fdt_fixup_msi(blob);
 #endif
+
 }
diff --git a/arch/arm/cpu/armv8/sec_firmware.c b/arch/arm/cpu/armv8/sec_firmware.c
index 4afa3ad..f460cca 100644
--- a/arch/arm/cpu/armv8/sec_firmware.c
+++ b/arch/arm/cpu/armv8/sec_firmware.c
@@ -232,6 +232,59 @@  unsigned int sec_firmware_support_psci_version(void)
 #endif
 
 /*
+ * Check with sec_firmware if it supports random number generation
+ * via HW RNG
+ *
+ * The return value will be true if it is supported
+ */
+bool sec_firmware_support_hwrng(void)
+{
+	uint8_t rand[8];
+	if (sec_firmware_addr & SEC_FIRMWARE_RUNNING) {
+		if (!sec_firmware_get_random(rand, 8))
+			return true;
+	}
+
+	return false;
+}
+
+/*
+ * sec_firmware_get_random - Initialize the SEC Firmware
+ * @rand:		random number buffer to be filled
+ * @bytes:		Number of bytes of random number to be supported
+ * @eret:		-1 in case of error, 0 for success
+ */
+int sec_firmware_get_random(uint8_t *rand, int bytes)
+{
+	unsigned long long num;
+	struct pt_regs regs;
+	int param1;
+
+	if (!bytes || bytes > 8) {
+		printf("Max Random bytes genration supported is 8\n");
+		return -1;
+	}
+#define SIP_RNG_64 0xC200FF11
+	regs.regs[0] = SIP_RNG_64;
+
+	if (bytes <= 4)
+		param1 = 0;
+	else
+		param1 = 1;
+	regs.regs[1] = param1;
+
+	smc_call(&regs);
+
+	if (regs.regs[0])
+		return -1;
+
+	num = regs.regs[1];
+	memcpy(rand, &num, bytes);
+
+	return 0;
+}
+
+/*
  * sec_firmware_init - Initialize the SEC Firmware
  * @sec_firmware_img:	the SEC Firmware image address
  * @eret_hold_l:	the address to hold exception return address low
diff --git a/arch/arm/include/asm/armv8/sec_firmware.h b/arch/arm/include/asm/armv8/sec_firmware.h
index bc1d97d..1dc547a 100644
--- a/arch/arm/include/asm/armv8/sec_firmware.h
+++ b/arch/arm/include/asm/armv8/sec_firmware.h
@@ -8,10 +8,13 @@ 
 #define __SEC_FIRMWARE_H_
 
 #define PSCI_INVALID_VER		0xffffffff
+#define SEC_JR3_OFFSET			0x40000
 
 int sec_firmware_init(const void *, u32 *, u32 *);
 int _sec_firmware_entry(const void *, u32 *, u32 *);
 bool sec_firmware_is_valid(const void *);
+bool sec_firmware_support_hwrng(void);
+int sec_firmware_get_random(uint8_t *rand, int bytes);
 #ifdef CONFIG_SEC_FIRMWARE_ARMV8_PSCI
 unsigned int sec_firmware_support_psci_version(void);
 unsigned int _sec_firmware_support_psci_version(void);
@@ -22,4 +25,10 @@  static inline unsigned int sec_firmware_support_psci_version(void)
 }
 #endif
 
+static inline unsigned int sec_firmware_used_jobring_offset(void)
+{
+	return SEC_JR3_OFFSET;
+}
+
+
 #endif /* __SEC_FIRMWARE_H_ */