]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - SecurityPkg/RandomNumberGenerator/RngDxe/RdRand.c
SecurityPkg: Fix spelling errors
[mirror_edk2.git] / SecurityPkg / RandomNumberGenerator / RngDxe / RdRand.c
... / ...
CommitLineData
1/** @file\r
2 Support routines for RDRAND instruction access.\r
3\r
4Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>\r
5(C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>\r
6SPDX-License-Identifier: BSD-2-Clause-Patent\r
7\r
8**/\r
9#include <Library/RngLib.h>\r
10\r
11#include "RdRand.h"\r
12#include "AesCore.h"\r
13\r
14/**\r
15 Calls RDRAND to fill a buffer of arbitrary size with random bytes.\r
16\r
17 @param[in] Length Size of the buffer, in bytes, to fill with.\r
18 @param[out] RandBuffer Pointer to the buffer to store the random result.\r
19\r
20 @retval EFI_SUCCESS Random bytes generation succeeded.\r
21 @retval EFI_NOT_READY Failed to request random bytes.\r
22\r
23**/\r
24EFI_STATUS\r
25EFIAPI\r
26RdRandGetBytes (\r
27 IN UINTN Length,\r
28 OUT UINT8 *RandBuffer\r
29 )\r
30{\r
31 BOOLEAN IsRandom;\r
32 UINT64 TempRand[2];\r
33\r
34 while (Length > 0) {\r
35 IsRandom = GetRandomNumber128 (TempRand);\r
36 if (!IsRandom) {\r
37 return EFI_NOT_READY;\r
38 }\r
39 if (Length >= sizeof (TempRand)) {\r
40 WriteUnaligned64 ((UINT64*)RandBuffer, TempRand[0]);\r
41 RandBuffer += sizeof (UINT64);\r
42 WriteUnaligned64 ((UINT64*)RandBuffer, TempRand[1]);\r
43 RandBuffer += sizeof (UINT64);\r
44 Length -= sizeof (TempRand);\r
45 } else {\r
46 CopyMem (RandBuffer, TempRand, Length);\r
47 Length = 0;\r
48 }\r
49 }\r
50\r
51 return EFI_SUCCESS;\r
52}\r
53\r
54/**\r
55 Creates a 128bit random value that is fully forward and backward prediction resistant,\r
56 suitable for seeding a NIST SP800-90 Compliant, FIPS 1402-2 certifiable SW DRBG.\r
57 This function takes multiple random numbers through RDRAND without intervening\r
58 delays to ensure reseeding and performs AES-CBC-MAC over the data to compute the\r
59 seed value.\r
60\r
61 @param[out] SeedBuffer Pointer to a 128bit buffer to store the random seed.\r
62\r
63 @retval EFI_SUCCESS Random seed generation succeeded.\r
64 @retval EFI_NOT_READY Failed to request random bytes.\r
65\r
66**/\r
67EFI_STATUS\r
68EFIAPI\r
69RdRandGetSeed128 (\r
70 OUT UINT8 *SeedBuffer\r
71 )\r
72{\r
73 EFI_STATUS Status;\r
74 UINT8 RandByte[16];\r
75 UINT8 Key[16];\r
76 UINT8 Ffv[16];\r
77 UINT8 Xored[16];\r
78 UINT32 Index;\r
79 UINT32 Index2;\r
80\r
81 //\r
82 // Chose an arbitrary key and zero the feed_forward_value (FFV)\r
83 //\r
84 for (Index = 0; Index < 16; Index++) {\r
85 Key[Index] = (UINT8) Index;\r
86 Ffv[Index] = 0;\r
87 }\r
88\r
89 //\r
90 // Perform CBC_MAC over 32 * 128 bit values, with 10us gaps between 128 bit value\r
91 // The 10us gaps will ensure multiple reseeds within the HW RNG with a large design margin.\r
92 //\r
93 for (Index = 0; Index < 32; Index++) {\r
94 MicroSecondDelay (10);\r
95 Status = RdRandGetBytes (16, RandByte);\r
96 if (EFI_ERROR (Status)) {\r
97 return Status;\r
98 }\r
99\r
100 //\r
101 // Perform XOR operations on two 128-bit value.\r
102 //\r
103 for (Index2 = 0; Index2 < 16; Index2++) {\r
104 Xored[Index2] = RandByte[Index2] ^ Ffv[Index2];\r
105 }\r
106\r
107 AesEncrypt (Key, Xored, Ffv);\r
108 }\r
109\r
110 for (Index = 0; Index < 16; Index++) {\r
111 SeedBuffer[Index] = Ffv[Index];\r
112 }\r
113\r
114 return EFI_SUCCESS;\r
115}\r
116\r
117/**\r
118 Generate high-quality entropy source through RDRAND.\r
119\r
120 @param[in] Length Size of the buffer, in bytes, to fill with.\r
121 @param[out] Entropy Pointer to the buffer to store the entropy data.\r
122\r
123 @retval EFI_SUCCESS Entropy generation succeeded.\r
124 @retval EFI_NOT_READY Failed to request random data.\r
125\r
126**/\r
127EFI_STATUS\r
128EFIAPI\r
129RdRandGenerateEntropy (\r
130 IN UINTN Length,\r
131 OUT UINT8 *Entropy\r
132 )\r
133{\r
134 EFI_STATUS Status;\r
135 UINTN BlockCount;\r
136 UINT8 Seed[16];\r
137 UINT8 *Ptr;\r
138\r
139 Status = EFI_NOT_READY;\r
140 BlockCount = Length / 16;\r
141 Ptr = (UINT8 *)Entropy;\r
142\r
143 //\r
144 // Generate high-quality seed for DRBG Entropy\r
145 //\r
146 while (BlockCount > 0) {\r
147 Status = RdRandGetSeed128 (Seed);\r
148 if (EFI_ERROR (Status)) {\r
149 return Status;\r
150 }\r
151 CopyMem (Ptr, Seed, 16);\r
152\r
153 BlockCount--;\r
154 Ptr = Ptr + 16;\r
155 }\r
156\r
157 //\r
158 // Populate the remained data as request.\r
159 //\r
160 Status = RdRandGetSeed128 (Seed);\r
161 if (EFI_ERROR (Status)) {\r
162 return Status;\r
163 }\r
164 CopyMem (Ptr, Seed, (Length % 16));\r
165\r
166 return Status;\r
167}\r