1 /* $OpenBSD: efirng.c,v 1.2 2021/06/25 17:49:49 krw 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 "libsa.h" 25 26 extern EFI_BOOT_SERVICES *BS; 27 28 /* Random Number Generator Protocol */ 29 30 #define EFI_RNG_PROTOCOL_GUID \ 31 { 0x3152bca5, 0xeade, 0x433d, {0x86, 0x2e, 0xc0, 0x1c, 0xdc, 0x29, 0x1f, 0x44} } 32 33 INTERFACE_DECL(_EFI_RNG_PROTOCOL); 34 35 typedef EFI_GUID EFI_RNG_ALGORITHM; 36 37 typedef 38 EFI_STATUS 39 (EFIAPI *EFI_RNG_GET_INFO) ( 40 IN struct _EFI_RNG_PROTOCOL *This, 41 IN OUT UINTN *RNGAlgorithmListSize, 42 OUT EFI_RNG_ALGORITHM *RNGAlgorithmList 43 ); 44 45 typedef 46 EFI_STATUS 47 (EFIAPI *EFI_RNG_GET_RNG) ( 48 IN struct _EFI_RNG_PROTOCOL *This, 49 IN EFI_RNG_ALGORITHM *RNGAlgorithm, OPTIONAL 50 IN UINTN RNGValueLength, 51 OUT UINT8 *RNGValue 52 ); 53 54 typedef struct _EFI_RNG_PROTOCOL { 55 EFI_RNG_GET_INFO GetInfo; 56 EFI_RNG_GET_RNG GetRNG; 57 } EFI_RNG_PROTOCOL; 58 59 static EFI_GUID rng_guid = EFI_RNG_PROTOCOL_GUID; 60 61 int 62 fwrandom(char *buf, size_t buflen) 63 { 64 EFI_STATUS status; 65 EFI_RNG_PROTOCOL *rng = NULL; 66 UINT8 *random; 67 size_t i; 68 int ret = 0; 69 70 status = BS->LocateProtocol(&rng_guid, NULL, (void **)&rng); 71 if (rng == NULL || EFI_ERROR(status)) 72 return -1; 73 74 random = alloc(buflen); 75 76 status = rng->GetRNG(rng, NULL, buflen, random); 77 if (EFI_ERROR(status)) { 78 printf("RNG GetRNG() failed (%d)\n", status); 79 ret = -1; 80 goto out; 81 } 82 83 for (i = 0; i < buflen; i++) 84 buf[i] ^= random[i]; 85 86 out: 87 free(random, buflen); 88 return ret; 89 } 90