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