]> git.proxmox.com Git - mirror_edk2.git/blob - CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaExt.c
CryptoPkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / CryptoPkg / Library / BaseCryptLib / Pk / CryptRsaExt.c
1 /** @file
2 RSA Asymmetric Cipher Wrapper Implementation over OpenSSL.
3
4 This file implements following APIs which provide more capabilities for RSA:
5 1) RsaGetKey
6 2) RsaGenerateKey
7 3) RsaCheckKey
8 4) RsaPkcs1Sign
9
10 Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
11 SPDX-License-Identifier: BSD-2-Clause-Patent
12
13 **/
14
15 #include "InternalCryptLib.h"
16
17 #include <openssl/bn.h>
18 #include <openssl/rsa.h>
19 #include <openssl/err.h>
20 #include <openssl/objects.h>
21
22 /**
23 Gets the tag-designated RSA key component from the established RSA context.
24
25 This function retrieves the tag-designated RSA key component from the
26 established RSA context as a non-negative integer (octet string format
27 represented in RSA PKCS#1).
28 If specified key component has not been set or has been cleared, then returned
29 BnSize is set to 0.
30 If the BigNumber buffer is too small to hold the contents of the key, FALSE
31 is returned and BnSize is set to the required buffer size to obtain the key.
32
33 If RsaContext is NULL, then return FALSE.
34 If BnSize is NULL, then return FALSE.
35 If BnSize is large enough but BigNumber is NULL, then return FALSE.
36
37 @param[in, out] RsaContext Pointer to RSA context being set.
38 @param[in] KeyTag Tag of RSA key component being set.
39 @param[out] BigNumber Pointer to octet integer buffer.
40 @param[in, out] BnSize On input, the size of big number buffer in bytes.
41 On output, the size of data returned in big number buffer in bytes.
42
43 @retval TRUE RSA key component was retrieved successfully.
44 @retval FALSE Invalid RSA key component tag.
45 @retval FALSE BnSize is too small.
46
47 **/
48 BOOLEAN
49 EFIAPI
50 RsaGetKey (
51 IN OUT VOID *RsaContext,
52 IN RSA_KEY_TAG KeyTag,
53 OUT UINT8 *BigNumber,
54 IN OUT UINTN *BnSize
55 )
56 {
57 RSA *RsaKey;
58 BIGNUM *BnKey;
59 UINTN Size;
60
61 //
62 // Check input parameters.
63 //
64 if (RsaContext == NULL || BnSize == NULL) {
65 return FALSE;
66 }
67
68 RsaKey = (RSA *) RsaContext;
69 Size = *BnSize;
70 *BnSize = 0;
71 BnKey = NULL;
72
73 switch (KeyTag) {
74
75 //
76 // RSA Public Modulus (N)
77 //
78 case RsaKeyN:
79 RSA_get0_key (RsaKey, (const BIGNUM **)&BnKey, NULL, NULL);
80 break;
81
82 //
83 // RSA Public Exponent (e)
84 //
85 case RsaKeyE:
86 RSA_get0_key (RsaKey, NULL, (const BIGNUM **)&BnKey, NULL);
87 break;
88
89 //
90 // RSA Private Exponent (d)
91 //
92 case RsaKeyD:
93 RSA_get0_key (RsaKey, NULL, NULL, (const BIGNUM **)&BnKey);
94 break;
95
96 //
97 // RSA Secret Prime Factor of Modulus (p)
98 //
99 case RsaKeyP:
100 RSA_get0_factors (RsaKey, (const BIGNUM **)&BnKey, NULL);
101 break;
102
103 //
104 // RSA Secret Prime Factor of Modules (q)
105 //
106 case RsaKeyQ:
107 RSA_get0_factors (RsaKey, NULL, (const BIGNUM **)&BnKey);
108 break;
109
110 //
111 // p's CRT Exponent (== d mod (p - 1))
112 //
113 case RsaKeyDp:
114 RSA_get0_crt_params (RsaKey, (const BIGNUM **)&BnKey, NULL, NULL);
115 break;
116
117 //
118 // q's CRT Exponent (== d mod (q - 1))
119 //
120 case RsaKeyDq:
121 RSA_get0_crt_params (RsaKey, NULL, (const BIGNUM **)&BnKey, NULL);
122 break;
123
124 //
125 // The CRT Coefficient (== 1/q mod p)
126 //
127 case RsaKeyQInv:
128 RSA_get0_crt_params (RsaKey, NULL, NULL, (const BIGNUM **)&BnKey);
129 break;
130
131 default:
132 return FALSE;
133 }
134
135 if (BnKey == NULL) {
136 return FALSE;
137 }
138
139 *BnSize = Size;
140 Size = BN_num_bytes (BnKey);
141
142 if (*BnSize < Size) {
143 *BnSize = Size;
144 return FALSE;
145 }
146
147 if (BigNumber == NULL) {
148 *BnSize = Size;
149 return TRUE;
150 }
151 *BnSize = BN_bn2bin (BnKey, BigNumber) ;
152
153 return TRUE;
154 }
155
156 /**
157 Generates RSA key components.
158
159 This function generates RSA key components. It takes RSA public exponent E and
160 length in bits of RSA modulus N as input, and generates all key components.
161 If PublicExponent is NULL, the default RSA public exponent (0x10001) will be used.
162
163 Before this function can be invoked, pseudorandom number generator must be correctly
164 initialized by RandomSeed().
165
166 If RsaContext is NULL, then return FALSE.
167
168 @param[in, out] RsaContext Pointer to RSA context being set.
169 @param[in] ModulusLength Length of RSA modulus N in bits.
170 @param[in] PublicExponent Pointer to RSA public exponent.
171 @param[in] PublicExponentSize Size of RSA public exponent buffer in bytes.
172
173 @retval TRUE RSA key component was generated successfully.
174 @retval FALSE Invalid RSA key component tag.
175
176 **/
177 BOOLEAN
178 EFIAPI
179 RsaGenerateKey (
180 IN OUT VOID *RsaContext,
181 IN UINTN ModulusLength,
182 IN CONST UINT8 *PublicExponent,
183 IN UINTN PublicExponentSize
184 )
185 {
186 BIGNUM *KeyE;
187 BOOLEAN RetVal;
188
189 //
190 // Check input parameters.
191 //
192 if (RsaContext == NULL || ModulusLength > INT_MAX || PublicExponentSize > INT_MAX) {
193 return FALSE;
194 }
195
196 KeyE = BN_new ();
197 if (KeyE == NULL) {
198 return FALSE;
199 }
200
201 RetVal = FALSE;
202
203 if (PublicExponent == NULL) {
204 if (BN_set_word (KeyE, 0x10001) == 0) {
205 goto _Exit;
206 }
207 } else {
208 if (BN_bin2bn (PublicExponent, (UINT32) PublicExponentSize, KeyE) == NULL) {
209 goto _Exit;
210 }
211 }
212
213 if (RSA_generate_key_ex ((RSA *) RsaContext, (UINT32) ModulusLength, KeyE, NULL) == 1) {
214 RetVal = TRUE;
215 }
216
217 _Exit:
218 BN_free (KeyE);
219 return RetVal;
220 }
221
222 /**
223 Validates key components of RSA context.
224 NOTE: This function performs integrity checks on all the RSA key material, so
225 the RSA key structure must contain all the private key data.
226
227 This function validates key components of RSA context in following aspects:
228 - Whether p is a prime
229 - Whether q is a prime
230 - Whether n = p * q
231 - Whether d*e = 1 mod lcm(p-1,q-1)
232
233 If RsaContext is NULL, then return FALSE.
234
235 @param[in] RsaContext Pointer to RSA context to check.
236
237 @retval TRUE RSA key components are valid.
238 @retval FALSE RSA key components are not valid.
239
240 **/
241 BOOLEAN
242 EFIAPI
243 RsaCheckKey (
244 IN VOID *RsaContext
245 )
246 {
247 UINTN Reason;
248
249 //
250 // Check input parameters.
251 //
252 if (RsaContext == NULL) {
253 return FALSE;
254 }
255
256 if (RSA_check_key ((RSA *) RsaContext) != 1) {
257 Reason = ERR_GET_REASON (ERR_peek_last_error ());
258 if (Reason == RSA_R_P_NOT_PRIME ||
259 Reason == RSA_R_Q_NOT_PRIME ||
260 Reason == RSA_R_N_DOES_NOT_EQUAL_P_Q ||
261 Reason == RSA_R_D_E_NOT_CONGRUENT_TO_1) {
262 return FALSE;
263 }
264 }
265
266 return TRUE;
267 }
268
269 /**
270 Carries out the RSA-SSA signature generation with EMSA-PKCS1-v1_5 encoding scheme.
271
272 This function carries out the RSA-SSA signature generation with EMSA-PKCS1-v1_5 encoding scheme defined in
273 RSA PKCS#1.
274 If the Signature buffer is too small to hold the contents of signature, FALSE
275 is returned and SigSize is set to the required buffer size to obtain the signature.
276
277 If RsaContext is NULL, then return FALSE.
278 If MessageHash is NULL, then return FALSE.
279 If HashSize is not equal to the size of MD5, SHA-1 or SHA-256 digest, then return FALSE.
280 If SigSize is large enough but Signature is NULL, then return FALSE.
281
282 @param[in] RsaContext Pointer to RSA context for signature generation.
283 @param[in] MessageHash Pointer to octet message hash to be signed.
284 @param[in] HashSize Size of the message hash in bytes.
285 @param[out] Signature Pointer to buffer to receive RSA PKCS1-v1_5 signature.
286 @param[in, out] SigSize On input, the size of Signature buffer in bytes.
287 On output, the size of data returned in Signature buffer in bytes.
288
289 @retval TRUE Signature successfully generated in PKCS1-v1_5.
290 @retval FALSE Signature generation failed.
291 @retval FALSE SigSize is too small.
292
293 **/
294 BOOLEAN
295 EFIAPI
296 RsaPkcs1Sign (
297 IN VOID *RsaContext,
298 IN CONST UINT8 *MessageHash,
299 IN UINTN HashSize,
300 OUT UINT8 *Signature,
301 IN OUT UINTN *SigSize
302 )
303 {
304 RSA *Rsa;
305 UINTN Size;
306 INT32 DigestType;
307
308 //
309 // Check input parameters.
310 //
311 if (RsaContext == NULL || MessageHash == NULL) {
312 return FALSE;
313 }
314
315 Rsa = (RSA *) RsaContext;
316 Size = RSA_size (Rsa);
317
318 if (*SigSize < Size) {
319 *SigSize = Size;
320 return FALSE;
321 }
322
323 if (Signature == NULL) {
324 return FALSE;
325 }
326
327 //
328 // Determine the message digest algorithm according to digest size.
329 // Only MD5, SHA-1 or SHA-256 algorithm is supported.
330 //
331 switch (HashSize) {
332 case MD5_DIGEST_SIZE:
333 DigestType = NID_md5;
334 break;
335
336 case SHA1_DIGEST_SIZE:
337 DigestType = NID_sha1;
338 break;
339
340 case SHA256_DIGEST_SIZE:
341 DigestType = NID_sha256;
342 break;
343
344 default:
345 return FALSE;
346 }
347
348 return (BOOLEAN) RSA_sign (
349 DigestType,
350 MessageHash,
351 (UINT32) HashSize,
352 Signature,
353 (UINT32 *) SigSize,
354 (RSA *) RsaContext
355 );
356 }