blob: a1d0ec842c87bf60128a2bc8e0542ae79ce3da9e [file] [log] [blame]
Sughosh Ganu7064a5d2019-12-29 00:01:05 +05301// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (c) 2019, Linaro Limited
4 */
5
6#include <common.h>
7#include <dm.h>
8#include <efi_loader.h>
9#include <efi_rng.h>
10#include <rng.h>
11
12DECLARE_GLOBAL_DATA_PTR;
13
Sughosh Ganu693a4f42019-12-29 00:01:06 +053014const efi_guid_t efi_guid_rng_protocol = EFI_RNG_PROTOCOL_GUID;
15
Heinrich Schuchardt0410be22020-01-09 20:49:44 +010016/**
17 * platform_get_rng_device() - retrieve random number generator
18 *
19 * This function retrieves the udevice implementing a hardware random
20 * number generator.
21 *
22 * This function may be overridden if special initialization is needed.
23 *
24 * @dev: udevice
25 * Return: status code
26 */
Sughosh Ganu7064a5d2019-12-29 00:01:05 +053027__weak efi_status_t platform_get_rng_device(struct udevice **dev)
28{
29 int ret;
30 struct udevice *devp;
31
32 ret = uclass_get_device(UCLASS_RNG, 0, &devp);
33 if (ret) {
34 debug("Unable to get rng device\n");
35 return EFI_DEVICE_ERROR;
36 }
37
38 *dev = devp;
39
40 return EFI_SUCCESS;
41}
42
Heinrich Schuchardt0410be22020-01-09 20:49:44 +010043/**
44 * rng_getinfo() - get information about random number generation
45 *
46 * This function implement the GetInfo() service of the EFI random number
47 * generator protocol. See the UEFI spec for details.
48 *
49 * @this: random number generator protocol instance
50 * @rng_algorithm_list_size: number of random number generation algorithms
51 * @rng_algorithm_list: descriptions of random number generation
52 * algorithms
53 * Return: status code
54 */
Sughosh Ganu7064a5d2019-12-29 00:01:05 +053055static efi_status_t EFIAPI rng_getinfo(struct efi_rng_protocol *this,
56 efi_uintn_t *rng_algorithm_list_size,
57 efi_guid_t *rng_algorithm_list)
58{
59 efi_status_t ret = EFI_SUCCESS;
60 efi_guid_t rng_algo_guid = EFI_RNG_ALGORITHM_RAW;
61
62 EFI_ENTRY("%p, %p, %p", this, rng_algorithm_list_size,
63 rng_algorithm_list);
64
65 if (!this || !rng_algorithm_list_size) {
66 ret = EFI_INVALID_PARAMETER;
67 goto back;
68 }
69
70 if (!rng_algorithm_list ||
71 *rng_algorithm_list_size < sizeof(*rng_algorithm_list)) {
72 *rng_algorithm_list_size = sizeof(*rng_algorithm_list);
73 ret = EFI_BUFFER_TOO_SMALL;
74 goto back;
75 }
76
77 /*
78 * For now, use EFI_RNG_ALGORITHM_RAW as the default
79 * algorithm. If a new algorithm gets added in the
80 * future through a Kconfig, rng_algo_guid will be set
81 * based on that Kconfig option
82 */
83 *rng_algorithm_list_size = sizeof(*rng_algorithm_list);
84 guidcpy(rng_algorithm_list, &rng_algo_guid);
85
86back:
87 return EFI_EXIT(ret);
88}
89
Heinrich Schuchardt0410be22020-01-09 20:49:44 +010090/**
91 * rng_getrng() - get random value
92 *
93 * This function implement the GetRng() service of the EFI random number
94 * generator protocol. See the UEFI spec for details.
95 *
96 * @this: random number generator protocol instance
97 * @rng_algorithm: random number generation algorithm
98 * @rng_value_length: number of random bytes to generate, buffer length
99 * @rng_value: buffer to receive random bytes
100 * Return: status code
101 */
Sughosh Ganu7064a5d2019-12-29 00:01:05 +0530102static efi_status_t EFIAPI getrng(struct efi_rng_protocol *this,
103 efi_guid_t *rng_algorithm,
104 efi_uintn_t rng_value_length,
105 uint8_t *rng_value)
106{
107 int ret;
108 efi_status_t status = EFI_SUCCESS;
109 struct udevice *dev;
110 const efi_guid_t rng_raw_guid = EFI_RNG_ALGORITHM_RAW;
111
112 EFI_ENTRY("%p, %p, %zu, %p", this, rng_algorithm, rng_value_length,
113 rng_value);
114
115 if (!this || !rng_value || !rng_value_length) {
116 status = EFI_INVALID_PARAMETER;
117 goto back;
118 }
119
120 if (rng_algorithm) {
121 EFI_PRINT("RNG algorithm %pUl\n", rng_algorithm);
122 if (guidcmp(rng_algorithm, &rng_raw_guid)) {
123 status = EFI_UNSUPPORTED;
124 goto back;
125 }
126 }
127
128 ret = platform_get_rng_device(&dev);
129 if (ret != EFI_SUCCESS) {
130 EFI_PRINT("Rng device not found\n");
131 status = EFI_UNSUPPORTED;
132 goto back;
133 }
134
135 ret = dm_rng_read(dev, rng_value, rng_value_length);
136 if (ret < 0) {
137 EFI_PRINT("Rng device read failed\n");
138 status = EFI_DEVICE_ERROR;
139 goto back;
140 }
141
142back:
143 return EFI_EXIT(status);
144}
145
146const struct efi_rng_protocol efi_rng_protocol = {
147 .get_info = rng_getinfo,
148 .get_rng = getrng,
149};