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