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); > +} >
