]> git.proxmox.com Git - mirror_edk2.git/blame - CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaExt.c
Fix GCC build failure caused by R14307.
[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
10Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>\r
11This program and the accompanying materials\r
12are licensed and made available under the terms and conditions of the BSD License\r
13which accompanies this distribution. The full text of the license may be found at\r
14http://opensource.org/licenses/bsd-license.php\r
15\r
16THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
17WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
18\r
19**/\r
20\r
21#include "InternalCryptLib.h"\r
22\r
23#include <openssl/rsa.h>\r
24#include <openssl/err.h>\r
25\r
26//\r
27// ASN.1 value for Hash Algorithm ID with the Distringuished Encoding Rules (DER)\r
28// Refer to Section 9.2 of PKCS#1 v2.1\r
29// \r
30CONST UINT8 Asn1IdMd5[] = {\r
31 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86,\r
32 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10\r
33 };\r
34\r
35CONST UINT8 Asn1IdSha1[] = {\r
36 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e,\r
37 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14\r
38 };\r
39\r
40CONST UINT8 Asn1IdSha256[] = {\r
41 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,\r
42 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05,\r
43 0x00, 0x04, 0x20\r
44 };\r
45\r
46/**\r
47 Gets the tag-designated RSA key component from the established RSA context.\r
48\r
49 This function retrieves the tag-designated RSA key component from the\r
50 established RSA context as a non-negative integer (octet string format\r
51 represented in RSA PKCS#1).\r
52 If specified key component has not been set or has been cleared, then returned\r
53 BnSize is set to 0.\r
54 If the BigNumber buffer is too small to hold the contents of the key, FALSE\r
55 is returned and BnSize is set to the required buffer size to obtain the key.\r
56\r
57 If RsaContext is NULL, then return FALSE.\r
58 If BnSize is NULL, then return FALSE.\r
59 If BnSize is large enough but BigNumber is NULL, then return FALSE.\r
60\r
61 @param[in, out] RsaContext Pointer to RSA context being set.\r
62 @param[in] KeyTag Tag of RSA key component being set.\r
63 @param[out] BigNumber Pointer to octet integer buffer.\r
64 @param[in, out] BnSize On input, the size of big number buffer in bytes.\r
65 On output, the size of data returned in big number buffer in bytes.\r
66\r
67 @retval TRUE RSA key component was retrieved successfully.\r
68 @retval FALSE Invalid RSA key component tag.\r
69 @retval FALSE BnSize is too small.\r
70\r
71**/\r
72BOOLEAN\r
73EFIAPI\r
74RsaGetKey (\r
75 IN OUT VOID *RsaContext,\r
76 IN RSA_KEY_TAG KeyTag,\r
77 OUT UINT8 *BigNumber,\r
78 IN OUT UINTN *BnSize\r
79 )\r
80{\r
81 RSA *RsaKey;\r
82 BIGNUM *BnKey;\r
83 UINTN Size;\r
84\r
85 //\r
86 // Check input parameters.\r
87 //\r
88 if (RsaContext == NULL || BnSize == NULL) {\r
89 return FALSE;\r
90 }\r
91\r
92 RsaKey = (RSA *) RsaContext;\r
93 Size = *BnSize;\r
94 *BnSize = 0;\r
95\r
96 switch (KeyTag) {\r
97\r
98 //\r
99 // RSA Public Modulus (N)\r
100 //\r
101 case RsaKeyN:\r
102 if (RsaKey->n == NULL) {\r
103 return TRUE;\r
104 }\r
105 BnKey = RsaKey->n;\r
106 break;\r
107\r
108 //\r
109 // RSA Public Exponent (e)\r
110 //\r
111 case RsaKeyE:\r
112 if (RsaKey->e == NULL) {\r
113 return TRUE;\r
114 }\r
115 BnKey = RsaKey->e;\r
116 break;\r
117\r
118 //\r
119 // RSA Private Exponent (d)\r
120 //\r
121 case RsaKeyD:\r
122 if (RsaKey->d == NULL) {\r
123 return TRUE;\r
124 }\r
125 BnKey = RsaKey->d;\r
126 break;\r
127\r
128 //\r
129 // RSA Secret Prime Factor of Modulus (p)\r
130 //\r
131 case RsaKeyP:\r
132 if (RsaKey->p == NULL) {\r
133 return TRUE;\r
134 }\r
135 BnKey = RsaKey->p;\r
136 break;\r
137\r
138 //\r
139 // RSA Secret Prime Factor of Modules (q)\r
140 //\r
141 case RsaKeyQ:\r
142 if (RsaKey->q == NULL) {\r
143 return TRUE;\r
144 }\r
145 BnKey = RsaKey->q;\r
146 break;\r
147\r
148 //\r
149 // p's CRT Exponent (== d mod (p - 1))\r
150 //\r
151 case RsaKeyDp:\r
152 if (RsaKey->dmp1 == NULL) {\r
153 return TRUE;\r
154 }\r
155 BnKey = RsaKey->dmp1;\r
156 break;\r
157\r
158 //\r
159 // q's CRT Exponent (== d mod (q - 1))\r
160 //\r
161 case RsaKeyDq:\r
162 if (RsaKey->dmq1 == NULL) {\r
163 return TRUE;\r
164 }\r
165 BnKey = RsaKey->dmq1;\r
166 break;\r
167\r
168 //\r
169 // The CRT Coefficient (== 1/q mod p)\r
170 //\r
171 case RsaKeyQInv:\r
172 if (RsaKey->iqmp == NULL) {\r
173 return TRUE;\r
174 }\r
175 BnKey = RsaKey->iqmp;\r
176 break;\r
177\r
178 default:\r
179 return FALSE;\r
180 }\r
181\r
182 *BnSize = Size;\r
183 Size = BN_num_bytes (BnKey);\r
184\r
185 if (*BnSize < Size) {\r
186 *BnSize = Size;\r
187 return FALSE;\r
188 }\r
189\r
190 if (BigNumber == NULL) {\r
191 return FALSE;\r
192 }\r
193 *BnSize = BN_bn2bin (BnKey, BigNumber) ;\r
194 \r
195 return TRUE;\r
196}\r
197\r
198/**\r
199 Generates RSA key components.\r
200\r
201 This function generates RSA key components. It takes RSA public exponent E and\r
202 length in bits of RSA modulus N as input, and generates all key components.\r
203 If PublicExponent is NULL, the default RSA public exponent (0x10001) will be used.\r
204\r
205 Before this function can be invoked, pseudorandom number generator must be correctly\r
206 initialized by RandomSeed().\r
207\r
208 If RsaContext is NULL, then return FALSE.\r
209\r
210 @param[in, out] RsaContext Pointer to RSA context being set.\r
211 @param[in] ModulusLength Length of RSA modulus N in bits.\r
212 @param[in] PublicExponent Pointer to RSA public exponent.\r
213 @param[in] PublicExponentSize Size of RSA public exponent buffer in bytes. \r
214\r
215 @retval TRUE RSA key component was generated successfully.\r
216 @retval FALSE Invalid RSA key component tag.\r
217\r
218**/\r
219BOOLEAN\r
220EFIAPI\r
221RsaGenerateKey (\r
222 IN OUT VOID *RsaContext,\r
223 IN UINTN ModulusLength,\r
224 IN CONST UINT8 *PublicExponent,\r
225 IN UINTN PublicExponentSize\r
226 )\r
227{\r
228 BIGNUM *KeyE;\r
229 BOOLEAN RetVal;\r
230\r
231 //\r
232 // Check input parameters.\r
233 //\r
dda39f3a 234 if (RsaContext == NULL || ModulusLength > INT_MAX || PublicExponentSize > INT_MAX) {\r
532616bb 235 return FALSE;\r
236 }\r
237 \r
238 KeyE = BN_new ();\r
dda39f3a 239 if (KeyE == NULL) {\r
240 return FALSE;\r
241 }\r
242\r
243 RetVal = FALSE;\r
244 \r
532616bb 245 if (PublicExponent == NULL) {\r
dda39f3a 246 if (BN_set_word (KeyE, 0x10001) == 0) {\r
247 goto _Exit;\r
248 }\r
532616bb 249 } else {\r
dda39f3a 250 if (BN_bin2bn (PublicExponent, (UINT32) PublicExponentSize, KeyE) == NULL) {\r
251 goto _Exit;\r
252 }\r
532616bb 253 }\r
254\r
532616bb 255 if (RSA_generate_key_ex ((RSA *) RsaContext, (UINT32) ModulusLength, KeyE, NULL) == 1) {\r
256 RetVal = TRUE;\r
257 }\r
258\r
dda39f3a 259_Exit:\r
532616bb 260 BN_free (KeyE);\r
261 return RetVal;\r
262}\r
263\r
264/**\r
265 Validates key components of RSA context.\r
266\r
267 This function validates key compoents of RSA context in following aspects:\r
268 - Whether p is a prime\r
269 - Whether q is a prime\r
270 - Whether n = p * q\r
271 - Whether d*e = 1 mod lcm(p-1,q-1)\r
272\r
273 If RsaContext is NULL, then return FALSE.\r
274\r
275 @param[in] RsaContext Pointer to RSA context to check.\r
276\r
277 @retval TRUE RSA key components are valid.\r
278 @retval FALSE RSA key components are not valid.\r
279\r
280**/\r
281BOOLEAN\r
282EFIAPI\r
283RsaCheckKey (\r
284 IN VOID *RsaContext\r
285 )\r
286{\r
287 UINTN Reason;\r
288\r
289 //\r
290 // Check input parameters.\r
291 //\r
292 if (RsaContext == NULL) {\r
293 return FALSE;\r
294 }\r
295 \r
296 if (RSA_check_key ((RSA *) RsaContext) != 1) {\r
297 Reason = ERR_GET_REASON (ERR_peek_last_error ());\r
298 if (Reason == RSA_R_P_NOT_PRIME ||\r
299 Reason == RSA_R_Q_NOT_PRIME ||\r
300 Reason == RSA_R_N_DOES_NOT_EQUAL_P_Q ||\r
301 Reason == RSA_R_D_E_NOT_CONGRUENT_TO_1) {\r
302 return FALSE;\r
303 }\r
304 }\r
305\r
306 return TRUE;\r
307}\r
308\r
309/**\r
310 Performs the PKCS1-v1_5 encoding methods defined in RSA PKCS #1.\r
311\r
dda39f3a 312 @param[in] Message Message buffer to be encoded.\r
313 @param[in] MessageSize Size of message buffer in bytes.\r
314 @param[out] DigestInfo Pointer to buffer of digest info for output.\r
315 @param[in,out] DigestInfoSize On input, the size of DigestInfo buffer in bytes.\r
316 On output, the size of data returned in DigestInfo\r
317 buffer in bytes.\r
532616bb 318\r
dda39f3a 319 @retval TRUE PKCS1-v1_5 encoding finished successfully.\r
320 @retval FALSE Any input parameter is invalid.\r
321 @retval FALSE DigestInfo buffer is not large enough.\r
532616bb 322\r
323**/ \r
dda39f3a 324BOOLEAN\r
532616bb 325DigestInfoEncoding (\r
dda39f3a 326 IN CONST UINT8 *Message,\r
327 IN UINTN MessageSize,\r
328 OUT UINT8 *DigestInfo,\r
329 IN OUT UINTN *DigestInfoSize\r
532616bb 330 )\r
331{\r
332 CONST UINT8 *HashDer;\r
333 UINTN DerSize;\r
334\r
335 //\r
336 // Check input parameters.\r
337 //\r
dda39f3a 338 if (Message == NULL || DigestInfo == NULL || DigestInfoSize == NULL) {\r
532616bb 339 return FALSE;\r
340 }\r
341\r
342 //\r
343 // The original message length is used to determine the hash algorithm since\r
344 // message is digest value hashed by the specified algorithm.\r
345 //\r
346 switch (MessageSize) {\r
347 case MD5_DIGEST_SIZE:\r
348 HashDer = Asn1IdMd5;\r
349 DerSize = sizeof (Asn1IdMd5);\r
350 break;\r
351 \r
352 case SHA1_DIGEST_SIZE:\r
353 HashDer = Asn1IdSha1;\r
354 DerSize = sizeof (Asn1IdSha1);\r
355 break;\r
356 \r
357 case SHA256_DIGEST_SIZE:\r
358 HashDer = Asn1IdSha256;\r
359 DerSize = sizeof (Asn1IdSha256);\r
360 break;\r
361 \r
362 default:\r
363 return FALSE;\r
364 }\r
365\r
dda39f3a 366 if (*DigestInfoSize < DerSize + MessageSize) {\r
367 *DigestInfoSize = DerSize + MessageSize;\r
368 return FALSE;\r
369 }\r
370\r
532616bb 371 CopyMem (DigestInfo, HashDer, DerSize);\r
372 CopyMem (DigestInfo + DerSize, Message, MessageSize);\r
373\r
dda39f3a 374 *DigestInfoSize = DerSize + MessageSize;\r
375 return TRUE;\r
532616bb 376}\r
377\r
378/**\r
379 Carries out the RSA-SSA signature generation with EMSA-PKCS1-v1_5 encoding scheme.\r
380\r
381 This function carries out the RSA-SSA signature generation with EMSA-PKCS1-v1_5 encoding scheme defined in\r
382 RSA PKCS#1.\r
383 If the Signature buffer is too small to hold the contents of signature, FALSE\r
384 is returned and SigSize is set to the required buffer size to obtain the signature.\r
385\r
386 If RsaContext is NULL, then return FALSE.\r
387 If MessageHash is NULL, then return FALSE.\r
388 If HashSize is not equal to the size of MD5, SHA-1 or SHA-256 digest, then return FALSE.\r
389 If SigSize is large enough but Signature is NULL, then return FALSE.\r
390\r
391 @param[in] RsaContext Pointer to RSA context for signature generation.\r
392 @param[in] MessageHash Pointer to octet message hash to be signed.\r
393 @param[in] HashSize Size of the message hash in bytes.\r
394 @param[out] Signature Pointer to buffer to receive RSA PKCS1-v1_5 signature.\r
395 @param[in, out] SigSize On input, the size of Signature buffer in bytes.\r
396 On output, the size of data returned in Signature buffer in bytes.\r
397\r
398 @retval TRUE Signature successfully generated in PKCS1-v1_5.\r
399 @retval FALSE Signature generation failed.\r
400 @retval FALSE SigSize is too small.\r
401\r
402**/\r
403BOOLEAN\r
404EFIAPI\r
405RsaPkcs1Sign (\r
406 IN VOID *RsaContext,\r
407 IN CONST UINT8 *MessageHash,\r
408 IN UINTN HashSize,\r
409 OUT UINT8 *Signature,\r
410 IN OUT UINTN *SigSize\r
411 )\r
412{\r
413 RSA *Rsa;\r
414 UINTN Size;\r
415 INTN ReturnVal;\r
416\r
417 //\r
418 // Check input parameters.\r
419 //\r
420 if (RsaContext == NULL || MessageHash == NULL ||\r
421 (HashSize != MD5_DIGEST_SIZE && HashSize != SHA1_DIGEST_SIZE && HashSize != SHA256_DIGEST_SIZE)) {\r
422 return FALSE;\r
423 }\r
424\r
425 Rsa = (RSA *) RsaContext;\r
426 Size = BN_num_bytes (Rsa->n);\r
427\r
428 if (*SigSize < Size) {\r
429 *SigSize = Size;\r
430 return FALSE;\r
431 }\r
432\r
433 if (Signature == NULL) {\r
434 return FALSE;\r
435 }\r
436\r
dda39f3a 437 if (!DigestInfoEncoding (MessageHash, HashSize, Signature, SigSize)) {\r
438 return FALSE;\r
439 }\r
532616bb 440\r
441 ReturnVal = RSA_private_encrypt (\r
dda39f3a 442 (UINT32) *SigSize,\r
532616bb 443 Signature,\r
444 Signature,\r
445 Rsa,\r
446 RSA_PKCS1_PADDING\r
447 );\r
448\r
dda39f3a 449 if (ReturnVal < (INTN) *SigSize) {\r
532616bb 450 return FALSE;\r
451 }\r
452\r
dda39f3a 453 *SigSize = (UINTN) ReturnVal;\r
532616bb 454 return TRUE;\r
455}\r
456\r