1 /* $OpenBSD: efirng.c,v 1.3 2021/06/07 00:04:20 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
fwrandom(char * buf,size_t buflen)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