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