xref: /openbsd/sys/arch/amd64/stand/efiboot/efirng.c (revision 274d7c50)
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