1 /* $OpenBSD: efirng.c,v 1.1 2019/05/05 19:17:03 kettenis Exp $ */ 2 3 /* 4 * Copyright (c) 2018 Mark Kettenis <kettenis@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <sys/param.h> 20 21 #include <efi.h> 22 #include <efiapi.h> 23 24 #include "eficall.h" 25 #include "libsa.h" 26 27 extern EFI_BOOT_SERVICES *BS; 28 29 /* Random Number Generator Protocol */ 30 31 #define EFI_RNG_PROTOCOL_GUID \ 32 { 0x3152bca5, 0xeade, 0x433d, {0x86, 0x2e, 0xc0, 0x1c, 0xdc, 0x29, 0x1f, 0x44} } 33 34 INTERFACE_DECL(_EFI_RNG_PROTOCOL); 35 36 typedef EFI_GUID EFI_RNG_ALGORITHM; 37 38 typedef 39 EFI_STATUS 40 (EFIAPI *EFI_RNG_GET_INFO) ( 41 IN struct _EFI_RNG_PROTOCOL *This, 42 IN OUT UINTN *RNGAlgorithmListSize, 43 OUT EFI_RNG_ALGORITHM *RNGAlgorithmList 44 ); 45 46 typedef 47 EFI_STATUS 48 (EFIAPI *EFI_RNG_GET_RNG) ( 49 IN struct _EFI_RNG_PROTOCOL *This, 50 IN EFI_RNG_ALGORITHM *RNGAlgorithm, OPTIONAL 51 IN UINTN RNGValueLength, 52 OUT UINT8 *RNGValue 53 ); 54 55 typedef struct _EFI_RNG_PROTOCOL { 56 EFI_RNG_GET_INFO GetInfo; 57 EFI_RNG_GET_RNG GetRNG; 58 } EFI_RNG_PROTOCOL; 59 60 static EFI_GUID rng_guid = EFI_RNG_PROTOCOL_GUID; 61 62 void 63 fwrandom(char *buf, size_t buflen) 64 { 65 EFI_STATUS status; 66 EFI_RNG_PROTOCOL *rng = NULL; 67 UINT8 *random; 68 size_t i; 69 70 status = EFI_CALL(BS->LocateProtocol, &rng_guid, NULL, (void **)&rng); 71 if (rng == NULL || EFI_ERROR(status)) 72 return; 73 74 random = alloc(buflen); 75 76 status = EFI_CALL(rng->GetRNG, rng, NULL, buflen, random); 77 if (EFI_ERROR(status)) { 78 printf("RNG GetRNG() failed (%d)\n", status); 79 goto out; 80 } 81 82 for (i = 0; i < buflen; i++) 83 buf[i] ^= random[i]; 84 85 out: 86 free(random, buflen); 87 } 88