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