20f13469b30f407367557e01e4f1fac16cbf967e
[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 - 2012, 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/dh.h>\r
17 \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 pamameter 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 \r
91   //\r
92   // Check input parameters.\r
93   //\r
94   if (DhContext == NULL || Prime == NULL) {\r
95     return FALSE;\r
96   }\r
97 \r
98   if (Generator != DH_GENERATOR_2 && Generator != DH_GENERATOR_5) {\r
99     return FALSE;\r
100   }\r
101 \r
102   RetVal = (BOOLEAN) DH_generate_parameters_ex (DhContext, (UINT32) PrimeLength, (UINT32) Generator, NULL);\r
103   if (!RetVal) {\r
104     return FALSE;\r
105   }\r
106 \r
107   BN_bn2bin (((DH *) DhContext)->p, Prime);\r
108 \r
109   return TRUE;\r
110 }\r
111 \r
112 /**\r
113   Sets generator and prime parameters for DH.\r
114 \r
115   Given generator g, and prime number p, this function and sets DH\r
116   context accordingly.\r
117 \r
118   If DhContext is NULL, then return FALSE.\r
119   If Prime is NULL, then return FALSE.\r
120 \r
121   @param[in, out]  DhContext    Pointer to the DH context.\r
122   @param[in]       Generator    Value of generator.\r
123   @param[in]       PrimeLength  Length in bits of prime to be generated.\r
124   @param[in]       Prime        Pointer to the prime number.\r
125 \r
126   @retval TRUE   DH pamameter setting succeeded.\r
127   @retval FALSE  Value of Generator is not supported.\r
128   @retval FALSE  Value of Generator is not suitable for the Prime.\r
129   @retval FALSE  Value of Prime is not a prime number.\r
130   @retval FALSE  Value of Prime is not a safe prime number.\r
131 \r
132 **/\r
133 BOOLEAN\r
134 EFIAPI\r
135 DhSetParameter (\r
136   IN OUT  VOID         *DhContext,\r
137   IN      UINTN        Generator,\r
138   IN      UINTN        PrimeLength,\r
139   IN      CONST UINT8  *Prime\r
140   )\r
141 {\r
142   DH  *Dh;\r
143 \r
144   //\r
145   // Check input parameters.\r
146   //\r
147   if (DhContext == NULL || Prime == NULL) {\r
148     return FALSE;\r
149   }\r
150   \r
151   if (Generator != DH_GENERATOR_2 && Generator != DH_GENERATOR_5) {\r
152     return FALSE;\r
153   }\r
154 \r
155   Dh = (DH *) DhContext;\r
156   Dh->p = BN_new();\r
157   Dh->g = BN_new();\r
158 \r
159   BN_bin2bn (Prime, (UINT32) (PrimeLength / 8), Dh->p);\r
160   BN_set_word (Dh->g, (UINT32) Generator);\r
161 \r
162   return TRUE;\r
163 }\r
164 \r
165 /**\r
166   Generates DH public key.\r
167 \r
168   This function generates random secret exponent, and computes the public key, which is \r
169   returned via parameter PublicKey and PublicKeySize. DH context is updated accordingly.\r
170   If the PublicKey buffer is too small to hold the public key, FALSE is returned and\r
171   PublicKeySize is set to the required buffer size to obtain the public key.\r
172 \r
173   If DhContext is NULL, then return FALSE.\r
174   If PublicKeySize is NULL, then return FALSE.\r
175   If PublicKeySize is large enough but PublicKey is NULL, then return FALSE.\r
176 \r
177   @param[in, out]  DhContext      Pointer to the DH context.\r
178   @param[out]      PublicKey      Pointer to the buffer to receive generated public key.\r
179   @param[in, out]  PublicKeySize  On input, the size of PublicKey buffer in bytes.\r
180                                   On output, the size of data returned in PublicKey buffer in bytes.\r
181 \r
182   @retval TRUE   DH public key generation succeeded.\r
183   @retval FALSE  DH public key generation failed.\r
184   @retval FALSE  PublicKeySize is not large enough.\r
185 \r
186 **/\r
187 BOOLEAN\r
188 EFIAPI\r
189 DhGenerateKey (\r
190   IN OUT  VOID   *DhContext,\r
191   OUT     UINT8  *PublicKey,\r
192   IN OUT  UINTN  *PublicKeySize\r
193   )\r
194 {\r
195   BOOLEAN RetVal;\r
196   DH      *Dh;\r
197 \r
198   //\r
199   // Check input parameters.\r
200   //\r
201   if (DhContext == NULL || PublicKeySize == NULL) {\r
202     return FALSE;\r
203   }\r
204 \r
205   if (PublicKey == NULL && *PublicKeySize != 0) {\r
206     return FALSE;\r
207   }\r
208   \r
209   Dh = (DH *) DhContext;\r
210   *PublicKeySize = 0;\r
211 \r
212   RetVal = (BOOLEAN) DH_generate_key (DhContext);\r
213   if (RetVal) {\r
214     BN_bn2bin (Dh->pub_key, PublicKey);\r
215     *PublicKeySize  = BN_num_bytes (Dh->pub_key);\r
216   }\r
217 \r
218   return RetVal;\r
219 }\r
220 \r
221 /**\r
222   Computes exchanged common key.\r
223 \r
224   Given peer's public key, this function computes the exchanged common key, based on its own\r
225   context including value of prime modulus and random secret exponent. \r
226 \r
227   If DhContext is NULL, then return FALSE.\r
228   If PeerPublicKey is NULL, then return FALSE.\r
229   If KeySize is NULL, then return FALSE.\r
230   If KeySize is large enough but Key is NULL, then return FALSE.\r
231 \r
232   @param[in, out]  DhContext          Pointer to the DH context.\r
233   @param[in]       PeerPublicKey      Pointer to the peer's public key.\r
234   @param[in]       PeerPublicKeySize  Size of peer's public key in bytes.\r
235   @param[out]      Key                Pointer to the buffer to receive generated key.\r
236   @param[in, out]  KeySize            On input, the size of Key buffer in bytes.\r
237                                       On output, the size of data returned in Key buffer in bytes.\r
238 \r
239   @retval TRUE   DH exchanged key generation succeeded.\r
240   @retval FALSE  DH exchanged key generation failed.\r
241   @retval FALSE  KeySize is not large enough.\r
242 \r
243 **/\r
244 BOOLEAN\r
245 EFIAPI\r
246 DhComputeKey (\r
247   IN OUT  VOID         *DhContext,\r
248   IN      CONST UINT8  *PeerPublicKey,\r
249   IN      UINTN        PeerPublicKeySize,\r
250   OUT     UINT8        *Key,\r
251   IN OUT  UINTN        *KeySize\r
252   )\r
253 {\r
254   BIGNUM  *Bn;\r
255 \r
256   //\r
257   // Check input parameters.\r
258   //\r
259   if (DhContext == NULL || PeerPublicKey == NULL || KeySize == NULL) {\r
260     return FALSE;\r
261   }\r
262 \r
263   if (Key == NULL && *KeySize != 0) {\r
264     return FALSE;\r
265   }\r
266   \r
267   Bn = BN_bin2bn (PeerPublicKey, (UINT32) PeerPublicKeySize, NULL);\r
268 \r
269   *KeySize = (BOOLEAN) DH_compute_key (Key, Bn, DhContext);\r
270 \r
271   BN_free (Bn);\r
272 \r
273   return TRUE;\r
274 }\r