]> git.proxmox.com Git - mirror_edk2.git/blame - CryptoPkg/Library/BaseCryptLib/Pk/CryptDh.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / CryptoPkg / Library / BaseCryptLib / Pk / CryptDh.c
CommitLineData
a8c44645 1/** @file\r
2 Diffie-Hellman Wrapper Implementation over OpenSSL.\r
3\r
630f67dd 4Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>\r
2009f6b4 5SPDX-License-Identifier: BSD-2-Clause-Patent\r
a8c44645 6\r
7**/\r
8\r
9#include "InternalCryptLib.h"\r
1cae0c83 10#include <openssl/bn.h>\r
a8c44645 11#include <openssl/dh.h>\r
12\r
a8c44645 13/**\r
14 Allocates and Initializes one Diffie-Hellman Context for subsequent use.\r
15\r
16 @return Pointer to the Diffie-Hellman Context that has been initialized.\r
17 If the allocations fails, DhNew() returns NULL.\r
18\r
19**/\r
20VOID *\r
21EFIAPI\r
22DhNew (\r
23 VOID\r
24 )\r
25{\r
26 //\r
27 // Allocates & Initializes DH Context by OpenSSL DH_new()\r
28 //\r
7c342378 29 return (VOID *)DH_new ();\r
a8c44645 30}\r
31\r
32/**\r
33 Release the specified DH context.\r
34\r
16d2c32c 35 If DhContext is NULL, then return FALSE.\r
a8c44645 36\r
37 @param[in] DhContext Pointer to the DH context to be released.\r
38\r
39**/\r
40VOID\r
41EFIAPI\r
42DhFree (\r
43 IN VOID *DhContext\r
44 )\r
45{\r
46 //\r
47 // Free OpenSSL DH Context\r
48 //\r
7c342378 49 DH_free ((DH *)DhContext);\r
a8c44645 50}\r
51\r
52/**\r
53 Generates DH parameter.\r
54\r
55 Given generator g, and length of prime number p in bits, this function generates p,\r
56 and sets DH context according to value of g and p.\r
630f67dd 57\r
a8c44645 58 Before this function can be invoked, pseudorandom number generator must be correctly\r
59 initialized by RandomSeed().\r
60\r
16d2c32c 61 If DhContext is NULL, then return FALSE.\r
62 If Prime is NULL, then return FALSE.\r
a8c44645 63\r
64 @param[in, out] DhContext Pointer to the DH context.\r
65 @param[in] Generator Value of generator.\r
66 @param[in] PrimeLength Length in bits of prime to be generated.\r
67 @param[out] Prime Pointer to the buffer to receive the generated prime number.\r
68\r
2998af86 69 @retval TRUE DH parameter generation succeeded.\r
a8c44645 70 @retval FALSE Value of Generator is not supported.\r
71 @retval FALSE PRNG fails to generate random prime number with PrimeLength.\r
72\r
73**/\r
74BOOLEAN\r
75EFIAPI\r
76DhGenerateParameter (\r
77 IN OUT VOID *DhContext,\r
78 IN UINTN Generator,\r
79 IN UINTN PrimeLength,\r
80 OUT UINT8 *Prime\r
81 )\r
82{\r
7c342378
MK
83 BOOLEAN RetVal;\r
84 BIGNUM *BnP;\r
a8c44645 85\r
16d2c32c 86 //\r
87 // Check input parameters.\r
88 //\r
7c342378 89 if ((DhContext == NULL) || (Prime == NULL) || (PrimeLength > INT_MAX)) {\r
16d2c32c 90 return FALSE;\r
91 }\r
92\r
7c342378 93 if ((Generator != DH_GENERATOR_2) && (Generator != DH_GENERATOR_5)) {\r
a8c44645 94 return FALSE;\r
95 }\r
96\r
7c342378 97 RetVal = (BOOLEAN)DH_generate_parameters_ex (DhContext, (UINT32)PrimeLength, (UINT32)Generator, NULL);\r
a8c44645 98 if (!RetVal) {\r
99 return FALSE;\r
100 }\r
101\r
f56b11d2
QL
102 DH_get0_pqg (DhContext, (const BIGNUM **)&BnP, NULL, NULL);\r
103 BN_bn2bin (BnP, Prime);\r
a8c44645 104\r
105 return TRUE;\r
106}\r
107\r
108/**\r
109 Sets generator and prime parameters for DH.\r
110\r
111 Given generator g, and prime number p, this function and sets DH\r
112 context accordingly.\r
113\r
16d2c32c 114 If DhContext is NULL, then return FALSE.\r
115 If Prime is NULL, then return FALSE.\r
a8c44645 116\r
117 @param[in, out] DhContext Pointer to the DH context.\r
118 @param[in] Generator Value of generator.\r
119 @param[in] PrimeLength Length in bits of prime to be generated.\r
120 @param[in] Prime Pointer to the prime number.\r
121\r
2998af86 122 @retval TRUE DH parameter setting succeeded.\r
a8c44645 123 @retval FALSE Value of Generator is not supported.\r
124 @retval FALSE Value of Generator is not suitable for the Prime.\r
125 @retval FALSE Value of Prime is not a prime number.\r
126 @retval FALSE Value of Prime is not a safe prime number.\r
127\r
128**/\r
129BOOLEAN\r
130EFIAPI\r
131DhSetParameter (\r
132 IN OUT VOID *DhContext,\r
133 IN UINTN Generator,\r
134 IN UINTN PrimeLength,\r
135 IN CONST UINT8 *Prime\r
136 )\r
137{\r
dda39f3a 138 DH *Dh;\r
f56b11d2
QL
139 BIGNUM *BnP;\r
140 BIGNUM *BnG;\r
a8c44645 141\r
16d2c32c 142 //\r
143 // Check input parameters.\r
144 //\r
7c342378 145 if ((DhContext == NULL) || (Prime == NULL) || (PrimeLength > INT_MAX)) {\r
16d2c32c 146 return FALSE;\r
147 }\r
f56b11d2 148\r
7c342378 149 if ((Generator != DH_GENERATOR_2) && (Generator != DH_GENERATOR_5)) {\r
a8c44645 150 return FALSE;\r
151 }\r
152\r
f56b11d2
QL
153 //\r
154 // Set the generator and prime parameters for DH object.\r
155 //\r
156 Dh = (DH *)DhContext;\r
157 BnP = BN_bin2bn ((const unsigned char *)Prime, (int)(PrimeLength / 8), NULL);\r
158 BnG = BN_bin2bn ((const unsigned char *)&Generator, 1, NULL);\r
159 if ((BnP == NULL) || (BnG == NULL) || !DH_set0_pqg (Dh, BnP, NULL, BnG)) {\r
dda39f3a 160 goto Error;\r
161 }\r
a8c44645 162\r
163 return TRUE;\r
dda39f3a 164\r
165Error:\r
f56b11d2
QL
166 BN_free (BnP);\r
167 BN_free (BnG);\r
dda39f3a 168\r
dda39f3a 169 return FALSE;\r
a8c44645 170}\r
171\r
172/**\r
173 Generates DH public key.\r
174\r
630f67dd 175 This function generates random secret exponent, and computes the public key, which is\r
a8c44645 176 returned via parameter PublicKey and PublicKeySize. DH context is updated accordingly.\r
177 If the PublicKey buffer is too small to hold the public key, FALSE is returned and\r
178 PublicKeySize is set to the required buffer size to obtain the public key.\r
179\r
16d2c32c 180 If DhContext is NULL, then return FALSE.\r
181 If PublicKeySize is NULL, then return FALSE.\r
182 If PublicKeySize is large enough but PublicKey is NULL, then return FALSE.\r
a8c44645 183\r
184 @param[in, out] DhContext Pointer to the DH context.\r
185 @param[out] PublicKey Pointer to the buffer to receive generated public key.\r
186 @param[in, out] PublicKeySize On input, the size of PublicKey buffer in bytes.\r
187 On output, the size of data returned in PublicKey buffer in bytes.\r
188\r
189 @retval TRUE DH public key generation succeeded.\r
190 @retval FALSE DH public key generation failed.\r
191 @retval FALSE PublicKeySize is not large enough.\r
192\r
193**/\r
194BOOLEAN\r
195EFIAPI\r
196DhGenerateKey (\r
197 IN OUT VOID *DhContext,\r
198 OUT UINT8 *PublicKey,\r
199 IN OUT UINTN *PublicKeySize\r
200 )\r
201{\r
7c342378
MK
202 BOOLEAN RetVal;\r
203 DH *Dh;\r
204 BIGNUM *DhPubKey;\r
205 INTN Size;\r
a8c44645 206\r
16d2c32c 207 //\r
208 // Check input parameters.\r
209 //\r
7c342378 210 if ((DhContext == NULL) || (PublicKeySize == NULL)) {\r
16d2c32c 211 return FALSE;\r
212 }\r
213\r
7c342378 214 if ((PublicKey == NULL) && (*PublicKeySize != 0)) {\r
16d2c32c 215 return FALSE;\r
216 }\r
f56b11d2 217\r
7c342378 218 Dh = (DH *)DhContext;\r
a8c44645 219\r
7c342378 220 RetVal = (BOOLEAN)DH_generate_key (DhContext);\r
a8c44645 221 if (RetVal) {\r
f56b11d2
QL
222 DH_get0_key (Dh, (const BIGNUM **)&DhPubKey, NULL);\r
223 Size = BN_num_bytes (DhPubKey);\r
7c342378 224 if ((Size > 0) && (*PublicKeySize < (UINTN)Size)) {\r
dda39f3a 225 *PublicKeySize = Size;\r
226 return FALSE;\r
227 }\r
f56b11d2 228\r
a9fb7b78
LQ
229 if (PublicKey != NULL) {\r
230 BN_bn2bin (DhPubKey, PublicKey);\r
231 }\r
7c342378 232\r
dda39f3a 233 *PublicKeySize = Size;\r
a8c44645 234 }\r
235\r
236 return RetVal;\r
237}\r
238\r
239/**\r
240 Computes exchanged common key.\r
241\r
242 Given peer's public key, this function computes the exchanged common key, based on its own\r
630f67dd 243 context including value of prime modulus and random secret exponent.\r
a8c44645 244\r
16d2c32c 245 If DhContext is NULL, then return FALSE.\r
246 If PeerPublicKey is NULL, then return FALSE.\r
247 If KeySize is NULL, then return FALSE.\r
dda39f3a 248 If Key is NULL, then return FALSE.\r
249 If KeySize is not large enough, then return FALSE.\r
a8c44645 250\r
251 @param[in, out] DhContext Pointer to the DH context.\r
252 @param[in] PeerPublicKey Pointer to the peer's public key.\r
253 @param[in] PeerPublicKeySize Size of peer's public key in bytes.\r
254 @param[out] Key Pointer to the buffer to receive generated key.\r
255 @param[in, out] KeySize On input, the size of Key buffer in bytes.\r
256 On output, the size of data returned in Key buffer in bytes.\r
257\r
258 @retval TRUE DH exchanged key generation succeeded.\r
259 @retval FALSE DH exchanged key generation failed.\r
260 @retval FALSE KeySize is not large enough.\r
261\r
262**/\r
263BOOLEAN\r
264EFIAPI\r
265DhComputeKey (\r
266 IN OUT VOID *DhContext,\r
267 IN CONST UINT8 *PeerPublicKey,\r
268 IN UINTN PeerPublicKeySize,\r
269 OUT UINT8 *Key,\r
270 IN OUT UINTN *KeySize\r
271 )\r
272{\r
273 BIGNUM *Bn;\r
dda39f3a 274 INTN Size;\r
a8c44645 275\r
16d2c32c 276 //\r
277 // Check input parameters.\r
278 //\r
7c342378 279 if ((DhContext == NULL) || (PeerPublicKey == NULL) || (KeySize == NULL) || (Key == NULL)) {\r
16d2c32c 280 return FALSE;\r
281 }\r
282\r
dda39f3a 283 if (PeerPublicKeySize > INT_MAX) {\r
16d2c32c 284 return FALSE;\r
285 }\r
630f67dd 286\r
7c342378 287 Bn = BN_bin2bn (PeerPublicKey, (UINT32)PeerPublicKeySize, NULL);\r
dda39f3a 288 if (Bn == NULL) {\r
289 return FALSE;\r
290 }\r
a8c44645 291\r
dda39f3a 292 Size = DH_compute_key (Key, Bn, DhContext);\r
293 if (Size < 0) {\r
294 BN_free (Bn);\r
295 return FALSE;\r
296 }\r
a8c44645 297\r
7c342378 298 if (*KeySize < (UINTN)Size) {\r
dda39f3a 299 *KeySize = Size;\r
300 BN_free (Bn);\r
301 return FALSE;\r
302 }\r
a8c44645 303\r
dda39f3a 304 *KeySize = Size;\r
305 BN_free (Bn);\r
a8c44645 306 return TRUE;\r
307}\r