]> git.proxmox.com Git - mirror_edk2.git/blame - CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaExt.c
CryptoPkg: Replace BSD License with BSD+Patent License
[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
630f67dd 10Copyright (c) 2009 - 2018, 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
57 RSA *RsaKey;\r
58 BIGNUM *BnKey;\r
59 UINTN Size;\r
60\r
61 //\r
62 // Check input parameters.\r
63 //\r
64 if (RsaContext == NULL || BnSize == NULL) {\r
65 return FALSE;\r
66 }\r
67\r
68 RsaKey = (RSA *) RsaContext;\r
69 Size = *BnSize;\r
70 *BnSize = 0;\r
f56b11d2 71 BnKey = NULL;\r
532616bb 72\r
73 switch (KeyTag) {\r
74\r
75 //\r
76 // RSA Public Modulus (N)\r
77 //\r
78 case RsaKeyN:\r
f56b11d2 79 RSA_get0_key (RsaKey, (const BIGNUM **)&BnKey, NULL, NULL);\r
532616bb 80 break;\r
81\r
82 //\r
83 // RSA Public Exponent (e)\r
84 //\r
85 case RsaKeyE:\r
f56b11d2 86 RSA_get0_key (RsaKey, NULL, (const BIGNUM **)&BnKey, NULL);\r
532616bb 87 break;\r
88\r
89 //\r
90 // RSA Private Exponent (d)\r
91 //\r
92 case RsaKeyD:\r
f56b11d2 93 RSA_get0_key (RsaKey, NULL, NULL, (const BIGNUM **)&BnKey);\r
532616bb 94 break;\r
95\r
96 //\r
97 // RSA Secret Prime Factor of Modulus (p)\r
98 //\r
99 case RsaKeyP:\r
f56b11d2 100 RSA_get0_factors (RsaKey, (const BIGNUM **)&BnKey, NULL);\r
532616bb 101 break;\r
102\r
103 //\r
104 // RSA Secret Prime Factor of Modules (q)\r
105 //\r
106 case RsaKeyQ:\r
f56b11d2 107 RSA_get0_factors (RsaKey, NULL, (const BIGNUM **)&BnKey);\r
532616bb 108 break;\r
109\r
110 //\r
111 // p's CRT Exponent (== d mod (p - 1))\r
112 //\r
113 case RsaKeyDp:\r
f56b11d2 114 RSA_get0_crt_params (RsaKey, (const BIGNUM **)&BnKey, NULL, NULL);\r
532616bb 115 break;\r
116\r
117 //\r
118 // q's CRT Exponent (== d mod (q - 1))\r
119 //\r
120 case RsaKeyDq:\r
f56b11d2 121 RSA_get0_crt_params (RsaKey, NULL, (const BIGNUM **)&BnKey, NULL);\r
532616bb 122 break;\r
123\r
124 //\r
125 // The CRT Coefficient (== 1/q mod p)\r
126 //\r
127 case RsaKeyQInv:\r
f56b11d2 128 RSA_get0_crt_params (RsaKey, NULL, NULL, (const BIGNUM **)&BnKey);\r
532616bb 129 break;\r
130\r
131 default:\r
132 return FALSE;\r
133 }\r
134\r
f56b11d2
QL
135 if (BnKey == NULL) {\r
136 return FALSE;\r
137 }\r
138\r
532616bb 139 *BnSize = Size;\r
140 Size = BN_num_bytes (BnKey);\r
141\r
142 if (*BnSize < Size) {\r
143 *BnSize = Size;\r
144 return FALSE;\r
145 }\r
146\r
147 if (BigNumber == NULL) {\r
f56b11d2
QL
148 *BnSize = Size;\r
149 return TRUE;\r
532616bb 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
dda39f3a 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
dda39f3a 208 if (BN_bin2bn (PublicExponent, (UINT32) PublicExponentSize, KeyE) == NULL) {\r
209 goto _Exit;\r
210 }\r
532616bb 211 }\r
212\r
532616bb 213 if (RSA_generate_key_ex ((RSA *) RsaContext, (UINT32) ModulusLength, KeyE, NULL) == 1) {\r
214 RetVal = TRUE;\r
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
532616bb 256 if (RSA_check_key ((RSA *) RsaContext) != 1) {\r
257 Reason = ERR_GET_REASON (ERR_peek_last_error ());\r
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 return FALSE;\r
263 }\r
264 }\r
265\r
266 return TRUE;\r
267}\r
268\r
532616bb 269/**\r
270 Carries out the RSA-SSA signature generation with EMSA-PKCS1-v1_5 encoding scheme.\r
271\r
272 This function carries out the RSA-SSA signature generation with EMSA-PKCS1-v1_5 encoding scheme defined in\r
273 RSA PKCS#1.\r
274 If the Signature buffer is too small to hold the contents of signature, FALSE\r
275 is returned and SigSize is set to the required buffer size to obtain the signature.\r
276\r
277 If RsaContext is NULL, then return FALSE.\r
278 If MessageHash is NULL, then return FALSE.\r
279 If HashSize is not equal to the size of MD5, SHA-1 or SHA-256 digest, then return FALSE.\r
280 If SigSize is large enough but Signature is NULL, then return FALSE.\r
281\r
282 @param[in] RsaContext Pointer to RSA context for signature generation.\r
283 @param[in] MessageHash Pointer to octet message hash to be signed.\r
284 @param[in] HashSize Size of the message hash in bytes.\r
285 @param[out] Signature Pointer to buffer to receive RSA PKCS1-v1_5 signature.\r
286 @param[in, out] SigSize On input, the size of Signature buffer in bytes.\r
287 On output, the size of data returned in Signature buffer in bytes.\r
288\r
289 @retval TRUE Signature successfully generated in PKCS1-v1_5.\r
290 @retval FALSE Signature generation failed.\r
291 @retval FALSE SigSize is too small.\r
292\r
293**/\r
294BOOLEAN\r
295EFIAPI\r
296RsaPkcs1Sign (\r
297 IN VOID *RsaContext,\r
298 IN CONST UINT8 *MessageHash,\r
299 IN UINTN HashSize,\r
300 OUT UINT8 *Signature,\r
301 IN OUT UINTN *SigSize\r
302 )\r
303{\r
304 RSA *Rsa;\r
305 UINTN Size;\r
86b5c3ee 306 INT32 DigestType;\r
532616bb 307\r
308 //\r
309 // Check input parameters.\r
310 //\r
86b5c3ee 311 if (RsaContext == NULL || MessageHash == NULL) {\r
532616bb 312 return FALSE;\r
313 }\r
314\r
315 Rsa = (RSA *) RsaContext;\r
f56b11d2 316 Size = RSA_size (Rsa);\r
532616bb 317\r
318 if (*SigSize < Size) {\r
319 *SigSize = Size;\r
320 return FALSE;\r
321 }\r
f56b11d2 322\r
532616bb 323 if (Signature == NULL) {\r
324 return FALSE;\r
325 }\r
f56b11d2 326\r
86b5c3ee 327 //\r
328 // Determine the message digest algorithm according to digest size.\r
630f67dd 329 // Only MD5, SHA-1 or SHA-256 algorithm is supported.\r
86b5c3ee 330 //\r
331 switch (HashSize) {\r
332 case MD5_DIGEST_SIZE:\r
333 DigestType = NID_md5;\r
334 break;\r
f56b11d2 335\r
86b5c3ee 336 case SHA1_DIGEST_SIZE:\r
337 DigestType = NID_sha1;\r
338 break;\r
f56b11d2 339\r
86b5c3ee 340 case SHA256_DIGEST_SIZE:\r
341 DigestType = NID_sha256;\r
342 break;\r
532616bb 343\r
86b5c3ee 344 default:\r
532616bb 345 return FALSE;\r
f56b11d2 346 }\r
86b5c3ee 347\r
348 return (BOOLEAN) RSA_sign (\r
349 DigestType,\r
350 MessageHash,\r
351 (UINT32) HashSize,\r
352 Signature,\r
353 (UINT32 *) SigSize,\r
354 (RSA *) RsaContext\r
355 );\r
532616bb 356}\r