Nice.

Mike -- does this collide with your current work, or does it
not impact it?

Mark Kettenis <[email protected]> wrote:

> The UEFI standard defines an (optional) protocol for getting random
> numbers.  A while back I wrote support for this for the arm64
> bootloader.  But we should use this on amd64 as well.  I tested that
> this actually works on a machine with a recent AMD Ryzen APU.  Not
> sure if the firmware implements this using RDRAND or if it uses the
> random number generator of the integrated crypto unit.  Either way,
> this can't make matters worse since the "entropy" is XORed into the
> random data buffer.
> 
> ok?
> 
> 
> Index: arch/amd64/stand/efiboot/Makefile.common
> ===================================================================
> RCS file: /cvs/src/sys/arch/amd64/stand/efiboot/Makefile.common,v
> retrieving revision 1.14
> diff -u -p -r1.14 Makefile.common
> --- arch/amd64/stand/efiboot/Makefile.common  20 Apr 2019 22:59:03 -0000      
> 1.14
> +++ arch/amd64/stand/efiboot/Makefile.common  4 May 2019 20:59:48 -0000
> @@ -11,7 +11,7 @@ EFI_HEAP_LIMIT=     0xc00000
>  
>  LDFLAGS+=    -nostdlib -T${.CURDIR}/../${LDSCRIPT} -Bsymbolic -shared
>  
> -COPTS+=              -DEFIBOOT -DNEEDS_HEAP_H -I${.CURDIR}/..
> +COPTS+=              -DEFIBOOT -DFWRANDOM -DNEEDS_HEAP_H -I${.CURDIR}/..
>  COPTS+=              -I${EFIDIR}/include -I${S}/stand/boot
>  COPTS+=              -ffreestanding -std=gnu99
>  COPTS+=              -fshort-wchar -fPIC -mno-red-zone
> @@ -24,7 +24,7 @@ AFLAGS+=    -pipe -fPIC
>  
>  .PATH:       ${.CURDIR}/..
>  SRCS+=       self_reloc.c
> -SRCS+=       efiboot.c efidev.c efipxe.c
> +SRCS+=       efiboot.c efidev.c efipxe.c efirng.c
>  SRCS+=       conf.c
>  
>  .PATH:       ${S}/stand/boot
> Index: arch/amd64/stand/efiboot/efirng.c
> ===================================================================
> RCS file: arch/amd64/stand/efiboot/efirng.c
> diff -N arch/amd64/stand/efiboot/efirng.c
> --- /dev/null 1 Jan 1970 00:00:00 -0000
> +++ arch/amd64/stand/efiboot/efirng.c 4 May 2019 20:59:48 -0000
> @@ -0,0 +1,87 @@
> +/*   $OpenBSD: efirng.c,v 1.1 2018/04/08 13:27:22 kettenis Exp $     */
> +
> +/*
> + * Copyright (c) 2018 Mark Kettenis <[email protected]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#include <sys/param.h>
> +
> +#include <efi.h>
> +#include <efiapi.h>
> +
> +#include "eficall.h"
> +#include "libsa.h"
> +
> +extern EFI_BOOT_SERVICES     *BS;
> +
> +/* Random Number Generator Protocol */
> +
> +#define EFI_RNG_PROTOCOL_GUID \
> +    { 0x3152bca5, 0xeade, 0x433d, {0x86, 0x2e, 0xc0, 0x1c, 0xdc, 0x29, 0x1f, 
> 0x44} }
> +
> +INTERFACE_DECL(_EFI_RNG_PROTOCOL);
> +
> +typedef EFI_GUID EFI_RNG_ALGORITHM;
> +
> +typedef
> +EFI_STATUS
> +(EFIAPI *EFI_RNG_GET_INFO) (
> +    IN struct _EFI_RNG_PROTOCOL              *This,
> +    IN  OUT UINTN                    *RNGAlgorithmListSize,
> +    OUT EFI_RNG_ALGORITHM            *RNGAlgorithmList
> +    );
> +
> +typedef
> +EFI_STATUS
> +(EFIAPI *EFI_RNG_GET_RNG) (
> +    IN struct _EFI_RNG_PROTOCOL              *This,
> +    IN EFI_RNG_ALGORITHM             *RNGAlgorithm, OPTIONAL
> +    IN UINTN                         RNGValueLength,
> +    OUT UINT8                                *RNGValue
> +    );
> +
> +typedef struct _EFI_RNG_PROTOCOL {
> +     EFI_RNG_GET_INFO        GetInfo;
> +     EFI_RNG_GET_RNG         GetRNG;
> +} EFI_RNG_PROTOCOL;
> +
> +static EFI_GUID                      rng_guid = EFI_RNG_PROTOCOL_GUID;
> +
> +void
> +fwrandom(char *buf, size_t buflen)
> +{
> +     EFI_STATUS               status;
> +     EFI_RNG_PROTOCOL        *rng = NULL;
> +     UINT8                   *random;
> +     size_t                   i;
> +
> +     status = EFI_CALL(BS->LocateProtocol, &rng_guid, NULL, (void **)&rng);
> +     if (rng == NULL || EFI_ERROR(status))
> +             return;
> +
> +     random = alloc(buflen);
> +
> +     status = EFI_CALL(rng->GetRNG, rng, NULL, buflen, random);
> +     if (EFI_ERROR(status)) {
> +             printf("RNG GetRNG() failed (%d)\n", status);
> +             goto out;
> +     }
> +
> +     for (i = 0; i < buflen; i++)
> +             buf[i] ^= random[i];
> +
> +out:
> +     free(random, buflen);
> +}
> 

Reply via email to