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