1 | /** @file
|
---|
2 | Provides an implementation of the library class RngLib that uses the Rng protocol.
|
---|
3 |
|
---|
4 | Copyright (c) 2023, Arm Limited. All rights reserved.
|
---|
5 | Copyright (c) Microsoft Corporation. All rights reserved.
|
---|
6 | SPDX-License-Identifier: BSD-2-Clause-Patent
|
---|
7 |
|
---|
8 | **/
|
---|
9 | #include <Uefi.h>
|
---|
10 | #include <Library/UefiBootServicesTableLib.h>
|
---|
11 | #include <Library/DebugLib.h>
|
---|
12 | #include <Library/RngLib.h>
|
---|
13 | #include <Protocol/Rng.h>
|
---|
14 |
|
---|
15 | /**
|
---|
16 | Routine Description:
|
---|
17 |
|
---|
18 | Generates a random number via the NIST
|
---|
19 | 800-9A algorithm. Refer to
|
---|
20 | http://csrc.nist.gov/groups/STM/cavp/documents/drbg/DRBGVS.pdf
|
---|
21 | for more information.
|
---|
22 |
|
---|
23 | @param[out] Buffer Buffer to receive the random number.
|
---|
24 | @param[in] BufferSize Number of bytes in Buffer.
|
---|
25 |
|
---|
26 | @retval EFI_SUCCESS or underlying failure code.
|
---|
27 | **/
|
---|
28 | STATIC
|
---|
29 | EFI_STATUS
|
---|
30 | GenerateRandomNumberViaNist800Algorithm (
|
---|
31 | OUT UINT8 *Buffer,
|
---|
32 | IN UINTN BufferSize
|
---|
33 | )
|
---|
34 | {
|
---|
35 | EFI_STATUS Status;
|
---|
36 | EFI_RNG_PROTOCOL *RngProtocol;
|
---|
37 |
|
---|
38 | RngProtocol = NULL;
|
---|
39 |
|
---|
40 | if (Buffer == NULL) {
|
---|
41 | DEBUG ((DEBUG_ERROR, "%a: Buffer == NULL.\n", __func__));
|
---|
42 | return EFI_INVALID_PARAMETER;
|
---|
43 | }
|
---|
44 |
|
---|
45 | Status = gBS->LocateProtocol (&gEfiRngProtocolGuid, NULL, (VOID **)&RngProtocol);
|
---|
46 | if (EFI_ERROR (Status) || (RngProtocol == NULL)) {
|
---|
47 | DEBUG ((DEBUG_ERROR, "%a: Could not locate RNG prototocol, Status = %r\n", __func__, Status));
|
---|
48 | return Status;
|
---|
49 | }
|
---|
50 |
|
---|
51 | Status = RngProtocol->GetRNG (RngProtocol, &gEfiRngAlgorithmSp80090Ctr256Guid, BufferSize, Buffer);
|
---|
52 | DEBUG ((DEBUG_INFO, "%a: GetRNG algorithm CTR-256 - Status = %r\n", __func__, Status));
|
---|
53 | if (!EFI_ERROR (Status)) {
|
---|
54 | return Status;
|
---|
55 | }
|
---|
56 |
|
---|
57 | Status = RngProtocol->GetRNG (RngProtocol, &gEfiRngAlgorithmSp80090Hmac256Guid, BufferSize, Buffer);
|
---|
58 | DEBUG ((DEBUG_INFO, "%a: GetRNG algorithm HMAC-256 - Status = %r\n", __func__, Status));
|
---|
59 | if (!EFI_ERROR (Status)) {
|
---|
60 | return Status;
|
---|
61 | }
|
---|
62 |
|
---|
63 | Status = RngProtocol->GetRNG (RngProtocol, &gEfiRngAlgorithmSp80090Hash256Guid, BufferSize, Buffer);
|
---|
64 | DEBUG ((DEBUG_INFO, "%a: GetRNG algorithm Hash-256 - Status = %r\n", __func__, Status));
|
---|
65 | if (!EFI_ERROR (Status)) {
|
---|
66 | return Status;
|
---|
67 | }
|
---|
68 |
|
---|
69 | Status = RngProtocol->GetRNG (RngProtocol, &gEfiRngAlgorithmRaw, BufferSize, Buffer);
|
---|
70 | DEBUG ((DEBUG_INFO, "%a: GetRNG algorithm Raw - Status = %r\n", __func__, Status));
|
---|
71 | if (!EFI_ERROR (Status)) {
|
---|
72 | return Status;
|
---|
73 | }
|
---|
74 |
|
---|
75 | // If all the other methods have failed, use the default method from the RngProtocol
|
---|
76 | Status = RngProtocol->GetRNG (RngProtocol, NULL, BufferSize, Buffer);
|
---|
77 | DEBUG ((DEBUG_INFO, "%a: GetRNG algorithm default - Status = %r\n", __func__, Status));
|
---|
78 | if (!EFI_ERROR (Status)) {
|
---|
79 | return Status;
|
---|
80 | }
|
---|
81 |
|
---|
82 | // If we get to this point, we have failed
|
---|
83 | DEBUG ((DEBUG_ERROR, "%a: GetRNG() failed, staus = %r\n", __func__, Status));
|
---|
84 |
|
---|
85 | return Status;
|
---|
86 | }// GenerateRandomNumberViaNist800Algorithm()
|
---|
87 |
|
---|
88 | /**
|
---|
89 | Generates a 16-bit random number.
|
---|
90 |
|
---|
91 | if Rand is NULL, return FALSE.
|
---|
92 |
|
---|
93 | @param[out] Rand Buffer pointer to store the 16-bit random value.
|
---|
94 |
|
---|
95 | @retval TRUE Random number generated successfully.
|
---|
96 | @retval FALSE Failed to generate the random number.
|
---|
97 |
|
---|
98 | **/
|
---|
99 | BOOLEAN
|
---|
100 | EFIAPI
|
---|
101 | GetRandomNumber16 (
|
---|
102 | OUT UINT16 *Rand
|
---|
103 | )
|
---|
104 | {
|
---|
105 | EFI_STATUS Status;
|
---|
106 |
|
---|
107 | if (Rand == NULL) {
|
---|
108 | return FALSE;
|
---|
109 | }
|
---|
110 |
|
---|
111 | Status = GenerateRandomNumberViaNist800Algorithm ((UINT8 *)Rand, sizeof (UINT16));
|
---|
112 | if (EFI_ERROR (Status)) {
|
---|
113 | return FALSE;
|
---|
114 | }
|
---|
115 |
|
---|
116 | return TRUE;
|
---|
117 | }
|
---|
118 |
|
---|
119 | /**
|
---|
120 | Generates a 32-bit random number.
|
---|
121 |
|
---|
122 | if Rand is NULL, return FALSE.
|
---|
123 |
|
---|
124 | @param[out] Rand Buffer pointer to store the 32-bit random value.
|
---|
125 |
|
---|
126 | @retval TRUE Random number generated successfully.
|
---|
127 | @retval FALSE Failed to generate the random number.
|
---|
128 |
|
---|
129 | **/
|
---|
130 | BOOLEAN
|
---|
131 | EFIAPI
|
---|
132 | GetRandomNumber32 (
|
---|
133 | OUT UINT32 *Rand
|
---|
134 | )
|
---|
135 | {
|
---|
136 | EFI_STATUS Status;
|
---|
137 |
|
---|
138 | if (Rand == NULL) {
|
---|
139 | return FALSE;
|
---|
140 | }
|
---|
141 |
|
---|
142 | Status = GenerateRandomNumberViaNist800Algorithm ((UINT8 *)Rand, sizeof (UINT32));
|
---|
143 | if (EFI_ERROR (Status)) {
|
---|
144 | return FALSE;
|
---|
145 | }
|
---|
146 |
|
---|
147 | return TRUE;
|
---|
148 | }
|
---|
149 |
|
---|
150 | /**
|
---|
151 | Generates a 64-bit random number.
|
---|
152 |
|
---|
153 | if Rand is NULL, return FALSE.
|
---|
154 |
|
---|
155 | @param[out] Rand Buffer pointer to store the 64-bit random value.
|
---|
156 |
|
---|
157 | @retval TRUE Random number generated successfully.
|
---|
158 | @retval FALSE Failed to generate the random number.
|
---|
159 |
|
---|
160 | **/
|
---|
161 | BOOLEAN
|
---|
162 | EFIAPI
|
---|
163 | GetRandomNumber64 (
|
---|
164 | OUT UINT64 *Rand
|
---|
165 | )
|
---|
166 | {
|
---|
167 | EFI_STATUS Status;
|
---|
168 |
|
---|
169 | if (Rand == NULL) {
|
---|
170 | return FALSE;
|
---|
171 | }
|
---|
172 |
|
---|
173 | Status = GenerateRandomNumberViaNist800Algorithm ((UINT8 *)Rand, sizeof (UINT64));
|
---|
174 | if (EFI_ERROR (Status)) {
|
---|
175 | return FALSE;
|
---|
176 | }
|
---|
177 |
|
---|
178 | return TRUE;
|
---|
179 | }
|
---|
180 |
|
---|
181 | /**
|
---|
182 | Generates a 128-bit random number.
|
---|
183 |
|
---|
184 | if Rand is NULL, return FALSE.
|
---|
185 |
|
---|
186 | @param[out] Rand Buffer pointer to store the 128-bit random value.
|
---|
187 |
|
---|
188 | @retval TRUE Random number generated successfully.
|
---|
189 | @retval FALSE Failed to generate the random number.
|
---|
190 |
|
---|
191 | **/
|
---|
192 | BOOLEAN
|
---|
193 | EFIAPI
|
---|
194 | GetRandomNumber128 (
|
---|
195 | OUT UINT64 *Rand
|
---|
196 | )
|
---|
197 | {
|
---|
198 | EFI_STATUS Status;
|
---|
199 |
|
---|
200 | if (Rand == NULL) {
|
---|
201 | return FALSE;
|
---|
202 | }
|
---|
203 |
|
---|
204 | Status = GenerateRandomNumberViaNist800Algorithm ((UINT8 *)Rand, 2 * sizeof (UINT64));
|
---|
205 | if (EFI_ERROR (Status)) {
|
---|
206 | return FALSE;
|
---|
207 | }
|
---|
208 |
|
---|
209 | return TRUE;
|
---|
210 | }
|
---|
211 |
|
---|
212 | /**
|
---|
213 | Get a GUID identifying the RNG algorithm implementation.
|
---|
214 |
|
---|
215 | @param [out] RngGuid If success, contains the GUID identifying
|
---|
216 | the RNG algorithm implementation.
|
---|
217 |
|
---|
218 | @retval EFI_SUCCESS Success.
|
---|
219 | @retval EFI_UNSUPPORTED Not supported.
|
---|
220 | @retval EFI_INVALID_PARAMETER Invalid parameter.
|
---|
221 | **/
|
---|
222 | EFI_STATUS
|
---|
223 | EFIAPI
|
---|
224 | GetRngGuid (
|
---|
225 | GUID *RngGuid
|
---|
226 | )
|
---|
227 | {
|
---|
228 | /* It is not possible to know beforehand which Rng algorithm will
|
---|
229 | * be used by this library.
|
---|
230 | * This API is mainly used by RngDxe. RngDxe relies on the RngLib.
|
---|
231 | * The RngLib|DxeRngLib.inf implementation locates and uses an installed
|
---|
232 | * EFI_RNG_PROTOCOL.
|
---|
233 | * It is thus not possible to have both RngDxe and RngLib|DxeRngLib.inf.
|
---|
234 | * and it is ok not to support this API.
|
---|
235 | */
|
---|
236 | return EFI_UNSUPPORTED;
|
---|
237 | }
|
---|